Dr.HOUSEの透明のホワイトボードが欲しい

written by shn, on Feb 7, 2010 12:15:00 AM.

ハルヒ見に行こうと思ったら満席で予約取れなかった。 そこで、私のもう一つの願望である、Dr.HOUSEの透明のホワイトボードを手に入れるべくグーグルとの対話を始めたのであった。

同じ事考えている人発見 → 知的なホワイトボード?? 関係ないけどlive.comのblogのURLは酷いな。愛がなさ過ぎる。

言及されているYahooの質問回答にあるメーカーだと、20〜30万程するようだ。

見たこと無いのだけどCSIでも透明なボードが出てくるそうで似たような質問があった、それによると、ガラス黒板チェインジングボードという名前で似たような物があるけどちょっと違う。イーゼルタイプの物が欲しいのだ。

ライト黒板製作所の透明黒板はかなり近い。もっと透明であるとうれしいんだけど、お値段もいいかんじ。

アクリル、ガラスの板を買ってきて自分で作ればいいのかもしれない。この質問によると、アクリルだと使っていくと傷がついて字が消えなくなっていくので、ホワイトボード用の透明シートを貼るのが良いのではないかとのこと。 透明シートはここらへんだろうか。ダイナカルモウカル

ううむ。東急ハンズ行けば教えてくれるような気もしてきた。

eventlet kqueue hub

written by shn, on Jan 29, 2010 2:14:00 PM.

先日のAppleのイベント用にこんなのを作って、動かしたりしてたいました。

中身はテキトーに書いたeventletベースCometサーバをFreeBSDで動かしてるのですが、eventletはkqueueのhubが無いのでちょっと負荷が心配になった。ので、kqueueのhubをでっち上げた。例によってテストは無いけど、一晩動いてたのでこの方向でいいのかしら。

http://gist.github.com/287764

kqueueバージンだったので、誰か優しく手ほどきしてください。

2012

written by shn, on Jan 18, 2010 4:47:00 PM.

嫁の人がタダ券をもらったので、いまさら2012を見てきました。

3分に一回つっこみどころ(ニュートリノが核粒子?に変化する!、とか)がある面白い映画でした。 嫁の人が本編前の予告編だと思って「うわぁ ひでぇなこの映画」とか言ってたら、本編だったという感じです。

ネタバレなんですが、僕が一番気に入ったつっこみどころは、方舟のチケットに一席10億ドル(ユーロです、といいつつドルだったりする。相手によって値段が違う)といいつつ、後半ででてきた「船の建設費用は数10億ドル…」というセリフ。世界が終わるっていうのにぼろ儲けしてる奴がいるよ!と楽しかったです。

AVATARもそうなんですが、ハッピーエンドっぽいラストなんですけど、あの後本当の地獄が始まると思います。

eventletでCometサーバ

written by shn, on Jan 17, 2010 6:05:00 PM.

eventletづいてるので、Cometサーバを書いてみたよ。

tinycomet.py at master from shnjp's tinycomet - GitHub

eventlet.wsgiを使って、200行ぐらいで簡単なのが書けました。楽しいですね。

使い方

python tinycomet.pyで起動して、 /update/<UUID>にPOSTするとデータを作成

% curl -v 'http://127.0.0.1:8090/update/hogehoge' -d mogemoge
...
< HTTP/1.1 201 Created
< X-Tc-Timestamp: 2
< Content-Length: 0
...

受け取るには、/wait/<UUID>

% curl -v 'http://127.0.0.1:8090/wait/hogehoge'
...
< HTTP/1.1 200 OK
< Content-Type: application/octet-stream
< X-Tc-Timestamp: 4
< Content-Length: 7
...
mogemoge

waitにsince=<timestamp>をつけると、その時間になるまで待ちます。 各レスポンスのヘッダにあるX-TC-Timestampが、そのデータの最終更新時刻になります。 timestampは論理時間なので、実世界の時刻とは関係ありません

% curl 'http://127.0.0.1:8090/wait/hogehoge?since=4' &
[1] 97027
# waitに入る
% curl -v 'http://127.0.0.1:8090/update/hogeoge' -d fugafuga
fugafuga[1] + done ....

