ご注文はうさぎですか?第7羽からインスパイアを受けてHTML5で「ごちうさパズル」を作ってみた

ご注文はうさぎですか?第7羽からインスパイアを受けてHTML5で「ごちうさパズル」を作ってみた

ごちうさパズル

ご注文はうさぎですか?の第7羽Call Me Sister.のストーリー中で、ココアがパズルを完成させてしまうというエピソードがありました。

このエピソードからインスパイアを受け、「ごちうさパズル」を作ってみました。

あそびかた

選択した分割数(ピースの数)に応じて画像がパズルのピース毎にシャッフルされます。最大で81ピースまで選べるようにしてあります。ごちうさ本編中では4000ピースのパズルだったので、81ピースはだいぶ少ないですが、なかなか没頭できます。

解くのが面倒になった時は"RESET"ボタンを押すとパズルが元に戻ります。

ごちうさパズルの実装

パズルのエピソードを観た時、HTML5で実装できそうだと思い立ったのですが、実装で地味にハマるところが多かったです。

パズルのピースをシャッフルする際の乱数データの取得方法

パズルのピースをシャッフルする際、乱数を使ってデータをシャッフルしています。パズルのピースは重複しないため、値が重複しないように乱数値をあつめる必要があります。かなり昔のI/Oというコンピュータ雑誌に「重複しない乱数列を得る方法」的な投稿コラムがあったのですが、当時はその原理を理解できませんでした。

が、実際には難しい話ではなく、以下の方法で実現できます。

  • あらかじめ配列に値を入れておく(等差数列でOK)
  • 乱数の値を取得し、配列のインデックスとする(乱数の範囲は0〜(配列のサイズ-1))
  • インデックスが指す値を配列の末尾の値と入れ替える
  • 乱数の範囲を1減らす
  • 乱数の範囲が0より大きい間、処理を繰り返す

JavaScriptによるサンプルは以下のようになります。

var value_list = new Array(10000);

// あらかじめ配列に値を入れておく
for (var i = 0; i < value_list.length; i++) {
    value_list[i] = i;
}

var range = value_list.length - 1;
do {
    // 乱数の値を取得し、配列のインデックスとする
    var index = ~~(Math.random() * range);

    // インデックスが指す値を配列の末尾の値と入れ替える
    var tmp = value_list[index];
    value_list[index] = value_list[range];
    value_list[range] = tmp;

    // 乱数の範囲を減らす
    range--;
} while (0 < range);  // 乱数の範囲が0より大きい間、処理を繰り返す

for (var i = 0; i < value_list.length; i++) {
    console.log(value_list[i]);
}

上記のサンプルを試してみます。配列の中身を一行毎出力しており、単に行数をカウントした値とsort,uniqで重複する値を除去した行数の値が同じであることから、重複しない値であることが分かります。動作環境はNetBSD-6.1-i386です。

$ node sample.js | wc -l
   10000
$ node sample.js | sort | uniq | wc -l
   10000

値もシャッフルされています。

$ node sample.js | head
2537
6218
7624
7580
692
4295
2508
6329
1150
4781

Pemtium M 1GHz,データの件数1万件の場合で0.4秒程度の処理時間です。

$ time (node sample.js 2>&1 > /dev/null)

real    0m0.499s
user    0m0.462s
sys     0m0.020s

$ cat /proc/cpuinfo
processor       : 0
vendor_id       : GenuineIntel
cpu family      : 6
model           : 9
model name      : Intel(R) Pentium(R) M processor 1000MHz
stepping        : 5
cpu MHz         : 996.80
fdiv_bug        : no
fpu             : yes
fpu_exception   : yes
cpuid level     : 2
wp              : yes
flags           : fpu vme de pse tsc msr mce cx8 apic sep mtrr pge mca cmov pat clflush dts acpi mmx fxsr sse sse2 tm

参考までに、取得した乱数値が重複していないか逐一確認する処理方法の場合と比較してみます。30秒程度かかっており、こちらはオススメできない方法となっています。

$ cat sample-bad.js
var value_list = new Array(10000);

for (var i = 0; i < value_list.length; i++) {
    var index;

    // 配列の値が初期値(-1)でない間繰り返す
    do {
        // 乱数の値を取得し、配列のインデックスとする
        index = ~~(Math.random() * value_list.length);
    } while (value_list.indexOf(index) != -1);

    value_list[i] = index;
}

for (var i = 0; i < value_list.length; i++) {
    console.log(value_list[i]);
}
$ time (node sample-bad.js 2>&1 > /dev/null)

real    0m31.960s
user    0m30.481s
sys     0m0.040s

HTML5 Canvasと画像サイズの関係

