2010年12月30日木曜日

よいお年を

 今年は五色温泉に行かずに、実家に帰省という事で、フェリーに乗って新大阪に泊まってます。ここから先、しばらくネットの無い生活になります。未読は1日で100件ほど…年末という事もあって、濃い記事が多い…。

 ちょっとだけ・・・意味不明な雑感を・・・。

 最近のグーグルは、冴えない感が強い。しかし、BRIICSを考えれば、アンドロイドに軍配が上がるのだろう。個人的には Appleの方を押したい。Javaで開発するよりは、C++で開発したいもん(そこかヨ!)。未来を予測すると、想像以上にマルウェアやボットやクラックが深刻な問題になるであろうと考えてます。オープンで雑多でチープなものほど強いのか、統制の取れたものが勝つのか?ここは、見所だと思います。バージョンアップを断念しなければならないような製品にセキュリィティ対策が施せるとは思えませんがね・・・。

 メタプログラミングとアセンブラの関係記事をキボンヌ

 それでは、皆さん、良いお年を!

2010年12月24日金曜日

民主党だめだったか・・・(予算案)・・・(T/O)

最近買った本

 もうじき年末です。そろそろ、年末年始に読む本を仕入れないと、間に合わないですよー。と、いいつつ、ほとんど読み終わってしまって、年末年始用に本をもうちょい仕入れないと…orz な状況です。ほんとは、感想を書こうと思っていたのですが、なかなか、感想をまとめる時間がとれません。という事で、まとめて本を紹介する事に・・・。短時間で選んだので、割と本屋に山積みされていた本ばかりです。

 「結果を出し続けるために」将棋界を代表する羽生先生の書かれた本です。まぁ44才になって、瞬発力が無くなってきた中で、どういう指針で行けば良いのか模索するにはもってこいだ!と思って買いました。梅田望夫さんとの交流の影響も出ていて、ITに関する時代の流れについての対処法のようなものも書かれています。

 「」本屋で見るなり、一目ぼれしました。今まで、あるようで、無かった。茶について迫る本。茶家ならではの視点で、茶とは何か?を広めるために書いたとあるとおり、茶の精神に迫れます。これは、面白い。

 「さらば脳ブーム」脳トレで有名な川島先生の書かれた本。産学官連携の難しさなど、経験を書かれた内容が気になり、手にとりました。研究者としての立場と企業連帯との立場で、学問としての検証までできない産学連携において、論文レベルまでは昇華されていないが、十分な検証はしたつもりなのに、何で、ここまで言われなあかんねん?という恨みつらみも綴った内容で、川島先生が気の毒に思えてきました(ここまで書いて、遺恨を残さないのかな?という意味で)。世間でも結構叩かれていましたし…。

 「仕事をすぐやる人の習慣」マネジメントに関わる以上、読まない訳にはいかないので買いました。大前先生、やっぱり凄い・・・。しかしだ、工数一月以上かかるものを単独でこなしている中で、マルチタスクで雑用をこなして指示しなければならない立場というのは、これらのどれにも当てはまらないように思えます。つか、コーディングの仕事も並行稼動でやってるのに、優先順位もくそもあるか?ボケなのです。

 「現代語訳 論語」斉藤先生が書かれたものなので、買いました。しかし、漢文が載っていないのは、ちょっと辛い。初心者か、超上級者でないと、この本は読みづらいかな?とも思ったのですが、読み進めるうちに、これはこれでアリだと思えるようになりました。

 「呼吸の本」谷川俊太郎先生の書かれた本で、うちの坊ちゃんと楽しもうと思って買ってきましたが、時間が取れなくて全く読んでません。 iPadをうちの坊ちゃんに見せると、嫁さんに怒られちゃうんです…orz。本屋で、綺麗なカバーを付けてくれようとしましたが、「裁断するので要りません」と断りました。

 「ろんりの練習帳」やっぱ俺、ロジックが苦手だわ…と自覚して、復習するために買ってきました(苦手なのは、コーディング上のロジックではなく、数学的なセンスでのロジック)。ただ、必要性に迫られていないので、読まないかもしれない。

 「日本でいちばん社員満足度が高い会社の非常識な働き方」全国SaaSベンダー連合会の懇親会で、著者の山本さんとお話する機会があり、その関係で買った本。ベンチャー企業ならば、こういった考えは、どんどん取り入れた方がいい。受託で顧客を抱えてしまうと、お客様を見捨てるわけにはいかないので、中には実践するのが難しいものもあります。山本さんの印象は、聞き上手という感じ。ツッコミを入れるタイミングとか、絶妙でした。経営者なら、この本は目を通しておくべきだと思います。この本を読んで「情報」とは何だろう?と改めて疑問に思いました。卵が先か鶏が先か?といった面はあるでしょうが、経営がしっかりしないと実践できないな?とも思いました。ECStudioさんのほんとの強みは、そこにあるのかも?なんて考えてしまいました。

 「GIGAZINE 未来への暴言」GIGAZINEさんで、告知された瞬間に狂喜乱舞して予約して買いました。この本については、改めてエントリを起こしたい気もするのですが、ここで・・・。全般に断定的な表現で、何故ここまで言い切れるのか?という感じで、ここまでくれば、むしろ清清しささえ感じます。なるほど、だから暴言なんだ!と納得の一冊。寄付モデルを提唱されるのであれば、やはり、GIGAZINEさんでも実践すべきなのでは?とも思いました。こういうのって、文化なので、効果うんぬんよりも実践してなんぼの世界だとも思います。それから、日本の教育に関してですが、私の感覚では「道教」を元に教育が成されてきてますが、そもそも「道教」の解釈自体を間違えて教育しているような気がしてます。IT通なら、この本は外せないでしょう。

2010年12月22日水曜日

位置情報特許・・・くだらねぇ

 この記事を見て思ったが・・・
こんなのは、誰でも思いつくような、実にくだらない内容だ。RSSが出現した頃に私が夢想したのは、地図上の図形をユーザが登録して、このエリアに関する情報にクエリを絞って、リーダへ配信するというようなサービスだ。使い方の例は、不動産会社が、関心エリアをユーザに登録させて、或いは不動産会社が用意した地区図形を選択させて、そのエリア内で、価格が3000万円以下の土地物件が出現したら、配信する。というようなものだ。
 特許は100害あって1利無しなのではないか?企業が防衛的に特許を取るのは、しょうがないのだろうけど、あほくさすぎる。

delphi indy で smtp 備忘録

参考URL:http://hpcgi1.nifty.com/MADIA/DelphiBBS/wwwlng.cgi?print+200911/09110030.txt

MECSUtils は、こちら

uses ..., IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient,
  IdExplicitTLSClientServerBase, IdMessageClient, IdSMTPBase, IdSMTP, IdMessage,
  IdEMailAddress, MECSUtils;

...

procedure THoge.SendMail(title:string; desc :string);
var
  msg: TIdMessage;
  mItem: TIdEMailAddressItem;
begin
  IdSmtp1.AuthType := satNone;
  IdSmtp1.Host := 'mail.yourcorp.co.jp';
  IdSmtp1.Username := 'login@yourcopr.co.jp';
  IdSmtp1.Password := 'password';
  IdSmtp1.Port := 25;
  msg := TIdMessage.Create();
  try
    msg.ContentType := 'text/plain';
    msg.CharSet := 'ISO-2022-JP';
    msg.ContentTransferEncoding := '7bit';
    msg.From.Name := 'なんちゃら監視サービス';
    msg.From.Address := 'daemon@yourcorp.co.jp';
    mItem := msg.Recipients.Add();
    mItem.Name    := '管理者さま';
    mItem.Address := 'to@yourcorp.co.jp';
    msg.Subject := MecsMappingFix_UnicodeToJISX0208( title );
    msg.Body.Add( MecsMappingFix_UnicodeToJISX0208( desc ) );
    IdSmtp1.Connect;
    IdSmtp1.Send(msg);
    IdSmtp1.Disconnect;
  finally
    msg.Free;
  end;
end;

2010年12月17日金曜日

railsぼやっきー

 くっそー、ActiveRecord が初期化される前に Controller のメソッドがコールされやがる。
なんじゃこれ?
 で、レコードの代わりに、ご丁寧にも、なんかわからんオブジェクトが渡されやがる・・・
そして、そいつが
warning: Object#id will be deprecated; use Object#object_id
なんて、わけのわからん警告を出して、レコードのIDの代わりに、オブジェクトのIDを代入して、颯爽と風と共に去りぬ。
もう、わけわからん・・・。

追記:ちくしょー、アクティブレコードのオブジェクトじゃなくて、ただの配列になってるやん・・・まぬけ過ぎ・・・はやく気づけよ・・・。スクリプトは好きになれん

組込系が下火?

思うのですが、今時なら、何でもネットに繋いでHTTPで制御できるようにしておけば、使い方がわからなくても、それだけでプチイノベーションです。組込系頑張って!

2010年12月14日火曜日

cinderッテミタ

CinderでiPadアプリを実装してみたを踏襲して、cinderってみました。きっかけは、boost忘年会 in 札幌で、cinder ってお題が出てたのかな?と思ったからです。cinder なんて、しだんがなー(すみません。もうじき6歳になる息子が、かいけつゾロリの本を読んで、「おやじギャク言うよ」って五月蝿いんでふ。だもんで、うつっちゃった)
 踏襲してみたは、いいんですが、あちこち、おかしいんですね。オブジェクトのコピーとか、生成とか、もうちょっと、ちゃんと書かないといけないみたいです。面倒になったんで、色は、その場でカラフルにしますた。動画も面倒なんで、場当たり的にのっけてみましたが、これ、ちゃんと見えるんだろうか?
ま、いっか・・・。

2010年12月13日月曜日

narrowing conversion of ‘255’ from ‘int’ to ‘char’

なんとなく気分の問題で、gcc のコンパイルオプションで、-std=gnu++0x を付加してみたら
error: narrowing conversion of ‘255’ from ‘int’ to ‘char’ inside { }
なんつうエラーが、以下のコードで起こってしまった。
  char hoge[] = { 
    0x00, 0xFF, 0xFF, 0xFF, 0x00,
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
    0x00, 0xFF, 0xFF, 0xFF, 0x00,
  };
なるほど、signed char として考えれば、0xFF はダメと言えば、ダメ。
暗黒の歴史を垣間見たような気がします。
unsigned char に変更したら、コンパイルは通った。バイナリ値のつもりなんで
どっちでもいいんだけどね。

GCCくん、たまにヒステリック?

なんの変哲もない以下のコードが、gcc でエラーになってしまった。
 enum flann_log_level_t {
  LOG_NONE = 0,
  LOG_FATAL = 1,
  LOG_ERROR = 2,
  LOG_WARN = 3,
  LOG_INFO = 4
};
出たエラーは、以下。
 error: expected identifier before numeric constant
 error: expected ‘}’ before numeric constant
 error: expected unqualified-id before numeric constant

さっぱりわかんねぇ。enum の名前空間は、いけてない感じがすごいする。
どことぶつかってるのかわかんねぇけど、ぶつかってるくさいし、使われていないくさいので、コメントアウトした。コンパイルが通るようになった。わけわかんねぇ。まじ、わけわからん。

enum は、全部 BOOST_SCOPED_ENUM でも使った方がエレガントだろ。

Ubuntu 10.04 で NVIDIA GT 425M ドライバを入れる

参考: [HOWTO] Install NVIDIA drivers manually on Lynx
                  UbuntuでNvidiaの純正ドライバを導入する



面倒なんで、ざっと流れを

  1. Nvidia driver からドライバを入手する
  2. 必要なものをインストールしておく。
  3. 妨げになっているものを取り除く
  4. ドライバをインストールする



$ sudo aptitude install build-essential linux-source linux-headers-`uname -r` xserver-xorg-dev
Ctrl + ALT + F2
$ sudo /etc/init.d/gdm stop
$ sudo vi /etc/modprobe.d/blacklist.conf
編集して以下の行を追加する
blacklist vga16fb
blacklist nouveau
blacklist rivafb
blacklist nvidiafb
blacklist rivatv
NVIDIAで余計なものを削除する
$ sudo apt-get --purge remove nvidia-*
インストーラを実行する
$ sudo ./NVI*

2010年12月7日火曜日

ArtRage

 結構、値段がするので、迷いに迷いましたが、辛抱たまらず買って、ちょっと、はまりつつあるのが、ArtRage という油彩ソフト。油絵の道具を揃えたら、こんなアプリ程度の値段では済まないし、大掛かりで、後片付けやスペースも必要。
 油絵の知識は、まったくゼロの状態で描いたのが、下の2作。


 Apple教団に入信したからリンゴが題材になっているのではありません。昔から、何か試し書きする場合には、リンゴを題材としていたからです。


  いやー、ほんと油絵っぽく描けますねぇ。何の知識も無くても、このぐらい描けるのだから、もうちょい技法を勉強すれば、もっと凄い絵が描けそうです。

そんな欲が出てきて買った本が「油彩画超入門 光と影を描く」です。ただ、この本、アナログならではの技法のウェイトが多くて、少し消化不良気味。まだ買ってないので恐縮ですが、デジタル油彩画で買うなら、「油彩画プロの裏技」の方が良かったかな~と考えてます。

これは楽しいアプリです。

2010年12月4日土曜日

boost 忘年会

boost 忘年会 in 札幌 参加します。残り、三名ほどアリマスヨ。
せっかくなので、告知しときます。と、思って日付を確認したら、参加できない事が判明…無念。12日から、日程変わった?

2010年12月1日水曜日

icc うーむ

 Intel の Compiler icc を使えば、労力なしに実行速度アップ!と目論んで、評価版をダウンロードして評価してました。コンパイルするまで苦労の連続。Linux環境だったので、情報も少ない。で、サポートに問い合わせるも、新バージョンになったばかりだから、サポートの方も情報を押さえてなかったり・・・ほとんど自力解決でした。
 と、なんだかんだで速度を比較してみたけど、今回のコードでは、gcc と、ほとんど変わらない。その差、数パーセント。最近の gcc は、最適化もがんばっているようでして、これなら、よほどの事がない限り、iccを選択する理由も無いのかも?(ものによっては、性能が出るんでしょうけど)。

2010年11月30日火曜日

地図広告は、お金になりにくい

地図上に何があるか?は、あまりにも位置的な縛りが強すぎて、都心の密集した場所でもなければ、競争が生じないのである。ここへ、無理矢理、広告料による優先度を導入しても、使いでのない情報になってしまう。今いる場所から近いカレー屋さんなんて、いくらも無いだろうに…
いや、グループオンの記事をみて、お手並み拝見したく感じただけなんですけどね。順番が逆なんだよ。惹かれるものがあって、どう行くか?なんだよね。地図は、副次的なオマケ。

2010年11月27日土曜日

いろいろ

とりあえず、雑誌オンラインは、歯ね。後、二ヶ月で消去確定。

UQWiMax とか、それこそ電話サービスが付帯してれば、YahooBBを解約してでも契約しまっせ。料金が現行価格から1600円アップしても契約しまっせ。これって、難しいのだろうか?固定電話を置き換えてくれると嬉しい。

しばらく、C++の世界に戻れそうだ。しかし、スケジュールはタイト。やりたい事が多すぎるのかも…

2010年11月24日水曜日

雑誌オンライン、まる無視

案の定、定期購読の継続設定は、ウェブ上にのみ設定があった。iPadのアプリからだと、多分、気付きようが無い。
ひでぇんじゃねえの?の問い合わせも、まる無視されている状態だ。まあ、どのみちソフトウェアデザインは、読むつもりだったから、そんなに目くじらを立てるつもりもない。ログインした事の無いウェブから、ログインして、継続を中止するに設定した。
出版社は、ネットというもんが、よくわかってないのでは?対応、まずいですよ。

宝島から、別冊で「電子書籍の正体」なるものが出ていて、ワロタ。まさに、今の状況を的確に分析している。出版社ならではの視点だ。これを読んでると、出版社に同情したくなってきた…。今は、商業規模が小さい。だから、まぁ、儲からないのも半分しょうがない。紙で印刷する分は無いけど、インフラ部分は、お金がかかる。その辺を加味すれば、まぁ、思ったほど費用が安くなるわけでもない。デジタルは怖いしね…。がんばって紙本出してなさいよ。

2010年11月23日火曜日

iPad iOS更新イイ

ClockRadio が終了しても、ラジオが流れたままになった。
設定に空港モードが追加された。
五十音順日本語キーボードが追加された。
アイコンを重ねて整理できる(前から?)
ブラウザで、PDFを開くアプリを指定できるようになった。MIME-Typeを指定できれば、もっと面白い連帯が可能なのかな?ここは、RFCの縛りもあるので、JSON形式データと連帯できるようなAPIがあると、更に面白くなるかも?
気がついたのは、こんなところです。

