2009年4月23日

Yahoo!みんなの検定

Yahoo!みんなの検定の受験機能APIの紹介

  • このエントリーをはてなブックマークに追加

Yahoo!みんなの検定ProjectのK.K.です。

3か月以上の間が空いてしまいましたが、みんなの検定のAPIで【「三国志」に関する検定を表示し、受験する】機能の最後の仕上げを紹介します。

前々回検定リストAPI前回検定詳細APIを使いました。
今回は「検定受験API」を使ってみましょう。
この検定受験APIでは、以下の3種のパラメータが必要です。

  • cert_id(検定ID)
  • qid(各問題IDをコンマ区切りでつなげたもの)
  • answer(選んだ選択肢の番号をコンマ区切りでつなげたもの)

これらを送信することで合否の判定や評価メッセージを返すことが出来ます。

では最初に、問題IDとユーザーの解答を送信するための受験フォームを作成しましょう。
前回は「三国志」のキーワードを持つ最新の検定のなかから、
ランダムで1問取得しましたが、今回はその検定の受験結果を得るため全問取得します。
前回のサンプルのソースの、検定詳細APIのパラメータの「order_number」に0を指定すれば、
すべての問題の情報を取得できます。

require_once "XML/Unserializer.php"; 

	// みんなの検定APIの基本URL
	define( "API_BASE_URL", "http://cert.yahooapis.jp/MinnaCertWebService/V1/" );

	// APP_ID
	define( "APP_ID", "※{あなたのAPP_ID}" );

	// 指定するキーワード
	define( "KEYWORD", "三国志" );

	// 検定一覧APIのURL(order=1:公開日の降順 amount=1:1件取得)
	define( "LIST_API_URL", 	API_BASE_URL . "certList?appid=" . APP_ID . "&order=1&amount=1&keyword=" . rawurlencode( KEYWORD ) );

	// 検定詳細APIのURL(get_q=2:問題情報+正解と解説を取得 order_number=0:すべての問題情報取得)
	define( "DETAIL_API_URL", 	API_BASE_URL . "certDetail?appid=" . APP_ID 
								. "&get_q=2&order_number=0&cert_id=" );

	/* 
	 *
	 * XMLのパース
	 *
	*/

	// XMLパース用クラス作成
	$class_xml_uns = &new XML_Unserializer( array( 'parseAttributes' => true ) );

	// 検定一覧XMLのパース実行
	$class_xml_uns->unserialize( file_get_contents( LIST_API_URL ) );

	// パース結果を配列に格納
	$res_list	= $class_xml_uns->getUnserializedData();
取得した情報をもとに、ユーザーが各問題の答えをラジオボタンで選択、
採点ボタンを押すことで結果ページへ遷移するようにします。
/* 
	 *
	 * 検定の各情報を抽出
	 *
	*/
	
	// 検定の詳細を取得
	$ary_cert = $res_list[ "Result" ];

	// 検定ID抽出
	$cert_id	= $ary_cert[ "CertId" ];

	// 検定名抽出
	$cert_name 	= mb_convert_encoding( $ary_cert[ "CertName" ], "EUC-JP", "UTF-8" );

	// 検定概要抽出
	$cert_overview 	= mb_convert_encoding( $ary_cert[ "CertOverview" ], "EUC-JP", "UTF-8" );

	// 検定のURLを抽出
	$cert_url = $ary_cert[ "CertDetailPcUrl" ];

	// 抽出したIDで指定した検定の詳細XMLのパース実行
	$class_xml_uns->unserialize( file_get_contents( DETAIL_API_URL . $cert_id ) );

	// パース結果を配列に格納
	$res_detail = $class_xml_uns->getUnserializedData();

	// 問題部分のHTML
	$question_html = "";

	// 送信するパラメータ配列に使用するカウンタ
	$i = 0;

	// 各問題の情報抽出
	foreach( $res_detail[ "Result" ][ "QuestionResult" ][ "QuestionData" ] as $ary_detail ){
		
		// 何問目かを抽出
		$order_number = $ary_detail[ "OrderNumber" ];

		// 問題文抽出
		$question_text 	= mb_convert_encoding( $ary_detail[ "QuestionText" ], "EUCJP-WIN", "UTF-8" );
		$question_text 	= str_replace( "\n" ,"<br>", $question_text );

		// 問題IDを抽出
		$question_id = $ary_detail[ "QuestionId" ];

		// 問題文をHTMLに付加。
		// チェック先で必要になるのでhiddenのvalueとして問題IDを付加
		$question_html .= <<<_HTML_
<hr>
第${order_number}問:<br>
${question_text}
<input type="hidden" name="qid[${i}]" value="${question_id}">
<br>
<br>
_HTML_;

		// 選択肢抽出
		foreach( $ary_detail[ "ChoicesResult" ][ "ChoiceData" ] as $ary_choice ){

			// 選択肢番号
			$choice_number 	= $ary_choice[ "OrderNumber" ];

			// 選択肢本文
			$choice_text 	= mb_convert_encoding( $ary_choice[ "ChoiceText" ], "EUCJP-WIN", "UTF-8" );

			// 選択肢番号をvalueに持つラジオボタン付加
			$question_html .= <<<_HTML_

<input type="radio" name="answer[${i}]" value="${choice_number}">$choice_text
<br>
_HTML_;

		}
		$i++;
	}

	/* 
	 *
	 * HTML部分作成
	 *
	 * 採点ボタンを押すことで、 
	 * チェック用ページへ選択した答をPOSTする
	 *
	*/

	// 問題部分のHTMLを作成。hiddenで検定IDを付加
	$question_html = <<<_HTML_