ごちうさパズルではピースの数を選択できるようにしています。そのため、画像の幅・高さと1ピースあたりの幅・高さが割りきれないことがあり、ピースを並べて行った結果、Canvasや画像のサイズをわずかにはみ出してしまうことがあります。

今回のケースで考えると、画像サイズは600x600で、パズルのピースはNxNとしており、49pcs(7x7)と81pcs(9x9)の場合に幅・高さが割りきれない値になります。当初、単純に四捨五入(Math.round())する方法をとったのですが、Firefoxでは動作するもSafariではおかしなピースが描画されるという、ブラウザの挙動の違いにハマってしまいました。

$ node
> 600/2
300
> 600/3
200
> 600/4
150
> 600/5
120
> 600/6
100
> 600/7
85.71428571428571
> 600/8
75
> 600/9
66.66666666666667

結果、割りきれないケースの場合は、扱う画像の範囲を少し小さく扱うことで対応しました。

> 600/9
66.66666666666667
> 66*9
594        /* 594pxを画像の幅・高さとする */

Canvas.strokeStyle()の設定

これは私がCanvasの仕様を把握できていなかっただけなのですが、Canvas.strokeStyle()などでストロークの色を変更すると、既に描画したストロークの色も一緒に変更されるようです(Firefoxでしか確認してないので、他のブラウザだと違うかもしれません)。描画したデータについても、内部的には状態を保持しているようです。

まとめ

ご注文はうさぎですか?第7羽のエピソードを元に「ごちうさパズル」を作ってみました。HTML Canvasまわりではブラウザ毎の挙動の微妙な違いにハマってしまいました。Canvasまわりは私の理解が追いついていないところもあり、もう少し調べてみようと思います。

第1回SoftLayer勉強会に参加してきました

第1回SoftLayer勉強会に参加してきました

第1回SoftLayer勉強会が開催されたので参加してきました。

勉強会の告知ページの写真がラウドパークを彷彿とさせる感じだったので、Tシャツにジーンズという風貌で参加したところ、ほとんどの参加者が背広!まるで衣替えの日に一人だけ冬服で登校した中学生のような気分になってしまいました...(クラウド系の勉強会は背広の人が多い傾向があるようです)。

以下は勉強会のメモですが、クラウドまわりの知識に疎いので私の理解に間違いがある可能性にご留意ください。

SoftLayer Introduction

  • 発表者は@urasakoさん
    • 今回の勉強会の企画を行った方
  • (まずそもそも)クラウドってなに?

  • SoftLayerについて

    • SoftLayerはIaaS(Cloud Infrastructure as a Service)を提供する
    • 米国、アジア、ヨーロッパ合わせて13のデータセンタがある
    • SoftLayerの利用形態
      • server
      • storage
        • Object Storage
          • OpenStack swiftベースのオブジェクトストレージを持っている
        • SAN(Storage Area Network)
        • NAS(Network Attached Storage)
        • CDN(Contents Delivery Network)
        • QuantaStor
    • SoftLayerのWebポータルサイト上で世界中のリージョンが見える
    • CDN単独の提供も可能
    • Automation & API
      • Auto-scaling機構はないけれどAPIで操作できる
  • SoftLayerに関する日本語の資料について

  • SoftLayerユーザ会について

    • 日本SoftLayerユーザ会(JSLUG)が発足!
    • 今後のSoftLayer関連の勉強会、イベント
      • SoftLayer勉強会 in Hokkkaido(2014/06/12)
      • SoftLayer Night Hands-on
        • 2014/06/20
        • 2014/06/24
        • 2014/07/01(予定)
        • 2014/08/01(予定)
      • JTF(06/22)で'Hands-on
      • 第2回SoftLayer勉強会(2014/07/25)

Email Delivery on Email

  • 発表者は@nakansukeさん
  • SoftLayerとSendGridの話
  • SendGridとは

    • SoftLayerとSendGridの関係
      • SendGridはSoftLayerで動いている
      • "Built on SOftLayer,"
    • 2011年6月にSoftLayerとSendGridはパートナーに
    • SendGridのVP ofProduct&MarketingがもとSoftLayer
    • Email Infurastracture as a Service(仮)
    • ヘッダを見るとSendGridから来ていることが分かる
    • 発表者はSendGridに関わるようになってから、届くメールヘッダを見る癖がついたとのこと
    • SoftLayerからメールを送るときは実質SendGrid一択!
      • 通数で料金が決まる
  • メールについて改めて復習

    • 日本語ではメールに依らないメッセージサービスが多いため、メールはオワコンと考える人が多いようだ
    • また、スパムのイメージも強い?
    • しかし、海外ではコミュニケーションツールの一つとして活用されている
      • 加えて、HTMLメールが良く利用される
        • 日本国内ではテキストメールがメイン
  • メールの到達性について

    • 約20%のメールは届かない
      • ISPのスパム対策で正常な配信が困難になる
      • メールサーバの設定だけでなく、「到達性を高める」取り組みも必要
      • 時にはインフラ面での対応も必要になる
        • 社内LANから(スパムの踏み台等で)外部に変なメールを出すのを事前に阻止する等
        • スパム送信PCを放置したままにすると、ISPブラックリスト入り→メールの正常な配信が困難という状況になる
  • 構造計画研究所について

