オレオレF#コンパイラを作って集合論の記号(∩とか∪とか)の演算子が使えるようにする

を同時に実践しようと思って、F#のコンパイラを半日ほどいじってみました。

F# のコンパイラのソースコードは↓でダウンロードができます。

F# PowerPack with F# Compiler Source Drops – Source Code
https://fsharppowerpack.codeplex.com/SourceControl/latest

中身が見れるということは、修正できるということで、修正できるということは何かあったら自分で修正しろって訳ですね。たぶん。

■なぜ、コンパイラを弄るのか?

F# の場合、演算子は記号の組み合わせで作ります。この記号の組み合わせで、多用な演算子が作れるわけですが「+++」とか「—」とか一定の記号の組みあわせしかできないんですよね。

F# で Fizz-Buzz 番外編 – 新しい演算子の作成と、パイプライン演算子 : @jsakamoto
http://devadjust.exblog.jp/11067474/

を見たあたりから「残念、F# って記号の組み合わせしかダメなのか」と思っていたわけですが、Scala ができるわけだから(できるというのはつい先日知りました。正確には先のオレオレF#コンパイラを作った後に知りました)、F# でできない訳はないだろうってことです。
ただし、Scala の場合は、「演算子」を統一的にメソッドに置き換えるのですが、F# の場合は関数に括弧を入れないので、演算子と関数(キーワード)とは別に管理しているようです。まあ、カリー化をすると、これはこれでいいような気がします。表面的には演算子を関数としても使えるようです。

少しコンパイラを齧った方は分かると思うのですが、コンパイラを作るときには lex と yacc を使って文字解析と構文解析をします。F# には fslex と fsyacc という F# 実装のものがあります。となると、演算子を記号縛りにしているのは lex か yacc あたりを見れば OK と見当がつきます。

集合にはなっていませんが、集合の記号だけ使うと、以下のように演算子を定義しますが…∪のところでエラーになります。

open System
let (∪) x y = x + y
let (∩) x y = x - y

let ans1 = 10 ∪ 20
let ans2 = 10 ∩ 20
printfn "ans1:%A" ans1
printfn "ans2:%A" ans2

なので、代わりに下のような「代替」の演算子を作るわけですが…これって、数式をプログラムに直すときに無駄なギャップになるんですよね。

open System
let (+++) x y = x + y
let (---) x y = x - y

let ans1 = 10 +++ 20
let ans2 = 10 --- 20
printfn "ans1:%A" ans1
printfn "ans2:%A" ans2

できることならば、紙に書いた数式からプログラムコードに平たく直したいのです。そうするほうが、バグが混入しにくくなりますよね。wxMaxima と同じ発想です。

となると、演算子を記号のみにしてしまっている lex の部分に「∩」や「∪」を入れればなんとなるんではないかと。

■F#コンパイラを自前ビルドする

F# PowerPack with F# Compiler Source Drops – Source Code
https://fsharppowerpack.codeplex.com/SourceControl/latest

からソースコードをダウンロードして、compiler\3.1\Nov2013\README.html にある通りに、proto comiler を作ります。開発用のコマンドラインを「管理者権限」で実行して、以下を実行。

  cd src
  gacutil /i ..lkg\FSharp-2.0.50726.900\bin\FSharp.Core.dll
  msbuild fsharp-proto-build.proj
  ngen install ..Protonet40binfsc-proto.exe

これをやらないと、Visual Studio で F# プロジェクトがロードできません。
コンパイラ自体は、Fsc プロジェクトです。文字解析、構文解析の部分は、FSharp.Compiler プロジェクトの
lex.fsl と pars.fsy になります。それぞれ、ビルドを実行すると、fslex と fsyacc が使われます。

ひとまず Fsc をビルドします。結構時間が掛かりますが(10分ぐらい?)ビルドができて、自前のF#コンパイラができます。

■演算子を増やしてみる

最終的には、自由な演算子を作りたいのですが、暫定的に「∩」や「∪」だけを追加します。どうもカリー化の関係で文字解析部分で演算子を記号にしないとうまくいかなそうなのですが、F#の場合、関数定義などは前方参照のみなので、構文解析側(pars.fsy)をうまく修正すれば、回避できそうかなと。再帰関数の rec も外せそうな気がします。

lex.fsl を開いて、174行目あたり

let op_char = '!'|'$'|'%'|'&'|'*'|'+'|'-'|'.'|'/'|'<'|'='|'>'|'?'|'@'|'^'|'|'|'~'|':'
	|'あ'|'い'|'う'|'え'|'お'
	|'∪'|'∩'

な感じで、使いたい演算子を追加します。この部分は [‘あ’-‘ん’]のように範囲指定できるかもしれません(試していない)。

237行目あたりで、以下のように演算子の解析を入れます。

rule token args skip = parse
 | ignored_op_char* ('あ'|'い'|'う'|'え'|'お'|'∪'|'∩') op_char* { checkExprOp lexbuf; PLUS_MINUS_OP(lexeme lexbuf) }
 | ident
     { Keywords.KeywordOrIdentifierToken args lexbuf (lexeme lexbuf) }

キーワードを解析している Keywords.KeywordOrIdentifierToken の前に入れてしまうのがミソです。token を PLUS_MINUS_OP にしていますが、これは何でもOKです。どうせ再定義してしまうので。

これでビルドをしてから、先の F# コードをオレオレF#コンパイラでコンパイルしてみてください。うまくビルドができて、実行できます。ぱちぱちぱち。

open System
let (∪) x y = x + y
let (∩) x y = x - y

let ans1 = 10 ∪ 20
let ans2 = 10 ∩ 20
printfn "ans1:%A" ans1
printfn "ans2:%A" ans2