${cert_name}<br><br>
${cert_overview}
<form action="check.php" method="POST">
<input type="hidden" name="cert_id" value="${cert_id}">
<br>
${question_html}
<hr>
<input type="submit" value="採点">
</form>
_HTML_;

?>
<html>
	<head>
		<meta http-equiv="content-type" content="text/html;charset=utf-8">
		<title>受験サンプル</title>
	</head>
	<body>
	<?php echo $question_html ?>
	</body>
</html>
このサンプルを実行すると、その検定のすべての問題がずらっと表示されます。
続いて、このサンプルの採点ボタンを押した際に遷移するチェック用ページを作成します。
require_once "XML/Unserializer.php"; 

	// みんなの検定APIの基本URL
	define( "API_BASE_URL", "http://cert.yahooapis.jp/MinnaCertWebService/V1/" );

	// APP_ID
	define( "APP_ID", "※{あなたのAPP_ID}" );

	// 受験APIのURL
	define( "EXAM_API_URL", 	API_BASE_URL . "certExam?appid=" . APP_ID . "&cert_id=" );

	/* 
	 *
	 * POSTされたパラメータの取得
	 *
	*/
	
	// 検定ID
	$cert_id = $_REQUEST[ "cert_id" ];

	// 問題ID配列
	$ary_qid = $_REQUEST[ "qid" ];
	$qid = implode( ",", $ary_qid );	// 配列をカンマ区切りで連結して文字列に変換

	// 解答配列
	$ary_answer = $_REQUEST[ "answer" ];
	$answer = implode( ",", $ary_answer );	// 配列をカンマ区切りで連結して文字列に変換


	/* 
	 *
	 * XMLのパース
	 *
	*/

	// XMLパース用クラス作成
	$class_xml_uns = &new XML_Unserializer( array( 'parseAttributes' => true ) );

	// 取得したパラメータをもとにXMLのパース実行
	$class_xml_uns->unserialize( file_get_contents( EXAM_API_URL . $cert_id . 
							"&qid=" . $qid . "&answer=" . $answer ) );
先ほど作成した受験サンプルから送られてきたパラメータを成形して、検定受験APIのXMLをパースします。
あとは、帰ってきた結果を表示するだけです。
各問題の正誤や解説なども取得できるのですが、今回はシンプルに合否の判定と評価のメッセージなどを表示するだけにしておきます。
/* 
	 *
	 * 受験結果の情報を抽出
	 *
	*/

	// パース結果を配列に格納
	$res_exam = $class_xml_uns->getUnserializedData();

	// 検定名
	$cert_name = mb_convert_encoding( $res_exam[ "Result" ][ "CertName" ], "EUC-JP", "UTF-8" );

	// 合否(0:不合格 1:合格 NULL:合否の無い検定)
	$passing = "";
	switch ( $res_exam[ "Result" ][ "EvalResult" ][ "Passing" ] ) {
		case 0:
			$passing = "不合格";
			break;
		case 1:
			$passing = "合格";
			break;
		default:
			$passing = "※この検定には合否はありません。";
			break;
	}

	/*
	 *
	 * 以下の評価部分は出題者が設定していない場合あり
	 *
	*/

	// 評価の説明(あなたの○○に関する知識は?など)
	$eval_axis = mb_convert_encoding( $res_exam[ "Result" ][ "EvalResult" ][ "EvalAxis" ], "EUC-JP", "UTF-8" );
	
	// 評価タイトル(■■級!など)
	$eval_title = mb_convert_encoding( $res_exam[ "Result" ][ "EvalResult" ][ "EvalTitle" ], "EUC-JP", "UTF-8" );

	// 評価メッセージ(得た評価の詳しい説明)
	$eval_message = mb_convert_encoding( $res_exam[ "Result" ][ "EvalResult" ][ "EvalMessage" ], "EUC-JP", "UTF-8" );
	$eval_message = str_replace( "\n" ,"<br>", $eval_message );

	/* 
	 *
	 * HTML部分作成
	 *
	*/
	$result_html = <<<_HTML_
${cert_name}<br>
<b>${passing}</b>
<hr>
${eval_axis}<br>
<b>${eval_title}</b><br><br>
${eval_message}
_HTML_;
	
?>
<html>
	<head>
		<meta http-equiv="content-type" content="text/html;charset=utf-8">
		<title>結果サンプル</title>
	</head>
	<body>
	<?php echo $result_html ?>
	</body>
</html>

これで、その検定の受験結果を判定できます。
検定を探す、受験する、結果をみるという一連の流れがみんなの検定APIで可能となるのです。

これらのAPIを使って、パズルゲームを作成された方もいらっしゃいました。

http://as.crap.jp/KenteiPuzzle.html

受験機能とパズルを組み合わせるという発想が面白かったです。

このように、さまざまなものが作れると思いますのでぜひ挑戦してみてください。


Yahoo!デベロッパーネットワーク - みんなの検定 - 検定リストAPI
受けて作ってつながろう!Yahoo!みんなの検定

Yahoo! JAPANでは情報技術を駆使して人々や社会の課題を一緒に解決していける方を募集しています。詳しくは採用情報をご覧ください。

  • このエントリーをはてなブックマークに追加