2014年1月11日土曜日

JavaScriptによる関数のラッピング

目的

既存のWebアプリケーションにおいて、可能な限り既存の処理を変更せず関数の呼び出し前後に処理を入れたいことがある時の方法を考えてみた。

適用例

この方法の適用例としては以下のような状況が考えられる。

  • デバックやトレース情報の採取や表示を行う。
  • フォームのonSubmitやonCheckなどのイベントに既に関数を割り当ているときに処理を追加する。
実装方法

JavaScriptには、関数の this 値を指定のオブジェクトで置き換え、関数の引数を配列を置き換えて関数を呼び出詩を行うapplyメソッドという関数が用意されているのでこれを利用し実装する。
実際のコードとしては、既存の関数の前処理、後処理を実装した関数(functionWrapper)を用意し、既存関数の呼び出し部分を変更することにより、functionWrapper内に定義された処理を元の関数の呼び出し前後に処理を挟み込むことができる。
/**
 * 引数で指定した関数をラッピングしての前後に
 * 処理を差し込みます。
 * @param functionName 関数名
 * @return {Boolean}
 */
function functionWrapper(functionName){

    //前処理
    ~

    //既存ロジックの呼び出し
    var tmpArguments = 
           new Array(arguments.length-1);
    for(i = 0;i < arguments.length-1;i++){
        tmpArguments[i] = arguments[i+1];
    }
    var retValue = window[functionName]
                     .apply(window,tmpArguments);

    //後処理
    ~

    return retValue;
}

既存関数の呼び出しとして、例えば以下のようにformのonSubmitに既存のフォームのチェックをするcheckFormという関数の前後になんらかの処理を入れる場合、もともと定義されているchekFormという関数を文字列としてfunctionWrapperの第一引数とし、もともとcheckFormに指定されていた引数をそのままfunctionWrapperの第二引数以降に指定し、functionWrapperの呼び出しに書き換える。 (関数呼び出しの際の引数の受け渡しは、JavaScriptではオーバーロードがサポートされていないため同じ関数名は同一関数が実行されすべての引数がわたされるという性質を利用している。) この書き換えによりfunctionWrapper内に定義された処理を元の関数の呼び出し前後に処理が差し込まれる。
<form method="GET" action="action.do" 
  onSubmit="return checkForm(this);" >
<input text="name" value="value" />
<input text="submit" />
</form>

↓

<form method="GET" action="action.do"
  onSubmit=
    "return functionWrapper('checkForm',this);">
<input text="name" value="value" />
<input text="submit" />
</form>


※2014/02/09 ソースコードの表示方法を変えました。


2013年5月11日土曜日

Philipsのノンフライヤーを購入したのでいろいろ試してみた


揚げ物は油の処理が面倒なので絶対に自宅では作ることはないと思っていたんだけど、空気と熱で揚げ物を作るという“油を使わない揚げ物調理器”であるPhilipsのノンフライヤーが日本で発売されたので早速購入しいろいろと試してみた。総評としては、お手軽にヘルシーな揚げ物的なものを作るには良いものだといったところか。
下の写真を見ればわかると思うが、食材を調理する部分はバスケットとバスケットパンに分けることができ、それぞれ食器と同様洗うことができ、お手入れは簡単。使用するときはバスケットパンにバスケットをいれ、バスケットの網の部分に食材を置いて調理する。バスケットパンとバスケットの間に隙間があり、ここを空気が流れる。


取りあえずいろいろ試した結果、つぎの良い点・悪い点が分かった。
<良い点>
  • 後片付けが比較的楽、バスケットとバスケットパンは食器と同様に洗える(食洗器もOK)
  • 基本的に調理するために油は全く必要としない。
  • 油分が抑えられヘルシー(ただし、特別美味しくできるというわけでもない)
  • 最適な調理時間さえ押さえれば、常に同じ仕上がりが期待できる
<悪い点>
  • 消費電力が大きい(最大1420W)。ただし、常時この電力を使うというわけではなく温度が保たれている間はヒーターが自動で切れる。
  • 1度に調理できる量が少ない。とんかつはせいぜい2枚程度。
  • ちょっと音がうるさい(感覚的には掃除機のナイトモードぐらい?)
  • 調理中の食材が見えないため、最適な調理時間の見極めが難しい。
  • かつなど衣があるものは、ムラができてしまう。(見た目を美しく仕上げるには向かない)
以下いろいろ試した内容を記述する。

(1)フライドポテト

まずは、冷凍食品のポテトを使用してフライドポテトを作ってみた。
見た目・味ともに油で揚げたフライドポテトに近い感じに仕上がった。しかも、油っぽくなくていくらでも食べられる感じ。

(2)から揚げ

鶏もも肉に市販のから揚げ粉をまぶし、ノンフライヤーで調理する。

調理後、バスケットパンに余分な油分が落ちていた。これだけでも油分が減っていることがわかる。

もともと鶏肉に含まれていた油分があり、意外とジューシーな仕上がり。皮もパリパリ。ただ、一部ムラ(粉っぽく見えるところ)があった。熱は通っているので食べる分には問題なし。

(3)とんかつ

豚ロースに衣をつけ、ノンフライヤーで調理する。1度に作れるとんかつは2枚がせいぜい。

周りはきつね色になるが、全体的にきつね色にするのは困難。何度か挑戦したが、どうしてもムラが残り、きれいなきつね色にはならなかった。ネットで確認したが、揚げムラ?に悩まされている人は多いようだった。見た目きれいなとんかつを作るのはかなりの難度と思われる。

ただし、しっかり中まで加熱されていることは間違いない。

(4)ステーキ

あと、ステーキも作ったんだけど、写真撮り忘れたみたい。ただ、ステーキはフライパンで作るのとそれほど変わらない気がする。

2013年1月19日土曜日

アーロンチェアにヘッドレストをつけたよ!!

