00001 <?php
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 require_once "./assessment/classes/class.assQuestion.php";
00025 require_once "./assessment/classes/class.assAnswerCloze.php";
00026 require_once "./assessment/classes/class.ilQTIUtils.php";
00027
00028 define("CLOZE_TEXT", "0");
00029 define("CLOZE_SELECT", "1");
00030 define("CLOZE_TEST_IDENTIFIER", "CLOZE QUESTION");
00031
00042 class ASS_ClozeTest extends ASS_Question
00043 {
00052 var $cloze_text;
00053
00061 var $gaps;
00062
00070 var $start_tag;
00071
00079 var $end_tag;
00092 function ASS_ClozeTest(
00093 $title = "",
00094 $comment = "",
00095 $author = "",
00096 $owner = -1,
00097 $cloze_text = ""
00098 )
00099 {
00100 $this->start_tag = "<gap>";
00101 $this->end_tag = "</gap>";
00102 $this->ASS_Question($title, $comment, $author, $owner);
00103 $this->gaps = array();
00104 $this->set_cloze_text($cloze_text);
00105 }
00106
00115 function isComplete()
00116 {
00117 if (($this->title) and ($this->author) and ($this->cloze_text) and (count($this->gaps)))
00118 {
00119 return true;
00120 }
00121 else
00122 {
00123 return false;
00124 }
00125 }
00126
00135 function &createCloseTextArray()
00136 {
00137 $result = array();
00138 $search_pattern = "|<gap([^>]*?)>(.*?)</gap>|i";
00139 preg_match_all($search_pattern, $this->cloze_text, $gaps);
00140 if (count($gaps[0]))
00141 {
00142
00143 $delimiters = preg_split($search_pattern, $this->cloze_text, -1, PREG_SPLIT_OFFSET_CAPTURE);
00144 $result["gaps"] = array();
00145 foreach ($gaps[0] as $index => $gap)
00146 {
00147 $result["gaps"][$index] = array();
00148 $result["gaps"][$index]["gap"] = $gap;
00149 $result["gaps"][$index]["params"] = array();
00150 $result["gaps"][$index]["params"]["text"] = $gaps[1][$index];
00151
00152 if (preg_match("/name\=\"([^\"]*?)\"/", $gaps[1][$index], $params))
00153 {
00154 $result["gaps"][$index]["params"]["name"] = $params[1];
00155 }
00156 else
00157 {
00158 $result["gaps"][$index]["params"]["name"] = $this->lng->txt("gap") . " " . ($index+1);
00159 }
00160 if (preg_match("/type\=\"([^\"]*?)\"/", $gaps[1][$index], $params))
00161 {
00162 $result["gaps"][$index]["params"]["type"] = $params[1];
00163 }
00164 else
00165 {
00166 $result["gaps"][$index]["params"]["type"] = "text";
00167 }
00168 if (preg_match("/shuffle\=\"([^\"]*?)\"/", $gaps[1][$index], $params))
00169 {
00170 $result["gaps"][$index]["params"]["shuffle"] = $params[1];
00171 }
00172 else
00173 {
00174 if (strcmp(strtolower($result["gaps"][$index]["params"]["type"]), "select") == 0)
00175 {
00176 $result["gaps"][$index]["params"]["shuffle"] = "yes";
00177 }
00178 }
00179 $result["gaps"][$index]["text"] = array();
00180 $result["gaps"][$index]["text"]["text"] = $gaps[2][$index];
00181 $textparams = preg_split("/(?<!\\\\),/", $gaps[2][$index]);
00182 foreach ($textparams as $key => $value)
00183 {
00184 $result["gaps"][$index]["text"][$key] = $value;
00185 }
00186 }
00187 $result["delimiters"] = $delimiters;
00188 }
00189
00190 return $result;
00191 }
00192
00201 function createCloseTextFromArray($assoc_array)
00202 {
00203 $this->cloze_text = "";
00204 if (count($assoc_array))
00205 {
00206 $gap = 0;
00207 foreach ($assoc_array["delimiters"] as $key => $value)
00208 {
00209 if (($key > 0) && ($key < count($assoc_array["delimiters"])))
00210 {
00211 if (strcmp($assoc_array["gaps"][$gap]["params"]["shuffle"], "") == 0)
00212 {
00213 $shuffle = "";
00214 }
00215 else
00216 {
00217 $shuffle = " shuffle=\"" . $assoc_array["gaps"][$gap]["params"]["shuffle"] . "\"";
00218 }
00219 $textarray = array();
00220 foreach ($assoc_array["gaps"][$gap]["text"] as $textindex => $textvalue)
00221 {
00222 if (preg_match("/\d+/", $textindex))
00223 {
00224 array_push($textarray, $textvalue);
00225 }
00226 }
00227 $this->cloze_text .= sprintf("<gap name=\"%s\" type=\"%s\"%s>%s</gap>",
00228 $assoc_array["gaps"][$gap]["params"]["name"],
00229 $assoc_array["gaps"][$gap]["params"]["type"],
00230 $shuffle,
00231 join(",", $textarray)
00232 );
00233 $gap++;
00234 }
00235 $this->cloze_text .= $value[0];
00236 }
00237 }
00238 }
00239
00248 function saveToDb($original_id = "")
00249 {
00250 global $ilias;
00251
00252 $db =& $ilias->db;
00253 $complete = 0;
00254 if ($this->isComplete())
00255 {
00256 $complete = 1;
00257 }
00258
00259 $estw_time = $this->getEstimatedWorkingTime();
00260 $estw_time = sprintf("%02d:%02d:%02d", $estw_time['h'], $estw_time['m'], $estw_time['s']);
00261 $shuffle = 1;
00262
00263 if (!$this->shuffle)
00264 {
00265 $shuffle = 0;
00266 }
00267
00268 if ($original_id)
00269 {
00270 $original_id = $db->quote($original_id);
00271 }
00272 else
00273 {
00274 $original_id = "NULL";
00275 }
00276
00277 if ($this->id == -1)
00278 {
00279
00280 $now = getdate();
00281 $created = sprintf("%04d%02d%02d%02d%02d%02d", $now['year'], $now['mon'], $now['mday'], $now['hours'], $now['minutes'], $now['seconds']);
00282 $query = sprintf("INSERT INTO qpl_questions (question_id, question_type_fi, obj_fi, title, comment, author, owner, question_text, working_time, shuffle, complete, created, original_id, TIMESTAMP) VALUES (NULL, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, NULL)",
00283 $db->quote($this->getQuestionType()),
00284 $db->quote($this->obj_id),
00285 $db->quote($this->title),
00286 $db->quote($this->comment),
00287 $db->quote($this->author),
00288 $db->quote($this->owner),
00289 $db->quote($this->cloze_text),
00290 $db->quote($estw_time),
00291 $db->quote("$this->shuffle"),
00292 $db->quote("$complete"),
00293 $db->quote($created),
00294 $original_id
00295 );
00296 $result = $db->query($query);
00297 if ($result == DB_OK)
00298 {
00299 $this->id = $this->ilias->db->getLastInsertId();
00300
00301
00302 $this->createPageObject();
00303
00304
00305 if ($this->getTestId() > 0)
00306 {
00307 $this->insertIntoTest($this->getTestId());
00308 }
00309 }
00310 }
00311 else
00312 {
00313
00314 $query = sprintf("UPDATE qpl_questions SET obj_fi = %s, title = %s, comment = %s, author = %s, question_text = %s, working_time = %s, shuffle = %s, complete = %s WHERE question_id = %s",
00315 $db->quote($this->obj_id. ""),
00316 $db->quote($this->title),
00317 $db->quote($this->comment),
00318 $db->quote($this->author),
00319 $db->quote($this->cloze_text),
00320 $db->quote($estw_time),
00321 $db->quote("$this->shuffle"),
00322 $db->quote("$complete"),
00323 $db->quote($this->id)
00324 );
00325 $result = $db->query($query);
00326 }
00327
00328 if ($result == DB_OK)
00329 {
00330
00331
00332
00333 $query = sprintf("DELETE FROM qpl_answers WHERE question_fi = %s",
00334 $db->quote($this->id)
00335 );
00336 $result = $db->query($query);
00337
00338 foreach ($this->gaps as $key => $value)
00339 {
00340 foreach ($value as $answer_id => $answer_obj)
00341 {
00342 $query = sprintf("INSERT INTO qpl_answers (answer_id, question_fi, gap_id, answertext, points, aorder, cloze_type, name, shuffle, correctness, TIMESTAMP) VALUES (NULL, %s, %s, %s, %s, %s, %s, %s, %s, %s, NULL)",
00343 $db->quote($this->id),
00344 $db->quote($key),
00345 $db->quote($answer_obj->get_answertext() . ""),
00346 $db->quote($answer_obj->get_points() . ""),
00347 $db->quote($answer_obj->get_order() . ""),
00348 $db->quote($answer_obj->get_cloze_type() . ""),
00349 $db->quote($answer_obj->get_name() . ""),
00350 $db->quote($answer_obj->get_shuffle() . ""),
00351 $db->quote($answer_obj->getState() . "")
00352 );
00353 $answer_result = $db->query($query);
00354 }
00355 }
00356 }
00357 parent::saveToDb($original_id);
00358 }
00359
00369 function loadFromDb($question_id)
00370 {
00371 global $ilias;
00372 $db =& $ilias->db;
00373
00374 $query = sprintf("SELECT * FROM qpl_questions WHERE question_id = %s",
00375 $db->quote($question_id)
00376 );
00377 $result = $db->query($query);
00378 if (strcmp(strtolower(get_class($result)), db_result) == 0) {
00379 if ($result->numRows() == 1) {
00380 $data = $result->fetchRow(DB_FETCHMODE_OBJECT);
00381 $this->id = $question_id;
00382 $this->obj_id = $data->obj_fi;
00383 $this->title = $data->title;
00384 $this->comment = $data->comment;
00385 $this->solution_hint = $data->solution_hint;
00386 $this->original_id = $data->original_id;
00387 $this->author = $data->author;
00388 $this->owner = $data->owner;
00389 $this->cloze_text = $data->question_text;
00390 $this->shuffle = $data->shuffle;
00391 $this->setEstimatedWorkingTime(substr($data->working_time, 0, 2), substr($data->working_time, 3, 2), substr($data->working_time, 6, 2));
00392 }
00393
00394 $query = sprintf("SELECT * FROM qpl_answers WHERE question_fi = %s ORDER BY gap_id, aorder ASC",
00395 $db->quote($question_id)
00396 );
00397 $result = $db->query($query);
00398 if (strcmp(strtolower(get_class($result)), db_result) == 0) {
00399 $counter = -1;
00400 while ($data = $result->fetchRow(DB_FETCHMODE_OBJECT)) {
00401 if ($data->gap_id != $counter) {
00402 $answer_array = array();
00403 array_push($this->gaps, $answer_array);
00404 $counter = $data->gap_id;
00405 }
00406 if ($data->cloze_type == CLOZE_SELECT)
00407 {
00408 if ($data->correctness == 0)
00409 {
00410
00411 $data->correctness = 1;
00412 $data->points = 0;
00413 }
00414 }
00415 array_push($this->gaps[$counter], new ASS_AnswerCloze($data->answertext, $data->points, $data->aorder, $data->correctness, $data->cloze_type, $data->name, $data->shuffle, $data->answer_id));
00416 }
00417 }
00418 }
00419 parent::loadFromDb($question_id);
00420 }
00421
00429 function duplicate($for_test = true, $title = "", $author = "", $owner = "")
00430 {
00431 if ($this->id <= 0)
00432 {
00433
00434 return;
00435 }
00436
00437 $clone = $this;
00438 include_once ("./assessment/classes/class.assQuestion.php");
00439 $original_id = ASS_Question::_getOriginalId($this->id);
00440 $clone->id = -1;
00441 if ($title)
00442 {
00443 $clone->setTitle($title);
00444 }
00445 if ($author)
00446 {
00447 $clone->setAuthor($author);
00448 }
00449 if ($owner)
00450 {
00451 $clone->setOwner($owner);
00452 }
00453 if ($for_test)
00454 {
00455 $clone->saveToDb($original_id);
00456 }
00457 else
00458 {
00459 $clone->saveToDb();
00460 }
00461
00462
00463 $clone->copyPageOfQuestion($original_id);
00464
00465 return $clone->id;
00466 }
00467
00477 function from_xml($xml_text)
00478 {
00479 $result = false;
00480 if (!empty($this->domxml))
00481 {
00482 $this->domxml->free();
00483 }
00484 $xml_text = preg_replace("/>\s*?</", "><", $xml_text);
00485 $this->domxml = domxml_open_mem($xml_text);
00486 if (!empty($this->domxml))
00487 {
00488 $root = $this->domxml->document_element();
00489 $item = $root->first_child();
00490 $this->setTitle($item->get_attribute("title"));
00491 $this->gaps = array();
00492 $itemnodes = $item->child_nodes();
00493 $materials = array();
00494 $gapcounter = 0;
00495 foreach ($itemnodes as $index => $node)
00496 {
00497 switch ($node->node_name())
00498 {
00499 case "qticomment":
00500 $comment = $node->get_content();
00501 if (strpos($comment, "ILIAS Version=") !== false)
00502 {
00503 }
00504 elseif (strpos($comment, "Questiontype=") !== false)
00505 {
00506 }
00507 elseif (strpos($comment, "Author=") !== false)
00508 {
00509 $comment = str_replace("Author=", "", $comment);
00510 $this->setAuthor($comment);
00511 }
00512 else
00513 {
00514 $this->setComment($comment);
00515 }
00516 break;
00517 case "itemmetadata":
00518 $md_array = array();
00519 $metanodes = $node->child_nodes();
00520 foreach ($metanodes as $metanode)
00521 {
00522 switch ($metanode->node_name())
00523 {
00524 case "qtimetadata":
00525 $metafields = $metanode->child_nodes();
00526 foreach ($metafields as $metafield)
00527 {
00528 switch ($metafield->node_name())
00529 {
00530 case "qtimetadatafield":
00531 $metafieldlist = $metafield->child_nodes();
00532 $md = array("label" => "", "entry" => "");
00533 foreach ($metafieldlist as $attr)
00534 {
00535 switch ($attr->node_name())
00536 {
00537 case "fieldlabel":
00538 $md["label"] = $attr->get_content();
00539 break;
00540 case "fieldentry":
00541 $md["entry"] = $attr->get_content();
00542 break;
00543 }
00544 }
00545 array_push($md_array, $md);
00546 break;
00547 }
00548 }
00549 break;
00550 }
00551 }
00552 foreach ($md_array as $md)
00553 {
00554 switch ($md["label"])
00555 {
00556 case "ILIAS_VERSION":
00557 break;
00558 case "QUESTIONTYPE":
00559 break;
00560 case "AUTHOR":
00561 $this->setAuthor($md["entry"]);
00562 break;
00563 }
00564 }
00565 break;
00566 case "duration":
00567 $iso8601period = $node->get_content();
00568 if (preg_match("/P(\d+)Y(\d+)M(\d+)DT(\d+)H(\d+)M(\d+)S/", $iso8601period, $matches))
00569 {
00570 $this->setEstimatedWorkingTime($matches[4], $matches[5], $matches[6]);
00571 }
00572 break;
00573 case "presentation":
00574 $flow = $node->first_child();
00575 $flownodes = $flow->child_nodes();
00576 foreach ($flownodes as $idx => $flownode)
00577 {
00578 if (strcmp($flownode->node_name(), "material") == 0)
00579 {
00580 $mattext = $flownode->first_child();
00581 array_push($materials, $mattext->get_content());
00582 }
00583 elseif (strcmp($flownode->node_name(), "response_str") == 0)
00584 {
00585 $ident = $flownode->get_attribute("ident");
00586 $this->gaps["$ident"] = array();
00587 $shuffle = "";
00588 $subnodes = $flownode->child_nodes();
00589 foreach ($subnodes as $node_type)
00590 {
00591 switch ($node_type->node_name())
00592 {
00593 case "render_choice":
00594 $render_type = $node_type;
00595 if (strcmp($render_type->node_name(), "render_choice") == 0)
00596 {
00597
00598 $shuffle = $render_type->get_attribute("shuffle");
00599 $labels = $render_type->child_nodes();
00600 foreach ($labels as $lidx => $response_label)
00601 {
00602 $material = $response_label->first_child();
00603 $mattext = $material->first_child();
00604 $shuf = 0;
00605 if (strcmp(strtolower($shuffle), "yes") == 0)
00606 {
00607 $shuf = 1;
00608 }
00609 array_push($this->gaps["$ident"], new ASS_AnswerCloze($mattext->get_content(), 0, count($this->gaps["$ident"]), 0, CLOZE_SELECT, $ident, $shuf));
00610 }
00611 }
00612 break;
00613 case "render_fib":
00614 break;
00615 case "material":
00616 $matlabel = $node_type->get_attribute("label");
00617 if (strcmp($matlabel, "suggested_solution") == 0)
00618 {
00619 $mattype = $node_type->first_child();
00620 if (strcmp($mattype->node_name(), "mattext") == 0)
00621 {
00622 $suggested_solution = $mattype->get_content();
00623 if ($suggested_solution)
00624 {
00625 if ($this->getId() < 1)
00626 {
00627 $this->saveToDb();
00628 }
00629 if (preg_match("/gap_(\d+)/", $ident, $matches))
00630 {
00631 $this->setSuggestedSolution($suggested_solution, $matches[1], true);
00632 }
00633 }
00634 }
00635 }
00636 break;
00637 }
00638 }
00639 }
00640 }
00641 break;
00642 case "resprocessing":
00643 $resproc_nodes = $node->child_nodes();
00644 foreach ($resproc_nodes as $index => $respcondition)
00645 {
00646 if (strcmp($respcondition->node_name(), "respcondition") == 0)
00647 {
00648 $respcondition_array =& ilQTIUtils::_getRespcondition($respcondition);
00649 $found_answer = 0;
00650 foreach ($this->gaps[$respcondition_array["conditionvar"]["respident"]] as $key => $value)
00651 {
00652 if (strcmp($value->get_answertext(), $respcondition_array["conditionvar"]["value"]) == 0)
00653 {
00654 $found_answer = 1;
00655 $this->gaps[$respcondition_array["conditionvar"]["respident"]][$key]->set_points($respcondition_array["setvar"]["points"]);
00656 if ($respcondition_array["conditionvar"]["selected"])
00657 {
00658 $this->gaps[$respcondition_array["conditionvar"]["respident"]][$key]->setChecked();
00659 }
00660 }
00661 }
00662 if (!$found_answer)
00663 {
00664
00665 array_push($this->gaps[$respcondition_array["conditionvar"]["respident"]], new ASS_AnswerCloze($respcondition_array["conditionvar"]["value"], $respcondition_array["setvar"]["points"], count($this->gaps[$respcondition_array["conditionvar"]["respident"]]), 1, CLOZE_TEXT, $respcondition_array["conditionvar"]["respident"], 0));
00666 }
00667 }
00668 }
00669 break;
00670 }
00671 }
00672 $this->gaps = array_values($this->gaps);
00673 $i = 0;
00674 foreach ($materials as $key => $value)
00675 {
00676 $this->cloze_text .= $value;
00677 $gaptext = $this->get_gap_text_list($i);
00678 if ($gaptext)
00679 {
00680 $type = " type=\"select\"";
00681 if ($this->gaps[$i][0]->get_cloze_type() == CLOZE_TEXT)
00682 {
00683 $type = " type=\"text\"";
00684 }
00685 $shuffle = " shuffle=\"yes\"";
00686 if (!$this->gaps[$i][0]->get_shuffle())
00687 {
00688 $shuffle = " shuffle=\"no\"";
00689 }
00690 $this->cloze_text .= "<gap$type$shuffle>$gaptext</gap>";
00691 }
00692 $i++;
00693 }
00694 $result = true;
00695 }
00696 return $result;
00697 }
00698
00708 function to_xml($a_include_header = true, $a_include_binary = true, $a_shuffle = false, $test_output = false)
00709 {
00710 if (!empty($this->domxml))
00711 {
00712 $this->domxml->free();
00713 }
00714 $xml_header = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<questestinterop></questestinterop>\n";
00715 $this->domxml = domxml_open_mem($xml_header);
00716 $root = $this->domxml->document_element();
00717
00718 $qtiIdent = $this->domxml->create_element("item");
00719 $qtiIdent->set_attribute("ident", "il_".IL_INST_ID."_qst_".$this->getId());
00720 $qtiIdent->set_attribute("title", $this->getTitle());
00721 $root->append_child($qtiIdent);
00722
00723 $qtiComment = $this->domxml->create_element("qticomment");
00724 $qtiCommentText = $this->domxml->create_text_node($this->getComment());
00725 $qtiComment->append_child($qtiCommentText);
00726 $qtiIdent->append_child($qtiComment);
00727
00728 $qtiDuration = $this->domxml->create_element("duration");
00729 $workingtime = $this->getEstimatedWorkingTime();
00730 $qtiDurationText = $this->domxml->create_text_node(sprintf("P0Y0M0DT%dH%dM%dS", $workingtime["h"], $workingtime["m"], $workingtime["s"]));
00731 $qtiDuration->append_child($qtiDurationText);
00732 $qtiIdent->append_child($qtiDuration);
00733
00734
00735 $qtiItemmetadata = $this->domxml->create_element("itemmetadata");
00736 $qtiMetadata = $this->domxml->create_element("qtimetadata");
00737
00738 $qtiMetadatafield = $this->domxml->create_element("qtimetadatafield");
00739 $qtiFieldlabel = $this->domxml->create_element("fieldlabel");
00740 $qtiFieldlabelText = $this->domxml->create_text_node("ILIAS_VERSION");
00741 $qtiFieldlabel->append_child($qtiFieldlabelText);
00742 $qtiFieldentry = $this->domxml->create_element("fieldentry");
00743 $qtiFieldentryText = $this->domxml->create_text_node($this->ilias->getSetting("ilias_version"));
00744 $qtiFieldentry->append_child($qtiFieldentryText);
00745 $qtiMetadatafield->append_child($qtiFieldlabel);
00746 $qtiMetadatafield->append_child($qtiFieldentry);
00747 $qtiMetadata->append_child($qtiMetadatafield);
00748
00749 $qtiMetadatafield = $this->domxml->create_element("qtimetadatafield");
00750 $qtiFieldlabel = $this->domxml->create_element("fieldlabel");
00751 $qtiFieldlabelText = $this->domxml->create_text_node("QUESTIONTYPE");
00752 $qtiFieldlabel->append_child($qtiFieldlabelText);
00753 $qtiFieldentry = $this->domxml->create_element("fieldentry");
00754 $qtiFieldentryText = $this->domxml->create_text_node(CLOZE_TEST_IDENTIFIER);
00755 $qtiFieldentry->append_child($qtiFieldentryText);
00756 $qtiMetadatafield->append_child($qtiFieldlabel);
00757 $qtiMetadatafield->append_child($qtiFieldentry);
00758 $qtiMetadata->append_child($qtiMetadatafield);
00759
00760 $qtiMetadatafield = $this->domxml->create_element("qtimetadatafield");
00761 $qtiFieldlabel = $this->domxml->create_element("fieldlabel");
00762 $qtiFieldlabelText = $this->domxml->create_text_node("AUTHOR");
00763 $qtiFieldlabel->append_child($qtiFieldlabelText);
00764 $qtiFieldentry = $this->domxml->create_element("fieldentry");
00765 $qtiFieldentryText = $this->domxml->create_text_node($this->getAuthor());
00766 $qtiFieldentry->append_child($qtiFieldentryText);
00767 $qtiMetadatafield->append_child($qtiFieldlabel);
00768 $qtiMetadatafield->append_child($qtiFieldentry);
00769 $qtiMetadata->append_child($qtiMetadatafield);
00770
00771 $qtiItemmetadata->append_child($qtiMetadata);
00772 $qtiIdent->append_child($qtiItemmetadata);
00773
00774
00775 $qtiPresentation = $this->domxml->create_element("presentation");
00776 $qtiPresentation->set_attribute("label", $this->getTitle());
00777
00778 $qtiFlow = $this->domxml->create_element("flow");
00779
00780 $text_parts = preg_split("/<gap.*?<\/gap>/", $this->get_cloze_text());
00781
00782 for ($i = 0; $i <= $this->get_gap_count(); $i++)
00783 {
00784
00785 $qtiMaterial = $this->domxml->create_element("material");
00786 $qtiMatText = $this->domxml->create_element("mattext");
00787 $qtiMatTextText = $this->domxml->create_text_node($text_parts[$i]);
00788 $qtiMatText->append_child($qtiMatTextText);
00789 $qtiMaterial->append_child($qtiMatText);
00790 $qtiFlow->append_child($qtiMaterial);
00791
00792 if ($i < $this->get_gap_count())
00793 {
00794
00795 $gap = $this->get_gap($i);
00796 if ($gap[0]->get_cloze_type() == CLOZE_SELECT)
00797 {
00798
00799 $qtiResponseStr = $this->domxml->create_element("response_str");
00800 $qtiResponseStr->set_attribute("ident", "gap_$i");
00801 $qtiResponseStr->set_attribute("rcardinality", "Single");
00802 $solution = $this->getSuggestedSolution($i);
00803 if (count($solution))
00804 {
00805 if (preg_match("/il_(\d*?)_(\w+)_(\d+)/", $solution["internal_link"], $matches))
00806 {
00807 $qtiMaterial = $this->domxml->create_element("material");
00808 $qtiMaterial->set_attribute("label", "suggested_solution");
00809 $qtiMatText = $this->domxml->create_element("mattext");
00810 $intlink = "il_" . IL_INST_ID . "_" . $matches[2] . "_" . $matches[3];
00811 if (strcmp($matches[1], "") != 0)
00812 {
00813 $intlink = $solution["internal_link"];
00814 }
00815 $qtiMatTextText = $this->domxml->create_text_node($intlink);
00816 $qtiMatText->append_child($qtiMatTextText);
00817 $qtiMaterial->append_child($qtiMatText);
00818 $qtiResponseStr->append_child($qtiMaterial);
00819 }
00820 }
00821
00822 $qtiRenderChoice = $this->domxml->create_element("render_choice");
00823
00824 if ($gap[0]->get_shuffle())
00825 {
00826 $qtiRenderChoice->set_attribute("shuffle", "Yes");
00827 }
00828 else
00829 {
00830 $qtiRenderChoice->set_attribute("shuffle", "No");
00831 }
00832
00833 $gkeys = array_keys($gap);
00834 if ($this->getshuffle() && $a_shuffle)
00835 {
00836 $gkeys = $this->pcArrayShuffle($gkeys);
00837 }
00838
00839
00840 foreach ($gkeys as $key)
00841 {
00842 $value = $gap[$key];
00843 $qtiResponseLabel = $this->domxml->create_element("response_label");
00844 $qtiResponseLabel->set_attribute("ident", $key);
00845 $qtiMaterial = $this->domxml->create_element("material");
00846 $qtiMatText = $this->domxml->create_element("mattext");
00847 $tmpvalue = $value->get_answertext();
00848 $qtiMatTextText = $this->domxml->create_text_node($tmpvalue);
00849 $qtiMatText->append_child($qtiMatTextText);
00850 $qtiMaterial->append_child($qtiMatText);
00851 $qtiResponseLabel->append_child($qtiMaterial);
00852 $qtiRenderChoice->append_child($qtiResponseLabel);
00853 }
00854 $qtiResponseStr->append_child($qtiRenderChoice);
00855 $qtiFlow->append_child($qtiResponseStr);
00856 }
00857 else
00858 {
00859
00860 $qtiResponseStr = $this->domxml->create_element("response_str");
00861 $qtiResponseStr->set_attribute("ident", "gap_$i");
00862 $qtiResponseStr->set_attribute("rcardinality", "Single");
00863 $solution = $this->getSuggestedSolution($i);
00864 if (count($solution))
00865 {
00866 if (preg_match("/il_(\d*?)_(\w+)_(\d+)/", $solution["internal_link"], $matches))
00867 {
00868 $qtiMaterial = $this->domxml->create_element("material");
00869 $qtiMaterial->set_attribute("label", "suggested_solution");
00870 $qtiMatText = $this->domxml->create_element("mattext");
00871 $intlink = "il_" . IL_INST_ID . "_" . $matches[2] . "_" . $matches[3];
00872 if (strcmp($matches[1], "") != 0)
00873 {
00874 $intlink = $solution["internal_link"];
00875 }
00876 $qtiMatTextText = $this->domxml->create_text_node($intlink);
00877 $qtiMatText->append_child($qtiMatTextText);
00878 $qtiMaterial->append_child($qtiMatText);
00879 $qtiResponseStr->append_child($qtiMaterial);
00880 }
00881 }
00882 $qtiRenderFib = $this->domxml->create_element("render_fib");
00883 $qtiRenderFib->set_attribute("fibtype", "String");
00884 $qtiRenderFib->set_attribute("prompt", "Box");
00885 $qtiResponseLabel = $this->domxml->create_element("response_label");
00886 $qtiResponseLabel->set_attribute("ident", $i);
00887 $qtiRenderFib->append_child($qtiResponseLabel);
00888 $qtiResponseStr->append_child($qtiRenderFib);
00889 $qtiFlow->append_child($qtiResponseStr);
00890 }
00891 }
00892 }
00893 $qtiPresentation->append_child($qtiFlow);
00894 $qtiIdent->append_child($qtiPresentation);
00895
00896
00897 $qtiResprocessing = $this->domxml->create_element("resprocessing");
00898 $qtiOutcomes = $this->domxml->create_element("outcomes");
00899 $qtiDecvar = $this->domxml->create_element("decvar");
00900 $qtiOutcomes->append_child($qtiDecvar);
00901 $qtiResprocessing->append_child($qtiOutcomes);
00902
00903 for ($i = 0; $i < $this->get_gap_count(); $i++)
00904 {
00905 $gap = $this->get_gap($i);
00906 if ($gap[0]->get_cloze_type() == CLOZE_SELECT)
00907 {
00908 foreach ($gap as $index => $answer)
00909 {
00910 $qtiRespcondition = $this->domxml->create_element("respcondition");
00911 $qtiRespcondition->set_attribute("continue", "Yes");
00912
00913 $qtiConditionvar = $this->domxml->create_element("conditionvar");
00914
00915 if (!$answer->isStateSet())
00916 {
00917 $qtinot = $this->domxml->create_element("not");
00918 }
00919
00920 $qtiVarequal = $this->domxml->create_element("varequal");
00921 $qtiVarequal->set_attribute("respident", "gap_$i");
00922 $qtiVarequalText = $this->domxml->create_text_node($answer->get_answertext());
00923 $qtiVarequal->append_child($qtiVarequalText);
00924 if (!$answer->isStateSet())
00925 {
00926 $qtiConditionvar->append_child($qtinot);
00927 $qtinot->append_child($qtiVarequal);
00928 }
00929 else
00930 {
00931 $qtiConditionvar->append_child($qtiVarequal);
00932 }
00933
00934 $qtiSetvar = $this->domxml->create_element("setvar");
00935 $qtiSetvar->set_attribute("action", "Add");
00936 $qtiSetvarText = $this->domxml->create_text_node($answer->get_points());
00937 $qtiSetvar->append_child($qtiSetvarText);
00938
00939 $qtiDisplayfeedback = $this->domxml->create_element("displayfeedback");
00940 $qtiDisplayfeedback->set_attribute("feedbacktype", "Response");
00941 $linkrefid = "";
00942 if ($answer->isStateSet())
00943 {
00944 $linkrefid = "$i" . "_True";
00945 }
00946 else
00947 {
00948 $linkrefid = "$i" . "_False_$index";
00949 }
00950 $qtiDisplayfeedback->set_attribute("linkrefid", $linkrefid);
00951 $qtiRespcondition->append_child($qtiConditionvar);
00952 $qtiRespcondition->append_child($qtiSetvar);
00953 $qtiRespcondition->append_child($qtiDisplayfeedback);
00954 $qtiResprocessing->append_child($qtiRespcondition);
00955 }
00956 }
00957 else
00958 {
00959 foreach ($gap as $index => $answer)
00960 {
00961 $qtiRespcondition = $this->domxml->create_element("respcondition");
00962 $qtiRespcondition->set_attribute("continue", "Yes");
00963
00964 $qtiConditionvar = $this->domxml->create_element("conditionvar");
00965 $qtiVarequal = $this->domxml->create_element("varequal");
00966 $qtiVarequal->set_attribute("respident", "gap_$i");
00967 $qtiVarequalText = $this->domxml->create_text_node($answer->get_answertext());
00968 $qtiVarequal->append_child($qtiVarequalText);
00969 $qtiConditionvar->append_child($qtiVarequal);
00970
00971 $qtiSetvar = $this->domxml->create_element("setvar");
00972 $qtiSetvar->set_attribute("action", "Add");
00973 $qtiSetvarText = $this->domxml->create_text_node($answer->get_points());
00974 $qtiSetvar->append_child($qtiSetvarText);
00975
00976 $qtiDisplayfeedback = $this->domxml->create_element("displayfeedback");
00977 $qtiDisplayfeedback->set_attribute("feedbacktype", "Response");
00978 $qtiDisplayfeedback->set_attribute("linkrefid", "$i" . "_True_$index");
00979 $qtiRespcondition->append_child($qtiConditionvar);
00980 $qtiRespcondition->append_child($qtiSetvar);
00981 $qtiRespcondition->append_child($qtiDisplayfeedback);
00982 $qtiResprocessing->append_child($qtiRespcondition);
00983 }
00984 }
00985 }
00986 $qtiIdent->append_child($qtiResprocessing);
00987
00988
00989 for ($i = 0; $i < $this->get_gap_count(); $i++)
00990 {
00991 $gap = $this->get_gap($i);
00992 if ($gap[0]->get_cloze_type() == CLOZE_SELECT)
00993 {
00994 foreach ($gap as $index => $answer)
00995 {
00996 $qtiItemfeedback = $this->domxml->create_element("itemfeedback");
00997 $linkrefid = "";
00998 if ($answer->isStateSet())
00999 {
01000 $linkrefid = "$i" . "_True";
01001 }
01002 else
01003 {
01004 $linkrefid = "$i" . "_False_$index";
01005 }
01006 $qtiItemfeedback->set_attribute("ident", $linkrefid);
01007 $qtiItemfeedback->set_attribute("view", "All");
01008
01009 $qtiFlowmat = $this->domxml->create_element("flow_mat");
01010 $qtiMaterial = $this->domxml->create_element("material");
01011 $qtiMattext = $this->domxml->create_element("mattext");
01012
01013 $qtiMattextText = $this->domxml->create_text_node("");
01014 $qtiMattext->append_child($qtiMattextText);
01015 $qtiMaterial->append_child($qtiMattext);
01016 $qtiFlowmat->append_child($qtiMaterial);
01017 $qtiItemfeedback->append_child($qtiFlowmat);
01018 $qtiIdent->append_child($qtiItemfeedback);
01019 }
01020 }
01021 else
01022 {
01023 foreach ($gap as $index => $answer)
01024 {
01025 $qtiItemfeedback = $this->domxml->create_element("itemfeedback");
01026 $linkrefid = "";
01027 if ($answer->isStateSet())
01028 {
01029 $linkrefid = "$i" . "_True_$index";
01030 }
01031 else
01032 {
01033 $linkrefid = "$i" . "_False_$index";
01034 }
01035 $qtiItemfeedback->set_attribute("ident", $linkrefid);
01036 $qtiItemfeedback->set_attribute("view", "All");
01037
01038 $qtiFlowmat = $this->domxml->create_element("flow_mat");
01039 $qtiMaterial = $this->domxml->create_element("material");
01040 $qtiMattext = $this->domxml->create_element("mattext");
01041
01042 $qtiMattextText = $this->domxml->create_text_node("");
01043 $qtiMattext->append_child($qtiMattextText);
01044 $qtiMaterial->append_child($qtiMattext);
01045 $qtiFlowmat->append_child($qtiMaterial);
01046 $qtiItemfeedback->append_child($qtiFlowmat);
01047 $qtiIdent->append_child($qtiItemfeedback);
01048 }
01049 }
01050 }
01051
01052 $xml = $this->domxml->dump_mem(true);
01053 if (!$a_include_header)
01054 {
01055 $pos = strpos($xml, "?>");
01056 $xml = substr($xml, $pos + 2);
01057 }
01058
01059 return $xml;
01060
01061 }
01062
01074 function set_cloze_text($cloze_text = "")
01075 {
01076 $this->gaps = array();
01077 $this->cloze_text =& $cloze_text;
01078 $close = $this->createCloseTextArray();
01079 if (count($close))
01080 {
01081 foreach ($close["gaps"] as $key => $value)
01082 {
01083 if (strcmp(strtolower($value["params"]["type"]), "select") == 0)
01084 {
01085 $type = CLOZE_SELECT;
01086 }
01087 else
01088 {
01089 $type = CLOZE_TEXT;
01090 }
01091 if ($type == CLOZE_TEXT)
01092 {
01093 $default_state = 1;
01094 }
01095 else
01096 {
01097 $default_state = 0;
01098 }
01099 $name = $value["params"]["name"];
01100 if (strcmp(strtolower($value["params"]["shuffle"]), "no") == 0)
01101 {
01102 $shuffle = 0;
01103 }
01104 else
01105 {
01106 $shuffle = 1;
01107 }
01108 $answer_array = array();
01109 foreach ($value["text"] as $index => $textvalue)
01110 {
01111 if (preg_match("/\d+/", $index))
01112 {
01113 $textvalue = str_replace("\,", ",", $textvalue);
01114 array_push($answer_array, new ASS_AnswerCloze($textvalue, 0, $index, $default_state, $type, $name, $shuffle));
01115 }
01116 }
01117 array_push($this->gaps, $answer_array);
01118 }
01119 }
01120 }
01121
01131 function get_cloze_text() {
01132 return $this->cloze_text;
01133 }
01134
01144 function get_start_tag() {
01145 return $this->start_tag;
01146 }
01147
01157 function get_end_tag() {
01158 return $this->end_tag;
01159 }
01160
01170 function set_start_tag($start_tag = "<gap>") {
01171 $this->start_tag = $start_tag;
01172 }
01173
01174
01184 function set_end_tag($end_tag = "</gap>") {
01185 $this->end_tag = $end_tag;
01186 }
01187
01196 function rebuild_cloze_text()
01197 {
01198 $close =& $this->createCloseTextArray();
01199 if (count($close))
01200 {
01201 for ($i = 0; $i < count($this->gaps); $i++)
01202 {
01203 $gaptext = $this->get_gap_text_list($i);
01204 $textparams = preg_split("/(?<!\\\\),/", $gaptext);
01205 $close["gaps"][$i]["text"] = array();
01206 $close["gaps"][$i]["text"]["text"] = $gaptext;
01207 foreach ($textparams as $key => $value)
01208 {
01209 $close["gaps"][$i]["text"][$key] = $value;
01210 }
01211 }
01212 }
01213 $this->createCloseTextFromArray($close);
01214 }
01215
01227 function get_gap($index = 0) {
01228 if ($index < 0) return array();
01229 if (count($this->gaps) < 1) return array();
01230 if ($index >= count($this->gaps)) return array();
01231 return $this->gaps[$index];
01232 }
01233
01243 function get_gap_count() {
01244 return count($this->gaps);
01245 }
01246
01259 function get_gap_text_list($index = 0, $separator = ",") {
01260 if ($index < 0) return "";
01261 if (count($this->gaps) < 1) return "";
01262 if ($index >= count($this->gaps)) return "";
01263 $result = array();
01264 foreach ($this->gaps[$index] as $key => $value) {
01265 array_push($result, str_replace(",", "\,", $value->get_answertext()));
01266 }
01267 return join($separator, $result);
01268 }
01278 function get_gap_text_count($index = 0) {
01279 if ($index < 0) return 0;
01280 if (count($this->gaps) < 1) return 0;
01281 if ($index >= count($this->gaps)) return 0;
01282 return count($this->gaps[$index]);
01283 }
01294 function delete_gap($index = 0) {
01295 if ($index < 0) return;
01296 if (count($this->gaps) < 1) return;
01297 if ($index >= count($this->gaps)) return;
01298 $close = $this->createCloseTextArray();
01299 unset($close["gaps"][$index]);
01300 $this->createCloseTextFromArray($close);
01301 unset($this->gaps[$index]);
01302 $this->gaps = array_values($this->gaps);
01303 }
01304
01313 function flush_gaps() {
01314 $this->gaps = array();
01315 }
01316
01328 function delete_answertext_by_index($gap_index = 0, $answertext_index = 0) {
01329 if ($gap_index < 0) return;
01330 if (count($this->gaps) < 1) return;
01331 if ($gap_index >= count($this->gaps)) return;
01332 $old_text = $this->get_gap_text_list($gap_index);
01333 if (count($this->gaps[$gap_index]) == 1) {
01334 $this->delete_gap($gap_index);
01335 } else {
01336 $close = $this->createCloseTextArray();
01337 unset($this->gaps[$gap_index][$answertext_index]);
01338 $this->gaps[$gap_index] = array_values($this->gaps[$gap_index]);
01339 unset($close["gaps"][$gap_index]["text"][$answertext_index]);
01340 $this->createCloseTextFromArray($close);
01341 }
01342 }
01343
01356 function set_answertext($index = 0, $answertext_index = 0, $answertext = "", $add_gaptext=0) {
01357 $answertext = str_replace("\,", ",", $answertext);
01358 if ($add_gaptext == 1) {
01359 $arr = $this->gaps[$index][0];
01360 if (strlen($this->gaps[$index][count($this->gaps[$index])-1]->get_answertext()) != 0) {
01361 $default_state = 0;
01362 if ($arr->get_cloze_type() == CLOZE_TEXT)
01363 {
01364 $default_state = 1;
01365 }
01366 array_push($this->gaps[$index], new ASS_AnswerCloze($answertext, 0, count($this->gaps[$index]),
01367 $default_state, $arr->get_cloze_type(),
01368 $arr->get_name(), $arr->get_shuffle()));
01369 $this->rebuild_cloze_text();
01370 }
01371 return;
01372 }
01373 if ($index < 0) return;
01374 if (count($this->gaps) < 1) return;
01375 if ($index >= count($this->gaps)) return;
01376 if ($answertext_index < 0) return;
01377 if (count($this->gaps[$index]) < 1) return;
01378 if ($answertext_index >= count($this->gaps[$index])) return;
01379
01380
01381 if (strlen($answertext) == 0) {
01382
01383 $this->delete_answertext($index, $this->gaps[$index][$answertext_index]->get_answertext());
01384 } else {
01385 $this->gaps[$index][$answertext_index]->set_answertext($answertext);
01386 $this->rebuild_cloze_text();
01387 }
01388 }
01389
01398 function update_all_gap_params() {
01399 global $lng;
01400 $close = $this->createCloseTextArray();
01401 for ($i = 0; $i < $this->get_gap_count(); $i++)
01402 {
01403 $gaptext = $this->get_gap_text_list($i);
01404 if ($this->gaps[$i][0]->get_cloze_type() == CLOZE_TEXT)
01405 {
01406 $close["gaps"][$i]["params"]["type"] = "text";
01407 if (array_key_exists("shuffle", $close["gaps"][$i]["params"]))
01408 {
01409 unset($close["gaps"][$i]["params"]["shuffle"]);
01410 }
01411 }
01412 else
01413 {
01414 $close["gaps"][$i]["params"]["type"] = "select";
01415 if ($this->gaps[$i][0]->get_shuffle() == 0)
01416 {
01417 $close["gaps"][$i]["params"]["shuffle"] = "no";
01418 }
01419 else
01420 {
01421 $close["gaps"][$i]["params"]["shuffle"] = "yes";
01422 }
01423 }
01424 $name = $this->gaps[$i][0]->get_name();
01425 if (!$name)
01426 {
01427 $name = $this->lng->txt("gap") . " " . ($i+1);
01428 }
01429 $close["gaps"][$i]["params"]["name"] = $name;
01430 }
01431 $this->createCloseTextFromArray($close);
01432 }
01433
01444 function set_cloze_type($index, $cloze_type = CLOZE_TEXT) {
01445 if ($index < 0) return;
01446 if (count($this->gaps) < 1) return;
01447 if ($index >= count($this->gaps)) return;
01448 $close = $this->createCloseTextArray();
01449 foreach ($this->gaps[$index] as $key => $value) {
01450 $this->gaps[$index][$key]->set_cloze_type($cloze_type);
01451 $this->gaps[$index][$key]->setState(1);
01452 }
01453 if ($cloze_type == CLOZE_TEXT)
01454 {
01455 $type = "text";
01456 }
01457 else
01458 {
01459 $type = "select";
01460 }
01461 $close["gaps"][$index]["type"] = $type;
01462 $this->createCloseTextFromArray($close);
01463 }
01464
01476 function set_gap_points($index = 0, $points = 0.0) {
01477 if ($index < 0) return;
01478 if (count($this->gaps) < 1) return;
01479 if ($index >= count($this->gaps)) return;
01480 foreach ($this->gaps[$index] as $key => $value) {
01481 $this->gaps[$index][$key]->set_points($points);
01482 }
01483 }
01484
01496 function set_gap_shuffle($index = 0, $shuffle = 1) {
01497 if ($index < 0) return;
01498 if (count($this->gaps) < 1) return;
01499 if ($index >= count($this->gaps)) return;
01500 foreach ($this->gaps[$index] as $key => $value) {
01501 $this->gaps[$index][$key]->set_shuffle($shuffle);
01502 }
01503 }
01504
01505
01518 function set_single_answer_points($index_gaps = 0, $index_answerobject = 0, $points = 0.0) {
01519 if ($index_gaps < 0) return;
01520 if (count($this->gaps) < 1) return;
01521 if ($index_gaps >= count($this->gaps)) return;
01522 if ($index_answerobject < 0) return;
01523 if (count($this->gaps[$index_gaps]) < 1) return;
01524 if ($index_answerobject >= count($this->gaps[$index_gaps])) return;
01525 $this->gaps[$index_gaps][$index_answerobject]->set_points($points);
01526 }
01527
01540 function set_single_answer_state($index_gaps = 0, $index_answerobject = 0, $state = 0) {
01541 if ($index_gaps < 0) return;
01542 if (count($this->gaps) < 1) return;
01543 if ($index_gaps >= count($this->gaps)) return;
01544 if ($index_answerobject < 0) return;
01545 if (count($this->gaps[$index_gaps]) < 1) return;
01546 if ($index_answerobject >= count($this->gaps[$index_gaps])) return;
01547 $this->gaps[$index_gaps][$index_answerobject]->setState($state);
01548 }
01549
01559 function getReachedPoints($user_id, $test_id) {
01560 $found_value1 = array();
01561 $found_value2 = array();
01562 $query = sprintf("SELECT * FROM tst_solutions WHERE user_fi = %s AND test_fi = %s AND question_fi = %s",
01563 $this->ilias->db->quote($user_id),
01564 $this->ilias->db->quote($test_id),
01565 $this->ilias->db->quote($this->getId())
01566 );
01567 $result = $this->ilias->db->query($query);
01568 $user_result = array();
01569 while ($data = $result->fetchRow(DB_FETCHMODE_OBJECT)) {
01570 if (strcmp($data->value2, "") != 0)
01571 {
01572 $user_result[$data->value1] = array(
01573 "gap_id" => $data->value1,
01574 "value" => $data->value2
01575 );
01576 }
01577 }
01578 $points = 0;
01579 $counter = 0;
01580 foreach ($user_result as $gap_id => $value) {
01581 if ($this->gaps[$gap_id][0]->get_cloze_type() == CLOZE_TEXT)
01582 {
01583 $foundsolution = 0;
01584 foreach ($this->gaps[$gap_id] as $k => $v) {
01585 if ((strcmp(strtolower($v->get_answertext()), strtolower($value["value"])) == 0) && (!$foundsolution)) {
01586 $points += $v->get_points();
01587 $foundsolution = 1;
01588 }
01589 }
01590 }
01591 else
01592 {
01593 if ($value["value"] >= 0)
01594 {
01595 foreach ($this->gaps[$gap_id] as $answerkey => $answer)
01596 {
01597 if ($value["value"] == $answerkey)
01598 {
01599 $points += $answer->get_points();
01600 }
01601 }
01602 }
01603 }
01604 }
01605 return $points;
01606 }
01607
01617 function getReachedInformation($user_id, $test_id) {
01618 $found_value1 = array();
01619 $found_value2 = array();
01620 $query = sprintf("SELECT * FROM tst_solutions WHERE user_fi = %s AND test_fi = %s AND question_fi = %s",
01621 $this->ilias->db->quote($user_id),
01622 $this->ilias->db->quote($test_id),
01623 $this->ilias->db->quote($this->getId())
01624 );
01625 $result = $this->ilias->db->query($query);
01626 while ($data = $result->fetchRow(DB_FETCHMODE_OBJECT)) {
01627 array_push($found_value1, $data->value1);
01628 array_push($found_value2, $data->value2);
01629 }
01630 $counter = 1;
01631 $user_result = array();
01632 foreach ($found_value1 as $key => $value) {
01633 if ($this->gaps[$value][0]->get_cloze_type() == CLOZE_TEXT)
01634 {
01635 $solution = array(
01636 "gap" => "$counter",
01637 "points" => 0,
01638 "true" => 0,
01639 "value" => $found_value2[$key]
01640 );
01641 foreach ($this->gaps[$value] as $k => $v) {
01642 if (strcmp(strtolower($v->get_answertext()), strtolower($found_value2[$key])) == 0) {
01643 $solution = array(
01644 "gap" => "$counter",
01645 "points" => $v->get_points(),
01646 "true" => 1,
01647 "value" => $found_value2[$key]
01648 );
01649 }
01650 }
01651 }
01652 else
01653 {
01654 $solution = array(
01655 "gap" => "$counter",
01656 "points" => 0,
01657 "true" => 0,
01658 "value" => $found_value2[$key]
01659 );
01660 if ($this->gaps[$value][$found_value1[$key]]->isStateSet()) {
01661 $solution["points"] = $this->gaps[$value][$found_value1[$key]]->get_points();
01662 $solution["true"] = 1;
01663 }
01664 }
01665 $counter++;
01666 $user_result[$value] = $solution;
01667 }
01668 return $user_result;
01669 }
01670
01679 function getMaximumPoints() {
01680 $points = 0;
01681 foreach ($this->gaps as $key => $value) {
01682 if ($value[0]->get_cloze_type() == CLOZE_TEXT) {
01683 $points += $value[0]->get_points();
01684 } else {
01685 $points_arr = array("set" => 0, "unset" => 0);
01686 foreach ($value as $key2 => $value2) {
01687 if ($value2->get_points() > $points_arr["set"])
01688 {
01689 $points_arr["set"] = $value2->get_points();
01690 }
01691 }
01692 $points += $points_arr["set"];
01693 }
01694 }
01695 return $points;
01696 }
01697
01708 function saveWorkingData($test_id, $limit_to = LIMIT_NO_LIMIT) {
01709 global $ilDB;
01710 global $ilUser;
01711 $db =& $ilDB->db;
01712
01713 $query = sprintf("DELETE FROM tst_solutions WHERE user_fi = %s AND test_fi = %s AND question_fi = %s",
01714 $db->quote($ilUser->id),
01715 $db->quote($test_id),
01716 $db->quote($this->getId())
01717 );
01718 $result = $db->query($query);
01719
01720 foreach ($_POST as $key => $value) {
01721 if (preg_match("/^gap_(\d+)/", $key, $matches)) {
01722 $query = sprintf("INSERT INTO tst_solutions (solution_id, user_fi, test_fi, question_fi, value1, value2, TIMESTAMP) VALUES (NULL, %s, %s, %s, %s, %s, NULL)",
01723 $db->quote($ilUser->id),
01724 $db->quote($test_id),
01725 $db->quote($this->getId()),
01726 $db->quote($matches[1]),
01727 $db->quote(ilUtil::stripSlashes($value))
01728 );
01729 $result = $db->query($query);
01730 }
01731 }
01732
01733 return true;
01734 }
01735
01736 function syncWithOriginal()
01737 {
01738 global $ilias;
01739 if ($this->original_id)
01740 {
01741 $complete = 0;
01742 if ($this->isComplete())
01743 {
01744 $complete = 1;
01745 }
01746 $db = & $ilias->db;
01747
01748 $estw_time = $this->getEstimatedWorkingTime();
01749 $estw_time = sprintf("%02d:%02d:%02d", $estw_time['h'], $estw_time['m'], $estw_time['s']);
01750
01751 $query = sprintf("UPDATE qpl_questions SET obj_fi = %s, title = %s, comment = %s, author = %s, question_text = %s, working_time = %s, shuffle = %s, complete = %s WHERE question_id = %s",
01752 $db->quote($this->obj_id. ""),
01753 $db->quote($this->title . ""),
01754 $db->quote($this->comment . ""),
01755 $db->quote($this->author . ""),
01756 $db->quote($this->cloze_text . ""),
01757 $db->quote($estw_time . ""),
01758 $db->quote($this->shuffle . ""),
01759 $db->quote($complete . ""),
01760 $db->quote($this->original_id . "")
01761 );
01762 $result = $db->query($query);
01763
01764 if ($result == DB_OK)
01765 {
01766
01767
01768 $query = sprintf("DELETE FROM qpl_answers WHERE question_fi = %s",
01769 $db->quote($this->original_id)
01770 );
01771 $result = $db->query($query);
01772
01773 foreach ($this->gaps as $key => $value)
01774 {
01775 foreach ($value as $answer_id => $answer_obj)
01776 {
01777 $query = sprintf("INSERT INTO qpl_answers (answer_id, question_fi, gap_id, answertext, points, aorder, cloze_type, name, shuffle, correctness, TIMESTAMP) VALUES (NULL, %s, %s, %s, %s, %s, %s, %s, %s, %s, NULL)",
01778 $db->quote($this->original_id . ""),
01779 $db->quote($key . ""),
01780 $db->quote($answer_obj->get_answertext() . ""),
01781 $db->quote($answer_obj->get_points() . ""),
01782 $db->quote($answer_obj->get_order() . ""),
01783 $db->quote($answer_obj->get_cloze_type() . ""),
01784 $db->quote($answer_obj->get_name() . ""),
01785 $db->quote($answer_obj->get_shuffle() . ""),
01786 $db->quote($answer_obj->getState() . "")
01787 );
01788 $answer_result = $db->query($query);
01789 }
01790 }
01791 }
01792 parent::syncWithOriginal();
01793 }
01794 }
01795
01804 function getQuestionType()
01805 {
01806 return 3;
01807 }
01808 }
01809
01810 ?>