• Main Page
  • Related Pages
  • Namespaces
  • Data Structures
  • Files
  • File List
  • Globals

assessment/classes/class.ilObjTest.php

Go to the documentation of this file.
00001 <?php
00002 /*
00003         +-----------------------------------------------------------------------------+
00004         | ILIAS open source                                                           |
00005         +-----------------------------------------------------------------------------+
00006         | Copyright (c) 1998-2001 ILIAS open source, University of Cologne            |
00007         |                                                                             |
00008         | This program is free software; you can redistribute it and/or               |
00009         | modify it under the terms of the GNU General Public License                 |
00010         | as published by the Free Software Foundation; either version 2              |
00011         | of the License, or (at your option) any later version.                      |
00012         |                                                                             |
00013         | This program is distributed in the hope that it will be useful,             |
00014         | but WITHOUT ANY WARRANTY; without even the implied warranty of              |
00015         | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               |
00016         | GNU General Public License for more details.                                |
00017         |                                                                             |
00018         | You should have received a copy of the GNU General Public License           |
00019         | along with this program; if not, write to the Free Software                 |
00020         | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. |
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 
00140   var $reporting_date;
00141 
00149   var $evaluation_data;
00150 
00158   var $test_type;
00159 
00168   var $nr_of_tries;
00169 
00178         var $hide_previous_results;
00179 
00187   var $hide_title_points;
00188 
00196   var $processing_time;
00197         
00205         var $enable_processing_time;
00206 
00214   var $starting_time;
00215   
00223   var $ending_time;
00224 
00232   var $ects_output;
00233 
00241   var $ects_fx;
00242 
00253         var $test_types;
00254 
00262   var $ects_grades;
00263 
00273         var $random_test;
00274 
00282         var $random_question_count;
00283 
00290         var $count_system;
00291         
00297         var $mc_scoring;
00298 
00304         var $pass_scoring;
00305 
00312         function ilObjTest($a_id = 0,$a_call_by_reference = true)
00313         {
00314                 global $ilUser;
00315                 $this->type = "tst";
00316                 include_once "./assessment/classes/class.assMarkSchema.php";
00317                 $this->mark_schema = new ASS_MarkSchema();
00318                 //$this->ilObject($a_id, $a_call_by_reference);
00319                 $this->retrieveTestTypes();
00320                 $this->test_id = -1;
00321                 $this->author = $ilUser->fullname;
00322                 $this->introduction = "";
00323                 $this->questions = array();
00324                 $this->sequence_settings = TEST_FIXED_SEQUENCE;
00325                 $this->score_reporting = REPORT_AFTER_TEST;
00326                 $this->reporting_date = "";
00327                 $this->nr_of_tries = 0;
00328                 $this->hide_previous_results = 0;
00329                 $this->hide_title_points = 0;
00330                 $this->starting_time = "";
00331                 $this->ending_time = "";
00332                 $this->processing_time = "00:00:00";
00333                 $this->enable_processing_time = "0";
00334                 $this->test_type = TYPE_ASSESSMENT;
00335                 $this->ects_output = 0;
00336                 $this->ects_fx = "";
00337                 $this->random_test = 0;
00338                 $this->random_question_count = "";
00339                 $this->count_system = COUNT_PARTIAL_SOLUTIONS;
00340                 $this->mc_scoring = SCORE_ZERO_POINTS_WHEN_UNANSWERED;
00341                 $this->pass_scoring = SCORE_LAST_PASS;
00342                 global $lng;
00343                 $lng->loadLanguageModule("assessment");
00344                 $this->mark_schema->create_simple_schema($lng->txt("failed_short"), $lng->txt("failed_official"), 0, 0, $lng->txt("passed_short"), $lng->txt("passed_official"), 50, 1);
00345                 $this->ects_grades = array(
00346                         "A" => 90,
00347                         "B" => 65,
00348                         "C" => 35,
00349                         "D" => 10,
00350                         "E" => 0
00351                 );
00352                 $this->ilObject($a_id, $a_call_by_reference);
00353         }
00354 
00358         function create($a_upload = false)
00359         {
00360                 parent::create();
00361                 
00362                 // meta data will be created by
00363                 // import parser
00364                 if (!$a_upload)
00365                 {
00366                         $this->createMetaData();
00367                 }
00368         }
00369 
00376         function update()
00377         {
00378                 $this->updateMetaData();
00379                 if (!parent::update())
00380                 {
00381                         return false;
00382                 }
00383 
00384                 // put here object specific stuff
00385                 
00386                 return true;
00387         }
00388         
00397         function createReference() {
00398                 $result = parent::createReference();
00399                 $this->saveToDb();
00400                 return $result;
00401         }
00402         
00408         function read($a_force_db = false)
00409         {
00410                 parent::read($a_force_db);
00411                 $this->loadFromDb();
00412         }
00413 
00421         function ilClone($a_parent_ref)
00422         {               
00423                 global $rbacadmin;
00424 
00425                 // always call parent ilClone function first!!
00426                 $new_ref_id = parent::ilClone($a_parent_ref);
00427                 
00428                 // get object instance of ilCloned object
00429                 //$newObj =& $this->ilias->obj_factory->getInstanceByRefId($new_ref_id);
00430 
00431                 // create a local role folder & default roles
00432                 //$roles = $newObj->initDefaultRoles();
00433 
00434                 // ...finally assign role to creator of object
00435                 //$rbacadmin->assignUser($roles[0], $newObj->getOwner(), "n");          
00436 
00437                 // always destroy objects in ilClone method because ilClone() is recursive and creates instances for each object in subtree!
00438                 //unset($newObj);
00439 
00440                 // ... and finally always return new reference ID!!
00441                 return $new_ref_id;
00442         }
00443 
00450         function delete()
00451         {
00452                 // always call parent delete function first!!
00453                 if (!parent::delete())
00454                 {
00455                         return false;
00456                 }
00457 
00458                 // delet meta data
00459                 $this->deleteMetaData();
00460 
00461                 //put here your module specific stuff
00462                 $this->deleteTest();
00463 
00464                 return true;
00465         }
00466 
00474         function deleteTest()
00475         {
00476                 $query = sprintf("SELECT active_id FROM tst_active WHERE test_fi = %s",
00477                         $this->ilias->db->quote($this->getTestId())
00478                 );
00479                 $result = $this->ilias->db->query($query);
00480                 $active_array = array();
00481                 while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC))
00482                 {
00483                         array_push($active_array, $row["active_id"]);
00484                 }
00485 
00486                 $query = sprintf("DELETE FROM tst_active WHERE test_fi = %s",
00487                         $this->ilias->db->quote($this->getTestId())
00488                 );
00489                 $result = $this->ilias->db->query($query);
00490 
00491                 if (count($active_array))
00492                 {
00493                         foreach ($active_array as $active_id)
00494                         {
00495                                 $query = sprintf("DELETE FROM tst_times WHERE active_fi = %s",
00496                                         $this->ilias->db->quote($active_id)
00497                                 );
00498                                 $result = $this->ilias->db->query($query);
00499                         }
00500                 }
00501 
00502                 $query = sprintf("DELETE FROM tst_mark WHERE test_fi = %s",
00503                         $this->ilias->db->quote($this->getTestId())
00504                 );
00505                 $result = $this->ilias->db->query($query);
00506 
00507                 $query = sprintf("SELECT question_fi FROM tst_test_question WHERE test_fi = %s",
00508                         $this->ilias->db->quote($this->getTestId())
00509                 );
00510                 $result = $this->ilias->db->query($query);
00511                 while ($row = $result->fetchRow(DB_FETCHMODE_OBJECT))
00512                 {
00513                         $this->removeQuestion($row->question_fi);
00514                 }
00515 
00516                 $query = sprintf("DELETE FROM tst_tests WHERE test_id = %s",
00517                         $this->ilias->db->quote($this->getTestId())
00518                 );
00519                 $result = $this->ilias->db->query($query);
00520 
00521                 $query = sprintf("DELETE FROM tst_test_random WHERE test_fi = %s",
00522                         $this->ilias->db->quote($this->getTestId())
00523                 );
00524                 $result = $this->ilias->db->query($query);
00525 
00526                 $query = sprintf("DELETE FROM tst_test_random_question WHERE test_fi = %s",
00527                         $this->ilias->db->quote($this->getTestId())
00528                 );
00529                 $result = $this->ilias->db->query($query);
00530 
00531                 $this->removeAllTestEditings();
00532 
00533                 $query = sprintf("DELETE FROM tst_test_question WHERE test_fi = %s",
00534                         $this->ilias->db->quote($this->getTestId())
00535                 );
00536                 $result = $this->ilias->db->query($query);
00537 
00538                 // delete export files
00539                 include_once "./classes/class.ilUtil.php";
00540                 $tst_data_dir = ilUtil::getDataDir()."/tst_data";
00541                 $directory = $tst_data_dir."/tst_".$this->getId();
00542                 if (is_dir($directory))
00543                 {
00544                         include_once "./classes/class.ilUtil.php";
00545                         ilUtil::delDir($directory);
00546                 }
00547         }
00548 
00558         function initDefaultRoles()
00559         {
00560                 global $rbacadmin;
00561                 
00562                 // create a local role folder
00563                 //$rfoldObj = $this->createRoleFolder("Local roles","Role Folder of forum obj_no.".$this->getId());
00564 
00565                 // create moderator role and assign role to rolefolder...
00566                 //$roleObj = $rfoldObj->createRole("Moderator","Moderator of forum obj_no.".$this->getId());
00567                 //$roles[] = $roleObj->getId();
00568 
00569                 //unset($rfoldObj);
00570                 //unset($roleObj);
00571 
00572                 return $roles ? $roles : array();
00573         }
00574 
00588         function notify($a_event,$a_ref_id,$a_parent_non_rbac_id,$a_node_id,$a_params = 0)
00589         {
00590                 global $tree;
00591                 
00592                 switch ($a_event)
00593                 {
00594                         case "link":
00595                                 
00596                                 //var_dump("<pre>",$a_params,"</pre>");
00597                                 //echo "Module name ".$this->getRefId()." triggered by link event. Objects linked into target object ref_id: ".$a_ref_id;
00598                                 //exit;
00599                                 break;
00600                         
00601                         case "cut":
00602                                 
00603                                 //echo "Module name ".$this->getRefId()." triggered by cut event. Objects are removed from target object ref_id: ".$a_ref_id;
00604                                 //exit;
00605                                 break;
00606                                 
00607                         case "copy":
00608                         
00609                                 //var_dump("<pre>",$a_params,"</pre>");
00610                                 //echo "Module name ".$this->getRefId()." triggered by copy event. Objects are copied into target object ref_id: ".$a_ref_id;
00611                                 //exit;
00612                                 break;
00613 
00614                         case "paste":
00615 
00616                                 //echo "Module name ".$this->getRefId()." triggered by paste (cut) event. Objects are pasted into target object ref_id: ".$a_ref_id;
00617                                 //exit;
00618                                 break;
00619                         
00620                         case "new":
00621                                 
00622                                 //echo "Module name ".$this->getRefId()." triggered by paste (new) event. Objects are applied to target object ref_id: ".$a_ref_id;
00623                                 //exit;
00624                                 break;
00625                 }
00626                 
00627                 // At the beginning of the recursive process it avoids second call of the notify function with the same parameter
00628                 if ($a_node_id==$_GET["ref_id"])
00629                 {       
00630                         $parent_obj =& $this->ilias->obj_factory->getInstanceByRefId($a_node_id);
00631                         $parent_type = $parent_obj->getType();
00632                         if($parent_type == $this->getType())
00633                         {
00634                                 $a_node_id = (int) $tree->getParentId($a_node_id);
00635                         }
00636                 }
00637                 
00638                 parent::notify($a_event,$a_ref_id,$a_parent_non_rbac_id,$a_node_id,$a_params);
00639         }
00640         
00646         function createExportDirectory()
00647         {
00648                 include_once "./classes/class.ilUtil.php";
00649                 $tst_data_dir = ilUtil::getDataDir()."/tst_data";
00650                 ilUtil::makeDir($tst_data_dir);
00651                 if(!is_writable($tst_data_dir))
00652                 {
00653                         $this->ilias->raiseError("Test Data Directory (".$tst_data_dir
00654                                 .") not writeable.",$this->ilias->error_obj->MESSAGE);
00655                 }
00656                 
00657                 // create learning module directory (data_dir/lm_data/lm_<id>)
00658                 $tst_dir = $tst_data_dir."/tst_".$this->getId();
00659                 ilUtil::makeDir($tst_dir);
00660                 if(!@is_dir($tst_dir))
00661                 {
00662                         $this->ilias->raiseError("Creation of Test Directory failed.",$this->ilias->error_obj->MESSAGE);
00663                 }
00664                 // create Export subdirectory (data_dir/lm_data/lm_<id>/Export)
00665                 $export_dir = $tst_dir."/export";
00666                 ilUtil::makeDir($export_dir);
00667                 if(!@is_dir($export_dir))
00668                 {
00669                         $this->ilias->raiseError("Creation of Export Directory failed.",$this->ilias->error_obj->MESSAGE);
00670                 }
00671         }
00672 
00680         function getExportDirectory()
00681         {
00682                 include_once "./classes/class.ilUtil.php";
00683                 $export_dir = ilUtil::getDataDir()."/tst_data"."/tst_".$this->getId()."/export";
00684                 return $export_dir;
00685         }
00686         
00695         function getExportFiles($dir)
00696         {
00697                 // quit if import dir not available
00698                 if (!@is_dir($dir) or
00699                         !is_writeable($dir))
00700                 {
00701                         return array();
00702                 }
00703 
00704                 // open directory
00705                 $dir = dir($dir);
00706 
00707                 // initialize array
00708                 $file = array();
00709 
00710                 // get files and save the in the array
00711                 while ($entry = $dir->read())
00712                 {
00713                         if ($entry != "." and
00714                                 $entry != ".." and
00715                                 //substr($entry, -4) == ".zip" and
00716                                 ereg("^[0-9]{10}_{2}[0-9]+_{2}(test(__results)?__)*[0-9]+\.[a-z]{1,3}\$", $entry))
00717                         {
00718                                 $file[] = $entry;
00719                         }
00720                 }
00721 
00722                 // close import directory
00723                 $dir->close();
00724 
00725                 // sort files
00726                 sort ($file);
00727                 reset ($file);
00728 
00729                 return $file;
00730         }
00731 
00732         
00738         function _createImportDirectory()
00739         {
00740                 global $ilias;
00741                 
00742                 include_once "./classes/class.ilUtil.php";
00743                 $tst_data_dir = ilUtil::getDataDir()."/tst_data";
00744                 ilUtil::makeDir($tst_data_dir);
00745                 
00746                 if(!is_writable($tst_data_dir))
00747                 {
00748                         $ilias->raiseError("Test data directory (".$tst_data_dir
00749                                 .") not writeable.",$ilias->error_obj->FATAL);
00750                 }
00751 
00752                 // create test directory (data_dir/tst_data/tst_import)
00753                 $tst_dir = $tst_data_dir."/tst_import";
00754                 ilUtil::makeDir($tst_dir);
00755                 if(!@is_dir($tst_dir))
00756                 {
00757                         $ilias->raiseError("Creation of test import directory failed.",$ilias->error_obj->FATAL);
00758                 }
00759         }
00760 
00769         function _getImportDirectory()
00770         {
00771                 include_once "./classes/class.ilUtil.php";
00772                 $import_dir = ilUtil::getDataDir()."/tst_data/tst_import";
00773                 if(@is_dir($import_dir))
00774                 {
00775                         return $import_dir;
00776                 }
00777                 else
00778                 {
00779                         return false;
00780                 }
00781         }
00782 
00788         function createImportDirectory()
00789         {
00790                 include_once "./classes/class.ilUtil.php";
00791                 $tst_data_dir = ilUtil::getDataDir()."/tst_data";
00792                 ilUtil::makeDir($tst_data_dir);
00793                 
00794                 if(!is_writable($tst_data_dir))
00795                 {
00796                         $this->ilias->raiseError("Test Data Directory (".$tst_data_dir
00797                                 .") not writeable.",$this->ilias->error_obj->FATAL);
00798                 }
00799 
00800                 // create test directory (data_dir/tst_data/tst_import)
00801                 $tst_dir = $tst_data_dir."/tst_import";
00802                 ilUtil::makeDir($tst_dir);
00803                 if(!@is_dir($tst_dir))
00804                 {
00805                         $ilias->raiseError("Creation of test import directory failed.",$ilias->error_obj->FATAL);
00806                 }
00807         }
00808 
00817         function getImportDirectory()
00818         {
00819                 include_once "./classes/class.ilUtil.php";
00820                 $import_dir = ilUtil::getDataDir()."/tst_data/tst_import";
00821                 if(@is_dir($import_dir))
00822                 {
00823                         return $import_dir;
00824                 }
00825                 else
00826                 {
00827                         return false;
00828                 }
00829         }
00830 
00831         
00841         function retrieveTestTypes()
00842         {
00843                 global $ilDB;
00844 
00845                 $this->test_types = array();
00846                 $query = "SELECT * FROM tst_test_type ORDER BY test_type_id";
00847                 $result = $ilDB->query($query);
00848                 while ($row = $result->fetchRow(DB_FETCHMODE_OBJECT))
00849                 {
00850                         $this->test_types[$row->test_type_id] = $row->type_tag;
00851                 }
00852         }
00853         
00863   function testTitleExists($title) 
00864         {
00865     $query = sprintf("SELECT * FROM object_data WHERE title = %s AND type = %s",
00866       $this->ilias->db->quote($title),
00867                         $this->ilias->db->quote("tst")
00868     );
00869     $result = $this->ilias->db->query($query);
00870     if (strcmp(strtolower(get_class($result)), db_result) == 0) {
00871       if ($result->numRows() == 1) {
00872         return TRUE;
00873       }
00874     }
00875     return FALSE;
00876   }
00877   
00885   function duplicate() 
00886         {
00887     $clone = $this;
00888     $clone->set_id(-1);
00889     $counter = 2;
00890     while ($this->testTitleExists($this->get_title() . " ($counter)")) {
00891       $counter++;
00892     }
00893     $clone->set_title($this->get_title() . " ($counter)");
00894     $clone->set_owner($this->ilias->account->id);
00895     $clone->setAuthor($this->ilias->account->fullname);
00896     $clone->saveToDb($this->ilias->db);
00897     // Duplicate questions
00898     $query = sprintf("SELECT * FROM tst_test_question WHERE test_fi = %s",
00899       $this->ilias->db->quote($this->getId())
00900     );
00901     $result = $this->ilias->db->query($query);
00902     while ($data = $result->fetchRow(DB_FETCHMODE_OBJECT)) {
00903       $query = sprintf("INSERT INTO tst_test_question (test_question_id, test_fi, question_fi, sequence, TIMESTAMP) VALUES (NULL, %s, %s, %s, NULL)",
00904         $this->ilias->db->quote($clone->getId()),
00905         $this->ilias->db->quote($data->question_fi),
00906         $this->ilias->db->quote($data->sequence)
00907       );
00908       $insert_result = $this->ilias->db->query($query);
00909     }
00910   }
00911   
00920         function isComplete()
00921         {
00922                 if (($this->getTitle()) and ($this->author) and (count($this->mark_schema->mark_steps)) and (count($this->questions)))
00923                 {
00924                         return true;
00925                 } 
00926                         else 
00927                 {
00928                         if ($this->isRandomTest())
00929                         {
00930                                 $arr = $this->getRandomQuestionpools();
00931                                 if (count($arr) && ($this->getRandomQuestionCount() > 0))
00932                                 {
00933                                         return true;
00934                                 }
00935                                 $count = 0;
00936                                 foreach ($arr as $array)
00937                                 {
00938                                         $count += $array["count"];
00939                                 }
00940                                 if ($count)
00941                                 {
00942                                         return true;
00943                                 }
00944                         }
00945                         return false;
00946                 }
00947         }
00948 
00957         function _isComplete($obj_id)
00958         {
00959                 $test = new ilObjTest($obj_id, false);
00960                 $test->loadFromDb();
00961                 return $test->isComplete();
00962         }
00963 
00971         function saveECTSStatus($ects_output = 0, $fx_support = "", $ects_a = 90, $ects_b = 65, $ects_c = 35, $ects_d = 10, $ects_e = 0) 
00972         {
00973     global $ilDB;
00974     if ($this->test_id > 0) {
00975                         $fx_support = preg_replace("/,/", ".", $fx_support);
00976                         if (preg_match("/\d+/", $fx_support))
00977                         {
00978                                 $fx_support = $fx_support;
00979                         }
00980                         else
00981                         {
00982                                 $fx_support = "NULL";
00983                         }
00984       $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",
00985                                 $ilDB->quote("$ects_output"),
00986                                 $ilDB->quote($ects_a . ""),
00987                                 $ilDB->quote($ects_b . ""),
00988                                 $ilDB->quote($ects_c . ""),
00989                                 $ilDB->quote($ects_d . ""),
00990                                 $ilDB->quote($ects_e . ""),
00991         $fx_support,
00992                                 $this->getTestId()
00993       );
00994       $result = $ilDB->query($query);
00995                         $this->ects_output = $ects_output;
00996                         $this->ects_fx = $fx_support;
00997                 }
00998         }
00999 
01007         function saveCompleteStatus() 
01008         {
01009     global $ilias;
01010                 
01011     $db =& $ilias->db;
01012                 $complete = 0;
01013                 if ($this->isComplete()) {
01014                         $complete = 1;
01015                 }
01016     if ($this->test_id > 0) {
01017       $query = sprintf("UPDATE tst_tests SET complete = %s WHERE test_id = %s",
01018                                 $db->quote("$complete"),
01019         $db->quote($this->test_id)
01020       );
01021       $result = $db->query($query);
01022                 }
01023         }
01024 
01033   function saveToDb($properties_only = FALSE)
01034   {
01035     global $ilias;
01036     $db =& $ilias->db;
01037                 $complete = 0;
01038                 if ($this->isComplete()) {
01039                         $complete = 1;
01040                 }
01041                 $ects_fx = "NULL";
01042                 if (preg_match("/\d+/", $this->ects_fx))
01043                 {
01044                         $ects_fx = $this->ects_fx;
01045                 }
01046                 $random_question_count = "NULL";
01047                 if ($this->random_question_count > 0)
01048                 {
01049                         $random_question_count = $this->ilias->db->quote($this->random_question_count . "");
01050                 }
01051                 include_once ("./classes/class.ilObjAssessmentFolder.php");
01052     if ($this->test_id == -1) 
01053                 {
01054       // Create new dataset
01055       $now = getdate();
01056       $created = sprintf("%04d%02d%02d%02d%02d%02d", $now['year'], $now['mon'], $now['mday'], $now['hours'], $now['minutes'], $now['seconds']);
01057       $query = sprintf("INSERT INTO tst_tests (test_id, obj_fi, author, test_type_fi, introduction, sequence_settings, score_reporting, 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, pass_scoring, 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, NULL)",
01058                                 $db->quote($this->getId() . ""),
01059                                 $db->quote($this->author . ""),
01060                                 $db->quote($this->test_type . ""),
01061                                 $db->quote($this->introduction . ""), 
01062                                 $db->quote($this->sequence_settings . ""),
01063                                 $db->quote($this->score_reporting . ""),
01064                                 $db->quote(sprintf("%d", $this->nr_of_tries) . ""),
01065                                 $db->quote(sprintf("%d", $this->getHidePreviousResults() . "")),
01066                                 $db->quote(sprintf("%d", $this->getHideTitlePoints() . "")),
01067                                 $db->quote($this->processing_time . ""),
01068                                 $db->quote("$this->enable_processing_time"),
01069                                 $db->quote($this->reporting_date . ""),
01070                                 $db->quote($this->starting_time . ""),
01071                                 $db->quote($this->ending_time . ""),
01072                                 $db->quote("$complete"),
01073                                 $db->quote($this->ects_output . ""),
01074                                 $db->quote($this->ects_grades["A"] . ""),
01075                                 $db->quote($this->ects_grades["B"] . ""),
01076                                 $db->quote($this->ects_grades["C"] . ""),
01077                                 $db->quote($this->ects_grades["D"] . ""),
01078                                 $db->quote($this->ects_grades["E"] . ""),
01079                                 $ects_fx,
01080                                 $db->quote(sprintf("%d", $this->random_test) . ""),
01081                                 $random_question_count,
01082                                 $db->quote($this->count_system . ""),
01083                                 $db->quote($this->mc_scoring . ""),
01084                                 $db->quote($this->getPassScoring() . ""),
01085                                 $db->quote($created)
01086       );
01087       
01088                         if (ilObjAssessmentFolder::_enabledAssessmentLogging())
01089                         {
01090                                 $this->logAction($this->lng->txtlng("assessment", "log_create_new_test", ilObjAssessmentFolder::_getLogLanguage()));
01091                         }
01092       $result = $db->query($query);
01093       if ($result == DB_OK) {
01094         $this->test_id = $this->ilias->db->getLastInsertId();
01095       }
01096     } 
01097                 else 
01098                 {
01099       // Modify existing dataset
01100                         $oldrow = array();
01101                         if (ilObjAssessmentFolder::_enabledAssessmentLogging())
01102                         {
01103                                 $query = sprintf("SELECT * FROM tst_tests WHERE test_id = %s",
01104                 $db->quote($this->test_id)
01105                                 );
01106                                 $result = $db->query($query);
01107                                 if ($result->numRows() == 1)
01108                                 {
01109                                         $oldrow = $result->fetchRow(DB_FETCHMODE_ASSOC);
01110                                 }
01111                         }
01112       $query = sprintf("UPDATE tst_tests SET author = %s, test_type_fi = %s, introduction = %s, sequence_settings = %s, score_reporting = %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, pass_scoring = %s WHERE test_id = %s",
01113         $db->quote($this->author . ""), 
01114         $db->quote($this->test_type . ""), 
01115         $db->quote($this->introduction . ""), 
01116         $db->quote($this->sequence_settings . ""), 
01117         $db->quote($this->score_reporting . ""), 
01118         $db->quote(sprintf("%d", $this->nr_of_tries) . ""),
01119                                 $db->quote(sprintf("%d", $this->getHidePreviousResults() . "")),
01120                                 $db->quote(sprintf("%d", $this->getHideTitlePoints() . "")),
01121         $db->quote($this->processing_time . ""),
01122                                 $db->quote("$this->enable_processing_time"),
01123         $db->quote($this->reporting_date . ""), 
01124         $db->quote($this->starting_time . ""), 
01125         $db->quote($this->ending_time . ""), 
01126                                 $db->quote($this->ects_output . ""),
01127                                 $db->quote($this->ects_grades["A"] . ""),
01128                                 $db->quote($this->ects_grades["B"] . ""),
01129                                 $db->quote($this->ects_grades["C"] . ""),
01130                                 $db->quote($this->ects_grades["D"] . ""),
01131                                 $db->quote($this->ects_grades["E"] . ""),
01132                                 $ects_fx,
01133                                 $db->quote(sprintf("%d", $this->random_test) . ""),
01134                                 $db->quote("$complete"),
01135                                 $db->quote($this->count_system . ""),
01136                                 $db->quote($this->mc_scoring . ""),
01137                                 $db->quote($this->getPassScoring() . ""),
01138         $db->quote($this->test_id)
01139       );
01140       $result = $db->query($query);
01141                         include_once ("./classes/class.ilObjAssessmentFolder.php");
01142                         if (ilObjAssessmentFolder::_enabledAssessmentLogging())
01143                         {
01144                                 $query = sprintf("SELECT * FROM tst_tests WHERE test_id = %s",
01145                 $db->quote($this->test_id)
01146                                 );
01147                                 $logresult = $db->query($query);
01148                                 $newrow = array();
01149                                 if ($logresult->numRows() == 1)
01150                                 {
01151                                         $newrow = $logresult->fetchRow(DB_FETCHMODE_ASSOC);
01152                                 }
01153                                 $changed_fields = array();
01154                                 foreach ($oldrow as $key => $value)
01155                                 {
01156                                         if (strcmp($oldrow[$key], $newrow[$key]) != 0)
01157                                         {
01158                                                 array_push($changed_fields, "$key: " . $oldrow[$key] . " => " . $newrow[$key]);
01159                                         }
01160                                 }
01161                                 $changes = join($changed_fields, ", ");
01162                                 if (count($changed_fields) == 0)
01163                                 {
01164                                         $changes = $this->lng->txtlng("assessment", "log_no_test_fields_changed", ilObjAssessmentFolder::_getLogLanguage());
01165                                 }
01166                                 $this->logAction($this->lng->txtlng("assessment", "log_modified_test", ilObjAssessmentFolder::_getLogLanguage()) . " [".$changes."]");
01167                         }
01168     }
01169                 if (!$properties_only)
01170                 {
01171                         if ($result == DB_OK) {
01172                                 if (!$this->isRandomTest())
01173                                 {
01174                                         $this->saveQuestionsToDb();
01175                                 }
01176                                 $this->mark_schema->saveToDb($this->test_id);
01177                         }
01178                 }
01179   }
01180 
01189         function saveQuestionsToDb() 
01190         {
01191                 $oldquestions = array();
01192                 include_once "./classes/class.ilObjAssessmentFolder.php";
01193                 if (ilObjAssessmentFolder::_enabledAssessmentLogging())
01194                 {
01195                         $query = sprintf("SELECT question_fi FROM tst_test_question WHERE test_fi = %s ORDER BY sequence",
01196                                 $this->ilias->db->quote($this->getTestId())
01197                         );
01198                         $result = $this->ilias->db->query($query);
01199                         if ($result->numRows() > 0)
01200                         {
01201                                 while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC))
01202                                 {
01203                                         array_push($oldquestions, $row["question_fi"]);
01204                                 }
01205                         }
01206                 }
01207                 
01208                 // delete existing category relations
01209     $query = sprintf("DELETE FROM tst_test_question WHERE test_fi = %s",
01210                         $this->ilias->db->quote($this->getTestId())
01211                 );
01212                 $result = $this->ilias->db->query($query);
01213                 // create new category relations
01214                 foreach ($this->questions as $key => $value) {
01215                         $query = sprintf("INSERT INTO tst_test_question (test_question_id, test_fi, question_fi, sequence, TIMESTAMP) VALUES (NULL, %s, %s, %s, NULL)",
01216                                 $this->ilias->db->quote($this->getTestId() . ""),
01217                                 $this->ilias->db->quote($value . ""),
01218                                 $this->ilias->db->quote($key . "")
01219                         );
01220                         $result = $this->ilias->db->query($query);
01221                 }
01222                 include_once ("./classes/class.ilObjAssessmentFolder.php");
01223                 if (ilObjAssessmentFolder::_enabledAssessmentLogging())
01224                 {
01225                         $query = sprintf("SELECT question_fi FROM tst_test_question WHERE test_fi = %s ORDER BY sequence",
01226                                 $this->ilias->db->quote($this->getTestId())
01227                         );
01228                         $result = $this->ilias->db->query($query);
01229                         $newquestions = array();
01230                         if ($result->numRows() > 0)
01231                         {
01232                                 while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC))
01233                                 {
01234                                         array_push($newquestions, $row["question_fi"]);
01235                                 }
01236                         }
01237                         foreach ($oldquestions as $index => $question_id)
01238                         {
01239                                 if (strcmp($newquestions[$index], $question_id) != 0)
01240                                 {
01241                                         $pos = array_search($question_id, $newquestions);
01242                                         if ($pos === FALSE)
01243                                         {
01244                                                 $this->logAction($this->lng->txtlng("assessment", "log_question_removed", ilObjAssessmentFolder::_getLogLanguage()), $question_id);                                                     
01245                                         }
01246                                         else
01247                                         {
01248                                                 $this->logAction($this->lng->txtlng("assessment", "log_question_position_changed", ilObjAssessmentFolder::_getLogLanguage()) . ": " . ($index+1) . " => " . ($pos+1), $question_id);
01249                                         }
01250                                 }
01251                         }
01252                         foreach ($newquestions as $index => $question_id)
01253                         {
01254                                 if (array_search($question_id, $oldquestions) === FALSE)
01255                                 {
01256                                         $this->logAction($this->lng->txtlng("assessment", "log_question_added", ilObjAssessmentFolder::_getLogLanguage()) . ": " . ($index+1), $question_id);
01257                                 }
01258                         }
01259                 }
01260         }
01261 
01270         function saveRandomQuestion($question_id, $pass = NULL) 
01271         {
01272                 global $ilUser;
01273                 
01274                 if (is_null($pass)) $pass = 0;
01275                 $query = sprintf("SELECT test_random_question_id FROM tst_test_random_question WHERE test_fi = %s AND user_fi = %s AND pass = %s",
01276                         $this->ilias->db->quote($this->getTestId() . ""),
01277                         $this->ilias->db->quote($ilUser->id . ""),
01278                         $this->ilias->db->quote($pass . "")
01279                 );
01280                 $result = $this->ilias->db->query($query);
01281                 
01282                 $query = sprintf("INSERT INTO tst_test_random_question (test_random_question_id, test_fi, user_fi, question_fi, sequence, pass, TIMESTAMP) VALUES (NULL, %s, %s, %s, %s, %s, NULL)",
01283                         $this->ilias->db->quote($this->getTestId() . ""),
01284                         $this->ilias->db->quote($ilUser->id . ""),
01285                         $this->ilias->db->quote($question_id . ""),
01286                         $this->ilias->db->quote(($result->numRows()+1) . ""),
01287                         $this->ilias->db->quote($pass . "")
01288                 );
01289                 $result = $this->ilias->db->query($query);
01290         }
01291         
01299         function getNrOfResultsForPass($user_id, $pass)
01300         {
01301                 $query = sprintf("SELECT test_result_id FROM tst_test_result WHERE test_fi = %s AND user_fi = %s AND pass = %s",
01302                         $this->ilias->db->quote($this->getTestId() . ""),
01303                         $this->ilias->db->quote($user_id . ""),
01304                         $this->ilias->db->quote($pass . "")
01305                 );
01306                 $result = $this->ilias->db->query($query);
01307                 return $result->numRows();
01308         }
01309         
01318         function generateRandomQuestions($pass = NULL)
01319         {
01320                 global $ilUser;
01321                 $this->loadQuestions($ilUser->getId(), $pass);
01322                 if (count($this->questions) > 0)
01323                 {
01324                         // Something went wrong. Maybe the user pressed the start button twice
01325                         // Questions already exist so there is no need to create new questions
01326                         return;
01327                 }
01328                 if ($pass > 0)
01329                 {
01330                         if ($this->getNrOfResultsForPass($ilUser->getId(), $pass - 1) == 0)
01331                         {
01332                                 // This means that someone maybe reloaded the test submission page
01333                                 // If there are no existing results for the previous test, it makes
01334                                 // no sense to create a new set of random questions
01335                                 return;
01336                         }
01337                 }
01338                 if ($this->getRandomQuestionCount() > 0)
01339                 {
01340                         $qpls =& $this->getRandomQuestionpools();
01341                         $rndquestions = $this->randomSelectQuestions($this->getRandomQuestionCount(), 0, 1, $qpls, $pass);
01342                         $allquestions = array();
01343                         foreach ($rndquestions as $question_id)
01344                         {
01345                                 array_push($allquestions, $question_id);
01346                         }
01347                         srand ((float)microtime()*1000000);
01348                         shuffle($allquestions);
01349                         foreach ($allquestions as $question_id)
01350                         {
01351                                 $this->saveRandomQuestion($question_id, $pass);
01352                         }
01353                 }
01354                 else
01355                 {
01356                         $qpls =& $this->getRandomQuestionpools();
01357                         $allquestions = array();
01358                         foreach ($qpls as $key => $value)
01359                         {
01360                                 if ($value["count"] > 0)
01361                                 {
01362                                         $rndquestions = $this->randomSelectQuestions($value["count"], $value["qpl"], 1, $pass);
01363                                         foreach ($rndquestions as $question_id)
01364                                         {
01365                                                 array_push($allquestions, $question_id);
01366                                         }
01367                                 }
01368                         }
01369                         srand ((float)microtime()*1000000);
01370                         shuffle($allquestions);
01371                         foreach ($allquestions as $question_id)
01372                         {
01373                                 $this->saveRandomQuestion($question_id, $pass);
01374                         }
01375                 }
01376                 return;
01377         }
01378 
01387         function saveRandomQuestionCount($total_questions = "NULL")
01388         {
01389                 if (strcmp($total_questions, "NULL") != 0)
01390                 {
01391                         $this->setRandomQuestionCount($total_questions);
01392                         $total_questions = $this->ilias->db->quote($total_questions);
01393                 }
01394                 $query = sprintf("UPDATE tst_tests SET random_question_count = %s WHERE test_id = %s",
01395                         $total_questions,
01396                         $this->ilias->db->quote($this->getTestId() . "")
01397                 );
01398                 $result = $this->ilias->db->query($query);
01399         }
01400 
01410         function saveRandomQuestionpools($qpl_array) 
01411         {
01412                 // delete existing random questionpools
01413     $query = sprintf("DELETE FROM tst_test_random WHERE test_fi = %s",
01414                         $this->ilias->db->quote($this->getTestId())
01415                 );
01416                 $result = $this->ilias->db->query($query);
01417                 // create new random questionpools
01418                 foreach ($qpl_array as $key => $value) {
01419                         if ($value["qpl"] > -1)
01420                         {
01421                                 include_once "./assessment/classes/class.ilObjQuestionPool.php";
01422                                 $count = ilObjQuestionPool::_getQuestionCount($value["qpl"]);
01423                                 if ($value["count"] > $count)
01424                                 {
01425                                         $value["count"] = $count;
01426                                 }
01427                                 $query = sprintf("INSERT INTO tst_test_random (test_random_id, test_fi, questionpool_fi, num_of_q, TIMESTAMP) VALUES (NULL, %s, %s, %s, NULL)",
01428                                         $this->ilias->db->quote($this->getTestId() . ""),
01429                                         $this->ilias->db->quote($value["qpl"] . ""),
01430                                         $this->ilias->db->quote(sprintf("%d", $value["count"]) . "")
01431                                 );
01432                                 $result = $this->ilias->db->query($query);
01433                         }
01434                 }
01435         }
01436 
01446         function &getRandomQuestionpools() 
01447         {
01448                 $qpls = array();
01449                 $counter = 0;
01450                 $query = sprintf("SELECT * FROM tst_test_random WHERE test_fi = %s ORDER BY test_random_id",
01451                         $this->ilias->db->quote($this->getTestId() . "")
01452                 );
01453                 $result = $this->ilias->db->query($query);
01454                 if ($result->numRows())
01455                 {
01456                         while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC))
01457                         {
01458                                 $qpls[$counter] = array(
01459                                         "index" => $counter,
01460                                         "count" => $row["num_of_q"],
01461                                         "qpl"   => $row["questionpool_fi"]
01462                                 );
01463                                 $counter++;
01464                         }
01465                 }
01466                 return $qpls;
01467         }
01468 
01478         function loadFromDb()
01479         {
01480                 $db = $this->ilias->db;
01481 
01482                 $query = sprintf("SELECT * FROM tst_tests WHERE obj_fi = %s",
01483                 $db->quote($this->getId())
01484                         );
01485                 $result = $db->query($query);
01486                 if (strcmp(strtolower(get_class($result)), db_result) == 0)
01487                 {
01488                         if ($result->numRows() == 1)
01489                         {
01490                                 $data = $result->fetchRow(DB_FETCHMODE_OBJECT);
01491                                 $this->test_id = $data->test_id;
01492                                 $this->author = $data->author;
01493                                 $this->test_type = $data->test_type_fi;
01494                                 $this->introduction = $data->introduction;
01495                                 $this->sequence_settings = $data->sequence_settings;
01496                                 $this->score_reporting = $data->score_reporting;
01497                                 $this->nr_of_tries = $data->nr_of_tries;
01498                                 $this->setHidePreviousResults($data->hide_previous_results);
01499                                 $this->setHideTitlePoints($data->hide_title_points);
01500                                 $this->processing_time = $data->processing_time;
01501                                 $this->enable_processing_time = $data->enable_processing_time;
01502                                 $this->reporting_date = $data->reporting_date;
01503                                 $this->starting_time = $data->starting_time;
01504                                 $this->ending_time = $data->ending_time;
01505                                 $this->ects_output = $data->ects_output;
01506                                 $this->ects_grades = array(
01507                                         "A" => $data->ects_a,
01508                                         "B" => $data->ects_b,
01509                                         "C" => $data->ects_c,
01510                                         "D" => $data->ects_d,
01511                                         "E" => $data->ects_e
01512                                 );
01513                                 $this->ects_fx = $data->ects_fx;
01514                                 $this->random_test = $data->random_test;
01515                                 $this->random_question_count = $data->random_question_count;
01516                                 $this->mark_schema->flush();
01517                                 $this->mark_schema->loadFromDb($this->test_id);
01518                                 $this->count_system = $data->count_system;
01519                                 $this->mc_scoring = $data->mc_scoring;
01520                                 $this->setPassScoring($data->pass_scoring);
01521                                 $this->loadQuestions();
01522                         }
01523                 }
01524         }
01525 
01534         function loadQuestions($user_id = "", $pass = NULL) 
01535         {
01536                 global $ilUser;
01537                 
01538     $db = $this->ilias->db;
01539                 $this->questions = array();
01540                 if (strcmp($user_id, "") == 0)
01541                 {
01542                         $user_id = $ilUser->id;
01543                 }
01544                 if ($this->isRandomTest())
01545                 {
01546                         if (is_null($pass))
01547                         {
01548                                 if ($this->getTestType() == TYPE_VARYING_RANDOMTEST)
01549                                 {
01550                                         $pass = $this->_getPass($ilUser->id, $this->getTestId());
01551                                 }
01552                                 else
01553                                 {
01554                                         // normal random questions are created only once, for pass 0
01555                                         $pass = 0;
01556                                 }
01557                         }
01558                         $query = sprintf("SELECT tst_test_random_question.* FROM tst_test_random_question, qpl_questions WHERE tst_test_random_question.test_fi = %s AND tst_test_random_question.user_fi = %s AND qpl_questions.question_id = tst_test_random_question.question_fi AND tst_test_random_question.pass = %s ORDER BY sequence",
01559                                 $db->quote($this->test_id . ""),
01560                                 $db->quote($user_id . ""),
01561                                 $db->quote($pass . "")
01562                         );
01563                 }
01564                 else
01565                 {
01566                         $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",
01567                                 $db->quote($this->test_id . "")
01568                         );
01569                 }
01570                 $result = $db->query($query);
01571                 $index = 1;
01572                 while ($data = $result->fetchRow(DB_FETCHMODE_OBJECT)) 
01573                 {
01574                         $this->questions[$index++] = $data->question_fi;
01575                 }
01576         }
01577 
01587   function setAuthor($author = "") 
01588         {
01589     $this->author = $author;
01590   }
01591 
01601   function setIntroduction($introduction = "") 
01602         {
01603     $this->introduction = $introduction;
01604   }
01605 
01615   function getAuthor() 
01616         {
01617     return $this->author;
01618   }
01619 
01629   function isRandomTest() 
01630         {
01631     return $this->random_test;
01632   }
01633 
01643   function getRandomQuestionCount() 
01644         {
01645     return $this->random_question_count;
01646   }
01647 
01657   function getIntroduction() 
01658         {
01659     return $this->introduction;
01660   }
01661 
01671   function getTestId() 
01672         {
01673     return $this->test_id;
01674   }
01675 
01685   function setSequenceSettings($sequence_settings = 0) 
01686         {
01687     $this->sequence_settings = $sequence_settings;
01688   }
01689 
01699   function setTestType($type = TYPE_ASSESSMENT) 
01700   {
01701     $this->test_type = $type;
01702   }
01703 
01713   function setScoreReporting($score_reporting = 0) 
01714         {
01715     $this->score_reporting = $score_reporting;
01716   }
01717 
01727   function setRandomTest($a_random_test = 0) 
01728         {
01729     $this->random_test = $a_random_test;
01730   }
01731 
01741   function setRandomQuestionCount($a_random_question_count = "") 
01742         {
01743     $this->random_question_count = $a_random_question_count;
01744   }
01745 
01755   function setReportingDate($reporting_date) 
01756   {
01757                 if (!$reporting_date) 
01758                 {
01759                         $this->reporting_date = "";
01760                         $this->ects_output = 0;
01761                 }
01762                 else 
01763                 {
01764                         $this->reporting_date = $reporting_date;
01765                         $this->score_reporting = REPORT_AFTER_TEST;
01766                 }
01767   }
01768 
01778   function getSequenceSettings() 
01779         {
01780     return $this->sequence_settings;
01781   }
01782 
01792   function getScoreReporting() 
01793         {
01794     return $this->score_reporting;
01795   }
01796 
01806   function getCountSystem() 
01807         {
01808     return $this->count_system;
01809   }
01810 
01820   function _getCountSystem($test_id) 
01821         {
01822                 global $ilDB;
01823                 $query = sprintf("SELECT count_system FROM tst_tests WHERE test_id = %s",
01824                         $ilDB->quote($test_id)
01825                 );
01826                 $result = $ilDB->query($query);
01827                 if ($result->numRows())
01828                 {
01829                         $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
01830                         return $row["count_system"];
01831                 }
01832     return FALSE;
01833   }
01834         
01844   function getMCScoring() 
01845         {
01846     return $this->mc_scoring;
01847   }
01848 
01858   function getPassScoring() 
01859         {
01860     return $this->pass_scoring;
01861   }
01862 
01872   function _getPassScoring($test_id) 
01873         {
01874                 global $ilDB;
01875                 $query = sprintf("SELECT pass_scoring FROM tst_tests WHERE test_id = %s",
01876                         $ilDB->quote($test_id . "")
01877                 );
01878                 $result = $ilDB->query($query);
01879                 if ($result->numRows())
01880                 {
01881                         $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
01882                         return $row["pass_scoring"];
01883                 }
01884     return 0;
01885   }
01886 
01896   function _getMCScoring($test_id) 
01897         {
01898                 global $ilDB;
01899                 $query = sprintf("SELECT  mc_scoring FROM tst_tests WHERE test_id = %s",
01900                         $ilDB->quote($test_id)
01901                 );
01902                 $result = $ilDB->query($query);
01903                 if ($result->numRows())
01904                 {
01905                         $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
01906                         return $row["mc_scoring"];
01907                 }
01908     return FALSE;
01909   }
01910 
01920   function getTestType() 
01921         {
01922     return $this->test_type;
01923   }
01924 
01934   function getReportingDate() 
01935         {
01936     return $this->reporting_date;
01937   }
01938 
01948   function getNrOfTries() 
01949         {
01950     return $this->nr_of_tries;
01951   }
01952 
01962   function getHidePreviousResults() 
01963         {
01964     return $this->hide_previous_results;
01965   }
01966 
01976   function getHideTitlePoints() 
01977         {
01978     return $this->hide_title_points;
01979   }
01980 
01991   function _getHideTitlePoints($test_id) 
01992         {
01993                 global $ilDB;
01994 
01995                 $query = sprintf("SELECT hide_title_points FROM tst_tests WHERE test_id = %s",
01996                         $ilDB->quote($test_id . "")
01997                 );
01998                 $result = $ilDB->query($query);
01999                 if ($result->numRows())
02000                 {
02001                         $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
02002                         return $row["hide_title_points"];
02003                 }
02004                 return 0;
02005   }
02006 
02018   function _getHidePreviousResults($test_id, $user_active_user_setting = false) 
02019         {
02020                 global $ilDB;
02021                 global $ilUser;
02022                 
02023                 $user_hide_previous_results = 0;
02024                 if ($user_active_user_setting)
02025                 {
02026                         if (array_key_exists("tst_hide_previous_results", $ilUser->prefs))
02027                         {
02028                                 $user_hide_previous_results = $ilUser->prefs["tst_hide_previous_results"];
02029                         }
02030                 }
02031                 $query = sprintf("SELECT hide_previous_results FROM tst_tests WHERE test_id = %s",
02032                         $ilDB->quote($test_id . "")
02033                 );
02034                 $result = $ilDB->query($query);
02035                 if ($result->numRows())
02036                 {
02037                         $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
02038                         if ($row["hide_previous_results"] != 1)
02039                         {
02040                                 return $row["hide_previous_results"] | $user_hide_previous_results;
02041                         }
02042                         else
02043                         {
02044                                 return $row["hide_previous_results"];
02045                         }
02046                 }
02047                 return 0;
02048   }
02049 
02059   function getProcessingTime() 
02060         {
02061     return $this->processing_time;
02062   }
02063         
02073         function getProcessingTimeInSeconds()
02074         {
02075                 if (preg_match("/(\d{2}):(\d{2}):(\d{2})/", $this->getProcessingTime(), $matches))
02076                 {
02077                         return ($matches[1] * 3600) + ($matches[2] * 60) + $matches[3];
02078                 }
02079                         else
02080                 {
02081                         return 0;
02082                 }
02083         }
02084 
02094   function getEnableProcessingTime() 
02095         {
02096     return $this->enable_processing_time;
02097   }
02098 
02108   function getStartingTime() 
02109         {
02110     return $this->starting_time;
02111   }
02112 
02122   function getEndingTime() 
02123         {
02124     return $this->ending_time;
02125   }
02126 
02136   function setNrOfTries($nr_of_tries = 0) 
02137         {
02138     $this->nr_of_tries = $nr_of_tries;
02139   }
02140 
02150   function setHidePreviousResults($hide_previous_results = 0) 
02151         {
02152                 if ($hide_previous_results)
02153                 {
02154                         $this->hide_previous_results = 1;
02155                 }
02156                 else
02157                 {
02158                         $this->hide_previous_results = 0;
02159                 }
02160   }
02161 
02171   function setHideTitlePoints($hide_title_points = 0) 
02172         {
02173                 if ($hide_title_points)
02174                 {
02175                         $this->hide_title_points = 1;
02176                 }
02177                 else
02178                 {
02179                         $this->hide_title_points = 0;
02180                 }
02181   }
02182 
02192   function setProcessingTime($processing_time = "00:00:00") 
02193         {
02194     $this->processing_time = $processing_time;
02195   }
02196         
02206         function setEnableProcessingTime($enable = 0) 
02207         {
02208                 if ($enable) {
02209                         $this->enable_processing_time = "1";
02210                 } else {
02211                         $this->enable_processing_time = "0";
02212                 }
02213         }
02214 
02224   function setStartingTime($starting_time = "") 
02225         {
02226     $this->starting_time = $starting_time;
02227   }
02228 
02238   function setEndingTime($ending_time = "") 
02239         {
02240     $this->ending_time = $ending_time;
02241   }
02242   
02252   function setCountSystem($a_count_system = COUNT_PARTIAL_SOLUTIONS) 
02253         {
02254     $this->count_system = $a_count_system;
02255   }
02256   
02266   function setMCScoring($a_mc_scoring = SCORE_ZERO_POINTS_WHEN_UNANSWERED) 
02267         {
02268     $this->mc_scoring = $a_mc_scoring;
02269   }
02270   
02280   function setPassScoring($a_pass_scoring = SCORE_LAST_PASS) 
02281         { 
02282                 switch ($a_pass_scoring)
02283                 {
02284                         case SCORE_BEST_PASS:
02285                                 $this->pass_scoring = SCORE_BEST_PASS;
02286                                 break;
02287                         default:
02288                                 $this->pass_scoring = SCORE_LAST_PASS;
02289                                 break;
02290                 }
02291   }
02292   
02302         function removeQuestion($question_id) 
02303         {
02304                 include_once "./assessment/classes/class.assQuestion.php";
02305                 $question = new ASS_Question();
02306                 include_once ("./classes/class.ilObjAssessmentFolder.php");
02307                 if (ilObjAssessmentFolder::_enabledAssessmentLogging())
02308                 {
02309                         $this->logAction($this->lng->txtlng("assessment", "log_question_removed", ilObjAssessmentFolder::_getLogLanguage()), $question_id);
02310                 }
02311                 $question->delete($question_id);
02312                 $this->removeAllTestEditings($question_id);
02313                 $this->loadQuestions();
02314                 $this->saveQuestionsToDb();
02315         }
02316         
02324         function clearEvalSelectedUsers()
02325         {
02326                 $query = sprintf("DELETE FROM tst_eval_users WHERE test_fi = %s",
02327                         $this->ilias->db->quote($this->getTestId())
02328                 );
02329                 $result = $this->ilias->db->query($query);
02330         }
02331         
02343         function removeAllTestEditings($question_id = "") 
02344         {
02345                 // remove test_active entries, because test has changed
02346                 $this->deleteActiveTests();
02347                 // remove selected users/groups
02348                 $this->clearEvalSelectedUsers();
02349                 
02350                 // remove the question from tst_solutions
02351                 if ($question_id) 
02352                 {
02353                         $query = sprintf("DELETE FROM tst_solutions WHERE test_fi = %s AND question_fi = %s",
02354                                 $this->ilias->db->quote($this->getTestId()),
02355                                 $this->ilias->db->quote($question_id)
02356                         );
02357                         $query2 = sprintf("DELETE FROM tst_active_qst_sol_settings WHERE test_fi = %s AND question_fi=%s",
02358                                 $this->ilias->db->quote($this->getTestId()),                            
02359                                 $this->ilias->db->quote($question_id)
02360                         );
02361                         $query3 = sprintf("DELETE FROM tst_test_result WHERE test_fi = %s AND question_fi = %s",
02362                                 $this->ilias->db->quote($this->getTestId()),
02363                                 $this->ilias->db->quote($question_id)
02364                         );
02365                 } else {
02366                         $query = sprintf("DELETE FROM tst_solutions WHERE test_fi = %s",
02367                                 $this->ilias->db->quote($this->getTestId())
02368                         );
02369                         $query2 = sprintf("DELETE FROM tst_active_qst_sol_settings WHERE test_fi = %s",
02370                                 $this->ilias->db->quote($this->getTestId())                                                     
02371                         );                      
02372                         $query3 = sprintf("DELETE FROM tst_test_result WHERE test_fi = %s",
02373                                 $this->ilias->db->quote($this->getTestId())
02374                         );
02375                 }
02376                 $result = $this->ilias->db->query($query);
02377                 $result = $this->ilias->db->query($query2);
02378                 $result = $this->ilias->db->query($query3);
02379 
02380                 if ($this->isRandomTest())
02381                 {
02382                         $query = sprintf("DELETE FROM tst_test_random_question WHERE test_fi = %s",
02383                                 $this->ilias->db->quote($this->getTestId())
02384                         );
02385                         $result = $this->ilias->db->query($query);
02386                 }
02387                 include_once ("./classes/class.ilObjAssessmentFolder.php");
02388                 if (ilObjAssessmentFolder::_enabledAssessmentLogging())
02389                 {
02390                         $this->logAction($this->lng->txtlng("assessment", "log_user_data_removed", ilObjAssessmentFolder::_getLogLanguage()));
02391                 }
02392         }
02393         
02405         function removeSelectedTestResults($user_ids) 
02406         {
02407                 global $ilDB;
02408                 
02409                 // remove test_active entries of selected users
02410                 foreach ($user_ids as $user_id)
02411                 {
02412                         $query = sprintf("DELETE FROM tst_active WHERE user_fi = %s AND test_fi = %s",
02413                                 $ilDB->quote($user_id . ""),
02414                                 $ilDB->quote($this->getTestId() . "")
02415                         );
02416                         $result = $ilDB->query($query);
02417                 }
02418                 
02419                 // remove selected users/groups
02420                 $this->clearEvalSelectedUsers();
02421                 
02422                 // remove the question from tst_solutions
02423                 foreach ($user_ids as $user_id)
02424                 {
02425                         $query = sprintf("DELETE FROM tst_solutions WHERE test_fi = %s AND user_fi = %s",
02426                                 $ilDB->quote($this->getTestId() . ""),
02427                                 $ilDB->quote($user_id . "")
02428                         );
02429                         $query2 = sprintf("DELETE FROM tst_active_qst_sol_settings WHERE test_fi = %s AND user_fi = %s",
02430                                 $ilDB->quote($this->getTestId() . ""),
02431                                 $ilDB->quote($user_id . "")
02432                         );                      
02433                         $query3 = sprintf("DELETE FROM tst_test_result WHERE test_fi = %s AND user_fi = %s",
02434                                 $ilDB->quote($this->getTestId() . ""),
02435                                 $ilDB->quote($user_id . "")
02436                         );
02437                         $result = $ilDB->query($query);
02438                         $result = $ilDB->query($query2);
02439                         $result = $ilDB->query($query3);
02440         
02441                         if ($this->isRandomTest())
02442                         {
02443                                 $query = sprintf("DELETE FROM tst_test_random_question WHERE test_fi = %s AND user_fi = %s",
02444                                         $ilDB->quote($this->getTestId() . ""),
02445                                         $ilDB->quote($user_id . "")
02446                                 );
02447                                 $result = $ilDB->query($query);
02448                         }
02449                         include_once ("./classes/class.ilObjAssessmentFolder.php");
02450                         if (ilObjAssessmentFolder::_enabledAssessmentLogging())
02451                         {
02452                                 include_once ("./classes/class.ilObjUser.php");
02453                                 $uname = ilObjUser::_lookupName($user_id);
02454                                 $this->logAction(sprintf($this->lng->txtlng("assessment", "log_selected_user_data_removed", ilObjAssessmentFolder::_getLogLanguage()), trim($uname["title"] . " " . $uname["firstname"] . " " . $uname["lastname"] . " (" . $uname["user_id"] . ")")));
02455                         }
02456                 }
02457         }
02458         
02467         function deleteActiveTests() 
02468         {
02469                 $query = sprintf("DELETE FROM tst_active WHERE test_fi = %s",
02470                         $this->ilias->db->quote($this->getTestId())
02471                 );
02472                 $result = $this->ilias->db->query($query);
02473         }
02474         
02485         function deleteResults($user_id = "") 
02486         {
02487                 if ($user_id) 
02488                 {
02489                         $pass = $this->_getPass($user_id, $this->getTestId());
02490                         $query = sprintf("DELETE FROM tst_solutions WHERE test_fi = %s AND user_fi = %s AND pass = %s",
02491                                 $this->ilias->db->quote($this->getTestId() . ""),
02492                                 $this->ilias->db->quote($user_id . ""),
02493                                 $this->ilias->db->quote($pass . "")
02494                         );
02495                         $result = $this->ilias->db->query($query);
02496                         $query = sprintf("DELETE FROM tst_test_result WHERE test_fi = %s AND user_fi = %s AND pass = %s",
02497                                 $this->ilias->db->quote($this->getTestId() . ""),
02498                                 $this->ilias->db->quote($user_id . ""),
02499                                 $this->ilias->db->quote($pass . "")
02500                         );
02501                         $result = $this->ilias->db->query($query);
02502                         $sequence_arr = array_flip($this->questions);
02503                         $sequence = join($sequence_arr, ",");
02504                         $query = sprintf("UPDATE tst_active SET sequence = %s, lastindex = %s WHERE test_fi = %s and user_fi = %s",
02505                                 $this->ilias->db->quote($sequence),
02506                                 $this->ilias->db->quote("1"),
02507                                 $this->ilias->db->quote($this->getTestId()),
02508                                 $this->ilias->db->quote($user_id)
02509                         );
02510                         $result = $this->ilias->db->query($query);
02511                         
02512                         $query = sprintf("DELETE FROM tst_active_qst_sol_settings WHERE test_fi = %s AND user_fi = %s",
02513                                 $this->ilias->db->quote($this->getTestId()),
02514                                 $this->ilias->db->quote($user_id)
02515                         );
02516                         $result = $this->ilias->db->query($query);
02517                 }
02518         }
02519         
02529         function questionMoveUp($question_id) 
02530         {
02531                 // Move a question up in sequence
02532                 $query = sprintf("SELECT * FROM tst_test_question WHERE test_fi=%s AND question_fi=%s",
02533                         $this->ilias->db->quote($this->getTestId()),
02534                         $this->ilias->db->quote($question_id)
02535                 );
02536                 $result = $this->ilias->db->query($query);
02537                 $data = $result->fetchRow(DB_FETCHMODE_OBJECT);
02538                 if ($data->sequence > 1) {
02539                         // OK, it's not the top question, so move it up
02540                         $query = sprintf("SELECT * FROM tst_test_question WHERE test_fi=%s AND sequence=%s",
02541                                 $this->ilias->db->quote($this->getTestId()),
02542                                 $this->ilias->db->quote($data->sequence - 1)
02543                         );
02544                         $result = $this->ilias->db->query($query);
02545                         $data_previous = $result->fetchRow(DB_FETCHMODE_OBJECT);
02546                         // change previous dataset
02547                         $query = sprintf("UPDATE tst_test_question SET sequence=%s WHERE test_question_id=%s",
02548                                 $this->ilias->db->quote($data->sequence),
02549                                 $this->ilias->db->quote($data_previous->test_question_id)
02550                         );
02551                         $result = $this->ilias->db->query($query);
02552                         // move actual dataset up
02553                         $query = sprintf("UPDATE tst_test_question SET sequence=%s WHERE test_question_id=%s",
02554                                 $this->ilias->db->quote($data->sequence - 1),
02555                                 $this->ilias->db->quote($data->test_question_id)
02556                         );
02557                         $result = $this->ilias->db->query($query);
02558                         include_once ("./classes/class.ilObjAssessmentFolder.php");
02559                         if (ilObjAssessmentFolder::_enabledAssessmentLogging())
02560                         {
02561                                 $this->logAction($this->lng->txtlng("assessment", "log_question_position_changed", ilObjAssessmentFolder::_getLogLanguage()) . ": " . ($data->sequence) . " => " . ($data->sequence-1), $question_id);
02562                         }
02563                 }
02564                 $this->loadQuestions();
02565         }
02566         
02576         function questionMoveDown($question_id) 
02577         {
02578                 // Move a question down in sequence
02579                 $query = sprintf("SELECT * FROM tst_test_question WHERE test_fi=%s AND question_fi=%s",
02580                         $this->ilias->db->quote($this->getTestId()),
02581                         $this->ilias->db->quote($question_id)
02582                 );
02583                 $result = $this->ilias->db->query($query);
02584                 $data = $result->fetchRow(DB_FETCHMODE_OBJECT);
02585                 $query = sprintf("SELECT * FROM tst_test_question WHERE test_fi=%s AND sequence=%s",
02586                         $this->ilias->db->quote($this->getTestId()),
02587                         $this->ilias->db->quote($data->sequence + 1)
02588                 );
02589                 $result = $this->ilias->db->query($query);
02590                 if ($result->numRows() == 1) 
02591                 {
02592                         // OK, it's not the last question, so move it down
02593                         $data_next = $result->fetchRow(DB_FETCHMODE_OBJECT);
02594                         // change next dataset
02595                         $query = sprintf("UPDATE tst_test_question SET sequence=%s WHERE test_question_id=%s",
02596                                 $this->ilias->db->quote($data->sequence),
02597                                 $this->ilias->db->quote($data_next->test_question_id)
02598                         );
02599                         $result = $this->ilias->db->query($query);
02600                         // move actual dataset down
02601                         $query = sprintf("UPDATE tst_test_question SET sequence=%s WHERE test_question_id=%s",
02602                                 $this->ilias->db->quote($data->sequence + 1),
02603                                 $this->ilias->db->quote($data->test_question_id)
02604                         );
02605                         $result = $this->ilias->db->query($query);
02606                         include_once ("./classes/class.ilObjAssessmentFolder.php");
02607                         if (ilObjAssessmentFolder::_enabledAssessmentLogging())
02608                         {
02609                                 $this->logAction($this->lng->txtlng("assessment", "log_question_position_changed", ilObjAssessmentFolder::_getLogLanguage()) . ": " . ($data->sequence) . " => " . ($data->sequence+1), $question_id);
02610                         }
02611                 }
02612                 $this->loadQuestions();
02613         }
02614         
02624         function duplicateQuestionForTest($question_id)
02625         {
02626                 global $ilUser;
02627                 $question =& ilObjTest::_instanciateQuestion($question_id);
02628                 $duplicate_id = $question->duplicate(true);
02629 
02630                 return $duplicate_id;
02631         }
02632 
02641         function insertQuestion($question_id)
02642         {
02643                 $duplicate_id = $this->duplicateQuestionForTest($question_id);
02644 
02645                 // get maximum sequence index in test
02646                 $query = sprintf("SELECT MAX(sequence) AS seq FROM tst_test_question WHERE test_fi=%s",
02647                         $this->ilias->db->quote($this->getTestId())
02648                         );
02649                 $result = $this->ilias->db->query($query);
02650                 $sequence = 1;
02651 
02652                 if ($result->numRows() == 1)
02653                 {
02654                         $data = $result->fetchRow(DB_FETCHMODE_OBJECT);
02655                         $sequence = $data->seq + 1;
02656                 }
02657 
02658                 $query = sprintf("INSERT INTO tst_test_question (test_question_id, test_fi, question_fi, sequence, TIMESTAMP) VALUES (NULL, %s, %s, %s, NULL)",
02659                         $this->ilias->db->quote($this->getTestId()),
02660                         $this->ilias->db->quote($duplicate_id),
02661                         $this->ilias->db->quote($sequence)
02662                         );
02663                 $result = $this->ilias->db->query($query);
02664                 if ($result != DB_OK)
02665                 {
02666                         // Error
02667                 }
02668                 else
02669                 {
02670                         include_once ("./classes/class.ilObjAssessmentFolder.php");
02671                         if (ilObjAssessmentFolder::_enabledAssessmentLogging())
02672                         {
02673                                 $this->logAction($this->lng->txtlng("assessment", "log_question_added", ilObjAssessmentFolder::_getLogLanguage()) . ": " . $sequence, $duplicate_id);
02674                         }
02675                 }
02676                 // remove test_active entries, because test has changed
02677                 $query = sprintf("DELETE FROM tst_active WHERE test_fi = %s",
02678                         $this->ilias->db->quote($this->getTestId())
02679                         );
02680                 $result = $this->ilias->db->query($query);
02681                 $this->loadQuestions();
02682                 $this->saveCompleteStatus();
02683         }
02684 
02694         function &getQuestionTitles() 
02695         {
02696                 $titles = array();
02697                 if (!$this->isRandomTest())
02698                 {
02699                         global $ilDB;
02700                         $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",
02701                                 $ilDB->quote($this->getTestId() . "")
02702                         );
02703                         $result = $ilDB->query($query);
02704                         while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC))
02705                         {
02706                                 array_push($titles, $row["title"]);
02707                         }
02708                 }
02709                 return $titles;
02710         }
02711         
02722         function getQuestionDataset($question_id) 
02723         {
02724                 $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",
02725                         $this->ilias->db->quote("$question_id")
02726                 );
02727     $result = $this->ilias->db->query($query);
02728                 $row = $result->fetchRow(DB_FETCHMODE_OBJECT);
02729                 return $row;
02730         }
02731         
02740         function &get_qpl_titles() 
02741         {
02742                 global $rbacsystem;
02743                 
02744                 $qpl_titles = array();
02745                 // get all available questionpools and remove the trashed questionspools
02746                 $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";
02747                 $result = $this->ilias->db->query($query);
02748                 while ($row = $result->fetchRow(DB_FETCHMODE_OBJECT))
02749                 {               
02750                         if ($rbacsystem->checkAccess("write", $row->ref_id) && ($this->_hasUntrashedReference($row->obj_id)))
02751                         {
02752                                 include_once("./assessment/classes/class.ilObjQuestionPool.php");
02753                                 if (ilObjQuestionPool::_lookupOnline($row->obj_id))
02754                                 {
02755                                         $qpl_titles["$row->obj_id"] = $row->title;
02756                                 }
02757                         }
02758                 }
02759                 return $qpl_titles;
02760         }
02761         
02770         function &getExistingQuestions($pass = NULL) 
02771         {
02772                 global $ilUser;
02773                 $existing_questions = array();
02774                 if ($this->isRandomTest())
02775                 {
02776                         if (is_null($pass)) $pass = 0;
02777                         $query = sprintf("SELECT qpl_questions.original_id FROM qpl_questions, tst_test_random_question WHERE tst_test_random_question.test_fi = %s AND tst_test_random_question.user_fi = %s AND tst_test_random_question.question_fi = qpl_questions.question_id AND tst_test_random_question.pass = %s",
02778                                 $this->ilias->db->quote($this->getTestId() . ""),
02779                                 $this->ilias->db->quote($ilUser->id . ""),
02780                                 $this->ilias->db->quote($pass . "")
02781                         );
02782                 }
02783                 else
02784                 {
02785                         $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",
02786                                 $this->ilias->db->quote($this->getTestId())
02787                         );
02788                 }
02789                 $result = $this->ilias->db->query($query);
02790                 while ($data = $result->fetchRow(DB_FETCHMODE_OBJECT)) {
02791                         array_push($existing_questions, $data->original_id);
02792                 }
02793                 return $existing_questions;
02794         }
02795         
02805   function getQuestionType($question_id) 
02806         {
02807     if ($question_id < 1)
02808       return -1;
02809     $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",
02810       $this->ilias->db->quote($question_id)
02811     );
02812     $result = $this->ilias->db->query($query);
02813     if ($result->numRows() == 1) {
02814       $data = $result->fetchRow(DB_FETCHMODE_OBJECT);
02815       return $data->type_tag;
02816     } else {
02817       return "";
02818     }
02819   }
02820         
02829         function startWorkingTime($user_id) 
02830         {
02831                 $result = "";
02832                 if (!($result = $this->getActiveTestUser($user_id))) {
02833                         $this->setActiveTestUser();
02834                         $result = $this->getActiveTestUser($user_id);
02835                 }
02836                 $q = sprintf("INSERT INTO tst_times (times_id, active_fi, started, finished, TIMESTAMP) VALUES (NULL, %s, %s, %s, NULL)",
02837                         $this->ilias->db->quote($result->active_id),
02838                         $this->ilias->db->quote(strftime("%Y-%m-%d %H:%M:%S")),
02839                         $this->ilias->db->quote(strftime("%Y-%m-%d %H:%M:%S"))
02840                 );
02841                 $result = $this->ilias->db->query($q);
02842                 return $this->ilias->db->getLastInsertId();
02843         }
02844         
02853         function updateWorkingTime($times_id)
02854         {
02855                 $q = sprintf("UPDATE tst_times SET finished = %s WHERE times_id = %s",
02856                         $this->ilias->db->quote(strftime("%Y-%m-%d %H:%M:%S")),
02857                         $this->ilias->db->quote($times_id)
02858                 );
02859                 $result = $this->ilias->db->query($q);
02860         }
02861   
02871         function getQuestionIdFromActiveUserSequence($sequence) 
02872         {
02873                 global $ilUser;
02874 
02875                 $active = $this->getActiveTestUser();
02876                 $sequence_array = split(",", $active->sequence);
02877                 return $this->questions[$sequence_array[$sequence-1]];
02878         }
02879         
02888         function &getAllQuestionsForActiveUser() 
02889         {
02890                 $result_array = array();
02891                 $active = $this->getActiveTestUser();
02892                 $sequence_array = split(",", $active->sequence);
02893                 $all_questions = &$this->getAllQuestions();
02894                 $worked_questions = &$this->getWorkedQuestions();
02895                 foreach ($sequence_array as $sequence)
02896                 {
02897                         if (in_array($this->questions[$sequence], $worked_questions))
02898                         {
02899                                 $all_questions[$this->questions[$sequence]]["worked"] = 1;
02900                         }
02901                         else
02902                         {
02903                                 $all_questions[$this->questions[$sequence]]["worked"] = 0;
02904                         }
02905                         array_push($result_array, $all_questions[$this->questions[$sequence]]);
02906                 }
02907                 return $result_array;
02908         }
02909 
02910         function getWrongAnsweredQuestions()
02911         {
02912                 global $ilUser;
02913 
02914                 foreach($all_questions =& $this->getAllQuestionsForActiveUser() as $question)
02915                 {
02916                         foreach($this->getTestResult($ilUser->getId()) as $result)
02917                         {
02918                                 if($result['qid'] == $question['question_id'])
02919                                 {
02920                                         if($result['max'] != $result['reached'])
02921                                         {
02922                                                 $wrong[] = $question;
02923                                         }
02924                                 }
02925                         }
02926                 }
02927                 return $wrong ? $wrong : array();
02928         }
02929 
02930 
02931         function getFirstSequence()
02932         {
02933                 global $ilUser;
02934 
02935                 $results = $this->getTestResult($ilUser->getId());
02936 
02937                 for($i = 1; $i <= $this->getQuestionCount(); $i++)
02938                 {
02939                         $qid = $this->getQuestionIdFromActiveUserSequence($i);
02940 
02941                         foreach($results as $result)
02942                         {
02943                                 if($qid == $result['qid'])
02944                                 {
02945                                         if(!$result['max'] or $result['max'] != $result['reached'])
02946                                         {
02947                                                 return $i;
02948                                         }
02949                                 }
02950                         }
02951                 }
02952                 return 0;
02953         }
02954 
02955         
02964         function &getWorkedQuestions($pass = NULL)
02965         {
02966                 global $ilUser;
02967                 if (is_null($pass))
02968                 {
02969                         $query = sprintf("SELECT * FROM tst_solutions WHERE user_fi = %s AND test_fi = %s AND pass = 0 GROUP BY question_fi",
02970                                 $this->ilias->db->quote($ilUser->id),
02971                                 $this->ilias->db->quote($this->getTestId())
02972                         );
02973                 }
02974                 else
02975                 {
02976                         $query = sprintf("SELECT * FROM tst_solutions WHERE user_fi = %s AND test_fi = %s AND pass = %s GROUP BY question_fi",
02977                                 $this->ilias->db->quote($ilUser->id . ""),
02978                                 $this->ilias->db->quote($this->getTestId() . ""),
02979                                 $this->ilias->db->quote($pass . "")
02980                         );
02981                 }
02982                 $result = $this->ilias->db->query($query);
02983                 $result_array = array();
02984                 while ($row = $result->fetchRow(DB_FETCHMODE_OBJECT))
02985                 {
02986                         array_push($result_array, $row->question_fi);
02987                 }
02988                 return $result_array;
02989         }
02990         
02999         function &getAllQuestions($pass = NULL)
03000         {
03001                 global $ilUser;
03002                 
03003                 if ($this->isRandomTest())
03004                 {
03005                         if (is_null($pass)) $pass = 0;
03006                         $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.user_fi = %s AND tst_test_random_question.pass = %s AND qpl_questions.question_id IN (" . join($this->questions, ",") . ")",
03007                                 $this->ilias->db->quote($ilUser->id . ""),
03008                                 $this->ilias->db->quote($pass . "")
03009                         );
03010                 }
03011                 else
03012                 {
03013                         $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, ",") . ")";
03014                 }
03015                 $result = $this->ilias->db->query($query);
03016                 $result_array = array();
03017                 while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC))
03018                 {
03019                         $result_array[$row["question_id"]] = $row;
03020                 }
03021                 return $result_array;
03022         }
03023         
03033         function getActiveTestUser($user_id = "") 
03034         {
03035                 global $ilDB;
03036                 global $ilUser;
03037                 $db =& $ilDB->db;
03038                 if (!$user_id) 
03039                 {
03040                         $user_id = $ilUser->id;
03041                 }
03042                 $query = sprintf("SELECT * FROM tst_active WHERE user_fi = %s AND test_fi = %s",
03043                         $db->quote($user_id),
03044                         $db->quote($this->test_id)
03045                 );
03046         
03047                 $result = $db->query($query);
03048                 if ($result->numRows()) {
03049                         $this->active = $result->fetchRow(DB_FETCHMODE_OBJECT);
03050                 } 
03051                 else 
03052                 {
03053                         $this->active = null;
03054                 }
03055                 return $this->active;
03056         }
03057         
03068         function _getActiveTestUser($user_id = "", $test_id = "") {
03069                 global $ilDB;
03070                 global $ilUser;
03071                 
03072                 $db =& $ilDB->db;
03073                 if (!$user_id) {
03074                         $user_id = $ilUser->id;
03075                 }
03076                 if (!$test_id)
03077                 {
03078                         return "";
03079                 }
03080                 $query = sprintf("SELECT * FROM tst_active WHERE user_fi = %s AND test_fi = %s",
03081                         $db->quote($user_id),
03082                         $db->quote($test_id)
03083                 );
03084                 
03085                 $result = $db->query($query);
03086                 if ($result->numRows()) {
03087                         return $result->fetchRow(DB_FETCHMODE_OBJECT);
03088                 } else {
03089                         return "";
03090                 }
03091         }
03092         
03105         function setActiveTestUser($lastindex = 1, $postpone = "", $addTries = false) 
03106         {
03107                 global $ilDB;
03108                 global $ilUser;
03109                 
03110                 if ($lastindex < 1) $lastindex = 1;
03111                 $db =& $ilDB->db;
03112                 $old_active = $this->getActiveTestUser();
03113                 if ($old_active) 
03114                 {
03115                         $sequence = $old_active->sequence;
03116                         $postponed = $old_active->postponed;
03117                         if ($postpone) 
03118                         {
03119                                 $sequence_array = split(",", $sequence);
03120                                 $postpone_sequence = $sequence_array[$postpone-1];
03121                                 $question_id = $this->questions[$postpone_sequence];
03122                                 unset($sequence_array[$postpone-1]);
03123                                 array_push($sequence_array, $postpone_sequence);
03124                                 $sequence = join(",", $sequence_array);
03125                                 $postponed .= ",$question_id";
03126                                 $postponed = preg_replace("/^,/", "", $postponed);
03127                         }
03128                         $tries = $old_active->tries;
03129                         if ($addTries && ($this->getNrOfResultsForPass($ilUser->getId(), $old_active->tries) > 0)) 
03130                         {
03131                                 // only add the number of tries if there are ANY results for the current
03132                                 // test pass. Otherwise something must be wrong (doubleclick, reload etc.)
03133                                 $tries++;
03134                         }
03135                         $query = sprintf("UPDATE tst_active SET lastindex = %s, sequence = %s, postponed = %s, tries = %s WHERE user_fi = %s AND test_fi = %s",
03136                                 $db->quote($lastindex),
03137                                 $db->quote($sequence),
03138                                 $db->quote($postponed),
03139                                 $db->quote($tries),
03140                                 $db->quote($ilUser->id),
03141                                 $db->quote($this->test_id)
03142                         );
03143                 }
03144                 else 
03145                 {
03146                         $sequence_arr = array_flip($this->questions);
03147                         $sequence = join($sequence_arr, ",");
03148                         $query = sprintf("INSERT INTO tst_active (active_id, user_fi, test_fi, sequence, postponed, lastindex, tries, TIMESTAMP) VALUES (NULL, %s, %s, %s, %s, %s, %s, NULL)",
03149                                 $db->quote($ilUser->id),
03150                                 $db->quote($this->test_id),
03151                                 $db->quote($sequence),
03152                                 $db->quote(""),
03153                                 $db->quote($lastindex),
03154                                 $db->quote(0)
03155                         );
03156                 }
03157                 $db->query($query);
03158         }
03159         
03169         function &getTestResult($user_id, $pass = NULL)
03170         {
03171                 //              global $ilBench;
03172                 if ($this->isRandomTest())
03173                 {
03174                         $this->loadQuestions($user_id, $pass);
03175                 }
03176                 $total_max_points = 0;
03177                 $total_reached_points = 0;
03178                 
03179                 $key = 1;
03180                 $result_array = array();
03181                 include_once "./assessment/classes/class.assQuestion.php";
03182                 $workedthrough = 0;
03183                 foreach ($this->questions as $value)
03184                 {
03185                         $max_points = ASS_Question::_getMaximumPoints($value);
03186                         $total_max_points += $max_points;
03187                         $reached_points = ASS_Question::_getReachedPoints($user_id, $this->getTestId(), $value, $pass);
03188                         if (ASS_Question::_isWorkedThrough($user_id, $this->getTestId(), $value, $pass))
03189                         {
03190                                 $workedthrough = 1;
03191                         }
03192                         else
03193                         {
03194                                 $workedthrough = 0;
03195                         }
03196                         $total_reached_points += $reached_points;
03197                         if ($max_points > 0)
03198                         {
03199                                 $percentvalue = $reached_points / $max_points;
03200                         }
03201                         else
03202                         {
03203                                 $percentvalue = 0;
03204                         }
03205                         if (ASS_Question::_getSuggestedSolutionCount($value) == 1)
03206                         {
03207                                 $solution_array =& ASS_Question::_getSuggestedSolution($value, 0);
03208                                 $href = ASS_Question::_getInternalLinkHref($solution_array["internal_link"]);
03209                         }
03210                         elseif (ASS_Question::_getSuggestedSolutionCount($value) > 1)
03211                         {
03212                                 $href = "see_details_for_further_information";
03213                         }
03214                         else
03215                         {
03216                                 $href = "";
03217                         }
03218                         $info =& ASS_Question::_getQuestionInfo($value);
03219                         include_once "./classes/class.ilUtil.php";
03220                         $row = array(
03221                                 "nr" => "$key",
03222                                 "title" => ilUtil::prepareFormOutput($info["title"]),
03223                                 "max" => sprintf("%d", $max_points),
03224                                 "reached" => sprintf("%d", $reached_points),
03225                                 "percent" => sprintf("%2.2f ", ($percentvalue) * 100) . "%",
03226                                 "solution" => $href,
03227                                 "type" => $info["type_tag"],
03228                                 "qid" => $value,
03229                                 "workedthrough" => $workedthrough
03230                         );
03231                         array_push($result_array, $row);
03232                         $key++;
03233                 }
03234                 $result_array["test"]["total_max_points"] = $total_max_points;
03235                 $result_array["test"]["total_reached_points"] = $total_reached_points;
03236                 if ((!$total_reached_points) or (!$total_max_points))
03237                 {
03238                         $percentage = 0.0;
03239                 }
03240                 else
03241                 {
03242                         $percentage = ($total_reached_points / $total_max_points) * 100.0;
03243                 }
03244                 $mark_obj = $this->mark_schema->get_matching_mark($percentage);
03245                 $passed = "";
03246                 if ($mark_obj)
03247                 {
03248                         if ($mark_obj->get_passed())
03249                         {
03250                                 $passed = 1;
03251                         }
03252                         else
03253                         {
03254                                 $passed = 0;
03255                         }
03256                 }
03257                 $result_array["test"]["passed"] = $passed;
03258                 return $result_array;
03259         }
03260 
03261 
03270         function &getTestSummary($user_id, $pass = NULL)
03271         {
03272                 global $ilDB;
03273                 if ($this->isRandomTest())
03274                 {
03275                         $this->loadQuestions($user_id, $pass);
03276                 }
03277                 
03278                 $key = 1;
03279                 $result_array = array();
03280 
03281                 $active = $this->getActiveTestUser();
03282                 $solved_questions = ilObjTest::_getSolvedQuestions($this->test_id, $user_id);
03283                 include_once "./classes/class.ilObjUser.php";
03284                 $user = new ilObjUser($user_id);
03285                 foreach ($this->questions as $val) 
03286                 {
03287                         $question =& ilObjTest::_instanciateQuestion($val);
03288                         if (is_object($question))
03289                         {                       
03290                                 $answers = $question->getSolutionValues($this->test_id, $user);
03291                                 $visited = count($answers);
03292                                 $solved  = 0;
03293                                 if (array_key_exists($question->getId(),$solved_questions)) {
03294                                         $solved =  $solved_questions[$question->getId()]->solved; 
03295                                 }
03296                                 
03297                                 $row = array(
03298                                         "nr" => "$key",                                 
03299                                         "title" => $question->getTitle(),
03300                                         "qid" => $question->getId(),
03301                                         "visited" => $visited,
03302                                         "solved" => (($solved)?"1":"0"),
03303                                         "description" => $question->getComment(),
03304                                         "points" => $question->getMaximumPoints()
03305                                 );
03306                                 array_push($result_array, $row);
03307                                 $key++;
03308                         }                       
03309                 }
03310                 
03311                 return $result_array;
03312         }
03313 
03314         
03324         function &_getTestResult($user_id, $test_obj_id, $pass = NULL) 
03325         {
03326                 $test = new ilObjTest($test_obj_id, false);
03327                 $test->loadFromDb();
03328                 $result =& $test->getTestResult($user_id, $pass);
03329                 return $result;
03330         }
03331 
03340         function evalTotalPersons()
03341         {
03342                 $q = sprintf("SELECT COUNT(*) as total FROM tst_active WHERE test_fi = %s",
03343                         $this->ilias->db->quote($this->getTestId())
03344                 );
03345                 $result = $this->ilias->db->query($q);
03346                 $row = $result->fetchRow(DB_FETCHMODE_OBJECT);
03347                 return $row->total;
03348         }
03349         
03358         function canViewResults()
03359         {
03360                 $result = true;
03361                 if ($this->getTestType() != TYPE_SELF_ASSESSMENT)
03362                 {
03363                         if ($this->getReportingDate())
03364                         {
03365                                 if (preg_match("/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/", $this->getReportingDate(), $matches))
03366                                 {
03367                                         $epoch_time = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
03368                                         $now = mktime();
03369                                         if ($now < $epoch_time) 
03370                                         {
03371                                                 $result = false;
03372                                         }
03373                                 }
03374                         }
03375                 }
03376                 return $result;
03377         }
03378 
03387         function evalLoadStatisticalSettings($user_id)
03388         {
03389                 $q = sprintf("SELECT * FROM tst_eval_settings WHERE user_fi = %s",
03390                         $this->ilias->db->quote("$user_id")
03391                 );
03392                 $result = $this->ilias->db->query($q);
03393                 if (!$result->numRows()) 
03394                 {
03395                         $row = array(
03396                                 "qworkedthrough" => "1",
03397                                 "pworkedthrough" => "1",
03398                                 "timeofwork" => "1",
03399                                 "atimeofwork" => "1",
03400                                 "firstvisit" => "1",
03401                                 "lastvisit" => "1",
03402                                 "resultspoints" => "1",
03403                                 "resultsmarks" => "1",
03404                                 "distancemedian" => "1"
03405                         );
03406                 } 
03407                         else 
03408                 {
03409                         $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
03410                         unset($row["eval_settings_id"]);
03411                 }
03412                 return $row;            
03413         }
03414         
03423         function evalSaveStatisticalSettings($settings_array, $user_id)
03424         {
03425                 $q = sprintf("SELECT * FROM tst_eval_settings WHERE user_fi = %s",
03426                         $this->ilias->db->quote("$user_id")
03427                 );
03428                 $result = $this->ilias->db->query($q);
03429                 if ($result->numRows() > 0)
03430                 {
03431                         $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
03432                 }
03433                 $update = $row["eval_settings_id"];
03434                 if (!$update) {
03435                         $q = sprintf("INSERT INTO tst_eval_settings ".
03436                                          "(eval_settings_id, user_fi, qworkedthrough, pworkedthrough, timeofwork, atimeofwork, firstvisit, " .
03437                                          "lastvisit, resultspoints, resultsmarks, distancemedian, TIMESTAMP) VALUES " .
03438                                          "(NULL, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, NULL)",
03439                                 $this->ilias->db->quote("$user_id"),
03440                                 $this->ilias->db->quote(sprintf("%01d", $settings_array["qworkedthrough"])),
03441                                 $this->ilias->db->quote(sprintf("%01d", $settings_array["pworkedthrough"])),
03442                                 $this->ilias->db->quote(sprintf("%01d", $settings_array["timeofwork"])),
03443                                 $this->ilias->db->quote(sprintf("%01d", $settings_array["atimeofwork"])),
03444                                 $this->ilias->db->quote(sprintf("%01d", $settings_array["firstvisit"])),
03445                                 $this->ilias->db->quote(sprintf("%01d", $settings_array["lastvisit"])),
03446                                 $this->ilias->db->quote(sprintf("%01d", $settings_array["resultspoints"])),
03447                                 $this->ilias->db->quote(sprintf("%01d", $settings_array["resultsmarks"])),
03448                                 $this->ilias->db->quote(sprintf("%01d", $settings_array["distancemedian"]))
03449                         );
03450                 } 
03451                         else 
03452                 {
03453                         $q = sprintf("UPDATE tst_eval_settings SET ".
03454                                          "qworkedthrough = %s, pworkedthrough = %s, timeofwork = %s, atimeofwork = %s, firstvisit = %s, " .
03455                                          "lastvisit = %s, resultspoints = %s, resultsmarks = %s, distancemedian = %s " .
03456                                          "WHERE eval_settings_id = %s",
03457                                 $this->ilias->db->quote(sprintf("%01d", $settings_array["qworkedthrough"])),
03458                                 $this->ilias->db->quote(sprintf("%01d", $settings_array["pworkedthrough"])),
03459                                 $this->ilias->db->quote(sprintf("%01d", $settings_array["timeofwork"])),
03460                                 $this->ilias->db->quote(sprintf("%01d", $settings_array["atimeofwork"])),
03461                                 $this->ilias->db->quote(sprintf("%01d", $settings_array["firstvisit"])),
03462                                 $this->ilias->db->quote(sprintf("%01d", $settings_array["lastvisit"])),
03463                                 $this->ilias->db->quote(sprintf("%01d", $settings_array["resultspoints"])),
03464                                 $this->ilias->db->quote(sprintf("%01d", $settings_array["resultsmarks"])),
03465                                 $this->ilias->db->quote(sprintf("%01d", $settings_array["distancemedian"])),
03466                                 $this->ilias->db->quote("$update")
03467                         );
03468                 }
03469                 $result = $this->ilias->db->query($q);
03470         }
03471 
03480         function getCompleteWorkingTime($user_id)
03481         {
03482                 $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",
03483                         $this->ilias->db->quote($this->getTestId()),
03484                         $this->ilias->db->quote($user_id)
03485                 );
03486                 $result = $this->ilias->db->query($q);
03487                 $time = 0;
03488                 while ($row = $result->fetchRow(DB_FETCHMODE_OBJECT)) 
03489                 {
03490                         preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row->started, $matches);
03491                         $epoch_1 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
03492                         preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row->finished, $matches);
03493                         $epoch_2 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
03494                         $time += ($epoch_2 - $epoch_1);
03495                 }
03496                 return $time;
03497         }
03498         
03507         function &evalStatistical($user_id)
03508         {
03509 //              global $ilBench;
03510                 $pass = ilObjTest::_getResultPass($user_id, $this->getTestId());
03511                 $test_result =& $this->getTestResult($user_id, $pass);
03512                 $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",
03513                         $this->ilias->db->quote($this->getTestId()),
03514                         $this->ilias->db->quote($user_id)
03515                 );
03516                 $result = $this->ilias->db->query($q);
03517                 $times = array();
03518                 $first_visit = 0;
03519                 $last_visit = 0;
03520                 while ($row = $result->fetchRow(DB_FETCHMODE_OBJECT)) {
03521                         preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row->started, $matches);
03522                         $epoch_1 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
03523                         if (!$first_visit) {
03524                                 $first_visit = $epoch_1;
03525                         }
03526                         if ($epoch_1 < $first_visit) {
03527                                 $first_visit = $epoch_1;
03528                         }
03529                         preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row->finished, $matches);
03530                         $epoch_2 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
03531                         if (!$last_visit) {
03532                                 $last_visit = $epoch_2;
03533                         }
03534                         if ($epoch_2 > $last_visit) {
03535                                 $last_visit = $epoch_2;
03536                         }
03537                         $times[$row->active_fi] += ($epoch_2 - $epoch_1);
03538                 }
03539                 $max_time = 0;
03540                 foreach ($times as $key => $value) {
03541                         $max_time += $value;
03542                 }
03543                 if ((!$test_result["test"]["total_reached_points"]) or (!$test_result["test"]["total_max_points"])) {
03544                         $percentage = 0.0;
03545                 } else {
03546                         $percentage = ($test_result["test"]["total_reached_points"] / $test_result["test"]["total_max_points"]) * 100.0;
03547                 }
03548                 $mark_obj = $this->mark_schema->get_matching_mark($percentage);
03549                 $first_date = getdate($first_visit);
03550                 $last_date = getdate($last_visit);
03551                 $qworkedthrough = 0;
03552                 foreach ($test_result as $key => $value)
03553                 {
03554                         if (preg_match("/\d+/", $key))
03555                         {
03556                                 $qworkedthrough += $value["workedthrough"];
03557                         }
03558                 }
03559                 if (!$qworkedthrough)
03560                 {
03561                         $atimeofwork = 0;
03562                 }
03563                 else
03564                 {
03565                         $atimeofwork = $max_time / $qworkedthrough;
03566                 }
03567                 $result_mark = "";
03568                 $passed = "";
03569                 if ($mark_obj)
03570                 {
03571                         $result_mark = $mark_obj->get_short_name();
03572                         if ($mark_obj->get_passed())
03573                         {
03574                                 $passed = 1;
03575                         }
03576                         else
03577                         {
03578                                 $passed = 0;
03579                         }
03580                 }
03581                 $result_array = array(
03582                         "qworkedthrough" => $qworkedthrough,
03583                         "qmax" => count($this->questions),
03584                         "pworkedthrough" => $qworkedthrough / count($this->questions),
03585                         "timeofwork" => $max_time,
03586                         "atimeofwork" => $atimeofwork,
03587                         "firstvisit" => $first_date,
03588                         "lastvisit" => $last_date,
03589                         "resultspoints" => $test_result["test"]["total_reached_points"],
03590                         "maxpoints" => $test_result["test"]["total_max_points"],
03591                         "resultsmarks" => $result_mark,
03592                         "passed" => $passed,
03593                         "distancemedian" => "0"
03594                 );
03595                 foreach ($test_result as $key => $value)
03596                 {
03597                         if (preg_match("/\d+/", $key))
03598                         {
03599                                 $result_array[$key] = $value;
03600                         }
03601                 }
03602                 return $result_array;
03603         }
03604 
03614         function &getTotalPointsArray()
03615         {
03616                 $totalpoints_array = array();
03617                 $all_users =& $this->evalTotalPersonsArray();
03618                 foreach ($all_users as $user_id => $user_name)
03619                 {
03620                         $test_result =& $this->getTestResult($user_id);
03621                         array_push($totalpoints_array, $test_result["test"]["total_reached_points"]);
03622                 }
03623                 return $totalpoints_array;
03624         }
03625         
03635         function &getTotalPointsPassedArray()
03636         {
03637                 $totalpoints_array = array();
03638                 $all_users =& $this->evalTotalPersonsArray();
03639                 foreach ($all_users as $user_id => $user_name)
03640                 {
03641                         $test_result =& $this->getTestResult($user_id);
03642                         $reached = $test_result["test"]["total_reached_points"];
03643                         $total = $test_result["test"]["total_max_points"];
03644                         $percentage = $reached/$total;
03645                         $mark = $this->mark_schema->get_matching_mark($percentage*100.0);
03646                         if ($mark)
03647                         {
03648                                 if ($mark->get_passed())
03649                                 {
03650                                         array_push($totalpoints_array, $test_result["test"]["total_reached_points"]);
03651                                 }
03652                         }
03653                 }
03654                 return $totalpoints_array;
03655         }
03656 
03665         function &evalTotalPersonsArray($name_sort_order = "asc")
03666         {
03667                 $q = sprintf("SELECT tst_active.user_fi, 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),
03668                         $this->ilias->db->quote($this->getTestId())
03669                 );
03670                 $result = $this->ilias->db->query($q);
03671                 $persons_array = array();
03672                 while ($row = $result->fetchRow(DB_FETCHMODE_OBJECT))
03673                 {
03674                         if (strlen($row->firstname.$row->lastname.$row->title) == 0)
03675                         {
03676                                 $persons_array[$row->user_fi] = array("fullname" => $this->lng->txt("deleted_user"), "firstname" => "", "lastname" => $this->lng->txt("deleted_user"));
03677                         }
03678                         else
03679                         {
03680                                 $persons_array[$row->user_fi] = array("fullname" => trim("$row->lastname, $row->firstname $row->title"), "firstname" => $row->firstname, "lastname" => $row->lastname);
03681                         }
03682                         if ($this->getTestType() == TYPE_SELF_ASSESSMENT)
03683                         {
03684                                 $persons_array[$row->user_fi] = array("fullname" => $this->lng->txt("unknown"), "firstname" => $this->lng->txt("unknown"), "lastname" => $this->lng->txt("unknown"));
03685                         }
03686                 }
03687                 return $persons_array;
03688         }
03689         
03698         function evalTotalFinished()
03699         {
03700                 $q = sprintf("SELECT COUNT(*) as total FROM tst_active WHERE test_fi = %s AND tries > 0",
03701                         $this->ilias->db->quote($this->getTestId())
03702                 );
03703                 $result = $this->ilias->db->query($q);
03704                 $row = $result->fetchRow(DB_FETCHMODE_OBJECT);
03705                 return $row->total;
03706         }
03707         
03717         function evalTotalFinishedPassed()
03718         {
03719                 $q = sprintf("SELECT * FROM tst_active WHERE test_fi = %s",
03720                         $this->ilias->db->quote($this->getTestId())
03721                 );
03722                 $result = $this->ilias->db->query($q);
03723                 $points = array();
03724                 $passed_tests = 0;
03725                 $failed_tests = 0;
03726                 $maximum_points = 0;
03727                 while ($row = $result->fetchRow(DB_FETCHMODE_OBJECT)) 
03728                 {
03729                         $pass = ilObjTest::_getResultPass($row->user_fi, $this->getTestId());
03730                         $res =& $this->getTestResult($row->user_fi, $pass);
03731                         if ((!$res["test"]["total_reached_points"]) or (!$res["test"]["total_max_points"])) 
03732                         {
03733                                 $percentage = 0.0;
03734                         } 
03735                                 else 
03736                         {
03737                                 $percentage = ($res["test"]["total_reached_points"] / $res["test"]["total_max_points"]) * 100.0;
03738                         }
03739                         $mark_obj = $this->mark_schema->get_matching_mark($percentage);
03740                         $maximum_points = $res["test"]["total_max_points"];
03741                         if ($mark_obj)
03742                         {
03743                                 if ($mark_obj->get_passed()) {
03744                                         $passed_tests++;
03745                                         array_push($points, $res["test"]["total_reached_points"]);
03746                                 } 
03747                                         else 
03748                                 {
03749                                         $failed_tests++;
03750                                 }
03751                         }
03752                 }
03753                 $reached_points = 0;
03754                 $counter = 0;
03755                 foreach ($points as $key => $value) 
03756                 {
03757                         $reached_points += $value;
03758                         $counter++;
03759                 }
03760                 if ($counter) 
03761                 {
03762                         $average_points = ($reached_points / $counter);
03763                 } 
03764                         else 
03765                 {
03766                         $average_points = 0;
03767                 }
03768                 return array(
03769                         "total_passed" => $passed_tests,
03770                         "total_failed" => $failed_tests,
03771                         "average_points" => $average_points,
03772                         "maximum_points" => $maximum_points
03773                 );
03774         }
03775         
03784         function evalTotalFinishedAverageTime()
03785         {
03786                 $q = sprintf("SELECT tst_times.* FROM tst_active, tst_times WHERE tst_active.test_fi = %s AND tst_active.tries > 0 AND tst_active.active_id = tst_times.active_fi",
03787                         $this->ilias->db->quote($this->getTestId())
03788                 );
03789                 $result = $this->ilias->db->query($q);
03790                 $times = array();
03791                 while ($row = $result->fetchRow(DB_FETCHMODE_OBJECT)) 
03792                 {
03793                         preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row->started, $matches);
03794                         $epoch_1 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
03795                         preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row->finished, $matches);
03796                         $epoch_2 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
03797                         $times[$row->active_fi] += ($epoch_2 - $epoch_1);
03798                 }
03799                 $max_time = 0;
03800                 $counter = 0;
03801                 foreach ($times as $key => $value) 
03802                 {
03803                         $max_time += $value;
03804                         $counter++;
03805                 }
03806                 if ($counter) 
03807                 {
03808                         $average_time = round($max_time / $counter);
03809                 } 
03810                         else 
03811                 {
03812                         $average_time = 0;
03813                 }
03814                 return $average_time;
03815         }
03816         
03825         function evalTotalStartedAverageTime()
03826         {
03827                 $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",
03828                         $this->ilias->db->quote($this->getTestId())
03829                 );
03830                 $result = $this->ilias->db->query($q);
03831                 $times = array();
03832                 while ($row = $result->fetchRow(DB_FETCHMODE_OBJECT)) 
03833                 {
03834                         preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row->started, $matches);
03835                         $epoch_1 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
03836                         preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row->finished, $matches);
03837                         $epoch_2 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
03838                         $times[$row->active_fi] += ($epoch_2 - $epoch_1);
03839                 }
03840                 $max_time = 0;
03841                 $counter = 0;
03842                 foreach ($times as $key => $value) 
03843                 {
03844                         $max_time += $value;
03845                         $counter++;
03846                 }
03847                 if ($counter) 
03848                 {
03849                         $average_time = round($max_time / $counter);
03850                 } 
03851                         else 
03852                 {
03853                         $average_time = 0;
03854                 }
03855                 return $average_time;
03856         }
03857         
03866         function evalTotalPassedAverageTime()
03867         {
03868                 include_once "./assessment/classes/class.ilObjTestAccess.php";
03869                 $passed_users =& ilObjTest::_getPassedUsers($this->getId());
03870                 $q = sprintf("SELECT tst_times.*, tst_active.user_fi FROM tst_active, tst_times WHERE tst_active.test_fi = %s AND tst_active.active_id = tst_times.active_fi",
03871                         $this->ilias->db->quote($this->getTestId())
03872                 );
03873                 $result = $this->ilias->db->query($q);
03874                 $times = array();
03875                 while ($row = $result->fetchRow(DB_FETCHMODE_OBJECT)) 
03876                 {
03877                         if (in_array($row->user_fi, $passed_users))
03878                         {
03879                                 preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row->started, $matches);
03880                                 $epoch_1 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
03881                                 preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row->finished, $matches);
03882                                 $epoch_2 = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
03883                                 $times[$row->active_fi] += ($epoch_2 - $epoch_1);
03884                         }
03885                 }
03886                 $max_time = 0;
03887                 $counter = 0;
03888                 foreach ($times as $key => $value) 
03889                 {
03890                         $max_time += $value;
03891                         $counter++;
03892                 }
03893                 if ($counter) 
03894                 {
03895                         $average_time = round($max_time / $counter);
03896                 } 
03897                         else 
03898                 {
03899                         $average_time = 0;
03900                 }
03901                 return $average_time;
03902         }
03903         
03912         function &getAvailableQuestionpoolIDs()
03913         {
03914                 global $rbacsystem;
03915                 
03916                 $result_array = array();
03917                 $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'";
03918                 $result = $this->ilias->db->query($query);
03919                 while ($row = $result->fetchRow(DB_FETCHMODE_OBJECT))
03920                 {               
03921                         if ($rbacsystem->checkAccess("write", $row->ref_id) && ($this->_hasUntrashedReference($row->obj_id)))
03922                         {
03923                                 include_once("./assessment/classes/class.ilObjQuestionPool.php");
03924                                 if (ilObjQuestionPool::_lookupOnline($row->obj_id))
03925                                 {
03926                                         array_push($result_array, $row->obj_id);
03927                                 }
03928                         }
03929                 }
03930                 return $result_array;
03931         }
03932 
03941         function &getAvailableQuestionpools($use_object_id = false, $equal_points = false, $could_be_offline = false)
03942         {
03943                 global $rbacsystem;
03944                 
03945                 $result_array = array();
03946                 $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";
03947                 $result = $this->ilias->db->query($query);
03948                 while ($row = $result->fetchRow(DB_FETCHMODE_OBJECT))
03949                 {               
03950                         if ($rbacsystem->checkAccess("write", $row->ref_id) && ($this->_hasUntrashedReference($row->obj_id)))
03951                         {
03952                                 include_once("./assessment/classes/class.ilObjQuestionPool.php");
03953                                 if (ilObjQuestionPool::_lookupOnline($row->obj_id) || $could_be_offline)
03954                                 {
03955                                         if ((!$equal_points) || (($equal_points) && (ilObjQuestionPool::_hasEqualPoints($row->obj_id))))
03956                                         {
03957                                                 if ($use_object_id)
03958                                                 {
03959                                                         $result_array[$row->obj_id] = $row->title;
03960                                                 }
03961                                                 else
03962                                                 {
03963                                                         $result_array[$row->ref_id] = $row->title;
03964                                                 }
03965                                         }
03966                                 }
03967                         }
03968                 }
03969                 return $result_array;
03970         }
03971 
03980         function getEstimatedWorkingTime() 
03981         {
03982                 $time_in_seconds = 0;
03983                 foreach ($this->questions as $question_id) 
03984                 {
03985                         $question =& ilObjTest::_instanciateQuestion($question_id);
03986                         $est_time = $question->getEstimatedWorkingTime();
03987                         $time_in_seconds += $est_time["h"] * 3600 + $est_time["m"] * 60 + $est_time["s"];
03988                 }
03989                 $hours = (int)($time_in_seconds / 3600) ;
03990                 $time_in_seconds = $time_in_seconds - ($hours * 3600);
03991                 $minutes = (int)($time_in_seconds / 60);
03992                 $time_in_seconds = $time_in_seconds - ($minutes * 60);
03993                 $result = array("h" => $hours, "m" => $minutes, "s" => $time_in_seconds);
03994                 return $result;
03995         }
03996         
04009         function randomSelectQuestions($nr_of_questions, $questionpool, $use_obj_id = 0, $qpls = "", $pass = NULL)
04010         {
04011                 global $rbacsystem;
04012                 // get the questionpool id if a questionpool ref id was entered
04013                 if ($questionpool != 0)
04014                 {
04015                         // retrieve object id
04016                         if (!$use_obj_id)
04017                         {
04018                                 $query = sprintf("SELECT obj_id FROM object_reference WHERE ref_id = %s",
04019                                         $this->ilias->db->quote("$questionpool")
04020                                 );
04021                                 $result = $this->ilias->db->query($query);
04022                                 $row = $result->fetchRow(DB_FETCHMODE_ARRAY);
04023                                 $questionpool = $row[0];
04024                         }
04025                 }
04026                 
04027                 // get all existing questions in the test
04028                 $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",
04029                         $this->ilias->db->quote($this->getTestId() . "")
04030                 );
04031                 $result = $this->ilias->db->query($query);
04032                 $original_ids = array();
04033                 while ($row = $result->fetchRow(DB_FETCHMODE_ARRAY))
04034                 {
04035                         if (strcmp($row[0], "") != 0)
04036                         {
04037                                 array_push($original_ids, $row[0]);
04038                         }
04039                 }
04040                 $original_clause = "";
04041                 if (count($original_ids))
04042                 {
04043                         $original_clause = " AND ISNULL(qpl_questions.original_id) AND qpl_questions.question_id NOT IN (" . join($original_ids, ",") . ")";
04044                 }
04045                 
04046                 // get a list of questionpools which are not allowed for the test (only for random selection of questions in test questions editor)
04047                 if (($questionpool == 0) && (!is_array($qpls)))
04048                 {
04049                         $available_pools =& $this->getAvailableQuestionpoolIDs();
04050                         $available = "";
04051                         $constraint_qpls = "";
04052                         if (count($available_pools))
04053                         {
04054                                 $available = " AND qpl_questions.obj_fi IN (" . join($available_pools, ",") . ")";
04055                         }
04056                         else
04057                         {
04058                                 return array();
04059                         }
04060                 }
04061                 
04062                 $result_array = array();
04063                 if ($questionpool == 0)
04064                 {
04065                         if (is_array($qpls))
04066                         {
04067                                 if (count($qpls) > 0)
04068                                 {
04069                                         $qplidx = array();
04070                                         foreach ($qpls as $idx => $arr)
04071                                         {
04072                                                 array_push($qplidx, $arr["qpl"]);
04073                                         }
04074                                         $constraint_qpls = " AND qpl_questions.obj_fi IN (" . join($qplidx, ",") . ")";
04075                                 }
04076                         }
04077                         $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";
04078                 }
04079                         else
04080                 {
04081                         $query = sprintf("SELECT COUNT(question_id) FROM qpl_questions WHERE ISNULL(qpl_questions.original_id) AND obj_fi = %s$original_clause",
04082                                 $this->ilias->db->quote("$questionpool")
04083                         );
04084                 }
04085                 $result = $this->ilias->db->query($query);
04086                 $row = $result->fetchRow(DB_FETCHMODE_ARRAY);
04087                 if (($row[0]) <= $nr_of_questions)
04088                 {
04089                         // take all available questions
04090                         if ($questionpool == 0)
04091                         {
04092                                 $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";
04093                         }
04094                                 else
04095                         {
04096                                 $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",
04097                                         $this->ilias->db->quote("$questionpool")
04098                                 );
04099                         }
04100                         $result = $this->ilias->db->query($query);
04101                         while ($row = $result->fetchRow(DB_FETCHMODE_ARRAY))
04102                         {
04103                                 if ((!in_array($row[0], $this->questions)) && (strcmp($row[0], "") != 0))
04104                                 {
04105                                         $result_array[$row[0]] = $row[0];
04106                                 }
04107                         }
04108                 }
04109                         else
04110                 {
04111                         // select a random number out of the maximum number of questions
04112                         mt_srand((double)microtime()*1000000);
04113                         $random_number = mt_rand(0, $row[0] - 1);
04114                         $securitycounter = 500;
04115                         while ((count($result_array) < $nr_of_questions) && ($securitycounter > 0))
04116                         {
04117                                 if ($questionpool == 0)
04118                                 {
04119                                         $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";
04120                                 }
04121                                         else
04122                                 {
04123                                         $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",
04124                                                 $this->ilias->db->quote("$questionpool")
04125                                         );
04126                                 }
04127                                 $result = $this->ilias->db->query($query);
04128                                 $result_row = $result->fetchRow(DB_FETCHMODE_ARRAY);
04129                                 if ((!in_array($result_row[0], $this->questions)) && (strcmp($result_row[0], "") != 0))
04130                                 {
04131                                         $result_array[$result_row[0]] = $result_row[0];
04132                                 }
04133                                 $random_number = mt_rand(0, $row[0] - 1);
04134                                 $securitycounter--;
04135                         }
04136                 }
04137                 return $result_array;
04138         }
04139 
04148         function getImagePath() 
04149         {
04150                 return CLIENT_WEB_DIR . "/assessment/" . $this->getId() . "/images/";
04151         }
04152 
04161         function getImagePathWeb() 
04162         {
04163                 include_once "./classes/class.ilUtil.php";
04164                 $webdir = ilUtil::removeTrailingPathSeparators(CLIENT_WEB_DIR) . "/assessment/" . $this->getId() . "/images/";
04165                 return str_replace(ilUtil::removeTrailingPathSeparators(ILIAS_ABSOLUTE_PATH), ilUtil::removeTrailingPathSeparators(ILIAS_HTTP_PATH), $webdir);
04166         }
04167 
04178   function &createQuestionGUI($question_type, $question_id = -1) 
04179         {
04180     if ((!$question_type) and ($question_id > 0)) 
04181                 {
04182                         $question_type = $this->getQuestionType($question_id);
04183     }
04184     switch ($question_type) 
04185                 {
04186       case "qt_multiple_choice_sr":
04187                                 include_once "./assessment/classes/class.assMultipleChoiceGUI.php";
04188         $question =& new ASS_MultipleChoiceGUI();
04189         $question->object->set_response(RESPONSE_SINGLE);
04190         break;
04191       case "qt_multiple_choice_mr":
04192                                 include_once "./assessment/classes/class.assMultipleChoiceGUI.php";
04193         $question =& new ASS_MultipleChoiceGUI();
04194         $question->object->set_response(RESPONSE_MULTIPLE);
04195         break;
04196       case "qt_cloze":
04197                                 include_once "./assessment/classes/class.assClozeTestGUI.php";
04198         $question =& new ASS_ClozeTestGUI();
04199         break;
04200       case "qt_matching":
04201                                 include_once "./assessment/classes/class.assMatchingQuestionGUI.php";
04202         $question =& new ASS_MatchingQuestionGUI();
04203         break;
04204       case "qt_ordering":
04205                                 include_once "./assessment/classes/class.assOrderingQuestionGUI.php";
04206         $question =& new ASS_OrderingQuestionGUI();
04207         break;
04208       case "qt_imagemap":
04209                                 include_once "./assessment/classes/class.assImagemapQuestionGUI.php";
04210         $question =& new ASS_ImagemapQuestionGUI();
04211         break;
04212                         case "qt_javaapplet":
04213                                 include_once "./assessment/classes/class.assJavaAppletGUI.php";
04214                                 $question =& new ASS_JavaAppletGUI();
04215                                 break;
04216                         case "qt_text":
04217                                 include_once "./assessment/classes/class.assTextQuestionGUI.php";
04218                                 $question =& new ASS_TextQuestionGUI();
04219                                 break;
04220     }
04221                 if ($question_id > 0)
04222                 {
04223                         $question->object->loadFromDb($question_id);
04224                 }
04225                 return $question;
04226   }
04227 
04237   function &_instanciateQuestion($question_id) 
04238         {
04239                 if (strcmp($question_id, "") != 0)
04240                 {
04241                         include_once "./assessment/classes/class.assQuestion.php";
04242                         $question_type = ASS_Question::_getQuestionType($question_id);
04243 
04244                         switch ($question_type) {
04245                                 case "qt_cloze":
04246                                         include_once "./assessment/classes/class.assClozeTest.php";
04247                                         $question = new ASS_ClozeTest();
04248                                         break;
04249                                 case "qt_matching":
04250                                         include_once "./assessment/classes/class.assMatchingQuestion.php";
04251                                         $question = new ASS_MatchingQuestion();
04252                                         break;
04253                                 case "qt_ordering":
04254                                         include_once "./assessment/classes/class.assOrderingQuestion.php";
04255                                         $question = new ASS_OrderingQuestion();
04256                                         break;
04257                                 case "qt_imagemap":
04258                                         include_once "./assessment/classes/class.assImagemapQuestion.php";
04259                                         $question = new ASS_ImagemapQuestion();
04260                                         break;
04261                                 case "qt_multiple_choice_sr":
04262                                 case "qt_multiple_choice_mr":
04263                                         include_once "./assessment/classes/class.assMultipleChoice.php";
04264                                         $question = new ASS_MultipleChoice();
04265                                         break;
04266                                 case "qt_javaapplet":
04267                                         include_once "./assessment/classes/class.assJavaApplet.php";
04268                                         $question = new ASS_JavaApplet();
04269                                         break;
04270                                 case "qt_text":
04271                                         include_once "./assessment/classes/class.assTextQuestion.php";
04272                                         $question = new ASS_TextQuestion();
04273                                         break;
04274 
04275                                 default:
04276                                         // Return false if question id does not exists or type is unknown
04277                                         return false;
04278                         }
04279 
04280                         $question->loadFromDb($question_id);
04281                         return $question;
04282                 }
04283   }
04284 
04295         function moveQuestions($move_questions, $target_index, $insert_mode)
04296         {
04297                 $this->questions = array_values($this->questions);
04298                 $array_pos = array_search($target_index, $this->questions);
04299                 if ($insert_mode == 0)
04300                 {
04301                         $part1 = array_slice($this->questions, 0, $array_pos);
04302                         $part2 = array_slice($this->questions, $array_pos);
04303                 }
04304                 else if ($insert_mode == 1)
04305                 {
04306                         $part1 = array_slice($this->questions, 0, $array_pos + 1);
04307                         $part2 = array_slice($this->questions, $array_pos + 1);
04308                 }
04309                 foreach ($move_questions as $question_id)
04310                 {
04311                         if (!(array_search($question_id, $part1) === FALSE))
04312                         {
04313                                 unset($part1[array_search($question_id, $part1)]);
04314                         }
04315                         if (!(array_search($question_id, $part2) === FALSE))
04316                         {
04317                                 unset($part2[array_search($question_id, $part2)]);
04318                         }
04319                 }
04320                 $part1 = array_values($part1);
04321                 $part2 = array_values($part2);
04322                 $new_array = array_values(array_merge($part1, $move_questions, $part2));
04323                 $this->questions = array();
04324                 $counter = 1;
04325                 foreach ($new_array as $question_id)
04326                 {
04327                         $this->questions[$counter] = $question_id;
04328                         $counter++;
04329                 }
04330                 $this->saveQuestionsToDb();
04331         }
04332 
04333         
04343         function startingTimeReached()
04344         {
04345                 if ($this->getTestType() == TYPE_ASSESSMENT || $this->getTestType() == TYPE_ONLINE_TEST || $this->getTestType() == TYPE_VARYING_RANDOMTEST) 
04346                 {
04347                         if ($this->getStartingTime()) 
04348                         {
04349                                 if (preg_match("/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/", $this->getStartingTime(), $matches))
04350                                 {
04351                                         $epoch_time = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
04352                                         $now = mktime();
04353                                         if ($now < $epoch_time) 
04354                                         {
04355                                                 // starting time not reached
04356                                                 return false;
04357                                         }
04358                                 }
04359                         }
04360                 }
04361                 return true;
04362         }               
04363         
04373         function endingTimeReached()
04374         {
04375                 if ($this->getTestType() == TYPE_ASSESSMENT || $this->getTestType() == TYPE_ONLINE_TEST || $this->getTestType() == TYPE_VARYING_RANDOMTEST) 
04376                 {
04377                         if ($this->getEndingTime()) 
04378                         {
04379                                 if (preg_match("/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/", $this->getEndingTime(), $matches))
04380                                 {
04381                                         $epoch_time = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
04382                                         $now = mktime();                                
04383                                         if ($now > $epoch_time) 
04384                                         {
04385                                                 // ending time reached
04386                                                 return true;
04387                                         }
04388                                 }
04389                         }
04390                 }
04391                 return false;
04392         }               
04393         
04401         function getQuestionsTable($sortoptions, $filter_text, $sel_filter_type, $startrow = 0, $completeonly = 0, $filter_question_type = "", $filter_questionpool = "")
04402         {
04403                 global $ilUser;
04404                 $where = "";
04405                 if (strlen($filter_text) > 0) {
04406                         switch($sel_filter_type) {
04407                                 case "title":
04408                                         $where = " AND qpl_questions.title LIKE " . $this->ilias->db->quote("%" . $filter_text . "%");
04409                                         break;
04410                                 case "comment":
04411                                         $where = " AND qpl_questions.comment LIKE " . $this->ilias->db->quote("%" . $filter_text . "%");
04412                                         break;
04413                                 case "author":
04414                                         $where = " AND qpl_questions.author LIKE " . $this->ilias->db->quote("%" . $filter_text . "%");
04415                                         break;
04416                         }
04417                 }
04418                 
04419                 if ($filter_question_type && (strcmp($filter_question_type, "all") != 0))
04420                 {
04421                         $where .= " AND qpl_question_type.type_tag = " . $this->ilias->db->quote($filter_question_type);
04422                 }
04423                 
04424                 if ($filter_questionpool && (strcmp($filter_questionpool, "all") != 0))
04425                 {
04426                         $where .= " AND qpl_questions.obj_fi = $filter_questionpool";
04427                 }
04428   
04429     // build sort order for sql query
04430                 $order = "";
04431                 $images = array();
04432     if (count($sortoptions)) 
04433                 {
04434                         include_once "./classes/class.ilUtil.php";
04435       foreach ($sortoptions as $key => $value) 
04436                         {
04437         switch($key) {
04438           case "title":
04439             $order = " ORDER BY title $value";
04440             $images["title"] = " <img src=\"" . ilUtil::getImagePath(strtolower($value) . "_order.png", true) . "\" alt=\"" . $this->lng->txt(strtolower($value) . "ending_order")."\" />";
04441             break;
04442           case "comment":
04443             $order = " ORDER BY comment $value";
04444             $images["comment"] = " <img src=\"" . ilUtil::getImagePath(strtolower($value) . "_order.png", true) . "\" alt=\"" . $this->lng->txt(strtolower($value) . "ending_order")."\" />";
04445             break;
04446           case "type":
04447             $order = " ORDER BY question_type_id $value";
04448             $images["type"] = " <img src=\"" . ilUtil::getImagePath(strtolower($value) . "_order.png", true) . "\" alt=\"" . $this->lng->txt(strtolower($value) . "ending_order")."\" />";
04449             break;
04450           case "author":
04451             $order = " ORDER BY author $value";
04452             $images["author"] = " <img src=\"" . ilUtil::getImagePath(strtolower($value) . "_order.png", true) . "\" alt=\"" . $this->lng->txt(strtolower($value) . "ending_order")."\" />";
04453             break;
04454           case "created":
04455             $order = " ORDER BY created $value";
04456             $images["created"] = " <img src=\"" . ilUtil::getImagePath(strtolower($value) . "_order.png", true) . "\" alt=\"" . $this->lng->txt(strtolower($value) . "ending_order")."\" />";
04457             break;
04458           case "updated":
04459             $order = " ORDER BY TIMESTAMP14 $value";
04460             $images["updated"] = " <img src=\"" . ilUtil::getImagePath(strtolower($value) . "_order.png", true) . "\" alt=\"" . $this->lng->txt(strtolower($value) . "ending_order")."\" />";
04461             break;
04462           case "qpl":
04463             $order = " ORDER BY obj_fi $value";
04464             $images["qpl"] = " <img src=\"" . ilUtil::getImagePath(strtolower($value) . "_order.png", true) . "\" alt=\"" . $this->lng->txt(strtolower($value) . "ending_order")."\" />";
04465             break;
04466         }
04467       }
04468     }
04469                 $maxentries = $ilUser->prefs["hits_per_page"];
04470                 if ($maxentries < 1)
04471                 {
04472                         $maxentries = 9999;
04473                 }
04474                 $available_pools =& $this->getAvailableQuestionpoolIDs();
04475                 $available = "";
04476                 if (count($available_pools))
04477                 {
04478                         $available = " AND qpl_questions.obj_fi IN (" . join($available_pools, ",") . ")";
04479                 }
04480                 else
04481                 {
04482                         return array();
04483                 }
04484                 if ($completeonly)
04485                 {
04486                         $available .= " AND qpl_questions.complete = " . $this->ilias->db->quote("1");
04487                 }
04488 
04489                 // get all questions in the test
04490                 $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",
04491                         $this->ilias->db->quote($this->getTestId() . "")
04492                 );
04493                 $result = $this->ilias->db->query($query);
04494                 $original_ids = array();
04495                 while ($row = $result->fetchRow(DB_FETCHMODE_ARRAY))
04496                 {
04497                         if (strcmp($row[0], "") != 0)
04498                         {
04499                                 array_push($original_ids, $row[0]);
04500                         }
04501                 }
04502                 $original_clause = " ISNULL(qpl_questions.original_id)";
04503                 if (count($original_ids))
04504                 {
04505                         $original_clause = " ISNULL(qpl_questions.original_id) AND qpl_questions.question_id NOT IN (" . join($original_ids, ",") . ")";
04506                 }
04507 
04508                 $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";
04509     $query_result = $this->ilias->db->query($query);
04510                 $max = $query_result->numRows();
04511                 if ($startrow > $max -1)
04512                 {
04513                         $startrow = $max - ($max % $maxentries);
04514                 }
04515                 else if ($startrow < 0)
04516                 {
04517                         $startrow = 0;
04518                 }
04519                 $limit = " LIMIT $startrow, $maxentries";
04520                 $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";
04521     $query_result = $this->ilias->db->query($query);
04522                 $rows = array();
04523                 if ($query_result->numRows())
04524                 {
04525                         while ($row = $query_result->fetchRow(DB_FETCHMODE_ASSOC))
04526                         {
04527                                 array_push($rows, $row);
04528                         }
04529                 }
04530                 $nextrow = $startrow + $maxentries;
04531                 if ($nextrow > $max - 1)
04532                 {
04533                         $nextrow = $startrow;
04534                 }
04535                 $prevrow = $startrow - $maxentries;
04536                 if ($prevrow < 0)
04537                 {
04538                         $prevrow = 0;
04539                 }
04540                 return array(
04541                         "rows" => $rows,
04542                         "images" => $images,
04543                         "startrow" => $startrow,
04544                         "nextrow" => $nextrow,
04545                         "prevrow" => $prevrow,
04546                         "step" => $maxentries,
04547                         "rowcount" => $max
04548                 );
04549         }
04550         
04560         function _getTestType($test_id)
04561         {
04562                 global $ilDB;
04563                 
04564                 $result = "";
04565                 $query = sprintf("SELECT tst_test_type.type_tag FROM tst_test_type, tst_tests WHERE tst_test_type.test_type_id = tst_tests.test_type_fi AND tst_tests.test_id = %s",
04566                         $ilDB->quote($test_id)
04567                 );
04568                 $query_result = $ilDB->query($query);
04569                 if ($query_result->numRows())
04570                 {
04571                         $row = $query_result->fetchRow(DB_FETCHMODE_ASSOC);
04572                         $result = $row["type_tag"];
04573                 }
04574                 return $result;
04575         }
04576         
04585         function &_getQuestiontypes()
04586         {
04587                 global $ilDB;
04588                 
04589                 $questiontypes = array();
04590                 $query = "SELECT * FROM qpl_question_type ORDER BY type_tag";
04591                 $query_result = $ilDB->query($query);
04592                 while ($row = $query_result->fetchRow(DB_FETCHMODE_ASSOC))
04593                 {
04594                         array_push($questiontypes, $row["type_tag"]);
04595                 }
04596                 return $questiontypes;
04597         }
04598         
04607         function to_xml()
04608         {
04609                 $xml_header = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<questestinterop></questestinterop>\n";
04610                 $domxml = domxml_open_mem($xml_header);
04611                 $root = $domxml->document_element();
04612                 // qti assessment
04613                 $qtiAssessment = $domxml->create_element("assessment");
04614                 $qtiAssessment->set_attribute("ident", "il_".IL_INST_ID."_tst_".$this->getTestId());
04615                 $qtiAssessment->set_attribute("title", $this->getTitle());
04616                 
04617                 // add qti comment
04618                 $qtiComment = $domxml->create_element("qticomment");
04619                 $qtiCommentText = $domxml->create_text_node($this->getDescription());
04620                 $qtiComment->append_child($qtiCommentText);
04621                 $qtiAssessment->append_child($qtiComment);
04622 
04623                 // add qti duration
04624                 if ($this->enable_processing_time)
04625                 {
04626                         $qtiDuration = $domxml->create_element("duration");
04627                         preg_match("/(\d+):(\d+):(\d+)/", $this->processing_time, $matches);
04628                         $qtiDurationText = $domxml->create_text_node(sprintf("P0Y0M0DT%dH%dM%dS", $matches[1], $matches[2], $matches[3]));
04629                         $qtiDuration->append_child($qtiDurationText);
04630                         $qtiAssessment->append_child($qtiDuration);
04631                 }
04632 
04633                 // add the rest of the preferences in qtimetadata tags, because there is no correspondent definition in QTI
04634                 $qtiMetadata = $domxml->create_element("qtimetadata");
04635                 // ILIAS version
04636                 $qtiMetadatafield = $domxml->create_element("qtimetadatafield");
04637                 $qtiFieldLabel = $domxml->create_element("fieldlabel");
04638                 $qtiFieldLabelText = $domxml->create_text_node("ILIAS_VERSION");
04639                 $qtiFieldLabel->append_child($qtiFieldLabelText);
04640                 $qtiFieldEntry = $domxml->create_element("fieldentry");
04641                 $qtiFieldEntryText = $domxml->create_text_node($this->ilias->getSetting("ilias_version"));
04642                 $qtiFieldEntry->append_child($qtiFieldEntryText);
04643                 $qtiMetadatafield->append_child($qtiFieldLabel);
04644                 $qtiMetadatafield->append_child($qtiFieldEntry);
04645                 $qtiMetadata->append_child($qtiMetadatafield);
04646                 // test type
04647                 $qtiMetadatafield = $domxml->create_element("qtimetadatafield");
04648                 $qtiFieldLabel = $domxml->create_element("fieldlabel");
04649                 $qtiFieldLabelText = $domxml->create_text_node("test_type");
04650                 $qtiFieldLabel->append_child($qtiFieldLabelText);
04651                 $qtiFieldEntry = $domxml->create_element("fieldentry");
04652                 $qtiFieldEntryText = $domxml->create_text_node(sprintf("%d", $this->getTestType()));
04653                 $qtiFieldEntry->append_child($qtiFieldEntryText);
04654                 $qtiMetadatafield->append_child($qtiFieldLabel);
04655                 $qtiMetadatafield->append_child($qtiFieldEntry);
04656                 $qtiMetadata->append_child($qtiMetadatafield);
04657                 // sequence settings
04658                 $qtiMetadatafield = $domxml->create_element("qtimetadatafield");
04659                 $qtiFieldLabel = $domxml->create_element("fieldlabel");
04660                 $qtiFieldLabelText = $domxml->create_text_node("sequence_settings");
04661                 $qtiFieldLabel->append_child($qtiFieldLabelText);
04662                 $qtiFieldEntry = $domxml->create_element("fieldentry");
04663                 $qtiFieldEntryText = $domxml->create_text_node(sprintf("%d", $this->getSequenceSettings()));
04664                 $qtiFieldEntry->append_child($qtiFieldEntryText);
04665                 $qtiMetadatafield->append_child($qtiFieldLabel);
04666                 $qtiMetadatafield->append_child($qtiFieldEntry);
04667                 $qtiMetadata->append_child($qtiMetadatafield);
04668                 // author
04669                 $qtiMetadatafield = $domxml->create_element("qtimetadatafield");
04670                 $qtiFieldLabel = $domxml->create_element("fieldlabel");
04671                 $qtiFieldLabelText = $domxml->create_text_node("author");
04672                 $qtiFieldLabel->append_child($qtiFieldLabelText);
04673                 $qtiFieldEntry = $domxml->create_element("fieldentry");
04674                 $qtiFieldEntryText = $domxml->create_text_node($this->getAuthor());
04675                 $qtiFieldEntry->append_child($qtiFieldEntryText);
04676                 $qtiMetadatafield->append_child($qtiFieldLabel);
04677                 $qtiMetadatafield->append_child($qtiFieldEntry);
04678                 $qtiMetadata->append_child($qtiMetadatafield);
04679                 // count system
04680                 $qtiMetadatafield = $domxml->create_element("qtimetadatafield");
04681                 $qtiFieldLabel = $domxml->create_element("fieldlabel");
04682                 $qtiFieldLabelText = $domxml->create_text_node("count_system");
04683                 $qtiFieldLabel->append_child($qtiFieldLabelText);
04684                 $qtiFieldEntry = $domxml->create_element("fieldentry");
04685                 $qtiFieldEntryText = $domxml->create_text_node($this->getCountSystem());
04686                 $qtiFieldEntry->append_child($qtiFieldEntryText);
04687                 $qtiMetadatafield->append_child($qtiFieldLabel);
04688                 $qtiMetadatafield->append_child($qtiFieldEntry);
04689                 $qtiMetadata->append_child($qtiMetadatafield);
04690                 // multiple choice scoring
04691                 $qtiMetadatafield = $domxml->create_element("qtimetadatafield");
04692                 $qtiFieldLabel = $domxml->create_element("fieldlabel");
04693                 $qtiFieldLabelText = $domxml->create_text_node("mc_scoring");
04694                 $qtiFieldLabel->append_child($qtiFieldLabelText);
04695                 $qtiFieldEntry = $domxml->create_element("fieldentry");
04696                 $qtiFieldEntryText = $domxml->create_text_node($this->getMCScoring());
04697                 $qtiFieldEntry->append_child($qtiFieldEntryText);
04698                 $qtiMetadatafield->append_child($qtiFieldLabel);
04699                 $qtiMetadatafield->append_child($qtiFieldEntry);
04700                 $qtiMetadata->append_child($qtiMetadatafield);
04701                 // pass scoring
04702                 $qtiMetadatafield = $domxml->create_element("qtimetadatafield");
04703                 $qtiFieldLabel = $domxml->create_element("fieldlabel");
04704                 $qtiFieldLabelText = $domxml->create_text_node("pass_scoring");
04705                 $qtiFieldLabel->append_child($qtiFieldLabelText);
04706                 $qtiFieldEntry = $domxml->create_element("fieldentry");
04707                 $qtiFieldEntryText = $domxml->create_text_node($this->getPassScoring());
04708                 $qtiFieldEntry->append_child($qtiFieldEntryText);
04709                 $qtiMetadatafield->append_child($qtiFieldLabel);
04710                 $qtiMetadatafield->append_child($qtiFieldEntry);
04711                 $qtiMetadata->append_child($qtiMetadatafield);
04712                 // score reporting date
04713                 if ($this->getReportingDate())
04714                 {
04715                         $qtiMetadatafield = $domxml->create_element("qtimetadatafield");
04716                         $qtiFieldLabel = $domxml->create_element("fieldlabel");
04717                         $qtiFieldLabelText = $domxml->create_text_node("reporting_date");
04718                         $qtiFieldLabel->append_child($qtiFieldLabelText);
04719                         $qtiFieldEntry = $domxml->create_element("fieldentry");
04720                         preg_match("/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/", $this->reporting_date, $matches);
04721                         $qtiFieldEntryText = $domxml->create_text_node(sprintf("P%dY%dM%dDT%dH%dM%dS", $matches[1], $matches[2], $matches[3], $matches[4], $matches[5], $matches[6]));
04722                         $qtiFieldEntry->append_child($qtiFieldEntryText);
04723                         $qtiMetadatafield->append_child($qtiFieldLabel);
04724                         $qtiMetadatafield->append_child($qtiFieldEntry);
04725                         $qtiMetadata->append_child($qtiMetadatafield);
04726                 }
04727                 // number of tries
04728                 $qtiMetadatafield = $domxml->create_element("qtimetadatafield");
04729                 $qtiFieldLabel = $domxml->create_element("fieldlabel");
04730                 $qtiFieldLabelText = $domxml->create_text_node("nr_of_tries");
04731                 $qtiFieldLabel->append_child($qtiFieldLabelText);
04732                 $qtiFieldEntry = $domxml->create_element("fieldentry");
04733                 $qtiFieldEntryText = $domxml->create_text_node(sprintf("%d", $this->getNrOfTries()));
04734                 $qtiFieldEntry->append_child($qtiFieldEntryText);
04735                 $qtiMetadatafield->append_child($qtiFieldLabel);
04736                 $qtiMetadatafield->append_child($qtiFieldEntry);
04737                 $qtiMetadata->append_child($qtiMetadatafield);
04738                 // hide previous results
04739                 $qtiMetadatafield = $domxml->create_element("qtimetadatafield");
04740                 $qtiFieldLabel = $domxml->create_element("fieldlabel");
04741                 $qtiFieldLabelText = $domxml->create_text_node("hide_previous_results");
04742                 $qtiFieldLabel->append_child($qtiFieldLabelText);
04743                 $qtiFieldEntry = $domxml->create_element("fieldentry");
04744                 $qtiFieldEntryText = $domxml->create_text_node(sprintf("%d", $this->getHidePreviousResults()));
04745                 $qtiFieldEntry->append_child($qtiFieldEntryText);
04746                 $qtiMetadatafield->append_child($qtiFieldLabel);
04747                 $qtiMetadatafield->append_child($qtiFieldEntry);
04748                 $qtiMetadata->append_child($qtiMetadatafield);
04749                 // hide title points
04750                 $qtiMetadatafield = $domxml->create_element("qtimetadatafield");
04751                 $qtiFieldLabel = $domxml->create_element("fieldlabel");
04752                 $qtiFieldLabelText = $domxml->create_text_node("hide_title_points");
04753                 $qtiFieldLabel->append_child($qtiFieldLabelText);
04754                 $qtiFieldEntry = $domxml->create_element("fieldentry");
04755                 $qtiFieldEntryText = $domxml->create_text_node(sprintf("%d", $this->getHideTitlePoints()));
04756                 $qtiFieldEntry->append_child($qtiFieldEntryText);
04757                 $qtiMetadatafield->append_child($qtiFieldLabel);
04758                 $qtiMetadatafield->append_child($qtiFieldEntry);
04759                 $qtiMetadata->append_child($qtiMetadatafield);
04760                 // random test
04761                 $qtiMetadatafield = $domxml->create_element("qtimetadatafield");
04762                 $qtiFieldLabel = $domxml->create_element("fieldlabel");
04763                 $qtiFieldLabelText = $domxml->create_text_node("random_test");
04764                 $qtiFieldLabel->append_child($qtiFieldLabelText);
04765                 $qtiFieldEntry = $domxml->create_element("fieldentry");
04766                 $qtiFieldEntryText = $domxml->create_text_node(sprintf("%d", $this->isRandomTest()));
04767                 $qtiFieldEntry->append_child($qtiFieldEntryText);
04768                 $qtiMetadatafield->append_child($qtiFieldLabel);
04769                 $qtiMetadatafield->append_child($qtiFieldEntry);
04770                 $qtiMetadata->append_child($qtiMetadatafield);
04771                 // random question count
04772                 $qtiMetadatafield = $domxml->create_element("qtimetadatafield");
04773                 $qtiFieldLabel = $domxml->create_element("fieldlabel");
04774                 $qtiFieldLabelText = $domxml->create_text_node("random_question_count");
04775                 $qtiFieldLabel->append_child($qtiFieldLabelText);
04776                 $qtiFieldEntry = $domxml->create_element("fieldentry");
04777                 $qtiFieldEntryText = $domxml->create_text_node(sprintf("%d", $this->getRandomQuestionCount()));
04778                 $qtiFieldEntry->append_child($qtiFieldEntryText);
04779                 $qtiMetadatafield->append_child($qtiFieldLabel);
04780                 $qtiMetadatafield->append_child($qtiFieldEntry);
04781                 $qtiMetadata->append_child($qtiMetadatafield);
04782                 // starting time
04783                 if ($this->getStartingTime())
04784                 {
04785                         $qtiMetadatafield = $domxml->create_element("qtimetadatafield");
04786                         $qtiFieldLabel = $domxml->create_element("fieldlabel");
04787                         $qtiFieldLabelText = $domxml->create_text_node("starting_time");
04788                         $qtiFieldLabel->append_child($qtiFieldLabelText);
04789                         $qtiFieldEntry = $domxml->create_element("fieldentry");
04790                         preg_match("/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/", $this->starting_time, $matches);
04791                         $qtiFieldEntryText = $domxml->create_text_node(sprintf("P%dY%dM%dDT%dH%dM%dS", $matches[1], $matches[2], $matches[3], $matches[4], $matches[5], $matches[6]));
04792                         $qtiFieldEntry->append_child($qtiFieldEntryText);
04793                         $qtiMetadatafield->append_child($qtiFieldLabel);
04794                         $qtiMetadatafield->append_child($qtiFieldEntry);
04795                         $qtiMetadata->append_child($qtiMetadatafield);
04796                 }
04797                 // ending time
04798                 if ($this->getEndingTime())
04799                 {
04800                         $qtiMetadatafield = $domxml->create_element("qtimetadatafield");
04801                         $qtiFieldLabel = $domxml->create_element("fieldlabel");
04802                         $qtiFieldLabelText = $domxml->create_text_node("ending_time");
04803                         $qtiFieldLabel->append_child($qtiFieldLabelText);
04804                         $qtiFieldEntry = $domxml->create_element("fieldentry");
04805                         preg_match("/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/", $this->ending_time, $matches);
04806                         $qtiFieldEntryText = $domxml->create_text_node(sprintf("P%dY%dM%dDT%dH%dM%dS", $matches[1], $matches[2], $matches[3], $matches[4], $matches[5], $matches[6]));
04807                         $qtiFieldEntry->append_child($qtiFieldEntryText);
04808                         $qtiMetadatafield->append_child($qtiFieldLabel);
04809                         $qtiMetadatafield->append_child($qtiFieldEntry);
04810                         $qtiMetadata->append_child($qtiMetadatafield);
04811                 }
04812                 foreach ($this->mark_schema->mark_steps as $index => $mark)
04813                 {
04814                         // mark steps
04815                         $qtiMetadatafield = $domxml->create_element("qtimetadatafield");
04816                         $qtiFieldLabel = $domxml->create_element("fieldlabel");
04817                         $qtiFieldLabelText = $domxml->create_text_node("mark_step_$index");
04818                         $qtiFieldLabel->append_child($qtiFieldLabelText);
04819                         $qtiFieldEntry = $domxml->create_element("fieldentry");
04820                         $qtiFieldEntryText = $domxml->create_text_node(sprintf("<short>%s</short><official>%s</official><percentage>%.2f</percentage><passed>%d</passed>", $mark->get_short_name(), $mark->get_official_name(), $mark->get_minimum_level(), $mark->get_passed()));
04821                         $qtiFieldEntry->append_child($qtiFieldEntryText);
04822                         $qtiMetadatafield->append_child($qtiFieldLabel);
04823                         $qtiMetadatafield->append_child($qtiFieldEntry);
04824                         $qtiMetadata->append_child($qtiMetadatafield);
04825                 }
04826                 $qtiAssessment->append_child($qtiMetadata);
04827                 
04828                 // add qti objectives
04829                 $qtiObjectives = $domxml->create_element("objectives");
04830                 $qtiMaterial = $domxml->create_element("material");
04831                 $qtiMaterial->set_attribute("label", "introduction");
04832                 $qtiMatText = $domxml->create_element("mattext");
04833                 $qtiMatTextText = $domxml->create_text_node($this->getIntroduction());
04834                 $qtiMatText->append_child($qtiMatTextText);
04835                 $qtiMaterial->append_child($qtiMatText);
04836                 $qtiObjectives->append_child($qtiMaterial);
04837                 $qtiAssessment->append_child($qtiObjectives);
04838 
04839                 // add qti assessmentcontrol
04840                 $qtiAssessmentcontrol = $domxml->create_element("assessmentcontrol");
04841                 $score_reporting = "No";
04842                 switch ($this->getScoreReporting())
04843                 {
04844                         case "1":
04845                                 $score_reporting = "Yes";
04846                                 break;
04847                 }
04848                 $qtiAssessmentcontrol->set_attribute("solutionswitch", $score_reporting);
04849                 $qtiAssessment->append_child($qtiAssessmentcontrol);
04850                 
04851                 $qtiSection = $domxml->create_element("section");
04852                 $qtiSection->set_attribute("ident", "1");
04853                 $qtiAssessment->append_child($qtiSection);
04854                 
04855                 $root->append_child($qtiAssessment);
04856                 $xml = $domxml->dump_mem(true);
04857                 $domxml->free();
04858                 foreach ($this->questions as $question_id) 
04859                 {
04860                         $question =& ilObjTest::_instanciateQuestion($question_id);
04861                         $qti_question = $question->to_xml(false);
04862                         $qti_question = preg_replace("/<questestinterop>/", "", $qti_question);
04863                         $qti_question = preg_replace("/<\/questestinterop>/", "", $qti_question);
04864                         if (strpos($xml, "</section>") !== false)
04865                         {
04866                                 $xml = str_replace("</section>", "$qti_question</section>", $xml);
04867                         }
04868                         else
04869                         {
04870                                 $xml = str_replace("<section ident=\"1\"/>", "<section ident=\"1\">\n$qti_question</section>", $xml);
04871                         }
04872                 }
04873                 return $xml;
04874         }
04875         
04882         function exportPagesXML(&$a_xml_writer, $a_inst, $a_target_dir, &$expLog)
04883         {
04884                 global $ilBench;
04885                 
04886                 $this->mob_ids = array();
04887                 $this->file_ids = array();
04888 
04889                 $attrs = array();
04890                 $attrs["Type"] = "Test";
04891                 $a_xml_writer->xmlStartTag("ContentObject", $attrs);
04892 
04893                 // MetaData
04894                 $this->exportXMLMetaData($a_xml_writer);
04895 
04896                 // PageObjects
04897                 $expLog->write(date("[y-m-d H:i:s] ")."Start Export Page Objects");
04898                 $ilBench->start("ContentObjectExport", "exportPageObjects");
04899                 $this->exportXMLPageObjects($a_xml_writer, $a_inst, $expLog);
04900                 $ilBench->stop("ContentObjectExport", "exportPageObjects");
04901                 $expLog->write(date("[y-m-d H:i:s] ")."Finished Export Page Objects");
04902 
04903                 // MediaObjects
04904                 $expLog->write(date("[y-m-d H:i:s] ")."Start Export Media Objects");
04905                 $ilBench->start("ContentObjectExport", "exportMediaObjects");
04906                 $this->exportXMLMediaObjects($a_xml_writer, $a_inst, $a_target_dir, $expLog);
04907                 $ilBench->stop("ContentObjectExport", "exportMediaObjects");
04908                 $expLog->write(date("[y-m-d H:i:s] ")."Finished Export Media Objects");
04909 
04910                 // FileItems
04911                 $expLog->write(date("[y-m-d H:i:s] ")."Start Export File Items");
04912                 $ilBench->start("ContentObjectExport", "exportFileItems");
04913                 $this->exportFileItems($a_target_dir, $expLog);
04914                 $ilBench->stop("ContentObjectExport", "exportFileItems");
04915                 $expLog->write(date("[y-m-d H:i:s] ")."Finished Export File Items");
04916 
04917                 $a_xml_writer->xmlEndTag("ContentObject");
04918         }
04919 
04926         function exportXMLMetaData(&$a_xml_writer)
04927         {
04928                 include_once "./Services/MetaData/classes/class.ilMD2XML.php";
04929                 $md2xml = new ilMD2XML($this->getId(), 0, $this->getType());
04930                 $md2xml->setExportMode(true);
04931                 $md2xml->startExport();
04932                 $a_xml_writer->appendXML($md2xml->getXML());
04933         }
04934 
04942         function modifyExportIdentifier($a_tag, $a_param, $a_value)
04943         {
04944                 if ($a_tag == "Identifier" && $a_param == "Entry")
04945                 {
04946                         include_once "./classes/class.ilUtil.php";
04947                         $a_value = ilUtil::insertInstIntoID($a_value);
04948                 }
04949 
04950                 return $a_value;
04951         }
04952 
04953 
04960         function exportXMLPageObjects(&$a_xml_writer, $a_inst, &$expLog)
04961         {
04962                 global $ilBench;
04963 
04964                 include_once "./content/classes/class.ilLMPageObject.php";
04965 
04966                 foreach ($this->questions as $question_id)
04967                 {
04968                         $ilBench->start("ContentObjectExport", "exportPageObject");
04969                         $expLog->write(date("[y-m-d H:i:s] ")."Page Object ".$question_id);
04970 
04971                         $attrs = array();
04972                         $a_xml_writer->xmlStartTag("PageObject", $attrs);
04973 
04974                         
04975                         // export xml to writer object
04976                         $ilBench->start("ContentObjectExport", "exportPageObject_XML");
04977                         $page_object = new ilPageObject("qpl", $question_id);
04978                         $page_object->buildDom();
04979                         $page_object->insertInstIntoIDs($a_inst);
04980                         $mob_ids = $page_object->collectMediaObjects(false);
04981                         $file_ids = $page_object->collectFileItems();
04982                         $xml = $page_object->getXMLFromDom(false, false, false, "", true);
04983                         $xml = str_replace("&","&amp;", $xml);
04984                         $a_xml_writer->appendXML($xml);
04985                         $page_object->freeDom();
04986                         unset ($page_object);
04987                         
04988                         $ilBench->stop("ContentObjectExport", "exportPageObject_XML");
04989 
04990                         // collect media objects
04991                         $ilBench->start("ContentObjectExport", "exportPageObject_CollectMedia");
04992                         //$mob_ids = $page_obj->getMediaObjectIDs();
04993                         foreach($mob_ids as $mob_id)
04994                         {
04995                                 $this->mob_ids[$mob_id] = $mob_id;
04996                         }
04997                         $ilBench->stop("ContentObjectExport", "exportPageObject_CollectMedia");
04998 
04999                         // collect all file items
05000                         $ilBench->start("ContentObjectExport", "exportPageObject_CollectFileItems");
05001                         //$file_ids = $page_obj->getFileItemIds();
05002                         foreach($file_ids as $file_id)
05003                         {
05004                                 $this->file_ids[$file_id] = $file_id;
05005                         }
05006                         $ilBench->stop("ContentObjectExport", "exportPageObject_CollectFileItems");
05007                         
05008                         $a_xml_writer->xmlEndTag("PageObject");
05009                         //unset($page_obj);
05010 
05011                         $ilBench->stop("ContentObjectExport", "exportPageObject");
05012                         
05013 
05014                 }
05015         }
05016 
05023         function exportXMLMediaObjects(&$a_xml_writer, $a_inst, $a_target_dir, &$expLog)
05024         {
05025                 include_once "./content/classes/Media/class.ilObjMediaObject.php";
05026 
05027                 foreach ($this->mob_ids as $mob_id)
05028                 {
05029                         $expLog->write(date("[y-m-d H:i:s] ")."Media Object ".$mob_id);
05030                         $media_obj = new ilObjMediaObject($mob_id);
05031                         $media_obj->exportXML($a_xml_writer, $a_inst);
05032                         $media_obj->exportFiles($a_target_dir);
05033                         unset($media_obj);
05034                 }
05035         }
05036 
05041         function exportFileItems($a_target_dir, &$expLog)
05042         {
05043                 include_once "./classes/class.ilObjFile.php";
05044 
05045                 foreach ($this->file_ids as $file_id)
05046                 {
05047                         $expLog->write(date("[y-m-d H:i:s] ")."File Item ".$file_id);
05048                         $file_obj = new ilObjFile($file_id, false);
05049                         $file_obj->export($a_target_dir);
05050                         unset($file_obj);
05051                 }
05052         }
05053 
05058         function getImportMapping()
05059         {
05060                 if (!is_array($this->import_mapping))
05061                 {
05062                         return array();
05063                 }
05064                 else
05065                 {
05066                         return $this->import_mapping;
05067                 }
05068         }
05069         
05080         function getECTSGrade($reached_points, $max_points)
05081         {
05082                 include_once "./classes/class.ilStatistics.php";
05083                 // calculate the median
05084                 $passed_statistics = new ilStatistics();
05085                 $passed_array =& $this->getTotalPointsPassedArray();
05086                 $passed_statistics->setData($passed_array);
05087                 $ects_percentiles = array
05088                         (
05089                                 "A" => $passed_statistics->quantile($this->ects_grades["A"]),
05090                                 "B" => $passed_statistics->quantile($this->ects_grades["B"]),
05091                                 "C" => $passed_statistics->quantile($this->ects_grades["C"]),
05092                                 "D" => $passed_statistics->quantile($this->ects_grades["D"]),
05093                                 "E" => $passed_statistics->quantile($this->ects_grades["E"])
05094                         );
05095                         if (count($passed_array) && ($reached_points >= $ects_percentiles["A"]))
05096                         {
05097                                 return "A";
05098                         }
05099                         else if (count($passed_array) && ($reached_points >= $ects_percentiles["B"]))
05100                         {
05101                                 return "B";
05102                         }
05103                         else if (count($passed_array) && ($reached_points >= $ects_percentiles["C"]))
05104                         {
05105                                 return "C";
05106                         }
05107                         else if (count($passed_array) && ($reached_points >= $ects_percentiles["D"]))
05108                         {
05109                                 return "D";
05110                         }
05111                         else if (count($passed_array) && ($reached_points >= $ects_percentiles["E"]))
05112                         {
05113                                 return "E";
05114                         }
05115                         else if (strcmp($this->ects_fx, "") != 0)
05116                         {
05117                                 if ($max_points > 0)
05118                                 {
05119                                         $percentage = ($reached_points / $max_points) * 100.0;
05120                                 }
05121                                 else
05122                                 {
05123                                         $percentage = 0.0;
05124                                 }
05125                                 if ($percentage >= $this->ects_fx)
05126                                 {
05127                                         return "FX";
05128                                 }
05129                                 else
05130                                 {
05131                                         return "F";
05132                                 }
05133                         }
05134                         else
05135                         {
05136                                 return "F";
05137                         }
05138         }
05139         
05140         function checkMarks()
05141         {
05142                 return $this->mark_schema->checkMarks();
05143         }
05144         
05145         function updateMetaData()
05146         {
05147                 global $ilUser;
05148                 include_once "./Services/MetaData/classes/class.ilMD.php";
05149                 $md =& new ilMD($this->getId(), 0, $this->getType());
05150                 $md_gen =& $md->getGeneral();
05151                 if ($md_gen == false)
05152                 {
05153                         include_once "./Services/MetaData/classes/class.ilMDCreator.php";
05154                         $md_creator = new ilMDCreator($this->getId(),0,$this->getType());
05155                         $md_creator->setTitle($this->getTitle());
05156                         $md_creator->setTitleLanguage($ilUser->getPref('language'));
05157                         $md_creator->create();
05158                 }
05159                 parent::updateMetaData();
05160         }
05161         
05170         function &_getAvailableTests($use_object_id = false)
05171         {
05172                 global $rbacsystem;
05173                 global $ilDB;
05174                 
05175                 $result_array = array();
05176                 $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";
05177                 $result = $ilDB->query($query);
05178                 include_once "./classes/class.ilObject.php";
05179                 while ($row = $result->fetchRow(DB_FETCHMODE_OBJECT))
05180                 {               
05181                         if ($rbacsystem->checkAccess("write", $row->ref_id) && (ilObject::_hasUntrashedReference($row->obj_id)))
05182                         {
05183                                 if ($use_object_id)
05184                                 {
05185                                         $result_array[$row->obj_id] = $row->title;
05186                                 }
05187                                 else
05188                                 {
05189                                         $result_array[$row->ref_id] = $row->title;
05190                                 }
05191                         }
05192                 }
05193                 return $result_array;
05194         }
05195 
05204         function cloneRandomQuestions($new_id)
05205         {
05206                 if ($new_id > 0)
05207                 {
05208                         $query = sprintf("SELECT * FROM tst_test_random WHERE test_fi = %s",
05209                                 $this->ilias->db->quote($this->getTestId() . "")
05210                         );
05211                         $result = $this->ilias->db->query($query);
05212                         if ($result->numRows())
05213                         {
05214                                 while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC))
05215                                 {
05216                                         $query = sprintf("INSERT INTO tst_test_random (test_random_id, test_fi, questionpool_fi, num_of_q, TIMESTAMP) VALUES (NULL, %s, %s, %s, NULL)",
05217                                                 $this->ilias->db->quote($new_id . ""),
05218                                                 $this->ilias->db->quote($row["questionpool_fi"] . ""),
05219                                                 $this->ilias->db->quote($row["num_of_q"] . "")
05220                                         );
05221                                         $insertresult = $this->ilias->db->query($query);
05222                                 }
05223                         }
05224                 }
05225         }
05226         
05227         
05235         function _clone($obj_id)
05236         {
05237                 $original = new ilObjTest($obj_id, false);
05238                 $original->loadFromDb();
05239                 
05240                 $newObj = new ilObjTest();
05241                 $newObj->setType("tst");
05242     $counter = 2;
05243     while ($newObj->testTitleExists($newObj->getTitle() . " ($counter)")) 
05244                 {
05245       $counter++;
05246     }
05247 
05248                 $newObj->setAuthor($original->getAuthor());
05249                 $newObj->setHideTitlePoints($original->getHideTitlePoints());
05250                 $newObj->setPassScoring($original->getPassScoring());
05251                 $newObj->setTitle($original->getTitle() . " ($counter)");
05252                 $newObj->setDescription($original->getDescription());
05253                 $newObj->create(true);
05254                 $newObj->createReference();
05255                 $newObj->putInTree($_GET["ref_id"]);
05256                 $newObj->setPermissions($_GET["ref_id"]);
05257                 $newObj->author = $original->getAuthor();
05258                 $newObj->introduction = $original->getIntroduction();
05259                 $newObj->mark_schema = $original->mark_schema;
05260                 $newObj->sequence_settings = $original->getSequenceSettings();
05261                 $newObj->score_reporting = $original->getScoreReporting();
05262                 $newObj->reporting_date = $original->getReportingDate();
05263                 $newObj->test_type = $original->getTestType();
05264                 $newObj->nr_of_tries = $original->getNrOfTries();
05265                 $newObj->setHidePreviousResults($original->getHidePreviousResults());
05266                 $newObj->processing_time = $original->getProcessingTime();
05267                 $newObj->enable_processing_time = $original->getEnableProcessingTime();
05268                 $newObj->starting_time = $original->getStartingTime();
05269                 $newObj->ending_time = $original->getEndingTime();
05270                 $newObj->ects_output = $original->ects_output;
05271                 $newObj->ects_fx = $original->ects_fx;
05272                 $newObj->ects_grades = $original->ects_grades;
05273                 $newObj->random_test = $original->random_test;
05274                 $newObj->random_question_count = $original->random_question_count;
05275                 $newObj->setCountSystem($original->getCountSystem());
05276                 $newObj->setMCScoring($original->getMCScoring());
05277                 $newObj->saveToDb();            
05278                 if ($original->isRandomTest())
05279                 {
05280                         $newObj->saveRandomQuestionCount($newObj->random_question_count);
05281                         $original->cloneRandomQuestions($newObj->getTestId());
05282                 }
05283                 else
05284                 {
05285                         // clone the questions
05286                         include_once "./assessment/classes/class.assQuestion.php";
05287                         foreach ($original->questions as $key => $question_id)
05288                         {
05289                                 $question = ilObjTest::_instanciateQuestion($question_id);
05290                                 $newObj->questions[$key] = $question->duplicate();
05291         //                      $question->id = -1;
05292                                 $original_id = ASS_Question::_getOriginalId($question_id);
05293                                 $question = ilObjTest::_instanciateQuestion($newObj->questions[$key]);
05294                                 $question->saveToDb($original_id);
05295                         }
05296                 }
05297                 
05298                 $newObj->saveToDb();
05299 
05300                 // clone meta data
05301                 include_once "./Services/MetaData/classes/class.ilMD.php";
05302                 $md = new ilMD($original->getId(),0,$original->getType());
05303                 $new_md =& $md->cloneMD($newObj->getId(),0,$newObj->getType());
05304                 return $newObj->getRefId();
05305         }
05306 
05307         function _getRefIdFromObjId($obj_id)
05308         {
05309                 global $ilDB;
05310 
05311                 $query = sprintf("SELECT ref_id FROM object_reference WHERE obj_id=%s",
05312                         $ilDB->quote($obj_id)
05313                         
05314                 );
05315                 $result = $ilDB->query($query);
05316                 if ($result->numRows())
05317                 {
05318                         $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
05319                         return $row["ref_id"];
05320                 }
05321                 return 0;
05322         }
05323         
05324         function createRandomSolutionsForAllUsers()
05325         {
05326                 global $ilDB;
05327                 global $ilUser;
05328                 
05329                 $db =& $ilDB->db;
05330                 $sequence_arr = array_flip($this->questions);
05331                 $sequence = join($sequence_arr, ",");
05332                 include_once("./classes/class.ilObjUser.php");
05333                 $logins = ilObjUser::_getAllUserData(array("login"));
05334 
05335                 foreach ($logins as $login)
05336                 {
05337                         $user_id = $login["usr_id"];
05338                         $old_active = $this->getActiveTestUser($user_id);
05339                         if ($old_active) {
05340                                 $query = sprintf("UPDATE tst_active SET lastindex = %s, sequence = %s, postponed = %s, tries = %s WHERE user_fi = %s AND test_fi = %s",
05341                                         $db->quote("0"),
05342                                         $db->quote($sequence),
05343                                         $db->quote(""),
05344                                         $db->quote("1"),
05345                                         $db->quote($user_id),
05346                                         $db->quote($this->getTestId())
05347                                 );
05348                         } else {
05349                                 $sequence_arr = array_flip($this->questions);
05350                                 $sequence = join($sequence_arr, ",");
05351                                 $query = sprintf("INSERT INTO tst_active (active_id, user_fi, test_fi, sequence, postponed, lastindex, tries, TIMESTAMP) VALUES (NULL, %s, %s, %s, %s, %s, %s, NULL)",
05352                                         $db->quote($user_id),
05353                                         $db->quote($this->getTestId()),
05354                                         $db->quote($sequence),
05355                                         $db->quote(""),
05356                                         $db->quote("0"),
05357                                         $db->quote("1")
05358                                 );
05359                         }
05360                         $db->query($query);
05361                 }
05362                 foreach ($this->questions as $question_id) 
05363                 {
05364                         $question =& ilObjTest::_instanciateQuestion($question_id);
05365                         foreach ($logins as $login)
05366                         {
05367                                 $question->createRandomSolution($this->getTestId(), $login["usr_id"]);
05368                         }
05369                 }
05370         }
05371 
05379         function &getEvaluationUsers($user_id, $sort_name_option = "asc")
05380         {
05381                 $users = array();
05382                 $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),
05383                         $this->ilias->db->quote($this->getTestId() . ""),
05384                         $this->ilias->db->quote($user_id . "")
05385                 );
05386                 $result = $this->ilias->db->query($query);
05387                 if ($result->numRows())
05388                 {
05389                         while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC))
05390                         {
05391                                 $name = array("fullname" => trim($row["lastname"].", ".$row["firstname"] . " " . $row["title"]), "firstname" => $row["firstname"], "lastname" => $row["lastname"]);
05392                                 if ($this->getTestType() == TYPE_SELF_ASSESSMENT)
05393                                 {
05394                                         $name = array("fullname" => $this->lng->txt("unknown"), "firstname" => $this->lng->txt("unknown"), "lastname" => $this->lng->txt("unknown"));
05395                                 }
05396                                 $users[$row["user_fi"]] = $name;
05397                         }
05398                 }
05399                 return $users;
05400         }
05401 
05410         function removeSelectedUser($user_id, $evaluator_id)
05411         {
05412                 $query = sprintf("DELETE FROM tst_eval_users WHERE test_fi = %s AND user_fi = %s AND evaluator_fi = %s",
05413                         $this->ilias->db->quote($this->getTestId() . ""),
05414                         $this->ilias->db->quote($user_id . ""),
05415                         $this->ilias->db->quote($evaluator_id . "")
05416                 );
05417                 $result = $this->ilias->db->query($query);
05418         }
05419 
05428         function addSelectedUser($user_id, $evaluator_id)
05429         {
05430                 $query = sprintf("SELECT user_fi FROM tst_active WHERE test_fi = %s AND user_fi = %s",
05431                         $this->ilias->db->quote($this->getTestId() . ""),
05432                         $this->ilias->db->quote($user_id . "")
05433                 );
05434                 $result = $this->ilias->db->query($query);
05435                 if ($result->numRows() == 1)
05436                 {
05437                         $query = sprintf("REPLACE INTO tst_eval_users (test_fi, evaluator_fi, user_fi) VALUES (%s, %s, %s)",
05438                                 $this->ilias->db->quote($this->getTestId() . ""),
05439                                 $this->ilias->db->quote($evaluator_id . ""),
05440                                 $this->ilias->db->quote($user_id . "")
05441                         );
05442                         $result = $this->ilias->db->query($query);
05443                 }
05444         }
05445 
05454         function addSelectedGroup($group_id, $evaluator_id)
05455         {
05456                 include_once "./classes/class.ilObjGroup.php";
05457                 $group = new ilObjGroup($group_id);
05458                 $members = $group->getGroupMemberIds();
05459                 foreach ($members as $user_id)
05460                 {
05461                         $this->addSelectedUser($user_id, $evaluator_id);
05462                 }               
05463         }
05464         
05473         function addSelectedRole($role_id, $evaluator_id)
05474         {
05475                 global $rbacreview;
05476                 $members =  $rbacreview->assignedUsers($role_id,"usr_id");
05477                 foreach ($members as $user_id)
05478                 {
05479                         $this->addSelectedUser($user_id, $evaluator_id);
05480                 }               
05481         }
05482         
05491         function getQuestionCount()
05492         {
05493                 $num = 0;
05494                 
05495                 if ($this->isRandomTest())
05496                 {
05497                         if ($this->getRandomQuestionCount())
05498                         {
05499                                 $num = $this->getRandomQuestionCount();
05500                         }
05501                                 else
05502                         {
05503                                 $qpls =& $this->getRandomQuestionpools();
05504                                 foreach ($qpls as $data)
05505                                 {
05506                                         $num += $data["count"];
05507                                 }
05508                         }
05509                 }
05510                         else
05511                 {
05512                         $num = count($this->questions);
05513                 }
05514                 return $num;
05515         }
05516 
05525         function _getQuestionCount($test_id, $user_id)
05526         {
05527                 global $ilDB;
05528                 
05529                 $num = 0;
05530                 
05531                 $query = sprintf("SELECT * FROM tst_tests WHERE test_id = %s",
05532                         $ilDB->quote($test_id . "")
05533                 );
05534                 $result = $ilDB->query($query);
05535                 if (!$result->numRows())
05536                 {
05537                         return 0;
05538                 }
05539                 $test = $result->fetchRow(DB_FETCHMODE_ASSOC);
05540                 
05541                 if ($test["random_test"] == 1)
05542                 {
05543                         $query = sprintf("SELECT test_random_question_id FROM tst_test_random_question WHERE test_fi = %s AND user_fi = %s AND pass = 0",
05544                                 $ilDB->quote($test_id . ""),
05545                                 $ilDB->quote($user_id . "")
05546                         );
05547                         $result = $ilDB->query($query);
05548                         $num = $result->numRows();
05549                 }
05550                 else
05551                 {
05552                         $query = sprintf("SELECT test_question_id FROM tst_test_question WHERE test_fi = %s",
05553                                 $ilDB->quote($test_id . "")
05554                         );
05555                         $result = $ilDB->query($query);
05556                         $num = $result->numRows();
05557                 }
05558                 return $num;
05559         }
05560         
05569         function _goto($a_target)
05570         {
05571                 global $rbacsystem, $ilErr, $lng;
05572 
05573                 include_once "./classes/class.ilSearch.php";
05574                         
05575                 // Added this additional check (ParentConditions) to avoid calls of objects inside e.g courses.
05576                 // Will be replaced in future releases by ilAccess::checkAccess()
05577                 if ($rbacsystem->checkAccess("read", $a_target) and ilSearch::_checkParentConditions($a_target))
05578                 {
05579                         include_once "./classes/class.ilUtil.php";
05580                         ilUtil::redirect("ilias.php?baseClass=ilObjTestGUI&cmd=infoScreen&ref_id=$a_target");
05581                 }
05582                 else
05583                 {
05584                         $ilErr->raiseError($lng->txt("msg_no_perm_read_lm"), $ilErr->FATAL);
05585                 }
05586         }       
05587 
05595         function removeNonRandomTestData()
05596         {
05597                 // delete eventually set questions of a previous non-random test
05598                 $this->removeAllTestEditings();
05599                 $query = sprintf("DELETE FROM tst_test_question WHERE test_fi = %s",
05600                         $this->ilias->db->quote($this->getTestId())
05601                 );
05602                 $result = $this->ilias->db->query($query);
05603                 $this->questions = array();
05604                 $this->saveCompleteStatus();
05605         }
05606         
05614         function removeRandomTestData()
05615         {
05616                 // delete eventually set random question pools of a previous random test
05617                 $this->removeAllTestEditings();
05618                 $query = sprintf("DELETE FROM tst_test_random WHERE test_fi = %s",
05619                         $this->ilias->db->quote($this->getTestId())
05620                 );
05621                 $result = $this->ilias->db->query($query);
05622                 $this->questions = array();
05623                 $this->saveCompleteStatus();
05624         }
05625         
05635         function logAction($logtext = "", $question_id = "")
05636         {
05637                 global $ilUser;
05638 
05639                 $original_id = "";
05640                 if (strcmp($question_id, "") != 0)
05641                 {
05642                         include_once "./assessment/classes/class.assQuestion.php";
05643                         $original_id = ASS_Question::_getOriginalId($question_id);
05644                 }
05645                 include_once "./classes/class.ilObjAssessmentFolder.php";
05646                 ilObjAssessmentFolder::_addLog($ilUser->id, $this->getId(), $logtext, $question_id, $original_id);
05647         }
05648         
05658         function _getObjectIDFromTestID($test_id)
05659         {
05660                 global $ilDB;
05661                 $object_id = FALSE;
05662                 $query = sprintf("SELECT obj_fi FROM tst_tests WHERE test_id = %s",
05663                         $ilDB->quote($test_id . "")
05664                 );
05665                 $result = $ilDB->query($query);
05666                 if ($result->numRows())
05667                 {
05668                         $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
05669                         $object_id = $row["obj_fi"];
05670                 }
05671                 return $object_id;
05672         }
05673 
05683         function _getTestIDFromObjectID($object_id)
05684         {
05685                 global $ilDB;
05686                 $test_id = FALSE;
05687                 $query = sprintf("SELECT test_id FROM tst_tests WHERE obj_fi = %s",
05688                         $ilDB->quote($object_id . "")
05689                 );
05690                 $result = $ilDB->query($query);
05691                 if ($result->numRows())
05692                 {
05693                         $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
05694                         $test_id = $row["test_id"];
05695                 }
05696                 return $test_id;
05697         }
05698 
05709         function getTextAnswer($user_id, $question_id, $pass = NULL)
05710         {
05711                 $res = "";
05712                 if (($user_id) && ($question_id))
05713                 {
05714                         if (is_null($pass))
05715                         {
05716                                 include_once "./assessment/classes/class.assQuestion.php";
05717                                 $pass = ASS_Question::_getSolutionMaxPass($question_id, $user_id, $this->getTestId());
05718                         }
05719                         $query = sprintf("SELECT value1 FROM tst_solutions WHERE user_fi = %s AND test_fi = %s AND question_fi = %s AND pass = %s",
05720                                 $this->ilias->db->quote($user_id . ""),
05721                                 $this->ilias->db->quote($this->getTestId() . ""),
05722                                 $this->ilias->db->quote($question_id . ""),
05723                                 $this->ilias->db->quote($pass . "")
05724                         );
05725                         $result = $this->ilias->db->query($query);
05726                         if ($result->numRows() == 1)
05727                         {
05728                                 $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
05729                                 $res = $row["value1"];
05730                         }
05731                 }
05732                 return $res;
05733         }
05734         
05744         function getQuestiontext($question_id)
05745         {
05746                 $res = "";
05747                 if ($question_id)
05748                 {
05749                         $query = sprintf("SELECT question_text FROM qpl_questions WHERE question_id = %s",
05750                                 $this->ilias->db->quote($question_id . "")
05751                         );
05752                         $result = $this->ilias->db->query($query);
05753                         if ($result->numRows() == 1)
05754                         {
05755                                 $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
05756                                 $res = $row["question_text"];
05757                         }
05758                 }
05759                 return $res;            
05760         }
05761         
05770         function &getInvitedUsers($user_id="", $order="login, lastname, firstname")
05771         {
05772                 global $ilDB;
05773                 
05774                 $result_array = array();
05775 
05776                 if (is_numeric($user_id))
05777                 {
05778                         $query = sprintf("SELECT usr_id, login, lastname, firstname, tst_invited_user.clientip, " .
05779                                 "tst_active.submitted as test_finished, matriculation, IF(tst_active.active_id IS NULL,0,1) as test_started " .
05780                                 "FROM usr_data, tst_invited_user " . 
05781                                 "LEFT JOIN tst_active ON tst_active.user_fi = tst_invited_user.user_fi AND tst_active.test_fi = tst_invited_user.test_fi " .
05782                                 "WHERE tst_invited_user.test_fi = %s and tst_invited_user.user_fi=usr_data.usr_id AND usr_data.usr_id=%s " .
05783                                 "ORDER BY %s",
05784                                 $ilDB->quote($this->test_id),
05785                                 $user_id,
05786                                 $order
05787                         );
05788 /*              CREATED NEW VERSION FOR MYSQL 5 COMPATIBILITY (Helmut Schottmüller, 2006-09-18)
05789                                 $query = sprintf("SELECT usr_id, login, lastname, firstname, t.clientip, test.submitted as test_finished, matriculation, IF(test.active_id IS NULL,0,1) as test_started " .
05790                                                          "FROM tst_invited_user t, usr_data ".
05791                                                          "LEFT JOIN tst_active test ON test.user_fi=usr_id AND test.test_fi=t.test_fi ".
05792                                                          "WHERE t.test_fi = %s and t.user_fi=usr_id AND usr_id=%s ".
05793                                                          "ORDER BY %s",
05794                                 $ilDB->quote($this->test_id),
05795                                 $user_id,
05796                                 $order
05797                         );*/
05798                 }
05799                 else 
05800                 {
05801                         $query = sprintf("SELECT usr_id, login, lastname, firstname, tst_invited_user.clientip, " .
05802                                 "tst_active.submitted as test_finished, matriculation, IF(tst_active.active_id IS NULL,0,1) as test_started " .
05803                                 "FROM usr_data, tst_invited_user " . 
05804                                 "LEFT JOIN tst_active ON tst_active.user_fi = tst_invited_user.user_fi AND tst_active.test_fi = tst_invited_user.test_fi " .
05805                                 "WHERE tst_invited_user.test_fi = %s and tst_invited_user.user_fi=usr_data.usr_id " .
05806                                 "ORDER BY %s",
05807                                 $ilDB->quote($this->test_id),
05808                                 $order
05809                         );
05810 /*              CREATED NEW VERSION FOR MYSQL 5 COMPATIBILITY (Helmut Schottmüller, 2006-09-18)
05811                                 $query = sprintf("SELECT usr_id, login, lastname, firstname, t.clientip, test.submitted as test_finished, matriculation, IF(test.active_id IS NULL,0,1) as test_started " .                                                                                     
05812                                                          "FROM tst_invited_user t, usr_data ".
05813                                                          "LEFT JOIN tst_active test ON test.user_fi=usr_id AND test.test_fi=t.test_fi ".
05814                                                          "WHERE t.test_fi = %s and t.user_fi=usr_id ".
05815                                                          "ORDER BY %s",
05816                                 $ilDB->quote($this->test_id),
05817                                 $order
05818                         );*/
05819                 }
05820                 
05821                 return $this->getArrayData($query, "usr_id");
05822         }
05823         
05833         function &getUserData($ids)
05834         {
05835                 if (!is_array($ids) || count($ids) ==0)
05836                         return array();
05837                         
05838                 $result_array = array();
05839                         
05840                 $query = sprintf("SELECT usr_id, login, lastname, firstname, client_ip as clientip FROM usr_data WHERE usr_id IN (%s) ORDER BY login",                  
05841                         join ($ids,",")
05842                 );
05843                                 
05844                 return $this->getArrayData ($query, "usr_id");          
05845         }
05846         
05857         function &getArrayData($query, $id_field)
05858         {       
05859                 return ilObjTest::_getArrayData ($query, $id_field);
05860         }
05861         
05862         function &_getArrayData($query, $id_field)
05863         {       
05864                 global $ilDB;
05865                 $result = $ilDB->query($query);
05866                 while ($row = $result->fetchRow(DB_FETCHMODE_OBJECT))
05867                 {
05868                         $result_array[$row->$id_field]= $row;
05869                 }
05870                 return ($result_array)?$result_array:array();
05871         }
05872 
05873         function &getGroupData($ids)
05874         {
05875                 if (!is_array($ids) || count($ids) ==0)
05876                         return array();
05877                         
05878                 $result_array = array();
05879                         
05880                 $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)",                     
05881                         join ($ids,",")
05882                 );
05883                 
05884                 return $this->getArrayData ($query, "ref_id");          
05885         }
05886         
05887         function &getRoleData($ids)
05888         {
05889                 if (!is_array($ids) || count($ids) ==0)
05890                         return array();
05891                         
05892                 $result_array = array();
05893                         
05894                 $query = sprintf("SELECT obj_id, description, title FROM role_data, object_data o WHERE o.obj_id=role_id AND role_id IN (%s)",                  
05895                         join ($ids,",")
05896                 );
05897                 
05898                 return $this->getArrayData ($query, "obj_id");          
05899         }
05900 
05901 
05910         function inviteGroup($group_id)
05911         {                       
05912                 include_once "./classes/class.ilObjGroup.php";
05913                 $group = new ilObjGroup($group_id);
05914                 $members = $group->getGroupMemberIds();
05915                 include_once "./classes/class.ilObjUser.php";
05916                 foreach ($members as $user_id)
05917                 {
05918                         $this->inviteUser($user_id, ilObjUser::_lookupClientIP($user_id));
05919                 }               
05920         }
05921         
05930         function inviteRole($role_id)
05931         {                       
05932                 global $rbacreview;
05933                 $members =  $rbacreview->assignedUsers($role_id,"usr_id");
05934                 include_once "./classes/class.ilObjUser.php";
05935                 foreach ($members as $user_id)
05936                 {
05937                         $this->inviteUser($user_id, ilObjUser::_lookupClientIP($user_id));
05938                 }               
05939         }
05940         
05941         
05942         
05951         function disinviteUser($user_id)
05952         {
05953                 $query = sprintf("DELETE FROM tst_invited_user WHERE test_fi = %s AND user_fi = %s",
05954                         $this->ilias->db->quote($this->test_id),
05955                         $this->ilias->db->quote($user_id)
05956                 );
05957                 $result = $this->ilias->db->query($query);      
05958         }
05959 
05968         function inviteUser($user_id, $client_ip="")
05969         {
05970                 $query = sprintf("INSERT IGNORE INTO tst_invited_user (test_fi, user_fi, clientip) VALUES (%s, %s, %s)",
05971                         $this->ilias->db->quote($this->test_id),
05972                         $this->ilias->db->quote($user_id),
05973                         $this->ilias->db->quote($client_ip)
05974                 );
05975                 
05976                 $result = $this->ilias->db->query($query);
05977         }
05978         
05979                 
05980         function setClientIP($user_id, $client_ip) {            
05981                 $query = sprintf("UPDATE tst_invited_user SET clientip=%s WHERE test_fi=%s and user_fi=%s",
05982                                 $this->ilias->db->quote($client_ip),
05983                                 $this->ilias->db->quote($this->test_id),
05984                                 $this->ilias->db->quote($user_id)
05985                 );
05986                 $insertresult = $this->ilias->db->query($query);
05987         }
05988         
05995         function isOnlineTest() 
05996         {
05997                 return $this->getTestType()==TYPE_ONLINE_TEST;
05998         }
05999         
06000         
06001         
06007         function _getSolvedQuestions($test_fi, $user_fi, $question_fi = null) 
06008         {
06009                 global $ilDB;
06010                 if (is_numeric($question_fi))
06011                         $query = sprintf("SELECT question_fi, solved FROM tst_active_qst_sol_settings " .
06012                                                  "WHERE user_fi = %s AND test_fi = %s AND question_fi=%s",
06013                                                         $ilDB->quote($user_fi),
06014                                                         $ilDB->quote($test_fi),
06015                                                         $question_fi
06016                         );
06017                 else $query = sprintf("SELECT question_fi, solved FROM tst_active_qst_sol_settings " .
06018                                                  "WHERE user_fi = %s AND test_fi = %s",
06019                         $ilDB->quote($user_fi),
06020                         $ilDB->quote($test_fi)
06021                 );
06022                 return ilObjTest::_getArrayData ($query, "question_fi");                
06023         }
06024         
06025         
06029         function setQuestionSetSolved ($value, $question_id, $user_id) 
06030         {
06031                 $query = sprintf("REPLACE INTO tst_active_qst_sol_settings SET solved=%s, question_fi=%s, test_fi=%s, user_fi=%s",
06032                         $this->ilias->db->quote($value),
06033                         $this->ilias->db->quote($question_id),
06034                         $this->ilias->db->quote($this->test_id),
06035                         $this->ilias->db->quote($user_id)
06036                 );
06037                 
06038                 $this->ilias->db->query($query);                                
06039         }
06040         
06041         
06045         function setActiveTestSubmitted($user_id) 
06046         {
06047                 $query = sprintf("UPDATE tst_active SET submitted=1, tries=1, submittimestamp=NOW() WHERE test_fi=%s AND user_fi=%s",
06048                         $this->ilias->db->quote($this->test_id),
06049                         $this->ilias->db->quote($user_id)
06050                 );              
06051                 $this->ilias->db->query($query);                                
06052                 
06053         }
06054         
06058         function isActiveTestSubmitted($user_id = null) 
06059         {
06060                 global $ilUser;
06061                 if (!is_numeric($user_id))
06062                         $user_id = $ilUser->getId();
06063                         
06064                 $query = sprintf("SELECT submitted FROM tst_active WHERE test_fi=%s AND user_fi=%s AND submitted=1",
06065                         $this->ilias->db->quote($this->test_id),
06066                         $this->ilias->db->quote($user_id)
06067                 );              
06068                 $result = $this->ilias->db->query($query);              
06069                 
06070                 return  $result->numRows() == 1;
06071                 
06072         }
06076         function hasNrOfTriesRestriction() 
06077         {
06078                 return $this->getNrOfTries() != 0;
06079         }
06080         
06081         
06086         function isNrOfTriesReached($tries) 
06087         {
06088                 return $tries >= (int) $this->getNrOfTries();
06089         }
06090         
06091         
06095         function getAllTestResults() 
06096         {
06097                 $participants = $this->getInvitedUsers("matriculation");
06098                 $results = array();             
06099                 $row = array("matriculation" =>  $this->lng->txt("matriculation"),
06100                                         "lastname" =>  $this->lng->txt("lastname"),
06101                                         "firstname" => $this->lng->txt("firstname"),                                    
06102                                         "reached_points" => $this->lng->txt("tst_reached_points"),
06103                                         "max_points" => $this->lng->txt("tst_maximum_points"),
06104                                         "percent_value" => $this->lng->txt("tst_percent_solved"),
06105                                         "mark" => $this->lng->txt("tst_mark"),
06106                                         "ects" => $this->lng->txt("ects_grade"));
06107                 
06108                 $results[] = $row;
06109                 foreach ($participants as $user_id => $user_rec) 
06110                 {
06111                         $row = array();         
06112                         $reached_points = 0;
06113                         $max_points = 0;                                        
06114                         
06115                         foreach ($this->questions as $value)
06116                         {
06117                         //$value = $this->questions[$seq];
06118 //                              $ilBench->start("getTestResult","instanciate question"); 
06119                                 $question =& ilObjTest::_instanciateQuestion($value);
06120 //                              $ilBench->stop("getTestResult","instanciate question"); 
06121                                 if (is_object($question))
06122                                 {
06123                                         $max_points += $question->getMaximumPoints();
06124                                         $reached_points += $question->getReachedPoints($user_id, $this->getTestId()); 
06125                                 }
06126                         }
06127                         
06128                         if ($max_points > 0)
06129                         {
06130                                 $percentvalue = $reached_points / $max_points;
06131                         }
06132                         else
06133                         {
06134                                 $percentvalue = 0;
06135                         }                       
06136                         $mark_obj = $this->mark_schema->get_matching_mark($percentvalue * 100);
06137                         $passed = "";   
06138                         if ($mark_obj)
06139                         {
06140                                 $mark = $mark_obj->get_official_name();
06141                                 $ects_mark = $this->getECTSGrade($reached_points, $max_points);
06142                         }
06143 
06144                         $row = array(
06145                                         "matriculation" =>  $user_rec->matriculation,
06146                                         "lastname" =>  $user_rec->lastname,
06147                                         "firstname" => $user_rec->firstname,
06148                                         "reached_points" => $reached_points,
06149                                         "max_points" => $max_points,
06150                                         "percent_value" => $percentvalue,
06151                                         "mark" => $mark,
06152                                         "ects" => $ects_mark);
06153                         $results[] = $this->processCSVRow ($row, true);
06154                 }                                                               
06155                 return $results;
06156         }
06157         
06170         function &processCSVRow($row, $quoteAll = FALSE, $separator = ";")
06171         {
06172                 $resultarray = array();
06173                 foreach ($row as $rowindex => $entry)
06174                 {
06175                         $surround = FALSE;
06176                         if ($quoteAll)
06177                         {
06178                                 $surround = TRUE;
06179                         }
06180                         if (strpos($entry, "\"") !== FALSE)
06181                         {
06182                                 $entry = str_replace("\"", "\"\"", $entry);
06183                                 $surround = TRUE;
06184                         }
06185                         if (strpos($entry, $separator) !== FALSE)
06186                         {
06187                                 $surround = TRUE;
06188                         }
06189                         // replace all CR LF with LF (for Excel for Windows compatibility
06190                         $entry = str_replace(chr(13).chr(10), chr(10), $entry);
06191                         if ($surround)
06192                         {
06193                                 $resultarray[$rowindex] = utf8_decode("\"" . $entry . "\"");
06194                         }
06195                         else
06196                         {
06197                                 $resultarray[$rowindex] = utf8_decode($entry);
06198                         }
06199                 }
06200                 return $resultarray;
06201         }
06202         
06213         function _getPass($user_id, $test_id)
06214         {
06215                 global $ilDB;
06216                 $query = sprintf("SELECT tries FROM tst_active WHERE user_fi = %s AND test_fi = %s",
06217                         $ilDB->quote($user_id . ""),
06218                         $ilDB->quote($test_id . "")
06219                 );
06220                 $result = $ilDB->query($query);
06221                 if ($result->numRows())
06222                 {
06223                         $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
06224                         return $row["tries"];
06225                 }
06226                 else
06227                 {
06228                         return 0;
06229                 }
06230         }
06231         
06242         function _getBestPass($user_id, $test_id)
06243         {
06244                 global $ilDB;
06245                 $lastpass = ilObjTest::_getPass($user_id, $test_id);
06246                 $bestpass = 0;
06247                 $maxpoints = 0;
06248                 for ($i = 0; $i <= $lastpass; $i++)
06249                 {
06250                         $query = sprintf("SELECT SUM(points) AS maxpoints FROM tst_test_result WHERE user_fi = %s AND test_fi = %s AND pass = %s",
06251                                 $ilDB->quote($user_id . ""),
06252                                 $ilDB->quote($test_id . ""),
06253                                 $ilDB->quote($i . "")
06254                         );
06255                         $result = $ilDB->query($query);
06256                         if ($result->numRows())
06257                         {
06258                                 $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
06259                                 if ($row["maxpoints"] > $maxpoints)
06260                                 {
06261                                         $maxpoints = $row["maxpoints"];
06262                                         $bestpass = $i;
06263                                 }
06264                         }
06265                 }
06266                 return $bestpass;
06267         }
06268         
06279         function _getResultPass($user_id, $test_id)
06280         {
06281                 $counted_pass = NULL;
06282                 if (strcmp(ilObjTest::_getTestType($test_id), "tt_varying_randomtest") == 0)
06283                 {
06284                         if (ilObjTest::_getPassScoring($test_id) == SCORE_BEST_PASS)
06285                         {
06286                                 $counted_pass = ilObjTest::_getBestPass($user_id, $test_id);
06287                         }
06288                         else
06289                         {
06290                                 $counted_pass = ilObjTest::_getPass($user_id, $test_id);
06291                                 global $ilDB;
06292                                 $query = sprintf("SELECT test_result_id FROM tst_test_result WHERE user_fi = %s AND test_fi = %s AND pass = %s",
06293                                         $ilDB->quote($user_id . ""),
06294                                         $ilDB->quote($test_id . ""),
06295                                         $ilDB->quote($counted_pass . "")
06296                                 );
06297                                 $result = $ilDB->query($query);
06298                                 if ($result->numRows() == 0)
06299                                 {
06300                                         // There was no answer answered in the actual pass, so the last pass is
06301                                         // $counted_pass - 1
06302                                         $counted_pass -= 1;
06303                                 }
06304                                 if ($counted_pass < 0) $counted_pass = 0;
06305                         }
06306                 }
06307                 return $counted_pass;
06308         }
06309         
06321         function getAnsweredQuestionCount($user_id, $test_id, $pass = NULL)
06322         {
06323                 if ($this->isRandomTest())
06324                 {
06325                         $this->loadQuestions($user_id, $pass);
06326                 }
06327                 include_once "./assessment/classes/class.assQuestion.php";
06328                 $workedthrough = 0;
06329                 foreach ($this->questions as $value)
06330                 {
06331                         if (ASS_Question::_isWorkedThrough($user_id, $this->getTestId(), $value, $pass))
06332                         {
06333                                 $workedthrough += 1;
06334                         }
06335                 }
06336                 return $workedthrough;
06337         }
06338 
06350         function getPassFinishDate($user_id, $test_id, $pass)
06351         {
06352                 global $ilDB;
06353                 if (is_null($pass)) $pass = 0;
06354                 $query = sprintf("SELECT tst_test_result.TIMESTAMP + 0 AS TIMESTAMP14 FROM tst_test_result WHERE user_fi = %s AND test_fi = %s AND pass = %s ORDER BY tst_test_result.TIMESTAMP DESC",
06355                         $ilDB->quote($user_id . ""),
06356                         $ilDB->quote($test_id . ""),
06357                         $ilDB->quote($pass . "")
06358                 );
06359                 $result = $ilDB->query($query);
06360                 if ($result->numRows())
06361                 {
06362                         $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
06363                         return $row["TIMESTAMP14"];
06364                 }
06365                 else
06366                 {
06367                         return 0;
06368                 }
06369         }
06370         
06380         function isExecutable($user_id)
06381         {
06382                 $result = array(
06383                         "executable" => true,
06384                         "errormessage" => ""
06385                 );
06386                 if (!$this->startingTimeReached())
06387                 {
06388                         $result["executable"] = false;
06389                         $result["errormessage"] = sprintf($this->lng->txt("detail_starting_time_not_reached"), ilFormat::ftimestamp2datetimeDB($this->getStartingTime()));
06390                         return $result;
06391                 }
06392                 if ($this->endingTimeReached())
06393                 {
06394                         $result["executable"] = false;
06395                         $result["errormessage"] = sprintf($this->lng->txt("detail_ending_time_reached"), ilFormat::ftimestamp2datetimeDB($this->getEndingTime()));
06396                         return $result;
06397                 }
06398                 if ($this->getEnableProcessingTime())
06399                 {
06400                         $starting_time = $this->getStartingTimeOfUser($user_id);
06401                         if ($starting_time !== FALSE)
06402                         {
06403                                 if ($this->isMaxProcessingTimeReached($starting_time))
06404                                 {
06405                                         $result["executable"] = false;
06406                                         $result["errormessage"] = $this->lng->txt("detail_max_processing_time_reached");
06407                                         return $result;
06408                                 }
06409                         }
06410                 }
06411 
06412                 $active = $this->getActiveTestUser($user_id);
06413                 if ($this->hasNrOfTriesRestriction() && is_object($active) && $this->isNrOfTriesReached($active->tries))
06414                 {
06415                         $result["executable"] = false;
06416                         if ($this->isOnlineTest())
06417                         {
06418                                 // don't display an errormessage for online exams. It could confuse users
06419                                 // because they will get either a finish test button or a print test button
06420                                 $result["errormessage"] = "";
06421                         }
06422                         else
06423                         {
06424                                 $result["errormessage"] = $this->lng->txt("maximum_nr_of_tries_reached");
06425                         }
06426                         return $result;
06427                 }
06428                 
06429                 // TODO: max. processing time
06430                 
06431                 return $result;
06432         }
06433 
06434         function canShowTestResults($user_id) 
06435         {
06436                 $active = $this->getActiveTestUser($user_id);
06437                 $starting_time = $this->getStartingTimeOfUser($user_id);
06438                 $notimeleft = FALSE;
06439                 if ($starting_time !== FALSE)
06440                 {
06441                         if ($this->isMaxProcessingTimeReached($starting_time))
06442                         {
06443                                 $notimeleft = TRUE;
06444                         }
06445                 }
06446                 $result = (($active->tries > 0) || ($this->endingTimeReached()) || $notimeleft) && $this->canViewResults();
06447                 if ($this->getTestType() == TYPE_ONLINE_TEST)
06448                 {
06449                         return $result && $this->isActiveTestSubmitted();
06450                 }
06451                 return $result;
06452         }
06453         
06454         function canEditMarks()
06455         {
06456                 $total = $this->evalTotalPersons();
06457                 if ($total > 0)
06458                 {
06459                         if ($this->getReportingDate())
06460                         {
06461                                 if (preg_match("/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/", $this->getReportingDate(), $matches))
06462                                 {
06463                                         $epoch_time = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
06464                                         $now = mktime();
06465                                         if ($now < $epoch_time) 
06466                                         {
06467                                                 return true;
06468                                         }
06469                                 }
06470                         }
06471                         return false;
06472                 }
06473                 else
06474                 {
06475                         return true;
06476                 }
06477         }
06478         
06488         function getStartingTimeOfUser($user_id)
06489         {
06490                 global $ilDB;
06491                 
06492                 if ($user_id < 1) return FALSE;
06493                 $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",
06494                         $ilDB->quote($user_id . ""),
06495                         $ilDB->quote($this->getTestId() . "")
06496                 );
06497                 $result = $ilDB->query($query);
06498                 if ($result->numRows())
06499                 {
06500                         $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
06501                         if (preg_match("/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/", $row["started"], $matches))
06502                         {
06503                                 return mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
06504                         }
06505                         else
06506                         {
06507                                 return FALSE;
06508                         }
06509                 }
06510                 else
06511                 {
06512                         return FALSE;
06513                 }
06514         }
06515         
06526         function isMaxProcessingTimeReached($starting_time)
06527         {
06528                 if ($this->getEnableProcessingTime())
06529                 {
06530                         $processing_time = $this->getProcessingTimeInSeconds();
06531                         $now = mktime();
06532                         if ($now > ($starting_time + $processing_time))
06533                         {
06534                                 return TRUE;
06535                         }
06536                         else
06537                         {
06538                                 return FALSE;
06539                         }
06540                 }
06541                 else
06542                 {
06543                         return FALSE;
06544                 }
06545         }
06546         
06558         function &_getPassedUsers($a_obj_id)
06559         {
06560                 global $ilDB;
06561                 
06562                 $passed_users = array();
06563                 $query = sprintf("SELECT tst_active.* FROM tst_active, tst_tests ".
06564                                                  "WHERE tst_tests.obj_fi = %s ".
06565                                                  "AND tst_active.test_fi = tst_tests.test_id",
06566                         $ilDB->quote($a_obj_id . "")
06567                 );
06568                 $result = $ilDB->query($query);
06569                 if ($result->numRows())
06570                 {
06571                         while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC))
06572                         {
06573                                 $user_id = $row["user_fi"];
06574                                 $test_id = $row["test_fi"];
06575                                 $pass = ilObjTest::_getResultPass($user_id, $test_id);
06576                                 include_once "./assessment/classes/class.ilObjTestAccess.php";
06577                                 $testres =& ilObjTestAccess::_getTestResult($user_id, $a_obj_id, $pass);
06578                                 if ((bool) $testres['passed'])
06579                                 {
06580                                         array_push($passed_users, $user_id);
06581                                 }
06582                         }
06583                 }
06584                 return $passed_users;
06585         }
06586 
06587 } // END class.ilObjTest
06588 
06589 ?>

Generated on Fri Dec 13 2013 11:57:53 for ILIAS Release_3_6_x_branch .rev 46809 by  doxygen 1.7.1