1<?php 2/* Copyright (c) 1998-2013 ILIAS open source, Extended GPL, see docs/LICENSE */ 3 4/** 5* Class ilTestEvaluationUserData 6* 7* @author Helmut Schottmüller <helmut.schottmueller@mac.com> 8* @author Björn Heyser <bheyser@databay.de> 9* @version $Id$ 10* 11* @defgroup ModulesTest Modules/Test 12* @extends ilObject 13*/ 14 15include_once "./Services/Object/classes/class.ilObject.php"; 16include_once "./Modules/Test/classes/inc.AssessmentConstants.php"; 17 18class ilTestEvaluationUserData 19{ 20 /** 21 * User name 22 * 23 * @var string 24 */ 25 public $name; 26 27 /** 28 * Login 29 * 30 * @var string 31 */ 32 public $login; 33 34 /** 35 * User ID 36 * 37 * @var integer 38 */ 39 public $user_id; 40 41 /** 42 * @var bool 43 */ 44 protected $submitted; 45 46 /** 47 * Reached points 48 * 49 * @var double 50 */ 51 public $reached; 52 53 /** 54 * Maximum available points 55 * 56 * @var double 57 */ 58 public $maxpoints; 59 60 /** 61 * Mark 62 * 63 * @var string 64 */ 65 public $mark; 66 67 /** 68 * Mark (official description) 69 * 70 * @var string 71 */ 72 public $mark_official; 73 74 /** 75 * ECTS Mark 76 * 77 * @var string 78 */ 79 public $markECTS; 80 81 /** 82 * Questions worked through 83 * 84 * @var integer 85 */ 86 public $questionsWorkedThrough; 87 88 /** 89 * Total number of questions 90 * 91 * @var integer 92 */ 93 public $numberOfQuestions; 94 95 /** 96 * Working time 97 * 98 * @var string 99 */ 100 public $timeOfWork; 101 102 /** 103 * First visit 104 * 105 * @var string 106 */ 107 public $firstVisit; 108 109 /** 110 * Last visit 111 * 112 * @var string 113 */ 114 public $lastVisit; 115 116 /** 117 * Is the test passed 118 * 119 * @var boolean 120 */ 121 public $passed; 122 123 /** 124 * Test passes 125 * 126 * @var array<int, ilTestEvaluationPassData> 127 */ 128 public $passes; 129 130 /** 131 * Questions 132 * 133 * @var array 134 */ 135 public $questions; 136 137 /** 138 * Pass Scoring (Last pass = 0, Best pass = 1) 139 * 140 * @var array 141 */ 142 private $passScoring; 143 144 public function __sleep() 145 { 146 return array('questions', 'passes', 'passed', 'lastVisit', 'firstVisit', 'timeOfWork', 'numberOfQuestions', 147 'questionsWorkedThrough', 'markECTS', 'mark_official', 'mark', 'maxpoints', 'reached', 'user_id', 'login', 148 'name', 'passScoring'); 149 } 150 151 /** 152 * Constructor 153 * 154 * @access public 155 */ 156 public function __construct($passScoring) 157 { 158 $this->passes = array(); 159 $this->questions = array(); 160 $this->passed = false; 161 $this->passScoring = $passScoring; 162 } 163 164 public function getPassScoring() 165 { 166 return $this->passScoring; 167 } 168 169 public function setPassScoring($passScoring) 170 { 171 $this->passScoring = $passScoring; 172 } 173 174 public function getPassed() 175 { 176 return $this->passed; 177 } 178 179 public function setPassed($a_passed) 180 { 181 $this->passed = ($a_passed ? true : false); 182 } 183 184 public function getName() 185 { 186 return $this->name; 187 } 188 189 public function setName($a_name) 190 { 191 $this->name = $a_name; 192 } 193 194 public function getLogin() 195 { 196 return $this->login; 197 } 198 199 public function setLogin($a_login) 200 { 201 $this->login = $a_login; 202 } 203 204 /** 205 * @return bool 206 */ 207 public function isSubmitted() 208 { 209 return $this->submitted; 210 } 211 212 /** 213 * @param bool $submitted 214 */ 215 public function setSubmitted($submitted) 216 { 217 $this->submitted = $submitted; 218 } 219 220 public function getReached() 221 { 222 return $this->getReachedPoints($this->getScoredPass()); 223 } 224 225 public function setReached($a_reached) 226 { 227 $this->reached = $a_reached; 228 } 229 230 public function getMaxpoints() 231 { 232 return $this->getAvailablePoints($this->getScoredPass()); 233 } 234 235 public function setMaxpoints($a_max_points) 236 { 237 $this->maxpoints = $a_max_points; 238 } 239 240 public function getReachedPointsInPercent() 241 { 242 return $this->getMaxPoints() ? $this->getReached() / $this->getMaxPoints() * 100.0 : 0; 243 } 244 245 public function getMark() 246 { 247 return $this->mark; 248 } 249 250 public function setMark($a_mark) 251 { 252 $this->mark = $a_mark; 253 } 254 255 public function getECTSMark() 256 { 257 return $this->markECTS; 258 } 259 260 public function setECTSMark($a_mark_ects) 261 { 262 $this->markECTS = $a_mark_ects; 263 } 264 265 public function getQuestionsWorkedThrough() 266 { 267 $questionpass = $this->getScoredPass(); 268 if (!is_object($this->passes[$questionpass])) { 269 $questionpass = 0; 270 } 271 if (is_object($this->passes[$questionpass])) { 272 return $this->passes[$questionpass]->getNrOfAnsweredQuestions(); 273 } 274 return 0; 275 } 276 277 public function setQuestionsWorkedThrough($a_nr) 278 { 279 $this->questionsWorkedThrough = $a_nr; 280 } 281 282 public function getNumberOfQuestions() 283 { 284 $questionpass = $this->getScoredPass(); 285 if (!is_object($this->passes[$questionpass])) { 286 $questionpass = 0; 287 } 288 if (is_object($this->passes[$questionpass])) { 289 return $this->passes[$questionpass]->getQuestionCount(); 290 } 291 return 0; 292 // return $this->numberOfQuestions; 293 } 294 295 public function setNumberOfQuestions($a_nr) 296 { 297 $this->numberOfQuestions = $a_nr; 298 } 299 300 public function getQuestionsWorkedThroughInPercent() 301 { 302 return $this->getNumberOfQuestions() ? $this->getQuestionsWorkedThrough() / $this->getNumberOfQuestions() * 100.0 : 0; 303 } 304 305 public function getTimeOfWork() 306 { 307 $time = 0; 308 foreach ($this->passes as $pass) { 309 $time += $pass->getWorkingTime(); 310 } 311 return $time; 312 } 313 314 public function setTimeOfWork($a_time_of_work) 315 { 316 $this->timeOfWork = $a_time_of_work; 317 } 318 319 public function getFirstVisit() 320 { 321 return $this->firstVisit; 322 } 323 324 public function setFirstVisit($a_time) 325 { 326 $this->firstVisit = $a_time; 327 } 328 329 public function getLastVisit() 330 { 331 return $this->lastVisit; 332 } 333 334 public function setLastVisit($a_time) 335 { 336 $this->lastVisit = $a_time; 337 } 338 339 public function getPasses() 340 { 341 return $this->passes; 342 } 343 344 /** 345 * @param int $pass_nr 346 * @param ilTestEvaluationPassData $pass 347 */ 348 public function addPass($pass_nr, $pass) 349 { 350 $this->passes[$pass_nr] = $pass; 351 } 352 353 /** 354 * @param $pass_nr 355 * @return ilTestEvaluationPassData|null 356 */ 357 public function getPass($pass_nr) 358 { 359 if (array_key_exists($pass_nr, $this->passes)) { 360 return $this->passes[$pass_nr]; 361 } else { 362 return null; 363 } 364 } 365 366 public function getPassCount() 367 { 368 return count($this->passes); 369 } 370 371 public function getScoredPass() 372 { 373 if ($this->getPassScoring() == 1) { 374 return $this->getBestPass(); 375 } else { 376 return $this->getLastPass(); 377 } 378 } 379 380 public function getBestPass() 381 { 382 $bestpoints = 0; 383 $bestpass = 0; 384 385 $obligationsAnsweredPassExists = $this->doesObligationsAnsweredPassExist(); 386 387 foreach ($this->passes as $pass) { 388 $reached = $this->getReachedPointsInPercentForPass($pass->getPass()); 389 390 if ($reached >= $bestpoints && ($pass->areObligationsAnswered() || !$obligationsAnsweredPassExists)) { 391 $bestpoints = $reached; 392 $bestpass = $pass->getPass(); 393 } 394 } 395 396 return $bestpass; 397 } 398 399 public function getLastPass() 400 { 401 $lastpass = 0; 402 foreach (array_keys($this->passes) as $pass) { 403 if ($pass > $lastpass) { 404 $lastpass = $pass; 405 } 406 } 407 return $lastpass; 408 } 409 410 public function addQuestionTitle($question_id, $question_title) 411 { 412 $this->questionTitles[$question_id] = $question_title; 413 } 414 415 public function getQuestionTitles() 416 { 417 return $this->questionTitles; 418 } 419 420 public function getQuestions($pass = 0) 421 { 422 if (array_key_exists($pass, $this->questions)) { 423 return $this->questions[$pass]; 424 } else { 425 return null; 426 } 427 } 428 429 public function addQuestion($original_id, $question_id, $max_points, $sequence = null, $pass = 0) 430 { 431 if (!isset($this->questions[$pass])) { 432 $this->questions[$pass] = array(); 433 } 434 435 $this->questions[$pass][] = array( 436 "id" => $question_id, // the so called "aid" from any historical time 437 "o_id" => $original_id, // when the "aid" was valid this was the "id" 438 "points" => $max_points, 439 "sequence" => $sequence 440 ); 441 } 442 443 public function getQuestion($index, $pass = 0) 444 { 445 if (array_key_exists($index, $this->questions[$pass])) { 446 return $this->questions[$pass][$index]; 447 } else { 448 return null; 449 } 450 } 451 452 public function getQuestionCount($pass = 0) 453 { 454 $count = 0; 455 if (array_key_exists($pass, $this->passes)) { 456 $count = $this->passes[$pass]->getQuestionCount(); 457 } 458 return $count; 459 } 460 461 public function getReachedPoints($pass = 0) 462 { 463 $reached = 0; 464 if (array_key_exists($pass, $this->passes)) { 465 $reached = $this->passes[$pass]->getReachedPoints(); 466 } 467 $reached = ($reached < 0) ? 0 : $reached; 468 $reached = round($reached, 2); 469 return $reached; 470 } 471 472 public function getAvailablePoints($pass = 0) 473 { 474 $available = 0; 475 if (!is_object($this->passes[$pass])) { 476 $pass = 0; 477 } 478 if (!is_object($this->passes[$pass])) { 479 return 0; 480 } 481 $available = $this->passes[$pass]->getMaxPoints(); 482 $available = round($available, 2); 483 return $available; 484 } 485 486 public function getReachedPointsInPercentForPass($pass = 0) 487 { 488 $reached = $this->getReachedPoints($pass); 489 $available = $this->getAvailablePoints($pass); 490 $percent = ($available > 0) ? $reached / $available : 0; 491 return $percent; 492 } 493 494 public function setUserID($a_usr_id) 495 { 496 $this->user_id = $a_usr_id; 497 } 498 499 public function getUserID() 500 { 501 return $this->user_id; 502 } 503 504 public function setMarkOfficial($a_mark_official) 505 { 506 $this->mark_official = $a_mark_official; 507 } 508 509 public function getMarkOfficial() 510 { 511 return $this->mark_official; 512 } 513 514 /** 515 * returns the object of class ilTestEvaluationPassData 516 * that relates to the the scored test pass (best pass / last pass) 517 * 518 * @return ilTestEvaluationPassData $passDataObject 519 */ 520 public function getScoredPassObject() 521 { 522 if ($this->getPassScoring() == 1) { 523 return $this->getBestPassObject(); 524 } else { 525 return $this->getLastPassObject(); 526 } 527 } 528 529 /** 530 * returns the count of hints requested by participant for scored testpass 531 * 532 * @return integer $requestedHintsCount 533 */ 534 public function getRequestedHintsCountFromScoredPass() 535 { 536 return $this->getRequestedHintsCount($this->getScoredPass()); 537 } 538 539 /** 540 * @return string 541 */ 542 public function getExamIdFromScoredPass() : string 543 { 544 $examId = ''; 545 $scoredPass = $this->getScoredPass(); 546 547 if (isset($this->passes[$scoredPass]) && $this->passes[$scoredPass] instanceof ilTestEvaluationPassData) { 548 $examId = $this->passes[$scoredPass]->getExamId(); 549 } 550 551 return $examId; 552 } 553 554 /** 555 * returns the count of hints requested by participant for given testpass 556 * 557 * @param integer $pass 558 * @return integer $requestedHintsCount 559 * @throws ilTestException 560 */ 561 public function getRequestedHintsCount($pass) 562 { 563 if (!isset($this->passes[$pass]) || !($this->passes[$pass] instanceof ilTestEvaluationPassData)) { 564 throw new ilTestException("invalid pass index given: $pass"); 565 } 566 567 $requestedHintsCount = $this->passes[$pass]->getRequestedHintsCount(); 568 569 return $requestedHintsCount; 570 } 571 572 /** 573 * returns the object of class ilTestEvaluationPassData 574 * that relates to the the best test pass 575 * 576 * @return ilTestEvaluationPassData $passDataObject 577 */ 578 public function getBestPassObject() 579 { 580 $bestpoints = 0; 581 $bestpassObject = 0; 582 583 $obligationsAnsweredPassExists = $this->doesObligationsAnsweredPassExist(); 584 585 foreach ($this->passes as $pass) { 586 $reached = $this->getReachedPointsInPercentForPass($pass->getPass()); 587 588 if ($reached >= $bestpoints && ($pass->areObligationsAnswered() || !$obligationsAnsweredPassExists)) { 589 $bestpoints = $reached; 590 $bestpassObject = $pass; 591 } 592 } 593 594 return $bestpassObject; 595 } 596 597 /** 598 * returns the object of class ilTestEvaluationPassData 599 * that relates to the the last test pass 600 * 601 * @return ilTestEvaluationPassData $passDataObject 602 */ 603 public function getLastPassObject() 604 { 605 $lastpassIndex = 0; 606 607 foreach (array_keys($this->passes) as $passIndex) { 608 if ($passIndex > $lastpassIndex) { 609 $lastpassIndex = $passIndex; 610 } 611 } 612 613 $lastpassObject = $this->passes[$lastpassIndex]; 614 615 return $lastpassObject; 616 } 617 618 /** 619 * returns the fact wether a test pass 620 * with all obligations answered exists or not 621 * 622 * @return boolean 623 */ 624 public function doesObligationsAnsweredPassExist() 625 { 626 foreach ($this->passes as $pass) { 627 if ($pass->areObligationsAnswered()) { 628 return true; 629 } 630 } 631 632 return false; 633 } 634 635 /** 636 * returns the fact wether all obligations 637 * in the scored test pass are answered or not 638 * 639 * @return boolean 640 */ 641 public function areObligationsAnswered() 642 { 643 return $this->getScoredPassObject()->areObligationsAnswered(); 644 } 645} // END ilTestEvaluationUserData 646