Annotation of processmail/createtable.pl, revision 3.4

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

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