diff --git a/question/engine/simpletest/helpers.php b/question/engine/simpletest/helpers.php
index 39fb6bf35b6..4c06029aac5 100644
--- a/question/engine/simpletest/helpers.php
+++ b/question/engine/simpletest/helpers.php
@@ -115,6 +115,40 @@ class test_question_maker {
$q->modifiedby = $USER->id;
}
+ public static function initialise_question_data($qdata) {
+ global $USER;
+
+ $qdata->id = 0;
+ $qdata->category = 0;
+ $qdata->contextid = 0;
+ $qdata->parent = 0;
+ $qdata->questiontextformat = FORMAT_HTML;
+ $qdata->generalfeedbackformat = FORMAT_HTML;
+ $qdata->defaultmark = 1;
+ $qdata->penalty = 0.3333333;
+ $qdata->length = 1;
+ $qdata->stamp = make_unique_id_code();
+ $qdata->version = make_unique_id_code();
+ $qdata->hidden = 0;
+ $qdata->timecreated = time();
+ $qdata->timemodified = time();
+ $qdata->createdby = $USER->id;
+ $qdata->modifiedby = $USER->id;
+ $qdata->hints = array();
+ }
+
+ public static function initialise_question_form_data($qdata) {
+ $formdata = new stdClass();
+ $formdata->id = 0;
+ $formdata->category = '0,0';
+ $formdata->usecurrentcat = 1;
+ $formdata->categorymoveto = '0,0';
+ $formdata->tags = array();
+ $formdata->penalty = 0.3333333;
+ $formdata->questiontextformat = FORMAT_HTML;
+ $formdata->generalfeedbackformat = FORMAT_HTML;
+ }
+
/**
* Get the test helper class for a particular question type.
* @param $qtype the question type name, e.g. 'multichoice'.
@@ -143,7 +177,16 @@ class test_question_maker {
return self::$testhelpers[$qtype];
}
- public static function make_question($qtype, $which = null) {
+ /**
+ * Call a method on a qtype_{$qtype}_test_helper class and return the result.
+ *
+ * @param string $methodtemplate e.g. 'make_{qtype}_question_{which}';
+ * @param string $qtype the question type to get a test question for.
+ * @param string $which one of the names returned by the get_test_questions
+ * method of the relevant qtype_{$qtype}_test_helper class.
+ * @param unknown_type $which
+ */
+ protected static function call_question_helper_method($methodtemplate, $qtype, $which = null) {
$helper = self::get_test_helper($qtype);
$available = $helper->get_test_questions();
@@ -152,18 +195,64 @@ class test_question_maker {
$which = reset($available);
} else if (!in_array($which, $available)) {
throw new coding_exception('Example question ' . $which . ' of type ' .
- $qtype . ' does not exist.');
+ $qtype . ' does not exist.');
}
- $method = "make_{$qtype}_question_{$which}";
+ $method = str_replace(array('{qtype}', '{which}'),
+ array($qtype, $which), $methodtemplate);
+
if (!method_exists($helper, $method)) {
throw new coding_exception('Method ' . $method . ' does not exist on the' .
- $qtype . ' question type test helper class.');
+ $qtype . ' question type test helper class.');
}
return $helper->$method();
}
+ /**
+ * Question types can provide a number of test question defintions.
+ * They do this by creating a qtype_{$qtype}_test_helper class that extends
+ * question_test_helper. The get_test_questions method returns the list of
+ * test questions available for this question type.
+ *
+ * @param string $qtype the question type to get a test question for.
+ * @param string $which one of the names returned by the get_test_questions
+ * method of the relevant qtype_{$qtype}_test_helper class.
+ * @return question_definition the requested question object.
+ */
+ public static function make_question($qtype, $which = null) {
+ return self::call_question_helper_method('make_{qtype}_question_{which}',
+ $qtype, $which);
+ }
+
+ /**
+ * Like {@link make_question()} but returns the datastructure from
+ * get_question_options instead of the question_definition object.
+ *
+ * @param string $qtype the question type to get a test question for.
+ * @param string $which one of the names returned by the get_test_questions
+ * method of the relevant qtype_{$qtype}_test_helper class.
+ * @return stdClass the requested question object.
+ */
+ public static function get_question_data($qtype, $which = null) {
+ return self::call_question_helper_method('get_{qtype}_question_data_{which}',
+ $qtype, $which);
+ }
+
+ /**
+ * Like {@link make_question()} but returns the data what would be saved from
+ * the question editing form instead of the question_definition object.
+ *
+ * @param string $qtype the question type to get a test question for.
+ * @param string $which one of the names returned by the get_test_questions
+ * method of the relevant qtype_{$qtype}_test_helper class.
+ * @return stdClass the requested question object.
+ */
+ public static function get_question_form_data($qtype, $which = null) {
+ return self::call_question_helper_method('get_{qtype}_question_form_data_{which}',
+ $qtype, $which);
+ }
+
/**
* Makes a multichoice question with choices 'A', 'B' and 'C' shuffled. 'A'
* is correct, defaultmark 1.
diff --git a/question/format/xml/format.php b/question/format/xml/format.php
index b4fd721268d..6d973273076 100644
--- a/question/format/xml/format.php
+++ b/question/format/xml/format.php
@@ -408,34 +408,38 @@ class qformat_xml extends qformat_default {
* @param array question question array from xml tree
* @return object question object
*/
- public function import_multianswer($questions) {
+ public function import_multianswer($question) {
question_bank::get_qtype('multianswer');
- $questiontext = array();
- $questiontext['text'] = $this->import_text($questions['#']['questiontext'][0]['#']['text']);
+ $questiontext['text'] = $this->import_text($question['#']['questiontext'][0]['#']['text']);
$questiontext['format'] = '1';
$questiontext['itemid'] = '';
$qo = qtype_multianswer_extract_question($questiontext);
// 'header' parts particular to multianswer
- $qo->qtype = MULTIANSWER;
+ $qo->qtype = 'multianswer';
$qo->course = $this->course;
$qo->generalfeedback = '';
// restore files in generalfeedback
- $qo->generalfeedback = $this->getpath($questions,
+ $qo->generalfeedback = $this->getpath($question,
array('#', 'generalfeedback', 0, '#', 'text', 0, '#'), $qo->generalfeedback, true);
- $qo->generalfeedbackformat = $this->trans_format($this->getpath($questions,
+ $qo->generalfeedbackformat = $this->trans_format($this->getpath($question,
array('#', 'generalfeedback', 0, '@', 'format'), 'moodle_auto_format'));
- $qo->generalfeedbackfiles = $this->import_files($this->getpath($questions,
+ $qo->generalfeedbackfiles = $this->import_files($this->getpath($question,
array('#', 'generalfeedback', 0, '#', 'file'), array(), false));
- if (!empty($questions)) {
- $qo->name = $this->import_text($questions['#']['name'][0]['#']['text']);
- }
- $qo->questiontext = $qo->questiontext['text'];
+ $qo->name = $this->import_text($question['#']['name'][0]['#']['text']);
+ $qo->questiontext = $qo->questiontext['text'];
$qo->questiontextformat = '';
- $this->import_hints($qo, $questions, true);
+ $qo->penalty = $this->getpath($question,
+ array('#', 'penalty', 0, '#'), $this->defaultquestion()->penalty);
+ // Fix problematic rounding from old files:
+ if (abs($qo->penalty - 0.3333333) < 0.005) {
+ $qo->penalty = 0.3333333;
+ }
+
+ $this->import_hints($qo, $question);
return $qo;
}
@@ -633,12 +637,12 @@ class qformat_xml extends qformat_default {
* @param array question question array from xml tree
* @return object question object
*/
- public function import_matching($question) {
+ public function import_match($question) {
// get common parts
$qo = $this->import_headers($question);
// header parts particular to matching
- $qo->qtype = MATCH;
+ $qo->qtype = 'match';
$qo->shuffleanswers = $this->trans_single($this->getpath($question,
array('#', 'shuffleanswers', 0, '#'), 1));
@@ -900,9 +904,9 @@ class qformat_xml extends qformat_default {
$qo = $this->import_numerical($question);
} else if ($questiontype == 'description') {
$qo = $this->import_description($question);
- } else if ($questiontype == 'matching') {
- $qo = $this->import_matching($question);
- } else if ($questiontype == 'cloze') {
+ } else if ($questiontype == 'matching' || $questiontype == 'match') {
+ $qo = $this->import_match($question);
+ } else if ($questiontype == 'cloze' || $questiontype == 'multianswer') {
$qo = $this->import_multianswer($question);
} else if ($questiontype == 'essay') {
$qo = $this->import_essay($question);
@@ -942,34 +946,21 @@ class qformat_xml extends qformat_default {
}
/**
- * Turn the internal question code into a human readable form
- * (The code used to be numeric, but this remains as some of
- * the names don't match the new internal format)
- * @param mixed $typeid Internal code
- * @return string question type string
+ * Turn the internal question type name into a human readable form.
+ * (In the past, the code used to use integers internally. Now, it uses
+ * strings, so there is less need for this, but to maintain
+ * backwards-compatibility we change two of the type names.)
+ * @param string $qtype question type plugin name.
+ * @return string $qtype string to use in the file.
*/
- protected function get_qtype($typeid) {
- switch($typeid) {
- case TRUEFALSE:
- return 'truefalse';
- case MULTICHOICE:
- return 'multichoice';
- case SHORTANSWER:
- return 'shortanswer';
- case NUMERICAL:
- return 'numerical';
- case MATCH:
+ protected function get_qtype($qtype) {
+ switch($qtype) {
+ case 'match':
return 'matching';
- case DESCRIPTION:
- return 'description';
- case MULTIANSWER:
+ case 'multianswer':
return 'cloze';
- case ESSAY:
- return 'essay';
- case CALCULATED:
- return 'calculated';
default:
- return false;
+ return $qtype;
}
}
@@ -1085,13 +1076,9 @@ class qformat_xml extends qformat_default {
$expout .= "\n";
// Check question type
- if (!$questiontype = $this->get_qtype($question->qtype)) {
- // must be a plugin then, so just accept the name supplied
- $questiontype = $question->qtype;
- }
+ $questiontype = $this->get_qtype($question->qtype);
- // add opening tag
- // generates specific header for Cloze and category type question
+ // Categories are a special case.
if ($question->qtype == 'category') {
$categorypath = $this->writetext($question->category);
$expout .= " \n";
@@ -1100,47 +1087,29 @@ class qformat_xml extends qformat_default {
$expout .= " \n";
$expout .= " \n";
return $expout;
-
- } else if ($question->qtype != MULTIANSWER) {
- // for all question types except Close
- $name_text = $this->writetext($question->name, 3);
-
- $expout .= " \n";
- $expout .= " \n";
- $expout .= $name_text;
- $expout .= " \n";
- $expout .= " format($question->questiontextformat)}>\n";
- $expout .= $this->writetext($question->questiontext, 3);
- $expout .= $this->writefiles($question->questiontextfiles);
- $expout .= " \n";
- $expout .= " format($question->generalfeedbackformat)}>\n";
- $expout .= $this->writetext($question->generalfeedback, 3);
- $expout .= $this->writefiles($question->generalfeedbackfiles);
- $expout .= " \n";
- $expout .= " {$question->defaultmark}\n";
- $expout .= " {$question->penalty}\n";
- $expout .= " {$question->hidden}\n";
-
- } else {
- // for Cloze type only
- $name_text = $this->writetext($question->name);
- $question_text = $this->writetext($question->questiontext);
- $generalfeedback = $this->writetext($question->generalfeedback);
- $expout .= " \n";
- $expout .= " \n";
- $expout .= $name_text;
- $expout .= " \n";
- $expout .= " \n";
- $expout .= $this->writetext($question->questiontext, 3);
- $expout .= $this->writefiles($question->questiontextfiles);
- $expout .= " \n";
- $expout .= " \n";
- $expout .= $this->writetext($question->generalfeedback, 3);
- $expout .= $this->writefiles($question->generalfeedbackfiles);
- $expout .= " \n";
}
- // output depends on question type
+ // Now we know we are are handing a real question.
+ // Output the generic information.
+ $expout .= " \n";
+ $expout .= " \n";
+ $expout .= $this->writetext($question->name, 3);
+ $expout .= " \n";
+ $expout .= " format($question->questiontextformat)}>\n";
+ $expout .= $this->writetext($question->questiontext, 3);
+ $expout .= $this->writefiles($question->questiontextfiles);
+ $expout .= " \n";
+ $expout .= " format($question->generalfeedbackformat)}>\n";
+ $expout .= $this->writetext($question->generalfeedback, 3);
+ $expout .= $this->writefiles($question->generalfeedbackfiles);
+ $expout .= " \n";
+ if ($question->qtype != 'multianswer') {
+ $expout .= " {$question->defaultmark}\n";
+ }
+ $expout .= " {$question->penalty}\n";
+ $expout .= " {$question->hidden}\n";
+
+ // The rest of the output depends on question type.
switch($question->qtype) {
case 'category':
// not a qtype really - dummy used for category switching
@@ -1238,12 +1207,8 @@ class qformat_xml extends qformat_default {
break;
case 'multianswer':
- $acount = 1;
- foreach ($question->options->questions as $question) {
- $thispattern = "{#".$acount."}";
- $thisreplace = $question->questiontext;
- $expout = preg_replace("~$thispattern~", $thisreplace, $expout);
- $acount++;
+ foreach ($question->options->questions as $index => $subq) {
+ $expout = preg_replace('~{#' . $index . '}~', $subq->questiontext, $expout);
}
break;
diff --git a/question/format/xml/simpletest/testxmlformat.php b/question/format/xml/simpletest/testxmlformat.php
index c82027ba4ff..86a8862c638 100644
--- a/question/format/xml/simpletest/testxmlformat.php
+++ b/question/format/xml/simpletest/testxmlformat.php
@@ -28,6 +28,7 @@ defined('MOODLE_INTERNAL') || die();
require_once($CFG->libdir . '/questionlib.php');
require_once($CFG->dirroot . '/question/format/xml/format.php');
+require_once($CFG->dirroot . '/question/engine/simpletest/helpers.php');
/**
@@ -64,6 +65,52 @@ class qformat_xml_test extends UnitTestCase {
return $q;
}
+ /**
+ * The data the XML import format sends to save_question is not exactly
+ * the same as the data returned from the editing form, so this method
+ * makes necessary changes to the return value of
+ * test_question_maker::get_question_form_data so that the tests can work.
+ * @param object $expectedq as returned by get_question_form_data.
+ * @return object one more likely to match the return value of import_...().
+ */
+ public function remove_irrelevant_form_data_fields($expectedq) {
+ return $this->itemid_to_files($expectedq);
+ }
+
+ /**
+ * Becuase XML import uses a files array instead of an itemid integer to
+ * handle saving files with a question, we need to covert the output of
+ * test_question_maker::get_question_form_data to match. This method recursively
+ * replaces all array elements with key itemid with an array entry with
+ * key files and value an empty array.
+ *
+ * @param mixed $var any data structure.
+ * @return mixed an equivalent structure with the relacements made.
+ */
+ protected function itemid_to_files($var) {
+ if (is_object($var)) {
+ $newvar = new stdClass();
+ foreach(get_object_vars($var) as $field => $value) {
+ $newvar->$field = $this->itemid_to_files($value);
+ }
+
+ } else if (is_array($var)) {
+ $newvar = array();
+ foreach ($var as $index => $value) {
+ if ($index === 'itemid') {
+ $newvar['files'] = array();
+ } else {
+ $newvar[$index] = $this->itemid_to_files($value);
+ }
+ }
+
+ } else {
+ $newvar = $var;
+ }
+
+ return $newvar;
+ }
+
public function test_write_hint_basic() {
$q = $this->make_test_question();
$q->name = 'Short answer question';
@@ -468,7 +515,7 @@ END;
$xmldata = xmlize($xml);
$importer = new qformat_xml();
- $q = $importer->import_matching($xmldata['question']);
+ $q = $importer->import_match($xmldata['question']);
$expectedq = new stdClass();
$expectedq->qtype = 'match';
@@ -1216,4 +1263,136 @@ END;
$this->assert_same_xml($expectedxml, $xml);
}
+
+ public function test_import_multianswer() {
+ $xml = '
+
+ Simple multianswer
+
+
+
+
+
+
+
+ 0.5
+ 0
+
+ Hint 1
+
+
+ Hint 2
+
+
+';
+ $xmldata = xmlize($xml);
+
+ $importer = new qformat_xml();
+ $q = $importer->import_multianswer($xmldata['question']);
+
+ // Annoyingly, import works in a weird way (it duplicates code, rather
+ // than just calling save_question) so we cannot use
+ // test_question_maker::get_question_form_data('multianswer', 'twosubq').
+ $expectedqa = new stdClass();
+ $expectedqa->name = 'Simple multianswer';
+ $expectedqa->qtype = 'multianswer';
+ $expectedqa->questiontext = 'Complete this opening line of verse: "The {#1} and the {#2} went to sea".';
+ $expectedqa->generalfeedback = 'General feedback: It\'s from "The Owl and the Pussy-cat" by Lear: "The owl and the pussycat went to sea".';
+ $expectedqa->defaultmark = 2;
+ $expectedqa->penalty = 0.5;
+
+ $expectedqa->hint = array(
+ array('text' => 'Hint 1', 'format' => FORMAT_HTML, 'files' => array()),
+ array('text' => 'Hint 2', 'format' => FORMAT_HTML, 'files' => array()),
+ );
+
+ $sa = new stdClass();
+
+ $sa->questiontext = array('text' => '{1:SHORTANSWER:Dog#Wrong, silly!~=Owl#Well done!~*#Wrong answer}',
+ 'format' => FORMAT_HTML, 'itemid' => null);
+ $sa->generalfeedback = array('text' => '', 'format' => FORMAT_HTML, 'itemid' => null);
+ $sa->defaultmark = 1.0;
+ $sa->qtype = 'shortanswer';
+ $sa->usecase = 0;
+
+ $sa->answer = array('Dog', 'Owl', '*');
+ $sa->fraction = array(0, 1, 0);
+ $sa->feedback = array(
+ array('text' => 'Wrong, silly!', 'format' => FORMAT_HTML, 'itemid' => null),
+ array('text' => 'Well done!', 'format' => FORMAT_HTML, 'itemid' => null),
+ array('text' => 'Wrong answer', 'format' => FORMAT_HTML, 'itemid' => null),
+ );
+
+ $mc = new stdClass();
+
+ $mc->generalfeedback = '';
+ $mc->questiontext = array('text' => '{1:MULTICHOICE:Bow-wow#You seem to have a dog obsessions!~' .
+ 'Wiggly worm#Now you are just being ridiculous!~=Pussy-cat#Well done!}',
+ 'format' => FORMAT_HTML, 'itemid' => null);
+ $mc->generalfeedback = array('text' => '', 'format' => FORMAT_HTML, 'itemid' => null);
+ $mc->defaultmark = 1.0;
+ $mc->qtype = 'multichoice';
+
+ $mc->layout = 0;
+ $mc->single = 1;
+ $mc->shuffleanswers = 1;
+ $mc->correctfeedback = array('text' => '', 'format' => FORMAT_HTML, 'itemid' => null);
+ $mc->partiallycorrectfeedback = array('text' => '', 'format' => FORMAT_HTML, 'itemid' => null);
+ $mc->incorrectfeedback = array('text' => '', 'format' => FORMAT_HTML, 'itemid' => null);
+ $mc->answernumbering = 0;
+
+ $mc->answer = array(
+ array('text' => 'Bow-wow', 'format' => FORMAT_HTML, 'itemid' => null),
+ array('text' => 'Wiggly worm', 'format' => FORMAT_HTML, 'itemid' => null),
+ array('text' => 'Pussy-cat', 'format' => FORMAT_HTML, 'itemid' => null),
+ );
+ $mc->fraction = array(0, 0, 1);
+ $mc->feedback = array(
+ array('text' => 'You seem to have a dog obsessions!', 'format' => FORMAT_HTML, 'itemid' => null),
+ array('text' => 'Now you are just being ridiculous!', 'format' => FORMAT_HTML, 'itemid' => null),
+ array('text' => 'Well done!', 'format' => FORMAT_HTML, 'itemid' => null),
+ );
+
+ $expectedqa->options = new stdClass();
+ $expectedqa->options->questions = array(
+ 1 => $sa,
+ 2 => $mc,
+ );
+
+ $this->assertEqual($expectedqa->hint, $q->hint);
+ $this->assertEqual($expectedqa->options->questions[1], $q->options->questions[1]);
+ $this->assertEqual($expectedqa->options->questions[2], $q->options->questions[2]);
+ $this->assert(new CheckSpecifiedFieldsExpectation($expectedqa), $q);
+ }
+
+ public function test_export_multianswer() {
+ $qdata = test_question_maker::get_question_data('multianswer', 'twosubq');
+
+ $exporter = new qformat_xml();
+ $xml = $exporter->writequestion($qdata);
+
+ $expectedxml = '
+
+
+ Simple multianswer
+
+
+
+
+
+
+
+ 0.3333333
+ 0
+
+ Hint 1
+
+
+ Hint 2
+
+
+';
+
+ $this->assert_same_xml($expectedxml, $xml);
+ }
}
diff --git a/question/type/multianswer/simpletest/helper.php b/question/type/multianswer/simpletest/helper.php
index bd828749b59..9bbe04ee821 100644
--- a/question/type/multianswer/simpletest/helper.php
+++ b/question/type/multianswer/simpletest/helper.php
@@ -41,7 +41,7 @@ class qtype_multianswer_test_helper extends question_test_helper {
}
/**
- * Makes a multianswer question about summing two numbers.
+ * Makes a multianswer question about completing two blanks in some text.
* @return qtype_multianswer_question
*/
public function make_multianswer_question_twosubq() {
@@ -51,10 +51,8 @@ class qtype_multianswer_test_helper extends question_test_helper {
$q->name = 'Simple multianswer';
$q->questiontext =
'Complete this opening line of verse: "The {#1} and the {#2} went to sea".';
- $q->generalfeedback = 'Generalfeedback: It\'s from "The Owl and the Pussy-cat" by Lear: ' .
- '"The owl and the pussycat went to see';
- $q->questiontextformat = FORMAT_HTML;
- $q->generalfeedbackformat = FORMAT_HTML;
+ $q->generalfeedback = 'General feedback: It\'s from "The Owl and the Pussy-cat" by Lear: ' .
+ '"The owl and the pussycat went to sea';
// Shortanswer subquestion.
question_bank::load_question_definition_classes('shortanswer');
@@ -107,4 +105,112 @@ class qtype_multianswer_test_helper extends question_test_helper {
return $q;
}
+
+ /**
+ * Makes a multianswer question about completing two blanks in some text.
+ * @return object the question definition data, as it might be returned from
+ * get_question_options.
+ */
+ public function get_multianswer_question_data_twosubq() {
+ $qdata = new stdClass();
+ test_question_maker::initialise_question_data($qdata);
+
+ $qdata->name = 'Simple multianswer';
+ $qdata->questiontext =
+ 'Complete this opening line of verse: "The {#1} and the {#2} went to sea".';
+ $qdata->generalfeedback = 'General feedback: It\'s from "The Owl and the Pussy-cat" by Lear: ' .
+ '"The owl and the pussycat went to sea';
+
+ $qdata->defaultmark = 2.0;
+ $qdata->qtype = 'multianswer';
+
+ $sa = new stdClass();
+ test_question_maker::initialise_question_data($sa);
+
+ $sa->name = 'Simple multianswer';
+ $sa->questiontext = '{1:SHORTANSWER:Dog#Wrong, silly!~=Owl#Well done!~*#Wrong answer}';
+ $sa->generalfeedback = '';
+ $sa->penalty = 0.0;
+ $sa->qtype = 'shortanswer';
+
+ $sa->options = new stdClass();
+ $sa->options->usecase = 0;
+
+ $sa->options->answers = array(
+ 13 => new question_answer(13, 'Dog', 0, 'Wrong, silly!', FORMAT_HTML),
+ 14 => new question_answer(14, 'Owl', 1, 'Well done!', FORMAT_HTML),
+ 15 => new question_answer(15, '*', 0, 'Wrong answer', FORMAT_HTML),
+ );
+
+ $mc = new stdClass();
+ test_question_maker::initialise_question_data($mc);
+
+ $mc->name = 'Simple multianswer';
+ $mc->questiontext = '{1:MULTICHOICE:Bow-wow#You seem to have a dog obsessions!~' .
+ 'Wiggly worm#Now you are just being ridiculous!~=Pussy-cat#Well done!}';
+ $mc->generalfeedback = '';
+ $mc->penalty = 0.0;
+ $mc->qtype = 'multichoice';
+
+ $mc->options = new stdClass();
+ $mc->options->layout = 0;
+ $mc->options->single = 1;
+ $mc->options->shuffleanswers = 1;
+ $mc->options->correctfeedback = '';
+ $mc->options->correctfeedbackformat = 1;
+ $mc->options->partiallycorrectfeedback = '';
+ $mc->options->partiallycorrectfeedbackformat = 1;
+ $mc->options->incorrectfeedback = '';
+ $mc->options->incorrectfeedbackformat = 1;
+ $mc->options->answernumbering = '';
+ $mc->options->shownumcorrect = 0;
+
+ $mc->options->answers = array(
+ 23 => new question_answer(23, 'Bow-wow', 0,
+ 'You seem to have a dog obsessions!', FORMAT_HTML),
+ 24 => new question_answer(24, 'Wiggly worm', 0,
+ 'Now you are just being ridiculous!', FORMAT_HTML),
+ 25 => new question_answer(25, 'Pussy-cat', 1,
+ 'Well done!', FORMAT_HTML),
+ );
+
+ $qdata->options = new stdClass();
+ $qdata->options->questions = array(
+ 1 => $sa,
+ 2 => $mc,
+ );
+
+ $qdata->hints = array(
+ new question_hint(0, 'Hint 1', FORMAT_HTML),
+ new question_hint(0, 'Hint 2', FORMAT_HTML),
+ );
+
+ return $qdata;
+ }
+
+ /**
+ * Makes a multianswer question about completing two blanks in some text.
+ * @return object the question definition data, as it might be returned from
+ * the question editing form.
+ */
+ public function get_multianswer_question_form_data_twosubq() {
+ $formdata = new stdClass();
+ test_question_maker::initialise_question_form_data($formdata);
+
+ $formdata->name = 'Simple multianswer';
+ $formdata->questiontext = 'Complete this opening line of verse: "The ' .
+ '{1:SHORTANSWER:Dog#Wrong, silly!~=Owl#Well done!~*#Wrong answer} ' .
+ 'and the {1:MULTICHOICE:Bow-wow#You seem to have a dog obsessions!' .
+ '~Wiggly worm#Now you are just being ridiculous!~=Pussy-cat#Well done!}' .
+ ' went to sea".';
+ $formdata->generalfeedback = 'General feedback: It\'s from "The Owl and the Pussy-cat" ' .
+ 'by Lear: "The owl and the pussycat went to sea';
+
+ $formdata->hint = array(
+ 0 => array('text' => 'Hint 1', 'format' => FORMAT_HTML, 'itemid' => 0),
+ 1 => array('text' => 'Hint 2', 'format' => FORMAT_HTML, 'itemid' => 0),
+ );
+
+ return $formdata;
+ }
}
diff --git a/question/type/multianswer/simpletest/testquestiontype.php b/question/type/multianswer/simpletest/testquestiontype.php
index b8f85819772..fcd96f411f7 100644
--- a/question/type/multianswer/simpletest/testquestiontype.php
+++ b/question/type/multianswer/simpletest/testquestiontype.php
@@ -108,7 +108,7 @@ class qtype_multianswer_test extends UnitTestCase {
}
public function test_get_random_guess_score() {
- $q = $this->get_test_question_data();
+ $q = test_question_maker::get_question_data('multianswer', 'twosubq');
$this->assertWithinMargin(0.1666667, $this->qtype->get_random_guess_score($q), 0.0000001);
}
}