]> git.mjollnir.org Git - moodle.git/commitdiff
random essay questions: MDL-8648 Allow essay questions to be selected by random question.
authortjhunt <tjhunt>
Fri, 28 Nov 2008 06:07:11 +0000 (06:07 +0000)
committertjhunt <tjhunt>
Fri, 28 Nov 2008 06:07:11 +0000 (06:07 +0000)
In the 1.9 branch this is controlled by a new option under Admin -> Experimental. In Moodle 2.0 dev it is not optional, it just works.

The main change is letting the manual grading report know which random questions might need manual grading. MDL-4004 - this depends on the random question under consideration, which requires a new questiontype method.

I also changed the random question code so that I could remove some global variables.

lang/en_utf8/qtype_random.php [new file with mode: 0644]
lib/questionlib.php
mod/quiz/report/grading/report.php
question/type/essay/questiontype.php
question/type/questiontype.php
question/type/random/questiontype.php

diff --git a/lang/en_utf8/qtype_random.php b/lang/en_utf8/qtype_random.php
new file mode 100644 (file)
index 0000000..8fec9a9
--- /dev/null
@@ -0,0 +1,4 @@
+<?php
+$string['configselectmanualquestions'] = 'Can the random question type select a manually graded question when it is making its random choice of a question from a category?';
+$string['selectmanualquestions'] = 'Random questions can use manually graded questions';
+?>
index 225ea880b0e9290f348618e45480fc59482a606f..10ad27e712d6b18a71d4cb8db4a0f6f3cd0d4da2 100644 (file)
@@ -119,19 +119,13 @@ define('QUESTION_FLAGSSHOWN', 1);
 define('QUESTION_FLAGSEDITABLE', 2);
 /**#@-*/
 
-/// QTYPES INITIATION //////////////////
-// These variables get initialised via calls to question_register_questiontype
-// as the question type classes are included.
-global $QTYPES, $QTYPE_EXCLUDE_FROM_RANDOM;
+/// GLOBAL VARAIBLES //////////////////
+global $QTYPES;
 /**
- * Array holding question type objects
+ * Array holding question type objects. Initialised via calls to
+ * question_register_questiontype as the question type classes are included.
  */
 $QTYPES = array();
-/**
- * String in the format "'type1','type2'" that can be used in SQL clauses like
- * "WHERE q.type NOT IN ($QTYPE_EXCLUDE_FROM_RANDOM)".
- */
-$QTYPE_EXCLUDE_FROM_RANDOM = '';
 
 /**
  * Add a new question type to the various global arrays above.
@@ -139,16 +133,10 @@ $QTYPE_EXCLUDE_FROM_RANDOM = '';
  * @param object $qtype An instance of the new question type class.
  */
 function question_register_questiontype($qtype) {
-    global $QTYPES, $QTYPE_EXCLUDE_FROM_RANDOM;
+    global $QTYPES;
 
     $name = $qtype->name();
     $QTYPES[$name] = $qtype;
-    if (!$qtype->is_usable_by_random()) {
-        if ($QTYPE_EXCLUDE_FROM_RANDOM) {
-            $QTYPE_EXCLUDE_FROM_RANDOM .= ',';
-        }
-        $QTYPE_EXCLUDE_FROM_RANDOM .= "'$name'";
-    }
 }
 
 require_once("$CFG->dirroot/question/type/questiontype.php");
index 688337582c1428ba5b487ee37d18c0d1d1713dd3..f18673dec1ee7c321d5f8e54e0df09ba28bb2a44 100644 (file)
@@ -68,8 +68,9 @@ class quiz_grading_report extends quiz_default_report {
         }
 
         $gradeableqs = quiz_report_load_questions($quiz);
