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 "duration":
00182 $iso8601period = $node->get_content();
00183 if (preg_match("/P(\d+)Y(\d+)M(\d+)DT(\d+)H(\d+)M(\d+)S/", $iso8601period, $matches))
00184 {
00185 $this->setEstimatedWorkingTime($matches[4], $matches[5], $matches[6]);
00186 }
00187 break;
00188 case "presentation":
00189 $flow = $node->first_child();
00190 $flownodes = $flow->child_nodes();
00191 foreach ($flownodes as $idx => $flownode)
00192 {
00193 if (strcmp($flownode->node_name(), "material") == 0)
00194 {
00195 $mattext = $flownode->first_child();
00196 $this->set_question($mattext->get_content());
00197 }
00198 elseif (strcmp($flownode->node_name(), "response_grp") == 0)
00199 {
00200 $ident = $flownode->get_attribute("ident");
00201 if (strcmp($ident, "MQT") == 0)
00202 {
00203 $this->set_matching_type(MT_TERMS_DEFINITIONS);
00204 }
00205 elseif (strcmp($ident, "MQP") == 0)
00206 {
00207 $this->set_matching_type(MT_TERMS_PICTURES);
00208 }
00209 $subnodes = $flownode->child_nodes();
00210 foreach ($subnodes as $node_type)
00211 {
00212 switch ($node_type->node_name())
00213 {
00214 case "material":
00215 $matlabel = $node_type->get_attribute("label");
00216 if (strcmp($matlabel, "suggested_solution") == 0)
00217 {
00218 $mattype = $node_type->first_child();
00219 if (strcmp($mattype->node_name(), "mattext") == 0)
00220 {
00221 $suggested_solution = $mattype->get_content();
00222 if ($suggested_solution)
00223 {
00224 if ($this->getId() < 1)
00225 {
00226 $this->saveToDb();
00227 }
00228 $this->setSuggestedSolution($suggested_solution, 0, true);
00229 }
00230 }
00231 }
00232 break;
00233 case "render_choice":
00234 $render_choice = $node_type;
00235 $shuffle = $render_choice->get_attribute("shuffle");
00236 $labels = $render_choice->child_nodes();
00237 foreach ($labels as $lidx => $response_label)
00238 {
00239 $material = $response_label->first_child();
00240 if ($this->get_matching_type() == MT_TERMS_PICTURES)
00241 {
00242 $mattype = $material->first_child();
00243 if (strcmp($mattype->node_name(), "matimage") == 0)
00244 {
00245 $filename = $mattype->get_attribute("label");
00246 $image = base64_decode($mattype->get_content());
00247 $images["$filename"] = $image;
00248 $materials[$response_label->get_attribute("ident")] = $filename;
00249 }
00250 else
00251 {
00252 $materials[$response_label->get_attribute("ident")] = $mattype->get_content();
00253 }
00254 }
00255 else
00256 {
00257 $mattext = $material->first_child();
00258 $materials[$response_label->get_attribute("ident")] = $mattext->get_content();
00259 }
00260 }
00261 break;
00262 }
00263 }
00264 }
00265 }
00266 break;
00267 case "resprocessing":
00268 $resproc_nodes = $node->child_nodes();
00269 foreach ($resproc_nodes as $index => $respcondition)
00270 {
00271 if (strcmp($respcondition->node_name(), "respcondition") == 0)
00272 {
00273 $respcondition_array =& ilQTIUtils::_getRespcondition($respcondition);
00274 $pair = split(",", $respcondition_array["conditionvar"]["value"]);
00275 $this->add_matchingpair($materials[$pair[0]], $materials[$pair[1]], $respcondition_array["setvar"]["points"], $pair[0], $pair[1]);
00276 }
00277 }
00278 break;
00279 }
00280 }
00281 if (count($images))
00282 {
00283 $this->saveToDb();
00284 foreach ($images as $filename => $image)
00285 {
00286 if ($filename)
00287 {
00288 $imagepath = $this->getImagePath();
00289 if (!file_exists($imagepath))
00290 {
00291 ilUtil::makeDirParents($imagepath);
00292 }
00293 $imagepath .= $filename;
00294 $fh = fopen($imagepath, "wb");
00295 if ($fh == false)
00296 {
00297 global $ilErr;
00298 $ilErr->raiseError($this->lng->txt("error_save_image_file") . ": $php_errormsg", $ilErr->WARNING);
00299 return;
00300 }
00301 $imagefile = fwrite($fh, $image);
00302 fclose($fh);
00303
00304 $thumbpath = $imagepath . "." . "thumb.jpg";
00305 ilUtil::convertImage($imagepath, $thumbpath, "JPEG", 100);
00306 }
00307 }
00308 }
00309 $result = true;
00310 }
00311 return $result;
00312 }
00313
00323 function to_xml($a_include_header = true, $a_include_binary = true, $a_shuffle = false, $test_output = false)
00324 {
00325 if (!empty($this->domxml))
00326 {
00327 $this->domxml->free();
00328 }
00329 $xml_header = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<questestinterop></questestinterop>\n";
00330 $this->domxml = domxml_open_mem($xml_header);
00331 $root = $this->domxml->document_element();
00332
00333
00334 $qtiComment = $this->domxml->create_element("qticomment");
00335
00336
00337 $qtiIdent = $this->domxml->create_element("item");
00338 $qtiIdent->set_attribute("ident", "il_".IL_INST_ID."_qst_".$this->getId());
00339 $qtiIdent->set_attribute("title", $this->getTitle());
00340 $root->append_child($qtiIdent);
00341
00342
00343 $qtiComment = $this->domxml->create_element("qticomment");
00344 $qtiCommentText = $this->domxml->create_text_node($this->getComment());
00345 $qtiComment->append_child($qtiCommentText);
00346 $qtiIdent->append_child($qtiComment);
00347 $qtiComment = $this->domxml->create_element("qticomment");
00348 $qtiCommentText = $this->domxml->create_text_node("ILIAS Version=".$this->ilias->getSetting("ilias_version"));
00349 $qtiComment->append_child($qtiCommentText);
00350 $qtiIdent->append_child($qtiComment);
00351 $qtiComment = $this->domxml->create_element("qticomment");
00352 $qtiCommentText = $this->domxml->create_text_node("Questiontype=".MATCHING_QUESTION_IDENTIFIER);
00353 $qtiComment->append_child($qtiCommentText);
00354 $qtiIdent->append_child($qtiComment);
00355 $qtiComment = $this->domxml->create_element("qticomment");
00356 $qtiCommentText = $this->domxml->create_text_node("Author=".$this->getAuthor());
00357 $qtiComment->append_child($qtiCommentText);
00358 $qtiIdent->append_child($qtiComment);
00359
00360 $qtiDuration = $this->domxml->create_element("duration");
00361 $workingtime = $this->getEstimatedWorkingTime();
00362 $qtiDurationText = $this->domxml->create_text_node(sprintf("P0Y0M0DT%dH%dM%dS", $workingtime["h"], $workingtime["m"], $workingtime["s"]));
00363 $qtiDuration->append_child($qtiDurationText);
00364 $qtiIdent->append_child($qtiDuration);
00365
00366
00367 $qtiPresentation = $this->domxml->create_element("presentation");
00368 $qtiPresentation->set_attribute("label", $this->getTitle());
00369
00370
00371 $qtiFlow = $this->domxml->create_element("flow");
00372
00373
00374 $qtiMaterial = $this->domxml->create_element("material");
00375 $qtiMatText = $this->domxml->create_element("mattext");
00376 $qtiMatTextText = $this->domxml->create_text_node($this->get_question());
00377 $qtiMatText->append_child($qtiMatTextText);
00378 $qtiMaterial->append_child($qtiMatText);
00379 $qtiFlow->append_child($qtiMaterial);
00380
00381
00382 $qtiResponseGrp = $this->domxml->create_element("response_grp");
00383 if ($this->get_matching_type() == MT_TERMS_PICTURES)
00384 {
00385 $qtiResponseGrp->set_attribute("ident", "MQP");
00386 $qtiResponseGrp->set_attribute("rcardinality", "Multiple");
00387 if ($this->getOutputType() == OUTPUT_JAVASCRIPT)
00388 {
00389 $qtiResponseGrp->set_attribute("output", "javascript");
00390 }
00391 }
00392 else
00393 {
00394 $qtiResponseGrp->set_attribute("ident", "MQT");
00395 $qtiResponseGrp->set_attribute("rcardinality", "Multiple");
00396 if ($this->getOutputType() == OUTPUT_JAVASCRIPT)
00397 {
00398 $qtiResponseGrp->set_attribute("output", "javascript");
00399 }
00400 }
00401 $solution = $this->getSuggestedSolution(0);
00402 if (count($solution))
00403 {
00404 if (preg_match("/il_(\d*?)_(\w+)_(\d+)/", $solution["internal_link"], $matches))
00405 {
00406 $qtiMaterial = $this->domxml->create_element("material");
00407 $qtiMaterial->set_attribute("label", "suggested_solution");
00408 $qtiMatText = $this->domxml->create_element("mattext");
00409 $intlink = "il_" . IL_INST_ID . "_" . $matches[2] . "_" . $matches[3];
00410 if (strcmp($matches[1], "") != 0)
00411 {
00412 $intlink = $solution["internal_link"];
00413 }
00414 $qtiMatTextText = $this->domxml->create_text_node($intlink);
00415 $qtiMatText->append_child($qtiMatTextText);
00416 $qtiMaterial->append_child($qtiMatText);
00417 $qtiResponseGrp->append_child($qtiMaterial);
00418 }
00419 }
00420 $qtiRenderChoice = $this->domxml->create_element("render_choice");
00421
00422
00423 if ($this->getShuffle())
00424 {
00425 $qtiRenderChoice->set_attribute("shuffle", "yes");
00426 }
00427 else
00428 {
00429 $qtiRenderChoice->set_attribute("shuffle", "no");
00430 }
00431
00432
00433 $matchingtext_orders = array();
00434 foreach ($this->matchingpairs as $index => $matchingpair)
00435 {
00436 array_push($matchingtext_orders, $matchingpair->getTermId());
00437 }
00438
00439
00440 $pkeys = array_keys($this->matchingpairs);
00441 if ($this->getshuffle() && $a_shuffle)
00442 {
00443 $pkeys = $this->pcArrayShuffle($pkeys);
00444 }
00445
00446
00447 foreach ($pkeys as $index)
00448 {
00449 $matchingpair = $this->matchingpairs[$index];
00450
00451 $qtiResponseLabel = $this->domxml->create_element("response_label");
00452 $qtiResponseLabel->set_attribute("ident", $matchingpair->getDefinitionId());
00453 $qtiResponseLabel->set_attribute("match_max", "1");
00454 $qtiResponseLabel->set_attribute("match_group", join($matchingtext_orders, ","));
00455 $qtiMaterial = $this->domxml->create_element("material");
00456 if ($this->get_matching_type() == MT_TERMS_PICTURES)
00457 {
00458 $qtiMatImage = $this->domxml->create_element("matimage");
00459 $qtiMatImage->set_attribute("imagtype", "image/jpeg");
00460 $qtiMatImage->set_attribute("label", $matchingpair->getPicture());
00461 $qtiMatImage->set_attribute("embedded", "base64");
00462 $imagepath = $this->getImagePath() . $matchingpair->getPicture();
00463 $fh = @fopen($imagepath, "rb");
00464 if ($fh == false)
00465 {
00466
00467
00468
00469 }
00470 else
00471 {
00472 $imagefile = fread($fh, filesize($imagepath));
00473 fclose($fh);
00474 $base64 = base64_encode($imagefile);
00475 $qtiBase64Data = $this->domxml->create_text_node($base64);
00476 $qtiMatImage->append_child($qtiBase64Data);
00477 $qtiMaterial->append_child($qtiMatImage);
00478 }
00479 }
00480 else
00481 {
00482 $qtiMatText = $this->domxml->create_element("mattext");
00483 $qtiMatTextText = $this->domxml->create_text_node($matchingpair->getDefinition());
00484 $qtiMatText->append_child($qtiMatTextText);
00485 $qtiMaterial->append_child($qtiMatText);
00486 }
00487 $qtiResponseLabel->append_child($qtiMaterial);
00488 $qtiRenderChoice->append_child($qtiResponseLabel);
00489 }
00490
00491 if ($a_shuffle)
00492 {
00493 $pkeys = $this->pcArrayShuffle($pkeys);
00494 }
00495
00496
00497 foreach ($this->matchingpairs as $index => $matchingpair)
00498 {
00499 $qtiResponseLabel = $this->domxml->create_element("response_label");
00500 $qtiResponseLabel->set_attribute("ident", $matchingpair->getTermId());
00501 $qtiMaterial = $this->domxml->create_element("material");
00502 $qtiMatText = $this->domxml->create_element("mattext");
00503 $qtiMatTextText = $this->domxml->create_text_node($matchingpair->getTerm());
00504 $qtiMatText->append_child($qtiMatTextText);
00505 $qtiMaterial->append_child($qtiMatText);
00506 $qtiResponseLabel->append_child($qtiMaterial);
00507 $qtiRenderChoice->append_child($qtiResponseLabel);
00508 }
00509 $qtiResponseGrp->append_child($qtiRenderChoice);
00510 $qtiFlow->append_child($qtiResponseGrp);
00511 $qtiPresentation->append_child($qtiFlow);
00512 $qtiIdent->append_child($qtiPresentation);
00513
00514
00515 $qtiResprocessing = $this->domxml->create_element("resprocessing");
00516 $qtiOutcomes = $this->domxml->create_element("outcomes");
00517 $qtiDecvar = $this->domxml->create_element("decvar");
00518 $qtiOutcomes->append_child($qtiDecvar);
00519 $qtiResprocessing->append_child($qtiOutcomes);
00520
00521
00522 foreach ($this->matchingpairs as $index => $matchingpair)
00523 {
00524 $qtiRespcondition = $this->domxml->create_element("respcondition");
00525 $qtiRespcondition->set_attribute("continue", "Yes");
00526
00527 $qtiConditionvar = $this->domxml->create_element("conditionvar");
00528 $qtiVarsubset = $this->domxml->create_element("varsubset");
00529 if ($this->get_matching_type() == MT_TERMS_PICTURES)
00530 {
00531 $qtiVarsubset->set_attribute("respident", "MQP");
00532 }
00533 else
00534 {
00535 $qtiVarsubset->set_attribute("respident", "MQT");
00536 }
00537 $qtiVarsubsetText = $this->domxml->create_text_node($matchingpair->getTermId() . "," . $matchingpair->getDefinitionId());
00538 $qtiVarsubset->append_child($qtiVarsubsetText);
00539 $qtiConditionvar->append_child($qtiVarsubset);
00540
00541 $qtiSetvar = $this->domxml->create_element("setvar");
00542 $qtiSetvar->set_attribute("action", "Add");
00543 $qtiSetvarText = $this->domxml->create_text_node($matchingpair->getPoints());
00544 $qtiSetvar->append_child($qtiSetvarText);
00545
00546 $qtiDisplayfeedback = $this->domxml->create_element("displayfeedback");
00547 $qtiDisplayfeedback->set_attribute("feedbacktype", "Response");
00548 $qtiDisplayfeedback->set_attribute("linkrefid", "correct_" . $matchingpair->getTermId() . "_" . $matchingpair->getDefinitionId());
00549 $qtiRespcondition->append_child($qtiConditionvar);
00550 $qtiRespcondition->append_child($qtiSetvar);
00551 $qtiRespcondition->append_child($qtiDisplayfeedback);
00552 $qtiResprocessing->append_child($qtiRespcondition);
00553 }
00554 $qtiIdent->append_child($qtiResprocessing);
00555
00556
00557 foreach ($this->matchingpairs as $index => $matchingpair)
00558 {
00559 $qtiItemfeedback = $this->domxml->create_element("itemfeedback");
00560 $qtiItemfeedback->set_attribute("ident", "correct_" . $matchingpair->getTermId() . "_" . $matchingpair->getDefinitionId());
00561 $qtiItemfeedback->set_attribute("view", "All");
00562
00563 $qtiFlowmat = $this->domxml->create_element("flow_mat");
00564 $qtiMaterial = $this->domxml->create_element("material");
00565 $qtiMattext = $this->domxml->create_element("mattext");
00566
00567 $qtiMattextText = $this->domxml->create_text_node("");
00568 $qtiMattext->append_child($qtiMattextText);
00569 $qtiMaterial->append_child($qtiMattext);
00570 $qtiFlowmat->append_child($qtiMaterial);
00571 $qtiItemfeedback->append_child($qtiFlowmat);
00572 $qtiIdent->append_child($qtiItemfeedback);
00573 }
00574
00575 $xml = $this->domxml->dump_mem(true);
00576 if (!$a_include_header)
00577 {
00578 $pos = strpos($xml, "?>");
00579 $xml = substr($xml, $pos + 2);
00580 }
00581
00582 return $xml;
00583
00584 }
00585
00594 function saveToDb($original_id = "")
00595 {
00596 global $ilias;
00597
00598 $db =& $ilias->db;
00599 $complete = 0;
00600 if ($this->isComplete())
00601 {
00602 $complete = 1;
00603 }
00604 $estw_time = $this->getEstimatedWorkingTime();
00605 $estw_time = sprintf("%02d:%02d:%02d", $estw_time['h'], $estw_time['m'], $estw_time['s']);
00606
00607 if ($original_id)
00608 {
00609 $original_id = $db->quote($original_id);
00610 }
00611 else
00612 {
00613 $original_id = "NULL";
00614 }
00615
00616 if ($this->id == -1)
00617 {
00618
00619 $now = getdate();
00620 $question_type = $this->getQuestionType();
00621 $created = sprintf("%04d%02d%02d%02d%02d%02d", $now['year'], $now['mon'], $now['mday'], $now['hours'], $now['minutes'], $now['seconds']);
00622 $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)",
00623 $db->quote($question_type. ""),
00624 $db->quote($this->obj_id. ""),
00625 $db->quote($this->title. ""),
00626 $db->quote($this->comment. ""),
00627 $db->quote($this->author. ""),
00628 $db->quote($this->owner. ""),
00629 $db->quote($this->question. ""),
00630 $db->quote($estw_time. ""),
00631 $db->quote($this->matching_type. ""),
00632 $db->quote($this->points. ""),
00633 $db->quote($complete. ""),
00634 $db->quote($created. ""),
00635 $original_id
00636 );
00637
00638 $result = $db->query($query);
00639 if ($result == DB_OK)
00640 {
00641 $this->id = $this->ilias->db->getLastInsertId();
00642
00643
00644 $this->createPageObject();
00645
00646
00647 if ($this->getTestId() > 0)
00648 {
00649 $this->insertIntoTest($this->getTestId());
00650 }
00651 }
00652 }
00653 else
00654 {
00655
00656 $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",
00657 $db->quote($this->obj_id. ""),
00658 $db->quote($this->title. ""),
00659 $db->quote($this->comment. ""),
00660 $db->quote($this->author. ""),
00661 $db->quote($this->question. ""),
00662 $db->quote($estw_time. ""),
00663 $db->quote($this->matching_type. ""),
00664 $db->quote($this->points. ""),
00665 $db->quote($complete. ""),
00666 $db->quote($this->id. "")
00667 );
00668 $result = $db->query($query);
00669 }
00670
00671 if ($result == DB_OK)
00672 {
00673
00674
00675 $query = sprintf("DELETE FROM qpl_answers WHERE question_fi = %s",
00676 $db->quote($this->id)
00677 );
00678 $result = $db->query($query);
00679
00680
00681 foreach ($this->matchingpairs as $key => $value)
00682 {
00683 $matching_obj = $this->matchingpairs[$key];
00684 $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)",
00685 $db->quote($this->id),
00686 $db->quote($matching_obj->getTerm() . ""),
00687 $db->quote($matching_obj->getPoints() . ""),
00688 $db->quote($matching_obj->getTermId() . ""),
00689 $db->quote($matching_obj->getDefinition() . ""),
00690 $db->quote($matching_obj->getDefinitionId() . "")
00691 );
00692 $matching_result = $db->query($query);
00693 }
00694 }
00695 parent::saveToDb($original_id);
00696 }
00697
00707 function loadFromDb($question_id)
00708 {
00709 global $ilias;
00710 $db =& $ilias->db;
00711
00712 $query = sprintf("SELECT * FROM qpl_questions WHERE question_id = %s",
00713 $db->quote($question_id)
00714 );
00715 $result = $db->query($query);
00716 if (strcmp(strtolower(get_class($result)), db_result) == 0)
00717 {
00718 if ($result->numRows() == 1)
00719 {
00720 $data = $result->fetchRow(DB_FETCHMODE_OBJECT);
00721 $this->id = $question_id;
00722 $this->title = $data->title;
00723 $this->comment = $data->comment;
00724 $this->author = $data->author;
00725 $this->solution_hint = $data->solution_hint;
00726 $this->obj_id = $data->obj_fi;
00727 $this->original_id = $data->original_id;
00728 $this->owner = $data->owner;
00729 $this->matching_type = $data->matching_type;
00730 $this->question = $data->question_text;
00731 $this->points = $data->points;
00732 $this->setEstimatedWorkingTime(substr($data->working_time, 0, 2), substr($data->working_time, 3, 2), substr($data->working_time, 6, 2));
00733 }
00734
00735 $query = sprintf("SELECT * FROM qpl_answers WHERE question_fi = %s ORDER BY answer_id ASC",
00736 $db->quote($question_id)
00737 );
00738 $result = $db->query($query);
00739 if (strcmp(strtolower(get_class($result)), db_result) == 0)
00740 {
00741 while ($data = $result->fetchRow(DB_FETCHMODE_OBJECT))
00742 {
00743 array_push($this->matchingpairs, new ASS_AnswerMatching($data->answertext, $data->points, $data->aorder, $data->matchingtext, $data->matching_order));
00744 }
00745 }
00746 }
00747 parent::loadFromDb($question_id);
00748 }
00749
00757 function duplicate($for_test = true, $title = "", $author = "", $owner = "")
00758 {
00759 if ($this->id <= 0)
00760 {
00761
00762 return;
00763 }
00764
00765 $clone = $this;
00766 $original_id = $this->id;
00767 if ($original_id <= 0)
00768 {
00769 $original_id = "";
00770 }
00771 $clone->id = -1;
00772 if ($title)
00773 {
00774 $clone->setTitle($title);
00775 }
00776 if ($author)
00777 {
00778 $clone->setAuthor($author);
00779 }
00780 if ($owner)
00781 {
00782 $clone->setOwner($owner);
00783 }
00784 if ($for_test)
00785 {
00786 $clone->saveToDb($original_id);
00787 }
00788 else
00789 {
00790 $clone->saveToDb();
00791 }
00792
00793
00794 $clone->copyPageOfQuestion($original_id);
00795
00796
00797 $clone->duplicateImages($original_id);
00798 return $clone->id;
00799 }
00800
00801 function duplicateImages($question_id)
00802 {
00803 if ($this->get_matching_type() == MT_TERMS_PICTURES)
00804 {
00805 $imagepath = $this->getImagePath();
00806 $imagepath_original = str_replace("/$this->id/images", "/$question_id/images", $imagepath);
00807 if (!file_exists($imagepath))
00808 {
00809 ilUtil::makeDirParents($imagepath);
00810 }
00811 foreach ($this->matchingpairs as $answer)
00812 {
00813 $filename = $answer->getPicture();
00814 if (!copy($imagepath_original . $filename, $imagepath . $filename))
00815 {
00816 print "image could not be duplicated!!!! ";
00817 }
00818 if (!copy($imagepath_original . $filename . ".thumb.jpg", $imagepath . $filename . ".thumb.jpg"))
00819 {
00820 print "image thumbnail could not be duplicated!!!! ";
00821 }
00822 }
00823 }
00824 }
00825
00835 function set_question($question = "")
00836 {
00837 $this->question = $question;
00838 }
00839
00849 function set_matching_type($matching_type = MT_TERMS_DEFINITIONS)
00850 {
00851 $this->matching_type = $matching_type;
00852 }
00853
00863 function get_question()
00864 {
00865 return $this->question;
00866 }
00867
00877 function get_matching_type()
00878 {
00879 return $this->matching_type;
00880 }
00881
00896 function add_matchingpair(
00897 $term = "",
00898 $picture_or_definition = "",
00899 $points = 0.0,
00900 $term_id = 0,
00901 $picture_or_definition_id = 0
00902 )
00903 {
00904
00905 if ($term_id == 0)
00906 {
00907 $term_id = $this->get_random_id();
00908 }
00909
00910 if ($picture_or_definition_id == 0)
00911 {
00912 $picture_or_definition_id = $this->get_random_id();
00913 }
00914 $matchingpair = new ASS_AnswerMatching($term, $points, $term_id, $picture_or_definition, $picture_or_definition_id);
00915 array_push($this->matchingpairs, $matchingpair);
00916 }
00917
00929 function get_matchingpair($index = 0)
00930 {
00931 if ($index < 0)
00932 {
00933 return NULL;
00934 }
00935 if (count($this->matchingpairs) < 1)
00936 {
00937 return NULL;
00938 }
00939 if ($index >= count($this->matchingpairs))
00940 {
00941 return NULL;
00942 }
00943 return $this->matchingpairs[$index];
00944 }
00945
00956 function delete_matchingpair($index = 0)
00957 {
00958 if ($index < 0)
00959 {
00960 return;
00961 }
00962 if (count($this->matchingpairs) < 1)
00963 {
00964 return;
00965 }
00966 if ($index >= count($this->matchingpairs))
00967 {
00968 return;
00969 }
00970 unset($this->matchingpairs[$index]);
00971 $this->matchingpairs = array_values($this->matchingpairs);
00972 }
00973
00982 function flush_matchingpairs()
00983 {
00984 $this->matchingpairs = array();
00985 }
00986
00996 function get_matchingpair_count()
00997 {
00998 return count($this->matchingpairs);
00999 }
01000
01010 function get_points()
01011 {
01012 return $this->points;
01013 }
01014
01024 function set_points($points = 0.0)
01025 {
01026 $this->points = $points;
01027 }
01028
01038 function getReachedPoints($user_id, $test_id)
01039 {
01040 $found_value1 = array();
01041 $found_value2 = array();
01042 $query = sprintf("SELECT * FROM tst_solutions WHERE user_fi = %s AND test_fi = %s AND question_fi = %s",
01043 $this->ilias->db->quote($user_id),
01044 $this->ilias->db->quote($test_id),
01045 $this->ilias->db->quote($this->getId())
01046 );
01047 $result = $this->ilias->db->query($query);
01048 while ($data = $result->fetchRow(DB_FETCHMODE_OBJECT))
01049 {
01050 if (strcmp($data->value1, "") != 0)
01051 {
01052 array_push($found_value1, $data->value1);
01053 array_push($found_value2, $data->value2);
01054 }
01055 }
01056 $points = 0;
01057 foreach ($found_value2 as $key => $value)
01058 {
01059 foreach ($this->matchingpairs as $answer_key => $answer_value)
01060 {
01061 if (($answer_value->getDefinitionId() == $value) and ($answer_value->getTermId() == $found_value1[$key]))
01062 {
01063 $points += $answer_value->getPoints();
01064 }
01065 }
01066 }
01067 return $points;
01068 }
01069
01079 function getReachedInformation($user_id, $test_id)
01080 {
01081 $found_value1 = array();
01082 $found_value2 = array();
01083 $query = sprintf("SELECT * FROM tst_solutions WHERE user_fi = %s AND test_fi = %s AND question_fi = %s",
01084 $this->ilias->db->quote($user_id),
01085 $this->ilias->db->quote($test_id),
01086 $this->ilias->db->quote($this->getId())
01087 );
01088 $result = $this->ilias->db->query($query);
01089 while ($data = $result->fetchRow(DB_FETCHMODE_OBJECT))
01090 {
01091 array_push($found_value1, $data->value1);
01092 array_push($found_value2, $data->value2);
01093 }
01094 $counter = 1;
01095 $user_result = array();
01096 foreach ($found_value1 as $key => $value)
01097 {
01098 $solution = array(
01099 "order" => "$counter",
01100 "points" => 0,
01101 "true" => 0,
01102 "term" => "",
01103 "definition" => ""
01104 );
01105 foreach ($this->matchingpairs as $answer_key => $answer_value)
01106 {
01107 if (($answer_value->getDefinitionId() == $found_value2[$key]) and ($answer_value->getTermId() == $value))
01108 {
01109 $points += $answer_value->getPoints();
01110 $solution["points"] = $answer_value->getPoints();
01111 $solution["term"] = $value;
01112 $solution["definition"] = $found_value2[$key];
01113 $solution["true"] = 1;
01114 }
01115 else
01116 {
01117 $solution["term"] = $value;
01118 $solution["definition"] = $found_value2[$key];
01119 }
01120 }
01121 $counter++;
01122 array_push($user_result, $solution);
01123 }
01124 return $user_result;
01125 }
01126
01135 function getMaximumPoints()
01136 {
01137 $points = 0;
01138 foreach ($this->matchingpairs as $key => $value)
01139 {
01140 if ($value->getPoints() > 0)
01141 {
01142 $points += $value->getPoints();
01143 }
01144 }
01145 return $points;
01146 }
01147
01158 function set_image_file($image_filename, $image_tempfilename = "")
01159 {
01160 $result = 0;
01161 if (!empty($image_tempfilename))
01162 {
01163 $imagepath = $this->getImagePath();
01164 if (!file_exists($imagepath))
01165 {
01166 ilUtil::makeDirParents($imagepath);
01167 }
01168
01169 if (!ilUtil::moveUploadedFile($image_tempfilename, $image_filename, $imagepath.$image_filename))
01170 {
01171 $result = 2;
01172 }
01173 else
01174 {
01175 require_once "./content/classes/Media/class.ilObjMediaObject.php";
01176 $mimetype = ilObjMediaObject::getMimeType($imagepath . $image_filename);
01177 if (!preg_match("/^image/", $mimetype))
01178 {
01179 unlink($imagepath . $image_filename);
01180 $result = 1;
01181 }
01182 else
01183 {
01184
01185 $thumbpath = $imagepath . $image_filename . "." . "thumb.jpg";
01186 ilUtil::convertImage($imagepath.$image_filename, $thumbpath, "JPEG", 100);
01187 }
01188 }
01189 }
01190 return $result;
01191 }
01192
01202 function checkSaveData()
01203 {
01204 $result = true;
01205 $matching_values = array();
01206 foreach ($_POST as $key => $value)
01207 {
01208 if (preg_match("/^sel_matching_(\d+)/", $key, $matches))
01209 {
01210 if ((strcmp($value, "") != 0) && ($value != -1))
01211 {
01212 array_push($matching_values, $value);
01213 }
01214 }
01215 }
01216 $check_matching = array_flip($matching_values);
01217 if (count($check_matching) != count($matching_values))
01218 {
01219
01220 $result = false;
01221 sendInfo($this->lng->txt("duplicate_matching_values_selected"));
01222 }
01223 return $result;
01224 }
01225
01236 function saveWorkingData($test_id, $limit_to = LIMIT_NO_LIMIT)
01237 {
01238 global $ilDB;
01239 global $ilUser;
01240 $saveWorkingDataResult = $this->checkSaveData();
01241 if ($saveWorkingDataResult)
01242 {
01243 $db =& $ilDB->db;
01244
01245 $query = sprintf("DELETE FROM tst_solutions WHERE user_fi = %s AND test_fi = %s AND question_fi = %s",
01246 $db->quote($ilUser->id),
01247 $db->quote($test_id),
01248 $db->quote($this->getId())
01249 );
01250 $result = $db->query($query);
01251
01252 foreach ($_POST as $key => $value)
01253 {
01254 if (preg_match("/^sel_matching_(\d+)/", $key, $matches))
01255 {
01256 if (!(preg_match("/initial_value_\d+/", $value)))
01257 {
01258 $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)",
01259 $db->quote($ilUser->id),
01260 $db->quote($test_id),
01261 $db->quote($this->getId()),
01262 $db->quote($value),
01263 $db->quote($matches[1])
01264 );
01265 $result = $db->query($query);
01266 }
01267 }
01268 }
01269 $saveWorkingDataResult = true;
01270 }
01271
01272 return $saveWorkingDataResult;
01273 }
01274
01275 function get_random_id()
01276 {
01277 mt_srand((double)microtime()*1000000);
01278 $random_number = mt_rand(1, 100000);
01279 $found = FALSE;
01280 while ($found)
01281 {
01282 $found = FALSE;
01283 foreach ($this->matchingpairs as $key => $value)
01284 {
01285 if (($value->getTermId() == $random_number) || ($value->getDefinitionId() == $random_number))
01286 {
01287 $found = TRUE;
01288 $random_number++;
01289 }
01290 }
01291 }
01292 return $random_number;
01293 }
01294
01295 function syncWithOriginal()
01296 {
01297 global $ilias;
01298 if ($this->original_id)
01299 {
01300 $complete = 0;
01301 if ($this->isComplete())
01302 {
01303 $complete = 1;
01304 }
01305 $db = & $ilias->db;
01306
01307 $estw_time = $this->getEstimatedWorkingTime();
01308 $estw_time = sprintf("%02d:%02d:%02d", $estw_time['h'], $estw_time['m'], $estw_time['s']);
01309
01310 $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",
01311 $db->quote($this->obj_id. ""),
01312 $db->quote($this->title. ""),
01313 $db->quote($this->comment. ""),
01314 $db->quote($this->author. ""),
01315 $db->quote($this->question. ""),
01316 $db->quote($estw_time. ""),
01317 $db->quote($this->matching_type. ""),
01318 $db->quote($this->points. ""),
01319 $db->quote($complete. ""),
01320 $db->quote($this->original_id. "")
01321 );
01322 $result = $db->query($query);
01323
01324 if ($result == DB_OK)
01325 {
01326
01327
01328 $query = sprintf("DELETE FROM qpl_answers WHERE question_fi = %s",
01329 $db->quote($this->original_id)
01330 );
01331 $result = $db->query($query);
01332
01333 foreach ($this->matchingpairs as $key => $value)
01334 {
01335 $matching_obj = $this->matchingpairs[$key];
01336 $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)",
01337 $db->quote($this->original_id . ""),
01338 $db->quote($matching_obj->getTerm() . ""),
01339 $db->quote($matching_obj->getPoints() . ""),
01340 $db->quote($matching_obj->getTermId() . ""),
01341 $db->quote($matching_obj->getDefinition() . ""),
01342 $db->quote($matching_obj->getDefinitionId() . "")
01343 );
01344 $matching_result = $db->query($query);
01345 }
01346 }
01347 parent::syncWithOriginal();
01348 }
01349 }
01350
01351 function pc_array_shuffle($array) {
01352 $i = count($array);
01353 mt_srand((double)microtime()*1000000);
01354 while(--$i)
01355 {
01356 $j = mt_rand(0, $i);
01357 if ($i != $j)
01358 {
01359
01360 $tmp = $array[$j];
01361 $array[$j] = $array[$i];
01362 $array[$i] = $tmp;
01363 }
01364 }
01365 return $array;
01366 }
01367
01368 function createRandomSolution($test_id, $user_id)
01369 {
01370 global $ilDB;
01371 global $ilUser;
01372 $db =& $ilDB->db;
01373
01374 $query = sprintf("DELETE FROM tst_solutions WHERE user_fi = %s AND test_fi = %s AND question_fi = %s",
01375 $db->quote($user_id),
01376 $db->quote($test_id),
01377 $db->quote($this->getId())
01378 );
01379 $result = $db->query($query);
01380
01381 $terms = array();
01382 $definitions = array();
01383
01384 foreach ($this->matchingpairs as $key => $pair)
01385 {
01386 array_push($terms, $pair->getTermId());
01387 array_push($definitions, $pair->getDefinitionId());
01388 }
01389 $definitions = $this->pc_array_shuffle($definitions);
01390 foreach ($terms as $key => $value)
01391 {
01392 $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)",
01393 $db->quote($user_id),
01394 $db->quote($test_id),
01395 $db->quote($this->getId()),
01396 $db->quote($value),
01397 $db->quote($definitions[$key])
01398 );
01399 $result = $db->query($query);
01400 }
01401 }
01402
01411 function getQuestionType()
01412 {
01413 return 4;
01414 }
01415
01416 }
01417
01418 ?>