Shape text using Pango and HarfBuzz; gives us nice ligatures and exotic scripts.
[ccbs] / html / show-tournament.pl
1 #! /usr/bin/perl
2
3 use ccbs;
4 use strict;
5 use warnings;
6
7 my $cgi = new CGI;
8 my $id = $cgi->param('id');
9
10 my $dbh = ccbs::db_connect();
11
12 my $tournament = $dbh->selectrow_hashref('SELECT * FROM tournaments NATURAL JOIN seasons NATURAL JOIN countries NATURAL JOIN machines NATURAL JOIN scoringsystems WHERE tournament=?', undef, $id);
13
14 # Push season name through i18n
15 $tournament = { %$tournament, seasonname => Locale::gettext::gettext($tournament->{'seasonname'}) };
16
17
18 my $rankings;
19 if ($tournament->{'country'} == 1) {
20         $rankings = ccbs::db_fetch_all($dbh, 'SELECT ranking,player,nick || \' (\' || countrycode::varchar || \')\' AS nick,COALESCE(points,-1) AS points FROM tournamentrankings NATURAL JOIN players NATURAL JOIN countries WHERE tournament=? ORDER BY ranking', $id);
21 } else {
22         $rankings = ccbs::db_fetch_all($dbh, 'SELECT ranking,player,COALESCE(nick || \' (\' || clubcode::varchar || \')\', nick) AS nick,COALESCE(points,-1) AS points FROM tournamentrankings NATURAL JOIN players NATURAL LEFT JOIN clubs WHERE tournament=? ORDER BY ranking', $id);
23 }
24
25 my $songs = ccbs::db_fetch_all($dbh, 'SELECT song,title FROM machinesongs NATURAL JOIN songs WHERE machine=? ORDER BY LOWER(title)', $tournament->{'machine'});
26
27 # Check if the last round is valid for closing (by checking if all scores
28 # entered are valid)
29 my $ref = $dbh->selectrow_hashref('SELECT COUNT(*) AS num_incomplete FROM scores WHERE tournament=? AND (song IS NULL OR playmode IS NULL OR difficulty IS NULL OR chosen IS NULL or score IS NULL)', undef, $tournament->{'tournament'});
30 my ($closing_valid,$finishing_valid);
31 $finishing_valid = 0;
32 if ($ref->{'num_incomplete'} == 0) {
33         $closing_valid = 1;
34 } else {
35         $closing_valid = 0;
36 }
37
38 # Check if this tournament is on the bigscreen or not.
39 my $ref = $dbh->selectrow_hashref('SELECT * FROM bigscreen.active_tournament');
40 my $bigscreen = ($ref->{'tournament'} == $id) ? 1 : 0;
41
42 my $active_groups;
43 if ($bigscreen) {
44         # Find all groups currently shown on the bigscreen.
45         $active_groups = ccbs::db_fetch_all($dbh, 'SELECT * FROM bigscreen.active_groups WHERE tournament=?', $id);
46 }
47
48 # Swoop all the data in in a big join, then order it over to quasi-sane Perl objects.
49 # (round -> parallel -> player -> songs -> title,chosen,score)
50 my $scores;
51 if ($tournament->{'country'} == 1) {
52         $scores = ccbs::db_fetch_all($dbh,
53         'SELECT round,parallel,position,playmode,difficulty,songnumber,player,nick || \' (\' || countrycode::varchar || \')\' AS nick,song,title,chosen,score,best_rank,worst_rank FROM roundparticipation NATURAL JOIN players NATURAL JOIN countries NATURAL JOIN scores NATURAL LEFT JOIN songs NATURAL JOIN get_minmax_rank_for_players(?,\'single\') WHERE tournament=? ORDER BY round,parallel,position,songnumber',
54         $id, $id);
55 } else {
56         $scores = ccbs::db_fetch_all($dbh,
57         'SELECT round,parallel,position,playmode,difficulty,songnumber,player,COALESCE(nick || \' (\' || clubcode::varchar || \')\', nick) AS nick,song,title,chosen,score,best_rank,worst_rank FROM roundparticipation NATURAL JOIN players NATURAL JOIN scores NATURAL LEFT JOIN songs NATURAL LEFT JOIN clubs NATURAL JOIN get_minmax_rank_for_players(?,\'single\') WHERE tournament=? ORDER BY round,parallel,position,songnumber',
58         $id, $id);
59 }
60
61 my @rounds = ();
62
63 my ($round, $parallel, $player) = (-1,-1,'');
64 for my $score (@$scores) {
65         if ($score->{'round'} != $round) {
66                 $round = $score->{'round'};
67                 push @rounds, { round => $round, parallels => [], locked => 0 };
68                 $parallel = -1;
69         }
70         my $p = $rounds[$#rounds]->{'parallels'};
71         if ($score->{'parallel'} != $parallel) {
72                 $parallel = $score->{'parallel'};
73                 push @$p, { parallel => $parallel, players => [], songs => [], num_songs => 0 };
74                 $player = '';
75
76                 if ($bigscreen) {
77                         # suboptimal, but heck :-)
78                         $p->[$#$p]->{'bigscreen'} = 0;
79                         for my $ag (@$active_groups) {
80                                 if ($ag->{'round'} == $round && $ag->{'parallel'} == $parallel) {
81                                         $p->[$#$p]->{'bigscreen'} = 1;
82                                         last;
83                                 }
84                         }
85                 }
86
87                 # Information on songs is not selected from roundrandomsongs etc.,
88                 # but is filled in the first time the song is seen for this round
89                 # (ie. below)
90         }
91         if ($score->{'position'} == 1) {
92                 if ($score->{'chosen'}) {
93                         push @{$p->[$#$p]->{'songs'}}, { song => -1, title => '' };
94                 } else {
95                         push @{$p->[$#$p]->{'songs'}}, $score;
96                 }
97                 $p->[$#$p]->{'num_songs'}++;
98         }
99         
100         my $pl = $p->[$#$p]->{'players'};
101         if ($score->{'nick'} ne $player) {
102                 $player = $score->{'nick'};
103                 push @$pl, { player => $score->{'player'}, nick => $player, songs => [], total => 0, best_rank => $score->{'best_rank'},
104                         worst_rank => $score->{'worst_rank'} };
105         }
106
107         push @{$pl->[$#$pl]->{'songs'}}, $score;
108
109         if (defined($score->{'score'})) {
110                 $pl->[$#$pl]->{'total'} += $score->{'score'};
111         }
112 }
113
114 # FIXME: In some odd cases, there _might_ be an empty group right at the end. Fix this when
115 #        we are able to add/delete people in groups.
116
117 my $num_rounds = scalar @rounds;
118 my $num_rankings = scalar @$rankings;
119
120 # Lock all rounds but the last (active?) one
121 for my $r (0..$#rounds-1) {
122         $rounds[$r]->{'locked'} = 1;
123 }
124
125 # If there's only one group left and it's valid for closing, we can also finish
126 # the entire tournament if we'd like
127 if ($closing_valid && (scalar @rounds > 0 && scalar @{$rounds[$#rounds]->{'parallels'}}) == 1) {
128         $finishing_valid = 1;
129 }
130
131 # If there have been no rounds, check out the number of participants; if not, check the
132 # number of qualified from the last round
133 my $num_qualified;
134 if ($num_rounds == 0) {
135         my $ref = $dbh->selectrow_hashref('SELECT COUNT(*) AS num_participants FROM tournamentparticipation WHERE tournament=?', undef, $id);
136         $num_qualified = $ref->{'num_participants'};
137 } else {
138         my $ref = $dbh->selectrow_hashref('SELECT SUM(numqualifying) AS numqualifying FROM rounds NATURAL JOIN groups WHERE tournament=? AND round=?', undef, $id, $num_rounds);
139         $num_qualified = $ref->{'numqualifying'};
140 }
141
142 # And last: If there is a ranking list, the tournament is closed and we really can't
143 # do anything more
144 if ($num_rankings > 0) {
145         $closing_valid = 0;
146         $finishing_valid = 0;
147         if ($#rounds > -1) {
148                 $rounds[$#rounds]->{'locked'} = 1;
149         }
150 }
151
152 ccbs::print_header();
153 ccbs::process_template('show-tournament.tmpl', $tournament->{'tournamentname'}, {
154         tournament => $tournament,
155         rankings => $rankings,
156         num_rankings => $num_rankings,
157         rounds => \@rounds,
158         num_rounds => $num_rounds,
159         num_qualified => $num_qualified,
160         songs => $songs,
161         closing_valid => $closing_valid,
162         finishing_valid => $finishing_valid,
163         bigscreen => $bigscreen
164 });
165 $dbh->disconnect;