駅データベース(2) – 位置情報サービスと連携

前記事に引き続いて、駅データベースを作成を続ける。今回は、位置情報サービス(foursquare/ロケタッチ)と連携する。現時点で、データベースに各駅の経緯度情報を保持しているので、これを使って、自動チェックイン時に必要な位置情報サービスの地点ID(foursquareではvenue id、ロケタッチではスポットID)と紐付ける機能を作成する。

画面は以下のイメージで、前回の画面に「位置情報サービスの地点検索ボタン」「検索結果表示」と、「保存ボタン」を追加した。
xttrw02_a01

  • foursquareの地点検索/表示
    以前作成したfoursquareの検索サーブレットを呼び出す

    //
    function srcSpotFrsq(mode){
      // 指定された駅をキーとして検索サーブレット呼び出し
      searchSpotsFrsqStation(gCurStation, mode, function(spots){
        // 結果表示
        if (spots){
          showSrcSpots(spots, mode);
        }
      });
    }
    
    // foursquareの検索サーブレットを呼び出す
    function searchSpotsFrsqStation(station, mode, callback){
      // mode が'station'の時は駅名を検索パラメータに追加、'all':追加しない
      // 駅の経緯度は常にパラメータとして使用
      // 検索(サーブレット呼び出し)は非同期で実行
      // 結果は独自のspot形式
    }
    
    // 検索ボタンのイベントハンドラ
    //// 検索結果を地図・グリッドに表示する。frsq/loct共通のヘルパー関数
    function showSrcSpots(spots, mode){
      // 地点としての駅を検索時は、結果に「駅」という文字を含むものだけを抽出
      if (mode == 'station'){
        spots = spots.filter(function(item, index){
        if ((item.name).indexOf(gCurStation.station_name + '駅') != -1) return true;
        });
      }
      displayLoctSpots(spots); // 結果をマーカーにして地図に表示
      setDgdSrcSpots(spots);  // 結果をデータグリッドに表示
    }
    
  • ロケタッチの地点検索/表示
    ロケタッチの地点検索は、ブラウザからロケタッチのサーバに直接リクエストを発行する。検索パラメータとして経緯度・結果の最大数を指定し、さらに駅を検索する場合は、駅名もパラメータに追加する。また異なるドメインへのリクエストになるので、JSONP方式による。(以下のサンプルの callback=? の部分。)

    
    https://api.loctouch.com/v1/spots/search?lat=41.990692&lng=140.700333&limit=30&callback=?
    
    

    それ以外はfoursquare とほぼ同じ。

  • 検索結果を保存する
    保存ボタンがクリックされたら、駅データの地点IDプロパティ(foursquare/ロケタッチのそれぞれに定義)に、検索して得られたvenue ID、スポットIDを保存する。

    // JavaScript
    
    $('.btnSaveSpot').live('click', function(){
    
      // datagrid上で選択されているスポットを取得する
      //// 複数行選択不可なので最初の選択行でOK
      var cur_spot = $('#dgdSrcSpots').datagrid('getSelected'); 
      if (cur_spot == null){ // 選択されていない場合はメッセージを表示し戻る
        xumiscMessage('No spot selected.'); return;
      }
      
      // どのボタンがクリックされたかを判別する
      var btn_id = $(this).attr('id'); console.debug($(this).attr('id'));
      
      // 選択されているスポットがfoursquareかロケタッチかを判別する
      var spot_type = checkSpotType(cur_spot.id);
      
      switch (btn_id){
      case 'btnSaveSpot':
        // サービスによって対応するプロパティにスポットIDをセットする
        if (spot_type == 'loct'){
          gCurStation.loc_loct =cur_spot.id;
        } else {
          gCurStation.loc_frsq =cur_spot.id;
        }
      
        // データストアを更新する
        gDSrwStation.dbUpd(gCurStation.station_cd, gCurStation, function(){
          xumiscMessage('Updated. ' + gCurStation.station_name + ':' + 
            spot_type + ' spot_id = ' + cur_spot.id);
        });
        break;
        
      case 'btnSaveSpotE':
        xumiscMessage('Not implemented.');
        break;
      }
    });
    
  • 実行例
    xttrw02_a02
カテゴリー: Development | タグ: | コメントする

JavaScriptのsetTimeout()でパラメータ付き関数を呼び出す

