2011年12月16日金曜日

node.js + socket.io + Arduinoでイイネ!



eXtreme Hagoで使われていた、リアルタイムに「いいね」と出すあのシステムをパクりました。


node.js + CoffeeScript + express + node-arduino + MongoDBで出来てます。


デモ動画



動機


ITfrogsとLexuesAcademyの懇親会でくまさんがいいねと同じの200分で作った!と言ってたので僕も作りたくなった。


これが@さんがつくったやつ。


higumachan/iine ? GitHub


本家のイイネに加え、グラフ機能つき。


開始時間と終了時間にぽちっとボタン押すとグラフが表示され、どこで盛り上がったか一目瞭然。


こんなすごいの「200分で作った」なんて言われたら僕も作りたくなっちゃうでしょ!!


僕が何か1つ機能を付け加えるなら何がいいか?


「そうだ、リアルにボタン押す機能でも作るか」


出来ました。


f:id:h6n:20111216035307j:image:w360


ソースコード


hanachin/iine_duino ? GitHub


※何分で出来たかは秘密です


解説


僕はCoffeeScriptにハマっています。ちゃんと使ってみたい。


CoffeeScriptが書ければJavaScriptも書ける。


JavaScriptが書ければnode.jsが使える。


なので、CoffeeScript + node.jsで作成することに決めました。


ウェブサイトを表示する

ウェブ側はexpressを使って表示することにした。


理由:




  • 直接書くのは多分面倒

  • Sinatra-likeで学習コストが低そう

  • 持ってる本(パーフェクトJavaScript)に例がのってる


本のサンプルを動かしながら使い方を覚えさくっと開発環境を整える。


リアルタイムにイイネを出すために

Nodeが使えればsocket.ioが使える!!


ということでsocket.io使えば楽勝でした。


ただし実際にコード書くよりも使い方を調べる方が時間かかった。


socket.ioを使う理由:




  • リアルタイムに通信したいから

  • 自分でリアルタイムに通信出来るように一から書くより簡単、確実、便利、安心

  • 使ってみたかった


グラフを表示するために

くまさんはjqplotというライブラリを使っていたので僕もそれを使うことに。


グラフを表示するためには記録が必要、なのでMongoDBを使うことにしました。


理由:




  • RDBを設定するのが面倒だった

  • 既にmongooseというライブラリがある

  • 本に例が載ってる


イイネが押された時刻だけを記録するシンプルなデータベースです。


まず、開始時刻と終了時刻を含んだURLにアクセスすると、その間のイイネを集計してJSONで返すようなAPIを作った。


あとはグラフを表示する側からそれを叩いて、jqplotに渡すだけ。jqplot便利ですね。


リアルにボタンを押すために

ボタンをArduino経由でPCに接続しようと考えた。


押せればなんでもいいので100円ショップでプッシュライトボタンを買います。


Arduinoとnode.jsをつなぐにはnode-arduinoを使います。


普通にnpm install arduinoで入れると、digitalRead(入力)が使えなくてハマってました。


Forkされてるこちらのリポジトリを使いましょう。


hapticdata/node-arduino ? GitHub


後は、ボタンを分解してスイッチのところにつなぐだけ。簡単ですね。


Tips等



  • Guardを使うとCoffeeScriptを勝手にコンパイルしてくれる。coffee -wcでやるよりも便利。

  • node-devを使うとJavaScriptファイルが更新されると自動でサーバーを再起動してくれて楽。

  • プッシュライトはLEDが3つついてるんだけど、どうやって光らせるか誰か教えてください。(Arduinoじゃ電流足りないよね?)


反省点


3つあげると




  • コード書くのに時間をかけすぎた

  • ブログの解説がざっくりすぎる

  • ブログ書くのも旬なうちじゃないと書けない(なので早く製品を作ろう)


まとめ




  • CoffeeScriptでイイネシステムが書けた。

  • expressを使うと簡単にウェブアプリが書ける。

  • socket.io使えばリアルタイムに通信が出来る。


    • どうやって通信するか考えなくて済むのでリアルタイム性の高いものがすぐ作れる。



  • jqplotは見栄えのいいグラフをさっと作れる。

  • node-arduinoを使えばnode.jsとArduinoを連携出来る。


    • ソフトウェアだけでは出来ないことが出来るようになるかも。




