PageRenderTime 62ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 1ms

/common/libraries/php/shared/ims/qti/import_strategy/qti_import_strategy_generic.class.php

https://bitbucket.org/cbenelug/chamilo
PHP | 931 lines | 748 code | 99 blank | 84 comment | 113 complexity | 0b5842f2a408da673aaef84e715b0496 MD5 | raw file
Possible License(s): GPL-3.0, MIT, GPL-2.0, BSD-3-Clause, LGPL-2.1, LGPL-3.0
  1. <?php
  2. namespace common\libraries;
  3. use Exception;
  4. /**
  5. * Generic import strategy. Make as little assumptions as possible about the qti file.
  6. *
  7. * University of Geneva
  8. * @author laurent.opprecht@unige.ch
  9. *
  10. */
  11. class QtiImportStrategyGeneric extends QtiImportStrategyBase
  12. {
  13. public function __construct(QtiRendererBase $renderer, $head)
  14. {
  15. parent :: __construct($renderer, $head);
  16. }
  17. public function get_question_text(ImsXmlReader $item)
  18. {
  19. $body = $item->get_itemBody();
  20. $result = $this->to_html($body);
  21. return $result;
  22. }
  23. public function get_question_title(ImsXmlReader $item)
  24. {
  25. return $item->title;
  26. }
  27. //FEEDBACKS
  28. public function get_feedbacks(ImsXmlReader $item, ImsXmlReader $interaction, $answer, $filter_out = array())
  29. {
  30. $modal_feedbacks = $this->head()->get_modal_feedbacks($item, $interaction, $answer, $filter_out);
  31. $inline_feedbacks = $this->head()->get_inline_feedbacks($item, $interaction, $answer, $filter_out);
  32. $result = array_merge($modal_feedbacks, $inline_feedbacks);
  33. $result = array_diff($result, $filter_out);
  34. return $result;
  35. }
  36. public function get_modal_feedbacks(ImsXmlReader $item, ImsXmlReader $interaction, $answer, $filter_out = array())
  37. {
  38. $interpreter = new QtiInterpreter();
  39. $interpreter->init($item);
  40. $interpreter->add_response($interaction, $answer);
  41. $interpreter->response($item);
  42. $this->get_renderer()->init($interpreter);
  43. $result = $this->render($item->list_modalFeedback());
  44. $result = array_diff($result, $filter_out, array(''));
  45. $this->get_renderer()->reset_outcomes();
  46. return $result;
  47. }
  48. public function get_inline_feedbacks(ImsXmlReader $item, ImsXmlReader $interaction, $answer, $filter_out = array())
  49. {
  50. $interpreter = new QtiInterpreter();
  51. $interpreter->init($item);
  52. $interpreter->add_response($interaction, $answer);
  53. $interpreter->response($item);
  54. $this->get_renderer()->init($interpreter);
  55. $result = $this->render($item->all_feedbackInline());
  56. $result = array_diff($result, $filter_out, array(''));
  57. $this->get_renderer()->reset_outcomes();
  58. return $result;
  59. }
  60. /**
  61. * I.e. feedbacks that are always output
  62. * @param ImsXmlReader $item
  63. * @return array
  64. */
  65. public function get_general_feedbacks(ImsXmlReader $item)
  66. {
  67. $feedbacks = $item->list_modalFeedback();
  68. $interpreter = new QtiInterpreter();
  69. $interpreter->execute($item);
  70. $this->get_renderer()->init($interpreter);
  71. $null_feedbacks = $this->render($feedbacks);
  72. $interpreter = new QtiInterpreter();
  73. $this->head()->set_correct_responses($item, $interpreter);
  74. $interpreter->execute($item);
  75. $this->get_renderer()->init($interpreter);
  76. $correct_feedbacks = $this->render($feedbacks);
  77. $interpreter = new QtiInterpreter();
  78. $this->head()->set_incorrect_responses($item, $interpreter);
  79. $interpreter->execute($item);
  80. $this->get_renderer()->init($interpreter);
  81. $incorrect_feedbacks = $this->render($feedbacks);
  82. $result = array();
  83. for($i = 0; $i < count($feedbacks); $i ++)
  84. {
  85. if ($null_feedbacks[$i] == $correct_feedbacks[$i] && $correct_feedbacks[$i] == $incorrect_feedbacks[$i] && ! empty($correct_feedbacks[$i]))
  86. {
  87. $result[] = $correct_feedbacks[$i];
  88. }
  89. }
  90. $this->get_renderer()->reset_outcomes();
  91. return $result;
  92. }
  93. /**
  94. * Feedback for any correct response
  95. * @param ImsXmlReader $item
  96. * @param array $filter_out
  97. * @return array
  98. */
  99. public function get_correct_feedbacks(ImsXmlReader $item, $filter_out = array())
  100. {
  101. $interpreter = new QtiInterpreter();
  102. $interpreter->init($item);
  103. $this->head()->set_correct_responses($item, $interpreter);
  104. $interpreter->response($item);
  105. $this->get_renderer()->init($interpreter);
  106. $result = $this->render($item->list_modalFeedback());
  107. $result = array_diff($result, $filter_out, array(''));
  108. $this->get_renderer()->reset_outcomes();
  109. return $result;
  110. }
  111. /**
  112. * Feedback for any partially correct response
  113. * @param ImsXmlReader $item
  114. * @param array $filter_out
  115. * @return array
  116. */
  117. public function get_partiallycorrect_feedbacks(ImsXmlReader $item, $filter_out = array())
  118. {
  119. return false;
  120. }
  121. /**
  122. * Feedback for any incorrect response
  123. * @param ImsXmlReader $item
  124. * @param array $filter_out
  125. * @return array
  126. */
  127. public function get_incorrect_feedbacks(ImsXmlReader $item, $filter_out = array())
  128. {
  129. $interpreter = new QtiInterpreter();
  130. $interpreter->execute($item);
  131. $this->get_renderer()->init($interpreter);
  132. $result = $this->render($item->list_modalFeedback());
  133. $result = array_diff($result, $filter_out, array(''));
  134. $this->get_renderer()->reset_outcomes();
  135. return $result;
  136. }
  137. /**
  138. * Returns all visible inline feedbacks which are a descendant of parent
  139. * @param ImsXmlReader $item
  140. * @param ImsXmlReader $interaction
  141. * @param any $answer
  142. * @param ImsXmlReader $parent
  143. * @return array
  144. */
  145. public function get_children_feedbacks(ImsXmlReader $item, ImsXmlReader $interaction, $answer, $parent)
  146. {
  147. $interpreter = new QtiInterpreter();
  148. $interpreter->init($item);
  149. $interpreter->add_response($interaction, $answer);
  150. $interpreter->response($item);
  151. $this->get_renderer()->init($interpreter);
  152. $result = $this->render($parent->all_feedbackInline());
  153. $this->get_renderer()->reset_outcomes();
  154. return $result;
  155. }
  156. //END FEEDBACKS
  157. //SCORE
  158. public function get_outcome(ImsXmlReader $item, ImsXmlReader $interaction, $answer, $outcome_id = '')
  159. {
  160. $interpreter = new QtiInterpreter();
  161. $interpreter->init($item);
  162. if (empty($outcome_id))
  163. {
  164. $declaration = $this->head()->get_score_outcome_declaration($item);
  165. if ($declaration->is_empty())
  166. { //i.e. no correct outcome
  167. return 0;
  168. }
  169. $outcome_id = $declaration->identifier;
  170. }
  171. $interpreter->add_response($interaction, $answer);
  172. $interpreter->response($item);
  173. $result = $interpreter->get_outcome($outcome_id);
  174. $result = empty($result) ? 0 : $result;
  175. return $result;
  176. }
  177. public function get_scores(ImsXmlReader $item, $responses, $interpreter = null)
  178. {
  179. $result = array();
  180. $responses_id = array_keys($responses);
  181. if (empty($interpreter))
  182. {
  183. $interpreter = new QtiInterpreter();
  184. $interpreter->init($item);
  185. }
  186. if (count($interactions) == 1)
  187. {
  188. $answers = reset($responses);
  189. $response_id = reset($responses_id);
  190. foreach ($answers as $answer)
  191. {
  192. if ($this->head()->is_formula($answer))
  193. {
  194. $answer = $interpreter->execute($answer);
  195. }
  196. $interpreter->add_response($response_id, $answer);
  197. $score = $interpreter->get_outcome($score_id);
  198. $score = empty($score) ? 0 : $score;
  199. $result[$score] = $score;
  200. }
  201. return $result;
  202. }
  203. else
  204. if (count($interactions) == 2)
  205. {
  206. $answers_0 = $responses[0];
  207. $response_id_0 = $responses_id[0];
  208. $answers_1 = $responses[1];
  209. $response_id_1 = $responses_id[1];
  210. foreach ($answers_0 as $answer_0)
  211. {
  212. if ($this->head()->is_formula($answer_0))
  213. {
  214. $answer_0 = $interpreter->execute($answer_0);
  215. }
  216. $interpreter->add_response($response_id_0, $answer_0);
  217. foreach ($answers_1 as $answer_1)
  218. {
  219. if ($this->head()->is_formula($answer_1))
  220. {
  221. $answer_1 = $interpreter->execute($answer_1);
  222. }
  223. $interpreter->add_response($response_id_1, $answer_1);
  224. $score = $interpreter->get_outcome($score_id);
  225. $score = empty($score) ? 0 : $score;
  226. $result[$score] = $score;
  227. }
  228. }
  229. return $result;
  230. }
  231. else
  232. {
  233. throw new Exception('Not implemented, too many interactions: ' . count($interactions));
  234. }
  235. }
  236. public function get_minimum_score(ImsXmlReader $item)
  237. {
  238. $interpreter = new QtiInterpreter();
  239. $interpreter->execute($item);
  240. $score_id = $this->head()->get_score_outcome_declaration($item)->identifier;
  241. $result = $interpreter->get_outcome($score_id);
  242. return empty($result) ? 0 : $result;
  243. }
  244. public function get_maximum_score(ImsXmlReader $item, $interaction = null)
  245. {
  246. $score_declaration = $this->head()->get_score_outcome_declaration($item);
  247. if ($score_declaration->is_empty())
  248. {
  249. return 0;
  250. }
  251. if ($normal_maximum = $score_declaration->normalMaximum && empty($interaction))
  252. {
  253. return $normal_maximum;
  254. }
  255. else
  256. if (empty($interaction))
  257. {
  258. $answers = $this->get_maximum_score_possible_answers($item);
  259. $scores = $this->get_scores($item, $answers);
  260. return max($scores);
  261. }
  262. else
  263. {
  264. $result = 0;
  265. $responses = $this->head()->get_possible_responses($item, $interaction);
  266. foreach ($responses as $response)
  267. {
  268. $score = $this->head()->get_score($item, $interaction, $response);
  269. $result = max($score, $result);
  270. }
  271. return $result;
  272. }
  273. }
  274. protected function get_maximum_score_possible_answers(ImsXmlReader $item)
  275. {
  276. $result = array();
  277. foreach ($interactions as $interaction)
  278. {
  279. $answers = $this->head()->get_correct_responses($item, $interaction);
  280. if (empty($answers))
  281. {
  282. $answers = $this->head()->get_possible_responses($item, $interaction);
  283. }
  284. $cardinality = $this->head()->get_response_declaration($item, $interaction)->cardinality;
  285. if ($cardinality == qti :: CARDINALITY_MULTIPLE)
  286. {
  287. $answers = $this->combine($answers);
  288. }
  289. $result[$interaction->responseIdentifier] = $answers;
  290. }
  291. return $result;
  292. }
  293. public function get_score_default(ImsXmlReader $item)
  294. {
  295. $result = $this->head()->get_score_outcome_declaration($item);
  296. $result = $result->get_defaultValue();
  297. $result = $result->first_value();
  298. $result = $result->value();
  299. $result = empty($result) ? 0 : round($result);
  300. return $result;
  301. }
  302. public function get_penalty(ImsXmlReader $item, $interaction = null, $response = null)
  303. {
  304. if (empty($response))
  305. {
  306. $max_penalty = 0;
  307. $interaction = $this->head()->get_main_interaction($item);
  308. $responses = $this->head()->get_possible_responses($item, $interaction);
  309. foreach ($responses as $response)
  310. {
  311. $response_penalty = $this->get_penalty($item, $interaction, $response);
  312. $max_penalty = max(floatval($response_penalty), floatval($max_penalty));
  313. }
  314. $result = $max_penalty;
  315. }
  316. else
  317. {
  318. $interpreter = new QtiInterpreter();
  319. $interpreter->init($item);
  320. $interpreter->add_response($interaction->responseIdentifier, $response);
  321. $interpreter->response($item);
  322. $score_without_penalty = $interpreter->get_outcome(Qti :: SCORE);
  323. $interpreter = new QtiInterpreter();
  324. $interpreter->init($item);
  325. $interpreter->response($item);
  326. $interpreter->add_response($interaction->responseIdentifier, $response);
  327. $interpreter->response($item);
  328. $score_with_penalty = $interpreter->get_outcome(Qti :: SCORE);
  329. $result = abs($score_without_penalty - $score_with_penalty);
  330. }
  331. return empty($result) ? 0 : (float) $result;
  332. }
  333. //END SCORE
  334. public function get_tolerance(ImsXmlReader $item, ImsXmlReader $interaction = null, $answer = '')
  335. {
  336. if (! $interaction->is_sliderInteraction() && ! $interaction->is_textEntryInteraction() && ! ! $interaction->is_extendedTextEntryInteraction())
  337. {
  338. return false;
  339. }
  340. $interpreter = new QtiInterpreter();
  341. if ($this->head()->is_formula($answer))
  342. {
  343. $equal = $answer->get_parent();
  344. $if = $equal->get_parent();
  345. $set = $if->get_setOutcomeValue();
  346. $score_id = $this->head()->get_score_outcome_declaration($item)->identifier;
  347. if ($equal->is_equal() && $set->identifier == $score_id)
  348. {
  349. $result = max(explode(' ', $equal->tolerance));
  350. $result = empty($result) ? 0 : $result;
  351. return $result;
  352. }
  353. else
  354. {
  355. $interpreter->init($item);
  356. $answer = $interpreter->execute($answer);
  357. }
  358. }
  359. else
  360. if (empty($answer))
  361. {
  362. $answer = $this->head()->get_correct_responses($item, $interaction);
  363. $answer = reset($answer);
  364. }
  365. $outcome_base_type = $this->head()->get_response_declaration($item, $interaction)->baseType;
  366. $answer_score = $this->head()->get_score($item, $interaction, $answer, '', $interpreter);
  367. $lower_bound = $interaction->lowerBound;
  368. $upper_bound = $interaction->upperBound;
  369. $step = $interaction->step;
  370. $step = empty($step) ? ($upper_bound - $lower_bound) / 20 : $step;
  371. $step = $outcome_base_type == 'integer' ? round($step) : $step;
  372. $step = empty($step) ? 1 : $step;
  373. $value_top = $value_bottom = is_array($answer) ? reset($answer) : $answer;
  374. for($shift = $count = 0; $lower_bound <= $value_bottom && $value_top <= $upper_bound; $shift += $step, $count ++)
  375. {
  376. $value_top += $step;
  377. $value_bottom -= $step;
  378. $score_top = $this->head()->get_score($item, $interaction, $value_top);
  379. $score_bottom = $this->head()->get_score($item, $interaction, $value_bottom);
  380. if (abs($score_top - $answer_score) != 0 || abs($score_bottom - $answer_score) != 0 || $count > 50)
  381. {
  382. break;
  383. }
  384. }
  385. $result = empty($shift) ? 0 : $shift;
  386. return $result;
  387. }
  388. public function get_tolerance_type(ImsXmlReader $item, ImsXmlReader $interaction = null, $answer = '')
  389. {
  390. if (! $interaction->is_sliderInteraction() && ! $interaction->is_textEntryInteraction() && ! $interaction->is_extendedTextInteraction())
  391. {
  392. return false;
  393. }
  394. if ($this->head()->is_formula($answer))
  395. {
  396. $equal = $answer->get_parent();
  397. $if = $equal->get_parent();
  398. $set = $if->get_setOutcomeValue();
  399. $score_id = $this->head()->get_score_outcome_declaration($item)->identifier;
  400. if ($equal->is_equal() && $set->identifier == $score_id)
  401. {
  402. $result = $equal->toleranceMode;
  403. return $result;
  404. }
  405. }
  406. return false;
  407. }
  408. /**
  409. *
  410. * @param $item
  411. * @param $interaction
  412. */
  413. public function get_partial_responses(ImsXmlReader $item, ImsXmlReader $interaction)
  414. {
  415. if (! $interaction->is_sliderInteraction())
  416. {
  417. return array();
  418. }
  419. $base_type = $this->head()->get_response_declaration($item, $interaction)->baseType;
  420. $answers = $this->head()->get_correct_responses($item, $interaction);
  421. $answer = reset($answers);
  422. $answer_score = $this->head()->get_score($item, $interaction, $answer);
  423. $lower_bound = $interaction->lowerBound;
  424. $upper_bound = $interaction->upperBound;
  425. $step = $interaction->step;
  426. $step = empty($step) ? ($upper_bound - $lower_bound) / 20 : $step;
  427. $step = $base_type == 'integer' ? round($step) : $step;
  428. $step = empty($step) ? 1 : $step;
  429. $start = max($lower_bound, $answer - $step * 10);
  430. $stop = min($upper_bound, $answer + $step * 10);
  431. //$scores = array();
  432. $result = array();
  433. for($value = $start, $count = 0; $value <= $stop && $count <= 50; $value += $step, $count ++)
  434. {
  435. $score = $this->head()->get_score($item, $interaction, $value);
  436. if (abs($score - $answer_score) != 0 && $score != 0)
  437. {
  438. $result[] = $value;
  439. }
  440. }
  441. /*
  442. $result = array();
  443. $start = $stop = $current_score = false;
  444. foreach($scores as $value => $score){
  445. if($current_score === false || $current_score != $score){
  446. if($current_score !== false){
  447. $middle = ($start+$stop) / 2;
  448. $middle = $base_type == 'integer' ? round($middle) : $middle;
  449. $result[] = $middle;
  450. }
  451. $start = $stop = $value;
  452. $current_score = $core;
  453. }else{
  454. $start = min($value, $start);
  455. $end = max($value, $end);
  456. }
  457. }
  458. */
  459. return $result;
  460. }
  461. public function get_template_values(ImsXmlReader $item, $maximum = 100)
  462. {
  463. $result = array();
  464. $parameters = $item->list_templateDeclaration();
  465. foreach ($parameters as $param)
  466. {
  467. $result[$param->identifier] = array();
  468. }
  469. $interpreter = new QtiInterpreter();
  470. for($i = 0; $i < $maximum; $i ++)
  471. {
  472. $interpreter->reset();
  473. $interpreter->execute($item);
  474. foreach ($parameters as $param)
  475. {
  476. $id = $param->identifier;
  477. $value = $interpreter->get_template($id);
  478. $result[$id][$value] = $value;
  479. }
  480. }
  481. return $result;
  482. }
  483. public function get_rubricBlock(ImsXmlReader $item, $role = QTI::VIEW_ALL)
  484. {
  485. $result = array();
  486. $interpreter = new QtiInterpreter($role);
  487. $interpreter->init($item);
  488. $interpreter->execute($item);
  489. $this->get_renderer()->init($interpreter);
  490. $rubrics = $item->query('.//def:rubricBlock');
  491. foreach ($rubrics as $rubric)
  492. {
  493. $html = $this->to_html($rubric);
  494. if (! empty($html))
  495. {
  496. $result[] = $html;
  497. }
  498. }
  499. $this->get_renderer()->reset_outcomes();
  500. return $result;
  501. }
  502. public function list_outcome(ImsXmlReader $item, $include_feedback_outcome = false)
  503. {
  504. $outcomes = $item->list_outcomeDeclaration();
  505. if ($include_feedback_outcome)
  506. {
  507. return $outcomes;
  508. }
  509. $inline_feedback = $item->query('.//feedbackInline');
  510. $modal_feedback = $item->query('.//modalFeedback');
  511. $feedbacks = array_merge($modal_feedback, $inline_feedback);
  512. $result = array();
  513. foreach ($outcomes as $outcome)
  514. {
  515. $id = $outcome->identifier;
  516. $is_feedback = false;
  517. foreach ($feedbacks as $feedback)
  518. {
  519. if ($feedback->outcomeIdentifier == $id)
  520. {
  521. $is_feedback = true;
  522. break;
  523. }
  524. }
  525. if (! $is_feedback)
  526. {
  527. $result[] = $outcome;
  528. }
  529. }
  530. return $result;
  531. }
  532. /**
  533. *
  534. * @param ImsXmlReader $item
  535. * @return ImsQtiReader
  536. */
  537. public function get_score_outcome_declaration(ImsXmlReader $item)
  538. {
  539. $score = $item->get_by_id('SCORE');
  540. if (! $score->is_empty())
  541. {
  542. return $score;
  543. }
  544. $outcomes = $item->list_outcomeDeclaration();
  545. $filtered = array();
  546. foreach ($outcomes as $outcome)
  547. {
  548. $type = strtolower($outcome->baseType);
  549. if ($type == 'float' || $type == 'integer')
  550. {
  551. $filtered[] = $outcome;
  552. }
  553. }
  554. foreach ($filtered as $outcome)
  555. {
  556. $type = strtolower($outcome->baseType);
  557. if ($type == 'float')
  558. {
  559. return $outcome;
  560. }
  561. }
  562. foreach ($filtered as $outcome)
  563. {
  564. return $outcome;
  565. }
  566. return $item->get_default_result();
  567. }
  568. public function get_main_response(ImsXmlReader $item)
  569. {
  570. return $item->get_by_id(Qti :: RESPONSE);
  571. }
  572. public function get_response_declaration(ImsXmlReader $item, ImsXmlReader $interaction)
  573. {
  574. return $item->get_child_by_id($interaction->responseIdentifier);
  575. }
  576. //FORMULA
  577. /**
  578. * Returns expressions used to compare against the interaction's response for score processing.
  579. * @param $item
  580. * @param $interaction
  581. */
  582. public function get_score_formulas(ImsXmlReader $item, ImsXmlReader $interaction)
  583. {
  584. $result = array();
  585. $outcome_id = $this->head()->get_response_declaration($item, $interaction)->identifier;
  586. $score_id = $this->head()->get_score_outcome_declaration($item)->identifier;
  587. $conditions = $item->get_responseProcessing()->list_responseCondition();
  588. foreach ($conditions as $condition)
  589. {
  590. $formulas = $this->get_score_formula_from_condition($condition, $outcome_id, $score_id);
  591. $result = array_merge($result, $formulas);
  592. }
  593. return $result;
  594. }
  595. public function is_formula($item)
  596. {
  597. return $item instanceof ImsXmlReader;
  598. }
  599. public function is_formula_constant(ImsXmlReader $item)
  600. {
  601. return count($item->all_variable()) == 0;
  602. }
  603. public function execute_formula(ImsXmlReader $item, ImsXmlReader $formula)
  604. {
  605. $interpreter = new QtiInterpreter();
  606. $interpreter->init($item);
  607. $result = $interpreter->execute($formula);
  608. return $result;
  609. }
  610. protected function get_score_formula_from_condition(ImsXmlReader $condition, $outcome_id, $score_id)
  611. {
  612. $result = array();
  613. $ifs = array_merge($condition->list_responseIf(), $condition->list_responseElseIf());
  614. foreach ($ifs as $if)
  615. {
  616. if ($formula = $this->get_score_formula_from_if($if, $outcome_id, $score_id))
  617. {
  618. $result[] = $formula;
  619. }
  620. }
  621. return $result;
  622. }
  623. protected function get_score_formula_from_if(ImsXmlReader $if, $response_id, $score_id)
  624. {
  625. if (! $if->is_responseIf() && ! $if->is_responseElseIf())
  626. {
  627. return false;
  628. }
  629. if ($if->get_setOutcomeValue()->identifier != $score_id)
  630. {
  631. return false;
  632. }
  633. $response_pattern = './/def:variable[@identifier="' . $response_id . '"]';
  634. $branches = $if->children();
  635. $condition = $branches[0];
  636. $response_rule = $branches[1];
  637. if (! $condition->exist($response_pattern) || $response_rule->exist($response_pattern))
  638. {
  639. return false;
  640. }
  641. if ($condition->is_equal())
  642. {
  643. $branches = $condition->children();
  644. $has_response[0] = $branches[0]->exist($response_pattern);
  645. $has_response[1] = $branches[1]->exist($response_pattern);
  646. if (! $has_response[0] && $has_response[1])
  647. {
  648. return $branches[0];
  649. }
  650. else
  651. if ($has_response[0] && ! $has_response[1])
  652. {
  653. return $branches[1];
  654. }
  655. else
  656. {
  657. return false;
  658. }
  659. }
  660. else
  661. if ($condition->is_patternMatch() && $condition->get_patternMatch()->get_variable()->identifier == $response_id)
  662. {
  663. return $condition;
  664. }
  665. return false;
  666. }
  667. //END FORMULAS
  668. //CORRECT-INCORRECT METHODS
  669. public function get_correct_responses(ImsXmlReader $item, ImsXmlReader $interaction)
  670. {
  671. $response = $this->head()->get_response_declaration($item, $interaction);
  672. $correct_values = $response->get_correctResponse()->list_value();
  673. $result = array();
  674. foreach ($correct_values as $correct_value)
  675. {
  676. $value = $correct_value->valueof();
  677. $result[$value] = $value;
  678. }
  679. if (empty($result) && $interaction->is_choiceInteraction())
  680. {
  681. $choices = $interaction->list_simpleChoice();
  682. $answers = array();
  683. foreach ($choices as $choice)
  684. {
  685. $answer = $choice->identifier;
  686. $score = $this->head()->get_score($item, $interaction, $answer);
  687. $answers[$answer] = $score;
  688. }
  689. arsort($answers, SORT_NUMERIC);
  690. $max_choices = $interaction->maxChoices;
  691. $max_choices = empty($max_choices) ? 100000 : $max_choices;
  692. if ($max_choices == 1)
  693. {
  694. $result[] = reset($answers);
  695. }
  696. else
  697. {
  698. $response = array();
  699. $count = min($max_choices, count($answers));
  700. $i = 0;
  701. foreach ($answers as $answer => $score)
  702. {
  703. if ($i < $count)
  704. {
  705. $response[] = $answer;
  706. $i ++;
  707. }
  708. else
  709. {
  710. break;
  711. }
  712. }
  713. $result = $response;
  714. }
  715. }
  716. return $result;
  717. }
  718. public function get_possible_responses(ImsXmlReader $item, ImsXmlReader $interaction)
  719. {
  720. $result = array();
  721. if ($interaction->is_choiceInteraction())
  722. {
  723. $choices = $interaction->list_simpleChoice();
  724. foreach ($choices as $choice)
  725. {
  726. $result[] = $choice->identifier;
  727. }
  728. }
  729. if ($interaction->is_inlineChoiceInteraction())
  730. {
  731. $choices = $interaction->list_inlineChoice();
  732. foreach ($choices as $choice)
  733. {
  734. $result[] = $choice->identifier;
  735. }
  736. }
  737. if ($interaction->is_hotspotInteraction())
  738. {
  739. $choices = $interaction->list_hotspotChoice();
  740. foreach ($choices as $choice)
  741. {
  742. $result[] = $choice->identifier;
  743. }
  744. }
  745. if (empty($result))
  746. {
  747. $response = $this->head()->get_response_declaration($item, $interaction);
  748. $entries = $response->get_areaMapping()->list_areaMapEntry();
  749. foreach ($entries as $entry)
  750. {
  751. $result[] = $entry;
  752. }
  753. }
  754. if (empty($result))
  755. {
  756. $response = $this->head()->get_response_declaration($item, $interaction);
  757. $entries = $response->get_mapping()->list_mapEntry();
  758. foreach ($entries as $entry)
  759. {
  760. $result[] = $entry->mapKey;
  761. }
  762. }
  763. if (empty($result) && $interaction->is_sliderInteraction())
  764. {
  765. $base_type = $this->head()->get_response_declaration($item, $interaction)->baseType;
  766. $answers = $this->head()->get_correct_responses($item, $interaction);
  767. $answer = reset($answers);
  768. $answer_score = $this->head()->get_score($item, $interaction, $answer);
  769. $lower_bound = $interaction->lowerBound;
  770. $upper_bound = $interaction->upperBound;
  771. $step = $interaction->step;
  772. $step = empty($step) ? ($upper_bound - $lower_bound) / 20 : $step;
  773. $step = $base_type == 'integer' ? round($step) : $step;
  774. $step = empty($step) ? 1 : $step;
  775. $start = max($lower_bound, $answer - $step * 10);
  776. $stop = min($upper_bound, $answer + $step * 10);
  777. //$scores = array();
  778. $result = array();
  779. for($value = $start, $count = 0; $value <= $stop && $count <= 50; $value += $step, $count ++)
  780. {
  781. $score = $this->head()->get_score($item, $interaction, $value);
  782. if (abs($score - $answer_score) != 0 && $score != 0)
  783. {
  784. $result[] = $value;
  785. }
  786. }
  787. }
  788. //if(empty($result) && $answers = $this->head()->get_correct_responses($item, $interaction)){
  789. // $result = $answers;
  790. //}
  791. if (empty($result))
  792. {
  793. $result = $this->head()->get_score_formulas($item, $interaction);
  794. }
  795. return $result;
  796. }
  797. public function get_possible_responses_text(ImsXmlReader $item, ImsXmlReader $interaction)
  798. {
  799. $result = array();
  800. if ($interaction->is_choiceInteraction())
  801. {
  802. $choices = $interaction->list_simpleChoice();
  803. foreach ($choices as $choice)
  804. {
  805. $result[] = $choice->value();
  806. }
  807. }
  808. else
  809. {
  810. $response = $this->head()->get_response_declaration($item, $interaction);
  811. $entries = $response->get_mapping()->list_mapEntry();
  812. foreach ($entries as $entry)
  813. {
  814. $result[] = $entry->mapKey;
  815. }
  816. }
  817. return $result;
  818. }
  819. protected function get_incorrect_response(ImsXmlReader $item, $interaction)
  820. {
  821. $correct_responses = $this->head()->get_correct_responses($item, $interaction);
  822. $base_type = $this->head()->get_response_declaration($item, $interaction)->baseType;
  823. $count = 0;
  824. $answer = $this->random_value($base_type);
  825. while ($this->head()->get_score($item, $interaction, $answer) != 0 && $count < 50)
  826. {
  827. $answer = $this->random_value($base_type, ++ $count);
  828. }
  829. return $count < 50 ? $answer : null;
  830. }
  831. //END CORRECT-INCORRECT METHODS
  832. }