Skip to content

Commit

Permalink
New feature that makes it possible to specify the number of decimals
Browse files Browse the repository at this point in the history
for the correct answer in calculated questions
as well as some minor refactoring and debugging.
  • Loading branch information
kaipe committed Dec 5, 2004
1 parent 2ad1b38 commit 180bcb2
Show file tree
Hide file tree
Showing 5 changed files with 118 additions and 46 deletions.
4 changes: 4 additions & 0 deletions lang/en/quiz.php
Expand Up @@ -52,6 +52,7 @@
$string['correctanswerformula'] = 'Correct Answer Formula';
$string['correctanswerlength'] = 'Significant Figures';
$string['correctanswers'] = 'Correct answers';
$string['correctanswershows'] = 'Correct answer shows';
$string['corrresp'] = 'Correct Response';
$string['countdown'] = 'Countdown';
$string['countdownfinished'] = 'The quiz is closing, you should submit your answers now.';
Expand All @@ -63,6 +64,7 @@
$string['datasetdefinitions'] = 'Reusable dataset definitions for category $a';
$string['datasetnumber'] = 'Number';
$string['daysavailable'] = 'Days available';
$string['decimalformat'] = 'decimals';
$string['decimals'] = ' with $a ';
$string['default'] = 'Default';
$string['defaultgrade'] = 'Default question grade';
Expand Down Expand Up @@ -238,6 +240,7 @@
$string['showfeedback'] = 'After answering, show feedback?';
$string['shuffleanswers'] = 'Shuffle answers';
$string['shufflequestions'] = 'Shuffle questions';
$string['significantfiguresformat'] = 'significant figures';
$string['significantfigures'] = ' with $a ';
$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.';
$string['substitutedby'] = 'will be substituted by';
Expand Down Expand Up @@ -267,5 +270,6 @@
$string['wronggrade'] = 'Wrong grade (after line $a) : ';
$string['xml'] = 'Moodle XML format';
$string['yourfinalgradeis'] = 'Your final grade for this quiz is $a';
$string['zerosignificantfiguresnotallowed'] = 'The correct answer cannot have zero significant figures!';

?>
20 changes: 14 additions & 6 deletions mod/quiz/questiontypes/calculated/calculated.html
Expand Up @@ -88,14 +88,18 @@
</td>
</tr>
<tr valign="top">
<td align="right"><b><?php print_string("correctanswerlength", "quiz"); ?>:</b></td>
<td align="right"><b><?php print_string("correctanswershows", "quiz"); ?>:</b></td>
<td>
<?php choose_from_menu(array('1' => '1', '2' => '2', '3' => '3',
'4' => '4', '5' => '5', '6' => '6',
'7' => '7', '8' => '8', '9' => '9',
'10' => '10'),
<?php choose_from_menu(array('0' => ' 0 ',
'1' => ' 1 ', '2' => ' 2 ', '3' => ' 3 ',
'4' => ' 4 ', '5' => ' 5 ', '6' => ' 6 ',
'7' => ' 7 ', '8' => ' 8 ', '9' => ' 9 '),
'correctanswerlength[]',
$answers[0]->correctanswerlength, false); ?>
<?php choose_from_menu(array('1' => get_string('decimalformat', 'quiz'),
'2' => get_string('significantfiguresformat', 'quiz')),
'correctanswerformat[]',
$answers[0]->correctanswerformat, false); ?>
</td>
</tr>
<tr valign="top">
Expand Down Expand Up @@ -158,14 +162,18 @@
return false;
/* It could perhaps be an idea to parse the formula here
* but as it is necessary at the server anyway, we can
* leave like this for the moment. */
* it leave like this for the moment. */

} else if (''!=defaultunit.value && !isNaN(defaultunit.value)) {
alert('<?php print_string("unitmustnotbenumeric","quiz") ?>');
return false;
} else if (isNaN(tolerance0.value)) {
alert('<?php print_string("tolerancemustbenumeric","quiz") ?>');
return false;
} else if ('2' == document.theform['correctanswerformat[]'].value
&& '0' == document.theform['correctanswerlength[]'].value) {
alert('<?php print_string("zerosignificantfiguresnotallowed","quiz") ?>');
return false;
} else {
return true;
}
Expand Down
86 changes: 64 additions & 22 deletions mod/quiz/questiontypes/calculated/editquestion.php
Expand Up @@ -36,9 +36,15 @@
// Let's trust the drop down menus.

