24 include_once
"./Modules/TestQuestionPool/classes/class.assQuestion.php";
25 include_once
"./Modules/Test/classes/inc.AssessmentConstants.php";
114 $this->start_tag =
"[gap]";
115 $this->end_tag =
"[/gap]";
116 $this->gaps = array();
118 $this->fixedTextLength =
"";
119 $this->identical_scoring = 1;
149 $text = preg_replace(
"/\[gap[^\]]*?\]/",
"[gap]", $text);
150 $text = preg_replace(
"/<gap([^>]*?)>/",
"[gap]", $text);
151 $text = str_replace(
"</gap>",
"[/gap]", $text);
172 $this->
setId($question_id);
185 include_once(
"./Services/RTE/classes/class.ilRTE.php");
191 include_once
"./Modules/TestQuestionPool/classes/class.assAnswerCloze.php";
192 include_once
"./Modules/TestQuestionPool/classes/class.assClozeGap.php";
193 $result = $ilDB->queryF(
"SELECT * FROM qpl_a_cloze WHERE question_fi = %s ORDER BY gap_id, aorder ASC",
199 $this->gaps = array();
202 switch (
$data[
"cloze_type"])
205 if (!array_key_exists(
$data[
"gap_id"], $this->gaps))
214 $this->gaps[
$data[
"gap_id"]]->addItem($answer);
217 if (!array_key_exists(
$data[
"gap_id"], $this->gaps))
220 $this->gaps[$data[
"gap_id"]]->setShuffle($data[
"shuffle"]);
227 $this->gaps[
$data[
"gap_id"]]->addItem($answer);
230 if (!array_key_exists(
$data[
"gap_id"], $this->gaps))
239 $answer->setLowerBound(
$data[
"lowerlimit"]);
240 $answer->setUpperBound(
$data[
"upperlimit"]);
241 $this->gaps[
$data[
"gap_id"]]->addItem($answer);
262 include_once
"./Services/Math/classes/class.EvalMath.php";
264 $eval->suppress_errors = TRUE;
267 $affectedRows = $ilDB->manipulateF(
"DELETE FROM " . $this->
getAdditionalTableName() .
" WHERE question_fi = %s",
269 array($this->
getId())
273 $affectedRows = $ilDB->manipulateF(
"INSERT INTO " . $this->
getAdditionalTableName() .
" (question_fi, textgap_rating, identical_scoring, fixed_textlen) VALUES (%s, %s, %s, %s)",
288 $affectedRows = $ilDB->manipulateF(
"DELETE FROM qpl_a_cloze WHERE question_fi = %s",
290 array($this->
getId())
293 foreach ($this->gaps as $key => $gap)
295 foreach ($gap->getItems() as $item)
298 switch ($gap->getType())
301 $next_id = $ilDB->nextId(
'qpl_a_cloze');
302 $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)",
316 strlen($item->getAnswertext()) ? $item->getAnswertext() :
"",
324 $next_id = $ilDB->nextId(
'qpl_a_cloze');
325 $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)",
340 strlen($item->getAnswertext()) ? $item->getAnswertext() :
"",
344 ($gap->getShuffle()) ?
"1" :
"0"
349 $next_id = $ilDB->nextId(
'qpl_a_cloze');
350 $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)",
366 strlen($item->getAnswertext()) ? $item->getAnswertext() :
"",
370 ($eval->e($item->getLowerBound() !== FALSE) && strlen($item->getLowerBound()) > 0) ? $item->getLowerBound() : $item->getAnswertext(),
371 ($eval->e($item->getUpperBound() !== FALSE) && strlen($item->getUpperBound()) > 0) ? $item->getUpperBound() : $item->getAnswertext()
401 $this->gaps = array();
415 $this->gaps = array();
417 $this->question = $cloze_text;
489 include_once
"./Modules/TestQuestionPool/classes/class.assClozeGap.php";
490 include_once
"./Modules/TestQuestionPool/classes/class.assAnswerCloze.php";
491 $search_pattern =
"|\[gap\](.*?)\[/gap\]|i";
492 preg_match_all($search_pattern, $this->
getClozeText(), $found);
493 $this->gaps = array();
494 if (count($found[0]))
496 foreach ($found[1] as $gap_index => $answers)
500 $textparams = preg_split(
"/(?<!\\\\),/", $answers);
501 foreach ($textparams as $key => $value)
504 $gap->addItem($answer);
506 $this->gaps[$gap_index] = $gap;
518 if (array_key_exists($gap_index, $this->gaps))
520 $this->gaps[$gap_index]->setType($gap_type);
535 if (array_key_exists($gap_index, $this->gaps))
537 $this->gaps[$gap_index]->setShuffle(
$shuffle);
549 foreach ($this->gaps as $gap_index => $gap)
551 $this->gaps[$gap_index]->clearItems();
564 if (is_array($this->gaps))
566 return count($this->gaps);
586 if (array_key_exists($gap_index, $this->gaps))
591 $answer = str_replace(
",",
".", $answer);
593 $this->gaps[$gap_index]->addItem(
new assAnswerCloze($answer, 0, $order));
607 if (array_key_exists($gap_index, $this->gaps))
609 return $this->gaps[$gap_index];
629 if (array_key_exists($gap_index, $this->gaps))
631 $this->gaps[$gap_index]->setItemPoints($order,
$points);
645 if (array_key_exists($gap_index, $this->gaps))
647 include_once
"./Modules/TestQuestionPool/classes/class.assAnswerCloze.php";
651 $this->gaps[$gap_index]->getItemCount()
653 $this->gaps[$gap_index]->addItem($answer);
667 $this->gaps[$index] = $gap;
682 if (array_key_exists($gap_index, $this->gaps))
684 $this->gaps[$gap_index]->setItemLowerBound($order, $bound);
700 if (array_key_exists($gap_index, $this->gaps))
702 $this->gaps[$gap_index]->setItemUpperBound($order, $bound);
715 foreach ($this->gaps as $gap_index => $gap)
720 foreach ($gap->getItems() as $item)
722 if ($item->getPoints() > $gap_max_points)
724 $gap_max_points = $item->getPoints();
732 foreach ($gap->getItems() as $item)
734 if ($item->getPoints() > $srpoints)
736 $srpoints = $item->getPoints();
744 foreach ($gap->getItems() as $item)
746 if ($item->getPoints() > $numpoints)
748 $numpoints = $item->getPoints();
770 $this_id = $this->
getId();
772 if( (
int)$testObjId > 0 )
778 include_once (
"./Modules/TestQuestionPool/classes/class.assQuestion.php");
782 if( (
int)$testObjId > 0 )
784 $clone->setObjId($testObjId);
809 $clone->copyPageOfQuestion($this_id);
811 $clone->copyXHTMLMediaObjectsOfQuestion($this_id);
813 $clone->duplicateFeedbackGeneric($this_id);
815 $clone->onDuplicate($thisObjId, $this_id, $clone->getObjId(), $clone->getId());
817 return $clone->getId();
827 if ($this->
getId() <= 0)
833 include_once (
"./Modules/TestQuestionPool/classes/class.assQuestion.php");
836 $source_questionpool = $this->
getObjId();
837 $clone->setObjId($target_questionpool);
852 return $clone->getId();
863 foreach ($this->
getGaps() as $gap_index => $gap)
866 foreach ($gap->getItemsRaw() as $item)
868 array_push($answers, str_replace(
",",
"\\,", $item->getAnswerText()));
870 $output = preg_replace(
"/\[gap\].*?\[\/gap\]/",
"[_gap]" . $this->
prepareTextareaOutput(join(
",", $answers),
true) .
"[/_gap]", $output, 1);
872 $output = str_replace(
"_gap]",
"gap]", $output);
873 $this->question = $output;
887 if (array_key_exists($gap_index, $this->gaps))
889 if ($this->gaps[$gap_index]->getItemCount() == 1)
897 $this->gaps[$gap_index]->deleteItem($answer_index);
913 if (array_key_exists($gap_index, $this->gaps))
916 foreach ($this->
getGaps() as $replace_gap_index => $gap)
919 foreach ($gap->getItemsRaw() as $item)
921 array_push($answers, str_replace(
",",
"\\,", $item->getAnswerText()));
923 if ($replace_gap_index == $gap_index)
925 $output = preg_replace(
"/\[gap\].*?\[\/gap\]/",
"", $output, 1);
929 $output = preg_replace(
"/\[gap\].*?\[\/gap\]/",
"[_gap]" . join(
",", $answers) .
"[/_gap]", $output, 1);
932 $output = str_replace(
"_gap]",
"gap]", $output);
933 $this->question = $output;
934 unset($this->gaps[$gap_index]);
935 $this->gaps = array_values($this->gaps);
950 include_once
"./Services/Utilities/classes/class.ilStr.php";
959 if (strcmp($a_original, $a_entered) == 0)
$result = $max_points;
962 if (levenshtein($a_original, $a_entered) <= 1)
$result = $max_points;
965 if (levenshtein($a_original, $a_entered) <= 2)
$result = $max_points;
968 if (levenshtein($a_original, $a_entered) <= 3)
$result = $max_points;
971 if (levenshtein($a_original, $a_entered) <= 4)
$result = $max_points;
974 if (levenshtein($a_original, $a_entered) <= 5)
$result = $max_points;
991 if( !is_numeric($a_entered) )
996 include_once
"./Services/Math/classes/class.EvalMath.php";
998 $eval->suppress_errors = TRUE;
1000 if (($eval->e($lowerBound) !== FALSE) && ($eval->e($upperBound) !== FALSE))
1002 if (($eval->e($a_entered) >= $eval->e($lowerBound)) && ($eval->e($a_entered) <= $eval->e($upperBound)))
$result = $max_points;
1004 else if ($eval->e($lowerBound) !== FALSE)
1006 if (($eval->e($a_entered) >= $eval->e($lowerBound)) && ($eval->e($a_entered) <= $eval->e($a_original)))
$result = $max_points;
1008 else if ($eval->e($upperBound) !== FALSE)
1010 if (($eval->e($a_entered) >= $eval->e($a_original)) && ($eval->e($a_entered) <= $eval->e($upperBound)))
$result = $max_points;
1014 if ($eval->e($a_entered) == $eval->e($a_original))
$result = $max_points;
1032 $found_value1 = array();
1033 $found_value2 = array();
1034 $detailed = array();
1039 $result = $ilDB->queryF(
"SELECT * FROM tst_solutions WHERE active_fi = %s AND question_fi = %s AND pass = %s",
1051 $user_result = array();
1054 if (strcmp(
$data[
"value2"],
"") != 0)
1056 $user_result[
$data[
"value1"]] = array(
1057 "gap_id" => $data[
"value1"],
1058 "value" => $data[
"value2"]
1064 $solution_values_text = array();
1065 $solution_values_select = array();
1066 $solution_values_numeric = array();
1067 foreach ($user_result as $gap_id => $value)
1069 if (array_key_exists($gap_id, $this->gaps))
1071 switch ($this->gaps[$gap_id]->getType())
1075 for ($order = 0; $order < $this->gaps[$gap_id]->getItemCount(); $order++)
1077 $answer = $this->gaps[$gap_id]->getItem($order);
1078 $gotpoints = $this->
getTextgapPoints($answer->getAnswertext(), $value[
"value"], $answer->getPoints());
1079 if ($gotpoints > $gappoints) $gappoints = $gotpoints;
1084 if ((in_array($value[
"value"], $solution_values_text)) && ($gappoints > 0))
1090 $detailed[$gap_id] = array(
"points" =>$gappoints,
"best" => ($this->
getMaximumGapPoints($gap_id) == $gappoints) ? TRUE : FALSE,
"positive" => ($gappoints > 0) ? TRUE : FALSE);
1091 array_push($solution_values_text, $value[
"value"]);
1095 for ($order = 0; $order < $this->gaps[$gap_id]->getItemCount(); $order++)
1097 $answer = $this->gaps[$gap_id]->getItem($order);
1098 $gotpoints = $this->
getNumericgapPoints($answer->getAnswertext(), $value[
"value"], $answer->getPoints(), $answer->getLowerBound(), $answer->getUpperBound());
1099 if ($gotpoints > $gappoints) $gappoints = $gotpoints;
1104 include_once
"./Services/Math/classes/class.EvalMath.php";
1106 $eval->suppress_errors = TRUE;
1107 $found_value = FALSE;
1108 foreach ($solution_values_numeric as $solval)
1110 if ($eval->e($solval) == $eval->e($value[
"value"]))
1112 $found_value = TRUE;
1115 if ($found_value && ($gappoints > 0))
1121 $detailed[$gap_id] = array(
"points" =>$gappoints,
"best" => ($this->
getMaximumGapPoints($gap_id) == $gappoints) ? TRUE : FALSE,
"positive" => ($gappoints > 0) ? TRUE : FALSE);
1122 array_push($solution_values_numeric, $value[
"value"]);
1125 if ($value[
"value"] >= 0)
1127 for ($order = 0; $order < $this->gaps[$gap_id]->getItemCount(); $order++)
1129 $answer = $this->gaps[$gap_id]->getItem($order);
1130 if ($value[
"value"] == $answer->getOrder())
1132 $answerpoints = $answer->getPoints();
1136 if ((in_array($answer->getAnswertext(), $solution_values_select)) && ($answerpoints > 0))
1142 $detailed[$gap_id] = array(
"points" =>$answerpoints,
"best" => ($this->
getMaximumGapPoints($gap_id) == $answerpoints) ? TRUE : FALSE,
"positive" => ($answerpoints > 0) ? TRUE : FALSE);
1143 array_push($solution_values_select, $answer->getAnswertext());
1176 include_once
"./Modules/Test/classes/class.ilObjTest.php";
1180 $affectedRows = $ilDB->manipulateF(
"DELETE FROM tst_solutions WHERE active_fi = %s AND question_fi = %s AND pass = %s",
1193 $entered_values = 0;
1194 foreach (
$_POST as $key => $value)
1196 if (preg_match(
"/^gap_(\d+)/", $key, $matches))
1201 $gap = $this->
getGap($matches[1]);
1202 if (is_object($gap))
1204 if (!(($gap->getType() ==
CLOZE_SELECT) && ($value == -1)))
1208 $value = str_replace(
",",
".", $value);
1210 $next_id = $ilDB->nextId(
"tst_solutions");
1211 $affectedRows = $ilDB->insert(
"tst_solutions", array(
1212 "solution_id" => array(
"integer", $next_id),
1213 "active_fi" => array(
"integer", $active_id),
1214 "question_fi" => array(
"integer", $this->
getId()),
1215 "value1" => array(
"clob", trim($matches[1])),
1216 "value2" => array(
"clob", trim($value)),
1217 "pass" => array(
"integer",
$pass),
1218 "tstamp" => array(
"integer", time())
1226 if ($entered_values)
1228 include_once (
"./Modules/Test/classes/class.ilObjAssessmentFolder.php");
1236 include_once (
"./Modules/Test/classes/class.ilObjAssessmentFolder.php");
1254 return "assClozeTest";
1278 switch ($a_textgap_rating)
1287 $this->textgap_rating = $a_textgap_rating;
1304 return ($this->identical_scoring) ? 1 : 0;
1316 $this->identical_scoring = ($a_identical_scoring) ? 1 : 0;
1327 return "qpl_qst_cloze";
1338 return "qpl_a_cloze";
1349 $this->fixedTextLength = $a_text_len;
1374 if (array_key_exists($gap_index, $this->gaps))
1376 $gap =& $this->gaps[$gap_index];
1377 foreach ($gap->getItems() as $answer)
1379 if ($answer->getPoints() > $gap_max_points)
1381 $gap_max_points = $answer->getPoints();
1412 include_once (
"./Services/Excel/classes/class.ilExcelUtils.php");
1417 foreach ($this->
getGaps() as $gap_index => $gap)
1421 foreach ($solution as $solutionvalue)
1423 if ($gap_index == $solutionvalue[
"value1"])
1425 switch ($gap->getType())
1428 $worksheet->writeString($startrow + $i, 1, $gap->getItem($solutionvalue[
"value2"])->getAnswertext());
1432 $worksheet->writeString($startrow + $i, 1, $solutionvalue[
"value2"]);
1439 return $startrow + $i + 1;
1447 include_once(
"./Services/RTE/classes/class.ilRTE.php");
1460 foreach ($this->
getGaps() as $key => $gap)
1463 foreach ($gap->getItems() as $item)
1466 $jitem[
'points'] = $item->getPoints();
1467 $jitem[
'value'] = $item->getAnswertext();
1468 $jitem[
'order'] = $item->getOrder();
1471 $jitem[
'lowerbound'] = $item->getLowerBound();
1472 $jitem[
'upperbound'] = $item->getUpperBound();
1474 array_push($items, $jitem);
1476 $jgap[
'shuffle'] = $gap->getShuffle();
1477 $jgap[
'type'] = $gap->getType();
1478 $jgap[
'item'] = $items;
1479 array_push(
$gaps, $jgap);