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);
 
  180                $output = str_replace(
'GAPMASKEDDOLLAR', 
'$', $output);
 
  202            $this->
setId($question_id);
 
  224            include_once(
"./Services/RTE/classes/class.ilRTE.php");
 
  236            include_once 
"./Modules/TestQuestionPool/classes/class.assAnswerCloze.php";
 
  237            include_once 
"./Modules/TestQuestionPool/classes/class.assClozeGap.php";
 
  239                "SELECT * FROM qpl_a_cloze WHERE question_fi = %s ORDER BY gap_id, aorder ASC",
 
  244                $this->gaps = array();
 
  246                    switch (
$data[
"cloze_type"]) {
 
  248                            if (!array_key_exists(
$data[
"gap_id"], $this->gaps)) {
 
  256                            $this->gaps[
$data[
"gap_id"]]->setGapSize(
$data[
'gap_size']);
 
  258                            $this->gaps[
$data[
"gap_id"]]->addItem($answer);
 
  261                            if (!array_key_exists(
$data[
"gap_id"], $this->gaps)) {
 
  263                                $this->gaps[
$data[
"gap_id"]]->setShuffle(
$data[
"shuffle"]);
 
  270                            $this->gaps[
$data[
"gap_id"]]->addItem($answer);
 
  273                            if (!array_key_exists(
$data[
"gap_id"], $this->gaps)) {
 
  281                            $this->gaps[
$data[
"gap_id"]]->setGapSize(
$data[
'gap_size']);
 
  282                            $answer->setLowerBound(
$data[
"lowerlimit"]);
 
  283                            $answer->setUpperBound(
$data[
"upperlimit"]);
 
  284                            $this->gaps[
$data[
"gap_id"]]->addItem($answer);
 
  291        $check_for_gap_combinations = $assClozeGapCombinationObj->loadFromDb($question_id);
 
  292        if (count($check_for_gap_combinations) != 0) {
 
  296        parent::loadFromDb($question_id);
 
  299    #region Save question to db 
  328            "DELETE FROM qpl_a_cloze WHERE question_fi = %s",
 
  330            array( $this->
getId() )
 
  333        foreach ($this->gaps as $key => $gap) {
 
  348        $DIC->database()->manipulateF(
 
  351            array( $this->
getId() )
 
  355            'question_fi' => array(
'integer', $this->
getId()),
 
  374        foreach ($gap->getItems($this->getShuffler()) as $item) {
 
  376            $next_id = 
$ilDB->nextId(
'qpl_a_cloze');
 
  377            switch ($gap->getType()) {
 
  404            "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)",
 
  419                                strlen($item->getAnswertext()) ? $item->getAnswertext() : 
"",
 
  423                                (
int) $gap->getGapSize()
 
  441            "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)",
 
  456                                strlen($item->getAnswertext()) ? $item->getAnswertext() : 
"",
 
  460                                ($gap->getShuffle()) ? 
"1" : 
"0" 
  478        include_once 
"./Services/Math/classes/class.EvalMath.php";
 
  480        $eval->suppress_errors = 
true;
 
  482            "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)",
 
  499                                strlen($item->getAnswertext()) ? $item->getAnswertext() : 
"",
 
  503                                ($eval->e($item->getLowerBound() !== 
false) && strlen(
 
  504                                    $item->getLowerBound()
 
  505                                ) > 0) ? $item->getLowerBound() : $item->getAnswertext(),
 
  506                                ($eval->e($item->getUpperBound() !== 
false) && strlen(
 
  507                                    $item->getUpperBound()
 
  508                                ) > 0) ? $item->getUpperBound() : $item->getAnswertext(),
 
  509                                (
int) $gap->getGapSize()
 
  516    #endregion Save question to db 
  538        $this->gaps = array();
 
  552        $this->gaps = array();
 
  647        include_once 
"./Modules/TestQuestionPool/classes/class.assClozeGap.php";
 
  648        include_once 
"./Modules/TestQuestionPool/classes/class.assAnswerCloze.php";
 
  649        $search_pattern = 
"|\[gap\](.*?)\[/gap\]|i";
 
  650        preg_match_all($search_pattern, $this->
getClozeText(), $found);
 
  651        $this->gaps = array();
 
  652        if (count($found[0])) {
 
  653            foreach ($found[1] as $gap_index => $answers) {
 
  656                $textparams = preg_split(
"/(?<!\\\\),/", $answers);
 
  657                foreach ($textparams as $key => $value) {
 
  659                    $gap->addItem($answer);
 
  661                $this->gaps[$gap_index] = $gap;
 
  673        if (array_key_exists($gap_index, $this->gaps)) {
 
  674            $this->gaps[$gap_index]->setType($gap_type);
 
  689        if (array_key_exists($gap_index, $this->gaps)) {
 
  690            $this->gaps[$gap_index]->setShuffle(
$shuffle);
 
  702        foreach ($this->gaps as $gap_index => $gap) {
 
  703            $this->gaps[$gap_index]->clearItems();
 
  716        if (is_array($this->gaps)) {
 
  717            return count($this->gaps);
 
  735        if (array_key_exists($gap_index, $this->gaps)) {
 
  738                $answer = str_replace(
",", 
".", $answer);
 
  740            $this->gaps[$gap_index]->addItem(
new assAnswerCloze($answer, 0, $order));
 
  754        if (array_key_exists($gap_index, $this->gaps)) {
 
  755            return $this->gaps[$gap_index];
 
  763        if (array_key_exists($gap_index, $this->gaps)) {
 
  764            $this->gaps[$gap_index]->setGapSize(
$size);
 
  780        if (array_key_exists($gap_index, $this->gaps)) {
 
  781            $this->gaps[$gap_index]->setItemPoints($order, 
$points);
 
  795        if (array_key_exists($gap_index, $this->gaps)) {
 
  796            include_once 
"./Modules/TestQuestionPool/classes/class.assAnswerCloze.php";
 
  800                $this->gaps[$gap_index]->getItemCount()
 
  802            $this->gaps[$gap_index]->addItem($answer);
 
  816        $this->gaps[
$index] = $gap;
 
  831        if (array_key_exists($gap_index, $this->gaps)) {
 
  832            $this->gaps[$gap_index]->setItemLowerBound($order, $bound);
 
  848        if (array_key_exists($gap_index, $this->gaps)) {
 
  849            $this->gaps[$gap_index]->setItemUpperBound($order, $bound);
 
  863        $gaps_used_in_combination = array();
 
  864        if ($assClozeGapCombinationObj->combinationExistsForQid($this->getId())) {
 
  865            $points = $assClozeGapCombinationObj->getMaxPointsForCombination($this->
getId());
 
  866            $gaps_used_in_combination = $assClozeGapCombinationObj->getGapsWhichAreUsedInCombination($this->
getId());
 
  868        foreach ($this->gaps as $gap_index => $gap) {
 
  869            if (!array_key_exists($gap_index, $gaps_used_in_combination)) {
 
  872                    foreach ($gap->getItems($this->getShuffler()) as $item) {
 
  873                        if ($item->getPoints() > $gap_max_points) {
 
  874                            $gap_max_points = $item->getPoints();
 
  880                    foreach ($gap->getItems($this->getShuffler()) as $item) {
 
  881                        if ($item->getPoints() > $srpoints) {
 
  882                            $srpoints = $item->getPoints();
 
  888                    foreach ($gap->getItems($this->getShuffler()) as $item) {
 
  889                        if ($item->getPoints() > $numpoints) {
 
  890                            $numpoints = $item->getPoints();
 
  908        if ($this->
id <= 0) {
 
  913        $this_id = $this->
getId();
 
  917        include_once(
"./Modules/TestQuestionPool/classes/class.assQuestion.php");
 
  921        if ((
int) $testObjId > 0) {
 
  922            $clone->setObjId($testObjId);
 
  939        if ($this->gap_combinations_exists) {
 
  948        $clone->copyPageOfQuestion($this_id);
 
  950        $clone->copyXHTMLMediaObjectsOfQuestion($this_id);
 
  952        $clone->onDuplicate($thisObjId, $this_id, $clone->getObjId(), $clone->getId());
 
  954        return $clone->getId();
 
  964        if ($this->
getId() <= 0) {
 
  969        $thisId = $this->
getId();
 
  973        include_once(
"./Modules/TestQuestionPool/classes/class.assQuestion.php");
 
  976        $clone->setObjId($target_questionpool_id);
 
  983        if ($this->gap_combinations_exists) {
 
  993        $clone->onCopy($thisObjId, $thisId, $clone->getObjId(), $clone->getId());
 
  995        return $clone->getId();
 
 1000        if ($this->
id <= 0) {
 
 1005        include_once(
"./Modules/TestQuestionPool/classes/class.assQuestion.php");
 
 1008        $sourceParentId = $this->
getObjId();
 
 1014        $clone->setObjId($targetParentId);
 
 1016        if ($targetQuestionTitle) {
 
 1017            $clone->setTitle($targetQuestionTitle);
 
 1022        if ($this->gap_combinations_exists) {
 
 1027        $clone->copyPageOfQuestion($sourceQuestionId);
 
 1029        $clone->copyXHTMLMediaObjectsOfQuestion($sourceQuestionId);
 
 1031        $clone->onCopy($sourceParentId, $sourceQuestionId, $clone->getObjId(), $clone->getId());
 
 1039        $array = $assClozeGapCombinationObj->loadFromDb($orgID);
 
 1040        $assClozeGapCombinationObj->importGapCombinationToDb($newID, $array);
 
 1051        foreach ($this->
getGaps() as $gap_index => $gap) {
 
 1053            foreach ($gap->getItemsRaw() as $item) {
 
 1054                array_push($answers, str_replace(
",", 
"\\,", $item->getAnswerText()));
 
 1060        $output = str_replace(
"_gap]", 
"gap]", $output);
 
 1061        $this->cloze_text = $output;
 
 1075        if (array_key_exists($gap_index, $this->gaps)) {
 
 1076            if ($this->gaps[$gap_index]->getItemCount() == 1) {
 
 1081                $this->gaps[$gap_index]->deleteItem($answer_index);
 
 1097        if (array_key_exists($gap_index, $this->gaps)) {
 
 1099            foreach ($this->
getGaps() as $replace_gap_index => $gap) {
 
 1101                foreach ($gap->getItemsRaw() as $item) {
 
 1102                    array_push($answers, str_replace(
",", 
"\\,", $item->getAnswerText()));
 
 1104                if ($replace_gap_index == $gap_index) {
 
 1110                                        $output = $this->
replaceFirstGap($output, 
"[_gap]" . join(
",", $answers) . 
"[/_gap]");
 
 1114            $output = str_replace(
"_gap]", 
"gap]", $output);
 
 1115            $this->cloze_text = $output;
 
 1116            unset($this->gaps[$gap_index]);
 
 1117            $this->gaps = array_values($this->gaps);
 
 1132        include_once 
"./Services/Utilities/classes/class.ilStr.php";
 
 1135        switch ($gaprating) {
 
 1142                if (strcmp($a_original, $a_entered) == 0) {
 
 1147                if (levenshtein($a_original, $a_entered) <= 1) {
 
 1152                if (levenshtein($a_original, $a_entered) <= 2) {
 
 1157                if (levenshtein($a_original, $a_entered) <= 3) {
 
 1162                if (levenshtein($a_original, $a_entered) <= 4) {
 
 1167                if (levenshtein($a_original, $a_entered) <= 5) {
 
 1192        include_once 
"./Services/Math/classes/class.EvalMath.php";
 
 1194        $eval->suppress_errors = 
true;
 
 1197        if ($eval->e($a_entered) === 
false) {
 
 1199        } elseif (($eval->e($lowerBound) !== 
false) && ($eval->e($upperBound) !== 
false)) {
 
 1201            if (($eval->e($a_entered) >= $eval->e($lowerBound)) && ($eval->e($a_entered) <= $eval->e($upperBound))) {
 
 1204        } elseif ($eval->e($lowerBound) !== 
false) {
 
 1205            if (($eval->e($a_entered) >= $eval->e($lowerBound)) && ($eval->e($a_entered) <= $eval->e($a_original))) {
 
 1208        } elseif ($eval->e($upperBound) !== 
false) {
 
 1209            if (($eval->e($a_entered) >= $eval->e($a_original)) && ($eval->e($a_entered) <= $eval->e($upperBound))) {
 
 1213            if ($eval->e($a_entered) == $eval->e($a_original)) {
 
 1226        return preg_match(
"/^-?(\\d*)(,|\\.|\\/){0,1}(\\d*)$/", $value, $matches);
 
 1243        if (is_null(
$pass)) {
 
 1248        $user_result = array();
 
 1250            if (strcmp(
$data[
"value2"], 
"") != 0) {
 
 1251                $user_result[
$data[
"value1"]] = array(
 
 1252                    "gap_id" => 
$data[
"value1"],
 
 1253                    "value" => 
$data[
"value2"]
 
 1258        ksort($user_result); 
 
 1260        if ($returndetails) {
 
 1261            $detailed = array();
 
 1271        if (is_numeric($submittedValue)) {
 
 1275        if (preg_match(
'/^[-+]{0,1}\d+\/\d+$/', $submittedValue)) {
 
 1285            $gap = $this->
getGap($gapIndex);
 
 1302        $solutionSubmit = array();
 
 1304        foreach ($submit as $key => $value) {
 
 1305            if (preg_match(
"/^gap_(\d+)/", $key, $matches)) {
 
 1307                if (strlen($value)) {
 
 1308                    $gap = $this->
getGap($matches[1]);
 
 1309                    if (is_object($gap)) {
 
 1310                        if (!(($gap->getType() == 
CLOZE_SELECT) && ($value == -1))) {
 
 1311                            if ($gap->getType() == 
CLOZE_NUMERIC && !is_numeric(str_replace(
",", 
".", $value))) {
 
 1314                                $value = str_replace(
",", 
".", $value);
 
 1316                            $solutionSubmit[trim($matches[1])] = $value;
 
 1323        return $solutionSubmit;
 
 1329        $solutionSubmit = array();
 
 1331        foreach ($submit as $key => $value) {
 
 1332            if (preg_match(
"/^gap_(\d+)/", $key, $matches)) {
 
 1334                if (strlen($value)) {
 
 1335                    $gap = $this->
getGap($matches[1]);
 
 1336                    if (is_object($gap)) {
 
 1337                        if (!(($gap->getType() == 
CLOZE_SELECT) && ($value == -1))) {
 
 1339                                $value = str_replace(
",", 
".", $value);
 
 1341                            $solutionSubmit[trim($matches[1])] = $value;
 
 1348        return $solutionSubmit;
 
 1369        if (is_null(
$pass)) {
 
 1370            include_once 
"./Modules/Test/classes/class.ilObjTest.php";
 
 1374        $entered_values = 0;
 
 1376        $this->
getProcessLocker()->executeUserSolutionUpdateLockOperation(
function () use (&$entered_values, $active_id, 
$pass, $authorized) {
 
 1381                if (strlen($value)) {
 
 1383                    if (is_object($gap)) {
 
 1384                        if (!(($gap->getType() == 
CLOZE_SELECT) && ($value == -1))) {
 
 1393        if ($entered_values) {
 
 1394            include_once(
"./Modules/Test/classes/class.ilObjAssessmentFolder.php");
 
 1399            include_once(
"./Modules/Test/classes/class.ilObjAssessmentFolder.php");
 
 1416        return "assClozeTest";
 
 1440        switch ($a_textgap_rating) {
 
 1448                $this->textgap_rating = $a_textgap_rating;
 
 1465        return ($this->identical_scoring) ? 1 : 0;
 
 1477        $this->identical_scoring = ($a_identical_scoring) ? 1 : 0;
 
 1488        return "qpl_qst_cloze";
 
 1499        return array(
"qpl_a_cloze",
'qpl_a_cloze_combi_res');
 
 1510        $this->fixedTextLength = $a_text_len;
 
 1535        $gap_max_points = 0;
 
 1536        if (array_key_exists($gap_index, $this->gaps)) {
 
 1537            $gap = &$this->gaps[$gap_index];
 
 1538            foreach ($gap->getItems($this->getShuffler()) as $answer) {
 
 1539                if ($answer->getPoints() > $gap_max_points) {
 
 1540                    $gap_max_points = $answer->getPoints();
 
 1554        return parent::getRTETextWithMediaObjects() . $this->
getClozeText();
 
 1568        $this->gap_combinations_exists = $value;
 
 1573        $this->gap_combinations = $value;
 
 1581        parent::setExportDetailsXLS($worksheet, $startrow, $active_id, 
$pass);
 
 1585        foreach ($this->
getGaps() as $gap_index => $gap) {
 
 1586            $worksheet->setCell($startrow + 
$i, 0, $this->lng->txt(
"gap") . 
" $i");
 
 1587            $worksheet->setBold($worksheet->getColumnCoord(0) . ($startrow + 
$i));
 
 1589            foreach ($solution as $solutionvalue) {
 
 1590                if ($gap_index == $solutionvalue[
"value1"]) {
 
 1591                    $string_escaping_org_value = $worksheet->getStringEscaping();
 
 1593                        $worksheet->setStringEscaping(
false);
 
 1595                        switch ($gap->getType()) {
 
 1597                                $worksheet->setCell($startrow + 
$i, 1, $gap->getItem($solutionvalue[
"value2"])->getAnswertext());
 
 1601                                $worksheet->setCell($startrow + 
$i, 1, $solutionvalue[
"value2"]);
 
 1605                        $worksheet->setStringEscaping($string_escaping_org_value);
 
 1612        return $startrow + 
$i + 1;
 
 1631        include_once(
"./Services/RTE/classes/class.ilRTE.php");
 
 1641            'onenotcorrect' => $this->
formatSAQuestion($this->feedbackOBJ->getGenericFeedbackTestPresentation($this->getId(), 
false)),
 
 1642            'allcorrect' => $this->formatSAQuestion($this->feedbackOBJ->getGenericFeedbackTestPresentation($this->getId(), 
true))
 
 1646        foreach ($this->
getGaps() as $key => $gap) {
 
 1648            foreach ($gap->getItems($this->getShuffler()) as $item) {
 
 1650                $jitem[
'points'] = $item->getPoints();
 
 1652                $jitem[
'order'] = $item->getOrder();
 
 1654                    $jitem[
'lowerbound'] = $item->getLowerBound();
 
 1655                    $jitem[
'upperbound'] = $item->getUpperBound();
 
 1657                    $jitem[
'value'] = trim($jitem[
'value']);
 
 1659                array_push($items, $jitem);
 
 1663                $jgap[
'size'] = $gap->getGapSize();
 
 1666            $jgap[
'shuffle'] = $gap->getShuffle();
 
 1667            $jgap[
'type'] = $gap->getType();
 
 1668            $jgap[
'item'] = $items;
 
 1670            array_push(
$gaps, $jgap);
 
 1688        require_once 
"./Modules/TestQuestionPool/classes/class.ilOperatorsExpressionMapping.php";
 
 1722        $maxStep = $this->lookupMaxStep($active_id, 
$pass);
 
 1724        if ($maxStep !== 
null) {
 
 1727                                SELECT sol.value1+1 as val, sol.value2, cloze.cloze_type 
 1728                                FROM tst_solutions sol 
 1729                                INNER JOIN qpl_a_cloze cloze ON cloze.gap_id = value1 AND cloze.question_fi = sol.question_fi 
 1730                                WHERE sol.active_fi = %s AND sol.pass = %s AND sol.question_fi = %s AND sol.step = %s 
 1731                                GROUP BY sol.solution_id, sol.value1+1, sol.value2, cloze.cloze_type 
 1733                array(
"integer", 
"integer", 
"integer",
"integer"),
 
 1734                array($active_id, 
$pass, $this->
getId(), $maxStep)
 
 1739                                SELECT sol.value1+1 as val, sol.value2, cloze.cloze_type 
 1740                                FROM tst_solutions sol 
 1741                                INNER JOIN qpl_a_cloze cloze ON cloze.gap_id = value1 AND cloze.question_fi = sol.question_fi 
 1742                                WHERE sol.active_fi = %s AND sol.pass = %s AND sol.question_fi = %s 
 1743                                GROUP BY sol.solution_id, sol.value1+1, sol.value2, cloze.cloze_type 
 1745                array(
"integer", 
"integer", 
"integer"),
 
 1751            if ($row[
"cloze_type"] == 1) {
 
 1754            $result->addKeyValue($row[
"val"], $row[
"value2"]);
 
 1788        if ($assClozeGapCombinationObj->combinationExistsForQid($this->getId())) {
 
 1789            $combinations_for_question = $assClozeGapCombinationObj->getCleanCombinationArray($this->
getId());
 
 1790            $gap_answers = array();
 
 1791            $gap_used_in_combination = array();
 
 1792            foreach ($user_result as $user_result_build_list) {
 
 1793                if (is_array($user_result_build_list)) {
 
 1794                    $gap_answers[$user_result_build_list[
'gap_id']] = $user_result_build_list[
'value'];
 
 1798            foreach ($combinations_for_question as $combination) {
 
 1799                foreach ($combination as $row_key => $row_answers) {
 
 1800                    $combination_fulfilled = 
true;
 
 1801                    $points_for_combination = $row_answers[
'points'];
 
 1802                    foreach ($row_answers as $gap_key => $combination_gap_answer) {
 
 1803                        if ($gap_key !== 
'points') {
 
 1804                            $gap_used_in_combination[$gap_key] = $gap_key;
 
 1806                        if ($combination_fulfilled && array_key_exists($gap_key, $gap_answers)) {
 
 1807                            switch ($combination_gap_answer[
'type']) {
 
 1809                                    $is_text_gap_correct = $this->
getTextgapPoints($gap_answers[$gap_key], $combination_gap_answer[
'answer'], 1);
 
 1810                                    if ($is_text_gap_correct != 1) {
 
 1811                                        $combination_fulfilled = 
false;
 
 1815                                    $answer = $this->gaps[$gap_key]->getItem($gap_answers[$gap_key]);
 
 1816                                    $answertext = $answer->getAnswertext();
 
 1817                                    if ($answertext != $combination_gap_answer[
'answer']) {
 
 1818                                        $combination_fulfilled = 
false;
 
 1822                                    $answer = $this->gaps[$gap_key]->getItem(0);
 
 1823                                    if ($combination_gap_answer[
'answer'] != 
'out_of_bound') {
 
 1824                                        $is_numeric_gap_correct = $this->
getNumericgapPoints($answer->getAnswertext(), $gap_answers[$gap_key], 1, $answer->getLowerBound(), $answer->getUpperBound());
 
 1825                                        if ($is_numeric_gap_correct != 1) {
 
 1826                                            $combination_fulfilled = 
false;
 
 1829                                        $wrong_is_the_new_right = $this->
getNumericgapPoints($answer->getAnswertext(), $gap_answers[$gap_key], 1, $answer->getLowerBound(), $answer->getUpperBound());
 
 1830                                        if ($wrong_is_the_new_right == 1) {
 
 1831                                            $combination_fulfilled = 
false;
 
 1837                            if ($gap_key !== 
'points') {
 
 1838                                $combination_fulfilled = 
false;
 
 1842                    if ($combination_fulfilled) {
 
 1843                        $points += $points_for_combination;
 
 1848        return array(
$points, $gap_used_in_combination);
 
 1857        if ($detailed === 
null) {
 
 1858            $detailed = array();
 
 1862        $combinations[1] = array();
 
 1863        if ($assClozeGapCombinationObj->combinationExistsForQid($this->getId())) {
 
 1868        $solution_values_text = array(); 
 
 1869        $solution_values_select = array(); 
 
 1870        $solution_values_numeric = array(); 
 
 1871        foreach ($user_result as $gap_id => $value) {
 
 1872            if (is_string($value)) {
 
 1873                $value = array(
"value" => $value);
 
 1876            if (array_key_exists($gap_id, $this->gaps) && !array_key_exists($gap_id, $combinations[1])) {
 
 1877                switch ($this->gaps[$gap_id]->getType()) {
 
 1880                        for ($order = 0; $order < $this->gaps[$gap_id]->getItemCount(); $order++) {
 
 1881                            $answer = $this->gaps[$gap_id]->getItem($order);
 
 1882                            $gotpoints = $this->
getTextgapPoints($answer->getAnswertext(), $value[
"value"], $answer->getPoints());
 
 1883                            if ($gotpoints > $gappoints) {
 
 1884                                $gappoints = $gotpoints;
 
 1889                            if ((in_array($value[
"value"], $solution_values_text)) && ($gappoints > 0)) {
 
 1894                        $detailed[$gap_id] = array(
"points" => $gappoints, 
"best" => ($this->
getMaximumGapPoints($gap_id) == $gappoints) ? 
true : 
false, 
"positive" => ($gappoints > 0) ? 
true : 
false);
 
 1895                        array_push($solution_values_text, $value[
"value"]);
 
 1899                        for ($order = 0; $order < $this->gaps[$gap_id]->getItemCount(); $order++) {
 
 1900                            $answer = $this->gaps[$gap_id]->getItem($order);
 
 1901                            $gotpoints = $this->
getNumericgapPoints($answer->getAnswertext(), $value[
"value"], $answer->getPoints(), $answer->getLowerBound(), $answer->getUpperBound());
 
 1902                            if ($gotpoints > $gappoints) {
 
 1903                                $gappoints = $gotpoints;
 
 1908                            include_once 
"./Services/Math/classes/class.EvalMath.php";
 
 1910                            $eval->suppress_errors = 
true;
 
 1911                            $found_value = 
false;
 
 1912                            foreach ($solution_values_numeric as $solval) {
 
 1913                                if ($eval->e($solval) == $eval->e($value[
"value"])) {
 
 1914                                    $found_value = 
true;
 
 1917                            if ($found_value && ($gappoints > 0)) {
 
 1922                        $detailed[$gap_id] = array(
"points" => $gappoints, 
"best" => ($this->
getMaximumGapPoints($gap_id) == $gappoints) ? 
true : 
false, 
"positive" => ($gappoints > 0) ? 
true : 
false);
 
 1923                        array_push($solution_values_numeric, $value[
"value"]);
 
 1926                        if ($value[
"value"] >= 0) {
 
 1927                            for ($order = 0; $order < $this->gaps[$gap_id]->getItemCount(); $order++) {
 
 1928                                $answer = $this->gaps[$gap_id]->getItem($order);
 
 1929                                if ($value[
"value"] == $answer->getOrder()) {
 
 1930                                    $answerpoints = $answer->getPoints();
 
 1933                                        if ((in_array($answer->getAnswertext(), $solution_values_select)) && ($answerpoints > 0)) {
 
 1938                                    $detailed[$gap_id] = array(
"points" => $answerpoints, 
"best" => ($this->
getMaximumGapPoints($gap_id) == $answerpoints) ? 
true : 
false, 
"positive" => ($answerpoints > 0) ? 
true : 
false);
 
 1939                                    array_push($solution_values_select, $answer->getAnswertext());
 
 1953        $userSolution = array();
 
 1956            $userSolution[$key] = array(
'gap_id' => $key, 
'value' => $val);
 
 1969        foreach ($userSolution as $value1 => $value2) {
 
 1970            if ($value1 == $gapIndex) {
 
 1971                $answerValue = $value2;
 
 1976        return $answerValue;
 
 1981        $gap = $this->
getGap($qIndex);
 
 1988            if ($item->getAnswertext() == $answerOptionValue) {
 
 1998        $gap = $this->
getGap($qIndex); 
 
 2001        $item->setOrder($gap->getItemCount());
 
 2003        $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.
setLifecycle(ilAssQuestionLifecycle $lifecycle)
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)
static getDraftInstance()
static getInstance($identifier)
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.
__construct(Container $dic, ilPlugin $plugin)
@inheritDoc