Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

New feature

Unit support for numerical questions
  • Loading branch information...
commit 7a82d193240ab6a3df435ac2c89821864d5d2ee4 1 parent 8c5a95f
authored July 30, 2004
61  mod/quiz/questiontypes/numerical/editquestion.php
@@ -19,6 +19,67 @@
19 19
             $i++;
20 20
         }
21 21
     }
  22
+    $units = array();
  23
+    for ($i=0 ; $i<6 ; $i++) {
  24
+        $units[$i]->multiplier = ''; // Make unit slots, default as blank...
  25
+        $units[$i]->unit = '';
  26
+    }
  27
+    if (!empty($question->id) and $unitsraw = get_records(
  28
+            'quiz_numerical_units', 'question', $question->id)) {
  29
+        /// Find default unit and have it put in the zero slot
  30
+        /// This procedure might be overridden later when
  31
+        /// the unit is stripped form an answer...
  32
+        foreach ($unitsraw as $key => $unit) {
  33
+            if (1.0 == $unit->multiplier) {
  34
+                /// Default unit found:
  35
+                $units[0] = $unit;
  36
+                unset($unitsraw[$key]);
  37
+                break;
  38
+            }
  39
+        }
  40
+        /// Fill remaining answer slots with whatsever left
  41
+        if (!empty($unitsraw)) {
  42
+            $i = 1; // The zero slot got the default unit...
  43
+            foreach ($unitsraw as $unit) {
  44
+                $units[$i] = $unit;
  45
+                $i++;
  46
+            }
  47
+        }
  48
+    } else {
  49
+        $units[0]->multiplier = 1.0;
  50
+    }
  51
+
  52
+    // Strip unit from answers, if they have any:
  53
+    foreach ($units as $key => $unit) {
  54
+        if (1.0 == $unit->multiplier && $unit->unit) {
  55
+            $ukey = $key;
  56
+            // Possible default unit found:
  57
+            foreach ($answers as $i => $answer) {
  58
+                if (($answer->min || $answer->max) && ereg(
  59
+                        "^(.*)$unit->unit$", $answer->answer, $numreg)) {
  60
+                    $answers[$i]->answer = $numreg[1];
  61
+                    if (0!=$ukey) {
  62
+                        // Make unit default by putting it first:
  63
+                        $units[$ukey] = $units[0];
  64
+                        $units[0] = $unit;
  65
+                        $ukey = 0;
  66
+                    }
  67
+                }    
  68
+            }
  69
+        }
  70
+    }
  71
+
  72
+    // Strip trailing zeros from multipliers
  73
+    foreach ($units as $i => $unit) {
  74
+        if (ereg('^(.*\\..(.*[^0])?)0+$', $unit->multiplier, $regs1)) {
  75
+            if (ereg('^(.+)\\.0$', $regs1[1], $regs2)) {
  76
+                $units[$i]->multiplier = $regs2[1];
  77
+            } else {
  78
+                $units[$i]->multiplier = $regs1[1];
  79
+            }
  80
+        }
  81
+    }
  82
+
22 83
     print_heading_with_help(get_string("editingnumerical", "quiz"), "numerical", "quiz");
23 84
     require("numerical.html");
24 85
 
42  mod/quiz/questiontypes/numerical/numerical.html
@@ -98,6 +98,40 @@
98 98
         <textarea name="feedback[]" rows=2 cols=50 wrap="virtual"><?php  p($answers[0]->feedback) ?></textarea>
99 99
     </TD>
100 100
 </TR>
  101
+<TR valign=top>
  102
+<TD align=right><P><B><?php  print_string("unit", "quiz") ?>:</B></P></TD>
  103
+    <TD>
  104
+        <P><INPUT type="HIDDEN" name="multiplier[]" value="1.0"/>
  105
+        <INPUT align="LEFT" type="text" id="defaultunit" name="unit[]"
  106
+                size="5" value="<?php  p($units[0]->unit) ?>"/>
  107
+        <B>(<?php  print_string("optional", "quiz") ?>)</B></P>
  108
+    </TD>
  109
+</TR>
  110
+<TR valign=top>
  111
+<td></td>
  112
+<TD align=left><P><B><?php  print_string("alternativeunits", "quiz") ?>:</B></P></TD>
  113