ワーキングチェアとして長年愛用してきたアーロンチェア。ヘッドレストがないことがずっと不満だったけど、つい最近サードパーティーからヘッドレストが販売されていることを知り、速攻購入し装着してみた。
 ちなみに、アーロンチェアとは、ハーマンミラー社が販売している割と有名なワーキングチェアで、コンセプト通り作業するために特化した椅子である。あくまで作業するための椅子なので、ハーマンミラー社としてはアーロンチェアにはヘッドレスト的なものは必要なしということらしい。 (ただ、作業していれば、椅子の上でちょっとくらい休みたくなるよね!!)

ということで、以下アーロンチェアの気に入っている点およびヘッドレストの使用感を述べてみたい。

アーロンチェアを個人的に気に入ってる点は以下の通りで、とにかく座っていて疲れにくい。
  • 全体的にメッシュ構造で夏でも蒸れない。また、メッシュの絶妙な反発で接地面(太ももやおしり)に圧迫感をあまり感じない。
  • リクライニング時の反動も絶妙で宙に浮いている感じがする。
    (これは実際に座ってみないとわからない感覚だと思う。)
  • リクライニングを前に傾け、前傾姿勢をとることができる。
    (前傾姿勢をとると前のめりに緊張が増し、やる気が増すように感じる)
  • 作りがシンプルで構造がしっかりしているため長持ちする
    (10年近く使用しているが、不具合らしい不具合はない)
気に入っている点は以上になるが、1つ注意点がある。アーロンチェアについているキャスターは意外と硬いのでフローリングで使用する際は、厚手のカーペットまたはマットを引くことをお勧めする。ないと確実にフローリングにダメージ(キャスターのあと)が残ることになると思う。

そして、ヘッドレストの使用感は以下の通り。
  • 付属の6角レンチでネジを締めて固定する仕組みになっていて、かなりしっかりと固定される(ぐらつきは全くない)。そのため、都度装着・脱着するようなことには向いていない。基本的に使用しないときは下図のようにヘッドレスト部分の角度を変えることになる。
  • ヘッドレスト部分のメッシュは、本体のメッシュの素材は異なっているようで、本体のメッシュより張りが少しゆるい。また、色味も少し異なっている(若干艶っぽい感じで若干安っぽく見える)。
    ただ、それほど気にはならないとは思う。
  • ヘッドレストに頭を預けリクライニングすると、背中のラインとヘッドレストの位置に若干の違和感を感じる。長時間休むには向いていないと思う。(サードパーティーが作成したものでこの辺はしょうがないか)
    ただ、疲れた時にちょっと頭を預けるには十分か。
総合的にみると5点満点中3.8点というところだけど、今までずっとなかったことを考えると、やはり必須アイテムと思う。


2012年7月7日土曜日

B&W(Bowers & Wilkins) CM5 購入しました。

先日、スピーカー新調してからおよそ一週間たちエージングもそこそこ進んだ感じなので感想などを書いてみる。

B&W CM5(写真上)を購入する前は、DIATONE DS-600ZA(写真下)を使用していました。DS-600ZAもかなり気に入っていた良かったのですが、少し音の立ち上がりが遅くキーボードなどを繋げると音のアタック部分が若干消えてしまうところだけが不満でした。そこで今回は、なるべく音の立ち上がりがクリアな音を求め、予算と相談した結果CM5に決定し購入しました。
ウーハーとか買うつもりがないので、ホントはもう少し大きなクロージャーのスピーカーが良かったんだけど、DS-600ZA位の大きさのスピーカーが少なくなってきたのと、トールボーイ型ではちょっと部屋に置くスペースを確保するのが難しいという点もCM5にした理由の一つ。
自分自身オーディオマニアというわけでもなく、そんなにいろんなスピーカーの音を聴いているわけでもないのため、感想は前に使用していたDS-6000ZAとの比較っぽい点があると思いますがご容赦願います。

CM5の視聴環境

オーディオマニアではなけれど、今回はケーブルなど可能な範囲でいろいろ頑張ってみました。
  • スピーカー Bowers & Wilkins CM5(色はローズナット)
    今回購入したスピーカー
  • アンプ Pionneer VSA-920TV、ゲーム機、楽器などを色々なソースを接続するために、以前購入したAVアンプ。
  • ケーブル BELDEN 1810Aスピーカーと一緒に新調した4芯のケーブル。思ったより柔らかく引き回しが楽でした。
  • インシュレーター audio-technica ハネナイトAVインシュレーター

まずは、アンプとスピーカーとの接続方法ですが、一般的な接続方法として大きく分けると3パターンあります。

  • Single-wire(シングルワイヤ)
    一般的な接続方法。アンプの±とスピーカーの±をそれぞれ1本のケーブルで接続する。
  • Bi-wire(バイワイヤ)スピーカー側のLHの±とアンプの±を4本のケーブルを使用して接続する  。アンプ側の±は1つで、それぞれ2本接続する下図(右側) 。(Bi-wire接続する場合はブリッジ金具を外して接続する。)
    ※Bi-wire接続することでスピーカーの高音域と低音域の干渉を少なくするらしい。
  • Bi-amp(バイアンプ)アンプ側の対応が必要となるが、Bi-wireをパワーアップした感じで、アンプ側の±がそれおれ独立した回路から接続する形。アンプ側の回路も別になるので更に干渉が少なくなる。
    (VSA-920にはゾーン2(メインとは別の機器を接続するための回路)をBi-amp用の回路として使用するモードがある)

ホントは、Bi-ampで接続したかったんだけど、ゾーン2を別室用のアンプと使用しているため、Bi-ampはあきらめ、今回はBi-wire接続することにしました。スピーカー側の接続は左の写真の様な感じになります。

CM5の感想

まずは、エージングしつつ感じた全体的なイメージ、
  • ファーストインプレッション(購入直後)
    高音がキツく、音が軽い。ただ、中高音の鮮明さは流石。
  • 2日後(エージング15時間位経った頃)
    高音のきつさが少しとれ、全体的にまとまってきたけどやっぱり低音が軽い。
  • 1週間後(エージング30時間以上経った頃)
    中高音と低音のバランスが良くなり、全体的なレベルが数段上った感じになった。ただ、やっぱり低音はやっぱり少し軽い感じがする(これは以前使用していたスピーカーの低音がかなり強いためだと思われる)。
