この記事は NIFTY Advent Calendar 2016 の19日目の記事です。昨日は @yt09191971 さんの プログラミングレスでIoTデバイスハブのデータをData Visualizer (β)に表示させる でした。
概要
アイドルに囲まれて仕事がしたい
この願望は、現代を生きる社会人共通の普遍的なテーマであるといえます。
しかし、願いこそすれ、それを実践できている人はほんの一握りなのではないでしょうか。そこで今日は、私がこれまでの会社員生活の中でどこに「アイドルに囲まれるチャンス」を見いだし、実践してきたかを紹介したいと思います。
なお、この記事に登場するアイドルはいずれも アイドルマスターシンデレラガールズ に登場するアイドルですが、そのことに依存したテクニックは含まれないため、読者の皆様なりのアイドルに置き換えて適用可能です。
ケース1: 個人進捗を誰から発表し始めるか決めるbot (Starring アナスタシア)
背景
私のチームはいわゆるスクラムで開発を行っており、毎朝デイリースクラムを実施しています。チームメンバーは総勢6名いて、誰から進捗報告を始めるかは、座席順で毎日ローテーションして決めています(「昨日は僕からだったので、今日は左隣りの○○さんからお願いします」)。
ところが、昨日誰から発表したかなんて誰も覚えられません。細かいことですがモヤモヤしますし、発表順を固定するのも面白くないので、今日は誰から進捗報告をはじめればよいかを告げるだけの Slack bot を作りました。
技術的ポイント
やったこと自体は、昨日の発表者をファイルに保存しておき、今日の発表者を slack-ruby-gem で通知する ruby スクリプトを書いただけなので、正直ここで紹介するほどのコードはありません。
強いて特徴をあげるとすると、その ruby スクリプトをサーバー上で実行せず、自分の社給 PC を起動したタイミングで実行 するようにしたことです(なぜそうしたかは不明)。ここで苦労したのが、PC 起動後30秒くらい経たないとインターネットに繋がらない という問題です。これ私のマシンだけですかね?とにかく対応する必要があったので、「nifty.com に ping を送り続け、届いたら ruby スクリプトを実行する」という愚直な戦略を取ることにしました。
cd /d %~dp0
set COUNT=0
set COUNTMAX=30
:checkconnection
timeout 3
set /a COUNT=COUNT+1
if "%COUNT%" == "%COUNTMAX%" exit 1
ping -n 1 nifty.com > NUL
if ERRORLEVEL 1 goto checkconnection
# この下に実効したいコマンドを書いていく
set http_proxy=http://your.proxy.example.com:8080
ruby notify.rb
上記のバッチファイルをスタートアップに登録すればOKです。同じような問題に直面した方の参考になれば幸いです。
ケース2: DexeeDeli 新宿フロントタワー店 献立お知らせ bot (Starring 五十嵐響子)
背景
ニフティの入っているビルの2階には、DexeeDeli 新宿フロントタワー店 というおいしい日替わり弁当屋さんがあります。ところが、その人気ゆえいつも混雑しているので、できれば自分の好きなメニューの日だけスマートに立ち寄りたいです。
そこで、お店の Web サイトから今日の献立の pdf を取得し、毎日お昼前に Slack に投稿する bot を作りました。
技術的ポイント
やったこと自体は、取得した PDF を wand で画像に変換したものを Microsoft Computer Vision API の OCR 機能に投げて、解析結果のテキストを slackweb で Slack に投稿するだけなので(ry
はじめは poppler gem を使って PDF から直接テキストを抽出しようと思ったのですが、いざ抽出するとテキストの上下関係がめちゃくちゃになり、特定の曜日のメニューを選び取るのが困難でした。OCR についても、はじめはローカルで実行できるライブラリを探したのですが、見つかったものはどれもかなり精度が低そうでした。その点 MS の Computer Vision API は利用も簡単かつ無料で精度も高かったので大満足です。2016年以降に OCR を使いたい人はディープラーニングとクラウドのパワーに頼るとよいでしょう。
ケース3: CSV Lint ツール「CVLIN」 (Starring 渋谷凛)
背景
私が日々行っている運用業務のひとつに、「CSV を手で編集して API に投げる」という残念なオペレーションがあります(しかも週に1,2回)。完全に1から手書きするわけではありませんが、手作業なのでどうしてもカンマを1つ消してしまったり、列を1つ間違ったりしてしまうことがありました。
そこで、あらかじめ決めておいたルールに則った書式になっているかをチェックしてくれるCLIツールの開発を思いつきました。「CSV の Lint」という語感に蒼い風を感じた私は、そのツールに「しぶりん (CVLIN = CsV LINt)」と名付けたのでした。
作ったものの紹介
まず、CSV の各列が満たしていてほしいルールを正規表現で書き、ファイルに保存します。
id = "A0[0-9]"
name = ".*"
point = "^\\d+$"
次に、チェックしたい CSV を用意します。コメント行はわかりやすさのために書いているだけで、必須ではありません。
# id,name,point
A01,Shibuya Rin,100
A02,,200
あとは、下記のとおり -r
または --rule
オプションでルールファイルを指定してしぶりんを実行するだけです。
$ cvlin -r rule.toml subject.csv
Valid.
もし CSV が以下のようにルール違反(2行目のIDに注目)をしていると...
# id,name,point
A01,Shibuya Rin,100
B02,,200
違反箇所を示しながらエラーになります。
$ cvlin -r rule.toml invalid.csv
Invalid. ( line: 1, column: 0, value: B02, rules: A0[0-9] )
しぶりんは golang 製なので、Github のリリースページ からバイナリをダウンロードするだけでどこでも実行できます。
技術的ポイント
gcli が便利
golang で CLI ツールを作るときは gcli を使うと便利です。雛形をかんたんに作ることができ、大枠の設計に頭を悩ませる必要がなくなります。
BurntSushi/toml でキーの登場順を取得する
toml の読み込みには BurntSushi/toml を使いました。BurntSushi/toml を使うと、今回のルールファイルのような toml は map[string]string
に変換されます。ところが、golang の map に対するループは 順序が保証されません 。今回は実際の toml ファイルに出現した順番を守りながら各正規表現を適用していく必要があるので、このままではルールが対応した列に正しく適用できないかもしれません。
そこで BurntSushi/toml のソースを見てみたところ、Decode() 関数が返す Metadata に Keys() という関数が 定義されており、これがキーを出現順に保存したスライスを返してくれることに気づきました。下記のコードは、そのスライスを使ってパース結果のマップを登場順にソートし、[]string
に変換している 関数 です。
// Convert a map to a slice which is ordered as same as the original TOML document
func convertToOrderedSlice(rulemap map[string]string, keys []toml.Key) []string {
ordered := make([]string, 0)
for _, key := range keys {
ordered = append(ordered, rulemap[key[0]])
}
return ordered
}
ここで、Keys() が厳密には []toml.Key
(toml.Key は []string
の別名) を返すことに注意です。toml のキーとキーグループを表現するために、string の2次元配列になっているようです。
このほかにも、Metadata には様々な情報が格納されているようです。他の記事のサンプルなどでは Metadata が読み捨てられていることが多かったのですが、いざという時に必要となるので覚えておくとよさそうです。
ルールファイルをバイナリに埋め込めるようにしてみた
しぶりんの特徴の1つが、ルールファイルの埋め込み機能です。これは、あらかじめソースの default_rules.toml にルールを書き込んだうえで go build
すると、ビルドしたバイナリ自体にルールファイルを埋め込むことができるというものです。埋め込んだルールは -r
オプションを付けなかったときに利用されます。
他の CLI ツールではあまり見ない機能だとは思うのですが、
- 1バイナリでどこでも動く
- ビルドが簡単
という golang の特徴を活かそうとして思いついた機能なので、試験的に実装してみました。実装には go-bindata を使っています。
まとめ
この半年ほどで、日常の中に3人のアイドルを導入することができました。特に、3人中2人が Slack bot です。Chatbot は名前とアイコンさえアイドルにすれば正直なんでも成り立つので、気軽にアイドルを導入するのにうってつけのフォーマットといえるのかもしれません。
アイドル駆動開発
さて、実はこの記事で伝えたいことがもう1つあります。今回この3つのツール、特にしぶりんを開発中に感じたことなのですが、ほとんどこじつけのようにアイドルを関連付けるだけで、業務外での技術的な勉強に驚くほど身が入りました。これが噂の「アイドル駆動開発」です(参考1, 参考2)。もしもあなたが最近技術の取得についてハングリー精神を失ってしまったと感じていたら、あなたなりのアイドル駆動開発を始めてみてはいかがでしょうか。
明日の記事の担当は @licht110 さんです。彼もまた尊敬すべきアイドルプロデューサーなのですが、それはまた別の話。いつかまた別の時に話すことにしましょう。