use strict;
use warnings;
+ccbs::admin_only();
+
my $dbh = ccbs::db_connect();
my $cgi = new CGI;
# This should never happen
if (!defined($last_sround)) {
- ccbs::user_error("Forsøk på å avslutte en turnering med flere grupper aktive.");
+ ccbs::user_error("Forsøk på å avslutte en turnering med flere grupper aktive.");
}
# Grab all the remaining groups; we order by the simple criteria:
# 1. If player A has gone to group X and player B hasn't, player A is higher.
-# 2. If player A has higher max score than player B, player A is higher.
-my $scores = ccbs::db_fetch_all($dbh, 'SELECT player FROM scores WHERE tournament=? AND round < ? GROUP BY round,player ORDER BY round DESC,MAX(score) DESC',
- $tournament, $last_sround);
-for my $s (@$scores) {
- next if ($already_ordered{$s->{'player'}});
- $dbh->do('INSERT INTO tournamentrankings (tournament, ranking, player, points) VALUES (?,?,?,?)',
- undef, $tournament, $ranking, $s->{'player'}, points_for_place($ranking));
- $ranking++;
- $already_ordered{$s->{'player'}} = 1;
+# 2. If player A has a higher ranking in his/her group than player B, player A is higher.
+# 3. If player A has higher max score than player B, player A is higher.
+
+# Basically, #2 makes this impossible to achieve in pure SQL. We just have
+# to fetch one and one group and make the best out of it. Fetch out all the
+# parallels (in sorted order) and grab all players in turn.
+
+my $qscores = $dbh->prepare('SELECT parallel,player,SUM(score) AS sum_score,MAX(score) AS max_score FROM scores WHERE tournament=? AND round=? GROUP BY parallel,player ORDER BY SUM(score) DESC');
+for my $r (reverse (1..($last_sround-1))) {
+ my @parallels = ();
+ my $num_players = 0;
+
+ $qscores->execute($tournament, $r);
+
+ while (my $ref = $qscores->fetchrow_hashref()) {
+ my $p = $ref->{'parallel'};
+ if (!defined($parallels[$p])) {
+ $parallels[$p] = [];
+ }
+
+ push @{$parallels[$p]}, {%$ref};
+ $num_players++;
+ }
+
+ my $place = 0;
+
+ # Grab players from the top until nobody's left
+ while ($num_players > 0) {
+ my @players_this_place = ();
+ for my $p (@parallels) {
+ next if (!defined($p->[$place]));
+ $num_players--;
+ next if ($already_ordered{$p->[$place]->{'player'}});
+
+ push @players_this_place, $p->[$place];
+ }
+
+ @players_this_place = sort { $b->{'max_score'} <=> $a->{'max_score'} } @players_this_place;
+
+ for my $s (@players_this_place) {
+ $dbh->do('INSERT INTO tournamentrankings (tournament, ranking, player, points) VALUES (?,?,?,?)',
+ undef, $tournament, $ranking, $s->{'player'}, points_for_place($ranking));
+ $ranking++;
+ $already_ordered{$s->{'player'}} = 1;
+ }
+
+ $place++;
+ }
}
$dbh->commit;