7 /// QUESTION TYPE CLASS //////////////////
9 * @package questionbank
10 * @subpackage questiontypes
12 class question_truefalse_qtype
extends default_questiontype
{
18 function save_question_options($question) {
19 $result = new stdClass
;
21 // fetch old answer ids so that we can reuse them
22 if (!$oldanswers = get_records("question_answers", "question", $question->id
, "id ASC")) {
23 $oldanswers = array();
27 if ($true = array_shift($oldanswers)) { // Existing answer, so reuse it
28 $true->answer
= get_string("true", "quiz");
29 $true->fraction
= $question->correctanswer
;
30 $true->feedback
= $question->feedbacktrue
;
31 if (!update_record("question_answers", $true)) {
32 $result->error
= "Could not update quiz answer \"true\")!";
37 $true->answer
= get_string("true", "quiz");
38 $true->question
= $question->id
;
39 $true->fraction
= $question->correctanswer
;
40 $true->feedback
= $question->feedbacktrue
;
41 if (!$true->id
= insert_record("question_answers", $true)) {
42 $result->error
= "Could not insert quiz answer \"true\")!";
47 // Save answer 'False'
48 if ($false = array_shift($oldanswers)) { // Existing answer, so reuse it
49 $false->answer
= get_string("false", "quiz");
50 $false->fraction
= 1 - (int)$question->correctanswer
;
51 $false->feedback
= $question->feedbackfalse
;
52 if (!update_record("question_answers", $false)) {
53 $result->error
= "Could not insert quiz answer \"false\")!";
58 $false->answer
= get_string("false", "quiz");
59 $false->question
= $question->id
;
60 $false->fraction
= 1 - (int)$question->correctanswer
;
61 $false->feedback
= $question->feedbackfalse
;
62 if (!$false->id
= insert_record("question_answers", $false)) {
63 $result->error
= "Could not insert quiz answer \"false\")!";
68 // delete any leftover old answer records (there couldn't really be any, but who knows)
69 if (!empty($oldanswers)) {
70 foreach($oldanswers as $oa) {
71 delete_records('question_answers', 'id', $oa->id
);
75 // Save question options in question_truefalse table
76 if ($options = get_record("question_truefalse", "question", $question->id
)) {
77 // No need to do anything, since the answer IDs won't have changed
78 // But we'll do it anyway, just for robustness
79 $options->trueanswer
= $true->id
;
80 $options->falseanswer
= $false->id
;
81 if (!update_record("question_truefalse", $options)) {
82 $result->error
= "Could not update quiz truefalse options! (id=$options->id)";
87 $options->question
= $question->id
;
88 $options->trueanswer
= $true->id
;
89 $options->falseanswer
= $false->id
;
90 if (!insert_record("question_truefalse", $options)) {
91 $result->error
= "Could not insert quiz truefalse options!";
99 * Loads the question type specific options for the question.
101 function get_question_options(&$question) {
102 // Get additional information from database
103 // and attach it to the question object
104 if (!$question->options
= get_record('question_truefalse', 'question', $question->id
)) {
105 notify('Error: Missing question options!');
109 if (!$question->options
->answers
= get_records('question_answers', 'question', $question->id
, 'id ASC')) {
110 notify('Error: Missing question answers!');
118 * Deletes question from the question-type specific tables
120 * @return boolean Success/Failure
121 * @param object $question The question being deleted
123 function delete_question($questionid) {
124 delete_records("question_truefalse", "question", $questionid);
128 function get_correct_responses(&$question, &$state) {
129 // The correct answer is the one which gives full marks
130 foreach ($question->options
->answers
as $answer) {
131 if (((int) $answer->fraction
) === 1) {
132 return array('' => $answer->id
);
139 * Prints the main content of the question including any interactions
141 function print_question_formulation_and_controls(&$question, &$state,
142 $cmoptions, $options) {
145 $readonly = $options->readonly ?
' disabled="disabled"' : '';
147 $formatoptions = new stdClass
;
148 $formatoptions->noclean
= true;
149 $formatoptions->para
= false;
151 // Print question formulation
152 $questiontext = format_text($question->questiontext
,
153 $question->questiontextformat
,
154 $formatoptions, $cmoptions->course
);
155 $image = get_question_image($question);
157 $answers = &$question->options
->answers
;
158 $trueanswer = &$answers[$question->options
->trueanswer
];
159 $falseanswer = &$answers[$question->options
->falseanswer
];
160 $correctanswer = ($trueanswer->fraction
== 1) ?
$trueanswer : $falseanswer;
164 $truefeedbackimg = '';
165 $falsefeedbackimg = '';
167 // Work out which radio button to select (if any)
168 if (isset($state->responses
[''])) {
169 $response = $state->responses
[''];
173 $truechecked = ($response == $trueanswer->id
) ?
' checked="checked"' : '';
174 $falsechecked = ($response == $falseanswer->id
) ?
' checked="checked"' : '';
176 // Work out visual feedback for answer correctness.
177 if ($options->feedback
) {
179 $trueclass = question_get_feedback_class($trueanswer->fraction
);
180 } else if ($falsechecked) {
181 $falseclass = question_get_feedback_class($falseanswer->fraction
);
184 if ($options->feedback ||
$options->correct_responses
) {
185 if (isset($answers[$response])) {
186 $truefeedbackimg = question_get_feedback_image($trueanswer->fraction
, !empty($truechecked) && $options->feedback
);
187 $falsefeedbackimg = question_get_feedback_image($falseanswer->fraction
, !empty($falsechecked) && $options->feedback
);
191 $inputname = ' name="'.$question->name_prefix
.'" ';
192 $trueid = $question->name_prefix
.'true';
193 $falseid = $question->name_prefix
.'false';
195 $radiotrue = '<input type="radio"' . $truechecked . $readonly . $inputname
196 . 'id="'.$trueid . '" value="' . $trueanswer->id
. '" alt="'
197 . s($trueanswer->answer
) . '" /><label for="'.$trueid . '">'
198 . s($trueanswer->answer
) . '</label>';
199 $radiofalse = '<input type="radio"' . $falsechecked . $readonly . $inputname
200 . 'id="'.$falseid . '" value="' . $falseanswer->id
. '" alt="'
201 . s($falseanswer->answer
) . '" /><label for="'.$falseid . '">'
202 . s($falseanswer->answer
) . '</label>';
205 if ($options->feedback
and isset($answers[$response])) {
206 $chosenanswer = $answers[$response];
207 $feedback = format_text($chosenanswer->feedback
, true, $formatoptions, $cmoptions->course
);
210 include("$CFG->dirroot/question/type/truefalse/display.html");
213 function grade_responses(&$question, &$state, $cmoptions) {
214 if (isset($state->responses
['']) && isset($question->options
->answers
[$state->responses
['']])) {
215 $state->raw_grade
= $question->options
->answers
[$state->responses
['']]->fraction
* $question->maxgrade
;
217 $state->raw_grade
= 0;
219 // Only allow one attempt at the question
220 $state->penalty
= 1 * $question->maxgrade
;
222 // mark the state as graded
223 $state->event
= ($state->event
== QUESTION_EVENTCLOSE
) ? QUESTION_EVENTCLOSEANDGRADE
: QUESTION_EVENTGRADE
;
228 function response_summary($question, $state, $length=80) {
229 if (isset($question->options
->answers
[$state->answer
])) {
230 $responses = $question->options
->answers
[$state->answer
]->answer
;
237 function get_actual_response($question, $state) {
238 if (isset($question->options
->answers
[$state->responses
['']])) {
239 $responses[] = $question->options
->answers
[$state->responses
['']]->answer
;
246 /// BACKUP FUNCTIONS ////////////////////////////
249 * Backup the data in a truefalse question
251 * This is used in question/backuplib.php
253 function backup($bf,$preferences,$question,$level=6) {
257 $truefalses = get_records("question_truefalse","question",$question,"id");
258 //If there are truefalses
260 //Iterate over each truefalse
261 foreach ($truefalses as $truefalse) {
262 $status = fwrite ($bf,start_tag("TRUEFALSE",$level,true));
263 //Print truefalse contents
264 fwrite ($bf,full_tag("TRUEANSWER",$level+
1,false,$truefalse->trueanswer
));
265 fwrite ($bf,full_tag("FALSEANSWER",$level+
1,false,$truefalse->falseanswer
));
266 $status = fwrite ($bf,end_tag("TRUEFALSE",$level,true));
268 //Now print question_answers
269 $status = question_backup_answers($bf,$preferences,$question);
274 /// RESTORE FUNCTIONS /////////////////
277 * Restores the data in the question
279 * This is used in question/restorelib.php
281 function restore($old_question_id,$new_question_id,$info,$restore) {
285 //Get the truefalse array
286 $truefalses = $info['#']['TRUEFALSE'];
288 //Iterate over truefalse
289 for($i = 0; $i < sizeof($truefalses); $i++
) {
290 $tru_info = $truefalses[$i];
292 //Now, build the question_truefalse record structure
293 $truefalse = new stdClass
;
294 $truefalse->question
= $new_question_id;
295 $truefalse->trueanswer
= backup_todb($tru_info['#']['TRUEANSWER']['0']['#']);
296 $truefalse->falseanswer
= backup_todb($tru_info['#']['FALSEANSWER']['0']['#']);
298 ////We have to recode the trueanswer field
299 $answer = backup_getid($restore->backup_unique_code
,"question_answers",$truefalse->trueanswer
);
301 $truefalse->trueanswer
= $answer->new_id
;
304 ////We have to recode the falseanswer field
305 $answer = backup_getid($restore->backup_unique_code
,"question_answers",$truefalse->falseanswer
);
307 $truefalse->falseanswer
= $answer->new_id
;
310 //The structure is equal to the db, so insert the question_truefalse
311 $newid = insert_record ("question_truefalse", $truefalse);
314 if (($i+
1) %
50 == 0) {
315 if (!defined('RESTORE_SILENTLY')) {
317 if (($i+
1) %
1000 == 0) {
332 function restore_recode_answer($state, $restore) {
333 $answer = backup_getid($restore->backup_unique_code
,"question_answers",$state->answer
);
335 return $answer->new_id
;
337 echo 'Could not recode truefalse answer id '.$state->answer
.' for state '.$state->oldid
.'<br />';
343 //// END OF CLASS ////
345 //////////////////////////////////////////////////////////////////////////
346 //// INITIATION - Without this line the question type is not in use... ///
347 //////////////////////////////////////////////////////////////////////////
348 question_register_questiontype(new question_truefalse_qtype());