一站到底
《一站到底》是一个益智答题类节目。趣味十足,在挑战中挖掘个性。
实现方案
首先,我们需要有一个题库,用户答题的内容均从题库中获取。
该题库SQL语句如下:
--
-- 表的结构 `questions`
--
DROP TABLE IF EXISTS `questions`;
CREATE TABLE IF NOT EXISTS `questions` (
`id` int(5) NOT NULL AUTO_INCREMENT,
`figure` varchar(1) DEFAULT NULL,
`types` varchar(1) DEFAULT NULL,
`question` varchar(255) DEFAULT NULL,
`numbers` int(1) DEFAULT NULL,
`optionA` varchar(50) DEFAULT NULL,
`optionB` varchar(60) DEFAULT NULL,
`optionC` varchar(60) DEFAULT NULL,
`optionD` varchar(60) DEFAULT NULL,
`optionE` varchar(60) DEFAULT NULL,
`optionF` varchar(30) DEFAULT NULL,
`answer` varchar(6) DEFAULT NULL,
`classify` varchar(4) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM;
id:表示题目的序号
question:为题目的内容
aoptionA-optionF: 表示该题可选择的答案有A到F 六个选项,但不是每一个题目都有这么多选项,大多数为4个,所以允许答案为空
answer:为该题的正确答案
然后,需要有一个保存用户答案记录的表,以便为用户的答案情况记录分数等情况。
记录表结构如下
--
-- 表的结构 `record`
--
DROP TABLE IF EXISTS `record`;
CREATE TABLE IF NOT EXISTS `record` (
`openid` varchar(28) NOT NULL COMMENT '微信ID',
`question` int(5) DEFAULT '-1' COMMENT '答题偏移',
`question_y` int(5) DEFAULT '0' COMMENT '答题正确',
`question_n` int(5) DEFAULT '0' COMMENT '答题错误',
PRIMARY KEY (`openid`)
) ENGINE=MyISAM;
开发实现:
首先,当我们接收到用户发过来的文字消息的时候,判断是否是答案有关的输入,这里使用 “答题”作为进入答题开始的指令,使用A到F共6个字母(不区分大小写)作为答案的输入指令。
private function receiveText($object)
{
$keyword = trim($object->Content);
//判断用户输入是否为“答题”,并使用正则表达式判断字母范围
if ($keyword == "答题" || preg_match("/^[A-Fa-f]$/", $keyword)){
include("question.php");
//将字母强制转换成了小写
$content = getQuestionInfo($object->FromUserName, (($keyword == "答题")?$keyword:strtoupper(trim($object->Content))));
}
$result = $this->transmitText($object, $content);
return $result;
}
答题部分的程序实现如下:
question.php整体代码
<?php
// var_dump(getQuestionInfo("ollB4jtmI_i8CqYlj-QMiuxx", "A"));
function getQuestionInfo($openid, $answer)
{
$dbname = "app_dq095";
$host = "w.rdc.sae.sina.com.cn";
$port = "3306";
$user = "4k514n103z";
$pwd = "2402314li2j1i5im1xy2xizj5y332w2x41k2z203";
/*接着调用mysql_connect()连接服务器*/
$db = mysql_connect($host,$user,$pwd);
if(!$db){
die("Connect Server Failed: " . mysql_error($db));
}
/*连接成功后立即调用mysql_select_db()选中需要连接的数据库*/
if (!mysql_select_db($dbname)) {
die("Select Database Failed: " . mysql_error($db));
}
mysql_query("set names utf-8",$db);
$mysql_table_questions = "questions";
//查询得到当前数据库中题目的数量,便于下面代码中进行判断
$mysql_get_rows = "SHOW TABLE STATUS like '".$mysql_table_questions."';";
$result5 = mysql_query($mysql_get_rows);
$row = mysql_fetch_array($result5);
//当前数据库中题目的数量
$max_question = $row['Rows'];
$mysql_table_record = "record";
$finish_question = 0;
//当用户输入“答题”时,初始化用户答题记录,如果已经有记录,则清零,并且设置当前用户答题数量为0
if ($answer == "答题"){
$mysql_insert = "INSERT INTO `".$mysql_table_record."` (`openid`, `question`, `question_y`, `question_n`) VALUES('".$openid."', '0', '0', '0') ON DUPLICATE KEY UPDATE `question` = '0', `question_y` = '0', `question_n` = '0';";
@mysql_query($mysql_insert);
$finish_question = 0;
}else{
$mysql_select = "SELECT * FROM `".$mysql_table_record."` WHERE `openid` = '".$openid."';";
$result4 = mysql_query($mysql_select);
$row = mysql_fetch_array($result4);
$finish_question = $row['question'];
//如果用户答题的个数已经为题目数量,那么说明用户已经完成答题,不需要再参加此次答题了。
if($finish_question == $max_question){
return "你已经答完了全部题目";
}
//如果还不等于题目数量,那么说明没有答玩,这里将用户的答题数增加 1
$mysql_update = "UPDATE `".$mysql_table_record."` SET `question` = `question` + 1 WHERE `openid` = '".$openid."';";
$result3 = mysql_query($mysql_update);
$finish_question += 1;
}
//根据用户答题个数,定义不同的查询语句
//当用户答第一题的题目时,取回第一个题目
if ($finish_question == 0){
$mysql_state = "SELECT * FROM `".$mysql_table_questions."` LIMIT ".$finish_question.",1";
//当用户答最后一题的题目时,需要取最后一题
}else if($finish_question == $max_question){
$mysql_state = "SELECT * FROM `".$mysql_table_questions."` LIMIT ".($finish_question - 1).",1";
//其他情况下,需要取回当前题目的答案及下一题的题目。
}else{
$mysql_state = "SELECT * FROM `".$mysql_table_questions."` LIMIT ".($finish_question - 1).",2";
}
//执行上述查询语句
$result = @mysql_query($mysql_state);
$content = "";
//获取当用户题数为0时的返回内容,表示用户没有参加过答题
if ($finish_question == 0){
//如果没有查询到题目,则可能是系统出现异常。
if (mysql_num_rows($result) < 1){
$content .= "系统繁忙,请过会重试\n";
}else{
//首先加上一段“一站到底在线答题开始”的提示语,再将第一题的题目及选项返回给用户
$content .= "一站到底在线答题开始\n";
while($row = mysql_fetch_array($result))
{
$content .= "第".$row['id']."题:".$row['question']."\n";
$content .= empty($row['optionA'])?"":"A. ".$row['optionA']."\n";
$content .= empty($row['optionB'])?"":"B. ".$row['optionB']."\n";
$content .= empty($row['optionC'])?"":"C. ".$row['optionC']."\n";
$content .= empty($row['optionD'])?"":"D. ".$row['optionD']."\n";
$content .= empty($row['optionE'])?"":"E. ".$row['optionE']."\n";
$content .= empty($row['optionF'])?"":"F. ".$row['optionF']."\n";
}
}
//这段代码处理用户答到最后一题的情况,这时只需要判断用户答案是否正确,然后将用户的答案情况记录到表中,
//最后,在统计一下用户的答题情况,包括答题个数,正确个数即正确率。
}else if($finish_question == $max_question){
while($row = mysql_fetch_array($result))
{
$content .= ($answer == $row['answer'])?"回答正确\n":"回答错误!正确答案为 ".$row['answer']."\n";
if ($answer == $row['answer']){
$mysql_update_yesno = "UPDATE `".$mysql_table_record."` SET `question_y` = `question_y` + 1 WHERE `openid` = '".$openid."';";
}else{
$mysql_update_yesno = "UPDATE `".$mysql_table_record."` SET `question_n` = `question_n` + 1 WHERE `openid` = '".$openid."';";
}
$result_yesno = mysql_query($mysql_update_yesno);
$mysql_statistics = "SELECT * FROM `".$mysql_table_record."` WHERE `openid` = '".$openid."';";
$result6 = mysql_query($mysql_statistics);
$row = mysql_fetch_array($result6);
$result_all = $row['question'];
$result_yes = $row['question_y'];
$content .= "恭喜,您已完成全部题目。"."\n题目个数:".$result_all."\n正确个数:".$result_yes."\n正确率:".round(($result_yes / $result_all) * 100, 2)."%";
}
//这里处理既不是第一题,也不是最后一题的情况,这种情况下,SQL查询语句中会返回两条记录,
//第一条是当前题目,第二条是下一个题目。系统获取当前题目的答案用于判断用户是否回答正确,获取下一条内容及选项返回给用户,以便用户回答下一题。
}else{
$first = true;
while($row = mysql_fetch_array($result))
{
if ($first){
$content .= ($answer == $row['answer'])?"回答正确\n":"回答错误!正确答案为 ".$row['answer']."\n";
$first = false;
if ($answer == $row['answer']){
$mysql_update_yesno = "UPDATE `".$mysql_table_record."` SET `question_y` = `question_y` + 1 WHERE `openid` = '".$openid."';";
}else{
$mysql_update_yesno = "UPDATE `".$mysql_table_record."` SET `question_n` = `question_n` + 1 WHERE `openid` = '".$openid."';";
}
$result_yesno = mysql_query($mysql_update_yesno);
}else{
$content .= "第".$row['id']."题:".$row['question']."\n";
$content .= empty($row['optionA'])?"":"A. ".$row['optionA']."\n";
$content .= empty($row['optionB'])?"":"B. ".$row['optionB']."\n";
$content .= empty($row['optionC'])?"":"C. ".$row['optionC']."\n";
$content .= empty($row['optionD'])?"":"D. ".$row['optionD']."\n";
$content .= empty($row['optionE'])?"":"E. ".$row['optionE']."\n";
$content .= empty($row['optionF'])?"":"F. ".$row['optionF']."\n";
}
}
}
mysql_close($db);
return trim($content);
}
?>
index.php整体代码如下:
<?php
/*
CopyRight 2018 All Rights Reserved
*/
define("TOKEN", "weixin");
$wechatObj = new wechatCallbackapiTest();
if (!isset($_GET['echostr'])) {
$wechatObj->responseMsg();
}else{
$wechatObj->valid();
}
class wechatCallbackapiTest
{
public function valid()
{
$echoStr = $_GET["echostr"];
if($this->checkSignature()){
echo $echoStr;
exit;
}
}
private function checkSignature()
{
$signature = $_GET["signature"];
$timestamp = $_GET["timestamp"];
$nonce = $_GET["nonce"];
$token = TOKEN;
$tmpArr = array($token, $timestamp, $nonce);
sort($tmpArr);
$tmpStr = implode($tmpArr);
$tmpStr = sha1($tmpStr);
if($tmpStr == $signature){
return true;
}else{
return false;
}
}
public function responseMsg()
{
$postStr = $GLOBALS["HTTP_RAW_POST_DATA"];
if (!empty($postStr)){
$this->logger("R ".$postStr);
$postObj = simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA);
$RX_TYPE = trim($postObj->MsgType);
switch ($RX_TYPE)
{
case "event":
$result = $this->receiveEvent($postObj);
break;
case "text":
$result = $this->receiveText($postObj);
break;
}
$this->logger("T ".$result);
echo $result;
}else {
echo "";
exit;
}
}
private function receiveEvent($object)
{
$content = "";
switch ($object->Event)
{
case "subscribe":
$content = "欢迎关注方倍工作室 ";
break;
case "unsubscribe":
$content = "取消关注";
break;
}
$result = $this->transmitText($object, $content);
return $result;
}
private function receiveText($object)
{
$keyword = trim($object->Content);
if ($keyword == "答题" || preg_match("/^[A-Fa-f]$/", $keyword)){
include("question.php");
$content = getQuestionInfo($object->FromUserName, (($keyword == "答题")?$keyword:strtoupper(trim($object->Content))));
}
$result = $this->transmitText($object, $content);
return $result;
}
private function transmitText($object, $content)
{
$textTpl = "<xml>
<ToUserName><![CDATA[%s]]></ToUserName>
<FromUserName><![CDATA[%s]]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[text]]></MsgType>
<Content><![CDATA[%s]]></Content>
</xml>";
$result = sprintf($textTpl, $object->FromUserName, $object->ToUserName, time(), $content);
return $result;
}
private function logger($log_content)
{
if(isset($_SERVER['HTTP_BAE_ENV_APPID'])){ //BAE
require_once "BaeLog.class.php";
$logger = BaeLog::getInstance();
$logger ->logDebug($log_content);
}else if(isset($_SERVER['HTTP_APPNAME'])){ //SAE
sae_set_display_errors(false);
sae_debug($log_content);
sae_set_display_errors(true);
}else if($_SERVER['REMOTE_ADDR'] != "127.0.0.1"){ //LOCAL
$max_size = 10000;
$log_filename = "log.xml";
if(file_exists($log_filename) and (abs(filesize($log_filename)) > $max_size)){unlink($log_filename);}
file_put_contents($log_filename, date('H:i:s')." ".$log_content."\r\n", FILE_APPEND);
}
}
}
?>