@xcpcio/core 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs ADDED
@@ -0,0 +1,716 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ const dayjs = require('dayjs');
6
+ const duration = require('dayjs/plugin/duration');
7
+ const utc = require('dayjs/plugin/utc');
8
+ const timezone = require('dayjs/plugin/timezone');
9
+ const advancedFormat = require('dayjs/plugin/advancedFormat');
10
+ const isSameOrBefore = require('dayjs/plugin/isSameOrBefore');
11
+ const isSameOrAfter = require('dayjs/plugin/isSameOrAfter');
12
+ const minMax = require('dayjs/plugin/minMax');
13
+ const relativeTime = require('dayjs/plugin/relativeTime');
14
+ const types = require('@xcpcio/types');
15
+ const _ = require('lodash');
16
+
17
+ function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e["default"] : e; }
18
+
19
+ const dayjs__default = /*#__PURE__*/_interopDefaultLegacy(dayjs);
20
+ const duration__default = /*#__PURE__*/_interopDefaultLegacy(duration);
21
+ const utc__default = /*#__PURE__*/_interopDefaultLegacy(utc);
22
+ const timezone__default = /*#__PURE__*/_interopDefaultLegacy(timezone);
23
+ const advancedFormat__default = /*#__PURE__*/_interopDefaultLegacy(advancedFormat);
24
+ const isSameOrBefore__default = /*#__PURE__*/_interopDefaultLegacy(isSameOrBefore);
25
+ const isSameOrAfter__default = /*#__PURE__*/_interopDefaultLegacy(isSameOrAfter);
26
+ const minMax__default = /*#__PURE__*/_interopDefaultLegacy(minMax);
27
+ const relativeTime__default = /*#__PURE__*/_interopDefaultLegacy(relativeTime);
28
+ const ___default = /*#__PURE__*/_interopDefaultLegacy(_);
29
+
30
+ dayjs__default.extend(duration__default);
31
+ dayjs__default.extend(utc__default);
32
+ dayjs__default.extend(timezone__default);
33
+ dayjs__default.extend(advancedFormat__default);
34
+ dayjs__default.extend(isSameOrBefore__default);
35
+ dayjs__default.extend(isSameOrAfter__default);
36
+ dayjs__default.extend(minMax__default);
37
+ dayjs__default.extend(relativeTime__default);
38
+ function createDayJS(time = void 0) {
39
+ if (time === void 0) {
40
+ return dayjs__default();
41
+ }
42
+ if (typeof time == "number" && String(time).length === 10) {
43
+ return dayjs__default.unix(time);
44
+ }
45
+ return dayjs__default(time);
46
+ }
47
+ function getTimestamp(time) {
48
+ if (typeof time === "number") {
49
+ return time;
50
+ }
51
+ return time.unix();
52
+ }
53
+ function getTimeDiff(seconds) {
54
+ const two = (a) => {
55
+ if (a < 10)
56
+ return "0" + a;
57
+ return String(a);
58
+ };
59
+ const h = Math.floor(seconds / 3600);
60
+ const m = Math.floor(seconds % 3600 / 60);
61
+ const s = seconds % 60;
62
+ return [two(h), two(m), two(s)].join(":");
63
+ }
64
+
65
+ class Problem {
66
+ constructor() {
67
+ this.id = "";
68
+ this.label = "";
69
+ this.name = "";
70
+ this.statistics = {
71
+ acceptedNum: 0,
72
+ rejectedNum: 0,
73
+ pendingNum: 0,
74
+ submittedNum: 0
75
+ };
76
+ }
77
+ }
78
+ function createProblem(problemJSON) {
79
+ const p = new Problem();
80
+ p.id = String(problemJSON.id);
81
+ p.label = problemJSON.label;
82
+ p.name = problemJSON.name ?? "";
83
+ p.timeLimit = problemJSON.time_limit;
84
+ p.memoryLimit = problemJSON.memory_limit;
85
+ p.balloonColor = problemJSON.balloon_color;
86
+ return p;
87
+ }
88
+ function createProblems(problemsJSON) {
89
+ return problemsJSON.map((pJSON) => {
90
+ const p = new Problem();
91
+ p.id = pJSON.id;
92
+ p.label = pJSON.label;
93
+ p.name = pJSON.name ?? "";
94
+ p.timeLimit = pJSON.time_limit;
95
+ p.memoryLimit = pJSON.memory_limit;
96
+ p.balloonColor = pJSON.balloon_color;
97
+ return p;
98
+ });
99
+ }
100
+ function createProblemsByProblemIds(problemIds, balloonColors) {
101
+ const problems = problemIds.map((label, index) => {
102
+ const p = new Problem();
103
+ p.id = String(index);
104
+ p.label = label;
105
+ return p;
106
+ });
107
+ if (balloonColors !== void 0 && balloonColors !== null) {
108
+ for (const index in balloonColors) {
109
+ problems[index].balloonColor = balloonColors[index];
110
+ }
111
+ }
112
+ return problems;
113
+ }
114
+ class TeamProblemStatistics {
115
+ constructor(options) {
116
+ this.isFirstSolved = options?.teamProblemStatistics?.isFirstSolved ?? false;
117
+ this.isSolved = options?.teamProblemStatistics?.isSolved ?? false;
118
+ this.solvedTimestamp = options?.teamProblemStatistics?.solvedTimestamp ?? 0;
119
+ this.isSubmitted = options?.teamProblemStatistics?.isSubmitted ?? false;
120
+ this.lastSubmitTimestamp = options?.teamProblemStatistics?.lastSubmitTimestamp ?? 0;
121
+ this.failedCount = options?.teamProblemStatistics?.failedCount ?? 0;
122
+ this.pendingCount = options?.teamProblemStatistics?.pendingCount ?? 0;
123
+ this.ignoreCount = options?.teamProblemStatistics?.ignoreCount ?? 0;
124
+ this.totalCount = options?.teamProblemStatistics?.totalCount ?? 0;
125
+ this.submissions = options?.teamProblemStatistics?.submissions ?? [];
126
+ this.problem = options?.teamProblemStatistics?.problem ?? new Problem();
127
+ this.contestPenalty = options?.teamProblemStatistics?.contestPenalty ?? 20 * 60;
128
+ }
129
+ get isAccepted() {
130
+ return this.isSolved;
131
+ }
132
+ get isWrongAnswer() {
133
+ return !this.isSolved && this.pendingCount === 0 && this.failedCount > 0;
134
+ }
135
+ get isPending() {
136
+ return !this.isSolved && this.pendingCount > 0;
137
+ }
138
+ get isUnSubmitted() {
139
+ return this.totalCount === 0;
140
+ }
141
+ get penalty() {
142
+ if (this.isSolved === false) {
143
+ return 0;
144
+ }
145
+ return Math.floor(this.solvedTimestamp / 60) * 60 + this.failedCount * this.contestPenalty;
146
+ }
147
+ }
148
+
149
+ class Contest {
150
+ constructor() {
151
+ this.name = "";
152
+ this.version = types.VERSION;
153
+ this.startTime = createDayJS();
154
+ this.endTime = createDayJS();
155
+ this.freezeTime = createDayJS();
156
+ this.totalDurationTimestamp = 0;
157
+ this.freezeDurationTimestamp = 0;
158
+ this.unFreezeDurationTimestamp = 0;
159
+ this.penalty = 20 * 60;
160
+ this.problems = [];
161
+ this.problemsMap = /* @__PURE__ */ new Map();
162
+ this.statusTimeDisplay = {
163
+ correct: true,
164
+ incorrect: true,
165
+ pending: true
166
+ };
167
+ }
168
+ getContestDuration(timeFormat = "HH:mm:ss") {
169
+ return dayjs__default.duration(this.endTime.diff(this.startTime)).format(timeFormat);
170
+ }
171
+ getContestState() {
172
+ const now = createDayJS();
173
+ if (now.isBefore(this.startTime)) {
174
+ return types.ContestState.PENDING;
175
+ }
176
+ if (now.isSameOrAfter(this.endTime)) {
177
+ return types.ContestState.FINISHED;
178
+ }
179
+ if (now.isSameOrAfter(this.freezeTime)) {
180
+ return types.ContestState.FROZEN;
181
+ }
182
+ return types.ContestState.RUNNING;
183
+ }
184
+ getContestPendingTime() {
185
+ let baseTime = createDayJS();
186
+ if (baseTime.isAfter(this.startTime)) {
187
+ baseTime = this.startTime;
188
+ }
189
+ return getTimeDiff(Math.floor(dayjs__default.duration(this.startTime.diff(baseTime)).asSeconds()));
190
+ }
191
+ getContestRemainingTime(endTime) {
192
+ let baseTime = dayjs__default();
193
+ if (baseTime.isAfter(endTime)) {
194
+ baseTime = endTime;
195
+ }
196
+ return getTimeDiff(Math.floor(dayjs__default.duration(endTime.diff(baseTime)).asSeconds()));
197
+ }
198
+ getContestElapsedTime() {
199
+ let baseTime = dayjs__default();
200
+ if (baseTime.isAfter(this.endTime)) {
201
+ baseTime = this.endTime;
202
+ }
203
+ return getTimeDiff(Math.floor(dayjs__default.duration(baseTime.diff(this.startTime)).asSeconds()));
204
+ }
205
+ getContestProgressRatio() {
206
+ const baseTime = dayjs__default();
207
+ if (this.startTime.isSameOrAfter(baseTime)) {
208
+ return 0;
209
+ }
210
+ if (this.endTime.isSameOrBefore(baseTime)) {
211
+ return 100;
212
+ }
213
+ const total = this.endTime.diff(this.startTime, "s");
214
+ const pass = baseTime.diff(this.startTime, "s");
215
+ return Math.round(pass * 100 / total);
216
+ }
217
+ }
218
+ function createContest(contestJSON) {
219
+ const c = new Contest();
220
+ c.name = contestJSON.contest_name;
221
+ c.startTime = createDayJS(contestJSON.start_time);
222
+ c.endTime = createDayJS(contestJSON.end_time);
223
+ c.totalDurationTimestamp = c.endTime.unix() - c.startTime.unix();
224
+ {
225
+ c.freezeTime = c.endTime;
226
+ c.freezeDurationTimestamp = 0;
227
+ if (contestJSON.frozen_time !== void 0 && contestJSON.frozen_time != null) {
228
+ const frozenTime = Number(contestJSON.frozen_time);
229
+ c.freezeTime = createDayJS(c.endTime.unix() - frozenTime);
230
+ c.freezeDurationTimestamp = frozenTime;
231
+ }
232
+ if (contestJSON.freeze_time !== void 0 && contestJSON.freeze_time !== null) {
233
+ c.freezeTime = createDayJS(contestJSON.freeze_time);
234
+ c.freezeDurationTimestamp = c.endTime.unix() - c.freezeTime.unix();
235
+ }
236
+ c.unFreezeDurationTimestamp = c.totalDurationTimestamp - c.freezeDurationTimestamp;
237
+ }
238
+ c.penalty = contestJSON.penalty;
239
+ {
240
+ if (contestJSON.problem_id !== void 0 && contestJSON.problem_id !== null) {
241
+ c.problems = createProblemsByProblemIds(contestJSON.problem_id, contestJSON.balloon_color);
242
+ }
243
+ if (contestJSON.problems !== void 0 && contestJSON.problems !== null) {
244
+ c.problems = createProblems(contestJSON.problems);
245
+ }
246
+ c.problemsMap = new Map(c.problems.map((p) => [p.id, p]));
247
+ }
248
+ if (contestJSON.status_time_display !== void 0 && contestJSON.status_time_display !== null) {
249
+ c.statusTimeDisplay = {
250
+ correct: Boolean(contestJSON.status_time_display.correct ?? false),
251
+ incorrect: Boolean(contestJSON.status_time_display.incorrect ?? false),
252
+ pending: Boolean(contestJSON.status_time_display.pending ?? false)
253
+ };
254
+ }
255
+ c.badge = contestJSON.badge;
256
+ c.medal = contestJSON.medal;
257
+ c.organization = contestJSON.organization;
258
+ c.group = contestJSON.group;
259
+ c.tag = contestJSON.tag;
260
+ c.banner = contestJSON.banner;
261
+ c.logo = contestJSON.logo;
262
+ c.boardLink = contestJSON.board_link;
263
+ return c;
264
+ }
265
+
266
+ function getImageSource(image) {
267
+ if (image?.url) {
268
+ return image.url;
269
+ }
270
+ if (image?.base64) {
271
+ return `data:image/${image.type};base64,${image.base64}`;
272
+ }
273
+ return "";
274
+ }
275
+
276
+ class Team {
277
+ constructor() {
278
+ this.id = "";
279
+ this.name = "";
280
+ this.organization = "";
281
+ this.group = [];
282
+ this.tag = [];
283
+ this.rank = 0;
284
+ this.solvedProblemNum = 0;
285
+ this.penalty = 0;
286
+ this.problemStatistics = [];
287
+ this.problemStatisticsMap = /* @__PURE__ */ new Map();
288
+ }
289
+ penaltyToMinute() {
290
+ return Math.floor(this.penalty / 60);
291
+ }
292
+ calcSolvedData() {
293
+ this.solvedProblemNum = 0;
294
+ this.penalty = 0;
295
+ for (const p of this.problemStatistics) {
296
+ if (p.isAccepted) {
297
+ this.solvedProblemNum++;
298
+ this.penalty += p.penalty;
299
+ }
300
+ }
301
+ }
302
+ static compare(lhs, rhs) {
303
+ if (lhs.solvedProblemNum !== rhs.solvedProblemNum) {
304
+ return rhs.solvedProblemNum - lhs.solvedProblemNum;
305
+ }
306
+ if (lhs.penalty !== rhs.penalty) {
307
+ return lhs.penalty - rhs.penalty;
308
+ }
309
+ if (lhs.name < rhs.name) {
310
+ return -1;
311
+ } else if (lhs.name > rhs.name) {
312
+ return 1;
313
+ }
314
+ return 0;
315
+ }
316
+ }
317
+ function createTeam(teamJSON) {
318
+ const t = new Team();
319
+ t.id = teamJSON.id ?? teamJSON.team_id ?? "";
320
+ t.name = teamJSON.name ?? teamJSON.team_name ?? "";
321
+ t.organization = teamJSON.organization ?? "";
322
+ t.group = teamJSON.group ?? [];
323
+ t.tag = teamJSON.group ?? [];
324
+ t.coach = teamJSON.coach;
325
+ t.members = teamJSON.members;
326
+ if (teamJSON.official === true) {
327
+ t.group.push("official");
328
+ }
329
+ if (teamJSON.unofficial === true) {
330
+ t.group.push("unofficial");
331
+ }
332
+ if (teamJSON.girl === true) {
333
+ t.group.push("girl");
334
+ }
335
+ t.group = [...new Set(t.group)];
336
+ t.group.sort();
337
+ return t;
338
+ }
339
+ function createTeams(teamsJSON) {
340
+ if (Array.isArray(teamsJSON)) {
341
+ return teamsJSON.map((t) => createTeam(t));
342
+ } else {
343
+ const teams = Object.entries(teamsJSON).map(
344
+ ([teamId, team]) => createTeam({ ...team, team_id: team.team_id ?? teamId })
345
+ );
346
+ return teams;
347
+ }
348
+ }
349
+
350
+ function stringToSubmissionStatus(status) {
351
+ status = status.toUpperCase().replace(" ", "_");
352
+ if (["OK", "AC", types.SubmissionStatus.ACCEPTED.toString()].includes(status)) {
353
+ return types.SubmissionStatus.ACCEPTED;
354
+ }
355
+ if ([types.SubmissionStatus.CORRECT.toString()].includes(status)) {
356
+ return types.SubmissionStatus.CORRECT;
357
+ }
358
+ if ([types.SubmissionStatus.PARTIALLY_CORRECT.toString()].includes(status)) {
359
+ return types.SubmissionStatus.PARTIALLY_CORRECT;
360
+ }
361
+ if (["WA", types.SubmissionStatus.WRONG_ANSWER.toString()].includes(status)) {
362
+ return types.SubmissionStatus.WRONG_ANSWER;
363
+ }
364
+ if (["RJ", "INCORRECT", types.SubmissionStatus.REJECTED.toString()].includes(status)) {
365
+ return types.SubmissionStatus.REJECTED;
366
+ }
367
+ if (["PD", types.SubmissionStatus.PENDING.toString()].includes(status)) {
368
+ return types.SubmissionStatus.PENDING;
369
+ }
370
+ if ([types.SubmissionStatus.WAITING.toString()].includes(status)) {
371
+ return types.SubmissionStatus.WAITING;
372
+ }
373
+ if ([types.SubmissionStatus.JUDGING.toString()].includes(status)) {
374
+ return types.SubmissionStatus.JUDGING;
375
+ }
376
+ if ([types.SubmissionStatus.FROZEN.toString()].includes(status)) {
377
+ return types.SubmissionStatus.FROZEN;
378
+ }
379
+ if (["CE", types.SubmissionStatus.COMPILE_ERROR.toString()].includes(status)) {
380
+ return types.SubmissionStatus.COMPILE_ERROR;
381
+ }
382
+ if (["PE", types.SubmissionStatus.PRESENTATION_ERROR.toString()].includes(status)) {
383
+ return types.SubmissionStatus.PRESENTATION_ERROR;
384
+ }
385
+ if (["TL", "TLE", types.SubmissionStatus.TIME_LIMIT_EXCEEDED.toString()].includes(status)) {
386
+ return types.SubmissionStatus.TIME_LIMIT_EXCEEDED;
387
+ }
388
+ if (["ML", "MLE", types.SubmissionStatus.MEMORY_LIMIT_EXCEEDED.toString()].includes(status)) {
389
+ return types.SubmissionStatus.MEMORY_LIMIT_EXCEEDED;
390
+ }
391
+ if (["OL", "OLE", types.SubmissionStatus.OUTPUT_LIMIT_EXCEEDED.toString()].includes(status)) {
392
+ return types.SubmissionStatus.OUTPUT_LIMIT_EXCEEDED;
393
+ }
394
+ if (["IL", "ILE", types.SubmissionStatus.IDLENESS_LIMIT_EXCEEDED.toString()].includes(status)) {
395
+ return types.SubmissionStatus.IDLENESS_LIMIT_EXCEEDED;
396
+ }
397
+ if (["RT", "RE", "RTE", types.SubmissionStatus.RUNTIME_ERROR.toString()].includes(status)) {
398
+ return types.SubmissionStatus.RUNTIME_ERROR;
399
+ }
400
+ if (["JE", types.SubmissionStatus.JUDGEMENT_FAILED.toString()].includes(status)) {
401
+ return types.SubmissionStatus.JUDGEMENT_FAILED;
402
+ }
403
+ if (["SE", types.SubmissionStatus.SYSTEM_ERROR.toString()].includes(status)) {
404
+ return types.SubmissionStatus.SYSTEM_ERROR;
405
+ }
406
+ if ([types.SubmissionStatus.HACKED.toString()].includes(status)) {
407
+ return types.SubmissionStatus.HACKED;
408
+ }
409
+ if ([types.SubmissionStatus.CONFIGURATION_ERROR.toString()].includes(status)) {
410
+ return types.SubmissionStatus.CONFIGURATION_ERROR;
411
+ }
412
+ if ([types.SubmissionStatus.CANCELED.toString()].includes(status)) {
413
+ return types.SubmissionStatus.CANCELED;
414
+ }
415
+ if ([types.SubmissionStatus.SKIPPED.toString()].includes(status)) {
416
+ return types.SubmissionStatus.SKIPPED;
417
+ }
418
+ if ([types.SubmissionStatus.SECURITY_VIOLATED.toString()].includes(status)) {
419
+ return types.SubmissionStatus.SECURITY_VIOLATED;
420
+ }
421
+ if ([types.SubmissionStatus.DENIAL_OF_JUDGEMENT.toString()].includes(status)) {
422
+ return types.SubmissionStatus.DENIAL_OF_JUDGEMENT;
423
+ }
424
+ return types.SubmissionStatus.UNKNOWN;
425
+ }
426
+ function isAccepted(status) {
427
+ const acceptedArray = [types.SubmissionStatus.ACCEPTED, types.SubmissionStatus.CORRECT];
428
+ return acceptedArray.includes(status);
429
+ }
430
+ function isRejected(status) {
431
+ const rejectArray = [
432
+ types.SubmissionStatus.RUNTIME_ERROR,
433
+ types.SubmissionStatus.TIME_LIMIT_EXCEEDED,
434
+ types.SubmissionStatus.MEMORY_LIMIT_EXCEEDED,
435
+ types.SubmissionStatus.OUTPUT_LIMIT_EXCEEDED,
436
+ types.SubmissionStatus.IDLENESS_LIMIT_EXCEEDED,
437
+ types.SubmissionStatus.WRONG_ANSWER,
438
+ types.SubmissionStatus.REJECTED,
439
+ types.SubmissionStatus.JUDGEMENT_FAILED,
440
+ types.SubmissionStatus.HACKED
441
+ ];
442
+ return rejectArray.includes(status);
443
+ }
444
+ function isPending(status) {
445
+ const pendingArray = [
446
+ types.SubmissionStatus.PENDING,
447
+ types.SubmissionStatus.WAITING,
448
+ types.SubmissionStatus.JUDGING,
449
+ types.SubmissionStatus.FROZEN
450
+ ];
451
+ return pendingArray.includes(status);
452
+ }
453
+ function isNotCalculatedPenaltyStatus(status) {
454
+ const isNotCalculatedPenaltyArray = [
455
+ types.SubmissionStatus.COMPILE_ERROR,
456
+ types.SubmissionStatus.PRESENTATION_ERROR,
457
+ types.SubmissionStatus.CONFIGURATION_ERROR,
458
+ types.SubmissionStatus.SYSTEM_ERROR,
459
+ types.SubmissionStatus.CANCELED,
460
+ types.SubmissionStatus.SKIPPED,
461
+ types.SubmissionStatus.UNKNOWN,
462
+ types.SubmissionStatus.UNDEFINED
463
+ ];
464
+ return isNotCalculatedPenaltyArray.includes(status);
465
+ }
466
+
467
+ class Submission {
468
+ constructor() {
469
+ this.status = types.SubmissionStatus.UNKNOWN;
470
+ this.isIgnore = false;
471
+ this.id = "";
472
+ this.teamId = "";
473
+ this.problemId = "";
474
+ this.timestamp = 0;
475
+ }
476
+ isAccepted() {
477
+ return isAccepted(this.status);
478
+ }
479
+ isRejected() {
480
+ return isRejected(this.status);
481
+ }
482
+ isPending() {
483
+ return isPending(this.status);
484
+ }
485
+ isNotCalculatedPenaltyStatus() {
486
+ return isNotCalculatedPenaltyStatus(this.status);
487
+ }
488
+ static compare(lhs, rhs) {
489
+ if (lhs.timestamp !== rhs.timestamp) {
490
+ return lhs.timestamp - rhs.timestamp;
491
+ }
492
+ if (lhs.teamId === rhs.teamId) {
493
+ if (lhs.isAccepted() && !rhs.isAccepted()) {
494
+ return -1;
495
+ }
496
+ if (!lhs.isAccepted() && rhs.isAccepted()) {
497
+ return 1;
498
+ }
499
+ }
500
+ return 0;
501
+ }
502
+ }
503
+ function createSubmission(submissionJSON) {
504
+ const s = new Submission();
505
+ s.id = String(submissionJSON.id ?? submissionJSON.submission_id ?? "");
506
+ s.teamId = String(submissionJSON.team_id);
507
+ s.problemId = String(submissionJSON.problem_id);
508
+ s.timestamp = submissionJSON.timestamp;
509
+ s.status = stringToSubmissionStatus(submissionJSON.status);
510
+ s.isIgnore = submissionJSON.is_ignore ?? false;
511
+ return s;
512
+ }
513
+ function createSubmissions(submissionsJSON) {
514
+ if (Array.isArray(submissionsJSON)) {
515
+ return submissionsJSON.map((s, index) => createSubmission({ ...s, id: s.submission_id ?? String(index) }));
516
+ } else {
517
+ const submissions = Object.entries(submissionsJSON).map(
518
+ ([submissionId, s]) => createSubmission({ ...s, id: s.submission_id ?? submissionId })
519
+ );
520
+ return submissions;
521
+ }
522
+ }
523
+
524
+ class Rank {
525
+ constructor(contest, teams, submissions) {
526
+ this.contest = contest;
527
+ this.teams = ___default.cloneDeep(teams);
528
+ this.teamsMap = new Map(this.teams.map((t) => [t.id, t]));
529
+ this.submissions = ___default.cloneDeep(submissions).sort(Submission.compare);
530
+ this.submissionsMap = new Map(this.submissions.map((s) => [s.id, s]));
531
+ this.firstSolvedSubmissions = new Map(this.contest.problems.map((p) => [p.id, []]));
532
+ }
533
+ buildRank(options) {
534
+ (() => {
535
+ for (const t of this.teams) {
536
+ t.problemStatistics = this.contest.problems.map((p) => {
537
+ const ps = new TeamProblemStatistics();
538
+ ps.problem = p;
539
+ ps.contestPenalty = this.contest.penalty;
540
+ return ps;
541
+ });
542
+ t.problemStatisticsMap = new Map(t.problemStatistics.map((ps) => [ps.problem.id, ps]));
543
+ }
544
+ this.firstSolvedSubmissions = new Map(this.contest.problems.map((p) => [p.id, []]));
545
+ for (const s of this.submissions) {
546
+ const teamId = s.teamId;
547
+ const problemId = s.problemId;
548
+ const team = this.teamsMap.get(teamId);
549
+ const problem = this.contest.problemsMap.get(problemId);
550
+ if (team === void 0 || problem === void 0) {
551
+ continue;
552
+ }
553
+ if (options?.timestamp !== void 0 && options?.timestamp !== null) {
554
+ if (s.timestamp > options.timestamp) {
555
+ break;
556
+ }
557
+ }
558
+ const problemStatistics = team.problemStatisticsMap.get(problemId);
559
+ const submissions = problemStatistics.submissions;
560
+ const firstSolvedSubmissions = this.firstSolvedSubmissions.get(problemId);
561
+ submissions.push(s);
562
+ problem.statistics.submittedNum++;
563
+ if (problemStatistics.isSolved) {
564
+ continue;
565
+ }
566
+ if (s.isIgnore || s.isNotCalculatedPenaltyStatus()) {
567
+ problemStatistics.ignoreCount++;
568
+ continue;
569
+ }
570
+ problemStatistics.isSubmitted = true;
571
+ problemStatistics.lastSubmitTimestamp = s.timestamp;
572
+ problemStatistics.totalCount++;
573
+ if (s.isAccepted()) {
574
+ problemStatistics.isSolved = true;
575
+ problemStatistics.solvedTimestamp = s.timestamp;
576
+ problem.statistics.acceptedNum++;
577
+ if (firstSolvedSubmissions.length === 0 || firstSolvedSubmissions[firstSolvedSubmissions.length - 1].timestamp === s.timestamp) {
578
+ problemStatistics.isFirstSolved = true;
579
+ firstSolvedSubmissions.push(s);
580
+ }
581
+ }
582
+ if (s.isRejected()) {
583
+ problemStatistics.failedCount++;
584
+ problem.statistics.rejectedNum++;
585
+ }
586
+ if (s.isPending()) {
587
+ problemStatistics.pendingCount++;
588
+ problem.statistics.pendingNum++;
589
+ }
590
+ }
591
+ this.teams.forEach((t) => t.calcSolvedData());
592
+ this.teams.sort(Team.compare);
593
+ {
594
+ let rank = 1;
595
+ for (const t of this.teams) {
596
+ t.rank = rank++;
597
+ }
598
+ }
599
+ })();
600
+ return this;
601
+ }
602
+ }
603
+
604
+ class ResolverOperation {
605
+ constructor() {
606
+ this.id = 0;
607
+ this.team = new Team();
608
+ this.problemIx = 0;
609
+ this.beforeTeamProblemStatistics = new TeamProblemStatistics();
610
+ this.afterTeamProblemStatistics = new TeamProblemStatistics();
611
+ }
612
+ }
613
+
614
+ class Resolver extends Rank {
615
+ constructor(contest, teams, submissions) {
616
+ submissions.sort(Submission.compare);
617
+ let beforeFreezeSubmissions = submissions;
618
+ let afterFreezeSubmissions = submissions;
619
+ {
620
+ const ix = ___default.sortedIndex(
621
+ submissions.map((s) => s.timestamp),
622
+ contest.unFreezeDurationTimestamp
623
+ );
624
+ beforeFreezeSubmissions = submissions.slice(0, ix + 1);
625
+ afterFreezeSubmissions = submissions.slice(ix, -1);
626
+ }
627
+ super(contest, teams, beforeFreezeSubmissions);
628
+ this.finalRank = new Rank(contest, teams, submissions);
629
+ this.operations = [];
630
+ this.beforeFreezeSubmissions = beforeFreezeSubmissions;
631
+ this.afterFreezeSubmissions = afterFreezeSubmissions;
632
+ }
633
+ buildResolver() {
634
+ this.buildRank();
635
+ this.finalRank.buildRank();
636
+ for (const s of this.afterFreezeSubmissions) {
637
+ const teamId = s.teamId;
638
+ const problemId = s.problemId;
639
+ const team = this.teamsMap.get(teamId);
640
+ const problem = this.contest.problemsMap.get(problemId);
641
+ if (team === void 0 || problem === void 0) {
642
+ continue;
643
+ }
644
+ const problemStatistics = team.problemStatisticsMap.get(problemId);
645
+ problemStatistics.pendingCount++;
646
+ problemStatistics.totalCount++;
647
+ if (!problemStatistics.isAccepted) {
648
+ problemStatistics.lastSubmitTimestamp = s.timestamp;
649
+ }
650
+ }
651
+ {
652
+ const teams_ = ___default.cloneDeep(this.teams);
653
+ for (let i = this.teams.length - 1; i >= 0; ) {
654
+ const team = teams_[i];
655
+ const teamId = team.id;
656
+ let handleCnt = 0;
657
+ let problemIx = -1;
658
+ for (const p of team.problemStatistics) {
659
+ problemIx++;
660
+ if (!p.isPending) {
661
+ continue;
662
+ }
663
+ handleCnt++;
664
+ const beforeTeamProblemStatistics = this.teamsMap.get(teamId)?.problemStatistics[problemIx];
665
+ const afterTeamProblemStatistics = this.finalRank.teamsMap.get(teamId)?.problemStatistics[problemIx];
666
+ const op = new ResolverOperation();
667
+ op.id = this.operations.length;
668
+ op.team = this.teamsMap.get(teamId);
669
+ op.problemIx = problemIx;
670
+ op.beforeTeamProblemStatistics = beforeTeamProblemStatistics;
671
+ op.afterTeamProblemStatistics = afterTeamProblemStatistics;
672
+ this.operations.push(op);
673
+ team.problemStatistics[problemIx] = afterTeamProblemStatistics;
674
+ team.calcSolvedData();
675
+ break;
676
+ }
677
+ {
678
+ let j = i;
679
+ while (j > 0 && Team.compare(teams_[j], teams_[j - 1]) < 0) {
680
+ [teams_[j], teams_[j - 1]] = [teams_[j - 1], teams_[j]];
681
+ j--;
682
+ }
683
+ }
684
+ if (handleCnt === 0) {
685
+ i--;
686
+ }
687
+ }
688
+ }
689
+ }
690
+ }
691
+
692
+ exports.dayjs = dayjs__default;
693
+ exports.Contest = Contest;
694
+ exports.Problem = Problem;
695
+ exports.Rank = Rank;
696
+ exports.Resolver = Resolver;
697
+ exports.Submission = Submission;
698
+ exports.Team = Team;
699
+ exports.TeamProblemStatistics = TeamProblemStatistics;
700
+ exports.createContest = createContest;
701
+ exports.createDayJS = createDayJS;
702
+ exports.createProblem = createProblem;
703
+ exports.createProblems = createProblems;
704
+ exports.createProblemsByProblemIds = createProblemsByProblemIds;
705
+ exports.createSubmission = createSubmission;
706
+ exports.createSubmissions = createSubmissions;
707
+ exports.createTeam = createTeam;
708
+ exports.createTeams = createTeams;
709
+ exports.getImageSource = getImageSource;
710
+ exports.getTimeDiff = getTimeDiff;
711
+ exports.getTimestamp = getTimestamp;
712
+ exports.isAccepted = isAccepted;
713
+ exports.isNotCalculatedPenaltyStatus = isNotCalculatedPenaltyStatus;
714
+ exports.isPending = isPending;
715
+ exports.isRejected = isRejected;
716
+ exports.stringToSubmissionStatus = stringToSubmissionStatus;