演算子は「あいうえお」のように複数でも定義できるし「あ+あ+あ」のように元の記号と組み合わせもできます。このあたりは、論理記号、集合論の記号を入れておきたいところです。

数学記号の表 – Wikipedia
http://ja.wikipedia.org/wiki/%E6%95%B0%E5%AD%A6%E8%A8%98%E5%8F%B7%E3%81%AE%E8%A1%A8

■演算子とキーワードをデバッグする

演算子のチェックは checkExprOp で、キーワードのチェックは KeywordOrIdentifierToken で行っているので、ここにデバッグログを入れておきます。

演算子チェックは、lex.fsl 内

let checkExprOp (lexbuf:UnicodeLexing.Lexbuf) =
    printfn "exprOp %A" (lexeme lexbuf)
    if String.contains (lexeme lexbuf)  ':' then
        deprecatedWithError (FSComp.SR.lexCharNotAllowedInOperatorNames(":")) lexbuf.LexemeRange;
    if String.contains (lexeme lexbuf)  '$' then
        deprecatedWithError (FSComp.SR.lexCharNotAllowedInOperatorNames("$")) lexbuf.LexemeRange

キーワードチェックは lexhelp.fs 内

    let KeywordOrIdentifierToken args (lexbuf:UnicodeLexing.Lexbuf) s =
        printfn "keyword %A" s
        if not permitFsharpKeywords && List.mem s unreserveWords then
...

これを入れた状態でF#コードをコンパイルすると、演算子/キーワードの状態がわかります。
あとは、集合論の記号あたりを入れて、ざっと実装していくということで。

カテゴリー: F# | 1件のコメント

艦これのバトルJSONをNetwork Monitorで解析(端歩編)

艦これのバトルJSONを再解析(祥鳳改小破編) | Moonmile Solutions Blog
http://www.moonmile.net/blog/archives/5517

で解析をした後で、hp を減算すれば ok というのは分かったので、さて他の艦これブラウザを見てみると…なんか、もうこれでいいやってな感じになってしまいました。もともと諜報員はデスクトップアクセサリ的に作りたかったわけで、戦略ゲーム的な内容を調査してというのはちょっと苦手で。ただし、デスクトップアクセサリといえば、

<b>MMDDM</b>MMDモデル用デスクトップマスコットツール?-?[?BowlRoll?]
http://bowlroll.net/up/dl30246

が動いているわけで、これでもいいか(偉そう)ってな感じになってます。そうなると、

  • 艦これブラウザで、GUI をまかなう
  • MMDDM で 榛名/ハルナ のマスコットが動く

という2点を満たせればいいわけで(ワタクシ的には)、となるとここの繋ぎの部分を作ればいいわけですね。業務的にもよくあるパターンです。

艦これブラウザは、

回転母港ページ
http://spinpreach.webcrow.jp/SpinHomePort.html
艦これ 司令部室
http://nozomi.arege.jp/KanHQ/
提督業も忙しい! | grabacr.net
http://grabacr.net/kancolleviewer

を使います。後、ブラウザ上(IE,Firefoxなど)で艦これを動かしている場合も含めます。先の艦これブラウザが fiddler を使っているので、fiddler から fiddler をフックすればいいのですが、ちょっとこれがうまくいかず。更に通常のブラウザの場合は fiddler だけではうまくいかないので(タブブラウザなのでピンポイントで proxy を変えることができるのか不明)、network monitor に立ち返って調べています。

Download Microsoft Network Monitor 3.4 from Official Microsoft Download Center
http://www.microsoft.com/en-us/download/details.aspx?id=4865

ネットワークのフックツールが wincap → network monitor → fiddler となっているので、ひとつ手前の技術なのですが、fiddler と違ってネットワーク全体をフックします(ネットワークドライバー系なのか、ちょっと不明)。なので、PC全体のネットワークを監視できますね。当然、proxy 形式の fiddler もフックできます。
逆に、fiddler にできて、network monitor にできないのが、

  • 通信データを改変する。
  • fiddler は HTTP プロトコルに特化していて、C#/VB.NETから扱いやすい。
  • network monitor をインストールする必要がある(多分)

なところです。下りデータの swf や mp3 を改変して「榛名をハルナにする」ことは network monitor ではできませんが、まあ、夜戦前の状態取得とか、Azure mobile service と連携して push 通信とかならできそうです(当然、fiddler でも可能ですが)。あと、network monitor の場合は、データをモニタ型式(たぶん内部的なコピー)で取ってくるので、PCに対するネットワーク負荷が(たぶん)低いと思われます。まあ、これも艦これに対してだけだし、艦これサーバー自体には fiddler でも network monitor でも負荷が低いのは同じなので(むしろブラウザのほうが負荷が高い)そのあたりは問題ありません。

■network monitor で艦これ通信だけ抽出する

Display Filter で以下を設定すれば OK です。SourceAddress は、艦これサーバーなので鎮守府が違うと別IPになります。URIで絞ったほうがいいも

.ProtocolName == "HTTP" and
.HTTP.Response and
.Ipv4.SourceAddress == XXX.XXX.XXX.167

■ヘルプを見る

実は network monitor には api があります。ヘルプもあります。API は wincap だけかと思い込んでいたので、これは結構使えますね。

C:Program FilesMicrosoft Network Monitor 3HelpNetMon.chm

なところに HTML ヘルプがあります。C++とC#の api も API フォルダに NmApi.h や NetmonAPI.cs というファイルであります。ヘルプには api を使ったサンプルが載っているので、これを手がかりにして作っています。

■api を使ってフックする

まだまだ途中ですが、晒しておきます。google で検索してもリアルタイムにフックする方法がなかなか出てこないので。
ハンドルのクローズとか例外処理とかは省いています。

