monoの開発ブログ

Puroland Greetingの設計と実装

いつの間にかオープンソースにしていたPuroland Greetingのシステムについて解説します。

構成

本システムは、クローラとWebサーバの2つのプログラムから構成されています。クローラは、サンリオピューロランドの公式サイトからグリーティング情報を取得し、データベースに格納します。Webサーバは、ユーザからのリクエストに応じてデータベース内の情報を表示します。

テーブル構成

データベースのテーブル構成は以下のER図のようになっています。なお、ここでは本質的ではないいくつかのカラムは省略しています。

ER図

schedulesは、複数回のグリーティングを束ねた1日のスケジュールを表現するためのテーブルです。1行が1日に対応しています。

greetingsは、グリーティングを表現するテーブルです。本システムでは、開始時刻、終了時刻、場所の3要素が一致する複数のキャラクターの登場を1つのグリーティングとして扱います。Webページの下図のような枠1つが1行に対応すると考えるとわかりやすいかもしれません。

グリーティング

appearancesは、greetingscharactersを結ぶための中間テーブルで、キャラクターの登場を表現しています。

characterscostumesplacesは、それぞれキャラクター、衣装、場所を表現するテーブルです。キャラクター、場所については特に説明は不要かと思います。衣装というのは、キャラクター名の後ろに括弧書きで記述された内容 (ハロウィンなど) のことを意味しています。

クロール

解説は必要ないと思われるので省略。ちなみに、クローラのUser-AgentはiPhone (Ruby; http://greeting.sucretown.net/)です。

情報の表示

本システムで一番使われている /schedule/yyyy/mm/dd/ のタイムテーブル表示について解説します。といっても、本システムの要であるレスポンシブデザインはBootstrapが実現してくれているものなので、ここではHTMLの組み立て方とJavaScriptの処理概要について述べます。

HTMLの組み立て

HTML生成の流れは以下のとおりです。これはあくまで概念的なものなので、実際の処理順序とは異なります。

  1. 対象となる日のすべてのgreetingを取り出す
  2. 開始時刻と終了時刻の組でグルーピングを行い、greeting-groupを作る
  3. greeting-groupを開催中 (開始時刻が現在時刻以降かつ終了時刻が現在時刻以前)、開始前 (開始時刻が現在時刻より後)、終了 (終了時刻が現在時刻より前) の3種類のgreeting-categoryに分類する
  4. greeting-category内のgreeting-groupを終了時刻順で並び替える (終了時刻が同じ場合は開始時刻順)
  5. greeting-categoryおよびgreeting-groupについて順にHMTLを生成していく

最終的に出力されるHTMLのグリーティング情報部分は以下の図のような構造です。図中の緑の部分は最終的なレンダリング結果として描画される部分で、破線部分は実際には表示されません。

DOM構造

PCだと同じ時間のグリーティングが横に並び、スマホでは縦に並ぶ機能は、BootstrapのGrid systemによって実現しています。

HTML (の元になるHamlテンプレート) はviewsディレクトリ、CSS (の元になるSCSS) はassets/stylesheetsディレクトリにあります。Hamlで書かれているので理解しづらいかもしれませんが、タグで囲む代わりにインデントで階層構造を表現しているだけで、複雑なものではありません。上の図や実際に動いているシステムのHTMLと見比べると若干わかりやくなると思います。

JavaScript

本システムのJavaScriptは、主にgreeting-categoryの更新を行っています。具体的には、毎分各greeting-categoryの開始時刻と終了時刻 (それぞれdata-start-at属性とdata-end-at属性) をチェックし、現状から変化する場合には適切なgreeting-category内に配置し直します。この処理はassets/javascripts/greetings.jsに記述されています。