4require_once 
'./Modules/TestQuestionPool/classes/class.assQuestion.php';
 
    5require_once 
'./Modules/Test/classes/inc.AssessmentConstants.php';
 
    6require_once 
'./Modules/TestQuestionPool/classes/class.assClozeGapCombination.php';
 
    7require_once 
'./Modules/TestQuestionPool/interfaces/interface.ilObjQuestionScoringAdjustable.php';
 
    8require_once 
'./Modules/TestQuestionPool/interfaces/interface.ilObjAnswerScoringAdjustable.php';
 
    9require_once 
'./Modules/TestQuestionPool/interfaces/interface.iQuestionCondition.php';
 
   10require_once 
'./Modules/TestQuestionPool/classes/class.ilUserQuestionResult.php';
 
   11require_once 
'Modules/TestQuestionPool/classes/feedback/class.ilAssClozeTestFeedback.php';
 
  125        $this->start_tag = 
"[gap]";
 
  126        $this->end_tag = 
"[/gap]";
 
  127        $this->gaps = array();
 
  129        $this->fixedTextLength = 
"";
 
  130        $this->identical_scoring = 1;
 
  131        $this->gap_combinations_exists = 
false;
 
  132        $this->gap_combinations = array();
 
  162                $text = str_replace(
'$',
'GAPMASKEDDOLLAR', 
$text);
$text = preg_replace(
"/\[gap[^\]]*?\]/", 
"[gap]", 
$text);
 
  163        $text = preg_replace(
"/<gap([^>]*?)>/", 
"[gap]", 
$text);
 
  164        $text = str_replace(
"</gap>", 
"[/gap]", 
$text);
$text = str_replace(
'GAPMASKEDDOLLAR', 
'$', 
$text);
 
  178                $content = str_replace(
'$',
'GAPMASKEDDOLLAR', $content);
 
  179                $output = preg_replace(
"/\[gap\].*?\[\/gap\]/", $content, $gaptext, 1);
 
  202            $this->
setId($question_id);
 
  217            include_once(
"./Services/RTE/classes/class.ilRTE.php");
 
  229            include_once 
"./Modules/TestQuestionPool/classes/class.assAnswerCloze.php";
 
  230            include_once 
