55use App \Entity \Contest ;
66use App \Entity \ContestProblem ;
77use App \Entity \Problem ;
8+ use App \Entity \RankCache ;
89use App \Entity \ScoreCache ;
910use App \Entity \Team ;
1011use App \Entity \TeamAffiliation ;
1415use App \Service \ScoreboardService ;
1516use App \Utils \FreezeData ;
1617use App \Utils \Scoreboard \Scoreboard ;
18+ use App \Utils \Utils ;
1719use Symfony \Component \Console \Attribute \AsCommand ;
1820use Symfony \Component \Console \Command \Command ;
1921use 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