ドミニオン日本選手権に参加してきた

なんだかんだで毎月のように夜会*1ドミニオンやってるんだけど、行きつけのゲームバー、ナインティの店長が日本選手権に出るということで、それに対抗するべく夜会メンバーの@No6と一緒に参加してきた。一緒にとは言っても、@No6は午前の部で、おれは午後の部だったけど。
昼過ぎに午前の部の様子を見にいったら、夜会四天王の中で最弱の男は残念なことになってた。午前の部では、鬼が住むという噂のゲームスペース柏木の人たちが猛威を振るっていて怖かった。午後はさらに参加者が増えるらしく予選通過は絶望的な気がしていた。
のろくと別れて午後の部に参加しようとエレベーターに向かったら、アルファブロガーの@manameさんに出会って色々話した。
午後の部の参加者は110人らしく、午前の部よりもやっぱり多かった。
以下簡易レポート(サプライは覚えてないので他のレポート参照のこと)

1戦目

一戦目は確か2,5スタートで、地下貯蔵庫と祝祭買ったような記憶ある。方針としては、サプライに民兵あったから、民兵や地下貯蔵庫や祝祭で手札を減らして、そこに書庫を入れて大量ドローする方針で行ったけど、最後の最後に金が出ず7金で悲しみの2位。祝祭はいらなかったかも。金貸しは確か一枚入れて圧縮した。確か研究所プレイに負けた

2戦目

2戦目は庭園と礼拝堂、魔女などがあったけど、礼拝堂や魔女に目が眩んで他のメンバーが庭園ゲーしないみたいだったので木こり、泥棒からの庭園スタート。工房は無いけど、木こりと市場でbuyを増やし、泥棒で金を奪ってデッキを増やした。あと呪いを10枚近くもらって最終的に52枚、庭園は7枚で1位。

3戦目

午前の部で16位通過ラインが15点(1位が6点、2位が3点、3位が1点、4位が0点という配分)だったので、ここで4位を取ると終了してしまうことがわかっていたので、最低でも3位を取る戦略をとろうと思ってた。
3戦目は鉱山、冒険者などの金プレイ場だったので、練習通り?銀貨宰相でスタート。4ターン目に宰相が来て金貨を購入し、5ターン目にも6金産むという割と理想的な周りをしたけど、初手で鉱山取った人のスピードが普通に速くて安定していてついていけそうになかったので途中で公領を買いまくって2位を確保しにいった。今回も悲しみの7金が幾度と無くあったが2位。

4戦目

現時点で12点で15位。1位または同点1位で通過、2位だとかなり厳しい状況だったので1位狙いをせざるを得ない状況でスタート。
4戦目は初手で魔女取った人が玉座と組み合わせてぶん回す中、銀貨銀貨スタートで議事堂ステロっぽいことしようと思ったら、3,4ターン目で4金しか集まらず涙目。午前中@retletさんが全く同じ状況になってたことを思い出して悲しさ倍増。
仕方ないので改築を2枚入れて改築プレイに変更。他を楽させないように魔女を途中で一枚入れたけど、これが失敗だった気がする。議事堂か改築入れたほうがたぶん良かった。
魔女を配ることに必死で展開が遅かったので、意外と行けるかもと思ったんだけど、終盤に最下位の人が市場と改築と工房使ってアホみたいに屋敷買ったせいで3山切れて死。最後の公領が買えればワンチャンあったのに、1位と5点差、2位と1点差で死。やはり柏木勢強し。これにてドミニオン日本選手権終了

感想

あとで知ったけど、実は最後のゲームは2位でも16位以内に入れていて、実際4戦目で2位だった人が通過してた。すげーくやしい。基本セットは1年くらい前にBSWでやりまくったから大丈夫かなと思ったけど、柏木勢は戦略とかカウンティングもちゃんとしてて(おれも割とやってる方だと思ってたけど…)練習不足を痛感した。
あと参加者にオタクっぽい人はもちろん多かったけど、女性とか8歳の男の子とかもいていろんなプレイヤーがいて楽しかった。基本的に内輪でやってて、たまにゆるドミとかナインティでやってるけど、他のところに参加してやるのも楽しいだろうなぁと思った。
次に開催されるようなことがあったらまた参加したい。次はちゃんと練習して行く!

