@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.cjs +306 -245
- package/dist/index.d.ts +16 -2
- package/dist/index.mjs +306 -246
- package/package.json +2 -2
- package/src/balloon.ts +21 -0
- package/src/index.ts +3 -1
- package/src/problem.ts +5 -5
- package/src/rank-statistics.ts +7 -0
- package/src/rank.ts +84 -23
package/dist/index.cjs
CHANGED
|
@@ -557,17 +557,251 @@ class TeamProblemStatistics {
|
|
|
557
557
|
get isUnSubmitted() {
|
|
558
558
|
return this.totalCount === 0;
|
|
559
559
|
}
|
|
560
|
+
get solvedTimestampToMinute() {
|
|
561
|
+
return Math.floor(this.solvedTimestamp / 60);
|
|
562
|
+
}
|
|
560
563
|
get penalty() {
|
|
561
564
|
if (this.isSolved === false) {
|
|
562
565
|
return 0;
|
|
563
566
|
}
|
|
564
|
-
return
|
|
567
|
+
return this.solvedTimestampToMinute * 60 + this.failedCount * this.contestPenalty;
|
|
565
568
|
}
|
|
566
569
|
get penaltyToMinute() {
|
|
567
570
|
return Math.floor(this.penalty / 60);
|
|
568
571
|
}
|
|
569
|
-
|
|
570
|
-
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
class PlaceChartPointData {
|
|
575
|
+
constructor() {
|
|
576
|
+
this.timePoint = 0;
|
|
577
|
+
this.rank = 0;
|
|
578
|
+
this.lastSolvedProblem = null;
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
class Team {
|
|
582
|
+
constructor() {
|
|
583
|
+
this.id = "";
|
|
584
|
+
this.name = "";
|
|
585
|
+
this.organization = "";
|
|
586
|
+
this.group = [];
|
|
587
|
+
this.tag = [];
|
|
588
|
+
this.rank = 0;
|
|
589
|
+
this.originalRank = 0;
|
|
590
|
+
this.organizationRank = -1;
|
|
591
|
+
this.solvedProblemNum = 0;
|
|
592
|
+
this.attemptedProblemNum = 0;
|
|
593
|
+
this.lastSolvedProblem = null;
|
|
594
|
+
this.lastSolvedProblemTimestamp = 0;
|
|
595
|
+
this.penalty = 0;
|
|
596
|
+
this.problemStatistics = [];
|
|
597
|
+
this.problemStatisticsMap = /* @__PURE__ */ new Map();
|
|
598
|
+
this.submissions = [];
|
|
599
|
+
this.placeChartPoints = [];
|
|
600
|
+
this.awards = [];
|
|
601
|
+
}
|
|
602
|
+
reset() {
|
|
603
|
+
this.rank = 0;
|
|
604
|
+
this.originalRank = 0;
|
|
605
|
+
this.organizationRank = -1;
|
|
606
|
+
this.solvedProblemNum = 0;
|
|
607
|
+
this.attemptedProblemNum = 0;
|
|
608
|
+
this.lastSolvedProblem = null;
|
|
609
|
+
this.lastSolvedProblemTimestamp = 0;
|
|
610
|
+
this.penalty = 0;
|
|
611
|
+
this.problemStatistics = [];
|
|
612
|
+
this.problemStatisticsMap = /* @__PURE__ */ new Map();
|
|
613
|
+
this.submissions = [];
|
|
614
|
+
this.placeChartPoints = [];
|
|
615
|
+
this.awards = [];
|
|
616
|
+
}
|
|
617
|
+
get penaltyToMinute() {
|
|
618
|
+
return Math.floor(this.penalty / 60);
|
|
619
|
+
}
|
|
620
|
+
get dirt() {
|
|
621
|
+
const attemptedNum = this.attemptedProblemNum;
|
|
622
|
+
const solvedNum = this.solvedProblemNum;
|
|
623
|
+
return calcDirt(attemptedNum, solvedNum);
|
|
624
|
+
}
|
|
625
|
+
get membersToString() {
|
|
626
|
+
if (typeof this.members === "string") {
|
|
627
|
+
return this.members;
|
|
628
|
+
}
|
|
629
|
+
return this.members?.join(", ");
|
|
630
|
+
}
|
|
631
|
+
calcSolvedData() {
|
|
632
|
+
this.solvedProblemNum = 0;
|
|
633
|
+
this.attemptedProblemNum = 0;
|
|
634
|
+
this.penalty = 0;
|
|
635
|
+
for (const p of this.problemStatistics) {
|
|
636
|
+
if (p.isAccepted) {
|
|
637
|
+
this.solvedProblemNum++;
|
|
638
|
+
this.attemptedProblemNum += p.failedCount + 1;
|
|
639
|
+
this.penalty += p.penalty;
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
calcAwards(awards) {
|
|
644
|
+
if (!awards) {
|
|
645
|
+
return;
|
|
646
|
+
}
|
|
647
|
+
for (const award of awards) {
|
|
648
|
+
if (this.rank >= award.minRank && this.rank <= award.maxRank) {
|
|
649
|
+
this.awards.push(award.medalType);
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
isEqualRank(otherTeam) {
|
|
654
|
+
return this.solvedProblemNum === otherTeam.solvedProblemNum && this.penalty === otherTeam.penalty;
|
|
655
|
+
}
|
|
656
|
+
postProcessPlaceChartPoints() {
|
|
657
|
+
if (this.placeChartPoints.length === 0) {
|
|
658
|
+
return;
|
|
659
|
+
}
|
|
660
|
+
const res = [];
|
|
661
|
+
res.push(this.placeChartPoints[0]);
|
|
662
|
+
for (let i = 1; i < this.placeChartPoints.length - 1; i++) {
|
|
663
|
+
const p = this.placeChartPoints[i];
|
|
664
|
+
const preP = res[res.length - 1];
|
|
665
|
+
if (p.rank !== preP.rank || p.lastSolvedProblem !== preP.lastSolvedProblem) {
|
|
666
|
+
res.push(p);
|
|
667
|
+
}
|
|
668
|
+
}
|
|
669
|
+
if (this.placeChartPoints.length > 1) {
|
|
670
|
+
res.push(this.placeChartPoints[this.placeChartPoints.length - 1]);
|
|
671
|
+
}
|
|
672
|
+
this.placeChartPoints = res;
|
|
673
|
+
}
|
|
674
|
+
static compare(lhs, rhs) {
|
|
675
|
+
if (lhs.solvedProblemNum !== rhs.solvedProblemNum) {
|
|
676
|
+
return rhs.solvedProblemNum - lhs.solvedProblemNum;
|
|
677
|
+
}
|
|
678
|
+
if (lhs.penalty !== rhs.penalty) {
|
|
679
|
+
return lhs.penalty - rhs.penalty;
|
|
680
|
+
}
|
|
681
|
+
if (lhs.lastSolvedProblemTimestamp !== rhs.lastSolvedProblemTimestamp) {
|
|
682
|
+
return lhs.lastSolvedProblemTimestamp - rhs.lastSolvedProblemTimestamp;
|
|
683
|
+
}
|
|
684
|
+
if (lhs.name < rhs.name) {
|
|
685
|
+
return -1;
|
|
686
|
+
} else if (lhs.name > rhs.name) {
|
|
687
|
+
return 1;
|
|
688
|
+
}
|
|
689
|
+
return 0;
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
function createTeam(teamJSON) {
|
|
693
|
+
const t = new Team();
|
|
694
|
+
t.id = teamJSON.id ?? teamJSON.team_id ?? "";
|
|
695
|
+
t.name = teamJSON.name ?? teamJSON.team_name ?? "";
|
|
696
|
+
t.organization = teamJSON.organization ?? "";
|
|
697
|
+
t.badge = teamJSON.badge;
|
|
698
|
+
t.group = teamJSON.group ?? [];
|
|
699
|
+
t.tag = teamJSON.group ?? [];
|
|
700
|
+
t.coach = teamJSON.coach;
|
|
701
|
+
t.members = teamJSON.members;
|
|
702
|
+
if (Boolean(teamJSON.official) === true) {
|
|
703
|
+
t.group.push("official");
|
|
704
|
+
}
|
|
705
|
+
if (Boolean(teamJSON.unofficial) === true) {
|
|
706
|
+
t.group.push("unofficial");
|
|
707
|
+
}
|
|
708
|
+
if (Boolean(teamJSON.girl) === true) {
|
|
709
|
+
t.group.push("girl");
|
|
710
|
+
}
|
|
711
|
+
{
|
|
712
|
+
const tt = teamJSON;
|
|
713
|
+
for (const key of Object.keys(tt)) {
|
|
714
|
+
if (tt[key] === 1 || tt[key] === true) {
|
|
715
|
+
t.group.push(key);
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
}
|
|
719
|
+
t.group = [...new Set(t.group)];
|
|
720
|
+
t.group.sort();
|
|
721
|
+
if (teamJSON.location) {
|
|
722
|
+
t.location = teamJSON.location;
|
|
723
|
+
}
|
|
724
|
+
return t;
|
|
725
|
+
}
|
|
726
|
+
function createTeams(teamsJSON) {
|
|
727
|
+
if (Array.isArray(teamsJSON)) {
|
|
728
|
+
return teamsJSON.map((t) => createTeam(t));
|
|
729
|
+
} else {
|
|
730
|
+
const teams = Object.entries(teamsJSON).map(
|
|
731
|
+
([teamId, team]) => createTeam({ ...team, team_id: team.team_id ?? teamId })
|
|
732
|
+
);
|
|
733
|
+
return teams;
|
|
734
|
+
}
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
class Submission {
|
|
738
|
+
constructor() {
|
|
739
|
+
this.status = types.SubmissionStatus.UNKNOWN;
|
|
740
|
+
this.isIgnore = false;
|
|
741
|
+
this.id = "";
|
|
742
|
+
this.teamId = "";
|
|
743
|
+
this.problemId = "";
|
|
744
|
+
this.timestamp = 0;
|
|
745
|
+
}
|
|
746
|
+
isAccepted() {
|
|
747
|
+
return isAccepted(this.status);
|
|
748
|
+
}
|
|
749
|
+
isRejected() {
|
|
750
|
+
return isRejected(this.status);
|
|
751
|
+
}
|
|
752
|
+
isPending() {
|
|
753
|
+
return isPending(this.status);
|
|
754
|
+
}
|
|
755
|
+
isNotCalculatedPenaltyStatus() {
|
|
756
|
+
return isNotCalculatedPenaltyStatus(this.status);
|
|
757
|
+
}
|
|
758
|
+
get timestampToMinute() {
|
|
759
|
+
return Math.floor(this.timestamp / 60);
|
|
760
|
+
}
|
|
761
|
+
static compare(lhs, rhs) {
|
|
762
|
+
if (lhs.timestamp !== rhs.timestamp) {
|
|
763
|
+
return lhs.timestamp - rhs.timestamp;
|
|
764
|
+
}
|
|
765
|
+
if (lhs.teamId === rhs.teamId) {
|
|
766
|
+
if (lhs.isAccepted() && !rhs.isAccepted()) {
|
|
767
|
+
return -1;
|
|
768
|
+
}
|
|
769
|
+
if (!lhs.isAccepted() && rhs.isAccepted()) {
|
|
770
|
+
return 1;
|
|
771
|
+
}
|
|
772
|
+
}
|
|
773
|
+
return 0;
|
|
774
|
+
}
|
|
775
|
+
}
|
|
776
|
+
function createSubmission(submissionJSON) {
|
|
777
|
+
const s = new Submission();
|
|
778
|
+
s.id = String(submissionJSON.id ?? submissionJSON.submission_id ?? "");
|
|
779
|
+
s.teamId = String(submissionJSON.team_id);
|
|
780
|
+
s.problemId = String(submissionJSON.problem_id);
|
|
781
|
+
s.timestamp = submissionJSON.timestamp;
|
|
782
|
+
s.status = stringToSubmissionStatus(submissionJSON.status);
|
|
783
|
+
s.isIgnore = submissionJSON.is_ignore ?? false;
|
|
784
|
+
return s;
|
|
785
|
+
}
|
|
786
|
+
function createSubmissions(submissionsJSON) {
|
|
787
|
+
if (Array.isArray(submissionsJSON)) {
|
|
788
|
+
return submissionsJSON.map((s, index) => createSubmission({ ...s, id: s.submission_id ?? String(index) }));
|
|
789
|
+
} else {
|
|
790
|
+
const submissions = Object.entries(submissionsJSON).map(
|
|
791
|
+
([submissionId, s]) => createSubmission({ ...s, id: s.submission_id ?? submissionId })
|
|
792
|
+
);
|
|
793
|
+
return submissions;
|
|
794
|
+
}
|
|
795
|
+
}
|
|
796
|
+
|
|
797
|
+
class Balloon {
|
|
798
|
+
constructor() {
|
|
799
|
+
this.problem = new Problem();
|
|
800
|
+
this.team = new Team();
|
|
801
|
+
this.submission = new Submission();
|
|
802
|
+
}
|
|
803
|
+
get key() {
|
|
804
|
+
return `balloon-${this.team.id}-${this.problem.id}`;
|
|
571
805
|
}
|
|
572
806
|
}
|
|
573
807
|
|
|
@@ -840,234 +1074,16 @@ function getImageSource(image) {
|
|
|
840
1074
|
class RankStatistics {
|
|
841
1075
|
constructor() {
|
|
842
1076
|
this.teamSolvedNum = [];
|
|
1077
|
+
this.teamSolvedNumIndex = [];
|
|
843
1078
|
this.maxSolvedProblems = 0;
|
|
844
1079
|
}
|
|
845
1080
|
reset() {
|
|
846
1081
|
this.teamSolvedNum = [];
|
|
1082
|
+
this.teamSolvedNumIndex = [];
|
|
847
1083
|
this.maxSolvedProblems = 0;
|
|
848
1084
|
}
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
class PlaceChartPointData {
|
|
852
|
-
constructor() {
|
|
853
|
-
this.timePoint = 0;
|
|
854
|
-
this.rank = 0;
|
|
855
|
-
this.lastSolvedProblem = null;
|
|
856
|
-
}
|
|
857
|
-
}
|
|
858
|
-
class Team {
|
|
859
|
-
constructor() {
|
|
860
|
-
this.id = "";
|
|
861
|
-
this.name = "";
|
|
862
|
-
this.organization = "";
|
|
863
|
-
this.group = [];
|
|
864
|
-
this.tag = [];
|
|
865
|
-
this.rank = 0;
|
|
866
|
-
this.originalRank = 0;
|
|
867
|
-
this.organizationRank = -1;
|
|
868
|
-
this.solvedProblemNum = 0;
|
|
869
|
-
this.attemptedProblemNum = 0;
|
|
870
|
-
this.lastSolvedProblem = null;
|
|
871
|
-
this.lastSolvedProblemTimestamp = 0;
|
|
872
|
-
this.penalty = 0;
|
|
873
|
-
this.problemStatistics = [];
|
|
874
|
-
this.problemStatisticsMap = /* @__PURE__ */ new Map();
|
|
875
|
-
this.submissions = [];
|
|
876
|
-
this.placeChartPoints = [];
|
|
877
|
-
this.awards = [];
|
|
878
|
-
}
|
|
879
|
-
reset() {
|
|
880
|
-
this.rank = 0;
|
|
881
|
-
this.originalRank = 0;
|
|
882
|
-
this.organizationRank = -1;
|
|
883
|
-
this.solvedProblemNum = 0;
|
|
884
|
-
this.attemptedProblemNum = 0;
|
|
885
|
-
this.lastSolvedProblem = null;
|
|
886
|
-
this.lastSolvedProblemTimestamp = 0;
|
|
887
|
-
this.penalty = 0;
|
|
888
|
-
this.problemStatistics = [];
|
|
889
|
-
this.problemStatisticsMap = /* @__PURE__ */ new Map();
|
|
890
|
-
this.submissions = [];
|
|
891
|
-
this.placeChartPoints = [];
|
|
892
|
-
this.awards = [];
|
|
893
|
-
}
|
|
894
|
-
get penaltyToMinute() {
|
|
895
|
-
return Math.floor(this.penalty / 60);
|
|
896
|
-
}
|
|
897
|
-
get dirt() {
|
|
898
|
-
const attemptedNum = this.attemptedProblemNum;
|
|
899
|
-
const solvedNum = this.solvedProblemNum;
|
|
900
|
-
return calcDirt(attemptedNum, solvedNum);
|
|
901
|
-
}
|
|
902
|
-
get membersToString() {
|
|
903
|
-
if (typeof this.members === "string") {
|
|
904
|
-
return this.members;
|
|
905
|
-
}
|
|
906
|
-
return this.members?.join(", ");
|
|
907
|
-
}
|
|
908
|
-
calcSolvedData() {
|
|
909
|
-
this.solvedProblemNum = 0;
|
|
910
|
-
this.attemptedProblemNum = 0;
|
|
911
|
-
this.penalty = 0;
|
|
912
|
-
for (const p of this.problemStatistics) {
|
|
913
|
-
if (p.isAccepted) {
|
|
914
|
-
this.solvedProblemNum++;
|
|
915
|
-
this.attemptedProblemNum += p.failedCount + 1;
|
|
916
|
-
this.penalty += p.penalty;
|
|
917
|
-
}
|
|
918
|
-
}
|
|
919
|
-
}
|
|
920
|
-
calcAwards(awards) {
|
|
921
|
-
if (!awards) {
|
|
922
|
-
return;
|
|
923
|
-
}
|
|
924
|
-
for (const award of awards) {
|
|
925
|
-
if (this.rank >= award.minRank && this.rank <= award.maxRank) {
|
|
926
|
-
this.awards.push(award.medalType);
|
|
927
|
-
}
|
|
928
|
-
}
|
|
929
|
-
}
|
|
930
|
-
isEqualRank(otherTeam) {
|
|
931
|
-
return this.solvedProblemNum === otherTeam.solvedProblemNum && this.penalty === otherTeam.penalty;
|
|
932
|
-
}
|
|
933
|
-
postProcessPlaceChartPoints() {
|
|
934
|
-
if (this.placeChartPoints.length === 0) {
|
|
935
|
-
return;
|
|
936
|
-
}
|
|
937
|
-
const res = [];
|
|
938
|
-
res.push(this.placeChartPoints[0]);
|
|
939
|
-
for (let i = 1; i < this.placeChartPoints.length - 1; i++) {
|
|
940
|
-
const p = this.placeChartPoints[i];
|
|
941
|
-
const preP = res[res.length - 1];
|
|
942
|
-
if (p.rank !== preP.rank || p.lastSolvedProblem !== preP.lastSolvedProblem) {
|
|
943
|
-
res.push(p);
|
|
944
|
-
}
|
|
945
|
-
}
|
|
946
|
-
if (this.placeChartPoints.length > 1) {
|
|
947
|
-
res.push(this.placeChartPoints[this.placeChartPoints.length - 1]);
|
|
948
|
-
}
|
|
949
|
-
this.placeChartPoints = res;
|
|
950
|
-
}
|
|
951
|
-
static compare(lhs, rhs) {
|
|
952
|
-
if (lhs.solvedProblemNum !== rhs.solvedProblemNum) {
|
|
953
|
-
return rhs.solvedProblemNum - lhs.solvedProblemNum;
|
|
954
|
-
}
|
|
955
|
-
if (lhs.penalty !== rhs.penalty) {
|
|
956
|
-
return lhs.penalty - rhs.penalty;
|
|
957
|
-
}
|
|
958
|
-
if (lhs.lastSolvedProblemTimestamp !== rhs.lastSolvedProblemTimestamp) {
|
|
959
|
-
return lhs.lastSolvedProblemTimestamp - rhs.lastSolvedProblemTimestamp;
|
|
960
|
-
}
|
|
961
|
-
if (lhs.name < rhs.name) {
|
|
962
|
-
return -1;
|
|
963
|
-
} else if (lhs.name > rhs.name) {
|
|
964
|
-
return 1;
|
|
965
|
-
}
|
|
966
|
-
return 0;
|
|
967
|
-
}
|
|
968
|
-
}
|
|
969
|
-
function createTeam(teamJSON) {
|
|
970
|
-
const t = new Team();
|
|
971
|
-
t.id = teamJSON.id ?? teamJSON.team_id ?? "";
|
|
972
|
-
t.name = teamJSON.name ?? teamJSON.team_name ?? "";
|
|
973
|
-
t.organization = teamJSON.organization ?? "";
|
|
974
|
-
t.badge = teamJSON.badge;
|
|
975
|
-
t.group = teamJSON.group ?? [];
|
|
976
|
-
t.tag = teamJSON.group ?? [];
|
|
977
|
-
t.coach = teamJSON.coach;
|
|
978
|
-
t.members = teamJSON.members;
|
|
979
|
-
if (Boolean(teamJSON.official) === true) {
|
|
980
|
-
t.group.push("official");
|
|
981
|
-
}
|
|
982
|
-
if (Boolean(teamJSON.unofficial) === true) {
|
|
983
|
-
t.group.push("unofficial");
|
|
984
|
-
}
|
|
985
|
-
if (Boolean(teamJSON.girl) === true) {
|
|
986
|
-
t.group.push("girl");
|
|
987
|
-
}
|
|
988
|
-
{
|
|
989
|
-
const tt = teamJSON;
|
|
990
|
-
for (const key of Object.keys(tt)) {
|
|
991
|
-
if (tt[key] === 1 || tt[key] === true) {
|
|
992
|
-
t.group.push(key);
|
|
993
|
-
}
|
|
994
|
-
}
|
|
995
|
-
}
|
|
996
|
-
t.group = [...new Set(t.group)];
|
|
997
|
-
t.group.sort();
|
|
998
|
-
if (teamJSON.location) {
|
|
999
|
-
t.location = teamJSON.location;
|
|
1000
|
-
}
|
|
1001
|
-
return t;
|
|
1002
|
-
}
|
|
1003
|
-
function createTeams(teamsJSON) {
|
|
1004
|
-
if (Array.isArray(teamsJSON)) {
|
|
1005
|
-
return teamsJSON.map((t) => createTeam(t));
|
|
1006
|
-
} else {
|
|
1007
|
-
const teams = Object.entries(teamsJSON).map(
|
|
1008
|
-
([teamId, team]) => createTeam({ ...team, team_id: team.team_id ?? teamId })
|
|
1009
|
-
);
|
|
1010
|
-
return teams;
|
|
1011
|
-
}
|
|
1012
|
-
}
|
|
1013
|
-
|
|
1014
|
-
class Submission {
|
|
1015
|
-
constructor() {
|
|
1016
|
-
this.status = types.SubmissionStatus.UNKNOWN;
|
|
1017
|
-
this.isIgnore = false;
|
|
1018
|
-
this.id = "";
|
|
1019
|
-
this.teamId = "";
|
|
1020
|
-
this.problemId = "";
|
|
1021
|
-
this.timestamp = 0;
|
|
1022
|
-
}
|
|
1023
|
-
isAccepted() {
|
|
1024
|
-
return isAccepted(this.status);
|
|
1025
|
-
}
|
|
1026
|
-
isRejected() {
|
|
1027
|
-
return isRejected(this.status);
|
|
1028
|
-
}
|
|
1029
|
-
isPending() {
|
|
1030
|
-
return isPending(this.status);
|
|
1031
|
-
}
|
|
1032
|
-
isNotCalculatedPenaltyStatus() {
|
|
1033
|
-
return isNotCalculatedPenaltyStatus(this.status);
|
|
1034
|
-
}
|
|
1035
|
-
get timestampToMinute() {
|
|
1036
|
-
return Math.floor(this.timestamp / 60);
|
|
1037
|
-
}
|
|
1038
|
-
static compare(lhs, rhs) {
|
|
1039
|
-
if (lhs.timestamp !== rhs.timestamp) {
|
|
1040
|
-
return lhs.timestamp - rhs.timestamp;
|
|
1041
|
-
}
|
|
1042
|
-
if (lhs.teamId === rhs.teamId) {
|
|
1043
|
-
if (lhs.isAccepted() && !rhs.isAccepted()) {
|
|
1044
|
-
return -1;
|
|
1045
|
-
}
|
|
1046
|
-
if (!lhs.isAccepted() && rhs.isAccepted()) {
|
|
1047
|
-
return 1;
|
|
1048
|
-
}
|
|
1049
|
-
}
|
|
1050
|
-
return 0;
|
|
1051
|
-
}
|
|
1052
|
-
}
|
|
1053
|
-
function createSubmission(submissionJSON) {
|
|
1054
|
-
const s = new Submission();
|
|
1055
|
-
s.id = String(submissionJSON.id ?? submissionJSON.submission_id ?? "");
|
|
1056
|
-
s.teamId = String(submissionJSON.team_id);
|
|
1057
|
-
s.problemId = String(submissionJSON.problem_id);
|
|
1058
|
-
s.timestamp = submissionJSON.timestamp;
|
|
1059
|
-
s.status = stringToSubmissionStatus(submissionJSON.status);
|
|
1060
|
-
s.isIgnore = submissionJSON.is_ignore ?? false;
|
|
1061
|
-
return s;
|
|
1062
|
-
}
|
|
1063
|
-
function createSubmissions(submissionsJSON) {
|
|
1064
|
-
if (Array.isArray(submissionsJSON)) {
|
|
1065
|
-
return submissionsJSON.map((s, index) => createSubmission({ ...s, id: s.submission_id ?? String(index) }));
|
|
1066
|
-
} else {
|
|
1067
|
-
const submissions = Object.entries(submissionsJSON).map(
|
|
1068
|
-
([submissionId, s]) => createSubmission({ ...s, id: s.submission_id ?? submissionId })
|
|
1069
|
-
);
|
|
1070
|
-
return submissions;
|
|
1085
|
+
getTeamSolvedNumIndex(solvedNum) {
|
|
1086
|
+
return this.teamSolvedNumIndex[solvedNum] ?? 0;
|
|
1071
1087
|
}
|
|
1072
1088
|
}
|
|
1073
1089
|
|
|
@@ -1149,31 +1165,35 @@ class Rank {
|
|
|
1149
1165
|
this.originTeams.sort(Team.compare);
|
|
1150
1166
|
this.rankStatistics = new RankStatistics();
|
|
1151
1167
|
this.options = new RankOptions();
|
|
1168
|
+
this.balloons = [];
|
|
1152
1169
|
}
|
|
1153
|
-
|
|
1170
|
+
cleanRank() {
|
|
1154
1171
|
(() => {
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
continue;
|
|
1160
|
-
}
|
|
1161
|
-
this.teams.push(v);
|
|
1172
|
+
this.teams = [];
|
|
1173
|
+
for (const [_k, v] of this.teamsMap) {
|
|
1174
|
+
if (this.filterTeamByOrg(v)) {
|
|
1175
|
+
continue;
|
|
1162
1176
|
}
|
|
1163
|
-
|
|
1164
|
-
for (const t of this.teams) {
|
|
1165
|
-
t.reset();
|
|
1166
|
-
t.problemStatistics = this.contest.problems.map((p) => {
|
|
1167
|
-
const ps = new TeamProblemStatistics();
|
|
1168
|
-
ps.problem = p;
|
|
1169
|
-
ps.contestPenalty = this.contest.penalty;
|
|
1170
|
-
return ps;
|
|
1171
|
-
});
|
|
1172
|
-
t.problemStatisticsMap = new Map(t.problemStatistics.map((ps) => [ps.problem.id, ps]));
|
|
1177
|
+
this.teams.push(v);
|
|
1173
1178
|
}
|
|
1174
|
-
|
|
1175
|
-
|
|
1179
|
+
})();
|
|
1180
|
+
for (const t of this.teams) {
|
|
1181
|
+
t.reset();
|
|
1182
|
+
t.problemStatistics = this.contest.problems.map((p) => {
|
|
1183
|
+
const ps = new TeamProblemStatistics();
|
|
1184
|
+
ps.problem = p;
|
|
1185
|
+
ps.contestPenalty = this.contest.penalty;
|
|
1186
|
+
return ps;
|
|
1176
1187
|
});
|
|
1188
|
+
t.problemStatisticsMap = new Map(t.problemStatistics.map((ps) => [ps.problem.id, ps]));
|
|
1189
|
+
}
|
|
1190
|
+
this.contest.problems.forEach((p) => {
|
|
1191
|
+
p.statistics.reset();
|
|
1192
|
+
});
|
|
1193
|
+
}
|
|
1194
|
+
buildRank() {
|
|
1195
|
+
(() => {
|
|
1196
|
+
this.cleanRank();
|
|
1177
1197
|
this.teams.forEach(
|
|
1178
1198
|
(t) => t.placeChartPoints.push({
|
|
1179
1199
|
timePoint: 0,
|
|
@@ -1184,6 +1204,7 @@ class Rank {
|
|
|
1184
1204
|
(() => {
|
|
1185
1205
|
this.rankStatistics.reset();
|
|
1186
1206
|
this.rankStatistics.teamSolvedNum = Array(this.contest.problems.length + 1).fill(0);
|
|
1207
|
+
this.rankStatistics.teamSolvedNumIndex = Array(this.contest.problems.length + 1).fill(0);
|
|
1187
1208
|
})();
|
|
1188
1209
|
let preSubmissionTimestampToMinute = 0;
|
|
1189
1210
|
const allSubmissions = this.getSubmissions();
|
|
@@ -1265,6 +1286,15 @@ class Rank {
|
|
|
1265
1286
|
for (const t of this.teams) {
|
|
1266
1287
|
this.rankStatistics.teamSolvedNum[t.solvedProblemNum]++;
|
|
1267
1288
|
}
|
|
1289
|
+
{
|
|
1290
|
+
let current = 0;
|
|
1291
|
+
const teamSolvedNum = this.rankStatistics.teamSolvedNum;
|
|
1292
|
+
const teamSolvedNumIndex = this.rankStatistics.teamSolvedNumIndex;
|
|
1293
|
+
for (let i = teamSolvedNumIndex.length - 1; i >= 0; i--) {
|
|
1294
|
+
current += teamSolvedNum[i] > 0 ? 1 : 0;
|
|
1295
|
+
teamSolvedNumIndex[i] = current;
|
|
1296
|
+
}
|
|
1297
|
+
}
|
|
1268
1298
|
if (this.teams.length > 0) {
|
|
1269
1299
|
this.rankStatistics.maxSolvedProblems = this.teams[0].solvedProblemNum;
|
|
1270
1300
|
}
|
|
@@ -1342,6 +1372,36 @@ class Rank {
|
|
|
1342
1372
|
(s) => s.timestamp <= this.options.timestamp
|
|
1343
1373
|
).sort(Submission.compare);
|
|
1344
1374
|
}
|
|
1375
|
+
buildBalloons() {
|
|
1376
|
+
this.balloons = [];
|
|
1377
|
+
this.cleanRank();
|
|
1378
|
+
const allSubmissions = this.getSubmissions();
|
|
1379
|
+
for (let ix = 0; ix < allSubmissions.length; ix++) {
|
|
1380
|
+
const s = allSubmissions[ix];
|
|
1381
|
+
const teamId = s.teamId;
|
|
1382
|
+
const problemId = s.problemId;
|
|
1383
|
+
const team = this.teamsMap.get(teamId);
|
|
1384
|
+
const problem = this.contest.problemsMap.get(problemId);
|
|
1385
|
+
(() => {
|
|
1386
|
+
if (team === void 0 || problem === void 0) {
|
|
1387
|
+
return;
|
|
1388
|
+
}
|
|
1389
|
+
const problemStatistics = team.problemStatisticsMap.get(problemId);
|
|
1390
|
+
if (problemStatistics.isSolved) {
|
|
1391
|
+
return;
|
|
1392
|
+
}
|
|
1393
|
+
if (s.isAccepted()) {
|
|
1394
|
+
problemStatistics.isSolved = true;
|
|
1395
|
+
problemStatistics.solvedTimestamp = s.timestamp;
|
|
1396
|
+
const b = new Balloon();
|
|
1397
|
+
b.team = team;
|
|
1398
|
+
b.problem = problem;
|
|
1399
|
+
b.submission = s;
|
|
1400
|
+
this.balloons.push(b);
|
|
1401
|
+
}
|
|
1402
|
+
})();
|
|
1403
|
+
}
|
|
1404
|
+
}
|
|
1345
1405
|
}
|
|
1346
1406
|
|
|
1347
1407
|
class ResolverOperation {
|
|
@@ -1434,6 +1494,7 @@ class Resolver extends Rank {
|
|
|
1434
1494
|
|
|
1435
1495
|
exports.dayjs = dayjs__default;
|
|
1436
1496
|
exports.Award = Award;
|
|
1497
|
+
exports.Balloon = Balloon;
|
|
1437
1498
|
exports.CodeforcesGymGhostDATConverter = CodeforcesGymGhostDATConverter;
|
|
1438
1499
|
exports.Contest = Contest;
|
|
1439
1500
|
exports.ContestIndex = ContestIndex;
|
package/dist/index.d.ts
CHANGED
|
@@ -69,9 +69,9 @@ declare class TeamProblemStatistics {
|
|
|
69
69
|
get isWrongAnswer(): boolean;
|
|
70
70
|
get isPending(): boolean;
|
|
71
71
|
get isUnSubmitted(): boolean;
|
|
72
|
+
get solvedTimestampToMinute(): number;
|
|
72
73
|
get penalty(): number;
|
|
73
74
|
get penaltyToMinute(): number;
|
|
74
|
-
get solvedTimestampToMinute(): number;
|
|
75
75
|
}
|
|
76
76
|
|
|
77
77
|
declare function calcDirt(attemptedNum: number, solvedNum: number): number;
|
|
@@ -181,10 +181,21 @@ declare function createTeams(teamsJSON: Teams$1): Teams;
|
|
|
181
181
|
|
|
182
182
|
declare class RankStatistics {
|
|
183
183
|
teamSolvedNum: Array<number>;
|
|
184
|
+
teamSolvedNumIndex: Array<number>;
|
|
184
185
|
maxSolvedProblems: number;
|
|
185
186
|
constructor();
|
|
186
187
|
reset(): void;
|
|
188
|
+
getTeamSolvedNumIndex(solvedNum: number): number;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
declare class Balloon {
|
|
192
|
+
problem: Problem;
|
|
193
|
+
team: Team;
|
|
194
|
+
submission: Submission;
|
|
195
|
+
constructor();
|
|
196
|
+
get key(): string;
|
|
187
197
|
}
|
|
198
|
+
type Balloons = Array<Balloon>;
|
|
188
199
|
|
|
189
200
|
interface SelectOptionItem {
|
|
190
201
|
value: string;
|
|
@@ -219,13 +230,16 @@ declare class Rank {
|
|
|
219
230
|
originTeams: Teams;
|
|
220
231
|
rankStatistics: RankStatistics;
|
|
221
232
|
options: RankOptions;
|
|
233
|
+
balloons: Balloons;
|
|
222
234
|
constructor(contest: Contest, teams: Teams, submissions: Submissions);
|
|
235
|
+
cleanRank(): void;
|
|
223
236
|
buildRank(): this;
|
|
224
237
|
buildTeamRank(): void;
|
|
225
238
|
buildOrgRank(): void;
|
|
226
239
|
buildOrganizations(): string[];
|
|
227
240
|
filterTeamByOrg(team: Team): boolean;
|
|
228
241
|
getSubmissions(): Submissions;
|
|
242
|
+
buildBalloons(): void;
|
|
229
243
|
}
|
|
230
244
|
|
|
231
245
|
declare class CodeforcesGymGhostDATConverter {
|
|
@@ -288,4 +302,4 @@ declare function isRejected(status: SubmissionStatus): boolean;
|
|
|
288
302
|
declare function isPending(status: SubmissionStatus): boolean;
|
|
289
303
|
declare function isNotCalculatedPenaltyStatus(status: SubmissionStatus): boolean;
|
|
290
304
|
|
|
291
|
-
export { Award, Awards, CodeforcesGymGhostDATConverter, Contest, ContestIndex, ContestIndexConfig, ContestIndexList, GeneralExcelConverter, MedalType, PlaceChartPointData, Problem, ProblemStatistics, Problems, Rank, RankOptions, RankStatistics, Resolver, SelectOptionItem, Submission, Submissions, Team, TeamProblemStatistics, Teams, calcDirt, createContest, createContestIndex, createContestIndexList, createDayJS, createProblem, createProblems, createProblemsByProblemIds, createSubmission, createSubmissions, createTeam, createTeams, getImageSource, getTimeDiff, getTimestamp, isAccepted, isNotCalculatedPenaltyStatus, isPending, isRejected, isValidMedalType, stringToSubmissionStatus };
|
|
305
|
+
export { Award, Awards, Balloon, Balloons, CodeforcesGymGhostDATConverter, Contest, ContestIndex, ContestIndexConfig, ContestIndexList, GeneralExcelConverter, MedalType, PlaceChartPointData, Problem, ProblemStatistics, Problems, Rank, RankOptions, RankStatistics, Resolver, SelectOptionItem, Submission, Submissions, Team, TeamProblemStatistics, Teams, calcDirt, createContest, createContestIndex, createContestIndexList, createDayJS, createProblem, createProblems, createProblemsByProblemIds, createSubmission, createSubmissions, createTeam, createTeams, getImageSource, getTimeDiff, getTimestamp, isAccepted, isNotCalculatedPenaltyStatus, isPending, isRejected, isValidMedalType, stringToSubmissionStatus };
|