追記:ロックが回転から音に変更された。寝ながらiPadを操作できないのは超痛い…どこかに設定は無いものだろうか?痛すぎ…
2010/11/24 追記:ホームボタンをダブルクリックすれば、回転ロックが設定できる(ステータスバーの一番左端)

2010年11月20日土曜日

アプリの課金は慎重に

この体験を元に、システム屋として深堀してみる。
雑誌オンラインは、推察するに、もともとウェブを主にビジネス展開しており、そこから、iPadアプリへも展開した。あるいは、iPadが出たので、ほぼ同時にビジネス展開した。雑誌の定期購読をデフォルトで自動継続するようにし、お金を取りやすい仕組みをサービスする側は、考えたのだろう。
実は、このような痛い目に合うのは2度目である。お試しで無料キャンペーン中だった Amazonのプレミアム会員を試したとき、同意した覚えもないのに、何も手続きをしないと自動的に Amazonのプレミアム会員にされてしまった事があった。さすがに、このやり口には閉口してサポートにメール連絡し、文句を書いたら、Amazonでは、即座にプレミアム会員をキャンセルしてくれた。正確に書くと、プレミアム会員の機能をキャンペーン期間の3ヶ月過ぎてから利用すると、自動的にプレミアム会員扱いにするという措置が取られていた。本人は、いつキャンペーンに乗ったのか覚えていないので、3ヶ月を過ぎたという意識もなかった。
まず iPadやiPhoneのアプリだが、インストールするのも自由だし、削除するのも自由だ。よって、定期的にお金を取る仕組みは、Evernoteなどの総合的サービスでなければ難しいと心得た方が良いだろう。アプリを削除時に何かイベントが起こるとは考えにくい。仮にイベントが起こったとしても、通信可能であるとは考えられない。アプリによる継続課金はトラブルの元である。であるからして、利用する分だけ払う仕組みが本質であり、クラウドのビジネスは、根本的には利用する分だけ払う仕組みがあっている。
仮に継続させたいとしたら、どうすれば良いだろうか?課金単位の区切りで、継続するかどうか1度だけ問い合わせるのが良いと思う。自動継続の設定ができるとしても、自動継続の設定はアプリで保持しておくべきであろう。サーバ側で自動継続の情報を持たせてしまうと、アプリが削除された場合に問題を引き起こす可能性が大だ。ハードウェアが壊れた場合などは、どうであろうか?それこそ、ユーザにとっては、お手上げではなかろうか?
 とにかく、デフォルトはサービスする側にとって都合のいい値ではなく、ユーザに迷惑のかからない値でないと、評判を落として損をするのは、サービスする側なのだ。

2010年11月19日金曜日

雑誌オンラインで勝手に購読を更新された

 ソフトウェアデザインの今月号が読めるので、バグかと思ってメールで問い合わせた。
 そしたらバグではなく、リーディングルームに、継続購読するという設定があるので、3ヶ月定期購読が更新されたという回答が来た。周知徹底が足りなくて、今後気をつけますということなのだが、リーディングルームのどこにも、購読を継続するという設定が見当たらない。
 俺は、どうすればいいの? iPad のアプリを削除したら、定期購読を解除してくれるの???そんなわけないよね???
新手のカード詐欺ですか?コレ???
 でさ、定期購読が終了したので、アプリを削除した人、どうなるの???マジ勘弁してください。
つか、金返してくれ。
それから、どうやったら定期購読の継続設定を解除できるのか、教えてくれ。
ひでぇ、電子書籍ビジネスは、ほんとうに混迷が深まるばかりだ・・・。

2010年11月17日水曜日

民主党大丈夫か?

レアアースの代替素材研究を中国とやるなんて、正気とは思えん。馬鹿か?

2010年11月15日月曜日

Objective-C

暇を見ては、Cocoa や Objective-C の勉強してます。思っていたよりも、Objective-C が良くて、共感を覚えてます。ただし、実際に使いこなすかどうかは別です。パフォーマンスも気になるのです。なんのこっちゃ…

もがー

 私は壊れ気味ですが、みなさん、いかがお過ごしでしょうか?今日(昨日)は、OpenVGについて調べていて、首を捻ってました。何の意味があるのでしょうか?よくわかんねぇーです。つまり、OpenGLを実装するのは大変だから、ミニマルセットなライブラリを定義しようという趣旨でいいのかな?いや、なんか、C++で表現すると、stl を提供するのはシンドイから、stlのラッパ・ライブラリを定義して提供しようみたいな感じにしか思えんのです。そりゃ、ハードウェアベンダーさんの敷居は下がるから、意味はあるんでしょうけど…。

 閃いた事があって、あとでブログにまとめて書こうと思っていたんですが・・・、すっからかんに忘れてしまいました。テーマは、ソーシャルとマーケティングとビジネスについてだった気がするんですが、いったい自分は何を妄想していたのか?

 マーケティング3.0を読んだ事も関係していたと思うので、そこを手がかりに、ゆるゆると書き散らすと・・・。世の中ソーシャル合戦が激しくなって、今、Facebook と Google が囲い込み戦争をやってるじゃないですか?情報革命による勝者総取り的な要素があったりするんで、世界中が、ライバルを蹴落として、いかに自分だけが生き残るか?に、躍起になっていると感じるんです。
 でもね?未来を思い描き、未来をデザインし、そのデザインに向かって行動するのは人間なんだよね。自分だけが生き残るためのデザインと行動って、寂しくないですか?そんな世界、息苦しくないですか?だから、みんなもっと、お金が回るビジネスモデルを考えようよ?
 って感じの事でも考えてたのかな・・・今となっては、よくわかんねぇです。

 何はともあれ、今の Google は間違っていると思う(Facebook に対する措置は、間違ってはいない)。

2010年11月12日金曜日

クラウド・コンピューティングEXPO感想

 自分が想像していたものよりは、こじんまりした感じでした。

 これは!と思ったのは、LSIロジック株式会社のブース。PCI Express 2.0 のインターフェイスを介して、転送レート 6Gb/s という爆速SSD コントローラ。スタック接続していけるみたいで、SSDも3年間の保証つきだとか…。用途によっては、本格的に次世代のアルゴリズムを彷彿とさせるものができちゃうかも?値段は、普通のSSDよりは高いですが、手が届かないという値段でもない。

 さくらインターネットさんのプレゼンが、すごい面白かった。

 ブラウザは、世相を反映してIEを使っているところが圧倒的に多かった。まぁ、何か高度な事をしようと思うと、Flashを使うしか無いんだろうけど、リスキーだなぁと感じます。それから、ウェブ・アプリの作りこみは、皆さん結構、地道に直球勝負でやってるんだなぁというのも実感しました。

 うちの会社、GISのソフト開発をメインにしているので、オークニーさんのブースも寄って、森社長さまとお話をしました。考え方が被ってて、やっぱこうなるしかないよなーというところに落ち着いてました。正直、オークニーさんのビジネスセンスは素晴らしく、見習わなければ…とも思いました。ちなみに、うちの会社では、SalesForce の存在がもの凄い気になってるんです…と訴えても、お客もないし投資する余力もないという事で見送りになってました。まぁ、今の Salesforce でオークニーさんのような事をやろうと思うと、サービス用のサーバをどっかから用意して面倒を見なきゃならんと思うので、これはこれで結構大変そうです。被らないよう、また、いろいろと考えなくては…

2010年11月10日水曜日

東京出張

木曜と金曜にクラウドコンピューティングEXPOを見に行ってきます。泊りですが、SaaSベンダ連合会の懇親会で21時まで拘束っす。

2010年11月3日水曜日

いろいろ

 ここんところ、全てにおいて、はまってます…。人生、なかなか思うようには行かない。俺の考えるコーディング・スピードって、普通よりも遥かに速いのかも…?などと悩んだりしてます。そんなに速くないと思うんだけど…。
 日曜日も、例のごとく、うちの坊ちゃんを連れて、自転車ツーリング!今度は、円山動物園まで往復20キロ強の旅してきました。ちょっと、スパルタだったかな?まぁ、北海道では、そろそろ自転車の季節も終わりです。
 そうそう、「Masterminds of Programing」それなりに面白かったです。とくに、「Haskell」と「Forth」と「Objective-C」の章が良かったです。正直、「Beautiful Code」が、ちーっとも面白くなかったので、「Beautiful Architecture」に続くと思われる、このシリーズも、Stroustrup 先生のところ以外は期待していませんでした。当然ながら、Beautiful Architecture は、私はスルーしてます。
経営にも携わるので、「プロフェッショナルCIOの教科書」を読んでみましたが、そもそもITを創る企業が、こんなもんを読んでも何の役にも立たない…というのは言いすぎでしょうか?だいぶ前に読んだ「CIOのITマネジメント」で、漠然としすぎていて役にたたねぇーと懲りていたはずなんですが…。でプロマネのスキルも本格的に必要なのかと思って「見積もり技術」を読んで、反省するところしきりなのです。でも、規模がでかすぎて、これ全部やってたらコストかかりすぎだろ…と憂鬱にもなります。見積もりの精度を上げるとリスクは減るけど、それだけでコストがかかる。そのコストは、誰も見てはくれない。


 

2010年10月22日金曜日

スクリプトのこんなところが嫌い

 rails で @hoge = Hash.new を使っていたのだが、erb の template で値が引けない。何が悪いのかさっぱり、わからんかったが、どうやら、key に代入された型が、integer なのか、string なのかで挙動が変わっていた。
ところが、片方では 明示的に .to_i しなくても integer 型で登録され、もう片方では明示的に .to_i しないと string 型で登録されてしまう。

 ソースを追うと、ここかしこに選択子があり嫌な感じだ。

1. ActiveRecord から find_by_sql で引いた値が、integer 型なのか、string型なのか不明瞭
2. Hash.new した値に登録する時に、integer 型で登録するのか string 型で登録するのか選択できる
3. template 内で、@hoge[ key.to_i ] するのかどうか?そもそも、key の型が何なのか全く予測がつかない。

どうも、こんなあたりに、げんなりします。

2010年10月21日木曜日

Postgresql 値比較備忘録

 今回は、PostgreSQL の Stored Procedure にて、こんなコードではまった。
  ...
  IF TG_OP = 'UPDATE' THEN
    IF OLD.name <> NEW.name THEN
       UPDATE ...
    END IF;
  END IF;
  ...

この場合、OLD.name か、NEW.name が null の場合に条件に合致しない。正しくは
  ...
  IF TG_OP = 'UPDATE' THEN
    IF COALESCE(OLD.name,'') <> COALESCE(NEW.name,'') THEN
       UPDATE ...
    END IF;
  END IF;
  ...

2010年10月16日土曜日

xcode で symbol(s) not found 備忘録

xcode で、c++ のコードを追加したら、symbol(s) not found と怒られてしまった。
あるはずの関数がシンボルが見つからない。名前をみると _hoge という形式なので、ははぁ?C++の関数をC でリンクしにいってるな?と、そこまではわかったのだが、手を抜いて単純に extern "C" だけを付けたのがまずかった。

 *.mm *.cpp 等では、cplusplus のコードとしてコンパイルされるが、*.m など Objective-C では c と同じ扱いのようだ。そのせいで、extern "C" 自体が構文エラーになっていた。ヘッダの宣言では、ちゃんと

#ifdef __cplusplus
extern "C" {
#endif

...

#ifdef __cplusplus
};
#endif

してやらんと、いけません。
なんとなく、不安にかられるなぁー。class や template キーワードが入った場合は、c++ マングリングにスイッチしたりすんの??? Objective-C 不気味な感じがする

2010年10月15日金曜日

DLL_PROCESS_DETACH は難しい

 ちょい記憶が曖昧なのだが、DLL_THREAD_DETACH は、必ずしもコールされるとは限らないのである。APIで無効にできるからだ。そして、DLL_PROCESS_DETACH時の処理も非常に難しい。実は、このタイミングで C|C++ランタイムのクリーンアップ処理が自動で実行されるからだ(Vista, 7 では、どうかわからん)。
 よって、DLL_PROCESS_DETACH のタイミングで、スレッドの同期保護オブジェクトを利用して何かを実行しようとすると、たいていは、デッドロックを起こしてしまう。とにかく、厄介な代物なのである。
 MSには、DLL_PROCESS_DETACH の他に、DLL_PROCESS_DETACHING とかいった通知をDLL_PROCESS_DETACHの前にしてもらいたいと希望したい。そうすれば、デッドロックを起こさずに済む。結局のところ、このような仕様のおかげで、マルチスレッド絡みで、ほいほいとDLLをロードしたりアンロードしたりできない。つか、不可能だろう。皆さん、どうされているのだろうか?あ?C#使ってるから、関係ねぇのか!

2010年10月14日木曜日

apple id の管理がひどいっぽい

どうも、apple id の管理は、ひどいような気がしてきた。macbook を買った時に登録した apple id が、どうも消失しているような気がする。いや、多分、消失している。おそらく、iphone sdk 用のアカウントを作成した時にでも、統一されて上書きされてしまったのだろう。
macbook のアドレスブックに記載されている apple id をなんとかしようとしても、全くもって、どうにも見つからない。メールを送信しましたって、メッセージは表示されても、いっこうにメールが届かない。アカウントの確認の生年月日が、違うと言われてはじかれるし、どないなっとんねん。
それはそうと、なんでもかんでもサービスで、やれ、ログインIDを作成してパスワードを入力しろだの、アホかっちゅーーーーーねーーーん。
もう、そんなにたくさんのIDとパスワードなんて管理できへんねん。人間の限界を超えてるねん。
最近のアプリやサービスの流行は、ユーザ ーイン。俺のサービスは、こんなにユーザがいてまんねん。おかげで、何かアプリをダウンロードするたびに、サインアップを求められて、ちょーうざい。これからのサービスは、まじめに OpenID を考慮してくれ。

追記:どうやら、apple id と mac.com の id は別物らしい。後者は有料という事でいいのかな?あと、使わないけど iChat のアカウントが AOL で、もう訳がわかんねぇ。

2010年10月12日火曜日

自炊再開

 全然忙しくて、どうにもならんかった本の自炊を再開した。ScanSnapの設定は、スーパーファインで、自動補正の類は用紙サイズ以外、すべてオフにしている。なんだかんだと、AdobeAcrobatの最適化で修正する方向で落ち着いてしまった。
 また、ダンボール2箱分ぐらい本が減って嬉しい。新書も読む前から容赦なくスキャンだ。

 日曜日には坊ちゃん連れて自転車キャンプだー!と画策していたが、あいにくの雨で中止。月曜日には、やっぱりツーリングに連れていきました。でも今回は15キロぐらいしか走らなかった。

2010年10月9日土曜日

iPhoneSDK用のboost

 探したらあった。情報はCompiling Boost 1.44 for iPhone
 とりあえず、ライブラリのコンパイルまでは成功した。

2010年10月5日火曜日

macでboost

簡単だった。

bjam は、既にコンパイル済みのものが www.boost.org で配布されている。なので、ダウンロードして、

$ sudo cp bjam /usr/bin

デフォルトで利用する事に、ほんでもって /usr/local/src/boost_1_44_0 を展開して、そこで

$ sudo bjam

を実行すると、めでたくコンパイルも通った。

$ sudo bjam install

で、/usr/local/include/boost, /usr/local/lib にインストールされた。

試しに boost::thread のコードをコンパイルしてみたが、よさげだ。

$ c++ y.cpp -I /usr/local/include -lboost_thread

2010年10月4日月曜日

mac ぼやきてぇよ

 なんか、iconひとつ作成するのにも、えらい面倒くさい。適当なアイコン作成アプリもわかんねぇ。/Develper/Applications/Utilities/Icon Composer 72x72のアイコンはどうすんだ?しかも、先に psd ファイルを生成しろ?えーっ?
ソフトを入れようとしたら、six とか、知らねー圧縮形式出てきて、面食らって、やっと解凍したと思ったら、「クラッシック形式の実行ファイルは対応してません」とか怒られて、、、orz こりゃ、慣れるまでしばらくかかりそう。

2010年10月2日土曜日

本日も親子でツーリング

 本日も、親子で自転車ツーリング、ドリームビーチへ行って、森林公園に行って、帰ってきた。








23キロぐらいは走ったでしょうか・・・。
森林公園で、おやつのオールレーズンを鴨にあげたのが、地味に楽しかったらしい。

ウルトラマン・アート展

旭川市の美術館で、ウルトラマン・アート展があったので行ってきました。
ノスタルジーに浸れました









散歩

9月の通勤風景




iTunes iPad データ windowsからwindows移動備忘録

コピーするフォルダは、以下の3つ

  • C:\ProgramData\Apple Computer\iTunes
  • C:\Users\yourname\AppData\Roaming\Apple Computer\iTunes
  • C:\Users\yourname\Music\iTunes

