「AIテキサス・ホールデム」DL数の(希望的)予測

h1

上図は、おいらのアプリの中でDL数稼ぎ頭である、「AIテキサス・ホールデム」の日々のDL数の推移グラフだ。概ね安定しているが、何度か平均DL数が変化している箇所がある。2015年11月末は原因が明確で、TVでテキサスホールデムが紹介され、それにより日本でのDL数が急増した。2015年7月、2016年4月にも急増しているが、これらの原因は定かではない。

h2

上図は日本からのみのDL数のグラフだ。前述の理由で2015年11月にDL数が急増してからは、徐々にDL数が減少しているように見える。にもかかわらず、全世界でのDL数が減少していないのは、日本以外の国からのDL数が増加しているからだ。

h3

上図はUSからのDL数の推移。2015年7月頃は平均1DLあるかないかだったのが、半年後の2016年1月頃は3DL程度に、さらに半年後の2016年7月には10DL程度になっている。つまり半年で約3倍のペースで増加しているということだ。
実数で見ても、以前は日本からのDL数が50%以上とダントツだったのが、2016年6月頃からはUSのDL数が日本のそれを上回る日が多くなっている。

というわけで、今後の予想だが、日本からのDL数は、(積極的なアップデートを行わなければ)今後もゆるやかに減少していくが、日本以外からのDL、特にUSからは半年に3倍程度のペースで増加していくと(希望的に)予測される。
2016年7月初め現時点での1日のDL数は40~50、日本からのそれは 5~12なのでこれが半減しても 2~6 にしかならない。日本以外は倍増すると(希望的)予測されるので、28~45 が倍増して 56~90DL/day と予測される。

さて、2016年末にはどの程度になることやら。

SDKBOX を使って cocos2d-x プロジェクトに AdMob を追加

SDKBOXを使うと、cocos2d-x プロジェクトに AdMob を簡単に追加できるみたいだぞ。
オリジナルの解説は AdMob Integration Guide を読んでね。

プロジェクトに AdMob を組み込む

SDKBOX がすでにインストールされていれば、プロジェクトに AdMob を組み込むのは簡単だ。
コマンドプロンプトをひらき、プロジェクトのディレクトリに行き、以下のようにタイプするだけだ。

$sdkbox import admon

これだけで、AdMob のためのコードや設定がプロジェクトに追加される。

コードの追加・設定変更

上記だけでは、まだ AdMob 広告が表示されるわけではない。以下の様にコードの追加や設定変更が必要だ。

設定ファイルの修正

project/Resources に  sdkbox_config.json が追加されているので、それをテキストエディタで開く。
“ca-app-pub-XXXXXXXXXX/XXXXXXXX” という広告IDがあるので、それを適切なものに置き換え、
(後でコードから参照するための)広告シンボル名、バナー広告のサイズ位置を設定する。

        "AdMob": {
            "test": true, 
            "ads": {
                "gameover": {
                    "type": "interstitial", 
                    "id": "ca-app-pub-XXXXXXXXXX/XXXXXXXX"
                }, 
                "home": {
                    "width": 300, 
                    "type": "banner", 
                    "id": "ca-app-pub-XXXXXXXXXX/XXXXXXXX", 
                    "alignment": "bottom", 
                    "height": 50
                }
            }
        }

コードの修正

ソースコードに SDKBOX 関連のコードを記述する場合、ソースに以下の分を追加しよう。

#ifdef SDKBOX_ENABLED
#include "PluginAdMob/PluginAdMob.h"
#endif

初期化:

