milkcocoaを使ってみた

この記事はmilkcocoa Advent Calendar 2014の13日目の記事です。

簡単にリアルタイム通信できると聞いて興味が湧いたので思わず参加しました。

とりあえず、作成したもの=>GO!

みんなに紹介したいこと

1つDataStoreを使用して異なるコマンドを送受信してみたので
その対応方法を書いてみたいと思います
※以下ソースコードはTypeScriptを使用しています。

それでは、説明していきましょう~

1.異なるコマンドを分岐するために列挙を定義する

enum Command {
  Born,   // 生まれる(キャラ作成)
  Alive,  // 生存しているアピール
  Move,   // 移動(クリックした座標を送信)
}

2.送信用パッケージ定義する

class Package {
  // cmd : パッケージコマンド
  // data : 追加データ(コマンド毎に異なる)
  constructor(public cmd: Command, public data: any) { }
}

3.送信ヘルパー関数

実行したいコマンド+必要なデータを1つオブジェクトにして送信しています

var ds = milkcocoa.dataStore("message");
function send(command: Command, data: any) {
  ds.send(new Package(command,data));
}

4.受信部

何か受信したら、data.valueから送信したオブジェクトを取得できます

var ds = milkcocoa.dataStore("message");
ds.on("send", (data:any)=>{
  var p = <Package>data.value; // オブジェクトをPackageにキャスト
  switch (p.cmd) {
    case Command.Born:
    // MEMO:誰か生まれた
    break;
    case Command.Alive:
    // MEMO:誰か生存しているアピールした
    break;
    case Command.Move:
    // MEMO:誰か移動した
    break;
  }
});

使用例:移動先の座標を送信する場合

send(Command.Move,{x:10,y:20});

最後に

書き終わって振り返ってみたら、

milkcocoa成分が少なすぎる、本当にいいのか・・

と思っちゃいます、これもmilkcocoaの強みと言えるでしょう。

駆け足ですが以上で終わります。ではでは~

おまけ

サンプルのソースコード=> DL
Visual Studio Community 2013で動作確認

milkcocoaのTypeScript用型定義ファイル=> GitHub

必要な方どうぞ~

3分でTypeScriptの定義ファイルの作成方法を覚えよう

この記事はTypeScript Advent Calendar 2014の9日目の記事です。

TypeScriptの定義ファイル(d.ts)の作成方法について書いてみます(自分用メモを兼ねて・・)
まだTypeScript歴は浅いので、間違ったことがありましたら指摘していただければ幸いです

説明に使用するJavaScriptライブラリ:milkcocoa

JavaScript1行でバックエンドを提供します」と面白そうなので、
このライブラリを使って説明していきます

簡単!?3分で作成方法を覚えられる

リファレンスが揃えれば、簡単に変換できます(全手動ですが・・・)

  • ステップ1:クラスのレイアウト作成
  • ステップ2:メソッド(&パラメータ)をコピペ
  • ステップ3:パラメータの型を決める

ステップ1:クラスのレイアウト作成

以下はレイアウトのテンプレートです

declare module <ライブラリ名> {
    export class <クラス名> {
        // ...メンバの実装...
    }
}
// 外部アクセスのために定義、なくても可
import <クラス名> = <ライブラリ名>.<クラス名>;

milkcocoaは以下三つクラスがあります。リファレンス

  • MilkCocoa
  • DataStore
  • Query

以下はテンプレートから変換したレイアウト

declare module milkcocoa {
    export class MilkCocoa {
    }
}
declare module milkcocoa {
    export class DataStore {
    }
}
declare module milkcocoa {
    export class Query {
    }
}
import MilkCocoa = milkcocoa.MilkCocoa;
import DataStore = milkcocoa.DataStore;
import Query = milkcocoa.Query;

ステップ2:メソッド(&パラメータ)をコピペ

MilkCocoaクラスのメソッド一覧

  • new MilkCocoa()
  • dataStore()
  • addAccount()
  • login()
  • logout()
  • getCurrentUser()