このスピーカーは、エージングによってかなり感じが変わるようです。特に購入直後の音は、お店で聴いたのと全く違い、何か接続を間違えたかと思うレベルです。
エージングが進むと全体的な音のバランスが良くなり、まとまり感が増してくるようです。中高音は音の立ち上がり位も早く、鮮明な音が素晴らしいです。ただ、ある程度の音量で鳴らさないと低音がほんと弱い感じです。低音が弱く感じた場合、少し音量を上げてみると良いかもしれません。
音質は素直な感じで、アンプ側のエフェクトによく反応してくれます(というか効き過ぎな感じがしてすぐに戻してしまうのですが。。。)


空間的な感じはしないので、映画などにはあまり向かないかもしれません。(ただ、アンプ側である程度カーバー可能?)。また、低音の「ず~ん」という感じは、あまりでなっく映画を視聴するにはウーハーが別にないと物足りない。
ハイハットやシンバルのような音は残響が少し耳に残ります。


最後に楽器種別毎の感想

  • 弦楽器系(ストリング系)高音域は少しきつい感じがするけど中低音から高音域の間は、響きが素晴らしい。スピーカー本体が単板で作成されているという事前知識によるプラシーボ効果もあり、スピーカーが共鳴しているような感じすらする。
  • 鍵盤系(ピアノなど)
    音の粒が鮮明でとても心地良い。
  • 管楽器系特にないというか、全体的に高レベルな音であるのは間違く、突っ込みどころがない。
  • ドラム関係
    ハイハットなどの残響が少々耳障りな感じ。音の粒が細かいせいか、ドラムの音が軽い感じになる。
  • ボーカル音は鮮明で前に出てくる感じ。ただ、ボーカルが際立ちすぎるのか、他の音とあまり馴染まない感じで聴こえる(極端に云うとバックの演奏と独立した感じで聴こえる)

2011年9月17日土曜日

狭い部屋でKinectを使えるようにするZOOM for Xbox 360

Xbox 360 Kinect センサーを使うためにはそれなりの広さが必要(Kinectから1人だと1.8m、2人だと2.5m離れないと正しく認識されない)なため、買ったは良いけど部屋が狭くお蔵入りとなっていた。しかし、この距離の問題を解決してくれるZOOM for Xbox 360が発売されたので早速購入してみた。パッケージや商品のデザインは、純正品っぽい感じを出している。




仕組みとしては、焦点距離の短いレンズを本体に被せる形で装着して識別出来る範囲を近くするようだ。商品説明では40%程度近づくことが可能とある。装着もワンタッチで簡単に装着できる。装着した感じもあまり違和感がない感じに仕上がっている。


装着後、早速Kinectの設定を行ってみると、1.4mほどの位置で無事認識することができた。40%ちかづけるというのもホントだった。



とりあえず、ゲーム(ユアシェイプ フィットネス・エボルブ)をやってみた。他のレビューなどを見ると認識率が悪くなるようなことも書かれているのでちょっと気になるところもあるが、とりあえず遊べそうだ。ゲーム画面の右側に映っているのが自分なんだけど、Kinectって着ているものも含め結構細かく認識するんだな~と改めて関心。



Kinect SDKも公開されたし、これでKinectで色々と遊べそう。



2011年9月4日日曜日

getResourceAsStream()でリソースが読み込めない

getResource(),getResourceAsStream()でちょっとはまったので忘れないうちにメモっとく。
まずは動作の基本から、クラスローダ(ClassLoader)に対するgetResource(),getResourceAsStream()は、クラスパスのルートのパスを検索するようになっており、引数で渡した文字列でそのままクラスパスのルートから検索する。なので、文字列の頭に基本的に"/"は付けない。
一方、クラス(Class)に対するgetResource(),getResourceAsStream()は、引き数の文字列の頭に"/"が付いてる場合は"/"を以降の文字列で、引数の文字列の頭に"/"がついていない場合はパッケージ名の"."を"/"に置き換え引数の文字列と"/"とで連結した文字列を、クラスパスのルートから検索する。
例えば、foo.bar.TestMainというクラスがあり、同じパッケージのフォルダ内にTestMain.propertiesというリソースがあった場合、以下の3つの方法でアクセスが出来る(すべて同じ動作)。


TestMain.class.getClassLoader()
    .getResource("foo/bar/test.properties"));

TestMain.class
    .getResource("/foo/bar/test.properties"));

TestMain.class
    .getResource("test.properties"));

ここまでは、位置に依存しない方法でのリソースへのアクセスの仕様を見ればわかるのだけれど、実行時にクラスがjarファイルなどに格納されている場合、実行環境によりなぜかgetResourceAsStream()でリソースが読み込めない場合があるようだ。どうやら、内部的にファイルとしてアクセスしようとして、zip内のファイルを読み取ることが出来ずに例外が発生しているらしい。ちなみにgetResource()でURLはちゃんと戻るからファイルの存在は認識しているようなので不思議だ。
今回、Windowsで開発していたときは問題なかったのだが、LinuxのWebLogic上で実行した際に、リソースにアクセス出来ないという現象が発生していた(WebLogicはwarをデプロイすると/WEB-INF/classesがjarにまとめられる)。


結局のところ実行環境によらずにリソースにアクセスするための解決方法としては、下記のようにするのが良いようだ。
URL resource
    = new URL(TestMain.class.getResource("."),
              "test.properties");

InputStream in 
    = resource
      .openConnection().getInputStream();
:


※2014/02/09 ソースコードの表示方法を変えました。




2011年3月10日木曜日

LifeTouch NOTEを使ってみる

以前モバイルギアを使用していたこともあり、モバイルギアの後継とも思えるLifeTouchノートを早速購入したので使用感などを報告しようと思う。

