2011年6月20日月曜日

ブラウザ三国志 経路算出:ChromeExtensionを改良

さて前回ダイクストラで最短経路を算出してみました。
このままではもちろんダメで何がダメかというと、
マップ見るたびに経路計算をしてしまうというダメダメな仕様。

このままでは通常時マップを見る時に計算してしまう。
ただ線引くだけのくせに、、、ジャマ!アンインストール。である。

なのでGUIを作って(無駄に画面だけあったけど><)
そこでON/OFFできるようにする。せっかくなので座標を貯めこむ。

で座標を指定して経路を算出!みたいな感じである。

前回利用したcontent_scriptsとページ間のリソースの共有は基本的にできません。
コンテキストスクリプトは拡張機能というよりWebページに埋め込む。という仕組みである為、
拡張機能とは隔離されているもの。という風にできています。

そこでbackgroundという仕組みを利用します。manifest.jsonに以下を追加します。

  1. "background_page": "html/background.html",  


全体はココ

で、イベントによる受け渡しをやるわけですが、以下が概要です。



こういう風にしたいと思います。

座標を保存する

まず、content_script により、51x51マップの時に、座標を吸い上げて以下を行います。

  1. var map = document.getElementById( "map51-content" );  
  2. if ( map == null ) {  
  3.  return false;  
  4. }  
  5.   
  6. var pointArray = [];  
  7. var mapUlList = map.getElementsByTagName("ul");  
  8. for ( var ulIdx = 0; ulIdx < mapUlList.length; ++ulIdx ) {  
  9.   var mapLiList = mapUlList[ulIdx].getElementsByTagName("li");  
  10.   for ( var liIdx = 0; liIdx < mapUlList.length; ++liIdx ) {  
  11.     var linkTag = mapLiList[liIdx].getElementsByTagName("a")[0];  
  12.     var point = createPoint(linkTag);  
  13.     pointArray.push(point);  
  14.   }  
  15. }  
  16.   
  17. //バックグラウンドで保存する  
  18. chrome.extension.sendRequest( {   
  19.   action : "save" ,  
  20.   args : [pointArray]  
  21.  } , function( response )  {  
  22.   //戻り値処理  
  23.   console.log(response);  
  24.  }  
  25. );  


以前処理した時と同じように座標オブジェクトをcreatePoint()によって作成しています。
ここで重要なのは、chrome.extension.sendRequest()により、イベントを発生しています。

これはbackgroundで以下のように処理して、イベントを待機しています。

  1. var CMD = {  
  2.     isSaveMode    : isSaveMode ,  
  3.     save      : save ,  
  4.     analysisDijkstra : analysisDijkstra   
  5. };  
  6.   
  7. function init() {  
  8.     chrome.extension.onRequest.addListener( function ( message , sender , sendResponse) {  
  9.         var retVal = CMD[message.action].apply(this,message.args);   
  10.         sendResponse( { values : retVal } );  
  11.     } ) ;  
  12. };  


backgroundの処理はブラウザが立ち上がった瞬間に始まりますので
そこでinit()を呼び出してあげます。
CMDはmessageによりメソッド名を送ってそれを実行する為の配列ですね。
自分で判定文を作って、関数を作っても良いのですが、こうしておくと、やりとりが増えても大丈夫です。

listenerですのでsendRequest()を呼んであげたらここが呼び出されるので
「save」というactionを呼び出してる感じ。argsにはオブジェクトのリストを渡してます。

ここでオブジェクトに変換せずにそのままHTMLのDOMを送りたい所ですが、
この通信手段にはJSONが使われているみたいで、その引数の変換時にデータ内に改行が存在してしまい、変換に失敗するようです。

で受け取ったbackgroundはリストにより、座標を保存します。

  1. function save( mapArray ){  
  2.  for ( var idx = 0; idx < mapArray.length; ++idx ) {  
  3.   var point = mapArray[idx];  
  4.      localStorage[point.x + ":" + point.y] = JSON.stringify(point);  
  5.  }  
  6. };  


こんな感じですね。

localStorageは「WebStorage」と呼ばれるHTML5的な新しい技術で拡張機能として専用のサンドボックス内にデータを保存するような仕組みです。
配列と同じようにして保存する事が可能です。
"他のブラウザで、、、"って一瞬思いましたが、冷静に考えればChromeExtensionでした><。

localStorageには文字列が保存できるので JSON.stringify(point);で文字列にして保存しています。
※使っている場所ではJSON.parse()を実行しています。

これで座標を保存ができるようになったわけです。
実際にはGUIを利用して、「保存モード」かを判定して処理を行っています。
※それも通信とlocalStorageを利用してから実現しています。


経路の計算を行う

これで十分座標は保存できたと考えて、
次は画面操作との兼ね合いです。とは言っても簡単なHTMLですので、そんなに難しい事はしていません。



こういう画面です。
ソースはココ

※経路表示はまだ実装してないです><

この画面から経路算出の為に座標をbackgroundに渡して
※座標は保存するようにしたので、引数では渡してませんけど><
そこから経路算出を行っています。そこから戻り値で、経路情報を返しています。

ソース自体はgithubにすべておきました。
ダイクストラの大部分は変更していませんが、

・51x51の配列を使わないようにした。
・座標データはlocalStorageにある

って事で、直接座標データを取って処理しています。
※色々改良する余地はあると思います。

さて、これでWebページの情報を残して処理をするという基本アーキテクトの変更は可能になったわけです。
次回はbackgroundを利用して、経路表示も行いたいと思います。

1 件のコメント:

匿名 さんのコメント...

一ブラウザ三国志プレイヤーです。(mixiじゃなくて公式の方ですが……)
ブログがためになりました。
丼ちゃんゴンを公式鯖(m21ではなくs21)でも使えるようにしたいのですが、書き換えとか出来ますでしょうか?

できればお教えくださいますと幸いです。