とりあえず、これで移行は完了した。

2010年9月30日木曜日

iphone sdk ゲット

 とりあえず、Apple Developer に登録するのが、めちゃくちゃしんどかった。文字コードの関係で、日本語を使えない事は知っていたのだが、まったく違うところではまっていた。iPad で登録したアカウントのメール情報が、ダブっていないか?ご丁寧にもチェックしているらしい。慣れないマウスで、一度途中でページをバックしてしまったのも痛かった。そう、手持ちの個人メールのアドレスが尽きてしまったのである。南無!
 GMail のアカウントを増やそうかと思ったが、最近は、どうにもガードが上がっている感じで、無償で複数アカウントをホイホイ持つのもリスクが高そうである(2つ持っているので、これ以上増やすのは・・・)。
 いろいろと調べているうちに、GMail のメールアドレスでは、+を使用すれば、好きなメールアドレスを利用できる事がわかった。 foo@gmail.com というアカウントを持っていれば、foo+nandemokoi@gmail.com というように、+以後は自由に名乗れる。これだ!という事で、Apple Developer に登録するメールアドレスも、この手で違うように見せかけて、レジストをクリアできた。
 で、ダウンロードをしてインストールしただけで、力尽きてしまったのである。

2010年9月28日火曜日

このケータイは、すでにほかの・・・

 このケータイは、すでにほかの 3台の機器に登録済みのため、このパソコンでは使用できません。
macbook に windows7 を入れて、LismoPort に接続しようと思ったら、上記メッセージが出て怒られた。すごく、うざい。秘技、散歩返しをしようと狙っていたのに、これでは実現できないではないか・・・か・・・か・・・。埴輪・・・。うーん、iPadのiTunesの設定も移行しようと思っていたのだけども、簡単にはいかない。これも、Amazon で注文した 2.5inchi HDD を USB 接続するための機材が届くまで、作業はお預け・・・。
 パーティションを3つに分けてインストールする手順も面倒そうなんで、WuBIで、お茶を濁そうかと思ってる・・・。

2010年9月26日日曜日

macbook ゲット

 悩みに悩んだ末、macbook という選択肢にしました。ドスパラへ行ったら i3で、GeForce GT 330M で軽くて画面も大きい上、HDD500G、メモリ4Gというノートパソコンが、56000円ぐらいで売っていて、げろげろmacbook pro と同等以上で半額じゃん。Windows7のOS持ってるんですよと話したら、展示品だったやつだけど、もう1万足せば、i5で GT335Mのスペックもありますよ?と言われて、更にクラクラきました。
 シングルになっても、稼げる手段は多い方がいいだろうという事もあるし、何よりiPhone SDKをいじってみたいという衝動は押さえがたく、ドスパラノートを買って、MacMiniを買うという選択肢も無いわけじゃなかったんですが、そんなに投資もできないので、単純にmacbookという結論に。
 さすがに純正HDDを500Gにアップグレードするのはアホ臭いと思って、SATA 500G のHDDはドスパラで別買いしました。リサーチした情報によると、SATA2の規格は接続できないくさい点。7200rpm は、最近のものだと問題無さそうだけども、振動が大きくなったり発熱も大きくなったりする可能性がある上、シーケンシャルアクセスでは30パーセントほどの速度向上が見られるものの、ランダムアクセスの読み書きでは5400rpmよりもパフォーマンスが落ちる場合もある点。トータルパフォーマンスを考慮して5400rpmのものをチョイスしました。
 店員さんにHDDのキャッシュは何メガですか?とか、HDDの規格でSATA2をサポートしてますか?と聞いたけど、非公開情報なのでわからないですとの事でした。
 買ったHDDは Hitachi 2.5" SATA 500G 5400 8M 。macbookの中身を開けてみたら、同じHitachi 製の250G が入っていて、たぶん純正品と変わらないんじゃないかな?さすが、ドスパラのにいちゃん。すげぇぜ。ただ、HDD交換に必要な星形のドライバが想像していた以上に小さいサイズが必要で、本日の作業では無理な事が判明しました。
 つう訳で、今、マックから書き込んでいる訳です。
500Gにしたんで、たぶん、Ubuntu, Windows7, Mac のトリプルブートにする予定です。
 しかし、痛い出費だにゃー。借りがでけた。
追記:店員さん、さんざん保証外とか脅しやがって!マニュアルにHDDの交換方法が、堂々と載ってるやんけー。しかも星形ドライバいらんやん。ちょーーーーっ。
すぐさま追記:なるほど、やっぱ星形ドライバいるんかいorz...

パソくん壊れた

忙しくて、できなかった本の自炊を再開しようとしたら、運ぶ途中でノートパソコンを落としてしまいました。
そしたら、パソくん起動しねー。つか、そんなに無茶な衝撃があったわけでもないのに、へたれすぎです。保証期間も過ぎてるし、cuda sdk もまともに動作しないし、修理に出しても一月かかるリアルショップのない安いだけのBTO品は、もう懲り懲りだ。壊れた症状も前回と同じで、作りのボロさが気になります。リアルショップのあるドスパラで買っとけば良かった…
今更デスクトップにも戻れんし、GPGPUを使って遊ばなければダメだとわかっていても、遊べる時間がとれていない状況。欲を言えば、iPhone SDK でも遊びたかったので、MAC mini も欲しいところだったけど。現状を考えると、ネットブック系のパソくんを導入するぐらいが、精一杯かな…

海までツーリング

土曜日、また凝りもせず、うちの坊ちゃんとツーリング。弟子屈ラーメンで昼を食べて、ドリームビーチまで行きました。帰りは、時間がかかるかな?と思っていたのですが、一時間切るぐらいで済んだ。変速機付きだと、行動範囲も拡がりそうです。大体、15キロぐらい走ったでしょうか…

2010年9月24日金曜日

html buttonの挙動 忘備録

また、くだらない事ではまってしまった。
<button>クリック</button>
では、問答無用で submit が実行される。
<input type='button' value='クリック' />
では、submit が実行される事はない。
つか、使い辛いよ…。

日本政府の対応は糞だろ

 なんで尖閣諸島の件の船長を釈放すんの?アホだろ?アホ?しかも、なんの避難声明も出さずに・・・。
対中関係に大人の対応なんてねぇんだよ。
 レアメタルを輸出を止められたのが致命的だったか?あ?
 今度は、レアメタルと何を交換すんだ?あー?
アホだろ、アホ。

2010年9月23日木曜日

今日も親子ツーリング

本日も親子ツーリングで、飽きもせず公園まで往復10キロの旅。うちの坊ちゃんも、だいぶ自転車に慣れてきた。昼ごはんは、ラーメンてつや。俺としては、弟子屈ラーメンの方が良かったのだが、坊ちゃんのリクエストだったので、仕方ない。

困った国、中国

無条件で、尖閣諸島の問題の船長を釈放せよ?とは、何事だ?ふざけるのもいい加減にしろよ!
全く、この国には節度というものが、全く無いな。居直り強盗かよっ!
日本は、毅然とした態度をとらないと、属国扱いだぞ?

2010年9月22日水曜日

親子ツーリング

うちの坊ちゃんに、新しい自転車を買いました。変速機付きです。まだ、足がぎりぎり届く状態なので、慣れるまで、時間がかかりそうです。
日曜日は、公園まで往復10キロの旅、家につく間際では、疲れたらしく数回転けてました。月曜日は、レンタカーを借りに、自転車ででかけようとすると、「僕も行く」と言い出しました。坂道が結構あるから、大変だぞ?と言ったけど、大丈夫とはりきってます。試しに連れて行ったら、一回も転けずに、自転車を押して歩く事もなく、レンタカー屋さんにたどり着きました。およそ3.5キロ。
嫁さんも自転車買ったけど、ツーリングは楽しいという感じでは無さそう。
そろそろ、坊ちゃんに、膝、肘のパッドが必要か?

2010年9月21日火曜日

Mediawiki-PostgreSQLのアップグレード(ようやく成功)

 ずいぶん前の記事になるが、Mediawiki-PostgreSQLのアップグレード(結局失敗)で、止まっていました。
 今回、Trac,Mediawiki,Subversionで使用しているサーバの電源がデロデロになって、ぶっ壊れたのを機会に、Mediawikiもアップグレードしました。

 手順は、
http://www.mediawiki.org/wiki/Manual:Upgrading_Postgres
と基本的に同じです。
アップグレードに成功したかに見えて、最後の最後にアクセスしてみると、l10n_cache を更新する権限がないとか言われて、怒られます。こいつは、なんて事はない可愛いミスです。
オーナーを "postgres" から "wikiuser" に変更してやれば済む事でした。(アカウント名は、インストールした時の状態に応じて変わります)

 いやー、長かった。

 まぁ、ちょい手間取ったのには、ぶっとんだサーバが i386 版でして、手元にあるのが x86_64 ばかりなためでした。PostgreSQL の database イメージが i386 版で構築されているので、i386版のPostgreSQLを用意する必要がありました。CentOS x86_64 を KVM に変更して、仮想化環境を構築。そして i386 のカーネルをインストール。で、KVM ネットワークの接続を可能にするために、ブリッジ環境を構築。ファイルのやりとりが面倒になってきたので、NFSを設定…とかやったからでした。

 時間があれば、KVM とブリッジの設定、DRBD と Heartbeat とかについても書くんですが・・・パス。

2010/09/22 追記:別のマシンにセットアップしたら、Table '...l10n_cache' doesn't exist と言われて怒られてしまった。しばらく原因がわからなかったが、どうやら、PostgreSQLのschemaのsearch_pathの設定がまずかったようだ。
ここは、ちょっと詳しく解説する。
最初に成功した設定では、ログインロール(login role)が下記のようになっていた。
ALTER ROLE wikiuser SET search_path='mediawiki, public';
そして、backup & restore で、取り込んだサイトでは、下記のようになっていた。
ALTER ROLE wikiuser SET search_path="mediawiki, public";
wikiuser でログインしてエラーになったクエリを実行してみると、確かにエラーになる。
試しに mediawiki.l10n_cache と指定してみると、クエリはパスした。
犯人は、search_path の設定だ。
postgres でログインしてみると、エラーにならないので、postgres を wikiuser に
置き換えて設定をし直すと、うまく動作するようになった(下記)。
おかしな事に、pgadmin3 のバージョンによって、'mediawiki, public' だったり、
mediawiki, public だったりする。下記はエラーになったマシンでの表記だ。
ALTER ROLE wikiuser SET search_path=mediawiki, public;
まぁ、まっとうに考えれば、シングル・クォーテーションが正解だろう。
どこで、ダブル・クォーテーションに化けた???

2010/09/22 更に追記: はっきり言って、エラーの山…。データベース・パーミッションの設定がボロボロ。新しいテーブルは、ことごとくユーザが postgres のままなので、もぐらたたきのように wikiuser をオーナーに変更して回った。疲れる。

2010年9月16日木曜日

national geographic ゲット

zinio のバージョンがアップされていて、もしや?と思い、アプリをインストールしたのが、ちょい前の話。日本のショップにロシア版のnational geographic だけが、売られていて、何の嫌がらせだよ?と思ったのが昨日。今日見たら、英語版のnational geographic が売っていた。値段は、12 issues で、15円ナリ。ちなみに、昨日の段階では買えなかった。
という訳で、めでたくnational geographic 英語版のデジタル本をゲットしました!

2010/09/18 追記:価格は12ヵ月あたり、6千円以上にかわっていた。間違い価格だったのかな。ちょっとかわいそう。
2010/09/20 追記:どうやら、本来の意図した価格は、12ヵ月15ドルのようだ。円高の今、端折りすぎだけど、およそ1500円が妥当。zinioアプリのバグで、インターナショナルのショップ設定で日本だけ選択できない問題もあり、アプリの設定が不可能だが、zinioのhpから、アプリを通さないで直接デジタル版を購入するのが幸せになれるだろう。

2010年9月15日水曜日

windows7 の WM_WINDOWPOSCHANGING ではまる。

 なんかしらんが、アプリケーションが再描画を繰り返して止まらなくなってしまうという変な現象に出くわした。
アプリケーションは、Delphi で記述されている。Windows XP では、このような現象は起こらない。
まず、Spy++ で何が起こっているのか探ってみると、
WM_WINDOWPOSCHANGING
  WM_NCCALCSIZE
  WM_NCPAINT
  WM_ERASEBKGND
  WM_WINDOWPOSCHANGED
  WM_SIZE
  ...
というようなメッセージが送られていた。
元凶は、一番上の WM_WINDOWPOSCHANGING だ。

 どんな時に、この現象が起こるか?というと、Delphi のフォームで StayOnTop なダイアログをモードレスで表示した時であった。アホみたいにウィンドウもあるので、どいつが犯人なのかお手上げに近い。何か手がかりはないか?と探して

たいぶろぐさんの情報を見つけた。

SetParent API をコールすると、WM_WINDOWPOSCHANGING のメッセージがもれなくプレゼントされるようだ。

今回の現象が、このケースに該当するのかどうかは、置いておいて、ウィンドウのZオーダー絡みである事は関係しそうな気がしている。しかし、こんな微妙なメッセージの妙で、破綻するとは…モゲー

2010/09/16 追記:OnSize のイベントで、サイズに変更があったかどうかチェックを行い、変更が無い場合には何もしないように処理をすると、この無限連鎖を回避できた。全くもって謎だ…。ちなみに、この処理を行ったのは COM コンポーネントなので、描画のイベントで誰かが何かしているのかも…。

2010年9月12日日曜日

tsマーク取得良い

tsマークを取得するために、自転車を買ったところ(自転車本舗)に整備をしてもらいました。まず、スーパーイオンで、整備する技術が無いと言っていたのは、本当の事でした。スポークを調整して、車輪の歪みを矯正したり、ディレーラを調整したり、整備をするだけでも軽く二時間以上かかった事だと思います。ブレーキパッドが、かなり消耗していて、ほとんど溝が無い状態だったので、即、交換にもなりました。タイヤも今シーズンが終了したら、交換した方が良いでしょうという見たてでした。整備に時間を費やした分、費用は、それなりにかかりましたが、整備をして貰って凄い良かったです。
最近、自転車の状態が、どこか、ギシギシ、ガシャガシャする感じだったのが、整備後は、嘘のように滑らかでスムーズに動きます!車輪の歪みは、特別な道具が無いと微妙な歪みは絶対に分からないですし、ディレーラの調整も自分でやるのとは、雲泥の差があります。
そんな訳で、軽快感が2ポイントアップです。マジ、機動力が2,3キロ違います。
自転車による対人賠償額の最高判例が4700万円とからしいので、tsマークだけでは、こころもとないとのアドバイスも貰えました。
tsマーク制度、良いと思います。

2010年9月11日土曜日

運動会

今日は、息子の運動会でした。evernote にでも書けば、いいんでしょうが、なんとなくブログに書きたい気分。evernote iPadのWIFIだとGPSが機能しないので、使い物になりません。後から位置情報を加えられれば使う気がするのですが…
とまあ、それだけです。このブログの趣旨からは、随分外れた投稿でふ。
追伸
C# どうしても、この言語にだけは、馴染めない。何故だろう?

強者の生き方

 ふと、TechCrunchのNexus OneはGoogleの夢だったという記事を見て思った。
 自然界を見てみよう。強い動物から弱い動物、微生物、それぞれが循環して命が巡っているのだ。この情報化時代に、勝者総取りの傾向が強いのは、既に周知の事実と言っても過言ではなかろう。だが、勝者が一人残って、その勝者が自らのためだけに突っ走るとどうなるだろうか?巡らない命は敬遠されるのだ。そういう事のような気がした。
 同じ土俵で戦う Apple と Google の明暗を分けたのは、ちょっとしたビジネスモデルの差だと思う。Apple のやり方は、Google のやり方に比べて、まだ、ビジネスという土壌で循環する仕組みが高いのだろう。独善的ではあるにせよ…。

2010年9月10日金曜日

.Net はバラ色か?

 開発ツールを巡って、COM はダメで .Net ならOKとかいう話を聞いたので、不思議に思って調べてみた。
.Netからのコンポーネント呼び出し
以下、引用
そして、さまざまな言語研究者の勧めに従って、コードをコンポーネント化していました。つまり、COM (以前の ActiveX) サーバーとして、アプリケーションを呼び出し可能な機能の集まりとして分割しています。もちろん、他の開発者や企業から、ActiveX コントロールなどのコンポーネントを大量に購入している場合もあるでしょう。