まず、本体の色だが、購入する前は黒または赤にしようと考えていた。しかし、実物を見ると黒はツヤがありすぎて指紋が目立ちそうだし、赤はちょっとイメージしていた感じと違っていた。意外にチョコレートブラウンの色がいい感じだったのでチョコレートブラウンを選択することにした。

モバイルギアと比較するために、並べて写真を撮ってみた。横幅が少し短くなっているが大きさはほぼ同じくらいで薄くなっている。

初回起動時にネットワークの設定が必須(ウィザードに従うとネットワーク有効にならないと先に進めない)のようなので注意が必要かも。。。


起動は、30秒ちょっとと思ったより時間がかかる感じ(動画参照)。ただ、スリープからの復帰は瞬時なので普段は気にならないと思う。文字の入力する際のキータッチはモバイルギアよりちょっと浅めでちょっとちゃちな感じするが、それほど悪くはない?少なくともASUSのeeePC901よりは入力しやすいと思う。。また、モバイルギア同様に、IMEとしてATOKが入っているのがうれしい。難点をあげると、_(アンダーバー)キーの位置か、なにゆえにカーソルを挟んでしまったかな。。。。

ついでにモバイルギアのスタイラスとLifeTouch NOTEのスタイラスも比べてみた。やっぱり、スタイラスはモバイルギアのほうが大きくて使いやすいと思うが、本体の厚みがちがうので仕方が無いところか。。


ちなみに、Andoroid OSのバージョンは2.2。バージョンアップが提供されるかが気になるところ。しかし、Android Marketがインストールされているところが良い点。また、Android Marketの他に、NECのAndronaviもインストールされているので、追加でアプリケーションをインストールしたいときに困ることはなさそう。

早速ツイッターなどのアプリを入れてみた。動作は軽快だがちょっとフォントが見づらいかも。。。

まだ、触ったばかりなのでもう少し慣れてから続報をお届けしたいと思う(いつになるかは不明)



2011.09.17 更新
今更なのだが、、_(アンダーバー)キーの位置とかをカスタマイズ出来るアップデートが公開されている。「Insert」・「カタカナ」・「←」・「↑」(矢印キー)「ろ」の5つのキーで配置パターンを選べるみたい。ついでにキートップもなんとかなると更に良いのだけどね。。。
「個人向けスマートブック「LifeTouch NOTE」無償アップデートを開始 」
http://121ware.com/navigate/support/ltn/info/20110627/

2009年11月1日日曜日

WindowsでAppleのMagic Mouseを使用する



Apple からMagic Mouseが発売されました。Magic Mouseが発表されたとき、一目見たときからそのデザインのよさにほれ込んでしまい、Apple Storeで発売されるとすぐに購入してしまいました。実際に届いたマウスは右側の写真です。化粧箱もなかなかかっこいい。ちなみに右側のマウスは、携帯用のお気に入りマウスのMicrosoft Arc Mouseです。
基本的にはMagbookをもっているのでそちらで使うつもりで購入しました。しかし、Windowsでも使えないかとためしたところ、専用のドライバがないためタッチによる操作、スワイプはもちろんのことホイール操作もできませんが、Bluetooth接続で普通の2ボタンマウスとしては使用できることがわかりました。
ちょっとしたステータスとして持ち歩く分にはかっこいいマウスであることは間違いないのでWindowsでの設定方法を紹介します。
ここでの設定は、EeePC901(windowsXP SP3)との接続ですの例ですが、実績としては、WindowsXP SP2とPLANEX BT-MicroEDR2Xとも接続できたので、Bluetoothのデバイスさえあればたいていの場合接続できると思います。






Magic Mouse側の電源をONにして、マイ Bluetoothを開きます。そうするとMagic MouseがApple Wireless Mouseとして認識されます。






次に認識されたApple Wireless Mouseを選択し、コンテキストメニューから「デバイスを接続」選択します。




HID(Human Interface Device)に接続するには[はい]をクリックししてください。とたずねられるので「はい」を選択します。






デバイスの接続を選択すると接続確認をもとめられるので、表示されている時間内に「ここをクリック」をクリックして接続を完了させます。







デバイスが接続状態となると同時にセキュリティコード(PIN)の入力を求められます。ここには、「0000」と入力することで接続できます。最初ここで接続できなくてはまり結構悩みました。ちなみにWindowsXP SP2では、端末側のセキュリティコードの設定を聞かれますが、端末側は設定なしでOKでした。



以上の設定でMagic MouseをWindowsで使用することができます。ただし、先ほど述べたようにスワイプ等ができないので、残念ながら見た目を自慢することくらいしかできませんが。。。。




2009年8月13日木曜日

スリープトラッカーで快適な目覚めを[SleeptrackerPRO ELITE]


「ほぼ目覚めている状態」にアラームが鳴り、起こしてくれるという画期的な?腕時計です。睡眠には、眠りの浅い状態のレム睡眠と眠りの深い状態のノンレム睡眠の2種類の状態があります。このスリートラッカーは、眠りの浅い状態のレム睡眠の半覚醒状態に近いときに、アラームが鳴り起こしてくれるというものです。また、眠りの浅い状態を記録し、それをUSB経由で付属のWindows用のソフトウェアで管理することもできます。

まず、目覚ましの機能ですが、仕組み的には時計に加速度計が内蔵されおり、寝ている時の動きによって眠りの状態を判断しているようです。実際に使用した感覚では、私の場合は寝返りのタイミングでアラームが鳴るといった感じでした。ここら辺の判定は、個人差はあると思います。この時計のうたい文句であるすっきりとした目覚めであるかは微妙ですが、普通の目覚ましよりは、気がつきやすいのではないかと思います。
それから、アラームの鳴る時間は、アラーム時間とアラーム・ウィンドウ(分数)で時間帯として設定します。設定したアラーム時間よりアラーム・ウィンドウ(分数)前の間の眠りの浅い時にアラームが鳴ります。例えば7時にアラームを設定し、アラーム・ウィンドウを60分と設定すると6時から7時の間で眠りの浅い時にアラームが鳴ります。設定した時間帯に眠りの浅い状態がなかった場合でも、アラームの設定時間にはアラームが鳴ります。ちなみに、アラーム・ウィンドウ(分数)は、最大90分の設定が可能です。
また、スリープトラッカーPROシリーズでは、アラームの他にバイブレーションも選択することができるので、音が聞こえない状態でのアラーム機能としても使えます。例えば、音楽を聴きながら長時間電車に乗っているときに、時間を知らせてほしい場合とか。

