‘プログラミング’のエントリ

既に各所で告知されている通り、12/1の「REALFORCE TYPING CHAMPIONSHIP 2019」のオフライントーナメントでWeather Typingが使われる。で、今日告知があったが、11/24に行われる「N高等学校 第2回 ネット運動会~esports Festival~」の競技の一つにWeather Typingが入った。RTC2019は現地参加予定、ネット運動会の方もネット配信あるので楽しみ。

両方とも事前に話を聞いていたが、日程かぶってなくてよかった。ていうか、日程かぶりを心配するほどWeather Typingが使われることにビックリだ。ゲームに詳しい人に聞く感じ、RTC2019会場の大型ビジョン(タイトーステーションのところ)はゲーマー界隈では知られているらしく、そこに映るのは結構スゴイらしいし、ネット運動会もFortniteと並んでいるのはスゴイことらしい。まあ、タイピングでe-sportsというのが(TODを除いて)商業ソフトにないだけではあるけど。

ちなみにRTC2019の方はOEM的に配信特化した版を提供している。運営の方にはWeather Typing本体にも配信用のデザインを反映させて欲しいとは伝えている。「Warriors of Typing」も続けて頂けているし、配信用画面とか観戦機能を付けて4.0にできるといいなあ。

Weather Typing 3.7を公開。

Windowsデスクトップ版は、いつかのWindows 10のアップデートでUIがおかしくなった問題の修正。これだけでバージョン番号をあげるとWT4.0に近づいてしまうのでなんとなく保留していたのだが、いろいろ大会に使われてきてもいるので、そろそろ公開しないと。

MacOS版は、本当は対戦サーバに接続する機能だけ追加しようとしていたのだが、結局ほぼWT3.6までの機能は入れた上で公開した。当時のソースコードを再度ビルドすると、新しいMacOSライブラリでは全然ちゃんと動かなくて、Xamarin Formsを4にしたり、いろんなバグを回避をしたり大変。結局最新ソースを使うしかなかった。

  • 今まで問題なかったところで「UIスレッドで呼べ」エラーで落ちるようになった
  • スクロールビューなどの中にエディットボックスを入れて、エディットボックスに一度でもフォーカスしてから画面遷移するとフリーズする

UIスレッドの問題は面倒だけど回避は簡単。いろんなところにUIスレッドコールを追加して解決。エディットボックスの問題は、その時点でもうMacOS版を捨てようとしたくらい致命的。バグは増えても減ることはないので今後も修正されることはないし。でもあがいた結果、画面遷移の直前にエディットボックスを含むちょうどいい領域を非表示にすることでたまたまうまく動いたので、それで回避することにした。

そしてリリース版を作ろうとしたらVisual Studioの署名オプションがDisableになっていて付けられない。MacOS Developerのサイトから証明書をダウンロードしたりいろいろしたけど、結局サイトからダウンロードする必要はなくて、XCodeのオーガナイザで追加することでVisual Studioの署名オプションが有効になった。

で、WT3.6で入れた背景画像選択機能がサンドボックス化で動かなくてトークン化したり、初回起動時に権限を聞かれるようになったりしつつようやくpkg化完了。したんだけど、pkgをインストールしたらもう二度とpkgからもMacOS Appストアからウェザタイをインストールできなくなった。トラップ。3.7をリリースしたらストアから入れられるようになったけど、これだとバージョンアップのテストが不可能。やっぱりMacOSは一般の開発者に厳しい。

最低限月1回の投稿を目指しているので、そろそろ何か書いておこう。日記じゃなくて月記になってるけど。


ウェザタイの開発はiOS/Mac版のAppiumによるテストをやろうとしてるけど、iOSはそれだけで何ヶ月もかかりそうだし、MacはAppiumの機能が少なすぎておそらく無理。いいかげんプラットフォーム対応は終わらせて新しいことをやりたい。


上にも関連して、最近は開発に時間がかかりすぎる気がしていて、もう少しなんとかならないかな。てことで関数型言語の勉強を進めている。ただ、関数型言語は数学の素養がないとちゃんと理解できないので数学を勉強中。

もともと、物理シミュレータとか暗号論の勉強でちょっとずつ数学を勉強していたが、4年くらい前に「数学ガール」を読んで面白くなった。大学の頃は、数学の本を読んでも定義と定理と証明ばっかりで誰が理解できるのか不思議だったけど、「数学ガール」でだいぶ教科書の読み方が分かってきた。Haskelは圏論をベースにしていて、さらに圏論を真面目にやるには、群論などをちゃんと理解しないと言ってることが分からない。てことで数学のいろいろな分野に手を出しているところ。


さらに平行して人工知能も勉強中。こっちは具体的にウェザタイに活かしたいものがあって、ワードの自動生成とか、人間みたいなCPUの作成とかができると面白いかな。で、「ゼロから作るDeep Learning」を見つつ、ウェザタイに使うためPythonで書かれたものをC#で実装している。1巻は既に実装が終わって、今2巻のRNNあたりを実装しているところ。ウェザタイに使うには時系列が必要なので。

人工知能の本を読んでいると脳の仕組みとはかけ離れた方向に向かっているので、今まであまり勉強したくなかったのだが、部分的には人間の脳と同じようなことが再現できているようなので、とりあえず追いつくために勉強している感じ。うまく動かすために、脳を研究するのではなくて、数学的な仕組みやパラメータで解決するので、これを進めても脳の実現は無理そうな気がするけど、まあ特定の問題を解くのには便利そうなのでこれはこれで使っていこう。


あれ、電子工作やってない。。。

ちょっと長めの夏休みってことで関東に行っていて帰ってきた。もう関西に「帰ってきた」という表現になるくらいだ。

開発環境もあんまりないのでひたすら人工知能の勉強。といっても普通のディープラーニングとかではなく脳科学からのアプローチだけど。

普通のディープラーニングもそろそろ実装できてきたのでウェザタイへの応用を考えよう。

神奈川の家にしばらくいたので、Amazon Prime Videoでシリコンバレー第5期を一気に見た。関西の家だと通信に制限があるのでちょっと見づらい。

第4期はリチャードが闇落ちして犯罪を犯したけど、運良く捕まらずにラッキー、で終わった。そのストーリーはどうなのか、第5期はもっと酷いのか、と思っていたけど、第3期以前のノリに戻った感じ。ピンチに陥って誤った道を進みそうになるけど、ギリギリ正しい道を選んで、運良く助かる、っていうのの繰り返し。マンネリ気味ではあるけどやっぱり面白い。