そのような状況で、まったく別のオペレーティング システムに切り替えるという極端な決定を下すとどうなるでしょうか? その時点で、COM に対して行ってきた投資はすべて無価値になります。既存のコードを使用することはできず、新しいプラットフォームをゼロから学ばなくてはなりません。開発者の生産性が大きな打撃を受けるのは間違いないでしょう。
このシナリオは矛盾している。つまり、Windows から、Windows でないOSへの移行が、.Net で書かれていれば無駄にならないというものだ。そもそも、バルマー氏になってから、Mono への投資も下火になったのではなかったか?.Net のAPIって、Windows から完全に分離されているのか? DirectX 系を使う場合は、相変わらず COM ベースじゃねぇのか?低レベル(ハードウェアに近い事)な事をやるには、ネイティブ呼び出しをせんとパフォーマンス出ねーんじゃねぇの?とは言え、Yaneさんは.Net系でゲームを移植されているみたいなので、実質そうなのかもしれない。
 .Net って、Windows 縛りではない???ここがよくわからない。
 この考え方だと、C++ ネイティブによるコードが Windows 不遇の待遇を受けているのもよくわかる。システム・サービスやウェブ系サービスを書こうと思っても、新しい Visual Studio では軒並み C# 使え光線が出まくりで、C++ネイティブは排除されているからだ。

2010年9月7日火曜日

いろいろ

 困った時は、このタイトルで・・・。<- 何回目やねん・・・。  自炊を始めてから、圧倒的に再読する本の量が多くなった。なので新書を読む量が減っている。本屋には、ちょくちょく足を向けているのだが、触手が動く本が少ないのも一因かも・・・。  ブログの更新頻度が落ちているのは、いそがしいから・・・。正直、最近、仕事もあまり面白くない。雑用が多すぎる。いそがしいのだけど、休日はキープしている。うちの坊ちゃんの相手もしてやらんと不憫でならんから・・・。先々週の日曜日は、10kmほど走って、先週は20kmほど走った。さすがに20kmは4時間ほど走りっぱなしでふ。おかし休憩や公園遊びとかをはさんで6時間30分を費やしました。坊ちゃんのチャリは、足ブレーキで変速機無なんだけども、足ブレーキで下り坂はスピード調節ができないのと、変速機無もつらいし、ハンドの前ブレーキはガタがきて怖くなってきたので、今度の休みの日は、新しいチャリを買おうと思ってます。嫁さんも、チャリを買おうかな?と思っているようなので、3人でツーリングなんてのもいいかもしれない。  実は、つい先日、夜間に走っていて横断歩道を渡ってきた自転車に突っ込んでしまって、軽い打撲をおわせてしまいました。ちゃんとしておこうと思って、警察に電話して事故処理してもらって、その後も対応しました。で、横断歩道の信号が変わったという記憶が全く無い・・・記憶が欠落しているというのも、自戒も込めてどないなもんかな?と思うわけです。警察の方がおっしゃるには、こういった自転車の事故が増えているのだそうで、だんだんと、罰則も強化される方向にあるのだとか。  このような背景から、保険会社も自転車の保険を別扱いするようになってきているようです。自転車で相手に怪我をおわせてしまった時には、自転車だから大したことない・・・などと思わず、ちゃんと賠償も含めた保険に入っておいた方が良いと思いました。自転車人口が増えれば、必然的にこういった事故も増えてくるでしょう。  そんなおり、嫁さんが TSマークってのがあるよ?と教えてくれました。自転車の点検を1000円で受けると、1年間の対人保険が最大1000万円まで付いてくるという制度です。2000円バージョンもあり、2000万円までというのもあるみたいです。整備不良による怪我も増えているそうなので、いっそのこと自賠責保険のように義務化してもいいのかも?とも思います。ちなみに、TSマークを受けようと近くのイオンに自転車を持っていったら「すみません、うちでは、この自転車を整備する技術を持ち合わせていません」と断られてしまいましたorz...。車無生活で、遠くの自転車屋さんで整備してもらうのは厳しいっす(;_;)。
 てな訳もあって、今度の休みは、レンタカー&自転車ツアーの予定なんです・・・。レンタカーに3台も自転車積めるのかな・・・??? 載らなかったら、俺だけチャリで帰ればいいのか・・・

2010年9月6日月曜日

電子ブックビジネス混迷

 もうわけがわからん。週刊ダイヤモンド、定価690円なのに、マガストアでは700円で販売されている。しかも、デジタル版なのかどうなのかすらよくわからない。そして、ダイヤモンド社のHPを見ると、最新号の記事がばら売りされていた。おおーっ、ばら売りすげー先進的・・・とも思ったのですが、特集記事を5つにバラして、たったの4頁についた値段が税込み263円。ええーっ???時間と共に価格が下がっていくのでしょうか???かと思いきや、特集号は1冊300円で売られていたりします。
 今は過渡期なんでしょうかねぇ。

2010年9月3日金曜日

utvpnserver 管理IP制御備忘録

マニュアルがよくわからんので、ソースコードを追った。管理は、管理パスワードがあれば、何でもできてしまう。これは、あまりにひどい。しかも管理用ポートは、普通のポートと同じだ。

 @adminip.txt というファイルに、IPアドレスを記述しておけば、一応、接続制御してくれるようだ。

2010年9月1日水曜日

Bookman キターーーーーーッ

得非ょーーーーッ!
スゴアプリ Bookman が、バージョンアップしたでーーーー!
更にパワーアップしたでーーーーーー!
キターーーーーーッ!
キタ、キタ、キタ、キタ、キターーーーーーーーーーーーーーーーッ!!!

2010年8月31日火曜日

boost::filesystem で link2019 備忘録

 boost::filesystem で、LINK2019 codevec ... とか、generic_string とかで、リンクができずに怒られた。原因が良くわからずに、四苦八苦していたのだが、エラーをよく見ると、unsigned short の文字が!!! wchar_t を組み込み型としてコンパイルしていなかったのが原因だった…。

iPadのバックアップが死ぬほど遅い

 いろいろと調べているうちに、Windows7の場合
/Users/username/AppData/Roaming/AppleComputer/MobileSync/Backup フォルダ下に iTunes のバックアップが取られている事がわかった。
 まずやる事は、ウィルス・チェッカーにて、このフォルダを捜査の対象外に設定する事だ。そして、どうせウィルスが活動するのだから、活動して感染しそうになった時に考えれば良いという事で、USBデバイス等の積極的なスキャンもオフにする事にした。次に、/Program Files (x86)/Common Files/Apple/Mobile Device Support/AppleMobileBackup.exe と、AppleMobileDeviceHelper.exe もプロセスの対象外に設定した。

 それでも、バックアップが死ぬほど遅いのに変りない。大量にテンポラリ・ファイルを作成するアプリは?と探っていたら「雑誌オンライン」が犯人であった。なんとかしてくれ。Explorer Flicker も、そこそこテンポラリファイルが多い。雑誌オンラインで雑誌を4冊購入したけど、アプリごと削除するかもしれん。かごの中の鳥も勘弁ならん上に、こうテンポラリファイルが多いのでは、かなわん。4冊分の雑誌代金よりも時間の方が貴重なのだ。

追記:「雑誌オンライン」の設定から、キャッシュを全てクリアし、Explorer Flicker を削除したら、あっという間にバックアップが完了するようになった。予告「雑誌オンライン」アプリの余命は、あと3ヶ月。それまでにテンポラリファイル数を減らす改善がされない場合には、このアプリはfujisanに続いて削除する。

更に追記: テンポラリファイルを調べていて、Zinio と Sonata note も削除する事にした。Sonata note は面白いアプリだと思うのだけども、最近は起動していない。

2010/11/13 追記:Zinioでは、ライブラリのバックアップをスキップする設定が可能になっている。この設定をすると、バックアップが速くなる。

2010年8月28日土曜日

自転車通勤の効果

昨年の五月からはじめて、八月末に鎖骨骨折、今年の四月中ごろ完治。という経過をたどっています。昨年から、今年の四月までは、そんなに体重が落ちませんでした。落ちても、せいぜい二キロ以内。ところが、今年は体質が改善されたためか、六キロほど痩せました。67k前後から61k前後に!体脂肪率も23前後から19ぐらいに!身長が172.5cmぐらいなので、110を引くと62.5。いい傾向です。通勤で片道13キロなんで、一日26キロ走っている勘定になります。体質が改善すると、盆休みと雨続きで、運動しなくても体重が増えません。
自転車通勤していなければ、糖尿病になる可能性が大きかったと、あらためて感じている今日この頃です。通勤時間ですが、慣れると自転車の方が速いです。皆さんも是非、自転車通勤を試してみてください。

2010年8月27日金曜日

Windows の PageSetupDialog ではまる(3)

その1その2、ときて、車輪の開発を行うよりない・・・という結論でしたが、なんとか回避する方法はないものか?
という事で、親ウィンドウと連帯して、ページ設定ダイアログを開きなおすという手法で回避する事にしました。今度は大丈夫です。

 流れは、こんな感じです。
  1. 親ウィンドウに対して、開きなおしをしてほしいフラグを設定する
  2. PrintDialog 中の HDEVMODE をコピーして保管する
  3. PrintDialog 中の HDEVNAMES をコピーして保管する
  4. ::PostMessage( m_hDlg, WM_COMMAND, IDCANCEL, 0 ); する
  5. 親ウィンドウ側の処理で、開きなおししてほしいフラグがあれば、フラグをクリアして、再度、ページ設定ダイアログを開く。その時には PAGESETUPDLG構造体に(2,3)で保管したものを流用する。


 ダイアログをキャンセルしても、プリンタの情報等は更新されてしまいますが、しょうがないところでしょう。キャンセル時の HDEVMODE と HDEVNAME も保管しとくか???

Windows の PageSetupDialog ではまる(2)

結局のところ、PageSetupDlg というコモンコントロールの用紙選択コンボボックスを書き換えるという手法で対応することにしました。
 用紙選択コンボボックスは、Dlgs.h にて cmb2 と定義されています。給紙方法が、cmb3 です。

//
// Combo boxes.
//
#define cmb1 0x0470
#define cmb2 0x0471
#define cmb3 0x0472
#define cmb4 0x0473
...


WTL を使っている場合は、CComboBox を利用して

void CCustomPageSetupDialog::OnInitDialog( HWND hDlg ) {
m_hDlg = hDlg;
m_combo_size.Attach( ::GetDlgItem( hDlg, cmb2 ) );
m_combo_kyusi.Attach( ::GetDlgItem( hDlg, cmb3 ) );
}
void CCustomPageSetupDialog::OnDestroy() {
m_combo_kyusi.Detach();
m_combo_size.Detach();
}

という感じでアタッチできます。
で、プリンタ設定ダイアログを呼び出した直後にプリンタ設定ダイアログの DEVMODE をぱくってきて
以下のような感じで、用紙サイズをシンクロさせます。

void CCustomPageSetupDialog::SyncPaperSize() {
DEVMODE* pDev = GetDevMode();
int n = DeviceCapabilities( (LPCSTR)pDev->dmDeviceName, NULL, DC_PAPERS, NULL, pDev );
struct paper_name { char name_[64]; };
boost::scoped_array<paper_name> pn( new paper_name[ n + 2 ] );
boost::scoped_array<WORD> pi( new WORD[ n + 2 ] );
DeviceCapabilities( (LPCSTR)pDev->dmDeviceName, NULL, DC_PAPERNAMES, (LPSTR)pn.get(), pDev );
DeviceCapabilities( (LPCSTR)pDev->dmDeviceName, NULL, DC_PAPERS, (LPSTR)pi.get(), pDev );
m_combo_size.ResetContent();
for( int i = 0; i < n; ++i ) {
int item = m_combo_size.AddString( pn[i].name_ );
DWORD_PTR siz = pi[i];
m_combo_size.SetItemData( item, siz );
}
// プリンタ設定で選択された用紙を選択
for( int i = 0; i < n; ++i ) {
if( pDev->dmPaperSize == m_combo_size.GetItemData( i ) ) {
m_combo_size.SetCurSel( i );
break;
}
}
GlobalFree( pDev );
}

予想通りというか、dmPaperSize は、コンボボックスのItemDataPtr として保持されていました。
ここは、たぶんドキュメントに記述されていないです。
あほくさ・・・

追記:プリンタ設定ダイアログにてプリンタが変更されている場合、ページ設定ダイアログにて
 用紙サイズを変更した場合の副作用が生じて、ページ設定ダイアログ内のプリンタ情報
(=hDevNames と思われる)をうまく更新しないと、プリンタが元に戻ってしまいます。
 コモンダイアログがプリンタ情報のコピーを使用している場合は、どうにもならないので、
 やはり、車輪の開発で、自前でページ設定ダイアログを作成するほうが良さそうという
 結論にならざるを得ません。

結論:車輪の開発をしないと不可避です。
 PageSetupDlg API がプリンタ情報のコピーを保持しているので、どんなに頑張ってプリンタ情報を
 変更しても、用紙サイズのコンボボックスの値を変更した時点で、DEVMODE構造体が元のプリンタの
 情報に戻されてしまいます。

Windows の PageSetupDialog ではまる

 Windows には、CommonDialog と呼ばれるものが存在します。色の設定、フォントの設定、プリンタの設定、ドキュメントの印刷ページ設定などが、これで行えます。ルック&フィールを統一しようという趣旨で提供されています。
 ある日、PageSetupDialog に存在していた プリンタの選択機能が取り除かれました。Windows Vista からです。糞OS Vista から取り除かれました。
 ドキュメントでは
http://msdn.microsoft.com/ja-jp/library/cc410957.aspx

PrintDlg 関数は、[プリンタの設定]ダイアログボックスを表示することもできます。
しかし、新しいアプリケーションはこの目的で PrintDlg を使うべきではありません。
[プリンタの設定]ダイアログボックスは、PageSetupDlg 関数が作成する
[ページ設定]ダイアログボックスによって置き換えられています。

と、ありますが、こうせざるをえない状況を強いられているのです。

 さて、CommonDialog では、Hook によりハンドラを設定してカスタマイズを行います。
しかし、PageSetupDialog 内のプリンタを変更する手段が用意されていません。もっと言うと、強いられた状況において、プリンタの設定ダイアログで変更された用紙サイズ等の情報を反映させるための手段が用意されていません。つまり、車輪の開発で自前でプリンタを変更する手段を実装しないといけなさそうなんです。
 何故プリンタの設定ボタンが急に無くなったのでしょう?無くなったら、無くなったで代替手段を用意してくれても良さそうなもんですが、完全に隠蔽されていて対処のやりように困ってます。
 残された手段は、コモンダイアログを使わない事。何のためのコモンダイアログなのか、ぼやきまくりっす。

2010年8月26日木曜日

passenger ? mongrel_cluster

まぁ、passenger と mongrel_cluster どちらを使ったらええの?とお悩みの方は多いと思います。
将来性を加味した場合、mongrel_cluster は、もうメンテナンスされてなさそうなんで、先行きは暗いです。しかも、長期に稼働させる事を考えると、定期的にリスタートさせる必要があるでしょう。
今後は、passenger を使うのが主流になるような気がしてます。ただし、現時点では CentOS にて passenger を選択する場合には、SELinux の事はスッパリと諦める覚悟が必要です。ここをクリアできるのは、SELinux マスターの方だけでしょう…。テンポラリ・ファイルを設定して…など…ゴニョゴニョとチャレンジしてみましたが、似非ネットワーク管理者には無理な事でした。
 passenger は、結構簡単に動作させる事ができます。はまりどころは、Rails の public とかに、.ht* 系のファイルが残っていて、mod_rewrite のルールが記述されており、そいつが邪魔をしている。あるいは、environment の指定を httpd の conf ファイルに書き忘れていて、dbに接続できていない。といったあたりになります。

2010/12/03 追記: CentOS Passenger + SELinux 成功例を見つけた。

2010年8月25日水曜日

電子書籍ショップがひでぇ

ZINIOのデフォルト地域がやっと日本になったが、何故か日本だけ選択できない。何かとてつもない陰謀を感じる。iPadユーザには、敷居の高いfujisanは、使えそうもないので削除した。雑誌オンラインでも代用が効くので…。ただ、こいつもカゴの中の雑誌なんで、4冊購入したが、ここで打ち止めにしようと思う。毎回ログインボタンを押すのもうんざりだし、ビュウワを選べないのは致命的。理想書店は、新着本がわからないので、いずれ使い物にならなくなるだろう。こいつのビュウワは、まだ読み易いが、カゴの中の本にかわりはない。楽天ブックス、iPadでリアル書籍を買えってか?
eBook, PDF で電子書籍を販売する予定のアプリがあれば、喜んで乗り換えまっせ!さもなくば、自炊したほうが良い。

仕事でけん

 いや、仕事はしてるのだが、コーディングの方やらをやっている時間がねぇ。ミッション・クリティカルなコードを結構、俺が押さえてるのに、そいつをどうこうする時間がねぇ。

2010年8月24日火曜日