private void Window_Loaded(object sender, RoutedEventArgs e)
{
    // netmon api の初期化
    IntPtr phCaptureEngine = IntPtr.Zero;
    NetmonAPI.NmOpenCaptureEngine(out phCaptureEngine);
    // フィルタを作成
    MyLoadNPL();

    // ネットワークアダプタのチェック(複数差し込み、VMWare Netなど)
    uint ucnt = 0;
    NetmonAPI.NmGetAdapterCount(phCaptureEngine, out ucnt);
    NM_NIC_ADAPTER_INFO adapterInfo = new NM_NIC_ADAPTER_INFO();
    adapterInfo.Size = (ushort)System.Runtime.InteropServices.Marshal.SizeOf(typeof(NM_NIC_ADAPTER_INFO));
    // 4番目のネットワークをフック
    uint ulIndex = 3;
    uint errno = NetmonAPI.NmGetAdapter(phCaptureEngine, ulIndex, ref adapterInfo);
    // モニタの準備
    uint ret = 0;
    IntPtr myTempCap = IntPtr.Zero;
    ret = NetmonAPI.NmConfigAdapter(phCaptureEngine, ulIndex,
        new CaptureCallbackDelegate(FrameIndicationCallback), 
        myTempCap, 
        NmCaptureCallbackExitMode.ReturnRemainFrames);
    // モニタの開始
    ret = NetmonAPI.NmStartCapture(phCaptureEngine, ulIndex, NmCaptureMode.Promiscuous);


}
/// <summary>
/// コールバック
/// </summary>
/// <param name="hCapEng"></param>
/// <param name="ulAdatIdx"></param>
/// <param name="pContext"></param>
/// <param name="hRawFrame"></param>
public void FrameIndicationCallback(IntPtr hCapEng, UInt32 ulAdatIdx, IntPtr pContext, IntPtr hRawFrame)
{

    IntPtr parsedFrame, insertedRawFrame;
    // フレームのパースチェック
    if( NetmonAPI.NmParseFrame(
        _frameParserHandle,
        hRawFrame,
        0,
        NmFrameParsingOption.None ,
        out parsedFrame,
        out insertedRawFrame)  != 0 )
    {
        // NetmonAPI.NmCloseHandle(hRawFrame);
        return;
    }

    // フィルタ
    bool passed = false;
    NetmonAPI.NmEvaluateFilter(parsedFrame, _httpFilterId, out passed);
    if (passed == false)
        return;

    uint ret;
    var name = new char[256];
    // ポインタを直接扱うので unsafe を使う
    unsafe
    {
        fixed (char* value = &name[0])
        {
            ret = NetmonAPI.NmGetFieldValueString(parsedFrame, _uriFeildId, 256, value);
        }
    }
    var bytes = new byte[4000];
    unsafe
    {
        fixed (byte* buf = &bytes[0])
        {
            uint offset, size;
            NetmonAPI.?NmGetFieldOffsetAndSize(parsedFrame, _uriFeildId, out offset, out size);
            Debug.WriteLine("offset:{0} size:{1} ", offset, size);
            // NetmonAPI.NmGetRawFrame(hRawFrame, 4000, buf, out size);
            // Debug.WriteLine("size2 {0}", size);
        }
    }
}

IntPtr _engineHandle, _frameParserHandle, _nplParserHandle, _configParserHandle;
uint _httpFilterId, _uriFeildId;

private void MyParserBuild(IntPtr pCallerContext, uint ulStatusCode, string lpDescription, NmCallbackMsgType ulType)
{
    /*
    // throw new NotImplementedException();
    if (pCallerContext == IntPtr.Zero)
        return;

    GCHandle gch = GCHandle.FromIntPtr(pCallerContext);
    NM_NIC_ADAPTER_INFO adapterInfo = (NM_NIC_ADAPTER_INFO)gch.Target;
        * */
}
/// <summary>
/// フィルタの作成
/// </summary>
void MyLoadNPL()
{
    IntPtr myFrameParser = IntPtr.Zero;
    ulong ret;
    IntPtr myNplParser = IntPtr.Zero;
    IntPtr myFrameParserConfig = IntPtr.Zero;


    // Use NULL to load the default NPL parser set.
    ret = NetmonAPI.NmLoadNplParser(null, NmNplParserLoadingOption.NmAppendRegisteredNplSets, MyParserBuild, IntPtr.Zero, out myNplParser);
    ret = NetmonAPI.NmCreateFrameParserConfiguration(myNplParser, MyParserBuild, IntPtr.Zero, out myFrameParserConfig);
    ret = NetmonAPI.NmConfigConversation(myFrameParserConfig, NmConversationConfigOption.None, true);
    ret = NetmonAPI.NmConfigReassembly(myFrameParserConfig, NmReassemblyConfigOption.None, true);

    uint myHTTPFilterID = 0;
    uint myHTTPFieldID = 0;
    // ret = NetmonAPI.NmAddFilter(myFrameParserConfig, "http.request.command == "GET"", out myHTTPFilterID);
    // ret = NetmonAPI.NmAddField( myFrameParserConfig, "http.request.uri", out myHTTPFieldID);
    // ret = NetmonAPI.NmAddFilter(myFrameParserConfig, "Protocol.HTTP", out _httpFilterId);
    // ret = NetmonAPI.NmAddFilter(myFrameParserConfig, "tcp.Port == 80", out _httpFilterId);
    ret = NetmonAPI.NmAddFilter(myFrameParserConfig, "http.request.command == "GET"", out _httpFilterId);
    ret = NetmonAPI.NmAddField(myFrameParserConfig, "http.request.uri", out _uriFeildId);
    ret = NetmonAPI.NmCreateFrameParser(myFrameParserConfig, out myFrameParser, NmFrameParserOptimizeOption.ParserOptimizeNone);
    _frameParserHandle = myFrameParser;
}