bool AppDelegate::applicationDidFinishLaunching() {
#ifdef SDKBOX_ENABLED
    sdkbox::PluginAdMob::init();
#endif
    // initialize director
    :
    :

キャッシュ:
自動的にはキャッシュされないので、表示する前にかならずキャッシュすること。

sdkbox::PluginAdMob::cache("home");
sdkbox::PluginAdMob::cache("gameover");

表示:

sdkbox::PluginAdMob::show("home");
sdkbox::PluginAdMob::show("gameover");

ここ2年間の広告収益の推移と今年後半の方針・目標

早いもので、もう2016年も前半が終わってしまった。
というわけで、これまでを振り返りつつ、今年後半の目標とかを述べてみたい。

ここ2年間の広告収益の推移

g

上図は一ヶ月ごとの広告収益(合計(黄)=webコンテンツ(緑)+スマホアプリ(赤))のグラフだ。
※ Y軸は金額だが、具体的な金額はナイショ ;^p
おかげさまで、2016Q2の収益はQ1の約1.5倍、前年Q2と比べると約4.4倍にもなった。
まさしく倍々ゲームで増えていて、非常に嬉しい限りだ。

このように指数関数的に収益が増えている原因としては以下が考えられる。

  • 昨年11月末に「テキサスホールデム」がTVで紹介され、「AIホールデム」のDL数が飛躍的に増えた
  • 今年に入ってから、おいらの中で人気があるアプリを iOSに移植し、リリースした
  • 3月にインテ広告を導入した

上記はうまくいっている要因だが、今年に入ってからは3本しかアプリをリリースしておらず、しかもそれらのDL数は全然伸びていない、というネガティブな要因もある。

webコンテンツとスマホアプリの収益を比べると、以前は前者の収益が多かった(というか、スマホアプリの収益が少なすぎたのだが)のだが、去年12月に逆転し、現在では後者が前者の2~3倍にもなっている。

各アプリの6月のアプリ広告収入に占める割合をみると、ホールデム:約50%、数独:約14%、さくさく将棋:約12% となっている。DL数的にはホールデムは数独・さくさく将棋の約10倍もあるのだが、収益的にはそこまでの差はついておいらず、健闘しているとも言える。これば、ホールデムは日本以外でのDL数が多く、日本・欧米以外ではクリック単価が 1/10程度なことが一因だと考えている。

今年後半の方針

  • 数(3~6)本のアプリをとりあえずリリース
    • 関数電卓
    • 詰将棋
    • ハーフギャモン
    • パズル・ボードゲーム・ツール? etc…
  • 上記の中でDL数の多いものをアップデート
  • 数独・ホールデムのアップデート

今年後半の目標

  • 12月の合計収益が6月の約2倍

新PC(win10)に cocos2d-x v3.11 をセットアップ

まずは、cocos2d-x の公式ページに行き、アーカイブをダウンロードしてくる。今現在は v3.11.1 が最新だ。
ダウンロードしたら、適当な場所に展開する。おいらは G:\cocos\cocos2d-x-3.11.1 に展開した。

で、Android 版をビルドするのであれば、Java JDK, Android SDK, NDK, ANT も必要だ。
ただし、NDK は最新版をインストールすると、cocos2d-x の方の対応がまだでビルド時にエラーになるので、少し古い版をインストールする必要があるぞ。

おいらは上記らを C:\Program Files\Java, G:\Android\android-sdk, G:\Android\android-ndk-r10e, G:\Android\apache-ant-1.9.7 に展開したぞ。

んで、cocos2d-x の setup.py を実行するのだが、これには 2系パイソンが必要だ。セットアップしていない人はセットアップが必要だぞ。

setup.py を実行すると、Android SDK らの位置を聞いてくるので正しく入力しよう。
ただし ANT_ROOT は ANT のルートディレクトリそのものではなく、すぐ下の bin を指定しなくてはいけないので注意だ。
あと、JAVA_HOME 環境変数も同様に java/jdk の位置を設定しよう。

セットアップが済めば、コマンドプロンプトから cocos を実行し、バージョン番号・簡単な使い方の説明が表示されればOKだ。

念の為に、cocos new Test -l cpp でプロジェクトを作り、cocos compile -p android でちゃんと apk が出来上がることを確認しよう。
何か間違っていると、エラーが表示されるので、エラーメッセージをよく読んで対処してね。

「足す引く算数」

【自分用メモ】

最近、親戚の集まりがあり、タブレットアプリが大好きな小2になったばかりの女の子が「算数が苦手」と言ってたので、彼女の気をひくために加減算練習アプリを作ってみることにする。

  • 難易度は、超入門(1桁+1桁=2桁、ドット表示)、入門(1桁+1桁=1桁)、初級(1桁+1桁=2桁)、中級(1桁+2桁=2桁)、上級(2桁+2桁=2桁)の5段階。
  • 問題形式は A+B=?, A-B=?, A+?=B, ?+A=B, A-?=B, ?-A=B の6種類。
  • 自然数のみ(最大2桁なので [1, 99] )
  • トップシーンで難易度選択+自動(?)
    • 指定難易度の問題をランダム形式で出題
    • 自動(?):
      • ランク情報  [0, 5] を保持
      • ランクにより問題を動的に生成
        • R が8割、R-1 が1割、R+1 が1割?
        • (R+0.5) に [-0.6, +0.6] の範囲の乱数を加える
      • 解答時間:0.5秒、1秒、2秒、5秒、10秒、10秒超 で ランク += ポイント
      • 解答を間違えると ランク -= ポイント
      • 最近
  • 1セット10問、不正解の場合は問題数が増える?

【自分用メモ】cocos2d-x Android AdMob interstitial広告表示

単に表示するコード(起動してしばらく経つと広告が表示される)

import com.google.android.gms.ads.*;

public class AppActivity extends Cocos2dxActivity {
    private InterstitialAd m_interstitial;
    protected void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState); 
        m_interstitial = new InterstitialAd(this);
        m_interstitial.setAdUnitId("ca-app-pub-XXXXXXXXXX/XXXXXXXXXX");     // インテ広告ID
    
        m_interstitial.setAdListener(new AdListener() {
          @Override
          public void onAdLoaded() {
            if (m_interstitial.isLoaded()) {
              m_interstitial.show();
            } else {
              ///ロードエラー
            }
          }
        AdRequest interRequest = new AdRequest.Builder().build();
        m_interstitial.loadAd(interRequest);
    }
}

【自分用メモ】ベイズ推定

ベイズの定理: P(A|X) = P(X|A)*P(A) / P(X)
※ P(A|X) は X が発生したときに A が発生する確率を表す

証明:

P(A|X)*P(X) = P(X|A)*P(A) なので、P(X) を右辺に移動すると、ベイズの定理となる。

例:
碁笥(ごけ 碁石の入れ物)O1, O2 があり、黒石, 白石が O1 には 10, 30個、O2 には 20, 20個入っているものとする。
プレイヤーは最初にどちらかの碁笥を選ぶ。
どちらを取るかはランダムなので P(O1) = P(O2) = 0.5 である。
どちらの碁笥を選んだかの情報は何もないので、両方 0.5 となる。

次に、プレイヤーは選んだ碁笥のなかから石をひとつ取り出して見る。
それが黒石だった場合、プレイヤーが選んだ碁笥が O1 だった確率(P(O1|B))はいくつだろうか?
ベイズの定理より、
P(O1|B) = P(B|O1)*P(O1) / P(B)
= 0.25*0.5 / (0.25*0.5 + 0.5*0.5)
= 1/3

黒石はO1の方が少ないで、O1 を選んでいた確率は 0.5 から 1/3 に下がった。
つまり、碁石をひとつ見るという観測により、どちらの碁笥を選んだかの確率が修正されたというわけだ。
ちなみに、P(O2|B) を計算すると 2/3 となり、当然ながら P(O1|B) + P(O2|B) = 1.0 となる。

では、取り出したのが白石だった場合はどうだろうか?
それぞれの碁笥を選んだ確率は以下のようになる。
P(O1|W) = P(W|O1)*P(O1) / P(W)
= 0.75 * 0.5 / (0.75*0.5 + 0.5*0.5)
= 0.6
P(O2|W) = P(W|O2)*P(O2) / P(W)
= 0.5 * 0.5 / (0.75*0.5 + 0.5*0.5)
= 0.4

白を観測した場合は白が多く入っている O1 を選んだ確率が高くなり、黒を観測した場合は黒が多く入っている O2 を選んだ確率が高くなるという、もっともらしい結論になる。

では、観測した石を碁笥に戻し、もう一度石をひとつ取り出すと、それぞれの碁笥を選んだ確率はどうなるであろうか?
観測した石が2回とも黒石だった場合:
P(O1|(B2,B1)) = P((B1,B2)|O1)*P(O1) / P(B1, B2)
= 0.25*0.25*0.5 / (0.25*0.25*0.5 + 0.5*0.5*0.5)
=

P(A|B) = P(A,B)*P(B)
P(A,B) = P(A)*P(B) = P(B,A)
P((A,B),C) = P(A,(B,C)) = P(A,b,C)
P((A,B)|C) = P(A,B,C)*P(C)

cocos2d-x iOS 移植メモ

Android 用が既に動いている cocos2d-x アプリを iOS 用にビルドするための手順メモ

  • 必要な環境
    • Mac (xcode が必要)
    • iOS 端末 (バイナリをアップロードするのに必要な Provisioning Profile を作成するのに必要)
  • プロジェクト/proj.ios_mac/プロジェクト名.xcodeproj を xcode で開く
  • 追加リソースがあれば、プロジェクトに追加

Project Navigator から Resources を選び、右クリックして Add Files to “プロジェクト名”… メニューを実行
この時、OSX 用もビルドするのであれば【Option】を開いて、ターゲットを有効にしておくと、各リソースをいちいちあとで追加しなくて済む

  • アプリアイコン、スプラッシュスクリーン変更
    • Resources 下に images.xcassets を追加
      • Command+New を実行し、iOS > Resourece > Asset Catalog を選択し、【Next】。ファイル名(例:images)を入力し、【Create】を押すとと出来上がり
      • スクリーンショット 2016-02-20 09.25.17
    • images.xcassets を開き、左下の [+] を押し、AppIcons & Launch Images > New iOS App Icon   を選び、アイコン追加
    • 同様に AppIcons & Launch Images > New iOS Launch Image   を選び、スプラッシュスクリーン追加
    • 各サイズのアプリアイコンを作成し、プロジェクト > ios > Icons に登録
      • 各サイズのアイコンを作成するのはかなり面倒。なので、下記サイト等を使うといいぞ
      • App Icon Resizer
    • 上記を images.xcassets > AppIcon の各サイズ部分にドロップ
    • 同様に、Launch Image(スプラッシュスクリーン) も追加
    • プロジェクト > General > App Icons abd Launch Images の App Icon Source の 【Use Asset Catalog】を押し、先に作った xcassets の名前を選択し、【Migrate】 を押す
    • プロジェクト > General > App Icons abd Launch Images を Application に、Launch Images Source を LaunchImage にする
  • バナー広告
    • SDKをインポート
      • Add Files to “プロジェクト”…
      • option を押し、「Copy Items if needed」にチェックを入れるのを忘れずに!
    • プロジェクト > General > Linked Frameworks and Libraries で必要なモジュールを追加
      • AdSupport
      • AudioToolbox
      • AVFoundation
      • CoreGraphics
      • CoreMedia
      • CoreTelephony
      • EventKit
      • EventKitUI
      • MessageUI
      • StoreKit
      • SystemConfiguration
    • AppController.h, AppContoller.mm にコードを追加

AppController.h:

extern "C" {
#import <GoogleMobileAds/GoogleMobileAds.h>
}

AppController.mm:

@property (nonatomic, strong) GADBannerView *adView;
.....
    self.adView = [[GADBannerView alloc] initWithAdSize:kGADAdSizeBanner];
    self.adView.adUnitID = @"ca-app-pub-0xxxxxxxxxxxxxxx/xxxxxxxxxx";
    self.adView.rootViewController = _viewController;
    [_viewController.view addSubview:self.adView];
    [self.adView loadRequest:[GADRequest request]];
    self.adView.center = CGPointMake(
                                     self.viewController.view.center.x,
                                     self.viewController.view.frame.size.height-self.adView.frame.size.height/2);

 

 

iOSアプリをAppStoreに公開するとき、理解しておいた方がいい用語をまとめてみた

iOSアプリをAppStoreに公開しようとすると大抵の人は躓くみたいだ。筆者も例外では無い。現時点も躓いている。

多くの人が躓く原因は、

  • web上、xcode での設定方法がスマートではなく、それが頻繁に変わる
  • 上記のために、ぐぐっても古い情報が大量に出てきてますます混乱する
  • 用語がよくわからない

ということではないだろうか。

というわけで、iOSアプリをAppStoreに公開する場合に理解が必要な用語について、とりあえず3つだけだけどまとめてみた。

Provisioning Profile とは:

 証明書、AppID、デバイス(端末)情報を組みにしたもの?
 端末を所有していないと作成できない
 以下で作成・管理できる
  https://developer.apple.com/account/ios/profile/profileList.action
  ※ このページは Provisioning だけでなく、認証・AppID・デバイスなども管理

App ID とは:

 アプリケーションを識別するID?
 一旦作成すると削除出来ない
 以下で作成・管理可能
  https://developer.apple.com/account/ios/identifiers/bundle/bundleCreate.action
 「App ID Description」、「App ID Prefix」「App ID Suffix」等から構成される
  「App ID Description」は単なる名前。
   例:"MyApp"
   「App ID Suffix」が異なっていれば、同じ名前の AppID を生成可能
  「App ID Prefix」は自動的に生成される
  「App ID Suffix」には「Explicit App ID」と「Wildcard App ID」の2種類がある
   == Bundle ID ?
   "com.domainname.MyApp" のような形式が推奨される
 「App Services」:アプリケーションが提供するサービスを選択可能

Bundle ID とは:

 アプリケーションバイナリとAppStore上のアプリ情報とを紐付けるID?
 == App ID の「App ID Suffix」?