Merge branch 'MDL-27418' of git://github.com/timhunt/moodle

This commit is contained in:
Eloy Lafuente (stronk7)
2011-06-29 23:51:33 +02:00
12 changed files with 277 additions and 70 deletions
+1 -1
View File
@@ -207,7 +207,7 @@ class qtype_calculated_qe2_attempt_updater extends question_qtype_attempt_update
* @param $x
*/
public function format_float($x, $length = null, $format = null) {
if (!is_null($format) && !is_null($format)) {
if (!is_null($length) && !is_null($format)) {
if ($format == 1) {
// Decimal places.
$x = sprintf('%.' . $length . 'F', $x);
+1 -1
View File
@@ -310,7 +310,7 @@ class qtype_calculated_variable_substituter {
* @param $x
*/
public function format_float($x, $length = null, $format = null) {
if (!is_null($format) && !is_null($format)) {
if (!is_null($length) && !is_null($format)) {
if ($format == 1) {
// Decimal places.
$x = sprintf('%.' . $length . 'F', $x);
@@ -231,7 +231,7 @@ class qtype_calculatedmulti_qe2_attempt_updater extends question_qtype_attempt_u
* @param $x
*/
public function format_float($x, $length = null, $format = null) {
if (!is_null($format) && !is_null($format)) {
if (!is_null($length) && !is_null($format)) {
if ($format == 1) {
// Decimal places.
$x = sprintf('%.' . $length . 'F', $x);
+2
View File
@@ -168,6 +168,8 @@ class qtype_multianswer_textfield_renderer extends qtype_multianswer_subq_render
$response = $qa->get_last_qt_var($fieldname);
if ($subq->qtype->name() == 'shortanswer') {
$matchinganswer = $subq->get_matching_answer(array('answer' => $response));
} else if ($subq->qtype->name() == 'numerical') {
$matchinganswer = $subq->get_matching_answer($response, 1);
} else {
$matchinganswer = $subq->get_matching_answer($response);
}
@@ -26,6 +26,7 @@
defined('MOODLE_INTERNAL') || die();
require_once($CFG->dirroot . '/question/type/edit_question_form.php');
require_once($CFG->dirroot . '/question/type/numerical/questiontype.php');
@@ -36,6 +37,7 @@ require_once($CFG->dirroot . '/question/type/numerical/questiontype.php');
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class qtype_numerical_edit_form extends question_edit_form {
protected $ap = null;
protected function definition_inner($mform) {
$this->add_per_answer_fields($mform, get_string('answerno', 'qtype_numerical', '{no}'),
@@ -54,6 +56,7 @@ class qtype_numerical_edit_form extends question_edit_form {
$tolerance = $mform->createElement('text', 'tolerance',
get_string('acceptederror', 'qtype_numerical'));
$repeatedoptions['tolerance']['type'] = PARAM_NUMBER;
$repeatedoptions['tolerance']['default'] = 0;
array_splice($repeated, 3, 0, array($tolerance));
$repeated[1]->setSize(10);
@@ -256,7 +259,7 @@ class qtype_numerical_edit_form extends question_edit_form {
if ($trimmedanswer != '') {
$answercount++;
if (!$this->is_valid_answer($trimmedanswer, $data)) {
$errors['answer[' . $key . ']'] = $this->valid_answer_message();
$errors['answer[' . $key . ']'] = $this->valid_answer_message($trimmedanswer);
}
if ($data['fraction'][$key] == 1) {
$maxgrade = true;
@@ -267,7 +270,7 @@ class qtype_numerical_edit_form extends question_edit_form {
}
} else if ($data['fraction'][$key] != 0 ||
!html_is_blank($data['feedback'][$key]['text'])) {
$errors['answer[' . $key . ']'] = $this->valid_answer_message();
$errors['answer[' . $key . ']'] = $this->valid_answer_message($trimmedanswer);
$answercount++;
}
}
@@ -277,6 +280,8 @@ class qtype_numerical_edit_form extends question_edit_form {
if ($maxgrade == false) {
$errors['fraction[0]'] = get_string('fractionsnomax', 'question');
}
return $errors;
}
/**
@@ -286,7 +291,22 @@ class qtype_numerical_edit_form extends question_edit_form {
* @return bool whether this is a valid answer.
*/
protected function is_valid_answer($answer, $data) {
return $answer == '*' || is_numeric($answer);
return $answer == '*' || $this->is_valid_number($x);
}
/**
* Validate that a string is a nubmer formatted correctly for the current locale.
* @param string $x a string
* @return bool whether $x is a number that the numerical question type can interpret.
*/
protected function is_valid_number($x) {
if (is_null($this->ap)) {
$this->ap = new qtype_numerical_answer_processor(array());
}
list($value, $unit) = $this->ap->apply_units($x);
return !is_null($value) && !$unit;
}
/**
@@ -27,7 +27,7 @@ $string['acceptederror'] = 'Accepted error';
$string['addingnumerical'] = 'Adding a Numerical question';
$string['addmoreanswerblanks'] = 'Blanks for {no} More Answers';
$string['addmoreunitblanks'] = 'Blanks for {no} More Units';
$string['answermustbenumberorstar'] = 'The answer must be a number, or \'*\'.';
$string['answermustbenumberorstar'] = 'The answer must be a number, for example -1.234 or 3e8, or \'*\'.';
$string['answerno'] = 'Answer {$a}';
$string['decfractionofquestiongrade'] = 'as a fraction (0-1) of the question grade';
$string['decfractionofresponsegrade'] = 'as a fraction (0-1) of the response grade';
@@ -64,6 +64,7 @@ $string['nominal'] = 'Nominal';
$string['onlynumerical'] = 'Units are not used at all. Only the numerical value is graded.';
$string['oneunitshown'] = 'Unit 1 is automatically displayed beside the answer box.';
$string['pleaseenterananswer'] = 'Please enter an answer.';
$string['pleaseenteranswerwithoutthousandssep'] = 'Please enter your answer without using the thousand separator ({$a}).';
$string['relative'] = 'Relative';
$string['rightexample'] = 'on the right, for example 1.00cm or 1.00km';
$string['selectunits'] = 'Select units';
+48 -13
View File
@@ -109,6 +109,10 @@ class qtype_numerical_question extends question_graded_automatically {
return false;
}
if ($this->ap->contains_thousands_seaparator($response['answer'])) {
return false;
}
return true;
}
@@ -130,6 +134,11 @@ 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 '';
}
@@ -153,7 +162,7 @@ class qtype_numerical_question extends question_graded_automatically {
return array();
}
$response = array('answer' => $answer->answer);
$response = array('answer' => str_replace('.', $this->ap->get_point(), $answer->answer));
if ($this->has_separate_unit_field()) {
$response['unit'] = $this->ap->get_default_unit();
@@ -168,12 +177,22 @@ class qtype_numerical_question extends question_graded_automatically {
* Get an answer that contains the feedback and fraction that should be
* awarded for this resonse.
* @param number $value the numerical value of a response.
* @param number $multiplier for the unit the student gave, if any. When no
* unit was given, or an unrecognised unit was given, $multiplier will be null.
* @return question_answer the matching answer.
*/
public function get_matching_answer($value) {
public function get_matching_answer($value, $multiplier) {
if (!is_null($multiplier)) {
$scaledvalue = $value * $multiplier;
} else {
$scaledvalue = $value;
}
foreach ($this->answers as $aid => $answer) {
if ($answer->within_tolerance($value)) {
$answer->id = $aid;
if ($answer->within_tolerance($scaledvalue)) {
$answer->unitisright = !is_null($multiplier);
return $answer;
} else if ($answer->within_tolerance($value)) {
$answer->unitisright = false;
return $answer;
}
}
@@ -190,8 +209,14 @@ class qtype_numerical_question extends question_graded_automatically {
return null;
}
public function apply_unit_penalty($fraction, $unit) {
if (!empty($unit) && $this->ap->is_known_unit($unit)) {
/**
* Adjust the fraction based on whether the unit was correct.
* @param number $fraction
* @param bool $unitisright
* @return number
*/
public function apply_unit_penalty($fraction, $unitisright) {
if ($unitisright) {
return $fraction;
}
@@ -209,13 +234,15 @@ class qtype_numerical_question extends question_graded_automatically {
} else {
$selectedunit = null;
}
list($value, $unit) = $this->ap->apply_units($response['answer'], $selectedunit);
$answer = $this->get_matching_answer($value);
list($value, $unit, $multiplier) = $this->ap->apply_units(
$response['answer'], $selectedunit);
$answer = $this->get_matching_answer($value, $multiplier);
if (!$answer) {
return array(0, question_state::$gradedwrong);
}
$fraction = $this->apply_unit_penalty($answer->fraction, $unit);
$fraction = $this->apply_unit_penalty($answer->fraction, $answer->unitisright);
return array($fraction, question_state::graded_state_for_fraction($fraction));
}
@@ -229,8 +256,8 @@ class qtype_numerical_question extends question_graded_automatically {
} else {
$selectedunit = null;
}
list($value, $unit) = $this->ap->apply_units($response['answer'], $selectedunit);
$ans = $this->get_matching_answer($value);
list($value, $unit, $multiplier) = $this->ap->apply_units($response['answer'], $selectedunit);
$ans = $this->get_matching_answer($value, $multiplier);
if (!$ans) {
return array($this->id => question_classified_response::no_response());
}
@@ -242,14 +269,22 @@ class qtype_numerical_question extends question_graded_automatically {
return array($this->id => new question_classified_response($ans->id,
$resp,
$this->apply_unit_penalty($ans->fraction, $unit)));
$this->apply_unit_penalty($ans->fraction, $ans->unitisright)));
}
public function check_file_access($qa, $options, $component, $filearea, $args,
$forcedownload) {
if ($component == 'question' && $filearea == 'answerfeedback') {
$question = $qa->get_question();
$currentanswer = $qa->get_last_qt_var('answer');
$answer = $qa->get_question()->get_matching_answer(array('answer' => $currentanswer));
if ($this->has_separate_unit_field()) {
$selectedunit = $qa->get_last_qt_var('unit');
} else {
$selectedunit = null;
}
list($value, $unit, $multiplier) = $question->ap->apply_units(
$currentanswer, $selectedunit);
$answer = $question->get_matching_answer($value, $multiplier);
$answerid = reset($args); // itemid is answer id.
return $options->feedback && $answerid == $answer->id;
+54 -14
View File
@@ -449,7 +449,10 @@ class qtype_numerical extends question_type {
*/
public function apply_unit($rawresponse, $units, $unitsleft) {
$ap = $this->make_answer_processor($units, $unitsleft);
list($value, $unit) = $ap->apply_units($rawresponse);
list($value, $unit, $multiplier) = $ap->apply_units($rawresponse);
if (!is_null($multiplier)) {
$value *= $multiplier;
}
return $value;
}
@@ -524,6 +527,19 @@ class qtype_numerical_answer_processor {
return $this->thousandssep;
}
/**
* @return book If the student's response contains a '.' or a ',' that
* matches the thousands separator in the current locale. In this case, the
* parsing in apply_unit can give a result that the student did not expect.
*/
public function contains_thousands_seaparator($value) {
if (!in_array($this->thousandssep, array('.', ','))) {
return false;
}
return strpos($value, $this->thousandssep) !== false;
}
/**
* Create the regular expression that {@link parse_response()} requires.
* @return string
@@ -550,6 +566,11 @@ class qtype_numerical_answer_processor {
}
/**
* This method can be used for more locale-strict parsing of repsonses. At the
* moment we don't use it, and instead use the more lax parsing in apply_units.
* This is just a note that this funciton was used in the past, so if you are
* intersted, look through version control history.
*
* Take a string which is a number with or without a decimal point and exponent,
* and possibly followed by one of the units, and split it into bits.
* @param string $response a value, optionally with a unit.
@@ -585,25 +606,44 @@ class qtype_numerical_answer_processor {
}
/**
* Takes a number in localised form, that is, using the decsep and thousandssep
* defined in the lanuage pack, and possibly with a unit after it. It separates
* off the unit, if present, and converts to the default unit, by using the
* given unit multiplier.
* Takes a number in almost any localised form, and possibly with a unit
* after it. It separates off the unit, if present, and converts to the
* default unit, by using the given unit multiplier.
*
* @param string $response a value, optionally with a unit.
* @return array(numeric, sting) the value with the unit stripped, and normalised
* by the unit multiplier, if any, and the unit string, for reference.
*/
public function apply_units($response, $separateunit = null) {
list($beforepoint, $decimals, $exponent, $unit) = $this->parse_response($response);
// Strip spaces (which may be thousands separators) and change other forms
// of writing e to e.
$response = str_replace(' ', '', $response);
$response = preg_replace('~(?:e|E|(?:x|\*|×)10(?:\^|\*\*))([+-]?\d+)~', 'e$1', $response);
if (is_null($beforepoint)) {
return array(null, null);
// 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);
}
$numberstring = $beforepoint . '.' . $decimals;
if ($exponent) {
$numberstring .= 'e' . $exponent;
$regex = '[+-]?(?:\d+(?:\\.\d*)?|\\.\d+)(?:e[-+]?\d+)?';
if ($this->unitsbefore) {
$regex = "/$regex$/";
} else {
$regex = "/^$regex/";
}
if (!preg_match($regex, $response, $matches)) {
return array(null, null, null);
}
$numberstring = $matches[0];
if ($this->unitsbefore) {
$unit = substr($response, 0, -strlen($numberstring));
} else {
$unit = substr($response, strlen($numberstring));
}
if (!is_null($separateunit)) {
@@ -611,12 +651,12 @@ class qtype_numerical_answer_processor {
}
if ($unit && $this->is_known_unit($unit)) {
$value = $numberstring / $this->units[$unit];
$multiplier = 1 / $this->units[$unit];
} else {
$value = $numberstring * 1;
$multiplier = null;
}
return array($value, $unit);
return array($numberstring + 0, $unit, $multiplier); // + 0 to convert to number.
}
/**
+7 -6
View File
@@ -57,10 +57,11 @@ class qtype_numerical_renderer extends qtype_renderer {
$feedbackimg = '';
if ($options->correctness) {
list($value, $unit) = $question->ap->apply_units($currentanswer, $selectedunit);
$answer = $question->get_matching_answer($value);
list($value, $unit, $multiplier) = $question->ap->apply_units(
$currentanswer, $selectedunit);
$answer = $question->get_matching_answer($value, $multiplier);
if ($answer) {
$fraction = $question->apply_unit_penalty($answer->fraction, $unit);
$fraction = $question->apply_unit_penalty($answer->fraction, $answer->unitisright);
} else {
$fraction = 0;
}
@@ -140,9 +141,9 @@ class qtype_numerical_renderer extends qtype_renderer {
} else {
$selectedunit = null;
}
list($value, $unit) = $question->ap->apply_units(
list($value, $unit, $multiplier) = $question->ap->apply_units(
$qa->get_last_qt_var('answer'), $selectedunit);
$answer = $question->get_matching_answer($value);
$answer = $question->get_matching_answer($value, $multiplier);
if ($answer && $answer->feedback) {
$feedback = $question->format_text($answer->feedback, $answer->feedbackformat,
@@ -165,7 +166,7 @@ class qtype_numerical_renderer extends qtype_renderer {
return '';
}
$response = $answer->answer;
$response = str_replace('.', $question->ap->get_point(), $answer->answer);
if ($question->unitdisplay != qtype_numerical::UNITNONE) {
$response = $question->ap->add_unit($response);
}
@@ -82,15 +82,20 @@ class qtype_numerical_answer_processor_test extends UnitTestCase {
$this->assertEqual(array(null, null, null, null), $ap->parse_response(','));
}
protected function verify_value_and_unit($exectedval, $expectedunit,
protected function verify_value_and_unit($exectedval, $expectedunit, $expectedmultiplier,
qtype_numerical_answer_processor $ap, $input, $separateunit = null) {
list($val, $unit) = $ap->apply_units($input, $separateunit);
list($val, $unit, $multiplier) = $ap->apply_units($input, $separateunit);
if (is_null($exectedval)) {
$this->assertNull($val);
} else {
$this->assertWithinMargin($exectedval, $val, 0.0001);
}
$this->assertEqual($expectedunit, $unit);
if (is_null($expectedmultiplier)) {
$this->assertNull($multiplier);
} else {
$this->assertWithinMargin($expectedmultiplier, $multiplier, 0.0001);
}
}
public function test_apply_units() {
@@ -98,13 +103,13 @@ class qtype_numerical_answer_processor_test extends UnitTestCase {
array('m/s' => 1, 'c' => 3.3356409519815E-9,
'mph' => 2.2369362920544), false, '.', ',');
$this->verify_value_and_unit(3e8, 'm/s', $ap, '3x10^8 m/s');
$this->verify_value_and_unit(3e8, '', $ap, '3x10^8');
$this->verify_value_and_unit(299792458, 'c', $ap, '1c');
$this->verify_value_and_unit(0.44704, 'mph', $ap, '0001.000 mph');
$this->verify_value_and_unit(3e8, 'm/s', 1, $ap, '3x10^8 m/s');
$this->verify_value_and_unit(3e8, '', null, $ap, '3x10^8');
$this->verify_value_and_unit(1, 'c', 299792458, $ap, '1c');
$this->verify_value_and_unit(1, 'mph', 0.44704, $ap, '0001.000 mph');
$this->verify_value_and_unit(1, 'frogs', $ap, '1 frogs');
$this->verify_value_and_unit(null, null, $ap, '. m/s');
$this->verify_value_and_unit(1, 'frogs', null, $ap, '1 frogs');
$this->verify_value_and_unit(null, null, null, $ap, '. m/s');
}
public function test_apply_units_separate_unit() {
@@ -112,39 +117,39 @@ class qtype_numerical_answer_processor_test extends UnitTestCase {
array('m/s' => 1, 'c' => 3.3356409519815E-9,
'mph' => 2.2369362920544), false, '.', ',');
$this->verify_value_and_unit(3e8, 'm/s', $ap, '3x10^8', 'm/s');
$this->verify_value_and_unit(3e8, '', $ap, '3x10^8', '');
$this->verify_value_and_unit(299792458, 'c', $ap, '1', 'c');
$this->verify_value_and_unit(0.44704, 'mph', $ap, '0001.000', 'mph');
$this->verify_value_and_unit(3e8, 'm/s', 1, $ap, '3x10^8', 'm/s');
$this->verify_value_and_unit(3e8, '', null, $ap, '3x10^8', '');
$this->verify_value_and_unit(1, 'c', 299792458, $ap, '1', 'c');
$this->verify_value_and_unit(1, 'mph', 0.44704, $ap, '0001.000', 'mph');
$this->verify_value_and_unit(1, 'frogs', $ap, '1', 'frogs');
$this->verify_value_and_unit(null, null, $ap, '.', 'm/s');
$this->verify_value_and_unit(1, 'frogs', null, $ap, '1', 'frogs');
$this->verify_value_and_unit(null, null, null, $ap, '.', 'm/s');
}
public function test_euro_style() {
$ap = new qtype_numerical_answer_processor(array(), false, ',', ' ');
$this->assertEqual(array(-1000, ''), $ap->apply_units('-1 000'));
$this->assertEqual(array(3.14159, ''), $ap->apply_units('3,14159'));
$this->assertEqual(array(-1000, '', null), $ap->apply_units('-1 000'));
$this->assertEqual(array(3.14159, '', null), $ap->apply_units('3,14159'));
}
public function test_percent() {
$ap = new qtype_numerical_answer_processor(array('%' => 100), false, '.', ',');
$this->assertEqual(array('0.03', '%'), $ap->apply_units('3%'));
$this->assertEqual(array('1e-8', '%'), $ap->apply_units('1e-6 %'));
$this->assertEqual(array('100', ''), $ap->apply_units('100'));
$this->assertEqual(array('3', '%', 0.01), $ap->apply_units('3%'));
$this->assertEqual(array('1e-6', '%', 0.01), $ap->apply_units('1e-6 %'));
$this->assertEqual(array('100', '', null), $ap->apply_units('100'));
}
public function test_currency() {
$ap = new qtype_numerical_answer_processor(array('$' => 1, '£' => 1), true, '.', ',');
$this->assertEqual(array('1234.56', '£'), $ap->apply_units('£1,234.56'));
$this->assertEqual(array('100', '$'), $ap->apply_units('$100'));
$this->assertEqual(array('100', '$'), $ap->apply_units('$100.'));
$this->assertEqual(array('100.00', '$'), $ap->apply_units('$100.00'));
$this->assertEqual(array('100', ''), $ap->apply_units('100'));
$this->assertEqual(array('100', 'frog'), $ap->apply_units('frog 100'));
$this->assertEqual(array('1234.56', '£', 1), $ap->apply_units('£1,234.56'));
$this->assertEqual(array('100', '$', 1), $ap->apply_units('$100'));
$this->assertEqual(array('100', '$', 1), $ap->apply_units('$100.'));
$this->assertEqual(array('100.00', '$', 1), $ap->apply_units('$100.00'));
$this->assertEqual(array('100', '', null), $ap->apply_units('100'));
$this->assertEqual(array('100', 'frog', null), $ap->apply_units('frog 100'));
}
}
+80
View File
@@ -0,0 +1,80 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Unit tests for (some of) question/type/numerical/edit_numerical_form.php.
*
* @package qtype
* @subpackage numerical
* @copyright 2011 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
require_once($CFG->dirroot . '/question/type/numerical/edit_numerical_form.php');
/**
* Test sub-class, so we can force the locale.
*
* @copyright 2011 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class test_qtype_numerical_edit_form extends qtype_numerical_edit_form {
public function __construct() {
// Warning, avoid running the parent constructor. That means the form is
// not properly tested but for now that is OK, we are only testing a few
// methods.
$this->ap = new qtype_numerical_answer_processor(array(), false, ',', ' ');
}
public function is_valid_number($x) {
return parent::is_valid_number($x);
}
}
/**
* Unit tests for question/type/numerical/edit_numerical_form.php.
*
* @copyright 2011 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class qtype_numerical_form_test extends UnitTestCase {
public static $includecoverage = array(
'question/type/numerical/edit_numerical_form.php'
);
protected $form;
public function setUp() {
$this->form = new test_qtype_numerical_edit_form();
}
public function tearDown() {
$this->form = null;
}
public function test_is_valid_number() {
$this->assertTrue($this->form->is_valid_number('1,001'));
$this->assertTrue($this->form->is_valid_number('1.001'));
$this->assertTrue($this->form->is_valid_number('1'));
$this->assertTrue($this->form->is_valid_number('1,e8'));
$this->assertFalse($this->form->is_valid_number('1001 xxx'));
$this->assertTrue($this->form->is_valid_number('1.e8'));
}
}
@@ -64,6 +64,7 @@ class qtype_numerical_question_test extends UnitTestCase {
public function test_grading_with_units() {
$question = test_question_maker::make_question('numerical');
$question->unitgradingtype = qtype_numerical::UNITOPTIONAL;
$question->ap = new qtype_numerical_answer_processor(
array('m' => 1, 'cm' => 100), false, '.', ',');
@@ -79,6 +80,28 @@ class qtype_numerical_question_test extends UnitTestCase {
$question->grade_response(array('answer' => '314000000x10^-8m')));
}
public function test_grading_with_units_graded() {
$question = test_question_maker::make_question('numerical');
$question->unitgradingtype = qtype_numerical::UNITGRADED;
$question->ap = new qtype_numerical_answer_processor(
array('m' => 1, 'cm' => 100), false, '.', ',');
$this->assertEqual(array(0.8, question_state::$gradedpartial),
$question->grade_response(array('answer' => '3.14 frogs')));
$this->assertEqual(array(0.8, question_state::$gradedpartial),
$question->grade_response(array('answer' => '3.14')));
$this->assertEqual(array(1, question_state::$gradedright),
$question->grade_response(array('answer' => '3.14 m')));
$this->assertEqual(array(1, question_state::$gradedright),
$question->grade_response(array('answer' => '314cm')));
$this->assertEqual(array(1, question_state::$gradedright),
$question->grade_response(array('answer' => '314000000x10^-8m')));
$this->assertEqual(array(0.8, question_state::$gradedpartial),
$question->grade_response(array('answer' => '3.14 cm')));
$this->assertEqual(array(0, question_state::$gradedwrong),
$question->grade_response(array('answer' => '314 m')));
}
public function test_grading_unit() {
$question = test_question_maker::make_question('numerical', 'unit');
@@ -110,17 +133,17 @@ class qtype_numerical_question_test extends UnitTestCase {
$this->assertEqual(array(1, question_state::$gradedright),
$question->grade_response(array('answer' => '$1332')));
$this->assertEqual(array(1, question_state::$gradedright),
$question->grade_response(array('answer' => '$ 1,332')));
$question->grade_response(array('answer' => '$ 1332')));
$this->assertEqual(array(0.8, question_state::$gradedpartial),
$question->grade_response(array('answer' => 'frog 1332')));
$this->assertEqual(array(0.8, question_state::$gradedpartial),
$question->grade_response(array('answer' => '1332')));
$this->assertEqual(array(0.8, question_state::$gradedpartial),
$question->grade_response(array('answer' => ' 1,332')));
$question->grade_response(array('answer' => ' 1332')));
$this->assertEqual(array(0, question_state::$gradedwrong),
$question->grade_response(array('answer' => '1332 $')));
$this->assertEqual(array(0, question_state::$gradedwrong),
$question->grade_response(array('answer' => '1,332 frogs')));
$question->grade_response(array('answer' => '1332 frogs')));
$this->assertEqual(array(0, question_state::$gradedwrong),
$question->grade_response(array('answer' => '$1')));
}
@@ -225,7 +248,7 @@ class qtype_numerical_question_test extends UnitTestCase {
new question_classified_response(14, '$100', 0)),
$num->classify_response(array('answer' => '$100')));
$this->assertEqual(array(
new question_classified_response(13, '1,332', 0.8)),
$num->classify_response(array('answer' => '1,332')));
new question_classified_response(13, '1 332', 0.8)),
$num->classify_response(array('answer' => '1 332')));
}
}