次に、データを管理するソフトです。スリープトラッカーでは1日分の睡眠データが記録されるので、このデータを毎日USB経由で転送します。データ転送し、睡眠データを登録するとき(左図)に、自分の気分と状態(昼寝をしたとか、アルコールを摂取したとか)を登録することで、どういったことが睡眠に影響しているのかを記録していくことができます。

登録したデータは、画面(下図)で確認できます。左側のバー表示が眠りの状態で、黒丸が付いている部分が眠りの浅かった時間になります。この画面でいうと8月13日のAM2:30頃~AM4:00過ぎまでは、眠りが深かったことを示しています。また、8月11は、黒丸が多いのでかなり眠りが浅かったということになります。
そして、右側には、先ほどの画面で登録した気分と状態がアイコンで表示されます。これをもとに自分の睡眠の良い状態を維持・管理していくといったことになります。



まあまあ実用性ある時計だと思いますが、次の点は改善してほしいなと思っています。(ただ、すでに購入しているので改善されたら、改善されたでくやしいだけなのですが。。。。)
  • アラームの種類・音量はバリエーションがほしい(アラームと音量は固定となっている)。
  • デザインをもう少しなんとかほしい。(個人的にはあまり気にっていない)。
  • USB接続でなく、無線(Bluetoothとか)にしてほしい(クリップで挟むだけなのでそれほど手間にはなっていないけど、やはり無線の方が便利)。
  • 値段が高い(もうちょっと安くならないかと思う)。
スリープトラッカーのオフィシャルサイトはこちらです。

2009年6月30日火曜日

ピコピコゲーム(PikoPiko Game)

Javaを覚えたてのころに作ったゲームです。息抜きに遊んでみてください。

左側が自分で、マウスを枠内で押し続けるとハンマーが下がります。
少し勢いがついた時に相手にヒットすると勝利となります。
枠内からマウスが出るとポーズ状態がかかります。





※Java Appletにて作成していますので、遊ぶためにはJava Runtimeのインストールが必要となります。

2009年5月30日土曜日

Java 6 Mustang のXML機能(JAXB)によるXmlDAO

Java 6 MustangのXMLの機能(JAXB)の機能がかなり拡張され、これを利用してXML用のDAOクラスを作ってみました。

まず、Java 6に付属しているSchemagenというツールにより、DAOで扱うクラスのスキーマファイルを生成します。
たとえば次のようなSampleクラスを作成します。schemaのルートノードとなるクラス(ここではSampleクラス)には
アノテーションXmlRootElementを指定します。

Sampleクラス:

import javax.xml.bind.annotation.XmlRootElement;

/**
* サンプルクラス
*/
@XmlRootElement
public class Sample {

/* 名前 */
private String name;

/* 年齢 */
private int age;

/**
* 名前を取得する。
*
* @return 名前
*/
public String getName() {
return name;
}

/**
* 名前を設定する。
*
* @param 名前
*/
public void setName(String name) {
this.name = name;
}

/**
* 年齢を取得する。
*
* @return 年齢
*/
public int getAge() {
return age;
}

/**
* 年齢を設定する。
*
* @param 年齢
*/
public void setAge(int age) {
this.age = age;
}
}



Sampleクラスに対するスキーマを作成する場合以下のようにコマンドを実行します。

> schemagen -classpath <クラスパス> Sample.java

※なぜかMacでは動作しなかった(InvocationTargetExceptionが発生してしまう)ので、Windowsでschemagenを実行しました。

schemagenを実行するとschema1.xsdというファイルが生成されますので、これをSample.xsdという名前に変更し保存します。


今回作成したXmlDAOにより、上記のSampleクラスの保存および読み込みのロジックは記述すると次のようなコードになります。
XmlDAOのテストコード:

import java.io.File;

import jp.aarkiton.xml.dao.XmlDAO;

/**
* XmlDAO用テストソース
*/
public class XmlDAOTest {

public static void main(String args[]) throws Exception {
// 保存対象のテスト用オブジェクト
Sample sample = new Sample();
sample.setName("tama");
sample.setAge(10);

// XmlDAOのインスタンス生成
XmlDAO<Sample> xmlDAO = XmlDAO.getInstance(Sample.class, "Sample.xsd");

// オブジェクトの保存
xmlDAO.save(sample, new File("sample.xml"));
// 一旦オブジェクトを解放
sample = null;

// オブジェクトの読み込み
sample = xmlDAO.load(new File("sample.xml"));

System.out.println(sample.getName());
System.out.println(sample.getAge());

}

}


上記コードを実行した結果得られるsample.xmlは以下のようになります。
sample.xml:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<sample>
<age>10</age>
<name>tama</name>
</sample>


最後に今回作成したClassUtils、XmlDAO、のクラスを記載します。
ClassUtils:

/*
* Copyright 2009 (C) Aarkiton Soft. All Rights Reserved.
*
* This software is open source.
*/
package jp.aarkiton.util;

import java.io.InputStream;
import java.net.URL;

