5
5
use App \Entity \Contest ;
6
6
use App \Entity \ContestProblem ;
7
7
use App \Entity \Problem ;
8
+ use App \Entity \RankCache ;
8
9
use App \Entity \ScoreCache ;
9
10
use App \Entity \Team ;
10
11
use App \Entity \TeamAffiliation ;
14
15
use App \Service \ScoreboardService ;
15
16
use App \Utils \FreezeData ;
16
17
use App \Utils \Scoreboard \Scoreboard ;
18
+ use App \Utils \Utils ;
17
19
use Symfony \Component \Console \Attribute \AsCommand ;
18
20
use Symfony \Component \Console \Command \Command ;
19
21
use Symfony \Component \Console \Input \InputArgument ;
@@ -131,6 +133,11 @@ protected function execute(InputInterface $input, OutputInterface $output): int
131
133
$ problems = [];
132
134
$ problemNameToIdMap = [];
133
135
$ 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 = [];
134
141
$ affiliations = [];
135
142
$ firstSolve = [];
136
143
$ contest = (new Contest ())
@@ -261,6 +268,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
261
268
$ id = count ($ problems );
262
269
$ problemObj = (new Problem ())
263
270
->setProbid ($ id )
271
+ ->setExternalid ((string )$ id )
264
272
->setName ($ name );
265
273
$ contestProblemObj = (new ContestProblem ())
266
274
->setProblem ($ problemObj )
@@ -280,10 +288,8 @@ protected function execute(InputInterface $input, OutputInterface $output): int
280
288
$ scoreCacheObj
281
289
->setSolveTimePublic ($ problem ['time ' ] * 60 )
282
290
->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 ]) {
287
293
$ firstSolve [$ name ] = $ problem ['time ' ] * 60 ;
288
294
}
289
295
}
@@ -302,14 +308,64 @@ protected function execute(InputInterface $input, OutputInterface $output): int
302
308
if ($ scoreCacheObj ->getSolveTimeRestricted () == $ firstSolve [$ scoreCacheObj ->getProblem ()->getName ()]) {
303
309
$ scoreCacheObj ->setIsFirstToSolve (true );
304
310
}
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
+ }
305
341
}
306
342
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
+
307
362
$ scoreboard = new Scoreboard (
308
363
$ contest ,
309
364
$ teams ,
310
365
[$ category ],
311
366
$ problems ,
312
367
$ scoreCache ,
368
+ array_values ($ rankCache ),
313
369
$ freezeData ,
314
370
false ,
315
371
(int )$ this ->config ->get ('penalty_time ' ),
0 commit comments