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 assNumeric extends assQuestion
00038 {
00046 var $ranges;
00047
00055 var $maxchars;
00056
00070 function assNumeric(
00071 $title = "",
00072 $comment = "",
00073 $author = "",
00074 $owner = -1,
00075 $question = ""
00076 )
00077 {
00078 $this->assQuestion($title, $comment, $author, $owner, $question);
00079 $this->ranges = array();
00080 $this->maxchars = 6;
00081 }
00082
00091 function isComplete()
00092 {
00093 if (($this->title) and ($this->author) and ($this->question) and (count($this->ranges)) 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, points, working_time, 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($this->getMaximumPoints() . ""),
00149 $ilDB->quote($estw_time),
00150 $ilDB->quote("$complete"),
00151 $ilDB->quote($created),
00152 $original_id
00153 );
00154 $result = $ilDB->query($query);
00155
00156 if ($result == DB_OK)
00157 {
00158 $this->id = $ilDB->getLastInsertId();
00159 $query = sprintf("INSERT INTO qpl_question_numeric (question_fi, maxNumOfChars) VALUES (%s, %s)",
00160 $ilDB->quote($this->id . ""),
00161 $ilDB->quote($this->getMaxChars() . "")
00162 );
00163 $ilDB->query($query);
00164
00165
00166 $this->createPageObject();
00167
00168 if ($this->getTestId() > 0)
00169 {
00170 $this->insertIntoTest($this->getTestId());
00171 }
00172 }
00173 }
00174 else
00175 {
00176
00177 $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",
00178 $ilDB->quote($this->obj_id. ""),
00179 $ilDB->quote($this->title),
00180 $ilDB->quote($this->comment),
00181 $ilDB->quote($this->author),
00182 $ilDB->quote(ilRTE::_replaceMediaObjectImageSrc($this->question, 0)),
00183 $ilDB->quote($this->getMaximumPoints() . ""),
00184 $ilDB->quote($estw_time),
00185 $ilDB->quote("$complete"),
00186 $ilDB->quote($this->id)
00187 );
00188 $result = $ilDB->query($query);
00189 $query = sprintf("UPDATE qpl_question_numeric SET maxNumOfChars = %s WHERE question_fi = %s",
00190 $ilDB->quote($this->getMaxChars() . ""),
00191 $ilDB->quote($this->id . "")
00192 );
00193 $result = $ilDB->query($query);
00194 }
00195 if ($result == DB_OK)
00196 {
00197
00198
00199
00200 $query = sprintf("DELETE FROM qpl_numeric_range WHERE question_fi = %s",
00201 $ilDB->quote($this->id)
00202 );
00203 $result = $ilDB->query($query);
00204
00205
00206 foreach ($this->ranges as $key => $range)
00207 {
00208 $query = sprintf("INSERT INTO qpl_numeric_range (range_id, question_fi, lowerlimit, upperlimit, points, aorder, lastchange) VALUES (NULL, %s, %s, %s, %s, %s, NULL)",
00209 $ilDB->quote($this->id),
00210 $ilDB->quote($range->getLowerLimit()),
00211 $ilDB->quote($range->getUpperLimit() . ""),
00212 $ilDB->quote($range->getPoints() . ""),
00213 $ilDB->quote($range->getOrder() . "")
00214 );
00215 $answer_result = $ilDB->query($query);
00216 }
00217 }
00218 parent::saveToDb($original_id);
00219 }
00220
00230 function loadFromDb($question_id)
00231 {
00232 global $ilDB;
00233
00234 $query = sprintf("SELECT qpl_questions.*, qpl_question_numeric.* FROM qpl_questions, qpl_question_numeric WHERE question_id = %s AND qpl_questions.question_id = qpl_question_numeric.question_fi",
00235 $ilDB->quote($question_id)
00236 );
00237 $result = $ilDB->query($query);
00238 if (strcmp(strtolower(get_class($result)), db_result) == 0)
00239 {
00240 if ($result->numRows() == 1)
00241 {
00242 $data = $result->fetchRow(DB_FETCHMODE_OBJECT);
00243 $this->id = $question_id;
00244 $this->title = $data->title;
00245 $this->comment = $data->comment;
00246 $this->solution_hint = $data->solution_hint;
00247 $this->original_id = $data->original_id;
00248 $this->obj_id = $data->obj_fi;
00249 $this->author = $data->author;
00250 $this->owner = $data->owner;
00251 $this->points = $data->points;
00252 include_once("./Services/RTE/classes/class.ilRTE.php");
00253 $this->question = ilRTE::_replaceMediaObjectImageSrc($data->question_text, 1);
00254 $this->maxchars = $data->maxNumOfChars;
00255 $this->setEstimatedWorkingTime(substr($data->working_time, 0, 2), substr($data->working_time, 3, 2), substr($data->working_time, 6, 2));
00256 }
00257
00258 $query = sprintf("SELECT * FROM qpl_numeric_range WHERE question_fi = %s ORDER BY aorder ASC",
00259 $ilDB->quote($question_id)
00260 );
00261
00262 $result = $ilDB->query($query);
00263
00264 include_once "./Modules/TestQuestionPool/classes/class.assNumericRange.php";
00265 if (strcmp(strtolower(get_class($result)), db_result) == 0)
00266 {
00267 while ($data = $result->fetchRow(DB_FETCHMODE_ASSOC))
00268 {
00269 array_push($this->ranges, new assNumericRange($data["lowerlimit"], $data["upperlimit"], $data["points"], $data["aorder"]));
00270 }
00271 }
00272 }
00273 parent::loadFromDb($question_id);
00274 }
00275
00290 function addRange(
00291 $lowerlimit = 0.0,
00292 $upperlimit = 0.0,
00293 $points = 0.0,
00294 $order = 0
00295 )
00296 {
00297 $found = -1;
00298 foreach ($this->ranges as $key => $range)
00299 {
00300 if ($range->getOrder() == $order)
00301 {
00302 $found = $order;
00303 }
00304 }
00305 include_once "./Modules/TestQuestionPool/classes/class.assNumericRange.php";
00306 if ($found >= 0)
00307 {
00308
00309 $range = new assNumericRange($lowerlimit, $upperlimit, $points, $found);
00310 array_push($this->ranges, $range);
00311 for ($i = $found + 1; $i < count($this->ranges); $i++)
00312 {
00313 $this->ranges[$i] = $this->ranges[$i-1];
00314 }
00315 $this->ranges[$found] = $range;
00316 }
00317 else
00318 {
00319
00320 $range = new assNumericRange($lowerlimit, $upperlimit, $points, count($this->ranges));
00321 array_push($this->ranges, $range);
00322 }
00323 }
00324
00332 function duplicate($for_test = true, $title = "", $author = "", $owner = "")
00333 {
00334 if ($this->id <= 0)
00335 {
00336
00337 return;
00338 }
00339
00340 $this_id = $this->getId();
00341 $clone = $this;
00342 include_once ("./Modules/TestQuestionPool/classes/class.assQuestion.php");
00343 $original_id = assQuestion::_getOriginalId($this->id);
00344 $clone->id = -1;
00345 if ($title)
00346 {
00347 $clone->setTitle($title);
00348 }
00349
00350 if ($author)
00351 {
00352 $clone->setAuthor($author);
00353 }
00354 if ($owner)
00355 {
00356 $clone->setOwner($owner);
00357 }
00358
00359 if ($for_test)
00360 {
00361 $clone->saveToDb($original_id);
00362 }
00363 else
00364 {
00365 $clone->saveToDb();
00366 }
00367
00368
00369 $clone->copyPageOfQuestion($this_id);
00370
00371 $clone->copyXHTMLMediaObjectsOfQuestion($this_id);
00372
00373 $clone->duplicateFeedbackGeneric($this_id);
00374
00375 return $clone->id;
00376 }
00377
00385 function copyObject($target_questionpool, $title = "")
00386 {
00387 if ($this->id <= 0)
00388 {
00389
00390 return;
00391 }
00392
00393 $clone = $this;
00394 include_once ("./Modules/TestQuestionPool/classes/class.assQuestion.php");
00395 $original_id = assQuestion::_getOriginalId($this->id);
00396 $clone->id = -1;
00397 $source_questionpool = $this->getObjId();
00398 $clone->setObjId($target_questionpool);
00399 if ($title)
00400 {
00401 $clone->setTitle($title);
00402 }
00403 $clone->saveToDb();
00404
00405
00406 $clone->copyPageOfQuestion($original_id);
00407
00408 $clone->copyXHTMLMediaObjectsOfQuestion($original_id);
00409
00410 $clone->duplicateFeedbackGeneric($original_id);
00411
00412 return $clone->id;
00413 }
00414
00424 function getRangeCount()
00425 {
00426 return count($this->ranges);
00427 }
00428
00440 function getRange($index = 0)
00441 {
00442 if ($index < 0) return NULL;
00443 if (count($this->ranges) < 1) return NULL;
00444 if ($index >= count($this->ranges)) return NULL;
00445
00446 return $this->ranges[$index];
00447 }
00448
00459 function deleteRange($index = 0)
00460 {
00461 if ($index < 0) return;
00462 if (count($this->ranges) < 1) return;
00463 if ($index >= count($this->ranges)) return;
00464 unset($this->ranges[$index]);
00465 $this->ranges = array_values($this->ranges);
00466 for ($i = 0; $i < count($this->ranges); $i++)
00467 {
00468 if ($this->ranges[$i]->getOrder() > $index)
00469 {
00470 $this->ranges[$i]->setOrder($i);
00471 }
00472 }
00473 }
00474
00483 function flushRanges()
00484 {
00485 $this->ranges = array();
00486 }
00487
00496 function getMaximumPoints()
00497 {
00498 $max = 0;
00499 foreach ($this->ranges as $key => $range)
00500 {
00501 if ($range->getPoints() > $max)
00502 {
00503 $max = $range->getPoints();
00504 }
00505 }
00506 return $max;
00507 }
00508
00517 function getBestRange()
00518 {
00519 $max = 0;
00520 $bestrange = NULL;
00521 foreach ($this->ranges as $key => $range)
00522 {
00523 if ($range->getPoints() > $max)
00524 {
00525 $max = $range->getPoints();
00526 $bestrange = $range;
00527 }
00528 }
00529 return $bestrange;
00530 }
00531
00543 function calculateReachedPoints($active_id, $pass = NULL)
00544 {
00545 global $ilDB;
00546
00547 $found_values = array();
00548 if (is_null($pass))
00549 {
00550 $pass = $this->getSolutionMaxPass($active_id);
00551 }
00552 $query = sprintf("SELECT * FROM tst_solutions WHERE active_fi = %s AND question_fi = %s AND pass = %s",
00553 $ilDB->quote($active_id . ""),
00554 $ilDB->quote($this->getId() . ""),
00555 $ilDB->quote($pass . "")
00556 );
00557 $result = $ilDB->query($query);
00558 $data = $result->fetchRow(DB_FETCHMODE_ASSOC);
00559
00560 $enteredvalue = $data["value1"];
00561
00562 $points = 0;
00563 foreach ($this->ranges as $key => $range)
00564 {
00565 if ($points == 0)
00566 {
00567 if ($range->contains($enteredvalue))
00568 {
00569 $points = $range->getPoints();
00570 }
00571 }
00572 }
00573
00574 $points = parent::calculateReachedPoints($active_id, $pass = NULL, $points);
00575 return $points;
00576 }
00577
00588 function saveWorkingData($active_id, $pass = NULL)
00589 {
00590 global $ilDB;
00591 global $ilUser;
00592
00593 if (is_null($pass))
00594 {
00595 include_once "./Modules/Test/classes/class.ilObjTest.php";
00596 $pass = ilObjTest::_getPass($active_id);
00597 }
00598 $entered_values = 0;
00599 $numeric_result = str_replace(",",".",$_POST["numeric_result"]);
00600
00601 include_once "./Services/Math/classes/class.EvalMath.php";
00602 $math = new EvalMath();
00603 $math->suppress_errors = TRUE;
00604 $result = $math->evaluate($numeric_result);
00605 $returnvalue = true;
00606 if (($result === FALSE) || ($result === TRUE))
00607 {
00608 ilUtil::sendInfo($this->lng->txt("err_no_numeric_value"), true);
00609 $returnvalue = false;
00610 }
00611 $query = sprintf("SELECT * FROM tst_solutions WHERE active_fi = %s AND question_fi = %s AND pass = %s",
00612 $ilDB->quote($active_id . ""),
00613 $ilDB->quote($this->getId() . ""),
00614 $ilDB->quote($pass . "")
00615 );
00616 $result = $ilDB->query($query);
00617 $row = $result->fetchRow(DB_FETCHMODE_OBJECT);
00618 $update = $row->solution_id;
00619 if ($update)
00620 {
00621 if (strlen($numeric_result))
00622 {
00623 $query = sprintf("UPDATE tst_solutions SET value1 = %s WHERE solution_id = %s",
00624 $ilDB->quote(trim($numeric_result)),
00625 $ilDB->quote($update)
00626 );
00627 $result = $ilDB->query($query);
00628 $entered_values++;
00629 }
00630 else
00631 {
00632 $query = sprintf("DELETE FROM tst_solutions WHERE solution_id = %s",
00633 $ilDB->quote($update)
00634 );
00635 $result = $ilDB->query($query);
00636 }
00637 }
00638 else
00639 {
00640 if (strlen($numeric_result))
00641 {
00642 $query = sprintf("INSERT INTO tst_solutions (solution_id, active_fi, question_fi, value1, value2, pass, TIMESTAMP) VALUES (NULL, %s, %s, %s, NULL, %s, NULL)",
00643 $ilDB->quote($active_id),
00644 $ilDB->quote($this->getId()),
00645 $ilDB->quote(trim($numeric_result)),
00646 $ilDB->quote($pass . "")
00647 );
00648 $result = $ilDB->query($query);
00649 $entered_values++;
00650 }
00651 }
00652 if ($entered_values)
00653 {
00654 include_once ("./classes/class.ilObjAssessmentFolder.php");
00655 if (ilObjAssessmentFolder::_enabledAssessmentLogging())
00656 {
00657 $this->logAction($this->lng->txtlng("assessment", "log_user_entered_values", ilObjAssessmentFolder::_getLogLanguage()), $active_id, $this->getId());
00658 }
00659 }
00660 else
00661 {
00662 include_once ("./classes/class.ilObjAssessmentFolder.php");
00663 if (ilObjAssessmentFolder::_enabledAssessmentLogging())
00664 {
00665 $this->logAction($this->lng->txtlng("assessment", "log_user_not_entered_values", ilObjAssessmentFolder::_getLogLanguage()), $active_id, $this->getId());
00666 }
00667 }
00668 parent::saveWorkingData($active_id, $pass);
00669
00670 return $returnvalue;
00671 }
00672
00681 function getQuestionType()
00682 {
00683 return "assNumeric";
00684 }
00685
00694 function getMaxChars()
00695 {
00696 return $this->maxchars;
00697 }
00698
00707 function setMaxChars($maxchars)
00708 {
00709 $this->maxchars = $maxchars;
00710 }
00711
00720 function getAdditionalTableName()
00721 {
00722 return "qpl_question_numeric";
00723 }
00724
00729 function getRTETextWithMediaObjects()
00730 {
00731 return parent::getRTETextWithMediaObjects();
00732 }
00733
00737 function &getRanges()
00738 {
00739 return $this->ranges;
00740 }
00741 }
00742
00743 ?>