Skip to content

Commit e7360ba

Browse files
committed
complexity reduced in userstatstable
1 parent 1e58530 commit e7360ba

File tree

2 files changed

+109
-89
lines changed

2 files changed

+109
-89
lines changed

classes/tables/userstats_table.php

Lines changed: 58 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
use mod_moodleoverflow\ratings;
2929
global $CFG;
3030
require_once($CFG->dirroot . '/mod/moodleoverflow/lib.php');
31+
require_once($CFG->dirroot . '/mod/moodleoverflow/locallib.php');
3132
require_once($CFG->libdir . '/tablelib.php');
3233

3334
/**
@@ -101,14 +102,14 @@ public function out() {
101102
/**
102103
* Method to collect all the data.
103104
* Method will collect all users from the given course and will determine the user statistics
104-
*
105-
* @return 2d-array with user statistic
105+
* Builds an 2d-array with user statistic
106106
*/
107107
public function get_table_data() {
108108
// Get all userdata from a course.
109109
$context = \context_course::instance($this->courseid);
110110
$users = get_enrolled_users($context , '', 0, 'u.id, u.firstname, u.lastname');
111111

112+
// Step 1.0: Build the datatable with all relevant information.
112113
$ratingdata = $this->get_rating_data();
113114

114115
// Step 2.0: Now collect the data for every user in the course.
@@ -117,18 +118,19 @@ public function get_table_data() {
117118

118119
foreach ($ratingdata as $row) {
119120
// Did the student receive an up- or downvote?
120-
// Only count if the post is not anonymous (no anonymous setting or only questioner anonymous discussion).
121-
$this->process_received_votes($student, $row);
121+
if ($row->postuserid == $student->id) {
122+
$this->process_received_votes($student, $row);
123+
}
122124

123125
// Did a student submit a rating?
124-
// For solution marks: only count a solution if the discussion is not completely anonymous.
125-
// For helpful marks: only count helpful marks if the discussion is not any kind of anonymous.
126-
// Up and downvotes are always counted.
127-
$this->process_submitted_ratings($student, $row);
126+
if ($row->rateuserid == $student->id ) {
127+
$this->process_submitted_ratings($student, $row);
128+
}
128129

129-
// Did the student write a post? Only count a written post if: the post is not in an anonymous discussion;
130-
// or the post is in a partial anonymous discussion and the user is not the starter of the discussion.
131-
$this->process_written_posts($student, $row);
130+
// Did the student write a post?
131+
if ($row->postuserid == $student->id ) {
132+
$this->process_written_posts($student, $row);
133+
}
132134

133135
}
134136
// Get the user reputation from the course.
@@ -156,16 +158,16 @@ public function set_helpactivity() {
156158
get_string('helpamountofactivity', 'moodleoverflow'));
157159
$this->helpactivity->class = 'helpactivityclass btn btn-link';
158160
$this->helpactivity->iconattributes = ['role' => 'button',
159-
'data-container' => 'body',
160-
'data-toggle' => 'popover',
161-
'data-placement' => 'right',
162-
'data-action' => 'showhelpicon',
163-
'data-html' => 'true',
164-
'data-trigger' => 'focus',
165-
'tabindex' => '0',
166-
'data-content' => '<div class=&quot;no-overflow&quot;><p>' .
167-
get_string('helpamountofactivity', 'moodleoverflow') .
168-
'</p> </div>', ];
161+
'data-container' => 'body',
162+
'data-toggle' => 'popover',
163+
'data-placement' => 'right',
164+
'data-action' => 'showhelpicon',
165+
'data-html' => 'true',
166+
'data-trigger' => 'focus',
167+
'tabindex' => '0',
168+
'data-content' => '<div class=&quot;no-overflow&quot;><p>' .
169+
get_string('helpamountofactivity', 'moodleoverflow') .
170+
'</p> </div>', ];
169171

170172
$this->helpactivity->object = \html_writer::span($this->helpactivity->icon,
171173
$this->helpactivity->class,
@@ -251,6 +253,7 @@ private function badge_render($number) {
251253
$number . \html_writer::end_span());
252254
}
253255
}
256+
254257
/**
255258
* error handling
256259
* @param object $colname
@@ -274,14 +277,14 @@ private function createstudent($user) {
274277
$student->name = $user->firstname . ' ' . $user->lastname;
275278
$linktostudent = new \moodle_url('/user/view.php', ['id' => $student->id, 'course' => $this->courseid]);
276279
$student->link = \html_writer::link($linktostudent->out(), $student->name);
277-
$student->submittedposts = []; // Posts written by the student. Key = postid, Value = postid.
278-
$student->ratedposts = []; // Posts that the student rated. Key = rateid, Value = rateid.
280+
$student->submittedposts = []; // Posts written by the student. Key = postid, Value = postid.
281+
$student->ratedposts = []; // Posts that the student rated. Key = rateid, Value = rateid.
279282
$student->receivedupvotes = 0;
280283
$student->receiveddownvotes = 0;
281-
$student->forumactivity = 0; // Number of written posts and submitted ratings in the current moodleoverflow.
282-
$student->courseactivity = 0; // Number of written posts and submitted ratings in the course.
283-
$student->forumreputation = 0; // Reputation in the current moodleoverflow.
284-
$student->coursereputation = 0; // Reputation in the course.
284+
$student->forumactivity = 0; // Number of written posts and submitted ratings in the current moodleoverflow.
285+
$student->courseactivity = 0; // Number of written posts and submitted ratings in the course.
286+
$student->forumreputation = 0; // Reputation in the current moodleoverflow.
287+
$student->coursereputation = 0; // Reputation in the course.
285288
return $student;
286289
}
287290

@@ -292,7 +295,6 @@ private function createstudent($user) {
292295
*/
293296
private function get_rating_data() {
294297
global $DB;
295-
// Step 1.0: Build the datatable with all relevant Informations.
296298
$sqlquery = 'SELECT (ROW_NUMBER() OVER (ORDER BY ratings.id)) AS row_num,
297299
discuss.id AS discussid,
298300
discuss.userid AS discussuserid,
@@ -319,8 +321,8 @@ private function get_rating_data() {
319321
* @return void
320322
*/
321323
private function process_received_votes(&$student, $row) {
322-
if ($row->postuserid == $student->id &&
323-
(($row->anonymoussetting == 0) || ($row->anonymoussetting == 1 && $row->postuserid != $row->discussuserid))) {
324+
// Only count received votes if the post is not anonymous (no anonymous setting or only questioner anonymous discussion).
325+
if ((($row->anonymoussetting == 0) || ($row->anonymoussetting == 1 && $row->postuserid != $row->discussuserid))) {
324326
if ($row->rating == RATING_UPVOTE) {
325327
$student->receivedupvotes += 1;
326328
} else if ($row->rating == RATING_DOWNVOTE) {
@@ -336,38 +338,53 @@ private function process_received_votes(&$student, $row) {
336338
* @return void
337339
*/
338340
private function process_submitted_ratings(&$student, $row) {
341+
// For solution marks: only count a solution if the discussion is not completely anonymous.
342+
// For helpful marks: only count helpful marks if the discussion is not any kind of anonymous.
343+
// Up and downvotes are always counted.
339344
$solvedcheck = ($row->rating == RATING_SOLVED && $row->anonymoussetting != 2);
340345
$helpfulcheck = ($row->rating == RATING_HELPFUL && $row->anonymoussetting == 0);
341346
$isvote = ($row->rating == RATING_UPVOTE || $row->rating == RATING_DOWNVOTE);
342347

343-
if ($row->rateuserid == $student->id && !array_key_exists($row->rateid, $student->ratedpost)) {
348+
if (!array_key_exists($row->rateid, $student->ratedposts)) {
344349
if ($solvedcheck || $helpfulcheck || $isvote) {
345-
if ($row->moodleoverflowid == $this->moodleoverflowid) {
346-
$student->forumactivity++;
347-
}
350+
$this->increment_forumactivity($student, $row);
348351
$student->courseactivity++;
349352
$student->ratedposts[$row->rateid] = $row->rateid;
350353
}
351354
}
352355
}
353356

354357
/**
355-
* Process the written posts from a student.
358+
* Process the written posts from a student for the activity.
356359
* @param $student
357360
* @param $row
358361
* @return void
359362
*/
360363
private function process_written_posts(&$student, $row) {
361-
if ($row->postuserid == $student->id && !array_key_exists($row->postid, $student->submittedposts) &&
364+
// Only count a written post if: the post is not in an anonymous discussion:
365+
// or the post is in a partial anonymous discussion and the user is not the starter of the discussion.
366+
if (!array_key_exists($row->postid, $student->submittedposts) &&
362367
($row->anonymoussetting == 0 || ($row->anonymoussetting == 1 && $row->postuserid != $row->discussuserid))) {
363368

364-
if ($row->moodleoverflowid == $this->moodleoverflowid) {
365-
$student->forumactivity += 1;
366-
}
369+
$this->increment_forumactivity($student, $row);
367370
$student->courseactivity += 1;
368371
$student->submittedposts[$row->postid] = $row->postid;
369372
}
370373
}
374+
375+
/**
376+
* Increments the forum activity of a student.
377+
* @param $row
378+
* @param $moodleoverflowid
379+
* @param $forumactivity
380+
* @return void
381+
*/
382+
private function increment_forumactivity(&$student, $row) {
383+
if ($row->moodleoverflowid == $this->moodleoverflowid) {
384+
$student->forumactivity++;
385+
}
386+
}
387+
371388
// Sort function.
372389

373390
/**
@@ -381,58 +398,10 @@ private function sort_table_data($sortorder) {
381398
$length = count($this->userstatsdata);
382399
if ($sortorder['sortorder'] == 4) {
383400
// 4 means sort in ascending order.
384-
$this->quick_usertable_sort(0, $length - 1, $key, 'asc');
401+
moodleoverflow_quick_array_sort(0, $length - 1, $this->userstatsdata, $key, 'asc');
385402
} else if ($sortorder['sortorder'] == 3) {
386403
// 3 means sort in descending order.
387-
$this->quick_usertable_sort(0, $length - 1, $key, 'desc');
388-
}
389-
}
390-
391-
/**
392-
* Sorts userstatsdata with quicksort algorithm.
393-
*
394-
* @param int $low index for quicksort.
395-
* @param int $high index for quicksort.
396-
* @param int $key the column that is being sorted (upvotes, downvotes etc.).
397-
* @param string $order sort in ascending or descending order.
398-
* @return void
399-
*/
400-
private function quick_usertable_sort($low, $high, $key, $order) {
401-
if ($low >= $high) {
402-
return;
403-
}
404-
$left = $low;
405-
$right = $high;
406-
$pivot = $this->userstatsdata[intval(($low + $high) / 2)]->key;
407-
408-
$compare = function($a, $b) use ($order) {
409-
if ($order == 'asc') {
410-
return $a < $b;
411-
} else {
412-
return $a > $b;
413-
}
414-
};
415-
416-
do {
417-
while ($compare($this->userstatsdata[$left]->$key, $pivot)) {
418-
$left++;
419-
}
420-
while ($compare($pivot, $this->userstatsdata[$right]->$key)) {
421-
$right--;
422-
}
423-
if ($left <= $right) {
424-
$temp = $this->userstatsdata[$right];
425-
$this->userstatsdata[$right] = $this->userstatsdata[$left];
426-
$this->userstatsdata[$left] = $temp;
427-
$right--;
428-
$left++;
429-
}
430-
} while ($left <= $right);
431-
if ($low < $right) {
432-
$this->quick_usertable_sort($low, $right, $key, $order);
433-
}
434-
if ($high > $left) {
435-
$this->quick_usertable_sort($left, $high, $key, $order);
404+
moodleoverflow_quick_array_sort(0, $length - 1, $this->userstatsdata, $key, 'desc');
436405
}
437406
}
438407
}

locallib.php

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2130,3 +2130,54 @@ function moodleoverflow_update_all_grades() {
21302130
moodleoverflow_update_all_grades_for_cm($cmid->id);
21312131
}
21322132
}
2133+
2134+
2135+
/**
2136+
* Function to sort an array with a quicksort algorithm. This function is a recursive function that needs to
2137+
* be called from outside.
2138+
*
2139+
* @param int $low The lowest index of the array. The first call should set it to 0.
2140+
* @param int $high The highest index of the array. The first call should set it to the length of the array - 1.
2141+
* @param array $array The array to be sorted. It is passed by reference.
2142+
* @param string $key The key/attribute after what the algorithm sorts. The key should be an comparable integer.
2143+
* @param string $order The order of the sorting. It can be 'asc' or 'desc'.
2144+
* @return void
2145+
*/
2146+
function moodleoverflow_quick_array_sort($low, $high, &$array, $key, $order) {
2147+
if ($low >= $high) {
2148+
return;
2149+
}
2150+
$left = $low;
2151+
$right = $high;
2152+
$pivot = $array[intval(($low + $high) / 2)]->$key;
2153+
2154+
$compare = function($a, $b) use ($order) {
2155+
if ($order == 'asc') {
2156+
return $a < $b;
2157+
} else {
2158+
return $a > $b;
2159+
}
2160+
};
2161+
2162+
do {
2163+
while ($compare($array[$left]->$key, $pivot)) {
2164+
$left++;
2165+
}
2166+
while ($compare($pivot, $array[$right]->$key)) {
2167+
$right--;
2168+
}
2169+
if ($left <= $right) {
2170+
$temp = $array[$right];
2171+
$array[$right] = $array[$left];
2172+
$array[$left] = $temp;
2173+
$right--;
2174+
$left++;
2175+
}
2176+
} while ($left <= $right);
2177+
if ($low < $right) {
2178+
moodleoverflow_quick_array_sort($low, $right, $array, $key, $order);
2179+
}
2180+
if ($high > $left) {
2181+
moodleoverflow_quick_array_sort($left, $high, $array, $key, $order);
2182+
}
2183+
}

0 commit comments

Comments
 (0)