00001 <?php
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 include_once "./assessment/classes/class.assQuestion.php";
00024 include_once "./assessment/classes/inc.AssessmentConstants.php";
00025
00038 class assTextSubset extends assQuestion
00039 {
00047 var $question;
00048
00056 var $answers;
00057
00065 var $correctanswers;
00066
00074 var $text_rating;
00075
00089 function assTextSubset(
00090 $title = "",
00091 $comment = "",
00092 $author = "",
00093 $owner = -1,
00094 $question = ""
00095 )
00096 {
00097 $this->assQuestion($title, $comment, $author, $owner);
00098 $this->question = $question;
00099 $this->answers = array();
00100 $this->correctanswers = 0;
00101 }
00102
00111 function isComplete()
00112 {
00113 if (($this->title) and ($this->author) and ($this->question) and (count($this->answers) >= $this->correctanswers) and ($this->getMaximumPoints() > 0))
00114 {
00115 return true;
00116 }
00117 else
00118 {
00119 return false;
00120 }
00121 }
00122
00136 function fromXML(&$item, &$questionpool_id, &$tst_id, &$tst_object, &$question_counter, &$import_mapping)
00137 {
00138 global $ilUser;
00139
00140
00141 unset($_SESSION["import_mob_xhtml"]);
00142 $presentation = $item->getPresentation();
00143 $duration = $item->getDuration();
00144 $shuffle = 0;
00145 $idents = array();
00146 $now = getdate();
00147 $created = sprintf("%04d%02d%02d%02d%02d%02d", $now['year'], $now['mon'], $now['mday'], $now['hours'], $now['minutes'], $now['seconds']);
00148 $gaps = array();
00149 foreach ($presentation->order as $entry)
00150 {
00151 switch ($entry["type"])
00152 {
00153 case "response":
00154 $response = $presentation->response[$entry["index"]];
00155 if ($response->getResponseType() == RT_RESPONSE_STR)
00156 {
00157 array_push($idents, $response->getIdent());
00158 }
00159 break;
00160 }
00161 }
00162 $responses = array();
00163 foreach ($item->resprocessing as $resprocessing)
00164 {
00165 foreach ($resprocessing->respcondition as $respcondition)
00166 {
00167 $ident = "";
00168 $correctness = 1;
00169 $conditionvar = $respcondition->getConditionvar();
00170 foreach ($conditionvar->order as $order)
00171 {
00172 switch ($order["field"])
00173 {
00174 case "varsubset":
00175 $respident = $conditionvar->varsubset[$order["index"]]->getRespident();
00176 $content = $conditionvar->varsubset[$order["index"]]->getContent();
00177 if (!is_array($responses[$respident])) $responses[$respident] = array();
00178 $vars = split(",", $content);
00179 foreach ($vars as $var)
00180 {
00181 array_push($responses[$respident], array("solution" => $var, "points" => ""));
00182 }
00183 break;
00184 }
00185 }
00186 foreach ($respcondition->setvar as $setvar)
00187 {
00188 if ((strcmp($setvar->getVarname(), "matches") == 0) && ($setvar->getAction() == ACTION_ADD))
00189 {
00190 foreach ($responses[$respident] as $idx => $solutionarray)
00191 {
00192 if (strlen($solutionarray["points"] == 0))
00193 {
00194 $responses[$respident][$idx]["points"] = $setvar->getContent();
00195 }
00196 }
00197 }
00198 }
00199 }
00200 }
00201
00202 $this->setTitle($item->getTitle());
00203 $this->setComment($item->getComment());
00204 $this->setAuthor($item->getAuthor());
00205 $this->setOwner($ilUser->getId());
00206 $this->setQuestion($this->QTIMaterialToString($item->getQuestiontext()));
00207 $this->setObjId($questionpool_id);
00208 $this->setEstimatedWorkingTime($duration["h"], $duration["m"], $duration["s"]);
00209 $textrating = $item->getMetadataEntry("textrating");
00210 if (strlen($textrating) == 0) $textrating = "ci";
00211 $this->setTextRating($textgap_rating);
00212 $this->setCorrectAnswers($item->getMetadataEntry("correctanswers"));
00213 $response = current($responses);
00214 $counter = 0;
00215 if (is_array($response))
00216 {
00217 foreach ($response as $answer)
00218 {
00219 $this->addAnswer($answer["solution"], $answer["points"], $counter);
00220 $counter++;
00221 }
00222 }
00223 $this->saveToDb();
00224 if (count($item->suggested_solutions))
00225 {
00226 foreach ($item->suggested_solutions as $suggested_solution)
00227 {
00228 $this->setSuggestedSolution($suggested_solution["solution"]->getContent(), $suggested_solution["gap_index"], true);
00229 }
00230 $this->saveToDb();
00231 }
00232
00233 if (is_array($_SESSION["import_mob_xhtml"]))
00234 {
00235 include_once "./content/classes/Media/class.ilObjMediaObject.php";
00236 include_once "./Services/RTE/classes/class.ilRTE.php";
00237 foreach ($_SESSION["import_mob_xhtml"] as $mob)
00238 {
00239 if ($tst_id > 0)
00240 {
00241 include_once "./assessment/classes/class.ilObjTest.php";
00242 $importfile = ilObjTest::_getImportDirectory() . "/" . $_SESSION["tst_import_subdir"] . "/" . $mob["uri"];
00243 }
00244 else
00245 {
00246 include_once "./assessment/classes/class.ilObjQuestionPool.php";
00247 $importfile = ilObjQuestionPool::_getImportDirectory() . "/" . $_SESSION["qpl_import_subdir"] . "/" . $mob["uri"];
00248 }
00249 $media_object =& ilObjMediaObject::_saveTempFileAsMediaObject(basename($importfile), $importfile, FALSE);
00250 ilObjMediaObject::_saveUsage($media_object->getId(), "qpl:html", $this->getId());
00251 $this->setQuestion(ilRTE::_replaceMediaObjectImageSrc(str_replace("src=\"" . $mob["mob"] . "\"", "src=\"" . "il_" . IL_INST_ID . "_mob_" . $media_object->getId() . "\"", $this->getQuestion()), 1));
00252 }
00253 $this->saveToDb();
00254 }
00255 if ($tst_id > 0)
00256 {
00257 $q_1_id = $this->getId();
00258 $question_id = $this->duplicate(true);
00259 $tst_object->questions[$question_counter++] = $question_id;
00260 $import_mapping[$item->getIdent()] = array("pool" => $q_1_id, "test" => $question_id);
00261 }
00262 else
00263 {
00264 $import_mapping[$item->getIdent()] = array("pool" => $this->getId(), "test" => 0);
00265 }
00266
00267 }
00268
00278 function to_xml($a_include_header = true, $a_include_binary = true, $a_shuffle = false, $test_output = false, $force_image_references = false)
00279 {
00280 include_once("./classes/class.ilXmlWriter.php");
00281 $a_xml_writer = new ilXmlWriter;
00282
00283 $a_xml_writer->xmlHeader();
00284 $a_xml_writer->xmlStartTag("questestinterop");
00285 $attrs = array(
00286 "ident" => "il_".IL_INST_ID."_qst_".$this->getId(),
00287 "title" => $this->getTitle()
00288 );
00289 $a_xml_writer->xmlStartTag("item", $attrs);
00290
00291 $a_xml_writer->xmlElement("qticomment", NULL, $this->getComment());
00292
00293 $workingtime = $this->getEstimatedWorkingTime();
00294 $duration = sprintf("P0Y0M0DT%dH%dM%dS", $workingtime["h"], $workingtime["m"], $workingtime["s"]);
00295 $a_xml_writer->xmlElement("duration", NULL, $duration);
00296
00297 $a_xml_writer->xmlStartTag("itemmetadata");
00298 $a_xml_writer->xmlStartTag("qtimetadata");
00299 $a_xml_writer->xmlStartTag("qtimetadatafield");
00300 $a_xml_writer->xmlElement("fieldlabel", NULL, "ILIAS_VERSION");
00301 $a_xml_writer->xmlElement("fieldentry", NULL, $this->ilias->getSetting("ilias_version"));
00302 $a_xml_writer->xmlEndTag("qtimetadatafield");
00303 $a_xml_writer->xmlStartTag("qtimetadatafield");
00304 $a_xml_writer->xmlElement("fieldlabel", NULL, "QUESTIONTYPE");
00305 $a_xml_writer->xmlElement("fieldentry", NULL, TEXTSUBSET_QUESTION_IDENTIFIER);
00306 $a_xml_writer->xmlEndTag("qtimetadatafield");
00307 $a_xml_writer->xmlStartTag("qtimetadatafield");
00308 $a_xml_writer->xmlElement("fieldlabel", NULL, "AUTHOR");
00309 $a_xml_writer->xmlElement("fieldentry", NULL, $this->getAuthor());
00310 $a_xml_writer->xmlEndTag("qtimetadatafield");
00311 $a_xml_writer->xmlStartTag("qtimetadatafield");
00312 $a_xml_writer->xmlElement("fieldlabel", NULL, "textrating");
00313 $a_xml_writer->xmlElement("fieldentry", NULL, $this->getTextRating());
00314 $a_xml_writer->xmlEndTag("qtimetadatafield");
00315 $a_xml_writer->xmlStartTag("qtimetadatafield");
00316 $a_xml_writer->xmlElement("fieldlabel", NULL, "correctanswers");
00317 $a_xml_writer->xmlElement("fieldentry", NULL, $this->getCorrectAnswers());
00318 $a_xml_writer->xmlEndTag("qtimetadatafield");
00319 $a_xml_writer->xmlStartTag("qtimetadatafield");
00320 $a_xml_writer->xmlElement("fieldlabel", NULL, "points");
00321 $a_xml_writer->xmlElement("fieldentry", NULL, $this->getPoints());
00322 $a_xml_writer->xmlEndTag("qtimetadatafield");
00323 $a_xml_writer->xmlEndTag("qtimetadata");
00324 $a_xml_writer->xmlEndTag("itemmetadata");
00325
00326
00327 $attrs = array(
00328 "label" => $this->getTitle()
00329 );
00330 $a_xml_writer->xmlStartTag("presentation", $attrs);
00331
00332 $a_xml_writer->xmlStartTag("flow");
00333
00334 $this->addQTIMaterial($a_xml_writer, $this->getQuestion());
00335
00336 for ($counter = 1; $counter <= $this->getCorrectAnswers(); $counter++)
00337 {
00338 $attrs = array(
00339 "ident" => "TEXTSUBSET_" . sprintf("%02d", $counter),
00340 "rcardinality" => "Single"
00341 );
00342 $a_xml_writer->xmlStartTag("response_str", $attrs);
00343 $solution = $this->getSuggestedSolution(0);
00344 if (count($solution))
00345 {
00346 if (preg_match("/il_(\d*?)_(\w+)_(\d+)/", $solution["internal_link"], $matches))
00347 {
00348 $a_xml_writer->xmlStartTag("material");
00349 $intlink = "il_" . IL_INST_ID . "_" . $matches[2] . "_" . $matches[3];
00350 if (strcmp($matches[1], "") != 0)
00351 {
00352 $intlink = $solution["internal_link"];
00353 }
00354 $attrs = array(
00355 "label" => "suggested_solution"
00356 );
00357 $a_xml_writer->xmlElement("mattext", $attrs, $intlink);
00358 $a_xml_writer->xmlEndTag("material");
00359 }
00360 }
00361
00362 $attrs = array(
00363 "fibtype" => "String",
00364 "columns" => $this->getMaxTextboxWidth()
00365 );
00366 $a_xml_writer->xmlStartTag("render_fib", $attrs);
00367 $a_xml_writer->xmlEndTag("render_fib");
00368 $a_xml_writer->xmlEndTag("response_str");
00369 }
00370
00371 $a_xml_writer->xmlEndTag("flow");
00372 $a_xml_writer->xmlEndTag("presentation");
00373
00374
00375 $a_xml_writer->xmlStartTag("resprocessing");
00376 $a_xml_writer->xmlStartTag("outcomes");
00377 $a_xml_writer->xmlStartTag("decvar");
00378 $a_xml_writer->xmlEndTag("decvar");
00379 $attribs = array(
00380 "varname" => "matches",
00381 "defaultval" => "0"
00382 );
00383 $a_xml_writer->xmlElement("decvar", $attribs, NULL);
00384 $a_xml_writer->xmlEndTag("outcomes");
00385
00386 for ($counter = 1; $counter <= $this->getCorrectAnswers(); $counter++)
00387 {
00388 $scoregroups =& $this->joinAnswers();
00389 foreach ($scoregroups as $points => $scoreanswers)
00390 {
00391 $attrs = array(
00392 "continue" => "Yes"
00393 );
00394 $a_xml_writer->xmlStartTag("respcondition", $attrs);
00395
00396 $a_xml_writer->xmlStartTag("conditionvar");
00397 $attrs = array(
00398 "respident" => "TEXTSUBSET_" . sprintf("%02d", $counter)
00399 );
00400 $a_xml_writer->xmlElement("varsubset", $attrs, join(",", $scoreanswers));
00401 $a_xml_writer->xmlEndTag("conditionvar");
00402
00403 $attrs = array(
00404 "varname" => "matches",
00405 "action" => "Add"
00406 );
00407 $a_xml_writer->xmlElement("setvar", $attrs, $points);
00408
00409 $attrs = array(
00410 "feedbacktype" => "Response",
00411 "linkrefid" => "Matches_" . sprintf("%02d", $counter)
00412 );
00413 $a_xml_writer->xmlElement("displayfeedback", $attrs);
00414 $a_xml_writer->xmlEndTag("respcondition");
00415 }
00416 }
00417 $a_xml_writer->xmlEndTag("resprocessing");
00418
00419
00420 for ($counter = 1; $counter <= $this->getCorrectAnswers(); $counter++)
00421 {
00422 $attrs = array(
00423 "ident" => "Matches_" . sprintf("%02d", $counter),
00424 "view" => "All"
00425 );
00426 $a_xml_writer->xmlStartTag("itemfeedback", $attrs);
00427
00428 $a_xml_writer->xmlStartTag("flow_mat");
00429 $a_xml_writer->xmlStartTag("material");
00430 $a_xml_writer->xmlElement("mattext");
00431 $a_xml_writer->xmlEndTag("material");
00432 $a_xml_writer->xmlEndTag("flow_mat");
00433 $a_xml_writer->xmlEndTag("itemfeedback");
00434 }
00435
00436 $a_xml_writer->xmlEndTag("item");
00437 $a_xml_writer->xmlEndTag("questestinterop");
00438
00439 $xml = $a_xml_writer->xmlDumpMem(FALSE);
00440 if (!$a_include_header)
00441 {
00442 $pos = strpos($xml, "?>");
00443 $xml = substr($xml, $pos + 2);
00444 }
00445 return $xml;
00446 }
00447
00456 function saveToDb($original_id = "")
00457 {
00458 global $ilDB;
00459
00460 $complete = 0;
00461 if ($this->isComplete())
00462 {
00463 $complete = 1;
00464 }
00465 $estw_time = $this->getEstimatedWorkingTime();
00466 $estw_time = sprintf("%02d:%02d:%02d", $estw_time['h'], $estw_time['m'], $estw_time['s']);
00467
00468 if ($original_id)
00469 {
00470 $original_id = $ilDB->quote($original_id);
00471 }
00472 else
00473 {
00474 $original_id = "NULL";
00475 }
00476
00477
00478 include_once("./Services/RTE/classes/class.ilRTE.php");
00479 ilRTE::_cleanupMediaObjectUsage($this->question, "qpl:html",
00480 $this->getId());
00481
00482 if ($this->id == -1)
00483 {
00484
00485 $now = getdate();
00486 $question_type = $this->getQuestionType();
00487 $created = sprintf("%04d%02d%02d%02d%02d%02d", $now['year'], $now['mon'], $now['mday'], $now['hours'], $now['minutes'], $now['seconds']);
00488 $query = sprintf("INSERT INTO qpl_questions (question_id, question_type_fi, obj_fi, title, comment, author, owner, question_text, points, working_time, complete, created, original_id, TIMESTAMP) VALUES (NULL, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, NULL)",
00489 $ilDB->quote($question_type),
00490 $ilDB->quote($this->obj_id),
00491 $ilDB->quote($this->title),
00492 $ilDB->quote($this->comment),
00493 $ilDB->quote($this->author),
00494 $ilDB->quote($this->owner),
00495 $ilDB->quote(ilRTE::_replaceMediaObjectImageSrc($this->question, 0)),
00496 $ilDB->quote($this->getMaximumPoints() . ""),
00497 $ilDB->quote($estw_time),
00498 $ilDB->quote("$complete"),
00499 $ilDB->quote($created),
00500 $original_id
00501 );
00502 $result = $ilDB->query($query);
00503
00504 if ($result == DB_OK)
00505 {
00506 $this->id = $ilDB->getLastInsertId();
00507 $query = sprintf("INSERT INTO qpl_question_textsubset (question_fi, textgap_rating, correctanswers) VALUES (%s, %s, %s)",
00508 $ilDB->quote($this->id . ""),
00509 $ilDB->quote($this->getTextRating() . ""),
00510 $ilDB->quote($this->getCorrectAnswers() . "")
00511 );
00512 $ilDB->query($query);
00513
00514
00515 $this->createPageObject();
00516
00517
00518 if ($this->getTestId() > 0)
00519 {
00520 $this->insertIntoTest($this->getTestId());
00521 }
00522 }
00523 }
00524 else
00525 {
00526
00527 $query = sprintf("UPDATE qpl_questions SET obj_fi = %s, title = %s, comment = %s, author = %s, question_text = %s, points = %s, working_time=%s, complete = %s WHERE question_id = %s",
00528 $ilDB->quote($this->obj_id. ""),
00529 $ilDB->quote($this->title),
00530 $ilDB->quote($this->comment),
00531 $ilDB->quote($this->author),
00532 $ilDB->quote(ilRTE::_replaceMediaObjectImageSrc($this->question, 0)),
00533 $ilDB->quote($this->getMaximumPoints() . ""),
00534 $ilDB->quote($estw_time),
00535 $ilDB->quote("$complete"),
00536 $ilDB->quote($this->id)
00537 );
00538 $result = $ilDB->query($query);
00539 $query = sprintf("UPDATE qpl_question_textsubset SET textgap_rating = %s, correctanswers = %s WHERE question_fi = %s",
00540 $ilDB->quote($this->getTextRating() . ""),
00541 $ilDB->quote($this->getCorrectAnswers() . ""),
00542 $ilDB->quote($this->id . "")
00543 );
00544 $result = $ilDB->query($query);
00545 }
00546 if ($result == DB_OK)
00547 {
00548
00549
00550
00551 $query = sprintf("DELETE FROM qpl_answer_textsubset WHERE question_fi = %s",
00552 $ilDB->quote($this->id)
00553 );
00554 $result = $ilDB->query($query);
00555
00556
00557 foreach ($this->answers as $key => $value)
00558 {
00559 $answer_obj = $this->answers[$key];
00560 $query = sprintf("INSERT INTO qpl_answer_textsubset (answer_id, question_fi, answertext, points, aorder) VALUES (NULL, %s, %s, %s, %s)",
00561 $ilDB->quote($this->id),
00562 $ilDB->quote($answer_obj->getAnswertext()),
00563 $ilDB->quote($answer_obj->getPoints() . ""),
00564 $ilDB->quote($answer_obj->getOrder() . "")
00565 );
00566 $answer_result = $ilDB->query($query);
00567 }
00568 }
00569 parent::saveToDb($original_id);
00570 }
00571
00581 function loadFromDb($question_id)
00582 {
00583 global $ilDB;
00584
00585 $query = sprintf("SELECT qpl_questions.*, qpl_question_textsubset.* FROM qpl_questions, qpl_question_textsubset WHERE question_id = %s AND qpl_questions.question_id = qpl_question_textsubset.question_fi",
00586 $ilDB->quote($question_id)
00587 );
00588 $result = $ilDB->query($query);
00589 if (strcmp(strtolower(get_class($result)), db_result) == 0)
00590 {
00591 if ($result->numRows() == 1)
00592 {
00593 $data = $result->fetchRow(DB_FETCHMODE_OBJECT);
00594 $this->id = $question_id;
00595 $this->title = $data->title;
00596 $this->comment = $data->comment;
00597 $this->solution_hint = $data->solution_hint;
00598 $this->original_id = $data->original_id;
00599 $this->obj_id = $data->obj_fi;
00600 $this->author = $data->author;
00601 $this->owner = $data->owner;
00602 $this->points = $data->points;
00603 include_once("./Services/RTE/classes/class.ilRTE.php");
00604 $this->question = ilRTE::_replaceMediaObjectImageSrc($data->question_text, 1);
00605 $this->correctanswers = $data->correctanswers;
00606 $this->text_rating = $data->textgap_rating;
00607 $this->setEstimatedWorkingTime(substr($data->working_time, 0, 2), substr($data->working_time, 3, 2), substr($data->working_time, 6, 2));
00608 }
00609
00610 $query = sprintf("SELECT * FROM qpl_answer_textsubset WHERE question_fi = %s ORDER BY aorder ASC",
00611 $ilDB->quote($question_id)
00612 );
00613 $result = $ilDB->query($query);
00614
00615 include_once "./assessment/classes/class.assAnswerSimple.php";
00616 if (strcmp(strtolower(get_class($result)), db_result) == 0)
00617 {
00618 while ($data = $result->fetchRow(DB_FETCHMODE_ASSOC))
00619 {
00620 array_push($this->answers, new ASS_AnswerSimple($data["answertext"], $data["points"], $data["aorder"]));
00621 }
00622 }
00623 }
00624 parent::loadFromDb($question_id);
00625 }
00626
00627
00637 function setQuestion($question = "")
00638 {
00639 $this->question = $question;
00640 }
00641
00649 function addAnswer($answertext, $points, $answerorder)
00650 {
00651 include_once "./assessment/classes/class.assAnswerSimple.php";
00652 array_push($this->answers, new ASS_AnswerSimple($answertext, $points, $answerorder));
00653 }
00654
00662 function duplicate($for_test = true, $title = "", $author = "", $owner = "")
00663 {
00664 if ($this->id <= 0)
00665 {
00666
00667 return;
00668 }
00669
00670 $this_id = $this->getId();
00671 $clone = $this;
00672 include_once ("./assessment/classes/class.assQuestion.php");
00673 $original_id = assQuestion::_getOriginalId($this->id);
00674 $clone->id = -1;
00675 if ($title)
00676 {
00677 $clone->setTitle($title);
00678 }
00679
00680 if ($author)
00681 {
00682 $clone->setAuthor($author);
00683 }
00684 if ($owner)
00685 {
00686 $clone->setOwner($owner);
00687 }
00688
00689 if ($for_test)
00690 {
00691 $clone->saveToDb($original_id);
00692 }
00693 else
00694 {
00695 $clone->saveToDb();
00696 }
00697
00698
00699 $clone->copyPageOfQuestion($this_id);
00700
00701 $clone->copyXHTMLMediaObjectsOfQuestion($this_id);
00702
00703 return $clone->id;
00704 }
00705
00713 function copyObject($target_questionpool, $title = "")
00714 {
00715 if ($this->id <= 0)
00716 {
00717
00718 return;
00719 }
00720
00721 $clone = $this;
00722 include_once ("./assessment/classes/class.assQuestion.php");
00723 $original_id = assQuestion::_getOriginalId($this->id);
00724 $clone->id = -1;
00725 $source_questionpool = $this->getObjId();
00726 $clone->setObjId($target_questionpool);
00727 if ($title)
00728 {
00729 $clone->setTitle($title);
00730 }
00731 $clone->saveToDb();
00732
00733
00734 $clone->copyPageOfQuestion($original_id);
00735
00736 $clone->copyXHTMLMediaObjectsOfQuestion($original_id);
00737
00738 return $clone->id;
00739 }
00740
00750 function getQuestion()
00751 {
00752 return $this->question;
00753 }
00754
00764 function getAnswerCount()
00765 {
00766 return count($this->answers);
00767 }
00768
00780 function getAnswer($index = 0)
00781 {
00782 if ($index < 0) return NULL;
00783 if (count($this->answers) < 1) return NULL;
00784 if ($index >= count($this->answers)) return NULL;
00785
00786 return $this->answers[$index];
00787 }
00788
00799 function deleteAnswer($index = 0)
00800 {
00801 if ($index < 0) return;
00802 if (count($this->answers) < 1) return;
00803 if ($index >= count($this->answers)) return;
00804 unset($this->answers[$index]);
00805 $this->answers = array_values($this->answers);
00806 for ($i = 0; $i < count($this->answers); $i++)
00807 {
00808 if ($this->answers[$i]->getOrder() > $index)
00809 {
00810 $this->answers[$i]->setOrder($i);
00811 }
00812 }
00813 }
00814
00823 function flushAnswers()
00824 {
00825 $this->answers = array();
00826 }
00827
00836 function getMaximumPoints()
00837 {
00838 $points = array();
00839 foreach ($this->answers as $answer)
00840 {
00841 if ($answer->getPoints() > 0)
00842 {
00843 array_push($points, $answer->getPoints());
00844 }
00845 }
00846 rsort($points, SORT_NUMERIC);
00847 $maxpoints = 0;
00848 for ($counter = 0; $counter < $this->getCorrectAnswers(); $counter++)
00849 {
00850 $maxpoints += $points[$counter];
00851 }
00852 return $maxpoints;
00853 }
00854
00863 function &getAvailableAnswers()
00864 {
00865 $available_answers = array();
00866 foreach ($this->answers as $answer)
00867 {
00868 array_push($available_answers, $answer->getAnswertext());
00869 }
00870 return $available_answers;
00871 }
00872
00885 function isAnswerCorrect($answers, $answer)
00886 {
00887 $textrating = $this->getTextRating();
00888 foreach ($answers as $key => $value)
00889 {
00890 switch ($textrating)
00891 {
00892 case TEXTGAP_RATING_CASEINSENSITIVE:
00893 if (strcmp(strtolower(utf8_decode($value)), strtolower(utf8_decode($answer))) == 0) return $key;
00894 break;
00895 case TEXTGAP_RATING_CASESENSITIVE:
00896 if (strcmp(utf8_decode($value), utf8_decode($answer)) == 0) return $key;
00897 break;
00898 case TEXTGAP_RATING_LEVENSHTEIN1:
00899 if (levenshtein(utf8_decode($value), utf8_decode($answer)) <= 1) return $key;
00900 break;
00901 case TEXTGAP_RATING_LEVENSHTEIN2:
00902 if (levenshtein(utf8_decode($value), utf8_decode($answer)) <= 2) return $key;
00903 break;
00904 case TEXTGAP_RATING_LEVENSHTEIN3:
00905 if (levenshtein(utf8_decode($value), utf8_decode($answer)) <= 3) return $key;
00906 break;
00907 case TEXTGAP_RATING_LEVENSHTEIN4:
00908 if (levenshtein(utf8_decode($value), utf8_decode($answer)) <= 4) return $key;
00909 break;
00910 case TEXTGAP_RATING_LEVENSHTEIN5:
00911 if (levenshtein(utf8_decode($value), utf8_decode($answer)) <= 5) return $key;
00912 break;
00913 }
00914 }
00915 return FALSE;
00916 }
00917
00927 function getTextRating()
00928 {
00929 return $this->text_rating;
00930 }
00931
00941 function setTextRating($a_text_rating)
00942 {
00943 switch ($a_text_rating)
00944 {
00945 case TEXTGAP_RATING_CASEINSENSITIVE:
00946 case TEXTGAP_RATING_CASESENSITIVE:
00947 case TEXTGAP_RATING_LEVENSHTEIN1:
00948 case TEXTGAP_RATING_LEVENSHTEIN2:
00949 case TEXTGAP_RATING_LEVENSHTEIN3:
00950 case TEXTGAP_RATING_LEVENSHTEIN4:
00951 case TEXTGAP_RATING_LEVENSHTEIN5:
00952 $this->text_rating = $a_text_rating;
00953 break;
00954 default:
00955 $this->text_rating = TEXTGAP_RATING_CASEINSENSITIVE;
00956 break;
00957 }
00958 }
00959
00971 function calculateReachedPoints($active_id, $pass = NULL)
00972 {
00973 global $ilDB;
00974
00975 $available_answers =& $this->getAvailableAnswers();
00976 $found_counter = 0;
00977
00978 if (is_null($pass))
00979 {
00980 $pass = $this->getSolutionMaxPass($active_id);
00981 }
00982 $query = sprintf("SELECT * FROM tst_solutions WHERE active_fi = %s AND question_fi = %s AND pass = %s",
00983 $ilDB->quote($active_id . ""),
00984 $ilDB->quote($this->getId() . ""),
00985 $ilDB->quote($pass . "")
00986 );
00987 $result = $ilDB->query($query);
00988 $points = 0;
00989 while ($data = $result->fetchRow(DB_FETCHMODE_ASSOC))
00990 {
00991 $enteredtext = $data["value1"];
00992 $index = $this->isAnswerCorrect($available_answers, $enteredtext);
00993 if ($index !== FALSE)
00994 {
00995 unset($available_answers[$index]);
00996 $points += $this->answers[$index]->getPoints();
00997 }
00998 }
00999
01000 $points = parent::calculateReachedPoints($active_id, $pass = NULL, $points);
01001 return $points;
01002 }
01003
01012 function setCorrectAnswers($a_correct_answers)
01013 {
01014 $this->correctanswers = $a_correct_answers;
01015 }
01016
01025 function getCorrectAnswers()
01026 {
01027 return $this->correctanswers;
01028 }
01029
01040 function saveWorkingData($active_id, $pass = NULL)
01041 {
01042 global $ilDB;
01043 global $ilUser;
01044
01045 include_once "./assessment/classes/class.ilObjTest.php";
01046 $actualpass = ilObjTest::_getPass($active_id);
01047 $entered_values = 0;
01048
01049 $query = sprintf("DELETE FROM tst_solutions WHERE active_fi = %s AND question_fi = %s AND pass = %s",
01050 $ilDB->quote($active_id . ""),
01051 $ilDB->quote($this->getId() . ""),
01052 $ilDB->quote($actualpass . "")
01053 );
01054 $result = $ilDB->query($query);
01055 foreach ($_POST as $key => $value)
01056 {
01057 if (preg_match("/^TEXTSUBSET_(\d+)/", $key, $matches))
01058 {
01059 if (strlen($value))
01060 {
01061 $query = sprintf("INSERT INTO tst_solutions (solution_id, active_fi, question_fi, value1, value2, pass, TIMESTAMP) VALUES (NULL, %s, %s, %s, NULL, %s, NULL)",
01062 $ilDB->quote($active_id),
01063 $ilDB->quote($this->getId()),
01064 $ilDB->quote(trim($value)),
01065 $ilDB->quote($actualpass . "")
01066 );
01067 $result = $ilDB->query($query);
01068 $entered_values++;
01069 }
01070 }
01071 }
01072 if ($entered_values)
01073 {
01074 include_once ("./classes/class.ilObjAssessmentFolder.php");
01075 if (ilObjAssessmentFolder::_enabledAssessmentLogging())
01076 {
01077 $this->logAction($this->lng->txtlng("assessment", "log_user_entered_values", ilObjAssessmentFolder::_getLogLanguage()), $active_id, $this->getId());
01078 }
01079 }
01080 else
01081 {
01082 include_once ("./classes/class.ilObjAssessmentFolder.php");
01083 if (ilObjAssessmentFolder::_enabledAssessmentLogging())
01084 {
01085 $this->logAction($this->lng->txtlng("assessment", "log_user_not_entered_values", ilObjAssessmentFolder::_getLogLanguage()), $active_id, $this->getId());
01086 }
01087 }
01088 parent::saveWorkingData($active_id, $pass);
01089 return true;
01090 }
01091
01092 function syncWithOriginal()
01093 {
01094 global $ilDB;
01095
01096 if ($this->original_id)
01097 {
01098 $complete = 0;
01099 if ($this->isComplete())
01100 {
01101 $complete = 1;
01102 }
01103
01104 $estw_time = $this->getEstimatedWorkingTime();
01105 $estw_time = sprintf("%02d:%02d:%02d", $estw_time['h'], $estw_time['m'], $estw_time['s']);
01106
01107 $query = sprintf("UPDATE qpl_questions SET obj_fi = %s, title = %s, comment = %s, author = %s, question_text = %s, points = %s, working_time=%s, complete = %s WHERE question_id = %s",
01108 $ilDB->quote($this->obj_id. ""),
01109 $ilDB->quote($this->title. ""),
01110 $ilDB->quote($this->comment. ""),
01111 $ilDB->quote($this->author. ""),
01112 $ilDB->quote($this->question. ""),
01113 $ilDB->quote($this->getMaximumPoints() . ""),
01114 $ilDB->quote($estw_time. ""),
01115 $ilDB->quote($complete. ""),
01116 $ilDB->quote($this->original_id. "")
01117 );
01118 $result = $ilDB->query($query);
01119 $query = sprintf("UPDATE qpl_question_textsubset SET textgap_rating = %s, correctanswers = %s WHERE question_fi = %s",
01120 $ilDB->quote($this->getTextRating() . ""),
01121 $ilDB->quote($this->getCorrectAnswers() . ""),
01122 $ilDB->quote($this->original_id . "")
01123 );
01124 $result = $ilDB->query($query);
01125
01126 if ($result == DB_OK)
01127 {
01128
01129
01130
01131 $query = sprintf("DELETE FROM qpl_answer_textsubset WHERE question_fi = %s",
01132 $ilDB->quote($this->original_id)
01133 );
01134 $result = $ilDB->query($query);
01135
01136
01137 foreach ($this->answers as $key => $value)
01138 {
01139 $answer_obj = $this->answers[$key];
01140 $query = sprintf("INSERT INTO qpl_answer_textsubset (answer_id, question_fi, answertext, points, aorder) VALUES (NULL, %s, %s, %s, %s)",
01141 $ilDB->quote($this->original_id. ""),
01142 $ilDB->quote($answer_obj->getAnswertext(). ""),
01143 $ilDB->quote($answer_obj->getPoints() . ""),
01144 $ilDB->quote($answer_obj->getOrder() . "")
01145 );
01146 $answer_result = $ilDB->query($query);
01147 }
01148 }
01149 parent::syncWithOriginal();
01150 }
01151 }
01152
01161 function getQuestionType()
01162 {
01163 return 10;
01164 }
01165
01174 function &joinAnswers()
01175 {
01176 $join = array();
01177 foreach ($this->answers as $answer)
01178 {
01179 if (!is_array($join[$answer->getPoints() . ""]))
01180 {
01181 $join[$answer->getPoints() . ""] = array();
01182 }
01183 array_push($join[$answer->getPoints() . ""], $answer->getAnswertext());
01184 }
01185 return $join;
01186 }
01187
01196 function getMaxTextboxWidth()
01197 {
01198 $maxwidth = 0;
01199 foreach ($this->answers as $answer)
01200 {
01201 $len = strlen($answer->getAnswertext());
01202 if ($len > $maxwidth) $maxwidth = $len;
01203 }
01204 return $maxwidth + 3;
01205 }
01206
01215 function getAdditionalTableName()
01216 {
01217 return "qpl_question_textsubset";
01218 }
01219
01228 function getAnswerTableName()
01229 {
01230 return "qpl_answer_textsubset";
01231 }
01232 }
01233
01234 ?>