柔軟な記述を許容するJavaScriptならではの方法。

JavaScriptで一定時間ごとに(一定回数)処理を実行したいときは、

  • setInterval()を使う
    setInterval()で処理関数名と実行間隔を指定する。一定回数実行したらclearInterval()でタイマーを止める。
  • setTimeout()を使う
    setTimeout()で処理関数名と待機時間を指定する。これを一定回数実行する。

ことで実現できる。後者を使う場合、以下の記述パターンを紹介した

// JavaScript
function kick(){
  hoge(); // 繰り返しやりたい処理
  setTimeout('kick()',5000); // 5000ミリ秒後にkick()を再実行
}

実行回数が予め決まっている場合は次の記述法も取り得る。(ただし、実行内容は多少異なる可能性がある。)

// JavaScript
function kick(){
  for (var i = 0; i < 3; i++){   
    setTimeout('hoge()',5000 * i); // hoge()の実行タイミングを指定
  }
}

この例では、hoge()は(ほぼ)即時、5秒後・10秒後の3回実行される。

関数hoge()をパラメータ付きで呼び出したいときは、setTimeout(‘hoge(1)’,5000 ); のように記述することで実現できる。このhoge(1) の部分は文字列なので、変数を使って組み立てることもできる。例えば、外部の配列を一定間隔で処理したい場合は、以下のように書ける。

// JavaScript

var gArray = ['a', 'b', 'c']; // 処理対象

// 一定間隔で実行したい関数
function hoge1(idx){
  // 呼び出されるたびに異なる処理対象にアクセスする
  console.debug('called:' + gArray[idx]); 
}

function test1(){
  for (var i = 0; i < gArray.length; i++) {
    var func = 'hoge1(' + i + ')';
    console.debug(func);
    setTimeout(func, 5000 * i);
  }
}

これを実行すると以下の出力が得られる。

hoge1(0) 
hoge1(1) 
hoge1(2) 
called:a 
called:b 
called:c 

ただし、次のような記述は別の関数のローカル変数にアクセスするためエラーが発生する。

// JavaScript
function hoge2(data){
  console.debug('called:' + data);
}

function test2(){
  var lArray = ['a', 'b', 'c'];
  for (var i = 0; i < lArray.length; i++) {
    var func = 'hoge2(lArray[' + i + '])';
    console.debug(func)
    setTimeout(func, 5000 * i);
  }
}

実行結果

hoge2(lArray[0]) 
hoge2(lArray[1]) 
hoge2(lArray[2]) 

Uncaught ReferenceError: lArray is not defined
カテゴリー: Tips | タグ: | コメントする

駅データベース(1) – データビューアの作成

予定表(自動チェックイン)アプリや、列車時刻表を作っていて、鉄道駅のデータベースが欲しいと感じたので、既存サービスを利用しつつ、自前の簡単なデータベースを作ってみる。想定しているのは、
・時刻表アプリを使って乗車予定を作成し、
・その結果をスケジューラに自動登録し、
・予定時刻になったら位置情報サービスに自動チェックインする
という流れで、「訪問予定地(駅)」と「位置情報サービスの地点ID」を紐付けるのが今回の目的。

元になる路線や駅のデータとして、「駅データ.jp」が提供しているものを利用させていただく。

まず、CSV形式で提供される以下のデータを取り込む。

  • 事業者マスタ
    JSON形式に変換し、サーバに配置する(ファイル名:rw_company.json、サイズ:58kb)。
  • 路線マスタ
    JSON形式に変換し、サーバに配置する(ファイル名:rw_line.json、サイズ:231kb)。
  • 駅マスタ
    JSON形式に変換し、サーバに配置する(ファイル名:rw_station.json、サイズ:3,215kb)。あわせて位置情報サービス用の項目を付加し、データストアにも保存する。(JSONファイルは検索用のため、いずれ廃止する想定。)
  • 各マスタの関連(駅.jpサイトより引用)
    stationjp_master

