Advent LINQ (5): Flatten

Advent LINQ (3)で、フォルダを探索しながらファイルを列挙するFilesAsEnumerableを作った。このような、木構造のシーケンスを探索するというシチュエーションは、色々ありそうだ。なので、このアルゴリズムを一般化する事を考える。

public static class LinqExtensions
{
    public static IEnumerable<U> Flatten<T, U>(
        this T node,
        Func<T, IEnumerable<T>> predictBySubNode,
        Func<T, IEnumerable<U>> predictByNode)
    {
        var bySubNode =
            from subNode in predictBySubNode(node)
            from childNode in Flatten(subNode, predictBySubNode, predictByNode)
            select childNode;

        var byNode =
            from childNode in predictByNode(node)
            select childNode;

        return bySubNode.Concat(byNode);
    }
}

これを使ってファイルの探索を行うには、以下のように記述する。

var baseDirectory = new DirectoryInfo(@"C:project");
foreach (var file in baseDirectory.Flatten(
    directory => directory.GetDirectories(),
    directory => directory.GetFiles("*.cs")))
{
    Console.WriteLine(file.FullName);
}

XmlDocumentから、テキストノードを抜き出してみる。

var document = new XmlDocument();
document.Load(@"C:projectdata.xml");
foreach (var text in document.DocumentElement.Flatten(
    element => element.SelectNodes("*").Cast<XmlElement>(),
    element => element.SelectNodes("text()").Cast<XmlText>()))
{
    Console.WriteLine(text.Value);
}

もちろん、XDocumentにも応用可能。

Advent LINQ (4): Buffering

列挙子を非同期で実行して、可能なら結果をキューに蓄積したい場合がある。列挙子の要素生成速度が十分に早ければ、並列実行出来ることになる。
並列実行コレクションに、丁度この目的に使えるBlockingCollectionクラスがある。

public static class LinqExtensions
{
    public static IEnumerable<T> Buffering<T>(this IEnumerable<T> enumerable, int queueCount = 10)
    {
        var queue = new BlockingCollection<T>(queueCount);
        Task.Factory.StartNew(() =>
            {
                try
                {
                    foreach (var value in enumerable)
                    {
                        queue.Add(value);
                    }
                }
                finally
                {
                    queue.CompleteAdding();
                }
            });

        return queue.GetConsumingEnumerable();
    }
}

使うときは、非同期化したい列挙子の直後に指定するだけだ。

var r = new Random();
foreach (var value in
    Enumerable.Range(0, 1000000).
    Select(index => r.Next()).
    Buffering(1000))
{
    Console.WriteLine(value);
}

これで、乱数の生成は最大1000個まで非同期で実行されてバッファリングされる。コンシューマー側(foreach)の処理が遅く、乱数の生成が早ければ、効率よく動作する。

Advent LINQ (3): FilesAsEnumerable

Directory.GetFilesが配列を返すので、列挙子にしてみる。特にSearchOption.AllDirectoriesが指定されると、処理が返って来るまでにかなり時間がかかることがある。
フォルダーは再帰探索する必要があるので、実装は少し捻る必要がある。

public static class LinqExtensions
{
    public static IEnumerable<string> FilesAsEnumerable(string path, string patterns)
    {
        foreach (var directoryPath in
            Directory.GetDirectories(path, "*", SearchOption.TopDirectoryOnly))
        {
            foreach (var filePath in
                FilesAsEnumerable(directoryPath, patterns))
            {
                yield return filePath;
            }
        }

        foreach (var filePath in
            Directory.GetFiles(path, patterns, SearchOption.TopDirectoryOnly))
        {
            yield return filePath;
        }
    }
}

これでもいいのだが、foreachだらけで見通しが悪い。全てクエリに置き換える。

public static class LinqExtensions
{
    public static IEnumerable<string> FilesAsEnumerable(string path, string patterns)
    {
        var byDirectory =
            from directoryPath in Directory.GetDirectories(path, "*", SearchOption.TopDirectoryOnly)
            from filePath in FilesAsEnumerable(directoryPath, patterns)
            select filePath;

        var byFile =
            from filePath in Directory.GetFiles(path, patterns, SearchOption.TopDirectoryOnly)
            select filePath;

        return byDirectory.Concat(byFile);
    }
}

これでファイルの列挙は以下のように記述できる。

foreach (var path in LinqExtensions.FilesAsEnumerable(@"C:project", "*.cs"))
{
    Console.WriteLine(path);
}

