MDL-34306 gift question format: allow import of general feedback

This change introduces #### as a separator for general feedback. You need
to add ####General feedback goes here as the last thing inside the {...}.
For example

// question: 123  name: Shortanswer
::Shortanswer::Which is the best animal?{
    =Frog#Good!
    =%50%Cat#What is it with Moodlers and cats?
    =%0%*#Completely wrong
    ####Here is some general feedback!
}

Note that this change is not entirely backwards compatible. It will break
any existing GIFT file where the character sequence #### us used between the
{} as part of the question. This seems highly unlikely.
This commit is contained in:
Tim Hunt 2012-07-12 19:11:06 +01:00
parent d71c486507
commit 19de315e83
3 changed files with 175 additions and 15 deletions

View File

@ -213,42 +213,56 @@ class qformat_gift extends qformat_default {
$question->name = false;
}
// FIND ANSWER section
// no answer means its a description
// Find the answer section.
$answerstart = strpos($text, '{');
$answerfinish = strpos($text, '}');
$description = false;
if (($answerstart === false) and ($answerfinish === false)) {
if ($answerstart === false && $answerfinish === false) {
// No answer means it's a description.
$description = true;
$answertext = '';
$answerlength = 0;
} else if (!(($answerstart !== false) and ($answerfinish !== false))) {
} else if ($answerstart === false || $answerfinish === false) {
$this->error(get_string('braceerror', 'qformat_gift'), $text);
return false;
} else {
$answerlength = $answerfinish - $answerstart;
$answertext = trim(substr($text, $answerstart + 1, $answerlength - 1));
}
// Format QUESTION TEXT without answer, inserting "_____" as necessary
// Format the question text, without answer, inserting "_____" as necessary.
if ($description) {
$questiontext = $text;
} else if (substr($text, -1) == "}") {
// no blank line if answers follow question, outside of closing punctuation
$questiontext = substr_replace($text, "", $answerstart, $answerlength+1);
// No blank line if answers follow question, outside of closing punctuation.
$questiontext = substr_replace($text, "", $answerstart, $answerlength + 1);
} else {
// inserts blank line for missing word format
$questiontext = substr_replace($text, "_____", $answerstart, $answerlength+1);
// Inserts blank line for missing word format.
$questiontext = substr_replace($text, "_____", $answerstart, $answerlength + 1);
}
// Get questiontext format from questiontext
// Look to see if there is any general feedback.
$gfseparator = strrpos($answertext, '####');
if ($gfseparator === false) {
$generalfeedback = '';
} else {
$generalfeedback = substr($answertext, $gfseparator + 4);
$answertext = trim(substr($answertext, 0, $gfseparator));
}
// Get questiontext format from questiontext.
$text = $this->parse_text_with_format($questiontext);
$question->questiontextformat = $text['format'];
$question->generalfeedbackformat = $text['format'];
$question->questiontext = $text['text'];
// Get generalfeedback format from questiontext.
$text = $this->parse_text_with_format($generalfeedback, $question->questiontextformat);
$question->generalfeedback = $text['text'];
$question->generalfeedbackformat = $text['format'];
// set question name if not already set
if ($question->name === false) {
$question->name = $question->questiontext;
@ -609,6 +623,27 @@ class qformat_gift extends qformat_default {
return $output;
}
/**
* Outputs the general feedback for the question, if any. This needs to be the
* last thing before the }.
* @param object $question the question data.
* @param string $indent to put before the general feedback. Defaults to a tab.
* If this is not blank, a newline is added after the line.
*/
public function write_general_feedback($question, $indent = "\t") {
$generalfeedback = $this->write_questiontext($question->generalfeedback,
$question->generalfeedbackformat, $question->questiontextformat);
if ($generalfeedback) {
$generalfeedback = '####' . $generalfeedback;
if ($indent) {
$generalfeedback = $indent . $generalfeedback . "\n";
}
}
return $generalfeedback;
}
public function writequestion($question) {
global $OUTPUT;
@ -631,7 +666,9 @@ class qformat_gift extends qformat_default {
case ESSAY:
$expout .= $this->write_name($question->name);
$expout .= $this->write_questiontext($question->questiontext, $question->questiontextformat);
$expout .= "{}\n";
$expout .= "{";
$expout .= $this->write_general_feedback($question, '');
$expout .= "}\n";
break;
case TRUEFALSE:
@ -662,6 +699,7 @@ class qformat_gift extends qformat_default {
if ($rightfeedback) {
$expout .= '#' . $rightfeedback;
}
$expout .= $this->write_general_feedback($question, '');
$expout .= "}\n";
break;
@ -686,6 +724,7 @@ class qformat_gift extends qformat_default {
}
$expout .= "\n";
}
$expout .= $this->write_general_feedback($question);
$expout .= "}\n";
break;
@ -699,6 +738,7 @@ class qformat_gift extends qformat_default {
'#' . $this->write_questiontext($answer->feedback,
$answer->feedbackformat, $question->questiontextformat) . "\n";
}
$expout .= $this->write_general_feedback($question);
$expout .= "}\n";
break;
@ -717,6 +757,7 @@ class qformat_gift extends qformat_default {
$answer->feedbackformat, $question->questiontextformat) . "\n";
}
}
$expout .= $this->write_general_feedback($question);
$expout .= "}\n";
break;
@ -729,6 +770,7 @@ class qformat_gift extends qformat_default {
$subquestion->questiontextformat, $question->questiontextformat) .
' -> ' . $this->repchar($subquestion->answertext) . "\n";
}
$expout .= $this->write_general_feedback($question);
$expout .= "}\n";
break;

View File

@ -37,9 +37,10 @@
=%0%*#Completely wrong
}
// true/false
// true/false, with general feedback
::Q1:: 42 is the Absolute Answer to everything.{
FALSE#42 is the Ultimate Answer.#You gave the right answer.}";
FALSE#42 is the Ultimate Answer.#You gave the right answer.
####This is, of course, a Hitchiker's Guide to the Galaxy reference.}";
// name 0-11
::2-08 TSL::TSL is blablabla.{T}

View File

@ -673,6 +673,62 @@ class qformat_gift_test extends question_testcase {
$this->assert(new question_check_specified_fields_expectation($expectedq), $q);
}
public function test_import_shortanswer_with_general_feedback() {
$gift = "
// question: 666 name: Shortanswer
::Shortanswer::Which is the best animal?{
=Frog#Good!
=%50%Cat#What is it with Moodlers and cats?
=%0%*#Completely wrong
####[html]Here is some general feedback!
}";
$lines = preg_split('/[\\n\\r]/', str_replace("\r\n", "\n", $gift));
$importer = new qformat_gift();
$q = $importer->readquestion($lines);
$expectedq = (object) array(
'name' => 'Shortanswer',
'questiontext' => "Which is the best animal?",
'questiontextformat' => FORMAT_MOODLE,
'generalfeedback' => 'Here is some general feedback!',
'generalfeedbackformat' => FORMAT_HTML,
'qtype' => 'shortanswer',
'defaultmark' => 1,
'penalty' => 0.3333333,
'length' => 1,
'answer' => array(
'Frog',
'Cat',
'*',
),
'fraction' => array(1, 0.5, 0),
'feedback' => array(
0 => array(
'text' => 'Good!',
'format' => FORMAT_MOODLE,
'files' => array(),
),
1 => array(
'text' => "What is it with Moodlers and cats?",
'format' => FORMAT_MOODLE,
'files' => array(),
),
2 => array(
'text' => "Completely wrong",
'format' => FORMAT_MOODLE,
'files' => array(),
),
),
);
// Repeated test for better failure messages.
$this->assertEquals($expectedq->answer, $q->answer);
$this->assertEquals($expectedq->fraction, $q->fraction);
$this->assertEquals($expectedq->feedback, $q->feedback);
$this->assert(new question_check_specified_fields_expectation($expectedq), $q);
}
public function test_export_shortanswer() {
$qdata = (object) array(
'id' => 666 ,
@ -728,6 +784,67 @@ class qformat_gift_test extends question_testcase {
\t=%0%*#Completely wrong
}
";
$this->assert_same_gift($expectedgift, $gift);
}
public function test_export_shortanswer_with_general_feedback() {
$qdata = (object) array(
'id' => 666 ,
'name' => 'Shortanswer',
'questiontext' => "Which is the best animal?",
'questiontextformat' => FORMAT_MOODLE,
'generalfeedback' => 'Here is some general feedback!',
'generalfeedbackformat' => FORMAT_HTML,
'defaultmark' => 1,
'penalty' => 1,
'length' => 1,
'qtype' => 'shortanswer',
'options' => (object) array(
'id' => 123,
'question' => 666,
'usecase' => 1,
'answers' => array(
1 => (object) array(
'id' => 1,
'answer' => 'Frog',
'answerformat' => 0,
'fraction' => 1,
'feedback' => 'Good!',
'feedbackformat' => FORMAT_MOODLE,
),
2 => (object) array(
'id' => 2,
'answer' => 'Cat',
'answerformat' => 0,
'fraction' => 0.5,
'feedback' => "What is it with Moodlers and cats?",
'feedbackformat' => FORMAT_MOODLE,
),
3 => (object) array(
'id' => 3,
'answer' => '*',
'answerformat' => 0,
'fraction' => 0,
'feedback' => "Completely wrong",
'feedbackformat' => FORMAT_MOODLE,
),
),
),
);
$exporter = new qformat_gift();
$gift = $exporter->writequestion($qdata);
$expectedgift = "// question: 666 name: Shortanswer
::Shortanswer::Which is the best animal?{
\t=%100%Frog#Good!
\t=%50%Cat#What is it with Moodlers and cats?
\t=%0%*#Completely wrong
\t####[html]Here is some general feedback!
}
";
$this->assert_same_gift($expectedgift, $gift);