ILIAS  release_8 Revision v8.19
All Data Structures Namespaces Files Functions Variables Modules Pages
class.assFormulaQuestion.php
Go to the documentation of this file.
1 <?php
2 
19 include_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']);
666  } catch (ilTestQuestionPoolException $e) {
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 }
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...
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...
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.
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.
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...
static _getOriginalId(int $question_id)
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 ...
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.
$index
Definition: metadata.php:145
global $DIC
Definition: feed.php:28
setExportDetailsXLS(ilAssExcelFormatHelper $worksheet, int $startrow, int $active_id, int $pass)
{}
saveCurrentSolution(int $active_id, int $pass, $value1, $value2, bool $authorized=true, $tstamp=0)
setBold(string $a_coords)
Set cell(s) to bold.
purifyAndPrepareTextAreaOutput(string $content)
duplicate(bool $for_test=true, string $title="", string $author="", string $owner="", $testObjId=null)
Duplicates an assFormulaQuestion public.
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)
$query
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.
createNewOriginalFromThisDuplicate($targetParentId, $targetQuestionTitle="")
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.
__construct(Container $dic, ilPlugin $plugin)
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.
$i
Definition: metadata.php:41
savePreviewData(ilAssQuestionPreviewSession $previewSession)
setQuestion(string $question="")