Skip to content

Commit 2de7534

Browse files
nickygerritsenvmcj
authored andcommitted
Calculate rank cache when merging scoreboards
This also fixes a PHPStan error
1 parent 60006a0 commit 2de7534

File tree

1 file changed

+60
-4
lines changed

1 file changed

+60
-4
lines changed

webapp/src/Command/ScoreboardMergeCommand.php

Lines changed: 60 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use App\Entity\Contest;
66
use App\Entity\ContestProblem;
77
use App\Entity\Problem;
8+
use App\Entity\RankCache;
89
use App\Entity\ScoreCache;
910
use App\Entity\Team;
1011
use App\Entity\TeamAffiliation;
@@ -14,6 +15,7 @@
1415
use App\Service\ScoreboardService;
1516
use App\Utils\FreezeData;
1617
use App\Utils\Scoreboard\Scoreboard;
18+
use App\Utils\Utils;
1719
use Symfony\Component\Console\Attribute\AsCommand;
1820
use Symfony\Component\Console\Command\Command;
1921
use Symfony\Component\Console\Input\InputArgument;
@@ -131,6 +133,11 @@ protected function execute(InputInterface $input, OutputInterface $output): int
131133
$problems = [];
132134
$problemNameToIdMap = [];
133135
$scoreCache = [];
136+
/** @var RankCache[] $rankCache */
137+
$rankCache = [];
138+
$penaltyTime = (int)$this->config->get('penalty_time');
139+
$scoreIsInSeconds = (bool)$this->config->get('score_in_seconds');
140+
$timeOfLastCorrect = [];
134141
$affiliations = [];
135142
$firstSolve = [];
136143
$contest = (new Contest())
@@ -261,6 +268,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
261268
$id = count($problems);
262269
$problemObj = (new Problem())
263270
->setProbid($id)
271+
->setExternalid((string)$id)
264272
->setName($name);
265273
$contestProblemObj = (new ContestProblem())
266274
->setProblem($problemObj)
@@ -280,10 +288,8 @@ protected function execute(InputInterface $input, OutputInterface $output): int
280288
$scoreCacheObj
281289
->setSolveTimePublic($problem['time'] * 60)
282290
->setSolveTimeRestricted($problem['time'] * 60);
283-
if (
284-
$firstSolve[$name] === null or
285-
$problem['time'] * 60 < $firstSolve[$name]
286-
) {
291+
if ($firstSolve[$name] === null ||
292+
$problem['time'] * 60 < $firstSolve[$name]) {
287293
$firstSolve[$name] = $problem['time'] * 60;
288294
}
289295
}
@@ -302,14 +308,64 @@ protected function execute(InputInterface $input, OutputInterface $output): int
302308
if ($scoreCacheObj->getSolveTimeRestricted() == $firstSolve[$scoreCacheObj->getProblem()->getName()]) {
303309
$scoreCacheObj->setIsFirstToSolve(true);
304310
}
311+
312+
$teamId = $scoreCacheObj->getTeam()->getTeamid();
313+
if (isset($rankCache[$teamId])) {
314+
$rankCacheObj = $rankCache[$teamId];
315+
} else {
316+
$rankCacheObj = (new RankCache())
317+
->setTeam($scoreCacheObj->getTeam());
318+
$rankCache[$teamId] = $rankCacheObj;
319+
}
320+
321+
$problem = $problems[$scoreCacheObj->getProblem()->getProbid()];
322+
if ($scoreCacheObj->getIsCorrectRestricted()) {
323+
$rankCacheObj->setPointsRestricted($rankCacheObj->getPointsRestricted() + $problem->getPoints());
324+
$solveTime = Utils::scoretime(
325+
(float)$scoreCacheObj->getSolvetimeRestricted(),
326+
$scoreIsInSeconds
327+
);
328+
$penalty = Utils::calcPenaltyTime($scoreCacheObj->getIsCorrectRestricted(),
329+
$scoreCacheObj->getSubmissionsRestricted(),
330+
$penaltyTime, $scoreIsInSeconds);
331+
$rankCacheObj->setTotaltimeRestricted($rankCacheObj->getTotaltimeRestricted() + $solveTime + $penalty);
332+
$rankCacheObj->setTotalruntimeRestricted($rankCacheObj->getTotalruntimeRestricted() + $scoreCacheObj->getRuntimeRestricted());
333+
$timeOfLastCorrect[$teamId] = max(
334+
$timeOfLastCorrect[$teamId] ?? 0,
335+
Utils::scoretime(
336+
(float)$scoreCacheObj->getSolvetimeRestricted(),
337+
$scoreIsInSeconds
338+
),
339+
);
340+
}
305341
}
306342

343+
foreach ($rankCache as $rankCacheObj) {
344+
$teamId = $rankCacheObj->getTeam()->getTeamid();
345+
$rankCacheObj->setSortKeyRestricted(ScoreboardService::getICPCScoreKey(
346+
$rankCacheObj->getPointsRestricted(),
347+
$rankCacheObj->getTotaltimeRestricted(), $timeOfLastCorrect[$teamId] ?? 0
348+
));
349+
}
350+
351+
usort($teams, function (Team $a, Team $b) use ($rankCache) {
352+
$rankCacheA = $rankCache[$a->getTeamid()];
353+
$rankCacheB = $rankCache[$b->getTeamid()];
354+
$rankCacheSort = $rankCacheB->getSortKeyRestricted() <=> $rankCacheA->getSortKeyRestricted();
355+
if ($rankCacheSort === 0) {
356+
return $a->getEffectiveName() <=> $b->getEffectiveName();
357+
}
358+
359+
return $rankCacheSort;
360+
});
361+
307362
$scoreboard = new Scoreboard(
308363
$contest,
309364
$teams,
310365
[$category],
311366
$problems,
312367
$scoreCache,
368+
array_values($rankCache),
313369
$freezeData,
314370
false,
315371
(int)$this->config->get('penalty_time'),

0 commit comments

Comments
 (0)