matching.class.php 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  1. <?php
  2. /* For licensing terms, see /license.txt */
  3. /**
  4. * Class Matching
  5. * Matching questions type class
  6. *
  7. * This class allows to instantiate an object of
  8. * type MULTIPLE_ANSWER (MULTIPLE CHOICE, MULTIPLE ANSWER)
  9. * extending the class question
  10. *
  11. * @author Eric Marguin
  12. * @package chamilo.exercise
  13. */
  14. class Matching extends Question
  15. {
  16. public static $typePicture = 'matching.png';
  17. public static $explanationLangVar = 'Matching';
  18. /**
  19. * Constructor
  20. */
  21. public function __construct()
  22. {
  23. parent::__construct();
  24. $this->type = MATCHING;
  25. $this->isContent = $this->getIsContent();
  26. }
  27. /**
  28. * @inheritdoc
  29. */
  30. public function createAnswersForm($form)
  31. {
  32. $defaults = array();
  33. $nb_matches = $nb_options = 2;
  34. $matches = array();
  35. $answer = null;
  36. $counter = 1;
  37. if (isset($this->id)) {
  38. $answer = new Answer($this->id);
  39. $answer->read();
  40. if (count($answer->nbrAnswers) > 0) {
  41. for ($i = 1; $i <= $answer->nbrAnswers; $i++) {
  42. $correct = $answer->isCorrect($i);
  43. if (empty($correct)) {
  44. $matches[$answer->selectAutoId($i)] = chr(64 + $counter);
  45. $counter++;
  46. }
  47. }
  48. }
  49. }
  50. if ($form->isSubmitted()) {
  51. $nb_matches = $form->getSubmitValue('nb_matches');
  52. $nb_options = $form->getSubmitValue('nb_options');
  53. if (isset($_POST['lessOptions'])) {
  54. $nb_matches--;
  55. $nb_options--;
  56. }
  57. if (isset($_POST['moreOptions'])) {
  58. $nb_matches++;
  59. $nb_options++;
  60. }
  61. } else if (!empty($this->id)) {
  62. if (count($answer->nbrAnswers) > 0) {
  63. $nb_matches = $nb_options = 0;
  64. for ($i = 1; $i <= $answer->nbrAnswers; $i++) {
  65. if ($answer->isCorrect($i)) {
  66. $nb_matches++;
  67. $defaults['answer['.$nb_matches.']'] = $answer->selectAnswer($i);
  68. $defaults['weighting['.$nb_matches.']'] = float_format($answer->selectWeighting($i), 1);
  69. $defaults['matches['.$nb_matches.']'] = $answer->correct[$i];
  70. } else {
  71. $nb_options++;
  72. $defaults['option['.$nb_options.']'] = $answer->selectAnswer($i);
  73. }
  74. }
  75. }
  76. } else {
  77. $defaults['answer[1]'] = get_lang('DefaultMakeCorrespond1');
  78. $defaults['answer[2]'] = get_lang('DefaultMakeCorrespond2');
  79. $defaults['matches[2]'] = '2';
  80. $defaults['option[1]'] = get_lang('DefaultMatchingOptA');
  81. $defaults['option[2]'] = get_lang('DefaultMatchingOptB');
  82. }
  83. if (empty($matches)) {
  84. for ($i = 1; $i <= $nb_options; ++$i) {
  85. // fill the array with A, B, C.....
  86. $matches[$i] = chr(64 + $i);
  87. }
  88. } else {
  89. for ($i = $counter; $i <= $nb_options; ++$i) {
  90. // fill the array with A, B, C.....
  91. $matches[$i] = chr(64 + $i);
  92. }
  93. }
  94. $form->addElement('hidden', 'nb_matches', $nb_matches);
  95. $form->addElement('hidden', 'nb_options', $nb_options);
  96. // DISPLAY MATCHES
  97. $html = '<table class="table table-striped table-hover">
  98. <thead>
  99. <tr>
  100. <th width="5%">' . get_lang('Number').'</th>
  101. <th width="70%">' . get_lang('Answer').'</th>
  102. <th width="15%">' . get_lang('MatchesTo').'</th>
  103. <th width="10%">' . get_lang('Weighting').'</th>
  104. </tr>
  105. </thead>
  106. <tbody>';
  107. $form->addHeader(get_lang('MakeCorrespond'));
  108. $form->addHtml($html);
  109. if ($nb_matches < 1) {
  110. $nb_matches = 1;
  111. Display::addFlash(
  112. Display::return_message(get_lang('YouHaveToCreateAtLeastOneAnswer'))
  113. );
  114. }
  115. $editorConfig = array(
  116. 'ToolbarSet' => 'TestMatching',
  117. 'Width' => '100%',
  118. 'Height' => '125'
  119. );
  120. for ($i = 1; $i <= $nb_matches; ++$i) {
  121. $renderer = &$form->defaultRenderer();
  122. $renderer->setElementTemplate(
  123. '<td><!-- BEGIN error --><span class="form_error">{error}</span><!-- END error -->{element}</td>',
  124. "answer[$i]"
  125. );
  126. $renderer->setElementTemplate(
  127. '<td><!-- BEGIN error --><span class="form_error">{error}</span><!-- END error -->{element}</td>',
  128. "matches[$i]"
  129. );
  130. $renderer->setElementTemplate(
  131. '<td><!-- BEGIN error --><span class="form_error">{error}</span><!-- END error -->{element}</td>',
  132. "weighting[$i]"
  133. );
  134. $form->addHtml('<tr>');
  135. $form->addHtml("<td>$i</td>");
  136. //$form->addText("answer[$i]", null);
  137. $form->addHtmlEditor(
  138. "answer[$i]",
  139. null,
  140. null,
  141. false,
  142. $editorConfig
  143. );
  144. $form->addSelect(
  145. "matches[$i]",
  146. null,
  147. $matches,
  148. ['id' => 'matches_'.$i]
  149. );
  150. $form->addText(
  151. "weighting[$i]",
  152. null,
  153. true,
  154. ['id' => 'weighting_'.$i, 'value' => 10]
  155. );
  156. $form->addHtml('</tr>');
  157. }
  158. $form->addHtml('</tbody></table>');
  159. // DISPLAY OPTIONS
  160. $html = '<table class="table table-striped table-hover">
  161. <thead>
  162. <tr>
  163. <th width="15%">' . get_lang('Number').'</th>
  164. <th width="85%">' . get_lang('Answer').'</th>
  165. </tr>
  166. </thead>
  167. <tbody>';
  168. $form->addHtml($html);
  169. if ($nb_options < 1) {
  170. $nb_options = 1;
  171. Display::addFlash(
  172. Display::return_message(get_lang('YouHaveToCreateAtLeastOneAnswer'))
  173. );
  174. }
  175. for ($i = 1; $i <= $nb_options; ++$i) {
  176. $renderer = &$form->defaultRenderer();
  177. $renderer->setElementTemplate(
  178. '<td><!-- BEGIN error --><span class="form_error">{error}</span><!-- END error -->{element}</td>',
  179. "option[$i]"
  180. );
  181. $form->addHtml('<tr>');
  182. $form->addHtml('<td>'.chr(64 + $i).'</td>');
  183. $form->addHtmlEditor(
  184. "option[$i]",
  185. null,
  186. null,
  187. false,
  188. $editorConfig
  189. );
  190. $form->addHtml('</tr>');
  191. }
  192. $form->addHtml('</table>');
  193. global $text;
  194. $group = array();
  195. // setting the save button here and not in the question class.php
  196. $group[] = $form->addButtonDelete(get_lang('DelElem'), 'lessOptions', true);
  197. $group[] = $form->addButtonCreate(get_lang('AddElem'), 'moreOptions', true);
  198. $group[] = $form->addButtonSave($text, 'submitQuestion', true);
  199. $form->addGroup($group);
  200. if (!empty($this->id)) {
  201. $form->setDefaults($defaults);
  202. } else {
  203. if ($this->isContent == 1) {
  204. $form->setDefaults($defaults);
  205. }
  206. }
  207. $form->setConstants(
  208. array(
  209. 'nb_matches' => $nb_matches,
  210. 'nb_options' => $nb_options
  211. )
  212. );
  213. }
  214. /**
  215. * @inheritdoc
  216. */
  217. public function processAnswersCreation($form, $exercise)
  218. {
  219. $nb_matches = $form->getSubmitValue('nb_matches');
  220. $nb_options = $form->getSubmitValue('nb_options');
  221. $this->weighting = 0;
  222. $position = 0;
  223. $objAnswer = new Answer($this->id);
  224. // Insert the options
  225. for ($i = 1; $i <= $nb_options; ++$i) {
  226. $position++;
  227. $option = $form->getSubmitValue('option['.$i.']');
  228. $objAnswer->createAnswer($option, 0, '', 0, $position);
  229. }
  230. // Insert the answers
  231. for ($i = 1; $i <= $nb_matches; ++$i) {
  232. $position++;
  233. $answer = $form->getSubmitValue('answer['.$i.']');
  234. $matches = $form->getSubmitValue('matches['.$i.']');
  235. $weighting = $form->getSubmitValue('weighting['.$i.']');
  236. $this->weighting += $weighting;
  237. $objAnswer->createAnswer(
  238. $answer,
  239. $matches,
  240. '',
  241. $weighting,
  242. $position
  243. );
  244. }
  245. $objAnswer->save();
  246. $this->save($exercise);
  247. }
  248. /**
  249. * @inheritdoc
  250. */
  251. public function return_header($exercise, $counter = null, $score = null)
  252. {
  253. $header = parent::return_header($exercise, $counter, $score);
  254. $header .= '<table class="'.$this->question_table_class.'">';
  255. $header .= '<tr>
  256. <th>'.get_lang('ElementList').'</th>
  257. <th>'.get_lang('YourChoice').'</th>
  258. <th>'.get_lang('ExpectedChoice').'</th>
  259. <th>'.get_lang('Status').'</th>
  260. </tr>';
  261. return $header;
  262. }
  263. /**
  264. * Check if a answer is correct
  265. * @param int $position
  266. * @param int $answer
  267. * @param int $questionId
  268. *
  269. * @return bool
  270. */
  271. public static function isCorrect($position, $answer, $questionId)
  272. {
  273. $em = Database::getManager();
  274. $count = $em
  275. ->createQuery('
  276. SELECT COUNT(a) From ChamiloCourseBundle:CQuizAnswer a
  277. WHERE a.iid = :position AND a.correct = :answer AND a.questionId = :question
  278. ')
  279. ->setParameters([
  280. 'position' => $position,
  281. 'answer' => $answer,
  282. 'question' => $questionId
  283. ])
  284. ->getSingleScalarResult();
  285. return $count ? true : false;
  286. }
  287. }