*1:大学時代の友達で集まって夜な夜なゲームなどする

node.jsでRubyのBundlerのようにパッケージを管理する

仕事でRails3を使ってて便利だったもののひとつにbundlerがある。
これはGemfileというファイルに、プロジェクトで使うgemを記述しておきbundle installコマンドで必要なgemがインストールされるというもの。
node.jsを触ってる時にも同じようにできないかなーと探していたら、npmにすでに同様の機能が備わっていることを知ったので使ってみた。

package.jsonを作成する

npmeで、rubyのGemfileに相当するものがpackage.jsonになる。他のライブラリの設定ファイルとか見てもjsonだったし、JSだとそりゃjsonになるよなぁと思ったりした。
このpackage.jsonをプロジェクトの直下に配置して以下のように書く

{
  "name": "tohae_example",
  "version": "0.0.1",
  "engines": "0.4.11",
  "author": "tohae",
  "dependencies": {
    "express": "2.3.11",
    "jade": "0.15.4",
    "everyauth": "0.2.18",
    "now": "0.7.4",
    "node-dev": "0.1.9"
  }
}

Gemfileとの違いは、依存するパッケージだけではなく、プロジェクトや作者の名前や、使用するnodeのバージョンも書くというところか。
nameにはプロジェクト名(githubのリポジトリ名とかが使われるらしい?)、versionはバージョン、enginesにはnode.jsのバージョン、authorには作者名、そしてdependenciesに依存するライブラリを記述する。
npm install expressのようにして入れるパッケージ名と、バージョン番号をハッシュで記述する。バージョン番号には>= 0.0.1 のような書き方もできるみたい。
このファイルを配置したあとに以下のコマンドを実行する。

$ npm install

何も指定せずにnpm installコマンドを実行すると、package.jsonを見てインストールを始めてくれて、プロジェクト以下にnode_modulesというディレクトリが作成され、その中にインストールされる。便利!

npm initでpackage.jsonを作る

前述のように直接package.jsonを作成しても良いが、npmにはnpm init というpackage.jsonの雛形を作成する機能が備わっていた(あとで気づいた)ので、そちらも試してみる。

$ mkdir node_tohae_example
$ cd node_tohae_example
$ npm init
Package name: (tohae_example)
Description: tohae example
Package version: (0.0.0)
Project homepage: (none) http://d.hatena.ne.jp/tohae
Project git repository: (none) https://github.com/tohae
Author name: tohae
Author email: (none) tohaechan@hoge
Author url: (none) http://twitter.com/tohae
Main module/entry point: (none)
Test command: (none)
What versions of node does it run on? (~v0.4.11)
About to write to /Users/wakizaka/git/node_tohae_example/package.json

{
  "author": "tohae <tohaechan@hoge> (http://twitter.com/tohae)",
  "name": "tohae_example",
  "description": "tohae example",
  "version": "0.0.0",
  "homepage": "http://d.hatena.ne.jp/tohae",
  "repository": {
    "type": "git",
    "url": "git://github.com/tohae.git"
  },
  "engines": {
    "node": "~v0.4.11"
  },
  "dependencies": {},
  "devDependencies": {}
}


Is this ok? (yes) yes

npm init を実行すると、対話シェルが出てくるので、プロジェクト名や作者情報などをそれぞれ入れていくと、それをもとにpackage.jsonが作成された。さっき自力で作ったのに比べて間違いも無いし便利ですね。よく見るとさっき自分で書いたのとenginesの記述方法違うし…。

というわけで、node.jsでもbundlerのようにパッケージのバージョン指定してインストールができました。便利ですね。
他にも色々できるっぽいですが、詳しいことは公式ドキュメントや、日本語訳を見ると良いと思います。
http://npmjs.org/doc/json.html
http://hideyukisaito.com/doc/npm/dev/

そろそろnode.jsを触っておかないとダメかなと思って、nowjsってのを使ってみた日記

ブクマをさかのぼっていてnowjsってのを思い出したので使ってみることにした。
nowjs for Node - Directly call remote functions in Javascript

