@xcpcio/core 0.13.0 → 0.15.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 +410 -223
- package/dist/index.d.ts +55 -38
- package/dist/index.mjs +394 -223
- package/package.json +4 -2
- package/src/award.ts +16 -5
- package/src/contest.ts +12 -0
- package/src/export/cf.ts +120 -0
- package/src/export/general-excel.ts +184 -0
- package/src/export/index.ts +2 -0
- package/src/index.ts +1 -1
- package/src/problem.ts +8 -0
- package/src/team.ts +2 -0
- package/src/export.ts +0 -116
package/dist/index.cjs
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
|
+
const types = require('@xcpcio/types');
|
|
5
6
|
const dayjs = require('dayjs');
|
|
6
7
|
const duration = require('dayjs/plugin/duration');
|
|
7
8
|
const utc = require('dayjs/plugin/utc');
|
|
@@ -11,11 +12,24 @@ const isSameOrBefore = require('dayjs/plugin/isSameOrBefore');
|
|
|
11
12
|
const isSameOrAfter = require('dayjs/plugin/isSameOrAfter');
|
|
12
13
|
const minMax = require('dayjs/plugin/minMax');
|
|
13
14
|
const relativeTime = require('dayjs/plugin/relativeTime');
|
|
14
|
-
const types = require('@xcpcio/types');
|
|
15
15
|
const _ = require('lodash');
|
|
16
|
+
const XLSX = require('xlsx-js-style');
|
|
17
|
+
const stringWidth = require('string-width');
|
|
16
18
|
|
|
17
19
|
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e["default"] : e; }
|
|
18
20
|
|
|
21
|
+
function _interopNamespace(e) {
|
|
22
|
+
if (e && e.__esModule) return e;
|
|
23
|
+
const n = Object.create(null);
|
|
24
|
+
if (e) {
|
|
25
|
+
for (const k in e) {
|
|
26
|
+
n[k] = e[k];
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
n["default"] = e;
|
|
30
|
+
return n;
|
|
31
|
+
}
|
|
32
|
+
|
|
19
33
|
const dayjs__default = /*#__PURE__*/_interopDefaultLegacy(dayjs);
|
|
20
34
|
const duration__default = /*#__PURE__*/_interopDefaultLegacy(duration);
|
|
21
35
|
const utc__default = /*#__PURE__*/_interopDefaultLegacy(utc);
|
|
@@ -26,28 +40,124 @@ const isSameOrAfter__default = /*#__PURE__*/_interopDefaultLegacy(isSameOrAfter)
|
|
|
26
40
|
const minMax__default = /*#__PURE__*/_interopDefaultLegacy(minMax);
|
|
27
41
|
const relativeTime__default = /*#__PURE__*/_interopDefaultLegacy(relativeTime);
|
|
28
42
|
const ___default = /*#__PURE__*/_interopDefaultLegacy(_);
|
|
43
|
+
const XLSX__namespace = /*#__PURE__*/_interopNamespace(XLSX);
|
|
44
|
+
const stringWidth__default = /*#__PURE__*/_interopDefaultLegacy(stringWidth);
|
|
29
45
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
MedalType2[MedalType2["BRONZE"] = 3] = "BRONZE";
|
|
35
|
-
MedalType2[MedalType2["HONORABLE"] = 4] = "HONORABLE";
|
|
36
|
-
return MedalType2;
|
|
37
|
-
})(MedalType || {});
|
|
38
|
-
class Award {
|
|
39
|
-
constructor() {
|
|
40
|
-
this.medalType = 0 /* UNKNOWN */;
|
|
41
|
-
this.minRank = 0;
|
|
42
|
-
this.maxRank = 0;
|
|
46
|
+
function stringToSubmissionStatus(status) {
|
|
47
|
+
status = status.toUpperCase().replace(" ", "_");
|
|
48
|
+
if (["OK", "AC", types.SubmissionStatus.ACCEPTED.toString()].includes(status)) {
|
|
49
|
+
return types.SubmissionStatus.ACCEPTED;
|
|
43
50
|
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
function calcDict(attemptedNum, solvedNum) {
|
|
47
|
-
if (solvedNum === 0) {
|
|
48
|
-
return 0;
|
|
51
|
+
if ([types.SubmissionStatus.CORRECT.toString()].includes(status)) {
|
|
52
|
+
return types.SubmissionStatus.ACCEPTED;
|
|
49
53
|
}
|
|
50
|
-
|
|
54
|
+
if ([types.SubmissionStatus.PARTIALLY_CORRECT.toString()].includes(status)) {
|
|
55
|
+
return types.SubmissionStatus.PARTIALLY_CORRECT;
|
|
56
|
+
}
|
|
57
|
+
if (["WA", types.SubmissionStatus.WRONG_ANSWER.toString()].includes(status)) {
|
|
58
|
+
return types.SubmissionStatus.WRONG_ANSWER;
|
|
59
|
+
}
|
|
60
|
+
if (["RJ", "INCORRECT", types.SubmissionStatus.REJECTED.toString()].includes(status)) {
|
|
61
|
+
return types.SubmissionStatus.REJECTED;
|
|
62
|
+
}
|
|
63
|
+
if (["PD", types.SubmissionStatus.PENDING.toString()].includes(status)) {
|
|
64
|
+
return types.SubmissionStatus.PENDING;
|
|
65
|
+
}
|
|
66
|
+
if ([types.SubmissionStatus.WAITING.toString()].includes(status)) {
|
|
67
|
+
return types.SubmissionStatus.WAITING;
|
|
68
|
+
}
|
|
69
|
+
if ([types.SubmissionStatus.JUDGING.toString()].includes(status)) {
|
|
70
|
+
return types.SubmissionStatus.JUDGING;
|
|
71
|
+
}
|
|
72
|
+
if ([types.SubmissionStatus.FROZEN.toString()].includes(status)) {
|
|
73
|
+
return types.SubmissionStatus.FROZEN;
|
|
74
|
+
}
|
|
75
|
+
if (["CE", types.SubmissionStatus.COMPILATION_ERROR.toString()].includes(status)) {
|
|
76
|
+
return types.SubmissionStatus.COMPILATION_ERROR;
|
|
77
|
+
}
|
|
78
|
+
if (["PE", types.SubmissionStatus.PRESENTATION_ERROR.toString()].includes(status)) {
|
|
79
|
+
return types.SubmissionStatus.PRESENTATION_ERROR;
|
|
80
|
+
}
|
|
81
|
+
if (["TL", "TLE", types.SubmissionStatus.TIME_LIMIT_EXCEEDED.toString()].includes(status)) {
|
|
82
|
+
return types.SubmissionStatus.TIME_LIMIT_EXCEEDED;
|
|
83
|
+
}
|
|
84
|
+
if (["ML", "MLE", types.SubmissionStatus.MEMORY_LIMIT_EXCEEDED.toString()].includes(status)) {
|
|
85
|
+
return types.SubmissionStatus.MEMORY_LIMIT_EXCEEDED;
|
|
86
|
+
}
|
|
87
|
+
if (["OL", "OLE", types.SubmissionStatus.OUTPUT_LIMIT_EXCEEDED.toString()].includes(status)) {
|
|
88
|
+
return types.SubmissionStatus.OUTPUT_LIMIT_EXCEEDED;
|
|
89
|
+
}
|
|
90
|
+
if (["IL", "ILE", types.SubmissionStatus.IDLENESS_LIMIT_EXCEEDED.toString()].includes(status)) {
|
|
91
|
+
return types.SubmissionStatus.IDLENESS_LIMIT_EXCEEDED;
|
|
92
|
+
}
|
|
93
|
+
if (["RT", "RE", "RTE", types.SubmissionStatus.RUNTIME_ERROR.toString()].includes(status)) {
|
|
94
|
+
return types.SubmissionStatus.RUNTIME_ERROR;
|
|
95
|
+
}
|
|
96
|
+
if (["JE", types.SubmissionStatus.JUDGEMENT_FAILED.toString()].includes(status)) {
|
|
97
|
+
return types.SubmissionStatus.JUDGEMENT_FAILED;
|
|
98
|
+
}
|
|
99
|
+
if (["SE", types.SubmissionStatus.SYSTEM_ERROR.toString()].includes(status)) {
|
|
100
|
+
return types.SubmissionStatus.SYSTEM_ERROR;
|
|
101
|
+
}
|
|
102
|
+
if ([types.SubmissionStatus.HACKED.toString()].includes(status)) {
|
|
103
|
+
return types.SubmissionStatus.HACKED;
|
|
104
|
+
}
|
|
105
|
+
if ([types.SubmissionStatus.CONFIGURATION_ERROR.toString()].includes(status)) {
|
|
106
|
+
return types.SubmissionStatus.CONFIGURATION_ERROR;
|
|
107
|
+
}
|
|
108
|
+
if ([types.SubmissionStatus.CANCELED.toString()].includes(status)) {
|
|
109
|
+
return types.SubmissionStatus.CANCELED;
|
|
110
|
+
}
|
|
111
|
+
if ([types.SubmissionStatus.SKIPPED.toString()].includes(status)) {
|
|
112
|
+
return types.SubmissionStatus.SKIPPED;
|
|
113
|
+
}
|
|
114
|
+
if ([types.SubmissionStatus.SECURITY_VIOLATED.toString()].includes(status)) {
|
|
115
|
+
return types.SubmissionStatus.SECURITY_VIOLATED;
|
|
116
|
+
}
|
|
117
|
+
if ([types.SubmissionStatus.DENIAL_OF_JUDGEMENT.toString()].includes(status)) {
|
|
118
|
+
return types.SubmissionStatus.DENIAL_OF_JUDGEMENT;
|
|
119
|
+
}
|
|
120
|
+
return types.SubmissionStatus.UNKNOWN;
|
|
121
|
+
}
|
|
122
|
+
function isAccepted(status) {
|
|
123
|
+
const acceptedArray = [types.SubmissionStatus.ACCEPTED, types.SubmissionStatus.CORRECT];
|
|
124
|
+
return acceptedArray.includes(status);
|
|
125
|
+
}
|
|
126
|
+
function isRejected(status) {
|
|
127
|
+
const rejectArray = [
|
|
128
|
+
types.SubmissionStatus.RUNTIME_ERROR,
|
|
129
|
+
types.SubmissionStatus.TIME_LIMIT_EXCEEDED,
|
|
130
|
+
types.SubmissionStatus.MEMORY_LIMIT_EXCEEDED,
|
|
131
|
+
types.SubmissionStatus.OUTPUT_LIMIT_EXCEEDED,
|
|
132
|
+
types.SubmissionStatus.IDLENESS_LIMIT_EXCEEDED,
|
|
133
|
+
types.SubmissionStatus.WRONG_ANSWER,
|
|
134
|
+
types.SubmissionStatus.REJECTED,
|
|
135
|
+
types.SubmissionStatus.JUDGEMENT_FAILED,
|
|
136
|
+
types.SubmissionStatus.HACKED
|
|
137
|
+
];
|
|
138
|
+
return rejectArray.includes(status);
|
|
139
|
+
}
|
|
140
|
+
function isPending(status) {
|
|
141
|
+
const pendingArray = [
|
|
142
|
+
types.SubmissionStatus.PENDING,
|
|
143
|
+
types.SubmissionStatus.WAITING,
|
|
144
|
+
types.SubmissionStatus.JUDGING,
|
|
145
|
+
types.SubmissionStatus.FROZEN
|
|
146
|
+
];
|
|
147
|
+
return pendingArray.includes(status);
|
|
148
|
+
}
|
|
149
|
+
function isNotCalculatedPenaltyStatus(status) {
|
|
150
|
+
const isNotCalculatedPenaltyArray = [
|
|
151
|
+
types.SubmissionStatus.COMPILATION_ERROR,
|
|
152
|
+
types.SubmissionStatus.PRESENTATION_ERROR,
|
|
153
|
+
types.SubmissionStatus.CONFIGURATION_ERROR,
|
|
154
|
+
types.SubmissionStatus.SYSTEM_ERROR,
|
|
155
|
+
types.SubmissionStatus.CANCELED,
|
|
156
|
+
types.SubmissionStatus.SKIPPED,
|
|
157
|
+
types.SubmissionStatus.UNKNOWN,
|
|
158
|
+
types.SubmissionStatus.UNDEFINED
|
|
159
|
+
];
|
|
160
|
+
return isNotCalculatedPenaltyArray.includes(status);
|
|
51
161
|
}
|
|
52
162
|
|
|
53
163
|
dayjs__default.extend(duration__default);
|
|
@@ -86,6 +196,267 @@ function getTimeDiff(seconds) {
|
|
|
86
196
|
return [two(h), two(m), two(s)].join(":");
|
|
87
197
|
}
|
|
88
198
|
|
|
199
|
+
class CodeforcesGymGhostDATConverter {
|
|
200
|
+
constructor() {
|
|
201
|
+
}
|
|
202
|
+
convert(rank) {
|
|
203
|
+
let res = "";
|
|
204
|
+
res += `@contest "${rank.contest.name}"
|
|
205
|
+
@contlen ${Math.floor(dayjs__default.duration(rank.contest.endTime.diff(rank.contest.startTime)).asMinutes())}
|
|
206
|
+
@problems ${rank.contest.problems.length}
|
|
207
|
+
@teams ${rank.teams.length + 100}
|
|
208
|
+
@submissions ${rank.submissions.length}
|
|
209
|
+
`;
|
|
210
|
+
rank.contest.problems.forEach((p) => {
|
|
211
|
+
res += `@p ${p.label},${p.label},20,0
|
|
212
|
+
`;
|
|
213
|
+
});
|
|
214
|
+
let teamIndex = 1;
|
|
215
|
+
const teamIdMap = /* @__PURE__ */ new Map();
|
|
216
|
+
const submissionsIdMap = /* @__PURE__ */ new Map();
|
|
217
|
+
rank.teams.forEach((team) => {
|
|
218
|
+
let name = team.name;
|
|
219
|
+
if (team.organization) {
|
|
220
|
+
name = `${team.organization} - ${name}`;
|
|
221
|
+
}
|
|
222
|
+
if (team.members) {
|
|
223
|
+
name = `${name} - ${team.membersToString}`;
|
|
224
|
+
}
|
|
225
|
+
res += `@t ${teamIndex},0,1,${name}
|
|
226
|
+
`;
|
|
227
|
+
teamIdMap.set(team.id, teamIndex);
|
|
228
|
+
teamIndex++;
|
|
229
|
+
{
|
|
230
|
+
const mp = /* @__PURE__ */ new Map();
|
|
231
|
+
rank.contest.problems.forEach((p) => {
|
|
232
|
+
mp.set(p.id, 0);
|
|
233
|
+
});
|
|
234
|
+
submissionsIdMap.set(team.id, mp);
|
|
235
|
+
}
|
|
236
|
+
});
|
|
237
|
+
for (let i = 0; i < 100; i++) {
|
|
238
|
+
res += `@t ${teamIndex},0,1,\u041F\u043E\u043F\u043E\u043B\u043D\u0438\u0442\u044C \u043A\u043E\u043C\u0430\u043D\u0434\u0443
|
|
239
|
+
`;
|
|
240
|
+
teamIndex++;
|
|
241
|
+
}
|
|
242
|
+
rank.getSubmissions().forEach((submission) => {
|
|
243
|
+
const teamId = submission.teamId;
|
|
244
|
+
const problemId = submission.problemId;
|
|
245
|
+
const problem = rank.contest.problemsMap.get(problemId);
|
|
246
|
+
if (!problem) {
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
const status = this.submissionStatusToCodeforcesGymDatStatus(submission.status);
|
|
250
|
+
submissionsIdMap.get(teamId).set(problemId, submissionsIdMap.get(teamId).get(problemId) + 1);
|
|
251
|
+
res += `@s ${teamIdMap.get(teamId)},${problem.label},${submissionsIdMap.get(teamId)?.get(problemId)},${submission.timestamp},${status}
|
|
252
|
+
`;
|
|
253
|
+
});
|
|
254
|
+
return res;
|
|
255
|
+
}
|
|
256
|
+
submissionStatusToCodeforcesGymDatStatus(status) {
|
|
257
|
+
if (isAccepted(status)) {
|
|
258
|
+
return "OK";
|
|
259
|
+
}
|
|
260
|
+
if (status === types.SubmissionStatus.WRONG_ANSWER) {
|
|
261
|
+
return "WA";
|
|
262
|
+
}
|
|
263
|
+
if (status === types.SubmissionStatus.TIME_LIMIT_EXCEEDED) {
|
|
264
|
+
return "TL";
|
|
265
|
+
}
|
|
266
|
+
if (status === types.SubmissionStatus.MEMORY_LIMIT_EXCEEDED) {
|
|
267
|
+
return "ML";
|
|
268
|
+
}
|
|
269
|
+
if (status === types.SubmissionStatus.OUTPUT_LIMIT_EXCEEDED) {
|
|
270
|
+
return "IL";
|
|
271
|
+
}
|
|
272
|
+
if (status === types.SubmissionStatus.PRESENTATION_ERROR) {
|
|
273
|
+
return "PE";
|
|
274
|
+
}
|
|
275
|
+
if (status === types.SubmissionStatus.RUNTIME_ERROR) {
|
|
276
|
+
return "RT";
|
|
277
|
+
}
|
|
278
|
+
if (status === types.SubmissionStatus.COMPILATION_ERROR || isNotCalculatedPenaltyStatus(status)) {
|
|
279
|
+
return "CE";
|
|
280
|
+
}
|
|
281
|
+
if (isPending(status)) {
|
|
282
|
+
return "PD";
|
|
283
|
+
}
|
|
284
|
+
return "RJ";
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
var MedalType = /* @__PURE__ */ ((MedalType2) => {
|
|
289
|
+
MedalType2["UNKNOWN"] = "Unknown";
|
|
290
|
+
MedalType2["GOLD"] = "Gold";
|
|
291
|
+
MedalType2["SILVER"] = "Silver";
|
|
292
|
+
MedalType2["BRONZE"] = "Bronze";
|
|
293
|
+
MedalType2["HONORABLE"] = "Honorable";
|
|
294
|
+
return MedalType2;
|
|
295
|
+
})(MedalType || {});
|
|
296
|
+
class Award {
|
|
297
|
+
constructor() {
|
|
298
|
+
this.medalType = "Unknown" /* UNKNOWN */;
|
|
299
|
+
this.minRank = 0;
|
|
300
|
+
this.maxRank = 0;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
function isValidMedalType(medal) {
|
|
304
|
+
const validMedalType = [
|
|
305
|
+
"Gold" /* GOLD */,
|
|
306
|
+
"Silver" /* SILVER */,
|
|
307
|
+
"Bronze" /* BRONZE */,
|
|
308
|
+
"Honorable" /* HONORABLE */
|
|
309
|
+
];
|
|
310
|
+
return validMedalType.includes(medal);
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
class GeneralExcelConverter {
|
|
314
|
+
constructor() {
|
|
315
|
+
}
|
|
316
|
+
convert(oriRank) {
|
|
317
|
+
const rank = ___default.cloneDeep(oriRank);
|
|
318
|
+
rank.options.disableFilterTeamsByGroup();
|
|
319
|
+
rank.options.disableFilterSubmissionByTimestamp();
|
|
320
|
+
const workbook = XLSX__namespace.utils.book_new();
|
|
321
|
+
for (const [k, v] of rank.contest.group) {
|
|
322
|
+
rank.options.setGroup(k);
|
|
323
|
+
rank.buildRank();
|
|
324
|
+
const sheet = this.convertToSheet(rank);
|
|
325
|
+
XLSX__namespace.utils.book_append_sheet(workbook, sheet, v.names.get(v.defaultLang));
|
|
326
|
+
}
|
|
327
|
+
return workbook;
|
|
328
|
+
}
|
|
329
|
+
convertAndWrite(rank, filename) {
|
|
330
|
+
return XLSX__namespace.writeFile(
|
|
331
|
+
this.convert(rank),
|
|
332
|
+
filename,
|
|
333
|
+
{
|
|
334
|
+
compression: true
|
|
335
|
+
}
|
|
336
|
+
);
|
|
337
|
+
}
|
|
338
|
+
convertToSheet(rank) {
|
|
339
|
+
const aoa = this.convertToAoa(rank);
|
|
340
|
+
const sheet = XLSX__namespace.utils.aoa_to_sheet(aoa);
|
|
341
|
+
const cols = [];
|
|
342
|
+
const head = aoa[1];
|
|
343
|
+
for (let j = 0; j < head.length; j++) {
|
|
344
|
+
let wch = 10;
|
|
345
|
+
for (let i = 1; i < aoa.length; i++) {
|
|
346
|
+
wch = Math.max(wch, stringWidth__default(aoa[i][j]) + 2);
|
|
347
|
+
}
|
|
348
|
+
cols.push({
|
|
349
|
+
wch
|
|
350
|
+
});
|
|
351
|
+
}
|
|
352
|
+
sheet["!cols"] = cols;
|
|
353
|
+
{
|
|
354
|
+
const mergeRange = { s: { r: 0, c: 0 }, e: { r: 0, c: head.length - 1 } };
|
|
355
|
+
const merges = [{ s: mergeRange.s, e: mergeRange.e }];
|
|
356
|
+
sheet["!merges"] = merges;
|
|
357
|
+
}
|
|
358
|
+
const font = {
|
|
359
|
+
name: "Arial Unicode MS",
|
|
360
|
+
bold: false,
|
|
361
|
+
italic: false,
|
|
362
|
+
sz: 12
|
|
363
|
+
};
|
|
364
|
+
const borderStyle = {
|
|
365
|
+
style: "thin"
|
|
366
|
+
};
|
|
367
|
+
const cellStyle = {
|
|
368
|
+
alignment: {
|
|
369
|
+
vertical: "center",
|
|
370
|
+
horizontal: "center"
|
|
371
|
+
},
|
|
372
|
+
border: {
|
|
373
|
+
top: borderStyle,
|
|
374
|
+
bottom: borderStyle,
|
|
375
|
+
left: borderStyle,
|
|
376
|
+
right: borderStyle
|
|
377
|
+
},
|
|
378
|
+
font
|
|
379
|
+
};
|
|
380
|
+
for (let i = 1; i < aoa.length; i++) {
|
|
381
|
+
for (let j = 0; j < aoa[i].length; j++) {
|
|
382
|
+
const cellAddress = XLSX__namespace.utils.encode_cell({ r: i, c: j });
|
|
383
|
+
const cell = sheet[cellAddress];
|
|
384
|
+
cell.s = cellStyle;
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
{
|
|
388
|
+
const cellAddress = XLSX__namespace.utils.encode_cell({ r: 0, c: 0 });
|
|
389
|
+
const cell = sheet[cellAddress];
|
|
390
|
+
const titleStyle = ___default.cloneDeep(cellStyle);
|
|
391
|
+
titleStyle.font.sz = 28;
|
|
392
|
+
titleStyle.font.bold = true;
|
|
393
|
+
cell.s = titleStyle;
|
|
394
|
+
}
|
|
395
|
+
return sheet;
|
|
396
|
+
}
|
|
397
|
+
convertToAoa(rank) {
|
|
398
|
+
const aoa = [];
|
|
399
|
+
const enableAwards = rank.contest.isEnableAwards(rank.options.group);
|
|
400
|
+
{
|
|
401
|
+
aoa.push([rank.contest.name]);
|
|
402
|
+
}
|
|
403
|
+
{
|
|
404
|
+
const head = [];
|
|
405
|
+
head.push("Rank");
|
|
406
|
+
if (rank.contest.organization) {
|
|
407
|
+
head.push(`${rank.contest.organization} Rank`);
|
|
408
|
+
head.push(rank.contest.organization);
|
|
409
|
+
}
|
|
410
|
+
head.push("Name", "Solved", "Penalty", ...rank.contest.problems.map((p) => p.label), "Dict");
|
|
411
|
+
if (enableAwards) {
|
|
412
|
+
head.push("Medal");
|
|
413
|
+
}
|
|
414
|
+
aoa.push(head);
|
|
415
|
+
}
|
|
416
|
+
for (const team of rank.teams) {
|
|
417
|
+
const arr = [];
|
|
418
|
+
arr.push(team.rank.toString());
|
|
419
|
+
if (team.organization) {
|
|
420
|
+
if (team.organizationRank !== -1) {
|
|
421
|
+
arr.push(team.organizationRank.toString());
|
|
422
|
+
} else {
|
|
423
|
+
arr.push("");
|
|
424
|
+
}
|
|
425
|
+
arr.push(team.organization);
|
|
426
|
+
}
|
|
427
|
+
arr.push(team.name, team.solvedProblemNum.toString(), team.penaltyToMinute.toString());
|
|
428
|
+
for (const p of team.problemStatistics) {
|
|
429
|
+
if (p.isUnSubmitted) {
|
|
430
|
+
arr.push("-");
|
|
431
|
+
}
|
|
432
|
+
if (p.isSolved) {
|
|
433
|
+
arr.push(`+${p.totalCount}(${p.solvedTimestampToMinute})`);
|
|
434
|
+
}
|
|
435
|
+
if (p.isWrongAnswer) {
|
|
436
|
+
arr.push(`-${p.failedCount}`);
|
|
437
|
+
}
|
|
438
|
+
if (p.isPending) {
|
|
439
|
+
arr.push(`? ${p.failedCount} + ${p.pendingCount}`);
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
arr.push(`${team.dict}%`);
|
|
443
|
+
if (enableAwards) {
|
|
444
|
+
const medals = team.awards.filter((a) => isValidMedalType(a)).map((a) => a.toString());
|
|
445
|
+
arr.push(medals.join(", "));
|
|
446
|
+
}
|
|
447
|
+
aoa.push(arr);
|
|
448
|
+
}
|
|
449
|
+
return aoa;
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
function calcDict(attemptedNum, solvedNum) {
|
|
454
|
+
if (solvedNum === 0) {
|
|
455
|
+
return 0;
|
|
456
|
+
}
|
|
457
|
+
return Math.floor((attemptedNum - solvedNum) * 100 / attemptedNum);
|
|
458
|
+
}
|
|
459
|
+
|
|
89
460
|
class ProblemStatistics {
|
|
90
461
|
constructor() {
|
|
91
462
|
this.acceptedNum = 0;
|
|
@@ -191,6 +562,12 @@ class TeamProblemStatistics {
|
|
|
191
562
|
}
|
|
192
563
|
return Math.floor(this.solvedTimestamp / 60) * 60 + this.failedCount * this.contestPenalty;
|
|
193
564
|
}
|
|
565
|
+
get penaltyToMinute() {
|
|
566
|
+
return Math.floor(this.penalty / 60);
|
|
567
|
+
}
|
|
568
|
+
get solvedTimestampToMinute() {
|
|
569
|
+
return Math.floor(this.solvedTimestamp / 60);
|
|
570
|
+
}
|
|
194
571
|
}
|
|
195
572
|
|
|
196
573
|
class Group {
|
|
@@ -276,6 +653,15 @@ class Contest {
|
|
|
276
653
|
const pass = baseTime.diff(this.startTime, "s");
|
|
277
654
|
return Math.round(pass * 100 / total);
|
|
278
655
|
}
|
|
656
|
+
isEnableAwards(group) {
|
|
657
|
+
if (!this.awards) {
|
|
658
|
+
return false;
|
|
659
|
+
}
|
|
660
|
+
if (!this.awards.has(group)) {
|
|
661
|
+
return false;
|
|
662
|
+
}
|
|
663
|
+
return true;
|
|
664
|
+
}
|
|
279
665
|
}
|
|
280
666
|
function createContest(contestJSON) {
|
|
281
667
|
const c = new Contest();
|
|
@@ -440,208 +826,6 @@ function createContestIndexList(contestListJSON) {
|
|
|
440
826
|
return contestIndexList;
|
|
441
827
|
}
|
|
442
828
|
|
|
443
|
-
function stringToSubmissionStatus(status) {
|
|
444
|
-
status = status.toUpperCase().replace(" ", "_");
|
|
445
|
-
if (["OK", "AC", types.SubmissionStatus.ACCEPTED.toString()].includes(status)) {
|
|
446
|
-
return types.SubmissionStatus.ACCEPTED;
|
|
447
|
-
}
|
|
448
|
-
if ([types.SubmissionStatus.CORRECT.toString()].includes(status)) {
|
|
449
|
-
return types.SubmissionStatus.ACCEPTED;
|
|
450
|
-
}
|
|
451
|
-
if ([types.SubmissionStatus.PARTIALLY_CORRECT.toString()].includes(status)) {
|
|
452
|
-
return types.SubmissionStatus.PARTIALLY_CORRECT;
|
|
453
|
-
}
|
|
454
|
-
if (["WA", types.SubmissionStatus.WRONG_ANSWER.toString()].includes(status)) {
|
|
455
|
-
return types.SubmissionStatus.WRONG_ANSWER;
|
|
456
|
-
}
|
|
457
|
-
if (["RJ", "INCORRECT", types.SubmissionStatus.REJECTED.toString()].includes(status)) {
|
|
458
|
-
return types.SubmissionStatus.REJECTED;
|
|
459
|
-
}
|
|
460
|
-
if (["PD", types.SubmissionStatus.PENDING.toString()].includes(status)) {
|
|
461
|
-
return types.SubmissionStatus.PENDING;
|
|
462
|
-
}
|
|
463
|
-
if ([types.SubmissionStatus.WAITING.toString()].includes(status)) {
|
|
464
|
-
return types.SubmissionStatus.WAITING;
|
|
465
|
-
}
|
|
466
|
-
if ([types.SubmissionStatus.JUDGING.toString()].includes(status)) {
|
|
467
|
-
return types.SubmissionStatus.JUDGING;
|
|
468
|
-
}
|
|
469
|
-
if ([types.SubmissionStatus.FROZEN.toString()].includes(status)) {
|
|
470
|
-
return types.SubmissionStatus.FROZEN;
|
|
471
|
-
}
|
|
472
|
-
if (["CE", types.SubmissionStatus.COMPILATION_ERROR.toString()].includes(status)) {
|
|
473
|
-
return types.SubmissionStatus.COMPILATION_ERROR;
|
|
474
|
-
}
|
|
475
|
-
if (["PE", types.SubmissionStatus.PRESENTATION_ERROR.toString()].includes(status)) {
|
|
476
|
-
return types.SubmissionStatus.PRESENTATION_ERROR;
|
|
477
|
-
}
|
|
478
|
-
if (["TL", "TLE", types.SubmissionStatus.TIME_LIMIT_EXCEEDED.toString()].includes(status)) {
|
|
479
|
-
return types.SubmissionStatus.TIME_LIMIT_EXCEEDED;
|
|
480
|
-
}
|
|
481
|
-
if (["ML", "MLE", types.SubmissionStatus.MEMORY_LIMIT_EXCEEDED.toString()].includes(status)) {
|
|
482
|
-
return types.SubmissionStatus.MEMORY_LIMIT_EXCEEDED;
|
|
483
|
-
}
|
|
484
|
-
if (["OL", "OLE", types.SubmissionStatus.OUTPUT_LIMIT_EXCEEDED.toString()].includes(status)) {
|
|
485
|
-
return types.SubmissionStatus.OUTPUT_LIMIT_EXCEEDED;
|
|
486
|
-
}
|
|
487
|
-
if (["IL", "ILE", types.SubmissionStatus.IDLENESS_LIMIT_EXCEEDED.toString()].includes(status)) {
|
|
488
|
-
return types.SubmissionStatus.IDLENESS_LIMIT_EXCEEDED;
|
|
489
|
-
}
|
|
490
|
-
if (["RT", "RE", "RTE", types.SubmissionStatus.RUNTIME_ERROR.toString()].includes(status)) {
|
|
491
|
-
return types.SubmissionStatus.RUNTIME_ERROR;
|
|
492
|
-
}
|
|
493
|
-
if (["JE", types.SubmissionStatus.JUDGEMENT_FAILED.toString()].includes(status)) {
|
|
494
|
-
return types.SubmissionStatus.JUDGEMENT_FAILED;
|
|
495
|
-
}
|
|
496
|
-
if (["SE", types.SubmissionStatus.SYSTEM_ERROR.toString()].includes(status)) {
|
|
497
|
-
return types.SubmissionStatus.SYSTEM_ERROR;
|
|
498
|
-
}
|
|
499
|
-
if ([types.SubmissionStatus.HACKED.toString()].includes(status)) {
|
|
500
|
-
return types.SubmissionStatus.HACKED;
|
|
501
|
-
}
|
|
502
|
-
if ([types.SubmissionStatus.CONFIGURATION_ERROR.toString()].includes(status)) {
|
|
503
|
-
return types.SubmissionStatus.CONFIGURATION_ERROR;
|
|
504
|
-
}
|
|
505
|
-
if ([types.SubmissionStatus.CANCELED.toString()].includes(status)) {
|
|
506
|
-
return types.SubmissionStatus.CANCELED;
|
|
507
|
-
}
|
|
508
|
-
if ([types.SubmissionStatus.SKIPPED.toString()].includes(status)) {
|
|
509
|
-
return types.SubmissionStatus.SKIPPED;
|
|
510
|
-
}
|
|
511
|
-
if ([types.SubmissionStatus.SECURITY_VIOLATED.toString()].includes(status)) {
|
|
512
|
-
return types.SubmissionStatus.SECURITY_VIOLATED;
|
|
513
|
-
}
|
|
514
|
-
if ([types.SubmissionStatus.DENIAL_OF_JUDGEMENT.toString()].includes(status)) {
|
|
515
|
-
return types.SubmissionStatus.DENIAL_OF_JUDGEMENT;
|
|
516
|
-
}
|
|
517
|
-
return types.SubmissionStatus.UNKNOWN;
|
|
518
|
-
}
|
|
519
|
-
function isAccepted(status) {
|
|
520
|
-
const acceptedArray = [types.SubmissionStatus.ACCEPTED, types.SubmissionStatus.CORRECT];
|
|
521
|
-
return acceptedArray.includes(status);
|
|
522
|
-
}
|
|
523
|
-
function isRejected(status) {
|
|
524
|
-
const rejectArray = [
|
|
525
|
-
types.SubmissionStatus.RUNTIME_ERROR,
|
|
526
|
-
types.SubmissionStatus.TIME_LIMIT_EXCEEDED,
|
|
527
|
-
types.SubmissionStatus.MEMORY_LIMIT_EXCEEDED,
|
|
528
|
-
types.SubmissionStatus.OUTPUT_LIMIT_EXCEEDED,
|
|
529
|
-
types.SubmissionStatus.IDLENESS_LIMIT_EXCEEDED,
|
|
530
|
-
types.SubmissionStatus.WRONG_ANSWER,
|
|
531
|
-
types.SubmissionStatus.REJECTED,
|
|
532
|
-
types.SubmissionStatus.JUDGEMENT_FAILED,
|
|
533
|
-
types.SubmissionStatus.HACKED
|
|
534
|
-
];
|
|
535
|
-
return rejectArray.includes(status);
|
|
536
|
-
}
|
|
537
|
-
function isPending(status) {
|
|
538
|
-
const pendingArray = [
|
|
539
|
-
types.SubmissionStatus.PENDING,
|
|
540
|
-
types.SubmissionStatus.WAITING,
|
|
541
|
-
types.SubmissionStatus.JUDGING,
|
|
542
|
-
types.SubmissionStatus.FROZEN
|
|
543
|
-
];
|
|
544
|
-
return pendingArray.includes(status);
|
|
545
|
-
}
|
|
546
|
-
function isNotCalculatedPenaltyStatus(status) {
|
|
547
|
-
const isNotCalculatedPenaltyArray = [
|
|
548
|
-
types.SubmissionStatus.COMPILATION_ERROR,
|
|
549
|
-
types.SubmissionStatus.PRESENTATION_ERROR,
|
|
550
|
-
types.SubmissionStatus.CONFIGURATION_ERROR,
|
|
551
|
-
types.SubmissionStatus.SYSTEM_ERROR,
|
|
552
|
-
types.SubmissionStatus.CANCELED,
|
|
553
|
-
types.SubmissionStatus.SKIPPED,
|
|
554
|
-
types.SubmissionStatus.UNKNOWN,
|
|
555
|
-
types.SubmissionStatus.UNDEFINED
|
|
556
|
-
];
|
|
557
|
-
return isNotCalculatedPenaltyArray.includes(status);
|
|
558
|
-
}
|
|
559
|
-
|
|
560
|
-
function submissionStatusToCodeforcesGymDatStatus(status) {
|
|
561
|
-
if (isAccepted(status)) {
|
|
562
|
-
return "OK";
|
|
563
|
-
}
|
|
564
|
-
if (status === types.SubmissionStatus.WRONG_ANSWER) {
|
|
565
|
-
return "WA";
|
|
566
|
-
}
|
|
567
|
-
if (status === types.SubmissionStatus.TIME_LIMIT_EXCEEDED) {
|
|
568
|
-
return "TL";
|
|
569
|
-
}
|
|
570
|
-
if (status === types.SubmissionStatus.MEMORY_LIMIT_EXCEEDED) {
|
|
571
|
-
return "ML";
|
|
572
|
-
}
|
|
573
|
-
if (status === types.SubmissionStatus.OUTPUT_LIMIT_EXCEEDED) {
|
|
574
|
-
return "IL";
|
|
575
|
-
}
|
|
576
|
-
if (status === types.SubmissionStatus.PRESENTATION_ERROR) {
|
|
577
|
-
return "PE";
|
|
578
|
-
}
|
|
579
|
-
if (status === types.SubmissionStatus.RUNTIME_ERROR) {
|
|
580
|
-
return "RT";
|
|
581
|
-
}
|
|
582
|
-
if (status === types.SubmissionStatus.COMPILATION_ERROR || isNotCalculatedPenaltyStatus(status)) {
|
|
583
|
-
return "CE";
|
|
584
|
-
}
|
|
585
|
-
if (isPending(status)) {
|
|
586
|
-
return "PD";
|
|
587
|
-
}
|
|
588
|
-
return "RJ";
|
|
589
|
-
}
|
|
590
|
-
function rankToCodeforcesGymDAT(rank) {
|
|
591
|
-
let res = "";
|
|
592
|
-
res += `@contest "${rank.contest.name}"
|
|
593
|
-
@contlen ${Math.floor(dayjs__default.duration(rank.contest.endTime.diff(rank.contest.startTime)).asMinutes())}
|
|
594
|
-
@problems ${rank.contest.problems.length}
|
|
595
|
-
@teams ${rank.teams.length + 100}
|
|
596
|
-
@submissions ${rank.submissions.length}
|
|
597
|
-
`;
|
|
598
|
-
rank.contest.problems.forEach((p) => {
|
|
599
|
-
res += `@p ${p.label},${p.label},20,0
|
|
600
|
-
`;
|
|
601
|
-
});
|
|
602
|
-
let teamIndex = 1;
|
|
603
|
-
const teamIdMap = /* @__PURE__ */ new Map();
|
|
604
|
-
const submissionsIdMap = /* @__PURE__ */ new Map();
|
|
605
|
-
rank.teams.forEach((team) => {
|
|
606
|
-
let name = team.name;
|
|
607
|
-
if (team.organization) {
|
|
608
|
-
name = `${team.organization} - ${name}`;
|
|
609
|
-
}
|
|
610
|
-
if (team.members) {
|
|
611
|
-
name = `${name} - ${team.membersToString}`;
|
|
612
|
-
}
|
|
613
|
-
res += `@t ${teamIndex},0,1,${name}
|
|
614
|
-
`;
|
|
615
|
-
teamIdMap.set(team.id, teamIndex);
|
|
616
|
-
teamIndex++;
|
|
617
|
-
{
|
|
618
|
-
const mp = /* @__PURE__ */ new Map();
|
|
619
|
-
rank.contest.problems.forEach((p) => {
|
|
620
|
-
mp.set(p.id, 0);
|
|
621
|
-
});
|
|
622
|
-
submissionsIdMap.set(team.id, mp);
|
|
623
|
-
}
|
|
624
|
-
});
|
|
625
|
-
for (let i = 0; i < 100; i++) {
|
|
626
|
-
res += `@t ${teamIndex},0,1,\u041F\u043E\u043F\u043E\u043B\u043D\u0438\u0442\u044C \u043A\u043E\u043C\u0430\u043D\u0434\u0443
|
|
627
|
-
`;
|
|
628
|
-
teamIndex++;
|
|
629
|
-
}
|
|
630
|
-
rank.getSubmissions().forEach((submission) => {
|
|
631
|
-
const teamId = submission.teamId;
|
|
632
|
-
const problemId = submission.problemId;
|
|
633
|
-
const problem = rank.contest.problemsMap.get(problemId);
|
|
634
|
-
if (!problem) {
|
|
635
|
-
return;
|
|
636
|
-
}
|
|
637
|
-
const status = submissionStatusToCodeforcesGymDatStatus(submission.status);
|
|
638
|
-
submissionsIdMap.get(teamId).set(problemId, submissionsIdMap.get(teamId).get(problemId) + 1);
|
|
639
|
-
res += `@s ${teamIdMap.get(teamId)},${problem.label},${submissionsIdMap.get(teamId)?.get(problemId)},${submission.timestamp},${status}
|
|
640
|
-
`;
|
|
641
|
-
});
|
|
642
|
-
return res;
|
|
643
|
-
}
|
|
644
|
-
|
|
645
829
|
function getImageSource(image) {
|
|
646
830
|
if (image?.url) {
|
|
647
831
|
return image.url;
|
|
@@ -704,6 +888,7 @@ class Team {
|
|
|
704
888
|
this.problemStatisticsMap = /* @__PURE__ */ new Map();
|
|
705
889
|
this.submissions = [];
|
|
706
890
|
this.placeChartPoints = [];
|
|
891
|
+
this.awards = [];
|
|
707
892
|
}
|
|
708
893
|
get penaltyToMinute() {
|
|
709
894
|
return Math.floor(this.penalty / 60);
|
|
@@ -1245,9 +1430,11 @@ class Resolver extends Rank {
|
|
|
1245
1430
|
|
|
1246
1431
|
exports.dayjs = dayjs__default;
|
|
1247
1432
|
exports.Award = Award;
|
|
1433
|
+
exports.CodeforcesGymGhostDATConverter = CodeforcesGymGhostDATConverter;
|
|
1248
1434
|
exports.Contest = Contest;
|
|
1249
1435
|
exports.ContestIndex = ContestIndex;
|
|
1250
1436
|
exports.ContestIndexConfig = ContestIndexConfig;
|
|
1437
|
+
exports.GeneralExcelConverter = GeneralExcelConverter;
|
|
1251
1438
|
exports.MedalType = MedalType;
|
|
1252
1439
|
exports.PlaceChartPointData = PlaceChartPointData;
|
|
1253
1440
|
exports.Problem = Problem;
|
|
@@ -1278,5 +1465,5 @@ exports.isAccepted = isAccepted;
|
|
|
1278
1465
|
exports.isNotCalculatedPenaltyStatus = isNotCalculatedPenaltyStatus;
|
|
1279
1466
|
exports.isPending = isPending;
|
|
1280
1467
|
exports.isRejected = isRejected;
|
|
1281
|
-
exports.
|
|
1468
|
+
exports.isValidMedalType = isValidMedalType;
|
|
1282
1469
|
exports.stringToSubmissionStatus = stringToSubmissionStatus;
|