diff --git a/classes/task/cron_task.php b/classes/task/cron_task.php index c91ded43..edd08b20 100644 --- a/classes/task/cron_task.php +++ b/classes/task/cron_task.php @@ -73,7 +73,17 @@ public function execute() { return true; } + // For testing purpsoses + + // Clear eventually scheduled distribution of unallocated users. + $ratingallocate->clear_distribute_unallocated_tasks(); + // Run allocation. + $ratingallocate->distrubute_choices(); + + + // To do wieder alte funktion... // Only start the algorithm, if it should be run by the cron and hasn't been started somehow, yet. + /* if ($ratingallocate->ratingallocate->runalgorithmbycron === "1" && $ratingallocate->get_algorithm_status() === \mod_ratingallocate\algorithm_status::NOTSTARTED) { // Clear eventually scheduled distribution of unallocated users. @@ -81,6 +91,7 @@ public function execute() { // Run allocation. $ratingallocate->distrubute_choices(); } + */ } return true; } diff --git a/locallib.php b/locallib.php index dfcb5fbd..464132fc 100644 --- a/locallib.php +++ b/locallib.php @@ -1284,6 +1284,33 @@ public function get_ratings_for_rateable_choices() { return $fromraters; } + /** + * Returns all ratings for active choices but takes teamvote into consideration + */ + public function get_ratings_for_rateable_choices_with_teamvote() { + $sql = 'SELECT ra.* + FROM {ratingallocate_choices} c + JOIN ( SELECT min(r.id) as id, r.choiceid, r.rating, r.groupid + FROM {ratingallocate_ratings} r + GROUP BY r.choiceid, r.rating, r.groupid ) ra + ON c.id = ra.choiceid + WHERE c.ratingallocateid = :ratingallocateid AND c.active = 1'; + + $ratings = $this->db->get_records_sql($sql, array( + 'ratingallocateid' => $this->ratingallocateid + )); + /* + $raters = $this->get_raters_in_course(); + + // Filter out everyone who can't give ratings. + $fromraters = array_filter($ratings, function($rating) use ($raters) { + return array_key_exists($rating->userid, $raters); + }); + */ + + return $ratings; + } + /** * Returns the groups in the teamvote grouping with the amount of groupmembers * diff --git a/solver/edmonds-karp.php b/solver/edmonds-karp.php index 57c1b093..8fba19ae 100644 --- a/solver/edmonds-karp.php +++ b/solver/edmonds-karp.php @@ -80,7 +80,7 @@ public function compute_distribution($choicerecords, $ratings, $usercount, $team // with Bellman-Ford as search function (see: Edmonds-Karp in Introduction to Algorithms) // http://stackoverflow.com/questions/6681075/while-loop-in-php-with-assignment-operator // Look for an augmenting path (a shortest path from the source to the sink). - while ($path = $this->find_shortest_path_bellf_cspf($source, $sink, $teamvote, $toteamid)) { // If the function returns null, the while will stop. + while ($path = $this->find_shortest_path_bellf_cspf2($source, $sink, $teamvote, $toteamid)) { // If the function returns null, the while will stop. // Reverse the augmentin path, thereby distributing a user into a group. $this->augment_flow($path); unset($path); // Clear up old path. @@ -93,7 +93,56 @@ public function compute_distribution($choicerecords, $ratings, $usercount, $team /** * Find the shortest path with constraint (enough space for all teammembers in choice). - * This is a modified version of the Yen Algorithm for the consstrained shortest path first problem. + * This is a modified version of the Yen Algorithm for the constrained shortest path first problem. + * + * @param $from + * @param $to + * @param $teamvote + * @param $toteamid + * @return array|mixed|null array of the nodes in the path, null if no path found. + */ + private function find_shortest_path_bellf_cspf2 ($from, $to, $teamvote, $toteamid) { + + // Stop if no shortest path is found. + $i=1; + while ($pathcandidate = $this->find_shortest_path_bellf($from, $to)) { + // var_dump($this->graph); + var_dump($i); + var_dump($pathcandidate); + $foundedge = null; + + foreach ($this->graph[$pathcandidate[1]] as $index => $edge) { + if ($edge->to == $pathcandidate[0]) { + $foundedge = $edge; + $foundedgeid = $index; + break; + } + } + if ($foundedge->space > $teamvote[$toteamid[$pathcandidate[2]]]) { + // We just found the shortest path fulfilling the constraint. + return $pathcandidate; + } else { + // Remove the edge since this path is impossible. + array_splice($this->graph[1], $foundedgeid, 1); + // Add a new edge in the opposite direction whose weight has an opposite sign + // array_push($this->graph[$to], new edge($to, $from, -1 * $edge->weight)); + // according to php doc, this is faster. + // $this->graph[2][] = new edge(2, 1, -1 * $edge->weight); + } + unset($pathcandidate); + $i++; + } + var_dump("nix gefunden"); + return null; + + } + + + + + /** + * Find the shortest path with constraint (enough space for all teammembers in choice). + * This is a modified version of the Yen Algorithm for the constrained shortest path first problem. * * @param $from * @param $to @@ -103,30 +152,38 @@ public function compute_distribution($choicerecords, $ratings, $usercount, $team */ private function find_shortest_path_bellf_cspf ($from, $to, $teamvote, $toteamid) { + var_dump("find shortest path cspf"); + var_dump($this->graph); // Find the first shortest path. $pathcandidates = array(); $pathcandidates[0] = $this->find_shortest_path_bellf($from, $to); $nopathfound = is_null($pathcandidates[0]); - // Check if the path fulfills our constraint: space in choice left >= teammembers. - $constraintflag = true; - $foundedge = null; - foreach ($this->graph[$pathcandidates[0][1]] as $edge) { - if ($edge->to == $pathcandidates[0][0]) { - $foundedge = $edge; - break; + + // If the path exists, check if the path fulfills our constraint: space in choice left >= teammembers. + if (!$nopathfound) { + $constraintflag = true; + $foundedge = null; + + $pclenth = count($pathcandidates[0]); + foreach ($this->graph[$pathcandidates[0][1]] as $edge) { + if ($edge->to == $pathcandidates[0][0]) { + $foundedge = $edge; + break; + } + } + if ($foundedge->space <= $teamvote[$toteamid[$pathcandidates[0][2]]]) { + $constraintflag = false; + } + + if ($constraintflag) { + // We just found the shortest path fulfilling the constraint. + return $pathcandidates[0]; } - } - if ($foundedge->space <= $teamvote[$toteamid[$pathcandidates[0][2]]]) { - $constraintflag = false; + $constraintflag = true; } - if ($constraintflag) { - // We just found the shortest path fulfilling the constraint. - return $pathcandidates[0]; - } - $constraintflag = true; // Array of the potential next shortest paths. $nextpaths = array(); @@ -177,6 +234,11 @@ private function find_shortest_path_bellf_cspf ($from, $to, $teamvote, $toteamid // Calculate the spur path from the spur node to the sink. $spurpath = $this->find_shortest_path_bellf($i, $to); + if (is_null($spurpath)) { + var_dump("No spurpath"); + $nopathfound = true; + break; + } // Entire path is made up of the root path and spur path. $totalpath = array_merge($rootpath, $spurpath); @@ -210,13 +272,14 @@ private function find_shortest_path_bellf_cspf ($from, $to, $teamvote, $toteamid var_dump($nextpaths); // Check if the next best path fullfillst our constraint. - foreach ($this->graph[$nextpaths[0][1]] as $edge) { - if ($edge->to == $nextpaths[0][0]) { + $pclenth = count($pathcandidates[0]); + foreach ($this->graph[$pathcandidates[0][1]] as $edge) { + if ($edge->to == $pathcandidates[0][0]) { $foundedge = $edge; break; } } - if ($foundedge->space <= $teamvote[$toteamid[$nextpaths[0][2]]]) { + if ($foundedge->space <= $teamvote[$toteamid[$pathcandidates[0][2]]]) { $constraintflag = false; } @@ -225,6 +288,7 @@ private function find_shortest_path_bellf_cspf ($from, $to, $teamvote, $toteamid return $nextpaths[0]; } + // Not sure if saving all the paths is even necessary... $pathcandidates[$k] = $nextpaths[0]; // Reset flag condition. @@ -234,6 +298,7 @@ private function find_shortest_path_bellf_cspf ($from, $to, $teamvote, $toteamid } $k++; } + var_dump("Path not found"); return null; } @@ -247,7 +312,7 @@ private function get_cost_of_path ($path) { $cost = 0; - for ($i = count($path) - 1; $i > 0; $i--) { + for ($i = count($path)-1; $i > 0; $i--) { $from = $path[$i]; $to = $path[$i - 1]; $edge = null; diff --git a/solver/solver-template.php b/solver/solver-template.php index 82728f24..1a4aa4df 100644 --- a/solver/solver-template.php +++ b/solver/solver-template.php @@ -93,7 +93,11 @@ public function distribute_users(\ratingallocate $ratingallocate) { // Load data from database. $choicerecords = $ratingallocate->get_rateable_choices(); - $ratings = $ratingallocate->get_ratings_for_rateable_choices(); + if ($teamvote) { + $ratings = $ratingallocate->get_ratings_for_rateable_choices_with_teamvote(); + } else { + $ratings = $ratingallocate->get_ratings_for_rateable_choices(); + } // Randomize the order of the entries to prevent advantages for early entry. shuffle($ratings); @@ -116,9 +120,9 @@ public function distribute_users(\ratingallocate $ratingallocate) { $userids = array(); foreach ($distributions as $choiceid => $teamids) { foreach ($teamids as $teamid) { - $userids[$teamid] = groups_get_members($teamid, 'u.id'); + array_merge($userids, groups_get_members($teamid, 'u.id')); } - $userdistributions[$choiceid] = array_merge($userids); + $userdistributions[$choiceid] = $userids; } // We have to delete the provisionally groups containing only one user.