@xcpcio/core 0.58.3 → 0.59.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/src/resolver.ts DELETED
@@ -1,138 +0,0 @@
1
- import type { Contest } from "./contest";
2
- import type { TeamProblemStatistics } from "./problem";
3
- import type { Submissions } from "./submission";
4
- import type { Teams } from "./team";
5
-
6
- import _ from "lodash";
7
-
8
- import { Rank } from "./rank";
9
- import { ResolverOperation } from "./resolver-operation";
10
- import { Submission } from "./submission";
11
- import { Team } from "./team";
12
-
13
- export class Resolver extends Rank {
14
- finalRank: Rank;
15
- operations: Array<ResolverOperation>;
16
-
17
- beforeFreezeSubmissions: Submissions;
18
- afterFreezeSubmissions: Submissions;
19
-
20
- constructor(contest: Contest, teams: Teams, submissions: Submissions) {
21
- submissions.sort(Submission.compare);
22
-
23
- let beforeFreezeSubmissions = submissions;
24
- let afterFreezeSubmissions = submissions;
25
-
26
- {
27
- // TODO(Dup4): Remove this block
28
- let unFreezeDurationTimestamp = contest.unFreezeDurationTimestamp;
29
- if (contest.options.submissionTimestampUnit === "millisecond") {
30
- unFreezeDurationTimestamp *= 1000;
31
- }
32
- if (contest.options.submissionTimestampUnit === "microsecond") {
33
- unFreezeDurationTimestamp *= 1000000;
34
- }
35
- if (contest.options.submissionTimestampUnit === "nanosecond") {
36
- unFreezeDurationTimestamp *= 1000000000;
37
- }
38
-
39
- const ix = _.sortedIndex(
40
- submissions.map(s => s.timestamp),
41
- unFreezeDurationTimestamp,
42
- );
43
-
44
- beforeFreezeSubmissions = submissions.slice(0, ix + 1);
45
- afterFreezeSubmissions = submissions.slice(ix, -1);
46
- }
47
-
48
- super(contest, teams, beforeFreezeSubmissions);
49
-
50
- this.finalRank = new Rank(contest, teams, submissions);
51
- this.operations = [];
52
-
53
- this.beforeFreezeSubmissions = beforeFreezeSubmissions;
54
- this.afterFreezeSubmissions = afterFreezeSubmissions;
55
- }
56
-
57
- buildResolver() {
58
- this.buildRank();
59
- this.finalRank.buildRank();
60
-
61
- this.teams.forEach(t => t.rank = t.originalRank);
62
- this.finalRank.teams.forEach(t => t.rank = t.originalRank);
63
-
64
- for (const s of this.afterFreezeSubmissions) {
65
- const teamId = s.teamId;
66
- const problemId = s.problemId;
67
- const team = this.teamsMap.get(teamId);
68
- const problem = this.contest.problemsMap.get(problemId);
69
-
70
- if (team === undefined || problem === undefined) {
71
- continue;
72
- }
73
-
74
- const problemStatistics = team.problemStatisticsMap.get(problemId) as TeamProblemStatistics;
75
-
76
- problemStatistics.pendingCount++;
77
- problemStatistics.totalCount++;
78
- if (!problemStatistics.isAccepted) {
79
- problemStatistics.lastSubmitTimestamp = s.timestamp;
80
- }
81
- }
82
-
83
- {
84
- const teams_ = _.cloneDeep(this.teams);
85
-
86
- for (let i = this.teams.length - 1; i >= 0;) {
87
- const team = teams_[i];
88
- const teamId = team.id;
89
-
90
- let handleCnt = 0;
91
- let problemIx = -1;
92
- for (const p of team.problemStatistics) {
93
- problemIx++;
94
-
95
- if (!p.isPending) {
96
- continue;
97
- }
98
-
99
- handleCnt++;
100
-
101
- const beforeTeamProblemStatistics = this.teamsMap.get(teamId)?.problemStatistics[
102
- problemIx
103
- ] as TeamProblemStatistics;
104
- const afterTeamProblemStatistics = this.finalRank.teamsMap.get(teamId)?.problemStatistics[
105
- problemIx
106
- ] as TeamProblemStatistics;
107
-
108
- const op = new ResolverOperation();
109
- op.id = this.operations.length;
110
- op.team = this.teamsMap.get(teamId) as Team;
111
- op.problemIx = problemIx;
112
-
113
- op.beforeTeamProblemStatistics = beforeTeamProblemStatistics;
114
- op.afterTeamProblemStatistics = afterTeamProblemStatistics;
115
-
116
- this.operations.push(op);
117
-
118
- team.problemStatistics[problemIx] = afterTeamProblemStatistics;
119
- team.calcSolvedData(this.contest.options);
120
-
121
- break;
122
- }
123
-
124
- {
125
- let j = i;
126
- while (j > 0 && Team.compare(teams_[j], teams_[j - 1]) < 0) {
127
- [teams_[j], teams_[j - 1]] = [teams_[j - 1], teams_[j]];
128
- j--;
129
- }
130
- }
131
-
132
- if (handleCnt === 0) {
133
- i--;
134
- }
135
- }
136
- }
137
- }
138
- }
@@ -1,157 +0,0 @@
1
- import { SubmissionStatus } from "@xcpcio/types";
2
-
3
- export function stringToSubmissionStatus(status: string): SubmissionStatus {
4
- status = status.toUpperCase().replace(" ", "_");
5
-
6
- if (["OK", "AC", SubmissionStatus.ACCEPTED.toString()].includes(status)) {
7
- return SubmissionStatus.ACCEPTED;
8
- }
9
-
10
- if ([SubmissionStatus.CORRECT.toString()].includes(status)) {
11
- return SubmissionStatus.ACCEPTED;
12
- }
13
-
14
- if ([SubmissionStatus.PARTIALLY_CORRECT.toString()].includes(status)) {
15
- return SubmissionStatus.PARTIALLY_CORRECT;
16
- }
17
-
18
- if (["WA", SubmissionStatus.WRONG_ANSWER.toString()].includes(status)) {
19
- return SubmissionStatus.WRONG_ANSWER;
20
- }
21
-
22
- if (["RJ", "INCORRECT", SubmissionStatus.REJECTED.toString()].includes(status)) {
23
- return SubmissionStatus.REJECTED;
24
- }
25
-
26
- if (["NO", SubmissionStatus.NO_OUTPUT.toString()].includes(status)) {
27
- return SubmissionStatus.NO_OUTPUT;
28
- }
29
-
30
- if (["PD", SubmissionStatus.PENDING.toString()].includes(status)) {
31
- return SubmissionStatus.PENDING;
32
- }
33
-
34
- if ([SubmissionStatus.WAITING.toString()].includes(status)) {
35
- return SubmissionStatus.WAITING;
36
- }
37
-
38
- if ([SubmissionStatus.JUDGING.toString()].includes(status)) {
39
- return SubmissionStatus.JUDGING;
40
- }
41
-
42
- if ([SubmissionStatus.FROZEN.toString()].includes(status)) {
43
- return SubmissionStatus.FROZEN;
44
- }
45
-
46
- if (["CE", SubmissionStatus.COMPILATION_ERROR.toString()].includes(status)) {
47
- return SubmissionStatus.COMPILATION_ERROR;
48
- }
49
-
50
- if (["PE", SubmissionStatus.PRESENTATION_ERROR.toString()].includes(status)) {
51
- return SubmissionStatus.PRESENTATION_ERROR;
52
- }
53
-
54
- if (["TL", "TLE", SubmissionStatus.TIME_LIMIT_EXCEEDED.toString()].includes(status)) {
55
- return SubmissionStatus.TIME_LIMIT_EXCEEDED;
56
- }
57
-
58
- if (["ML", "MLE", SubmissionStatus.MEMORY_LIMIT_EXCEEDED.toString()].includes(status)) {
59
- return SubmissionStatus.MEMORY_LIMIT_EXCEEDED;
60
- }
61
-
62
- if (["OL", "OLE", SubmissionStatus.OUTPUT_LIMIT_EXCEEDED.toString()].includes(status)) {
63
- return SubmissionStatus.OUTPUT_LIMIT_EXCEEDED;
64
- }
65
-
66
- if (["IL", "ILE", SubmissionStatus.IDLENESS_LIMIT_EXCEEDED.toString()].includes(status)) {
67
- return SubmissionStatus.IDLENESS_LIMIT_EXCEEDED;
68
- }
69
-
70
- if (["RT", "RE", "RTE", SubmissionStatus.RUNTIME_ERROR.toString()].includes(status)) {
71
- return SubmissionStatus.RUNTIME_ERROR;
72
- }
73
-
74
- if (["JE", SubmissionStatus.JUDGEMENT_FAILED.toString()].includes(status)) {
75
- return SubmissionStatus.JUDGEMENT_FAILED;
76
- }
77
-
78
- if (["SE", SubmissionStatus.SYSTEM_ERROR.toString()].includes(status)) {
79
- return SubmissionStatus.SYSTEM_ERROR;
80
- }
81
-
82
- if ([SubmissionStatus.HACKED.toString()].includes(status)) {
83
- return SubmissionStatus.HACKED;
84
- }
85
-
86
- if ([SubmissionStatus.CONFIGURATION_ERROR.toString()].includes(status)) {
87
- return SubmissionStatus.CONFIGURATION_ERROR;
88
- }
89
-
90
- if ([SubmissionStatus.CANCELED.toString()].includes(status)) {
91
- return SubmissionStatus.CANCELED;
92
- }
93
-
94
- if ([SubmissionStatus.SKIPPED.toString()].includes(status)) {
95
- return SubmissionStatus.SKIPPED;
96
- }
97
-
98
- if ([SubmissionStatus.SECURITY_VIOLATED.toString()].includes(status)) {
99
- return SubmissionStatus.SECURITY_VIOLATED;
100
- }
101
-
102
- if ([SubmissionStatus.DENIAL_OF_JUDGEMENT.toString()].includes(status)) {
103
- return SubmissionStatus.DENIAL_OF_JUDGEMENT;
104
- }
105
-
106
- return SubmissionStatus.UNKNOWN;
107
- }
108
-
109
- export function isAccepted(status: SubmissionStatus): boolean {
110
- const acceptedArray = [SubmissionStatus.ACCEPTED, SubmissionStatus.CORRECT];
111
-
112
- return acceptedArray.includes(status);
113
- }
114
-
115
- export function isRejected(status: SubmissionStatus): boolean {
116
- const rejectArray = [
117
- SubmissionStatus.RUNTIME_ERROR,
118
- SubmissionStatus.TIME_LIMIT_EXCEEDED,
119
- SubmissionStatus.MEMORY_LIMIT_EXCEEDED,
120
- SubmissionStatus.OUTPUT_LIMIT_EXCEEDED,
121
- SubmissionStatus.IDLENESS_LIMIT_EXCEEDED,
122
- SubmissionStatus.WRONG_ANSWER,
123
- SubmissionStatus.REJECTED,
124
- SubmissionStatus.NO_OUTPUT,
125
- SubmissionStatus.JUDGEMENT_FAILED,
126
- SubmissionStatus.HACKED,
127
- ];
128
-
129
- return rejectArray.includes(status);
130
- }
131
-
132
- export function isPending(status: SubmissionStatus): boolean {
133
- const pendingArray = [
134
- SubmissionStatus.PENDING,
135
- SubmissionStatus.WAITING,
136
- SubmissionStatus.COMPILING,
137
- SubmissionStatus.JUDGING,
138
- SubmissionStatus.FROZEN,
139
- ];
140
-
141
- return pendingArray.includes(status);
142
- }
143
-
144
- export function isNotCalculatedPenaltyStatus(status: SubmissionStatus): boolean {
145
- const isNotCalculatedPenaltyArray = [
146
- SubmissionStatus.COMPILATION_ERROR,
147
- SubmissionStatus.PRESENTATION_ERROR,
148
- SubmissionStatus.CONFIGURATION_ERROR,
149
- SubmissionStatus.SYSTEM_ERROR,
150
- SubmissionStatus.CANCELED,
151
- SubmissionStatus.SKIPPED,
152
- SubmissionStatus.UNKNOWN,
153
- SubmissionStatus.UNDEFINED,
154
- ];
155
-
156
- return isNotCalculatedPenaltyArray.includes(status);
157
- }
package/src/submission.ts DELETED
@@ -1,177 +0,0 @@
1
- import type { Submission as ISubmission, Submissions as ISubmissions, SubmissionReaction, TimeUnit } from "@xcpcio/types";
2
- import type { Contest } from "./contest";
3
-
4
- import { SubmissionStatus } from "@xcpcio/types";
5
-
6
- import {
7
- isAccepted,
8
- isNotCalculatedPenaltyStatus,
9
- isPending,
10
- isRejected,
11
- stringToSubmissionStatus,
12
- } from "./submission-status";
13
-
14
- export class Submission {
15
- id: string;
16
- teamId: string;
17
- problemId: string;
18
- timestamp: number;
19
- timestampUnit: TimeUnit;
20
-
21
- time?: number;
22
- language?: string;
23
-
24
- reaction?: SubmissionReaction;
25
-
26
- status = SubmissionStatus.UNKNOWN;
27
- isIgnore = false;
28
- isSolved = false;
29
- isFirstSolved = false;
30
-
31
- constructor() {
32
- this.id = "";
33
- this.teamId = "";
34
- this.problemId = "";
35
- this.timestamp = 0;
36
- this.timestampUnit = "second";
37
- }
38
-
39
- isAccepted() {
40
- return isAccepted(this.status);
41
- }
42
-
43
- isRejected() {
44
- return isRejected(this.status);
45
- }
46
-
47
- isPending() {
48
- return isPending(this.status);
49
- }
50
-
51
- isNotCalculatedPenaltyStatus() {
52
- return isNotCalculatedPenaltyStatus(this.status);
53
- }
54
-
55
- get timestampToMinute() {
56
- if (this.timestampUnit === "nanosecond") {
57
- return Math.floor(this.timestamp / 60 / 1000 / 1000 / 1000);
58
- }
59
-
60
- if (this.timestampUnit === "microsecond") {
61
- return Math.floor(this.timestamp / 60 / 1000 / 1000);
62
- }
63
-
64
- if (this.timestampUnit === "millisecond") {
65
- return Math.floor(this.timestamp / 60 / 1000);
66
- }
67
-
68
- return Math.floor(this.timestamp / 60);
69
- }
70
-
71
- get timestampToSecond() {
72
- if (this.timestampUnit === "nanosecond") {
73
- return Math.floor(this.timestamp / 1000 / 1000 / 1000);
74
- }
75
-
76
- if (this.timestampUnit === "microsecond") {
77
- return Math.floor(this.timestamp / 1000 / 1000);
78
- }
79
-
80
- if (this.timestampUnit === "millisecond") {
81
- return Math.floor(this.timestamp / 1000);
82
- }
83
-
84
- return this.timestamp;
85
- }
86
-
87
- get timestampDisplayFormatWithSecond(): string {
88
- const second = this.timestampToSecond;
89
-
90
- const h = Math.floor(second / 3600);
91
- const m = Math.floor(second % 3600 / 60);
92
- const s = second % 60;
93
-
94
- const f = (x: number) => x.toString().padStart(2, "0");
95
-
96
- const res = `${f(h)}:${f(m)}:${f(s)}`;
97
-
98
- return res;
99
- }
100
-
101
- get timestampDisplayFormatWithMilliSecond(): string {
102
- let res = this.timestampDisplayFormatWithSecond;
103
-
104
- if (this.timestampUnit === "millisecond") {
105
- const fl = (this.timestamp % 1000).toString().padStart(3, "0");
106
- res += `.${fl}`;
107
- }
108
-
109
- return res;
110
- }
111
-
112
- static compare(lhs: Submission, rhs: Submission): number {
113
- if (lhs.timestamp !== rhs.timestamp) {
114
- return lhs.timestamp - rhs.timestamp;
115
- }
116
-
117
- if (lhs.teamId === rhs.teamId) {
118
- if (lhs.isAccepted() && !rhs.isAccepted()) {
119
- return -1;
120
- }
121
-
122
- if (!lhs.isAccepted() && rhs.isAccepted()) {
123
- return 1;
124
- }
125
- }
126
-
127
- if (lhs.id < rhs.id) {
128
- return -1;
129
- } else if (lhs.id === rhs.id) {
130
- return 0;
131
- } else {
132
- return 1;
133
- }
134
- }
135
- }
136
-
137
- export type Submissions = Array<Submission>;
138
-
139
- export function createSubmission(submissionJSON: ISubmission, contest?: Contest): Submission {
140
- const s = new Submission();
141
-
142
- s.id = String(submissionJSON.id ?? submissionJSON.submission_id ?? "");
143
- s.teamId = String(submissionJSON.team_id);
144
- s.problemId = String(submissionJSON.problem_id);
145
- s.timestamp = submissionJSON.timestamp;
146
- s.status = stringToSubmissionStatus(submissionJSON.status);
147
- s.isIgnore = submissionJSON.is_ignore ?? false;
148
-
149
- if (submissionJSON.time) {
150
- s.time = submissionJSON.time;
151
- }
152
-
153
- if (submissionJSON.language) {
154
- s.language = submissionJSON.language;
155
- }
156
-
157
- if (submissionJSON.reaction) {
158
- s.reaction = submissionJSON.reaction;
159
- } else if (contest?.options.reactionVideoUrlTemplate) {
160
- s.reaction = {
161
- url: contest.options.reactionVideoUrlTemplate.replace(/\$\{submission_id\}/, s.id),
162
- };
163
- }
164
-
165
- return s;
166
- }
167
-
168
- export function createSubmissions(submissionsJSON: ISubmissions, contest?: Contest): Submissions {
169
- if (Array.isArray(submissionsJSON)) {
170
- return submissionsJSON.map((s, index) => createSubmission({ ...s, id: s.submission_id ?? String(index) }, contest));
171
- } else {
172
- const submissions = Object.entries(submissionsJSON).map(([submissionId, s]) =>
173
- createSubmission({ ...s, id: s.submission_id ?? submissionId }, contest),
174
- );
175
- return submissions;
176
- }
177
- }