Permalink
Browse files

MDL-27414 Upgrade the randomsamatch qtype to the new question engine

Added XML import/export
Different randomsamatch qtypes in the same quiz can now pick the same
shortanswer question.
Images are not preserved if shortanswer question is deleted after being
used in a randomsamatch attempt.
  • Loading branch information...
Jean-Michel Vedrine
Jean-Michel Vedrine committed May 10, 2013
1 parent c8d383f commit ee34440ae493ceceb8199b4ee577cc3a9d8c9b58
@@ -58,9 +58,7 @@ public function formulation_and_controls(question_attempt $qa,
$result .= html_writer::start_tag('tr', array('class' => 'r' . $parity));
$fieldname = 'sub' . $key;
$result .= html_writer::tag('td', $question->format_text(
$question->stems[$stemid], $question->stemformat[$stemid],
$qa, 'qtype_match', 'subquestion', $stemid),
$result .= html_writer::tag('td', $this->format_stem_text($qa, $stemid),
array('class' => 'text'));
$classes = 'control';
@@ -109,6 +107,20 @@ public function specific_feedback(question_attempt $qa) {
return $this->combined_feedback($qa);
}
/**
* Format each question stem. Overwritten by randomsamatch renderer.
*
* @param question_attempt $qa
* @param integer $stemid stem index
* @return string
*/
public function format_stem_text($qa, $stemid) {
$question = $qa->get_question();
return $question->format_text(
$question->stems[$stemid], $question->stemformat[$stemid],
$qa, 'qtype_match', 'subquestion', $stemid);
}
protected function format_choices($question) {
$choices = array();
foreach ($question->get_choice_order() as $key => $choiceid) {
@@ -125,9 +137,7 @@ public function correct_response(question_attempt $qa) {
$choices = $this->format_choices($question);
$right = array();
foreach ($stemorder as $key => $stemid) {
$right[] = $question->format_text($question->stems[$stemid],
$question->stemformat[$stemid], $qa,
'qtype_match', 'subquestion', $stemid) . '' .
$right[] = $this->format_stem_text($qa, $stemid) . '' .
$choices[$question->get_right_choice_for($stemid)];
}
@@ -0,0 +1,71 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Serve question type files
*
* @package qtype_randomsamatch
* @copyright 2013 Jean-Michel Vedrine
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
/**
* Random shortanswer matching question type conversion handler.
*
* @copyright 2013 Jean-Michel Vedrine
* @license http://www.gnu.org/copyleft/gpl.html GNU Public License
*/
class moodle1_qtype_randomsamatch_handler extends moodle1_qtype_handler {
/**
* Returns the list of paths within one <QUESTION> that this qtype needs to have included
* in the grouped question structure
*
* @return array of strings
*/
public function get_question_subpaths() {
return array(
'RANDOMSAMATCH',
);
}
/**
* Appends the randomsamatch specific information to the question.
*
* @param array $data grouped question data
* @param array $raw grouped raw QUESTION data
*/
public function process_question(array $data, array $raw) {
// Convert match options.
if (isset($data['randomsamatch'])) {
$randomsamatch = $data['randomsamatch'][0];
} else {
$randomsamatch = array('choose' => 4);
}
$randomsamatch['id'] = $this->converter->get_nextid();
$randomsamatch['subcats'] = 1;
$randomsamatch['correctfeedback'] = '';
$randomsamatch['correctfeedbackformat'] = FORMAT_HTML;
$randomsamatch['partiallycorrectfeedback'] = '';
$randomsamatch['partiallycorrectfeedbackformat'] = FORMAT_HTML;
$randomsamatch['incorrectfeedback'] = '';
$randomsamatch['incorrectfeedbackformat'] = FORMAT_HTML;
$this->write_xml('randomsamatch', $randomsamatch, array('/randomsamatch/id'));
}
}
@@ -49,14 +49,16 @@ protected function define_question_plugin_structure() {
// Now create the qtype own structures.
$randomsamatch = new backup_nested_element('randomsamatch', array('id'), array(
'choose'));
'choose', 'subcats', 'correctfeedback', 'correctfeedbackformat',
'partiallycorrectfeedback', 'partiallycorrectfeedbackformat',
'incorrectfeedback', 'incorrectfeedbackformat', 'shownumcorrect'));
// Now the own qtype tree.
$pluginwrapper->add_child($randomsamatch);
// Set source to populate the data.
$randomsamatch->set_source_table('question_randomsamatch',
array('question' => backup::VAR_PARENTID));
$randomsamatch->set_source_table('qtype_randomsamatch_options',
array('questionid' => backup::VAR_PARENTID));
return $plugin;
}
@@ -41,7 +41,7 @@ protected function define_question_plugin_structure() {
$paths = array();
// Add own qtype stuff
// Add own qtype stuff.
$elename = 'randomsamatch';
$elepath = $this->get_pathfor('/randomsamatch');
$paths[] = new restore_path_element($elename, $elepath);
@@ -64,14 +64,34 @@ public function process_randomsamatch($data) {
$questioncreated = $this->get_mappingid('question_created', $oldquestionid) ? true : false;
// If the question has been created by restore, we need to create its
// question_randomsamatch too.
// qtype_randomsamatch_options too.
if ($questioncreated) {
// Fill in some field that were added in 2.1, and so which may be missing
// from backups made in older versions of Moodle.
if (!isset($data->subcats)) {
$data->subcats = 1;
}
if (!isset($data->correctfeedback)) {
$data->correctfeedback = '';
$data->correctfeedbackformat = FORMAT_HTML;
}
if (!isset($data->partiallycorrectfeedback)) {
$data->partiallycorrectfeedback = '';
$data->partiallycorrectfeedbackformat = FORMAT_HTML;
}
if (!isset($data->incorrectfeedback)) {
$data->incorrectfeedback = '';
$data->incorrectfeedbackformat = FORMAT_HTML;
}
if (!isset($data->shownumcorrect)) {
$data->shownumcorrect = 0;
}
// Adjust some columns.
$data->question = $newquestionid;
$data->questionid = $newquestionid;
// Insert record.
$newitemid = $DB->insert_record('question_randomsamatch', $data);
$newitemid = $DB->insert_record('qtype_randomsamatch_options', $data);
// Create mapping.
$this->set_mapping('question_randomsamatch', $oldid, $newitemid);
$this->set_mapping('qtype_randomsamatch_options', $oldid, $newitemid);
}
}
@@ -82,7 +102,7 @@ public function process_randomsamatch($data) {
* answer is one comma separated list of hypen separated pairs
* containing question->id and question_answers->id
*/
public function recode_state_answer($state) {
public function recode_legacy_state_answer($state) {
$answer = $state->answer;
$resultarr = array();
foreach (explode(',', $answer) as $pair) {
@@ -95,4 +115,17 @@ public function recode_state_answer($state) {
}
return implode(',', $resultarr);
}
/**
* Return the contents of this qtype to be processed by the links decoder.
*/
public static function define_decode_contents() {
$contents = array();
$fields = array('correctfeedback', 'partiallycorrectfeedback', 'incorrectfeedback');
$contents[] = new restore_decode_content('qtype_randomsamatch_options', $fields, 'qtype_randomsamatch_options');
return $contents;
}
}
@@ -4,15 +4,23 @@
xsi:noNamespaceSchemaLocation="../../../../lib/xmldb/xmldb.xsd"
>
<TABLES>
<TABLE NAME="question_randomsamatch" COMMENT="Info about a random short-answer matching question">
<TABLE NAME="qtype_randomsamatch_options" COMMENT="Info about a random short-answer matching question">
<FIELDS>
<FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="true"/>
<FIELD NAME="question" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="Foreign key references question.id."/>
<FIELD NAME="questionid" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="Foreign key references question.id."/>
<FIELD NAME="choose" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="4" SEQUENCE="false" COMMENT="Number of subquestions to randomly generate."/>
<FIELD NAME="subcats" TYPE="int" LENGTH="2" NOTNULL="true" DEFAULT="1" SEQUENCE="false" COMMENT="Whether to include or not the subcategories."/>
<FIELD NAME="correctfeedback" TYPE="text" NOTNULL="true" SEQUENCE="false" COMMENT="Feedback shown for any correct response."/>
<FIELD NAME="correctfeedbackformat" TYPE="int" LENGTH="2" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
<FIELD NAME="partiallycorrectfeedback" TYPE="text" NOTNULL="true" SEQUENCE="false" COMMENT="Feedback shown for any partially correct response."/>
<FIELD NAME="partiallycorrectfeedbackformat" TYPE="int" LENGTH="2" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
<FIELD NAME="incorrectfeedback" TYPE="text" NOTNULL="true" SEQUENCE="false" COMMENT="Feedback shown for any incorrect response."/>
<FIELD NAME="incorrectfeedbackformat" TYPE="int" LENGTH="2" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
<FIELD NAME="shownumcorrect" TYPE="int" LENGTH="2" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="If true, then when the user gets the question partially correct, tell them how many choices they got correct alongside the feedback."/>
</FIELDS>
<KEYS>
<KEY NAME="primary" TYPE="primary" FIELDS="id"/>
<KEY NAME="question" TYPE="foreign" FIELDS="question" REFTABLE="question" REFFIELDS="id"/>
<KEY NAME="questionid" TYPE="foreign-unique" FIELDS="questionid" REFTABLE="question" REFFIELDS="id"/>
</KEYS>
</TABLE>
</TABLES>
Oops, something went wrong.

0 comments on commit ee34440

Please sign in to comment.