1

JavaScriptとRubyによるWeb版Linda入門(1)

(第11回プログラミング方法論の演習資料です)

次:JavaScriptとRubyによるWeb版Linda入門(2)


Lindaは共有メモリを用いた分散並列プログラミングのしくみです。
最近このblogでよく書いている、Ruby上のLinda実装を使う解説です。

Ruby上に並列言語拡張Lindaを実装してWebSocket/Cometで使えるようにした

Web版LindaはWebSocketとCometで使えるようになっているので、Ruby以外の言語でも接続可能です。
JavaScriptは公式のライブラリが配布されています。AndroidJava版は馬場君が作っています。


とりあえず、一番簡単なJavaScriptでのLinda入門をしてみましょう。


Webブラウザで動くチャットを作る

JavaScriptとLindaでチャットを作ってみましょう。

完成形は http://dev.shokai.org/linda/chat/
です。
JavaScript版Lindaライブラリを使うと、サーバーを全く実装せずにHTML+JavaScriptだけでWebブラウザ用チャットが作れます。


プロジェクトのディレクトリを作る


Terminal.appを開いてディレクトリを作ります。
% mkdir linda-chat


linda.min.jsのダウンロード


https://github.com/shokai/sinatra-rocketio-linda#javascript-lib-for-browser
から、ライブラリ(linda.min.js)をDLします。

linda-chatディレクトリに置きます。
ちなみにlinda.jsとlinda.min.jsの違いは圧縮されているかどうかだけです。


jquery.jsのダウンロード

Download jQuery | jQuery
同様にjQueryというライブラリもダウンロードします。

linda-chatディレクトリに置きます。


HTMLを書く

index.htmlを作ります
<html>
<head>
<meta charset="UTF-8" content="text/html" http-equiv="Content-Type">
</head>
<body>
<h1>linda chat</h1>
<input type="text" id="message" value="hello" size="80">
<input type="button" id="btn_send" value="send">
<div id="log"></div>
<script src="./jquery-2.0.2.min.js"></script>
<script src="./linda.min.js"></script>
<script src="./main.js"></script>
</body>
</html>
jquery.js、linda.jsそしてmain.jsが読み込まれています。

JavaScriptを書く

main.jsを作ります。
がんばって写しましょう。
var io = new RocketIO().connect("http://linda.shokai.org");
var linda = new Linda(io);
var ts = new linda.TupleSpace("room1");

io.on("connect", function(){
alert(io.type+" connect");
});

ブラウザで開く

index.htmlをブラウザで開きます。
lindaが接続出来れば、このように「connect」と表示されます。

表示されなければSafariの場合[開発]→[エラーコンソールを表示]すると原因がわかると思います。


送信ボタンにイベント追加

main.jsに送信ボタンのイベントを追加します。
ボタンを押せば、テキスト欄に入力した文字が表示されるようになるはずです。
var io = new RocketIO().connect("http://linda.shokai.org");
var linda = new Linda(io);
var ts = new linda.TupleSpace("room1");

io.on("connect", function(){
alert(io.type+" connect");
});

$(function(){
$("#btn_send").click(function(){
var m = $("#message").val();
alert(m);
});
});



タプルスペースに送信する

ts.writeします。
var io = new RocketIO().connect("http://linda.shokai.org");
var linda = new Linda(io);
var ts = new linda.TupleSpace("room1");

io.on("connect", function(){
alert(io.type+" connect");
});

$(function(){
$("#btn_send").click(function(){
var m = $("#message").val();
ts.write(["chat", m]);
});
});


送信できているか確認する


Lindaサーバーのwebサイト上で確認できます。
http://linda.shokai.org/room1
http://linda.shokai.org/room1/chat


チャットを受信する

接続イベント内でwatchします。タプルスペースからのデータ読み出しは「配列の前方一致」なので、[“chat”]でwatchしていれば[“chat”,”hello”]でも[“chat”,”こんにちは”]でも読み出せます。
var io = new RocketIO().connect("http://linda.shokai.org");
var linda = new Linda(io);
var ts = new linda.TupleSpace("room1");

