C84の3日目に「ななかINSIDE PRESS vol.3」を出します(東ぺ-15a)
いよいよ今日から夏コミですね!なんだか気温がとても高くなりそうとのことで、参加者の方々はくれぐれも温度調節、水分補給を怠らず楽しく参加してきてくださいね。家に帰るまでがコミケです。
さて、私がコミケに出展側で参加するのもこれで3回目。前回、前々回に続いてプログラミングメインのよもやま話がどばどば詰まった「ななかINSIDE PRESS vol.3」を頒布します。 執筆者8人で128ページときりの良い数字になっております(お値段は600円ときりがよくありませんね)。かなり分厚い(背表紙の幅が1cmくらい?)ので近くを通られましたら、お手にとって確かめていただければと思います。 第7開発セクションのサイトにはサンプルページも用意してしますので興味がある方はそちらもご覧くださいませ。
本の内容
- AWS実践入門 -AWSの本当のところ @con_mame
- 業務でAWSを使用しているid:con_mameによる、使用時の注意ポイントや性能測定です。 Let's インスタンスガチャ (※有料です)!
- よりよい設計手法でSAN値を守る More Better Rails @rosylilly
- coffeescriptで作るcoffeebotで優雅なコーヒーブレイク @saiten
- 「それ名前駆動開発」だろって言ってしまうタイトルですが、中身はコーヒーメーカーにコーヒーが残っているかどうかを監視してくれるボットを作った話です。個人的に一番好きな記事です。
- Render Scriptでサクサク動くAndroidアプリを @binzume
- RenderScriptというのはアプリからネイティブコードを実行する仕組みです。それNDKでいいじゃん?と思うかもしれませんが、CPU非依存で書けるのでARM以外も対象とするときには楽ができるかも。
- できる!たのしい!週末iPhoneアプリ開発 @kenmaz
- 知識に差が出る!? Coureutils大全#2 @tboffice
- lsやcatといった日常生活に欠かせないコマンドたちのご紹介。こんなコマンドあるんだへー、とお手持ちのへぇボタンを押しながらパラパラ読むのが多分正しいかと。前号からの続きですが、これだけ読んでも問題ないです。
- Asteriskで作る個人認証システム @mtgto
- 私です。最近増えてきている「二段階認証」を個人でもやるための方法を音声電話、SMSの2つで書きました。
- 88888の多い動画は!? ニコニコ動画のデータを分析してみよう @shibacow
- 今年の5月に公開された830万件の動画のデータとコメントをHadoopを使って分析する方法の解説です。例としてコメントに「88888」が多いものを調べています。
ということで
8月12日(月)、東ぺ-15aでお待ちしております。私は朝頃サークルブースにいると思いますのでよろしくお願いします。既刊も持っていくよー。
DashでJava SE 7 日本語ドキュメントに対応させてみた
今年の5月にJava SE 7のAPIドキュメントをはじめとした、Java SE 7のドキュメントの日本語版が公開されました(Java SE7API日本語版提供開始、Java SE ドキュメント)。
バージョン6までのように「Java 7 HashMap」のように検索して(Googleなら「日本語のページを検索」に制限すると最初に出てくるようになります)Webブラウザで見るのでももちろんいいのですが、MacユーザとしてはやはりDashで見たいわけです。 ちなみにDashというのはMac/iOSなどのAPIドキュメントをキーワードからインクリメンタルサーチで高速に見ることができるツールで、私は重宝しています。ダウンロードすることでScala, Ruby, Python, Node.jsなどにも対応することができます。ちなみに無料でも使えますが、フルバージョンを購入してないと検索時にたまに数秒待たされるとのことだったので、速攻でポチりました。
DashでJava 7 SE API日本語版を対応できるようにするのにはちょっと面倒くさかったのでやり方をメモっておきます。なおJava APIドキュメントのライセンスで、インターネットでの再配布は許可されていないため、Docsetの再配布をする予定はありません。予めご了承ください。
ドキュメントの取得
いくつかキーワードを変えて検索してみたのですが、どうやらJava SE 7の日本語ドキュメントはzip書庫などでまとめて取得することができないようで、仕方なくスクレイピングで取ってくることにしました。wgetで再帰ダウンロードでもいいのかもしれませんが、リンクされてないページがあると嫌だったので英語版ドキュメントをunzipしたもののファイル構造から日本語ドキュメントをダウンロードするという方法を取りました。
Javadocをdocsetに変換するツールの修正
JavadocをDash用のDocsetに変換するツールがGitHubで公開されていたので取ってきます。
https://github.com/Kapeli/javadocset
ですがこれをそのまま使うと変換中に大量の警告が出力され、Dashに取り込んでもクラスやインターフェイスがほとんど読み込めません。 これはこのツールが英語版ドキュメントの書式にのみ対応しているため、クラス名などを取得するためのキーワードが違う日本語ドキュメントは正しく処理ができないんですね。
ということで、日本語ドキュメントに対応できるようにしたForkをGitHubに用意しました。
https://github.com/mtgto/javadocset/tree/japanese
英語版にはない、表現の微妙な差にハマりました(「〜 内のクラス」と「〜 のクラス」とか)。 使用上の注意として、masterブランチは上記の修正を入れてないので、もし使おうとする人はjapaneseブランチからビルドして使ってください。
Docsetに変換
あとはDocsetに変換してDashに取り込むだけです。 javadocsetをXcodeでビルドして、
javadocset Java /path/to/api
と実行するとJava.docset
が生成されます(/path/to/api
は日本語ドキュメント内のapiフォルダへのパスを入れてください)。
これをDashにインストールすればJava 7のドキュメントが検索できるようになっているはずです。英語版Javaドキュメントがすでにインストールされていて、もう不要でしたら削除しておきましょう。
終わりに
以上でJava SE 7日本語ドキュメントをDashで引くための方法についての説明は終わりです。
参考リンクにも入れましたが、Rubyの日本語リファレンスマニュアルをDash用に対応してくれている人がいるので、よろしければそちらもチェックしてみてください。
参考
Chromeで「サードパーティのCookieとサイトデータをブロックする」をオンにしているとはてなブログにログイン出来ない
例外的にblog.hatena.ne.jpをサードパーティ許可したらログインできるようになったが、釈然としない。
scala irc botでのbotの作り方
はじめに
この記事は、私がGitHubで公開しているscala-irc-botというプログラムの使い方とボットの書き方のチュートリアルです。 ScalaでIRCボットを書きたいという需要が非常に少ない目的のために書きました。
目次
scala irc botの紹介
scala irc botってなんですか
https://github.com/scala-irc-bot
私がScalaでirc botを書けるように作成しているプログラムです。 実際にIRCに接続するのにはPircBotというJava製のIRCクライアントを使用しています。
現在の最新バージョンは0.2.0-SNAPSHOTです。バージョンは大きく設計が変わるときに更新されます。プラグインに影響のない修正ではバージョンを上げません(mavenリポジトリの更新が面倒だからです)。
現在の使い方は sbt run
によって起動させるのを推奨しています。
性質的に常時起動しておくプログラムなのでデーモンのように使うほうがいいのかなあ。。。
irc botってなんですか
IRCでの誰かの発言などのイベントなどに反応して発言したり作業したり愛したり恋したりしてくれるプログラムです。 ときには喧嘩して殴りあったりするけれど、でもそんなお前のこと、そんなに嫌いじゃないぜ?っていう人格を持っています。
ircってなんですか
つ RFC1459
デプロイ方法
次のものを用意してください。
- sbt
- git
git clone
本体のコードはgithubで管理しているので、cloneで持ってきます。
git clone https://github.com/scala-irc-bot/scala-irc-bot.git
設定ファイルの記述
cloneしたディレクトリに移動し、configディレクトリの中に、Config.scalaというファイルを作成します。
Config.scala
import net.mtgto.irc.Config import net.mtgto.irc.config.BotConfig new Config { val hostname = "irc.example.com" // IRCサーバの名前 val port = 6667 // IRCサーバのポート val password = None // 必要ならSome("password")のように記述する val encoding = "utf-8" // 使用するエンコーディング val messageDelay = 2000 // メッセージ間の遅延(ミリ秒) val timerDelay = 60000 // タイマーイベント間隔(ミリ秒) val nickname = "scala-irc-bot" // ボットのニックネーム val username = "scala-irc-bot" // ボットのログイン名 val realname = "mtgto@example.com" // ボットのリアルネーム // channels val channels = Array("#mtgto", "#test") // JOINさせたいチャンネル // bots val bots = Array[(String, Option[BotConfig])]( // ここにプラグインの設定を記述する ) }
起動する
コンソールからsbt
で起動します。
sbt run
(初回のみ)コンパイルが実行され、設定ファイルやネットワークなどに問題が起きなければ、しばらく経つとIRCサーバにscala irc botが接続してきます。
ですが今のままではボットプラグインを何も入れてないので、何もしてくれません。
コンソール画面にexit
と入力して終了させましょう。
プラグインの作成方法 (シンプル)
ここからはまずはシンプルなプラグインを作成していきます。 ここでいうシンプルなプラグインというのは、
- 設定ファイルでボットプラグインごとのオプションを設定できない
っていう前提のものです。下の方にオプションを使う方法も載せてあります。
Scala + sbtで作る
今回作る環境は、
- sbt (バージョンはユーザの環境に依る)
- Scala 2.10.0
- PircBot 1.8.0
です。
最小構成では build.sbt
Echobot.scala
の2ファイルで構成されます。
echobot/build.sbt
// -*- scala -*- name := "EchoBot" organization := "net.mtgto" version := "0.1.0-SNAPSHOT" scalaVersion := "2.10.0" resolvers += "mtgto repos" at "http://scala-irc-bot.github.com/scala-irc-bot/maven/" libraryDependencies := Seq( "net.mtgto" %% "scala-irc-bot" % "0.2.0-SNAPSHOT" % "provided" ) scalacOptions ++= Seq("-deprecation", "-unchecked", "-encoding", "UTF8")
echobot/Echobot.scala
package net.mtgto import net.mtgto.irc.{Bot, Client} import net.mtgto.irc.event._ /** * 受け取ったメッセージをNOTICEで送り返すボット */ class Echobot extends Bot { /** * 誰かがPRIVMSGを書いた時に通知される */ override def onMessage(client: Client, message: Message) = { // メッセージが送信されたチャンネルに同じメッセージをNOTICEで送り返す client.sendNotice(message.channel, message.text) } }
ファイルを置いたら、
sbt package
と実行すると、 target/scala-2.10.0/echobot_2.10.0-0.1.0-SNAPSHOT.jar
が作成されます。
このjarファイルがコンパイルされたプラグインです。
プラグインをインストール
まず、作成した echobot_2.10.0-0.1.0-SNAPSHOT.jar
を scala-irc-bot/bots
フォルダの中に置いてください。
次に config/Config.scala
にボットプラグインの設定を記述します。
val bots = Array[(String, Option[BotConfig])]( // ここにプラグインの設定を記述する ("net.mtgto.Echobot", None) )
sbt run
すると画像のようにこちらの発言をNOTICEで繰り返してくれるようになります。
botテンプレートを使う (g8)
giter8用のテンプレートを作ってあるので、これを使うこともできます。
g8 scala-irc-bot/bot
version [0.1.0-SNAPSHOT]: organization [com.example]: net.mtgto name [IRC Bot Project]: EchoBot
こちらは先ほどの手順で作成した時に加えて、テスト用にSpecs2、ビルド用にsbt-assemblyの設定をしてあります。 慣れてきた場合や他ライブラリに依存するプラグインを作るときにはこちらをおすすめします。
プラグインの作成方法 (設定可能)
設定ファイルでボットプラグインごとのオプションを設定することができます。
設定ファイルに書いたオプションを読み込むには、net.mtgto.irc.config.BotConfig
を実装したクラスを作り、そのオブジェクトをプラグインのメインクラスのコンストラクタにもたせてあげればよいです。
実例を示してみます。今回は設定ファイルに書いたキーワードが書かれた時だけ反応するようにしてみましょう。 KeywordEchobotを作成します。
KeywordEchobot.scala
package net.mtgto import net.mtgto.irc.{Bot, Client} import net.mtgto.irc.event._ import net.mtgto.irc.config.BotConfig /** * BotConfigを実装したクラスを定義する必要がある。 */ case class KeywordEchobotConfig( val keywords: Seq[String] ) extends BotConfig /** * 特定のメッセージをNOTICEで送り返すボット * * コンストラクタでEchobotConfigを受け取る */ class KeywordEchobot(val config: KeywordEchobotConfig) extends Bot { /** * 誰かがPRIVMSGを書いた時に通知される */ override def onMessage(client: Client, message: Message) = { if (config.keywords.contains(message.text)) { // メッセージが送信されたチャンネルに同じメッセージをNOTICEで送り返す client.sendNotice(message.channel, message.text) } } }
これを先ほどと同じように sbt package
でビルドして、target/scala-2.9.2/keywordechobot_2.10.0-0.1.0-SNAPSHOT.jar
を scala-irc-bot/bots
にコピーします。
あとは config/Config.scala
に設定を書いてあげます。
val bots = Array[(String, Option[BotConfig])]( ("net.mtgto.Echobot", Some(net.mtgto.KeywordEchobotConfig(Seq("こんばんは", "おはようございます")))) )
Seqに好きな言葉を列挙してあげます。
あとは sbt run
すると、設定ファイルにある言葉が書かれた時にだけ応答してくれるようになります。
まとめ
簡単でしたが、scala irc botの導入方法とプラグインの作成方法を書きました。 多分ここまで読んでいる方はいらっしゃらないと思うのですが、さらにプラグインを作ってみたいという奇特な方がいらっしゃるようでしたらこの上なく幸せです。 まだサンプルプログラムが少ないのですが、私も幾つかプラグインを作っているのでよろしければそれを見てみてください。
CocoaPodsでGHUnit + OCMockなiOS開発環境を構築する
なにこれ
新しいプロジェクト作るたびにいつも構築手順を忘れてるのでメモ。 おまけでコンソールからのテスト実行(Jenkinsとの統合が目的)のやり方も書いた。
対象者
- Objective-CによるiOS開発者
- CocoaPodsを知っている・使いたい
- GHUnitを知っている・使いたい
- (JenkinsでCIしたい)←必須じゃない
検証環境
2012年12月9日時点で最新のもの。
手順
1. Xcodeでプロジェクト作成
Unit TestはGHUnitを使うので不要。
このドキュメントでは MyProject
とする。
2. 新しいターゲット作成
プロジェクト設定を開いて、テスト実行用のターゲットを作成する。
ターゲットの種類はiOSのEmpty Application、名前は Tests
にしておく。
名前は変更してもいいけど、以下の説明で Tests
と出てきたら自分で読み替えること。
自動生成されるファイルのうち、次のものだけ残して全部消す(ファイルごと)
Tests-Info.plist
InfoPlist.strings
main.m
Tests-Prefix.pch
3. Podfile作成
MyProject.xcodeproj
と同じ所に Podfile
を作成する。
platform :ios, '5.0' pod 'AFNetworking', '~> 1.0.1' pod 'CocoaLumberjack', '~> 1.6' target :Tests, :exclusive => true do pod 'GHUnitIOS', '~> 0.5.5' pod 'OCMock', '~> 2.0.1' end
一行目でiOS 5.0以上を指定しているが、実際には作成するプロジェクトに合わせて指定する。
AFNetworkingとCocoaLumberjackは実際に作ったPodfileから取ってきただけのただのサンプル。実際に必要な物を指定して欲しい。
このとき target :Tests
を2.で作ったターゲット名にするのを忘れないこと。
終わったらコンソールからworkspaceを作成してもらう。
pod install
4. xcodeproj閉じてxcworkspace開く
両方同じxcodeprojを参照するのでわけわからないことになる前に xcodeproj
を閉じる。
5. ターゲット Tests
の Build Settings
いじる
Other Linker Flags
に -ObjC
-all_load
を追加する。
俺の環境では -ObjC
はすでに追加されていた。
6. main.m
いじる
// // main.m // Tests // // Created by <ユーザ名> on 12/8/12. // Copyright (c) 2012 <組織名>. All rights reserved. // #import <UIKit/UIKit.h> int main(int argc, char *argv[]) { @autoreleasepool { return UIApplicationMain(argc, argv, nil, @"GHUnitIOSAppDelegate"); } }
ここまでやってiPhone Simulatorで起動するとGHUnitのテスト実行画面が表示される。
7. ユニットテスト作ってみる
GHUnit
ここまでうまくいってるか確認するために一個テスト作ってみる。
Tests
に一個Objective-Cのクラスを作る。
GHUnitのガイド にあるコードのままだとコンパイルが通らないのでちょいと手直し。
MyTest.h
#import <GHUnitIOS/GHUnit.h> @interface MyTest : GHTestCase @end
MyTest.m
#import "MyTest.h" @implementation MyTest - (void)testStrings { NSString *string1 = @"a string"; GHTestLog(@"I can log to the GHUnit test console: %@", string1); // Assert string1 is not NULL, with no custom error description GHAssertNotNil(string1, nil); // Assert equal objects, add custom error description NSString *string2 = @"a string"; GHAssertEqualObjects(string1, string2, @"A custom error message. string1 should be equal to: %@.", string2); } @end
修正前はGHAssertNotNULLを使ってたのでGHAssertNotNilに変えた。
もっかいiPhone Simulator起動してみてテストできることを確認する。
OCMockも確認する
MyMockTest.h
#import <GHUnitIOS/GHUnit.h> #import <OCMock/OCMock.h> @interface MyTest : GHTestCase @end
MyMockTest.m
#import "MyMockTest.h" @implementation MyMockTest - (void)testMock { id mock = [OCMockObject mockForClass:[NSString class]]; [[[mock stub] andReturnValue:OCMOCK_VALUE((NSUInteger){100})] length]; GHAssertEquals(100U, [mock length], @"ocmock works"); } @end
iPhone Simulator起動してみてテストできることを確認する。
8. コンソールからテスト実行してみる
Jenkins用なんで興味ない人はスルー。 基本は GHUnitのガイド 通り。
i. シェルスクリプトを取ってくる
xcodeproj, xcworkspaceがあるところで以下を実行。
wget https://raw.github.com/gabriel/gh-unit/master/Scripts/RunTests.sh wget https://raw.github.com/gabriel/gh-unit/master/Scripts/RunIPhoneSecurityd.sh
ii. テスト実行時にスクリプトを実行するようにする
プロジェクト設定内のTests
のBuild Phases
を開き、Add Build Phase
-> Add Run Script
を選択。
入力欄にsh RunTests.sh
と入れる。
iii. Makefile
GHUnitのドキュメントにはworkspaceのときの例がないのでそのままだと動かない。 適当に作ってみる。
clean: -rm -rf build/* test: GHUNIT_CLI=1 xcodebuild ONLY_ACTIVE_ARCH=NO -workspace <xcworkspaceファイルへのパス> -scheme Tests -configuration Debug -sdk iphonesimulator build
ワークスペースへのパスに書き換えるのを忘れないこと。 連続空白に見えるところはタブ文字にすること。
iv. (Base SDKが6.0のときのみ) main.mの修正
2012年12月9日現在、iOS SDKが6.0だと、コンソールから動かせない問題がある(GHUnitのIssue at GitHub)。 暫定措置だが一番下のgfxさんのコメント通りにmain.mを書き換えるとコンソールから動かせるようになる。
v. テストを実行する
make test
echo $?
して0だったら、おめでとう。すべてのテストをパスしたぞ!
9. Jenkinsからテスト実行
まず前章で作ったRunTests.sh
, RunIPhoneSecurityd.sh
, Makefile
をgit commitしておく。
公開前提のプロジェクトだと、git cloneしたユーザにpod install
を実行させるのでxcworkspaceをソースコードリポジトリ管理しないと思う。
なのでその流儀に則り、Jenkinsでもpod install
することにする。
i. ジョブを作る
名前はMyProject
にしてみた。フリースタイル・プロジェクトを選択。
ii. 設定
ソースコード管理システムでソースの位置を指定する。
俺はローカルホストにJenkinsを立ててるので、GitのRepository URLがfile:///
からはじまる。
ビルドに シェルの実行
を追加する。
WORKSPACE_FILE=MyProject.xcworkspace if [ ! -d "$WORKSPACE_FILE" ]; then pod install open -R "$WORKSPACE_FILE" echo "We need to init the workspace file. Please try re-run test after you open workspace file." exit 1 fi make clean && WRITE_JUNIT_XML=YES JUNIT_XML_DIR=tmp/test-results make test
最初のビルドではxcworkspaceの初期化が終わっていないため、
xcodebuild: error: The workspace 'MyProject' does not contain a scheme named 'Tests'.
と失敗してしまう。
少し悩んだが、ユーザにXcodeでxcworkspaceを開かせることにした。 一度Xcodeで開いてしまえばもうこの作業はやらなくてOKだ。
※open -R <ファイルパス>
はFinderでファイルを表示するコマンド。
ビルド後の処理
から JUnitテスト結果の集計
を選び、tmp/test-results/*.xml
と指定する。
ビルドしてみると一回目は失敗すると思う。 xcworkspaceがFinderで表示されていると思うので、ダブルクリックして初期化してから再度ビルドすればテストが実行されるはずだ。
このへんはバッドノウハウなんで、もっといい方法あるって人は教えて欲しい。
サンプル
https://github.com/mtgto/CocoaPodsSample
ここまでの説明があってるかの確認のために作ってみた。
参考
全部英語のページ。