でようやく「新しいインターネット」に動きが。ラスに説明したとおり、P2Pを基本に、世界中にある端末のストレージを共有するインターネットって感じかな。ギャビンベルソンの懸念するデータゲドン(くだらないデータが増えすぎてデータ量が爆発する)を解決することはできるかもしれないけど、理念であるGoogleとかMicrosoftに支配されない世界とはあんまり関係ない気もする。個人的には、今のインターネットは極度に商用に偏ってもはや無価値になってきているので、昔の集合知みたいなインターネットに戻るといいんだけど。てな感じでシリコンバレー、今後どうなっていくのか。ていうか続くのか?

Android版Weather Typing。Android版というか全プラットフォームでネイティブライブラリを使っているのだが、Visual Studio Xamarinを使ってアーカイブを作るとx86/x64のどちらかにしかネイティブライブラリが入らない。仕方ないので今までは64bit版だけを入れていたのだが、おそらくx86のAndroidでは起動エラーになっていたはず。なので今回はもう64bit専用にして32bitはインストール不可にしたのだが、掲示板で32bit版のOSに関する報告があった。

いくつか調べてみたが、Xamarinの公式でも困っている人がいて、Xamarinとしての解決策はなさそう。Androidとしての解決策として、32bit用と64bit用のapkを両方登録することができるらしい。なので今回、32bit用のネイティブライブラリを入れたapkを登録した。ただ、Xamarinの制約?バグ?として32bit版専用のapkを作っても64bit用のmonoライブラリも入ってしまう。なので、GooglePlayに、1つVersion Codeを下げた32bit版を登録してみた。これでどうなるか。

Weather Typing 3.6 Android版を更新。ロビー参加とネット対戦に正式対応。今までホストを作るのが困難だったので隠し機能扱いにしていたのだが、サーバクライアント式にしたことでようやく正式対応と言えるようになった。

今回、Android 64bit版のみ対応にしてみたけど大丈夫なのかな。前のバージョンでも32bit版ネイティブDLLを入れていなかったのでエラーになっていたはずで、64bitのみにした方がややこしくないかなってことで。

Xamarin+Appiumによる自動テストは、入力関係はうまくいかなかったりしたが、70%くらいは自動化できた。あとはMacOSとiOSの自動テストができるとテスト効率が上がる。

ちょっと更新が遅れたけど、高知県のPCショップエレパさんの2019エレパ夏祭り内でタイピング大会が開かれ、Weather Typingを使って頂いた。

メールで連絡を頂いたものの高知県ということでどうかな、と思いつつツイートしてみたところ、タイピングAGOGOおはようさんが高知県在住ということで参加された模様。しかも優勝してるし。Twitterすごい。

大会の詳細もブログにまとめられていて参考になる。RTCはかなりガチな競技会になっているが、こういう場の場合、対戦だと時間拘束もされるし、単純にスコアを競う感じの方がよいってことかな。もっと派手な見た目のソフトの方が一般受けはしそうだけど、その中でウェザタイを使ってもらってありがたい。

Windows 10のMay 2019 Updateを入れたら、ウェザタイのタイトルや結果画面のListViewが崩れるようになった。

調べてみたところ、ListViewの表示がちょっと遅れて、最初の行を追加するときはListViewの幅が分からず最小の幅になって、その後の行はListViewの幅が確定してちゃんと表示される、っぽい。なので、最初の表示だけListView.SizeChangedが来たときにListViewItemを追加するようにした。もうWPFは廃れていくだろうし、適当でいいや。

ウェザタイのiOS/MacOS版のアップデートをするにあたって、今まで使っていた2012年のMac Book ProではmacOS Mojaveを入れられないという問題が。さすがに7年前に買ったやつだしなあ、ということで買い換え。

開発に使うので最近発売されたMac Book Proというのは決めてヨドバシカメラへ。7年前は13インチにしたんだけど、店頭で触ってみた感じだと15インチでも2012年の13インチと同じくらいのサイズ、重さに至っては15インチの方が軽い。なので15インチにしてみた。約30万円。去年買ったSurface Book 2とほぼ同等のスペックだけどSSDが256GBな分(?)多少安い。

とりあえず開発環境を整えて、iOSとMacOS用XamarinアプリをビルドしてAppium経由で起動できるようにした。

Surface Book 2+Mac Book Pro 2019の絵。


これで、神奈川の家用にDELL機+2012年Mac Book Pro、関西の拠点用にSurface Book 2と2019年Mac Book Pro、出張用にSurface 3で、全部で5台になった。多い。

Weather Typing 3.6を公開するにあたって、UIテストの自動化を研究していた。今、ウェザタイのリグレッションテストの項目が約2500件、WPFだけで500件くらいある。これだけあるとテストだけで数週間かかってしまい、何か修正してもテストがめんどうで公開をあとまわしにしてしまう。人を増やさずになんとかならないか考え続けた結果、UIテストがそろそろ実用的になっていそうなので、やってみた。

Webの世界ではSeleniumがよく使われているが、それをデスクトップアプリやモバイルアプリに使えるようにしたAppiumというフレームワークがある。バイナリだけでテストができるので、C#+Xamarin.Formsで作ったアプリでも、C#でテストコードを書いて、マルチプラットフォームでテストできる。

で、まあいろいろ苦労はしたが、最終的にWPFのテストは77%の自動化ができた。しかも面倒なテストはほとんど自動化できたので、手動のテストを含めても、早ければ1日でテストが終わる感触。

なお、今回はWPFなので、WindowsAppDriverを使用。Windowsストアアプリも同じものが使えるはずで、Android他はまた違うAppiumのドライバを使うが、テストコードは基本的に共有ができるはず。

Palm OSのアプリを作ってた時代は、グレムリンテスト(モンキーテストの自動化)くらいしかなくて、とてもちゃんとUIのテストはできなかった記憶があるけど、RPAも実用的になっている今の時代、以下のような項目くらいは自動化できるようになっていた。

  • ボタンなどをクリックして画面遷移した先のラベルなどが表示されていることを確認する
  • 入力ボックスの文字数制限やエラー表示が正しいことを確認する
  • 複数のインスタンスを起動して、互いに協調動作(具体的にはネット対戦)することを確認する

具体的には、プログラム上でUI部品にIDを与えておくと、実行時にそのIDからテキストを取得したり、クリックしたりできる。さらにテスト自体はプログラミング言語を使って書くので、ロジックは入れ放題。プラットフォーム依存になるけどファイル操作なんかも普通にできるので、かなり自由度が高い。