ファイルの逐次探索が可能になったので、大量のファイルをパイプライン処理できるようになった。
なお、このコードは.NET 4.0以降では、Directory.EnumerateFilesとほぼ同じ動作となる。

Advent LINQ (2): TextReader.AsEnumerable

TextReaderで読み取れる行を、列挙子に変えてみる。

public static class LinqExtensions
{
    public static IEnumerable<string> AsEnumerable(this TextReader tr)
    {
        try
        {
            while (true)
            {
                var line = tr.ReadLine();
                if (line == null)
                {
                    break;
                }
                yield return line;
            }
        }
        finally
        {
            tr.Dispose();
        }
    }
}

TextReaderは全て読み取った時点でDisposeを呼び出している。こうする事で、

foreach (var line in File.OpenText("VeryLongTextFile.txt").AsEnumerable())
{
    Console.WriteLine(line);
}

という使い方をしても、列挙が終わればリーダーがクローズされるようになる。
一旦列挙子になってしまえば、

// フォルダ内のすべてのテキストファイルの、先頭・終端の空白を削除し、
// 空行や#で始まる行を除外して、ソートして表示
foreach (var line in
    from path in
        Directory.GetFiles(".", "*.txt", SearchOption.AllDirectories).
        AsParallel()
    from line in
        File.OpenText(path).
        AsEnumerable()
    let trim = line.Trim()
    where (trim.Length >= 1) && (trim.StartsWith("#") == false)
    orderby trim
    select trim)
{
    Console.WriteLine(line);
}

こんなことも自在に行える。

Advent LINQ (1): SplitAsEnumerable

System.Stringクラスには、Splitというメソッドがある。引数で指定された文字で文字列を分割するメソッドなのだが、返却される結果は配列になっている。配列と言う事は、非常に多くの文字列が分割されると、それだけメモリを消費する事になる。
そんなわけで、このメソッドを逐次実行可能な列挙子を返すLINQメソッドとして定義してみる。

public static class LinqExtensions
{
    public static IEnumerable<string> SplitAsEnumerable(this string target, params char[] separators)
    {
        var startIndex = 0;
        while (true)
        {
            var index = target.IndexOfAny(separators, startIndex);
            if (index == -1)
            {
                yield return target.Substring(startIndex);
                break;
            }

            yield return target.Substring(startIndex, index - startIndex);
            startIndex = index + 1;
        }
    }
}

System.String.Splitはインスタンスメンバーなので、Splitというメソッド名にすると呼び出せなくなってしまう。仕方がないので、SplitAsEnumerableという名前で定義した。

var veryLongStringValue = "...";
foreach (var value in veryLongStringValue.SplitAsEnumerable(','))
{
    Console.WriteLine("Value={0}", value);
}

これで逐次分割できるようになった。ロジックを拡張して、ダブルクオートで囲まれた文字列を切り出す等の応用が出来ると思う。

Visual Studio Coverage file to Emma converter

CodePlex now!
And 1.0.1.0 released!!

Visual Studio Coverage file to Emma converter : CodePlex


Visual Studio Coverage file to Emma converter.
Simple solution, can apply only one tool to five Visual Studio versions.
Fast multicore processing.

Included:

  • Command line executable.
  • MSBuild custom task.

Thank you choosing this tool, probably use with jenkins.
(I’m not jenkins professional ops, may not operate this tool…)

Require:
.NET Framework 4.5.1 Runtime environment.
Visual Studio 2005, 2008, 2010, 2012 and/or 2013 versions (Require code coverage option)

Setup:
1. Copy VSCoverageToEmma.exe, VSCoverageToEmma.dll to your tool folder.
2. Copy VS
folders (ex:VS2013) to your tool folder.
3. Copy your Visual Studio’s “Microsoft.VisualStudio.Coverage..dll”
(In %VSROOTFOLDER%Common7IDEPrivateAssemblies) into VS
folders.

