@xcpcio/core 0.7.2 → 0.9.0

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 CHANGED
@@ -27,6 +27,22 @@ const minMax__default = /*#__PURE__*/_interopDefaultLegacy(minMax);
27
27
  const relativeTime__default = /*#__PURE__*/_interopDefaultLegacy(relativeTime);
28
28
  const ___default = /*#__PURE__*/_interopDefaultLegacy(_);
29
29
 
30
+ var MedalType = /* @__PURE__ */ ((MedalType2) => {
31
+ MedalType2[MedalType2["UNKNOWN"] = 0] = "UNKNOWN";
32
+ MedalType2[MedalType2["GOLD"] = 1] = "GOLD";
33
+ MedalType2[MedalType2["SILVER"] = 2] = "SILVER";
34
+ MedalType2[MedalType2["BRONZE"] = 3] = "BRONZE";
35
+ MedalType2[MedalType2["HONORABLE"] = 4] = "HONORABLE";
36
+ return MedalType2;
37
+ })(MedalType || {});
38
+ class Award {
39
+ constructor() {
40
+ this.medalType = 0 /* UNKNOWN */;
41
+ this.minRank = 0;
42
+ this.maxRank = 0;
43
+ }
44
+ }
45
+
30
46
  function calcDict(attemptedNum, solvedNum) {
31
47
  if (solvedNum === 0) {
32
48
  return 0;
@@ -300,6 +316,40 @@ function createContest(contestJSON) {
300
316
  }
301
317
  c.badge = contestJSON.badge;
302
318
  c.medal = contestJSON.medal;
319
+ (() => {
320
+ if (contestJSON.medal === void 0 || contestJSON.medal === null) {
321
+ return;
322
+ }
323
+ c.awards = /* @__PURE__ */ new Map();
324
+ for (const k in contestJSON.medal) {
325
+ const v = contestJSON.medal[k];
326
+ {
327
+ const award = [];
328
+ let rank = 1;
329
+ const work = (key, medalType) => {
330
+ if (Object.keys(v).includes(key)) {
331
+ const a = new Award();
332
+ a.medalType = medalType;
333
+ a.minRank = rank;
334
+ rank += Number(v[key]);
335
+ a.maxRank = rank - 1;
336
+ award.push(a);
337
+ }
338
+ };
339
+ work("gold", MedalType.GOLD);
340
+ work("silver", MedalType.SILVER);
341
+ work("bronze", MedalType.BRONZE);
342
+ {
343
+ const a = new Award();
344
+ a.medalType = MedalType.HONORABLE;
345
+ a.minRank = rank;
346
+ a.maxRank = 1061109567;
347
+ award.push(a);
348
+ }
349
+ c.awards.set(k, award);
350
+ }
351
+ }
352
+ })();
303
353
  c.organization = contestJSON.organization;
304
354
  {
305
355
  const g = new Group();
@@ -390,6 +440,208 @@ function createContestIndexList(contestListJSON) {
390
440
  return contestIndexList;
391
441
  }
392
442
 
443
+ function stringToSubmissionStatus(status) {
444
+ status = status.toUpperCase().replace(" ", "_");
445
+ if (["OK", "AC", types.SubmissionStatus.ACCEPTED.toString()].includes(status)) {
446
+ return types.SubmissionStatus.ACCEPTED;
447
+ }
448
+ if ([types.SubmissionStatus.CORRECT.toString()].includes(status)) {
449
+ return types.SubmissionStatus.CORRECT;
450
+ }
451
+ if ([types.SubmissionStatus.PARTIALLY_CORRECT.toString()].includes(status)) {
452
+ return types.SubmissionStatus.PARTIALLY_CORRECT;
453
+ }
454
+ if (["WA", types.SubmissionStatus.WRONG_ANSWER.toString()].includes(status)) {
455
+ return types.SubmissionStatus.WRONG_ANSWER;
456
+ }
457
+ if (["RJ", "INCORRECT", types.SubmissionStatus.REJECTED.toString()].includes(status)) {
458
+ return types.SubmissionStatus.REJECTED;
459
+ }
460
+ if (["PD", types.SubmissionStatus.PENDING.toString()].includes(status)) {
461
+ return types.SubmissionStatus.PENDING;
462
+ }
463
+ if ([types.SubmissionStatus.WAITING.toString()].includes(status)) {
464
+ return types.SubmissionStatus.WAITING;
465
+ }
466
+ if ([types.SubmissionStatus.JUDGING.toString()].includes(status)) {
467
+ return types.SubmissionStatus.JUDGING;
468
+ }
469
+ if ([types.SubmissionStatus.FROZEN.toString()].includes(status)) {
470
+ return types.SubmissionStatus.FROZEN;
471
+ }
472
+ if (["CE", types.SubmissionStatus.COMPILE_ERROR.toString()].includes(status)) {
473
+ return types.SubmissionStatus.COMPILE_ERROR;
474
+ }
475
+ if (["PE", types.SubmissionStatus.PRESENTATION_ERROR.toString()].includes(status)) {
476
+ return types.SubmissionStatus.PRESENTATION_ERROR;
477
+ }
478
+ if (["TL", "TLE", types.SubmissionStatus.TIME_LIMIT_EXCEEDED.toString()].includes(status)) {
479
+ return types.SubmissionStatus.TIME_LIMIT_EXCEEDED;
480
+ }
481
+ if (["ML", "MLE", types.SubmissionStatus.MEMORY_LIMIT_EXCEEDED.toString()].includes(status)) {
482
+ return types.SubmissionStatus.MEMORY_LIMIT_EXCEEDED;
483
+ }
484
+ if (["OL", "OLE", types.SubmissionStatus.OUTPUT_LIMIT_EXCEEDED.toString()].includes(status)) {
485
+ return types.SubmissionStatus.OUTPUT_LIMIT_EXCEEDED;
486
+ }
487
+ if (["IL", "ILE", types.SubmissionStatus.IDLENESS_LIMIT_EXCEEDED.toString()].includes(status)) {
488
+ return types.SubmissionStatus.IDLENESS_LIMIT_EXCEEDED;
489
+ }
490
+ if (["RT", "RE", "RTE", types.SubmissionStatus.RUNTIME_ERROR.toString()].includes(status)) {
491
+ return types.SubmissionStatus.RUNTIME_ERROR;
492
+ }
493
+ if (["JE", types.SubmissionStatus.JUDGEMENT_FAILED.toString()].includes(status)) {
494
+ return types.SubmissionStatus.JUDGEMENT_FAILED;
495
+ }
496
+ if (["SE", types.SubmissionStatus.SYSTEM_ERROR.toString()].includes(status)) {
497
+ return types.SubmissionStatus.SYSTEM_ERROR;
498
+ }
499
+ if ([types.SubmissionStatus.HACKED.toString()].includes(status)) {
500
+ return types.SubmissionStatus.HACKED;
501
+ }
502
+ if ([types.SubmissionStatus.CONFIGURATION_ERROR.toString()].includes(status)) {
503
+ return types.SubmissionStatus.CONFIGURATION_ERROR;
504
+ }
505
+ if ([types.SubmissionStatus.CANCELED.toString()].includes(status)) {
506
+ return types.SubmissionStatus.CANCELED;
507
+ }
508
+ if ([types.SubmissionStatus.SKIPPED.toString()].includes(status)) {
509
+ return types.SubmissionStatus.SKIPPED;
510
+ }
511
+ if ([types.SubmissionStatus.SECURITY_VIOLATED.toString()].includes(status)) {
512
+ return types.SubmissionStatus.SECURITY_VIOLATED;
513
+ }
514
+ if ([types.SubmissionStatus.DENIAL_OF_JUDGEMENT.toString()].includes(status)) {
515
+ return types.SubmissionStatus.DENIAL_OF_JUDGEMENT;
516
+ }
517
+ return types.SubmissionStatus.UNKNOWN;
518
+ }
519
+ function isAccepted(status) {
520
+ const acceptedArray = [types.SubmissionStatus.ACCEPTED, types.SubmissionStatus.CORRECT];
521
+ return acceptedArray.includes(status);
522
+ }
523
+ function isRejected(status) {
524
+ const rejectArray = [
525
+ types.SubmissionStatus.RUNTIME_ERROR,
526
+ types.SubmissionStatus.TIME_LIMIT_EXCEEDED,
527
+ types.SubmissionStatus.MEMORY_LIMIT_EXCEEDED,
528
+ types.SubmissionStatus.OUTPUT_LIMIT_EXCEEDED,
529
+ types.SubmissionStatus.IDLENESS_LIMIT_EXCEEDED,
530
+ types.SubmissionStatus.WRONG_ANSWER,
531
+ types.SubmissionStatus.REJECTED,
532
+ types.SubmissionStatus.JUDGEMENT_FAILED,
533
+ types.SubmissionStatus.HACKED
534
+ ];
535
+ return rejectArray.includes(status);
536
+ }
537
+ function isPending(status) {
538
+ const pendingArray = [
539
+ types.SubmissionStatus.PENDING,
540
+ types.SubmissionStatus.WAITING,
541
+ types.SubmissionStatus.JUDGING,
542
+ types.SubmissionStatus.FROZEN
543
+ ];
544
+ return pendingArray.includes(status);
545
+ }
546
+ function isNotCalculatedPenaltyStatus(status) {
547
+ const isNotCalculatedPenaltyArray = [
548
+ types.SubmissionStatus.COMPILE_ERROR,
549
+ types.SubmissionStatus.PRESENTATION_ERROR,
550
+ types.SubmissionStatus.CONFIGURATION_ERROR,
551
+ types.SubmissionStatus.SYSTEM_ERROR,
552
+ types.SubmissionStatus.CANCELED,
553
+ types.SubmissionStatus.SKIPPED,
554
+ types.SubmissionStatus.UNKNOWN,
555
+ types.SubmissionStatus.UNDEFINED
556
+ ];
557
+ return isNotCalculatedPenaltyArray.includes(status);
558
+ }
559
+
560
+ function submissionStatusToCodeforcesGymDatStatus(status) {
561
+ if (isAccepted(status)) {
562
+ return "OK";
563
+ }
564
+ if (status === types.SubmissionStatus.WRONG_ANSWER) {
565
+ return "WA";
566
+ }
567
+ if (status === types.SubmissionStatus.TIME_LIMIT_EXCEEDED) {
568
+ return "TL";
569
+ }
570
+ if (status === types.SubmissionStatus.MEMORY_LIMIT_EXCEEDED) {
571
+ return "ML";
572
+ }
573
+ if (status === types.SubmissionStatus.OUTPUT_LIMIT_EXCEEDED) {
574
+ return "IL";
575
+ }
576
+ if (status === types.SubmissionStatus.PRESENTATION_ERROR) {
577
+ return "PE";
578
+ }
579
+ if (status === types.SubmissionStatus.RUNTIME_ERROR) {
580
+ return "RT";
581
+ }
582
+ if (status === types.SubmissionStatus.COMPILE_ERROR || isNotCalculatedPenaltyStatus(status)) {
583
+ return "CE";
584
+ }
585
+ if (isPending(status)) {
586
+ return "PD";
587
+ }
588
+ return "RJ";
589
+ }
590
+ function rankToCodeforcesGymDAT(rank) {
591
+ let res = "";
592
+ res += `@contest "${rank.contest.name}"
593
+ @contlen ${Math.floor(rank.contest.endTime.diff(rank.contest.startTime) / 1e3 / 60)}
594
+ @problems ${rank.contest.problems.length}
595
+ @teams ${rank.teams.length + 100}
596
+ @submissions ${rank.submissions.length}
597
+ `;
598
+ rank.contest.problems.forEach((p) => {
599
+ res += `@p ${p.label},${p.label},20,0
600
+ `;
601
+ });
602
+ let teamIndex = 1;
603
+ const teamIdMap = /* @__PURE__ */ new Map();
604
+ const submissionsIdMap = /* @__PURE__ */ new Map();
605
+ rank.teams.forEach((team) => {
606
+ let name = team.name;
607
+ if (team.organization) {
608
+ name = `${team.organization} - ${name}`;
609
+ }
610
+ if (team.members) {
611
+ name = `${name} - ${team.membersToString}`;
612
+ }
613
+ res += `@t ${teamIndex},0,1,${name}
614
+ `;
615
+ teamIdMap.set(team.id, teamIndex);
616
+ teamIndex++;
617
+ {
618
+ const mp = /* @__PURE__ */ new Map();
619
+ rank.contest.problems.forEach((p) => {
620
+ mp.set(p.id, 0);
621
+ });
622
+ submissionsIdMap.set(team.id, mp);
623
+ }
624
+ });
625
+ for (let i = 0; i < 100; i++) {
626
+ res += `@t ${teamIndex},0,1,\u041F\u043E\u043F\u043E\u043B\u043D\u0438\u0442\u044C \u043A\u043E\u043C\u0430\u043D\u0434\u0443
627
+ `;
628
+ teamIndex++;
629
+ }
630
+ rank.submissions.forEach((submission) => {
631
+ const teamId = submission.teamId;
632
+ const problemId = submission.problemId;
633
+ const problem = rank.contest.problemsMap.get(problemId);
634
+ if (!problem) {
635
+ return;
636
+ }
637
+ const status = submissionStatusToCodeforcesGymDatStatus(submission.status);
638
+ submissionsIdMap.get(teamId).set(problemId, submissionsIdMap.get(teamId).get(problemId) + 1);
639
+ res += `@s ${teamIdMap.get(teamId)},${problem.label},${submissionsIdMap.get(teamId)?.get(problemId)},${submission.timestamp},${status}
640
+ `;
641
+ });
642
+ return res;
643
+ }
644
+
393
645
  function getImageSource(image) {
394
646
  if (image?.url) {
395
647
  return image.url;
@@ -437,6 +689,7 @@ class Team {
437
689
  this.problemStatisticsMap = /* @__PURE__ */ new Map();
438
690
  this.submissions = [];
439
691
  this.placeChartPoints = [];
692
+ this.awards = [];
440
693
  }
441
694
  reset() {
442
695
  this.rank = 0;
@@ -460,6 +713,12 @@ class Team {
460
713
  const solvedNum = this.solvedProblemNum;
461
714
  return calcDict(attemptedNum, solvedNum);
462
715
  }
716
+ get membersToString() {
717
+ if (typeof this.members === "string") {
718
+ return this.members;
719
+ }
720
+ return this.members?.join(", ");
721
+ }
463
722
  calcSolvedData() {
464
723
  this.solvedProblemNum = 0;
465
724
  this.attemptedProblemNum = 0;
@@ -472,6 +731,16 @@ class Team {
472
731
  }
473
732
  }
474
733
  }
734
+ calcAwards(awards) {
735
+ if (!awards) {
736
+ return;
737
+ }
738
+ for (const award of awards) {
739
+ if (this.rank >= award.minRank && this.rank <= award.maxRank) {
740
+ this.awards.push(award.medalType);
741
+ }
742
+ }
743
+ }
475
744
  isEqualRank(otherTeam) {
476
745
  return this.solvedProblemNum === otherTeam.solvedProblemNum && this.penalty === otherTeam.penalty;
477
746
  }
@@ -530,6 +799,14 @@ function createTeam(teamJSON) {
530
799
  if (Boolean(teamJSON.girl) === true) {
531
800
  t.group.push("girl");
532
801
  }
802
+ {
803
+ const tt = teamJSON;
804
+ for (const key of Object.keys(tt)) {
805
+ if (tt[key] === 1 || tt[key] === true) {
806
+ t.group.push(key);
807
+ }
808
+ }
809
+ }
533
810
  t.group = [...new Set(t.group)];
534
811
  t.group.sort();
535
812
  return t;
@@ -545,123 +822,6 @@ function createTeams(teamsJSON) {
545
822
  }
546
823
  }
547
824
 
548
- function stringToSubmissionStatus(status) {
549
- status = status.toUpperCase().replace(" ", "_");
550
- if (["OK", "AC", types.SubmissionStatus.ACCEPTED.toString()].includes(status)) {
551
- return types.SubmissionStatus.ACCEPTED;
552
- }
553
- if ([types.SubmissionStatus.CORRECT.toString()].includes(status)) {
554
- return types.SubmissionStatus.CORRECT;
555
- }
556
- if ([types.SubmissionStatus.PARTIALLY_CORRECT.toString()].includes(status)) {
557
- return types.SubmissionStatus.PARTIALLY_CORRECT;
558
- }
559
- if (["WA", types.SubmissionStatus.WRONG_ANSWER.toString()].includes(status)) {
560
- return types.SubmissionStatus.WRONG_ANSWER;
561
- }
562
- if (["RJ", "INCORRECT", types.SubmissionStatus.REJECTED.toString()].includes(status)) {
563
- return types.SubmissionStatus.REJECTED;
564
- }
565
- if (["PD", types.SubmissionStatus.PENDING.toString()].includes(status)) {
566
- return types.SubmissionStatus.PENDING;
567
- }
568
- if ([types.SubmissionStatus.WAITING.toString()].includes(status)) {
569
- return types.SubmissionStatus.WAITING;
570
- }
571
- if ([types.SubmissionStatus.JUDGING.toString()].includes(status)) {
572
- return types.SubmissionStatus.JUDGING;
573
- }
574
- if ([types.SubmissionStatus.FROZEN.toString()].includes(status)) {
575
- return types.SubmissionStatus.FROZEN;
576
- }
577
- if (["CE", types.SubmissionStatus.COMPILE_ERROR.toString()].includes(status)) {
578
- return types.SubmissionStatus.COMPILE_ERROR;
579
- }
580
- if (["PE", types.SubmissionStatus.PRESENTATION_ERROR.toString()].includes(status)) {
581
- return types.SubmissionStatus.PRESENTATION_ERROR;
582
- }
583
- if (["TL", "TLE", types.SubmissionStatus.TIME_LIMIT_EXCEEDED.toString()].includes(status)) {
584
- return types.SubmissionStatus.TIME_LIMIT_EXCEEDED;
585
- }
586
- if (["ML", "MLE", types.SubmissionStatus.MEMORY_LIMIT_EXCEEDED.toString()].includes(status)) {
587
- return types.SubmissionStatus.MEMORY_LIMIT_EXCEEDED;
588
- }
589
- if (["OL", "OLE", types.SubmissionStatus.OUTPUT_LIMIT_EXCEEDED.toString()].includes(status)) {
590
- return types.SubmissionStatus.OUTPUT_LIMIT_EXCEEDED;
591
- }
592
- if (["IL", "ILE", types.SubmissionStatus.IDLENESS_LIMIT_EXCEEDED.toString()].includes(status)) {
593
- return types.SubmissionStatus.IDLENESS_LIMIT_EXCEEDED;
594
- }
595
- if (["RT", "RE", "RTE", types.SubmissionStatus.RUNTIME_ERROR.toString()].includes(status)) {
596
- return types.SubmissionStatus.RUNTIME_ERROR;
597
- }
598
- if (["JE", types.SubmissionStatus.JUDGEMENT_FAILED.toString()].includes(status)) {
599
- return types.SubmissionStatus.JUDGEMENT_FAILED;
600
- }
601
- if (["SE", types.SubmissionStatus.SYSTEM_ERROR.toString()].includes(status)) {
602
- return types.SubmissionStatus.SYSTEM_ERROR;
603
- }
604
- if ([types.SubmissionStatus.HACKED.toString()].includes(status)) {
605
- return types.SubmissionStatus.HACKED;
606
- }
607
- if ([types.SubmissionStatus.CONFIGURATION_ERROR.toString()].includes(status)) {
608
- return types.SubmissionStatus.CONFIGURATION_ERROR;
609
- }
610
- if ([types.SubmissionStatus.CANCELED.toString()].includes(status)) {
611
- return types.SubmissionStatus.CANCELED;
612
- }
613
- if ([types.SubmissionStatus.SKIPPED.toString()].includes(status)) {
614
- return types.SubmissionStatus.SKIPPED;
615
- }
616
- if ([types.SubmissionStatus.SECURITY_VIOLATED.toString()].includes(status)) {
617
- return types.SubmissionStatus.SECURITY_VIOLATED;
618
- }
619
- if ([types.SubmissionStatus.DENIAL_OF_JUDGEMENT.toString()].includes(status)) {
620
- return types.SubmissionStatus.DENIAL_OF_JUDGEMENT;
621
- }
622
- return types.SubmissionStatus.UNKNOWN;
623
- }
624
- function isAccepted(status) {
625
- const acceptedArray = [types.SubmissionStatus.ACCEPTED, types.SubmissionStatus.CORRECT];
626
- return acceptedArray.includes(status);
627
- }
628
- function isRejected(status) {
629
- const rejectArray = [
630
- types.SubmissionStatus.RUNTIME_ERROR,
631
- types.SubmissionStatus.TIME_LIMIT_EXCEEDED,
632
- types.SubmissionStatus.MEMORY_LIMIT_EXCEEDED,
633
- types.SubmissionStatus.OUTPUT_LIMIT_EXCEEDED,
634
- types.SubmissionStatus.IDLENESS_LIMIT_EXCEEDED,
635
- types.SubmissionStatus.WRONG_ANSWER,
636
- types.SubmissionStatus.REJECTED,
637
- types.SubmissionStatus.JUDGEMENT_FAILED,
638
- types.SubmissionStatus.HACKED
639
- ];
640
- return rejectArray.includes(status);
641
- }
642
- function isPending(status) {
643
- const pendingArray = [
644
- types.SubmissionStatus.PENDING,
645
- types.SubmissionStatus.WAITING,
646
- types.SubmissionStatus.JUDGING,
647
- types.SubmissionStatus.FROZEN
648
- ];
649
- return pendingArray.includes(status);
650
- }
651
- function isNotCalculatedPenaltyStatus(status) {
652
- const isNotCalculatedPenaltyArray = [
653
- types.SubmissionStatus.COMPILE_ERROR,
654
- types.SubmissionStatus.PRESENTATION_ERROR,
655
- types.SubmissionStatus.CONFIGURATION_ERROR,
656
- types.SubmissionStatus.SYSTEM_ERROR,
657
- types.SubmissionStatus.CANCELED,
658
- types.SubmissionStatus.SKIPPED,
659
- types.SubmissionStatus.UNKNOWN,
660
- types.SubmissionStatus.UNDEFINED
661
- ];
662
- return isNotCalculatedPenaltyArray.includes(status);
663
- }
664
-
665
825
  class Submission {
666
826
  constructor() {
667
827
  this.status = types.SubmissionStatus.UNKNOWN;
@@ -728,7 +888,7 @@ class RankOptions {
728
888
  this.width = 0;
729
889
  this.timestamp = 0;
730
890
  this.enableFilterTeamsByGroup = false;
731
- this.group = "";
891
+ this.group = "all";
732
892
  this.filterOrganizations = [];
733
893
  this.filterOrganizationMap = /* @__PURE__ */ new Map();
734
894
  this.filterTeams = [];
@@ -751,6 +911,7 @@ class RankOptions {
751
911
  }
752
912
  disableFilterTeamsByGroup() {
753
913
  this.enableFilterTeamsByGroup = false;
914
+ this.group = "all";
754
915
  }
755
916
  setFilterOrganizations(filterOrganizations) {
756
917
  const m = /* @__PURE__ */ new Map();
@@ -908,6 +1069,7 @@ class Rank {
908
1069
  this.teams.sort(Team.compare);
909
1070
  this.buildTeamRank();
910
1071
  this.buildOrgRank();
1072
+ this.teams.forEach((t) => t.calcAwards(this.contest.awards?.get(this.options.group)));
911
1073
  this.teams.forEach((t) => t.postProcessPlaceChartPoints());
912
1074
  })();
913
1075
  (() => {
@@ -1080,9 +1242,11 @@ class Resolver extends Rank {
1080
1242
  }
1081
1243
 
1082
1244
  exports.dayjs = dayjs__default;
1245
+ exports.Award = Award;
1083
1246
  exports.Contest = Contest;
1084
1247
  exports.ContestIndex = ContestIndex;
1085
1248
  exports.ContestIndexConfig = ContestIndexConfig;
1249
+ exports.MedalType = MedalType;
1086
1250
  exports.PlaceChartPointData = PlaceChartPointData;
1087
1251
  exports.Problem = Problem;
1088
1252
  exports.ProblemStatistics = ProblemStatistics;
@@ -1112,4 +1276,5 @@ exports.isAccepted = isAccepted;
1112
1276
  exports.isNotCalculatedPenaltyStatus = isNotCalculatedPenaltyStatus;
1113
1277
  exports.isPending = isPending;
1114
1278
  exports.isRejected = isRejected;
1279
+ exports.rankToCodeforcesGymDAT = rankToCodeforcesGymDAT;
1115
1280
  exports.stringToSubmissionStatus = stringToSubmissionStatus;
package/dist/index.d.ts CHANGED
@@ -2,6 +2,21 @@ import dayjs from 'dayjs';
2
2
  export { default as dayjs } from 'dayjs';
3
3
  import { SubmissionStatus, Submission as Submission$1, Submissions as Submissions$1, BalloonColor, Problem as Problem$1, Problems as Problems$1, Lang, StatusTimeDisplay, Image, ContestState, Contest as Contest$1, ContestIndex as ContestIndex$1, Team as Team$1, Teams as Teams$1 } from '@xcpcio/types';
4
4
 
5
+ declare enum MedalType {
6
+ UNKNOWN = 0,
7
+ GOLD = 1,
8
+ SILVER = 2,
9
+ BRONZE = 3,
10
+ HONORABLE = 4
11
+ }
12
+ declare class Award {
13
+ medalType: MedalType;
14
+ minRank: number;
15
+ maxRank: number;
16
+ constructor();
17
+ }
18
+ type Awards = Map<string, Award[]>;
19
+
5
20
  declare class Submission {
6
21
  id: string;
7
22
  teamId: string;
@@ -98,6 +113,7 @@ declare class Contest {
98
113
  statusTimeDisplay: StatusTimeDisplay;
99
114
  badge?: string;
100
115
  medal?: Record<string, Record<string, number>>;
116
+ awards?: Awards;
101
117
  organization?: string;
102
118
  group: Map<string, Group>;
103
119
  tag: Map<string, string>;
@@ -134,15 +150,6 @@ type ContestIndexList = Array<ContestIndex>;
134
150
  declare function createContestIndex(contestIndexJSON: ContestIndex$1): ContestIndex;
135
151
  declare function createContestIndexList(contestListJSON: any): ContestIndexList;
136
152
 
137
- declare function getImageSource(image: Image): string;
138
-
139
- declare class RankStatistics {
140
- teamSolvedNum: Array<number>;
141
- maxSolvedProblems: number;
142
- constructor();
143
- reset(): void;
144
- }
145
-
146
153
  declare class PlaceChartPointData {
147
154
  timePoint: number;
148
155
  rank: number;
@@ -170,11 +177,14 @@ declare class Team {
170
177
  problemStatisticsMap: Map<string, TeamProblemStatistics>;
171
178
  submissions: Submissions;
172
179
  placeChartPoints: Array<PlaceChartPointData>;
180
+ awards: MedalType[];
173
181
  constructor();
174
182
  reset(): void;
175
183
  get penaltyToMinute(): number;
176
184
  get dict(): number;
185
+ get membersToString(): string | undefined;
177
186
  calcSolvedData(): void;
187
+ calcAwards(awards?: Award[]): void;
178
188
  isEqualRank(otherTeam: Team): boolean;
179
189
  postProcessPlaceChartPoints(): void;
180
190
  static compare(lhs: Team, rhs: Team): number;
@@ -183,6 +193,13 @@ type Teams = Array<Team>;
183
193
  declare function createTeam(teamJSON: Team$1): Team;
184
194
  declare function createTeams(teamsJSON: Teams$1): Teams;
185
195
 
196
+ declare class RankStatistics {
197
+ teamSolvedNum: Array<number>;
198
+ maxSolvedProblems: number;
199
+ constructor();
200
+ reset(): void;
201
+ }
202
+
186
203
  interface SelectOptionItem {
187
204
  value: string;
188
205
  text: string;
@@ -225,6 +242,10 @@ declare class Rank {
225
242
  getSubmissions(): Submissions;
226
243
  }
227
244
 
245
+ declare function rankToCodeforcesGymDAT(rank: Rank): string;
246
+
247
+ declare function getImageSource(image: Image): string;
248
+
228
249
  declare class ResolverOperation {
229
250
  id: number;
230
251
  team: Team;
@@ -249,4 +270,4 @@ declare function isRejected(status: SubmissionStatus): boolean;
249
270
  declare function isPending(status: SubmissionStatus): boolean;
250
271
  declare function isNotCalculatedPenaltyStatus(status: SubmissionStatus): boolean;
251
272
 
252
- export { Contest, ContestIndex, ContestIndexConfig, ContestIndexList, PlaceChartPointData, Problem, ProblemStatistics, Problems, Rank, RankOptions, RankStatistics, Resolver, SelectOptionItem, Submission, Submissions, Team, TeamProblemStatistics, Teams, calcDict, createContest, createContestIndex, createContestIndexList, createDayJS, createProblem, createProblems, createProblemsByProblemIds, createSubmission, createSubmissions, createTeam, createTeams, getImageSource, getTimeDiff, getTimestamp, isAccepted, isNotCalculatedPenaltyStatus, isPending, isRejected, stringToSubmissionStatus };
273
+ export { Award, Awards, Contest, ContestIndex, ContestIndexConfig, ContestIndexList, MedalType, PlaceChartPointData, Problem, ProblemStatistics, Problems, Rank, RankOptions, RankStatistics, Resolver, SelectOptionItem, Submission, Submissions, Team, TeamProblemStatistics, Teams, calcDict, createContest, createContestIndex, createContestIndexList, createDayJS, createProblem, createProblems, createProblemsByProblemIds, createSubmission, createSubmissions, createTeam, createTeams, getImageSource, getTimeDiff, getTimestamp, isAccepted, isNotCalculatedPenaltyStatus, isPending, isRejected, rankToCodeforcesGymDAT, stringToSubmissionStatus };
package/dist/index.mjs CHANGED
@@ -11,6 +11,22 @@ import relativeTime from 'dayjs/plugin/relativeTime';
11
11
  import { ContestState, SubmissionStatus } from '@xcpcio/types';
12
12
  import _ from 'lodash';
13
13
 
14
+ var MedalType = /* @__PURE__ */ ((MedalType2) => {
15
+ MedalType2[MedalType2["UNKNOWN"] = 0] = "UNKNOWN";
16
+ MedalType2[MedalType2["GOLD"] = 1] = "GOLD";
17
+ MedalType2[MedalType2["SILVER"] = 2] = "SILVER";
18
+ MedalType2[MedalType2["BRONZE"] = 3] = "BRONZE";
19
+ MedalType2[MedalType2["HONORABLE"] = 4] = "HONORABLE";
20
+ return MedalType2;
21
+ })(MedalType || {});
22
+ class Award {
23
+ constructor() {
24
+ this.medalType = 0 /* UNKNOWN */;
25
+ this.minRank = 0;
26
+ this.maxRank = 0;
27
+ }
28
+ }
29
+
14
30
  function calcDict(attemptedNum, solvedNum) {
15
31
  if (solvedNum === 0) {
16
32
  return 0;
@@ -284,6 +300,40 @@ function createContest(contestJSON) {
284
300
  }
285
301
  c.badge = contestJSON.badge;
286
302
  c.medal = contestJSON.medal;
303
+ (() => {
304
+ if (contestJSON.medal === void 0 || contestJSON.medal === null) {
305
+ return;
306
+ }
307
+ c.awards = /* @__PURE__ */ new Map();
308
+ for (const k in contestJSON.medal) {
309
+ const v = contestJSON.medal[k];
310
+ {
311
+ const award = [];
312
+ let rank = 1;
313
+ const work = (key, medalType) => {
314
+ if (Object.keys(v).includes(key)) {
315
+ const a = new Award();
316
+ a.medalType = medalType;
317
+ a.minRank = rank;
318
+ rank += Number(v[key]);
319
+ a.maxRank = rank - 1;
320
+ award.push(a);
321
+ }
322
+ };
323
+ work("gold", MedalType.GOLD);
324
+ work("silver", MedalType.SILVER);
325
+ work("bronze", MedalType.BRONZE);
326
+ {
327
+ const a = new Award();
328
+ a.medalType = MedalType.HONORABLE;
329
+ a.minRank = rank;
330
+ a.maxRank = 1061109567;
331
+ award.push(a);
332
+ }
333
+ c.awards.set(k, award);
334
+ }
335
+ }
336
+ })();
287
337
  c.organization = contestJSON.organization;
288
338
  {
289
339
  const g = new Group();
@@ -374,6 +424,208 @@ function createContestIndexList(contestListJSON) {
374
424
  return contestIndexList;
375
425
  }
376
426
 
427
+ function stringToSubmissionStatus(status) {
428
+ status = status.toUpperCase().replace(" ", "_");
429
+ if (["OK", "AC", SubmissionStatus.ACCEPTED.toString()].includes(status)) {
430
+ return SubmissionStatus.ACCEPTED;
431
+ }
432
+ if ([SubmissionStatus.CORRECT.toString()].includes(status)) {
433
+ return SubmissionStatus.CORRECT;
434
+ }
435
+ if ([SubmissionStatus.PARTIALLY_CORRECT.toString()].includes(status)) {
436
+ return SubmissionStatus.PARTIALLY_CORRECT;
437
+ }
438
+ if (["WA", SubmissionStatus.WRONG_ANSWER.toString()].includes(status)) {
439
+ return SubmissionStatus.WRONG_ANSWER;
440
+ }
441
+ if (["RJ", "INCORRECT", SubmissionStatus.REJECTED.toString()].includes(status)) {
442
+ return SubmissionStatus.REJECTED;
443
+ }
444
+ if (["PD", SubmissionStatus.PENDING.toString()].includes(status)) {
445
+ return SubmissionStatus.PENDING;
446
+ }
447
+ if ([SubmissionStatus.WAITING.toString()].includes(status)) {
448
+ return SubmissionStatus.WAITING;
449
+ }
450
+ if ([SubmissionStatus.JUDGING.toString()].includes(status)) {
451
+ return SubmissionStatus.JUDGING;
452
+ }
453
+ if ([SubmissionStatus.FROZEN.toString()].includes(status)) {
454
+ return SubmissionStatus.FROZEN;
455
+ }
456
+ if (["CE", SubmissionStatus.COMPILE_ERROR.toString()].includes(status)) {
457
+ return SubmissionStatus.COMPILE_ERROR;
458
+ }
459
+ if (["PE", SubmissionStatus.PRESENTATION_ERROR.toString()].includes(status)) {
460
+ return SubmissionStatus.PRESENTATION_ERROR;
461
+ }
462
+ if (["TL", "TLE", SubmissionStatus.TIME_LIMIT_EXCEEDED.toString()].includes(status)) {
463
+ return SubmissionStatus.TIME_LIMIT_EXCEEDED;
464
+ }
465
+ if (["ML", "MLE", SubmissionStatus.MEMORY_LIMIT_EXCEEDED.toString()].includes(status)) {
466
+ return SubmissionStatus.MEMORY_LIMIT_EXCEEDED;
467
+ }
468
+ if (["OL", "OLE", SubmissionStatus.OUTPUT_LIMIT_EXCEEDED.toString()].includes(status)) {
469
+ return SubmissionStatus.OUTPUT_LIMIT_EXCEEDED;
470
+ }
471
+ if (["IL", "ILE", SubmissionStatus.IDLENESS_LIMIT_EXCEEDED.toString()].includes(status)) {
472
+ return SubmissionStatus.IDLENESS_LIMIT_EXCEEDED;
473
+ }
474
+ if (["RT", "RE", "RTE", SubmissionStatus.RUNTIME_ERROR.toString()].includes(status)) {
475
+ return SubmissionStatus.RUNTIME_ERROR;
476
+ }
477
+ if (["JE", SubmissionStatus.JUDGEMENT_FAILED.toString()].includes(status)) {
478
+ return SubmissionStatus.JUDGEMENT_FAILED;
479
+ }
480
+ if (["SE", SubmissionStatus.SYSTEM_ERROR.toString()].includes(status)) {
481
+ return SubmissionStatus.SYSTEM_ERROR;
482
+ }
483
+ if ([SubmissionStatus.HACKED.toString()].includes(status)) {
484
+ return SubmissionStatus.HACKED;
485
+ }
486
+ if ([SubmissionStatus.CONFIGURATION_ERROR.toString()].includes(status)) {
487
+ return SubmissionStatus.CONFIGURATION_ERROR;
488
+ }
489
+ if ([SubmissionStatus.CANCELED.toString()].includes(status)) {
490
+ return SubmissionStatus.CANCELED;
491
+ }
492
+ if ([SubmissionStatus.SKIPPED.toString()].includes(status)) {
493
+ return SubmissionStatus.SKIPPED;
494
+ }
495
+ if ([SubmissionStatus.SECURITY_VIOLATED.toString()].includes(status)) {
496
+ return SubmissionStatus.SECURITY_VIOLATED;
497
+ }
498
+ if ([SubmissionStatus.DENIAL_OF_JUDGEMENT.toString()].includes(status)) {
499
+ return SubmissionStatus.DENIAL_OF_JUDGEMENT;
500
+ }
501
+ return SubmissionStatus.UNKNOWN;
502
+ }
503
+ function isAccepted(status) {
504
+ const acceptedArray = [SubmissionStatus.ACCEPTED, SubmissionStatus.CORRECT];
505
+ return acceptedArray.includes(status);
506
+ }
507
+ function isRejected(status) {
508
+ const rejectArray = [
509
+ SubmissionStatus.RUNTIME_ERROR,
510
+ SubmissionStatus.TIME_LIMIT_EXCEEDED,
511
+ SubmissionStatus.MEMORY_LIMIT_EXCEEDED,
512
+ SubmissionStatus.OUTPUT_LIMIT_EXCEEDED,
513
+ SubmissionStatus.IDLENESS_LIMIT_EXCEEDED,
514
+ SubmissionStatus.WRONG_ANSWER,
515
+ SubmissionStatus.REJECTED,
516
+ SubmissionStatus.JUDGEMENT_FAILED,
517
+ SubmissionStatus.HACKED
518
+ ];
519
+ return rejectArray.includes(status);
520
+ }
521
+ function isPending(status) {
522
+ const pendingArray = [
523
+ SubmissionStatus.PENDING,
524
+ SubmissionStatus.WAITING,
525
+ SubmissionStatus.JUDGING,
526
+ SubmissionStatus.FROZEN
527
+ ];
528
+ return pendingArray.includes(status);
529
+ }
530
+ function isNotCalculatedPenaltyStatus(status) {
531
+ const isNotCalculatedPenaltyArray = [
532
+ SubmissionStatus.COMPILE_ERROR,
533
+ SubmissionStatus.PRESENTATION_ERROR,
534
+ SubmissionStatus.CONFIGURATION_ERROR,
535
+ SubmissionStatus.SYSTEM_ERROR,
536
+ SubmissionStatus.CANCELED,
537
+ SubmissionStatus.SKIPPED,
538
+ SubmissionStatus.UNKNOWN,
539
+ SubmissionStatus.UNDEFINED
540
+ ];
541
+ return isNotCalculatedPenaltyArray.includes(status);
542
+ }
543
+
544
+ function submissionStatusToCodeforcesGymDatStatus(status) {
545
+ if (isAccepted(status)) {
546
+ return "OK";
547
+ }
548
+ if (status === SubmissionStatus.WRONG_ANSWER) {
549
+ return "WA";
550
+ }
551
+ if (status === SubmissionStatus.TIME_LIMIT_EXCEEDED) {
552
+ return "TL";
553
+ }
554
+ if (status === SubmissionStatus.MEMORY_LIMIT_EXCEEDED) {
555
+ return "ML";
556
+ }
557
+ if (status === SubmissionStatus.OUTPUT_LIMIT_EXCEEDED) {
558
+ return "IL";
559
+ }
560
+ if (status === SubmissionStatus.PRESENTATION_ERROR) {
561
+ return "PE";
562
+ }
563
+ if (status === SubmissionStatus.RUNTIME_ERROR) {
564
+ return "RT";
565
+ }
566
+ if (status === SubmissionStatus.COMPILE_ERROR || isNotCalculatedPenaltyStatus(status)) {
567
+ return "CE";
568
+ }
569
+ if (isPending(status)) {
570
+ return "PD";
571
+ }
572
+ return "RJ";
573
+ }
574
+ function rankToCodeforcesGymDAT(rank) {
575
+ let res = "";
576
+ res += `@contest "${rank.contest.name}"
577
+ @contlen ${Math.floor(rank.contest.endTime.diff(rank.contest.startTime) / 1e3 / 60)}
578
+ @problems ${rank.contest.problems.length}
579
+ @teams ${rank.teams.length + 100}
580
+ @submissions ${rank.submissions.length}
581
+ `;
582
+ rank.contest.problems.forEach((p) => {
583
+ res += `@p ${p.label},${p.label},20,0
584
+ `;
585
+ });
586
+ let teamIndex = 1;
587
+ const teamIdMap = /* @__PURE__ */ new Map();
588
+ const submissionsIdMap = /* @__PURE__ */ new Map();
589
+ rank.teams.forEach((team) => {
590
+ let name = team.name;
591
+ if (team.organization) {
592
+ name = `${team.organization} - ${name}`;
593
+ }
594
+ if (team.members) {
595
+ name = `${name} - ${team.membersToString}`;
596
+ }
597
+ res += `@t ${teamIndex},0,1,${name}
598
+ `;
599
+ teamIdMap.set(team.id, teamIndex);
600
+ teamIndex++;
601
+ {
602
+ const mp = /* @__PURE__ */ new Map();
603
+ rank.contest.problems.forEach((p) => {
604
+ mp.set(p.id, 0);
605
+ });
606
+ submissionsIdMap.set(team.id, mp);
607
+ }
608
+ });
609
+ for (let i = 0; i < 100; i++) {
610
+ res += `@t ${teamIndex},0,1,\u041F\u043E\u043F\u043E\u043B\u043D\u0438\u0442\u044C \u043A\u043E\u043C\u0430\u043D\u0434\u0443
611
+ `;
612
+ teamIndex++;
613
+ }
614
+ rank.submissions.forEach((submission) => {
615
+ const teamId = submission.teamId;
616
+ const problemId = submission.problemId;
617
+ const problem = rank.contest.problemsMap.get(problemId);
618
+ if (!problem) {
619
+ return;
620
+ }
621
+ const status = submissionStatusToCodeforcesGymDatStatus(submission.status);
622
+ submissionsIdMap.get(teamId).set(problemId, submissionsIdMap.get(teamId).get(problemId) + 1);
623
+ res += `@s ${teamIdMap.get(teamId)},${problem.label},${submissionsIdMap.get(teamId)?.get(problemId)},${submission.timestamp},${status}
624
+ `;
625
+ });
626
+ return res;
627
+ }
628
+
377
629
  function getImageSource(image) {
378
630
  if (image?.url) {
379
631
  return image.url;
@@ -421,6 +673,7 @@ class Team {
421
673
  this.problemStatisticsMap = /* @__PURE__ */ new Map();
422
674
  this.submissions = [];
423
675
  this.placeChartPoints = [];
676
+ this.awards = [];
424
677
  }
425
678
  reset() {
426
679
  this.rank = 0;
@@ -444,6 +697,12 @@ class Team {
444
697
  const solvedNum = this.solvedProblemNum;
445
698
  return calcDict(attemptedNum, solvedNum);
446
699
  }
700
+ get membersToString() {
701
+ if (typeof this.members === "string") {
702
+ return this.members;
703
+ }
704
+ return this.members?.join(", ");
705
+ }
447
706
  calcSolvedData() {
448
707
  this.solvedProblemNum = 0;
449
708
  this.attemptedProblemNum = 0;
@@ -456,6 +715,16 @@ class Team {
456
715
  }
457
716
  }
458
717
  }
718
+ calcAwards(awards) {
719
+ if (!awards) {
720
+ return;
721
+ }
722
+ for (const award of awards) {
723
+ if (this.rank >= award.minRank && this.rank <= award.maxRank) {
724
+ this.awards.push(award.medalType);
725
+ }
726
+ }
727
+ }
459
728
  isEqualRank(otherTeam) {
460
729
  return this.solvedProblemNum === otherTeam.solvedProblemNum && this.penalty === otherTeam.penalty;
461
730
  }
@@ -514,6 +783,14 @@ function createTeam(teamJSON) {
514
783
  if (Boolean(teamJSON.girl) === true) {
515
784
  t.group.push("girl");
516
785
  }
786
+ {
787
+ const tt = teamJSON;
788
+ for (const key of Object.keys(tt)) {
789
+ if (tt[key] === 1 || tt[key] === true) {
790
+ t.group.push(key);
791
+ }
792
+ }
793
+ }
517
794
  t.group = [...new Set(t.group)];
518
795
  t.group.sort();
519
796
  return t;
@@ -529,123 +806,6 @@ function createTeams(teamsJSON) {
529
806
  }
530
807
  }
531
808
 
532
- function stringToSubmissionStatus(status) {
533
- status = status.toUpperCase().replace(" ", "_");
534
- if (["OK", "AC", SubmissionStatus.ACCEPTED.toString()].includes(status)) {
535
- return SubmissionStatus.ACCEPTED;
536
- }
537
- if ([SubmissionStatus.CORRECT.toString()].includes(status)) {
538
- return SubmissionStatus.CORRECT;
539
- }
540
- if ([SubmissionStatus.PARTIALLY_CORRECT.toString()].includes(status)) {
541
- return SubmissionStatus.PARTIALLY_CORRECT;
542
- }
543
- if (["WA", SubmissionStatus.WRONG_ANSWER.toString()].includes(status)) {
544
- return SubmissionStatus.WRONG_ANSWER;
545
- }
546
- if (["RJ", "INCORRECT", SubmissionStatus.REJECTED.toString()].includes(status)) {
547
- return SubmissionStatus.REJECTED;
548
- }
549
- if (["PD", SubmissionStatus.PENDING.toString()].includes(status)) {
550
- return SubmissionStatus.PENDING;
551
- }
552
- if ([SubmissionStatus.WAITING.toString()].includes(status)) {
553
- return SubmissionStatus.WAITING;
554
- }
555
- if ([SubmissionStatus.JUDGING.toString()].includes(status)) {
556
- return SubmissionStatus.JUDGING;
557
- }
558
- if ([SubmissionStatus.FROZEN.toString()].includes(status)) {
559
- return SubmissionStatus.FROZEN;
560
- }
561
- if (["CE", SubmissionStatus.COMPILE_ERROR.toString()].includes(status)) {
562
- return SubmissionStatus.COMPILE_ERROR;
563
- }
564
- if (["PE", SubmissionStatus.PRESENTATION_ERROR.toString()].includes(status)) {
565
- return SubmissionStatus.PRESENTATION_ERROR;
566
- }
567
- if (["TL", "TLE", SubmissionStatus.TIME_LIMIT_EXCEEDED.toString()].includes(status)) {
568
- return SubmissionStatus.TIME_LIMIT_EXCEEDED;
569
- }
570
- if (["ML", "MLE", SubmissionStatus.MEMORY_LIMIT_EXCEEDED.toString()].includes(status)) {
571
- return SubmissionStatus.MEMORY_LIMIT_EXCEEDED;
572
- }
573
- if (["OL", "OLE", SubmissionStatus.OUTPUT_LIMIT_EXCEEDED.toString()].includes(status)) {
574
- return SubmissionStatus.OUTPUT_LIMIT_EXCEEDED;
575
- }
576
- if (["IL", "ILE", SubmissionStatus.IDLENESS_LIMIT_EXCEEDED.toString()].includes(status)) {
577
- return SubmissionStatus.IDLENESS_LIMIT_EXCEEDED;
578
- }
579
- if (["RT", "RE", "RTE", SubmissionStatus.RUNTIME_ERROR.toString()].includes(status)) {
580
- return SubmissionStatus.RUNTIME_ERROR;
581
- }
582
- if (["JE", SubmissionStatus.JUDGEMENT_FAILED.toString()].includes(status)) {
583
- return SubmissionStatus.JUDGEMENT_FAILED;
584
- }
585
- if (["SE", SubmissionStatus.SYSTEM_ERROR.toString()].includes(status)) {
586
- return SubmissionStatus.SYSTEM_ERROR;
587
- }
588
- if ([SubmissionStatus.HACKED.toString()].includes(status)) {
589
- return SubmissionStatus.HACKED;
590
- }
591
- if ([SubmissionStatus.CONFIGURATION_ERROR.toString()].includes(status)) {
592
- return SubmissionStatus.CONFIGURATION_ERROR;
593
- }
594
- if ([SubmissionStatus.CANCELED.toString()].includes(status)) {
595
- return SubmissionStatus.CANCELED;
596
- }
597
- if ([SubmissionStatus.SKIPPED.toString()].includes(status)) {
598
- return SubmissionStatus.SKIPPED;
599
- }
600
- if ([SubmissionStatus.SECURITY_VIOLATED.toString()].includes(status)) {
601
- return SubmissionStatus.SECURITY_VIOLATED;
602
- }
603
- if ([SubmissionStatus.DENIAL_OF_JUDGEMENT.toString()].includes(status)) {
604
- return SubmissionStatus.DENIAL_OF_JUDGEMENT;
605
- }
606
- return SubmissionStatus.UNKNOWN;
607
- }
608
- function isAccepted(status) {
609
- const acceptedArray = [SubmissionStatus.ACCEPTED, SubmissionStatus.CORRECT];
610
- return acceptedArray.includes(status);
611
- }
612
- function isRejected(status) {
613
- const rejectArray = [
614
- SubmissionStatus.RUNTIME_ERROR,
615
- SubmissionStatus.TIME_LIMIT_EXCEEDED,
616
- SubmissionStatus.MEMORY_LIMIT_EXCEEDED,
617
- SubmissionStatus.OUTPUT_LIMIT_EXCEEDED,
618
- SubmissionStatus.IDLENESS_LIMIT_EXCEEDED,
619
- SubmissionStatus.WRONG_ANSWER,
620
- SubmissionStatus.REJECTED,
621
- SubmissionStatus.JUDGEMENT_FAILED,
622
- SubmissionStatus.HACKED
623
- ];
624
- return rejectArray.includes(status);
625
- }
626
- function isPending(status) {
627
- const pendingArray = [
628
- SubmissionStatus.PENDING,
629
- SubmissionStatus.WAITING,
630
- SubmissionStatus.JUDGING,
631
- SubmissionStatus.FROZEN
632
- ];
633
- return pendingArray.includes(status);
634
- }
635
- function isNotCalculatedPenaltyStatus(status) {
636
- const isNotCalculatedPenaltyArray = [
637
- SubmissionStatus.COMPILE_ERROR,
638
- SubmissionStatus.PRESENTATION_ERROR,
639
- SubmissionStatus.CONFIGURATION_ERROR,
640
- SubmissionStatus.SYSTEM_ERROR,
641
- SubmissionStatus.CANCELED,
642
- SubmissionStatus.SKIPPED,
643
- SubmissionStatus.UNKNOWN,
644
- SubmissionStatus.UNDEFINED
645
- ];
646
- return isNotCalculatedPenaltyArray.includes(status);
647
- }
648
-
649
809
  class Submission {
650
810
  constructor() {
651
811
  this.status = SubmissionStatus.UNKNOWN;
@@ -712,7 +872,7 @@ class RankOptions {
712
872
  this.width = 0;
713
873
  this.timestamp = 0;
714
874
  this.enableFilterTeamsByGroup = false;
715
- this.group = "";
875
+ this.group = "all";
716
876
  this.filterOrganizations = [];
717
877
  this.filterOrganizationMap = /* @__PURE__ */ new Map();
718
878
  this.filterTeams = [];
@@ -735,6 +895,7 @@ class RankOptions {
735
895
  }
736
896
  disableFilterTeamsByGroup() {
737
897
  this.enableFilterTeamsByGroup = false;
898
+ this.group = "all";
738
899
  }
739
900
  setFilterOrganizations(filterOrganizations) {
740
901
  const m = /* @__PURE__ */ new Map();
@@ -892,6 +1053,7 @@ class Rank {
892
1053
  this.teams.sort(Team.compare);
893
1054
  this.buildTeamRank();
894
1055
  this.buildOrgRank();
1056
+ this.teams.forEach((t) => t.calcAwards(this.contest.awards?.get(this.options.group)));
895
1057
  this.teams.forEach((t) => t.postProcessPlaceChartPoints());
896
1058
  })();
897
1059
  (() => {
@@ -1063,4 +1225,4 @@ class Resolver extends Rank {
1063
1225
  }
1064
1226
  }
1065
1227
 
1066
- export { Contest, ContestIndex, ContestIndexConfig, PlaceChartPointData, Problem, ProblemStatistics, Rank, RankOptions, RankStatistics, Resolver, Submission, Team, TeamProblemStatistics, calcDict, createContest, createContestIndex, createContestIndexList, createDayJS, createProblem, createProblems, createProblemsByProblemIds, createSubmission, createSubmissions, createTeam, createTeams, getImageSource, getTimeDiff, getTimestamp, isAccepted, isNotCalculatedPenaltyStatus, isPending, isRejected, stringToSubmissionStatus };
1228
+ export { Award, Contest, ContestIndex, ContestIndexConfig, MedalType, PlaceChartPointData, Problem, ProblemStatistics, Rank, RankOptions, RankStatistics, Resolver, Submission, Team, TeamProblemStatistics, calcDict, createContest, createContestIndex, createContestIndexList, createDayJS, createProblem, createProblems, createProblemsByProblemIds, createSubmission, createSubmissions, createTeam, createTeams, getImageSource, getTimeDiff, getTimestamp, isAccepted, isNotCalculatedPenaltyStatus, isPending, isRejected, rankToCodeforcesGymDAT, stringToSubmissionStatus };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xcpcio/core",
3
- "version": "0.7.2",
3
+ "version": "0.9.0",
4
4
  "description": "XCPCIO Core",
5
5
  "author": "Dup4 <lyuzhi.pan@gmail.com>",
6
6
  "license": "MIT",
@@ -42,7 +42,7 @@
42
42
  "dependencies": {
43
43
  "dayjs": "^1.11.8",
44
44
  "lodash": "^4.17.21",
45
- "@xcpcio/types": "0.7.2"
45
+ "@xcpcio/types": "0.9.0"
46
46
  },
47
47
  "devDependencies": {
48
48
  "@babel/types": "^7.22.4",
package/src/award.ts ADDED
@@ -0,0 +1,21 @@
1
+ export enum MedalType {
2
+ UNKNOWN,
3
+ GOLD,
4
+ SILVER,
5
+ BRONZE,
6
+ HONORABLE,
7
+ }
8
+
9
+ export class Award {
10
+ medalType: MedalType;
11
+ minRank: number;
12
+ maxRank: number;
13
+
14
+ constructor() {
15
+ this.medalType = MedalType.UNKNOWN;
16
+ this.minRank = 0;
17
+ this.maxRank = 0;
18
+ }
19
+ }
20
+
21
+ export type Awards = Map<string, Award[]>;
package/src/contest.ts CHANGED
@@ -5,6 +5,8 @@ import type { Problem, Problems } from "./problem";
5
5
  import { createProblems, createProblemsByProblemIds } from "./problem";
6
6
  import { createDayJS, dayjs, getTimeDiff } from "./utils";
7
7
  import { Group } from "./group";
8
+ import { Award } from "./award";
9
+ import { type Awards, MedalType } from "./award";
8
10
 
9
11
  export class Contest {
10
12
  name = "";
@@ -26,6 +28,7 @@ export class Contest {
26
28
 
27
29
  badge?: string;
28
30
  medal?: Record<string, Record<string, number>>;
31
+ awards?: Awards;
29
32
  organization?: string;
30
33
 
31
34
  group: Map<string, Group>;
@@ -189,6 +192,49 @@ export function createContest(contestJSON: IContest): Contest {
189
192
 
190
193
  c.badge = contestJSON.badge;
191
194
  c.medal = contestJSON.medal;
195
+
196
+ (() => {
197
+ if (contestJSON.medal === undefined || contestJSON.medal === null) {
198
+ return;
199
+ }
200
+
201
+ c.awards = new Map<string, Award[]>();
202
+
203
+ for (const k in contestJSON.medal) {
204
+ const v = contestJSON.medal[k];
205
+
206
+ {
207
+ const award: Award[] = [];
208
+
209
+ let rank = 1;
210
+ const work = (key: string, medalType: MedalType) => {
211
+ if (Object.keys(v).includes(key)) {
212
+ const a = new Award();
213
+ a.medalType = medalType;
214
+ a.minRank = rank;
215
+ rank += Number(v[key]);
216
+ a.maxRank = rank - 1;
217
+ award.push(a);
218
+ }
219
+ };
220
+
221
+ work("gold", MedalType.GOLD);
222
+ work("silver", MedalType.SILVER);
223
+ work("bronze", MedalType.BRONZE);
224
+
225
+ {
226
+ const a = new Award();
227
+ a.medalType = MedalType.HONORABLE;
228
+ a.minRank = rank;
229
+ a.maxRank = 0x3F3F3F3F;
230
+ award.push(a);
231
+ }
232
+
233
+ c.awards.set(k, award);
234
+ }
235
+ }
236
+ })();
237
+
192
238
  c.organization = contestJSON.organization;
193
239
 
194
240
  {
package/src/export.ts ADDED
@@ -0,0 +1,114 @@
1
+ import { SubmissionStatus } from "@xcpcio/types";
2
+
3
+ import type { Rank } from "./rank";
4
+
5
+ import {
6
+ isAccepted,
7
+ isNotCalculatedPenaltyStatus,
8
+ isPending,
9
+ } from "./submission-status";
10
+
11
+ function submissionStatusToCodeforcesGymDatStatus(status: SubmissionStatus): string {
12
+ if (isAccepted(status)) {
13
+ return "OK";
14
+ }
15
+
16
+ if (status === SubmissionStatus.WRONG_ANSWER) {
17
+ return "WA";
18
+ }
19
+
20
+ if (status === SubmissionStatus.TIME_LIMIT_EXCEEDED) {
21
+ return "TL";
22
+ }
23
+
24
+ if (status === SubmissionStatus.MEMORY_LIMIT_EXCEEDED) {
25
+ return "ML";
26
+ }
27
+
28
+ if (status === SubmissionStatus.OUTPUT_LIMIT_EXCEEDED) {
29
+ return "IL";
30
+ }
31
+
32
+ if (status === SubmissionStatus.PRESENTATION_ERROR) {
33
+ return "PE";
34
+ }
35
+
36
+ if (status === SubmissionStatus.RUNTIME_ERROR) {
37
+ return "RT";
38
+ }
39
+
40
+ if (status === SubmissionStatus.COMPILE_ERROR || isNotCalculatedPenaltyStatus(status)) {
41
+ return "CE";
42
+ }
43
+
44
+ if (isPending(status)) {
45
+ return "PD";
46
+ }
47
+
48
+ return "RJ";
49
+ }
50
+
51
+ export function rankToCodeforcesGymDAT(rank: Rank) {
52
+ let res = "";
53
+
54
+ res += `@contest "${rank.contest.name}"
55
+ @contlen ${Math.floor(rank.contest.endTime.diff(rank.contest.startTime) / 1000 / 60)}
56
+ @problems ${rank.contest.problems.length}
57
+ @teams ${rank.teams.length + 100}
58
+ @submissions ${rank.submissions.length}
59
+ `;
60
+
61
+ rank.contest.problems.forEach((p) => {
62
+ res += `@p ${p.label},${p.label},20,0\n`;
63
+ });
64
+
65
+ let teamIndex = 1;
66
+ const teamIdMap = new Map<string, number>();
67
+ const submissionsIdMap = new Map<string, Map<string, number>>();
68
+
69
+ rank.teams.forEach((team) => {
70
+ let name = team.name;
71
+
72
+ if (team.organization) {
73
+ name = `${team.organization} - ${name}`;
74
+ }
75
+
76
+ if (team.members) {
77
+ name = `${name} - ${team.membersToString}`;
78
+ }
79
+
80
+ res += `@t ${teamIndex},0,1,${name}\n`;
81
+ teamIdMap.set(team.id, teamIndex);
82
+ teamIndex++;
83
+
84
+ {
85
+ const mp = new Map<string, number>();
86
+ rank.contest.problems.forEach((p) => {
87
+ mp.set(p.id, 0);
88
+ });
89
+ submissionsIdMap.set(team.id, mp);
90
+ }
91
+ });
92
+
93
+ for (let i = 0; i < 100; i++) {
94
+ res += `@t ${teamIndex},0,1,Пополнить команду\n`;
95
+ teamIndex++;
96
+ }
97
+
98
+ rank.submissions.forEach((submission) => {
99
+ const teamId = submission.teamId;
100
+ const problemId = submission.problemId;
101
+ const problem = rank.contest.problemsMap.get(problemId);
102
+
103
+ if (!problem) {
104
+ return;
105
+ }
106
+
107
+ const status = submissionStatusToCodeforcesGymDatStatus(submission.status);
108
+ submissionsIdMap.get(teamId)!.set(problemId, submissionsIdMap.get(teamId)!.get(problemId)! + 1);
109
+
110
+ res += `@s ${teamIdMap.get(teamId)},${problem.label},${submissionsIdMap.get(teamId)?.get(problemId)},${submission.timestamp},${status}\n`;
111
+ });
112
+
113
+ return res;
114
+ }
package/src/index.ts CHANGED
@@ -1,6 +1,8 @@
1
+ export * from "./award";
1
2
  export * from "./contest-index";
2
3
  export * from "./utils";
3
4
  export * from "./contest";
5
+ export * from "./export";
4
6
  export * from "./image";
5
7
  export * from "./problem";
6
8
  export * from "./rank-statistics";
package/src/rank.ts CHANGED
@@ -32,7 +32,7 @@ export class RankOptions {
32
32
  this.timestamp = 0;
33
33
 
34
34
  this.enableFilterTeamsByGroup = false;
35
- this.group = "";
35
+ this.group = "all";
36
36
 
37
37
  this.filterOrganizations = [];
38
38
  this.filterOrganizationMap = new Map<string, SelectOptionItem>();
@@ -62,6 +62,7 @@ export class RankOptions {
62
62
 
63
63
  disableFilterTeamsByGroup() {
64
64
  this.enableFilterTeamsByGroup = false;
65
+ this.group = "all";
65
66
  }
66
67
 
67
68
  setFilterOrganizations(filterOrganizations: Array<SelectOptionItem>) {
@@ -285,6 +286,7 @@ export class Rank {
285
286
  this.buildTeamRank();
286
287
  this.buildOrgRank();
287
288
 
289
+ this.teams.forEach(t => t.calcAwards(this.contest.awards?.get(this.options.group)));
288
290
  this.teams.forEach(t => t.postProcessPlaceChartPoints());
289
291
  })();
290
292
 
package/src/team.ts CHANGED
@@ -3,6 +3,7 @@ import type { Team as ITeam, Teams as ITeams, Image } from "@xcpcio/types";
3
3
  import type { Problem, TeamProblemStatistics } from "./problem";
4
4
  import { calcDict } from "./utils";
5
5
  import type { Submissions } from "./submission";
6
+ import type { Award, MedalType } from "./award";
6
7
 
7
8
  export class PlaceChartPointData {
8
9
  timePoint: number;
@@ -48,6 +49,8 @@ export class Team {
48
49
 
49
50
  placeChartPoints: Array<PlaceChartPointData>;
50
51
 
52
+ awards: MedalType[];
53
+
51
54
  constructor() {
52
55
  this.id = "";
53
56
  this.name = "";
@@ -75,6 +78,8 @@ export class Team {
75
78
  this.submissions = [];
76
79
 
77
80
  this.placeChartPoints = [];
81
+
82
+ this.awards = [];
78
83
  }
79
84
 
80
85
  reset() {
@@ -109,6 +114,14 @@ export class Team {
109
114
  return calcDict(attemptedNum, solvedNum);
110
115
  }
111
116
 
117
+ get membersToString() {
118
+ if (typeof this.members === "string") {
119
+ return this.members;
120
+ }
121
+
122
+ return this.members?.join(", ");
123
+ }
124
+
112
125
  calcSolvedData() {
113
126
  this.solvedProblemNum = 0;
114
127
  this.attemptedProblemNum = 0;
@@ -125,6 +138,18 @@ export class Team {
125
138
  }
126
139
  }
127
140
 
141
+ calcAwards(awards?: Award[]) {
142
+ if (!awards) {
143
+ return;
144
+ }
145
+
146
+ for (const award of awards) {
147
+ if (this.rank >= award.minRank && this.rank <= award.maxRank) {
148
+ this.awards.push(award.medalType);
149
+ }
150
+ }
151
+ }
152
+
128
153
  isEqualRank(otherTeam: Team) {
129
154
  return this.solvedProblemNum === otherTeam.solvedProblemNum && this.penalty === otherTeam.penalty;
130
155
  }
@@ -205,6 +230,15 @@ export function createTeam(teamJSON: ITeam): Team {
205
230
  t.group.push("girl");
206
231
  }
207
232
 
233
+ {
234
+ const tt: any = teamJSON as any;
235
+ for (const key of Object.keys(tt)) {
236
+ if (tt[key] === 1 || tt[key] === true) {
237
+ t.group.push(key);
238
+ }
239
+ }
240
+ }
241
+
208
242
  t.group = [...new Set(t.group)];
209
243
  t.group.sort();
210
244