1<?php
2/* Copyright (c) 1998-2013 ILIAS open source, Extended GPL, see docs/LICENSE */
3
4require_once 'Modules/Test/classes/class.ilTestRandomQuestionSetQuestion.php';
5
6/**
7 * @author		Björn Heyser <bheyser@databay.de>
8 * @version		$Id$
9 *
10 * @package     Modules/Test
11 */
12// hey: fixRandomTestBuildable - iterator interface for collection
13class ilTestRandomQuestionSetQuestionCollection implements
14    Iterator
15// hey.
16{
17    private $questions = array();
18
19    public function setQuestions($questions)
20    {
21        $this->questions = $questions;
22    }
23
24    public function getQuestions()
25    {
26        return $this->questions;
27    }
28
29    public function addQuestion(ilTestRandomQuestionSetQuestion $question)
30    {
31        $this->questions[] = $question;
32    }
33
34    // hey: fixRandomTestBuildable - iterator interface for collection
35    /* @return ilTestRandomQuestionSetQuestion */
36    public function current()
37    {
38        return current($this->questions);
39    }
40    /* @return ilTestRandomQuestionSetQuestion */
41    public function next()
42    {
43        return next($this->questions);
44    }
45    /* @return string */
46    public function key()
47    {
48        return key($this->questions);
49    }
50    /* @return bool */
51    public function valid()
52    {
53        return key($this->questions) !== null;
54    }
55    /* @return ilTestRandomQuestionSetQuestion */
56    public function rewind()
57    {
58        return reset($this->questions);
59    }
60    // hey.
61
62    public function isGreaterThan($amount)
63    {
64        return count($this->questions) > $amount;
65    }
66
67    public function isSmallerThan($amount)
68    {
69        return count($this->questions) < $amount;
70    }
71
72    /**
73     * @param int $requiredAmount
74     * @return int
75     */
76    public function getMissingCount($requiredAmount)
77    {
78        // hey: fixRandomTestBuildable - fix returning missing count instead of difference (neg values!)
79        $difference = $requiredAmount - count($this->questions);
80        $missingCount = $difference < 0 ? 0 : $difference;
81        return $missingCount;
82        // hey.
83    }
84
85    public function shuffleQuestions()
86    {
87        shuffle($this->questions);
88    }
89
90    public function mergeQuestionCollection(self $questionCollection)
91    {
92        $this->questions = array_merge($this->questions, $questionCollection->getQuestions());
93    }
94
95    public function getUniqueQuestionCollection()
96    {
97        $uniqueQuestions = array();
98
99        foreach ($this->getQuestions() as $question) {
100            /* @var ilTestRandomQuestionSetQuestion $question */
101
102            if (!isset($uniqueQuestions[$question->getQuestionId()])) {
103                $uniqueQuestions[$question->getQuestionId()] = $question;
104            }
105        }
106
107        $uniqueQuestionCollection = new self();
108        $uniqueQuestionCollection->setQuestions($uniqueQuestions);
109
110        return $uniqueQuestionCollection;
111    }
112
113    public function getRelativeComplementCollection(self $questionCollection)
114    {
115        // hey: fixRandomTestBuildable - comment for refactoring
116        /**
117         * actually i would like to consider $this as quantity A
118         * passed $questionCollection is should be considered as quantity B
119         *
120         * --> relative complement usually means all element from B missing in A
121         *
122         * indeed we are considering $questionCollection as A and $this as B currently (!)
123         * when changing, do not forget to switch caller and param for all usages (!)
124         */
125        // hey.
126
127        $questionIds = array_flip($questionCollection->getInvolvedQuestionIds());
128
129        $relativeComplementCollection = new self();
130
131        foreach ($this->getQuestions() as $question) {
132            if (!isset($questionIds[$question->getQuestionId()])) {
133                $relativeComplementCollection->addQuestion($question);
134            }
135        }
136
137        return $relativeComplementCollection;
138    }
139
140    // hey: fixRandomTestBuildable - advanced need for quantity tools
141    /**
142     * @param ilTestRandomQuestionSetQuestionCollection $questionCollection
143     * @return ilTestRandomQuestionSetQuestionCollection
144     */
145    public function getIntersectionCollection(self $questionCollection)
146    {
147        $questionIds = array_flip($questionCollection->getInvolvedQuestionIds());
148
149        $intersectionCollection = new self();
150
151        foreach ($this->getQuestions() as $question) {
152            if (!isset($questionIds[$question->getQuestionId()])) {
153                continue;
154            }
155
156            $intersectionCollection->addQuestion($question);
157        }
158
159        return $intersectionCollection;
160    }
161
162    /**
163     * @return int
164     */
165    public function getQuestionAmount()
166    {
167        return count($this->getQuestions());
168    }
169    // hey.
170
171    public function getInvolvedQuestionIds()
172    {
173        $questionIds = array();
174
175        foreach ($this->getQuestions() as $question) {
176            $questionIds[] = $question->getQuestionId();
177        }
178
179        return $questionIds;
180    }
181
182    public function getRandomQuestionCollection($requiredAmount)
183    {
184        $randomKeys = $this->getRandomArrayKeys($this->questions, $requiredAmount);
185
186        $randomQuestionCollection = new self();
187
188        foreach ($randomKeys as $randomKey) {
189            $randomQuestionCollection->addQuestion($this->questions[$randomKey]);
190        }
191
192        return $randomQuestionCollection;
193    }
194
195    private function getRandomArrayKeys($array, $numKeys)
196    {
197        if ($numKeys < 1) {
198            return array();
199        }
200
201        if ($numKeys > 1) {
202            return array_rand($array, $numKeys);
203        }
204
205        return array( array_rand($array, $numKeys) );
206    }
207}
208