1<?php
2/* Copyright (c) 1998-2013 ILIAS open source, Extended GPL, see docs/LICENSE */
3
4/**
5 * Service class for tests.
6 *
7 * @author	Björn Heyser <bheyser@databay.de>
8 * @version	$Id$
9 *
10 * @ingroup ModulesTest
11 */
12class ilTestService
13{
14    /**
15     * @access protected
16     * @var ilObjTest
17     */
18    protected $object = null;
19
20    /**
21     * @access public
22     * @param	ilObjTest $a_object
23     */
24    public function __construct(ilObjTest $a_object)
25    {
26        $this->object = $a_object;
27    }
28
29    /**
30     * @access public
31     * @global	ilObjUser	$ilUser
32     * @param	integer		$active_id
33     * @param	boolean		$short
34     * @return	array		$passOverwiewData
35     */
36    public function getPassOverviewData($active_id, $short = false)
37    {
38        $passOverwiewData = array();
39
40        global $DIC;
41        $ilUser = $DIC['ilUser'];
42
43        $scoredPass = $this->object->_getResultPass($active_id);
44        $lastPass = ilObjTest::_getPass($active_id);
45
46        $testPercentage = 0;
47        $testReachedPoints = 0;
48        $testMaxPoints = 0;
49
50        for ($pass = 0; $pass <= $lastPass; $pass++) {
51            $passFinishDate = ilObjTest::lookupPassResultsUpdateTimestamp($active_id, $pass);
52
53            if ($passFinishDate <= 0) {
54                continue;
55            }
56
57            if (!$short) {
58                $resultData = &$this->object->getTestResult($active_id, $pass);
59
60                if (!$resultData["pass"]["total_max_points"]) {
61                    $passPercentage = 0;
62                } else {
63                    $passPercentage = ($resultData["pass"]["total_reached_points"] / $resultData["pass"]["total_max_points"]) * 100;
64                }
65
66                $passMaxPoints = $resultData["pass"]["total_max_points"];
67                $passReachedPoints = $resultData["pass"]["total_reached_points"];
68
69                $passAnsweredQuestions = $this->object->getAnsweredQuestionCount($active_id, $pass);
70                $passTotalQuestions = count($resultData) - 2;
71
72                if ($pass == $scoredPass) {
73                    $isScoredPass = true;
74
75                    if (!$resultData["test"]["total_max_points"]) {
76                        $testPercentage = 0;
77                    } else {
78                        $testPercentage = ($resultData["test"]["total_reached_points"] / $resultData["test"]["total_max_points"]) * 100;
79                    }
80
81                    $testMaxPoints = $resultData["test"]["total_max_points"];
82                    $testReachedPoints = $resultData["test"]["total_reached_points"];
83
84                    $passOverwiewData['test'] = array(
85                        'active_id' => $active_id,
86                        'scored_pass' => $scoredPass,
87                        'max_points' => $testMaxPoints,
88                        'reached_points' => $testReachedPoints,
89                        'percentage' => $testPercentage
90                    );
91                } else {
92                    $isScoredPass = false;
93                }
94
95                $passOverwiewData['passes'][] = array(
96                    'active_id' => $active_id,
97                    'pass' => $pass,
98                    'finishdate' => $passFinishDate,
99                    'max_points' => $passMaxPoints,
100                    'reached_points' => $passReachedPoints,
101                    'percentage' => $passPercentage,
102                    'answered_questions' => $passAnsweredQuestions,
103                    'total_questions' => $passTotalQuestions,
104                    'is_scored_pass' => $isScoredPass
105                );
106            }
107        }
108
109        return $passOverwiewData;
110    }
111
112    /**
113     * Returns the list of answers of a users test pass and offers a scoring option
114     *
115     * @access public
116     * @param integer $active_id Active ID of the active user
117     * @param integer $pass Test pass
118     * @return string HTML code of the list of answers
119     */
120    public function getManScoringQuestionGuiList($activeId, $pass)
121    {
122        include_once "./Modules/Test/classes/class.ilObjAssessmentFolder.php";
123        $manScoringQuestionTypes = ilObjAssessmentFolder::_getManualScoring();
124
125        $testResultData = $this->object->getTestResult($activeId, $pass);
126
127        $manScoringQuestionGuiList = array();
128
129        foreach ($testResultData as $questionData) {
130            if (!isset($questionData['qid'])) {
131                continue;
132            }
133
134            if (!isset($questionData['type'])) {
135                throw new ilTestException('no question type given!');
136            }
137
138            $questionGUI = $this->object->createQuestionGUI("", $questionData['qid']);
139
140            if (!in_array($questionGUI->object->getQuestionTypeID(), $manScoringQuestionTypes)) {
141                continue;
142            }
143
144            $manScoringQuestionGuiList[ $questionData['qid'] ] = $questionGUI;
145        }
146
147        return $manScoringQuestionGuiList;
148    }
149
150    /**
151     * reads the flag wether manscoring is done for the given test active or not
152     * from the global settings (scope: assessment / key: manscoring_done_<activeId>)
153     *
154     * @access public
155     * @static
156     * @param integer $activeId
157     * @return boolean $manScoringDone
158     */
159    public static function isManScoringDone($activeId)
160    {
161        $assessmentSetting = new ilSetting("assessment");
162        return $assessmentSetting->get("manscoring_done_" . $activeId, false);
163    }
164
165    /**
166     * stores the flag wether manscoring is done for the given test active or not
167     * within the global settings (scope: assessment / key: manscoring_done_<activeId>)
168     *
169     * @access public
170     * @static
171     * @param integer $activeId
172     * @param boolean $manScoringDone
173     */
174    public static function setManScoringDone($activeId, $manScoringDone)
175    {
176        $assessmentSetting = new ilSetting("assessment");
177        $assessmentSetting->set("manscoring_done_" . $activeId, (bool) $manScoringDone);
178    }
179
180    public function buildVirtualSequence(ilTestSession $testSession)
181    {
182        global $DIC;
183        $ilDB = $DIC['ilDB'];
184        $lng = $DIC['lng'];
185        $ilPluginAdmin = $DIC['ilPluginAdmin'];
186
187        require_once 'Modules/Test/classes/class.ilTestVirtualSequence.php';
188        $testSequenceFactory = new ilTestSequenceFactory($ilDB, $lng, $ilPluginAdmin, $this->object);
189
190        if ($this->object->isRandomTest()) {
191            require_once 'Modules/Test/classes/class.ilTestVirtualSequenceRandomQuestionSet.php';
192            $virtualSequence = new ilTestVirtualSequenceRandomQuestionSet($ilDB, $this->object, $testSequenceFactory);
193        } else {
194            require_once 'Modules/Test/classes/class.ilTestVirtualSequence.php';
195            $virtualSequence = new ilTestVirtualSequence($ilDB, $this->object, $testSequenceFactory);
196        }
197
198        $virtualSequence->setActiveId($testSession->getActiveId());
199
200        $virtualSequence->init();
201
202        return $virtualSequence;
203    }
204
205    public function getVirtualSequenceUserResults(ilTestVirtualSequence $virtualSequence)
206    {
207        $resultsByPass = array();
208
209        foreach ($virtualSequence->getUniquePasses() as $pass) {
210            $results = $this->object->getTestResult(
211                $virtualSequence->getActiveId(),
212                $pass,
213                false,
214                true,
215                true
216            );
217
218            $resultsByPass[$pass] = $results;
219        }
220
221        $virtualPassResults = array();
222
223        foreach ($virtualSequence->getQuestionsPassMap() as $questionId => $pass) {
224            foreach ($resultsByPass[$pass] as $key => $questionResult) {
225                if ($key === 'test' || $key === 'pass') {
226                    continue;
227                }
228
229                if ($questionResult['qid'] == $questionId) {
230                    $questionResult['pass'] = $pass;
231                    $virtualPassResults[$questionId] = $questionResult;
232                    break;
233                }
234            }
235        }
236
237        return $virtualPassResults;
238    }
239
240    /**
241     * @param ilTestSequenceSummaryProvider $testSequence
242     * @param bool $obligationsFilter
243     * @return array
244     */
245    public function getQuestionSummaryData(ilTestSequenceSummaryProvider $testSequence, $obligationsFilterEnabled)
246    {
247        $result_array = $testSequence->getSequenceSummary($obligationsFilterEnabled);
248
249        $marked_questions = array();
250
251        if ($this->object->getShowMarker()) {
252            include_once "./Modules/Test/classes/class.ilObjTest.php";
253            $marked_questions = ilObjTest::_getSolvedQuestions($testSequence->getActiveId());
254        }
255
256        $data = array();
257        $firstQuestion = true;
258
259        foreach ($result_array as $key => $value) {
260            $disableLink = (
261                $this->object->isFollowupQuestionAnswerFixationEnabled()
262                && !$value['presented'] && !$firstQuestion
263            );
264
265            $description = "";
266            if ($this->object->getListOfQuestionsDescription()) {
267                $description = $value["description"];
268            }
269
270            $points = "";
271            if (!$this->object->getTitleOutput()) {
272                $points = $value["points"];
273            }
274
275            $marked = false;
276            if (count($marked_questions)) {
277                if (array_key_exists($value["qid"], $marked_questions)) {
278                    $obj = $marked_questions[$value["qid"]];
279                    if ($obj["solved"] == 1) {
280                        $marked = true;
281                    }
282                }
283            }
284
285            // fau: testNav - add number parameter for getQuestionTitle()
286            $data[] = array(
287                'order' => $value["nr"],
288                'title' => $this->object->getQuestionTitle($value["title"], $value["nr"]),
289                'description' => $description,
290                'disabled' => $disableLink,
291                'worked_through' => $value["worked_through"],
292                'postponed' => $value["postponed"],
293                'points' => $points,
294                'marked' => $marked,
295                'sequence' => $value["sequence"],
296                'obligatory' => $value['obligatory'],
297                'isAnswered' => $value['isAnswered']
298            );
299
300            $firstQuestion = false;
301            // fau.
302        }
303
304        return $data;
305    }
306}
307