MDL-27649 Convert the calculated question types to use the new variants mechanism.

This commit is contained in:
Tim Hunt
2011-05-26 21:53:47 +01:00
parent 1da821bbde
commit c014b989ba
16 changed files with 186 additions and 72 deletions
+1
View File
@@ -235,6 +235,7 @@ $string['questionsrescuedfrom'] = 'Questions saved from context {$a}.';
$string['questionsrescuedfrominfo'] = 'These questions (some of which may be hidden) were saved when context {$a} was deleted because they are still used by some quizzes or other activities.';
$string['questiontype'] = 'Question type';
$string['questionuse'] = 'Use question in this activity';
$string['questionvariant'] = 'Question variant';
$string['reviewresponse'] = 'Review response';
$string['saveflags'] = 'Save the state of the flags';
$string['selectacategory'] = 'Select a category:';
+20 -12
View File
@@ -699,20 +699,28 @@ function question_move_category_to_context($categoryid, $oldcontextid, $newconte
* @param string $preferredbehaviour the behaviour to use for the preview.
* @param float $maxmark the maximum to mark the question out of.
* @param question_display_options $displayoptions the display options to use.
* @param int $variant the variant of the question to preview. If null, one will
* be picked randomly.
* @return string the URL.
*/
function question_preview_url($questionid, $preferredbehaviour, $maxmark, $displayoptions) {
return new moodle_url('/question/preview.php', array(
'id' => $questionid,
'behaviour' => $preferredbehaviour,
'maxmark' => $maxmark,
'correctness' => $displayoptions->correctness,
'marks' => $displayoptions->marks,
'markdp' => $displayoptions->markdp,
'feedback' => (bool) $displayoptions->feedback,
'generalfeedback' => (bool) $displayoptions->generalfeedback,
'rightanswer' => (bool) $displayoptions->rightanswer,
'history' => (bool) $displayoptions->history));
function question_preview_url($questionid, $preferredbehaviour, $maxmark, $displayoptions,
$variant = null) {
$params = array(
'id' => $questionid,
'behaviour' => $preferredbehaviour,
'maxmark' => $maxmark,
'correctness' => $displayoptions->correctness,
'marks' => $displayoptions->marks,
'markdp' => $displayoptions->markdp,
'feedback' => (bool) $displayoptions->feedback,
'generalfeedback' => (bool) $displayoptions->generalfeedback,
'rightanswer' => (bool) $displayoptions->rightanswer,
'history' => (bool) $displayoptions->history
);
if ($variant) {
$params['variant'] = $variant;
}
return new moodle_url('/question/preview.php', $params);
}
/**
+9 -2
View File
@@ -144,8 +144,15 @@ if (!($quiz->attemptonlast && $lastattempt)) {
$questionsinuse[] = $question->id;
}
// Start all the quetsions.
$quba->start_all_questions(null, time(), null);
// Start all the questions.
if ($attempt->preview) {
$variantoffset = rand(1, 100);
} else {
$variantoffset = $attemptnumber;
}
$quba->start_all_questions(
new question_variant_pseudorandom_no_repeats_strategy($variantoffset),
time());
// Update attempt layout.
$newlayout = array();
+48 -2
View File
@@ -765,7 +765,7 @@ abstract class question_utils {
/**
* The interface for strategies for controlling which variant of each question is used.
*
* @copyright 2010 The Open University
* @copyright 2011 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
interface question_variant_selection_strategy {
@@ -782,7 +782,7 @@ interface question_variant_selection_strategy {
/**
* A {@link question_variant_selection_strategy} that is completely random.
*
* @copyright 2010 The Open University
* @copyright 2011 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class question_variant_random_strategy implements question_variant_selection_strategy {
@@ -790,3 +790,49 @@ class question_variant_random_strategy implements question_variant_selection_str
return rand(1, $maxvariants);
}
}
/**
* A {@link question_variant_selection_strategy} that is effectively random
* for the first attempt, and then after that cycles through the available
* variants so that the students will not get a repeated variant until they have
* seen them all.
*
* @copyright 2011 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class question_variant_pseudorandom_no_repeats_strategy
implements question_variant_selection_strategy {
/** @var int the number of attempts this users has had, including the curent one. */
protected $attemptno;
/** @var int the user id the attempt belongs to. */
protected $userid;
/**
* Constructor.
* @param int $attemptno The attempt number.
* @param int $userid the user the attempt is for (defaults to $USER->id).
*/
public function __construct($attemptno, $userid = null) {
$this->attemptno = $attemptno;
if (is_null($userid)) {
global $USER;
$this->userid = $USER->id;
} else {
$this->userid = $userid;
}
}
public function choose_variant($maxvariants, $seed) {
if ($maxvariants == 1) {
return 1;
}
$hash = sha1($seed . '|user' . $this->userid);
$randint = hexdec(substr($hash, 17, 7));
return ($randint + $this->attemptno) % $maxvariants + 1;
}
}
+2 -2
View File
@@ -424,10 +424,10 @@ class qbehaviour_walkthrough_test_base extends UnitTestCase {
}
protected function start_attempt_at_question($question, $preferredbehaviour,
$maxmark = null) {
$maxmark = null, $variant = 1) {
$this->quba->set_preferred_behaviour($preferredbehaviour);
$this->slot = $this->quba->add_question($question, $maxmark);
$this->quba->start_all_questions();
$this->quba->start_question($this->slot, $variant);
}
protected function process_submission($data) {
$this->quba->process_action($this->slot, $data);
+17 -6
View File
@@ -38,12 +38,14 @@ require_once(dirname(__FILE__) . '/previewlib.php');
$id = required_param('id', PARAM_INT);
$question = question_bank::load_question($id);
require_login();
$category = $DB->get_record('question_categories', array('id' => $question->category), '*', MUST_EXIST);
$category = $DB->get_record('question_categories',
array('id' => $question->category), '*', MUST_EXIST);
question_require_capability_on($question, 'use');
$PAGE->set_pagelayout('popup');
$PAGE->set_context(get_context_instance_by_id($category->contextid));
// Get and validate display options.
$maxvariant = $question->get_num_variants();
$options = new question_preview_options($question);
$options->load_user_defaults();
$options->set_from_request();
@@ -57,7 +59,7 @@ if ($previewid) {
}
try {
$quba = question_engine::load_questions_usage_by_activity($previewid);
} catch (Exception $e){
} catch (Exception $e) {
print_error('submissionoutofsequencefriendlymessage', 'question',
question_preview_url($question->id, $options->behaviour,
$options->maxmark, $options), null, $e);
@@ -68,13 +70,21 @@ if ($previewid) {
print_error('questionidmismatch', 'question');
}
$question = $usedquestion;
$options->variant = $quba->get_variant($slot);
} else {
$quba = question_engine::make_questions_usage_by_activity('core_question_preview',
get_context_instance_by_id($category->contextid));
$quba->set_preferred_behaviour($options->behaviour);
$slot = $quba->add_question($question, $options->maxmark);
$quba->start_all_questions();
if ($options->variant) {
$options->variant = min($maxvariant, max(1, $options->variant));
} else {
$options->variant = rand(1, $maxvariant);
}
$quba->start_question($slot, $options->variant);
$transaction = $DB->start_delegated_transaction();
question_engine::save_questions_usage_by_activity($quba);
@@ -86,7 +96,8 @@ $options->behaviour = $quba->get_preferred_behaviour();
$options->maxmark = $quba->get_question_max_mark($slot);
// Create the settings form, and initialise the fields.
$optionsform = new preview_options_form($CFG->wwwroot . '/question/preview.php?id=' . $question->id, $quba);
$optionsform = new preview_options_form(new moodle_url('/question/preview.php',
array('id' => $question->id)), array('quba' => $quba, 'maxvariant' => $maxvariant));
$optionsform->set_data($options);
// Process change of settings, if that was requested.
@@ -117,7 +128,7 @@ if (data_submitted() && confirm_sesskey()) {
} else if (optional_param('finish', null, PARAM_BOOL)) {
try {
$quba->process_all_actions();
} catch (question_out_of_sequence_exception $e){
} catch (question_out_of_sequence_exception $e) {
print_error('submissionoutofsequencefriendlymessage', 'question', $actionurl);
}
$quba->finish_all_questions();
@@ -130,7 +141,7 @@ if (data_submitted() && confirm_sesskey()) {
} else {
try {
$quba->process_all_actions();
} catch (question_out_of_sequence_exception $e){
} catch (question_out_of_sequence_exception $e) {
print_error('submissionoutofsequencefriendlymessage', 'question', $actionurl);
}
+33 -11
View File
@@ -46,14 +46,25 @@ class preview_options_form extends moodleform {
$mform->addElement('header', 'optionsheader', get_string('changeoptions', 'question'));
$behaviours = question_engine::get_behaviour_options($this->_customdata->get_preferred_behaviour());
$mform->addElement('select', 'behaviour', get_string('howquestionsbehave', 'question'), $behaviours);
$behaviours = question_engine::get_behaviour_options(
$this->_customdata['quba']->get_preferred_behaviour());
$mform->addElement('select', 'behaviour',
get_string('howquestionsbehave', 'question'), $behaviours);
$mform->addHelpButton('behaviour', 'howquestionsbehave', 'question');
$mform->addElement('text', 'maxmark', get_string('markedoutof', 'question'), array('size' => '5'));
$mform->addElement('text', 'maxmark', get_string('markedoutof', 'question'),
array('size' => '5'));
$mform->setType('maxmark', PARAM_NUMBER);
$mform->addElement('select', 'correctness', get_string('whethercorrect', 'question'), $hiddenofvisible);
if ($this->_customdata['maxvariant'] > 1) {
$variants = range(1, $this->_customdata['maxvariant']);
$mform->addElement('select', 'variant', get_string('questionvariant', 'question'),
array_combine($variants, $variants));
}
$mform->setType('maxmark', PARAM_INT);
$mform->addElement('select', 'correctness', get_string('whethercorrect', 'question'),
$hiddenofvisible);
$marksoptions = array(
question_display_options::HIDDEN => get_string('notshown', 'question'),
@@ -65,15 +76,20 @@ class preview_options_form extends moodleform {
$mform->addElement('select', 'markdp', get_string('decimalplacesingrades', 'question'),
question_engine::get_dp_options());
$mform->addElement('select', 'feedback', get_string('specificfeedback', 'question'), $hiddenofvisible);
$mform->addElement('select', 'feedback',
get_string('specificfeedback', 'question'), $hiddenofvisible);
$mform->addElement('select', 'generalfeedback', get_string('generalfeedback', 'question'), $hiddenofvisible);
$mform->addElement('select', 'generalfeedback',
get_string('generalfeedback', 'question'), $hiddenofvisible);
$mform->addElement('select', 'rightanswer', get_string('rightanswer', 'question'), $hiddenofvisible);
$mform->addElement('select', 'rightanswer',
get_string('rightanswer', 'question'), $hiddenofvisible);
$mform->addElement('select', 'history', get_string('responsehistory', 'question'), $hiddenofvisible);
$mform->addElement('select', 'history',
get_string('responsehistory', 'question'), $hiddenofvisible);
$mform->addElement('submit', 'submit', get_string('restartwiththeseoptions', 'question'), $hiddenofvisible);
$mform->addElement('submit', 'submit',
get_string('restartwiththeseoptions', 'question'), $hiddenofvisible);
}
}
@@ -92,6 +108,9 @@ class question_preview_options extends question_display_options {
/** @var number the maximum mark to use for this preview. */
public $maxmark;
/** @var int the variant of the question to preview. */
public $variant;
/** @var string prefix to append to field names to get user_preference names. */
const OPTIONPREFIX = 'question_preview_options_';
@@ -102,6 +121,7 @@ class question_preview_options extends question_display_options {
global $CFG;
$this->behaviour = 'deferredfeedback';
$this->maxmark = $question->defaultmark;
$this->variant = null;
$this->correctness = self::VISIBLE;
$this->marks = self::MARK_AND_MAX;
$this->markdp = get_config('quiz', 'decimalpoints');
@@ -129,6 +149,7 @@ class question_preview_options extends question_display_options {
return array(
'behaviour' => PARAM_ALPHA,
'maxmark' => PARAM_NUMBER,
'variant' => PARAM_INT,
'correctness' => PARAM_BOOL,
'marks' => PARAM_INT,
'markdp' => PARAM_INT,
@@ -179,7 +200,7 @@ class question_preview_options extends question_display_options {
public function get_query_string() {
$querystring = array();
foreach ($this->get_field_types() as $field => $notused) {
if ($field == 'behaviour' || $field == 'maxmark') {
if ($field == 'behaviour' || $field == 'maxmark' || is_null($this->$field)) {
continue;
}
$querystring[] = $field . '=' . $this->$field;
@@ -266,5 +287,6 @@ function restart_preview($previewid, $questionid, $displayoptions) {
question_engine::delete_questions_usage_by_activity($previewid);
$transaction->allow_commit();
}
redirect(question_preview_url($questionid, $displayoptions->behaviour, $displayoptions->maxmark, $displayoptions));
redirect(question_preview_url($questionid, $displayoptions->behaviour,
$displayoptions->maxmark, $displayoptions, $displayoptions->variant));
}
@@ -200,7 +200,7 @@ class qtype_calculated_attempt_upgrader_test extends question_attempt_upgrader_t
$expectedqa = (object) array(
'behaviour' => 'adaptive',
'questionid' => 18,
'variant' => 1,
'variant' => 10,
'maxmark' => 1.0000000,
'minfraction' => 0,
'flagged' => 0,
@@ -219,7 +219,7 @@ Remember to type a unit.',
'fraction' => null,
'timecreated' => 1305830650,
'userid' => 4,
'data' => array('-_try' => 1, '_dataset' => '10', '_separators' => '.$,',
'data' => array('-_try' => 1, '_separators' => '.$,',
'_var_a' => '7.5', '_var_b' => '4.9'),
),
1 => (object) array(
@@ -423,7 +423,7 @@ Remember to type a unit.',
$expectedqa = (object) array(
'behaviour' => 'adaptive',
'questionid' => 18,
'variant' => 1,
'variant' => 11,
'maxmark' => 1.0000000,
'minfraction' => 0,
'flagged' => 0,
@@ -442,7 +442,7 @@ Remember to type a unit.',
'fraction' => null,
'timecreated' => 1305830661,
'userid' => 4,
'data' => array('-_try' => 1, '_dataset' => '11', '_separators' => '.$,',
'data' => array('-_try' => 1, '_separators' => '.$,',
'_var_a' => '5.1', '_var_b' => '4.5'),
),
1 => (object) array(
@@ -672,7 +672,7 @@ Remember to type a unit.',
'fraction' => null,
'timecreated' => 1305830744,
'userid' => 3,
'data' => array('-_try' => 1, '_dataset' => '1', '_separators' => '.$,',
'data' => array('-_try' => 1, '_separators' => '.$,',
'_var_a' => '9.9', '_var_b' => '2.5'),
),
1 => (object) array(
+1 -1
View File
@@ -141,7 +141,6 @@ class qtype_calculated_qe2_attempt_updater extends question_qtype_attempt_update
$this->replace_expressions_in_text($this->question->questiontext));
$this->updater->qa->rightanswer = $this->right_answer($this->question);
$data['_dataset'] = $this->selecteditem;
foreach ($this->values as $name => $value) {
$data['_var_' . $name] = $value;
}
@@ -181,6 +180,7 @@ class qtype_calculated_qe2_attempt_updater extends question_qtype_attempt_update
public function load_dataset($selecteditem) {
$this->selecteditem = $selecteditem;
$this->updater->qa->variant = $selecteditem;
$this->values = $this->qeupdater->load_dataset(
$this->question->id, $selecteditem);
+17 -14
View File
@@ -51,7 +51,7 @@ class qtype_calculated_question extends qtype_numerical_question
public $synchronised;
public function start_attempt(question_attempt_step $step, $variant) {
qtype_calculated_question_helper::start_attempt($this, $step);
qtype_calculated_question_helper::start_attempt($this, $step, $variant);
parent::start_attempt($step, $variant);
}
@@ -73,6 +73,19 @@ class qtype_calculated_question extends qtype_numerical_question
$ans->correctanswerlength, $ans->correctanswerformat);
}
}
public function get_num_variants() {
return $this->datasetloader->get_number_of_items();
}
public function get_variants_selection_seed() {
if (!empty($this->synchronised) &&
$this->datasetloader->datasets_are_synchronised($question->category)) {
return 'category' . $this->category;
} else {
return parent::get_variants_selection_seed();
}
}
}
@@ -110,24 +123,14 @@ interface qtype_calculated_question_with_expressions {
*/
abstract class qtype_calculated_question_helper {
public static function start_attempt(
qtype_calculated_question_with_expressions $question, question_attempt_step $step) {
$maxnumber = $question->datasetloader->get_number_of_items();
if (!empty($question->synchronised) &&
$question->datasetloader->datasets_are_synchronised($question->category)) {
$setnumber = ($step->get_timecreated() % $maxnumber) + 1;
} else {
$setnumber = rand(1, $maxnumber);
}
qtype_calculated_question_with_expressions $question,
question_attempt_step $step, $variant) {
$question->vs = new qtype_calculated_variable_substituter(
$question->datasetloader->get_values($setnumber),
$question->datasetloader->get_values($variant),
get_string('decsep', 'langconfig'));
$question->calculate_all_expressions();
$step->set_qt_var('_dataset', $setnumber);
foreach ($question->vs->get_values() as $name => $value) {
$step->set_qt_var('_var_' . $name, $value);
}
@@ -44,8 +44,9 @@ class qtype_calculated_walkthrough_test extends qbehaviour_walkthrough_test_base
new question_hint(1, 'This is the first hint.', FORMAT_HTML),
new question_hint(2, 'This is the second hint.', FORMAT_HTML),
);
$this->start_attempt_at_question($q, 'interactive', 3);
$this->start_attempt_at_question($q, 'interactive', 3, 1);
$values = $q->vs->get_values();
$this->assertEqual($values, $q->datasetloader->load_values(1));
// Check the initial state.
$this->check_current_state(question_state::$todo);
@@ -227,7 +227,7 @@ class qtype_calculatedmulti_attempt_upgrader_test extends question_attempt_upgra
$expectedqa = (object) array(
'behaviour' => 'adaptive',
'questionid' => 17,
'variant' => 1,
'variant' => 3,
'maxmark' => 1.0000000,
'minfraction' => 0,
'flagged' => 0,
@@ -242,7 +242,7 @@ class qtype_calculatedmulti_attempt_upgrader_test extends question_attempt_upgra
'fraction' => null,
'timecreated' => 1305830650,
'userid' => 4,
'data' => array('-_try' => 1, '_dataset' => '3',
'data' => array('-_try' => 1,
'_order' => '24,26,27,25', '_var_a' => '4.3', '_var_b' => '5.4'),
),
1 => (object) array(
@@ -461,7 +461,7 @@ class qtype_calculatedmulti_attempt_upgrader_test extends question_attempt_upgra
$expectedqa = (object) array(
'behaviour' => 'adaptive',
'questionid' => 17,
'variant' => 1,
'variant' => 8,
'maxmark' => 1.0000000,
'minfraction' => 0,
'flagged' => 0,
@@ -476,7 +476,7 @@ class qtype_calculatedmulti_attempt_upgrader_test extends question_attempt_upgra
'fraction' => null,
'timecreated' => 1305830661,
'userid' => 4,
'data' => array('-_try' => 1, '_dataset' => '8',
'data' => array('-_try' => 1,
'_order' => '25,24,27,26', '_var_a' => '3.7', '_var_b' => '6.0'),
),
1 => (object) array(
@@ -739,7 +739,7 @@ class qtype_calculatedmulti_attempt_upgrader_test extends question_attempt_upgra
$expectedqa = (object) array(
'behaviour' => 'adaptive',
'questionid' => 17,
'variant' => 1,
'variant' => 7,
'maxmark' => 1.0000000,
'minfraction' => 0,
'flagged' => 0,
@@ -754,7 +754,7 @@ class qtype_calculatedmulti_attempt_upgrader_test extends question_attempt_upgra
'fraction' => null,
'timecreated' => 1305830744,
'userid' => 3,
'data' => array('-_try' => 1, '_dataset' => '7',
'data' => array('-_try' => 1,
'_order' => '26,24,25,27', '_var_a' => '4.4', '_var_b' => '8.2'),
),
1 => (object) array(
@@ -164,7 +164,6 @@ class qtype_calculatedmulti_qe2_attempt_updater extends question_qtype_attempt_u
$this->replace_expressions_in_text($this->question->questiontext));
$this->updater->qa->rightanswer = $this->right_answer($this->question);
$data['_dataset'] = $this->selecteditem;
foreach ($this->values as $name => $value) {
$data['_var_' . $name] = $value;
}
@@ -205,6 +204,7 @@ class qtype_calculatedmulti_qe2_attempt_updater extends question_qtype_attempt_u
public function load_dataset($selecteditem) {
$this->selecteditem = $selecteditem;
$this->updater->qa->variant = $selecteditem;
$this->values = $this->qeupdater->load_dataset(
$this->question->id, $selecteditem);
+16 -2
View File
@@ -52,8 +52,8 @@ class qtype_calculatedmulti_single_question extends qtype_multichoice_single_que
public $synchronised;
public function start_attempt(question_attempt_step $step, $variant) {
qtype_calculated_question_helper::start_attempt($this, $step);
parent::start_attempt($step);
qtype_calculated_question_helper::start_attempt($this, $step, $variant);
parent::start_attempt($step, $variant);
}
public function apply_attempt_state(question_attempt_step $step) {
@@ -64,6 +64,20 @@ class qtype_calculatedmulti_single_question extends qtype_multichoice_single_que
public function calculate_all_expressions() {
qtype_calculatedmulti_calculate_helper::calculate_all_expressions($this);
}
public function get_num_variants() {
return $this->datasetloader->get_number_of_items();
}
public function get_variants_selection_seed() {
if (!empty($this->synchronised) &&
$this->datasetloader->datasets_are_synchronised($question->category)) {
return 'category' . $this->category;
} else {
return parent::get_variants_selection_seed();
}
}
}
@@ -44,8 +44,9 @@ class qtype_calculatedmulti_walkthrough_test extends qbehaviour_walkthrough_test
new question_hint(1, 'This is the first hint.', FORMAT_HTML),
new question_hint(2, 'This is the second hint.', FORMAT_HTML),
);
$this->start_attempt_at_question($q, 'interactive', 3);
$this->start_attempt_at_question($q, 'interactive', 3, 2);
$values = $q->vs->get_values();
$this->assertEqual($values, $q->datasetloader->load_values(2));
// Check the initial state.
$this->check_current_state(question_state::$todo);
@@ -191,7 +191,7 @@ class qtype_calculatedsimple_attempt_upgrader_test extends question_attempt_upgr
$expectedqa = (object) array(
'behaviour' => 'adaptive',
'questionid' => 16,
'variant' => 1,
'variant' => 7,
'maxmark' => 1.0000000,
'minfraction' => 0,
'flagged' => 0,
@@ -206,7 +206,7 @@ class qtype_calculatedsimple_attempt_upgrader_test extends question_attempt_upgr
'fraction' => null,
'timecreated' => 1305830650,
'userid' => 4,
'data' => array('-_try' => 1, '_dataset' => '7', '_separators' => '.$,',
'data' => array('-_try' => 1, '_separators' => '.$,',
'_var_a' => '3', '_var_b' => '6'),
),
1 => (object) array(
@@ -401,7 +401,7 @@ class qtype_calculatedsimple_attempt_upgrader_test extends question_attempt_upgr
$expectedqa = (object) array(
'behaviour' => 'adaptive',
'questionid' => 16,
'variant' => 1,
'variant' => 4,
'maxmark' => 1.0000000,
'minfraction' => 0,
'flagged' => 0,
@@ -416,7 +416,7 @@ class qtype_calculatedsimple_attempt_upgrader_test extends question_attempt_upgr
'fraction' => null,
'timecreated' => 1305830661,
'userid' => 4,
'data' => array('-_try' => 1, '_dataset' => '4', '_separators' => '.$,',
'data' => array('-_try' => 1, '_separators' => '.$,',
'_var_a' => '6.4', '_var_b' => '9'),
),
1 => (object) array(
@@ -603,7 +603,7 @@ class qtype_calculatedsimple_attempt_upgrader_test extends question_attempt_upgr
$expectedqa = (object) array(
'behaviour' => 'adaptive',
'questionid' => 16,
'variant' => 1,
'variant' => 6,
'maxmark' => 1.0000000,
'minfraction' => 0,
'flagged' => 0,
@@ -618,7 +618,7 @@ class qtype_calculatedsimple_attempt_upgrader_test extends question_attempt_upgr
'fraction' => null,
'timecreated' => 1305830744,
'userid' => 3,
'data' => array('-_try' => 1, '_dataset' => '6', '_separators' => '.$,',
'data' => array('-_try' => 1, '_separators' => '.$,',
'_var_a' => '6.1', '_var_b' => '7'),
),
1 => (object) array(