逆に、どうしても自動化できなかったのは例えば以下の項目。そりゃそうだろうね、っていう感じ。頑張ればできるかも知れないけど手動でやってもたいしたことはない。

  • 文字の色や背景画像を確認する
  • 音がなる、ならないことを確認する
  • 拡大縮小やスプリッターの位置を確認する
  • マウスカーソルの表示・非表示を確認する

UIテストをやる前は、結局目で見ないとおかしいことに気付かないから意味がないかな、と思ってたけど、Appiumの場合、実際にマウスでクリックしたりキーボードを入力したりするので、手動でテストするのとそんなに変わらない。テストスピードがあまり早くないのもあって、テストの様子を見ていればレイアウトが変になっていたりしても割と気付く。

手動ではどうしても確認にミスが出るので、むしろ自動の方が正確だし、手動の時は全組合せのテストは不可能である程度抜粋にせざるをえなかったが、自動なら何も考えずに全組合せテストしてもたいしたことはないので網羅的になる。

メモ。今回のUIテストでは以下のことを気を付けて作ってみた。

  • 汎用的になるようにする。エラーメッセージの確認なんかは、メッセージそのものを確認するとエラーメッセージの変更に堪えられないので、キーワードを含むかどうかだけ確認するようにしてみた。
  • いつでもテストを実行できるようにする。前提条件がないように、テスト項目開始時に設定ファイルやリプレイファイルなんかを全て削除して、必ず同じ条件で実行できるようにしてみた。

ついでに、WindowsAppDriverでハマったこと。

  • Xamarinからだと直接Accessibility IDを設定できない。Xamlから、Effectを使ってIDを設定し、各プラットフォーム固有コードでIDを設定するようにした。
  • 画面に表示されていない項目をクリックしたりはできないので、スクロールがめんどう。結果的にWindows用に最適化されている状態なので、Androidとかでどうしよう。
  • キーボードが101キーボードになっていて、打てない記号がある。特にバックスラッシュを打つ方法が見つからなかった。
  • Windows用のAppium用クラスとAndroid用のAppium用クラスが別物なので、統一的に扱えない。なので、一個ラップしたクラスを作って同じように使えるようにした。
  • Async/Awaitするとテストが終わってしまう。WaiterのUntilをうまく使って回避するくらいしかない。

しばらくWeather Typing 3.5を開発版としていたが、開発版のままにしておくデメリットが大きいので、正式版として公開した。Xamarin Formsがバージョン同じままバイナリが変わる問題もあって、リビジョンアップができないのでマイナーバージョンアップにしている。

本当はストア版やMac/モバイル版をアップデートしてから正式版にしたかったのだが、もうこっちは少し時間がかかりそう。

あんまり下手なことはかけないのでTwitterかブログか迷ったけど、折角なのでこっちに。TwitterでGANGASさんの、タイプウェルランキングが6/1で更新終了という話が。TODとタイプウェルがなければウェザタイはここまでになってないので、感謝。思わずタイピング本のインタビューを読み返したりした。ウェザタイの適当なランキングと比べて、あの厳格なランキングを20年くらいメンテし続けているのはすごい。

ウェザタイはどうなるかな。メンテだけなら負担はほとんどないので、ランキングやロビーは続けようと思えばいつまでも続けられる。ただ、プラットフォームについていくには、定期的に作り直しが必要になるので、WT2のときみたく他のソフトウェアを作り始めてしばらく放置はありうる。あとは、何かあったとき用に、ボタン一つでソースコードを公開する仕組みか、ランキングと対戦で不正ができないようにした上でオープンソース化できる仕組みを編み出さないと。

Visual Studio 2019に入れ替え。とりあえずウェザタイプロジェクトを開いてみたが、プロジェクト設定を最新のプラットフォームにしたり何度かリビルドして、とりあえずビルドはできた。

Channel 9の動画で見たが、Xamarin.FormsのXAMLがデザイナーで表示できるようになった。デザイン時だけのリストを入れたり、かなり改善されている。

で、XAMLデザイナーを使うためにはXamarin Forms 3.6にアップグレードする必要があるようなので、嫌々アップデート。ただ、今回増えたバグは、Xamarin Forms WPFのリストボックスのスクロールバーが、常に表示されるようになったことくらい。思ったよりバグは増えなかった。

で、スクロールバーの件はListView hide scroll view scroll barsで作り込まれている。スクロールバーのhidden/visibleが指定できるようになったみたいだけど、何故かWPFでは今まで使えていたAutoが使えなくなっている。なので、例のごとくListViewのRendererで以下を指定して回避。

System.Windows.Controls.ScrollViewer.SetVerticalScrollBarVisibility(Control, System.Windows.Controls.ScrollBarVisibility.Auto);

Twitterで東京理科大の近代科学資料館がリニューアルで一時休館という話が流れてきた。 近代科学資料館自体知らなかったけど、調べてみると古い計算機を置いているらしい。これは見ておかないと。ってことで行ってみた。

以前アメリカのComputer History Museumへ行ったときはものすごい量の計算機があって一日いたのだが、そこまではないよね、って思っていたけど、思ったより充実していた。また、Computer History Museumに行った後、コンピュータの歴史の本も何冊か読んだので、これがあれか、ってなって面白かった。

見所としてはUNIVAC(世界初の商用コンピュータ)とか、IBM 5110(あのIBN 5100の元ネタの後継機)とか。UNIVACはComputer History Museumではガラスの向こう側であまり見えなかったけど、ここではそのまま置いてあってだいぶ詳しく観ることができた。あとは、Altair 8800(世界初のパーソナル・コンピュータ)は初めて見たけど、思っていたより大きい。パラメトロン(真空管からの移行期に、トランジスタかパラメトロンか、みたいな話だったかな)もどんなものかな、と思っていたけど、外見からはあまり分からず。去年企画があったらしいので観たかったかも。

あとは、計算尺は自宅にあるけど使ったことないなあ、とか、タイガー計算機(ハンドルを回して計算する機械)とか、これも実家にあったような気がするTK-80とか。 Bush式アナログ微分解析機 。アメリカでバベッジの解析機関のデモをやっていて、それは1部屋使った超巨大なものだったが、それとは別の話なのかな。この辺りは後で調べてみよう。

