ILIAS  Release_3_10_x_branch Revision 61812
 All Data Structures Namespaces Files Functions Variables Groups Pages
class.ilTestSequence.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 
34 {
43 
52 
61 
69  var $pass;
70 
79 
89  function ilTestSequence($active_id, $pass, $randomtest)
90  {
91  $this->active_id = $active_id;
92  $this->pass = $pass;
93  $this->isRandomTest = $randomtest;
94  $this->sequencedata = array(
95  "sequence" => array(),
96  "postponed" => array(),
97  "hidden" => array()
98  );
99  $this->loadFromDb();
100  $this->loadQuestions();
101  }
102 
103  function getActiveId()
104  {
105  return $this->active_id;
106  }
107 
108  function createNewSequence($max, $shuffle)
109  {
110  $newsequence = array();
111  if ($max > 0)
112  {
113  for ($i = 1; $i <= $max; $i++)
114  {
115  array_push($newsequence, $i);
116  }
117  if ($shuffle) $newsequence = $this->pcArrayShuffle($newsequence);
118  }
119  $this->sequencedata["sequence"] = $newsequence;
120  }
121 
129  private function loadQuestions()
130  {
131  global $ilDB;
132 
133  $this->questions = array();
134  if ($this->isRandomTest)
135  {
136  $query = sprintf("SELECT tst_test_random_question.* FROM tst_test_random_question, qpl_questions WHERE tst_test_random_question.active_fi = %s AND qpl_questions.question_id = tst_test_random_question.question_fi AND tst_test_random_question.pass = %s ORDER BY sequence",
137  $ilDB->quote($this->active_id . ""),
138  $ilDB->quote($this->pass . "")
139  );
140  $result = $ilDB->query($query);
141  // The following is a fix for random tests prior to ILIAS 3.8. If someone started a random test in ILIAS < 3.8, there
142  // is only one test pass (pass = 0) in tst_test_random_question while with ILIAS 3.8 there are questions for every test pass.
143  // To prevent problems with tests started in an older version and continued in ILIAS 3.8, the first pass should be taken if
144  // no questions are present for a newer pass.
145  if ($result->numRows() == 0)
146  {
147  $query = sprintf("SELECT tst_test_random_question.* FROM tst_test_random_question, qpl_questions WHERE tst_test_random_question.active_fi = %s AND qpl_questions.question_id = tst_test_random_question.question_fi AND tst_test_random_question.pass = 0 ORDER BY sequence",
148  $ilDB->quote($this->active_id . "")
149  );
150  $result = $ilDB->query($query);
151  }
152  }
153  else
154  {
155  $query = sprintf("SELECT tst_test_question.* FROM tst_test_question, qpl_questions, tst_active WHERE tst_active.active_id = %s AND tst_test_question.test_fi = tst_active.test_fi AND qpl_questions.question_id = tst_test_question.question_fi ORDER BY tst_test_question.sequence",
156  $ilDB->quote($this->active_id . "")
157  );
158  $result = $ilDB->query($query);
159  }
160  $index = 1;
161  while ($data = $result->fetchRow(MDB2_FETCHMODE_ASSOC))
162  {
163  $this->questions[$index++] = $data["question_fi"];
164  }
165  }
166 
175  private function loadFromDb()
176  {
177  global $ilDB;
178  $query = sprintf("SELECT * FROM tst_sequence WHERE active_fi = %s AND pass = %s",
179  $ilDB->quote($this->active_id . ""),
180  $ilDB->quote($this->pass . "")
181  );
182  $result = $ilDB->query($query);
183  if ($result->numRows())
184  {
185  $row = $result->fetchRow(MDB2_FETCHMODE_ASSOC);
186  $this->sequencedata = array(
187  "sequence" => unserialize($row["sequence"]),
188  "postponed" => unserialize($row["postponed"]),
189  "hidden" => unserialize($row["hidden"])
190  );
191  if (!is_array($this->sequencedata["sequence"])) $this->sequencedata["sequence"] = array();
192  if (!is_array($this->sequencedata["postponed"])) $this->sequencedata["postponed"] = array();
193  if (!is_array($this->sequencedata["hidden"])) $this->sequencedata["hidden"] = array();
194  }
195  }
196 
204  public function saveToDb()
205  {
206  global $ilDB;
207 
208  $postponed = "NULL";
209  if ((is_array($this->sequencedata["postponed"])) && (count($this->sequencedata["postponed"])))
210  {
211  $postponed = $ilDB->quote(serialize($this->sequencedata["postponed"]));
212  }
213  $hidden = "NULL";
214  if ((is_array($this->sequencedata["hidden"])) && (count($this->sequencedata["hidden"])))
215  {
216  $hidden = $ilDB->quote(serialize($this->sequencedata["hidden"]));
217  }
218 
219  $query = sprintf("REPLACE INTO tst_sequence (active_fi, pass, sequence, postponed, hidden) VALUES (%s, %s, %s, %s, %s)",
220  $ilDB->quote($this->active_id . ""),
221  $ilDB->quote($this->pass . ""),
222  $ilDB->quote(serialize($this->sequencedata["sequence"])),
223  $postponed,
224  $hidden
225  );
226  $result = $ilDB->query($query);
227  }
228 
229  function postponeQuestion($question_id)
230  {
231  if (!$this->isPostponedQuestion($question_id))
232  {
233  array_push($this->sequencedata["postponed"], intval($question_id));
234  }
235  }
236 
237  function hideQuestion($question_id)
238  {
239  if (!$this->isHiddenQuestion($question_id))
240  {
241  array_push($this->sequencedata["hidden"], intval($question_id));
242  }
243  }
244 
245  function isPostponedQuestion($question_id)
246  {
247  if (!is_array($this->sequencedata["postponed"])) return FALSE;
248  if (!in_array($question_id, $this->sequencedata["postponed"]))
249  {
250  return FALSE;
251  }
252  else
253  {
254  return TRUE;
255  }
256  }
257 
258  function isHiddenQuestion($question_id)
259  {
260  if (!is_array($this->sequencedata["hidden"])) return FALSE;
261  if (!in_array($question_id, $this->sequencedata["hidden"]))
262  {
263  return FALSE;
264  }
265  else
266  {
267  return TRUE;
268  }
269  }
270 
271  function isPostponedSequence($sequence)
272  {
273  if (!array_key_exists($sequence, $this->questions)) return FALSE;
274  if (!is_array($this->sequencedata["postponed"])) return FALSE;
275  if (!in_array($this->questions[$sequence], $this->sequencedata["postponed"]))
276  {
277  return FALSE;
278  }
279  else
280  {
281  return TRUE;
282  }
283  }
284 
285  function isHiddenSequence($sequence)
286  {
287  if (!array_key_exists($sequence, $this->questions)) return FALSE;
288  if (!is_array($this->sequencedata["hidden"])) return FALSE;
289  if (!in_array($this->questions[$sequence], $this->sequencedata["hidden"]))
290  {
291  return FALSE;
292  }
293  else
294  {
295  return TRUE;
296  }
297  }
298 
299  function postponeSequence($sequence)
300  {
301  if (!$this->isPostponedSequence($sequence))
302  {
303  if (array_key_exists($sequence, $this->questions))
304  {
305  if (!is_array($this->sequencedata["postponed"])) $this->sequencedata["postponed"] = array();
306  array_push($this->sequencedata["postponed"], intval($this->questions[$sequence]));
307  }
308  }
309  }
310 
311  function hideSequence($sequence)
312  {
313  if (!$this->isHiddenSequence($sequence))
314  {
315  if (array_key_exists($sequence, $this->questions))
316  {
317  if (!is_array($this->sequencedata["hidden"])) $this->sequencedata["hidden"] = array();
318  array_push($this->sequencedata["hidden"], intval($this->questions[$sequence]));
319  }
320  }
321  }
322 
323  function getPositionOfSequence($sequence)
324  {
325  $correctedsequence = $this->getCorrectedSequence();
326  $sequencekey = array_search($sequence, $correctedsequence);
327  if ($sequencekey !== FALSE)
328  {
329  return $sequencekey + 1;
330  }
331  else
332  {
333  return "";
334  }
335  }
336 
338  {
339  return count($this->getCorrectedSequence());
340  }
341 
343  {
344  return array_keys($this->questions);
345  }
346 
347  function getUserSequence()
348  {
349  return $this->getCorrectedSequence(TRUE);
350  }
351 
352  protected function getCorrectedSequence($with_hidden_questions = FALSE)
353  {
354  $correctedsequence = $this->sequencedata["sequence"];
355  if (!$with_hidden_questions)
356  {
357  if (is_array($this->sequencedata["hidden"]))
358  {
359  foreach ($this->sequencedata["hidden"] as $question_id)
360  {
361  $foundsequence = array_search($question_id, $this->questions);
362  if ($foundsequence !== FALSE)
363  {
364  $sequencekey = array_search($foundsequence, $correctedsequence);
365  if ($sequencekey !== FALSE)
366  {
367  unset($correctedsequence[$sequencekey]);
368  }
369  }
370  }
371  }
372  }
373  if (is_array($this->sequencedata["postponed"]))
374  {
375  foreach ($this->sequencedata["postponed"] as $question_id)
376  {
377  $foundsequence = array_search($question_id, $this->questions);
378  if ($foundsequence !== FALSE)
379  {
380  $sequencekey = array_search($foundsequence, $correctedsequence);
381  if ($sequencekey !== FALSE)
382  {
383  unset($correctedsequence[$sequencekey]);
384  array_push($correctedsequence, $foundsequence);
385  }
386  }
387  }
388  }
389  return array_values($correctedsequence);
390  }
391 
392  function getSequenceForQuestion($question_id)
393  {
394  return array_search($question_id, $this->questions);
395  }
396 
397  function getFirstSequence()
398  {
399  $correctedsequence = $this->getCorrectedSequence();
400  if (count($correctedsequence))
401  {
402  return reset($correctedsequence);
403  }
404  else
405  {
406  return FALSE;
407  }
408  }
409 
410  function getLastSequence()
411  {
412  $correctedsequence = $this->getCorrectedSequence();
413  if (count($correctedsequence))
414  {
415  return end($correctedsequence);
416  }
417  else
418  {
419  return FALSE;
420  }
421  }
422 
423  function getNextSequence($sequence)
424  {
425  $correctedsequence = $this->getCorrectedSequence();
426  $sequencekey = array_search($sequence, $correctedsequence);
427  if ($sequencekey !== FALSE)
428  {
429  $nextsequencekey = $sequencekey + 1;
430  if (array_key_exists($nextsequencekey, $correctedsequence))
431  {
432  return $correctedsequence[$nextsequencekey];
433  }
434  }
435  return FALSE;
436  }
437 
438  function getPreviousSequence($sequence)
439  {
440  $correctedsequence = $this->getCorrectedSequence();
441  $sequencekey = array_search($sequence, $correctedsequence);
442  if ($sequencekey !== FALSE)
443  {
444  $prevsequencekey = $sequencekey - 1;
445  if (($prevsequencekey >= 0) && (array_key_exists($prevsequencekey, $correctedsequence)))
446  {
447  return $correctedsequence[$prevsequencekey];
448  }
449  }
450  return FALSE;
451  }
452 
461  function pcArrayShuffle($array)
462  {
463  mt_srand((double)microtime()*1000000);
464  $i = count($array);
465  if ($i > 0)
466  {
467  while(--$i)
468  {
469  $j = mt_rand(0, $i);
470  if ($i != $j)
471  {
472  // swap elements
473  $tmp = $array[$j];
474  $array[$j] = $array[$i];
475  $array[$i] = $tmp;
476  }
477  }
478  }
479  return $array;
480  }
481 
482  function getQuestionForSequence($sequence)
483  {
484  if ($sequence < 1) return FALSE;
485  if (array_key_exists($sequence, $this->questions))
486  {
487  return $this->questions[$sequence];
488  }
489  else
490  {
491  return FALSE;
492  }
493  }
494 
495  function &getSequenceSummary()
496  {
497  $correctedsequence = $this->getCorrectedSequence();
498  $result_array = array();
499  include_once "./Modules/Test/classes/class.ilObjTest.php";
500  $solved_questions = ilObjTest::_getSolvedQuestions($this->active_id);
501  $key = 1;
502  foreach ($correctedsequence as $sequence)
503  {
504  $question =& ilObjTest::_instanciateQuestion($this->getQuestionForSequence($sequence));
505  if (is_object($question))
506  {
507  $worked_through = $question->_isWorkedThrough($this->active_id, $question->getId(), $this->pass);
508  $solved = 0;
509  if (array_key_exists($question->getId(), $solved_questions))
510  {
511  $solved = $solved_questions[$question->getId()]->solved;
512  }
513  $is_postponed = $this->isPostponedQuestion($question->getId());
514 
515  $row = array(
516  "nr" => "$key",
517  "title" => $question->getTitle(),
518  "qid" => $question->getId(),
519  "visited" => $worked_through,
520  "solved" => (($solved)?"1":"0"),
521  "description" => $question->getComment(),
522  "points" => $question->getMaximumPoints(),
523  "worked_through" => $worked_through,
524  "postponed" => $is_postponed,
525  "sequence" => $sequence
526  );
527  array_push($result_array, $row);
528  $key++;
529  }
530  }
531  return $result_array;
532  }
533 
534  function getPass()
535  {
536  return $this->pass;
537  }
538 
539  function setPass($pass)
540  {
541  $this->pass = $pass;
542  }
543 
544  function hasSequence()
545  {
546  if ((is_array($this->sequencedata["sequence"])) && (count($this->sequencedata["sequence"]) > 0))
547  {
548  return TRUE;
549  }
550  else
551  {
552  return FALSE;
553  }
554  }
555 
557  {
558  if ((is_array($this->sequencedata["hidden"])) && (count($this->sequencedata["hidden"]) > 0))
559  {
560  return TRUE;
561  }
562  else
563  {
564  return FALSE;
565  }
566  }
567 
569  {
570  $this->sequencedata["hidden"] = array();
571  }
572 }
573 
574 ?>