公式サイトを見ると、nowjsはクライアントとサーバ側で互いにメソッドを呼び合うことができ、12行でリアルタイムチャットが作れるらしい。12行って簡単すぎわろた。
というわけで今回はnowjsの導入と、サンプルを動かし、サンプルコードの中身を見てわかったことをメモっておく。

準備

naveを使ったnode.jsインストールと、最近のnpmの使い方 - ラシウラ

上記URLを参考に、naveとnpmをインストールする。
ただしnodeの最新版を入れると0.5系が入ってしまい、nowjs*1が動かないので、安定板の0.4.11を入れてnpmもインストールする。

$ nave use 0.4.11
$ curl http://npmjs.org/install.sh | sh

nowjs用のディレクトリを作って、そこにnpmでnowjsに必要なライブラリをインストールする。
nowjsについてくるexampleを動かすために、express(Sinatraっぽいやつ)とels(ERB的なテンプレートエンジン)を入れる。

$ npm install now
$ npm install express
$ npm install ejs

インストールしたらそのディレクトリ以下に node_modulesというディレクトリができていて、その中にnowjsの本体とexampleが入っているので、それを動かしてみる。

$ cd node_modules/now/examples/express_example
$ node app.js

これで http://localhost:8080/ にアクセスすればチャットを試せます。ChromeSafariだとwebsocketでアクセスしてるみたいだけど、他のブラウザだとcometみたいにずっとリクエストし続けてた。これはnowjsを入れたときに一緒に入るsocket.ioがなんかやってるのかな?

express_exampleの他にサンプルが2つあるけど、express_exampleを選んだのは一番コードが単純だから。というわけで今回はこのexpress_exampleのコードを見ながらどういう風に動いてるのか見ていきたいと思う。

サーバ側

先にサーバ側のコード(app.js)を見る
30行目まではexpressのコードなので無視する。重要なのは30行目以降

// NowJS component
var nowjs = require("now");
var everyone = nowjs.initialize(app);

これはnowjsの準備。とりあえず書いとく。

>|javascript||
nowjs.on('connect', function(){
console.log("Joined: " + this.now.name);
});
nowjs.on('disconnect', function(){
console.log("Left: " + this.now.name);
});
|

これはサーバに接続した(または抜けた)時にコールバックされる。例えばチャットを作るのであれば、接続時に「〜さんがオンラインになりました」と表示したりだとか、接続中のユーザーを保存して「現在オンラインのユーザーを表示」みたいなことができるかなと。disconnectの方は逆のことができますね。

everyone.now.distributeMessage = function(message){
  everyone.now.receiveMessage(this.now.name, message);
};

これはdistributeMessageという関数を定義している。
this.now.nameはクライアント側のJSで定義した変数。receiveMessageというメソッドはクライアント側で定義したメソッドを呼び出している。

クライアント側

クライアント側は/nowjs/now.jsというファイルをまず読み込んでいる。
このファイルはサーバを起動したときに作られるっぽい。
メインのコードはchat.ejsにある

<script>
    $(document).ready(function(){
      now.receiveMessage = function(name, message){
        $("#messages").append("<br>" + name + ": " + message);
      }
      $("#send-button").click(function(){
        now.distributeMessage($("#text-input").val());
        $("#text-input").val("");
        $("#text-input").focus();
      });
      now.name = prompt("What's your name?", "");
    });
</script>

now.nameのように定義すると、サーバ側と変数を共有できる。サーバ側ではnow.nameではなくthis.nameで参照する。
now.distributeMessage()とやると、サーバ側で先程定義したメソッドが呼び出せる。
now.receiveMessage = のように関数を定義しておくと、サーバ側で呼び出すことが可能になる。
クライアント側からサーバ側の関数を、サーバ側からクライアント側のコードを直接叩けばいいので、ajaxのリクエストみたいにコールバック指定したりいろいろする必要がなくてすっきりしますね!

まとめ

