Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

New feature that makes it possible to specify the number of decimals

for the correct answer in calculated questions
as well as some minor refactoring and debugging.
  • Loading branch information...
commit 180bcb27405d684e33cfa0425c6e0362fdb0524f 1 parent 2ad1b38
kaipe authored
4 lang/en/quiz.php
@@ -52,6 +52,7 @@
52 52 $string['correctanswerformula'] = 'Correct Answer Formula';
53 53 $string['correctanswerlength'] = 'Significant Figures';
54 54 $string['correctanswers'] = 'Correct answers';
  55 +$string['correctanswershows'] = 'Correct answer shows';
55 56 $string['corrresp'] = 'Correct Response';
56 57 $string['countdown'] = 'Countdown';
57 58 $string['countdownfinished'] = 'The quiz is closing, you should submit your answers now.';
@@ -63,6 +64,7 @@
63 64 $string['datasetdefinitions'] = 'Reusable dataset definitions for category $a';
64 65 $string['datasetnumber'] = 'Number';
65 66 $string['daysavailable'] = 'Days available';
  67 +$string['decimalformat'] = 'decimals';
66 68 $string['decimals'] = ' with $a ';
67 69 $string['default'] = 'Default';
68 70 $string['defaultgrade'] = 'Default question grade';
@@ -238,6 +240,7 @@
238 240 $string['showfeedback'] = 'After answering, show feedback?';
239 241 $string['shuffleanswers'] = 'Shuffle answers';
240 242 $string['shufflequestions'] = 'Shuffle questions';
  243 +$string['significantfiguresformat'] = 'significant figures';
241 244 $string['significantfigures'] = ' with $a ';
242 245 $string['subneterror'] = 'Sorry, this quiz has been locked so that it is only accessible from certain locations. Currently your computer is not one of those allowed to use this quiz.';
243 246 $string['substitutedby'] = 'will be substituted by';
@@ -267,5 +270,6 @@
267 270 $string['wronggrade'] = 'Wrong grade (after line $a) : ';
268 271 $string['xml'] = 'Moodle XML format';
269 272 $string['yourfinalgradeis'] = 'Your final grade for this quiz is $a';
  273 +$string['zerosignificantfiguresnotallowed'] = 'The correct answer cannot have zero significant figures!';
270 274
271 275 ?>
20 mod/quiz/questiontypes/calculated/calculated.html
@@ -88,14 +88,18 @@
88 88 </td>
89 89 </tr>
90 90 <tr valign="top">
91   -<td align="right"><b><?php print_string("correctanswerlength", "quiz"); ?>:</b></td>
  91 +<td align="right"><b><?php print_string("correctanswershows", "quiz"); ?>:</b></td>
92 92 <td>
93   - <?php choose_from_menu(array('1' => '1', '2' => '2', '3' => '3',
94   - '4' => '4', '5' => '5', '6' => '6',
95   - '7' => '7', '8' => '8', '9' => '9',
96   - '10' => '10'),
  93 + <?php choose_from_menu(array('0' => ' 0 ',
  94 + '1' => ' 1 ', '2' => ' 2 ', '3' => ' 3 ',
  95 + '4' => ' 4 ', '5' => ' 5 ', '6' => ' 6 ',
  96 + '7' => ' 7 ', '8' => ' 8 ', '9' => ' 9 '),
97 97 'correctanswerlength[]',
98 98 $answers[0]->correctanswerlength, false); ?>
  99 + <?php choose_from_menu(array('1' => get_string('decimalformat', 'quiz'),
  100 + '2' => get_string('significantfiguresformat', 'quiz')),
  101 + 'correctanswerformat[]',
  102 + $answers[0]->correctanswerformat, false); ?>
99 103 </td>
100 104 </tr>
101 105 <tr valign="top">
@@ -158,7 +162,7 @@
158 162 return false;
159 163 /* It could perhaps be an idea to parse the formula here
160 164 * but as it is necessary at the server anyway, we can
161   - * leave like this for the moment. */
  165 + * it leave like this for the moment. */
162 166
163 167 } else if (''!=defaultunit.value && !isNaN(defaultunit.value)) {
164 168 alert('<?php print_string("unitmustnotbenumeric","quiz") ?>');
@@ -166,6 +170,10 @@
166 170 } else if (isNaN(tolerance0.value)) {
167 171 alert('<?php print_string("tolerancemustbenumeric","quiz") ?>');
168 172 return false;
  173 + } else if ('2' == document.theform['correctanswerformat[]'].value
  174 + && '0' == document.theform['correctanswerlength[]'].value) {
  175 + alert('<?php print_string("zerosignificantfiguresnotallowed","quiz") ?>');
  176 + return false;
169 177 } else {
170 178 return true;
171 179 }
86 mod/quiz/questiontypes/calculated/editquestion.php
@@ -36,9 +36,15 @@
36 36 // Let's trust the drop down menus.
37 37
38 38 $answers[0]->tolerancetype = array_shift($form->tolerancetype);
39   - $answers[0]->correctanswerlength = array_shift($form->correctanswerlength);
40 39 $answers[0]->fraction = array_shift($form->fraction);
41 40
  41 + $answers[0]->correctanswerlength = array_shift($form->correctanswerlength);
  42 + $answers[0]->correctanswerformat = array_shift($form->correctanswerformat);
  43 +
  44 + 2 == $answers[0]->correctanswerformat
  45 + and 0 == $answers[0]->correctanswerlength
  46 + and $calculatedmessages[]=get_string('zerosignificantfiguresnotallowed','quiz');
  47 +
