ILIAS  release_8 Revision v8.19
All Data Structures Namespaces Files Functions Variables Modules Pages
class.assNumericGUI.php
Go to the documentation of this file.
1 <?php
18 require_once './Modules/Test/classes/inc.AssessmentConstants.php';
19 
37 {
45  public function __construct($id = -1)
46  {
48  require_once './Modules/TestQuestionPool/classes/class.assNumeric.php';
49  $this->object = new assNumeric();
50  if ($id >= 0) {
51  $this->object->loadFromDb($id);
52  }
53  }
54 
55  public function getCommand($cmd)
56  {
57  if (substr($cmd, 0, 6) == "delete") {
58  $cmd = "delete";
59  }
60  return $cmd;
61  }
62 
66  protected function writePostData(bool $always = false): int
67  {
68  $hasErrors = (!$always) ? $this->editQuestion(true) : false;
69  if (!$hasErrors) {
70  require_once 'Services/Form/classes/class.ilPropertyFormGUI.php';
74  $this->saveTaxonomyAssignments();
75  return 0;
76  }
77  return 1;
78  }
79 
87  public function editQuestion($checkonly = false): bool
88  {
89  $save = $this->isSaveCommand();
90  $this->getQuestionTemplate();
91 
92  include_once("./Services/Form/classes/class.ilPropertyFormGUI.php");
93  $form = new ilPropertyFormGUI();
94  $this->editForm = $form;
95 
96  $form->setFormAction($this->ctrl->getFormAction($this));
97  $form->setTitle($this->outQuestionType());
98  $form->setMultipart(true);
99  $form->setTableWidth("100%");
100  $form->setId("assnumeric");
101 
102  $this->addBasicQuestionFormProperties($form);
103  $this->populateQuestionSpecificFormPart($form);
104  $this->populateAnswerSpecificFormPart($form);
105  $this->populateTaxonomyFormSection($form);
106  $this->addQuestionFormCommandButtons($form);
107 
108  $errors = false;
109 
110  if ($save) {
111  $form->setValuesByPost();
112  $errors = !$form->checkInput();
113  $form->setValuesByPost(); // again, because checkInput now performs the whole stripSlashes handling and we need this if we don't want to have duplication of backslashes
114 
115  $lower = $form->getItemByPostVar('lowerlimit');
116  $upper = $form->getItemByPostVar('upperlimit');
117 
118  if (!$this->checkRange($lower->getValue(), $upper->getValue())) {
119  global $DIC;
120  $lower->setAlert($DIC->language()->txt('qpl_numeric_lower_needs_valid_lower_alert'));
121  $upper->setAlert($DIC->language()->txt('qpl_numeric_upper_needs_valid_upper_alert'));
122  $this->tpl->setOnScreenMessage('failure', $DIC->language()->txt("form_input_not_valid"));
123  $errors = true;
124  }
125 
126  if ($errors) {
127  $checkonly = false;
128  }
129  }
130 
131  if (!$checkonly) {
132  $this->tpl->setVariable("QUESTION_DATA", $form->getHTML());
133  }
134  return $errors;
135  }
136 
144  public function checkRange($lower, $upper): bool
145  {
146  include_once "./Services/Math/classes/class.EvalMath.php";
147  $eval = new EvalMath();
148  $eval->suppress_errors = true;
149  if (($eval->e($lower) !== false) and ($eval->e($upper) !== false)) {
150  if ($eval->e($lower) <= $eval->e($upper)) {
151  return true;
152  } else {
153  return false;
154  }
155  }
156  return false;
157  }
158 
172  public function getSolutionOutput(
173  $active_id,
174  $pass = null,
175  $graphicalOutput = false,
176  $result_output = false,
177  $show_question_only = true,
178  $show_feedback = false,
179  $show_correct_solution = false,
180  $show_manual_scoring = false,
181  $show_question_text = true
182  ): string {
183  // get the solution of the user for the active pass or from the last pass if allowed
184  $solutions = array();
185  if (($active_id > 0) && (!$show_correct_solution)) {
186  $solutions = $this->object->getSolutionValues($active_id, $pass);
187  } else {
188  array_push($solutions, array("value1" => sprintf($this->lng->txt("value_between_x_and_y"), $this->object->getLowerLimit(), $this->object->getUpperLimit())));
189  }
190 
191  // generate the question output
192  require_once './Services/UICore/classes/class.ilTemplate.php';
193  $template = new ilTemplate("tpl.il_as_qpl_numeric_output_solution.html", true, true, "Modules/TestQuestionPool");
194  $solutiontemplate = new ilTemplate("tpl.il_as_tst_solution_output.html", true, true, "Modules/TestQuestionPool");
195  if (is_array($solutions)) {
196  if (($active_id > 0) && (!$show_correct_solution)) {
197  if ($graphicalOutput) {
198  if ($this->object->getStep() === null) {
199  $reached_points = $this->object->getReachedPoints($active_id, $pass);
200  } else {
201  $reached_points = $this->object->calculateReachedPoints($active_id, $pass);
202  }
203 
204  $correctness_icon = $this->generateCorrectnessIconsForCorrectness(self::CORRECTNESS_NOT_OK);
205  if ($reached_points == $this->object->getMaximumPoints()) {
206  $correctness_icon = $this->generateCorrectnessIconsForCorrectness(self::CORRECTNESS_OK);
207  }
208  $template->setCurrentBlock("icon_ok");
209  $template->setVariable("ICON_OK", $correctness_icon);
210  $template->parseCurrentBlock();
211  }
212  }
213  foreach ($solutions as $solution) {
214  $template->setVariable("NUMERIC_VALUE", $solution["value1"]);
215  }
216  if (count($solutions) == 0) {
217  $template->setVariable("NUMERIC_VALUE", "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;");
218  }
219  }
220  $template->setVariable("NUMERIC_SIZE", $this->object->getMaxChars());
221  if ($show_question_text == true) {
222  $template->setVariable("QUESTIONTEXT", $this->object->getQuestionForHTMLOutput());
223  }
224  $questionoutput = $template->get();
225  //$feedback = ($show_feedback) ? $this->getAnswerFeedbackOutput($active_id, $pass) : ""; // Moving new method
226  // due to deprecation.
227  $feedback = ($show_feedback && !$this->isTestPresentationContext()) ? $this->getGenericFeedbackOutput((int) $active_id, $pass) : "";
228  if (strlen($feedback)) {
229  $cssClass = (
230  $this->hasCorrectSolution($active_id, $pass) ?
232  );
233 
234  $solutiontemplate->setVariable("ILC_FB_CSS_CLASS", $cssClass);
235  $solutiontemplate->setVariable("FEEDBACK", $this->object->prepareTextareaOutput($feedback, true));
236  }
237  $solutiontemplate->setVariable("SOLUTION_OUTPUT", $questionoutput);
238 
239  $solutionoutput = $solutiontemplate->get();
240  if (!$show_question_only) {
241  // get page object output
242  $solutionoutput = $this->getILIASPage($solutionoutput);
243  }
244  return $solutionoutput;
245  }
246 
252  public function getPreview($show_question_only = false, $showInlineFeedback = false): string
253  {
254  // generate the question output
255  require_once './Services/UICore/classes/class.ilTemplate.php';
256  $template = new ilTemplate("tpl.il_as_qpl_numeric_output.html", true, true, "Modules/TestQuestionPool");
257  if (is_object($this->getPreviewSession())) {
258  $template->setVariable("NUMERIC_VALUE", " value=\"" . $this->getPreviewSession()->getParticipantsSolution() . "\"");
259  }
260  $template->setVariable("NUMERIC_SIZE", $this->object->getMaxChars());
261  $template->setVariable("QUESTIONTEXT", $this->object->getQuestionForHTMLOutput());
262  $questionoutput = $template->get();
263  if (!$show_question_only) {
264  // get page object output
265  $questionoutput = $this->getILIASPage($questionoutput);
266  }
267  return $questionoutput;
268  }
269 
278  // hey: prevPassSolutions - pass will be always available from now on
279  public function getTestOutput($active_id, $pass, $is_postponed = false, $use_post_solutions = false, $inlineFeedback = false): string
280  // hey.
281  {
282  $solutions = null;
283  // get the solution of the user for the active pass or from the last pass if allowed
284  if ($use_post_solutions !== false) {
286  $solutions = array(
287  array('value1' => $use_post_solutions['numeric_result'])
288  );
289  } elseif ($active_id) {
290  $solutions = $this->object->getTestOutputSolutions($active_id, $pass);
291  }
292 
293  // generate the question output
294  require_once './Services/UICore/classes/class.ilTemplate.php';
295  $template = new ilTemplate("tpl.il_as_qpl_numeric_output.html", true, true, "Modules/TestQuestionPool");
296  if (is_array($solutions)) {
297  foreach ($solutions as $solution) {
298  $template->setVariable("NUMERIC_VALUE", " value=\"" . $solution["value1"] . "\"");
299  }
300  }
301  $template->setVariable("NUMERIC_SIZE", $this->object->getMaxChars());
302  $template->setVariable("QUESTIONTEXT", $this->object->getQuestionForHTMLOutput());
303  $questionoutput = $template->get();
304  $pageoutput = $this->outQuestionPage("", $is_postponed, $active_id, $questionoutput);
305  return $pageoutput;
306  }
307 
313  public function getSpecificFeedbackOutput(array $userSolution): string
314  {
315  $output = "";
316  return $this->object->prepareTextareaOutput($output, true);
317  }
318 
320  {
321  $this->object->setMaxChars($_POST["maxchars"]);
322  }
323 
324  public function writeAnswerSpecificPostData(ilPropertyFormGUI $form): void
325  {
326  $this->object->setLowerLimit($_POST['lowerlimit']);
327  $this->object->setUpperLimit($_POST['upperlimit']);
328  $this->object->setPoints((float) str_replace(',', '.', $_POST['points']));
329  }
330 
332  {
333  // maxchars
334  $maxchars = new ilNumberInputGUI($this->lng->txt("maxchars"), "maxchars");
335  $maxchars->setInfo($this->lng->txt('qpl_maxchars_info_numeric_question'));
336  $maxchars->setSize(10);
337  $maxchars->setDecimals(0);
338  $maxchars->setMinValue(1);
339  $maxchars->setRequired(true);
340  if ($this->object->getMaxChars() > 0) {
341  $maxchars->setValue($this->object->getMaxChars());
342  }
343  $form->addItem($maxchars);
344  return $form;
345  }
346 
348  {
349  // points
350  $points = new ilNumberInputGUI($this->lng->txt("points"), "points");
351  $points->allowDecimals(true);
352  $points->setValue($this->object->getPoints() > 0 ? $this->object->getPoints() : '');
353  $points->setRequired(true);
354  $points->setSize(3);
355  $points->setMinValue(0.0);
356  $points->setMinvalueShouldBeGreater(true);
357  $form->addItem($points);
358 
359  $header = new ilFormSectionHeaderGUI();
360  $header->setTitle($this->lng->txt("range"));
361  $form->addItem($header);
362 
363  // lower bound
364  $lower_limit = new ilFormulaInputGUI($this->lng->txt("range_lower_limit"), "lowerlimit");
365  $lower_limit->setSize(25);
366  $lower_limit->setMaxLength(20);
367  $lower_limit->setRequired(true);
368  $lower_limit->setValue((string) $this->object->getLowerLimit());
369  $form->addItem($lower_limit);
370 
371  // upper bound
372  $upper_limit = new ilFormulaInputGUI($this->lng->txt("range_upper_limit"), "upperlimit");
373  $upper_limit->setSize(25);
374  $upper_limit->setMaxLength(20);
375  $upper_limit->setRequired(true);
376  $upper_limit->setValue((string) $this->object->getUpperLimit());
377  $form->addItem($upper_limit);
378 
379  // reset input length, if max chars are set
380  if ($this->object->getMaxChars() > 0) {
381  $lower_limit->setSize($this->object->getMaxChars());
382  $lower_limit->setMaxLength($this->object->getMaxChars());
383  $upper_limit->setSize($this->object->getMaxChars());
384  $upper_limit->setMaxLength($this->object->getMaxChars());
385  }
386  return $form;
387  }
388 
399  {
400  return array();
401  }
402 
413  {
414  return array();
415  }
416 
423  public function getAggregatedAnswersView(array $relevant_answers): string
424  {
425  return $this->renderAggregateView(
426  $this->aggregateAnswers($relevant_answers)
427  )->get();
428  }
429 
430  public function aggregateAnswers($relevant_answers_chosen): array
431  {
432  $aggregate = array();
433 
434  foreach ($relevant_answers_chosen as $relevant_answer) {
435  if (array_key_exists($relevant_answer['value1'], $aggregate)) {
436  $aggregate[$relevant_answer['value1']]++;
437  } else {
438  $aggregate[$relevant_answer['value1']] = 1;
439  }
440  }
441  return $aggregate;
442  }
443 
449  public function renderAggregateView($aggregate): ilTemplate
450  {
451  $tpl = new ilTemplate('tpl.il_as_aggregated_answers_table.html', true, true, "Modules/TestQuestionPool");
452 
453  $tpl->setCurrentBlock('headercell');
454  $tpl->setVariable('HEADER', $this->lng->txt('tst_answer_aggr_answer_header'));
456 
457  $tpl->setCurrentBlock('headercell');
458  $tpl->setVariable('HEADER', $this->lng->txt('tst_answer_aggr_frequency_header'));
460 
461  foreach ($aggregate as $key => $value) {
462  $tpl->setCurrentBlock('aggregaterow');
463  $tpl->setVariable('OPTION', $key);
464  $tpl->setVariable('COUNT', $value);
466  }
467  return $tpl;
468  }
469 
470  public function getAnswersFrequency($relevantAnswers, $questionIndex): array
471  {
472  $answers = array();
473 
474  foreach ($relevantAnswers as $ans) {
475  if (!isset($answers[$ans['value1']])) {
476  $answers[$ans['value1']] = array(
477  'answer' => $ans['value1'], 'frequency' => 0
478  );
479  }
480 
481  $answers[$ans['value1']]['frequency']++;
482  }
483 
484  return $answers;
485  }
486 
488  {
489  // points
490  $points = new ilNumberInputGUI($this->lng->txt("points"), "points");
491  $points->allowDecimals(true);
492  $points->setValue($this->object->getPoints() > 0 ? $this->object->getPoints() : '');
493  $points->setRequired(true);
494  $points->setSize(3);
495  $points->setMinValue(0.0);
496  $points->setMinvalueShouldBeGreater(true);
497  $form->addItem($points);
498 
499  $header = new ilFormSectionHeaderGUI();
500  $header->setTitle($this->lng->txt("range"));
501  $form->addItem($header);
502 
503  // lower bound
504  $lower_limit = new ilFormulaInputGUI($this->lng->txt("range_lower_limit"), "lowerlimit");
505  $lower_limit->setSize(25);
506  $lower_limit->setMaxLength(20);
507  $lower_limit->setRequired(true);
508  $lower_limit->setValue($this->object->getLowerLimit());
509  $form->addItem($lower_limit);
510 
511  // upper bound
512  $upper_limit = new ilFormulaInputGUI($this->lng->txt("range_upper_limit"), "upperlimit");
513  $upper_limit->setSize(25);
514  $upper_limit->setMaxLength(20);
515  $upper_limit->setRequired(true);
516  $upper_limit->setValue($this->object->getUpperLimit());
517  $form->addItem($upper_limit);
518 
519  // reset input length, if max chars are set
520  if ($this->object->getMaxChars() > 0) {
521  $lower_limit->setSize($this->object->getMaxChars());
522  $lower_limit->setMaxLength($this->object->getMaxChars());
523  $upper_limit->setSize($this->object->getMaxChars());
524  $upper_limit->setMaxLength($this->object->getMaxChars());
525  }
526  }
527 
532  {
533  $this->object->setPoints((float) str_replace(',', '.', $form->getInput('points')));
534  $this->object->setLowerLimit((float) str_replace(',', '.', $form->getInput('lowerlimit')));
535  $this->object->setUpperLimit((float) str_replace(',', '.', $form->getInput('upperlimit')));
536  }
537 }
editQuestion($checkonly=false)
Creates an output of the edit form for the question.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
hasCorrectSolution($activeId, $passIndex)
generateCorrectnessIconsForCorrectness(int $correctness)
setCurrentBlock(string $blockname=self::DEFAULT_BLOCK)
Sets the template to the given block.
$errors
Definition: imgupload.php:65
getPreview($show_question_only=false, $showInlineFeedback=false)
getAfterParticipationSuppressionAnswerPostVars()
Returns a list of postvars which will be suppressed in the form output when used in scoring adjustmen...
writeQuestionSpecificPostData(ilPropertyFormGUI $form)
Extracts the question specific values from $_POST and applies them to the data object.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
saveCorrectionsFormProperties(ilPropertyFormGUI $form)
getAnswersFrequency($relevantAnswers, $questionIndex)
aggregateAnswers($relevant_answers_chosen)
addBasicQuestionFormProperties(ilPropertyFormGUI $form)
getSolutionOutput( $active_id, $pass=null, $graphicalOutput=false, $result_output=false, $show_question_only=true, $show_feedback=false, $show_correct_solution=false, $show_manual_scoring=false, $show_question_text=true)
Get the question solution output.
getSpecificFeedbackOutput(array $userSolution)
parseCurrentBlock(string $blockname=self::DEFAULT_BLOCK)
Parses the given block.
ilGlobalPageTemplate $tpl
populateTaxonomyFormSection(ilPropertyFormGUI $form)
getInput(string $a_post_var, bool $ensureValidation=true)
Returns the input of an item, if item provides getInput method and as fallback the value of the HTTP-...
addQuestionFormCommandButtons(ilPropertyFormGUI $form)
global $DIC
Definition: feed.php:28
allowDecimals(bool $a_value)
writeAnswerSpecificPostData(ilPropertyFormGUI $form)
Extracts the answer specific values from $_POST and applies them to the data object.
checkRange($lower, $upper)
Checks the range limits.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
This class represents a number property in a property form.
string $key
Consumer key/client ID value.
Definition: System.php:193
getTestOutput($active_id, $pass, $is_postponed=false, $use_post_solutions=false, $inlineFeedback=false)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
populateQuestionSpecificFormPart(\ilPropertyFormGUI $form)
getAggregatedAnswersView(array $relevant_answers)
Returns an html string containing a question specific representation of the answers so far given in t...
getAfterParticipationSuppressionQuestionPostVars()
Returns a list of postvars which will be suppressed in the form output when used in scoring adjustmen...
populateCorrectionsFormProperties(ilPropertyFormGUI $form)
getILIASPage(string $html="")
Returns the ILIAS Page around a question.
outQuestionPage($a_temp_var, $a_postponed=false, $active_id="", $html="", $inlineFeedbackEnabled=false)
writePostData(bool $always=false)
{}
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
__construct(Container $dic, ilPlugin $plugin)
$id
plugin.php for ilComponentBuildPluginInfoObjectiveTest::testAddPlugins
Definition: plugin.php:23
__construct($id=-1)
assNumericGUI constructor
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
renderAggregateView($aggregate)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
populateAnswerSpecificFormPart(\ilPropertyFormGUI $form)
setVariable(string $variable, $value='')
Sets the given variable to the given value.
getGenericFeedbackOutput(int $active_id, ?int $pass)