@xcpcio/core 0.55.2 → 0.57.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 +43 -14
- package/dist/index.d.cts +77 -74
- package/dist/index.d.mts +77 -74
- package/dist/index.d.ts +77 -74
- package/dist/index.mjs +43 -14
- package/package.json +20 -20
- package/src/contest-options.ts +13 -2
- package/src/export/general-excel.ts +46 -10
- package/src/submission.ts +10 -5
package/dist/index.cjs
CHANGED
|
@@ -512,7 +512,7 @@ class Submission {
|
|
|
512
512
|
}
|
|
513
513
|
}
|
|
514
514
|
}
|
|
515
|
-
function createSubmission(submissionJSON) {
|
|
515
|
+
function createSubmission(submissionJSON, contest) {
|
|
516
516
|
const s = new Submission();
|
|
517
517
|
s.id = String(submissionJSON.id ?? submissionJSON.submission_id ?? "");
|
|
518
518
|
s.teamId = String(submissionJSON.team_id);
|
|
@@ -528,15 +528,19 @@ function createSubmission(submissionJSON) {
|
|
|
528
528
|
}
|
|
529
529
|
if (submissionJSON.reaction) {
|
|
530
530
|
s.reaction = submissionJSON.reaction;
|
|
531
|
+
} else if (contest?.options.reactionVideoUrlTemplate) {
|
|
532
|
+
s.reaction = {
|
|
533
|
+
url: contest.options.reactionVideoUrlTemplate.replace(/\$\{submission_id\}/, s.id)
|
|
534
|
+
};
|
|
531
535
|
}
|
|
532
536
|
return s;
|
|
533
537
|
}
|
|
534
|
-
function createSubmissions(submissionsJSON) {
|
|
538
|
+
function createSubmissions(submissionsJSON, contest) {
|
|
535
539
|
if (Array.isArray(submissionsJSON)) {
|
|
536
|
-
return submissionsJSON.map((s, index) => createSubmission({ ...s, id: s.submission_id ?? String(index) }));
|
|
540
|
+
return submissionsJSON.map((s, index) => createSubmission({ ...s, id: s.submission_id ?? String(index) }, contest));
|
|
537
541
|
} else {
|
|
538
542
|
const submissions = Object.entries(submissionsJSON).map(
|
|
539
|
-
([submissionId, s]) => createSubmission({ ...s, id: s.submission_id ?? submissionId })
|
|
543
|
+
([submissionId, s]) => createSubmission({ ...s, id: s.submission_id ?? submissionId }, contest)
|
|
540
544
|
);
|
|
541
545
|
return submissions;
|
|
542
546
|
}
|
|
@@ -928,12 +932,16 @@ class ContestOptions {
|
|
|
928
932
|
submissionHasTimeField;
|
|
929
933
|
submissionHasLanguageField;
|
|
930
934
|
submissionEnableActionField;
|
|
935
|
+
submissionHasReactionField;
|
|
936
|
+
reactionVideoUrlTemplate;
|
|
931
937
|
constructor() {
|
|
932
938
|
this.calculationOfPenalty = "in_minutes";
|
|
933
939
|
this.submissionTimestampUnit = "second";
|
|
934
940
|
this.submissionHasTimeField = false;
|
|
935
941
|
this.submissionHasLanguageField = false;
|
|
936
942
|
this.submissionEnableActionField = false;
|
|
943
|
+
this.submissionHasReactionField = false;
|
|
944
|
+
this.reactionVideoUrlTemplate = void 0;
|
|
937
945
|
}
|
|
938
946
|
}
|
|
939
947
|
function createContestOptions(contestOptionsJSON = {}) {
|
|
@@ -945,9 +953,11 @@ function createContestOptions(contestOptionsJSON = {}) {
|
|
|
945
953
|
if (j.submission_timestamp_unit) {
|
|
946
954
|
o.submissionTimestampUnit = j.submission_timestamp_unit;
|
|
947
955
|
}
|
|
948
|
-
if (j.submission_has_reaction) {
|
|
949
|
-
o.
|
|
956
|
+
if (j.submission_has_reaction || j.has_reaction_videos) {
|
|
957
|
+
o.submissionHasReactionField = true;
|
|
950
958
|
}
|
|
959
|
+
o.submissionEnableActionField = o.submissionHasReactionField;
|
|
960
|
+
o.reactionVideoUrlTemplate = j.reaction_video_url_template;
|
|
951
961
|
return o;
|
|
952
962
|
}
|
|
953
963
|
|
|
@@ -1405,13 +1415,13 @@ class GeneralExcelConverter {
|
|
|
1405
1415
|
}
|
|
1406
1416
|
convertToSheet(rank) {
|
|
1407
1417
|
const aoa = this.convertToAoa(rank);
|
|
1408
|
-
const sheet = XLSX__namespace.utils.aoa_to_sheet(aoa);
|
|
1418
|
+
const sheet = XLSX__namespace.utils.aoa_to_sheet(aoa.aoa);
|
|
1409
1419
|
const cols = [];
|
|
1410
|
-
const head = aoa[1];
|
|
1420
|
+
const head = aoa.aoa[1];
|
|
1411
1421
|
for (let j = 0; j < head.length; j++) {
|
|
1412
1422
|
let wch = 10;
|
|
1413
|
-
for (let i = 1; i < aoa.length; i++) {
|
|
1414
|
-
wch = Math.max(wch, stringWidth__default(aoa[i][j]) + 2);
|
|
1423
|
+
for (let i = 1; i < aoa.aoa.length; i++) {
|
|
1424
|
+
wch = Math.max(wch, stringWidth__default(aoa.aoa[i][j]) + 2);
|
|
1415
1425
|
}
|
|
1416
1426
|
cols.push({
|
|
1417
1427
|
wch
|
|
@@ -1445,11 +1455,22 @@ class GeneralExcelConverter {
|
|
|
1445
1455
|
},
|
|
1446
1456
|
font
|
|
1447
1457
|
};
|
|
1448
|
-
|
|
1449
|
-
|
|
1458
|
+
const firstSolvedCellStyle = {
|
|
1459
|
+
...cellStyle,
|
|
1460
|
+
fill: {
|
|
1461
|
+
fgColor: { rgb: "009900" }
|
|
1462
|
+
}
|
|
1463
|
+
};
|
|
1464
|
+
for (let i = 1; i < aoa.aoa.length; i++) {
|
|
1465
|
+
for (let j = 0; j < aoa.aoa[i].length; j++) {
|
|
1450
1466
|
const cellAddress = XLSX__namespace.utils.encode_cell({ r: i, c: j });
|
|
1451
1467
|
const cell = sheet[cellAddress];
|
|
1452
|
-
|
|
1468
|
+
const specialCell = aoa.specialCells.find((sc) => sc.row === i && sc.col === j);
|
|
1469
|
+
if (specialCell?.type === "firstSolved" /* FIRST_SOLVED */) {
|
|
1470
|
+
cell.s = firstSolvedCellStyle;
|
|
1471
|
+
} else {
|
|
1472
|
+
cell.s = cellStyle;
|
|
1473
|
+
}
|
|
1453
1474
|
}
|
|
1454
1475
|
}
|
|
1455
1476
|
{
|
|
@@ -1464,6 +1485,7 @@ class GeneralExcelConverter {
|
|
|
1464
1485
|
}
|
|
1465
1486
|
convertToAoa(rank) {
|
|
1466
1487
|
const aoa = [];
|
|
1488
|
+
const specialCells = [];
|
|
1467
1489
|
const enableAwards = rank.contest.isEnableAwards(rank.options.group);
|
|
1468
1490
|
const enableMembers = (Array.isArray(rank.teams) && rank.teams[0]?.members) ?? false;
|
|
1469
1491
|
const enableCoach = rank.teams[0]?.coach ?? false;
|
|
@@ -1509,6 +1531,13 @@ class GeneralExcelConverter {
|
|
|
1509
1531
|
}
|
|
1510
1532
|
if (p.isSolved) {
|
|
1511
1533
|
arr.push(`+${p.totalCount}(${p.solvedTimestampToMinute})`);
|
|
1534
|
+
if (p.isFirstSolved) {
|
|
1535
|
+
specialCells.push({
|
|
1536
|
+
row: aoa.length,
|
|
1537
|
+
col: arr.length - 1,
|
|
1538
|
+
type: "firstSolved" /* FIRST_SOLVED */
|
|
1539
|
+
});
|
|
1540
|
+
}
|
|
1512
1541
|
}
|
|
1513
1542
|
if (p.isWrongAnswer) {
|
|
1514
1543
|
arr.push(`-${p.failedCount}`);
|
|
@@ -1543,7 +1572,7 @@ class GeneralExcelConverter {
|
|
|
1543
1572
|
arr.push(team.isGirl ? "Y" : "N");
|
|
1544
1573
|
aoa.push(arr);
|
|
1545
1574
|
}
|
|
1546
|
-
return aoa;
|
|
1575
|
+
return { aoa, specialCells };
|
|
1547
1576
|
}
|
|
1548
1577
|
}
|
|
1549
1578
|
|
package/dist/index.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { TimeUnit, SubmissionReaction, SubmissionStatus, Submission as Submission$1, Submissions as Submissions$1, BalloonColor, Problem as Problem$1, Problems as Problems$1,
|
|
1
|
+
import { CalculationOfPenalty, TimeUnit, Lang, StatusTimeDisplay, MedalPreset, Image, BannerMode, ContestState, Contest as Contest$1, SubmissionReaction, SubmissionStatus, Submission as Submission$1, Submissions as Submissions$1, BalloonColor, Problem as Problem$1, Problems as Problems$1, Team as Team$1, Teams as Teams$1, ContestIndex as ContestIndex$1, IPerson, IRatingHistory, IRatingUser, IRating } from '@xcpcio/types';
|
|
2
2
|
import dayjs from 'dayjs';
|
|
3
3
|
export { default as dayjs } from 'dayjs';
|
|
4
4
|
import * as XLSX from 'xlsx-js-style';
|
|
@@ -19,6 +19,78 @@ declare class Award {
|
|
|
19
19
|
declare function isValidMedalType(medal: MedalType): boolean;
|
|
20
20
|
type Awards = Map<string, Award[]>;
|
|
21
21
|
|
|
22
|
+
declare class ContestOptions {
|
|
23
|
+
calculationOfPenalty: CalculationOfPenalty;
|
|
24
|
+
submissionTimestampUnit: TimeUnit;
|
|
25
|
+
submissionHasTimeField: boolean;
|
|
26
|
+
submissionHasLanguageField: boolean;
|
|
27
|
+
submissionEnableActionField: boolean;
|
|
28
|
+
submissionHasReactionField: boolean;
|
|
29
|
+
reactionVideoUrlTemplate?: string;
|
|
30
|
+
constructor();
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
declare class Group {
|
|
34
|
+
names: Map<Lang, string>;
|
|
35
|
+
defaultLang: Lang;
|
|
36
|
+
isDefault: boolean;
|
|
37
|
+
constructor();
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
declare function calcDirt(attemptedNum: number, solvedNum: number): number;
|
|
41
|
+
|
|
42
|
+
declare function getWhiteOrBlackColorV1(background: string): "#000" | "#fff";
|
|
43
|
+
declare function getWhiteOrBlackColor(background: string): "#000" | "#fff";
|
|
44
|
+
|
|
45
|
+
declare function createDayJS(time?: Date | string | number | undefined): dayjs.Dayjs;
|
|
46
|
+
declare function getTimestamp(time: number | dayjs.Dayjs): number;
|
|
47
|
+
declare function getTimeDiff(seconds: number): string;
|
|
48
|
+
|
|
49
|
+
declare class Contest {
|
|
50
|
+
id: string;
|
|
51
|
+
name: string;
|
|
52
|
+
startTime: dayjs.Dayjs;
|
|
53
|
+
endTime: dayjs.Dayjs;
|
|
54
|
+
freezeTime: dayjs.Dayjs;
|
|
55
|
+
replayStartTime?: dayjs.Dayjs;
|
|
56
|
+
replayEndTime?: dayjs.Dayjs;
|
|
57
|
+
replayFreezeTime?: dayjs.Dayjs;
|
|
58
|
+
replayNowTime?: dayjs.Dayjs;
|
|
59
|
+
replayContestStartTimestamp?: number;
|
|
60
|
+
totalDurationTimestamp: number;
|
|
61
|
+
freezeDurationTimestamp: number;
|
|
62
|
+
unFreezeDurationTimestamp: number;
|
|
63
|
+
penalty: number;
|
|
64
|
+
problems: Problems;
|
|
65
|
+
problemsMap: Map<string, Problem>;
|
|
66
|
+
statusTimeDisplay: StatusTimeDisplay;
|
|
67
|
+
badge?: string;
|
|
68
|
+
medal?: Record<string, Record<string, number>> | MedalPreset;
|
|
69
|
+
awards?: Awards;
|
|
70
|
+
organization?: string;
|
|
71
|
+
group: Map<string, Group>;
|
|
72
|
+
tag: Map<string, string>;
|
|
73
|
+
logo?: Image;
|
|
74
|
+
banner?: Image;
|
|
75
|
+
bannerMode?: BannerMode;
|
|
76
|
+
boardLink?: string;
|
|
77
|
+
options: ContestOptions;
|
|
78
|
+
constructor();
|
|
79
|
+
getStartTime(): dayjs.Dayjs;
|
|
80
|
+
getEndTime(): dayjs.Dayjs;
|
|
81
|
+
getFreezeTime(): dayjs.Dayjs;
|
|
82
|
+
getContestDuration(timeFormat?: string): string;
|
|
83
|
+
getContestState(nowTime?: Date): ContestState;
|
|
84
|
+
getContestPendingTime(nowTime?: Date): string;
|
|
85
|
+
getContestElapsedTime(nowTime?: Date): string;
|
|
86
|
+
getContestRemainingTime(nowTime?: Date): string;
|
|
87
|
+
getContestProgressRatio(nowTime?: Date): number;
|
|
88
|
+
isEnableAwards(group: string): boolean;
|
|
89
|
+
resetReplayTime(): void;
|
|
90
|
+
setReplayTime(replayStartTimestamp: number): void;
|
|
91
|
+
}
|
|
92
|
+
declare function createContest(contestJSON: Contest$1): Contest;
|
|
93
|
+
|
|
22
94
|
declare class Submission {
|
|
23
95
|
id: string;
|
|
24
96
|
teamId: string;
|
|
@@ -44,8 +116,8 @@ declare class Submission {
|
|
|
44
116
|
static compare(lhs: Submission, rhs: Submission): number;
|
|
45
117
|
}
|
|
46
118
|
type Submissions = Array<Submission>;
|
|
47
|
-
declare function createSubmission(submissionJSON: Submission$1): Submission;
|
|
48
|
-
declare function createSubmissions(submissionsJSON: Submissions$1): Submissions;
|
|
119
|
+
declare function createSubmission(submissionJSON: Submission$1, contest?: Contest): Submission;
|
|
120
|
+
declare function createSubmissions(submissionsJSON: Submissions$1, contest?: Contest): Submissions;
|
|
49
121
|
|
|
50
122
|
declare class ProblemStatistics {
|
|
51
123
|
acceptedNum: number;
|
|
@@ -102,15 +174,6 @@ declare class TeamProblemStatistics {
|
|
|
102
174
|
get penaltyInSecond(): number;
|
|
103
175
|
}
|
|
104
176
|
|
|
105
|
-
declare class ContestOptions {
|
|
106
|
-
calculationOfPenalty: CalculationOfPenalty;
|
|
107
|
-
submissionTimestampUnit: TimeUnit;
|
|
108
|
-
submissionHasTimeField: boolean;
|
|
109
|
-
submissionHasLanguageField: boolean;
|
|
110
|
-
submissionEnableActionField: boolean;
|
|
111
|
-
constructor();
|
|
112
|
-
}
|
|
113
|
-
|
|
114
177
|
declare class PlaceChartPointData {
|
|
115
178
|
timePoint: number;
|
|
116
179
|
rank: number;
|
|
@@ -215,67 +278,6 @@ declare class BattleOfGiants {
|
|
|
215
278
|
FromBase64(base64: string): void;
|
|
216
279
|
}
|
|
217
280
|
|
|
218
|
-
declare class Group {
|
|
219
|
-
names: Map<Lang, string>;
|
|
220
|
-
defaultLang: Lang;
|
|
221
|
-
isDefault: boolean;
|
|
222
|
-
constructor();
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
declare function calcDirt(attemptedNum: number, solvedNum: number): number;
|
|
226
|
-
|
|
227
|
-
declare function getWhiteOrBlackColorV1(background: string): "#000" | "#fff";
|
|
228
|
-
declare function getWhiteOrBlackColor(background: string): "#000" | "#fff";
|
|
229
|
-
|
|
230
|
-
declare function createDayJS(time?: Date | string | number | undefined): dayjs.Dayjs;
|
|
231
|
-
declare function getTimestamp(time: number | dayjs.Dayjs): number;
|
|
232
|
-
declare function getTimeDiff(seconds: number): string;
|
|
233
|
-
|
|
234
|
-
declare class Contest {
|
|
235
|
-
id: string;
|
|
236
|
-
name: string;
|
|
237
|
-
startTime: dayjs.Dayjs;
|
|
238
|
-
endTime: dayjs.Dayjs;
|
|
239
|
-
freezeTime: dayjs.Dayjs;
|
|
240
|
-
replayStartTime?: dayjs.Dayjs;
|
|
241
|
-
replayEndTime?: dayjs.Dayjs;
|
|
242
|
-
replayFreezeTime?: dayjs.Dayjs;
|
|
243
|
-
replayNowTime?: dayjs.Dayjs;
|
|
244
|
-
replayContestStartTimestamp?: number;
|
|
245
|
-
totalDurationTimestamp: number;
|
|
246
|
-
freezeDurationTimestamp: number;
|
|
247
|
-
unFreezeDurationTimestamp: number;
|
|
248
|
-
penalty: number;
|
|
249
|
-
problems: Problems;
|
|
250
|
-
problemsMap: Map<string, Problem>;
|
|
251
|
-
statusTimeDisplay: StatusTimeDisplay;
|
|
252
|
-
badge?: string;
|
|
253
|
-
medal?: Record<string, Record<string, number>> | MedalPreset;
|
|
254
|
-
awards?: Awards;
|
|
255
|
-
organization?: string;
|
|
256
|
-
group: Map<string, Group>;
|
|
257
|
-
tag: Map<string, string>;
|
|
258
|
-
logo?: Image;
|
|
259
|
-
banner?: Image;
|
|
260
|
-
bannerMode?: BannerMode;
|
|
261
|
-
boardLink?: string;
|
|
262
|
-
options: ContestOptions;
|
|
263
|
-
constructor();
|
|
264
|
-
getStartTime(): dayjs.Dayjs;
|
|
265
|
-
getEndTime(): dayjs.Dayjs;
|
|
266
|
-
getFreezeTime(): dayjs.Dayjs;
|
|
267
|
-
getContestDuration(timeFormat?: string): string;
|
|
268
|
-
getContestState(nowTime?: Date): ContestState;
|
|
269
|
-
getContestPendingTime(nowTime?: Date): string;
|
|
270
|
-
getContestElapsedTime(nowTime?: Date): string;
|
|
271
|
-
getContestRemainingTime(nowTime?: Date): string;
|
|
272
|
-
getContestProgressRatio(nowTime?: Date): number;
|
|
273
|
-
isEnableAwards(group: string): boolean;
|
|
274
|
-
resetReplayTime(): void;
|
|
275
|
-
setReplayTime(replayStartTimestamp: number): void;
|
|
276
|
-
}
|
|
277
|
-
declare function createContest(contestJSON: Contest$1): Contest;
|
|
278
|
-
|
|
279
281
|
declare class ContestIndexConfig {
|
|
280
282
|
contestName: string;
|
|
281
283
|
startTime: dayjs.Dayjs;
|
|
@@ -516,4 +518,5 @@ declare function isRejected(status: SubmissionStatus): boolean;
|
|
|
516
518
|
declare function isPending(status: SubmissionStatus): boolean;
|
|
517
519
|
declare function isNotCalculatedPenaltyStatus(status: SubmissionStatus): boolean;
|
|
518
520
|
|
|
519
|
-
export { Award,
|
|
521
|
+
export { Award, Balloon, BattleOfGiants, CodeforcesGymGhostDATConverter, Contest, ContestIndex, ContestIndexConfig, ContestOptions, GeneralExcelConverter, Giants, GiantsType, ICPCStandingsCsvConverter, MedalType, Person, PlaceChartPointData, Problem, ProblemStatistics, Rank, RankOptions, RankStatistics, Rating, RatingCalculator, RatingHistory, RatingLevel, RatingLevelToString, RatingUser, RatingUtility, Resolver, ResolverVue, Submission, Team, TeamProblemStatistics, calcDirt, createContest, createContestIndex, createContestIndexList, createDayJS, createPersons, createProblem, createProblems, createProblemsByProblemIds, createSubmission, createSubmissions, createTeam, createTeams, getImageSource, getTimeDiff, getTimestamp, getWhiteOrBlackColor, getWhiteOrBlackColorV1, isAccepted, isNotCalculatedPenaltyStatus, isPending, isRejected, isValidMedalType, stringToSubmissionStatus };
|
|
522
|
+
export type { Awards, Balloons, ContestIndexList, Persons, Problems, Ranks, RatingHistories, RatingUserMap, RatingUsers, SelectOptionItem, Submissions, Teams };
|
package/dist/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { TimeUnit, SubmissionReaction, SubmissionStatus, Submission as Submission$1, Submissions as Submissions$1, BalloonColor, Problem as Problem$1, Problems as Problems$1,
|
|
1
|
+
import { CalculationOfPenalty, TimeUnit, Lang, StatusTimeDisplay, MedalPreset, Image, BannerMode, ContestState, Contest as Contest$1, SubmissionReaction, SubmissionStatus, Submission as Submission$1, Submissions as Submissions$1, BalloonColor, Problem as Problem$1, Problems as Problems$1, Team as Team$1, Teams as Teams$1, ContestIndex as ContestIndex$1, IPerson, IRatingHistory, IRatingUser, IRating } from '@xcpcio/types';
|
|
2
2
|
import dayjs from 'dayjs';
|
|
3
3
|
export { default as dayjs } from 'dayjs';
|
|
4
4
|
import * as XLSX from 'xlsx-js-style';
|
|
@@ -19,6 +19,78 @@ declare class Award {
|
|
|
19
19
|
declare function isValidMedalType(medal: MedalType): boolean;
|
|
20
20
|
type Awards = Map<string, Award[]>;
|
|
21
21
|
|
|
22
|
+
declare class ContestOptions {
|
|
23
|
+
calculationOfPenalty: CalculationOfPenalty;
|
|
24
|
+
submissionTimestampUnit: TimeUnit;
|
|
25
|
+
submissionHasTimeField: boolean;
|
|
26
|
+
submissionHasLanguageField: boolean;
|
|
27
|
+
submissionEnableActionField: boolean;
|
|
28
|
+
submissionHasReactionField: boolean;
|
|
29
|
+
reactionVideoUrlTemplate?: string;
|
|
30
|
+
constructor();
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
declare class Group {
|
|
34
|
+
names: Map<Lang, string>;
|
|
35
|
+
defaultLang: Lang;
|
|
36
|
+
isDefault: boolean;
|
|
37
|
+
constructor();
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
declare function calcDirt(attemptedNum: number, solvedNum: number): number;
|
|
41
|
+
|
|
42
|
+
declare function getWhiteOrBlackColorV1(background: string): "#000" | "#fff";
|
|
43
|
+
declare function getWhiteOrBlackColor(background: string): "#000" | "#fff";
|
|
44
|
+
|
|
45
|
+
declare function createDayJS(time?: Date | string | number | undefined): dayjs.Dayjs;
|
|
46
|
+
declare function getTimestamp(time: number | dayjs.Dayjs): number;
|
|
47
|
+
declare function getTimeDiff(seconds: number): string;
|
|
48
|
+
|
|
49
|
+
declare class Contest {
|
|
50
|
+
id: string;
|
|
51
|
+
name: string;
|
|
52
|
+
startTime: dayjs.Dayjs;
|
|
53
|
+
endTime: dayjs.Dayjs;
|
|
54
|
+
freezeTime: dayjs.Dayjs;
|
|
55
|
+
replayStartTime?: dayjs.Dayjs;
|
|
56
|
+
replayEndTime?: dayjs.Dayjs;
|
|
57
|
+
replayFreezeTime?: dayjs.Dayjs;
|
|
58
|
+
replayNowTime?: dayjs.Dayjs;
|
|
59
|
+
replayContestStartTimestamp?: number;
|
|
60
|
+
totalDurationTimestamp: number;
|
|
61
|
+
freezeDurationTimestamp: number;
|
|
62
|
+
unFreezeDurationTimestamp: number;
|
|
63
|
+
penalty: number;
|
|
64
|
+
problems: Problems;
|
|
65
|
+
problemsMap: Map<string, Problem>;
|
|
66
|
+
statusTimeDisplay: StatusTimeDisplay;
|
|
67
|
+
badge?: string;
|
|
68
|
+
medal?: Record<string, Record<string, number>> | MedalPreset;
|
|
69
|
+
awards?: Awards;
|
|
70
|
+
organization?: string;
|
|
71
|
+
group: Map<string, Group>;
|
|
72
|
+
tag: Map<string, string>;
|
|
73
|
+
logo?: Image;
|
|
74
|
+
banner?: Image;
|
|
75
|
+
bannerMode?: BannerMode;
|
|
76
|
+
boardLink?: string;
|
|
77
|
+
options: ContestOptions;
|
|
78
|
+
constructor();
|
|
79
|
+
getStartTime(): dayjs.Dayjs;
|
|
80
|
+
getEndTime(): dayjs.Dayjs;
|
|
81
|
+
getFreezeTime(): dayjs.Dayjs;
|
|
82
|
+
getContestDuration(timeFormat?: string): string;
|
|
83
|
+
getContestState(nowTime?: Date): ContestState;
|
|
84
|
+
getContestPendingTime(nowTime?: Date): string;
|
|
85
|
+
getContestElapsedTime(nowTime?: Date): string;
|
|
86
|
+
getContestRemainingTime(nowTime?: Date): string;
|
|
87
|
+
getContestProgressRatio(nowTime?: Date): number;
|
|
88
|
+
isEnableAwards(group: string): boolean;
|
|
89
|
+
resetReplayTime(): void;
|
|
90
|
+
setReplayTime(replayStartTimestamp: number): void;
|
|
91
|
+
}
|
|
92
|
+
declare function createContest(contestJSON: Contest$1): Contest;
|
|
93
|
+
|
|
22
94
|
declare class Submission {
|
|
23
95
|
id: string;
|
|
24
96
|
teamId: string;
|
|
@@ -44,8 +116,8 @@ declare class Submission {
|
|
|
44
116
|
static compare(lhs: Submission, rhs: Submission): number;
|
|
45
117
|
}
|
|
46
118
|
type Submissions = Array<Submission>;
|
|
47
|
-
declare function createSubmission(submissionJSON: Submission$1): Submission;
|
|
48
|
-
declare function createSubmissions(submissionsJSON: Submissions$1): Submissions;
|
|
119
|
+
declare function createSubmission(submissionJSON: Submission$1, contest?: Contest): Submission;
|
|
120
|
+
declare function createSubmissions(submissionsJSON: Submissions$1, contest?: Contest): Submissions;
|
|
49
121
|
|
|
50
122
|
declare class ProblemStatistics {
|
|
51
123
|
acceptedNum: number;
|
|
@@ -102,15 +174,6 @@ declare class TeamProblemStatistics {
|
|
|
102
174
|
get penaltyInSecond(): number;
|
|
103
175
|
}
|
|
104
176
|
|
|
105
|
-
declare class ContestOptions {
|
|
106
|
-
calculationOfPenalty: CalculationOfPenalty;
|
|
107
|
-
submissionTimestampUnit: TimeUnit;
|
|
108
|
-
submissionHasTimeField: boolean;
|
|
109
|
-
submissionHasLanguageField: boolean;
|
|
110
|
-
submissionEnableActionField: boolean;
|
|
111
|
-
constructor();
|
|
112
|
-
}
|
|
113
|
-
|
|
114
177
|
declare class PlaceChartPointData {
|
|
115
178
|
timePoint: number;
|
|
116
179
|
rank: number;
|
|
@@ -215,67 +278,6 @@ declare class BattleOfGiants {
|
|
|
215
278
|
FromBase64(base64: string): void;
|
|
216
279
|
}
|
|
217
280
|
|
|
218
|
-
declare class Group {
|
|
219
|
-
names: Map<Lang, string>;
|
|
220
|
-
defaultLang: Lang;
|
|
221
|
-
isDefault: boolean;
|
|
222
|
-
constructor();
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
declare function calcDirt(attemptedNum: number, solvedNum: number): number;
|
|
226
|
-
|
|
227
|
-
declare function getWhiteOrBlackColorV1(background: string): "#000" | "#fff";
|
|
228
|
-
declare function getWhiteOrBlackColor(background: string): "#000" | "#fff";
|
|
229
|
-
|
|
230
|
-
declare function createDayJS(time?: Date | string | number | undefined): dayjs.Dayjs;
|
|
231
|
-
declare function getTimestamp(time: number | dayjs.Dayjs): number;
|
|
232
|
-
declare function getTimeDiff(seconds: number): string;
|
|
233
|
-
|
|
234
|
-
declare class Contest {
|
|
235
|
-
id: string;
|
|
236
|
-
name: string;
|
|
237
|
-
startTime: dayjs.Dayjs;
|
|
238
|
-
endTime: dayjs.Dayjs;
|
|
239
|
-
freezeTime: dayjs.Dayjs;
|
|
240
|
-
replayStartTime?: dayjs.Dayjs;
|
|
241
|
-
replayEndTime?: dayjs.Dayjs;
|
|
242
|
-
replayFreezeTime?: dayjs.Dayjs;
|
|
243
|
-
replayNowTime?: dayjs.Dayjs;
|
|
244
|
-
replayContestStartTimestamp?: number;
|
|
245
|
-
totalDurationTimestamp: number;
|
|
246
|
-
freezeDurationTimestamp: number;
|
|
247
|
-
unFreezeDurationTimestamp: number;
|
|
248
|
-
penalty: number;
|
|
249
|
-
problems: Problems;
|
|
250
|
-
problemsMap: Map<string, Problem>;
|
|
251
|
-
statusTimeDisplay: StatusTimeDisplay;
|
|
252
|
-
badge?: string;
|
|
253
|
-
medal?: Record<string, Record<string, number>> | MedalPreset;
|
|
254
|
-
awards?: Awards;
|
|
255
|
-
organization?: string;
|
|
256
|
-
group: Map<string, Group>;
|
|
257
|
-
tag: Map<string, string>;
|
|
258
|
-
logo?: Image;
|
|
259
|
-
banner?: Image;
|
|
260
|
-
bannerMode?: BannerMode;
|
|
261
|
-
boardLink?: string;
|
|
262
|
-
options: ContestOptions;
|
|
263
|
-
constructor();
|
|
264
|
-
getStartTime(): dayjs.Dayjs;
|
|
265
|
-
getEndTime(): dayjs.Dayjs;
|
|
266
|
-
getFreezeTime(): dayjs.Dayjs;
|
|
267
|
-
getContestDuration(timeFormat?: string): string;
|
|
268
|
-
getContestState(nowTime?: Date): ContestState;
|
|
269
|
-
getContestPendingTime(nowTime?: Date): string;
|
|
270
|
-
getContestElapsedTime(nowTime?: Date): string;
|
|
271
|
-
getContestRemainingTime(nowTime?: Date): string;
|
|
272
|
-
getContestProgressRatio(nowTime?: Date): number;
|
|
273
|
-
isEnableAwards(group: string): boolean;
|
|
274
|
-
resetReplayTime(): void;
|
|
275
|
-
setReplayTime(replayStartTimestamp: number): void;
|
|
276
|
-
}
|
|
277
|
-
declare function createContest(contestJSON: Contest$1): Contest;
|
|
278
|
-
|
|
279
281
|
declare class ContestIndexConfig {
|
|
280
282
|
contestName: string;
|
|
281
283
|
startTime: dayjs.Dayjs;
|
|
@@ -516,4 +518,5 @@ declare function isRejected(status: SubmissionStatus): boolean;
|
|
|
516
518
|
declare function isPending(status: SubmissionStatus): boolean;
|
|
517
519
|
declare function isNotCalculatedPenaltyStatus(status: SubmissionStatus): boolean;
|
|
518
520
|
|
|
519
|
-
export { Award,
|
|
521
|
+
export { Award, Balloon, BattleOfGiants, CodeforcesGymGhostDATConverter, Contest, ContestIndex, ContestIndexConfig, ContestOptions, GeneralExcelConverter, Giants, GiantsType, ICPCStandingsCsvConverter, MedalType, Person, PlaceChartPointData, Problem, ProblemStatistics, Rank, RankOptions, RankStatistics, Rating, RatingCalculator, RatingHistory, RatingLevel, RatingLevelToString, RatingUser, RatingUtility, Resolver, ResolverVue, Submission, Team, TeamProblemStatistics, calcDirt, createContest, createContestIndex, createContestIndexList, createDayJS, createPersons, createProblem, createProblems, createProblemsByProblemIds, createSubmission, createSubmissions, createTeam, createTeams, getImageSource, getTimeDiff, getTimestamp, getWhiteOrBlackColor, getWhiteOrBlackColorV1, isAccepted, isNotCalculatedPenaltyStatus, isPending, isRejected, isValidMedalType, stringToSubmissionStatus };
|
|
522
|
+
export type { Awards, Balloons, ContestIndexList, Persons, Problems, Ranks, RatingHistories, RatingUserMap, RatingUsers, SelectOptionItem, Submissions, Teams };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { TimeUnit, SubmissionReaction, SubmissionStatus, Submission as Submission$1, Submissions as Submissions$1, BalloonColor, Problem as Problem$1, Problems as Problems$1,
|
|
1
|
+
import { CalculationOfPenalty, TimeUnit, Lang, StatusTimeDisplay, MedalPreset, Image, BannerMode, ContestState, Contest as Contest$1, SubmissionReaction, SubmissionStatus, Submission as Submission$1, Submissions as Submissions$1, BalloonColor, Problem as Problem$1, Problems as Problems$1, Team as Team$1, Teams as Teams$1, ContestIndex as ContestIndex$1, IPerson, IRatingHistory, IRatingUser, IRating } from '@xcpcio/types';
|
|
2
2
|
import dayjs from 'dayjs';
|
|
3
3
|
export { default as dayjs } from 'dayjs';
|
|
4
4
|
import * as XLSX from 'xlsx-js-style';
|
|
@@ -19,6 +19,78 @@ declare class Award {
|
|
|
19
19
|
declare function isValidMedalType(medal: MedalType): boolean;
|
|
20
20
|
type Awards = Map<string, Award[]>;
|
|
21
21
|
|
|
22
|
+
declare class ContestOptions {
|
|
23
|
+
calculationOfPenalty: CalculationOfPenalty;
|
|
24
|
+
submissionTimestampUnit: TimeUnit;
|
|
25
|
+
submissionHasTimeField: boolean;
|
|
26
|
+
submissionHasLanguageField: boolean;
|
|
27
|
+
submissionEnableActionField: boolean;
|
|
28
|
+
submissionHasReactionField: boolean;
|
|
29
|
+
reactionVideoUrlTemplate?: string;
|
|
30
|
+
constructor();
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
declare class Group {
|
|
34
|
+
names: Map<Lang, string>;
|
|
35
|
+
defaultLang: Lang;
|
|
36
|
+
isDefault: boolean;
|
|
37
|
+
constructor();
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
declare function calcDirt(attemptedNum: number, solvedNum: number): number;
|
|
41
|
+
|
|
42
|
+
declare function getWhiteOrBlackColorV1(background: string): "#000" | "#fff";
|
|
43
|
+
declare function getWhiteOrBlackColor(background: string): "#000" | "#fff";
|
|
44
|
+
|
|
45
|
+
declare function createDayJS(time?: Date | string | number | undefined): dayjs.Dayjs;
|
|
46
|
+
declare function getTimestamp(time: number | dayjs.Dayjs): number;
|
|
47
|
+
declare function getTimeDiff(seconds: number): string;
|
|
48
|
+
|
|
49
|
+
declare class Contest {
|
|
50
|
+
id: string;
|
|
51
|
+
name: string;
|
|
52
|
+
startTime: dayjs.Dayjs;
|
|
53
|
+
endTime: dayjs.Dayjs;
|
|
54
|
+
freezeTime: dayjs.Dayjs;
|
|
55
|
+
replayStartTime?: dayjs.Dayjs;
|
|
56
|
+
replayEndTime?: dayjs.Dayjs;
|
|
57
|
+
replayFreezeTime?: dayjs.Dayjs;
|
|
58
|
+
replayNowTime?: dayjs.Dayjs;
|
|
59
|
+
replayContestStartTimestamp?: number;
|
|
60
|
+
totalDurationTimestamp: number;
|
|
61
|
+
freezeDurationTimestamp: number;
|
|
62
|
+
unFreezeDurationTimestamp: number;
|
|
63
|
+
penalty: number;
|
|
64
|
+
problems: Problems;
|
|
65
|
+
problemsMap: Map<string, Problem>;
|
|
66
|
+
statusTimeDisplay: StatusTimeDisplay;
|
|
67
|
+
badge?: string;
|
|
68
|
+
medal?: Record<string, Record<string, number>> | MedalPreset;
|
|
69
|
+
awards?: Awards;
|
|
70
|
+
organization?: string;
|
|
71
|
+
group: Map<string, Group>;
|
|
72
|
+
tag: Map<string, string>;
|
|
73
|
+
logo?: Image;
|
|
74
|
+
banner?: Image;
|
|
75
|
+
bannerMode?: BannerMode;
|
|
76
|
+
boardLink?: string;
|
|
77
|
+
options: ContestOptions;
|
|
78
|
+
constructor();
|
|
79
|
+
getStartTime(): dayjs.Dayjs;
|
|
80
|
+
getEndTime(): dayjs.Dayjs;
|
|
81
|
+
getFreezeTime(): dayjs.Dayjs;
|
|
82
|
+
getContestDuration(timeFormat?: string): string;
|
|
83
|
+
getContestState(nowTime?: Date): ContestState;
|
|
84
|
+
getContestPendingTime(nowTime?: Date): string;
|
|
85
|
+
getContestElapsedTime(nowTime?: Date): string;
|
|
86
|
+
getContestRemainingTime(nowTime?: Date): string;
|
|
87
|
+
getContestProgressRatio(nowTime?: Date): number;
|
|
88
|
+
isEnableAwards(group: string): boolean;
|
|
89
|
+
resetReplayTime(): void;
|
|
90
|
+
setReplayTime(replayStartTimestamp: number): void;
|
|
91
|
+
}
|
|
92
|
+
declare function createContest(contestJSON: Contest$1): Contest;
|
|
93
|
+
|
|
22
94
|
declare class Submission {
|
|
23
95
|
id: string;
|
|
24
96
|
teamId: string;
|
|
@@ -44,8 +116,8 @@ declare class Submission {
|
|
|
44
116
|
static compare(lhs: Submission, rhs: Submission): number;
|
|
45
117
|
}
|
|
46
118
|
type Submissions = Array<Submission>;
|
|
47
|
-
declare function createSubmission(submissionJSON: Submission$1): Submission;
|
|
48
|
-
declare function createSubmissions(submissionsJSON: Submissions$1): Submissions;
|
|
119
|
+
declare function createSubmission(submissionJSON: Submission$1, contest?: Contest): Submission;
|
|
120
|
+
declare function createSubmissions(submissionsJSON: Submissions$1, contest?: Contest): Submissions;
|
|
49
121
|
|
|
50
122
|
declare class ProblemStatistics {
|
|
51
123
|
acceptedNum: number;
|
|
@@ -102,15 +174,6 @@ declare class TeamProblemStatistics {
|
|
|
102
174
|
get penaltyInSecond(): number;
|
|
103
175
|
}
|
|
104
176
|
|
|
105
|
-
declare class ContestOptions {
|
|
106
|
-
calculationOfPenalty: CalculationOfPenalty;
|
|
107
|
-
submissionTimestampUnit: TimeUnit;
|
|
108
|
-
submissionHasTimeField: boolean;
|
|
109
|
-
submissionHasLanguageField: boolean;
|
|
110
|
-
submissionEnableActionField: boolean;
|
|
111
|
-
constructor();
|
|
112
|
-
}
|
|
113
|
-
|
|
114
177
|
declare class PlaceChartPointData {
|
|
115
178
|
timePoint: number;
|
|
116
179
|
rank: number;
|
|
@@ -215,67 +278,6 @@ declare class BattleOfGiants {
|
|
|
215
278
|
FromBase64(base64: string): void;
|
|
216
279
|
}
|
|
217
280
|
|
|
218
|
-
declare class Group {
|
|
219
|
-
names: Map<Lang, string>;
|
|
220
|
-
defaultLang: Lang;
|
|
221
|
-
isDefault: boolean;
|
|
222
|
-
constructor();
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
declare function calcDirt(attemptedNum: number, solvedNum: number): number;
|
|
226
|
-
|
|
227
|
-
declare function getWhiteOrBlackColorV1(background: string): "#000" | "#fff";
|
|
228
|
-
declare function getWhiteOrBlackColor(background: string): "#000" | "#fff";
|
|
229
|
-
|
|
230
|
-
declare function createDayJS(time?: Date | string | number | undefined): dayjs.Dayjs;
|
|
231
|
-
declare function getTimestamp(time: number | dayjs.Dayjs): number;
|
|
232
|
-
declare function getTimeDiff(seconds: number): string;
|
|
233
|
-
|
|
234
|
-
declare class Contest {
|
|
235
|
-
id: string;
|
|
236
|
-
name: string;
|
|
237
|
-
startTime: dayjs.Dayjs;
|
|
238
|
-
endTime: dayjs.Dayjs;
|
|
239
|
-
freezeTime: dayjs.Dayjs;
|
|
240
|
-
replayStartTime?: dayjs.Dayjs;
|
|
241
|
-
replayEndTime?: dayjs.Dayjs;
|
|
242
|
-
replayFreezeTime?: dayjs.Dayjs;
|
|
243
|
-
replayNowTime?: dayjs.Dayjs;
|
|
244
|
-
replayContestStartTimestamp?: number;
|
|
245
|
-
totalDurationTimestamp: number;
|
|
246
|
-
freezeDurationTimestamp: number;
|
|
247
|
-
unFreezeDurationTimestamp: number;
|
|
248
|
-
penalty: number;
|
|
249
|
-
problems: Problems;
|
|
250
|
-
problemsMap: Map<string, Problem>;
|
|
251
|
-
statusTimeDisplay: StatusTimeDisplay;
|
|
252
|
-
badge?: string;
|
|
253
|
-
medal?: Record<string, Record<string, number>> | MedalPreset;
|
|
254
|
-
awards?: Awards;
|
|
255
|
-
organization?: string;
|
|
256
|
-
group: Map<string, Group>;
|
|
257
|
-
tag: Map<string, string>;
|
|
258
|
-
logo?: Image;
|
|
259
|
-
banner?: Image;
|
|
260
|
-
bannerMode?: BannerMode;
|
|
261
|
-
boardLink?: string;
|
|
262
|
-
options: ContestOptions;
|
|
263
|
-
constructor();
|
|
264
|
-
getStartTime(): dayjs.Dayjs;
|
|
265
|
-
getEndTime(): dayjs.Dayjs;
|
|
266
|
-
getFreezeTime(): dayjs.Dayjs;
|
|
267
|
-
getContestDuration(timeFormat?: string): string;
|
|
268
|
-
getContestState(nowTime?: Date): ContestState;
|
|
269
|
-
getContestPendingTime(nowTime?: Date): string;
|
|
270
|
-
getContestElapsedTime(nowTime?: Date): string;
|
|
271
|
-
getContestRemainingTime(nowTime?: Date): string;
|
|
272
|
-
getContestProgressRatio(nowTime?: Date): number;
|
|
273
|
-
isEnableAwards(group: string): boolean;
|
|
274
|
-
resetReplayTime(): void;
|
|
275
|
-
setReplayTime(replayStartTimestamp: number): void;
|
|
276
|
-
}
|
|
277
|
-
declare function createContest(contestJSON: Contest$1): Contest;
|
|
278
|
-
|
|
279
281
|
declare class ContestIndexConfig {
|
|
280
282
|
contestName: string;
|
|
281
283
|
startTime: dayjs.Dayjs;
|
|
@@ -516,4 +518,5 @@ declare function isRejected(status: SubmissionStatus): boolean;
|
|
|
516
518
|
declare function isPending(status: SubmissionStatus): boolean;
|
|
517
519
|
declare function isNotCalculatedPenaltyStatus(status: SubmissionStatus): boolean;
|
|
518
520
|
|
|
519
|
-
export { Award,
|
|
521
|
+
export { Award, Balloon, BattleOfGiants, CodeforcesGymGhostDATConverter, Contest, ContestIndex, ContestIndexConfig, ContestOptions, GeneralExcelConverter, Giants, GiantsType, ICPCStandingsCsvConverter, MedalType, Person, PlaceChartPointData, Problem, ProblemStatistics, Rank, RankOptions, RankStatistics, Rating, RatingCalculator, RatingHistory, RatingLevel, RatingLevelToString, RatingUser, RatingUtility, Resolver, ResolverVue, Submission, Team, TeamProblemStatistics, calcDirt, createContest, createContestIndex, createContestIndexList, createDayJS, createPersons, createProblem, createProblems, createProblemsByProblemIds, createSubmission, createSubmissions, createTeam, createTeams, getImageSource, getTimeDiff, getTimestamp, getWhiteOrBlackColor, getWhiteOrBlackColorV1, isAccepted, isNotCalculatedPenaltyStatus, isPending, isRejected, isValidMedalType, stringToSubmissionStatus };
|
|
522
|
+
export type { Awards, Balloons, ContestIndexList, Persons, Problems, Ranks, RatingHistories, RatingUserMap, RatingUsers, SelectOptionItem, Submissions, Teams };
|
package/dist/index.mjs
CHANGED
|
@@ -481,7 +481,7 @@ class Submission {
|
|
|
481
481
|
}
|
|
482
482
|
}
|
|
483
483
|
}
|
|
484
|
-
function createSubmission(submissionJSON) {
|
|
484
|
+
function createSubmission(submissionJSON, contest) {
|
|
485
485
|
const s = new Submission();
|
|
486
486
|
s.id = String(submissionJSON.id ?? submissionJSON.submission_id ?? "");
|
|
487
487
|
s.teamId = String(submissionJSON.team_id);
|
|
@@ -497,15 +497,19 @@ function createSubmission(submissionJSON) {
|
|
|
497
497
|
}
|
|
498
498
|
if (submissionJSON.reaction) {
|
|
499
499
|
s.reaction = submissionJSON.reaction;
|
|
500
|
+
} else if (contest?.options.reactionVideoUrlTemplate) {
|
|
501
|
+
s.reaction = {
|
|
502
|
+
url: contest.options.reactionVideoUrlTemplate.replace(/\$\{submission_id\}/, s.id)
|
|
503
|
+
};
|
|
500
504
|
}
|
|
501
505
|
return s;
|
|
502
506
|
}
|
|
503
|
-
function createSubmissions(submissionsJSON) {
|
|
507
|
+
function createSubmissions(submissionsJSON, contest) {
|
|
504
508
|
if (Array.isArray(submissionsJSON)) {
|
|
505
|
-
return submissionsJSON.map((s, index) => createSubmission({ ...s, id: s.submission_id ?? String(index) }));
|
|
509
|
+
return submissionsJSON.map((s, index) => createSubmission({ ...s, id: s.submission_id ?? String(index) }, contest));
|
|
506
510
|
} else {
|
|
507
511
|
const submissions = Object.entries(submissionsJSON).map(
|
|
508
|
-
([submissionId, s]) => createSubmission({ ...s, id: s.submission_id ?? submissionId })
|
|
512
|
+
([submissionId, s]) => createSubmission({ ...s, id: s.submission_id ?? submissionId }, contest)
|
|
509
513
|
);
|
|
510
514
|
return submissions;
|
|
511
515
|
}
|
|
@@ -897,12 +901,16 @@ class ContestOptions {
|
|
|
897
901
|
submissionHasTimeField;
|
|
898
902
|
submissionHasLanguageField;
|
|
899
903
|
submissionEnableActionField;
|
|
904
|
+
submissionHasReactionField;
|
|
905
|
+
reactionVideoUrlTemplate;
|
|
900
906
|
constructor() {
|
|
901
907
|
this.calculationOfPenalty = "in_minutes";
|
|
902
908
|
this.submissionTimestampUnit = "second";
|
|
903
909
|
this.submissionHasTimeField = false;
|
|
904
910
|
this.submissionHasLanguageField = false;
|
|
905
911
|
this.submissionEnableActionField = false;
|
|
912
|
+
this.submissionHasReactionField = false;
|
|
913
|
+
this.reactionVideoUrlTemplate = void 0;
|
|
906
914
|
}
|
|
907
915
|
}
|
|
908
916
|
function createContestOptions(contestOptionsJSON = {}) {
|
|
@@ -914,9 +922,11 @@ function createContestOptions(contestOptionsJSON = {}) {
|
|
|
914
922
|
if (j.submission_timestamp_unit) {
|
|
915
923
|
o.submissionTimestampUnit = j.submission_timestamp_unit;
|
|
916
924
|
}
|
|
917
|
-
if (j.submission_has_reaction) {
|
|
918
|
-
o.
|
|
925
|
+
if (j.submission_has_reaction || j.has_reaction_videos) {
|
|
926
|
+
o.submissionHasReactionField = true;
|
|
919
927
|
}
|
|
928
|
+
o.submissionEnableActionField = o.submissionHasReactionField;
|
|
929
|
+
o.reactionVideoUrlTemplate = j.reaction_video_url_template;
|
|
920
930
|
return o;
|
|
921
931
|
}
|
|
922
932
|
|
|
@@ -1374,13 +1384,13 @@ class GeneralExcelConverter {
|
|
|
1374
1384
|
}
|
|
1375
1385
|
convertToSheet(rank) {
|
|
1376
1386
|
const aoa = this.convertToAoa(rank);
|
|
1377
|
-
const sheet = XLSX.utils.aoa_to_sheet(aoa);
|
|
1387
|
+
const sheet = XLSX.utils.aoa_to_sheet(aoa.aoa);
|
|
1378
1388
|
const cols = [];
|
|
1379
|
-
const head = aoa[1];
|
|
1389
|
+
const head = aoa.aoa[1];
|
|
1380
1390
|
for (let j = 0; j < head.length; j++) {
|
|
1381
1391
|
let wch = 10;
|
|
1382
|
-
for (let i = 1; i < aoa.length; i++) {
|
|
1383
|
-
wch = Math.max(wch, stringWidth(aoa[i][j]) + 2);
|
|
1392
|
+
for (let i = 1; i < aoa.aoa.length; i++) {
|
|
1393
|
+
wch = Math.max(wch, stringWidth(aoa.aoa[i][j]) + 2);
|
|
1384
1394
|
}
|
|
1385
1395
|
cols.push({
|
|
1386
1396
|
wch
|
|
@@ -1414,11 +1424,22 @@ class GeneralExcelConverter {
|
|
|
1414
1424
|
},
|
|
1415
1425
|
font
|
|
1416
1426
|
};
|
|
1417
|
-
|
|
1418
|
-
|
|
1427
|
+
const firstSolvedCellStyle = {
|
|
1428
|
+
...cellStyle,
|
|
1429
|
+
fill: {
|
|
1430
|
+
fgColor: { rgb: "009900" }
|
|
1431
|
+
}
|
|
1432
|
+
};
|
|
1433
|
+
for (let i = 1; i < aoa.aoa.length; i++) {
|
|
1434
|
+
for (let j = 0; j < aoa.aoa[i].length; j++) {
|
|
1419
1435
|
const cellAddress = XLSX.utils.encode_cell({ r: i, c: j });
|
|
1420
1436
|
const cell = sheet[cellAddress];
|
|
1421
|
-
|
|
1437
|
+
const specialCell = aoa.specialCells.find((sc) => sc.row === i && sc.col === j);
|
|
1438
|
+
if (specialCell?.type === "firstSolved" /* FIRST_SOLVED */) {
|
|
1439
|
+
cell.s = firstSolvedCellStyle;
|
|
1440
|
+
} else {
|
|
1441
|
+
cell.s = cellStyle;
|
|
1442
|
+
}
|
|
1422
1443
|
}
|
|
1423
1444
|
}
|
|
1424
1445
|
{
|
|
@@ -1433,6 +1454,7 @@ class GeneralExcelConverter {
|
|
|
1433
1454
|
}
|
|
1434
1455
|
convertToAoa(rank) {
|
|
1435
1456
|
const aoa = [];
|
|
1457
|
+
const specialCells = [];
|
|
1436
1458
|
const enableAwards = rank.contest.isEnableAwards(rank.options.group);
|
|
1437
1459
|
const enableMembers = (Array.isArray(rank.teams) && rank.teams[0]?.members) ?? false;
|
|
1438
1460
|
const enableCoach = rank.teams[0]?.coach ?? false;
|
|
@@ -1478,6 +1500,13 @@ class GeneralExcelConverter {
|
|
|
1478
1500
|
}
|
|
1479
1501
|
if (p.isSolved) {
|
|
1480
1502
|
arr.push(`+${p.totalCount}(${p.solvedTimestampToMinute})`);
|
|
1503
|
+
if (p.isFirstSolved) {
|
|
1504
|
+
specialCells.push({
|
|
1505
|
+
row: aoa.length,
|
|
1506
|
+
col: arr.length - 1,
|
|
1507
|
+
type: "firstSolved" /* FIRST_SOLVED */
|
|
1508
|
+
});
|
|
1509
|
+
}
|
|
1481
1510
|
}
|
|
1482
1511
|
if (p.isWrongAnswer) {
|
|
1483
1512
|
arr.push(`-${p.failedCount}`);
|
|
@@ -1512,7 +1541,7 @@ class GeneralExcelConverter {
|
|
|
1512
1541
|
arr.push(team.isGirl ? "Y" : "N");
|
|
1513
1542
|
aoa.push(arr);
|
|
1514
1543
|
}
|
|
1515
|
-
return aoa;
|
|
1544
|
+
return { aoa, specialCells };
|
|
1516
1545
|
}
|
|
1517
1546
|
}
|
|
1518
1547
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xcpcio/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.57.0",
|
|
4
4
|
"description": "XCPCIO Core",
|
|
5
5
|
"author": "Dup4 <lyuzhi.pan@gmail.com>",
|
|
6
6
|
"license": "MIT",
|
|
@@ -42,34 +42,34 @@
|
|
|
42
42
|
"dependencies": {
|
|
43
43
|
"chroma-js": "^3.1.2",
|
|
44
44
|
"color-diff": "^1.4.0",
|
|
45
|
-
"dayjs": "^1.11.
|
|
46
|
-
"js-base64": "^3.7.
|
|
45
|
+
"dayjs": "^1.11.18",
|
|
46
|
+
"js-base64": "^3.7.8",
|
|
47
47
|
"lodash": "^4.17.21",
|
|
48
48
|
"ordinal": "^1.0.3",
|
|
49
|
-
"papaparse": "^5.5.
|
|
50
|
-
"string-width": "^
|
|
49
|
+
"papaparse": "^5.5.3",
|
|
50
|
+
"string-width": "^8.1.0",
|
|
51
51
|
"xlsx-js-style": "^1.2.0",
|
|
52
|
-
"@xcpcio/types": "0.
|
|
52
|
+
"@xcpcio/types": "0.57.0"
|
|
53
53
|
},
|
|
54
54
|
"devDependencies": {
|
|
55
|
-
"@babel/types": "^7.
|
|
55
|
+
"@babel/types": "^7.28.4",
|
|
56
56
|
"@types/chroma-js": "^3.1.1",
|
|
57
57
|
"@types/color-diff": "^1.2.5",
|
|
58
|
-
"@types/lodash": "^4.17.
|
|
59
|
-
"@types/node": "^
|
|
60
|
-
"@types/papaparse": "^5.3.
|
|
61
|
-
"@typescript-eslint/eslint-plugin": "^8.
|
|
62
|
-
"@typescript-eslint/parser": "^8.
|
|
63
|
-
"bumpp": "^10.
|
|
64
|
-
"eslint": "^9.
|
|
58
|
+
"@types/lodash": "^4.17.20",
|
|
59
|
+
"@types/node": "^20.19.13",
|
|
60
|
+
"@types/papaparse": "^5.3.16",
|
|
61
|
+
"@typescript-eslint/eslint-plugin": "^8.42.0",
|
|
62
|
+
"@typescript-eslint/parser": "^8.42.0",
|
|
63
|
+
"bumpp": "^10.2.3",
|
|
64
|
+
"eslint": "^9.35.0",
|
|
65
65
|
"esmo": "^4.8.0",
|
|
66
66
|
"npm-run-all": "^4.1.5",
|
|
67
|
-
"pnpm": "^10.
|
|
68
|
-
"taze": "^19.0
|
|
69
|
-
"typescript": "^5.
|
|
70
|
-
"unbuild": "^3.
|
|
71
|
-
"vite": "^
|
|
72
|
-
"vitest": "^3.
|
|
67
|
+
"pnpm": "^10.15.1",
|
|
68
|
+
"taze": "^19.5.0",
|
|
69
|
+
"typescript": "^5.9.2",
|
|
70
|
+
"unbuild": "^3.6.1",
|
|
71
|
+
"vite": "^7.1.4",
|
|
72
|
+
"vitest": "^3.2.4"
|
|
73
73
|
},
|
|
74
74
|
"scripts": {
|
|
75
75
|
"build": "unbuild",
|
package/src/contest-options.ts
CHANGED
|
@@ -6,7 +6,11 @@ export class ContestOptions {
|
|
|
6
6
|
|
|
7
7
|
submissionHasTimeField: boolean;
|
|
8
8
|
submissionHasLanguageField: boolean;
|
|
9
|
+
|
|
9
10
|
submissionEnableActionField: boolean;
|
|
11
|
+
submissionHasReactionField: boolean;
|
|
12
|
+
|
|
13
|
+
reactionVideoUrlTemplate?: string;
|
|
10
14
|
|
|
11
15
|
constructor() {
|
|
12
16
|
this.calculationOfPenalty = "in_minutes";
|
|
@@ -14,7 +18,11 @@ export class ContestOptions {
|
|
|
14
18
|
|
|
15
19
|
this.submissionHasTimeField = false;
|
|
16
20
|
this.submissionHasLanguageField = false;
|
|
21
|
+
|
|
17
22
|
this.submissionEnableActionField = false;
|
|
23
|
+
this.submissionHasReactionField = false;
|
|
24
|
+
|
|
25
|
+
this.reactionVideoUrlTemplate = undefined;
|
|
18
26
|
}
|
|
19
27
|
}
|
|
20
28
|
|
|
@@ -30,9 +38,12 @@ export function createContestOptions(contestOptionsJSON: IContestOptions = {}):
|
|
|
30
38
|
o.submissionTimestampUnit = j.submission_timestamp_unit;
|
|
31
39
|
}
|
|
32
40
|
|
|
33
|
-
if (j.submission_has_reaction) {
|
|
34
|
-
o.
|
|
41
|
+
if (j.submission_has_reaction || j.has_reaction_videos) {
|
|
42
|
+
o.submissionHasReactionField = true;
|
|
35
43
|
}
|
|
36
44
|
|
|
45
|
+
o.submissionEnableActionField = o.submissionHasReactionField;
|
|
46
|
+
o.reactionVideoUrlTemplate = j.reaction_video_url_template;
|
|
47
|
+
|
|
37
48
|
return o;
|
|
38
49
|
}
|
|
@@ -6,8 +6,23 @@ import * as XLSX from "xlsx-js-style";
|
|
|
6
6
|
|
|
7
7
|
import { isValidMedalType } from "../award";
|
|
8
8
|
|
|
9
|
+
enum SpecialCellType {
|
|
10
|
+
FIRST_SOLVED = "firstSolved",
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
interface SpecialCell {
|
|
14
|
+
row: number;
|
|
15
|
+
col: number;
|
|
16
|
+
type: SpecialCellType;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
interface AoaConvertResult {
|
|
20
|
+
aoa: string[][];
|
|
21
|
+
specialCells: SpecialCell[];
|
|
22
|
+
}
|
|
23
|
+
|
|
9
24
|
export class GeneralExcelConverter {
|
|
10
|
-
constructor() {}
|
|
25
|
+
constructor() { }
|
|
11
26
|
|
|
12
27
|
public convert(oriRank: Rank): XLSX.WorkBook {
|
|
13
28
|
const rank = _.cloneDeep(oriRank);
|
|
@@ -40,14 +55,14 @@ export class GeneralExcelConverter {
|
|
|
40
55
|
|
|
41
56
|
private convertToSheet(rank: Rank): XLSX.WorkSheet {
|
|
42
57
|
const aoa = this.convertToAoa(rank);
|
|
43
|
-
const sheet = XLSX.utils.aoa_to_sheet(aoa);
|
|
58
|
+
const sheet = XLSX.utils.aoa_to_sheet(aoa.aoa);
|
|
44
59
|
|
|
45
60
|
const cols = [];
|
|
46
|
-
const head = aoa[1];
|
|
61
|
+
const head = aoa.aoa[1];
|
|
47
62
|
for (let j = 0; j < head.length; j++) {
|
|
48
63
|
let wch = 10;
|
|
49
|
-
for (let i = 1; i < aoa.length; i++) {
|
|
50
|
-
wch = Math.max(wch, stringWidth(aoa[i][j]) + 2);
|
|
64
|
+
for (let i = 1; i < aoa.aoa.length; i++) {
|
|
65
|
+
wch = Math.max(wch, stringWidth(aoa.aoa[i][j]) + 2);
|
|
51
66
|
}
|
|
52
67
|
|
|
53
68
|
cols.push({
|
|
@@ -88,11 +103,23 @@ export class GeneralExcelConverter {
|
|
|
88
103
|
font,
|
|
89
104
|
};
|
|
90
105
|
|
|
91
|
-
|
|
92
|
-
|
|
106
|
+
const firstSolvedCellStyle = {
|
|
107
|
+
...cellStyle,
|
|
108
|
+
fill: {
|
|
109
|
+
fgColor: { rgb: "009900" },
|
|
110
|
+
},
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
for (let i = 1; i < aoa.aoa.length; i++) {
|
|
114
|
+
for (let j = 0; j < aoa.aoa[i].length; j++) {
|
|
93
115
|
const cellAddress = XLSX.utils.encode_cell({ r: i, c: j });
|
|
94
116
|
const cell = sheet[cellAddress];
|
|
95
|
-
|
|
117
|
+
const specialCell = aoa.specialCells.find(sc => sc.row === i && sc.col === j);
|
|
118
|
+
if (specialCell?.type === SpecialCellType.FIRST_SOLVED) {
|
|
119
|
+
cell.s = firstSolvedCellStyle;
|
|
120
|
+
} else {
|
|
121
|
+
cell.s = cellStyle;
|
|
122
|
+
}
|
|
96
123
|
}
|
|
97
124
|
}
|
|
98
125
|
|
|
@@ -108,8 +135,9 @@ export class GeneralExcelConverter {
|
|
|
108
135
|
return sheet;
|
|
109
136
|
}
|
|
110
137
|
|
|
111
|
-
private convertToAoa(rank: Rank):
|
|
138
|
+
private convertToAoa(rank: Rank): AoaConvertResult {
|
|
112
139
|
const aoa: string[][] = [];
|
|
140
|
+
const specialCells: SpecialCell[] = [];
|
|
113
141
|
|
|
114
142
|
const enableAwards = rank.contest.isEnableAwards(rank.options.group);
|
|
115
143
|
const enableMembers = (Array.isArray(rank.teams) && rank.teams[0]?.members) ?? false;
|
|
@@ -152,6 +180,7 @@ export class GeneralExcelConverter {
|
|
|
152
180
|
const arr: string[] = [];
|
|
153
181
|
|
|
154
182
|
arr.push(team.rank.toString());
|
|
183
|
+
|
|
155
184
|
if (team.organization) {
|
|
156
185
|
if (team.organizationRank !== -1) {
|
|
157
186
|
arr.push(team.organizationRank.toString());
|
|
@@ -171,6 +200,13 @@ export class GeneralExcelConverter {
|
|
|
171
200
|
|
|
172
201
|
if (p.isSolved) {
|
|
173
202
|
arr.push(`+${p.totalCount}(${p.solvedTimestampToMinute})`);
|
|
203
|
+
if (p.isFirstSolved) {
|
|
204
|
+
specialCells.push({
|
|
205
|
+
row: aoa.length,
|
|
206
|
+
col: arr.length - 1,
|
|
207
|
+
type: SpecialCellType.FIRST_SOLVED,
|
|
208
|
+
});
|
|
209
|
+
}
|
|
174
210
|
}
|
|
175
211
|
|
|
176
212
|
if (p.isWrongAnswer) {
|
|
@@ -216,6 +252,6 @@ export class GeneralExcelConverter {
|
|
|
216
252
|
aoa.push(arr);
|
|
217
253
|
}
|
|
218
254
|
|
|
219
|
-
return aoa;
|
|
255
|
+
return { aoa, specialCells };
|
|
220
256
|
}
|
|
221
257
|
}
|
package/src/submission.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import type { Submission as ISubmission, Submissions as ISubmissions, SubmissionReaction, TimeUnit } from "@xcpcio/types";
|
|
2
|
+
import type { Contest } from "./contest";
|
|
3
|
+
|
|
2
4
|
import { SubmissionStatus } from "@xcpcio/types";
|
|
3
5
|
|
|
4
6
|
import {
|
|
@@ -134,7 +136,7 @@ export class Submission {
|
|
|
134
136
|
|
|
135
137
|
export type Submissions = Array<Submission>;
|
|
136
138
|
|
|
137
|
-
export function createSubmission(submissionJSON: ISubmission): Submission {
|
|
139
|
+
export function createSubmission(submissionJSON: ISubmission, contest?: Contest): Submission {
|
|
138
140
|
const s = new Submission();
|
|
139
141
|
|
|
140
142
|
s.id = String(submissionJSON.id ?? submissionJSON.submission_id ?? "");
|
|
@@ -154,19 +156,22 @@ export function createSubmission(submissionJSON: ISubmission): Submission {
|
|
|
154
156
|
|
|
155
157
|
if (submissionJSON.reaction) {
|
|
156
158
|
s.reaction = submissionJSON.reaction;
|
|
159
|
+
} else if (contest?.options.reactionVideoUrlTemplate) {
|
|
160
|
+
s.reaction = {
|
|
161
|
+
url: contest.options.reactionVideoUrlTemplate.replace(/\$\{submission_id\}/, s.id),
|
|
162
|
+
};
|
|
157
163
|
}
|
|
158
164
|
|
|
159
165
|
return s;
|
|
160
166
|
}
|
|
161
167
|
|
|
162
|
-
export function createSubmissions(submissionsJSON: ISubmissions): Submissions {
|
|
168
|
+
export function createSubmissions(submissionsJSON: ISubmissions, contest?: Contest): Submissions {
|
|
163
169
|
if (Array.isArray(submissionsJSON)) {
|
|
164
|
-
return submissionsJSON.map((s, index) => createSubmission({ ...s, id: s.submission_id ?? String(index) }));
|
|
170
|
+
return submissionsJSON.map((s, index) => createSubmission({ ...s, id: s.submission_id ?? String(index) }, contest));
|
|
165
171
|
} else {
|
|
166
172
|
const submissions = Object.entries(submissionsJSON).map(([submissionId, s]) =>
|
|
167
|
-
createSubmission({ ...s, id: s.submission_id ?? submissionId }),
|
|
173
|
+
createSubmission({ ...s, id: s.submission_id ?? submissionId }, contest),
|
|
168
174
|
);
|
|
169
|
-
|
|
170
175
|
return submissions;
|
|
171
176
|
}
|
|
172
177
|
}
|