ILIAS  release_9 Revision v9.13-25-g2c18ec4c24f
class.ilTestTopList.php
Go to the documentation of this file.
1 <?php
2 
19 declare(strict_types=1);
20 
22 {
23  public function __construct(
24  private ilObjTest $object,
25  private ilDBInterface $db
26  ) {
27  }
28 
34  public function getUserToplistByWorkingtime(int $a_test_ref_id, int $a_user_id): array
35  {
36  $result = $this->db->query(
37  '
38  SELECT COUNT(tst_pass_result.workingtime) cnt
39  FROM object_reference
40  INNER JOIN tst_tests ON object_reference.obj_id = tst_tests.obj_fi
41  INNER JOIN tst_active ON tst_tests.test_id = tst_active.test_fi
42  INNER JOIN tst_result_cache ON tst_active.active_id = tst_result_cache.active_fi
43  INNER JOIN tst_pass_result ON tst_active.active_id = tst_pass_result.active_fi
44  AND tst_pass_result.pass = tst_result_cache.pass
45  INNER JOIN usr_data ON usr_data.usr_id = tst_active.user_fi
46  WHERE object_reference.ref_id = ' . $this->db->quote($a_test_ref_id, 'integer') . '
47  AND tst_active.user_fi != ' . $this->db->quote($a_user_id, 'integer') . '
48  AND workingtime <
49  (
50  SELECT workingtime
51  FROM object_reference
52  INNER JOIN tst_tests ON object_reference.obj_id = tst_tests.obj_fi
53  INNER JOIN tst_active ON tst_tests.test_id = tst_active.test_fi
54  INNER JOIN tst_result_cache ON tst_active.active_id = tst_result_cache.active_fi
55  INNER JOIN tst_pass_result ON tst_active.active_id = tst_pass_result.active_fi
56  AND tst_pass_result.pass = tst_result_cache.pass
57  WHERE object_reference.ref_id = ' . $this->db->quote($a_test_ref_id, 'integer') . '
58  AND tst_active.user_fi = ' . $this->db->quote($a_user_id, 'integer') . '
59  )
60  '
61  );
62  $row = $this->db->fetchAssoc($result);
63  $better_participants = $row['cnt'];
64  $own_placement = $better_participants + 1;
65 
66  $result = $this->db->query(
67  '
68  SELECT COUNT(tst_pass_result.workingtime) cnt
69  FROM object_reference
70  INNER JOIN tst_tests ON object_reference.obj_id = tst_tests.obj_fi
71  INNER JOIN tst_active ON tst_tests.test_id = tst_active.test_fi
72  INNER JOIN tst_result_cache ON tst_active.active_id = tst_result_cache.active_fi
73  INNER JOIN tst_pass_result ON tst_active.active_id = tst_pass_result.active_fi
74  AND tst_pass_result.pass = tst_result_cache.pass
75  INNER JOIN usr_data ON usr_data.usr_id = tst_active.user_fi
76  WHERE object_reference.ref_id = ' . $this->db->quote($a_test_ref_id, 'integer')
77  );
78  $row = $this->db->fetchAssoc($result);
79  $number_total = $row['cnt'];
80 
81  $result = $this->db->query(
82  '
83  SELECT tst_result_cache.*, round(reached_points/max_points*100) as percentage ,
84  tst_pass_result.workingtime, usr_id, usr_data.firstname, usr_data.lastname
85  FROM object_reference
86  INNER JOIN tst_tests ON object_reference.obj_id = tst_tests.obj_fi
87  INNER JOIN tst_active ON tst_tests.test_id = tst_active.test_fi
88  INNER JOIN tst_result_cache ON tst_active.active_id = tst_result_cache.active_fi
89  INNER JOIN tst_pass_result ON tst_active.active_id = tst_pass_result.active_fi
90  AND tst_pass_result.pass = tst_result_cache.pass
91  INNER JOIN usr_data ON usr_data.usr_id = tst_active.user_fi
92 
93  WHERE object_reference.ref_id = ' . $this->db->quote($a_test_ref_id, 'integer') . '
94  AND tst_active.user_fi = ' . $this->db->quote($a_user_id, 'integer') . '
95 
96  UNION(
97  SELECT tst_result_cache.*, round(reached_points/max_points*100) as percentage,
98  tst_pass_result.workingtime, usr_id, usr_data.firstname, usr_data.lastname
99  FROM object_reference
100  INNER JOIN tst_tests ON object_reference.obj_id = tst_tests.obj_fi
101  INNER JOIN tst_active ON tst_tests.test_id = tst_active.test_fi
102  INNER JOIN tst_result_cache ON tst_active.active_id = tst_result_cache.active_fi
103  INNER JOIN tst_pass_result ON tst_active.active_id = tst_pass_result.active_fi
104  AND tst_pass_result.pass = tst_result_cache.pass
105  INNER JOIN usr_data ON usr_data.usr_id = tst_active.user_fi
106  WHERE object_reference.ref_id = ' . $this->db->quote($a_test_ref_id, 'integer') . '
107  AND tst_active.user_fi != ' . $this->db->quote($a_user_id, 'integer') . '
108  AND workingtime >=
109  (
110  SELECT tst_pass_result.workingtime
111  FROM object_reference
112  INNER JOIN tst_tests ON object_reference.obj_id = tst_tests.obj_fi
113  INNER JOIN tst_active ON tst_tests.test_id = tst_active.test_fi
114  INNER JOIN tst_result_cache ON tst_active.active_id = tst_result_cache.active_fi
115  INNER JOIN tst_pass_result ON tst_active.active_id = tst_pass_result.active_fi
116  AND tst_pass_result.pass = tst_result_cache.pass
117  WHERE object_reference.ref_id = ' . $this->db->quote($a_test_ref_id, 'integer') . '
118  AND tst_active.user_fi = ' . $this->db->quote($a_user_id, 'integer') . '
119  )
120  ORDER BY workingtime DESC
121  LIMIT 0, ' . $this->db->quote($this->object->getHighscoreTopNum(), 'integer') . '
122  )
123  UNION(
124  SELECT tst_result_cache.*, round(reached_points/max_points*100) as percentage,
125  tst_pass_result.workingtime, usr_id, usr_data.firstname, usr_data.lastname
126  FROM object_reference
127  INNER JOIN tst_tests ON object_reference.obj_id = tst_tests.obj_fi
128  INNER JOIN tst_active ON tst_tests.test_id = tst_active.test_fi
129  INNER JOIN tst_result_cache ON tst_active.active_id = tst_result_cache.active_fi
130  INNER JOIN tst_pass_result ON tst_active.active_id = tst_pass_result.active_fi
131  AND tst_pass_result.pass = tst_result_cache.pass
132  INNER JOIN usr_data ON usr_data.usr_id = tst_active.user_fi
133  WHERE object_reference.ref_id = ' . $this->db->quote($a_test_ref_id, 'integer') . '
134  AND tst_active.user_fi != ' . $this->db->quote($a_user_id, 'integer') . '
135  AND workingtime <
136  (
137  SELECT tst_pass_result.workingtime
138  FROM object_reference
139  INNER JOIN tst_tests ON object_reference.obj_id = tst_tests.obj_fi
140  INNER JOIN tst_active ON tst_tests.test_id = tst_active.test_fi
141  INNER JOIN tst_result_cache ON tst_active.active_id = tst_result_cache.active_fi
142  INNER JOIN tst_pass_result ON tst_active.active_id = tst_pass_result.active_fi
143  AND tst_pass_result.pass = tst_result_cache.pass
144  WHERE object_reference.ref_id = ' . $this->db->quote($a_test_ref_id, 'integer') . '
145  AND tst_active.user_fi = ' . $this->db->quote($a_user_id, 'integer') . '
146  )
147  ORDER BY workingtime DESC
148  LIMIT 0, ' . $this->db->quote($this->object->getHighscoreTopNum(), 'integer') . '
149  )
150  ORDER BY workingtime ASC
151  LIMIT 0, ' . $this->db->quote($this->object->getHighscoreTopNum(), 'integer') . '
152  '
153  );
154 
155  $i = $own_placement - (($better_participants >= 3) ? 3 : $better_participants);
156 
157  $data = [];
158 
159  if ($i > 1) {
160  $item = $this->buildEmptyItem();
161  $data[] = $item;
162  }
163 
164  while ($row = $this->db->fetchAssoc($result)) {
165  $item = $this->getResultTableRow($row, $i, $a_user_id);
166  $i++;
167  $data[] = $item;
168  }
169 
170  if ($number_total > $i) {
171  $item = $this->buildEmptyItem();
172  $data[] = $item;
173  }
174 
175  return $data;
176  }
177 
183  public function getGeneralToplistByPercentage(int $a_test_ref_id, int $a_user_id): array
184  {
185  $this->db->setLimit($this->object->getHighscoreTopNum(), 0);
186  $result = $this->db->query(
187  '
188  SELECT tst_result_cache.*, round(points/maxpoints*100,2) as percentage, tst_pass_result.workingtime, usr_data.usr_id, usr_data.firstname, usr_data.lastname
189  FROM object_reference
190  INNER JOIN tst_tests ON object_reference.obj_id = tst_tests.obj_fi
191  INNER JOIN tst_active ON tst_tests.test_id = tst_active.test_fi
192  INNER JOIN tst_result_cache ON tst_active.active_id = tst_result_cache.active_fi
193  INNER JOIN tst_pass_result ON tst_active.active_id = tst_pass_result.active_fi AND tst_pass_result.pass = tst_result_cache.pass
194  INNER JOIN usr_data ON usr_data.usr_id = tst_active.user_fi
195  WHERE object_reference.ref_id = ' . $this->db->quote($a_test_ref_id, 'integer') . '
196  ORDER BY percentage DESC'
197  );
198 
199  $i = 0;
200  $data = [];
201 
202  while ($row = $this->db->fetchAssoc($result)) {
203  $i++;
204  $item = $this->getResultTableRow($row, $i, $a_user_id);
205 
206  $data[] = $item;
207  }
208 
209  return $data;
210  }
211 
217  public function getGeneralToplistByWorkingtime(int $a_test_ref_id, int $a_user_id): array
218  {
219  $this->db->setLimit($this->object->getHighscoreTopNum(), 0);
220  $result = $this->db->query(
221  '
222  SELECT tst_result_cache.*, round(points/maxpoints*100,2) as percentage, tst_pass_result.workingtime, usr_data.usr_id, usr_data.firstname, usr_data.lastname
223  FROM object_reference
224  INNER JOIN tst_tests ON object_reference.obj_id = tst_tests.obj_fi
225  INNER JOIN tst_active ON tst_tests.test_id = tst_active.test_fi
226  INNER JOIN tst_result_cache ON tst_active.active_id = tst_result_cache.active_fi
227  INNER JOIN tst_pass_result ON tst_active.active_id = tst_pass_result.active_fi AND tst_pass_result.pass = tst_result_cache.pass
228  INNER JOIN usr_data ON usr_data.usr_id = tst_active.user_fi
229  WHERE object_reference.ref_id = ' . $this->db->quote($a_test_ref_id, 'integer') . '
230  ORDER BY workingtime ASC'
231  );
232 
233  $i = 0;
234  $data = [];
235 
236  while ($row = $this->db->fetchAssoc($result)) {
237  $i++;
238  $item = $this->getResultTableRow($row, $i, $a_user_id);
239  $data[] = $item;
240  }
241 
242  return $data;
243  }
244 
250  public function getUserToplistByPercentage(int $a_test_ref_id, int $a_user_id): array
251  {
252  $result = $this->db->query(
253  '
254  SELECT COUNT(tst_pass_result.workingtime) cnt
255  FROM object_reference
256  INNER JOIN tst_tests ON object_reference.obj_id = tst_tests.obj_fi
257  INNER JOIN tst_active ON tst_tests.test_id = tst_active.test_fi
258  INNER JOIN tst_result_cache ON tst_active.active_id = tst_result_cache.active_fi
259  INNER JOIN tst_pass_result ON tst_active.active_id = tst_pass_result.active_fi
260  AND tst_pass_result.pass = tst_result_cache.pass
261  INNER JOIN usr_data ON usr_data.usr_id = tst_active.user_fi
262  WHERE object_reference.ref_id = ' . $this->db->quote($a_test_ref_id, 'integer') . '
263  AND tst_active.user_fi != ' . $this->db->quote($a_user_id, 'integer') . '
264  AND round(reached_points/max_points*100) >=
265  (
266  SELECT round(reached_points/max_points*100)
267  FROM object_reference
268  INNER JOIN tst_tests ON object_reference.obj_id = tst_tests.obj_fi
269  INNER JOIN tst_active ON tst_tests.test_id = tst_active.test_fi
270  INNER JOIN tst_result_cache ON tst_active.active_id = tst_result_cache.active_fi
271  INNER JOIN tst_pass_result ON tst_active.active_id = tst_pass_result.active_fi
272  AND tst_pass_result.pass = tst_result_cache.pass
273  WHERE object_reference.ref_id = ' . $this->db->quote($a_test_ref_id, 'integer') . '
274  AND tst_active.user_fi = ' . $this->db->quote($a_user_id, 'integer') . '
275  )
276  '
277  );
278  $row = $this->db->fetchAssoc($result);
279  $better_participants = $row['cnt'];
280  $own_placement = $better_participants + 1;
281 
282  $result = $this->db->query(
283  '
284  SELECT COUNT(tst_pass_result.workingtime) cnt
285  FROM object_reference
286  INNER JOIN tst_tests ON object_reference.obj_id = tst_tests.obj_fi
287  INNER JOIN tst_active ON tst_tests.test_id = tst_active.test_fi
288  INNER JOIN tst_result_cache ON tst_active.active_id = tst_result_cache.active_fi
289  INNER JOIN tst_pass_result ON tst_active.active_id = tst_pass_result.active_fi
290  AND tst_pass_result.pass = tst_result_cache.pass
291  INNER JOIN usr_data ON usr_data.usr_id = tst_active.user_fi
292  WHERE object_reference.ref_id = ' . $this->db->quote($a_test_ref_id, 'integer')
293  );
294  $row = $this->db->fetchAssoc($result);
295  $number_total = $row['cnt'];
296 
297  $result = $this->db->query(
298  '
299  SELECT tst_result_cache.*, round(reached_points/max_points*100) as percentage ,
300  tst_pass_result.workingtime, usr_id, usr_data.firstname, usr_data.lastname
301  FROM object_reference
302  INNER JOIN tst_tests ON object_reference.obj_id = tst_tests.obj_fi
303  INNER JOIN tst_active ON tst_tests.test_id = tst_active.test_fi
304  INNER JOIN tst_result_cache ON tst_active.active_id = tst_result_cache.active_fi
305  INNER JOIN tst_pass_result ON tst_active.active_id = tst_pass_result.active_fi
306  AND tst_pass_result.pass = tst_result_cache.pass
307  INNER JOIN usr_data ON usr_data.usr_id = tst_active.user_fi
308 
309  WHERE object_reference.ref_id = ' . $this->db->quote($a_test_ref_id, 'integer') . '
310  AND tst_active.user_fi = ' . $this->db->quote($a_user_id, 'integer') . '
311 
312  UNION(
313  SELECT tst_result_cache.*, round(reached_points/max_points*100) as percentage,
314  tst_pass_result.workingtime, usr_id, usr_data.firstname, usr_data.lastname
315  FROM object_reference
316  INNER JOIN tst_tests ON object_reference.obj_id = tst_tests.obj_fi
317  INNER JOIN tst_active ON tst_tests.test_id = tst_active.test_fi
318  INNER JOIN tst_result_cache ON tst_active.active_id = tst_result_cache.active_fi
319  INNER JOIN tst_pass_result ON tst_active.active_id = tst_pass_result.active_fi
320  AND tst_pass_result.pass = tst_result_cache.pass
321  INNER JOIN usr_data ON usr_data.usr_id = tst_active.user_fi
322  WHERE object_reference.ref_id = ' . $this->db->quote($a_test_ref_id, 'integer') . '
323  AND tst_active.user_fi != ' . $this->db->quote($a_user_id, 'integer') . '
324  AND round(reached_points/max_points*100) >=
325  (
326  SELECT round(reached_points/max_points*100)
327  FROM object_reference
328  INNER JOIN tst_tests ON object_reference.obj_id = tst_tests.obj_fi
329  INNER JOIN tst_active ON tst_tests.test_id = tst_active.test_fi
330  INNER JOIN tst_result_cache ON tst_active.active_id = tst_result_cache.active_fi
331  INNER JOIN tst_pass_result ON tst_active.active_id = tst_pass_result.active_fi
332  AND tst_pass_result.pass = tst_result_cache.pass
333  WHERE object_reference.ref_id = ' . $this->db->quote($a_test_ref_id, 'integer') . '
334  AND tst_active.user_fi = ' . $this->db->quote($a_user_id, 'integer') . '
335  )
336  ORDER BY round(reached_points/max_points*100) ASC
337  LIMIT 0, ' . $this->db->quote($this->object->getHighscoreTopNum(), 'integer') . '
338  )
339  UNION(
340  SELECT tst_result_cache.*, round(reached_points/max_points*100) as percentage,
341  tst_pass_result.workingtime, usr_id, usr_data.firstname, usr_data.lastname
342  FROM object_reference
343  INNER JOIN tst_tests ON object_reference.obj_id = tst_tests.obj_fi
344  INNER JOIN tst_active ON tst_tests.test_id = tst_active.test_fi
345  INNER JOIN tst_result_cache ON tst_active.active_id = tst_result_cache.active_fi
346  INNER JOIN tst_pass_result ON tst_active.active_id = tst_pass_result.active_fi
347  AND tst_pass_result.pass = tst_result_cache.pass
348  INNER JOIN usr_data ON usr_data.usr_id = tst_active.user_fi
349  WHERE object_reference.ref_id = ' . $this->db->quote($a_test_ref_id, 'integer') . '
350  AND tst_active.user_fi != ' . $this->db->quote($a_user_id, 'integer') . '
351  AND round(reached_points/max_points*100) <=
352  (
353  SELECT round(reached_points/max_points*100)
354  FROM object_reference
355  INNER JOIN tst_tests ON object_reference.obj_id = tst_tests.obj_fi
356  INNER JOIN tst_active ON tst_tests.test_id = tst_active.test_fi
357  INNER JOIN tst_result_cache ON tst_active.active_id = tst_result_cache.active_fi
358  INNER JOIN tst_pass_result ON tst_active.active_id = tst_pass_result.active_fi
359  AND tst_pass_result.pass = tst_result_cache.pass
360  WHERE object_reference.ref_id = ' . $this->db->quote($a_test_ref_id, 'integer') . '
361  AND tst_active.user_fi = ' . $this->db->quote($a_user_id, 'integer') . '
362  )
363  ORDER BY round(reached_points/max_points*100) ASC
364  LIMIT 0, ' . $this->db->quote($this->object->getHighscoreTopNum(), 'integer') . '
365  )
366  ORDER BY round(reached_points/max_points*100) DESC, tstamp ASC
367  LIMIT 0, ' . $this->db->quote($this->object->getHighscoreTopNum(), 'integer') . '
368  '
369  );
370 
371  $i = $own_placement - ($better_participants >= $this->object->getHighscoreTopNum()
372  ? $this->object->getHighscoreTopNum() : $better_participants);
373 
374  $data = [];
375 
376  if ($i > 1) {
377  $item = $this->buildEmptyItem();
378  $data[] = $item;
379  }
380 
381  while ($row = $this->db->fetchAssoc($result)) {
382  $item = $this->getResultTableRow($row, $i, $a_user_id);
383  $i++;
384  $data[] = $item;
385  }
386 
387  if ($number_total > $i) {
388  $item = $this->buildEmptyItem();
389  $data[] = $item;
390  }
391 
392  return $data;
393  }
394 
402  private function getResultTableRow(array $row, int $i, int $usrId): array
403  {
404  $item = [];
405 
406  $item['rank'] = $i . '. ';
407 
408  if ($this->object->isHighscoreAnon() && (int) $row['usr_id'] !== $usrId) {
409  $item['participant'] = '-, -';
410  } else {
411  $item['participant'] = $row['lastname'] . ', ' . $row['firstname'];
412  }
413 
414  if ($this->object->getHighscoreAchievedTS()) {
415  $item['achieved'] = new ilDateTime($row['tstamp'], IL_CAL_UNIX);
416  }
417 
418  if ($this->object->getHighscoreScore()) {
419  $item['score'] = $row['reached_points'] . ' / ' . $row['max_points'];
420  }
421 
422  if ($this->object->getHighscorePercentage()) {
423  $item['percentage'] = $row['percentage'] . '%';
424  }
425 
426  if ($this->object->getHighscoreHints()) {
427  $item['hints'] = $row['hint_count'];
428  }
429 
430  if ($this->object->getHighscoreWTime()) {
431  $item['time'] = $this->formatTime((int) $row['workingtime']);
432  }
433 
434  $item['is_actor'] = ((int) $row['usr_id'] === $usrId);
435 
436  return $item;
437  }
438 
443  private function formatTime(int $seconds): string
444  {
445  $hours = floor($seconds / 3600);
446  $seconds -= $hours * 3600;
447  $minutes = floor($seconds / 60);
448  $seconds -= $minutes * 60;
449 
450  return str_pad(number_format($hours, 0, '.', ''), 2, '0', STR_PAD_LEFT) . ":"
451  . str_pad(number_format($minutes, 0, '.', ''), 2, '0', STR_PAD_LEFT) . ":"
452  . str_pad(number_format($seconds, 0, '.', ''), 2, '0', STR_PAD_LEFT);
453  }
454 
455  private function buildEmptyItem(): array
456  {
457  return [
458  'rank' => '...' ,
459  'is_actor' => false,
460  'participant' => '',
461  'achieved' => '',
462  'score' => '',
463  'percentage' => '',
464  'hints' => '',
465  'time' => ''
466  ];
467  }
468 }
getUserToplistByWorkingtime(int $a_test_ref_id, int $a_user_id)
getGeneralToplistByPercentage(int $a_test_ref_id, int $a_user_id)
const IL_CAL_UNIX
formatTime(int $seconds)
getUserToplistByPercentage(int $a_test_ref_id, int $a_user_id)
getGeneralToplistByWorkingtime(int $a_test_ref_id, int $a_user_id)
__construct(private ilObjTest $object, private ilDBInterface $db)
getResultTableRow(array $row, int $i, int $usrId)