]> git.sesse.net Git - ccbs/blob - html/do-start-round.pl
Combined patch (sorry): fix URL, fix points awarded.
[ccbs] / html / do-start-round.pl
1 #! /usr/bin/perl
2
3 use ccbs;
4 use strict;
5 use warnings;
6
7 ccbs::admin_only();
8
9 my $dbh = ccbs::db_connect();
10 my $cgi = new CGI;
11
12 my $tournament = $cgi->param('tournament');
13 my $round = $cgi->param('round');
14 my $num_random = $cgi->param('numrandom');
15 my $num_chosen = $cgi->param('numchosen');
16 my $num_groups = $cgi->param('numgroups');
17 my $num_qual = $cgi->param('numqual');
18
19 $dbh->{AutoCommit} = 0;
20
21 $dbh->do('INSERT INTO rounds (tournament, round, randomsongs, chosensongs, numqualifying) VALUES (?, ?, ?, ?, ?)',
22         undef, $tournament, $round, $num_random, $num_chosen, $num_qual);
23
24 if ($num_groups == 1) {
25         $dbh->do('INSERT INTO groups (tournament, round, parallel) VALUES (?, ?, ?)',
26                 undef, $tournament, $round, 0);
27 } else {
28         for my $i (1..$num_groups) {
29                 $dbh->do('INSERT INTO groups (tournament, round, parallel) VALUES (?, ?, ?)',
30                         undef, $tournament, $round, $i);
31         }
32 }
33
34 # Seed people into groups (quite preliminary for now)
35 my $people;
36 if ($round == 1) {
37         $people = ccbs::db_fetch_all($dbh, 'SELECT * FROM players WHERE player IN ( SELECT player FROM tournamentparticipation WHERE tournament=? ) ORDER BY lower(nick)',
38                 $tournament);
39 } else {
40         # First of all, check that there are no null values!
41         my $ref = $dbh->selectrow_hashref('SELECT COUNT(*) AS num_incomplete FROM scores WHERE tournament=? AND round=? AND (song IS NULL OR playmode IS NULL OR difficulty IS NULL OR chosen IS NULL or score IS NULL)', undef, $tournament, $round-1);
42         if ($ref->{'num_incomplete'} != 0) {
43                 ccbs::user_error("Det er fortsatt $ref->{'num_incomplete'} sanger igjen i denne runden som ikke har alle data registrert.");
44         }
45
46         # Find out how many people will go on from the _current_ group (ie. the one
47         # before the one we just inserted)
48         my $ref = $dbh->selectrow_hashref('SELECT numqualifying FROM rounds WHERE tournament=? AND round=?',
49                 undef, $tournament, $round - 1);
50         my $num_qual_prev = $ref->{'numqualifying'};
51
52         # Get the total list of scores for each player in this round, and pick
53         # out the best N
54         $people = [];
55         my $q = $dbh->prepare('SELECT parallel,player,SUM(score)/SUM(CASE WHEN chosen THEN 10 ELSE feetrating END) AS score FROM scores NATURAL JOIN tournaments NATURAL JOIN max_single_feetrating WHERE tournament=? AND round=? GROUP BY parallel,player ORDER BY parallel, SUM(score) DESC');
56         $q->execute($tournament, $round - 1);
57         
58         my ($parallel,$num_from_this_parallel);
59
60         while (my $ref = $q->fetchrow_hashref()) {
61                 if (!defined($parallel) || $parallel != $ref->{'parallel'}) {
62                         $parallel = $ref->{'parallel'};
63                         $num_from_this_parallel = 0;
64                 }
65                 if ($num_from_this_parallel++ < $num_qual_prev) {
66                         push @$people, {%$ref};
67                 }
68         }
69 }
70
71 if ($num_groups == 1) {
72         # Everybody's in the same group
73         my @speople = sort { $a->{'score'} <=> $b->{'score'} } @$people;
74
75         my $position = 1;
76         for my $p (@speople) {
77                 $dbh->do('INSERT INTO roundparticipation (tournament, round, parallel, player, position) VALUES (?, ?, ?, ?, ?)', undef,
78                         $tournament, $round, 0, $p->{'player'}, $position);
79                 $position++;
80         }
81 } else {
82         # Zigzag people to get the most fair groups possible
83         my @speople = sort { $b->{'score'} <=> $a->{'score'} } @$people;
84
85         my @ngroups = ();
86         for my $g (1..$num_groups) {
87                 push @ngroups, [];
88         }
89         
90         my $group = 0;
91         my $direction = 1;
92         for my $p (@speople) {
93                 push @{$ngroups[$group]}, $p->{'player'};
94                 if ($group + $direction < 0 || $group + $direction >= $num_groups) {
95                         $direction = -$direction;
96                 } else {
97                         $group += $direction;
98                 }
99         }
100
101         $group = 1;
102         for my $g (@ngroups) {
103                 my @gpeople = reverse @$g;
104                 for my $position (0..$#gpeople) {
105                         $dbh->do('INSERT INTO roundparticipation (tournament, round, parallel, player, position) VALUES (?, ?, ?, ?, ?)', undef,
106                                 $tournament, $round, $group, $gpeople[$position], $position + 1);
107                 }
108                 $group++;
109         }
110 }
111
112 # Pick random songs for the groups (don't pick challenge-only songs; slightly
113 # clumsy, should we have used an IN subquery instead?)
114 for my $g (1..$num_groups) {
115         my $gg = ($num_groups == 1) ? 0 : $g;
116
117         for my $s (1..$num_random) {
118                 my $ref = $dbh->selectrow_hashref('SELECT * FROM machinesongs NATURAL JOIN songratings WHERE song NOT IN ( SELECT song FROM randomsongsused ) AND machine=( SELECT machine FROM tournaments WHERE tournament=? ) AND playmode=\'single\' AND difficulty=\'expert\' ORDER BY random() LIMIT 1',
119                         undef, $tournament);
120                 if (!defined($ref)) {
121                         ccbs::user_error('Det er ikke flere sanger igjen i sangvelgeren!');
122                 }
123                 $dbh->do('INSERT INTO randomsongsused (song) VALUES (?)',
124                         undef, $ref->{'song'});
125                 $dbh->do('INSERT INTO roundrandomsongs (tournament, round, parallel, song) VALUES (?,?,?,?)',
126                         undef, $tournament, $round, $gg, $ref->{'song'});
127
128                 $dbh->do('INSERT INTO scores SELECT tournament,round,parallel,player,?,?,\'single\',\'expert\',\'f\',NULL FROM roundparticipation WHERE tournament=? AND round=? AND parallel=?', undef,
129                         $s, $ref->{'song'}, $tournament, $round, $gg);
130         }
131 }
132
133 # Add empty "score" records for the chosen songs.
134 for my $g (1..$num_groups) {
135         my $gg = ($num_groups == 1) ? 0 : $g;
136
137         for my $s (1..$num_chosen) {
138                 $dbh->do('INSERT INTO scores SELECT tournament,round,parallel,player,?,NULL,\'single\',\'expert\',\'t\',NULL FROM roundparticipation WHERE tournament=? AND round=? AND parallel=?', undef,
139                         $s + $num_random, $tournament, $round, $gg);
140         }
141 }
142
143 ccbs::print_see_other('show-tournament.pl?id=' . $tournament);
144
145 $dbh->commit;
146 $dbh->disconnect;