ILIAS  release_5-3 Revision v5.3.23-19-g915713cf615
class.ilTestSkillEvaluation.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (c) 1998-2013 ILIAS open source, Extended GPL, see docs/LICENSE */
3 
4 require_once 'Modules/TestQuestionPool/classes/class.ilAssQuestionSkillAssignmentList.php';
5 require_once 'Modules/TestQuestionPool/classes/questions/LogicalAnswerCompare/ilAssLacQuestionProvider.php';
6 require_once 'Modules/TestQuestionPool/classes/questions/LogicalAnswerCompare/ilAssLacConditionParser.php';
7 require_once 'Modules/TestQuestionPool/classes/questions/LogicalAnswerCompare/ilAssLacCompositeEvaluator.php';
8 require_once 'Modules/Test/classes/class.ilTestSkillPointAccount.php';
9 require_once 'Modules/Test/classes/class.ilTestSkillLevelThresholdList.php';
10 require_once 'Services/Skill/classes/class.ilBasicSkill.php';
11 
19 {
23  private $db;
24 
28  private $refId;
29 
34 
39 
43  private $questions;
44 
49 
54 
59 
64 
68  private $userId;
69 
73  private $activeId;
74 
78  private $pass;
79 
84 
85  public function __construct(ilDBInterface $db, $testId, $refId)
86  {
87  $this->db = $db;
88  $this->refId = $refId;
89 
90  $this->skillQuestionAssignmentList = new ilAssQuestionSkillAssignmentList($this->db);
91 
92  $this->skillLevelThresholdList = new ilTestSkillLevelThresholdList($this->db);
93  $this->skillLevelThresholdList->setTestId($testId);
94 
95  $this->questions = array();
96  $this->maxPointsByQuestion = array();
97  }
98 
99  public function getUserId()
100  {
101  return $this->userId;
102  }
103 
104  public function setUserId($userId)
105  {
106  $this->userId = $userId;
107  }
108 
109  public function getActiveId()
110  {
111  return $this->activeId;
112  }
113 
114  public function setActiveId($activeId)
115  {
116  $this->activeId = $activeId;
117  }
118 
119  public function getPass()
120  {
121  return $this->pass;
122  }
123 
124  public function setPass($pass)
125  {
126  $this->pass = $pass;
127  }
128 
130  {
132  }
133 
135  {
136  $this->numRequiredBookingsForSkillTriggering = $numRequiredBookingsForSkillTriggering;
137  }
138 
139  public function init(ilAssQuestionList $questionList)
140  {
141  $this->skillQuestionAssignmentList->setParentObjId($questionList->getParentObjId());
142  $this->skillQuestionAssignmentList->loadFromDb();
143 
144  $this->skillLevelThresholdList->loadFromDb();
145 
146  $this->initTestQuestionData($questionList);
147  }
148 
152  public function evaluate($testResults)
153  {
154  $this->reset();
155 
156  $this->initTestResultData($testResults);
157 
158  $this->drawUpSkillPointAccounts();
160  }
161 
162  public function getReachedSkillLevels()
163  {
165  }
166 
167  private function reset()
168  {
169  $this->reachedPointsByQuestion = array();
170  $this->skillPointAccounts = array();
171  $this->reachedSkillLevels = array();
172  }
173 
174  private function initTestQuestionData(ilAssQuestionList $questionList)
175  {
176  foreach ($questionList->getQuestionDataArray() as $questionData) {
177  $this->questions[] = $questionData['question_id'];
178 
179  $this->maxPointsByQuestion[ $questionData['question_id'] ] = $questionData['points'];
180  }
181  }
182 
186  private function initTestResultData($testResults)
187  {
188  foreach ($testResults as $key => $result) {
189  if ($key === 'pass' || $key === 'test') { // note: key int 0 IS == 'pass' or 'buxtehude'
190  continue;
191  }
192 
193  if (!$result['workedthrough']) {
194  continue;
195  }
196 
197  $this->reachedPointsByQuestion[ $result['qid'] ] = $result['reached'];
198  }
199  }
200 
201  private function drawUpSkillPointAccounts()
202  {
203  foreach ($this->questions as $questionId) {
204  if (!$this->isAnsweredQuestion($questionId)) {
205  continue;
206  }
207 
208  $assignments = $this->skillQuestionAssignmentList->getAssignmentsByQuestionId($questionId);
209 
210  foreach ($assignments as $assignment) {
211  if ($assignment->hasEvalModeBySolution()) {
212  $reachedSkillPoints = $this->determineReachedSkillPointsWithSolutionCompare(
213  $assignment->getSolutionComparisonExpressionList()
214  );
215  } else {
216  $maxTestPoints = $this->maxPointsByQuestion[$questionId];
217  $reachedTestPoints = $this->reachedPointsByQuestion[$questionId];
218 
219  $reachedSkillPoints = $this->calculateReachedSkillPointsFromTestPoints(
220  $assignment->getSkillPoints(),
221  $maxTestPoints,
222  $reachedTestPoints
223  );
224  }
225 
227  $assignment->getSkillBaseId(),
228  $assignment->getSkillTrefId(),
229  $assignment->getMaxSkillPoints(),
230  $reachedSkillPoints
231  );
232  }
233  }
234  }
235 
236  private function isAnsweredQuestion($questionId)
237  {
238  return isset($this->reachedPointsByQuestion[$questionId]);
239  }
240 
242  {
243  $questionProvider = new ilAssLacQuestionProvider();
244  $questionProvider->setQuestionId($expressionList->getQuestionId());
245 
246  foreach ($expressionList->get() as $expression) {
247  /* @var ilAssQuestionSolutionComparisonExpression $expression */
248 
249  $conditionParser = new ilAssLacConditionParser();
250  $conditionComposite = $conditionParser->parse($expression->getExpression());
251 
252  $compositeEvaluator = new ilAssLacCompositeEvaluator(
253  $questionProvider,
254  $this->getActiveId(),
255  $this->getPass()
256  );
257 
258  if ($compositeEvaluator->evaluate($conditionComposite)) {
259  return $expression->getPoints();
260  }
261  }
262 
263  return 0;
264  }
265 
266  private function calculateReachedSkillPointsFromTestPoints($skillPoints, $maxTestPoints, $reachedTestPoints)
267  {
268  if ($reachedTestPoints < 0) {
269  $reachedTestPoints = 0;
270  }
271 
272  $factor = 0;
273 
274  if ($maxTestPoints > 0) {
275  $factor = $reachedTestPoints / $maxTestPoints;
276  }
277 
278  return ($skillPoints * $factor);
279  }
280 
281  private function bookToSkillPointAccount($skillBaseId, $skillTrefId, $maxSkillPoints, $reachedSkillPoints)
282  {
283  $skillKey = $skillBaseId . ':' . $skillTrefId;
284 
285  if (!isset($this->skillPointAccounts[$skillKey])) {
286  $this->skillPointAccounts[$skillKey] = new ilTestSkillPointAccount();
287  }
288 
289  $this->skillPointAccounts[$skillKey]->addBooking($maxSkillPoints, $reachedSkillPoints);
290  }
291 
292  private function evaluateSkillPointAccounts()
293  {
294  foreach ($this->skillPointAccounts as $skillKey => $skillPointAccount) {
295  /* @var ilTestSkillPointAccount $skillPointAccount */
296 
297  if (!$this->doesNumBookingsExceedRequiredBookingsBarrier($skillPointAccount)) {
298  continue;
299  }
300 
301  list($skillBaseId, $skillTrefId) = explode(':', $skillKey);
302 
303  $skill = new ilBasicSkill($skillBaseId);
304  $levels = $skill->getLevelData();
305 
306  $reachedLevelId = null;
307 
308  foreach ($levels as $level) {
309  $threshold = $this->skillLevelThresholdList->getThreshold($skillBaseId, $skillTrefId, $level['id']);
310 
311  if (!($threshold instanceof ilTestSkillLevelThreshold) || !$threshold->getThreshold()) {
312  continue;
313  }
314 
315  $reachedLevelId = $level['id'];
316 
317  if ($skillPointAccount->getTotalReachedSkillPercent() <= $threshold->getThreshold()) {
318  break;
319  }
320  }
321 
322  if ($reachedLevelId) {
323  $this->reachedSkillLevels[] = array(
324  'sklBaseId' => $skillBaseId, 'sklTrefId' => $skillTrefId, 'sklLevelId' => $reachedLevelId
325  );
326  }
327  }
328  }
329 
331  {
332  return $skillPointAccount->getNumBookings() >= $this->getNumRequiredBookingsForSkillTriggering();
333  }
334 
335  public function handleSkillTriggering()
336  {
337  foreach ($this->getReachedSkillLevels() as $reachedSkillLevel) {
338  $this->invokeSkillLevelTrigger($reachedSkillLevel['sklLevelId'], $reachedSkillLevel['sklTrefId']);
339  }
340  }
341 
342  private function invokeSkillLevelTrigger($skillLevelId, $skillTrefId)
343  {
345  $skillLevelId,
346  $this->getUserId(),
347  $this->refId,
348  $skillTrefId,
350  true,
351  0,
352  $this->getPass()
353  );
354 
355  /* @var ILIAS\DI\Container $DIC */ global $DIC;
356 
357  $DIC->logger()->root()->info(
358  "refId={$this->refId} / usrId={$this->getUserId()} / levelId={$skillLevelId} / trefId={$skillTrefId}"
359  );
360 
361  //mail('bheyser@databay.de', "trigger skill level $skillLevelId for user {$this->getUserId()}", '');
362  }
363 
365  {
366  $skillsMatchingNumAnswersBarrier = array();
367 
368  foreach ($this->skillPointAccounts as $skillKey => $skillPointAccount) {
369  if ($this->doesNumBookingsExceedRequiredBookingsBarrier($skillPointAccount)) {
370  list($skillBaseId, $skillTrefId) = explode(':', $skillKey);
371 
372  $skillsMatchingNumAnswersBarrier[$skillKey] = array(
373  'base_skill_id' => (int) $skillBaseId,
374  'tref_id' => (int) $skillTrefId
375  );
376  }
377  }
378 
379  return $skillsMatchingNumAnswersBarrier;
380  }
381 
383  {
384  $uniqueSkills = array();
385 
386  foreach ($this->skillQuestionAssignmentList->getUniqueAssignedSkills() as $skill) {
387  $skillKey = $skill['skill_base_id'] . ':' . $skill['skill_tref_id'];
388 
389  $uniqueSkills[$skillKey] = array(
390  'base_skill_id' => (int) $skill['skill_base_id'],
391  'tref_id' => (int) $skill['skill_tref_id']
392  );
393  }
394 
395  return $uniqueSkills;
396  }
397 
398  public function isAssignedSkill($skillBaseId, $skillTrefId)
399  {
400  $this->skillQuestionAssignmentList->isAssignedSkill($skillBaseId, $skillTrefId);
401  }
402 
404  {
405  $matchingSkillProfiles = array();
406 
407  include_once("./Services/Skill/classes/class.ilSkillProfile.php");
408  $usersProfiles = ilSkillProfile::getProfilesOfUser($this->getUserId());
409 
410  foreach ($usersProfiles as $profileData) {
411  $profile = new ilSkillProfile($profileData['id']);
412  $assignedSkillLevels = $profile->getSkillLevels();
413 
414  foreach ($assignedSkillLevels as $assignedSkillLevel) {
415  $skillBaseId = $assignedSkillLevel['base_skill_id'];
416  $skillTrefId = $assignedSkillLevel['tref_id'];
417 
418  if ($this->skillQuestionAssignmentList->isAssignedSkill($skillBaseId, $skillTrefId)) {
419  $matchingSkillProfiles[$profileData['id']] = $profile->getTitle();
420  }
421  }
422  }
423 
424  return $matchingSkillProfiles;
425  }
426 
427  public function noProfileMatchingAssignedSkillExists($availableSkillProfiles)
428  {
429  $noProfileMatchingSkills = $this->skillQuestionAssignmentList->getUniqueAssignedSkills();
430 
431  foreach ($availableSkillProfiles as $skillProfileId => $skillProfileTitle) {
432  $profile = new ilSkillProfile($skillProfileId);
433  $assignedSkillLevels = $profile->getSkillLevels();
434 
435  foreach ($assignedSkillLevels as $assignedSkillLevel) {
436  $skillBaseId = $assignedSkillLevel['base_skill_id'];
437  $skillTrefId = $assignedSkillLevel['tref_id'];
438 
439  if ($this->skillQuestionAssignmentList->isAssignedSkill($skillBaseId, $skillTrefId)) {
440  unset($noProfileMatchingSkills["{$skillBaseId}:{$skillTrefId}"]);
441  }
442  }
443  }
444 
445  return count($noProfileMatchingSkills);
446  }
447 }
init(ilAssQuestionList $questionList)
setNumRequiredBookingsForSkillTriggering($numRequiredBookingsForSkillTriggering)
invokeSkillLevelTrigger($skillLevelId, $skillTrefId)
calculateReachedSkillPointsFromTestPoints($skillPoints, $maxTestPoints, $reachedTestPoints)
$result
global $DIC
Definition: saml.php:7
__construct(ilDBInterface $db, $testId, $refId)
Interface ilDBInterface.
static getProfilesOfUser($a_user_id)
Get profiles of a user.
isAssignedSkill($skillBaseId, $skillTrefId)
noProfileMatchingAssignedSkillExists($availableSkillProfiles)
bookToSkillPointAccount($skillBaseId, $skillTrefId, $maxSkillPoints, $reachedSkillPoints)
Create styles array
The data for the language used.
Class ilParserQuestionProvider.
initTestQuestionData(ilAssQuestionList $questionList)
static writeUserSkillLevelStatus( $a_level_id, $a_user_id, $a_trigger_ref_id, $a_tref_id=0, $a_status=ilBasicSkill::ACHIEVED, $a_force=false, $a_self_eval=false, $a_unique_identifier="")
Write skill level status.
doesNumBookingsExceedRequiredBookingsBarrier(ilTestSkillPointAccount $skillPointAccount)
Basic Skill.
determineReachedSkillPointsWithSolutionCompare(ilAssQuestionSolutionComparisonExpressionList $expressionList)
$key
Definition: croninfo.php:18