2007年07月30日
自分のリードで2人熱中症にしてしまうとさすがにヘコむ
中国から友人が仕事で東京に来ていたので、週末の昨日、東京を案内した。
有楽町から銀ブラ、築地市場あたりを歩いて浜離宮、んで水上バスに乗って浅草に向かい、浅草寺、江戸東京博物館と回ったのだが、その後新宿にでも行って食事、と思ったら、友人がおそらく熱中症と思われる症状でぶっ倒れてしまった。
慌てて救急車を呼んで、2時間ほど病院で点滴を打ってもらって大分回復したようだったが、言葉の通じない異国で不安な思いをさせてしまった。
聞けば、日本滞在期間中朝8時半?終電近くまで開発業務をしていたので、相当疲れが溜まっていたらしい。
といっても本人もあまり自覚はなかったようなのだけれど、強行軍の観光で一気に臨界値を超えてしまったみたいだ。
私が企画した観光スケジュールで付き合った人間が熱中症になったのはこれが始めてじゃない。
名古屋の愛・地球博の際にも、初日に家内が熱中症になってぶっ倒れてる。
その時も、家内は名古屋行きの前日まで、なんやかやと忙しくほとんど睡眠を取ってない日が続いており、にもかかわらず無理させてしまったため熱中症にしてしまった。
さすがに2回もこんなことがあると、自分は相手の体調を慮る能力に欠けているのかとヘコむ。
とはいえ、みんな暑い日はほんと水分とらなきゃ駄目よ。
俺は昨日、昼飯の際にレストランのウェイターがお冷やを埋めるたびにガブ飲みして、友人にも家内にも笑われたけど、お陰で俺も結構、朝は遅めだけど夜は終電近い日が続いたので疲れてたんだけど、熱中症にはならなかった。
友人はジャスミン茶のペットボトルを持っていたので、大丈夫だと思っていたら、倒れた後ボトルを見てみると一日かけて5分の1くらいしか口をつけていなかった。
またやっかいなのは、地球博の時の家内も、今回の友人も、一旦倒れた後、明らかに熱中症っぽいからとにかく水分とれ、といってもほとんど口にしない。
熱中症なめちゃ駄目だって…水分取らない限りはいくら寝ようが休もうが治らないよ。
その辺は、やっぱ自己管理して欲しいなとも思ったり。
2007年07月22日
Location::GeoToolの代わりに使えるProj.4
タイトルはオコガマシスで、本当はLocation::GeoToolの方がProj.4の代替でしかないのですが、Location::GeoToolを使っている人への呼びかけということなのでこのタイトルで。
先日、Web-APIを連発している某社のオフィスを訪ねたのですが、中の人の話によりますと、Perlで開発しているAPI内での経緯度測地系変換には拙作のLocation::GeoToolを使っていただいている、という話を伺いました。
いや、作った者として、使っていただけるのはありがたいのですが、昔昔に作ったモジュール構成を踏襲しているのでパフォーマンス的にも問題あるだろうし、また超エンタープライズな用途で変換結果に全幅の信頼を置かれてしまうのも中々辛いものがあるなと(いや、別に信頼を置かれてはマズイ問題は見つかっているわけではないのですが)、いうことで、間違いの許されない超エンタープライズな用途であるのならば、Proj.4のようなより専門的な投影変換ツールを使った方がよいのでは、という示唆をさせてもらいました。
ですが先方はProj.4をご存じなかったようなので、この記事で簡単に紹介させてもらいます。
Proj.4はオープンソースの地図投影変換ツール/ライブラリで、様々な地理的座標系間の相互変換機能を提供してくれます。
オープンソースのGISツールとして有名な、PostGISやMapServer等の投影変換部分のバックエンドとしても機能している、実績のある枯れたツール/ライブラリです。
利用法としてはコマンドラインで使うほか、Cライブラリとしても使うことができるのですが、とりあえずコマンドラインツールとしての使い方をご紹介。
インストール方法としては、Proj.4のサイトからソースをダウンロードして、
./configure
make
make install
するだけで超簡単。特に必要なライブラリ等もなく、すぐインストールできます。
以下、Location::GeoToolとの比較で、いろいろできることを列挙します。
1.世界測地系から日本測地系への変換
Location::GeoToolではこんな感じ(コマンドラインツールとの比較なので、コマンドラインでの実行で示します)。
bash-3.1# perl -MLocation::GeoTool -e ' > my $loc = Location::GeoTool->create_coord("35.00000","135.00000","wgs84","degree"); > print join("\t",$loc->datum_tokyo->array)."\n";' 34.9968036251296 135.002780769243これを行おうと思うと、Proj.4では投影法間の相互変換を行うコマンドcs2csを使って、こんな感じで行います。
bash-3.1# cs2cs +proj=latlong +ellps=WGS84 +to +proj=latlong +ellps=bessel +towgs84=-148,507,681 +no_defs -r -s -f "%.8f" <<EOF > 35.00000 135.00000 > EOF 34.99680329 135.00278102 -51.96734185大体誤差範囲内の変換結果に収まって安心しました(汗)。
上記で、青で示した部分の設定が、変換元の世界測地系を表す投影法の設定であり、「+to」以降の赤字で表した部分が変換先の日本測地系を表す投影法の設定です。
日本測地系側の「+towgs84」で設定している楕円体重心のシフトパラメータは、以前私がWeb2.0ワークショップで提示した値(-146.336,506.832,680.254)と異なっていますが、この辺はどの値が最も正しいというのははっきり言って判らないところがあるので、今回はLocation::GeoToolで採用しているシフトパラメータを用いました。
その他のオプションは、-r、-sがそれぞれ入力・出力での座標値の並び順をY,Xの順(つまり緯度、経度の順)にする設定、-fは出力のフォーマット指定です。
cs2csの出力の第3値は高度ですが、世界測地系と日本測地系は楕円体が異なる上に原点も異なるので、高度ははっきり言って議論しても仕方ありません(日本測地系では高度0だけど世界測地系だと高度-51m、とか言われても困りますよね)。
2.日本測地系から世界測地系への変換
Location::GeoToolではこんな感じ。
bash-3.1# perl -MLocation::GeoTool -e ' > my $loc = Location::GeoTool->create_coord("35.00000","135.00000","tokyo","degree"); > print join("\t",$loc->datum_wgs84->array)."\n";' 35.0031965891345 134.997218898985Proj.4ではやはりcs2csを使って、
bash-3.1# cs2cs +proj=latlong +ellps=bessel +towgs84=-148,507,681 +no_defs +to +proj=latlong +ellps=WGS84 -r -s -f "%.8f" <<EOF > 35.00000 135.00000 > EOF 35.00319625 134.99721915 51.99721753まあ、要するに1.の場合の逆、を行えばよいわけですね。
3.2点間の距離と方位角を求める
世界測地系で北緯35度、東経135度と北緯40度、東経140度間の距離と方位角を求める場合、Location::GeoToolだとこうなります。
bash-3.1# perl -MLocation::GeoTool -e ' > my $loc = Location::GeoTool->create_coord("35.00000","135.00000","wgs84","degree"); > my $dir = $loc->direction_point("40.00000","140.0000","wgs84","degree"); > print $dir->direction."\t".$dir->distance."\n";' 37.047375828035 709253.729428108で、結果は方位角37.047度(北北東)、距離709253mですね。
Proj.4では2点間の距離等の変換を行うgeodコマンドを用いて、
bash-3.1# geod +ellps=WGS84 -I -p -f "%.8f" <<EOF > 35.00000 135.00000 40.00000 140.00000 > EOF 37.04737580 220.09531204 709253.728のようにします。
入力の「+ellps」が計測するにあたって準拠する楕円体、-Iオプションは、このコマンドが本来1点と距離・方位角を与えて別の点を得るコマンドなので、その逆変換を指定するオプションです。
-pは、方位角の出力に負値を使わず、0-360度の値で出力させるオプション。
出力の第1値と第3値が、求める始点⇒終点方向の方位角、及び距離(m)ですね。
これも誤差範囲くらいの結果に終わってよかった(汗汗)。ちなみに、出力の第2値は、終点から始点を見た場合の方位角です。
Location::GeoToolでこれを得たい場合には、次のようにすればOKです。bash-3.1# perl -MLocation::GeoTool -e '
> my $loc = Location::GeoTool->create_coord("35.00000","135.00000","wgs84","degree"); > my $dir = $loc->direction_point("40.00000","140.0000","wgs84","degree"); > print $dir->reverse->direction."\n";' 220.095312067574
4.1点からの距離と方位角から、その先の1点を求める。
世界測地系で北緯35度、東経135度から方位角45度(北東)、距離1000000mの地点の経緯度を求める場合、Location::GeoToolだとこうなります。
bash-3.1# perl -MLocation::GeoTool -e ' > my $loc = Location::GeoTool->create_coord("35.00000","135.00000","wgs84","degree"); > my $dir = $loc->direction_vector(45.00000,1000000); > print join("\t",$dir->to_point->array)."\n";' 41.0881639279743 143.411403618375で、結果は北緯41.088度、東経143.411度です。
Proj.4だと、やはりgeodコマンドを-Iオプションなしで使って、
bash-3.1# geod +ellps=WGS84 -p -f "%.8f" <<EOF > 35.00000 135.00000 45.00000 1000000 > EOF 41.08816395 143.41140363 230.19682191出力の第3値は、やはり終点から始点を見た際の方位角です。
という感じで、Proj.4を使うと、Location::GeoToolと同等の変換を、より高い信頼性で行う事ができます。
とは言え、Location::GeoToolにはこれ以外にも、
- 経緯度を表す各種フォーマット間の相互変換が出来る
- 方位角をその方向を表す表現(例:北北東、NW、等等)に変換できる
- 2点間の中点等も扱える
- GridLocator、Locapoint、DoCoMoのiエリア等との連携もできる
といった蓄積や利点もあるので、本当はLocation::GeoTool内部の変換エンジンを、Proj.4にアップデートできれば一番いいんですけどね。
でも、Proj.4ライブラリを叩くXSコードを書くのは私には敷居タカス...コマンドラインを叩いて実現する形なら、すぐにもできそうだけど...。
2007年07月21日
何回やっても何回やってもCPAN::Miniが使えないよ
タイトルはネタなので使えるようにした話です。
仕事場のサーバ群が内から外への接続が禁じられているので、Perlモジュールの設定がしたくてもcpanスクリプトが使えません。
というかwgetすら使えないので、いつも泣きながら、手動で依存解決しつつ1つ1つモジュールアップしてインストールという作業をし、cpanさえあれば2、3分で終わらせられる作業に何時間も費やしたりしていました。
そのボヤキをtwitterでつぶやいたら、CPAN::Miniというモジュールを使ってローカルにCPANレポジトリを作ってしまう方法をすぐさま教えてもらいました。
その時はとにかく環境を急いで作るのに精一杯でかつ環境できかけていたので、手を出してなかったのですが、今回サービスインしてちょびっとだけ余裕できたので、試してみました。
使い方なんかはこの辺から知識を得まして、まず自分PCのVMWare上で
> minicpan -r http://ftp.cpan.jp/ -l ~/minicpan
してCPANレポジトリを作成し、それをサーバにアップして、そのレポジトリをデフォルトのCPANレポジトリに指定してサーバのcpanスクリプトを初期化しました。
で、うまく動いてるか試そうと、手始めにEncodeモジュールのアップデートでもしてやるかと
cpan> install Encode
とかやってみたんだけど、全く動かない。
「Encodeモジュールって何?食べられるの?」とか聞かれる。
他のモジュールでも試してみたけど、全く同じ。
cpan> reload index
とかしてみてもダメ。
何回やっても何をやってもCPAN::Miniが使えないよ...という事で途方にくれてた。
でも、よく見ると、インデックス再構築時に出てるエラーとか見てると、
Fetching with LWP:
file:///.../cpan/modules/02packages.details.txt.gz
LWP failed with code[404] message[File `/.../cpan/modules/02packages.details.txt.gz' does not exist]
...
Fetching with LWP:
file:///.../cpan/modules/03modlist.data.gz
LWP failed with code[404] message[File `/.../cpan/modules/03modlist.data.gz' does not exist]
とかってエラーが出てる。
実際にローカルCPANレポジトリのディレクトリ内を覗いてみると、「authors」というディレクトリしかなくて、「modules」というディレクトリがない。
もしやと思って、ネット上のCPANレポジトリから、上でないと言われてる「02packages.details.txt.gz」と「03modlist.data.gz」をダウンロードしてきて、さらにローカルCPANレポジトリディレクトリ内に「modules」ディレクトリを切り、そこにこの2ファイルを置いてみた。
その上で
cpan> reload index cpan> install Encode
とかしてやると...動いた!動いたよママン!
とか言う感じで、何とか動かせるようになりました。
cpanスクリプトの動作原理とか判らないので、挙動からの飽くまで想像だけど、CPAN::Miniは飽くまでモジュールインデックスはオンライン時にネット上のCPANレポジトリから作成しつつ、モジュール本体のアーカイブのみオフライン時にローカルから使う、というユースケースのために作られているっぽい。
なのでモジュールインデックス作成に必要な「modules」以下のファイルは落としてこず、結果完全オフラインの環境ではそのままでは動かないのかな...とか思った。
2007年07月19日
個人のこだわりが機能美を生める
昼休みもほとんど仕事、夜も何度か終電近くまでという状況でブログ書けるような状況じゃなかったが、何とか今日、というかもう昨日だけれども、今担当しているサービスをサービスインすることができた。
数年前から今の会社でこの時期にやっているキャンペーンの今年を私が担当する事になり数ヶ月、企画から始めて判らないところも同僚やいろんな人にいろいろ助けられ、形にすることができた。
サービスイン早々、今年から投入した新機能等へのユーザの反応も上々だし、ものを作るという意味で非常に面白かったのだが、一方で複雑な気分も一方である。
その気分の理由は、自分がこだわりを持ってきて培ってきたノウハウや技術を、全く活かせなかったことだ。
今回サービスインしたキャンペーン、ケータイの位置情報を使ったゲームなのだけど、今の会社に入る少し前、私は個人で非常に似たコンセプトのゲームを運営していた。
その時は、当然企画も制作も開発も自分ひとりで、挙動をテストする端末にすら事欠いて、自分の持つ機種の端末以外は、ユーザからのバグレポートを元に何が起きているかを想像して解決しなければならない、というような酷い状況だった。
が、機種毎のHTTPの遷移の違いからセッション管理の違い、位置情報の扱いの違い、等等、とにかくあらゆる事を思い存分追求調査することができ、それを実装に反映する事ができた。
結果、自分でいうのもなんだが、そんな環境で作っていたにもかかわらず、かなり完成度の高いものを作れていたと思っている(プログラム技術とか、データベース技術とかはショボかったが)。
先にも書いたように作っていたのはケータイの位置情報を使ったゲームだったのだが、実はケータイの位置情報というのは、キャリアや取得方法にもよるが、詐称できる。
ところが、ゲームとして使う以上、詐称されてしまってはゲームが成り立たない。
そこで、各キャリア毎のセッションの持たせ方等を研究しつくし、絶対に位置情報を詐称されないような遷移パターンを取りつつ、かつケータイ3キャリア+PHS1キャリアで共通の基盤上で動作するようなシステムを作ることが出来た。
過去私が採用していた方法で、100%位置情報詐称を防げる自信のある、まさにケータイ愛・位置情報愛を注ぎ込んだサイトになっていた。
ところが、今回投入したサービスには、そうしたこだわりやそれから生まれたノウハウは、全く反映されていない。
昨年度の同じキャンペーンの実施中、私は外からプレイヤーの側で参加していたので、すぐに位置情報詐称の問題に気付き、中の人(いまや同僚だが)に連絡した。
その時、まあとりあえず、の対策はなされたのだが、完全に詐称を許さない抜本的対策はとられなかった。
そういった経緯があったので、今年のを私が担当することになった時、絶対その辺の自分のノウハウがある部分は対策してやる、と最初は思っていた。
でも、いざ始まってみると、とても自分のノウハウを盛り込むどころではなく、期間内に形にするだけで精一杯だった。
私の担当は実装ではなく、実装依頼先・クリエイティブ制作依頼先等を管理し全体をまとめる役回りだったのだが、昨年のコードで動作を理解してもらい、今年度の追加分を実装してもらったり、制作と開発の間の同期・作業の拾遺をするのに精一杯で、ノウハウを伝えて実装してもらうどころではなかった。
余裕なく、そもそも検討の俎上にも上げられなかった。
私が作っていたサイトよりも、今回のキャンペーンの方が、デザインや登場するキャラクター、ゲームのストーリー性等あらゆる点で上だし、広告費用等も大量につぎ込まれ、ユーザの数・支持・反応も桁違いだ。
技術的な面でも、プログラミング技術等の面では、今年の開発依頼先は腕の信頼できる私の友人の会社に頼んだので、私のプログラムなんかよりはるかに高度なもので仕上がっている。
ただ、ここまで追求しましたというような、ケータイ愛や位置情報愛がない。感じられない。
具体的なキャンペーン名も書かないし方法も書かないが、位置情報を詐称できてしまうような問題は残されてしまっている。
詐称できないような機構をシステム全体に施そうと思うと、下手すればシステム全体の開発工数が1.5倍増しくらいにもなるので、限られた期間内でできる事から考えると、そういった瑣末なことの追求より集客できる新機能、といったトレードオフから仕方ない事なのだけど、やっぱり過去その辺を追及したことのある立場からすると、やはり複雑な思いではある。
よほど皆が同じベクトルの意志でも持たない限り、色んな思惑の交錯する複数人で構築するサイト、特に商用では、ここに限界までこだわって追求しました、みたいな機能美、統一美を持ったものというのは、作るのは難しいのかなと思った。
例えば別の例で言うと、無料からキャリア公式の有料のものまで、ケータイの地図サイトというのは数多く存在するけれど、その全ての中で、今どれが一番機能的に洗練されていて使い易いか、と聞かれれば、私は数多の有料・大手のケータイ地図サイトより、個人で運営されている「ここらで」を選ぶ。
どうでもいいいらない機能が多数ついて判りにくく、また全体の統一の取れていない下手な大手サイトより、シンプルで(一人でやってるから当たり前ですが)全体の設計・機能思想が一貫している「ここらで」の方が、はるかに使い易い。
だからこそ、以前ケータイ地図サイトのQRコードを表示するMappletを作った際も、Googleローカルモバイルと併せてQRコードの生成先として選んだのは、「マピオン」でも「MapFan」でもなく、「ここらで」だった。
(今は、MapSurferマップレットに統合された上で、マピオンやMapFanにも対応していますが)
デザインに凝ってたり金かけたり、広告等リーチ手段にお金をかけたりとか、そういった点で個人サイトは商用サイトなんかにとても勝てないけれども、機能美を追求して使い易いサイトを作るという点では、むしろ有利な立場にいるんじゃないだろうか、と思った。
ケータイ版ここギコを閉じてしまってもう3年以上、既に今は「ここらで」もあるわけだし今さらの感もあるけれど、今手を取られているマッシュアップアワード3が終わったりしたら、ケータイ版ここギコの復活でも手がけてみようかな...。
2007年07月06日
JavaScript::SpiderMonkeyを試してみた
先週末くらいから、今さらかもしれませんがJavaScriptにはまっています。
Ajaxとかじゃなくて、割と純JavaScriptなんですけど、いやあ結構おもしろいですね。
まだ恥ずかしながらプロトタイプベースのオブジェクト指向とか十分に理解しているわけじゃないんですけど、ぼちぼちいろいろ試しています。
今メインでやっているのが、色んな地図サイトななんかで同じ位置情報を表すURL間の相互変換です。
各サイト間の変換情報をハッシュテーブルで持つ際に、どうしても一部クロージャでロジックそのものをテーブルに持たざるを得ない状況です。
で、同じ処理をサーバサイドでもやる必要が生じたんですが(Mappletとかグリモンとか、携帯サイトとか、いろんな形で同じ機能を提供するため)、変換テーブルをJavaScript用とPerl用の2つ持って両方メンテナンスするというのはいかにも面倒くさい。
そこで、その部分だけJavaScriptで処理したったらええんちゃう?と思って、SpiderMonkeyとJavaScript::SpiderMonkeyモジュールを導入してみました。
インストールは超簡単。
こちらの記事で取り上げられている通りにするだけで、手順的にも時間的にも簡単にできました。
大体この手の導入って、過去の経験上、導入記事に簡単に書かれていても一悶着二悶着あるものと身構えていたのですが、本当にあっさりと。
ただうちの場合、CVSは使ってないのでtarballをこちらから落としてきたことくらい。
テストも問題なく通り、拍子抜けするくらいでした。
ただ、「その部分だけJavaScript処理」といっても、他言語の処理環境を走らせるわけだし、処理が重くなる度合いが度を越えていたら使えないので、ちょっと実験してみました。
JavaScript::SpiderMonkeyでの処理を含んだFastCGIスクリプトを実行した際と、同じ処理をPerlにやらせた際の処理速度の比較。
試したのは、
- FastCGIループの外でJavaScript::SpiderMonkeyのオブジェクトを作って、JavaScript実行
- アクセスの都度JavaScript::SpiderMonkeyのオブジェクトを作って、JavaScript実行
- Perlでeval実行
- Perlでハードコーディングしての実行
んで、PerlとJavaScriptで、同じ内容で同じ処理をするプログラムとして、n9dさんのFizzBuzzコードを少々改題したものを使いました。
コード的にはこんな感じ。
#!/usr/bin/perl
use CGI::Fast;
use JavaScript::SpiderMonkey;
my $js = JavaScript::SpiderMonkey->new();
my $code = 'for($i=1;$i<=100;$i++){print_to_perl($i%15?$i%5?$i%3?$i:"Fizz":"Buzz":"FizzBuzz");}';
while (my $q = CGI::Fast->new) {
print "Content-type:text/html\n\n";
my $p = $q->param("mode");
if($p !~ /[0-3]/) {
print "Error!";
next;
}
if ($p < 2) {
my $ljs = $p ? JavaScript::SpiderMonkey->new() : $js;
$ljs->init();
$ljs->function_set("print_to_perl", sub { print "@_<br/>"; });
$ljs->eval($code);
$ljs->destroy() if ($p == 1);
} elsif ($p == 2) {
eval($code);
} else {
for($i=1;$i<=100;$i++){print_to_perl($i%15?$i%5?$i%3?$i:"Fizz":"Buzz":"FizzBuzz");}
}
}
sub print_to_perl { print "@_<br/>"; }
これでApacheBenchで1000回アクセスして実験してやると、こんな感じになりました。
|
SpiderMonkey (使い回し) |
SpiderMonkey (都度生成) |
Perl eval |
Perl | |
|
平均処理速度 [ms] |
22.030 | 28.222 | 5.860 | 5.076 |
|
秒あたり 処理回数 |
45.39 | 35.43 | 170.64 | 196.99 |
うーん、やっぱり歴然とした差がありますねえ…。
秒あたり1アクセスとかみたいに死ぬほど遅いってわけでもないですが、せっかくFastCGIで動かしてるのがCGI並みの処理能力になってしまう...。
かといって、やっぱ変換テーブル2重持ちの管理コストも結構なもんだし...。
死ぬほど遅かったりしたらすっぱりあきらめられるところなんですが、微妙な線だけに悩めるところです。
![[ここギコ!]](http://kokogiko.net/logo.png)



・京都外国人排斥カウンターデモの「反日上等」「日の丸ウンコ」とかについて(名無し)
・京都外国人排斥カウンターデモの「反日上等」「日の丸ウンコ」とかについて(**)
・3Dどきゅめんと…って何?点字文書?(MrSwant)
・3Dどきゅめんと…って何?点字文書?(Ufoceleb)
・コロカの詳細が判りました&店舗誘導における来店検知の方法について(kokogiko)
・コロカの詳細が判りました&店舗誘導における来店検知の方法について(通りすがり)
・可視光通信って自位置特定にも使えるんじゃないか(Light Wire)
・新型インフルエンザでマスクとか(和知父くま)
・気持ちのよいサービス2:タクシーに携帯電話忘れたら届けてくれた(あああ)