幻想水滸伝シリーズの108星検索システムを題材にしたWebアプリケーション開発

※昔の記事なのでいろいろひどい(日本語カラム名とか)ですが、これも歴史であるので残しておきます

題名がえらいことになっていますが内容は極めて基本的でシンプルなものです。

「幻想水滸伝」シリーズには各タイトルごとに108星の宿星を纏った108人のキャラが(最低でも)出てきます。タイトルにして現在までに7作出ていますので、実にデータしてキャラ数は108人×7作=756人分あるわけです。ここまでデータ量が肥大化すると効率的に管理、検索するシステムが欲しくなりますし、実際作れますので作ってみました。以下はその詳細になります。

1.まずはデータの収集と作成

とにかく一にも二にもデータそのものがないと話になりません。宿星名とそれに対応した7作分のキャラクタ名を所定のフォーマットで作成する必要があります。作成にあたっては「攻略!幻想水滸伝」様と「KINGDOM HEARTS GUIDELINE」様のページを用いさせて頂きました。本当に感謝です。


http://www.kh-guideline.org/

データの編集には普通にExcelを用いました。フィールド数は8(「宿星」というフィールドと、7作分のタイトル名のフィールド)です。ロー数は109(ヘッダ+108星分)になります。
f:id:gregminster:20140928164505p:plain

Excelでデータが作成できたらCSVで書き出します。CSVで書き出したデータをエディタで確認、微調整をします。
f:id:gregminster:20140928164643p:plain

ExcelからのCSV書き出しはシフトJISで書き出されて一部の文字(「天罡星」など)が正しく表示されませんので、UTF8で保存し直し、文字も正しく書き換えます。余分なカンマも削除して整形をします。
f:id:gregminster:20140928164929p:plain

これでデータは完成です。

2.データベースにデータをインポートする

できたCSVファイルをデータベースにインポートします。RDBMSの違いによりいろいろ手段はありますが、ここではphpMyAdmin経由でMySQLにインポートをします。

まずはデータベースを作成し、続いてテーブルを作成します。ここではデータベース「suikoden」内に、テーブル「stars_name」を作成しています。
f:id:gregminster:20140928165429p:plain
f:id:gregminster:20140928165608p:plain

テーブルが作成できたらフィールドを定義しましょう(下記画像はミスでTKが漏れていますが、後から追加しました)
f:id:gregminster:20140928165853p:plain

フィールド定義が正しく行われたかを確認します。
f:id:gregminster:20140928170639p:plain

フィールドを定義したらCSVファイルをインポートします。1行目はヘッダなので2行目から読み込むように設定をしましょう。
f:id:gregminster:20140928170235p:plain
f:id:gregminster:20140928170352p:plain

CSVファイルが正しくインポートされたかを確認します。ここで文字化けをする場合が非常に多いです。文字化けをした場合はMySQLやphpMyAdminの文字コードの設定を見直しましょう。
f:id:gregminster:20140928170918p:plain

インポート完了です。

3.Webページを作る

いよいよ表示するためにWebページを作ります。ここではPHPを用いていますがもちろん言語は何でも構いません。というか私もPHPはあまり使わないので以下のコードには稚拙なところが多々見られると思いますがそこは勘弁して下さい。

まずはとにかくデータベースの内容を単に表示するだけのコードです。

<?php
// もろもろ
$connect = mysql_connect("サーバアドレス", "ユーザ名","パスワード");
mysql_select_db("suikoden", $connect);
$query = mysql_query("SELECT * FROM stars_name;");
for ($i = 0; $i < mysql_num_fields($query); $i++){
	$column_name[$i] = mysql_fetch_field($query, $i);
}

// カラム名(フィールド名)表示
echo "<table border='1'>";
echo "<tr>";
for ($i = 0; $i < mysql_num_fields($query); $i++){
	echo "<td>" . $column_name[$i]->name;
	echo "</td>";
}
echo "</tr>";