BOOST_SCOPED_ENUM_START

 boost::filesystem::copy_file を使おうと思って、オプションについて調べていたら、


BOOST_SCOPED_ENUM_START(copy_option)
{fail_if_exists, overwrite_if_exists};
BOOST_SCOPED_ENUM_END


という記述にぶち当たった。実は、boost::filesystem::overwrite_if_exists と指定したら、コンパイルエラーで怒られて、えー?じゃ何を指定すればいいんだわさ???となったわけです。

 ご存知のとおり、enum は scope じゃないので、コードを書く上で、いろんなものが、ごっちゃり混ざって美しくない。て訳で、BOOST_SCOPED_ENUM_START -> BOOST_SCOPED_ENUM_END で効率よくスコープ付きの enum を定義しようってことらしい。

boost::filesystem::copy_option::overwrite_if_exists で、めでたくコンパイルも通りました。

2010年8月21日土曜日

カゴの中の本

iPad で本を購入してるが、どいつもこいつもアプリの中に閉じ込められていて、だんだん鬱陶しくなってきた。こんな、使いづらい仕打ちを受けるぐらいなら、新書や中古本を買って自分でスキャンした方がマシだ。
マシだマシだマシだマシだマシだマシだマシだーーーーーーーーーー

2010年8月19日木曜日

boost::filesystem 習作

いやー、ここんところ boost のリリースのタイミングが速い。実は、今まで使用するのを避けていたライブラリがありました。boost::filesystem です。もちろん、Version 3 のような日が来るまでは使えないと思っていたからです。
 と、そんなこんなで、晴れて boost::filesystem を使ってみる事に…。ただの exists に FindFirstFile -> FindClose せんだけでも、随分すっきり書ける。しかし、findfirst に相当する部分が無いようだ。この辺は、path_iterator と range 使ってスマートに書けって事なんだろうか? OSのFileSystemが面倒みるのと、ゴリゴリとフィルタを書くのとどっちがいいんだろう…。


#define BOOST_FILESYSTEM_VERSION 3
#include <iostream>
#include <boost/format.hpp>
#include <boost/filesystem.hpp>
using namespace std;
using namespace boost::filesystem;

namespace {
std::string make_backup_filename( const char* basename, int cnt ) {
return boost::str( boost::format( "%s.%03d" ) % basename % cnt );
}

std::string shift_and_find( const char* basename, int maxcnt ) {
std::string result = make_backup_filename( basename, maxcnt );
boost::filesystem::path p( result );
// バックアップ・カウント分のバックアップが作成されている場合
if( boost::filesystem::exists( p ) ) {
//一番古いファイルは、ベースのファイル名.001
p = make_backup_filename( basename, 1 );
boost::filesystem::remove( p );
// ベースのファイル名.00N (N >= 2) に対して
// Nをデクリメントしたファイル名にする
boost::filesystem::path n;
for( int i = 2; i <= maxcnt; ++i ) {
n = make_backup_filename( basename, i );
if( boost::filesystem::exists( n ) )
boost::filesystem::rename( n, p );
p = n;
}
} else {
// ベースのファイル名.00N (N > 0 && N < backupcount)
// で最大のものを見つける。
for( int i = maxcnt - 1; i > 0; --i ) {
p = make_backup_filename( basename, i );
if( boost::filesystem::exists( p ) ) {
p = make_backup_filename( basename, i + 1 );
break;
}
}
}
return p.generic_string();
}
}

int main(int argc, char* argv[])
{
if (argc < 2)
{
cout << "Usage: bktest basename\n";
return 1;
}

cout << shift_and_find( argv[1], 5 );

return 0;
}

電子障壁その後

せっかくなので、national geographic に、
俺は日本のiPadユーザだ。今世紀ITの世紀なのに、zinio でさえ電子書籍が買えなかった。ペーパーバックの配送なんていらんから、電子書籍の販売について、検討してくれ。
という趣旨の問い合せをしてみたら、
残念ながら、君の地域ではリクエストには応えられない。詳しくはカスタマーサービスに問い合わせてみてくれ。
という感じの返答がきた。何か契約が絡んでるのかも。本家ホームページでの価格も、アメリカ、カナダ、その他で違っていたから、そことの折り合いがつかないのかもしれない。

2010年8月18日水曜日

いろいろ

 まぁ、Pマークの審査が通ったと思ってたら、また二ヶ月以内に審査のための書類を用意しなくてはならない。そして、今抱えてる仕事も重たいので、時間が取れるとも思えない。気分はブルーオーシャンですわ。どないすんねん。iPadで雑誌をちら読みしてたら、ブラックITなる言葉が暗躍していた。
 東京の会社がニアソーシングという言葉と共にパートナー企業を探しに来てたけど、話を聞いた感じでは、単価も納期の相当厳しいと感じた。売上と人数から逆算すると、元請けでも、おそらく現在のうちの会社の受託価格と変わらない。そこを、もう中国とか人件費の安いところでカバーしている感じだ。しかし、外注する仕様書を書くだけでもアホらしい気がする。詳細な仕様書を書いた時点で、既に7割は完成しているだろうからだ。
 日本の受託ソフトウェア産業は、そのうち死ぬような気がしている。予算はありません。期間もありません。だから、だんだんと割に合わなくなって、セット受託しか残らないのでは?と・・・。ここを差別化して生き残った会社は強いんだろうけど、半自動プログラミングでも無ければ無理っぽい。DRY原則程度では、とてもペイできません。要するに、受託に見せかけて受託したら負けという変な状況が理想的。SaaSでプラットフォーム戦略にみんな流れるわけだわ。

 8/16 にフェリーに乗って帰ってきたんだけど、京都では大文字焼きをしていました。大阪育ちなんだけども、生まれてこのかた、大文字焼きなんて全く無縁でした。ただ、見物する時間も取れなくて、かろうじて、電車の中から「大」の字を拝むことができました。これは、これで感慨深いものがありました。

 プログラミングの魔導書 vol 1 のレビューも、ざっとしてみたいところなのだが、コードも交えてレビューする余裕がねぇ。
 Visitor パターンについての雑感(C++で使うと、ひでぇので、もう二度と使いたくない。機能拡張が恐ろしくしんどい)。
 もう少しベタな記事の方が、読者層が広がるのではなかろうか?比較的ベタな記事は、boost::serialization。
 Crowling In the stream 正直、あまり泳ぎたくない場所ゆえに、面白かった。
 Variadic Template は、スペースの問題もあって難しいかもしれないけれども、もう少し動機を書いた方が良い気がしました。つまり、今までは、こんなコードを書いていたんだけども、もうちょっとマシな書き方はねぇのか?と感じた瞬間があると思うのです。ここが無いと、このコードにどんなメリットがあるのか、ピンとこない感じがしました。自分が不勉強なだけかもしれません。
 Oven range cooking は template と延遅評価にもう少し解説があると、もっとオモロかったかも? boost::numeric::ublas など、この辺は割と重要なトピック…てか? 参照を返す at, front, back 馬鹿と鋏は使いよう・・・初心者には、ちょぅと怖い。
 Hello C++ world. ブログで読んでいたので・・・すみません。でもADLの説明はしっくりきたかも?
 メタプログラミング・・・この手のコードは、書いている時に何か変なものに取り憑かれているのだ・・・後から冷静になって「俺は一体何を書いていたんだ?このコードは、一体何をしているんだ?」と首を傾げるのが、たぶん普通の感覚。この記事を読めるのは、ごく少数のような気がしました。
 Chrono ・・・ melpon さんのブログ記事から考えると、おとなしめな感じ。でも、その分、一般向けでわかりやすい感じがしました。
Boost.Asio ・・・ ここは、私も相当突っ込んでるので、なんとも・・・。応援してます。
 BoostCon ・・・ マシンガン質疑応答ディスカッション、怖ぇ~
 ムーブ・コンストラクタ ・・・ この記事のおかげで、rvalue がすっきり爽快。実はコンテナ操作のコピーコストを気にして、ポインタで保持するとか、今まで悩みの種のひとつだった。

 C,C++ はメモリをレイアウトする言語だ。GCなんて言語機能としていらねぇ。ライブラリでも書いてろ。

 iPad で プログラミングの魔導書 vol1 を読むためには、PDFをPDFに変換する必要がありました。私は、iPadで読んでます。


 

2010年8月9日月曜日

盆休み

 iPadで自炊するようになって、1度読んだ事のある本を読み返す事が多くなりました。もちろん新書0という訳でもないです。気に入った本は何回読んでも面白いです。
 ほんとは9日から休みを取って9日間を確保したかったのですが、仕事の都合でダメでした・・・。そんな訳で、水曜日から盆休みです。また、ネットとは無縁の世界になります。印刷物の代わりにPDFに出力したものをiPadに入れて持っていこうと思ったら、iPadにかまけないで盆休みは子供の相手をちゃんとしてほしいと怒られました。そんなつもり無いっちゅうねん。
 個人情報保護管理責任者の仕事とか、勘弁してほしい事だらけです。才能の無駄使いです。あほみたいにやる事があって、休日中もうなされそうです・・・。休日後のいちばんしんどそうな時期に、俺ひとりでプロジェクト担当です。折衝・コーディング・マニュアル・残設計・部分納品・設定・データコンバート・デザイン・インストーラ作成・・・体がいくつあっても足りなさそうです。

2010年8月8日日曜日

公式サイトの情報は、ちゃんと書こうよ

 地球最古の恐竜展に、息子を連れて行きました。
事前に下調べし、
公式サイトの「アクセス」

■[札幌展]
2011年7月2日(土)-8月28日(日)
会  場:北翔クロテック月寒ドーム
主  催:NHK札幌放送局、NHKプラネット北海道、北海道新聞社、財団法人北海道体育文化協会

の記述を信じて、地下鉄福住駅から、月寒ドームまで歩きました。
現場に着くと、トヨタの車の試乗会しかやっていなくて、係員の人に尋ねると「ここで今日は他にイベントなんてやってませんよ?」との事。狐につままれたような気分で、疲れた~という、うちの坊ちゃんを連れて歩いて福住駅に引き返しながら、嫁さんに確認してもらうと、札幌ドームだよ?との返答。

 朝一番(午前5時)にプログラミングの魔道書をダウンロードしようとしたら、ダウンロードできなくて5回ぐらい繰り返してもダメでした。そこで問い合わせたら、akiraさん直々にダウンロードが問題なくできますよという回答をいただいて、同じアカウントとパスワードで、すんなりダウンロードできて、もしかしてメールアドレス5回も(@と.を)打ち間違えたかなーと恐縮していたところに、嫁さんから札幌ドームだよとの返答をもらい、俺の頭が壊れてしまったのか???とも思いました。

 でも、さっき確認したら、会場:北翔クロテック月寒ドームって、書いてあんじゃん。ちょー、頼むよ、公式サイト…。

 追記:よくよく見ると、2011年じゃん… orz 。やっぱ、どうかしてたのは、俺の頭か・・・
本当の公式サイトは、こっちでした。酷い間違い

2010年8月6日金曜日

今回もキツイなー

今回の受注も厳しいのだ…。工期も短ければ、価格も安く、難度も高い。別に、ウェブのシステムだから、特段しんどい訳じゃないとも思う。しかし、社内ではウェブのシステムは、高コストでペイしないという感覚で見られていると感じる。しかし、最近、仕事の芽があるのは、ことごとくウェブの話だ。無理してでも、ここを鍛えないと未来はないだろう。
正直、本音をいえば、なんで他人の面倒を見なきゃならんのだ?という感覚が強い。仕事に対する姿勢が社員とは、違うのでGIGAZINEさんの人材募集の話が身に染みて解る。
それは置いておいて、単価の安すぎる仕事は、お客さんのためにもならないし、会社のためにもならない。こんかいは、ちょっと反省しよう。

2010年8月1日日曜日

