ILIAS  release_8 Revision v8.24
class.assFormulaQuestionResult.php
Go to the documentation of this file.
1<?php
2
26{
27 public const RESULT_NO_SELECTION = 0;
28 public const RESULT_DEC = 1;
29 public const RESULT_FRAC = 2;
30 public const RESULT_CO_FRAC = 3;
31
32 private $result;
33 private $range_min;
34 private $range_max;
35 private $tolerance;
36 private $unit;
37 private $formula;
39 private $rating_sign;
41 private $rating_unit;
42 private $points;
43 private $precision;
44 private $result_type;
47
48 private $available_units = array();
49 private \ilGlobalTemplateInterface $main_tpl;
50
68 {
69 global $DIC;
70 $this->main_tpl = $DIC->ui()->mainTemplate();
71 $this->result = $result;
72 # $this->setRangeMin((is_numeric($range_min)) ? $range_min : NULL);
73 # $this->setRangeMax((is_numeric($range_max)) ? $range_max : NULL);
74 $this->setRangeMin($range_min);
75 $this->setRangeMax($range_max);
76
77
78 $this->tolerance = $tolerance;
79 $this->unit = $unit;
80 $this->formula = $formula;
81 $this->setPoints($points);
82 $this->precision = $precision;
83 $this->rating_simple = $rating_simple;
84 $this->rating_sign = $rating_sign;
85 $this->rating_value = $rating_value;
86 $this->rating_unit = $rating_unit;
87 $this->result_type = $result_type;
90 }
91
92 public function substituteFormula($variables, $results)
93 {
94 global $DIC;
95 $lng = $DIC['lng'];
96
97 $formula = $this->getFormula();
98
99 if (preg_match_all("/(\\\$r\\d+)/ims", $formula, $matches)) {
100 foreach ($matches[1] as $result) {
101 if (strcmp($result, $this->getResult()) == 0) {
102 $this->main_tpl->setOnScreenMessage('failure', $lng->txt("errRecursionInResult"));
103 return false;
104 }
105
106 if (is_object($results[$result])) {
107 $formula = str_replace($result, $results[$result]->substituteFormula($variables, $results), $formula);
108 } else {
109 $this->main_tpl->setOnScreenMessage('failure', $lng->txt("errFormulaQuestion"));
110 return false;
111 }
112 }
113 }
114
115 return "(" . $formula . ")";
116 }
117
118 public function calculateFormula($variables, $results, $question_id = 0, $use_precision = true)
119 {
120 $resultunits = array();
121 if ($question_id > 0) {
122 $resultunits = $this->getAvailableResultUnits($question_id);
123 }
124
125 include_once "./Services/Math/classes/class.ilMath.php";
126 include_once "./Services/Math/classes/class.EvalMath.php";
127 $formula = $this->substituteFormula($variables, $results);
128 if (preg_match_all("/(\\\$v\\d+)/ims", $formula, $matches)) {
129 foreach ($matches[1] as $variable) {
130 $varObj = $variables[$variable];
131 if (!is_object($varObj)) {
132 continue;
133 }
134 $value = $varObj->getBaseValue();
135 $formula = preg_replace("/\\\$" . substr($variable, 1) . "(?![0-9]+)/", "(" . $value . ")" . "\\1", $formula);
136 }
137 }
138 $math = new EvalMath();
139 $math->suppress_errors = true;
140
141 $formula = str_replace(",", ".", $formula);
142 $result = $math->evaluate($formula);
143 if (is_object($this->getUnit())) {
144 $result = ilMath::_div($result, $this->getUnit()->getFactor(), 100);
145 }
146
147 // @todo DON'T USE ilMath::_mul() ... bcmul() returns wrong result !!!!
148
149 if ($use_precision == true) {
150 $res = $result * 1;
151 if (is_numeric($this->getPrecision())) {
152 if ($this->getResultType() == self::RESULT_DEC || $this->getResultType() == self::RESULT_NO_SELECTION) {
153 $result = ilMath::_round($res, $this->getPrecision());
154 }
155 }
156 }
157 return $result;
158 }
159
160 public function findValidRandomVariables($variables, $results): void
161 {
162 include_once "./Services/Math/classes/class.EvalMath.php";
163 $i = 0;
164 $inRange = false;
165 while ($i < 1000 && !$inRange) {
166 $formula = $this->substituteFormula($variables, $results);
167 if (preg_match_all("/(\\\$v\\d+)/ims", $formula, $matches)) {
168 foreach ($matches[1] as $variable) {
169 $varObj = $variables[$variable];
170 if (!is_object($varObj)) {
171 continue;
172 }
173 $varObj->setRandomValue();
174 $formula = preg_replace("/\\\$" . substr($variable, 1) . "(?![0-9]+)/", "(" . $varObj->getBaseValue() . ")" . "\\1", $formula);
175 }
176 }
177 $math = new EvalMath();
178 $math->suppress_errors = true;
179 $result = $math->evaluate($formula);
180 $inRange = (is_numeric($result)) ? true : false;
181 if ($inRange) {
182 if (is_numeric($this->getRangeMin())) {
183 if ($result < $this->getRangeMinBase()) {
184 $inRange = false;
185 }
186 }
187 if (is_numeric($this->getRangeMax())) {
188 if ($result > $this->getRangeMaxBase()) {
189 $inRange = false;
190 }
191 }
192 }
193 $i++;
194 }
195 }
196
197 public function suggestRange($variables, $results): void
198 {
199
200// @todo Check this
201 include_once "./Services/Math/classes/class.EvalMath.php";
202 $range_min = null;
203 $range_max = null;
204 for ($i = 0; $i < 1000; $i++) {
205 $formula = $this->substituteFormula($variables, $results);
206 if (preg_match_all("/(\\\$v\\d+)/ims", $formula, $matches)) {
207 foreach ($matches[1] as $variable) {
208 $varObj = $variables[$variable];
209 if (!is_object($varObj)) {
210 continue;
211 }
212 $varObj->setRandomValue();
213 $formula = preg_replace("/\\\$" . substr($variable, 1) . "(?![0-9]+)/", "(" . $varObj->getBaseValue() . ")" . "\\1", $formula);
214 }
215 }
216 $math = new EvalMath();
217 $math->suppress_errors = true;
218 $result = $math->evaluate($formula);
219 if (($range_min == null) || ($result < $range_min)) {
221 }
222 if (($range_max == null) || ($result > $range_max)) {
224 }
225 }
226 include_once "./Services/Math/classes/class.ilMath.php";
227 if (is_object($this->getUnit())) {
228 $range_min = ilMath::_div($range_min, $this->getUnit()->getFactor());
229 $range_max = ilMath::_div($range_max, $this->getUnit()->getFactor());
230 }
231 $this->setRangeMin(ilMath::_mul($range_min, 1, $this->getPrecision()));
232 $this->setRangeMax(ilMath::_mul($range_max, 1, $this->getPrecision()));
233 }
234
242 public function isCorrect($variables, $results, $value, $unit = null): bool
243 {
244 // The user did not answer the question ....
245 if ($value === null || 0 == strlen($value)) {
246 return false;
247 }
248 $value = str_replace(' ', '', $value);
249
250 include_once "./Services/Math/classes/class.EvalMath.php";
251 include_once "./Services/Math/classes/class.ilMath.php";
252 $formula = $this->substituteFormula($variables, $results);
253
254 $check_valid_chars = true;
255
256 if (preg_match_all("/(\\\$v\\d+)/ims", $formula, $matches)) {
257 foreach ($matches[1] as $variable) {
258 $varObj = $variables[$variable];
259 if (!is_object($varObj)) {
260 continue;
261 }
262
263 if ($varObj->getUnit() != null) {
264 //convert unit and value to baseunit.... because vars could have different units
265 if ($varObj->getUnit()->getBaseUnit() != -1) { #$this->getUnit() != NULL)
266 $tmp_value = $varObj->getValue() * $varObj->getUnit()->getFactor();
267 } else {
268 $tmp_value = $varObj->getValue();
269 }
270 } else {
271 $tmp_value = $varObj->getValue();
272 }
273
274 $formula = preg_replace("/\\\$" . substr($variable, 1) . "(?![0-9]+)/", "(" . $tmp_value . ")" . "\\1", $formula);
275 }
276 }
277
278 $math = new EvalMath();
279 $math->suppress_errors = true;
280 $result = $math->evaluate($formula); // baseunit-result!!
281 $resultWithRespectedUnit = $result;
282
283 if (is_object($this->getUnit())) {
284 //there is a "fix" result_unit defined!
285
286 // if expected resultunit != baseunit convert to "fix" result_unit
287 if ($this->getUnit()->getBaseUnit() != -1) {
288 $resultWithRespectedUnit = ilMath::_div($result, $this->getUnit()->getFactor());
289 }
290 } elseif ($this->getUnit() == null && $unit != null) {
291 // there is no "fix" result_unit defined, but the user has selected a unit ...
292 // so .... there are "available resultunits" in multi-selectbox selected
293 // -> check if selected user-unit is baseunit
294 if ($unit->getFactor() != 1 && strlen(trim($unit->getFactor())) != 1) {
295 // result is already calculated to baseunit.... -> get correct precision..
296 $resultWithRespectedUnit = ilMath::_div($result, $unit->getFactor());
297 }
298 }
299
300 $result = substr($result, 0, strlen($resultWithRespectedUnit));
301
302 // check for valid chars ("0-9",",|.|/","0-9","e|E","+|-","0-9")
303 $has_valid_chars = preg_match("/^-?([0-9]*)(,|\\.|\\/){0,1}([0-9]*)([eE][\\+|-]([0-9])+)?$/", $value, $matches);
304 if (!$has_valid_chars) {
305 $check_valid_chars = false;
306 } elseif (
307 (isset($matches[2]) && $matches[2] == '/') &&
308 (isset($matches[4]) && strtolower($matches[4]) == "e") &&
309 (!isset($matches[1]) || !strlen($matches[1]) || !isset($matches[3]) || !strlen($matches[3]) || $matches[3] == 0)) {
310 $check_valid_chars = false;
311 }
312
313 // result_type extension
314 switch ($this->getResultType()) {
316 if (substr_count($value, '.') == 1 || substr_count($value, ',') == 1) {
317 $exp_val = $value;
318 $frac_value = str_replace(',', '.', $exp_val);
319 } else {
320 $frac_value = $value;
321 }
322
323 if (substr_count($value, '/') >= 1) {
324 $check_fraction = false;
325 } else {
326 $check_fraction = true;
327 }
328 break;
329
332 $exp_val = explode('/', $value);
333 if (count($exp_val) == 1) {
334 $frac_value = ilMath::_div($exp_val[0], 1);
335
336 if (ilMath::_equals($frac_value, $resultWithRespectedUnit, $this->getPrecision())) {
337 $check_fraction = true;
338 } else {
339 $check_fraction = false;
340 }
341 } else {
342 try {
343 $frac_value = ilMath::_div($exp_val[0], $exp_val[1]);
344 } catch (ilMathDivisionByZeroException $ex) {
345 if ($result) {
346 return false;
347 } else {
348 return true;
349 }
350 }
351 $frac_value = str_replace(',', '.', $frac_value);
352
353 if (ilMath::_equals($frac_value, $resultWithRespectedUnit, $this->getPrecision())) {
354 $check_fraction = true;
355 }
356
358 if (!self::isCoprimeFraction($exp_val[0], $exp_val[1])) {
359 $check_fraction = false;
360 }
361 }
362 }
363
364 if (substr_count($value, '.') >= 1 || substr_count($value, ',') >= 1) {
365 $check_fraction = false;
366 }
367 break;
368
370 default:
371 if (substr_count($value, '.') == 1 || substr_count($value, ',') == 1) {
372 $frac_value = str_replace(',', '.', $value);
373 } elseif (substr_count($value, '/') == 1) {
374 $exp_val = explode('/', $value);
375 try {
376 $frac_value = ilMath::_div($exp_val[0], $exp_val[1]);
377 } catch (ilMathDivisionByZeroException $ex) {
378 if ($result) {
379 return false;
380 } else {
381 return true;
382 }
383 }
384 } else {
385 $frac_value = $value;
386 }
387
388 $check_fraction = true;
389 break;
390 }
391
392 if (is_object($unit)) {
393 if (isset($frac_value)) {
394 $value = ilMath::_mul($frac_value, $unit->getFactor(), 100);
395 }
396 }
397
398 $frac_value = ilMath::_round($frac_value, $this->getPrecision());
399 $resultWithRespectedUnit = ilMath::_round($resultWithRespectedUnit, $this->getPrecision());
400
401 $checkvalue = false;
402 if (isset($frac_value)) {
403 if ($this->isInTolerance($frac_value, $resultWithRespectedUnit, $this->getTolerance())) {
404 $checkvalue = true;
405 }
406 } else {
407 if ($this->isInTolerance($value, $resultWithRespectedUnit, $this->getTolerance())) {
408 $checkvalue = true;
409 }
410 }
411
412 $checkunit = true;
413 if (is_object($this->getUnit())) {
414 if (is_object($unit)) {
415 if ($unit->getId() != $this->getUnit()->getId()) {
416 $checkunit = false;
417 }
418 }
419 }
420 return $checkvalue && $checkunit && $check_fraction && $check_valid_chars;
421 }
422
423 protected function isInTolerance($user_answer, $expected, $tolerated_percentage): bool
424 {
425 $user_answer = ilMath::_mul($user_answer, 1, $this->getPrecision());
426 $tolerance_abs = abs(ilMath::_div(ilMath::_mul($tolerated_percentage, $expected, 100), 100));
427 $lower_boundary = ilMath::_sub($expected, $tolerance_abs);
428 $upper_boundary = ilMath::_add($expected, $tolerance_abs);
429
430 return $lower_boundary <= $user_answer
431 && $user_answer <= $upper_boundary;
432 }
433
434 protected function checkSign($v1, $v2): bool
435 {
436 if ((($v1 >= 0) && ($v2 >= 0)) || (($v1 <= 0) && ($v2 <= 0))) {
437 return true;
438 } else {
439 return false;
440 }
441 }
442
443 public function getReachedPoints($variables, $results, $value, $unit, $units)
444 {
445 global $DIC;
446 $ilLog = $DIC['ilLog'];
447 if ($this->getRatingSimple()) {
448 if ($this->isCorrect($variables, $results, $value, $units[$unit] ?? null)) {
449 return $this->getPoints();
450 } else {
451 return 0;
452 }
453 } else {
454 $points = 0;
455 include_once "./Services/Math/classes/class.EvalMath.php";
456 include_once "./Services/Math/classes/class.ilMath.php";
457 $formula = $this->substituteFormula($variables, $results);
458
459 if (preg_match_all("/(\\\$v\\d+)/ims", $formula, $matches)) {
460 foreach ($matches[1] as $variable) {
461 $varObj = $variables[$variable];
462 if (!is_object($varObj)) {
463 continue;
464 }
465 if ($varObj->getUnit() != null) {
466 //convert unit and value to baseunit
467 if ($varObj->getUnit()->getBaseUnit() != -1) {
468 $tmp_value = $varObj->getValue() * $varObj->getUnit()->getFactor();
469 } else {
470 $tmp_value = $varObj->getValue();
471 }
472 } else {
473 $tmp_value = $varObj->getValue();
474 }
475 $formula = preg_replace("/\\\$" . substr($variable, 1) . "(?![0-9]+)/", "(" . $tmp_value . ")" . "\\1", $formula);
476 }
477 }
478
479 $math = new EvalMath();
480 $math->suppress_errors = true;
481 $result = $math->evaluate($formula);
482
483 // result_type extension
484 switch ($this->getResultType()) {
486 if ((substr_count($value, '.') == 1) || (substr_count($value, ',') == 1)) {
487 $exp_val = $value;
488 $frac_value = str_replace(',', '.', $exp_val);
489 } else {
490 $frac_value = $value;
491 }
492 $check_fraction = true;
493 break;
495 $exp_val = explode('/', $value);
496 if (count($exp_val) == 1) {
497 $frac_value = ilMath::_div($exp_val[0], 1, $this->getPrecision());
498 if (ilMath::_equals(abs($frac_value), abs($result), $this->getPrecision())) {
499 $check_fraction = true;
500 } else {
501 $check_fraction = false;
502 }
503 } else {
504 $frac_value = ilMath::_div($exp_val[0], $exp_val[1], $this->getPrecision());
505 if (ilMath::_equals(abs($frac_value), abs($result), $this->getPrecision())) {
506 $check_fraction = true;
507 }
508 }
509 break;
511 $exp_val = explode('/', $value);
512 if (count($exp_val) == 1) {
513 $check_fraction = false;
514 } else {
515 $frac_value = ilMath::_div($exp_val[0], $exp_val[1], $this->getPrecision());
516 if (self::isCoprimeFraction($exp_val[0], $exp_val[1])) {
517 $check_fraction = true;
518 }
519 }
520 break;
522 default:
523 $check_fraction = true;
524 break;
525 }
526
527 // result unit!!
528 if (is_object($this->getUnit())) {
529 // if expected resultunit != baseunit convert to resultunit
530 if ($this->getUnit()->getBaseUnit() != -1) {
531 $result = ilMath::_div($result, $this->getUnit()->getFactor(), $this->getPrecision());
532 } else {
533 //if resultunit == baseunit calculate to get correct precision
534 $result = ilMath::_mul($result, $this->getUnit()->getFactor(), $this->getPrecision());
535 }
536 }
537
538 if (is_object($unit)) {
539 if (isset($frac_value)) {
540 $value = ilMath::_mul($frac_value, $unit->getFactor(), 100);
541 }
542 }
543
544 if ($this->checkSign($result, $value)) {
545 $points += ilMath::_mul($this->getPoints(), ilMath::_div($this->getRatingSign(), 100));
546 }
547
548 if ($this->isInTolerance(abs($value), abs($result), $this->getTolerance())) {
549 $points += ilMath::_mul($this->getPoints(), ilMath::_div($this->getRatingValue(), 100));
550 }
551 if (is_object($this->getUnit())) {
552 $base1 = $units[$unit] ?? null;
553 if (is_object($base1)) {
554 $base1 = $units[$base1->getBaseUnit()];
555 }
556 $base2 = $units[$this->getUnit()->getBaseUnit()];
557 if (is_object($base1) && is_object($base2) && $base1->getId() == $base2->getId()) {
558 $points += ilMath::_mul($this->getPoints(), ilMath::_div($this->getRatingUnit(), 100));
559 }
560 }
561 return $points;
562 }
563 }
564
565 public function getResultInfo($variables, $results, $value, $unit, $units): array
566 {
567 if ($this->getRatingSimple()) {
568 if ($this->isCorrect($variables, $results, $value, $units[$unit] ?? null)) {
569 return array("points" => $this->getPoints());
570 } else {
571 return array("points" => 0);
572 }
573 } else {
574 include_once "./Services/Math/classes/class.EvalMath.php";
575 include_once "./Services/Math/classes/class.ilMath.php";
576 $totalpoints = 0;
577 $formula = $this->substituteFormula($variables, $results);
578 if (preg_match_all("/(\\\$v\\d+)/ims", $formula, $matches)) {
579 foreach ($matches[1] as $variable) {
580 $varObj = $variables[$variable];
581 $formula = preg_replace("/\\\$" . substr($variable, 1) . "(?![0-9]+)/", "(" . $varObj->getBaseValue() . ")" . "\\1", $formula);
582 }
583 }
584 $math = new EvalMath();
585 $math->suppress_errors = true;
586 $result = $math->evaluate($formula);
587 if (is_object($this->getUnit())) {
588 $result = ilMath::_mul($result, $this->getUnit()->getFactor(), 100);
589 }
590 if (is_object($unit)) {
591 $value = ilMath::_mul($value, $unit->getFactor(), 100);
592 } else {
593 }
594 $details = array();
595 if ($this->checkSign($result, $value)) {
596 $points = ilMath::_mul($this->getPoints(), $this->getRatingSign() / 100);
597 $totalpoints += $points;
598 $details['sign'] = $points;
599 }
600 if ($this->isInTolerance(abs($value), abs($result), $this->getTolerance())) {
601 $points = ilMath::_mul($this->getPoints(), $this->getRatingValue() / 100);
602 $totalpoints += $points;
603 $details['value'] = $points;
604 }
605 if (is_object($this->getUnit())) {
606 $base1 = $units[$unit];
607 if (is_object($base1)) {
608 $base1 = $units[$base1->getBaseUnit()];
609 }
610 $base2 = $units[$this->getUnit()->getBaseUnit()];
611 if (is_object($base1) && is_object($base2) && $base1->getId() == $base2->getId()) {
612 $points = ilMath::_mul($this->getPoints(), $this->getRatingUnit() / 100);
613 $totalpoints += $points;
614 $details['unit'] = $points;
615 }
616 }
617 $details['points'] = $totalpoints;
618 return $details;
619 }
620 }
621
622 /************************************
623 * Getter and Setter
624 ************************************/
625
626 public function setResult($result): void
627 {
628 $this->result = $result;
629 }
630
631 public function getResult(): string
632 {
633 return $this->result;
634 }
635
636 public function setRangeMin($range_min): void
637 {
638 // include_once "./Services/Math/classes/class.EvalMath.php";
639 // $math = new EvalMath();
640 // $math->suppress_errors = TRUE;
641 // $result = $math->evaluate($range_min);
642 // $val = (strlen($result) > 8) ? strtoupper(sprintf("%e", $result)) : $result;
643 // $this->range_min = $val;
644
645 include_once "./Services/Math/classes/class.EvalMath.php";
646 $math = new EvalMath();
647 $math->suppress_errors = true;
648 $result = $math->evaluate((string) $range_min);
649 $this->range_min = $result;
650 }
651
652 public function getRangeMin()
653 {
654 return $this->range_min;
655 }
656
657 public function getRangeMinBase()
658 {
659 if (is_numeric($this->getRangeMin())) {
660 if (is_object($this->getUnit())) {
661 include_once "./Services/Math/classes/class.ilMath.php";
662 return ilMath::_mul($this->getRangeMin(), $this->getUnit()->getFactor(), 100);
663 }
664 }
665 return $this->getRangeMin();
666 }
667
668 public function setRangeMax($range_max): void
669 {
670 // include_once "./Services/Math/classes/class.EvalMath.php";
671 // $math = new EvalMath();
672 // $math->suppress_errors = TRUE;
673 // $result = $math->evaluate($range_max);
674 // $val = (strlen($result) > 8) ? strtoupper(sprintf("%e", $result)) : $result;
675 // $this->range_max = $val;
676
677 include_once "./Services/Math/classes/class.EvalMath.php";
678 $math = new EvalMath();
679 $math->suppress_errors = true;
680 $result = $math->evaluate((string) $range_max);
681 $this->range_max = $result;
682 }
683
684 public function getRangeMax()
685 {
686 return $this->range_max;
687 }
688
689 public function getRangeMaxBase()
690 {
691 if (is_numeric($this->getRangeMax())) {
692 if (is_object($this->getUnit())) {
693 include_once "./Services/Math/classes/class.ilMath.php";
694 return ilMath::_mul($this->getRangeMax(), $this->getUnit()->getFactor(), 100);
695 }
696 }
697 return $this->getRangeMax();
698 }
699
700 public function setTolerance($tolerance): void
701 {
702 $this->tolerance = $tolerance;
703 }
704
705 public function getTolerance(): float
706 {
707 return $this->tolerance;
708 }
709
710 public function setUnit($unit): void
711 {
712 $this->unit = $unit;
713 }
714
715 public function getUnit()
716 {
717 return $this->unit;
718 }
719
720 public function setFormula($formula): void
721 {
722 $this->formula = $formula;
723 }
724
725 public function getFormula(): ?string
726 {
727 return $this->formula;
728 }
729
730 public function setPoints($points): void
731 {
732 $this->points = (float) str_replace(",", ".", $points);
733 }
734
735 public function getPoints(): float
736 {
737 return $this->points;
738 }
739
740 public function setRatingSimple($rating_simple): void
741 {
742 $this->rating_simple = $rating_simple;
743 }
744
745 public function getRatingSimple(): bool
746 {
748 }
749
750 public function setRatingSign($rating_sign): void
751 {
752 $this->rating_sign = $rating_sign;
753 }
754
755 public function getRatingSign()
756 {
757 return $this->rating_sign;
758 }
759
760 public function setRatingValue($rating_value): void
761 {
762 $this->rating_value = $rating_value;
763 }
764
765 public function getRatingValue()
766 {
767 return $this->rating_value;
768 }
769
770 public function setRatingUnit($rating_unit): void
771 {
772 $this->rating_unit = $rating_unit;
773 }
774
775 public function getRatingUnit()
776 {
777 return $this->rating_unit;
778 }
779
780 public function setPrecision($precision): void
781 {
782 $this->precision = $precision;
783 }
784
785 public function getPrecision(): int
786 {
787 return $this->precision;
788 }
789
790 public function setResultType($a_result_type): void
791 {
792 $this->result_type = $a_result_type;
793 }
794
795 public function getResultType(): int
796 {
797 return (int) $this->result_type;
798 }
799
800 public function setRangeMaxTxt($range_max_txt): void
801 {
802 $this->range_max_txt = $range_max_txt;
803 }
804
805 public function getRangeMaxTxt()
806 {
808 }
809
810 public function setRangeMinTxt($range_min_txt): void
811 {
812 $this->range_min_txt = $range_min_txt;
813 }
814
815 public function getRangeMinTxt()
816 {
818 }
819
820 public static function getResultTypeByQstId($a_qst_id, $a_result)
821 {
822 global $DIC;
823 $ilDB = $DIC['ilDB'];
824
825 $res = $ilDB->queryF(
826 '
827 SELECT result_type
828 FROM il_qpl_qst_fq_res
829 WHERE question_fi = %s
830 AND result = %s',
831 array('integer', 'text'),
832 array($a_qst_id, $a_result)
833 );
834
835 $row = $ilDB->fetchAssoc($res);
836
837 return $row['result_type'];
838 }
839
840 public static function isCoprimeFraction($numerator, $denominator): bool
841 {
842 $gcd = self::getGreatestCommonDivisor(abs($numerator), abs($denominator));
843
844 return $gcd == 1 ? true : false;
845 }
846
847 public static function convertDecimalToCoprimeFraction($decimal_value, $tolerance = 1.e-9)
848 {
849 if (empty($decimal_value)) {
850 return '';
851 }
852
853 $to_string = (string) $decimal_value;
854 $is_negative = strpos($to_string, '-') === 0;
855 if ($is_negative) {
856 $decimal_value = substr($decimal_value, 1);
857 }
858 $h1 = 1;
859 $h2 = 0;
860 $k1 = 0;
861 $k2 = 1;
862 $b = 1 / $decimal_value;
863 do {
864 $b = 1 / $b;
865 $a = floor($b);
866 $aux = $h1;
867 $h1 = $a * $h1 + $h2;
868 $h2 = $aux;
869 $aux = $k1;
870 $k1 = $a * $k1 + $k2;
871 $k2 = $aux;
872 $b = $b - $a;
873 } while ((abs($decimal_value - $h1 / $k1) > $decimal_value * $tolerance) || ($k1 < 0 || $b < 0));
874 if ($k1 == 1) {
875 $result = $h1;
876 $checkResult = $h1;
877 } else {
878 $result = "$h1/$k1";
879 $checkResult = ($h1 / $k1);
880 }
881 if ($is_negative) {
882 $result = '-' . $result;
883 $checkResult = ($h1 / $k1) * -1;
884 }
885 if ($to_string == $checkResult . '' || $checkResult . '' == $result) {
886 return $result;
887 } else {
888 return array($to_string,$result);
889 }
890 }
891
892 public static function getGreatestCommonDivisor($a, $b)
893 {
894 if ($b > 0) {
896 } else {
897 return $a;
898 }
899 }
900
901
902 public function getAvailableResultUnits($question_id): array
903 {
904 global $DIC;
905 $ilDB = $DIC['ilDB'];
906
907 $res = $ilDB->queryF(
908 '
909 SELECT * FROM il_qpl_qst_fq_res_unit
910 WHERE question_fi = %s
911 ORDER BY result',
912 array('integer'),
913 array($question_id)
914 );
915
916
917 while ($row = $ilDB->fetchAssoc($res)) {
918 $this->available_units[$row['result']][] = $row['unit_fi'] ;
919 }
920
922 }
923}
return true
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
isInTolerance($user_answer, $expected, $tolerated_percentage)
static getResultTypeByQstId($a_qst_id, $a_result)
calculateFormula($variables, $results, $question_id=0, $use_precision=true)
static isCoprimeFraction($numerator, $denominator)
getResultInfo($variables, $results, $value, $unit, $units)
static convertDecimalToCoprimeFraction($decimal_value, $tolerance=1.e-9)
findValidRandomVariables($variables, $results)
getReachedPoints($variables, $results, $value, $unit, $units)
__construct($result, $range_min, $range_max, $tolerance, $unit, $formula, $points, $precision, $rating_simple=true, $rating_sign=33, $rating_value=34, $rating_unit=33, $result_type=0)
assFormulaQuestionResult constructor
isCorrect($variables, $results, $value, $unit=null)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static _sub($left_operand, $right_operand, int $scale=50)
static _add($left_operand, $right_operand, int $scale=50)
static _div($left_operand, $right_operand, int $scale=50)
static _mul($left_operand, $right_operand, int $scale=50)
global $DIC
Definition: feed.php:28
$res
Definition: ltiservices.php:69
$i
Definition: metadata.php:41
array $details
Details for error message relating to last request processed.
Definition: System.php:109
$a
thx to https://mlocati.github.io/php-cs-fixer-configurator for the examples
$results
$lng