@xcpcio/core 0.52.0 → 0.53.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 +2008 -1683
- package/dist/index.d.cts +519 -0
- package/dist/index.d.mts +519 -0
- package/dist/index.d.ts +127 -127
- package/dist/index.mjs +1990 -1663
- package/package.json +21 -21
- package/src/balloon.ts +1 -1
- package/src/battle-of-giants.ts +3 -2
- package/src/contest-index.ts +2 -3
- package/src/contest.ts +6 -6
- package/src/export/cf.ts +2 -2
- package/src/export/general-excel.ts +5 -3
- package/src/export/icpc-standings-csv.ts +4 -3
- package/src/index.ts +6 -7
- package/src/problem.ts +3 -3
- package/src/rank.ts +12 -12
- package/src/rating/index.ts +1 -1
- package/src/rating/rating-history.ts +3 -3
- package/src/rating/rating.ts +2 -3
- package/src/resolver-vue.ts +4 -3
- package/src/resolver.ts +7 -6
- package/src/team.ts +6 -6
- package/src/utils/dayjs.ts +4 -4
package/dist/index.cjs
CHANGED
|
@@ -1,55 +1,312 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
const _ = require('lodash');
|
|
4
|
+
const chroma = require('chroma-js');
|
|
5
|
+
const colorDiff = require('color-diff');
|
|
5
6
|
const types = require('@xcpcio/types');
|
|
7
|
+
const jsBase64 = require('js-base64');
|
|
6
8
|
const dayjs = require('dayjs');
|
|
7
|
-
const duration = require('dayjs/plugin/duration');
|
|
8
|
-
const utc = require('dayjs/plugin/utc');
|
|
9
|
-
const timezone = require('dayjs/plugin/timezone');
|
|
10
9
|
const advancedFormat = require('dayjs/plugin/advancedFormat');
|
|
11
|
-
const
|
|
10
|
+
const duration = require('dayjs/plugin/duration');
|
|
12
11
|
const isSameOrAfter = require('dayjs/plugin/isSameOrAfter');
|
|
12
|
+
const isSameOrBefore = require('dayjs/plugin/isSameOrBefore');
|
|
13
13
|
const minMax = require('dayjs/plugin/minMax');
|
|
14
14
|
const relativeTime = require('dayjs/plugin/relativeTime');
|
|
15
|
-
const
|
|
16
|
-
const
|
|
15
|
+
const timezone = require('dayjs/plugin/timezone');
|
|
16
|
+
const utc = require('dayjs/plugin/utc');
|
|
17
17
|
const stringWidth = require('string-width');
|
|
18
|
-
const
|
|
18
|
+
const XLSX = require('xlsx-js-style');
|
|
19
19
|
const ordinal = require('ordinal');
|
|
20
|
-
const
|
|
21
|
-
const colorDiff = require('color-diff');
|
|
22
|
-
const jsBase64 = require('js-base64');
|
|
20
|
+
const Papa = require('papaparse');
|
|
23
21
|
|
|
24
|
-
function
|
|
22
|
+
function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e.default : e; }
|
|
25
23
|
|
|
26
|
-
function
|
|
27
|
-
if (e && e
|
|
24
|
+
function _interopNamespaceCompat(e) {
|
|
25
|
+
if (e && typeof e === 'object' && 'default' in e) return e;
|
|
28
26
|
const n = Object.create(null);
|
|
29
27
|
if (e) {
|
|
30
28
|
for (const k in e) {
|
|
31
29
|
n[k] = e[k];
|
|
32
30
|
}
|
|
33
31
|
}
|
|
34
|
-
n
|
|
32
|
+
n.default = e;
|
|
35
33
|
return n;
|
|
36
34
|
}
|
|
37
35
|
|
|
38
|
-
const
|
|
39
|
-
const
|
|
40
|
-
const
|
|
41
|
-
const
|
|
42
|
-
const
|
|
43
|
-
const
|
|
44
|
-
const
|
|
45
|
-
const minMax__default = /*#__PURE__*/
|
|
46
|
-
const relativeTime__default = /*#__PURE__*/
|
|
47
|
-
const
|
|
48
|
-
const
|
|
49
|
-
const stringWidth__default = /*#__PURE__*/
|
|
50
|
-
const
|
|
51
|
-
const ordinal__default = /*#__PURE__*/
|
|
52
|
-
const
|
|
36
|
+
const ___default = /*#__PURE__*/_interopDefaultCompat(_);
|
|
37
|
+
const chroma__default = /*#__PURE__*/_interopDefaultCompat(chroma);
|
|
38
|
+
const dayjs__default = /*#__PURE__*/_interopDefaultCompat(dayjs);
|
|
39
|
+
const advancedFormat__default = /*#__PURE__*/_interopDefaultCompat(advancedFormat);
|
|
40
|
+
const duration__default = /*#__PURE__*/_interopDefaultCompat(duration);
|
|
41
|
+
const isSameOrAfter__default = /*#__PURE__*/_interopDefaultCompat(isSameOrAfter);
|
|
42
|
+
const isSameOrBefore__default = /*#__PURE__*/_interopDefaultCompat(isSameOrBefore);
|
|
43
|
+
const minMax__default = /*#__PURE__*/_interopDefaultCompat(minMax);
|
|
44
|
+
const relativeTime__default = /*#__PURE__*/_interopDefaultCompat(relativeTime);
|
|
45
|
+
const timezone__default = /*#__PURE__*/_interopDefaultCompat(timezone);
|
|
46
|
+
const utc__default = /*#__PURE__*/_interopDefaultCompat(utc);
|
|
47
|
+
const stringWidth__default = /*#__PURE__*/_interopDefaultCompat(stringWidth);
|
|
48
|
+
const XLSX__namespace = /*#__PURE__*/_interopNamespaceCompat(XLSX);
|
|
49
|
+
const ordinal__default = /*#__PURE__*/_interopDefaultCompat(ordinal);
|
|
50
|
+
const Papa__default = /*#__PURE__*/_interopDefaultCompat(Papa);
|
|
51
|
+
|
|
52
|
+
var __defProp$j = Object.defineProperty;
|
|
53
|
+
var __defNormalProp$j = (obj, key, value) => key in obj ? __defProp$j(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
54
|
+
var __publicField$j = (obj, key, value) => {
|
|
55
|
+
__defNormalProp$j(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
56
|
+
return value;
|
|
57
|
+
};
|
|
58
|
+
var MedalType = /* @__PURE__ */ ((MedalType2) => {
|
|
59
|
+
MedalType2["UNKNOWN"] = "Unknown";
|
|
60
|
+
MedalType2["GOLD"] = "Gold";
|
|
61
|
+
MedalType2["SILVER"] = "Silver";
|
|
62
|
+
MedalType2["BRONZE"] = "Bronze";
|
|
63
|
+
MedalType2["HONORABLE"] = "Honorable";
|
|
64
|
+
return MedalType2;
|
|
65
|
+
})(MedalType || {});
|
|
66
|
+
class Award {
|
|
67
|
+
constructor() {
|
|
68
|
+
__publicField$j(this, "medalType");
|
|
69
|
+
__publicField$j(this, "minRank");
|
|
70
|
+
__publicField$j(this, "maxRank");
|
|
71
|
+
this.medalType = "Unknown" /* UNKNOWN */;
|
|
72
|
+
this.minRank = 0;
|
|
73
|
+
this.maxRank = 0;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
function isValidMedalType(medal) {
|
|
77
|
+
const validMedalType = [
|
|
78
|
+
"Gold" /* GOLD */,
|
|
79
|
+
"Silver" /* SILVER */,
|
|
80
|
+
"Bronze" /* BRONZE */,
|
|
81
|
+
"Honorable" /* HONORABLE */
|
|
82
|
+
];
|
|
83
|
+
return validMedalType.includes(medal);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function calcDirt(attemptedNum, solvedNum) {
|
|
87
|
+
if (solvedNum === 0) {
|
|
88
|
+
return 0;
|
|
89
|
+
}
|
|
90
|
+
return Math.floor((attemptedNum - solvedNum) * 100 / attemptedNum);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function getWhiteOrBlackColorV1(background) {
|
|
94
|
+
const [R, G, B] = chroma__default(background).rgb();
|
|
95
|
+
const color = { R, G, B };
|
|
96
|
+
const palette = [
|
|
97
|
+
{ R: 0, G: 0, B: 0 },
|
|
98
|
+
{ R: 255, G: 255, B: 255 }
|
|
99
|
+
];
|
|
100
|
+
const f = colorDiff.furthest(color, palette);
|
|
101
|
+
if (f.R === 0 && f.G === 0 && f.B === 0) {
|
|
102
|
+
return "#000";
|
|
103
|
+
} else {
|
|
104
|
+
return "#fff";
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
function getWhiteOrBlackColor(background) {
|
|
108
|
+
const [R, G, B] = chroma__default(background).rgb();
|
|
109
|
+
const brightness = (R * 299 + G * 587 + B * 114) / 1e3;
|
|
110
|
+
const threshold = 148;
|
|
111
|
+
return brightness <= threshold ? "#fff" : "#000";
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
dayjs__default.extend(duration__default);
|
|
115
|
+
dayjs__default.extend(utc__default);
|
|
116
|
+
dayjs__default.extend(timezone__default);
|
|
117
|
+
dayjs__default.extend(advancedFormat__default);
|
|
118
|
+
dayjs__default.extend(isSameOrBefore__default);
|
|
119
|
+
dayjs__default.extend(isSameOrAfter__default);
|
|
120
|
+
dayjs__default.extend(minMax__default);
|
|
121
|
+
dayjs__default.extend(relativeTime__default);
|
|
122
|
+
function createDayJS(time = void 0) {
|
|
123
|
+
if (time === void 0) {
|
|
124
|
+
return dayjs__default();
|
|
125
|
+
}
|
|
126
|
+
if (typeof time == "number" && String(time).length === 10) {
|
|
127
|
+
return dayjs__default.unix(time);
|
|
128
|
+
}
|
|
129
|
+
return dayjs__default(time);
|
|
130
|
+
}
|
|
131
|
+
function getTimestamp(time) {
|
|
132
|
+
if (typeof time === "number") {
|
|
133
|
+
return time;
|
|
134
|
+
}
|
|
135
|
+
return time.unix();
|
|
136
|
+
}
|
|
137
|
+
function getTimeDiff(seconds) {
|
|
138
|
+
const two = (a) => {
|
|
139
|
+
if (a < 10) {
|
|
140
|
+
return `0${a}`;
|
|
141
|
+
}
|
|
142
|
+
return String(a);
|
|
143
|
+
};
|
|
144
|
+
const h = Math.floor(seconds / 3600);
|
|
145
|
+
const m = Math.floor(seconds % 3600 / 60);
|
|
146
|
+
const s = seconds % 60;
|
|
147
|
+
return [two(h), two(m), two(s)].join(":");
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
var __defProp$i = Object.defineProperty;
|
|
151
|
+
var __defNormalProp$i = (obj, key, value) => key in obj ? __defProp$i(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
152
|
+
var __publicField$i = (obj, key, value) => {
|
|
153
|
+
__defNormalProp$i(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
154
|
+
return value;
|
|
155
|
+
};
|
|
156
|
+
class ProblemStatistics {
|
|
157
|
+
constructor() {
|
|
158
|
+
__publicField$i(this, "acceptedNum");
|
|
159
|
+
__publicField$i(this, "rejectedNum");
|
|
160
|
+
__publicField$i(this, "pendingNum");
|
|
161
|
+
__publicField$i(this, "submittedNum");
|
|
162
|
+
__publicField$i(this, "attemptedNum");
|
|
163
|
+
__publicField$i(this, "ignoreNum");
|
|
164
|
+
__publicField$i(this, "firstSolveSubmissions");
|
|
165
|
+
__publicField$i(this, "lastSolveSubmissions");
|
|
166
|
+
__publicField$i(this, "se");
|
|
167
|
+
this.acceptedNum = 0;
|
|
168
|
+
this.rejectedNum = 0;
|
|
169
|
+
this.pendingNum = 0;
|
|
170
|
+
this.submittedNum = 0;
|
|
171
|
+
this.attemptedNum = 0;
|
|
172
|
+
this.ignoreNum = 0;
|
|
173
|
+
this.se = 0;
|
|
174
|
+
this.firstSolveSubmissions = [];
|
|
175
|
+
this.lastSolveSubmissions = [];
|
|
176
|
+
}
|
|
177
|
+
reset() {
|
|
178
|
+
this.acceptedNum = 0;
|
|
179
|
+
this.rejectedNum = 0;
|
|
180
|
+
this.pendingNum = 0;
|
|
181
|
+
this.submittedNum = 0;
|
|
182
|
+
this.attemptedNum = 0;
|
|
183
|
+
this.ignoreNum = 0;
|
|
184
|
+
this.se = 0;
|
|
185
|
+
this.firstSolveSubmissions = [];
|
|
186
|
+
this.lastSolveSubmissions = [];
|
|
187
|
+
}
|
|
188
|
+
get dirt() {
|
|
189
|
+
if (this.acceptedNum === 0) {
|
|
190
|
+
return 0;
|
|
191
|
+
}
|
|
192
|
+
return calcDirt(this.attemptedNum, this.acceptedNum);
|
|
193
|
+
}
|
|
194
|
+
calcSE(totalTeams) {
|
|
195
|
+
const res = (totalTeams - this.acceptedNum) / totalTeams;
|
|
196
|
+
this.se = Math.round(res * 100) / 100;
|
|
197
|
+
return this.se;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
class Problem {
|
|
201
|
+
constructor() {
|
|
202
|
+
__publicField$i(this, "id");
|
|
203
|
+
__publicField$i(this, "label");
|
|
204
|
+
__publicField$i(this, "name");
|
|
205
|
+
__publicField$i(this, "timeLimit");
|
|
206
|
+
__publicField$i(this, "memoryLimit");
|
|
207
|
+
__publicField$i(this, "balloonColor");
|
|
208
|
+
__publicField$i(this, "statistics");
|
|
209
|
+
this.id = "";
|
|
210
|
+
this.label = "";
|
|
211
|
+
this.name = "";
|
|
212
|
+
this.statistics = new ProblemStatistics();
|
|
213
|
+
this.balloonColor = {
|
|
214
|
+
background_color: "#a0f0a0",
|
|
215
|
+
color: "#000"
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
function createProblem(problemJSON) {
|
|
220
|
+
const p = new Problem();
|
|
221
|
+
p.id = String(problemJSON.id);
|
|
222
|
+
p.label = problemJSON.label;
|
|
223
|
+
p.name = problemJSON.name ?? "";
|
|
224
|
+
p.timeLimit = problemJSON.time_limit;
|
|
225
|
+
p.memoryLimit = problemJSON.memory_limit;
|
|
226
|
+
if (problemJSON.balloon_color) {
|
|
227
|
+
p.balloonColor = ___default.cloneDeep(problemJSON.balloon_color);
|
|
228
|
+
}
|
|
229
|
+
p.balloonColor.color = getWhiteOrBlackColor(p.balloonColor.background_color);
|
|
230
|
+
return p;
|
|
231
|
+
}
|
|
232
|
+
function createProblems(problemsJSON) {
|
|
233
|
+
return problemsJSON.map((pJSON) => createProblem(pJSON));
|
|
234
|
+
}
|
|
235
|
+
function createProblemsByProblemIds(problemIds, balloonColors) {
|
|
236
|
+
const problems = problemIds.map((label, index) => {
|
|
237
|
+
const p = new Problem();
|
|
238
|
+
p.id = String(index);
|
|
239
|
+
p.label = label;
|
|
240
|
+
return p;
|
|
241
|
+
});
|
|
242
|
+
if (balloonColors !== void 0 && balloonColors !== null) {
|
|
243
|
+
for (const index in balloonColors) {
|
|
244
|
+
problems[index].balloonColor = ___default.cloneDeep(balloonColors[index]);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
problems.forEach((p) => {
|
|
248
|
+
p.balloonColor.color = getWhiteOrBlackColor(p.balloonColor.background_color);
|
|
249
|
+
});
|
|
250
|
+
return problems;
|
|
251
|
+
}
|
|
252
|
+
class TeamProblemStatistics {
|
|
253
|
+
constructor(options) {
|
|
254
|
+
__publicField$i(this, "isFirstSolved");
|
|
255
|
+
__publicField$i(this, "isSolved");
|
|
256
|
+
__publicField$i(this, "solvedTimestamp");
|
|
257
|
+
__publicField$i(this, "isSubmitted");
|
|
258
|
+
__publicField$i(this, "lastSubmitTimestamp");
|
|
259
|
+
__publicField$i(this, "failedCount");
|
|
260
|
+
__publicField$i(this, "pendingCount");
|
|
261
|
+
__publicField$i(this, "ignoreCount");
|
|
262
|
+
__publicField$i(this, "totalCount");
|
|
263
|
+
__publicField$i(this, "submissions");
|
|
264
|
+
__publicField$i(this, "problem");
|
|
265
|
+
__publicField$i(this, "contestPenalty");
|
|
266
|
+
this.isFirstSolved = options?.teamProblemStatistics?.isFirstSolved ?? false;
|
|
267
|
+
this.isSolved = options?.teamProblemStatistics?.isSolved ?? false;
|
|
268
|
+
this.solvedTimestamp = options?.teamProblemStatistics?.solvedTimestamp ?? 0;
|
|
269
|
+
this.isSubmitted = options?.teamProblemStatistics?.isSubmitted ?? false;
|
|
270
|
+
this.lastSubmitTimestamp = options?.teamProblemStatistics?.lastSubmitTimestamp ?? 0;
|
|
271
|
+
this.failedCount = options?.teamProblemStatistics?.failedCount ?? 0;
|
|
272
|
+
this.pendingCount = options?.teamProblemStatistics?.pendingCount ?? 0;
|
|
273
|
+
this.ignoreCount = options?.teamProblemStatistics?.ignoreCount ?? 0;
|
|
274
|
+
this.totalCount = options?.teamProblemStatistics?.totalCount ?? 0;
|
|
275
|
+
this.submissions = options?.teamProblemStatistics?.submissions ?? [];
|
|
276
|
+
this.problem = options?.teamProblemStatistics?.problem ?? new Problem();
|
|
277
|
+
this.contestPenalty = options?.teamProblemStatistics?.contestPenalty ?? 20 * 60;
|
|
278
|
+
}
|
|
279
|
+
get isAccepted() {
|
|
280
|
+
return this.isSolved;
|
|
281
|
+
}
|
|
282
|
+
get isWrongAnswer() {
|
|
283
|
+
return !this.isSolved && this.pendingCount === 0 && this.failedCount > 0;
|
|
284
|
+
}
|
|
285
|
+
get isPending() {
|
|
286
|
+
return !this.isSolved && this.pendingCount > 0;
|
|
287
|
+
}
|
|
288
|
+
get isUnSubmitted() {
|
|
289
|
+
return this.totalCount === 0;
|
|
290
|
+
}
|
|
291
|
+
get solvedTimestampToMinute() {
|
|
292
|
+
return Math.floor(this.solvedTimestamp / 60);
|
|
293
|
+
}
|
|
294
|
+
get penalty() {
|
|
295
|
+
if (this.isSolved === false) {
|
|
296
|
+
return 0;
|
|
297
|
+
}
|
|
298
|
+
return this.solvedTimestampToMinute * 60 + this.failedCount * this.contestPenalty;
|
|
299
|
+
}
|
|
300
|
+
get penaltyToMinute() {
|
|
301
|
+
return Math.floor(this.penalty / 60);
|
|
302
|
+
}
|
|
303
|
+
get penaltyInSecond() {
|
|
304
|
+
if (this.isSolved === false) {
|
|
305
|
+
return 0;
|
|
306
|
+
}
|
|
307
|
+
return this.solvedTimestamp + this.failedCount * this.contestPenalty;
|
|
308
|
+
}
|
|
309
|
+
}
|
|
53
310
|
|
|
54
311
|
function stringToSubmissionStatus(status) {
|
|
55
312
|
status = status.toUpperCase().replace(" ", "_");
|
|
@@ -173,1675 +430,1233 @@ function isNotCalculatedPenaltyStatus(status) {
|
|
|
173
430
|
return isNotCalculatedPenaltyArray.includes(status);
|
|
174
431
|
}
|
|
175
432
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
dayjs__default.extend(relativeTime__default);
|
|
184
|
-
function createDayJS(time = void 0) {
|
|
185
|
-
if (time === void 0) {
|
|
186
|
-
return dayjs__default();
|
|
187
|
-
}
|
|
188
|
-
if (typeof time == "number" && String(time).length === 10) {
|
|
189
|
-
return dayjs__default.unix(time);
|
|
190
|
-
}
|
|
191
|
-
return dayjs__default(time);
|
|
192
|
-
}
|
|
193
|
-
function getTimestamp(time) {
|
|
194
|
-
if (typeof time === "number") {
|
|
195
|
-
return time;
|
|
196
|
-
}
|
|
197
|
-
return time.unix();
|
|
198
|
-
}
|
|
199
|
-
function getTimeDiff(seconds) {
|
|
200
|
-
const two = (a) => {
|
|
201
|
-
if (a < 10) {
|
|
202
|
-
return `0${a}`;
|
|
203
|
-
}
|
|
204
|
-
return String(a);
|
|
205
|
-
};
|
|
206
|
-
const h = Math.floor(seconds / 3600);
|
|
207
|
-
const m = Math.floor(seconds % 3600 / 60);
|
|
208
|
-
const s = seconds % 60;
|
|
209
|
-
return [two(h), two(m), two(s)].join(":");
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
class CodeforcesGymGhostDATConverter {
|
|
433
|
+
var __defProp$h = Object.defineProperty;
|
|
434
|
+
var __defNormalProp$h = (obj, key, value) => key in obj ? __defProp$h(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
435
|
+
var __publicField$h = (obj, key, value) => {
|
|
436
|
+
__defNormalProp$h(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
437
|
+
return value;
|
|
438
|
+
};
|
|
439
|
+
class Submission {
|
|
213
440
|
constructor() {
|
|
441
|
+
__publicField$h(this, "id");
|
|
442
|
+
__publicField$h(this, "teamId");
|
|
443
|
+
__publicField$h(this, "problemId");
|
|
444
|
+
__publicField$h(this, "timestamp");
|
|
445
|
+
__publicField$h(this, "timestampUnit");
|
|
446
|
+
__publicField$h(this, "time");
|
|
447
|
+
__publicField$h(this, "language");
|
|
448
|
+
__publicField$h(this, "reaction");
|
|
449
|
+
__publicField$h(this, "status", types.SubmissionStatus.UNKNOWN);
|
|
450
|
+
__publicField$h(this, "isIgnore", false);
|
|
451
|
+
__publicField$h(this, "isSolved", false);
|
|
452
|
+
__publicField$h(this, "isFirstSolved", false);
|
|
453
|
+
this.id = "";
|
|
454
|
+
this.teamId = "";
|
|
455
|
+
this.problemId = "";
|
|
456
|
+
this.timestamp = 0;
|
|
457
|
+
this.timestampUnit = "second";
|
|
214
458
|
}
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
res += `@contest "${rank.contest.name}"
|
|
218
|
-
@contlen ${Math.floor(dayjs__default.duration(rank.contest.endTime.diff(rank.contest.startTime)).asMinutes())}
|
|
219
|
-
@problems ${rank.contest.problems.length}
|
|
220
|
-
@teams ${rank.teams.length + 100}
|
|
221
|
-
@submissions ${rank.submissions.length}
|
|
222
|
-
`;
|
|
223
|
-
rank.contest.problems.forEach((p) => {
|
|
224
|
-
res += `@p ${p.label},${p.label},20,0
|
|
225
|
-
`;
|
|
226
|
-
});
|
|
227
|
-
let teamIndex = 1;
|
|
228
|
-
const teamIdMap = /* @__PURE__ */ new Map();
|
|
229
|
-
const submissionsIdMap = /* @__PURE__ */ new Map();
|
|
230
|
-
rank.teams.forEach((team) => {
|
|
231
|
-
let name = team.name;
|
|
232
|
-
if (team.organization) {
|
|
233
|
-
name = `${team.organization} - ${name}`;
|
|
234
|
-
}
|
|
235
|
-
if (team.members) {
|
|
236
|
-
name = `${name} - ${team.membersToString}`;
|
|
237
|
-
}
|
|
238
|
-
res += `@t ${teamIndex},0,1,"${name}"
|
|
239
|
-
`;
|
|
240
|
-
teamIdMap.set(team.id, teamIndex);
|
|
241
|
-
teamIndex++;
|
|
242
|
-
{
|
|
243
|
-
const mp = /* @__PURE__ */ new Map();
|
|
244
|
-
rank.contest.problems.forEach((p) => {
|
|
245
|
-
mp.set(p.id, 0);
|
|
246
|
-
});
|
|
247
|
-
submissionsIdMap.set(team.id, mp);
|
|
248
|
-
}
|
|
249
|
-
});
|
|
250
|
-
for (let i = 0; i < 100; i++) {
|
|
251
|
-
res += `@t ${teamIndex},0,1,"\u041F\u043E\u043F\u043E\u043B\u043D\u0438\u0442\u044C \u043A\u043E\u043C\u0430\u043D\u0434\u0443"
|
|
252
|
-
`;
|
|
253
|
-
teamIndex++;
|
|
254
|
-
}
|
|
255
|
-
rank.getSubmissions().forEach((submission) => {
|
|
256
|
-
const teamId = submission.teamId;
|
|
257
|
-
const problemId = submission.problemId;
|
|
258
|
-
const problem = rank.contest.problemsMap.get(problemId);
|
|
259
|
-
const teamIndex2 = teamIdMap.get(teamId);
|
|
260
|
-
if (!problem) {
|
|
261
|
-
return;
|
|
262
|
-
}
|
|
263
|
-
if (!teamIndex2) {
|
|
264
|
-
return;
|
|
265
|
-
}
|
|
266
|
-
const status = this.submissionStatusToCodeforcesGymDatStatus(submission.status);
|
|
267
|
-
submissionsIdMap.get(teamId).set(problemId, submissionsIdMap.get(teamId).get(problemId) + 1);
|
|
268
|
-
res += `@s ${teamIndex2},${problem.label},${submissionsIdMap.get(teamId)?.get(problemId)},${submission.timestampToSecond},${status}
|
|
269
|
-
`;
|
|
270
|
-
});
|
|
271
|
-
return res;
|
|
459
|
+
isAccepted() {
|
|
460
|
+
return isAccepted(this.status);
|
|
272
461
|
}
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
462
|
+
isRejected() {
|
|
463
|
+
return isRejected(this.status);
|
|
464
|
+
}
|
|
465
|
+
isPending() {
|
|
466
|
+
return isPending(this.status);
|
|
467
|
+
}
|
|
468
|
+
isNotCalculatedPenaltyStatus() {
|
|
469
|
+
return isNotCalculatedPenaltyStatus(this.status);
|
|
470
|
+
}
|
|
471
|
+
get timestampToMinute() {
|
|
472
|
+
if (this.timestampUnit === "nanosecond") {
|
|
473
|
+
return Math.floor(this.timestamp / 60 / 1e3 / 1e3 / 1e3);
|
|
276
474
|
}
|
|
277
|
-
if (
|
|
278
|
-
return
|
|
475
|
+
if (this.timestampUnit === "microsecond") {
|
|
476
|
+
return Math.floor(this.timestamp / 60 / 1e3 / 1e3);
|
|
279
477
|
}
|
|
280
|
-
if (
|
|
281
|
-
return
|
|
478
|
+
if (this.timestampUnit === "millisecond") {
|
|
479
|
+
return Math.floor(this.timestamp / 60 / 1e3);
|
|
282
480
|
}
|
|
283
|
-
|
|
284
|
-
|
|
481
|
+
return Math.floor(this.timestamp / 60);
|
|
482
|
+
}
|
|
483
|
+
get timestampToSecond() {
|
|
484
|
+
if (this.timestampUnit === "nanosecond") {
|
|
485
|
+
return Math.floor(this.timestamp / 1e3 / 1e3 / 1e3);
|
|
285
486
|
}
|
|
286
|
-
if (
|
|
287
|
-
return
|
|
487
|
+
if (this.timestampUnit === "microsecond") {
|
|
488
|
+
return Math.floor(this.timestamp / 1e3 / 1e3);
|
|
288
489
|
}
|
|
289
|
-
if (
|
|
290
|
-
return
|
|
490
|
+
if (this.timestampUnit === "millisecond") {
|
|
491
|
+
return Math.floor(this.timestamp / 1e3);
|
|
291
492
|
}
|
|
292
|
-
|
|
293
|
-
|
|
493
|
+
return this.timestamp;
|
|
494
|
+
}
|
|
495
|
+
get timestampDisplayFormatWithSecond() {
|
|
496
|
+
const second = this.timestampToSecond;
|
|
497
|
+
const h = Math.floor(second / 3600);
|
|
498
|
+
const m = Math.floor(second % 3600 / 60);
|
|
499
|
+
const s = second % 60;
|
|
500
|
+
const f = (x) => x.toString().padStart(2, "0");
|
|
501
|
+
const res = `${f(h)}:${f(m)}:${f(s)}`;
|
|
502
|
+
return res;
|
|
503
|
+
}
|
|
504
|
+
get timestampDisplayFormatWithMilliSecond() {
|
|
505
|
+
let res = this.timestampDisplayFormatWithSecond;
|
|
506
|
+
if (this.timestampUnit === "millisecond") {
|
|
507
|
+
const fl = (this.timestamp % 1e3).toString().padStart(3, "0");
|
|
508
|
+
res += `.${fl}`;
|
|
294
509
|
}
|
|
295
|
-
|
|
296
|
-
|
|
510
|
+
return res;
|
|
511
|
+
}
|
|
512
|
+
static compare(lhs, rhs) {
|
|
513
|
+
if (lhs.timestamp !== rhs.timestamp) {
|
|
514
|
+
return lhs.timestamp - rhs.timestamp;
|
|
297
515
|
}
|
|
298
|
-
if (
|
|
299
|
-
|
|
516
|
+
if (lhs.teamId === rhs.teamId) {
|
|
517
|
+
if (lhs.isAccepted() && !rhs.isAccepted()) {
|
|
518
|
+
return -1;
|
|
519
|
+
}
|
|
520
|
+
if (!lhs.isAccepted() && rhs.isAccepted()) {
|
|
521
|
+
return 1;
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
if (lhs.id < rhs.id) {
|
|
525
|
+
return -1;
|
|
526
|
+
} else if (lhs.id === rhs.id) {
|
|
527
|
+
return 0;
|
|
528
|
+
} else {
|
|
529
|
+
return 1;
|
|
300
530
|
}
|
|
301
|
-
return "RJ";
|
|
302
531
|
}
|
|
303
532
|
}
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
533
|
+
function createSubmission(submissionJSON) {
|
|
534
|
+
const s = new Submission();
|
|
535
|
+
s.id = String(submissionJSON.id ?? submissionJSON.submission_id ?? "");
|
|
536
|
+
s.teamId = String(submissionJSON.team_id);
|
|
537
|
+
s.problemId = String(submissionJSON.problem_id);
|
|
538
|
+
s.timestamp = submissionJSON.timestamp;
|
|
539
|
+
s.status = stringToSubmissionStatus(submissionJSON.status);
|
|
540
|
+
s.isIgnore = submissionJSON.is_ignore ?? false;
|
|
541
|
+
if (submissionJSON.time) {
|
|
542
|
+
s.time = submissionJSON.time;
|
|
543
|
+
}
|
|
544
|
+
if (submissionJSON.language) {
|
|
545
|
+
s.language = submissionJSON.language;
|
|
546
|
+
}
|
|
547
|
+
if (submissionJSON.reaction) {
|
|
548
|
+
s.reaction = submissionJSON.reaction;
|
|
318
549
|
}
|
|
550
|
+
return s;
|
|
319
551
|
}
|
|
320
|
-
function
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
552
|
+
function createSubmissions(submissionsJSON) {
|
|
553
|
+
if (Array.isArray(submissionsJSON)) {
|
|
554
|
+
return submissionsJSON.map((s, index) => createSubmission({ ...s, id: s.submission_id ?? String(index) }));
|
|
555
|
+
} else {
|
|
556
|
+
const submissions = Object.entries(submissionsJSON).map(
|
|
557
|
+
([submissionId, s]) => createSubmission({ ...s, id: s.submission_id ?? submissionId })
|
|
558
|
+
);
|
|
559
|
+
return submissions;
|
|
560
|
+
}
|
|
328
561
|
}
|
|
329
562
|
|
|
330
|
-
|
|
563
|
+
var __defProp$g = Object.defineProperty;
|
|
564
|
+
var __defNormalProp$g = (obj, key, value) => key in obj ? __defProp$g(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
565
|
+
var __publicField$g = (obj, key, value) => {
|
|
566
|
+
__defNormalProp$g(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
567
|
+
return value;
|
|
568
|
+
};
|
|
569
|
+
class PlaceChartPointData {
|
|
331
570
|
constructor() {
|
|
571
|
+
__publicField$g(this, "timePoint");
|
|
572
|
+
__publicField$g(this, "rank");
|
|
573
|
+
__publicField$g(this, "lastSolvedProblem");
|
|
574
|
+
this.timePoint = 0;
|
|
575
|
+
this.rank = 0;
|
|
576
|
+
this.lastSolvedProblem = null;
|
|
332
577
|
}
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
578
|
+
}
|
|
579
|
+
class Team {
|
|
580
|
+
constructor() {
|
|
581
|
+
__publicField$g(this, "id");
|
|
582
|
+
__publicField$g(this, "name");
|
|
583
|
+
__publicField$g(this, "organization");
|
|
584
|
+
__publicField$g(this, "badge");
|
|
585
|
+
__publicField$g(this, "group");
|
|
586
|
+
__publicField$g(this, "tag");
|
|
587
|
+
__publicField$g(this, "coach");
|
|
588
|
+
__publicField$g(this, "members");
|
|
589
|
+
__publicField$g(this, "rank");
|
|
590
|
+
__publicField$g(this, "originalRank");
|
|
591
|
+
__publicField$g(this, "organizationRank");
|
|
592
|
+
__publicField$g(this, "solvedProblemNum");
|
|
593
|
+
__publicField$g(this, "attemptedProblemNum");
|
|
594
|
+
__publicField$g(this, "lastSolvedProblem");
|
|
595
|
+
__publicField$g(this, "lastSolvedProblemStatistics");
|
|
596
|
+
__publicField$g(this, "penalty");
|
|
597
|
+
__publicField$g(this, "problemStatistics");
|
|
598
|
+
__publicField$g(this, "problemStatisticsMap");
|
|
599
|
+
__publicField$g(this, "submissions");
|
|
600
|
+
__publicField$g(this, "placeChartPoints");
|
|
601
|
+
__publicField$g(this, "awards");
|
|
602
|
+
__publicField$g(this, "location");
|
|
603
|
+
__publicField$g(this, "icpcID");
|
|
604
|
+
__publicField$g(this, "se");
|
|
605
|
+
this.id = "";
|
|
606
|
+
this.name = "";
|
|
607
|
+
this.organization = "";
|
|
608
|
+
this.group = [];
|
|
609
|
+
this.tag = [];
|
|
610
|
+
this.rank = 0;
|
|
611
|
+
this.originalRank = 0;
|
|
612
|
+
this.organizationRank = -1;
|
|
613
|
+
this.solvedProblemNum = 0;
|
|
614
|
+
this.attemptedProblemNum = 0;
|
|
615
|
+
this.lastSolvedProblem = null;
|
|
616
|
+
this.lastSolvedProblemStatistics = null;
|
|
617
|
+
this.penalty = 0;
|
|
618
|
+
this.problemStatistics = [];
|
|
619
|
+
this.problemStatisticsMap = /* @__PURE__ */ new Map();
|
|
620
|
+
this.submissions = [];
|
|
621
|
+
this.placeChartPoints = [];
|
|
622
|
+
this.awards = [];
|
|
623
|
+
this.se = 0;
|
|
345
624
|
}
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
625
|
+
reset() {
|
|
626
|
+
this.rank = 0;
|
|
627
|
+
this.originalRank = 0;
|
|
628
|
+
this.organizationRank = -1;
|
|
629
|
+
this.solvedProblemNum = 0;
|
|
630
|
+
this.attemptedProblemNum = 0;
|
|
631
|
+
this.lastSolvedProblem = null;
|
|
632
|
+
this.lastSolvedProblemStatistics = null;
|
|
633
|
+
this.penalty = 0;
|
|
634
|
+
this.problemStatistics = [];
|
|
635
|
+
this.problemStatisticsMap = /* @__PURE__ */ new Map();
|
|
636
|
+
this.submissions = [];
|
|
637
|
+
this.placeChartPoints = [];
|
|
638
|
+
this.awards = [];
|
|
639
|
+
this.se = 0;
|
|
354
640
|
}
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
});
|
|
368
|
-
}
|
|
369
|
-
sheet["!cols"] = cols;
|
|
370
|
-
{
|
|
371
|
-
const mergeRange = { s: { r: 0, c: 0 }, e: { r: 0, c: head.length - 1 } };
|
|
372
|
-
const merges = [{ s: mergeRange.s, e: mergeRange.e }];
|
|
373
|
-
sheet["!merges"] = merges;
|
|
641
|
+
get penaltyToMinute() {
|
|
642
|
+
return Math.floor(this.penalty / 60);
|
|
643
|
+
}
|
|
644
|
+
get isUnofficial() {
|
|
645
|
+
return this.group.includes("unofficial");
|
|
646
|
+
}
|
|
647
|
+
get isGirl() {
|
|
648
|
+
return this.group.includes("girl");
|
|
649
|
+
}
|
|
650
|
+
get membersToArray() {
|
|
651
|
+
if (Array.isArray(this.members)) {
|
|
652
|
+
return this.members;
|
|
374
653
|
}
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
const borderStyle = {
|
|
382
|
-
style: "thin"
|
|
383
|
-
};
|
|
384
|
-
const cellStyle = {
|
|
385
|
-
alignment: {
|
|
386
|
-
vertical: "center",
|
|
387
|
-
horizontal: "center"
|
|
388
|
-
},
|
|
389
|
-
border: {
|
|
390
|
-
top: borderStyle,
|
|
391
|
-
bottom: borderStyle,
|
|
392
|
-
left: borderStyle,
|
|
393
|
-
right: borderStyle
|
|
394
|
-
},
|
|
395
|
-
font
|
|
396
|
-
};
|
|
397
|
-
for (let i = 1; i < aoa.length; i++) {
|
|
398
|
-
for (let j = 0; j < aoa[i].length; j++) {
|
|
399
|
-
const cellAddress = XLSX__namespace.utils.encode_cell({ r: i, c: j });
|
|
400
|
-
const cell = sheet[cellAddress];
|
|
401
|
-
cell.s = cellStyle;
|
|
654
|
+
if (typeof this.members === "string") {
|
|
655
|
+
if (this.members.includes(", ")) {
|
|
656
|
+
return this.members.split(", ");
|
|
657
|
+
}
|
|
658
|
+
if (this.members.includes("\u3001")) {
|
|
659
|
+
return this.members.split("\u3001");
|
|
402
660
|
}
|
|
403
661
|
}
|
|
404
|
-
|
|
405
|
-
const cellAddress = XLSX__namespace.utils.encode_cell({ r: 0, c: 0 });
|
|
406
|
-
const cell = sheet[cellAddress];
|
|
407
|
-
const titleStyle = ___default.cloneDeep(cellStyle);
|
|
408
|
-
titleStyle.font.sz = 28;
|
|
409
|
-
titleStyle.font.bold = true;
|
|
410
|
-
cell.s = titleStyle;
|
|
411
|
-
}
|
|
412
|
-
return sheet;
|
|
662
|
+
return [];
|
|
413
663
|
}
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
const enableMembers = (Array.isArray(rank.teams) && rank.teams[0]?.members) ?? false;
|
|
418
|
-
const enableCoach = rank.teams[0]?.coach ?? false;
|
|
419
|
-
{
|
|
420
|
-
aoa.push([rank.contest.name]);
|
|
664
|
+
get membersToString() {
|
|
665
|
+
if (typeof this.members === "string") {
|
|
666
|
+
return this.members;
|
|
421
667
|
}
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
if (
|
|
437
|
-
|
|
668
|
+
return this.members?.join(", ");
|
|
669
|
+
}
|
|
670
|
+
get isEffectiveTeam() {
|
|
671
|
+
return this.solvedProblemNum > 0;
|
|
672
|
+
}
|
|
673
|
+
get dirt() {
|
|
674
|
+
const attemptedNum = this.attemptedProblemNum;
|
|
675
|
+
const solvedNum = this.solvedProblemNum;
|
|
676
|
+
return calcDirt(attemptedNum, solvedNum);
|
|
677
|
+
}
|
|
678
|
+
calcSE(totalTeams) {
|
|
679
|
+
let acceptedProblemNums = 0;
|
|
680
|
+
let total = 0;
|
|
681
|
+
this.problemStatistics.forEach((p) => {
|
|
682
|
+
if (p.isSolved) {
|
|
683
|
+
acceptedProblemNums += 1;
|
|
684
|
+
total += p.problem.statistics.acceptedNum;
|
|
438
685
|
}
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
686
|
+
});
|
|
687
|
+
if (totalTeams === 0 || acceptedProblemNums === 0) {
|
|
688
|
+
return 0;
|
|
442
689
|
}
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
arr.push("-");
|
|
458
|
-
}
|
|
459
|
-
if (p.isSolved) {
|
|
460
|
-
arr.push(`+${p.totalCount}(${p.solvedTimestampToMinute})`);
|
|
461
|
-
}
|
|
462
|
-
if (p.isWrongAnswer) {
|
|
463
|
-
arr.push(`-${p.failedCount}`);
|
|
464
|
-
}
|
|
465
|
-
if (p.isPending) {
|
|
466
|
-
arr.push(`? ${p.failedCount} + ${p.pendingCount}`);
|
|
467
|
-
}
|
|
468
|
-
}
|
|
469
|
-
arr.push(`${team.dirt}%`);
|
|
470
|
-
if (enableAwards) {
|
|
471
|
-
const medals = team.awards.filter((a) => isValidMedalType(a)).map((a) => a.toString());
|
|
472
|
-
arr.push(medals.join(", "));
|
|
473
|
-
}
|
|
474
|
-
if (enableMembers) {
|
|
475
|
-
const members = team.members;
|
|
476
|
-
if (Array.isArray(members)) {
|
|
477
|
-
arr.push(members[0] ?? "");
|
|
478
|
-
arr.push(members[1] ?? "");
|
|
479
|
-
arr.push(members[2] ?? "");
|
|
480
|
-
} else {
|
|
481
|
-
arr.push("", "", "");
|
|
482
|
-
}
|
|
483
|
-
}
|
|
484
|
-
if (enableCoach) {
|
|
485
|
-
if (typeof team.coach === "string") {
|
|
486
|
-
arr.push(team.coach ?? "");
|
|
690
|
+
const res = (acceptedProblemNums * totalTeams - total) / totalTeams / acceptedProblemNums;
|
|
691
|
+
this.se = Math.round(res * 100) / 100;
|
|
692
|
+
return this.se;
|
|
693
|
+
}
|
|
694
|
+
calcSolvedData(options) {
|
|
695
|
+
this.solvedProblemNum = 0;
|
|
696
|
+
this.attemptedProblemNum = 0;
|
|
697
|
+
this.penalty = 0;
|
|
698
|
+
for (const p of this.problemStatistics) {
|
|
699
|
+
if (p.isAccepted) {
|
|
700
|
+
this.solvedProblemNum++;
|
|
701
|
+
this.attemptedProblemNum += p.failedCount + 1;
|
|
702
|
+
if (options?.calculationOfPenalty === "in_seconds" || options?.calculationOfPenalty === "accumulate_in_seconds_and_finally_to_the_minute") {
|
|
703
|
+
this.penalty += p.penaltyInSecond;
|
|
487
704
|
} else {
|
|
488
|
-
|
|
705
|
+
this.penalty += p.penalty;
|
|
489
706
|
}
|
|
490
707
|
}
|
|
491
|
-
arr.push(team.isUnofficial ? "Y" : "N");
|
|
492
|
-
arr.push(team.isGirl ? "Y" : "N");
|
|
493
|
-
aoa.push(arr);
|
|
494
708
|
}
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
}
|
|
498
|
-
|
|
499
|
-
class ICPCStandingsCsvConverter {
|
|
500
|
-
constructor() {
|
|
501
|
-
}
|
|
502
|
-
convert(oriRank) {
|
|
503
|
-
const rank = ___default.cloneDeep(oriRank);
|
|
504
|
-
rank.options.disableFilterTeamsByGroup();
|
|
505
|
-
rank.options.disableFilterSubmissionByTimestamp();
|
|
506
|
-
rank.options.setGroup("official");
|
|
507
|
-
rank.buildRank();
|
|
508
|
-
const resList = [];
|
|
509
|
-
for (const team of rank.teams) {
|
|
510
|
-
const res = {
|
|
511
|
-
teamId: team.icpcID ?? "",
|
|
512
|
-
rank: team.rank,
|
|
513
|
-
medalCitation: this.getMedalCitation(team),
|
|
514
|
-
problemsSolved: team.solvedProblemNum,
|
|
515
|
-
totalTime: team.penaltyToMinute,
|
|
516
|
-
lastProblemTime: team.lastSolvedProblemStatistics?.solvedTimestampToMinute ?? 0,
|
|
517
|
-
siteCitation: rank.contest.name,
|
|
518
|
-
citation: ordinal__default(team.rank),
|
|
519
|
-
teamName: team.name,
|
|
520
|
-
institution: team.organization
|
|
521
|
-
};
|
|
522
|
-
resList.push(res);
|
|
709
|
+
if (options?.calculationOfPenalty === "accumulate_in_seconds_and_finally_to_the_minute") {
|
|
710
|
+
this.penalty = Math.floor(this.penalty / 60) * 60;
|
|
523
711
|
}
|
|
524
|
-
const csv = Papa__default.unparse(resList);
|
|
525
|
-
return csv;
|
|
526
712
|
}
|
|
527
|
-
|
|
528
|
-
if (
|
|
529
|
-
return
|
|
713
|
+
calcAwards(awards) {
|
|
714
|
+
if (!awards) {
|
|
715
|
+
return;
|
|
530
716
|
}
|
|
531
|
-
const
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
if (medal === "Gold") {
|
|
535
|
-
return "Gold Medal";
|
|
536
|
-
}
|
|
537
|
-
if (medal === "Silver") {
|
|
538
|
-
return "Silver Medal";
|
|
539
|
-
}
|
|
540
|
-
if (medal === "Bronze") {
|
|
541
|
-
return "Bronze Medal";
|
|
542
|
-
}
|
|
543
|
-
if (medal === "Honorable") {
|
|
544
|
-
return "Honorable Mention";
|
|
717
|
+
for (const award of awards) {
|
|
718
|
+
if (this.rank >= award.minRank && this.rank <= award.maxRank) {
|
|
719
|
+
this.awards.push(award.medalType);
|
|
545
720
|
}
|
|
546
721
|
}
|
|
547
|
-
return "";
|
|
548
722
|
}
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
class Person {
|
|
552
|
-
constructor(name = "") {
|
|
553
|
-
this.name = name;
|
|
723
|
+
isEqualRank(otherTeam) {
|
|
724
|
+
return this.solvedProblemNum === otherTeam.solvedProblemNum && this.penalty === otherTeam.penalty;
|
|
554
725
|
}
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
}
|
|
726
|
+
postProcessPlaceChartPoints() {
|
|
727
|
+
if (this.placeChartPoints.length === 0) {
|
|
728
|
+
return;
|
|
729
|
+
}
|
|
730
|
+
const res = [];
|
|
731
|
+
res.push(this.placeChartPoints[0]);
|
|
732
|
+
for (let i = 1; i < this.placeChartPoints.length - 1; i++) {
|
|
733
|
+
const p = this.placeChartPoints[i];
|
|
734
|
+
const preP = res[res.length - 1];
|
|
735
|
+
if (p.rank !== preP.rank || p.lastSolvedProblem !== preP.lastSolvedProblem) {
|
|
736
|
+
res.push(p);
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
if (this.placeChartPoints.length > 1) {
|
|
740
|
+
res.push(this.placeChartPoints[this.placeChartPoints.length - 1]);
|
|
741
|
+
}
|
|
742
|
+
this.placeChartPoints = res;
|
|
559
743
|
}
|
|
560
|
-
static
|
|
561
|
-
if (
|
|
562
|
-
|
|
744
|
+
static compare(lhs, rhs) {
|
|
745
|
+
if (lhs.solvedProblemNum !== rhs.solvedProblemNum) {
|
|
746
|
+
return rhs.solvedProblemNum - lhs.solvedProblemNum;
|
|
563
747
|
}
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
748
|
+
if (lhs.penalty !== rhs.penalty) {
|
|
749
|
+
return lhs.penalty - rhs.penalty;
|
|
750
|
+
}
|
|
751
|
+
if (lhs.lastSolvedProblemStatistics && rhs.lastSolvedProblemStatistics) {
|
|
752
|
+
return lhs.lastSolvedProblemStatistics.solvedTimestampToMinute - rhs.lastSolvedProblemStatistics.solvedTimestampToMinute;
|
|
753
|
+
}
|
|
754
|
+
if (lhs.name < rhs.name) {
|
|
755
|
+
return -1;
|
|
756
|
+
} else if (lhs.name > rhs.name) {
|
|
757
|
+
return 1;
|
|
758
|
+
}
|
|
759
|
+
return 0;
|
|
567
760
|
}
|
|
568
761
|
}
|
|
569
|
-
function
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
762
|
+
function createTeam(teamJSON) {
|
|
763
|
+
const t = new Team();
|
|
764
|
+
t.id = teamJSON.id ?? teamJSON.team_id ?? "";
|
|
765
|
+
t.name = teamJSON.name ?? teamJSON.team_name ?? "";
|
|
766
|
+
t.organization = teamJSON.organization ?? "";
|
|
767
|
+
t.badge = teamJSON.badge;
|
|
768
|
+
t.group = ___default.cloneDeep(teamJSON.group ?? []);
|
|
769
|
+
t.tag = ___default.cloneDeep(teamJSON.tag ?? []);
|
|
770
|
+
t.coach = teamJSON.coach;
|
|
771
|
+
t.members = teamJSON.members;
|
|
772
|
+
if (Boolean(teamJSON.official) === true) {
|
|
773
|
+
t.group.push("official");
|
|
774
|
+
}
|
|
775
|
+
if (Boolean(teamJSON.unofficial) === true) {
|
|
776
|
+
t.group.push("unofficial");
|
|
777
|
+
}
|
|
778
|
+
if (Boolean(teamJSON.girl) === true) {
|
|
779
|
+
t.group.push("girl");
|
|
780
|
+
}
|
|
781
|
+
{
|
|
782
|
+
const tt = teamJSON;
|
|
783
|
+
for (const key of Object.keys(tt)) {
|
|
784
|
+
if (tt[key] === 1 || tt[key] === true) {
|
|
785
|
+
t.group.push(key);
|
|
574
786
|
}
|
|
575
787
|
}
|
|
576
|
-
return [new Person(iPersons)];
|
|
577
788
|
}
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
if (solvedNum === 0) {
|
|
583
|
-
return 0;
|
|
789
|
+
t.group = [...new Set(t.group)];
|
|
790
|
+
t.group.sort();
|
|
791
|
+
if (teamJSON.location) {
|
|
792
|
+
t.location = teamJSON.location;
|
|
584
793
|
}
|
|
585
|
-
|
|
794
|
+
if (teamJSON.icpc_id) {
|
|
795
|
+
t.icpcID = teamJSON.icpc_id;
|
|
796
|
+
}
|
|
797
|
+
return t;
|
|
586
798
|
}
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
const color = { R, G, B };
|
|
591
|
-
const palette = [
|
|
592
|
-
{ R: 0, G: 0, B: 0 },
|
|
593
|
-
{ R: 255, G: 255, B: 255 }
|
|
594
|
-
];
|
|
595
|
-
const f = colorDiff.furthest(color, palette);
|
|
596
|
-
if (f.R === 0 && f.G === 0 && f.B === 0) {
|
|
597
|
-
return "#000";
|
|
799
|
+
function createTeams(teamsJSON) {
|
|
800
|
+
if (Array.isArray(teamsJSON)) {
|
|
801
|
+
return teamsJSON.map((t) => createTeam(t));
|
|
598
802
|
} else {
|
|
599
|
-
|
|
803
|
+
const teams = Object.entries(teamsJSON).map(
|
|
804
|
+
([teamId, team]) => createTeam({ ...team, team_id: team.team_id ?? teamId })
|
|
805
|
+
);
|
|
806
|
+
return teams;
|
|
600
807
|
}
|
|
601
808
|
}
|
|
602
|
-
function getWhiteOrBlackColor(background) {
|
|
603
|
-
const [R, G, B] = chroma__default(background).rgb();
|
|
604
|
-
const brightness = (R * 299 + G * 587 + B * 114) / 1e3;
|
|
605
|
-
const threshold = 148;
|
|
606
|
-
return brightness <= threshold ? "#fff" : "#000";
|
|
607
|
-
}
|
|
608
809
|
|
|
609
|
-
|
|
810
|
+
var __defProp$f = Object.defineProperty;
|
|
811
|
+
var __defNormalProp$f = (obj, key, value) => key in obj ? __defProp$f(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
812
|
+
var __publicField$f = (obj, key, value) => {
|
|
813
|
+
__defNormalProp$f(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
814
|
+
return value;
|
|
815
|
+
};
|
|
816
|
+
class Balloon {
|
|
610
817
|
constructor() {
|
|
611
|
-
this
|
|
612
|
-
this
|
|
613
|
-
this
|
|
614
|
-
this.
|
|
615
|
-
this.
|
|
616
|
-
this.
|
|
617
|
-
this.contestID = "";
|
|
618
|
-
this.contestName = "";
|
|
619
|
-
this.contestLink = "";
|
|
620
|
-
this.contestTime = createDayJS();
|
|
818
|
+
__publicField$f(this, "problem");
|
|
819
|
+
__publicField$f(this, "team");
|
|
820
|
+
__publicField$f(this, "submission");
|
|
821
|
+
this.problem = new Problem();
|
|
822
|
+
this.team = new Team();
|
|
823
|
+
this.submission = new Submission();
|
|
621
824
|
}
|
|
622
|
-
|
|
623
|
-
return {
|
|
624
|
-
rank: this.rank,
|
|
625
|
-
rating: this.rating,
|
|
626
|
-
teamName: this.teamName,
|
|
627
|
-
organization: this.organization,
|
|
628
|
-
members: this.members.map((member) => member.toJSON()),
|
|
629
|
-
coaches: this.coaches.map((coach) => coach.toJSON()),
|
|
630
|
-
contestID: this.contestID,
|
|
631
|
-
contestName: this.contestName,
|
|
632
|
-
contestLink: this.contestLink,
|
|
633
|
-
contestTime: this.contestTime.toDate()
|
|
634
|
-
};
|
|
825
|
+
get key() {
|
|
826
|
+
return `balloon-${this.team.id}-${this.problem.id}`;
|
|
635
827
|
}
|
|
636
|
-
static
|
|
637
|
-
|
|
638
|
-
iRatingHistory = JSON.parse(iRatingHistory);
|
|
639
|
-
}
|
|
640
|
-
const ratingHistory = new RatingHistory();
|
|
641
|
-
ratingHistory.rank = iRatingHistory.rank;
|
|
642
|
-
ratingHistory.rating = iRatingHistory.rating;
|
|
643
|
-
ratingHistory.teamName = iRatingHistory.teamName;
|
|
644
|
-
ratingHistory.organization = iRatingHistory.organization;
|
|
645
|
-
ratingHistory.members = iRatingHistory.members.map((iMember) => Person.fromJSON(iMember));
|
|
646
|
-
ratingHistory.coaches = iRatingHistory.coaches.map((iCoach) => Person.fromJSON(iCoach));
|
|
647
|
-
ratingHistory.contestID = iRatingHistory.contestID;
|
|
648
|
-
ratingHistory.contestName = iRatingHistory.contestName;
|
|
649
|
-
ratingHistory.contestLink = iRatingHistory.contestLink;
|
|
650
|
-
ratingHistory.contestTime = createDayJS(iRatingHistory.contestTime);
|
|
651
|
-
return ratingHistory;
|
|
828
|
+
static compare(lhs, rhs) {
|
|
829
|
+
return Submission.compare(lhs.submission, rhs.submission);
|
|
652
830
|
}
|
|
653
831
|
}
|
|
654
832
|
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
this
|
|
669
|
-
this
|
|
833
|
+
var __defProp$e = Object.defineProperty;
|
|
834
|
+
var __defNormalProp$e = (obj, key, value) => key in obj ? __defProp$e(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
835
|
+
var __publicField$e = (obj, key, value) => {
|
|
836
|
+
__defNormalProp$e(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
837
|
+
return value;
|
|
838
|
+
};
|
|
839
|
+
var GiantsType = /* @__PURE__ */ ((GiantsType2) => {
|
|
840
|
+
GiantsType2[GiantsType2["BLUE"] = 0] = "BLUE";
|
|
841
|
+
GiantsType2[GiantsType2["RED"] = 1] = "RED";
|
|
842
|
+
return GiantsType2;
|
|
843
|
+
})(GiantsType || {});
|
|
844
|
+
class Giants {
|
|
845
|
+
constructor(type = 0 /* BLUE */) {
|
|
846
|
+
__publicField$e(this, "type");
|
|
847
|
+
__publicField$e(this, "name");
|
|
848
|
+
__publicField$e(this, "filterOrganizations");
|
|
849
|
+
__publicField$e(this, "filterOrganizationMap");
|
|
850
|
+
__publicField$e(this, "filterTeams");
|
|
851
|
+
__publicField$e(this, "filterTeamMap");
|
|
852
|
+
__publicField$e(this, "teams");
|
|
853
|
+
this.type = type;
|
|
854
|
+
this.name = `${type === 0 /* BLUE */ ? "Blue" : "Red"} Team`;
|
|
855
|
+
this.teams = [];
|
|
856
|
+
this.filterOrganizations = [];
|
|
857
|
+
this.filterOrganizationMap = /* @__PURE__ */ new Map();
|
|
858
|
+
this.filterTeams = [];
|
|
859
|
+
this.filterTeamMap = /* @__PURE__ */ new Map();
|
|
670
860
|
}
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
861
|
+
setFilterOrganizations(filterOrganizations) {
|
|
862
|
+
const m = /* @__PURE__ */ new Map();
|
|
863
|
+
filterOrganizations.forEach((item) => {
|
|
864
|
+
m.set(item.value, item);
|
|
865
|
+
});
|
|
866
|
+
this.filterOrganizations = filterOrganizations;
|
|
867
|
+
this.filterOrganizationMap = m;
|
|
675
868
|
}
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
rating: this.rating,
|
|
684
|
-
minRating: this.minRating,
|
|
685
|
-
maxRating: this.maxRating,
|
|
686
|
-
ratingHistories: this.ratingHistories.map((ratingHistory) => ratingHistory.toJSON())
|
|
687
|
-
};
|
|
869
|
+
setFilterTeams(filterTeams) {
|
|
870
|
+
const m = /* @__PURE__ */ new Map();
|
|
871
|
+
filterTeams.forEach((item) => {
|
|
872
|
+
m.set(item.value, item);
|
|
873
|
+
});
|
|
874
|
+
this.filterTeams = filterTeams;
|
|
875
|
+
this.filterTeamMap = m;
|
|
688
876
|
}
|
|
689
|
-
|
|
690
|
-
if (
|
|
691
|
-
|
|
692
|
-
}
|
|
693
|
-
|
|
694
|
-
ratingUser.id = iRatingUser.id;
|
|
695
|
-
ratingUser.name = iRatingUser.name;
|
|
696
|
-
ratingUser.organization = iRatingUser.organization;
|
|
697
|
-
ratingUser.members = iRatingUser.members.map((member) => Person.fromJSON(member));
|
|
698
|
-
ratingUser.coaches = iRatingUser.coaches.map((coach) => Person.fromJSON(coach));
|
|
699
|
-
ratingUser.rating = iRatingUser.rating;
|
|
700
|
-
ratingUser.minRating = iRatingUser.minRating;
|
|
701
|
-
ratingUser.maxRating = iRatingUser.maxRating;
|
|
702
|
-
for (const iRatingHistory of iRatingUser.ratingHistories) {
|
|
703
|
-
ratingUser.ratingHistories.push(RatingHistory.fromJSON(iRatingHistory));
|
|
877
|
+
refreshName() {
|
|
878
|
+
if (this.filterOrganizations.length > 0) {
|
|
879
|
+
this.name = this.filterOrganizations[0].text;
|
|
880
|
+
} else {
|
|
881
|
+
this.name = `${this.type === 0 /* BLUE */ ? "Blue" : "Red"} Team`;
|
|
704
882
|
}
|
|
705
|
-
return
|
|
706
|
-
}
|
|
707
|
-
}
|
|
708
|
-
|
|
709
|
-
class RatingCalculator {
|
|
710
|
-
constructor() {
|
|
711
|
-
this.users = [];
|
|
712
|
-
}
|
|
713
|
-
calculate() {
|
|
714
|
-
this.calculateInternal();
|
|
883
|
+
return this.name;
|
|
715
884
|
}
|
|
716
|
-
|
|
717
|
-
|
|
885
|
+
get totalSolvedProblemNum() {
|
|
886
|
+
let total = 0;
|
|
887
|
+
this.teams.forEach((team) => {
|
|
888
|
+
total += team.solvedProblemNum;
|
|
889
|
+
});
|
|
890
|
+
return total;
|
|
718
891
|
}
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
users.forEach((user) => {
|
|
724
|
-
if (user.id !== ownUser.id) {
|
|
725
|
-
res += this.calcP(user, exUser);
|
|
726
|
-
}
|
|
892
|
+
get totalPenalty() {
|
|
893
|
+
let total = 0;
|
|
894
|
+
this.teams.forEach((team) => {
|
|
895
|
+
total += team.penaltyToMinute;
|
|
727
896
|
});
|
|
728
|
-
return
|
|
897
|
+
return total;
|
|
729
898
|
}
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
if (this.getExSeed(users, mid, user) < rank) {
|
|
736
|
-
right = mid;
|
|
737
|
-
} else {
|
|
738
|
-
left = mid;
|
|
899
|
+
get totalPenaltyToString() {
|
|
900
|
+
const penalty = this.totalPenalty;
|
|
901
|
+
const two = (a) => {
|
|
902
|
+
if (a < 10) {
|
|
903
|
+
return `0${a}`;
|
|
739
904
|
}
|
|
740
|
-
|
|
741
|
-
|
|
905
|
+
return String(a);
|
|
906
|
+
};
|
|
907
|
+
const h = Math.floor(penalty / 60);
|
|
908
|
+
const m = Math.floor(penalty % 60);
|
|
909
|
+
return [two(h), two(m)].join(":");
|
|
742
910
|
}
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
911
|
+
toJSON() {
|
|
912
|
+
return {
|
|
913
|
+
type: this.type,
|
|
914
|
+
name: this.name,
|
|
915
|
+
filterOrganizations: this.filterOrganizations,
|
|
916
|
+
filterTeams: this.filterTeams
|
|
917
|
+
};
|
|
918
|
+
}
|
|
919
|
+
}
|
|
920
|
+
class BattleOfGiants {
|
|
921
|
+
constructor() {
|
|
922
|
+
__publicField$e(this, "enable");
|
|
923
|
+
__publicField$e(this, "topX");
|
|
924
|
+
__publicField$e(this, "equalTeams");
|
|
925
|
+
__publicField$e(this, "persist");
|
|
926
|
+
__publicField$e(this, "blueTeam");
|
|
927
|
+
__publicField$e(this, "redTeam");
|
|
928
|
+
this.enable = false;
|
|
929
|
+
this.topX = 5;
|
|
930
|
+
this.equalTeams = true;
|
|
931
|
+
this.persist = false;
|
|
932
|
+
this.blueTeam = new Giants(0 /* BLUE */);
|
|
933
|
+
this.redTeam = new Giants(1 /* RED */);
|
|
934
|
+
}
|
|
935
|
+
ToBase64() {
|
|
936
|
+
return jsBase64.Base64.encode(JSON.stringify(this));
|
|
937
|
+
}
|
|
938
|
+
FromBase64(base64) {
|
|
939
|
+
if (base64.length === 0) {
|
|
940
|
+
return;
|
|
766
941
|
}
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
let sumS = 0;
|
|
770
|
-
for (let i = 0; i < s; i++) {
|
|
771
|
-
sumS += this.users[i].delta;
|
|
942
|
+
if (jsBase64.Base64.isValid(base64) === false) {
|
|
943
|
+
return;
|
|
772
944
|
}
|
|
773
|
-
|
|
774
|
-
this.
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
this.
|
|
945
|
+
const j = JSON.parse(jsBase64.Base64.decode(base64));
|
|
946
|
+
this.enable = j.enable;
|
|
947
|
+
this.topX = j.topX;
|
|
948
|
+
this.equalTeams = j.equalTeams;
|
|
949
|
+
this.persist = j.persist;
|
|
950
|
+
this.blueTeam = new Giants(0 /* BLUE */);
|
|
951
|
+
this.blueTeam.name = j.blueTeam.name;
|
|
952
|
+
this.blueTeam.setFilterOrganizations(j.blueTeam.filterOrganizations);
|
|
953
|
+
this.blueTeam.setFilterTeams(j.blueTeam.filterTeams);
|
|
954
|
+
this.redTeam = new Giants(1 /* RED */);
|
|
955
|
+
this.redTeam.name = j.redTeam.name;
|
|
956
|
+
this.redTeam.setFilterOrganizations(j.redTeam.filterOrganizations);
|
|
957
|
+
this.redTeam.setFilterTeams(j.redTeam.filterTeams);
|
|
779
958
|
}
|
|
780
959
|
}
|
|
781
960
|
|
|
782
|
-
var
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
RatingLevel2["CANDIDATE_MASTER"] = "CANDIDATE_MASTER";
|
|
788
|
-
RatingLevel2["MASTER"] = "MASTER";
|
|
789
|
-
RatingLevel2["INTERNATIONAL_MASTER"] = "INTERNATIONAL_MASTER";
|
|
790
|
-
RatingLevel2["GRANDMASTER"] = "GRANDMASTER";
|
|
791
|
-
RatingLevel2["INTERNATIONAL_GRANDMASTER"] = "INTERNATIONAL_GRANDMASTER";
|
|
792
|
-
RatingLevel2["LEGENDARY_GRANDMASTER"] = "LEGENDARY_GRANDMASTER";
|
|
793
|
-
return RatingLevel2;
|
|
794
|
-
})(RatingLevel || {});
|
|
795
|
-
const RatingLevelToString = {
|
|
796
|
-
["NEWBIE" /* NEWBIE */]: "Newbie",
|
|
797
|
-
["PUPIL" /* PUPIL */]: "Pupil",
|
|
798
|
-
["SPECIALIST" /* SPECIALIST */]: "Specialist",
|
|
799
|
-
["EXPERT" /* EXPERT */]: "Expert",
|
|
800
|
-
["CANDIDATE_MASTER" /* CANDIDATE_MASTER */]: "Candidate Master",
|
|
801
|
-
["MASTER" /* MASTER */]: "Master",
|
|
802
|
-
["INTERNATIONAL_MASTER" /* INTERNATIONAL_MASTER */]: "International Master",
|
|
803
|
-
["GRANDMASTER" /* GRANDMASTER */]: "Grandmaster",
|
|
804
|
-
["INTERNATIONAL_GRANDMASTER" /* INTERNATIONAL_GRANDMASTER */]: "International Grandmaster",
|
|
805
|
-
["LEGENDARY_GRANDMASTER" /* LEGENDARY_GRANDMASTER */]: "Legendary Grandmaster"
|
|
961
|
+
var __defProp$d = Object.defineProperty;
|
|
962
|
+
var __defNormalProp$d = (obj, key, value) => key in obj ? __defProp$d(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
963
|
+
var __publicField$d = (obj, key, value) => {
|
|
964
|
+
__defNormalProp$d(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
965
|
+
return value;
|
|
806
966
|
};
|
|
807
|
-
class
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
} else if (rating >= 1900) {
|
|
820
|
-
return "CANDIDATE_MASTER" /* CANDIDATE_MASTER */;
|
|
821
|
-
} else if (rating >= 1600) {
|
|
822
|
-
return "EXPERT" /* EXPERT */;
|
|
823
|
-
} else if (rating >= 1400) {
|
|
824
|
-
return "SPECIALIST" /* SPECIALIST */;
|
|
825
|
-
} else if (rating >= 1200) {
|
|
826
|
-
return "PUPIL" /* PUPIL */;
|
|
827
|
-
}
|
|
828
|
-
return "NEWBIE" /* NEWBIE */;
|
|
967
|
+
class ContestOptions {
|
|
968
|
+
constructor() {
|
|
969
|
+
__publicField$d(this, "calculationOfPenalty");
|
|
970
|
+
__publicField$d(this, "submissionTimestampUnit");
|
|
971
|
+
__publicField$d(this, "submissionHasTimeField");
|
|
972
|
+
__publicField$d(this, "submissionHasLanguageField");
|
|
973
|
+
__publicField$d(this, "submissionEnableActionField");
|
|
974
|
+
this.calculationOfPenalty = "in_minutes";
|
|
975
|
+
this.submissionTimestampUnit = "second";
|
|
976
|
+
this.submissionHasTimeField = false;
|
|
977
|
+
this.submissionHasLanguageField = false;
|
|
978
|
+
this.submissionEnableActionField = false;
|
|
829
979
|
}
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
return "user-blue";
|
|
843
|
-
case "CANDIDATE_MASTER" /* CANDIDATE_MASTER */:
|
|
844
|
-
return "user-violet";
|
|
845
|
-
case "MASTER" /* MASTER */:
|
|
846
|
-
return "user-orange";
|
|
847
|
-
case "INTERNATIONAL_MASTER" /* INTERNATIONAL_MASTER */:
|
|
848
|
-
return "user-orange";
|
|
849
|
-
case "GRANDMASTER" /* GRANDMASTER */:
|
|
850
|
-
return "user-red";
|
|
851
|
-
case "INTERNATIONAL_GRANDMASTER" /* INTERNATIONAL_GRANDMASTER */:
|
|
852
|
-
return "user-red";
|
|
853
|
-
case "LEGENDARY_GRANDMASTER" /* LEGENDARY_GRANDMASTER */:
|
|
854
|
-
return "user-legendary";
|
|
855
|
-
}
|
|
980
|
+
}
|
|
981
|
+
function createContestOptions(contestOptionsJSON = {}) {
|
|
982
|
+
const j = contestOptionsJSON;
|
|
983
|
+
const o = new ContestOptions();
|
|
984
|
+
if (j.calculation_of_penalty) {
|
|
985
|
+
o.calculationOfPenalty = j.calculation_of_penalty;
|
|
986
|
+
}
|
|
987
|
+
if (j.submission_timestamp_unit) {
|
|
988
|
+
o.submissionTimestampUnit = j.submission_timestamp_unit;
|
|
989
|
+
}
|
|
990
|
+
if (j.submission_has_reaction) {
|
|
991
|
+
o.submissionEnableActionField = j.submission_has_reaction;
|
|
856
992
|
}
|
|
993
|
+
return o;
|
|
857
994
|
}
|
|
858
995
|
|
|
859
|
-
|
|
996
|
+
var __defProp$c = Object.defineProperty;
|
|
997
|
+
var __defNormalProp$c = (obj, key, value) => key in obj ? __defProp$c(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
998
|
+
var __publicField$c = (obj, key, value) => {
|
|
999
|
+
__defNormalProp$c(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
1000
|
+
return value;
|
|
1001
|
+
};
|
|
1002
|
+
class Group {
|
|
860
1003
|
constructor() {
|
|
861
|
-
this
|
|
862
|
-
this
|
|
863
|
-
this
|
|
864
|
-
this.
|
|
865
|
-
this.
|
|
866
|
-
this.
|
|
867
|
-
this.userMap = /* @__PURE__ */ new Map();
|
|
868
|
-
}
|
|
869
|
-
buildRating() {
|
|
870
|
-
for (const rank of this.ranks) {
|
|
871
|
-
rank.buildRank();
|
|
872
|
-
const ratingCalculator = new RatingCalculator();
|
|
873
|
-
for (const t of rank.teams) {
|
|
874
|
-
const id = this.generateTeamId(t);
|
|
875
|
-
let u = null;
|
|
876
|
-
if (!this.userMap.has(id)) {
|
|
877
|
-
u = new RatingUser();
|
|
878
|
-
u.id = id;
|
|
879
|
-
u.name = t.name;
|
|
880
|
-
u.organization = t.organization;
|
|
881
|
-
u.members = createPersons(t.members ?? []);
|
|
882
|
-
u.coaches = createPersons(t.coach ?? []);
|
|
883
|
-
u.rank = t.rank;
|
|
884
|
-
u.oldRating = this.baseRating;
|
|
885
|
-
u.UpdateRating(this.baseRating);
|
|
886
|
-
this.userMap.set(id, u);
|
|
887
|
-
this.users.push(u);
|
|
888
|
-
ratingCalculator.users.push(u);
|
|
889
|
-
} else {
|
|
890
|
-
u = this.userMap.get(id);
|
|
891
|
-
u.rank = t.rank;
|
|
892
|
-
u.oldRating = u.rating;
|
|
893
|
-
ratingCalculator.users.push(u);
|
|
894
|
-
}
|
|
895
|
-
{
|
|
896
|
-
const h = new RatingHistory();
|
|
897
|
-
h.rank = t.rank;
|
|
898
|
-
h.rating = u.rating;
|
|
899
|
-
h.teamName = t.name;
|
|
900
|
-
h.organization = t.organization;
|
|
901
|
-
h.members = createPersons(t.members ?? []);
|
|
902
|
-
h.coaches = createPersons(t.coach ?? []);
|
|
903
|
-
h.contestID = rank.contest.id;
|
|
904
|
-
h.contestLink = h.contestID;
|
|
905
|
-
h.contestName = rank.contest.name;
|
|
906
|
-
h.contestTime = rank.contest.startTime;
|
|
907
|
-
u.ratingHistories.push(h);
|
|
908
|
-
}
|
|
909
|
-
}
|
|
910
|
-
ratingCalculator.calculate();
|
|
911
|
-
for (const u of ratingCalculator.users) {
|
|
912
|
-
u.ratingHistories.at(-1).rating = u.rating;
|
|
913
|
-
}
|
|
914
|
-
}
|
|
915
|
-
}
|
|
916
|
-
generateTeamId(t) {
|
|
917
|
-
const persons = createPersons(t.members ?? []);
|
|
918
|
-
if (persons.length > 0) {
|
|
919
|
-
return persons.map((person) => person.name.trim()).sort().join("|");
|
|
920
|
-
}
|
|
921
|
-
return `${t.organization}-${t.name}`;
|
|
922
|
-
}
|
|
923
|
-
toJSON() {
|
|
924
|
-
return {
|
|
925
|
-
id: this.id,
|
|
926
|
-
name: this.name,
|
|
927
|
-
baseRating: this.baseRating,
|
|
928
|
-
contestIDs: this.contestIDs,
|
|
929
|
-
users: this.users.map((ratingUser) => ratingUser.toJSON())
|
|
930
|
-
};
|
|
931
|
-
}
|
|
932
|
-
static fromJSON(iRating) {
|
|
933
|
-
if (typeof iRating === "string") {
|
|
934
|
-
iRating = JSON.parse(iRating);
|
|
935
|
-
}
|
|
936
|
-
const rating = new Rating();
|
|
937
|
-
rating.id = iRating.id;
|
|
938
|
-
rating.name = iRating.name;
|
|
939
|
-
rating.baseRating = iRating.baseRating;
|
|
940
|
-
rating.contestIDs = iRating.contestIDs;
|
|
941
|
-
for (const iUser of iRating.users) {
|
|
942
|
-
rating.users.push(RatingUser.fromJSON(iUser));
|
|
943
|
-
}
|
|
944
|
-
return rating;
|
|
1004
|
+
__publicField$c(this, "names");
|
|
1005
|
+
__publicField$c(this, "defaultLang");
|
|
1006
|
+
__publicField$c(this, "isDefault");
|
|
1007
|
+
this.names = /* @__PURE__ */ new Map();
|
|
1008
|
+
this.defaultLang = "zh-CN";
|
|
1009
|
+
this.isDefault = false;
|
|
945
1010
|
}
|
|
946
1011
|
}
|
|
947
1012
|
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
this.ignoreNum = 0;
|
|
956
|
-
this.se = 0;
|
|
957
|
-
this.firstSolveSubmissions = [];
|
|
958
|
-
this.lastSolveSubmissions = [];
|
|
959
|
-
}
|
|
960
|
-
reset() {
|
|
961
|
-
this.acceptedNum = 0;
|
|
962
|
-
this.rejectedNum = 0;
|
|
963
|
-
this.pendingNum = 0;
|
|
964
|
-
this.submittedNum = 0;
|
|
965
|
-
this.attemptedNum = 0;
|
|
966
|
-
this.ignoreNum = 0;
|
|
967
|
-
this.se = 0;
|
|
968
|
-
this.firstSolveSubmissions = [];
|
|
969
|
-
this.lastSolveSubmissions = [];
|
|
970
|
-
}
|
|
971
|
-
get dirt() {
|
|
972
|
-
if (this.acceptedNum === 0) {
|
|
973
|
-
return 0;
|
|
974
|
-
}
|
|
975
|
-
return calcDirt(this.attemptedNum, this.acceptedNum);
|
|
976
|
-
}
|
|
977
|
-
calcSE(totalTeams) {
|
|
978
|
-
const res = (totalTeams - this.acceptedNum) / totalTeams;
|
|
979
|
-
this.se = Math.round(res * 100) / 100;
|
|
980
|
-
return this.se;
|
|
981
|
-
}
|
|
982
|
-
}
|
|
983
|
-
class Problem {
|
|
1013
|
+
var __defProp$b = Object.defineProperty;
|
|
1014
|
+
var __defNormalProp$b = (obj, key, value) => key in obj ? __defProp$b(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
1015
|
+
var __publicField$b = (obj, key, value) => {
|
|
1016
|
+
__defNormalProp$b(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
1017
|
+
return value;
|
|
1018
|
+
};
|
|
1019
|
+
class Contest {
|
|
984
1020
|
constructor() {
|
|
985
|
-
this
|
|
986
|
-
this
|
|
987
|
-
this
|
|
988
|
-
this
|
|
989
|
-
this
|
|
990
|
-
|
|
991
|
-
|
|
1021
|
+
__publicField$b(this, "id", "");
|
|
1022
|
+
__publicField$b(this, "name", "");
|
|
1023
|
+
__publicField$b(this, "startTime");
|
|
1024
|
+
__publicField$b(this, "endTime");
|
|
1025
|
+
__publicField$b(this, "freezeTime");
|
|
1026
|
+
__publicField$b(this, "replayStartTime");
|
|
1027
|
+
__publicField$b(this, "replayEndTime");
|
|
1028
|
+
__publicField$b(this, "replayFreezeTime");
|
|
1029
|
+
__publicField$b(this, "replayNowTime");
|
|
1030
|
+
__publicField$b(this, "replayContestStartTimestamp");
|
|
1031
|
+
__publicField$b(this, "totalDurationTimestamp");
|
|
1032
|
+
__publicField$b(this, "freezeDurationTimestamp");
|
|
1033
|
+
__publicField$b(this, "unFreezeDurationTimestamp");
|
|
1034
|
+
__publicField$b(this, "penalty");
|
|
1035
|
+
__publicField$b(this, "problems");
|
|
1036
|
+
__publicField$b(this, "problemsMap");
|
|
1037
|
+
__publicField$b(this, "statusTimeDisplay");
|
|
1038
|
+
__publicField$b(this, "badge");
|
|
1039
|
+
__publicField$b(this, "medal");
|
|
1040
|
+
__publicField$b(this, "awards");
|
|
1041
|
+
__publicField$b(this, "organization");
|
|
1042
|
+
__publicField$b(this, "group");
|
|
1043
|
+
__publicField$b(this, "tag");
|
|
1044
|
+
__publicField$b(this, "logo");
|
|
1045
|
+
__publicField$b(this, "banner");
|
|
1046
|
+
__publicField$b(this, "bannerMode");
|
|
1047
|
+
__publicField$b(this, "boardLink");
|
|
1048
|
+
__publicField$b(this, "options");
|
|
1049
|
+
this.startTime = createDayJS();
|
|
1050
|
+
this.endTime = createDayJS();
|
|
1051
|
+
this.freezeTime = createDayJS();
|
|
1052
|
+
this.totalDurationTimestamp = 0;
|
|
1053
|
+
this.freezeDurationTimestamp = 0;
|
|
1054
|
+
this.unFreezeDurationTimestamp = 0;
|
|
1055
|
+
this.penalty = 20 * 60;
|
|
1056
|
+
this.problems = [];
|
|
1057
|
+
this.problemsMap = /* @__PURE__ */ new Map();
|
|
1058
|
+
this.statusTimeDisplay = {
|
|
1059
|
+
correct: true,
|
|
1060
|
+
incorrect: true,
|
|
1061
|
+
pending: true
|
|
992
1062
|
};
|
|
1063
|
+
this.group = /* @__PURE__ */ new Map();
|
|
1064
|
+
this.tag = /* @__PURE__ */ new Map();
|
|
1065
|
+
this.options = new ContestOptions();
|
|
993
1066
|
}
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
const p = new Problem();
|
|
997
|
-
p.id = String(problemJSON.id);
|
|
998
|
-
p.label = problemJSON.label;
|
|
999
|
-
p.name = problemJSON.name ?? "";
|
|
1000
|
-
p.timeLimit = problemJSON.time_limit;
|
|
1001
|
-
p.memoryLimit = problemJSON.memory_limit;
|
|
1002
|
-
if (problemJSON.balloon_color) {
|
|
1003
|
-
p.balloonColor = ___default.cloneDeep(problemJSON.balloon_color);
|
|
1067
|
+
getStartTime() {
|
|
1068
|
+
return this.replayStartTime ?? this.startTime;
|
|
1004
1069
|
}
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
}
|
|
1008
|
-
function createProblems(problemsJSON) {
|
|
1009
|
-
return problemsJSON.map((pJSON) => createProblem(pJSON));
|
|
1010
|
-
}
|
|
1011
|
-
function createProblemsByProblemIds(problemIds, balloonColors) {
|
|
1012
|
-
const problems = problemIds.map((label, index) => {
|
|
1013
|
-
const p = new Problem();
|
|
1014
|
-
p.id = String(index);
|
|
1015
|
-
p.label = label;
|
|
1016
|
-
return p;
|
|
1017
|
-
});
|
|
1018
|
-
if (balloonColors !== void 0 && balloonColors !== null) {
|
|
1019
|
-
for (const index in balloonColors) {
|
|
1020
|
-
problems[index].balloonColor = ___default.cloneDeep(balloonColors[index]);
|
|
1021
|
-
}
|
|
1070
|
+
getEndTime() {
|
|
1071
|
+
return this.replayEndTime ?? this.endTime;
|
|
1022
1072
|
}
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
});
|
|
1026
|
-
return problems;
|
|
1027
|
-
}
|
|
1028
|
-
class TeamProblemStatistics {
|
|
1029
|
-
constructor(options) {
|
|
1030
|
-
this.isFirstSolved = options?.teamProblemStatistics?.isFirstSolved ?? false;
|
|
1031
|
-
this.isSolved = options?.teamProblemStatistics?.isSolved ?? false;
|
|
1032
|
-
this.solvedTimestamp = options?.teamProblemStatistics?.solvedTimestamp ?? 0;
|
|
1033
|
-
this.isSubmitted = options?.teamProblemStatistics?.isSubmitted ?? false;
|
|
1034
|
-
this.lastSubmitTimestamp = options?.teamProblemStatistics?.lastSubmitTimestamp ?? 0;
|
|
1035
|
-
this.failedCount = options?.teamProblemStatistics?.failedCount ?? 0;
|
|
1036
|
-
this.pendingCount = options?.teamProblemStatistics?.pendingCount ?? 0;
|
|
1037
|
-
this.ignoreCount = options?.teamProblemStatistics?.ignoreCount ?? 0;
|
|
1038
|
-
this.totalCount = options?.teamProblemStatistics?.totalCount ?? 0;
|
|
1039
|
-
this.submissions = options?.teamProblemStatistics?.submissions ?? [];
|
|
1040
|
-
this.problem = options?.teamProblemStatistics?.problem ?? new Problem();
|
|
1041
|
-
this.contestPenalty = options?.teamProblemStatistics?.contestPenalty ?? 20 * 60;
|
|
1073
|
+
getFreezeTime() {
|
|
1074
|
+
return this.replayFreezeTime ?? this.freezeTime;
|
|
1042
1075
|
}
|
|
1043
|
-
|
|
1044
|
-
return this.
|
|
1076
|
+
getContestDuration(timeFormat = "HH:mm:ss") {
|
|
1077
|
+
return dayjs__default.duration(this.getEndTime().diff(this.getStartTime())).format(timeFormat);
|
|
1045
1078
|
}
|
|
1046
|
-
|
|
1047
|
-
|
|
1079
|
+
getContestState(nowTime) {
|
|
1080
|
+
const now = createDayJS(nowTime);
|
|
1081
|
+
if (now.isBefore(this.getStartTime())) {
|
|
1082
|
+
return types.ContestState.PENDING;
|
|
1083
|
+
}
|
|
1084
|
+
if (now.isSameOrAfter(this.getEndTime())) {
|
|
1085
|
+
return types.ContestState.FINISHED;
|
|
1086
|
+
}
|
|
1087
|
+
if (now.isSameOrAfter(this.getFreezeTime())) {
|
|
1088
|
+
return types.ContestState.FROZEN;
|
|
1089
|
+
}
|
|
1090
|
+
return types.ContestState.RUNNING;
|
|
1048
1091
|
}
|
|
1049
|
-
|
|
1050
|
-
|
|
1092
|
+
getContestPendingTime(nowTime) {
|
|
1093
|
+
let baseTime = createDayJS(nowTime);
|
|
1094
|
+
if (baseTime.isAfter(this.getStartTime())) {
|
|
1095
|
+
baseTime = this.getStartTime();
|
|
1096
|
+
}
|
|
1097
|
+
return getTimeDiff(Math.floor(dayjs__default.duration(this.getStartTime().diff(baseTime)).asSeconds()));
|
|
1051
1098
|
}
|
|
1052
|
-
|
|
1053
|
-
|
|
1099
|
+
getContestElapsedTime(nowTime) {
|
|
1100
|
+
let baseTime = createDayJS(nowTime);
|
|
1101
|
+
if (baseTime.isAfter(this.getEndTime())) {
|
|
1102
|
+
baseTime = this.getEndTime();
|
|
1103
|
+
}
|
|
1104
|
+
if (baseTime.isBefore(this.getStartTime())) {
|
|
1105
|
+
baseTime = this.getStartTime();
|
|
1106
|
+
}
|
|
1107
|
+
return getTimeDiff(Math.floor(dayjs__default.duration(baseTime.diff(this.getStartTime())).asSeconds()));
|
|
1054
1108
|
}
|
|
1055
|
-
|
|
1056
|
-
|
|
1109
|
+
getContestRemainingTime(nowTime) {
|
|
1110
|
+
let baseTime = createDayJS(nowTime);
|
|
1111
|
+
if (baseTime.isAfter(this.getEndTime())) {
|
|
1112
|
+
baseTime = this.getEndTime();
|
|
1113
|
+
}
|
|
1114
|
+
if (baseTime.isBefore(this.getStartTime())) {
|
|
1115
|
+
baseTime = this.getStartTime();
|
|
1116
|
+
}
|
|
1117
|
+
return getTimeDiff(Math.floor(dayjs__default.duration(this.getEndTime().diff(baseTime)).asSeconds()));
|
|
1057
1118
|
}
|
|
1058
|
-
|
|
1059
|
-
|
|
1119
|
+
getContestProgressRatio(nowTime) {
|
|
1120
|
+
const baseTime = createDayJS(nowTime);
|
|
1121
|
+
if (this.getStartTime().isSameOrAfter(baseTime)) {
|
|
1060
1122
|
return 0;
|
|
1061
1123
|
}
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1124
|
+
if (this.getEndTime().isSameOrBefore(baseTime)) {
|
|
1125
|
+
return 100;
|
|
1126
|
+
}
|
|
1127
|
+
const total = this.getEndTime().diff(this.getStartTime(), "s");
|
|
1128
|
+
const pass = baseTime.diff(this.getStartTime(), "s");
|
|
1129
|
+
return Math.round(pass * 100 / total);
|
|
1066
1130
|
}
|
|
1067
|
-
|
|
1068
|
-
if (this.
|
|
1069
|
-
return
|
|
1131
|
+
isEnableAwards(group) {
|
|
1132
|
+
if (!this.awards) {
|
|
1133
|
+
return false;
|
|
1070
1134
|
}
|
|
1071
|
-
|
|
1135
|
+
if (!this.awards.has(group)) {
|
|
1136
|
+
return false;
|
|
1137
|
+
}
|
|
1138
|
+
return true;
|
|
1072
1139
|
}
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
this.
|
|
1078
|
-
this.
|
|
1079
|
-
this.lastSolvedProblem = null;
|
|
1140
|
+
resetReplayTime() {
|
|
1141
|
+
this.replayStartTime = void 0;
|
|
1142
|
+
this.replayEndTime = void 0;
|
|
1143
|
+
this.replayFreezeTime = void 0;
|
|
1144
|
+
this.replayNowTime = void 0;
|
|
1145
|
+
this.replayContestStartTimestamp = void 0;
|
|
1080
1146
|
}
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
this.name = "";
|
|
1086
|
-
this.organization = "";
|
|
1087
|
-
this.group = [];
|
|
1088
|
-
this.tag = [];
|
|
1089
|
-
this.rank = 0;
|
|
1090
|
-
this.originalRank = 0;
|
|
1091
|
-
this.organizationRank = -1;
|
|
1092
|
-
this.solvedProblemNum = 0;
|
|
1093
|
-
this.attemptedProblemNum = 0;
|
|
1094
|
-
this.lastSolvedProblem = null;
|
|
1095
|
-
this.lastSolvedProblemStatistics = null;
|
|
1096
|
-
this.penalty = 0;
|
|
1097
|
-
this.problemStatistics = [];
|
|
1098
|
-
this.problemStatisticsMap = /* @__PURE__ */ new Map();
|
|
1099
|
-
this.submissions = [];
|
|
1100
|
-
this.placeChartPoints = [];
|
|
1101
|
-
this.awards = [];
|
|
1102
|
-
this.se = 0;
|
|
1103
|
-
}
|
|
1104
|
-
reset() {
|
|
1105
|
-
this.rank = 0;
|
|
1106
|
-
this.originalRank = 0;
|
|
1107
|
-
this.organizationRank = -1;
|
|
1108
|
-
this.solvedProblemNum = 0;
|
|
1109
|
-
this.attemptedProblemNum = 0;
|
|
1110
|
-
this.lastSolvedProblem = null;
|
|
1111
|
-
this.lastSolvedProblemStatistics = null;
|
|
1112
|
-
this.penalty = 0;
|
|
1113
|
-
this.problemStatistics = [];
|
|
1114
|
-
this.problemStatisticsMap = /* @__PURE__ */ new Map();
|
|
1115
|
-
this.submissions = [];
|
|
1116
|
-
this.placeChartPoints = [];
|
|
1117
|
-
this.awards = [];
|
|
1118
|
-
this.se = 0;
|
|
1119
|
-
}
|
|
1120
|
-
get penaltyToMinute() {
|
|
1121
|
-
return Math.floor(this.penalty / 60);
|
|
1122
|
-
}
|
|
1123
|
-
get isUnofficial() {
|
|
1124
|
-
return this.group.includes("unofficial");
|
|
1125
|
-
}
|
|
1126
|
-
get isGirl() {
|
|
1127
|
-
return this.group.includes("girl");
|
|
1128
|
-
}
|
|
1129
|
-
get membersToArray() {
|
|
1130
|
-
if (Array.isArray(this.members)) {
|
|
1131
|
-
return this.members;
|
|
1132
|
-
}
|
|
1133
|
-
if (typeof this.members === "string") {
|
|
1134
|
-
if (this.members.includes(", ")) {
|
|
1135
|
-
return this.members.split(", ");
|
|
1136
|
-
}
|
|
1137
|
-
if (this.members.includes("\u3001")) {
|
|
1138
|
-
return this.members.split("\u3001");
|
|
1139
|
-
}
|
|
1140
|
-
}
|
|
1141
|
-
return [];
|
|
1142
|
-
}
|
|
1143
|
-
get membersToString() {
|
|
1144
|
-
if (typeof this.members === "string") {
|
|
1145
|
-
return this.members;
|
|
1146
|
-
}
|
|
1147
|
-
return this.members?.join(", ");
|
|
1148
|
-
}
|
|
1149
|
-
get isEffectiveTeam() {
|
|
1150
|
-
return this.solvedProblemNum > 0;
|
|
1151
|
-
}
|
|
1152
|
-
get dirt() {
|
|
1153
|
-
const attemptedNum = this.attemptedProblemNum;
|
|
1154
|
-
const solvedNum = this.solvedProblemNum;
|
|
1155
|
-
return calcDirt(attemptedNum, solvedNum);
|
|
1156
|
-
}
|
|
1157
|
-
calcSE(totalTeams) {
|
|
1158
|
-
let acceptedProblemNums = 0;
|
|
1159
|
-
let total = 0;
|
|
1160
|
-
this.problemStatistics.forEach((p) => {
|
|
1161
|
-
if (p.isSolved) {
|
|
1162
|
-
acceptedProblemNums += 1;
|
|
1163
|
-
total += p.problem.statistics.acceptedNum;
|
|
1164
|
-
}
|
|
1165
|
-
});
|
|
1166
|
-
if (totalTeams === 0 || acceptedProblemNums === 0) {
|
|
1167
|
-
return 0;
|
|
1147
|
+
setReplayTime(replayStartTimestamp) {
|
|
1148
|
+
if (replayStartTimestamp === 0) {
|
|
1149
|
+
this.resetReplayTime();
|
|
1150
|
+
return;
|
|
1168
1151
|
}
|
|
1169
|
-
const
|
|
1170
|
-
|
|
1171
|
-
|
|
1152
|
+
const replayStartTime = createDayJS(replayStartTimestamp);
|
|
1153
|
+
const diff = replayStartTime.diff(this.startTime, "s");
|
|
1154
|
+
this.replayStartTime = this.startTime.add(diff, "s");
|
|
1155
|
+
this.replayEndTime = this.endTime.add(diff, "s");
|
|
1156
|
+
this.replayFreezeTime = this.freezeTime.add(diff, "s");
|
|
1157
|
+
this.replayNowTime = createDayJS();
|
|
1158
|
+
this.replayContestStartTimestamp = this.replayNowTime.diff(this.replayStartTime, "s");
|
|
1172
1159
|
}
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1160
|
+
}
|
|
1161
|
+
function createContest(contestJSON) {
|
|
1162
|
+
const c = new Contest();
|
|
1163
|
+
c.name = contestJSON.contest_name;
|
|
1164
|
+
c.startTime = createDayJS(contestJSON.start_time);
|
|
1165
|
+
c.endTime = createDayJS(contestJSON.end_time);
|
|
1166
|
+
c.totalDurationTimestamp = c.endTime.unix() - c.startTime.unix();
|
|
1167
|
+
{
|
|
1168
|
+
c.freezeTime = c.endTime;
|
|
1169
|
+
c.freezeDurationTimestamp = 0;
|
|
1170
|
+
if (contestJSON.frozen_time !== void 0 && contestJSON.frozen_time != null) {
|
|
1171
|
+
const frozenTime = Number(contestJSON.frozen_time);
|
|
1172
|
+
c.freezeTime = createDayJS(c.endTime.unix() - frozenTime);
|
|
1173
|
+
c.freezeDurationTimestamp = frozenTime;
|
|
1187
1174
|
}
|
|
1188
|
-
if (
|
|
1189
|
-
|
|
1175
|
+
if (contestJSON.freeze_time !== void 0 && contestJSON.freeze_time !== null) {
|
|
1176
|
+
c.freezeTime = createDayJS(contestJSON.freeze_time);
|
|
1177
|
+
c.freezeDurationTimestamp = c.endTime.unix() - c.freezeTime.unix();
|
|
1190
1178
|
}
|
|
1179
|
+
c.unFreezeDurationTimestamp = c.totalDurationTimestamp - c.freezeDurationTimestamp;
|
|
1191
1180
|
}
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1181
|
+
c.penalty = contestJSON.penalty;
|
|
1182
|
+
{
|
|
1183
|
+
if (contestJSON.problem_id !== void 0 && contestJSON.problem_id !== null) {
|
|
1184
|
+
c.problems = createProblemsByProblemIds(contestJSON.problem_id, contestJSON.balloon_color);
|
|
1195
1185
|
}
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
this.awards.push(award.medalType);
|
|
1199
|
-
}
|
|
1186
|
+
if (contestJSON.problems !== void 0 && contestJSON.problems !== null) {
|
|
1187
|
+
c.problems = createProblems(contestJSON.problems);
|
|
1200
1188
|
}
|
|
1189
|
+
c.problemsMap = new Map(c.problems.map((p) => [p.id, p]));
|
|
1201
1190
|
}
|
|
1202
|
-
|
|
1203
|
-
|
|
1191
|
+
if (contestJSON.status_time_display !== void 0 && contestJSON.status_time_display !== null) {
|
|
1192
|
+
c.statusTimeDisplay = {
|
|
1193
|
+
correct: Boolean(contestJSON.status_time_display.correct ?? false),
|
|
1194
|
+
incorrect: Boolean(contestJSON.status_time_display.incorrect ?? false),
|
|
1195
|
+
pending: Boolean(contestJSON.status_time_display.pending ?? false)
|
|
1196
|
+
};
|
|
1204
1197
|
}
|
|
1205
|
-
|
|
1206
|
-
|
|
1198
|
+
c.badge = contestJSON.badge;
|
|
1199
|
+
c.medal = contestJSON.medal;
|
|
1200
|
+
(() => {
|
|
1201
|
+
if (contestJSON.medal === void 0 || contestJSON.medal === null) {
|
|
1207
1202
|
return;
|
|
1208
1203
|
}
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1204
|
+
c.awards = /* @__PURE__ */ new Map();
|
|
1205
|
+
if (typeof contestJSON.medal === "string") ; else {
|
|
1206
|
+
for (const k in contestJSON.medal) {
|
|
1207
|
+
const v = contestJSON.medal[k];
|
|
1208
|
+
{
|
|
1209
|
+
const award = [];
|
|
1210
|
+
let rank = 1;
|
|
1211
|
+
const work = (key, medalType) => {
|
|
1212
|
+
if (Object.keys(v).includes(key)) {
|
|
1213
|
+
const a = new Award();
|
|
1214
|
+
a.medalType = medalType;
|
|
1215
|
+
a.minRank = rank;
|
|
1216
|
+
rank += Number(v[key]);
|
|
1217
|
+
a.maxRank = rank - 1;
|
|
1218
|
+
award.push(a);
|
|
1219
|
+
}
|
|
1220
|
+
};
|
|
1221
|
+
work("gold", MedalType.GOLD);
|
|
1222
|
+
work("silver", MedalType.SILVER);
|
|
1223
|
+
work("bronze", MedalType.BRONZE);
|
|
1224
|
+
{
|
|
1225
|
+
const a = new Award();
|
|
1226
|
+
a.medalType = MedalType.HONORABLE;
|
|
1227
|
+
a.minRank = rank;
|
|
1228
|
+
a.maxRank = 1061109567;
|
|
1229
|
+
award.push(a);
|
|
1230
|
+
}
|
|
1231
|
+
c.awards.set(k, award);
|
|
1232
|
+
}
|
|
1216
1233
|
}
|
|
1217
1234
|
}
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1235
|
+
})();
|
|
1236
|
+
c.organization = contestJSON.organization;
|
|
1237
|
+
{
|
|
1238
|
+
const g = new Group();
|
|
1239
|
+
g.names.set("en", "All");
|
|
1240
|
+
g.names.set("zh-CN", "\u6240\u6709\u961F\u4F0D");
|
|
1241
|
+
g.isDefault = true;
|
|
1242
|
+
c.group.set("all", g);
|
|
1222
1243
|
}
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
if (
|
|
1228
|
-
|
|
1244
|
+
for (const [k, v] of Object.entries(contestJSON?.group ?? {})) {
|
|
1245
|
+
let key = k;
|
|
1246
|
+
const g = new Group();
|
|
1247
|
+
g.names.set("zh-CN", v);
|
|
1248
|
+
if (k === "official") {
|
|
1249
|
+
g.names.set("en", "Official");
|
|
1229
1250
|
}
|
|
1230
|
-
if (
|
|
1231
|
-
|
|
1251
|
+
if (k === "unofficial") {
|
|
1252
|
+
g.names.set("en", "Unofficial");
|
|
1232
1253
|
}
|
|
1233
|
-
if (
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
return 1;
|
|
1254
|
+
if (k === "girl" || k === "girls") {
|
|
1255
|
+
g.names.set("en", "Girls");
|
|
1256
|
+
key = "girl";
|
|
1237
1257
|
}
|
|
1238
|
-
|
|
1258
|
+
c.group.set(key, g);
|
|
1239
1259
|
}
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
t.id = teamJSON.id ?? teamJSON.team_id ?? "";
|
|
1244
|
-
t.name = teamJSON.name ?? teamJSON.team_name ?? "";
|
|
1245
|
-
t.organization = teamJSON.organization ?? "";
|
|
1246
|
-
t.badge = teamJSON.badge;
|
|
1247
|
-
t.group = ___default.cloneDeep(teamJSON.group ?? []);
|
|
1248
|
-
t.tag = ___default.cloneDeep(teamJSON.tag ?? []);
|
|
1249
|
-
t.coach = teamJSON.coach;
|
|
1250
|
-
t.members = teamJSON.members;
|
|
1251
|
-
if (Boolean(teamJSON.official) === true) {
|
|
1252
|
-
t.group.push("official");
|
|
1260
|
+
c.banner = contestJSON.banner;
|
|
1261
|
+
if (c.banner) {
|
|
1262
|
+
c.bannerMode = contestJSON.banner_mode ?? "ALL";
|
|
1253
1263
|
}
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
t.group.push("girl");
|
|
1259
|
-
}
|
|
1260
|
-
{
|
|
1261
|
-
const tt = teamJSON;
|
|
1262
|
-
for (const key of Object.keys(tt)) {
|
|
1263
|
-
if (tt[key] === 1 || tt[key] === true) {
|
|
1264
|
-
t.group.push(key);
|
|
1265
|
-
}
|
|
1266
|
-
}
|
|
1267
|
-
}
|
|
1268
|
-
t.group = [...new Set(t.group)];
|
|
1269
|
-
t.group.sort();
|
|
1270
|
-
if (teamJSON.location) {
|
|
1271
|
-
t.location = teamJSON.location;
|
|
1272
|
-
}
|
|
1273
|
-
if (teamJSON.icpc_id) {
|
|
1274
|
-
t.icpcID = teamJSON.icpc_id;
|
|
1275
|
-
}
|
|
1276
|
-
return t;
|
|
1277
|
-
}
|
|
1278
|
-
function createTeams(teamsJSON) {
|
|
1279
|
-
if (Array.isArray(teamsJSON)) {
|
|
1280
|
-
return teamsJSON.map((t) => createTeam(t));
|
|
1281
|
-
} else {
|
|
1282
|
-
const teams = Object.entries(teamsJSON).map(
|
|
1283
|
-
([teamId, team]) => createTeam({ ...team, team_id: team.team_id ?? teamId })
|
|
1284
|
-
);
|
|
1285
|
-
return teams;
|
|
1264
|
+
c.logo = contestJSON.logo;
|
|
1265
|
+
c.boardLink = contestJSON.board_link;
|
|
1266
|
+
if (contestJSON.options) {
|
|
1267
|
+
c.options = createContestOptions(contestJSON.options);
|
|
1286
1268
|
}
|
|
1269
|
+
return c;
|
|
1287
1270
|
}
|
|
1288
1271
|
|
|
1289
|
-
|
|
1272
|
+
var __defProp$a = Object.defineProperty;
|
|
1273
|
+
var __defNormalProp$a = (obj, key, value) => key in obj ? __defProp$a(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
1274
|
+
var __publicField$a = (obj, key, value) => {
|
|
1275
|
+
__defNormalProp$a(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
1276
|
+
return value;
|
|
1277
|
+
};
|
|
1278
|
+
class ContestIndexConfig {
|
|
1290
1279
|
constructor() {
|
|
1291
|
-
this
|
|
1292
|
-
this
|
|
1293
|
-
this
|
|
1294
|
-
this
|
|
1295
|
-
this
|
|
1296
|
-
this
|
|
1297
|
-
this
|
|
1298
|
-
this
|
|
1299
|
-
this.
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
}
|
|
1307
|
-
isPending() {
|
|
1308
|
-
return isPending(this.status);
|
|
1280
|
+
__publicField$a(this, "contestName");
|
|
1281
|
+
__publicField$a(this, "startTime");
|
|
1282
|
+
__publicField$a(this, "endTime");
|
|
1283
|
+
__publicField$a(this, "freezeTime");
|
|
1284
|
+
__publicField$a(this, "totalDurationTimestamp");
|
|
1285
|
+
__publicField$a(this, "freezeDurationTimestamp");
|
|
1286
|
+
__publicField$a(this, "unFreezeDurationTimestamp");
|
|
1287
|
+
__publicField$a(this, "logo");
|
|
1288
|
+
this.contestName = "";
|
|
1289
|
+
this.startTime = createDayJS();
|
|
1290
|
+
this.endTime = createDayJS();
|
|
1291
|
+
this.freezeTime = createDayJS();
|
|
1292
|
+
this.totalDurationTimestamp = 0;
|
|
1293
|
+
this.freezeDurationTimestamp = 0;
|
|
1294
|
+
this.unFreezeDurationTimestamp = 0;
|
|
1309
1295
|
}
|
|
1310
|
-
|
|
1311
|
-
|
|
1296
|
+
}
|
|
1297
|
+
class ContestIndex {
|
|
1298
|
+
constructor() {
|
|
1299
|
+
__publicField$a(this, "contest");
|
|
1300
|
+
__publicField$a(this, "boardLink");
|
|
1301
|
+
this.contest = new Contest();
|
|
1302
|
+
this.boardLink = "";
|
|
1312
1303
|
}
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1304
|
+
}
|
|
1305
|
+
function createContestIndex(contestIndexJSON) {
|
|
1306
|
+
const c = new ContestIndex();
|
|
1307
|
+
const cjc = contestIndexJSON.config;
|
|
1308
|
+
c.contest = createContest(cjc);
|
|
1309
|
+
c.boardLink = contestIndexJSON.board_link;
|
|
1310
|
+
return c;
|
|
1311
|
+
}
|
|
1312
|
+
function createContestIndexList(contestListJSON) {
|
|
1313
|
+
const contestIndexList = [];
|
|
1314
|
+
const dfs = (contestList) => {
|
|
1315
|
+
if (Object.prototype.hasOwnProperty.call(contestList, "config")) {
|
|
1316
|
+
contestIndexList.push(createContestIndex(contestList));
|
|
1317
|
+
} else {
|
|
1318
|
+
for (const k in contestList) {
|
|
1319
|
+
dfs(contestList[k]);
|
|
1320
|
+
}
|
|
1316
1321
|
}
|
|
1317
|
-
|
|
1318
|
-
|
|
1322
|
+
};
|
|
1323
|
+
dfs(contestListJSON);
|
|
1324
|
+
contestIndexList.sort((a, b) => {
|
|
1325
|
+
if (a.contest.startTime.isBefore(b.contest.startTime)) {
|
|
1326
|
+
return 1;
|
|
1319
1327
|
}
|
|
1320
|
-
if (
|
|
1321
|
-
return
|
|
1328
|
+
if (a.contest.startTime.isAfter(b.contest.startTime)) {
|
|
1329
|
+
return -1;
|
|
1322
1330
|
}
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
get timestampToSecond() {
|
|
1326
|
-
if (this.timestampUnit === "nanosecond") {
|
|
1327
|
-
return Math.floor(this.timestamp / 1e3 / 1e3 / 1e3);
|
|
1331
|
+
if (a.contest.endTime.isBefore(b.contest.endTime)) {
|
|
1332
|
+
return 1;
|
|
1328
1333
|
}
|
|
1329
|
-
if (
|
|
1330
|
-
return
|
|
1334
|
+
if (a.contest.endTime.isAfter(b.contest.endTime)) {
|
|
1335
|
+
return -1;
|
|
1331
1336
|
}
|
|
1332
|
-
if (
|
|
1333
|
-
return
|
|
1337
|
+
if (a.contest.name < b.contest.name) {
|
|
1338
|
+
return 1;
|
|
1334
1339
|
}
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
get timestampDisplayFormatWithSecond() {
|
|
1338
|
-
const second = this.timestampToSecond;
|
|
1339
|
-
const h = Math.floor(second / 3600);
|
|
1340
|
-
const m = Math.floor(second % 3600 / 60);
|
|
1341
|
-
const s = second % 60;
|
|
1342
|
-
const f = (x) => x.toString().padStart(2, "0");
|
|
1343
|
-
const res = `${f(h)}:${f(m)}:${f(s)}`;
|
|
1344
|
-
return res;
|
|
1345
|
-
}
|
|
1346
|
-
get timestampDisplayFormatWithMilliSecond() {
|
|
1347
|
-
let res = this.timestampDisplayFormatWithSecond;
|
|
1348
|
-
if (this.timestampUnit === "millisecond") {
|
|
1349
|
-
const fl = (this.timestamp % 1e3).toString().padStart(3, "0");
|
|
1350
|
-
res += `.${fl}`;
|
|
1340
|
+
if (a.contest.name > b.contest.name) {
|
|
1341
|
+
return -1;
|
|
1351
1342
|
}
|
|
1352
|
-
return
|
|
1343
|
+
return 0;
|
|
1344
|
+
});
|
|
1345
|
+
return contestIndexList;
|
|
1346
|
+
}
|
|
1347
|
+
|
|
1348
|
+
class CodeforcesGymGhostDATConverter {
|
|
1349
|
+
constructor() {
|
|
1353
1350
|
}
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1351
|
+
convert(rank) {
|
|
1352
|
+
let res = "";
|
|
1353
|
+
res += `@contest "${rank.contest.name}"
|
|
1354
|
+
@contlen ${Math.floor(dayjs__default.duration(rank.contest.endTime.diff(rank.contest.startTime)).asMinutes())}
|
|
1355
|
+
@problems ${rank.contest.problems.length}
|
|
1356
|
+
@teams ${rank.teams.length + 100}
|
|
1357
|
+
@submissions ${rank.submissions.length}
|
|
1358
|
+
`;
|
|
1359
|
+
rank.contest.problems.forEach((p) => {
|
|
1360
|
+
res += `@p ${p.label},${p.label},20,0
|
|
1361
|
+
`;
|
|
1362
|
+
});
|
|
1363
|
+
let teamIndex = 1;
|
|
1364
|
+
const teamIdMap = /* @__PURE__ */ new Map();
|
|
1365
|
+
const submissionsIdMap = /* @__PURE__ */ new Map();
|
|
1366
|
+
rank.teams.forEach((team) => {
|
|
1367
|
+
let name = team.name;
|
|
1368
|
+
if (team.organization) {
|
|
1369
|
+
name = `${team.organization} - ${name}`;
|
|
1370
|
+
}
|
|
1371
|
+
if (team.members) {
|
|
1372
|
+
name = `${name} - ${team.membersToString}`;
|
|
1373
|
+
}
|
|
1374
|
+
res += `@t ${teamIndex},0,1,"${name}"
|
|
1375
|
+
`;
|
|
1376
|
+
teamIdMap.set(team.id, teamIndex);
|
|
1377
|
+
teamIndex++;
|
|
1378
|
+
{
|
|
1379
|
+
const mp = /* @__PURE__ */ new Map();
|
|
1380
|
+
rank.contest.problems.forEach((p) => {
|
|
1381
|
+
mp.set(p.id, 0);
|
|
1382
|
+
});
|
|
1383
|
+
submissionsIdMap.set(team.id, mp);
|
|
1384
|
+
}
|
|
1385
|
+
});
|
|
1386
|
+
for (let i = 0; i < 100; i++) {
|
|
1387
|
+
res += `@t ${teamIndex},0,1,"\u041F\u043E\u043F\u043E\u043B\u043D\u0438\u0442\u044C \u043A\u043E\u043C\u0430\u043D\u0434\u0443"
|
|
1388
|
+
`;
|
|
1389
|
+
teamIndex++;
|
|
1357
1390
|
}
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1391
|
+
rank.getSubmissions().forEach((submission) => {
|
|
1392
|
+
const teamId = submission.teamId;
|
|
1393
|
+
const problemId = submission.problemId;
|
|
1394
|
+
const problem = rank.contest.problemsMap.get(problemId);
|
|
1395
|
+
const teamIndex2 = teamIdMap.get(teamId);
|
|
1396
|
+
if (!problem) {
|
|
1397
|
+
return;
|
|
1361
1398
|
}
|
|
1362
|
-
if (!
|
|
1363
|
-
return
|
|
1399
|
+
if (!teamIndex2) {
|
|
1400
|
+
return;
|
|
1364
1401
|
}
|
|
1402
|
+
const status = this.submissionStatusToCodeforcesGymDatStatus(submission.status);
|
|
1403
|
+
submissionsIdMap.get(teamId).set(problemId, submissionsIdMap.get(teamId).get(problemId) + 1);
|
|
1404
|
+
res += `@s ${teamIndex2},${problem.label},${submissionsIdMap.get(teamId)?.get(problemId)},${submission.timestampToSecond},${status}
|
|
1405
|
+
`;
|
|
1406
|
+
});
|
|
1407
|
+
return res;
|
|
1408
|
+
}
|
|
1409
|
+
submissionStatusToCodeforcesGymDatStatus(status) {
|
|
1410
|
+
if (isAccepted(status)) {
|
|
1411
|
+
return "OK";
|
|
1365
1412
|
}
|
|
1366
|
-
if (
|
|
1367
|
-
return
|
|
1368
|
-
}
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1413
|
+
if (status === types.SubmissionStatus.WRONG_ANSWER) {
|
|
1414
|
+
return "WA";
|
|
1415
|
+
}
|
|
1416
|
+
if (status === types.SubmissionStatus.TIME_LIMIT_EXCEEDED) {
|
|
1417
|
+
return "TL";
|
|
1418
|
+
}
|
|
1419
|
+
if (status === types.SubmissionStatus.MEMORY_LIMIT_EXCEEDED) {
|
|
1420
|
+
return "ML";
|
|
1421
|
+
}
|
|
1422
|
+
if (status === types.SubmissionStatus.OUTPUT_LIMIT_EXCEEDED) {
|
|
1423
|
+
return "IL";
|
|
1424
|
+
}
|
|
1425
|
+
if (status === types.SubmissionStatus.PRESENTATION_ERROR) {
|
|
1426
|
+
return "PE";
|
|
1427
|
+
}
|
|
1428
|
+
if (status === types.SubmissionStatus.RUNTIME_ERROR) {
|
|
1429
|
+
return "RT";
|
|
1430
|
+
}
|
|
1431
|
+
if (status === types.SubmissionStatus.COMPILATION_ERROR || isNotCalculatedPenaltyStatus(status)) {
|
|
1432
|
+
return "CE";
|
|
1372
1433
|
}
|
|
1434
|
+
if (isPending(status)) {
|
|
1435
|
+
return "PD";
|
|
1436
|
+
}
|
|
1437
|
+
return "RJ";
|
|
1373
1438
|
}
|
|
1374
1439
|
}
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
s.teamId = String(submissionJSON.team_id);
|
|
1379
|
-
s.problemId = String(submissionJSON.problem_id);
|
|
1380
|
-
s.timestamp = submissionJSON.timestamp;
|
|
1381
|
-
s.status = stringToSubmissionStatus(submissionJSON.status);
|
|
1382
|
-
s.isIgnore = submissionJSON.is_ignore ?? false;
|
|
1383
|
-
if (submissionJSON.time) {
|
|
1384
|
-
s.time = submissionJSON.time;
|
|
1440
|
+
|
|
1441
|
+
class GeneralExcelConverter {
|
|
1442
|
+
constructor() {
|
|
1385
1443
|
}
|
|
1386
|
-
|
|
1387
|
-
|
|
1444
|
+
convert(oriRank) {
|
|
1445
|
+
const rank = ___default.cloneDeep(oriRank);
|
|
1446
|
+
rank.options.disableFilterTeamsByGroup();
|
|
1447
|
+
rank.options.disableFilterSubmissionByTimestamp();
|
|
1448
|
+
const workbook = XLSX__namespace.utils.book_new();
|
|
1449
|
+
for (const [k, v] of rank.contest.group) {
|
|
1450
|
+
rank.options.setGroup(k);
|
|
1451
|
+
rank.buildRank();
|
|
1452
|
+
const sheet = this.convertToSheet(rank);
|
|
1453
|
+
XLSX__namespace.utils.book_append_sheet(workbook, sheet, v.names.get(v.defaultLang));
|
|
1454
|
+
}
|
|
1455
|
+
return workbook;
|
|
1388
1456
|
}
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
return submissionsJSON.map((s, index) => createSubmission({ ...s, id: s.submission_id ?? String(index) }));
|
|
1397
|
-
} else {
|
|
1398
|
-
const submissions = Object.entries(submissionsJSON).map(
|
|
1399
|
-
([submissionId, s]) => createSubmission({ ...s, id: s.submission_id ?? submissionId })
|
|
1457
|
+
convertAndWrite(rank, filename) {
|
|
1458
|
+
return XLSX__namespace.writeFile(
|
|
1459
|
+
this.convert(rank),
|
|
1460
|
+
filename,
|
|
1461
|
+
{
|
|
1462
|
+
compression: true
|
|
1463
|
+
}
|
|
1400
1464
|
);
|
|
1401
|
-
return submissions;
|
|
1402
|
-
}
|
|
1403
|
-
}
|
|
1404
|
-
|
|
1405
|
-
class Balloon {
|
|
1406
|
-
constructor() {
|
|
1407
|
-
this.problem = new Problem();
|
|
1408
|
-
this.team = new Team();
|
|
1409
|
-
this.submission = new Submission();
|
|
1410
|
-
}
|
|
1411
|
-
get key() {
|
|
1412
|
-
return `balloon-${this.team.id}-${this.problem.id}`;
|
|
1413
|
-
}
|
|
1414
|
-
static compare(lhs, rhs) {
|
|
1415
|
-
return Submission.compare(lhs.submission, rhs.submission);
|
|
1416
|
-
}
|
|
1417
|
-
}
|
|
1418
|
-
|
|
1419
|
-
var GiantsType = /* @__PURE__ */ ((GiantsType2) => {
|
|
1420
|
-
GiantsType2[GiantsType2["BLUE"] = 0] = "BLUE";
|
|
1421
|
-
GiantsType2[GiantsType2["RED"] = 1] = "RED";
|
|
1422
|
-
return GiantsType2;
|
|
1423
|
-
})(GiantsType || {});
|
|
1424
|
-
class Giants {
|
|
1425
|
-
constructor(type = 0 /* BLUE */) {
|
|
1426
|
-
this.type = type;
|
|
1427
|
-
this.name = `${type === 0 /* BLUE */ ? "Blue" : "Red"} Team`;
|
|
1428
|
-
this.teams = [];
|
|
1429
|
-
this.filterOrganizations = [];
|
|
1430
|
-
this.filterOrganizationMap = /* @__PURE__ */ new Map();
|
|
1431
|
-
this.filterTeams = [];
|
|
1432
|
-
this.filterTeamMap = /* @__PURE__ */ new Map();
|
|
1433
|
-
}
|
|
1434
|
-
setFilterOrganizations(filterOrganizations) {
|
|
1435
|
-
const m = /* @__PURE__ */ new Map();
|
|
1436
|
-
filterOrganizations.forEach((item) => {
|
|
1437
|
-
m.set(item.value, item);
|
|
1438
|
-
});
|
|
1439
|
-
this.filterOrganizations = filterOrganizations;
|
|
1440
|
-
this.filterOrganizationMap = m;
|
|
1441
|
-
}
|
|
1442
|
-
setFilterTeams(filterTeams) {
|
|
1443
|
-
const m = /* @__PURE__ */ new Map();
|
|
1444
|
-
filterTeams.forEach((item) => {
|
|
1445
|
-
m.set(item.value, item);
|
|
1446
|
-
});
|
|
1447
|
-
this.filterTeams = filterTeams;
|
|
1448
|
-
this.filterTeamMap = m;
|
|
1449
|
-
}
|
|
1450
|
-
refreshName() {
|
|
1451
|
-
if (this.filterOrganizations.length > 0) {
|
|
1452
|
-
this.name = this.filterOrganizations[0].text;
|
|
1453
|
-
} else {
|
|
1454
|
-
this.name = `${this.type === 0 /* BLUE */ ? "Blue" : "Red"} Team`;
|
|
1455
|
-
}
|
|
1456
|
-
return this.name;
|
|
1457
|
-
}
|
|
1458
|
-
get totalSolvedProblemNum() {
|
|
1459
|
-
let total = 0;
|
|
1460
|
-
this.teams.forEach((team) => {
|
|
1461
|
-
total += team.solvedProblemNum;
|
|
1462
|
-
});
|
|
1463
|
-
return total;
|
|
1464
1465
|
}
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
const two = (a) => {
|
|
1475
|
-
if (a < 10) {
|
|
1476
|
-
return `0${a}`;
|
|
1466
|
+
convertToSheet(rank) {
|
|
1467
|
+
const aoa = this.convertToAoa(rank);
|
|
1468
|
+
const sheet = XLSX__namespace.utils.aoa_to_sheet(aoa);
|
|
1469
|
+
const cols = [];
|
|
1470
|
+
const head = aoa[1];
|
|
1471
|
+
for (let j = 0; j < head.length; j++) {
|
|
1472
|
+
let wch = 10;
|
|
1473
|
+
for (let i = 1; i < aoa.length; i++) {
|
|
1474
|
+
wch = Math.max(wch, stringWidth__default(aoa[i][j]) + 2);
|
|
1477
1475
|
}
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
const m = Math.floor(penalty % 60);
|
|
1482
|
-
return [two(h), two(m)].join(":");
|
|
1483
|
-
}
|
|
1484
|
-
toJSON() {
|
|
1485
|
-
return {
|
|
1486
|
-
type: this.type,
|
|
1487
|
-
name: this.name,
|
|
1488
|
-
filterOrganizations: this.filterOrganizations,
|
|
1489
|
-
filterTeams: this.filterTeams
|
|
1490
|
-
};
|
|
1491
|
-
}
|
|
1492
|
-
}
|
|
1493
|
-
class BattleOfGiants {
|
|
1494
|
-
constructor() {
|
|
1495
|
-
this.enable = false;
|
|
1496
|
-
this.topX = 5;
|
|
1497
|
-
this.equalTeams = true;
|
|
1498
|
-
this.persist = false;
|
|
1499
|
-
this.blueTeam = new Giants(0 /* BLUE */);
|
|
1500
|
-
this.redTeam = new Giants(1 /* RED */);
|
|
1501
|
-
}
|
|
1502
|
-
ToBase64() {
|
|
1503
|
-
return jsBase64.Base64.encode(JSON.stringify(this));
|
|
1504
|
-
}
|
|
1505
|
-
FromBase64(base64) {
|
|
1506
|
-
if (base64.length === 0) {
|
|
1507
|
-
return;
|
|
1476
|
+
cols.push({
|
|
1477
|
+
wch
|
|
1478
|
+
});
|
|
1508
1479
|
}
|
|
1509
|
-
|
|
1510
|
-
|
|
1480
|
+
sheet["!cols"] = cols;
|
|
1481
|
+
{
|
|
1482
|
+
const mergeRange = { s: { r: 0, c: 0 }, e: { r: 0, c: head.length - 1 } };
|
|
1483
|
+
const merges = [{ s: mergeRange.s, e: mergeRange.e }];
|
|
1484
|
+
sheet["!merges"] = merges;
|
|
1511
1485
|
}
|
|
1512
|
-
const
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
this.blueTeam = new Giants(0 /* BLUE */);
|
|
1518
|
-
this.blueTeam.name = j.blueTeam.name;
|
|
1519
|
-
this.blueTeam.setFilterOrganizations(j.blueTeam.filterOrganizations);
|
|
1520
|
-
this.blueTeam.setFilterTeams(j.blueTeam.filterTeams);
|
|
1521
|
-
this.redTeam = new Giants(1 /* RED */);
|
|
1522
|
-
this.redTeam.name = j.redTeam.name;
|
|
1523
|
-
this.redTeam.setFilterOrganizations(j.redTeam.filterOrganizations);
|
|
1524
|
-
this.redTeam.setFilterTeams(j.redTeam.filterTeams);
|
|
1525
|
-
}
|
|
1526
|
-
}
|
|
1527
|
-
|
|
1528
|
-
class Group {
|
|
1529
|
-
constructor() {
|
|
1530
|
-
this.names = /* @__PURE__ */ new Map();
|
|
1531
|
-
this.defaultLang = "zh-CN";
|
|
1532
|
-
this.isDefault = false;
|
|
1533
|
-
}
|
|
1534
|
-
}
|
|
1535
|
-
|
|
1536
|
-
class ContestOptions {
|
|
1537
|
-
constructor() {
|
|
1538
|
-
this.calculationOfPenalty = "in_minutes";
|
|
1539
|
-
this.submissionTimestampUnit = "second";
|
|
1540
|
-
this.submissionHasTimeField = false;
|
|
1541
|
-
this.submissionHasLanguageField = false;
|
|
1542
|
-
this.submissionEnableActionField = false;
|
|
1543
|
-
}
|
|
1544
|
-
}
|
|
1545
|
-
function createContestOptions(contestOptionsJSON = {}) {
|
|
1546
|
-
const j = contestOptionsJSON;
|
|
1547
|
-
const o = new ContestOptions();
|
|
1548
|
-
if (j.calculation_of_penalty) {
|
|
1549
|
-
o.calculationOfPenalty = j.calculation_of_penalty;
|
|
1550
|
-
}
|
|
1551
|
-
if (j.submission_timestamp_unit) {
|
|
1552
|
-
o.submissionTimestampUnit = j.submission_timestamp_unit;
|
|
1553
|
-
}
|
|
1554
|
-
if (j.submission_has_reaction) {
|
|
1555
|
-
o.submissionEnableActionField = j.submission_has_reaction;
|
|
1556
|
-
}
|
|
1557
|
-
return o;
|
|
1558
|
-
}
|
|
1559
|
-
|
|
1560
|
-
class Contest {
|
|
1561
|
-
constructor() {
|
|
1562
|
-
this.id = "";
|
|
1563
|
-
this.name = "";
|
|
1564
|
-
this.startTime = createDayJS();
|
|
1565
|
-
this.endTime = createDayJS();
|
|
1566
|
-
this.freezeTime = createDayJS();
|
|
1567
|
-
this.totalDurationTimestamp = 0;
|
|
1568
|
-
this.freezeDurationTimestamp = 0;
|
|
1569
|
-
this.unFreezeDurationTimestamp = 0;
|
|
1570
|
-
this.penalty = 20 * 60;
|
|
1571
|
-
this.problems = [];
|
|
1572
|
-
this.problemsMap = /* @__PURE__ */ new Map();
|
|
1573
|
-
this.statusTimeDisplay = {
|
|
1574
|
-
correct: true,
|
|
1575
|
-
incorrect: true,
|
|
1576
|
-
pending: true
|
|
1486
|
+
const font = {
|
|
1487
|
+
name: "Arial Unicode MS",
|
|
1488
|
+
bold: false,
|
|
1489
|
+
italic: false,
|
|
1490
|
+
sz: 12
|
|
1577
1491
|
};
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
return types.ContestState.FINISHED;
|
|
1601
|
-
}
|
|
1602
|
-
if (now.isSameOrAfter(this.getFreezeTime())) {
|
|
1603
|
-
return types.ContestState.FROZEN;
|
|
1604
|
-
}
|
|
1605
|
-
return types.ContestState.RUNNING;
|
|
1606
|
-
}
|
|
1607
|
-
getContestPendingTime(nowTime) {
|
|
1608
|
-
let baseTime = createDayJS(nowTime);
|
|
1609
|
-
if (baseTime.isAfter(this.getStartTime())) {
|
|
1610
|
-
baseTime = this.getStartTime();
|
|
1611
|
-
}
|
|
1612
|
-
return getTimeDiff(Math.floor(dayjs__default.duration(this.getStartTime().diff(baseTime)).asSeconds()));
|
|
1613
|
-
}
|
|
1614
|
-
getContestElapsedTime(nowTime) {
|
|
1615
|
-
let baseTime = createDayJS(nowTime);
|
|
1616
|
-
if (baseTime.isAfter(this.getEndTime())) {
|
|
1617
|
-
baseTime = this.getEndTime();
|
|
1618
|
-
}
|
|
1619
|
-
if (baseTime.isBefore(this.getStartTime())) {
|
|
1620
|
-
baseTime = this.getStartTime();
|
|
1621
|
-
}
|
|
1622
|
-
return getTimeDiff(Math.floor(dayjs__default.duration(baseTime.diff(this.getStartTime())).asSeconds()));
|
|
1623
|
-
}
|
|
1624
|
-
getContestRemainingTime(nowTime) {
|
|
1625
|
-
let baseTime = createDayJS(nowTime);
|
|
1626
|
-
if (baseTime.isAfter(this.getEndTime())) {
|
|
1627
|
-
baseTime = this.getEndTime();
|
|
1628
|
-
}
|
|
1629
|
-
if (baseTime.isBefore(this.getStartTime())) {
|
|
1630
|
-
baseTime = this.getStartTime();
|
|
1631
|
-
}
|
|
1632
|
-
return getTimeDiff(Math.floor(dayjs__default.duration(this.getEndTime().diff(baseTime)).asSeconds()));
|
|
1633
|
-
}
|
|
1634
|
-
getContestProgressRatio(nowTime) {
|
|
1635
|
-
const baseTime = createDayJS(nowTime);
|
|
1636
|
-
if (this.getStartTime().isSameOrAfter(baseTime)) {
|
|
1637
|
-
return 0;
|
|
1638
|
-
}
|
|
1639
|
-
if (this.getEndTime().isSameOrBefore(baseTime)) {
|
|
1640
|
-
return 100;
|
|
1641
|
-
}
|
|
1642
|
-
const total = this.getEndTime().diff(this.getStartTime(), "s");
|
|
1643
|
-
const pass = baseTime.diff(this.getStartTime(), "s");
|
|
1644
|
-
return Math.round(pass * 100 / total);
|
|
1645
|
-
}
|
|
1646
|
-
isEnableAwards(group) {
|
|
1647
|
-
if (!this.awards) {
|
|
1648
|
-
return false;
|
|
1649
|
-
}
|
|
1650
|
-
if (!this.awards.has(group)) {
|
|
1651
|
-
return false;
|
|
1652
|
-
}
|
|
1653
|
-
return true;
|
|
1654
|
-
}
|
|
1655
|
-
resetReplayTime() {
|
|
1656
|
-
this.replayStartTime = void 0;
|
|
1657
|
-
this.replayEndTime = void 0;
|
|
1658
|
-
this.replayFreezeTime = void 0;
|
|
1659
|
-
this.replayNowTime = void 0;
|
|
1660
|
-
this.replayContestStartTimestamp = void 0;
|
|
1661
|
-
}
|
|
1662
|
-
setReplayTime(replayStartTimestamp) {
|
|
1663
|
-
if (replayStartTimestamp === 0) {
|
|
1664
|
-
this.resetReplayTime();
|
|
1665
|
-
return;
|
|
1666
|
-
}
|
|
1667
|
-
const replayStartTime = createDayJS(replayStartTimestamp);
|
|
1668
|
-
const diff = replayStartTime.diff(this.startTime, "s");
|
|
1669
|
-
this.replayStartTime = this.startTime.add(diff, "s");
|
|
1670
|
-
this.replayEndTime = this.endTime.add(diff, "s");
|
|
1671
|
-
this.replayFreezeTime = this.freezeTime.add(diff, "s");
|
|
1672
|
-
this.replayNowTime = createDayJS();
|
|
1673
|
-
this.replayContestStartTimestamp = this.replayNowTime.diff(this.replayStartTime, "s");
|
|
1674
|
-
}
|
|
1675
|
-
}
|
|
1676
|
-
function createContest(contestJSON) {
|
|
1677
|
-
const c = new Contest();
|
|
1678
|
-
c.name = contestJSON.contest_name;
|
|
1679
|
-
c.startTime = createDayJS(contestJSON.start_time);
|
|
1680
|
-
c.endTime = createDayJS(contestJSON.end_time);
|
|
1681
|
-
c.totalDurationTimestamp = c.endTime.unix() - c.startTime.unix();
|
|
1682
|
-
{
|
|
1683
|
-
c.freezeTime = c.endTime;
|
|
1684
|
-
c.freezeDurationTimestamp = 0;
|
|
1685
|
-
if (contestJSON.frozen_time !== void 0 && contestJSON.frozen_time != null) {
|
|
1686
|
-
const frozenTime = Number(contestJSON.frozen_time);
|
|
1687
|
-
c.freezeTime = createDayJS(c.endTime.unix() - frozenTime);
|
|
1688
|
-
c.freezeDurationTimestamp = frozenTime;
|
|
1492
|
+
const borderStyle = {
|
|
1493
|
+
style: "thin"
|
|
1494
|
+
};
|
|
1495
|
+
const cellStyle = {
|
|
1496
|
+
alignment: {
|
|
1497
|
+
vertical: "center",
|
|
1498
|
+
horizontal: "center"
|
|
1499
|
+
},
|
|
1500
|
+
border: {
|
|
1501
|
+
top: borderStyle,
|
|
1502
|
+
bottom: borderStyle,
|
|
1503
|
+
left: borderStyle,
|
|
1504
|
+
right: borderStyle
|
|
1505
|
+
},
|
|
1506
|
+
font
|
|
1507
|
+
};
|
|
1508
|
+
for (let i = 1; i < aoa.length; i++) {
|
|
1509
|
+
for (let j = 0; j < aoa[i].length; j++) {
|
|
1510
|
+
const cellAddress = XLSX__namespace.utils.encode_cell({ r: i, c: j });
|
|
1511
|
+
const cell = sheet[cellAddress];
|
|
1512
|
+
cell.s = cellStyle;
|
|
1513
|
+
}
|
|
1689
1514
|
}
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1515
|
+
{
|
|
1516
|
+
const cellAddress = XLSX__namespace.utils.encode_cell({ r: 0, c: 0 });
|
|
1517
|
+
const cell = sheet[cellAddress];
|
|
1518
|
+
const titleStyle = ___default.cloneDeep(cellStyle);
|
|
1519
|
+
titleStyle.font.sz = 28;
|
|
1520
|
+
titleStyle.font.bold = true;
|
|
1521
|
+
cell.s = titleStyle;
|
|
1693
1522
|
}
|
|
1694
|
-
|
|
1523
|
+
return sheet;
|
|
1695
1524
|
}
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1525
|
+
convertToAoa(rank) {
|
|
1526
|
+
const aoa = [];
|
|
1527
|
+
const enableAwards = rank.contest.isEnableAwards(rank.options.group);
|
|
1528
|
+
const enableMembers = (Array.isArray(rank.teams) && rank.teams[0]?.members) ?? false;
|
|
1529
|
+
const enableCoach = rank.teams[0]?.coach ?? false;
|
|
1530
|
+
{
|
|
1531
|
+
aoa.push([rank.contest.name]);
|
|
1703
1532
|
}
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1533
|
+
{
|
|
1534
|
+
const head = [];
|
|
1535
|
+
head.push("Rank");
|
|
1536
|
+
if (rank.contest.organization) {
|
|
1537
|
+
head.push(`${rank.contest.organization} Rank`);
|
|
1538
|
+
head.push(rank.contest.organization);
|
|
1539
|
+
}
|
|
1540
|
+
head.push("Team", "Solved", "Penalty", ...rank.contest.problems.map((p) => p.label), "Dirt");
|
|
1541
|
+
if (enableAwards) {
|
|
1542
|
+
head.push("Medal");
|
|
1543
|
+
}
|
|
1544
|
+
if (enableMembers) {
|
|
1545
|
+
head.push("Member1", "Member2", "Member3");
|
|
1546
|
+
}
|
|
1547
|
+
if (enableCoach) {
|
|
1548
|
+
head.push("Coach");
|
|
1549
|
+
}
|
|
1550
|
+
head.push("Unofficial");
|
|
1551
|
+
head.push("Girl");
|
|
1552
|
+
aoa.push(head);
|
|
1718
1553
|
}
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
{
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
if (Object.keys(v).includes(key)) {
|
|
1728
|
-
const a = new Award();
|
|
1729
|
-
a.medalType = medalType;
|
|
1730
|
-
a.minRank = rank;
|
|
1731
|
-
rank += Number(v[key]);
|
|
1732
|
-
a.maxRank = rank - 1;
|
|
1733
|
-
award.push(a);
|
|
1734
|
-
}
|
|
1735
|
-
};
|
|
1736
|
-
work("gold", MedalType.GOLD);
|
|
1737
|
-
work("silver", MedalType.SILVER);
|
|
1738
|
-
work("bronze", MedalType.BRONZE);
|
|
1739
|
-
{
|
|
1740
|
-
const a = new Award();
|
|
1741
|
-
a.medalType = MedalType.HONORABLE;
|
|
1742
|
-
a.minRank = rank;
|
|
1743
|
-
a.maxRank = 1061109567;
|
|
1744
|
-
award.push(a);
|
|
1745
|
-
}
|
|
1746
|
-
c.awards.set(k, award);
|
|
1554
|
+
for (const team of rank.teams) {
|
|
1555
|
+
const arr = [];
|
|
1556
|
+
arr.push(team.rank.toString());
|
|
1557
|
+
if (team.organization) {
|
|
1558
|
+
if (team.organizationRank !== -1) {
|
|
1559
|
+
arr.push(team.organizationRank.toString());
|
|
1560
|
+
} else {
|
|
1561
|
+
arr.push("");
|
|
1747
1562
|
}
|
|
1563
|
+
arr.push(team.organization);
|
|
1748
1564
|
}
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1565
|
+
arr.push(team.name, team.solvedProblemNum.toString(), team.penaltyToMinute.toString());
|
|
1566
|
+
for (const p of team.problemStatistics) {
|
|
1567
|
+
if (p.isUnSubmitted) {
|
|
1568
|
+
arr.push("-");
|
|
1569
|
+
}
|
|
1570
|
+
if (p.isSolved) {
|
|
1571
|
+
arr.push(`+${p.totalCount}(${p.solvedTimestampToMinute})`);
|
|
1572
|
+
}
|
|
1573
|
+
if (p.isWrongAnswer) {
|
|
1574
|
+
arr.push(`-${p.failedCount}`);
|
|
1575
|
+
}
|
|
1576
|
+
if (p.isPending) {
|
|
1577
|
+
arr.push(`? ${p.failedCount} + ${p.pendingCount}`);
|
|
1578
|
+
}
|
|
1579
|
+
}
|
|
1580
|
+
arr.push(`${team.dirt}%`);
|
|
1581
|
+
if (enableAwards) {
|
|
1582
|
+
const medals = team.awards.filter((a) => isValidMedalType(a)).map((a) => a.toString());
|
|
1583
|
+
arr.push(medals.join(", "));
|
|
1584
|
+
}
|
|
1585
|
+
if (enableMembers) {
|
|
1586
|
+
const members = team.members;
|
|
1587
|
+
if (Array.isArray(members)) {
|
|
1588
|
+
arr.push(members[0] ?? "");
|
|
1589
|
+
arr.push(members[1] ?? "");
|
|
1590
|
+
arr.push(members[2] ?? "");
|
|
1591
|
+
} else {
|
|
1592
|
+
arr.push("", "", "");
|
|
1593
|
+
}
|
|
1594
|
+
}
|
|
1595
|
+
if (enableCoach) {
|
|
1596
|
+
if (typeof team.coach === "string") {
|
|
1597
|
+
arr.push(team.coach ?? "");
|
|
1598
|
+
} else {
|
|
1599
|
+
arr.push("");
|
|
1600
|
+
}
|
|
1601
|
+
}
|
|
1602
|
+
arr.push(team.isUnofficial ? "Y" : "N");
|
|
1603
|
+
arr.push(team.isGirl ? "Y" : "N");
|
|
1604
|
+
aoa.push(arr);
|
|
1605
|
+
}
|
|
1606
|
+
return aoa;
|
|
1783
1607
|
}
|
|
1784
|
-
return c;
|
|
1785
1608
|
}
|
|
1786
1609
|
|
|
1787
|
-
class
|
|
1788
|
-
constructor() {
|
|
1789
|
-
this.contestName = "";
|
|
1790
|
-
this.startTime = createDayJS();
|
|
1791
|
-
this.endTime = createDayJS();
|
|
1792
|
-
this.freezeTime = createDayJS();
|
|
1793
|
-
this.totalDurationTimestamp = 0;
|
|
1794
|
-
this.freezeDurationTimestamp = 0;
|
|
1795
|
-
this.unFreezeDurationTimestamp = 0;
|
|
1796
|
-
}
|
|
1797
|
-
}
|
|
1798
|
-
class ContestIndex {
|
|
1610
|
+
class ICPCStandingsCsvConverter {
|
|
1799
1611
|
constructor() {
|
|
1800
|
-
this.contest = new Contest();
|
|
1801
|
-
this.boardLink = "";
|
|
1802
1612
|
}
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
if (a.contest.startTime.isBefore(b.contest.startTime)) {
|
|
1825
|
-
return 1;
|
|
1826
|
-
}
|
|
1827
|
-
if (a.contest.startTime.isAfter(b.contest.startTime)) {
|
|
1828
|
-
return -1;
|
|
1829
|
-
}
|
|
1830
|
-
if (a.contest.endTime.isBefore(b.contest.endTime)) {
|
|
1831
|
-
return 1;
|
|
1832
|
-
}
|
|
1833
|
-
if (a.contest.endTime.isAfter(b.contest.endTime)) {
|
|
1834
|
-
return -1;
|
|
1613
|
+
convert(oriRank) {
|
|
1614
|
+
const rank = ___default.cloneDeep(oriRank);
|
|
1615
|
+
rank.options.disableFilterTeamsByGroup();
|
|
1616
|
+
rank.options.disableFilterSubmissionByTimestamp();
|
|
1617
|
+
rank.options.setGroup("official");
|
|
1618
|
+
rank.buildRank();
|
|
1619
|
+
const resList = [];
|
|
1620
|
+
for (const team of rank.teams) {
|
|
1621
|
+
const res = {
|
|
1622
|
+
teamId: team.icpcID ?? "",
|
|
1623
|
+
rank: team.rank,
|
|
1624
|
+
medalCitation: this.getMedalCitation(team),
|
|
1625
|
+
problemsSolved: team.solvedProblemNum,
|
|
1626
|
+
totalTime: team.penaltyToMinute,
|
|
1627
|
+
lastProblemTime: team.lastSolvedProblemStatistics?.solvedTimestampToMinute ?? 0,
|
|
1628
|
+
siteCitation: rank.contest.name,
|
|
1629
|
+
citation: ordinal__default(team.rank),
|
|
1630
|
+
teamName: team.name,
|
|
1631
|
+
institution: team.organization
|
|
1632
|
+
};
|
|
1633
|
+
resList.push(res);
|
|
1835
1634
|
}
|
|
1836
|
-
|
|
1837
|
-
|
|
1635
|
+
const csv = Papa__default.unparse(resList);
|
|
1636
|
+
return csv;
|
|
1637
|
+
}
|
|
1638
|
+
getMedalCitation(team) {
|
|
1639
|
+
if (team.solvedProblemNum === 0) {
|
|
1640
|
+
return "";
|
|
1838
1641
|
}
|
|
1839
|
-
|
|
1840
|
-
|
|
1642
|
+
const medals = team.awards.filter((a) => isValidMedalType(a)).map((a) => a.toString());
|
|
1643
|
+
if (medals.length === 1) {
|
|
1644
|
+
const medal = medals[0];
|
|
1645
|
+
if (medal === "Gold") {
|
|
1646
|
+
return "Gold Medal";
|
|
1647
|
+
}
|
|
1648
|
+
if (medal === "Silver") {
|
|
1649
|
+
return "Silver Medal";
|
|
1650
|
+
}
|
|
1651
|
+
if (medal === "Bronze") {
|
|
1652
|
+
return "Bronze Medal";
|
|
1653
|
+
}
|
|
1654
|
+
if (medal === "Honorable") {
|
|
1655
|
+
return "Honorable Mention";
|
|
1656
|
+
}
|
|
1841
1657
|
}
|
|
1842
|
-
return
|
|
1843
|
-
}
|
|
1844
|
-
return contestIndexList;
|
|
1658
|
+
return "";
|
|
1659
|
+
}
|
|
1845
1660
|
}
|
|
1846
1661
|
|
|
1847
1662
|
function getImageSource(image, asset_host) {
|
|
@@ -1860,8 +1675,56 @@ function getImageSource(image, asset_host) {
|
|
|
1860
1675
|
return "";
|
|
1861
1676
|
}
|
|
1862
1677
|
|
|
1678
|
+
var __defProp$9 = Object.defineProperty;
|
|
1679
|
+
var __defNormalProp$9 = (obj, key, value) => key in obj ? __defProp$9(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
1680
|
+
var __publicField$9 = (obj, key, value) => {
|
|
1681
|
+
__defNormalProp$9(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
1682
|
+
return value;
|
|
1683
|
+
};
|
|
1684
|
+
class Person {
|
|
1685
|
+
constructor(name = "") {
|
|
1686
|
+
__publicField$9(this, "name");
|
|
1687
|
+
this.name = name;
|
|
1688
|
+
}
|
|
1689
|
+
toJSON() {
|
|
1690
|
+
return {
|
|
1691
|
+
name: this.name
|
|
1692
|
+
};
|
|
1693
|
+
}
|
|
1694
|
+
static fromJSON(iPerson) {
|
|
1695
|
+
if (typeof iPerson === "string") {
|
|
1696
|
+
iPerson = JSON.parse(iPerson);
|
|
1697
|
+
}
|
|
1698
|
+
const person = new Person();
|
|
1699
|
+
person.name = iPerson.name;
|
|
1700
|
+
return person;
|
|
1701
|
+
}
|
|
1702
|
+
}
|
|
1703
|
+
function createPersons(iPersons) {
|
|
1704
|
+
if (typeof iPersons === "string") {
|
|
1705
|
+
for (const c of " ,\u3001|") {
|
|
1706
|
+
if (iPersons.includes(c)) {
|
|
1707
|
+
return iPersons.split(c).map((name) => new Person(name));
|
|
1708
|
+
}
|
|
1709
|
+
}
|
|
1710
|
+
return [new Person(iPersons)];
|
|
1711
|
+
}
|
|
1712
|
+
return iPersons.map((name) => new Person(name));
|
|
1713
|
+
}
|
|
1714
|
+
|
|
1715
|
+
var __defProp$8 = Object.defineProperty;
|
|
1716
|
+
var __defNormalProp$8 = (obj, key, value) => key in obj ? __defProp$8(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
1717
|
+
var __publicField$8 = (obj, key, value) => {
|
|
1718
|
+
__defNormalProp$8(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
1719
|
+
return value;
|
|
1720
|
+
};
|
|
1863
1721
|
class RankStatistics {
|
|
1864
1722
|
constructor() {
|
|
1723
|
+
__publicField$8(this, "teamSolvedNum");
|
|
1724
|
+
__publicField$8(this, "teamSolvedNumIndex");
|
|
1725
|
+
__publicField$8(this, "maxSolvedProblems");
|
|
1726
|
+
__publicField$8(this, "effectiveTeamNum");
|
|
1727
|
+
__publicField$8(this, "totalTeamNum");
|
|
1865
1728
|
this.teamSolvedNum = [];
|
|
1866
1729
|
this.teamSolvedNumIndex = [];
|
|
1867
1730
|
this.maxSolvedProblems = 0;
|
|
@@ -1880,8 +1743,25 @@ class RankStatistics {
|
|
|
1880
1743
|
}
|
|
1881
1744
|
}
|
|
1882
1745
|
|
|
1746
|
+
var __defProp$7 = Object.defineProperty;
|
|
1747
|
+
var __defNormalProp$7 = (obj, key, value) => key in obj ? __defProp$7(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
1748
|
+
var __publicField$7 = (obj, key, value) => {
|
|
1749
|
+
__defNormalProp$7(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
1750
|
+
return value;
|
|
1751
|
+
};
|
|
1883
1752
|
class RankOptions {
|
|
1884
1753
|
constructor() {
|
|
1754
|
+
__publicField$7(this, "enableFilterSubmissionsByTimestamp");
|
|
1755
|
+
__publicField$7(this, "width");
|
|
1756
|
+
__publicField$7(this, "timestamp");
|
|
1757
|
+
__publicField$7(this, "enableFilterTeamsByGroup");
|
|
1758
|
+
__publicField$7(this, "group");
|
|
1759
|
+
__publicField$7(this, "filterOrganizations");
|
|
1760
|
+
__publicField$7(this, "filterOrganizationMap");
|
|
1761
|
+
__publicField$7(this, "filterTeams");
|
|
1762
|
+
__publicField$7(this, "filterTeamMap");
|
|
1763
|
+
__publicField$7(this, "enableAnimatedSubmissions");
|
|
1764
|
+
__publicField$7(this, "battleOfGiants");
|
|
1885
1765
|
this.enableFilterSubmissionsByTimestamp = false;
|
|
1886
1766
|
this.width = 0;
|
|
1887
1767
|
this.timestamp = 0;
|
|
@@ -1963,6 +1843,18 @@ class RankOptions {
|
|
|
1963
1843
|
}
|
|
1964
1844
|
class Rank {
|
|
1965
1845
|
constructor(contest, teams, submissions) {
|
|
1846
|
+
__publicField$7(this, "contest");
|
|
1847
|
+
__publicField$7(this, "teams");
|
|
1848
|
+
__publicField$7(this, "teamsMap");
|
|
1849
|
+
__publicField$7(this, "submissions");
|
|
1850
|
+
__publicField$7(this, "submissionsMap");
|
|
1851
|
+
__publicField$7(this, "organizations");
|
|
1852
|
+
__publicField$7(this, "originTeams");
|
|
1853
|
+
__publicField$7(this, "rankStatistics");
|
|
1854
|
+
__publicField$7(this, "options");
|
|
1855
|
+
__publicField$7(this, "balloons");
|
|
1856
|
+
__publicField$7(this, "languages");
|
|
1857
|
+
__publicField$7(this, "statuses");
|
|
1966
1858
|
this.contest = contest;
|
|
1967
1859
|
this.teams = ___default.cloneDeep(teams);
|
|
1968
1860
|
this.teamsMap = new Map(this.teams.map((t) => [t.id, t]));
|
|
@@ -2040,8 +1932,8 @@ class Rank {
|
|
|
2040
1932
|
);
|
|
2041
1933
|
(() => {
|
|
2042
1934
|
this.rankStatistics.reset();
|
|
2043
|
-
this.rankStatistics.teamSolvedNum = Array(this.contest.problems.length + 1).fill(0);
|
|
2044
|
-
this.rankStatistics.teamSolvedNumIndex = Array(this.contest.problems.length + 1).fill(0);
|
|
1935
|
+
this.rankStatistics.teamSolvedNum = Array.from({ length: this.contest.problems.length + 1 }).fill(0);
|
|
1936
|
+
this.rankStatistics.teamSolvedNumIndex = Array.from({ length: this.contest.problems.length + 1 }).fill(0);
|
|
2045
1937
|
})();
|
|
2046
1938
|
let preSubmissionTimestampToMinute = 0;
|
|
2047
1939
|
const allSubmissions = this.getSubmissions();
|
|
@@ -2141,178 +2033,583 @@ class Rank {
|
|
|
2141
2033
|
teamSolvedNumIndex[i] = current;
|
|
2142
2034
|
}
|
|
2143
2035
|
}
|
|
2144
|
-
if (this.teams.length > 0) {
|
|
2145
|
-
this.rankStatistics.maxSolvedProblems = this.teams[0].solvedProblemNum;
|
|
2036
|
+
if (this.teams.length > 0) {
|
|
2037
|
+
this.rankStatistics.maxSolvedProblems = this.teams[0].solvedProblemNum;
|
|
2038
|
+
}
|
|
2039
|
+
})();
|
|
2040
|
+
return this;
|
|
2041
|
+
}
|
|
2042
|
+
buildTeamRank() {
|
|
2043
|
+
let rank = 1;
|
|
2044
|
+
let originalRank = 1;
|
|
2045
|
+
let preTeam = null;
|
|
2046
|
+
for (const t of this.teams) {
|
|
2047
|
+
t.rank = rank++;
|
|
2048
|
+
t.originalRank = originalRank++;
|
|
2049
|
+
if (preTeam !== null) {
|
|
2050
|
+
if (t.isEqualRank(preTeam)) {
|
|
2051
|
+
t.rank = preTeam.rank;
|
|
2052
|
+
}
|
|
2053
|
+
}
|
|
2054
|
+
preTeam = t;
|
|
2055
|
+
}
|
|
2056
|
+
}
|
|
2057
|
+
buildOrgRank() {
|
|
2058
|
+
if (!this.contest.organization) {
|
|
2059
|
+
return;
|
|
2060
|
+
}
|
|
2061
|
+
let rank = 1;
|
|
2062
|
+
let preTeam = null;
|
|
2063
|
+
const se = /* @__PURE__ */ new Set();
|
|
2064
|
+
for (const t of this.teams) {
|
|
2065
|
+
const org = t.organization;
|
|
2066
|
+
if (se.has(org)) {
|
|
2067
|
+
continue;
|
|
2068
|
+
}
|
|
2069
|
+
se.add(org);
|
|
2070
|
+
t.organizationRank = rank++;
|
|
2071
|
+
if (preTeam !== null) {
|
|
2072
|
+
if (t.isEqualRank(preTeam)) {
|
|
2073
|
+
t.organizationRank = preTeam.organizationRank;
|
|
2074
|
+
}
|
|
2075
|
+
}
|
|
2076
|
+
preTeam = t;
|
|
2077
|
+
}
|
|
2078
|
+
}
|
|
2079
|
+
buildOrganizations() {
|
|
2080
|
+
if (!this.contest.organization) {
|
|
2081
|
+
return [];
|
|
2082
|
+
}
|
|
2083
|
+
const res = new Array();
|
|
2084
|
+
const se = /* @__PURE__ */ new Set();
|
|
2085
|
+
this.teams.forEach((t) => {
|
|
2086
|
+
const org = t.organization;
|
|
2087
|
+
if (se.has(org)) {
|
|
2088
|
+
return;
|
|
2089
|
+
}
|
|
2090
|
+
res.push(org);
|
|
2091
|
+
se.add(org);
|
|
2092
|
+
});
|
|
2093
|
+
res.sort();
|
|
2094
|
+
return res;
|
|
2095
|
+
}
|
|
2096
|
+
buildAwards() {
|
|
2097
|
+
if (this.contest.medal === "ccpc") {
|
|
2098
|
+
this.contest.awards = /* @__PURE__ */ new Map();
|
|
2099
|
+
const tot = this.rankStatistics.effectiveTeamNum;
|
|
2100
|
+
const award = [];
|
|
2101
|
+
const gold = new Award();
|
|
2102
|
+
const silver = new Award();
|
|
2103
|
+
const bronze = new Award();
|
|
2104
|
+
const honorable = new Award();
|
|
2105
|
+
{
|
|
2106
|
+
gold.medalType = MedalType.GOLD;
|
|
2107
|
+
gold.minRank = 1;
|
|
2108
|
+
gold.maxRank = Math.ceil(tot * 0.1);
|
|
2109
|
+
if (gold.maxRank >= gold.minRank) {
|
|
2110
|
+
award.push(gold);
|
|
2111
|
+
}
|
|
2112
|
+
}
|
|
2113
|
+
{
|
|
2114
|
+
silver.medalType = MedalType.SILVER;
|
|
2115
|
+
silver.minRank = gold.maxRank + 1;
|
|
2116
|
+
silver.maxRank = Math.ceil(tot * 0.3);
|
|
2117
|
+
if (silver.maxRank >= silver.minRank) {
|
|
2118
|
+
award.push(silver);
|
|
2119
|
+
}
|
|
2120
|
+
}
|
|
2121
|
+
{
|
|
2122
|
+
bronze.medalType = MedalType.BRONZE;
|
|
2123
|
+
bronze.minRank = silver.maxRank + 1;
|
|
2124
|
+
bronze.maxRank = Math.ceil(tot * 0.6);
|
|
2125
|
+
if (bronze.maxRank >= bronze.minRank) {
|
|
2126
|
+
award.push(bronze);
|
|
2127
|
+
}
|
|
2128
|
+
}
|
|
2129
|
+
{
|
|
2130
|
+
honorable.medalType = MedalType.HONORABLE;
|
|
2131
|
+
honorable.minRank = bronze.maxRank + 1;
|
|
2132
|
+
this.teams.forEach((t) => {
|
|
2133
|
+
if (t.solvedProblemNum > 0) {
|
|
2134
|
+
honorable.maxRank = Math.max(honorable.maxRank, t.rank);
|
|
2135
|
+
}
|
|
2136
|
+
});
|
|
2137
|
+
if (honorable.maxRank >= honorable.minRank) {
|
|
2138
|
+
award.push(honorable);
|
|
2139
|
+
}
|
|
2140
|
+
}
|
|
2141
|
+
this.contest.awards.set("official", award);
|
|
2142
|
+
}
|
|
2143
|
+
}
|
|
2144
|
+
filterTeamByOrg(team) {
|
|
2145
|
+
const o = this.options;
|
|
2146
|
+
if (o.enableFilterTeamsByGroup) {
|
|
2147
|
+
if (!team.group?.includes(o.group)) {
|
|
2148
|
+
return true;
|
|
2149
|
+
}
|
|
2150
|
+
}
|
|
2151
|
+
return false;
|
|
2152
|
+
}
|
|
2153
|
+
getSubmissions() {
|
|
2154
|
+
if (this.contest.replayContestStartTimestamp === void 0 && this.options.enableFilterSubmissionsByTimestamp === false) {
|
|
2155
|
+
return this.submissions;
|
|
2156
|
+
}
|
|
2157
|
+
return this.submissions.filter((s) => {
|
|
2158
|
+
if (this.contest.replayContestStartTimestamp !== void 0) {
|
|
2159
|
+
if (s.timestampToSecond > this.contest.replayContestStartTimestamp) {
|
|
2160
|
+
return false;
|
|
2161
|
+
}
|
|
2162
|
+
}
|
|
2163
|
+
if (this.options.enableFilterSubmissionsByTimestamp) {
|
|
2164
|
+
if (s.timestampToSecond > this.options.timestamp) {
|
|
2165
|
+
return false;
|
|
2166
|
+
}
|
|
2146
2167
|
}
|
|
2147
|
-
|
|
2148
|
-
|
|
2168
|
+
return true;
|
|
2169
|
+
});
|
|
2149
2170
|
}
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
for (
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2171
|
+
buildBalloons() {
|
|
2172
|
+
this.balloons = [];
|
|
2173
|
+
this.cleanRank();
|
|
2174
|
+
const allSubmissions = this.getSubmissions();
|
|
2175
|
+
for (let ix = 0; ix < allSubmissions.length; ix++) {
|
|
2176
|
+
const s = allSubmissions[ix];
|
|
2177
|
+
const teamId = s.teamId;
|
|
2178
|
+
const problemId = s.problemId;
|
|
2179
|
+
const team = this.teamsMap.get(teamId);
|
|
2180
|
+
const problem = this.contest.problemsMap.get(problemId);
|
|
2181
|
+
(() => {
|
|
2182
|
+
if (team === void 0 || problem === void 0) {
|
|
2183
|
+
return;
|
|
2160
2184
|
}
|
|
2161
|
-
|
|
2162
|
-
|
|
2185
|
+
const problemStatistics = team.problemStatisticsMap.get(problemId);
|
|
2186
|
+
if (problemStatistics.isSolved) {
|
|
2187
|
+
return;
|
|
2188
|
+
}
|
|
2189
|
+
if (s.isAccepted()) {
|
|
2190
|
+
problemStatistics.isSolved = true;
|
|
2191
|
+
problemStatistics.solvedTimestamp = s.timestampToSecond;
|
|
2192
|
+
const b = new Balloon();
|
|
2193
|
+
b.team = team;
|
|
2194
|
+
b.problem = problem;
|
|
2195
|
+
b.submission = s;
|
|
2196
|
+
this.balloons.push(b);
|
|
2197
|
+
}
|
|
2198
|
+
})();
|
|
2163
2199
|
}
|
|
2164
2200
|
}
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
|
|
2201
|
+
setReplayTime(replayStartTimestamp) {
|
|
2202
|
+
this.contest.setReplayTime(replayStartTimestamp);
|
|
2203
|
+
}
|
|
2204
|
+
}
|
|
2205
|
+
|
|
2206
|
+
var __defProp$6 = Object.defineProperty;
|
|
2207
|
+
var __defNormalProp$6 = (obj, key, value) => key in obj ? __defProp$6(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
2208
|
+
var __publicField$6 = (obj, key, value) => {
|
|
2209
|
+
__defNormalProp$6(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
2210
|
+
return value;
|
|
2211
|
+
};
|
|
2212
|
+
class RatingHistory {
|
|
2213
|
+
constructor() {
|
|
2214
|
+
__publicField$6(this, "rank");
|
|
2215
|
+
__publicField$6(this, "rating");
|
|
2216
|
+
__publicField$6(this, "teamName");
|
|
2217
|
+
__publicField$6(this, "organization");
|
|
2218
|
+
__publicField$6(this, "members");
|
|
2219
|
+
__publicField$6(this, "coaches");
|
|
2220
|
+
__publicField$6(this, "contestID");
|
|
2221
|
+
__publicField$6(this, "contestName");
|
|
2222
|
+
__publicField$6(this, "contestLink");
|
|
2223
|
+
__publicField$6(this, "contestTime");
|
|
2224
|
+
this.rank = 0;
|
|
2225
|
+
this.rating = 0;
|
|
2226
|
+
this.teamName = "";
|
|
2227
|
+
this.organization = "";
|
|
2228
|
+
this.members = [];
|
|
2229
|
+
this.coaches = [];
|
|
2230
|
+
this.contestID = "";
|
|
2231
|
+
this.contestName = "";
|
|
2232
|
+
this.contestLink = "";
|
|
2233
|
+
this.contestTime = createDayJS();
|
|
2234
|
+
}
|
|
2235
|
+
toJSON() {
|
|
2236
|
+
return {
|
|
2237
|
+
rank: this.rank,
|
|
2238
|
+
rating: this.rating,
|
|
2239
|
+
teamName: this.teamName,
|
|
2240
|
+
organization: this.organization,
|
|
2241
|
+
members: this.members.map((member) => member.toJSON()),
|
|
2242
|
+
coaches: this.coaches.map((coach) => coach.toJSON()),
|
|
2243
|
+
contestID: this.contestID,
|
|
2244
|
+
contestName: this.contestName,
|
|
2245
|
+
contestLink: this.contestLink,
|
|
2246
|
+
contestTime: this.contestTime.toDate()
|
|
2247
|
+
};
|
|
2248
|
+
}
|
|
2249
|
+
static fromJSON(iRatingHistory) {
|
|
2250
|
+
if (typeof iRatingHistory === "string") {
|
|
2251
|
+
iRatingHistory = JSON.parse(iRatingHistory);
|
|
2168
2252
|
}
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2253
|
+
const ratingHistory = new RatingHistory();
|
|
2254
|
+
ratingHistory.rank = iRatingHistory.rank;
|
|
2255
|
+
ratingHistory.rating = iRatingHistory.rating;
|
|
2256
|
+
ratingHistory.teamName = iRatingHistory.teamName;
|
|
2257
|
+
ratingHistory.organization = iRatingHistory.organization;
|
|
2258
|
+
ratingHistory.members = iRatingHistory.members.map((iMember) => Person.fromJSON(iMember));
|
|
2259
|
+
ratingHistory.coaches = iRatingHistory.coaches.map((iCoach) => Person.fromJSON(iCoach));
|
|
2260
|
+
ratingHistory.contestID = iRatingHistory.contestID;
|
|
2261
|
+
ratingHistory.contestName = iRatingHistory.contestName;
|
|
2262
|
+
ratingHistory.contestLink = iRatingHistory.contestLink;
|
|
2263
|
+
ratingHistory.contestTime = createDayJS(iRatingHistory.contestTime);
|
|
2264
|
+
return ratingHistory;
|
|
2265
|
+
}
|
|
2266
|
+
}
|
|
2267
|
+
|
|
2268
|
+
var __defProp$5 = Object.defineProperty;
|
|
2269
|
+
var __defNormalProp$5 = (obj, key, value) => key in obj ? __defProp$5(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
2270
|
+
var __publicField$5 = (obj, key, value) => {
|
|
2271
|
+
__defNormalProp$5(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
2272
|
+
return value;
|
|
2273
|
+
};
|
|
2274
|
+
class RatingUser {
|
|
2275
|
+
constructor() {
|
|
2276
|
+
__publicField$5(this, "id");
|
|
2277
|
+
__publicField$5(this, "name");
|
|
2278
|
+
__publicField$5(this, "organization");
|
|
2279
|
+
__publicField$5(this, "members");
|
|
2280
|
+
__publicField$5(this, "coaches");
|
|
2281
|
+
__publicField$5(this, "rating");
|
|
2282
|
+
__publicField$5(this, "minRating");
|
|
2283
|
+
__publicField$5(this, "maxRating");
|
|
2284
|
+
__publicField$5(this, "rank");
|
|
2285
|
+
__publicField$5(this, "oldRating");
|
|
2286
|
+
__publicField$5(this, "seed");
|
|
2287
|
+
__publicField$5(this, "delta");
|
|
2288
|
+
__publicField$5(this, "ratingHistories");
|
|
2289
|
+
this.id = "";
|
|
2290
|
+
this.name = "";
|
|
2291
|
+
this.organization = "";
|
|
2292
|
+
this.members = [];
|
|
2293
|
+
this.coaches = [];
|
|
2294
|
+
this.rating = 0;
|
|
2295
|
+
this.minRating = 1061109567;
|
|
2296
|
+
this.maxRating = -1061109567;
|
|
2297
|
+
this.rank = 0;
|
|
2298
|
+
this.oldRating = 0;
|
|
2299
|
+
this.seed = 1;
|
|
2300
|
+
this.delta = 0;
|
|
2301
|
+
this.ratingHistories = [];
|
|
2302
|
+
}
|
|
2303
|
+
UpdateRating(rating) {
|
|
2304
|
+
this.rating = rating;
|
|
2305
|
+
this.minRating = Math.min(this.minRating, rating);
|
|
2306
|
+
this.maxRating = Math.max(this.maxRating, rating);
|
|
2307
|
+
}
|
|
2308
|
+
toJSON() {
|
|
2309
|
+
return {
|
|
2310
|
+
id: this.id,
|
|
2311
|
+
name: this.name,
|
|
2312
|
+
organization: this.organization,
|
|
2313
|
+
members: this.members.map((member) => member.toJSON()),
|
|
2314
|
+
coaches: this.coaches.map((coach) => coach.toJSON()),
|
|
2315
|
+
rating: this.rating,
|
|
2316
|
+
minRating: this.minRating,
|
|
2317
|
+
maxRating: this.maxRating,
|
|
2318
|
+
ratingHistories: this.ratingHistories.map((ratingHistory) => ratingHistory.toJSON())
|
|
2319
|
+
};
|
|
2320
|
+
}
|
|
2321
|
+
static fromJSON(iRatingUser) {
|
|
2322
|
+
if (typeof iRatingUser === "string") {
|
|
2323
|
+
iRatingUser = JSON.parse(iRatingUser);
|
|
2324
|
+
}
|
|
2325
|
+
const ratingUser = new RatingUser();
|
|
2326
|
+
ratingUser.id = iRatingUser.id;
|
|
2327
|
+
ratingUser.name = iRatingUser.name;
|
|
2328
|
+
ratingUser.organization = iRatingUser.organization;
|
|
2329
|
+
ratingUser.members = iRatingUser.members.map((member) => Person.fromJSON(member));
|
|
2330
|
+
ratingUser.coaches = iRatingUser.coaches.map((coach) => Person.fromJSON(coach));
|
|
2331
|
+
ratingUser.rating = iRatingUser.rating;
|
|
2332
|
+
ratingUser.minRating = iRatingUser.minRating;
|
|
2333
|
+
ratingUser.maxRating = iRatingUser.maxRating;
|
|
2334
|
+
for (const iRatingHistory of iRatingUser.ratingHistories) {
|
|
2335
|
+
ratingUser.ratingHistories.push(RatingHistory.fromJSON(iRatingHistory));
|
|
2336
|
+
}
|
|
2337
|
+
return ratingUser;
|
|
2338
|
+
}
|
|
2339
|
+
}
|
|
2340
|
+
|
|
2341
|
+
var __defProp$4 = Object.defineProperty;
|
|
2342
|
+
var __defNormalProp$4 = (obj, key, value) => key in obj ? __defProp$4(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
2343
|
+
var __publicField$4 = (obj, key, value) => {
|
|
2344
|
+
__defNormalProp$4(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
2345
|
+
return value;
|
|
2346
|
+
};
|
|
2347
|
+
class RatingCalculator {
|
|
2348
|
+
constructor() {
|
|
2349
|
+
__publicField$4(this, "users");
|
|
2350
|
+
this.users = [];
|
|
2351
|
+
}
|
|
2352
|
+
calculate() {
|
|
2353
|
+
this.calculateInternal();
|
|
2354
|
+
}
|
|
2355
|
+
calcP(userA, userB) {
|
|
2356
|
+
return 1 / (1 + 10 ** ((userB.oldRating - userA.oldRating) / 400));
|
|
2357
|
+
}
|
|
2358
|
+
getExSeed(users, rating, ownUser) {
|
|
2359
|
+
const exUser = new RatingUser();
|
|
2360
|
+
exUser.oldRating = rating;
|
|
2361
|
+
let res = 0;
|
|
2362
|
+
users.forEach((user) => {
|
|
2363
|
+
if (user.id !== ownUser.id) {
|
|
2364
|
+
res += this.calcP(user, exUser);
|
|
2176
2365
|
}
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2366
|
+
});
|
|
2367
|
+
return res;
|
|
2368
|
+
}
|
|
2369
|
+
calcRating(users, rank, user) {
|
|
2370
|
+
let left = 1;
|
|
2371
|
+
let right = 8e3;
|
|
2372
|
+
while (right - left > 1) {
|
|
2373
|
+
const mid = Math.floor((left + right) / 2);
|
|
2374
|
+
if (this.getExSeed(users, mid, user) < rank) {
|
|
2375
|
+
right = mid;
|
|
2376
|
+
} else {
|
|
2377
|
+
left = mid;
|
|
2183
2378
|
}
|
|
2184
|
-
preTeam = t;
|
|
2185
2379
|
}
|
|
2380
|
+
return left;
|
|
2186
2381
|
}
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
return;
|
|
2382
|
+
calculateInternal() {
|
|
2383
|
+
for (let i = 0; i < this.users.length; i++) {
|
|
2384
|
+
const u = this.users[i];
|
|
2385
|
+
u.seed = 1;
|
|
2386
|
+
for (let j = 0; j < this.users.length; j++) {
|
|
2387
|
+
if (i !== j) {
|
|
2388
|
+
const otherUser = this.users[j];
|
|
2389
|
+
u.seed += this.calcP(otherUser, u);
|
|
2390
|
+
}
|
|
2197
2391
|
}
|
|
2198
|
-
|
|
2199
|
-
|
|
2392
|
+
}
|
|
2393
|
+
let sumDelta = 0;
|
|
2394
|
+
for (let i = 0; i < this.users.length; i++) {
|
|
2395
|
+
const u = this.users[i];
|
|
2396
|
+
u.delta = Math.floor(
|
|
2397
|
+
(this.calcRating(this.users, Math.sqrt(u.rank * u.seed), u) - u.oldRating) / 2
|
|
2398
|
+
);
|
|
2399
|
+
sumDelta += u.delta;
|
|
2400
|
+
}
|
|
2401
|
+
let inc = Math.floor(-sumDelta / this.users.length) - 1;
|
|
2402
|
+
for (let i = 0; i < this.users.length; i++) {
|
|
2403
|
+
const u = this.users[i];
|
|
2404
|
+
u.delta += inc;
|
|
2405
|
+
}
|
|
2406
|
+
this.users = this.users.sort((a, b) => b.oldRating - a.oldRating);
|
|
2407
|
+
const s = Math.min(this.users.length, Math.floor(4 * Math.round(Math.sqrt(this.users.length))));
|
|
2408
|
+
let sumS = 0;
|
|
2409
|
+
for (let i = 0; i < s; i++) {
|
|
2410
|
+
sumS += this.users[i].delta;
|
|
2411
|
+
}
|
|
2412
|
+
inc = Math.min(Math.max(Math.floor(-sumS / s), -10), 0);
|
|
2413
|
+
this.users.forEach((u) => {
|
|
2414
|
+
u.delta += inc;
|
|
2415
|
+
u.UpdateRating(u.oldRating + u.delta);
|
|
2200
2416
|
});
|
|
2201
|
-
|
|
2202
|
-
return res;
|
|
2417
|
+
this.users = this.users.sort((a, b) => a.rank - b.rank);
|
|
2203
2418
|
}
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2419
|
+
}
|
|
2420
|
+
|
|
2421
|
+
var __defProp$3 = Object.defineProperty;
|
|
2422
|
+
var __defNormalProp$3 = (obj, key, value) => key in obj ? __defProp$3(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
2423
|
+
var __publicField$3 = (obj, key, value) => {
|
|
2424
|
+
__defNormalProp$3(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
2425
|
+
return value;
|
|
2426
|
+
};
|
|
2427
|
+
class Rating {
|
|
2428
|
+
constructor() {
|
|
2429
|
+
__publicField$3(this, "id");
|
|
2430
|
+
__publicField$3(this, "name");
|
|
2431
|
+
__publicField$3(this, "baseRating");
|
|
2432
|
+
__publicField$3(this, "contestIDs");
|
|
2433
|
+
__publicField$3(this, "users");
|
|
2434
|
+
__publicField$3(this, "ranks");
|
|
2435
|
+
__publicField$3(this, "userMap");
|
|
2436
|
+
this.id = "";
|
|
2437
|
+
this.name = "";
|
|
2438
|
+
this.baseRating = 1500;
|
|
2439
|
+
this.contestIDs = [];
|
|
2440
|
+
this.users = [];
|
|
2441
|
+
this.ranks = [];
|
|
2442
|
+
this.userMap = /* @__PURE__ */ new Map();
|
|
2443
|
+
}
|
|
2444
|
+
buildRating() {
|
|
2445
|
+
for (const rank of this.ranks) {
|
|
2446
|
+
rank.buildRank();
|
|
2447
|
+
const ratingCalculator = new RatingCalculator();
|
|
2448
|
+
for (const t of rank.teams) {
|
|
2449
|
+
const id = this.generateTeamId(t);
|
|
2450
|
+
let u = null;
|
|
2451
|
+
if (!this.userMap.has(id)) {
|
|
2452
|
+
u = new RatingUser();
|
|
2453
|
+
u.id = id;
|
|
2454
|
+
u.name = t.name;
|
|
2455
|
+
u.organization = t.organization;
|
|
2456
|
+
u.members = createPersons(t.members ?? []);
|
|
2457
|
+
u.coaches = createPersons(t.coach ?? []);
|
|
2458
|
+
u.rank = t.rank;
|
|
2459
|
+
u.oldRating = this.baseRating;
|
|
2460
|
+
u.UpdateRating(this.baseRating);
|
|
2461
|
+
this.userMap.set(id, u);
|
|
2462
|
+
this.users.push(u);
|
|
2463
|
+
ratingCalculator.users.push(u);
|
|
2464
|
+
} else {
|
|
2465
|
+
u = this.userMap.get(id);
|
|
2466
|
+
u.rank = t.rank;
|
|
2467
|
+
u.oldRating = u.rating;
|
|
2468
|
+
ratingCalculator.users.push(u);
|
|
2227
2469
|
}
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2470
|
+
{
|
|
2471
|
+
const h = new RatingHistory();
|
|
2472
|
+
h.rank = t.rank;
|
|
2473
|
+
h.rating = u.rating;
|
|
2474
|
+
h.teamName = t.name;
|
|
2475
|
+
h.organization = t.organization;
|
|
2476
|
+
h.members = createPersons(t.members ?? []);
|
|
2477
|
+
h.coaches = createPersons(t.coach ?? []);
|
|
2478
|
+
h.contestID = rank.contest.id;
|
|
2479
|
+
h.contestLink = h.contestID;
|
|
2480
|
+
h.contestName = rank.contest.name;
|
|
2481
|
+
h.contestTime = rank.contest.startTime;
|
|
2482
|
+
u.ratingHistories.push(h);
|
|
2235
2483
|
}
|
|
2236
2484
|
}
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
this.teams.forEach((t) => {
|
|
2241
|
-
if (t.solvedProblemNum > 0) {
|
|
2242
|
-
honorable.maxRank = Math.max(honorable.maxRank, t.rank);
|
|
2243
|
-
}
|
|
2244
|
-
});
|
|
2245
|
-
if (honorable.maxRank >= honorable.minRank) {
|
|
2246
|
-
award.push(honorable);
|
|
2247
|
-
}
|
|
2485
|
+
ratingCalculator.calculate();
|
|
2486
|
+
for (const u of ratingCalculator.users) {
|
|
2487
|
+
u.ratingHistories.at(-1).rating = u.rating;
|
|
2248
2488
|
}
|
|
2249
|
-
this.contest.awards.set("official", award);
|
|
2250
2489
|
}
|
|
2251
2490
|
}
|
|
2252
|
-
|
|
2253
|
-
const
|
|
2254
|
-
if (
|
|
2255
|
-
|
|
2256
|
-
return true;
|
|
2257
|
-
}
|
|
2491
|
+
generateTeamId(t) {
|
|
2492
|
+
const persons = createPersons(t.members ?? []);
|
|
2493
|
+
if (persons.length > 0) {
|
|
2494
|
+
return persons.map((person) => person.name.trim()).sort().join("|");
|
|
2258
2495
|
}
|
|
2259
|
-
return
|
|
2496
|
+
return `${t.organization}-${t.name}`;
|
|
2260
2497
|
}
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2498
|
+
toJSON() {
|
|
2499
|
+
return {
|
|
2500
|
+
id: this.id,
|
|
2501
|
+
name: this.name,
|
|
2502
|
+
baseRating: this.baseRating,
|
|
2503
|
+
contestIDs: this.contestIDs,
|
|
2504
|
+
users: this.users.map((ratingUser) => ratingUser.toJSON())
|
|
2505
|
+
};
|
|
2506
|
+
}
|
|
2507
|
+
static fromJSON(iRating) {
|
|
2508
|
+
if (typeof iRating === "string") {
|
|
2509
|
+
iRating = JSON.parse(iRating);
|
|
2264
2510
|
}
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
}
|
|
2275
|
-
}
|
|
2276
|
-
return true;
|
|
2277
|
-
});
|
|
2511
|
+
const rating = new Rating();
|
|
2512
|
+
rating.id = iRating.id;
|
|
2513
|
+
rating.name = iRating.name;
|
|
2514
|
+
rating.baseRating = iRating.baseRating;
|
|
2515
|
+
rating.contestIDs = iRating.contestIDs;
|
|
2516
|
+
for (const iUser of iRating.users) {
|
|
2517
|
+
rating.users.push(RatingUser.fromJSON(iUser));
|
|
2518
|
+
}
|
|
2519
|
+
return rating;
|
|
2278
2520
|
}
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2521
|
+
}
|
|
2522
|
+
|
|
2523
|
+
var RatingLevel = /* @__PURE__ */ ((RatingLevel2) => {
|
|
2524
|
+
RatingLevel2["NEWBIE"] = "NEWBIE";
|
|
2525
|
+
RatingLevel2["PUPIL"] = "PUPIL";
|
|
2526
|
+
RatingLevel2["SPECIALIST"] = "SPECIALIST";
|
|
2527
|
+
RatingLevel2["EXPERT"] = "EXPERT";
|
|
2528
|
+
RatingLevel2["CANDIDATE_MASTER"] = "CANDIDATE_MASTER";
|
|
2529
|
+
RatingLevel2["MASTER"] = "MASTER";
|
|
2530
|
+
RatingLevel2["INTERNATIONAL_MASTER"] = "INTERNATIONAL_MASTER";
|
|
2531
|
+
RatingLevel2["GRANDMASTER"] = "GRANDMASTER";
|
|
2532
|
+
RatingLevel2["INTERNATIONAL_GRANDMASTER"] = "INTERNATIONAL_GRANDMASTER";
|
|
2533
|
+
RatingLevel2["LEGENDARY_GRANDMASTER"] = "LEGENDARY_GRANDMASTER";
|
|
2534
|
+
return RatingLevel2;
|
|
2535
|
+
})(RatingLevel || {});
|
|
2536
|
+
const RatingLevelToString = {
|
|
2537
|
+
["NEWBIE" /* NEWBIE */]: "Newbie",
|
|
2538
|
+
["PUPIL" /* PUPIL */]: "Pupil",
|
|
2539
|
+
["SPECIALIST" /* SPECIALIST */]: "Specialist",
|
|
2540
|
+
["EXPERT" /* EXPERT */]: "Expert",
|
|
2541
|
+
["CANDIDATE_MASTER" /* CANDIDATE_MASTER */]: "Candidate Master",
|
|
2542
|
+
["MASTER" /* MASTER */]: "Master",
|
|
2543
|
+
["INTERNATIONAL_MASTER" /* INTERNATIONAL_MASTER */]: "International Master",
|
|
2544
|
+
["GRANDMASTER" /* GRANDMASTER */]: "Grandmaster",
|
|
2545
|
+
["INTERNATIONAL_GRANDMASTER" /* INTERNATIONAL_GRANDMASTER */]: "International Grandmaster",
|
|
2546
|
+
["LEGENDARY_GRANDMASTER" /* LEGENDARY_GRANDMASTER */]: "Legendary Grandmaster"
|
|
2547
|
+
};
|
|
2548
|
+
class RatingUtility {
|
|
2549
|
+
static getRatingLevel(rating) {
|
|
2550
|
+
if (rating >= 3e3) {
|
|
2551
|
+
return "LEGENDARY_GRANDMASTER" /* LEGENDARY_GRANDMASTER */;
|
|
2552
|
+
} else if (rating >= 2600) {
|
|
2553
|
+
return "INTERNATIONAL_GRANDMASTER" /* INTERNATIONAL_GRANDMASTER */;
|
|
2554
|
+
} else if (rating >= 2400) {
|
|
2555
|
+
return "GRANDMASTER" /* GRANDMASTER */;
|
|
2556
|
+
} else if (rating >= 2300) {
|
|
2557
|
+
return "INTERNATIONAL_MASTER" /* INTERNATIONAL_MASTER */;
|
|
2558
|
+
} else if (rating >= 2100) {
|
|
2559
|
+
return "MASTER" /* MASTER */;
|
|
2560
|
+
} else if (rating >= 1900) {
|
|
2561
|
+
return "CANDIDATE_MASTER" /* CANDIDATE_MASTER */;
|
|
2562
|
+
} else if (rating >= 1600) {
|
|
2563
|
+
return "EXPERT" /* EXPERT */;
|
|
2564
|
+
} else if (rating >= 1400) {
|
|
2565
|
+
return "SPECIALIST" /* SPECIALIST */;
|
|
2566
|
+
} else if (rating >= 1200) {
|
|
2567
|
+
return "PUPIL" /* PUPIL */;
|
|
2307
2568
|
}
|
|
2569
|
+
return "NEWBIE" /* NEWBIE */;
|
|
2308
2570
|
}
|
|
2309
|
-
|
|
2310
|
-
|
|
2571
|
+
static getRatingLevelClass(ratingLevel) {
|
|
2572
|
+
if (typeof ratingLevel === "number") {
|
|
2573
|
+
return this.getRatingLevelClass(this.getRatingLevel(ratingLevel));
|
|
2574
|
+
}
|
|
2575
|
+
switch (ratingLevel) {
|
|
2576
|
+
case "NEWBIE" /* NEWBIE */:
|
|
2577
|
+
return "user-gray";
|
|
2578
|
+
case "PUPIL" /* PUPIL */:
|
|
2579
|
+
return "user-green";
|
|
2580
|
+
case "SPECIALIST" /* SPECIALIST */:
|
|
2581
|
+
return "user-cyan";
|
|
2582
|
+
case "EXPERT" /* EXPERT */:
|
|
2583
|
+
return "user-blue";
|
|
2584
|
+
case "CANDIDATE_MASTER" /* CANDIDATE_MASTER */:
|
|
2585
|
+
return "user-violet";
|
|
2586
|
+
case "MASTER" /* MASTER */:
|
|
2587
|
+
return "user-orange";
|
|
2588
|
+
case "INTERNATIONAL_MASTER" /* INTERNATIONAL_MASTER */:
|
|
2589
|
+
return "user-orange";
|
|
2590
|
+
case "GRANDMASTER" /* GRANDMASTER */:
|
|
2591
|
+
return "user-red";
|
|
2592
|
+
case "INTERNATIONAL_GRANDMASTER" /* INTERNATIONAL_GRANDMASTER */:
|
|
2593
|
+
return "user-red";
|
|
2594
|
+
case "LEGENDARY_GRANDMASTER" /* LEGENDARY_GRANDMASTER */:
|
|
2595
|
+
return "user-legendary";
|
|
2596
|
+
}
|
|
2311
2597
|
}
|
|
2312
2598
|
}
|
|
2313
2599
|
|
|
2600
|
+
var __defProp$2 = Object.defineProperty;
|
|
2601
|
+
var __defNormalProp$2 = (obj, key, value) => key in obj ? __defProp$2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
2602
|
+
var __publicField$2 = (obj, key, value) => {
|
|
2603
|
+
__defNormalProp$2(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
2604
|
+
return value;
|
|
2605
|
+
};
|
|
2314
2606
|
class ResolverOperation {
|
|
2315
2607
|
constructor() {
|
|
2608
|
+
__publicField$2(this, "id");
|
|
2609
|
+
__publicField$2(this, "team");
|
|
2610
|
+
__publicField$2(this, "problemIx");
|
|
2611
|
+
__publicField$2(this, "beforeTeamProblemStatistics");
|
|
2612
|
+
__publicField$2(this, "afterTeamProblemStatistics");
|
|
2316
2613
|
this.id = 0;
|
|
2317
2614
|
this.team = new Team();
|
|
2318
2615
|
this.problemIx = 0;
|
|
@@ -2321,6 +2618,12 @@ class ResolverOperation {
|
|
|
2321
2618
|
}
|
|
2322
2619
|
}
|
|
2323
2620
|
|
|
2621
|
+
var __defProp$1 = Object.defineProperty;
|
|
2622
|
+
var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
2623
|
+
var __publicField$1 = (obj, key, value) => {
|
|
2624
|
+
__defNormalProp$1(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
2625
|
+
return value;
|
|
2626
|
+
};
|
|
2324
2627
|
class Resolver extends Rank {
|
|
2325
2628
|
constructor(contest, teams, submissions) {
|
|
2326
2629
|
submissions.sort(Submission.compare);
|
|
@@ -2345,6 +2648,10 @@ class Resolver extends Rank {
|
|
|
2345
2648
|
afterFreezeSubmissions = submissions.slice(ix, -1);
|
|
2346
2649
|
}
|
|
2347
2650
|
super(contest, teams, beforeFreezeSubmissions);
|
|
2651
|
+
__publicField$1(this, "finalRank");
|
|
2652
|
+
__publicField$1(this, "operations");
|
|
2653
|
+
__publicField$1(this, "beforeFreezeSubmissions");
|
|
2654
|
+
__publicField$1(this, "afterFreezeSubmissions");
|
|
2348
2655
|
this.finalRank = new Rank(contest, teams, submissions);
|
|
2349
2656
|
this.operations = [];
|
|
2350
2657
|
this.beforeFreezeSubmissions = beforeFreezeSubmissions;
|
|
@@ -2411,11 +2718,29 @@ class Resolver extends Rank {
|
|
|
2411
2718
|
}
|
|
2412
2719
|
}
|
|
2413
2720
|
|
|
2721
|
+
var __defProp = Object.defineProperty;
|
|
2722
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
2723
|
+
var __publicField = (obj, key, value) => {
|
|
2724
|
+
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
2725
|
+
return value;
|
|
2726
|
+
};
|
|
2414
2727
|
class ResolverVue extends Resolver {
|
|
2415
2728
|
constructor(contest, teams, submissions) {
|
|
2416
2729
|
super(contest, teams, submissions);
|
|
2417
|
-
this
|
|
2418
|
-
this
|
|
2730
|
+
__publicField(this, "FLASHING_TIME_MS", 100);
|
|
2731
|
+
__publicField(this, "ROLLING_TIME_MS", 600);
|
|
2732
|
+
__publicField(this, "maxIndex");
|
|
2733
|
+
__publicField(this, "currentIndex");
|
|
2734
|
+
__publicField(this, "maxOpIndex");
|
|
2735
|
+
__publicField(this, "currentOpIndex");
|
|
2736
|
+
__publicField(this, "oldRank");
|
|
2737
|
+
__publicField(this, "newRank");
|
|
2738
|
+
__publicField(this, "currentTeamId");
|
|
2739
|
+
__publicField(this, "currentProblemIndex");
|
|
2740
|
+
__publicField(this, "problemFlashingEnded");
|
|
2741
|
+
__publicField(this, "duringAnimation");
|
|
2742
|
+
__publicField(this, "startScrollUp");
|
|
2743
|
+
__publicField(this, "startScrollDown");
|
|
2419
2744
|
this.maxIndex = 0;
|
|
2420
2745
|
this.currentIndex = 0;
|
|
2421
2746
|
this.maxOpIndex = 0;
|