Tool folder example:

  Tool
    +--- VSCoverageToEmma.exe
    +--- VSCoverageToEmma.Interfaces.dll
    +--- VSCoverageToEmma.Core.dll
    +--- VSCoverageToEmma.VS2005Converter.dll
    +--- VSCoverageToEmma.VS2008Converter.dll
    +--- VSCoverageToEmma.VS2010Converter.dll
    +--- VSCoverageToEmma.VS2012Converter.dll
    +--- VSCoverageToEmma.VS2013Converter.dll
    +--- VS2005
    |       +--- Microsoft.VisualStudio.Coverage.Analysis.dll (From Visual Studio 2005, if use)
    +--- VS2008
    |       +--- Microsoft.VisualStudio.Coverage.Analysis.dll (From Visual Studio 2008, if use)
    +--- VS2010
    |       +--- Microsoft.VisualStudio.Coverage.Analysis.dll (From Visual Studio 2010, if use)
    |       +--- Microsoft.VisualStudio.Coverage.Interop.dll  (From Visual Studio 2010, if use)
    |       +--- Microsoft.VisualStudio.Coverage.Symbols.dll  (From Visual Studio 2010, if use)
    +--- VS2012
    |       +--- Microsoft.VisualStudio.Coverage.Analysis.dll (From Visual Studio 2012, if use)
    |       +--- Microsoft.VisualStudio.Coverage.Interop.dll  (From Visual Studio 2012, if use)
    |       +--- Microsoft.VisualStudio.Coverage.Symbols.dll  (From Visual Studio 2012, if use)
    +--- VS2013
            +--- Microsoft.VisualStudio.Coverage.Analysis.dll (From Visual Studio 2013, if use)
            +--- Microsoft.VisualStudio.Coverage.Interop.dll  (From Visual Studio 2013, if use)
            +--- Microsoft.VisualStudio.Coverage.Symbols.dll  (From Visual Studio 2013, if use)

Command line usage (VS2013):

  C:TEMPVSCoverageToEmmaDebug&gt;VSCoverageToEmma.exe VS2013 &quot;C:TEMPCoverageTargetTestResults&quot; &quot;C:TEMPCoverageTargetbinDebug&quot; &quot;C:TEMPCoverageTargetbinDebug&quot; &quot;C:TEMPCoverageTargetTestResults&quot;

If use VS2010/VS2012/VS2013 converter, automatically recursive search binary/symbol files in nested folders.

MSBuild usage:
Target assembly is “VSCoverageToEmma.Core.dll”, task name is “VSCoverageToEmma”.
ConverterName: required (ex: “VS2005”)
VSCoverageFolderPath: required (path)
BinariesFolderPath: optional (path)
SymbolsFolderPath: optional (path)
EmmaFolderPath: optional (path)
VSCoverageFiles: output (path list)
EmmaFiles: output (path list)
Methods: output (number)

MSBuild limitation: Tool execution failed in 64bit process. (VS Coverage library required 32bit mode)

Download from SkyDrive: VSCoverageToEmma-1.0.zip

Bar Windows 8.1 – BluetoothでGO!

Bar Windows 8 in 名古屋 with 8.1に登壇して、「BluetoothでGO!」というタイトルでセッションしてきました。

ご清聴ありがとうございました。プレゼンを置いておきます。
最後のデモで見せたコードはあまり整理されていません。反響があれば公開したいと思います。→ GitHubで公開しています。

BluetoothでGo!

次回も頑張ります (^^)

名古屋MS秋祭り – LINQソースでGO!

名古屋MS秋祭りにて登壇して、「LINQソースでGO!」というお題目でセッションをさせて頂きました。

詰め込み過ぎなのに時間が短すぎという結果で、大変分かりにくい解説になってしまったようで、またしても反省です m(_ _)m
参加者の皆様、ご静聴いただき、ありがとうございました。次回登壇の際には、これに懲りずに、宜しくお願いします。

