ILIAS  release_8 Revision v8.24
class.ilTestSkillEvaluation.php
Go to the documentation of this file.
1<?php
2
20
30{
34 private $db;
35
39 private $refId;
40
45
50
54 private $questions;
55
60
65
70
75
79 private $userId;
80
84 private $activeId;
85
89 private $pass;
90
95
97
99 {
100 global $DIC;
101
102 $this->db = $db;
103 $this->refId = $refId;
104
105 $this->skillQuestionAssignmentList = new ilAssQuestionSkillAssignmentList($this->db);
106
107 $this->skillLevelThresholdList = new ilTestSkillLevelThresholdList($this->db);
108 $this->skillLevelThresholdList->setTestId($testId);
109
110 $this->skill_profile_service = ($skill_profile_service == null)
111 ? $DIC->skills()->profile()
113
114 $this->questions = array();
115 $this->maxPointsByQuestion = array();
116 }
117
118 public function getUserId(): int
119 {
120 return $this->userId;
121 }
122
123 public function setUserId($userId)
124 {
125 $this->userId = $userId;
126 }
127
128 public function getActiveId(): int
129 {
130 return $this->activeId;
131 }
132
133 public function setActiveId($activeId)
134 {
135 $this->activeId = $activeId;
136 }
137
138 public function getPass(): int
139 {
140 return $this->pass;
141 }
142
143 public function setPass($pass)
144 {
145 $this->pass = $pass;
146 }
147
149 {
151 }
152
154 {
155 $this->numRequiredBookingsForSkillTriggering = $numRequiredBookingsForSkillTriggering;
156 }
157
158 public function init(ilAssQuestionList $questionList)
159 {
160 $this->skillQuestionAssignmentList->setParentObjId($questionList->getParentObjId());
161 $this->skillQuestionAssignmentList->loadFromDb();
162
163 $this->skillLevelThresholdList->loadFromDb();
164
165 $this->initTestQuestionData($questionList);
166 }
167
171 public function evaluate($testResults)
172 {
173 $this->reset();
174
175 $this->initTestResultData($testResults);
176
179 }
180
181 public function getReachedSkillLevels(): array
182 {
184 }
185
186 private function reset()
187 {
188 $this->reachedPointsByQuestion = array();
189 $this->skillPointAccounts = array();
190 $this->reachedSkillLevels = array();
191 }
192
193 private function initTestQuestionData(ilAssQuestionList $questionList)
194 {
195 foreach ($questionList->getQuestionDataArray() as $questionData) {
196 $this->questions[] = $questionData['question_id'];
197
198 $this->maxPointsByQuestion[ $questionData['question_id'] ] = $questionData['points'];
199 }
200 }
201
205 private function initTestResultData($testResults)
206 {
207 foreach ($testResults as $key => $result) {
208 if ($key === 'pass' || $key === 'test') { // note: key int 0 IS == 'pass' or 'buxtehude'
209 continue;
210 }
211
212 if (!$result['workedthrough']) {
213 continue;
214 }
215
216 $this->reachedPointsByQuestion[ $result['qid'] ] = $result['reached'];
217 }
218 }
219
220 private function drawUpSkillPointAccounts()
221 {
222 foreach ($this->questions as $questionId) {
223 if (!$this->isAnsweredQuestion($questionId)) {
224 continue;
225 }
226
227 $assignments = $this->skillQuestionAssignmentList->getAssignmentsByQuestionId($questionId);
228
229 foreach ($assignments as $assignment) {
230 if ($assignment->hasEvalModeBySolution()) {
231 $reachedSkillPoints = $this->determineReachedSkillPointsWithSolutionCompare(
232 $assignment->getSolutionComparisonExpressionList()
233 );
234 } else {
235 $maxTestPoints = $this->maxPointsByQuestion[$questionId];
236 $reachedTestPoints = $this->reachedPointsByQuestion[$questionId];
237
238 $reachedSkillPoints = $this->calculateReachedSkillPointsFromTestPoints(
239 $assignment->getSkillPoints(),
240 $maxTestPoints,
241 $reachedTestPoints
242 );
243 }
244
246 $assignment->getSkillBaseId(),
247 $assignment->getSkillTrefId(),
248 $assignment->getMaxSkillPoints(),
249 $reachedSkillPoints
250 );
251 }
252 }
253 }
254
255 private function isAnsweredQuestion($questionId): bool
256 {
257 return isset($this->reachedPointsByQuestion[$questionId]);
258 }
259
261 {
262 $questionProvider = new ilAssLacQuestionProvider();
263 $questionProvider->setQuestionId($expressionList->getQuestionId());
264
265 foreach ($expressionList->get() as $expression) {
266 /* @var ilAssQuestionSolutionComparisonExpression $expression */
267
268 $conditionParser = new ilAssLacConditionParser();
269 $conditionComposite = $conditionParser->parse($expression->getExpression());
270
271 $compositeEvaluator = new ilAssLacCompositeEvaluator(
272 $questionProvider,
273 $this->getActiveId(),
274 $this->getPass()
275 );
276 if ($compositeEvaluator->evaluate($conditionComposite)) {
277 return $expression->getPoints();
278 }
279 }
280
281 return 0;
282 }
283
284 private function calculateReachedSkillPointsFromTestPoints($skillPoints, $maxTestPoints, $reachedTestPoints)
285 {
286 if ($reachedTestPoints < 0) {
287 $reachedTestPoints = 0;
288 }
289
290 $factor = 0;
291
292 if ($maxTestPoints > 0) {
293 $factor = $reachedTestPoints / $maxTestPoints;
294 }
295
296 return ($skillPoints * $factor);
297 }
298
299 private function bookToSkillPointAccount($skillBaseId, $skillTrefId, $maxSkillPoints, $reachedSkillPoints)
300 {
301 $skillKey = $skillBaseId . ':' . $skillTrefId;
302
303 if (!isset($this->skillPointAccounts[$skillKey])) {
304 $this->skillPointAccounts[$skillKey] = new ilTestSkillPointAccount();
305 }
306
307 $this->skillPointAccounts[$skillKey]->addBooking($maxSkillPoints, $reachedSkillPoints);
308 }
309
310 private function evaluateSkillPointAccounts()
311 {
312 foreach ($this->skillPointAccounts as $skillKey => $skillPointAccount) {
313 /* @var ilTestSkillPointAccount $skillPointAccount */
314
315 if (!$this->doesNumBookingsExceedRequiredBookingsBarrier($skillPointAccount)) {
316 continue;
317 }
318
319 list($skillBaseId, $skillTrefId) = explode(':', $skillKey);
320
321 $skill = new ilBasicSkill($skillBaseId);
322 $levels = $skill->getLevelData();
323
324 $reachedLevelId = null;
325
326 foreach ($levels as $level) {
327 $threshold = $this->skillLevelThresholdList->getThreshold($skillBaseId, $skillTrefId, $level['id']);
328
329 if (!($threshold instanceof ilTestSkillLevelThreshold) || !$threshold->getThreshold()) {
330 continue;
331 }
332
333 $reachedLevelId = $level['id'];
334
335 if ($skillPointAccount->getTotalReachedSkillPercent() <= $threshold->getThreshold()) {
336 break;
337 }
338 }
339
340 if ($reachedLevelId) {
341 $this->reachedSkillLevels[] = array(
342 'sklBaseId' => $skillBaseId, 'sklTrefId' => $skillTrefId, 'sklLevelId' => $reachedLevelId
343 );
344 }
345 }
346 }
347
349 {
350 return $skillPointAccount->getNumBookings() >= $this->getNumRequiredBookingsForSkillTriggering();
351 }
352
353 public function handleSkillTriggering()
354 {
355 foreach ($this->getReachedSkillLevels() as $reachedSkillLevel) {
356 $this->invokeSkillLevelTrigger($reachedSkillLevel['sklLevelId'], $reachedSkillLevel['sklTrefId']);
357
358 if ($reachedSkillLevel['sklTrefId'] > 0) {
359 ilPersonalSkill::addPersonalSkill($this->getUserId(), $reachedSkillLevel['sklTrefId']);
360 } else {
361 ilPersonalSkill::addPersonalSkill($this->getUserId(), $reachedSkillLevel['sklBaseId']);
362 }
363 }
364 //write profile completion entries if fulfilment status has changed
365 $this->skill_profile_service->writeCompletionEntryForAllProfiles($this->getUserId());
366 }
367
368 private function invokeSkillLevelTrigger($skillLevelId, $skillTrefId)
369 {
371 $skillLevelId,
372 $this->getUserId(),
373 $this->refId,
374 $skillTrefId,
376 true,
377 0,
378 $this->getPass()
379 );
380
381 /* @var ILIAS\DI\Container $DIC */ global $DIC;
382
383 $DIC->logger()->root()->info(
384 "refId={$this->refId} / usrId={$this->getUserId()} / levelId={$skillLevelId} / trefId={$skillTrefId}"
385 );
386
387 //mail('bheyser@databay.de', "trigger skill level $skillLevelId for user {$this->getUserId()}", '');
388 }
389
390 public function getSkillsMatchingNumAnswersBarrier(): array
391 {
392 $skillsMatchingNumAnswersBarrier = array();
393
394 foreach ($this->skillPointAccounts as $skillKey => $skillPointAccount) {
395 if ($this->doesNumBookingsExceedRequiredBookingsBarrier($skillPointAccount)) {
396 list($skillBaseId, $skillTrefId) = explode(':', $skillKey);
397
398 $skillsMatchingNumAnswersBarrier[$skillKey] = array(
399 'base_skill_id' => (int) $skillBaseId,
400 'tref_id' => (int) $skillTrefId
401 );
402 }
403 }
404
405 return $skillsMatchingNumAnswersBarrier;
406 }
407
408 public function getSkillsInvolvedByAssignment(): array
409 {
410 $uniqueSkills = array();
411
412 foreach ($this->skillQuestionAssignmentList->getUniqueAssignedSkills() as $skill) {
413 $skillKey = $skill['skill_base_id'] . ':' . $skill['skill_tref_id'];
414
415 $uniqueSkills[$skillKey] = array(
416 'base_skill_id' => (int) $skill['skill_base_id'],
417 'tref_id' => (int) $skill['skill_tref_id']
418 );
419 }
420
421 return $uniqueSkills;
422 }
423
424 public function isAssignedSkill($skillBaseId, $skillTrefId)
425 {
426 $this->skillQuestionAssignmentList->isAssignedSkill($skillBaseId, $skillTrefId);
427 }
428
430 {
431 $matchingSkillProfiles = array();
432
433 $usersProfiles = $this->skill_profile_service->getProfilesOfUser($this->getUserId());
434
435 foreach ($usersProfiles as $profileData) {
436 $profile = $this->skill_profile_service->getById($profileData['id']);
437 $assignedSkillLevels = $profile->getSkillLevels();
438
439 foreach ($assignedSkillLevels as $assignedSkillLevel) {
440 $skillBaseId = $assignedSkillLevel['base_skill_id'];
441 $skillTrefId = $assignedSkillLevel['tref_id'];
442
443 if ($this->skillQuestionAssignmentList->isAssignedSkill($skillBaseId, $skillTrefId)) {
444 $matchingSkillProfiles[$profileData['id']] = $profile->getTitle();
445 }
446 }
447 }
448
449 return $matchingSkillProfiles;
450 }
451
452 public function noProfileMatchingAssignedSkillExists($availableSkillProfiles): int
453 {
454 $noProfileMatchingSkills = $this->skillQuestionAssignmentList->getUniqueAssignedSkills();
455
456 foreach ($availableSkillProfiles as $skillProfileId => $skillProfileTitle) {
457 $profile = $this->skill_profile_service->getById($skillProfileId);
458 $assignedSkillLevels = $profile->getSkillLevels();
459
460 foreach ($assignedSkillLevels as $assignedSkillLevel) {
461 $skillBaseId = $assignedSkillLevel['base_skill_id'];
462 $skillTrefId = $assignedSkillLevel['tref_id'];
463
464 if ($this->skillQuestionAssignmentList->isAssignedSkill($skillBaseId, $skillTrefId)) {
465 unset($noProfileMatchingSkills["{$skillBaseId}:{$skillTrefId}"]);
466 }
467 }
468 }
469
470 return count($noProfileMatchingSkills);
471 }
472}
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static writeUserSkillLevelStatus(int $a_level_id, int $a_user_id, int $a_trigger_ref_id, int $a_tref_id=0, int $a_status=ilBasicSkill::ACHIEVED, bool $a_force=false, bool $a_self_eval=false, string $a_unique_identifier="", float $a_next_level_fulfilment=0.0, string $trigger_user_id="")
static addPersonalSkill(int $a_user_id, int $a_skill_node_id)
init(ilAssQuestionList $questionList)
initTestQuestionData(ilAssQuestionList $questionList)
calculateReachedSkillPointsFromTestPoints($skillPoints, $maxTestPoints, $reachedTestPoints)
determineReachedSkillPointsWithSolutionCompare(ilAssQuestionSolutionComparisonExpressionList $expressionList)
SkillProfileService $skill_profile_service
setNumRequiredBookingsForSkillTriggering($numRequiredBookingsForSkillTriggering)
noProfileMatchingAssignedSkillExists($availableSkillProfiles)
isAssignedSkill($skillBaseId, $skillTrefId)
bookToSkillPointAccount($skillBaseId, $skillTrefId, $maxSkillPoints, $reachedSkillPoints)
invokeSkillLevelTrigger($skillLevelId, $skillTrefId)
doesNumBookingsExceedRequiredBookingsBarrier(ilTestSkillPointAccount $skillPointAccount)
__construct(ilDBInterface $db, $testId, $refId, SkillProfileService $skill_profile_service=null)
global $DIC
Definition: feed.php:28
Interface ilDBInterface.
string $key
Consumer key/client ID value.
Definition: System.php:193