]> mj.ucw.cz Git - moe.git/blob - bin/mo-score
Use `char *' for all strings instead of `byte *'.
[moe.git] / bin / mo-score
1 #!/usr/bin/perl
2
3 $debug = 0;
4 $detail = 0;
5 $html = 0;
6 $tex = 0;
7 $extras = 0;
8 $alt = 0;
9 $merged = 0;
10 $usage = "Usage: mo-score [--detail] [--alt] [--extras] [--html] [--tex] [--merged] [<directory>/]<task> ...";
11 while (($arg = $ARGV[0]) =~ /^--([a-z]+)$/) {
12         shift @ARGV;
13         $var = "\$$1";
14         if (!eval "defined $var") { die $usage; }
15         eval "$var = 1;";
16 }
17 @ARGV || die $usage;
18
19 print STDERR "Scanning contestants... ";
20 open (CT, "bin/mo-get-users --full |") || die "Cannot get list of contestants";
21 while (<CT>) {
22         chomp;
23         ($u,$f) = split /\t/;
24         ($u eq "somebody") && next;
25         $users{$u}=$f;
26 }
27 close CT;
28 print STDERR 0+keys %users, "\n";
29
30 print STDERR "Scanning exceptions... ";
31 if ($extras && open (EX, "exceptions")) {
32         while (<EX>) {
33                 chomp;
34                 (/^$/ || /^#/) && next;
35                 @a = split /\s+/;
36                 $u = shift @a;
37                 defined $users{$u} || die "Unknown user $u";
38                 while (@a) { $extra{$u} += shift @a; }
39         }
40         close EX;
41         print STDERR "OK\n";
42 } else { print STDERR "none\n"; }
43
44 print STDERR "Scanning task results... ";
45 %messages = ();
46 %error_codes = ();
47 foreach $u (keys %users) {
48         foreach $task (@ARGV) {
49                 my ($dir, $t) = ("testing", $task);
50                 if ($task =~ m@^(.*)/([^/]*)$@) {
51                         $dir = $1;
52                         $t = $2;
53                 }
54                 $known_tasks{$t} = 1;
55                 $tt = "$dir/$u/$t/points" . ($alt ? ".alt" : "");
56                 -f $tt || next;
57                 print STDERR "$u/$t ";
58                 open (X, $tt) || die "Unable to open $tt";
59                 while (<X>) {
60                         chomp;
61                         /^(\S+) (-?\d+)\s*(.*)/ || die "Parse error: $_";
62                         $ttest = $1;
63                         $tpts = $2;
64                         $trem = $3;
65                         $trem =~ s/\[.*//;
66                         ($ttest_merged = $ttest) =~ s/[^0-9]//g;
67                         $ttest = $ttest_merged if $merged;
68                         $known_tests{$t}{$ttest} = 1;
69                         $cmt = $tpts;
70                         if ($tpts == 0 && $trem ne "OK") {
71                                 if ($trem =~ /^Compile /) { $cmt = "CE"; }
72                                 elsif ($trem =~ /^Time limit exceeded/) { $cmt = "TO"; }
73                                 elsif ($trem =~ /^Exited with error /) { $cmt = "RE"; }
74                                 elsif ($trem =~ /^Caught fatal signal /) { $cmt = "SG"; }
75                                 elsif ($trem =~ /^([A-Za-z])\S*\s+([A-Za-z])/) {
76                                         ($cmt = "$1$2") =~ tr/a-z/A-Z/;
77                                 }
78                                 if (!defined $messages{$trem}) {
79                                         $messages{$trem} = $cmt;
80                                         if (!defined $error_codes{$cmt}) {
81                                                 $error_codes{$cmt} = $trem;
82                                         } else {
83                                                 $error_codes{$cmt} .= ", $trem";
84                                         }
85                                 }
86                         }
87                         if (!defined($results{$u}{$t}{$ttest}) || $results{$u}{$t}{$ttest} > $tpts) {
88                                 $results{$u}{$t}{$ttest} = $tpts;
89                                 $comment{$u}{$t}{$ttest} = $cmt;
90                         }
91                         if (!defined($results_merged{$u}{$t}{$ttest_merged}) || $results_merged{$u}{$t}{$ttest_merged} > $tpts) {
92                                 $results_merged{$u}{$t}{$ttest_merged} = $tpts;
93                         }
94                 }
95                 close X;
96         }
97         foreach my $t (keys %known_tasks) {
98                 $total{$u}{$t} = 0;
99                 foreach my $pts (values %{$results_merged{$u}{$t}}) { $total{$u}{$t} += $pts; }
100         }
101 }
102 print STDERR "OK\n";
103
104 print STDERR "Creating table template... ";
105 @header = ("Rank","User","Name");
106 @body = ('','$u','$users{$u}');
107 @bodysums = ();
108 @footer = ('"Total"','','');
109 if (keys %extra) {
110         push @header, "Extra";
111         push @body, '$extra{$u}';
112         $col = 0+@footer;
113         push @bodysums, $col;
114         push @footer, "sum($col)";
115 }
116 @tasks = ();
117 foreach $task (@ARGV) {
118         my $t = ($task =~ m@/([^/]*)$@) ? $1 : $task;
119         defined $known_tasks{$t} || die "Unknown task $t";
120         push @tasks, $t;
121         push @header, substr($t, 0, 4);
122         push @body, "(\$xx = \$total{\$u}{'$t'}) > 0 ? \$xx : 0";
123         $col = 0+@footer;
124         push @footer, "sum($col)";
125         push @bodysums, $col;
126         if ($detail) {
127                 foreach $s (sort { $a <=> $b } keys %{$known_tests{$t}}) {
128                         push @header, "$s";
129                         push @body, "\$comment{\$u}{'$t'}{'$s'}";
130                         $col = 0+@footer;
131                         push @footer, "sum($col)";
132                 }
133         }
134 }
135 push @header, "Total";
136 push @body, join('+', map { $_ = "\$$_" } @bodysums);
137 $col = 0+@footer;
138 push @footer, "sum($col)";
139 print STDERR "OK\n";
140
141 print STDERR "h: ", join(':',@header), "\n" if $debug;
142 print STDERR "b: ", join(':',@body), "\n" if $debug;
143 print STDERR "f: ", join(':',@footer), "\n" if $debug;
144
145 print STDERR "Filling in results... ";
146 @table = ();
147 foreach $u (keys %users) {
148         $row = [];
149         foreach my $c (@body) {
150                 $c =~ s/\$(\d+)/\$\$row[$1]/g;
151                 $x = eval $c;
152                 push @$row, (defined $x ? $x : '-');
153         }
154         print STDERR "row: ", join(':',@$row), "\n" if $debug;
155         push @table, $row;
156 }
157 print STDERR "OK\n";
158
159 print STDERR "Sorting... ";
160 $sortcol = @{$table[0]} - 1;
161 $namecol = 2;
162 @table = sort {
163         my $p, $an, $bn;
164         $p = $$b[$sortcol] <=> $$a[$sortcol];
165         ($an = $$a[$namecol]) =~ s/(\S+)\s+(\S+)/$2 $1/;
166         ($bn = $$b[$namecol]) =~ s/(\S+)\s+(\S+)/$2 $1/;
167         $p ? $p : ($an cmp $bn);
168 } @table;
169 $i=0;
170 while ($i < @table) {
171         $j = $i;
172         while ($i < @table && ${$table[$i]}[$sortcol] == ${$table[$j]}[$sortcol]) {
173                 $i++;
174         }
175         if ($i == $j+1) {
176                 ${table[$j]}[0] = "$i.";
177         } else {
178                 ${table[$j]}[0] = $j+1 . ".-" . $i . ".";
179                 $j++;
180                 while ($j < $i) { ${table[$j++]}[0] = ""; };
181         }
182 }
183 print STDERR "OK\n";
184
185 print STDERR "Attaching headers and footers... ";
186 sub sum { my $col=shift @_; my $t=0; foreach my $z (0..@table-1) { $t += ${$table[$z]}[$col]; } $t; }
187 map { $_ = eval $_; } @footer;
188 push @table, \@footer;
189 unshift @table, \@header;
190 print STDERR "OK\n";
191
192 if ($debug) {
193         foreach $r (@table) { print join(':',@$r), "\n"; }
194 } elsif ($html) {
195         print '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html40/strict.dtd">', "\n";
196         print "<HTML><HEAD><TITLE>Rank list</TITLE></HEAD><BODY>\n";
197         print "<H1>Rank list</H1>\n";
198
199         my @perm;
200         &printHtmlHeader(\@perm);
201         print "<tbody>";
202         
203         foreach $r (@table[1..($#table - 1)]) {
204                 &printHtmlRow(@{$r}[@perm]);
205         }
206
207         print "<tbody>";
208         &printHtmlRow(@{$table[$#table]}[@perm]);
209
210         print "</TABLE>\n";
211         if ($detail) {
212                 print "<H2>Error codes</H2><UL>\n";
213                 foreach $r (sort keys %error_codes) { print "<LI>$r: $error_codes{$r}\n"; }
214                 print "</UL>\n";
215         }
216         print "</BODY></HTML>\n";
217 } elsif ($tex) {
218         print "\\error{TeX output not supported yet!}\n";
219 } else {
220         foreach $r (@table) { print join("\t",@$r), "\n"; }
221         print "\n";
222         foreach $r (sort keys %error_codes) { print "$r: $error_codes{$r}\n"; }
223 }
224
225
226 sub printHtmlRow {
227         print "<TR>", join('',map {
228                 if ($hdr) { $_ = "<TH>$_"; }
229                 else { $_ = "<TD align=" . (/^[0-9A-Z-]+$/ ? "right" : "left") . (length($_) > 14 ? " width=150" : "") . ">$_"; }
230         } @_), "\n";
231 }
232
233
234 sub printHtmlHeader {
235
236   my ($perm) = @_;
237
238    my $colspec = "<colgroup span=3>";
239    my $hdr1;
240    my $hdr2;
241
242    @$perm = (0, 1, 2);
243    my $p = 3;
244
245    if ($detail) {
246      $hdr1 = "<th rowspan=2>Rank<th rowspan=2>User<th rowspan=2>Name";
247      $extras and $p++ and push @$perm, 3 and $hdr1.="<th rowspan=2>Extra" and $colspec.="<colgroup span=1>";         ##Extra hack
248      for my $task (@tasks) {
249
250         my $nSub = scalar(keys %{$known_tests{$task}});
251
252         $p++;
253         map { push @$perm, $p++ } (1..$nSub);
254         push @$perm, $p - $nSub - 1;
255         
256         $colspec .= "<colgroup span='" . $nSub . "'>\n";
257         $colspec .= "<colgroup span='1'>\n";
258         $hdr1 .= "<th colspan='" . ($nSub + 1) . "' style='border-bottom:1px solid black;'>$task";
259         $hdr2 .= join("", map { "<th>$_" } sort {$a <=> $b} keys %{$known_tests{$task}});
260         $hdr2 .= "<th>Total";
261      }
262    
263      $hdr1 .= "<th rowspan='2'>Total";
264      
265    } else {  ## no detail
266    
267      $hdr1 = "<th>Rank<th>User<th>Name";
268      $extras and $p++ and push @$perm, 3 and $hdr1.="<th>Extra" and $colspec.="<colgroup span=1>";                  ##Extra hack
269
270      for my $task (@tasks) {
271         push @$perm, $p++;
272         $hdr1 .= "<th>$task";
273      }
274      $hdr1 .= "<th>Total";
275      $colspec .= "<colgroup span='" . scalar (@tasks) . "'>";
276    }
277
278    push @$perm, $p++;
279    
280    print "<TABLE rules=groups frame=all border='1' cellpadding='2'>\n";
281    print "$colspec<colgroup span='1'>\n";
282    print "<tr>$hdr1</tr>\n";
283    print "<tr>$hdr2</tr>\n" if $detail;
284   
285 }