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.assAnswerMatching.php";
00026
00027 define ("MT_TERMS_PICTURES", 0);
00028 define ("MT_TERMS_DEFINITIONS", 1);
00029 define ("MATCHING_QUESTION_IDENTIFIER", "MATCHING QUESTION");
00040 class ASS_MatchingQuestion extends ASS_Question
00041 {
00049 var $question;
00050
00058 var $matchingpairs;
00059
00068 var $matching_type;
00069
00079 var $points;
00080
00094 function ASS_MatchingQuestion (
00095 $title = "",
00096 $comment = "",
00097 $author = "",
00098 $owner = -1,
00099 $question = "",
00100 $points = 0.0,
00101 $matching_type = MT_TERMS_DEFINITIONS
00102 )
00103 {
00104 $this->ASS_Question($title, $comment, $author, $owner);
00105 $this->matchingpairs = array();
00106 $this->question = $question;
00107 $this->points = $points;
00108 $this->matching_type = $matching_type;
00109 }
00110
00119 function isComplete()
00120 {
00121 if (($this->title) and ($this->author) and ($this->question) and (count($this->matchingpairs)))
00122 {
00123 return true;
00124 }
00125 else
00126 {
00127 return false;
00128 }
00129 }
00130
00140 function from_xml($xml_text)
00141 {
00142 $result = false;
00143 if (!empty($this->domxml))
00144 {
00145 $this->domxml->free();
00146 }
00147 $xml_text = preg_replace("/>\s*?</", "><", $xml_text);
00148 $this->domxml = domxml_open_mem($xml_text);
00149 if (!empty($this->domxml))
00150 {
00151 $root = $this->domxml->document_element();
00152 $item = $root->first_child();
00153 $this->setTitle($item->get_attribute("title"));
00154 $this->gaps = array();
00155 $itemnodes = $item->child_nodes();
00156 $materials = array();
00157 $images = array();
00158 $shuffle = "";
00159 foreach ($itemnodes as $index => $node)
00160 {
00161 switch ($node->node_name())
00162 {
00163 case "qticomment":
00164 $comment = $node->get_content();
00165 if (strpos($comment, "ILIAS Version=") !== false)
00166 {
00167 }
00168 elseif (strpos($comment, "Questiontype=") !== false)
00169 {
00170 }
00171 elseif (strpos($comment, "Author=") !== false)
00172 {
00173 $comment = str_replace("Author=", "", $comment);
00174 $this->setAuthor($comment);
00175 }
00176 else
00177 {
00178 $this->setComment($comment);
00179 }
00180 break;
00181 case "itemmetadata":
00182 $md_array = array();
00183 $metanodes = $node->child_nodes();
00184 foreach ($metanodes as $metanode)
00185 {
00186 switch ($metanode->node_name())
00187 {
00188 case "qtimetadata":
00189 $metafields = $metanode->child_nodes();
00190 foreach ($metafields as $metafield)
00191 {
00192 switch ($metafield->node_name())
00193 {
00194 case "qtimetadatafield":
00195 $metafieldlist = $metafield->child_nodes();
00196 $md = array("label" => "", "entry" => "");
00197 foreach ($metafieldlist as $attr)
00198 {
00199 switch ($attr->node_name())
00200 {
00201 case "fieldlabel":
00202 $md["label"] = $attr->get_content();
00203 break;
00204 case "fieldentry":
00205 $md["entry"] = $attr->get_content();
00206 break;
00207 }
00208 }
00209 array_push($md_array, $md);
00210 break;
00211 }
00212 }
00213 break;
00214 }
00215 }
00216 foreach ($md_array as $md)
00217 {
00218 switch ($md["label"])
00219 {
00220 case "ILIAS_VERSION":
00221 break;
00222 case "QUESTIONTYPE":
00223 break;
00224 case "AUTHOR":
00225 $this->setAuthor($md["entry"]);
00226 break;
00227 }
00228 }
00229 break;
00230 case "duration":
00231 $iso8601period = $node->get_content();
00232 if (preg_match("/P(\d+)Y(\d+)M(\d+)DT(\d+)H(\d+)M(\d+)S/", $iso8601period, $matches))
00233 {
00234 $this->setEstimatedWorkingTime($matches[4], $matches[5], $matches[6]);
00235 }
00236 break;
00237 case "presentation":
00238 $flow = $node->first_child();
00239 $flownodes = $flow->child_nodes();
00240 foreach ($flownodes as $idx => $flownode)
00241 {
00242 if (strcmp($flownode->node_name(), "material") == 0)
00243 {
00244 $mattext = $flownode->first_child();
00245 $this->set_question($mattext->get_content());
00246 }
00247 elseif (strcmp($flownode->node_name(), "response_grp") == 0)
00248 {
00249 $ident = $flownode->get_attribute("ident");
00250 if (strcmp($ident, "MQT") == 0)
00251 {
00252 $this->set_matching_type(MT_TERMS_DEFINITIONS);
00253 }
00254 elseif (strcmp($ident, "MQP") == 0)
00255 {
00256 $this->set_matching_type(MT_TERMS_PICTURES);
00257 }
00258 $subnodes = $flownode->child_nodes();
00259 foreach ($subnodes as $node_type)
00260 {
00261 switch ($node_type->node_name())
00262 {
00263 case "material":
00264 $matlabel = $node_type->get_attribute("label");
00265 if (strcmp($matlabel, "suggested_solution") == 0)
00266 {
00267 $mattype = $node_type->first_child();
00268 if (strcmp($mattype->node_name(), "mattext") == 0)
00269 {
00270 $suggested_solution = $mattype->get_content();
00271 if ($suggested_solution)
00272 {
00273 if ($this->getId() < 1)
00274 {
00275 $this->saveToDb();
00276 }
00277 $this->setSuggestedSolution($suggested_solution, 0, true);
00278 }
00279 }
00280 }
00281 break;
00282 case "render_choice":
00283 $render_choice = $node_type;
00284 $shuffle = $render_choice->get_attribute("shuffle");
00285 $shuf = 0;
00286 if (strcmp(strtolower($shuffle), "yes") == 0)
00287 {
00288 $shuf = 1;
00289 }
00290 $this->setShuffle($shuf);
00291 $labels = $render_choice->child_nodes();
00292 foreach ($labels as $lidx => $response_label)
00293 {
00294 $material = $response_label->first_child();
00295 if ($this->get_matching_type() == MT_TERMS_PICTURES)
00296 {
00297 $mattype = $material->first_child();
00298 if (strcmp($mattype->node_name(), "matimage") == 0)
00299 {
00300 $filename = $mattype->get_attribute("label");
00301 $image = base64_decode($mattype->get_content());
00302 $images["$filename"] = $image;
00303 $materials[$response_label->get_attribute("ident")] = $filename;
00304 }
00305 else
00306 {
00307 $materials[$response_label->get_attribute("ident")] = $mattype->get_content();
00308 }
00309 }
00310 else
00311 {
00312 $mattext = $material->first_child();
00313 $materials[$response_label->get_attribute("ident")] = $mattext->get_content();
00314 }
00315 }
00316 break;
00317 }
00318 }
00319 }
00320 }
00321 break;
00322 case "resprocessing":
00323 $resproc_nodes = $node->child_nodes();
00324 foreach ($resproc_nodes as $index => $respcondition)
00325 {
00326 if (strcmp($respcondition->node_name(), "respcondition") == 0)
00327 {
00328 $respcondition_array =& ilQTIUtils::_getRespcondition($respcondition);
00329 $pair = split(",", $respcondition_array["conditionvar"]["value"]);
00330 $this->add_matchingpair($materials[$pair[0]], $materials[$pair[1]], $respcondition_array["setvar"]["points"], $pair[0], $pair[1]);
00331 }
00332 }
00333 break;
00334 }
00335 }
00336 if (count($images))
00337 {
00338 $this->saveToDb();
00339 foreach ($images as $filename => $image)
00340 {
00341 if ($filename)
00342 {
00343 $imagepath = $this->getImagePath();
00344 if (!file_exists($imagepath))
00345 {
00346 ilUtil::makeDirParents($imagepath);
00347 }
00348 $imagepath .= $filename;
00349 $fh = fopen($imagepath, "wb");
00350 if ($fh == false)
00351 {
00352 global $ilErr;
00353 $ilErr->raiseError($this->lng->txt("error_save_image_file") . ": $php_errormsg", $ilErr->MESSAGE);
00354 return;
00355 }
00356 $imagefile = fwrite($fh, $image);
00357 fclose($fh);
00358
00359 $thumbpath = $imagepath . "." . "thumb.jpg";
00360 ilUtil::convertImage($imagepath, $thumbpath, "JPEG", 100);
00361 }
00362 }
00363 }
00364 $result = true;
00365 }
00366 return $result;
00367 }
00368
00378 function to_xml($a_include_header = true, $a_include_binary = true, $a_shuffle = false, $test_output = false)
00379 {
00380 if (!empty($this->domxml))
00381 {
00382 $this->domxml->free();
00383 }
00384 $xml_header = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<questestinterop></questestinterop>\n";
00385 $this->domxml = domxml_open_mem($xml_header);
00386 $root = $this->domxml->document_element();
00387
00388
00389 $qtiComment = $this->domxml->create_element("qticomment");
00390
00391
00392 $qtiIdent = $this->domxml->create_element("item");
00393 $qtiIdent->set_attribute("ident", "il_".IL_INST_ID."_qst_".$this->getId());
00394 $qtiIdent->set_attribute("title", $this->getTitle());
00395 $root->append_child($qtiIdent);
00396
00397
00398 $qtiComment = $this->domxml->create_element("qticomment");
00399 $qtiCommentText = $this->domxml->create_text_node($this->getComment());
00400 $qtiComment->append_child($qtiCommentText);
00401 $qtiIdent->append_child($qtiComment);
00402
00403
00404 $qtiDuration = $this->domxml->create_element("duration");
00405 $workingtime = $this->getEstimatedWorkingTime();
00406 $qtiDurationText = $this->domxml->create_text_node(sprintf("P0Y0M0DT%dH%dM%dS", $workingtime["h"], $workingtime["m"], $workingtime["s"]));
00407 $qtiDuration->append_child($qtiDurationText);
00408 $qtiIdent->append_child($qtiDuration);
00409
00410
00411 $qtiItemmetadata = $this->domxml->create_element("itemmetadata");
00412 $qtiMetadata = $this->domxml->create_element("qtimetadata");
00413
00414 $qtiMetadatafield = $this->domxml->create_element("qtimetadatafield");
00415 $qtiFieldlabel = $this->domxml->create_element("fieldlabel");
00416 $qtiFieldlabelText = $this->domxml->create_text_node("ILIAS_VERSION");
00417 $qtiFieldlabel->append_child($qtiFieldlabelText);
00418 $qtiFieldentry = $this->domxml->create_element("fieldentry");
00419 $qtiFieldentryText = $this->domxml->create_text_node($this->ilias->getSetting("ilias_version"));
00420 $qtiFieldentry->append_child($qtiFieldentryText);
00421 $qtiMetadatafield->append_child($qtiFieldlabel);
00422 $qtiMetadatafield->append_child($qtiFieldentry);
00423 $qtiMetadata->append_child($qtiMetadatafield);
00424
00425 $qtiMetadatafield = $this->domxml->create_element("qtimetadatafield");
00426 $qtiFieldlabel = $this->domxml->create_element("fieldlabel");
00427 $qtiFieldlabelText = $this->domxml->create_text_node("QUESTIONTYPE");
00428 $qtiFieldlabel->append_child($qtiFieldlabelText);
00429 $qtiFieldentry = $this->domxml->create_element("fieldentry");
00430 $qtiFieldentryText = $this->domxml->create_text_node(MATCHING_QUESTION_IDENTIFIER);
00431 $qtiFieldentry->append_child($qtiFieldentryText);
00432 $qtiMetadatafield->append_child($qtiFieldlabel);
00433 $qtiMetadatafield->append_child($qtiFieldentry);
00434 $qtiMetadata->append_child($qtiMetadatafield);
00435
00436 $qtiMetadatafield = $this->domxml->create_element("qtimetadatafield");
00437 $qtiFieldlabel = $this->domxml->create_element("fieldlabel");
00438 $qtiFieldlabelText = $this->domxml->create_text_node("AUTHOR");
00439 $qtiFieldlabel->append_child($qtiFieldlabelText);
00440 $qtiFieldentry = $this->domxml->create_element("fieldentry");
00441 $qtiFieldentryText = $this->domxml->create_text_node($this->getAuthor());
00442 $qtiFieldentry->append_child($qtiFieldentryText);
00443 $qtiMetadatafield->append_child($qtiFieldlabel);
00444 $qtiMetadatafield->append_child($qtiFieldentry);
00445 $qtiMetadata->append_child($qtiMetadatafield);
00446
00447 $qtiItemmetadata->append_child($qtiMetadata);
00448 $qtiIdent->append_child($qtiItemmetadata);
00449
00450
00451 $qtiPresentation = $this->domxml->create_element("presentation");
00452 $qtiPresentation->set_attribute("label", $this->getTitle());
00453
00454
00455 $qtiFlow = $this->domxml->create_element("flow");
00456
00457
00458 $qtiMaterial = $this->domxml->create_element("material");
00459 $qtiMatText = $this->domxml->create_element("mattext");
00460 $qtiMatTextText = $this->domxml->create_text_node($this->get_question());
00461 $qtiMatText->append_child($qtiMatTextText);
00462 $qtiMaterial->append_child($qtiMatText);
00463 $qtiFlow->append_child($qtiMaterial);
00464
00465
00466 $qtiResponseGrp = $this->domxml->create_element("response_grp");
00467 if ($this->get_matching_type() == MT_TERMS_PICTURES)
00468 {
00469 $qtiResponseGrp->set_attribute("ident", "MQP");
00470 $qtiResponseGrp->set_attribute("rcardinality", "Multiple");
00471 if ($this->getOutputType() == OUTPUT_JAVASCRIPT)
00472 {
00473 $qtiResponseGrp->set_attribute("output", "javascript");
00474 }
00475 }
00476 else
00477 {
00478 $qtiResponseGrp->set_attribute("ident", "MQT");
00479 $qtiResponseGrp->set_attribute("rcardinality", "Multiple");
00480 if ($this->getOutputType() == OUTPUT_JAVASCRIPT)
00481 {
00482 $qtiResponseGrp->set_attribute("output", "javascript");
00483 }
00484 }
00485 $solution = $this->getSuggestedSolution(0);
00486 if (count($solution))
00487 {
00488 if (preg_match("/il_(\d*?)_(\w+)_(\d+)/", $solution["internal_link"], $matches))
00489 {
00490 $qtiMaterial = $this->domxml->create_element("material");
00491 $qtiMaterial->set_attribute("label", "suggested_solution");
00492 $qtiMatText = $this->domxml->create_element("mattext");
00493 $intlink = "il_" . IL_INST_ID . "_" . $matches[2] . "_" . $matches[3];
00494 if (strcmp($matches[1], "") != 0)
00495 {
00496 $intlink = $solution["internal_link"];
00497 }
00498 $qtiMatTextText = $this->domxml->create_text_node($intlink);
00499 $qtiMatText->append_child($qtiMatTextText);
00500 $qtiMaterial->append_child($qtiMatText);
00501 $qtiResponseGrp->append_child($qtiMaterial);
00502 }
00503 }
00504 $qtiRenderChoice = $this->domxml->create_element("render_choice");
00505
00506
00507 if ($this->getShuffle())
00508 {
00509 $qtiRenderChoice->set_attribute("shuffle", "Yes");
00510 }
00511 else
00512 {
00513 $qtiRenderChoice->set_attribute("shuffle", "No");
00514 }
00515
00516
00517 $matchingtext_orders = array();
00518 foreach ($this->matchingpairs as $index => $matchingpair)
00519 {
00520 array_push($matchingtext_orders, $matchingpair->getTermId());
00521 }
00522
00523
00524 $pkeys = array_keys($this->matchingpairs);
00525 if ($this->getshuffle() && $a_shuffle)
00526 {
00527 $pkeys = $this->pcArrayShuffle($pkeys);
00528 }
00529
00530
00531 foreach ($pkeys as $index)
00532 {
00533 $matchingpair = $this->matchingpairs[$index];
00534
00535 $qtiResponseLabel = $this->domxml->create_element("response_label");
00536 $qtiResponseLabel->set_attribute("ident", $matchingpair->getDefinitionId());
00537 $qtiResponseLabel->set_attribute("match_max", "1");
00538 $qtiResponseLabel->set_attribute("match_group", join($matchingtext_orders, ","));
00539 $qtiMaterial = $this->domxml->create_element("material");
00540 if ($this->get_matching_type() == MT_TERMS_PICTURES)
00541 {
00542 $qtiMatImage = $this->domxml->create_element("matimage");
00543 $qtiMatImage->set_attribute("imagtype", "image/jpeg");
00544 $qtiMatImage->set_attribute("label", $matchingpair->getPicture());
00545 $qtiMatImage->set_attribute("embedded", "base64");
00546 $imagepath = $this->getImagePath() . $matchingpair->getPicture();
00547 $fh = @fopen($imagepath, "rb");
00548 if ($fh == false)
00549 {
00550
00551
00552
00553 }
00554 else
00555 {
00556 $imagefile = fread($fh, filesize($imagepath));
00557 fclose($fh);
00558 $base64 = base64_encode($imagefile);
00559 $qtiBase64Data = $this->domxml->create_text_node($base64);
00560 $qtiMatImage->append_child($qtiBase64Data);
00561 $qtiMaterial->append_child($qtiMatImage);
00562 }
00563 }
00564 else
00565 {
00566 $qtiMatText = $this->domxml->create_element("mattext");
00567 $qtiMatTextText = $this->domxml->create_text_node($matchingpair->getDefinition());
00568 $qtiMatText->append_child($qtiMatTextText);
00569 $qtiMaterial->append_child($qtiMatText);
00570 }
00571 $qtiResponseLabel->append_child($qtiMaterial);
00572 $qtiRenderChoice->append_child($qtiResponseLabel);
00573 }
00574
00575
00576 if ($this->getshuffle() && $a_shuffle)
00577 {
00578 $pkeys = $this->pcArrayShuffle($pkeys);
00579 }
00580
00581 foreach ($pkeys as $index)
00582 {
00583 $matchingpair = $this->matchingpairs[$index];
00584 $qtiResponseLabel = $this->domxml->create_element("response_label");
00585 $qtiResponseLabel->set_attribute("ident", $matchingpair->getTermId());
00586 $qtiMaterial = $this->domxml->create_element("material");
00587 $qtiMatText = $this->domxml->create_element("mattext");
00588 $qtiMatTextText = $this->domxml->create_text_node($matchingpair->getTerm());
00589 $qtiMatText->append_child($qtiMatTextText);
00590 $qtiMaterial->append_child($qtiMatText);
00591 $qtiResponseLabel->append_child($qtiMaterial);
00592 $qtiRenderChoice->append_child($qtiResponseLabel);
00593 }
00594 $qtiResponseGrp->append_child($qtiRenderChoice);
00595 $qtiFlow->append_child($qtiResponseGrp);
00596 $qtiPresentation->append_child($qtiFlow);
00597 $qtiIdent->append_child($qtiPresentation);
00598
00599
00600 $qtiResprocessing = $this->domxml->create_element("resprocessing");
00601 $qtiOutcomes = $this->domxml->create_element("outcomes");
00602 $qtiDecvar = $this->domxml->create_element("decvar");
00603 $qtiOutcomes->append_child($qtiDecvar);
00604 $qtiResprocessing->append_child($qtiOutcomes);
00605
00606
00607 foreach ($this->matchingpairs as $index => $matchingpair)
00608 {
00609 $qtiRespcondition = $this->domxml->create_element("respcondition");
00610 $qtiRespcondition->set_attribute("continue", "Yes");
00611
00612 $qtiConditionvar = $this->domxml->create_element("conditionvar");
00613 $qtiVarsubset = $this->domxml->create_element("varsubset");
00614 if ($this->get_matching_type() == MT_TERMS_PICTURES)
00615 {
00616 $qtiVarsubset->set_attribute("respident", "MQP");
00617 }
00618 else
00619 {
00620 $qtiVarsubset->set_attribute("respident", "MQT");
00621 }
00622 $qtiVarsubsetText = $this->domxml->create_text_node($matchingpair->getTermId() . "," . $matchingpair->getDefinitionId());
00623 $qtiVarsubset->append_child($qtiVarsubsetText);
00624 $qtiConditionvar->append_child($qtiVarsubset);
00625
00626 $qtiSetvar = $this->domxml->create_element("setvar");
00627 $qtiSetvar->set_attribute("action", "Add");
00628 $qtiSetvarText = $this->domxml->create_text_node($matchingpair->getPoints());
00629 $qtiSetvar->append_child($qtiSetvarText);
00630
00631 $qtiDisplayfeedback = $this->domxml->create_element("displayfeedback");
00632 $qtiDisplayfeedback->set_attribute("feedbacktype", "Response");
00633 $qtiDisplayfeedback->set_attribute("linkrefid", "correct_" . $matchingpair->getTermId() . "_" . $matchingpair->getDefinitionId());
00634 $qtiRespcondition->append_child($qtiConditionvar);
00635 $qtiRespcondition->append_child($qtiSetvar);
00636 $qtiRespcondition->append_child($qtiDisplayfeedback);
00637 $qtiResprocessing->append_child($qtiRespcondition);
00638 }
00639 $qtiIdent->append_child($qtiResprocessing);
00640
00641
00642 foreach ($this->matchingpairs as $index => $matchingpair)
00643 {
00644 $qtiItemfeedback = $this->domxml->create_element("itemfeedback");
00645 $qtiItemfeedback->set_attribute("ident", "correct_" . $matchingpair->getTermId() . "_" . $matchingpair->getDefinitionId());
00646 $qtiItemfeedback->set_attribute("view", "All");
00647
00648 $qtiFlowmat = $this->domxml->create_element("flow_mat");
00649 $qtiMaterial = $this->domxml->create_element("material");
00650 $qtiMattext = $this->domxml->create_element("mattext");
00651
00652 $qtiMattextText = $this->domxml->create_text_node("");
00653 $qtiMattext->append_child($qtiMattextText);
00654 $qtiMaterial->append_child($qtiMattext);
00655 $qtiFlowmat->append_child($qtiMaterial);
00656 $qtiItemfeedback->append_child($qtiFlowmat);
00657 $qtiIdent->append_child($qtiItemfeedback);
00658 }
00659
00660 $xml = $this->domxml->dump_mem(true);
00661 if (!$a_include_header)
00662 {
00663 $pos = strpos($xml, "?>");
00664 $xml = substr($xml, $pos + 2);
00665 }
00666
00667 return $xml;
00668
00669 }
00670
00679 function saveToDb($original_id = "")
00680 {
00681 global $ilias;
00682
00683 $db =& $ilias->db;
00684 $complete = 0;
00685 if ($this->isComplete())
00686 {
00687 $complete = 1;
00688 }
00689 $estw_time = $this->getEstimatedWorkingTime();
00690 $estw_time = sprintf("%02d:%02d:%02d", $estw_time['h'], $estw_time['m'], $estw_time['s']);
00691
00692 if ($original_id)
00693 {
00694 $original_id = $db->quote($original_id);
00695 }
00696 else
00697 {
00698 $original_id = "NULL";
00699 }
00700
00701 if ($this->id == -1)
00702 {
00703
00704 $now = getdate();
00705 $question_type = $this->getQuestionType();
00706 $created = sprintf("%04d%02d%02d%02d%02d%02d", $now['year'], $now['mon'], $now['mday'], $now['hours'], $now['minutes'], $now['seconds']);
00707 $query = sprintf("INSERT INTO qpl_questions (question_id, question_type_fi, obj_fi, title, comment, author, owner, question_text, working_time, matching_type, points, complete, created, original_id, TIMESTAMP) VALUES (NULL, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, NULL)",
00708 $db->quote($question_type. ""),
00709 $db->quote($this->obj_id. ""),
00710 $db->quote($this->title. ""),
00711 $db->quote($this->comment. ""),
00712 $db->quote($this->author. ""),
00713 $db->quote($this->owner. ""),
00714 $db->quote($this->question. ""),
00715 $db->quote($estw_time. ""),
00716 $db->quote($this->matching_type. ""),
00717 $db->quote($this->points. ""),
00718 $db->quote($complete. ""),
00719 $db->quote($created. ""),
00720 $original_id
00721 );
00722
00723 $result = $db->query($query);
00724 if ($result == DB_OK)
00725 {
00726 $this->id = $this->ilias->db->getLastInsertId();
00727
00728
00729 $this->createPageObject();
00730
00731
00732 if ($this->getTestId() > 0)
00733 {
00734 $this->insertIntoTest($this->getTestId());
00735 }
00736 }
00737 }
00738 else
00739 {
00740
00741 $query = sprintf("UPDATE qpl_questions SET obj_fi = %s, title = %s, comment = %s, author = %s, question_text = %s, working_time=%s, matching_type = %s, points = %s, complete = %s WHERE question_id = %s",
00742 $db->quote($this->obj_id. ""),
00743 $db->quote($this->title. ""),
00744 $db->quote($this->comment. ""),
00745 $db->quote($this->author. ""),
00746 $db->quote($this->question. ""),
00747 $db->quote($estw_time. ""),
00748 $db->quote($this->matching_type. ""),
00749 $db->quote($this->points. ""),
00750 $db->quote($complete. ""),
00751 $db->quote($this->id. "")
00752 );
00753 $result = $db->query($query);
00754 }
00755
00756 if ($result == DB_OK)
00757 {
00758
00759
00760 $query = sprintf("DELETE FROM qpl_answers WHERE question_fi = %s",
00761 $db->quote($this->id)
00762 );
00763 $result = $db->query($query);
00764
00765
00766 foreach ($this->matchingpairs as $key => $value)
00767 {
00768 $matching_obj = $this->matchingpairs[$key];
00769 $query = sprintf("INSERT INTO qpl_answers (answer_id, question_fi, answertext, points, aorder, matchingtext, matching_order, TIMESTAMP) VALUES (NULL, %s, %s, %s, %s, %s, %s, NULL)",
00770 $db->quote($this->id),
00771 $db->quote($matching_obj->getTerm() . ""),
00772 $db->quote($matching_obj->getPoints() . ""),
00773 $db->quote($matching_obj->getTermId() . ""),
00774 $db->quote($matching_obj->getDefinition() . ""),
00775 $db->quote($matching_obj->getDefinitionId() . "")
00776 );
00777 $matching_result = $db->query($query);
00778 }
00779 }
00780 parent::saveToDb($original_id);
00781 }
00782
00792 function loadFromDb($question_id)
00793 {
00794 global $ilias;
00795 $db =& $ilias->db;
00796
00797 $query = sprintf("SELECT * FROM qpl_questions WHERE question_id = %s",
00798 $db->quote($question_id)
00799 );
00800 $result = $db->query($query);
00801 if (strcmp(strtolower(get_class($result)), db_result) == 0)
00802 {
00803 if ($result->numRows() == 1)
00804 {
00805 $data = $result->fetchRow(DB_FETCHMODE_OBJECT);
00806 $this->id = $question_id;
00807 $this->title = $data->title;
00808 $this->comment = $data->comment;
00809 $this->author = $data->author;
00810 $this->solution_hint = $data->solution_hint;
00811 $this->obj_id = $data->obj_fi;
00812 $this->original_id = $data->original_id;
00813 $this->owner = $data->owner;
00814 $this->matching_type = $data->matching_type;
00815 $this->question = $data->question_text;
00816 $this->points = $data->points;
00817 $this->setEstimatedWorkingTime(substr($data->working_time, 0, 2), substr($data->working_time, 3, 2), substr($data->working_time, 6, 2));
00818 }
00819
00820 $query = sprintf("SELECT * FROM qpl_answers WHERE question_fi = %s ORDER BY answer_id ASC",
00821 $db->quote($question_id)
00822 );
00823 $result = $db->query($query);
00824 if (strcmp(strtolower(get_class($result)), db_result) == 0)
00825 {
00826 while ($data = $result->fetchRow(DB_FETCHMODE_OBJECT))
00827 {
00828 array_push($this->matchingpairs, new ASS_AnswerMatching($data->answertext, $data->points, $data->aorder, $data->matchingtext, $data->matching_order));
00829 }
00830 }
00831 }
00832 parent::loadFromDb($question_id);
00833 }
00834
00842 function duplicate($for_test = true, $title = "", $author = "", $owner = "")
00843 {
00844 if ($this->id <= 0)
00845 {
00846
00847 return;
00848 }
00849
00850 $clone = $this;
00851 include_once ("./assessment/classes/class.assQuestion.php");
00852 $original_id = ASS_Question::_getOriginalId($this->id);
00853 $clone->id = -1;
00854 if ($title)
00855 {
00856 $clone->setTitle($title);
00857 }
00858 if ($author)
00859 {
00860 $clone->setAuthor($author);
00861 }
00862 if ($owner)
00863 {
00864 $clone->setOwner($owner);
00865 }
00866 if ($for_test)
00867 {
00868 $clone->saveToDb($original_id);
00869 }
00870 else
00871 {
00872 $clone->saveToDb();
00873 }
00874
00875
00876 $clone->copyPageOfQuestion($original_id);
00877
00878
00879 $clone->duplicateImages($original_id);
00880 return $clone->id;
00881 }
00882
00883 function duplicateImages($question_id)
00884 {
00885 if ($this->get_matching_type() == MT_TERMS_PICTURES)
00886 {
00887 $imagepath = $this->getImagePath();
00888 $imagepath_original = str_replace("/$this->id/images", "/$question_id/images", $imagepath);
00889 if (!file_exists($imagepath))
00890 {
00891 ilUtil::makeDirParents($imagepath);
00892 }
00893 foreach ($this->matchingpairs as $answer)
00894 {
00895 $filename = $answer->getPicture();
00896 if (!copy($imagepath_original . $filename, $imagepath . $filename))
00897 {
00898 print "image could not be duplicated!!!! ";
00899 }
00900 if (!copy($imagepath_original . $filename . ".thumb.jpg", $imagepath . $filename . ".thumb.jpg"))
00901 {
00902 print "image thumbnail could not be duplicated!!!! ";
00903 }
00904 }
00905 }
00906 }
00907
00917 function set_question($question = "")
00918 {
00919 $this->question = $question;
00920 }
00921
00931 function set_matching_type($matching_type = MT_TERMS_DEFINITIONS)
00932 {
00933 $this->matching_type = $matching_type;
00934 }
00935
00945 function get_question()
00946 {
00947 return $this->question;
00948 }
00949
00959 function get_matching_type()
00960 {
00961 return $this->matching_type;
00962 }
00963
00978 function add_matchingpair(
00979 $term = "",
00980 $picture_or_definition = "",
00981 $points = 0.0,
00982 $term_id = 0,
00983 $picture_or_definition_id = 0
00984 )
00985 {
00986
00987 if ($term_id == 0)
00988 {
00989 $term_id = $this->get_random_id();
00990 }
00991
00992 if ($picture_or_definition_id == 0)
00993 {
00994 $picture_or_definition_id = $this->get_random_id();
00995 }
00996 $matchingpair = new ASS_AnswerMatching($term, $points, $term_id, $picture_or_definition, $picture_or_definition_id);
00997 array_push($this->matchingpairs, $matchingpair);
00998 }
00999
01011 function get_matchingpair($index = 0)
01012 {
01013 if ($index < 0)
01014 {
01015 return NULL;
01016 }
01017 if (count($this->matchingpairs) < 1)
01018 {
01019 return NULL;
01020 }
01021 if ($index >= count($this->matchingpairs))
01022 {
01023 return NULL;
01024 }
01025 return $this->matchingpairs[$index];
01026 }
01027
01038 function delete_matchingpair($index = 0)
01039 {
01040 if ($index < 0)
01041 {
01042 return;
01043 }
01044 if (count($this->matchingpairs) < 1)
01045 {
01046 return;
01047 }
01048 if ($index >= count($this->matchingpairs))
01049 {
01050 return;
01051 }
01052 unset($this->matchingpairs[$index]);
01053 $this->matchingpairs = array_values($this->matchingpairs);
01054 }
01055
01064 function flush_matchingpairs()
01065 {
01066 $this->matchingpairs = array();
01067 }
01068
01078 function get_matchingpair_count()
01079 {
01080 return count($this->matchingpairs);
01081 }
01082
01092 function get_points()
01093 {
01094 return $this->points;
01095 }
01096
01106 function set_points($points = 0.0)
01107 {
01108 $this->points = $points;
01109 }
01110
01120 function getReachedPoints($user_id, $test_id)
01121 {
01122 $found_value1 = array();
01123 $found_value2 = array();
01124 $query = sprintf("SELECT * FROM tst_solutions WHERE user_fi = %s AND test_fi = %s AND question_fi = %s",
01125 $this->ilias->db->quote($user_id),
01126 $this->ilias->db->quote($test_id),
01127 $this->ilias->db->quote($this->getId())
01128 );
01129 $result = $this->ilias->db->query($query);
01130 while ($data = $result->fetchRow(DB_FETCHMODE_OBJECT))
01131 {
01132 if (strcmp($data->value1, "") != 0)
01133 {
01134 array_push($found_value1, $data->value1);
01135 array_push($found_value2, $data->value2);
01136 }
01137 }
01138 $points = 0;
01139 foreach ($found_value2 as $key => $value)
01140 {
01141 foreach ($this->matchingpairs as $answer_key => $answer_value)
01142 {
01143 if (($answer_value->getDefinitionId() == $value) and ($answer_value->getTermId() == $found_value1[$key]))
01144 {
01145 $points += $answer_value->getPoints();
01146 }
01147 }
01148 }
01149 return $points;
01150 }
01151
01161 function getReachedInformation($user_id, $test_id)
01162 {
01163 $found_value1 = array();
01164 $found_value2 = array();
01165 $query = sprintf("SELECT * FROM tst_solutions WHERE user_fi = %s AND test_fi = %s AND question_fi = %s",
01166 $this->ilias->db->quote($user_id),
01167 $this->ilias->db->quote($test_id),
01168 $this->ilias->db->quote($this->getId())
01169 );
01170 $result = $this->ilias->db->query($query);
01171 while ($data = $result->fetchRow(DB_FETCHMODE_OBJECT))
01172 {
01173 array_push($found_value1, $data->value1);
01174 array_push($found_value2, $data->value2);
01175 }
01176 $counter = 1;
01177 $user_result = array();
01178 foreach ($found_value1 as $key => $value)
01179 {
01180 $solution = array(
01181 "order" => "$counter",
01182 "points" => 0,
01183 "true" => 0,
01184 "term" => "",
01185 "definition" => ""
01186 );
01187 foreach ($this->matchingpairs as $answer_key => $answer_value)
01188 {
01189 if (($answer_value->getDefinitionId() == $found_value2[$key]) and ($answer_value->getTermId() == $value))
01190 {
01191 $points += $answer_value->getPoints();
01192 $solution["points"] = $answer_value->getPoints();
01193 $solution["term"] = $value;
01194 $solution["definition"] = $found_value2[$key];
01195 $solution["true"] = 1;
01196 }
01197 else
01198 {
01199 $solution["term"] = $value;
01200 $solution["definition"] = $found_value2[$key];
01201 }
01202 }
01203 $counter++;
01204 array_push($user_result, $solution);
01205 }
01206 return $user_result;
01207 }
01208
01217 function getMaximumPoints()
01218 {
01219 $points = 0;
01220 foreach ($this->matchingpairs as $key => $value)
01221 {
01222 if ($value->getPoints() > 0)
01223 {
01224 $points += $value->getPoints();
01225 }
01226 }
01227 return $points;
01228 }
01229
01240 function set_image_file($image_filename, $image_tempfilename = "")
01241 {
01242 $result = 0;
01243 if (!empty($image_tempfilename))
01244 {
01245 $image_filename = str_replace(" ", "_", $image_filename);
01246 $imagepath = $this->getImagePath();
01247 if (!file_exists($imagepath))
01248 {
01249 ilUtil::makeDirParents($imagepath);
01250 }
01251
01252 if (!ilUtil::moveUploadedFile($image_tempfilename, $image_filename, $imagepath.$image_filename))
01253 {
01254 $result = 2;
01255 }
01256 else
01257 {
01258 require_once "./content/classes/Media/class.ilObjMediaObject.php";
01259 $mimetype = ilObjMediaObject::getMimeType($imagepath . $image_filename);
01260 if (!preg_match("/^image/", $mimetype))
01261 {
01262 unlink($imagepath . $image_filename);
01263 $result = 1;
01264 }
01265 else
01266 {
01267
01268 $thumbpath = $imagepath . $image_filename . "." . "thumb.jpg";
01269 ilUtil::convertImage($imagepath.$image_filename, $thumbpath, "JPEG", 100);
01270 }
01271 }
01272 }
01273 return $result;
01274 }
01275
01285 function checkSaveData()
01286 {
01287 $result = true;
01288 $matching_values = array();
01289 foreach ($_POST as $key => $value)
01290 {
01291 if (preg_match("/^sel_matching_(\d+)/", $key, $matches))
01292 {
01293 if ((strcmp($value, "") != 0) && ($value != -1))
01294 {
01295 array_push($matching_values, $value);
01296 }
01297 }
01298 }
01299 $check_matching = array_flip($matching_values);
01300 if (count($check_matching) != count($matching_values))
01301 {
01302
01303 $result = false;
01304 sendInfo($this->lng->txt("duplicate_matching_values_selected"));
01305 }
01306 return $result;
01307 }
01308
01319 function saveWorkingData($test_id, $limit_to = LIMIT_NO_LIMIT)
01320 {
01321 global $ilDB;
01322 global $ilUser;
01323 $saveWorkingDataResult = $this->checkSaveData();
01324 if ($saveWorkingDataResult)
01325 {
01326 $db =& $ilDB->db;
01327
01328 $query = sprintf("DELETE FROM tst_solutions WHERE user_fi = %s AND test_fi = %s AND question_fi = %s",
01329 $db->quote($ilUser->id),
01330 $db->quote($test_id),
01331 $db->quote($this->getId())
01332 );
01333 $result = $db->query($query);
01334
01335 foreach ($_POST as $key => $value)
01336 {
01337 if (preg_match("/^sel_matching_(\d+)/", $key, $matches))
01338 {
01339 if (!(preg_match("/initial_value_\d+/", $value)))
01340 {
01341 $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)",
01342 $db->quote($ilUser->id),
01343 $db->quote($test_id),
01344 $db->quote($this->getId()),
01345 $db->quote($value),
01346 $db->quote($matches[1])
01347 );
01348 $result = $db->query($query);
01349 }
01350 }
01351 }
01352 $saveWorkingDataResult = true;
01353 }
01354
01355 return $saveWorkingDataResult;
01356 }
01357
01358 function get_random_id()
01359 {
01360 mt_srand((double)microtime()*1000000);
01361 $random_number = mt_rand(1, 100000);
01362 $found = FALSE;
01363 while ($found)
01364 {
01365 $found = FALSE;
01366 foreach ($this->matchingpairs as $key => $value)
01367 {
01368 if (($value->getTermId() == $random_number) || ($value->getDefinitionId() == $random_number))
01369 {
01370 $found = TRUE;
01371 $random_number++;
01372 }
01373 }
01374 }
01375 return $random_number;
01376 }
01377
01378 function syncWithOriginal()
01379 {
01380 global $ilias;
01381 if ($this->original_id)
01382 {
01383 $complete = 0;
01384 if ($this->isComplete())
01385 {
01386 $complete = 1;
01387 }
01388 $db = & $ilias->db;
01389
01390 $estw_time = $this->getEstimatedWorkingTime();
01391 $estw_time = sprintf("%02d:%02d:%02d", $estw_time['h'], $estw_time['m'], $estw_time['s']);
01392
01393 $query = sprintf("UPDATE qpl_questions SET obj_fi = %s, title = %s, comment = %s, author = %s, question_text = %s, working_time=%s, matching_type = %s, points = %s, complete = %s WHERE question_id = %s",
01394 $db->quote($this->obj_id. ""),
01395 $db->quote($this->title. ""),
01396 $db->quote($this->comment. ""),
01397 $db->quote($this->author. ""),
01398 $db->quote($this->question. ""),
01399 $db->quote($estw_time. ""),
01400 $db->quote($this->matching_type. ""),
01401 $db->quote($this->points. ""),
01402 $db->quote($complete. ""),
01403 $db->quote($this->original_id. "")
01404 );
01405 $result = $db->query($query);
01406
01407 if ($result == DB_OK)
01408 {
01409
01410
01411 $query = sprintf("DELETE FROM qpl_answers WHERE question_fi = %s",
01412 $db->quote($this->original_id)
01413 );
01414 $result = $db->query($query);
01415
01416 foreach ($this->matchingpairs as $key => $value)
01417 {
01418 $matching_obj = $this->matchingpairs[$key];
01419 $query = sprintf("INSERT INTO qpl_answers (answer_id, question_fi, answertext, points, aorder, matchingtext, matching_order, TIMESTAMP) VALUES (NULL, %s, %s, %s, %s, %s, %s, NULL)",
01420 $db->quote($this->original_id . ""),
01421 $db->quote($matching_obj->getTerm() . ""),
01422 $db->quote($matching_obj->getPoints() . ""),
01423 $db->quote($matching_obj->getTermId() . ""),
01424 $db->quote($matching_obj->getDefinition() . ""),
01425 $db->quote($matching_obj->getDefinitionId() . "")
01426 );
01427 $matching_result = $db->query($query);
01428 }
01429 }
01430 parent::syncWithOriginal();
01431 }
01432 }
01433
01434 function pc_array_shuffle($array) {
01435 $i = count($array);
01436 mt_srand((double)microtime()*1000000);
01437 while(--$i)
01438 {
01439 $j = mt_rand(0, $i);
01440 if ($i != $j)
01441 {
01442
01443 $tmp = $array[$j];
01444 $array[$j] = $array[$i];
01445 $array[$i] = $tmp;
01446 }
01447 }
01448 return $array;
01449 }
01450
01451 function createRandomSolution($test_id, $user_id)
01452 {
01453 global $ilDB;
01454 global $ilUser;
01455 $db =& $ilDB->db;
01456
01457 $query = sprintf("DELETE FROM tst_solutions WHERE user_fi = %s AND test_fi = %s AND question_fi = %s",
01458 $db->quote($user_id),
01459 $db->quote($test_id),
01460 $db->quote($this->getId())
01461 );
01462 $result = $db->query($query);
01463
01464 $terms = array();
01465 $definitions = array();
01466
01467 foreach ($this->matchingpairs as $key => $pair)
01468 {
01469 array_push($terms, $pair->getTermId());
01470 array_push($definitions, $pair->getDefinitionId());
01471 }
01472 $definitions = $this->pc_array_shuffle($definitions);
01473 foreach ($terms as $key => $value)
01474 {
01475 $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)",
01476 $db->quote($user_id),
01477 $db->quote($test_id),
01478 $db->quote($this->getId()),
01479 $db->quote($value),
01480 $db->quote($definitions[$key])
01481 );
01482 $result = $db->query($query);
01483 }
01484 }
01485
01494 function getQuestionType()
01495 {
01496 return 4;
01497 }
01498
01499 }
01500
01501 ?>