@xcpcio/core 0.41.1 → 0.41.3
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 +65 -5
- package/dist/index.d.ts +9 -2
- package/dist/index.mjs +63 -6
- package/package.json +5 -2
- package/src/export/icpc-standings-csv.ts +88 -0
- package/src/export/index.ts +1 -0
- package/src/rank.ts +1 -1
- package/src/team.ts +10 -5
package/dist/index.cjs
CHANGED
|
@@ -15,6 +15,8 @@ const relativeTime = require('dayjs/plugin/relativeTime');
|
|
|
15
15
|
const _ = require('lodash');
|
|
16
16
|
const XLSX = require('xlsx-js-style');
|
|
17
17
|
const stringWidth = require('string-width');
|
|
18
|
+
const Papa = require('papaparse');
|
|
19
|
+
const ordinal = require('ordinal');
|
|
18
20
|
const chroma = require('chroma-js');
|
|
19
21
|
const colorDiff = require('color-diff');
|
|
20
22
|
|
|
@@ -44,6 +46,8 @@ const relativeTime__default = /*#__PURE__*/_interopDefaultLegacy(relativeTime);
|
|
|
44
46
|
const ___default = /*#__PURE__*/_interopDefaultLegacy(_);
|
|
45
47
|
const XLSX__namespace = /*#__PURE__*/_interopNamespace(XLSX);
|
|
46
48
|
const stringWidth__default = /*#__PURE__*/_interopDefaultLegacy(stringWidth);
|
|
49
|
+
const Papa__default = /*#__PURE__*/_interopDefaultLegacy(Papa);
|
|
50
|
+
const ordinal__default = /*#__PURE__*/_interopDefaultLegacy(ordinal);
|
|
47
51
|
const chroma__default = /*#__PURE__*/_interopDefaultLegacy(chroma);
|
|
48
52
|
|
|
49
53
|
function stringToSubmissionStatus(status) {
|
|
@@ -491,6 +495,58 @@ class GeneralExcelConverter {
|
|
|
491
495
|
}
|
|
492
496
|
}
|
|
493
497
|
|
|
498
|
+
class ICPCStandingsCsvConverter {
|
|
499
|
+
constructor() {
|
|
500
|
+
}
|
|
501
|
+
convert(oriRank) {
|
|
502
|
+
const rank = ___default.cloneDeep(oriRank);
|
|
503
|
+
rank.options.disableFilterTeamsByGroup();
|
|
504
|
+
rank.options.disableFilterSubmissionByTimestamp();
|
|
505
|
+
rank.options.setGroup("official");
|
|
506
|
+
rank.buildRank();
|
|
507
|
+
const resList = [];
|
|
508
|
+
for (const team of rank.teams) {
|
|
509
|
+
const res = {
|
|
510
|
+
teamId: team.icpcID ?? "",
|
|
511
|
+
rank: team.rank,
|
|
512
|
+
medalCitation: this.getMedalCitation(team),
|
|
513
|
+
problemsSolved: team.solvedProblemNum,
|
|
514
|
+
totalTime: team.penaltyToMinute,
|
|
515
|
+
lastProblemTime: team.lastSolvedProblemStatistics?.solvedTimestampToMinute ?? 0,
|
|
516
|
+
siteCitation: rank.contest.name,
|
|
517
|
+
citation: ordinal__default(team.rank),
|
|
518
|
+
teamName: team.name,
|
|
519
|
+
institution: team.organization
|
|
520
|
+
};
|
|
521
|
+
resList.push(res);
|
|
522
|
+
}
|
|
523
|
+
const csv = Papa__default.unparse(resList);
|
|
524
|
+
return csv;
|
|
525
|
+
}
|
|
526
|
+
getMedalCitation(team) {
|
|
527
|
+
if (team.solvedProblemNum === 0) {
|
|
528
|
+
return "";
|
|
529
|
+
}
|
|
530
|
+
const medals = team.awards.filter((a) => isValidMedalType(a)).map((a) => a.toString());
|
|
531
|
+
if (medals.length === 1) {
|
|
532
|
+
const medal = medals[0];
|
|
533
|
+
if (medal === "Gold") {
|
|
534
|
+
return "Gold Medal";
|
|
535
|
+
}
|
|
536
|
+
if (medal === "Silver") {
|
|
537
|
+
return "Silver Medal";
|
|
538
|
+
}
|
|
539
|
+
if (medal === "Bronze") {
|
|
540
|
+
return "Bronze Medal";
|
|
541
|
+
}
|
|
542
|
+
if (medal === "Honorable") {
|
|
543
|
+
return "Honorable Mention";
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
return "";
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
|
|
494
550
|
function calcDirt(attemptedNum, solvedNum) {
|
|
495
551
|
if (solvedNum === 0) {
|
|
496
552
|
return 0;
|
|
@@ -666,7 +722,7 @@ class Team {
|
|
|
666
722
|
this.solvedProblemNum = 0;
|
|
667
723
|
this.attemptedProblemNum = 0;
|
|
668
724
|
this.lastSolvedProblem = null;
|
|
669
|
-
this.
|
|
725
|
+
this.lastSolvedProblemStatistics = null;
|
|
670
726
|
this.penalty = 0;
|
|
671
727
|
this.problemStatistics = [];
|
|
672
728
|
this.problemStatisticsMap = /* @__PURE__ */ new Map();
|
|
@@ -682,7 +738,7 @@ class Team {
|
|
|
682
738
|
this.solvedProblemNum = 0;
|
|
683
739
|
this.attemptedProblemNum = 0;
|
|
684
740
|
this.lastSolvedProblem = null;
|
|
685
|
-
this.
|
|
741
|
+
this.lastSolvedProblemStatistics = null;
|
|
686
742
|
this.penalty = 0;
|
|
687
743
|
this.problemStatistics = [];
|
|
688
744
|
this.problemStatisticsMap = /* @__PURE__ */ new Map();
|
|
@@ -801,8 +857,8 @@ class Team {
|
|
|
801
857
|
if (lhs.penalty !== rhs.penalty) {
|
|
802
858
|
return lhs.penalty - rhs.penalty;
|
|
803
859
|
}
|
|
804
|
-
if (lhs.
|
|
805
|
-
return lhs.
|
|
860
|
+
if (lhs.lastSolvedProblemStatistics && rhs.lastSolvedProblemStatistics) {
|
|
861
|
+
return lhs.lastSolvedProblemStatistics.solvedTimestampToMinute - rhs.lastSolvedProblemStatistics.solvedTimestampToMinute;
|
|
806
862
|
}
|
|
807
863
|
if (lhs.name < rhs.name) {
|
|
808
864
|
return -1;
|
|
@@ -844,6 +900,9 @@ function createTeam(teamJSON) {
|
|
|
844
900
|
if (teamJSON.location) {
|
|
845
901
|
t.location = teamJSON.location;
|
|
846
902
|
}
|
|
903
|
+
if (teamJSON.icpc_id) {
|
|
904
|
+
t.icpcID = teamJSON.icpc_id;
|
|
905
|
+
}
|
|
847
906
|
return t;
|
|
848
907
|
}
|
|
849
908
|
function createTeams(teamsJSON) {
|
|
@@ -1526,7 +1585,7 @@ class Rank {
|
|
|
1526
1585
|
}
|
|
1527
1586
|
problem.statistics.lastSolveSubmissions.push(s);
|
|
1528
1587
|
team.lastSolvedProblem = problem;
|
|
1529
|
-
team.
|
|
1588
|
+
team.lastSolvedProblemStatistics = problemStatistics;
|
|
1530
1589
|
}
|
|
1531
1590
|
if (s.isRejected()) {
|
|
1532
1591
|
problemStatistics.failedCount++;
|
|
@@ -1845,6 +1904,7 @@ exports.ContestIndex = ContestIndex;
|
|
|
1845
1904
|
exports.ContestIndexConfig = ContestIndexConfig;
|
|
1846
1905
|
exports.ContestOptions = ContestOptions;
|
|
1847
1906
|
exports.GeneralExcelConverter = GeneralExcelConverter;
|
|
1907
|
+
exports.ICPCStandingsCsvConverter = ICPCStandingsCsvConverter;
|
|
1848
1908
|
exports.MedalType = MedalType;
|
|
1849
1909
|
exports.PlaceChartPointData = PlaceChartPointData;
|
|
1850
1910
|
exports.Problem = Problem;
|
package/dist/index.d.ts
CHANGED
|
@@ -189,7 +189,7 @@ declare class Team {
|
|
|
189
189
|
solvedProblemNum: number;
|
|
190
190
|
attemptedProblemNum: number;
|
|
191
191
|
lastSolvedProblem: Problem | null;
|
|
192
|
-
|
|
192
|
+
lastSolvedProblemStatistics: TeamProblemStatistics | null;
|
|
193
193
|
penalty: number;
|
|
194
194
|
problemStatistics: Array<TeamProblemStatistics>;
|
|
195
195
|
problemStatisticsMap: Map<string, TeamProblemStatistics>;
|
|
@@ -197,6 +197,7 @@ declare class Team {
|
|
|
197
197
|
placeChartPoints: Array<PlaceChartPointData>;
|
|
198
198
|
awards: MedalType[];
|
|
199
199
|
location?: string;
|
|
200
|
+
icpcID?: string;
|
|
200
201
|
se: number;
|
|
201
202
|
constructor();
|
|
202
203
|
reset(): void;
|
|
@@ -303,6 +304,12 @@ declare class GeneralExcelConverter {
|
|
|
303
304
|
private convertToAoa;
|
|
304
305
|
}
|
|
305
306
|
|
|
307
|
+
declare class ICPCStandingsCsvConverter {
|
|
308
|
+
constructor();
|
|
309
|
+
convert(oriRank: Rank): string;
|
|
310
|
+
private getMedalCitation;
|
|
311
|
+
}
|
|
312
|
+
|
|
306
313
|
declare class ContestIndexConfig {
|
|
307
314
|
contestName: string;
|
|
308
315
|
startTime: dayjs.Dayjs;
|
|
@@ -349,4 +356,4 @@ declare function isRejected(status: SubmissionStatus): boolean;
|
|
|
349
356
|
declare function isPending(status: SubmissionStatus): boolean;
|
|
350
357
|
declare function isNotCalculatedPenaltyStatus(status: SubmissionStatus): boolean;
|
|
351
358
|
|
|
352
|
-
export { Award, Awards, Balloon, Balloons, CodeforcesGymGhostDATConverter, Contest, ContestIndex, ContestIndexConfig, ContestIndexList, ContestOptions, GeneralExcelConverter, MedalType, PlaceChartPointData, Problem, ProblemStatistics, Problems, Rank, RankOptions, RankStatistics, Resolver, SelectOptionItem, Submission, Submissions, Team, TeamProblemStatistics, Teams, calcDirt, createContest, createContestIndex, createContestIndexList, createDayJS, createProblem, createProblems, createProblemsByProblemIds, createSubmission, createSubmissions, createTeam, createTeams, getImageSource, getTimeDiff, getTimestamp, getWhiteOrBlackColor, getWhiteOrBlackColorV1, isAccepted, isNotCalculatedPenaltyStatus, isPending, isRejected, isValidMedalType, stringToSubmissionStatus };
|
|
359
|
+
export { Award, Awards, Balloon, Balloons, CodeforcesGymGhostDATConverter, Contest, ContestIndex, ContestIndexConfig, ContestIndexList, ContestOptions, GeneralExcelConverter, ICPCStandingsCsvConverter, MedalType, PlaceChartPointData, Problem, ProblemStatistics, Problems, Rank, RankOptions, RankStatistics, Resolver, SelectOptionItem, Submission, Submissions, Team, TeamProblemStatistics, Teams, calcDirt, createContest, createContestIndex, createContestIndexList, createDayJS, createProblem, createProblems, createProblemsByProblemIds, createSubmission, createSubmissions, createTeam, createTeams, getImageSource, getTimeDiff, getTimestamp, getWhiteOrBlackColor, getWhiteOrBlackColorV1, isAccepted, isNotCalculatedPenaltyStatus, isPending, isRejected, isValidMedalType, stringToSubmissionStatus };
|
package/dist/index.mjs
CHANGED
|
@@ -12,6 +12,8 @@ import relativeTime from 'dayjs/plugin/relativeTime';
|
|
|
12
12
|
import _ from 'lodash';
|
|
13
13
|
import * as XLSX from 'xlsx-js-style';
|
|
14
14
|
import stringWidth from 'string-width';
|
|
15
|
+
import Papa from 'papaparse';
|
|
16
|
+
import ordinal from 'ordinal';
|
|
15
17
|
import chroma from 'chroma-js';
|
|
16
18
|
import { furthest } from 'color-diff';
|
|
17
19
|
|
|
@@ -460,6 +462,58 @@ class GeneralExcelConverter {
|
|
|
460
462
|
}
|
|
461
463
|
}
|
|
462
464
|
|
|
465
|
+
class ICPCStandingsCsvConverter {
|
|
466
|
+
constructor() {
|
|
467
|
+
}
|
|
468
|
+
convert(oriRank) {
|
|
469
|
+
const rank = _.cloneDeep(oriRank);
|
|
470
|
+
rank.options.disableFilterTeamsByGroup();
|
|
471
|
+
rank.options.disableFilterSubmissionByTimestamp();
|
|
472
|
+
rank.options.setGroup("official");
|
|
473
|
+
rank.buildRank();
|
|
474
|
+
const resList = [];
|
|
475
|
+
for (const team of rank.teams) {
|
|
476
|
+
const res = {
|
|
477
|
+
teamId: team.icpcID ?? "",
|
|
478
|
+
rank: team.rank,
|
|
479
|
+
medalCitation: this.getMedalCitation(team),
|
|
480
|
+
problemsSolved: team.solvedProblemNum,
|
|
481
|
+
totalTime: team.penaltyToMinute,
|
|
482
|
+
lastProblemTime: team.lastSolvedProblemStatistics?.solvedTimestampToMinute ?? 0,
|
|
483
|
+
siteCitation: rank.contest.name,
|
|
484
|
+
citation: ordinal(team.rank),
|
|
485
|
+
teamName: team.name,
|
|
486
|
+
institution: team.organization
|
|
487
|
+
};
|
|
488
|
+
resList.push(res);
|
|
489
|
+
}
|
|
490
|
+
const csv = Papa.unparse(resList);
|
|
491
|
+
return csv;
|
|
492
|
+
}
|
|
493
|
+
getMedalCitation(team) {
|
|
494
|
+
if (team.solvedProblemNum === 0) {
|
|
495
|
+
return "";
|
|
496
|
+
}
|
|
497
|
+
const medals = team.awards.filter((a) => isValidMedalType(a)).map((a) => a.toString());
|
|
498
|
+
if (medals.length === 1) {
|
|
499
|
+
const medal = medals[0];
|
|
500
|
+
if (medal === "Gold") {
|
|
501
|
+
return "Gold Medal";
|
|
502
|
+
}
|
|
503
|
+
if (medal === "Silver") {
|
|
504
|
+
return "Silver Medal";
|
|
505
|
+
}
|
|
506
|
+
if (medal === "Bronze") {
|
|
507
|
+
return "Bronze Medal";
|
|
508
|
+
}
|
|
509
|
+
if (medal === "Honorable") {
|
|
510
|
+
return "Honorable Mention";
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
return "";
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
|
|
463
517
|
function calcDirt(attemptedNum, solvedNum) {
|
|
464
518
|
if (solvedNum === 0) {
|
|
465
519
|
return 0;
|
|
@@ -635,7 +689,7 @@ class Team {
|
|
|
635
689
|
this.solvedProblemNum = 0;
|
|
636
690
|
this.attemptedProblemNum = 0;
|
|
637
691
|
this.lastSolvedProblem = null;
|
|
638
|
-
this.
|
|
692
|
+
this.lastSolvedProblemStatistics = null;
|
|
639
693
|
this.penalty = 0;
|
|
640
694
|
this.problemStatistics = [];
|
|
641
695
|
this.problemStatisticsMap = /* @__PURE__ */ new Map();
|
|
@@ -651,7 +705,7 @@ class Team {
|
|
|
651
705
|
this.solvedProblemNum = 0;
|
|
652
706
|
this.attemptedProblemNum = 0;
|
|
653
707
|
this.lastSolvedProblem = null;
|
|
654
|
-
this.
|
|
708
|
+
this.lastSolvedProblemStatistics = null;
|
|
655
709
|
this.penalty = 0;
|
|
656
710
|
this.problemStatistics = [];
|
|
657
711
|
this.problemStatisticsMap = /* @__PURE__ */ new Map();
|
|
@@ -770,8 +824,8 @@ class Team {
|
|
|
770
824
|
if (lhs.penalty !== rhs.penalty) {
|
|
771
825
|
return lhs.penalty - rhs.penalty;
|
|
772
826
|
}
|
|
773
|
-
if (lhs.
|
|
774
|
-
return lhs.
|
|
827
|
+
if (lhs.lastSolvedProblemStatistics && rhs.lastSolvedProblemStatistics) {
|
|
828
|
+
return lhs.lastSolvedProblemStatistics.solvedTimestampToMinute - rhs.lastSolvedProblemStatistics.solvedTimestampToMinute;
|
|
775
829
|
}
|
|
776
830
|
if (lhs.name < rhs.name) {
|
|
777
831
|
return -1;
|
|
@@ -813,6 +867,9 @@ function createTeam(teamJSON) {
|
|
|
813
867
|
if (teamJSON.location) {
|
|
814
868
|
t.location = teamJSON.location;
|
|
815
869
|
}
|
|
870
|
+
if (teamJSON.icpc_id) {
|
|
871
|
+
t.icpcID = teamJSON.icpc_id;
|
|
872
|
+
}
|
|
816
873
|
return t;
|
|
817
874
|
}
|
|
818
875
|
function createTeams(teamsJSON) {
|
|
@@ -1495,7 +1552,7 @@ class Rank {
|
|
|
1495
1552
|
}
|
|
1496
1553
|
problem.statistics.lastSolveSubmissions.push(s);
|
|
1497
1554
|
team.lastSolvedProblem = problem;
|
|
1498
|
-
team.
|
|
1555
|
+
team.lastSolvedProblemStatistics = problemStatistics;
|
|
1499
1556
|
}
|
|
1500
1557
|
if (s.isRejected()) {
|
|
1501
1558
|
problemStatistics.failedCount++;
|
|
@@ -1805,4 +1862,4 @@ class Resolver extends Rank {
|
|
|
1805
1862
|
}
|
|
1806
1863
|
}
|
|
1807
1864
|
|
|
1808
|
-
export { Award, Balloon, CodeforcesGymGhostDATConverter, Contest, ContestIndex, ContestIndexConfig, ContestOptions, GeneralExcelConverter, MedalType, PlaceChartPointData, Problem, ProblemStatistics, Rank, RankOptions, RankStatistics, Resolver, Submission, Team, TeamProblemStatistics, calcDirt, createContest, createContestIndex, createContestIndexList, createDayJS, createProblem, createProblems, createProblemsByProblemIds, createSubmission, createSubmissions, createTeam, createTeams, getImageSource, getTimeDiff, getTimestamp, getWhiteOrBlackColor, getWhiteOrBlackColorV1, isAccepted, isNotCalculatedPenaltyStatus, isPending, isRejected, isValidMedalType, stringToSubmissionStatus };
|
|
1865
|
+
export { Award, Balloon, CodeforcesGymGhostDATConverter, Contest, ContestIndex, ContestIndexConfig, ContestOptions, GeneralExcelConverter, ICPCStandingsCsvConverter, MedalType, PlaceChartPointData, Problem, ProblemStatistics, Rank, RankOptions, RankStatistics, Resolver, Submission, Team, TeamProblemStatistics, calcDirt, createContest, createContestIndex, createContestIndexList, createDayJS, createProblem, createProblems, createProblemsByProblemIds, createSubmission, createSubmissions, createTeam, createTeams, getImageSource, getTimeDiff, getTimestamp, getWhiteOrBlackColor, getWhiteOrBlackColorV1, isAccepted, isNotCalculatedPenaltyStatus, isPending, isRejected, isValidMedalType, stringToSubmissionStatus };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xcpcio/core",
|
|
3
|
-
"version": "0.41.
|
|
3
|
+
"version": "0.41.3",
|
|
4
4
|
"description": "XCPCIO Core",
|
|
5
5
|
"author": "Dup4 <lyuzhi.pan@gmail.com>",
|
|
6
6
|
"license": "MIT",
|
|
@@ -44,9 +44,11 @@
|
|
|
44
44
|
"color-diff": "^1.4.0",
|
|
45
45
|
"dayjs": "^1.11.8",
|
|
46
46
|
"lodash": "^4.17.21",
|
|
47
|
+
"ordinal": "^1.0.3",
|
|
48
|
+
"papaparse": "^5.4.1",
|
|
47
49
|
"string-width": "^6.1.0",
|
|
48
50
|
"xlsx-js-style": "^1.2.0",
|
|
49
|
-
"@xcpcio/types": "0.41.
|
|
51
|
+
"@xcpcio/types": "0.41.3"
|
|
50
52
|
},
|
|
51
53
|
"devDependencies": {
|
|
52
54
|
"@babel/types": "^7.22.4",
|
|
@@ -54,6 +56,7 @@
|
|
|
54
56
|
"@types/color-diff": "^1.2.3",
|
|
55
57
|
"@types/lodash": "^4.14.195",
|
|
56
58
|
"@types/node": "^17.0.45",
|
|
59
|
+
"@types/papaparse": "^5.3.14",
|
|
57
60
|
"@typescript-eslint/eslint-plugin": "^5.59.9",
|
|
58
61
|
"@typescript-eslint/parser": "^5.59.9",
|
|
59
62
|
"bumpp": "^7.2.0",
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import _ from "lodash";
|
|
2
|
+
import Papa from "papaparse";
|
|
3
|
+
import ordinal from "ordinal";
|
|
4
|
+
|
|
5
|
+
import type { Rank } from "../rank";
|
|
6
|
+
import type { Team } from "../team";
|
|
7
|
+
import { isValidMedalType } from "../award";
|
|
8
|
+
|
|
9
|
+
interface ICPCTeamResult {
|
|
10
|
+
teamId: string;
|
|
11
|
+
rank: number;
|
|
12
|
+
medalCitation: string;
|
|
13
|
+
problemsSolved: number;
|
|
14
|
+
totalTime: number;
|
|
15
|
+
lastProblemTime: number;
|
|
16
|
+
siteCitation: string;
|
|
17
|
+
citation: string;
|
|
18
|
+
teamName: string;
|
|
19
|
+
institution: string;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export class ICPCStandingsCsvConverter {
|
|
23
|
+
constructor() {}
|
|
24
|
+
|
|
25
|
+
public convert(oriRank: Rank) {
|
|
26
|
+
const rank = _.cloneDeep(oriRank);
|
|
27
|
+
|
|
28
|
+
rank.options.disableFilterTeamsByGroup();
|
|
29
|
+
rank.options.disableFilterSubmissionByTimestamp();
|
|
30
|
+
|
|
31
|
+
rank.options.setGroup("official");
|
|
32
|
+
rank.buildRank();
|
|
33
|
+
|
|
34
|
+
const resList: Array<ICPCTeamResult> = [];
|
|
35
|
+
|
|
36
|
+
for (const team of rank.teams) {
|
|
37
|
+
const res: ICPCTeamResult = {
|
|
38
|
+
teamId: team.icpcID ?? "",
|
|
39
|
+
rank: team.rank,
|
|
40
|
+
medalCitation: this.getMedalCitation(team),
|
|
41
|
+
problemsSolved: team.solvedProblemNum,
|
|
42
|
+
totalTime: team.penaltyToMinute,
|
|
43
|
+
lastProblemTime: team.lastSolvedProblemStatistics?.solvedTimestampToMinute ?? 0,
|
|
44
|
+
siteCitation: rank.contest.name,
|
|
45
|
+
citation: ordinal(team.rank),
|
|
46
|
+
teamName: team.name,
|
|
47
|
+
institution: team.organization,
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
resList.push(res);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const csv = Papa.unparse(resList);
|
|
54
|
+
|
|
55
|
+
return csv;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
private getMedalCitation(team: Team): string {
|
|
59
|
+
if (team.solvedProblemNum === 0) {
|
|
60
|
+
return "";
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const medals = team.awards
|
|
64
|
+
.filter(a => isValidMedalType(a))
|
|
65
|
+
.map(a => a.toString());
|
|
66
|
+
|
|
67
|
+
if (medals.length === 1) {
|
|
68
|
+
const medal = medals[0];
|
|
69
|
+
if (medal === "Gold") {
|
|
70
|
+
return "Gold Medal";
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (medal === "Silver") {
|
|
74
|
+
return "Silver Medal";
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (medal === "Bronze") {
|
|
78
|
+
return "Bronze Medal";
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (medal === "Honorable") {
|
|
82
|
+
return "Honorable Mention";
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return "";
|
|
87
|
+
}
|
|
88
|
+
}
|
package/src/export/index.ts
CHANGED
package/src/rank.ts
CHANGED
|
@@ -312,7 +312,7 @@ export class Rank {
|
|
|
312
312
|
problem.statistics.lastSolveSubmissions.push(s);
|
|
313
313
|
|
|
314
314
|
team.lastSolvedProblem = problem;
|
|
315
|
-
team.
|
|
315
|
+
team.lastSolvedProblemStatistics = problemStatistics;
|
|
316
316
|
}
|
|
317
317
|
|
|
318
318
|
if (s.isRejected()) {
|
package/src/team.ts
CHANGED
|
@@ -39,7 +39,7 @@ export class Team {
|
|
|
39
39
|
attemptedProblemNum: number;
|
|
40
40
|
|
|
41
41
|
lastSolvedProblem: Problem | null;
|
|
42
|
-
|
|
42
|
+
lastSolvedProblemStatistics: TeamProblemStatistics | null;
|
|
43
43
|
|
|
44
44
|
penalty: number;
|
|
45
45
|
|
|
@@ -53,6 +53,7 @@ export class Team {
|
|
|
53
53
|
awards: MedalType[];
|
|
54
54
|
|
|
55
55
|
location?: string;
|
|
56
|
+
icpcID?: string;
|
|
56
57
|
|
|
57
58
|
se: number;
|
|
58
59
|
|
|
@@ -73,7 +74,7 @@ export class Team {
|
|
|
73
74
|
this.attemptedProblemNum = 0;
|
|
74
75
|
|
|
75
76
|
this.lastSolvedProblem = null;
|
|
76
|
-
this.
|
|
77
|
+
this.lastSolvedProblemStatistics = null;
|
|
77
78
|
|
|
78
79
|
this.penalty = 0;
|
|
79
80
|
|
|
@@ -98,7 +99,7 @@ export class Team {
|
|
|
98
99
|
this.attemptedProblemNum = 0;
|
|
99
100
|
|
|
100
101
|
this.lastSolvedProblem = null;
|
|
101
|
-
this.
|
|
102
|
+
this.lastSolvedProblemStatistics = null;
|
|
102
103
|
|
|
103
104
|
this.penalty = 0;
|
|
104
105
|
|
|
@@ -258,8 +259,8 @@ export class Team {
|
|
|
258
259
|
return lhs.penalty - rhs.penalty;
|
|
259
260
|
}
|
|
260
261
|
|
|
261
|
-
if (lhs.
|
|
262
|
-
return lhs.
|
|
262
|
+
if (lhs.lastSolvedProblemStatistics && rhs.lastSolvedProblemStatistics) {
|
|
263
|
+
return lhs.lastSolvedProblemStatistics.solvedTimestampToMinute - rhs.lastSolvedProblemStatistics.solvedTimestampToMinute;
|
|
263
264
|
}
|
|
264
265
|
|
|
265
266
|
if (lhs.name < rhs.name) {
|
|
@@ -317,6 +318,10 @@ export function createTeam(teamJSON: ITeam): Team {
|
|
|
317
318
|
t.location = teamJSON.location;
|
|
318
319
|
}
|
|
319
320
|
|
|
321
|
+
if (teamJSON.icpc_id) {
|
|
322
|
+
t.icpcID = teamJSON.icpc_id;
|
|
323
|
+
}
|
|
324
|
+
|
|
320
325
|
return t;
|
|
321
326
|
}
|
|
322
327
|
|