-        foreach ($gradeableqs as $qid => $questionformenu){
-            if (!$QTYPES[$questionformenu->qtype]->is_manual_graded()){
+        $questionsinuse = implode(',', array_keys($gradeableqs));
+        foreach ($gradeableqs as $qid => $question){
+            if (!$QTYPES[$question->qtype]->is_question_manual_graded($question, $questionsinuse)){
                 unset($gradeableqs[$qid]);
             }
         }
index 9ad13e663b7207a87576eb32713624f07b54efd7..5fe289e7109eecee84f333d7927b344c734d79e2 100644 (file)
@@ -19,10 +19,6 @@ class question_essay_qtype extends default_questiontype {
         return true;
     }
 
-    function is_usable_by_random() {
-        return false;
-    }
-
     function save_question_options($question) {
         global $DB;
         $result = true;
index 267ddcb4ac4b98816aec5550edba2b2504c58fa5..601512087909c5e7139d5e25591eda05c486d2ac 100644 (file)
@@ -85,12 +85,21 @@ class default_questiontype {
     }
 
     /**
-     * @return boolean true if this question can only be graded manually.
+     * @return boolean true if this question type may require manual grading.
      */
     function is_manual_graded() {
         return false;
     }
 
+    /**
+     * @param object $question a question of this type.
+     * @param string $otherquestionsinuse comma-separate list of other question ids in this attempt.
+     * @return boolean true if a particular instance of this question requires manual grading.
+     */
+    function is_question_manual_graded($question, $otherquestionsinuse) {
+        return $this->is_manual_graded();
+    }
+
     /**
      * @return boolean true if a table analyzing responses should be shown in
      * the quiz statistics report. Usually if a question is manually graded
index 19d862e7862f53432e11365c2bda7a98f6ad8450..31e5f8663ef50a59beac1e79076bd54b49112d6c 100644 (file)
  * @subpackage questiontypes
  */
 class random_qtype extends default_questiontype {
+    protected $excludedqtypes = null;
+    protected $manualqtypes = null;
 
     // Caches questions available as randoms sorted by category
     // This is a 2-d array. The first key is question category, and the
     // second is whether to include subcategories.
-    var $catrandoms = array();
+    private $catrandoms = array();
 
     function name() {
         return 'random';
@@ -26,10 +28,65 @@ class random_qtype extends default_questiontype {
         return false;
     }
 
+    function show_analysis_of_responses() {
+        return true;
+    }
+
+    function is_manual_graded() {
+        return true;
+    }
+
+    function is_question_manual_graded($question, $otherquestionsinuse) {
+        global $DB;
+        // We take our best shot at working whether a particular question is manually
+        // graded follows: We look to see if any of the questions that this random
+        // question might select if of a manually graded type. If a category contains
+        // a mixture of manual and non-manual questions, and if all the attempts so
+        // far selected non-manual ones, this will give the wrong answer, but we
+        // don't care. Even so, this is an expensive calculation!
+        $this->init_qtype_lists();
+        if (!$this->manualqtypes) {
+            return false;
+        }
+        if ($question->questiontext) {
+            $categorylist = question_categorylist($question->category);
+        } else {
+            $categorylist = $question->category;
+        }
+        return $DB->record_exists_select('question',
+                "category IN ($categorylist)
+                     AND parent = 0
+                     AND hidden = 0
+                     AND id NOT IN ($otherquestionsinuse)
+                     AND qtype IN ($this->manualqtypes)");
+    }
+
     function is_usable_by_random() {
         return false;
     }
 
+    /**
+     * This method needs to be called before the ->excludedqtypes and
+     *      ->manualqtypes fields can be used.
+     */
+    function init_qtype_lists() {
+        global $QTYPES;
+        if (is_null($this->excludedqtypes)) {
+            $excludedqtypes = array();
+            $manualqtypes = array();
+            foreach ($QTYPES as $qtype) {
+                $quotedname = "'" . $qtype->name() . "'";
+                if (!$qtype->is_usable_by_random()) {
+                    $excludedqtypes[] = $quotedname;
+                } else if ($qtype->is_manual_graded()) {
+                    $manualqtypes[] = $quotedname;
+                }
+            }
+            $this->excludedqtypes = implode(',', $excludedqtypes);
+            $this->manualqtypes = implode(',', $manualqtypes);
+        }
+    }
+
     function display_question_editing_page(&$mform, $question, $wizardnow){
         list($heading, $langmodule) = $this->get_heading(empty($question->id));
         print_heading_with_help($heading, $this->name(), $langmodule);
@@ -87,7 +144,8 @@ class random_qtype extends default_questiontype {
      * @return array of question records.
      */
     function get_usable_questions_from_category($categoryid, $subcategories, $questionsinuse) {
-        global $QTYPE_EXCLUDE_FROM_RANDOM, $DB;
+        global $DB;
+        $this->init_qtype_lists();
         if ($subcategories) {
             $categorylist = question_categorylist($categoryid);
         } else {
@@ -95,10 +153,10 @@ class random_qtype extends default_questiontype {
         }
         if (!$catrandoms = $DB->get_records_select('question',
                 "category IN ($categorylist)
-                     AND parent = '0'
-                     AND hidden = '0'
+                     AND parent = 0
+                     AND hidden = 0
                      AND id NOT IN ($questionsinuse)
-                     AND qtype NOT IN ($QTYPE_EXCLUDE_FROM_RANDOM)", null, '', 'id')) {
+                     AND qtype NOT IN ($this->excludedqtypes)", null, '', 'id')) {
             $catrandoms = array();
         }
         return $catrandoms;