version 1.2, 2002/02/04 16:23:23
|
version 3.4, 2013/10/30 19:28:30
|
Line 1
|
Line 1
|
#!/usr/local/bin/perl |
#!/usr/bin/perl |
#$Id$ |
#$Id$ |
# |
# |
# |
# |
Line 6
|
Line 6
|
# Исходные файлы и параметры |
# Исходные файлы и параметры |
# |
# |
|
|
use Getopt::Std; |
use Getopt::Std; |
|
|
$usage = 'createtable.pl $Revision$, $Date$'. "\n". |
$usage = |
"Usage: createtable.pl [-d] [-s] [-t answers_file] [-m mail_file] [-o results] \n"; |
"Usage: createtable.pl [-d] [-s|-m] [-t answers_file] [-o results] \n"; |
|
|
require 'parameters.pl'; |
require 'parameters.pl'; |
require 'subroutines.pl'; |
require 'subroutines.pl'; |
|
|
die $usage unless getopts('t:m:o:ds'); |
die $usage unless getopts('t:o:dsm'); |
|
|
$DEBUG=$opt_d; |
$DEBUG=$opt_d; |
$SHORT=$opt_s; |
$SHORT=$opt_s; |
|
$MEDIUM=$opt_m; |
|
|
|
# Находим максимальный и минимальный вопрос и слегка подстраховываемся. |
|
$MINQUEST=1e99; |
|
$MAXQUEST=-1; |
|
for (my $r=1; $r<=$ROUNDS; $r++) { |
|
if ($MINQUEST>$MINQUEST[$r]) { |
|
$MINQUEST=$MINQUEST[$r]; |
|
} |
|
if ($MAXQUEST<$MAXQUEST[$r]) { |
|
$MAXQUEST=$MAXQUEST[$r]; |
|
} |
|
} |
|
if ($MINQUEST < 0 || $MAXQUEST < 0) { |
|
die "Отрицательные номера вопросов не поддерживаются!\n"; |
|
} |
|
|
my %teams; |
my %teams; |
my @answers; |
my @answers; |
Line 25 my @ratings;
|
Line 41 my @ratings;
|
# |
# |
# Читаем старые результаты |
# Читаем старые результаты |
# |
# |
if ($opt_t) |
if ($opt_t) { |
{ |
|
die "Cannot open $opt_t\n" unless open(INFILE,$opt_t); |
die "Cannot open $opt_t\n" unless open(INFILE,$opt_t); |
readhash(\@answers); |
} else { |
close(INFILE); |
*INFILE=*STDIN; |
} |
|
|
|
# |
|
# Читаем ответы команд |
|
# |
|
if ($opt_m) |
|
{ |
|
die "Cannot open $opt_m\n" unless open(INFILE,$opt_m) |
|
} |
|
else |
|
{ |
|
*INFILE=*STDIN; |
|
} |
} |
readmail(\%teams); |
|
|
readhash(\@answers); |
close(INFILE); |
close(INFILE); |
|
|
|
|
# |
# |
# Чистим хэш %answers |
# Открываем файл для записи |
# |
|
collect_answers(\%teams,\@answers); |
|
# |
|
# Подсчитываем рейтинги вопросов |
|
# |
|
rate_questions(\%teams,\@answers,\@ratings); |
|
# |
|
# Вычисляем число ответов и рейтинги команд |
|
# |
|
find_scores(\%teams,\@answers,\@ratings); |
|
# |
|
# Ну а теперь печатаем саму таблицу... |
|
# |
# |
if ($opt_o) |
if ($opt_o) { |
{ |
|
die "Cannot open $opt_o\n" unless open(OUTFILE,">$opt_o"); |
die "Cannot open $opt_o\n" unless open(OUTFILE,">$opt_o"); |
select OUTFILE; |
select OUTFILE; |
} |
} |
|
|
# |
# |
# Печатаем заголовок |
# Таблица подводится отдельно по каждому раунду |
# |
# |
printf "%5s ", "N"; |
my @nopoint_questions; # Здесь будут внезачётные вопросы |
for ($i=1;$i<=$MAXQUEST;$i++) |
my @unknowns; # Сюда запомним все '?' |
{ |
for (my $r=1; $r<=$ROUNDS; $r++) { |
if ($SHORT) { |
if ($DEBUG) { |
printf("%1d",$i%10); |
print STDERR "Раунд $r\n"; |
} else { |
|
printf "%3d",$i; |
|
} |
} |
} |
|
printf "%3s","О"; |
# |
printf "%4s","Р"; |
# Удаляем старые рейтинги (Ivan A Derzhanski <iad58@mail.ru>) |
printf " КОМАНДА"; |
# |
print "\n"; |
for ($i=$MINQUEST;$i<=$MAXQUEST;$i++) { |
# |
foreach $answer (keys %{$answers[$i]}) { |
# Печатаем команды построчно |
%{$answers[$i]->{$answer}->{teams}} = (); |
# |
} |
foreach $team (sort |
} |
{ |
|
$teams{$b}->{score} <=> $teams{$a}->{score} |
# |
or |
# Читаем ответы в данном раунде |
$teams{$b}->{rating} <=> $teams{$a}->{rating} |
# |
} keys %teams |
foreach my $file ( @{$FILES[$r]} ) { |
) |
open (INFILE, $file); |
{ |
readmail(\%teams); |
printf "%5d ",$teams{$team}->{regnum}; |
collect_answers(\%teams,\@answers); |
for ($i=1;$i<=$MAXQUEST;$i++) |
close (INFILE); |
|
} |
|
|
|
# |
|
# Дополняем (добавляем к имеющемуся!) список вопросов, идущих вне зачёта |
|
# в данном туре. Для них проставляются плюсы и минусы, но они не входят |
|
# в суммарный результат и рейтинг команд. |
|
# |
|
foreach my $num ( @{$NOCOUNT[$r]} ) |
|
{ |
|
# Если номер не начинается с минуса, то включить его в список |
|
# внезачётных, иначе - исключить. Проверяем регэкспом, а не на |
|
# "> 0", чтобы можно было использовать и "-0". |
|
if ($num =~ /^\d+/) { |
|
push @nopoint_questions, $num; |
|
} else { |
|
@nopoint_questions = grep( $_ != -$num, @nopoint_questions ); |
|
} |
|
} |
|
# И удаляем возможные дубликаты, чтобы всё было красиво. |
|
my %seen; |
|
@nopoint_questions = grep( !$seen{$_}++, @nopoint_questions ); |
|
|
|
# |
|
# Подсчитываем рейтинги вопросов |
|
# |
|
rate_questions(\%teams,\@answers,\@ratings,$r); |
|
|
|
# |
|
# Вычисляем число ответов и рейтинги команд |
|
# |
|
find_scores(\%teams,\@answers,\@ratings,$r,0.01,\@nopoint_questions); |
|
|
|
# |
|
# Ну а теперь печатаем саму таблицу... |
|
# |
|
# |
|
# Печатаем заголовок |
|
# |
|
# Столько столбцов до пробела в среднем формате ("++-++ +-+-+ -+--+") |
|
my $COL=5; |
|
|
|
print "ЗАЧЁТ $NAME[$r]\n"; |
|
if ( @nopoint_questions ) { |
|
# Есть незачётные вопросы - печатаем их список. |
|
print "Вне зачёта вопрос" . (scalar(@nopoint_questions)>1 ? "ы" : "") |
|
. ": " . join(", ", sort {$a<=>$b} @nopoint_questions) . "\n"; |
|
} |
|
|
|
printf "%5s ", "N"; |
|
for ($i=$MINQUEST[$r];$i<=$MAXQUEST[$r];$i++) |
{ |
{ |
my $answer = $teams{$team}->{answers}[$i]; |
|
my $score = $answers[$i]->{$answer}->{score}; |
|
$score = '-' unless $score; |
|
if ($SHORT) { |
if ($SHORT) { |
printf "%1s",$score; |
printf("%1d",$i%10); |
|
} elsif ($MEDIUM) { |
|
if ($i == int($i/$COL)*$COL || $i==$MAXQUEST[$r]) { |
|
printf "%-3d", $i; |
|
} else { |
|
printf "%s", "."; |
|
} |
} else { |
} else { |
printf "%3s", $score; |
printf "%3d",$i; |
} |
} |
} |
} |
printf "%3s",$teams{$team}->{score}; |
printf "%6s","О"; |
printf "%4s",$teams{$team}->{rating}; |
printf "%4s","Р"; |
print " $team"; |
printf " КОМАНДА"; |
print "\n"; |
print "\n"; |
} |
|
# |
# |
# Печатаем последнюю строку таблицы |
# Печатаем команды построчно |
# в ней рейтинги вопросов |
# |
# |
foreach $team (sort |
if ($SHORT) { |
{ |
print "Рейтинг\n"; |
$teams{$b}->{score} <=> $teams{$a}->{score} |
for ($j=0;$j<$MAXQUEST/12;$j++) { |
or |
my $max=$j*12+12; |
$teams{$b}->{rating} <=> $teams{$a}->{rating} |
if ($max>$MAXQUEST) { |
} keys %teams |
$max=$MAXQUEST; |
) |
} |
{ |
for ($i=$j*12+1;$i<=$max;$i++){ |
printf "%5d ",$teams{$team}->{regnum}; |
printf("%3s",$i); |
for ($i=$MINQUEST[$r];$i<=$MAXQUEST[$r];$i++) |
} |
{ |
printf "\n"; |
my $answer = $teams{$team}->{answers}[$i]; |
for ($i=1+$j*12;$i<=$max;$i++){ |
my $score = $answers[$i]->{$answer}->{score}; |
printf("%3s",$ratings[$i]); |
$score = '-' unless $score; |
|
|
|
# Особо пометим взятые внезачётные вопросы. |
|
if ( $score eq '+' && grep($_==$i, @nopoint_questions) ) { |
|
$score = 'X'; |
|
} |
|
|
|
# И запомним, если вопрос не взят и не не взят ;-). |
|
if ( $score eq '?' ) { |
|
my $unk = { |
|
question => $i, |
|
score => $score, |
|
team => $team, |
|
regnum => $teams{$team}->{regnum}, |
|
round => $r, |
|
}; |
|
push( @unknowns, $unk ); |
|
} |
|
|
|
# Ну наконец-то! Печатаем. |
|
if ($SHORT) { |
|
printf "%1s",$score; |
|
} elsif ($MEDIUM) { |
|
printf "%1s",$score; |
|
print " " if ($i == int($i/$COL)*$COL || $i==$MAXQUEST[$r]); |
|
} else { |
|
printf "%3s", $score; |
|
} |
} |
} |
printf "\n"; |
printf "%6.2f",$teams{$team}->{score}; |
|
printf "%4s",$teams{$team}->{rating}; |
|
print " $team"; |
|
print "\n"; |
} |
} |
} else { |
|
printf "%5s ", "Р"; |
# |
for ($i=1; $i<=$MAXQUEST;$i++) |
# Печатаем рейтинги вопросов - длинный или короткий варианты. |
{ |
# |
printf "%3s", $ratings[$i]; |
if ($SHORT || $MEDIUM) { |
|
my $nline = 24; # По $nline рейтингов в строке |
|
print "\nРейтинг\n"; |
|
for ($j=0; $j<$MAXQUEST[$r]/$nline; $j++) { |
|
my $max = $j*$nline + $nline; |
|
if ($max>$MAXQUEST[$r]) { |
|
$max=$MAXQUEST[$r]; |
|
} |
|
for ($i=$MINQUEST[$r]+$j*$nline; $i<=$max; $i++){ |
|
printf("%3s",$i); |
|
} |
|
printf "\n"; |
|
for ($i=$MINQUEST[$r]+$j*$nline; $i<=$max; $i++){ |
|
printf("%3s",$ratings[$i]); |
|
} |
|
printf "\n"; |
|
} |
|
} else { |
|
# Длинный вариант - под каждым вопросом. |
|
printf "%5s ", "Р"; |
|
for ($i=$MINQUEST[$r]; $i<=$MAXQUEST[$r]; $i++) |
|
{ |
|
printf "%3s", $ratings[$i]; |
|
} |
|
print "\n"; |
} |
} |
print "\n"; |
print "\n"; |
|
print "\n"; # LG: One more for better readability |
|
} |
|
|
|
|
|
# Печатаем предупреждение если есть неясные ответы. |
|
if ( @unknowns ) { |
|
print STDERR "ВНИМАНИЕ! Не всем ответам проставлены '+' и '-':\n"; |
|
foreach my $unk ( @unknowns ) { |
|
print STDERR "\tКоманда $unk->{team} ($unk->{regnum}), " |
|
. "вопрос $unk->{question} ($NAME[$unk->{round}]): " |
|
. "$unk->{score}\n"; |
|
} |
} |
} |
|
# На всякий случай проверяем на наличие команд с дублирующимися номерами. |
|
check_dup_numbers(\%teams); |