+<td></td>
  114
+</TR>
  115
+<?PHP
  116
+for ($i=1; $i<count($units); $i++) {
  117
+    $unit=$units[$i];
  118
+?>
  119
+<TR valign=top>
  120
+<td></td>
  121
+    <TD align=left>
  122
+        <P><B><?php  print_string("multiplier", "quiz") ?>:</B>
  123
+        <INPUT type="text" id="<?php  p("multiplier$i") ?>" size="10"
  124
+                align="RIGHT" name="multiplier[]"
  125
+                value="<?php  p($unit->multiplier) ?>"/>
  126
+        <B>&nbsp;&nbsp;&nbsp;<?php  print_string("unit", "quiz") ?>:</B>
  127
+        <INPUT align="LEFT" type="text" id="<?php  p("unit$i") ?>"
  128
+                name="unit[]"
  129
+                size="5" value="<?php  p($unit->unit) ?>"/></P>
  130
+    </TD>
  131
+</TR>
  132
+<?PHP
  133
+} /// END for
  134
+?>
101 135
 </TABLE>
102 136
 
103 137
 <INPUT type="hidden" name=id value="<?php  p($question->id) ?>">
@@ -113,11 +147,18 @@
113 147
         if (correct0.value=='') {
114 148
             alert('<?php  print_string("missingcorrectanswer","quiz") ?>');
115 149
             return false;
  150
+        } else if (isNaN(correct0.value) && defaultunit.value) {
  151
+            alert('<?php  print_string("unitonlyworksfornumericanswers","quiz") ?>');
  152
+            return false;
  153
+        } else if (''!=defaultunit.value && !isNaN(defaultunit.value)) {
  154
+            alert('<?php  print_string("unitmustnotbenumeric","quiz") ?>');
  155
+            return false;
116 156
         } else if (acceptederror0.value=='') {
117 157
             var correct= parseFloat(correct0.value);
118 158
             if (!isNaN(correct)) {
119 159
                 min0.value= correct;
120 160
                 max0.value= correct;
  161
+                correct0.value += defaultunit.value;
121 162
             }
122 163
             return true;
123 164
         } else if (isNaN(acceptederror0.value) || isNaN(correct0.value)) {
@@ -128,6 +169,7 @@
128 169
             var error= Math.abs(acceptederror0.value);
129 170
             min0.value= correct-error;
130 171
             max0.value= correct+error;
  172
+            correct0.value += defaultunit.value;
131 173
             return true;
132 174
         }
133 175
     }
93  mod/quiz/questiontypes/numerical/questiontype.php
@@ -96,6 +96,45 @@ function save_question_options($question) {
96 96
             }
97 97
         }
98 98
 
  99
+        /// Save units
  100
+        /// Make unit records
  101
+        $newunits = array();
  102
+        unset($tmpunit);
  103
+        $tmpunit->question = $question->id;
  104
+        foreach ($question->multiplier as $key => $multiplier) {
  105
+            if ($multiplier && is_numeric($multiplier)) {
  106
+                $tmpunit->multiplier = $multiplier;
  107
+                $tmpunit->unit = trim($question->unit[$key]);
  108
+                $newunits[] = $tmpunit;
  109
+            }
  110
+        }
  111
+        if (1 == count($newunits) && !$newunits[0]->unit) {
  112
+            /// Only default unit and it is empty, so drop it:
  113
+            $newunits = array();
  114
+        }
  115
+        if ($oldunits = get_records('quiz_numerical_units',
  116
+                                    'question', $question->id)) {
  117
+            foreach ($oldunits as $unit) {
  118
+                if ($newunit = array_shift($newunits)) {
  119
+                    $unit->multiplier = $newunit->multiplier;
  120
+                    $unit->unit = $newunit->unit;
  121
+                    if (!update_record('quiz_numerical_units', $unit)) {
  122
+                        $result->error = "Could not update quiz_numerical_unit $unit->unit";
  123
+                        return $result;
  124
+                    }
  125
+                } else {
  126
+                    delete_records('quiz_numerical_units', 'id', $unit->id);
  127
+                }
  128
+            }
  129
+        }
  130
