@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.mjs CHANGED
@@ -1,3 +1,4 @@
1
+ import { SubmissionStatus, ContestState } from '@xcpcio/types';
1
2
  import dayjs from 'dayjs';
2
3
  export { default as dayjs } from 'dayjs';
3
4
  import duration from 'dayjs/plugin/duration';
@@ -8,30 +9,125 @@ import isSameOrBefore from 'dayjs/plugin/isSameOrBefore';
8
9
  import isSameOrAfter from 'dayjs/plugin/isSameOrAfter';
9
10
  import minMax from 'dayjs/plugin/minMax';
10
11
  import relativeTime from 'dayjs/plugin/relativeTime';
11
- import { ContestState, SubmissionStatus } from '@xcpcio/types';
12
12
  import _ from 'lodash';
13
+ import * as XLSX from 'xlsx-js-style';
14
+ import stringWidth from 'string-width';
13
15
 
14
- var MedalType = /* @__PURE__ */ ((MedalType2) => {
15
- MedalType2[MedalType2["UNKNOWN"] = 0] = "UNKNOWN";
16
- MedalType2[MedalType2["GOLD"] = 1] = "GOLD";
17
- MedalType2[MedalType2["SILVER"] = 2] = "SILVER";
18
- MedalType2[MedalType2["BRONZE"] = 3] = "BRONZE";
19
- MedalType2[MedalType2["HONORABLE"] = 4] = "HONORABLE";
20
- return MedalType2;
21
- })(MedalType || {});
22
- class Award {
23
- constructor() {
24
- this.medalType = 0 /* UNKNOWN */;
25
- this.minRank = 0;
26
- this.maxRank = 0;
16
+ function stringToSubmissionStatus(status) {
17
+ status = status.toUpperCase().replace(" ", "_");
18
+ if (["OK", "AC", SubmissionStatus.ACCEPTED.toString()].includes(status)) {
19
+ return SubmissionStatus.ACCEPTED;
27
20
  }
28
- }
29
-
30
- function calcDict(attemptedNum, solvedNum) {
31
- if (solvedNum === 0) {
32
- return 0;
21
+ if ([SubmissionStatus.CORRECT.toString()].includes(status)) {
22
+ return SubmissionStatus.ACCEPTED;
33
23
  }
34
- return Math.floor((attemptedNum - solvedNum) * 100 / attemptedNum);
24
+ if ([SubmissionStatus.PARTIALLY_CORRECT.toString()].includes(status)) {
25
+ return SubmissionStatus.PARTIALLY_CORRECT;
26
+ }
27
+ if (["WA", SubmissionStatus.WRONG_ANSWER.toString()].includes(status)) {
28
+ return SubmissionStatus.WRONG_ANSWER;
29
+ }
30
+ if (["RJ", "INCORRECT", SubmissionStatus.REJECTED.toString()].includes(status)) {
31
+ return SubmissionStatus.REJECTED;
32
+ }
33
+ if (["PD", SubmissionStatus.PENDING.toString()].includes(status)) {
34
+ return SubmissionStatus.PENDING;
35
+ }
36
+ if ([SubmissionStatus.WAITING.toString()].includes(status)) {
37
+ return SubmissionStatus.WAITING;
38
+ }
39
+ if ([SubmissionStatus.JUDGING.toString()].includes(status)) {
40
+ return SubmissionStatus.JUDGING;
41
+ }
42
+ if ([SubmissionStatus.FROZEN.toString()].includes(status)) {
43
+ return SubmissionStatus.FROZEN;
44
+ }
45
+ if (["CE", SubmissionStatus.COMPILATION_ERROR.toString()].includes(status)) {
46
+ return SubmissionStatus.COMPILATION_ERROR;
47
+ }
48
+ if (["PE", SubmissionStatus.PRESENTATION_ERROR.toString()].includes(status)) {
49
+ return SubmissionStatus.PRESENTATION_ERROR;
50
+ }
51
+ if (["TL", "TLE", SubmissionStatus.TIME_LIMIT_EXCEEDED.toString()].includes(status)) {
52
+ return SubmissionStatus.TIME_LIMIT_EXCEEDED;
53
+ }
54
+ if (["ML", "MLE", SubmissionStatus.MEMORY_LIMIT_EXCEEDED.toString()].includes(status)) {
55
+ return SubmissionStatus.MEMORY_LIMIT_EXCEEDED;
56
+ }
57
+ if (["OL", "OLE", SubmissionStatus.OUTPUT_LIMIT_EXCEEDED.toString()].includes(status)) {
58
+ return SubmissionStatus.OUTPUT_LIMIT_EXCEEDED;
59
+ }
60
+ if (["IL", "ILE", SubmissionStatus.IDLENESS_LIMIT_EXCEEDED.toString()].includes(status)) {
61
+ return SubmissionStatus.IDLENESS_LIMIT_EXCEEDED;
62
+ }
63
+ if (["RT", "RE", "RTE", SubmissionStatus.RUNTIME_ERROR.toString()].includes(status)) {
64
+ return SubmissionStatus.RUNTIME_ERROR;
65
+ }
66
+ if (["JE", SubmissionStatus.JUDGEMENT_FAILED.toString()].includes(status)) {
67
+ return SubmissionStatus.JUDGEMENT_FAILED;
68
+ }
69
+ if (["SE", SubmissionStatus.SYSTEM_ERROR.toString()].includes(status)) {
70
+ return SubmissionStatus.SYSTEM_ERROR;
71
+ }
72
+ if ([SubmissionStatus.HACKED.toString()].includes(status)) {
73
+ return SubmissionStatus.HACKED;
74
+ }
75
+ if ([SubmissionStatus.CONFIGURATION_ERROR.toString()].includes(status)) {
76
+ return SubmissionStatus.CONFIGURATION_ERROR;
77
+ }
78
+ if ([SubmissionStatus.CANCELED.toString()].includes(status)) {
79
+ return SubmissionStatus.CANCELED;
80
+ }
81
+ if ([SubmissionStatus.SKIPPED.toString()].includes(status)) {
82
+ return SubmissionStatus.SKIPPED;
83
+ }
84
+ if ([SubmissionStatus.SECURITY_VIOLATED.toString()].includes(status)) {
85
+ return SubmissionStatus.SECURITY_VIOLATED;
86
+ }
87
+ if ([SubmissionStatus.DENIAL_OF_JUDGEMENT.toString()].includes(status)) {
88
+ return SubmissionStatus.DENIAL_OF_JUDGEMENT;
89
+ }
90
+ return SubmissionStatus.UNKNOWN;
91
+ }
92
+ function isAccepted(status) {
93
+ const acceptedArray = [SubmissionStatus.ACCEPTED, SubmissionStatus.CORRECT];
94
+ return acceptedArray.includes(status);
95
+ }
96
+ function isRejected(status) {
97
+ const rejectArray = [
98
+ SubmissionStatus.RUNTIME_ERROR,
99
+ SubmissionStatus.TIME_LIMIT_EXCEEDED,
100
+ SubmissionStatus.MEMORY_LIMIT_EXCEEDED,
101
+ SubmissionStatus.OUTPUT_LIMIT_EXCEEDED,
102
+ SubmissionStatus.IDLENESS_LIMIT_EXCEEDED,
103
+ SubmissionStatus.WRONG_ANSWER,
104
+ SubmissionStatus.REJECTED,
105
+ SubmissionStatus.JUDGEMENT_FAILED,
106
+ SubmissionStatus.HACKED
107
+ ];
108
+ return rejectArray.includes(status);
109
+ }
110
+ function isPending(status) {
111
+ const pendingArray = [
112
+ SubmissionStatus.PENDING,
113
+ SubmissionStatus.WAITING,
114
+ SubmissionStatus.JUDGING,
115
+ SubmissionStatus.FROZEN
116
+ ];
117
+ return pendingArray.includes(status);
118
+ }
119
+ function isNotCalculatedPenaltyStatus(status) {
120
+ const isNotCalculatedPenaltyArray = [
121
+ SubmissionStatus.COMPILATION_ERROR,
122
+ SubmissionStatus.PRESENTATION_ERROR,
123
+ SubmissionStatus.CONFIGURATION_ERROR,
124
+ SubmissionStatus.SYSTEM_ERROR,
125
+ SubmissionStatus.CANCELED,
126
+ SubmissionStatus.SKIPPED,
127
+ SubmissionStatus.UNKNOWN,
128
+ SubmissionStatus.UNDEFINED
129
+ ];
130
+ return isNotCalculatedPenaltyArray.includes(status);
35
131
  }
36
132
 
37
133
  dayjs.extend(duration);
@@ -70,6 +166,267 @@ function getTimeDiff(seconds) {
70
166
  return [two(h), two(m), two(s)].join(":");
71
167
  }
72
168
 
169
+ class CodeforcesGymGhostDATConverter {
170
+ constructor() {
171
+ }
172
+ convert(rank) {
173
+ let res = "";
174
+ res += `@contest "${rank.contest.name}"
175
+ @contlen ${Math.floor(dayjs.duration(rank.contest.endTime.diff(rank.contest.startTime)).asMinutes())}
176
+ @problems ${rank.contest.problems.length}
177
+ @teams ${rank.teams.length + 100}
178
+ @submissions ${rank.submissions.length}
179
+ `;
180
+ rank.contest.problems.forEach((p) => {
181
+ res += `@p ${p.label},${p.label},20,0
182
+ `;
183
+ });
184
+ let teamIndex = 1;
185
+ const teamIdMap = /* @__PURE__ */ new Map();
186
+ const submissionsIdMap = /* @__PURE__ */ new Map();
187
+ rank.teams.forEach((team) => {
188
+ let name = team.name;
189
+ if (team.organization) {
190
+ name = `${team.organization} - ${name}`;
191
+ }
192
+ if (team.members) {
193
+ name = `${name} - ${team.membersToString}`;
194
+ }
195
+ res += `@t ${teamIndex},0,1,${name}
196
+ `;
197
+ teamIdMap.set(team.id, teamIndex);
198
+ teamIndex++;
199
+ {
200
+ const mp = /* @__PURE__ */ new Map();
201
+ rank.contest.problems.forEach((p) => {
202
+ mp.set(p.id, 0);
203
+ });
204
+ submissionsIdMap.set(team.id, mp);
205
+ }
206
+ });
207
+ for (let i = 0; i < 100; i++) {
208
+ res += `@t ${teamIndex},0,1,\u041F\u043E\u043F\u043E\u043B\u043D\u0438\u0442\u044C \u043A\u043E\u043C\u0430\u043D\u0434\u0443
209
+ `;
210
+ teamIndex++;
211
+ }
212
+ rank.getSubmissions().forEach((submission) => {
213
+ const teamId = submission.teamId;
214
+ const problemId = submission.problemId;
215
+ const problem = rank.contest.problemsMap.get(problemId);
216
+ if (!problem) {
217
+ return;
218
+ }
219
+ const status = this.submissionStatusToCodeforcesGymDatStatus(submission.status);
220
+ submissionsIdMap.get(teamId).set(problemId, submissionsIdMap.get(teamId).get(problemId) + 1);
221
+ res += `@s ${teamIdMap.get(teamId)},${problem.label},${submissionsIdMap.get(teamId)?.get(problemId)},${submission.timestamp},${status}
222
+ `;
223
+ });
224
+ return res;
225
+ }
226
+ submissionStatusToCodeforcesGymDatStatus(status) {
227
+ if (isAccepted(status)) {
228
+ return "OK";
229
+ }
230
+ if (status === SubmissionStatus.WRONG_ANSWER) {
231
+ return "WA";
232
+ }
233
+ if (status === SubmissionStatus.TIME_LIMIT_EXCEEDED) {
234
+ return "TL";
235
+ }
236
+ if (status === SubmissionStatus.MEMORY_LIMIT_EXCEEDED) {
237
+ return "ML";
238
+ }
239
+ if (status === SubmissionStatus.OUTPUT_LIMIT_EXCEEDED) {
240
+ return "IL";
241
+ }
242
+ if (status === SubmissionStatus.PRESENTATION_ERROR) {
243
+ return "PE";
244
+ }
245
+ if (status === SubmissionStatus.RUNTIME_ERROR) {
246
+ return "RT";
247
+ }
248
+ if (status === SubmissionStatus.COMPILATION_ERROR || isNotCalculatedPenaltyStatus(status)) {
249
+ return "CE";
250
+ }
251
+ if (isPending(status)) {
252
+ return "PD";
253
+ }
254
+ return "RJ";
255
+ }
256
+ }
257
+
258
+ var MedalType = /* @__PURE__ */ ((MedalType2) => {
259
+ MedalType2["UNKNOWN"] = "Unknown";
260
+ MedalType2["GOLD"] = "Gold";
261
+ MedalType2["SILVER"] = "Silver";
262
+ MedalType2["BRONZE"] = "Bronze";
263
+ MedalType2["HONORABLE"] = "Honorable";
264
+ return MedalType2;
265
+ })(MedalType || {});
266
+ class Award {
267
+ constructor() {
268
+ this.medalType = "Unknown" /* UNKNOWN */;
269
+ this.minRank = 0;
270
+ this.maxRank = 0;
271
+ }
272
+ }
273
+ function isValidMedalType(medal) {
274
+ const validMedalType = [
275
+ "Gold" /* GOLD */,
276
+ "Silver" /* SILVER */,
277
+ "Bronze" /* BRONZE */,
278
+ "Honorable" /* HONORABLE */
279
+ ];
280
+ return validMedalType.includes(medal);
281
+ }
282
+
283
+ class GeneralExcelConverter {
284
+ constructor() {
285
+ }
286
+ convert(oriRank) {
287
+ const rank = _.cloneDeep(oriRank);
288
+ rank.options.disableFilterTeamsByGroup();
289
+ rank.options.disableFilterSubmissionByTimestamp();
290
+ const workbook = XLSX.utils.book_new();
291
+ for (const [k, v] of rank.contest.group) {
292
+ rank.options.setGroup(k);
293
+ rank.buildRank();
294
+ const sheet = this.convertToSheet(rank);
295
+ XLSX.utils.book_append_sheet(workbook, sheet, v.names.get(v.defaultLang));
296
+ }
297
+ return workbook;
298
+ }
299
+ convertAndWrite(rank, filename) {
300
+ return XLSX.writeFile(
301
+ this.convert(rank),
302
+ filename,
303
+ {
304
+ compression: true
305
+ }
306
+ );
307
+ }
308
+ convertToSheet(rank) {
309
+ const aoa = this.convertToAoa(rank);
310
+ const sheet = XLSX.utils.aoa_to_sheet(aoa);
311
+ const cols = [];
312
+ const head = aoa[1];
313
+ for (let j = 0; j < head.length; j++) {
314
+ let wch = 10;
315
+ for (let i = 1; i < aoa.length; i++) {
316
+ wch = Math.max(wch, stringWidth(aoa[i][j]) + 2);
317
+ }
318
+ cols.push({
319
+ wch
320
+ });
321
+ }
322
+ sheet["!cols"] = cols;
323
+ {
324
+ const mergeRange = { s: { r: 0, c: 0 }, e: { r: 0, c: head.length - 1 } };
325
+ const merges = [{ s: mergeRange.s, e: mergeRange.e }];
326
+ sheet["!merges"] = merges;
327
+ }
328
+ const font = {
329
+ name: "Arial Unicode MS",
330
+ bold: false,
331
+ italic: false,
332
+ sz: 12
333
+ };
334
+ const borderStyle = {
335
+ style: "thin"
336
+ };
337
+ const cellStyle = {
338
+ alignment: {
339
+ vertical: "center",
340
+ horizontal: "center"
341
+ },
342
+ border: {
343
+ top: borderStyle,
344
+ bottom: borderStyle,
345
+ left: borderStyle,
346
+ right: borderStyle
347
+ },
348
+ font
349
+ };
350
+ for (let i = 1; i < aoa.length; i++) {
351
+ for (let j = 0; j < aoa[i].length; j++) {
352
+ const cellAddress = XLSX.utils.encode_cell({ r: i, c: j });
353
+ const cell = sheet[cellAddress];
354
+ cell.s = cellStyle;
355
+ }
356
+ }
357
+ {
358
+ const cellAddress = XLSX.utils.encode_cell({ r: 0, c: 0 });
359
+ const cell = sheet[cellAddress];
360
+ const titleStyle = _.cloneDeep(cellStyle);
361
+ titleStyle.font.sz = 28;
362
+ titleStyle.font.bold = true;
363
+ cell.s = titleStyle;
364
+ }
365
+ return sheet;
366
+ }
367
+ convertToAoa(rank) {
368
+ const aoa = [];
369
+ const enableAwards = rank.contest.isEnableAwards(rank.options.group);
370
+ {
371
+ aoa.push([rank.contest.name]);
372
+ }
373
+ {
374
+ const head = [];
375
+ head.push("Rank");
376
+ if (rank.contest.organization) {
377
+ head.push(`${rank.contest.organization} Rank`);
378
+ head.push(rank.contest.organization);
379
+ }
380
+ head.push("Name", "Solved", "Penalty", ...rank.contest.problems.map((p) => p.label), "Dict");
381
+ if (enableAwards) {
382
+ head.push("Medal");
383
+ }
384
+ aoa.push(head);
385
+ }
386
+ for (const team of rank.teams) {
387
+ const arr = [];
388
+ arr.push(team.rank.toString());
389
+ if (team.organization) {
390
+ if (team.organizationRank !== -1) {
391
+ arr.push(team.organizationRank.toString());
392
+ } else {
393
+ arr.push("");
394
+ }
395
+ arr.push(team.organization);
396
+ }
397
+ arr.push(team.name, team.solvedProblemNum.toString(), team.penaltyToMinute.toString());
398
+ for (const p of team.problemStatistics) {
399
+ if (p.isUnSubmitted) {
400
+ arr.push("-");
401
+ }
402
+ if (p.isSolved) {
403
+ arr.push(`+${p.totalCount}(${p.solvedTimestampToMinute})`);
404
+ }
405
+ if (p.isWrongAnswer) {
406
+ arr.push(`-${p.failedCount}`);
407
+ }
408
+ if (p.isPending) {
409
+ arr.push(`? ${p.failedCount} + ${p.pendingCount}`);
410
+ }
411
+ }
412
+ arr.push(`${team.dict}%`);
413
+ if (enableAwards) {
414
+ const medals = team.awards.filter((a) => isValidMedalType(a)).map((a) => a.toString());
415
+ arr.push(medals.join(", "));
416
+ }
417
+ aoa.push(arr);
418
+ }
419
+ return aoa;
420
+ }
421
+ }
422
+
423
+ function calcDict(attemptedNum, solvedNum) {
424
+ if (solvedNum === 0) {
425
+ return 0;
426
+ }
427
+ return Math.floor((attemptedNum - solvedNum) * 100 / attemptedNum);
428
+ }
429
+
73
430
  class ProblemStatistics {
74
431
  constructor() {
75
432
  this.acceptedNum = 0;
@@ -175,6 +532,12 @@ class TeamProblemStatistics {
175
532
  }
176
533
  return Math.floor(this.solvedTimestamp / 60) * 60 + this.failedCount * this.contestPenalty;
177
534
  }
535
+ get penaltyToMinute() {
536
+ return Math.floor(this.penalty / 60);
537
+ }
538
+ get solvedTimestampToMinute() {
539
+ return Math.floor(this.solvedTimestamp / 60);
540
+ }
178
541
  }
179
542
 
180
543
  class Group {
@@ -260,6 +623,15 @@ class Contest {
260
623
  const pass = baseTime.diff(this.startTime, "s");
261
624
  return Math.round(pass * 100 / total);
262
625
  }
626
+ isEnableAwards(group) {
627
+ if (!this.awards) {
628
+ return false;
629
+ }
630
+ if (!this.awards.has(group)) {
631
+ return false;
632
+ }
633
+ return true;
634
+ }
263
635
  }
264
636
  function createContest(contestJSON) {
265
637
  const c = new Contest();
@@ -424,208 +796,6 @@ function createContestIndexList(contestListJSON) {
424
796
  return contestIndexList;
425
797
  }
426
798
 
427
- function stringToSubmissionStatus(status) {
428
- status = status.toUpperCase().replace(" ", "_");
429
- if (["OK", "AC", SubmissionStatus.ACCEPTED.toString()].includes(status)) {
430
- return SubmissionStatus.ACCEPTED;
431
- }
432
- if ([SubmissionStatus.CORRECT.toString()].includes(status)) {
433
- return SubmissionStatus.ACCEPTED;
434
- }
435
- if ([SubmissionStatus.PARTIALLY_CORRECT.toString()].includes(status)) {
436
- return SubmissionStatus.PARTIALLY_CORRECT;
437
- }
438
- if (["WA", SubmissionStatus.WRONG_ANSWER.toString()].includes(status)) {
439
- return SubmissionStatus.WRONG_ANSWER;
440
- }
441
- if (["RJ", "INCORRECT", SubmissionStatus.REJECTED.toString()].includes(status)) {
442
- return SubmissionStatus.REJECTED;
443
- }
444
- if (["PD", SubmissionStatus.PENDING.toString()].includes(status)) {
445
- return SubmissionStatus.PENDING;
446
- }
447
- if ([SubmissionStatus.WAITING.toString()].includes(status)) {
448
- return SubmissionStatus.WAITING;
449
- }
450
- if ([SubmissionStatus.JUDGING.toString()].includes(status)) {
451
- return SubmissionStatus.JUDGING;
452
- }
453
- if ([SubmissionStatus.FROZEN.toString()].includes(status)) {
454
- return SubmissionStatus.FROZEN;
455
- }
456
- if (["CE", SubmissionStatus.COMPILATION_ERROR.toString()].includes(status)) {
457
- return SubmissionStatus.COMPILATION_ERROR;
458
- }
459
- if (["PE", SubmissionStatus.PRESENTATION_ERROR.toString()].includes(status)) {
460
- return SubmissionStatus.PRESENTATION_ERROR;
461
- }
462
- if (["TL", "TLE", SubmissionStatus.TIME_LIMIT_EXCEEDED.toString()].includes(status)) {
463
- return SubmissionStatus.TIME_LIMIT_EXCEEDED;
464
- }
465
- if (["ML", "MLE", SubmissionStatus.MEMORY_LIMIT_EXCEEDED.toString()].includes(status)) {
466
- return SubmissionStatus.MEMORY_LIMIT_EXCEEDED;
467
- }
468
- if (["OL", "OLE", SubmissionStatus.OUTPUT_LIMIT_EXCEEDED.toString()].includes(status)) {
469
- return SubmissionStatus.OUTPUT_LIMIT_EXCEEDED;
470
- }
471
- if (["IL", "ILE", SubmissionStatus.IDLENESS_LIMIT_EXCEEDED.toString()].includes(status)) {
472
- return SubmissionStatus.IDLENESS_LIMIT_EXCEEDED;
473
- }
474
- if (["RT", "RE", "RTE", SubmissionStatus.RUNTIME_ERROR.toString()].includes(status)) {
475
- return SubmissionStatus.RUNTIME_ERROR;
476
- }
477
- if (["JE", SubmissionStatus.JUDGEMENT_FAILED.toString()].includes(status)) {
478
- return SubmissionStatus.JUDGEMENT_FAILED;
479
- }
480
- if (["SE", SubmissionStatus.SYSTEM_ERROR.toString()].includes(status)) {
481
- return SubmissionStatus.SYSTEM_ERROR;
482
- }
483
- if ([SubmissionStatus.HACKED.toString()].includes(status)) {
484
- return SubmissionStatus.HACKED;
485
- }
486
- if ([SubmissionStatus.CONFIGURATION_ERROR.toString()].includes(status)) {
487
- return SubmissionStatus.CONFIGURATION_ERROR;
488
- }
489
- if ([SubmissionStatus.CANCELED.toString()].includes(status)) {
490
- return SubmissionStatus.CANCELED;
491
- }
492
- if ([SubmissionStatus.SKIPPED.toString()].includes(status)) {
493
- return SubmissionStatus.SKIPPED;
494
- }
495
- if ([SubmissionStatus.SECURITY_VIOLATED.toString()].includes(status)) {
496
- return SubmissionStatus.SECURITY_VIOLATED;
497
- }
498
- if ([SubmissionStatus.DENIAL_OF_JUDGEMENT.toString()].includes(status)) {
499
- return SubmissionStatus.DENIAL_OF_JUDGEMENT;
500
- }
501
- return SubmissionStatus.UNKNOWN;
502
- }
503
- function isAccepted(status) {
504
- const acceptedArray = [SubmissionStatus.ACCEPTED, SubmissionStatus.CORRECT];
505
- return acceptedArray.includes(status);
506
- }
507
- function isRejected(status) {
508
- const rejectArray = [
509
- SubmissionStatus.RUNTIME_ERROR,
510
- SubmissionStatus.TIME_LIMIT_EXCEEDED,
511
- SubmissionStatus.MEMORY_LIMIT_EXCEEDED,
512
- SubmissionStatus.OUTPUT_LIMIT_EXCEEDED,
513
- SubmissionStatus.IDLENESS_LIMIT_EXCEEDED,
514
- SubmissionStatus.WRONG_ANSWER,
515
- SubmissionStatus.REJECTED,
516
- SubmissionStatus.JUDGEMENT_FAILED,
517
- SubmissionStatus.HACKED
518
- ];
519
- return rejectArray.includes(status);
520
- }
521
- function isPending(status) {
522
- const pendingArray = [
523
- SubmissionStatus.PENDING,
524
- SubmissionStatus.WAITING,
525
- SubmissionStatus.JUDGING,
526
- SubmissionStatus.FROZEN
527
- ];
528
- return pendingArray.includes(status);
529
- }
530
- function isNotCalculatedPenaltyStatus(status) {
531
- const isNotCalculatedPenaltyArray = [
532
- SubmissionStatus.COMPILATION_ERROR,
533
- SubmissionStatus.PRESENTATION_ERROR,
534
- SubmissionStatus.CONFIGURATION_ERROR,
535
- SubmissionStatus.SYSTEM_ERROR,
536
- SubmissionStatus.CANCELED,
537
- SubmissionStatus.SKIPPED,
538
- SubmissionStatus.UNKNOWN,
539
- SubmissionStatus.UNDEFINED
540
- ];
541
- return isNotCalculatedPenaltyArray.includes(status);
542
- }
543
-
544
- function submissionStatusToCodeforcesGymDatStatus(status) {
545
- if (isAccepted(status)) {
546
- return "OK";
547
- }
548
- if (status === SubmissionStatus.WRONG_ANSWER) {
549
- return "WA";
550
- }
551
- if (status === SubmissionStatus.TIME_LIMIT_EXCEEDED) {
552
- return "TL";
553
- }
554
- if (status === SubmissionStatus.MEMORY_LIMIT_EXCEEDED) {
555
- return "ML";
556
- }
557
- if (status === SubmissionStatus.OUTPUT_LIMIT_EXCEEDED) {
558
- return "IL";
559
- }
560
- if (status === SubmissionStatus.PRESENTATION_ERROR) {
561
- return "PE";
562
- }
563
- if (status === SubmissionStatus.RUNTIME_ERROR) {
564
- return "RT";
565
- }
566
- if (status === SubmissionStatus.COMPILATION_ERROR || isNotCalculatedPenaltyStatus(status)) {
567
- return "CE";
568
- }
569
- if (isPending(status)) {
570
- return "PD";
571
- }
572
- return "RJ";
573
- }
574
- function rankToCodeforcesGymDAT(rank) {
575
- let res = "";
576
- res += `@contest "${rank.contest.name}"
577
- @contlen ${Math.floor(dayjs.duration(rank.contest.endTime.diff(rank.contest.startTime)).asMinutes())}
578
- @problems ${rank.contest.problems.length}
579
- @teams ${rank.teams.length + 100}
580
- @submissions ${rank.submissions.length}
581
- `;
582
- rank.contest.problems.forEach((p) => {
583
- res += `@p ${p.label},${p.label},20,0
584
- `;
585
- });
586
- let teamIndex = 1;
587
- const teamIdMap = /* @__PURE__ */ new Map();
588
- const submissionsIdMap = /* @__PURE__ */ new Map();
589
- rank.teams.forEach((team) => {
590
- let name = team.name;
591
- if (team.organization) {
592
- name = `${team.organization} - ${name}`;
593
- }
594
- if (team.members) {
595
- name = `${name} - ${team.membersToString}`;
596
- }
597
- res += `@t ${teamIndex},0,1,${name}
598
- `;
599
- teamIdMap.set(team.id, teamIndex);
600
- teamIndex++;
601
- {
602
- const mp = /* @__PURE__ */ new Map();
603
- rank.contest.problems.forEach((p) => {
604
- mp.set(p.id, 0);
605
- });
606
- submissionsIdMap.set(team.id, mp);
607
- }
608
- });
609
- for (let i = 0; i < 100; i++) {
610
- res += `@t ${teamIndex},0,1,\u041F\u043E\u043F\u043E\u043B\u043D\u0438\u0442\u044C \u043A\u043E\u043C\u0430\u043D\u0434\u0443
611
- `;
612
- teamIndex++;
613
- }
614
- rank.getSubmissions().forEach((submission) => {
615
- const teamId = submission.teamId;
616
- const problemId = submission.problemId;
617
- const problem = rank.contest.problemsMap.get(problemId);
618
- if (!problem) {
619
- return;
620
- }
621
- const status = submissionStatusToCodeforcesGymDatStatus(submission.status);
622
- submissionsIdMap.get(teamId).set(problemId, submissionsIdMap.get(teamId).get(problemId) + 1);
623
- res += `@s ${teamIdMap.get(teamId)},${problem.label},${submissionsIdMap.get(teamId)?.get(problemId)},${submission.timestamp},${status}
624
- `;
625
- });
626
- return res;
627
- }
628
-
629
799
  function getImageSource(image) {
630
800
  if (image?.url) {
631
801
  return image.url;
@@ -688,6 +858,7 @@ class Team {
688
858
  this.problemStatisticsMap = /* @__PURE__ */ new Map();
689
859
  this.submissions = [];
690
860
  this.placeChartPoints = [];
861
+ this.awards = [];
691
862
  }
692
863
  get penaltyToMinute() {
693
864
  return Math.floor(this.penalty / 60);
@@ -1227,4 +1398,4 @@ class Resolver extends Rank {
1227
1398
  }
1228
1399
  }
1229
1400
 
1230
- export { Award, Contest, ContestIndex, ContestIndexConfig, MedalType, PlaceChartPointData, Problem, ProblemStatistics, Rank, RankOptions, RankStatistics, Resolver, Submission, Team, TeamProblemStatistics, calcDict, createContest, createContestIndex, createContestIndexList, createDayJS, createProblem, createProblems, createProblemsByProblemIds, createSubmission, createSubmissions, createTeam, createTeams, getImageSource, getTimeDiff, getTimestamp, isAccepted, isNotCalculatedPenaltyStatus, isPending, isRejected, rankToCodeforcesGymDAT, stringToSubmissionStatus };
1401
+ export { Award, CodeforcesGymGhostDATConverter, Contest, ContestIndex, ContestIndexConfig, GeneralExcelConverter, MedalType, PlaceChartPointData, Problem, ProblemStatistics, Rank, RankOptions, RankStatistics, Resolver, Submission, Team, TeamProblemStatistics, calcDict, createContest, createContestIndex, createContestIndexList, createDayJS, createProblem, createProblems, createProblemsByProblemIds, createSubmission, createSubmissions, createTeam, createTeams, getImageSource, getTimeDiff, getTimestamp, isAccepted, isNotCalculatedPenaltyStatus, isPending, isRejected, isValidMedalType, stringToSubmissionStatus };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xcpcio/core",
3
- "version": "0.13.0",
3
+ "version": "0.15.0",
4
4
  "description": "XCPCIO Core",
5
5
  "author": "Dup4 <lyuzhi.pan@gmail.com>",
6
6
  "license": "MIT",
@@ -42,7 +42,9 @@
42
42
  "dependencies": {
43
43
  "dayjs": "^1.11.8",
44
44
  "lodash": "^4.17.21",
45
- "@xcpcio/types": "0.13.0"
45
+ "string-width": "^6.1.0",
46
+ "xlsx-js-style": "^1.2.0",
47
+ "@xcpcio/types": "0.15.0"
46
48
  },
47
49
  "devDependencies": {
48
50
  "@babel/types": "^7.22.4",