mirror of
https://github.com/moodle/moodle.git
synced 2025-01-18 05:58:34 +01:00
MDL-5969 Let multiple choice questions have feedback that does not depend on the chosen answer
In passing, I fixed MDL-6297 Export of multichoice questions in Moodle XML format doesn't save shuffle option too.
This commit is contained in:
parent
6e557c0806
commit
307f045f07
25
lang/en_utf8/qtype_multichoice.php
Normal file
25
lang/en_utf8/qtype_multichoice.php
Normal file
@ -0,0 +1,25 @@
|
||||
<?php
|
||||
/*
|
||||
* Created on Aug 20, 2006
|
||||
*
|
||||
* To change the template for this generated file go to
|
||||
* Window - Preferences - PHPeclipse - PHP - Code Templates
|
||||
*/
|
||||
|
||||
$string['answersingleno'] = 'Multiple answers allowed';
|
||||
$string['answersingleyes'] = 'One answer only';
|
||||
$string['choiceno'] = 'Choice $a';
|
||||
$string['choices'] = 'Available choices';
|
||||
$string['editingmultichoice'] = 'Editing a Multiple Choice question';
|
||||
$string['fillouttwochoices'] = 'You must fill out at least two choices. Choices left blank will not be used.';
|
||||
$string['fractionsaddwrong'] = 'The positive grades you have chosen do not add up to 100%%<br />Instead, they add up to $a%%<br />Do you want to go back and fix this question?';
|
||||
$string['fractionsnomax'] = 'One of the answers should be 100%%, so that it is<br />possible to get a full grade for this question.<br />Do you want to go back and fix this question?';
|
||||
$string['feedback'] = 'Feedback';
|
||||
$string['notenoughanswers'] = 'This type of question requires at least $a answers';
|
||||
$string['overallcorrectfeedback'] = 'Feedback for any correct answer';
|
||||
$string['overallpartiallycorrectfeedback'] = 'Feedback for any partially correct answer';
|
||||
$string['overallincorrectfeedback'] = 'Feedback for any incorrect answer';
|
||||
$string['shuffleanswers'] = 'Shuffle answers';
|
||||
$string['singleanswer'] = 'Choose one answer.';
|
||||
|
||||
?>
|
@ -82,6 +82,21 @@ class qformat_xml extends qformat_default {
|
||||
return addslashes(trim( $data ));
|
||||
}
|
||||
|
||||
/**
|
||||
* Process text from an element in the XML that may or not be there.
|
||||
* @param string $subelement the name of the element which is either present or missing.
|
||||
* @param array $question a bit of xml tree, this method looks for $question['#'][$subelement][0]['#']['text'].
|
||||
* @return string If $subelement is present, return the content of the text tag inside it.
|
||||
* Otherwise returns an empty string.
|
||||
*/
|
||||
function import_optional_text($subelement, $question) {
|
||||
if (array_key_exists($subelement, $question['#'])) {
|
||||
return $this->import_text($question['#'][$subelement][0]['#']['text']);
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* import parts of question common to all types
|
||||
* @param array question question array from xml tree
|
||||
@ -149,7 +164,16 @@ class qformat_xml extends qformat_default {
|
||||
$qo->qtype = MULTICHOICE;
|
||||
$single = $question['#']['single'][0]['#'];
|
||||
$qo->single = $this->trans_single( $single );
|
||||
|
||||
if (array_key_exists('shuffleanswers', $question['#'])) {
|
||||
$shuffleanswers = $question['#']['shuffleanswers'][0]['#'];
|
||||
} else {
|
||||
$shuffleanswers = 'false';
|
||||
}
|
||||
$qo->$shuffleanswers = $this->trans_single($shuffleanswers);
|
||||
$qo->correctfeedback = $this->import_optional_text('correctfeedback', $question);
|
||||
$qo->partiallycorrectfeedback = $this->import_optional_text('partiallycorrectfeedback', $question);
|
||||
$qo->incorrectfeedback = $this->import_optional_text('incorrectfeedback', $question);
|
||||
|
||||
// run through the answers
|
||||
$answers = $question['#']['answer'];
|
||||
$a_count = 0;
|
||||
@ -671,6 +695,10 @@ class qformat_xml extends qformat_default {
|
||||
break;
|
||||
case MULTICHOICE:
|
||||
$expout .= " <single>".$this->get_single($question->options->single)."</single>\n";
|
||||
$expout .= " <shuffleanswers>".$this->get_single($question->options->shuffleanswers)."</shuffleanswers>\n";
|
||||
$expout .= " <correctfeedback>".$this->writetext($question->options->correctfeedback, 3)."</correctfeedback>\n";
|
||||
$expout .= " <partiallycorrectfeedback>".$this->writetext($question->options->partiallycorrectfeedback, 3)."</partiallycorrectfeedback>\n";
|
||||
$expout .= " <incorrectfeedback>".$this->writetext($question->options->incorrectfeedback, 3)."</incorrectfeedback>\n";
|
||||
foreach($question->options->answers as $answer) {
|
||||
$percent = $answer->fraction * 100;
|
||||
$expout .= " <answer fraction=\"$percent\">\n";
|
||||
|
@ -614,6 +614,7 @@
|
||||
$state->grade = backup_todb($res_info['#']['GRADE']['0']['#']);
|
||||
$state->raw_grade = backup_todb($res_info['#']['RAW_GRADE']['0']['#']);
|
||||
$state->penalty = backup_todb($res_info['#']['PENALTY']['0']['#']);
|
||||
$state->oldid = $oldid; // So it is available to restore_recode_answer.
|
||||
|
||||
//We have to recode the question field
|
||||
$question = backup_getid($restore->backup_unique_code,"question",$state->question);
|
||||
|
@ -4,8 +4,15 @@
|
||||
|
||||
function qtype_multichoice_upgrade($oldversion=0) {
|
||||
global $CFG;
|
||||
|
||||
return true;
|
||||
$success = true;
|
||||
|
||||
if ($success && $oldversion < 2006081900) {
|
||||
$success = $success && table_column('question_multichoice', '', 'correctfeedback', 'text', '', '', '');
|
||||
$success = $success && table_column('question_multichoice', '', 'partiallycorrectfeedback', 'text', '', '', '');
|
||||
$success = $success && table_column('question_multichoice', '', 'incorrectfeedback', 'text', '', '', '');
|
||||
}
|
||||
|
||||
return $success;
|
||||
}
|
||||
|
||||
?>
|
||||
|
@ -11,6 +11,9 @@ CREATE TABLE prefix_question_multichoice (
|
||||
answers varchar(255) NOT NULL default '',
|
||||
single tinyint(4) NOT NULL default '0',
|
||||
shuffleanswers tinyint(4) NOT NULL default '1',
|
||||
correctfeedback text NOT NULL default '',
|
||||
partiallycorrectfeedback text NOT NULL default '',
|
||||
incorrectfeedback text NOT NULL default '',
|
||||
PRIMARY KEY (id),
|
||||
KEY question (question)
|
||||
) TYPE=MyISAM COMMENT='Options for multiple choice questions';
|
||||
|
@ -4,8 +4,15 @@
|
||||
|
||||
function qtype_multichoice_upgrade($oldversion=0) {
|
||||
global $CFG;
|
||||
|
||||
return true;
|
||||
$success = true;
|
||||
|
||||
if ($success && $oldversion < 2006081900) {
|
||||
$success = $success && table_column('question_multichoice', '', 'correctfeedback', 'text', '', '', '');
|
||||
$success = $success && table_column('question_multichoice', '', 'partiallycorrectfeedback', 'text', '', '', '');
|
||||
$success = $success && table_column('question_multichoice', '', 'incorrectfeedback', 'text', '', '', '');
|
||||
}
|
||||
|
||||
return $success;
|
||||
}
|
||||
|
||||
?>
|
||||
|
@ -11,7 +11,10 @@ CREATE TABLE prefix_question_multichoice (
|
||||
layout integer NOT NULL default '0',
|
||||
answers varchar(255) NOT NULL default '',
|
||||
single integer NOT NULL default '0',
|
||||
shuffleanswers integer NOT NULL default '1'
|
||||
shuffleanswers integer NOT NULL default '1',
|
||||
correctfeedback text NOT NULL default '',
|
||||
partiallycorrectfeedback text NOT NULL default '',
|
||||
incorrectfeedback text NOT NULL default ''
|
||||
);
|
||||
|
||||
CREATE INDEX prefix_question_multichoice_question_idx ON prefix_question_multichoice (question);
|
||||
|
@ -28,5 +28,10 @@
|
||||
</tr>
|
||||
<?php } ?>
|
||||
</table>
|
||||
<?php if ($feedback) { ?>
|
||||
<div class="feedback">
|
||||
<?php echo $feedback ?>
|
||||
</div>
|
||||
<?php } ?>
|
||||
<?php $this->print_question_submit_buttons($question, $state, $cmoptions, $options); ?>
|
||||
</div>
|
||||
|
@ -2,28 +2,28 @@
|
||||
$QTYPES[$question->qtype]->print_question_form_start($question, array(), $course, $usehtmleditor);
|
||||
?>
|
||||
<tr valign="top">
|
||||
<td align="right"><b><?php print_string("answerhowmany", "quiz") ?>:</b></td>
|
||||
<td align="right"><b><?php print_string("answerhowmany", "qtype_multichoice") ?>:</b></td>
|
||||
<td align="left">
|
||||
<?php
|
||||
$menu[0] = get_string("answersingleno", "quiz");
|
||||
$menu[1] = get_string("answersingleyes", "quiz");
|
||||
$menu[0] = get_string("answersingleno", "qtype_multichoice");
|
||||
$menu[1] = get_string("answersingleyes", "qtype_multichoice");
|
||||
choose_from_menu($menu, "single", "$options->single", "");
|
||||
unset($menu);
|
||||
?>
|
||||
</td>
|
||||
</tr>
|
||||
<tr valign="top">
|
||||
<td align="right"><b><?php print_string("shuffleanswers", "quiz") ?>:</b></td>
|
||||
<td align="right"><b><?php print_string("shuffleanswers", "qtype_multichoice") ?>:</b></td>
|
||||
<td align="left">
|
||||
<?php
|
||||
choose_from_menu($yesnooptions, "shuffleanswers", "$options->shuffleanswers", "");
|
||||
helpbutton("multichoiceshuffle", get_string("shuffleanswers","quiz"), "quiz");
|
||||
helpbutton("multichoiceshuffle", get_string("shuffleanswers","qtype_multichoice"), "quiz");
|
||||
?>
|
||||
</td>
|
||||
</tr>
|
||||
<tr valign="top">
|
||||
<td align="right"><b><?php print_string("choices", "quiz") ?></b>:</td>
|
||||
<td align="left"><?php print_string("fillouttwochoices", "quiz") ?></td>
|
||||
<td align="right"><b><?php print_string("choices", "qtype_multichoice") ?></b>:</td>
|
||||
<td align="left"><?php print_string("fillouttwochoices", "qtype_multichoice") ?></td>
|
||||
</tr>
|
||||
|
||||
<?php
|
||||
@ -36,9 +36,9 @@ for ($i=1; $i<=count($answers); $i++) {
|
||||
?>
|
||||
|
||||
<tr valign="top">
|
||||
<td align="right"><b><?php echo get_string("choice", "quiz")." $i"; ?>:</b></td>
|
||||
<td align="right"><b><?php print_string("choiceno", "qtype_multichoice", $i); ?>:</b></td>
|
||||
<td align="left">
|
||||
<input type="text" name="answer[]" size="50" value="<?php p($answers[$i-1]->answer) ?>" alt="<?php echo get_string("choice", "quiz")." $i"; ?>"/>
|
||||
<input type="text" name="answer[]" size="50" value="<?php p($answers[$i-1]->answer) ?>" />
|
||||
<?php
|
||||
print_string("grade");
|
||||
echo ": ";
|
||||
@ -49,7 +49,7 @@ for ($i=1; $i<=count($answers); $i++) {
|
||||
</tr>
|
||||
|
||||
<tr valign="top">
|
||||
<td align="right"><b><?php print_string("feedback", "quiz") ?>:</b></td>
|
||||
<td align="right"><b><?php print_string("feedback", "qtype_multichoice") ?>:</b></td>
|
||||
<td align="left">
|
||||
<textarea name="feedback[]" rows="2" cols="50"><?php p($answers[$i-1]->feedback) ?></textarea>
|
||||
</td>
|
||||
@ -61,7 +61,33 @@ for ($i=1; $i<=count($answers); $i++) {
|
||||
|
||||
<?php
|
||||
} /// End of loop, printing answers
|
||||
?>
|
||||
<tr valign="top">
|
||||
<td align="right"><b><?php print_string("overallcorrectfeedback", "qtype_multichoice") ?>:</b></td>
|
||||
<td align="left">
|
||||
<textarea name="correctfeedback" rows="4" cols="50"><?php p($options->correctfeedback) ?></textarea>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr valign="top">
|
||||
<td align="right"><b><?php print_string("overallpartiallycorrectfeedback", "qtype_multichoice") ?>:</b></td>
|
||||
<td align="left">
|
||||
<textarea name="partiallycorrectfeedback" rows="4" cols="50"><?php p($options->partiallycorrectfeedback) ?></textarea>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr valign="top">
|
||||
<td align="right"><b><?php print_string("overallincorrectfeedback", "qtype_multichoice") ?>:</b></td>
|
||||
<td align="left">
|
||||
<textarea name="incorrectfeedback" rows="4" cols="50"><?php p($options->incorrectfeedback) ?></textarea>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr valign="top">
|
||||
<td colspan="2"> </td>
|
||||
</tr>
|
||||
|
||||
<?php
|
||||
$QTYPES[$question->qtype]->print_replacement_options($question, $course, $contextquiz);
|
||||
$QTYPES[$question->qtype]->print_question_form_end($question);
|
||||
?>
|
||||
|
@ -5,6 +5,9 @@
|
||||
} else {
|
||||
$options->single = 1;
|
||||
$options->shuffleanswers = 1;
|
||||
$options->correctfeedback = '';
|
||||
$options->partiallycorrectfeedback = '';
|
||||
$options->incorrectfeedback = '';
|
||||
}
|
||||
if (!empty($options->answers)) {
|
||||
$answersraw = get_records_list("question_answers", "id", $options->answers);
|
||||
@ -29,7 +32,7 @@
|
||||
$yesnooptions[0] = get_string("no");
|
||||
$yesnooptions[1] = get_string("yes");
|
||||
|
||||
print_heading_with_help(get_string("editingmultichoice", "quiz"), "multichoice", "quiz");
|
||||
print_heading_with_help(get_string("editingmultichoice", "qtype_multichoice"), "multichoice", "quiz");
|
||||
require("$CFG->dirroot/question/type/multichoice/editquestion.html");
|
||||
|
||||
?>
|
||||
|
@ -35,7 +35,7 @@ class question_multichoice_qtype extends default_questiontype {
|
||||
}
|
||||
|
||||
function save_question_options($question) {
|
||||
|
||||
$result = new stdClass;
|
||||
if (!$oldanswers = get_records("question_answers", "question",
|
||||
$question->id, "id ASC")) {
|
||||
$oldanswers = array();
|
||||
@ -50,7 +50,7 @@ class question_multichoice_qtype extends default_questiontype {
|
||||
}
|
||||
$answercount += count($oldanswers);
|
||||
if ($answercount < 2) { // check there are at lest 2 answers for multiple choice
|
||||
$result->notice = get_string("notenoughanswers", "quiz", "2");
|
||||
$result->notice = get_string("notenoughanswers", "qtype_multichoice", "2");
|
||||
return $result;
|
||||
}
|
||||
|
||||
@ -93,20 +93,26 @@ class question_multichoice_qtype extends default_questiontype {
|
||||
}
|
||||
}
|
||||
|
||||
if ($options = get_record("question_multichoice", "question", $question->id)) {
|
||||
$options->answers = implode(",",$answers);
|
||||
$options->single = $question->single;
|
||||
$options->shuffleanswers = $question->shuffleanswers;
|
||||
$update = true;
|
||||
$options = get_record("question_multichoice", "question", $question->id);
|
||||
if (!$options) {
|
||||
$update = false;
|
||||
$options = new stdClass;
|
||||
$options->question = $question->id;
|
||||
|
||||
}
|
||||
$options->answers = implode(",",$answers);
|
||||
$options->single = $question->single;
|
||||
$options->shuffleanswers = $question->shuffleanswers;
|
||||
$options->correctfeedback = trim($question->correctfeedback);
|
||||
$options->partiallycorrectfeedback = trim($question->partiallycorrectfeedback);
|
||||
$options->incorrectfeedback = trim($question->incorrectfeedback);
|
||||
if ($update) {
|
||||
if (!update_record("question_multichoice", $options)) {
|
||||
$result->error = "Could not update quiz multichoice options! (id=$options->id)";
|
||||
return $result;
|
||||
}
|
||||
} else {
|
||||
unset($options);
|
||||
$options->question = $question->id;
|
||||
$options->answers = implode(",",$answers);
|
||||
$options->single = $question->single;
|
||||
$options->shuffleanswers = $question->shuffleanswers;
|
||||
if (!insert_record("question_multichoice", $options)) {
|
||||
$result->error = "Could not insert quiz multichoice options!";
|
||||
return $result;
|
||||
@ -124,14 +130,14 @@ class question_multichoice_qtype extends default_questiontype {
|
||||
if ($options->single) {
|
||||
if ($maxfraction != 1) {
|
||||
$maxfraction = $maxfraction * 100;
|
||||
$result->noticeyesno = get_string("fractionsnomax", "quiz", $maxfraction);
|
||||
$result->noticeyesno = get_string("fractionsnomax", "qtype_multichoice", $maxfraction);
|
||||
return $result;
|
||||
}
|
||||
} else {
|
||||
$totalfraction = round($totalfraction,2);
|
||||
if ($totalfraction != 1) {
|
||||
$totalfraction = $totalfraction * 100;
|
||||
$result->noticeyesno = get_string("fractionsaddwrong", "quiz", $totalfraction);
|
||||
$result->noticeyesno = get_string("fractionsaddwrong", "qtype_multichoice", $totalfraction);
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
@ -291,6 +297,7 @@ class question_multichoice_qtype extends default_questiontype {
|
||||
? 'checked="checked"' : '';
|
||||
}
|
||||
|
||||
$a = new stdClass;
|
||||
$a->id = $question->name_prefix . $aid;
|
||||
|
||||
// Print the control
|
||||
@ -314,6 +321,21 @@ class question_multichoice_qtype extends default_questiontype {
|
||||
|
||||
$anss[] = clone($a);
|
||||
}
|
||||
|
||||
$feedback = '';
|
||||
if ($options->feedback) {
|
||||
if ($state->raw_grade >= $question->maxgrade/1.01) {
|
||||
$feedback = $question->options->correctfeedback;
|
||||
} else if ($state->raw_grade > 0) {
|
||||
$feedback = $question->options->partiallycorrectfeedback;
|
||||
} else {
|
||||
$feedback = $question->options->incorrectfeedback;
|
||||
}
|
||||
$feedback = format_text($feedback,
|
||||
$question->questiontextformat,
|
||||
$formatoptions, $cmoptions->course);
|
||||
}
|
||||
|
||||
include("$CFG->dirroot/question/type/multichoice/display.html");
|
||||
}
|
||||
|
||||
@ -392,6 +414,9 @@ class question_multichoice_qtype extends default_questiontype {
|
||||
fwrite ($bf,full_tag("ANSWERS",$level+1,false,$multichoice->answers));
|
||||
fwrite ($bf,full_tag("SINGLE",$level+1,false,$multichoice->single));
|
||||
fwrite ($bf,full_tag("SHUFFLEANSWERS",$level+1,false,$multichoice->shuffleanswers));
|
||||
fwrite ($bf,full_tag("CORRECTFEEDBACK",$level+1,false,$multichoice->correctfeedback));
|
||||
fwrite ($bf,full_tag("PARTIALLYCORRECTFEEDBACK",$level+1,false,$multichoice->partiallycorrectfeedback));
|
||||
fwrite ($bf,full_tag("INCORRECTFEEDBACK",$level+1,false,$multichoice->incorrectfeedback));
|
||||
$status = fwrite ($bf,end_tag("MULTICHOICE",$level,true));
|
||||
}
|
||||
|
||||
@ -420,11 +445,27 @@ class question_multichoice_qtype extends default_questiontype {
|
||||
$mul_info = $multichoices[$i];
|
||||
|
||||
//Now, build the question_multichoice record structure
|
||||
$multichoice = new stdClass;
|
||||
$multichoice->question = $new_question_id;
|
||||
$multichoice->layout = backup_todb($mul_info['#']['LAYOUT']['0']['#']);
|
||||
$multichoice->answers = backup_todb($mul_info['#']['ANSWERS']['0']['#']);
|
||||
$multichoice->single = backup_todb($mul_info['#']['SINGLE']['0']['#']);
|
||||
$multichoice->shuffleanswers = backup_todb($mul_info['#']['SHUFFLEANSWERS']['0']['#']);
|
||||
if (array_key_exists("CORRECTFEEDBACK", $mul_info['#'])) {
|
||||
$multichoice->correctfeedback = backup_todb($mul_info['#']['CORRECTFEEDBACK']['0']['#']);
|
||||
} else {
|
||||
$multichoice->correctfeedback = '';
|
||||
}
|
||||
if (array_key_exists("PARTIALLYCORRECTFEEDBACK", $mul_info['#'])) {
|
||||
$multichoice->partiallycorrectfeedback = backup_todb($mul_info['#']['PARTIALLYCORRECTFEEDBACK']['0']['#']);
|
||||
} else {
|
||||
$multichoice->partiallycorrectfeedback = '';
|
||||
}
|
||||
if (array_key_exists("INCORRECTFEEDBACK", $mul_info['#'])) {
|
||||
$multichoice->incorrectfeedback = backup_todb($mul_info['#']['INCORRECTFEEDBACK']['0']['#']);
|
||||
} else {
|
||||
$multichoice->incorrectfeedback = '';
|
||||
}
|
||||
|
||||
//We have to recode the answers field (a list of answers id)
|
||||
//Extracts answer id from sequence
|
||||
@ -490,7 +531,7 @@ class question_multichoice_qtype extends default_questiontype {
|
||||
if ($answer) {
|
||||
$order[$key] = $answer->new_id;
|
||||
} else {
|
||||
echo 'Could not recode multichoice answer id '.$oldansid.' for state '.$oldid.'<br />';
|
||||
echo 'Could not recode multichoice answer id '.$oldansid.' for state '.$state->oldid.'<br />';
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -500,7 +541,7 @@ class question_multichoice_qtype extends default_questiontype {
|
||||
if ($answer) {
|
||||
$responses[$key] = $answer->new_id;
|
||||
} else {
|
||||
echo 'Could not recode multichoice response answer id '.$oldansid.' for state '.$oldid.'<br />';
|
||||
echo 'Could not recode multichoice response answer id '.$oldansid.' for state '.$state->oldid.'<br />';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
<?PHP // $Id$
|
||||
|
||||
$plugin->version = 2006032200;
|
||||
$plugin->version = 2006081900;
|
||||
$plugin->requires = 2006032200;
|
||||
|
||||
?>
|
||||
|
@ -615,10 +615,7 @@ table.message_search_results td {
|
||||
.truefalse .answer {
|
||||
background-color: #EEE;
|
||||
}
|
||||
.calculated .feedback,
|
||||
.numerical .feedback,
|
||||
.shortanswer .feedback,
|
||||
.truefalse .feedback {
|
||||
.que .feedback {
|
||||
border-color: #DDD;
|
||||
}
|
||||
.que.multianswer .incorrect {
|
||||
|
@ -1208,7 +1208,7 @@ body#message-messages {
|
||||
padding: 0 0 0.3em 0.3em;
|
||||
border: 1px solid;
|
||||
}
|
||||
.multichoice .feedback {
|
||||
.multichoice td.feedback {
|
||||
width: auto;
|
||||
vertical-align: top;
|
||||
padding-top: 0.3em;
|
||||
|
Loading…
x
Reference in New Issue
Block a user