そのままコピペしましょう。(見やすいように整形しましょう

export class MilkCocoa {
  constructor(host);  //new MilkCocoa()の代わりにコンストラクタを使用する
  dataStore(path);
  addAccount(email, password, options, callback);
  login(email, password, callback);
  logout(callback);
  getCurrentUser(callback);
}

ステップ3:パラメータの型を決める

リファレンスを読みながらパラメータの型を決めていきます
※リファレンスを読んでも分からなかった場合、設定しなくても問題ありません

例1:new MilkCocoa(host)

引数:MilkCocoaのデータストアのホストへのURLをString型で渡します
戻り値:通信が確立しているMilkCocoaのインスタンスを取得することができます
※コールバック関数は引数に入れても入れなくても動作します

// コールバックを提供しない場合
constructor(host: string);
// コールバックを提供する場合
constructor(host: string, cb?: () => void);

例2:dataStore(path)

引数:データストアへのパスを指定できます
戻り値:指定したパスへのDataStoreオブジェクトを返します

dataStore(path:string) : DataStore;


説明は以上です
他のメソッドも同じようにひたすら作成していきましょう。

最後に

定義ファイルを読んだことある方にも知っていますが、いろんな書き方があります。
個人的覚えやすいと思う手順を紹介しました。

今回作成した定義ファイルはGitHubにアップしています。
作成時のご参考になるようでしたら幸いです。

ではでは~

【iOS】招待コードはリジェクト対象?

この最近、招待コードを実装されたiOSアプリがリジェクト対象になる情報が拡散している

傾向として

招待された側がアイテムを貰えるのはNG
招待した側だけアイテムを貰えるのはOK

と考える方が多く見られる

それで、なぜ招待コードはリジェクト対象になるのか
私の見解を述べてみようと思います

招待コードの仕組みに問題がある
あるユーザがゲーム開始時、
他のユーザのIDを入力すれば、
何かもらえる

この仕組みを単純化すると

ユーザがコードを入力すれば、
何かもらえる

シリアルコードと同じです

シリアルコードこそリジェクト対象

理由は簡単

ユーザがアップルの課金システムを介さずに
外部の決済システムからコードを購入できれば
アップルの30%取り分がなくなる

アプリ内課金を使わず、外部の決済システムを使うとリジェクト対象になる
すでに規約に記載されてある

App Store Review Guidelines:Purchasing and currencies
11.2
Apps utilizing a system other than the In-App Purchase API (IAP) to purchase content, 
functionality, or services in an App will be rejected

この規約を違反したからリジェクトされると私は思っています

なぜ、招待された側がもらえてはいけない、招待した側は大丈夫だと思うの?

たぶん、

何かあげるからこのアプリをダウンロードしてよ

この挙動がリジェクト対象になる

App Store Review Guidelines:Metadata
3.10
Developers who attempt to manipulate or cheat the user reviews or chart ranking in the App
Store with fake or paid reviews, or any other inappropriate methods will be removed from the iOS
Developer Program

価値あるものを配れば、
一時的ダウンロード数が増える
ランキング操作とみなす

招待した側だけアイテムがもらえる場合
ランキング操作しにくいためリジェクトされない可能性が高いだけ
※このような実装をしたアプリ数も少ない

まとめ

アップルは招待コードだからリジェクトするではなく
アップルが不利になりそうなものをリジェクトしただけと思う

【C++】2進数文字列変換

再帰でやってみた

#include <string>     // std::string
#include <functional> // std::function
std::string binary(int dec)
{
    std::function<std::string(int)> base2 = [&](int val) {
        if(val == 0) return std::string{};
        return base2(val >> 1) + std::to_string(val%2);
    };
    if(dec == 0) return "0";
    else return base2(dec);
}
#include <iostream> // std::cout & std::endl
int main()
{
    std::cout << binary(15) << std::endl; // 1111
}

cmath にある remquo という 数学関数

浮動小数点剰余を計算する関数 fmod は使ってるが、
剰余と商の両方もほしい場合、何を使うべきかを探してみた。

fmodと同じヘッダにある remquo はよさそうにみえて以下コードを書いてみた

#include <cmath>
#include <iostream>
int main()
{
    int quo;
    auto rem = remquo(59,60,&quo); // 59秒 / 60秒(1分)
    std::cout << "rem:" << rem << " quo:" << quo;
}
結果 : rem:-1 quo:1

剰余は 59 じゃなく -1 になってたけど?

しばらく調べて、どうやら戻り値は remainder の結果と同じです

remainderが返す戻り値の計算式は

x - n * y

実際に実行結果をこの計算式に適用してみた

x = 59
y = 60
n = quo = 1

x - n * y = 59 - 1 * 60 = -1

確かに、計算式はあってるけど・・・

まぁ、とりあえず remquo の挙動が分かった (正しい使い方は不明だが)

検索を再開して、cstdlib ヘッダに div を見つかりました

さっそくコードを書いて予期した挙動を確認した

#include <cstdlib>
#include <iostream>
int main()
{
    auto div = std::div(59,60);
    std::cout << "rem:" << div.rem << " quo:" << div.quot;
}
結果 : rem:59 quo:0