Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

New feature

Unit support for numerical questions
  • Loading branch information...
commit 7a82d193240ab6a3df435ac2c89821864d5d2ee4 1 parent 8c5a95f
kaipe authored
View
61 mod/quiz/questiontypes/numerical/editquestion.php
@@ -19,6 +19,67 @@
$i++;
}
}
+ $units = array();
+ for ($i=0 ; $i<6 ; $i++) {
+ $units[$i]->multiplier = ''; // Make unit slots, default as blank...
+ $units[$i]->unit = '';
+ }
+ if (!empty($question->id) and $unitsraw = get_records(
+ 'quiz_numerical_units', 'question', $question->id)) {
+ /// Find default unit and have it put in the zero slot
+ /// This procedure might be overridden later when
+ /// the unit is stripped form an answer...
+ foreach ($unitsraw as $key => $unit) {
+ if (1.0 == $unit->multiplier) {
+ /// Default unit found:
+ $units[0] = $unit;
+ unset($unitsraw[$key]);
+ break;
+ }
+ }
+ /// Fill remaining answer slots with whatsever left
+ if (!empty($unitsraw)) {
+ $i = 1; // The zero slot got the default unit...
+ foreach ($unitsraw as $unit) {
+ $units[$i] = $unit;
+ $i++;
+ }
+ }
+ } else {
+ $units[0]->multiplier = 1.0;
+ }
+
+ // Strip unit from answers, if they have any:
+ foreach ($units as $key => $unit) {
+ if (1.0 == $unit->multiplier && $unit->unit) {
+ $ukey = $key;
+ // Possible default unit found:
+ foreach ($answers as $i => $answer) {
+ if (($answer->min || $answer->max) && ereg(
+ "^(.*)$unit->unit$", $answer->answer, $numreg)) {
+ $answers[$i]->answer = $numreg[1];
+ if (0!=$ukey) {
+ // Make unit default by putting it first:
+ $units[$ukey] = $units[0];
+ $units[0] = $unit;
+ $ukey = 0;
+ }
+ }
+ }
+ }
+ }
+
+ // Strip trailing zeros from multipliers
+ foreach ($units as $i => $unit) {
+ if (ereg('^(.*\\..(.*[^0])?)0+$', $unit->multiplier, $regs1)) {
+ if (ereg('^(.+)\\.0$', $regs1[1], $regs2)) {
+ $units[$i]->multiplier = $regs2[1];
+ } else {
+ $units[$i]->multiplier = $regs1[1];
+ }
+ }
+ }
+
print_heading_with_help(get_string("editingnumerical", "quiz"), "numerical", "quiz");
require("numerical.html");
View
42 mod/quiz/questiontypes/numerical/numerical.html
@@ -98,6 +98,40 @@
<textarea name="feedback[]" rows=2 cols=50 wrap="virtual"><?php p($answers[0]->feedback) ?></textarea>
</TD>
</TR>
+<TR valign=top>
+<TD align=right><P><B><?php print_string("unit", "quiz") ?>:</B></P></TD>
+ <TD>
+ <P><INPUT type="HIDDEN" name="multiplier[]" value="1.0"/>
+ <INPUT align="LEFT" type="text" id="defaultunit" name="unit[]"
+ size="5" value="<?php p($units[0]->unit) ?>"/>
+ <B>(<?php print_string("optional", "quiz") ?>)</B></P>
+ </TD>
+</TR>
+<TR valign=top>
+<td></td>
+<TD align=left><P><B><?php print_string("alternativeunits", "quiz") ?>:</B></P></TD>
+<td></td>
+</TR>
+<?PHP
+for ($i=1; $i<count($units); $i++) {
+ $unit=$units[$i];
+?>
+<TR valign=top>
+<td></td>
+ <TD align=left>
+ <P><B><?php print_string("multiplier", "quiz") ?>:</B>
+ <INPUT type="text" id="<?php p("multiplier$i") ?>" size="10"
+ align="RIGHT" name="multiplier[]"
+ value="<?php p($unit->multiplier) ?>"/>
+ <B>&nbsp;&nbsp;&nbsp;<?php print_string("unit", "quiz") ?>:</B>
+ <INPUT align="LEFT" type="text" id="<?php p("unit$i") ?>"
+ name="unit[]"
+ size="5" value="<?php p($unit->unit) ?>"/></P>
+ </TD>
+</TR>
+<?PHP
+} /// END for
+?>
</TABLE>
<INPUT type="hidden" name=id value="<?php p($question->id) ?>">
@@ -113,11 +147,18 @@
if (correct0.value=='') {
alert('<?php print_string("missingcorrectanswer","quiz") ?>');
return false;
+ } else if (isNaN(correct0.value) && defaultunit.value) {
+ alert('<?php print_string("unitonlyworksfornumericanswers","quiz") ?>');
+ return false;
+ } else if (''!=defaultunit.value && !isNaN(defaultunit.value)) {
+ alert('<?php print_string("unitmustnotbenumeric","quiz") ?>');
+ return false;
} else if (acceptederror0.value=='') {
var correct= parseFloat(correct0.value);
if (!isNaN(correct)) {
min0.value= correct;
max0.value= correct;
+ correct0.value += defaultunit.value;
}
return true;
} else if (isNaN(acceptederror0.value) || isNaN(correct0.value)) {
@@ -128,6 +169,7 @@
var error= Math.abs(acceptederror0.value);
min0.value= correct-error;
max0.value= correct+error;
+ correct0.value += defaultunit.value;
return true;
}
}
View
93 mod/quiz/questiontypes/numerical/questiontype.php
@@ -96,6 +96,45 @@ function save_question_options($question) {
}
}
+ /// Save units
+ /// Make unit records
+ $newunits = array();
+ unset($tmpunit);
+ $tmpunit->question = $question->id;
+ foreach ($question->multiplier as $key => $multiplier) {
+ if ($multiplier && is_numeric($multiplier)) {
+ $tmpunit->multiplier = $multiplier;
+ $tmpunit->unit = trim($question->unit[$key]);
+ $newunits[] = $tmpunit;
+ }
+ }
+ if (1 == count($newunits) && !$newunits[0]->unit) {
+ /// Only default unit and it is empty, so drop it:
+ $newunits = array();
+ }
+ if ($oldunits = get_records('quiz_numerical_units',
+ 'question', $question->id)) {
+ foreach ($oldunits as $unit) {
+ if ($newunit = array_shift($newunits)) {
+ $unit->multiplier = $newunit->multiplier;
+ $unit->unit = $newunit->unit;
+ if (!update_record('quiz_numerical_units', $unit)) {
+ $result->error = "Could not update quiz_numerical_unit $unit->unit";
+ return $result;
+ }
+ } else {
+ delete_records('quiz_numerical_units', 'id', $unit->id);
+ }
+ }
+ }
+ foreach ($newunits as $newunit) {
+ // Create new records for the remaining units:
+ if (!insert_record('quiz_numerical_units', $newunit)) {
+ $result->error = "Unable to insert new unit $newunit->unit";
+ return $result;
+ }
+ }
+
/// Perform sanity checks on fractional grades
if ($maxfraction != 1) {
$maxfraction = $maxfraction * 100;
@@ -109,28 +148,58 @@ function save_question_options($question) {
function grade_response($question, $nameprefix, $addedanswercondition='') {
$result->answers = array();
+ $units = get_records('quiz_numerical_units',
+ 'question', $question->id);
if (isset($question->response[$nameprefix])) {
$response = trim(stripslashes($question->response[$nameprefix]));
- if (!is_numeric($response) and is_numeric(
- $tmp = str_replace(',', '.', $response))) {
- /// I haven't ever needed to make a workaround like this
- /// before, I have no idea why I need to do it now...
- $response = $tmp;
+ // Arrays with 'wild cards':
+ $search = array(' ',',');
+ $replace = array('','.');
+ $responsenum = str_replace($search, $replace, $response);
+ if (empty($units)) {
+ if ('' !== $responsenum && is_numeric($responsenum)) {
+ $responsenum = (float)$responsenum;
+ } else {
+ unset($responsenum); // Answer is not numeric
+ }
+ } else if (ereg(
+ '^(([0-9]+(\\.[0-9]*)?|[.][0-9]+)([eE][-+]?[0-9]+)?)([^0-9].*)?$',
+ $responsenum, $responseparts)) {
+ $responsenum = (float)$responseparts[1];
+ if ($responseparts[5]) {
+ $responseunit = $responseparts[5];
+ } else {
+ $responseunit = '';
+ }
+ $unitidentified = false;
+ foreach ($units as $unit) {
+ if (str_replace($search, $replace, $unit->unit)
+ == $responseunit) {
+ $unitidentified = true;
+ $responsenum /= $unit->multiplier;
+ break;
+ }
+ }
+ if (!$unitidentified) {
+ unset($responsenum); // No unit OK
+ }
+ } else {
+ unset($responsenum); // Answer is not numeric
}
} else {
- $response = NULL;
+ $response = '';
}
$answers = $this->get_answers($question, $addedanswercondition);
foreach ($answers as $answer) {
/// Check if response matches answer...
- if ('' != $response and empty($result->answers)
+ if ('' !== $response and empty($result->answers)
|| $answer->fraction
> $result->answers[$nameprefix]->fraction
and strtolower($response) == strtolower($answer->answer)
- || '' != trim($answer->min)
- && ((float)$response >= (float)$answer->min)
- && ((float)$response <= (float)$answer->max)) {
+ || '' != trim($answer->min) && isset($responsenum)
+ && $responsenum >= (float)$answer->min
+ && $responsenum <= (float)$answer->max) {
$result->answers[$nameprefix] = $answer;
}
}
@@ -143,8 +212,8 @@ function grade_response($question, $nameprefix, $addedanswercondition='') {
/////////////////////////////////////////////////
// For numerical answer we have the policy to
- // set feedback for any response, even it the
- // response does not entitles the student to it.
+ // set feedback for any response, even if the
+ // response does not entitle the student to it.
/////////////////////////////////////////////////
if ('' !== $response and empty($result->answers)
|| empty($result->answers[$nameprefix]->feedback)) {
Please sign in to comment.
Something went wrong with that request. Please try again.