ごらくらいふ

プログラミングしたりゲームしたり

togglを三日坊主する

こういう脇道をせずにそのまま仕事をすればそのまま成果になるだろうに、逸れちゃうんだな、これが。

time tracking web service "toggl"を、とりあえず三日坊主する。

また三日坊主するときのために書き方まとめ。

何を記入するか

タスク

  • 行動のタイトルをサッと書く。

プロジェクト

  • プロジェクト名が明確ならそのまま書く
  • プロジェクト名が無いようなタスクの場合
    • 飯を食うとか風呂とか→生活→Life
    • アニメを見る→期毎に分けてもいい→Anime-YYYY-春

アルファベット表記を使えるなら使う。フィルタかけるのが楽になるから。

クライアント
  • 自社のプロジェクト→自社とわかるやつ
  • 他者のプロジェクト→他社とわかるやつ
  • 自分用→Me

タグ

  • すきなように

iPadでdvorak jpほしい

f:id:yajamon:20160419210359p:plain

無いから作ってる。

とりあえずアルファベット直輸入と末梢できるようにしたよ。

f:id:yajamon:20160419210541p:plain

f:id:yajamon:20160419210640p:plain

ハハッワロス

入力中の文字列をinputAccessoryViewに表示したいけど、UITextViewとか入力先が保持してるパターンの資料しか見つかってないので辛い。

ローマ字テーブルも作らなきゃ

プログラムする前にペーパークラフトするのは

先日、すごくためになりそうなツイートを見た。

最近、マルバツゲームを元にBDDやってみようと始めたところ、無計画ゆえに案の定停滞してしまった。 ここはひとつ有能な人の手法を利用しようと思った次第。

yajamon.hatenablog.com

手探り状態のとき

マルバツゲームは空いてるマスにマルとバツを埋めていくゲームだ。

マスが3x3に集まったものをFieldとして定義したは良いものの、 肝心のマスがどうあればマルで、どうあればバツとするかの定義に迷ってしまった。

そこで書いたコードが以下である。

enum SQUARE_STATE {
    EMPTY,
    CIRCLE,
    CROSS,
}
class Square {
    state:SQUARE_STATE;
}

目前の書きかけのコードとぼんやりとした想像だけで進めた結果、こういうコードを書いてしまう。

これを元に動作を実装すると以下のような感じだろうか。

class Game {
    field;
    setState(x, y){
        var state = this.getSide(); // CIRCLE or CROSS
        this.field.setSquareState(x, y, state);
    }
    setSquareState(x, y, state){
        this.field.getSquare(x, y).set(state);
    }
}

規模が小さいのでまあ別に…って気もする。が、なんだかGameがSquareにべったりな気がして落ち着かない。

とにかくクラフトだ

f:id:yajamon:20160404181033j:plain

f:id:yajamon:20160404175724j:plain

作ってみた。

見えてくる設計

ざっくり作ってみるだけでも、これは設計のポイントじゃないか、と思えるものがいくつか見えてきた。

  1. マル・バツはマス目の状態じゃなく、マス目に置けるものに見えた
    • Puttableというinterfaceが見えた
      • (置くものであることを表現したいので英語力ください)
      • (Pieceが適切?)
    • マス目の状態は"置いてある"か"置いていないか"の2つ
  2. マスを1つ埋めるとき、GameやFieldが直接マル・バツを意識しなくてもいい
    • マスを埋めるモノを持っているのはプレイヤー
      • Playerというclassが見えた
    • ゲーム開始時に、2人のプレイヤーにマル、バツを配り、Gameは誰の手番か管理するほうが自然

if設計

紙を自由に動かせるので、違うパターンをすぐに試せるの便利だった。

プレイヤーは1人では

f:id:yajamon:20160404182739j:plain

操作するのは結局Webページを開いている1人と考えると、別にマル・バツを配らずに、 ゲーム管理クラス側で管理してもいいんじゃないか。と考えた場合。

マス目クリック時にgame.put(x, y)と呼ぶだけで済みそう。 そのかわり「今操作するとマル(バツ)を置く」ことを明示したほうがいい。ということが見えた。

最初のコードにそってマス目をクラフトしてみる

f:id:yajamon:20160404183301j:plain

「マス目が状態を切り替える」ってつまりこういう事では。 大した作業じゃないけど、微妙にめんどくさかった。

クラフトする時点でめんどくさいのだから、コードにしてもめんどくさいんじゃないかな。

所感・その後

ペーパークラフト最強では。そりゃあ有能な人が使うわけだ。 有能に近づきたい。

現在は「ゲームルール」という「概念」をクラフトなりBDDなりに落としこむ方法を考え中。

ターミナルからプロビジョニングプロファイルのUUIDを確認する

コマンドラインを使ってDeveloper Centerから落としたプロビジョニングプロファイルのUUIDを確認したかった。

