G*と言えば猫、ということで子猫Tube作りました #gadvent2011

たいしたものではありませんが、まぁ実行してみてください。(猫好きさんは仕事の手が止まるので注意!!!)

YouTubeAPIはGETでAtomフォーマットのXMLを取得できますので、それを解析してURLを抽出しています。ブラウザ表示のところはjava.awt.Desktopを利用しているので、JDK1.6以上が必要です。
あと、たいしたことではないですが、検索結果件数がfeed/itemsPerPageに入っているので、その範囲内でランダムになるようにしてあります。

次は id:ksky さんです。よろしく!

スキャンしたJPEGを縮小してzipで固めるGroovyスクリプト

念願のAndroid Tablet(ICONIA TAB A500)を入手し、本格的な自炊生活に突入しました。以前から裁断機とScanSnapは準備してあったのですが、やはりビューアーがあるとやる気が出ますね。

技術書などは検索可能PDFにするのでScanSnapの付属ソフトだけで後処理まで完了なのですが、漫画本は作業効率(ページ単位でのスキャンチェック)や汎用性を考慮してJPEGのzip圧縮で運用しています。

スキャンは300dpiで行っているので、そのままだとファイルサイズが1ページあたり500KBなので、200ページの本だと全体で100MB程度になります。これではちょっとサイズが大きすぎるので、Tabletで参照するための縮小バージョンを作成しています。

JPEGはすでに十分圧縮がかかっているので、単純にピクセル数を間引けばサイズが縮小できます。この作業を一括で行える汎用ツールを探したのですが、なかなか目的に見合ったものが見つかりません。探すのも疲れたのでGroovyで軽く自作してみました。

JPEGサイズ縮小スクリプト

指定されたディレクトリ以下の階層をたどって、すべてのJPEGファイルを変換します。
javax.imageio.ImageIOを使ってます。圧縮率は縦横1/2で固定(中途半端な倍率だとかえって画質が落ちるので)。
変換後のファイル名は、s+(変換元ファイル名)に決めうちです。ファイル名がsで始まるものは処理済とみなして無視します。

最適化など特に行っておらず、とりあえず「動く」レベルのものですが、私の環境(Core i7 2.8Gx4core)では1冊分の加工に約4分ほどです。動かして放置しておけばよいので、当面はこれで十分。

フォルダごとにzipで固めるスクリプト

指定されたディレクトリ直下にあるすべてのディレクトリを、ディレクトリ単位でzipにします。
AntBuilderを使えば簡単ですね。
zipファイル名は、(対象ディレクトリ).zipに決めうちです。

こういう小物はGroovyで作っておくと、他の環境(LinuxとかMacOSとか)でもそのまま使えるのでいいですね。

参考:愛用のTablet

3万円台後半で購入できます。Tegra2なので中身はXoomやRegza Tabletと大差ないです。お買い得。

acer【アイコニア】ICONIA タブレットPC シルバー ICONIA TAB A500-10S16

acer【アイコニア】ICONIA タブレットPC シルバー ICONIA TAB A500-10S16

Grails Database Reverse Engineering Pluginインストール失敗

既存テーブルのマスタメンテアプリを自動生成したいというお話があり、GrailsのDatabase Reverse Engineering Pluginを試してみました。
とりあえず最新の安定版であるGrails-1.3.7でgrails install-plugin db-reverse-engineerしたところ、残念ながら以下のエラーでインストール失敗です。

::::::::::::::::::::::::::::::::::::::::::::
UNRESOLVED DEPENDENCIES ::
::::::::::::::::::::::::::::::::::::::::::::
org.hibernate#hibernate-tools;3.2.4.GA: not found
freemarker#freemarker;2.3.8: not found
org.beanshell#bsh;2.0b4: not found
org.hibernate#jtidy;r8-20060801: not found
::::::::::::::::::::::::::::::::::::::::::::

いまg*workshopの最中なので、原因追及は帰ってからやるか。。。

Groovy-1.8の新機能:JsonBulider

エスケープされた日本語が通るかどうか確認してみました。(Groovy-1.8RC2での結果です。)

JsonSluperやJsonBuilderではエスケープされたUnicode文字列が問題なく扱えていることが確認できました。
ただし、JsonOutput.toJson()にはエスケープを行う機能は無いようです。RFC上ではオプション扱いなので問題ないですが。

あと注意点として、JsonSlurperでパースしたJSONオブジェクトはHashMapに変換されるため、項目の並び順は保存されません。文字列化して比較するときなどはご注意を。

Twitter Botの改善を目指して機械学習勉強中

http://gihyo.jp/dev/serial/01/machine-learning/0003 を参考に勉強中です。
元記事のコード例はPythonですが、ためしにGroovyで実装してみました。

ほとんどがMapの処理なので、GroovyでもPythonとほぼ同じくらいのコード量で実装できますね。
目標は、http://twitter.com/hatena_groovy に混入してくるノイズの除去です。(PCの周辺機器の情報とかね。。。)

G*ワークショップ@仙台の資料

2010/4/24に仙台にて開催されました、G*ワークショップにて発表させていただきました。
JGGUGのイベントでしゃべるのは昨年夏以来ですね。。。

最近Groovyってどうなの?という方は、最後の「お得情報」だけでもチェックしてみてください。
本当にお得ですから!!

土曜日にも関わらず、多数の方にご参加いただきありがとうございました。
また、会場をご提供いただいた富士通東北システムズ様、ありがとうございました。
また仙台でやりたいですね。

GroovyのWritableインターフェースの存在意義

id:uehajさんの解説が分かりやすいです。
http://d.hatena.ne.jp/uehaj/20091019/1255925722
典型的な利用例としては、StreamingMarkupBuilderでのXML出力です。
XMLの出力ロジックをクロージャ(MarkupBuilderの記法)で構成し、StreamingMarkupBuilderのbind()メソッドの引数に指定してやると、bind()の結果としてクロージャによって表現されたXML文書ツリーの構造を出力するためのWritableを得ることができます。重要なのは、Writableを得た時点では実際の処理は行われておらず、Writable.writeTo(Writer out)で指定された出力先outが結果を要求した時点で必要なだけの処理を行うということです。
すなわち、Writableを利用することで、

  • 処理を先送りできる(遅延実行)
  • 処理をバッファリングできる(ストリーミング実行)

が実現できるということです。
ちなみに、XmlSlurper.parse()でXMLをパースするとGPathResultが得られますが、これはXML文書ツリーをトラバースするためのポインタ(イテレータ)のようなものと解釈すると理解しやすいです。なので、GPathResult経由で取り出したXMLを加工して出力するためには、StreamingMarkupBuilderにbindしてやる必要があるのです。
うまくまとまりませんが、ひとまずメモということで。