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