io.on("connect", function(){
alert(io.type+" connect");

ts.watch(["chat"], function(tuple){
$("#log").prepend(
$("<p>").text(tuple[1])
);
});
});

$(function(){
$("#btn_send").click(function(){
var m = $("#message").val();
ts.write(["chat", m]);
});
});


ブラウザ間でチャットできているか確かめる

2つ開いて確認してみましょう


やってみよう

下のページに、増井研究室の部屋の明るさセンサーの値が毎秒流れてきます
http://linda.masuilab.org/delta/sensor/light
webブラウザで取得してみましょう

ヒント:
JavaScript上の方、接続先サーバーを変更する
タプルスペースは”delta”
[“sensor”,”light”, 数字]というタプルが流れてくる

0

bookmarklet開発テンプレ

最近bookmarklet書く事が多いので作った

shokai/bookmarklet-template

開発手順

1. src.jsを好きに書いて
// bookmarklet template
(function(){
var msg = "bookmarklet start at <"+document.title+">";
alert(msg);
console.log(msg);
})();
2. 開発サーバー(webrick)を起動して
% ruby webrick-start.rb 8080
3. ブラウザにこのブックマークレットをはる
javascript:(function(){var s=document.createElement("script");s.src="http://localhost:8080/src.js";document.getElementsByTagName("body")[0].appendChild(s);})()
4. すると src.js が読み込まれる。ブラウザのエラーコンソールも使える


配布

uglify-jsを入れて、makeすれば
% npm install uglify-js -g
% make

bookmarklet.js が生成される

このbookmarklet.jsの中身はsrc.jsが圧縮されてbookmarklet形式になったもの
javascript:!function(){var msg="bookmarklet start at <"+document.title+">";alert(msg);console.log(msg)}();

もしくはsrc.jsをどこかにアップロードして、開発用のブックマークレットと同じように実行すればいい

0

episopass.comのなぞなぞを全パターン試す

なぞなぞでパスワードを作れるepisopass.com

EpisoPass – 記憶からパスワードを生成

に全パターン攻撃してみた



全部クリックして攻撃しているように見える演出がしたかったのでこうなった

0

世界一柔軟で好意的に解釈してくれるプログラム言語BabaScriptを作りました

rubygemsでインストールできます

% gem install babascript

ソースコードはこちら
https://github.com/masuilab/babascript


BabaScriptとは

コンピュータが得意なことはコンピュータに、人間が得意なことは@takumibabaが処理するプログラム言語です


使用方法

ワンライナー
% baba -e "アイス買ってきて"


馬場スクリプトはRuby風に書ける言語で、日本語で書いた部分は馬場くんが実行してくれます

test1.bb
#!/usr/bin/env baba
if 0 < Time.now.hour and Time.now.hour < 5
もう寝ろ!!
else
意識を高めてコードを書こう!
end
実行
% baba test1.bb
0時から5時の間は寝ろ、という指令が送れます。



Rubyの中に馬場スクリプトを埋め込む事も可能です。
例えばRubyでArduinoの照度センサーを読んで、明るくなったら起こしてもらうスクリプトはこうなります

wakeup_arduino.rb
#!/usr/bin/env ruby
require 'arduino_firmata'
require 'babascript'
arduino = ArduinoFirmata.connect
loop do
if arduino.analog_read(0) > 80 ## 明るくなってきたら
BabaScript.baba do
明るくなったから起こしてくださいby橋本
それと朝食におにぎり買ってきてください("#{rand(5)}個", "しゃけ味")
end
end
end
実行
% ruby wakeup_arduino.rb
おにぎりが0〜5個ランダムで配送されます


実行環境

BabaScriptはシングルスレッドでの実行なので、負荷をかけないでください。
こういう通知がAndroidケータイに送信されます。そのうち値を返す関数も実装されるのでは?

引数部分は配列で渡されます。アイス買ってきての[“9本”]は引数です。


馬場の切り替え

