1<?php
2/* Copyright (c) 1998-2013 ILIAS open source, Extended GPL, see docs/LICENSE */
3
4require_once './Modules/TestQuestionPool/classes/class.assQuestion.php';
5require_once './Modules/Test/classes/inc.AssessmentConstants.php';
6require_once './Modules/TestQuestionPool/interfaces/interface.ilObjQuestionScoringAdjustable.php';
7require_once './Modules/TestQuestionPool/interfaces/interface.iQuestionCondition.php';
8require_once './Modules/TestQuestionPool/classes/class.ilUserQuestionResult.php';
9
10/**
11 * Class for Java Applet Questions
12 *
13 * assJavaApplet is a class for Java Applet Questions.
14 *
15 * @author		Helmut Schottmüller <helmut.schottmueller@mac.com>
16 * @author		Björn Heyser <bheyser@databay.de>
17 * @author		Maximilian Becker <mbecker@databay.de>
18 *
19 * @version		$Id$
20 *
21 * @ingroup		ModulesTestQuestionPool
22 */
23class assJavaApplet extends assQuestion implements ilObjQuestionScoringAdjustable, iQuestionCondition
24{
25    /**
26    * Java applet file name
27    *
28    * The file name of the java applet
29    *
30    * @var string
31    */
32    public $javaapplet_filename;
33
34    /**
35    * Java Applet code parameter
36    *
37    * Java Applet code parameter
38    *
39    * @var string
40    */
41    public $java_code;
42
43    /**
44    * Java Applet codebase parameter
45    *
46    * Java Applet codebase parameter
47    *
48    * @var string
49    */
50    public $java_codebase;
51
52    /**
53    * Java Applet archive parameter
54    *
55    * Java Applet archive parameter
56    *
57    * @var string
58    */
59    public $java_archive;
60
61    /**
62    * Java Applet width parameter
63    *
64    * Java Applet width parameter
65    *
66    * @var integer
67    */
68    public $java_width;
69
70    /**
71    * Java Applet height parameter
72    *
73    * Java Applet height parameter
74    *
75    * @var integer
76    */
77    public $java_height;
78
79    /**
80    * Additional java applet parameters
81    *
82    * Additional java applet parameters
83    *
84    * @var array
85    */
86    public $parameters;
87
88    /**
89     * assJavaApplet constructor
90     *
91     * The constructor takes possible arguments an creates an instance of the assJavaApplet object.
92     *
93     * @param string  $title    			A title string to describe the question.
94     * @param string  $comment  			A comment string to describe the question.
95     * @param string  $author   			A string containing the name of the questions author.
96     * @param integer $owner    			A numerical ID to identify the owner/creator.
97     * @param string  $question 			The question string of the multiple choice question.
98     * @param string  $javaapplet_filename	Applet filename.
99     *
100     * @return \assJavaApplet
101     */
102    public function __construct(
103        $title = "",
104        $comment = "",
105        $author = "",
106        $owner = -1,
107        $question = "",
108        $javaapplet_filename = ""
109    ) {
110        parent::__construct($title, $comment, $author, $owner, $question);
111        $this->javaapplet_filename = $javaapplet_filename;
112        $this->parameters = array();
113    }
114
115    /**
116     * Sets the applet parameters from a parameter string containing all parameters in a list
117     *
118     * Sets the applet parameters from a parameter string containing all parameters in a list
119     *
120     * @param string $params All applet parameters in a list
121     */
122    public function splitParams($params = "")
123    {
124        $params_array = explode("<separator>", $params);
125        foreach ($params_array as $pair) {
126            if (preg_match("/(.*?)\=(.*)/", $pair, $matches)) {
127                switch ($matches[1]) {
128                    case "java_code":
129                        $this->java_code = $matches[2];
130                        break;
131                    case "java_codebase":
132                        $this->java_codebase = $matches[2];
133                        break;
134                    case "java_archive":
135                        $this->java_archive = $matches[2];
136                        break;
137                    case "java_width":
138                        $this->java_width = $matches[2];
139                        break;
140                    case "java_height":
141                        $this->java_height = $matches[2];
142                        break;
143                }
144                if (preg_match("/param_name_(\d+)/", $matches[1], $found_key)) {
145                    $this->parameters[$found_key[1]]["name"] = $matches[2];
146                }
147                if (preg_match("/param_value_(\d+)/", $matches[1], $found_key)) {
148                    $this->parameters[$found_key[1]]["value"] = $matches[2];
149                }
150            }
151        }
152    }
153
154    /**
155     * Returns a string containing the applet parameters
156     *
157     * Returns a string containing the applet parameters. This is used for saving the applet data to database
158     *
159     * @return string All applet parameters
160     */
161    public function buildParams()
162    {
163        $params_array = array();
164        if ($this->java_code) {
165            array_push($params_array, "java_code=$this->java_code");
166        }
167        if ($this->java_codebase) {
168            array_push($params_array, "java_codebase=$this->java_codebase");
169        }
170        if ($this->java_archive) {
171            array_push($params_array, "java_archive=$this->java_archive");
172        }
173        if ($this->java_width) {
174            array_push($params_array, "java_width=$this->java_width");
175        }
176        if ($this->java_height) {
177            array_push($params_array, "java_height=$this->java_height");
178        }
179        foreach ($this->parameters as $key => $value) {
180            array_push($params_array, "param_name_$key=" . $value["name"]);
181            array_push($params_array, "param_value_$key=" . $value["value"]);
182        }
183
184        return join("<separator>", $params_array);
185    }
186
187    /**
188     * Returns a string containing the additional applet parameters
189     *
190     * @return string All additional applet parameters
191     */
192    public function buildParamsOnly()
193    {
194        $params_array = array();
195        if ($this->java_code) {
196            array_push($params_array, "java_code=$this->java_code");
197            array_push($params_array, "java_codebase=$this->java_codebase");
198            array_push($params_array, "java_archive=$this->java_archive");
199        }
200        foreach ($this->parameters as $key => $value) {
201            array_push($params_array, "param_name_$key=" . $value["name"]);
202            array_push($params_array, "param_value_$key=" . $value["value"]);
203        }
204        return join("<separator>", $params_array);
205    }
206
207    /**
208     * Returns true, if a imagemap question is complete for use
209     *
210     * @return boolean True, if the imagemap question is complete for use, otherwise false
211     */
212    public function isComplete()
213    {
214        if (strlen($this->title)
215            && $this->author
216            && $this->question
217            && $this->javaapplet_filename
218            && $this->java_width
219            && $this->java_height
220            && $this->getPoints() > 0
221        ) {
222            return true;
223        } elseif (strlen($this->title)
224            && $this->author
225            && $this->question
226            && $this->getJavaArchive()
227            && $this->getJavaCodebase()
228            && $this->java_width
229            && $this->java_height
230            && $this->getPoints() > 0
231        ) {
232            return true;
233        }
234        return false;
235    }
236
237
238    /**
239     * Saves a assJavaApplet object to a database
240     *
241     * @param string $original_id
242     *
243     * @return mixed|void
244     */
245    public function saveToDb($original_id = "")
246    {
247        $this->saveQuestionDataToDb($original_id);
248        $this->saveAdditionalQuestionDataToDb();
249        parent::saveToDb($original_id);
250    }
251
252    public function saveAdditionalQuestionDataToDb()
253    {
254        global $DIC;
255        $ilDB = $DIC['ilDB'];
256        $params = $this->buildParams();
257        // save additional data
258        $ilDB->manipulateF(
259            "DELETE FROM " . $this->getAdditionalTableName() . " WHERE question_fi = %s",
260            array( "integer" ),
261            array( $this->getId() )
262        );
263        $ilDB->manipulateF(
264            "INSERT INTO " . $this->getAdditionalTableName(
265                                                            ) . " (question_fi, image_file, params) VALUES (%s, %s, %s)",
266            array( "integer", "text", "text" ),
267            array(
268                                $this->getId(),
269                                $this->javaapplet_filename,
270                                $params
271                            )
272        );
273    }
274
275    /**
276     * Loads a assJavaApplet object from a database
277     *
278     * @param integer $question_id A unique key which defines the multiple choice test in the database
279     *
280     */
281    public function loadFromDb($question_id)
282    {
283        global $DIC;
284        $ilDB = $DIC['ilDB'];
285
286        $result = $ilDB->queryF(
287            "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",
288            array("integer"),
289            array($question_id)
290        );
291        if ($result->numRows() == 1) {
292            $data = $ilDB->fetchAssoc($result);
293            $this->setId($question_id);
294            $this->setObjId($data["obj_fi"]);
295            $this->setNrOfTries($data['nr_of_tries']);
296            $this->setTitle($data["title"]);
297            $this->setComment($data["description"]);
298            $this->setOriginalId($data["original_id"]);
299            $this->setAuthor($data["author"]);
300            $this->setPoints($data["points"]);
301            $this->setOwner($data["owner"]);
302            include_once("./Services/RTE/classes/class.ilRTE.php");
303            $this->setQuestion(ilRTE::_replaceMediaObjectImageSrc($data["question_text"], 1));
304            $this->setJavaAppletFilename($data["image_file"]);
305            $this->splitParams($data["params"]);
306            $this->setEstimatedWorkingTime(substr($data["working_time"], 0, 2), substr($data["working_time"], 3, 2), substr($data["working_time"], 6, 2));
307
308            try {
309                $this->setLifecycle(ilAssQuestionLifecycle::getInstance($data['lifecycle']));
310            } catch (ilTestQuestionPoolInvalidArgumentException $e) {
311                $this->setLifecycle(ilAssQuestionLifecycle::getDraftInstance());
312            }
313
314            try {
315                $this->setAdditionalContentEditingMode($data['add_cont_edit_mode']);
316            } catch (ilTestQuestionPoolException $e) {
317            }
318        }
319        parent::loadFromDb($question_id);
320    }
321
322    /**
323    * Duplicates an assJavaApplet
324    *
325    * @access public
326    */
327    public function duplicate($for_test = true, $title = "", $author = "", $owner = "", $testObjId = null)
328    {
329        if ($this->id <= 0) {
330            // The question has not been saved. It cannot be duplicated
331            return;
332        }
333        // duplicate the question in database
334        $this_id = $this->getId();
335        $thisObjId = $this->getObjId();
336
337        $clone = $this;
338        include_once("./Modules/TestQuestionPool/classes/class.assQuestion.php");
339        $original_id = assQuestion::_getOriginalId($this->id);
340        $clone->id = -1;
341
342        if ((int) $testObjId > 0) {
343            $clone->setObjId($testObjId);
344        }
345
346        if ($title) {
347            $clone->setTitle($title);
348        }
349        if ($author) {
350            $clone->setAuthor($author);
351        }
352        if ($owner) {
353            $clone->setOwner($owner);
354        }
355        if ($for_test) {
356            $clone->saveToDb($original_id);
357        } else {
358            $clone->saveToDb();
359        }
360
361        // copy question page content
362        $clone->copyPageOfQuestion($this_id);
363        // copy XHTML media objects
364        $clone->copyXHTMLMediaObjectsOfQuestion($this_id);
365        // duplicate the image
366        $clone->duplicateApplet($this_id, $thisObjId);
367
368        $clone->onDuplicate($thisObjId, $this_id, $clone->getObjId(), $clone->getId());
369
370        return $clone->id;
371    }
372
373    /**
374    * Copies an assJavaApplet object
375    *
376    * Copies an assJavaApplet object
377    *
378    * @access public
379    */
380    public function copyObject($target_questionpool_id, $title = "")
381    {
382        if ($this->id <= 0) {
383            // The question has not been saved. It cannot be duplicated
384            return;
385        }
386        // duplicate the question in database
387        $clone = $this;
388        include_once("./Modules/TestQuestionPool/classes/class.assQuestion.php");
389        $original_id = assQuestion::_getOriginalId($this->id);
390        $clone->id = -1;
391        $source_questionpool_id = $this->getObjId();
392        $clone->setObjId($target_questionpool_id);
393        if ($title) {
394            $clone->setTitle($title);
395        }
396        $clone->saveToDb();
397
398        // copy question page content
399        $clone->copyPageOfQuestion($original_id);
400        // copy XHTML media objects
401        $clone->copyXHTMLMediaObjectsOfQuestion($original_id);
402        // duplicate the image
403        $clone->copyApplet($original_id, $source_questionpool_id);
404
405        $clone->onCopy($source_questionpool_id, $original_id, $clone->getObjId(), $clone->getId());
406
407        return $clone->id;
408    }
409
410    public function createNewOriginalFromThisDuplicate($targetParentId, $targetQuestionTitle = "")
411    {
412        if ($this->id <= 0) {
413            // The question has not been saved. It cannot be duplicated
414            return;
415        }
416
417        include_once("./Modules/TestQuestionPool/classes/class.assQuestion.php");
418
419        $sourceQuestionId = $this->id;
420        $sourceParentId = $this->getObjId();
421
422        // duplicate the question in database
423        $clone = $this;
424        $clone->id = -1;
425
426        $clone->setObjId($targetParentId);
427
428        if ($targetQuestionTitle) {
429            $clone->setTitle($targetQuestionTitle);
430        }
431
432        $clone->saveToDb();
433        // copy question page content
434        $clone->copyPageOfQuestion($sourceQuestionId);
435        // copy XHTML media objects
436        $clone->copyXHTMLMediaObjectsOfQuestion($sourceQuestionId);
437        // duplicate the image
438        $clone->copyApplet($sourceQuestionId, $sourceParentId);
439
440        $clone->onCopy($sourceParentId, $sourceQuestionId, $clone->getObjId(), $clone->getId());
441
442        return $clone->id;
443    }
444
445    public function duplicateApplet($question_id, $objectId = null)
446    {
447        $javapath = $this->getJavaPath();
448        $javapath_original = preg_replace("/([^\d])$this->id([^\d])/", "\${1}$question_id\${2}", $javapath);
449
450        if ((int) $objectId > 0) {
451            $javapath_original = str_replace("/$this->obj_id/", "/$objectId/", $javapath_original);
452        }
453
454        if (!file_exists($javapath)) {
455            ilUtil::makeDirParents($javapath);
456        }
457        $filename = $this->getJavaAppletFilename();
458        if (!copy($javapath_original . $filename, $javapath . $filename)) {
459            print "java applet could not be duplicated!!!! ";
460        }
461    }
462
463    public function copyApplet($question_id, $source_questionpool)
464    {
465        $javapath = $this->getJavaPath();
466        $javapath_original = preg_replace("/([^\d])$this->id([^\d])/", "\${1}$question_id\${2}", $javapath);
467        $javapath_original = str_replace("/$this->obj_id/", "/$source_questionpool/", $javapath_original);
468        if (!file_exists($javapath)) {
469            ilUtil::makeDirParents($javapath);
470        }
471        $filename = $this->getJavaAppletFilename();
472        if (!copy($javapath_original . $filename, $javapath . $filename)) {
473            print "java applet could not be copied!!!! ";
474        }
475    }
476
477    /**
478    * Returns the java applet code parameter
479    *
480    * Returns the java applet code parameter
481    *
482    * @return string java applet code parameter
483    * @access public
484    */
485    public function getJavaCode()
486    {
487        return $this->java_code;
488    }
489
490    /**
491    * Returns the java applet codebase parameter
492    *
493    * Returns the java applet codebase parameter
494    *
495    * @return string java applet codebase parameter
496    * @access public
497    */
498    public function getJavaCodebase()
499    {
500        return $this->java_codebase;
501    }
502
503    /**
504    * Returns the java applet archive parameter
505    *
506    * Returns the java applet archive parameter
507    *
508    * @return string java applet archive parameter
509    * @access public
510    */
511    public function getJavaArchive()
512    {
513        return $this->java_archive;
514    }
515
516    /**
517    * Sets the java applet code parameter
518    *
519    * Sets the java applet code parameter
520    *
521    * @param string java applet code parameter
522    * @access public
523    */
524    public function setJavaCode($java_code = "")
525    {
526        $this->java_code = $java_code;
527    }
528
529    /**
530    * Sets the java applet codebase parameter
531    *
532    * Sets the java applet codebase parameter
533    *
534    * @param string java applet codebase parameter
535    * @access public
536    */
537    public function setJavaCodebase($java_codebase = "")
538    {
539        $this->java_codebase = $java_codebase;
540    }
541
542    /**
543    * Sets the java applet archive parameter
544    *
545    * Sets the java applet archive parameter
546    *
547    * @param string java applet archive parameter
548    * @access public
549    */
550    public function setJavaArchive($java_archive = "")
551    {
552        $this->java_archive = $java_archive;
553    }
554
555    /**
556    * Returns the java applet width parameter
557    *
558    * Returns the java applet width parameter
559    *
560    * @return integer java applet width parameter
561    * @access public
562    */
563    public function getJavaWidth()
564    {
565        return $this->java_width;
566    }
567
568    /**
569     * Sets the java applet width parameter
570     *
571     * Sets the java applet width parameter
572     *
573     * @param string $java_width applet width parameter
574     */
575    public function setJavaWidth($java_width = "")
576    {
577        $this->java_width = $java_width;
578    }
579
580    /**
581    * Returns the java applet height parameter
582    *
583    * Returns the java applet height parameter
584    *
585    * @return integer java applet height parameter
586    * @access public
587    */
588    public function getJavaHeight()
589    {
590        return $this->java_height;
591    }
592
593    /**
594    * Sets the java applet height parameter
595    *
596    * Sets the java applet height parameter
597    *
598    * @param integer java applet height parameter
599    * @access public
600    */
601    public function setJavaHeight($java_height = "")
602    {
603        $this->java_height = $java_height;
604    }
605
606    /**
607     * Returns the points, a learner has reached answering the question.
608     * The points are calculated from the given answers.
609     *
610     * @param integer $active_id
611     * @param integer $pass
612     * @param boolean $returndetails (deprecated !!)
613     *
614     * @throws ilTestException
615     * @return integer/array $points/$details (array $details is deprecated !!)
616     */
617    public function calculateReachedPoints($active_id, $pass = null, $authorizedSolution = true, $returndetails = false)
618    {
619        if ($returndetails) {
620            throw new ilTestException('return details not implemented for ' . __METHOD__);
621        }
622
623        global $DIC;
624        $ilDB = $DIC['ilDB'];
625
626        $found_values = array();
627        if (is_null($pass)) {
628            $pass = $this->getSolutionMaxPass($active_id);
629        }
630
631        $result = $this->getCurrentSolutionResultSet($active_id, $pass, $authorizedSolution);
632
633        $points = 0;
634        while ($data = $ilDB->fetchAssoc($result)) {
635            $points += $data["points"];
636        }
637
638        return $points;
639    }
640
641    public function calculateReachedPointsFromPreviewSession(ilAssQuestionPreviewSession $previewSession)
642    {
643        $points = 0;
644        foreach ($previewSession->getParticipantsSolution() as $solution) {
645            if (isset($solution['points'])) {
646                $points += $solution['points'];
647            }
648        }
649
650        $reachedPoints = $this->deductHintPointsFromReachedPoints($previewSession, $points);
651
652        return $this->ensureNonNegativePoints($reachedPoints);
653    }
654
655    // hey: prevPassSolutions - bypass intermediate solution requests and deligate
656    //							to own implementation for requests to authorized solutions
657    public function getSolutionValues($active_id, $pass = null, $authorized = true)
658    {
659        if (!$authorized) {
660            return array();
661        }
662
663        return $this->getSolutionValuesRegardlessOfAuthorization($active_id, $pass);
664    }
665
666    public function getSolutionValuesRegardlessOfAuthorization($active_id, $pass = null)
667    {
668        // - similar to getSolutionValues in general
669        // - does not consider "step" in any kind
670        // - returns a customized associative array
671        // - is the original implementation for qtype
672        return $this->getReachedInformation($active_id, $pass);
673    }
674    // hey.
675
676    /**
677     * Returns the evaluation data, a learner has entered to answer the question
678     *
679     * @param      $active_id
680     * @param null $pass
681     *
682     * @return array
683     */
684    public function getReachedInformation($active_id, $pass = null)
685    {
686        global $DIC;
687        $ilDB = $DIC['ilDB'];
688
689        $found_values = array();
690        if (is_null($pass)) {
691            $pass = $this->getSolutionMaxPass($active_id);
692        }
693        $result = $ilDB->queryF(
694            "SELECT * FROM tst_solutions WHERE active_fi = %s AND question_fi = %s AND pass = %s",
695            array('integer','integer','integer'),
696            array($active_id, $this->getId(), $pass)
697        );
698        $counter = 1;
699        $user_result = array();
700        while ($data = $ilDB->fetchAssoc($result)) {
701            $true = 0;
702            if ($data["points"] > 0) {
703                $true = 1;
704            }
705            $solution = array(
706                "order" => $counter,
707                "points" => $data["points"],
708                "true" => $true,
709                "value1" => $data["value1"],
710                "value2" => $data["value2"],
711            );
712            $counter++;
713            array_push($user_result, $solution);
714        }
715        return $user_result;
716    }
717
718    /**
719    * Adds a new parameter value to the parameter list
720    *
721    * @param string $name The name of the parameter value
722    * @param string $value The value of the parameter value
723    * @access public
724    * @see $parameters
725    */
726    public function addParameter($name = "", $value = "")
727    {
728        $index = $this->getParameterIndex($name);
729        if ($index > -1) {
730            $this->parameters[$index] = array("name" => $name, "value" => $value);
731        } else {
732            array_push($this->parameters, array("name" => $name, "value" => $value));
733        }
734    }
735
736    public function addParameterAtIndex($index = 0, $name = "", $value = "")
737    {
738        if (array_key_exists($index, $this->parameters)) {
739            // insert parameter
740            $newparams = array();
741            for ($i = 0; $i < $index; $i++) {
742                array_push($newparams, $this->parameters[$i]);
743            }
744            array_push($newparams, array($name, $value));
745            for ($i = $index; $i < count($this->parameters); $i++) {
746                array_push($newparams, $this->parameters[$i]);
747            }
748            $this->parameters = $newparams;
749        } else {
750            array_push($this->parameters, array($name, $value));
751        }
752    }
753
754    /**
755    * Removes a parameter value from the parameter list
756    *
757    * @param integer $index The parameter index
758    * @access public
759    * @see $parameters
760    */
761    public function removeParameter($index)
762    {
763        if ($index < 0) {
764            return;
765        }
766        if (count($this->parameters) < 1) {
767            return;
768        }
769        if ($index >= count($this->parameters)) {
770            return;
771        }
772        unset($this->parameters[$index]);
773        $this->parameters = array_values($this->parameters);
774    }
775
776    /**
777    * Returns the paramter at a given index
778    *
779    * @param intege $index The index value of the parameter
780    * @return array The parameter at the given index
781    * @access public
782    * @see $parameters
783    */
784    public function getParameter($index)
785    {
786        if (($index < 0) or ($index >= count($this->parameters))) {
787            return undef;
788        }
789        return $this->parameters[$index];
790    }
791
792    /**
793    * Returns the index of an applet parameter
794    *
795    * @param string $name The name of the parameter value
796    * @return integer The index of the applet parameter or -1 if the parameter wasn't found
797    * @access private
798    * @see $parameters
799    */
800    public function getParameterIndex($name)
801    {
802        foreach ($this->parameters as $key => $value) {
803            if (array_key_exists($name, $value)) {
804                return $key;
805            }
806        }
807        return -1;
808    }
809
810    /**
811    * Returns the number of additional applet parameters
812    *
813    * @return integer The number of additional applet parameters
814    * @access public
815    * @see $parameters
816    */
817    public function getParameterCount()
818    {
819        return count($this->parameters);
820    }
821
822    /**
823    * Removes all applet parameters
824    *
825    * @access public
826    * @see $parameters
827    */
828    public function flushParams()
829    {
830        $this->parameters = array();
831    }
832
833    /**
834     * Saves the learners input of the question to the database.
835     *
836     * @access public
837     * @param integer $active_id Active id of the user
838     * @param integer $pass Test pass
839     * @return boolean $status
840     */
841    public function saveWorkingData($active_id, $pass = null, $authorized = true)
842    {
843        // nothing to save!
844
845        //$this->getProcessLocker()->requestUserSolutionUpdateLock();
846        // store in tst_solutions
847        //$this->getProcessLocker()->releaseUserSolutionUpdateLock();
848
849        return true;
850    }
851
852    protected function savePreviewData(ilAssQuestionPreviewSession $previewSession)
853    {
854        // nothing to save!
855
856        return true;
857    }
858
859    /**
860    * Gets the java applet file name
861    *
862    * @return string The java applet file of the assJavaApplet object
863    * @access public
864    * @see $javaapplet_filename
865    */
866    public function getJavaAppletFilename()
867    {
868        return $this->javaapplet_filename;
869    }
870
871    /**
872     * Sets the java applet file name
873     *
874     * @param        $javaapplet_filename
875     * @param string $javaapplet_tempfilename
876     *
877     * @see      $javaapplet_filename
878     */
879    public function setJavaAppletFilename($javaapplet_filename, $javaapplet_tempfilename = "")
880    {
881        if (!empty($javaapplet_filename)) {
882            $this->javaapplet_filename = $javaapplet_filename;
883        }
884        if (!empty($javaapplet_tempfilename)) {
885            $javapath = $this->getJavaPath();
886            if (!file_exists($javapath)) {
887                ilUtil::makeDirParents($javapath);
888            }
889
890            if (!ilUtil::moveUploadedFile($javaapplet_tempfilename, $javaapplet_filename, $javapath . $javaapplet_filename)) {
891                $ilLog->write("ERROR: java applet question: java applet not uploaded: $javaapplet_filename");
892            } else {
893                $this->setJavaCodebase();
894                $this->setJavaArchive();
895            }
896        }
897    }
898
899    public function deleteJavaAppletFilename()
900    {
901        @unlink($this->getJavaPath() . $this->getJavaAppletFilename());
902        $this->javaapplet_filename = "";
903    }
904
905    /**
906    * Returns the question type of the question
907    *
908    * @return integer The question type of the question
909    */
910    public function getQuestionType()
911    {
912        return "assJavaApplet";
913    }
914
915    /**
916    * Returns the name of the additional question data table in the database
917    *
918    * @return string The additional table name
919    */
920    public function getAdditionalTableName()
921    {
922        return "qpl_qst_javaapplet";
923    }
924
925    /**
926    * Collects all text in the question which could contain media objects
927    * which were created with the Rich Text Editor
928    */
929    public function getRTETextWithMediaObjects()
930    {
931        return parent::getRTETextWithMediaObjects();
932    }
933
934    /**
935     * {@inheritdoc}
936     */
937    public function setExportDetailsXLS($worksheet, $startrow, $active_id, $pass)
938    {
939        parent::setExportDetailsXLS($worksheet, $startrow, $active_id, $pass);
940
941        $solutions = $this->getSolutionValues($active_id, $pass);
942
943        $i = 1;
944        foreach ($solutions as $solution) {
945            $worksheet->setCell($startrow + $i, 1, $this->lng->txt("result") . " $i");
946            if (strlen($solution["value1"])) {
947                $worksheet->setCell($startrow + $i, 1, $solution["value1"]);
948            }
949            if (strlen($solution["value2"])) {
950                $worksheet->setCell($startrow + $i, 2, $solution["value2"]);
951            }
952            $i++;
953        }
954
955        return $startrow + $i + 1;
956    }
957
958    public function isAutosaveable()
959    {
960        return false;
961    }
962
963    /**
964     * Get all available operations for a specific question
965     *
966     * @param $expression
967     *
968     * @internal param string $expression_type
969     * @return array
970     */
971    public function getOperators($expression)
972    {
973        require_once "./Modules/TestQuestionPool/classes/class.ilOperatorsExpressionMapping.php";
974        return ilOperatorsExpressionMapping::getOperatorsByExpression($expression);
975    }
976
977    /**
978     * Get all available expression types for a specific question
979     * @return array
980     */
981    public function getExpressionTypes()
982    {
983        return array(
984            iQuestionCondition::PercentageResultExpression,
985            iQuestionCondition::EmptyAnswerExpression,
986        );
987    }
988
989    /**
990     * Get the user solution for a question by active_id and the test pass
991     *
992     * @param int $active_id
993     * @param int $pass
994     *
995     * @return ilUserQuestionResult
996     */
997    public function getUserQuestionResult($active_id, $pass)
998    {
999        $result = new ilUserQuestionResult($this, $active_id, $pass);
1000
1001        $points = $this->calculateReachedPoints($active_id, $pass);
1002        $max_points = $this->getMaximumPoints();
1003
1004        $result->setReachedPercentage(($points / $max_points) * 100);
1005
1006        return $result;
1007    }
1008
1009    /**
1010     * If index is null, the function returns an array with all anwser options
1011     * Else it returns the specific answer option
1012     *
1013     * @param null|int $index
1014     *
1015     * @return array|ASS_AnswerSimple
1016     */
1017    public function getAvailableAnswerOptions($index = null)
1018    {
1019        return array();
1020    }
1021
1022    // fau: testNav - new function getTestQuestionConfig()
1023    /**
1024     * Get the test question configuration
1025     * @return ilTestQuestionConfig
1026     */
1027    // hey: refactored identifiers
1028    public function buildTestPresentationConfig()
1029    // hey.
1030    {
1031        // hey: refactored identifiers
1032        return parent::buildTestPresentationConfig()
1033        // hey.
1034            ->setFormChangeDetectionEnabled(false)
1035            ->setBackgroundChangeDetectionEnabled(true);
1036    }
1037    // fau.
1038}
1039