MDL-27413 qtype_multianswer upgrade. First passing test.

This commit is contained in:
Tim Hunt 2011-05-26 18:25:19 +01:00
parent dcedbb0e25
commit 1cacb05989
3 changed files with 300 additions and 45 deletions

View file

@ -37,5 +37,206 @@ require_once($CFG->dirroot . '/question/engine/upgrade/simpletest/helper.php');
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/ */
class qtype_multianswer_attempt_upgrader_test extends question_attempt_upgrader_test_base { class qtype_multianswer_attempt_upgrader_test extends question_attempt_upgrader_test_base {
// TODO public function test_multianswer_adaptivenopenalty_qsession104() {
$quiz = (object) array(
'id' => '5',
'course' => '2',
'name' => 'Multianswer 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' => '28,19,0',
'sumgrades' => '14.00000',
'grade' => '10.00000',
'timecreated' => '0',
'timemodified' => '1306424728',
'timelimit' => '0',
'password' => '',
'subnet' => '',
'popup' => '0',
'delay1' => '0',
'delay2' => '0',
'showuserpicture' => '0',
'showblocks' => '0',
'preferredbehaviour' => 'adaptivenopenalty',
);
$attempt = (object) array(
'id' => '16',
'uniqueid' => '16',
'quiz' => '5',
'userid' => '4',
'attempt' => '1',
'sumgrades' => '6.00000',
'timestart' => '1306425691',
'timefinish' => '1306425746',
'timemodified' => '1306425746',
'layout' => '28,19,0',
'preview' => '0',
'needsupgradetonewqe' => 1,
);
$question = (object) array(
'id' => '28',
'category' => '2',
'parent' => '0',
'name' => 'Very simple cloze',
'questiontext' => '<p>An answer {#1}.</p>',
'questiontextformat' => '1',
'generalfeedback' => '',
'generalfeedbackformat' => '1',
'penalty' => '0.1000000',
'qtype' => 'multianswer',
'length' => '1',
'stamp' => 'tjh238.vledev2.open.ac.uk+110526154631+XQLcXi',
'version' => 'tjh238.vledev2.open.ac.uk+110526154631+T8hPiI',
'hidden' => '0',
'timecreated' => '1306424791',
'timemodified' => '1306424791',
'createdby' => '2',
'modifiedby' => '2',
'maxmark' => '1.0000000',
'options' => (object) array(
'questions' => array(
1 => (object) array(
'id' => '29',
'category' => '2',
'parent' => '28',
'name' => 'Very simple cloze',
'questiontext' => '{1:SHORTANSWER:=frog#Yay!}',
'questiontextformat' => '0',
'generalfeedback' => '',
'generalfeedbackformat' => '1',
'defaultgrade' => '1.0000000',
'penalty' => '0.0000000',
'qtype' => 'shortanswer',
'length' => '1',
'stamp' => 'tjh238.vledev2.open.ac.uk+110526154631+j3BYTL',
'version' => 'tjh238.vledev2.open.ac.uk+110526154631+lxNwQv',
'hidden' => '0',
'timecreated' => '1306424791',
'timemodified' => '1306424791',
'createdby' => '2',
'modifiedby' => '2',
'options' => (object) array(
'answers' => array(
52 => (object) array(
'id' => '52',
'question' => '29',
'answer' => 'frog',
'answerformat' => '0',
'fraction' => '1.0000000',
'feedback' => 'Yay!',
'feedbackformat' => '1',
),
),
'usecase' => '0',
),
'maxgrade' => '1.0000000',
),
),
),
'defaultmark' => '1.0000000',
);
$qsession = (object) array(
'id' => '104',
'attemptid' => '16',
'questionid' => '28',
'newest' => '285',
'newgraded' => '285',
'sumpenalty' => '0.1000000',
'manualcomment' => '',
'manualcommentformat' => '1',
'flagged' => '0',
);
$qstates = array(
281 => (object) array(
'id' => '281',
'attempt' => '16',
'question' => '28',
'seq_number' => '0',
'answer' => '1-',
'timestamp' => '1306425691',
'event' => '0',
'grade' => '0.0000000',
'raw_grade' => '0.0000000',
'penalty' => '0.0000000',
),
283 => (object) array(
'id' => '283',
'attempt' => '16',
'question' => '28',
'seq_number' => '1',
'answer' => '1-frog',
'timestamp' => '1306425739',
'event' => '2',
'grade' => '0.0000000',
'raw_grade' => '1.0000000',
'penalty' => '0.1000000',
),
285 => (object) array(
'id' => '285',
'attempt' => '16',
'question' => '28',
'seq_number' => '2',
'answer' => '1-frog',
'timestamp' => '1306425739',
'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' => 'adaptivenopenalty',
'questionid' => 28,
'maxmark' => 1.0000000,
'minfraction' => 0,
'flagged' => 0,
'questionsummary' => 'An answer _____.',
'rightanswer' => 'part 1: frog',
'responsesummary' => 'part 1: frog',
'timemodified' => 1306425739,
'steps' => array(
0 => (object) array(
'sequencenumber' => 0,
'state' => 'todo',
'fraction' => null,
'timecreated' => 1306425691,
'userid' => 4,
'data' => array('-_try' => 1),
),
1 => (object) array(
'sequencenumber' => 1,
'state' => 'complete',
'fraction' => null,
'timecreated' => 1306425739,
'userid' => 4,
'data' => array('sub1_answer' => 'frog'),
),
2 => (object) array(
'sequencenumber' => 2,
'state' => 'gradedright',
'fraction' => 1.0,
'timecreated' => 1306425739,
'userid' => 4,
'data' => array('sub1_answer' => 'frog', '-finish' => '1',
'-_try' => '1', '-_rawfraction' => 1.0),
),
),
);
$this->assertEqual($expectedqa, $qa);
}
} }

