@xcpcio/core 0.24.3 → 0.26.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -569,6 +569,12 @@ class TeamProblemStatistics {
569
569
  get penaltyToMinute() {
570
570
  return Math.floor(this.penalty / 60);
571
571
  }
572
+ get penaltyInSecond() {
573
+ if (this.isSolved === false) {
574
+ return 0;
575
+ }
576
+ return this.solvedTimestamp + this.failedCount * this.contestPenalty;
577
+ }
572
578
  }
573
579
 
574
580
  class PlaceChartPointData {
@@ -628,7 +634,7 @@ class Team {
628
634
  }
629
635
  return this.members?.join(", ");
630
636
  }
631
- calcSolvedData() {
637
+ calcSolvedData(options) {
632
638
  this.solvedProblemNum = 0;
633
639
  this.attemptedProblemNum = 0;
634
640
  this.penalty = 0;
@@ -636,9 +642,16 @@ class Team {
636
642
  if (p.isAccepted) {
637
643
  this.solvedProblemNum++;
638
644
  this.attemptedProblemNum += p.failedCount + 1;
639
- this.penalty += p.penalty;
645
+ if (options?.calculationOfPenalty === "in_seconds" || options?.calculationOfPenalty === "accumulate_in_seconds_and_finally_to_the_minute") {
646
+ this.penalty += p.penaltyInSecond;
647
+ } else {
648
+ this.penalty += p.penalty;
649
+ }
640
650
  }
641
651
  }
652
+ if (options?.calculationOfPenalty === "accumulate_in_seconds_and_finally_to_the_minute") {
653
+ this.penalty = Math.floor(this.penalty / 60) * 60;
654
+ }
642
655
  }
643
656
  calcAwards(awards) {
644
657
  if (!awards) {
@@ -813,6 +826,20 @@ class Group {
813
826
  }
814
827
  }
815
828
 
829
+ class ContestOptions {
830
+ constructor() {
831
+ this.calculationOfPenalty = "in_minutes";
832
+ }
833
+ }
834
+ function createContestOptions(contestOptionsJSON = {}) {
835
+ const j = contestOptionsJSON;
836
+ const o = new ContestOptions();
837
+ if (j.calculation_of_penalty) {
838
+ o.calculationOfPenalty = j.calculation_of_penalty;
839
+ }
840
+ return o;
841
+ }
842
+
816
843
  class Contest {
817
844
  constructor() {
818
845
  this.name = "";
@@ -832,6 +859,7 @@ class Contest {
832
859
  };
833
860
  this.group = /* @__PURE__ */ new Map();
834
861
  this.tag = /* @__PURE__ */ new Map();
862
+ this.options = new ContestOptions();
835
863
  }
836
864
  getContestDuration(timeFormat = "HH:mm:ss") {
837
865
  return dayjs__default.duration(this.endTime.diff(this.startTime)).format(timeFormat);
@@ -998,6 +1026,9 @@ function createContest(contestJSON) {
998
1026
  c.banner = contestJSON.banner;
999
1027
  c.logo = contestJSON.logo;
1000
1028
  c.boardLink = contestJSON.board_link;
1029
+ if (contestJSON.options) {
1030
+ c.options = createContestOptions(contestJSON.options);
1031
+ }
1001
1032
  return c;
1002
1033
  }
1003
1034
 
@@ -1260,7 +1291,7 @@ class Rank {
1260
1291
  }
1261
1292
  })();
1262
1293
  if (s.timestampToMinute > preSubmissionTimestampToMinute || ix === allSubmissions.length - 1) {
1263
- this.teams.forEach((t) => t.calcSolvedData());
1294
+ this.teams.forEach((t) => t.calcSolvedData(this.contest.options));
1264
1295
  this.teams.sort(Team.compare);
1265
1296
  this.buildTeamRank();
1266
1297
  this.teams.forEach(
@@ -1275,7 +1306,7 @@ class Rank {
1275
1306
  }
1276
1307
  preSubmissionTimestampToMinute = s.timestampToMinute;
1277
1308
  }
1278
- this.teams.forEach((t) => t.calcSolvedData());
1309
+ this.teams.forEach((t) => t.calcSolvedData(this.contest.options));
1279
1310
  this.teams.sort(Team.compare);
1280
1311
  this.buildTeamRank();
1281
1312
  this.buildOrgRank();
@@ -1474,7 +1505,7 @@ class Resolver extends Rank {
1474
1505
  op.afterTeamProblemStatistics = afterTeamProblemStatistics;
1475
1506
  this.operations.push(op);
1476
1507
  team.problemStatistics[problemIx] = afterTeamProblemStatistics;
1477
- team.calcSolvedData();
1508
+ team.calcSolvedData(this.contest.options);
1478
1509
  break;
1479
1510
  }
1480
1511
  {
@@ -1499,6 +1530,7 @@ exports.CodeforcesGymGhostDATConverter = CodeforcesGymGhostDATConverter;
1499
1530
  exports.Contest = Contest;
1500
1531
  exports.ContestIndex = ContestIndex;
1501
1532
  exports.ContestIndexConfig = ContestIndexConfig;
1533
+ exports.ContestOptions = ContestOptions;
1502
1534
  exports.GeneralExcelConverter = GeneralExcelConverter;
1503
1535
  exports.MedalType = MedalType;
1504
1536
  exports.PlaceChartPointData = PlaceChartPointData;
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { SubmissionStatus, Submission as Submission$1, Submissions as Submissions$1, BalloonColor, Problem as Problem$1, Problems as Problems$1, Lang, StatusTimeDisplay, Image, ContestState, Contest as Contest$1, Team as Team$1, Teams as Teams$1, ContestIndex as ContestIndex$1 } from '@xcpcio/types';
1
+ import { SubmissionStatus, Submission as Submission$1, Submissions as Submissions$1, BalloonColor, Problem as Problem$1, Problems as Problems$1, Lang, CalculationOfPenalty, StatusTimeDisplay, Image, ContestState, Contest as Contest$1, Team as Team$1, Teams as Teams$1, ContestIndex as ContestIndex$1 } 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';
@@ -72,6 +72,7 @@ declare class TeamProblemStatistics {
72
72
  get solvedTimestampToMinute(): number;
73
73
  get penalty(): number;
74
74
  get penaltyToMinute(): number;
75
+ get penaltyInSecond(): number;
75
76
  }
76
77
 
77
78
  declare function calcDirt(attemptedNum: number, solvedNum: number): number;
@@ -103,6 +104,11 @@ declare class Award {
103
104
  declare function isValidMedalType(medal: MedalType): boolean;
104
105
  type Awards = Map<string, Award[]>;
105
106
 
107
+ declare class ContestOptions {
108
+ calculationOfPenalty: CalculationOfPenalty;
109
+ constructor();
110
+ }
111
+
106
112
  declare class Contest {
107
113
  name: string;
108
114
  startTime: dayjs.Dayjs;
@@ -124,6 +130,7 @@ declare class Contest {
124
130
  logo?: Image;
125
131
  banner?: Image;
126
132
  boardLink?: string;
133
+ options: ContestOptions;
127
134
  constructor();
128
135
  getContestDuration(timeFormat?: string): string;
129
136
  getContestState(nowTime?: Date): ContestState;
@@ -169,7 +176,7 @@ declare class Team {
169
176
  get penaltyToMinute(): number;
170
177
  get dirt(): number;
171
178
  get membersToString(): string | undefined;
172
- calcSolvedData(): void;
179
+ calcSolvedData(options: ContestOptions): void;
173
180
  calcAwards(awards?: Award[]): void;
174
181
  isEqualRank(otherTeam: Team): boolean;
175
182
  postProcessPlaceChartPoints(): void;
@@ -302,4 +309,4 @@ declare function isRejected(status: SubmissionStatus): boolean;
302
309
  declare function isPending(status: SubmissionStatus): boolean;
303
310
  declare function isNotCalculatedPenaltyStatus(status: SubmissionStatus): boolean;
304
311
 
305
- export { Award, Awards, Balloon, Balloons, CodeforcesGymGhostDATConverter, Contest, ContestIndex, ContestIndexConfig, ContestIndexList, 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, isAccepted, isNotCalculatedPenaltyStatus, isPending, isRejected, isValidMedalType, stringToSubmissionStatus };
312
+ 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, isAccepted, isNotCalculatedPenaltyStatus, isPending, isRejected, isValidMedalType, stringToSubmissionStatus };
package/dist/index.mjs CHANGED
@@ -539,6 +539,12 @@ class TeamProblemStatistics {
539
539
  get penaltyToMinute() {
540
540
  return Math.floor(this.penalty / 60);
541
541
  }
542
+ get penaltyInSecond() {
543
+ if (this.isSolved === false) {
544
+ return 0;
545
+ }
546
+ return this.solvedTimestamp + this.failedCount * this.contestPenalty;
547
+ }
542
548
  }
543
549
 
544
550
  class PlaceChartPointData {
@@ -598,7 +604,7 @@ class Team {
598
604
  }
599
605
  return this.members?.join(", ");
600
606
  }
601
- calcSolvedData() {
607
+ calcSolvedData(options) {
602
608
  this.solvedProblemNum = 0;
603
609
  this.attemptedProblemNum = 0;
604
610
  this.penalty = 0;
@@ -606,9 +612,16 @@ class Team {
606
612
  if (p.isAccepted) {
607
613
  this.solvedProblemNum++;
608
614
  this.attemptedProblemNum += p.failedCount + 1;
609
- this.penalty += p.penalty;
615
+ if (options?.calculationOfPenalty === "in_seconds" || options?.calculationOfPenalty === "accumulate_in_seconds_and_finally_to_the_minute") {
616
+ this.penalty += p.penaltyInSecond;
617
+ } else {
618
+ this.penalty += p.penalty;
619
+ }
610
620
  }
611
621
  }
622
+ if (options?.calculationOfPenalty === "accumulate_in_seconds_and_finally_to_the_minute") {
623
+ this.penalty = Math.floor(this.penalty / 60) * 60;
624
+ }
612
625
  }
613
626
  calcAwards(awards) {
614
627
  if (!awards) {
@@ -783,6 +796,20 @@ class Group {
783
796
  }
784
797
  }
785
798
 
799
+ class ContestOptions {
800
+ constructor() {
801
+ this.calculationOfPenalty = "in_minutes";
802
+ }
803
+ }
804
+ function createContestOptions(contestOptionsJSON = {}) {
805
+ const j = contestOptionsJSON;
806
+ const o = new ContestOptions();
807
+ if (j.calculation_of_penalty) {
808
+ o.calculationOfPenalty = j.calculation_of_penalty;
809
+ }
810
+ return o;
811
+ }
812
+
786
813
  class Contest {
787
814
  constructor() {
788
815
  this.name = "";
@@ -802,6 +829,7 @@ class Contest {
802
829
  };
803
830
  this.group = /* @__PURE__ */ new Map();
804
831
  this.tag = /* @__PURE__ */ new Map();
832
+ this.options = new ContestOptions();
805
833
  }
806
834
  getContestDuration(timeFormat = "HH:mm:ss") {
807
835
  return dayjs.duration(this.endTime.diff(this.startTime)).format(timeFormat);
@@ -968,6 +996,9 @@ function createContest(contestJSON) {
968
996
  c.banner = contestJSON.banner;
969
997
  c.logo = contestJSON.logo;
970
998
  c.boardLink = contestJSON.board_link;
999
+ if (contestJSON.options) {
1000
+ c.options = createContestOptions(contestJSON.options);
1001
+ }
971
1002
  return c;
972
1003
  }
973
1004
 
@@ -1230,7 +1261,7 @@ class Rank {
1230
1261
  }
1231
1262
  })();
1232
1263
  if (s.timestampToMinute > preSubmissionTimestampToMinute || ix === allSubmissions.length - 1) {
1233
- this.teams.forEach((t) => t.calcSolvedData());
1264
+ this.teams.forEach((t) => t.calcSolvedData(this.contest.options));
1234
1265
  this.teams.sort(Team.compare);
1235
1266
  this.buildTeamRank();
1236
1267
  this.teams.forEach(
@@ -1245,7 +1276,7 @@ class Rank {
1245
1276
  }
1246
1277
  preSubmissionTimestampToMinute = s.timestampToMinute;
1247
1278
  }
1248
- this.teams.forEach((t) => t.calcSolvedData());
1279
+ this.teams.forEach((t) => t.calcSolvedData(this.contest.options));
1249
1280
  this.teams.sort(Team.compare);
1250
1281
  this.buildTeamRank();
1251
1282
  this.buildOrgRank();
@@ -1444,7 +1475,7 @@ class Resolver extends Rank {
1444
1475
  op.afterTeamProblemStatistics = afterTeamProblemStatistics;
1445
1476
  this.operations.push(op);
1446
1477
  team.problemStatistics[problemIx] = afterTeamProblemStatistics;
1447
- team.calcSolvedData();
1478
+ team.calcSolvedData(this.contest.options);
1448
1479
  break;
1449
1480
  }
1450
1481
  {
@@ -1462,4 +1493,4 @@ class Resolver extends Rank {
1462
1493
  }
1463
1494
  }
1464
1495
 
1465
- export { Award, Balloon, CodeforcesGymGhostDATConverter, Contest, ContestIndex, ContestIndexConfig, 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, isAccepted, isNotCalculatedPenaltyStatus, isPending, isRejected, isValidMedalType, stringToSubmissionStatus };
1496
+ 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, isAccepted, isNotCalculatedPenaltyStatus, isPending, isRejected, isValidMedalType, stringToSubmissionStatus };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xcpcio/core",
3
- "version": "0.24.3",
3
+ "version": "0.26.0",
4
4
  "description": "XCPCIO Core",
5
5
  "author": "Dup4 <lyuzhi.pan@gmail.com>",
6
6
  "license": "MIT",
@@ -44,7 +44,7 @@
44
44
  "lodash": "^4.17.21",
45
45
  "string-width": "^6.1.0",
46
46
  "xlsx-js-style": "^1.2.0",
47
- "@xcpcio/types": "0.24.3"
47
+ "@xcpcio/types": "0.26.0"
48
48
  },
49
49
  "devDependencies": {
50
50
  "@babel/types": "^7.22.4",
@@ -0,0 +1,20 @@
1
+ import type { CalculationOfPenalty, ContestOptions as IContestOptions } from "@xcpcio/types";
2
+
3
+ export class ContestOptions {
4
+ calculationOfPenalty: CalculationOfPenalty;
5
+
6
+ constructor() {
7
+ this.calculationOfPenalty = "in_minutes";
8
+ }
9
+ }
10
+
11
+ export function createContestOptions(contestOptionsJSON: IContestOptions = {}): ContestOptions {
12
+ const j = contestOptionsJSON;
13
+ const o = new ContestOptions();
14
+
15
+ if (j.calculation_of_penalty) {
16
+ o.calculationOfPenalty = j.calculation_of_penalty;
17
+ }
18
+
19
+ return o;
20
+ }
package/src/contest.ts CHANGED
@@ -7,6 +7,7 @@ import { createDayJS, dayjs, getTimeDiff } from "./utils";
7
7
  import { Group } from "./group";
8
8
  import { Award } from "./award";
9
9
  import { type Awards, MedalType } from "./award";
10
+ import { ContestOptions, createContestOptions } from "./contest-options";
10
11
 
11
12
  export class Contest {
12
13
  name = "";
@@ -38,6 +39,8 @@ export class Contest {
38
39
  banner?: Image;
39
40
  boardLink?: string;
40
41
 
42
+ options: ContestOptions;
43
+
41
44
  constructor() {
42
45
  this.startTime = createDayJS();
43
46
  this.endTime = createDayJS();
@@ -61,6 +64,8 @@ export class Contest {
61
64
 
62
65
  this.group = new Map<string, Group>();
63
66
  this.tag = new Map<string, string>();
67
+
68
+ this.options = new ContestOptions();
64
69
  }
65
70
 
66
71
  getContestDuration(timeFormat = "HH:mm:ss"): string {
@@ -285,5 +290,10 @@ export function createContest(contestJSON: IContest): Contest {
285
290
  c.logo = contestJSON.logo;
286
291
  c.boardLink = contestJSON.board_link;
287
292
 
293
+ if (contestJSON.options) {
294
+ c.options = createContestOptions(contestJSON.options);
295
+ }
296
+
288
297
  return c;
289
298
  }
299
+ export { ContestOptions };
package/src/problem.ts CHANGED
@@ -197,4 +197,12 @@ export class TeamProblemStatistics {
197
197
  get penaltyToMinute() {
198
198
  return Math.floor(this.penalty / 60);
199
199
  }
200
+
201
+ get penaltyInSecond() {
202
+ if (this.isSolved === false) {
203
+ return 0;
204
+ }
205
+
206
+ return this.solvedTimestamp + this.failedCount * this.contestPenalty;
207
+ }
200
208
  }
package/src/rank.ts CHANGED
@@ -273,7 +273,7 @@ export class Rank {
273
273
  })();
274
274
 
275
275
  if (s.timestampToMinute > preSubmissionTimestampToMinute || ix === allSubmissions.length - 1) {
276
- this.teams.forEach(t => t.calcSolvedData());
276
+ this.teams.forEach(t => t.calcSolvedData(this.contest.options));
277
277
  this.teams.sort(Team.compare);
278
278
  this.buildTeamRank();
279
279
 
@@ -291,7 +291,7 @@ export class Rank {
291
291
  preSubmissionTimestampToMinute = s.timestampToMinute;
292
292
  }
293
293
 
294
- this.teams.forEach(t => t.calcSolvedData());
294
+ this.teams.forEach(t => t.calcSolvedData(this.contest.options));
295
295
  this.teams.sort(Team.compare);
296
296
  this.buildTeamRank();
297
297
  this.buildOrgRank();
package/src/resolver.ts CHANGED
@@ -100,7 +100,7 @@ export class Resolver extends Rank {
100
100
  this.operations.push(op);
101
101
 
102
102
  team.problemStatistics[problemIx] = afterTeamProblemStatistics;
103
- team.calcSolvedData();
103
+ team.calcSolvedData(this.contest.options);
104
104
 
105
105
  break;
106
106
  }
package/src/team.ts CHANGED
@@ -4,6 +4,7 @@ import type { Problem, TeamProblemStatistics } from "./problem";
4
4
  import { calcDirt } from "./utils";
5
5
  import type { Submissions } from "./submission";
6
6
  import type { Award, MedalType } from "./award";
7
+ import type { ContestOptions } from "./contest-options";
7
8
 
8
9
  export class PlaceChartPointData {
9
10
  timePoint: number;
@@ -126,7 +127,7 @@ export class Team {
126
127
  return this.members?.join(", ");
127
128
  }
128
129
 
129
- calcSolvedData() {
130
+ calcSolvedData(options: ContestOptions) {
130
131
  this.solvedProblemNum = 0;
131
132
  this.attemptedProblemNum = 0;
132
133
 
@@ -137,9 +138,18 @@ export class Team {
137
138
  this.solvedProblemNum++;
138
139
  this.attemptedProblemNum += p.failedCount + 1;
139
140
 
140
- this.penalty += p.penalty;
141
+ if (options?.calculationOfPenalty === "in_seconds"
142
+ || options?.calculationOfPenalty === "accumulate_in_seconds_and_finally_to_the_minute") {
143
+ this.penalty += p.penaltyInSecond;
144
+ } else {
145
+ this.penalty += p.penalty;
146
+ }
141
147
  }
142
148
  }
149
+
150
+ if (options?.calculationOfPenalty === "accumulate_in_seconds_and_finally_to_the_minute") {
151
+ this.penalty = Math.floor(this.penalty / 60) * 60;
152
+ }
143
153
  }
144
154
 
145
155
  calcAwards(awards?: Award[]) {