4require_once
'./Modules/TestQuestionPool/classes/class.assQuestion.php';
5require_once
'./Modules/Test/classes/inc.AssessmentConstants.php';
6require_once
'./Modules/TestQuestionPool/interfaces/interface.ilObjQuestionScoringAdjustable.php';
7require_once
'./Modules/TestQuestionPool/interfaces/interface.ilObjAnswerScoringAdjustable.php';
8require_once
'./Modules/TestQuestionPool/interfaces/interface.iQuestionCondition.php';
9require_once
'./Modules/TestQuestionPool/classes/class.ilUserQuestionResult.php';
49 $this->errortext =
'';
50 $this->textsize = 100.0;
51 $this->errordata = array();
61 if (strlen($this->title)
87 "DELETE FROM qpl_a_errortext WHERE question_fi = %s",
89 array( $this->
getId() )
93 foreach ($this->errordata as $object) {
94 $next_id =
$ilDB->nextId(
'qpl_a_errortext');
96 "INSERT INTO qpl_a_errortext (answer_id, question_fi, text_wrong, text_correct, points, sequence) VALUES (%s, %s, %s, %s, %s, %s)",
97 array(
'integer',
'integer',
'text',
'text',
'float',
'integer' ),
102 $object->text_correct,
122 array( $this->
getId() )
126 "INSERT INTO " . $this->
getAdditionalTableName() .
" (question_fi, errortext, textsize, points_wrong) VALUES (%s, %s, %s, %s)",
127 array(
"integer",
"text",
"float",
"float"),
154 $this->
setId($question_id);
163 include_once(
"./Services/RTE/classes/class.ilRTE.php");
177 "SELECT * FROM qpl_a_errortext WHERE question_fi = %s ORDER BY sequence ASC",
181 include_once
"./Modules/TestQuestionPool/classes/class.assAnswerErrorText.php";
188 parent::loadFromDb($question_id);
196 if ($this->
id <= 0) {
201 $this_id = $this->
getId();
205 include_once(
"./Modules/TestQuestionPool/classes/class.assQuestion.php");
209 if ((
int) $testObjId > 0) {
210 $clone->setObjId($testObjId);
230 $clone->copyPageOfQuestion($this_id);
232 $clone->copyXHTMLMediaObjectsOfQuestion($this_id);
234 $clone->onDuplicate($thisObjId, $this_id, $clone->getObjId(), $clone->getId());
243 if ($this->
id <= 0) {
249 $thisId = $this->
getId();
253 include_once(
"./Modules/TestQuestionPool/classes/class.assQuestion.php");
256 $clone->setObjId($target_questionpool_id);
267 $clone->onCopy($thisObjId, $thisId, $clone->getObjId(), $clone->getId());
274 if ($this->
id <= 0) {
279 include_once(
"./Modules/TestQuestionPool/classes/class.assQuestion.php");
282 $sourceParentId = $this->
getObjId();
288 $clone->setObjId($targetParentId);
290 if ($targetQuestionTitle) {
291 $clone->setTitle($targetQuestionTitle);
296 $clone->copyPageOfQuestion($sourceQuestionId);
298 $clone->copyXHTMLMediaObjectsOfQuestion($sourceQuestionId);
300 $clone->onCopy($sourceParentId, $sourceQuestionId, $clone->getObjId(), $clone->getId());
313 foreach ($this->errordata as $object) {
314 if ($object->points > 0) {
315 $maxpoints += $object->points;
333 if ($returndetails) {
334 throw new ilTestException(
'return details not implemented for ' . __METHOD__);
340 $positions = array();
341 if (is_null(
$pass)) {
347 array_push($positions,
$row[
'value1']);
373 if (is_null(
$pass)) {
374 include_once
"./Modules/Test/classes/class.ilObjTest.php";
378 $entered_values =
false;
380 $this->
getProcessLocker()->executeUserSolutionUpdateLockOperation(
function () use (&$entered_values, $active_id,
$pass, $authorized) {
384 $selected = explode(
",",
$_POST[
"qst_" . $this->
getId()]);
385 foreach ($selected as $position) {
388 $entered_values =
true;
392 if ($entered_values) {
393 include_once(
"./Modules/Test/classes/class.ilObjAssessmentFolder.php");
398 include_once(
"./Modules/Test/classes/class.ilObjAssessmentFolder.php");
410 $selection = explode(
',',
$_POST[
"qst_{$this->getId()}"]);
412 $selection = array();
433 return "assErrorText";
443 return "qpl_qst_errortext";
453 return "qpl_a_errortext";
462 $text = parent::getRTETextWithMediaObjects();
474 $selections = array();
476 if (is_array($solutions)) {
477 foreach ($solutions as $solution) {
478 array_push($selections, $solution[
'value1']);
480 $errortext_value = join(
",", $selections);
487 return $startrow +
$i + 1;
502 public function fromXML(&$item, &$questionpool_id, &$tst_id, &$tst_object, &$question_counter, &$import_mapping)
504 include_once
"./Modules/TestQuestionPool/classes/import/qti12/class.assErrorTextImport.php";
506 $import->fromXML($item, $questionpool_id, $tst_id, $tst_object, $question_counter, $import_mapping);
515 public function toXML($a_include_header =
true, $a_include_binary =
true, $a_shuffle =
false, $test_output =
false, $force_image_references =
false)
517 include_once
"./Modules/TestQuestionPool/classes/export/qti12/class.assErrorTextExport.php";
519 return $export->toXML($a_include_header, $a_include_binary, $a_shuffle, $test_output, $force_image_references);
529 $user_solution = array();
530 return $user_solution;
535 if (strlen($a_text) == 0) {
542 $a_text = str_replace(array(
"((",
"))"), array(
"~",
"~"), $a_text);
546 $r_passage =
"/(~([^~]+)~|#([^\s]+))/";
548 preg_match_all($r_passage, $a_text, $matches);
550 if (is_array($matches[0]) && !empty($matches[0])) {
555 $matches = array_intersect_key($matches, array(2 =>
'', 3 =>
''));
558 $matches[2] = array_diff($matches[2], array(
''));
559 $matches[3] = array_diff($matches[3], array(
''));
562 "passages" => $matches[2],
563 "words" => $matches[3],);
571 include_once
"./Modules/TestQuestionPool/classes/class.assAnswerErrorText.php";
573 $this->errordata = array();
574 foreach ($a_data as $err_type =>
$errors) {
581 foreach ($temp as $object) {
582 if (strcmp($object->text_wrong,
$error) == 0) {
583 $text_correct = $object->text_correct;
591 ksort($this->errordata);
594 public function createErrorTextOutput($selections =
null, $graphicalOutput =
false, $correct_solution =
false, $use_link_tags =
true)
598 include_once
"./Services/Utilities/classes/class.ilStr.php";
599 if (!is_array($selections)) {
600 $selections = array();
602 $textarray = preg_split(
"/[\n\r]+/", $this->
getErrorText());
604 foreach ($textarray as $textidx =>
$text) {
606 $passage_end =
false;
607 $items = preg_split(
"/\s+/",
$text);
608 foreach ($items as $idx => $item) {
612 ($posHash = strpos($item,
'#')) === 0 ||
613 ($posOpeningBrackets = strpos($item,
'((')) === 0 ||
614 ($posClosingBrackets = strpos($item,
'))')) !==
false
618 if ($posHash !==
false) {
619 $item = ilStr::substr($item, 1, ilStr::strlen($item) - 1);
620 $passage_end =
false;
621 } elseif ($posOpeningBrackets !==
false) {
624 $items_in_passage = array();
625 $passage_end =
false;
626 $item = ilStr::substr($item, 2, ilStr::strlen($item) - 2);
630 if (strpos($item,
'))') !==
false) {
631 $item = str_replace(
"))",
"", $item);
636 $item = str_replace(
"))",
"", $item);
639 if ($correct_solution && !$in_passage) {
640 $errorobject = $this->errordata[$errorcounter];
641 if (is_object($errorobject)) {
642 $item = strlen($errorobject->text_correct) ? $errorobject->text_correct :
' ';
648 if ($in_passage && !$passage_end) {
649 $items_in_passage[$idx] = $item;
655 if ($in_passage && $passage_end) {
657 $passage_end =
false;
658 if ($correct_solution) {
661 "ilc_qetitem_ErrorTextSelected" :
"ilc_qetitem_ErrorTextItem"
664 $errorobject = $this->errordata[$errorcounter];
665 if (is_object($errorobject)) {
666 $item = strlen($errorobject->text_correct) ? $errorobject->text_correct :
' ';
674 $group_selected =
true;
675 if ($graphicalOutput) {
676 $start_idx = $passage_start_idx;
677 foreach ($items_in_passage as $tmp_idx => $tmp_item) {
679 $group_selected =
false;
685 if ($group_selected) {
687 $group_selected =
false;
692 $item_stack = array();
693 $start_idx = $passage_start_idx;
694 foreach ($items_in_passage as $tmp_idx => $tmp_item) {
697 "ilc_qetitem_ErrorTextSelected" :
"ilc_qetitem_ErrorTextItem"
704 "ilc_qetitem_ErrorTextSelected" :
"ilc_qetitem_ErrorTextItem"
706 if ($graphicalOutput) {
707 if ($group_selected) {
708 $img =
' <img src="' .
ilUtil::getImagePath(
"icon_ok.svg") .
'" alt="' . $this->lng->txt(
"answer_is_right") .
'" title="' . $this->lng->txt(
"answer_is_right") .
'" /> ';
710 $img =
' <img src="' .
ilUtil::getImagePath(
"icon_not_ok.svg") .
'" alt="' . $this->lng->txt(
"answer_is_wrong") .
'" title="' . $this->lng->txt(
"answer_is_wrong") .
'" /> ';
715 $item_stack = trim(implode(
" ", $item_stack));
716 $item_stack = strlen($item_stack) ? $item_stack :
' ';
718 if ($graphicalOutput) {
719 $items[$idx] =
'<span class="selGroup">' . $item_stack .
'</span>';
721 $items[$idx] = $item_stack;
729 $class =
'ilc_qetitem_ErrorTextItem';
732 $class =
"ilc_qetitem_ErrorTextSelected";
733 if ($graphicalOutput) {
735 $img =
' <img src="' .
ilUtil::getImagePath(
"icon_ok.svg") .
'" alt="' . $this->lng->txt(
"answer_is_right") .
'" title="' . $this->lng->txt(
"answer_is_right") .
'" /> ';
737 $img =
' <img src="' .
ilUtil::getImagePath(
"icon_not_ok.svg") .
'" alt="' . $this->lng->txt(
"answer_is_wrong") .
'" title="' . $this->lng->txt(
"answer_is_wrong") .
'" /> ';
745 $textarray[$textidx] =
'<p>' . implode(
" ", $items) .
'</p>';
748 return implode(
"\n", $textarray);
753 foreach ($selection as
$data) {
754 if (!is_array(
$data)) {
770 include_once
"./Services/Utilities/classes/class.ilStr.php";
771 if (!is_array($selections)) {
772 $selections = array();
774 $textarray = preg_split(
"/[\n\r]+/", $this->
getErrorText());
775 foreach ($textarray as $textidx =>
$text) {
776 $items = preg_split(
"/\s+/",
$text);
777 foreach ($items as $idx => $item) {
778 if (($posHash = strpos($item,
'#')) === 0
779 || ($posOpeningBrackets = strpos($item,
'((')) === 0
780 || ($posClosingBrackets = strpos($item,
'))')) !==
false) {
783 if ($posHash !==
false) {
784 $item = ilStr::substr($item, 1, ilStr::strlen($item) - 1);
785 } elseif ($posOpeningBrackets !==
false) {
786 $item = ilStr::substr($item, 2, ilStr::strlen($item) - 2);
790 if (strpos($item,
'))') !==
false) {
791 $item = ilStr::substr($item, 0, ilStr::strlen($item) - 2);
795 if ($item{$posClosingBrackets+2} ==
',') {
799 $item = ilStr::substr($item, 0, $posClosingBrackets) . $appendComma;
804 if (in_array(
$counter, $selections)) {
808 if (in_array(
$counter, $selections)) {
811 $items[$idx] = $word;
814 $textarray[$textidx] = join($items,
" ");
816 return join($textarray,
"\n");
825 $textarray = preg_split(
"/[\n\r]+/", $this->
getErrorText());
826 foreach ($textarray as $textidx =>
$text) {
827 $items = preg_split(
"/\s+/",
$text);
829 foreach ($items as $word) {
831 $isErrorItem =
false;
832 if (strpos($word,
'#') === 0) {
834 $errorobject = $this->errordata[$errorcounter];
835 if (is_object($errorobject)) {
836 $points = $errorobject->points;
840 } elseif (($posOpeningBracket = strpos($word,
'((')) === 0
841 || ($posClosingBracket = strpos($word,
'))')) !==
false
845 if ($posOpeningBracket !==
false) {
846 $passages[] = array(
'begin_pos' =>
$counter,
'cnt_words' => 0);
848 } elseif ($posClosingBracket !==
false) {
850 $cur_pidx = count($passages) - 1;
851 $passages[$cur_pidx][
'end_pos'] =
$counter;
853 $errorobject = $this->errordata[$errorcounter];
854 if (is_object($errorobject)) {
855 $passages[$cur_pidx][
'score'] = $errorobject->points;
856 $passages[$cur_pidx][
'isError'] =
true;
862 $cur_pidx = count($passages) - 1;
863 $passages[$cur_pidx][
'cnt_words']++;
867 $words[
$counter] = array(
"word" => $word,
"points" =>
$points,
"isError" => $isErrorItem);
872 $selections = array();
873 foreach ($passages as $cnt => $pdata) {
874 if (!$withPositivePointsOnly && $pdata[
'isError'] || $withPositivePointsOnly && $pdata[
'score'] > 0) {
875 $indexes = range($pdata[
'begin_pos'], $pdata[
'end_pos']);
876 $selections[$pdata[
'begin_pos']] = $indexes;
880 foreach ($words as $idx => $word) {
881 if (!$withPositivePointsOnly && $word[
'isError'] || $withPositivePointsOnly && $word[
'points'] > 0) {
882 $selections[$idx] = array($idx);
888 $selections = array_values($selections);
899 $textarray = preg_split(
"/[\n\r]+/", $this->
getErrorText());
900 foreach ($textarray as $textidx =>
$text) {
901 $items = preg_split(
"/\s+/",
$text);
903 foreach ($items as $word) {
905 if (strpos($word,
'#') === 0) {
907 $errorobject = $this->errordata[$errorcounter];
908 if (is_object($errorobject)) {
909 $points = $errorobject->points;
912 } elseif (($posOpeningBracket = strpos($word,
'((')) === 0
913 || ($posClosingBracket = strpos($word,
'))')) !==
false
917 if ($posOpeningBracket !==
false) {
918 $passages[] = array(
'begin_pos' =>
$counter,
'cnt_words' => 0);
920 } elseif ($posClosingBracket !==
false) {
922 $cur_pidx = count($passages) - 1;
923 $passages[$cur_pidx][
'end_pos'] =
$counter;
925 $errorobject = $this->errordata[$errorcounter];
926 if (is_object($errorobject)) {
927 $passages[$cur_pidx][
'score'] = $errorobject->points;
932 $cur_pidx = count($passages) - 1;
933 $passages[$cur_pidx][
'cnt_words']++;
944 foreach ($positions as $position) {
948 $total += $words[$position][
'points'];
951 foreach ($passages as $cnt => $p_data) {
956 $isSelected = in_array($p_data[
'begin_pos'], $positions);
958 for (
$i = 0;
$i < $p_data[
'cnt_words'];
$i++) {
959 $current_pos = $p_data[
'begin_pos'] +
$i;
960 $isSelected = $isSelected && in_array($current_pos, $positions);
963 $total += $isSelected ? $p_data[
'score'] : 0;
974 $this->errordata = array();
979 include_once
"./Modules/TestQuestionPool/classes/class.assAnswerErrorText.php";
1010 $this->errortext = $a_value;
1031 if ($a_value ===
null) {
1034 $this->textsize = $a_value;
1054 $this->points_wrong = $a_value;
1069 case "points_wrong":
1073 return parent::__get($value);
1090 case "points_wrong":
1094 parent::__set(
$key, $value);
1105 include_once(
"./Services/RTE/classes/class.ilRTE.php");
1115 'onenotcorrect' => $this->
formatSAQuestion($this->feedbackOBJ->getGenericFeedbackTestPresentation($this->getId(),
false)),
1116 'allcorrect' => $this->formatSAQuestion($this->feedbackOBJ->getGenericFeedbackTestPresentation($this->getId(),
true))
1120 foreach ($this->
getErrorData() as $idx => $answer_obj) {
1121 array_push($answers, array(
1122 "answertext_wrong" => (
string) $answer_obj->text_wrong,
1123 "answertext_correct" => (
string) $answer_obj->text_correct,
1124 "points" => (
float) $answer_obj->points,
1125 "order" => (
int) $idx+1
1128 $result[
'correct_answers'] = $answers;
1131 $textarray = preg_split(
"/[\n\r]+/", $this->
getErrorText());
1132 foreach ($textarray as $textidx =>
$text) {
1133 $items = preg_split(
"/\s+/", trim(
$text));
1134 foreach ($items as $idx => $item) {
1135 if (substr($item, 0, 1) ==
"#") {
1136 $item = substr($item, 1);
1139 foreach (
$result[
"correct_answers"] as $aidx => $answer) {
1140 if ($answer[
"answertext_wrong"] == $item && !$answer[
"pos"]) {
1141 $result[
"correct_answers"][$aidx][
"pos"] = $this->
getId() .
"_" . $textidx .
"_" . ($idx+1);
1146 array_push($answers, array(
1148 "order" => $this->
getId() .
"_" . $textidx .
"_" . ($idx+1)
1151 if ($textidx !=
sizeof($textarray)-1) {
1152 array_push($answers, array(
1153 "answertext" =>
"###",
1154 "order" => $this->
getId() .
"_" . $textidx .
"_" . ($idx+2)
1158 $result[
'answers'] = $answers;
1176 require_once
"./Modules/TestQuestionPool/classes/class.ilOperatorsExpressionMapping.php";
1209 "SELECT value1+1 as value1 FROM tst_solutions WHERE active_fi = %s AND pass = %s AND question_fi = %s AND step = (
1210 SELECT MAX(step) FROM tst_solutions WHERE active_fi = %s AND pass = %s AND question_fi = %s
1212 array(
"integer",
"integer",
"integer",
"integer",
"integer",
"integer"),
1216 while (
$row = $ilDB->fetchAssoc(
$data)) {
1238 $error_text_array = explode(
' ', $this->errortext);
1241 if (array_key_exists(
$index, $error_text_array)) {
1242 return $error_text_array[
$index];
1246 return $error_text_array;
An exception for terminatinating execution or to throw for unit testing.
Class for error text answers.
Class for error text question exports.
Class for error text question imports.
Class for error text questions.
getErrorData()
Get error data.
reworkWorkingData($active_id, $pass, $obligationsAnswered, $authorized)
{Reworks the allready saved working data if neccessary.}
toXML($a_include_header=true, $a_include_binary=true, $a_shuffle=false, $test_output=false, $force_image_references=false)
Returns a QTI xml representation of the question and sets the internal domxml variable with the DOM X...
saveWorkingData($active_id, $pass=null, $authorized=true)
Saves the learners input of the question to the database.
flushErrorData()
Flush error data.
loadFromDb($question_id)
Loads the object from the database.
getTextSize()
Set text size in percent.
getOperators($expression)
Get all available operations for a specific question.
__construct( $title='', $comment='', $author='', $owner=-1, $question='')
assErorText constructor
getAvailableAnswerOptions($index=null)
If index is null, the function returns an array with all anwser options Else it returns the specific ...
getErrorsFromText($a_text="")
__get($value)
Object getter.
createErrorTextExport($selections=null)
duplicate($for_test=true, $title="", $author="", $owner="", $testObjId=null)
Duplicates the object.
savePreviewData(ilAssQuestionPreviewSession $previewSession)
__set($key, $value)
Object setter.
getErrorText()
Get error text.
toJSON()
Returns a JSON representation of the question.
createErrorTextOutput($selections=null, $graphicalOutput=false, $correct_solution=false, $use_link_tags=true)
setTextSize($a_value)
Set text size in percent.
setErrorText($a_value)
Set error text.
getAnswerTableName()
Returns the name of the answer table in the database.
saveToDb($original_id="")
Saves a the object to the database.
setExportDetailsXLS($worksheet, $startrow, $active_id, $pass)
{Creates an Excel worksheet for the detailed cumulated results of this question.object}
saveAnswerSpecificDataToDb()
Saves the answer specific records into a question types answer table.
copyObject($target_questionpool_id, $title="")
Copies an object.
setPointsWrong($a_value)
Set wrong points.
calculateReachedPoints($active_id, $pass=null, $authorizedSolution=true, $returndetails=false)
Returns the points, a learner has reached answering the question.
calculateReachedPointsFromPreviewSession(ilAssQuestionPreviewSession $previewSession)
getErrorTokenHtml($item, $class, $useLinkTags)
getBestSelection($withPositivePointsOnly=true)
getMaximumPoints()
Returns the maximum points, a learner can reach answering the question.
getRTETextWithMediaObjects()
Collects all text in the question which could contain media objects which were created with the Rich ...
getPointsForSelectedPositions($positions)
createNewOriginalFromThisDuplicate($targetParentId, $targetQuestionTitle="")
getAdditionalTableName()
Returns the name of the additional question data table in the database.
getPointsWrong()
Get wrong points.
isTokenSelected($counter, array $selection)
isComplete()
Returns true, if a single choice question is complete for use.
getBestSolution($active_id, $pass)
Returns the best solution for a given pass of a participant.
fromXML(&$item, &$questionpool_id, &$tst_id, &$tst_object, &$question_counter, &$import_mapping)
Creates a question from a QTI file.
saveAdditionalQuestionDataToDb()
Saves the data for the additional data table.
addErrorData($text_wrong, $text_correct, $points)
getExpressionTypes()
Get all available expression types for a specific question.
getQuestionType()
Returns the question type 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.
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.
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)
getParticipantsSolution()
setParticipantsSolution($participantSolution)
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...
Base Exception for all Exceptions relating to Modules/Test.
Class ilUserQuestionResult.
static getImagePath($img, $module_path="", $mode="output", $offline=false)
get image path (for images located in a template directory)
static prepareFormOutput($a_str, $a_strip=false)
prepares string output for html forms @access public
Class iQuestionCondition.
const PercentageResultExpression
getUserQuestionResult($active_id, $pass)
Get the user solution for a question by active_id and the test pass.
const EmptyAnswerExpression
const ExclusiveResultExpression
const NumberOfResultExpression
Interface ilObjAnswerScoringAdjustable.
Interface ilObjQuestionScoringAdjustable.