MDL-20636 Split question_definition::init_first_step into start_attempt and apply_attempt_state.

This commit is contained in:
Tim Hunt
2011-02-24 19:12:42 +00:00
parent 2daffca554
commit ef31a28343
16 changed files with 172 additions and 135 deletions
+7 -5
View File
@@ -179,7 +179,7 @@ abstract class question_behaviour {
/**
* What is the minimum fraction that can be scored for this question.
* Normally this will be based on $this->question->init_first_step($step),
* Normally this will be based on $this->question->get_min_fraction(),
* but may be modified in some way by the model.
*
* @return number the minimum fraction when this question is attempted under
@@ -325,15 +325,17 @@ abstract class question_behaviour {
abstract public function summarise_action(question_attempt_step $step);
/**
* Initialise the first step in a question attempt.
* Initialise the first step in a question attempt when a new
* {@link question_attempt} is being started.
*
* This method must call $this->question->init_first_step($step), and may
* This method must call $this->question->start_attempt($step), and may
* perform additional processing if the model requries it.
*
* @param question_attempt_step $step the step being initialised.
* @param question_attempt_step $step the first step of the
* question_attempt being started.
*/
public function init_first_step(question_attempt_step $step) {
$this->question->init_first_step($step);
$this->question->start_attempt($step);
}
/**
-5
View File
@@ -65,11 +65,6 @@ class qbehaviour_opaque extends question_behaviour {
public function init_first_step(question_attempt_step $step) {
global $USER;
if ($step->has_behaviour_var('_randomseed')) {
// Reinitialising, nothing to do.
return;
}
// Set up the random seed to be the current time in milliseconds.
list($micros, $sec) = explode(' ', microtime());
$step->set_behaviour_var('_randomseed', $sec . floor($micros * 1000));
+10 -8
View File
@@ -1891,16 +1891,16 @@ class question_attempt {
}
/**
* Start (or re-start) this question attempt.
* Start this question attempt.
*
* You should not call this method directly. Call
* {@link question_usage_by_activity::start_question()} instead.
*
* @param string|question_behaviour $preferredbehaviour the name of the
* desired archetypal behaviour, or an actual model instance.
* @param $submitteddata optional, used when re-starting to keep the same initial state.
* @param $timestamp optional, the timstamp to record for this action. Defaults to now.
* @param $userid optional, the user to attribute this action to. Defaults to the current user.
* @param array $submitteddata optional, used when re-starting to keep the same initial state.
* @param int $timestamp optional, the timstamp to record for this action. Defaults to now.
* @param int $userid optional, the user to attribute this action to. Defaults to the current user.
*/
public function start($preferredbehaviour, $submitteddata = array(), $timestamp = null, $userid = null) {
// Initialise the behaviour.
@@ -1918,12 +1918,14 @@ class question_attempt {
// Initialise the first step.
$firststep = new question_attempt_step($submitteddata, $timestamp, $userid);
$firststep->set_state(question_state::$todo);
$this->behaviour->init_first_step($firststep);
if ($submitteddata) {
$this->question->apply_attempt_state($firststep);
} else {
$this->behaviour->init_first_step($firststep);
}
$this->add_step($firststep);
// Record questionline and correct answer.
// TODO we should only really do this for new attempts, not when called
// via load_from_records.
$this->questionsummary = $this->behaviour->get_question_summary();
$this->rightanswer = $this->behaviour->get_right_answer_summary();
}
@@ -2243,7 +2245,7 @@ class question_attempt {
while ($record && $record->questionattemptid == $questionattemptid && !is_null($record->attemptstepid)) {
$qa->steps[$i] = question_attempt_step::load_from_records($records, $record->attemptstepid);
if ($i == 0) {
$question->init_first_step($qa->steps[0]);
$question->apply_attempt_state($qa->steps[0]);
}
$i++;
$record = current($records);
@@ -55,7 +55,7 @@ class qtype_ddwtos_question_test extends UnitTestCase {
public function test_summarise_response() {
$dd = qtype_ddwtos_test_helper::make_a_ddwtos_question();
$dd->shufflechoices = false;
$dd->init_first_step(new question_attempt_step());
$dd->start_attempt(new question_attempt_step());
$this->assertEqual('{quick} {fox} {lazy}',
$dd->summarise_response(array('p1' => '1', 'p2' => '1', 'p3' => '1')));
@@ -64,7 +64,7 @@ class qtype_ddwtos_question_test extends UnitTestCase {
public function test_summarise_response_maths() {
$dd = qtype_ddwtos_test_helper::make_a_maths_ddwtos_question();
$dd->shufflechoices = false;
$dd->init_first_step(new question_attempt_step());
$dd->start_attempt(new question_attempt_step());
$this->assertEqual('{+} {-} {+} {-}',
$dd->summarise_response(array('p1' => '1', 'p2' => '2', 'p3' => '1', 'p4' => '2')));
@@ -83,7 +83,7 @@ class qtype_ddwtos_question_test extends UnitTestCase {
public function test_get_right_choice_for() {
$dd = qtype_ddwtos_test_helper::make_a_ddwtos_question();
$dd->shufflechoices = false;
$dd->init_first_step(new question_attempt_step());
$dd->start_attempt(new question_attempt_step());
$this->assertEqual(1, $dd->get_right_choice_for(1));
$this->assertEqual(1, $dd->get_right_choice_for(2));
@@ -92,7 +92,7 @@ class qtype_ddwtos_question_test extends UnitTestCase {
public function test_get_right_choice_for_maths() {
$dd = qtype_ddwtos_test_helper::make_a_maths_ddwtos_question();
$dd->shufflechoices = false;
$dd->init_first_step(new question_attempt_step());
$dd->start_attempt(new question_attempt_step());
$this->assertEqual(1, $dd->get_right_choice_for(1));
$this->assertEqual(2, $dd->get_right_choice_for(2));
@@ -101,7 +101,7 @@ class qtype_ddwtos_question_test extends UnitTestCase {
public function test_clear_wrong_from_response() {
$dd = qtype_ddwtos_test_helper::make_a_maths_ddwtos_question();
$dd->shufflechoices = false;
$dd->init_first_step(new question_attempt_step());
$dd->start_attempt(new question_attempt_step());
$initialresponse = array('p1' => '1', 'p2' => '1', 'p3' => '1', 'p4' => '1');
$this->assertEqual(array('p1' => '1', 'p2' => '0', 'p3' => '1', 'p4' => '0'),
@@ -111,7 +111,7 @@ class qtype_ddwtos_question_test extends UnitTestCase {
public function test_get_num_parts_right() {
$dd = qtype_ddwtos_test_helper::make_a_ddwtos_question();
$dd->shufflechoices = false;
$dd->init_first_step(new question_attempt_step());
$dd->start_attempt(new question_attempt_step());
$this->assertEqual(array(2, 3),
$dd->get_num_parts_right(array('p1' => '1', 'p2' => '1', 'p3' => '2')));
@@ -122,7 +122,7 @@ class qtype_ddwtos_question_test extends UnitTestCase {
public function test_get_num_parts_right_maths() {
$dd = qtype_ddwtos_test_helper::make_a_maths_ddwtos_question();
$dd->shufflechoices = false;
$dd->init_first_step(new question_attempt_step());
$dd->start_attempt(new question_attempt_step());
$this->assertEqual(array(2, 4),
$dd->get_num_parts_right(array('p1' => '1', 'p2' => '1', 'p3' => '1', 'p4' => '1')));
@@ -130,7 +130,7 @@ class qtype_ddwtos_question_test extends UnitTestCase {
public function test_get_expected_data() {
$dd = qtype_ddwtos_test_helper::make_a_ddwtos_question();
$dd->init_first_step(new question_attempt_step());
$dd->start_attempt(new question_attempt_step());
$this->assertEqual(array('p1' => PARAM_INT, 'p2' => PARAM_INT, 'p3' => PARAM_INT),
$dd->get_expected_data());
@@ -139,7 +139,7 @@ class qtype_ddwtos_question_test extends UnitTestCase {
public function test_get_correct_response() {
$dd = qtype_ddwtos_test_helper::make_a_ddwtos_question();
$dd->shufflechoices = false;
$dd->init_first_step(new question_attempt_step());
$dd->start_attempt(new question_attempt_step());
$this->assertEqual(array('p1' => '1', 'p2' => '1', 'p3' => '1'),
$dd->get_correct_response());
@@ -148,7 +148,7 @@ class qtype_ddwtos_question_test extends UnitTestCase {
public function test_get_correct_response_maths() {
$dd = qtype_ddwtos_test_helper::make_a_maths_ddwtos_question();
$dd->shufflechoices = false;
$dd->init_first_step(new question_attempt_step());
$dd->start_attempt(new question_attempt_step());
$this->assertEqual(array('p1' => '1', 'p2' => '2', 'p3' => '1', 'p4' => '2'),
$dd->get_correct_response());
@@ -156,7 +156,7 @@ class qtype_ddwtos_question_test extends UnitTestCase {
public function test_is_same_response() {
$dd = qtype_ddwtos_test_helper::make_a_ddwtos_question();
$dd->init_first_step(new question_attempt_step());
$dd->start_attempt(new question_attempt_step());
$this->assertTrue($dd->is_same_response(
array(),
@@ -180,7 +180,7 @@ class qtype_ddwtos_question_test extends UnitTestCase {
}
public function test_is_complete_response() {
$dd = qtype_ddwtos_test_helper::make_a_ddwtos_question();
$dd->init_first_step(new question_attempt_step());
$dd->start_attempt(new question_attempt_step());
$this->assertFalse($dd->is_complete_response(array()));
$this->assertFalse($dd->is_complete_response(
@@ -192,7 +192,7 @@ class qtype_ddwtos_question_test extends UnitTestCase {
public function test_is_gradable_response() {
$dd = qtype_ddwtos_test_helper::make_a_ddwtos_question();
$dd->init_first_step(new question_attempt_step());
$dd->start_attempt(new question_attempt_step());
$this->assertFalse($dd->is_gradable_response(array()));
$this->assertFalse($dd->is_gradable_response(
@@ -207,7 +207,7 @@ class qtype_ddwtos_question_test extends UnitTestCase {
public function test_grading() {
$dd = qtype_ddwtos_test_helper::make_a_ddwtos_question();
$dd->shufflechoices = false;
$dd->init_first_step(new question_attempt_step());
$dd->start_attempt(new question_attempt_step());
$this->assertEqual(array(1, question_state::$gradedright),
$dd->grade_response(array('p1' => '1', 'p2' => '1', 'p3' => '1')));
@@ -220,7 +220,7 @@ class qtype_ddwtos_question_test extends UnitTestCase {
public function test_grading_maths() {
$dd = qtype_ddwtos_test_helper::make_a_maths_ddwtos_question();
$dd->shufflechoices = false;
$dd->init_first_step(new question_attempt_step());
$dd->start_attempt(new question_attempt_step());
$this->assertEqual(array(1, question_state::$gradedright),
$dd->grade_response(array('p1' => '1', 'p2' => '2', 'p3' => '1', 'p4' => '2')));
@@ -233,7 +233,7 @@ class qtype_ddwtos_question_test extends UnitTestCase {
public function test_classify_response() {
$dd = qtype_ddwtos_test_helper::make_a_ddwtos_question();
$dd->shufflechoices = false;
$dd->init_first_step(new question_attempt_step());
$dd->start_attempt(new question_attempt_step());
$this->assertEqual(array(
1 => new question_classified_response(1, 'quick', 1),
+23 -17
View File
@@ -66,27 +66,33 @@ abstract class qtype_gapselect_question_base extends question_graded_automatical
/** @var array shuffled choice indexes. */
protected $choiceorder;
public function init_first_step(question_attempt_step $step) {
public function start_attempt(question_attempt_step $step) {
foreach ($this->choices as $group => $choices) {
$varname = '_choiceorder' . $group;
if ($step->has_qt_var($varname)) {
$choiceorder = explode(',', $step->get_qt_var($varname));
} else {
$choiceorder = array_keys($choices);
if ($this->shufflechoices) {
shuffle($choiceorder);
}
$choiceorder = array_keys($choices);
if ($this->shufflechoices) {
shuffle($choiceorder);
}
$step->set_qt_var('_choiceorder' . $group, implode(',', $choiceorder));
$this->set_choiceorder($group, $choiceorder);
}
}
foreach ($choiceorder as $key => $value) {
$this->choiceorder[$group][$key + 1] = $value;
}
public function apply_attempt_state(question_attempt_step $step) {
foreach ($this->choices as $group => $choices) {
$this->set_choiceorder($group, explode(',',
$step->get_qt_var('_choiceorder' . $group)));
}
}
if (!$step->has_qt_var($varname)) {
$step->set_qt_var($varname, implode(',', $this->choiceorder[$group]));
}
/**
* Helper method used by both {@link start_attempt()} and
* {@link apply_attempt_state()}.
* @param int $group the group number.
* @param array $choiceorder the choices, in order.
*/
protected function set_choiceorder($group, $choiceorder) {
foreach ($choiceorder as $key => $value) {
$this->choiceorder[$group][$key + 1] = $value;
}
}
@@ -55,7 +55,7 @@ class qtype_gapselect_question_test extends UnitTestCase {
public function test_summarise_response() {
$gapselect = qtype_gapselect_test_helper::make_a_gapselect_question();
$gapselect->shufflechoices = false;
$gapselect->init_first_step(new question_attempt_step());
$gapselect->start_attempt(new question_attempt_step());
$this->assertEqual('{quick} {fox} {lazy}',
$gapselect->summarise_response(array('p1' => '1', 'p2' => '1', 'p3' => '1')));
@@ -64,7 +64,7 @@ class qtype_gapselect_question_test extends UnitTestCase {
public function test_summarise_response_maths() {
$gapselect = qtype_gapselect_test_helper::make_a_maths_gapselect_question();
$gapselect->shufflechoices = false;
$gapselect->init_first_step(new question_attempt_step());
$gapselect->start_attempt(new question_attempt_step());
$this->assertEqual('{+} {-} {+} {-}',
$gapselect->summarise_response(array('p1' => '1', 'p2' => '2', 'p3' => '1', 'p4' => '2')));
@@ -83,7 +83,7 @@ class qtype_gapselect_question_test extends UnitTestCase {
public function test_get_right_choice_for() {
$gapselect = qtype_gapselect_test_helper::make_a_gapselect_question();
$gapselect->shufflechoices = false;
$gapselect->init_first_step(new question_attempt_step());
$gapselect->start_attempt(new question_attempt_step());
$this->assertEqual(1, $gapselect->get_right_choice_for(1));
$this->assertEqual(1, $gapselect->get_right_choice_for(2));
@@ -92,7 +92,7 @@ class qtype_gapselect_question_test extends UnitTestCase {
public function test_get_right_choice_for_maths() {
$gapselect = qtype_gapselect_test_helper::make_a_maths_gapselect_question();
$gapselect->shufflechoices = false;
$gapselect->init_first_step(new question_attempt_step());
$gapselect->start_attempt(new question_attempt_step());
$this->assertEqual(1, $gapselect->get_right_choice_for(1));
$this->assertEqual(2, $gapselect->get_right_choice_for(2));
@@ -101,7 +101,7 @@ class qtype_gapselect_question_test extends UnitTestCase {
public function test_clear_wrong_from_response() {
$gapselect = qtype_gapselect_test_helper::make_a_maths_gapselect_question();
$gapselect->shufflechoices = false;
$gapselect->init_first_step(new question_attempt_step());
$gapselect->start_attempt(new question_attempt_step());
$initialresponse = array('p1' => '1', 'p2' => '1', 'p3' => '1', 'p4' => '1');
$this->assertEqual(array('p1' => '1', 'p2' => '0', 'p3' => '1', 'p4' => '0'),
@@ -111,7 +111,7 @@ class qtype_gapselect_question_test extends UnitTestCase {
public function test_get_num_parts_right() {
$gapselect = qtype_gapselect_test_helper::make_a_gapselect_question();
$gapselect->shufflechoices = false;
$gapselect->init_first_step(new question_attempt_step());
$gapselect->start_attempt(new question_attempt_step());
$this->assertEqual(array(2, 3),
$gapselect->get_num_parts_right(array('p1' => '1', 'p2' => '1', 'p3' => '2')));
@@ -122,7 +122,7 @@ class qtype_gapselect_question_test extends UnitTestCase {
public function test_get_num_parts_right_maths() {
$gapselect = qtype_gapselect_test_helper::make_a_maths_gapselect_question();
$gapselect->shufflechoices = false;
$gapselect->init_first_step(new question_attempt_step());
$gapselect->start_attempt(new question_attempt_step());
$this->assertEqual(array(2, 4),
$gapselect->get_num_parts_right(array('p1' => '1', 'p2' => '1', 'p3' => '1', 'p4' => '1')));
@@ -130,7 +130,7 @@ class qtype_gapselect_question_test extends UnitTestCase {
public function test_get_expected_data() {
$gapselect = qtype_gapselect_test_helper::make_a_gapselect_question();
$gapselect->init_first_step(new question_attempt_step());
$gapselect->start_attempt(new question_attempt_step());
$this->assertEqual(array('p1' => PARAM_INT, 'p2' => PARAM_INT, 'p3' => PARAM_INT),
$gapselect->get_expected_data());
@@ -139,7 +139,7 @@ class qtype_gapselect_question_test extends UnitTestCase {
public function test_get_correct_response() {
$gapselect = qtype_gapselect_test_helper::make_a_gapselect_question();
$gapselect->shufflechoices = false;
$gapselect->init_first_step(new question_attempt_step());
$gapselect->start_attempt(new question_attempt_step());
$this->assertEqual(array('p1' => '1', 'p2' => '1', 'p3' => '1'),
$gapselect->get_correct_response());
@@ -148,7 +148,7 @@ class qtype_gapselect_question_test extends UnitTestCase {
public function test_get_correct_response_maths() {
$gapselect = qtype_gapselect_test_helper::make_a_maths_gapselect_question();
$gapselect->shufflechoices = false;
$gapselect->init_first_step(new question_attempt_step());
$gapselect->start_attempt(new question_attempt_step());
$this->assertEqual(array('p1' => '1', 'p2' => '2', 'p3' => '1', 'p4' => '2'),
$gapselect->get_correct_response());
@@ -156,7 +156,7 @@ class qtype_gapselect_question_test extends UnitTestCase {
public function test_is_same_response() {
$gapselect = qtype_gapselect_test_helper::make_a_gapselect_question();
$gapselect->init_first_step(new question_attempt_step());
$gapselect->start_attempt(new question_attempt_step());
$this->assertTrue($gapselect->is_same_response(
array(),
@@ -180,7 +180,7 @@ class qtype_gapselect_question_test extends UnitTestCase {
}
public function test_is_complete_response() {
$gapselect = qtype_gapselect_test_helper::make_a_gapselect_question();
$gapselect->init_first_step(new question_attempt_step());
$gapselect->start_attempt(new question_attempt_step());
$this->assertFalse($gapselect->is_complete_response(array()));
$this->assertFalse($gapselect->is_complete_response(
@@ -192,7 +192,7 @@ class qtype_gapselect_question_test extends UnitTestCase {
public function test_is_gradable_response() {
$gapselect = qtype_gapselect_test_helper::make_a_gapselect_question();
$gapselect->init_first_step(new question_attempt_step());
$gapselect->start_attempt(new question_attempt_step());
$this->assertFalse($gapselect->is_gradable_response(array()));
$this->assertFalse($gapselect->is_gradable_response(
@@ -207,7 +207,7 @@ class qtype_gapselect_question_test extends UnitTestCase {
public function test_grading() {
$gapselect = qtype_gapselect_test_helper::make_a_gapselect_question();
$gapselect->shufflechoices = false;
$gapselect->init_first_step(new question_attempt_step());
$gapselect->start_attempt(new question_attempt_step());
$this->assertEqual(array(1, question_state::$gradedright),
$gapselect->grade_response(array('p1' => '1', 'p2' => '1', 'p3' => '1')));
@@ -220,7 +220,7 @@ class qtype_gapselect_question_test extends UnitTestCase {
public function test_grading_maths() {
$gapselect = qtype_gapselect_test_helper::make_a_maths_gapselect_question();
$gapselect->shufflechoices = false;
$gapselect->init_first_step(new question_attempt_step());
$gapselect->start_attempt(new question_attempt_step());
$this->assertEqual(array(1, question_state::$gradedright),
$gapselect->grade_response(array('p1' => '1', 'p2' => '2', 'p3' => '1', 'p4' => '2')));
@@ -233,7 +233,7 @@ class qtype_gapselect_question_test extends UnitTestCase {
public function test_classify_response() {
$gapselect = qtype_gapselect_test_helper::make_a_gapselect_question();
$gapselect->shufflechoices = false;
$gapselect->init_first_step(new question_attempt_step());
$gapselect->start_attempt(new question_attempt_step());
$this->assertEqual(array(
1 => new question_classified_response(1, 'quick', 1),
+23 -13
View File
@@ -57,20 +57,30 @@ class qtype_match_question extends question_graded_automatically_with_countback
/** @var array shuffled choice indexes. */
protected $choiceorder;
public function init_first_step(question_attempt_step $step) {
if ($step->has_qt_var('_stemorder')) {
$this->stemorder = explode(',', $step->get_qt_var('_stemorder'));
$choiceorder = explode(',', $step->get_qt_var('_choiceorder'));
} else {
$this->stemorder = array_keys($this->stems);
$choiceorder = array_keys($this->choices);
if ($this->shufflestems) {
shuffle($this->stemorder);
}
shuffle($choiceorder);
$step->set_qt_var('_stemorder', implode(',', $this->stemorder));
$step->set_qt_var('_choiceorder', implode(',', $choiceorder));
public function start_attempt(question_attempt_step $step) {
$this->stemorder = array_keys($this->stems);
if ($this->shufflestems) {
shuffle($this->stemorder);
}
$step->set_qt_var('_stemorder', implode(',', $this->stemorder));
$choiceorder = array_keys($this->choices);
shuffle($choiceorder);
$step->set_qt_var('_choiceorder', implode(',', $choiceorder));
$this->set_choiceorder($choiceorder);
}
public function apply_attempt_state(question_attempt_step $step) {
$this->stemorder = explode(',', $step->get_qt_var('_stemorder'));
$this->set_choiceorder(explode(',', $step->get_qt_var('_choiceorder')));
}
/**
* Helper method used by both {@link start_attempt()} and
* {@link apply_attempt_state()}.
* @param array $choiceorder the choices, in order.
*/
protected function set_choiceorder($choiceorder) {
$this->choiceorder = array();
foreach ($choiceorder as $key => $value) {
$this->choiceorder[$key + 1] = $value;
@@ -40,7 +40,7 @@ class qtype_match_question_test extends UnitTestCase {
public function test_get_expected_data() {
$question = test_question_maker::make_a_matching_question();
$question->init_first_step(new question_attempt_step());
$question->start_attempt(new question_attempt_step());
$this->assertEqual(array('sub0' => PARAM_INT, 'sub1' => PARAM_INT,
'sub2' => PARAM_INT, 'sub3' => PARAM_INT), $question->get_expected_data());
@@ -48,7 +48,7 @@ class qtype_match_question_test extends UnitTestCase {
public function test_is_complete_response() {
$question = test_question_maker::make_a_matching_question();
$question->init_first_step(new question_attempt_step());
$question->start_attempt(new question_attempt_step());
$this->assertFalse($question->is_complete_response(array()));
$this->assertFalse($question->is_complete_response(
@@ -60,7 +60,7 @@ class qtype_match_question_test extends UnitTestCase {
public function test_is_gradable_response() {
$question = test_question_maker::make_a_matching_question();
$question->init_first_step(new question_attempt_step());
$question->start_attempt(new question_attempt_step());
$this->assertFalse($question->is_gradable_response(array()));
$this->assertFalse($question->is_gradable_response(
@@ -74,7 +74,7 @@ class qtype_match_question_test extends UnitTestCase {
public function test_is_same_response() {
$question = test_question_maker::make_a_matching_question();
$question->init_first_step(new question_attempt_step());
$question->start_attempt(new question_attempt_step());
$this->assertTrue($question->is_same_response(
array(),
@@ -100,7 +100,7 @@ class qtype_match_question_test extends UnitTestCase {
public function test_grading() {
$question = test_question_maker::make_a_matching_question();
$question->shufflestems = false;
$question->init_first_step(new question_attempt_step());
$question->start_attempt(new question_attempt_step());
$choiceorder = $question->get_choice_order();
$orderforchoice = array_combine(array_values($choiceorder), array_keys($choiceorder));
@@ -117,7 +117,7 @@ class qtype_match_question_test extends UnitTestCase {
public function test_get_correct_response() {
$question = test_question_maker::make_a_matching_question();
$question->shufflestems = false;
$question->init_first_step(new question_attempt_step());
$question->start_attempt(new question_attempt_step());
$choiceorder = $question->get_choice_order();
$orderforchoice = array_combine(array_values($choiceorder), array_keys($choiceorder));
@@ -128,7 +128,7 @@ class qtype_match_question_test extends UnitTestCase {
public function test_get_question_summary() {
$match = test_question_maker::make_a_matching_question();
$match->init_first_step(new question_attempt_step());
$match->start_attempt(new question_attempt_step());
$qsummary = $match->get_question_summary();
$this->assertPattern('/' . preg_quote($match->questiontext) . '/', $qsummary);
foreach ($match->stems as $stem) {
@@ -142,7 +142,7 @@ class qtype_match_question_test extends UnitTestCase {
public function test_summarise_response() {
$match = test_question_maker::make_a_matching_question();
$match->shufflestems = false;
$match->init_first_step(new question_attempt_step());
$match->start_attempt(new question_attempt_step());
$summary = $match->summarise_response(array('sub0' => 2, 'sub1' => 1));
@@ -152,7 +152,7 @@ class qtype_match_question_test extends UnitTestCase {
public function test_classify_response() {
$match = test_question_maker::make_a_matching_question();
$match->shufflestems = false;
$match->init_first_step(new question_attempt_step());
$match->start_attempt(new question_attempt_step());
$choiceorder = $match->get_choice_order();
$orderforchoice = array_combine(array_values($choiceorder), array_keys($choiceorder));
+2 -1
View File
@@ -76,7 +76,8 @@ class qtype_missingtype_question extends question_definition implements question
return array();
}
public function init_first_step(question_attempt_step $step) {
public function start_attempt(question_attempt_step $step) {
throw new coding_exception('This question is of a type that is not installed on your system. No processing is possible.');
}
public function grade_response(array $response) {
+9 -9
View File
@@ -55,16 +55,16 @@ abstract class qtype_multichoice_base extends question_graded_automatically {
protected $order = null;
public function init_first_step(question_attempt_step $step) {
if ($step->has_qt_var('_order')) {
$this->order = explode(',', $step->get_qt_var('_order'));
} else {
$this->order = array_keys($this->answers);
if ($this->shuffleanswers) {
shuffle($this->order);
}
$step->set_qt_var('_order', implode(',', $this->order));
public function start_attempt(question_attempt_step $step) {
$this->order = array_keys($this->answers);
if ($this->shuffleanswers) {
shuffle($this->order);
}
$step->set_qt_var('_order', implode(',', $this->order));
}
public function apply_attempt_state(question_attempt_step $step) {
$this->order = explode(',', $step->get_qt_var('_order'));
}
public function get_question_summary() {
@@ -62,7 +62,7 @@ class qtype_multichoice_single_question_test extends UnitTestCase {
public function test_grading() {
$question = test_question_maker::make_a_multichoice_single_question();
$question->shuffleanswers = false;
$question->init_first_step(new question_attempt_step());
$question->start_attempt(new question_attempt_step());
$this->assertEqual(array(1, question_state::$gradedright),
$question->grade_response(array('answer' => 0)));
@@ -95,7 +95,7 @@ class qtype_multichoice_single_question_test extends UnitTestCase {
16 => new question_answer(16, '6', -1, '', FORMAT_HTML),
);
$mc->init_first_step(new question_attempt_step());
$mc->start_attempt(new question_attempt_step());
list($grade, $state) = $mc->grade_response(
array('choice0' => 1, 'choice2' => 1, 'choice4' => 1));
@@ -106,7 +106,7 @@ class qtype_multichoice_single_question_test extends UnitTestCase {
public function test_get_correct_response() {
$question = test_question_maker::make_a_multichoice_single_question();
$question->shuffleanswers = false;
$question->init_first_step(new question_attempt_step());
$question->start_attempt(new question_attempt_step());
$this->assertEqual(array('answer' => 0),
$question->get_correct_response());
@@ -115,7 +115,7 @@ class qtype_multichoice_single_question_test extends UnitTestCase {
public function test_summarise_response() {
$mc = test_question_maker::make_a_multichoice_single_question();
$mc->shuffleanswers = false;
$mc->init_first_step(new question_attempt_step());
$mc->start_attempt(new question_attempt_step());
$summary = $mc->summarise_response(array('answer' => 0),
test_question_maker::get_a_qa($mc));
@@ -126,7 +126,7 @@ class qtype_multichoice_single_question_test extends UnitTestCase {
public function test_classify_response() {
$mc = test_question_maker::make_a_multichoice_single_question();
$mc->shuffleanswers = false;
$mc->init_first_step(new question_attempt_step());
$mc->start_attempt(new question_attempt_step());
$this->assertEqual(array(
$mc->id => new question_classified_response(14, 'B', -0.3333333),
@@ -149,7 +149,7 @@ class qtype_multichoice_multi_question_test extends UnitTestCase {
public function test_get_expected_data() {
$question = test_question_maker::make_a_multichoice_multi_question();
$question->init_first_step(new question_attempt_step());
$question->start_attempt(new question_attempt_step());
$this->assertEqual(array('choice0' => PARAM_BOOL, 'choice1' => PARAM_BOOL,
'choice2' => PARAM_BOOL, 'choice3' => PARAM_BOOL), $question->get_expected_data());
@@ -157,7 +157,7 @@ class qtype_multichoice_multi_question_test extends UnitTestCase {
public function test_is_complete_response() {
$question = test_question_maker::make_a_multichoice_multi_question();
$question->init_first_step(new question_attempt_step());
$question->start_attempt(new question_attempt_step());
$this->assertFalse($question->is_complete_response(array()));
$this->assertFalse($question->is_complete_response(
@@ -169,7 +169,7 @@ class qtype_multichoice_multi_question_test extends UnitTestCase {
public function test_is_gradable_response() {
$question = test_question_maker::make_a_multichoice_multi_question();
$question->init_first_step(new question_attempt_step());
$question->start_attempt(new question_attempt_step());
$this->assertFalse($question->is_gradable_response(array()));
$this->assertFalse($question->is_gradable_response(
@@ -182,7 +182,7 @@ class qtype_multichoice_multi_question_test extends UnitTestCase {
public function test_grading() {
$question = test_question_maker::make_a_multichoice_multi_question();
$question->shuffleanswers = false;
$question->init_first_step(new question_attempt_step());
$question->start_attempt(new question_attempt_step());
$this->assertEqual(array(1, question_state::$gradedright),
$question->grade_response(array('choice0' => '1', 'choice2' => '1')));
@@ -197,7 +197,7 @@ class qtype_multichoice_multi_question_test extends UnitTestCase {
public function test_get_correct_response() {
$question = test_question_maker::make_a_multichoice_multi_question();
$question->shuffleanswers = false;
$question->init_first_step(new question_attempt_step());
$question->start_attempt(new question_attempt_step());
$this->assertEqual(array('choice0' => '1', 'choice2' => '1'),
$question->get_correct_response());
@@ -205,7 +205,7 @@ class qtype_multichoice_multi_question_test extends UnitTestCase {
public function test_get_question_summary() {
$mc = test_question_maker::make_a_multichoice_single_question();
$mc->init_first_step(new question_attempt_step());
$mc->start_attempt(new question_attempt_step());
$qsummary = $mc->get_question_summary();
@@ -218,7 +218,7 @@ class qtype_multichoice_multi_question_test extends UnitTestCase {
public function test_summarise_response() {
$mc = test_question_maker::make_a_multichoice_multi_question();
$mc->shuffleanswers = false;
$mc->init_first_step(new question_attempt_step());
$mc->start_attempt(new question_attempt_step());
$summary = $mc->summarise_response(array('choice1' => 1, 'choice2' => 1),
test_question_maker::get_a_qa($mc));
@@ -229,7 +229,7 @@ class qtype_multichoice_multi_question_test extends UnitTestCase {
public function test_classify_response() {
$mc = test_question_maker::make_a_multichoice_multi_question();
$mc->shuffleanswers = false;
$mc->init_first_step(new question_attempt_step());
$mc->start_attempt(new question_attempt_step());
$this->assertEqual(array(
13 => new question_classified_response(13, 'A', 0.5),
+8 -8
View File
@@ -51,14 +51,14 @@ class qtype_numerical_question extends question_graded_by_strategy
return array('answer' => PARAM_RAW_TRIMMED);
}
public function init_first_step(question_attempt_step $step) {
if ($step->has_qt_var('_separators')) {
list($point, $separator) = explode('$', $step->get_qt_var('_separators'));
$this->ap->set_characters($point, $separator);
} else {
$step->set_qt_var('_separators',
$this->ap->get_point() . '$' . $this->ap->get_separator());
}
public function start_attempt(question_attempt_step $step) {
$step->set_qt_var('_separators',
$this->ap->get_point() . '$' . $this->ap->get_separator());
}
public function apply_attempt_state(question_attempt_step $step) {
list($point, $separator) = explode('$', $step->get_qt_var('_separators'));
$this->ap->set_characters($point, $separator);
}
public function summarise_response(array $response) {
@@ -49,7 +49,7 @@ class qtype_oumultiresponse_question_test extends UnitTestCase {
public function test_grade_responses_right_right() {
$mc = qtype_oumultiresponse_test_helper::make_an_oumultiresponse_two_of_four();
$mc->shuffleanswers = false;
$mc->init_first_step(new question_attempt_step());
$mc->start_attempt(new question_attempt_step());
list($fraction, $state) = $mc->grade_response(array('choice0' => '1', 'choice2' => '1'));
$this->assertWithinMargin(1, $fraction, $this->tolerance);
@@ -59,7 +59,7 @@ class qtype_oumultiresponse_question_test extends UnitTestCase {
public function test_grade_responses_right() {
$mc = qtype_oumultiresponse_test_helper::make_an_oumultiresponse_two_of_four();
$mc->shuffleanswers = false;
$mc->init_first_step(new question_attempt_step());
$mc->start_attempt(new question_attempt_step());
list($fraction, $state) = $mc->grade_response(array('choice0' => '1'));
$this->assertWithinMargin(0.5, $fraction, $this->tolerance);
@@ -69,7 +69,7 @@ class qtype_oumultiresponse_question_test extends UnitTestCase {
public function test_grade_responses_wrong_wrong() {
$mc = qtype_oumultiresponse_test_helper::make_an_oumultiresponse_two_of_four();
$mc->shuffleanswers = false;
$mc->init_first_step(new question_attempt_step());
$mc->start_attempt(new question_attempt_step());
list($fraction, $state) = $mc->grade_response(array('choice1' => '1', 'choice3' => '1'));
$this->assertWithinMargin(0, $fraction, $this->tolerance);
@@ -79,7 +79,7 @@ class qtype_oumultiresponse_question_test extends UnitTestCase {
public function test_grade_responses_right_wrong_wrong() {
$mc = qtype_oumultiresponse_test_helper::make_an_oumultiresponse_two_of_four();
$mc->shuffleanswers = false;
$mc->init_first_step(new question_attempt_step());
$mc->start_attempt(new question_attempt_step());
list($fraction, $state) = $mc->grade_response(array('choice0' => '1', 'choice1' => '1', 'choice3' => '1'));
$this->assertWithinMargin(0, $fraction, $this->tolerance);
@@ -89,7 +89,7 @@ class qtype_oumultiresponse_question_test extends UnitTestCase {
public function test_grade_responses_right_wrong() {
$mc = qtype_oumultiresponse_test_helper::make_an_oumultiresponse_two_of_four();
$mc->shuffleanswers = false;
$mc->init_first_step(new question_attempt_step());
$mc->start_attempt(new question_attempt_step());
list($fraction, $state) = $mc->grade_response(array('choice0' => '1', 'choice1' => '1'));
$this->assertWithinMargin(0.5, $fraction, $this->tolerance);
@@ -99,7 +99,7 @@ class qtype_oumultiresponse_question_test extends UnitTestCase {
public function test_grade_responses_right_right_wrong() {
$mc = qtype_oumultiresponse_test_helper::make_an_oumultiresponse_two_of_four();
$mc->shuffleanswers = false;
$mc->init_first_step(new question_attempt_step());
$mc->start_attempt(new question_attempt_step());
list($fraction, $state) = $mc->grade_response(array(
'choice0' => '1', 'choice2' => '1', 'choice3' => '1'));
@@ -110,7 +110,7 @@ class qtype_oumultiresponse_question_test extends UnitTestCase {
public function test_grade_responses_right_right_wrong_wrong() {
$mc = qtype_oumultiresponse_test_helper::make_an_oumultiresponse_two_of_four();
$mc->shuffleanswers = false;
$mc->init_first_step(new question_attempt_step());
$mc->start_attempt(new question_attempt_step());
list($fraction, $state) = $mc->grade_response(array(
'choice0' => '1', 'choice1' => '1', 'choice2' => '1', 'choice3' => '1'));
+27 -6
View File
@@ -146,15 +146,36 @@ abstract class question_definition {
}
/**
* Initialise the first step of an attempt at this quetsion.
* Start a new attempt at this question, storing any information that will
* be needed later in the step.
*
* For example, the multiple choice question type uses this method to
* randomly shuffle the choices, if that option has been set in the question.
* It then stores that order by calling $step->set_qt_var(...).
* This is where the question can do any initialisation required on a
* per-attempt basis. For example, this is where the multiple choice
* question type randomly shuffles the choices (if that option is set).
*
* @param question_attempt_step $step the step to be initialised.
* Any information about how the question has been set up for this attempt
* should be stored in the $step, by calling $step->set_qt_var(...).
*
* @param question_attempt_step The first step of the {@link question_attempt}
* being started. Can be used to store state.
*/
public function init_first_step(question_attempt_step $step) {
public function start_attempt(question_attempt_step $step) {
}
/**
* When an in-progress {@link question_attempt} is re-loaded from the
* database, this method is called so that the question can re-initialise
* its internal state as needed by this attempt.
*
* For example, the multiple choice question type needs to set the order
* of the choices to the order that was set up when start_attempt was called
* originally. All the information required to do this should be in the
* $step object, which is the first step of the question_attempt being loaded.
*
* @param question_attempt_step The first step of the {@link question_attempt}
* being loaded.
*/
public function apply_attempt_state(question_attempt_step $step) {
}
/**
@@ -132,7 +132,7 @@ class qtype_shortanswer_question_test extends UnitTestCase {
public function test_classify_response() {
$sa = test_question_maker::make_a_shortanswer_question();
$sa->init_first_step(new question_attempt_step());
$sa->start_attempt(new question_attempt_step());
$this->assertEqual(array(
new question_classified_response(13, 'frog', 1.0)),
@@ -93,7 +93,7 @@ class qtype_truefalse_question_test extends UnitTestCase {
public function test_classify_response() {
$tf = test_question_maker::make_a_truefalse_question();
$tf->init_first_step(new question_attempt_step());
$tf->start_attempt(new question_attempt_step());
$this->assertEqual(array(
$tf->id => new question_classified_response(0, get_string('false', 'qtype_truefalse'), 0.0)),