取り込んだデータのビューアを作成する。実装サンプルはこちら。(動作は若干不安定。)

  • 全体イメージ
    上パネルで「事業者名」-「路線名」-「駅名」の絞込み検索を行う。各項目は指定した文字列で検索を行うこともできる。路線名まで絞り込んだら、左パネルに駅リストを、中央パネルに路線地図を表示する。右パネルには選択した駅の詳細情報を表示する。
    xttrw01_b01
  • 事業者・路線・駅検索(リスト)
    各マスタをコンボボックスにマッピングし、絞込み検索を行う。
    xttrw01_b06
    ・事業者を選択中
    xttrw01_b03
    ・路線を選択中
    選択が完了すると、左パネルに駅のリストを、中央パネルに駅の地図を表示する。(全ての駅が表示されるように縮尺を変更する。)
    xttrw01_b04
    ・駅を選択中
    駅の選択は左パネルのリストからも可能。選択した駅の情報を右パネルに表示する。また選択した駅を地図の中心とし、縮尺を変更する。
    xttrw01_b05
  • 乗換駅(同一駅)の表示
    駅は路線に属しているが、(1)同一改札内の駅、(2)改札が異なっていても乗換可能な駅、については路線が異なっていても「同じ駅グループコード」が与えられている。これを使って、駅が選択されたら、同一駅を検索し上パネルの右に表示する。
    xttrw01_b07
    上記の例では、「函館本線の函館駅」に対し、「江差線」「函館市電2系統」「函館市電5系統」の函館駅を表示している。
  • 事業者・路線・駅検索(文字列)
    コンボボックスの右の検索ボックスで、任意の文字列(部分一致)で検索できる。
    ・「東」を含む事業者を検索中
    xttrw01_b08
    ・「東」を含む路線を検索中
    xttrw01_b09
    ・「大阪」を含む駅を検索中-乗換駅(同一駅)もあわせて表示
    xttrw01_b10
カテゴリー: Development, Location Service | タグ: | コメントする

jQuery EasyUI の検索ボックス(SearchBox)を使う

検索用の「テキストボックスと検索ボタン」の組み合わせは使いたい局面が多いが、jQuery EasyUI の検索ボックス(SearchBox)により簡単に実装できる。
xttrw01_a01
説明文字(プレースホルダ)が薄い灰色で表示され、虫眼鏡ボタンがクリックされるか、Enterキーを押すと処理が実行される。

<!-- HTML -->
<input
 id="srcCompany" name="srcCompany" 
 class="easyui-searchbox"           <!-- SearchBox を指定 -->
 style="width:150px" 
 data-options="searcher:searchItem, <!-- イベントハンドラ --> 
 prompt:'Input Company Name'">      <!-- プレースホルダ -->
</input>

クリック時のイベントハンドラ名を’searcher’オプションで指定する。イベントハンドラにはクリック時の入力値と、input要素のnameの値が渡される。複数のSearchBox に異なるname を指定することにより、イベントハンドラを共通化することができる。

<!-- HTML -->
<input name="srcCompany" class="easyui-searchbox" data-options="searcher:searchItem"/>
<input name="srcLine" class="easyui-searchbox" data-options="searcher:searchItem"/>
// JavaScript
// 共通のイベントハンドラ _name の値で処理を分岐する
function searchItem(_value, _name){ // 空白のときは何もしない
  if (_value != '') {
    switch(_name){
      case 'srcCompany': 
        setCbxCompany( filterCompanyByName(_value));
        break;
      case 'srcLine':
        setCbxLine( filterLineByName(_value) );
        break;
    }
  }
}
カテゴリー: Tips | タグ: | コメントする

列車時刻表(第1版)のファイル/データ説明

列車時刻表(第1版)で使用しているJSONファイル/データの説明。

  • コントロールファイル (tt_res3.json)
    路線一覧や各路線のデータ更新日などを格納する。
  • 路線データファイル (T9999999.json)
    駅一覧・列車一覧(時刻)などを格納したファイルで、路線ごとに1つのファイルを構成する。画面で路線が指定されたときに対応するファイルがロードされ、ロードされたデータはローカルストレージに保存される。保存したものより新しいバージョンのデータがない場合は、次回以降ローカルストレージのデータを使用する。
  • 駅一覧 (データストア)
    駅名の一覧はデータストアに格納している。このデータは、今のところ駅名検索にのみ使用している。

