Merge branch 'MDL-33105' of https://github.com/ppichet/moodle
authorDan Poltawski <dan@moodle.com>
Tue, 18 Jun 2013 02:35:47 +0000 (10:35 +0800)
committerDan Poltawski <dan@moodle.com>
Tue, 18 Jun 2013 02:35:47 +0000 (10:35 +0800)
question/type/multianswer/edit_multianswer_form.php
question/type/multianswer/questiontype.php
question/type/numerical/edit_numerical_form.php
question/type/numerical/question.php
question/type/numerical/questiontype.php
question/type/numerical/tests/answerprocessor_test.php

index cd792f7..1eafd99 100644 (file)
@@ -366,8 +366,12 @@ class qtype_multianswer_edit_form extends question_edit_form {
                         }
                         foreach ($subquestion->answer as $key => $answer) {
                             if ($subquestion->qtype == 'numerical' && $key == 0) {
-                                $default_values[$prefix.'tolerance['.$key.']'] =
+                                if (isset($subquestion->tolerance[0])) {
+                                    $default_values[$prefix.'tolerance['.$key.']'] =
                                         $subquestion->tolerance[0];
+                                } else {
+                                    $default_values[$prefix.'tolerance['.$key.']'] = 0;
+                                }
                             }
                             if (is_array($answer)) {
                                 $answer = $answer['text'];
@@ -472,10 +476,11 @@ class qtype_multianswer_edit_form extends question_edit_form {
                         $trimmedanswer = trim($answer);
                         if ($trimmedanswer !== '') {
                             $answercount++;
-                            if ($subquestion->qtype == 'numerical' &&
-                                    !($this->is_valid_number($trimmedanswer) || $trimmedanswer == '*')) {
-                                $errors[$prefix.'answer['.$key.']'] =
+                            if ($subquestion->qtype == 'numerical' && $trimmedanswer != '*') {
+                                if (!$this->is_valid_number($trimmedanswer)) {
+                                    $errors[$prefix.'answer['.$key.']'] =
                                         get_string('answermustbenumberorstar', 'qtype_numerical');
+                                }
                             }
                             if ($subquestion->fraction[$key] == 1) {
                                 $maxgrade = true;
index 5df9f2c..acd9df0 100644 (file)
@@ -262,9 +262,9 @@ define('ANSWER_ALTERNATIVE_REGEX_FEEDBACK', 5);
 // NUMBER_FORMATED_ALTERNATIVE_ANSWER_REGEX is used
 // for identifying numerical answers in ANSWER_ALTERNATIVE_REGEX_ANSWER.
 define('NUMBER_REGEX',
-        '-?(([0-9]+[.,]?[0-9]*|[.,][0-9]+)([eE][-+]?[0-9]+)?)');
+        '-?(([0-9]+[., ]?[., 0-9]*|[., ][0-9]+)([eE][-+]?[0-9]+)?)');
 define('NUMERICAL_ALTERNATIVE_REGEX',
-        '^(' . NUMBER_REGEX . ')(:' . NUMBER_REGEX . ')?$');
+        '^(' . NUMBER_REGEX . ')([ ]*:' . NUMBER_REGEX . ')?$');
 
 // Parenthesis positions for NUMERICAL_FORMATED_ALTERNATIVE_ANSWER_REGEX.
 define('NUMERICAL_CORRECT_ANSWER', 1);
index 2554177..488e599 100644 (file)
@@ -59,7 +59,7 @@ class qtype_numerical_edit_form extends question_edit_form {
 
         $tolerance = $mform->createElement('text', 'tolerance',
                 get_string('answererror', 'qtype_numerical'), array('size' => 15));
-        $repeatedoptions['tolerance']['type'] = PARAM_FLOAT;
+        $repeatedoptions['tolerance']['type'] = PARAM_RAW;// This parameter will be validated in validation().
         $repeatedoptions['tolerance']['default'] = 0;
         $elements = $repeated[0]->getElements();
         $elements[0]->setSize(15);
@@ -293,7 +293,7 @@ class qtype_numerical_edit_form extends question_edit_form {
                 if ($data['fraction'][$key] == 1) {
                     $maxgrade = true;
                 }
-                if ($answer !== '*' && !is_numeric($data['tolerance'][$key])) {
+                if ($answer !== '*' && !$this->is_valid_number($data['tolerance'][$key])) {
                     $errors['answeroptions['.$key.']'] =
                             get_string('xmustbenumeric', 'qtype_numerical',
                                 get_string('acceptederror', 'qtype_numerical'));
index 8df2ce9..2e39db1 100644 (file)
@@ -106,10 +106,6 @@ class qtype_numerical_question extends question_graded_automatically {
             return false;
         }
 
-        if ($this->ap->contains_thousands_seaparator($response['answer'])) {
-            return false;
-        }
-
         return true;
     }
 
@@ -131,11 +127,6 @@ class qtype_numerical_question extends question_graded_automatically {
             return get_string('unitnotselected', 'qtype_numerical');
         }
 
-        if ($this->ap->contains_thousands_seaparator($response['answer'])) {
-            return get_string('pleaseenteranswerwithoutthousandssep', 'qtype_numerical',
-                    $this->ap->get_separator());
-        }
-
         return '';
     }
 
index 2d290aa..04ca91f 100644 (file)
@@ -632,17 +632,35 @@ class qtype_numerical_answer_processor {
         // Strip spaces (which may be thousands separators) and change other forms
         // of writing e to e.
         $response = str_replace(' ', '', $response);
+        // Strip thousand separators like half space.
+        if (!in_array($this->thousandssep, array(',', '.', ' '))) {
+            if (strpos($response, $this->thousandssep) !== false) {
+                $response = str_replace($this->thousandssep, '', $response);
+            }
+        }
         $response = preg_replace('~(?:e|E|(?:x|\*|×)10(?:\^|\*\*))([+-]?\d+)~', 'e$1', $response);
-
-        // If a . is present or there are multiple , (i.e. 2,456,789 ) assume ,
-        // is a thouseands separator, and strip it, else assume it is a decimal
-        // separator, and change it to ..
-        if (strpos($response, '.') !== false || substr_count($response, ',') > 1) {
-            $response = str_replace(',', '', $response);
-        } else {
-            $response = str_replace(',', '.', $response);
+        // Dot . is mostly a decimal separator there a few exceptions where it is a thousand separator
+        // If a . is present or there are multiple , (i.e. 2,456,789 ) assume,
+        // is a thousands separator and strip it or else assume it is a decimal
+        // separator and change it to .
+        // if only one and it is , then change to .
+        if (substr_count($response, ',')+ substr_count($response, '.') == 1 ) {
+            if (strpos($response, ',') !== false) {
+                $response = str_replace(',', '.', $response);
+            }
+        } else if (substr_count($response, ',') == 1 && substr_count($response, '.') == 1) {
+            if (strpos($response, '.') > strpos($response, ',')) { // Then , is thousand.
+                $response = str_replace(',', '', $response);
+            } else {
+                $response = str_replace('.', '', $response);
+                $response = str_replace(',', '.', $response);
+            }
+        } else if (substr_count($response, ',') > 1) {
+              $response = str_replace(',', '', $response);
+        } else if (substr_count($response, '.') > 1) {
+              $response = str_replace('.', '', $response);
+              $response = str_replace(',', '.', $response);
         }
-
         $regex = '[+-]?(?:\d+(?:\\.\d*)?|\\.\d+)(?:e[-+]?\d+)?';
         if ($this->unitsbefore) {
             $regex = "/$regex$/";
index f27bb2f..000df7a 100644 (file)
@@ -131,9 +131,36 @@ class qtype_numerical_answer_processor_test extends advanced_testcase {
         $ap = new qtype_numerical_answer_processor(array(), false, ',', ' ');
 
         $this->assertEquals(array(-1000, '', null), $ap->apply_units('-1 000'));
+        $this->assertEquals(array(-1000000, '', null), $ap->apply_units('-1 000 000'));
+        $this->assertEquals(array(-1000000, '', null), $ap->apply_units('-1.000.000'));
+        $this->assertEquals(array(-1000000, '', null), $ap->apply_units('-1,000,000'));
+        $this->assertEquals(array(-1000.1, '', null), $ap->apply_units('-1000,1'));
+        $this->assertEquals(array(-1000.1, '', null), $ap->apply_units('-1.000,1'));
+        $this->assertEquals(array(-1000.1, '', null), $ap->apply_units('-1,000.1'));
         $this->assertEquals(array(3.14159, '', null), $ap->apply_units('3,14159'));
     }
 
+    public function test_deutsch_style() {
+        $ap = new qtype_numerical_answer_processor(array(), false, ',', '.');
+
+        $this->assertEquals(array(-1000, '', null), $ap->apply_units('-1 000'));
+        $this->assertEquals(array(-1000000, '', null), $ap->apply_units('-1 000 000'));
+        $this->assertEquals(array(-1000000, '', null), $ap->apply_units('-1.000.000'));
+        $this->assertEquals(array(-1000000, '', null), $ap->apply_units('-1.000.000,'));
+        $this->assertEquals(array(-1000.1, '', null), $ap->apply_units('-1000,1'));
+        $this->assertEquals(array(-1000.1, '', null), $ap->apply_units('-1.000,1'));
+        $this->assertEquals(array(-1000.1, '', null), $ap->apply_units('-1,000.1'));
+        $this->assertEquals(array(3.14159, '', null), $ap->apply_units('3.14159'));
+        $this->assertEquals(array(3.14159, '', null), $ap->apply_units('3,14159'));
+    }
+    public function test_unusual_thousandseps_style() {
+        // Test with ' as thousandsep as used for currency in Swizterland.
+        $ap = new qtype_numerical_answer_processor(array(), false, '.', "'");
+
+        $this->assertEquals(array(-1000, '', null), $ap->apply_units("-1'000"));
+        $this->assertEquals(array(-1000000, '', null), $ap->apply_units("'-1'000'000"));
+        $this->assertEquals(array(-1000000, '', null), $ap->apply_units("-1'000'000."));
+    }
     public function test_percent() {
         $ap = new qtype_numerical_answer_processor(array('%' => 100), false, '.', ',');