/**
* クラス、パッケージ関連のユーティリティクラス
* @author Takanori
* @version 1.0.0
* @since 1.0.0
*/
public class ClassUtils {

/**
* 指定したクラスのパッケージパスから、指定したファイルのURLを取得する。
* @param cls クラス
* @param name ファイル名
* @param URL
*/
@SuppressWarnings("unchecked")
public static URL getResource(Class cls,String name){
return cls.getClassLoader().getResource(getPackagePath(cls)+"/"+name);
}

/**
* 指定したクラスのパッケージパスから、指定したファイルの入力ストリームを取得する。
* @param cls クラス
* @param name ファイル名
* @param 入力ストリーム
*/
@SuppressWarnings("unchecked")
public static InputStream getResourceAsStream(Class cls,String name){
return cls.getClassLoader().getResourceAsStream(getPackagePath(cls)+"/"+name);
}

/**
* クラスを指定してパッケージのパスを取得する。
* @param cls クラス
* @return パッケージのパス
*/
@SuppressWarnings("unchecked")
private static String getPackagePath(Class cls){
return cls.getPackage().getName().replace('.','/');
}

}


XmlDAO:

/*
* Copyright 2009 (C) Aarkiton Soft. All Rights Reserved.
*
* This software is open source.
*/
package jp.aarkiton.xml.dao;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Map;

import javax.xml.XMLConstants;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;

import jp.aarkiton.util.ClassUtils;

import org.xml.sax.SAXException;