初期化は、
1. NmOpenCaptureEngine で api 初期化
2. NmGetAdapterCount と NmGetAdapter で、フック対象のネットワークアダプタを取得
3. NmConfigAdapter でコールバック関数の登録
4. NmStartCapture でモニタ開始

フィルタ作成は、
1. NmLoadNplParser と NmCreateFrameParserConfiguration で初期化
2. NmAddFilter でフィルタ作成
3. NmAddField でフィールド作成(値を取得するところ)
4. NmCreateFrameParser でパーサの作成
_httpFilterId や _uriFeildId は、グローバルに保存しておいて使いまわしをします。たぶん、コールバックの時に作ってもよいのですが、あらかじめ作ったほうがハンドルとしてベターかと。

コールバック関数には、全ての通信が入って来るのでフィルタで選別します(ここに注意)。
1. 最初に NmParseFrame でパースします。
2. NmEvaluateFilter で、先に作成したフィルタを適用
3. NmGetFieldValueString や NmGetFieldOffsetAndSize などを使って各種フィールドの値を取得

network monitor を調べていくと NPL にぶち当たるのですが、所謂構造体定義です。

Network Monitor Open Source Parsers – Home
http://nmparsers.codeplex.com/

HTTPプロトコルとかICMPプロトコルとか、各種プロトコルを疑似的な構造対で定義します(中身はコードです)。これは、既に network monitor にデフォルトで含まれているので NmLoadNplParser の NmNplParserLoadingOption.NmAppendRegisteredNplSets で読み込ませれば OK です。独自プロトコルを作るときには NPL を作ればいいのでしょう。ここでは HTTP プロトコルしか使わないのでこれで十分です。

netmon api の C# は薄いラッパーなので、NmGetFieldValueString を使った受け渡しはポインタになります。この手のデータを扱うためには unsafe と fixed が必要なのですが…このあたりは C++/CLI で作り直したほうがよさそう。あるいは、string に変換する関数を作るとか。
または HTTP プロトコルしか使わないので、fidder 互換にしてしまうのがよさそうですね。まあ、network monitor 自体が 2010/06 で更新が終わっているので、今更感がありますが。ネットワーク解析的には便利かな。ちなみに、System requirements には Winodws 8 までしか書いてありませんが、Windows 8.1 x64 で動作してます。

カテゴリー: 艦これ | 艦これのバトルJSONをNetwork Monitorで解析(端歩編) はコメントを受け付けていません

艦これのバトルJSONを再解析(祥鳳改小破編)

Fiddlerを使って艦これのバトルJSONを解析(敷波復活編) | Moonmile Solutions Blog
http://www.moonmile.net/blog/archives/5071

結局のところ Feddler 使った諜報ブラウザを作って再び解析。やっぱり夜戦の前とか続行の前とかに「うっかり続行してしまって撃沈」してしまうのもアレなので。いやいや、ゲームとしてはありなんですけどね。

  1. /kcsapi/api_req_sortie/battle
  2. /kcsapi/api_req_sortie/battleresult
  3. /kcsapi/api_get_member/deck
  4. /kcsapi/api_get_member/ship2
  5. /kcsapi/api_get_member/ship3

の順番で流れてくるので順番に調べます。以下、メモ的に。

戦闘を開始すると battle が降ってくるので、

“api_dock_id”:1,
“api_ship_ke”:[-1,510,510,510,505,502,502],
“api_ship_lv”:[-1,1,1,1,1,1,1],
“api_nowhps”:[-1,70,77,45,55,29,74,65,65,65,33,22,22],
“api_maxhps”:[-1,75,77,45,55,32,74,65,65,65,33,22,22],

で敵戦艦の種類とHPを取得。バトル自体の順番は、

“api_hougeki1”:{
“api_at_list”:[-1,2,1,12,6,7,4,5,3],
“api_at_type”:[-1,0,0,0,0,0,0,0,0],
“api_df_list”:[-1,[10],[9],[6],[12],[3],[8],[7],[7]],
“api_si_list”:[-1,7,8,502,7,-1,6,3,-1],
“api_cl_list”:[-1,[2],[1],[0],[1],[1],[1],[2],[1]],
“api_damage”:[-1,[129],[102],[0],[73],[12],[33.1],[28],[65]]
},
“api_hougeki2”:{
“api_at_list”:[-1,1],
“api_at_type”:[-1,0],
“api_df_list”:[-1,[8]],
“api_si_list”:[-1,8],
“api_cl_list”:[-1,[1]],
“api_damage”:[-1,[98]]
},
“api_hougeki3”:null,
“api_raigeki”:null
}

なところで、hougekiX を順番に調べればOK。たぶん、api_at_list のところが味方&敵の攻撃&防御の順番と思う。このあたりはあとで動画キャプチャを利用して突合せ。

戦闘が終わると battleresult が降ってくるので、これで結果をチェック。艦娘の経験値などは

“api_win_rank”:”S”,
“api_get_exp”:60,
“api_mvp”:1,
“api_member_lv”:54,
“api_member_exp”:146241,
“api_get_base_exp”:120,
“api_get_ship_exp”:[-1,432,144,144,144,144,144],
“api_get_exp_lvup”:[[390850,397000],[53943,56100],[41250,43500],[36353,37800],[44292,46500],[5851,6600]],

で取得。

“api_lost_flag”:[-1,0,0,0,0,0,0],

のところは、味方かロスト…だと思う。敵の撃沈がここではわからない?ので、先の api_damage あたりでチェック?

ここで、祥鳳改が「小破」になっているので、

image

続き deck で艦隊に属している艦娘を調べて、

