]> git.mjollnir.org Git - moodle.git/commitdiff
MDL-5969 Let multiple choice questions have feedback that does not depend on the...
authortjhunt <tjhunt>
Thu, 24 Aug 2006 10:22:43 +0000 (10:22 +0000)
committertjhunt <tjhunt>
Thu, 24 Aug 2006 10:22:43 +0000 (10:22 +0000)
In passing, I fixed MDL-6297 Export of multichoice questions in Moodle XML format doesn't save shuffle option too.

14 files changed:
lang/en_utf8/qtype_multichoice.php [new file with mode: 0644]
question/format/xml/format.php
question/restorelib.php
question/type/multichoice/db/mysql.php
question/type/multichoice/db/mysql.sql
question/type/multichoice/db/postgres7.php
question/type/multichoice/db/postgres7.sql
question/type/multichoice/display.html
question/type/multichoice/editquestion.html
question/type/multichoice/editquestion.php
question/type/multichoice/questiontype.php
question/type/multichoice/version.php
theme/standard/styles_color.css
theme/standard/styles_layout.css

diff --git a/lang/en_utf8/qtype_multichoice.php b/lang/en_utf8/qtype_multichoice.php
new file mode 100644 (file)
index 0000000..69b5e10
--- /dev/null
@@ -0,0 +1,25 @@
+<?php
+/*
+ * Created on Aug 20, 2006
+ *
+ * To change the template for this generated file go to
+ * Window - Preferences - PHPeclipse - PHP - Code Templates
+ */
+
+$string['answersingleno'] = 'Multiple answers allowed';
+$string['answersingleyes'] = 'One answer only';
+$string['choiceno'] = 'Choice $a';
+$string['choices'] = 'Available choices';
+$string['editingmultichoice'] = 'Editing a Multiple Choice question';
+$string['fillouttwochoices'] = 'You must fill out at least two choices.  Choices left blank will not be used.';
+$string['fractionsaddwrong'] = 'The positive grades you have chosen do not add up to 100%%<br />Instead, they add up to $a%%<br />Do you want to go back and fix this question?';
+$string['fractionsnomax'] = 'One of the answers should be 100%%, so that it is<br />possible to get a full grade for this question.<br />Do you want to go back and fix this question?';
+$string['feedback'] = 'Feedback';
+$string['notenoughanswers'] = 'This type of question requires at least $a answers';
+$string['overallcorrectfeedback'] = 'Feedback for any correct answer';
+$string['overallpartiallycorrectfeedback'] = 'Feedback for any partially correct answer';
+$string['overallincorrectfeedback'] = 'Feedback for any incorrect answer';
+$string['shuffleanswers'] = 'Shuffle answers';
+$string['singleanswer'] = 'Choose one answer.';
+
+?>
index f11198e01c11ea11d5c47a4df9e0a00126662782..d1583dbb174a56be3a6ce86560b494d133984d88 100755 (executable)
@@ -82,6 +82,21 @@ class qformat_xml extends qformat_default {
         return addslashes(trim( $data ));
     }
 
