--- processmail/subroutines.pl 2005/02/15 19:27:51 1.4 +++ processmail/subroutines.pl 2013/10/30 20:29:22 3.4 @@ -1,7 +1,7 @@ # В этот файл собраны процедуры, общие для всей системы # работы с ответами. # -#$Id: subroutines.pl,v 1.4 2005/02/15 19:27:51 boris Exp $ +#$Id: subroutines.pl,v 3.4 2013/10/30 20:29:22 boris Exp $ # sub readhash { @@ -17,7 +17,7 @@ sub readhash { print STDERR "\#$number. Score: $score\n",$answer; } - if ($answer ne "" && $number >0) + if ($answer ne "" && $number >= 0) { $$answers[$number]->{$answer}->{score} = $score; %{$$answers[$number]->{$answer}->{teams}} = (); @@ -33,7 +33,7 @@ sub readhash } if (/^\s*\*\*\*\s*$/) { - if ($answer ne "" && $number >0) + if ($answer ne "" && $number >= 0) { $$answers[$number]->{$answer}->{score} = $score; } @@ -73,8 +73,8 @@ sub readmail $$table{$team}->{'numletters'}++; if ($$table{$team}->{regnum} != $2) { - print STDERR "Warning: Team $team uses registration nos. ", - $$table{$team}->{regnum}, " and $2!\n"; + print STDERR "Warning: Team $team uses registration numbers ", + "'" . $$table{$team}->{regnum} . "'", " and '$2'!\n"; } next; } @@ -112,7 +112,7 @@ sub readmail # sub canonize_answer { - s/^\s*(.*)\s*$/ $1/; + s/^\s*(.*?)\s*$/ $1/; if (/^\s*$/) { return ""; @@ -129,7 +129,7 @@ sub canonize_answer sub collect_answers { my ($teams,$answers) = @_; - for ($i=1;$i<=$MAXQUEST;$i++) + for ($i=$MINQUEST;$i<=$MAXQUEST;$i++) { foreach $team (keys %$teams) { @@ -176,6 +176,7 @@ sub dumphash } return 1; } + # # Сбрасываем ответы на вопрос $number с оценкой $symbol # в формате, пригодном для собрания сочинений @@ -215,9 +216,9 @@ sub anondump # sub rate_questions { - my($teams,$answers,$ratings) = @_; + my($teams,$answers,$ratings,$round) = @_; my $numteams = scalar keys %$teams; - for ($i=1;$i<=$MAXQUEST;$i++) + for ($i=$MINQUEST[$round];$i<=$MAXQUEST[$round];$i++) { $$ratings[$i]=$numteams+1; foreach $answer (keys %{$$answers[$i]}) @@ -225,25 +226,26 @@ sub rate_questions if ($$answers[$i]->{$answer}{score} eq '+') { $$ratings[$i] -= - scalar keys %{$answers->[$i]->{$answer}->{teams}} ; + scalar keys %{$answers->[$i]->{$answer}->{teams}} ; + if ($DEBUG) { + print STDERR "Частота ответа $answer", + scalar keys %{$answers->[$i]->{$answer}->{teams}}, + "\n"; + } } } } - if ($DEBUG) - { - for ($i=1;$i<=$MAXQUEST;$i++) - { - print STDERR "Вопрос $i, Рейтинг: ", $$ratings[$i], "\n"; - } - } } # # Подсчитываем рейтинги команд +# @{$nopoint_questions} - список номеров вопросов, идущих вне зачёта. +# Для них проставляются плюсы/минусы, но они не учитываются в подсчёте +# очков и рейтингов команд. # sub find_scores { - my ($teams,$answers,$ratings,$factor) = @_; + my ($teams,$answers,$ratings,$round,$factor,$nopoint_questions) = @_; foreach $team (keys %$teams) { if (!defined($factor)) { @@ -251,11 +253,14 @@ sub find_scores } $$teams{$team}->{score} *=$factor; $$teams{$team}->{rating} = 0; - for ($i=1;$i<=$MAXQUEST;$i++) + for ($i=$MINQUEST[$round];$i<=$MAXQUEST[$round];$i++) { my $answer=$$teams{$team}->{answers}[$i]; if ($$answers[$i]->{$answer}{score} eq '+') { + next if ( @{$nopoint_questions} && + grep($_==$i, @{$nopoint_questions}) + ); $$teams{$team}->{score} += 1; $$teams{$team}->{rating} += $$ratings[$i]; @@ -272,18 +277,57 @@ sub find_scores } -1; - - - - - - - - +# +# Проверяем на наличие дублирующихся номеров у разных команд. +# +sub check_dup_numbers +{ + my ($teams) = @_; + my %seen; + # Имена команд, номера которых встречаются >1 раза. + # Массив uniq_compr_names содержит по одному имени на каждый повторяющийся + # номер (чуть позже мы найдём все имена, соответствующие каждому из + # этих номеров). + # '+0' - чтобы номера обрабатывались как числа (072 == 72). + my @uniq_compr_names = + grep( ++$seen{$teams->{$_}->{regnum}+0} > 1, keys %$teams ); + + # А теперь извлекаем номера из полученного списка. + my @dup_numbers = map {$teams->{$_}->{regnum}} @uniq_compr_names; + @dup_numbers = sort @dup_numbers; + + # И печатаем предупреждение. + if ( @dup_numbers ) { + print STDERR "\nВНИМАНИЕ! Одинаковые номера у нескольких команд:\n"; + foreach my $num ( @dup_numbers ) { + my @dup_names = grep($teams->{$_}->{regnum}+0 == $num+0, keys %$teams); + print STDERR "\tНомер $num: " . join(", ", @dup_names) . "\n"; + } + print STDERR "\n"; + } +} +# +# Считаем ответы на вопрос $number с оценкой $symbol +# (фактически, это anondump(), только без печати списка +# таких ответов). +# +sub countanswers +{ + my ($teams,$answers,$number,$symbol) = @_; + my $num=0; + foreach $answer (keys %{$answers->[$number]}) + { + if ($$answers[$number]->{$answer}{score} eq $symbol) + { + $num++; + } + } + return $num; +} +1;