Annotation of processmail/createtable.pl, revision 3.1

1.1       boris       1: #!/usr/local/bin/perl
3.0       boris       2: #$Id: createtable.pl,v 1.3 2005/02/16 22:20:08 boris Exp $
1.1       boris       3: #
                      4: #
                      5: #
                      6: # Исходные файлы и параметры
                      7: #
                      8: 
1.3       boris       9: use Getopt::Std; 
1.1       boris      10: 
1.3       boris      11: $usage = 
3.0       boris      12: "Usage: createtable.pl [-d] [-s|-m] [-t answers_file]  [-o results] \n";
1.1       boris      13: 
                     14: require 'parameters.pl';
                     15: require 'subroutines.pl';
                     16: 
3.0       boris      17: die $usage unless getopts('t:o:dsm');
1.1       boris      18: 
                     19: $DEBUG=$opt_d;
1.2       boris      20: $SHORT=$opt_s;
3.0       boris      21: $MEDIUM=$opt_m;
1.1       boris      22: 
                     23: my %teams;
                     24: my @answers;
                     25: my @ratings;
                     26: #
                     27: # Читаем старые результаты
                     28: #
1.3       boris      29: if ($opt_t) {
1.1       boris      30:     die "Cannot open $opt_t\n" unless open(INFILE,$opt_t);
1.3       boris      31: } else {
                     32:    *INFILE=*STDIN;
1.1       boris      33: }
1.3       boris      34:     
                     35: readhash(\@answers);
                     36: close(INFILE);
                     37: 
1.1       boris      38: 
                     39: #
1.3       boris      40: # Открываем файл для записи
1.1       boris      41: #
1.3       boris      42: if ($opt_o) { 
                     43:     die "Cannot open $opt_o\n" unless open(OUTFILE,">$opt_o");
                     44:     select OUTFILE;
1.1       boris      45: }
1.3       boris      46: 
                     47: # Находим максимальный вопрос
                     48: $MAXQUEST=1;
                     49: for (my $i=1; $i<=$ROUNDS; $i++) {
                     50:     if ($MAXQUEST<$MAXQUEST[$i]) {
                     51:        $MAXQUEST=$MAXQUEST[$i];
                     52:     }
1.1       boris      53: }
1.3       boris      54: 
                     55: 
                     56: #
                     57: # Таблица подводится отдельно по каждому раунду
1.1       boris      58: #
3.1     ! boris      59: my @nopoint_questions;                         # Здесь будут внезачётные вопросы
        !            60: my @unknowns;                          # Сюда запомним все '?'
