ILIAS  Release_5_0_x_branch Revision 61816
 All Data Structures Namespaces Files Functions Variables Groups Pages
class.assImagemapQuestion.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (c) 1998-2013 ILIAS open source, Extended GPL, see docs/LICENSE */
3 
4 require_once './Modules/TestQuestionPool/classes/class.assQuestion.php';
5 require_once './Modules/Test/classes/inc.AssessmentConstants.php';
6 require_once './Modules/TestQuestionPool/interfaces/interface.ilObjQuestionScoringAdjustable.php';
7 require_once './Modules/TestQuestionPool/interfaces/interface.ilObjAnswerScoringAdjustable.php';
8 require_once './Modules/TestQuestionPool/interfaces/interface.iQuestionCondition.php';
9 require_once './Modules/TestQuestionPool/classes/class.ilUserQuestionResult.php';
10 
25 {
26  const MODE_SINGLE_CHOICE = 0;
28 
30  var $answers;
31 
34 
37 
39  var $coords;
40 
42  protected $is_multiple_choice = false;
43 
58  public function __construct(
59  $title = "",
60  $comment = "",
61  $author = "",
62  $owner = -1,
63  $question = "",
64  $image_filename = ""
65  )
66  {
68  $this->image_filename = $image_filename;
69  $this->answers = array();
70  $this->coords = array();
71  }
72 
79  {
80  $this->is_multiple_choice = $is_multiple_choice;
81  }
82 
88  public function getIsMultipleChoice()
89  {
91  }
92 
99  function isComplete()
100  {
101  if (strlen($this->title)
102  && ($this->author)
103  && ($this->question)
104  && ($this->image_filename)
105  && (count($this->answers))
106  && ($this->getMaximumPoints() > 0)
107  )
108  {
109  return true;
110  }
111  return false;
112  }
113 
123  public function saveToDb($original_id = "")
124  {
129  }
130 
131  public function saveAnswerSpecificDataToDb()
132  {
133  global $ilDB;
134  $ilDB->manipulateF( "DELETE FROM qpl_a_imagemap WHERE question_fi = %s",
135  array( "integer" ),
136  array( $this->getId() )
137  );
138 
139  // Anworten wegschreiben
140  foreach ($this->answers as $key => $value)
141  {
142  $answer_obj = $this->answers[$key];
143  $next_id = $ilDB->nextId( 'qpl_a_imagemap' );
144  $ilDB->manipulateF( "INSERT INTO qpl_a_imagemap (answer_id, question_fi, answertext, points, aorder, coords, area, points_unchecked) VALUES (%s, %s, %s, %s, %s, %s, %s, %s)",
145  array( "integer", "integer", "text", "float", "integer", "text", "text", "float" ),
146  array( $next_id, $this->id, $answer_obj->getAnswertext(
147  ), $answer_obj->getPoints(), $answer_obj->getOrder(
148  ), $answer_obj->getCoords(), $answer_obj->getArea(
149  ), $answer_obj->getPointsUnchecked() )
150  );
151  }
152  }
153 
155  {
156  global $ilDB;
157 
158  $ilDB->manipulateF( "DELETE FROM " . $this->getAdditionalTableName() . " WHERE question_fi = %s",
159  array( "integer" ),
160  array( $this->getId() )
161  );
162 
163  $ilDB->manipulateF( "INSERT INTO " . $this->getAdditionalTableName(
164  ) . " (question_fi, image_file, is_multiple_choice) VALUES (%s, %s, %s)",
165  array( "integer", "text", 'integer' ),
166  array(
167  $this->getId(),
168  $this->image_filename,
169  (int)$this->is_multiple_choice
170  )
171  );
172  }
173 
179  function duplicate($for_test = true, $title = "", $author = "", $owner = "", $testObjId = null)
180  {
181  if ($this->id <= 0)
182  {
183  // The question has not been saved. It cannot be duplicated
184  return;
185  }
186  // duplicate the question in database
187  $this_id = $this->getId();
188  $thisObjId = $this->getObjId();
189 
190  $clone = $this;
191  include_once ("./Modules/TestQuestionPool/classes/class.assQuestion.php");
193  $clone->id = -1;
194 
195  if( (int)$testObjId > 0 )
196  {
197  $clone->setObjId($testObjId);
198  }
199 
200  if ($title)
201  {
202  $clone->setTitle($title);
203  }
204  if ($author)
205  {
206  $clone->setAuthor($author);
207  }
208  if ($owner)
209  {
210  $clone->setOwner($owner);
211  }
212  if ($for_test)
213  {
214  $clone->saveToDb($original_id);
215  }
216  else
217  {
218  $clone->saveToDb();
219  }
220 
221  // copy question page content
222  $clone->copyPageOfQuestion($this_id);
223  // copy XHTML media objects
224  $clone->copyXHTMLMediaObjectsOfQuestion($this_id);
225  // duplicate the image
226  $clone->duplicateImage($this_id, $thisObjId);
227 
228  $clone->onDuplicate($thisObjId, $this_id, $clone->getObjId(), $clone->getId());
229 
230  return $clone->id;
231  }
232 
240  function copyObject($target_questionpool_id, $title = "")
241  {
242  if ($this->id <= 0)
243  {
244  // The question has not been saved. It cannot be duplicated
245  return;
246  }
247  // duplicate the question in database
248  $clone = $this;
249  include_once ("./Modules/TestQuestionPool/classes/class.assQuestion.php");
251  $clone->id = -1;
252  $source_questionpool_id = $this->getObjId();
253  $clone->setObjId($target_questionpool_id);
254  if ($title)
255  {
256  $clone->setTitle($title);
257  }
258  $clone->saveToDb();
259 
260  // copy question page content
261  $clone->copyPageOfQuestion($original_id);
262  // copy XHTML media objects
263  $clone->copyXHTMLMediaObjectsOfQuestion($original_id);
264  // duplicate the image
265  $clone->copyImage($original_id, $source_questionpool_id);
266 
267  $clone->onCopy($source_questionpool_id, $original_id, $clone->getObjId(), $clone->getId());
268 
269  return $clone->id;
270  }
271 
272  public function createNewOriginalFromThisDuplicate($targetParentId, $targetQuestionTitle = "")
273  {
274  if ($this->id <= 0)
275  {
276  // The question has not been saved. It cannot be duplicated
277  return;
278  }
279 
280  include_once ("./Modules/TestQuestionPool/classes/class.assQuestion.php");
281 
282  $sourceQuestionId = $this->id;
283  $sourceParentId = $this->getObjId();
284 
285  // duplicate the question in database
286  $clone = $this;
287  $clone->id = -1;
288 
289  $clone->setObjId($targetParentId);
290 
291  if ($targetQuestionTitle)
292  {
293  $clone->setTitle($targetQuestionTitle);
294  }
295 
296  $clone->saveToDb();
297  // copy question page content
298  $clone->copyPageOfQuestion($sourceQuestionId);
299  // copy XHTML media objects
300  $clone->copyXHTMLMediaObjectsOfQuestion($sourceQuestionId);
301  // duplicate the image
302  $clone->copyImage($sourceQuestionId, $sourceParentId);
303 
304  $clone->onCopy($sourceParentId, $sourceQuestionId, $clone->getObjId(), $clone->getId());
305 
306  return $clone->id;
307  }
308 
309  function duplicateImage($question_id, $objectId = null)
310  {
311  $imagepath = $this->getImagePath();
312  $imagepath_original = str_replace("/$this->id/images", "/$question_id/images", $imagepath);
313 
314  if( (int)$objectId > 0 )
315  {
316  $imagepath_original = str_replace("/$this->obj_id/", "/$objectId/", $imagepath_original);
317  }
318 
319  if (!file_exists($imagepath)) {
320  ilUtil::makeDirParents($imagepath);
321  }
322  $filename = $this->getImageFilename();
323  if (!copy($imagepath_original . $filename, $imagepath . $filename)) {
324  print "image could not be duplicated!!!! ";
325  }
326  }
327 
328  function copyImage($question_id, $source_questionpool)
329  {
330  $imagepath = $this->getImagePath();
331  $imagepath_original = str_replace("/$this->id/images", "/$question_id/images", $imagepath);
332  $imagepath_original = str_replace("/$this->obj_id/", "/$source_questionpool/", $imagepath_original);
333  if (!file_exists($imagepath))
334  {
335  ilUtil::makeDirParents($imagepath);
336  }
337  $filename = $this->getImageFilename();
338  if (!copy($imagepath_original . $filename, $imagepath . $filename))
339  {
340  print "image could not be copied!!!! ";
341  }
342  }
343 
353  function loadFromDb($question_id)
354  {
355  global $ilDB;
356 
357  $result = $ilDB->queryF("SELECT qpl_questions.*, " . $this->getAdditionalTableName() . ".* FROM qpl_questions LEFT JOIN " . $this->getAdditionalTableName() . " ON " . $this->getAdditionalTableName() . ".question_fi = qpl_questions.question_id WHERE qpl_questions.question_id = %s",
358  array("integer"),
359  array($question_id)
360  );
361  if ($result->numRows() == 1)
362  {
363  $data = $ilDB->fetchAssoc($result);
364  $this->setId($question_id);
365  $this->setObjId($data["obj_fi"]);
366  $this->setTitle($data["title"]);
367  $this->setComment($data["description"]);
368  $this->setOriginalId($data["original_id"]);
369  $this->setNrOfTries($data['nr_of_tries']);
370  $this->setAuthor($data["author"]);
371  $this->setPoints($data["points"]);
372  $this->setOwner($data["owner"]);
373  $this->setIsMultipleChoice($data["is_multiple_choice"] == self::MODE_MULTIPLE_CHOICE);
374  include_once("./Services/RTE/classes/class.ilRTE.php");
375  $this->setQuestion(ilRTE::_replaceMediaObjectImageSrc($data["question_text"], 1));
376  $this->setImageFilename($data["image_file"]);
377  $this->setEstimatedWorkingTime(substr($data["working_time"], 0, 2), substr($data["working_time"], 3, 2), substr($data["working_time"], 6, 2));
378 
379  try
380  {
381  $this->setAdditionalContentEditingMode($data['add_cont_edit_mode']);
382  }
384  {
385  }
386 
387  $result = $ilDB->queryF("SELECT * FROM qpl_a_imagemap WHERE question_fi = %s ORDER BY aorder ASC",
388  array("integer"),
389  array($question_id)
390  );
391  include_once "./Modules/TestQuestionPool/classes/class.assAnswerImagemap.php";
392  if ($result->numRows() > 0)
393  {
394  while ($data = $ilDB->fetchAssoc($result))
395  {
396  array_push($this->answers, new ASS_AnswerImagemap($data["answertext"], $data["points"], $data["aorder"], $data["coords"], $data["area"], $data['question_fi'], $data['points_unchecked']));
397  }
398  }
399  }
400  parent::loadFromDb($question_id);
401  }
402 
409  function uploadImagemap($imagemap_filename = "")
410  {
411  $added = 0;
412  if (!empty($imagemap_filename))
413  {
414  $fp = fopen($imagemap_filename, "r");
415  $contents = fread($fp, filesize($imagemap_filename));
416  fclose($fp);
417  if (preg_match_all("/<area(.+)>/siU", $contents, $matches))
418  {
419  for ($i=0; $i< count($matches[1]); $i++)
420  {
421  preg_match("/alt\s*=\s*\"(.+)\"\s*/siU", $matches[1][$i], $alt);
422  preg_match("/coords\s*=\s*\"(.+)\"\s*/siU", $matches[1][$i], $coords);
423  preg_match("/shape\s*=\s*\"(.+)\"\s*/siU", $matches[1][$i], $shape);
424  $this->addAnswer($alt[1], 0.0, count($this->answers), $coords[1], $shape[1]);
425  $added++;
426  }
427  }
428  }
429  return $added;
430  }
431 
432  function getImageFilename()
433  {
434  return $this->image_filename;
435  }
436 
444  function setImageFilename($image_filename, $image_tempfilename = "")
445  {
446  if (!empty($image_filename))
447  {
448  $image_filename = str_replace(" ", "_", $image_filename);
449  $this->image_filename = $image_filename;
450  }
451  if (!empty($image_tempfilename))
452  {
453  $imagepath = $this->getImagePath();
454  if (!file_exists($imagepath))
455  {
456  ilUtil::makeDirParents($imagepath);
457  }
458  if (!ilUtil::moveUploadedFile($image_tempfilename, $image_filename, $imagepath.$image_filename))
459  {
460  $this->ilias->raiseError("The image could not be uploaded!", $this->ilias->error_obj->MESSAGE);
461  }
462  global $ilLog; $ilLog->write("gespeichert: " . $imagepath.$image_filename);
463  }
464  }
465 
475  function get_imagemap_contents($href = "#") {
476  $imagemap_contents = "<map name=\"".$this->title."\"> ";
477  for ($i = 0; $i < count($this->answers); $i++) {
478  $imagemap_contents .= "<area alt=\"".$this->answers[$i]->getAnswertext()."\" ";
479  $imagemap_contents .= "shape=\"".$this->answers[$i]->getArea()."\" ";
480  $imagemap_contents .= "coords=\"".$this->answers[$i]->getCoords()."\" ";
481  $imagemap_contents .= "href=\"$href&selimage=" . $this->answers[$i]->getOrder() . "\" /> ";
482  }
483  $imagemap_contents .= "</map>";
484  return $imagemap_contents;
485  }
486 
501  function addAnswer(
502  $answertext = "",
503  $points = 0.0,
504  $order = 0,
505  $coords="",
506  $area="",
507  $points_unchecked = 0.0
508  )
509  {
510  include_once "./Modules/TestQuestionPool/classes/class.assAnswerImagemap.php";
511  if (array_key_exists($order, $this->answers))
512  {
513  // Insert answer
514  $answer = new ASS_AnswerImagemap($answertext, $points, $order, $coords, $area, -1, $points_unchecked);
515  for ($i = count($this->answers) - 1; $i >= $order; $i--)
516  {
517  $this->answers[$i+1] = $this->answers[$i];
518  $this->answers[$i+1]->setOrder($i+1);
519  }
520  $this->answers[$order] = $answer;
521  }
522  else
523  {
524  // Append answer
525  $answer = new ASS_AnswerImagemap($answertext, $points, count($this->answers), $coords, $area, -1, $points_unchecked);
526  array_push($this->answers, $answer);
527  }
528  }
529 
539  function getAnswerCount() {
540  return count($this->answers);
541  }
542 
554  function getAnswer($index = 0) {
555  if ($index < 0) return NULL;
556  if (count($this->answers) < 1) return NULL;
557  if ($index >= count($this->answers)) return NULL;
558  return $this->answers[$index];
559  }
560 
570  function &getAnswers()
571  {
572  return $this->answers;
573  }
574 
585  function deleteArea($index = 0)
586  {
587  if ($index < 0) return;
588  if (count($this->answers) < 1) return;
589  if ($index >= count($this->answers)) return;
590  unset($this->answers[$index]);
591  $this->answers = array_values($this->answers);
592  for ($i = 0; $i < count($this->answers); $i++) {
593  if ($this->answers[$i]->getOrder() > $index) {
594  $this->answers[$i]->setOrder($i);
595  }
596  }
597  }
598 
607  function flushAnswers() {
608  $this->answers = array();
609  }
610 
619  function getMaximumPoints() {
620  $points = 0;
621  foreach ($this->answers as $key => $value) {
622  if($this->is_multiple_choice)
623  {
624  if($value->getPoints() > $value->getPointsUnchecked())
625  {
626  $points += $value->getPoints();
627  }
628  else
629  {
630  $points += $value->getPointsUnchecked();
631  }
632  }
633  else
634  {
635  if($value->getPoints() > $points)
636  {
637  $points = $value->getPoints();
638  }
639  }
640  }
641  return $points;
642  }
643 
654  public function calculateReachedPoints($active_id, $pass = NULL, $returndetails = FALSE)
655  {
656  if( $returndetails )
657  {
658  throw new ilTestException('return details not implemented for '.__METHOD__);
659  }
660 
661  global $ilDB;
662 
663  $found_values = array();
664  if (is_null($pass))
665  {
666  $pass = $this->getSolutionMaxPass($active_id);
667  }
668  $result = $this->getCurrentSolutionResultSet($active_id, $pass);
669  while ($data = $ilDB->fetchAssoc($result))
670  {
671  if (strcmp($data["value1"], "") != 0)
672  {
673  array_push($found_values, $data["value1"]);
674  }
675  }
676 
677  $points = $this->calculateReachedPointsForSolution($found_values);
678 
679  return $points;
680  }
681 
683  {
684  return $this->calculateReachedPointsForSolution(array_values($previewSession->getParticipantsSolution()));
685  }
686 
687  public function isAutosaveable()
688  {
689  return false; // #15217
690  }
691 
700  public function saveWorkingData($active_id, $pass = NULL)
701  {
702  global $ilDB;
703  global $ilUser;
704 
705  if (is_null($pass))
706  {
707  include_once "./Modules/Test/classes/class.ilObjTest.php";
708  $pass = ilObjTest::_getPass($active_id);
709  }
710 
711  $this->getProcessLocker()->requestUserSolutionUpdateLock();
712 
713  if($this->is_multiple_choice && strlen($_GET['remImage']))
714  {
715  $query = "DELETE FROM tst_solutions WHERE active_fi = %s AND question_fi = %s AND pass = %s AND value1 = %s";
716  $types = array("integer", "integer", "integer", "integer");
717  $values = array($active_id, $this->getId(), $pass, $_GET['remImage']);
718 
719  if( $this->getStep() !== NULL )
720  {
721  $query .= " AND step = %s ";
722  $types[] = 'integer';
723  $values[] = $this->getStep();
724  }
725  $affectedRows = $ilDB->manipulateF($query, $types, $values);
726  }
727  elseif(!$this->is_multiple_choice)
728  {
729  $affectedRows = $this->removeCurrentSolution($active_id, $pass);
730  }
731 
732  if (strlen($_GET["selImage"]))
733  {
734  $imageWasSelected = true;
735 
736  $types = array('integer', 'integer', 'integer', 'integer');
737  $values = array($active_id, $this->getId(), $pass, (int)$_GET['selImage']);
738  $query = 'DELETE FROM tst_solutions WHERE active_fi = %s AND question_fi = %s AND pass = %s AND value1 = %s';
739  if($this->getStep() != null)
740  {
741  $types[] = 'integer';
742  $values[] = $this->getStep();
743  $query .= ' AND step = %s';
744  }
745 
746  $ilDB->manipulateF($query, $types, $values);
747 
748  $affectedRows = $this->saveCurrentSolution($active_id, $pass, $_GET['selImage'], null);
749  }
750  else
751  {
752  $imageWasSelected = false;
753  }
754 
755  $this->getProcessLocker()->releaseUserSolutionUpdateLock();
756 
757  require_once 'Modules/Test/classes/class.ilObjAssessmentFolder.php';
759  {
760  if( $imageWasSelected )
761  {
762  $this->logAction($this->lng->txtlng("assessment", "log_user_entered_values", ilObjAssessmentFolder::_getLogLanguage()), $active_id, $this->getId());
763  }
764  else
765  {
766  $this->logAction($this->lng->txtlng("assessment", "log_user_not_entered_values", ilObjAssessmentFolder::_getLogLanguage()), $active_id, $this->getId());
767  }
768  }
769 
770  return true;
771  }
772 
773  protected function savePreviewData(ilAssQuestionPreviewSession $previewSession)
774  {
775  $solution = $previewSession->getParticipantsSolution();
776 
777  if( $this->is_multiple_choice && strlen($_GET['remImage']) )
778  {
779  unset($solution[(int)$_GET['remImage']]);
780  }
781 
782  if( strlen($_GET['selImage']) )
783  {
784  if( !$this->is_multiple_choice )
785  {
786  $solution = array();
787  }
788 
789  $solution[(int)$_GET['selImage']] = (int)$_GET['selImage'];
790  }
791 
792  $previewSession->setParticipantsSolution($solution);
793  }
794 
803  protected function reworkWorkingData($active_id, $pass, $obligationsAnswered)
804  {
805  // nothing to rework!
806  }
807 
808  function syncWithOriginal()
809  {
810  if ($this->getOriginalId())
811  {
813  }
814  }
815 
824  function getQuestionType()
825  {
826  return "assImagemapQuestion";
827  }
828 
838  {
839  return "qpl_qst_imagemap";
840  }
841 
851  {
852  return "qpl_a_imagemap";
853  }
854 
860  {
862  foreach ($this->answers as $index => $answer)
863  {
864  $text .= $this->feedbackOBJ->getSpecificAnswerFeedbackContent($this->getId(), $index);
865  }
866  return $text;
867  }
868 
881  public function setExportDetailsXLS(&$worksheet, $startrow, $active_id, $pass, &$format_title, &$format_bold)
882  {
883  include_once ("./Services/Excel/classes/class.ilExcelUtils.php");
884  $solution = $this->getSolutionValues($active_id, $pass);
885  $worksheet->writeString($startrow, 0, ilExcelUtils::_convert_text($this->lng->txt($this->getQuestionType())), $format_title);
886  $worksheet->writeString($startrow, 1, ilExcelUtils::_convert_text($this->getTitle()), $format_title);
887  $i = 1;
888  foreach ($this->getAnswers() as $id => $answer)
889  {
890  $worksheet->writeString($startrow + $i, 0, ilExcelUtils::_convert_text($answer->getArea() . ": " . $answer->getCoords()), $format_bold);
891  if ($id == $solution[0]["value1"])
892  {
893  $worksheet->write($startrow + $i, 1, 1);
894  }
895  else
896  {
897  $worksheet->write($startrow + $i, 1, 0);
898  }
899  $i++;
900  }
901  return $startrow + $i + 1;
902  }
903 
907  public function deleteImage()
908  {
909  $file = $this->getImagePath() . $this->getImageFilename();
910  @unlink($file);
911  $this->flushAnswers();
912  $this->image_filename = "";
913  }
914 
918  public function toJSON()
919  {
920  include_once("./Services/RTE/classes/class.ilRTE.php");
921  $result = array();
922  $result['id'] = (int) $this->getId();
923  $result['type'] = (string) $this->getQuestionType();
924  $result['title'] = (string) $this->getTitle();
925  $result['question'] = $this->formatSAQuestion($this->getQuestion());
926  $result['nr_of_tries'] = (int) $this->getNrOfTries();
927  $result['shuffle'] = (bool) $this->getShuffle();
928  $result['is_multiple'] = (bool) $this->getIsMultipleChoice();
929  $result['feedback'] = array(
930  'onenotcorrect' => $this->formatSAQuestion($this->feedbackOBJ->getGenericFeedbackTestPresentation($this->getId(), false)),
931  'allcorrect' => $this->formatSAQuestion($this->feedbackOBJ->getGenericFeedbackTestPresentation($this->getId(), true))
932  );
933  $result['image'] = (string) $this->getImagePathWeb() . $this->getImageFilename();
934 
935  $answers = array();
936  $order = 0;
937  foreach ($this->getAnswers() as $key => $answer_obj)
938  {
939  array_push($answers, array(
940  "answertext" => (string)$answer_obj->getAnswertext(),
941  "points" => (float)$answer_obj->getPoints(),
942  "points_unchecked" => (float)$answer_obj->getPointsUnchecked(),
943  "order" => (int)$order,
944  "coords" => $answer_obj->getCoords(),
945  "state" => $answer_obj->getState(),
946  "area" => $answer_obj->getArea(),
948  $this->feedbackOBJ->getSpecificAnswerFeedbackExportPresentation($this->getId(), $key), 0
949  )
950  ));
951  $order++;
952  }
953  $result['answers'] = $answers;
954 
955  $mobs = ilObjMediaObject::_getMobsOfObject("qpl:html", $this->getId());
956  $result['mobs'] = $mobs;
957 
958  return json_encode($result);
959  }
960 
965  protected function calculateReachedPointsForSolution($found_values)
966  {
967  $points = 0;
968  if(count($found_values) > 0)
969  {
970  foreach($this->answers as $key => $answer)
971  {
972  if(in_array($key, $found_values))
973  {
974  $points += $answer->getPoints();
975  } elseif($this->getIsMultipleChoice())
976  {
977  $points += $answer->getPointsUnchecked();
978  }
979  }
980  return $points;
981  }
982  return $points;
983  }
984 
993  public function getOperators($expression)
994  {
995  require_once "./Modules/TestQuestionPool/classes/class.ilOperatorsExpressionMapping.php";
997  }
998 
1003  public function getExpressionTypes()
1004  {
1005  return array(
1010  );
1011  }
1012 
1021  public function getUserQuestionResult($active_id, $pass)
1022  {
1024  global $ilDB;
1025  $result = new ilUserQuestionResult($this, $active_id, $pass);
1026 
1027  $data = $ilDB->queryF(
1028  "SELECT value1+1 as value1 FROM tst_solutions WHERE active_fi = %s AND pass = %s AND question_fi = %s AND step = (
1029  SELECT MAX(step) FROM tst_solutions WHERE active_fi = %s AND pass = %s AND question_fi = %s
1030  )",
1031  array("integer", "integer", "integer","integer", "integer", "integer"),
1032  array($active_id, $pass, $this->getId(), $active_id, $pass, $this->getId())
1033  );
1034 
1035  while($row = $ilDB->fetchAssoc($data))
1036  {
1037  $result->addKeyValue($row["value1"], $row["value1"]);
1038  }
1039 
1040  $points = $this->calculateReachedPoints($active_id, $pass);
1041  $max_points = $this->getMaximumPoints();
1042 
1043  $result->setReachedPercentage(($points/$max_points) * 100);
1044 
1045  return $result;
1046  }
1047 
1056  public function getAvailableAnswerOptions($index = null)
1057  {
1058  if($index !== null)
1059  {
1060  return $this->getAnswer($index);
1061  }
1062  else
1063  {
1064  return $this->getAnswers();
1065  }
1066  }
1067 }