00001 <?php
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
00024 include_once "./Modules/Test/classes/inc.AssessmentConstants.php";
00025
00037 class assTextSubset extends assQuestion
00038 {
00046 var $answers;
00047
00055 var $correctanswers;
00056
00064 var $text_rating;
00065
00079 function assTextSubset(
00080 $title = "",
00081 $comment = "",
00082 $author = "",
00083 $owner = -1,
00084 $question = ""
00085 )
00086 {
00087 $this->assQuestion($title, $comment, $author, $owner, $question);
00088 $this->answers = array();
00089 $this->correctanswers = 0;
00090 }
00091
00100 function isComplete()
00101 {
00102 if (($this->title) and ($this->author) and ($this->question) and (count($this->answers) >= $this->correctanswers) and ($this->getMaximumPoints() > 0))
00103 {
00104 return true;
00105 }
00106 else
00107 {
00108 return false;
00109 }
00110 }
00111
00120 function saveToDb($original_id = "")
00121 {
00122 global $ilDB;
00123
00124 $complete = 0;
00125 if ($this->isComplete())
00126 {
00127 $complete = 1;
00128 }
00129 $estw_time = $this->getEstimatedWorkingTime();
00130 $estw_time = sprintf("%02d:%02d:%02d", $estw_time['h'], $estw_time['m'], $estw_time['s']);
00131
00132 if ($original_id)
00133 {
00134 $original_id = $ilDB->quote($original_id);
00135 }
00136 else
00137 {
00138 $original_id = "NULL";
00139 }
00140
00141
00142 include_once("./Services/RTE/classes/class.ilRTE.php");
00143 if ($this->id == -1)
00144 {
00145
00146 $now = getdate();
00147 $question_type = $this->getQuestionTypeID();
00148 $created = sprintf("%04d%02d%02d%02d%02d%02d", $now['year'], $now['mon'], $now['mday'], $now['hours'], $now['minutes'], $now['seconds']);
00149 $query = sprintf("INSERT INTO qpl_questions (question_id, question_type_fi, obj_fi, title, comment, author, owner, question_text, points, working_time, complete, created, original_id, TIMESTAMP) VALUES (NULL, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, NULL)",
00150 $ilDB->quote($question_type),
00151 $ilDB->quote($this->obj_id),
00152 $ilDB->quote($this->title),
00153 $ilDB->quote($this->comment),
00154 $ilDB->quote($this->author),
00155 $ilDB->quote($this->owner),
00156 $ilDB->quote(ilRTE::_replaceMediaObjectImageSrc($this->question, 0)),
00157 $ilDB->quote($this->getMaximumPoints() . ""),
00158 $ilDB->quote($estw_time),
00159 $ilDB->quote("$complete"),
00160 $ilDB->quote($created),
00161 $original_id
00162 );
00163 $result = $ilDB->query($query);
00164
00165 if ($result == DB_OK)
00166 {
00167 $this->id = $ilDB->getLastInsertId();
00168 $query = sprintf("INSERT INTO qpl_question_textsubset (question_fi, textgap_rating, correctanswers) VALUES (%s, %s, %s)",
00169 $ilDB->quote($this->id . ""),
00170 $ilDB->quote($this->getTextRating() . ""),
00171 $ilDB->quote($this->getCorrectAnswers() . "")
00172 );
00173 $ilDB->query($query);
00174
00175
00176 $this->createPageObject();
00177
00178
00179 if ($this->getTestId() > 0)
00180 {
00181 $this->insertIntoTest($this->getTestId());
00182 }
00183 }
00184 }
00185 else
00186 {
00187
00188 $query = sprintf("UPDATE qpl_questions SET obj_fi = %s, title = %s, comment = %s, author = %s, question_text = %s, points = %s, working_time=%s, complete = %s WHERE question_id = %s",
00189 $ilDB->quote($this->obj_id. ""),
00190 $ilDB->quote($this->title),
00191 $ilDB->quote($this->comment),
00192 $ilDB->quote($this->author),
00193 $ilDB->quote(ilRTE::_replaceMediaObjectImageSrc($this->question, 0)),
00194 $ilDB->quote($this->getMaximumPoints() . ""),
00195 $ilDB->quote($estw_time),
00196 $ilDB->quote("$complete"),
00197 $ilDB->quote($this->id)
00198 );
00199 $result = $ilDB->query($query);
00200 $query = sprintf("UPDATE qpl_question_textsubset SET textgap_rating = %s, correctanswers = %s WHERE question_fi = %s",
00201 $ilDB->quote($this->getTextRating() . ""),
00202 $ilDB->quote($this->getCorrectAnswers() . ""),
00203 $ilDB->quote($this->id . "")
00204 );
00205 $result = $ilDB->query($query);
00206 }
00207 if ($result == DB_OK)
00208 {
00209
00210
00211
00212 $query = sprintf("DELETE FROM qpl_answer_textsubset WHERE question_fi = %s",
00213 $ilDB->quote($this->id)
00214 );
00215 $result = $ilDB->query($query);
00216
00217
00218 foreach ($this->answers as $key => $value)
00219 {
00220 $answer_obj = $this->answers[$key];
00221 $query = sprintf("INSERT INTO qpl_answer_textsubset (answer_id, question_fi, answertext, points, aorder) VALUES (NULL, %s, %s, %s, %s)",
00222 $ilDB->quote($this->id),
00223 $ilDB->quote($answer_obj->getAnswertext()),
00224 $ilDB->quote($answer_obj->getPoints() . ""),
00225 $ilDB->quote($answer_obj->getOrder() . "")
00226 );
00227 $answer_result = $ilDB->query($query);
00228 }
00229 }
00230 parent::saveToDb($original_id);
00231 }
00232
00242 function loadFromDb($question_id)
00243 {
00244 global $ilDB;
00245
00246 $query = sprintf("SELECT qpl_questions.*, qpl_question_textsubset.* FROM qpl_questions, qpl_question_textsubset WHERE question_id = %s AND qpl_questions.question_id = qpl_question_textsubset.question_fi",
00247 $ilDB->quote($question_id)
00248 );
00249 $result = $ilDB->query($query);
00250 if (strcmp(strtolower(get_class($result)), db_result) == 0)
00251 {
00252 if ($result->numRows() == 1)
00253 {
00254 $data = $result->fetchRow(DB_FETCHMODE_OBJECT);
00255 $this->id = $question_id;
00256 $this->title = $data->title;
00257 $this->comment = $data->comment;
00258 $this->solution_hint = $data->solution_hint;
00259 $this->original_id = $data->original_id;
00260 $this->obj_id = $data->obj_fi;
00261 $this->author = $data->author;
00262 $this->owner = $data->owner;
00263 $this->points = $data->points;
00264 include_once("./Services/RTE/classes/class.ilRTE.php");
00265 $this->question = ilRTE::_replaceMediaObjectImageSrc($data->question_text, 1);
00266 $this->correctanswers = $data->correctanswers;
00267 $this->text_rating = $data->textgap_rating;
00268 $this->setEstimatedWorkingTime(substr($data->working_time, 0, 2), substr($data->working_time, 3, 2), substr($data->working_time, 6, 2));
00269 }
00270
00271 $query = sprintf("SELECT * FROM qpl_answer_textsubset WHERE question_fi = %s ORDER BY aorder ASC",
00272 $ilDB->quote($question_id)
00273 );
00274 $result = $ilDB->query($query);
00275
00276 include_once "./Modules/TestQuestionPool/classes/class.assAnswerSimple.php";
00277 if (strcmp(strtolower(get_class($result)), db_result) == 0)
00278 {
00279 while ($data = $result->fetchRow(DB_FETCHMODE_ASSOC))
00280 {
00281 array_push($this->answers, new ASS_AnswerSimple($data["answertext"], $data["points"], $data["aorder"]));
00282 }
00283 }
00284 }
00285 parent::loadFromDb($question_id);
00286 }
00287
00295 function addAnswer($answertext, $points, $answerorder)
00296 {
00297 include_once "./Modules/TestQuestionPool/classes/class.assAnswerSimple.php";
00298 array_push($this->answers, new ASS_AnswerSimple($answertext, $points, $answerorder));
00299 }
00300
00308 function duplicate($for_test = true, $title = "", $author = "", $owner = "")
00309 {
00310 if ($this->id <= 0)
00311 {
00312
00313 return;
00314 }
00315
00316 $this_id = $this->getId();
00317 $clone = $this;
00318 include_once ("./Modules/TestQuestionPool/classes/class.assQuestion.php");
00319 $original_id = assQuestion::_getOriginalId($this->id);
00320 $clone->id = -1;
00321 if ($title)
00322 {
00323 $clone->setTitle($title);
00324 }
00325
00326 if ($author)
00327 {
00328 $clone->setAuthor($author);
00329 }
00330 if ($owner)
00331 {
00332 $clone->setOwner($owner);
00333 }
00334
00335 if ($for_test)
00336 {
00337 $clone->saveToDb($original_id);
00338 }
00339 else
00340 {
00341 $clone->saveToDb();
00342 }
00343
00344
00345 $clone->copyPageOfQuestion($this_id);
00346
00347 $clone->copyXHTMLMediaObjectsOfQuestion($this_id);
00348
00349 $clone->duplicateFeedbackGeneric($this_id);
00350
00351 return $clone->id;
00352 }
00353
00361 function copyObject($target_questionpool, $title = "")
00362 {
00363 if ($this->id <= 0)
00364 {
00365
00366 return;
00367 }
00368
00369 $clone = $this;
00370 include_once ("./Modules/TestQuestionPool/classes/class.assQuestion.php");
00371 $original_id = assQuestion::_getOriginalId($this->id);
00372 $clone->id = -1;
00373 $source_questionpool = $this->getObjId();
00374 $clone->setObjId($target_questionpool);
00375 if ($title)
00376 {
00377 $clone->setTitle($title);
00378 }
00379 $clone->saveToDb();
00380
00381
00382 $clone->copyPageOfQuestion($original_id);
00383
00384 $clone->copyXHTMLMediaObjectsOfQuestion($original_id);
00385
00386 $clone->duplicateFeedbackGeneric($original_id);
00387
00388 return $clone->id;
00389 }
00390
00400 function getAnswerCount()
00401 {
00402 return count($this->answers);
00403 }
00404
00416 function getAnswer($index = 0)
00417 {
00418 if ($index < 0) return NULL;
00419 if (count($this->answers) < 1) return NULL;
00420 if ($index >= count($this->answers)) return NULL;
00421
00422 return $this->answers[$index];
00423 }
00424
00435 function deleteAnswer($index = 0)
00436 {
00437 if ($index < 0) return;
00438 if (count($this->answers) < 1) return;
00439 if ($index >= count($this->answers)) return;
00440 unset($this->answers[$index]);
00441 $this->answers = array_values($this->answers);
00442 for ($i = 0; $i < count($this->answers); $i++)
00443 {
00444 if ($this->answers[$i]->getOrder() > $index)
00445 {
00446 $this->answers[$i]->setOrder($i);
00447 }
00448 }
00449 }
00450
00459 function flushAnswers()
00460 {
00461 $this->answers = array();
00462 }
00463
00472 function getMaximumPoints()
00473 {
00474 $points = array();
00475 foreach ($this->answers as $answer)
00476 {
00477 if ($answer->getPoints() > 0)
00478 {
00479 array_push($points, $answer->getPoints());
00480 }
00481 }
00482 rsort($points, SORT_NUMERIC);
00483 $maxpoints = 0;
00484 for ($counter = 0; $counter < $this->getCorrectAnswers(); $counter++)
00485 {
00486 $maxpoints += $points[$counter];
00487 }
00488 return $maxpoints;
00489 }
00490
00499 function &getAvailableAnswers()
00500 {
00501 $available_answers = array();
00502 foreach ($this->answers as $answer)
00503 {
00504 array_push($available_answers, $answer->getAnswertext());
00505 }
00506 return $available_answers;
00507 }
00508
00521 function isAnswerCorrect($answers, $answer)
00522 {
00523 include_once "./Services/Utilities/classes/class.ilStr.php";
00524 $result = 0;
00525 $textrating = $this->getTextRating();
00526 foreach ($answers as $key => $value)
00527 {
00528 switch ($textrating)
00529 {
00530 case TEXTGAP_RATING_CASEINSENSITIVE:
00531 if (strcmp(ilStr::strToLower($value), ilStr::strToLower($answer)) == 0) return $key;
00532 break;
00533 case TEXTGAP_RATING_CASESENSITIVE:
00534 if (strcmp($value, $answer) == 0) return $key;
00535 break;
00536 case TEXTGAP_RATING_LEVENSHTEIN1:
00537 if (levenshtein($value, $answer) <= 1) return $key;
00538 break;
00539 case TEXTGAP_RATING_LEVENSHTEIN2:
00540 if (levenshtein($value, $answer) <= 2) return $key;
00541 break;
00542 case TEXTGAP_RATING_LEVENSHTEIN3:
00543 if (levenshtein($value, $answer) <= 3) return $key;
00544 break;
00545 case TEXTGAP_RATING_LEVENSHTEIN4:
00546 if (levenshtein($value, $answer) <= 4) return $key;
00547 break;
00548 case TEXTGAP_RATING_LEVENSHTEIN5:
00549 if (levenshtein($value, $answer) <= 5) return $key;
00550 break;
00551 }
00552 }
00553 return FALSE;
00554 }
00555
00565 function getTextRating()
00566 {
00567 return $this->text_rating;
00568 }
00569
00579 function setTextRating($a_text_rating)
00580 {
00581 switch ($a_text_rating)
00582 {
00583 case TEXTGAP_RATING_CASEINSENSITIVE:
00584 case TEXTGAP_RATING_CASESENSITIVE:
00585 case TEXTGAP_RATING_LEVENSHTEIN1:
00586 case TEXTGAP_RATING_LEVENSHTEIN2:
00587 case TEXTGAP_RATING_LEVENSHTEIN3:
00588 case TEXTGAP_RATING_LEVENSHTEIN4:
00589 case TEXTGAP_RATING_LEVENSHTEIN5:
00590 $this->text_rating = $a_text_rating;
00591 break;
00592 default:
00593 $this->text_rating = TEXTGAP_RATING_CASEINSENSITIVE;
00594 break;
00595 }
00596 }
00597
00609 function calculateReachedPoints($active_id, $pass = NULL)
00610 {
00611 global $ilDB;
00612
00613 $available_answers =& $this->getAvailableAnswers();
00614 $found_counter = 0;
00615
00616 if (is_null($pass))
00617 {
00618 $pass = $this->getSolutionMaxPass($active_id);
00619 }
00620 $query = sprintf("SELECT * FROM tst_solutions WHERE active_fi = %s AND question_fi = %s AND pass = %s",
00621 $ilDB->quote($active_id . ""),
00622 $ilDB->quote($this->getId() . ""),
00623 $ilDB->quote($pass . "")
00624 );
00625 $result = $ilDB->query($query);
00626 $points = 0;
00627 while ($data = $result->fetchRow(DB_FETCHMODE_ASSOC))
00628 {
00629 $enteredtext = $data["value1"];
00630 $index = $this->isAnswerCorrect($available_answers, $enteredtext);
00631 if ($index !== FALSE)
00632 {
00633 unset($available_answers[$index]);
00634 $points += $this->answers[$index]->getPoints();
00635 }
00636 }
00637
00638 $points = parent::calculateReachedPoints($active_id, $pass = NULL, $points);
00639 return $points;
00640 }
00641
00650 function setCorrectAnswers($a_correct_answers)
00651 {
00652 $this->correctanswers = $a_correct_answers;
00653 }
00654
00663 function getCorrectAnswers()
00664 {
00665 return $this->correctanswers;
00666 }
00667
00678 function saveWorkingData($active_id, $pass = NULL)
00679 {
00680 global $ilDB;
00681 global $ilUser;
00682
00683 if (is_null($pass))
00684 {
00685 include_once "./Modules/Test/classes/class.ilObjTest.php";
00686 $pass = ilObjTest::_getPass($active_id);
00687 }
00688 $entered_values = 0;
00689
00690 $query = sprintf("DELETE FROM tst_solutions WHERE active_fi = %s AND question_fi = %s AND pass = %s",
00691 $ilDB->quote($active_id . ""),
00692 $ilDB->quote($this->getId() . ""),
00693 $ilDB->quote($pass . "")
00694 );
00695 $result = $ilDB->query($query);
00696 foreach ($_POST as $key => $value)
00697 {
00698 if (preg_match("/^TEXTSUBSET_(\d+)/", $key, $matches))
00699 {
00700 if (strlen($value))
00701 {
00702 $query = sprintf("INSERT INTO tst_solutions (solution_id, active_fi, question_fi, value1, value2, pass, TIMESTAMP) VALUES (NULL, %s, %s, %s, NULL, %s, NULL)",
00703 $ilDB->quote($active_id),
00704 $ilDB->quote($this->getId()),
00705 $ilDB->quote(trim($value)),
00706 $ilDB->quote($pass . "")
00707 );
00708 $result = $ilDB->query($query);
00709 $entered_values++;
00710 }
00711 }
00712 }
00713 if ($entered_values)
00714 {
00715 include_once ("./classes/class.ilObjAssessmentFolder.php");
00716 if (ilObjAssessmentFolder::_enabledAssessmentLogging())
00717 {
00718 $this->logAction($this->lng->txtlng("assessment", "log_user_entered_values", ilObjAssessmentFolder::_getLogLanguage()), $active_id, $this->getId());
00719 }
00720 }
00721 else
00722 {
00723 include_once ("./classes/class.ilObjAssessmentFolder.php");
00724 if (ilObjAssessmentFolder::_enabledAssessmentLogging())
00725 {
00726 $this->logAction($this->lng->txtlng("assessment", "log_user_not_entered_values", ilObjAssessmentFolder::_getLogLanguage()), $active_id, $this->getId());
00727 }
00728 }
00729 parent::saveWorkingData($active_id, $pass);
00730 return true;
00731 }
00732
00741 function getQuestionType()
00742 {
00743 return "assTextSubset";
00744 }
00745
00754 function &joinAnswers()
00755 {
00756 $join = array();
00757 foreach ($this->answers as $answer)
00758 {
00759 if (!is_array($join[$answer->getPoints() . ""]))
00760 {
00761 $join[$answer->getPoints() . ""] = array();
00762 }
00763 array_push($join[$answer->getPoints() . ""], $answer->getAnswertext());
00764 }
00765 return $join;
00766 }
00767
00776 function getMaxTextboxWidth()
00777 {
00778 $maxwidth = 0;
00779 foreach ($this->answers as $answer)
00780 {
00781 $len = strlen($answer->getAnswertext());
00782 if ($len > $maxwidth) $maxwidth = $len;
00783 }
00784 return $maxwidth + 3;
00785 }
00786
00795 function getAdditionalTableName()
00796 {
00797 return "qpl_question_textsubset";
00798 }
00799
00808 function getAnswerTableName()
00809 {
00810 return "qpl_answer_textsubset";
00811 }
00812
00817 function getRTETextWithMediaObjects()
00818 {
00819 return parent::getRTETextWithMediaObjects();
00820 }
00821 }
00822
00823 ?>