ユーザーが合計タイマーまたは個々の質問タイマーに基づいてテストできるようにするテストタイマーを作成しています。このタイマーは、終了時にデータベースに保存して、時間どおりに完了したかどうかを確認したり、時間がなくなった場合にテストを停止したりする必要があります。問題は、ユーザーが何らかの方法で終了した場合に再開する必要があることです。関数 "register_shutdown_function()" と "pcntl_signal()" は通常の終了イベントをキャッチしますが、ブラウザを手動で (タスク マネージャーのようなものを使用して) 強制終了したり、ブルー スクリーン エラーが発生したりしても、すべての終了イベントをキャッチするものがあるかどうかを知りたいです。クッキーは機能しますが、ユーザーはさまざまなステーションから切り替えます。私が見つけた唯一の代替手段は、10 秒ごとに保存することです (1 秒ごとに保存すると帯域幅と PC リソースが消費されるため)。何かアドバイス?
質問する
668 次
1 に答える
0
この例では、次の形式の SQL テーブルを作成します。
id,session,expire
-----------------
1,d41d8cd98f00b204e9800998ecf8427e,1367727317
このテーブルを作成するには、次を使用します。
CREATE TABLE `quizzes` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`session` varchar(32),
`expire` int(11),
PRIMARY KEY (`id`),
UNIQUE KEY `uc_session` (`session`)
);
さて、楽しい部分です。バックエンド:
<?php
$expire_time=20; //twenty seconds
$precision=2; //how accurate the time is (lower = better, but more polls)
$db_host="127.0.0.1";
$db_user="root";
$db_pass="DATABASE_PASSWORD";
$db_db="DATABASE_NAME";
$precision_mill=$precision*1000;
$script=<<<ZZZ
<script>
function keepAlive() {
var xmlhttp;
if (window.XMLHttpRequest) {
xmlhttp=new XMLHttpRequest();
} else {
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange=function() {
if (xmlhttp.readyState==4 && xmlhttp.status==200) {
if (xmlhttp.responseText=="expired") {
clearInterval(interval);
clearInterval(minusTime);
document.getElementById("timeleft").innerHTML = 0;
alert("Quiz Expired. Please start a new one.");
return;
}
document.getElementById("timeleft").innerHTML = xmlhttp.responseText;
}
}
xmlhttp.open("GET",document.URL+"?keepalive",true);
xmlhttp.send();
}
function keepTime() {
document.getElementById("timeleft").innerHTML-=1;
}
var interval=setInterval(keepAlive,$precision_mill);
var minusTime=setInterval(keepTime,1000);
</script>
ZZZ;
if (isset($_COOKIE['session'])) {
$mysqli=new Mysqli($db_host,$db_user,$db_pass,$db_db);
$session=$mysqli->real_escape_string($_COOKIE['session']);
$expire=$mysqli->query("SELECT `expire` FROM `quizzes` WHERE `session`='".$session."'");
$expire=$expire->fetch_assoc();
if (isset($expire['expire'])) {
$expire=$expire['expire'];
if (isset($_GET['keepalive'])) {
$expire-=$precision;
if ($expire<=0) {
$mysqli->query("DELETE FROM `quizzes` WHERE `session`='".$session."'");
setcookie("session","",time()-3600);
echo "expired";
$mysqli->close();
exit;
}
$mysqli->query("UPDATE `quizzes` SET `expire`=".$expire." WHERE `session`='".$session."'");
echo $expire;
exit;
}
?>
<!DOCTYPE html>
<html>
<head>
<?php
echo $script;
?>
</head>
<body>
<?php
echo 'Quiz resumed, you currently have <div style="display:inline" id="timeleft">'.$expire.'</div> second(s) left.';
?>
</body>
</html>
<?php
$mysqli->close();
exit;
} else {
echo "Quiz expired. Please start a new one.";
exit;
}
} else {
if ($_SERVER['REQUEST_METHOD']==='POST') {
$mysqli=new Mysqli($db_host,$db_user,$db_pass,$db_db);
$session=str_shuffle(md5(microtime()));
$mysqli->query("INSERT INTO `quizzes`(`session`,`expire`) VALUES('".$session."',".$expire_time.")");
setcookie("session",$session);
?>
<!DOCTYPE html>
<html>
<head>
<?php
echo $script;
?>
</head>
<body>
<?php
echo 'Quiz started, you currently have <div style="display:inline" id="timeleft">'.$expire_time.'</div> second(s) left.';
?>
</body>
</html>
<?php
$mysqli->close();
exit;
}
}
if (isset($_GET['keepalive'])) {
echo "expired";
exit;
}
?>
<!DOCTYPE html>
<html>
<head>
<title>Quiz</title>
</head>
<body>
<form method="post" action="">
<input type="Submit" value="Start Quiz">
</form>
</body>
</html>
ユーザーがクイズの開始をクリックすると、最初に開始をクリックしたときを追跡するデータベースでセッションが作成されます。そして、制限時間から までの時間が経過すると、セッションは削除され、クイズは中止されます。
ポーリングを追加したので、ユーザーがいつでもクイズを閉じた場合、サーバーは停止した場所を追跡し、再開できるようにします。
于 2013-05-05T04:16:56.500 に答える