{
“api_member_id”:41898,
“api_id”:1,
“api_name”:”u524du885bu8266u968a”,
“api_name_id”:”110117909,
“api_mission”:[0,0,0,0],
“api_flagship”:”0″,
“api_ship”:[83,252,278,81,288,675]
},

ここの api_ship は「保持してい艦娘」。保持している祥鳳改は「278」なので、ship2 か ship3 で艦娘IDに直すと、「282」が「祥鳳改」とわかる。

{
“api_id”:278,
“api_sortno”:382,
“api_ship_id”:282,
“api_lv”:29,
“api_exp”:[41394,2106,27],
“api_nowhp”:33,
“api_maxhp”:45,
“api_leng”:1,
“api_slot”:[699,700,475,218,-1],
“api_onslot”:[18,12,12,6,0],
“api_kyouka”:[11,0,6,6,0],
“api_backs”:4,
“api_fuel”:40,
“api_bull”:40,
“api_slotnum”:4,
“api_ndock_time”:4260000,
“api_ndock_item”:[15,28],
“api_srate”:1,
“api_cond”:49,
“api_karyoku”:[11,29],
“api_raisou”:[0,0],
“api_taiku”:[30,39],
“api_soukou”:[31,59],
“api_kaihi”:[37,59],
“api_taisen”:[9,0],
“api_sakuteki”:[47,79],
“api_lucky”:[12,59],
“api_locked”:1
},

小破などは、

“api_nowhp”:33,
“api_maxhp”:45,

を見るのだと思う。ここは後で。ちなみに、弾丸と燃料が

“api_fuel”:40,
“api_bull”:40,

入渠がこれ。

“api_ndock_time”:4260000,
“api_ndock_item”:[15,28],

なので、進撃の選択の場合は ship2 が降ってくるので、これから hp を見ればいいんだけど、夜戦の場合は違うようで、battle の後に「夜戦」の選択になるので、battle の api_damage を見て艦娘の hp を減らさないといけない。

多分、艦娘と敵艦の hp と

“api_ship_ke”:[-1,510,510,510,505,502,502],
“api_ship_lv”:[-1,1,1,1,1,1,1],
“api_nowhps”:[-1,70,77,45,55,29,74,65,65,65,33,22,22],
“api_maxhps”:[-1,75,77,45,55,32,74,65,65,65,33,22,22],

バトルの対応(1から12番まで)があるので、これで hp を引けばいい。

“api_hougeki1”:{
“api_at_list”:[-1,2,1,12,6,7,4,5,3],
“api_at_type”:[-1,0,0,0,0,0,0,0,0],
“api_df_list”:[-1,[10],[9],[6],[12],[3],[8],[7],[7]],
“api_si_list”:[-1,7,8,502,7,-1,6,3,-1],
“api_cl_list”:[-1,[2],[1],[0],[1],[1],[1],[2],[1]],
“api_damage”:[-1,[129],[102],[0],[73],[12],[33.1],[28],[65]]
},

演習の場合もいっしょ。小破、大破などは、maxhp が分かっているので hp と比較して割合だと思う。艦娘の名前は先に現れる ship2 などであらかじめチェックしておけばOK。

カテゴリー: 艦これ | 2件のコメント

MVP Community Camp 2014でXamarinの話をします

MVP Community Camp 2014
https://msevents.microsoft.com/CUI/EventDetail.aspx?EventID=1032577010&culture=ja-JP

来る3月22日(土)に東京会場で「Xamarinで作るiPhoneとWindows ストア アプリの共通コンポーネント」というタイトルで話します。iPhoneとWindowsストアアプリ、ってことになっていますが、実際はXamarinでiOS/Android/WinRTで共通のコードを使おう(PLC)ってことです。手元で作っている下なアプリ(というかゲーム)をベースにしてプロジェクト構成とかXamariの使い方とかを話す予定です。ええ、予定ってのは、まだプレゼン資料を作ってないからなんですね。

image

Xamarin自体は、http://xamarin.com/ からダウンロードしてBUSSINESS版が試用期間1か月で試すことができます。最近は、Microsoft MVP の方向け無償 Xamarin Business ライセンスについて – Xamarin 日本語情報 な感じで MVP の方に配っていたりします(これは去年も配っていました)。

プレゼンで発表するのは、Visual Studio との組み合わせで結構な値段($999/年)するほうなのですが、Xamarin Studio だけで開発するならば INDIE版が $299/年 で手に入ります。「結構な値段」というのは、当時会社員だったときMSDNが年間15万円ぐらいを自腹で買っていました。Windows XPとVisual Studio 6.0、Office が手に入ってそれはそれでよかったのですが、Xamarin だと Xamarin だけなんですよね。ただ、前身の MonoDevelop や Xamarin Studio とXcode との連携を考えてみると、それだけの労力はある削減されるような気がするのですが。

ええ、おそらく Xamarin はきっちり「費用対効果」を考えないといけない代物です。そこに対して「先行投資」をしてきちんとペイできるか、を考えないと駄目で「興味」だけでやるには高価な遊び道具ですね。もちろん「高価な趣味」として嗜むのもよいのですが。

そんなことを踏まえてか踏まえてないか、3/22 は品川へどうぞ。ちなみに MvvmCross な話は14:00 からの田中さん担当で。私のところは、普通にPCLの話か、Xamarin で具体的にゲームをつくっていく話です。

カテゴリー: Xamarin, 勉強会 | MVP Community Camp 2014でXamarinの話をします はコメントを受け付けていません

うっかりAndroid SDK ToolsをアップデートしてXamarin StudioのAXMLデザイナが動かなくなった時の対処

現時点 Xamarin Studio 4.2.3 のものなので、いずれ直るかもしれませんが。念のため。