オリジナル版と、くまさんの作った奴がなかったら作れなかった。ありがとうございます。


作ってる途中、失敗がいくつもあったけど最終的にボタン押して出来るようになると超楽しかった。


もっと電子工作、はんだづけやってみたい!


もっと聞きたい事、詳しく書いてほしい事があれば@までお願いします。





2011年12月13日火曜日

SimpleTimeKeeperにURLでタイマーの時間を指定出来る機能を追加してpull requestおくったった



SimpleTimeKeeperという便利なタイマーがあります。


SimpleTimeKeeper


シンプルで見やすくてとってもべんり。プレゼンの時に重宝します。


その、SimpleTimeKeeperに、タイマーの時間をURLで設定出来る機能を付け加えてみた。


URLの末尾に#10:20や?10:30や#10-20や#10m20sとつけるだけで設定出来るよ!


実装


location.searchかlocation.hashを数字ごとに区切って、前から3つとってくる感じになってます。


最後にreverseしてるのは、10:20みたいに、hours, minutes, secondsを全部指定してないときに都合がいいからです。



time = (location.search || location.hash).split(/[^0-9]/).filter(function (x) { return x !== ""; }).slice(0, 3).map(function (x) { return parseInt(x, 10); }).reverse();
// Set Timer
$('#hours').val(time[2] || 0);
$('#minutes').val(time[1] || 0);
$('#seconds').val(time[0] || 10);


まとめ




  • SimpleTimeKeeperはシンプルだから機能を追加するのもらくちん。

  • もっと追加したい機能があるけど、追加するにしても、なるべくシンプルにいきたい。

  • 僕はforEachやfilterやmap等、enumerateするメソッドを続けて書く事が好きだということに気づきました。


こないだもこんなの書いてたし。



urls = tweets.select{|t|
not t.attrs["entities"].empty?
}.select{|t|
t.attrs["entities"]["urls"]
}.map{|t|
t.attrs["entities"]["urls"].map{|u| u["expanded_url"]}
}.inject([]) {|result, urls|
result + urls
}.select{|u|
DB[:urls].where(:url => u).count.zero?
}.uniq





カップ麺用タイマーアプリ「QuickNoodleTimer」



作りました。


hanachin/qnoodle ? GitHub


起動した瞬間から3分間カウントが始まります。


タイマーのスタートボタン押す必要なし。


Homeボタンを押して別のアプリを開いてても安心、3分たつとToastメッセージと(ちょっと小さい)音とバイブで知らせてくれます。


野良アプリですけど、インストールはこちらから


QNoodle.apk





ホモスレbotを書きました。



ホモスレのURLをツイートするホモスレbotを書きました。


Twitter

ホモスレbot


ソースコード(ライセンスはWTFPL)

hanachin/homosure ? GitHub


要求


最近はホモスレ多いですよね。1日に何本も立ってる気がします。


僕が欲しかったもの



  • 手動でホモスレ検索する手間が省ける

  • 面白いホモスレならTwitterで誰かがつぶやいてくれているはず

  • 2chの生のホモスレではなくまとめが見れればよい

  • 既に見た事あるスレは見なくてもいい

  • なるべくホモスレでの検索結果を汚さない


欲しかったので作る、いつもの流れですね。


実装


何度か使ってなれているので、Twitterのgemを使っています。


Twitterの「ホモスレ」の検索結果からURLを抽出し、DBにデータを蓄積しツイートするようになってます。


既にツイートしたことのあるURLはツイートしないようになってます。


一旦Mechanizeで実際にアクセスすることで、リダイレクト後のURLを取得するようになっています。(なっているはずです、多分)


実際にアクセスする前のURLと、実際にアクセスしたURLが違う場合(リダイレクトなど)データベースで、リダイレクト後のページとひもづけてます。


これから機能を追加するなら




  • Twitterでそのホモスレの検索結果の隆盛等をグラフで表示する

  • URLリダイレクタを挟んでクリック数等の情報を取得する

  • 【今日のホモスレ】や【お勧めのホモスレ】等、既にDBにあるホモスレからリコメンドする

  • ページの内容からホモスレ度を判定する

  • 蓄積したホモスレのURLを元に、ホモスレを掲載してるまとめブログの一覧を作り、RSS等からもホモスレ情報を集める