SoftLayer x Bit-isle = ? Bit-isleが提供するハイブリッドクラウドソリューション

  • 発表者は成迫剛志さん

  • ビットアイル総合研究所

  • OpenStackに強く(ノウハウがある、という意味で)、所内の一定数の人にはOpenStackの研修を受けてもらっているとのこと

  • SoftLayerの色

    • SoftLayerのデータセンターではラックの配線をキレイに色分けしているという話
    • 緑色は管理ネットワーク(1本)
    • 青色はプライベートネットワーク(2本)
    • 赤はパブリックネットワーク(2本)
  • 5本×3種類のネットワーク構成になっている
  • ラックは最初にきっちり配置し、後から追加・変更しないため、配線がキレイに揃っている

  • SoftLayerのプライベートネットワーク活用例

    • ビットアイルのデータセンターとSoftLayer間のプライベートネットワークの活用例
    • ビットアイルデータセンター側にDBやioDriveなどの高速IOサーバーを用意し、SoftLayerとはBI Direct Accessで接続することでIOのレイテンシ低減

    • インターネットを介さない社内LAN/WANとの直接接続

      • WANのプライベートネットワークからビットアイルのデータセンターに接続し、そこからSoftLayerのプライベートネットワークに接続するような構成
      • セキュリティの観点から「インターネットは経由したくない」というケースに対応
      • 各拠点システムDBを集約してBI/データウェアハウスを構築
        • こちらもWANのプライベートネットワーク→ビットアイルのデータセンター→SoftLayerという構成
        • DBのリモートレプリケーション先をビットアイルのデータセンターにする
      • x86サーバとのハイブリッド構成
    • SoftLayerが提供するインターネットを介さないプライベートネットワークを活用する話
      • 国際回線費用の大幅な削減になるとのこと

LT:今さらでも聞きたいSoftLayer network〜VLANとVPNを何とかしたい〜

  • 発表者は新島智之さん
  • 利用者の観点からのSoftLayerネットワーク構成に関する話
  • SoftLayer上に最初のサーバを作成した段階で、パブリック/プライベートVLANが作成される
    • IPは利用者側では付けられない
    • パブリックVLANには119.x.45.74/29のサブネットが割り当てられる
    • プライベートVLANには10.x.158.2/26のサブネットが割り当てられる
  • サーバの数が増えてゆくと、自動的にサブネットが追加される
  • Portable IPを使うと、VLANで使えるサブネットを追加できる
    • 例えば、119.x.63.2/29(パブリックVLAN)、10.x.172.2/26(プライベートVLAN)のようなサブネットを追加できる
    • 追加したサブネットはAliasで設定する仕組みのため、別のサーバに移動できる(IPアドレスの割り当てを動的に変更できる)
  • VLAN間のルーティング
    • VLAN spanningという機能をONにすることで、VLAN間のルーティングが行えるようになる
    • 異なるデータセンターのVLAN間もルーティング可能
  • 複数VLANとの通信
    • Trank portを利用することで、複数のVLANと接続できる
    • 最初のVLANはnative VLANとして扱われ、追加したVLANはtag VLANとして扱われる

コマンドラインで始めるSoftLayer

  • 発表者は@lyumeiさん
  • RESTでSoftLayerを操作する話
  • curlでのREST API呼び出し例
    • SL_USERNAME,SL_API_KEYはあらかじめ環境変数として値を設定しておく
$ curl "https://${SL_USERNAME}:${SL_API_KEY}@api.softlayer.com/rest/v3/SoftLayer_Account.xml?objectMask=fitstName;lastName;id"

(以降にXMLが続く)

LT:ベアメタルサーバを作ってみた

  • (集中力が途切れてしまってメモを取らずに話を聞くだけになっていました...)

LT: Riak on SoftLayer

  • (こちらも話を聞くだけになっていました...)
  • 発表者は@monmondawaさん
  • 分散データベースriakの話

まとめ

第1回SoftLayer勉強会の参加メモをまとめてみました。SoftLayerって何?という状態で参加していたので、後から自分が読み返しても分かるようにメモをまとめるのが大変でした。初めて参加する勉強会には予習が必要だと痛感しました。SoftLayerは興味を惹かれるので、第2回も参加してみようと思います。

更新履歴

  • 「メールの到達性について」の項目で説明と逆の意味にとれる文章になっていたのを修正しました。(5/27)