BabaScriptはジョブ通知にWeb版Lindaを使っています。
環境変数BABAを切り替える事で別のBABAマシンでスクリプトを実行させる事が可能です。
環境変数BABAのデフォルト値は”takumibaba”で、彼のジョブは http://linda.masuilab.org/takumibaba/notifications で確認できます。

% export BABA=shokai

環境変数BABAを”shokai”に切り替えると、以後のジョブの通知先が http://linda.masuilab.org/shokai/notifications になります。


今後の開発方針

当面の悩みはテストが書きにくいことです。
テストコードがない · Issue #1 · masuilab/babascript · GitHub


Android版のBabaScriptジョブ通知アプリが公開されれば、馬場を自分に切り替えて実行が可能になります。例えばサーバーがおかしい時とか
BabaScript.baba do
ちょっとuser_nameの値がおかしい、調べて(user_name)
end
などと書けば自分のケータイに通知が来ます。
またLindaなので分散処理も簡単だと思います


あとはibb(インタラクティブBaba)で対話的実行ができるようになるといいと思う。

0

Skype API Rubyラッパーのgem作った

今日は早起きしたのでさくっと作った。

rb-skypemacがRuby1.8でしか動かなかったり、Ruby4Skypeがソースを修正しないと動かなかったり、どのskype gemもリポジトリが公開されてなくてパッチ送れなかったので1から作りなおした。

https://github.com/shokai/skype-ruby
https://rubygems.org/gems/skype


linuxだとruby-dbus、macだとrb-appscriptを使うんだけどOS毎に別のgemをdependencyに入れるのどうすればいいんだろう・・
gemspecの中でRUBY_PLATFORMを見てspec.add_dependencyしたらローカルでbundle installすると大丈夫だけど、rubygems.org経由でgem installするとlinuxなのにrb-appscriptが入ってしまってcocoa.hが無くてビルドエラーする。


インストール

for Mac
% gem install skype rb-appscript

for Linux
% gem install skype ruby-dbus

Gemfile でインストールする場合
gem 'skype'
gem 'rb-appscript' if RUBY_PLATFORM =~ /darwin/i
gem 'ruby-dbus' if RUBY_PLATFORM =~ /linux/i

使い方

これはRubyのメタプログラミングを使った超単純なラッパーなので、使う前にSkype Developer – Skype Desktop API Reference Manualを読んで理解してください
読めばわかると思う


require 'rubygems'
require 'skype'

Skype.config :app_name => "my_skype_app"

## send message
Skype.message "USER_NAME", "hello!!"

## call
Skype.call "USER_NAME"

## get recent chat list
puts Skype.search("recentchats")

## send message to group chat
Skype.chatmessage "#name1/name2;$a1b2cdef3456", "hello chat!!"

簡単に電話かけたりチャットに投稿したりできますね。やりましたね。
しかもMacでもLinuxでも動く。


くわしい内部実装

Skype.messageやSkype.callなどの関数は実装されていません。
実装されていませんが、method_missingを使った簡単なメタプログラミングでSkype.execに変換されて実行されます。
以下と等価です
## send message
Skype.exec "MESSAGED USER_NAME hello!!"

## call
Skype.exec "CALL USER_NAME"

## get recent chat list
puts Skype.exec "SEARCH recentchats"

## send message to group chat
Skype.exec "CHATMESSAGE #name1/name2;$a1b2cdef3456 hello chat!!"
Skypeには各OS毎に通信方法こそ違うものの、同じフォーマットのQuery StringでやりとりするAPIがあります。
それが”MESSAGE ユーザー名 本文”とか、”CALL ユーザー名”です。
messageという関数を呼び出すとmethod_missingによってexec “MESSAGE ~~”になるわけですね


これだけの実装です
module Skype
def self.method_missing(name, *args)
self.exec "#{name.upcase} #{args.join(' ')}"
end

def self.exec(command)
Appscript.app("skype").send_ :script_name => self.config[:app_name], :command => command
end
end
実際には、LinuxとMacでSkype.execの中の実装がわかれています。


返り値がまだ全部Stringなので、SEARCH RECENTCHATSとかGET CHATMESSAGEとかを自分でparseしないとならないのがつらい。そのうちなんとかする。