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