ここにオリジナルプレゼンを置いておきます(アニメーションを使用しているので、オリジナルを見た方が良いです)。早すぎて理解不能だった場合の足しにしてください (^^;;

Windowsマーケットプレースで収益を上げる為に

Windows PhoneやXBOX アプリケーションを開発する際に、Microsoftのデベロッパーセンターに、デベロッパーアカウントを登録する必要があります。
(Windows 8 ストアアプリの場合は、ここです。この記事では、基本的にWindows Phoneの話を扱いますが、大枠では同じです)

デベロッパーアカウントの登録は、MSDNライセンス契約があれば、1年間は無料で登録可能です。それ以外は、年間登録料を支払う必要があります(その代わり、個々のアプリケーションの申請費用は不要です、多分何度でも)。

で、登録を行い、Windows Phoneの物理デバイスのアンロック(デベロッパーアカウントを使って、自由にアプリケーションのインストールとデバッグを可能にする)まで行えば、開発と公開の準備が整ったことになります(XBOXはやったことが無いので、詳しくは分かりません)。
実際にアプリケーションの申請を行うと、早く数時間?遅くて5日程度かかるようです。

ところで、ここまでの話は、無料のアプリケーションの公開と配布です。有料アプリケーション・アプリケーション内課金・広告を使用した収入を前提とするのであれば、Microsoftから収益を送金してもらう必要があります。ここでは、実際に手続きを行った際に気が付いた事を(雑多ですが)メモっておきます。

但し、Microsoftを通じて課金しない場合(サービスを提供し、そのサービス対価を、例えばPayPalで独自に課金するなど)は、以下の内容に当てはまりません。この方法は、ひょっとするとグレーゾーンかもしれないので、あらかじめ良く調べてください(私にはわかりません)。


注意:私は税理士ではないので、以下の理解は間違っている可能性があります。慎重に事を進めたいのであれば、必ず専門の税理士にご相談下さい。内容について、一切保証出来ません。

収益を送金する場合、Microsoftに対して、「W-8BEN Form」という申請書を提出する必要があります。米国では、例えばユーザーがアプリケーションを購入した場合、その代金を徴収した時点で、Microsoftが源泉所得税徴収義務者となるようです。そのため、そこで源泉所得税を差し引いてから、送金が行われます。

w-8ben

日本で主たる業務を行う法人事業者がアプリケーションを販売する場合、国内であれば売上と利益を期末に決算処理によって確定し、法人税確定申告を行います。その際に、日本の国内法に基づいて算出した利益(所得、でしたね。税会計は難しい)から税額が確定し、納税を行います。

Microsoft経由でアプリケーションを販売した場合、前述のように、米国内にて米国向けの源泉所得税が(自動的に)徴収されることになります。現行の米国法では、これは売上の30%とのことです(非常に大きい!!)。そして、差し引かれた売上が送金されてきます。

しかし、これは期末の決算処理で損金算入出来ません(出来るのかもしれませんが、ちょっと分からない)。ということは、米国と日本で二重に課税されてしまうのです。
(この部分は、法人ではなく個人でアプリケーションを販売する場合も同様です。そして、更にMicrosoftの取り分がある事をお忘れなく)

幸い、米国と日本は「通常の国交」があり、租税条約が結ばれているため、米国での源泉所得税徴収を免除してもらう事が出来ます。その為には、米国での納税者番号(EIN)が必要です(実際には納税しませんが、納税者番号が必要)。
この番号を申請書類「W-8BEN Form」に記載する事で、米国での源泉所得税が徴収されなくなります。

EINの取得は、IRS(アメリカ合衆国内国歳入庁)から行いますが、当然の事ながら、電話とFAXによる申請を根気よく実行する必要があります。私には不可能に思えたww ので、これを代行してくれる税理士に頼みました。親切に対応して頂き助かりましたが、EINの取得までにはそれなりの時間がかかります。急ぐ場合はあらかじめ相談しましょう。

EIN取得後、デベロッパーセンターの「税務情報」から、W-8BENの申請を行います。この申請はすべてオンラインで行う事が出来ます。Microsoftの米国法人に直接連絡したりする必要はありません。オンラインのフォームを入力すればOKです。

w-8ben2

なお、今のところ、EINの維持には、これ以上の負担はありません。今のところ、というのは、米国の法律が改正されて、例えば毎年更新が必要になったりする可能性が0ではない、と言う事です。まぁ、それは考えても始まらない事でしょう。そして、一度EINを取得すれば、Microsoftだけではなく、Appleや他のApp開発でも勿論使用出来ます。マルチプラットフォーム戦略があるのなら、必ず取得しておきたいところです。

さて、W-8BENをクリアした後は、利益を送金する先の「着金銀行」を入力する必要があります(Windows 8ストアアプリでは順序が逆)が、そこにも問題があります。米国から利益を送金する場合、送金にかかる手数料が馬鹿にならないと言う事です。
送金元銀行から着金先銀行(つまり、自分の銀行)に送金する場合、P2Pの如く直接送金されない可能性が高いのです。その場合は、バケツリレーのように中間経由される銀行が存在し、その度に手数料が徴収されます。

2ホップの例:

  • 送金元→送金元銀行(振込手数料)
  • 送金元銀行→中間転送銀行1(転送手数料)
  • 中間転送銀行1→中間転送銀行2(転送手数料)
  • 中間転送銀行2→着金銀行(着金手数料)
  • 着金銀行→自分の口座(振込手数料・口座維持手数料etc)

(手数料については書きませんが、国内の振込手数料をイメージしていると愕然とします。アプリ何十本分の利益が吹き飛びます)

しかも、どのように転送されるのか(あるいはされないのか)は、あらかじめ分からない可能性があるとの事です(シティバンクにて相談)。そのため、一度にまとまった額で送金する事はもちろん、如何に中間転送を省けるか、着金手数料を省けるかが鍵となります。

実は、着金銀行として選択できる銀行は、国内では事実上二択しかありません。シティバンクか、新生銀行です。しかも、2012年12月までであれば、シティバンク一択だったのです。シティバンクには「eセービング口座」という、とんでもなくおいしい商品がありました。口座維持手数料無料、着金手数料無料なのです。しかも、シティバンクは全世界に沢山の支店を構えています。そのため、中間転送の可能性が大幅に減るのです(支店に転送されれば、日本国内の口座への転送は無料)。

シティバンクは「eセービング口座」の新規受け付けを止めてしまいました。今から口座を開設する場合、口座維持手数料が「月額2,100円」かかります。あり得ないほどお得だったと言う事が分かると思います。

次点の新生銀行も、今のところ口座維持手数料は無料です。但し、今後課金を行う可能性がある事をアナウンスしています。また、着金手数料も無料ですが、シティバンクのように、全世界に支店を持っていないため、中間転送が発生する可能性はあります。

このような銀行間送金を行う場合、突っ込んでやるのであれば、送金の際に中間転送経路を指定する事も出来るようです。この辺りは、株や為替取引をやる人には当たり前かもしれないので、近くに知り合いが居るのであれば聞いてみると良いでしょう。(但し、Microsoftからの送金に、中間転送経路を指定出来るかどうかは分かりません)

そして、この二行以外の銀行が選択としてあり得ないのは、一つは着金手数料がバカ高いこと、もう一つは国内での中間転送がほぼ必ず発生し、その手数料は振込手数料の比ではない事、なのです。そんな事をするぐらいなら、上記二行に着金させた後、手動で振り込んだ方がマシです。

しかし、別の方法もあります。もし、PayPal口座を持つことが可能なら、PayPalも送金先として選択可能になったと言う事です(以前は選択できなかったらしい)。
PayPal強し! 上に挙げた数々の問題は、PayPalでは一切発生しません。PayPalでかかる手数料はシンプルで安く、しかもPayPal口座から国内の銀行への送金は、50,000円以上であれば手数料無料です(記述ミスではありませんよ、「以上」です)。

そのため、個人で利益を受け取る場合や、法人でもPayPal口座を持つことが出来るのであれば(会社のポリシーの話であって、法人口座に制限があるわけではない)、PayPalはお勧めの送金手段です。

PayPalは預金保護の対象となるのかどうかが不透明です。一応、その事を理解しておく必要があります。

もっとも、PayPalがマズい事になったら、世界的にもマズい事になっている気がしますがw

また、現在のところ、Windows 8ストアアプリでは、PayPal口座を送金先にする事は出来ないようです。

デベロッパーセンターも別々の扱いになっており、やる事は殆ど同じであるにも関わらず、面倒な事になっています。

そのため、将来的には統合されるのではないかと思います。

以上の事を調べたことで、得た感想:

  • 「国交」って大切なんだ
  • シティバンク強し!!金融取引も鎖国的な日本
  • シンガポール法人最強伝説(PayPalの事。TaxHeavenとまでは言わないが)

第六回まどべんよっかいち勉強会 LTスライド

第六回まどべんよっかいち勉強会お疲れ様でした。
「DotNetOpenAuthをうまいこと使う」というタイトルで、LTさせて頂きました。スライド置いておきます。

ASP.NET MVC4の新規プロジェクトで使用される「DotNetOpenAuth」ライブラリと、「Facebook C# SDK」を連携させるネタです。オリジナルはUsing OAuth Providers with MVC 4 By Tom FitzMackenですが、ポイントはほぼ一か所なので、LTネタとしては良かったと思います。

良くないのは、LTとして長すぎだったと言う事か orz すいません、時間が押していたのに。精進します。

オリジナルスライドはこちら(アニメーションを多用しているので、オリジナルを見た方が良いです)

なお、時間が無かったので補足しませんでしたが、通常のウェブサイト向け(ASP.NETウェブサイト)のOAuth運用では、アクセストークンを直接取得するのではなく、代わりに「コード」と呼ばれる、ログイン毎に一意の暗号コードを受け取り、暗号コードからアクセストークンを取得します。

The Login Flow for Web (without JavaScript SDK)

そのため、LTで紹介した方法(直接アクセストークンを取得する)は、最後にWindows Phone向けの事を絡めましたが、元々Windows Phoneのようなクライアントアプリケーション向けの処理方法です。

… と言う事を喋る余裕もありませんでしたw