2 # A generator of score sheets. More ugly than it deserves.
12 $usage = "Usage: mo-score [--detail] [--alt] [--extras] [--html] [--tex] [--table] [--merged] [<directory>/]<task> ...";
13 while (($arg = $ARGV[0]) =~ /^--([a-z]+)$/) {
16 if (!eval "defined $var") { die $usage; }
23 open STDOUT, "|column -t -s'\t'" or die;
27 print STDERR "Scanning contestants... ";
28 open (CT, "bin/mo-get-users --full |") || die "Cannot get list of contestants";
32 ($u eq "somebody") && next;
36 print STDERR 0+keys %users, "\n";
38 print STDERR "Scanning exceptions... ";
39 if ($extras && open (EX, "exceptions")) {
42 (/^$/ || /^#/) && next;
45 defined $users{$u} || die "Unknown user $u";
46 while (@a) { $extra{$u} += shift @a; }
50 } else { print STDERR "none\n"; }
52 print STDERR "Scanning task results... ";
55 foreach $u (keys %users) {
56 foreach $task (@ARGV) {
57 my ($dir, $t) = ("testing", $task);
58 if ($task =~ m@^(.*)/([^/]*)$@) {
63 $tt = "$dir/$u/$t/points" . ($alt ? ".alt" : "");
65 print STDERR "$u/$t ";
66 open (X, $tt) || die "Unable to open $tt";
69 /^(\S+) (-?\d+)\s*(.*)/ || die "Parse error: $_";
74 ($ttest_merged = $ttest) =~ s/[^0-9]//g;
75 $ttest = $ttest_merged if $merged;
76 $known_tests{$t}{$ttest} = 1;
78 if ($tpts == 0 && $trem ne "OK") {
79 if ($trem =~ /^Compile /) { $cmt = "CE"; }
80 elsif ($trem =~ /^Time limit exceeded/) { $cmt = "TO"; }
81 elsif ($trem =~ /^Exited with error /) { $cmt = "RE"; }
82 elsif ($trem =~ /^Caught fatal signal /) { $cmt = "SG"; }
83 elsif ($trem =~ /^([A-Za-z])\S*\s+([A-Za-z])/) {
84 ($cmt = "$1$2") =~ tr/a-z/A-Z/;
86 if (!defined $messages{$trem}) {
87 $messages{$trem} = $cmt;
88 if (!defined $error_codes{$cmt}) {
89 $error_codes{$cmt} = $trem;
91 $error_codes{$cmt} .= ", $trem";
95 if (!defined($results{$u}{$t}{$ttest}) || $results{$u}{$t}{$ttest} > $tpts) {
96 $results{$u}{$t}{$ttest} = $tpts;
97 $comment{$u}{$t}{$ttest} = $cmt;
99 if (!defined($results_merged{$u}{$t}{$ttest_merged}) || $results_merged{$u}{$t}{$ttest_merged} > $tpts) {
100 $results_merged{$u}{$t}{$ttest_merged} = $tpts;
105 foreach my $t (keys %known_tasks) {
107 foreach my $pts (values %{$results_merged{$u}{$t}}) { $total{$u}{$t} += $pts; }
112 print STDERR "Creating table template... ";
113 @header = ("Rank","User","Name");
114 @body = ('','$u','$users{$u}');
116 @footer = ('"Total"','','');
118 push @header, "Extra";
119 push @body, '$extra{$u}';
121 push @bodysums, $col;
122 push @footer, "sum($col)";
125 foreach $task (@ARGV) {
126 my $t = ($task =~ m@/([^/]*)$@) ? $1 : $task;
127 defined $known_tasks{$t} || die "Unknown task $t";
129 push @header, substr($t, 0, 4);
130 push @body, "(\$xx = \$total{\$u}{'$t'}) > 0 ? \$xx : 0";
132 push @footer, "sum($col)";
133 push @bodysums, $col;
135 foreach $s (sort { $a <=> $b } keys %{$known_tests{$t}}) {
137 push @body, "\$comment{\$u}{'$t'}{'$s'}";
139 push @footer, "sum($col)";
143 push @header, "Total";
144 push @body, join('+', map { $_ = "\$$_" } @bodysums);
146 push @footer, "sum($col)";
149 print STDERR "h: ", join(':',@header), "\n" if $debug;
150 print STDERR "b: ", join(':',@body), "\n" if $debug;
151 print STDERR "f: ", join(':',@footer), "\n" if $debug;
153 print STDERR "Filling in results... ";
155 foreach $u (keys %users) {
157 foreach my $c (@body) {
158 $c =~ s/\$(\d+)/\$\$row[$1]/g;
160 push @$row, (defined $x ? $x : '-');
162 print STDERR "row: ", join(':',@$row), "\n" if $debug;
167 print STDERR "Sorting... ";
168 $sortcol = @{$table[0]} - 1;
172 $p = $$b[$sortcol] <=> $$a[$sortcol];
173 ($an = $$a[$namecol]) =~ s/(\S+)\s+(\S+)/$2 $1/;
174 ($bn = $$b[$namecol]) =~ s/(\S+)\s+(\S+)/$2 $1/;
175 $p ? $p : ($an cmp $bn);
178 while ($i < @table) {
180 while ($i < @table && ${$table[$i]}[$sortcol] == ${$table[$j]}[$sortcol]) {
184 ${table[$j]}[0] = "$i.";
186 ${table[$j]}[0] = $j+1 . ".-" . $i . ".";
188 while ($j < $i) { ${table[$j++]}[0] = ""; };
193 print STDERR "Attaching headers and footers... ";
194 sub sum { my $col=shift @_; my $t=0; foreach my $z (0..@table-1) { $t += ${$table[$z]}[$col]; } $t; }
195 map { $_ = eval $_; } @footer;
196 push @table, \@footer;
197 unshift @table, \@header;
201 foreach $r (@table) { print join(':',@$r), "\n"; }
203 print '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html40/strict.dtd">', "\n";
204 print "<HTML><HEAD><TITLE>Rank list</TITLE></HEAD><BODY>\n";
205 print "<H1>Rank list</H1>\n";
208 &printHtmlHeader(\@perm);
211 foreach $r (@table[1..($#table - 1)]) {
212 &printHtmlRow(@{$r}[@perm]);
216 &printHtmlRow(@{$table[$#table]}[@perm]);
220 print "<H2>Error codes</H2><UL>\n";
221 foreach $r (sort keys %error_codes) { print "<LI>$r: $error_codes{$r}\n"; }
224 print "</BODY></HTML>\n";
226 print "\\error{TeX output not supported yet!}\n";
228 foreach $r (@table) { print join("\t",@$r), "\n"; }
231 foreach $r (sort keys %error_codes) { print "$r: $error_codes{$r}\n"; }
236 print "<TR>", join('',map {
237 if ($hdr) { $_ = "<TH>$_"; }
238 else { $_ = "<TD align=" . (/^[0-9A-Z-]+$/ ? "right" : "left") . (length($_) > 14 ? " width=150" : "") . ">$_"; }
242 sub printHtmlHeader {
246 my $colspec = "<colgroup span=3>";
254 $hdr1 = "<th rowspan=2>Rank<th rowspan=2>User<th rowspan=2>Name";
255 $extras and $p++ and push @$perm, 3 and $hdr1.="<th rowspan=2>Extra" and $colspec.="<colgroup span=1>"; ##Extra hack
256 for my $task (@tasks) {
258 my $nSub = scalar(keys %{$known_tests{$task}});
261 map { push @$perm, $p++ } (1..$nSub);
262 push @$perm, $p - $nSub - 1;
264 $colspec .= "<colgroup span='" . $nSub . "'>\n";
265 $colspec .= "<colgroup span='1'>\n";
266 $hdr1 .= "<th colspan='" . ($nSub + 1) . "' style='border-bottom:1px solid black;'>$task";
267 $hdr2 .= join("", map { "<th>$_" } sort {$a <=> $b} keys %{$known_tests{$task}});
268 $hdr2 .= "<th>Total";
271 $hdr1 .= "<th rowspan='2'>Total";
273 } else { ## no detail
275 $hdr1 = "<th>Rank<th>User<th>Name";
276 $extras and $p++ and push @$perm, 3 and $hdr1.="<th>Extra" and $colspec.="<colgroup span=1>"; ##Extra hack
278 for my $task (@tasks) {
280 $hdr1 .= "<th>$task";
282 $hdr1 .= "<th>Total";
283 $colspec .= "<colgroup span='" . scalar (@tasks) . "'>";
288 print "<TABLE rules=groups frame=all border='1' cellpadding='2'>\n";
289 print "$colspec<colgroup span='1'>\n";
290 print "<tr>$hdr1</tr>\n";
291 print "<tr>$hdr2</tr>\n" if $detail;