追記 2014/03/19
現在 Xamarin.Android 4.12.x の場合は、逆に Andorid SDK tools ver 22.6.x 以上を要求してきます。そうしないとデザイナが開けません。アップデートした後は SDK Manager で「Android SDK tools」をアップデートのこと

最新のAndroid 4.4.2 API 19 を入れようと思って、同時に「Android SDK tools」を「22.6」にアップデートしてしまうと…

image

こんな風に Xamarin Studio の AXML デザイナが死にます。Disconnected from layout renderer. Please close open the file agein.  というメッセージが出て、閉じて開いてもダメ。
Xamarin Studio の場合はデザイナだけが死ぬですが、Visual Studio の場合は、Visual Studio ごと落ちるという憂き目に。

image

そもそもなんでデザイナだけが落ちるのか分からなかったので苦労したのですが…まあ、最新の Android SDK Tools を入れてダメだったんだから、前のバージョンに戻せばよい。戻せばよいのですが、どうやって戻せばいいのか分かりません。

SDK Tools | Android Developers からダウンロードのページ Android SDK | Android Developers へ行って、下にある DOWNLOAD FOR OTHER PLATFORMS をクリックすると、「最新のバージョン」はダウンロードできます。過去バージョンはどうするかという、アドレスを見て書き換えて、dl.google.com/android/android-sdk_r22.3-windows.zip をダウンロード。

これを解凍すると tools というフォルダがあるので、C:UsersmasudaAppDataLocalAndroidandroid-sdk の中に tools フォルダと置き換えます。すると無事 22.3 のバージョンが戻って AXML デザイナが動きます。めでたしめでたし。

ちなみに、Xamarin Studio 4.2.4 (Alpha版)にアップデートすると、下記のようになります。最悪ですね。

image

Xamarin-Studio Android Form Designer: Android Version not installed – Xamarin を見ると、api 19 にはデザイナが対応してないよってことなんですが、この返答自体が去年の11月なので、tools のアップデートはしなほうがよいかも。バグ報告したほうがいいのかな?

カテゴリー: Xamarin | うっかりAndroid SDK ToolsをアップデートしてXamarin StudioのAXMLデザイナが動かなくなった時の対処 はコメントを受け付けていません

Visual Studio 2013のソリューションをXamarin Studioを編集すると再び開けなくなる、の対処方法

Term Foundation Service を Xamarin から利用する | Moonmile Solutions Blog
http://www.moonmile.net/blog/archives/5461

で Mac 側とソース共有していたら突如として Xamarin Studioでソリューションが開けなくなったので、それの対処方法です。Xamarin Studio 4.2.3 です。

  1. Visual Studio 2013でXamarin.Andoroidのプロジェクトを作って保存
  2. Xamarin Studio で、作成したソリューションを開いて、なんか編集(スタートアプトとか)をして *.sln を保存
  3. 再び、Xamarin Studio を開くとエラーが発生。

image

なんかよくわからないけど、*.sln をメモ帳で開くと、

# Visual Studio 2012
VisualStudioVersion = {0}
MinimumVisualStudioVersion = {0}

な感じになっているので、

# Visual Studio 2013
VisualStudioVersion = 12.0.30110.0
MinimumVisualStudioVersion = 10.0.40219.1

に直します。ベータ版では直っているかもしれませんが、一応。

Windows 上のVisual Studio 2013(Xamarin.iOS)で編集をして、Mac上のXamarin Studioでデザイナ(storyboard)を編集してあれこれやっていたら、発覚した現象でした。これ関係で、Xamarin Studioでデバッグ実行ができなくなっていたのですが、VisualStudioVersion を直したら、うまく動いたので。Xamarin にはバグ報告済みです。

カテゴリー: Xamarin | Visual Studio 2013のソリューションをXamarin Studioを編集すると再び開けなくなる、の対処方法 はコメントを受け付けていません

Windows Azure Mobile Service で独自テーブルを作ってみる

カレンダー – Windows Azure – 技術者でつなぐ日めくりカレンダー の3/4の記事です。関係ないですが、3/4はうちの娘の誕生日です。誕生日プレゼントは何がいい?と聞くと「携帯電話がいい」という答えだったので「みまもり携帯とガラケーとiPhone5cから選べ」と言うと「なんでもいいそうです」欲がないですね…つーか、みまもり携帯だと何にもできないから私が(!)詰まららないですけど。

さて、Windows Azureというと仮想化の話から盛り上がっていたので、それのちょっと前の ひと目でわかるWindows Azureアプリケーション開発入門 を書いた身としては、BLOB と Table ストレージの API はどうなったんですか?ってな感じなのですが、まあ、いまいち Windows Azure に直接接続する API 絡みは流行らなかったんですよね(どうも、Azure 側にいないので事情がよくわからないのですが、感想的に)。当時は、Google の Big Table あたりの話があって、Amazon EC とか「ビックデータ」以前の純粋にでかい検索データをどうやって扱うのか?という点で、BLOB のフラットな構造や SQLと中間的な Table ストレージとかが API 的によいのではないかと思っていたのですが、いやはや、撃沈しております。まあ、そんなにでかいデータなんてそうそう必要ないって現実ですよね。本格的に業務で使うにしても、ほどよい柔軟性とアクセスがしやすければレンタルサーバーで十分な訳です…と思ったけど、仮想化の話が続くのだから、それはそれでVPSの移行なりで辛い思いをするよりはいいのかな?

■モバイルサービスを試してみる

MSDNを持っているので、単体でのWindows Azureの課金状態を忘れてしまったのですが、モバイルサービスでアクセスするデータベースは SQL Serverを使います(内部的にもSQL Serverなのかな?)。以前 SQL Azure と言われていたときはデータベースを扱うときに結構な値段になったので、あまりお勧めできなかったのですが「無料の20MB」ってことで、ちょっとした設定ぐらいならば Azure サーバーに置くのもありかな、と思ったりします。大量なデータは BLOB やらテーブルストレージやらがいいんでしょうが、そんなことをするよりも仮想マシンを使ってMySQLに落とし込んだほうが楽みたいですね。

