ILIAS  release_8 Revision v8.24
class.assFormulaQuestion.php
Go to the documentation of this file.
1<?php
2
19include_once "./Modules/Test/classes/inc.AssessmentConstants.php";
20
29{
30 private array $variables;
31 private array $results;
32 private array $resultunits;
34
35 public function __construct(
36 string $title = "",
37 string $comment = "",
38 string $author = "",
39 int $owner = -1,
40 string $question = ""
41 ) {
43 $this->variables = array();
44 $this->results = array();
45 $this->resultunits = array();
46 $this->unitrepository = new ilUnitConfigurationRepository(0);
47 }
48
49 public function clearVariables(): void
50 {
51 $this->variables = array();
52 }
53
54 public function getVariables(): array
55 {
56 return $this->variables;
57 }
58
59 public function getVariable($variable)
60 {
61 if (array_key_exists($variable, $this->variables)) {
62 return $this->variables[$variable];
63 }
64 return null;
65 }
66
67 public function addVariable($variable): void
68 {
69 $this->variables[$variable->getVariable()] = $variable;
70 }
71
72 public function clearResults(): void
73 {
74 $this->results = array();
75 }
76
77 public function getResults(): array
78 {
79 return $this->results;
80 }
81
82 public function getResult($result)
83 {
84 if (array_key_exists($result, $this->results)) {
85 return $this->results[$result];
86 }
87 return null;
88 }
89
90 public function addResult($result): void
91 {
92 $this->results[$result->getResult()] = $result;
93 }
94
95 public function addResultUnits($result, $unit_ids): void
96 {
97 $this->resultunits[$result->getResult()] = array();
98 if ((!is_object($result)) || (!is_array($unit_ids))) {
99 return;
100 }
101 foreach ($unit_ids as $id) {
102 if (is_numeric($id) && ($id > 0)) {
103 $this->resultunits[$result->getResult()][$id] = $this->getUnitrepository()->getUnit($id);
104 }
105 }
106 }
107
108 public function addResultUnit($result, $unit): void
109 {
110 if (is_object($result) && is_object($unit)) {
111 if (!array_key_exists($result->getResult(), $this->resultunits) ||
112 !is_array($this->resultunits[$result->getResult()])) {
113 $this->resultunits[$result->getResult()] = array();
114 }
115 $this->resultunits[$result->getResult()][$unit->getId()] = $unit;
116 }
117 }
118
119 public function getResultUnits(assFormulaQuestionResult $result): array
120 {
121 if (!isset($this->resultunits[$result->getResult()])) {
122 return [];
123 }
124
125 $result_units = $this->resultunits[$result->getResult()];
126
127 usort($result_units, static function (assFormulaQuestionUnit $a, assFormulaQuestionUnit $b) {
128 return $a->getSequence() <=> $b->getSequence();
129 });
130
131 return $result_units;
132 }
133
134 public function getAllResultUnits(): array
135 {
136 return $this->resultunits;
137 }
138
139 public function hasResultUnit($result, $unit_id): bool
140 {
141 if (array_key_exists($result->getResult(), $this->resultunits)) {
142 if (array_key_exists($unit_id, $this->resultunits[$result->getResult()])) {
143 return true;
144 }
145 }
146
147 return false;
148 }
149
150 public function parseQuestionText(): void
151 {
152 $this->clearResults();
153 $this->clearVariables();
154 if (preg_match_all("/(\\\$v\\d+)/ims", $this->getQuestion(), $matches)) {
155 foreach ($matches[1] as $variable) {
156 $varObj = new assFormulaQuestionVariable($variable, 0, 0, null, 0);
157 $this->addVariable($varObj);
158 }
159 }
160
161 if (preg_match_all("/(\\\$r\\d+)/ims", $this->getQuestion(), $rmatches)) {
162 foreach ($rmatches[1] as $result) {
163 $resObj = new assFormulaQuestionResult($result, null, null, 0, -1, null, 1, 1, true);
164 $this->addResult($resObj);
165 }
166 }
167 }
168
169 public function checkForDuplicateVariables(): bool
170 {
171 if (preg_match_all("/(\\\$v\\d+)/ims", $this->getQuestion(), $matches)) {
172 if ((count(array_unique($matches[1]))) != count($matches[1])) {
173 return false;
174 }
175 }
176 return true;
177 }
178
179 public function checkForDuplicateResults(): bool
180 {
181 if (preg_match_all("/(\\\$r\\d+)/ims", $this->getQuestion(), $rmatches)) {
182 if ((count(array_unique($rmatches[1]))) != count($rmatches[1])) {
183 return false;
184 }
185 }
186 return true;
187 }
188
193 public function fetchAllResults($questionText): array
194 {
195 $resObjects = array();
196 $matches = null;
197
198 if (preg_match_all("/(\\\$r\\d+)/ims", $questionText, $matches)) {
199 foreach ($matches[1] as $resultKey) {
200 $resObjects[] = $this->getResult($resultKey);
201 }
202 }
203
204 return $resObjects;
205 }
206
211 public function fetchAllVariables($questionText): array
212 {
213 $varObjects = array();
214 $matches = null;
215
216 if (preg_match_all("/(\\\$v\\d+)/ims", $questionText, $matches)) {
217 foreach ($matches[1] as $variableKey) {
218 $varObjects[] = $this->getVariable($variableKey);
219 }
220 }
221
222 return $varObjects;
223 }
224
229 public function hasRequiredVariableSolutionValues(array $userSolution): bool
230 {
231 foreach ($this->fetchAllVariables($this->getQuestion()) as $varObj) {
232 if (!isset($userSolution[$varObj->getVariable()])) {
233 return false;
234 }
235
236 if (!strlen($userSolution[$varObj->getVariable()])) {
237 return false;
238 }
239 }
240
241 return true;
242 }
243
247 public function getInitialVariableSolutionValues(): array
248 {
249 foreach ($this->fetchAllResults($this->getQuestion()) as $resObj) {
250 $resObj->findValidRandomVariables($this->getVariables(), $this->getResults());
251 }
252
253 $variableSolutionValues = array();
254
255 foreach ($this->fetchAllVariables($this->getQuestion()) as $varObj) {
256 $variableSolutionValues[$varObj->getVariable()] = $varObj->getValue();
257 }
258
259 return $variableSolutionValues;
260 }
261
267 public function substituteVariables(array $userdata, bool $graphicalOutput = false, bool $forsolution = false, bool $result_output = false, array $correctness_icons = [])
268 {
269 if ((count($this->results) == 0) && (count($this->variables) == 0)) {
270 return false;
271 }
272
273 $text = $this->getQuestion();
274
275 foreach ($this->fetchAllVariables($this->getQuestion()) as $varObj) {
276 if (isset($userdata[$varObj->getVariable()]) && strlen($userdata[$varObj->getVariable()])) {
277 $varObj->setValue($userdata[$varObj->getVariable()]);
278 }
279
280 $unit = (is_object($varObj->getUnit())) ? $varObj->getUnit()->getUnit() : "";
281 $val = (strlen($varObj->getValue()) > 8) ? strtoupper(sprintf("%e", $varObj->getValue())) : $varObj->getValue();
282
283 $text = preg_replace("/\\$" . substr($varObj->getVariable(), 1) . "(?![0-9]+)/", $val . " " . $unit . "\\1", $text);
284 }
285
286 $text = $this->purifyAndPrepareTextAreaOutput($text);
287
288 if (preg_match_all("/(\\\$r\\d+)/ims", $this->getQuestion(), $rmatches)) {
289 foreach ($rmatches[1] as $result) {
290 $resObj = $this->getResult($result);
291 $value = "";
292 $frac_helper = '';
293 $userdata[$result]['result_type'] = $resObj->getResultType();
294 $is_frac = false;
295 if (
296 $resObj->getResultType() == assFormulaQuestionResult::RESULT_FRAC ||
297 $resObj->getResultType() == assFormulaQuestionResult::RESULT_CO_FRAC
298 ) {
299 $is_frac = true;
300 }
301 if (is_array($userdata) &&
302 isset($userdata[$result]) &&
303 isset($userdata[$result]["value"])) {
304
305 $input = $this->generateResultInputHTML($result, $userdata[$result]["value"], $forsolution);
306 } elseif ($forsolution) {
307 $value = '';
308 if (!is_array($userdata)) {
309 $value = $resObj->calculateFormula($this->getVariables(), $this->getResults(), parent::getId());
310 $value = sprintf("%." . $resObj->getPrecision() . "f", $value);
311 }
312
313 if ($is_frac) {
315 if (is_array($value)) {
316 $frac_helper = $value[1];
317 $value = $value[0];
318 }
319 }
320
321 $input = $this->generateResultInputHTML($result, $value, true);
322 } else {
323 $input = $this->generateResultInputHTML($result, '', false);
324 }
325
326 $units = "";
327 $result_units = $this->getResultUnits($resObj);
328 if (count($result_units) > 0) {
329 if ($forsolution) {
330 if (is_array($userdata)) {
331 foreach ($result_units as $unit) {
332 if (isset($userdata[$result]["unit"]) && $userdata[$result]["unit"] == $unit->getId()) {
333 $units = $unit->getUnit();
334 }
335 }
336 } else {
337 if ($resObj->getUnit()) {
338 $units = $resObj->getUnit()->getUnit();
339 }
340 }
341 } else {
342 $units = '<select name="result_' . $result . '_unit">';
343 $units .= '<option value="-1">' . $this->lng->txt("select_unit") . '</option>';
344 foreach ($result_units as $unit) {
345 $units .= '<option value="' . $unit->getId() . '"';
346 if (array_key_exists($result, $userdata) &&
347 is_array($userdata[$result]) &&
348 array_key_exists('unit', $userdata[$result])) {
349 if ($userdata[$result]["unit"] == $unit->getId()) {
350 $units .= ' selected="selected"';
351 }
352 }
353 $units .= '>' . $unit->getUnit() . '</option>';
354 }
355 $units .= '</select>';
356 }
357 } else {
358 $units = "";
359 }
360 switch ($resObj->getResultType()) {
362 $units .= ' ' . $this->lng->txt('expected_result_type') . ': ' . $this->lng->txt('result_dec');
363 break;
365 if ($frac_helper !== '') {
366 $units .= ' &asymp; ' . $frac_helper . ', ';
367 } elseif (is_array($userdata) &&
368 array_key_exists($result, $userdata) &&
369 array_key_exists('frac_helper', $userdata[$result]) &&
370 is_string($userdata[$result]["frac_helper"])) {
371 if (!preg_match('-/-', $value)) {
372 $units .= ' &asymp; ' . $userdata[$result]["frac_helper"] . ', ';
373 }
374 }
375 $units .= ' ' . $this->lng->txt('expected_result_type') . ': ' . $this->lng->txt('result_frac');
376 break;
378 if ($frac_helper !== '') {
379 $units .= ' &asymp; ' . $frac_helper . ', ';
380 } elseif (is_array($userdata) && isset($userdata[$result]) && isset($userdata[$result]["frac_helper"]) && $userdata[$result]["frac_helper"] !== '') {
381 if (!preg_match('-/-', $value)) {
382 $units .= ' &asymp; ' . $userdata[$result]["frac_helper"] . ', ';
383 }
384 }
385 $units .= ' ' . $this->lng->txt('expected_result_type') . ': ' . $this->lng->txt('result_co_frac');
386 break;
388 break;
389 }
390 $checkSign = "";
391 if ($graphicalOutput) {
392 $resunit = null;
393 $user_value = '';
394 if (is_array($userdata) &&
395 array_key_exists($result, $userdata) &&
396 is_array($userdata[$result])) {
397 if (array_key_exists('unit', $userdata[$result]) && $userdata[$result]["unit"] > 0) {
398 $resunit = $this->getUnitrepository()->getUnit($userdata[$result]["unit"]);
399 }
400
401 if (isset($userdata[$result]["value"])) {
402 $user_value = $userdata[$result]["value"];
403 }
404 }
405
406 $template = new ilTemplate("tpl.il_as_qpl_formulaquestion_output_solution_image.html", true, true, 'Modules/TestQuestionPool');
407
408 $correctness_icon = $correctness_icons['not_correct'];
409 if ($resObj->isCorrect($this->getVariables(), $this->getResults(), $user_value, $resunit)) {
410 $correctness_icon = $correctness_icons['correct'];
411 }
412 $template->setCurrentBlock("icon_ok");
413 $template->setVariable("ICON_OK", $correctness_icon);
414 $template->parseCurrentBlock();
415
416 $checkSign = $template->get();
417 }
418 $resultOutput = "";
419 if ($result_output) {
420 $template = new ilTemplate("tpl.il_as_qpl_formulaquestion_output_solution_result.html", true, true, 'Modules/TestQuestionPool');
421
422 if (is_array($userdata) &&
423 array_key_exists($resObj->getResult(), $userdata) &&
424 array_key_exists('value', $userdata[$resObj->getResult()])) {
425 $found = $resObj->getResultInfo(
426 $this->getVariables(),
427 $this->getResults(),
428 $userdata[$resObj->getResult()]["value"],
429 $userdata[$resObj->getResult()]["unit"] ?? null,
430 $this->getUnitrepository()->getUnits()
431 );
432 } else {
433 $found = $resObj->getResultInfo(
434 $this->getVariables(),
435 $this->getResults(),
436 $resObj->calculateFormula($this->getVariables(), $this->getResults(), parent::getId()),
437 is_object($resObj->getUnit()) ? $resObj->getUnit()->getId() : null,
438 $this->getUnitrepository()->getUnits()
439 );
440 }
441 $resulttext = "(";
442 if ($resObj->getRatingSimple()) {
443 if ($frac_helper) {
444 $resulttext .= "n/a";
445 } else {
446 $resulttext .= $found['points'] . " " . (($found['points'] == 1) ? $this->lng->txt('point') : $this->lng->txt('points'));
447 }
448 } else {
449 $resulttext .= $this->lng->txt("rated_sign") . " " . (($found['sign']) ? $found['sign'] : 0) . " " . (($found['sign'] == 1) ? $this->lng->txt('point') : $this->lng->txt('points')) . ", ";
450 $resulttext .= $this->lng->txt("rated_value") . " " . (($found['value']) ? $found['value'] : 0) . " " . (($found['value'] == 1) ? $this->lng->txt('point') : $this->lng->txt('points')) . ", ";
451 $resulttext .= $this->lng->txt("rated_unit") . " " . (($found['unit']) ? $found['unit'] : 0) . " " . (($found['unit'] == 1) ? $this->lng->txt('point') : $this->lng->txt('points'));
452 }
453
454 $resulttext .= ")";
455 $template->setVariable("RESULT_OUTPUT", $resulttext);
456
457 $resultOutput = $template->get();
458 }
459 $text = preg_replace("/\\\$" . substr($result, 1) . "(?![0-9]+)/", $input . " " . $units . " " . $checkSign . " " . $resultOutput . " " . "\\1", $text);
460 }
461 }
462 return $text;
463 }
464
465 protected function generateResultInputHTML(string $result_key, string $result_value, bool $forsolution): string
466 {
467 if ($forsolution) {
468 return '<span class="ilc_qinput_TextInput solutionbox">'
470 . '</span>';
471 }
472 $input = '<input class="ilc_qinput_TextInput" type="text"';
473 $input .= 'spellcheck="false" autocomplete="off" autocorrect="off" autocapitalize="off"';
474 $input .= 'name="result_' . $result_key . '"';
475 $input .= ' value="' . $result_value . '"/>';
476 return $input;
477 }
478
485 public function canUseAdvancedRating($result): bool
486 {
487 $result_units = $this->getResultUnits($result);
488 $resultunit = $result->getUnit();
489 $similar_units = 0;
490 foreach ($result_units as $unit) {
491 if (is_object($resultunit)) {
492 if ($resultunit->getId() != $unit->getId()) {
493 if ($resultunit->getBaseUnit() && $unit->getBaseUnit()) {
494 if ($resultunit->getBaseUnit() == $unit->getBaseUnit()) {
495 return false;
496 }
497 }
498 if ($resultunit->getBaseUnit()) {
499 if ($resultunit->getBaseUnit() == $unit->getId()) {
500 return false;
501 }
502 }
503 if ($unit->getBaseUnit()) {
504 if ($unit->getBaseUnit() == $resultunit->getId()) {
505 return false;
506 }
507 }
508 }
509 }
510 }
511 return true;
512 }
513
518 public function isComplete(): bool
519 {
520 if (($this->title) and ($this->author) and ($this->question) and ($this->getMaximumPoints() > 0)) {
521 return true;
522 } else {
523 return false;
524 }
525 }
526
531 public function saveToDb($original_id = ""): void
532 {
533 global $DIC;
534 $ilDB = $DIC['ilDB'];
535
536 if ($original_id == "") {
537 $this->saveQuestionDataToDb();
538 } else {
540 }
541
542 // save variables
543 $affectedRows = $ilDB->manipulateF(
544 "
545 DELETE FROM il_qpl_qst_fq_var
546 WHERE question_fi = %s",
547 array("integer"),
548 array($this->getId())
549 );
550
551 foreach ($this->variables as $variable) {
552 $next_id = $ilDB->nextId('il_qpl_qst_fq_var');
553 $ilDB->insert(
554 'il_qpl_qst_fq_var',
555 array(
556 'variable_id' => array('integer', $next_id),
557 'question_fi' => array('integer', $this->getId()),
558 'variable' => array('text', $variable->getVariable()),
559 'range_min' => array('float', ((strlen($variable->getRangeMin())) ? $variable->getRangeMin() : 0.0)),
560 'range_max' => array('float', ((strlen($variable->getRangeMax())) ? $variable->getRangeMax() : 0.0)),
561 'unit_fi' => array('integer', (is_object($variable->getUnit()) ? (int) $variable->getUnit()->getId() : 0)),
562 'varprecision' => array('integer', (int) $variable->getPrecision()),
563 'intprecision' => array('integer', (int) $variable->getIntprecision()),
564 'range_min_txt' => array('text', $variable->getRangeMinTxt()),
565 'range_max_txt' => array('text', $variable->getRangeMaxTxt())
566 )
567 );
568 }
569 // save results
570 $affectedRows = $ilDB->manipulateF(
571 "DELETE FROM il_qpl_qst_fq_res WHERE question_fi = %s",
572 array("integer"),
573 array($this->getId())
574 );
575
576 foreach ($this->results as $result) {
577 $next_id = $ilDB->nextId('il_qpl_qst_fq_res');
578 if (is_object($result->getUnit())) {
579 $tmp_result_unit = $result->getUnit()->getId();
580 } else {
581 $tmp_result_unit = null;
582 }
583
584 $formula = str_replace(",", ".", $result->getFormula());
585
586 $ilDB->insert("il_qpl_qst_fq_res", array(
587 "result_id" => array("integer", $next_id),
588 "question_fi" => array("integer", $this->getId()),
589 "result" => array("text", $result->getResult()),
590 "range_min" => array("float", ((strlen($result->getRangeMin())) ? $result->getRangeMin() : 0)),
591 "range_max" => array("float", ((strlen($result->getRangeMax())) ? $result->getRangeMax() : 0)),
592 "tolerance" => array("float", ((strlen($result->getTolerance())) ? $result->getTolerance() : 0)),
593 "unit_fi" => array("integer", (int) $tmp_result_unit),
594 "formula" => array("clob", $formula),
595 "resprecision" => array("integer", $result->getPrecision()),
596 "rating_simple" => array("integer", ($result->getRatingSimple()) ? 1 : 0),
597 "rating_sign" => array("float", ($result->getRatingSimple()) ? 0 : $result->getRatingSign()),
598 "rating_value" => array("float", ($result->getRatingSimple()) ? 0 : $result->getRatingValue()),
599 "rating_unit" => array("float", ($result->getRatingSimple()) ? 0 : $result->getRatingUnit()),
600 "points" => array("float", $result->getPoints()),
601 "result_type" => array('integer', (int) $result->getResultType()),
602 "range_min_txt" => array("text", $result->getRangeMinTxt()),
603 "range_max_txt" => array("text", $result->getRangeMaxTxt())
604
605 ));
606 }
607 // save result units
608 $affectedRows = $ilDB->manipulateF(
609 "DELETE FROM il_qpl_qst_fq_res_unit WHERE question_fi = %s",
610 array("integer"),
611 array($this->getId())
612 );
613 foreach ($this->results as $result) {
614 foreach ($this->getResultUnits($result) as $unit) {
615 $next_id = $ilDB->nextId('il_qpl_qst_fq_res_unit');
616 $affectedRows = $ilDB->manipulateF(
617 "INSERT INTO il_qpl_qst_fq_res_unit (result_unit_id, question_fi, result, unit_fi) VALUES (%s, %s, %s, %s)",
618 array('integer', 'integer', 'text', 'integer'),
619 array(
620 $next_id,
621 $this->getId(),
622 $result->getResult(),
623 $unit->getId()
624 )
625 );
626 }
627 }
628
629 parent::saveToDb();
630 }
631
636 public function loadFromDb($question_id): void
637 {
638 global $DIC;
639 $ilDB = $DIC['ilDB'];
640
641 $result = $ilDB->queryF(
642 "SELECT qpl_questions.* FROM qpl_questions WHERE question_id = %s",
643 array('integer'),
644 array($question_id)
645 );
646 if ($result->numRows() == 1) {
647 $data = $ilDB->fetchAssoc($result);
648 $this->setId($question_id);
649 $this->setTitle((string) $data["title"]);
650 $this->setComment((string) $data["description"]);
651 //$this->setSuggestedSolution($data["solution_hint"]);
652 $this->setPoints($data['points']);
653 $this->setOriginalId($data["original_id"]);
654 $this->setObjId($data["obj_fi"]);
655 $this->setAuthor($data["author"]);
656 $this->setOwner($data["owner"]);
657
658 try {
659 $this->setLifecycle(ilAssQuestionLifecycle::getInstance($data['lifecycle']));
662 }
663
664 try {
665 $this->setAdditionalContentEditingMode($data['add_cont_edit_mode']);
667 }
668
669 $this->unitrepository = new ilUnitConfigurationRepository($question_id);
670
671 include_once("./Services/RTE/classes/class.ilRTE.php");
672 $this->setQuestion(ilRTE::_replaceMediaObjectImageSrc((string) $data["question_text"], 1));
673
674 // load variables
675 $result = $ilDB->queryF(
676 "SELECT * FROM il_qpl_qst_fq_var WHERE question_fi = %s",
677 array('integer'),
678 array($question_id)
679 );
680 if ($result->numRows() > 0) {
681 while ($data = $ilDB->fetchAssoc($result)) {
682 $varObj = new assFormulaQuestionVariable($data["variable"], $data["range_min"], $data["range_max"], $this->getUnitrepository()->getUnit($data["unit_fi"]), $data["varprecision"], $data["intprecision"]);
683 $varObj->setRangeMinTxt($data['range_min_txt']);
684 $varObj->setRangeMaxTxt($data['range_max_txt']);
685 $this->addVariable($varObj);
686 }
687 }
688 // load results
689 $result = $ilDB->queryF(
690 "SELECT * FROM il_qpl_qst_fq_res WHERE question_fi = %s",
691 array('integer'),
692 array($question_id)
693 );
694 if ($result->numRows() > 0) {
695 while ($data = $ilDB->fetchAssoc($result)) {
696 $resObj = new assFormulaQuestionResult($data["result"], $data["range_min"], $data["range_max"], $data["tolerance"], $this->getUnitrepository()->getUnit($data["unit_fi"]), $data["formula"], $data["points"], $data["resprecision"], $data["rating_simple"], $data["rating_sign"], $data["rating_value"], $data["rating_unit"]);
697 $resObj->setResultType($data['result_type']);
698 $resObj->setRangeMinTxt($data['range_min_txt']);
699 $resObj->setRangeMaxTxt($data['range_max_txt']);
700 $this->addResult($resObj);
701 }
702 }
703
704 // load result units
705 $result = $ilDB->queryF(
706 "SELECT * FROM il_qpl_qst_fq_res_unit WHERE question_fi = %s",
707 array('integer'),
708 array($question_id)
709 );
710 if ($result->numRows() > 0) {
711 while ($data = $ilDB->fetchAssoc($result)) {
712 $unit = $this->getUnitrepository()->getUnit($data["unit_fi"]);
713 $resObj = $this->getResult($data["result"]);
714 $this->addResultUnit($resObj, $unit);
715 }
716 }
717 }
718 parent::loadFromDb($question_id);
719 }
720
725 public function duplicate(bool $for_test = true, string $title = "", string $author = "", string $owner = "", $testObjId = null): int
726 {
727 if ($this->id <= 0) {
728 // The question has not been saved. It cannot be duplicated
729 return -1;
730 }
731 // duplicate the question in database
732 $this_id = $this->getId();
733 $thisObjId = $this->getObjId();
734
735 $clone = $this;
736 include_once("./Modules/TestQuestionPool/classes/class.assQuestion.php");
738 $clone->id = -1;
739
740 if ((int) $testObjId > 0) {
741 $clone->setObjId($testObjId);
742 }
743
744 if ($title) {
745 $clone->setTitle($title);
746 }
747
748 if ($author) {
749 $clone->setAuthor($author);
750 }
751 if ($owner) {
752 $clone->setOwner($owner);
753 }
754
755 if ($for_test) {
756 $clone->saveToDb($original_id);
757 } else {
758 $clone->saveToDb();
759 }
760
761 $clone->unitrepository->cloneUnits($this_id, $clone->getId());
762
763 // copy question page content
764 $clone->copyPageOfQuestion($this_id);
765 // copy XHTML media objects
766 $clone->copyXHTMLMediaObjectsOfQuestion($this_id);
767 $clone->onDuplicate($thisObjId, $this_id, $clone->getObjId(), $clone->getId());
768
769 return $clone->id;
770 }
771
776 public function copyObject($target_questionpool_id, $title = ""): int
777 {
778 if ($this->getId() <= 0) {
779 throw new RuntimeException('The question has not been saved. It cannot be duplicated');
780 }
781 // duplicate the question in database
782 $clone = $this;
783 include_once("./Modules/TestQuestionPool/classes/class.assQuestion.php");
785 $clone->id = -1;
786 $source_questionpool_id = $this->getObjId();
787 $clone->setObjId($target_questionpool_id);
788 if ($title) {
789 $clone->setTitle($title);
790 }
791 $clone->saveToDb();
792
793 $clone->unitrepository->cloneUnits($original_id, $clone->getId());
794
795 // copy question page content
796 $clone->copyPageOfQuestion($original_id);
797 // copy XHTML media objects
798 $clone->copyXHTMLMediaObjectsOfQuestion($original_id);
799
800 $clone->onCopy($source_questionpool_id, $original_id, $clone->getObjId(), $clone->getId());
801
802 return $clone->id;
803 }
804
805 public function createNewOriginalFromThisDuplicate($targetParentId, $targetQuestionTitle = ""): int
806 {
807 if ($this->getId() <= 0) {
808 throw new RuntimeException('The question has not been saved. It cannot be duplicated');
809 }
810
811 include_once("./Modules/TestQuestionPool/classes/class.assQuestion.php");
812
813 $sourceQuestionId = $this->id;
814 $sourceParentId = $this->getObjId();
815
816 // duplicate the question in database
817 $clone = $this;
818 $clone->id = -1;
819
820 $clone->setObjId($targetParentId);
821
822 if ($targetQuestionTitle) {
823 $clone->setTitle($targetQuestionTitle);
824 }
825
826 $clone->saveToDb();
827 // copy question page content
828 $clone->copyPageOfQuestion($sourceQuestionId);
829 // copy XHTML media objects
830 $clone->copyXHTMLMediaObjectsOfQuestion($sourceQuestionId);
831
832 $clone->onCopy($sourceParentId, $sourceQuestionId, $clone->getObjId(), $clone->getId());
833
834 return $clone->id;
835 }
836
841 public function getMaximumPoints(): float
842 {
843 $points = 0;
844 foreach ($this->results as $result) {
845 $points += $result->getPoints();
846 }
847 return $points;
848 }
849
858 public function calculateReachedPoints($active_id, $pass = null, $authorizedSolution = true, $returndetails = false)
859 {
860 if (is_null($pass)) {
861 $pass = $this->getSolutionMaxPass($active_id);
862 }
863 $solutions = $this->getSolutionValues($active_id, $pass, $authorizedSolution);
864 $user_solution = array();
865 foreach ($solutions as $idx => $solution_value) {
866 if (preg_match("/^(\\\$v\\d+)$/", $solution_value["value1"], $matches)) {
867 $user_solution[$matches[1]] = $solution_value["value2"];
868 $varObj = $this->getVariable($solution_value["value1"]);
869 $varObj->setValue($solution_value["value2"]);
870 } elseif (preg_match("/^(\\\$r\\d+)$/", $solution_value["value1"], $matches)) {
871 if (!array_key_exists($matches[1], $user_solution)) {
872 $user_solution[$matches[1]] = array();
873 }
874 $user_solution[$matches[1]]["value"] = $solution_value["value2"];
875 } elseif (preg_match("/^(\\\$r\\d+)_unit$/", $solution_value["value1"], $matches)) {
876 if (!array_key_exists($matches[1], $user_solution)) {
877 $user_solution[$matches[1]] = array();
878 }
879 $user_solution[$matches[1]]["unit"] = $solution_value["value2"];
880 }
881 }
882 //vd($this->getResults());
883 $points = 0;
884 foreach ($this->getResults() as $result) {
885 //vd($user_solution[$result->getResult()]["value"]);
886 $points += $result->getReachedPoints(
887 $this->getVariables(),
888 $this->getResults(),
889 $user_solution[$result->getResult()]["value"] ?? '',
890 $user_solution[$result->getResult()]["unit"] ?? '',
891 $this->unitrepository->getUnits()
892 );
893 }
894
895 return $points;
896 }
897
899 {
900 $user_solution = $previewSession->getParticipantsSolution();
901
902 $points = 0;
903 foreach ($this->getResults() as $result) {
904 $v = isset($user_solution[$result->getResult()]) ? $user_solution[$result->getResult()] : null;
905 $u = isset($user_solution[$result->getResult() . '_unit']) ? $user_solution[$result->getResult() . '_unit'] : null;
906
907 $points += $result->getReachedPoints(
908 $this->getVariables(),
909 $this->getResults(),
910 $v,
911 $u,
912 $this->unitrepository->getUnits()
913 );
914 }
915
916 $reachedPoints = $this->deductHintPointsFromReachedPoints($previewSession, $points);
917
918 return $this->ensureNonNegativePoints($reachedPoints);
919 }
920
921 protected function isValidSolutionResultValue($submittedValue): bool
922 {
923 $submittedValue = str_replace(',', '.', $submittedValue);
924
925 if (is_numeric($submittedValue)) {
926 return true;
927 }
928
929 if (preg_match('/^[-+]{0,1}\d+\/\d+$/', $submittedValue)) {
930 return true;
931 }
932
933 return false;
934 }
935
943 public function saveWorkingData($active_id, $pass = null, $authorized = true): bool
944 {
945 global $DIC;
946 $ilDB = $DIC['ilDB'];
947
948 if (is_null($pass)) {
949 include_once "./Modules/Test/classes/class.ilObjTest.php";
950 $pass = ilObjTest::_getPass($active_id);
951 }
952
953 $entered_values = false;
954
955 $this->getProcessLocker()->executeUserSolutionUpdateLockOperation(function () use (&$entered_values, $ilDB, $active_id, $pass, $authorized) {
956 $solutionSubmit = $this->getSolutionSubmit();
957 foreach ($solutionSubmit as $key => $value) {
958 $matches = null;
959 if (preg_match("/^result_(\\\$r\\d+)$/", $key, $matches)) {
960 if (strlen($value)) {
961 $entered_values = true;
962 }
963
964 $queryResult = "SELECT solution_id FROM tst_solutions WHERE active_fi = %s AND pass = %s AND question_fi = %s AND authorized = %s AND " . $ilDB->like('value1', 'clob', $matches[1]);
965
966 if ($this->getStep() !== null) {
967 $queryResult .= " AND step = " . $ilDB->quote((int) $this->getStep(), 'integer') . " ";
968 }
969
970 $result = $ilDB->queryF(
971 $queryResult,
972 array('integer', 'integer', 'integer', 'integer'),
973 array($active_id, $pass, $this->getId(), (int) $authorized)
974 );
975 if ($result->numRows()) {
976 while ($row = $ilDB->fetchAssoc($result)) {
977 $ilDB->manipulateF(
978 "DELETE FROM tst_solutions WHERE solution_id = %s AND authorized = %s",
979 array('integer', 'integer'),
980 array($row['solution_id'], (int) $authorized)
981 );
982 }
983 }
984
985 $this->saveCurrentSolution($active_id, $pass, $matches[1], str_replace(",", ".", $value), $authorized);
986 } elseif (preg_match("/^result_(\\\$r\\d+)_unit$/", $key, $matches)) {
987 $queryResultUnit = "SELECT solution_id FROM tst_solutions WHERE active_fi = %s AND pass = %s AND question_fi = %s AND authorized = %s AND " . $ilDB->like('value1', 'clob', $matches[1] . "_unit");
988
989 if ($this->getStep() !== null) {
990 $queryResultUnit .= " AND step = " . $ilDB->quote((int) $this->getStep(), 'integer') . " ";
991 }
992
993 $result = $ilDB->queryF(
994 $queryResultUnit,
995 array('integer', 'integer', 'integer', 'integer'),
996 array($active_id, $pass, $this->getId(), (int) $authorized)
997 );
998 if ($result->numRows()) {
999 while ($row = $ilDB->fetchAssoc($result)) {
1000 $ilDB->manipulateF(
1001 "DELETE FROM tst_solutions WHERE solution_id = %s AND authorized = %s",
1002 array('integer', 'integer'),
1003 array($row['solution_id'], (int) $authorized)
1004 );
1005 }
1006 }
1007
1008 $this->saveCurrentSolution($active_id, $pass, $matches[1] . "_unit", $value, $authorized);
1009 }
1010 }
1011 });
1012
1013 if ($entered_values) {
1014 include_once("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
1016 assQuestion::logAction($this->lng->txtlng(
1017 "assessment",
1018 "log_user_entered_values",
1020 ), $active_id, $this->getId());
1021 }
1022 } else {
1023 include_once("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
1025 assQuestion::logAction($this->lng->txtlng(
1026 "assessment",
1027 "log_user_not_entered_values",
1029 ), $active_id, $this->getId());
1030 }
1031 }
1032
1033 return true;
1034 }
1035
1036 // fau: testNav - overridden function lookupForExistingSolutions (specific for formula question: don't lookup variables)
1043 public function lookupForExistingSolutions(int $activeId, int $pass): array
1044 {
1045 global $DIC;
1046 $ilDB = $DIC['ilDB'];
1047
1048 $return = array(
1049 'authorized' => false,
1050 'intermediate' => false
1051 );
1052
1053 $query = "
1054 SELECT authorized, COUNT(*) cnt
1055 FROM tst_solutions
1056 WHERE active_fi = " . $ilDB->quote($activeId, 'integer') . "
1057 AND question_fi = " . $ilDB->quote($this->getId(), 'integer') . "
1058 AND pass = " . $ilDB->quote($pass, 'integer') . "
1059 AND value1 like '\$r%'
1060 AND value2 is not null
1061 AND value2 <> ''
1062 ";
1063
1064 if ($this->getStep() !== null) {
1065 $query .= " AND step = " . $ilDB->quote((int) $this->getStep(), 'integer') . " ";
1066 }
1067
1068 $query .= "
1069 GROUP BY authorized
1070 ";
1071
1072 $result = $ilDB->query($query);
1073
1074 while ($row = $ilDB->fetchAssoc($result)) {
1075 if ($row['authorized']) {
1076 $return['authorized'] = $row['cnt'] > 0;
1077 } else {
1078 $return['intermediate'] = $row['cnt'] > 0;
1079 }
1080 }
1081 return $return;
1082 }
1083 // fau.
1084
1085 // fau: testNav - Remove an existing solution (specific for formula question: don't delete variables)
1092 public function removeExistingSolutions(int $activeId, int $pass): int
1093 {
1094 global $DIC;
1095 $ilDB = $DIC['ilDB'];
1096
1097 $query = "
1098 DELETE FROM tst_solutions
1099 WHERE active_fi = " . $ilDB->quote($activeId, 'integer') . "
1100 AND question_fi = " . $ilDB->quote($this->getId(), 'integer') . "
1101 AND pass = " . $ilDB->quote($pass, 'integer') . "
1102 AND value1 like '\$r%'
1103 ";
1104
1105 if ($this->getStep() !== null) {
1106 $query .= " AND step = " . $ilDB->quote((int) $this->getStep(), 'integer') . " ";
1107 }
1108
1109 return $ilDB->manipulate($query);
1110 }
1111 // fau.
1112
1113 protected function savePreviewData(ilAssQuestionPreviewSession $previewSession): void
1114 {
1115 $userSolution = $previewSession->getParticipantsSolution();
1116
1117 foreach ($this->getSolutionSubmit() as $key => $val) {
1118 $matches = null;
1119
1120 if (preg_match("/^result_(\\\$r\\d+)$/", $key, $matches)) {
1121 $userSolution[$matches[1]] = $val;
1122 } elseif (preg_match("/^result_(\\\$r\\d+)_unit$/", $key, $matches)) {
1123 $userSolution[$matches[1] . "_unit"] = $val;
1124 }
1125 }
1126
1127 $previewSession->setParticipantsSolution($userSolution);
1128 }
1129
1134 public function getQuestionType(): string
1135 {
1136 return "assFormulaQuestion";
1137 }
1138
1143 public function getAdditionalTableName(): string
1144 {
1145 return "";
1146 }
1147
1152 public function getAnswerTableName(): string
1153 {
1154 return "";
1155 }
1156
1162 public function deleteAnswers($question_id): void
1163 {
1164 global $DIC;
1165 $ilDB = $DIC['ilDB'];
1166
1167 $affectedRows = $ilDB->manipulateF(
1168 "DELETE FROM il_qpl_qst_fq_var WHERE question_fi = %s",
1169 array('integer'),
1170 array($question_id)
1171 );
1172
1173 $affectedRows = $ilDB->manipulateF(
1174 "DELETE FROM il_qpl_qst_fq_res WHERE question_fi = %s",
1175 array('integer'),
1176 array($question_id)
1177 );
1178
1179 $affectedRows = $ilDB->manipulateF(
1180 "DELETE FROM il_qpl_qst_fq_res_unit WHERE question_fi = %s",
1181 array('integer'),
1182 array($question_id)
1183 );
1184
1185 $affectedRows = $ilDB->manipulateF(
1186 "DELETE FROM il_qpl_qst_fq_ucat WHERE question_fi = %s",
1187 array('integer'),
1188 array($question_id)
1189 );
1190
1191 $affectedRows = $ilDB->manipulateF(
1192 "DELETE FROM il_qpl_qst_fq_unit WHERE question_fi = %s",
1193 array('integer'),
1194 array($question_id)
1195 );
1196 }
1197
1202 public function getRTETextWithMediaObjects(): string
1203 {
1204 $text = parent::getRTETextWithMediaObjects();
1205 return $text;
1206 }
1207
1211 public function setExportDetailsXLS(ilAssExcelFormatHelper $worksheet, int $startrow, int $active_id, int $pass): int
1212 {
1213 parent::setExportDetailsXLS($worksheet, $startrow, $active_id, $pass);
1214
1215 $solution = $this->getSolutionValues($active_id, $pass);
1216
1217 $i = 1;
1218 foreach ($solution as $solutionvalue) {
1219 $worksheet->setCell($startrow + $i, 0, $solutionvalue["value1"]);
1220 $worksheet->setBold($worksheet->getColumnCoord(0) . ($startrow + $i));
1221 if (strpos($solutionvalue["value1"], "_unit")) {
1222 $unit = $this->getUnitrepository()->getUnit($solutionvalue["value2"]);
1223 if (is_object($unit)) {
1224 $worksheet->setCell($startrow + $i, 2, $unit->getUnit());
1225 }
1226 } else {
1227 $worksheet->setCell($startrow + $i, 2, $solutionvalue["value2"]);
1228 }
1229 if (preg_match("/(\\\$v\\d+)/", $solutionvalue["value1"], $matches)) {
1230 $var = $this->getVariable($solutionvalue["value1"]);
1231 if (is_object($var) && (is_object($var->getUnit()))) {
1232 $worksheet->setCell($startrow + $i, 3, $var->getUnit()->getUnit());
1233 }
1234 }
1235 $i++;
1236 }
1237
1238 return $startrow + $i + 1;
1239 }
1240
1246 public function getBestSolution($solutions): array
1247 {
1248 $user_solution = array();
1249
1250 foreach ($solutions as $idx => $solution_value) {
1251 if (preg_match("/^(\\\$v\\d+)$/", $solution_value["value1"], $matches)) {
1252 $user_solution[$matches[1]] = $solution_value["value2"];
1253 $varObj = $this->getVariable($matches[1]);
1254 $varObj->setValue($solution_value["value2"]);
1255 } elseif (preg_match("/^(\\\$r\\d+)$/", $solution_value["value1"], $matches)) {
1256 if (!array_key_exists($matches[1], $user_solution)) {
1257 $user_solution[$matches[1]] = array();
1258 }
1259 $user_solution[$matches[1]]["value"] = $solution_value["value2"];
1260 } elseif (preg_match("/^(\\\$r\\d+)_unit$/", $solution_value["value1"], $matches)) {
1261 if (!array_key_exists($matches[1], $user_solution)) {
1262 $user_solution[$matches[1]] = array();
1263 }
1264 $user_solution[$matches[1]]["unit"] = $solution_value["value2"];
1265 }
1266 }
1267 foreach ($this->getResults() as $result) {
1268 $resVal = $result->calculateFormula($this->getVariables(), $this->getResults(), parent::getId(), false);
1269
1270 if (is_object($result->getUnit())) {
1271 $user_solution[$result->getResult()]["unit"] = $result->getUnit()->getId();
1272 $user_solution[$result->getResult()]["value"] = $resVal;
1273 } elseif ($result->getUnit() == null) {
1274 $unit_factor = 1;
1275 // there is no fix result_unit, any "available unit" is accepted
1276
1277 $available_units = $result->getAvailableResultUnits(parent::getId());
1278 $result_name = $result->getResult();
1279
1280 $check_unit = false;
1281 if (array_key_exists($result_name, $available_units) &&
1282 $available_units[$result_name] !== null) {
1283 $check_unit = in_array($user_solution[$result_name]['unit'], $available_units[$result_name]);
1284 }
1285
1286 if ($check_unit == true) {
1287 //get unit-factor
1288 $unit_factor = assFormulaQuestionUnit::lookupUnitFactor($user_solution[$result_name]['unit']);
1289 }
1290
1291 try {
1292 $user_solution[$result->getResult()]["value"] = ilMath::_div($resVal, $unit_factor, 55);
1293 } catch (ilMathDivisionByZeroException $ex) {
1294 $user_solution[$result->getResult()]["value"] = 0;
1295 }
1296 }
1297 if ($result->getResultType() == assFormulaQuestionResult::RESULT_CO_FRAC
1298 || $result->getResultType() == assFormulaQuestionResult::RESULT_FRAC) {
1300 if (is_array($value)) {
1301 $user_solution[$result->getResult()]["value"] = $value[0];
1302 $user_solution[$result->getResult()]["frac_helper"] = $value[1];
1303 } else {
1304 $user_solution[$result->getResult()]["value"] = $value;
1305 $user_solution[$result->getResult()]["frac_helper"] = null;
1306 }
1307 } else {
1308 $user_solution[$result->getResult()]["value"] = round($user_solution[$result->getResult()]["value"], $result->getPrecision());
1309 /*
1310 $user_solution[$result->getResult()]["value"] = ilMath::_div(
1311 $user_solution[$result->getResult()]["value"],
1312 1,
1313 $result->getPrecision()
1314 );
1315 */
1316 }
1317 }
1318 return $user_solution;
1319 }
1320
1321 public function setId($id = -1): void
1322 {
1323 parent::setId($id);
1324 $this->unitrepository->setConsumerId($this->getId());
1325 }
1326
1330 public function setUnitrepository($unitrepository): void
1331 {
1332 $this->unitrepository = $unitrepository;
1333 }
1334
1339 {
1340 return $this->unitrepository;
1341 }
1342
1346 protected function getSolutionSubmit(): array
1347 {
1348 $solutionSubmit = [];
1349
1350 $post = $this->dic->http()->wrapper()->post();
1351
1352 foreach ($this->getResults() as $index => $a) {
1353 $key = "result_$index";
1354 if ($post->has($key)) {
1355 $value = $post->retrieve(
1356 $key,
1357 $this->dic->refinery()->kindlyTo()->string()
1358 );
1359
1360 $solutionSubmit[$key] = $value;
1361 }
1362 if ($post->has($key . "_unit")) {
1363 $value = $post->retrieve(
1364 $key . "_unit",
1365 $this->dic->refinery()->kindlyTo()->string()
1366 );
1367 $solutionSubmit[$key . "_unit"] = $value;
1368 }
1369 }
1370 return $solutionSubmit;
1371 }
1372
1373 public function validateSolutionSubmit(): bool
1374 {
1375 foreach ($this->getSolutionSubmit() as $key => $value) {
1376 if ($value && !$this->isValidSolutionResultValue($value)) {
1377 $this->tpl->setOnScreenMessage(
1378 'failure',
1379 $this->lng->txt("err_no_numeric_value"),
1380 true
1381 );
1382 return false;
1383 }
1384 }
1385
1386 return true;
1387 }
1388
1397 public function getOperators($expression): array
1398 {
1400 }
1401
1406 public function getExpressionTypes(): array
1407 {
1408 return array(
1412 );
1413 }
1414
1423 public function getUserQuestionResult($active_id, $pass): ilUserQuestionResult
1424 {
1426 global $DIC;
1427 $ilDB = $DIC['ilDB'];
1428 $result = new ilUserQuestionResult($this, $active_id, $pass);
1429
1430 $maxStep = $this->lookupMaxStep($active_id, $pass);
1431
1432 if ($maxStep !== null) {
1433 $data = $ilDB->queryF(
1434 "SELECT value1, value2 FROM tst_solutions WHERE active_fi = %s AND pass = %s AND question_fi = %s AND step = %s",
1435 array("integer", "integer", "integer",'integer'),
1436 array($active_id, $pass, $this->getId(), $maxStep)
1437 );
1438 } else {
1439 $data = $ilDB->queryF(
1440 "SELECT value1, value2 FROM tst_solutions WHERE active_fi = %s AND pass = %s AND question_fi = %s",
1441 array("integer", "integer", "integer"),
1442 array($active_id, $pass, $this->getId())
1443 );
1444 }
1445
1446 while ($row = $ilDB->fetchAssoc($data)) {
1447 if (strstr($row["value1"], '$r') && $row["value2"] != null) {
1448 $result->addKeyValue(str_replace('$r', "", $row["value1"]), $row["value2"]);
1449 }
1450 }
1451
1452 $points = $this->calculateReachedPoints($active_id, $pass);
1453 $max_points = $this->getMaximumPoints();
1454
1455 $result->setReachedPercentage(($points / $max_points) * 100);
1456
1457 return $result;
1458 }
1459
1468 public function getAvailableAnswerOptions($index = null)
1469 {
1470 if ($index !== null) {
1471 return $this->getResult('$r' . ($index + 1));
1472 } else {
1473 return $this->getResults();
1474 }
1475 }
1476}
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static convertDecimalToCoprimeFraction($decimal_value, $tolerance=1.e-9)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static lookupUnitFactor(int $a_unit_id)
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...
getBestSolution($solutions)
Returns the best solution for a given pass of a participant.
getQuestionType()
Returns the question type of the question.
getAvailableAnswerOptions($index=null)
If index is null, the function returns an array with all anwser options Else it returns the specific ...
ilUnitConfigurationRepository $unitrepository
setUnitrepository($unitrepository)
canUseAdvancedRating($result)
Check if advanced rating can be used for a result.
hasResultUnit($result, $unit_id)
isValidSolutionResultValue($submittedValue)
addResultUnits($result, $unit_ids)
lookupForExistingSolutions(int $activeId, int $pass)
Lookup if an authorized or intermediate solution exists.
getExpressionTypes()
Get all available expression types for a specific question.
savePreviewData(ilAssQuestionPreviewSession $previewSession)
getOperators($expression)
Get all available operations for a specific question.
calculateReachedPointsFromPreviewSession(ilAssQuestionPreviewSession $previewSession)
copyObject($target_questionpool_id, $title="")
Copies an assFormulaQuestion object @access public.
getRTETextWithMediaObjects()
Collects all text in the question which could contain media objects which were created with the Rich ...
duplicate(bool $for_test=true, string $title="", string $author="", string $owner="", $testObjId=null)
Duplicates an assFormulaQuestion @access public.
saveWorkingData($active_id, $pass=null, $authorized=true)
Saves the learners input of the question to the database.
loadFromDb($question_id)
Loads a assFormulaQuestion object from a database.
removeExistingSolutions(int $activeId, int $pass)
Remove an existing solution without removing the variables.
__construct(string $title="", string $comment="", string $author="", int $owner=-1, string $question="")
assQuestion constructor
createNewOriginalFromThisDuplicate($targetParentId, $targetQuestionTitle="")
setExportDetailsXLS(ilAssExcelFormatHelper $worksheet, int $startrow, int $active_id, int $pass)
{}
getAdditionalTableName()
Returns the name of the additional question data table in the database.
getResultUnits(assFormulaQuestionResult $result)
calculateReachedPoints($active_id, $pass=null, $authorizedSolution=true, $returndetails=false)
Returns the points, a learner has reached answering the question The points are calculated from the g...
getMaximumPoints()
Returns the maximum points, a learner can reach answering the question.
saveToDb($original_id="")
Saves a assFormulaQuestion object to a database @access public.
hasRequiredVariableSolutionValues(array $userSolution)
generateResultInputHTML(string $result_key, string $result_value, bool $forsolution)
deleteAnswers($question_id)
Deletes datasets from answers tables.
substituteVariables(array $userdata, bool $graphicalOutput=false, bool $forsolution=false, bool $result_output=false, array $correctness_icons=[])
getAnswerTableName()
Returns the name of the answer table in the database.
isComplete()
Returns true, if the question is complete for use.
Abstract basic class which is to be extended by the concrete assessment question type classes.
float $points
The maximum available points for the question.
setOriginalId(?int $original_id)
string $question
The question text.
static logAction(string $logtext, int $active_id, int $question_id)
setAdditionalContentEditingMode(?string $additionalContentEditingMode)
saveCurrentSolution(int $active_id, int $pass, $value1, $value2, bool $authorized=true, $tstamp=0)
getSolutionValues($active_id, $pass=null, bool $authorized=true)
Loads solutions of a given user from the database an returns it.
deductHintPointsFromReachedPoints(ilAssQuestionPreviewSession $previewSession, $reachedPoints)
setQuestion(string $question="")
static _getOriginalId(int $question_id)
saveQuestionDataToDb(int $original_id=-1)
setAuthor(string $author="")
purifyAndPrepareTextAreaOutput(string $content)
setComment(string $comment="")
setObjId(int $obj_id=0)
getSolutionMaxPass(int $active_id)
setOwner(int $owner=-1)
setLifecycle(ilAssQuestionLifecycle $lifecycle)
setTitle(string $title="")
lookupMaxStep(int $active_id, int $pass)
setPoints(float $points)
ensureNonNegativePoints($points)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
setCell($a_row, $a_col, $a_value, $datatype=null)
setBold(string $a_coords)
Set cell(s) to bold.
getColumnCoord(int $a_col)
Get column "name" from number.
static prepareFormOutput($a_str, bool $a_strip=false)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static _div($left_operand, $right_operand, int $scale=50)
static _getPass($active_id)
Retrieves the actual pass of a given user for a given test.
static _replaceMediaObjectImageSrc(string $a_text, int $a_direction=0, string $nic='')
Replaces image source from mob image urls with the mob id or replaces mob id with the correct image s...
special template class to simplify handling of ITX/PEAR
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...
global $DIC
Definition: feed.php:28
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
getUserQuestionResult($active_id, $pass)
Get the user solution for a question by active_id and the test pass.
$post
Definition: ltitoken.php:49
$index
Definition: metadata.php:145
$i
Definition: metadata.php:41
__construct(Container $dic, ilPlugin $plugin)
@inheritDoc
string $key
Consumer key/client ID value.
Definition: System.php:193
$a
thx to https://mlocati.github.io/php-cs-fixer-configurator for the examples
$query