/**
* Java 6 Mustang のXML機能を使用したJavaオブジェクトのシリアライザークラス

* Java 6 から同梱されたschemagenにより、Javaのクラスからスキーマを生成することができ、
* その生成されたスキーマを使用しオブジェクトのロード、セーブを行う。
* スキーマファイル名を指定しない場合、スキーマは対象となるクラスのパッケージパスの
* 「クラス名.xsd」という名前のスキーマファイルを使用する。
*
*

* (1)スキーマの生成
* Usage: schemagen [-options ...] <java files>
* Options:
* -d <path> : 出力先ディレクトリ
* -cp <path> : ユーザ定義ファイルの検索パス
* -classpath <path> : ユーザ定義ファイルの検索パス
* -version : バージョン情報
*
* (2)クラスの使用例
* 例1)SampleクラスのインスタンスをXMLスキーマ定義(Sample.xsd)に基づき、
*     XMLファイル(sample.xml)として保存する。
*
* Sample sample = new Sample();
* :
* XmlDAO<Sample> xmldao = XmlDAO.getInstance(Sample.class,"Sample.xsd");
* xmldao.save(sample, new File("sample.xml"));
*
* 例2)SampleクラスのインスタンスをXMLファイル(sample.xml)として保存する。
*     (XMLスキーマ定義を指定しなかった場合、パッケージフォルダにある<クラス名>.xsdファイルが使用される)
* Sample sample = new Sample();
* :
* XmlDAO<Sample> xmldao = XmlDAO.getInstance(Sample.class);
* xmldao.save(sample, new File("sample.xml"));
*
* 例3)SampleクラスのインスタンスをXMLスキーマ定義(Sample.xsd)に基づき、
*     XMLファイル(sample.xml)からロードする。
*
* XmlDAO<Sample> xmldao = XmlDAO.getInstance(Sample.class,"Sample.xsd");
* Sample sample = xmldao.load(new File("sample.xml"));
*
* 例4)SampleクラスのインスタンスをXMLファイル(sample.xsd)からロードする。
*     (XMLスキーマ定義を指定しなかった場合、パッケージフォルダにある<クラス名>.xsdファイルが使用される)
* XmlDAO<Sample> xmldao = XmlDAO.getInstance(Sample.class);
* Sample sample = xmldao.load(new File("sample.xml"));
*
*


* @author Takanori
* @version 1.0.0
* @since 1.0.0
*
* @param
*/
public class XmlDAO {

/** 永続化クラス */
protected Class targetClass;

/** Marshallerオブジェクトに渡すプロパティ */
protected Map properties;

/** スキーマファイル */
protected File schemaFile = null;

/**
* クラスオブジェクトを入力としてXmlDAOのインスタスを生成するファクトリメソッド。
*
* @param targetClass
* ターゲットクラス
*/
public static XmlDAO getInstance(Class targetClass) {
return new XmlDAO(targetClass);
}

/**
* クラスオブジェクト、スキーマファイル名を入力としてXmlDAOのインスタスを生成するファクトリメソッド。
*
* @param targetClass
* ターゲットクラス
* @param schemaFilename
* スキーマファイル名
*/
public static XmlDAO getInstance(Class targetClass,
String schemaFilename) {
return new XmlDAO(targetClass, schemaFilename);
}

/**
* クラスオブジェクト、スキーマファイル名を入力としてXmlDAOのインスタスを生成するファクトリメソッド。
*
* @param targetClass
* ターゲットクラス
* @param schemaFile
* スキーマファイル
*/
public static XmlDAO getInstance(Class targetClass,
File schemaFile) {
return new XmlDAO(targetClass, schemaFile);
}

/**
* クラスオブジェクトを入力としてXmlDAOのインスタスを生成するコンストラクタ。
*
* @param targetClass
* ターゲットクラス
*/
protected XmlDAO(Class targetClass) {
this(targetClass, (File) null);
}

/**
* クラスオブジェクト、スキーマファイル名を入力としてXmlDAOのインスタスを生成するコンストラクタ。
*
* @param targetClass
* ターゲットクラス
* @param schemaFile
* スキーマファイル名
*/
protected XmlDAO(Class targetClass, String schemaFilename) {
this(targetClass, new File(schemaFilename));
}

/**
* クラスオブジェクト、スキーマファイルを入力としてXmlDAOのインスタスを生成するコンストラクタ。
*
* @param targetClass
* ターゲットクラス
* @param schemaFile
* スキーマファイル
*/
protected XmlDAO(Class targetClass, File schemaFile) {
this.targetClass = targetClass;
this.schemaFile = schemaFile;
this.properties = getDefaultProperties();
}

/**
* Marshallerオブジェクトに渡すデフォルトのプロパティを取得する。
*
* @return デフォルトのプロパティ
*/
protected Map getDefaultProperties() {
Map defualtProperteis = new HashMap();
defualtProperteis.put(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
return defualtProperteis;
}

/**
* オブジェクトをセーブする。
*
* @param o
* ターゲットオブジェクト
* @param output
* 出力ファイル
*/
public void save(T o, File output) throws JAXBException, SAXException,
IOException {
save(o, new FileOutputStream(output));
}

/**
* オブジェクトをセーブする。
*
* @param o
* ターゲットオブジェクト
* @param output
* 出力ストリーム
*/
public void save(T o, OutputStream output) throws JAXBException,
SAXException, IOException {
// ターゲットクラスのためのコンテキストを作成.
JAXBContext context = JAXBContext.newInstance(targetClass);

// 使用する Schema オブジェクトを作成.
Schema schema = getSchema();

// Java オブジェクトから XML に変換するための Marshaller を作成.
Marshaller marshaller = context.createMarshaller();
marshaller.setSchema(schema);
for (Map.Entry entry : properties.entrySet()) {
marshaller.setProperty(entry.getKey(), entry.getValue());
}

// XML に変換.
marshaller.marshal(o, output);
}

/**
* オブジェクトをロードする。
*
* @param input
* 入力ファイル
* @return オブジェクト
*/
public T load(File input) throws JAXBException, SAXException, IOException {
return load(new FileInputStream(input));
}

/**
* オブジェクトをロードする。
*
* @param input
* 入力ストリーム
* @return オブジェクト
*/
@SuppressWarnings("unchecked")
public T load(InputStream input) throws JAXBException, SAXException,
IOException {
// ターゲットクラスのためのコンテキストを作成.
JAXBContext context = JAXBContext.newInstance(targetClass);

// 使用する Schema オブジェクトを作成.
Schema schema = getSchema();

// XML から Java オブジェクトに変換するための Unmarshaller を作成.
Unmarshaller unmarshaller = context.createUnmarshaller();
unmarshaller.setSchema(schema);

// XML から Java オブジェクトに変換.
return (T) unmarshaller.unmarshal(input);

}

/**
* オブジェクトを入力にストリームに変換する。
*
* @param o
* ターゲットオブジェクト
*/
public InputStream getInputStream(T o) throws JAXBException, SAXException,
IOException {
// ターゲットクラスのためのコンテキストを作成.
JAXBContext context = JAXBContext.newInstance(targetClass);

// 使用する Schema オブジェクトを作成.
Schema schema = getSchema();

// XML から Java オブジェクトに変換するための Unmarshaller を作成.
Unmarshaller unmarshaller = context.createUnmarshaller();
unmarshaller.setSchema(schema);

// Java オブジェクトから XML に変換するための Marshaller を作成.
Marshaller marshaller = context.createMarshaller();
marshaller.setSchema(schema);
for (Map.Entry entry : properties.entrySet()) {
marshaller.setProperty(entry.getKey(), entry.getValue());
}
ByteArrayOutputStream output = new ByteArrayOutputStream();
// XML に変換.
marshaller.marshal(o, output);

return new ByteArrayInputStream(output.toByteArray());
}

/* クラスと同一フォルダからスキーマを読み込む。 */
private Schema getSchema() throws SAXException {
SchemaFactory factory = SchemaFactory
.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
if (schemaFile != null) {
return factory.newSchema(schemaFile);
} else {
return factory.newSchema(ClassUtils.getResource(targetClass,
targetClass.getSimpleName() + ".xsd"));
}
}

}

2009年5月27日水曜日

汎用Diffライブラリ

仕事上の必要性にかられ、汎用Diffライブラリを作ってみました。



Diff関連の資料をいろいろと調べたところ、「An O(NP) Sequence Comparison Algorithm」のアルゴリズムがよさそうだったのでこれをもとに実装しています。
実装にあたっては、可読性>メモリ使用量>性能の優先順位をおいて実装しているので性能的には改善の余地があるとは思っています。ただ、自分としてはとにかくシンプルに拡張できることが重要だったのであまり凝った作りにはしていません。

実際に使う場合は、以下の図にあるDiffSourceを実装することで様々なDiffをとることができます。標準の実装として文字列用のDiffStringSourceというクラスが用意してあるので文字列のDiffであればこちらを使用してください。



以下は文字列用のDiffStringSourceを使用したときの結果イメージを示しています。図のようにDiffSequenceに開始、終了インデックスが格納されDiffSequenceのリストとして結果を取得できます。



ソースと結果イメージは次のようになります。
サンプルソース:

public class DiffTest {

public static void main(String[] args)
throws Exception
{

DiffSource s1 = new DiffStringSource("abcdefg");
DiffSource s2 = new DiffStringSource("abzge");
Diff diff = new Diff();
List diffList = diff.diff(s1, s2);
int i = 0;
for(DiffSequence seq : diffList){
if(seq instanceof CommonSequence){
System.out.println(i+":共通部分");
System.out.println(
" source("+seq.getSourceStartIndex()
+","+seq.getSourceEndIndex()
+") = "+seq.getSourceElements());
System.out.println(
" target("+seq.getTargetStartIndex()
+","+seq.getTargetEndIndex()
+") = "+seq.getTargetElements());
}else{
System.out.println(i+":差異部分");
System.out.println(
" source("+seq.getSourceStartIndex()
+","+seq.getSourceEndIndex()
+") = "+seq.getSourceElements());
System.out.println(
" target("+seq.getTargetStartIndex()
+","+seq.getTargetEndIndex()
+") = "+seq.getTargetElements());
}
i++;
}
}
}


結果:
0:共通部分
source(0,2) = ab
target(0,2) = ab
1:差異部分
source(2,4) = cd
target(2,4) = zg
2:共通部分
source(4,5) = e
target(4,5) = e
3:差異部分
source(5,7) = fg
target(5,5) =

2009年4月19日日曜日

MacBook + Intel SSD X25-M で Boot Camp

iPhone Appが気になってとうとうMacBookを購入してしまいました。せっかくなのでこれをメインPCとして使用すべく、内蔵ディスクをIntel SSD X25-Mにしてみました。ここまでは順調だったのですが、欲を出し、さらにBoot CampでWindowsXPを入れようとしたところ、なぜか内蔵ドライブでは、WindowsXPのインストールディスクが起動しない。ネットをいろいろと調べていみるとどうやら同じ症状(起動はするけど認識しない場合もあるようです)の人がかなりいるようで、原因もいろいろな説が飛び交っていました。
最近になってIntel SSDで使用しているIndilinxのチップの問題でNVIDIAのチップセットとのネゴシエーションがうまくいかないらしいことがわかりました。(もっとも、軟弱なJavaプログラマーにはさっぱりわからない世界ですが。。。)

そこでIntelに問い合わせしてみたところ、最新のFirmware(8820)があるので試してみてくださいとのこと。
Intel® SATA SSD Firmware Update Toolのダウロードページへ
早速ダウンロードしてFirmwareをバージョンアップしてみたところ、なんと認識するじゃないですか(やったー!!)。念のためバックアップをとってバージョンアップを行いましたが、幸いディスクの中身は無事でした。しかも性能も向上するようです。ただ、Firmwareのバージョンアップをするには別のPCで行う必要があるのでMacBookしかない人はどうするんだろう?
あと、すべての場合で問題が解決するわけではなさそうなので注意が必要です。
http://www.pcper.com/article.php?aid=691&type=expert&pid=7

早速、Boot CampでWindowsXPをいれ、CrystalDiskMarkで測定してみるとめっちゃ満足な結果となりました。


調子にのって、さらに、Boot CampのパーティションをVMWare Fusionで仮想化してCrystalDiskMarkで測定してみると、なぜか読み取り速度が異常に遅くがっかりな結果に。。。この結果遅すぎない?何かチューニングできないのだろうか?



しかしながら、体感速度的には快適なので問題なし。
これでMacBookさえあればなんでもできる環境になったので、本題のプログラム等の掲載も開始しなければ。。

【2009/11/5 更新】
私が購入した当時(上記内容)は50nm版だったけど、今は34nm版になっている。また、先日SSD(Solid-State Drive)用の管理・最適化ツール「Intel Solid-State Drive Toolbox (v1.1)」とファームウエア・アップデート「Intel SATA SSD Firmware Update Tool (v1.4)」の提供が開始されたようです。ただし、34nm版用の高速化が期待されるtrimコマンドに不具合があったらしく、ファームウェアは提供を中断しているようです。
それから、VMWare Fusionからのアクセスは、Snow LepardにしてもVMWare Fusion3にアップデートしてもほとんど変わらなかった。どうにかならないかな?

【2009/12/5 更新】
ファームウェアの提供が11/30よりされているようです。
ただ、50nmに関しては、変更がないようですね。

2009年1月22日木曜日

ピータッチ2430PC

単なるラベルプリンターですが、PCに接続するだけで専用アプリケーションが立ち上がり、PCにドライバ等をインストールせずに利用可能だそうです。
お手軽さと価格的になかなかのものだと思います。ちょっと前に自分のポストにラベルを付けたのですが、そのときはシールに印刷して作りましたが、出来栄えはいまいちでした。
そのとき、これがあれば迷わず買っていたと思います。。。

2009年1月21日水曜日

SSD[Mtron SSD MOBI 3000]


現在Eee PC 901-Xを所有していますが、最近になってEee PC S101、Sony Type-Pなど魅力的な製品が出てきてもう少し待てばよかったと少し後悔しています。
ただ、後悔ばかりしてもしょうがないのでなんとか今使用しているEee PCをパワーアップさせるべく、いろいろとネットを検索してMtronから出ているSSD MOBI 3000[MSD-PATA3018032-ZIF2]を見つけました。
このSSDはZIFで接続するのですが、ZIFのインタフェースが初期のEee PC 901-Xにしかないらしく、最近のモデルだと自分でZIFのインタフェースを半田付けするしかないようです。半田付けはちょっと。。。でもSSDをつけたいという場合は南烏山という製品があるようです。

いづれにしろ保証外となってしまうのがつらいところですが。。。また、SSDを取り付ける場合、既存のDドライブのSSDは取り外し、CドライブはDドライブとして使用することになります。
あとMOBI 3000にはケーブルが含まれていないので、私の場合は、別途CF (コンパクトフラッシュ) 1.8ZIF変換カードなどを購入してその中の付属品を使用しました。
実際の分解・接続にあっては、こちらなどを参考にしています。取り付けが完了すると上の写真のようになり、BIOSではSecondary Masterとして認識されます。あとは付属のCD-ROMからシステムを普及させれば換装が完了します。
起動速度を測ってみる(下の動画)とだいたい20秒強で立ち上がるようになり、DISKの速度もS101に近い値となりまずまずの結果になりました。実際の使用してみると、以前はときどきもっさりとした感じることもあったのが、待たされている感じがほとんどなくなりとても快適になりました。
これでEee PCももうしばらく活躍させることができそうです。

2009年1月16日金曜日

モバイル無線ルータ[CMR-350]


先日coviaのCMR-350を購入しました。CMR-350は、e-mobileとの組み合わせて使用することによりどこでもアクセスポイントになるルータです。
インタフェースとしてLAN専用ポート、LAN/WAN兼用ポートとUSBが2ポートあります。実際にUSBポートにD11LCを接続してみると左のような感じになります。
写真のようにe-mobileを直接接続でき、ルータ自身がダイアルアップしてくれる点が強みだと思います。
iPod Touch、PSPなどWiFi機能を持った機器をインターネットで接続したいけど近くにホットスポットがないような場合でもこれさえあればどこでもインターネットに接続できます。(コンセントは必要ですが。。)



そのほか次のような機能があり、インターネット上に簡単なサーバーを立ち上げることができます。
・Webカメラサーバー
・ファイルサーバー
・FTPサーバー
・プリンタサーバー
しかもDynamicDNS(DynDNS)にも対応しているので外部からの接続も容易にできます。

製品のページ
http://www.covia.net/main/index.html