View file

@ -37,55 +37,77 @@ defined('MOODLE_INTERNAL') || die();
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/ */
class qtype_multianswer_qe2_attempt_updater extends question_qtype_attempt_updater { class qtype_multianswer_qe2_attempt_updater extends question_qtype_attempt_updater {
// TODO
public function right_answer() { public function question_summary() {
foreach ($this->question->options->answers as $ans) { $summary = $this->to_text($this->question->questiontext);
if ($ans->fraction > 0.999) { foreach ($this->question->options->questions as $i => $subq) {
return $ans->answer; switch ($subq->qtype) {
case 'multichoice':
$choices = array();
foreach ($subq->options->answers as $ans) {
$choices[] = $this->to_text($ans->answer);
}
$answerbit = '{' . implode('; ', $choices) . '}';
break;
case 'numerical':
case 'shortanswer':
$answerbit = '_____';
break;
default:
$answerbit = '{ERR unknown sub-question type}';
} }
$summary = str_replace('{#' . $i . '}', $answerbit, $summary);
} }
return $summary;
} }
// public function restore_session_and_responses(&$question, &$state) { public function right_answer() {
// $responses = explode(',', $state->responses['']); $right = array();
// $state->responses = array();
// foreach ($responses as $response) { foreach ($this->question->options->questions as $i => $subq) {
// $tmp = explode("-", $response); foreach ($subq->options->answers as $ans) {
// // restore encoded characters if ($ans->fraction > 0.999) {
// $state->responses[$tmp[0]] = str_replace(array("&#0044;", "&#0045;"), $right[$i] = $ans->answer;
// array(",", "-"), $tmp[1]); break;
// } }
// return true; }
// } }
//
// public function save_session_and_responses(&$question, &$state) { return $this->display_response($right);
// global $DB; }
// $responses = $state->responses;
// // encode - (hyphen) and , (comma) to &#0045; because they are used as public function explode_answer($answer) {
// // delimiters $response = array();
// array_walk($responses, create_function('&$val, $key',
// '$val = str_replace(array(",", "-"), array("&#0044;", "&#0045;"), $val); foreach (explode(',', $answer) as $part) {
// $val = "$key-$val";')); list($index, $partanswer) = explode('-', $part, 2);
// $responses = implode(',', $responses); $response[$index] = str_replace(
// array(",", "-"), array('&#0044;', '&#0045;'), $partanswer);
// // Set the legacy answer field }
// $DB->set_field('question_states', 'answer', $responses, array('id' => $state->id));
// return true; return $response;
// } }
public function display_response($response) {
$summary = array();
foreach ($this->question->options->questions as $i => $subq) {
$a = new stdClass();
$a->i = $i;
$a->response = $this->to_text($response[$i]);
$summary[] = get_string('subqresponse', 'qtype_multianswer', $a);
}
return implode('; ', $summary);
}
public function response_summary($state) { public function response_summary($state) {
if (is_numeric($state->answer)) { $response = $this->explode_answer($state->answer);
if (array_key_exists($state->answer, $this->question->options->answers)) { foreach ($this->question->options->questions as $i => $subq) {
return $this->question->options->answers[$state->answer]->answer; if ($response[$i] && $subq->qtype == 'multichoice') {
} else { $response[$i] = $subq->options->answers[$response[$i]];
$this->logger->log_assumption("Dealing with a place where the
student selected a choice that was later deleted for
true/false question {$this->question->id}");
return null;
} }
} else {
return null;
} }
return $this->display_response($response);
} }
public function was_answered($state) { public function was_answered($state) {
@ -99,8 +121,38 @@ class qtype_multianswer_qe2_attempt_updater extends question_qtype_attempt_updat
} }
public function set_data_elements_for_step($state, &$data) { public function set_data_elements_for_step($state, &$data) {
if (is_numeric($state->answer)) { $response = $this->explode_answer($state->answer);
$data['answer'] = (int) ($state->answer == $this->question->options->trueanswer); foreach ($this->question->options->questions as $i => $subq) {
if (empty($response[$i])) {
continue;
}
switch ($subq->qtype) {
case 'multichoice':
$choices = array();
foreach ($subq->options->answers as $ans) {
$choices[] = $this->to_text($ans->answer);
}
$answerbit = '{' . implode('; ', $choices) . '}';
break;
case 'numerical':
case 'shortanswer':
$data[$this->add_prefix('answer', $i)] = $response[$i];
break;
}
}
}
public function add_prefix($field, $i) {
$prefix = 'sub' . $i . '_';
if (substr($field, 0, 2) === '!_') {
return '-_' . $prefix . substr($field, 2);
} else if (substr($field, 0, 1) === '-') {
return '-' . $prefix . substr($field, 1);
} else if (substr($field, 0, 1) === '_') {
return '_' . $prefix . substr($field, 1);
} else {
return $prefix . $field;
} }
} }
} }

View file

@ -318,6 +318,7 @@ function qtype_multianswer_extract_question($text) {
} else if (!empty($answerregs[ANSWER_REGEX_ANSWER_TYPE_MULTICHOICE])) { } else if (!empty($answerregs[ANSWER_REGEX_ANSWER_TYPE_MULTICHOICE])) {
$wrapped->qtype = 'multichoice'; $wrapped->qtype = 'multichoice';
$wrapped->single = 1; $wrapped->single = 1;
$wrapped->shuffleanswers = 1;
$wrapped->answernumbering = 0; $wrapped->answernumbering = 0;
$wrapped->correctfeedback['text'] = ''; $wrapped->correctfeedback['text'] = '';
$wrapped->correctfeedback['format'] = '1'; $wrapped->correctfeedback['format'] = '1';
@ -332,6 +333,7 @@ function qtype_multianswer_extract_question($text) {
} else if (!empty($answerregs[ANSWER_REGEX_ANSWER_TYPE_MULTICHOICE_REGULAR])) { } else if (!empty($answerregs[ANSWER_REGEX_ANSWER_TYPE_MULTICHOICE_REGULAR])) {
$wrapped->qtype = 'multichoice'; $wrapped->qtype = 'multichoice';
$wrapped->single = 1; $wrapped->single = 1;
$wrapped->shuffleanswers = 0;
$wrapped->answernumbering = 0; $wrapped->answernumbering = 0;
$wrapped->correctfeedback['text'] = ''; $wrapped->correctfeedback['text'] = '';
$wrapped->correctfeedback['format'] = '1'; $wrapped->correctfeedback['format'] = '1';
@ -346,6 +348,7 @@ function qtype_multianswer_extract_question($text) {
} else if (!empty($answerregs[ANSWER_REGEX_ANSWER_TYPE_MULTICHOICE_HORIZONTAL])) { } else if (!empty($answerregs[ANSWER_REGEX_ANSWER_TYPE_MULTICHOICE_HORIZONTAL])) {
$wrapped->qtype = 'multichoice'; $wrapped->qtype = 'multichoice';
$wrapped->single = 1; $wrapped->single = 1;
$wrapped->shuffleanswers = 0;
$wrapped->answernumbering = 0; $wrapped->answernumbering = 0;
$wrapped->correctfeedback['text'] = ''; $wrapped->correctfeedback['text'] = '';
$wrapped->correctfeedback['format'] = '1'; $wrapped->correctfeedback['format'] = '1';
@ -368,7 +371,6 @@ function qtype_multianswer_extract_question($text) {
$wrapped->answer = array(); $wrapped->answer = array();
$wrapped->fraction = array(); $wrapped->fraction = array();
$wrapped->feedback = array(); $wrapped->feedback = array();
$wrapped->shuffleanswers = 1;
$wrapped->questiontext['text'] = $answerregs[0]; $wrapped->questiontext['text'] = $answerregs[0];
$wrapped->questiontext['format'] = 0; $wrapped->questiontext['format'] = 0;
$wrapped->questiontext['itemid'] = ''; $wrapped->questiontext['itemid'] = '';