ILIAS  Release_3_10_x_branch Revision 61812
 All Data Structures Namespaces Files Functions Variables Groups Pages
class.assNumeric.php
Go to the documentation of this file.
1 <?php
2  /*
3  +----------------------------------------------------------------------------+
4  | ILIAS open source |
5  +----------------------------------------------------------------------------+
6  | Copyright (c) 1998-2001 ILIAS open source, University of Cologne |
7  | |
8  | This program is free software; you can redistribute it and/or |
9  | modify it under the terms of the GNU General Public License |
10  | as published by the Free Software Foundation; either version 2 |
11  | of the License, or (at your option) any later version. |
12  | |
13  | This program is distributed in the hope that it will be useful, |
14  | but WITHOUT ANY WARRANTY; without even the implied warranty of |
15  | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16  | GNU General Public License for more details. |
17  | |
18  | You should have received a copy of the GNU General Public License |
19  | along with this program; if not, write to the Free Software |
20  | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
21  +----------------------------------------------------------------------------+
22 */
23 include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
24 include_once "./Modules/Test/classes/inc.AssessmentConstants.php";
25 
37 class assNumeric extends assQuestion
38 {
46  var $ranges;
47 
55  var $maxchars;
56 
70  function assNumeric(
71  $title = "",
72  $comment = "",
73  $author = "",
74  $owner = -1,
75  $question = ""
76  )
77  {
79  $this->ranges = array();
80  $this->maxchars = 6;
81  }
82 
91  function isComplete()
92  {
93  if (($this->title) and ($this->author) and ($this->question) and (count($this->ranges)) and ($this->getMaximumPoints() > 0))
94  {
95  return true;
96  }
97  else
98  {
99  return false;
100  }
101  }
102 
111  function saveToDb($original_id = "")
112  {
113  global $ilDB;
114 
115  $complete = 0;
116  if ($this->isComplete())
117  {
118  $complete = 1;
119  }
120  $estw_time = $this->getEstimatedWorkingTime();
121  $estw_time = sprintf("%02d:%02d:%02d", $estw_time['h'], $estw_time['m'], $estw_time['s']);
122 
123  if ($original_id)
124  {
125  $original_id = $ilDB->quote($original_id);
126  }
127  else
128  {
129  $original_id = "NULL";
130  }
131 
132  // cleanup RTE images which are not inserted into the question text
133  include_once("./Services/RTE/classes/class.ilRTE.php");
134  if ($this->id == -1)
135  {
136  // Neuen Datensatz schreiben
137  $now = getdate();
138  $question_type = $this->getQuestionTypeID();
139  $created = sprintf("%04d%02d%02d%02d%02d%02d", $now['year'], $now['mon'], $now['mday'], $now['hours'], $now['minutes'], $now['seconds']);
140  $query = sprintf("INSERT INTO qpl_questions (question_id, question_type_fi, obj_fi, title, comment, author, owner, question_text, points, working_time, complete, created, original_id, TIMESTAMP) VALUES (NULL, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, NULL)",
141  $ilDB->quote($question_type),
142  $ilDB->quote($this->obj_id),
143  $ilDB->quote($this->title),
144  $ilDB->quote($this->comment),
145  $ilDB->quote($this->author),
146  $ilDB->quote($this->owner),
147  $ilDB->quote(ilRTE::_replaceMediaObjectImageSrc($this->question, 0)),
148  $ilDB->quote($this->getMaximumPoints() . ""),
149  $ilDB->quote($estw_time),
150  $ilDB->quote("$complete"),
151  $ilDB->quote($created),
153  );
154  $result = $ilDB->query($query);
155 
156  if (PEAR::isError($result))
157  {
158  global $ilias;
159  $ilias->raiseError($result->getMessage());
160  }
161  else
162  {
163  $this->id = $ilDB->getLastInsertId();
164  $query = sprintf("INSERT INTO qpl_question_numeric (question_fi, maxNumOfChars) VALUES (%s, %s)",
165  $ilDB->quote($this->id . ""),
166  $ilDB->quote($this->getMaxChars() . "")
167  );
168  $ilDB->query($query);
169 
170  // create page object of question
171  $this->createPageObject();
172 
173  if ($this->getTestId() > 0)
174  {
175  $this->insertIntoTest($this->getTestId());
176  }
177  }
178  }
179  else
180  {
181  // Vorhandenen Datensatz aktualisieren
182  $query = sprintf("UPDATE qpl_questions SET obj_fi = %s, title = %s, comment = %s, author = %s, question_text = %s, points = %s, working_time=%s, complete = %s WHERE question_id = %s",
183  $ilDB->quote($this->obj_id. ""),
184  $ilDB->quote($this->title),
185  $ilDB->quote($this->comment),
186  $ilDB->quote($this->author),
187  $ilDB->quote(ilRTE::_replaceMediaObjectImageSrc($this->question, 0)),
188  $ilDB->quote($this->getMaximumPoints() . ""),
189  $ilDB->quote($estw_time),
190  $ilDB->quote("$complete"),
191  $ilDB->quote($this->id)
192  );
193  $result = $ilDB->query($query);
194  $query = sprintf("UPDATE qpl_question_numeric SET maxNumOfChars = %s WHERE question_fi = %s",
195  $ilDB->quote($this->getMaxChars() . ""),
196  $ilDB->quote($this->id . "")
197  );
198  $result = $ilDB->query($query);
199  }
200  if (PEAR::isError($result))
201  {
202  global $ilias;
203  $ilias->raiseError($result->getMessage());
204  }
205  else
206  {
207  // Write Ranges to the database
208 
209  // 1. delete old ranges
210  $query = sprintf("DELETE FROM qpl_numeric_range WHERE question_fi = %s",
211  $ilDB->quote($this->id)
212  );
213  $result = $ilDB->query($query);
214 
215  // 2. write ranges
216  foreach ($this->ranges as $key => $range)
217  {
218  $query = sprintf("INSERT INTO qpl_numeric_range (range_id, question_fi, lowerlimit, upperlimit, points, aorder, lastchange) VALUES (NULL, %s, %s, %s, %s, %s, NULL)",
219  $ilDB->quote($this->id),
220  $ilDB->quote($range->getLowerLimit()),
221  $ilDB->quote($range->getUpperLimit() . ""),
222  $ilDB->quote($range->getPoints() . ""),
223  $ilDB->quote($range->getOrder() . "")
224  );
225  $answer_result = $ilDB->query($query);
226  }
227  }
229  }
230 
240  function loadFromDb($question_id)
241  {
242  global $ilDB;
243 
244  $query = sprintf("SELECT qpl_questions.*, qpl_question_numeric.* FROM qpl_questions, qpl_question_numeric WHERE question_id = %s AND qpl_questions.question_id = qpl_question_numeric.question_fi",
245  $ilDB->quote($question_id)
246  );
247  $result = $ilDB->query($query);
248  if ($result->numRows() == 1)
249  {
250  $data = $result->fetchRow(MDB2_FETCHMODE_OBJECT);
251  $this->id = $question_id;
252  $this->title = $data->title;
253  $this->comment = $data->comment;
254  $this->solution_hint = $data->solution_hint;
255  $this->original_id = $data->original_id;
256  $this->obj_id = $data->obj_fi;
257  $this->author = $data->author;
258  $this->owner = $data->owner;
259  $this->points = $data->points;
260  include_once("./Services/RTE/classes/class.ilRTE.php");
261  $this->question = ilRTE::_replaceMediaObjectImageSrc($data->question_text, 1);
262  $this->maxchars = $data->maxNumOfChars;
263  $this->setEstimatedWorkingTime(substr($data->working_time, 0, 2), substr($data->working_time, 3, 2), substr($data->working_time, 6, 2));
264 
265  $query = sprintf("SELECT * FROM qpl_numeric_range WHERE question_fi = %s ORDER BY aorder ASC",
266  $ilDB->quote($question_id)
267  );
268 
269  $result = $ilDB->query($query);
270 
271  include_once "./Modules/TestQuestionPool/classes/class.assNumericRange.php";
272  if ($result->numRows() > 0)
273  {
274  while ($data = $result->fetchRow(MDB2_FETCHMODE_ASSOC))
275  {
276  array_push($this->ranges, new assNumericRange($data["lowerlimit"], $data["upperlimit"], $data["points"], $data["aorder"]));
277  }
278  }
279  }
280  parent::loadFromDb($question_id);
281  }
282 
297  function addRange(
298  $lowerlimit = 0.0,
299  $upperlimit = 0.0,
300  $points = 0.0,
301  $order = 0
302  )
303  {
304  $found = -1;
305  foreach ($this->ranges as $key => $range)
306  {
307  if ($range->getOrder() == $order)
308  {
309  $found = $order;
310  }
311  }
312  include_once "./Modules/TestQuestionPool/classes/class.assNumericRange.php";
313  if ($found >= 0)
314  {
315  // insert range
316  $range = new assNumericRange($lowerlimit, $upperlimit, $points, $found);
317  array_push($this->ranges, $range);
318  for ($i = $found + 1; $i < count($this->ranges); $i++)
319  {
320  $this->ranges[$i] = $this->ranges[$i-1];
321  }
322  $this->ranges[$found] = $range;
323  }
324  else
325  {
326  // append range
327  $range = new assNumericRange($lowerlimit, $upperlimit, $points, count($this->ranges));
328  array_push($this->ranges, $range);
329  }
330  }
331 
339  function duplicate($for_test = true, $title = "", $author = "", $owner = "")
340  {
341  if ($this->id <= 0)
342  {
343  // The question has not been saved. It cannot be duplicated
344  return;
345  }
346  // duplicate the question in database
347  $this_id = $this->getId();
348  $clone = $this;
349  include_once ("./Modules/TestQuestionPool/classes/class.assQuestion.php");
351  $clone->id = -1;
352  if ($title)
353  {
354  $clone->setTitle($title);
355  }
356 
357  if ($author)
358  {
359  $clone->setAuthor($author);
360  }
361  if ($owner)
362  {
363  $clone->setOwner($owner);
364  }
365 
366  if ($for_test)
367  {
368  $clone->saveToDb($original_id);
369  }
370  else
371  {
372  $clone->saveToDb();
373  }
374 
375  // copy question page content
376  $clone->copyPageOfQuestion($this_id);
377  // copy XHTML media objects
378  $clone->copyXHTMLMediaObjectsOfQuestion($this_id);
379  // duplicate the generic feedback
380  $clone->duplicateFeedbackGeneric($this_id);
381 
382  return $clone->id;
383  }
384 
392  function copyObject($target_questionpool, $title = "")
393  {
394  if ($this->id <= 0)
395  {
396  // The question has not been saved. It cannot be duplicated
397  return;
398  }
399  // duplicate the question in database
400  $clone = $this;
401  include_once ("./Modules/TestQuestionPool/classes/class.assQuestion.php");
403  $clone->id = -1;
404  $source_questionpool = $this->getObjId();
405  $clone->setObjId($target_questionpool);
406  if ($title)
407  {
408  $clone->setTitle($title);
409  }
410  $clone->saveToDb();
411 
412  // copy question page content
413  $clone->copyPageOfQuestion($original_id);
414  // copy XHTML media objects
415  $clone->copyXHTMLMediaObjectsOfQuestion($original_id);
416  // duplicate the generic feedback
417  $clone->duplicateFeedbackGeneric($original_id);
418 
419  return $clone->id;
420  }
421 
431  function getRangeCount()
432  {
433  return count($this->ranges);
434  }
435 
447  function getRange($index = 0)
448  {
449  if ($index < 0) return NULL;
450  if (count($this->ranges) < 1) return NULL;
451  if ($index >= count($this->ranges)) return NULL;
452 
453  return $this->ranges[$index];
454  }
455 
466  function deleteRange($index = 0)
467  {
468  if ($index < 0) return;
469  if (count($this->ranges) < 1) return;
470  if ($index >= count($this->ranges)) return;
471  unset($this->ranges[$index]);
472  $this->ranges = array_values($this->ranges);
473  for ($i = 0; $i < count($this->ranges); $i++)
474  {
475  if ($this->ranges[$i]->getOrder() > $index)
476  {
477  $this->ranges[$i]->setOrder($i);
478  }
479  }
480  }
481 
490  function flushRanges()
491  {
492  $this->ranges = array();
493  }
494 
503  function getMaximumPoints()
504  {
505  $max = 0;
506  foreach ($this->ranges as $key => $range)
507  {
508  if ($range->getPoints() > $max)
509  {
510  $max = $range->getPoints();
511  }
512  }
513  return $max;
514  }
515 
524  function getBestRange()
525  {
526  $max = 0;
527  $bestrange = NULL;
528  foreach ($this->ranges as $key => $range)
529  {
530  if ($range->getPoints() > $max)
531  {
532  $max = $range->getPoints();
533  $bestrange = $range;
534  }
535  }
536  return $bestrange;
537  }
538 
550  function calculateReachedPoints($active_id, $pass = NULL)
551  {
552  global $ilDB;
553 
554  $found_values = array();
555  if (is_null($pass))
556  {
557  $pass = $this->getSolutionMaxPass($active_id);
558  }
559  $query = sprintf("SELECT * FROM tst_solutions WHERE active_fi = %s AND question_fi = %s AND pass = %s",
560  $ilDB->quote($active_id . ""),
561  $ilDB->quote($this->getId() . ""),
562  $ilDB->quote($pass . "")
563  );
564  $result = $ilDB->query($query);
565  $data = $result->fetchRow(MDB2_FETCHMODE_ASSOC);
566 
567  $enteredvalue = $data["value1"];
568  //if (!is_numeric($enteredvalue)) return 0;
569  $points = 0;
570  foreach ($this->ranges as $key => $range)
571  {
572  if ($points == 0)
573  {
574  if ($range->contains($enteredvalue))
575  {
576  $points = $range->getPoints();
577  }
578  }
579  }
580 
581  $points = parent::calculateReachedPoints($active_id, $pass = NULL, $points);
582  return $points;
583  }
584 
595  function saveWorkingData($active_id, $pass = NULL)
596  {
597  global $ilDB;
598  global $ilUser;
599 
600  if (is_null($pass))
601  {
602  include_once "./Modules/Test/classes/class.ilObjTest.php";
603  $pass = ilObjTest::_getPass($active_id);
604  }
605  $entered_values = 0;
606  $numeric_result = str_replace(",",".",$_POST["numeric_result"]);
607 
608  include_once "./Services/Math/classes/class.EvalMath.php";
609  $math = new EvalMath();
610  $math->suppress_errors = TRUE;
611  $result = $math->evaluate($numeric_result);
612  $returnvalue = true;
613  if ((($result === FALSE) || ($result === TRUE)) && (strlen($result) > 0))
614  {
615  ilUtil::sendInfo($this->lng->txt("err_no_numeric_value"), true);
616  $returnvalue = false;
617  }
618  $query = sprintf("SELECT * FROM tst_solutions WHERE active_fi = %s AND question_fi = %s AND pass = %s",
619  $ilDB->quote($active_id . ""),
620  $ilDB->quote($this->getId() . ""),
621  $ilDB->quote($pass . "")
622  );
623  $result = $ilDB->query($query);
624  $row = $result->fetchRow(MDB2_FETCHMODE_OBJECT);
625  $update = $row->solution_id;
626  if ($update)
627  {
628  if (strlen($numeric_result))
629  {
630  $query = sprintf("UPDATE tst_solutions SET value1 = %s WHERE solution_id = %s",
631  $ilDB->quote(trim($numeric_result)),
632  $ilDB->quote($update)
633  );
634  $result = $ilDB->query($query);
635  $entered_values++;
636  }
637  else
638  {
639  $query = sprintf("DELETE FROM tst_solutions WHERE solution_id = %s",
640  $ilDB->quote($update)
641  );
642  $result = $ilDB->query($query);
643  }
644  }
645  else
646  {
647  if (strlen($numeric_result))
648  {
649  $query = sprintf("INSERT INTO tst_solutions (solution_id, active_fi, question_fi, value1, value2, pass, TIMESTAMP) VALUES (NULL, %s, %s, %s, NULL, %s, NULL)",
650  $ilDB->quote($active_id),
651  $ilDB->quote($this->getId()),
652  $ilDB->quote(trim($numeric_result)),
653  $ilDB->quote($pass . "")
654  );
655  $result = $ilDB->query($query);
656  $entered_values++;
657  }
658  }
659  if ($entered_values)
660  {
661  include_once ("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
663  {
664  $this->logAction($this->lng->txtlng("assessment", "log_user_entered_values", ilObjAssessmentFolder::_getLogLanguage()), $active_id, $this->getId());
665  }
666  }
667  else
668  {
669  include_once ("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
671  {
672  $this->logAction($this->lng->txtlng("assessment", "log_user_not_entered_values", ilObjAssessmentFolder::_getLogLanguage()), $active_id, $this->getId());
673  }
674  }
675  parent::saveWorkingData($active_id, $pass);
676 
677  return $returnvalue;
678  }
679 
688  function getQuestionType()
689  {
690  return "assNumeric";
691  }
692 
701  function getMaxChars()
702  {
703  return $this->maxchars;
704  }
705 
715  {
716  $this->maxchars = $maxchars;
717  }
718 
728  {
729  return "qpl_question_numeric";
730  }
731 
737  {
739  }
740 
744  function &getRanges()
745  {
746  return $this->ranges;
747  }
748 
761  public function setExportDetailsXLS(&$worksheet, $startrow, $active_id, $pass, &$format_title, &$format_bold)
762  {
763  include_once ("./classes/class.ilExcelUtils.php");
764  $solutions = $this->getSolutionValues($active_id, $pass);
765  $worksheet->writeString($startrow, 0, ilExcelUtils::_convert_text($this->lng->txt($this->getQuestionType())), $format_title);
766  $worksheet->writeString($startrow, 1, ilExcelUtils::_convert_text($this->getTitle()), $format_title);
767  $i = 1;
768  $worksheet->writeString($startrow + $i, 0, ilExcelUtils::_convert_text($this->lng->txt("result")), $format_bold);
769  if (strlen($solutions[0]["value1"]))
770  {
771  $worksheet->write($startrow + $i, 1, ilExcelUtils::_convert_text($solutions[0]["value1"]));
772  }
773  $i++;
774  return $startrow + $i + 1;
775  }
776 }
777 
778 ?>