1.3       boris      61: for (my $r=1; $r<=$ROUNDS; $r++) {
                     62:     if ($DEBUG) {
                     63:        print STDERR "Раунд $r\n";
                     64:     }
                     65: 
3.1     ! boris      66:     #
        !            67:     #  Читаем ответы в данном раунде
        !            68:     #
3.0       boris      69:     foreach my $file ( @{$FILES[$r]} ) {
1.3       boris      70:        open (INFILE, $file);
                     71:        readmail(\%teams);
                     72:        collect_answers(\%teams,\@answers);
                     73:        close (INFILE);
                     74:     }
                     75: 
3.1     ! boris      76:     #
        !            77:     # Дополняем (добавляем к имеющемуся!) список вопросов, идущих вне зачёта
        !            78:     # в данном туре.  Для них проставляются плюсы и минусы, но они не входят
        !            79:     # в суммарный результат и рейтинг команд.
        !            80:     #
3.0       boris      81:     foreach my $num ( @{$NOCOUNT[$r]} )
                     82:     {
                     83:        # Если номер не начинается с минуса, то включить его в список
                     84:        # внезачётных, иначе - исключить.  Проверяем регэкспом, а не на
                     85:        # "> 0", чтобы можно было использовать и "-0".
                     86:        if ($num =~ /^\d+/) {
                     87:            push @nopoint_questions, $num; 
                     88:        } else {
                     89:             @nopoint_questions = grep( $_ != -$num, @nopoint_questions );
                     90:        }
                     91:     }
                     92:     # И удаляем возможные дубликаты, чтобы всё было красиво.
                     93:     my %seen;
                     94:     @nopoint_questions = grep( !$seen{$_}++, @nopoint_questions );
                     95: 
3.1     ! boris      96:     #
        !            97:     # Подсчитываем рейтинги вопросов
        !            98:     #
1.3       boris      99:     rate_questions(\%teams,\@answers,\@ratings,$r);
3.1     ! boris     100: 
        !           101:     #
        !           102:     # Вычисляем число ответов и рейтинги команд
        !           103:     #
3.0       boris     104:     find_scores(\%teams,\@answers,\@ratings,$r,0.01,\@nopoint_questions);
3.1     ! boris     105: 
        !           106:     #
        !           107:     # Ну а теперь печатаем саму таблицу...
        !           108:     #
        !           109:     #
        !           110:     # Печатаем заголовок
        !           111:     #
3.0       boris     112:     # Столько столбцов до пробела в среднем формате ("++-++ +-+-+ -+--+")
                    113:     my $COL=5;
                    114: 
1.3       boris     115:     print "ЗАЧЁТ  $NAME[$r]\n";
3.0       boris     116:     if ( @nopoint_questions ) {
                    117:        # Есть незачётные вопросы - печатаем их список.
                    118:        print  "Вне зачёта вопрос" . (scalar(@nopoint_questions)>1 ? "ы" : "") 
                    119:                . ": " . join(", ", sort {$a<=>$b} @nopoint_questions) . "\n";
                    120:     }
                    121: 
1.3       boris     122:     printf "%5s ", "N";
                    123:     for ($i=$MINQUEST[$r];$i<=$MAXQUEST[$r];$i++)
                    124:     {
                    125:        if ($SHORT) {
                    126:            printf("%1d",$i%10);
3.0       boris     127:        } elsif ($MEDIUM) {
                    128:             if ($i == int($i/$COL)*$COL || $i==$MAXQUEST[$r]) {
                    129:                printf "%-3d", $i;
                    130:             } else {
                    131:                printf "%s", ".";
                    132:             }
1.3       boris     133:        } else {
                    134:            printf "%3d",$i;
                    135:        }
1.2       boris     136:     }
1.3       boris     137:     printf "%6s","О";
                    138:     printf "%4s","Р";
                    139:     printf " КОМАНДА";
                    140:     print "\n";
3.1     ! boris     141: 
        !           142:     #
        !           143:     # Печатаем команды построчно
        !           144:     #
1.3       boris     145:     foreach $team (sort 
                    146:                   {
                    147:                       $teams{$b}->{score} <=> $teams{$a}->{score}
                    148:                       or
                    149:                           $teams{$b}->{rating} <=> $teams{$a}->{rating}
                    150:                   } keys %teams
                    151:                   )
1.1       boris     152:     {
1.3       boris     153:        printf "%5d ",$teams{$team}->{regnum};
                    154:        for ($i=$MINQUEST[$r];$i<=$MAXQUEST[$r];$i++)
                    155:        {
                    156:            my $answer = $teams{$team}->{answers}[$i];
                    157:            my $score = $answers[$i]->{$answer}->{score};
                    158:            $score = '-' unless $score;
3.1     ! boris     159: 
        !           160:            # Особо пометим взятые внезачётные вопросы.
        !           161:            if ( $score eq '+' && grep($_==$i, @nopoint_questions) ) {
        !           162:                $score = 'X';
        !           163:            }
        !           164: 
        !           165:            # И запомним, если вопрос не взят и не не взят ;-).
        !           166:            if ( $score eq '?' ) {
        !           167:                my $unk = {
        !           168:                            question => $i,
        !           169:                            score => $score,
        !           170:                            team  => $team,
        !           171:                            regnum => $teams{$team}->{regnum},
        !           172:                            round => $r,
        !           173:                          };
        !           174:                push( @unknowns, $unk );
        !           175:            }
        !           176: 
        !           177:            # Ну наконец-то!  Печатаем.
1.3       boris     178:            if ($SHORT) {
                    179:                printf "%1s",$score;
3.0       boris     180:            } elsif ($MEDIUM) {
                    181:                printf "%1s",$score;
                    182:                print "  " if ($i == int($i/$COL)*$COL || $i==$MAXQUEST[$r]);
1.3       boris     183:            } else {
                    184:                printf "%3s", $score;
                    185:            }
1.2       boris     186:        }
1.3       boris     187:        printf "%6.2f",$teams{$team}->{score};
                    188:        printf "%4s",$teams{$team}->{rating};
                    189:        print " $team";
                    190:        print "\n";
1.1       boris     191:     }
3.1     ! boris     192: 
        !           193:     #
        !           194:     # Печатаем рейтинги вопросов - длинный или короткий варианты.
        !           195:     #
3.0       boris     196:     if ($SHORT || $MEDIUM) {
3.1     ! boris     197:         my $nline = 24;                        # По $nline рейтингов в строке
3.0       boris     198:        print "\nРейтинг\n";
                    199:        for ($j=0; $j<$MAXQUEST[$r]/$nline; $j++) {
                    200:            my $max = $j*$nline + $nline;
1.3       boris     201:            if ($max>$MAXQUEST[$r]) {
                    202:                $max=$MAXQUEST[$r];
                    203:            }
3.0       boris     204:            for ($i=$j*$nline+1; $i<=$max; $i++){
1.3       boris     205:                printf("%3s",$i);
                    206:            }
                    207:            printf "\n";
3.0       boris     208:            for ($i=$j*$nline+1; $i<=$max; $i++){
1.3       boris     209:                printf("%3s",$ratings[$i]);
                    210:            }
                    211:            printf "\n";
1.2       boris     212:        }
1.3       boris     213:     } else {
3.0       boris     214:        # Длинный вариант - под каждым вопросом.
1.3       boris     215:        printf "%5s ", "Р";
3.0       boris     216:        for ($i=$MINQUEST[$r]; $i<=$MAXQUEST[$r]; $i++)
1.3       boris     217:        {
                    218:            printf "%3s", $ratings[$i];
1.2       boris     219:        }
1.3       boris     220:        print "\n";
1.2       boris     221:     }
                    222:     print "\n";
1.1       boris     223: }
3.1     ! boris     224: 
        !           225: 
        !           226: # Печатаем предупреждение если есть неясные ответы.
        !           227: if ( @unknowns ) {
        !           228:     print STDERR "ВНИМАНИЕ!  Не всем ответам проставлены '+' и '-':\n";
        !           229:     foreach my $unk ( @unknowns ) {
        !           230:        print STDERR "\tКоманда $unk->{team} ($unk->{regnum}), "
        !           231:                . "вопрос $unk->{question} ($NAME[$unk->{round}]): "
        !           232:                . "$unk->{score}\n";
        !           233:     }
        !           234: }
        !           235: # На всякий случай проверяем на наличие команд с дублирующимися номерами.
        !           236: check_dup_numbers(\%teams);

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>