5 include_once
"./Modules/TestQuestionPool/classes/class.assQuestion.php";
6 include_once
"./Modules/Test/classes/inc.AssessmentConstants.php";
99 $this->start_tag =
"[gap]";
100 $this->end_tag =
"[/gap]";
101 $this->gaps = array();
103 $this->fixedTextLength =
"";
104 $this->identical_scoring = 1;
134 $text = preg_replace(
"/\[gap[^\]]*?\]/",
"[gap]", $text);
135 $text = preg_replace(
"/<gap([^>]*?)>/",
"[gap]", $text);
136 $text = str_replace(
"</gap>",
"[/gap]", $text);
157 $this->
setId($question_id);
170 include_once(
"./Services/RTE/classes/class.ilRTE.php");
176 include_once
"./Modules/TestQuestionPool/classes/class.assAnswerCloze.php";
177 include_once
"./Modules/TestQuestionPool/classes/class.assClozeGap.php";
178 $result = $ilDB->queryF(
"SELECT * FROM qpl_a_cloze WHERE question_fi = %s ORDER BY gap_id, aorder ASC",
184 $this->gaps = array();
187 switch (
$data[
"cloze_type"])
190 if (!array_key_exists(
$data[
"gap_id"], $this->gaps))
199 $this->gaps[
$data[
"gap_id"]]->addItem($answer);
202 if (!array_key_exists(
$data[
"gap_id"], $this->gaps))
205 $this->gaps[$data[
"gap_id"]]->setShuffle($data[
"shuffle"]);
212 $this->gaps[
$data[
"gap_id"]]->addItem($answer);
215 if (!array_key_exists(
$data[
"gap_id"], $this->gaps))
224 $answer->setLowerBound(
$data[
"lowerlimit"]);
225 $answer->setUpperBound(
$data[
"upperlimit"]);
226 $this->gaps[
$data[
"gap_id"]]->addItem($answer);
247 include_once
"./Services/Math/classes/class.EvalMath.php";
249 $eval->suppress_errors = TRUE;
252 $affectedRows = $ilDB->manipulateF(
"DELETE FROM " . $this->
getAdditionalTableName() .
" WHERE question_fi = %s",
254 array($this->
getId())
258 $affectedRows = $ilDB->manipulateF(
"INSERT INTO " . $this->
getAdditionalTableName() .
" (question_fi, textgap_rating, identical_scoring, fixed_textlen) VALUES (%s, %s, %s, %s)",
273 $affectedRows = $ilDB->manipulateF(
"DELETE FROM qpl_a_cloze WHERE question_fi = %s",
275 array($this->
getId())
278 foreach ($this->gaps as $key => $gap)
280 foreach ($gap->getItems() as $item)
283 switch ($gap->getType())
286 $next_id = $ilDB->nextId(
'qpl_a_cloze');
287 $affectedRows = $ilDB->manipulateF(
"INSERT INTO qpl_a_cloze (answer_id, question_fi, gap_id, answertext, points, aorder, cloze_type) VALUES (%s, %s, %s, %s, %s, %s, %s)",
301 strlen($item->getAnswertext()) ? $item->getAnswertext() :
"",
309 $next_id = $ilDB->nextId(
'qpl_a_cloze');
310 $affectedRows = $ilDB->manipulateF(
"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)",
325 strlen($item->getAnswertext()) ? $item->getAnswertext() :
"",
329 ($gap->getShuffle()) ?
"1" :
"0"
334 $next_id = $ilDB->nextId(
'qpl_a_cloze');
335 $affectedRows = $ilDB->manipulateF(
"INSERT INTO qpl_a_cloze (answer_id, question_fi, gap_id, answertext, points, aorder, cloze_type, lowerlimit, upperlimit) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s)",
351 strlen($item->getAnswertext()) ? $item->getAnswertext() :
"",
355 ($eval->e($item->getLowerBound() !== FALSE) && strlen($item->getLowerBound()) > 0) ? $item->getLowerBound() : $item->getAnswertext(),
356 ($eval->e($item->getUpperBound() !== FALSE) && strlen($item->getUpperBound()) > 0) ? $item->getUpperBound() : $item->getAnswertext()
386 $this->gaps = array();
400 $this->gaps = array();
402 $this->question = $cloze_text;
474 include_once
"./Modules/TestQuestionPool/classes/class.assClozeGap.php";
475 include_once
"./Modules/TestQuestionPool/classes/class.assAnswerCloze.php";
476 $search_pattern =
"|\[gap\](.*?)\[/gap\]|i";
477 preg_match_all($search_pattern, $this->
getClozeText(), $found);
478 $this->gaps = array();
479 if (count($found[0]))
481 foreach ($found[1] as $gap_index => $answers)
485 $textparams = preg_split(
"/(?<!\\\\),/", $answers);
486 foreach ($textparams as $key => $value)
489 $gap->addItem($answer);
491 $this->gaps[$gap_index] = $gap;
503 if (array_key_exists($gap_index, $this->gaps))
505 $this->gaps[$gap_index]->setType($gap_type);
520 if (array_key_exists($gap_index, $this->gaps))
522 $this->gaps[$gap_index]->setShuffle(
$shuffle);
534 foreach ($this->gaps as $gap_index => $gap)
536 $this->gaps[$gap_index]->clearItems();
549 if (is_array($this->gaps))
551 return count($this->gaps);
571 if (array_key_exists($gap_index, $this->gaps))
576 $answer = str_replace(
",",
".", $answer);
578 $this->gaps[$gap_index]->addItem(
new assAnswerCloze($answer, 0, $order));
592 if (array_key_exists($gap_index, $this->gaps))
594 return $this->gaps[$gap_index];
614 if (array_key_exists($gap_index, $this->gaps))
616 $this->gaps[$gap_index]->setItemPoints($order,
$points);
630 if (array_key_exists($gap_index, $this->gaps))
632 include_once
"./Modules/TestQuestionPool/classes/class.assAnswerCloze.php";
636 $this->gaps[$gap_index]->getItemCount()
638 $this->gaps[$gap_index]->addItem($answer);
652 $this->gaps[$index] = $gap;
667 if (array_key_exists($gap_index, $this->gaps))
669 $this->gaps[$gap_index]->setItemLowerBound($order, $bound);
685 if (array_key_exists($gap_index, $this->gaps))
687 $this->gaps[$gap_index]->setItemUpperBound($order, $bound);
700 foreach ($this->gaps as $gap_index => $gap)
705 foreach ($gap->getItems() as $item)
707 if ($item->getPoints() > $gap_max_points)
709 $gap_max_points = $item->getPoints();
717 foreach ($gap->getItems() as $item)
719 if ($item->getPoints() > $srpoints)
721 $srpoints = $item->getPoints();
729 foreach ($gap->getItems() as $item)
731 if ($item->getPoints() > $numpoints)
733 $numpoints = $item->getPoints();
755 $this_id = $this->
getId();
757 if( (
int)$testObjId > 0 )
763 include_once (
"./Modules/TestQuestionPool/classes/class.assQuestion.php");
767 if( (
int)$testObjId > 0 )
769 $clone->setObjId($testObjId);
794 $clone->copyPageOfQuestion($this_id);
796 $clone->copyXHTMLMediaObjectsOfQuestion($this_id);
798 $clone->duplicateGenericFeedback($this_id);
800 $clone->duplicateSpecificFeedback($this_id);
802 $clone->onDuplicate($thisObjId, $this_id, $clone->getObjId(), $clone->getId());
804 return $clone->getId();
817 $result = $ilDB->queryF(
"SELECT * FROM qpl_fb_cloze WHERE question_fi = %s",
825 $next_id = $ilDB->nextId(
'qpl_fb_cloze');
828 $ilDB->insert(
'qpl_fb_cloze', array(
829 'feedback_id' => array(
'integer', $next_id ),
830 'question_fi' => array(
'integer', $this->
getId() ),
831 'answer' => array(
'integer',
$row[
"answer"] ),
832 'feedback' => array(
'clob',
$row[
"feedback"] ),
833 'tstamp' => array(
'integer', time() ),
847 if ($this->
getId() <= 0)
853 include_once (
"./Modules/TestQuestionPool/classes/class.assQuestion.php");
856 $source_questionpool = $this->
getObjId();
857 $clone->setObjId($target_questionpool);
874 return $clone->getId();
885 foreach ($this->
getGaps() as $gap_index => $gap)
888 foreach ($gap->getItemsRaw() as $item)
890 array_push($answers, str_replace(
",",
"\\,", $item->getAnswerText()));
892 $output = preg_replace(
"/\[gap\].*?\[\/gap\]/",
"[_gap]" . $this->
prepareTextareaOutput(join(
",", $answers),
true) .
"[/_gap]", $output, 1);
894 $output = str_replace(
"_gap]",
"gap]", $output);
895 $this->question = $output;
909 if (array_key_exists($gap_index, $this->gaps))
911 if ($this->gaps[$gap_index]->getItemCount() == 1)
919 $this->gaps[$gap_index]->deleteItem($answer_index);
935 if (array_key_exists($gap_index, $this->gaps))
938 foreach ($this->
getGaps() as $replace_gap_index => $gap)
941 foreach ($gap->getItemsRaw() as $item)
943 array_push($answers, str_replace(
",",
"\\,", $item->getAnswerText()));
945 if ($replace_gap_index == $gap_index)
947 $output = preg_replace(
"/\[gap\].*?\[\/gap\]/",
"", $output, 1);
951 $output = preg_replace(
"/\[gap\].*?\[\/gap\]/",
"[_gap]" . join(
",", $answers) .
"[/_gap]", $output, 1);
954 $output = str_replace(
"_gap]",
"gap]", $output);
955 $this->question = $output;
956 unset($this->gaps[$gap_index]);
957 $this->gaps = array_values($this->gaps);
972 include_once
"./Services/Utilities/classes/class.ilStr.php";
981 if (strcmp($a_original, $a_entered) == 0)
$result = $max_points;
984 if (levenshtein($a_original, $a_entered) <= 1)
$result = $max_points;
987 if (levenshtein($a_original, $a_entered) <= 2)
$result = $max_points;
990 if (levenshtein($a_original, $a_entered) <= 3)
$result = $max_points;
993 if (levenshtein($a_original, $a_entered) <= 4)
$result = $max_points;
996 if (levenshtein($a_original, $a_entered) <= 5)
$result = $max_points;
1013 if( !is_numeric($a_entered) )
1018 include_once
"./Services/Math/classes/class.EvalMath.php";
1020 $eval->suppress_errors = TRUE;
1022 if (($eval->e($lowerBound) !== FALSE) && ($eval->e($upperBound) !== FALSE))
1024 if (($eval->e($a_entered) >= $eval->e($lowerBound)) && ($eval->e($a_entered) <= $eval->e($upperBound)))
$result = $max_points;
1026 else if ($eval->e($lowerBound) !== FALSE)
1028 if (($eval->e($a_entered) >= $eval->e($lowerBound)) && ($eval->e($a_entered) <= $eval->e($a_original)))
$result = $max_points;
1030 else if ($eval->e($upperBound) !== FALSE)
1032 if (($eval->e($a_entered) >= $eval->e($a_original)) && ($eval->e($a_entered) <= $eval->e($upperBound)))
$result = $max_points;
1036 if ($eval->e($a_entered) == $eval->e($a_original))
$result = $max_points;
1055 $found_value1 = array();
1056 $found_value2 = array();
1057 $detailed = array();
1062 $result = $ilDB->queryF(
"SELECT * FROM tst_solutions WHERE active_fi = %s AND question_fi = %s AND pass = %s",
1074 $user_result = array();
1077 if (strcmp(
$data[
"value2"],
"") != 0)
1079 $user_result[
$data[
"value1"]] = array(
1080 "gap_id" => $data[
"value1"],
1081 "value" => $data[
"value2"]
1086 ksort($user_result);
1090 $solution_values_text = array();
1091 $solution_values_select = array();
1092 $solution_values_numeric = array();
1093 foreach ($user_result as $gap_id => $value)
1095 if (array_key_exists($gap_id, $this->gaps))
1097 switch ($this->gaps[$gap_id]->getType())
1101 for ($order = 0; $order < $this->gaps[$gap_id]->getItemCount(); $order++)
1103 $answer = $this->gaps[$gap_id]->getItem($order);
1104 $gotpoints = $this->
getTextgapPoints($answer->getAnswertext(), $value[
"value"], $answer->getPoints());
1105 if ($gotpoints > $gappoints) $gappoints = $gotpoints;
1110 if ((in_array($value[
"value"], $solution_values_text)) && ($gappoints > 0))
1116 $detailed[$gap_id] = array(
"points" =>$gappoints,
"best" => ($this->
getMaximumGapPoints($gap_id) == $gappoints) ? TRUE : FALSE,
"positive" => ($gappoints > 0) ? TRUE : FALSE);
1117 array_push($solution_values_text, $value[
"value"]);
1121 for ($order = 0; $order < $this->gaps[$gap_id]->getItemCount(); $order++)
1123 $answer = $this->gaps[$gap_id]->getItem($order);
1124 $gotpoints = $this->
getNumericgapPoints($answer->getAnswertext(), $value[
"value"], $answer->getPoints(), $answer->getLowerBound(), $answer->getUpperBound());
1125 if ($gotpoints > $gappoints) $gappoints = $gotpoints;
1130 include_once
"./Services/Math/classes/class.EvalMath.php";
1132 $eval->suppress_errors = TRUE;
1133 $found_value = FALSE;
1134 foreach ($solution_values_numeric as $solval)
1136 if ($eval->e($solval) == $eval->e($value[
"value"]))
1138 $found_value = TRUE;
1141 if ($found_value && ($gappoints > 0))
1147 $detailed[$gap_id] = array(
"points" =>$gappoints,
"best" => ($this->
getMaximumGapPoints($gap_id) == $gappoints) ? TRUE : FALSE,
"positive" => ($gappoints > 0) ? TRUE : FALSE);
1148 array_push($solution_values_numeric, $value[
"value"]);
1151 if ($value[
"value"] >= 0)
1153 for ($order = 0; $order < $this->gaps[$gap_id]->getItemCount(); $order++)
1155 $answer = $this->gaps[$gap_id]->getItem($order);
1156 if ($value[
"value"] == $answer->getOrder())
1158 $answerpoints = $answer->getPoints();
1162 if ((in_array($answer->getAnswertext(), $solution_values_select)) && ($answerpoints > 0))
1168 $detailed[$gap_id] = array(
"points" =>$answerpoints,
"best" => ($this->
getMaximumGapPoints($gap_id) == $answerpoints) ? TRUE : FALSE,
"positive" => ($answerpoints > 0) ? TRUE : FALSE);
1169 array_push($solution_values_select, $answer->getAnswertext());
1201 include_once
"./Modules/Test/classes/class.ilObjTest.php";
1205 $affectedRows = $ilDB->manipulateF(
"DELETE FROM tst_solutions WHERE active_fi = %s AND question_fi = %s AND pass = %s",
1218 $entered_values = 0;
1219 foreach (
$_POST as $key => $value)
1221 if (preg_match(
"/^gap_(\d+)/", $key, $matches))
1226 $gap = $this->
getGap($matches[1]);
1227 if (is_object($gap))
1229 if (!(($gap->getType() ==
CLOZE_SELECT) && ($value == -1)))
1233 $value = str_replace(
",",
".", $value);
1235 $next_id = $ilDB->nextId(
"tst_solutions");
1236 $affectedRows = $ilDB->insert(
"tst_solutions", array(
1237 "solution_id" => array(
"integer", $next_id),
1238 "active_fi" => array(
"integer", $active_id),
1239 "question_fi" => array(
"integer", $this->
getId()),
1240 "value1" => array(
"clob", trim($matches[1])),
1241 "value2" => array(
"clob", trim($value)),
1242 "pass" => array(
"integer",
$pass),
1243 "tstamp" => array(
"integer", time())
1251 if ($entered_values)
1253 include_once (
"./Modules/Test/classes/class.ilObjAssessmentFolder.php");
1261 include_once (
"./Modules/Test/classes/class.ilObjAssessmentFolder.php");
1292 return "assClozeTest";
1316 switch ($a_textgap_rating)
1325 $this->textgap_rating = $a_textgap_rating;
1342 return ($this->identical_scoring) ? 1 : 0;
1354 $this->identical_scoring = ($a_identical_scoring) ? 1 : 0;
1365 return "qpl_qst_cloze";
1376 return "qpl_a_cloze";
1387 $this->fixedTextLength = $a_text_len;
1412 if (array_key_exists($gap_index, $this->gaps))
1414 $gap =& $this->gaps[$gap_index];
1415 foreach ($gap->getItems() as $answer)
1417 if ($answer->getPoints() > $gap_max_points)
1419 $gap_max_points = $answer->getPoints();
1450 include_once (
"./Services/Excel/classes/class.ilExcelUtils.php");
1455 foreach ($this->
getGaps() as $gap_index => $gap)
1459 foreach ($solution as $solutionvalue)
1461 if ($gap_index == $solutionvalue[
"value1"])
1463 switch ($gap->getType())
1466 $worksheet->writeString($startrow + $i, 1, $gap->getItem($solutionvalue[
"value2"])->getAnswertext());
1470 $worksheet->writeString($startrow + $i, 1, $solutionvalue[
"value2"]);
1477 return $startrow + $i + 1;
1485 include_once(
"./Services/RTE/classes/class.ilRTE.php");
1498 foreach ($this->
getGaps() as $key => $gap)
1501 foreach ($gap->getItems() as $item)
1504 $jitem[
'points'] = $item->getPoints();
1505 $jitem[
'value'] = $item->getAnswertext();
1506 $jitem[
'order'] = $item->getOrder();
1509 $jitem[
'lowerbound'] = $item->getLowerBound();
1510 $jitem[
'upperbound'] = $item->getUpperBound();
1512 array_push($items, $jitem);
1514 $jgap[
'shuffle'] = $gap->getShuffle();
1515 $jgap[
'type'] = $gap->getType();
1516 $jgap[
'item'] = $items;
1517 array_push(
$gaps, $jgap);
1533 function saveFeedbackSingleAnswer($answer_index, $feedback)
1537 $affectedRows = $ilDB->manipulateF(
"DELETE FROM qpl_fb_cloze WHERE question_fi = %s AND answer = %s",
1538 array(
'integer',
'integer'),
1539 array($this->
getId(), $answer_index)
1541 if (strlen($feedback))
1543 include_once(
"./Services/RTE/classes/class.ilRTE.php");
1544 $next_id = $ilDB->nextId(
'qpl_fb_cloze');
1546 $ilDB->insert(
'qpl_fb_cloze', array(
1547 'feedback_id' => array(
'integer', $next_id ),
1548 'question_fi' => array(
'integer', $this->
getId() ),
1549 'answer' => array(
'integer', $answer_index ),
1551 'tstamp' => array(
'integer', time() ),
1569 $result = $ilDB->queryF(
"SELECT * FROM qpl_fb_cloze WHERE question_fi = %s AND answer = %s",
1570 array(
'integer',
'integer'),
1571 array($this->
getId(), $answer_index)
1576 include_once(
"./Services/RTE/classes/class.ilRTE.php");
1588 WHERE question_fi = %s',