21require_once
'./Modules/Test/classes/inc.AssessmentConstants.php';
134 $this->start_tag =
"[gap]";
135 $this->end_tag =
"[/gap]";
138 $this->fixedTextLength =
"";
139 $this->identical_scoring = 1;
140 $this->gap_combinations_exists =
false;
141 $this->gap_combinations = [];
142 $this->randomGroup =
$DIC->refinery()->random();
172 $text = str_replace(
'$',
'GAPMASKEDDOLLAR', $text);
173 $text = preg_replace(
"/\[gap[^\]]*?\]/",
"[gap]", $text);
174 $text = preg_replace(
"/<gap([^>]*?)>/",
"[gap]", $text);
175 $text = str_replace(
"</gap>",
"[/gap]", $text);
176 $text = str_replace(
'GAPMASKEDDOLLAR',
'$', $text);
190 $content = str_replace(
'$',
'GAPMASKEDDOLLAR', $content);
191 $output = preg_replace(
"/\[gap\].*?\[\/gap\]/", $content, $gaptext, 1);
192 $output = str_replace(
'GAPMASKEDDOLLAR',
'$', $output);
207 $result =
$ilDB->queryF(
212 if ($result->numRows() == 1) {
214 $this->
setId($question_id);
218 $this->
setComment((
string) $data[
"description"]);
236 include_once(
"./Services/RTE/classes/class.ilRTE.php");
247 include_once
"./Modules/TestQuestionPool/classes/class.assAnswerCloze.php";
248 include_once
"./Modules/TestQuestionPool/classes/class.assClozeGap.php";
249 $result =
$ilDB->queryF(
250 "SELECT * FROM qpl_a_cloze WHERE question_fi = %s ORDER BY gap_id, aorder ASC",
254 if ($result->numRows() > 0) {
257 switch (
$data[
"cloze_type"]) {
259 if (!array_key_exists(
$data[
"gap_id"], $this->gaps)) {
267 $this->gaps[
$data[
"gap_id"]]->setGapSize((
int)
$data[
'gap_size']);
269 $this->gaps[
$data[
"gap_id"]]->addItem($answer);
272 if (!array_key_exists(
$data[
"gap_id"], $this->gaps)) {
274 $this->gaps[
$data[
"gap_id"]]->setShuffle(
$data[
"shuffle"]);
281 $this->gaps[
$data[
"gap_id"]]->addItem($answer);
284 if (!array_key_exists(
$data[
"gap_id"], $this->gaps)) {
292 $this->gaps[
$data[
"gap_id"]]->setGapSize((
int)
$data[
'gap_size']);
293 $answer->setLowerBound(
$data[
"lowerlimit"]);
294 $answer->setUpperBound(
$data[
"upperlimit"]);
295 $this->gaps[
$data[
"gap_id"]]->addItem($answer);
302 $check_for_gap_combinations = $assClozeGapCombinationObj->loadFromDb($question_id);
303 if (count($check_for_gap_combinations) != 0) {
307 parent::loadFromDb($question_id);
310 #region Save question to db
343 "DELETE FROM qpl_a_cloze WHERE question_fi = %s",
345 array( $this->
getId() )
348 foreach ($this->gaps as
$key => $gap) {
363 $DIC->database()->manipulateF(
366 array( $this->
getId() )
370 'question_fi' => array(
'integer', $this->
getId()),
389 foreach ($gap->getItems($this->getShuffler()) as $item) {
391 $next_id =
$ilDB->nextId(
'qpl_a_cloze');
392 switch ($gap->getType()) {
419 "INSERT INTO qpl_a_cloze (answer_id, question_fi, gap_id, answertext, points, aorder, cloze_type, gap_size) VALUES (%s, %s, %s, %s, %s, %s, %s, %s)",
434 strlen($item->getAnswertext()) ? $item->getAnswertext() :
"",
438 (
int) $gap->getGapSize()
456 "INSERT INTO qpl_a_cloze (answer_id, question_fi, gap_id, answertext, points, aorder, cloze_type, shuffle) VALUES (%s, %s, %s, %s, %s, %s, %s, %s)",
471 strlen($item->getAnswertext()) ? $item->getAnswertext() :
"",
475 ($gap->getShuffle()) ?
"1" :
"0"
493 include_once
"./Services/Math/classes/class.EvalMath.php";
495 $eval->suppress_errors =
true;
497 "INSERT INTO qpl_a_cloze (answer_id, question_fi, gap_id, answertext, points, aorder, cloze_type, lowerlimit, upperlimit, gap_size) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s)",
514 strlen($item->getAnswertext()) ? $item->getAnswertext() :
"",
518 ($eval->e($item->getLowerBound() !==
false) && strlen(
519 $item->getLowerBound()
520 ) > 0) ? $item->getLowerBound() : $item->getAnswertext(),
521 ($eval->e($item->getUpperBound() !==
false) && strlen(
522 $item->getUpperBound()
523 ) > 0) ? $item->getUpperBound() : $item->getAnswertext(),
524 (
int) $gap->getGapSize()
531 #endregion Save question to db
596 preg_match_all(
'/\[gap\].*?\[\/gap\]/', $this->
getClozeText(), $gaps);
597 $string_with_replaced_gaps = str_replace(
$gaps[0],
'######GAP######', $this->
getClozeText());
599 $string_with_replaced_gaps
601 $cleaned_text_with_gaps = preg_replace_callback(
'/######GAP######/',
function ($match) use (&
$gaps) {
602 return array_shift(
$gaps[0]);
606 || !(
new ilSetting(
'advanced_editing'))->
get(
'advanced_editing_javascript_editor') ===
'tinymce') {
607 $cleaned_text_with_gaps = nl2br($cleaned_text_with_gaps);
685 include_once
"./Modules/TestQuestionPool/classes/class.assClozeGap.php";
686 include_once
"./Modules/TestQuestionPool/classes/class.assAnswerCloze.php";
687 $search_pattern =
"|\[gap\](.*?)\[/gap\]|i";
688 preg_match_all($search_pattern, $this->
getClozeText(), $found);
690 if (count($found[0])) {
691 foreach ($found[1] as $gap_index => $answers) {
694 $textparams = preg_split(
"/(?<!\\\\),/", $answers);
695 foreach ($textparams as
$key => $value) {
697 $gap->addItem($answer);
699 $this->gaps[$gap_index] = $gap;
711 if (array_key_exists($gap_index, $this->gaps)) {
712 $this->gaps[$gap_index]->setType($gap_type);
727 if (array_key_exists($gap_index, $this->gaps)) {
728 $this->gaps[$gap_index]->setShuffle(
$shuffle);
740 foreach ($this->gaps as $gap_index => $gap) {
741 $this->gaps[$gap_index]->clearItems();
754 if (is_array($this->gaps)) {
755 return count($this->gaps);
773 if (array_key_exists($gap_index, $this->gaps)) {
776 $answer = str_replace(
",",
".", $answer);
778 $this->gaps[$gap_index]->addItem(
new assAnswerCloze(trim($answer), 0, $order));
790 if (array_key_exists($gap_index, $this->gaps)) {
791 return $this->gaps[$gap_index];
799 if (array_key_exists($gap_index, $this->gaps)) {
800 $this->gaps[$gap_index]->setGapSize((
int) $size);
816 if (array_key_exists($gap_index, $this->gaps)) {
817 $this->gaps[$gap_index]->setItemPoints($order,
$points);
831 if (array_key_exists($gap_index, $this->gaps)) {
832 include_once
"./Modules/TestQuestionPool/classes/class.assAnswerCloze.php";
836 $this->gaps[$gap_index]->getItemCount()
838 $this->gaps[$gap_index]->addItem($answer);
852 $this->gaps[
$index] = $gap;
867 if (array_key_exists($gap_index, $this->gaps)) {
868 $this->gaps[$gap_index]->setItemLowerBound($order, $bound);
884 if (array_key_exists($gap_index, $this->gaps)) {
885 $this->gaps[$gap_index]->setItemUpperBound($order, $bound);
899 $gaps_used_in_combination = [];
900 if ($assClozeGapCombinationObj->combinationExistsForQid($this->getId())) {
901 $points = $assClozeGapCombinationObj->getMaxPointsForCombination($this->
getId());
902 $gaps_used_in_combination = $assClozeGapCombinationObj->getGapsWhichAreUsedInCombination($this->
getId());
904 foreach ($this->gaps as $gap_index => $gap) {
905 if (!array_key_exists($gap_index, $gaps_used_in_combination)) {
908 foreach ($gap->getItems($this->getShuffler()) as $item) {
909 if ($item->getPoints() > $gap_max_points) {
910 $gap_max_points = $item->getPoints();
916 foreach ($gap->getItems($this->getShuffler()) as $item) {
917 if ($item->getPoints() > $srpoints) {
918 $srpoints = $item->getPoints();
924 foreach ($gap->getItems($this->getShuffler()) as $item) {
925 if ($item->getPoints() > $numpoints) {
926 $numpoints = $item->getPoints();
944 if ($this->
id <= 0) {
949 $this_id = $this->
getId();
953 include_once(
"./Modules/TestQuestionPool/classes/class.assQuestion.php");
957 if ((
int) $testObjId > 0) {
958 $clone->setObjId($testObjId);
975 if ($this->gap_combinations_exists) {
984 $clone->copyPageOfQuestion($this_id);
986 $clone->copyXHTMLMediaObjectsOfQuestion($this_id);
988 $clone->onDuplicate($thisObjId, $this_id, $clone->getObjId(), $clone->getId());
990 return $clone->getId();
1000 if ($this->
getId() <= 0) {
1001 throw new RuntimeException(
'The question has not been saved. It cannot be duplicated');
1004 $thisId = $this->
getId();
1008 include_once(
"./Modules/TestQuestionPool/classes/class.assQuestion.php");
1011 $clone->setObjId($target_questionpool_id);
1013 $clone->setTitle(
$title);
1018 if ($this->gap_combinations_exists) {
1028 $clone->onCopy($thisObjId, $thisId, $clone->getObjId(), $clone->getId());
1030 return $clone->getId();
1035 if ($this->
getId() <= 0) {
1036 throw new RuntimeException(
'The question has not been saved. It cannot be duplicated');
1039 include_once(
"./Modules/TestQuestionPool/classes/class.assQuestion.php");
1042 $sourceParentId = $this->
getObjId();
1048 $clone->setObjId($targetParentId);
1050 if ($targetQuestionTitle) {
1051 $clone->setTitle($targetQuestionTitle);
1056 if ($this->gap_combinations_exists) {
1061 $clone->copyPageOfQuestion($sourceQuestionId);
1063 $clone->copyXHTMLMediaObjectsOfQuestion($sourceQuestionId);
1065 $clone->onCopy($sourceParentId, $sourceQuestionId, $clone->getObjId(), $clone->getId());
1073 $array = $assClozeGapCombinationObj->loadFromDb($orgID);
1074 $assClozeGapCombinationObj->importGapCombinationToDb($newID, $array);
1085 foreach ($this->
getGaps() as $gap_index => $gap) {
1087 foreach ($gap->getItemsRaw() as $item) {
1088 array_push($answers, str_replace([
',',
'['], [
"\\,",
'[ '], $item->getAnswerText()));
1094 $output = str_replace(
"_gap]",
"gap]", $output);
1095 $this->cloze_text = $output;
1109 if (array_key_exists($gap_index, $this->gaps)) {
1110 if ($this->gaps[$gap_index]->getItemCount() == 1) {
1115 $this->gaps[$gap_index]->deleteItem($answer_index);
1131 if (array_key_exists($gap_index, $this->gaps)) {
1133 foreach ($this->
getGaps() as $replace_gap_index => $gap) {
1135 foreach ($gap->getItemsRaw() as $item) {
1136 array_push($answers, str_replace(
",",
"\\,", $item->getAnswerText()));
1138 if ($replace_gap_index == $gap_index) {
1144 $output = $this->
replaceFirstGap($output,
"[_gap]" . join(
",", $answers) .
"[/_gap]");
1148 $output = str_replace(
"_gap]",
"gap]", $output);
1149 $this->cloze_text = $output;
1150 unset($this->gaps[$gap_index]);
1151 $this->gaps = array_values($this->gaps);
1166 include_once
"./Services/Utilities/classes/class.ilStr.php";
1172 switch ($gaprating) {
1175 $result = $max_points;
1179 if (strcmp($a_original, $a_entered) == 0) {
1180 $result = $max_points;
1184 $transformation =
$refinery->string()->levenshtein()->standard($a_original, 1);
1187 $transformation =
$refinery->string()->levenshtein()->standard($a_original, 2);
1190 $transformation =
$refinery->string()->levenshtein()->standard($a_original, 3);
1193 $transformation =
$refinery->string()->levenshtein()->standard($a_original, 4);
1196 $transformation =
$refinery->string()->levenshtein()->standard($a_original, 5);
1201 if (isset($transformation) && $transformation->transform($a_entered) >= 0) {
1202 $result = $max_points;
1219 include_once
"./Services/Math/classes/class.EvalMath.php";
1221 $eval->suppress_errors =
true;
1224 if ($eval->e($a_entered) ===
false) {
1226 } elseif (($eval->e($lowerBound) !==
false) && ($eval->e($upperBound) !==
false)) {
1227 if (($eval->e($a_entered) >= $eval->e($lowerBound)) && ($eval->e($a_entered) <= $eval->e($upperBound))) {
1228 $result = $max_points;
1230 } elseif ($eval->e($lowerBound) !==
false) {
1231 if (($eval->e($a_entered) >= $eval->e($lowerBound)) && ($eval->e($a_entered) <= $eval->e($a_original))) {
1232 $result = $max_points;
1234 } elseif ($eval->e($upperBound) !==
false) {
1235 if (($eval->e($a_entered) >= $eval->e($a_original)) && ($eval->e($a_entered) <= $eval->e($upperBound))) {
1236 $result = $max_points;
1238 } elseif ($eval->e($a_entered) == $eval->e($a_original)) {
1239 $result = $max_points;
1250 return preg_match(
"/^-?(\\d*)(,|\\.|\\/){0,1}(\\d*)$/", $value, $matches);
1265 if (is_null($pass)) {
1272 if (strcmp(
$data[
"value2"],
"") != 0) {
1273 $user_result[
$data[
"value1"]] = array(
1274 "gap_id" =>
$data[
"value1"],
1275 "value" =>
$data[
"value2"]
1280 ksort($user_result);
1282 if ($returndetails) {
1293 if (is_numeric($submittedValue)) {
1297 if (preg_match(
'/^[-+]{0,1}\d+\/\d+$/', $submittedValue)) {
1307 $gap = $this->
getGap($gapIndex);
1314 $this->tpl->setOnScreenMessage(
'failure', $this->
lng->txt(
"err_no_numeric_value"),
true);
1324 $solutionSubmit = [];
1325 $post_wrapper = $this->dic->http()->wrapper()->post();
1327 if (!$post_wrapper->has(
"gap_$index")) {
1330 $value = trim($post_wrapper->retrieve(
1332 $this->dic->refinery()->kindlyTo()->string()
1334 if ($value ===
'') {
1338 if (!(($gap->getType() === (
int)
CLOZE_SELECT) && ($value === -1))) {
1341 && !is_numeric(str_replace(
",",
".", $value))
1345 $value = str_replace(
",",
".", $value);
1347 $solutionSubmit[
$index] = $value;
1351 return $solutionSubmit;
1357 $solutionSubmit = [];
1359 foreach ($submit as
$key => $value) {
1360 if (preg_match(
"/^gap_(\d+)/",
$key, $matches)) {
1361 if ($value !==
null && $value !==
'') {
1362 $gap = $this->
getGap($matches[1]);
1363 if (is_object($gap)) {
1364 if (!(($gap->getType() ==
CLOZE_SELECT) && ($value == -1))) {
1366 $value = str_replace(
",",
".", $value);
1368 $solutionSubmit[trim($matches[1])] = $value;
1375 return $solutionSubmit;
1393 if (is_null($pass)) {
1394 include_once
"./Modules/Test/classes/class.ilObjTest.php";
1398 $entered_values = 0;
1400 $this->
getProcessLocker()->executeUserSolutionUpdateLockOperation(
function () use (&$entered_values, $active_id, $pass, $authorized) {
1404 if ($value !==
null && $value !==
'') {
1406 if (is_object($gap)) {
1407 if (!(($gap->getType() ==
CLOZE_SELECT) && ($value == -1))) {
1416 if ($entered_values) {
1417 include_once(
"./Modules/Test/classes/class.ilObjAssessmentFolder.php");
1421 "log_user_entered_values",
1423 ), $active_id, $this->getId());
1426 include_once(
"./Modules/Test/classes/class.ilObjAssessmentFolder.php");
1430 "log_user_not_entered_values",
1432 ), $active_id, $this->getId());
1447 return "assClozeTest";
1471 switch ($a_textgap_rating) {
1479 $this->textgap_rating = $a_textgap_rating;
1496 return ($this->identical_scoring) ? 1 : 0;
1508 $this->identical_scoring = ($a_identical_scoring) ? 1 : 0;
1519 return "qpl_qst_cloze";
1524 return array(
"qpl_a_cloze",
'qpl_a_cloze_combi_res');
1535 $this->fixedTextLength = $a_text_len;
1560 $gap_max_points = 0;
1561 if (array_key_exists($gap_index, $this->gaps)) {
1562 $gap = &$this->gaps[$gap_index];
1563 foreach ($gap->getItems($this->getShuffler()) as $answer) {
1564 if ($answer->getPoints() > $gap_max_points) {
1565 $gap_max_points = $answer->getPoints();
1579 return parent::getRTETextWithMediaObjects() . $this->
getClozeText();
1593 $this->gap_combinations_exists = $value;
1598 $this->gap_combinations = $value;
1606 parent::setExportDetailsXLS($worksheet, $startrow, $active_id, $pass);
1610 foreach ($this->
getGaps() as $gap_index => $gap) {
1611 $worksheet->
setCell($startrow +
$i, 0, $this->
lng->txt(
"gap") .
" $i");
1614 foreach ($solution as $solutionvalue) {
1615 if ($gap_index == $solutionvalue[
"value1"]) {
1620 switch ($gap->getType()) {
1622 $worksheet->
setCell($startrow +
$i, 2, $gap->getItem($solutionvalue[
"value2"])->getAnswertext());
1626 $worksheet->
setCell($startrow +
$i, 2, $solutionvalue[
"value2"]);
1637 return $startrow +
$i + 1;
1656 include_once(
"./Services/RTE/classes/class.ilRTE.php");
1658 $result[
'id'] = $this->
getId();
1665 $result[
'feedback'] = array(
1666 'onenotcorrect' => $this->
formatSAQuestion($this->feedbackOBJ->getGenericFeedbackTestPresentation($this->getId(),
false)),
1667 'allcorrect' => $this->formatSAQuestion($this->feedbackOBJ->getGenericFeedbackTestPresentation($this->getId(),
true))
1673 foreach ($gap->getItems($this->getShuffler()) as $item) {
1675 $jitem[
'points'] = $item->getPoints();
1677 $jitem[
'order'] = $item->getOrder();
1679 $jitem[
'lowerbound'] = $item->getLowerBound();
1680 $jitem[
'upperbound'] = $item->getUpperBound();
1682 $jitem[
'value'] = trim($jitem[
'value']);
1684 array_push($items, $jitem);
1688 $jgap[
'size'] = $gap->getGapSize();
1691 $jgap[
'shuffle'] = $gap->getShuffle();
1692 $jgap[
'type'] = $gap->getType();
1693 $jgap[
'item'] = $items;
1695 array_push(
$gaps, $jgap);
1697 $result[
'gaps'] =
$gaps;
1699 $result[
'mobs'] =
$mobs;
1700 return json_encode($result);
1748 if ($maxStep !==
null) {
1751 SELECT sol.value1+1 as val, sol.value2, cloze.cloze_type
1752 FROM tst_solutions sol
1753 INNER JOIN qpl_a_cloze cloze ON cloze.gap_id = value1 AND cloze.question_fi = sol.question_fi
1754 WHERE sol.active_fi = %s AND sol.pass = %s AND sol.question_fi = %s AND sol.step = %s
1755 GROUP BY sol.solution_id, sol.value1+1, sol.value2, cloze.cloze_type
1757 array(
"integer",
"integer",
"integer",
"integer"),
1758 array($active_id, $pass, $this->
getId(), $maxStep)
1763 SELECT sol.value1+1 as val, sol.value2, cloze.cloze_type
1764 FROM tst_solutions sol
1765 INNER JOIN qpl_a_cloze cloze ON cloze.gap_id = value1 AND cloze.question_fi = sol.question_fi
1766 WHERE sol.active_fi = %s AND sol.pass = %s AND sol.question_fi = %s
1767 GROUP BY sol.solution_id, sol.value1+1, sol.value2, cloze.cloze_type
1769 array(
"integer",
"integer",
"integer"),
1770 array($active_id, $pass, $this->
getId())
1775 if ($row[
"cloze_type"] == 1) {
1778 $result->addKeyValue($row[
"val"], $row[
"value2"]);
1784 $result->setReachedPercentage((
$points / $max_points) * 100);
1811 $gap_used_in_combination = [];
1812 if ($assClozeGapCombinationObj->combinationExistsForQid($this->getId())) {
1813 $combinations_for_question = $assClozeGapCombinationObj->getCleanCombinationArray($this->
getId());
1816 foreach ($user_result as $user_result_build_list) {
1817 if (is_array($user_result_build_list)) {
1818 $gap_answers[$user_result_build_list[
'gap_id']] = $user_result_build_list[
'value'];
1822 foreach ($combinations_for_question as $combination) {
1823 foreach ($combination as $row_key => $row_answers) {
1824 $combination_fulfilled =
true;
1825 $points_for_combination = $row_answers[
'points'];
1826 foreach ($row_answers as $gap_key => $combination_gap_answer) {
1827 if ($gap_key !==
'points') {
1828 $gap_used_in_combination[$gap_key] = $gap_key;
1830 if ($combination_fulfilled && array_key_exists($gap_key, $gap_answers)) {
1831 switch ($combination_gap_answer[
'type']) {
1833 $is_text_gap_correct = $this->
getTextgapPoints($gap_answers[$gap_key], $combination_gap_answer[
'answer'], 1);
1834 if ($is_text_gap_correct != 1) {
1835 $combination_fulfilled =
false;
1839 $answer = $this->gaps[$gap_key]->getItem($gap_answers[$gap_key]);
1841 if ($answer !==
null) {
1842 $answertext = $answer->getAnswertext();
1845 if ($answertext != $combination_gap_answer[
'answer']) {
1846 $combination_fulfilled =
false;
1850 $answer = $this->gaps[$gap_key]->getItem(0);
1851 if ($combination_gap_answer[
'answer'] !=
'out_of_bound') {
1852 $is_numeric_gap_correct = $this->
getNumericgapPoints($answer->getAnswertext(), $gap_answers[$gap_key], 1, $answer->getLowerBound(), $answer->getUpperBound());
1853 if ($is_numeric_gap_correct != 1) {
1854 $combination_fulfilled =
false;
1857 $wrong_is_the_new_right = $this->
getNumericgapPoints($answer->getAnswertext(), $gap_answers[$gap_key], 1, $answer->getLowerBound(), $answer->getUpperBound());
1858 if ($wrong_is_the_new_right == 1) {
1859 $combination_fulfilled =
false;
1865 if ($gap_key !==
'points') {
1866 $combination_fulfilled =
false;
1870 if ($combination_fulfilled) {
1871 $points += $points_for_combination;
1876 return array(
$points, $gap_used_in_combination);
1884 if ($detailed ===
null) {
1891 $combinations[1] = [];
1892 if ($assClozeGapCombinationObj->combinationExistsForQid($this->getId())) {
1897 $solution_values_text = [];
1898 $solution_values_select = [];
1899 $solution_values_numeric = [];
1900 foreach ($user_result as $gap_id => $value) {
1901 if (is_string($value)) {
1902 $value = array(
"value" => $value);
1905 if (array_key_exists($gap_id, $this->gaps) && !array_key_exists($gap_id, $combinations[1])) {
1906 switch ($this->gaps[$gap_id]->getType()) {
1909 for ($order = 0; $order < $this->gaps[$gap_id]->getItemCount(); $order++) {
1910 $answer = $this->gaps[$gap_id]->getItem($order);
1911 $gotpoints = $this->
getTextgapPoints($answer->getAnswertext(), $value[
"value"], $answer->getPoints());
1912 if ($gotpoints > $gappoints) {
1913 $gappoints = $gotpoints;
1918 if ((in_array($value[
"value"], $solution_values_text)) && ($gappoints > 0)) {
1923 $detailed[$gap_id] = array(
"points" => $gappoints,
"best" => ($this->
getMaximumGapPoints($gap_id) == $gappoints) ?
true :
false,
"positive" => ($gappoints > 0) ?
true :
false);
1924 array_push($solution_values_text, $value[
"value"]);
1928 for ($order = 0; $order < $this->gaps[$gap_id]->getItemCount(); $order++) {
1929 $answer = $this->gaps[$gap_id]->getItem($order);
1930 $gotpoints = $this->
getNumericgapPoints($answer->getAnswertext(), $value[
"value"], $answer->getPoints(), $answer->getLowerBound(), $answer->getUpperBound());
1931 if ($gotpoints > $gappoints) {
1932 $gappoints = $gotpoints;
1937 include_once
"./Services/Math/classes/class.EvalMath.php";
1939 $eval->suppress_errors =
true;
1940 $found_value =
false;
1941 foreach ($solution_values_numeric as $solval) {
1942 if ($eval->e($solval) == $eval->e($value[
"value"])) {
1943 $found_value =
true;
1946 if ($found_value && ($gappoints > 0)) {
1951 $detailed[$gap_id] = array(
"points" => $gappoints,
"best" => ($this->
getMaximumGapPoints($gap_id) == $gappoints) ?
true :
false,
"positive" => ($gappoints > 0) ?
true :
false);
1952 array_push($solution_values_numeric, $value[
"value"]);
1955 if ($value[
"value"] >= 0) {
1956 for ($order = 0; $order < $this->gaps[$gap_id]->getItemCount(); $order++) {
1957 $answer = $this->gaps[$gap_id]->getItem($order);
1958 if ($value[
"value"] == $answer->getOrder()) {
1959 $answerpoints = $answer->getPoints();
1962 if ((in_array($answer->getAnswertext(), $solution_values_select)) && ($answerpoints > 0)) {
1967 $detailed[$gap_id] = array(
"points" => $answerpoints,
"best" => ($this->
getMaximumGapPoints($gap_id) == $answerpoints) ?
true :
false,
"positive" => ($answerpoints > 0) ?
true :
false);
1968 array_push($solution_values_select, $answer->getAnswertext());
1984 if (!is_array($participant_session)) {
1988 $user_solution = [];
1990 foreach ($participant_session as
$key => $val) {
1991 $user_solution[
$key] = array(
'gap_id' =>
$key,
'value' => $val);
2004 foreach ($userSolution as $value1 => $value2) {
2005 if ($value1 == $gapIndex) {
2006 $answerValue = $value2;
2011 return $answerValue;
2016 $gap = $this->
getGap($qIndex);
2022 foreach ($gap->getItems($this->randomGroup->dontShuffle()) as $item) {
2023 if ($item->getAnswertext() === $answerOptionValue) {
2033 $gap = $this->
getGap($qIndex);
2036 $item->setOrder($gap->getItemCount());
2038 $gap->addItem($item);
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
Class for cloze question gaps.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
clearGapAnswers()
Removes all answers from the gaps.
getEndTag()
Returns the end tag of a cloze gap.
addGapAnswer($gap_index, $order, $answer)
Sets the answer text of a gap with a given index.
calculateReachedPoints($active_id, $pass=null, $authorizedSolution=true, $returndetails=false)
Returns the points, a learner has reached answering the question.
isComplete()
Returns TRUE, if a cloze test is complete for use.
setGapShuffle($gap_index=0, $shuffle=1)
Sets the shuffle state of a gap with a given index.
setGapSize($gap_index, $size)
getClozeText()
Returns the cloze text.
getTextgapPoints($a_original, $a_entered, $max_points)
Returns the points for a text gap and compares the given solution with the entered solution using the...
isValidNumericSubmitValue($submittedValue)
setGapAnswerPoints($gap_index, $order, $points)
Sets the points of a gap with a given index and an answer with a given order.
getMaximumPoints()
Returns the maximum points, a learner can reach answering the question.
setFeedbackMode($feedbackMode)
copyObject($target_questionpool_id, $title="")
Copies an assClozeTest object.
setClozeTextValue($cloze_text="")
getAvailableAnswerOptions($index=null)
If index is null, the function returns an array with all anwser options Else it returns the specific ...
getRTETextWithMediaObjects()
Collects all text in the question which could contain media objects which were created with the Rich ...
addGapAtIndex($gap, $index)
Adds a ClozeGap object at a given index.
setTextgapRating($a_textgap_rating)
Sets the rating option for text gaps.
getAdditionalTableName()
Returns the name of the additional question data table in the database.
getSolutionSubmitValidation()
setGapAnswerUpperBound($gap_index, $order, $bound)
Sets the upper bound of a gap with a given index and an answer with a given order.
createGapsFromQuestiontext()
Create gap entries by parsing the question text.
setGapCombinations($value)
createNewOriginalFromThisDuplicate($targetParentId, $targetQuestionTitle="")
addAnswerOptionValue(int $qIndex, string $answerOptionValue, float $points)
saveWorkingData($active_id, $pass=null, $authorized=true)
Saves the learners input of the question to the database.
updateClozeTextFromGaps()
Updates the gap parameters in the cloze text from the form input.
flushGaps()
Deletes all gaps without changing the cloze text.
getStartTag()
Returns the start tag of a cloze gap.
saveAnswerSpecificDataToDb()
Save all gaps to the database.
getFixedTextLength()
Gets the fixed text length for all text fields in the cloze question.
ilAssQuestionFeedback $feedbackOBJ
addGapText($gap_index)
Adds a new answer text value to a text gap with a given index.
setIdenticalScoring($a_identical_scoring)
Sets the identical scoring option for cloze questions.
calculateReachedPointsFromPreviewSession(ilAssQuestionPreviewSession $preview_session)
saveToDb($original_id="")
Saves a assClozeTest object to a database.
getGaps()
Returns the array of gaps.
getOperators($expression)
Get all available operations for a specific question.
__construct( $title="", $comment="", $author="", $owner=-1, $question="")
assClozeTest constructor
setExportDetailsXLS(ilAssExcelFormatHelper $worksheet, int $startrow, int $active_id, int $pass)
{}
getQuestionType()
Returns the question type of the question.
checkForValidFormula($value)
getTextgapRating()
Returns the rating option for text gaps.
deleteGap($gap_index)
Deletes a gap with a given index.
getGap($gap_index=0)
Returns the gap at a given index.
setGapType($gap_index, $gap_type)
Set the type of a gap with a given index.
copyGapCombination($orgID, $newID)
calculateReachedPointsForSolution($user_result, &$detailed=null)
getGapCombinationsExists()
getExpressionTypes()
Get all available expression types for a specific question.
saveClozeTextGapRecordToDb($next_id, $key, $item, $gap)
Saves a gap-item record.
getGapCount()
Returns the number of gaps.
setGapCombinationsExists($value)
saveClozeGapItemsToDb($gap, $key)
Save all items belonging to one cloze gap to the db.
setGapAnswerLowerBound($gap_index, $order, $bound)
Sets the lower bound of a gap with a given index and an answer with a given order.
setEndTag($end_tag="[/gap]")
Sets the end tag of a cloze gap.
fetchAnswerValueForGap($userSolution, $gapIndex)
getMaximumGapPoints($gap_index)
Returns the maximum points for a gap.
lmMigrateQuestionTypeSpecificContent(ilAssSelfAssessmentMigrator $migrator)
saveAdditionalQuestionDataToDb()
Saves the data for the additional data table.
deleteAnswerText($gap_index, $answer_index)
Deletes the answer text of a gap with a given index and an answer with a given order.
saveClozeSelectGapRecordToDb($next_id, $key, $item, $gap)
Saves a gap-item record.
fetchSolutionSubmit($submit)
duplicate(bool $for_test=true, string $title="", string $author="", string $owner="", $testObjId=null)
Duplicates an assClozeTest.
toJSON()
Returns a JSON representation of the question.
loadFromDb($question_id)
Loads a assClozeTest object from a database.
isAddableAnswerOptionValue(int $qIndex, string $answerOptionValue)
setFixedTextLength($a_text_len)
Sets a fixed text length for all text fields in the cloze question.
calculateCombinationResult($user_result)
setClozeText($cloze_text="")
Evaluates the text gap solutions from the cloze text.
saveClozeNumericGapRecordToDb($next_id, $key, $item, $gap)
Saves a gap-item record.
replaceFirstGap($gaptext, $content)
Replace the first gap in a string without treating backreferences.
setStartTag($start_tag="[gap]")
Sets the start tag of a cloze gap.
getNumericgapPoints($a_original, $a_entered, $max_points, $lowerBound, $upperBound)
Returns the points for a text gap and compares the given solution with the entered solution using the...
cleanQuestiontext($text)
Cleans cloze question text to remove attributes or tags from older ILIAS versions.
getIdenticalScoring()
Returns the identical scoring status of the question.
getClozeTextForHTMLOutput()
Returns the cloze text as HTML (with optional nl2br) Fix for Mantis 29987: We assume Tiny embeds any ...
Abstract basic class which is to be extended by the concrete assessment question type classes.
float $points
The maximum available points for the question.
setOriginalId(?int $original_id)
string $question
The question text.
static logAction(string $logtext, int $active_id, int $question_id)
prepareTextareaOutput(string $txt_output, bool $prepare_for_latex_output=false, bool $omitNl2BrWhenTextArea=false)
getHtmlQuestionContentPurifier()
setAdditionalContentEditingMode(?string $additionalContentEditingMode)
saveCurrentSolution(int $active_id, int $pass, $value1, $value2, bool $authorized=true, $tstamp=0)
getSolutionValues($active_id, $pass=null, bool $authorized=true)
Loads solutions of a given user from the database an returns it.
deductHintPointsFromReachedPoints(ilAssQuestionPreviewSession $previewSession, $reachedPoints)
ILIAS Refinery Factory $refinery
setQuestion(string $question="")
getCurrentSolutionResultSet(int $active_id, int $pass, bool $authorized=true)
static _getOriginalId(int $question_id)
saveQuestionDataToDb(int $original_id=-1)
setAuthor(string $author="")
bool $shuffle
Indicates whether the answers will be shuffled or not.
setComment(string $comment="")
getSolutionMaxPass(int $active_id)
setNrOfTries(int $a_nr_of_tries)
setLifecycle(ilAssQuestionLifecycle $lifecycle)
isAdditionalContentEditingModePageObject()
setTitle(string $title="")
removeCurrentSolution(int $active_id, int $pass, bool $authorized=true)
lookupMaxStep(int $active_id, int $pass)
ensureNonNegativePoints($points)
const FB_MODE_GAP_QUESTION
constants for different feedback modes (per gap or per gap-answers/options)
static getDraftInstance()
static getInstance($identifier)
getParticipantsSolution()
setBold(string $a_coords)
Set cell(s) to bold.
getColumnCoord(int $a_col)
Get column "name" from number.
static _enabledAssessmentLogging()
static _getPass($active_id)
Retrieves the actual pass of a given user for a given test.
static getOperatorsByExpression($expression)
static _replaceMediaObjectImageSrc(string $a_text, int $a_direction=0, string $nic='')
Replaces image source from mob image urls with the mob id or replaces mob id with the correct image s...
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static strToLower(string $a_string)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static stripSlashes(string $a_str, bool $a_strip_html=true, string $a_allow="")
const TEXTGAP_RATING_LEVENSHTEIN5
const TEXTGAP_RATING_LEVENSHTEIN4
const TEXTGAP_RATING_LEVENSHTEIN3
const TEXTGAP_RATING_CASESENSITIVE
const TEXTGAP_RATING_LEVENSHTEIN2
const TEXTGAP_RATING_CASEINSENSITIVE
const TEXTGAP_RATING_LEVENSHTEIN1
const CLOZE_TEXT
Cloze question constants.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
const PercentageResultExpression
getUserQuestionResult($active_id, $pass)
Get the user solution for a question by active_id and the test pass.
const StringResultExpression
const NumericResultExpression
const EmptyAnswerExpression
const NumberOfResultExpression
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
migrateToLmContent($content)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
__construct(Container $dic, ilPlugin $plugin)
@inheritDoc