PageRenderTime 52ms CodeModel.GetById 23ms RepoModel.GetById 1ms app.codeStats 0ms

/attempt/hp/6/jquiz/renderer.php

https://github.com/KieranRBriggs/moodle-mod_hotpot
PHP | 404 lines | 191 code | 52 blank | 161 comment | 30 complexity | fd19ef4b505623edb9573264fb6668d4 MD5 | raw file
  1. <?php
  2. // This file is part of Moodle - http://moodle.org/
  3. //
  4. // Moodle is free software: you can redistribute it and/or modify
  5. // it under the terms of the GNU General Public License as published by
  6. // the Free Software Foundation, either version 3 of the License, or
  7. // (at your option) any later version.
  8. //
  9. // Moodle is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU General Public License
  15. // along with Moodle. If not, see <http://www.gnu.org/licenses/>.
  16. /**
  17. * Render an attempt at a HotPot quiz
  18. * Output format: hp_6_jquiz
  19. *
  20. * @package mod-hotpot
  21. * @copyright 2010 Gordon Bateson <gordon.bateson@gmail.com>
  22. * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  23. */
  24. defined('MOODLE_INTERNAL') || die();
  25. // get parent class
  26. require_once($CFG->dirroot.'/mod/hotpot/attempt/hp/6/renderer.php');
  27. /**
  28. * mod_hotpot_attempt_hp_6_jquiz_renderer
  29. *
  30. * @copyright 2010 Gordon Bateson
  31. * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  32. * @since Moodle 2.0
  33. */
  34. class mod_hotpot_attempt_hp_6_jquiz_renderer extends mod_hotpot_attempt_hp_6_renderer {
  35. public $icon = 'pix/f/jqz.gif';
  36. public $js_object_type = 'JQuiz';
  37. public $templatefile = 'jquiz6.ht_';
  38. public $templatestrings = 'PreloadImageList|QsToShow';
  39. // Glossary autolinking settings
  40. public $headcontent_strings = 'CorrectIndicator|IncorrectIndicator|YourScoreIs|CorrectFirstTime|DefaultRight|DefaultWrong|ShowAllQuestionsCaption|ShowOneByOneCaption|I';
  41. public $headcontent_arrays = 'I';
  42. public $response_num_fields = array(
  43. 'score', 'weighting', 'hints', 'checks' // remove: clues
  44. );
  45. /**
  46. * init
  47. *
  48. * @param xxx $hotpot
  49. */
  50. function init($hotpot) {
  51. parent::init($hotpot);
  52. array_push($this->javascripts, 'mod/hotpot/attempt/hp/6/jquiz/jquiz.js');
  53. }
  54. /**
  55. * fix_bodycontent
  56. */
  57. function fix_bodycontent() {
  58. // switch off auto complete on short answer text boxes
  59. $search = '/<div class="ShortAnswer"[^>]*><form([^>]*)>/';
  60. if (preg_match_all($search, $this->bodycontent, $matches, PREG_OFFSET_CAPTURE)) {
  61. $i_max = count($matches[0]) - 1;
  62. for ($i=$i_max; $i>=0; $i--) {
  63. list($match, $start) = $matches[1][$i];
  64. if (strpos($match, 'autocomplete')===false) {
  65. $start += strlen($match);
  66. $this->bodycontent = substr_replace($this->bodycontent, ' autocomplete="off"', $start, 0);
  67. }
  68. }
  69. }
  70. parent::fix_bodycontent();
  71. }
  72. /**
  73. * fix_headcontent
  74. */
  75. function fix_headcontent() {
  76. if ($pos = strrpos($this->headcontent, '</style>')) {
  77. $insert = ''
  78. .'ol.QuizQuestions{'."\n"
  79. .' margin-bottom:0px;'."\n"
  80. .'}'."\n"
  81. ;
  82. $this->headcontent = substr_replace($this->headcontent, $insert, $pos, 0);
  83. }
  84. parent::fix_headcontent();
  85. }
  86. /**
  87. * get_js_functionnames
  88. *
  89. * @return xxx
  90. */
  91. function get_js_functionnames() {
  92. // start list of function names
  93. $names = parent::get_js_functionnames();
  94. $names .= ($names ? ',' : '').'TypeChars,ShowHint,ShowAnswers,ChangeQ,ShowHideQuestions,CheckMCAnswer,CheckMultiSelAnswer,CheckShortAnswer,CheckFinished,SwitchHybridDisplay,SetUpQuestions,CalculateOverallScore';
  95. return $names;
  96. }
  97. /**
  98. * fix_js_TypeChars_obj
  99. *
  100. * @return xxx
  101. */
  102. function fix_js_TypeChars_obj() {
  103. return 'CurrBox';
  104. }
  105. /**
  106. * fix_js_ChangeQ
  107. *
  108. * @param xxx $str (passed by reference)
  109. * @param xxx $start
  110. * @param xxx $length
  111. */
  112. function fix_js_ChangeQ(&$str, $start, $length) {
  113. $substr = substr($str, $start, $length);
  114. // stretch the canvas vertically down to cover the reading, if any
  115. if ($pos = strrpos($substr, '}')) {
  116. $substr = substr_replace($substr, ' StretchCanvasToCoverContent(true);'."\n", $pos, 0);
  117. }
  118. $str = substr_replace($str, $substr, $start, $length);
  119. }
  120. /**
  121. * fix_js_ShowHideQuestions
  122. *
  123. * @param xxx $str (passed by reference)
  124. * @param xxx $start
  125. * @param xxx $length
  126. */
  127. function fix_js_ShowHideQuestions(&$str, $start, $length) {
  128. $substr = substr($str, $start, $length);
  129. // hide/show bottom border of questions (override class="QuizQuestion")
  130. $n = "\n\t\t\t\t";
  131. if ($pos = strpos($substr, "QArray[i].style.display = '';")) {
  132. $substr = substr_replace($substr, 'if ((i+1)<QArray.length){'.$n."\t"."QArray[i].style.borderWidth = '';".$n.'}'.$n, $pos, 0);
  133. }
  134. if ($pos = strpos($substr, "if (i != CurrQNum){")) {
  135. $substr = substr_replace($substr, "QArray[i].style.borderWidth = '0px';".$n, $pos, 0);
  136. }
  137. // stretch the canvas vertically down to cover the reading, if any
  138. if ($pos = strrpos($substr, '}')) {
  139. $substr = substr_replace($substr, ' StretchCanvasToCoverContent(true);'."\n", $pos, 0);
  140. }
  141. $str = substr_replace($str, $substr, $start, $length);
  142. }
  143. /**
  144. * fix_js_SetUpQuestions
  145. *
  146. * @param xxx $str (passed by reference)
  147. * @param xxx $start
  148. * @param xxx $length
  149. */
  150. function fix_js_SetUpQuestions(&$str, $start, $length) {
  151. $substr = substr($str, $start, $length);
  152. // catch FF errors due to invalid XHTML syntax (e.g. inclosed <font> tags)
  153. $search = "QList.push(Qs.removeChild(Qs.getElementsByTagName('li')[0]));";
  154. if ($pos = strrpos($substr, $search)) {
  155. $replace = ''
  156. ."try {\n\t\t"
  157. ." ".$search."\n\t\t"
  158. ."} catch(err) {\n\t\t"
  159. ." alert('Sorry, SetUpQuestions() failed.'+'\\n'+'Perhaps the XHTML of this quiz file is not valid?');\n\t\t"
  160. ." return;\n\t\t"
  161. ."}"
  162. ;
  163. $substr = substr_replace($substr, $replace, $pos, strlen($search));
  164. }
  165. // hide bottom border of question (override class="QuizQuestion")
  166. if ($pos = strpos($substr, "Qs.appendChild(QList[i]);")) {
  167. $substr = substr_replace($substr, "QList[i].style.borderWidth = '0px';"."\n\t\t", $pos, 0);
  168. }
  169. $str = substr_replace($str, $substr, $start, $length);
  170. }
  171. /**
  172. * fix_js_SwitchHybridDisplay
  173. *
  174. * @param xxx $str (passed by reference)
  175. * @param xxx $start
  176. * @param xxx $length
  177. */
  178. function fix_js_SwitchHybridDisplay(&$str, $start, $length) {
  179. $substr = substr($str, $start, $length);
  180. // stretch the canvas vertically down to cover the reading, if any
  181. if ($pos = strrpos($substr, '}')) {
  182. $substr = substr_replace($substr, ' StretchCanvasToCoverContent(true);'."\n", $pos, 0);
  183. }
  184. $str = substr_replace($str, $substr, $start, $length);
  185. }
  186. /**
  187. * fix_js_ShowHint
  188. *
  189. * @param xxx $str (passed by reference)
  190. * @param xxx $start
  191. * @param xxx $length
  192. */
  193. function fix_js_ShowHint(&$str, $start, $length) {
  194. $substr = substr($str, $start, $length);
  195. // intercept Hints
  196. if ($pos = strpos($substr, '{')) {
  197. $insert = "\n"
  198. ." // intercept this Hint\n"
  199. ." HP.onclickHint(QNum);\n"
  200. ;
  201. $substr = substr_replace($substr, $insert, $pos+1, 0);
  202. }
  203. $str = substr_replace($str, $substr, $start, $length);
  204. }
  205. /**
  206. * fix_js_ShowAnswers
  207. *
  208. * @param xxx $str (passed by reference)
  209. * @param xxx $start
  210. * @param xxx $length
  211. */
  212. function fix_js_ShowAnswers(&$str, $start, $length) {
  213. $substr = substr($str, $start, $length);
  214. // intercept Clues
  215. if ($pos = strpos($substr, '{')) {
  216. $insert = "\n"
  217. ." // intercept this Clue\n"
  218. ." if (State[QNum][0]<1) HP.onclickClue(QNum);\n"
  219. ;
  220. $substr = substr_replace($substr, $insert, $pos+1, 0);
  221. }
  222. $str = substr_replace($str, $substr, $start, $length);
  223. }
  224. /**
  225. * fix_js_CheckMCAnswer
  226. *
  227. * @param xxx $str (passed by reference)
  228. * @param xxx $start
  229. * @param xxx $length
  230. */
  231. function fix_js_CheckMCAnswer(&$str, $start, $length) {
  232. $substr = substr($str, $start, $length);
  233. // intercept Check
  234. if ($pos = strpos($substr, '{')) {
  235. $insert = "\n"
  236. ." // intercept this Check\n"
  237. ." if(!Finished && State[QNum].length && State[QNum][0]<0) {\n"
  238. ." var args = new Array(QNum, I[QNum][3][ANum][0]);\n"
  239. ." HP.onclickCheck(args);\n"
  240. ." }\n"
  241. ;
  242. $substr = substr_replace($substr, $insert, $pos+1, 0);
  243. }
  244. $str = substr_replace($str, $substr, $start, $length);
  245. }
  246. /**
  247. * fix_js_CheckShortAnswer
  248. *
  249. * @param xxx $str (passed by reference)
  250. * @param xxx $start
  251. * @param xxx $length
  252. */
  253. function fix_js_CheckShortAnswer(&$str, $start, $length) {
  254. $substr = substr($str, $start, $length);
  255. // intercept Check
  256. if ($pos = strpos($substr, '{')) {
  257. $insert = "\n"
  258. ." // intercept this Check\n"
  259. ." if(!Finished && State[QNum].length && State[QNum][0]<0) {\n"
  260. ." var obj = document.getElementById('Q_'+QNum+'_Guess');\n"
  261. ." var args = new Array(QNum, obj.value);\n"
  262. ." HP.onclickCheck(args);\n"
  263. ." }\n"
  264. ;
  265. $substr = substr_replace($substr, $insert, $pos+1, 0);
  266. }
  267. $str = substr_replace($str, $substr, $start, $length);
  268. }
  269. /**
  270. * fix_js_CheckMultiSelAnswer
  271. *
  272. * @param xxx $str (passed by reference)
  273. * @param xxx $start
  274. * @param xxx $length
  275. */
  276. function fix_js_CheckMultiSelAnswer(&$str, $start, $length) {
  277. $substr = substr($str, $start, $length);
  278. // intercept Check
  279. if ($pos = strpos($substr, '{')) {
  280. $insert = "\n"
  281. ." // intercept this Check\n"
  282. ." if(!Finished && State[QNum].length && State[QNum][0]<0) {\n"
  283. ." var g='';\n"
  284. ." for (var ANum=0; ANum<I[QNum][3].length; ANum++){\n"
  285. ." var obj = document.getElementById('Q_'+QNum+'_'+ANum+'_Chk');\n"
  286. ." if (obj.checked) g += (g ? '+' : '') + I[QNum][3][ANum][0];\n"
  287. ." }\n"
  288. ." var args = new Array(QNum, g);\n"
  289. ." HP.onclickCheck(args);\n"
  290. ." }\n"
  291. ;
  292. $substr = substr_replace($substr, $insert, $pos+1, 0);
  293. }
  294. $str = substr_replace($str, $substr, $start, $length);
  295. }
  296. /**
  297. * fix_js_CheckFinished
  298. *
  299. * @param xxx $str (passed by reference)
  300. * @param xxx $start
  301. * @param xxx $length
  302. */
  303. function fix_js_CheckFinished(&$str, $start, $length) {
  304. $substr = substr($str, $start, $length);
  305. // remove creation of HotPotNet results XML and call to Finish()
  306. $search = '/\s*'.'Detail = [^;]*?;'.'.*?'.'setTimeout[^;]*;'.'/s';
  307. $substr = preg_replace($search, '', $substr, 1);
  308. // add other changes as per CheckAnswers in other type of HP quiz
  309. $this->fix_js_CheckAnswers($substr, 0, strlen($substr));
  310. $str = substr_replace($str, $substr, $start, $length);
  311. }
  312. /**
  313. * fix_js_CalculateOverallScore
  314. *
  315. * @param xxx $str (passed by reference)
  316. * @param xxx $start
  317. * @param xxx $length
  318. */
  319. function fix_js_CalculateOverallScore(&$str, $start, $length) {
  320. $substr = substr($str, $start, $length);
  321. $substr = preg_replace('/(\s*)var TotalScore = 0;/s', '$0$1'.'var TotalCount = 0;', $substr, 1);
  322. $substr = preg_replace('/(\s*)TotalScore \+= [^;]*;/s', '$0$1'.'TotalCount ++;', $substr, 1);
  323. $substr = preg_replace('/(\s*)\}\s*else\s*\{/s', '$1} else if (TotalCount==0) {$1'."\t".'Score = 0;'.'$0', $substr, 1);
  324. $str = substr_replace($str, $substr, $start, $length);
  325. }
  326. /**
  327. * get_stop_function_name
  328. *
  329. * @return xxx
  330. */
  331. function get_stop_function_name() {
  332. return 'CheckFinished';
  333. }
  334. /**
  335. * get_stop_function_intercept
  336. *
  337. * @return xxx
  338. */
  339. function get_stop_function_intercept() {
  340. // intercept is not required in the giveup function of JQuiz
  341. // because the checks are intercepted by CheckFinished (see above)
  342. return '';
  343. }
  344. /**
  345. * get_stop_function_search
  346. *
  347. * @return xxx
  348. */
  349. function get_stop_function_search() {
  350. return '/\s*if \((AllDone) == true\)({.*?WriteToInstructions[^;]*;).*?\w+ = true;\s*}\s*/s';
  351. }
  352. }