public function recalculateSolutions()
 {
     $participants = $this->test->getCompleteEvaluationData(false)->getParticipants();
     if (is_array($participants)) {
         require_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
         foreach ($participants as $active_id => $userdata) {
             if (is_object($userdata) && is_array($userdata->getPasses())) {
                 $this->recalculatePasses($userdata, $active_id);
             }
             assQuestion::_updateTestResultCache($active_id);
         }
     }
 }
Beispiel #2
0
 public function getResultsForActiveId($active_id)
 {
     global $ilDB;
     $query = "\n\t\t\tSELECT\t\t*\n\t\t\tFROM\t\ttst_result_cache\n\t\t\tWHERE\t\tactive_fi = %s\n\t\t";
     $result = $ilDB->queryF($query, array('integer'), array($active_id));
     if (!$result->numRows()) {
         include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
         assQuestion::_updateTestResultCache($active_id);
         $query = "\n\t\t\t\tSELECT\t\t*\n\t\t\t\tFROM\t\ttst_result_cache\n\t\t\t\tWHERE\t\tactive_fi = %s\n\t\t\t";
         $result = $ilDB->queryF($query, array('integer'), array($active_id));
     }
     $row = $ilDB->fetchAssoc($result);
     return $row;
 }
    public function performDeletePass()
    {
        if (!$this->object->isPassDeletionAllowed()) {
            $this->ctrl->redirect($this, 'outUserResultsOverview');
        }
        /** @var ilDB $ilDB */
        global $ilDB;
        $active_fi = null;
        $pass = null;
        if (isset($_POST['active_id']) && (int) $_POST['active_id']) {
            $active_fi = $_POST['active_id'];
        }
        if (isset($_POST['pass']) && is_numeric($_POST['pass'])) {
            $pass = $_POST['pass'];
        }
        if (is_null($active_fi) || is_null($pass)) {
            $this->ctrl->redirect($this, 'outUserResultsOverview');
        }
        if (!$this->object->isDynamicTest() && $pass == $this->object->_getResultPass($active_fi)) {
            $this->ctrl->redirect($this, 'outUserResultsOverview');
        }
        // Get information
        $result = $ilDB->query("\n\t\t\t\tSELECT tst_active.tries, tst_active.last_finished_pass, tst_sequence.pass\n\t\t\t\tFROM tst_active\n\t\t\t\tLEFT JOIN tst_sequence\n\t\t\t\tON tst_sequence.active_fi = tst_active.active_id\n\t\t\t\tAND tst_sequence.pass = tst_active.tries\n\t\t\t\tWHERE tst_active.active_id = {$ilDB->quote($active_fi, 'integer')}\n\t\t\t");
        $row = $ilDB->fetchAssoc($result);
        $tries = $row['tries'];
        $lastFinishedPass = is_numeric($row['last_finished_pass']) ? $row['last_finished_pass'] : -1;
        if ($pass < $lastFinishedPass) {
            $isActivePass = false;
            $must_renumber = true;
        } elseif ($pass == $lastFinishedPass) {
            $isActivePass = false;
            if ($tries == $row['pass']) {
                $must_renumber = true;
            } else {
                $must_renumber = false;
            }
        } elseif ($pass == $row['pass']) {
            $isActivePass = true;
            $must_renumber = false;
        } else {
            throw new ilTestException('This should not happen, please contact Bjoern Heyser to clean up this pass salad!');
        }
        if (!$this->object->isDynamicTest() && $isActivePass) {
            $this->ctrl->redirect($this, 'outUserResultsOverview');
        }
        if ($pass == 0 && ($lastFinishedPass == 0 && $tries == 1 && $tries != $row['pass'] || $isActivePass == true)) {
            $last_pass = true;
        } else {
            $last_pass = false;
        }
        // Work on tables:
        // tst_active
        if ($last_pass) {
            $ilDB->manipulate('DELETE
					FROM tst_active
					WHERE active_id = ' . $ilDB->quote($active_fi, 'integer'));
        } elseif (!$isActivePass) {
            $ilDB->manipulate('UPDATE tst_active
					SET tries = ' . $ilDB->quote($tries - 1, 'integer') . ',
					last_finished_pass = '******'integer') . '
					WHERE active_id = ' . $ilDB->quote($active_fi, 'integer'));
        }
        // tst_manual_fb
        $ilDB->manipulate('DELETE
				FROM tst_manual_fb
				WHERE active_fi = ' . $ilDB->quote($active_fi, 'integer') . '
				AND pass = '******'integer'));
        if ($must_renumber) {
            $ilDB->manipulate('UPDATE tst_manual_fb
				SET pass = pass - 1
				WHERE active_fi = ' . $ilDB->quote($active_fi, 'integer') . '
				AND pass > ' . $ilDB->quote($pass, 'integer'));
        }
        // tst_mark -> nothing to do
        //
        // tst_pass_result
        $ilDB->manipulate('DELETE
				FROM tst_pass_result
				WHERE active_fi = ' . $ilDB->quote($active_fi, 'integer') . '
				AND pass = '******'integer'));
        if ($must_renumber) {
            $ilDB->manipulate('UPDATE tst_pass_result
				SET pass = pass - 1
				WHERE active_fi = ' . $ilDB->quote($active_fi, 'integer') . '
				AND pass > ' . $ilDB->quote($pass, 'integer'));
        }
        // tst_qst_solved -> nothing to do
        // tst_rnd_copy -> nothing to do
        // tst_rnd_qpl_title -> nothing to do
        // tst_sequence
        $ilDB->manipulate('DELETE
				FROM tst_sequence
				WHERE active_fi = ' . $ilDB->quote($active_fi, 'integer') . '
				AND pass = '******'integer'));
        if ($must_renumber) {
            $ilDB->manipulate('UPDATE tst_sequence
				SET pass = pass - 1
				WHERE active_fi = ' . $ilDB->quote($active_fi, 'integer') . '
				AND pass > ' . $ilDB->quote($pass, 'integer'));
        }
        if ($this->object->isDynamicTest()) {
            $tables = array('tst_seq_qst_tracking', 'tst_seq_qst_answstatus', 'tst_seq_qst_postponed', 'tst_seq_qst_checked');
            foreach ($tables as $table) {
                $ilDB->manipulate("\n\t\t\t\t\t\tDELETE FROM {$table}\n\t\t\t\t\t\tWHERE active_fi = {$ilDB->quote($active_fi, 'integer')}\n\t\t\t\t\t\tAND pass = {$ilDB->quote($pass, 'integer')}\n\t\t\t\t");
                if ($must_renumber) {
                    $ilDB->manipulate("\n\t\t\t\t\t\tUPDATE {$table}\n\t\t\t\t\t\tSET pass = pass - 1\n\t\t\t\t\t\tWHERE active_fi = {$ilDB->quote($active_fi, 'integer')}\n\t\t\t\t\t\tAND pass > {$ilDB->quote($pass, 'integer')}\n\t\t\t\t\t");
                }
            }
        }
        // tst_solutions
        $ilDB->manipulate('DELETE
				FROM tst_solutions
				WHERE active_fi = ' . $ilDB->quote($active_fi, 'integer') . '
				AND pass = '******'integer'));
        if ($must_renumber) {
            $ilDB->manipulate('UPDATE tst_solutions
				SET pass = pass - 1
				WHERE active_fi = ' . $ilDB->quote($active_fi, 'integer') . '
				AND pass > ' . $ilDB->quote($pass, 'integer'));
        }
        // tst_test_result
        $ilDB->manipulate('DELETE
				FROM tst_test_result
				WHERE active_fi = ' . $ilDB->quote($active_fi, 'integer') . '
				AND pass = '******'integer'));
        if ($must_renumber) {
            $ilDB->manipulate('UPDATE tst_test_result
				SET pass = pass - 1
				WHERE active_fi = ' . $ilDB->quote($active_fi, 'integer') . '
				AND pass > ' . $ilDB->quote($pass, 'integer'));
        }
        // tst_test_rnd_qst -> nothing to do
        // tst_times
        $ilDB->manipulate('DELETE
				FROM tst_times
				WHERE active_fi = ' . $ilDB->quote($active_fi, 'integer') . '
				AND pass = '******'integer'));
        if ($must_renumber) {
            $ilDB->manipulate('UPDATE tst_times
				SET pass = pass - 1
				WHERE active_fi = ' . $ilDB->quote($active_fi, 'integer') . '
				AND pass > ' . $ilDB->quote($pass, 'integer'));
        }
        require_once 'Modules/Test/classes/class.ilObjAssessmentFolder.php';
        if (ilObjAssessmentFolder::_enabledAssessmentLogging()) {
            $this->object->logAction($this->lng->txtlng("assessment", "log_deleted_pass", ilObjAssessmentFolder::_getLogLanguage()));
        }
        // tst_result_cache
        // Ggfls. nur renumbern.
        require_once './Modules/TestQuestionPool/classes/class.assQuestion.php';
        assQuestion::_updateTestResultCache($active_fi);
        if ($this->object->isDynamicTest()) {
            require_once 'Modules/Test/classes/tables/class.ilTestDynamicQuestionSetStatisticTableGUI.php';
            unset($_SESSION['form_' . ilTestDynamicQuestionSetStatisticTableGUI::FILTERED_TABLE_ID]);
        }
        $this->redirectToPassDeletionContext($_POST['context']);
    }
Beispiel #4
0
    /** @TODO Move this to a proper place. */
    function _updateTestPassResults($active_id, $pass, $obligationsEnabled = false, ilAssQuestionProcessLocker $processLocker = null, $test_obj_id = null)
    {
        global $ilDB;
        include_once "./Modules/Test/classes/class.ilObjTest.php";
        if (self::getResultGateway() !== null) {
            $data = self::getResultGateway()->getQuestionCountAndPointsForPassOfParticipant($active_id, $pass);
            $time = self::getResultGateway()->getWorkingTimeOfParticipantForPass($active_id, $pass);
        } else {
            $data = ilObjTest::_getQuestionCountAndPointsForPassOfParticipant($active_id, $pass);
            $time = ilObjTest::_getWorkingTimeOfParticipantForPass($active_id, $pass);
        }
        // update test pass results
        $result = $ilDB->queryF("\n\t\t\tSELECT\t\tSUM(points) reachedpoints,\n\t\t\t\t\t\tSUM(hint_count) hint_count,\n\t\t\t\t\t\tSUM(hint_points) hint_points,\n\t\t\t\t\t\tCOUNT(DISTINCT(question_fi)) answeredquestions\n\t\t\tFROM\t\ttst_test_result\n\t\t\tWHERE\t\tactive_fi = %s\n\t\t\tAND\t\t\tpass = %s\n\t\t\t", array('integer', 'integer'), array($active_id, $pass));
        if ($result->numRows() > 0) {
            if ($obligationsEnabled) {
                $query = '
					SELECT		count(*) cnt,
								min( answered ) answ
					FROM		tst_test_question
					INNER JOIN	tst_active
					ON			active_id = %s
					AND			tst_test_question.test_fi = tst_active.test_fi
					LEFT JOIN	tst_test_result
					ON			tst_test_result.active_fi = %s
					AND			tst_test_result.pass = %s
					AND			tst_test_question.question_fi = tst_test_result.question_fi
					WHERE		obligatory = 1';
                $result_obligatory = $ilDB->queryF($query, array('integer', 'integer', 'integer'), array($active_id, $active_id, $pass));
                $row_obligatory = $ilDB->fetchAssoc($result_obligatory);
                if ($row_obligatory['cnt'] == 0) {
                    $obligations_answered = 1;
                } else {
                    $obligations_answered = (int) $row_obligatory['answ'];
                }
            } else {
                $obligations_answered = 1;
            }
            $row = $ilDB->fetchAssoc($result);
            if ($row['hint_count'] === null) {
                $row['hint_count'] = 0;
            }
            if ($row['hint_points'] === null) {
                $row['hint_points'] = 0;
            }
            $exam_identifier = ilObjTest::buildExamId($active_id, $pass, $test_obj_id);
            if (is_object($processLocker)) {
                $processLocker->requestUserPassResultUpdateLock();
            }
            /*
            $query = "
            	DELETE FROM		tst_pass_result
            
            	WHERE			active_fi = %s
            	AND				pass = %s
            ";
            		
            $affectedRows = $ilDB->manipulateF(
            	$query, array('integer','integer'), array($active_id, $pass)
            );
            */
            /** @var $ilDB ilDB */
            $ilDB->replace('tst_pass_result', array('active_fi' => array('integer', $active_id), 'pass' => array('integer', strlen($pass) ? $pass : 0)), array('points' => array('float', $row['reachedpoints'] ? $row['reachedpoints'] : 0), 'maxpoints' => array('float', $data['points']), 'questioncount' => array('integer', $data['count']), 'answeredquestions' => array('integer', $row['answeredquestions']), 'workingtime' => array('integer', $time), 'tstamp' => array('integer', time()), 'hint_count' => array('integer', $row['hint_count']), 'hint_points' => array('float', $row['hint_points']), 'obligations_answered' => array('integer', $obligations_answered), 'exam_id' => array('text', $exam_identifier)));
            /*
            $ilDB->insert('tst_pass_result', array(
            	'active_fi'				=> array('integer', $active_id),
            	'pass'					=> array('integer', strlen($pass) ? $pass : 0),
            	'points'				=> array('float', $row['reachedpoints'] ? $row['reachedpoints'] : 0),
            	'maxpoints'				=> array('float', $data['points']),
            	'questioncount'			=> array('integer', $data['count']),
            	'answeredquestions'		=> array('integer', $row['answeredquestions']),
            	'workingtime'			=> array('integer', $time),
            	'tstamp'				=> array('integer', time()),
            	'hint_count'			=> array('integer', $row['hint_count']),
            	'hint_points'			=> array('float', $row['hint_points']),
            	'obligations_answered'	=> array('integer', $obligations_answered),
                'exam_id'				=> array('text', $exam_identifier)
            ));
            */
            if (is_object($processLocker)) {
                $this->getProcessLocker()->releaseUserPassResultUpdateLock();
            }
        }
        assQuestion::_updateTestResultCache($active_id, $processLocker);
        return array('active_fi' => $active_id, 'pass' => $pass, 'points' => $row["reachedpoints"] ? $row["reachedpoints"] : 0, 'maxpoints' => $data["points"], 'questioncount' => $data["count"], 'answeredquestions' => $row["answeredquestions"], 'workingtime' => $time, 'tstamp' => time(), 'hint_count' => $row['hint_count'], 'hint_points' => $row['hint_points'], 'obligations_answered' => $obligations_answered, 'exam_id' => $exam_identifier);
    }
 /**
 * Returns an array containing the users who passed the test
 *
 * @return array An array containing the users who passed the test.
 *         Format of the values of the resulting array:
 *           array(
 *             "user_id"        => user ID,
 *             "max_points"     => maximum available points in the test
 *             "reached_points" => maximum reached points of the user
 *             "mark_short"     => short text of the passed mark
 *             "mark_official"  => official text of the passed mark
 *           )
 * @access public
 */
 function &_getPassedUsers($a_obj_id)
 {
     global $ilDB;
     $passed_users = array();
     // Maybe SELECT DISTINCT(tst_active.user_fi)... ?
     $userresult = $ilDB->queryF("SELECT DISTINCT(tst_active.active_id) FROM tst_active, tst_tests WHERE tst_tests.test_id = tst_active.test_fi AND tst_tests.obj_fi = %s", array('integer'), array($a_obj_id));
     $all_participants = array();
     while ($row = $ilDB->fetchAssoc($userresult)) {
         array_push($all_participants, $row['active_id']);
     }
     $result = $ilDB->query("SELECT tst_result_cache.*, tst_active.user_fi FROM tst_result_cache, tst_active WHERE tst_active.active_id = tst_result_cache.active_fi AND " . $ilDB->in('active_fi', $all_participants, false, 'integer'));
     $found_all = $result->numRows() == count($all_participants) ? true : false;
     if (!$found_all) {
         // if the result cache entries do not exist, create them
         $found_participants = array();
         while ($data = $ilDB->fetchAssoc($result)) {
             array_push($found_participants, $data['active_fi']);
         }
         foreach ($all_participants as $active_id) {
             if (!in_array($active_id, $found_participants)) {
                 include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
                 assQuestion::_updateTestResultCache($active_id);
             }
         }
         $result = $ilDB->query("SELECT tst_result_cache.*, tst_active.user_fi FROM tst_result_cache, tst_active WHERE tst_active.active_id = tst_result_cache.active_fi AND " . $ilDB->in('active_fi', $all_participants, false, 'integer'));
     }
     while ($data = $ilDB->fetchAssoc($result)) {
         $data['user_id'] = $data['user_fi'];
         array_push($passed_users, $data);
     }
     return $passed_users;
 }
 /**
 * Returns an array containing the users who passed the test
 *
 * @return array An array containing the users who passed the test.
 *         Format of the values of the resulting array:
 *           array(
 *             "user_id"        => user ID,
 *             "max_points"     => maximum available points in the test
 *             "reached_points" => maximum reached points of the user
 *             "mark_short"     => short text of the passed mark
 *             "mark_official"  => official text of the passed mark
 *           )
 * @access public
 */
 function &_getPassedUsers($a_obj_id)
 {
     global $ilDB;
     $passed_users = array();
     // Maybe SELECT DISTINCT(tst_active.user_fi)... ?
     $userresult = $ilDB->queryF("\n\t\t\tSELECT tst_active.active_id, COUNT(tst_sequence.active_fi) sequences\n\t\t\tFROM tst_tests\n\t\t\tINNER JOIN tst_active\n\t\t\tON tst_active.test_fi = tst_tests.test_id\n\t\t\tLEFT JOIN tst_sequence\n\t\t\tON tst_sequence.active_fi = tst_active.active_id\n\t\t\tWHERE tst_tests.obj_fi = %s\n\t\t\tGROUP BY tst_active.active_id\n\t\t\t", array('integer'), array($a_obj_id));
     $all_participants = array();
     $notAttempted = array();
     while ($row = $ilDB->fetchAssoc($userresult)) {
         if ($row['sequences'] == 0) {
             $notAttempted[$row['active_id']] = $row['active_id'];
         }
         $all_participants[$row['active_id']] = $row['active_id'];
     }
     $result = $ilDB->query("SELECT tst_result_cache.*, tst_active.user_fi FROM tst_result_cache, tst_active WHERE tst_active.active_id = tst_result_cache.active_fi AND " . $ilDB->in('active_fi', $all_participants, false, 'integer'));
     $found_all = $result->numRows() == count($all_participants) ? true : false;
     if (!$found_all) {
         // if the result cache entries do not exist, create them
         $found_participants = array();
         while ($data = $ilDB->fetchAssoc($result)) {
             array_push($found_participants, $data['active_fi']);
         }
         foreach ($all_participants as $active_id) {
             if (!in_array($active_id, $found_participants)) {
                 include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
                 assQuestion::_updateTestResultCache($active_id);
             }
         }
         $result = $ilDB->query("SELECT tst_result_cache.*, tst_active.user_fi FROM tst_result_cache, tst_active WHERE tst_active.active_id = tst_result_cache.active_fi AND " . $ilDB->in('active_fi', $all_participants, false, 'integer'));
     }
     while ($data = $ilDB->fetchAssoc($result)) {
         if (isset($notAttempted[$data['active_fi']])) {
             $data['failed'] = 0;
             $data['passed'] = 0;
         }
         $data['user_id'] = $data['user_fi'];
         array_push($passed_users, $data);
     }
     return $passed_users;
 }
    public function performDeletePass()
    {
        if (!$this->object->isPassDeletionAllowed()) {
            $this->ctrl->redirect($this, 'outUserResultsOverview');
        }
        global $ilDB;
        $active_fi = $_GET['active_id'];
        $pass = $_GET['pass'];
        // Get information
        $result = $ilDB->query('SELECT tries 
				FROM tst_active
				WHERE active_id = ' . $ilDB->quote($active_fi, 'integer'));
        $row = $ilDB->fetchAssoc($result);
        $tries = $row['tries'];
        $last_pass = false;
        $must_renumber = true;
        // No renumbering - last pass to be deleted.
        if ($tries == 1) {
            $must_renumber = false;
            $last_pass = true;
        }
        // No renumbering - high pass to be deleted.
        if ($tries - 1 == $pass) {
            $must_renumber = false;
        }
        // Work on tables:
        // tst_active
        if ($last_pass) {
            $ilDB->manipulate('DELETE
					FROM tst_active
					WHERE active_id = ' . $ilDB->quote($active_fi, 'integer'));
        } else {
            $ilDB->manipulate('UPDATE tst_active
					SET tries = ' . $ilDB->quote($tries - 1, 'integer') . '
					WHERE active_id = ' . $ilDB->quote($active_fi, 'integer'));
        }
        // tst_manual_fb
        $ilDB->manipulate('DELETE
				FROM tst_manual_fb
				WHERE active_fi = ' . $ilDB->quote($active_fi, 'integer') . '
				AND pass = '******'integer'));
        if ($must_renumber) {
            $ilDB->manipulate('UPDATE tst_manual_fb
				SET pass = pass - 1
				WHERE active_fi = ' . $ilDB->quote($active_fi, 'integer'));
        }
        // tst_mark -> nothing to do
        //
        // tst_pass_result
        $ilDB->manipulate('DELETE
				FROM tst_pass_result
				WHERE active_fi = ' . $ilDB->quote($active_fi, 'integer') . '
				AND pass = '******'integer'));
        if ($must_renumber) {
            $ilDB->manipulate('UPDATE tst_pass_result
				SET pass = pass - 1
				WHERE active_fi = ' . $ilDB->quote($active_fi, 'integer'));
        }
        // tst_qst_solved -> nothing to do
        // tst_rnd_copy -> nothing to do
        // tst_rnd_qpl_title -> nothing to do
        // tst_sequence
        $ilDB->manipulate('DELETE
				FROM tst_sequence
				WHERE active_fi = ' . $ilDB->quote($active_fi, 'integer') . '
				AND pass = '******'integer'));
        if ($must_renumber) {
            $ilDB->manipulate('UPDATE tst_sequence
				SET pass = pass - 1
				WHERE active_fi = ' . $ilDB->quote($active_fi, 'integer'));
        }
        // tst_solutions
        $ilDB->manipulate('DELETE
				FROM tst_solutions
				WHERE active_fi = ' . $ilDB->quote($active_fi, 'integer') . '
				AND pass = '******'integer'));
        if ($must_renumber) {
            $ilDB->manipulate('UPDATE tst_solutions
				SET pass = pass - 1
				WHERE active_fi = ' . $ilDB->quote($active_fi, 'integer'));
        }
        // tst_tests -> nothing to do
        // tst_test_defaults -> nothing to do
        // tst_test_question -> nothing to do
        // tst_test_random -> nothing to do
        // tst_test_result
        $ilDB->manipulate('DELETE
				FROM tst_test_result
				WHERE active_fi = ' . $ilDB->quote($active_fi, 'integer') . '
				AND pass = '******'integer'));
        if ($must_renumber) {
            $ilDB->manipulate('UPDATE tst_test_result
				SET pass = pass - 1
				WHERE active_fi = ' . $ilDB->quote($active_fi, 'integer') . '
				AND pass > ' . $ilDB->quote($pass, 'integer'));
        }
        // tst_test_rnd_qst -> nothing to do
        // tst_times
        $ilDB->manipulate('DELETE
				FROM tst_times
				WHERE active_fi = ' . $ilDB->quote($active_fi, 'integer') . '
				AND pass = '******'integer'));
        if ($must_renumber) {
            $ilDB->manipulate('UPDATE tst_times
				SET pass = pass - 1
				WHERE active_fi = ' . $ilDB->quote($active_fi, 'integer'));
        }
        require_once 'Modules/Test/classes/class.ilObjAssessmentFolder.php';
        if (ilObjAssessmentFolder::_enabledAssessmentLogging()) {
            $this->object->logAction($this->lng->txtlng("assessment", "log_deleted_pass", ilObjAssessmentFolder::_getLogLanguage()));
        }
        // tst_result_cache
        // Ggfls. nur renumbern.
        require_once './Modules/TestQuestionPool/classes/class.assQuestion.php';
        assQuestion::_updateTestResultCache($active_fi);
        $this->ctrl->redirectByClass('iltestoutputgui', 'outuserresultsoverview');
    }
    function _updateTestPassResults($active_id, $pass, $obligationsEnabled = false)
    {
        global $ilDB;
        include_once "./Modules/Test/classes/class.ilObjTest.php";
        $data = ilObjTest::_getQuestionCountAndPointsForPassOfParticipant($active_id, $pass);
        $time = ilObjTest::_getWorkingTimeOfParticipantForPass($active_id, $pass);
        // update test pass results
        $result = $ilDB->queryF("\n\t\t\tSELECT\t\tSUM(points) reachedpoints,\n\t\t\t\t\t\tSUM(hint_count) hint_count,\n\t\t\t\t\t\tSUM(hint_points) hint_points,\n\t\t\t\t\t\tCOUNT(question_fi) answeredquestions\n\t\t\tFROM\t\ttst_test_result\n\t\t\tWHERE\t\tactive_fi = %s\n\t\t\tAND\t\t\tpass = %s\n\t\t\t", array('integer', 'integer'), array($active_id, $pass));
        if ($result->numRows() > 0) {
            if ($obligationsEnabled) {
                $query = '
					SELECT		count(*) cnt,
								min( answered ) answ
					FROM		tst_test_question
					INNER JOIN	tst_active
					ON			active_id = %s
					AND			tst_test_question.test_fi = tst_active.test_fi
					LEFT JOIN	tst_test_result
					ON			tst_test_result.active_fi = %s
					AND			tst_test_result.pass = %s
					AND			tst_test_question.question_fi = tst_test_result.question_fi
					WHERE		obligatory = 1';
                $result_obligatory = $ilDB->queryF($query, array('integer', 'integer', 'integer'), array($active_id, $active_id, $pass));
                $row_obligatory = $ilDB->fetchAssoc($result_obligatory);
                if ($row_obligatory['cnt'] == 0) {
                    $obligations_answered = 1;
                } else {
                    $obligations_answered = (int) $row_obligatory['answ'];
                }
            } else {
                $obligations_answered = 1;
            }
            $row = $ilDB->fetchAssoc($result);
            if ($row['hint_count'] === null) {
                $row['hint_count'] = 0;
            }
            if ($row['hint_points'] === null) {
                $row['hint_points'] = 0;
            }
            $query = "\n\t\t\t\tDELETE FROM\t\ttst_pass_result\n\n\t\t\t\tWHERE\t\t\tactive_fi = %s\n\t\t\t\tAND\t\t\t\tpass = %s\n\t\t\t";
            $affectedRows = $ilDB->manipulateF($query, array('integer', 'integer'), array($active_id, $pass));
            $ilDB->insert('tst_pass_result', array('active_fi' => array('integer', $active_id), 'pass' => array('integer', strlen($pass) ? $pass : 0), 'points' => array('float', $row['reachedpoints'] ? $row['reachedpoints'] : 0), 'maxpoints' => array('float', $data['points']), 'questioncount' => array('integer', $data['count']), 'answeredquestions' => array('integer', $row['answeredquestions']), 'workingtime' => array('integer', $time), 'tstamp' => array('integer', time()), 'hint_count' => array('integer', $row['hint_count']), 'hint_points' => array('float', $row['hint_points']), 'obligations_answered' => array('integer', $obligations_answered)));
        }
        assQuestion::_updateTestResultCache($active_id);
        return array('active_fi' => $active_id, 'pass' => $pass, 'points' => $row["reachedpoints"] ? $row["reachedpoints"] : 0, 'maxpoints' => $data["points"], 'questioncount' => $data["count"], 'answeredquestions' => $row["answeredquestions"], 'workingtime' => $time, 'tstamp' => time(), 'hint_count' => $row['hint_count'], 'hint_points' => $row['hint_points'], 'obligations_answered' => $obligations_answered);
    }