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