"./Modules/TestQuestionPool/classes/class.assClozeGap.php";
 
  232                "SELECT * FROM qpl_a_cloze WHERE question_fi = %s ORDER BY gap_id, aorder ASC",
 
  237                $this->gaps = array();
 
  239                    switch (
$data[
"cloze_type"]) {
 
  241                            if (!array_key_exists(
$data[
"gap_id"], $this->gaps)) {
 
  249                            $this->gaps[
$data[
"gap_id"]]->setGapSize(
$data[
'gap_size']);
 
  251                            $this->gaps[
$data[
"gap_id"]]->addItem($answer);
 
  254                            if (!array_key_exists(
$data[
"gap_id"], $this->gaps)) {
 
  256                                $this->gaps[
$data[
"gap_id"]]->setShuffle(
$data[
"shuffle"]);
 
  263                            $this->gaps[
$data[
"gap_id"]]->addItem($answer);
 
  266                            if (!array_key_exists(
$data[
"gap_id"], $this->gaps)) {
 
  274                            $this->gaps[
$data[
"gap_id"]]->setGapSize(
$data[
'gap_size']);
 
  275                            $answer->setLowerBound(
$data[
"lowerlimit"]);
 
  276                            $answer->setUpperBound(
$data[
"upperlimit"]);
 
  277                            $this->gaps[
$data[
"gap_id"]]->addItem($answer);
 
  284        $check_for_gap_combinations = $assClozeGapCombinationObj->loadFromDb($question_id);
 
  285        if (count($check_for_gap_combinations) != 0) {
 
  289        parent::loadFromDb($question_id);
 
  292    #region Save question to db 
  321            "DELETE FROM qpl_a_cloze WHERE question_fi = %s",
 
  323            array( $this->
getId() )
 
  326        foreach ($this->gaps as 
$key => $gap) {
 
  341        $DIC->database()->manipulateF(
 
  344            array( $this->
getId() )
 
  348            'question_fi' => array(
'integer', $this->
getId()),
 
  367        foreach ($gap->getItems($this->getShuffler()) as $item) {
 
  369            $next_id = 
$ilDB->nextId(
'qpl_a_cloze');
 
  370            switch ($gap->getType()) {
 
  397            "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)",
 
  412                                strlen($item->getAnswertext()) ? $item->getAnswertext() : 
"",
 
  416                                (
int) $gap->getGapSize()
 
  434            "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)",
 
  449                                strlen($item->getAnswertext()) ? $item->getAnswertext() : 
"",
 
  453                                ($gap->getShuffle()) ? 
"1" : 
"0" 
  471        include_once 
"./Services/Math/classes/class.EvalMath.php";
 
  473        $eval->suppress_errors = 
true;
 
  475            "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)",
 
  492                                strlen($item->getAnswertext()) ? $item->getAnswertext() : 
"",
 
  496                                ($eval->e($item->getLowerBound() !== 
false) && strlen(
 
  497                                    $item->getLowerBound()
 
  498                                ) > 0) ? $item->getLowerBound() : $item->getAnswertext(),
 
  499                                ($eval->e($item->getUpperBound() !== 
false) && strlen(
 
  500                                    $item->getUpperBound()
 
  501                                ) > 0) ? $item->getUpperBound() : $item->getAnswertext(),
 
  502                                (
int) $gap->getGapSize()
 
  509    #endregion Save question to db 
  531        $this->gaps = array();
 
  545        $this->gaps = array();
 
  640        include_once 
"./Modules/TestQuestionPool/classes/class.assClozeGap.php";
 
  641        include_once 
"./Modules/TestQuestionPool/classes/class.assAnswerCloze.php";
 
  642        $search_pattern = 
"|\[gap\](.*?)\[/gap\]|i";
 
  643        preg_match_all($search_pattern, $this->
getClozeText(), $found);
 
  644        $this->gaps = array();
 
  645        if (count($found[0])) {
 
  646            foreach ($found[1] as $gap_index => $answers) {
 
  649                $textparams = preg_split(
"/(?<!\\\\),/", $answers);
 
  650                foreach ($textparams as 
$key => $value) {
 
  652                    $gap->addItem($answer);
 
  654                $this->gaps[$gap_index] = $gap;
 
  666        if (array_key_exists($gap_index, $this->gaps)) {
 
  667            $this->gaps[$gap_index]->setType($gap_type);
 
  682        if (array_key_exists($gap_index, $this->gaps)) {
 
  683            $this->gaps[$gap_index]->setShuffle(
$shuffle);
 
  695        foreach ($this->gaps as $gap_index => $gap) {
 
  696            $this->gaps[$gap_index]->clearItems();
 
  709        if (is_array($this->gaps)) {
 
  710            return count($this->gaps);
 
  728        if (array_key_exists($gap_index, $this->gaps)) {
 
  731                $answer = str_replace(
",", 
".", $answer);
 
  733            $this->gaps[$gap_index]->addItem(
new assAnswerCloze($answer, 0, $order));
 
  747        if (array_key_exists($gap_index, $this->gaps)) {
 
  748            return $this->gaps[$gap_index];
 
  756        if (array_key_exists($gap_index, $this->gaps)) {
 
  757            $this->gaps[$gap_index]->setGapSize(
$size);
 
  773        if (array_key_exists($gap_index, $this->gaps)) {
 
  774            $this->gaps[$gap_index]->setItemPoints($order, 
$points);
 
  788        if (array_key_exists($gap_index, $this->gaps)) {
 
  789            include_once 
"./Modules/TestQuestionPool/classes/class.assAnswerCloze.php";
 
  793                $this->gaps[$gap_index]->getItemCount()
 
  795            $this->gaps[$gap_index]->addItem($answer);
 
  809        $this->gaps[
$index] = $gap;
 
  824        if (array_key_exists($gap_index, $this->gaps)) {
 
  825            $this->gaps[$gap_index]->setItemLowerBound($order, $bound);
 
  841        if (array_key_exists($gap_index, $this->gaps)) {
 
  842            $this->gaps[$gap_index]->setItemUpperBound($order, $bound);
 
  856        $gaps_used_in_combination = array();
 
  857        if ($assClozeGapCombinationObj->combinationExistsForQid($this->getId())) {
 
  858            $points = $assClozeGapCombinationObj->getMaxPointsForCombination($this->
getId());
 
  859            $gaps_used_in_combination = $assClozeGapCombinationObj->getGapsWhichAreUsedInCombination($this->
getId());
 
  861        foreach ($this->gaps as $gap_index => $gap) {
 
  862            if (!array_key_exists($gap_index, $gaps_used_in_combination)) {
 
  865                    foreach ($gap->getItems($this->getShuffler()) as $item) {
 
  866                        if ($item->getPoints() > $gap_max_points) {
 
  867                            $gap_max_points = $item->getPoints();
 
  873                    foreach ($gap->getItems($this->getShuffler()) as $item) {
 
  874                        if ($item->getPoints() > $srpoints) {
 
  875                            $srpoints = $item->getPoints();
 
  881                    foreach ($gap->getItems($this->getShuffler()) as $item) {
 
  882                        if ($item->getPoints() > $numpoints) {
 
  883                            $numpoints = $item->getPoints();
 
  901        if ($this->
id <= 0) {
 
  906        $this_id = $this->
getId();
 
  910        include_once(
"./Modules/TestQuestionPool/classes/class.assQuestion.php");
 
  914        if ((
int) $testObjId > 0) {
 
  915            $clone->setObjId($testObjId);
 
  932        if ($this->gap_combinations_exists) {
 
  941        $clone->copyPageOfQuestion($this_id);
 
  943        $clone->copyXHTMLMediaObjectsOfQuestion($this_id);
 
  945        $clone->onDuplicate($thisObjId, $this_id, $clone->getObjId(), $clone->getId());
 
  947        return $clone->getId();
 
  957        if ($this->
getId() <= 0) {
 
  962        $thisId = $this->
getId();
 
  966        include_once(
"./Modules/TestQuestionPool/classes/class.assQuestion.php");
 
  969        $clone->setObjId($target_questionpool_id);
 
  976        if ($this->gap_combinations_exists) {
 
  986        $clone->onCopy($thisObjId, $thisId, $clone->getObjId(), $clone->getId());
 
  988        return $clone->getId();
 
  993        if ($this->
id <= 0) {
 
  998        include_once(
"./Modules/TestQuestionPool/classes/class.assQuestion.php");
 
 1001        $sourceParentId = $this->
getObjId();
 
 1007        $clone->setObjId($targetParentId);
 
 1009        if ($targetQuestionTitle) {
 
 1010            $clone->setTitle($targetQuestionTitle);
 
 1015        if ($this->gap_combinations_exists) {
 
 1020        $clone->copyPageOfQuestion($sourceQuestionId);
 
 1022        $clone->copyXHTMLMediaObjectsOfQuestion($sourceQuestionId);
 
 1024        $clone->onCopy($sourceParentId, $sourceQuestionId, $clone->getObjId(), $clone->getId());
 
 1032        $array = $assClozeGapCombinationObj->loadFromDb($orgID);
 
 1033        $assClozeGapCombinationObj->importGapCombinationToDb($newID, $array);
 
 1044        foreach ($this->
getGaps() as $gap_index => $gap) {
 
 1046            foreach ($gap->getItemsRaw() as $item) {
 
 1047                array_push($answers, str_replace(
",", 
"\\,", $item->getAnswerText()));
 
 1068        if (array_key_exists($gap_index, $this->gaps)) {
 
 1069            if ($this->gaps[$gap_index]->getItemCount() == 1) {
 
 1074                $this->gaps[$gap_index]->deleteItem($answer_index);
 
 1090        if (array_key_exists($gap_index, $this->gaps)) {
 
 1092            foreach ($this->
getGaps() as $replace_gap_index => $gap) {
 
 1094                foreach ($gap->getItemsRaw() as $item) {
 
 1095                    array_push($answers, str_replace(
",", 
"\\,", $item->getAnswerText()));
 
 1097                if ($replace_gap_index == $gap_index) {
 
 1109            unset($this->gaps[$gap_index]);
 
 1110            $this->gaps = array_values($this->gaps);
 
 1125        include_once 
"./Services/Utilities/classes/class.ilStr.php";
 
 1128        switch ($gaprating) {
 
 1135                if (strcmp($a_original, $a_entered) == 0) {
 
 1140                if (levenshtein($a_original, $a_entered) <= 1) {
 
 1145                if (levenshtein($a_original, $a_entered) <= 2) {
 
 1150                if (levenshtein($a_original, $a_entered) <= 3) {
 
 1155                if (levenshtein($a_original, $a_entered) <= 4) {
 
 1160                if (levenshtein($a_original, $a_entered) <= 5) {
 
 1185        include_once 
"./Services/Math/classes/class.EvalMath.php";
 
 1187        $eval->suppress_errors = 
true;
 
 1190        if ($eval->e($a_entered) === 
false) {
 
 1192        } elseif (($eval->e($lowerBound) !== 
false) && ($eval->e($upperBound) !== 
false)) {
 
 1194            if (($eval->e($a_entered) >= $eval->e($lowerBound)) && ($eval->e($a_entered) <= $eval->e($upperBound))) {
 
 1197        } elseif ($eval->e($lowerBound) !== 
false) {
 
 1198            if (($eval->e($a_entered) >= $eval->e($lowerBound)) && ($eval->e($a_entered) <= $eval->e($a_original))) {
 
 1201        } elseif ($eval->e($upperBound) !== 
false) {
 
 1202            if (($eval->e($a_entered) >= $eval->e($a_original)) && ($eval->e($a_entered) <= $eval->e($upperBound))) {
 
 1206            if ($eval->e($a_entered) == $eval->e($a_original)) {
 
 1219        return preg_match(
"/^-?(\\d*)(,|\\.|\\/){0,1}(\\d*)$/", $value, $matches);
 
 1236        if (is_null(
$pass)) {
 
 1241        $user_result = array();
 
 1243            if (strcmp(
$data[
"value2"], 
"") != 0) {
 
 1244                $user_result[
$data[
"value1"]] = array(
 
 1245                    "gap_id" => 
$data[
"value1"],
 
 1246                    "value" => 
$data[
"value2"]
 
 1251        ksort($user_result); 
 
 1253        if ($returndetails) {
 
 1254            $detailed = array();
 
 1264        if (is_numeric($submittedValue)) {
 
 1268        if (preg_match(
'/^[-+]{0,1}\d+\/\d+$/', $submittedValue)) {
 
 1278            $gap = $this->
getGap($gapIndex);
 
 1295        $solutionSubmit = array();
 
 1297        foreach ($submit as 
$key => $value) {
 
 1298            if (preg_match(
"/^gap_(\d+)/", 
$key, $matches)) {
 
 1300                if (strlen($value)) {
 
 1301                    $gap = $this->
getGap($matches[1]);
 
 1302                    if (is_object($gap)) {
 
 1303                        if (!(($gap->getType() == 
CLOZE_SELECT) && ($value == -1))) {
 
 1304                            if ($gap->getType() == 
CLOZE_NUMERIC && !is_numeric(str_replace(
",", 
".", $value))) {
 
 1307                                $value = str_replace(
",", 
".", $value);
 
 1309                            $solutionSubmit[trim($matches[1])] = $value;
 
 1316        return $solutionSubmit;
 
 1322        $solutionSubmit = array();
 
 1324        foreach ($submit as 
$key => $value) {
 
 1325            if (preg_match(
"/^gap_(\d+)/", 
$key, $matches)) {
 
 1327                if (strlen($value)) {
 
 1328                    $gap = $this->
getGap($matches[1]);
 
 1329                    if (is_object($gap)) {
 
 1330                        if (!(($gap->getType() == 
CLOZE_SELECT) && ($value == -1))) {
 
 1332                                $value = str_replace(
",", 
".", $value);
 
 1334                            $solutionSubmit[trim($matches[1])] = $value;
 
 1341        return $solutionSubmit;
 
 1362        if (is_null(
$pass)) {
 
 1363            include_once 
"./Modules/Test/classes/class.ilObjTest.php";
 
 1367        $entered_values = 0;
 
 1369        $this->
getProcessLocker()->executeUserSolutionUpdateLockOperation(
function () use (&$entered_values, $active_id, 
$pass, $authorized) {
 
 1374                if (strlen($value)) {
 
 1376                    if (is_object($gap)) {
 
 1377                        if (!(($gap->getType() == 
CLOZE_SELECT) && ($value == -1))) {
 
 1386        if ($entered_values) {
 
 1387            include_once(
"./Modules/Test/classes/class.ilObjAssessmentFolder.php");
 
 1392            include_once(
"./Modules/Test/classes/class.ilObjAssessmentFolder.php");
 
 1409        return "assClozeTest";
 
 1433        switch ($a_textgap_rating) {
 
 1441                $this->textgap_rating = $a_textgap_rating;
 
 1458        return ($this->identical_scoring) ? 1 : 0;
 
 1470        $this->identical_scoring = ($a_identical_scoring) ? 1 : 0;
 
 1481        return "qpl_qst_cloze";
 
 1492        return array(
"qpl_a_cloze",
'qpl_a_cloze_combi_res');
 
 1503        $this->fixedTextLength = $a_text_len;
 
 1528        $gap_max_points = 0;
 
 1529        if (array_key_exists($gap_index, $this->gaps)) {
 
 1530            $gap = &$this->gaps[$gap_index];
 
 1531            foreach ($gap->getItems($this->getShuffler()) as $answer) {
 
 1532                if ($answer->getPoints() > $gap_max_points) {
 
 1533                    $gap_max_points = $answer->getPoints();
 
 1547        return parent::getRTETextWithMediaObjects() . $this->
getClozeText();
 
 1561        $this->gap_combinations_exists = $value;
 
 1566        $this->gap_combinations = $value;
 
 1574        parent::setExportDetailsXLS($worksheet, $startrow, $active_id, 
$pass);
 
 1578        foreach ($this->
getGaps() as $gap_index => $gap) {
 
 1579            $worksheet->setCell($startrow + 
$i, 0, $this->lng->txt(
"gap") . 
" $i");
 
 1580            $worksheet->setBold($worksheet->getColumnCoord(0) . ($startrow + 
$i));
 
 1582            foreach ($solution as $solutionvalue) {
 
 1583                if ($gap_index == $solutionvalue[
"value1"]) {
 
 1584                    $string_escaping_org_value = $worksheet->getStringEscaping();
 
 1586                        $worksheet->setStringEscaping(
false);
 
 1588                        switch ($gap->getType()) {
 
 1590                                $worksheet->setCell($startrow + 
$i, 1, $gap->getItem($solutionvalue[
"value2"])->getAnswertext());
 
 1594                                $worksheet->setCell($startrow + 
$i, 1, $solutionvalue[
"value2"]);
 
 1598                        $worksheet->setStringEscaping($string_escaping_org_value);
 
 1605        return $startrow + 
$i + 1;
 
 1624        include_once(
"./Services/RTE/classes/class.ilRTE.php");
 
 1634            'onenotcorrect' => $this->
formatSAQuestion($this->feedbackOBJ->getGenericFeedbackTestPresentation($this->getId(), 
false)),
 
 1635            'allcorrect' => $this->formatSAQuestion($this->feedbackOBJ->getGenericFeedbackTestPresentation($this->getId(), 
true))
 
 1641            foreach ($gap->getItems($this->getShuffler()) as $item) {
 
 1643                $jitem[
'points'] = $item->getPoints();
 
 1645                $jitem[
'order'] = $item->getOrder();
 
 1647                    $jitem[
'lowerbound'] = $item->getLowerBound();
 
 1648                    $jitem[
'upperbound'] = $item->getUpperBound();
 
 1650                    $jitem[
'value'] = trim($jitem[
'value']);
 
 1652                array_push($items, $jitem);
 
 1656                $jgap[
'size'] = $gap->getGapSize();
 
 1659            $jgap[
'shuffle'] = $gap->getShuffle();
 
 1660            $jgap[
'type'] = $gap->getType();
 
 1661            $jgap[
'item'] = $items;
 
 1663            array_push(
$gaps, $jgap);
 
 1681        require_once 
"./Modules/TestQuestionPool/classes/class.ilOperatorsExpressionMapping.php";
 
 1715        $maxStep = $this->lookupMaxStep($active_id, 
$pass);
 
 1717        if ($maxStep !== 
null) {
 
 1720                                SELECT sol.value1+1 as val, sol.value2, cloze.cloze_type 
 1721                                FROM tst_solutions sol 
 1722                                INNER JOIN qpl_a_cloze cloze ON cloze.gap_id = value1 AND cloze.question_fi = sol.question_fi 
 1723                                WHERE sol.active_fi = %s AND sol.pass = %s AND sol.question_fi = %s AND sol.step = %s 
 1724                                GROUP BY sol.solution_id, sol.value1+1, sol.value2, cloze.cloze_type 
 1726                array(
"integer", 
"integer", 
"integer",
"integer"),
 
 1727                array($active_id, 
$pass, $this->
getId(), $maxStep)
 
 1732                                SELECT sol.value1+1 as val, sol.value2, cloze.cloze_type 
 1733                                FROM tst_solutions sol 
 1734                                INNER JOIN qpl_a_cloze cloze ON cloze.gap_id = value1 AND cloze.question_fi = sol.question_fi 
 1735                                WHERE sol.active_fi = %s AND sol.pass = %s AND sol.question_fi = %s 
 1736                                GROUP BY sol.solution_id, sol.value1+1, sol.value2, cloze.cloze_type 
 1738                array(
"integer", 
"integer", 
"integer"),
 
 1744            if (
$row[
"cloze_type"] == 1) {
 
 1781        if ($assClozeGapCombinationObj->combinationExistsForQid($this->getId())) {
 
 1782            $combinations_for_question = $assClozeGapCombinationObj->getCleanCombinationArray($this->
getId());
 
 1783            $gap_answers = array();
 
 1784            $gap_used_in_combination = array();
 
 1785            foreach ($user_result as $user_result_build_list) {
 
 1786                if (is_array($user_result_build_list)) {
 
 1787                    $gap_answers[$user_result_build_list[
'gap_id']] = $user_result_build_list[
'value'];
 
 1791            foreach ($combinations_for_question as $combination) {
 
 1792                foreach ($combination as $row_key => $row_answers) {
 
 1793                    $combination_fulfilled = 
true;
 
 1794                    $points_for_combination = $row_answers[
'points'];
 
 1795                    foreach ($row_answers as $gap_key => $combination_gap_answer) {
 
 1796                        if ($gap_key !== 
'points') {
 
 1797                            $gap_used_in_combination[$gap_key] = $gap_key;
 
 1799                        if ($combination_fulfilled && array_key_exists($gap_key, $gap_answers)) {
 
 1800                            switch ($combination_gap_answer[
'type']) {
 
 1802                                    $is_text_gap_correct = $this->
getTextgapPoints($gap_answers[$gap_key], $combination_gap_answer[
'answer'], 1);
 
 1803                                    if ($is_text_gap_correct != 1) {
 
 1804                                        $combination_fulfilled = 
false;
 
 1808                                    $answer = $this->gaps[$gap_key]->getItem($gap_answers[$gap_key]);
 
 1809                                    $answertext = $answer->getAnswertext();
 
 1810                                    if ($answertext != $combination_gap_answer[
'answer']) {
 
 1811                                        $combination_fulfilled = 
false;
 
 1815                                    $answer = $this->gaps[$gap_key]->getItem(0);
 
 1816                                    if ($combination_gap_answer[
'answer'] != 
'out_of_bound') {
 
 1817                                        $is_numeric_gap_correct = $this->
getNumericgapPoints($answer->getAnswertext(), $gap_answers[$gap_key], 1, $answer->getLowerBound(), $answer->getUpperBound());
 
 1818                                        if ($is_numeric_gap_correct != 1) {
 
 1819                                            $combination_fulfilled = 
false;
 
 1822                                        $wrong_is_the_new_right = $this->
getNumericgapPoints($answer->getAnswertext(), $gap_answers[$gap_key], 1, $answer->getLowerBound(), $answer->getUpperBound());
 
 1823                                        if ($wrong_is_the_new_right == 1) {
 
 1824                                            $combination_fulfilled = 
false;
 
 1830                            if ($gap_key !== 
'points') {
 
 1831                                $combination_fulfilled = 
false;
 
 1835                    if ($combination_fulfilled) {
 
 1836                        $points += $points_for_combination;
 
 1841        return array(
$points, $gap_used_in_combination);
 
 1850        if ($detailed === 
null) {
 
 1851            $detailed = array();
 
 1855        $combinations[1] = array();
 
 1856        if ($assClozeGapCombinationObj->combinationExistsForQid($this->getId())) {
 
 1861        $solution_values_text = array(); 
 
 1862        $solution_values_select = array(); 
 
 1863        $solution_values_numeric = array(); 
 
 1864        foreach ($user_result as $gap_id => $value) {
 
 1865            if (is_string($value)) {
 
 1866                $value = array(
"value" => $value);
 
 1869            if (array_key_exists($gap_id, $this->gaps) && !array_key_exists($gap_id, $combinations[1])) {
 
 1870                switch ($this->gaps[$gap_id]->getType()) {
 
 1873                        for ($order = 0; $order < $this->gaps[$gap_id]->getItemCount(); $order++) {
 
 1874                            $answer = $this->gaps[$gap_id]->getItem($order);
 
 1875                            $gotpoints = $this->
getTextgapPoints($answer->getAnswertext(), $value[
"value"], $answer->getPoints());
 
 1876                            if ($gotpoints > $gappoints) {
 
 1877                                $gappoints = $gotpoints;
 
 1882                            if ((in_array($value[
"value"], $solution_values_text)) && ($gappoints > 0)) {
 
 1887                        $detailed[$gap_id] = array(
"points" => $gappoints, 
"best" => ($this->
getMaximumGapPoints($gap_id) == $gappoints) ? 
true : 
false, 
"positive" => ($gappoints > 0) ? 
true : 
false);
 
 1888                        array_push($solution_values_text, $value[
"value"]);
 
 1892                        for ($order = 0; $order < $this->gaps[$gap_id]->getItemCount(); $order++) {
 
 1893                            $answer = $this->gaps[$gap_id]->getItem($order);
 
 1894                            $gotpoints = $this->
getNumericgapPoints($answer->getAnswertext(), $value[
"value"], $answer->getPoints(), $answer->getLowerBound(), $answer->getUpperBound());
 
 1895                            if ($gotpoints > $gappoints) {
 
 1896                                $gappoints = $gotpoints;
 
 1901                            include_once 
"./Services/Math/classes/class.EvalMath.php";
 
 1903                            $eval->suppress_errors = 
true;
 
 1904                            $found_value = 
false;
 
 1905                            foreach ($solution_values_numeric as $solval) {
 
 1906                                if ($eval->e($solval) == $eval->e($value[
"value"])) {
 
 1907                                    $found_value = 
true;
 
 1910                            if ($found_value && ($gappoints > 0)) {
 
 1915                        $detailed[$gap_id] = array(
"points" => $gappoints, 
"best" => ($this->
getMaximumGapPoints($gap_id) == $gappoints) ? 
true : 
false, 
"positive" => ($gappoints > 0) ? 
true : 
false);
 
 1916                        array_push($solution_values_numeric, $value[
"value"]);
 
 1919                        if ($value[
"value"] >= 0) {
 
 1920                            for ($order = 0; $order < $this->gaps[$gap_id]->getItemCount(); $order++) {
 
 1921                                $answer = $this->gaps[$gap_id]->getItem($order);
 
 1922                                if ($value[
"value"] == $answer->getOrder()) {
 
 1923                                    $answerpoints = $answer->getPoints();
 
 1926                                        if ((in_array($answer->getAnswertext(), $solution_values_select)) && ($answerpoints > 0)) {
 
 1931                                    $detailed[$gap_id] = array(
"points" => $answerpoints, 
"best" => ($this->
getMaximumGapPoints($gap_id) == $answerpoints) ? 
true : 
false, 
"positive" => ($answerpoints > 0) ? 
true : 
false);
 
 1932                                    array_push($solution_values_select, $answer->getAnswertext());
 
 1946        $userSolution = array();
 
 1950            $userSolution[
$key] = array(
'gap_id' => 
$key, 
'value' => $val);
 
 1964        foreach ($userSolution as $value1 => $value2) {
 
 1965            if ($value1 == $gapIndex) {
 
 1966                $answerValue = $value2;
 
 1971        return $answerValue;
 
 1976        $gap = $this->
getGap($qIndex);
 
 1983            if ($item->getAnswertext() == $answerOptionValue) {
 
 1993        $gap = $this->
getGap($qIndex); 
 
 1996        $item->setOrder($gap->getItemCount());
 
 1998        $gap->addItem($item);
 
An exception for terminatinating execution or to throw for unit testing.
Class for cloze question numeric answers.
Class for cloze question gaps.
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.
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.
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.
addAnswerOptionValue($qIndex, $answerOptionValue, $points)
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()
setGapSize($gap_index, $order, $size)
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.
getAnswerTableName()
Returns the name of the answer table in the database.
setGapCombinations($value)
createNewOriginalFromThisDuplicate($targetParentId, $targetQuestionTitle="")
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.
calculateReachedPointsFromPreviewSession(ilAssQuestionPreviewSession $previewSession)
saveAnswerSpecificDataToDb()
Save all gaps to the database.
getFixedTextLength()
Gets the fixed text length for all text fields in the cloze question.
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.
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
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.
setExportDetailsXLS($worksheet, $startrow, $active_id, $pass)
{Creates an Excel worksheet for the detailed cumulated results of this question.object}
calculateReachedPoints($active_id, $pass=null, $authorized=true, $returndetails=false)
Returns the points, a learner has reached answering the question.
copyGapCombination($orgID, $newID)
calculateReachedPointsForSolution($user_result, &$detailed=null)
getGapCombinationsExists()
getExpressionTypes()
Get all available expression types for a specific question.
isAddableAnswerOptionValue($qIndex, $answerOptionValue)
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)
toJSON()
Returns a JSON representation of the question.
loadFromDb($question_id)
Loads a assClozeTest object from a database.
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...
duplicate($for_test=true, $title="", $author="", $owner="", $testObjId=null)
Duplicates an assClozeTest.
cleanQuestiontext($text)
Cleans cloze question text to remove attributes or tags from older ILIAS versions.
getIdenticalScoring()
Returns the identical scoring status of the question.
Abstract basic class which is to be extended by the concrete assessment question type classes.
getCurrentSolutionResultSet($active_id, $pass, $authorized=true)
Get a restulset for the current user solution for a this question by active_id and pass.
getSolutionValues($active_id, $pass=null, $authorized=true)
Loads solutions of a given user from the database an returns it.
static _getOriginalId($question_id)
Returns the original id of a question.
formatSAQuestion($a_q)
Format self assessment question.
setId($id=-1)
Sets the id of the assQuestion object.
setOriginalId($original_id)
setObjId($obj_id=0)
Set the object id of the container object.
getSolutionMaxPass($active_id)
Returns the maximum pass a users question solution.
saveQuestionDataToDb($original_id="")
getId()
Gets the id of the assQuestion object.
saveCurrentSolution($active_id, $pass, $value1, $value2, $authorized=true, $tstamp=null)
getObjId()
Get the object id of the container object.
setTitle($title="")
Sets the title string of the assQuestion object.
setOwner($owner="")
Sets the creator/owner ID of the assQuestion object.
setEstimatedWorkingTime($hour=0, $min=0, $sec=0)
Sets the estimated working time of a question from given hour, minute and second.
deductHintPointsFromReachedPoints(ilAssQuestionPreviewSession $previewSession, $reachedPoints)
static logAction($logtext="", $active_id="", $question_id="")
Logs an action into the Test&Assessment log.
removeCurrentSolution($active_id, $pass, $authorized=true)
setAuthor($author="")
Sets the authors name of the assQuestion object.
prepareTextareaOutput($txt_output, $prepare_for_latex_output=false, $omitNl2BrWhenTextArea=false)
Prepares a string for a text area output in tests.
getShuffle()
Gets the shuffle flag.
getTitle()
Gets the title string of the assQuestion object.
setPoints($a_points)
Sets the maximum available points for the question.
setComment($comment="")
Sets the comment string of the assQuestion object.
getAuthor()
Gets the authors name of the assQuestion object.
setNrOfTries($a_nr_of_tries)
getQuestion()
Gets the question string of the question object.
setAdditionalContentEditingMode($additinalContentEditingMode)
setter for additional content editing mode for this question
setQuestion($question="")
Sets the question string of the question object.
ensureNonNegativePoints($points)
const FB_MODE_GAP_QUESTION
constants for different feedback modes (per gap or per gap-answers/options)
getParticipantsSolution()
static _getLogLanguage()
retrieve the log language for assessment logging
static _enabledAssessmentLogging()
check wether assessment logging is enabled or not
static _getPass($active_id)
Retrieves the actual pass of a given user for a given test.
static getOperatorsByExpression($expression)
static _replaceMediaObjectImageSrc($a_text, $a_direction=0, $nic=IL_INST_ID)
Replaces image source from mob image urls with the mob id or replaces mob id with the correct image s...
static strToLower($a_string)
Class ilUserQuestionResult.
static sendFailure($a_info="", $a_keep=false)
Send Failure Message to Screen.
static stripSlashes($a_str, $a_strip_html=true, $a_allow="")
strip slashes if magic qoutes is enabled
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.
Class iQuestionCondition.
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
migrateToLmContent($content)
Interface ilObjAnswerScoringAdjustable.
Interface ilObjQuestionScoringAdjustable.