電子古本屋

 もしかしたら、法律の方が追いついていないとは思う。中古ゲームも一時期、使用許諾権の問題でもめていたと思う。
 本をスキャンしてて無駄だと思うのが、日本全国中で同じ本をスキャンしている人が何人いるのだろうか?という事である。こういう不毛な作業は、プログラマからしてみれば、時間の浪費に思えてしょうがない。本と引換に、誰かが綺麗にスキャンしてくれた電子本と交換してくれたら、どんなに労力の削減になるだろうか?と、考えてしまうのである。DRY(Don't Repeat Yourself)原則の日本全国版といったところである。
 さて、これが許されるのであれば、実在書籍の破棄証明書を電子的に発行して、既に綺麗にスキャンされた電子本と交換するというビジネスが成立するのではないだろうか?大手の古本屋Bookoffならば、それが可能だろう。リアルな書籍を販売しながら、電子化対応本の場合には、手数料を取って、その場で書籍の破棄と電子本を行うというわけだ。持ち込みの書籍も手数料を取って、電子本と交換なんて事もできるかもしれない。
 スキャン代行業者も、こういうチャンスはあるんだろうけど、書籍を預かるだけなので手元に電子本を置くわけにはいかないのだろう。そもそも、スキャン代行の場合は、本に書き込みされた内容込みで電子化なので、ダメな場合もあるか…

電子障壁

Zinio で national geographic 誌を12ヶ月講読しようと、カ-ドまで入力したのに、あんたの地域では、この本は売れない…と、拒否されてしまった。軍事機密や技術書なら、わかるが、フラットな情報時代に、この時代錯誤感はなんだ?俺が読みたいのは、英語版だ。
アホだろ?ACMで論文だって読める時代だぞ???

2010年7月29日木曜日

rails helper の汚染ふたたび

 ヘルパの汚染が深刻なのである…。
active_scaffold を使っていると、helper にて

def options_for_association_conditions(association)
if association.name == :hoge
['hoge.funya = ?', 1]
elsif association.name == :fuga
['fuga.hoe = ?', 2]
else
super
end
end

なんてコードを書いて、リレーションの選択時に、コントローラで特有のフィルタリングを行ないます。
ところが、こいつも汚染されてしまう…。

 どう対処するか?ヘタレな方法だけども


class ApplicationController < ActionController::Base
before_filter :set_controller_name

def set_controller_name
session[:controller_name] = self.class;
end
end


として、


def options_for_association_conditions(association)
if session[:controller_name] == 'MogeController'
if association.name == :hoge
['hoge.funya = ?', 1]
elsif association.name == :fuga
['fuga.hoe = ?', 2]
else
super
end
else
if association.name == :hoge
['hoge.funya = ?', 2]
elsif association.name == :fuga
['fuga.hoe = ?', 3]
else
super
end
end
end


という指針にしますた。まだ何か落とし穴がありそうな… Object って危ないのねん、好きになれないな…。

2010/8/6 追記: appliction_controller.rb に

helper :all

の文字が…、こんなの知らねーよっ orz...

rails duplicate habtm 二重に多対多備忘録

 Hoges と Fugas が多対多の関係で欲しい場合は、habtm を使えばシンプルに済みます。しかし、この多対多の関係が、もうひとつ欲しい・・・となったとき、?????かなり悩んだ

create table hoges (
id serial primary key,
name varchar(16)
);
create table fugas (
id serial primary key,
name varchar(16)
);
create table fugas_and_hoges (
id serial primary key,
fuga_id integer,
hoge_id integer
);
create table another_fugas_and_hoges (
id serial primary key,
fuga_id integer,
hoge_id integer
);

このようなテーブルに対して

class FugasAndHoge < ActiveRecord::Base
belongs_to :fuga
belongs_to :hoge
end

class AnotherFugasAndHoge < ActiveRecord::Base
belongs_to :fuga
belongs_to :hoge
end

class Fuga < ActiveRecord::Base
has_many :fugas_and_hoges, :dependent => :destroy
has_many :hoges, :through => :fugas_and_hoges, :dependent => :destroy
has_many :another_fugas_and_hoges, :dependent => :destroy
has_many :another_hoges, :source => :hoge, :through => :another_fugas_and_hoges, :dependent => :destroy
end


class Hoge < ActiveRecord::Base
has_many :fugas_and_hoges, :dependent => :destroy
has_many :fugas, :through => :fugas_and_hoges, :dependent => :destroy
has_many :another_fugas_and_hoges, :dependent => :destroy
has_many :another_fugas, :source => :fuga, :through => :another_fugas_and_hoges, :dependent => :destroy
end



 うーむ・・・

2010年7月28日水曜日

iPadのPDFアプリ比較

 はじめにお断りしておきますが、この比較は、独断と偏見によるもので、完全に裏をとったものではありません。また、PDFも書籍をデジタルスキャンしたままの状態で、画像をの集合体というPDFに特化した比較となっています。その点を考慮にいれておいてください。テキストを含むPDFの評価はありません。

 Cloudreaders 1.12, iBooks 1.1.2, Bookman 1.3, FastPDF 1.2, GoodReader 2.8.1, iBunkoHD 1.03 以上が私の持っているPDFアプリです。これらのアプリを系統で分けると
  1. iBooks, iBunkoHD, Cloudreaders
  2. Bookman
  3. GoodReader
  4. FastPDF

になります。
 iBooks 等は、Apple が提供する PDFライブラリを駆使すると思われるもの
 Bookman は、ページ毎にPDF内のObjectタグから直接画像を処理して適切な解像度の画像を生成するもの
 GoodReader, FastPDF は、独自のPDFライブラリを駆使すると思われるもの

いきなり結論から言うと、A5版までの文字が極端に細かくない書籍を読むのに最適なアプリは、Bookman がダントツでしょう。インデックス用のサムネイル画像と、表示用の画像を事前に生成していると思われます。Bookmanの動作推定根拠は、一定以上は拡大しても解像度が固定のままであるし、ページの回転情報を無視して生の画像からページを生成しているので、PDFが指定する画像の向きと異なる表示になる事がある点です。これに見開きページの偶奇と、左右読み方向の設定に対応してくれれば、もう思い残すことはありません。それぐらい快適です。一般的な本を読むのに、Bookmanを愛用してます。

 どんなに重たい画像がきても落ちる事なく安定している凄アプリは、GoodReaderです。安定度No1と言えます。高解像度のカラー画像本(600Mにも及ぶ)を、いろいろなアプリで開きましたが、落ちなかったのは、GoodReaderとBookmanだけでした。他のアプリは落ちまくりです。Bookmanは、画像処理をやってしまうので落ちません。GoodReaderは、拡大した範囲しか画像を展開しないので落ちません。よって、困ったPDFは全部GoodReaderで開いとけば安心です。GoodReaderでは、解像度の変更もできます。<-Resizeというフォルダがインデックス化されているのを見て勘違いしてた。解像度の変更まではできません。

 さて、それでは、やや重たい程度の節度ある画像が含まれるPDFを読むのに適したアプリは?というと、FastPDFという事になるでしょうか…。正直、どれも決定打に欠けるのですが、適度な解像度をキープしてくれるのと、ストレスが少ない点が評価のポイントです。 結構、落ちるので、GoodReader 以外に選択肢は無し。

 iBooksは、eBookと同様にサムネイルを展開するので良いのですが、いかんせん、まともな解像度で表示されるまでの時間が長すぎて使い物になりません。iBunkoHDは、いろいろと裏技を駆使して落ちないように努力されているみたいなのですが、おかげで準備が整うまでページをめくる事ができないという現象が出てしまいます。

 画像ではないPDFは、評価の対象ではありませんが、iBooksはサムネイル対応あり、iBunkoHDは左右読み方向と見開き偶奇に対応ありで、一歩抜きん出ていると言えるかもしれません。




数学本などのスキャンでは神経質に1200dpiとかでスキャンしていますが、将来的には、これぐらいの解像度が当たり前な時代になるかもしれません。それまでの繋ぎとして、どうやって低解像度のPDFを効率よく生成するか?Windows限定な方法となりますが、画像梱包で画像を展開し、リサイズ超簡単プロ!で画像解像度を%指定で落とします。最後に、画像梱包でResizeフォルダを指定してPDFを復元します。

2010/8/2 追記: モノクロ画像だとカラー画像に変換されてしまうので、圧縮後のサイズが余計に大きくなってしまう…カラーPDFにしか使えない技だった…。しかも、ScanSnapの文字傾きの訂正とかは、読み取った後の画像に対してPDF的に回転角度を指定しているだけで、画像自体には、ちっとも手を入れていない。そのため、画像にバラした後は、向きを手動で訂正しなければならない。だいたい、PDFで画像を回転するという事は、それだけPDFでの表示が遅くなるという事だ。もう読み取り速度が遅くなっても、今後は縦方向スキャンしかしないし、文字の傾き訂正機能も使わないようにしようと思う。驚いた事に、角度は90度だけでなく、数度単位で回転を指定している場合もあった。頁の余白がなくて急に写真が出現する場合は、10度程度、頁が傾いてしまう事があるが、取り出した画像には傾きは見られなかった。空白を削除するのも、やめておいた方がいいだろうと思う。レイアウトが崩れるし、後で処理に困るからだ…。いやー、イラつく…。時間なんて全然無いのに、生産消費者の道を進めとの声が聞こえてきそうである…。

 Enjoy 自炊ライフ!

2010/8/1 追記: FastPDF は、結構な頻度で落ちる。おすすめは撤回した。
2010/8/29 追記:この後、FastPDF, GoodReader, iBunkoHDのバージョンアップが行われた。FastPDF は安定度が増したように思う。iBunkoHD は、大幅改修されてオールマイティに利用できる感じになった。どれも甲乙つけ難い。ポイントだけ列挙すると、FastPDF は、見開きにした時に1頁だけズラせる事ができるので、偶奇・奇偶とどんなタイプの見開きも見れるように調整できる点が良い。GoodReader のクリッピング領域を固定しながら頁をめくる機能が、かなり重宝される。余白の多いPDFでは、これが無いと読みにくい。iBunkoHDは、欠点が見当たらなくなってしまった。

 ところで、iPad では、写真フォルダを他のアプリから閲覧できるのだが、本に対しても同じような事ができないものなのだろうか?アプリに閉じ込められた本というのは、正直、取扱い辛い

2010/9/6 追記:Bookman のバージョンが上がって、死角がほとんど無くなってしまった。自炊に関しては、正直Bookman一本で良いと思う。ウェブからダウンロードするPDF用にはGoodReader、気分でソツない iBunkoHDをチョイス。といった所で落ち着いてしまいました。

2010/11/13 追記:グレースケールの大型本は、GoodReaderで読むようにしている。とにかく、Bookman, GoodReader の2大アプリさまさまだ。

2010年7月27日火曜日

今度はwindows7が止まる

でかいファイルをドラッグドロップすると、いちいちCOM Surrogateを経由するので、メモリが足りなくなって、反応しなくなる。タスクマネージャも反応しなくなるので、何もできずに30分以上見守るしかない。カーネルは何のためにあるのか?糞だろ。
素直にファイル名だけ渡せよ、あほか?
また、強制電源オフの悪夢がはじまるのか?
Oh no! The nightmare begins again.

2010年7月25日日曜日

自炊は続く

ここんところ、スキャンに勤しみ、本と対話の日々なのだ。iPadのbook系アプリの違いも見えてきた。モノクロ1200dpi相当と言うのは、ちょっとやりすぎで、実はぼやけて見えるのもアプリのせいだと言う事がわかった。へたれなことに、Windows上でのPDFレビューも、あまり良くないようだ。ただし、これはディスプレイの環境に依存しそうである。こんなところ(ディスプレイの表現力)にもアップルのデザイン力を強く感じる。
あとで、book系アプリの特色をまとめることにしよう。同じPDFを扱っていても、こうも違うものなのかと感心します。

2010年7月17日土曜日

iPadユーザには敷居の高いfujisan

Fujisanという書籍アプリがでていて、インストールしてみたが、ログインしないと使えない。なんだこれは?速攻アンインストールしようかと思ったが、猶予を与えておくことにした。アプリの、トップページにあるfujisanのロゴがリンクになって無いのも痛い。そして、苦労してfujisanのページに行ってもアカウントの作成方法が全くもってわからないのも痛い。極めつけは、ちょい読み機能がflashなのか、iPadユーザさまお断りで救いようがない。

2010年7月15日木曜日

CentOSでutvpnserverをサービス化

 お客さんからutvpnserverを使いたいという要望があったので、サービスで自動起動できるようにする必要があった。しょうがないので書いてみた。正直シェルスクリプトを書く機会は滅多に無いので自信がない・・・。${HOGE[@]: -1} とかで、最後の文字列が取れればビューティフルなんだけど、最後のキャラクタしかとれなかったので、ループを回す事に・・・。ま、出現位置が変わっても対応できるから、こっちの方が良いだろうと納得する事にした。

#!/bin/bash
#
# utvpnd Startup script for the utvpn Server
#

### BEGIN INIT INFO
# chkconfig: 345 88 16
# Default-Start: 3 5
# Deafult-Stop: 0 1 2 6
# Required-Start: $network $syslog sshd
# Required-Stop:
# description: utvpn server.
# processname: utvpnserver
# pidfile: -------------------- /var/run/utvpn.pid
### END INIT INFO

UTVPNSETUP=/usr/bin/utvpnserver

case "$1" in
start)
${UTVPNSETUP} start

;;

status)
PLIST=`ps -C utvpnserver | tail -n 1`
running=false
for i in ${PLIST}
do
if [ "utvpnserver" = $i ]; then
running=true
fi
done
if [ $running = true ]; then
echo "utvpnserver is running"
else
echo "tuvpnserver is stopped"
fi
;;

stop)
${UTVPNSETUP} stop
;;
*)
echo "Usage: /etc/init.d/utvpnd {start|stop|status}"
exit 1
;;
esac

exit 0

こいつを、/etc/init.d/ 下にコピーして

$ chmod 755 /etc/init.d/utvpnd
$ chcon system_u:object_r:initrc_exec_t /etc/init.d/utvpnd
$ chkconfig --add utvpnd
$ chkconfig utvpnd on

といったあたりで、OKだろう。動作確認は

$ service utvpnd start
$ service utvpnd status
$ service utvpnd stop
$ service utvpnd status

って感じです。

2010年7月11日日曜日

数学本のスキャン

 いやー、苦痛です。モノクロ600dpi相当でスキャンして、これはいけてると思ってました。ところが、いざiPadで読んでみると、添字の添字やら、ギリシャ文字系μ等の記号がわからない…。結局、モノクロ1200dpi相当でスキャンするよりありません。ものすごい時間がかかります。
 1200dpiで読もうと思ったら、横向きにスキャンしないと時間がかかってしょうがありません。横向きにスキャンしたら、裏表の向きが反対になってしまうんです。90度回転しても、奇数ページと偶数ページで逆向きになってしまいます。白紙ページを削除する…なんてやってたら、偶奇入り乱れるので、機械的に回転処理ができません。漫画をスキャンする時は、向きがグチャグチャになるので、スキャンした本の自動回転をオフにしていました。しかし、数学本を読む時は、横向きで、自動回転をオンにして1200dpiのモノクロでスキャンしてます。

2010年7月10日土曜日

自炊が気持ちイイ

 いやー、本の自炊、いいです。電子化してみると、いろんな事が見えてきました。

 まず、スキャンすべきか?せざるべきか?それが問題だ!
本を切り刻むという事は、元に戻せません。また、中途半端にスキャンしてから、切り刻んだ本を捨てると、再スキャンができません。例えば、微妙に写真の混ざっている本なんかだと、モノクロ2値スキャンではなく、グレースケールにすべきか?400dpi相当で留めておくべきか?600dpi相当まで上げるべきか?選択子は山のようにあって、決断を迫られます。そうやって、スキャンする本の値踏みを迫られる訳です。こうして、ああ、俺は、この本にこれぐらいの愛着を持っていたんだ…と、スキャンする過程で気付かされます。

 本棚から本を探して引っ張り出すコストの高さに愕然とする。
スキャンした本なんて読まないよー。と思っている方も多い事だと思います。しかし、逆でした。恐らく、この逆転現象が現れるのは、好きな部類の本だと思います。まだ、スキャンはじめて日が浅いので、自分でも良くわかっていないところがあります。例えば、HUNTERxHUNTER…正直、本棚に眠っていました。本来、全巻読もうと思ったら、両手に抱えて本を運んで山積みし、読まなければならないところ。それが、iPadの中に全部収まってしまうと、サクッと読めてしまいます。そして、拷問のように重たく大きい技術書…。えーっ?サクッと取り出せてしまいます。気が向けば、すぐに見れる。思い立ったが吉日です。これはほんとに敷居が低い。

 スペースが空いて楽しい
スキャンした後に、広がっていくスペース。いやー、もう、Space, the final frontiea... っす。楽しい。

2010年7月8日木曜日

activescaffold controller is nested call?

コントローラが、nested つまり、親コントローラの入れ子コントローラとして動作しているかどうかを判定したい…。こんな簡単そうな事が、意外と難しい。なんでもかんでも隠蔽しすぎているからだ。それだけ、activescaffold の完成度が高いとも言えるのだが…。

answer


<% if params[:parent_model] != nil -%>
...
<% end -%>


もちろん、コントローラ内でも使えます。

自炊開始

ついに裁断機が来ました!さっそくスキャン開始!手始めに、どうでもよさそうなドラッガー本を練習台にしました。縦にスキャンした方が、紙詰まりしにくい感じです。
続いてHUNTERxHUNTERをスキャン。紙質がしょぼいので、白が多いページは、裏が薄らと写りこんでいます。でも、上々!一冊五分ちょいでスキャンできました。
IPad のアプリですが、Bookman が熱いです。チェックだ!
そうそう、iPadのアプリを作成する方、ファイル数が多いと同期に時間がかかるので、少なくする努力をして下さい。でないと、せっかくのアプリも台無しです。そういうアプリはユーザに削除される可能性があります。

2010年7月6日火曜日

デジタル化は、ババか?

ディズニーやら過去の作品の著作権が切れて、ワンコインやツーコインで、DVDが売られていたりします。宝島社から、バグズバニーが、出ていて、買いました。だいぶ前の話です。ふと、DVDを眺めていると、このDVDは、無断で上映したり複製することができません…と、書いてあり混乱しました。著作権が切れてるから、こうして安価で売っているのでは?
しばらく考えて、字幕に著作権でもあるのだろう…という結論に達しました。何という、商魂たくましい戦略!なけてきました。
理想書店も、いっこうに品揃えが増える気配がありません。出版社に期待した自分が馬鹿でした。自分の業界ソフトウエア産業同用の道を辿るリスクを冒す必要は無いでしょう。せいぜいババをつかまないよう頑張ってほしいものです。
ブックスキャナと裁断機買いました。現在、裁断機の到着まちです。試しで少年ジャンプのブリーチだけ、スキャンしてみました。ハサミで適当にフリーハンドで切ったのに、感動的なスキャン速度と仕上りでした。ふと、毎号週刊誌を買っている人は、コミックの単行本を買わなくても良い気がしてきました。買いのがした分だけ部分買いするとか?恐ろしい…。デジタル化は、やっぱ怖いです。

追記:もしかしたら、著作権は、まだ切れていなくて、切れる寸前なのかもしれない…。

2010年6月27日日曜日

Windows で SSID 取得

 といっても、ググってこちらをまんま実行してみただけ…。うーむ・・・この時間帯だと取得できるSSIDは、自分のとこの無線LANだけ…。今度、引越しするか無線LANを持ち運んだときに、どのような結果がでるのか追試してみたくなってきた。こういう時車が無いの痛いなぁー。いつになるかわかんねぇけど、嫁さんの実家に無線LAN運んでみよっと…。GPSユニットって、今時なら安いだろうに…、なんでiPadの3G版にしか付いてないんじゃ???質問したら「人は1日に10時間も本を読まない」と同様に「Wifiだけの人は、iPadを持ち運んだりしない」って、ぶちきれられるのか?