security cms -D -i your.mobileprovision | grep UUID -A 1

参考URL

iOS 開発で使用する証明書、プロビジョニングプロファイルの内容を確認する方法 | moonxseed

共通のキーワードを持つファイルたちをBashで一括置換リネームする

記事タイトルの通り、共通のキーワードを持つファイルたちを一括でリネームしたい状況になった。

たとえば

  • デザイナと image_yyyymmdd_{s,m,l}というファイル名でやり取りしてるが、最終的にはyyyymmddが不要とか、キーワードに置換するとか
  • app.yyyymmdd.log の日付部分を消したいとか

bashには置換する変数展開がある

item="a findString."
echo ${item/findString/replaceString} # a replaceString.

例に適用する

ls
# image_yyyymmdd_s.jpg image_yyyymmdd_m.jpg image_yyyymmdd_l.jpg

for item in $(ls)
do
    mv -v $item ${item//yyyymmdd/00000000}
done
ls
# app.yyyymmdd.log debug.yyyymmdd.log error.yyyymmdd.log

for item in $(ls)
do
    mv -v $item ${item//.yyyymmdd/}
done

参考

d.hatena.ne.jp

BDDの書き方、始め方が分からなかったので、まず書いた

テストは大事なのは分かる。TDDやBDDでキーワードを手繰って、向き不向きやコンセプトの説明も見た。 けどそればかり拾ってしまって、実際にどう考えたらいいのか、どう書き出せばいいのか全くわからない。

「BDDでプログラミングする」を指針にマルバツゲームを作る。 という流れで、BDDで書き始める過程をメモ。

前提

  • typescriptで
  • コーディング環境は構築済みで
  • mocha+chaiを使って進める

まずは考えたことを捨てないことから

「テストのできるコードってなんだ」というQが頭に浮かんだまま、コードを考えようとしていた。

「盤面は3x3で、先手後手があって、つまりプレイヤーが2人いて、3つ記号が並んだら勝ちで」

自分はこの時、句点がひとつ入るたびに前の言葉が頭から消えている。 考えは連続してしていても次のこと考えるたびに「保存しない」を選択していちゃ意味が無い。

「盤面は3x3で」を意識から捨てない

この、「どうあるのか」考えたことをテストに吐き出していくのがBDDの書き方なのでは、と思ったので書きなぐる。 幅、高さが3の二次元配列を想像したので、そのように書く。

命名も多分このタイミングでしないといけない。

describe("Field", function(){
    let field = new MainApp.Field();

    describe("data", function() {
        it("is array", function () {
            expect(field.data).to.be.a("array");
        });

        it("width 3", function() {
            expect(field.data).to.have.lengthOf(3);
        });
        
        it("has array in data", function () {
            field.data.forEach((element)=>{
                expect(element).to.be.a("array");
            });
        });
        
        it("height 3", function () {
            field.data.forEach((element)=>{
                expect(element).to.have.lengthOf(3);
            });
        });
    });
});
実装

今書いたテストをPassするコードを書いた。

namespace MainApp {
    /**
     * Field
     */
    export class Field {
        data:any[][];
        constructor() {
            this.data = [
                [null, null, null],
                [null, null, null],
                [null, null, null],
            ];
        }
    }
}

なんかテスト通った。謎の感動。

所感

テストコードなんて書かないか、思いのままに実装してから動作確認に雑なものを書く程度だから難しい。 この「思いのまま」をテストコードに言語化するのかー。

リポジトリ

github.com

あるマスタから順不同に取り出した要素2件を組み合わせ、意味を持たせるときのテーブル構造

※ながめだよ

先日、PSStoreのセールにつられて「俺に働けって言われても乙 HD」を買った。 ほんのりプレイしていたところ、『このデータを表現するテーブルはどんな構造だ?』と気になったので考えた。 考えたので残すことにした。

経緯

ゲームシステムのひとつに「施設建設」というものがある。 武器屋や採掘場を建設し、新しい武器の開発や素材生産で冒険をサポートするのだ。

さらに、特定の施設を隣接させると「シナジー効果」が発生する。 武器屋の隣に鍛冶屋を建てれば「武器の性能が5%UP」する、といった具合だ。

このシナジー効果、建物によって発生したりしなかったりする上、UI上の問題でシナジー効果の確認が少々面倒くさい。 ので、スプレッドシートにメモを取ろうとしたところ、どういう構造なのか疑問を持った。

テーブル考察

RDBのテーブルとして定義した場合を考える。これは趣味だ。

(KVSとかドキュメントストアの考え方知りたい)

前提情報

状況

すでに武器屋が建設済みで、その隣に鍛冶屋を建設するという状況で進めていく。

マスタ

施設と効果について、以下のようにマスタが区切られている。 IDカラムは主キーである。

施設マスタ

ID 施設名
1 武器屋
2 防具屋
3 道具屋
4 鍛冶屋

効果マスタ

ID 効果内容
1 武器の性能が5%UP
2 施設維持費300J/日
複合主キー?サロゲートキー

前述のマスタに登場するIDカラムを除き、主キーを明言しない。

パターン1:とにかく最小で必要なレコードを追加したパターン

シナジー効果

施設ID1 施設ID2 効果ID
1 4 1
1 4 2

とりあえず作りましたパターン。 効果マスタのJOINはするかしないか流派があるので割愛するが、必要となるSQLは以下のような感じだろうか。

SELECT * FROM シナジー効果 WHERE 施設ID1=4 AND 施設ID2=1;
-- 最小で必要なレコードしかないため、施設IDを入れ替えての確認もする
SELECT * FROM シナジー効果 WHERE 施設ID1=1 AND 施設ID2=4;
所感
  • アプリケーション側が2度SQLを発行するのが喧嘩の種になりそう
  • 効果IDが同じで、施設IDが入れ替ったレコードがさらに追加される危険がある
    • 効果IDをユニークにしてしまう対策
      • 施設維持費加算の効果レコードが、対象の施設ごとに必要になる
    • 施設IDが小さい方が常に施設ID1になるようデータ登録する運用対策
      • コード側での比較処理が必要
      • 負担は減る
      • 間違って登録したときに、施設ID1に大きなものが入ってることを認識していないと、調査が困難
        • 間違って登録してしまうのに、調査で間違いに気づけるかどうか……
        • 「とりあえず正しいレコード足しとけ」で解決はできる

パターン2:コードの簡素化を優先し、似たようなレコードを登録したパターン

シナジー効果

施設ID 隣接施設ID 効果ID
1 4 1
1 4 2
4 1 1
4 1 2

これから建設しようとしてる施設と、建設済みの施設が明確なことから、実装作業の簡素化を目的にテーブル側に苦労させるパターン。 SQLは一度だけ実行すれば良いのでシンプル。

SELECT * FROM シナジー効果 WHERE 施設ID=4 AND 隣接施設ID=1;
所感
  • 登録作業がめんどくさそう
    • 登録補助がないとやりたくない
    • 管理画面なり表計算ソフトなりでのサポートさえできればよくある選択肢ではないだろうか

パターン3:効果IDを主体にするパターン

シナジー効果

効果ID 施設ID
1 1
1 4
2 1
2 4

組み合わせに順番なんか必要ないという発想を体現したパターン。SQLはちょっと豪快。

SELECT DISTINCT
    シナジー効果.効果ID
FROM
    シナジー効果
    INNER JOIN シナジー効果 AS temporary
        ON シナジー効果.効果ID = temporary.効果ID
        AND temporary.施設ID = 1 --隣接施設ID
WHERE
    シナジー効果.施設ID=4
;

-- あるいは

SELECT
    効果ID,
    COUNT(*) AS RecordCount
FROM
    シナジー効果
WHERE
    施設ID IN (1, 4)
GROUP BY
    効果ID
HAVING
    RecordCount > 1
;
所感
  • 仕様に胡座をかいてる感がある
  • 効果を使い回すことができなくなるので、同じ効果だが組み合わせが違うケース1件につきひとつ、効果レコードが必要になる
効果を使い回せない問題

例えば防具と鍛冶屋の組み合わせ。この場合、防具の効果5%UP施設維持費300J/日が発生する。 この内、5%UPを効果ID=3とし、維持費は効果ID=2を使い回そうとして、以下の様なテーブルを作ったとする。

シナジー効果

効果ID 施設ID
1 1
1 4
2 1
2 4
2 2
3 2
3 4

そして次のようなSQLをかけると

SELECT
    効果ID,
    COUNT(*) AS RecordCount
FROM
    シナジー効果
WHERE
    施設ID IN (1, 2)
GROUP BY
    効果ID
HAVING
    RecordCount > 1
;

武器屋と防具屋の間にシナジー効果が発生し、ただ維持費をむしり取られる展開になってしまう。

パターン4:パターン3を発展、組み合わせという概念を定義するパターン

組み合わせマスタ

組み合わせID
1

施設組み合わせ

組み合わせID 施設ID
1 1
1 4

シナジー効果

組み合わせID 効果ID
1 1
1 2

シナジー効果は施設の組み合わせに紐づくため、新たに組み合わせマスタを定義したパターン。 SQLは以下の様になるだろう。

SELECT
    *
FROM (
    SELECT
        組み合わせID,
        COUNT(*) AS RecordCount
    FROM
        施設組み合わせ
    WHERE
        施設ID IN (1, 2)
    GROUP BY
        組み合わせID
    HAVING
        RecordCount > 1
    ) AS 組み合わせ
    INNER JOIN シナジー効果
        ON 組み合わせ.組み合わせID = シナジー効果.組み合わせID
;
所感
  • SQLながい
  • 施設の順番も、余分なレコードも討ち取った