ILIAS  trunk Revision v12.0_alpha-16-g3e876e53c80
ConsecutiveScoring.php
Go to the documentation of this file.
1<?php
2
19declare(strict_types=1);
20
22
28
30{
31 public function __construct(
32 private readonly Positions $positions,
33 private readonly \ilObjTest $object,
34 private readonly \ilTestShuffler $shuffler,
35 private readonly TestLogger $logger,
36 private TestScoring $scorer,
37 private TestManScoringDoneHelper $scoring_done_helper,
38 private \ilObjUser $current_user,
39 private readonly \ilTestAccess $test_access,
40 ) {
41 }
42
43 public function getPositions(): Positions
44 {
45 return $this->positions;
46 }
47
48 public function getAttemptUsedForEvaluation(int $usr_active_id): int
49 {
50 return $this->positions->getAllAttempts()[$usr_active_id];
51 }
52
53 private function getQuestionGUI(int $qid): \assQuestionGUI
54 {
55 return $this->object->createQuestionGUI("", $qid);
56 }
57
58 public function getQuestionObject(int $qid): \assQuestion
59 {
60 return $this->getQuestionGUI($qid)->getObject();
61 }
62
63 public function getParticipantNames(): array
64 {
65 $participants = [];
66 foreach ($this->positions->getAllAttempts() as $usr_active_id => $attempt) {
67 $participants[$usr_active_id] = $this->getUserFullName(
68 $usr_active_id,
69 (string) $attempt
70 );
71 };
72 return $participants;
73 }
74
75 public function getQuestionTitles(\ilLanguage $lng): array
76 {
77 $question_titles = [];
78 foreach ($this->positions->getAllQuestionProperties() as $qid => $qprop) {
79 $question_titles[$qid] = sprintf(
80 '%s (%s)',
81 $qprop->getTitle(),
82 $qprop->getTypeName($lng)
83 );
84 }
85 return $question_titles;
86 }
87
88 public function getUserFullName(
89 int $usr_active_id,
90 string $attempt
91 ): string {
92 if ($this->object->getAnonymity()
93 || !$this->test_access->checkScoreParticipantsAccess()
94 ) {
95 return \ilObjTest::buildExamId($usr_active_id, $attempt, $this->object->getId());
96 }
97 $user_id = (string) $this->object->_getUserIdFromActiveId($usr_active_id);
98 $user_data = $this->object->getUserData([$user_id]);
99 $user = $user_data[$user_id];
100 return sprintf(
101 "%s %s [%s]",
102 $user["firstname"],
103 $user["lastname"],
104 $user["login"]
105 );
106 }
107
108 public function getUserId(
109 int $usr_active_id,
110 string $attempt,
111 ): string {
112 if ($this->object->getAnonymity()
113 || !$this->test_access->checkScoreParticipantsAccess()
114 ) {
115 return \ilObjTest::buildExamId($usr_active_id, $attempt, $this->object->getId());
116 }
117 return (string) $this->object->_getUserIdFromActiveId($usr_active_id);
118 }
119
120 public function getSingleManualFeedback(int $qid, int $usr_active_id, int $attempt_id): array
121 {
122 $fb = \ilObjTest::getSingleManualFeedback($usr_active_id, $qid, $attempt_id);
123 if (array_key_exists("finalized_tstamp", $fb)) {
124 $fb["finalized_time"] = $this->current_user->getDateTimeFormat()->applyTo(
125 \DateTimeImmutable::createFromFormat('U', (string) $fb["finalized_tstamp"])
126 );
127 }
128 return $fb;
129 }
130
131 public function getUserQuestionGUI(int $qid, int $usr_active_id, int $attempt_id): \assQuestionGUI
132 {
133 $question_gui = $this->getQuestionGUI($qid);
134 $shuffle_trafo = $this->shuffler->getAnswerShuffleFor($qid, $usr_active_id, $attempt_id);
135 $question = $question_gui->getObject();
136 $question->setShuffler($shuffle_trafo);
137 $question_gui->setObject($question);
138 return $question_gui;
139 }
140
144 public function getAnsweredQuestionIds(): array
145 {
146 $answered = [];
147 foreach ($this->positions->getAllAttempts() as $usr_active_id => $attempt_id) {
148 $answered[$usr_active_id] = [];
149
150 $user_results = $this->object->getTestResult(
151 $usr_active_id,
152 $attempt_id,
153 false,
154 true,
155 true
156 );
157
158 foreach ($user_results as $idx => $qresult) {
159 if (!is_numeric($idx)) {
160 continue;
161 }
162 if ((bool) $qresult['answered']) {
163 $answered[$usr_active_id][] = (int) $qresult['qid'];
164 }
165 }
166 }
167 return $answered;
168 }
169
173 public function getFinalizedFeedbackIds(): array
174 {
175 $finalized = [];
176 $usr_active_ids = array_keys($this->positions->getAllAttempts());
177 foreach (array_keys($this->positions->getAllQuestionProperties()) as $qid) {
178 $feedback = $this->object->getCompleteManualFeedback($qid);
179 foreach ($usr_active_ids as $uid) {
180 if (! array_key_exists($uid, $finalized)) {
181 $finalized[$uid] = [];
182 }
183 $attempt_id = $this->getAttemptUsedForEvaluation($uid);
184 if ((bool) ($feedback[$uid][$attempt_id][$qid]['finalized_evaluation'] ?? false)) {
185 $finalized[$uid][] = $qid;
186 }
187 }
188 }
189 return $finalized;
190 }
191
195 public function getQidsFinalizedBy(array $finalizing_usr_ids): array
196 {
197 $finalized = [];
198 $usr_active_ids = array_keys($this->positions->getAllAttempts());
199 foreach (array_keys($this->positions->getAllQuestionProperties()) as $qid) {
200 $feedback = $this->object->getCompleteManualFeedback($qid);
201 foreach ($usr_active_ids as $uid) {
202 $attempt_id = $this->getAttemptUsedForEvaluation($uid);
203 $scorer = $feedback[$uid][$attempt_id][$qid]['finalized_by_usr_id'] ?? 0;
204
205 if (in_array($scorer, $finalizing_usr_ids)) {
206 $finalized[] = $qid;
207 }
208 }
209 }
210 return array_unique($finalized);
211 }
212
216 public function getAllFinalizingUserNames(): array
217 {
218 $finalized_by = [];
219 $attempts = $this->positions->getAllAttempts();
220 $question_ids = array_keys($this->positions->getAllQuestionProperties());
221
222 foreach ($question_ids as $qid) {
223 $feedback = $this->object->getCompleteManualFeedback($qid);
224
225 foreach ($attempts as $uid => $attempt_id) {
226 if ($feedback[$uid][$attempt_id][$qid]['finalized_by_usr_id'] ?? false) {
227 $scorer_id = $feedback[$uid][$attempt_id][$qid]['finalized_by_usr_id'];
228 $finalized_by[$scorer_id] = $scorer_id;
229 }
230 }
231 }
232 return array_map(
233 function ($scorer_id) {
234 $ud = current(\ilObjUser::_getUserData([$scorer_id]));
235 return $ud['firstname'] . ' ' . $ud['lastname'];
236 },
237 $finalized_by
238 );
239 }
240
241 public function store(
242 int $qid,
243 int $usr_active_id,
244 int $attempt_id,
245 float $score,
246 bool $final,
247 string $feedback,
248 float $max_points
249 ) {
250 $feedback = \ilUtil::stripSlashes(
251 $feedback,
252 false,
254 );
255
256 // fix #35543: save manual points only if they differ from the existing points
257 // this prevents a question being set to "answered" if only feedback is entered
258 $previously_reached_points = $this->getQuestionObject($qid)
259 ->getReachedPoints($usr_active_id, $attempt_id);
260 if ($score !== $previously_reached_points) {
261 \assQuestion::_setReachedPoints(
262 $usr_active_id,
263 $qid,
264 $score,
265 $max_points,
266 $attempt_id,
267 true
268 );
269 }
270
271 $this->object->saveManualFeedback(
272 $usr_active_id,
273 $qid,
274 $attempt_id,
275 $feedback,
276 $final
277 );
278
279 $this->scorer->setPreserveManualScores(true);
280 $this->scorer->recalculateSolution($usr_active_id, $attempt_id);
281
283 $this->object->getId(),
285 );
286
287 if ($this->logger->isLoggingEnabled()) {
288 $this->logger->logScoringInteraction(
289 $this->logger->getInteractionFactory()->buildScoringInteraction(
290 $this->object->getRefId(),
291 $qid,
292 $this->current_user->getId(),
293 \ilObjTestAccess::_getParticipantId($usr_active_id),
294 TestScoringInteractionTypes::QUESTION_GRADED,
295 [
296 AdditionalInformationGenerator::KEY_REACHED_POINTS => $score,
297 AdditionalInformationGenerator::KEY_FEEDBACK => $feedback,
298 AdditionalInformationGenerator::KEY_EVAL_FINALIZED => $this->logger
299 ->getAdditionalInformationGenerator()->getTrueFalseTagForBool($final)
300 ]
301 )
302 );
303 }
304 }
305
306 public function completeScoring(
307 int $usr_active_id,
308 bool $flag = true
309 ) {
310 $this->scoring_done_helper->setDone($usr_active_id, $flag);
311 }
312
313 public function isScoringComplete(int $usr_active_id): bool
314 {
315 return $this->scoring_done_helper->isDone($usr_active_id);
316 }
317
318}
getSingleManualFeedback(int $qid, int $usr_active_id, int $attempt_id)
getUserId(int $usr_active_id, string $attempt,)
completeScoring(int $usr_active_id, bool $flag=true)
getUserQuestionGUI(int $qid, int $usr_active_id, int $attempt_id)
__construct(private readonly Positions $positions, private readonly \ilObjTest $object, private readonly \ilTestShuffler $shuffler, private readonly TestLogger $logger, private TestScoring $scorer, private TestManScoringDoneHelper $scoring_done_helper, private \ilObjUser $current_user, private readonly \ilTestAccess $test_access,)
store(int $qid, int $usr_active_id, int $attempt_id, float $score, bool $final, string $feedback, float $max_points)
getUserFullName(int $usr_active_id, string $attempt)
static _updateStatus(int $a_obj_id, int $a_usr_id, ?object $a_obj=null, bool $a_percentage=false, bool $a_force_raise=false)
language handling
static _getParticipantId(int $active_id)
Get user id for active id.
static getSingleManualFeedback(int $active_id, int $question_id, int $pass)
User class.
static _getUserData(array $a_internalids)
static _getUsedHTMLTagsAsString(string $module='')
static stripSlashes(string $a_str, bool $a_strip_html=true, string $a_allow="")
global $lng
Definition: privfeed.php:31
if(!file_exists('../ilias.ini.php'))