Gregory Huxley il y a 1 semaine
Parent
commit
ee350c0968
3 fichiers modifiés avec 78 ajouts et 57 suppressions
  1. 13 0
      obsolete/.htaccess
  2. 1 0
      obsolete/timekeeper.log
  3. 64 57
      questionGenerators/math/numbers2.php

+ 13 - 0
obsolete/.htaccess

@@ -0,0 +1,13 @@
+# TimeKeeper obsolete/ folder: kept in git for reference only.
+# Block all web access to everything in here.
+
+# Apache 2.4+
+<IfModule mod_authz_core.c>
+    Require all denied
+</IfModule>
+
+# Apache 2.2
+<IfModule !mod_authz_core.c>
+    Order deny,allow
+    Deny from all
+</IfModule>

+ 1 - 0
obsolete/timekeeper.log

@@ -0,0 +1 @@
+Timekeeper 3.8 initialised for www-data

+ 64 - 57
questionGenerators/math/numbers2.php

@@ -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 . " &nbsp; ") . "\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;
-        
     }
-}
+}