(BACK)

CGIを利用したランキング作成方法

06/5/4 ランキングCGIver5公開、その他書き直し
CGIとデータをやりとりする事で、ランキングのようなものを作成可能である。
ここでは、サンプルを用いて「とりあえずの機能の有るランキングシステム」を作る事を解説する。

しかし、CGIを扱う以上、CGIの事を全く知らないと無理があるので、フリーで配布されているCGI(掲示板など)を自分で設置出来る程度には知識が必要である。

サンプルファイル.lzh (ver 2)
中身>
ranking.cgi … ランキングCGIスクリプト
ranking.dat … ランキング用データファイルのサンプル
jcode.pl … 日本語文字コード変換ライブラリ

→上位バージョンのCGI


サンプルファイルをダウンロードし、以下の手順に従って準備する。
1.CGIファイルの準備
ranking.cgiをテキストエディタで開く。
perlのパスを確認し、必要ならば書きかえる。
「設定部」の項目を必要ならば書きかえる。
チェック用パスワードは必ずわかりにくい文字列を設定し、覚えておくこと。後ほど使う。
2.データファイルの準備
ranking.datをテキストエディタで開く。
name1=1位の名前&score1=1位の得点&……
というように並んでいるので、ランキングの最初の状態を作成する。
「&」の位置を間違えないこと。改行しないこと。名前には全角文字を使ってもよい。


ここからは、paraflaでの作業である。
「何が書いてあるかわからん」というレベルの人はASの勉強が先である。
3.前準備
親イベントの最初に、次のフレームアクションを入れる。
System.useCodepage = true;
cgifile = "ranking.cgi";
datafile = "ranking.dat";
cgifileとは、ランキングCGIのファイル名である。
通常このままで良いが、その場合は、ローカルでflashを実行した時に、ランキングへの登録が出来ない。
「http://〜/ranking.cgi」のようにフルパスで記述すると、ローカルでの実行時もランキングへの登録が出来るようになる。
datafileとは、データファイルのファイル名である。
通常このままで良いが、その場合は、ローカルでflashを実行した時に、ランキングの参照が出来ない。
「http://〜/ranking.dat」のようにフルパスで記述すると、ローカルでの実行時もランキングの参照が出来るようになる。
4.ランキング表示処理の作成
データの登録ではなく、単にランキングデータを読み込み、表示する処理を作成する。
ランキング表示をしたい箇所に、以下のようにイベントを作成する。
なお、これは親イベントに書く事が前提になっている。

・何も入っていない、空のスプライト(読み込み用スプライト)を作成し、表示する。
 適当なインスタンス名をつけ(ここではsprとする)、それに以下のクリップアクションをつける。
onClipEvent(load){

	this.loadVariables(_root.datafile + "?" + random(60000));

}
-
onClipEvent(data){

	_root.play();

}
・「アクション:停止」

これにより、親イベントを停止させてからランキングデータを読み込み、それが完了したら親イベントを「停止」された場所から再生させる、という事になる。

読み込みに成功していれば、スプライトの中の変数に、以下のようにデータが入っている。あとはこれらをテキストで表示すればよい。
読み込み用スプライトのインスタンス名が「spr」である場合
spr.name1 = 1位の名前
spr.score1 = 1位の得点
spr.name2 = 2位の名前
spr.score2 = 2位の得点
spr.name3 = 3位の名前
spr.score3 = 3位の得点
spr.name4 = 4位の名前
spr.score4 = 4位の得点
spr.name5 = 5位の名前
spr.score5 = 5位の得点

なんらかの原因で読み込みに失敗した場合は、いつまで経っても「停止」したままになる。
成功失敗に関わらず、「先に進むボタン」をあらかじめ置いておく等の工夫が必要である。
テキストで「この表示のまま止まったら読み込み失敗」と表示してから読み込むのも安易でよい。

用が済んだら読み込み用スプライトは消しておくこと。
5.名前の入力
ランキングに登録するために、プレイヤーに名前を入力してもらう必要がある。
テキストの入力窓は、テキスト機能で簡単に実現可能である。