ずっと前から気になっていたSonyのデジタルペーパーKindleを買ったときにあまりに紙に近くて感動したので、もっと大きいのがあればいいのに、と思っていた。で、デジタルペーパーはまさにそういうデバイス。でも8万円って高いよね、と思っていたらいつの間にか手元にあった。

PDFしか見られないのでだいぶ用途が狭いのだが、読みたいPDFがあるならかなりよい。まずでかくて薄くて軽い。雑誌でも拡大しないで普通に読めるし、本より軽い。表示切り替えはまだ遅いけど、Kindleと変わらないというかKindleよりは早い気もする。

あとどのくらい待てば電子ペーパーでAnalog Book Readerを動かせるようになるかな。液晶に近いくらい反応速度が上がって、電子書籍のストアとデバイスの組合せが自由になって、Analog Book Readerくらいの使い勝手が実現できれば、紙の本はいらなくなるのに。

とりあえず、これでたまっているSoftware Designを読めるかな。液晶だと目が疲れるからなかなか進まなかった。

あとは、電子メモ的な使い方もできるので、Boogie Boardの代わりに使えるかな。Boogie Boardの手軽さには勝てないと思うけど、白地に黒なのと書いたメモを保存できるのは魅力的。

3/2のWarriors of Typing #0を観戦。たのんさん企画のタイピングオンライン対戦で、ウェザタイを使ってもらっている。定期的にやっていきたいとのことなので、今後にも期待というかウェザタイも頑張らないと。配信はTwitchで観られるので是非。

最初の話では、WT3.5でポート開放が不要になったのもきっかけということだったが、確かにこういう形だと、ポート開放があると難しい。いくつかの試合が同時進行なのでホストを一人でやることはできないし、接続が安定しないと大会がその都度中断されてしまう。

たのんさんも今回は#0でお試しと言っていたが、ウェザタイ的にもWT3.5が本格的に使われるのは初めてなので、サーバ負荷等、貴重なデータを取ることができた。大会中のサーバ負荷についてはCPU/Disk/Traffic特に問題なし。不安だった同時対戦についても、2人対戦を4試合同時くらいでは問題なし。むしろ、既に安定していると思っていたロビーサーバの方で対戦接続時にエラーが発生する現象があり、開始時間が遅れた。てことで今日、昔作ったロビー負荷テストクライアントをC#に移植してテストして、かなり負荷をかけてみると同じ現象が発生した。対戦開始時、対戦相手を検索するときにプレイヤー情報が入っていないときがあってエラーが出る。ただ、大会ではこんな負荷はかかってなかったしなあ、と思ってその視点でログを解析した結果、ようやく原因が判明。ロビーに入るときにパスワードが間違っているとクライアント側でエラーメッセージが出るのだが、これにOKを押さないと、ロビーサーバ上、プレイヤー情報がないメンバーが入ってきてエラーになってしまう。その人がOKを押せば直るのだが、その状態で放置するとその間は誰も対戦ができなくなっていた。たぶん初期からの問題。

あとはRTC2018でも起きていた、対戦が終了すると対戦相手がいなくなってしまう現象がまだ起きている。一応WT3.5で怪しそうな所は直したのだが、まだダメみたい。現象が発生したときの全員分のリプレイでもないと直せそうにない。

で、VTuber配信やオフライン大会など、新しい使い方が出る度にいろいろ改善したいことが出てくるが、今回もいくつかある。開発が間に合ってないけど。

  • ロビーのチャットのフォントサイズを変更できるようにする
  • 運営機能。ワードなどの設定を中央から強制したり、対戦結果を収集するなど
  • ゲスト側のルール画面に、ホスト側のワード数を反映させる
  • 観戦用のラグなしモード。リアルタイムから少しだけ遅れるが、対戦相手の打つ様子がスムーズに表示される機能
  • 上記を応用して、1フレーム内の打鍵を個別に扱うことで、ラグが大きいときに同着になる問題が改善できる。

ちょっと前からWeather TypingのWindowsデスクトップ版以外の更新をやっているのだが、テストが2300件くらいあって、さすがにテストが大変。てことでUIテストの自動化を本格的に調査。1週間くらいかかってようやく見えてきたのでメモ。ちなみにAndroid/UWP/WPFは実験成功して、Mac/iOSはまだ試せていない。

UIテストはいろいろな方法があると思うけど、マルチプラットフォーム対応だとAppiumがよさそう。Appiumは、WebのUIテスト自動化Seleniumと同様の方法でモバイルアプリのテストをするフレームワーク。サーバクライアントになっていて、クライアントでテストコードを書くと、サーバにJSON形式のコマンドを投げて、サーバからアプリのUIに向かってキーボードやマウスのイベントを投げてくれる。AppiumのサーバだとAndroidとiOSがテストできるが、Windows Application Driverを使えばWindowsのWPFやUWPもテストができる。クライアントについては、Pythonなどでやるのが普通かもしれないけど、Appium.WebDriverを使えばでC#で開発が可能。

まとめると、C#でUIをテストするコードを書いて、Appiumのサーバを起動すればAndroid/iOSのUIテスト、Windows Application Driverを起動すればWPF/UWPのテストが可能ということ。さらに一工夫いるが、Xamarin.Formsのアプリもテスト可能である。

Appiumのインストール
ここは普通にAppiumとAppium-doctorをインストール。Pythonとかnodeとかそのあたり。Appium-doctorを通すためにいろいろインストールする必要がある。だいたいはなんとかなるはずだが、Windowsで「bundletool.jar cannot be found」になるので環境変数「PATHEXT」に「.JAR」を追加する。これ1日はまったけどappium-doctorのソースまで見てようやく分かった。
Windows Application Driverのインストール
普通にインストール。特に困ることはない
Appium.WebDriverのインストール
とりあえずVisual StudioでUnitTestプロジェクトを作り、NuGetからインストールした。UnitTestなの? って思うけど・・・別にコンソールアプリでもいいのだが、テストケースの管理とかでUnitTestがいいかな、ってくらい
UI部品にIDを振る
テストの時にUI部品を特定するため、それぞれIDを振る。Appiumではいくつか特定の仕方があるが、これ実質Accessibility IDしか使えないよね。てことでXamarinのXAMLで、ButtonとかにAutomationId=”hoge”を入れる。だけでよければ話は簡単なんだけど、Android、UWPはうまくいったがWPFはダメだった。Xamarinのソースを見る限りWPFではViewRendererでSetAutomationIdをやっていないみたい。なので、Effectを使って特定の属性を設定すると、各プラットフォーム向けにAccessibility IDに対応する属性を設定するようにしてみた。これもEffectなの? って感じだけど、これ以外にうまい方法は思い浮かばない。

