@xcpcio/core 0.14.0 → 0.16.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 +76 -33
- package/dist/index.d.ts +11 -7
- package/dist/index.mjs +76 -34
- package/package.json +2 -2
- package/src/award.ts +16 -5
- package/src/contest.ts +12 -0
- package/src/export/general-excel.ts +49 -18
- package/src/submission-status.ts +1 -0
- package/src/team.ts +8 -0
package/dist/index.cjs
CHANGED
|
@@ -141,6 +141,7 @@ function isPending(status) {
|
|
|
141
141
|
const pendingArray = [
|
|
142
142
|
types.SubmissionStatus.PENDING,
|
|
143
143
|
types.SubmissionStatus.WAITING,
|
|
144
|
+
types.SubmissionStatus.COMPILING,
|
|
144
145
|
types.SubmissionStatus.JUDGING,
|
|
145
146
|
types.SubmissionStatus.FROZEN
|
|
146
147
|
];
|
|
@@ -285,13 +286,59 @@ class CodeforcesGymGhostDATConverter {
|
|
|
285
286
|
}
|
|
286
287
|
}
|
|
287
288
|
|
|
289
|
+
var MedalType = /* @__PURE__ */ ((MedalType2) => {
|
|
290
|
+
MedalType2["UNKNOWN"] = "Unknown";
|
|
291
|
+
MedalType2["GOLD"] = "Gold";
|
|
292
|
+
MedalType2["SILVER"] = "Silver";
|
|
293
|
+
MedalType2["BRONZE"] = "Bronze";
|
|
294
|
+
MedalType2["HONORABLE"] = "Honorable";
|
|
295
|
+
return MedalType2;
|
|
296
|
+
})(MedalType || {});
|
|
297
|
+
class Award {
|
|
298
|
+
constructor() {
|
|
299
|
+
this.medalType = "Unknown" /* UNKNOWN */;
|
|
300
|
+
this.minRank = 0;
|
|
301
|
+
this.maxRank = 0;
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
function isValidMedalType(medal) {
|
|
305
|
+
const validMedalType = [
|
|
306
|
+
"Gold" /* GOLD */,
|
|
307
|
+
"Silver" /* SILVER */,
|
|
308
|
+
"Bronze" /* BRONZE */,
|
|
309
|
+
"Honorable" /* HONORABLE */
|
|
310
|
+
];
|
|
311
|
+
return validMedalType.includes(medal);
|
|
312
|
+
}
|
|
313
|
+
|
|
288
314
|
class GeneralExcelConverter {
|
|
289
315
|
constructor() {
|
|
290
316
|
}
|
|
291
|
-
convert(
|
|
317
|
+
convert(oriRank) {
|
|
318
|
+
const rank = ___default.cloneDeep(oriRank);
|
|
319
|
+
rank.options.disableFilterTeamsByGroup();
|
|
320
|
+
rank.options.disableFilterSubmissionByTimestamp();
|
|
292
321
|
const workbook = XLSX__namespace.utils.book_new();
|
|
322
|
+
for (const [k, v] of rank.contest.group) {
|
|
323
|
+
rank.options.setGroup(k);
|
|
324
|
+
rank.buildRank();
|
|
325
|
+
const sheet = this.convertToSheet(rank);
|
|
326
|
+
XLSX__namespace.utils.book_append_sheet(workbook, sheet, v.names.get(v.defaultLang));
|
|
327
|
+
}
|
|
328
|
+
return workbook;
|
|
329
|
+
}
|
|
330
|
+
convertAndWrite(rank, filename) {
|
|
331
|
+
return XLSX__namespace.writeFile(
|
|
332
|
+
this.convert(rank),
|
|
333
|
+
filename,
|
|
334
|
+
{
|
|
335
|
+
compression: true
|
|
336
|
+
}
|
|
337
|
+
);
|
|
338
|
+
}
|
|
339
|
+
convertToSheet(rank) {
|
|
293
340
|
const aoa = this.convertToAoa(rank);
|
|
294
|
-
const
|
|
341
|
+
const sheet = XLSX__namespace.utils.aoa_to_sheet(aoa);
|
|
295
342
|
const cols = [];
|
|
296
343
|
const head = aoa[1];
|
|
297
344
|
for (let j = 0; j < head.length; j++) {
|
|
@@ -303,11 +350,11 @@ class GeneralExcelConverter {
|
|
|
303
350
|
wch
|
|
304
351
|
});
|
|
305
352
|
}
|
|
306
|
-
|
|
353
|
+
sheet["!cols"] = cols;
|
|
307
354
|
{
|
|
308
355
|
const mergeRange = { s: { r: 0, c: 0 }, e: { r: 0, c: head.length - 1 } };
|
|
309
356
|
const merges = [{ s: mergeRange.s, e: mergeRange.e }];
|
|
310
|
-
|
|
357
|
+
sheet["!merges"] = merges;
|
|
311
358
|
}
|
|
312
359
|
const font = {
|
|
313
360
|
name: "Arial Unicode MS",
|
|
@@ -334,32 +381,23 @@ class GeneralExcelConverter {
|
|
|
334
381
|
for (let i = 1; i < aoa.length; i++) {
|
|
335
382
|
for (let j = 0; j < aoa[i].length; j++) {
|
|
336
383
|
const cellAddress = XLSX__namespace.utils.encode_cell({ r: i, c: j });
|
|
337
|
-
const cell =
|
|
384
|
+
const cell = sheet[cellAddress];
|
|
338
385
|
cell.s = cellStyle;
|
|
339
386
|
}
|
|
340
387
|
}
|
|
341
388
|
{
|
|
342
389
|
const cellAddress = XLSX__namespace.utils.encode_cell({ r: 0, c: 0 });
|
|
343
|
-
const cell =
|
|
390
|
+
const cell = sheet[cellAddress];
|
|
344
391
|
const titleStyle = ___default.cloneDeep(cellStyle);
|
|
345
392
|
titleStyle.font.sz = 28;
|
|
346
393
|
titleStyle.font.bold = true;
|
|
347
394
|
cell.s = titleStyle;
|
|
348
395
|
}
|
|
349
|
-
|
|
350
|
-
return workbook;
|
|
351
|
-
}
|
|
352
|
-
convertAndWrite(rank, filename) {
|
|
353
|
-
return XLSX__namespace.writeFile(
|
|
354
|
-
this.convert(rank),
|
|
355
|
-
filename,
|
|
356
|
-
{
|
|
357
|
-
compression: true
|
|
358
|
-
}
|
|
359
|
-
);
|
|
396
|
+
return sheet;
|
|
360
397
|
}
|
|
361
398
|
convertToAoa(rank) {
|
|
362
399
|
const aoa = [];
|
|
400
|
+
const enableAwards = rank.contest.isEnableAwards(rank.options.group);
|
|
363
401
|
{
|
|
364
402
|
aoa.push([rank.contest.name]);
|
|
365
403
|
}
|
|
@@ -371,6 +409,9 @@ class GeneralExcelConverter {
|
|
|
371
409
|
head.push(rank.contest.organization);
|
|
372
410
|
}
|
|
373
411
|
head.push("Name", "Solved", "Penalty", ...rank.contest.problems.map((p) => p.label), "Dict");
|
|
412
|
+
if (enableAwards) {
|
|
413
|
+
head.push("Medal");
|
|
414
|
+
}
|
|
374
415
|
aoa.push(head);
|
|
375
416
|
}
|
|
376
417
|
for (const team of rank.teams) {
|
|
@@ -400,28 +441,16 @@ class GeneralExcelConverter {
|
|
|
400
441
|
}
|
|
401
442
|
}
|
|
402
443
|
arr.push(`${team.dict}%`);
|
|
444
|
+
if (enableAwards) {
|
|
445
|
+
const medals = team.awards.filter((a) => isValidMedalType(a)).map((a) => a.toString());
|
|
446
|
+
arr.push(medals.join(", "));
|
|
447
|
+
}
|
|
403
448
|
aoa.push(arr);
|
|
404
449
|
}
|
|
405
450
|
return aoa;
|
|
406
451
|
}
|
|
407
452
|
}
|
|
408
453
|
|
|
409
|
-
var MedalType = /* @__PURE__ */ ((MedalType2) => {
|
|
410
|
-
MedalType2[MedalType2["UNKNOWN"] = 0] = "UNKNOWN";
|
|
411
|
-
MedalType2[MedalType2["GOLD"] = 1] = "GOLD";
|
|
412
|
-
MedalType2[MedalType2["SILVER"] = 2] = "SILVER";
|
|
413
|
-
MedalType2[MedalType2["BRONZE"] = 3] = "BRONZE";
|
|
414
|
-
MedalType2[MedalType2["HONORABLE"] = 4] = "HONORABLE";
|
|
415
|
-
return MedalType2;
|
|
416
|
-
})(MedalType || {});
|
|
417
|
-
class Award {
|
|
418
|
-
constructor() {
|
|
419
|
-
this.medalType = 0 /* UNKNOWN */;
|
|
420
|
-
this.minRank = 0;
|
|
421
|
-
this.maxRank = 0;
|
|
422
|
-
}
|
|
423
|
-
}
|
|
424
|
-
|
|
425
454
|
function calcDict(attemptedNum, solvedNum) {
|
|
426
455
|
if (solvedNum === 0) {
|
|
427
456
|
return 0;
|
|
@@ -625,6 +654,15 @@ class Contest {
|
|
|
625
654
|
const pass = baseTime.diff(this.startTime, "s");
|
|
626
655
|
return Math.round(pass * 100 / total);
|
|
627
656
|
}
|
|
657
|
+
isEnableAwards(group) {
|
|
658
|
+
if (!this.awards) {
|
|
659
|
+
return false;
|
|
660
|
+
}
|
|
661
|
+
if (!this.awards.has(group)) {
|
|
662
|
+
return false;
|
|
663
|
+
}
|
|
664
|
+
return true;
|
|
665
|
+
}
|
|
628
666
|
}
|
|
629
667
|
function createContest(contestJSON) {
|
|
630
668
|
const c = new Contest();
|
|
@@ -851,6 +889,7 @@ class Team {
|
|
|
851
889
|
this.problemStatisticsMap = /* @__PURE__ */ new Map();
|
|
852
890
|
this.submissions = [];
|
|
853
891
|
this.placeChartPoints = [];
|
|
892
|
+
this.awards = [];
|
|
854
893
|
}
|
|
855
894
|
get penaltyToMinute() {
|
|
856
895
|
return Math.floor(this.penalty / 60);
|
|
@@ -956,6 +995,9 @@ function createTeam(teamJSON) {
|
|
|
956
995
|
}
|
|
957
996
|
t.group = [...new Set(t.group)];
|
|
958
997
|
t.group.sort();
|
|
998
|
+
if (teamJSON.location) {
|
|
999
|
+
t.location = teamJSON.location;
|
|
1000
|
+
}
|
|
959
1001
|
return t;
|
|
960
1002
|
}
|
|
961
1003
|
function createTeams(teamsJSON) {
|
|
@@ -1427,4 +1469,5 @@ exports.isAccepted = isAccepted;
|
|
|
1427
1469
|
exports.isNotCalculatedPenaltyStatus = isNotCalculatedPenaltyStatus;
|
|
1428
1470
|
exports.isPending = isPending;
|
|
1429
1471
|
exports.isRejected = isRejected;
|
|
1472
|
+
exports.isValidMedalType = isValidMedalType;
|
|
1430
1473
|
exports.stringToSubmissionStatus = stringToSubmissionStatus;
|
package/dist/index.d.ts
CHANGED
|
@@ -88,11 +88,11 @@ declare class Group {
|
|
|
88
88
|
}
|
|
89
89
|
|
|
90
90
|
declare enum MedalType {
|
|
91
|
-
UNKNOWN =
|
|
92
|
-
GOLD =
|
|
93
|
-
SILVER =
|
|
94
|
-
BRONZE =
|
|
95
|
-
HONORABLE =
|
|
91
|
+
UNKNOWN = "Unknown",
|
|
92
|
+
GOLD = "Gold",
|
|
93
|
+
SILVER = "Silver",
|
|
94
|
+
BRONZE = "Bronze",
|
|
95
|
+
HONORABLE = "Honorable"
|
|
96
96
|
}
|
|
97
97
|
declare class Award {
|
|
98
98
|
medalType: MedalType;
|
|
@@ -100,6 +100,7 @@ declare class Award {
|
|
|
100
100
|
maxRank: number;
|
|
101
101
|
constructor();
|
|
102
102
|
}
|
|
103
|
+
declare function isValidMedalType(medal: MedalType): boolean;
|
|
103
104
|
type Awards = Map<string, Award[]>;
|
|
104
105
|
|
|
105
106
|
declare class Contest {
|
|
@@ -130,6 +131,7 @@ declare class Contest {
|
|
|
130
131
|
getContestElapsedTime(nowTime?: Date): string;
|
|
131
132
|
getContestRemainingTime(nowTime?: Date): string;
|
|
132
133
|
getContestProgressRatio(nowTime?: Date): number;
|
|
134
|
+
isEnableAwards(group: string): boolean;
|
|
133
135
|
}
|
|
134
136
|
declare function createContest(contestJSON: Contest$1): Contest;
|
|
135
137
|
|
|
@@ -161,6 +163,7 @@ declare class Team {
|
|
|
161
163
|
submissions: Submissions;
|
|
162
164
|
placeChartPoints: Array<PlaceChartPointData>;
|
|
163
165
|
awards: MedalType[];
|
|
166
|
+
location?: string;
|
|
164
167
|
constructor();
|
|
165
168
|
reset(): void;
|
|
166
169
|
get penaltyToMinute(): number;
|
|
@@ -233,8 +236,9 @@ declare class CodeforcesGymGhostDATConverter {
|
|
|
233
236
|
|
|
234
237
|
declare class GeneralExcelConverter {
|
|
235
238
|
constructor();
|
|
236
|
-
convert(
|
|
239
|
+
convert(oriRank: Rank): XLSX.WorkBook;
|
|
237
240
|
convertAndWrite(rank: Rank, filename: string): any;
|
|
241
|
+
private convertToSheet;
|
|
238
242
|
private convertToAoa;
|
|
239
243
|
}
|
|
240
244
|
|
|
@@ -284,4 +288,4 @@ declare function isRejected(status: SubmissionStatus): boolean;
|
|
|
284
288
|
declare function isPending(status: SubmissionStatus): boolean;
|
|
285
289
|
declare function isNotCalculatedPenaltyStatus(status: SubmissionStatus): boolean;
|
|
286
290
|
|
|
287
|
-
export { Award, Awards, CodeforcesGymGhostDATConverter, Contest, ContestIndex, ContestIndexConfig, ContestIndexList, GeneralExcelConverter, MedalType, PlaceChartPointData, Problem, ProblemStatistics, Problems, Rank, RankOptions, RankStatistics, Resolver, SelectOptionItem, Submission, Submissions, Team, TeamProblemStatistics, Teams, calcDict, createContest, createContestIndex, createContestIndexList, createDayJS, createProblem, createProblems, createProblemsByProblemIds, createSubmission, createSubmissions, createTeam, createTeams, getImageSource, getTimeDiff, getTimestamp, isAccepted, isNotCalculatedPenaltyStatus, isPending, isRejected, stringToSubmissionStatus };
|
|
291
|
+
export { Award, Awards, CodeforcesGymGhostDATConverter, Contest, ContestIndex, ContestIndexConfig, ContestIndexList, GeneralExcelConverter, MedalType, PlaceChartPointData, Problem, ProblemStatistics, Problems, Rank, RankOptions, RankStatistics, Resolver, SelectOptionItem, Submission, Submissions, Team, TeamProblemStatistics, Teams, calcDict, createContest, createContestIndex, createContestIndexList, createDayJS, createProblem, createProblems, createProblemsByProblemIds, createSubmission, createSubmissions, createTeam, createTeams, getImageSource, getTimeDiff, getTimestamp, isAccepted, isNotCalculatedPenaltyStatus, isPending, isRejected, isValidMedalType, stringToSubmissionStatus };
|
package/dist/index.mjs
CHANGED
|
@@ -111,6 +111,7 @@ function isPending(status) {
|
|
|
111
111
|
const pendingArray = [
|
|
112
112
|
SubmissionStatus.PENDING,
|
|
113
113
|
SubmissionStatus.WAITING,
|
|
114
|
+
SubmissionStatus.COMPILING,
|
|
114
115
|
SubmissionStatus.JUDGING,
|
|
115
116
|
SubmissionStatus.FROZEN
|
|
116
117
|
];
|
|
@@ -255,13 +256,59 @@ class CodeforcesGymGhostDATConverter {
|
|
|
255
256
|
}
|
|
256
257
|
}
|
|
257
258
|
|
|
259
|
+
var MedalType = /* @__PURE__ */ ((MedalType2) => {
|
|
260
|
+
MedalType2["UNKNOWN"] = "Unknown";
|
|
261
|
+
MedalType2["GOLD"] = "Gold";
|
|
262
|
+
MedalType2["SILVER"] = "Silver";
|
|
263
|
+
MedalType2["BRONZE"] = "Bronze";
|
|
264
|
+
MedalType2["HONORABLE"] = "Honorable";
|
|
265
|
+
return MedalType2;
|
|
266
|
+
})(MedalType || {});
|
|
267
|
+
class Award {
|
|
268
|
+
constructor() {
|
|
269
|
+
this.medalType = "Unknown" /* UNKNOWN */;
|
|
270
|
+
this.minRank = 0;
|
|
271
|
+
this.maxRank = 0;
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
function isValidMedalType(medal) {
|
|
275
|
+
const validMedalType = [
|
|
276
|
+
"Gold" /* GOLD */,
|
|
277
|
+
"Silver" /* SILVER */,
|
|
278
|
+
"Bronze" /* BRONZE */,
|
|
279
|
+
"Honorable" /* HONORABLE */
|
|
280
|
+
];
|
|
281
|
+
return validMedalType.includes(medal);
|
|
282
|
+
}
|
|
283
|
+
|
|
258
284
|
class GeneralExcelConverter {
|
|
259
285
|
constructor() {
|
|
260
286
|
}
|
|
261
|
-
convert(
|
|
287
|
+
convert(oriRank) {
|
|
288
|
+
const rank = _.cloneDeep(oriRank);
|
|
289
|
+
rank.options.disableFilterTeamsByGroup();
|
|
290
|
+
rank.options.disableFilterSubmissionByTimestamp();
|
|
262
291
|
const workbook = XLSX.utils.book_new();
|
|
292
|
+
for (const [k, v] of rank.contest.group) {
|
|
293
|
+
rank.options.setGroup(k);
|
|
294
|
+
rank.buildRank();
|
|
295
|
+
const sheet = this.convertToSheet(rank);
|
|
296
|
+
XLSX.utils.book_append_sheet(workbook, sheet, v.names.get(v.defaultLang));
|
|
297
|
+
}
|
|
298
|
+
return workbook;
|
|
299
|
+
}
|
|
300
|
+
convertAndWrite(rank, filename) {
|
|
301
|
+
return XLSX.writeFile(
|
|
302
|
+
this.convert(rank),
|
|
303
|
+
filename,
|
|
304
|
+
{
|
|
305
|
+
compression: true
|
|
306
|
+
}
|
|
307
|
+
);
|
|
308
|
+
}
|
|
309
|
+
convertToSheet(rank) {
|
|
263
310
|
const aoa = this.convertToAoa(rank);
|
|
264
|
-
const
|
|
311
|
+
const sheet = XLSX.utils.aoa_to_sheet(aoa);
|
|
265
312
|
const cols = [];
|
|
266
313
|
const head = aoa[1];
|
|
267
314
|
for (let j = 0; j < head.length; j++) {
|
|
@@ -273,11 +320,11 @@ class GeneralExcelConverter {
|
|
|
273
320
|
wch
|
|
274
321
|
});
|
|
275
322
|
}
|
|
276
|
-
|
|
323
|
+
sheet["!cols"] = cols;
|
|
277
324
|
{
|
|
278
325
|
const mergeRange = { s: { r: 0, c: 0 }, e: { r: 0, c: head.length - 1 } };
|
|
279
326
|
const merges = [{ s: mergeRange.s, e: mergeRange.e }];
|
|
280
|
-
|
|
327
|
+
sheet["!merges"] = merges;
|
|
281
328
|
}
|
|
282
329
|
const font = {
|
|
283
330
|
name: "Arial Unicode MS",
|
|
@@ -304,32 +351,23 @@ class GeneralExcelConverter {
|
|
|
304
351
|
for (let i = 1; i < aoa.length; i++) {
|
|
305
352
|
for (let j = 0; j < aoa[i].length; j++) {
|
|
306
353
|
const cellAddress = XLSX.utils.encode_cell({ r: i, c: j });
|
|
307
|
-
const cell =
|
|
354
|
+
const cell = sheet[cellAddress];
|
|
308
355
|
cell.s = cellStyle;
|
|
309
356
|
}
|
|
310
357
|
}
|
|
311
358
|
{
|
|
312
359
|
const cellAddress = XLSX.utils.encode_cell({ r: 0, c: 0 });
|
|
313
|
-
const cell =
|
|
360
|
+
const cell = sheet[cellAddress];
|
|
314
361
|
const titleStyle = _.cloneDeep(cellStyle);
|
|
315
362
|
titleStyle.font.sz = 28;
|
|
316
363
|
titleStyle.font.bold = true;
|
|
317
364
|
cell.s = titleStyle;
|
|
318
365
|
}
|
|
319
|
-
|
|
320
|
-
return workbook;
|
|
321
|
-
}
|
|
322
|
-
convertAndWrite(rank, filename) {
|
|
323
|
-
return XLSX.writeFile(
|
|
324
|
-
this.convert(rank),
|
|
325
|
-
filename,
|
|
326
|
-
{
|
|
327
|
-
compression: true
|
|
328
|
-
}
|
|
329
|
-
);
|
|
366
|
+
return sheet;
|
|
330
367
|
}
|
|
331
368
|
convertToAoa(rank) {
|
|
332
369
|
const aoa = [];
|
|
370
|
+
const enableAwards = rank.contest.isEnableAwards(rank.options.group);
|
|
333
371
|
{
|
|
334
372
|
aoa.push([rank.contest.name]);
|
|
335
373
|
}
|
|
@@ -341,6 +379,9 @@ class GeneralExcelConverter {
|
|
|
341
379
|
head.push(rank.contest.organization);
|
|
342
380
|
}
|
|
343
381
|
head.push("Name", "Solved", "Penalty", ...rank.contest.problems.map((p) => p.label), "Dict");
|
|
382
|
+
if (enableAwards) {
|
|
383
|
+
head.push("Medal");
|
|
384
|
+
}
|
|
344
385
|
aoa.push(head);
|
|
345
386
|
}
|
|
346
387
|
for (const team of rank.teams) {
|
|
@@ -370,28 +411,16 @@ class GeneralExcelConverter {
|
|
|
370
411
|
}
|
|
371
412
|
}
|
|
372
413
|
arr.push(`${team.dict}%`);
|
|
414
|
+
if (enableAwards) {
|
|
415
|
+
const medals = team.awards.filter((a) => isValidMedalType(a)).map((a) => a.toString());
|
|
416
|
+
arr.push(medals.join(", "));
|
|
417
|
+
}
|
|
373
418
|
aoa.push(arr);
|
|
374
419
|
}
|
|
375
420
|
return aoa;
|
|
376
421
|
}
|
|
377
422
|
}
|
|
378
423
|
|
|
379
|
-
var MedalType = /* @__PURE__ */ ((MedalType2) => {
|
|
380
|
-
MedalType2[MedalType2["UNKNOWN"] = 0] = "UNKNOWN";
|
|
381
|
-
MedalType2[MedalType2["GOLD"] = 1] = "GOLD";
|
|
382
|
-
MedalType2[MedalType2["SILVER"] = 2] = "SILVER";
|
|
383
|
-
MedalType2[MedalType2["BRONZE"] = 3] = "BRONZE";
|
|
384
|
-
MedalType2[MedalType2["HONORABLE"] = 4] = "HONORABLE";
|
|
385
|
-
return MedalType2;
|
|
386
|
-
})(MedalType || {});
|
|
387
|
-
class Award {
|
|
388
|
-
constructor() {
|
|
389
|
-
this.medalType = 0 /* UNKNOWN */;
|
|
390
|
-
this.minRank = 0;
|
|
391
|
-
this.maxRank = 0;
|
|
392
|
-
}
|
|
393
|
-
}
|
|
394
|
-
|
|
395
424
|
function calcDict(attemptedNum, solvedNum) {
|
|
396
425
|
if (solvedNum === 0) {
|
|
397
426
|
return 0;
|
|
@@ -595,6 +624,15 @@ class Contest {
|
|
|
595
624
|
const pass = baseTime.diff(this.startTime, "s");
|
|
596
625
|
return Math.round(pass * 100 / total);
|
|
597
626
|
}
|
|
627
|
+
isEnableAwards(group) {
|
|
628
|
+
if (!this.awards) {
|
|
629
|
+
return false;
|
|
630
|
+
}
|
|
631
|
+
if (!this.awards.has(group)) {
|
|
632
|
+
return false;
|
|
633
|
+
}
|
|
634
|
+
return true;
|
|
635
|
+
}
|
|
598
636
|
}
|
|
599
637
|
function createContest(contestJSON) {
|
|
600
638
|
const c = new Contest();
|
|
@@ -821,6 +859,7 @@ class Team {
|
|
|
821
859
|
this.problemStatisticsMap = /* @__PURE__ */ new Map();
|
|
822
860
|
this.submissions = [];
|
|
823
861
|
this.placeChartPoints = [];
|
|
862
|
+
this.awards = [];
|
|
824
863
|
}
|
|
825
864
|
get penaltyToMinute() {
|
|
826
865
|
return Math.floor(this.penalty / 60);
|
|
@@ -926,6 +965,9 @@ function createTeam(teamJSON) {
|
|
|
926
965
|
}
|
|
927
966
|
t.group = [...new Set(t.group)];
|
|
928
967
|
t.group.sort();
|
|
968
|
+
if (teamJSON.location) {
|
|
969
|
+
t.location = teamJSON.location;
|
|
970
|
+
}
|
|
929
971
|
return t;
|
|
930
972
|
}
|
|
931
973
|
function createTeams(teamsJSON) {
|
|
@@ -1360,4 +1402,4 @@ class Resolver extends Rank {
|
|
|
1360
1402
|
}
|
|
1361
1403
|
}
|
|
1362
1404
|
|
|
1363
|
-
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, stringToSubmissionStatus };
|
|
1405
|
+
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.
|
|
3
|
+
"version": "0.16.0",
|
|
4
4
|
"description": "XCPCIO Core",
|
|
5
5
|
"author": "Dup4 <lyuzhi.pan@gmail.com>",
|
|
6
6
|
"license": "MIT",
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
"lodash": "^4.17.21",
|
|
45
45
|
"string-width": "^6.1.0",
|
|
46
46
|
"xlsx-js-style": "^1.2.0",
|
|
47
|
-
"@xcpcio/types": "0.
|
|
47
|
+
"@xcpcio/types": "0.16.0"
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
50
|
"@babel/types": "^7.22.4",
|
package/src/award.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
export enum MedalType {
|
|
2
|
-
UNKNOWN,
|
|
3
|
-
GOLD,
|
|
4
|
-
SILVER,
|
|
5
|
-
BRONZE,
|
|
6
|
-
HONORABLE,
|
|
2
|
+
UNKNOWN = "Unknown",
|
|
3
|
+
GOLD = "Gold",
|
|
4
|
+
SILVER = "Silver",
|
|
5
|
+
BRONZE = "Bronze",
|
|
6
|
+
HONORABLE = "Honorable",
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
export class Award {
|
|
@@ -18,4 +18,15 @@ export class Award {
|
|
|
18
18
|
}
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
+
export function isValidMedalType(medal: MedalType): boolean {
|
|
22
|
+
const validMedalType = [
|
|
23
|
+
MedalType.GOLD,
|
|
24
|
+
MedalType.SILVER,
|
|
25
|
+
MedalType.BRONZE,
|
|
26
|
+
MedalType.HONORABLE,
|
|
27
|
+
];
|
|
28
|
+
|
|
29
|
+
return validMedalType.includes(medal);
|
|
30
|
+
}
|
|
31
|
+
|
|
21
32
|
export type Awards = Map<string, Award[]>;
|
package/src/contest.ts
CHANGED
|
@@ -136,6 +136,18 @@ export class Contest {
|
|
|
136
136
|
|
|
137
137
|
return Math.round((pass * 100) / total);
|
|
138
138
|
}
|
|
139
|
+
|
|
140
|
+
isEnableAwards(group: string): boolean {
|
|
141
|
+
if (!this.awards) {
|
|
142
|
+
return false;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
if (!this.awards.has(group)) {
|
|
146
|
+
return false;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
return true;
|
|
150
|
+
}
|
|
139
151
|
}
|
|
140
152
|
|
|
141
153
|
export function createContest(contestJSON: IContest): Contest {
|
|
@@ -2,15 +2,43 @@ import _ from "lodash";
|
|
|
2
2
|
import * as XLSX from "xlsx-js-style";
|
|
3
3
|
import stringWidth from "string-width";
|
|
4
4
|
|
|
5
|
+
import { isValidMedalType } from "../award";
|
|
5
6
|
import type { Rank } from "../rank";
|
|
6
7
|
|
|
7
8
|
export class GeneralExcelConverter {
|
|
8
9
|
constructor() {}
|
|
9
10
|
|
|
10
|
-
public convert(
|
|
11
|
+
public convert(oriRank: Rank): XLSX.WorkBook {
|
|
12
|
+
const rank = _.cloneDeep(oriRank);
|
|
13
|
+
|
|
14
|
+
rank.options.disableFilterTeamsByGroup();
|
|
15
|
+
rank.options.disableFilterSubmissionByTimestamp();
|
|
16
|
+
|
|
11
17
|
const workbook = XLSX.utils.book_new();
|
|
18
|
+
|
|
19
|
+
for (const [k, v] of rank.contest.group) {
|
|
20
|
+
rank.options.setGroup(k);
|
|
21
|
+
rank.buildRank();
|
|
22
|
+
|
|
23
|
+
const sheet = this.convertToSheet(rank);
|
|
24
|
+
XLSX.utils.book_append_sheet(workbook, sheet, v.names.get(v.defaultLang) as string);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return workbook;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
public convertAndWrite(rank: Rank, filename: string): any {
|
|
31
|
+
return XLSX.writeFile(
|
|
32
|
+
this.convert(rank),
|
|
33
|
+
filename,
|
|
34
|
+
{
|
|
35
|
+
compression: true,
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
private convertToSheet(rank: Rank): XLSX.WorkSheet {
|
|
12
40
|
const aoa = this.convertToAoa(rank);
|
|
13
|
-
const
|
|
41
|
+
const sheet = XLSX.utils.aoa_to_sheet(aoa);
|
|
14
42
|
|
|
15
43
|
const cols = [];
|
|
16
44
|
const head = aoa[1];
|
|
@@ -25,12 +53,12 @@ export class GeneralExcelConverter {
|
|
|
25
53
|
});
|
|
26
54
|
}
|
|
27
55
|
|
|
28
|
-
|
|
56
|
+
sheet["!cols"] = cols;
|
|
29
57
|
|
|
30
58
|
{
|
|
31
59
|
const mergeRange = { s: { r: 0, c: 0 }, e: { r: 0, c: head.length - 1 } };
|
|
32
60
|
const merges = [{ s: mergeRange.s, e: mergeRange.e }];
|
|
33
|
-
|
|
61
|
+
sheet["!merges"] = merges;
|
|
34
62
|
}
|
|
35
63
|
|
|
36
64
|
const font = {
|
|
@@ -61,37 +89,28 @@ export class GeneralExcelConverter {
|
|
|
61
89
|
for (let i = 1; i < aoa.length; i++) {
|
|
62
90
|
for (let j = 0; j < aoa[i].length; j++) {
|
|
63
91
|
const cellAddress = XLSX.utils.encode_cell({ r: i, c: j });
|
|
64
|
-
const cell =
|
|
92
|
+
const cell = sheet[cellAddress];
|
|
65
93
|
cell.s = cellStyle;
|
|
66
94
|
}
|
|
67
95
|
}
|
|
68
96
|
|
|
69
97
|
{
|
|
70
98
|
const cellAddress = XLSX.utils.encode_cell({ r: 0, c: 0 });
|
|
71
|
-
const cell =
|
|
99
|
+
const cell = sheet[cellAddress];
|
|
72
100
|
const titleStyle = _.cloneDeep(cellStyle);
|
|
73
101
|
titleStyle.font.sz = 28;
|
|
74
102
|
titleStyle.font.bold = true;
|
|
75
103
|
cell.s = titleStyle;
|
|
76
104
|
}
|
|
77
105
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
return workbook;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
public convertAndWrite(rank: Rank, filename: string): any {
|
|
84
|
-
return XLSX.writeFile(
|
|
85
|
-
this.convert(rank),
|
|
86
|
-
filename,
|
|
87
|
-
{
|
|
88
|
-
compression: true,
|
|
89
|
-
});
|
|
106
|
+
return sheet;
|
|
90
107
|
}
|
|
91
108
|
|
|
92
109
|
private convertToAoa(rank: Rank): string[][] {
|
|
93
110
|
const aoa: string[][] = [];
|
|
94
111
|
|
|
112
|
+
const enableAwards = rank.contest.isEnableAwards(rank.options.group);
|
|
113
|
+
|
|
95
114
|
{
|
|
96
115
|
aoa.push([rank.contest.name]);
|
|
97
116
|
}
|
|
@@ -106,6 +125,11 @@ export class GeneralExcelConverter {
|
|
|
106
125
|
}
|
|
107
126
|
|
|
108
127
|
head.push("Name", "Solved", "Penalty", ...rank.contest.problems.map(p => p.label), "Dict");
|
|
128
|
+
|
|
129
|
+
if (enableAwards) {
|
|
130
|
+
head.push("Medal");
|
|
131
|
+
}
|
|
132
|
+
|
|
109
133
|
aoa.push(head);
|
|
110
134
|
}
|
|
111
135
|
|
|
@@ -145,6 +169,13 @@ export class GeneralExcelConverter {
|
|
|
145
169
|
|
|
146
170
|
arr.push(`${team.dict}%`);
|
|
147
171
|
|
|
172
|
+
if (enableAwards) {
|
|
173
|
+
const medals = team.awards
|
|
174
|
+
.filter(a => isValidMedalType(a))
|
|
175
|
+
.map(a => a.toString());
|
|
176
|
+
arr.push(medals.join(", "));
|
|
177
|
+
}
|
|
178
|
+
|
|
148
179
|
aoa.push(arr);
|
|
149
180
|
}
|
|
150
181
|
|
package/src/submission-status.ts
CHANGED
package/src/team.ts
CHANGED
|
@@ -51,6 +51,8 @@ export class Team {
|
|
|
51
51
|
|
|
52
52
|
awards: MedalType[];
|
|
53
53
|
|
|
54
|
+
location?: string;
|
|
55
|
+
|
|
54
56
|
constructor() {
|
|
55
57
|
this.id = "";
|
|
56
58
|
this.name = "";
|
|
@@ -101,6 +103,8 @@ export class Team {
|
|
|
101
103
|
this.submissions = [];
|
|
102
104
|
|
|
103
105
|
this.placeChartPoints = [];
|
|
106
|
+
|
|
107
|
+
this.awards = [];
|
|
104
108
|
}
|
|
105
109
|
|
|
106
110
|
get penaltyToMinute() {
|
|
@@ -242,6 +246,10 @@ export function createTeam(teamJSON: ITeam): Team {
|
|
|
242
246
|
t.group = [...new Set(t.group)];
|
|
243
247
|
t.group.sort();
|
|
244
248
|
|
|
249
|
+
if (teamJSON.location) {
|
|
250
|
+
t.location = teamJSON.location;
|
|
251
|
+
}
|
|
252
|
+
|
|
245
253
|
return t;
|
|
246
254
|
}
|
|
247
255
|
|