00001 <?php
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 require_once "./assessment/classes/class.assQuestion.php";
00024 require_once "./assessment/classes/class.ilQTIUtils.php";
00025
00026 define("TEXT_QUESTION_IDENTIFIER", "TEXT QUESTION");
00027
00038 class ASS_TextQuestion extends ASS_Question
00039 {
00047 var $question;
00048
00056 var $maxNumOfChars;
00057
00065 var $points;
00066
00080 function ASS_TextQuestion(
00081 $title = "",
00082 $comment = "",
00083 $author = "",
00084 $owner = -1,
00085 $question = ""
00086 )
00087 {
00088 $this->ASS_Question($title, $comment, $author, $owner);
00089 $this->question = $question;
00090 $this->maxNumOfChars = 0;
00091 $this->points = 0;
00092 }
00093
00102 function isComplete()
00103 {
00104 if (($this->title) and ($this->author) and ($this->question))
00105 {
00106 return true;
00107 }
00108 else
00109 {
00110 return false;
00111 }
00112 }
00113
00123 function from_xml($xml_text)
00124 {
00125 $result = false;
00126 if (!empty($this->domxml))
00127 {
00128 $this->domxml->free();
00129 }
00130 $xml_text = preg_replace("/>\s*?</", "><", $xml_text);
00131 $this->domxml = domxml_open_mem($xml_text);
00132 if (!empty($this->domxml))
00133 {
00134 $root = $this->domxml->document_element();
00135 $item = $root->first_child();
00136 $this->setTitle($item->get_attribute("title"));
00137 $this->gaps = array();
00138 $itemnodes = $item->child_nodes();
00139 foreach ($itemnodes as $index => $node)
00140 {
00141 switch ($node->node_name())
00142 {
00143 case "qticomment":
00144 $comment = $node->get_content();
00145 if (strpos($comment, "ILIAS Version=") !== false)
00146 {
00147 }
00148 elseif (strpos($comment, "Questiontype=") !== false)
00149 {
00150 }
00151 elseif (strpos($comment, "Author=") !== false)
00152 {
00153 $comment = str_replace("Author=", "", $comment);
00154 $this->setAuthor($comment);
00155 }
00156 else
00157 {
00158 $this->setComment($comment);
00159 }
00160 break;
00161 case "duration":
00162 $iso8601period = $node->get_content();
00163 if (preg_match("/P(\d+)Y(\d+)M(\d+)DT(\d+)H(\d+)M(\d+)S/", $iso8601period, $matches))
00164 {
00165 $this->setEstimatedWorkingTime($matches[4], $matches[5], $matches[6]);
00166 }
00167 break;
00168 case "presentation":
00169 $flow = $node->first_child();
00170 $flownodes = $flow->child_nodes();
00171 foreach ($flownodes as $idx => $flownode)
00172 {
00173 if (strcmp($flownode->node_name(), "material") == 0)
00174 {
00175 $mattext = $flownode->first_child();
00176 $this->set_question($mattext->get_content());
00177 }
00178 elseif (strcmp($flownode->node_name(), "response_str") == 0)
00179 {
00180 $subnodes = $flownode->child_nodes();
00181 foreach ($subnodes as $node_type)
00182 {
00183 switch ($node_type->node_name())
00184 {
00185 case "render_fib":
00186 $render_choice = $node_type;
00187 if (strcmp($render_choice->node_name(), "render_fib") == 0)
00188 {
00189
00190 $maxchars = $render_choice->get_attribute("maxchars");
00191 $this->setMaxNumOfChars($maxchars);
00192 }
00193 break;
00194 case "material":
00195 $matlabel = $node_type->get_attribute("label");
00196 if (strcmp($matlabel, "suggested_solution") == 0)
00197 {
00198 $mattype = $node_type->first_child();
00199 if (strcmp($mattype->node_name(), "mattext") == 0)
00200 {
00201 $suggested_solution = $mattype->get_content();
00202 if ($suggested_solution)
00203 {
00204 if ($this->getId() < 1)
00205 {
00206 $this->saveToDb();
00207 }
00208 $this->setSuggestedSolution($suggested_solution, 0, true);
00209 }
00210 }
00211 }
00212 break;
00213 }
00214 }
00215 }
00216 }
00217 break;
00218 case "resprocessing":
00219 $resproc_nodes = $node->child_nodes();
00220 foreach ($resproc_nodes as $index => $respcondition)
00221 {
00222 if (strcmp($respcondition->node_name(), "outcomes") == 0)
00223 {
00224 $outcomes_nodes = $respcondition->child_nodes();
00225 foreach ($outcomes_nodes as $oidx => $decvar)
00226 {
00227 if (strcmp($decvar->node_name(), "decvar") == 0)
00228 {
00229 $maxpoints = $decvar->get_attribute("maxvalue");
00230 $this->setPoints($maxpoints);
00231 }
00232 }
00233 }
00234 }
00235 break;
00236 }
00237 }
00238 $result = true;
00239 }
00240 return $result;
00241 }
00242
00252 function to_xml($a_include_header = true, $a_include_binary = true, $a_shuffle = false, $test_output = false)
00253 {
00254 if (!empty($this->domxml))
00255 {
00256 $this->domxml->free();
00257 }
00258 $xml_header = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
00259 $xml_header .= "<questestinterop></questestinterop>\n";
00260 $this->domxml = domxml_open_mem($xml_header);
00261 $root = $this->domxml->document_element();
00262
00263 $qtiIdent = $this->domxml->create_element("item");
00264 $qtiIdent->set_attribute("ident", "il_".IL_INST_ID."_qst_".$this->getId());
00265 $qtiIdent->set_attribute("title", $this->getTitle());
00266 $root->append_child($qtiIdent);
00267
00268 $qtiComment = $this->domxml->create_element("qticomment");
00269 $qtiCommentText = $this->domxml->create_text_node($this->getComment());
00270 $qtiComment->append_child($qtiCommentText);
00271 $qtiIdent->append_child($qtiComment);
00272 $qtiComment = $this->domxml->create_element("qticomment");
00273 $qtiCommentText = $this->domxml->create_text_node("ILIAS Version=".$this->ilias->getSetting("ilias_version"));
00274 $qtiComment->append_child($qtiCommentText);
00275 $qtiIdent->append_child($qtiComment);
00276 $qtiComment = $this->domxml->create_element("qticomment");
00277 $qtiCommentText = $this->domxml->create_text_node("Questiontype=".TEXT_QUESTION_IDENTIFIER);
00278 $qtiComment->append_child($qtiCommentText);
00279 $qtiIdent->append_child($qtiComment);
00280 $qtiComment = $this->domxml->create_element("qticomment");
00281 $qtiCommentText = $this->domxml->create_text_node("Author=".$this->getAuthor());
00282 $qtiComment->append_child($qtiCommentText);
00283 $qtiIdent->append_child($qtiComment);
00284
00285 $qtiDuration = $this->domxml->create_element("duration");
00286 $workingtime = $this->getEstimatedWorkingTime();
00287 $qtiDurationText = $this->domxml->create_text_node(sprintf("P0Y0M0DT%dH%dM%dS", $workingtime["h"], $workingtime["m"], $workingtime["s"]));
00288 $qtiDuration->append_child($qtiDurationText);
00289 $qtiIdent->append_child($qtiDuration);
00290
00291 $qtiPresentation = $this->domxml->create_element("presentation");
00292 $qtiPresentation->set_attribute("label", $this->getTitle());
00293
00294 $qtiFlow = $this->domxml->create_element("flow");
00295
00296 $qtiMaterial = $this->domxml->create_element("material");
00297 $qtiMatText = $this->domxml->create_element("mattext");
00298 $qtiMatTextText = $this->domxml->create_text_node($this->get_question());
00299 $qtiMatText->append_child($qtiMatTextText);
00300 $qtiMaterial->append_child($qtiMatText);
00301 $qtiFlow->append_child($qtiMaterial);
00302
00303 $qtiResponseStr = $this->domxml->create_element("response_str");
00304 $qtiResponseStr->set_attribute("ident", "TEXT");
00305 $qtiResponseStr->set_attribute("rcardinality", "Ordered");
00306 $qtiRenderFib = $this->domxml->create_element("render_fib");
00307 $qtiRenderFib->set_attribute("fibtype", "String");
00308 $qtiRenderFib->set_attribute("prompt", "Box");
00309 $qtiResponseLabel = $this->domxml->create_element("response_label");
00310 $qtiResponseLabel->set_attribute("ident", "A");
00311 $qtiRenderFib->append_child($qtiResponseLabel);
00312 $qtiResponseStr->append_child($qtiRenderFib);
00313 if ($this->getMaxNumOfChars() > 0)
00314 {
00315 $qtiRenderFib->set_attribute("maxchars", $this->getMaxNumOfChars());
00316 }
00317 $solution = $this->getSuggestedSolution(0);
00318 if (count($solution))
00319 {
00320 if (preg_match("/il_(\d*?)_(\w+)_(\d+)/", $solution["internal_link"], $matches))
00321 {
00322 $qtiMaterial = $this->domxml->create_element("material");
00323 $qtiMaterial->set_attribute("label", "suggested_solution");
00324 $qtiMatText = $this->domxml->create_element("mattext");
00325 $intlink = "il_" . IL_INST_ID . "_" . $matches[2] . "_" . $matches[3];
00326 if (strcmp($matches[1], "") != 0)
00327 {
00328 $intlink = $solution["internal_link"];
00329 }
00330 $qtiMatTextText = $this->domxml->create_text_node($intlink);
00331 $qtiMatText->append_child($qtiMatTextText);
00332 $qtiMaterial->append_child($qtiMatText);
00333 $qtiResponseStr->append_child($qtiMaterial);
00334 }
00335 }
00336 $qtiFlow->append_child($qtiResponseStr);
00337 $qtiPresentation->append_child($qtiFlow);
00338 $qtiIdent->append_child($qtiPresentation);
00339
00340 $qtiResprocessing = $this->domxml->create_element("resprocessing");
00341 $qtiResprocessing->set_attribute("scoremodel", "HumanRater");
00342 $qtiOutcomes = $this->domxml->create_element("outcomes");
00343 $qtiDecvar = $this->domxml->create_element("decvar");
00344 $qtiDecvar->set_attribute("varname", "WritingScore");
00345 $qtiDecvar->set_attribute("vartype", "Integer");
00346 $qtiDecvar->set_attribute("minvalue", "0");
00347 $qtiDecvar->set_attribute("maxvalue", $this->getPoints());
00348 $qtiOutcomes->append_child($qtiDecvar);
00349 $qtiResprocessing->append_child($qtiOutcomes);
00350 $qtiIdent->append_child($qtiResprocessing);
00351
00352 $xml = $this->domxml->dump_mem(true);
00353 if (!$a_include_header)
00354 {
00355 $pos = strpos($xml, "?>");
00356 $xml = substr($xml, $pos + 2);
00357 }
00358 return $xml;
00359 }
00360
00369 function saveToDb($original_id = "")
00370 {
00371 global $ilias;
00372
00373 $complete = 0;
00374 if ($this->isComplete())
00375 {
00376 $complete = 1;
00377 }
00378 $db = & $ilias->db;
00379
00380 $estw_time = $this->getEstimatedWorkingTime();
00381 $estw_time = sprintf("%02d:%02d:%02d", $estw_time['h'], $estw_time['m'], $estw_time['s']);
00382
00383 if ($original_id)
00384 {
00385 $original_id = $db->quote($original_id);
00386 }
00387 else
00388 {
00389 $original_id = "NULL";
00390 }
00391
00392 if ($this->id == -1)
00393 {
00394
00395 $now = getdate();
00396 $question_type = $this->getQuestionType();
00397 $created = sprintf("%04d%02d%02d%02d%02d%02d", $now['year'], $now['mon'], $now['mday'], $now['hours'], $now['minutes'], $now['seconds']);
00398 $query = sprintf("INSERT INTO qpl_questions (question_id, question_type_fi, obj_fi, title, comment, author, owner, points, question_text, working_time, maxNumOfChars, complete, created, original_id, TIMESTAMP) VALUES (NULL, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, NULL)",
00399 $db->quote($question_type),
00400 $db->quote($this->obj_id),
00401 $db->quote($this->title),
00402 $db->quote($this->comment),
00403 $db->quote($this->author),
00404 $db->quote($this->owner),
00405 $db->quote($this->getPoints() . ""),
00406 $db->quote($this->question),
00407 $db->quote($estw_time),
00408 $db->quote($this->getMaxNumOfChars()),
00409 $db->quote("$complete"),
00410 $db->quote($created),
00411 $original_id
00412 );
00413 $result = $db->query($query);
00414
00415 if ($result == DB_OK)
00416 {
00417 $this->id = $this->ilias->db->getLastInsertId();
00418
00419
00420 $this->createPageObject();
00421
00422
00423 if ($this->getTestId() > 0)
00424 {
00425 $this->insertIntoTest($this->getTestId());
00426 }
00427 }
00428 }
00429 else
00430 {
00431
00432 $query = sprintf("UPDATE qpl_questions SET obj_fi = %s, title = %s, comment = %s, author = %s, points = %s, question_text = %s, working_time=%s, maxNumOfChars = %s, complete = %s WHERE question_id = %s",
00433 $db->quote($this->obj_id. ""),
00434 $db->quote($this->title),
00435 $db->quote($this->comment),
00436 $db->quote($this->author),
00437 $db->quote($this->getPoints() . ""),
00438 $db->quote($this->question),
00439 $db->quote($estw_time),
00440 $db->quote($this->getMaxNumOfChars()),
00441 $db->quote("$complete"),
00442 $db->quote($this->id)
00443 );
00444 $result = $db->query($query);
00445 }
00446 parent::saveToDb($original_id);
00447 }
00448
00458 function loadFromDb($question_id)
00459 {
00460 global $ilias;
00461
00462 $db = & $ilias->db;
00463 $query = sprintf("SELECT * FROM qpl_questions WHERE question_id = %s",
00464 $db->quote($question_id));
00465 $result = $db->query($query);
00466 if (strcmp(strtolower(get_class($result)), db_result) == 0)
00467 {
00468 if ($result->numRows() == 1)
00469 {
00470 $data = $result->fetchRow(DB_FETCHMODE_OBJECT);
00471 $this->id = $question_id;
00472 $this->title = $data->title;
00473 $this->comment = $data->comment;
00474 $this->solution_hint = $data->solution_hint;
00475 $this->original_id = $data->original_id;
00476 $this->obj_id = $data->obj_fi;
00477 $this->author = $data->author;
00478 $this->owner = $data->owner;
00479 $this->question = $data->question_text;
00480 $this->maxNumOfChars = $data->maxNumOfChars;
00481 $this->points = $data->points;
00482 $this->setEstimatedWorkingTime(substr($data->working_time, 0, 2), substr($data->working_time, 3, 2), substr($data->working_time, 6, 2));
00483 }
00484 }
00485 parent::loadFromDb($question_id);
00486 }
00487
00495 function duplicate($for_test = true, $title = "", $author = "", $owner = "")
00496 {
00497 if ($this->id <= 0)
00498 {
00499
00500 return;
00501 }
00502
00503 $clone = $this;
00504 $original_id = $this->id;
00505 if ($original_id <= 0)
00506 {
00507 $original_id = "";
00508 }
00509 $clone->id = -1;
00510 if ($title)
00511 {
00512 $clone->setTitle($title);
00513 }
00514
00515 if ($author)
00516 {
00517 $clone->setAuthor($author);
00518 }
00519 if ($owner)
00520 {
00521 $clone->setOwner($owner);
00522 }
00523
00524 if ($for_test)
00525 {
00526 $clone->saveToDb($original_id);
00527 }
00528 else
00529 {
00530 $clone->saveToDb();
00531 }
00532
00533
00534 $clone->copyPageOfQuestion($original_id);
00535
00536 return $clone->id;
00537 }
00538
00548 function get_question()
00549 {
00550 return $this->question;
00551 }
00552
00562 function set_question($question = "")
00563 {
00564 $this->question = $question;
00565 }
00566
00576 function getMaxNumOfChars()
00577 {
00578 if (strcmp($this->maxNumOfChars, "") == 0)
00579 {
00580 return 0;
00581 }
00582 else
00583 {
00584 return $this->maxNumOfChars;
00585 }
00586 }
00587
00597 function setMaxNumOfChars($maxchars = 0)
00598 {
00599 $this->maxNumOfChars = $maxchars;
00600 }
00601
00611 function getPoints()
00612 {
00613 if (strcmp($this->points, "") == 0)
00614 {
00615 return 0;
00616 }
00617 else
00618 {
00619 return $this->points;
00620 }
00621 }
00622
00632 function setPoints($points = 0)
00633 {
00634 $this->points = $points;
00635 }
00636
00645 function getMaximumPoints()
00646 {
00647 return $this->points;
00648 }
00649
00661 function setReachedPoints($user_id, $test_id, $points)
00662 {
00663 if (($points > 0) && ($points <= $this->getPoints()))
00664 {
00665 $query = sprintf("UPDATE tst_solutions SET points = %s WHERE user_fi = %s AND test_fi = %s AND question_fi = %s",
00666 $this->ilias->db->quote($points . ""),
00667 $this->ilias->db->quote($user_id . ""),
00668 $this->ilias->db->quote($test_id . ""),
00669 $this->ilias->db->quote($this->getId() . "")
00670 );
00671 $result = $this->ilias->db->query($query);
00672 return true;
00673 }
00674 else
00675 {
00676 return false;
00677 }
00678 }
00679
00691 function _setReachedPoints($user_id, $test_id, $question_id, $points, $maxpoints)
00692 {
00693 global $ilDB;
00694
00695 if (($points > 0) && ($points <= $maxpoints))
00696 {
00697 $query = sprintf("UPDATE tst_solutions SET points = %s WHERE user_fi = %s AND test_fi = %s AND question_fi = %s",
00698 $ilDB->quote($points . ""),
00699 $ilDB->quote($user_id . ""),
00700 $ilDB->quote($test_id . ""),
00701 $ilDB->quote($question_id . "")
00702 );
00703 $result = $this->ilias->db->query($query);
00704 return true;
00705 }
00706 else
00707 {
00708 return false;
00709 }
00710 }
00711
00721 function getReachedPoints($user_id, $test_id)
00722 {
00723 $query = sprintf("SELECT * FROM tst_solutions WHERE user_fi = %s AND test_fi = %s AND question_fi = %s",
00724 $this->ilias->db->quote($user_id),
00725 $this->ilias->db->quote($test_id),
00726 $this->ilias->db->quote($this->getId())
00727 );
00728 $result = $this->ilias->db->query($query);
00729 if ($result->numRows() == 1)
00730 {
00731 $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
00732 if ($row["points"])
00733 {
00734 return $row["points"];
00735 }
00736 }
00737 return 0;
00738 }
00739
00751 function _getReachedPoints($user_id, $test_id)
00752 {
00753 return 0;
00754 }
00755
00765 function getReachedInformation($user_id, $test_id)
00766 {
00767 $found_values = array();
00768 $query = sprintf("SELECT * FROM tst_solutions WHERE user_fi = %s AND test_fi = %s AND question_fi = %s",
00769 $this->ilias->db->quote($user_id),
00770 $this->ilias->db->quote($test_id),
00771 $this->ilias->db->quote($this->getId())
00772 );
00773 $result = $this->ilias->db->query($query);
00774 $user_result = array();
00775 while ($data = $result->fetchRow(DB_FETCHMODE_OBJECT))
00776 {
00777 $user_result = array(
00778 "value" => $data->value1
00779 );
00780 }
00781 return $user_result;
00782 }
00783
00794 function saveWorkingData($test_id, $limit_to = LIMIT_NO_LIMIT)
00795 {
00796 global $ilDB;
00797 global $ilUser;
00798
00799 $db =& $ilDB->db;
00800
00801 $query = sprintf("DELETE FROM tst_solutions WHERE user_fi = %s AND test_fi = %s AND question_fi = %s",
00802 $db->quote($ilUser->id),
00803 $db->quote($test_id),
00804 $db->quote($this->getId())
00805 );
00806 $result = $db->query($query);
00807
00808 $text = ilUtil::stripSlashes($_POST["TEXT"]);
00809 if ($this->getMaxNumOfChars())
00810 {
00811 $text = substr($text, 0, $this->getMaxNumOfChars());
00812 }
00813 $query = sprintf("INSERT INTO tst_solutions (solution_id, user_fi, test_fi, question_fi, value1, value2, TIMESTAMP) VALUES (NULL, %s, %s, %s, %s, NULL, NULL)",
00814 $db->quote($ilUser->id),
00815 $db->quote($test_id),
00816 $db->quote($this->getId()),
00817 $db->quote($text)
00818 );
00819 $result = $db->query($query);
00820 return true;
00821 }
00822
00823 function syncWithOriginal()
00824 {
00825 global $ilias;
00826 if ($this->original_id)
00827 {
00828 $complete = 0;
00829 if ($this->isComplete())
00830 {
00831 $complete = 1;
00832 }
00833 $db = & $ilias->db;
00834
00835 $estw_time = $this->getEstimatedWorkingTime();
00836 $estw_time = sprintf("%02d:%02d:%02d", $estw_time['h'], $estw_time['m'], $estw_time['s']);
00837
00838 $query = sprintf("UPDATE qpl_questions SET obj_fi = %s, title = %s, comment = %s, author = %s, question_text = %s, working_time=%s, maxNumOfChars = %s, complete = %s WHERE question_id = %s",
00839 $db->quote($this->obj_id. ""),
00840 $db->quote($this->title. ""),
00841 $db->quote($this->comment. ""),
00842 $db->quote($this->author. ""),
00843 $db->quote($this->question. ""),
00844 $db->quote($estw_time. ""),
00845 $db->quote($this->maxNumOfChars. ""),
00846 $db->quote($complete. ""),
00847 $db->quote($this->original_id. "")
00848 );
00849 $result = $db->query($query);
00850
00851 parent::syncWithOriginal();
00852 }
00853 }
00854
00855 function createRandomSolution($test_id, $user_id)
00856 {
00857 }
00858
00867 function getQuestionType()
00868 {
00869 return 8;
00870 }
00871 }
00872
00873 ?>