00001 <?php
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00035 include_once "./classes/class.ilObject.php";
00036 include_once "./assessment/classes/inc.AssessmentConstants.php";
00037
00038 class ilObjTest extends ilObject
00039 {
00047 var $test_id;
00048
00056 var $invitation = INVITATION_OFF;
00057
00058
00067 var $author;
00068
00076 var $metadata;
00077
00085 var $questions;
00086
00095 var $introduction;
00096
00104 var $mark_schema;
00105
00115 var $sequence_settings;
00116
00128 var $score_reporting;
00129
00139 var $instant_verification;
00140
00151 var $reporting_date;
00152
00160 var $evaluation_data;
00161
00169 var $test_type;
00170
00179 var $nr_of_tries;
00180
00189 var $hide_previous_results;
00190
00198 var $hide_title_points;
00199
00207 var $processing_time;
00208
00216 var $enable_processing_time;
00217
00225 var $starting_time;
00226
00234 var $ending_time;
00235
00243 var $ects_output;
00244
00252 var $ects_fx;
00253
00264 var $test_types;
00265
00273 var $ects_grades;
00274
00284 var $random_test;
00285
00293 var $random_question_count;
00294
00301 var $count_system;
00302
00308 var $mc_scoring;
00309
00315 var $pass_scoring;
00316
00323 var $shuffle_questions;
00324
00331 var $show_solution_details;
00332
00338 var $show_summary;
00339
00346 var $show_solution_printview;
00347
00353 var $score_cutting;
00354
00360 var $password;
00361
00367 var $allowedUsers;
00368
00374 var $allowedUsersTimeGap;
00375
00382 function ilObjTest($a_id = 0,$a_call_by_reference = true)
00383 {
00384 global $ilUser;
00385 $this->type = "tst";
00386 include_once "./assessment/classes/class.assMarkSchema.php";
00387 $this->mark_schema = new ASS_MarkSchema();
00388
00389 $this->retrieveTestTypes();
00390 $this->test_id = -1;
00391 $this->author = $ilUser->fullname;
00392 $this->introduction = "";
00393 $this->questions = array();
00394 $this->sequence_settings = TEST_FIXED_SEQUENCE;
00395 $this->score_reporting = REPORT_AFTER_TEST;
00396 $this->instant_verification = 0;
00397 $this->reporting_date = "";
00398 $this->nr_of_tries = 0;
00399 $this->hide_previous_results = 0;
00400 $this->hide_title_points = 0;
00401 $this->starting_time = "";
00402 $this->ending_time = "";
00403 $this->processing_time = "00:00:00";
00404 $this->enable_processing_time = "0";
00405 $this->test_type = TYPE_ASSESSMENT;
00406 $this->ects_output = 0;
00407 $this->ects_fx = "";
00408 $this->random_test = 0;
00409 $this->shuffle_questions = FALSE;
00410 $this->show_solution_details = TRUE;
00411 $this->show_summary = FALSE;
00412 $this->show_solution_printview = FALSE;
00413 $this->random_question_count = "";
00414 $this->count_system = COUNT_PARTIAL_SOLUTIONS;
00415 $this->mc_scoring = SCORE_ZERO_POINTS_WHEN_UNANSWERED;
00416 $this->score_cutting = SCORE_CUT_QUESTION;
00417 $this->pass_scoring = SCORE_LAST_PASS;
00418 $this->password = "";
00419 $this->allowedUsers = "";
00420 $this->allowedUsersTimeGap = "";
00421 global $lng;
00422 $lng->loadLanguageModule("assessment");
00423 $this->mark_schema->createSimpleSchema($lng->txt("failed_short"), $lng->txt("failed_official"), 0, 0, $lng->txt("passed_short"), $lng->txt("passed_official"), 50, 1);
00424 $this->ects_grades = array(
00425 "A" => 90,
00426 "B" => 65,
00427 "C" => 35,
00428 "D" => 10,
00429 "E" => 0
00430 );
00431 $this->ilObject($a_id, $a_call_by_reference);
00432 }
00433
00437 function create($a_upload = false)
00438 {
00439 parent::create();
00440
00441
00442
00443 if (!$a_upload)
00444 {
00445 $this->createMetaData();
00446 }
00447 }
00448
00455 function update()
00456 {
00457 $this->updateMetaData();
00458 if (!parent::update())
00459 {
00460 return false;
00461 }
00462
00463
00464
00465 return true;
00466 }
00467
00476 function createReference() {
00477 $result = parent::createReference();
00478 $this->saveToDb();
00479 return $result;
00480 }
00481
00487 function read($a_force_db = false)
00488 {
00489 parent::read($a_force_db);
00490 $this->loadFromDb();
00491 }
00492
00500 function ilClone($a_parent_ref)
00501 {
00502 global $rbacadmin;
00503
00504
00505 $new_ref_id = parent::ilClone($a_parent_ref);
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520 return $new_ref_id;
00521 }
00522
00529 function delete()
00530 {
00531
00532 if (!parent::delete())
00533 {
00534 return false;
00535 }
00536
00537
00538 $this->deleteMetaData();
00539
00540
00541 $this->deleteTest();
00542
00543 return true;
00544 }
00545
00553 function deleteTest()
00554 {
00555 global $ilDB;
00556
00557 $query = sprintf("SELECT active_id FROM tst_active WHERE test_fi = %s",
00558 $ilDB->quote($this->getTestId())
00559 );
00560 $result = $ilDB->query($query);
00561 $active_array = array();
00562 while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC))
00563 {
00564 array_push($active_array, $row["active_id"]);
00565 }
00566
00567 $query = sprintf("DELETE FROM tst_active WHERE test_fi = %s",
00568 $ilDB->quote($this->getTestId())
00569 );
00570 $result = $ilDB->query($query);
00571
00572 if (count($active_array))
00573 {
00574 foreach ($active_array as $active_id)
00575 {
00576 $query = sprintf("DELETE FROM tst_times WHERE active_fi = %s",
00577 $ilDB->quote($active_id)
00578 );
00579 $result = $ilDB->query($query);
00580 }
00581 }
00582
00583 $query = sprintf("DELETE FROM tst_mark WHERE test_fi = %s",
00584 $ilDB->quote($this->getTestId())
00585 );
00586 $result = $ilDB->query($query);
00587
00588 $query = sprintf("SELECT question_fi FROM tst_test_question WHERE test_fi = %s",
00589 $ilDB->quote($this->getTestId())
00590 );
00591 $result = $ilDB->query($query);
00592 while ($row = $result->fetchRow(DB_FETCHMODE_OBJECT))
00593 {
00594 $this->removeQuestion($row->question_fi);
00595 }
00596
00597 $query = sprintf("DELETE FROM tst_tests WHERE test_id = %s",
00598 $ilDB->quote($this->getTestId())
00599 );
00600 $result = $ilDB->query($query);
00601
00602 $query = sprintf("DELETE FROM tst_test_random WHERE test_fi = %s",
00603 $ilDB->quote($this->getTestId())
00604 );
00605 $result = $ilDB->query($query);
00606
00607 $query = sprintf("DELETE FROM tst_test_random_question USING tst_test_random_question, tst_active WHERE tst_active.test_fi = %s AND tst_active.active_id = tst_test_random_question.active_fi",
00608 $ilDB->quote($this->getTestId())
00609 );
00610 $result = $ilDB->query($query);
00611
00612 $this->removeAllTestEditings();
00613
00614 $query = sprintf("DELETE FROM tst_test_question WHERE test_fi = %s",
00615 $ilDB->quote($this->getTestId())
00616 );
00617 $result = $ilDB->query($query);
00618
00619
00620 include_once "./classes/class.ilUtil.php";
00621 $tst_data_dir = ilUtil::getDataDir()."/tst_data";
00622 $directory = $tst_data_dir."/tst_".$this->getId();
00623 if (is_dir($directory))
00624 {
00625 include_once "./classes/class.ilUtil.php";
00626 ilUtil::delDir($directory);
00627 }
00628 include_once("./content/classes/Media/class.ilObjMediaObject.php");
00629 $mobs = ilObjMediaObject::_getMobsOfObject("tst:html", $this->getId());
00630
00631
00632
00633
00634 foreach($mobs as $mob)
00635 {
00636 ilObjMediaObject::_removeUsage($mob, "tst:html", $this->getId());
00637 $mob_obj =& new ilObjMediaObject($mob);
00638 $mob_obj->delete();
00639 }
00640 }
00641
00651 function initDefaultRoles()
00652 {
00653 global $rbacadmin;
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665 return $roles ? $roles : array();
00666 }
00667
00681 function notify($a_event,$a_ref_id,$a_parent_non_rbac_id,$a_node_id,$a_params = 0)
00682 {
00683 global $tree;
00684
00685 switch ($a_event)
00686 {
00687 case "link":
00688
00689
00690
00691
00692 break;
00693
00694 case "cut":
00695
00696
00697
00698 break;
00699
00700 case "copy":
00701
00702
00703
00704
00705 break;
00706
00707 case "paste":
00708
00709
00710
00711 break;
00712
00713 case "new":
00714
00715
00716
00717 break;
00718 }
00719
00720
00721 if ($a_node_id==$_GET["ref_id"])
00722 {
00723 $parent_obj =& $this->ilias->obj_factory->getInstanceByRefId($a_node_id);
00724 $parent_type = $parent_obj->getType();
00725 if($parent_type == $this->getType())
00726 {
00727 $a_node_id = (int) $tree->getParentId($a_node_id);
00728 }
00729 }
00730
00731 parent::notify($a_event,$a_ref_id,$a_parent_non_rbac_id,$a_node_id,$a_params);
00732 }
00733
00739 function createExportDirectory()
00740 {
00741 include_once "./classes/class.ilUtil.php";
00742 $tst_data_dir = ilUtil::getDataDir()."/tst_data";
00743 ilUtil::makeDir($tst_data_dir);
00744 if(!is_writable($tst_data_dir))
00745 {
00746 $this->ilias->raiseError("Test Data Directory (".$tst_data_dir
00747 .") not writeable.",$this->ilias->error_obj->MESSAGE);
00748 }
00749
00750
00751 $tst_dir = $tst_data_dir."/tst_".$this->getId();
00752 ilUtil::makeDir($tst_dir);
00753 if(!@is_dir($tst_dir))
00754 {
00755 $this->ilias->raiseError("Creation of Test Directory failed.",$this->ilias->error_obj->MESSAGE);
00756 }
00757
00758 $export_dir = $tst_dir."/export";
00759 ilUtil::makeDir($export_dir);
00760 if(!@is_dir($export_dir))
00761 {
00762 $this->ilias->raiseError("Creation of Export Directory failed.",$this->ilias->error_obj->MESSAGE);
00763 }
00764 }
00765
00773 function getExportDirectory()
00774 {
00775 include_once "./classes/class.ilUtil.php";
00776 $export_dir = ilUtil::getDataDir()."/tst_data"."/tst_".$this->getId()."/export";
00777 return $export_dir;
00778 }
00779
00788 function getExportFiles($dir)
00789 {
00790
00791 if (!@is_dir($dir) or
00792 !is_writeable($dir))
00793 {
00794 return array();
00795 }
00796
00797
00798 $dir = dir($dir);
00799
00800
00801 $file = array();
00802
00803
00804 while ($entry = $dir->read())
00805 {
00806 if ($entry != "." and
00807 $entry != ".." and
00808
00809 ereg("^[0-9]{10}_{2}[0-9]+_{2}(test(__results)?__)*[0-9]+\.[a-z]{1,3}\$", $entry))
00810 {
00811 $file[] = $entry;
00812 }
00813 }
00814
00815
00816 $dir->close();
00817
00818
00819 sort ($file);
00820 reset ($file);
00821
00822 return $file;
00823 }
00824
00825
00831 function _createImportDirectory()
00832 {
00833 global $ilias;
00834
00835 include_once "./classes/class.ilUtil.php";
00836 $tst_data_dir = ilUtil::getDataDir()."/tst_data";
00837 ilUtil::makeDir($tst_data_dir);
00838
00839 if(!is_writable($tst_data_dir))
00840 {
00841 $ilias->raiseError("Test data directory (".$tst_data_dir
00842 .") not writeable.",$ilias->error_obj->FATAL);
00843 }
00844
00845
00846 $tst_dir = $tst_data_dir."/tst_import";
00847 ilUtil::makeDir($tst_dir);
00848 if(!@is_dir($tst_dir))
00849 {
00850 $ilias->raiseError("Creation of test import directory failed.",$ilias->error_obj->FATAL);
00851 }
00852 }
00853
00862 function _getImportDirectory()
00863 {
00864 include_once "./classes/class.ilUtil.php";
00865 $import_dir = ilUtil::getDataDir()."/tst_data/tst_import";
00866 if(@is_dir($import_dir))
00867 {
00868 return $import_dir;
00869 }
00870 else
00871 {
00872 return false;
00873 }
00874 }
00875
00881 function createImportDirectory()
00882 {
00883 include_once "./classes/class.ilUtil.php";
00884 $tst_data_dir = ilUtil::getDataDir()."/tst_data";
00885 ilUtil::makeDir($tst_data_dir);
00886
00887 if(!is_writable($tst_data_dir))
00888 {
00889 $this->ilias->raiseError("Test Data Directory (".$tst_data_dir
00890 .") not writeable.",$this->ilias->error_obj->FATAL);
00891 }
00892
00893
00894 $tst_dir = $tst_data_dir."/tst_import";
00895 ilUtil::makeDir($tst_dir);
00896 if(!@is_dir($tst_dir))
00897 {
00898 $ilias->raiseError("Creation of test import directory failed.",$ilias->error_obj->FATAL);
00899 }
00900 }
00901
00910 function getImportDirectory()
00911 {
00912 include_once "./classes/class.ilUtil.php";
00913 $import_dir = ilUtil::getDataDir()."/tst_data/tst_import";
00914 if(@is_dir($import_dir))
00915 {
00916 return $import_dir;
00917 }
00918 else
00919 {
00920 return false;
00921 }
00922 }
00923
00924
00934 function retrieveTestTypes()
00935 {
00936 global $ilDB;
00937
00938 $this->test_types = array();
00939 $query = "SELECT * FROM tst_test_type ORDER BY test_type_id";
00940 $result = $ilDB->query($query);
00941 while ($row = $result->fetchRow(DB_FETCHMODE_OBJECT))
00942 {
00943 $this->test_types[$row->test_type_id] = $row->type_tag;
00944 }
00945 }
00946
00956 function testTitleExists($title)
00957 {
00958 global $ilDB;
00959
00960 $query = sprintf("SELECT * FROM object_data WHERE title = %s AND type = %s",
00961 $ilDB->quote($title),
00962 $ilDB->quote("tst")
00963 );
00964 $result = $ilDB->query($query);
00965 if (strcmp(strtolower(get_class($result)), db_result) == 0) {
00966 if ($result->numRows() == 1) {
00967 return TRUE;
00968 }
00969 }
00970 return FALSE;
00971 }
00972
00980 function duplicate()
00981 {
00982 global $ilDB;
00983
00984 $clone = $this;
00985 $clone->setId(-1);
00986 $counter = 2;
00987 while ($this->testTitleExists($this->get_title() . " ($counter)")) {
00988 $counter++;
00989 }
00990 $clone->setTitle($this->get_title() . " ($counter)");
00991 $clone->setOwner($this->ilias->account->id);
00992 $clone->setAuthor($this->ilias->account->fullname);
00993 $clone->saveToDb($ilDB);
00994
00995 $query = sprintf("SELECT * FROM tst_test_question WHERE test_fi = %s",
00996 $ilDB->quote($this->getId())
00997 );
00998 $result = $ilDB->query($query);
00999 while ($data = $result->fetchRow(DB_FETCHMODE_OBJECT)) {
01000 $query = sprintf("INSERT INTO tst_test_question (test_question_id, test_fi, question_fi, sequence, TIMESTAMP) VALUES (NULL, %s, %s, %s, NULL)",
01001 $ilDB->quote($clone->getId()),
01002 $ilDB->quote($data->question_fi),
01003 $ilDB->quote($data->sequence)
01004 );
01005 $insert_result = $ilDB->query($query);
01006 }
01007 }
01008
01017 function isComplete()
01018 {
01019 if (($this->getTitle()) and ($this->author) and (count($this->mark_schema->mark_steps)) and (count($this->questions)))
01020 {
01021 return true;
01022 }
01023 else
01024 {
01025 if ($this->isRandomTest())
01026 {
01027 $arr = $this->getRandomQuestionpools();
01028 if (count($arr) && ($this->getRandomQuestionCount() > 0))
01029 {
01030 return true;
01031 }
01032 $count = 0;
01033 foreach ($arr as $array)
01034 {
01035 $count += $array["count"];
01036 }
01037 if ($count)
01038 {
01039 return true;
01040 }
01041 }
01042 return false;
01043 }
01044 }
01045
01054 function _isComplete($obj_id)
01055 {
01056 $test = new ilObjTest($obj_id, false);
01057 $test->loadFromDb();
01058 return $test->isComplete();
01059 }
01060
01068 function saveECTSStatus($ects_output = 0, $fx_support = "", $ects_a = 90, $ects_b = 65, $ects_c = 35, $ects_d = 10, $ects_e = 0)
01069 {
01070 global $ilDB;
01071 if ($this->test_id > 0) {
01072 $fx_support = preg_replace("/,/", ".", $fx_support);
01073 if (preg_match("/\d+/", $fx_support))
01074 {
01075 $fx_support = $fx_support;
01076 }
01077 else
01078 {
01079 $fx_support = "NULL";
01080 }
01081 $query = sprintf("UPDATE tst_tests SET ects_output = %s, ects_a = %s, ects_b = %s, ects_c = %s, ects_d = %s, ects_e = %s, ects_fx = %s WHERE test_id = %s",
01082 $ilDB->quote("$ects_output"),
01083 $ilDB->quote($ects_a . ""),
01084 $ilDB->quote($ects_b . ""),
01085 $ilDB->quote($ects_c . ""),
01086 $ilDB->quote($ects_d . ""),
01087 $ilDB->quote($ects_e . ""),
01088 $fx_support,
01089 $this->getTestId()
01090 );
01091 $result = $ilDB->query($query);
01092 $this->ects_output = $ects_output;
01093 $this->ects_fx = $fx_support;
01094 }
01095 }
01096
01104 function saveCompleteStatus()
01105 {
01106 global $ilDB;
01107
01108 $complete = 0;
01109 if ($this->isComplete()) {
01110 $complete = 1;
01111 }
01112 if ($this->test_id > 0) {
01113 $query = sprintf("UPDATE tst_tests SET complete = %s WHERE test_id = %s",
01114 $ilDB->quote("$complete"),
01115 $ilDB->quote($this->test_id)
01116 );
01117 $result = $ilDB->query($query);
01118 }
01119 }
01120
01129 function saveToDb($properties_only = FALSE)
01130 {
01131 global $ilDB;
01132
01133 $complete = 0;
01134 if ($this->isComplete()) {
01135 $complete = 1;
01136 }
01137 $ects_fx = "NULL";
01138 if (preg_match("/\d+/", $this->ects_fx))
01139 {
01140 $ects_fx = $this->ects_fx;
01141 }
01142 $random_question_count = "NULL";
01143 if ($this->random_question_count > 0)
01144 {
01145 $random_question_count = $ilDB->quote($this->random_question_count . "");
01146 }
01147 $shuffle_questions = 0;
01148 if ($this->getShuffleQuestions())
01149 {
01150 $shuffle_questions = 1;
01151 }
01152 $show_solution_details = 0;
01153 if ($this->getShowSolutionDetails())
01154 {
01155 $show_solution_details = 1;
01156 }
01157 $show_summary = 0;
01158 if ($this->getShowSummary())
01159 {
01160 $show_summary = 1;
01161 }
01162 $show_solution_printview = 0;
01163 if ($this->getShowSolutionPrintview())
01164 {
01165 $show_solution_printview = 1;
01166 }
01167 $allowedUsers = $this->getAllowedUsers();
01168 if ($allowedUsers == 0)
01169 {
01170 $allowedUsers = "NULL";
01171 }
01172 else
01173 {
01174 $allowedUsers = $ilDB->quote($allowedUsers);
01175 }
01176 $allowedUsersTimeGap = $this->getAllowedUsersTimeGap();
01177 if ($allowedUsersTimeGap == 0)
01178 {
01179 $allowedUsersTimeGap = "NULL";
01180 }
01181 else
01182 {
01183 $allowedUsersTimeGap = $ilDB->quote($allowedUsersTimeGap);
01184 }
01185
01186
01187 include_once("./Services/RTE/classes/class.ilRTE.php");
01188 ilRTE::_cleanupMediaObjectUsage($this->introduction, $this->getType() . ":html",
01189 $this->getId());
01190
01191 include_once ("./classes/class.ilObjAssessmentFolder.php");
01192 if ($this->test_id == -1)
01193 {
01194
01195 $now = getdate();
01196 $created = sprintf("%04d%02d%02d%02d%02d%02d", $now['year'], $now['mon'], $now['mday'], $now['hours'], $now['minutes'], $now['seconds']);
01197 $query = sprintf("INSERT INTO tst_tests (test_id, obj_fi, author, test_type_fi, introduction, sequence_settings, score_reporting, instant_verification, nr_of_tries, hide_previous_results, hide_title_points, processing_time, enable_processing_time, reporting_date, starting_time, ending_time, complete, ects_output, ects_a, ects_b, ects_c, ects_d, ects_e, ects_fx, random_test, random_question_count, count_system, mc_scoring, score_cutting, pass_scoring, shuffle_questions, show_solution_details, show_summary, show_solution_printview, password, allowedUsers, allowedUsersTimeGap, created, TIMESTAMP) VALUES (NULL, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, NULL)",
01198 $ilDB->quote($this->getId() . ""),
01199 $ilDB->quote($this->author . ""),
01200 $ilDB->quote($this->test_type . ""),
01201 $ilDB->quote(ilRTE::_replaceMediaObjectImageSrc($this->introduction, 0)),
01202 $ilDB->quote($this->sequence_settings . ""),
01203 $ilDB->quote($this->score_reporting . ""),
01204 $ilDB->quote($this->instant_verification . ""),
01205 $ilDB->quote(sprintf("%d", $this->nr_of_tries) . ""),
01206 $ilDB->quote(sprintf("%d", $this->getHidePreviousResults() . "")),
01207 $ilDB->quote(sprintf("%d", $this->getHideTitlePoints() . "")),
01208 $ilDB->quote($this->processing_time . ""),
01209 $ilDB->quote("$this->enable_processing_time"),
01210 $ilDB->quote($this->reporting_date . ""),
01211 $ilDB->quote($this->starting_time . ""),
01212 $ilDB->quote($this->ending_time . ""),
01213 $ilDB->quote("$complete"),
01214 $ilDB->quote($this->ects_output . ""),
01215 $ilDB->quote($this->ects_grades["A"] . ""),
01216 $ilDB->quote($this->ects_grades["B"] . ""),
01217 $ilDB->quote($this->ects_grades["C"] . ""),
01218 $ilDB->quote($this->ects_grades["D"] . ""),
01219 $ilDB->quote($this->ects_grades["E"] . ""),
01220 $ects_fx,
01221 $ilDB->quote(sprintf("%d", $this->random_test) . ""),
01222 $random_question_count,
01223 $ilDB->quote($this->count_system . ""),
01224 $ilDB->quote($this->mc_scoring . ""),
01225 $ilDB->quote($this->getScoreCutting() . ""),
01226 $ilDB->quote($this->getPassScoring() . ""),
01227 $ilDB->quote($shuffle_questions . ""),
01228 $ilDB->quote($show_solution_details . ""),
01229 $ilDB->quote($show_summary . ""),
01230 $ilDB->quote($show_solution_printview . ""),
01231 $ilDB->quote($this->getPassword() . ""),
01232 $allowedUsers,
01233 $allowedUsersTimeGap,
01234 $ilDB->quote($created)
01235 );
01236
01237 if (ilObjAssessmentFolder::_enabledAssessmentLogging())
01238 {
01239 $this->logAction($this->lng->txtlng("assessment", "log_create_new_test", ilObjAssessmentFolder::_getLogLanguage()));
01240 }
01241 $result = $ilDB->query($query);
01242 if ($result == DB_OK) {
01243 $this->test_id = $ilDB->getLastInsertId();
01244 }
01245 }
01246 else
01247 {
01248
01249 $oldrow = array();
01250 if (ilObjAssessmentFolder::_enabledAssessmentLogging())
01251 {
01252 $query = sprintf("SELECT * FROM tst_tests WHERE test_id = %s",
01253 $ilDB->quote($this->test_id)
01254 );
01255 $result = $ilDB->query($query);
01256 if ($result->numRows() == 1)
01257 {
01258 $oldrow = $result->fetchRow(DB_FETCHMODE_ASSOC);
01259 }
01260 }
01261 $query = sprintf("UPDATE tst_tests SET author = %s, test_type_fi = %s, introduction = %s, sequence_settings = %s, score_reporting = %s, instant_verification = %s, nr_of_tries = %s, hide_previous_results = %s, hide_title_points = %s, processing_time = %s, enable_processing_time = %s, reporting_date = %s, starting_time = %s, ending_time = %s, ects_output = %s, ects_a = %s, ects_b = %s, ects_c = %s, ects_d = %s, ects_e = %s, ects_fx = %s, random_test = %s, complete = %s, count_system = %s, mc_scoring = %s, score_cutting = %s, pass_scoring = %s, shuffle_questions = %s, show_solution_details = %s, show_summary = %s, show_solution_printview = %s, password = %s, allowedUsers = %s, allowedUsersTimeGap = %s WHERE test_id = %s",
01262 $ilDB->quote($this->author . ""),
01263 $ilDB->quote($this->test_type . ""),
01264 $ilDB->quote(ilRTE::_replaceMediaObjectImageSrc($this->introduction, 0)),
01265 $ilDB->quote($this->sequence_settings . ""),
01266 $ilDB->quote($this->score_reporting . ""),
01267 $ilDB->quote($this->instant_verification . ""),
01268 $ilDB->quote(sprintf("%d", $this->nr_of_tries) . ""),
01269 $ilDB->quote(sprintf("%d", $this->getHidePreviousResults() . "")),
01270 $ilDB->quote(sprintf("%d", $this->getHideTitlePoints() . "")),
01271 $ilDB->quote($this->processing_time . ""),
01272 $ilDB->quote("$this->enable_processing_time"),
01273 $ilDB->quote($this->reporting_date . ""),
01274 $ilDB->quote($this->starting_time . ""),
01275 $ilDB->quote($this->ending_time . ""),
01276 $ilDB->quote($this->ects_output . ""),
01277 $ilDB->quote($this->ects_grades["A"] . ""),
01278 $ilDB->quote($this->ects_grades["B"] . ""),
01279 $ilDB->quote($this->ects_grades["C"] . ""),
01280 $ilDB->quote($this->ects_grades["D"] . ""),
01281 $ilDB->quote($this->ects_grades["E"] . ""),
01282 $ects_fx,
01283 $ilDB->quote(sprintf("%d", $this->random_test) . ""),
01284 $ilDB->quote("$complete"),
01285 $ilDB->quote($this->count_system . ""),
01286 $ilDB->quote($this->mc_scoring . ""),
01287 $ilDB->quote($this->getScoreCutting() . ""),
01288 $ilDB->quote($this->getPassScoring() . ""),
01289 $ilDB->quote($shuffle_questions . ""),
01290 $ilDB->quote($show_solution_details . ""),
01291 $ilDB->quote($show_summary . ""),
01292 $ilDB->quote($show_solution_printview . ""),
01293 $ilDB->quote($this->getPassword() . ""),
01294 $allowedUsers,
01295 $allowedUsersTimeGap,
01296 $ilDB->quote($this->test_id)
01297 );
01298 $result = $ilDB->query($query);
01299 include_once ("./classes/class.ilObjAssessmentFolder.php");
01300 if (ilObjAssessmentFolder::_enabledAssessmentLogging())
01301 {
01302 $query = sprintf("SELECT * FROM tst_tests WHERE test_id = %s",
01303 $ilDB->quote($this->test_id)
01304 );
01305 $logresult = $ilDB->query($query);
01306 $newrow = array();
01307 if ($logresult->numRows() == 1)
01308 {
01309 $newrow = $logresult->fetchRow(DB_FETCHMODE_ASSOC);
01310 }
01311 $changed_fields = array();
01312 foreach ($oldrow as $key => $value)
01313 {
01314 if (strcmp($oldrow[$key], $newrow[$key]) != 0)
01315 {
01316 array_push($changed_fields, "$key: " . $oldrow[$key] . " => " . $newrow[$key]);
01317 }
01318 }
01319 $changes = join($changed_fields, ", ");
01320 if (count($changed_fields) == 0)
01321 {
01322 $changes = $this->lng->txtlng("assessment", "log_no_test_fields_changed", ilObjAssessmentFolder::_getLogLanguage());
01323 }
01324 $this->logAction($this->lng->txtlng("assessment", "log_modified_test", ilObjAssessmentFolder::_getLogLanguage()) . " [".$changes."]");
01325 }
01326 }
01327 if (!$properties_only)
01328 {
01329 if ($result == DB_OK) {
01330 if (!$this->isRandomTest())
01331 {
01332 $this->saveQuestionsToDb();
01333 }
01334 $this->mark_schema->saveToDb($this->test_id);
01335 }
01336 }
01337 }
01338
01347 function saveQuestionsToDb()
01348 {
01349 global $ilDB;
01350
01351 $oldquestions = array();
01352 include_once "./classes/class.ilObjAssessmentFolder.php";
01353 if (ilObjAssessmentFolder::_enabledAssessmentLogging())
01354 {
01355 $query = sprintf("SELECT question_fi FROM tst_test_question WHERE test_fi = %s ORDER BY sequence",
01356 $ilDB->quote($this->getTestId())
01357 );
01358 $result = $ilDB->query($query);
01359 if ($result->numRows() > 0)
01360 {
01361 while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC))
01362 {
01363 array_push($oldquestions, $row["question_fi"]);
01364 }
01365 }
01366 }
01367
01368
01369 $query = sprintf("DELETE FROM tst_test_question WHERE test_fi = %s",
01370 $ilDB->quote($this->getTestId())
01371 );
01372 $result = $ilDB->query($query);
01373
01374 foreach ($this->questions as $key => $value) {
01375 $query = sprintf("INSERT INTO tst_test_question (test_question_id, test_fi, question_fi, sequence, TIMESTAMP) VALUES (NULL, %s, %s, %s, NULL)",
01376 $ilDB->quote($this->getTestId() . ""),
01377 $ilDB->quote($value . ""),
01378 $ilDB->quote($key . "")
01379 );
01380 $result = $ilDB->query($query);
01381 }
01382 include_once ("./classes/class.ilObjAssessmentFolder.php");
01383 if (ilObjAssessmentFolder::_enabledAssessmentLogging())
01384 {
01385 $query = sprintf("SELECT question_fi FROM tst_test_question WHERE test_fi = %s ORDER BY sequence",
01386 $ilDB->quote($this->getTestId())
01387 );
01388 $result = $ilDB->query($query);
01389 $newquestions = array();
01390 if ($result->numRows() > 0)
01391 {
01392 while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC))
01393 {
01394 array_push($newquestions, $row["question_fi"]);
01395 }
01396 }
01397 foreach ($oldquestions as $index => $question_id)
01398 {
01399 if (strcmp($newquestions[$index], $question_id) != 0)
01400 {
01401 $pos = array_search($question_id, $newquestions);
01402 if ($pos === FALSE)
01403 {
01404 $this->logAction($this->lng->txtlng("assessment", "log_question_removed", ilObjAssessmentFolder::_getLogLanguage()), $question_id);
01405 }
01406 else
01407 {
01408 $this->logAction($this->lng->txtlng("assessment", "log_question_position_changed", ilObjAssessmentFolder::_getLogLanguage()) . ": " . ($index+1) . " => " . ($pos+1), $question_id);
01409 }
01410 }
01411 }
01412 foreach ($newquestions as $index => $question_id)
01413 {
01414 if (array_search($question_id, $oldquestions) === FALSE)
01415 {
01416 $this->logAction($this->lng->txtlng("assessment", "log_question_added", ilObjAssessmentFolder::_getLogLanguage()) . ": " . ($index+1), $question_id);
01417 }
01418 }
01419 }
01420 }
01421
01430 function saveRandomQuestion($active_id, $question_id, $pass = NULL, $maxcount)
01431 {
01432 global $ilUser;
01433 global $ilDB;
01434
01435 if (is_null($pass)) $pass = 0;
01436 $query = sprintf("SELECT test_random_question_id FROM tst_test_random_question WHERE active_fi = %s AND pass = %s",
01437 $ilDB->quote($active_id . ""),
01438 $ilDB->quote($pass . "")
01439 );
01440 $result = $ilDB->query($query);
01441 if ($result->numRows() < $maxcount)
01442 {
01443 $duplicate_id = $this->getRandomQuestionDuplicate($question_id, $active->active_id);
01444 if ($duplicate_id === FALSE)
01445 {
01446 $duplicate_id = $this->duplicateQuestionForTest($question_id);
01447 }
01448
01449 $query = sprintf("INSERT INTO tst_test_random_question (test_random_question_id, active_fi, question_fi, sequence, pass, TIMESTAMP) VALUES (NULL, %s, %s, %s, %s, NULL)",
01450 $ilDB->quote($active_id . ""),
01451 $ilDB->quote($duplicate_id . ""),
01452 $ilDB->quote(($result->numRows()+1) . ""),
01453 $ilDB->quote($pass . "")
01454 );
01455 $result = $ilDB->query($query);
01456 }
01457 }
01458
01470 function getRandomQuestionDuplicate($question_id, $active_id)
01471 {
01472 global $ilDB;
01473
01474 $query = sprintf("SELECT qpl_questions.question_id FROM qpl_questions, tst_test_random_question WHERE qpl_questions.original_id = %s AND tst_test_random_question.question_fi = qpl_questions.question_id AND tst_test_random_question.active_fi = %s",
01475 $ilDB->quote($question_id . ""),
01476 $ilDB->quote($active_id . "")
01477 );
01478 $result = $ilDB->query($query);
01479 $num = $result->numRows();
01480 if ($num > 0)
01481 {
01482 $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
01483 return $row["question_id"];
01484 }
01485 else
01486 {
01487 return FALSE;
01488 }
01489 }
01490
01498 function getNrOfResultsForPass($active_id, $pass)
01499 {
01500 global $ilDB;
01501
01502 $query = sprintf("SELECT test_result_id FROM tst_test_result WHERE active_fi = %s AND pass = %s",
01503 $ilDB->quote($active_id . ""),
01504 $ilDB->quote($pass . "")
01505 );
01506 $result = $ilDB->query($query);
01507 return $result->numRows();
01508 }
01509
01518 function generateRandomQuestions($pass = NULL)
01519 {
01520 global $ilUser;
01521 $active = $this->getActiveTestUser($ilUser->getId());
01522 $active_id = 0;
01523 if (is_object($active))
01524 {
01525 $active_id = $active->active_id;
01526 $this->loadQuestions($active_id, $pass);
01527 if (count($this->questions) > 0)
01528 {
01529
01530
01531 return;
01532 }
01533 if ($pass > 0)
01534 {
01535 if ($this->getNrOfResultsForPass($active_id, $pass - 1) == 0)
01536 {
01537
01538
01539
01540 return;
01541 }
01542 }
01543 }
01544 else
01545 {
01546 $active_id = $this->setActiveTestUser();
01547 }
01548 if ($active_id == 0)
01549 {
01550
01551 global $ilias, $ilErr;
01552 $ilias->raiseError(sprintf($this->lng->txt("error_random_question_generation"), $ilUser->getId(), $this->getTestId()), $ilErr->FATAL);
01553 }
01554 $num = $this->getRandomQuestionCount();
01555 if ($num > 0)
01556 {
01557 $qpls =& $this->getRandomQuestionpools();
01558 $rndquestions = $this->randomSelectQuestions($num, 0, 1, $qpls, $pass);
01559 $allquestions = array();
01560 foreach ($rndquestions as $question_id)
01561 {
01562 array_push($allquestions, $question_id);
01563 }
01564 srand ((float)microtime()*1000000);
01565 shuffle($allquestions);
01566
01567 $maxcount = 0;
01568 foreach ($qpls as $data)
01569 {
01570 $maxcount += $data["contains"];
01571 }
01572 if ($num > $maxcount) $num = $maxcount;
01573 foreach ($allquestions as $question_id)
01574 {
01575 $this->saveRandomQuestion($active_id, $question_id, $pass, $num);
01576 }
01577 }
01578 else
01579 {
01580 $qpls =& $this->getRandomQuestionpools();
01581 $allquestions = array();
01582 $maxcount = 0;
01583 foreach ($qpls as $key => $value)
01584 {
01585 if ($value["count"] > 0)
01586 {
01587 $rndquestions = $this->randomSelectQuestions($value["count"], $value["qpl"], 1, $pass);
01588 foreach ($rndquestions as $question_id)
01589 {
01590 array_push($allquestions, $question_id);
01591 }
01592 }
01593 $add = ($value["count"] <= $value["contains"]) ? $value["count"] : $value["contains"];
01594 $maxcount += $add;
01595 }
01596 srand ((float)microtime()*1000000);
01597 shuffle($allquestions);
01598 foreach ($allquestions as $question_id)
01599 {
01600 $this->saveRandomQuestion($active_id, $question_id, $pass, $maxcount);
01601 }
01602 }
01603 if (!is_object($active))
01604 {
01605 $active = $this->getActiveTestUser($ilUser->getId());
01606 }
01607 if (strlen($active->sequence) == 0)
01608 {
01609 $this->addQuestionSequence($active->active_id);
01610 }
01611 return;
01612 }
01613
01622 function saveRandomQuestionCount($total_questions = "NULL")
01623 {
01624 global $ilDB;
01625
01626 if (strcmp($total_questions, "NULL") != 0)
01627 {
01628 $this->setRandomQuestionCount($total_questions);
01629 $total_questions = $ilDB->quote($total_questions);
01630 }
01631 $query = sprintf("UPDATE tst_tests SET random_question_count = %s WHERE test_id = %s",
01632 $total_questions,
01633 $ilDB->quote($this->getTestId() . "")
01634 );
01635 $result = $ilDB->query($query);
01636 include_once ("./classes/class.ilObjAssessmentFolder.php");
01637 if (ilObjAssessmentFolder::_enabledAssessmentLogging())
01638 {
01639 if (strcmp($total_questions, "NULL") == 0) $total_questions = '0';
01640 $this->logAction(sprintf($this->lng->txtlng("assessment", "log_total_amount_of_questions", ilObjAssessmentFolder::_getLogLanguage()), $total_questions));
01641 }
01642 }
01643
01653 function saveRandomQuestionpools($qpl_array)
01654 {
01655 global $ilDB;
01656
01657 include_once ("./classes/class.ilObjAssessmentFolder.php");
01658
01659 $query = sprintf("DELETE FROM tst_test_random WHERE test_fi = %s",
01660 $ilDB->quote($this->getTestId())
01661 );
01662 $result = $ilDB->query($query);
01663 if (ilObjAssessmentFolder::_enabledAssessmentLogging())
01664 {
01665 $this->logAction($this->lng->txtlng("assessment", "log_random_question_pool_deleted", ilObjAssessmentFolder::_getLogLanguage()));
01666 }
01667
01668 foreach ($qpl_array as $key => $value) {
01669 if ($value["qpl"] > -1)
01670 {
01671 include_once "./assessment/classes/class.ilObjQuestionPool.php";
01672 $count = ilObjQuestionPool::_getQuestionCount($value["qpl"]);
01673 if ($value["count"] > $count)
01674 {
01675 $value["count"] = $count;
01676 }
01677 $query = sprintf("INSERT INTO tst_test_random (test_random_id, test_fi, questionpool_fi, num_of_q, TIMESTAMP) VALUES (NULL, %s, %s, %s, NULL)",
01678 $ilDB->quote($this->getTestId() . ""),
01679 $ilDB->quote($value["qpl"] . ""),
01680 $ilDB->quote(sprintf("%d", $value["count"]) . "")
01681 );
01682 $result = $ilDB->query($query);
01683 if (ilObjAssessmentFolder::_enabledAssessmentLogging())
01684 {
01685 $this->logAction(sprintf($this->lng->txtlng("assessment", "log_random_question_pool_added", ilObjAssessmentFolder::_getLogLanguage()), $value["title"] . " (" . $value["qpl"] . ")", $value["count"]));
01686 }
01687 }
01688 }
01689 }
01690
01700 function &getRandomQuestionpools()
01701 {
01702 global $ilDB;
01703
01704 $qpls = array();
01705 $counter = 0;
01706 if ($ilDB->tableColumnExists("qpl_questionpool", "questioncount"))
01707 {
01708 $query = sprintf("SELECT tst_test_random.*, qpl_questionpool.questioncount FROM tst_test_random, qpl_questionpool WHERE tst_test_random.test_fi = %s AND tst_test_random.questionpool_fi = qpl_questionpool.obj_fi ORDER BY test_random_id",
01709 $ilDB->quote($this->getTestId() . "")
01710 );
01711 $result = $ilDB->query($query);
01712 if ($result->numRows())
01713 {
01714 while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC))
01715 {
01716 $qpls[$counter] = array(
01717 "index" => $counter,
01718 "count" => $row["num_of_q"],
01719 "qpl" => $row["questionpool_fi"],
01720 "contains" => $row["questioncount"]
01721 );
01722 $counter++;
01723 }
01724 }
01725 }
01726 else
01727 {
01728 $query = sprintf("SELECT * FROM tst_test_random WHERE test_fi = %s ORDER BY test_random_id",
01729 $ilDB->quote($this->getTestId() . "")
01730 );
01731 $result = $ilDB->query($query);
01732 if ($result->numRows())
01733 {
01734 while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC))
01735 {
01736 $countquery = sprintf("SELECT question_id FROM qpl_questions WHERE obj_fi = %s AND original_id IS NULL",
01737 $ilDB->quote($row["questionpool_fi"] . "")
01738 );
01739 $countresult = $ilDB->query($countquery);
01740 $contains = $countresult->numRows();
01741 $qpls[$counter] = array(
01742 "index" => $counter,
01743 "count" => $row["num_of_q"],
01744 "qpl" => $row["questionpool_fi"],
01745 "contains" => $contains
01746 );
01747 $counter++;
01748 }
01749 }
01750 }
01751 return $qpls;
01752 }
01753
01763 function loadFromDb()
01764 {
01765 global $ilDB;
01766
01767 $query = sprintf("SELECT * FROM tst_tests WHERE obj_fi = %s",
01768 $ilDB->quote($this->getId())
01769 );
01770 $result = $ilDB->query($query);
01771 if (strcmp(strtolower(get_class($result)), db_result) == 0)
01772 {
01773 if ($result->numRows() == 1)
01774 {
01775 $data = $result->fetchRow(DB_FETCHMODE_OBJECT);
01776 $this->test_id = $data->test_id;
01777 $this->author = $data->author;
01778 $this->test_type = $data->test_type_fi;
01779 include_once("./Services/RTE/classes/class.ilRTE.php");
01780 $this->introduction = ilRTE::_replaceMediaObjectImageSrc($data->introduction, 1);
01781 $this->sequence_settings = $data->sequence_settings;
01782 $this->score_reporting = $data->score_reporting;
01783 $this->instant_verification = $data->instant_verification;
01784 $this->nr_of_tries = $data->nr_of_tries;
01785 $this->setHidePreviousResults($data->hide_previous_results);
01786 $this->setHideTitlePoints($data->hide_title_points);
01787 $this->processing_time = $data->processing_time;
01788 $this->enable_processing_time = $data->enable_processing_time;
01789 $this->reporting_date = $data->reporting_date;
01790 $this->setShuffleQuestions($data->shuffle_questions);
01791 $this->setShowSolutionDetails($data->show_solution_details);
01792 $this->setShowSummary($data->show_summary);
01793 $this->setShowSolutionPrintview($data->show_solution_printview);
01794 $this->starting_time = $data->starting_time;
01795 $this->ending_time = $data->ending_time;
01796 $this->ects_output = $data->ects_output;
01797 $this->ects_grades = array(
01798 "A" => $data->ects_a,
01799 "B" => $data->ects_b,
01800 "C" => $data->ects_c,
01801 "D" => $data->ects_d,
01802 "E" => $data->ects_e
01803 );
01804 $this->ects_fx = $data->ects_fx;
01805 $this->random_test = $data->random_test;
01806 $this->random_question_count = $data->random_question_count;
01807 $this->mark_schema->flush();
01808 $this->mark_schema->loadFromDb($this->test_id);
01809 $this->count_system = $data->count_system;
01810 $this->mc_scoring = $data->mc_scoring;
01811 $this->setScoreCutting($data->score_cutting);
01812 $this->setPassword($data->password);
01813 $this->setAllowedUsers($data->allowedUsers);
01814 $this->setAllowedUsersTimeGap($data->allowedUsersTimeGap);
01815 $this->setPassScoring($data->pass_scoring);
01816 $this->loadQuestions();
01817 }
01818 }
01819 }
01820
01829 function loadQuestions($active_id = "", $pass = NULL)
01830 {
01831 global $ilUser;
01832 global $ilDB;
01833
01834 $this->questions = array();
01835 if (strcmp($active_id, "") == 0)
01836 {
01837 $active = $this->getActiveTestUser($ilUser->getId());
01838 $active_id = $active->active_id;
01839 }
01840 if ($this->isRandomTest())
01841 {
01842 if (is_null($pass))
01843 {
01844 if ($this->getTestType() == TYPE_VARYING_RANDOMTEST)
01845 {
01846 $pass = $this->_getPass($active_id);
01847 }
01848 else
01849 {
01850
01851 $pass = 0;
01852 }
01853 }
01854 $query = sprintf("SELECT tst_test_random_question.* FROM tst_test_random_question, qpl_questions WHERE tst_test_random_question.active_fi = %s AND qpl_questions.question_id = tst_test_random_question.question_fi AND tst_test_random_question.pass = %s ORDER BY sequence",
01855 $ilDB->quote($active_id . ""),
01856 $ilDB->quote($pass . "")
01857 );
01858 }
01859 else
01860 {
01861 $query = sprintf("SELECT tst_test_question.* FROM tst_test_question, qpl_questions WHERE tst_test_question.test_fi = %s AND qpl_questions.question_id = tst_test_question.question_fi ORDER BY sequence",
01862 $ilDB->quote($this->test_id . "")
01863 );
01864 }
01865 $result = $ilDB->query($query);
01866 $index = 1;
01867 while ($data = $result->fetchRow(DB_FETCHMODE_OBJECT))
01868 {
01869 $this->questions[$index++] = $data->question_fi;
01870 }
01871 }
01872
01886 function &getQuestions($active_id = "", $pass = NULL, $userorder = FALSE)
01887 {
01888 if ($active_id > 0)
01889 {
01890 if ($this->isRandomTest())
01891 {
01892 $this->loadQuestions($active_id, $pass);
01893 }
01894 if ($userorder)
01895 {
01896 $result_array = array();
01897 $active =& $this->getActiveTestUserFromActiveId($active_id);
01898 $sequence_array = split(",", $active->sequence);
01899 $index = 1;
01900 foreach ($sequence_array as $sequence)
01901 {
01902 $result_array[$index] = $this->questions[$sequence];
01903 $index++;
01904 }
01905 return $result_array;
01906 }
01907 }
01908 return $this->questions;
01909 }
01910
01920 function setAuthor($author = "")
01921 {
01922 $this->author = $author;
01923 }
01924
01934 function setIntroduction($introduction = "")
01935 {
01936 $this->introduction = $introduction;
01937 }
01938
01948 function getAuthor()
01949 {
01950 return $this->author;
01951 }
01952
01962 function isRandomTest()
01963 {
01964 return $this->random_test;
01965 }
01966
01976 function getRandomQuestionCount()
01977 {
01978 return $this->random_question_count;
01979 }
01980
01990 function getIntroduction()
01991 {
01992 return $this->introduction;
01993 }
01994
02004 function getTestId()
02005 {
02006 return $this->test_id;
02007 }
02008
02018 function setSequenceSettings($sequence_settings = 0)
02019 {
02020 $this->sequence_settings = $sequence_settings;
02021 }
02022
02032 function setTestType($type = TYPE_ASSESSMENT)
02033 {
02034 $this->test_type = $type;
02035 }
02036
02046 function setScoreReporting($score_reporting = 0)
02047 {
02048 $this->score_reporting = $score_reporting;
02049 }
02050
02060 function setInstantVerification($instant_verification = 0)
02061 {
02062 switch ($instant_verification)
02063 {
02064 case 1:
02065 $this->instant_verification = 1;
02066 break;
02067 default:
02068 $this->instant_verification = 0;
02069 break;
02070 }
02071 }
02072
02082 function setRandomTest($a_random_test = 0)
02083 {
02084 $this->random_test = $a_random_test;
02085 }
02086
02096 function setRandomQuestionCount($a_random_question_count = "")
02097 {
02098 $this->random_question_count = $a_random_question_count;
02099 }
02100
02110 function setReportingDate($reporting_date)
02111 {
02112 if (!$reporting_date)
02113 {
02114 $this->reporting_date = "";
02115 $this->ects_output = 0;
02116 }
02117 else
02118 {
02119 $this->reporting_date = $reporting_date;
02120 }
02121 }
02122
02132 function getSequenceSettings()
02133 {
02134 return $this->sequence_settings;
02135 }
02136
02146 function getScoreReporting()
02147 {
02148 return $this->score_reporting;
02149 }
02150
02160 function getInstantVerification()
02161 {
02162 return $this->instant_verification;
02163 }
02164
02174 function getCountSystem()
02175 {
02176 return $this->count_system;
02177 }
02178
02188 function _getCountSystem($active_id)
02189 {
02190 global $ilDB;
02191 $query = sprintf("SELECT tst_tests.count_system FROM tst_tests, tst_active WHERE tst_active.active_id = %s AND tst_active.test_fi = tst_tests.test_id",
02192 $ilDB->quote($active_id)
02193 );
02194 $result = $ilDB->query($query);
02195 if ($result->numRows())
02196 {
02197 $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
02198 return $row["count_system"];
02199 }
02200 return FALSE;
02201 }
02202
02212 function getMCScoring()
02213 {
02214 return $this->mc_scoring;
02215 }
02216
02226 function getScoreCutting()
02227 {
02228 return $this->score_cutting;
02229 }
02230
02240 function getPassword()
02241 {
02242 return $this->password;
02243 }
02244
02254 function getPassScoring()
02255 {
02256 return $this->pass_scoring;
02257 }
02258
02268 function _getPassScoring($active_id)
02269 {
02270 global $ilDB;
02271 $query = sprintf("SELECT tst_tests.pass_scoring FROM tst_tests, tst_active WHERE tst_tests.test_id = tst_active.test_fi AND tst_active.active_id = %s",
02272 $ilDB->quote($active_id . "")
02273 );
02274 $result = $ilDB->query($query);
02275 if ($result->numRows())
02276 {
02277 $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
02278 return $row["pass_scoring"];
02279 }
02280 return 0;
02281 }
02282
02292 function _getMCScoring($active_id)
02293 {
02294 global $ilDB;
02295 $query = sprintf("SELECT tst_tests.mc_scoring FROM tst_tests, tst_active WHERE tst_active.active_id = %s AND tst_active.test_fi = tst_tests.test_id",
02296 $ilDB->quote($active_id)
02297 );
02298 $result = $ilDB->query($query);
02299 if ($result->numRows())
02300 {
02301 $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
02302 return $row["mc_scoring"];
02303 }
02304 return FALSE;
02305 }
02306
02316 function _getScoreCutting($active_id)
02317 {
02318 global $ilDB;
02319 $query = sprintf("SELECT tst_tests.score_cutting FROM tst_tests, tst_active WHERE tst_active.active_id = %s AND tst_tests.test_id = tst_active.test_fi",
02320 $ilDB->quote($active_id)
02321 );
02322 $result = $ilDB->query($query);
02323 if ($result->numRows())
02324 {
02325 $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
02326 return $row["score_cutting"];
02327 }
02328 return FALSE;
02329 }
02330
02340 function getTestType()
02341 {
02342 return $this->test_type;
02343 }
02344
02353 function _lookupTestType($a_obj_id)
02354 {
02355 global $ilDB;
02356
02357 $query = "SELECT test_type_fi FROM tst_tests ".
02358 "WHERE obj_fi = '".$a_obj_id."'";
02359 $res = $ilDB->query($query);
02360 while($row = $res->fetchRow(DB_FETCHMODE_ASSOC))
02361 {
02362 return $row['test_type_fi'];
02363 }
02364 return 0;
02365 }
02366
02375 function _lookupTestIdForQuestion($a_question_id)
02376 {
02377 global $ilDB;
02378
02379 $query = sprintf("SELECT tst_tests.obj_fi FROM tst_tests, tst_test_question WHERE tst_test_question.test_fi = tst_tests.test_id AND tst_test_question.question_fi = %s",
02380 $ilDB->quote($a_question_id)
02381 );
02382 $res = $ilDB->query($query);
02383
02384 while($row = $res->fetchRow(DB_FETCHMODE_ASSOC))
02385 {
02386 return $row['obj_fi'];
02387 }
02388 return 0;
02389 }
02390
02400 function _lookupAuthor($obj_id)
02401 {
02402 global $ilDB;
02403 $query = sprintf("SELECT author FROM tst_tests WHERE obj_fi = %s",
02404 $ilDB->quote($obj_id . "")
02405 );
02406 $result = $ilDB->query($query);
02407 if ($result->numRows())
02408 {
02409 $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
02410 return $row["author"];
02411 }
02412 return "";
02413 }
02414
02415
02425 function getReportingDate()
02426 {
02427 return $this->reporting_date;
02428 }
02429
02439 function getNrOfTries()
02440 {
02441 return $this->nr_of_tries;
02442 }
02443
02453 function getHidePreviousResults()
02454 {
02455 return $this->hide_previous_results;
02456 }
02457
02467 function getHideTitlePoints()
02468 {
02469 return $this->hide_title_points;
02470 }
02471
02482 function _getHideTitlePoints($active_id)
02483 {
02484 global $ilDB;
02485
02486 $query = sprintf("SELECT tst_tests.hide_title_points FROM tst_tests, tst_active WHERE tst_tests.test_id = tst_active.test_fi AND tst_active.active_id = %s",
02487 $ilDB->quote($active_id . "")
02488 );
02489 $result = $ilDB->query($query);
02490 if ($result->numRows())
02491 {
02492 $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
02493 return $row["hide_title_points"];
02494 }
02495 return 0;
02496 }
02497
02509 function _getHidePreviousResults($active_id, $user_active_user_setting = false)
02510 {
02511 global $ilDB;
02512 global $ilUser;
02513
02514 $user_hide_previous_results = 0;
02515 if ($user_active_user_setting)
02516 {
02517 if (array_key_exists("tst_hide_previous_results", $ilUser->prefs))
02518 {
02519 $user_hide_previous_results = $ilUser->prefs["tst_hide_previous_results"];
02520 }
02521 }
02522 $query = sprintf("SELECT tst_tests.hide_previous_results FROM tst_tests, tst_active WHERE tst_tests.test_id = tst_active.test_fi AND tst_active.active_id = %s",
02523 $ilDB->quote($active_id . "")
02524 );
02525 $result = $ilDB->query($query);
02526 if ($result->numRows())
02527 {
02528 $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
02529 if ($row["hide_previous_results"] != 1)
02530 {
02531 return $row["hide_previous_results"] | $user_hide_previous_results;
02532 }
02533 else
02534 {
02535 return $row["hide_previous_results"];
02536 }
02537 }
02538 return 0;
02539 }
02540
02550 function getProcessingTime()
02551 {
02552 return $this->processing_time;
02553 }
02554
02564 function getProcessingTimeInSeconds()
02565 {
02566 if (preg_match("/(\d{2}):(\d{2}):(\d{2})/", $this->getProcessingTime(), $matches))
02567 {
02568 return ($matches[1] * 3600) + ($matches[2] * 60) + $matches[3];
02569 }
02570 else
02571 {
02572 return 0;
02573 }
02574 }
02575
02585 function getSecondsUntilEndingTime()
02586 {
02587 if (preg_match("/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/", $this->getEndingTime(), $matches))
02588 {
02589 $ending = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
02590 $now = time();
02591 return $ending - $now;
02592 }
02593 else
02594 {
02595 return 0;
02596 }
02597 }
02598
02608 function getEnableProcessingTime()
02609 {
02610 return $this->enable_processing_time;
02611 }
02612
02622 function getStartingTime()
02623 {
02624 return $this->starting_time;
02625 }
02626
02636 function getEndingTime()
02637 {
02638 return $this->ending_time;
02639 }
02640
02650 function setNrOfTries($nr_of_tries = 0)
02651 {
02652 $this->nr_of_tries = $nr_of_tries;
02653 }
02654
02664 function setHidePreviousResults($hide_previous_results = 0)
02665 {
02666 if ($hide_previous_results)
02667 {
02668 $this->hide_previous_results = 1;
02669 }
02670 else
02671 {
02672 $this->hide_previous_results = 0;
02673 }
02674 }
02675
02685 function setHideTitlePoints($hide_title_points = 0)
02686 {
02687 if ($hide_title_points)
02688 {
02689 $this->hide_title_points = 1;
02690 }
02691 else
02692 {
02693 $this->hide_title_points = 0;
02694 }
02695 }
02696
02706 function setProcessingTime($processing_time = "00:00:00")
02707 {
02708 $this->processing_time = $processing_time;
02709 }
02710
02720 function setEnableProcessingTime($enable = 0)
02721 {
02722 if ($enable) {
02723 $this->enable_processing_time = "1";
02724 } else {
02725 $this->enable_processing_time = "0";
02726 }
02727 }
02728
02738 function setStartingTime($starting_time = "")
02739 {
02740 $this->starting_time = $starting_time;
02741 }
02742
02752 function setEndingTime($ending_time = "")
02753 {
02754 $this->ending_time = $ending_time;
02755 }
02756
02766 function setCountSystem($a_count_system = COUNT_PARTIAL_SOLUTIONS)
02767 {
02768 $this->count_system = $a_count_system;
02769 }
02770
02780 function setPassword($a_password = "")
02781 {
02782 $this->password = $a_password;
02783 }
02784
02794 function setScoreCutting($a_score_cutting = SCORE_CUT_QUESTION)
02795 {
02796 $this->score_cutting = $a_score_cutting;
02797 }
02798
02808 function setMCScoring($a_mc_scoring = SCORE_ZERO_POINTS_WHEN_UNANSWERED)
02809 {
02810 $this->mc_scoring = $a_mc_scoring;
02811 }
02812
02822 function setPassScoring($a_pass_scoring = SCORE_LAST_PASS)
02823 {
02824 switch ($a_pass_scoring)
02825 {
02826 case SCORE_BEST_PASS:
02827 $this->pass_scoring = SCORE_BEST_PASS;
02828 break;
02829 default:
02830 $this->pass_scoring = SCORE_LAST_PASS;
02831 break;
02832 }
02833 }
02834
02844 function removeQuestion($question_id)
02845 {
02846 $question =& ilObjTest::_instanciateQuestion($question_id);
02847 include_once ("./classes/class.ilObjAssessmentFolder.php");
02848 if (ilObjAssessmentFolder::_enabledAssessmentLogging())
02849 {
02850 $this->logAction($this->lng->txtlng("assessment", "log_question_removed", ilObjAssessmentFolder::_getLogLanguage()), $question_id);
02851 }
02852 $question->delete($question_id);
02853 $this->removeAllTestEditings($question_id);
02854 $this->loadQuestions();
02855 $this->saveQuestionsToDb();
02856 }
02857
02865 function clearEvalSelectedUsers()
02866 {
02867 global $ilDB;
02868
02869 $query = sprintf("DELETE FROM tst_eval_users WHERE test_fi = %s",
02870 $ilDB->quote($this->getTestId())
02871 );
02872 $result = $ilDB->query($query);
02873 }
02874
02886 function removeAllTestEditings($question_id = "")
02887 {
02888 global $ilDB;
02889
02890 $this->deleteActiveTests();
02891
02892 $this->clearEvalSelectedUsers();
02893
02894
02895 if ($question_id)
02896 {
02897 $query = sprintf("DELETE FROM tst_solutions USING tst_solutions, tst_active where tst_solutions.active_fi = tst_active.active_id AND tst_active.test_fi = %s AND tst_solutions.question_fi = %s",
02898 $ilDB->quote($this->getTestId()),
02899 $ilDB->quote($question_id)
02900 );
02901 $query2 = sprintf("DELETE FROM tst_active_qst_sol_settings USING tst_active_qst_sol_settings, tst_active where tst_active_qst_sol_settings.active_fi = tst_active.active_id AND tst_active.test_fi = %s AND tst_active_qst_sol_settings.question_fi = %s",
02902 $ilDB->quote($this->getTestId()),
02903 $ilDB->quote($question_id)
02904 );
02905 $query3 = sprintf("DELETE FROM tst_test_result USING tst_test_result, tst_active WHERE tst_active.test_fi = %s AND tst_test_result.question_fi = %s AND tst_active.active_id = tst_test_result.active_fi",
02906 $ilDB->quote($this->getTestId()),
02907 $ilDB->quote($question_id)
02908 );
02909 } else {
02910 $query = sprintf("DELETE FROM tst_solutions USING tst_solutions, tst_active where tst_solutions.active_fi = tst_active.active_id AND tst_active.test_fi = %s",
02911 $ilDB->quote($this->getTestId())
02912 );
02913 $query2 = sprintf("DELETE FROM tst_active_qst_sol_settings USING tst_active_qst_sol_settings, tst_active where tst_active_qst_sol_settings.active_fi = tst_active.active_id AND tst_active.test_fi = %s",
02914 $ilDB->quote($this->getTestId())
02915 );
02916 $query3 = sprintf("DELETE FROM tst_test_result USING tst_test_result, tst_active WHERE tst_active.test_fi = %s AND tst_active.active_id = tst_test_result.active_fi",
02917 $ilDB->quote($this->getTestId())
02918 );
02919 }
02920 $result = $ilDB->query($query);
02921 $result = $ilDB->query($query2);
02922 $result = $ilDB->query($query3);
02923
02924 if ($this->isRandomTest())
02925 {
02926 $query = sprintf("DELETE FROM tst_test_random_question USING tst_test_random_question, tst_active WHERE tst_active.test_fi = %s AND tst_test_random_question.active_fi = tst_active.active_id",
02927 $ilDB->quote($this->getTestId())
02928 );
02929 $result = $ilDB->query($query);
02930 }
02931 include_once ("./classes/class.ilObjAssessmentFolder.php");
02932 if (ilObjAssessmentFolder::_enabledAssessmentLogging())
02933 {
02934 $this->logAction($this->lng->txtlng("assessment", "log_user_data_removed", ilObjAssessmentFolder::_getLogLanguage()));
02935 }
02936 }
02937
02949 function removeSelectedTestResults($active_ids)
02950 {
02951 global $ilDB;
02952
02953
02954 $this->clearEvalSelectedUsers();
02955
02956
02957 foreach ($active_ids as $active_id)
02958 {
02959 $query = sprintf("DELETE FROM tst_solutions WHERE active_fi = %s",
02960 $ilDB->quote($active_id . "")
02961 );
02962 $query2 = sprintf("DELETE FROM tst_active_qst_sol_settings WHERE active_fi = %s",
02963 $ilDB->quote($active_id . "")
02964 );
02965 $query3 = sprintf("DELETE FROM tst_test_result WHERE active_fi = %s",
02966 $ilDB->quote($active_id . "")
02967 );
02968 $result = $ilDB->query($query);
02969 $result = $ilDB->query($query2);
02970 $result = $ilDB->query($query3);
02971
02972 if ($this->isRandomTest())
02973 {
02974 $query = sprintf("DELETE FROM tst_test_random_question WHERE active_fi = %s",
02975 $ilDB->quote($active_id . "")
02976 );
02977 $result = $ilDB->query($query);
02978 }
02979
02980 include_once ("./classes/class.ilObjAssessmentFolder.php");
02981 if (ilObjAssessmentFolder::_enabledAssessmentLogging())
02982 {
02983 include_once ("./classes/class.ilObjUser.php");
02984 $uname = ilObjUser::_lookupName($this->_getUserIdFromActiveId($active_id));
02985 $this->logAction(sprintf($this->lng->txtlng("assessment", "log_selected_user_data_removed", ilObjAssessmentFolder::_getLogLanguage()), trim($uname["title"] . " " . $uname["firstname"] . " " . $uname["lastname"] . " (" . $uname["user_id"] . ")")));
02986 }
02987 }
02988
02989
02990 foreach ($active_ids as $active_id)
02991 {
02992 $query = sprintf("DELETE FROM tst_active WHERE active_id = %s",
02993 $ilDB->quote($active_id . "")
02994 );
02995 $result = $ilDB->query($query);
02996 }
02997 }
02998
03010 function removeTestResultsForUser($user_id)
03011 {
03012 global $ilDB;
03013
03014 $active = $this->getActiveTestUser($user_id);
03015 $active_id = $active->active_id;
03016
03017
03018 $query = sprintf("DELETE FROM tst_solutions WHERE active_fi = %s",
03019 $ilDB->quote($active_id . "")
03020 );
03021 $query2 = sprintf("DELETE FROM tst_active_qst_sol_settings WHERE active_fi = %s",
03022 $ilDB->quote($active_id . "")
03023 );
03024 $query3 = sprintf("DELETE FROM tst_test_result WHERE active_fi = %s",
03025 $ilDB->quote($active_id . "")
03026 );
03027 $result = $ilDB->query($query);
03028 $result = $ilDB->query($query2);
03029 $result = $ilDB->query($query3);
03030
03031 if ($this->isRandomTest())
03032 {
03033 $query = sprintf("DELETE FROM tst_test_random_question WHERE active_fi = %s",
03034 $ilDB->quote($active_id . "")
03035 );
03036 $result = $ilDB->query($query);
03037 }
03038
03039 include_once ("./classes/class.ilObjAssessmentFolder.php");
03040 if (ilObjAssessmentFolder::_enabledAssessmentLogging())
03041 {
03042 include_once ("./classes/class.ilObjUser.php");
03043 $uname = ilObjUser::_lookupName($this->_getUserIdFromActiveId($active_id));
03044 $this->logAction(sprintf($this->lng->txtlng("assessment", "log_selected_user_data_removed", ilObjAssessmentFolder::_getLogLanguage()), trim($uname["title"] . " " . $uname["firstname"] . " " . $uname["lastname"] . " (" . $uname["user_id"] . ")")));
03045 }
03046
03047
03048 $query = sprintf("DELETE FROM tst_active WHERE active_id = %s",
03049 $ilDB->quote($active_id . "")
03050 );
03051 $result = $ilDB->query($query);
03052 }
03053
03062 function deleteActiveTests()
03063 {
03064 global $ilDB;
03065
03066 $query = sprintf("DELETE FROM tst_active WHERE test_fi = %s",
03067 $ilDB->quote($this->getTestId())
03068 );
03069 $result = $ilDB->query($query);
03070 }
03071
03082 function deleteResults($user_id = "")
03083 {
03084 global $ilDB;
03085
03086 if ($user_id)
03087 {
03088 $active = $this->getActiveTestUser($user_id);
03089 $pass = $this->_getPass($active->active_id);
03090 $query = sprintf("DELETE FROM tst_solutions USING tst_solutions, tst_active where tst_solutions.active_fi = tst_active.active_id AND tst_active.test_fi = %s AND tst_active.user_fi = %s AND tst_solutions.pass = %s",
03091 $ilDB->quote($this->getTestId() . ""),
03092 $ilDB->quote($user_id . ""),
03093 $ilDB->quote($pass . "")
03094 );
03095 $result = $ilDB->query($query);
03096 $query = sprintf("DELETE FROM tst_test_result WHERE active_fi = %s AND pass = %s",
03097 $ilDB->quote($active->active_id . ""),
03098 $ilDB->quote($pass . "")
03099 );
03100 $result = $ilDB->query($query);
03101 $sequence_arr = array_flip($this->questions);
03102 $sequence = join($sequence_arr, ",");
03103 $query = sprintf("UPDATE tst_active SET sequence = %s, lastindex = %s WHERE test_fi = %s and user_fi = %s",
03104 $ilDB->quote($sequence),
03105 $ilDB->quote("1"),
03106 $ilDB->quote($this->getTestId()),
03107 $ilDB->quote($user_id)
03108 );
03109 $result = $ilDB->query($query);
03110
03111 $query = sprintf("DELETE FROM tst_active_qst_sol_settings USING tst_active_qst_sol_settings, tst_active where tst_active_qst_sol_settings.active_fi = tst_active.active_id AND tst_active.test_fi = %s AND tst_active.user_fi = %s",
03112 $ilDB->quote($this->getTestId()),
03113 $ilDB->quote($user_id)
03114 );
03115 $result = $ilDB->query($query);
03116 }
03117 }
03118
03128 function questionMoveUp($question_id)
03129 {
03130 global $ilDB;
03131
03132
03133 $query = sprintf("SELECT * FROM tst_test_question WHERE test_fi=%s AND question_fi=%s",
03134 $ilDB->quote($this->getTestId()),
03135 $ilDB->quote($question_id)
03136 );
03137 $result = $ilDB->query($query);
03138 $data = $result->fetchRow(DB_FETCHMODE_OBJECT);
03139 if ($data->sequence > 1) {
03140
03141 $query = sprintf("SELECT * FROM tst_test_question WHERE test_fi=%s AND sequence=%s",
03142 $ilDB->quote($this->getTestId()),
03143 $ilDB->quote($data->sequence - 1)
03144 );
03145 $result = $ilDB->query($query);
03146 $data_previous = $result->fetchRow(DB_FETCHMODE_OBJECT);
03147
03148 $query = sprintf("UPDATE tst_test_question SET sequence=%s WHERE test_question_id=%s",
03149 $ilDB->quote($data->sequence),
03150 $ilDB->quote($data_previous->test_question_id)
03151 );
03152 $result = $ilDB->query($query);
03153
03154 $query = sprintf("UPDATE tst_test_question SET sequence=%s WHERE test_question_id=%s",
03155 $ilDB->quote($data->sequence - 1),
03156 $ilDB->quote($data->test_question_id)
03157 );
03158 $result = $ilDB->query($query);
03159 include_once ("./classes/class.ilObjAssessmentFolder.php");
03160 if (ilObjAssessmentFolder::_enabledAssessmentLogging())
03161 {
03162 $this->logAction($this->lng->txtlng("assessment", "log_question_position_changed", ilObjAssessmentFolder::_getLogLanguage()) . ": " . ($data->sequence) . " => " . ($data->sequence-1), $question_id);
03163 }
03164 }
03165 $this->loadQuestions();
03166 }
03167
03177 function questionMoveDown($question_id)
03178 {
03179 global $ilDB;
03180
03181
03182 $query = sprintf("SELECT * FROM tst_test_question WHERE test_fi=%s AND question_fi=%s",
03183 $ilDB->quote($this->getTestId()),
03184 $ilDB->quote($question_id)
03185 );
03186 $result = $ilDB->query($query);
03187 $data = $result->fetchRow(DB_FETCHMODE_OBJECT);
03188 $query = sprintf("SELECT * FROM tst_test_question WHERE test_fi=%s AND sequence=%s",
03189 $ilDB->quote($this->getTestId()),
03190 $ilDB->quote($data->sequence + 1)
03191 );
03192 $result = $ilDB->query($query);
03193 if ($result->numRows() == 1)
03194 {
03195
03196 $data_next = $result->fetchRow(DB_FETCHMODE_OBJECT);
03197
03198 $query = sprintf("UPDATE tst_test_question SET sequence=%s WHERE test_question_id=%s",
03199 $ilDB->quote($data->sequence),
03200 $ilDB->quote($data_next->test_question_id)
03201 );
03202 $result = $ilDB->query($query);
03203
03204 $query = sprintf("UPDATE tst_test_question SET sequence=%s WHERE test_question_id=%s",
03205 $ilDB->quote($data->sequence + 1),
03206 $ilDB->quote($data->test_question_id)
03207 );
03208 $result = $ilDB->query($query);
03209 include_once ("./classes/class.ilObjAssessmentFolder.php");
03210 if (ilObjAssessmentFolder::_enabledAssessmentLogging())
03211 {
03212 $this->logAction($this->lng->txtlng("assessment", "log_question_position_changed", ilObjAssessmentFolder::_getLogLanguage()) . ": " . ($data->sequence) . " => " . ($data->sequence+1), $question_id);
03213 }
03214 }
03215 $this->loadQuestions();
03216 }
03217
03227 function duplicateQuestionForTest($question_id)
03228 {
03229 global $ilUser;
03230 $question =& ilObjTest::_instanciateQuestion($question_id);
03231 $duplicate_id = $question->duplicate(true);
03232
03233 return $duplicate_id;
03234 }
03235
03244 function insertQuestion($question_id)
03245 {
03246 global $ilDB;
03247
03248 $duplicate_id = $this->duplicateQuestionForTest($question_id);
03249
03250
03251 $query = sprintf("SELECT MAX(sequence) AS seq FROM tst_test_question WHERE test_fi=%s",
03252 $ilDB->quote($this->getTestId())
03253 );
03254 $result = $ilDB->query($query);
03255 $sequence = 1;
03256
03257 if ($result->numRows() == 1)
03258 {
03259 $data = $result->fetchRow(DB_FETCHMODE_OBJECT);
03260 $sequence = $data->seq + 1;
03261 }
03262
03263 $query = sprintf("INSERT INTO tst_test_question (test_question_id, test_fi, question_fi, sequence, TIMESTAMP) VALUES (NULL, %s, %s, %s, NULL)",
03264 $ilDB->quote($this->getTestId()),
03265 $ilDB->quote($duplicate_id),
03266 $ilDB->quote($sequence)
03267 );
03268 $result = $ilDB->query($query);
03269 if ($result != DB_OK)
03270 {
03271
03272 }
03273 else
03274 {
03275 include_once ("./classes/class.ilObjAssessmentFolder.php");
03276 if (ilObjAssessmentFolder::_enabledAssessmentLogging())
03277 {
03278 $this->logAction($this->lng->txtlng("assessment", "log_question_added", ilObjAssessmentFolder::_getLogLanguage()) . ": " . $sequence, $duplicate_id);
03279 }
03280 }
03281
03282 $query = sprintf("DELETE FROM tst_active WHERE test_fi = %s",
03283 $ilDB->quote($this->getTestId())
03284 );
03285 $result = $ilDB->query($query);
03286 $this->loadQuestions();
03287 $this->saveCompleteStatus();
03288 }
03289
03299 function &getQuestionTitles()
03300 {
03301 $titles = array();
03302 if (!$this->isRandomTest())
03303 {
03304 global $ilDB;
03305 $query = sprintf("SELECT qpl_questions.title FROM tst_test_question, qpl_questions WHERE tst_test_question.test_fi = %s AND tst_test_question.question_fi = qpl_questions.question_id ORDER BY tst_test_question.sequence",
03306 $ilDB->quote($this->getTestId() . "")
03307 );
03308 $result = $ilDB->query($query);
03309 while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC))
03310 {
03311 array_push($titles, $row["title"]);
03312 }
03313 }
03314 return $titles;
03315 }
03316
03327 function getQuestionDataset($question_id)
03328 {
03329 global $ilDB;
03330
03331 $query = sprintf("SELECT qpl_questions.*, qpl_question_type.type_tag FROM qpl_questions, qpl_question_type WHERE qpl_questions.question_id = %s AND qpl_questions.question_type_fi = qpl_question_type.question_type_id",
03332 $ilDB->quote("$question_id")
03333 );
03334 $result = $ilDB->query($query);
03335 $row = $result->fetchRow(DB_FETCHMODE_OBJECT);
03336 return $row;
03337 }
03338
03347 function &get_qpl_titles()
03348 {
03349 global $rbacsystem;
03350 global $ilDB;
03351
03352 $qpl_titles = array();
03353
03354 $query = "SELECT object_data.*, object_data.obj_id, object_reference.ref_id FROM object_data, object_reference WHERE object_data.obj_id = object_reference.obj_id AND object_data.type = 'qpl' ORDER BY object_data.title";
03355 $result = $ilDB->query($query);
03356 while ($row = $result->fetchRow(DB_FETCHMODE_OBJECT))
03357 {
03358 if ($rbacsystem->checkAccess("write", $row->ref_id) && ($this->_hasUntrashedReference($row->obj_id)))
03359 {
03360 include_once("./assessment/classes/class.ilObjQuestionPool.php");
03361 if (ilObjQuestionPool::_lookupOnline($row->obj_id))
03362 {
03363 $qpl_titles["$row->obj_id"] = $row->title;
03364 }
03365 }
03366 }
03367 return $qpl_titles;
03368 }
03369
03378 function &getExistingQuestions($pass = NULL)
03379 {
03380 global $ilUser;
03381 global $ilDB;
03382
03383 $existing_questions = array();
03384 $active = $this->getActiveTestUser($ilUser->getId());
03385 if ($this->isRandomTest())
03386 {
03387 if (is_null($pass)) $pass = 0;
03388 $query = sprintf("SELECT qpl_questions.original_id FROM qpl_questions, tst_test_random_question WHERE tst_test_random_question.active_fi = %s AND tst_test_random_question.question_fi = qpl_questions.question_id AND tst_test_random_question.pass = %s",
03389 $ilDB->quote($active->active_id . ""),
03390 $ilDB->quote($pass . "")
03391 );
03392 }
03393 else
03394 {
03395 $query = sprintf("SELECT qpl_questions.original_id FROM qpl_questions, tst_test_question WHERE tst_test_question.test_fi = %s AND tst_test_question.question_fi = qpl_questions.question_id",
03396 $ilDB->quote($this->getTestId())
03397 );
03398 }
03399 $result = $ilDB->query($query);
03400 while ($data = $result->fetchRow(DB_FETCHMODE_OBJECT)) {
03401 array_push($existing_questions, $data->original_id);
03402 }
03403 return $existing_questions;
03404 }
03405
03415 function getQuestionType($question_id)
03416 {
03417 global $ilDB;
03418
03419 if ($question_id < 1)
03420 return -1;
03421 $query = sprintf("SELECT type_tag FROM qpl_questions, qpl_question_type WHERE qpl_questions.question_id = %s AND qpl_questions.question_type_fi = qpl_question_type.question_type_id",
03422 $ilDB->quote($question_id)
03423 );
03424 $result = $ilDB->query($query);
03425 if ($result->numRows() == 1) {
03426 $data = $result->fetchRow(DB_FETCHMODE_OBJECT);
03427 return $data->type_tag;
03428 } else {
03429 return "";
03430 }
03431 }
03432
03441 function startWorkingTime($user_id)
03442 {
03443 global $ilDB;
03444
03445 $result = "";
03446 if (!($result = $this->getActiveTestUser($user_id))) {
03447 $this->setActiveTestUser();
03448 $result = $this->getActiveTestUser($user_id);
03449 }
03450 $q = sprintf("INSERT INTO tst_times (times_id, active_fi, started, finished, TIMESTAMP) VALUES (NULL, %s, %s, %s, NULL)",
03451 $ilDB->quote($result->active_id),
03452 $ilDB->quote(strftime("%Y-%m-%d %H:%M:%S")),
03453 $ilDB->quote(strftime("%Y-%m-%d %H:%M:%S"))
03454 );
03455 $result = $ilDB->query($q);
03456 return $ilDB->getLastInsertId();
03457 }
03458
03467 function updateWorkingTime($times_id)
03468 {
03469 global $ilDB;
03470
03471 $q = sprintf("UPDATE tst_times SET finished = %s WHERE times_id = %s",
03472 $ilDB->quote(strftime("%Y-%m-%d %H:%M:%S")),
03473 $ilDB->quote($times_id)
03474 );
03475 $result = $ilDB->query($q);
03476 }
03477
03487 function getQuestionIdFromActiveUserSequence($sequence)
03488 {
03489 global $ilUser;
03490
03491 $active = $this->getActiveTestUser();
03492 $sequence_array = split(",", $active->sequence);
03493 return $this->questions[$sequence_array[$sequence-1]];
03494 }
03495
03504 function &getAllQuestionsForActiveUser()
03505 {
03506 $result_array = array();
03507 $active = $this->getActiveTestUser();
03508 $sequence_array = split(",", $active->sequence);
03509 $all_questions = &$this->getAllQuestions();
03510 $worked_questions = &$this->getWorkedQuestions($active->active_id);
03511 foreach ($sequence_array as $sequence)
03512 {
03513 if (in_array($this->questions[$sequence], $worked_questions))
03514 {
03515 $all_questions[$this->questions[$sequence]]["worked"] = 1;
03516 }
03517 else
03518 {
03519 $all_questions[$this->questions[$sequence]]["worked"] = 0;
03520 }
03521 array_push($result_array, $all_questions[$this->questions[$sequence]]);
03522 }
03523 return $result_array;
03524 }
03525
03526 function getFirstSequence()
03527 {
03528 global $ilUser;
03529
03530 $active = $this->getActiveTestUser($ilUser->getId());
03531 $results = $this->getTestResult($active->active_id);
03532
03533 for($i = 1; $i <= $this->getQuestionCount(); $i++)
03534 {
03535 $qid = $this->getQuestionIdFromActiveUserSequence($i);
03536
03537 foreach($results as $result)
03538 {
03539 if($qid == $result['qid'])
03540 {
03541 if(!$result['max'] or $result['max'] != $result['reached'])
03542 {
03543 return $i;
03544 }
03545 }
03546 }
03547 }
03548 return 0;
03549 }
03550
03551
03560 function &getWorkedQuestions($active_id, $pass = NULL)
03561 {
03562 global $ilUser;
03563 global $ilDB;
03564
03565 if (is_null($pass))
03566 {
03567 $query = sprintf("SELECT * FROM tst_solutions WHERE active_fi = %s AND pass = 0 GROUP BY question_fi",
03568 $ilDB->quote($active_id . "")
03569 );
03570 }
03571 else
03572 {
03573 $query = sprintf("SELECT * FROM tst_solutions WHERE active_fi = %s AND pass = %s GROUP BY question_fi",
03574 $ilDB->quote($active_id . ""),
03575 $ilDB->quote($pass . "")
03576 );
03577 }
03578 $result = $ilDB->query($query);
03579 $result_array = array();
03580 while ($row = $result->fetchRow(DB_FETCHMODE_OBJECT))
03581 {
03582 array_push($result_array, $row->question_fi);
03583 }
03584 return $result_array;
03585 }
03586
03597 function isTestFinishedToViewResults($active_id, $currentpass)
03598 {
03599 $num = $this->getPassFinishDate($active_id, $currentpass);
03600 if (($currentpass > 0) && ($num == 0))
03601 {
03602 return TRUE;
03603 }
03604 else
03605 {
03606 if (($currentpass > 0) && ($this->getTestType() != TYPE_VARYING_RANDOMTEST))
03607 {
03608 return TRUE;
03609 }
03610 else
03611 {
03612 return FALSE;
03613 }
03614 }
03615 }
03616
03617
03626 function &getAllQuestions($pass = NULL)
03627 {
03628 global $ilUser;
03629 global $ilDB;
03630
03631 if ($this->isRandomTest())
03632 {
03633 $active = $this->getActiveTestUser($ilUser->getId());
03634 $this->loadQuestions($active->active_id, $pass);
03635 $query = sprintf("SELECT qpl_questions.* FROM qpl_questions, tst_test_random_question WHERE tst_test_random_question.question_fi = qpl_questions.question_id AND tst_test_random_question.active_fi = %s AND tst_test_random_question.pass = %s AND qpl_questions.question_id IN (" . join($this->questions, ",") . ")",
03636 $ilDB->quote($active->active_id . ""),
03637 $ilDB->quote($pass . "")
03638 );
03639 }
03640 else
03641 {
03642 $query = "SELECT qpl_questions.* FROM qpl_questions, tst_test_question WHERE tst_test_question.question_fi = qpl_questions.question_id AND qpl_questions.question_id IN (" . join($this->questions, ",") . ")";
03643 }
03644 $result = $ilDB->query($query);
03645 $result_array = array();
03646 while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC))
03647 {
03648 $result_array[$row["question_id"]] = $row;
03649 }
03650 return $result_array;
03651 }
03652
03653 function &getActiveTestUserFromActiveId($active_id)
03654 {
03655 global $ilDB;
03656 $query = sprintf("SELECT * FROM tst_active WHERE active_id = %s",
03657 $ilDB->quote($active_id . "")
03658 );
03659 $result = $ilDB->query($query);
03660 $row = NULL;
03661 if ($result->numRows())
03662 {
03663 $row = $result->fetchRow(DB_FETCHMODE_OBJECT);
03664 }
03665 return $row;
03666 }
03667
03677 function getActiveTestUser($user_id = "", $anonymous_id = "")
03678 {
03679 global $ilDB;
03680 global $ilUser;
03681
03682 if (!$user_id)
03683 {
03684 $user_id = $ilUser->id;
03685 }
03686 if (($_SESSION["AccountId"] == ANONYMOUS_USER_ID) && (strlen($_SESSION["tst_access_code"][$this->getTestId()])))
03687 {
03688 $query = sprintf("SELECT * FROM tst_active WHERE user_fi = %s AND test_fi = %s AND anonymous_id = %s",
03689 $ilDB->quote($user_id),
03690 $ilDB->quote($this->test_id),
03691 $ilDB->quote($_SESSION["tst_access_code"][$this->getTestId()])
03692 );
03693 }
03694 else if (strlen($anonymous_id))
03695 {
03696 $query = sprintf("SELECT * FROM tst_active WHERE user_fi = %s AND test_fi = %s AND anonymous_id = %s",
03697 $ilDB->quote($user_id),
03698 $ilDB->quote($this->test_id),
03699 $ilDB->quote($anonymous_id)
03700 );
03701 }
03702 else
03703 {
03704 if ($_SESSION["AccountId"] == ANONYMOUS_USER_ID)
03705 {
03706 return NULL;
03707 }
03708 $query = sprintf("SELECT * FROM tst_active WHERE user_fi = %s AND test_fi = %s",
03709 $ilDB->quote($user_id),
03710 $ilDB->quote($this->test_id)
03711 );
03712 }
03713 $result = $ilDB->query($query);
03714 if ($result->numRows())
03715 {
03716 $this->active = $result->fetchRow(DB_FETCHMODE_OBJECT);
03717 }
03718 else
03719 {
03720 $this->active = null;
03721 }
03722 return $this->active;
03723 }
03724
03735 function getActiveIdOfUser($user_id = "", $anonymous_id = "")
03736 {
03737 global $ilDB;
03738 global $ilUser;
03739
03740 if (!$user_id) $user_id = $ilUser->getId();
03741 if (($_SESSION["AccountId"] == ANONYMOUS_USER_ID) && (strlen($_SESSION["tst_access_code"][$this->getTestId()])))
03742 {
03743 $query = sprintf("SELECT active_id FROM tst_active WHERE user_fi = %s AND test_fi = %s AND anonymous_id = %s",
03744 $ilDB->quote($user_id),
03745 $ilDB->quote($this->test_id),
03746 $ilDB->quote($_SESSION["tst_access_code"][$this->getTestId()])
03747 );
03748 }
03749 else if (strlen($anonymous_id))
03750 {
03751 $query = sprintf("SELECT active_id FROM tst_active WHERE user_fi = %s AND test_fi = %s AND anonymous_id = %s",
03752 $ilDB->quote($user_id),
03753 $ilDB->quote($this->test_id),
03754 $ilDB->quote($anonymous_id)
03755 );
03756 }
03757 else
03758 {
03759 if ($_SESSION["AccountId"] == ANONYMOUS_USER_ID)
03760 {
03761 return NULL;
03762 }
03763 $query = sprintf("SELECT active_id FROM tst_active WHERE user_fi = %s AND test_fi = %s",
03764 $ilDB->quote($user_id),
03765 $ilDB->quote($this->test_id)
03766 );
03767 }
03768 $result = $ilDB->query($query);
03769 if ($result->numRows())
03770 {
03771 $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
03772 return $row["active_id"];
03773 }
03774 else
03775 {
03776 return 0;
03777 }
03778 }
03779
03790 function _getActiveTestUser($user_id = "", $test_id = "") {
03791 global $ilDB;
03792 global $ilUser;
03793
03794 if (!$user_id) {
03795 $user_id = $ilUser->id;
03796 }
03797 if (!$test_id)
03798 {
03799 return "";
03800 }
03801 $query = sprintf("SELECT * FROM tst_active WHERE user_fi = %s AND test_fi = %s",
03802 $ilDB->quote($user_id),
03803 $ilDB->quote($test_id)
03804 );
03805
03806 $result = $ilDB->query($query);
03807 if ($result->numRows()) {
03808 return $result->fetchRow(DB_FETCHMODE_OBJECT);
03809 } else {
03810 return "";
03811 }
03812 }
03813
03826 function setActiveTestUser($lastindex = 1, $postpone = "", $addTries = false)
03827 {
03828 global $ilDB;
03829 global $ilUser;
03830
03831 if ($lastindex < 1) $lastindex = 1;
03832
03833 $old_active = $this->getActiveTestUser();
03834 if ($old_active)
03835 {
03836 $sequence = $old_active->sequence;
03837 $postponed = $old_active->postponed;
03838 if ($postpone)
03839 {
03840 $sequence_array = split(",", $sequence);
03841 $postpone_sequence = $sequence_array[$postpone-1];
03842 $question_id = $this->questions[$postpone_sequence];
03843 unset($sequence_array[$postpone-1]);
03844 array_push($sequence_array, $postpone_sequence);
03845 $sequence = join(",", $sequence_array);
03846 $postponed .= ",$question_id";
03847 $postponed = preg_replace("/^,/", "", $postponed);
03848 }
03849 $tries = $old_active->tries;
03850 if ($addTries && ($this->getNrOfResultsForPass($old_active->active_id, $old_active->tries) > 0))
03851 {
03852
03853
03854 $tries++;
03855 }
03856 $query = sprintf("UPDATE tst_active SET lastindex = %s, sequence = %s, postponed = %s, tries = %s WHERE user_fi = %s AND test_fi = %s",
03857 $ilDB->quote($lastindex),
03858 $ilDB->quote($sequence),
03859 $ilDB->quote($postponed),
03860 $ilDB->quote($tries),
03861 $ilDB->quote($ilUser->id),
03862 $ilDB->quote($this->test_id)
03863 );
03864 }
03865 else
03866 {
03867 $sequence_arr = array_flip($this->questions);
03868 if ($this->getShuffleQuestions())
03869 {
03870 $sequence_arr = array_values($sequence_arr);
03871 $sequence_arr = $this->pcArrayShuffle($sequence_arr);
03872 }
03873 $sequence = join($sequence_arr, ",");
03874 if ($_SESSION["tst_access_code"][$this->getTestId()])
03875 {
03876 $anonymous_id = $ilDB->quote($_SESSION["tst_access_code"][$this->getTestId()]);
03877 }
03878 else
03879 {
03880 $anonymous_id = "NULL";
03881 }
03882 $query = sprintf("INSERT INTO tst_active (active_id, user_fi, test_fi, anonymous_id, sequence, postponed, lastindex, tries, TIMESTAMP) VALUES (NULL, %s, %s, %s, %s, %s, %s, %s, NULL)",
03883 $ilDB->quote($ilUser->getId()),
03884 $ilDB->quote($this->getTestId()),
03885 $anonymous_id,
03886 $ilDB->quote($sequence),
03887 $ilDB->quote(""),
03888 $ilDB->quote($lastindex),
03889 $ilDB->quote(0)
03890 );
03891 }
03892 $ilDB->query($query);
03893 if ($old_active)
03894 {
03895 return $old_active->active_id;
03896 }
03897 else
03898 {
03899 return $ilDB->getLastInsertId();
03900 }
03901 }
03902
03915 function addQuestionSequence($active_id)
03916 {
03917 if ($this->isRandomTest())
03918 {
03919 global $ilUser;
03920 global $ilDB;
03921
03922 $this->loadQuestions($active_id, 0);
03923 if ((count($this->questions)) > $this->getQuestionCount())
03924 {
03925
03926
03927 global $ilLog;
03928 $ilLog->write("fatal error: The number of questions is greater than the allowed question count. user id = " . $ilUser->getId() . ", active id = $active_id, questions = " . print_r($this->questions, true));
03929 $sequence_arr = array();
03930 for ($i = 1; $i <= $this->getQuestionCount(); $i++)
03931 {
03932 $sequence_arr[$i] = $i;
03933 }
03934 }
03935 else
03936 {
03937 $sequence_arr = array_flip($this->questions);
03938 }
03939 if ($this->getShuffleQuestions())
03940 {
03941 $sequence_arr = array_values($sequence_arr);
03942 $sequence_arr = $this->pcArrayShuffle($sequence_arr);
03943 }
03944 $sequence = join($sequence_arr, ",");
03945 $query = sprintf("UPDATE tst_active SET sequence = %s WHERE active_id = %s",
03946 $ilDB->quote($sequence . ""),
03947 $ilDB->quote($active_id . "")
03948 );
03949 $ilDB->query($query);
03950 }
03951 }
03952
03961 function pcArrayShuffle($array)
03962 {
03963 mt_srand((double)microtime()*1000000);
03964 $i = count($array);
03965 if ($i > 0)
03966 {
03967 while(--$i)
03968 {
03969 $j = mt_rand(0, $i);
03970 if ($i != $j)
03971 {
03972
03973 $tmp = $array[$j];
03974 $array[$j] = $array[$i];
03975 $array[$i] = $tmp;
03976 }
03977 }
03978 }
03979 return $array;
03980 }
03981
03991 function &getTestResult($active_id, $pass = NULL)
03992 {
03993
03994 if ($this->isRandomTest())
03995 {
03996 $this->loadQuestions($active_id, $pass);
03997 }
03998 $total_max_points = 0;
03999 $total_reached_points = 0;
04000
04001 $key = 1;
04002 $result_array = array();
04003 include_once "./assessment/classes/class.assQuestion.php";
04004 $workedthrough = 0;
04005 $active_object = $this->getActiveTestUserFromActiveId($active_id);
04006 $user_sequence = split(",", $active_object->sequence);
04007 foreach ($user_sequence as $questionindex)
04008 {
04009 $value = $this->questions[$questionindex];
04010 $max_points = assQuestion::_getMaximumPoints($value);
04011 $total_max_points += $max_points;
04012 $reached_points = assQuestion::_getReachedPoints($active_id, $value, $pass);
04013 if (assQuestion::_isWorkedThrough($active_id, $value, $pass))
04014 {
04015 $workedthrough = 1;
04016 }
04017 else
04018 {
04019 $workedthrough = 0;
04020 }
04021 $total_reached_points += $reached_points;
04022 if ($max_points > 0)
04023 {
04024 $percentvalue = $reached_points / $max_points;
04025 }
04026 else
04027 {
04028 $percentvalue = 0;
04029 }
04030 if ($percentvalue < 0) $percentvalue = 0.0;
04031 if (assQuestion::_getSuggestedSolutionCount($value) == 1)
04032 {
04033 $solution_array =& assQuestion::_getSuggestedSolution($value, 0);
04034 $href = assQuestion::_getInternalLinkHref($solution_array["internal_link"]);
04035 }
04036 elseif (assQuestion::_getSuggestedSolutionCount($value) > 1)
04037 {
04038 $href = "see_details_for_further_information";
04039 }
04040 else
04041 {
04042 $href = "";
04043 }
04044 $info =& assQuestion::_getQuestionInfo($value);
04045 include_once "./classes/class.ilUtil.php";
04046 $row = array(
04047 "nr" => "$key",
04048 "title" => ilUtil::prepareFormOutput($info["title"]),
04049 "max" => $max_points,
04050 "reached" => $reached_points,
04051 "percent" => sprintf("%2.2f ", ($percentvalue) * 100) . "%",
04052 "solution" => $href,
04053 "type" => $info["type_tag"],
04054 "qid" => $value,
04055 "original_id" => $info["original_id"],
04056 "workedthrough" => $workedthrough
04057 );
04058 array_push($result_array, $row);
04059 $key++;
04060 }
04061 if ($this->getScoreCutting() == 1)
04062 {
04063 if ($total_reached_points < 0)
04064 {
04065 $total_reached_points = 0;
04066 }
04067 }
04068 $result_array["test"]["total_max_points"] = $total_max_points;
04069 $result_array["test"]["total_reached_points"] = $total_reached_points;
04070 if ((!$total_reached_points) or (!$total_max_points))
04071 {
04072 $percentage = 0.0;
04073 }
04074 else
04075 {
04076 $percentage = ($total_reached_points / $total_max_points) * 100.0;
04077 if ($percentage < 0) $percentage = 0.0;
04078 }
04079 $mark_obj = $this->mark_schema->getMatchingMark($percentage);
04080 $passed = "";
04081 if ($mark_obj)
04082 {
04083 if ($mark_obj->getPassed())
04084 {
04085 $passed = 1;
04086 }
04087 else
04088 {
04089 $passed = 0;
04090 }
04091 }
04092 $result_array["test"]["passed"] = $passed;
04093 return $result_array;
04094 }
04095
04096
04105 function &getTestSummary($active_id, $pass = NULL)
04106 {
04107 global $ilDB;
04108 if ($this->isRandomTest())
04109 {
04110 $this->loadQuestions($active_id, $pass);
04111 }
04112
04113 $key = 1;
04114 $result_array = array();
04115
04116 $active = $this->getActiveTestUserFromActiveId($active_id);
04117 $postponed = explode(",", $active->postponed);
04118 $solved_questions = ilObjTest::_getSolvedQuestions($active_id);
04119 include_once "./classes/class.ilObjUser.php";
04120 $user = new ilObjUser($user_id);
04121 $sequence_array = split(",", $active->sequence);
04122 foreach ($sequence_array as $question_index)
04123 {
04124 $val = $this->questions[$question_index];
04125 $question =& ilObjTest::_instanciateQuestion($val);
04126 if (is_object($question))
04127 {
04128 $worked_through = $question->_isWorkedThrough($active_id, $question->getId(), $pass);
04129 $solved = 0;
04130 if (array_key_exists($question->getId(),$solved_questions))
04131 {
04132 $solved = $solved_questions[$question->getId()]->solved;
04133 }
04134 $is_postponed = FALSE;
04135 if (in_array($question->getId(), $postponed))
04136 {
04137 $is_postponed = TRUE;
04138 }
04139
04140 $row = array(
04141 "nr" => "$key",
04142 "title" => $question->getTitle(),
04143 "qid" => $question->getId(),
04144 "visited" => $worked_through,
04145 "solved" => (($solved)?"1":"0"),
04146 "description" => $question->getComment(),
04147 "points" => $question->getMaximumPoints(),
04148 "worked_through" => $worked_through,
04149 "postponed" => $is_postponed
04150 );
04151 array_push($result_array, $row);
04152 $key++;
04153 }
04154 }
04155
04156 return $result_array;
04157 }
04158
04159
04168 function evalTotalPersons()
04169 {
04170 global $ilDB;
04171
04172 $q = sprintf("SELECT COUNT(*) as total FROM tst_active WHERE test_fi = %s",
04173 $ilDB->quote($this->getTestId())
04174 );
04175 $result = $ilDB->query($q);
04176 $row = $result->fetchRow(DB_FETCHMODE_OBJECT);
04177 return $row->total;
04178 }
04179
04188 function canViewResults()
04189 {
04190 $result = true;
04191 if ($this->getTestType() != TYPE_SELF_ASSESSMENT)
04192 {
04193 if ($this->getReportingDate())
04194 {
04195 if (preg_match("/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/", $this->getReportingDate(), $matches))
04196 {
04197 $epoch_time = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
04198 $now = mktime();
04199 if ($now < $epoch_time)
04200 {
04201 $result = false;
04202 }
04203 }
04204 }
04205 }
04206 return $result;
04207 }
04208
04217 function evalLoadStatisticalSettings($user_id)
04218 {
04219 global $ilDB;
04220
04221 $q = sprintf("SELECT * FROM tst_eval_settings WHERE user_fi = %s",
04222 $ilDB->quote("$user_id")
04223 );
04224 $result = $ilDB->query($q);
04225 if (!$result->numRows())
04226 {
04227 $row = array(
04228 "qworkedthrough" => "1",
04229 "pworkedthrough" => "1",
04230 "timeofwork" => "1",
04231 "atimeofwork" => "1",
04232 "firstvisit" => "1",
04233 "lastvisit" => "1",
04234 "resultspoints" => "1",
04235 "resultsmarks" => "1",
04236 "distancemedian" => "1"
04237 );
04238 }
04239 else
04240 {
04241 $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
04242 unset($row["eval_settings_id"]);
04243 }
04244 return $row;
04245 }
04246
04255 function evalSaveStatisticalSettings($settings_array, $user_id)
04256 {
04257 global $ilDB;
04258
04259 $q = sprintf("SELECT * FROM tst_eval_settings WHERE user_fi = %s",
04260 $ilDB->quote("$user_id")
04261 );
04262 $result = $ilDB->query($q);
04263 if ($result->numRows() > 0)
04264 {
04265 $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
04266 }
04267 $update = $row["eval_settings_id"];
04268 if (!$update) {
04269 $q = sprintf("INSERT INTO tst_eval_settings ".
04270 "(eval_settings_id, user_fi, qworkedthrough, pworkedthrough, timeofwork, atimeofwork, firstvisit, " .
04271 "lastvisit, resultspoints, resultsmarks, distancemedian, TIMESTAMP) VALUES " .
04272 "(NULL, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, NULL)",
04273 $ilDB->quote("$user_id"),
04274 $ilDB->quote(sprintf("%01d", $settings_array["qworkedthrough"])),
04275 $ilDB->quote(sprintf("%01d", $settings_array["pworkedthrough"])),
04276 $ilDB->quote(sprintf("%01d", $settings_array["timeofwork"])),
04277 $ilDB->quote(sprintf("%01d", $settings_array["atimeofwork"])),
04278 $ilDB->quote(sprintf("%01d", $settings_array["firstvisit"])),
04279 $ilDB->quote(sprintf("%01d", $settings_array["lastvisit"])),
04280 $ilDB->quote(sprintf("%01d", $settings_array["resultspoints"])),
04281 $ilDB->quote(sprintf("%01d", $settings_array["resultsmarks"])),
04282 $ilDB->quote(sprintf("%01d", $settings_array["distancemedian"]))
04283 );
04284 }
04285 else
04286 {
04287 $q = sprintf("UPDATE tst_eval_settings SET ".
04288 "qworkedthrough = %s, pworkedthrough = %s, timeofwork = %s, atimeofwork = %s, firstvisit = %s, " .
04289 "lastvisit = %s, resultspoints = %s, resultsmarks = %s, distancemedian = %s " .
04290 "WHERE eval_settings_id = %s",
04291 $ilDB->quote(sprintf("%01d", $settings_array["qworkedthrough"])),
04292 $ilDB->quote(sprintf("%01d", $settings_array["pworkedthrough"])),
04293 $ilDB->quote(sprintf("%01d", $settings_array["timeofwork"])),
04294 $ilDB->quote(sprintf("%01d", $settings_array["atimeofwork"])),
04295 $ilDB->quote(sprintf("%01d", $settings_array["firstvisit"])),
04296 $ilDB->quote(sprintf("%01d", $settings_array["lastvisit"])),
04297 $ilDB->quote(sprintf("%01d", $settings_array["resultspoints"])),
04298 $ilDB->quote(sprintf("%01d", $settings_array["resultsmarks"])),
04299 $ilDB->quote(sprintf("%01d", $settings_array["distancemedian"])),
04300 $ilDB->quote("$update")
04301 );
04302 }
04303 $result = $ilDB->query($q);
04304 }
04305
04314 function getCompleteWorkingTime($user_id)
04315 {
04316 global $ilDB;
04317
04318 $q = sprintf("SELECT tst_times.* FROM tst_active, tst_times WHERE tst_active.test_fi = %s AND tst_active.active_id = tst_times.active_fi AND tst_active.user_fi = %s",
04319 $ilDB->quote($this->getTestId()),
04320 $ilDB->quote($user_id)
04321 );
04322 $result = $ilDB->query($q);
04323 $time = 0;
04324 while ($row = $result->fetchRow(DB_FETCHMODE_OBJECT))
04325 {
04326 preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row->started, $matches);
04327 $epoch_1 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
04328 preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row->finished, $matches);
04329 $epoch_2 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
04330 $time += ($epoch_2 - $epoch_1);
04331 }
04332 return $time;
04333 }
04334
04343 function &evalStatistical($active_id)
04344 {
04345 global $ilDB;
04346
04347 $pass = ilObjTest::_getResultPass($active_id);
04348 $test_result =& $this->getTestResult($active_id, $pass);
04349 $q = sprintf("SELECT tst_times.* FROM tst_active, tst_times WHERE tst_active.active_id = %s AND tst_active.active_id = tst_times.active_fi",
04350 $ilDB->quote($active_id)
04351 );
04352 $result = $ilDB->query($q);
04353 $times = array();
04354 $first_visit = 0;
04355 $last_visit = 0;
04356 while ($row = $result->fetchRow(DB_FETCHMODE_OBJECT)) {
04357 preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row->started, $matches);
04358 $epoch_1 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
04359 if (!$first_visit) {
04360 $first_visit = $epoch_1;
04361 }
04362 if ($epoch_1 < $first_visit) {
04363 $first_visit = $epoch_1;
04364 }
04365 preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row->finished, $matches);
04366 $epoch_2 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
04367 if (!$last_visit) {
04368 $last_visit = $epoch_2;
04369 }
04370 if ($epoch_2 > $last_visit) {
04371 $last_visit = $epoch_2;
04372 }
04373 $times[$row->active_fi] += ($epoch_2 - $epoch_1);
04374 }
04375 $max_time = 0;
04376 foreach ($times as $key => $value) {
04377 $max_time += $value;
04378 }
04379 if ((!$test_result["test"]["total_reached_points"]) or (!$test_result["test"]["total_max_points"]))
04380 {
04381 $percentage = 0.0;
04382 }
04383 else
04384 {
04385 $percentage = ($test_result["test"]["total_reached_points"] / $test_result["test"]["total_max_points"]) * 100.0;
04386 if ($percentage < 0) $percentage = 0.0;
04387 }
04388 $mark_obj = $this->mark_schema->getMatchingMark($percentage);
04389 $first_date = getdate($first_visit);
04390 $last_date = getdate($last_visit);
04391 $qworkedthrough = 0;
04392 foreach ($test_result as $key => $value)
04393 {
04394 if (preg_match("/\d+/", $key))
04395 {
04396 $qworkedthrough += $value["workedthrough"];
04397 }
04398 }
04399 if (!$qworkedthrough)
04400 {
04401 $atimeofwork = 0;
04402 }
04403 else
04404 {
04405 $atimeofwork = $max_time / $qworkedthrough;
04406 }
04407 $result_mark = "";
04408 $passed = "";
04409 if ($mark_obj)
04410 {
04411 $result_mark = $mark_obj->getShortName();
04412 if ($mark_obj->getPassed())
04413 {
04414 $passed = 1;
04415 }
04416 else
04417 {
04418 $passed = 0;
04419 }
04420 }
04421 $percent_worked_through = 0;
04422 if (count($this->questions))
04423 {
04424 $percent_worked_through = $qworkedthrough / count($this->questions);
04425 }
04426 $result_array = array(
04427 "qworkedthrough" => $qworkedthrough,
04428 "qmax" => count($this->questions),
04429 "pworkedthrough" => $percent_worked_through,
04430 "timeofwork" => $max_time,
04431 "atimeofwork" => $atimeofwork,
04432 "firstvisit" => $first_date,
04433 "lastvisit" => $last_date,
04434 "resultspoints" => $test_result["test"]["total_reached_points"],
04435 "maxpoints" => $test_result["test"]["total_max_points"],
04436 "resultsmarks" => $result_mark,
04437 "passed" => $passed,
04438 "distancemedian" => "0"
04439 );
04440 foreach ($test_result as $key => $value)
04441 {
04442 if (preg_match("/\d+/", $key))
04443 {
04444 $result_array[$key] = $value;
04445 }
04446 }
04447 return $result_array;
04448 }
04449
04459 function &getTotalPointsArray()
04460 {
04461 $totalpoints_array = array();
04462 $all_users =& $this->evalTotalParticipantsArray();
04463 foreach ($all_users as $active_id => $user_name)
04464 {
04465 $test_result =& $this->getTestResult($active_id);
04466 array_push($totalpoints_array, $test_result["test"]["total_reached_points"]);
04467 }
04468 return $totalpoints_array;
04469 }
04470
04480 function &getTotalPointsPassedArray()
04481 {
04482 $totalpoints_array = array();
04483 $all_users =& $this->evalTotalParticipantsArray();
04484 foreach ($all_users as $active_id => $user_name)
04485 {
04486 $test_result =& $this->getTestResult($active_id);
04487 $reached = $test_result["test"]["total_reached_points"];
04488 $total = $test_result["test"]["total_max_points"];
04489 $percentage = $total != 0 ? $reached/$total : 0;
04490 $mark = $this->mark_schema->getMatchingMark($percentage*100.0);
04491 if ($mark)
04492 {
04493 if ($mark->getPassed())
04494 {
04495 array_push($totalpoints_array, $test_result["test"]["total_reached_points"]);
04496 }
04497 }
04498 }
04499 return $totalpoints_array;
04500 }
04501
04510 function &evalTotalPersonsArray($name_sort_order = "asc")
04511 {
04512 global $ilDB;
04513 $q = sprintf("SELECT tst_active.active_id, usr_data.firstname, usr_data.lastname, usr_data.title FROM tst_active LEFT JOIN usr_data ON tst_active.user_fi = usr_data.usr_id WHERE tst_active.test_fi = %s ORDER BY usr_data.lastname " . strtoupper($name_sort_order),
04514 $ilDB->quote($this->getTestId())
04515 );
04516 $result = $ilDB->query($q);
04517 $persons_array = array();
04518 while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC))
04519 {
04520 if (strlen($row["firstname"].$row["lastname"].$row["title"]) == 0)
04521 {
04522 $persons_array[$row["active_id"]] = $this->lng->txt("deleted_user");
04523 }
04524 else
04525 {
04526 if ($row["user_fi"] == ANONYMOUS_USER_ID)
04527 {
04528 $persons_array[$row["active_id"]] = $row["lastname"];
04529 }
04530 else
04531 {
04532 $persons_array[$row["active_id"]] = trim($row["lastname"] . ", " . $row["firstname"] . " " . $row["title"]);
04533 }
04534 if ($this->getTestType() == TYPE_SELF_ASSESSMENT)
04535 {
04536 $persons_array[$row["active_id"]] = $this->lng->txt("anonymous");
04537 }
04538 }
04539 }
04540 return $persons_array;
04541 }
04542
04551 function &evalTotalParticipantsArray($name_sort_order = "asc")
04552 {
04553 global $ilDB;
04554 $q = sprintf("SELECT tst_active.active_id, usr_data.login, usr_data.firstname, usr_data.lastname, usr_data.title FROM tst_active LEFT JOIN usr_data ON tst_active.user_fi = usr_data.usr_id WHERE tst_active.test_fi = %s ORDER BY usr_data.lastname " . strtoupper($name_sort_order),
04555 $ilDB->quote($this->getTestId())
04556 );
04557 $result = $ilDB->query($q);
04558 $persons_array = array();
04559 while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC))
04560 {
04561 if (strlen($row["firstname"].$row["lastname"].$row["title"]) == 0)
04562 {
04563 $persons_array[$row["active_id"]] = array("name" => $this->lng->txt("deleted_user"));
04564 }
04565 else
04566 {
04567 if ($row["user_fi"] == ANONYMOUS_USER_ID)
04568 {
04569 $persons_array[$row["active_id"]] = array("name" => $row["lastname"]);
04570 }
04571 else
04572 {
04573 $persons_array[$row["active_id"]] = array("name" => trim($row["lastname"] . ", " . $row["firstname"] . " " . $row["title"]), "login" => $row["login"]);
04574 }
04575 if ($this->getTestType() == TYPE_SELF_ASSESSMENT)
04576 {
04577 $persons_array[$row["active_id"]] = array("name" => $this->lng->txt("anonymous"));
04578 }
04579 }
04580 }
04581 return $persons_array;
04582 }
04583
04592 function evalTotalFinished()
04593 {
04594 global $ilDB;
04595
04596 $q = sprintf("SELECT COUNT(*) as total FROM tst_active WHERE test_fi = %s AND tries > 0",
04597 $ilDB->quote($this->getTestId())
04598 );
04599 $result = $ilDB->query($q);
04600 $row = $result->fetchRow(DB_FETCHMODE_OBJECT);
04601 return $row->total;
04602 }
04603
04612 function evalTotalStartedAverageTime()
04613 {
04614 global $ilDB;
04615
04616 $q = sprintf("SELECT tst_times.* FROM tst_active, tst_times WHERE tst_active.test_fi = %s AND tst_active.active_id = tst_times.active_fi",
04617 $ilDB->quote($this->getTestId())
04618 );
04619 $result = $ilDB->query($q);
04620 $times = array();
04621 while ($row = $result->fetchRow(DB_FETCHMODE_OBJECT))
04622 {
04623 preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row->started, $matches);
04624 $epoch_1 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
04625 preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row->finished, $matches);
04626 $epoch_2 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
04627 $times[$row->active_fi] += ($epoch_2 - $epoch_1);
04628 }
04629 $max_time = 0;
04630 $counter = 0;
04631 foreach ($times as $key => $value)
04632 {
04633 $max_time += $value;
04634 $counter++;
04635 }
04636 if ($counter)
04637 {
04638 $average_time = round($max_time / $counter);
04639 }
04640 else
04641 {
04642 $average_time = 0;
04643 }
04644 return $average_time;
04645 }
04646
04655 function evalTotalPassedAverageTime()
04656 {
04657 global $ilDB;
04658
04659 include_once "./assessment/classes/class.ilObjTestAccess.php";
04660 $passed_users =& ilObjTest::_getPassedUsers($this->getId());
04661 $q = sprintf("SELECT tst_times.*, tst_active.active_id FROM tst_active, tst_times WHERE tst_active.test_fi = %s AND tst_active.active_id = tst_times.active_fi",
04662 $ilDB->quote($this->getTestId())
04663 );
04664 $result = $ilDB->query($q);
04665 $times = array();
04666 while ($row = $result->fetchRow(DB_FETCHMODE_OBJECT))
04667 {
04668 if (in_array($row->active_id, $passed_users))
04669 {
04670 preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row->started, $matches);
04671 $epoch_1 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
04672 preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row->finished, $matches);
04673 $epoch_2 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
04674 $times[$row->active_id] += ($epoch_2 - $epoch_1);
04675 }
04676 }
04677 $max_time = 0;
04678 $counter = 0;
04679 foreach ($times as $key => $value)
04680 {
04681 $max_time += $value;
04682 $counter++;
04683 }
04684 if ($counter)
04685 {
04686 $average_time = round($max_time / $counter);
04687 }
04688 else
04689 {
04690 $average_time = 0;
04691 }
04692 return $average_time;
04693 }
04694
04703 function &getAvailableQuestionpoolIDs()
04704 {
04705 global $rbacsystem;
04706 global $ilDB;
04707
04708 $result_array = array();
04709 $query = "SELECT object_data.*, object_data.obj_id, object_reference.ref_id FROM object_data, object_reference WHERE object_data.obj_id = object_reference.obj_id AND object_data.type = 'qpl'";
04710 $result = $ilDB->query($query);
04711 while ($row = $result->fetchRow(DB_FETCHMODE_OBJECT))
04712 {
04713 if ($rbacsystem->checkAccess("write", $row->ref_id) && ($this->_hasUntrashedReference($row->obj_id)))
04714 {
04715 include_once("./assessment/classes/class.ilObjQuestionPool.php");
04716 if (ilObjQuestionPool::_lookupOnline($row->obj_id))
04717 {
04718 array_push($result_array, $row->obj_id);
04719 }
04720 }
04721 }
04722 return $result_array;
04723 }
04724
04733 function &getAvailableQuestionpools($use_object_id = false, $equal_points = false, $could_be_offline = false, $with_questioncount = FALSE)
04734 {
04735 global $rbacsystem;
04736 global $ilDB;
04737
04738 $result_array = array();
04739 $query = "SELECT object_data.*, object_data.obj_id, object_reference.ref_id, qpl_questionpool.* FROM object_data, object_reference, qpl_questionpool WHERE object_data.obj_id = object_reference.obj_id AND object_data.type = 'qpl' AND object_data.obj_id = qpl_questionpool.obj_fi ORDER BY object_data.title";
04740 $result = $ilDB->query($query);
04741 while ($row = $result->fetchRow(DB_FETCHMODE_OBJECT))
04742 {
04743 if ($rbacsystem->checkAccess("write", $row->ref_id) && ($this->_hasUntrashedReference($row->obj_id)))
04744 {
04745 include_once("./assessment/classes/class.ilObjQuestionPool.php");
04746 if (ilObjQuestionPool::_lookupOnline($row->obj_id) || $could_be_offline)
04747 {
04748 if ((!$equal_points) || (($equal_points) && (ilObjQuestionPool::_hasEqualPoints($row->obj_id))))
04749 {
04750 $qpl_title = $row->title;
04751 if ($with_questioncount)
04752 {
04753 if ($row->questioncount == 1)
04754 {
04755 $qpl_title .= " (" . $row->questioncount . " " . $this->lng->txt("ass_question") . ")";
04756 }
04757 else
04758 {
04759 $qpl_title .= " (" . $row->questioncount . " " . $this->lng->txt("assQuestions") . ")";
04760 }
04761 }
04762 if ($use_object_id)
04763 {
04764 $result_array[$row->obj_id] = array("title" => $qpl_title, "count" => $row->questioncount);
04765 }
04766 else
04767 {
04768 $result_array[$row->ref_id] = array("title" => $qpl_title, "count" => $row->questioncount);
04769 }
04770 }
04771 }
04772 }
04773 }
04774 return $result_array;
04775 }
04776
04785 function getEstimatedWorkingTime()
04786 {
04787 $time_in_seconds = 0;
04788 foreach ($this->questions as $question_id)
04789 {
04790 $question =& ilObjTest::_instanciateQuestion($question_id);
04791 $est_time = $question->getEstimatedWorkingTime();
04792 $time_in_seconds += $est_time["h"] * 3600 + $est_time["m"] * 60 + $est_time["s"];
04793 }
04794 $hours = (int)($time_in_seconds / 3600) ;
04795 $time_in_seconds = $time_in_seconds - ($hours * 3600);
04796 $minutes = (int)($time_in_seconds / 60);
04797 $time_in_seconds = $time_in_seconds - ($minutes * 60);
04798 $result = array("h" => $hours, "m" => $minutes, "s" => $time_in_seconds);
04799 return $result;
04800 }
04801
04814 function randomSelectQuestions($nr_of_questions, $questionpool, $use_obj_id = 0, $qpls = "", $pass = NULL)
04815 {
04816 global $rbacsystem;
04817 global $ilDB;
04818
04819 if ($questionpool != 0)
04820 {
04821
04822 if (!$use_obj_id)
04823 {
04824 $query = sprintf("SELECT obj_id FROM object_reference WHERE ref_id = %s",
04825 $ilDB->quote("$questionpool")
04826 );
04827 $result = $ilDB->query($query);
04828 $row = $result->fetchRow(DB_FETCHMODE_ARRAY);
04829 $questionpool = $row[0];
04830 }
04831 }
04832
04833
04834 $query = sprintf("SELECT qpl_questions.original_id FROM qpl_questions, tst_test_question WHERE qpl_questions.question_id = tst_test_question.question_fi AND tst_test_question.test_fi = %s",
04835 $ilDB->quote($this->getTestId() . "")
04836 );
04837 $result = $ilDB->query($query);
04838 $original_ids = array();
04839 while ($row = $result->fetchRow(DB_FETCHMODE_ARRAY))
04840 {
04841 if (strcmp($row[0], "") != 0)
04842 {
04843 array_push($original_ids, $row[0]);
04844 }
04845 }
04846 $original_clause = "";
04847 if (count($original_ids))
04848 {
04849 $original_clause = " AND ISNULL(qpl_questions.original_id) AND qpl_questions.question_id NOT IN (" . join($original_ids, ",") . ")";
04850 }
04851
04852
04853 if (($questionpool == 0) && (!is_array($qpls)))
04854 {
04855 $available_pools =& $this->getAvailableQuestionpoolIDs();
04856 $available = "";
04857 $constraint_qpls = "";
04858 if (count($available_pools))
04859 {
04860 $available = " AND qpl_questions.obj_fi IN (" . join($available_pools, ",") . ")";
04861 }
04862 else
04863 {
04864 return array();
04865 }
04866 }
04867
04868 $result_array = array();
04869 if ($questionpool == 0)
04870 {
04871 if (is_array($qpls))
04872 {
04873 if (count($qpls) > 0)
04874 {
04875 $qplidx = array();
04876 foreach ($qpls as $idx => $arr)
04877 {
04878 array_push($qplidx, $arr["qpl"]);
04879 }
04880 $constraint_qpls = " AND qpl_questions.obj_fi IN (" . join($qplidx, ",") . ")";
04881 }
04882 }
04883 $query = "SELECT COUNT(question_id) FROM qpl_questions, object_data WHERE ISNULL(qpl_questions.original_id) AND object_data.type = 'qpl' AND object_data.obj_id = qpl_questions.obj_fi$available$constraint_qpls AND qpl_questions.complete = '1'$original_clause";
04884 }
04885 else
04886 {
04887 $query = sprintf("SELECT COUNT(question_id) FROM qpl_questions WHERE ISNULL(qpl_questions.original_id) AND obj_fi = %s$original_clause",
04888 $ilDB->quote("$questionpool")
04889 );
04890 }
04891 $result = $ilDB->query($query);
04892 $row = $result->fetchRow(DB_FETCHMODE_ARRAY);
04893 if (($row[0]) <= $nr_of_questions)
04894 {
04895
04896 if ($questionpool == 0)
04897 {
04898 $query = "SELECT question_id FROM qpl_questions, object_data WHERE ISNULL(qpl_questions.original_id) AND object_data.type = 'qpl' AND object_data.obj_id = qpl_questions.obj_fi$available$constraint_qpls AND qpl_questions.complete = '1'$original_clause";
04899 }
04900 else
04901 {
04902 $query = sprintf("SELECT question_id FROM qpl_questions WHERE ISNULL(qpl_questions.original_id) AND obj_fi = %s AND qpl_questions.complete = '1'$original_clause",
04903 $ilDB->quote("$questionpool")
04904 );
04905 }
04906 $result = $ilDB->query($query);
04907 while ($row = $result->fetchRow(DB_FETCHMODE_ARRAY))
04908 {
04909 if ((!in_array($row[0], $this->questions)) && (strcmp($row[0], "") != 0))
04910 {
04911 $result_array[$row[0]] = $row[0];
04912 }
04913 }
04914 }
04915 else
04916 {
04917
04918 mt_srand((double)microtime()*1000000);
04919 $random_number = mt_rand(0, $row[0] - 1);
04920 $securitycounter = 500;
04921 while ((count($result_array) < $nr_of_questions) && ($securitycounter > 0))
04922 {
04923 if ($questionpool == 0)
04924 {
04925 $query = "SELECT question_id FROM qpl_questions, object_data WHERE ISNULL(qpl_questions.original_id) AND object_data.type = 'qpl' AND object_data.obj_id = qpl_questions.obj_fi$available$constraint_qpls AND qpl_questions.complete = '1'$original_clause LIMIT $random_number, 1";
04926 }
04927 else
04928 {
04929 $query = sprintf("SELECT question_id FROM qpl_questions WHERE ISNULL(qpl_questions.original_id) AND obj_fi = %s AND qpl_questions.complete = '1'$original_clause LIMIT $random_number, 1",
04930 $ilDB->quote("$questionpool")
04931 );
04932 }
04933 $result = $ilDB->query($query);
04934 $result_row = $result->fetchRow(DB_FETCHMODE_ARRAY);
04935 if ((!in_array($result_row[0], $this->questions)) && (strcmp($result_row[0], "") != 0))
04936 {
04937 $result_array[$result_row[0]] = $result_row[0];
04938 }
04939 $random_number = mt_rand(0, $row[0] - 1);
04940 $securitycounter--;
04941 }
04942 }
04943 return $result_array;
04944 }
04945
04954 function getImagePath()
04955 {
04956 return CLIENT_WEB_DIR . "/assessment/" . $this->getId() . "/images/";
04957 }
04958
04967 function getImagePathWeb()
04968 {
04969 include_once "./classes/class.ilUtil.php";
04970 $webdir = ilUtil::removeTrailingPathSeparators(CLIENT_WEB_DIR) . "/assessment/" . $this->getId() . "/images/";
04971 return str_replace(ilUtil::removeTrailingPathSeparators(ILIAS_ABSOLUTE_PATH), ilUtil::removeTrailingPathSeparators(ILIAS_HTTP_PATH), $webdir);
04972 }
04973
04984 function &createQuestionGUI($question_type, $question_id = -1)
04985 {
04986 if ((!$question_type) and ($question_id > 0))
04987 {
04988 $question_type = $this->getQuestionType($question_id);
04989 }
04990 include_once "./assessment/classes/class.".$question_type."GUI.php";
04991 $question_type_gui = $question_type . "GUI";
04992 $question =& new $question_type_gui();
04993 if ($question_id > 0)
04994 {
04995 $question->object->loadFromDb($question_id);
04996 }
04997 return $question;
04998 }
04999
05009 function &_instanciateQuestion($question_id)
05010 {
05011 if (strcmp($question_id, "") != 0)
05012 {
05013 include_once "./assessment/classes/class.assQuestion.php";
05014 $question_type = assQuestion::_getQuestionType($question_id);
05015
05016 if(!strlen($question_type))
05017 {
05018 return false;
05019 }
05020
05021 include_once "./assessment/classes/class.".$question_type.".php";
05022 $question = new $question_type();
05023
05024 $question->loadFromDb($question_id);
05025 return $question;
05026 }
05027 }
05028
05039 function moveQuestions($move_questions, $target_index, $insert_mode)
05040 {
05041 $this->questions = array_values($this->questions);
05042 $array_pos = array_search($target_index, $this->questions);
05043 if ($insert_mode == 0)
05044 {
05045 $part1 = array_slice($this->questions, 0, $array_pos);
05046 $part2 = array_slice($this->questions, $array_pos);
05047 }
05048 else if ($insert_mode == 1)
05049 {
05050 $part1 = array_slice($this->questions, 0, $array_pos + 1);
05051 $part2 = array_slice($this->questions, $array_pos + 1);
05052 }
05053 foreach ($move_questions as $question_id)
05054 {
05055 if (!(array_search($question_id, $part1) === FALSE))
05056 {
05057 unset($part1[array_search($question_id, $part1)]);
05058 }
05059 if (!(array_search($question_id, $part2) === FALSE))
05060 {
05061 unset($part2[array_search($question_id, $part2)]);
05062 }
05063 }
05064 $part1 = array_values($part1);
05065 $part2 = array_values($part2);
05066 $new_array = array_values(array_merge($part1, $move_questions, $part2));
05067 $this->questions = array();
05068 $counter = 1;
05069 foreach ($new_array as $question_id)
05070 {
05071 $this->questions[$counter] = $question_id;
05072 $counter++;
05073 }
05074 $this->saveQuestionsToDb();
05075 }
05076
05077
05087 function startingTimeReached()
05088 {
05089 if ($this->getTestType() == TYPE_ASSESSMENT || $this->getTestType() == TYPE_ONLINE_TEST || $this->getTestType() == TYPE_VARYING_RANDOMTEST)
05090 {
05091 if ($this->getStartingTime())
05092 {
05093 if (preg_match("/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/", $this->getStartingTime(), $matches))
05094 {
05095 $epoch_time = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
05096 $now = mktime();
05097 if ($now < $epoch_time)
05098 {
05099
05100 return false;
05101 }
05102 }
05103 }
05104 }
05105 return true;
05106 }
05107
05117 function endingTimeReached()
05118 {
05119 if ($this->getTestType() == TYPE_ASSESSMENT || $this->getTestType() == TYPE_ONLINE_TEST || $this->getTestType() == TYPE_VARYING_RANDOMTEST)
05120 {
05121 if ($this->getEndingTime())
05122 {
05123 if (preg_match("/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/", $this->getEndingTime(), $matches))
05124 {
05125 $epoch_time = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
05126 $now = mktime();
05127 if ($now > $epoch_time)
05128 {
05129
05130 return true;
05131 }
05132 }
05133 }
05134 }
05135 return false;
05136 }
05137
05145 function getQuestionsTable($sort, $sortorder, $filter_text, $sel_filter_type, $startrow = 0, $completeonly = 0, $filter_question_type = "", $filter_questionpool = "")
05146 {
05147 global $ilUser;
05148 global $ilDB;
05149
05150 $where = "";
05151 if (strlen($filter_text) > 0) {
05152 switch($sel_filter_type) {
05153 case "title":
05154 $where = " AND qpl_questions.title LIKE " . $ilDB->quote("%" . $filter_text . "%");
05155 break;
05156 case "comment":
05157 $where = " AND qpl_questions.comment LIKE " . $ilDB->quote("%" . $filter_text . "%");
05158 break;
05159 case "author":
05160 $where = " AND qpl_questions.author LIKE " . $ilDB->quote("%" . $filter_text . "%");
05161 break;
05162 }
05163 }
05164
05165 if ($filter_question_type && (strcmp($filter_question_type, "all") != 0))
05166 {
05167 $where .= " AND qpl_question_type.type_tag = " . $ilDB->quote($filter_question_type);
05168 }
05169
05170 if ($filter_questionpool && (strcmp($filter_questionpool, "all") != 0))
05171 {
05172 $where .= " AND qpl_questions.obj_fi = $filter_questionpool";
05173 }
05174
05175
05176 $order = "";
05177 $images = array();
05178 include_once "./classes/class.ilUtil.php";
05179 switch($sort)
05180 {
05181 case "title":
05182 $order = " ORDER BY title $sortorder";
05183 $images["title"] = " <img src=\"" . ilUtil::getImagePath(strtolower($sortorder) . "_order.gif") . "\" alt=\"" . $this->lng->txt(strtolower($sortorder) . "ending_order")."\" />";
05184 break;
05185 case "comment":
05186 $order = " ORDER BY comment $sortorder";
05187 $images["comment"] = " <img src=\"" . ilUtil::getImagePath(strtolower($sortorder) . "_order.gif") . "\" alt=\"" . $this->lng->txt(strtolower($sortorder) . "ending_order")."\" />";
05188 break;
05189 case "type":
05190 $order = " ORDER BY question_type_id $sortorder";
05191 $images["type"] = " <img src=\"" . ilUtil::getImagePath(strtolower($sortorder) . "_order.gif") . "\" alt=\"" . $this->lng->txt(strtolower($sortorder) . "ending_order")."\" />";
05192 break;
05193 case "author":
05194 $order = " ORDER BY author $sortorder";
05195 $images["author"] = " <img src=\"" . ilUtil::getImagePath(strtolower($sortorder) . "_order.gif") . "\" alt=\"" . $this->lng->txt(strtolower($sortorder) . "ending_order")."\" />";
05196 break;
05197 case "created":
05198 $order = " ORDER BY created $sortorder";
05199 $images["created"] = " <img src=\"" . ilUtil::getImagePath(strtolower($sortorder) . "_order.gif") . "\" alt=\"" . $this->lng->txt(strtolower($sortorder) . "ending_order")."\" />";
05200 break;
05201 case "updated":
05202 $order = " ORDER BY TIMESTAMP14 $sortorder";
05203 $images["updated"] = " <img src=\"" . ilUtil::getImagePath(strtolower($sortorder) . "_order.gif") . "\" alt=\"" . $this->lng->txt(strtolower($sortorder) . "ending_order")."\" />";
05204 break;
05205 case "qpl":
05206 $order = " ORDER BY obj_fi $sortorder";
05207 $images["qpl"] = " <img src=\"" . ilUtil::getImagePath(strtolower($sortorder) . "_order.gif") . "\" alt=\"" . $this->lng->txt(strtolower($sortorder) . "ending_order")."\" />";
05208 break;
05209 }
05210 $maxentries = $ilUser->prefs["hits_per_page"];
05211 if ($maxentries < 1)
05212 {
05213 $maxentries = 9999;
05214 }
05215 $available_pools =& $this->getAvailableQuestionpoolIDs();
05216 $available = "";
05217 if (count($available_pools))
05218 {
05219 $available = " AND qpl_questions.obj_fi IN (" . join($available_pools, ",") . ")";
05220 }
05221 else
05222 {
05223 return array();
05224 }
05225 if ($completeonly)
05226 {
05227 $available .= " AND qpl_questions.complete = " . $ilDB->quote("1");
05228 }
05229
05230
05231 $query = sprintf("SELECT qpl_questions.original_id, qpl_questions.TIMESTAMP + 0 AS TIMESTAMP14 FROM qpl_questions, tst_test_question WHERE qpl_questions.question_id = tst_test_question.question_fi AND tst_test_question.test_fi = %s",
05232 $ilDB->quote($this->getTestId() . "")
05233 );
05234 $result = $ilDB->query($query);
05235 $original_ids = array();
05236 while ($row = $result->fetchRow(DB_FETCHMODE_ARRAY))
05237 {
05238 if (strcmp($row[0], "") != 0)
05239 {
05240 array_push($original_ids, $row[0]);
05241 }
05242 }
05243 $original_clause = " ISNULL(qpl_questions.original_id)";
05244 if (count($original_ids))
05245 {
05246 $original_clause = " ISNULL(qpl_questions.original_id) AND qpl_questions.question_id NOT IN (" . join($original_ids, ",") . ")";
05247 }
05248
05249 $query = "SELECT qpl_questions.question_id, qpl_questions.TIMESTAMP + 0 AS TIMESTAMP14 FROM qpl_questions, qpl_question_type WHERE $original_clause$available AND qpl_questions.question_type_fi = qpl_question_type.question_type_id $where$order$limit";
05250 $query_result = $ilDB->query($query);
05251 $max = $query_result->numRows();
05252 if ($startrow > $max -1)
05253 {
05254 $startrow = $max - ($max % $maxentries);
05255 }
05256 else if ($startrow < 0)
05257 {
05258 $startrow = 0;
05259 }
05260 $limit = " LIMIT $startrow, $maxentries";
05261 $query = "SELECT qpl_questions.*, qpl_questions.TIMESTAMP + 0 AS TIMESTAMP14, qpl_question_type.type_tag FROM qpl_questions, qpl_question_type WHERE $original_clause $available AND qpl_questions.question_type_fi = qpl_question_type.question_type_id $where$order$limit";
05262 $query_result = $ilDB->query($query);
05263 $rows = array();
05264 if ($query_result->numRows())
05265 {
05266 while ($row = $query_result->fetchRow(DB_FETCHMODE_ASSOC))
05267 {
05268 array_push($rows, $row);
05269 }
05270 }
05271 $nextrow = $startrow + $maxentries;
05272 if ($nextrow > $max - 1)
05273 {
05274 $nextrow = $startrow;
05275 }
05276 $prevrow = $startrow - $maxentries;
05277 if ($prevrow < 0)
05278 {
05279 $prevrow = 0;
05280 }
05281 return array(
05282 "rows" => $rows,
05283 "images" => $images,
05284 "startrow" => $startrow,
05285 "nextrow" => $nextrow,
05286 "prevrow" => $prevrow,
05287 "step" => $maxentries,
05288 "rowcount" => $max
05289 );
05290 }
05291
05301 function _getTestType($active_id)
05302 {
05303 global $ilDB;
05304
05305 $result = "";
05306 $query = sprintf("SELECT tst_test_type.type_tag FROM tst_test_type, tst_tests, tst_active WHERE tst_test_type.test_type_id = tst_tests.test_type_fi AND tst_tests.test_id = tst_active.test_fi AND tst_active.active_id = %s",
05307 $ilDB->quote($active_id . "")
05308 );
05309 $query_result = $ilDB->query($query);
05310 if ($query_result->numRows())
05311 {
05312 $row = $query_result->fetchRow(DB_FETCHMODE_ASSOC);
05313 $result = $row["type_tag"];
05314 }
05315 return $result;
05316 }
05317
05326 function &_getQuestiontypes()
05327 {
05328 global $ilDB;
05329
05330 $questiontypes = array();
05331 $query = "SELECT * FROM qpl_question_type ORDER BY type_tag";
05332 $query_result = $ilDB->query($query);
05333 while ($row = $query_result->fetchRow(DB_FETCHMODE_ASSOC))
05334 {
05335 $questiontypes[$this->lng->txt($row["type_tag"])] = $row;
05336 }
05337 ksort($questiontypes);
05338 return $questiontypes;
05339 }
05340
05349 function fromXML(&$assessment)
05350 {
05351 unset($_SESSION["import_mob_xhtml"]);
05352
05353 $this->setDescription($assessment->getComment());
05354 $this->setTitle($assessment->getTitle());
05355
05356 foreach ($assessment->objectives as $objectives)
05357 {
05358 foreach ($objectives->materials as $material)
05359 {
05360 $this->setIntroduction($this->QTIMaterialToString($material));
05361 }
05362 }
05363 foreach ($assessment->assessmentcontrol as $assessmentcontrol)
05364 {
05365 switch ($assessmentcontrol->getSolutionswitch())
05366 {
05367 case "Yes":
05368 $this->setInstantVerification(1);
05369 break;
05370 default:
05371 $this->setInstantVerification(0);
05372 break;
05373 }
05374 }
05375
05376 foreach ($assessment->qtimetadata as $metadata)
05377 {
05378 switch ($metadata["label"])
05379 {
05380 case "test_type":
05381 $this->setTestType($metadata["entry"]);
05382 break;
05383 case "sequence_settings":
05384 $this->setSequenceSettings($metadata["entry"]);
05385 break;
05386 case "author":
05387 $this->setAuthor($metadata["entry"]);
05388 break;
05389 case "nr_of_tries":
05390 $this->setNrOfTries($metadata["entry"]);
05391 break;
05392 case "hide_previous_results":
05393 $this->setHidePreviousResults($metadata["entry"]);
05394 break;
05395 case "hide_title_points":
05396 $this->setHideTitlePoints($metadata["entry"]);
05397 break;
05398 case "random_test":
05399 $this->setRandomTest($metadata["entry"]);
05400 break;
05401 case "random_question_count":
05402 $this->setRandomQuestionCount($metadata["entry"]);
05403 break;
05404 case "show_solution_details":
05405 $this->setShowSolutionDetails($metadata["entry"]);
05406 break;
05407 case "instant_verification":
05408 $this->setInstantVerification($metadata["entry"]);
05409 break;
05410 case "show_solution_printview":
05411 $this->setShowSolutionPrintview($metadata["entry"]);
05412 break;
05413 case "score_reporting":
05414 $this->setScoreReporting($metadata["entry"]);
05415 break;
05416 case "shuffle_questions":
05417 $this->setShuffleQuestions($metadata["entry"]);
05418 break;
05419 case "count_system":
05420 $this->setCountSystem($metadata["entry"]);
05421 break;
05422 case "mc_scoring":
05423 $this->setMCScoring($metadata["entry"]);
05424 break;
05425 case "score_cutting":
05426 $this->setScoreCutting($metadata["entry"]);
05427 break;
05428 case "password":
05429 $this->setPassword($metadata["entry"]);
05430 break;
05431 case "allowedUsers":
05432 $this->setAllowedUsers($metadata["entry"]);
05433 break;
05434 case "allowedUsersTimeGap":
05435 $this->setAllowedUsersTimeGap($metadata["entry"]);
05436 break;
05437 case "pass_scoring":
05438 $this->setPassScoring($metadata["entry"]);
05439 break;
05440 case "show_summary":
05441 $this->setShowSummary($metadata["entry"]);
05442 break;
05443 case "reporting_date":
05444 $iso8601period = $metadata["entry"];
05445 if (preg_match("/P(\d+)Y(\d+)M(\d+)DT(\d+)H(\d+)M(\d+)S/", $iso8601period, $matches))
05446 {
05447 $this->setReportingDate(sprintf("%02d%02d%02d%02d%02d%02d", $matches[1], $matches[2], $matches[3], $matches[4], $matches[5], $matches[6]));
05448 }
05449 break;
05450 case "starting_time":
05451 $iso8601period = $metadata["entry"];
05452 if (preg_match("/P(\d+)Y(\d+)M(\d+)DT(\d+)H(\d+)M(\d+)S/", $iso8601period, $matches))
05453 {
05454 $this->setStartingTime(sprintf("%02d%02d%02d%02d%02d%02d", $matches[1], $matches[2], $matches[3], $matches[4], $matches[5], $matches[6]));
05455 }
05456 break;
05457 case "ending_time":
05458 $iso8601period = $metadata["entry"];
05459 if (preg_match("/P(\d+)Y(\d+)M(\d+)DT(\d+)H(\d+)M(\d+)S/", $iso8601period, $matches))
05460 {
05461 $this->setEndingTime(sprintf("%02d%02d%02d%02d%02d%02d", $matches[1], $matches[2], $matches[3], $matches[4], $matches[5], $matches[6]));
05462 }
05463 break;
05464 }
05465 if (preg_match("/mark_step_\d+/", $metadata["label"]))
05466 {
05467 $xmlmark = $metadata["entry"];
05468 preg_match("/<short>(.*?)<\/short>/", $xmlmark, $matches);
05469 $mark_short = $matches[1];
05470 preg_match("/<official>(.*?)<\/official>/", $xmlmark, $matches);
05471 $mark_official = $matches[1];
05472 preg_match("/<percentage>(.*?)<\/percentage>/", $xmlmark, $matches);
05473 $mark_percentage = $matches[1];
05474 preg_match("/<passed>(.*?)<\/passed>/", $xmlmark, $matches);
05475 $mark_passed = $matches[1];
05476 $this->mark_schema->addMarkStep($mark_short, $mark_official, $mark_percentage, $mark_passed);
05477 }
05478 }
05479
05480 if (is_array($_SESSION["import_mob_xhtml"]))
05481 {
05482 include_once "./content/classes/Media/class.ilObjMediaObject.php";
05483 include_once "./Services/RTE/classes/class.ilRTE.php";
05484 include_once "./assessment/classes/class.ilObjQuestionPool.php";
05485 foreach ($_SESSION["import_mob_xhtml"] as $mob)
05486 {
05487 $importfile = $this->getImportDirectory() . "/" . $_SESSION["tst_import_subdir"] . "/" . $mob["uri"];
05488 if (file_exists($importfile))
05489 {
05490 $media_object =& ilObjMediaObject::_saveTempFileAsMediaObject(basename($importfile), $importfile, FALSE);
05491 ilObjMediaObject::_saveUsage($media_object->getId(), "tst:html", $this->getId());
05492 $this->setIntroduction(ilRTE::_replaceMediaObjectImageSrc(str_replace("src=\"" . $mob["mob"] . "\"", "src=\"" . "il_" . IL_INST_ID . "_mob_" . $media_object->getId() . "\"", $this->getIntroduction()), 1));
05493 }
05494 else
05495 {
05496 global $ilLog;
05497 $ilLog->write("Error: Could not open XHTML mob file for test introduction during test import. File $importfile does not exist!");
05498 }
05499 }
05500 $this->saveToDb();
05501 }
05502 }
05503
05512 function to_xml()
05513 {
05514 include_once("./classes/class.ilXmlWriter.php");
05515 $a_xml_writer = new ilXmlWriter;
05516
05517 $a_xml_writer->xmlHeader();
05518 $a_xml_writer->xmlSetDtdDef("<!DOCTYPE questestinterop SYSTEM \"ims_qtiasiv1p2p1.dtd\">");
05519 $a_xml_writer->xmlStartTag("questestinterop");
05520
05521 $attrs = array(
05522 "ident" => "il_".IL_INST_ID."_tst_".$this->getTestId(),
05523 "title" => $this->getTitle()
05524 );
05525 $a_xml_writer->xmlStartTag("assessment", $attrs);
05526
05527 $a_xml_writer->xmlElement("qticomment", NULL, $this->getDescription());
05528
05529
05530 if ($this->enable_processing_time)
05531 {
05532 preg_match("/(\d+):(\d+):(\d+)/", $this->processing_time, $matches);
05533 $a_xml_writer->xmlElement("duration", NULL, sprintf("P0Y0M0DT%dH%dM%dS", $matches[1], $matches[2], $matches[3]));
05534 }
05535
05536
05537 $a_xml_writer->xmlStartTag("qtimetadata");
05538 $a_xml_writer->xmlStartTag("qtimetadatafield");
05539 $a_xml_writer->xmlElement("fieldlabel", NULL, "ILIAS_VERSION");
05540 $a_xml_writer->xmlElement("fieldentry", NULL, $this->ilias->getSetting("ilias_version"));
05541 $a_xml_writer->xmlEndTag("qtimetadatafield");
05542
05543
05544 $a_xml_writer->xmlStartTag("qtimetadatafield");
05545 $a_xml_writer->xmlElement("fieldlabel", NULL, "test_type");
05546 $a_xml_writer->xmlElement("fieldentry", NULL, $this->getTestType());
05547 $a_xml_writer->xmlEndTag("qtimetadatafield");
05548
05549
05550 $a_xml_writer->xmlStartTag("qtimetadatafield");
05551 $a_xml_writer->xmlElement("fieldlabel", NULL, "sequence_settings");
05552 $a_xml_writer->xmlElement("fieldentry", NULL, $this->getSequenceSettings());
05553 $a_xml_writer->xmlEndTag("qtimetadatafield");
05554
05555
05556 $a_xml_writer->xmlStartTag("qtimetadatafield");
05557 $a_xml_writer->xmlElement("fieldlabel", NULL, "author");
05558 $a_xml_writer->xmlElement("fieldentry", NULL, $this->getAuthor());
05559 $a_xml_writer->xmlEndTag("qtimetadatafield");
05560
05561
05562 $a_xml_writer->xmlStartTag("qtimetadatafield");
05563 $a_xml_writer->xmlElement("fieldlabel", NULL, "count_system");
05564 $a_xml_writer->xmlElement("fieldentry", NULL, $this->getCountSystem());
05565 $a_xml_writer->xmlEndTag("qtimetadatafield");
05566
05567
05568 $a_xml_writer->xmlStartTag("qtimetadatafield");
05569 $a_xml_writer->xmlElement("fieldlabel", NULL, "mc_scoring");
05570 $a_xml_writer->xmlElement("fieldentry", NULL, $this->getMCScoring());
05571 $a_xml_writer->xmlEndTag("qtimetadatafield");
05572
05573
05574 $a_xml_writer->xmlStartTag("qtimetadatafield");
05575 $a_xml_writer->xmlElement("fieldlabel", NULL, "score_cutting");
05576 $a_xml_writer->xmlElement("fieldentry", NULL, $this->getScoreCutting());
05577 $a_xml_writer->xmlEndTag("qtimetadatafield");
05578
05579
05580 $a_xml_writer->xmlStartTag("qtimetadatafield");
05581 $a_xml_writer->xmlElement("fieldlabel", NULL, "password");
05582 $a_xml_writer->xmlElement("fieldentry", NULL, $this->getPassword());
05583 $a_xml_writer->xmlEndTag("qtimetadatafield");
05584
05585
05586 $a_xml_writer->xmlStartTag("qtimetadatafield");
05587 $a_xml_writer->xmlElement("fieldlabel", NULL, "allowedUsers");
05588 $a_xml_writer->xmlElement("fieldentry", NULL, $this->getAllowedUsers());
05589 $a_xml_writer->xmlEndTag("qtimetadatafield");
05590
05591
05592 $a_xml_writer->xmlStartTag("qtimetadatafield");
05593 $a_xml_writer->xmlElement("fieldlabel", NULL, "allowedUsersTimeGap");
05594 $a_xml_writer->xmlElement("fieldentry", NULL, $this->getAllowedUsersTimeGap());
05595 $a_xml_writer->xmlEndTag("qtimetadatafield");
05596
05597
05598 $a_xml_writer->xmlStartTag("qtimetadatafield");
05599 $a_xml_writer->xmlElement("fieldlabel", NULL, "pass_scoring");
05600 $a_xml_writer->xmlElement("fieldentry", NULL, $this->getPassScoring());
05601 $a_xml_writer->xmlEndTag("qtimetadatafield");
05602
05603
05604 if ($this->getReportingDate())
05605 {
05606 $a_xml_writer->xmlStartTag("qtimetadatafield");
05607 $a_xml_writer->xmlElement("fieldlabel", NULL, "reporting_date");
05608 preg_match("/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/", $this->reporting_date, $matches);
05609 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("P%dY%dM%dDT%dH%dM%dS", $matches[1], $matches[2], $matches[3], $matches[4], $matches[5], $matches[6]));
05610 $a_xml_writer->xmlEndTag("qtimetadatafield");
05611 }
05612
05613 $a_xml_writer->xmlStartTag("qtimetadatafield");
05614 $a_xml_writer->xmlElement("fieldlabel", NULL, "nr_of_tries");
05615 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getNrOfTries()));
05616 $a_xml_writer->xmlEndTag("qtimetadatafield");
05617
05618
05619 $a_xml_writer->xmlStartTag("qtimetadatafield");
05620 $a_xml_writer->xmlElement("fieldlabel", NULL, "hide_previous_results");
05621 $a_xml_writer->xmlElement("fieldentry", NULL, $this->getHidePreviousResults());
05622 $a_xml_writer->xmlEndTag("qtimetadatafield");
05623
05624
05625 $a_xml_writer->xmlStartTag("qtimetadatafield");
05626 $a_xml_writer->xmlElement("fieldlabel", NULL, "hide_title_points");
05627 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getHideTitlePoints()));
05628 $a_xml_writer->xmlEndTag("qtimetadatafield");
05629
05630
05631 $a_xml_writer->xmlStartTag("qtimetadatafield");
05632 $a_xml_writer->xmlElement("fieldlabel", NULL, "random_test");
05633 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->isRandomTest()));
05634 $a_xml_writer->xmlEndTag("qtimetadatafield");
05635
05636
05637 $a_xml_writer->xmlStartTag("qtimetadatafield");
05638 $a_xml_writer->xmlElement("fieldlabel", NULL, "random_question_count");
05639 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getRandomQuestionCount()));
05640 $a_xml_writer->xmlEndTag("qtimetadatafield");
05641
05642
05643 $a_xml_writer->xmlStartTag("qtimetadatafield");
05644 $a_xml_writer->xmlElement("fieldlabel", NULL, "show_solution_details");
05645 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getShowSolutionDetails()));
05646 $a_xml_writer->xmlEndTag("qtimetadatafield");
05647
05648
05649 $a_xml_writer->xmlStartTag("qtimetadatafield");
05650 $a_xml_writer->xmlElement("fieldlabel", NULL, "show_summary");
05651 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getShowSummary()));
05652 $a_xml_writer->xmlEndTag("qtimetadatafield");
05653
05654
05655 $a_xml_writer->xmlStartTag("qtimetadatafield");
05656 $a_xml_writer->xmlElement("fieldlabel", NULL, "score_reporting");
05657 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getScoreReporting()));
05658 $a_xml_writer->xmlEndTag("qtimetadatafield");
05659
05660
05661 $a_xml_writer->xmlStartTag("qtimetadatafield");
05662 $a_xml_writer->xmlElement("fieldlabel", NULL, "instant_verification");
05663 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getInstantVerification()));
05664 $a_xml_writer->xmlEndTag("qtimetadatafield");
05665
05666
05667 $a_xml_writer->xmlStartTag("qtimetadatafield");
05668 $a_xml_writer->xmlElement("fieldlabel", NULL, "show_solution_printview");
05669 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getShowSolutionPrintview()));
05670 $a_xml_writer->xmlEndTag("qtimetadatafield");
05671
05672
05673 $a_xml_writer->xmlStartTag("qtimetadatafield");
05674 $a_xml_writer->xmlElement("fieldlabel", NULL, "shuffle_questions");
05675 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getShuffleQuestions()));
05676 $a_xml_writer->xmlEndTag("qtimetadatafield");
05677
05678
05679 if ($this->getStartingTime())
05680 {
05681 $a_xml_writer->xmlStartTag("qtimetadatafield");
05682 $a_xml_writer->xmlElement("fieldlabel", NULL, "starting_time");
05683 preg_match("/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/", $this->starting_time, $matches);
05684 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("P%dY%dM%dDT%dH%dM%dS", $matches[1], $matches[2], $matches[3], $matches[4], $matches[5], $matches[6]));
05685 $a_xml_writer->xmlEndTag("qtimetadatafield");
05686 }
05687
05688 if ($this->getEndingTime())
05689 {
05690 $a_xml_writer->xmlStartTag("qtimetadatafield");
05691 $a_xml_writer->xmlElement("fieldlabel", NULL, "ending_time");
05692 preg_match("/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/", $this->ending_time, $matches);
05693 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("P%dY%dM%dDT%dH%dM%dS", $matches[1], $matches[2], $matches[3], $matches[4], $matches[5], $matches[6]));
05694 $a_xml_writer->xmlEndTag("qtimetadatafield");
05695 }
05696 foreach ($this->mark_schema->mark_steps as $index => $mark)
05697 {
05698
05699 $a_xml_writer->xmlStartTag("qtimetadatafield");
05700 $a_xml_writer->xmlElement("fieldlabel", NULL, "mark_step_$index");
05701 $a_xml_writer->xmlElement("fieldentry", NULL, sprintf("<short>%s</short><official>%s</official><percentage>%.2f</percentage><passed>%d</passed>", $mark->getShortName(), $mark->getOfficialName(), $mark->getMinimumLevel(), $mark->getPassed()));
05702 $a_xml_writer->xmlEndTag("qtimetadatafield");
05703 }
05704 $a_xml_writer->xmlEndTag("qtimetadata");
05705
05706
05707 $a_xml_writer->xmlStartTag("objectives");
05708 $this->addQTIMaterial($a_xml_writer, $this->getIntroduction());
05709 $a_xml_writer->xmlEndTag("objectives");
05710
05711
05712 if ($this->getInstantVerification() == 1)
05713 {
05714 $attrs = array(
05715 "solutionswitch" => "Yes"
05716 );
05717 }
05718 else
05719 {
05720 $attrs = NULL;
05721 }
05722 $a_xml_writer->xmlElement("assessmentcontrol", $attrs, NULL);
05723
05724 $attrs = array(
05725 "ident" => "1"
05726 );
05727 $a_xml_writer->xmlElement("section", $attrs, NULL);
05728 $a_xml_writer->xmlEndTag("assessment");
05729 $a_xml_writer->xmlEndTag("questestinterop");
05730
05731 $xml = $a_xml_writer->xmlDumpMem(FALSE);
05732
05733 foreach ($this->questions as $question_id)
05734 {
05735 $question =& ilObjTest::_instanciateQuestion($question_id);
05736 $qti_question = $question->to_xml(false);
05737 $qti_question = preg_replace("/<questestinterop>/", "", $qti_question);
05738 $qti_question = preg_replace("/<\/questestinterop>/", "", $qti_question);
05739 if (strpos($xml, "</section>") !== false)
05740 {
05741 $xml = str_replace("</section>", "$qti_question</section>", $xml);
05742 }
05743 else
05744 {
05745 $xml = str_replace("<section ident=\"1\"/>", "<section ident=\"1\">\n$qti_question</section>", $xml);
05746 }
05747 }
05748 return $xml;
05749 }
05750
05757 function exportPagesXML(&$a_xml_writer, $a_inst, $a_target_dir, &$expLog)
05758 {
05759 global $ilBench;
05760
05761 $this->mob_ids = array();
05762 $this->file_ids = array();
05763
05764 $attrs = array();
05765 $attrs["Type"] = "Test";
05766 $a_xml_writer->xmlStartTag("ContentObject", $attrs);
05767
05768
05769 $this->exportXMLMetaData($a_xml_writer);
05770
05771
05772 $expLog->write(date("[y-m-d H:i:s] ")."Start Export Page Objects");
05773 $ilBench->start("ContentObjectExport", "exportPageObjects");
05774 $this->exportXMLPageObjects($a_xml_writer, $a_inst, $expLog);
05775 $ilBench->stop("ContentObjectExport", "exportPageObjects");
05776 $expLog->write(date("[y-m-d H:i:s] ")."Finished Export Page Objects");
05777
05778
05779 $expLog->write(date("[y-m-d H:i:s] ")."Start Export Media Objects");
05780 $ilBench->start("ContentObjectExport", "exportMediaObjects");
05781 $this->exportXMLMediaObjects($a_xml_writer, $a_inst, $a_target_dir, $expLog);
05782 $ilBench->stop("ContentObjectExport", "exportMediaObjects");
05783 $expLog->write(date("[y-m-d H:i:s] ")."Finished Export Media Objects");
05784
05785
05786 $expLog->write(date("[y-m-d H:i:s] ")."Start Export File Items");
05787 $ilBench->start("ContentObjectExport", "exportFileItems");
05788 $this->exportFileItems($a_target_dir, $expLog);
05789 $ilBench->stop("ContentObjectExport", "exportFileItems");
05790 $expLog->write(date("[y-m-d H:i:s] ")."Finished Export File Items");
05791
05792 $a_xml_writer->xmlEndTag("ContentObject");
05793 }
05794
05801 function exportXMLMetaData(&$a_xml_writer)
05802 {
05803 include_once "./Services/MetaData/classes/class.ilMD2XML.php";
05804 $md2xml = new ilMD2XML($this->getId(), 0, $this->getType());
05805 $md2xml->setExportMode(true);
05806 $md2xml->startExport();
05807 $a_xml_writer->appendXML($md2xml->getXML());
05808 }
05809
05817 function modifyExportIdentifier($a_tag, $a_param, $a_value)
05818 {
05819 if ($a_tag == "Identifier" && $a_param == "Entry")
05820 {
05821 include_once "./classes/class.ilUtil.php";
05822 $a_value = ilUtil::insertInstIntoID($a_value);
05823 }
05824
05825 return $a_value;
05826 }
05827
05828
05835 function exportXMLPageObjects(&$a_xml_writer, $a_inst, &$expLog)
05836 {
05837 global $ilBench;
05838
05839 include_once "./content/classes/class.ilLMPageObject.php";
05840
05841 foreach ($this->questions as $question_id)
05842 {
05843 $ilBench->start("ContentObjectExport", "exportPageObject");
05844 $expLog->write(date("[y-m-d H:i:s] ")."Page Object ".$question_id);
05845
05846 $attrs = array();
05847 $a_xml_writer->xmlStartTag("PageObject", $attrs);
05848
05849
05850
05851 $ilBench->start("ContentObjectExport", "exportPageObject_XML");
05852 $page_object = new ilPageObject("qpl", $question_id);
05853 $page_object->buildDom();
05854 $page_object->insertInstIntoIDs($a_inst);
05855 $mob_ids = $page_object->collectMediaObjects(false);
05856 $file_ids = $page_object->collectFileItems();
05857 $xml = $page_object->getXMLFromDom(false, false, false, "", true);
05858 $xml = str_replace("&","&", $xml);
05859 $a_xml_writer->appendXML($xml);
05860 $page_object->freeDom();
05861 unset ($page_object);
05862
05863 $ilBench->stop("ContentObjectExport", "exportPageObject_XML");
05864
05865
05866 $ilBench->start("ContentObjectExport", "exportPageObject_CollectMedia");
05867
05868 foreach($mob_ids as $mob_id)
05869 {
05870 $this->mob_ids[$mob_id] = $mob_id;
05871 }
05872 $ilBench->stop("ContentObjectExport", "exportPageObject_CollectMedia");
05873
05874
05875 $ilBench->start("ContentObjectExport", "exportPageObject_CollectFileItems");
05876
05877 foreach($file_ids as $file_id)
05878 {
05879 $this->file_ids[$file_id] = $file_id;
05880 }
05881 $ilBench->stop("ContentObjectExport", "exportPageObject_CollectFileItems");
05882
05883 $a_xml_writer->xmlEndTag("PageObject");
05884
05885
05886 $ilBench->stop("ContentObjectExport", "exportPageObject");
05887
05888
05889 }
05890 }
05891
05898 function exportXMLMediaObjects(&$a_xml_writer, $a_inst, $a_target_dir, &$expLog)
05899 {
05900 include_once "./content/classes/Media/class.ilObjMediaObject.php";
05901
05902 foreach ($this->mob_ids as $mob_id)
05903 {
05904 $expLog->write(date("[y-m-d H:i:s] ")."Media Object ".$mob_id);
05905 $media_obj = new ilObjMediaObject($mob_id);
05906 $media_obj->exportXML($a_xml_writer, $a_inst);
05907 $media_obj->exportFiles($a_target_dir);
05908 unset($media_obj);
05909 }
05910 }
05911
05916 function exportFileItems($a_target_dir, &$expLog)
05917 {
05918 include_once "./classes/class.ilObjFile.php";
05919
05920 foreach ($this->file_ids as $file_id)
05921 {
05922 $expLog->write(date("[y-m-d H:i:s] ")."File Item ".$file_id);
05923 $file_obj = new ilObjFile($file_id, false);
05924 $file_obj->export($a_target_dir);
05925 unset($file_obj);
05926 }
05927 }
05928
05933 function getImportMapping()
05934 {
05935 if (!is_array($this->import_mapping))
05936 {
05937 return array();
05938 }
05939 else
05940 {
05941 return $this->import_mapping;
05942 }
05943 }
05944
05955 function getECTSGrade($reached_points, $max_points)
05956 {
05957 $passed_array =& $this->getTotalPointsPassedArray();
05958 return ilObjTest::_getECTSGrade($passed_array, $reached_points, $max_points, $this->ects_grades["A"], $this->ects_grades["B"], $this->ects_grades["C"], $this->ects_grades["D"], $this->ects_grades["E"], $this->ects_fx);
05959 }
05960
05971 function _getECTSGrade($points_passed, $reached_points, $max_points, $a, $b, $c, $d, $e, $fx)
05972 {
05973 include_once "./classes/class.ilStatistics.php";
05974
05975 $passed_statistics = new ilStatistics();
05976 $passed_statistics->setData($points_passed);
05977 $ects_percentiles = array
05978 (
05979 "A" => $passed_statistics->quantile($a),
05980 "B" => $passed_statistics->quantile($b),
05981 "C" => $passed_statistics->quantile($c),
05982 "D" => $passed_statistics->quantile($d),
05983 "E" => $passed_statistics->quantile($e)
05984 );
05985 if (count($passed_array) && ($reached_points >= $ects_percentiles["A"]))
05986 {
05987 return "A";
05988 }
05989 else if (count($passed_array) && ($reached_points >= $ects_percentiles["B"]))
05990 {
05991 return "B";
05992 }
05993 else if (count($passed_array) && ($reached_points >= $ects_percentiles["C"]))
05994 {
05995 return "C";
05996 }
05997 else if (count($passed_array) && ($reached_points >= $ects_percentiles["D"]))
05998 {
05999 return "D";
06000 }
06001 else if (count($passed_array) && ($reached_points >= $ects_percentiles["E"]))
06002 {
06003 return "E";
06004 }
06005 else if (strcmp($fx, "") != 0)
06006 {
06007 if ($max_points > 0)
06008 {
06009 $percentage = ($reached_points / $max_points) * 100.0;
06010 if ($percentage < 0) $percentage = 0.0;
06011 }
06012 else
06013 {
06014 $percentage = 0.0;
06015 }
06016 if ($percentage >= $fx)
06017 {
06018 return "FX";
06019 }
06020 else
06021 {
06022 return "F";
06023 }
06024 }
06025 else
06026 {
06027 return "F";
06028 }
06029 }
06030
06031 function checkMarks()
06032 {
06033 return $this->mark_schema->checkMarks();
06034 }
06035
06036 function updateMetaData()
06037 {
06038 global $ilUser;
06039 include_once "./Services/MetaData/classes/class.ilMD.php";
06040 $md =& new ilMD($this->getId(), 0, $this->getType());
06041 $md_gen =& $md->getGeneral();
06042 if ($md_gen == false)
06043 {
06044 include_once "./Services/MetaData/classes/class.ilMDCreator.php";
06045 $md_creator = new ilMDCreator($this->getId(),0,$this->getType());
06046 $md_creator->setTitle($this->getTitle());
06047 $md_creator->setTitleLanguage($ilUser->getPref('language'));
06048 $md_creator->create();
06049 }
06050 parent::updateMetaData();
06051 }
06052
06061 function &_getAvailableTests($use_object_id = false)
06062 {
06063 global $rbacsystem;
06064 global $ilDB;
06065
06066 $result_array = array();
06067 $query = "SELECT object_data.*, object_data.obj_id, object_reference.ref_id FROM object_data, object_reference WHERE object_data.obj_id = object_reference.obj_id AND object_data.type = 'tst' ORDER BY object_data.title";
06068 $result = $ilDB->query($query);
06069 include_once "./classes/class.ilObject.php";
06070 while ($row = $result->fetchRow(DB_FETCHMODE_OBJECT))
06071 {
06072 if ($rbacsystem->checkAccess("write", $row->ref_id) && (ilObject::_hasUntrashedReference($row->obj_id)))
06073 {
06074 if ($use_object_id)
06075 {
06076 $result_array[$row->obj_id] = $row->title;
06077 }
06078 else
06079 {
06080 $result_array[$row->ref_id] = $row->title;
06081 }
06082 }
06083 }
06084 return $result_array;
06085 }
06086
06095 function cloneRandomQuestions($new_id)
06096 {
06097 global $ilDB;
06098
06099 if ($new_id > 0)
06100 {
06101 $query = sprintf("SELECT * FROM tst_test_random WHERE test_fi = %s",
06102 $ilDB->quote($this->getTestId() . "")
06103 );
06104 $result = $ilDB->query($query);
06105 if ($result->numRows())
06106 {
06107 while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC))
06108 {
06109 $query = sprintf("INSERT INTO tst_test_random (test_random_id, test_fi, questionpool_fi, num_of_q, TIMESTAMP) VALUES (NULL, %s, %s, %s, NULL)",
06110 $ilDB->quote($new_id . ""),
06111 $ilDB->quote($row["questionpool_fi"] . ""),
06112 $ilDB->quote($row["num_of_q"] . "")
06113 );
06114 $insertresult = $ilDB->query($query);
06115 }
06116 }
06117 }
06118 }
06119
06120
06128 function _clone($obj_id)
06129 {
06130 $original = new ilObjTest($obj_id, false);
06131 $original->loadFromDb();
06132
06133 $newObj = new ilObjTest();
06134 $newObj->setType("tst");
06135 $counter = 2;
06136 while ($newObj->testTitleExists($newObj->getTitle() . " ($counter)"))
06137 {
06138 $counter++;
06139 }
06140 $newObj->setAuthor($original->getAuthor());
06141 $newObj->setHideTitlePoints($original->getHideTitlePoints());
06142 $newObj->setPassScoring($original->getPassScoring());
06143 $newObj->setTitle($original->getTitle() . " ($counter)");
06144 $newObj->setDescription($original->getDescription());
06145 $newObj->create(true);
06146 $newObj->createReference();
06147 $newObj->putInTree($_GET["ref_id"]);
06148 $newObj->setPermissions($_GET["ref_id"]);
06149 $newObj->author = $original->getAuthor();
06150 $newObj->introduction = $original->getIntroduction();
06151 $newObj->mark_schema = $original->mark_schema;
06152 $newObj->sequence_settings = $original->getSequenceSettings();
06153 $newObj->score_reporting = $original->getScoreReporting();
06154 $newObj->instant_verification = $original->getInstantVerification();
06155 $newObj->reporting_date = $original->getReportingDate();
06156 $newObj->test_type = $original->getTestType();
06157 $newObj->nr_of_tries = $original->getNrOfTries();
06158 $newObj->setHidePreviousResults($original->getHidePreviousResults());
06159 $newObj->processing_time = $original->getProcessingTime();
06160 $newObj->enable_processing_time = $original->getEnableProcessingTime();
06161 $newObj->starting_time = $original->getStartingTime();
06162 $newObj->ending_time = $original->getEndingTime();
06163 $newObj->ects_output = $original->ects_output;
06164 $newObj->ects_fx = $original->ects_fx;
06165 $newObj->ects_grades = $original->ects_grades;
06166 $newObj->random_test = $original->random_test;
06167 $newObj->random_question_count = $original->random_question_count;
06168 $newObj->setCountSystem($original->getCountSystem());
06169 $newObj->setMCScoring($original->getMCScoring());
06170 $newObj->saveToDb();
06171 if ($original->isRandomTest())
06172 {
06173 $newObj->saveRandomQuestionCount($newObj->random_question_count);
06174 $original->cloneRandomQuestions($newObj->getTestId());
06175 }
06176 else
06177 {
06178
06179 include_once "./assessment/classes/class.assQuestion.php";
06180 foreach ($original->questions as $key => $question_id)
06181 {
06182 $question = ilObjTest::_instanciateQuestion($question_id);
06183 $newObj->questions[$key] = $question->duplicate();
06184
06185 $original_id = assQuestion::_getOriginalId($question_id);
06186 $question = ilObjTest::_instanciateQuestion($newObj->questions[$key]);
06187 $question->saveToDb($original_id);
06188 }
06189 }
06190
06191 $newObj->saveToDb();
06192
06193
06194 include_once "./Services/MetaData/classes/class.ilMD.php";
06195 $md = new ilMD($original->getId(),0,$original->getType());
06196 $new_md =& $md->cloneMD($newObj->getId(),0,$newObj->getType());
06197 return $newObj->getRefId();
06198 }
06199
06200 function _getRefIdFromObjId($obj_id)
06201 {
06202 global $ilDB;
06203
06204 $query = sprintf("SELECT ref_id FROM object_reference WHERE obj_id=%s",
06205 $ilDB->quote($obj_id)
06206
06207 );
06208 $result = $ilDB->query($query);
06209 if ($result->numRows())
06210 {
06211 $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
06212 return $row["ref_id"];
06213 }
06214 return 0;
06215 }
06216
06224 function &getEvaluationUsers($user_id, $sort_name_option = "asc")
06225 {
06226 global $ilDB;
06227
06228 $users = array();
06229 $query = sprintf("SELECT tst_eval_users.user_fi, usr_data.firstname, usr_data.lastname FROM tst_eval_users, usr_data WHERE tst_eval_users.test_fi = %s AND tst_eval_users.evaluator_fi = %s AND tst_eval_users.user_fi = usr_data.usr_id ORDER BY usr_data.lastname " . strtoupper($sort_name_option),
06230 $ilDB->quote($this->getTestId() . ""),
06231 $ilDB->quote($user_id . "")
06232 );
06233 $result = $ilDB->query($query);
06234 if ($result->numRows())
06235 {
06236 while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC))
06237 {
06238 $name = trim($row["lastname"] . ", " . $row["firstname"] ." " . $row["title"]);
06239 if ($this->getTestType() == TYPE_SELF_ASSESSMENT)
06240 {
06241 $name = $this->lng->txt("anonymous");
06242 }
06243 $users[$row["user_fi"]] = $name;
06244 }
06245 }
06246 return $users;
06247 }
06248
06256 function &getEvaluationParticipants($user_id, $sort_name_option = "asc")
06257 {
06258 global $ilDB;
06259
06260 $users = array();
06261 $query = sprintf("SELECT tst_eval_users.user_fi, usr_data.firstname, usr_data.lastname FROM tst_eval_users, usr_data WHERE tst_eval_users.test_fi = %s AND tst_eval_users.evaluator_fi = %s AND tst_eval_users.user_fi = usr_data.usr_id ORDER BY usr_data.lastname " . strtoupper($sort_name_option),
06262 $ilDB->quote($this->getTestId() . ""),
06263 $ilDB->quote($user_id . "")
06264 );
06265 $result = $ilDB->query($query);
06266 if ($result->numRows())
06267 {
06268 while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC))
06269 {
06270 $active = $this->getActiveTestUser($row["user_fi"]);
06271 if (is_object($active))
06272 {
06273 $name = trim($row["lastname"] . ", " . $row["firstname"] ." " . $row["title"]);
06274 if ($this->getTestType() == TYPE_SELF_ASSESSMENT)
06275 {
06276 $name = $this->lng->txt("anonymous");
06277 }
06278 $users[$active->active_id] = $name;
06279 }
06280 }
06281 }
06282 return $users;
06283 }
06284
06293 function removeSelectedUser($user_id, $evaluator_id)
06294 {
06295 global $ilDB;
06296
06297 $query = sprintf("DELETE FROM tst_eval_users WHERE test_fi = %s AND user_fi = %s AND evaluator_fi = %s",
06298 $ilDB->quote($this->getTestId() . ""),
06299 $ilDB->quote($user_id . ""),
06300 $ilDB->quote($evaluator_id . "")
06301 );
06302 $result = $ilDB->query($query);
06303 }
06304
06313 function addSelectedUser($user_id, $evaluator_id)
06314 {
06315 global $ilDB;
06316
06317 $query = sprintf("SELECT user_fi FROM tst_active WHERE test_fi = %s AND user_fi = %s",
06318 $ilDB->quote($this->getTestId() . ""),
06319 $ilDB->quote($user_id . "")
06320 );
06321 $result = $ilDB->query($query);
06322 if ($result->numRows() == 1)
06323 {
06324 $query = sprintf("REPLACE INTO tst_eval_users (test_fi, evaluator_fi, user_fi) VALUES (%s, %s, %s)",
06325 $ilDB->quote($this->getTestId() . ""),
06326 $ilDB->quote($evaluator_id . ""),
06327 $ilDB->quote($user_id . "")
06328 );
06329 $result = $ilDB->query($query);
06330 }
06331 }
06332
06341 function addSelectedGroup($group_id, $evaluator_id)
06342 {
06343 include_once "./classes/class.ilObjGroup.php";
06344 $group = new ilObjGroup($group_id);
06345 $members = $group->getGroupMemberIds();
06346 foreach ($members as $user_id)
06347 {
06348 $this->addSelectedUser($user_id, $evaluator_id);
06349 }
06350 }
06351
06360 function addSelectedRole($role_id, $evaluator_id)
06361 {
06362 global $rbacreview;
06363 $members = $rbacreview->assignedUsers($role_id,"usr_id");
06364 foreach ($members as $user_id)
06365 {
06366 $this->addSelectedUser($user_id, $evaluator_id);
06367 }
06368 }
06369
06378 function getQuestionCount()
06379 {
06380 $num = 0;
06381
06382 if ($this->isRandomTest())
06383 {
06384 if ($this->getRandomQuestionCount())
06385 {
06386 $num = $this->getRandomQuestionCount();
06387 $qpls =& $this->getRandomQuestionpools();
06388 $maxcount = 0;
06389 foreach ($qpls as $data)
06390 {
06391 $maxcount += $data["contains"];
06392 }
06393 if ($num > $maxcount) $num = $maxcount;
06394 }
06395 else
06396 {
06397 $qpls =& $this->getRandomQuestionpools();
06398 foreach ($qpls as $data)
06399 {
06400 $add = ($data["count"] <= $data["contains"]) ? $data["count"] : $data["contains"];
06401 $num += $add;
06402 }
06403 }
06404 }
06405 else
06406 {
06407 $num = count($this->questions);
06408 }
06409 return $num;
06410 }
06411
06420 function _getQuestionCount($test_id)
06421 {
06422 global $ilDB;
06423
06424 $num = 0;
06425
06426 $query = sprintf("SELECT * FROM tst_tests WHERE test_id = %s",
06427 $ilDB->quote($test_id . "")
06428 );
06429 $result = $ilDB->query($query);
06430 if (!$result->numRows())
06431 {
06432 return 0;
06433 }
06434 $test = $result->fetchRow(DB_FETCHMODE_ASSOC);
06435
06436 if ($test["random_test"] == 1)
06437 {
06438 $qpls = array();
06439 $counter = 0;
06440 $query = sprintf("SELECT * FROM tst_test_random WHERE test_fi = %s ORDER BY test_random_id",
06441 $ilDB->quote($test_id . "")
06442 );
06443 $result = $ilDB->query($query);
06444 if ($result->numRows())
06445 {
06446 while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC))
06447 {
06448 $countquery = sprintf("SELECT question_id FROM qpl_questions WHERE obj_fi = %s AND original_id IS NULL",
06449 $ilDB->quote($row["questionpool_fi"] . "")
06450 );
06451 $countresult = $ilDB->query($countquery);
06452 $contains = $countresult->numRows();
06453 $qpls[$counter] = array(
06454 "index" => $counter,
06455 "count" => $row["num_of_q"],
06456 "qpl" => $row["questionpool_fi"],
06457 "contains" => $contains
06458 );
06459 $counter++;
06460 }
06461 }
06462 if ($test["random_question_count"] > 0)
06463 {
06464 $num = $test["random_question_count"];
06465 $maxcount = 0;
06466 foreach ($qpls as $data)
06467 {
06468 $maxcount += $data["contains"];
06469 }
06470 if ($num > $maxcount) $num = $maxcount;
06471 }
06472 else
06473 {
06474 $num = 0;
06475 foreach ($qpls as $data)
06476 {
06477 $add = ($data["count"] <= $data["contains"]) ? $data["count"] : $data["contains"];
06478 $num += $add;
06479 }
06480 }
06481 }
06482 else
06483 {
06484 $query = sprintf("SELECT test_question_id FROM tst_test_question WHERE test_fi = %s",
06485 $ilDB->quote($test_id . "")
06486 );
06487 $result = $ilDB->query($query);
06488 $num = $result->numRows();
06489 }
06490 return $num;
06491 }
06492
06493
06501 function removeNonRandomTestData()
06502 {
06503 global $ilDB;
06504
06505
06506 $this->removeAllTestEditings();
06507 $query = sprintf("DELETE FROM tst_test_question WHERE test_fi = %s",
06508 $ilDB->quote($this->getTestId())
06509 );
06510 $result = $ilDB->query($query);
06511 $this->questions = array();
06512 $this->saveCompleteStatus();
06513 }
06514
06522 function removeRandomTestData()
06523 {
06524 global $ilDB;
06525
06526 $this->removeAllTestEditings();
06527 $query = sprintf("DELETE FROM tst_test_random WHERE test_fi = %s",
06528 $ilDB->quote($this->getTestId())
06529 );
06530 $result = $ilDB->query($query);
06531 $this->questions = array();
06532 $this->saveCompleteStatus();
06533 }
06534
06544 function logAction($logtext = "", $question_id = "")
06545 {
06546 global $ilUser;
06547
06548 $original_id = "";
06549 if (strcmp($question_id, "") != 0)
06550 {
06551 include_once "./assessment/classes/class.assQuestion.php";
06552 $original_id = assQuestion::_getOriginalId($question_id);
06553 }
06554 include_once "./classes/class.ilObjAssessmentFolder.php";
06555 ilObjAssessmentFolder::_addLog($ilUser->id, $this->getId(), $logtext, $question_id, $original_id, TRUE, $this->getRefId());
06556 }
06557
06567 function _getObjectIDFromTestID($test_id)
06568 {
06569 global $ilDB;
06570 $object_id = FALSE;
06571 $query = sprintf("SELECT obj_fi FROM tst_tests WHERE test_id = %s",
06572 $ilDB->quote($test_id . "")
06573 );
06574 $result = $ilDB->query($query);
06575 if ($result->numRows())
06576 {
06577 $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
06578 $object_id = $row["obj_fi"];
06579 }
06580 return $object_id;
06581 }
06582
06592 function _getObjectIDFromActiveID($active_id)
06593 {
06594 global $ilDB;
06595 $object_id = FALSE;
06596 $query = sprintf("SELECT tst_tests.obj_fi FROM tst_tests, tst_active WHERE tst_tests.test_id = tst_active.test_fi AND tst_active.active_id = %s",
06597 $ilDB->quote($active_id . "")
06598 );
06599 $result = $ilDB->query($query);
06600 if ($result->numRows())
06601 {
06602 $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
06603 $object_id = $row["obj_fi"];
06604 }
06605 return $object_id;
06606 }
06607
06617 function _getTestIDFromObjectID($object_id)
06618 {
06619 global $ilDB;
06620 $test_id = FALSE;
06621 $query = sprintf("SELECT test_id FROM tst_tests WHERE obj_fi = %s",
06622 $ilDB->quote($object_id . "")
06623 );
06624 $result = $ilDB->query($query);
06625 if ($result->numRows())
06626 {
06627 $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
06628 $test_id = $row["test_id"];
06629 }
06630 return $test_id;
06631 }
06632
06643 function getTextAnswer($active_id, $question_id, $pass = NULL)
06644 {
06645 global $ilDB;
06646
06647 $res = "";
06648 if (($active_id) && ($question_id))
06649 {
06650 if (is_null($pass))
06651 {
06652 include_once "./assessment/classes/class.assQuestion.php";
06653 $pass = assQuestion::_getSolutionMaxPass($question_id, $active_id);
06654 }
06655 $query = sprintf("SELECT value1 FROM tst_solutions WHERE active_fi = %s AND question_fi = %s AND pass = %s",
06656 $ilDB->quote($active_id . ""),
06657 $ilDB->quote($question_id . ""),
06658 $ilDB->quote($pass . "")
06659 );
06660 $result = $ilDB->query($query);
06661 if ($result->numRows() == 1)
06662 {
06663 $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
06664 $res = $row["value1"];
06665 }
06666 }
06667 return $res;
06668 }
06669
06679 function getQuestiontext($question_id)
06680 {
06681 global $ilDB;
06682
06683 $res = "";
06684 if ($question_id)
06685 {
06686 $query = sprintf("SELECT question_text FROM qpl_questions WHERE question_id = %s",
06687 $ilDB->quote($question_id . "")
06688 );
06689 $result = $ilDB->query($query);
06690 if ($result->numRows() == 1)
06691 {
06692 $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
06693 $res = $row["question_text"];
06694 }
06695 }
06696 return $res;
06697 }
06698
06707 function &getInvitedUsers($user_id="", $order="login, lastname, firstname")
06708 {
06709 global $ilDB;
06710
06711 $result_array = array();
06712
06713 if (is_numeric($user_id))
06714 {
06715 $query = sprintf("SELECT usr_id, login, lastname, firstname, tst_invited_user.clientip, " .
06716 "tst_active.submitted as test_finished, matriculation, IF(tst_active.active_id IS NULL,0,1) as test_started " .
06717 "FROM usr_data, tst_invited_user " .
06718 "LEFT JOIN tst_active ON tst_active.user_fi = tst_invited_user.user_fi AND tst_active.test_fi = tst_invited_user.test_fi " .
06719 "WHERE tst_invited_user.test_fi = %s and tst_invited_user.user_fi=usr_data.usr_id AND usr_data.usr_id=%s " .
06720 "ORDER BY %s",
06721 $ilDB->quote($this->test_id),
06722 $user_id,
06723 $order
06724 );
06725
06726
06727
06728
06729
06730
06731
06732
06733
06734
06735 }
06736 else
06737 {
06738 $query = sprintf("SELECT usr_id, login, lastname, firstname, tst_invited_user.clientip, " .
06739 "tst_active.submitted as test_finished, matriculation, IF(tst_active.active_id IS NULL,0,1) as test_started " .
06740 "FROM usr_data, tst_invited_user " .
06741 "LEFT JOIN tst_active ON tst_active.user_fi = tst_invited_user.user_fi AND tst_active.test_fi = tst_invited_user.test_fi " .
06742 "WHERE tst_invited_user.test_fi = %s and tst_invited_user.user_fi=usr_data.usr_id " .
06743 "ORDER BY %s",
06744 $ilDB->quote($this->test_id),
06745 $order
06746 );
06747
06748
06749
06750
06751
06752
06753
06754
06755
06756 }
06757
06758 return $this->getArrayData($query, "usr_id");
06759 }
06760
06770 function &getUserData($ids)
06771 {
06772 if (!is_array($ids) || count($ids) ==0)
06773 return array();
06774
06775 $result_array = array();
06776
06777 $query = sprintf("SELECT usr_id, login, lastname, firstname, client_ip as clientip FROM usr_data WHERE usr_id IN (%s) ORDER BY login",
06778 join ($ids,",")
06779 );
06780
06781 return $this->getArrayData ($query, "usr_id");
06782 }
06783
06794 function &getArrayData($query, $id_field)
06795 {
06796 return ilObjTest::_getArrayData ($query, $id_field);
06797 }
06798
06799 function &_getArrayData($query, $id_field)
06800 {
06801 global $ilDB;
06802 $result = $ilDB->query($query);
06803 while ($row = $result->fetchRow(DB_FETCHMODE_OBJECT))
06804 {
06805 $result_array[$row->$id_field]= $row;
06806 }
06807 return ($result_array)?$result_array:array();
06808 }
06809
06810 function &getGroupData($ids)
06811 {
06812 if (!is_array($ids) || count($ids) ==0)
06813 return array();
06814
06815 $result_array = array();
06816
06817 $query = sprintf("SELECT ref_id, title, description FROM `grp_data` g, object_data o, object_reference r WHERE o.obj_id=grp_id AND o.obj_id = r.obj_id AND ref_id IN (%s)",
06818 join ($ids,",")
06819 );
06820
06821 return $this->getArrayData ($query, "ref_id");
06822 }
06823
06824 function &getRoleData($ids)
06825 {
06826 if (!is_array($ids) || count($ids) ==0)
06827 return array();
06828
06829 $result_array = array();
06830
06831 $query = sprintf("SELECT obj_id, description, title FROM role_data, object_data o WHERE o.obj_id=role_id AND role_id IN (%s)",
06832 join ($ids,",")
06833 );
06834
06835 return $this->getArrayData ($query, "obj_id");
06836 }
06837
06838
06847 function inviteGroup($group_id)
06848 {
06849 include_once "./classes/class.ilObjGroup.php";
06850 $group = new ilObjGroup($group_id);
06851 $members = $group->getGroupMemberIds();
06852 include_once "./classes/class.ilObjUser.php";
06853 foreach ($members as $user_id)
06854 {
06855 $this->inviteUser($user_id, ilObjUser::_lookupClientIP($user_id));
06856 }
06857 }
06858
06867 function inviteRole($role_id)
06868 {
06869 global $rbacreview;
06870 $members = $rbacreview->assignedUsers($role_id,"usr_id");
06871 include_once "./classes/class.ilObjUser.php";
06872 foreach ($members as $user_id)
06873 {
06874 $this->inviteUser($user_id, ilObjUser::_lookupClientIP($user_id));
06875 }
06876 }
06877
06878
06879
06888 function disinviteUser($user_id)
06889 {
06890 global $ilDB;
06891
06892 $query = sprintf("DELETE FROM tst_invited_user WHERE test_fi = %s AND user_fi = %s",
06893 $ilDB->quote($this->test_id),
06894 $ilDB->quote($user_id)
06895 );
06896 $result = $ilDB->query($query);
06897 }
06898
06907 function inviteUser($user_id, $client_ip="")
06908 {
06909 global $ilDB;
06910
06911 $query = sprintf("INSERT IGNORE INTO tst_invited_user (test_fi, user_fi, clientip) VALUES (%s, %s, %s)",
06912 $ilDB->quote($this->test_id),
06913 $ilDB->quote($user_id),
06914 $ilDB->quote($client_ip)
06915 );
06916
06917 $result = $ilDB->query($query);
06918 }
06919
06920
06921 function setClientIP($user_id, $client_ip)
06922 {
06923 global $ilDB;
06924
06925 $query = sprintf("UPDATE tst_invited_user SET clientip=%s WHERE test_fi=%s and user_fi=%s",
06926 $ilDB->quote($client_ip),
06927 $ilDB->quote($this->test_id),
06928 $ilDB->quote($user_id)
06929 );
06930 $insertresult = $ilDB->query($query);
06931 }
06932
06939 function isOnlineTest()
06940 {
06941 return $this->getTestType()==TYPE_ONLINE_TEST;
06942 }
06943
06949 function _getSolvedQuestions($active_id, $question_fi = null)
06950 {
06951 global $ilDB;
06952 if (is_numeric($question_fi))
06953 $query = sprintf("SELECT question_fi, solved FROM tst_active_qst_sol_settings " .
06954 "WHERE active_fi = %s AND question_fi=%s",
06955 $ilDB->quote($active_id),
06956 $question_fi
06957 );
06958 else $query = sprintf("SELECT question_fi, solved FROM tst_active_qst_sol_settings " .
06959 "WHERE active_fi = %s",
06960 $ilDB->quote($active_id)
06961 );
06962 return ilObjTest::_getArrayData ($query, "question_fi");
06963 }
06964
06965
06969 function setQuestionSetSolved($value, $question_id, $user_id)
06970 {
06971 global $ilDB;
06972
06973 $active = $this->getActiveTestUser($user_id);
06974 $query = sprintf("REPLACE INTO tst_active_qst_sol_settings SET solved=%s, question_fi=%s, active_fi = %s",
06975 $ilDB->quote($value),
06976 $ilDB->quote($question_id),
06977 $ilDB->quote($active->active_id)
06978 );
06979
06980 $ilDB->query($query);
06981 }
06982
06983
06987 function setActiveTestSubmitted($user_id)
06988 {
06989 global $ilDB;
06990
06991 $query = sprintf("UPDATE tst_active SET submitted=1, tries=1, submittimestamp=NOW() WHERE test_fi=%s AND user_fi=%s",
06992 $ilDB->quote($this->test_id),
06993 $ilDB->quote($user_id)
06994 );
06995 $ilDB->query($query);
06996
06997 }
06998
07002 function isActiveTestSubmitted($user_id = null)
07003 {
07004 global $ilUser;
07005 global $ilDB;
07006
07007 if (!is_numeric($user_id))
07008 $user_id = $ilUser->getId();
07009
07010 $query = sprintf("SELECT submitted FROM tst_active WHERE test_fi=%s AND user_fi=%s AND submitted=1",
07011 $ilDB->quote($this->test_id),
07012 $ilDB->quote($user_id)
07013 );
07014 $result = $ilDB->query($query);
07015
07016 return $result->numRows() == 1;
07017
07018 }
07022 function hasNrOfTriesRestriction()
07023 {
07024 return $this->getNrOfTries() != 0;
07025 }
07026
07027
07032 function isNrOfTriesReached($tries)
07033 {
07034 return $tries >= (int) $this->getNrOfTries();
07035 }
07036
07037
07041 function getAllTestResults($participants, $skip_csv = false)
07042 {
07043 $results = array();
07044 $row = array("matriculation" => $this->lng->txt("matriculation"),
07045 "lastname" => $this->lng->txt("lastname"),
07046 "firstname" => $this->lng->txt("firstname"),
07047 "reached_points" => $this->lng->txt("tst_reached_points"),
07048 "max_points" => $this->lng->txt("tst_maximum_points"),
07049 "percent_value" => $this->lng->txt("tst_percent_solved"),
07050 "mark" => $this->lng->txt("tst_mark"),
07051 "ects" => $this->lng->txt("ects_grade"));
07052
07053 $results[] = $row;
07054 foreach ($participants as $user_id => $user_rec)
07055 {
07056 $row = array();
07057 $active = $this->getActiveTestUser($user_id);
07058 $reached_points = 0;
07059 $max_points = 0;
07060
07061 foreach ($this->questions as $value)
07062 {
07063
07064
07065 $question =& ilObjTest::_instanciateQuestion($value);
07066
07067 if (is_object($question))
07068 {
07069 $max_points += $question->getMaximumPoints();
07070 $reached_points += $question->getReachedPoints($active->active_id);
07071 }
07072 }
07073
07074 if ($max_points > 0)
07075 {
07076 $percentvalue = $reached_points / $max_points;
07077 if ($percentvalue < 0) $percentvalue = 0.0;
07078 }
07079 else
07080 {
07081 $percentvalue = 0;
07082 }
07083 $mark_obj = $this->mark_schema->getMatchingMark($percentvalue * 100);
07084 $passed = "";
07085 if ($mark_obj)
07086 {
07087 $mark = $mark_obj->getOfficialName();
07088 $ects_mark = $this->getECTSGrade($reached_points, $max_points);
07089 }
07090
07091 $row = array(
07092 "matriculation" => $user_rec->matriculation,
07093 "lastname" => $user_rec->lastname,
07094 "firstname" => $user_rec->firstname,
07095 "reached_points" => $reached_points,
07096 "max_points" => $max_points,
07097 "percent_value" => $percentvalue,
07098 "mark" => $mark,
07099 "ects" => $ects_mark);
07100 $results[] = $skip_csv == true? $row : $this->processCSVRow ($row, true);
07101 }
07102 return $results;
07103 }
07104
07117 function &processCSVRow($row, $quoteAll = FALSE, $separator = ";")
07118 {
07119 $resultarray = array();
07120 foreach ($row as $rowindex => $entry)
07121 {
07122 $surround = FALSE;
07123 if ($quoteAll)
07124 {
07125 $surround = TRUE;
07126 }
07127 if (strpos($entry, "\"") !== FALSE)
07128 {
07129 $entry = str_replace("\"", "\"\"", $entry);
07130 $surround = TRUE;
07131 }
07132 if (strpos($entry, $separator) !== FALSE)
07133 {
07134 $surround = TRUE;
07135 }
07136
07137 $entry = str_replace(chr(13).chr(10), chr(10), $entry);
07138 if ($surround)
07139 {
07140 $resultarray[$rowindex] = utf8_decode("\"" . $entry . "\"");
07141 }
07142 else
07143 {
07144 $resultarray[$rowindex] = utf8_decode($entry);
07145 }
07146 }
07147 return $resultarray;
07148 }
07149
07160 function _getPass($active_id)
07161 {
07162 global $ilDB;
07163 $query = sprintf("SELECT tries FROM tst_active WHERE active_id = %s",
07164 $ilDB->quote($active_id . "")
07165 );
07166 $result = $ilDB->query($query);
07167 if ($result->numRows())
07168 {
07169 $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
07170 return $row["tries"];
07171 }
07172 else
07173 {
07174 return 0;
07175 }
07176 }
07177
07188 function _getBestPass($active_id)
07189 {
07190 global $ilDB;
07191 $query = sprintf("SELECT test_fi FROM tst_active WHERE active_id = %s",
07192 $ilDB->quote($active_id . "")
07193 );
07194 $result = $ilDB->query($query);
07195 if ($result->numRows())
07196 {
07197 $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
07198 $test_id = $row["test_fi"];
07199 $results =& ilObjTest::_getCompleteEvaluationData($test_id, FALSE, $active_id);
07200 $participant =& $results->getParticipant($active_id);
07201 if ($participant != null)
07202 {
07203 return $participant->getBestPass();
07204 }
07205 else
07206 {
07207 return 0;
07208 }
07209 }
07210 else
07211 {
07212 return 0;
07213 }
07214 }
07215
07226 function _getResultPass($active_id)
07227 {
07228 $counted_pass = NULL;
07229 if (strcmp(ilObjTest::_getTestType($active_id), "tt_varying_randomtest") == 0)
07230 {
07231 if (ilObjTest::_getPassScoring($active_id) == SCORE_BEST_PASS)
07232 {
07233 $counted_pass = ilObjTest::_getBestPass($active_id);
07234 }
07235 else
07236 {
07237 $counted_pass = ilObjTest::_getPass($active_id);
07238 global $ilDB;
07239 $query = sprintf("SELECT test_result_id FROM tst_test_result WHERE active_fi = %s AND pass = %s",
07240 $ilDB->quote($active_id . ""),
07241 $ilDB->quote($counted_pass . "")
07242 );
07243 $result = $ilDB->query($query);
07244 if ($result->numRows() == 0)
07245 {
07246
07247
07248 $counted_pass -= 1;
07249 }
07250 if ($counted_pass < 0) $counted_pass = 0;
07251 }
07252 }
07253 return $counted_pass;
07254 }
07255
07267 function getAnsweredQuestionCount($active_id, $pass = NULL)
07268 {
07269 if ($this->isRandomTest())
07270 {
07271 $this->loadQuestions($active_id, $pass);
07272 }
07273 include_once "./assessment/classes/class.assQuestion.php";
07274 $workedthrough = 0;
07275 foreach ($this->questions as $value)
07276 {
07277 if (assQuestion::_isWorkedThrough($active_id, $value, $pass))
07278 {
07279 $workedthrough += 1;
07280 }
07281 }
07282 return $workedthrough;
07283 }
07284
07296 function getPassFinishDate($active_id, $pass)
07297 {
07298 global $ilDB;
07299 if (is_null($pass)) $pass = 0;
07300 $query = sprintf("SELECT tst_test_result.TIMESTAMP + 0 AS TIMESTAMP14 FROM tst_test_result WHERE active_fi = %s AND pass = %s ORDER BY tst_test_result.TIMESTAMP DESC",
07301 $ilDB->quote($active_id . ""),
07302 $ilDB->quote($pass . "")
07303 );
07304 $result = $ilDB->query($query);
07305 if ($result->numRows())
07306 {
07307 $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
07308 return $row["TIMESTAMP14"];
07309 }
07310 else
07311 {
07312 return 0;
07313 }
07314 }
07315
07325 function isExecutable($user_id)
07326 {
07327 $result = array(
07328 "executable" => true,
07329 "errormessage" => ""
07330 );
07331 if (!$this->startingTimeReached())
07332 {
07333 $result["executable"] = false;
07334 $result["errormessage"] = sprintf($this->lng->txt("detail_starting_time_not_reached"), ilFormat::ftimestamp2datetimeDB($this->getStartingTime()));
07335 return $result;
07336 }
07337 if ($this->endingTimeReached())
07338 {
07339 $result["executable"] = false;
07340 $result["errormessage"] = sprintf($this->lng->txt("detail_ending_time_reached"), ilFormat::ftimestamp2datetimeDB($this->getEndingTime()));
07341 return $result;
07342 }
07343 if ($this->getEnableProcessingTime())
07344 {
07345 $starting_time = $this->getStartingTimeOfUser($user_id);
07346 if ($starting_time !== FALSE)
07347 {
07348 if ($this->isMaxProcessingTimeReached($starting_time))
07349 {
07350 $result["executable"] = false;
07351 $result["errormessage"] = $this->lng->txt("detail_max_processing_time_reached");
07352 return $result;
07353 }
07354 }
07355 }
07356
07357 $active = $this->getActiveTestUser($user_id);
07358 if ($this->hasNrOfTriesRestriction() && is_object($active) && $this->isNrOfTriesReached($active->tries))
07359 {
07360 $result["executable"] = false;
07361 if ($this->isOnlineTest())
07362 {
07363
07364
07365 $result["errormessage"] = "";
07366 }
07367 else
07368 {
07369 $result["errormessage"] = $this->lng->txt("maximum_nr_of_tries_reached");
07370 }
07371 return $result;
07372 }
07373
07374
07375
07376 return $result;
07377 }
07378
07379 function canShowTestResults($user_id)
07380 {
07381 $active = $this->getActiveTestUser($user_id);
07382 $starting_time = $this->getStartingTimeOfUser($user_id);
07383 $notimeleft = FALSE;
07384 if ($starting_time !== FALSE)
07385 {
07386 if ($this->isMaxProcessingTimeReached($starting_time))
07387 {
07388 $notimeleft = TRUE;
07389 }
07390 }
07391 $result = TRUE;
07392 if (!$this->isTestFinishedToViewResults($active->active_id, $active->tries) && ($this->getScoreReporting() == REPORT_AFTER_TEST))
07393 {
07394 $result = FALSE;
07395 }
07396 if (($this->endingTimeReached()) || $notimeleft) $result = TRUE;
07397 $result = $result & $this->canViewResults();
07398 if ($this->getTestType() == TYPE_ONLINE_TEST)
07399 {
07400 return $result && $this->isActiveTestSubmitted();
07401 }
07402 return $result;
07403 }
07404
07405 function canEditMarks()
07406 {
07407 $total = $this->evalTotalPersons();
07408 if ($total > 0)
07409 {
07410 if ($this->getReportingDate())
07411 {
07412 if (preg_match("/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/", $this->getReportingDate(), $matches))
07413 {
07414 $epoch_time = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
07415 $now = mktime();
07416 if ($now < $epoch_time)
07417 {
07418 return true;
07419 }
07420 }
07421 }
07422 return false;
07423 }
07424 else
07425 {
07426 return true;
07427 }
07428 }
07429
07439 function getStartingTimeOfUser($user_id)
07440 {
07441 global $ilDB;
07442
07443 if ($user_id < 1) return FALSE;
07444 $query = sprintf("SELECT tst_times.started FROM tst_times, tst_active WHERE tst_active.user_fi = %s AND tst_active.test_fi = %s AND tst_active.active_id = tst_times.active_fi ORDER BY tst_times.started",
07445 $ilDB->quote($user_id . ""),
07446 $ilDB->quote($this->getTestId() . "")
07447 );
07448 $result = $ilDB->query($query);
07449 if ($result->numRows())
07450 {
07451 $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
07452 if (preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row["started"], $matches))
07453 {
07454 return mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
07455 }
07456 else
07457 {
07458 return FALSE;
07459 }
07460 }
07461 else
07462 {
07463 return FALSE;
07464 }
07465 }
07466
07477 function isMaxProcessingTimeReached($starting_time)
07478 {
07479 if ($this->getEnableProcessingTime())
07480 {
07481 $processing_time = $this->getProcessingTimeInSeconds();
07482 $now = mktime();
07483 if ($now > ($starting_time + $processing_time))
07484 {
07485 return TRUE;
07486 }
07487 else
07488 {
07489 return FALSE;
07490 }
07491 }
07492 else
07493 {
07494 return FALSE;
07495 }
07496 }
07497
07498 function &getTestQuestions()
07499 {
07500 global $ilDB;
07501 $query = sprintf("SELECT qpl_questions.*, qpl_question_type.type_tag FROM qpl_questions, qpl_question_type, tst_test_question WHERE qpl_questions.question_type_fi = qpl_question_type.question_type_id AND tst_test_question.test_fi = %s AND tst_test_question.question_fi = qpl_questions.question_id ORDER BY sequence",
07502 $ilDB->quote($this->getTestId() . "")
07503 );
07504 $query_result = $ilDB->query($query);
07505 $removableQuestions = array();
07506 while ($row = $query_result->fetchRow(DB_FETCHMODE_ASSOC))
07507 {
07508 array_push($removableQuestions, $row);
07509 }
07510 return $removableQuestions;
07511 }
07512
07521 function getShuffleQuestions()
07522 {
07523 return $this->shuffle_questions;
07524 }
07525
07534 function setShuffleQuestions($a_shuffle)
07535 {
07536 if ($a_shuffle)
07537 {
07538 $this->shuffle_questions = TRUE;
07539 }
07540 else
07541 {
07542 $this->shuffle_questions = FALSE;
07543 }
07544 }
07545
07554 function getShowSolutionDetails()
07555 {
07556 return $this->show_solution_details;
07557 }
07558
07567 function getShowSummary()
07568 {
07569 return $this->show_summary;
07570 }
07571
07580 function getShowSolutionPrintview()
07581 {
07582 return $this->show_solution_printview;
07583 }
07584
07593 function setShowSolutionDetails($a_details = TRUE)
07594 {
07595 if ($a_details)
07596 {
07597 $this->show_solution_details = TRUE;
07598 }
07599 else
07600 {
07601 $this->show_solution_details = FALSE;
07602 }
07603 }
07604
07613 function setShowSummary($a_summary = TRUE)
07614 {
07615 if ($a_summary)
07616 {
07617 $this->show_summary = TRUE;
07618 }
07619 else
07620 {
07621 $this->show_summary = FALSE;
07622 }
07623 }
07624
07633 function canShowSolutionPrintview($user_id = NULL)
07634 {
07635 global $ilDB;
07636
07637 if (!is_numeric($user_id))
07638 {
07639 global $ilUser;
07640 $user_id = $ilUser->getId();
07641 }
07642
07643 if ($this->isOnlineTest())
07644 {
07645 $query = sprintf("SELECT submitted FROM tst_active WHERE test_fi=%s AND user_fi=%s AND submitted=1",
07646 $ilDB->quote($this->getTestId() . ""),
07647 $ilDB->quote($user_id . "")
07648 );
07649 $result = $ilDB->query($query);
07650 return $result->numRows() == 1;
07651 }
07652 else
07653 {
07654 if (($this->canShowTestResults($user_id)) && ($this->getShowSolutionPrintview()))
07655 {
07656 return TRUE;
07657 }
07658 else
07659 {
07660 return FALSE;
07661 }
07662 }
07663 return FALSE;
07664 }
07665
07674 function setShowSolutionPrintview($a_printview = TRUE)
07675 {
07676 if ($a_printview)
07677 {
07678 $this->show_solution_printview = TRUE;
07679 }
07680 else
07681 {
07682 $this->show_solution_printview = FALSE;
07683 }
07684 }
07685
07697 function &_getPassedUsers($a_obj_id)
07698 {
07699 $passed_users = array();
07700 $test_id = ilObjTest::_getTestIDFromObjectID($a_obj_id);
07701 $results =& ilObjTest::_getCompleteEvaluationData($test_id, FALSE);
07702 if (is_object($results))
07703 {
07704 $participants =& $results->getParticipants();
07705 foreach ($participants as $active_id => $participant)
07706 {
07707 if (is_object($participant) && $participant->getPassed())
07708 {
07709 array_push($passed_users, $active_id);
07710 }
07711 }
07712 }
07713 return $passed_users;
07714 }
07715
07721 function createNewAccessCode()
07722 {
07723
07724 $codestring = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
07725 mt_srand();
07726 $code = "";
07727 for ($i = 1; $i <=5; $i++)
07728 {
07729 $index = mt_rand(0, strlen($codestring)-1);
07730 $code .= substr($codestring, $index, 1);
07731 }
07732
07733 while ($this->isAccessCodeUsed($code))
07734 {
07735 $code = $this->createNewAccessCode();
07736 }
07737 return $code;
07738 }
07739
07740 function isAccessCodeUsed($code)
07741 {
07742 global $ilDB;
07743
07744 $query = sprintf("SELECT anonymous_id FROM tst_active WHERE test_fi = %s AND anonymous_id = %s",
07745 $ilDB->quote($this->getTestId() . ""),
07746 $ilDB->quote($code . "")
07747 );
07748 $result = $ilDB->query($query);
07749 if ($result->numRows() > 0)
07750 {
07751 return TRUE;
07752 }
07753 else
07754 {
07755 return FALSE;
07756 }
07757 }
07758
07759 function _getUserIdFromActiveId($active_id)
07760 {
07761 global $ilDB;
07762 $query = sprintf("SELECT user_fi FROM tst_active WHERE active_id = %s",
07763 $ilDB->quote($active_id . "")
07764 );
07765 $result = $ilDB->query($query);
07766 if ($result->numRows())
07767 {
07768 $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
07769 return $row["user_fi"];
07770 }
07771 else
07772 {
07773 return -1;
07774 }
07775 }
07776
07777 function getAccessCodeSession()
07778 {
07779 $id = $this->getTestId();
07780 if (!is_array($_SESSION["tst_access_code"]))
07781 {
07782 return "";
07783 }
07784 else
07785 {
07786 return $_SESSION["tst_access_code"]["$id"];
07787 }
07788 }
07789
07790 function setAccessCodeSession($access_code)
07791 {
07792 $id = $this->getTestId();
07793 if (!is_array($_SESSION["tst_access_code"]))
07794 {
07795 $_SESSION["tst_access_code"] = array();
07796 }
07797 $_SESSION["tst_access_code"]["$id"] = $access_code;
07798 }
07799
07800 function unsetAccessCodeSession()
07801 {
07802 $id = $this->getTestId();
07803 unset($_SESSION["tst_access_code"]["$id"]);
07804 }
07805
07806 function getAllowedUsers()
07807 {
07808 return $this->allowedUsers;
07809 }
07810
07811 function setAllowedUsers($a_allowed_users)
07812 {
07813 $this->allowedUsers = $a_allowed_users;
07814 }
07815
07816 function getAllowedUsersTimeGap()
07817 {
07818 return $this->allowedUsersTimeGap;
07819 }
07820
07821 function setAllowedUsersTimeGap($a_allowed_users_time_gap)
07822 {
07823 $this->allowedUsersTimeGap = $a_allowed_users_time_gap;
07824 }
07825
07826 function checkMaximumAllowedUsers()
07827 {
07828 global $ilDB;
07829
07830 $nr_of_users = $this->getAllowedUsers();
07831 $time_gap = $this->getAllowedUsersTimeGap();
07832 if (($nr_of_users > 0) && ($time_gap > 0))
07833 {
07834 $now = mktime();
07835 $time_border = $now - $time_gap;
07836 $str_time_border = strftime("%Y%m%d%H%M%S", $time_border);
07837 $query = sprintf("SELECT DISTINCT tst_times.active_fi, tst_times.times_id FROM tst_times, tst_active WHERE tst_times.TIMESTAMP > %s AND tst_times.active_fi = tst_active.active_id AND tst_active.test_fi = %s",
07838 $ilDB->quote($str_time_border),
07839 $ilDB->quote($this->getTestId() . "")
07840 );
07841 $result = $ilDB->query($query);
07842 if ($result->numRows() >= $nr_of_users)
07843 {
07844 include_once "./classes/class.ilObjAssessmentFolder.php";
07845 if (ilObjAssessmentFolder::_enabledAssessmentLogging())
07846 {
07847 $this->logAction($this->lng->txtlng("assessment", "log_could_not_enter_test_due_to_simultaneous_users", ilObjAssessmentFolder::_getLogLanguage()));
07848 }
07849 return FALSE;
07850 }
07851 else
07852 {
07853 return TRUE;
07854 }
07855 }
07856 return TRUE;
07857 }
07858
07859 function _getLastAccess($active_id)
07860 {
07861 global $ilDB;
07862
07863 $query = sprintf("SELECT finished FROM tst_times WHERE active_fi = %s ORDER BY finished DESC",
07864 $ilDB->quote($active_id . "")
07865 );
07866 $result = $ilDB->query($query);
07867 if ($result->numRows())
07868 {
07869 $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
07870 return $row["finished"];
07871 }
07872 return "";
07873 }
07874
07883 function isHTML($a_text)
07884 {
07885 if (preg_match("/<[^>]*?>/", $a_text))
07886 {
07887 return TRUE;
07888 }
07889 else
07890 {
07891 return FALSE;
07892 }
07893 }
07894
07902 function QTIMaterialToString($a_material)
07903 {
07904 $result = "";
07905 for ($i = 0; $i < $a_material->getMaterialCount(); $i++)
07906 {
07907 $material = $a_material->getMaterial($i);
07908 if (strcmp($material["type"], "mattext") == 0)
07909 {
07910 $result .= $material["material"]->getContent();
07911 }
07912 if (strcmp($material["type"], "matimage") == 0)
07913 {
07914 $matimage = $material["material"];
07915 if (preg_match("/(il_([0-9]+)_mob_([0-9]+))/", $matimage->getLabel(), $matches))
07916 {
07917
07918 if (!is_array($_SESSION["import_mob_xhtml"])) $_SESSION["import_mob_xhtml"] = array();
07919 array_push($_SESSION["import_mob_xhtml"], array("mob" => $matimage->getLabel(), "uri" => $matimage->getUri()));
07920 }
07921 }
07922 }
07923 return $result;
07924 }
07925
07934 function addQTIMaterial(&$a_xml_writer, $a_material)
07935 {
07936 include_once "./Services/RTE/classes/class.ilRTE.php";
07937 include_once("./content/classes/Media/class.ilObjMediaObject.php");
07938
07939 $a_xml_writer->xmlStartTag("material");
07940 $attrs = array(
07941 "texttype" => "text/plain"
07942 );
07943 if ($this->isHTML($a_material))
07944 {
07945 $attrs["texttype"] = "text/xhtml";
07946 }
07947 $a_xml_writer->xmlElement("mattext", $attrs, ilRTE::_replaceMediaObjectImageSrc($a_material, 0));
07948
07949 $mobs = ilObjMediaObject::_getMobsOfObject("tst:html", $this->getId());
07950 foreach ($mobs as $mob)
07951 {
07952 $mob_obj =& new ilObjMediaObject($mob);
07953 $imgattrs = array(
07954 "label" => "il_" . IL_INST_ID . "_mob_" . $mob,
07955 "uri" => "objects/" . "il_" . IL_INST_ID . "_mob_" . $mob . "/" . $mob_obj->getTitle()
07956 );
07957 $a_xml_writer->xmlElement("matimage", $imgattrs, NULL);
07958 }
07959 $a_xml_writer->xmlEndTag("material");
07960 }
07961
07968 function prepareTextareaOutput($txt_output, $prepare_for_latex_output = FALSE)
07969 {
07970 include_once "./classes/class.ilObjAdvancedEditing.php";
07971 $result = $txt_output;
07972 $is_html = $this->isHTML($result);
07973 if ($prepare_for_latex_output)
07974 {
07975 $result = ilUtil::insertLatexImages($result, "<span class\=\"latex\">", "<\/span>", URL_TO_LATEX);
07976 $result = ilUtil::insertLatexImages($result, "\[tex\]", "\[\/tex\]", URL_TO_LATEX);
07977 }
07978
07979
07980
07981 if (!$is_html)
07982 {
07983
07984 $result = preg_replace("/[\n]/", "<br />", $result);
07985 }
07986 else
07987 {
07988
07989 if (preg_match_all("/(<pre>.*?<\/pre>)/ims", $result, $matches))
07990 {
07991 foreach ($matches[0] as $found)
07992 {
07993 $replacement = "";
07994 if (strpos("\n", $found) === FALSE)
07995 {
07996 $replacement = "\n";
07997 }
07998 $removed = preg_replace("/<br\s*?\/>/ims", $replacement, $found);
07999 $result = str_replace($found, $removed, $result);
08000 }
08001 }
08002 }
08003 $result = str_replace("{", "{", $result);
08004 $result = str_replace("}", "}", $result);
08005 $result = str_replace("\\", "\", $result);
08006 return $result;
08007 }
08008
08017 function &evalResultsOverview()
08018 {
08019 return $this->_evalResultsOverview($this->getTestId());
08020 }
08021
08030 function &_evalResultsOverview($test_id)
08031 {
08032 global $ilDB;
08033
08034 $query = sprintf("SELECT usr_data.usr_id, usr_data.firstname, usr_data.lastname, usr_data.title, usr_data.login, " .
08035 "tst_test_result.*, qpl_questions.original_id, qpl_questions.title AS questiontitle, " .
08036 "qpl_questions.points AS maxpoints " .
08037 "FROM tst_test_result, qpl_questions, tst_active " .
08038 "LEFT JOIN usr_data ON tst_active.user_fi = usr_data.usr_id " .
08039 "WHERE tst_active.active_id = tst_test_result.active_fi " .
08040 "AND qpl_questions.question_id = tst_test_result.question_fi " .
08041 "AND tst_active.test_fi = %s " .
08042 "ORDER BY active_id, pass, TIMESTAMP",
08043 $ilDB->quote($test_id . "")
08044 );
08045 $result = $ilDB->query($query);
08046 $overview = array();
08047 while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC))
08048 {
08049 if (!array_key_exists($row["active_fi"], $overview))
08050 {
08051 $overview[$row["active_fi"]] = array();
08052 $overview[$row["active_fi"]]["firstname"] = $row["firstname"];
08053 $overview[$row["active_fi"]]["lastname"] = $row["lastname"];
08054 $overview[$row["active_fi"]]["title"] = $row["title"];
08055 $overview[$row["active_fi"]]["login"] = $row["login"];
08056 $overview[$row["active_fi"]]["usr_id"] = $row["usr_id"];
08057 $overview[$row["active_fi"]]["started"] = $row["started"];
08058 $overview[$row["active_fi"]]["finished"] = $row["finished"];
08059 }
08060 if (!array_key_exists($row["pass"], $overview[$row["active_fi"]]))
08061 {
08062 $overview[$row["active_fi"]][$row["pass"]] = array();
08063 $overview[$row["active_fi"]][$row["pass"]]["reached"] = 0;
08064 $overview[$row["active_fi"]][$row["pass"]]["maxpoints"] = $row["maxpoints"];
08065 }
08066 array_push($overview[$row["active_fi"]][$row["pass"]], $row);
08067 $overview[$row["active_fi"]][$row["pass"]]["reached"] += $row["points"];
08068 }
08069 return $overview;
08070 }
08071
08085 function buildName($user_id, $firstname, $lastname, $title)
08086 {
08087 $name = "";
08088 if (strlen($firstname.$lastname.$title) == 0)
08089 {
08090 $name = $this->lng->txt("deleted_user");
08091 }
08092 else
08093 {
08094 if ($user_id == ANONYMOUS_USER_ID)
08095 {
08096 $name = $row["lastname"];
08097 }
08098 else
08099 {
08100 $name = trim($lastname . ", " . $firstname . " " . $title);
08101 }
08102 if ($this->getTestType() == TYPE_SELF_ASSESSMENT)
08103 {
08104 $name = $this->lng->txt("anonymous");
08105 }
08106 }
08107 return $name;
08108 }
08109
08123 function _buildName($test_type, $user_id, $firstname, $lastname, $title)
08124 {
08125 global $lng;
08126 $name = "";
08127 if (strlen($firstname.$lastname.$title) == 0)
08128 {
08129 $name = $lng->txt("deleted_user");
08130 }
08131 else
08132 {
08133 if ($user_id == ANONYMOUS_USER_ID)
08134 {
08135 $name = $lastname;
08136 }
08137 else
08138 {
08139 $name = trim($lastname . ", " . $firstname . " " . $title);
08140 }
08141 if ($test_type == TYPE_SELF_ASSESSMENT)
08142 {
08143 $name = $lng->txt("anonymous");
08144 }
08145 }
08146 return $name;
08147 }
08148
08149 function &_getCompleteEvaluationData($test_id, $withStatistics = TRUE, $active_id = "")
08150 {
08151 global $ilDB;
08152
08153 $testquery = sprintf("SELECT * FROM tst_tests WHERE test_id = %s",
08154 $ilDB->quote($test_id . "")
08155 );
08156 $testres = $ilDB->query($testquery);
08157 $testdata = array();
08158 if ($testres->numRows())
08159 {
08160 $testdata = $testres->fetchRow(DB_FETCHMODE_ASSOC);
08161 }
08162
08163 include_once "./assessment/classes/class.assMarkSchema.php";
08164 $mark_schema = new ASS_MarkSchema();
08165 $mark_schema->loadFromDb($test_id);
08166
08167 include_once "./assessment/classes/class.ilTestEvaluationPassData.php";
08168 include_once "./assessment/classes/class.ilTestEvaluationUserData.php";
08169 include_once "./assessment/classes/class.ilTestEvaluationData.php";
08170 if ($active_id > 0) $withStatistics = FALSE;
08171 $data = new ilTestEvaluationData($test_id);
08172 $query = "";
08173 if ($active_id > 0)
08174 {
08175 $query = sprintf("SELECT usr_data.usr_id, usr_data.firstname, usr_data.lastname, usr_data.title, usr_data.login, " .
08176 "tst_test_result.*, qpl_questions.original_id, qpl_questions.title AS questiontitle, " .
08177 "qpl_questions.points AS maxpoints " .
08178 "FROM tst_test_result, qpl_questions, tst_active " .
08179 "LEFT JOIN usr_data ON tst_active.user_fi = usr_data.usr_id " .
08180 "WHERE tst_active.active_id = tst_test_result.active_fi " .
08181 "AND qpl_questions.question_id = tst_test_result.question_fi " .
08182 "AND tst_active.test_fi = %s AND tst_active.active_id = %s" .
08183 "ORDER BY active_id, pass, TIMESTAMP",
08184 $ilDB->quote($test_id . ""),
08185 $ilDB->quote($active_id . "")
08186 );
08187 }
08188 else
08189 {
08190 $query = sprintf("SELECT usr_data.usr_id, usr_data.firstname, usr_data.lastname, usr_data.title, usr_data.login, " .
08191 "tst_test_result.*, qpl_questions.original_id, qpl_questions.title AS questiontitle, " .
08192 "qpl_questions.points AS maxpoints " .
08193 "FROM tst_test_result, qpl_questions, tst_active " .
08194 "LEFT JOIN usr_data ON tst_active.user_fi = usr_data.usr_id " .
08195 "WHERE tst_active.active_id = tst_test_result.active_fi " .
08196 "AND qpl_questions.question_id = tst_test_result.question_fi " .
08197 "AND tst_active.test_fi = %s " .
08198 "ORDER BY active_id, pass, TIMESTAMP",
08199 $ilDB->quote($test_id . "")
08200 );
08201 }
08202 $result = $ilDB->query($query);
08203 $pass = NULL;
08204 $participant = NULL;
08205 $pass = NULL;
08206 while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC))
08207 {
08208 if (!$data->participantExists($row["active_fi"]))
08209 {
08210 $data->addParticipant($row["active_fi"], new ilTestEvaluationUserData());
08211 $participant =& $data->getParticipant($row["active_fi"]);
08212 $participant->setName(ilObjTest::_buildName($testdata["test_type_fi"], $row["usr_id"], $row["firstname"], $row["lastname"], $row["title"]));
08213 $participant->setLogin($row["login"]);
08214 $participant->setUserID($row["usr_id"]);
08215 }
08216 if (!is_object($participant->getPass($row["pass"])))
08217 {
08218 $participant->addPass($row["pass"], new ilTestEvaluationPassData($row["pass"]));
08219 $pass =& $participant->getPass($row["pass"]);
08220 }
08221 $pass->addAnsweredQuestion($row["original_id"] ? $row["original_id"] : $row["question_fi"], $row["maxpoints"], $row["points"]);
08222 }
08223 if ($testdata["test_type_fi"] != TYPE_VARYING_RANDOMTEST)
08224 {
08225
08226
08227 foreach ($data->getParticipantIds() as $active_id)
08228 {
08229 $participant =& $data->getParticipant($active_id);
08230 $lastpass = $participant->getLastPass();
08231 if ($lastpass > 0)
08232 {
08233 $passdatalast =& $participant->getPass($lastpass);
08234 $answeredids = array();
08235 foreach ($passdatalast->getAnsweredQuestions() as $foundquestion)
08236 {
08237 array_push($answeredids, $foundquestion["id"]);
08238 }
08239 $pointsarray = array();
08240 $reachedarray = array();
08241 for ($pc = 0; $pc <= $lastpass; $pc++)
08242 {
08243 $passdataactual =& $participant->getPass($pc);
08244 if ($passdataactual != null)
08245 {
08246 foreach ($passdataactual->getAnsweredQuestions() as $foundquestion)
08247 {
08248 $pointsarray[$foundquestion["id"]] = $foundquestion["points"];
08249 $reachedarray[$foundquestion["id"]] = $foundquestion["reached"];
08250 }
08251 }
08252 }
08253 foreach ($pointsarray as $question_id => $question_points)
08254 {
08255 if (!in_array($question_id, $answeredids))
08256 {
08257 $passdatalast->addAnsweredQuestion($question_id, $question_points, $reachedarray[$question_id]);
08258 }
08259 }
08260 }
08261 }
08262 }
08263 foreach ($data->getParticipantIds() as $active_id)
08264 {
08265 $participant =& $data->getParticipant($active_id);
08266 if ($testdata["random_test"])
08267 {
08268 for ($testpass = 0; $testpass <= $data->getLastPassOfParticipant($active_id); $testpass++)
08269 {
08270 $query = sprintf("SELECT tst_test_random_question.sequence, tst_test_random_question.question_fi, qpl_questions.original_id, " .
08271 "tst_test_random_question.pass, qpl_questions.points, qpl_questions.title, qpl_question_type.type_tag " .
08272 "FROM tst_test_random_question, qpl_questions, qpl_question_type " .
08273 "WHERE tst_test_random_question.question_fi = qpl_questions.question_id " .
08274 "AND tst_test_random_question.pass = %s " .
08275 "AND qpl_questions.question_type_fi = qpl_question_type.question_type_id " .
08276 "AND tst_test_random_question.active_fi = %s ORDER BY tst_test_random_question.sequence LIMIT 0, %s",
08277 $ilDB->quote($testpass . ""),
08278 $ilDB->quote($active_id . ""),
08279 ilObjTest::_getQuestionCount($test_id)
08280 );
08281 $result = $ilDB->query($query);
08282 if ($result->numRows())
08283 {
08284 while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC))
08285 {
08286 $rpass = array_key_exists("pass", $row) ? $row["pass"] : 0;
08287 $data->addQuestionForParticipant($active_id, $row["original_id"] ? $row["original_id"] : $row["question_fi"], $row["points"], $row["sequence"], $rpass, $row["type_tag"], $row["question_fi"]);
08288 $data->addQuestionTitle($row["original_id"] ? $row["original_id"] : $row["question_fi"], $row["title"]);
08289 }
08290 }
08291 }
08292 }
08293 else
08294 {
08295 $query = sprintf("SELECT tst_test_question.sequence, tst_test_question.question_fi, " .
08296 "qpl_questions.points, qpl_questions.title, qpl_questions.original_id, qpl_question_type.type_tag " .
08297 "FROM tst_test_question, tst_active, qpl_questions, qpl_question_type " .
08298 "WHERE tst_test_question.question_fi = qpl_questions.question_id " .
08299 "AND qpl_questions.question_type_fi = qpl_question_type.question_type_id " .
08300 "AND tst_active.active_id = %s AND tst_active.test_fi = tst_test_question.test_fi ORDER BY tst_test_question.sequence",
08301 $ilDB->quote($active_id . "")
08302 );
08303 $result = $ilDB->query($query);
08304 if ($result->numRows())
08305 {
08306 while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC))
08307 {
08308 $rpass = array_key_exists("pass", $row) ? $row["pass"] : 0;
08309 $participant->addQuestion($row["original_id"] ? $row["original_id"] : $row["question_fi"], $row["points"], $row["sequence"], $rpass, $row["type_tag"], $row["question_fi"]);
08310 $data->addQuestionTitle($row["original_id"] ? $row["original_id"] : $row["question_fi"], $row["title"]);
08311 }
08312 }
08313 }
08314 }
08315
08316 $workingTimes =& ilObjTest::_getCompleteWorkingTimeOfParticipants($test_id);
08317
08318 foreach (array_keys($data->getParticipants()) as $active_id)
08319 {
08320 $xpass = 0;
08321 $participant =& $data->getParticipant($active_id);
08322 if ($testdata["pass_scoring"] == SCORE_BEST_PASS)
08323 {
08324 $xpass = $participant->getBestPass();
08325 }
08326 else
08327 {
08328 $xpass = $participant->getLastPass();
08329 }
08330 $participant->setReached($participant->getReachedPoints($xpass));
08331 $participant->setMaxPoints($participant->getAvailablePoints($xpass));
08332 $percentage = $participant->getMaxPoints() ? $participant->getReached() / $participant->getMaxPoints() * 100.0 : 0;
08333 $mark = $mark_schema->getMatchingMark($percentage);
08334 if (is_object($mark))
08335 {
08336 $participant->setMark($mark->getShortName());
08337 $participant->setMarkOfficial($mark->getOfficialName());
08338 $participant->setPassed($mark->getPassed());
08339 }
08340 $userpass =& $participant->getPass($xpass);
08341 if (is_object($userpass)) $participant->setQuestionsWorkedThrough($userpass->getAnsweredQuestionCount());
08342 $questionpass = $xpass;
08343 if (!is_array($participant->getQuestions($xpass)))
08344 {
08345 $questionpass = 0;
08346 }
08347 $participant->setNumberOfQuestions(count($participant->getQuestions($questionpass)));
08348 $participant->setTimeOfWork($workingTimes[$active_id]);
08349 $visitingTime =& ilObjTest::_getVisitTimeOfParticipant($test_id, $active_id);
08350 $participant->setFirstVisit($visitingTime["firstvisit"]);
08351 $participant->setLastVisit($visitingTime["lastvisit"]);
08352 }
08353 $passed_points = array();
08354 foreach (array_keys($data->getParticipants()) as $active_id)
08355 {
08356 $participant =& $data->getParticipant($active_id);
08357 if ($participant->getPassed())
08358 {
08359 array_push($passed_points, $participant->getReached());
08360 }
08361 }
08362 foreach (array_keys($data->getParticipants()) as $active_id)
08363 {
08364 $participant =& $data->getParticipant($active_id);
08365 if ($testdata["ects_output"])
08366 {
08367 $ects_mark = ilObjTest::_getECTSGrade($passed_points, $participant->getReached(), $participant->getMaxPoints(), $testdata["ects_a"], $testdata["ects_b"], $testdata["ects_c"], $testdata["ects_d"], $testdata["ects_e"], $testdata["ects_fx"]);
08368 $participant->setECTSMark($ects_mark);
08369 }
08370 }
08371 if ($withStatistics)
08372 {
08373 $data->calculateStatistics();
08374 }
08375 return $data;
08376 }
08377
08378 function &getCompleteEvaluationData($withStatistics = TRUE)
08379 {
08380 global $ilDB;
08381 include_once "./assessment/classes/class.ilTestEvaluationPassData.php";
08382 include_once "./assessment/classes/class.ilTestEvaluationUserData.php";
08383 include_once "./assessment/classes/class.ilTestEvaluationData.php";
08384 $data = new ilTestEvaluationData($this->getTestId());
08385
08386 $query = sprintf("SELECT usr_data.usr_id, usr_data.firstname, usr_data.lastname, usr_data.title, usr_data.login, " .
08387 "tst_test_result.*, qpl_questions.original_id, qpl_questions.title AS questiontitle, " .
08388 "qpl_questions.points AS maxpoints " .
08389 "FROM tst_test_result, qpl_questions, tst_active " .
08390 "LEFT JOIN usr_data ON tst_active.user_fi = usr_data.usr_id " .
08391 "WHERE tst_active.active_id = tst_test_result.active_fi " .
08392 "AND qpl_questions.question_id = tst_test_result.question_fi " .
08393 "AND tst_active.test_fi = %s " .
08394 "ORDER BY active_id, pass, TIMESTAMP",
08395 $ilDB->quote($this->getTestId() . "")
08396 );
08397 $result = $ilDB->query($query);
08398 $pass = NULL;
08399 $participant = NULL;
08400 $pass = NULL;
08401 while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC))
08402 {
08403 if (!$data->participantExists($row["active_fi"]))
08404 {
08405 $data->addParticipant($row["active_fi"], new ilTestEvaluationUserData());
08406 $participant =& $data->getParticipant($row["active_fi"]);
08407 $participant->setName($this->buildName($row["usr_id"], $row["firstname"], $row["lastname"], $row["title"]));
08408 $participant->setLogin($row["login"]);
08409 $participant->setUserID($row["usr_id"]);
08410 }
08411 if (!is_object($participant->getPass($row["pass"])))
08412 {
08413 $participant->addPass($row["pass"], new ilTestEvaluationPassData($row["pass"]));
08414 $pass =& $participant->getPass($row["pass"]);
08415 }
08416 $pass->addAnsweredQuestion($row["original_id"] ? $row["original_id"] : $row["question_fi"], $row["maxpoints"], $row["points"]);
08417 }
08418 if ($this->getTestType() != TYPE_VARYING_RANDOMTEST)
08419 {
08420
08421
08422 foreach ($data->getParticipantIds() as $active_id)
08423 {
08424 $participant =& $data->getParticipant($active_id);
08425 $lastpass = $participant->getLastPass();
08426 if ($lastpass > 0)
08427 {
08428 $passdatalast =& $participant->getPass($lastpass);
08429 $answeredids = array();
08430 foreach ($passdatalast->getAnsweredQuestions() as $foundquestion)
08431 {
08432 array_push($answeredids, $foundquestion["id"]);
08433 }
08434 $pointsarray = array();
08435 $reachedarray = array();
08436 for ($pc = 0; $pc <= $lastpass; $pc++)
08437 {
08438 $passdataactual =& $participant->getPass($pc);
08439 if ($passdataactual != null)
08440 {
08441 foreach ($passdataactual->getAnsweredQuestions() as $foundquestion)
08442 {
08443 $pointsarray[$foundquestion["id"]] = $foundquestion["points"];
08444 $reachedarray[$foundquestion["id"]] = $foundquestion["reached"];
08445 }
08446 }
08447 }
08448 foreach ($pointsarray as $question_id => $question_points)
08449 {
08450 if (!in_array($question_id, $answeredids))
08451 {
08452 $passdatalast->addAnsweredQuestion($question_id, $question_points, $reachedarray[$question_id]);
08453 }
08454 }
08455 }
08456 }
08457 }
08458 foreach ($data->getParticipantIds() as $active_id)
08459 {
08460 $participant =& $data->getParticipant($active_id);
08461 if ($this->isRandomTest())
08462 {
08463 for ($testpass = 0; $testpass <= $data->getLastPassOfParticipant($active_id); $testpass++)
08464 {
08465 $query = sprintf("SELECT tst_test_random_question.sequence, tst_test_random_question.question_fi, qpl_questions.original_id, " .
08466 "tst_test_random_question.pass, qpl_questions.points, qpl_questions.title, qpl_question_type.type_tag " .
08467 "FROM tst_test_random_question, qpl_questions, qpl_question_type " .
08468 "WHERE tst_test_random_question.question_fi = qpl_questions.question_id " .
08469 "AND tst_test_random_question.pass = %s " .
08470 "AND qpl_questions.question_type_fi = qpl_question_type.question_type_id " .
08471 "AND tst_test_random_question.active_fi = %s ORDER BY tst_test_random_question.sequence LIMIT 0, %s",
08472 $ilDB->quote($testpass . ""),
08473 $ilDB->quote($active_id . ""),
08474 $this->getQuestionCount()
08475 );
08476 $result = $ilDB->query($query);
08477 if ($result->numRows())
08478 {
08479 while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC))
08480 {
08481 $rpass = array_key_exists("pass", $row) ? $row["pass"] : 0;
08482 $data->addQuestionForParticipant($active_id, $row["original_id"] ? $row["original_id"] : $row["question_fi"], $row["points"], $row["sequence"], $rpass, $row["type_tag"], $row["question_fi"]);
08483 $data->addQuestionTitle($row["original_id"] ? $row["original_id"] : $row["question_fi"], $row["title"]);
08484 }
08485 }
08486 }
08487 }
08488 else
08489 {
08490 $query = sprintf("SELECT tst_test_question.sequence, tst_test_question.question_fi, " .
08491 "qpl_questions.points, qpl_questions.title, qpl_questions.original_id, qpl_question_type.type_tag " .
08492 "FROM tst_test_question, tst_active, qpl_questions, qpl_question_type " .
08493 "WHERE tst_test_question.question_fi = qpl_questions.question_id " .
08494 "AND qpl_questions.question_type_fi = qpl_question_type.question_type_id " .
08495 "AND tst_active.active_id = %s AND tst_active.test_fi = tst_test_question.test_fi ORDER BY tst_test_question.sequence",
08496 $ilDB->quote($active_id . "")
08497 );
08498 $result = $ilDB->query($query);
08499 if ($result->numRows())
08500 {
08501 while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC))
08502 {
08503 $rpass = array_key_exists("pass", $row) ? $row["pass"] : 0;
08504 $participant->addQuestion($row["original_id"] ? $row["original_id"] : $row["question_fi"], $row["points"], $row["sequence"], $rpass, $row["type_tag"], $row["question_fi"]);
08505 $data->addQuestionTitle($row["original_id"] ? $row["original_id"] : $row["question_fi"], $row["title"]);
08506 }
08507 }
08508 }
08509 }
08510
08511 $workingTimes =& $this->getCompleteWorkingTimeOfParticipants();
08512
08513 foreach (array_keys($data->getParticipants()) as $active_id)
08514 {
08515 $xpass = 0;
08516 $participant =& $data->getParticipant($active_id);
08517 if ($this->getPassScoring() == SCORE_BEST_PASS)
08518 {
08519 $xpass = $participant->getBestPass();
08520 }
08521 else
08522 {
08523 $xpass = $participant->getLastPass();
08524 }
08525 $participant->setReached($participant->getReachedPoints($xpass));
08526 $participant->setMaxPoints($participant->getAvailablePoints($xpass));
08527 $percentage = $participant->getMaxPoints() ? $participant->getReached() / $participant->getMaxPoints() * 100.0 : 0;
08528 $mark = $this->mark_schema->getMatchingMark($percentage);
08529 if (is_object($mark))
08530 {
08531 $participant->setMark($mark->getShortName());
08532 $participant->setMarkOfficial($mark->getOfficialName());
08533 $participant->setPassed($mark->getPassed());
08534 }
08535 if ($this->ects_output)
08536 {
08537
08538 $ects_mark = $this->getECTSGrade($participant->getReached(), $participant->getMaxPoints());
08539 $participant->setECTSMark($ects_mark);
08540 }
08541 $userpass =& $participant->getPass($xpass);
08542 if (is_object($userpass)) $participant->setQuestionsWorkedThrough($userpass->getAnsweredQuestionCount());
08543 $questionpass = $xpass;
08544 if (!is_array($participant->getQuestions($xpass)))
08545 {
08546 $questionpass = 0;
08547 }
08548 $participant->setNumberOfQuestions(count($participant->getQuestions($questionpass)));
08549 $participant->setTimeOfWork($workingTimes[$active_id]);
08550 $visitingTime =& $this->getVisitTimeOfParticipant($active_id);
08551 $participant->setFirstVisit($visitingTime["firstvisit"]);
08552 $participant->setLastVisit($visitingTime["lastvisit"]);
08553 }
08554 if ($withStatistics)
08555 {
08556 $data->calculateStatistics();
08557 }
08558 return $data;
08559 }
08560
08569 function &getCompleteWorkingTimeOfParticipants()
08570 {
08571 return $this->_getCompleteWorkingTimeOfParticipants($this->getTestId());
08572 }
08573
08582 function &_getCompleteWorkingTimeOfParticipants($test_id)
08583 {
08584 global $ilDB;
08585
08586 $query = sprintf("SELECT tst_times.* FROM tst_active, tst_times WHERE tst_active.test_fi = %s AND tst_active.active_id = tst_times.active_fi ORDER BY tst_times.active_fi, tst_times.started",
08587 $ilDB->quote($test_id . "")
08588 );
08589 $result = $ilDB->query($query);
08590 $time = 0;
08591 $times = array();
08592 while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC))
08593 {
08594 if (!array_key_exists($row["active_fi"], $times))
08595 {
08596 $times[$row["active_fi"]] = 0;
08597 }
08598 preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row["started"], $matches);
08599 $epoch_1 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
08600 preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row["finished"], $matches);
08601 $epoch_2 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
08602 $times[$row["active_fi"]] += ($epoch_2 - $epoch_1);
08603 }
08604 return $times;
08605 }
08606
08615 function getVisitTimeOfParticipant($active_id)
08616 {
08617 return ilObjTest::_getVisitTimeOfParticipant($this->getTestId(), $active_id);
08618 }
08619
08628 function _getVisitTimeOfParticipant($test_id, $active_id)
08629 {
08630 global $ilDB;
08631
08632 $query = sprintf("SELECT tst_times.* FROM tst_active, tst_times WHERE tst_active.test_fi = %s AND tst_active.active_id = tst_times.active_fi AND tst_active.active_id = %s ORDER BY tst_times.started",
08633 $ilDB->quote($test_id . ""),
08634 $ilDB->quote($active_id . "")
08635 );
08636 $result = $ilDB->query($query);
08637 $firstvisit = 0;
08638 $lastvisit = 0;
08639 while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC))
08640 {
08641 preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row["started"], $matches);
08642 $epoch_1 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
08643 if ($firstvisit == 0 || $epoch_1 < $firstvisit) $firstvisit = $epoch_1;
08644 preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row["finished"], $matches);
08645 $epoch_2 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
08646 if ($epoch_2 > $lastvisit) $lastvisit = $epoch_2;
08647 }
08648 return array("firstvisit" => $firstvisit, "lastvisit" => $lastvisit);
08649 }
08650
08651 }
08652
08653 ?>