12行でリアルタイムチャットができるのは確かにすごいんだけど、nowjsの便利なところはクライアントとサーバ側でメソッドをお互いに呼び出しあったり、変数を共有できたりするところにあるのかなと思った。他のexampleには部屋を作ってグループチャットをするものも含まれていたし、これを使えばLingrみたいなのは意外と簡単に作れそうな気がした。
あとRailsアプリにnowjsを使ってリアルタイムに通知するみたいなのを遊びで実装してみたけど、railsとnodeでポート番号が違うせい(?)でクロスドメイン制約に引っかかったのか(または自分のプログラムが悪いのか)Firefoxで動かなかったりしたし、サーバ側がRailsなのに新しくnode.jsを立てるのはどうなのとか、運用さんにまた新しい仕事を頼むほどのメリットも感じなかったので諦めた。
というわけで全部JSで何らかのサービスを作ってみたくなったのでした。

*1:正確にはnode-proxy?

ActiveSupportが無いと俺はプログラミングも出来ないのかよ !

ウチらのあるある│あるあるを投稿して、みんなで共感しよう!

たまにRailsじゃなくてrubyを使うと、blank?とかが使えなくて悲しい思いをしますよね? blank?をRails以外でも使うときはいつもお世話になってる@sasata299さんのブログにあるのでそのとおりにすればいいです。
Rails以外の環境でblank?メソッドを使うときの注意 - (゚∀゚)o彡 sasata299's blog

ActiveSupportのblank?はよく使うメソッドの筆頭ですが、それ以外にも気づかないうちにお世話になっているものがいくつもあるので、最近使ったものを忘れないようにまとめておこうと思います。

Time.parse

(追記) ActiveSupportじゃなかった
適当な日時を表す文字列を引数に与えると、Timeオブジェクトに変換してくれるという便利なものです。
時間のフォーマットを指定したりすることなく、うまいことやってくれるのでとても楽です。

# mysqlのdatetime型
> Time.parse "2010-03-04 18:50:13"
 => 2010-03-04 18:50:13 +0900 

# solrの時間型
> Time.parse "2010-03-05T03:58:10Z"
 => 2010-03-05 03:58:10 UTC 

# twitterのAPIのレスポンス
> Time.parse "Fri Jul 16 16:55:52 +0000 2010"
 => 2010-07-17 01:55:52 +0900

プログラムで使いそうな時間の文字列はだいたいTimeオブジェクトに変換してくれました。

Time::DATE_FORMATS

先ほどのTime.parseの逆で、こっちはTimeオブジェクトを文字列に変換するやつです
まずTime::DATE_FORMATSに変換したいフォーマットを定義します

Time::DATE_FORMATS[:mysql] = "%Y-%m-%d %H:%M:%S"
Time::DATE_FORMATS[:solr] = "%Y-%m-%dT%H:%M:%SZ"
Time::DATE_FORMATS[:twitter] = "%a %b %d %H:%M:%S %z %Y"

このように定義したあとに、Timeオブジェクトのto_sメソッドで変換します

> Time.now.to_s(:mysql)
 => "2011-08-25 11:51:48" 
> Time.now.to_s(:solr)
 => "2011-08-25T11:52:05Z"
> Time.now.to_s(:twitter)
 => "Thu Aug 25 11:52:09 +0900 2011" 

ね?簡単でしょ

ActiveSupport::Concern

rubyにはmix-inというのがあります。あるクラスのメソッドを使いたいけど、継承するのはなんか意味が違うよなーって時とか、多重継承したいみたいな時に使うやつです。

module Hoge
  def moge
    puts "mogemoge"
  end
end

class Piyo
  include Hoge
end

piyo = Piyo.new
piyo.moge
# => mogemoge

上記の例のようにmoduleをclassの中でincludeしてやれば、moduleのmoreというメソッドがPiyoというクラスのインスタンスメソッドになることがわかります。
こういうことができると、includeでインスタンスメソッドだけじゃなくクラスメソッドも追加できるようにしたくなるんですが意外とめんどくさいです。(やり方は説明しません)
moduleをincludeしてインスタンスメソッドもクラスメソッドも追加したい場合は、ActiveSupport::Concernを使うと簡単にできますよというお話です。簡単さはコードを見れば一目瞭然です。

module Hoge
  extend ActiveSupport::Concern
  
  module InstanceMethods
    def instance_moge
      puts "いんすたんすめそっだよー"
    end
  end

  module ClassMethods
    def class_moge
      puts "くらすめそっだよー"
    end
  end
end

class Piyo
  include Hoge
end

Piyo.class_moge
# => くらすめそっだよー
piyo = Piyo.new
piyo.instance_moge
# => いんすたんすめそっだよー