まとめ


前から欲しいなーと思ってたので作りました。快適な生活に一歩近づきましたね。


もっと需要の高そうな別のワードに対するbotを作成するときに役立つかもしれません。


ホモスレbot作った話をブログに公開することで更にアレなものを作っても公開出来る謎の自信がつきました。





2011年12月10日土曜日

最近.zshrcに追記したgitの設定



とりあえず僕が使いそうなものだけ。


便利そうなのあったら追記しようと思う



# aliases
alias g='git'
alias ga='git add'
alias gb='git branch'
alias gc='git checkout'
alias gco='git commit'
alias gd='git diff'
alias gp='git push'
alias gs='git status'
alias gh='git push heroku master'





Guard + Powで快適Sinatra開発



Sinatraを使ってWebアプリケーションを作る際、Sinatraを手動で何度も再起動するのは面倒くさくないですか?


そんなときはGuardとPowを使えばSinatraのファイルを書き換え保存するだけで自動的に再起動させることが可能です。


これでテンポよく快適に開発出来ます。


Powの導入


~/.pow/以下にRackアプリのディレクトリへのシンボリックリンクをはるだけで、http://ほにゃらら.dev/でそのアプリにアクセス出来るようになります。


Homebrewを使っている場合は



% brew install pow


で導入出来ます。(多分)


僕はbrewを使わずに入れました。Powにはnode.jsが必要です。


僕はnvmを使ってnode.jsインストールしてPowのサイトに書かれたコマンドを実行してインストールしました。お好きな方で。


参考:Node.js 入門


参考:Pow: Zero-configuration Rack server for Mac OS X


Powderの導入


Powを更に便利に使うためにPowderをインストールします。



% gem install powder


で入ります。


参考:Pow使うならPowder入れておくだァーッ! - Meltdown Countdown


Guardの導入


Guardを使えばファイルが変更されたら自動で何かすることが出来ます。


自動で何をするのかをGuardfileに書きます。