テキストを作成し、このように設定する。
フォントは、デバイスフォントを使用すること。
このテキストを表示している間、入力窓への入力が可能である。
「幅」と「高さ」は、入力窓の大きさである。必要に応じて変更すること。
変更した内容は常に、変数myname に入っているので、これをプレイヤーの名前として扱う。
mynameにあらかじめ文字が入っていれば、それが最初の状態の名前になる。
6.ランキング登録処理の作成
ランキングに登録する処理を作成する。
ランキング登録をしたい箇所に、以下のようにイベントを作成する。
なお、これは親イベントに書く事が前提になっている。

・何も入っていない、空のスプライト(登録用スプライト)を作成し、表示する。
 適当なインスタンス名をつけ(ここではsprとする)、それに以下のクリップアクションをつける。
onClipEvent(load){

	name = 登録する名前 ;
	name = name.substr(0,10); // 10は名前の最大文字数
	score = 登録する得点 ;
	pass = "チェック用パスワード" ;

	this.loadVariables(_root.cgifile + "?" + random(60000),"POST");

}
-
onClipEvent(data){

	_root.play();

}
・「アクション:停止」
チェック用パスワードは、CGIファイルのほうに設定した文字列を同じように書く。1文字でも違っていてはならない。

これにより、親イベントを停止させてからランキングの登録を試み、それが完了したら親イベントを「停止」された場所から再生させる、という事になる。

CGIへのアクセスに成功していれば、スプライトの中のresultという変数に、以下のような意味を持つ数字が入っている。
状況に応じて表示や判断に使うとよい。
変数 spr.resultに返される値
# 0   : 予期しないエラー
# 1~5 : 1位~5位に登録された(データファイルは更新された)
# 6   : ランク外だった
# -1  : データファイルが見つからなかったので中止した
# -2  : データファイルの内容がおかしいので中止した
# -3  : CGIに渡したデータがおかしい(名前が無いか、得点が0)ので中止した
# -4  : 通信パスワードが違うので中止した

なんらかの原因でアクセスに失敗した場合は、いつまで経っても「停止」したままになる。
成功失敗に関わらず、「先に進むボタン」をあらかじめ置いておく等の工夫が必要である。
テキストで「この表示のまま止まったら読み込み失敗」と表示してから読み込むのも安易でよい。

用が済んだら登録用スプライトは消しておくこと。
7.アップロード
全てが準備出来たら、以下の5つのファイルを同じ場所にアップロードし、完成となる。
カッコ内は設定するパーミッションである。
再生用.html
フラッシュ.swf
ranking.cgi (755)
ranking.dat (666)
jcode.pl

ranking.cgi と ranking.dat と jcode.pl はアスキー転送すること。
8.うまくいかない時
まず、設置したCGIのファイルに、ブラウザから直接アクセスしてみること。
「result=-4」と表示されたら、CGIの設定はおそらくOKである。flashのほうの設定などを見直すこと。
何も表示されない場合は、下の3を参照。
エラー500が出た場合は、CGIファイルに何か間違いがある。よくわからなければサンプルファイルの最初の状態から作業し直すこと。

1.チェック用パスワードは合っている筈だが、result=-4になる
チェック用パスワードを半角英数字だけで構成すること。

2.何故かresult=-3になる
登録しようとした得点が0か、名前が無い時にはそうなる。
登録する前にチェックすること。

3.通信には成功しているらしいが、resultに何も入っていない
サーバーによっては「Content-type: text/html」が使えないようである。(infoseekなど)
ranking.cgiの25行付近にある以下の記述
print "Content-type: text/html;charset=Shift_JIS \n\n";
を、以下のように書きかえること。
print "Content-type: \n\n";

4.サーバーの都合で、swfファイルとcgiファイルを同じ場所に置けない(infoseek、@niftyなど)
cgifile,datafileをフルパスで書けばいいが、この場合はローカルからランキングへの参加が可能になる。
それが困る場合は、相対パスで記述する。
swfファイルのフルパス
http://pricure.co.jp/black/game.swf

cgiファイルのフルパス
http://pricure.co.jp/cgi-bin/ranking.cgi

この場合、flashのほうに設定するcgifileは
cgifile = "../cgi-bin/ranking.cgi";

または、ローカルで実行されているか、サーバー上で実行されているかを判断してからアクセスする。
この場合、cgiflie,datafile の記述はフルパスで書いてよい。
// _url という変数には、そのswfが実行されている場所が入っている。
// 頭の数文字でローカルかサーバーか判断できる。