moduleの中でActiveSupport::Concernをextendし、インスタンスメソッドを追加したい場合はInstanceMethodsを定義してその中に、クラスメソッドを追加したい場合はClassMethodsを定義してその中に書きます。簡単だし読みやすいので素敵です。
InstanceMethodsは特に明記しなくてもインスタンスメソッドになるのでなくていいかもしれません。僕は書いてません。

まとめ

今回紹介した以外にもActiveSupportには他にもいろんな便利メソッドがありますが、紹介してるとキリがないのでこのあたりでやめておきます。詳しく知りたい人は公式のドキュメントを読むとか、Rails3レシピブック190の技にあるので読んでみるといいと思います。

Rails3レシピブック 190の技

Rails3レシピブック 190の技

ActiveSupport以外にも便利なものがたくさん載ってるRails3レシピブックは超おすすめです!

iMacとMacBook Airを買ったので開発環境を整えた

会社PCがiMacに変わり、その快適さの前に屈してMacBook Airを個人で買った。2週連続で開発環境を構築したのでそれをまとめておく。
ちなみにiMacは21インチでSSD256GB,メモリ8GB。Airは11インチでCore i7にした。
27インチじゃないのは会社が金をくれなかったから。Airを13インチにしなかったのは会社に13インチAirが溢れてるからなのと安価でCore i7したかったから。

GUI

先にMacAppStoreやブラウザでダウンロードしてきてGUIで適当に入れる。開発用の環境はhomebrewなどで入れていくので後回し。

KeyRemap4MacBook

キーボードの配置などをマッピングするためのもの。
インストール後再起動が必要なので最初に入れる。
英語配列のキーボードで、commandキーを単体で入力した場合に、かなや英数に切り替えるようにしたりできる。日本語配列のMacキーボードに慣れていた(3年半近く白MacBookを使ってた)のでこの設定に変えた。あとは右optionキーをfnに変更したりした。

Xcode

iPhoneアプリの開発をするつもりは今のところないけれど、Xcodeを入れることでgccやgitが入るので最初に入れておく。ダウンロードにも時間がかかるから最初にやるのがいい。MacAppStoreから入れる

Growl

Skypeとかの通知はやっぱりGrowlでしたいので入れる。
zshrubyからも使いたいので、忘れずにgrowlnotifyも入れる

Google日本語入力

ことえりはかわいい(だけ)

Evernote

会議のメモはEvernoteで取ってiMacと共有する

Skype

仕事の連絡はSkypeでやってるから必須

Chrome

快適ですよね

Firefox

deliciousのアドオンやツリー型タブ、GoogleReader内でのリンクはバックグラウンドで新しいタブで開くなどの設定がChromeでできたら移行してる。
あとFireMobileSimulatorがなぜChromeにないのか。

macvim-kaoriya

通常のvimとの違いがいまいちわかってないけど入れる。
そのあとコマンドラインから使うために.zshrcに以下の記述を追加

export EDITOR=/Applications/MacVim.app/Contents/MacOS/Vim

CUI編

最近はhomebrewが大人気なのでまず最初に入れる。確かに便利。今後はだいたいのものがbrew installで入れる

homebrew

Terminal.appを起動して以下のコマンドをうつだけ。途中パスワードを聞かれる。

$ /usr/bin/ruby -e "$(curl -fsSL https://raw.github.com/gist/323731)"

Lionから、Teraminal.appが256色になったのと、フルスクリーンモードが使えるのでTerminal.appで問題ない気がする。iTerm2の便利な所があればだれか教えてください><

screen

tmuxも使ってみたけどなんだかんだでscreenに慣れてたのでscreenを使う。デフォルトで入ってるけど、256色に対応してないっぽいので最新版をビルドする。brew installではできなかった。

$ git clone git://git.savannah.gnu.org/screen.git
$ cd screen/src
$ autoconf
$ autoheader
$ ./configure --enable-colors256 --prefix=/Users/tohae/local

$ make
$ make install

最新版をgit cloneして、configureオプションで256色を有効にし、インストール先を自分のホームディレクトリ以下にした。
/Users/tohae/local/bin/screen というファイルができているので、.zshrcにaliasを書いておけばOK

