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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy