Note:

If you want to create a new page for developers, you should create it on the Moodle Developer Resource site.

The Question Engine 2 structure allows implementation of new features for numerical question types ( numerical and calculated). This page describes a possible implementation and its rationale.

The text should be readed as a personal summary of the work in progress and not as a textbook on computer language and real numbers representation.

It is related to the forum discussion http://moodle.org/mod/forum/discuss.php?d=172211#p755927


Numbers as written by human and readed by computer language

The main feature of numerical question type is to ask the student to give a numerical answer i.e. a number. Most often this means a numerical value that is not an integer ( dates are a current example of integer value response) but a real number which value is expressed most often as a decimal number i.e 1.234 .

Computer languages ( i.e PHP used in Moodle) store real numbers in a different way than human do (decimal part and exponent similar to 1.234 E00) and humans do not expressed real nmumbers in an universal format.

The separator between the unit and the decimal fraction is often either a . or a ,  
1.234   1,234

Furthermore to help reading large numbers, most language add another separator for thousands often space or , if it is not used already as unit separator.

123 456.78     123,456.78   123 456,78 

PHP as a computer language use space to separate the language components so cannot use space as a thousand separator.

, is also used to separate variables so PHP use a simpler syntax 123456.78.

As this is stored in the computer as 2 parts (number and exponent).

1.2345678+E05 will be a structure that is well recognized by a computer language as PHP.

Setting the answer when creating the question

In Moodle 1,9 and 2,0 in the edit_numerical_form.php, the number enter by the teacher (although student could be allowed to create question, I will use teacher for text clarity) must be conform to the PHP syntax (no thousand separator or space and . as decimal separator. E syntax is allowed.

                if (!(is_numeric($trimmedanswer) || $trimmedanswer == '*')) {
                   $errors['answer[' . $key . ']'] =
                           get_string('answermustbenumberorstar', 'qtype_numerical');
               }

So the teacher must know the PHP specific number syntax.

In the numerical/questiontype.php function save_question_options($question) there is an additional verification mostly for numerical questions imported through various formats or inside a Cloze numerical multianswer question.

            
               $answer->answer = $this->apply_unit($answerdata, $units);
               if ($answer->answer === false) {
                   $result->notice = get_string('invalidnumericanswer', 'quiz');
               }
   

the Moodle 2,0 apply_unit

   
   /**
    * Checks if the $rawresponse has a unit and applys it if appropriate.
    *
    * @param string $rawresponse  The response string to be converted to a float.
    * @param array $units         An array with the defined units, where the
    *                             unit is the key and the multiplier the value.
    * @return float               The rawresponse with the unit taken into
    *                             account as a float.
    */
   function apply_unit($rawresponse, $units) {
       // Make units more useful
       $tmpunits = array();
       foreach ($units as $unit) {
           $tmpunits[$unit->unit] = $unit->multiplier;
       }
       // remove spaces and normalise decimal places.
       $rawresponse = trim($rawresponse) ;
       $search  = array(' ', ',');
       // test if a . is present or there are multiple , (i.e. 2,456,789 ) so that we don't need spaces and ,
       if ( strpos($rawresponse,'.' ) !== false || substr_count($rawresponse,',') > 1 ) {
           $replace = array(, );
       }else { // remove spaces and normalise , to a . .
           $replace = array(, '.');
       }
       $rawresponse = str_replace($search, $replace, $rawresponse);


       // Apply any unit that is present.
       if (ereg('^([+-]?([0-9]+(\\.[0-9]*)?|\\.[0-9]+)([eE][-+]?[0-9]+)?)([^0-9].*)?$',
               $rawresponse, $responseparts)) {

echo"

responseparts

";print_r($responseparts) ;echo"

";

           if (!empty($responseparts[5])) {
               if (isset($tmpunits[$responseparts[5]])) {
                   // Valid number with unit.
                   return (float)$responseparts[1] / $tmpunits[$responseparts[5]];
               } else {
                   // Valid number with invalid unit. Must be wrong.
                   return false;
               }
           } else {
               // Valid number without unit.
               return (float)$responseparts[1];
           }
       }
       // Invalid number. Must be wrong.
       return false;
   }

The 2,0 apply_unit allows more number formats than the test in the editing form.

  • regular numbers 13500.67 : 13 500.67 : 13500,67: 13 500,67
  • if you use , as thousand separator *always* put the decimal . as in 13,500.67 : 13,500.
  • for exponent form, say 1.350067 * 104, use 1.350067 E4 : 1.350067 E04 ';

The 1,9 apply_unit is more restrictive as it does not support , as decimal separator.

More formats were allowed in 2,0 as the main objective in a numerical question is the numerical value. More about this further in the page (todo)

Retrieving the numerical value from the student response

As the function apply_unit() is also used to analyze the student response the number formats allowed are the same as the formats allowed for NON edit_numerical_form.php numerical i.e. import or Cloze.

However to help students know what are the number formats allowed an help icon aside the number text input element is shown on Moodle 2,0 numerical questions created either by edit_numerical_form.php or import but not for Cloze.

Grading the numerical format used by the student to express the numerical value

Pierre Pichet 21:24, 1 May 2011 (WST)