$answers[0]->tolerancetype = array_shift($form->tolerancetype);
$answers[0]->correctanswerlength = array_shift($form->correctanswerlength);
$answers[0]->fraction = array_shift($form->fraction);

$answers[0]->correctanswerlength = array_shift($form->correctanswerlength);
$answers[0]->correctanswerformat = array_shift($form->correctanswerformat);

2 == $answers[0]->correctanswerformat
and 0 == $answers[0]->correctanswerlength
and $calculatedmessages[]=get_string('zerosignificantfiguresnotallowed','quiz');

// Fill with remaining answers, in case calculated.html
// supports multiple formulas.
$i = 1;
Expand All @@ -50,6 +56,8 @@
$answers[$i]->tolerancetype = $form->tolerancetype[$key];
$answers[$i]->correctanswerlength =
$form->correctanswerlength[$key];
$answers[$i]->correctanswerformat =
$form->correctanswerformat[$key];

$answers[$i]->fraction = $form->fraction[$key];
$answers[$i]->feedback = $form->feedback[$key];
Expand Down Expand Up @@ -85,65 +93,99 @@


if (empty($calculatedmessages)) {
// First page calculated.html passed all right!
/*First page in the question wizard (calculated.html) passed all right!*/

if (!empty($form->dataset)) {
// Dataset definitions have been set
// Save question!
/* Second page in the question wizard has also passed all right */

/***** Save question! ... ****/
$subtypeoptions->answers = $answers;
$subtypeoptions->units = $units;
$question = $qtypeobj->save_question
($question, $form, $course, $subtypeoptions);

/***** ... and continue to the dataset item editing: *****/
require("$CFG->dirroot/mod/quiz/questiontypes/datasetdependent/datasetitems.php");
exit();
} else {
$datasetmessage = '';
}

// Now continue by preparing for the second page questiondatasets.html
/***** Now continue by preparing for the second page ******
***** in the question wizard: "questiondatasets.html" ******/
$datasetmessage = '';

/*** Answer information is not to be shown ***/
$hiddeninputnames= array();
$hiddeninputvalues= array();
foreach ($answers as $answer) {
$hiddeninputnames[] = 'answer[]';
$hiddeninputvalues[] = $answer->answer;
$hiddeninputnames[] = 'fraction[]';
$hiddeninputvalues[] = $answer->fraction;
$hiddeninputnames[] = 'feedback[]';
$hiddeninputvalues[] = $answer->feedback;
$hiddeninputnames[] = 'tolerance[]';
$hiddeninputvalues[] = $answer->tolerance;
$hiddeninputnames[] = 'tolerancetype[]';
$hiddeninputvalues[] = $answer->tolerancetype;
$hiddeninputnames[] = 'correctanswerlength[]';
$hiddeninputvalues[] = $answer->correctanswerlength;
$hiddeninputnames[] = 'correctanswerformat[]';
$hiddeninputvalues[] = $answer->correctanswerformat;
}
foreach ($units as $unit) {
$hiddeninputnames[] = 'unit[]';
$hiddeninputvalues[] = $unit->unit;
$hiddeninputnames[] = 'multiplier[]';
$hiddeninputvalues[] = $unit->multiplier;
}

$possibledatasets = $qtypeobj->find_dataset_names(
$question->questiontext);

/*** Determine possible and mandatory datasets... ***/
$possibledatasets = $qtypeobj->find_dataset_names($question->questiontext);
$mandatorydatasets = array();
foreach ($answers as $answer) {
$mandatorydatasets += $qtypeobj
->find_dataset_names($answer->answer);
}

$datasets = $qtypeobj->construct_dataset_menus(
$question, $mandatorydatasets, $possibledatasets);

/*** Print the page ***/
print_heading_with_help(get_string("choosedatasetproperties", "quiz"), "questiondatasets", "quiz");
require("$CFG->dirroot/mod/quiz/questiontypes/datasetdependent/questiondatasets.html");
exit();
}

} else {
// First page in question wizard - calculated.html!
/*********************************************************/
/***** First page in question wizard - calculated.html! **/
/*********************************************************/

// The layout of the editing page will only support
// one formula alternative for calculated questions.
// However, the code behind supports up to six formulas
// and the database store and attempt/review framework
// does not have any limit.
if (!empty($question->id)) {
$answersraw= $qtypeobj->get_answers($question);
}
$answers= array();
for ($i=0; $i<6; $i++) {
// Make answer slots with default values
/*** Make answer slots with default values ***/
$answers[$i]->answer = "";
$answers[$i]->feedback = "";
$answers[$i]->fraction = "1.0";
$answers[$i]->tolerance = "0.01";
$answers[$i]->tolerancetype = "1";
$answers[$i]->correctanswerlength = "2";
$answers[$i]->correctanswerlength = "2"; // Defaults to two ...
$answers[$i]->correctanswerformat = "1"; // ... decimals
}
if (!empty($answersraw)) {
$i=0;
foreach ($answersraw as $answer) {
$answers[$i] = $answer;
$i++;
if (!empty($question->id)) {
$answersraw = $qtypeobj->get_answers($question);
if (!empty($answersraw)) {
/*** Overwrite the default valued answer slots ***
*** with correct values from database ***/
$i=0;
foreach ($answersraw as $answer) {
$answers[$i] = $answer;
$i++;
}
}
}

Expand Down
40 changes: 33 additions & 7 deletions mod/quiz/questiontypes/calculated/questiontype.php
Expand Up @@ -15,7 +15,7 @@ class quiz_calculated_qtype extends quiz_dataset_dependent_questiontype {
function get_answers($question) {
global $CFG;
return get_records_sql(
"SELECT a.*, c.tolerance, c.tolerancetype, c.correctanswerlength, c.id calcid
"SELECT a.*, c.tolerance, c.tolerancetype, c.correctanswerlength, c.correctanswerformat, c.id calcid
FROM {$CFG->prefix}quiz_answers a,
{$CFG->prefix}quiz_calculated c
WHERE c.question = $question->id AND a.id = c.answer");
Expand Down Expand Up @@ -126,7 +126,7 @@ function generate_dataset_item($options) {
++$p10;
$nbr /= 10;
}
// ... and have the nbr rounded of to the correct length
// ... and have the nbr rounded off to the correct length
$nbr = round($nbr, $regs[4]);

// Have the nbr written on a suitable format,
Expand Down Expand Up @@ -202,7 +202,8 @@ function comment_on_datasetitems($question, $data, $number) {
foreach ($answers as $answer) {
$calculated = quiz_qtype_calculated_calculate_answer(
$answer->answer, $data, $answer->tolerance,
$answer->tolerancetype, $answer->correctanswerlength, $unit);
$answer->tolerancetype, $answer->correctanswerlength,
$answer->correctanswerformat, $unit);
if ($calculated->min === '') {
// This should mean that something is wrong
$errors .= " -$calculated->answer";
Expand Down Expand Up @@ -237,6 +238,7 @@ function save_question_options($question, $options) {
$calcrec->tolerance = $newanswer->tolerance;
$calcrec->tolerancetype = $newanswer->tolerancetype;
$calcrec->correctanswerlength = $newanswer->correctanswerlength;
$calcrec->correctanswerformat = $newanswer->correctanswerformat;
if ($oldanswer = array_shift($oldanswers)) {
// Reuse old record:
$calcrec->answer = $answerrec->id = $oldanswer->id;
Expand Down Expand Up @@ -386,7 +388,8 @@ function grade_response($question, $nameprefix) {
$answernumerical = quiz_qtype_calculated_calculate_answer(
$answer->answer, $individualdata,
$answer->tolerance, $answer->tolerancetype,
$answer->correctanswerlength, $unit);
$answer->correctanswerlength,
$answer->correctanswerformat, $unit);
$answers[$aid]->answer = $answernumerical->answer;
$answers[$aid]->min = $answernumerical->min;
$answers[$aid]->max = $answernumerical->max;
Expand All @@ -410,7 +413,7 @@ function grade_response($question, $nameprefix) {
$QUIZ_QTYPES[CALCULATED]= new quiz_calculated_qtype();

function quiz_qtype_calculated_calculate_answer($formula, $individualdata,
$tolerance, $tolerancetype, $answerlength, $unit='') {
$tolerance, $tolerancetype, $answerlength, $answerformat='1', $unit='') {
/// The return value has these properties:
/// ->answer the correct answer
/// ->min the lower bound for an acceptable response
Expand Down Expand Up @@ -466,8 +469,30 @@ function quiz_qtype_calculated_calculate_answer($formula, $individualdata,
$calculated->min = $min;
$calculated->max = $max;

/// Adjust the number of significant digits for the correct answer
if ($answer) { // Applies only if the result is non-zero
if ('1' == $answerformat) { /* Answer is to have $answerlength decimals */
/*** Adjust to the correct number of decimals ***/

$calculated->answer = round($answer, $answerlength);

if ($answerlength) {
/* Try to include missing zeros at the end */

if (ereg('^(.*\\.)(.*)$', $calculated->answer, $regs)) {
$calculated->answer = $regs[1] . substr(
$regs[2] . '00000000000000000000000000000000000000000x',
0, $answerlength)
. $unit;
} else {
$calculated->answer .=
substr('.00000000000000000000000000000000000000000x',
0, $answerlength + 1) . $unit;
}
} else {
/* Attach unit */
$calculated->answer .= $unit;
}

} else if ($answer) { // Significant figures does only apply if the result is non-zero

// Convert to positive answer...
if ($answer < 0) {
Expand Down Expand Up @@ -518,6 +543,7 @@ function quiz_qtype_calculated_calculate_answer($formula, $individualdata,
$calculated->answer = $sign.substr($answer, 0, $oklen).$unit;
}
}

} else {
$calculated->answer = 0.0;
}
Expand Down
14 changes: 3 additions & 11 deletions mod/quiz/questiontypes/datasetdependent/questiondatasets.html
Expand Up @@ -33,17 +33,9 @@
<input type="hidden" name="questiontext" value="<?php p($question->questiontext) ?>" />
<input type="hidden" name="questiontextformat" value="<?php p($question->questiontextformat) ?>" />
<input type="hidden" name="image" value="<?php p($question->image) ?>" />
<?php foreach ($answers as $answer) { ?>
<input type="hidden" name="answer[]" value="<?php p($answer->answer) ?>" />
<input type="hidden" name="fraction[]" value="<?php p($answer->fraction) ?>" />
<input type="hidden" name="feedback[]" value="<?php p($answer->feedback) ?>" />
<input type="hidden" name="tolerance[]" value="<?php p($answer->tolerance) ?>" />
<input type="hidden" name="tolerancetype[]" value="<?php p($answer->tolerancetype) ?>" />
<input type="hidden" name="correctanswerlength[]" value="<?php p($answer->correctanswerlength) ?>" />
<?php } ?>
<?php foreach ($units as $unit) { ?>
<input type="hidden" name="multiplier[]" value="<?php p($unit->multiplier) ?>" />
<input type="hidden" name="unit[]" value="<?php p($unit->unit) ?>" />
<?php if (!empty($hiddeninputnames)) foreach ($hiddeninputnames as $key => $hiddeninputname) { ?>
<input type="hidden" name="<?php p($hiddeninputname) ?>"
value="<?php p($hiddeninputvalues[$key]) ?>" />
<?php } ?>
</td>
</tr>
Expand Down

0 comments on commit 180bcb2

Please sign in to comment.