Say Numbersその2: プロジェクトの準備とサービスの作成

このブログで一からプロジェクトを作ります。書く手順はOS XのXamarin Studioに対しますが、Visual Studioでも行えるはずです。新規「Blank Xamarin.Forms App」を作って適当なIDとSayNumbersというタイトルを付けましょう。今の段階で4つのプロジェクトが入っているはずです: SayNumbers.iOS、SayNumbers.Droid、SayNumbers.SharedとSayNumbers.UITests。それぞれのプロジェクトを設定しましょう。

SayNumbersプロジェクトのSayNumbers.csを削除しましょう。このブログを書いた時点ではMvvmCrossのNugetはバージョン3以外がうまくいきませんが、解決としてpackages.configファイルをこの内容に切り替えてください。


<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="MvvmCross.HotTuna.Binding" version="4.0.0-alpha9" targetFramework="portable-net45+win+wp80+MonoTouch10+MonoAndroid10+xamarinmac20+xamarinios10" />
<package id="MvvmCross.HotTuna.CrossCore" version="4.0.0-alpha9" targetFramework="portable-net45+win+wp80+MonoTouch10+MonoAndroid10+xamarinmac20+xamarinios10" />
<package id="Xamarin.Forms" version="1.4.4.6392" targetFramework="portable-net45+win+wp80+MonoTouch10+MonoAndroid10+xamarinmac20+xamarinios10" />
</packages>

これで正しいフレームワークが入ってきます。そして、「packages」フォルダーに右クリックして「Restore」を押しましょう。

Androidの方では、MainActivity.csを消してpackages.configを以下の内容にしましょう。


<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Cirrious.MvvmCross.Forms.Presenter" version="3.5.2-alpha2" targetFramework="MonoAndroid50" />
<package id="MvvmCross.HotTuna.Binding" version="4.0.0-alpha9" targetFramework="MonoAndroid50" />
<package id="MvvmCross.HotTuna.CrossCore" version="4.0.0-alpha9" targetFramework="MonoAndroid50" />
<package id="MvvmCross.HotTuna.MvvmCrossLibraries" version="4.0.0-alpha9" targetFramework="MonoAndroid50" />
<package id="Xamarin.Android.Support.v4" version="22.2.1.0" targetFramework="MonoAndroid50" />
<package id="Xamarin.Forms" version="1.4.4.6392" targetFramework="MonoAndroid50" />
</packages>

そしてiOSではAppDelegate.csを消してpackages.configを以下の内容にしましょう。


<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Cirrious.MvvmCross.Forms.Presenter" version="3.5.2-alpha2" targetFramework="xamarinios10" />
<package id="MvvmCross.HotTuna.CrossCore" version="3.5.2-alpha2" targetFramework="xamarinios10" />
<package id="MvvmCross.HotTuna.MvvmCrossLibraries" version="3.5.1" targetFramework="xamarinios10" />
<package id="MvvmCross.PortableSupport" version="3.5.2-alpha2" targetFramework="xamarinios10" />
<package id="Xamarin.Forms" version="1.4.4.6392" targetFramework="xamarinios10" />
</packages>

さて、サービスに進みましょう。整数を画面に出すためにフォーマットするサービスを作ります。Servicesというフォルダーを作ってINumberConversionService.csNumberConversionService.csというファイルを追加しましょう。

INumberConversionService


これがサービスのインターフェースで、3つの関数を定義します。

string ToEnglish(int intValue);
string ToJapanese(int intValue);
string ToFormattedNumber(int intValue);

最初の関数は数字を英単語にする役割をします(例: 123 -> One Hundred Twenty Three)。2つ目の関数は日本語で出します(例: 54321 -> 5万4321)。そして、最後の関数はアメリカ英語のフォーマットで数字を出します(例: 654321 -> 654,321)。

NumberConversionService


こちらはINumberConversionServiceを実装するクラスです。プラットフォーム固有の機能を必要としないためにこの段階で実装することは可能です。このようにインターフェースを作るのは無駄だと思うかもしれませんが、例えばユニットテストの場合クラスを切り替えたかったら簡単にできます。数字を英単語にすることで始めましょう。嬉しいことで、数字の英単語には繰り返すパターンがあり、こう定義できます: [3桁数字] [ID] [3桁数字] [ID]、など。[ID]は「Thousand」や「Million」になります。それに、[3桁数字]にもパターンがあります: [数字] Hundred ([十欄][数字] | [特別])。[数字]はそのまま「One」から「Nine」で、[十蘭]は「Twenty」から「Ninety」で、[特別]は「Ten」から「Nineteen」です。アルゴリズムは1の位から始まって最大の位まで処理します。ソースは以下になります。

まず定数を定義します:

private static readonly string[] NUMBER_STRINGS = { String.Empty, "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Eleven", "Twelve", "Thirteen", "Fourteen", "Fifteen", "Sixteen", "Seventeen", "Eighteen", "Nineteen" };

private static readonly string[] TENS_STRINGS = { String.Empty, String.Empty, "Twenty", "Thirty", "Forty", "Fifty", "Sixty", "Seventy", "Eighty", "Ninety" };

private static readonly string[] PLACES_STRINGS = { String.Empty, "Thousand", "Million", "Billion" };

そして関数はこちら:

var sb = new StringBuilder();
int val = intValue;
int place = 0;
while(val > 0) {
    sb.Insert(0, " ");
    sb.Insert(0, PLACES_STRINGS[place++]); // [Identifier]
    var remainder = val % 1000; // [Three Digit Number]
    var hundredsPlace = remainder / 100;
    var tensPlace = (remainder / 10) % 10;
    var onesPlace = remainder % 10;

    sb.Insert(0, " ");
    if(tensPlace == 1) { 
        sb.Insert(0, NUMBER_STRINGS[10 + onesPlace]); // [SpecialTeen]
    } else { 
        sb.Insert(0, NUMBER_STRINGS[onesPlace]); // [Digit]
        if(!String.IsNullOrEmpty(NUMBER_STRINGS[onesPlace])) {
            sb.Insert(0, " ");
         }
        sb.Insert(0, TENS_STRINGS[tensPlace]); // [Tens]
    }

    if(hundredsPlace > 0) {
        sb.Insert(0, " Hundred ");
        sb.Insert(0, NUMBER_STRINGS[hundredsPlace]); // [Digit]
    }

    val /= 1000;
}

return sb.ToString().Trim();

この関数に比べて残りの2つはわりと簡単です。ToJapaneseを定義しましょう。

まず、追加の定数が必要です(「万」と「億」)。

private static readonly string[] JP_PLACES_STRINGS = { String.Empty, "万", "億" };

それでアルゴリズムを実装します。4桁と上の定数を加えるシンプルなアルゴリズムです。

var sb = new StringBuilder();
int val = intValue;
int place = 0;
while(val > 0) {
    sb.Insert(0, JP_PLACES_STRINGS[place++]);
    var remainder = val % 10000;
    sb.Insert(0, remainder);

    val /= 10000;
}

return sb.ToString();

最後の関数はとても簡単です。3桁とコンマを出力するだけです。

var sb = new StringBuilder(intValue.ToString());
for(int i = sb.Length - 3; i > 0; i -= 3) {
    sb.Insert(i, ',');
}

return sb.ToString();

それらによってサービスが完成しました。このセクションは終わります。次のブログではビューモデルの処理を行います!

Advertisements

One thought on “Say Numbersその2: プロジェクトの準備とサービスの作成

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s