@xcpcio/core 0.56.0 → 0.57.1

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
@@ -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.submissionEnableActionField = j.submission_has_reaction;
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
 
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, CalculationOfPenalty, Image, Team as Team$1, Teams as Teams$1, Lang, StatusTimeDisplay, MedalPreset, BannerMode, ContestState, Contest as Contest$1, ContestIndex as ContestIndex$1, IPerson, IRatingHistory, IRatingUser, IRating } from '@xcpcio/types';
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, type Awards, Balloon, type Balloons, BattleOfGiants, CodeforcesGymGhostDATConverter, Contest, ContestIndex, ContestIndexConfig, type ContestIndexList, ContestOptions, GeneralExcelConverter, Giants, GiantsType, ICPCStandingsCsvConverter, MedalType, Person, type Persons, PlaceChartPointData, Problem, ProblemStatistics, type Problems, Rank, RankOptions, RankStatistics, type Ranks, Rating, RatingCalculator, type RatingHistories, RatingHistory, RatingLevel, RatingLevelToString, RatingUser, type RatingUserMap, type RatingUsers, RatingUtility, Resolver, ResolverVue, type SelectOptionItem, Submission, type Submissions, Team, TeamProblemStatistics, type Teams, calcDirt, createContest, createContestIndex, createContestIndexList, createDayJS, createPersons, createProblem, createProblems, createProblemsByProblemIds, createSubmission, createSubmissions, createTeam, createTeams, getImageSource, getTimeDiff, getTimestamp, getWhiteOrBlackColor, getWhiteOrBlackColorV1, isAccepted, isNotCalculatedPenaltyStatus, isPending, isRejected, isValidMedalType, stringToSubmissionStatus };
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, CalculationOfPenalty, Image, Team as Team$1, Teams as Teams$1, Lang, StatusTimeDisplay, MedalPreset, BannerMode, ContestState, Contest as Contest$1, ContestIndex as ContestIndex$1, IPerson, IRatingHistory, IRatingUser, IRating } from '@xcpcio/types';
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, type Awards, Balloon, type Balloons, BattleOfGiants, CodeforcesGymGhostDATConverter, Contest, ContestIndex, ContestIndexConfig, type ContestIndexList, ContestOptions, GeneralExcelConverter, Giants, GiantsType, ICPCStandingsCsvConverter, MedalType, Person, type Persons, PlaceChartPointData, Problem, ProblemStatistics, type Problems, Rank, RankOptions, RankStatistics, type Ranks, Rating, RatingCalculator, type RatingHistories, RatingHistory, RatingLevel, RatingLevelToString, RatingUser, type RatingUserMap, type RatingUsers, RatingUtility, Resolver, ResolverVue, type SelectOptionItem, Submission, type Submissions, Team, TeamProblemStatistics, type Teams, calcDirt, createContest, createContestIndex, createContestIndexList, createDayJS, createPersons, createProblem, createProblems, createProblemsByProblemIds, createSubmission, createSubmissions, createTeam, createTeams, getImageSource, getTimeDiff, getTimestamp, getWhiteOrBlackColor, getWhiteOrBlackColorV1, isAccepted, isNotCalculatedPenaltyStatus, isPending, isRejected, isValidMedalType, stringToSubmissionStatus };
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, CalculationOfPenalty, Image, Team as Team$1, Teams as Teams$1, Lang, StatusTimeDisplay, MedalPreset, BannerMode, ContestState, Contest as Contest$1, ContestIndex as ContestIndex$1, IPerson, IRatingHistory, IRatingUser, IRating } from '@xcpcio/types';
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, type Awards, Balloon, type Balloons, BattleOfGiants, CodeforcesGymGhostDATConverter, Contest, ContestIndex, ContestIndexConfig, type ContestIndexList, ContestOptions, GeneralExcelConverter, Giants, GiantsType, ICPCStandingsCsvConverter, MedalType, Person, type Persons, PlaceChartPointData, Problem, ProblemStatistics, type Problems, Rank, RankOptions, RankStatistics, type Ranks, Rating, RatingCalculator, type RatingHistories, RatingHistory, RatingLevel, RatingLevelToString, RatingUser, type RatingUserMap, type RatingUsers, RatingUtility, Resolver, ResolverVue, type SelectOptionItem, Submission, type Submissions, Team, TeamProblemStatistics, type Teams, calcDirt, createContest, createContestIndex, createContestIndexList, createDayJS, createPersons, createProblem, createProblems, createProblemsByProblemIds, createSubmission, createSubmissions, createTeam, createTeams, getImageSource, getTimeDiff, getTimestamp, getWhiteOrBlackColor, getWhiteOrBlackColorV1, isAccepted, isNotCalculatedPenaltyStatus, isPending, isRejected, isValidMedalType, stringToSubmissionStatus };
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.submissionEnableActionField = j.submission_has_reaction;
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
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xcpcio/core",
3
- "version": "0.56.0",
3
+ "version": "0.57.1",
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.13",
46
- "js-base64": "^3.7.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.2",
50
- "string-width": "^7.2.0",
49
+ "papaparse": "^5.5.3",
50
+ "string-width": "^8.1.0",
51
51
  "xlsx-js-style": "^1.2.0",
52
- "@xcpcio/types": "0.56.0"
52
+ "@xcpcio/types": "0.57.1"
53
53
  },
54
54
  "devDependencies": {
55
- "@babel/types": "^7.27.0",
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.16",
59
- "@types/node": "^18.19.86",
60
- "@types/papaparse": "^5.3.15",
61
- "@typescript-eslint/eslint-plugin": "^8.29.1",
62
- "@typescript-eslint/parser": "^8.29.1",
63
- "bumpp": "^10.1.0",
64
- "eslint": "^9.24.0",
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.8.0",
68
- "taze": "^19.0.4",
69
- "typescript": "^5.8.3",
70
- "unbuild": "^3.5.0",
71
- "vite": "^6.2.6",
72
- "vitest": "^3.1.1"
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",
@@ -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.submissionEnableActionField = j.submission_has_reaction;
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
  }
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
  }