PageRenderTime 35ms CodeModel.GetById 11ms RepoModel.GetById 0ms app.codeStats 0ms

/question/type/truefalse/questiontype.php

https://github.com/henriquecrang/e-UNI
PHP | 374 lines | 254 code | 52 blank | 68 comment | 56 complexity | 10211beb43c0a8bc7931c1bee704b908 MD5 | raw file
Possible License(s): LGPL-2.1, AGPL-3.0, BSD-3-Clause
  1. <?php // $Id: questiontype.php,v 1.17.2.5 2008/12/10 00:54:33 tjhunt Exp $
  2. /////////////////
  3. /// TRUEFALSE ///
  4. /////////////////
  5. /// QUESTION TYPE CLASS //////////////////
  6. /**
  7. * @package questionbank
  8. * @subpackage questiontypes
  9. */
  10. class question_truefalse_qtype extends default_questiontype {
  11. function name() {
  12. return 'truefalse';
  13. }
  14. function save_question_options($question) {
  15. $result = new stdClass;
  16. // fetch old answer ids so that we can reuse them
  17. if (!$oldanswers = get_records("question_answers", "question", $question->id, "id ASC")) {
  18. $oldanswers = array();
  19. }
  20. // Save answer 'True'
  21. if ($true = array_shift($oldanswers)) { // Existing answer, so reuse it
  22. $true->answer = get_string("true", "quiz");
  23. $true->fraction = $question->correctanswer;
  24. $true->feedback = $question->feedbacktrue;
  25. if (!update_record("question_answers", $true)) {
  26. $result->error = "Could not update quiz answer \"true\")!";
  27. return $result;
  28. }
  29. } else {
  30. unset($true);
  31. $true->answer = get_string("true", "quiz");
  32. $true->question = $question->id;
  33. $true->fraction = $question->correctanswer;
  34. $true->feedback = $question->feedbacktrue;
  35. if (!$true->id = insert_record("question_answers", $true)) {
  36. $result->error = "Could not insert quiz answer \"true\")!";
  37. return $result;
  38. }
  39. }
  40. // Save answer 'False'
  41. if ($false = array_shift($oldanswers)) { // Existing answer, so reuse it
  42. $false->answer = get_string("false", "quiz");
  43. $false->fraction = 1 - (int)$question->correctanswer;
  44. $false->feedback = $question->feedbackfalse;
  45. if (!update_record("question_answers", $false)) {
  46. $result->error = "Could not insert quiz answer \"false\")!";
  47. return $result;
  48. }
  49. } else {
  50. unset($false);
  51. $false->answer = get_string("false", "quiz");
  52. $false->question = $question->id;
  53. $false->fraction = 1 - (int)$question->correctanswer;
  54. $false->feedback = $question->feedbackfalse;
  55. if (!$false->id = insert_record("question_answers", $false)) {
  56. $result->error = "Could not insert quiz answer \"false\")!";
  57. return $result;
  58. }
  59. }
  60. // delete any leftover old answer records (there couldn't really be any, but who knows)
  61. if (!empty($oldanswers)) {
  62. foreach($oldanswers as $oa) {
  63. delete_records('question_answers', 'id', $oa->id);
  64. }
  65. }
  66. // Save question options in question_truefalse table
  67. if ($options = get_record("question_truefalse", "question", $question->id)) {
  68. // No need to do anything, since the answer IDs won't have changed
  69. // But we'll do it anyway, just for robustness
  70. $options->trueanswer = $true->id;
  71. $options->falseanswer = $false->id;
  72. if (!update_record("question_truefalse", $options)) {
  73. $result->error = "Could not update quiz truefalse options! (id=$options->id)";
  74. return $result;
  75. }
  76. } else {
  77. unset($options);
  78. $options->question = $question->id;
  79. $options->trueanswer = $true->id;
  80. $options->falseanswer = $false->id;
  81. if (!insert_record("question_truefalse", $options)) {
  82. $result->error = "Could not insert quiz truefalse options!";
  83. return $result;
  84. }
  85. }
  86. return true;
  87. }
  88. /**
  89. * Loads the question type specific options for the question.
  90. */
  91. function get_question_options(&$question) {
  92. // Get additional information from database
  93. // and attach it to the question object
  94. if (!$question->options = get_record('question_truefalse', 'question', $question->id)) {
  95. notify('Error: Missing question options!');
  96. return false;
  97. }
  98. // Load the answers
  99. if (!$question->options->answers = get_records('question_answers', 'question', $question->id, 'id ASC')) {
  100. notify('Error: Missing question answers for truefalse question ' . $question->id . '!');
  101. return false;
  102. }
  103. return true;
  104. }
  105. /**
  106. * Deletes question from the question-type specific tables
  107. *
  108. * @return boolean Success/Failure
  109. * @param object $question The question being deleted
  110. */
  111. function delete_question($questionid) {
  112. delete_records("question_truefalse", "question", $questionid);
  113. return true;
  114. }
  115. function get_correct_responses(&$question, &$state) {
  116. // The correct answer is the one which gives full marks
  117. foreach ($question->options->answers as $answer) {
  118. if (((int) $answer->fraction) === 1) {
  119. return array('' => $answer->id);
  120. }
  121. }
  122. return null;
  123. }
  124. /**
  125. * Prints the main content of the question including any interactions
  126. */
  127. function print_question_formulation_and_controls(&$question, &$state,
  128. $cmoptions, $options) {
  129. global $CFG;
  130. $readonly = $options->readonly ? ' disabled="disabled"' : '';
  131. $formatoptions = new stdClass;
  132. $formatoptions->noclean = true;
  133. $formatoptions->para = false;
  134. // Print question formulation
  135. $questiontext = format_text($question->questiontext,
  136. $question->questiontextformat,
  137. $formatoptions, $cmoptions->course);
  138. $image = get_question_image($question);
  139. $answers = &$question->options->answers;
  140. $trueanswer = &$answers[$question->options->trueanswer];
  141. $falseanswer = &$answers[$question->options->falseanswer];
  142. $correctanswer = ($trueanswer->fraction == 1) ? $trueanswer : $falseanswer;
  143. $trueclass = '';
  144. $falseclass = '';
  145. $truefeedbackimg = '';
  146. $falsefeedbackimg = '';
  147. // Work out which radio button to select (if any)
  148. if (isset($state->responses[''])) {
  149. $response = $state->responses[''];
  150. } else {
  151. $response = '';
  152. }
  153. $truechecked = ($response == $trueanswer->id) ? ' checked="checked"' : '';
  154. $falsechecked = ($response == $falseanswer->id) ? ' checked="checked"' : '';
  155. // Work out visual feedback for answer correctness.
  156. if ($options->feedback) {
  157. if ($truechecked) {
  158. $trueclass = question_get_feedback_class($trueanswer->fraction);
  159. } else if ($falsechecked) {
  160. $falseclass = question_get_feedback_class($falseanswer->fraction);
  161. }
  162. }
  163. if ($options->feedback || $options->correct_responses) {
  164. if (isset($answers[$response])) {
  165. $truefeedbackimg = question_get_feedback_image($trueanswer->fraction, !empty($truechecked) && $options->feedback);
  166. $falsefeedbackimg = question_get_feedback_image($falseanswer->fraction, !empty($falsechecked) && $options->feedback);
  167. }
  168. }
  169. $inputname = ' name="'.$question->name_prefix.'" ';
  170. $trueid = $question->name_prefix.'true';
  171. $falseid = $question->name_prefix.'false';
  172. $radiotrue = '<input type="radio"' . $truechecked . $readonly . $inputname
  173. . 'id="'.$trueid . '" value="' . $trueanswer->id . '" /><label for="'.$trueid . '">'
  174. . s($trueanswer->answer) . '</label>';
  175. $radiofalse = '<input type="radio"' . $falsechecked . $readonly . $inputname
  176. . 'id="'.$falseid . '" value="' . $falseanswer->id . '" /><label for="'.$falseid . '">'
  177. . s($falseanswer->answer) . '</label>';
  178. $feedback = '';
  179. if ($options->feedback and isset($answers[$response])) {
  180. $chosenanswer = $answers[$response];
  181. $feedback = format_text($chosenanswer->feedback, true, $formatoptions, $cmoptions->course);
  182. }
  183. include("$CFG->dirroot/question/type/truefalse/display.html");
  184. }
  185. function grade_responses(&$question, &$state, $cmoptions) {
  186. if (isset($state->responses['']) && isset($question->options->answers[$state->responses['']])) {
  187. $state->raw_grade = $question->options->answers[$state->responses['']]->fraction * $question->maxgrade;
  188. } else {
  189. $state->raw_grade = 0;
  190. }
  191. // Only allow one attempt at the question
  192. $state->penalty = 1 * $question->maxgrade;
  193. // mark the state as graded
  194. $state->event = ($state->event == QUESTION_EVENTCLOSE) ? QUESTION_EVENTCLOSEANDGRADE : QUESTION_EVENTGRADE;
  195. return true;
  196. }
  197. function response_summary($question, $state, $length=80) {
  198. if (isset($question->options->answers[$state->answer])) {
  199. $responses = $question->options->answers[$state->answer]->answer;
  200. } else {
  201. $responses = '';
  202. }
  203. return $responses;
  204. }
  205. function get_actual_response($question, $state) {
  206. if (isset($question->options->answers[$state->responses['']])) {
  207. $responses[] = $question->options->answers[$state->responses['']]->answer;
  208. } else {
  209. $responses[] = '';
  210. }
  211. return $responses;
  212. }
  213. /// BACKUP FUNCTIONS ////////////////////////////
  214. /*
  215. * Backup the data in a truefalse question
  216. *
  217. * This is used in question/backuplib.php
  218. */
  219. function backup($bf,$preferences,$question,$level=6) {
  220. $status = true;
  221. $truefalses = get_records("question_truefalse","question",$question,"id");
  222. //If there are truefalses
  223. if ($truefalses) {
  224. //Iterate over each truefalse
  225. foreach ($truefalses as $truefalse) {
  226. $status = fwrite ($bf,start_tag("TRUEFALSE",$level,true));
  227. //Print truefalse contents
  228. fwrite ($bf,full_tag("TRUEANSWER",$level+1,false,$truefalse->trueanswer));
  229. fwrite ($bf,full_tag("FALSEANSWER",$level+1,false,$truefalse->falseanswer));
  230. $status = fwrite ($bf,end_tag("TRUEFALSE",$level,true));
  231. }
  232. //Now print question_answers
  233. $status = question_backup_answers($bf,$preferences,$question);
  234. }
  235. return $status;
  236. }
  237. /// RESTORE FUNCTIONS /////////////////
  238. /*
  239. * Restores the data in the question
  240. *
  241. * This is used in question/restorelib.php
  242. */
  243. function restore($old_question_id,$new_question_id,$info,$restore) {
  244. $status = true;
  245. //Get the truefalse array
  246. if (array_key_exists('TRUEFALSE', $info['#'])) {
  247. $truefalses = $info['#']['TRUEFALSE'];
  248. } else {
  249. $truefalses = array();
  250. }
  251. //Iterate over truefalse
  252. for($i = 0; $i < sizeof($truefalses); $i++) {
  253. $tru_info = $truefalses[$i];
  254. //Now, build the question_truefalse record structure
  255. $truefalse = new stdClass;
  256. $truefalse->question = $new_question_id;
  257. $truefalse->trueanswer = backup_todb($tru_info['#']['TRUEANSWER']['0']['#']);
  258. $truefalse->falseanswer = backup_todb($tru_info['#']['FALSEANSWER']['0']['#']);
  259. ////We have to recode the trueanswer field
  260. $answer = backup_getid($restore->backup_unique_code,"question_answers",$truefalse->trueanswer);
  261. if ($answer) {
  262. $truefalse->trueanswer = $answer->new_id;
  263. }
  264. ////We have to recode the falseanswer field
  265. $answer = backup_getid($restore->backup_unique_code,"question_answers",$truefalse->falseanswer);
  266. if ($answer) {
  267. $truefalse->falseanswer = $answer->new_id;
  268. }
  269. //The structure is equal to the db, so insert the question_truefalse
  270. $newid = insert_record ("question_truefalse", $truefalse);
  271. //Do some output
  272. if (($i+1) % 50 == 0) {
  273. if (!defined('RESTORE_SILENTLY')) {
  274. echo ".";
  275. if (($i+1) % 1000 == 0) {
  276. echo "<br />";
  277. }
  278. }
  279. backup_flush(300);
  280. }
  281. if (!$newid) {
  282. $status = false;
  283. }
  284. }
  285. return $status;
  286. }
  287. function restore_recode_answer($state, $restore) {
  288. //answer may be empty
  289. if ($state->answer) {
  290. $answer = backup_getid($restore->backup_unique_code,"question_answers",$state->answer);
  291. if ($answer) {
  292. return $answer->new_id;
  293. } else {
  294. echo 'Could not recode truefalse answer id '.$state->answer.' for state '.$state->oldid.'<br />';
  295. }
  296. }
  297. }
  298. /**
  299. * Runs all the code required to set up and save an essay question for testing purposes.
  300. * Alternate DB table prefix may be used to facilitate data deletion.
  301. */
  302. function generate_test($name, $courseid = null) {
  303. list($form, $question) = parent::generate_test($name, $courseid);
  304. $question->category = $form->category;
  305. $form->questiontext = "This question is really stupid";
  306. $form->penalty = 1;
  307. $form->defaultgrade = 1;
  308. $form->correctanswer = 0;
  309. $form->feedbacktrue = array('Can you justify such a hasty judgment?');
  310. $form->feedbackfalse = array('Wisdom has spoken!');
  311. if ($courseid) {
  312. $course = get_record('course', 'id', $courseid);
  313. }
  314. return $this->save_question($question, $form, $course);
  315. }
  316. }
  317. //// END OF CLASS ////
  318. //////////////////////////////////////////////////////////////////////////
  319. //// INITIATION - Without this line the question type is not in use... ///
  320. //////////////////////////////////////////////////////////////////////////
  321. question_register_questiontype(new question_truefalse_qtype());
  322. ?>