@xcpcio/core 0.23.0 → 0.24.3

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.mjs CHANGED
@@ -527,17 +527,251 @@ class TeamProblemStatistics {
527
527
  get isUnSubmitted() {
528
528
  return this.totalCount === 0;
529
529
  }
530
+ get solvedTimestampToMinute() {
531
+ return Math.floor(this.solvedTimestamp / 60);
532
+ }
530
533
  get penalty() {
531
534
  if (this.isSolved === false) {
532
535
  return 0;
533
536
  }
534
- return Math.floor(this.solvedTimestamp / 60) * 60 + this.failedCount * this.contestPenalty;
537
+ return this.solvedTimestampToMinute * 60 + this.failedCount * this.contestPenalty;
535
538
  }
536
539
  get penaltyToMinute() {
537
540
  return Math.floor(this.penalty / 60);
538
541
  }
539
- get solvedTimestampToMinute() {
540
- return Math.floor(this.solvedTimestamp / 60);
542
+ }
543
+
544
+ class PlaceChartPointData {
545
+ constructor() {
546
+ this.timePoint = 0;
547
+ this.rank = 0;
548
+ this.lastSolvedProblem = null;
549
+ }
550
+ }
551
+ class Team {
552
+ constructor() {
553
+ this.id = "";
554
+ this.name = "";
555
+ this.organization = "";
556
+ this.group = [];
557
+ this.tag = [];
558
+ this.rank = 0;
559
+ this.originalRank = 0;
560
+ this.organizationRank = -1;
561
+ this.solvedProblemNum = 0;
562
+ this.attemptedProblemNum = 0;
563
+ this.lastSolvedProblem = null;
564
+ this.lastSolvedProblemTimestamp = 0;
565
+ this.penalty = 0;
566
+ this.problemStatistics = [];
567
+ this.problemStatisticsMap = /* @__PURE__ */ new Map();
568
+ this.submissions = [];
569
+ this.placeChartPoints = [];
570
+ this.awards = [];
571
+ }
572
+ reset() {
573
+ this.rank = 0;
574
+ this.originalRank = 0;
575
+ this.organizationRank = -1;
576
+ this.solvedProblemNum = 0;
577
+ this.attemptedProblemNum = 0;
578
+ this.lastSolvedProblem = null;
579
+ this.lastSolvedProblemTimestamp = 0;
580
+ this.penalty = 0;
581
+ this.problemStatistics = [];
582
+ this.problemStatisticsMap = /* @__PURE__ */ new Map();
583
+ this.submissions = [];
584
+ this.placeChartPoints = [];
585
+ this.awards = [];
586
+ }
587
+ get penaltyToMinute() {
588
+ return Math.floor(this.penalty / 60);
589
+ }
590
+ get dirt() {
591
+ const attemptedNum = this.attemptedProblemNum;
592
+ const solvedNum = this.solvedProblemNum;
593
+ return calcDirt(attemptedNum, solvedNum);
594
+ }
595
+ get membersToString() {
596
+ if (typeof this.members === "string") {
597
+ return this.members;
598
+ }
599
+ return this.members?.join(", ");
600
+ }
601
+ calcSolvedData() {
602
+ this.solvedProblemNum = 0;
603
+ this.attemptedProblemNum = 0;
604
+ this.penalty = 0;
605
+ for (const p of this.problemStatistics) {
606
+ if (p.isAccepted) {
607
+ this.solvedProblemNum++;
608
+ this.attemptedProblemNum += p.failedCount + 1;
609
+ this.penalty += p.penalty;
610
+ }
611
+ }
612
+ }
613
+ calcAwards(awards) {
614
+ if (!awards) {
615
+ return;
616
+ }
617
+ for (const award of awards) {
618
+ if (this.rank >= award.minRank && this.rank <= award.maxRank) {
619
+ this.awards.push(award.medalType);
620
+ }
621
+ }
622
+ }
623
+ isEqualRank(otherTeam) {
624
+ return this.solvedProblemNum === otherTeam.solvedProblemNum && this.penalty === otherTeam.penalty;
625
+ }
626
+ postProcessPlaceChartPoints() {
627
+ if (this.placeChartPoints.length === 0) {
628
+ return;
629
+ }
630
+ const res = [];
631
+ res.push(this.placeChartPoints[0]);
632
+ for (let i = 1; i < this.placeChartPoints.length - 1; i++) {
633
+ const p = this.placeChartPoints[i];
634
+ const preP = res[res.length - 1];
635
+ if (p.rank !== preP.rank || p.lastSolvedProblem !== preP.lastSolvedProblem) {
636
+ res.push(p);
637
+ }
638
+ }
639
+ if (this.placeChartPoints.length > 1) {
640
+ res.push(this.placeChartPoints[this.placeChartPoints.length - 1]);
641
+ }
642
+ this.placeChartPoints = res;
643
+ }
644
+ static compare(lhs, rhs) {
645
+ if (lhs.solvedProblemNum !== rhs.solvedProblemNum) {
646
+ return rhs.solvedProblemNum - lhs.solvedProblemNum;
647
+ }
648
+ if (lhs.penalty !== rhs.penalty) {
649
+ return lhs.penalty - rhs.penalty;
650
+ }
651
+ if (lhs.lastSolvedProblemTimestamp !== rhs.lastSolvedProblemTimestamp) {
652
+ return lhs.lastSolvedProblemTimestamp - rhs.lastSolvedProblemTimestamp;
653
+ }
654
+ if (lhs.name < rhs.name) {
655
+ return -1;
656
+ } else if (lhs.name > rhs.name) {
657
+ return 1;
658
+ }
659
+ return 0;
660
+ }
661
+ }
662
+ function createTeam(teamJSON) {
663
+ const t = new Team();
664
+ t.id = teamJSON.id ?? teamJSON.team_id ?? "";
665
+ t.name = teamJSON.name ?? teamJSON.team_name ?? "";
666
+ t.organization = teamJSON.organization ?? "";
667
+ t.badge = teamJSON.badge;
668
+ t.group = teamJSON.group ?? [];
669
+ t.tag = teamJSON.group ?? [];
670
+ t.coach = teamJSON.coach;
671
+ t.members = teamJSON.members;
672
+ if (Boolean(teamJSON.official) === true) {
673
+ t.group.push("official");
674
+ }
675
+ if (Boolean(teamJSON.unofficial) === true) {
676
+ t.group.push("unofficial");
677
+ }
678
+ if (Boolean(teamJSON.girl) === true) {
679
+ t.group.push("girl");
680
+ }
681
+ {
682
+ const tt = teamJSON;
683
+ for (const key of Object.keys(tt)) {
684
+ if (tt[key] === 1 || tt[key] === true) {
685
+ t.group.push(key);
686
+ }
687
+ }
688
+ }
689
+ t.group = [...new Set(t.group)];
690
+ t.group.sort();
691
+ if (teamJSON.location) {
692
+ t.location = teamJSON.location;
693
+ }
694
+ return t;
695
+ }
696
+ function createTeams(teamsJSON) {
697
+ if (Array.isArray(teamsJSON)) {
698
+ return teamsJSON.map((t) => createTeam(t));
699
+ } else {
700
+ const teams = Object.entries(teamsJSON).map(
701
+ ([teamId, team]) => createTeam({ ...team, team_id: team.team_id ?? teamId })
702
+ );
703
+ return teams;
704
+ }
705
+ }
706
+
707
+ class Submission {
708
+ constructor() {
709
+ this.status = SubmissionStatus.UNKNOWN;
710
+ this.isIgnore = false;
711
+ this.id = "";
712
+ this.teamId = "";
713
+ this.problemId = "";
714
+ this.timestamp = 0;
715
+ }
716
+ isAccepted() {
717
+ return isAccepted(this.status);
718
+ }
719
+ isRejected() {
720
+ return isRejected(this.status);
721
+ }
722
+ isPending() {
723
+ return isPending(this.status);
724
+ }
725
+ isNotCalculatedPenaltyStatus() {
726
+ return isNotCalculatedPenaltyStatus(this.status);
727
+ }
728
+ get timestampToMinute() {
729
+ return Math.floor(this.timestamp / 60);
730
+ }
731
+ static compare(lhs, rhs) {
732
+ if (lhs.timestamp !== rhs.timestamp) {
733
+ return lhs.timestamp - rhs.timestamp;
734
+ }
735
+ if (lhs.teamId === rhs.teamId) {
736
+ if (lhs.isAccepted() && !rhs.isAccepted()) {
737
+ return -1;
738
+ }
739
+ if (!lhs.isAccepted() && rhs.isAccepted()) {
740
+ return 1;
741
+ }
742
+ }
743
+ return 0;
744
+ }
745
+ }
746
+ function createSubmission(submissionJSON) {
747
+ const s = new Submission();
748
+ s.id = String(submissionJSON.id ?? submissionJSON.submission_id ?? "");
749
+ s.teamId = String(submissionJSON.team_id);
750
+ s.problemId = String(submissionJSON.problem_id);
751
+ s.timestamp = submissionJSON.timestamp;
752
+ s.status = stringToSubmissionStatus(submissionJSON.status);
753
+ s.isIgnore = submissionJSON.is_ignore ?? false;
754
+ return s;
755
+ }
756
+ function createSubmissions(submissionsJSON) {
757
+ if (Array.isArray(submissionsJSON)) {
758
+ return submissionsJSON.map((s, index) => createSubmission({ ...s, id: s.submission_id ?? String(index) }));
759
+ } else {
760
+ const submissions = Object.entries(submissionsJSON).map(
761
+ ([submissionId, s]) => createSubmission({ ...s, id: s.submission_id ?? submissionId })
762
+ );
763
+ return submissions;
764
+ }
765
+ }
766
+
767
+ class Balloon {
768
+ constructor() {
769
+ this.problem = new Problem();
770
+ this.team = new Team();
771
+ this.submission = new Submission();
772
+ }
773
+ get key() {
774
+ return `balloon-${this.team.id}-${this.problem.id}`;
541
775
  }
542
776
  }
543
777
 
@@ -810,234 +1044,16 @@ function getImageSource(image) {
810
1044
  class RankStatistics {
811
1045
  constructor() {
812
1046
  this.teamSolvedNum = [];
1047
+ this.teamSolvedNumIndex = [];
813
1048
  this.maxSolvedProblems = 0;
814
1049
  }
815
1050
  reset() {
816
1051
  this.teamSolvedNum = [];
1052
+ this.teamSolvedNumIndex = [];
817
1053
  this.maxSolvedProblems = 0;
818
1054
  }
819
- }
820
-
821
- class PlaceChartPointData {
822
- constructor() {
823
- this.timePoint = 0;
824
- this.rank = 0;
825
- this.lastSolvedProblem = null;
826
- }
827
- }
828
- class Team {
829
- constructor() {
830
- this.id = "";
831
- this.name = "";
832
- this.organization = "";
833
- this.group = [];
834
- this.tag = [];
835
- this.rank = 0;
836
- this.originalRank = 0;
837
- this.organizationRank = -1;
838
- this.solvedProblemNum = 0;
839
- this.attemptedProblemNum = 0;
840
- this.lastSolvedProblem = null;
841
- this.lastSolvedProblemTimestamp = 0;
842
- this.penalty = 0;
843
- this.problemStatistics = [];
844
- this.problemStatisticsMap = /* @__PURE__ */ new Map();
845
- this.submissions = [];
846
- this.placeChartPoints = [];
847
- this.awards = [];
848
- }
849
- reset() {
850
- this.rank = 0;
851
- this.originalRank = 0;
852
- this.organizationRank = -1;
853
- this.solvedProblemNum = 0;
854
- this.attemptedProblemNum = 0;
855
- this.lastSolvedProblem = null;
856
- this.lastSolvedProblemTimestamp = 0;
857
- this.penalty = 0;
858
- this.problemStatistics = [];
859
- this.problemStatisticsMap = /* @__PURE__ */ new Map();
860
- this.submissions = [];
861
- this.placeChartPoints = [];
862
- this.awards = [];
863
- }
864
- get penaltyToMinute() {
865
- return Math.floor(this.penalty / 60);
866
- }
867
- get dirt() {
868
- const attemptedNum = this.attemptedProblemNum;
869
- const solvedNum = this.solvedProblemNum;
870
- return calcDirt(attemptedNum, solvedNum);
871
- }
872
- get membersToString() {
873
- if (typeof this.members === "string") {
874
- return this.members;
875
- }
876
- return this.members?.join(", ");
877
- }
878
- calcSolvedData() {
879
- this.solvedProblemNum = 0;
880
- this.attemptedProblemNum = 0;
881
- this.penalty = 0;
882
- for (const p of this.problemStatistics) {
883
- if (p.isAccepted) {
884
- this.solvedProblemNum++;
885
- this.attemptedProblemNum += p.failedCount + 1;
886
- this.penalty += p.penalty;
887
- }
888
- }
889
- }
890
- calcAwards(awards) {
891
- if (!awards) {
892
- return;
893
- }
894
- for (const award of awards) {
895
- if (this.rank >= award.minRank && this.rank <= award.maxRank) {
896
- this.awards.push(award.medalType);
897
- }
898
- }
899
- }
900
- isEqualRank(otherTeam) {
901
- return this.solvedProblemNum === otherTeam.solvedProblemNum && this.penalty === otherTeam.penalty;
902
- }
903
- postProcessPlaceChartPoints() {
904
- if (this.placeChartPoints.length === 0) {
905
- return;
906
- }
907
- const res = [];
908
- res.push(this.placeChartPoints[0]);
909
- for (let i = 1; i < this.placeChartPoints.length - 1; i++) {
910
- const p = this.placeChartPoints[i];
911
- const preP = res[res.length - 1];
912
- if (p.rank !== preP.rank || p.lastSolvedProblem !== preP.lastSolvedProblem) {
913
- res.push(p);
914
- }
915
- }
916
- if (this.placeChartPoints.length > 1) {
917
- res.push(this.placeChartPoints[this.placeChartPoints.length - 1]);
918
- }
919
- this.placeChartPoints = res;
920
- }
921
- static compare(lhs, rhs) {
922
- if (lhs.solvedProblemNum !== rhs.solvedProblemNum) {
923
- return rhs.solvedProblemNum - lhs.solvedProblemNum;
924
- }
925
- if (lhs.penalty !== rhs.penalty) {
926
- return lhs.penalty - rhs.penalty;
927
- }
928
- if (lhs.lastSolvedProblemTimestamp !== rhs.lastSolvedProblemTimestamp) {
929
- return lhs.lastSolvedProblemTimestamp - rhs.lastSolvedProblemTimestamp;
930
- }
931
- if (lhs.name < rhs.name) {
932
- return -1;
933
- } else if (lhs.name > rhs.name) {
934
- return 1;
935
- }
936
- return 0;
937
- }
938
- }
939
- function createTeam(teamJSON) {
940
- const t = new Team();
941
- t.id = teamJSON.id ?? teamJSON.team_id ?? "";
942
- t.name = teamJSON.name ?? teamJSON.team_name ?? "";
943
- t.organization = teamJSON.organization ?? "";
944
- t.badge = teamJSON.badge;
945
- t.group = teamJSON.group ?? [];
946
- t.tag = teamJSON.group ?? [];
947
- t.coach = teamJSON.coach;
948
- t.members = teamJSON.members;
949
- if (Boolean(teamJSON.official) === true) {
950
- t.group.push("official");
951
- }
952
- if (Boolean(teamJSON.unofficial) === true) {
953
- t.group.push("unofficial");
954
- }
955
- if (Boolean(teamJSON.girl) === true) {
956
- t.group.push("girl");
957
- }
958
- {
959
- const tt = teamJSON;
960
- for (const key of Object.keys(tt)) {
961
- if (tt[key] === 1 || tt[key] === true) {
962
- t.group.push(key);
963
- }
964
- }
965
- }
966
- t.group = [...new Set(t.group)];
967
- t.group.sort();
968
- if (teamJSON.location) {
969
- t.location = teamJSON.location;
970
- }
971
- return t;
972
- }
973
- function createTeams(teamsJSON) {
974
- if (Array.isArray(teamsJSON)) {
975
- return teamsJSON.map((t) => createTeam(t));
976
- } else {
977
- const teams = Object.entries(teamsJSON).map(
978
- ([teamId, team]) => createTeam({ ...team, team_id: team.team_id ?? teamId })
979
- );
980
- return teams;
981
- }
982
- }
983
-
984
- class Submission {
985
- constructor() {
986
- this.status = SubmissionStatus.UNKNOWN;
987
- this.isIgnore = false;
988
- this.id = "";
989
- this.teamId = "";
990
- this.problemId = "";
991
- this.timestamp = 0;
992
- }
993
- isAccepted() {
994
- return isAccepted(this.status);
995
- }
996
- isRejected() {
997
- return isRejected(this.status);
998
- }
999
- isPending() {
1000
- return isPending(this.status);
1001
- }
1002
- isNotCalculatedPenaltyStatus() {
1003
- return isNotCalculatedPenaltyStatus(this.status);
1004
- }
1005
- get timestampToMinute() {
1006
- return Math.floor(this.timestamp / 60);
1007
- }
1008
- static compare(lhs, rhs) {
1009
- if (lhs.timestamp !== rhs.timestamp) {
1010
- return lhs.timestamp - rhs.timestamp;
1011
- }
1012
- if (lhs.teamId === rhs.teamId) {
1013
- if (lhs.isAccepted() && !rhs.isAccepted()) {
1014
- return -1;
1015
- }
1016
- if (!lhs.isAccepted() && rhs.isAccepted()) {
1017
- return 1;
1018
- }
1019
- }
1020
- return 0;
1021
- }
1022
- }
1023
- function createSubmission(submissionJSON) {
1024
- const s = new Submission();
1025
- s.id = String(submissionJSON.id ?? submissionJSON.submission_id ?? "");
1026
- s.teamId = String(submissionJSON.team_id);
1027
- s.problemId = String(submissionJSON.problem_id);
1028
- s.timestamp = submissionJSON.timestamp;
1029
- s.status = stringToSubmissionStatus(submissionJSON.status);
1030
- s.isIgnore = submissionJSON.is_ignore ?? false;
1031
- return s;
1032
- }
1033
- function createSubmissions(submissionsJSON) {
1034
- if (Array.isArray(submissionsJSON)) {
1035
- return submissionsJSON.map((s, index) => createSubmission({ ...s, id: s.submission_id ?? String(index) }));
1036
- } else {
1037
- const submissions = Object.entries(submissionsJSON).map(
1038
- ([submissionId, s]) => createSubmission({ ...s, id: s.submission_id ?? submissionId })
1039
- );
1040
- return submissions;
1055
+ getTeamSolvedNumIndex(solvedNum) {
1056
+ return this.teamSolvedNumIndex[solvedNum] ?? 0;
1041
1057
  }
1042
1058
  }
1043
1059
 
@@ -1119,31 +1135,35 @@ class Rank {
1119
1135
  this.originTeams.sort(Team.compare);
1120
1136
  this.rankStatistics = new RankStatistics();
1121
1137
  this.options = new RankOptions();
1138
+ this.balloons = [];
1122
1139
  }
1123
- buildRank() {
1140
+ cleanRank() {
1124
1141
  (() => {
1125
- (() => {
1126
- this.teams = [];
1127
- for (const [_k, v] of this.teamsMap) {
1128
- if (this.filterTeamByOrg(v)) {
1129
- continue;
1130
- }
1131
- this.teams.push(v);
1142
+ this.teams = [];
1143
+ for (const [_k, v] of this.teamsMap) {
1144
+ if (this.filterTeamByOrg(v)) {
1145
+ continue;
1132
1146
  }
1133
- })();
1134
- for (const t of this.teams) {
1135
- t.reset();
1136
- t.problemStatistics = this.contest.problems.map((p) => {
1137
- const ps = new TeamProblemStatistics();
1138
- ps.problem = p;
1139
- ps.contestPenalty = this.contest.penalty;
1140
- return ps;
1141
- });
1142
- t.problemStatisticsMap = new Map(t.problemStatistics.map((ps) => [ps.problem.id, ps]));
1147
+ this.teams.push(v);
1143
1148
  }
1144
- this.contest.problems.forEach((p) => {
1145
- p.statistics.reset();
1149
+ })();
1150
+ for (const t of this.teams) {
1151
+ t.reset();
1152
+ t.problemStatistics = this.contest.problems.map((p) => {
1153
+ const ps = new TeamProblemStatistics();
1154
+ ps.problem = p;
1155
+ ps.contestPenalty = this.contest.penalty;
1156
+ return ps;
1146
1157
  });
1158
+ t.problemStatisticsMap = new Map(t.problemStatistics.map((ps) => [ps.problem.id, ps]));
1159
+ }
1160
+ this.contest.problems.forEach((p) => {
1161
+ p.statistics.reset();
1162
+ });
1163
+ }
1164
+ buildRank() {
1165
+ (() => {
1166
+ this.cleanRank();
1147
1167
  this.teams.forEach(
1148
1168
  (t) => t.placeChartPoints.push({
1149
1169
  timePoint: 0,
@@ -1154,6 +1174,7 @@ class Rank {
1154
1174
  (() => {
1155
1175
  this.rankStatistics.reset();
1156
1176
  this.rankStatistics.teamSolvedNum = Array(this.contest.problems.length + 1).fill(0);
1177
+ this.rankStatistics.teamSolvedNumIndex = Array(this.contest.problems.length + 1).fill(0);
1157
1178
  })();
1158
1179
  let preSubmissionTimestampToMinute = 0;
1159
1180
  const allSubmissions = this.getSubmissions();
@@ -1235,6 +1256,15 @@ class Rank {
1235
1256
  for (const t of this.teams) {
1236
1257
  this.rankStatistics.teamSolvedNum[t.solvedProblemNum]++;
1237
1258
  }
1259
+ {
1260
+ let current = 0;
1261
+ const teamSolvedNum = this.rankStatistics.teamSolvedNum;
1262
+ const teamSolvedNumIndex = this.rankStatistics.teamSolvedNumIndex;
1263
+ for (let i = teamSolvedNumIndex.length - 1; i >= 0; i--) {
1264
+ current += teamSolvedNum[i] > 0 ? 1 : 0;
1265
+ teamSolvedNumIndex[i] = current;
1266
+ }
1267
+ }
1238
1268
  if (this.teams.length > 0) {
1239
1269
  this.rankStatistics.maxSolvedProblems = this.teams[0].solvedProblemNum;
1240
1270
  }
@@ -1312,6 +1342,36 @@ class Rank {
1312
1342
  (s) => s.timestamp <= this.options.timestamp
1313
1343
  ).sort(Submission.compare);
1314
1344
  }
1345
+ buildBalloons() {
1346
+ this.balloons = [];
1347
+ this.cleanRank();
1348
+ const allSubmissions = this.getSubmissions();
1349
+ for (let ix = 0; ix < allSubmissions.length; ix++) {
1350
+ const s = allSubmissions[ix];
1351
+ const teamId = s.teamId;
1352
+ const problemId = s.problemId;
1353
+ const team = this.teamsMap.get(teamId);
1354
+ const problem = this.contest.problemsMap.get(problemId);
1355
+ (() => {
1356
+ if (team === void 0 || problem === void 0) {
1357
+ return;
1358
+ }
1359
+ const problemStatistics = team.problemStatisticsMap.get(problemId);
1360
+ if (problemStatistics.isSolved) {
1361
+ return;
1362
+ }
1363
+ if (s.isAccepted()) {
1364
+ problemStatistics.isSolved = true;
1365
+ problemStatistics.solvedTimestamp = s.timestamp;
1366
+ const b = new Balloon();
1367
+ b.team = team;
1368
+ b.problem = problem;
1369
+ b.submission = s;
1370
+ this.balloons.push(b);
1371
+ }
1372
+ })();
1373
+ }
1374
+ }
1315
1375
  }
1316
1376
 
1317
1377
  class ResolverOperation {
@@ -1402,4 +1462,4 @@ class Resolver extends Rank {
1402
1462
  }
1403
1463
  }
1404
1464
 
1405
- export { Award, CodeforcesGymGhostDATConverter, Contest, ContestIndex, ContestIndexConfig, GeneralExcelConverter, MedalType, PlaceChartPointData, Problem, ProblemStatistics, Rank, RankOptions, RankStatistics, Resolver, Submission, Team, TeamProblemStatistics, calcDirt, createContest, createContestIndex, createContestIndexList, createDayJS, createProblem, createProblems, createProblemsByProblemIds, createSubmission, createSubmissions, createTeam, createTeams, getImageSource, getTimeDiff, getTimestamp, isAccepted, isNotCalculatedPenaltyStatus, isPending, isRejected, isValidMedalType, stringToSubmissionStatus };
1465
+ export { Award, Balloon, CodeforcesGymGhostDATConverter, Contest, ContestIndex, ContestIndexConfig, GeneralExcelConverter, MedalType, PlaceChartPointData, Problem, ProblemStatistics, Rank, RankOptions, RankStatistics, Resolver, Submission, Team, TeamProblemStatistics, calcDirt, createContest, createContestIndex, createContestIndexList, createDayJS, createProblem, createProblems, createProblemsByProblemIds, createSubmission, createSubmissions, createTeam, createTeams, getImageSource, getTimeDiff, getTimestamp, isAccepted, isNotCalculatedPenaltyStatus, isPending, isRejected, isValidMedalType, stringToSubmissionStatus };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xcpcio/core",
3
- "version": "0.23.0",
3
+ "version": "0.24.3",
4
4
  "description": "XCPCIO Core",
5
5
  "author": "Dup4 <lyuzhi.pan@gmail.com>",
6
6
  "license": "MIT",
@@ -44,7 +44,7 @@
44
44
  "lodash": "^4.17.21",
45
45
  "string-width": "^6.1.0",
46
46
  "xlsx-js-style": "^1.2.0",
47
- "@xcpcio/types": "0.23.0"
47
+ "@xcpcio/types": "0.24.3"
48
48
  },
49
49
  "devDependencies": {
50
50
  "@babel/types": "^7.22.4",
package/src/balloon.ts ADDED
@@ -0,0 +1,21 @@
1
+ import { Problem } from "./problem";
2
+ import { Team } from "./team";
3
+ import { Submission } from "./submission";
4
+
5
+ export class Balloon {
6
+ problem: Problem;
7
+ team: Team;
8
+ submission: Submission;
9
+
10
+ constructor() {
11
+ this.problem = new Problem();
12
+ this.team = new Team();
13
+ this.submission = new Submission();
14
+ }
15
+
16
+ get key() {
17
+ return `balloon-${this.team.id}-${this.problem.id}`;
18
+ }
19
+ }
20
+
21
+ export type Balloons = Array<Balloon>;
package/src/index.ts CHANGED
@@ -1,7 +1,9 @@
1
1
  export * from "./export";
2
+ export * from "./utils";
3
+
2
4
  export * from "./award";
5
+ export * from "./balloon";
3
6
  export * from "./contest-index";
4
- export * from "./utils";
5
7
  export * from "./contest";
6
8
  export * from "./image";
7
9
  export * from "./problem";
package/src/problem.ts CHANGED
@@ -182,19 +182,19 @@ export class TeamProblemStatistics {
182
182
  return this.totalCount === 0;
183
183
  }
184
184
 
185
+ get solvedTimestampToMinute() {
186
+ return Math.floor(this.solvedTimestamp / 60);
187
+ }
188
+
185
189
  get penalty() {
186
190
  if (this.isSolved === false) {
187
191
  return 0;
188
192
  }
189
193
 
190
- return Math.floor(this.solvedTimestamp / 60) * 60 + this.failedCount * this.contestPenalty;
194
+ return this.solvedTimestampToMinute * 60 + this.failedCount * this.contestPenalty;
191
195
  }
192
196
 
193
197
  get penaltyToMinute() {
194
198
  return Math.floor(this.penalty / 60);
195
199
  }
196
-
197
- get solvedTimestampToMinute() {
198
- return Math.floor(this.solvedTimestamp / 60);
199
- }
200
200
  }
@@ -1,14 +1,21 @@
1
1
  export class RankStatistics {
2
2
  teamSolvedNum: Array<number>;
3
+ teamSolvedNumIndex: Array<number>;
3
4
  maxSolvedProblems: number;
4
5
 
5
6
  constructor() {
6
7
  this.teamSolvedNum = [];
8
+ this.teamSolvedNumIndex = [];
7
9
  this.maxSolvedProblems = 0;
8
10
  }
9
11
 
10
12
  reset() {
11
13
  this.teamSolvedNum = [];
14
+ this.teamSolvedNumIndex = [];
12
15
  this.maxSolvedProblems = 0;
13
16
  }
17
+
18
+ getTeamSolvedNumIndex(solvedNum: number): number {
19
+ return this.teamSolvedNumIndex[solvedNum] ?? 0;
20
+ }
14
21
  }