]> git.mjollnir.org Git - moodle.git/commitdiff
New feature
authorkaipe <kaipe>
Fri, 30 Jul 2004 14:43:08 +0000 (14:43 +0000)
committerkaipe <kaipe>
Fri, 30 Jul 2004 14:43:08 +0000 (14:43 +0000)
Unit support for numerical questions

mod/quiz/questiontypes/numerical/editquestion.php
mod/quiz/questiontypes/numerical/numerical.html
mod/quiz/questiontypes/numerical/questiontype.php

index 527b06f3e4cce2402762144b17c721183ff5dd48..72c977627dd1119a97843c71dfdcb0bb27acea67 100644 (file)
             $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");
 
index 31daec18fd9b23471a884ec44df0d836626ff19f..68aaa1aa383b7408fbf7b62f1919bd0276a1e89e 100644 (file)
         <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 @@ function determineMinAndMax() {
         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 @@ function determineMinAndMax() {
             var error= Math.abs(acceptederror0.value);
             min0.value= correct-error;
             max0.value= correct+error;
+            correct0.value += defaultunit.value;
             return true;
         }
     }
index 77552108e5f93b0d36549811b16821b7d55d452d..cc3ddb763fdcbd99cfe449ad7857c5acfda9ba04 100644 (file)
@@ -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)) {