内容説明

  • コントロールファイル (tt_res3.json)
    路線ごとのオブジェクトの配列になっている。今のところ、rlで始まる要素とln_modeは使っていない。
    Online JSON Viewer00

  • 路線データファイル
    OuDia形式のファイルを独自形式でJSON形式にしたもので、データ項目は元のOuDiaファイルに準じる。平日(Weekday)、土曜(Saturday)、日祝(Holiday)の各独立したデータを格納している。
    Online JSON Viewer01
    Online JSON Viewer02
  • 駅一覧(データストア)
    主要項目は以下のとおり。
    ・st_key: 駅キー(路線キー+駅連番 9999999_000)
    ・st_idx: 駅連番文字列(’000′, ’001′, …)
    ・st_name: 駅名
    ・st_scale:駅規模(未使用)
    ・st_type:駅タイプ(未使用)
    ・ln_key:路線キー
    ・ln_name:路線名
カテゴリー: Development, Specification | タグ: , , | コメントする

列車時刻表(第1版)の画面一覧

ここまでの作業で、列車時刻表の第1版が完成した。画面は以下のとおり。

  • メイン画面 (#pgTTMain)
    駅・路線を検索し、各一覧画面に遷移する。
  • 路線一覧画面 (#pgTTLineList)
    路線の一覧を表示し、駅一覧・列車一覧画面に遷移する。
  • 駅一覧画面 (#pgTTStationList)
    指定された路線の駅一覧を表示し、駅時刻表画面に遷移する。
  • 列車一覧画面 (#pgTTTrainList)
    指定された路線の列車一覧を表示し、列車時刻表画面に遷移する。
  • 駅時刻表画面 (#pgTTStation)
    指定された駅の時刻表(列車ごとの到着/発車時刻の一覧)を表示し、列車時刻表画面に遷移する。また乗車登録を行う。
  • 列車時刻表画面 (#pgTTTrain)
    指定された列車の時刻表(駅ごとの到着/発車時刻の一覧)を表示し、駅時刻表画面に遷移する。また乗車/下車登録を行う。
  • 乗車一覧画面 (#pgTTRideList)
    登録された乗車の一覧を表示する。また、当該列車・乗車駅・下車駅の時刻表画面に遷移する。
  • 設定画面 (#pgSetting)
    乗車登録用の日付を設定する。また、ローカルストレージに保存した路線データの一覧を表示し、選択したものを削除する。

実行例:

  • メイン画面 (#pgTTMain)
    mttview06_f01
  • 路線一覧画面 (#pgTTLineList)
    mttview06_f02
  • 駅一覧画面 (#pgTTStationList)
    mttview06_f03
  • 列車一覧画面 (#pgTTTrainList)
    mttview06_f04
  • 駅時刻表画面 (#pgTTStation)
    mttview06_f05
  • 列車時刻表画面 (#pgTTTrain)
    mttview06_f06
  • 乗車一覧画面 (#pgTTRideList)
    mttview06_f07
  • 設定画面 (#pgSetting)
    mttview06_f08
  • 乗車登録確認画面
    mttview06_f11
  • 乗車登録後の列車一覧画面
    mttview06_f12
  • 下車登録確認画面
    mttview06_f13
カテゴリー: Development, Specification | タグ: , , | コメントする

列車時刻表(15) – ローカルストレージの管理

現在の実装では、ロードした路線データ(時刻表データ)をローカルストレージに保存している。ユーザ側で管理できるよう、使用中のローカルストレージの一覧を表示し、削除できるようにする。

  • 設定画面(#pgTTSetting)に一覧表を表示する
    <!-- HTML -->
    <ul data-role="listview" id="lvTTSettingLS" data-inset="true"></ul>
    

    ローカルストレージのキー(路線データのファイル名)をリストビューの各行に付加する。

    // JavaScript
    function showLocalStorage(){
      var lvItem = '';
      var lnname = ''; // 路線名
      $('#lvTTSettingLS').empty();
      
      for (var i=0; i<localStorage.length; i++){
        lnname = getObjectByKV(gLines, 'ln_file', localStorage.key(i)).ln_name
        lvItem += '<li data-icon="trash" data-lskey="' + localStorage.key(i) + '">'
          + '<a href="#">'
          + lnname + '<span class="ui-li-aside">' + localStorage.key(i) + '</span>'
          + '</a></li>';
      }
      
      $('#lvTTSettingLS').append(lvItem); $('#lvTTSettingLS').listview('refresh');
    }
    

    実行例:
    mttview06_e01

  • クリック時のイベントハンドラを定義する
    クリックされたら(確認ダイアログの表示はせずに)、該当する路線データをローカルストレージから削除する。

    // JavaScript
    $(this).on('click', '#lvTTSettingLS li', function(){
      // クリックされた行のキーを取得し、ローカルストレージを削除
      localStorage.removeItem($(this).data('lskey'));
      // ローカルストレージ一覧を表示
      showLocalStorage();
    });
    
カテゴリー: Development | タグ: , , | コメントする

列車時刻表(14) – 乗車予定一覧表(続)

前記事に引き続き乗車予定一覧表画面を修正する。

この画面が表示されるのは、
・任意の画面からフッタの’RideList’ボタンをクリックしたとき
・列車から「下車」したとき
で、後者については、下車した駅から別の列車に乗車する可能性が高い。そこで、以下のリンクボタンを追加する。
・下車駅の駅時刻表画面(乗車してきたのと同じ路線)
・駅時刻表の検索画面(下車駅と同じ名称を持つ駅を検索)
mttview06_d01
なお、この画面を表示する前に、路線データがロード済かを確認し、空の場合(初期状態など)にはこれらのボタンを無効化しておく。

駅の検索は’メイン画面’で行う。ボタンがクリックされたタイミングで、メイン画面の検索ボックスに駅名をセットして検索処理を実行する。

// JavaScript
$($this).on('click', '#btnTTRideListSrcStation', function(){		
  // 検索すべき駅名をセット
  $('#srcTTSrcStations').val( gCurRail.stations[gCurStationIdx].st_name );
  // 検索処理実行
  $('#srcTTSrcStations').trigger('change');
  // メイン画面に遷移
  $.mobile.changePage($('#pgTTMain'));
});

例えば、’会津若松駅’で下車した状態で、乗換駅を検索した結果は以下のとおり。(2路線の駅が検索された。)
mttview06_d02
mttview06_d03

あわせてアコーディオンの折り畳み部分にも乗換駅検索ボタンを追加しておく。
mttview06_d04

カテゴリー: Development | タグ: , , | コメントする

列車時刻表(13) – 乗車予定一覧表

乗車予定リストをアコーディオンを使うように変更したので、アイテムに表示したボタンの処理を実現する。

  • 列車時刻表ボタン
    この列車の’列車時刻表画面’に移動する。
  • 乗車駅/下車駅時刻表ボタン
    この乗車の乗車駅/下車駅の時刻表画面に移動する。
  • 削除ボタン
    この乗車を削除する。

mttview06_c01

  • 共通の考え方
    各ボタンは乗車ごとに複数あるので、ボタンごとに同一のクラス(以下の削除ボタンでは “clsBtnRideListDelete”)を指定し、このクラスに対するイベントハンドラを定義する。また、乗車を識別するキーとして、ride_key をdata属性として乗車ごとに指定し、イベントハンドラ内で取り出せるようにする。

    <!-- HTML -->
    <button data-role="button" 
      class="clsBtnRideListDelete"
      data-ridekey="' + rides[i].ride_key + '"
      data-icon="delete">削除
    </button>'
    
    // JavaScript
    // 削除ボタンをクリックした場合の処理
    $($this).on('click', '.clsBtnRideListDelete', function(){
      // クリックした乗車データのキーを取り出す 
      var _ride_key = $(this).data('ridekey');
      // 乗車データを取得
      var _ride = getObjectByKV(gCurRides, 'ride_key', _ride_key);
      // 処理実行
    
    }
    
  • 時刻表ボタン
    時刻表への3つのリンクボタンには同じクラスを指定し、同一のイベントハンドラで処理する。(異なるdata属性を指定し、この値で処理内容を分岐する。) また、時刻表を表示するためには、データのロードが必要なので、選択された乗車から路線を取り出し、路線データをロードする。

    // javascript
    colItem += '<div data-role="collapsible" class="clsColRideList">'
     + '<h3>' + _section + '<span class="ui-li-aside">' + _lnname + '</span></h3>'
     + '<p>' + _trinfo
     + '<button data-role="button" class="clsBtnRideListEdit" data-ridekey="' + rides[i].ride_key + '" data-actmode="mode_train" data-icon="arrow-r">列車時刻表</button>'
     + '<button data-role="button" class="clsBtnRideListEdit" data-ridekey="' + rides[i].ride_key + '" data-actmode="mode_st_on" data-icon="arrow-r">乗車駅時刻表</button>'
     + '<button data-role="button" class="clsBtnRideListEdit" data-ridekey="' + rides[i].ride_key + '" data-actmode="mode_st_off" data-icon="arrow-r">下車駅時刻表</button>'
     + '<button data-role="button" class="clsBtnRideListDelete" data-ridekey="' + rides[i].ride_key + '" data-icon="delete">削除</button>'
     + '</p></div>';
    

    イベントハンドラ

    // JavaScript
    $($this).on('click', '.clsBtnRideListEdit', function(){
    
      var _ride_key = $(this).data('ridekey');
      var _act_mode = $(this).data('actmode'); 
      var _ride = getObjectByKV(gCurRides, 'ride_key', _ride_key); 
    		
      gCurLine = getObjectByKV(gLines, 'ln_key', _ride.ln_key); console.debug(gCurLine);
    
      loadRail(gCurLine, function(){
        switch (_act_mode){
          case 'mode_train':
            gCurTrainIdx = _ride.tr_idx;
            $.mobile.changePage($('#pgTTTrain'));
            break;
          case 'mode_st_on':
            // ...
          case 'mode_st_off':
            // ...
        }
      }
    }
    
カテゴリー: Development | タグ: , , | 1件のコメント

列車時刻表(12) – 乗車予定登録の見直し(コード)

前記事の列車時刻表画面のコードイメージ。

// JavaScript
function showTrain(train){

  // listviewの要素格納用
  var lvItem = '';
  // 駅名、駅到着/発車時刻、駅インデックス
  var _st_name, _st_time, _st_idx;
  // 駅アイコン(固定)
  var _imgItem = '<img src="/images/icon-jqm/tt_station.png" class="ui-li-icon"/>';
  // リンクアイコン:現在のステータス(乗車/下車)により切り替え
  var _iconOnOff = (gRideMode == 'mode_off')? 'signin' : 'signout';
  // リンク先:駅時刻表画面
  var _link = (gRideMode == 'mode_off')? '#pgTTStation' : '';//li要素ごと無効にしたので不要
  // 乗車駅の駅インデックス
  var st_on_idx = (train.tr_direction == 'Kudari')? 
    gCurStationIdx : train.tr_timesAr.length - gCurStationIdx - 1;

  setAButtonLabel($('#btnTTTrainInfo'), toTrainInfo(train) + '-' + gCurRail.diaInfo.ln_name );
  $('#lvTTTrain').empty();

  // 駅ごとに順次処理
  for (var i=0; i < train.tr_timesAr.length; i++ ){

    // 通過/運行なしの場合は表示しない
    if (!(train.tr_timesAr[i]=='P'||train.tr_timesAr[i]=='N'||train.tr_timesAr[i]=='X')){
      // 当駅の駅インデックス
      _st_idx = (train.tr_direction == 'Kudari')? i : train.tr_timesAr.length - i - 1;
      // 当駅の駅名
      _st_name = gCurRail.stations[_st_idx].st_name;
      // 当駅の到着時刻/発車時刻
      _st_time = train.tr_timesAr[i] + ' / ' + train.tr_timesDp[i];

      // 現在のステータス(乗車/下車)と乗車駅によってアイテムの有効/無効を変える
      if (gRideMode == 'mode_off' || st_on_idx < i) {
        // 乗車していない(下車)ケース、または当駅が乗車駅より後ろにあるケースは有効
        lvItem += '<li stationIdx="' + _st_idx + '">';
      } else {
        // 乗車中、かつ当駅が乗車駅より前にあるケースはアイテムを無効化
        lvItem += '<li class="ui-disabled" stationIdx="' + _st_idx + '">';
      }
      // 駅時刻表へのリンクと駅名、時刻、乗車/下車画面へのリンク
      lvItem += '<a href="' + _link + '" data-transition="slide">' + _imgItem + _st_name +
      '<span class="ui-li-aside">'  + _st_time + '</span></a>' +
      '<a href="#pgTTRide0" data-transition="slide" data-icon="' + _iconOnOff + '"></a>' +
      '</li>';
    }
  }
  // DOM構築
  $('#lvTTTrain').append(lvItem);
  $('#lvTTTrain').listview('refresh');
}

実行例:
つばさ121号を選択
mttview06_b05
大宮駅から乗車
mttview06_b06

カテゴリー: Development | タグ: , , | コメントする