まずはEffectの属性。プラットフォーム共通。

    public static class TestEffect
    {
        public static readonly BindableProperty NameProperty =
          BindableProperty.CreateAttached("Name", typeof(string), typeof(TestEffect), "", propertyChanged: OnNameChanged);

        public static string GetName(BindableObject view)
        {
            return (string)view.GetValue(NameProperty);
        }

        public static void SetName(BindableObject view, string value)
        {
            view.SetValue(NameProperty, value);
        }

        private static void OnNameChanged(BindableObject bindable, object oldValue, object newValue)
        {
            var view = bindable as View;
            if (view == null)
            {
                return;
            }

            var name = (string)newValue;
            view.Effects.Add(new UITestEffect());
        }
    }

    class UITestEffect : RoutingEffect
    {
        public UITestEffect() : base("com.denasu.UITestEffect")
        {
        }
    }

次に各プラットフォーム用のEffect。

[assembly: ResolutionGroupName("company name")]
[assembly: ExportEffect(typeof(App1.WPF.UITestEffect), "UITestEffect")]

namespace App1.WPF
{
    public class UITestEffect : PlatformEffect
    {
        protected override void OnAttached()
        {
            var name = TestEffect.GetName(Element);
            Control.SetValue(System.Windows.FrameworkElement.NameProperty, name);
        }

        protected override void OnDetached()
        {
            Control.SetValue(System.Windows.FrameworkElement.NameProperty, "");
        }
    }
}
[assembly: ResolutionGroupName("company name")]
[assembly: ExportEffect(typeof(App1.UWP.UITestEffect), "UITestEffect")]

namespace App1.UWP
{
    public class UITestEffect : PlatformEffect
    {
        protected override void OnAttached()
        {
            var name = TestEffect.GetName(Element);
            Control.SetValue(Windows.UI.Xaml.Automation.AutomationProperties.AutomationIdProperty, name);
        }

        protected override void OnDetached()
        {
            Control.SetValue(Windows.UI.Xaml.Automation.AutomationProperties.AutomationIdProperty, "");
        }
    }
}
[assembly: ResolutionGroupName("company name")]
[assembly: ExportEffect(typeof(App1.Droid.UITestEffect), "UITestEffect")]

namespace App1.Droid
{
    public class UITestEffect : PlatformEffect
    {
        protected override void OnAttached()
        {
            var name = TestEffect.GetName(Element);
            Control.ContentDescription = name;
        }

        protected override void OnDetached()
        {
            Control.ContentDescription = "";
        }
    }
}

XAMLではEffectを付ける。

        <Entry local:TestEffect.Name="Text1" Text="{Binding TextA}" WidthRequest="100" />
        <Entry local:TestEffect.Name="Text2" Text="{Binding TextB}" WidthRequest="100"/>
        <Label local:TestEffect.Name="Result" Text="{Binding TextC}" WidthRequest="100"/>
        <Button local:TestEffect.Name="Execute" Text="Button" Clicked="Button_Click" WidthRequest="100"/>
テストケースの作成

C#ではこんな感じ。各プラットフォームのセッションを作って、共通のテストを実行するようにしてみた。

[TestClass]
public class UnitTest
{
    [TestMethod]
    public void TestMethod1()
    {
        var session = CreateSessionUWP();

        session.FindElementByAccessibilityId("Text1").Click();
        session.Keyboard.PressKey("111");
        session.FindElementByAccessibilityId("Text2").Click();
        session.Keyboard.PressKey("222");
        session.FindElementByAccessibilityId("Execute").Click();
        Assert.AreEqual(session.FindElementByAccessibilityId("Result").Text , "111222");
    }

    private WindowsDriver<WindowsElement> CreateSessionUWP()
    {
        DesiredCapabilities appCapabilities = new DesiredCapabilities();
        appCapabilities.SetCapability("app", "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXXXXXXXXXXXXXXXX!App");
        return new WindowsDriver<WindowsElement>(new Uri("http://127.0.0.1:4723"), appCapabilities);
    }

    private WindowsDriver<WindowsElement> CreateSessionWPF()
    {
        DesiredCapabilities appCapabilities = new DesiredCapabilities();
        appCapabilities.SetCapability("app", @"c:\xxx\App1.WPF.exe");
        return new WindowsDriver<WindowsElement>(new Uri("http://127.0.0.1:4723"), appCapabilities);
    }

