ILIAS  trunk Revision v12.0_alpha-1227-g7ff6d300864
TestTopListRepository.php
Go to the documentation of this file.
1<?php
2
19declare(strict_types=1);
20
22
24{
25 public function __construct(
26 private readonly \ilDBInterface $db
27 ) {
28 }
29
30 public function getGeneralToplist(\ilObjTest $object, TopListOrder $order_by): \Generator
31 {
32 $order_by_query = $order_by === TopListOrder::BY_TIME
33 ? 'tst_pass_result.workingtime ASC'
34 : 'percentage DESC';
35
36 $this->db->setLimit($object->getHighscoreTopNum(), 0);
37 $result = $this->db->queryF(
38 "
39 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, tst_active.active_id
40 FROM object_reference
41 INNER JOIN tst_tests ON object_reference.obj_id = tst_tests.obj_fi
42 INNER JOIN tst_active ON tst_tests.test_id = tst_active.test_fi
43 INNER JOIN tst_result_cache ON tst_active.active_id = tst_result_cache.active_fi
44 INNER JOIN tst_pass_result ON tst_active.active_id = tst_pass_result.active_fi 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 = %s
47 ORDER BY {$order_by_query}, tstamp ASC
48 ",
50 [$object->getRefId()]
51 );
52
53 $i = 1;
54 while ($row = $this->db->fetchAssoc($result)) {
55 $row['rank'] = $i;
56 $i++;
57 yield $row;
58 }
59 }
60
61 public function getUserToplistByPercentage(\ilObjTest $object, int $a_user_id): \Generator
62 {
63 $a_test_ref_id = $object->getRefId();
64 $better_participants = $this->db->fetchObject(
65 $this->db->query(
66 '
67 SELECT COUNT(tst_pass_result.workingtime) cnt
68 FROM object_reference
69 INNER JOIN tst_tests ON object_reference.obj_id = tst_tests.obj_fi
70 INNER JOIN tst_active ON tst_tests.test_id = tst_active.test_fi
71 INNER JOIN tst_result_cache ON tst_active.active_id = tst_result_cache.active_fi
72 INNER JOIN tst_pass_result ON tst_active.active_id = tst_pass_result.active_fi
73 AND tst_pass_result.pass = tst_result_cache.pass
74 INNER JOIN usr_data ON usr_data.usr_id = tst_active.user_fi
75 WHERE object_reference.ref_id = ' . $this->db->quote($a_test_ref_id, 'integer') . '
76 AND tst_active.user_fi != ' . $this->db->quote($a_user_id, 'integer') . '
77 AND round(reached_points/max_points*100) >=
78 (
79 SELECT round(reached_points/max_points*100)
80 FROM object_reference
81 INNER JOIN tst_tests ON object_reference.obj_id = tst_tests.obj_fi
82 INNER JOIN tst_active ON tst_tests.test_id = tst_active.test_fi
83 INNER JOIN tst_result_cache ON tst_active.active_id = tst_result_cache.active_fi
84 INNER JOIN tst_pass_result ON tst_active.active_id = tst_pass_result.active_fi
85 AND tst_pass_result.pass = tst_result_cache.pass
86 WHERE object_reference.ref_id = ' . $this->db->quote($a_test_ref_id, 'integer') . '
87 AND tst_active.user_fi = ' . $this->db->quote($a_user_id, 'integer') . '
88 )
89 '
90 )
91 )->cnt;
92
93 $total_participants = $this->db->fetchObject(
94 $this->db->query("
95 SELECT COUNT(tst_pass_result.workingtime) cnt
96 FROM object_reference
97 INNER JOIN tst_tests ON object_reference.obj_id = tst_tests.obj_fi
98 INNER JOIN tst_active ON tst_tests.test_id = tst_active.test_fi
99 INNER JOIN tst_result_cache ON tst_active.active_id = tst_result_cache.active_fi
100 INNER JOIN tst_pass_result ON tst_active.active_id = tst_pass_result.active_fi
101 AND tst_pass_result.pass = tst_result_cache.pass
102 INNER JOIN usr_data ON usr_data.usr_id = tst_active.user_fi
103 WHERE object_reference.ref_id = {$this->db->quote($a_test_ref_id, 'integer')}
104 ")
105 )->cnt;
106
107 [$offset, $amount] = $this->calculateLimits(
108 $object->getHighscoreTopNum(),
109 $better_participants,
110 $total_participants
111 );
112
113 $result = $this->db->query("
114 SELECT tst_result_cache.*, round(reached_points/max_points*100) as percentage ,
115 tst_pass_result.workingtime, usr_id, usr_data.firstname, usr_data.lastname, tst_active.active_id
116 FROM object_reference
117 INNER JOIN tst_tests ON object_reference.obj_id = tst_tests.obj_fi
118 INNER JOIN tst_active ON tst_tests.test_id = tst_active.test_fi
119 INNER JOIN tst_result_cache ON tst_active.active_id = tst_result_cache.active_fi
120 INNER JOIN tst_pass_result ON tst_active.active_id = tst_pass_result.active_fi
121 AND tst_pass_result.pass = tst_result_cache.pass
122 INNER JOIN usr_data ON usr_data.usr_id = tst_active.user_fi
123 WHERE object_reference.ref_id = {$this->db->quote($a_test_ref_id, 'integer')}
124 ORDER BY round(reached_points/max_points*100) DESC, tstamp ASC
125 LIMIT {$amount} OFFSET {$offset}
126 ");
127
128 if ($offset > 0) {
129 yield $this->buildEmptyItem();
130 }
131
132 $i = $offset + 1;
133 while ($row = $this->db->fetchAssoc($result)) {
134 $row['rank'] = $i;
135 $i += 1;
136 yield $row;
137 }
138
139 if ($total_participants > $offset + $amount) {
140 yield $this->buildEmptyItem();
141 }
142 }
143
144 public function getUserToplistByWorkingtime(\ilObjTest $object, int $a_user_id): \Generator
145 {
146
147 $a_test_ref_id = $object->getRefId();
148 $better_participants = $this->db->fetchObject(
149 $this->db->query(
150 '
151 SELECT COUNT(tst_pass_result.workingtime) cnt
152 FROM object_reference
153 INNER JOIN tst_tests ON object_reference.obj_id = tst_tests.obj_fi
154 INNER JOIN tst_active ON tst_tests.test_id = tst_active.test_fi
155 INNER JOIN tst_result_cache ON tst_active.active_id = tst_result_cache.active_fi
156 INNER JOIN tst_pass_result ON tst_active.active_id = tst_pass_result.active_fi
157 AND tst_pass_result.pass = tst_result_cache.pass
158 INNER JOIN usr_data ON usr_data.usr_id = tst_active.user_fi
159 WHERE object_reference.ref_id = ' . $this->db->quote($a_test_ref_id, 'integer') . '
160 AND tst_active.user_fi != ' . $this->db->quote($a_user_id, 'integer') . '
161 AND workingtime <
162 (
163 SELECT workingtime
164 FROM object_reference
165 INNER JOIN tst_tests ON object_reference.obj_id = tst_tests.obj_fi
166 INNER JOIN tst_active ON tst_tests.test_id = tst_active.test_fi
167 INNER JOIN tst_result_cache ON tst_active.active_id = tst_result_cache.active_fi
168 INNER JOIN tst_pass_result ON tst_active.active_id = tst_pass_result.active_fi
169 AND tst_pass_result.pass = tst_result_cache.pass
170 WHERE object_reference.ref_id = ' . $this->db->quote($a_test_ref_id, 'integer') . '
171 AND tst_active.user_fi = ' . $this->db->quote($a_user_id, 'integer') . '
172 )
173 '
174 )
175 )->cnt;
176
177 $total_participants = $this->db->fetchObject(
178 $this->db->query(
179 '
180 SELECT COUNT(tst_pass_result.workingtime) cnt
181 FROM object_reference
182 INNER JOIN tst_tests ON object_reference.obj_id = tst_tests.obj_fi
183 INNER JOIN tst_active ON tst_tests.test_id = tst_active.test_fi
184 INNER JOIN tst_result_cache ON tst_active.active_id = tst_result_cache.active_fi
185 INNER JOIN tst_pass_result ON tst_active.active_id = tst_pass_result.active_fi
186 AND tst_pass_result.pass = tst_result_cache.pass
187 INNER JOIN usr_data ON usr_data.usr_id = tst_active.user_fi
188 WHERE object_reference.ref_id = ' . $this->db->quote($a_test_ref_id, 'integer')
189 )
190 )->cnt;
191
192 [$offset, $amount] = $this->calculateLimits(
193 $object->getHighscoreTopNum(),
194 $better_participants,
195 $total_participants
196 );
197
198 $result = $this->db->query("
199 SELECT tst_result_cache.*, round(reached_points/max_points*100) as percentage,
200 tst_pass_result.workingtime, usr_id, usr_data.firstname, usr_data.lastname, tst_active.active_id
201 FROM object_reference
202 INNER JOIN tst_tests ON object_reference.obj_id = tst_tests.obj_fi
203 INNER JOIN tst_active ON tst_tests.test_id = tst_active.test_fi
204 INNER JOIN tst_result_cache ON tst_active.active_id = tst_result_cache.active_fi
205 INNER JOIN tst_pass_result ON tst_active.active_id = tst_pass_result.active_fi
206 AND tst_pass_result.pass = tst_result_cache.pass
207 INNER JOIN usr_data ON usr_data.usr_id = tst_active.user_fi
208 WHERE object_reference.ref_id = {$this->db->quote($a_test_ref_id, 'integer')}
209 ORDER BY workingtime ASC
210 LIMIT {$amount} OFFSET {$offset}
211 ");
212
213 if ($offset > 0) {
214 yield $this->buildEmptyItem();
215 }
216
217 $i = $offset + 1;
218 while ($row = $this->db->fetchAssoc($result)) {
219 $row['rank'] = $i;
220 $i += 1;
221 yield $row;
222 }
223
224 if ($total_participants > $offset + $amount) {
225 yield $this->buildEmptyItem();
226 }
227 }
228
229 private function calculateLimits(
230 int $pax_to_show,
231 int $better_pax,
232 int $total_pax
233 ): array {
234 if ($total_pax < $pax_to_show) {
235 return [0, $total_pax];
236 }
237
238 $pax_to_show_on_each_side = floor($pax_to_show / 2);
239 $offset = $better_pax - $pax_to_show_on_each_side;
240 if ($offset < 0) {
241 $offset = 0;
242 }
243 $end = $offset + $pax_to_show;
244
245 if ($end < $total_pax) {
246 return [$offset, $pax_to_show];
247 }
248
249 return [$total_pax - $pax_to_show, $pax_to_show];
250 }
251
252 private function buildEmptyItem(): array
253 {
254 return [
255 'rank' => '...',
256 'is_actor' => false,
257 'participant' => '',
258 'achieved' => '',
259 'score' => '',
260 'percentage' => null,
261 'time' => ''
262 ];
263 }
264}
getGeneralToplist(\ilObjTest $object, TopListOrder $order_by)
calculateLimits(int $pax_to_show, int $better_pax, int $total_pax)
__construct(private readonly \ilDBInterface $db)
getUserToplistByWorkingtime(\ilObjTest $object, int $a_user_id)
getUserToplistByPercentage(\ilObjTest $object, int $a_user_id)
getHighscoreTopNum(int $a_retval=10)
Gets the number of entries which are to be shown in the top-rankings table.
Interface ilDBInterface.
if(!file_exists('../ilias.ini.php'))