Skip to content

Commit

Permalink
MDL-20636 Fix upgrade of numerical questions.
Browse files Browse the repository at this point in the history
  • Loading branch information
timhunt committed May 13, 2011
1 parent aac80ff commit c468ce5
Show file tree
Hide file tree
Showing 8 changed files with 461 additions and 26 deletions.
2 changes: 2 additions & 0 deletions question/engine/bank.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@

defined('MOODLE_INTERNAL') || die();

require_once(dirname(__FILE__) . '/../type/questiontype.php');


/**
* This static class provides access to the other question bank.
Expand Down
196 changes: 196 additions & 0 deletions question/type/numerical/db/simpletest/testupgradelibnewqe.php
Original file line number Diff line number Diff line change
Expand Up @@ -262,4 +262,200 @@ public function test_numerical_deferredfeedback_history620() {

$this->assertEqual($expectedqa, $qa);
}

public function test_numerical_deferredfeedback_required_units() {
$quiz = (object) array(
'id' => '2',
'course' => '2',
'name' => 'Numerical quiz',
'intro' => '',
'introformat' => '1',
'timeopen' => '0',
'timeclose' => '0',
'attempts' => '0',
'attemptonlast' => '0',
'grademethod' => '1',
'decimalpoints' => '2',
'questiondecimalpoints' => '-1',
'review' => '4459503',
'questionsperpage' => '1',
'shufflequestions' => '0',
'shuffleanswers' => '1',
'questions' => '6,12,13,15,14,0',
'sumgrades' => '5.00000',
'grade' => '10.00000',
'timecreated' => '0',
'timemodified' => '1305273177',
'timelimit' => '0',
'password' => '',
'subnet' => '',
'popup' => '0',
'delay1' => '0',
'delay2' => '0',
'showuserpicture' => '0',
'showblocks' => '0',
'preferredbehaviour' => 'deferredfeedback',
);
$attempt = (object) array(
'id' => '6',
'uniqueid' => '6',
'quiz' => '2',
'userid' => '2',
'attempt' => '1',
'sumgrades' => '4.00000',
'timestart' => '1305273566',
'timefinish' => '1305273600',
'timemodified' => '1305273600',
'layout' => '6,12,13,15,14,0',
'preview' => '1',
'needsupgradetonewqe' => 1,
);
$question = (object) array(
'id' => '15',
'category' => '2',
'parent' => '0',
'name' => 'Required units',
'questiontext' => '<p>What is twice 1.5 m?</p>',
'questiontextformat' => '1',
'generalfeedback' => '',
'generalfeedbackformat' => '1',
'penalty' => '0.1000000',
'qtype' => 'numerical',
'length' => '1',
'stamp' => 'tjh238.vledev2.open.ac.uk+110513075857+rrvakr',
'version' => 'tjh238.vledev2.open.ac.uk+110513075857+PH0loi',
'hidden' => '0',
'timecreated' => '1305273537',
'timemodified' => '1305273537',
'createdby' => '2',
'modifiedby' => '2',
'maxmark' => '1.0000000',
'options' => (object) array(
'answers' => array(
22 => (object) array(
'id' => '22',
'question' => '15',
'answer' => '3',
'answerformat' => '0',
'fraction' => '1.0000000',
'feedback' => '',
'feedbackformat' => '1',
'tolerance' => '',
),
),
'units' => array(
0 => (object) array(
'id' => '7',
'question' => '15',
'multiplier' => 1,
'unit' => 'm',
),
1 => (object) array(
'id' => '8',
'question' => '15',
'multiplier' => 100,
'unit' => 'cm',
),
),
'unitgradingtype' => '2',
'unitpenalty' => '0.5000000',
'showunits' => '0',
'unitsleft' => '0',
'instructions' => '<p>Write an answer like 3 m.</p>',
'instructionsformat' => '1',
),
'defaultmark' => '1.0000000',
);
$qsession = (object) array(
'id' => '49',
'attemptid' => '6',
'questionid' => '15',
'newest' => '139',
'newgraded' => '139',
'sumpenalty' => '0.1000000',
'manualcomment' => '',
'manualcommentformat' => '1',
'flagged' => '0',
);
$qstates = array(
129 => (object) array(
'id' => '129',
'attempt' => '6',
'question' => '15',
'seq_number' => '0',
'answer' => '|||||',
'timestamp' => '1305273566',
'event' => '0',
'grade' => '0.0000000',
'raw_grade' => '0.0000000',
'penalty' => '0.0000000',
),
134 => (object) array(
'id' => '134',
'attempt' => '6',
'question' => '15',
'seq_number' => '1',
'answer' => '3|||||m',
'timestamp' => '1305273595',
'event' => '2',
'grade' => '0.0000000',
'raw_grade' => '1.0000000',
'penalty' => '0.1000000',
),
139 => (object) array(
'id' => '139',
'attempt' => '6',
'question' => '15',
'seq_number' => '2',
'answer' => '3|||||m',
'timestamp' => '1305273595',
'event' => '6',
'grade' => '1.0000000',
'raw_grade' => '1.0000000',
'penalty' => '0.1000000',
),
);

$qa = $this->updater->convert_question_attempt($quiz, $attempt, $question, $qsession, $qstates);

$expectedqa = (object) array(
'behaviour' => 'deferredfeedback',
'questionid' => 15,
'maxmark' => 1.0000000,
'minfraction' => 0,
'flagged' => 0,
'questionsummary' => 'What is twice 1.5 m?',
'rightanswer' => '3 m',
'responsesummary' => '3 m',
'timemodified' => 1305273595,
'steps' => array(
0 => (object) array(
'sequencenumber' => 0,
'state' => 'todo',
'fraction' => null,
'timecreated' => 1305273566,
'userid' => 2,
'data' => array('_separators' => '.$,'),
),
1 => (object) array(
'sequencenumber' => 1,
'state' => 'complete',
'fraction' => null,
'timecreated' => 1305273595,
'userid' => 2,
'data' => array('answer' => '3 m'),
),
2 => (object) array(
'sequencenumber' => 2,
'state' => 'gradedright',
'fraction' => 1,
'timecreated' => 1305273595,
'userid' => 2,
'data' => array('answer' => '3 m', '-finish' => '1'),
),
),
);

$this->assertEqual($expectedqa, $qa);
}
}
40 changes: 35 additions & 5 deletions question/type/numerical/db/upgradelib.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,17 +42,46 @@ class qtype_numerical_qe2_attempt_updater extends question_qtype_attempt_updater
public function right_answer() {
foreach ($this->question->options->answers as $ans) {
if ($ans->fraction > 0.999) {
return $ans->answer;
$right = $ans->answer;

if (empty($this->question->options->units)) {
return $right;
}

$unit = reset($this->question->options->units);
$unit = $unit->unit;
if (!empty($this->question->options->unitsleft)) {
return $unit . ' ' . $right;
} else {
return $right . ' ' . $unit;
}
}
}
}

public function response_summary($state) {
if (!empty($state->answer)) {
return $state->answer;
if (strpos($state->answer, '|||||') === false) {
$answer = $state->answer;
$unit = '';
} else {
return null;
list($answer, $unit) = explode('|||||', $state->answer, 2);
}

if (empty($answer) && empty($unit)) {
$resp = null;
} else {
$resp = $answer;
}

if (!empty($unit)) {
if (!empty($this->question->options->unitsleft)) {
$resp = trim($unit . ' ' . $resp);
} else {
$resp = trim($resp . ' ' . $unit);
}
}

return $resp;
}

public function was_answered($state) {
Expand All @@ -75,7 +104,8 @@ public function set_data_elements_for_step($state, &$data) {
$data['answer'] = $state->answer;
} else {
list($answer, $unit) = explode('|||||', $state->answer, 2);
if ($this->question->options->showunits == 1) {
if (!empty($this->question->options->showunits) &&
$this->question->options->showunits == 1) {
// Multichoice units.
$data['answer'] = $answer;
$data['unit'] = $unit;
Expand Down
4 changes: 2 additions & 2 deletions question/type/numerical/questiontype.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@

defined('MOODLE_INTERNAL') || die();

require_once($CFG->dirroot . '/question/type/numerical/question.php');
//require_once($CFG->dirroot . '/question/type/numerical/question.php');


/**
Expand Down Expand Up @@ -809,7 +809,7 @@ public function apply_units($response, $separateunit = null) {
}

if ($unit && $this->is_known_unit($unit)) {
$value = $numberstring * $this->units[$unit];
$value = $numberstring / $this->units[$unit];
} else {
$value = $numberstring * 1;
}
Expand Down
2 changes: 1 addition & 1 deletion question/type/numerical/simpletest/helper.php
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ public function make_numerical_question_unit() {
$num->unitdisplay = qtype_numerical::UNITSELECT;
$num->unitgradingtype = qtype_numerical::UNITGRADEDOUTOFMARK;
$num->unitpenalty = 0.5;
$num->ap = new qtype_numerical_answer_processor(array('m' => 1, 'cm' => 0.01));
$num->ap = new qtype_numerical_answer_processor(array('m' => 1, 'cm' => 100));

return $num;
}
Expand Down
43 changes: 27 additions & 16 deletions question/type/numerical/simpletest/testanswerprocessor.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public function parse_response($response) {
class qtype_numerical_answer_processor_test extends UnitTestCase {
public function test_parse_response() {
$ap = new testable_qtype_numerical_answer_processor(
array('m' => 1, 'cm' => 0.01), false, '.', ',');
array('m' => 1, 'cm' => 100), false, '.', ',');

$this->assertEqual(array('3', '142', '', ''), $ap->parse_response('3.142'));
$this->assertEqual(array('', '2', '', ''), $ap->parse_response('.2'));
Expand Down Expand Up @@ -83,30 +83,41 @@ public function test_parse_response() {
$this->assertEqual(array(null, null, null, null), $ap->parse_response(','));
}

protected function verify_value_and_unit($exectedval, $expectedunit,
qtype_numerical_answer_processor $ap, $input, $separateunit = null) {
list($val, $unit) = $ap->apply_units($input, $separateunit);
if (is_null($exectedval)) {
$this->assertNull($val);
} else {
$this->assertWithinMargin($exectedval, $val, 0.0001);
}
$this->assertEqual($expectedunit, $unit);
}

public function test_apply_units() {
$ap = new qtype_numerical_answer_processor(
array('m/s' => 1, 'c' => 299792458, 'mph' => 0.44704), false, '.', ',');
array('m/s' => 1, 'c' => 3.3356409519815E-9, 'mph' => 2.2369362920544), false, '.', ',');

$this->assertEqual(array(3e8, 'm/s'), $ap->apply_units('3x10^8 m/s'));
$this->assertEqual(array(3e8, ''), $ap->apply_units('3x10^8'));
$this->assertEqual(array(299792458, 'c'), $ap->apply_units('1c'));
$this->assertEqual(array(0.44704, 'mph'), $ap->apply_units('0001.000 mph'));
$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->assertEqual(array(1, 'frogs'), $ap->apply_units('1 frogs'));
$this->assertEqual(array(null, null), $ap->apply_units('. m/s'));
$this->verify_value_and_unit(1, 'frogs', $ap, '1 frogs');
$this->verify_value_and_unit(null, null, $ap, '. m/s');
}

public function test_apply_units_separate_unit() {
$ap = new qtype_numerical_answer_processor(
array('m/s' => 1, 'c' => 299792458, 'mph' => 0.44704), false, '.', ',');
array('m/s' => 1, 'c' => 3.3356409519815E-9, 'mph' => 2.2369362920544), false, '.', ',');

$this->assertEqual(array(3e8, 'm/s'), $ap->apply_units('3x10^8', 'm/s'));
$this->assertEqual(array(3e8, ''), $ap->apply_units('3x10^8', ''));
$this->assertEqual(array(299792458, 'c'), $ap->apply_units('1', 'c'));
$this->assertEqual(array(0.44704, 'mph'), $ap->apply_units('0001.000', 'mph'));
$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->assertEqual(array(1, 'frogs'), $ap->apply_units('1', 'frogs'));
$this->assertEqual(array(null, null), $ap->apply_units('.', 'm/s'));
$this->verify_value_and_unit(1, 'frogs', $ap, '1', 'frogs');
$this->verify_value_and_unit(null, null, $ap, '.', 'm/s');
}

public function test_euro_style() {
Expand All @@ -117,7 +128,7 @@ public function test_euro_style() {
}

public function test_percent() {
$ap = new qtype_numerical_answer_processor(array('%' => 0.01), false, '.', ',');
$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 %'));
Expand Down
2 changes: 1 addition & 1 deletion question/type/numerical/simpletest/testquestion.php
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ public function test_grading() {
public function test_grading_with_units() {
$question = test_question_maker::make_question('numerical');
$question->ap = new qtype_numerical_answer_processor(
array('m' => 1, 'cm' => 0.01), false, '.', ',');
array('m' => 1, 'cm' => 100), false, '.', ',');

$this->assertEqual(array(1, question_state::$gradedright),
$question->grade_response(array('answer' => '3.14 frogs')));
Expand Down
Loading

0 comments on commit c468ce5

Please sign in to comment.