//ローカル(PC上)での実行時
_url = "file://〜〜〜〜〜.swf";

//サーバー(ネット上)での実行時
_url = "http://〜〜〜〜〜.swf";

なお、ranking.cgi ranking.dat jcode.plの3つをcgi用のディレクトリに置くこと。

上位バージョン
以下は、ここまでの説明を完全に理解した上で、自己責任で使うこと。

ranking.cgi(ver5)

ver3→ver4の変更点

同名排他機能を付加。
 同名排他を有効にすると、ランキングの中で同じ名前が複数載らないようになる。
 自分の得点以下により登録されなかった場合も、ランク外の扱いとなる。

・記録数を変更可能。
 初期値では5であり、これは1~5位までを記録する事を示す。
 これを好きな数に変更可能。
 取得される変数はこれまでと同様、name9,name10…name99,name100… という名前になる。

・データファイルに、全てを1つの変数にまとめたデータ(集合データ)を付記。
 データファイルを読み込んだ時に、変数ardataに読み込まれる。
 使い方が判るならばこちらのほうが処理がし易い。

集合データ(ardata)は、以下の形式の文字列変数である。
ardata=1位名前,1位得点:2位名前,2位得点:3位名前,3位得点:
このように、まず順位ごとに半角コロン(:)で区切られ、
さらにその中で、半角カンマ(,)で区切られている。
まず「:」でsplitしてから、各データを「,」でsplitする事でデータを取り出せる。
最後の「:」がひとつ余分に有る事に注意。
名前などに、区切り文字が混ざらないように注意する必要がある。

なお、cgiは集合データを読み込まないので、ランキングの初期状態を集合データで記述する事は出来ない。また、その際には集合データは記述しなくてよい。

ランク外だった時のresultの値が、-5に変更された。
 これにより、resultに返る値は以下のように修正される。
# 0   : 予期しないエラー
# 1~n : 1位~n位に登録された(データファイルは更新された)
# -1  : データファイルが見つからなかったので中止した
# -2  : データファイルの内容がおかしいので中止した
# -3  : CGIに渡したデータがおかしい(名前が無いか、得点が0)ので中止した
# -4  : 通信パスワードが違うので中止した
# -5  : ランク外だった

ver4→ver5の変更点

・名前を「/」で区切った最初のデータだけが、同名排他の判断に使われるようになった。
(後述の複数のデータを登録するヒント参照)
例えば、複数のデータを混ぜて、
name = "なぎさ/北海道/14";
という名前で登録する時、
同盟排他の判断に使われるのは「/」で区切った最初の要素である
"なぎさ"
この部分だけとなる。

従って、
name = "なぎさ/北海道/14";
name = "なぎさ/青森/15";
name = "なぎさ/沖縄/16";
これらは全て、名前としては違うものであるが、同名排他の判断の際には同名として扱われる。

・データファイル構築モード
cgiファイルのURLが
〜〜〜〜〜/ranking.cgi
であり、通信パスワードが
black
である場合、ブラウザから
〜〜〜〜〜/ranking.cgi?black
というURLにアクセスすると、データファイルを読みこんで、そのまま書くというだけの動作を行う。
集合データardataが作成されるので、これが必要な時に使う。

複数のデータを登録するヒント
名前、得点の他にもデータを登録したい場合は、それら全てを名前に混ぜて登録すればよい。

例えば、名前の他に「出身地」「年齢」も登録したい場合、
登録する名前=名前/出身地/年齢
というように、何かの区切り文字(「/」を推奨)で区切って並べたデータにする。
実際には以下のように書く。
name = "NAGISA/北海道/14";

ランキングで扱う「名前」としてはこのまま扱われるので、
表示する前に、区切り文字でsplitし、データを切り取ればよい。
name1 = "NAGISA/北海道/14"; //こういう中身である場合…
 
datas = name1.split("/"); //こうすれば
 
datas[0] = "NAGISA"; //分割されてこのような中身になる
datas[1] = "北海道";
datas[2] = "14";

一応残しておく
ranking.cgi(ver3)
ranking.cgi(ver4)

by D4U