@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 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(rank) {
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 mainWorksheet = XLSX__namespace.utils.aoa_to_sheet(aoa);
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
- mainWorksheet["!cols"] = cols;
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
- mainWorksheet["!merges"] = merges;
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 = mainWorksheet[cellAddress];
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 = mainWorksheet[cellAddress];
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
- XLSX__namespace.utils.book_append_sheet(workbook, mainWorksheet, "Scoreboard");
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 = 0,
92
- GOLD = 1,
93
- SILVER = 2,
94
- BRONZE = 3,
95
- HONORABLE = 4
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(rank: Rank): XLSX.WorkBook;
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(rank) {
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 mainWorksheet = XLSX.utils.aoa_to_sheet(aoa);
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
- mainWorksheet["!cols"] = cols;
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
- mainWorksheet["!merges"] = merges;
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 = mainWorksheet[cellAddress];
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 = mainWorksheet[cellAddress];
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
- XLSX.utils.book_append_sheet(workbook, mainWorksheet, "Scoreboard");
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.14.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.14.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(rank: Rank): XLSX.WorkBook {
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 mainWorksheet = XLSX.utils.aoa_to_sheet(aoa);
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
- mainWorksheet["!cols"] = cols;
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
- mainWorksheet["!merges"] = merges;
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 = mainWorksheet[cellAddress];
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 = mainWorksheet[cellAddress];
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
- XLSX.utils.book_append_sheet(workbook, mainWorksheet, "Scoreboard");
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
 
@@ -128,6 +128,7 @@ export function isPending(status: SubmissionStatus): boolean {
128
128
  const pendingArray = [
129
129
  SubmissionStatus.PENDING,
130
130
  SubmissionStatus.WAITING,
131
+ SubmissionStatus.COMPILING,
131
132
  SubmissionStatus.JUDGING,
132
133
  SubmissionStatus.FROZEN,
133
134
  ];
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