19 declare(strict_types=1);
    32     private \ilDBInterface 
$db;
    39         return 'Update test attempt results on manual scoring after 1st of May 2024. We do this in one step to avoid creating tables and this might take a while.';
    50             new \ilDatabaseInitializedObjective(),
    51             new \ilSettingsFactoryExistsObjective()
    60             ->settingsFor(
'assessment');
    61         $this->manual_scoring_enabled = $this->
settings->get(
'assessment_manual_scoring', 
'') !== 
'';
    62         $this->migration_already_run = $this->
settings->get(self::MIGRATION_ALLREADY_RUN_SETTING, 
'0') === 
'1';
    70         if (!$this->manual_scoring_enabled) {
    74         $result = $this->db->query(
    75             'SELECT DISTINCT(active_fi), pass, question_set_type, (SELECT MAX(tstamp) FROM '    76             . self::TABLE_NAME . 
' ms2 WHERE ms1.active_fi = ms2.active_fi) tstamp FROM '    77             . self::TABLE_NAME . 
' ms1 '    78             . 
'INNER JOIN tst_active ta ON ms1.active_fi = ta.active_id '    79             . 
'INNER JOIN tst_tests tt ON ta.test_fi = tt.test_id '    83         while (($row = $this->db->fetchObject($result))) {
    84             if ($row->tstamp <= self::START_DATE) {
    91         $this->
settings->set(self::MIGRATION_ALLREADY_RUN_SETTING, 
'1');
    96         if (!$this->manual_scoring_enabled || $this->migration_already_run) {
   107         $result = $this->db->queryF(
   108             'SELECT             SUM(points) reachedpoints,   109                                                 SUM(hint_count) hint_count,   110                                                 SUM(hint_points) hint_points,   111                                                 COUNT(DISTINCT(question_fi)) answeredquestions   115             [
'integer',
'integer'],
   119         $row = $this->db->fetchAssoc($result);
   121         if ($row[
'reachedpoints'] === null
   122             || $row[
'reachedpoints'] < 0.0) {
   123             $row[
'reachedpoints'] = 0.0;
   125         if ($row[
'hint_count'] === null) {
   126             $row[
'hint_count'] = 0;
   128         if ($row[
'hint_points'] === null) {
   129             $row[
'hint_points'] = 0.0;
   137                 'active_fi' => [
'integer', $active_id],
   138                 'pass' => [
'integer', $pass]
   141                 'points' => [
'float', $row[
'reachedpoints']],
   142                 'maxpoints' => [
'float', 
$data[
'points']],
   143                 'questioncount' => [
'integer', 
$data[
'count']],
   144                 'answeredquestions' => [
'integer', $row[
'answeredquestions']],
   145                 'tstamp' => [
'integer', time()],
   146                 'hint_count' => [
'integer', $row[
'hint_count']],
   147                 'hint_points' => [
'float', $row[
'hint_points']]
   157             SELECT              tst_pass_result.*,   158                         tst_active.last_finished_pass,   161             INNER JOIN  tst_active   162             on          tst_pass_result.active_fi = tst_active.active_id   167         $result = $this->db->queryF(
   169             [
'integer',
'integer'],
   173         $test_pass_result_row = $this->db->fetchAssoc($result);
   175         if (!is_array($test_pass_result_row)) {
   176             $test_pass_result_row = [];
   178         $max = (float) ($test_pass_result_row[
'maxpoints'] ?? 0);
   179         $reached = (float) ($test_pass_result_row[
'points'] ?? 0);
   180         $percentage = ($max <= 0.0 || $reached <= 0.0) ? 0 : ($reached / $max) * 100.0;
   181         $obligations_answered = (
int) ($test_pass_result_row[
'obligations_answered'] ?? 1);
   183         $mark_schema = new \ASS_MarkSchema($this->db, 
new class (
'en') extends \
ilLanguage {
   188         $mark_schema->loadFromDb($test_pass_result_row[
'test_fi']);
   189         $mark = $mark_schema->getMatchingMark($percentage);
   190         $is_passed = $pass <= $test_pass_result_row[
'last_finished_pass'] && $mark->getPassed();
   192         $hint_count = $test_pass_result_row[
'hint_count'] ?? 0;
   193         $hint_points = $test_pass_result_row[
'hint_points'] ?? 0.0;
   195         $passed_once_before = 0;
   196         $query = 
'SELECT passed_once FROM tst_result_cache WHERE active_fi = %s';
   197         $res = $this->db->queryF($query, [
'integer'], [$active_id]);
   198         while ($passed_once_result_row = $this->db->fetchAssoc(
$res)) {
   199             $passed_once_before = (
int) $passed_once_result_row[
'passed_once'];
   202         $passed_once = (
int) ($is_passed || $passed_once_before);
   204         $this->db->manipulateF(
   205             'DELETE FROM tst_result_cache WHERE active_fi = %s',
   210         if ($reached < 0.0) {
   214         $mark_short_name = $mark->getShortName();
   215         if ($mark_short_name === 
'') {
   216             $mark_short_name = 
' ';
   219         $mark_official_name = $mark->getOfficialName();
   220         if ($mark_official_name === 
'') {
   221             $mark_official_name = 
' ';
   227                 'active_fi' => [
'integer', $active_id],
   228                 'pass' => [
'integer', $pass ?? 0],
   229                 'max_points' => [
'float', $max],
   230                 'reached_points' => [
'float', $reached],
   231                 'mark_short' => [
'text', $mark_short_name],
   232                 'mark_official' => [
'text', $mark_official_name],
   233                 'passed_once' => [
'integer', $passed_once],
   234                 'passed' => [
'integer', (
int) $is_passed],
   235                 'failed' => [
'integer', (
int) !$is_passed],
   236                 'tstamp' => [
'integer', time()],
   237                 'hint_count' => [
'integer', $hint_count],
   238                 'hint_points' => [
'float', $hint_points],
   239                 'obligations_answered' => [
'integer', $obligations_answered]
   246         $res = $this->db->queryF(
   248                 SELECT          tst_test_rnd_qst.pass,   249                             COUNT(tst_test_rnd_qst.question_fi) qcount,   250                             SUM(qpl_questions.points) qsum   252                 FROM            tst_test_rnd_qst,   255                 WHERE           tst_test_rnd_qst.question_fi = qpl_questions.question_id   256                 AND                     tst_test_rnd_qst.active_fi = %s   259                 GROUP BY        tst_test_rnd_qst.active_fi,   260                             tst_test_rnd_qst.pass   262             [
'integer', 
'integer'],
   266         $row = $this->db->fetchAssoc(
$res);
   268         if (is_array($row)) {
   269             return [
"count" => $row[
"qcount"], 
"points" => $row[
"qsum"]];
   272         return [
"count" => 0, 
"points" => 0];
 
const QUESTION_SET_TYPE_RANDOM
 
const MIGRATION_ALLREADY_RUN_SETTING
 
bool $manual_scoring_enabled
 
A migration is a potentially long lasting operation that can be broken into discrete steps...
 
step(Environment $environment)
 
prepare(Environment $environment)
Prepare the migration by means of some environment. 
 
getPreconditions(Environment $environment)
Objectives the migration depend on. 
 
bool $migration_already_run
 
__construct()
Constructor setup ILIAS global object  public. 
 
getResource(string $id)
Consumers of this method should check if the result is what they expect, e.g. 
 
updateTestPassResults(int $active_id, int $pass)
 
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
 
getDefaultAmountOfStepsPerRun()
Tell the default amount of steps to be executed for one run of the migration. 
 
An environment holds resources to be used in the setup process. 
 
getQuestionCountAndPointsForPassOfParticipant($active_id, $pass)
 
const RESOURCE_SETTINGS_FACTORY
 
getRemainingAmountOfSteps()
Count up how many "things" need to be migrated. 
 
updateTestResultCache(int $active_id, int $pass)