|
|
@@ -1,15 +1,18 @@
|
|
|
<?php
|
|
|
|
|
|
-/*
|
|
|
- * To change this license header, choose License Headers in Project Properties.
|
|
|
- * To change this template file, choose Tools | Templates
|
|
|
- * and open the template in the editor.
|
|
|
- */
|
|
|
-
|
|
|
/**
|
|
|
- * Description of numbers
|
|
|
+ * "Find the missing number" sequence generator.
|
|
|
*
|
|
|
- * @author gregory
|
|
|
+ * Changes from the current repo version:
|
|
|
+ * - difficulty() returned the int 1 for a new user and the code then indexed
|
|
|
+ * it like an array (null values, notices on PHP 7.4+/8); it always returns
|
|
|
+ * ['percent' => .., 'count' => ..] now
|
|
|
+ * - user escaped in SQL; the hard-coded `e107.` database name replaced by
|
|
|
+ * MPREFIX
|
|
|
+ * - the previous tkLastQuestion row is removed before inserting the new one
|
|
|
+ * (each question used to add another row)
|
|
|
+ * - the token from TkAnswerStore::issue() is built once, before the form
|
|
|
+ * - leftover commented-out debug line removed
|
|
|
*/
|
|
|
class numbers2 {
|
|
|
|
|
|
@@ -17,64 +20,65 @@ class numbers2 {
|
|
|
|
|
|
/**
|
|
|
* Setup new numbers engine
|
|
|
- *
|
|
|
- * @param bool $test Enable debug mode.
|
|
|
+ *
|
|
|
+ * @param string $user User to supply the question for.
|
|
|
*/
|
|
|
public function __construct($user) {
|
|
|
-
|
|
|
$this->user = $user;
|
|
|
-
|
|
|
}
|
|
|
|
|
|
public function getNumbers() {
|
|
|
-
|
|
|
$difficulty = $this->difficulty();
|
|
|
$question = $this->getSequence($difficulty);
|
|
|
$questionHtml = $this->htmlify($question);
|
|
|
-
|
|
|
- e107::getDb()->insert('tkLastQuestion', ['user'=>$this->user,'LastQuestionHtml'=>base64_encode($questionHtml)]);
|
|
|
-
|
|
|
+
|
|
|
+ $db = e107::getDb();
|
|
|
+ $db->delete('tkLastQuestion', "user = '" . $db->escape($this->user) . "'");
|
|
|
+ $db->insert('tkLastQuestion', ['user' => $this->user, 'LastQuestionHtml' => base64_encode($questionHtml)]);
|
|
|
+
|
|
|
e107::getRender()->tablerender('Numbers', $questionHtml);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * Return the difficulty based on previously answered questions.
|
|
|
+ * Difficulty based on the last month of answers.
|
|
|
*
|
|
|
- * @return int Difficulty as percent.
|
|
|
+ * @return array ['percent' => float 0-100, 'count' => int]
|
|
|
*/
|
|
|
private function difficulty() {
|
|
|
+ $db = e107::getDb();
|
|
|
+ $stats = $db->retrieve(
|
|
|
+ "SELECT (SUM(correct)/COUNT(correct)*100) AS percent, COUNT(correct) AS count
|
|
|
+ FROM `" . MPREFIX . "tkReport`
|
|
|
+ WHERE answereddatestamp >= UNIX_TIMESTAMP(NOW() - INTERVAL 1 MONTH)
|
|
|
+ AND username = '" . $db->escape($this->user) . "' AND subject = 'numbers'"
|
|
|
+ );
|
|
|
|
|
|
- $stats = e107::getDb()->retrieve("SELECT (SUM(correct)/COUNT(correct)*100) as percent,COUNT(correct) as count
|
|
|
- FROM e107.`e107_tkReport` WHERE
|
|
|
- answereddatestamp >= unix_timestamp((NOW()) - INTERVAL 1 MONTH)
|
|
|
- AND username = '$this->user' AND subject = 'numbers';");
|
|
|
-
|
|
|
- if ($stats["count"]==0) {
|
|
|
- return 1;
|
|
|
- } else {
|
|
|
- return $stats;
|
|
|
+ if (!is_array($stats) || (int) $stats['count'] === 0) {
|
|
|
+ return ['percent' => 0, 'count' => 0];
|
|
|
}
|
|
|
-
|
|
|
-
|
|
|
+
|
|
|
+ return ['percent' => (float) $stats['percent'], 'count' => (int) $stats['count']];
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
private function getSequence($difficulty) {
|
|
|
-
|
|
|
- //print_a(['slide'=>($difficulty['percent']/100)*2,'diff'=>$difficulty,'pow'=>(int)pow($difficulty['count'],($difficulty['percent']/100)*2)]);
|
|
|
-
|
|
|
- $startingNumber = mt_rand(0, (int) pow($difficulty['count'],($difficulty['percent']/100)*2));
|
|
|
- if($difficulty['count']>=300) {
|
|
|
- $incrementalNumber = mt_rand(1, 100 );
|
|
|
- }elseif($difficulty['count']>=200){
|
|
|
- $incrementalNumber = mt_rand(1, 10 );
|
|
|
- }elseif($difficulty['count']>=100){
|
|
|
- $incrementalNumber = mt_rand(1, 5 );
|
|
|
- }else{
|
|
|
+ $count = (int) $difficulty['count'];
|
|
|
+ $percent = (float) $difficulty['percent'];
|
|
|
+
|
|
|
+ $startingNumber = mt_rand(0, (int) pow($count, ($percent / 100) * 2));
|
|
|
+
|
|
|
+ if ($count >= 300) {
|
|
|
+ $incrementalNumber = mt_rand(1, 100);
|
|
|
+ } elseif ($count >= 200) {
|
|
|
+ $incrementalNumber = mt_rand(1, 10);
|
|
|
+ } elseif ($count >= 100) {
|
|
|
+ $incrementalNumber = mt_rand(1, 5);
|
|
|
+ } else {
|
|
|
$incrementalNumber = mt_rand(1, 2);
|
|
|
}
|
|
|
+
|
|
|
$missingNumber = mt_rand(1, 10);
|
|
|
$TempQuestion = [];
|
|
|
-
|
|
|
+
|
|
|
for ($i = 1; $i <= 10; $i++) {
|
|
|
if ($i == $missingNumber) {
|
|
|
$TempQuestion[] = "___,";
|
|
|
@@ -84,40 +88,43 @@ class numbers2 {
|
|
|
} else {
|
|
|
$TempQuestion[] = round($startingNumber) . ",";
|
|
|
}
|
|
|
- if($difficulty['percent']>=90 && $difficulty['count']>=200){
|
|
|
- $startingNumber += round((2*$incrementalNumber)/$i);
|
|
|
- }elseif($difficulty['percent']>=80 && $difficulty['count']>=100){
|
|
|
- $startingNumber += $incrementalNumber*($i*15);
|
|
|
- }else{
|
|
|
+
|
|
|
+ if ($percent >= 90 && $count >= 200) {
|
|
|
+ $startingNumber += round((2 * $incrementalNumber) / $i);
|
|
|
+ } elseif ($percent >= 80 && $count >= 100) {
|
|
|
+ $startingNumber += $incrementalNumber * ($i * 15);
|
|
|
+ } else {
|
|
|
$startingNumber += $incrementalNumber;
|
|
|
}
|
|
|
}
|
|
|
- return [ 'answer1'=>$solution, 'question'=>$TempQuestion, 'type'=>'numbers'];
|
|
|
+
|
|
|
+ return ['answer1' => $solution, 'question' => $TempQuestion, 'type' => 'numbers'];
|
|
|
}
|
|
|
|
|
|
private function htmlify($question) {
|
|
|
-
|
|
|
+ // Expected answer stays on the server; the form only carries a token.
|
|
|
+ $token = TkAnswerStore::issue($this->user, $question);
|
|
|
+
|
|
|
$frm = e107::getForm();
|
|
|
|
|
|
$fString = $frm->open('questionForm', 'post', '', ['autocomplete' => 'off', 'class' => 'formclass']);
|
|
|
$fString .= $frm->label('<h4>Numbers</h4>') . "</br>\n";
|
|
|
$fString .= $frm->label('Find the missing number.') . "\n";
|
|
|
$fString .= '</br>';
|
|
|
-
|
|
|
+
|
|
|
foreach ($question['question'] as $seq) {
|
|
|
$fString .= $frm->label($seq . " ") . "\n";
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
$fString .= '</br></br>';
|
|
|
$fString .= $frm->text('a1', '', 80, ['placeholder' => 'Write answer here!', 'autocomplete' => "off", 'spellcheck' => "false"]) . "\n";
|
|
|
- $fString .= $frm->hidden('checkerData', TkAnswerStore::issue($this->user, $question), ['id' => 'checkerData']);
|
|
|
+ $fString .= $frm->hidden('checkerData', $token, ['id' => 'checkerData']);
|
|
|
$fString .= $frm->hidden('subject', 'numbers', ['id' => 'subject']);
|
|
|
$fString .= '</br>' . "\n";
|
|
|
- $fString .= e107::getForm()->button('Answer', 'Check answer') . "\n";
|
|
|
- $fString .= e107::getForm()->close();
|
|
|
+ $fString .= $frm->button('Answer', 'Check answer') . "\n";
|
|
|
+ $fString .= $frm->close();
|
|
|
$fString .= '</br></br>';
|
|
|
-
|
|
|
+
|
|
|
return $fString;
|
|
|
-
|
|
|
}
|
|
|
-}
|
|
|
+}
|