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 include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
00025 include_once "./Modules/Test/classes/inc.AssessmentConstants.php";
00026
00036 class assMatchingQuestion extends assQuestion
00037 {
00045 var $matchingpairs;
00046
00055 var $matching_type;
00056
00069 function assMatchingQuestion (
00070 $title = "",
00071 $comment = "",
00072 $author = "",
00073 $owner = -1,
00074 $question = "",
00075 $matching_type = MT_TERMS_DEFINITIONS
00076 )
00077 {
00078 $this->assQuestion($title, $comment, $author, $owner, $question);
00079 $this->matchingpairs = array();
00080 $this->matching_type = $matching_type;
00081 }
00082
00091 function isComplete()
00092 {
00093 if (($this->title) and ($this->author) and ($this->question) and (count($this->matchingpairs)) and ($this->getMaximumPoints() > 0))
00094 {
00095 return true;
00096 }
00097 else
00098 {
00099 return false;
00100 }
00101 }
00102
00111 function saveToDb($original_id = "")
00112 {
00113 global $ilDB;
00114
00115 $complete = 0;
00116 if ($this->isComplete())
00117 {
00118 $complete = 1;
00119 }
00120 $estw_time = $this->getEstimatedWorkingTime();
00121 $estw_time = sprintf("%02d:%02d:%02d", $estw_time['h'], $estw_time['m'], $estw_time['s']);
00122
00123 if ($original_id)
00124 {
00125 $original_id = $ilDB->quote($original_id);
00126 }
00127 else
00128 {
00129 $original_id = "NULL";
00130 }
00131
00132
00133 include_once("./Services/RTE/classes/class.ilRTE.php");
00134 if ($this->id == -1)
00135 {
00136
00137 $now = getdate();
00138 $question_type = $this->getQuestionTypeID();
00139 $created = sprintf("%04d%02d%02d%02d%02d%02d", $now['year'], $now['mon'], $now['mday'], $now['hours'], $now['minutes'], $now['seconds']);
00140 $query = sprintf("INSERT INTO qpl_questions (question_id, question_type_fi, obj_fi, title, comment, author, owner, question_text, working_time, points, complete, created, original_id, TIMESTAMP) VALUES (NULL, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, NULL)",
00141 $ilDB->quote($question_type. ""),
00142 $ilDB->quote($this->obj_id. ""),
00143 $ilDB->quote($this->title. ""),
00144 $ilDB->quote($this->comment. ""),
00145 $ilDB->quote($this->author. ""),
00146 $ilDB->quote($this->owner. ""),
00147 $ilDB->quote(ilRTE::_replaceMediaObjectImageSrc($this->question, 0)),
00148 $ilDB->quote($estw_time. ""),
00149 $ilDB->quote($this->getMaximumPoints() . ""),
00150 $ilDB->quote($complete. ""),
00151 $ilDB->quote($created. ""),
00152 $original_id
00153 );
00154
00155 $result = $ilDB->query($query);
00156 if ($result == DB_OK)
00157 {
00158 $this->id = $ilDB->getLastInsertId();
00159 $query = sprintf("INSERT INTO qpl_question_matching (question_fi, shuffle, matching_type) VALUES (%s, %s, %s)",
00160 $ilDB->quote($this->id . ""),
00161 $ilDB->quote($this->shuffle . ""),
00162 $ilDB->quote($this->matching_type. "")
00163 );
00164 $ilDB->query($query);
00165
00166
00167 $this->createPageObject();
00168
00169
00170 if ($this->getTestId() > 0)
00171 {
00172 $this->insertIntoTest($this->getTestId());
00173 }
00174 }
00175 }
00176 else
00177 {
00178
00179 $query = sprintf("UPDATE qpl_questions SET obj_fi = %s, title = %s, comment = %s, author = %s, question_text = %s, working_time=%s, points = %s, complete = %s WHERE question_id = %s",
00180 $ilDB->quote($this->obj_id. ""),
00181 $ilDB->quote($this->title. ""),
00182 $ilDB->quote($this->comment. ""),
00183 $ilDB->quote($this->author. ""),
00184 $ilDB->quote(ilRTE::_replaceMediaObjectImageSrc($this->question, 0)),
00185 $ilDB->quote($estw_time. ""),
00186 $ilDB->quote($this->getMaximumPoints() . ""),
00187 $ilDB->quote($complete. ""),
00188 $ilDB->quote($this->id. "")
00189 );
00190 $result = $ilDB->query($query);
00191 $query = sprintf("UPDATE qpl_question_matching SET shuffle = %s, matching_type = %s WHERE question_fi = %s",
00192 $ilDB->quote($this->shuffle . ""),
00193 $ilDB->quote($this->matching_type. ""),
00194 $ilDB->quote($this->id . "")
00195 );
00196 $result = $ilDB->query($query);
00197 }
00198
00199 if ($result == DB_OK)
00200 {
00201
00202
00203 $query = sprintf("DELETE FROM qpl_answer_matching WHERE question_fi = %s",
00204 $ilDB->quote($this->id)
00205 );
00206 $result = $ilDB->query($query);
00207
00208
00209 foreach ($this->matchingpairs as $key => $value)
00210 {
00211 $matching_obj = $this->matchingpairs[$key];
00212 $query = sprintf("INSERT INTO qpl_answer_matching (answer_id, question_fi, answertext, points, aorder, matchingtext, matching_order) VALUES (NULL, %s, %s, %s, %s, %s, %s)",
00213 $ilDB->quote($this->id),
00214 $ilDB->quote($matching_obj->getTerm() . ""),
00215 $ilDB->quote($matching_obj->getPoints() . ""),
00216 $ilDB->quote($matching_obj->getTermId() . ""),
00217 $ilDB->quote($matching_obj->getDefinition() . ""),
00218 $ilDB->quote($matching_obj->getDefinitionId() . "")
00219 );
00220 $matching_result = $ilDB->query($query);
00221 }
00222 }
00223 parent::saveToDb($original_id);
00224 }
00225
00235 function loadFromDb($question_id)
00236 {
00237 global $ilDB;
00238
00239 $query = sprintf("SELECT qpl_questions.*, qpl_question_matching.* FROM qpl_questions, qpl_question_matching WHERE question_id = %s AND qpl_questions.question_id = qpl_question_matching.question_fi",
00240 $ilDB->quote($question_id)
00241 );
00242 $result = $ilDB->query($query);
00243 if (strcmp(strtolower(get_class($result)), db_result) == 0)
00244 {
00245 if ($result->numRows() == 1)
00246 {
00247 $data = $result->fetchRow(DB_FETCHMODE_OBJECT);
00248 $this->id = $question_id;
00249 $this->title = $data->title;
00250 $this->comment = $data->comment;
00251 $this->author = $data->author;
00252 $this->solution_hint = $data->solution_hint;
00253 $this->obj_id = $data->obj_fi;
00254 $this->original_id = $data->original_id;
00255 $this->owner = $data->owner;
00256 $this->matching_type = $data->matching_type;
00257 include_once("./Services/RTE/classes/class.ilRTE.php");
00258 $this->question = ilRTE::_replaceMediaObjectImageSrc($data->question_text, 1);
00259 $this->points = $data->points;
00260 $this->shuffle = $data->shuffle;
00261 $this->setEstimatedWorkingTime(substr($data->working_time, 0, 2), substr($data->working_time, 3, 2), substr($data->working_time, 6, 2));
00262 }
00263
00264 $query = sprintf("SELECT * FROM qpl_answer_matching WHERE question_fi = %s ORDER BY answer_id ASC",
00265 $ilDB->quote($question_id)
00266 );
00267 $result = $ilDB->query($query);
00268 include_once "./Modules/TestQuestionPool/classes/class.assAnswerMatching.php";
00269 if (strcmp(strtolower(get_class($result)), db_result) == 0)
00270 {
00271 while ($data = $result->fetchRow(DB_FETCHMODE_OBJECT))
00272 {
00273 array_push($this->matchingpairs, new ASS_AnswerMatching($data->answertext, $data->points, $data->aorder, $data->matchingtext, $data->matching_order));
00274 }
00275 }
00276 }
00277 parent::loadFromDb($question_id);
00278 }
00279
00287 function addMatchingPair($answertext, $points, $answerorder, $matchingtext, $matchingorder)
00288 {
00289 include_once "./Modules/TestQuestionPool/classes/class.assAnswerMatching.php";
00290 array_push($this->matchingpairs, new ASS_AnswerMatching($answertext, $points, $answerorder, $matchingtext, $matchingorder));
00291 }
00292
00293
00301 function duplicate($for_test = true, $title = "", $author = "", $owner = "")
00302 {
00303 if ($this->id <= 0)
00304 {
00305
00306 return;
00307 }
00308
00309 $this_id = $this->getId();
00310 $clone = $this;
00311 include_once ("./Modules/TestQuestionPool/classes/class.assQuestion.php");
00312 $original_id = assQuestion::_getOriginalId($this->id);
00313 $clone->id = -1;
00314 if ($title)
00315 {
00316 $clone->setTitle($title);
00317 }
00318 if ($author)
00319 {
00320 $clone->setAuthor($author);
00321 }
00322 if ($owner)
00323 {
00324 $clone->setOwner($owner);
00325 }
00326 if ($for_test)
00327 {
00328 $clone->saveToDb($original_id);
00329 }
00330 else
00331 {
00332 $clone->saveToDb();
00333 }
00334
00335
00336 $clone->copyPageOfQuestion($this_id);
00337
00338 $clone->copyXHTMLMediaObjectsOfQuestion($this_id);
00339
00340 $clone->duplicateFeedbackGeneric($this_id);
00341
00342
00343 $clone->duplicateImages($this_id);
00344 return $clone->id;
00345 }
00346
00354 function copyObject($target_questionpool, $title = "")
00355 {
00356 if ($this->id <= 0)
00357 {
00358
00359 return;
00360 }
00361
00362 $clone = $this;
00363 include_once ("./Modules/TestQuestionPool/classes/class.assQuestion.php");
00364 $original_id = assQuestion::_getOriginalId($this->id);
00365 $clone->id = -1;
00366 if ($title)
00367 {
00368 $clone->setTitle($title);
00369 }
00370 $source_questionpool = $this->getObjId();
00371 $clone->setObjId($target_questionpool);
00372 $clone->saveToDb();
00373
00374
00375 $clone->copyPageOfQuestion($original_id);
00376
00377 $clone->copyXHTMLMediaObjectsOfQuestion($original_id);
00378
00379 $clone->duplicateFeedbackGeneric($original_id);
00380
00381
00382 $clone->copyImages($original_id, $source_questionpool);
00383 return $clone->id;
00384 }
00385
00386 function duplicateImages($question_id)
00387 {
00388 if ($this->get_matching_type() == MT_TERMS_PICTURES)
00389 {
00390 $imagepath = $this->getImagePath();
00391 $imagepath_original = str_replace("/$this->id/images", "/$question_id/images", $imagepath);
00392 if (!file_exists($imagepath))
00393 {
00394 ilUtil::makeDirParents($imagepath);
00395 }
00396 foreach ($this->matchingpairs as $answer)
00397 {
00398 $filename = $answer->getPicture();
00399 if (!copy($imagepath_original . $filename, $imagepath . $filename))
00400 {
00401 print "image could not be duplicated!!!! ";
00402 }
00403 if (!copy($imagepath_original . $filename . ".thumb.jpg", $imagepath . $filename . ".thumb.jpg"))
00404 {
00405 print "image thumbnail could not be duplicated!!!! ";
00406 }
00407 }
00408 }
00409 }
00410
00411 function copyImages($question_id, $source_questionpool)
00412 {
00413 if ($this->get_matching_type() == MT_TERMS_PICTURES)
00414 {
00415 $imagepath = $this->getImagePath();
00416 $imagepath_original = str_replace("/$this->id/images", "/$question_id/images", $imagepath);
00417 $imagepath_original = str_replace("/$this->obj_id/", "/$source_questionpool/", $imagepath_original);
00418 if (!file_exists($imagepath))
00419 {
00420 ilUtil::makeDirParents($imagepath);
00421 }
00422 foreach ($this->matchingpairs as $answer)
00423 {
00424 $filename = $answer->getPicture();
00425 if (!copy($imagepath_original . $filename, $imagepath . $filename))
00426 {
00427 print "image could not be duplicated!!!! ";
00428 }
00429 if (!copy($imagepath_original . $filename . ".thumb.jpg", $imagepath . $filename . ".thumb.jpg"))
00430 {
00431 print "image thumbnail could not be duplicated!!!! ";
00432 }
00433 }
00434 }
00435 }
00436
00446 function setMatchingType($matching_type = MT_TERMS_DEFINITIONS)
00447 {
00448 $this->matching_type = $matching_type;
00449 }
00450
00460 function get_matching_type()
00461 {
00462 return $this->matching_type;
00463 }
00464
00465 function getMatchingType()
00466 {
00467 return $this->matching_type;
00468 }
00469
00484 function add_matchingpair(
00485 $term = "",
00486 $picture_or_definition = "",
00487 $points = 0.0,
00488 $term_id = 0,
00489 $picture_or_definition_id = 0
00490 )
00491 {
00492
00493 if ($term_id == 0)
00494 {
00495 $term_id = $this->get_random_id();
00496 }
00497
00498 if ($picture_or_definition_id == 0)
00499 {
00500 $picture_or_definition_id = $this->get_random_id();
00501 }
00502 include_once "./Modules/TestQuestionPool/classes/class.assAnswerMatching.php";
00503 $matchingpair = new ASS_AnswerMatching($term, $points, $term_id, $picture_or_definition, $picture_or_definition_id);
00504 array_push($this->matchingpairs, $matchingpair);
00505 }
00506
00518 function get_matchingpair($index = 0)
00519 {
00520 return $this->getMatchingPair($index);
00521 }
00522
00534 function getMatchingPair($index = 0)
00535 {
00536 if ($index < 0)
00537 {
00538 return NULL;
00539 }
00540 if (count($this->matchingpairs) < 1)
00541 {
00542 return NULL;
00543 }
00544 if ($index >= count($this->matchingpairs))
00545 {
00546 return NULL;
00547 }
00548 return $this->matchingpairs[$index];
00549 }
00550
00561 function delete_matchingpair($index = 0)
00562 {
00563 if ($index < 0)
00564 {
00565 return;
00566 }
00567 if (count($this->matchingpairs) < 1)
00568 {
00569 return;
00570 }
00571 if ($index >= count($this->matchingpairs))
00572 {
00573 return;
00574 }
00575 unset($this->matchingpairs[$index]);
00576 $this->matchingpairs = array_values($this->matchingpairs);
00577 }
00578
00587 function flush_matchingpairs()
00588 {
00589 $this->matchingpairs = array();
00590 }
00591
00601 function get_matchingpair_count()
00602 {
00603 return count($this->matchingpairs);
00604 }
00605
00617 function calculateReachedPoints($active_id, $pass = NULL)
00618 {
00619 global $ilDB;
00620
00621 $found_value1 = array();
00622 $found_value2 = array();
00623 if (is_null($pass))
00624 {
00625 $pass = $this->getSolutionMaxPass($active_id);
00626 }
00627 $query = sprintf("SELECT * FROM tst_solutions WHERE active_fi = %s AND question_fi = %s AND pass = %s",
00628 $ilDB->quote($active_id . ""),
00629 $ilDB->quote($this->getId() . ""),
00630 $ilDB->quote($pass . "")
00631 );
00632 $result = $ilDB->query($query);
00633 while ($data = $result->fetchRow(DB_FETCHMODE_OBJECT))
00634 {
00635 if (strcmp($data->value1, "") != 0)
00636 {
00637 array_push($found_value1, $data->value1);
00638 array_push($found_value2, $data->value2);
00639 }
00640 }
00641 $points = 0;
00642 foreach ($found_value2 as $key => $value)
00643 {
00644 foreach ($this->matchingpairs as $answer_key => $answer_value)
00645 {
00646 if (($answer_value->getDefinitionId() == $value) and ($answer_value->getTermId() == $found_value1[$key]))
00647 {
00648 $points += $answer_value->getPoints();
00649 }
00650 }
00651 }
00652
00653 $points = parent::calculateReachedPoints($active_id, $pass = NULL, $points);
00654 return $points;
00655 }
00656
00665 function getMaximumPoints()
00666 {
00667 $points = 0;
00668 foreach ($this->matchingpairs as $key => $value)
00669 {
00670 if ($value->getPoints() > 0)
00671 {
00672 $points += $value->getPoints();
00673 }
00674 }
00675 return $points;
00676 }
00677
00688 function setImageFile($image_filename, $image_tempfilename = "")
00689 {
00690 $result = 0;
00691 if (!empty($image_tempfilename))
00692 {
00693 $image_filename = str_replace(" ", "_", $image_filename);
00694 $imagepath = $this->getImagePath();
00695 if (!file_exists($imagepath))
00696 {
00697 ilUtil::makeDirParents($imagepath);
00698 }
00699
00700 if (!ilUtil::moveUploadedFile($image_tempfilename, $image_filename, $imagepath.$image_filename))
00701 {
00702 $result = 2;
00703 }
00704 else
00705 {
00706 include_once "./Services/MediaObjects/classes/class.ilObjMediaObject.php";
00707 $mimetype = ilObjMediaObject::getMimeType($imagepath . $image_filename);
00708 if (!preg_match("/^image/", $mimetype))
00709 {
00710 unlink($imagepath . $image_filename);
00711 $result = 1;
00712 }
00713 else
00714 {
00715
00716 $thumbpath = $imagepath . $image_filename . "." . "thumb.jpg";
00717 ilUtil::convertImage($imagepath.$image_filename, $thumbpath, "JPEG", 100);
00718 }
00719 }
00720 }
00721 return $result;
00722 }
00723
00733 function checkSaveData()
00734 {
00735 $result = true;
00736 $matching_values = array();
00737 foreach ($_POST as $key => $value)
00738 {
00739 if (preg_match("/^sel_matching_(\d+)/", $key, $matches))
00740 {
00741 if ((strcmp($value, "") != 0) && ($value != -1))
00742 {
00743 array_push($matching_values, $value);
00744 }
00745 }
00746 }
00747 $check_matching = array_flip($matching_values);
00748 if (count($check_matching) != count($matching_values))
00749 {
00750
00751 $result = false;
00752 ilUtil::sendInfo($this->lng->txt("duplicate_matching_values_selected"), TRUE);
00753 }
00754 return $result;
00755 }
00756
00767 function saveWorkingData($active_id, $pass = NULL)
00768 {
00769 global $ilDB;
00770 global $ilUser;
00771
00772 $saveWorkingDataResult = $this->checkSaveData();
00773 $entered_values = 0;
00774 if ($saveWorkingDataResult)
00775 {
00776 if (is_null($pass))
00777 {
00778 include_once "./Modules/Test/classes/class.ilObjTest.php";
00779 $pass = ilObjTest::_getPass($active_id);
00780 }
00781
00782 $query = sprintf("DELETE FROM tst_solutions WHERE active_fi = %s AND question_fi = %s AND pass = %s",
00783 $ilDB->quote($active_id . ""),
00784 $ilDB->quote($this->getId() . ""),
00785 $ilDB->quote($pass . "")
00786 );
00787 $result = $ilDB->query($query);
00788 foreach ($_POST as $key => $value)
00789 {
00790 if (preg_match("/^sel_matching_(\d+)/", $key, $matches))
00791 {
00792 if (!(preg_match("/initial_value_\d+/", $value)))
00793 {
00794 if ($value > -1)
00795 {
00796 $entered_values++;
00797 $query = sprintf("INSERT INTO tst_solutions (solution_id, active_fi, question_fi, value1, value2, pass, TIMESTAMP) VALUES (NULL, %s, %s, %s, %s, %s, NULL)",
00798 $ilDB->quote($active_id),
00799 $ilDB->quote($this->getId()),
00800 $ilDB->quote(trim($value)),
00801 $ilDB->quote(trim($matches[1])),
00802 $ilDB->quote($pass . "")
00803 );
00804 $result = $ilDB->query($query);
00805 }
00806 }
00807 }
00808 }
00809 $saveWorkingDataResult = true;
00810 }
00811 if ($entered_values)
00812 {
00813 include_once ("./classes/class.ilObjAssessmentFolder.php");
00814 if (ilObjAssessmentFolder::_enabledAssessmentLogging())
00815 {
00816 $this->logAction($this->lng->txtlng("assessment", "log_user_entered_values", ilObjAssessmentFolder::_getLogLanguage()), $active_id, $this->getId());
00817 }
00818 }
00819 else
00820 {
00821 include_once ("./classes/class.ilObjAssessmentFolder.php");
00822 if (ilObjAssessmentFolder::_enabledAssessmentLogging())
00823 {
00824 $this->logAction($this->lng->txtlng("assessment", "log_user_not_entered_values", ilObjAssessmentFolder::_getLogLanguage()), $active_id, $this->getId());
00825 }
00826 }
00827 parent::saveWorkingData($active_id, $pass);
00828 return $saveWorkingDataResult;
00829 }
00830
00831 function get_random_id()
00832 {
00833 mt_srand((double)microtime()*1000000);
00834 $random_number = mt_rand(1, 100000);
00835 $found = FALSE;
00836 while ($found)
00837 {
00838 $found = FALSE;
00839 foreach ($this->matchingpairs as $key => $value)
00840 {
00841 if (($value->getTermId() == $random_number) || ($value->getDefinitionId() == $random_number))
00842 {
00843 $found = TRUE;
00844 $random_number++;
00845 }
00846 }
00847 }
00848 return $random_number;
00849 }
00850
00851 function pc_array_shuffle($array) {
00852 $i = count($array);
00853 mt_srand((double)microtime()*1000000);
00854 while(--$i)
00855 {
00856 $j = mt_rand(0, $i);
00857 if ($i != $j)
00858 {
00859
00860 $tmp = $array[$j];
00861 $array[$j] = $array[$i];
00862 $array[$i] = $tmp;
00863 }
00864 }
00865 return $array;
00866 }
00867
00877 function setShuffle($shuffle)
00878 {
00879 switch ($shuffle)
00880 {
00881 case 0:
00882 case 1:
00883 case 2:
00884 case 3:
00885 $this->shuffle = $shuffle;
00886 break;
00887 default:
00888 $this->shuffle = 1;
00889 break;
00890 }
00891 }
00892
00901 function getQuestionType()
00902 {
00903 return "assMatchingQuestion";
00904 }
00905
00914 function getAdditionalTableName()
00915 {
00916 return "qpl_question_matching";
00917 }
00918
00927 function getAnswerTableName()
00928 {
00929 return "qpl_answer_matching";
00930 }
00931
00936 function getRTETextWithMediaObjects()
00937 {
00938 return parent::getRTETextWithMediaObjects();
00939 }
00940
00944 function &getMatchingPairs()
00945 {
00946 return $this->matchingpairs;
00947 }
00948
00957 function supportsJavascriptOutput()
00958 {
00959 return TRUE;
00960 }
00961 }
00962
00963 ?>