ほかに、waitにtimeout=[timeout:float]を与えると、timeout秒待って408 Request Timeoutを返します。

また、updateにfinished=1を与えると、次のwaitが終わった後にデータを消します。またcontent_type=[mimetype]でContent-Typeを指定できます。デフォルトはapplication/octet-stream

いろいろ引っかかったところ

event(pyevent)はだめくさい

eventletのdefault hubからthread safeじゃないという理由でpyeventが外されていたのだけど、今回はsingle threadなので試してみた。 しかしうまくimport出来ないので諦め。trunkも、配布バージョン(2007年!!)もだめじゃった。

python2.6からkqueueが使えるそうなので、自分でHubを書くのがよいのかな。eventlet自体もtrunkは結構変わっているので見ないといけなさげ

WaitForMultipleObjectsがやりたい

waitのところは、グローバルなConditionを作って

# wait側
with _update_lock:
    while data.last_update <= since:
        _update_lock.wait(timeout)

# update側
with _update_lock:
    _update_lock.notify_all()

とやっているので、捌くdataの数が増えると破綻すると思う。dataごとにイベントを持たせて、WaitForMultipleObjects()的なことがしたいのだけど、この枠組みではどうやるんだろう。オシエテエライヒト

/wait_multiはmultipart/*を吐くコードを書くのが面倒なので実装していない。

eventletでgearman worker

written by shn, on Jan 16, 2010 8:45:00 PM.

eventletっていうライブラリが僕好みの匂いを発していたので遊んでいる。 gearmanを使って、ブログのURLを与えたらそこのFeedのリストを返すってWorkerを書いていたので、それをeventlet化してみよう。

まず、gearmanのeventlet化、gearmanのライブラリにはpure-pythonのやつを使っていたのでさくっと行けた。

green_gearman.py

from eventlet import patcher
from eventlet.green import socket, select

for mod in ['worker', 'connection']:
    patcher.inject('gearman.%s' % mod, globals(),
        ('socket', socket),
        ('select', select)
    )
del patcher

eventletにはpatcherというざっくりしたモジュールがあって、これを使うと指定したモジュールのglobalsを置き換えてくれる。これでいいんかなっていうぐらい簡単。

試しにecho serverを書いてみる。

from eventlet import coros, api
from green_gearman import GearmanWorker

def echo_func(job):
    print api.getcurrent(), job.arg
    time.sleep(5.)

def main():
    pool = coros.CoroutinePool(max_size=200)
    waiters = []

    for idx in range(10):    
        worker = GearmanWorker(['0.0.0.0:4730'])
        worker.register_function('echo', echo_func)

        waiters.append(pool.execute(worker.work))

    for w in waiters:
        w.wait()
main()

gearmanのprotocolは同時に1ジョブしか処理できないっぽいので、とりあえず10個ぐらい突っ込んでみる。 gearman -h localhost -p 4730 -s -f echo hogehogeを20個ぐらい飛ばしてみた所、

<greenlet.greenlet object at 0x804137f30> hogehoge
<greenlet.greenlet object at 0x804127c90> hogehoge
<greenlet.greenlet object at 0x804137db0> hogehoge
<greenlet.greenlet object at 0x804137e10> hogehoge

ってなってるので、なんかまぁそれっぽくなってる気がする。こんなコードじゃよくわからんな… これで良いのでしょうか。

さて肝心のWorkerもこれにのせたいのだが、urllib2を使っていたので、代わりにfrom eventlet.green import urllib2に代えるだけっぽい(まだやってない…)。

んでつらつらコード見てたんだが、今のところ(eventlet 0.9.2)はlibeventサポートがdisabledされているようで、ちょっとがっかり。

eventlet化する場合、全てのIOをこれにしないとブロックが発生してみんな止まることになっちゃうのだけど、MySQL周りとかをeventlet化するのはめんどくさそうなのでアレでアレしてアレですね。

岡嶋さんの問題を解いたけど、採用されなさそう

written by shn, on Jan 12, 2010 1:13:00 AM.

去年の暮れにほってんとりになってた採用問題が公開されたのでやってみた。

というのも、当初問題文を読み違えていて(格子マップじゃなくて、連続的なマップだと思ってた)、「各経路点を取って最短経路問題ですかねぇ」とか「僕だったら、答えをASCIIにプロットするのに25分かかるなぁ」とか頓珍漢な事を言っていたのが恥ずかしかったからです。 問題文を読んでないので応募以前の問題ですね。ここらへんを参照

んで、最適解法を知った上でコード書いたのに40分かかりました…

さて、僕自身も経営者の端っこなので、いろいろ思う点がありました。

まず、こういうアルゴリズム系の問題を出すことでGoogleの使い方を知らない奴を簡単に落とせるのがわかったのは参考になりました。 というのも、問題解決について求められるのはその時点での知識ではなく、最終的に許される時間の中で解決できるかという点だからです。 また、実務をこなす上でのほとんどの細かい問題に関しては、それまで世界の誰もそんな問題に直面したことが無い!なんて事は殆どないはずなので、そういうった問題を確実に解けるのか?というのは重要なポイントだと思います。

また、話には聞いていましたが、それぐらいの人材が我々のような(勝手に一緒にしちゃいましたが)零細IT企業にふらっと応募することは少ないのだなというのも参考になります。そういう点で、公募する場合には根気よく採用を続ける必要がありそうなので、あんまり応募者をディスると今後の応募に影響してしまいそうな点は気になります。

このエントリに応えると、小さな企業が人を取った場合、新人の戦力が30で今の戦力と足して130だ!、というよりも、新人がしちめんどくせーことやってくれるお陰で俺らが強まって足して150だ!みたいな気概でいるのがいいんじゃないのかなーと思います。

イメージとしてはこんな感じ

以下がコード。Pythonです。:

#!/usr/bin/env python
# -*- coding:utf-8 -*-

import sys

CELLMAX = 9999

def main(input):
    m, start, goal = load_map(input)
    solve(m, start, goal)

    print_result(m, goal)

def load_map(input):
    start, goal = [], None

    d = {
        '*': -1,
        ' ': CELLMAX,
        'S': 0
    }
    m = []
    for l in input:
        m.append([d.get(ch, ch) for ch in l.rstrip()])

    for y in range(len(m)):
        for x in range(len(m[y])):
            if m[y][x] == 0:
                start.append((x, y))
            elif m[y][x] == 'G':
                goal = (x, y)

    return m, start, goal

def solve(m, start, goal):
    cur = 0
    while start:
        next = []

        for c in start:
            m[c[1]][c[0]] = cur

            for d in [(-1, 0), (0, -1), ( 1,  0), ( 0, 1)]:
                if m[c[1]+d[1]][c[0]+d[0]] > cur:
                   next.append((c[0]+d[0], c[1]+d[1]))
        start = next
        cur += 1
        if goal in start:
            m[goal[1]][goal[0]] = cur # syoboi
            return

    if goal not in start:
        raise RuntimeError, u'とけないよ'

def fill(m, c, x):
    filled = []
    for d in [(-1, 0), (0, -1), ( 1,  0), ( 0, 1)]:
        if m[c[1]+d[1]][c[0]+d[0]] > x:
           m[c[1]+d[1]][c[0]+d[0]] = x
           filled.append((c[0]+d[0], c[1]+d[1]))
    return filled

def print_result(m, goal):
    c = goal
    while True:
        check = m[c[1]][c[0]] - 1
        if check == -1:
            break

        m[c[1]][c[0]] = '$'
        for d in [(-1, 0), (0, -1), ( 1,  0), ( 0, 1)]:
            if m[c[1]+d[1]][c[0]+d[0]] == check:
               c = (c[0]+d[0], c[1]+d[1])
               break
        else:
            raise RuntimeError
    m[goal[1]][goal[0]] = 'G' # syoboi
    d = {
       -1: '*',
        0: 'S',
       '$': '$',
       'G': 'G',
    }
    for l in m:
       print ''.join(d.get(ch, ' ') for ch in l)    

if __name__=='__main__':
    main(sys.stdin)

「最短性のチェック」というのは、(コードの外で)アルゴリズムの証明をせよ、という意味だろうか?基本的にダイクストラ法を格子マップでやっているので、最短性はダイクストラ法の証明となると思うのだけど。

って岡嶋さんてスウィフトの関係者なのか!

あとはっちゅう君バジョナップ期待しています!

EC2 US-Westを試す

written by shn, on Jan 3, 2010 12:38:00 AM.

弊社サービスを引っ越ししたりせなあかんなーと思いつつ、US-West初め。 いくつかはまった。

S3 Bucket ExplorerがUS-Westに対応していない。

AMI作るときにはまった。 FirefoxのAddonのアレがUS-Westに対応しておらず、うっかりBucketを作るとUS-Eastに行っちゃう。 コマンドラインから頑張るのが面倒だったので、Bucket Explorerとかいうのを使って作成。

--region us-westを付ける。

API-Toolの引数にus-westを付ける。付けないとeastにデフォルトで行くのかなこれ。 export EC2_URL=https://us-west-1.ec2.amazonaws.comにするとデフォでwest見に行くのかな。試してはいない。

UQ WiMAX契約したよ

written by shn, on Dec 17, 2009 1:18:00 AM.

UQ WiMAXの一日プランに契約した。端末はUD03NA

会社
麻布十番の位置の橋交差点の道路沿い。つながる。電波強度は小〜中
居間も窓際も圏外。場所は港区の有栖川公園から一本入ったところ。
原宿の某社(地上19階)
窓際行くとつながった。電波微弱。でもtwitter/メールには十分な速度
汐留のWINSの麓(イタリア街?)
電波中
その近くの某社
電波弱. 下り0.7Mbps

聞いていた通り、電波弱い。弱くても満足行く通信速度が出るのが救いか

香港・深圳・澳門の旅4日間

written by shn, on Nov 26, 2009 3:48:00 AM.

ホーテンス・S・エンドウ氏にお連れ願い、電脳空間カウボーイズと共に香港・深圳・澳門に食い倒れ、変携帯探しの旅に行って参りました。

写真はこちら

各人の旅行記は以下のあたり

遠藤諭の東京カレー日記:

シン石丸の電脳芸事ニッキ:

Keep Crazy;shi3zの日記:

ガイドをしてくださった山根さんのサイト "山根康宏オフィシャルサイト - 香港携帯情報局" 山根さんありがとうございました! 至高の変ケータイを手に入れた山根さんの嬉しそうな顔が忘れられません。

香港の携帯文化、深圳の圧倒的なエネルギーに関しては皆さんがお書きになっているのでそれ以外の話でも書こうと思います。

金とかの話

2009-11-21 12-22-22

とにかく軍資金が無いとはじまりません。日本で両替しちゃうと札束を持って行くことになり、ちょっとそれは僕にはデンジャラスなので他の方法を探してみました。また今回のは買い出し旅行なのでレートも重要です。

レートから言うと一般的に、日本で両替 > 現地空港で両替 >> 現地市中で両替≒クレジットカードのキャッシング、といわれています。 今回の旅の場合、1HKDあたり市場のレートが11.4に対し、成田空港 13.9 JPY、現地空港 12.5 JPY 街中 11.53 JPYでした。なので成田空港のボッタクリ具合がよくわかると思います。

キャッシングの場合は他と違い、「決済時点での市場のレート」+「引き落としまでの金利」になります。今回の場合、ずっと円高が進行していたので、11.636 - 11.251で決裁されていました。キャッシングの場合はドルコスト平均法的に、日々の為替変動に対してトータルで損しない。という事も言えると思います。金利に関しては引き落としまでが一カ月未満な事を考えると両替手数料と大した差は出ません。

以上の事を考えると、現金を持ち歩かなくて良いという利点もありキャッシングが一番良いという事になります。ATMはそこらじゅう(例えば駅とか)にある上だいたい24時間営業なので、夜中でも現金が手に入る利点があります。

2009-11-21 12-03-49

ただ、今回の場合は両替・インド人・安宿で有名な重慶大厦に行きたかったので、現地で2万円を両替しました。重慶大厦の1,2Fにはインド人経営の両替商がたくさん詰まっており、店によって微妙にレートが違います。入口近くのお店が一番レートが高く、2Fをちょっと行ったところにあるお店が一番良かったです(上の写真のお店)

クレジットカードメインの旅行にする場合、

  • 限度額をあげておく。

現地からでも電話であげられます

  • キャッシング枠があるか確認しておく。

今回はメインのカードに枠を設定してなくて焦りました。日本では借金は禁忌されるので枠を設定していない人も多いと思います。

  • 決済口座の違う、MasterとVISAの2枚を持っておく。

海外ではクレジットカードを、ホテルのチェックイン、自転車のレンタルなどにおいてデポジットに使われる事があります。デポジットとは例えばレンタルするときにあらかじめ引き落としておいて、返却されたときにそのトランザクションをキャンセルすることで、客がバックれても大丈夫なようにすることです。 というわけで善良に生きてるなら特に問題ないのですが、昔、アメリカ旅行をしたときにロードバイクを借りたら1000ドル程デポジットされ、限度額を突破しそのあと面倒な事になったことがあります…

今回の旅では、深圳に行ったのですが、中国ではクレジットカードはあまり使えないようです。次に行く時は銀嶺カードを用意すべきかもしれんと思いました。

あと先達広場ではクレカだと5%ぐらいの手数料を要求されました。

言語とかの話

2009-11-21 10-27-19

香港は広東語、深圳は普通語(北京語)らしいのですが、どっちも等しく何言ってるかわからない。数字ぐらいしかわかりません(麻雀のおかげだ!) 広東語の方が発音が難しいそうです。

英語(根性英語)は香港では通じました。深圳・澳門はさっぱり。 深圳はカウボーイズが携帯を買う事に決めたから「ok! ok!」と言ってるのに、okが通じず延々と営業されて困った、なんて話もありました。

香港でちょっと困ったのは、「Cityview Hotel」という所に泊ったのですが、TAXIの運ちゃんにはそれが通じませんでした。「YMCA」という通名の方を言わないとだめなようです。他のホテルも中国語名の方しかしらない事があると思うので、タクる場合は調べておく必要があるかも。

ガジェットとか

香港の地下鉄(MTR)では、PSPをやっている人をよく見かけました。ちら見したら日本語のゲームをやっていたので驚き。NDSは見ませんでした。

携帯電話だと、Nokiaの細長い端末を良く見かけました。スマートフォンだとiPhone, BlackBerryあたり。Androidは見かけず。香港の地下鉄は電波が入るので驚き。

2009-11-23 14-53-23

MTRの駅にはデジタルサイネージがありました。こういうの増えて行くんでしょうね。もっと驚いたのは深圳で、広場に 5m * 30m ぐらいの巨大なデジタルサイネージが。この国はなんでもスケールがでかい。

深圳のPCパーツショップは、インクジェットプリンタ用の詰め替えインクがボトルで売ってたりして面白かったのですが、PCパーツ自体はあまり面白いのはありませんでした。日本で売ってる物がちょっと安いぐらい。MBは半額ぐらいだったかも。ハイエンドのVGAなんかも見かけましせんでした。やたらフォトフレーム売ってましたね。SANYOのものもあったけど本物なのかしら

澳門

2009-11-23 22-14-32

カウボーイズたちは前回行ったそうなので僕一人だけいきました。感想は「場末のラスベガス」。マカオグランプリの後片付けが終わっておらず、道路がレース場だったのがちょっとおもしろかったですね。 カジノは金をシュレッダーにかけているような感じでした。

CSSツールをうpした。 - スプライト作成、ネスト、変数

written by shn, on Nov 14, 2009 4:35:00 PM.

Python Hack-a-thonに来たので、昔作ったツールのメンテをしたりしてました。 んで、githubにうpした。

githubのプロジェクトはこちら: github cssc.git

  • YAMLで段組を定義して、CSSスプライトを生成する make_sprite.py
  • IE6のためにPNGをなるたけ綺麗にGIFにする to_gif.py
  • CSSの記述に、ネストや、変数などを使えるようにするコンバータ cssc.py

で構成されてます。

make_sprite.py

YAMLの定義ファイルからCSSスプライトを生成します。 CSSスプライトっていうのは、GoogleのCSSスプライトのような奴で、複数の画像を一枚にまとめて、リクエスト回数、ファイルサイズを節約します。

CSSスプライトを使用すると、タグの代わりに<div>などの要素にbackgroundを指定することのなります。 CSSスプライトの中で画像の座標を調べるのは面倒なので、そこらへんの生成はcssc.pyを通して自動化しています。

使い方

make_sprite.py -o sprite.png -c sprite.json -b ./images/ sprite.yaml
  • -o sprite.png 出力CSSスプライト名
  • -c sprite.json 座標定義ファイル。あとでcssc.pyで使います。
  • -b ./images/ 画像のベースディレクトリ
  • sprite.yaml 画像の段組を記載したyaml

yamlの記法

段組はyamlで記述します。

冗長に書くと、以下のような感じです。

direction: vertical
images:
  - direction: horizontal
    images:
      - left-arrow.png
      - google.png
      - right-arrow.png
  - direction: horizontal
    images:
      - google-large.png
      - direction: vertical
        images:
          - down.png
          - up.png
          - close.png

基本的に directionとimagesのマップのネストで段組を表現します。directionは horizontal もしくは vertical 、imagesは画像ファイル名もしくは、マップのリストになります。

directionを省略して、直接子イメージのリストを書くことも出来ます。その場合の方向は、親の方向と逆になります。 この省略記法を利用すると、上のyamlは以下のようになります。

direction: vertical
images:
    - [left-arrow.png, google.png, right-arrow.png]
    - [google-large.png, [down.png, up.png, close.png]]

to_gif.py

pngをgifにします。

使い方は to_gif.py in.png out.gif 

cssc.py

CSS手書き派は日々、ネストができないことや、変数が使えないことに憤慨しています。

つまりこういう書き方がしたい!

{% set header_height = '24px' %}
{% set main_color = '#001122' %}

#site-header {
    height: {{ header_height }};

    h1#logo {
        font-size: 24px;
        color: {{ main_color }};
    }

    a {
        color: #aabbcc;

        _:hover {
            border: 1px solid #ffeedd;
        }
    }
}

OK! それなら、そうすればよいわ

./cssc.py -o out.css in.cssc

in.csscにみょうちきりんなcssもどきを書くと、in.cssにちゃんとしたものをはいてくれます。

上のmake_sprite.pyで、座標ファイルを出力した場合は以下のような感じで使います。

./cssc.py --coords main,http://static.com/main.png -o out.css in.css

--coordsオプションに
スプライト名:スプライトのURLを指定します。 座標はスプライト名.jsonから読み込みます。

csscファイルの方は、以下のように。冗長

h1#logo {
    {{ sprite_background('main', 'logo.png') }}
}

sprite_background関数の第1引数にスプライト名(コマンドラインで指定する奴)、第2引数に元画像ファイル名を指定します。

cssc詳細

{% set width = '100px' %} /* 変数などはJinja2そのまんまなので[Jinja2のドキュメント](http://jinja.pocoo.org/2/documentation/)を見るのが良いと思います。 */
// C++スタイルのコメントも使えます
{# jinja2スタイルも使えるぜ... #} 

div {
    /* 普通にcssのスタイル定義を書きます */
    border: 1px solid black;
    margin: 4px 8px;

    width: {{ width }}; // これはjinja2

    span {
        /* ネストすると "div span" になります。 */
        font-weight: bold;
    }

    a {
        text-decoration: none;

        _:hover {
            // 親要素とスペース無しで続け対場合は '_' を使います。
            // この場合、このブロックは "div a:hover" になります。
            text-decoration: underline;
        }
    }
}

あとがき

  • いまどきCSSを手書きしている奴はいるのだろうか
  • でもYUI compressorとか使うならMakeで処理できるようにしておきたいよね。
  • みんなここらへんの地味な所どうしてんだろう。
  • PyParsingはじめてトライしてみたんだけど遅い… たぶん文法定義が悪い