image

モバイルサービス自体が何ぞや?ってことに関しては、モバイル サービス | Windows Azure と読む…のかな。プッシュ通知にメリットは、【第1回】がりっち勉強会 in 東京開催しました!! | がりっち勉強会 あたりにあります。自前サーバーを作らなくてもモバイルサービスを使えばプッシュ通知が作れますって話です。

簡単なToDoアプリのサンプルは、モバイルサービスを作ったあとにクイックスタートから各種のサンプルアプリがダウンロードできます。

image

※あれ?PhoneGapがあるけど最近増えましたっけ?

■ToDoサンプルのテーブル

自動作成されるテーブルは、こんな感じです。

image

Azure側のファイアーウォールを設定してやると、SQL Server Management Studio でも接続できます。データの編集とかはこっちのほうが楽でしょう。

image

CREATE TABLE [todomasuda].[TodoItem](
	[id] [nvarchar](255) NOT NULL,
	[__createdAt] [datetimeoffset](3) NOT NULL,
	[__updatedAt] [datetimeoffset](3) NULL,
	[__version] [timestamp] NOT NULL,
	[text] [nvarchar](max) NULL,
	[complete] [bit] NULL,
PRIMARY KEY NONCLUSTERED
(
	[id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
)

というテーブルが作られますが、これを独自に作ってみましょう、ってのがこの記事の本題です。やっと本題ですね。ToDoアプリだけダウンロードして、その先はどうするの?ってことで途方に暮れてしまったので、そのメモもかねて。

■独自にテーブルを作る

「データ」→「作成」で新しいテーブルを作ります。

image

新しいテーブルができたら、テーブル名をクリックして「列」タブを選択します。

image

文字列型のid列と、その他(__createdAt, __updatedAt, __version)という列が作られます。どうやら、この4つの列があれば最低限動きそうですね。

「Add COLUMN」(日本語化されてませんね)をクリックして「列を追加」します。

image

データ型は、String(文字列)、Number(数値)、Date(日付)、Boolean(ブール値)の4種類だけです。

image

こんな風に対応します。数値はfloatになってます。普通にCREATE文で作ると int 型もできると思ったのですが…Azure側で認識してくれないっぽいので、alter を使うのかな?

image

■テーブルをアクセスするクラスを作る

まずは、プロジェクトに windowsazure.mobileservices のモジュールを Nuget でインストールします。

image

データモデルのクラスを作ります。Azure側の列名と同じにしておくと JsonProperty の属性はいりません。クライアント側のコード規約とかがある場合は設定したほうがいいでしょう。

class OriginalTable
{
    public string id { get; set; }
    public string firstname { get; set; }
    public string lastname { get; set; }
    public DateTime birthday { get; set; }
    public int age { get; set; }
}

リストを取得して表示するだけのコード

public partial class MainWindow : Window
{
    public static MobileServiceClient MobileService = new MobileServiceClient(
        "https://todomasuda2.azure-mobile.net/",
        "<アクセスキー>"
    );

    public MainWindow()
    {
        InitializeComponent();
    }

    /// <summary>
    /// データを取得
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private async void Button_Click(object sender, RoutedEventArgs e)
    {
        var t = MobileService.GetTable<OriginalTable>();
        var data = await t.ToListAsync();
        dg.ItemsSource = data;
    }
}

MobileServiceClient クラスのコンストラクタを作っておいて、GetTable でテーブルを取得。そのあとは LINQ で取得できます。ここでは全件取得しているので ToListAasync しているだけですが、Where 句などを使えます。ここのクエリは API を呼び出すときに検索文字列(のようなもの)に変換されるので、検索を絞ればトラフィックは小さくなります。

データの挿入とか削除は Azure からダウンロードできるサンプルを参照ということで。ここのサンプルは時間を取ってあとで公開しておきましょう。

image

そんな訳で9歳の誕生日おめでとう&Azureの日本データセンターおめでとうございます、という親バカ記事でした。

カテゴリー: 開発, Azure | Windows Azure Mobile Service で独自テーブルを作ってみる はコメントを受け付けていません

1年間利用したSSDは遅くなるか?,,,というのは幻想でした

最強開発PCの HDDのアクセススピードは VMWare に影響するのか? | Moonmile Solutions Blog と比較して、1年間使ったSSD/HDD のスピードを確かめてみます。

左が1年前の新品、右が現在です。

image

全然変わっていませんね。数値は誤差の範囲です。このPCにはVisual Studio, VMWare等、もろもろの開発環境が入っているので相当ハードに使っています。何度かビデオドライバーの不具合でクラッシュ(ブルースクリーン)していますが、その他の問題は出ていません。先週あたり起動直後のUSB接続のキーボードの反応が悪かったのですが、なぜか最近直りました。

念のため同じように、DドライブのHDDも調べてみましょう。

左が1年前の新品HDD(2TB)、右が現在です。

image

比べてみると、遅くなっている?ってほど遅くはないですよね。Dドライブは作業用に使っているので、これも頻繁に読み書きしていた領域です。つまりは「SSD/HDDは、数年使うと遅くなる」ってのが幻想かも。

まあ、Windows XPの頃(だったか?)とは違って、Windows 8.1 の場合は定期的にデフラグが走るのでファイルが再配置されてそれほど遅くならないのかもしれません。このあたりは、体感速度的なものが大きいのでこの手のベンチマークでは現れないのかもしませんが。

カテゴリー: 最強.NET開発PC | 1年間利用したSSDは遅くなるか?,,,というのは幻想でした はコメントを受け付けていません

Term Foundation Service を Xamarin から利用する

旧 Team Foundation Services(新 Visual Studio Online)は、Visual Studio 2013 から接続する場合、TFS と Git が選べます。私の場合、もともと TFS で業務アプリのソース管理をしているので、そのまま使ってみたのですが、いやいやいや、Xamarin Studio からは Git と Subversion しかアクセスできないので、TFS 側も Git を利用するようにしないとダメっていうオチです。image

■作成するときに Git を指定する

プロジェクトを作成するときに「Version Control」で「Git」を選択します。

image

■Visual Studio Online の Git アドレスは何処にあるのか?

  1. Visual Studio 2013を起動して、
  2. チームエクスプローラーで TFS へ接続
  3. プロジェクトを右クリックして「複製」を選択すると、ローカル Git リポジトリにアドレスが表示されます。「https//<TFSの名前>.visualstudio.com/defaultcollection/_git/<プロジェクト名>」となっているはずです。

image

■Xamarin Studio で Git を指定する。

Xcode のデザイナを使う場合には、Xamarin Studio for Mac が必須なので、プロジェクトのソースをやり取りできるように共有させておきます。

  1. Xamarin Studio を起動
  2. メニューから「Version control」→「Check out」を選択して、git のリポジトリを指定する。
  3. 後は、普通に Git からダウンロードする。

image

Git の場合 TFS と違って、コミット → プッシュの順番になるのが VSS とかに慣れている場合、注意したいところ。コミットをした後でも、まだ Git サーバーにアップされていないという状態なので。

カテゴリー: Xamarin | Term Foundation Service を Xamarin から利用する はコメントを受け付けていません

Xamarin から BlueStacks を使って実行する

BlueStacks ってのは、Windows や Mac 上の Android エミュレータです。デバッグ用ではなくて、巷の Android ゲームを動かすための仕組みなのですが、これを Xamarin から使ってみます。

Android エミュレータは、Android SDK の高速エミュレータ、使ってますか? | OPTPiX Labs Blog にある Intel Atom (x86) Android エミュレータ を使えばいいんですが、これに必要な「Intel VT」が手元の VMWare と競合してしまうために動きません。まあ、BlueStacks 自体は仮想環境上では動かないので、実機 PC に入れないとダメという制約はあるのですが。後、試してみるとデバッグモードでは動かなくて、リリースモードだけ実行できます。なので、ブレークポイントを置けないので、ログ出力とか何らかの print デバッグをしないとダメっぽいです。素直に実機接続をしたほうがいい、ってのもありますね。

BlueStacks のインストール自体は、日本語Windows 8 Pro で Kindle を動かす方法 | Moonmile Solutions Blog を参考にしてください。

BlueStacks と visual studio + xamarin は同じPCで動作させます。

BlueStacks を起動して、adb devices を実行すると「emulator-5554」が実行された状態になる(このエミュレータ名は異なる可能性あり)

adb tcpip 5555 を実行してポートを開く。

adb connect localhost を実行してポートにつなげる。

image

adb devices を実行すると「localhost:5555」に接続できる。これが先の「emulator-5554」=bluestakcs .

Target Android Devices を更新するために、Visual Studio を再起動する。すると、エミュレータの「Samsung GT-N7000」が出てくる。モデル名は異なる場合あり?

image

Android プロジェクトのプロパティで、API バージョンを揃えて置く。最新の BlueStacks は Android 4.0 だそうなので、これにしておく。

image

デバッグビルドして実行すると、以下のようなエラーが出て実行できない。

image

Loaded assembly: Mono.Android.dll [External]
02-17 11:49:03.560 V/dalvikvm(27932): +++ not scanning ‘/system/lib/libwebcore.so’ for ‘register’ (wrong CL)
02-17 11:49:03.560 V/dalvikvm(27932): +++ not scanning ‘/system/lib/libmedia_jni.so’ for ‘register’ (wrong CL)
02-17 11:49:03.560 V/dalvikvm(27932): +++ not scanning ‘/system/lib/librs_jni.so’ for ‘register’ (wrong CL)
02-17 11:49:03.560 V/dalvikvm(27932): +++ scanning ‘/data/data/SamplePazzle.Android/lib/libmonodroid.so’ for ‘register’
02-17 11:49:03.560 V/dalvikvm(27932): +++ calling dlsym(Java_mono_android_Runtime_register)
Loaded assembly: System.Core.dll [External]
02-17 11:49:03.560 V/dalvikvm(27932): Found ‘Java_mono_android_Runtime_register’ with dlsym – func=0xab9e7805
Loaded assembly: MonoDroidConstructors [External]
Loaded assembly: System.dll [External]
プログラム ‘Mono’ はコード 0 (0x0) で終了しました。
Couldn’t connect to logcat, GetProcessId returned: 0

よくわからないけど、リリースモードで実行するとうまくいく。

image

BlueStacks は、こんな風なゲームも動くので、大抵のものなら大丈夫なはずです。ただし、OpenGL(かな?)の調子が悪いらしく私のPCのグラボ上では再描画がちかちかしていますが。

image

というわけで、かなり制限がありますが、VS2013 + Xamarin + BlueStacks で Android の実行ができます。制約としては、

  • BlueStacks は仮想環境(VMWare上)では動かないので、実PCで動かす必要がある。
  • Xamarin と BlueStacks は同じPCで動かす必要がある。
  • デバッグ実行ができず、リリースモードでの実行のみ可能。

せめて、ログが出ればいいんですけどね。これはあとで調べてみます。

カテゴリー: Xamarin | Xamarin から BlueStacks を使って実行する はコメントを受け付けていません