    private AndroidDriver<AndroidElement> CreateSessionAndroid()
    {
        DesiredCapabilities appCapabilities = new DesiredCapabilities();
        appCapabilities.SetCapability(MobileCapabilityType.DeviceName, "emulator-5554");
        appCapabilities.SetCapability(MobileCapabilityType.PlatformVersion, "8.1");
        appCapabilities.SetCapability(AndroidMobileCapabilityType.AppPackage, "com.companyname.App1");
        appCapabilities.SetCapability(MobileCapabilityType.PlatformName, "Android");
        appCapabilities.SetCapability(AndroidMobileCapabilityType.AppActivity, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.MainActivity");
        return new AndroidDriver<AndroidElement>(new Uri("http://127.0.0.1:4723/wd/hub"), appCapabilities);
    }

実行はこんな感じ。静止画じゃ分からないけど、勝手に文字が入力されてボタンが押される。

てことで、単純なUIのテストはこれで自動化できるかな。まあ、UIが崩れるとか、なんか変、っていうバグの方が多いんだけど、画面遷移とかはこれで自動化して、人が見ないと分からないようなテストにリソースを集中できれば成功かな。

そして、まだ試してないけど問題文章も自動で打てるのだろうか。そうすると不正ツールを作れてしまうかも。とりあえず打ち込み速度が遅いからよさそうだけど、設定ができたりすると厄介。

2019/03/02にWTオンライン大会「Warriors of Typing」が開かれるとのこと。運営Twitter参照。

運営者さんからは、ポート開放の手間がないWT3.5を使いたいという打診が少し前にあって、WT3.5での対戦実績がないから少し不安なものの、OKを返している。とりあえずWTサーバが落ちるとどうしようもなくなるため、1分ごとに監視して落ちてたら再起動する、という保険は打っておいた。

ちなみにWT3.5はまだ開発版。Windowsデスクトップ版ではテストは完了しているのだが、Windowsストア、Android、iOS、Macが一通りそろってから正式版にしようかと考えている。今のままだと、Mac版の人とWindows版の人がデフォルトでは対戦できなくなってしまうので。まあ、今の使われ方ではそこまで気にしなくていいだろうけど。

冬休みの研究としてウェザタイをクライアントサーバ方式にしてみた。これをそのまま使えばポート開放しなくてよくなる。ただ,全部をサーバクライアント方式にすると,サーバの通信量的にどうなんだろう,というのがあるので,直接つながらなかったときだけウェザタイサーバを使うようにすることを検討中。ちなみに通信量を測ってみたら,4人対戦で30ワード打つとだいたい送受信2.5MB。1日100回対戦があっても250MBで,全部クライアントサーバにしたところで,まあたいしたことはないのかな,とは思う。

ちなみに,以前のネットワーク構成。ホストとゲストをP2Pで接続するので,全員にポート開放が必要。元々はホストもゲストも同条件にしたかったのでこういう構成にした。

今のネットワーク構成。ホスト側にサーバを分離して,ゲストからはサーバにつなぎにいくので,ホスト側だけポート開放が必要。遅延が大きい環境だと,多少ホスト有利になる可能性がある。

で,検討中のネットワーク構成。分離していたホストをdenasuサーバへ持って行くことで完全なサーバクライアントに。

一応もう一つ選択肢があって,サーバを公開して誰でもサーバをたてられるようにする,というのもある。Linuxに.NET Core runtimeを入れて,1.5MBくらいのサーバを実行するだけで,サーバを立てるのは割とお手軽。

RTC2018の本番前、TwitterでWeather Typingの指摘をもらった。内容は、左右のシフトを両方押して片方離すとシフトが押されていないことになるというもの。ウェザタイ2では問題ないようなので、ウェザタイ3くらいからのバグっぽい。

ひとまず左右のシフトを区別しないまま、シフトを押した回数をReference Counter的に解決してみたが、左右のシフトの押し離しイベントの数が合わないことがあるようでダメ。RTC2018では修正しないことにした。

で、落ち着いて直してみたが、WPFはいいけど、UWPだとそもそもKeyDown-KeyDown-KeyUpしかイベントが来ない。こんなところでハマるとは。とりあえずKeyStateをとってシフトが押されてなければKeyUpイベントを無理矢理送ることでとりあえず解決。

ウェザタイ、RTC2018バージョンで改造した部分を本体のカスタマイズでできるようにする計画。まずは背景画像を設定できるように。

やっているうちにいろいろ増えてしまったけど、これだけあればだいたいのニーズに対応できるかな。タイル表示は難しいので入れてないけど。

前の日記で書いていたREALFORCEの画像を背景に設定したのがこれ。公式背景にはできないので、ここに貼り付けるだけ。

11/18、Red Bull Gaming Sphere Tokyoで行われたREALFORCE TYPING CHAMPIONSHIP 2018(以下RTC)を現地観戦してきた。RTCは東プレ主催のタイピング大会で、2年連続でオフライントーナメントとしてWeather Typingを使って頂いている。去年の大会も最高だったのだが、今年はいろいろと改善されていてさらによいものになっていた。

運営協力に名前が

今回、公式サイトや配信サイトの下にDenasu Systemが入っている。この並びにあるとどんな法人企業だ、という感じだけど、ありがたい。

で、実際に何をしたかというと、今のウェザタイのRTC2018向け改修。最近、配信でウェザタイをプレイしている方がいらっしゃったりするので、配信に向けた画面構成のヒントがもらえるかも、ってことでできるだけ協力させて頂いた。黒に赤でREALFORCE感を出しながらかっこよくなってますね。背景やフォントなんかは、デフォルトでこのぐらいカスタマイズできるようにはしたいところ。背景、なぜかREALFORCE画像だけでなくWeather Typingのロゴも出ていたけど、単にサンプルで適当に送っただけで、本番で使われるとは思ってなかった。

ちなみに、REALFORCEの遠近を強調した写真を背景画像にしてみたことがあって、なかなかかっこよかったのだか、意匠権的に自分でモデリングしないとな、ってところで止まっていた。まさか本家側で実現されてしまうとは。

さらに余談。ウェザタイの修正は、昼間の仕事が終わってからもう一つ仕事する感じてなかなか大変だった。けど、昼間の仕事と違って、やるかやらないかは全部自分で決められるというのはやっぱり楽しい。会社だと予算もあるしステークホルダーも多いし、作ってしまえばすぐなのにまずは断るところから入るとか、面白くないところも多いわけで。

オンライン予選

とりあえずe-typingを打ってみたけど、やっぱり話にならず、登録はせず。当日も参戦はしていないのだが、こんなの間近で見るしかないってことで、シンガポールから一時帰国。しかも月曜日は東京なので時間を気にする必要もない。

オフライントーナメント

いつもの通り、大会を純粋に楽しむのと、トラブルが起きないように祈る気持ちで観戦。会場、ゲーミングというとおり、対戦と観戦がしやすい作り。前回のTGSは混み合っていたのと他のブースの音と混じりあっていて、それもそれで良かったんだけど、やっぱり選手は大変そうだった。今回は、ヘッドフォンもあってミス音も(多分)聞こえるようになっていたり、選手が集中できる環境になっていた。観客の盛り上がりが、と言う話もあったけど、あれだけ接戦が続くと見入ってしまうというのはあると思う。他のe-sportsってどういう盛り上がり方をするんだろう。

画面構成。プロフィール表示とか、カメラを回さなくても画面が切り替えられたり、配信でも見やすくなっていた。ただ、WTの問題で結果画面がちゃんと出ない問題があって、対戦結果が分かりにくい場面が結構あった。実はロビーでテストしていたときに同じような現象が起きたというのは聞いたのだが、シンガポールでVMもない環境で、ちゃんとした調査がができないままだった。一応、片方画面がおかしくても、相手側にはちゃんと表示されていたので95%判定などはできていたのだが、観客にも分かりにくい画面になっていた。

あとは、必ず最初のワードのプレイヤ表示が2人重なっていたとか。最初のワードは見ても意味がないので支障はないのだか。

大会の内容は例のごとく他のレポートの方が詳しいはずなのでさらっと書く。まだ配信見てないので記憶間違いあるかも。予選かな決勝、TODでタイピングにはまったタイパーとしては、たにごんさん vs dqmaniacさんなんて、夢のカード。なんでこの二人がウェザタイで競ってるんだ、というのとか、去年のリベンジで1回戦から対戦相手にmiriさん指定しかもかなローマ字選択制ルールを活かして、かな入力で挑んだテルさんとか。で決勝。どうなっているんだろうというくらいの接戦。まだ第2回だけど、回を重ねるごとにドラマが生まれそうで熱い。

今回のルール。95%ルールに加えてワード選択により新たな戦略性を、ということかな。ただ自分くらいのレベルでローマ字しかしない人、だとワードの特性は分かりづらかった。このワードはこういう特性で、こういう選手に有利、っていうのがどこかにあるか、解説されると、もっとワード選択の意図が分かって面白いかも。大会を見ていて思ったのだか、95%ルールを付けてあえて複雑にすることで、観戦者もただタイピングの早さを見るんじゃなく、今94%だからこうするはず、とか考えることで面白さが増しているように感じる。多分観戦者も、情報があればワード選択の意図を考えて楽しむ余裕はありそう。

ダブルエリミネーションのルールもちょっと分かりにくくは感じたが、こっちは一般的なルール? であれば、観戦を楽しむためにちゃんと理解して観戦すればよい、のかな。

WT改善点

オフライン予選、トーナメント、大会後の会でもらった宿題のまとめ。やっぱり、サミットとか、こういう場所に行くと、いろいろな情報が得られる。

  • 結果画面問題。調査要
  • 最初のワードのユーザ表示問題。調査要
  • ロビーにゾンビが残ってしまう問題。なんか懐かしい。
  • ポート解放がやっぱり難しい。クラウドでサーバー借りて常設ホストを考えてはいるけど、まだ実行に移せず。
  • 入力不可時間に問題文を入れるのは無駄というか邪魔になるので、見えないようにしたらどうか。→ついでにワード毎のスピードとか出したらいいかな。出したいけどどこに表示しようか悩んでいたところなので。
  • 気付いた点。対戦を続けた場合に何勝したかを入れる。なんで今までなかったんだろう。
  • 気付いた点。対戦中はマウスカーソルを消す機能?

まとめ

今年も素晴らしい大会を開いてもらって感謝。これからも続けていきたいという話もあったので、ウェザタイも継続して使ってもらえるよう改善していくつもり。

で、WTのマルチプラットフォーム化でちょっと安定性が落ちてるので安定性を高めないと、とか、配信向けの最適化とか、さらにやることが増えた。宿題がどんどんたまっていくので開発が一人では限界。それだけでなく、RTCみたいな場が出てくると、私が開発を止めただけで終わってしまうようなリスクは避けないといけないし、どうにかしたい。Webランキング不正のリスクをとってでもオープンソース化するべきなのかも。

せっかくシンガポールにいるのでどこかに行かないとってことでシンガポールの電気街、Sim Lim Square、Sim Lim Towerへ。

Sim Lim Squareは1つのビルに電気店がたくさん入った場所。こっちは普通にスマホとかが売っている店なんだけど、すごいたくさん店がある。

もう一つのSim Lim Towerは面白かった。もう少しコアな店というか、パーツ店が集まった感じ。1店電子工作向けの店があったのでじっくり見てみた。日本と同じような感じでタミヤ製品もあったり。

シンガポールに来てから時間がなくて日記を更新できなかった。

今年もREALFORCE TYPING CHAMPIONSHIPが開催されるとのこと。既にe-typingによるオンライン予選がスタートしている。

前回の東京ゲームショウは、eスポーツとしてのタイピングの可能性が見えたので、今回も盛り上がってほしい。前回の感想→2017/09/24の日記

Xamarin.Forms 3.1のデグレードの続き。WPF版でXamarin.Formsを3.0から3.1にすると,UI部品を動的にサイズ変更できなくなるという問題が発生する。ソースの変更点を調べると,ViewRendererのUpdateHeight,UpdateWidthで,Element.HeightRequestとElement.WidthRequestを使っている箇所がElement.HeightとElement.Widthに変わっていた。元々Requestが-1のときは動いてなくて,Requestを取ってちゃんと動くようにしたっぽいんだけど,WPFのTextBlockのControl.Width/Heightを変えてしまうとうまくサイズ変更されない。なので,とりあえずLabelRendererを作ってUpdateHeight,UpdateWidthをオーバーライドして何もしないようにすればLabelはなんとかなる。だが,ListViewのHasUnevenRowsなんかは回避できなかったので,動的な行サイズの変更はやめた。

追記。Xamarin 3.2 Previewを動かしてみたらUWPではリストが途中で切れるようになるし,WPFではラベルが落ちるようになった。Xamarinのバージョンアップのバグに対応する前に次のバージョンのバグが出てくるからもう無理。過去のバグは1つも直らないのでバグ回避が増えていくだけ。

D.E.放送局さんの「視聴者参加型 タイピング対決~負けたら台詞読み~」を見てみた。ちょっと前に配信に使って良いか問い合わせて頂いたのだが,twitterで情報が流れてきたので。

タイピングサミットでオフラインの大会は何度か見ていたのだが,配信だとこうなるのか,というのでタイピングの動画としても面白かったし,開発視点でも参考になった。いくつかメモ。

  • 対戦できる人数。仕様としては8人まで。誰かがOKを押して「待機中」になると,その後の人が参加できなくなる。そのため,4人で締切になったりしていた。キャンセルすれば「待機中」を消せるとかあるけど,やっぱりここは分かりづらい。
  • 5人以上だと画面表示や通信の問題があるので,対戦人数を制限するオプションはいるかも。オフラインの大会だと人数を制限できるのでよいが,配信だと必要になってくる。
  • 4桁のゲーム番号はアプリを終了させるまでは変わらない。これは何度か連続で同じ人とやる場合を考えた仕様だけど,配信の場合,ゲーム番号をみんなに伝えて早い者勝ちにする,って感じになってて,毎回変わった方が便利そう
  • 配信者も,見てる側も,配信動画を流しながらウェザタイの対戦もしてるわけだが,4人対戦くらいなら十分な速度が出るというのが分かった。8人はさすがに重そうだったけど。

ついでに,ちょくちょくウェザタイを○○に使いたい,っていうメールを頂いているので,「よくある質問」にOKって書いておいた。

XamarinのListViewは鬼門というかおかしな動きが多い。2週間くらい前にXamarinを3.0から3.1にしたのだが,UWPでページ遷移をすると落ちるようになった。2週間ずっと調査していて,ようやく解決。

事象としては,NavigationPage内にListViewを含むページを入れて,ListView内の項目を全削除してから他のページにナビゲート(PopAsync/PushAsync)すると,UnhandledExceptionなNullReferenceExceptionが発生する。ノーヒント。

ListViewのBindingを外したりSleepを入れたりすると落ちなかったりするのだが,根本的には,Xamarin.Forms 3.1でUWP ListViewRendererのList.UpdateLayout()がDevice.BeginInvokeOnMainThreadで実行されるように変わったことが原因。今日神奈川に帰るときに新幹線内暇だったので,このレンダラーをプロジェクトに取り込んでデバッグしてみて,ようやく分かった。以前はListViewが変更されて,UpdateLayoutが行われて,ListViewがDisposeされるという順番だったのが,ListViewがDisposeされてからUIスレッドでUpdateLayoutが行われるので落ちる。

すっきりした回避方法もないんだけど,PopAsync/PushAsyncをDevice.BeginInvokeOnMainThreadで実行するようにして,Navigateが最後になるようにしてみてようやく落ちなくなった。

WPF版もXamarin.Forms 3.1でいろいろデグっているので回避しないと。いつになったら本当にやりたいことができるのか。

第一回第二回に引き続き、大阪南港ATCで開催されたALL ABOUT ベーマガIISP in 大阪に参加してきた。

元々、大阪の人に譲るためチケット争奪には加わらなかったのだが、しばらく売り切れにはならなかったのでポチっと。その後7月から関西に住むことになったので、にわか地元民として堂々と参加。本当申し込んでおいてよかった。

会場は前回までとちょっと変わって会議室。今回は後ろの座席だったけど、前の方は今までにないくらい出演者に近かったはず。ちなみに座席番号が「A-64」みたいな形になっていて、椅子に番号が付いてなかったので若干分かりづらそうだった。「座席はLOCATE 0, 63 です」みたいになっていれば、あそこが 0, 0 だな、みたいに全員瞬時に理解できるのに、と思った。

グッズ

前回のイベントで、電波新聞社が正式にサポートするという宣言をされていた通り、今回は電波新聞社が主催。ということで、前回の会場で売ってたら収拾がつかなくなってそうなグッズの充実っぷり。私も今は一時拠点で荷物を増やせない環境なのだが、Tシャツとかステッカーを入手。ヘルメッツさんのラズパイケースなんかもPC-6001だったら買っていたところだ。

マイコンソフトコーナー

東京ではなかったので楽しみだったマイコンソフトコーナー。今時ゼビウスのアンドアジェネシスを倒して拍手が起きるイベントって何なの、って感じだけど、そこがよかった。小学生の頃、家にPC-6001版のタイニーゼビウスがあってやっていた記憶があるのだが、Wikipediaによるとその後にX1に移植されてようやくタイニーが取れた? ってことなんだろうか。展示コーナーにタイニーゼビウス mkIIが置いてあって眺めたり。

まとめ

今回のイベントはどちらかというとゲームよりで、プログラムな話題はそれほど多くはなかった。もちろんトークの内容は前回までとほとんどかぶらず、ゲームの話も面白かった。毎回トークの内容が違うのはさすがで、20年の時間を感じるところ。ただ、プログラマ日記としてはあまり書くことがない感じかな。

今回会場を抑えめにしてマイコンソフトコーナーを持ってきたみたいに、投稿プログラムを解説するコーナーをメインにしたミニイベントとか、90年代中心のミニイベントとかあるといいなあ、みたいなことを思ったり。

今月は関西移住で生活がいっぱいいっぱいになって開発ができてなかったのだが、今回のイベントでまたモチベーションを高められた。いろいろ作りたいものがたまっているので開発を再開しよう。まずはウェザタイオフラインonラズパイだけど、ラズパイと電子工作の部品が手元にない。いつ一時拠点に持ってこれるのか。

その他

同時開催のメイカーズバザールも行ってみた。んだけど、物販開始まで20分くらいしか時間がなかったので、とりあえずオリジナル製品ゾーンを一通り見て回ったくらい。

本来は今日は大阪に泊まって明日日本橋とか見て回りたかったんだけど、いつでもいけるようになったので今日はそのまま帰宅。でんでんタウンはまた今度。

Weather Typing 3.3がMacOSストアで公開された。これで予定していた全プラットフォームで公開されたことになる。GitHub更新がまだ残ってるけど。

各ストアの入り口はWeather Typingのページを参照。

明日から関西に別荘を作って仮住まいするので,なんとか間に合ってよかった。これから荷物を準備しないと。

Weather Typing 3.3をMicrosoft/Google/Appleのストアに申請した。Windows/Androidは既に公開済みでiOS/MacOSは申請中。

久しぶりに申請した感想としては,Windowsストアが一番楽。Appleストアはきつい。Windowsストアはアプリが少ないのでできるだけ登録しやすくしていて,Appleはアプリが多すぎて質が落ちるのを嫌って障壁を作っているんじゃないかと邪推してしまう。


Microsoftストアは特に何もつまづくことなく申請と登録が完了した。前回の申請からそんなに期間が空いてないのもあるのかもだけど,一番申請しやすい気がする。


Googleプレイは特に前と変わらずだが,元々見づらいというか・・・。申請しようとしたら,もうすぐ古いOS(API)のアプリは申請できなくなるという警告が出た。でAPIレベルを上げたら,パーミッションの設定の方法が変わっていて動かなくなった。とりあえずアプリ起動時に,パーミッション許可をユーザに聞くようにして,許可されなかったら終了するようにした。本当は許可しなくてもある程度使えるようにするのがいいんだろうけど。


Appleストア。どのストアも必要なスクリーンショットやアイコンがかなりあるんだけど,Appleはビルド,アップロード,サブミットと色んな段階で少しずつエラーにしてくるのがつらい。スクリーンショットも,厳密にピクセル数が決まっているのに,シミュレータではどうやってもその解像度の画像を作れないとか。最終的に「アップロードして完了したけどiPadのアイコンはなかったよ」とか言われて,修正するにはアプリのバージョンを上げないといけないとか。ちゃんとしたアプリを開発している人は途中で投げ出して,スパム業者だけはちゃんと頑張るみたいな状況になったりしないのかな。

ただ,輸出管理のことをちゃんと出してきたのはAppleストアだけかな。Mac版を申請しようとしたら,HTTPSを使っているだけでも輸出管理が必要だ,と言われて,なるほど,的な。denasu.comのHTTPS化でここに影響があるのか。結局,年次レポートを米国に出せばいいのかな。