// 中身の表示
while ($data = mysql_fetch_array($query)){
	echo "<tr>";
	for ($i = 0; $i < mysql_num_fields($query); $i++){
		echo "<td>" . $data[$i];
		echo "</td>";
	}
	echo "</tr>";
}
echo "</table>";
?>

表示イメージは以下のようになります。
f:id:gregminster:20140928171755p:plain

次に、「タイトル名」と「宿星名」をキーにして、対応するキャラクターを検索するためのソースです。「タイトル名」をコンボボックス内に表示するにあたり、7個(7作)と少ないこともあり強引に手書きで表示させていますが、ここは本来はDBから値を取得してループで回したほうがいいでしょう。

<?php
// もろもろ
$connect = mysql_connect("サーバアドレス", "ユーザ名","パスワード");
mysql_select_db("suikoden", $connect);
$query = mysql_query("SELECT * FROM stars_name;");
for ($i = 0; $i < mysql_num_fields($query); $i++) {
	$column_name[$i] = mysql_fetch_field($query, $i);
}
$query_star_name_getter = mysql_query("SELECT 宿星 FROM stars_name");
$i = 0;
while ($tmp = mysql_fetch_row($query_star_name_getter)){
	$star_name[$i] = $tmp[0];
	$i++;
}
?>

<form action="108_2_result.php" method="POST">

<p>
<select name="title_name" size="7">
<option value="幻想水滸伝" selected="selected">幻想水滸伝</option>
<option value="幻想水滸伝II">幻想水滸伝II</option>
<option value="幻想水滸伝III">幻想水滸伝III</option>
<option value="幻想水滸伝IV">幻想水滸伝IV</option>
<option value="幻想水滸伝V">幻想水滸伝V</option>
<option value="幻想水滸伝ティアクライス">幻想水滸伝ティアクライス</option>
<option value="幻想水滸伝 紡がれし百年の時">幻想水滸伝 紡がれし百年の時</option>
</select>
</p>

<p>
<select name="star_name" size="20">
<?php
echo '<option value="' . $star_name[0] . '" selected="selected">' . $star_name[0]	 .'</option>';
$i = 1;
while ($star_name[$i]) {
	echo '<option value="' . $star_name[$i] . '">' . $star_name[$i]	 .'</option>';
	$i++;
}
?>
</select>
</p>

<p>
<input type="submit" name="submit" value="われらにしょうりを!">
</p>

</form>

表示イメージは次のようになります。
f:id:gregminster:20140928172544p:plain

この検索に対して検索結果を表示しましょう。以下のようになります。POSTされた文字列の処理がまどろっこしいのはXSSを防ぐことを明示的にしたいがためです。

<?php
$connect = mysql_connect("サーバアドレス", "ユーザ名","パスワード");
mysql_select_db("suikoden", $connect);
$print_title_name = htmlspecialchars($_POST['title_name']);
$print_star_name = htmlspecialchars($_POST['star_name']);
$q = 'SELECT `' . $_POST['title_name'] . '` FROM stars_name WHERE 宿星 = "' . $_POST['star_name'] . '"';
$query = mysql_query($q);
$result = mysql_fetch_row($query);

echo '<b>' . $print_title_name . '</b>';
echo ' の ';
echo '<b>' . $print_star_name . '</b>';
echo ' は ';
echo '<b>' . $result[0] . '</b> です。';
?>

検索結果のイメージは次のようになります。ちょっと余計なものを入れてます。
f:id:gregminster:20140928173342p:plain

4.メンテナンスをする

最低限の実装はできました。さらなるステップアップのために新しい機能を追加してみたいところですね。

せっかくDBにデータが蓄積されているのでそれを活用しない手はありません。様々な機能の組み合わせでもっと複雑なこともできるはずです。まずはアイデア出しからですが(実はそこが結構難しい)、そのアイデアを具現化することができれば色々な可能性がひらけると思います。

われらにしょうりを!

Powered by はてなブログ