From: kaipe Date: Fri, 30 Jul 2004 14:43:08 +0000 (+0000) Subject: New feature X-Git-Url: http://git.mjollnir.org/gw?a=commitdiff_plain;h=7a82d193240ab6a3df435ac2c89821864d5d2ee4;p=moodle.git New feature Unit support for numerical questions --- diff --git a/mod/quiz/questiontypes/numerical/editquestion.php b/mod/quiz/questiontypes/numerical/editquestion.php index 527b06f3e4..72c977627d 100644 --- a/mod/quiz/questiontypes/numerical/editquestion.php +++ b/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"); diff --git a/mod/quiz/questiontypes/numerical/numerical.html b/mod/quiz/questiontypes/numerical/numerical.html index 31daec18fd..68aaa1aa38 100644 --- a/mod/quiz/questiontypes/numerical/numerical.html +++ b/mod/quiz/questiontypes/numerical/numerical.html @@ -98,6 +98,40 @@ + +

:

+ +

+ + ()

+ + + + +

:

+ + + + + + +

: + " size="10" + align="RIGHT" name="multiplier[]" + value="multiplier) ?>"/> +    : + " + name="unit[]" + size="5" value="unit) ?>"/>

+ + + @@ -113,11 +147,18 @@ function determineMinAndMax() { if (correct0.value=='') { alert(''); return false; + } else if (isNaN(correct0.value) && defaultunit.value) { + alert(''); + return false; + } else if (''!=defaultunit.value && !isNaN(defaultunit.value)) { + alert(''); + 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 @@ function determineMinAndMax() { var error= Math.abs(acceptederror0.value); min0.value= correct-error; max0.value= correct+error; + correct0.value += defaultunit.value; return true; } } diff --git a/mod/quiz/questiontypes/numerical/questiontype.php b/mod/quiz/questiontypes/numerical/questiontype.php index 77552108e5..cc3ddb763f 100644 --- a/mod/quiz/questiontypes/numerical/questiontype.php +++ b/mod/quiz/questiontypes/numerical/questiontype.php @@ -96,6 +96,45 @@ class quiz_numerical_qtype extends quiz_shortanswer_qtype { } } + /// 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 @@ class quiz_numerical_qtype extends quiz_shortanswer_qtype { 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 @@ class quiz_numerical_qtype extends quiz_shortanswer_qtype { ///////////////////////////////////////////////// // 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)) {