bundlerやcucumberなど様々なツールに対応しています。(参考:List of available Guards ? guard/guard Wiki ? GitHub


guard-powを使えばSinatraのファイルをいじったら再起動、といったことが簡単に出来ます。



% gem install guard-pow


参考:Guard::PowでPowを更に快適に使う | ひげろぐ


試しにSinatraアプリを作ってみる


コマンドログ


Nil% mkdir hello
Nil% cd hello
Nil% cat > web.rb
require 'sinatra'
get '/' do
'Hello world!'
end
Nil% cat > config.ru
require "./web.rb"
run Sinatra::Application
Nil% cat > Guardfile
guard 'pow' do
watch('web.rb')
end
Nil% cat > .rvmrc
use 1.9.2
Nil% powder link
Your application is now available at http://hello.dev/
Nil% guard
Guard is now watching at '/Users/sei/hello'


ソースコード


この状態でweb.rbを書き換えると



Pow restarted.


と表示され、無事再起動していることが確認できます。


ハマったところなど




  • 僕はrvmでRubyを管理してるのですが、.rvmrcの中で使うRubyのバージョンを指定するのを忘れて怒られました。

  • guard pow initでGuardfileを生成する方が楽かも。(Railsアプリ等の場合)

  • 僕の場合、Sinatraのアプリの中に直接日本語を書いてたりするのでconfig.ruの先頭に1行これを付け加えてます。



# -*- coding: utf-8 -*-


まとめ


この記事はざっくりすぎるので参考リンクを読んだ方が詳しく書いてます。


ざっくりまとめると




  • Powを使うと~/.pow/シンボリックリンクはるだけでRackアプリが動く

  • Powderを使うとシンボリックリンクはるのや、Powに関わるあれやこれやをやってくれる

  • Guardを使うとPowで動いてるRackアプリを自動で再起動出来る


以上です。





Chromeのconsole.logの謎



この記事を読んで、Chromeのconsole.logの動きが謎すぎる気がして確認してみました。


CoffeeScriptで、newするときのプロパティ変数の初期化ってどーなってんの? - uzullaがブログ


検証


ソースコード


var a = [];

a.push('A');
console.log(a);

a.push('A');
console.log(a);


これをChromeのDeveloper toolのコンソールで実行してみました。


期待する出力


["A"]
["A", "A"]


実際の出力


["A", "A"]
["A", "A"]


調べてみた


console.log lazy等でググるとStackoverflow等のサイトがでてきた。


Is Chrome's JavaScript console lazy about evaluating arrays? - Stack Overflow


javascript - Bizarre console.log behaviour in Chrome Developer Tools - Stack Overflow


Bug 35801 – console.log object maps are read when you open the treeview on the console, not when they’re output in the console


なるほど。Webkit特有なのかもしれません。


console.logにオブジェクトを渡すと、console.logはそのオブジェクトの内容を出力します。


console.logが出力する準備をしている間にそのオブジェクトに変更を加えると変更後のオブジェクトの内容が出力されると。


シンプルな解決方法として




  • JSON.stringify

  • toString

  • slice (配列の場合)


等のメソッドや関数を使って別のオブジェクトを作成してから渡す方法が挙げられてますね。


ちなみに



Coffeescriptのクラスのプロパティ変数って、初期化が必須なの?(;´Д`)
コンストラクタで宣言しなおさないと、暗黙のウチに共有されちゃうの?
そういうもんなの??

JavaScriptのprototype継承ですね。



class Chain
queue: []
test: -> @queue.push "A"




var Chain;
Chain = (function() {
function Chain() {}
Chain.prototype.queue = [];
Chain.prototype.test = function() {
return this.queue.push("A");
};
return Chain;
})();


JavaScriptになるとこうなっています。


Chainクラスはprototypeというオブジェクトを持っています。(以下prototypeオブジェクト)


CoffeeScriptのクラスのメソッド等はこのprototypeオブジェクトのプロパティに定義されます。


Chainクラスのインスタンスはprototypeオブジェクトへの参照を持っています。


Chainクラスのインスタンスからqueueプロパティにアクセスするとき




  1. まずインスタンス自身がqueueプロパティを持っていないか調べる

  2. 持っていなければクラスのprototypeオブジェクトにqueueがないか調べる。

  3. クラスのprototypeオブジェクトにもqueueプロパティがなければ更に継承元のクラスを辿って行く


という感じになってます。


インスタンス自身がプロパティを持っているかどうか調べるためにはhasOwnPropertyを使います。



ソースコード



class Chain
queue: []
test: -> @queue.push "A"

c = new Chain
console.log "before c.queue = []"
console.log c.hasOwnProperty "queue"

c.queue = []

console.log "after c.queue = []"
console.log c.hasOwnProperty "queue"


実行結果


before c.queue = []
false
after c.queue = []
true


queueプロパティに配列を代入するまで、Chainクラスのインスタンスは自分自身のqueueプロパティを持ちません。


そのため、全てのインスタンスがChainクラスのprototypeオブジェクトのqueueプロパティを参照しています。


なのでtestメソッドの中でthis.queue.push("A")を呼び出すと、Chainクラスのprototypeオブジェクトのqueueプロパティが変更されるわけです。


こう書くとなおるわけ



ソースコード



class Chain
constructor: -> @queue = []

console.log "c = new Chain"
c = new Chain
console.log "c.hasOwnProperty 'queue': #{c.hasOwnProperty 'queue'}"


JavaScriptになると



var Chain, c;
Chain = (function() {
function Chain() {
this.queue = [];
}
return Chain;
})();

console.log("c = new Chain");
c = new Chain;
console.log("c.hasOwnProperty 'queue': " + (c.hasOwnProperty('queue')));


実行結果


c = new Chain
c.hasOwnProperty 'queue': true


コンストラクタの中で以下のコードを呼び出すことで、インスタンス自身のプロパティとしてqueueを定義しています。



this.queue = [];


インスタンス自身のプロパティなので、ほかのインスタンスのqueueを変更しても、関係ない。


そんな感じ。


まとめ




  • Webkitのconsole.logはオブジェクトが表示されるまでにディレイがあって、その途中でオブジェクトの中身を変更すると、変更後の内容が出力される

  • CoffeeScriptのクラスの仕組みについて知るためにはJavaScriptのプロトタイプチェーン等に関する知識が必要。


JavaScriptについて勉強するにはパーフェクトJavaScriptがお勧めです。



パーフェクトJavaScript (PERFECT SERIES 4)

パーフェクトJavaScript (PERFECT SERIES 4)










2011年12月7日水曜日

EmacsからnodeやブラウザでCoffeeScriptを動かす



前に書いたJavaScriptの開発環境を整えるついでにCoffeeScriptの環境が整います。


EmacsでJavaScriptの環境を整えたい - はなちん C-x C-c


swank-jsの導入


ivan4thさんのswank-jsを使うとEmacsからNodeやブラウザにつないでJavaScriptを実行できます。


JavaScriptならChromeの開発者ツールやFirebugでも出来ますが、やはりEmacs上で出来ると幸せです。(そのまま保存出来るし)


僕はswank-jsにCoffeeScript用の機能をいくつか付け加えました。


GitHubに置いてあるので、そこから導入します。


hanachin/swank-js ? GitHub


swank-js導入手順


ほとんど深町さんのこの記事と一緒です。


Emacsからnode.jsやChromeとSocket通信 - 八発白中


違うところだけ、説明します。


0.swank-jsのダウンロード

CoffeeScript用に改造してある僕のリポジトリから落とします。



% git clone git@github.com:hanachin/swank-js.git


1.nodeをインストールします

自分はここを参考にしました。


no title


3.SLIMEをインストール

僕の環境だと最新のSLIMEだとswank-jsがうまく動かなかったので、LispBox同梱の物を使いました。


Lispbox


中に入っているslimeのフォルダを、Emacsのロードパスの通っている場所へ置きます。


自分の場合だと~/.emacs.d/elisp/あたりに入れてます。


5.emacsに設定を追記

もとの記事のjs2-mode-hookに加えて、coffee-mode-hookの設定を.emacsに追記します。



(add-hook 'coffee-mode-hook
(lambda ()
(slime-js-minor-mode 1)))


EmacsからCoffeeScriptを使う


swank-jsのディレクトリで以下のコマンドを実行し、swank-jsのサーバーを立てます。



% node swank


EmacsでM-x slime-connect、接続。(ここでslimeとswank-jsのバージョンが違う等のメッセージが出るが気にしない)


ここまではJavaScriptと同じです。


slime-repl JSのバッファーで,select-remoteと入力して、CoffeeScript/directを選びます。


あとはJavaScriptと同じ感覚でCoffeeScriptを入力して実行出来ます。とっても簡単ですね。


EmacsからブラウザのREPLにアクセスしCoffeeScriptを使う


次のブックマークレットを、CoffeeScript使ってattachしたいページで実行します。


Attach Swank Coffee


後はslime-reple JSの画面で,select-remoteでCoffeeScript Browserと書いてるやつを選べばおk


f:id:h6n:20111208014158p:image


このように、Emacsで書いたCoffeeScriptをブラウザで実行できます。


また、coffee-modeで範囲を選択して、C-c C-rで実行することもできます。


まとめ




  • 最初はslime-js.elの方をいじって、elisp側でCoffeeScript->JavaScriptの変換かけようとしていたが面倒だった

  • swank-handlerのRemoteを継承するクラスを作ってevaluateメソッドをオーバーライドし、そこで実行前に変換をかければよい

  • そのクラスをswank.jsの中で使うようにする

  • 別のaltJS、JavaScriptにコンパイルされる言語(Cocoなど)をEmacsから叩きたいときも同じ感じでいけるかも。


という感じ。


CoffeeScriptの問題として、コンパイル後のJavaScriptコードを実行中にエラーがおき、エラー行が表示されても、元々のCoffeeScriptの何行目に対応するのか分からないといったところがあります。


これについてはこちらのスレッドで意見がかわされてるようです。


Issue #558: line number mapping for debug ? jashkenas/coffee-script ? GitHub


まぁ僕はとりあえずCoffeeScriptをEmacsから実行できる環境が整ったので満足です。


Emacs使いでCoffeeScript使いで興味を持ってくださった方は是非試されてみてください。


フィードバックは@まで。





EmacsでCoffeeScriptの環境を整えたい



flymakeでエラーを表示したい


いちいちコンパイルしてエラーが出てるか確認するのは面倒。

ここを参考にflymakeの設定をする。

coffeescriptでflymakeする - antipop

EmacsからCoffeeScriptを評価して、結果が見たい


regionを選択してえばるとChrome Developer Toolsに表示するところまで出来ました。

追記

こちらの方でより良い方法を解説しています。

EmacsからnodeやブラウザでCoffeeScriptを動かす - はなちん C-x C-c

1.まずはここを参考にJavaScriptの開発環境を整えます。

EmacsでJavaScriptの環境を整えたい - はなちん C-x C-c

2.CoffeeScriptをえばるためのslime-coffee.elを導入する

ロードパスの通った所に置いてください。

eval region, coffee-script — Gist

後は、JavaScriptと同じようにnode swankでswankサーバーを立ち上げ、ブラウザにブックマークレット使ってattachして、範囲を選んでC-c C-rで、えばれます。

デモ動画




next


もっといい方法を思いついたのでこれから実装




2011年12月6日火曜日

僕のブックマークの可視化



僕のはてなブックマークの、1月頃から10月の末あたりまでの、タグ付けの様子を可視化してみました。



タグごとに円で表示されています。


いっぱいブックマークされたタグは大きめに表示されます。


時間がたつにつれて円がだんだん小さくなります。





2011年12月5日月曜日

EmacsでJavaScriptの環境を整えたい



とりあえずここを参考にEmacsからChromeやNodeを叩けるようになりました。


Emacsからnode.jsやChromeとSocket通信 - 八発白中


ひっかかった点


swank-jsは更新されてるようで、本家のものを使うことでいけた。


僕の環境だと問題になったのはSLIME.


最新のSLIMEを使うと、slime-connectした際にcoding-systemが云々とエラーメッセージが出てうまく動かなかった。


昔のやつを落としてきて、うまく動いた。


js2-mode


js2-mode - 紫藤のWiki


ここを参考にしながら、Google Codeから最新版を落としてきて



% cp ~/Downloads/js2-20090723b.el ~/.emacs.d/elisp/js2.el
% emacs -batch -f batch-byte-compile ~/.emacs.d/elisp/js2.el

して、init.elに



(autoload 'js2-mode "js2" nil t)
(add-to-list 'auto-mode-alist '("\\.js$" . js2-mode))

を書き加えていけた。(~/.emacs.d/elisp/にパスを通してないとだめ)





2011年12月1日木曜日

CoffeeScriptでHQ9F+のインタプリタ書いた。



Esoteric Language - ネットワーク?なにそれおいしいの?


を見て書こうとおもったので、書いた!



インスタンス変数のデフォルト引数でハマりそうなところ



out = (x) -> console.log x
class Foo
constructor: (@out = out) ->


このようなCoffeeScriptは



var Foo, out;

out = function(x) {
return console.log(x);
};

Foo = (function() {

function Foo(out) {
this.out = out != null ? out : out;
}

return Foo;

})();


このようにコンパイルされる。


デフォルト引数の値に、インスタンス変数と同じ名前の変数を渡すと、インスタンス変数の方で隠されてしまうので注意。





週末ものづくり講座で作ったもの学んだこと



10月・11月と、@さんの週末ものづくり講座を受講していました。


「早く実装し、早く評価し、早く学ぶ」、元々はLean Startup用の「早く失敗し早く学習する」を応用したものです。


このエントリはその最終課題です。


授業を終えて


僕は「僕でもイイモノつくれる」という自信がつきました。


授業終わってからも、もっと何かつくって勉強会で発表していきたいと思っています。


まずは僕がこの2ヶ月の授業でやってきたことをまとめます。


技術的なことはブログに書いてあるので参考リンクからどうぞ。




作ったものは8つ、未公開1つ、発表1回、脆弱性の届出6件です。


失敗や成功から得た知見はそれぞれのエントリにまとめてあります。


一番変わったのは多分メンタル。


授業を受けてから、勉強会ROM専門が勉強会で発表するように、作品が無かったのが8つも物が作れました。


自分でもびっくり。


「ものが作れる」という自信も出来たし、後は継続的にものをつくって、GitHubで公開して、ブログに書いて、勉強会に貢献しながら、もっといいものを作りたいと思っています。