42 48 // Fill with remaining answers, in case calculated.html
43 49 // supports multiple formulas.
44 50 $i = 1;
@@ -50,6 +56,8 @@
50 56 $answers[$i]->tolerancetype = $form->tolerancetype[$key];
51 57 $answers[$i]->correctanswerlength =
52 58 $form->correctanswerlength[$key];
  59 + $answers[$i]->correctanswerformat =
  60 + $form->correctanswerformat[$key];
53 61
54 62 $answers[$i]->fraction = $form->fraction[$key];
55 63 $answers[$i]->feedback = $form->feedback[$key];
@@ -85,65 +93,99 @@
85 93
86 94
87 95 if (empty($calculatedmessages)) {
88   - // First page calculated.html passed all right!
  96 + /*First page in the question wizard (calculated.html) passed all right!*/
89 97
90 98 if (!empty($form->dataset)) {
91   - // Dataset definitions have been set
92   - // Save question!
  99 + /* Second page in the question wizard has also passed all right */
  100 +
  101 + /***** Save question! ... ****/
93 102 $subtypeoptions->answers = $answers;
94 103 $subtypeoptions->units = $units;
95 104 $question = $qtypeobj->save_question
96 105 ($question, $form, $course, $subtypeoptions);
  106 +
  107 + /***** ... and continue to the dataset item editing: *****/
97 108 require("$CFG->dirroot/mod/quiz/questiontypes/datasetdependent/datasetitems.php");
98 109 exit();
99   - } else {
100   - $datasetmessage = '';
101 110 }
102 111
103   - // Now continue by preparing for the second page questiondatasets.html
  112 + /***** Now continue by preparing for the second page ******
  113 + ***** in the question wizard: "questiondatasets.html" ******/
  114 + $datasetmessage = '';
  115 +
  116 + /*** Answer information is not to be shown ***/
  117 + $hiddeninputnames= array();
  118 + $hiddeninputvalues= array();
  119 + foreach ($answers as $answer) {
  120 + $hiddeninputnames[] = 'answer[]';
  121 + $hiddeninputvalues[] = $answer->answer;
  122 + $hiddeninputnames[] = 'fraction[]';
  123 + $hiddeninputvalues[] = $answer->fraction;
  124 + $hiddeninputnames[] = 'feedback[]';
  125 + $hiddeninputvalues[] = $answer->feedback;
  126 + $hiddeninputnames[] = 'tolerance[]';
  127 + $hiddeninputvalues[] = $answer->tolerance;
  128 + $hiddeninputnames[] = 'tolerancetype[]';
  129 + $hiddeninputvalues[] = $answer->tolerancetype;
  130 + $hiddeninputnames[] = 'correctanswerlength[]';
  131 + $hiddeninputvalues[] = $answer->correctanswerlength;
  132 + $hiddeninputnames[] = 'correctanswerformat[]';
  133 + $hiddeninputvalues[] = $answer->correctanswerformat;
  134 + }
  135 + foreach ($units as $unit) {
  136 + $hiddeninputnames[] = 'unit[]';
  137 + $hiddeninputvalues[] = $unit->unit;
  138 + $hiddeninputnames[] = 'multiplier[]';
  139 + $hiddeninputvalues[] = $unit->multiplier;
  140 + }
104 141
105   - $possibledatasets = $qtypeobj->find_dataset_names(
106   - $question->questiontext);
107   -
  142 + /*** Determine possible and mandatory datasets... ***/
  143 + $possibledatasets = $qtypeobj->find_dataset_names($question->questiontext);
108 144 $mandatorydatasets = array();
109 145 foreach ($answers as $answer) {
110 146 $mandatorydatasets += $qtypeobj
111 147 ->find_dataset_names($answer->answer);
112 148 }
113   -
114 149 $datasets = $qtypeobj->construct_dataset_menus(
115 150 $question, $mandatorydatasets, $possibledatasets);
  151 +
  152 + /*** Print the page ***/
116 153 print_heading_with_help(get_string("choosedatasetproperties", "quiz"), "questiondatasets", "quiz");
117 154 require("$CFG->dirroot/mod/quiz/questiontypes/datasetdependent/questiondatasets.html");
118 155 exit();
119 156 }
120 157
121 158 } else {
122   -// First page in question wizard - calculated.html!
  159 +/*********************************************************/
  160 +/***** First page in question wizard - calculated.html! **/
  161 +/*********************************************************/
123 162
124 163 // The layout of the editing page will only support
125 164 // one formula alternative for calculated questions.
126 165 // However, the code behind supports up to six formulas
127 166 // and the database store and attempt/review framework
128 167 // does not have any limit.
129   - if (!empty($question->id)) {
130   - $answersraw= $qtypeobj->get_answers($question);
131   - }
132 168 $answers= array();
133 169 for ($i=0; $i<6; $i++) {
134   - // Make answer slots with default values
  170 + /*** Make answer slots with default values ***/
135 171 $answers[$i]->answer = "";
136 172 $answers[$i]->feedback = "";
137 173 $answers[$i]->fraction = "1.0";
138 174 $answers[$i]->tolerance = "0.01";
139 175 $answers[$i]->tolerancetype = "1";
140   - $answers[$i]->correctanswerlength = "2";
  176 + $answers[$i]->correctanswerlength = "2"; // Defaults to two ...
  177 + $answers[$i]->correctanswerformat = "1"; // ... decimals
141 178 }
142   - if (!empty($answersraw)) {
143   - $i=0;
144   - foreach ($answersraw as $answer) {
145   - $answers[$i] = $answer;
146   - $i++;
  179 + if (!empty($question->id)) {
  180 + $answersraw = $qtypeobj->get_answers($question);
  181 + if (!empty($answersraw)) {
  182 + /*** Overwrite the default valued answer slots ***
  183 + *** with correct values from database ***/
  184 + $i=0;
  185 + foreach ($answersraw as $answer) {
  186 + $answers[$i] = $answer;
  187 + $i++;
  188 + }
147 189 }
148 190 }
149 191
40 mod/quiz/questiontypes/calculated/questiontype.php
@@ -15,7 +15,7 @@ class quiz_calculated_qtype extends quiz_dataset_dependent_questiontype {
15 15 function get_answers($question) {
16 16 global $CFG;
17 17 return get_records_sql(
18   - "SELECT a.*, c.tolerance, c.tolerancetype, c.correctanswerlength, c.id calcid
  18 + "SELECT a.*, c.tolerance, c.tolerancetype, c.correctanswerlength, c.correctanswerformat, c.id calcid
19 19 FROM {$CFG->prefix}quiz_answers a,
20 20 {$CFG->prefix}quiz_calculated c
21 21 WHERE c.question = $question->id AND a.id = c.answer");
@@ -126,7 +126,7 @@ function generate_dataset_item($options) {
126 126 ++$p10;
127 127 $nbr /= 10;
128 128 }
129   - // ... and have the nbr rounded of to the correct length
  129 + // ... and have the nbr rounded off to the correct length
130 130 $nbr = round($nbr, $regs[4]);
131 131
132 132 // Have the nbr written on a suitable format,
@@ -202,7 +202,8 @@ function comment_on_datasetitems($question, $data, $number) {
202 202 foreach ($answers as $answer) {
203 203 $calculated = quiz_qtype_calculated_calculate_answer(
204 204 $answer->answer, $data, $answer->tolerance,
205   - $answer->tolerancetype, $answer->correctanswerlength, $unit);
  205 + $answer->tolerancetype, $answer->correctanswerlength,
  206 + $answer->correctanswerformat, $unit);
206 207 if ($calculated->min === '') {
207 208 // This should mean that something is wrong
208 209 $errors .= " -$calculated->answer";
@@ -237,6 +238,7 @@ function save_question_options($question, $options) {
237 238 $calcrec->tolerance = $newanswer->tolerance;
238 239 $calcrec->tolerancetype = $newanswer->tolerancetype;
239 240 $calcrec->correctanswerlength = $newanswer->correctanswerlength;
  241 + $calcrec->correctanswerformat = $newanswer->correctanswerformat;
240 242 if ($oldanswer = array_shift($oldanswers)) {
241 243 // Reuse old record:
242 244 $calcrec->answer = $answerrec->id = $oldanswer->id;
@@ -386,7 +388,8 @@ function grade_response($question, $nameprefix) {
386 388 $answernumerical = quiz_qtype_calculated_calculate_answer(
387 389 $answer->answer, $individualdata,
388 390 $answer->tolerance, $answer->tolerancetype,
389   - $answer->correctanswerlength, $unit);
  391 + $answer->correctanswerlength,
  392 + $answer->correctanswerformat, $unit);
390 393 $answers[$aid]->answer = $answernumerical->answer;
391 394 $answers[$aid]->min = $answernumerical->min;
392 395 $answers[$aid]->max = $answernumerical->max;
@@ -410,7 +413,7 @@ function grade_response($question, $nameprefix) {
410 413 $QUIZ_QTYPES[CALCULATED]= new quiz_calculated_qtype();
411 414
412 415 function quiz_qtype_calculated_calculate_answer($formula, $individualdata,
413   - $tolerance, $tolerancetype, $answerlength, $unit='') {
  416 + $tolerance, $tolerancetype, $answerlength, $answerformat='1', $unit='') {
414 417 /// The return value has these properties:
415 418 /// ->answer the correct answer
416 419 /// ->min the lower bound for an acceptable response
@@ -466,8 +469,30 @@ function quiz_qtype_calculated_calculate_answer($formula, $individualdata,
466 469 $calculated->min = $min;
467 470 $calculated->max = $max;
468 471
469   - /// Adjust the number of significant digits for the correct answer
470   - if ($answer) { // Applies only if the result is non-zero
  472 + if ('1' == $answerformat) { /* Answer is to have $answerlength decimals */
  473 + /*** Adjust to the correct number of decimals ***/
  474 +
  475 + $calculated->answer = round($answer, $answerlength);
  476 +
  477 + if ($answerlength) {
  478 + /* Try to include missing zeros at the end */
  479 +
  480 + if (ereg('^(.*\\.)(.*)$', $calculated->answer, $regs)) {
  481 + $calculated->answer = $regs[1] . substr(
  482 + $regs[2] . '00000000000000000000000000000000000000000x',
  483 + 0, $answerlength)
  484 + . $unit;
  485 + } else {
  486 + $calculated->answer .=
  487 + substr('.00000000000000000000000000000000000000000x',
  488 + 0, $answerlength + 1) . $unit;
  489 + }
  490 + } else {
  491 + /* Attach unit */
  492 + $calculated->answer .= $unit;
  493 + }
  494 +
  495 + } else if ($answer) { // Significant figures does only apply if the result is non-zero
471 496
472 497 // Convert to positive answer...
473 498 if ($answer < 0) {
@@ -518,6 +543,7 @@ function quiz_qtype_calculated_calculate_answer($formula, $individualdata,
518 543 $calculated->answer = $sign.substr($answer, 0, $oklen).$unit;
519 544 }
520 545 }
  546 +
521 547 } else {
522 548 $calculated->answer = 0.0;
523 549 }
14 mod/quiz/questiontypes/datasetdependent/questiondatasets.html
@@ -33,17 +33,9 @@
33 33 <input type="hidden" name="questiontext" value="<?php p($question->questiontext) ?>" />
34 34 <input type="hidden" name="questiontextformat" value="<?php p($question->questiontextformat) ?>" />
35 35 <input type="hidden" name="image" value="<?php p($question->image) ?>" />
36   - <?php foreach ($answers as $answer) { ?>
37   - <input type="hidden" name="answer[]" value="<?php p($answer->answer) ?>" />
38   - <input type="hidden" name="fraction[]" value="<?php p($answer->fraction) ?>" />
39   - <input type="hidden" name="feedback[]" value="<?php p($answer->feedback) ?>" />
40   - <input type="hidden" name="tolerance[]" value="<?php p($answer->tolerance) ?>" />
41   - <input type="hidden" name="tolerancetype[]" value="<?php p($answer->tolerancetype) ?>" />
42   - <input type="hidden" name="correctanswerlength[]" value="<?php p($answer->correctanswerlength) ?>" />
43   - <?php } ?>
44   - <?php foreach ($units as $unit) { ?>
45   - <input type="hidden" name="multiplier[]" value="<?php p($unit->multiplier) ?>" />
46   - <input type="hidden" name="unit[]" value="<?php p($unit->unit) ?>" />
  36 + <?php if (!empty($hiddeninputnames)) foreach ($hiddeninputnames as $key => $hiddeninputname) { ?>
  37 + <input type="hidden" name="<?php p($hiddeninputname) ?>"
  38 + value="<?php p($hiddeninputvalues[$key]) ?>" />
47 39 <?php } ?>
48 40 </td>
49 41 </tr>

0 comments on commit 180bcb2

Please sign in to comment.
Something went wrong with that request. Please try again.