ILIAS  eassessment Revision 61809
 All Data Structures Namespaces Files Functions Variables Groups Pages
class.ilTestNewScoring.php
Go to the documentation of this file.
1 <?php
2 
3 /*
4 +-----------------------------------------------------------------------------+
5 | ILIAS open source |
6 +-----------------------------------------------------------------------------+
7 | Copyright (c) 1998-2001 ILIAS open source, University of Cologne |
8 | |
9 | This program is free software; you can redistribute it and/or |
10 | modify it under the terms of the GNU General Public License |
11 | as published by the Free Software Foundation; either version 2 |
12 | of the License, or (at your option) any later version. |
13 | |
14 | This program is distributed in the hope that it will be useful, |
15 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
17 | GNU General Public License for more details. |
18 | |
19 | You should have received a copy of the GNU General Public License |
20 | along with this program; if not, write to the Free Software |
21 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
22 +-----------------------------------------------------------------------------+
23 */
24 
35 {
36 
46 var $object;
47 var $lng;
48 var $ctrl;
49 var $tpl;
50 
51 function ilTestNewScoring(& $a_object)
52 {
53  global $lng, $ilCtrl, $tpl;
54 
55  include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
56  $this->lng =& $lng;
57  $this->object =& $a_object;
58  $this->ctrl =& $ilCtrl;
59  $this->tpl =& $tpl;
60 }
61 
62 function loadTempTable($qid)
63 {
64  global $ilDB;
65 
66  $result = $ilDB->queryF("SELECT * FROM tst_temp_solutions WHERE question_fi = %s",
67  array('integer'), array($qid)
68  );
69  if ($ilDB->numRows($result) > 0)
70  {
71  $result = $ilDB->queryF("DELETE FROM tst_temp_solutions WHERE question_fi = %s",
72  array('integer'), array($qid)
73  );
74  }
75  $ilDB->queryF("INSERT INTO tst_temp_solutions (SELECT * FROM tst_solutions WHERE question_fi = %s)",
76  array('integer'), array($qid)
77  );
78 }
79 
80 function checkItemPoints($postvars)
81 {
82 
83  $sum = 0;
84  foreach ($postvars as $key => $value)
85  {
86  if (strpos($value, ","))
87  {
88  $value = str_replace(",", ".",$value);
89  }
90  if (preg_match("/(\d+)_(\d+)/", $key, $matches) && is_numeric($value))
91  {
92  if ($matches[2] > 0)
93  {
94  $sum += $value;
95  }
96  else
97  {
98  $maxpoints = $value;
99  }
100  }
101  }
102  if ($maxpoints == $sum || $sum == 0)
103  {
104  return true;
105  }
106  else
107  {
108  return false;
109  }
110 }
111 
112 function saveOrderingItemPoints($postvars)
113 {
114  global $ilDB;
115 
116  $qid = $postvars["id"];
117 
118  $result = $ilDB->queryF("SELECT * FROM qpl_a_ordering_old WHERE question_fi = %s",
119  array('integer'), array($qid)
120  );
121  if ($ilDB->numRows($result) > 0)
122  {
123  $result = $ilDB->queryF("DELETE FROM qpl_a_ordering_old WHERE question_fi = %s",
124  array('integer'), array($qid)
125  );
126  }
127  if (!$this->checkItemPoints($postvars))
128  {
129  return FALSE;
130  }
131  foreach ($postvars as $key => $value) // save points
132  {
133  if (strpos($value, ","))
134  {
135  $value = str_replace(",", ".",$value);
136  }
137  if (preg_match("/(\d+)_(\d+)/", $key, $matches) && is_numeric($value))
138  {
139  $order = $matches[2];
140  if ($order > 0)
141  {
142  $next_id = $ilDB->nextId('qpl_a_ordering_old');
143  $affectedRows = $ilDB->manipulateF("INSERT INTO qpl_a_ordering_old (answer_id, question_fi, ".
144  "points, aorder, tstamp) VALUES (%s, %s, %s, %s, %s)",
145  array('integer','integer','float','integer', 'integer'),
146  array(
147  $next_id,
148  $qid,
149  $value,
150  $order,
151  time()
152  )
153  );
154  }
155  }
156  }
157  return TRUE;
158 }
159 
160 function loadOrderingItemPoints($q_id)
161 {
162  global $ilDB;
163 
164  $orderingItemPoints = array();
165  $result = $ilDB->queryF("SELECT * FROM qpl_a_ordering_old WHERE question_fi = %s ORDER BY aorder ASC",
166  array('integer'),
167  array($q_id)
168  );
169  if ($result->numRows() > 0)
170  {
171  while ($data = $ilDB->fetchAssoc($result))
172  {
173  array_push($orderingItemPoints, $data["points"]);
174  }
175  }
176  return $orderingItemPoints;
177 }
178 
179 function saveQuestionAndUserResults($postvars)
180 {
181  global $ilDB, $ilUser;
182 
183  $qid = $postvars["id"];
184  $qtype = assQuestion::_getQuestionType($qid);
185  $question = $this->object->createQuestionGUI("", $qid);
186 
187  // get $originalId zum Update der Frage im Fragenpool
188 
189  $orderingItemPoints = array();
190  foreach ($postvars as $key => $value) // save points
191  {
192  if (!is_array($value) && strpos($value, ","))
193  {
194  $value = str_replace(",", ".",$value);
195  }
196  if (preg_match("/(\d+)_(\d+)/", $key, $matches))
197  {
198  $order = $matches[2];
199  switch($qtype)
200  {
201  case "assClozeTest":
202  if ($question->object->gaps[$matches[1]]->getType() == CLOZE_NUMERIC)
203  {
204  $answer = $question->object->gaps[$matches[1]]->getItem(0);
205  if ($order == 1)
206  {
207  $answer->setLowerBound($value);
208  }
209  if ($order == 2)
210  {
211  $answer->setUpperBound($value);
212  }
213  if ($order == 3)
214  {
215  $answer->setAnswertext($value);
216  }
217  if ($order == 0)
218  {
219  $answer->setPoints($value);
220  }
221  }
222  else
223  {
224  $question->object->gaps[$matches[1]]->setItemPoints($order, $value);
225  }
226 
227  break;
228 
229  case "assMultipleChoice":
230  $answer = $question->object->getAnswer($order);
231  if (!$matches[1])
232  {
233  $answer->points = $value;
234  }
235  else
236  {
237  $answer->points_unchecked = $value;
238  }
239  break;
240 
241  case "assNumeric":
242  if ($matches[1] == 1)
243  {
244  $question->object->setLowerLimit($value);
245  }
246  if ($matches[1] == 2)
247  {
248  $question->object->setUpperLimit($value);
249  }
250  if ($matches[1] == 0)
251  {
252  $question->object->points = $value;
253  }
254  break;
255 
256  case "assMatchingQuestion":
257  $query = "UPDATE qpl_a_matching SET points= $value WHERE question_fi=$qid AND term_fi = $order";
258  $ilDB->query($query);
259  $matching = 1;
260  break;
261 
262  case "assOrderingQuestion":
263  case "assOrderingHorizontal":
264  if ($order == 0)
265  {
266  $question->object->setPoints($value);
267  }
268  elseif($order && is_numeric($value))
269  {
270  array_push($orderingItemPoints, $value);
271  }
272 
273  break;
274 
275  case "assSingleChoice":
276  case "assTextSubset":
277  $answer = $question->object->getAnswer($order);
278  $answer->points = $value;
279 
280  break;
281  }
282  }
283  }
284  // addLog
285 
286  $logtext = "Neu bewertete Frage";
287  $testObjId = $this->object->_lookupTestObjIdForQuestionId($qid);
288  $originalId = $question->object->original_id;
289  include_once "./Modules/Test/classes/class.ilObjAssessmentFolder.php";
290  ilObjAssessmentFolder::_addLog($ilUser->id, $testObjId, $logtext, $qid, $originalId);
291 
292  // Neue Bewertung aller TestTeilnehmer
293 
294  $maxpoints = $question->object->getMaximumPoints();
295  $query = "UPDATE qpl_questions SET points='$maxpoints' WHERE question_id=$qid";
296  $ilDB->query($query);
297 
298  if ($qtype == "assClozeTest")
299  {
300  $question->object->setIdenticalScoring($_POST["ident_scoring"]);
301  $question->object->setTextgapRating($_POST["textgap_rating"]);
302  }
303  if ($qtype == "assTextSubset")
304  {
305  $question->object->setTextRating($_POST["text_rating"]);
306  }
307  if (!$matching)
308  {
309  $question->object->SaveToDb();
310  }
311  $data =& $this->object->getCompleteEvaluationData(FALSE);
312  $foundParticipants =& $data->getParticipants();
313  foreach ($foundParticipants as $active_id => $userdata)
314  {
315  if ($qtype == "assOrderingQuestion" && count($orderingItemPoints) > 0)
316  {
317  $reached = $this->calcReachedPoints($active_id, $qid, $orderingItemPoints);
318 
319  }
320  else
321  {
322  $reached = $question->object->calculateReachedPoints($active_id);
323  }
324 
325  // save und log the new Scoring
326 
327  assQuestion::_setReachedPoints($active_id, $qid, $reached, $maxpoints, 0);
328 
329  }
330 }
331 
332 
333 function calcReachedPoints($active_id, $q_id, $orderingItemPoints)
334 {
335  global $ilDB;
336 
337  $pass = ilObjTest::_getResultPass($active_id);
338 
339  $result = $ilDB->queryF("SELECT * FROM tst_solutions WHERE active_fi = %s AND question_fi = %s AND pass = %s",
340  array('integer','integer','integer'),
341  array($active_id, $q_id, $pass)
342  );
343  $user_order = array();
344  while ($data = $ilDB->fetchAssoc($result))
345  {
346  if ((strcmp($data["value1"], "") != 0) && (strcmp($data["value2"], "") != 0))
347  {
348  $user_order[$data["value2"]] = $data["value1"];
349  }
350  }
351  ksort($user_order);
352  $user_order = array_values($user_order);
353  $points = 0;
354  foreach ($orderingItemPoints as $index => $value)
355  {
356  if (($index) == $user_order[$index])
357  {
358  $points = $points + $value;
359  }
360  }
361  return $points;
362 }
363 
364 function getSolutionStat($a_qid, $a_par = 0)
365 {
366  global $ilDB;
367 
368  $values = array();
369 
370  $qtype = assQuestion::_getQuestionType($a_qid);
371  switch ($qtype)
372  {
373  case "assClozeTest":
374  $rec = $ilDB->queryF("SELECT distinct(value2) FROM tst_temp_solutions, tst_active WHERE question_fi= %s AND value1 = %s AND active_id = active_fi",
375  array('integer', 'text'),
376  array($a_qid, $a_par)
377  );
378  while ($row = $ilDB->fetchAssoc($rec))
379  array_push($values, $row["value2"]);
380  break;
381 
382  case "assMatchingQuestion":
383  $len = strlen($a_par);
384  if (strpos($a_par, ".jpg", ($len -4)))
385  $where = "picture";
386  else
387  $where = "definition";
388  //echo $a_qid."/".$a_par."/".$where;exit;
389  $select = "SELECT * FROM qpl_a_mdef WHERE question_fi= %s AND $where = %s";
390  $rec = $ilDB->queryF($select,
391  array('integer', 'text'),
392  array($a_qid, $a_par)
393  );
394  $row = $ilDB->fetchAssoc($rec);
395  $value2 = $row["morder"];
396  array_push($values, $value2);
397  $rec = $ilDB->queryF("SELECT distinct(value1) FROM tst_temp_solutions WHERE question_fi= %s AND value2 = %s",
398  array('integer', 'text'),
399  array($a_qid, $value2)
400  );
401  while ($row = $ilDB->fetchAssoc($rec))
402  array_push($values, $row["value1"]);
403  break;
404 
405  case "assMultipleChoice":
406  case "assSingleChoice":
407  $rec = $ilDB->queryF("SELECT * FROM tst_temp_solutions, tst_active WHERE question_fi= %s AND value1 = %s AND active_id = active_fi",
408  array('integer', 'text'),
409  array($a_qid, $a_par)
410  );
411  while ($row = $ilDB->fetchAssoc($rec))
412  array_push($values, $row["value1"]);
413  break;
414 
415  case "assOrderingQuestion":
416  $rec = $ilDB->queryF("SELECT distinct(value2) FROM tst_temp_solutions, tst_active WHERE question_fi= %s AND value1 = %s AND active_id = active_fi",
417  array('integer', 'text'),
418  array($a_qid, $a_par)
419  );
420  while ($row = $ilDB->fetchAssoc($rec))
421  array_push($values, $row["value2"]);
422  break;
423 
424  case "assOrderingHorizontal":
425  $rec = $ilDB->queryF("SELECT distinct(value1) FROM tst_temp_solutions, tst_active WHERE question_fi= %s AND active_id = active_fi",
426  array('integer'),
427  array($a_qid)
428  );
429  while ($row = $ilDB->fetchAssoc($rec))
430  array_push($values, $row["value1"]);
431  break;
432 
433  case "assNumeric";
434  case "assTextSubset":
435  $rec = $ilDB->queryF("SELECT distinct(value1) FROM tst_temp_solutions, tst_active WHERE question_fi= %s AND active_id = active_fi ORDER BY value1",
436  array('integer'),
437  array($a_qid)
438  );
439  while ($row = $ilDB->fetchAssoc($rec))
440  {
441  if ($row["value1"])
442  array_push($values, $row["value1"]);
443  }
444  break;
445  }
446  return $values;
447 }
448 
449 function getUserAnswers($a_qid, $par1 = 0, $par2 = 0)
450 {
451  global $ilDB;
452 
453  $qtype = assQuestion::_getQuestionType($a_qid);
454  $stat = array("count", "val");
455 
456  switch ($qtype)
457  {
458  case "assClozeTest":
459  $rec = $ilDB->queryF("SELECT * FROM tst_temp_solutions WHERE question_fi= %s AND value2= %s AND value1 =%s",
460  array("integer", "text", "text"),
461  array($a_qid, $par1, $par2)
462  );
463  $stat["count"] = $ilDB->numRows($rec);
464  $row = $ilDB->fetchAssoc($rec);
465  $stat["val"] = $row["solution_id"];
466  break;
467 
468  case "assMatchingQuestion":
469 
470  $rec = $ilDB->queryF("SELECT * FROM tst_temp_solutions WHERE question_fi= %s AND value1= %s AND value2= %s",
471  array("integer", "text", "text"),
472  array($a_qid, $par1, $par2)
473  );
474  $rec1 = $ilDB->queryF("SELECT * FROM qpl_a_mterm WHERE question_fi= %s AND term_id=%s",
475  array("integer", "integer"),
476  array($a_qid, $par1)
477  );
478  $row = $ilDB->fetchAssoc($rec1);
479  $stat["count"] = $ilDB->numRows($rec);
480  $stat["val"] = $row["term"];
481  break;
482 
483  case "assOrderingQuestion":
484  $rec = $ilDB->queryF("SELECT * FROM tst_temp_solutions, tst_active WHERE question_fi=%s AND value1=%s AND value2=%s AND active_id = active_fi",
485  array("integer", "text", "text"),
486  array($a_qid, $par1, $par2)
487  );
488  $stat["count"] = $ilDB->numRows($rec);
489  break;
490 
491  case "assOrderingHorizontal":
492  $rec = $ilDB->queryF("SELECT * FROM tst_temp_solutions, tst_active WHERE question_fi=%s AND value1=%s AND active_id = active_fi",
493  array("integer", "text"),
494  array($a_qid, $par2)
495  );
496  $stat["count"] = $ilDB->numRows($rec);
497  break;
498 
499  case "assNumeric":
500  $rec = $ilDB->queryF("SELECT * FROM tst_temp_solutions, tst_active WHERE question_fi=%s AND value1=%s AND active_id = active_fi",
501  array("integer", "text"),
502  array($a_qid, $par1)
503  );
504  $stat["count"] = $ilDB->numRows($rec);
505  break;
506 
507  case "assTextSubset":
508  $rec = $ilDB->queryF("SELECT * FROM tst_temp_solutions, tst_active WHERE question_fi=%s AND value1=%s AND active_id = active_fi",
509  array("integer", "text"),
510  array($a_qid, $par1)
511  );
512  $row = $ilDB->fetchAssoc($rec);
513  $stat["count"] = $ilDB->numRows($rec);
514  $stat["val"] = $row["solution_id"];
515  break;
516  }
517  return ($stat);
518 
519 }
520 
521 function checkLevenstein(& $a_question, $answerarray, $userans)
522 {
523 
524  $question = & $a_question;
525  $temp = array();
526  //$syn_separator = $question->object->getSynonymSeparator();
527  $syn_separator = 0;
528  foreach($answerarray as $value)
529  {
530  $temp = split("_", $value);
531  if ($syn_separator)
532  {
533  $synonymArr = explode($syn_separator,$temp[0]);
534  for ($i = 0; $i < count($synonymArr); $i++)
535  {
536  $OK = $question->object->getTextgapPoints($userans, $synonymArr[$i], $temp[1]);
537  if (!$OK && ($userans == $synonymArr[$i]))
538  $OK = 1;
539  if ($OK)
540  break;
541  }
542  }
543  else
544  {
545  $OK = $question->object->getTextgapPoints($userans, $temp[0], $temp[1]);
546  if (!$OK && ($userans == $temp[0]))
547  $OK = 1;
548  }
549  if ($OK)
550  break;
551  }
552  return $OK;
553 }
554 
555 function addQuestionAnswer($solutionId, $qtype)
556 {
557  global $ilDB;
558 
559  // Save the changed question
560 
561  switch ($qtype)
562  {
563  case "assClozeTest":
564  $query = "SELECT value2 FROM tst_temp_solutions WHERE solution_id=". $solutionId;
565  $res = $ilDB->query($query);
566  $row = $ilDB->fetchAssoc($res);
567  $answer = $row["value2"];
568  break;
569 
570  case "assTextSubset":
571  $query = "SELECT value1 FROM tst_temp_solutions WHERE solution_id = $solutionId";
572  $res = $ilDB->query($query);
573  $row = $ilDB->fetchAssoc($res);
574  $answer = $row["value1"];
575  break;
576  }
577  return $answer;
578 }
579 
580 }
581 
582 ?>