21 require_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();
171 if ($text === null) {
175 $text = str_replace(
'$',
'GAPMASKEDDOLLAR', $text);
176 $text = preg_replace(
"/\[gap[^\]]*?\]/",
"[gap]", $text);
177 $text = preg_replace(
"/<gap([^>]*?)>/",
"[gap]", $text);
178 $text = str_replace(
"</gap>",
"[/gap]", $text);
179 $text = str_replace(
'GAPMASKEDDOLLAR',
'$', $text);
193 $content = str_replace(
'$',
'GAPMASKEDDOLLAR', $content);
194 $output = preg_replace(
"/\[gap\].*?\[\/gap\]/", $content, $gaptext, 1);
195 $output = str_replace(
'GAPMASKEDDOLLAR',
'$', $output);
209 $ilDB = $DIC[
'ilDB'];
210 $result =
$ilDB->queryF(
215 if ($result->numRows() == 1) {
217 $this->
setId($question_id);
221 $this->
setComment((
string) $data[
"description"]);
247 $result =
$ilDB->queryF(
248 "SELECT * FROM qpl_a_cloze WHERE question_fi = %s ORDER BY gap_id, aorder ASC",
252 if ($result->numRows() > 0) {
254 while ($data =
$ilDB->fetchAssoc($result)) {
255 switch ($data[
"cloze_type"]) {
257 if (!array_key_exists($data[
"gap_id"], $this->gaps)) {
265 $this->gaps[$data[
"gap_id"]]->setGapSize((
int) $data[
'gap_size']);
267 $this->gaps[$data[
"gap_id"]]->addItem($answer);
270 if (!array_key_exists($data[
"gap_id"], $this->gaps)) {
272 $this->gaps[$data[
"gap_id"]]->setShuffle($data[
"shuffle"]);
279 $this->gaps[$data[
"gap_id"]]->addItem($answer);
282 if (!array_key_exists($data[
"gap_id"], $this->gaps)) {
290 $this->gaps[$data[
"gap_id"]]->setGapSize((
int) $data[
'gap_size']);
291 $answer->setLowerBound($data[
"lowerlimit"]);
292 $answer->setUpperBound($data[
"upperlimit"]);
293 $this->gaps[$data[
"gap_id"]]->addItem($answer);
300 $check_for_gap_combinations = $assClozeGapCombinationObj->loadFromDb($question_id);
301 if (count($check_for_gap_combinations) != 0) {
305 parent::loadFromDb($question_id);
308 #region Save question to db 338 $ilDB = $DIC[
'ilDB'];
341 "DELETE FROM qpl_a_cloze WHERE question_fi = %s",
346 foreach ($this->gaps as
$key => $gap) {
361 $DIC->database()->manipulateF(
368 'question_fi' => [
'integer', $this->
getId()],
386 $ilDB = $DIC[
'ilDB'];
387 foreach ($gap->getItems($this->getShuffler()) as $item) {
389 $next_id =
$ilDB->nextId(
'qpl_a_cloze');
390 switch ($gap->getType()) {
415 $ilDB = $DIC[
'ilDB'];
417 "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)",
432 strlen($item->getAnswertext()) ? $item->getAnswertext() :
"",
436 (
int) $gap->getGapSize()
452 $ilDB = $DIC[
'ilDB'];
454 "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)",
469 strlen($item->getAnswertext()) ? $item->getAnswertext() :
"",
473 ($gap->getShuffle()) ?
"1" :
"0" 489 $ilDB = $DIC[
'ilDB'];
492 $eval->suppress_errors =
true;
494 "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)",
511 strlen($item->getAnswertext()) ? $item->getAnswertext() :
"",
515 ($eval->e($item->getLowerBound() !==
false) && strlen(
516 $item->getLowerBound()
517 ) > 0) ? $item->getLowerBound() : $item->getAnswertext(),
518 ($eval->e($item->getUpperBound() !==
false) && strlen(
519 $item->getUpperBound()
520 ) > 0) ? $item->getUpperBound() : $item->getAnswertext(),
521 (
int) $gap->getGapSize()
528 #endregion Save question to db 593 preg_match_all(
'/\[gap\].*?\[\/gap\]/', $this->
getClozeText(), $gaps);
594 $string_with_replaced_gaps = str_replace($gaps[0],
'######GAP######', $this->
getClozeText());
596 $string_with_replaced_gaps
598 $cleaned_text_with_gaps = preg_replace_callback(
'/######GAP######/',
function ($match) use (&$gaps) {
599 return array_shift($gaps[0]);
603 || !(
new ilSetting(
'advanced_editing'))->
get(
'advanced_editing_javascript_editor') ===
'tinymce') {
604 $cleaned_text_with_gaps = nl2br($cleaned_text_with_gaps);
682 $search_pattern =
"|\[gap\](.*?)\[/gap\]|i";
683 preg_match_all($search_pattern, $this->
getClozeText(), $found);
685 if (count($found[0])) {
686 foreach ($found[1] as $gap_index => $answers) {
689 $textparams = preg_split(
"/(?<!\\\\),/", $answers);
690 foreach ($textparams as
$key => $value) {
692 $gap->addItem($answer);
694 $this->gaps[$gap_index] = $gap;
706 if (array_key_exists($gap_index, $this->gaps)) {
707 $this->gaps[$gap_index]->setType($gap_type);
722 if (array_key_exists($gap_index, $this->gaps)) {
723 $this->gaps[$gap_index]->setShuffle(
$shuffle);
735 foreach ($this->gaps as $gap_index => $gap) {
736 $this->gaps[$gap_index]->clearItems();
749 if (is_array($this->gaps)) {
750 return count($this->gaps);
768 if (array_key_exists($gap_index, $this->gaps)) {
771 $answer = str_replace(
",",
".", $answer);
773 $this->gaps[$gap_index]->addItem(
new assAnswerCloze(trim($answer), 0, $order));
785 if (array_key_exists($gap_index, $this->gaps)) {
786 return $this->gaps[$gap_index];
794 if (array_key_exists($gap_index, $this->gaps)) {
795 $this->gaps[$gap_index]->setGapSize((
int) $size);
811 if (array_key_exists($gap_index, $this->gaps)) {
812 $this->gaps[$gap_index]->setItemPoints($order,
$points);
826 if (array_key_exists($gap_index, $this->gaps)) {
830 $this->gaps[$gap_index]->getItemCount()
832 $this->gaps[$gap_index]->addItem($answer);
846 $this->gaps[$index] = $gap;
861 if (array_key_exists($gap_index, $this->gaps)) {
862 $this->gaps[$gap_index]->setItemLowerBound($order, $bound);
878 if (array_key_exists($gap_index, $this->gaps)) {
879 $this->gaps[$gap_index]->setItemUpperBound($order, $bound);
893 $gaps_used_in_combination = [];
894 if ($this->gap_combinations_exists) {
895 $points = $assClozeGapCombinationObj->getMaxPointsForCombination($this->
getId());
896 $gaps_used_in_combination = $assClozeGapCombinationObj->getGapsWhichAreUsedInCombination($this->
getId());
898 foreach ($this->gaps as $gap_index => $gap) {
899 if (!array_key_exists($gap_index, $gaps_used_in_combination)) {
902 foreach ($gap->getItems($this->getShuffler()) as $item) {
903 if ($item->getPoints() > $gap_max_points) {
904 $gap_max_points = $item->getPoints();
910 foreach ($gap->getItems($this->getShuffler()) as $item) {
911 if ($item->getPoints() > $srpoints) {
912 $srpoints = $item->getPoints();
918 foreach ($gap->getItems($this->getShuffler()) as $item) {
919 if ($item->getPoints() > $numpoints) {
920 $numpoints = $item->getPoints();
938 if ($this->
id <= 0) {
943 $this_id = $this->
getId();
947 $original_id = $this->questioninfo->getOriginalId($this->
id);
950 if ((
int) $testObjId > 0) {
951 $clone->setObjId($testObjId);
968 if ($this->gap_combinations_exists) {
977 $clone->copyPageOfQuestion($this_id);
979 $clone->copyXHTMLMediaObjectsOfQuestion($this_id);
981 $clone->onDuplicate($thisObjId, $this_id, $clone->getObjId(), $clone->getId());
983 return $clone->getId();
993 if ($this->
getId() <= 0) {
994 throw new RuntimeException(
'The question has not been saved. It cannot be duplicated');
997 $thisId = $this->
getId();
1003 $clone->setObjId($target_questionpool_id);
1005 $clone->setTitle(
$title);
1010 if ($this->gap_combinations_exists) {
1020 $clone->onCopy($thisObjId, $thisId, $clone->getObjId(), $clone->getId());
1022 return $clone->getId();
1027 if ($this->
getId() <= 0) {
1028 throw new RuntimeException(
'The question has not been saved. It cannot be duplicated');
1032 $sourceParentId = $this->
getObjId();
1038 $clone->setObjId($targetParentId);
1040 if ($targetQuestionTitle) {
1041 $clone->setTitle($targetQuestionTitle);
1046 if ($this->gap_combinations_exists) {
1051 $clone->copyPageOfQuestion($sourceQuestionId);
1053 $clone->copyXHTMLMediaObjectsOfQuestion($sourceQuestionId);
1055 $clone->onCopy($sourceParentId, $sourceQuestionId, $clone->getObjId(), $clone->getId());
1063 $array = $assClozeGapCombinationObj->loadFromDb($orgID);
1064 $assClozeGapCombinationObj->importGapCombinationToDb($newID, $array);
1075 foreach ($this->
getGaps() as $gap_index => $gap) {
1077 foreach ($gap->getItemsRaw() as $item) {
1078 array_push($answers, str_replace([
',',
'['], [
"\\,",
'[ '], $item->getAnswerText()));
1084 $output = str_replace(
"_gap]",
"gap]", $output);
1085 $this->cloze_text = $output;
1099 if (array_key_exists($gap_index, $this->gaps)) {
1100 if ($this->gaps[$gap_index]->getItemCount() == 1) {
1105 $this->gaps[$gap_index]->deleteItem($answer_index);
1121 if (array_key_exists($gap_index, $this->gaps)) {
1123 foreach ($this->
getGaps() as $replace_gap_index => $gap) {
1125 foreach ($gap->getItemsRaw() as $item) {
1126 array_push($answers, str_replace(
",",
"\\,", $item->getAnswerText()));
1128 if ($replace_gap_index == $gap_index) {
1134 $output = $this->
replaceFirstGap($output,
"[_gap]" . join(
",", $answers) .
"[/_gap]");
1138 $output = str_replace(
"_gap]",
"gap]", $output);
1139 $this->cloze_text = $output;
1140 unset($this->gaps[$gap_index]);
1141 $this->gaps = array_values($this->gaps);
1161 switch ($gaprating) {
1164 $result = $max_points;
1168 if (strcmp($a_original, $a_entered) == 0) {
1169 $result = $max_points;
1173 $transformation =
$refinery->string()->levenshtein()->standard($a_original, 1);
1176 $transformation =
$refinery->string()->levenshtein()->standard($a_original, 2);
1179 $transformation =
$refinery->string()->levenshtein()->standard($a_original, 3);
1182 $transformation =
$refinery->string()->levenshtein()->standard($a_original, 4);
1185 $transformation =
$refinery->string()->levenshtein()->standard($a_original, 5);
1190 if (isset($transformation) && $transformation->transform($a_entered) >= 0) {
1191 $result = $max_points;
1209 $eval->suppress_errors =
true;
1212 if ($eval->e($a_entered) ===
false) {
1214 } elseif (($eval->e($lowerBound) !==
false) && ($eval->e($upperBound) !==
false)) {
1215 if (($eval->e($a_entered) >= $eval->e($lowerBound)) && ($eval->e($a_entered) <= $eval->e($upperBound))) {
1216 $result = $max_points;
1218 } elseif ($eval->e($lowerBound) !==
false) {
1219 if (($eval->e($a_entered) >= $eval->e($lowerBound)) && ($eval->e($a_entered) <= $eval->e($a_original))) {
1220 $result = $max_points;
1222 } elseif ($eval->e($upperBound) !==
false) {
1223 if (($eval->e($a_entered) >= $eval->e($a_original)) && ($eval->e($a_entered) <= $eval->e($upperBound))) {
1224 $result = $max_points;
1226 } elseif ($eval->e($a_entered) == $eval->e($a_original)) {
1227 $result = $max_points;
1238 return preg_match(
"/^-?(\\d*)(,|\\.|\\/){0,1}(\\d*)$/", $value, $matches);
1249 public function calculateReachedPoints($active_id, $pass = null, $authorizedSolution =
true, $returndetails =
false): float|array
1253 if (is_null($pass)) {
1260 if (strcmp(
$data[
"value2"],
"") != 0) {
1261 $user_result[
$data[
"value1"]] = [
1262 "gap_id" => $data[
"value1"],
1263 "value" => $data[
"value2"]
1268 ksort($user_result);
1270 if ($returndetails) {
1281 if (is_numeric($submittedValue)) {
1285 if (preg_match(
'/^[-+]{0,1}\d+\/\d+$/', $submittedValue)) {
1295 $gap = $this->
getGap($gapIndex);
1302 $this->tpl->setOnScreenMessage(
'failure', $this->
lng->txt(
"err_no_numeric_value"),
true);
1312 $solutionSubmit = [];
1313 $post_wrapper = $this->dic->http()->wrapper()->post();
1314 foreach ($this->
getGaps() as $index => $gap) {
1315 if (!$post_wrapper->has(
"gap_$index")) {
1318 $value = trim($post_wrapper->retrieve(
1320 $this->dic->refinery()->kindlyTo()->string()
1322 if ($value ===
'') {
1329 && !is_numeric(str_replace(
",",
".", $value))
1333 $value = str_replace(
",",
".", $value);
1335 $solutionSubmit[$index] = $value;
1339 return $solutionSubmit;
1345 $solutionSubmit = [];
1347 foreach ($submit as
$key => $value) {
1348 if (preg_match(
"/^gap_(\d+)/",
$key, $matches)) {
1349 if ($value !== null && $value !==
'') {
1350 $gap = $this->
getGap($matches[1]);
1351 if (is_object($gap)) {
1352 if (!(($gap->getType() ==
CLOZE_SELECT) && ($value == -1))) {
1354 $value = str_replace(
",",
".", $value);
1356 $solutionSubmit[trim($matches[1])] = $value;
1363 return $solutionSubmit;
1381 if (is_null($pass)) {
1385 $entered_values = 0;
1387 $this->
getProcessLocker()->executeUserSolutionUpdateLockOperation(
function () use (&$entered_values, $active_id, $pass, $authorized) {
1391 if ($value !== null && $value !==
'') {
1393 if (is_object($gap)) {
1394 if (!(($gap->getType() ==
CLOZE_SELECT) && ($value == -1))) {
1403 if ($entered_values) {
1407 "log_user_entered_values",
1409 ), $active_id, $this->
getId());
1415 "log_user_not_entered_values",
1417 ), $active_id, $this->
getId());
1432 return "assClozeTest";
1456 switch ($a_textgap_rating) {
1464 $this->textgap_rating = $a_textgap_rating;
1481 return ($this->identical_scoring) ? 1 : 0;
1493 $this->identical_scoring = ($a_identical_scoring) ? 1 : 0;
1504 return "qpl_qst_cloze";
1509 return [
"qpl_a_cloze",
'qpl_a_cloze_combi_res'];
1520 $this->fixedTextLength = $a_text_len;
1545 $gap_max_points = 0;
1546 if (array_key_exists($gap_index, $this->gaps)) {
1547 $gap = &$this->gaps[$gap_index];
1548 foreach ($gap->getItems($this->getShuffler()) as $answer) {
1549 if ($answer->getPoints() > $gap_max_points) {
1550 $gap_max_points = $answer->getPoints();
1564 return parent::getRTETextWithMediaObjects() . $this->
getClozeText();
1578 $this->gap_combinations_exists = $value;
1583 $this->gap_combinations = $value;
1591 parent::setExportDetailsXLSX($worksheet, $startrow, $col, $active_id, $pass);
1595 foreach ($this->
getGaps() as $gap_index => $gap) {
1596 $worksheet->
setCell($startrow + $i, $col, $this->
lng->txt(
"gap") .
" $i");
1599 foreach ($solution as $solutionvalue) {
1600 if ($gap_index == $solutionvalue[
"value1"]) {
1605 switch ($gap->getType()) {
1607 $worksheet->
setCell($startrow + $i, $col + 2, $gap->getItem($solutionvalue[
"value2"])->getAnswertext());
1611 $worksheet->
setCell($startrow + $i, $col + 2, $solutionvalue[
"value2"]);
1622 return $startrow + $i + 1;
1642 $result[
'id'] = $this->
getId();
1649 $result[
'feedback'] = [
1650 'onenotcorrect' => $this->
formatSAQuestion($this->feedbackOBJ->getGenericFeedbackTestPresentation($this->getId(),
false)),
1651 'allcorrect' => $this->
formatSAQuestion($this->feedbackOBJ->getGenericFeedbackTestPresentation($this->getId(),
true))
1657 foreach ($gap->getItems($this->getShuffler()) as $item) {
1659 $jitem[
'points'] = $item->getPoints();
1661 $jitem[
'order'] = $item->getOrder();
1663 $jitem[
'lowerbound'] = $item->getLowerBound();
1664 $jitem[
'upperbound'] = $item->getUpperBound();
1666 $jitem[
'value'] = trim($jitem[
'value']);
1668 array_push($items, $jitem);
1672 $jgap[
'size'] = $gap->getGapSize();
1675 $jgap[
'shuffle'] = $gap->getShuffle();
1676 $jgap[
'type'] = $gap->getType();
1677 $jgap[
'item'] = $items;
1679 array_push($gaps, $jgap);
1681 $result[
'gaps'] =
$gaps;
1683 $result[
'mobs'] = $mobs;
1684 return json_encode($result);
1727 $ilDB = $DIC[
'ilDB'];
1735 SELECT sol.value1+1 as val, sol.value2, cloze.cloze_type 1736 FROM tst_solutions sol 1737 INNER JOIN qpl_a_cloze cloze ON cloze.gap_id = value1 AND cloze.question_fi = sol.question_fi 1738 WHERE sol.active_fi = %s AND sol.pass = %s AND sol.question_fi = %s AND sol.step = %s 1739 GROUP BY sol.solution_id, sol.value1+1, sol.value2, cloze.cloze_type 1741 [
"integer",
"integer",
"integer",
"integer"],
1742 [$active_id, $pass, $this->
getId(), $maxStep]
1747 SELECT sol.value1+1 as val, sol.value2, cloze.cloze_type 1748 FROM tst_solutions sol 1749 INNER JOIN qpl_a_cloze cloze ON cloze.gap_id = value1 AND cloze.question_fi = sol.question_fi 1750 WHERE sol.active_fi = %s AND sol.pass = %s AND sol.question_fi = %s 1751 GROUP BY sol.solution_id, sol.value1+1, sol.value2, cloze.cloze_type 1753 [
"integer",
"integer",
"integer"],
1754 [$active_id, $pass, $this->
getId()]
1759 if ($row[
"cloze_type"] == 1) {
1762 $result->addKeyValue($row[
"val"], $row[
"value2"]);
1768 $result->setReachedPercentage((
$points / $max_points) * 100);
1783 if ($index !== null) {
1784 return $this->
getGap($index);
1795 $gap_used_in_combination = [];
1796 if ($assClozeGapCombinationObj->combinationExistsForQid($this->getId())) {
1797 $combinations_for_question = $assClozeGapCombinationObj->getCleanCombinationArray($this->
getId());
1800 foreach ($user_result as $user_result_build_list) {
1801 if (is_array($user_result_build_list)) {
1802 $gap_answers[$user_result_build_list[
'gap_id']] = $user_result_build_list[
'value'];
1806 foreach ($combinations_for_question as $combination) {
1807 foreach ($combination as $row_key => $row_answers) {
1808 $combination_fulfilled =
true;
1809 $points_for_combination = $row_answers[
'points'];
1810 foreach ($row_answers as $gap_key => $combination_gap_answer) {
1811 if ($gap_key !==
'points') {
1812 $gap_used_in_combination[$gap_key] = $gap_key;
1814 if ($combination_fulfilled && array_key_exists($gap_key, $gap_answers)) {
1815 switch ($combination_gap_answer[
'type']) {
1817 $is_text_gap_correct = $this->
getTextgapPoints($gap_answers[$gap_key], $combination_gap_answer[
'answer'], 1);
1818 if ($is_text_gap_correct != 1) {
1819 $combination_fulfilled =
false;
1823 $answer = $this->gaps[$gap_key]->getItem($gap_answers[$gap_key]);
1824 $answertext = $answer?->getAnswertext();
1825 if ($answertext != $combination_gap_answer[
'answer']) {
1826 $combination_fulfilled =
false;
1830 $answer = $this->gaps[$gap_key]->getItem(0);
1831 if ($combination_gap_answer[
'answer'] !=
'out_of_bound') {
1832 $is_numeric_gap_correct = $this->
getNumericgapPoints($answer->getAnswertext(), $gap_answers[$gap_key], 1, $answer->getLowerBound(), $answer->getUpperBound());
1833 if ($is_numeric_gap_correct != 1) {
1834 $combination_fulfilled =
false;
1837 $wrong_is_the_new_right = $this->
getNumericgapPoints($answer->getAnswertext(), $gap_answers[$gap_key], 1, $answer->getLowerBound(), $answer->getUpperBound());
1838 if ($wrong_is_the_new_right == 1) {
1839 $combination_fulfilled =
false;
1845 if ($gap_key !==
'points') {
1846 $combination_fulfilled =
false;
1850 if ($combination_fulfilled) {
1851 $points += $points_for_combination;
1856 return [
$points, $gap_used_in_combination];
1864 if ($detailed === null) {
1871 $combinations[1] = [];
1872 if ($this->gap_combinations_exists) {
1877 $solution_values_text = [];
1878 $solution_values_select = [];
1879 $solution_values_numeric = [];
1880 foreach ($user_result as $gap_id => $value) {
1881 if (is_string($value)) {
1882 $value = [
"value" => $value];
1885 if (array_key_exists($gap_id, $this->gaps) && !array_key_exists($gap_id, $combinations[1])) {
1886 switch ($this->gaps[$gap_id]->getType()) {
1889 for ($order = 0; $order < $this->gaps[$gap_id]->getItemCount(); $order++) {
1890 $answer = $this->gaps[$gap_id]->getItem($order);
1891 $gotpoints = $this->
getTextgapPoints($answer->getAnswertext(), $value[
"value"], $answer->getPoints());
1892 if ($gotpoints > $gappoints) {
1893 $gappoints = $gotpoints;
1898 if ((in_array($value[
"value"], $solution_values_text)) && ($gappoints > 0)) {
1903 $detailed[$gap_id] = [
"points" => $gappoints,
"best" => ($this->
getMaximumGapPoints($gap_id) == $gappoints) ?
true :
false,
"positive" => ($gappoints > 0) ? true :
false];
1904 array_push($solution_values_text, $value[
"value"]);
1908 for ($order = 0; $order < $this->gaps[$gap_id]->getItemCount(); $order++) {
1909 $answer = $this->gaps[$gap_id]->getItem($order);
1910 $gotpoints = $this->
getNumericgapPoints($answer->getAnswertext(), $value[
"value"], $answer->getPoints(), $answer->getLowerBound(), $answer->getUpperBound());
1911 if ($gotpoints > $gappoints) {
1912 $gappoints = $gotpoints;
1918 $eval->suppress_errors =
true;
1919 $found_value =
false;
1920 foreach ($solution_values_numeric as $solval) {
1921 if ($eval->e($solval) == $eval->e($value[
"value"])) {
1922 $found_value =
true;
1925 if ($found_value && ($gappoints > 0)) {
1930 $detailed[$gap_id] = [
"points" => $gappoints,
"best" => ($this->
getMaximumGapPoints($gap_id) == $gappoints) ?
true :
false,
"positive" => ($gappoints > 0) ? true :
false];
1931 array_push($solution_values_numeric, $value[
"value"]);
1934 if ($value[
"value"] >= 0) {
1935 for ($order = 0; $order < $this->gaps[$gap_id]->getItemCount(); $order++) {
1936 $answer = $this->gaps[$gap_id]->getItem($order);
1937 if ($value[
"value"] == $answer->getOrder()) {
1938 $answerpoints = $answer->getPoints();
1941 if ((in_array($answer->getAnswertext(), $solution_values_select)) && ($answerpoints > 0)) {
1946 $detailed[$gap_id] = [
"points" => $answerpoints,
"best" => ($this->
getMaximumGapPoints($gap_id) == $answerpoints) ?
true :
false,
"positive" => ($answerpoints > 0) ? true :
false];
1947 array_push($solution_values_select, $answer->getAnswertext());
1963 if (!is_array($participant_session)) {
1967 $user_solution = [];
1969 foreach ($participant_session as
$key => $val) {
1970 $user_solution[
$key] = [
'gap_id' =>
$key,
'value' => $val];
1983 foreach ($userSolution as $value1 => $value2) {
1984 if ($value1 == $gapIndex) {
1985 $answerValue = $value2;
1990 return $answerValue;
1995 $gap = $this->
getGap($qIndex);
2001 foreach ($gap->getItems($this->randomGroup->dontShuffle()) as $item) {
2002 if ($item->getAnswertext() === $answerOptionValue) {
2012 $gap = $this->
getGap($qIndex);
2015 $item->setOrder($gap->getItemCount());
2017 $gap->addItem($item);
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...
getSolutionValues($active_id, $pass=null, bool $authorized=true)
Loads solutions of a given user from the database an returns it.
setNrOfTries(int $a_nr_of_tries)
setGapCombinations($value)
fetchSolutionSubmit($submit)
toJSON()
Returns a JSON representation of the question.
static getInstance($identifier)
getGapCount()
Returns the number of gaps.
setExportDetailsXLSX(ilAssExcelFormatHelper $worksheet, int $startrow, int $col, int $active_id, int $pass)
{}
const TEXTGAP_RATING_LEVENSHTEIN5
const PercentageResultExpression
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
getMaximumGapPoints($gap_index)
Returns the maximum points for a gap.
createNewOriginalFromThisDuplicate($targetParentId, $targetQuestionTitle="")
getQuestionType()
Returns the question type of the question.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static _getPass($active_id)
Retrieves the actual pass of a given user for a given test.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
getClozeTextForHTMLOutput()
Returns the cloze text as HTML (with optional nl2br) Fix for Mantis 29987: We assume Tiny embeds any ...
setEndTag($end_tag="[/gap]")
Sets the end tag of a cloze gap.
clearGapAnswers()
Removes all answers from the gaps.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
getAdditionalTableName()
Returns the name of the additional question data table in the database.
const NumberOfResultExpression
saveAnswerSpecificDataToDb()
Save all gaps to the database.
setGapSize($gap_index, $size)
lmMigrateQuestionTypeSpecificContent(ilAssSelfAssessmentMigrator $migrator)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
const TEXTGAP_RATING_LEVENSHTEIN2
const TEXTGAP_RATING_LEVENSHTEIN1
Abstract basic class which is to be extended by the concrete assessment question type classes...
const CLOZE_TEXT
Cloze question constants.
getSolutionSubmitValidation()
getRTETextWithMediaObjects()
Collects all text in the question which could contain media objects which were created with the Rich ...
static stripSlashes(string $a_str, bool $a_strip_html=true, string $a_allow="")
calculateCombinationResult($user_result)
getOperators($expression)
Get all available operations for a specific question.
getMaximumPoints()
Returns the maximum points, a learner can reach answering the question.
getColumnCoord(int $a_col)
Get column "name" from number.
ensureNonNegativePoints($points)
bool $shuffle
Indicates whether the answers will be shuffled or not.
addAnswerOptionValue(int $qIndex, string $answerOptionValue, float $points)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
migrateToLmContent($content)
copyGapCombination($orgID, $newID)
getGap($gap_index=0)
Returns the gap at a given index.
setGapAnswerPoints($gap_index, $order, $points)
Sets the points of a gap with a given index and an answer with a given order.
getTextgapRating()
Returns the rating option for text gaps.
Class for cloze question gaps.
saveToDb($original_id="")
Saves a assClozeTest object to a database.
getParticipantsSolution()
setClozeTextValue($cloze_text="")
getUserQuestionResult($active_id, $pass)
Get the user solution for a question by active_id and the test pass.
checkForValidFormula($value)
const StringResultExpression
setComment(string $comment="")
createGapsFromQuestiontext()
Create gap entries by parsing the question text.
float $points
The maximum available points for the question.
calculateReachedPoints($active_id, $pass=null, $authorizedSolution=true, $returndetails=false)
Returns the points, a learner has reached answering the question.
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...
ilAssQuestionFeedback $feedbackOBJ
getStartTag()
Returns the start tag of a cloze gap.
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...
setGapType($gap_index, $gap_type)
Set the type of a gap with a given index.
setGapCombinationsExists($value)
getGaps()
Returns the array of gaps.
saveCurrentSolution(int $active_id, int $pass, $value1, $value2, bool $authorized=true, $tstamp=0)
setBold(string $a_coords)
Set cell(s) to bold.
static _enabledAssessmentLogging()
const TEXTGAP_RATING_LEVENSHTEIN3
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
setGapAnswerLowerBound($gap_index, $order, $bound)
Sets the lower bound of a gap with a given index and an answer with a given order.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static logAction(string $logtext, int $active_id, int $question_id)
setFixedTextLength($a_text_len)
Sets a fixed text length for all text fields in the cloze question.
saveWorkingData($active_id, $pass=null, $authorized=true)
Saves the learners input of the question to the database.
const NumericResultExpression
isValidNumericSubmitValue($submittedValue)
copyObject($target_questionpool_id, $title="")
Copies an assClozeTest object.
const TEXTGAP_RATING_CASESENSITIVE
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
addGapAtIndex($gap, $index)
Adds a ClozeGap object at a given index.
string $question
The question text.
getGapCombinationsExists()
setGapAnswerUpperBound($gap_index, $order, $bound)
Sets the upper bound of a gap with a given index and an answer with a given order.
calculateReachedPointsFromPreviewSession(ilAssQuestionPreviewSession $preview_session)
saveClozeTextGapRecordToDb($next_id, $key, $item, $gap)
Saves a gap-item record.
saveAdditionalQuestionDataToDb()
Saves the data for the additional data table.
addGapAnswer($gap_index, $order, $answer)
Sets the answer text of a gap with a given index.
setGapShuffle($gap_index=0, $shuffle=1)
Sets the shuffle state of a gap with a given index.
setClozeText($cloze_text="")
Evaluates the text gap solutions from the cloze text.
cleanQuestiontext($text)
Cleans cloze question text to remove attributes or tags from older ILIAS versions.
getExpressionTypes()
Get all available expression types for a specific question.
fetchAnswerValueForGap($userSolution, $gapIndex)
static getOperatorsByExpression($expression)
flushGaps()
Deletes all gaps without changing the cloze text.
isAdditionalContentEditingModePageObject()
deductHintPointsFromReachedPoints(ilAssQuestionPreviewSession $previewSession, $reachedPoints)
saveClozeNumericGapRecordToDb($next_id, $key, $item, $gap)
Saves a gap-item record.
saveQuestionDataToDb(int $original_id=-1)
deleteGap($gap_index)
Deletes a gap with a given index.
getSolutionMaxPass(int $active_id)
replaceFirstGap($gaptext, $content)
Replace the first gap in a string without treating backreferences.
removeCurrentSolution(int $active_id, int $pass, bool $authorized=true)
updateClozeTextFromGaps()
Updates the gap parameters in the cloze text from the form input.
setFeedbackMode($feedbackMode)
setTextgapRating($a_textgap_rating)
Sets the rating option for text gaps.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
getEndTag()
Returns the end tag of a cloze gap.
setStartTag($start_tag="[gap]")
Sets the start tag of a cloze gap.
addGapText($gap_index)
Adds a new answer text value to a text gap with a given index.
deleteAnswerText($gap_index, $answer_index)
Deletes the answer text of a gap with a given index and an answer with a given order.
getFixedTextLength()
Gets the fixed text length for all text fields in the cloze question.
setOriginalId(?int $original_id)
const TEXTGAP_RATING_LEVENSHTEIN4
setTitle(string $title="")
static strToLower(string $a_string)
setLifecycle(ilAssQuestionLifecycle $lifecycle)
saveClozeSelectGapRecordToDb($next_id, $key, $item, $gap)
Saves a gap-item record.
getClozeText()
Returns the cloze text.
getCurrentSolutionResultSet(int $active_id, int $pass, bool $authorized=true)
__construct( $title="", $comment="", $author="", $owner=-1, $question="")
assClozeTest constructor
loadFromDb($question_id)
Loads a assClozeTest object from a database.
isComplete()
Returns TRUE, if a cloze test is complete for use.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
getHtmlQuestionContentPurifier()
lookupMaxStep(int $active_id, int $pass)
getIdenticalScoring()
Returns the identical scoring status of the question.
setAuthor(string $author="")
setIdenticalScoring($a_identical_scoring)
Sets the identical scoring option for cloze questions.
setAdditionalContentEditingMode(?string $additionalContentEditingMode)
getAvailableAnswerOptions($index=null)
If index is null, the function returns an array with all anwser options Else it returns the specific ...
isAddableAnswerOptionValue(int $qIndex, string $answerOptionValue)
const FB_MODE_GAP_QUESTION
constants for different feedback modes (per gap or per gap-answers/options)
static getDraftInstance()
saveClozeGapItemsToDb($gap, $key)
Save all items belonging to one cloze gap to the db.
calculateReachedPointsForSolution($user_result, &$detailed=null)
ILIAS Refinery Factory $refinery
duplicate(bool $for_test=true, string $title="", string $author="", int $owner=-1, $testObjId=null)
Duplicates an assClozeTest.
const TEXTGAP_RATING_CASEINSENSITIVE
setQuestion(string $question="")
const EmptyAnswerExpression