+        foreach ($newunits as $newunit) {
  131
+            // Create new records for the remaining units:
  132
+            if (!insert_record('quiz_numerical_units', $newunit)) {
  133
+                $result->error = "Unable to insert new unit $newunit->unit";
  134
+                return $result;
  135
+            }
  136
+        }
  137
+
99 138
         /// Perform sanity checks on fractional grades
100 139
         if ($maxfraction != 1) {
101 140
             $maxfraction = $maxfraction * 100;
@@ -109,28 +148,58 @@ function save_question_options($question) {
109 148
     function grade_response($question, $nameprefix, $addedanswercondition='') {
110 149
 
111 150
         $result->answers = array();
  151
+        $units = get_records('quiz_numerical_units',
  152
+                             'question', $question->id);
112 153
         if (isset($question->response[$nameprefix])) {
113 154
             $response = trim(stripslashes($question->response[$nameprefix]));
114  
-            if (!is_numeric($response) and is_numeric(
115  
-                    $tmp = str_replace(',', '.', $response))) {
116  
-                /// I haven't ever needed to make a workaround like this
117  
-                /// before, I have no idea why I need to do it now...
118  
-                $response = $tmp;
  155
+            // Arrays with 'wild cards':
  156
+            $search = array(' ',',');
  157
+            $replace = array('','.');
  158
+            $responsenum = str_replace($search, $replace, $response);
  159
+            if (empty($units)) {
  160
+                if ('' !== $responsenum && is_numeric($responsenum)) {
  161
+                    $responsenum = (float)$responsenum;
  162
+                } else {
  163
+                    unset($responsenum); // Answer is not numeric
  164
+                }
  165
+            } else if (ereg(
  166
+                    '^(([0-9]+(\\.[0-9]*)?|[.][0-9]+)([eE][-+]?[0-9]+)?)([^0-9].*)?$',
  167
+                    $responsenum, $responseparts)) {
  168
+                $responsenum = (float)$responseparts[1];
  169
+                if ($responseparts[5]) {
  170
+                    $responseunit = $responseparts[5];
  171
+                } else {
  172
+                    $responseunit = '';
  173
+                }
  174
+                $unitidentified = false;
  175
+                foreach ($units as $unit) {
  176
+                    if (str_replace($search, $replace, $unit->unit)
  177
+                            == $responseunit) {
  178
+                        $unitidentified = true;
  179
+                        $responsenum /= $unit->multiplier;
  180
+                        break;
  181
+                    }
  182
+                }
  183
+                if (!$unitidentified) {
  184
+                    unset($responsenum); // No unit OK
  185
+                }
  186
+            } else {
  187
+                unset($responsenum); // Answer is not numeric
119 188
             }
120 189
        } else {
121  
-            $response = NULL;
  190
+            $response = '';
122 191
         }
123 192
         $answers = $this->get_answers($question, $addedanswercondition);
124 193
         foreach ($answers as $answer) {
125 194
 
126 195
             /// Check if response matches answer...
127  
-            if ('' != $response and empty($result->answers)
  196
+            if ('' !== $response and empty($result->answers)
128 197
                     || $answer->fraction
129 198
                      > $result->answers[$nameprefix]->fraction
130 199
                     and strtolower($response) == strtolower($answer->answer)
131  
-                    || '' != trim($answer->min)
132  
-                    && ((float)$response >= (float)$answer->min)
133  
-                    && ((float)$response <= (float)$answer->max)) {
  200
+                    || '' != trim($answer->min) && isset($responsenum)
  201
+                    && $responsenum >= (float)$answer->min
  202
+                    && $responsenum <= (float)$answer->max) {
134 203
                 $result->answers[$nameprefix] = $answer;
135 204
             }
136 205
         }
@@ -143,8 +212,8 @@ function grade_response($question, $nameprefix, $addedanswercondition='') {
143 212
 
144 213
         /////////////////////////////////////////////////
145 214
         // For numerical answer we have the policy to 
146  
-        // set feedback for any response, even it the
147  
-        // response does not entitles the student to it.
  215
+        // set feedback for any response, even if the
  216
+        // response does not entitle the student to it.
148 217
         /////////////////////////////////////////////////
149 218
         if ('' !== $response and empty($result->answers)
150 219
                 || empty($result->answers[$nameprefix]->feedback)) {

0 notes on commit 7a82d19

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