rvm

rubyはrvmを使って入れる

$ bash < <(curl -s https://rvm.beginrescueend.com/install/rvm)

インストールが完了したら.zshrcを再読み込みして、ruby 1.9.2を入れる。

$ source ~/.zshrc
$ rvm install 1.9.2
その他

ここまで書いて飽きてきた。
あとはmysqlとかMongoとか適当にbrewで入れる。ImageMagcikやredisやsolrも必要に応じていれる。nginxもbrewで入るけど、passenger使うんならpassenger経由で入れたほうがたぶんいい。Railsやるんだったらpowを入れたほうが良さそうだけどまだ試してない。
vimのプラグイン周りは適当にvundleで入れる。rails.vimとかneocomplcacheとか。あとcolorschemaも256色のやつぶち込む。

最後に

会社のiMacで環境構築してLionにも触れたあとだと、自分の金で買ったMacBook Airが到着しても特に興奮することもなく、むしろ腹が減ってたので未開封のまま放置して、肉じゃが作って食べました。

Capistranoでデプロイ時にJavascriptの圧縮を行う

前回の記事(http://d.hatena.ne.jp/tohae/20110812/1313116651)で、ほんものの社長がコメントしたり、文章をちょっと修正するなどして、前の会社でも同じようなことをしたなぁと懐かしい気持ちになって、ちょっとブログが楽しくなってきたのでブログ書くことにします。

今回はYSlowやGoogle Page Speedなんかで忠告される、Javascriptを圧縮(難読化?)してファイルサイズを減らして高速化しようというお話を、uglifyjsとcapistranoでデプロイする時に自動的にやってみようという話です。

UglifyJSのインストール

UglifyJSはnode.jsで作られたJSの圧縮ツール。jQueryの圧縮にも使われているそうです。
というわけでまずはnode.jsを入れる必要があります。
naveとかで入れるほうが流行りなのかもしれませんが、めんどくさいのでbrew installしました。

$ brew install node

UglifyJSはnpmで入れる方がよさげ?なので、次はnpmを入れます

$ curl http://npmjs.org/install.sh | sh 

npmが入ったらようやく本題のUglifyJSを入れます

$ npm install uglify-js -g

-gオプションはグローバル領域に入れるやつみたいで、/usr/local以下に入りました。付けないと~/.npm以下に入りました。付けずにやるとuglifyjsがないよみたいに怒られたのでよくわからず-gオプションを付けました。まぁ動いてるからいいかなと

動作確認

適当にJSファイルを作って保存します。

//hoge.jsで保存
var hoge = new Array(1,2,3,4,5);
alert(hoge);

uglifyコマンドで圧縮します

$ uglify hoge.js
//hoge.jsで保存
var hoge=[1,2,3,4,5];alert(hoge)

実行結果が出力され、Arrayが短い書き方になったり、改行が取り除かれたりしています。
ファイルに出力したり、コメントを取り除いたりなどいくつかのオプションがありますが、詳しくはgithubを見たほうが良いです。
https://github.com/mishoo/UglifyJS

CapistranoからUglifyJSを使う

デプロイ前にJSを圧縮してコミットするのはだるいので、デプロイ時にJSを圧縮して上書きしてしまえばいいよねって思ったので、capistranoにタスクを追加します。
config/deploy.rbに以下のようなタスクを追加

after "deploy:update_code", "deploy:minify_js"
namespace :deploy do
  task :minify_js do
    run <<-CMD
      cd #{release_path} &&
      /usr/local/bin/uglifyjs --overwrite public/javascripts/application.js
    CMD
  end 
end

deploy:update_code (ソースコードのアップデート)が終わったあとに、release_pathに移動して、public/javascripts/application.jsを圧縮して上書きするというタスクです。
こうしておけば、cap deployとかcap deploy:migrationsとかしたときに必ず圧縮されて便利ですね!

最後に

こうしてブログには書いたものの、この方法だと各サーバにnode.jsを入れる必要があってだるいので、本番に導入は今のところしてません。
一応試してみたしブログのネタにはなるかなと思って書いたのでした。
本番に導入されてYSlowやGoogle Page Speedの評価が高くなる日は来るのか!?来るといいですね…