contest_list_sth => 'SELECT * FROM contest_entry',
contest_entry_sth => 'SELECT * FROM contest_entry WHERE id = ?',
- contest_problems_sth => 'SELECT problem FROM contest_problems JOIN problems pb ON problem=pb.id WHERE contest = ? ORDER BY pb.value',
contest_has_problem_sth => 'SELECT EXISTS(SELECT 1 FROM contest_problems WHERE contest = ? AND problem = ?)',
opens_sth => 'SELECT problem,owner,time FROM opens WHERE contest = ?',
problem_entry_sth => 'SELECT ' . (join ',', @{PROBLEM_PUBLIC_COLUMNS()}, 'statement', 'solution') . ' FROM problems WHERE id = ?',
limits_sth => 'SELECT format,timeout FROM limits WHERE problem = ?',
- problem_values_sth => 'SELECT id,value FROM problems',
job_entry_sth => 'SELECT * FROM job_entry WHERE id = ?',
scalar $db->insert('jobs', \%args, {returning => 'id'})->list
}
-sub calc_score {
+sub _calc_score {
my ($mxscore, $time, $tries, $totaltime) = @_;
my $score = $mxscore;
$time = 300 if $time > $totaltime; # uncoverable branch true does not happen anymore (only possible if opens are broken)
sub standings {
my ($ct) = @_;
+ my @problems = sort { $a->{value} <=> $b->{value} } @{problem_list contest => $ct};
+ my %values = map { $_->{id} => $_->{value} } @problems;
$ct = contest_entry $ct;
- my @problems = query(contest_problems_sth => $ct->{id})->flat;
- my $pblist = problem_list;
- my %values = query('problem_values_sth')->map;
-
my (%scores, %tries, %opens);
my $opens = query(opens_sth => $ct->{id});
while ($opens->into(my ($problem, $owner, $time))) {
my $value = $values{$job->{problem}};
my $factor = $job->{result} ? 0 : 1;
$factor = $1 / 100 if $job->{result_text} =~ /^(\d+ )/s;
- $scores{$job->{owner}}{$job->{problem}} = int ($factor * calc_score ($value, $time, $tries{$job->{owner}}{$job->{problem}}++, $ct->{stop} - $ct->{start}));
+ $scores{$job->{owner}}{$job->{problem}} = int ($factor * _calc_score ($value, $time, $tries{$job->{owner}}{$job->{problem}}++, $ct->{stop} - $ct->{start}));
}
my @st = sort { $b->{score} <=> $a->{score} or $a->{user} cmp $b->{user} } map { ## no critic (ProhibitReverseSortBlock)
user => $user,
user_name => object_name(users => $user),
score => sum (values %{$scores{$user}}),
- scores => [map { $scores{$user}{$_} // '-'} @problems],
+ scores => [map { $scores{$user}{$_->{id}} // '-'} @problems],
}
} keys %scores;
$st[0]->{rank} = 1 if @st;
$st[$_]->{rank} = $st[$_ - 1]->{rank} + ($st[$_]->{score} < $st[$_ - 1]->{score}) for 1 .. $#st;
- +{
- st => \@st,
- problems => [map { [ $_, object_name(problems => $_)] } @problems],
- }
+
+ \@st
}
sub update_status {
my @contest_statuses = map {
my $ct = $_;
- map { [$ct, $_->{user}, $_->{score}, $_->{rank}] } @{standings($ct)->{st}}
+ map { [$ct, $_->{user}, $_->{score}, $_->{rank}] } @{standings $ct}
} $db->select('contests', 'id')->flat;
$db->begin;
ok !defined $x->{result}, 'job_entry 7 has NULL result';
$x = standings 'fc';
-is_deeply $x, {
- problems => [[fca => 'FC problem A']],
- st => [
- {rank => 1, user => 'MGV', user_name => undef, score => 50, scores => [50]},
- {rank => 2, user => 'nobody', user_name => undef, score => 40, scores => [40]},
- ]
-}, 'standings fc';
+is_deeply $x, [
+ {rank => 1, user => 'MGV', user_name => undef, score => 50, scores => [50]},
+ {rank => 2, user => 'nobody', user_name => undef, score => 40, scores => [40]},
+], 'standings fc';