iPad ケース

 自分のライフスタイルだと、低反発3Dメッシュケース(青(黒)が、ベストだと思ってチョイスしました。生のまんま使うので十分だけど、持ち運びには気をつけたい…。さすがに自転車のリアケースで運ぶ勇気は無いですが…。

Google map の位置検索

嫁さんの実家からだと、無線LANのSSIDから、現在位置が算出できない。という事は、ストリートカーで、収集したSSIDから位置情報を割り出しているのかもしれない。便利さとプライバシーはトレードオフの関係にあり、今後は、こういう問題に対して考慮する必要がありそうだ。さっき気がついたけど、iPadだと、ストリートビューが見れない。メモリが少ないので、大量の画像を扱うと、重くて使い物にならないのかも…

WZR2-G300NとiPad

いやー、ひでーな。無線LANの接続は出来るけど、しばらくすると切断されて、ネットに繋がらなくなる。不安定なんで、Biosのバージョンを上げてみたけど、改善されない。AOSSは使うな?ってこと?
嫁さんの実家の環境だけど、しょうがないから接続を2つ作成して、繋がらなくなったら、交互に切り替えてます。DHCPの更新では解決しない。g/nは、もうドラフトじゃなくなったはずだ。へたれすぎだろ。

楽天は?

今ごろ、楽天の英語公用語について、憶測してみるテスト。何となく、楽天はアマゾンのポジションを狙っている気がします。完全に同じものを目指しても、勝ち目は無いので、今のスタイルを世界展開して、winnerの地位を固めにいこうってところでしょうか。サムソン電子では、その国の文化を理解するために、専任者を置いていると聞きます。今のスタイルで勝負するなら、そういうデザイン力も必要かもしれません。

2010年6月26日土曜日

iPad つらつらと

 計ったように、「断言」と「決断」を買っていなかったので、理想書店にて購入しました。価格は、もう少し高くても大丈夫だと思います。iPad,iPhoneのアプリを作った事が無いので、カチンとくるかもしれませんが、理想書店のアプリを使って購入してみて、改善してほしいと思ったところをあげてみます。
  • アプリを再起動した時に前回の状態を記憶していてほしい。
  • 決済カードの記録日数180日は控えめすぎでは?
  • アフィリエイト・プログラムが欲しい(ここ、まじ重要だと思う。ネットで商売すんだろ?)
  • DLボタンの他に、全てダウンロードが欲しい
  • ショップの1頁に表示される書籍数を多くしてほしい(今のスペースの半分で十分)


といった感じです。

 規格書や、akiraさんが訳してくれたPDFなんかを読むために、GoodReader を購入しました。今まで、仕事上、どうしても読まないといけないPDFは印刷していたのですが、まんま読めるのは楽ちんです。つか、印刷しないと読む気になれない障壁が取っ払われたのは大きい。

 変わった無料アプリ、
 Molecules : 分子構造を眺めるアプリ、化学は苦手でサッパリわかりませんが、眺めていると楽しいです。スポーツ飲料などの成分表に書かれているアラニンとかを検索ダウンロードして、ホホーッと、意味もわからず唸ってます…なんじゃそりゃ?
 3D Sun : 太陽の活動をニュースでお届けするアプリ。うぉーっ、コロナたん萌してます。(たまに落ちます)

2010年6月25日金曜日

ぼやきまくる

 Rails の polymorphic association を調べていて、rails では クラスを継承できるから…うんぬんの記述を見つけた。冗談でしょ? foo_controller を継承して、bar_controller を作成した事がありますが、production 環境で、既に生成されたクラスを検索する時に bar_controller が foo_controller として表示されてしまうという酷い目にあいました。なんじゃこれ…?全然ダメじゃん…?と、ぼやきながら、継承を避けて DRY の原則を曲げて、泣く泣くコピペ・コーディングしました。
 Activescaffold の subform における更新も変です。昨日は、この問題を追っていましたが、簡単には解決できず、template オーバーライドで
_hoge_form_column.html.erb

<div>
<%= render :active_scaffold => "hoges", :constraints => { :fuga_id => @record.id }
-%>
</div>

解決しました。
そうでもしないと、has_many の関連レコードが、全部削除して、全部挿入されてしまいます。モデルで

:has_many => hoges, :dependent => :destroy

と指定しない場合には、全部削除の代わりに全部リンクが外され(fuga_id に nil がセットされる)、どんどんとレコードが増え続けます。仮に hoge モデルに対して belongs_to を指定しているモデルがあった場合には、どうするつもりなんでしょうか? ticket 353 の事ですが、habtm が前提となって書かれている気がします。enumlator と yield の嵐で、自己完結的に記述されていて、修正は難しいように感じました。ここは、バグの巣窟です。コントローラにて config.columns[:hoges].show_blank_record = false を指定すると、ここでは最後の1レコードが永遠に削除できません。逆に blank_record を表示するようにした場合、hoge の初期値に何かを設定すると、record.unsaved = true が働いてしまい。fuga 更新時には勝手に hoge のレコードが挿入されてしまいます。

2010年6月23日水曜日

Javascript は好きになれないのな

 いやー、今まで、こんなに突っ込んだ事無かったから、勉強になったのな。推測に過ぎないので、これから書く事は間違っているかもしれないです。

 今回は、ダイアログを出すのに jqModal を使ってるんですが、こいつの中身は ajax でバンバン書き換えるから、1ページにつき、1つしか用意してないわけなんです。iframe を使わないで済むのも気に入ってるところです。

 コードを書いていて、ダイアログを表示して、ウィザード・ページのように状態遷移する度に自己書き換えを ajax で行っていました。ところが、javascript の関数だけが更新されない…。???一体何が???

 冷静に考えてみれば、javascript は DOM 要素じゃないんで、例え inner html ごとゴッソリ入れ替えしても、消えないかもしんないわけです。やや思い悩んだ末に、プレスホルダを利用する事にしました。グローバルに変数定義しておいて、

<javascript defer='defer' type='text/javascript'>
$(function() {
$.hoge_holder = function() { ... }
$.fuga_holder = function() { ... }
});
</javascript>

というように、プレスホルダを更新するという訳です。これなら、だらだらとコードが無尽蔵に追加される訳じゃない。

 話は変わって、jQuery のセレクタで

$('input:name=[hoge]')

みたいにしてたんですが、rails で出力された select要素は、input type='select' ではなく select なわけです。これが、input に該当しないので、また、ハマりました。クソがーーーーーと、怒りながら

$('input:name=[hoge],select:name=[hoge]')

対応したわけなんですが、やっぱ、javascript はどうにも好きになれないかも…。ま、javascript が悪いのか、DOM が悪いのか?

 もひとつ、前々から気に入らないと思っている事があります。DOM要素に属性があり、要素の種類により属性が異なってきます。しかし、javascript 的に見れば、どんなプロパティを追加しようが、それは勝手な話。foo.name が属性なのか、プロパティなのか?ここらへんの感覚にアホ臭さを感じてしまいます。

2010年6月21日月曜日

本の自炊を考えてます

 まぁ、一度読んだ本を読む事は、稀です。ただし、技術書を除く。一度読んだ本を自炊(裁断+スキャンによる電子本化)して、次に読む事は無いでしょう。そう思います。しかし、結婚してから捨てた本は山のようにあります。OpenGL APIリファレンスなんて、一度捨てて、会社で買い直したりしてます。毎回、大掃除の度に聞かれるのが、「この本、いるの?」もう、こっちは譲歩して譲歩して本丸の堀まで埋めて本を残しているのに、これを聞かれるとイラッときてブチッと切れそうになります。
 よほどの豪邸に住むか、倉庫を借りてでも置くかしないと、一般の感覚では、本を置くスペースが足りなくなるでしょう。技術書に関して言えば、8割は枯れて使えない内容となりますが、後で見直したくなるものも多いです。もう、この本を見直す事は無いですが、「トランザクション処理(上)」「トランザクション処理(下)」のブタ本・・・割れてセロハンテープで止めまくりだけど、こいつを電子化したら、さぞかし気分もスカッとする事だろう。
 自炊できない本は、見開きページのある本とか、立体絵本「不思議の国のアリス」とか、巨大見開きの「妖怪の森」とか、まぁ、少数な気がします。

 ま、自炊して負けるとか勝つとかじゃなく、家では切実な問題なんです。

 昼に社長と、これからの本屋はどうする?って、話題になりました。この際だから、本屋もアプリを出して、本屋まで足を運んで電子書籍を買った人には、割引サービスをするとか、アミューズメント式でイベントを開催して電子書籍を売るとか、とにかく本屋まで足を運んで購入してくれた人に、何かサービスをするビジネスモデルなんてどう?って盛り上がりました。本屋での決済は、bluetooth とかで決済するんですよ。ここがミソ。価格を下げるだけでなく、マクドナルドみたいにドラクエのミニ・イベントがオマケになったっていいじゃないですか?出版社と共同で、本屋で電子書籍を買った人には、第0章が付いてきたっていいじゃないですか?って…

えこりん村

日曜日には、えこりん村に行ってきました。びっくりドンキーで有名?なアレフの運営する庭園です。まぁ、ガーデニングが似合うと言ったら、日本においては北海道しかないでしょう(ほんとか?)。正直、ガーデニング?はぁ?だったんですが、ここに足を運んでからは、認識が変わりました。なかなか楽しい世界です。すっかり、リピータと化してます…

















2010年6月19日土曜日

iPad を使って感じた事

 そろそろ iPad 単体での使い方に慣れてきたところです。基本的に、まだ家でしか使っていません。感想を…

有料アプリは、よほどの事が無い限り買いません。悩んだ挙句に買った有料アプリは、3つ(セコっ)。

Magic Piano(とりあえず最初にiPadらしそうな安いアプリを…という事でゲットしました), i文庫HD(ちょい高いのでは?とも思いましたが、サーバを用意したりPDFに加工したり、その他の手間や維持費を考えると妥当な線なのかもしれません), MagicWindow(少ない記憶容量でどう見せるか?が勉強になりました)です。Gravitarium は無料の時にゲットしました(気持ちがいいです)。これぐらいなら、すぐ書けそうな気がしている自分が怖いです…実際に書いてみると苦労が絶えなさそう…。

 売切型のアプリで、クラウド・インフラを提供しているものが多いです。これらのアプリは、どうやってサーバ側の維持費を捻出するのでしょうか?とても疑問に思います。

 adMob のアプリも幾つか使ってみました。しかし、自分の性分には合わなくて、割とすぐに削除しています。原因は、アプリを中断してブラウザが開いたり、AppStore が開いたりするからです。adMob は、よほどスマートに組み込むか、アプリの完成度が高くないと、やっていけないと思います。例えば、無料雑誌中の広告記事として組み込み、クリックされても直ぐに飛ばないで、飛んでいいかどうかを聞くぐらいの慎重さが必要でしょう。

 GoogleEarth、iPad に対応したのは良いとして、iPhone 版には実装されていた SSIDを使った位置情報算出ルーチンが無くなってます。Wifiで使えないので、実装し直して下さい。お願いです。

 Bloomberg 凄いです。何故これが無料なのか?このアプリから使用されるトラフィックを解析して、株式市場で一儲けでも企んでいるのだろうか???と、想像が膨らんでしまいます。

 Beatwave(適当にやっても音楽になるので感動です。オプションで音源を売るビジネスモデルのようですが、このビジネスモデルはどうなんでしょ?), Soundrop Free(これも楽しいです。ついつい起動してしまうアプリです), Backgrounds, Sudoku Tablet, ExploreFlickr, neuNotes, 30min.ランチ あたりが気にいってます。一応 Dropbox, SugarSync, Evernote も入れました。Google の音声検索も、なかなかイケテます。そら案内も、素早く天気がチェックできるので重宝してます。

 CD59枚取り込んで力尽きました…まだまだ残ってますorz... YouTube とかも全然見なかったのですが、iPad だと見る機会が増えました。JeffBeck の A day in the life. とか、Steve vai の Tender Surrender とか見て感動しますた…こんなの見てたら廃人になってしまうので、そこそこのところでやめるようにしてます。

 電子書籍の話にいきましょ…

 まぁ、iBook や Kindle のストアの味気ない事といったら…。ここからどうやって本を探せというのか?画一的な表紙が揃っていて玉石混合、多分 S/N 比が既に低い。こういう一般のものは、SNS的なカテゴリで分類した方が幸せになれるかも?と思いました。SNS的な要素も絡めて、リコメンデーションできれば強い。今後は、良い本に出会うために自分が読んできた本を登録して積極的にリコメンデーションできるようなクラウド・サービスが必要とされているようにも感じます。この役割は Google が担うべきでしょう。情報を収集すると共に、同意が得られればOpenIDでショップ側にも情報を提供する仕組みが欲しいです。

 日本の出版社は縦割りですよね?同じ構造のアプリを幾つもインストールさせられて、本を買うために「アカウントを作成して下さい」ときたもんだ。どうすんのコレ?確かに、iBook で売るのは賢いやり方では無いにしても、ユーザ側の立場で考えてサービスできないもんですかね?そして値段が恐ろしく高い。デジタル媒体ですよ???馬鹿にしてんの???
 Zinio で National Geographic を年間購読するのにかかる費用は $16.50、1冊だと $5.99 です。もう、この差がなんとも言えずガックシきます…。

 UIについても思うところがありました。立ち読みでデータ量を少なくしてボカシて見せて一石二鳥と思ってるかもしれませんが、ボケボケの画像見ても、あっそう?じゃーね?というのが正直な感想です。ただし、この流れるようなパラパラ見のUIは結構好きです。実物の本のようにパラパラめくって見せる必要は無いんだなぁ?と感心しました。一枚づつ指でめくる動作ですが、正直疲れます。パネルの決まった場所を持ったままiPadを少し傾けるとページがめくれるとか、2箇所の決まった場所を持ったまま傾けるとパラパラめくりになるとか、もうちょい工夫の余地があるように思います。片手しか使えない人のためにもUIを考えといた方がいいのかもしれません。

 と、まぁ、今のところは、こんな感じです。

2010年6月18日金曜日

activescaffold の subgroup をタブ化してみる(期待しないで)

あんましオススメできないかもしれないけど、一応、力入れて改造したのを、お披露目です。
activescaffold にて、全てのカラムが add_subgroup されている場合には、タブページのレイアウトにするというものです。jquery を使っているので、要注意です。 subgroup 名が 'main' の場合に限り、タブから脱出させて常に表示するよう配慮しました。

application.html.erb にて

<%= stylesheet_link_tag 'jquery-ui-1.8.1.custom', :media => 'all' %>
<%= javascript_include_tag "jquery-1.4.2.min.js" %>
<script type="text/javascript">
jQuery.noConflict();
var j$ = jQuery;
</script>
<%= javascript_include_tag "jquery-ui-1.8.1.custom.min.js" %>



lib/active_scaffold/helpers/id_helper.rb
追加

def tab_form_id(options = {})
options[:action] ||= params[:action]
options[:id] ||= params[:id]
options[:id] ||= params[:parent_id]
clean_id "#{controller_id}-#{options[:action]}-#{options[:id]}-tabform"
end

def tab_form_panel_id(column,options = {})
options[:action] ||= params[:action]
options[:id] ||= params[:id]
options[:id] ||= params[:parent_id]
clean_id "#{controller_id}-#{options[:action]}-#{options[:id]}-#{column.label}-tabform"
end



lib/active_scaffold/helpers/form_column_helper.rb

def override_tab_form_partial?(column)
path, partial_name = partial_pieces(override_tab_form_partial(column))
template_exists?(File.join(path, "_#{partial_name}"), true)
end

# the naming convention for overriding tab form with partials
def override_tab_form_partial(column)
"#{column.label}_tab_form"
end

def tab_form_partial_for_column(column)
if override_tab_form_partial?(column)
override_tab_form_partial(column)
else
"tab_form"
end
end



従来の_form.html.erb が _tab_form.html.erb になります。
frontends/default/views/_form.html.erb

<%
# 全ての column が、add_subgroup されているかどうかで、処理を切り替える
is_tabbed = true
columns.each :for => @record do |column|
if not is_subsection? column
is_tabbed = false;
break;
end
end
-%>
<% if is_tabbed -%>
<% columns.each :for => @record do |column| -%>
<% if column.label == 'main' %>
<div class="tab-form" id="<%= tab_form_panel_id(column) %>">
<% if !override_tab_form_partial?(column) -%>
<%= render :partial => 'tab_form', :locals => { :columns => column } %>
<% end -%>
</div>
<br clear="all" />
<% end -%>
<% end -%>
<script type="text/javascript">
j$(function(){
j$("#<%= tab_form_id %>").tabs();
});
</script>
<div id="<%= tab_form_id %>" class="form" <%= 'style="display: none;"' if columns.collapsed -%>>
<ul>
<% columns.each :for => @record do |column| -%>
<% if column.label != 'main' -%>
<li class="tab-form"><a href="#<%= tab_form_panel_id(column) %>"><%= t column.label %></a></li>
<% end -%>
<% end -%>
</ul>
<% columns.each :for => @record do |column| -%>
<% if column.label != 'main' -%>
<div class="tab-form" id="<%= tab_form_panel_id(column) %>">
<%= render :partial => tab_form_partial_for_column(column), :locals => { :columns => column } %>
</div>
<% end -%>
<% end -%>
</div>
<% else -%>
<%= render :partial => 'tab_form', :locals => { :columns => columns } %>
<% end -%>



frontends/default/views/_tab_form.html.erb

<ol class="form" <%= 'style="display: none;"' if columns.collapsed -%>>
<% columns.each :for => @record do |column| -%>
<% if is_subsection? column -%>
<li class="sub-section">
<h5><%= column.label %> (<%= link_to_visibility_toggle(:default_visible => !column.collapsed) -%>)</h5>
<%= render :partial => 'form', :locals => { :columns => column } %>
</li>
<% elsif is_subform? column and !override_form_field?(column) -%>
<li class="sub-form <%= active_scaffold_config_for(column.association.klass).subform.layout %>-sub-form <%= column.css_class unless column.css_class.nil? %>" id="<%= sub_form_id(:association => column.name) %>">
<%= render :partial => form_partial_for_column(column), :locals => { :column => column } -%>
</li>
<% else -%>
<li class="form-element <%= 'required' if column.required? %> <%= column.css_class unless column.css_class.nil? %>">
<%= render :partial => form_partial_for_column(column), :locals => { :column => column } -%>
</li>
<% end -%>
<% end -%>
</ol>


 ちょい実装してから、時間が経過しているので、ここにポストした改造箇所が足りてるかどうか不安…。あんまし期待しないで…。
 他にも、Java の absolute layout よろしく <table> レイアウトで、各 column のプロパティから、レイアウトを決定するような改造もしてみたのだけれども…。これもどうなのかな…?

FormHelper の汚染に対応(2)

 FormHelperの汚染に対応の続きです。
 前回のやり方だと、デフォルトの動作と切り替えるのが困難なので、activescaffold に新たにオーバーライドするかどうかをチェックするためのヘルパを加えてみました。

lib/active_scaffold/helpers/form_column_helpers.rb です。
まず下準備としてメソッドを追加します。

def override_form_field_will_do?(column)
respond_to?(override_form_field_will_do(column))
end

def override_form_field_will_do(column)
"#{column.name}_form_column_will_do"
end

次に、active_scaffold_input_for を改造します

module FormColumnHelpers
# This method decides which input to use for the given column.
# It does not do any rendering. It only decides which method is responsible for rendering.
def active_scaffold_input_for(column, scope = nil, options = {})
begin
will_do = true
options = active_scaffold_input_options(column, scope, options)
options = javascript_for_update_column(column, scope, options)
# prepare, check if form_field will be override?
if override_form_field_will_do?(column)
will_do = send(override_form_field_will_do(column), @record, options)
end
# first, check if the dev has created an override for this specific field
if will_do and override_form_field?(column)
send(override_form_field(column), @record, options)
# second, check if the dev has specified a valid form_ui for this column
elsif column.form_ui and override_input?(column.form_ui)
send(override_input(column.form_ui), column, options)
# fallback: we get to make the decision
else
....


同様に list_column_helper.rb も改造します

module ListColumnHelpers
def get_column_value(record, column)
begin
will_do = true
if column_override_will_do? column
will_do = send(column_override_will_do(column), record)
end
# check for an override helper
value = if will_do and column_override? column
......


def column_override_will_do(column)
"#{column.name.to_s.gsub('?', '')}_column_will_do"
# parse out any question marks (see issue 227)
end

def column_override_will_do?(column)
respond_to?(column_override_will_do(column))
end




 これで、FormHelper にて



def name_column_will_do
record.is_a? Customer
end

def name_column(record)
"<a href='mailto:" + record[:email_address].to_s + "'>" + record[:name].to_s + "</a>";
end



と、汚染に対する耐性が簡単に実装できました。

2010年6月17日木曜日

boost::spirit v2.3 ちららつきる

ちょいワケありで、簡単な定義を書いて wsdl を生成するコードをこさえました。
しかし、いざ wsdl を生成してみると、php の SoapServer や SoapClient で、動作させるのが辛そうな感じ。Delphi で、wsdl からクライアント用のインタフェイスを生成するのは、うまくいきました。肝心の ruby はどうか?というと、soap4r があり、いけそうにも思うのですが…。サーバとして常時稼働させるのには実績の面で心配がありまして、悩みまくった挙句、結論としては Soap は使わない…という事に…。
ここは、単純に Delphi + TIdHTTP の組み合わせで、リクエストを送って、レスポンスをゴリゴリ処理するという方式を採用する事にしました…。

 うーん…新しい spirit 書きやすいようで難しいです…。qi より lex 使った方が幸せなのかも?

def_grammar.hpp

#include <iostream>
#include <string>
#include <vector>
#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/include/phoenix_fusion.hpp>
#include <boost/spirit/include/phoenix_object.hpp>
#include <boost/spirit/include/phoenix_stl.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/fusion/include/io.hpp>

namespace client {
namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;
namespace phoenix = boost::phoenix;

struct xsd_datatypes_ : qi::symbols<char,std::string> {
xsd_datatypes_() {
add
( "string", "xsd:string" )
( "bool", "xsd:boolean" )
( "float", "xsd:float" )
( "double", "xsd:double" )
( "short", "xsd:short" )
( "ushort", "xsd:unsignedShort")
( "int", "xsd:integer" )
( "uint", "xsd:unsignedInt" )
( "long", "xsd:long" )
( "ulong", "xsd:ulong" )
( "date", "xsd:date" )
("dateTime", "xsd:dateTime" )
( "binary", "xsd:base64Binary" )
;
}
} xsd_datatypes;

struct inout_ : qi::symbols<char,int> {
inout_() {
add
( "in", 0 )
( "out", 1 )
;
}
} inout;

struct wsdl_arg {
int inout_;
std::string type_;
std::string name_;
};
}

BOOST_FUSION_ADAPT_STRUCT(
client::wsdl_arg,
// メンバ変数の並び順ではなく、構文解析の順番に合わせる事が大切
(std::string, type_ )
( int, inout_ )
(std::string, name_ )
)


namespace client {

#define ASCII_NAME (ascii::char_("a-zA-Z") >> *ascii::char_("a-zA-Z0-9"))

template <typename Iterator>
struct wsdl_arg_parser : qi::grammar<Iterator, wsdl_arg(), ascii::space_type> {
wsdl_arg_parser()
: wsdl_arg_parser::base_type(expression)
{
ioval %= inout;
tname %= xsd_datatypes;
sname %= ASCII_NAME;
expression = tname >> '[' >> ioval >> ']' >> sname;
// 間に lexeme[ qi::blank ] とか、やりたいけど、やり方がわかんね(全部エラー)orz
}
qi::rule<Iterator, int(), ascii::space_type> ioval;
qi::rule<Iterator, std::string(), ascii::space_type> sname, tname;
qi::rule<Iterator, wsdl_arg(), ascii::space_type> expression;
};

struct wsdl_func {
std::string name_;
std::vector<wsdl_arg> args_;
};
}

BOOST_FUSION_ADAPT_STRUCT(
client::wsdl_func,
(std::string, name_ )
(std::vector<client::wsdl_arg>, args_ )
)

namespace client {

template <typename Iterator>
struct wsdl_func_parser : qi::grammar<Iterator, wsdl_func(), ascii::space_type> {

#define SETUP_AT( idx ) (at_c<idx>(qi::_val) = qi::_1)
#define PUSH_BACK_AT( idx ) push_back( at_c<idx>(qi::_val), qi::_1 )
#define PUSH_BACK_ARG arg[ PUSH_BACK_AT(1) ]

wsdl_func_parser()
: wsdl_func_parser::base_type(expression, "expression")
{
using phoenix::push_back;
using phoenix::at_c;

using phoenix::construct;
using phoenix::val;

fname %= ASCII_NAME;
// SETUP_AT(0) しなくて入りそうなもんだけど、ここでは明示的に指定しないと
// いけない。client::wsdl_arg_parser は、何故指定しなくても大丈夫なのか?
// どんな魔術を使っているのだろうと…気になる
expression = qi::lit("function") >> fname[ SETUP_AT(0) ] >> '('
>> ( PUSH_BACK_ARG >> *(',' >> PUSH_BACK_ARG) )
// spirit の qi::eol の扱いがよくわからん(>_<)
// と思ったが、ascii::space_type が スペース・タブ・改行なのだろう・・・
>> ')' >> ';'; // >> qi::eol;

// エラーハンドリングを入れてみたけど動作しない・・・(;_;)
expression.name( "expression" );
fname.name( "fname" );

qi::on_error<qi::fail>(
expression
, std::cerr
<< val("Error! Expecting ")
<< qi::_4 // what failed?
<< val(" here: \"")
<< construct<std::string>(qi::_3, qi::_2) // iterators to error-pos, end
<< val("\"")
<< std::endl
);

}
qi::rule<Iterator, std::string(), ascii::space_type> fname;
qi::rule<Iterator, wsdl_func(), ascii::space_type> expression;
wsdl_arg_parser<Iterator> arg;
};

template <typename Iterator>
struct wsdl_def_grammar : qi::grammar<Iterator, std::vector<wsdl_func>(), ascii::space_type> {
wsdl_def_grammar()
: wsdl_def_grammar::base_type( expression )
{
using phoenix::push_back;

expression = +func[ push_back( qi::_val, qi::_1 ) ];
}
qi::rule<Iterator, std::vector<wsdl_func>(), ascii::space_type> expression;
wsdl_func_parser<Iterator> func;
};

}



wsdl_data.inc

//--------------------------------------------------------------
// PART: definitions
// def_header % 'ServiceName'
const char xml_header[] = "<?xml version=\"1.0\"?>\n";
const char def_header[] =
"<definitions \n" \
" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"\n" \
" xmlns:http=\"http://schemas.xmlsoap.org/wsdl/http/\"\n" \
" xmlns:mime=\"http://schemas.xmlsoap.org/wsdl/mime/\"\n" \
" xmlns:soap=\"http://schemas.xmlsoap.org/wsdl/soap/\"\n" \
" xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\"\n" \
" xmlns:ns1=\"urn:%1%\"\n" \
" xmlns:wsdl=\"http://schemas.xmlsoap.org/wsdl/\"\n" \
" targetNamespace=\"urn:%1%\"\n" \
" xmlns=\"http://schemas.xmlsoap.org/wsdl/\"\n" \
">\n";
// types
// message ...
// porttype ...
// operation1 ...
// binding
// operation2 ...
// service
const char def_footer[] = "</definitions>";

//--------------------------------------------------------------
// PART: types
// types_part % 'ServiceName'
const char types_part[] =
"<types>\n" \
" <xsd:schema targetNamespace=\"urn:%1%\" attributeFormDefault=\"qualified\" elementFormDefault=\"qualified\">\n" \
" <xsd:import namespace=\"http://schemas.xmlsoap.org/soap/encoding/\"/>\n" \
" </xsd:schema>\n" \
"</types>\n";

//--------------------------------------------------------------
// PART: message
// message_header % 'FunctionName' % 'In' | 'Out'
const char message_header[] = "<message name=\"%1%%2%\">\n";
// message_content % 'ArgName' % 'xsd:base64Binary' | 'xsd:string' | 'xsd:int' | 'xsd:unsignedInt' | ...
// ...
const char message_content[] = " <part name=\"%1%\" type=\"%2%\"/>\n";
const char message_footer[] = "</message>\n";

//--------------------------------------------------------------
// PART: portType
// portType_header % 'FunctionName'
const char portType_header[] = "<portType name=\"%1%Soap\">\n";
// operation ...
const char portType_footer[] = "</portType>\n";

//--------------------------------------------------------------
// PART: operation1
// operation_portType % 'FunctionName'
const char operation_portType[] =
"<operation name=\"%1%\">\n" \
" <input message=\"ns1:%1%In\"/>\n" \
" <output message=\"ns1:%1%Out\"/>\n" \
"</operation>\n";

//--------------------------------------------------------------
// PART: binding
// binding_header % 'ServiceName'
const char binding_header[] =
"<binding name=\"%1%Soap\" type=\"ns1:%1%Soap\">\n" \
"<soap:binding transport=\"http://schemas.xmlsoap.org/soap/http\" style=\"rpc\"/>\n";
// operation2 ....
const char binding_footer[] = "</binding>\n";

//--------------------------------------------------------------
// PART: operation1
// operation_binding % 'ServiceName' % 'FunctionName'
const char operation_binding[] =
"<operation name=\"%2%\">\n" \
" <soap:operation soapAction=\"#%2%\" style=\"rpc\"/>\n" \
" <input>\n" \
" <soap:body use=\"encoded\" namespace=\"urn:%1%\" encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\"/>\n" \
" </input>\n" \
" <output>\n" \
" <soap:body use=\"encoded\" namespace=\"urn:%1%\" encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\"/>\n" \
" </output>\n" \
"</operation>\n";

//--------------------------------------------------------------
// PART: service
// service_part % 'ServiceName' % 'ServiceURL'
// ServiceURL sample => 'http://hoge:8080/fuga.php'
const char service_part[] =
"<service name=\"%1%\">\n" \
" <port name=\"%1%Soap\" binding=\"ns1:%1%Soap\">\n" \
" <soap:address location=\"%2%\"/>\n" \
" </port>\n" \
"</service>\n";



def2wsdl.cpp

#include <iostream>
#include <string>
#include <vector>
#include <fstream>

#include <boost/format.hpp>
#include <boost/foreach.hpp>

#include "def_grammar.hpp"
#include "wsdl_data.inc"

void show_usage() {
std::cout << "def2wsdl [def filename] [output filename] [service name] [url]" << std::endl;
std::cout << "======================================" << std::endl;
std::cout << " >def2wsdl mysvcdef.txt mysvc.wsdl mysvc http://localhost/mysvc/mysvc.wsdl" << std::endl;
std::cout << "--------------------------------------" << std::endl;
std::cout << " type list " << std::endl;
std::cout << " string => xsd:string" << std::endl;
std::cout << " bool => xsd:boolean" << std::endl;
std::cout << " float => xsd:float" << std::endl;
std::cout << " double => xsd:double" << std::endl;
std::cout << " short => xsd:short" << std::endl;
std::cout << " ushort => xsd:unsignedShort" << std::endl;
std::cout << " int => xsd:integer" << std::endl;
std::cout << " uint => xsd:unsignedInt" << std::endl;
std::cout << " long => xsd:long" << std::endl;
std::cout << " ulong => xsd:ulong" << std::endl;
std::cout << " date => xsd:date" << std::endl;
std::cout << " dateTime => xsd:dateTime" << std::endl;
std::cout << " binary => xsd:base64Binary" << std::endl;
std::cout << "--------------------------------------" << std::endl;
std::cout << " def file sampe " << std::endl;
std::cout << "--------------------------------------" << std::endl;
std::cout << " function foo ( " << std::endl;
std::cout << " int [in] arg1, " << std::endl;
std::cout << " string [out] arg2 " << std::endl;
std::cout << " );" << std::endl;
std::cout << " function bar ( " << std::endl;
std::cout << " string [out] arg2 " << std::endl;
std::cout << " );" << std::endl;
}

namespace {
int arg_is_in( const client::wsdl_arg& arg ) {
return (arg.inout_ == 0) ? 1 : 0;
}
}

void output_wsdl(
std::ostream& os,
const std::string& svcname,
const std::string& svcurl,
const std::vector<client::wsdl_func>& funcs
) {
os << xml_header;
os << boost::format( def_header ) % svcname;
// PART: type
os << boost::format( types_part ) % svcname;
// PART: message
BOOST_FOREACH( const client::wsdl_func& func, funcs ) {
os << boost::format( message_header ) % func.name_ % "In";
// sort して range かけた方がスマートか?
// ま、arg の指定順序も壊せないので filter が欲しいところなのかも
BOOST_FOREACH( const client::wsdl_arg& arg, func.args_ ) {
if( !arg.inout_ ) {
os << boost::format( message_content ) % arg.name_ % arg.type_;
}
}
os << message_footer;
os << boost::format( message_header ) % func.name_ % "Out";
BOOST_FOREACH( const client::wsdl_arg& arg, func.args_ ) {
if( arg.inout_ ) {
os << boost::format( message_content ) % arg.name_ % arg.type_;
}
}
os << message_footer;
}
// PART: portType
os << boost::format( portType_header ) % svcname;
BOOST_FOREACH( const client::wsdl_func& func, funcs ) {
// PART: operation1
os << boost::format( operation_portType ) % func.name_;
}
os << portType_footer;
// PART: binding
os << boost::format( binding_header ) % svcname;
BOOST_FOREACH( const client::wsdl_func& func, funcs ) {
// PART: operation2
os << boost::format( operation_binding ) % svcname % func.name_;
}
os << binding_footer;
os << boost::format( service_part ) % svcname % svcurl;
os << def_footer;
}


int main( int argc, char* argv[] ) {
if( argc != 5 ) {
show_usage();
return 1;
}

std::ifstream ifs( argv[1], std::ios::in );
if( !ifs ) {
std::cerr << "fail to open: " << argv[1] << std::endl;
return 2;
}

std::string source_code;

ifs.unsetf(std::ios::skipws); // No white space skipping!
std::copy(
std::istream_iterator<char>(ifs),
std::istream_iterator<char>(),
std::back_inserter(source_code)
);

typedef client::wsdl_def_grammar<std::string::const_iterator> wsdl_parser;

wsdl_parser g;
std::vector<client::wsdl_func> fncs;

bool res = phrase_parse(
source_code.begin(), source_code.end(),
g, boost::spirit::ascii::space, fncs
);


if( res ) {
std::cout << "Success to parse!" << std::endl;
std::ofstream ofs( argv[2], std::ios::out | std::ios::trunc );
output_wsdl( ofs, argv[3], argv[4], fncs );
} else {
std::cerr << "Fail to parse: " << argv[1] << std::endl;
}

return 0;
}