+    /**
+     * Process text from an element in the XML that may or not be there.
+     * @param string $subelement the name of the element which is either present or missing.
+     * @param array $question a bit of xml tree, this method looks for $question['#'][$subelement][0]['#']['text'].
+     * @return string If $subelement is present, return the content of the text tag inside it.
+     *      Otherwise returns an empty string.
+     */
+    function import_optional_text($subelement, $question) {
+        if (array_key_exists($subelement, $question['#'])) {
+            return $this->import_text($question['#'][$subelement][0]['#']['text']);
+        } else {
+            return '';
+        }
+    }
+
     /**
      * import parts of question common to all types
      * @param array question question array from xml tree
@@ -149,7 +164,16 @@ class qformat_xml extends qformat_default {
         $qo->qtype = MULTICHOICE;
         $single = $question['#']['single'][0]['#'];
         $qo->single = $this->trans_single( $single );
-
+        if (array_key_exists('shuffleanswers', $question['#'])) {
+            $shuffleanswers = $question['#']['shuffleanswers'][0]['#'];
+        } else {
+            $shuffleanswers = 'false';
+        }
+        $qo->$shuffleanswers = $this->trans_single($shuffleanswers);
+        $qo->correctfeedback = $this->import_optional_text('correctfeedback', $question);
+        $qo->partiallycorrectfeedback = $this->import_optional_text('partiallycorrectfeedback', $question);
+        $qo->incorrectfeedback = $this->import_optional_text('incorrectfeedback', $question);
+        
         // run through the answers
         $answers = $question['#']['answer'];  
         $a_count = 0;
@@ -671,6 +695,10 @@ class qformat_xml extends qformat_default {
             break;
         case MULTICHOICE:
             $expout .= "    <single>".$this->get_single($question->options->single)."</single>\n";
+            $expout .= "    <shuffleanswers>".$this->get_single($question->options->shuffleanswers)."</shuffleanswers>\n";
+            $expout .= "    <correctfeedback>".$this->writetext($question->options->correctfeedback, 3)."</correctfeedback>\n";
+            $expout .= "    <partiallycorrectfeedback>".$this->writetext($question->options->partiallycorrectfeedback, 3)."</partiallycorrectfeedback>\n";
+            $expout .= "    <incorrectfeedback>".$this->writetext($question->options->incorrectfeedback, 3)."</incorrectfeedback>\n";
             foreach($question->options->answers as $answer) {
                 $percent = $answer->fraction * 100;
                 $expout .= "      <answer fraction=\"$percent\">\n";
index 25630ccfcee0b320f289a6f5ee465732a4a98cdb..b46a3c9f03169b369f673f45b42d216192662f42 100644 (file)
             $state->grade = backup_todb($res_info['#']['GRADE']['0']['#']);
             $state->raw_grade = backup_todb($res_info['#']['RAW_GRADE']['0']['#']);
             $state->penalty = backup_todb($res_info['#']['PENALTY']['0']['#']);
+            $state->oldid = $oldid; // So it is available to restore_recode_answer.
 
             //We have to recode the question field
             $question = backup_getid($restore->backup_unique_code,"question",$state->question);
index c95cd21f732792dfaccfd5f3b388e1481e3c7b92..d8fa976b726ae673315203ce94c6b4cdb43a2763 100644 (file)
@@ -4,8 +4,15 @@
 
 function qtype_multichoice_upgrade($oldversion=0) {
     global $CFG;
-
-    return true;
+    $success = true;
+    
+    if ($success && $oldversion < 2006081900) {
+        $success = $success && table_column('question_multichoice', '', 'correctfeedback', 'text', '', '', '');
+        $success = $success && table_column('question_multichoice', '', 'partiallycorrectfeedback', 'text', '', '', '');
+        $success = $success && table_column('question_multichoice', '', 'incorrectfeedback', 'text', '', '', '');
+    }
+    
+    return $success;
 }
 
 ?>
index e729bb199f6e3c973cff3f604fdfe415c2f7fe26..33016d3cfb6b9117c6f8a435c55fb0dd8fd0912e 100644 (file)
@@ -11,6 +11,9 @@ CREATE TABLE prefix_question_multichoice (
   answers varchar(255) NOT NULL default '',
   single tinyint(4) NOT NULL default '0',
   shuffleanswers tinyint(4) NOT NULL default '1',
+  correctfeedback text NOT NULL default '',
+  partiallycorrectfeedback text NOT NULL default '',
+  incorrectfeedback text NOT NULL default '',
   PRIMARY KEY  (id),
   KEY question (question)
 ) TYPE=MyISAM COMMENT='Options for multiple choice questions';
index b811bfe8cbfc781f2c841640b53b07f466179d57..2c11f2cffec24234bd8b31d8d63fd191f35c88c1 100644 (file)
@@ -4,8 +4,15 @@
 
 function qtype_multichoice_upgrade($oldversion=0) {
     global $CFG;
-
-    return true;
+    $success = true;
+    
+    if ($success && $oldversion < 2006081900) {
+        $success = $success && table_column('question_multichoice', '', 'correctfeedback', 'text', '', '', '');
+        $success = $success && table_column('question_multichoice', '', 'partiallycorrectfeedback', 'text', '', '', '');
+        $success = $success && table_column('question_multichoice', '', 'incorrectfeedback', 'text', '', '', '');
+    }
+    
+    return $success;
 }
 
 ?>
index 036278b9e876f33c96759dce39e1a662b2ece318..44a425afb2fb52c6cbb96f77e80e5b6336741aa5 100644 (file)
@@ -11,7 +11,10 @@ CREATE TABLE prefix_question_multichoice (
   layout integer NOT NULL default '0',
   answers varchar(255) NOT NULL default '',
   single integer NOT NULL default '0',
-  shuffleanswers integer NOT NULL default '1'
+  shuffleanswers integer NOT NULL default '1',
+  correctfeedback text NOT NULL default '',
+  partiallycorrectfeedback text NOT NULL default '',
+  incorrectfeedback text NOT NULL default ''
 );
 
 CREATE INDEX prefix_question_multichoice_question_idx ON prefix_question_multichoice (question);
index ef553d29f604ee14ff7e889352eb360d0ebbbe41..83960bc132a6e282f0b73775b619618a68661ab2 100644 (file)
       </tr>
     <?php } ?>
   </table>
+  <?php if ($feedback) { ?>
+    <div class="feedback">
+      <?php echo $feedback ?>
+    </div>
+  <?php } ?>
   <?php $this->print_question_submit_buttons($question, $state, $cmoptions, $options); ?>
 </div>
index 472fe062d36bf2ff76ed0af7550aee1087add80e..05d62a131c3256579b4581973aab06cf8c5e04dd 100644 (file)
@@ -2,28 +2,28 @@
 $QTYPES[$question->qtype]->print_question_form_start($question, array(), $course, $usehtmleditor);
 ?>
   <tr valign="top">
-    <td align="right"><b><?php  print_string("answerhowmany", "quiz") ?>:</b></td>
+    <td align="right"><b><?php  print_string("answerhowmany", "qtype_multichoice") ?>:</b></td>
     <td align="left">
       <?php
-          $menu[0] = get_string("answersingleno", "quiz");
-          $menu[1] = get_string("answersingleyes", "quiz");
+          $menu[0] = get_string("answersingleno", "qtype_multichoice");
+          $menu[1] = get_string("answersingleyes", "qtype_multichoice");
           choose_from_menu($menu, "single", "$options->single", "");
           unset($menu);
       ?>
     </td>
   </tr>
 <tr valign="top">
-    <td align="right"><b><?php print_string("shuffleanswers", "quiz") ?>:</b></td>
+    <td align="right"><b><?php print_string("shuffleanswers", "qtype_multichoice") ?>:</b></td>
      <td align="left">
     <?php
         choose_from_menu($yesnooptions, "shuffleanswers", "$options->shuffleanswers", "");
-        helpbutton("multichoiceshuffle", get_string("shuffleanswers","quiz"), "quiz");
+        helpbutton("multichoiceshuffle", get_string("shuffleanswers","qtype_multichoice"), "quiz");
      ?>
     </td>
 </tr>
   <tr valign="top">
-    <td align="right"><b><?php  print_string("choices", "quiz") ?></b>:</td>
-    <td align="left"><?php  print_string("fillouttwochoices", "quiz") ?></td>
+    <td align="right"><b><?php  print_string("choices", "qtype_multichoice") ?></b>:</td>
+    <td align="left"><?php  print_string("fillouttwochoices", "qtype_multichoice") ?></td>
   </tr>
 
 <?php
@@ -36,9 +36,9 @@ for ($i=1; $i<=count($answers); $i++) {
 ?>
 
   <tr valign="top">
-    <td align="right"><b><?php  echo get_string("choice", "quiz")." $i";  ?>:</b></td>
+    <td align="right"><b><?php print_string("choiceno", "qtype_multichoice", $i); ?>:</b></td>
     <td align="left">
-      <input type="text" name="answer[]" size="50" value="<?php  p($answers[$i-1]->answer) ?>" alt="<?php  echo get_string("choice", "quiz")." $i";  ?>"/>&nbsp;&nbsp;
+      <input type="text" name="answer[]" size="50" value="<?php  p($answers[$i-1]->answer) ?>" />&nbsp;&nbsp;
       <?php
           print_string("grade");
           echo ":&nbsp;";
@@ -49,7 +49,7 @@ for ($i=1; $i<=count($answers); $i++) {
   </tr>
 
   <tr valign="top">
-    <td align="right"><b><?php  print_string("feedback", "quiz") ?>:</b></td>
+    <td align="right"><b><?php print_string("feedback", "qtype_multichoice") ?>:</b></td>
     <td align="left">
       <textarea name="feedback[]" rows="2" cols="50"><?php  p($answers[$i-1]->feedback) ?></textarea>
     </td>
@@ -61,7 +61,33 @@ for ($i=1; $i<=count($answers); $i++) {
 
 <?php
 } /// End of loop, printing answers
+?>
+  <tr valign="top">
+    <td align="right"><b><?php print_string("overallcorrectfeedback", "qtype_multichoice") ?>:</b></td>
+    <td align="left">
+      <textarea name="correctfeedback" rows="4" cols="50"><?php p($options->correctfeedback) ?></textarea>
+    </td>
+  </tr>
+
+  <tr valign="top">
+    <td align="right"><b><?php print_string("overallpartiallycorrectfeedback", "qtype_multichoice") ?>:</b></td>
+    <td align="left">
+      <textarea name="partiallycorrectfeedback" rows="4" cols="50"><?php p($options->partiallycorrectfeedback) ?></textarea>
+    </td>
+  </tr>
 
+  <tr valign="top">
+    <td align="right"><b><?php print_string("overallincorrectfeedback", "qtype_multichoice") ?>:</b></td>
+    <td align="left">
+      <textarea name="incorrectfeedback" rows="4" cols="50"><?php p($options->incorrectfeedback) ?></textarea>
+    </td>
+  </tr>
+
+  <tr valign="top">
+    <td colspan="2">&nbsp;</td>
+  </tr>
+<?php
 $QTYPES[$question->qtype]->print_replacement_options($question, $course, $contextquiz);
 $QTYPES[$question->qtype]->print_question_form_end($question);
 ?>
index 2f55609deb45aeaeef89ac4abd81c74e9177387b..dc77af1b5b0ff4a1338b9c2a3104d6c2a4c143c5 100644 (file)
@@ -5,6 +5,9 @@
     } else {
         $options->single = 1;
         $options->shuffleanswers = 1;
+        $options->correctfeedback = '';
+        $options->partiallycorrectfeedback = '';
+        $options->incorrectfeedback = '';
     }
     if (!empty($options->answers)) {
         $answersraw = get_records_list("question_answers", "id", $options->answers);
@@ -29,7 +32,7 @@
     $yesnooptions[0] = get_string("no");
     $yesnooptions[1] = get_string("yes");
 
-    print_heading_with_help(get_string("editingmultichoice", "quiz"), "multichoice", "quiz");
+    print_heading_with_help(get_string("editingmultichoice", "qtype_multichoice"), "multichoice", "quiz");
     require("$CFG->dirroot/question/type/multichoice/editquestion.html");
 
 ?>
index 44ccadff9ed7670fed4f11681e183a251a49998e..63404e7801202353dd3785366870d814597f1a3e 100644 (file)
@@ -35,7 +35,7 @@ class question_multichoice_qtype extends default_questiontype {
     }
 
     function save_question_options($question) {
-
+        $result = new stdClass;
         if (!$oldanswers = get_records("question_answers", "question",
                                        $question->id, "id ASC")) {
             $oldanswers = array();
@@ -50,7 +50,7 @@ class question_multichoice_qtype extends default_questiontype {
         }
         $answercount += count($oldanswers);
         if ($answercount < 2) { // check there are at lest 2 answers for multiple choice
-            $result->notice = get_string("notenoughanswers", "quiz", "2");
+            $result->notice = get_string("notenoughanswers", "qtype_multichoice", "2");
             return $result;
         }
 
@@ -93,20 +93,26 @@ class question_multichoice_qtype extends default_questiontype {
             }
         }
 
-        if ($options = get_record("question_multichoice", "question", $question->id)) {
-            $options->answers = implode(",",$answers);
-            $options->single = $question->single;
-            $options->shuffleanswers = $question->shuffleanswers;
+        $update = true;
+        $options = get_record("question_multichoice", "question", $question->id);
+        if (!$options) {
+            $update = false;
+            $options = new stdClass;
+            $options->question = $question->id;
+            
+        }
+        $options->answers = implode(",",$answers);
+        $options->single = $question->single;
+        $options->shuffleanswers = $question->shuffleanswers;
+        $options->correctfeedback = trim($question->correctfeedback);
+        $options->partiallycorrectfeedback = trim($question->partiallycorrectfeedback);
+        $options->incorrectfeedback = trim($question->incorrectfeedback);
+        if ($update) {
             if (!update_record("question_multichoice", $options)) {
                 $result->error = "Could not update quiz multichoice options! (id=$options->id)";
                 return $result;
             }
         } else {
-            unset($options);
-            $options->question = $question->id;
-            $options->answers = implode(",",$answers);
-            $options->single = $question->single;
-            $options->shuffleanswers = $question->shuffleanswers;
             if (!insert_record("question_multichoice", $options)) {
                 $result->error = "Could not insert quiz multichoice options!";
                 return $result;
@@ -124,14 +130,14 @@ class question_multichoice_qtype extends default_questiontype {
         if ($options->single) {
             if ($maxfraction != 1) {
                 $maxfraction = $maxfraction * 100;
-                $result->noticeyesno = get_string("fractionsnomax", "quiz", $maxfraction);
+                $result->noticeyesno = get_string("fractionsnomax", "qtype_multichoice", $maxfraction);
                 return $result;
             }
         } else {
             $totalfraction = round($totalfraction,2);
             if ($totalfraction != 1) {
                 $totalfraction = $totalfraction * 100;
-                $result->noticeyesno = get_string("fractionsaddwrong", "quiz", $totalfraction);
+                $result->noticeyesno = get_string("fractionsaddwrong", "qtype_multichoice", $totalfraction);
                 return $result;
             }
         }
@@ -291,6 +297,7 @@ class question_multichoice_qtype extends default_questiontype {
                          ? 'checked="checked"' : '';
             }
 
+            $a = new stdClass;
             $a->id   = $question->name_prefix . $aid;
 
             // Print the control
@@ -314,6 +321,21 @@ class question_multichoice_qtype extends default_questiontype {
 
             $anss[] = clone($a);
         }
+        
+        $feedback = '';
+        if ($options->feedback) {
+            if ($state->raw_grade >= $question->maxgrade/1.01) {
+                $feedback = $question->options->correctfeedback;                
+            } else if ($state->raw_grade > 0) {
+                $feedback = $question->options->partiallycorrectfeedback;                
+            } else {
+                $feedback = $question->options->incorrectfeedback;                
+            }
+            $feedback = format_text($feedback,
+                    $question->questiontextformat,
+                    $formatoptions, $cmoptions->course);
+        }
+        
         include("$CFG->dirroot/question/type/multichoice/display.html");
     }
 
@@ -392,6 +414,9 @@ class question_multichoice_qtype extends default_questiontype {
                 fwrite ($bf,full_tag("ANSWERS",$level+1,false,$multichoice->answers));
                 fwrite ($bf,full_tag("SINGLE",$level+1,false,$multichoice->single));
                 fwrite ($bf,full_tag("SHUFFLEANSWERS",$level+1,false,$multichoice->shuffleanswers));
+                fwrite ($bf,full_tag("CORRECTFEEDBACK",$level+1,false,$multichoice->correctfeedback));
+                fwrite ($bf,full_tag("PARTIALLYCORRECTFEEDBACK",$level+1,false,$multichoice->partiallycorrectfeedback));
+                fwrite ($bf,full_tag("INCORRECTFEEDBACK",$level+1,false,$multichoice->incorrectfeedback));
                 $status = fwrite ($bf,end_tag("MULTICHOICE",$level,true));
             }
 
@@ -420,11 +445,27 @@ class question_multichoice_qtype extends default_questiontype {
             $mul_info = $multichoices[$i];
 
             //Now, build the question_multichoice record structure
+            $multichoice = new stdClass;
             $multichoice->question = $new_question_id;
             $multichoice->layout = backup_todb($mul_info['#']['LAYOUT']['0']['#']);
             $multichoice->answers = backup_todb($mul_info['#']['ANSWERS']['0']['#']);
             $multichoice->single = backup_todb($mul_info['#']['SINGLE']['0']['#']);
             $multichoice->shuffleanswers = backup_todb($mul_info['#']['SHUFFLEANSWERS']['0']['#']);
+            if (array_key_exists("CORRECTFEEDBACK", $mul_info['#'])) {
+                $multichoice->correctfeedback = backup_todb($mul_info['#']['CORRECTFEEDBACK']['0']['#']);
+            } else {
+                $multichoice->correctfeedback = '';
+            }
+            if (array_key_exists("PARTIALLYCORRECTFEEDBACK", $mul_info['#'])) {
+                $multichoice->partiallycorrectfeedback = backup_todb($mul_info['#']['PARTIALLYCORRECTFEEDBACK']['0']['#']);
+            } else {
+                $multichoice->partiallycorrectfeedback = '';
+            }
+            if (array_key_exists("INCORRECTFEEDBACK", $mul_info['#'])) {
+                $multichoice->incorrectfeedback = backup_todb($mul_info['#']['INCORRECTFEEDBACK']['0']['#']);
+            } else {
+                $multichoice->incorrectfeedback = '';
+            }
 
             //We have to recode the answers field (a list of answers id)
             //Extracts answer id from sequence
@@ -490,7 +531,7 @@ class question_multichoice_qtype extends default_questiontype {
                 if ($answer) {
                     $order[$key] = $answer->new_id;
                 } else {
-                    echo 'Could not recode multichoice answer id '.$oldansid.' for state '.$oldid.'<br />';
+                    echo 'Could not recode multichoice answer id '.$oldansid.' for state '.$state->oldid.'<br />';
                 }
             }
         }
@@ -500,7 +541,7 @@ class question_multichoice_qtype extends default_questiontype {
                 if ($answer) {
                     $responses[$key] = $answer->new_id;
                 } else {
-                    echo 'Could not recode multichoice response answer id '.$oldansid.' for state '.$oldid.'<br />';
+                    echo 'Could not recode multichoice response answer id '.$oldansid.' for state '.$state->oldid.'<br />';
                 }
             }
         }
index 2d2a8d9fa7fe95d4af7d3dab8617390b017d0b62..e6e6337095a09c70590cfe24a0ea259bfa94f392 100644 (file)
@@ -1,6 +1,6 @@
 <?PHP // $Id$
 
-$plugin->version  = 2006032200;
+$plugin->version  = 2006081900;
 $plugin->requires = 2006032200;
 
 ?>
index 9fa32e9afcb652bf28a6c212952ff9da0d993e57..fb1c68bcda6f6cc0e19d6130cb0bc2cc4ac69ff7 100644 (file)
@@ -615,10 +615,7 @@ table.message_search_results td {
 .truefalse .answer {
        background-color: #EEE;
 }
-.calculated .feedback,
-.numerical .feedback,
-.shortanswer .feedback,
-.truefalse .feedback {
+.que .feedback {
   border-color: #DDD;
 }      
 .que.multianswer .incorrect {
index 7f8763f99e6f27aad2032b7a0e74f433dbe4d17a..68138961f246179ae11630f962e58875ddc303c2 100644 (file)
@@ -1208,7 +1208,7 @@ body#message-messages {
   padding: 0 0 0.3em 0.3em;
   border: 1px solid;
 }
-.multichoice .feedback {
+.multichoice td.feedback {
   width: auto;
   vertical-align: top;
   padding-top: 0.3em;