@xcpcio/core 0.4.3 → 0.5.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 +137 -70
- package/dist/index.d.ts +14 -1
- package/dist/index.mjs +137 -71
- package/package.json +2 -2
- package/src/rank.ts +122 -82
- package/src/submission.ts +4 -0
- package/src/team.ts +58 -2
package/dist/index.cjs
CHANGED
|
@@ -379,6 +379,13 @@ class RankStatistics {
|
|
|
379
379
|
}
|
|
380
380
|
}
|
|
381
381
|
|
|
382
|
+
class PlaceChartPointData {
|
|
383
|
+
constructor() {
|
|
384
|
+
this.timePoint = 0;
|
|
385
|
+
this.rank = 0;
|
|
386
|
+
this.lastSolvedProblem = null;
|
|
387
|
+
}
|
|
388
|
+
}
|
|
382
389
|
class Team {
|
|
383
390
|
constructor() {
|
|
384
391
|
this.id = "";
|
|
@@ -390,20 +397,26 @@ class Team {
|
|
|
390
397
|
this.organizationRank = -1;
|
|
391
398
|
this.solvedProblemNum = 0;
|
|
392
399
|
this.attemptedProblemNum = 0;
|
|
400
|
+
this.lastSolvedProblem = null;
|
|
393
401
|
this.lastSolvedProblemTimestamp = 0;
|
|
394
402
|
this.penalty = 0;
|
|
395
403
|
this.problemStatistics = [];
|
|
396
404
|
this.problemStatisticsMap = /* @__PURE__ */ new Map();
|
|
405
|
+
this.submissions = [];
|
|
406
|
+
this.placeChartPoints = [];
|
|
397
407
|
}
|
|
398
408
|
reset() {
|
|
399
409
|
this.rank = 0;
|
|
400
410
|
this.organizationRank = -1;
|
|
401
411
|
this.solvedProblemNum = 0;
|
|
402
412
|
this.attemptedProblemNum = 0;
|
|
413
|
+
this.lastSolvedProblem = null;
|
|
403
414
|
this.lastSolvedProblemTimestamp = 0;
|
|
404
415
|
this.penalty = 0;
|
|
405
416
|
this.problemStatistics = [];
|
|
406
417
|
this.problemStatisticsMap = /* @__PURE__ */ new Map();
|
|
418
|
+
this.submissions = [];
|
|
419
|
+
this.placeChartPoints = [];
|
|
407
420
|
}
|
|
408
421
|
get penaltyToMinute() {
|
|
409
422
|
return Math.floor(this.penalty / 60);
|
|
@@ -415,8 +428,8 @@ class Team {
|
|
|
415
428
|
}
|
|
416
429
|
calcSolvedData() {
|
|
417
430
|
this.solvedProblemNum = 0;
|
|
418
|
-
this.penalty = 0;
|
|
419
431
|
this.attemptedProblemNum = 0;
|
|
432
|
+
this.penalty = 0;
|
|
420
433
|
for (const p of this.problemStatistics) {
|
|
421
434
|
if (p.isAccepted) {
|
|
422
435
|
this.solvedProblemNum++;
|
|
@@ -428,6 +441,24 @@ class Team {
|
|
|
428
441
|
isEqualRank(otherTeam) {
|
|
429
442
|
return this.solvedProblemNum === otherTeam.solvedProblemNum && this.penalty === otherTeam.penalty;
|
|
430
443
|
}
|
|
444
|
+
postProcessPlaceChartPoints() {
|
|
445
|
+
if (this.placeChartPoints.length === 0) {
|
|
446
|
+
return;
|
|
447
|
+
}
|
|
448
|
+
const res = [];
|
|
449
|
+
res.push(this.placeChartPoints[0]);
|
|
450
|
+
for (let i = 1; i < this.placeChartPoints.length - 1; i++) {
|
|
451
|
+
const p = this.placeChartPoints[i];
|
|
452
|
+
const preP = res[res.length - 1];
|
|
453
|
+
if (p.rank !== preP.rank || p.lastSolvedProblem !== preP.lastSolvedProblem) {
|
|
454
|
+
res.push(p);
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
if (this.placeChartPoints.length > 1) {
|
|
458
|
+
res.push(this.placeChartPoints[this.placeChartPoints.length - 1]);
|
|
459
|
+
}
|
|
460
|
+
this.placeChartPoints = res;
|
|
461
|
+
}
|
|
431
462
|
static compare(lhs, rhs) {
|
|
432
463
|
if (lhs.solvedProblemNum !== rhs.solvedProblemNum) {
|
|
433
464
|
return rhs.solvedProblemNum - lhs.solvedProblemNum;
|
|
@@ -618,6 +649,9 @@ class Submission {
|
|
|
618
649
|
isNotCalculatedPenaltyStatus() {
|
|
619
650
|
return isNotCalculatedPenaltyStatus(this.status);
|
|
620
651
|
}
|
|
652
|
+
get timestampToMinute() {
|
|
653
|
+
return Math.floor(this.timestamp / 60);
|
|
654
|
+
}
|
|
621
655
|
static compare(lhs, rhs) {
|
|
622
656
|
if (lhs.timestamp !== rhs.timestamp) {
|
|
623
657
|
return lhs.timestamp - rhs.timestamp;
|
|
@@ -694,87 +728,84 @@ class Rank {
|
|
|
694
728
|
this.contest.problems.forEach((p) => {
|
|
695
729
|
p.statistics.reset();
|
|
696
730
|
});
|
|
697
|
-
|
|
731
|
+
let preSubmissionTimestampToMinute = 0;
|
|
732
|
+
const allSubmissions = this.getSubmissions();
|
|
733
|
+
this.teams.forEach(
|
|
734
|
+
(t) => t.placeChartPoints.push({
|
|
735
|
+
timePoint: 0,
|
|
736
|
+
rank: 1,
|
|
737
|
+
lastSolvedProblem: null
|
|
738
|
+
})
|
|
739
|
+
);
|
|
740
|
+
for (let ix = 0; ix < allSubmissions.length; ix++) {
|
|
741
|
+
const s = allSubmissions[ix];
|
|
698
742
|
const teamId = s.teamId;
|
|
699
743
|
const problemId = s.problemId;
|
|
700
744
|
const team = this.teamsMap.get(teamId);
|
|
701
745
|
const problem = this.contest.problemsMap.get(problemId);
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
const problemStatistics = team.problemStatisticsMap.get(problemId);
|
|
706
|
-
const submissions = problemStatistics.submissions;
|
|
707
|
-
submissions.push(s);
|
|
708
|
-
problem.statistics.submittedNum++;
|
|
709
|
-
if (problemStatistics.isSolved) {
|
|
710
|
-
continue;
|
|
711
|
-
}
|
|
712
|
-
if (s.isIgnore || s.isNotCalculatedPenaltyStatus()) {
|
|
713
|
-
problem.statistics.ignoreNum++;
|
|
714
|
-
problemStatistics.ignoreCount++;
|
|
715
|
-
continue;
|
|
716
|
-
}
|
|
717
|
-
problemStatistics.isSubmitted = true;
|
|
718
|
-
problemStatistics.lastSubmitTimestamp = s.timestamp;
|
|
719
|
-
problemStatistics.totalCount++;
|
|
720
|
-
if (s.isAccepted()) {
|
|
721
|
-
problemStatistics.isSolved = true;
|
|
722
|
-
problemStatistics.solvedTimestamp = s.timestamp;
|
|
723
|
-
problem.statistics.acceptedNum++;
|
|
724
|
-
problem.statistics.attemptedNum += problemStatistics.failedCount + 1;
|
|
725
|
-
if (problem.statistics.firstSolveSubmissions.length === 0 || problem.statistics.firstSolveSubmissions[problem.statistics.firstSolveSubmissions.length - 1].timestamp === s.timestamp) {
|
|
726
|
-
problemStatistics.isFirstSolved = true;
|
|
727
|
-
problem.statistics.firstSolveSubmissions.push(s);
|
|
746
|
+
(() => {
|
|
747
|
+
if (team === void 0 || problem === void 0) {
|
|
748
|
+
return;
|
|
728
749
|
}
|
|
729
|
-
|
|
730
|
-
|
|
750
|
+
const problemStatistics = team.problemStatisticsMap.get(problemId);
|
|
751
|
+
const submissions = problemStatistics.submissions;
|
|
752
|
+
submissions.push(s);
|
|
753
|
+
team.submissions.push(s);
|
|
754
|
+
problem.statistics.submittedNum++;
|
|
755
|
+
if (problemStatistics.isSolved) {
|
|
756
|
+
return;
|
|
731
757
|
}
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
if (preTeam !== null) {
|
|
752
|
-
if (t.isEqualRank(preTeam)) {
|
|
753
|
-
t.rank = preTeam.rank;
|
|
758
|
+
if (s.isIgnore || s.isNotCalculatedPenaltyStatus()) {
|
|
759
|
+
problem.statistics.ignoreNum++;
|
|
760
|
+
problemStatistics.ignoreCount++;
|
|
761
|
+
return;
|
|
762
|
+
}
|
|
763
|
+
problemStatistics.isSubmitted = true;
|
|
764
|
+
problemStatistics.lastSubmitTimestamp = s.timestamp;
|
|
765
|
+
problemStatistics.totalCount++;
|
|
766
|
+
if (s.isAccepted()) {
|
|
767
|
+
problemStatistics.isSolved = true;
|
|
768
|
+
problemStatistics.solvedTimestamp = s.timestamp;
|
|
769
|
+
problem.statistics.acceptedNum++;
|
|
770
|
+
problem.statistics.attemptedNum += problemStatistics.failedCount + 1;
|
|
771
|
+
if (problem.statistics.firstSolveSubmissions.length === 0 || problem.statistics.firstSolveSubmissions[problem.statistics.firstSolveSubmissions.length - 1].timestamp === s.timestamp) {
|
|
772
|
+
problemStatistics.isFirstSolved = true;
|
|
773
|
+
problem.statistics.firstSolveSubmissions.push(s);
|
|
774
|
+
}
|
|
775
|
+
while (problem.statistics.lastSolveSubmissions.length > 0) {
|
|
776
|
+
problem.statistics.lastSolveSubmissions.pop();
|
|
754
777
|
}
|
|
778
|
+
problem.statistics.lastSolveSubmissions.push(s);
|
|
779
|
+
team.lastSolvedProblem = problem;
|
|
780
|
+
team.lastSolvedProblemTimestamp = s.timestamp;
|
|
755
781
|
}
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
if (this.contest.organization) {
|
|
760
|
-
let rank = 1;
|
|
761
|
-
let preTeam = null;
|
|
762
|
-
const se = /* @__PURE__ */ new Set();
|
|
763
|
-
for (const t of this.teams) {
|
|
764
|
-
const org = t.organization;
|
|
765
|
-
if (se.has(org)) {
|
|
766
|
-
continue;
|
|
782
|
+
if (s.isRejected()) {
|
|
783
|
+
problemStatistics.failedCount++;
|
|
784
|
+
problem.statistics.rejectedNum++;
|
|
767
785
|
}
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
if (t.isEqualRank(preTeam)) {
|
|
772
|
-
t.organizationRank = preTeam.organizationRank;
|
|
773
|
-
}
|
|
786
|
+
if (s.isPending()) {
|
|
787
|
+
problemStatistics.pendingCount++;
|
|
788
|
+
problem.statistics.pendingNum++;
|
|
774
789
|
}
|
|
775
|
-
|
|
790
|
+
})();
|
|
791
|
+
if (s.timestampToMinute > preSubmissionTimestampToMinute || ix === allSubmissions.length - 1) {
|
|
792
|
+
this.teams.forEach((t) => t.calcSolvedData());
|
|
793
|
+
this.teams.sort(Team.compare);
|
|
794
|
+
this.buildTeamRank();
|
|
795
|
+
this.teams.forEach(
|
|
796
|
+
(t) => t.placeChartPoints.push(
|
|
797
|
+
{
|
|
798
|
+
timePoint: s.timestampToMinute,
|
|
799
|
+
rank: t.rank,
|
|
800
|
+
lastSolvedProblem: t.lastSolvedProblem
|
|
801
|
+
}
|
|
802
|
+
)
|
|
803
|
+
);
|
|
776
804
|
}
|
|
805
|
+
preSubmissionTimestampToMinute = s.timestampToMinute;
|
|
777
806
|
}
|
|
807
|
+
this.teams.forEach((t) => t.postProcessPlaceChartPoints());
|
|
808
|
+
this.buildOrgRank();
|
|
778
809
|
})();
|
|
779
810
|
(() => {
|
|
780
811
|
this.rankStatistics.reset();
|
|
@@ -785,6 +816,41 @@ class Rank {
|
|
|
785
816
|
})();
|
|
786
817
|
return this;
|
|
787
818
|
}
|
|
819
|
+
buildTeamRank() {
|
|
820
|
+
let rank = 1;
|
|
821
|
+
let preTeam = null;
|
|
822
|
+
for (const t of this.teams) {
|
|
823
|
+
t.rank = rank++;
|
|
824
|
+
if (preTeam !== null) {
|
|
825
|
+
if (t.isEqualRank(preTeam)) {
|
|
826
|
+
t.rank = preTeam.rank;
|
|
827
|
+
}
|
|
828
|
+
}
|
|
829
|
+
preTeam = t;
|
|
830
|
+
}
|
|
831
|
+
}
|
|
832
|
+
buildOrgRank() {
|
|
833
|
+
if (!this.contest.organization) {
|
|
834
|
+
return;
|
|
835
|
+
}
|
|
836
|
+
let rank = 1;
|
|
837
|
+
let preTeam = null;
|
|
838
|
+
const se = /* @__PURE__ */ new Set();
|
|
839
|
+
for (const t of this.teams) {
|
|
840
|
+
const org = t.organization;
|
|
841
|
+
if (se.has(org)) {
|
|
842
|
+
continue;
|
|
843
|
+
}
|
|
844
|
+
se.add(org);
|
|
845
|
+
t.organizationRank = rank++;
|
|
846
|
+
if (preTeam !== null) {
|
|
847
|
+
if (t.isEqualRank(preTeam)) {
|
|
848
|
+
t.organizationRank = preTeam.organizationRank;
|
|
849
|
+
}
|
|
850
|
+
}
|
|
851
|
+
preTeam = t;
|
|
852
|
+
}
|
|
853
|
+
}
|
|
788
854
|
getSubmissions() {
|
|
789
855
|
if (this.options.enableFilterSubmissionsByTimestamp === false) {
|
|
790
856
|
return this.submissions;
|
|
@@ -885,6 +951,7 @@ exports.dayjs = dayjs__default;
|
|
|
885
951
|
exports.Contest = Contest;
|
|
886
952
|
exports.ContestIndex = ContestIndex;
|
|
887
953
|
exports.ContestIndexConfig = ContestIndexConfig;
|
|
954
|
+
exports.PlaceChartPointData = PlaceChartPointData;
|
|
888
955
|
exports.Problem = Problem;
|
|
889
956
|
exports.ProblemStatistics = ProblemStatistics;
|
|
890
957
|
exports.Rank = Rank;
|
package/dist/index.d.ts
CHANGED
|
@@ -14,6 +14,7 @@ declare class Submission {
|
|
|
14
14
|
isRejected(): boolean;
|
|
15
15
|
isPending(): boolean;
|
|
16
16
|
isNotCalculatedPenaltyStatus(): boolean;
|
|
17
|
+
get timestampToMinute(): number;
|
|
17
18
|
static compare(lhs: Submission, rhs: Submission): number;
|
|
18
19
|
}
|
|
19
20
|
type Submissions = Array<Submission>;
|
|
@@ -135,6 +136,12 @@ declare class RankStatistics {
|
|
|
135
136
|
reset(): void;
|
|
136
137
|
}
|
|
137
138
|
|
|
139
|
+
declare class PlaceChartPointData {
|
|
140
|
+
timePoint: number;
|
|
141
|
+
rank: number;
|
|
142
|
+
lastSolvedProblem: Problem | null;
|
|
143
|
+
constructor();
|
|
144
|
+
}
|
|
138
145
|
declare class Team {
|
|
139
146
|
id: string;
|
|
140
147
|
name: string;
|
|
@@ -148,16 +155,20 @@ declare class Team {
|
|
|
148
155
|
organizationRank: number;
|
|
149
156
|
solvedProblemNum: number;
|
|
150
157
|
attemptedProblemNum: number;
|
|
158
|
+
lastSolvedProblem: Problem | null;
|
|
151
159
|
lastSolvedProblemTimestamp: number;
|
|
152
160
|
penalty: number;
|
|
153
161
|
problemStatistics: Array<TeamProblemStatistics>;
|
|
154
162
|
problemStatisticsMap: Map<string, TeamProblemStatistics>;
|
|
163
|
+
submissions: Submissions;
|
|
164
|
+
placeChartPoints: Array<PlaceChartPointData>;
|
|
155
165
|
constructor();
|
|
156
166
|
reset(): void;
|
|
157
167
|
get penaltyToMinute(): number;
|
|
158
168
|
get dict(): number;
|
|
159
169
|
calcSolvedData(): void;
|
|
160
170
|
isEqualRank(otherTeam: Team): boolean;
|
|
171
|
+
postProcessPlaceChartPoints(): void;
|
|
161
172
|
static compare(lhs: Team, rhs: Team): number;
|
|
162
173
|
}
|
|
163
174
|
type Teams = Array<Team>;
|
|
@@ -182,6 +193,8 @@ declare class Rank {
|
|
|
182
193
|
options: RankOptions;
|
|
183
194
|
constructor(contest: Contest, teams: Teams, submissions: Submissions);
|
|
184
195
|
buildRank(): this;
|
|
196
|
+
buildTeamRank(): void;
|
|
197
|
+
buildOrgRank(): void;
|
|
185
198
|
getSubmissions(): Submissions;
|
|
186
199
|
}
|
|
187
200
|
|
|
@@ -209,4 +222,4 @@ declare function isRejected(status: SubmissionStatus): boolean;
|
|
|
209
222
|
declare function isPending(status: SubmissionStatus): boolean;
|
|
210
223
|
declare function isNotCalculatedPenaltyStatus(status: SubmissionStatus): boolean;
|
|
211
224
|
|
|
212
|
-
export { Contest, ContestIndex, ContestIndexConfig, ContestIndexList, Problem, ProblemStatistics, Problems, Rank, RankOptions, RankStatistics, Resolver, 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 };
|
|
225
|
+
export { Contest, ContestIndex, ContestIndexConfig, ContestIndexList, PlaceChartPointData, Problem, ProblemStatistics, Problems, Rank, RankOptions, RankStatistics, Resolver, 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 };
|
package/dist/index.mjs
CHANGED
|
@@ -363,6 +363,13 @@ class RankStatistics {
|
|
|
363
363
|
}
|
|
364
364
|
}
|
|
365
365
|
|
|
366
|
+
class PlaceChartPointData {
|
|
367
|
+
constructor() {
|
|
368
|
+
this.timePoint = 0;
|
|
369
|
+
this.rank = 0;
|
|
370
|
+
this.lastSolvedProblem = null;
|
|
371
|
+
}
|
|
372
|
+
}
|
|
366
373
|
class Team {
|
|
367
374
|
constructor() {
|
|
368
375
|
this.id = "";
|
|
@@ -374,20 +381,26 @@ class Team {
|
|
|
374
381
|
this.organizationRank = -1;
|
|
375
382
|
this.solvedProblemNum = 0;
|
|
376
383
|
this.attemptedProblemNum = 0;
|
|
384
|
+
this.lastSolvedProblem = null;
|
|
377
385
|
this.lastSolvedProblemTimestamp = 0;
|
|
378
386
|
this.penalty = 0;
|
|
379
387
|
this.problemStatistics = [];
|
|
380
388
|
this.problemStatisticsMap = /* @__PURE__ */ new Map();
|
|
389
|
+
this.submissions = [];
|
|
390
|
+
this.placeChartPoints = [];
|
|
381
391
|
}
|
|
382
392
|
reset() {
|
|
383
393
|
this.rank = 0;
|
|
384
394
|
this.organizationRank = -1;
|
|
385
395
|
this.solvedProblemNum = 0;
|
|
386
396
|
this.attemptedProblemNum = 0;
|
|
397
|
+
this.lastSolvedProblem = null;
|
|
387
398
|
this.lastSolvedProblemTimestamp = 0;
|
|
388
399
|
this.penalty = 0;
|
|
389
400
|
this.problemStatistics = [];
|
|
390
401
|
this.problemStatisticsMap = /* @__PURE__ */ new Map();
|
|
402
|
+
this.submissions = [];
|
|
403
|
+
this.placeChartPoints = [];
|
|
391
404
|
}
|
|
392
405
|
get penaltyToMinute() {
|
|
393
406
|
return Math.floor(this.penalty / 60);
|
|
@@ -399,8 +412,8 @@ class Team {
|
|
|
399
412
|
}
|
|
400
413
|
calcSolvedData() {
|
|
401
414
|
this.solvedProblemNum = 0;
|
|
402
|
-
this.penalty = 0;
|
|
403
415
|
this.attemptedProblemNum = 0;
|
|
416
|
+
this.penalty = 0;
|
|
404
417
|
for (const p of this.problemStatistics) {
|
|
405
418
|
if (p.isAccepted) {
|
|
406
419
|
this.solvedProblemNum++;
|
|
@@ -412,6 +425,24 @@ class Team {
|
|
|
412
425
|
isEqualRank(otherTeam) {
|
|
413
426
|
return this.solvedProblemNum === otherTeam.solvedProblemNum && this.penalty === otherTeam.penalty;
|
|
414
427
|
}
|
|
428
|
+
postProcessPlaceChartPoints() {
|
|
429
|
+
if (this.placeChartPoints.length === 0) {
|
|
430
|
+
return;
|
|
431
|
+
}
|
|
432
|
+
const res = [];
|
|
433
|
+
res.push(this.placeChartPoints[0]);
|
|
434
|
+
for (let i = 1; i < this.placeChartPoints.length - 1; i++) {
|
|
435
|
+
const p = this.placeChartPoints[i];
|
|
436
|
+
const preP = res[res.length - 1];
|
|
437
|
+
if (p.rank !== preP.rank || p.lastSolvedProblem !== preP.lastSolvedProblem) {
|
|
438
|
+
res.push(p);
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
if (this.placeChartPoints.length > 1) {
|
|
442
|
+
res.push(this.placeChartPoints[this.placeChartPoints.length - 1]);
|
|
443
|
+
}
|
|
444
|
+
this.placeChartPoints = res;
|
|
445
|
+
}
|
|
415
446
|
static compare(lhs, rhs) {
|
|
416
447
|
if (lhs.solvedProblemNum !== rhs.solvedProblemNum) {
|
|
417
448
|
return rhs.solvedProblemNum - lhs.solvedProblemNum;
|
|
@@ -602,6 +633,9 @@ class Submission {
|
|
|
602
633
|
isNotCalculatedPenaltyStatus() {
|
|
603
634
|
return isNotCalculatedPenaltyStatus(this.status);
|
|
604
635
|
}
|
|
636
|
+
get timestampToMinute() {
|
|
637
|
+
return Math.floor(this.timestamp / 60);
|
|
638
|
+
}
|
|
605
639
|
static compare(lhs, rhs) {
|
|
606
640
|
if (lhs.timestamp !== rhs.timestamp) {
|
|
607
641
|
return lhs.timestamp - rhs.timestamp;
|
|
@@ -678,87 +712,84 @@ class Rank {
|
|
|
678
712
|
this.contest.problems.forEach((p) => {
|
|
679
713
|
p.statistics.reset();
|
|
680
714
|
});
|
|
681
|
-
|
|
715
|
+
let preSubmissionTimestampToMinute = 0;
|
|
716
|
+
const allSubmissions = this.getSubmissions();
|
|
717
|
+
this.teams.forEach(
|
|
718
|
+
(t) => t.placeChartPoints.push({
|
|
719
|
+
timePoint: 0,
|
|
720
|
+
rank: 1,
|
|
721
|
+
lastSolvedProblem: null
|
|
722
|
+
})
|
|
723
|
+
);
|
|
724
|
+
for (let ix = 0; ix < allSubmissions.length; ix++) {
|
|
725
|
+
const s = allSubmissions[ix];
|
|
682
726
|
const teamId = s.teamId;
|
|
683
727
|
const problemId = s.problemId;
|
|
684
728
|
const team = this.teamsMap.get(teamId);
|
|
685
729
|
const problem = this.contest.problemsMap.get(problemId);
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
const problemStatistics = team.problemStatisticsMap.get(problemId);
|
|
690
|
-
const submissions = problemStatistics.submissions;
|
|
691
|
-
submissions.push(s);
|
|
692
|
-
problem.statistics.submittedNum++;
|
|
693
|
-
if (problemStatistics.isSolved) {
|
|
694
|
-
continue;
|
|
695
|
-
}
|
|
696
|
-
if (s.isIgnore || s.isNotCalculatedPenaltyStatus()) {
|
|
697
|
-
problem.statistics.ignoreNum++;
|
|
698
|
-
problemStatistics.ignoreCount++;
|
|
699
|
-
continue;
|
|
700
|
-
}
|
|
701
|
-
problemStatistics.isSubmitted = true;
|
|
702
|
-
problemStatistics.lastSubmitTimestamp = s.timestamp;
|
|
703
|
-
problemStatistics.totalCount++;
|
|
704
|
-
if (s.isAccepted()) {
|
|
705
|
-
problemStatistics.isSolved = true;
|
|
706
|
-
problemStatistics.solvedTimestamp = s.timestamp;
|
|
707
|
-
problem.statistics.acceptedNum++;
|
|
708
|
-
problem.statistics.attemptedNum += problemStatistics.failedCount + 1;
|
|
709
|
-
if (problem.statistics.firstSolveSubmissions.length === 0 || problem.statistics.firstSolveSubmissions[problem.statistics.firstSolveSubmissions.length - 1].timestamp === s.timestamp) {
|
|
710
|
-
problemStatistics.isFirstSolved = true;
|
|
711
|
-
problem.statistics.firstSolveSubmissions.push(s);
|
|
730
|
+
(() => {
|
|
731
|
+
if (team === void 0 || problem === void 0) {
|
|
732
|
+
return;
|
|
712
733
|
}
|
|
713
|
-
|
|
714
|
-
|
|
734
|
+
const problemStatistics = team.problemStatisticsMap.get(problemId);
|
|
735
|
+
const submissions = problemStatistics.submissions;
|
|
736
|
+
submissions.push(s);
|
|
737
|
+
team.submissions.push(s);
|
|
738
|
+
problem.statistics.submittedNum++;
|
|
739
|
+
if (problemStatistics.isSolved) {
|
|
740
|
+
return;
|
|
715
741
|
}
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
if (preTeam !== null) {
|
|
736
|
-
if (t.isEqualRank(preTeam)) {
|
|
737
|
-
t.rank = preTeam.rank;
|
|
742
|
+
if (s.isIgnore || s.isNotCalculatedPenaltyStatus()) {
|
|
743
|
+
problem.statistics.ignoreNum++;
|
|
744
|
+
problemStatistics.ignoreCount++;
|
|
745
|
+
return;
|
|
746
|
+
}
|
|
747
|
+
problemStatistics.isSubmitted = true;
|
|
748
|
+
problemStatistics.lastSubmitTimestamp = s.timestamp;
|
|
749
|
+
problemStatistics.totalCount++;
|
|
750
|
+
if (s.isAccepted()) {
|
|
751
|
+
problemStatistics.isSolved = true;
|
|
752
|
+
problemStatistics.solvedTimestamp = s.timestamp;
|
|
753
|
+
problem.statistics.acceptedNum++;
|
|
754
|
+
problem.statistics.attemptedNum += problemStatistics.failedCount + 1;
|
|
755
|
+
if (problem.statistics.firstSolveSubmissions.length === 0 || problem.statistics.firstSolveSubmissions[problem.statistics.firstSolveSubmissions.length - 1].timestamp === s.timestamp) {
|
|
756
|
+
problemStatistics.isFirstSolved = true;
|
|
757
|
+
problem.statistics.firstSolveSubmissions.push(s);
|
|
758
|
+
}
|
|
759
|
+
while (problem.statistics.lastSolveSubmissions.length > 0) {
|
|
760
|
+
problem.statistics.lastSolveSubmissions.pop();
|
|
738
761
|
}
|
|
762
|
+
problem.statistics.lastSolveSubmissions.push(s);
|
|
763
|
+
team.lastSolvedProblem = problem;
|
|
764
|
+
team.lastSolvedProblemTimestamp = s.timestamp;
|
|
739
765
|
}
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
if (this.contest.organization) {
|
|
744
|
-
let rank = 1;
|
|
745
|
-
let preTeam = null;
|
|
746
|
-
const se = /* @__PURE__ */ new Set();
|
|
747
|
-
for (const t of this.teams) {
|
|
748
|
-
const org = t.organization;
|
|
749
|
-
if (se.has(org)) {
|
|
750
|
-
continue;
|
|
766
|
+
if (s.isRejected()) {
|
|
767
|
+
problemStatistics.failedCount++;
|
|
768
|
+
problem.statistics.rejectedNum++;
|
|
751
769
|
}
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
if (t.isEqualRank(preTeam)) {
|
|
756
|
-
t.organizationRank = preTeam.organizationRank;
|
|
757
|
-
}
|
|
770
|
+
if (s.isPending()) {
|
|
771
|
+
problemStatistics.pendingCount++;
|
|
772
|
+
problem.statistics.pendingNum++;
|
|
758
773
|
}
|
|
759
|
-
|
|
774
|
+
})();
|
|
775
|
+
if (s.timestampToMinute > preSubmissionTimestampToMinute || ix === allSubmissions.length - 1) {
|
|
776
|
+
this.teams.forEach((t) => t.calcSolvedData());
|
|
777
|
+
this.teams.sort(Team.compare);
|
|
778
|
+
this.buildTeamRank();
|
|
779
|
+
this.teams.forEach(
|
|
780
|
+
(t) => t.placeChartPoints.push(
|
|
781
|
+
{
|
|
782
|
+
timePoint: s.timestampToMinute,
|
|
783
|
+
rank: t.rank,
|
|
784
|
+
lastSolvedProblem: t.lastSolvedProblem
|
|
785
|
+
}
|
|
786
|
+
)
|
|
787
|
+
);
|
|
760
788
|
}
|
|
789
|
+
preSubmissionTimestampToMinute = s.timestampToMinute;
|
|
761
790
|
}
|
|
791
|
+
this.teams.forEach((t) => t.postProcessPlaceChartPoints());
|
|
792
|
+
this.buildOrgRank();
|
|
762
793
|
})();
|
|
763
794
|
(() => {
|
|
764
795
|
this.rankStatistics.reset();
|
|
@@ -769,6 +800,41 @@ class Rank {
|
|
|
769
800
|
})();
|
|
770
801
|
return this;
|
|
771
802
|
}
|
|
803
|
+
buildTeamRank() {
|
|
804
|
+
let rank = 1;
|
|
805
|
+
let preTeam = null;
|
|
806
|
+
for (const t of this.teams) {
|
|
807
|
+
t.rank = rank++;
|
|
808
|
+
if (preTeam !== null) {
|
|
809
|
+
if (t.isEqualRank(preTeam)) {
|
|
810
|
+
t.rank = preTeam.rank;
|
|
811
|
+
}
|
|
812
|
+
}
|
|
813
|
+
preTeam = t;
|
|
814
|
+
}
|
|
815
|
+
}
|
|
816
|
+
buildOrgRank() {
|
|
817
|
+
if (!this.contest.organization) {
|
|
818
|
+
return;
|
|
819
|
+
}
|
|
820
|
+
let rank = 1;
|
|
821
|
+
let preTeam = null;
|
|
822
|
+
const se = /* @__PURE__ */ new Set();
|
|
823
|
+
for (const t of this.teams) {
|
|
824
|
+
const org = t.organization;
|
|
825
|
+
if (se.has(org)) {
|
|
826
|
+
continue;
|
|
827
|
+
}
|
|
828
|
+
se.add(org);
|
|
829
|
+
t.organizationRank = rank++;
|
|
830
|
+
if (preTeam !== null) {
|
|
831
|
+
if (t.isEqualRank(preTeam)) {
|
|
832
|
+
t.organizationRank = preTeam.organizationRank;
|
|
833
|
+
}
|
|
834
|
+
}
|
|
835
|
+
preTeam = t;
|
|
836
|
+
}
|
|
837
|
+
}
|
|
772
838
|
getSubmissions() {
|
|
773
839
|
if (this.options.enableFilterSubmissionsByTimestamp === false) {
|
|
774
840
|
return this.submissions;
|
|
@@ -865,4 +931,4 @@ class Resolver extends Rank {
|
|
|
865
931
|
}
|
|
866
932
|
}
|
|
867
933
|
|
|
868
|
-
export { Contest, ContestIndex, ContestIndexConfig, 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 };
|
|
934
|
+
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 };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xcpcio/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.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.
|
|
45
|
+
"@xcpcio/types": "0.5.0"
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
48
|
"@babel/types": "^7.22.4",
|
package/src/rank.ts
CHANGED
|
@@ -77,113 +77,108 @@ export class Rank {
|
|
|
77
77
|
p.statistics.reset();
|
|
78
78
|
});
|
|
79
79
|
|
|
80
|
-
|
|
80
|
+
let preSubmissionTimestampToMinute = 0;
|
|
81
|
+
const allSubmissions = this.getSubmissions();
|
|
82
|
+
|
|
83
|
+
this.teams.forEach(t =>
|
|
84
|
+
t.placeChartPoints.push({
|
|
85
|
+
timePoint: 0,
|
|
86
|
+
rank: 1,
|
|
87
|
+
lastSolvedProblem: null,
|
|
88
|
+
}),
|
|
89
|
+
);
|
|
90
|
+
|
|
91
|
+
for (let ix = 0; ix < allSubmissions.length; ix++) {
|
|
92
|
+
const s = allSubmissions[ix];
|
|
93
|
+
|
|
81
94
|
const teamId = s.teamId;
|
|
82
95
|
const problemId = s.problemId;
|
|
83
96
|
const team = this.teamsMap.get(teamId);
|
|
84
97
|
const problem = this.contest.problemsMap.get(problemId);
|
|
85
98
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
const problemStatistics = team.problemStatisticsMap.get(problemId) as TeamProblemStatistics;
|
|
91
|
-
const submissions = problemStatistics.submissions;
|
|
92
|
-
|
|
93
|
-
submissions.push(s);
|
|
94
|
-
problem.statistics.submittedNum++;
|
|
95
|
-
|
|
96
|
-
if (problemStatistics.isSolved) {
|
|
97
|
-
continue;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
if (s.isIgnore || s.isNotCalculatedPenaltyStatus()) {
|
|
101
|
-
problem.statistics.ignoreNum++;
|
|
102
|
-
problemStatistics.ignoreCount++;
|
|
103
|
-
continue;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
problemStatistics.isSubmitted = true;
|
|
107
|
-
problemStatistics.lastSubmitTimestamp = s.timestamp;
|
|
108
|
-
problemStatistics.totalCount++;
|
|
99
|
+
(() => {
|
|
100
|
+
if (team === undefined || problem === undefined) {
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
109
103
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
problemStatistics.solvedTimestamp = s.timestamp;
|
|
104
|
+
const problemStatistics = team.problemStatisticsMap.get(problemId) as TeamProblemStatistics;
|
|
105
|
+
const submissions = problemStatistics.submissions;
|
|
113
106
|
|
|
114
|
-
|
|
115
|
-
|
|
107
|
+
submissions.push(s);
|
|
108
|
+
team.submissions.push(s);
|
|
109
|
+
problem.statistics.submittedNum++;
|
|
116
110
|
|
|
117
|
-
if (
|
|
118
|
-
|
|
119
|
-
|| problem.statistics.firstSolveSubmissions[problem.statistics.firstSolveSubmissions.length - 1].timestamp === s.timestamp
|
|
120
|
-
) {
|
|
121
|
-
problemStatistics.isFirstSolved = true;
|
|
122
|
-
problem.statistics.firstSolveSubmissions.push(s);
|
|
111
|
+
if (problemStatistics.isSolved) {
|
|
112
|
+
return;
|
|
123
113
|
}
|
|
124
114
|
|
|
125
|
-
|
|
126
|
-
problem.statistics.
|
|
115
|
+
if (s.isIgnore || s.isNotCalculatedPenaltyStatus()) {
|
|
116
|
+
problem.statistics.ignoreNum++;
|
|
117
|
+
problemStatistics.ignoreCount++;
|
|
118
|
+
return;
|
|
127
119
|
}
|
|
128
120
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
if (s.isRejected()) {
|
|
134
|
-
problemStatistics.failedCount++;
|
|
135
|
-
problem.statistics.rejectedNum++;
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
if (s.isPending()) {
|
|
139
|
-
problemStatistics.pendingCount++;
|
|
140
|
-
problem.statistics.pendingNum++;
|
|
141
|
-
}
|
|
142
|
-
}
|
|
121
|
+
problemStatistics.isSubmitted = true;
|
|
122
|
+
problemStatistics.lastSubmitTimestamp = s.timestamp;
|
|
123
|
+
problemStatistics.totalCount++;
|
|
143
124
|
|
|
144
|
-
|
|
145
|
-
|
|
125
|
+
if (s.isAccepted()) {
|
|
126
|
+
problemStatistics.isSolved = true;
|
|
127
|
+
problemStatistics.solvedTimestamp = s.timestamp;
|
|
146
128
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
let preTeam = null;
|
|
150
|
-
for (const t of this.teams) {
|
|
151
|
-
t.rank = rank++;
|
|
129
|
+
problem.statistics.acceptedNum++;
|
|
130
|
+
problem.statistics.attemptedNum += problemStatistics.failedCount + 1;
|
|
152
131
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
132
|
+
if (
|
|
133
|
+
problem.statistics.firstSolveSubmissions.length === 0
|
|
134
|
+
|| problem.statistics.firstSolveSubmissions[problem.statistics.firstSolveSubmissions.length - 1].timestamp === s.timestamp
|
|
135
|
+
) {
|
|
136
|
+
problemStatistics.isFirstSolved = true;
|
|
137
|
+
problem.statistics.firstSolveSubmissions.push(s);
|
|
156
138
|
}
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
preTeam = t;
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
139
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
140
|
+
while (problem.statistics.lastSolveSubmissions.length > 0) {
|
|
141
|
+
problem.statistics.lastSolveSubmissions.pop();
|
|
142
|
+
}
|
|
166
143
|
|
|
167
|
-
|
|
144
|
+
problem.statistics.lastSolveSubmissions.push(s);
|
|
168
145
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
if (se.has(org)) {
|
|
172
|
-
continue;
|
|
146
|
+
team.lastSolvedProblem = problem;
|
|
147
|
+
team.lastSolvedProblemTimestamp = s.timestamp;
|
|
173
148
|
}
|
|
174
149
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
if (preTeam !== null) {
|
|
179
|
-
if (t.isEqualRank(preTeam)) {
|
|
180
|
-
t.organizationRank = preTeam.organizationRank;
|
|
181
|
-
}
|
|
150
|
+
if (s.isRejected()) {
|
|
151
|
+
problemStatistics.failedCount++;
|
|
152
|
+
problem.statistics.rejectedNum++;
|
|
182
153
|
}
|
|
183
154
|
|
|
184
|
-
|
|
155
|
+
if (s.isPending()) {
|
|
156
|
+
problemStatistics.pendingCount++;
|
|
157
|
+
problem.statistics.pendingNum++;
|
|
158
|
+
}
|
|
159
|
+
})();
|
|
160
|
+
|
|
161
|
+
if (s.timestampToMinute > preSubmissionTimestampToMinute || ix === allSubmissions.length - 1) {
|
|
162
|
+
this.teams.forEach(t => t.calcSolvedData());
|
|
163
|
+
this.teams.sort(Team.compare);
|
|
164
|
+
this.buildTeamRank();
|
|
165
|
+
|
|
166
|
+
this.teams.forEach(t =>
|
|
167
|
+
t.placeChartPoints.push(
|
|
168
|
+
{
|
|
169
|
+
timePoint: s.timestampToMinute,
|
|
170
|
+
rank: t.rank,
|
|
171
|
+
lastSolvedProblem: t.lastSolvedProblem,
|
|
172
|
+
},
|
|
173
|
+
),
|
|
174
|
+
);
|
|
185
175
|
}
|
|
176
|
+
|
|
177
|
+
preSubmissionTimestampToMinute = s.timestampToMinute;
|
|
186
178
|
}
|
|
179
|
+
|
|
180
|
+
this.teams.forEach(t => t.postProcessPlaceChartPoints());
|
|
181
|
+
this.buildOrgRank();
|
|
187
182
|
})();
|
|
188
183
|
|
|
189
184
|
(() => {
|
|
@@ -198,6 +193,51 @@ export class Rank {
|
|
|
198
193
|
return this;
|
|
199
194
|
}
|
|
200
195
|
|
|
196
|
+
buildTeamRank() {
|
|
197
|
+
let rank = 1;
|
|
198
|
+
let preTeam = null;
|
|
199
|
+
for (const t of this.teams) {
|
|
200
|
+
t.rank = rank++;
|
|
201
|
+
|
|
202
|
+
if (preTeam !== null) {
|
|
203
|
+
if (t.isEqualRank(preTeam)) {
|
|
204
|
+
t.rank = preTeam.rank;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
preTeam = t;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
buildOrgRank() {
|
|
213
|
+
if (!this.contest.organization) {
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
let rank = 1;
|
|
218
|
+
let preTeam = null;
|
|
219
|
+
|
|
220
|
+
const se = new Set<string>();
|
|
221
|
+
|
|
222
|
+
for (const t of this.teams) {
|
|
223
|
+
const org = t.organization;
|
|
224
|
+
if (se.has(org)) {
|
|
225
|
+
continue;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
se.add(org);
|
|
229
|
+
t.organizationRank = rank++;
|
|
230
|
+
|
|
231
|
+
if (preTeam !== null) {
|
|
232
|
+
if (t.isEqualRank(preTeam)) {
|
|
233
|
+
t.organizationRank = preTeam.organizationRank;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
preTeam = t;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
201
241
|
getSubmissions() {
|
|
202
242
|
if (this.options.enableFilterSubmissionsByTimestamp === false) {
|
|
203
243
|
return this.submissions;
|
package/src/submission.ts
CHANGED
|
@@ -41,6 +41,10 @@ export class Submission {
|
|
|
41
41
|
return isNotCalculatedPenaltyStatus(this.status);
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
+
get timestampToMinute() {
|
|
45
|
+
return Math.floor(this.timestamp / 60);
|
|
46
|
+
}
|
|
47
|
+
|
|
44
48
|
static compare(lhs: Submission, rhs: Submission): number {
|
|
45
49
|
if (lhs.timestamp !== rhs.timestamp) {
|
|
46
50
|
return lhs.timestamp - rhs.timestamp;
|
package/src/team.ts
CHANGED
|
@@ -1,7 +1,20 @@
|
|
|
1
1
|
import type { Team as ITeam, Teams as ITeams, Image } from "@xcpcio/types";
|
|
2
2
|
|
|
3
|
-
import type { TeamProblemStatistics } from "./problem";
|
|
3
|
+
import type { Problem, TeamProblemStatistics } from "./problem";
|
|
4
4
|
import { calcDict } from "./utils";
|
|
5
|
+
import type { Submissions } from "./submission";
|
|
6
|
+
|
|
7
|
+
export class PlaceChartPointData {
|
|
8
|
+
timePoint: number;
|
|
9
|
+
rank: number;
|
|
10
|
+
lastSolvedProblem: Problem | null;
|
|
11
|
+
|
|
12
|
+
constructor() {
|
|
13
|
+
this.timePoint = 0;
|
|
14
|
+
this.rank = 0;
|
|
15
|
+
this.lastSolvedProblem = null;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
5
18
|
|
|
6
19
|
export class Team {
|
|
7
20
|
id: string;
|
|
@@ -21,6 +34,8 @@ export class Team {
|
|
|
21
34
|
|
|
22
35
|
solvedProblemNum: number;
|
|
23
36
|
attemptedProblemNum: number;
|
|
37
|
+
|
|
38
|
+
lastSolvedProblem: Problem | null;
|
|
24
39
|
lastSolvedProblemTimestamp: number;
|
|
25
40
|
|
|
26
41
|
penalty: number;
|
|
@@ -28,6 +43,10 @@ export class Team {
|
|
|
28
43
|
problemStatistics: Array<TeamProblemStatistics>;
|
|
29
44
|
problemStatisticsMap: Map<string, TeamProblemStatistics>;
|
|
30
45
|
|
|
46
|
+
submissions: Submissions;
|
|
47
|
+
|
|
48
|
+
placeChartPoints: Array<PlaceChartPointData>;
|
|
49
|
+
|
|
31
50
|
constructor() {
|
|
32
51
|
this.id = "";
|
|
33
52
|
this.name = "";
|
|
@@ -42,12 +61,18 @@ export class Team {
|
|
|
42
61
|
|
|
43
62
|
this.solvedProblemNum = 0;
|
|
44
63
|
this.attemptedProblemNum = 0;
|
|
64
|
+
|
|
65
|
+
this.lastSolvedProblem = null;
|
|
45
66
|
this.lastSolvedProblemTimestamp = 0;
|
|
46
67
|
|
|
47
68
|
this.penalty = 0;
|
|
48
69
|
|
|
49
70
|
this.problemStatistics = [];
|
|
50
71
|
this.problemStatisticsMap = new Map<string, TeamProblemStatistics>();
|
|
72
|
+
|
|
73
|
+
this.submissions = [];
|
|
74
|
+
|
|
75
|
+
this.placeChartPoints = [];
|
|
51
76
|
}
|
|
52
77
|
|
|
53
78
|
reset() {
|
|
@@ -56,12 +81,18 @@ export class Team {
|
|
|
56
81
|
|
|
57
82
|
this.solvedProblemNum = 0;
|
|
58
83
|
this.attemptedProblemNum = 0;
|
|
84
|
+
|
|
85
|
+
this.lastSolvedProblem = null;
|
|
59
86
|
this.lastSolvedProblemTimestamp = 0;
|
|
60
87
|
|
|
61
88
|
this.penalty = 0;
|
|
62
89
|
|
|
63
90
|
this.problemStatistics = [];
|
|
64
91
|
this.problemStatisticsMap = new Map<string, TeamProblemStatistics>();
|
|
92
|
+
|
|
93
|
+
this.submissions = [];
|
|
94
|
+
|
|
95
|
+
this.placeChartPoints = [];
|
|
65
96
|
}
|
|
66
97
|
|
|
67
98
|
get penaltyToMinute() {
|
|
@@ -77,9 +108,10 @@ export class Team {
|
|
|
77
108
|
|
|
78
109
|
calcSolvedData() {
|
|
79
110
|
this.solvedProblemNum = 0;
|
|
80
|
-
this.penalty = 0;
|
|
81
111
|
this.attemptedProblemNum = 0;
|
|
82
112
|
|
|
113
|
+
this.penalty = 0;
|
|
114
|
+
|
|
83
115
|
for (const p of this.problemStatistics) {
|
|
84
116
|
if (p.isAccepted) {
|
|
85
117
|
this.solvedProblemNum++;
|
|
@@ -94,6 +126,30 @@ export class Team {
|
|
|
94
126
|
return this.solvedProblemNum === otherTeam.solvedProblemNum && this.penalty === otherTeam.penalty;
|
|
95
127
|
}
|
|
96
128
|
|
|
129
|
+
postProcessPlaceChartPoints() {
|
|
130
|
+
if (this.placeChartPoints.length === 0) {
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
const res = [];
|
|
135
|
+
res.push(this.placeChartPoints[0]);
|
|
136
|
+
|
|
137
|
+
for (let i = 1; i < this.placeChartPoints.length - 1; i++) {
|
|
138
|
+
const p = this.placeChartPoints[i];
|
|
139
|
+
const preP = res[res.length - 1];
|
|
140
|
+
|
|
141
|
+
if (p.rank !== preP.rank || p.lastSolvedProblem !== preP.lastSolvedProblem) {
|
|
142
|
+
res.push(p);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
if (this.placeChartPoints.length > 1) {
|
|
147
|
+
res.push(this.placeChartPoints[this.placeChartPoints.length - 1]);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
this.placeChartPoints = res;
|
|
151
|
+
}
|
|
152
|
+
|
|
97
153
|
static compare(lhs: Team, rhs: Team): number {
|
|
98
154
|
if (lhs.solvedProblemNum !== rhs.solvedProblemNum) {
|
|
99
155
|
return rhs.solvedProblemNum - lhs.solvedProblemNum;
|