@xcpcio/core 0.33.1 → 0.34.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
@@ -657,6 +657,9 @@ class Team {
657
657
  }
658
658
  return this.members?.join(", ");
659
659
  }
660
+ get isEffectiveTeam() {
661
+ return this.solvedProblemNum > 0;
662
+ }
660
663
  calcSolvedData(options) {
661
664
  this.solvedProblemNum = 0;
662
665
  this.attemptedProblemNum = 0;
@@ -1053,32 +1056,34 @@ function createContest(contestJSON) {
1053
1056
  return;
1054
1057
  }
1055
1058
  c.awards = /* @__PURE__ */ new Map();
1056
- for (const k in contestJSON.medal) {
1057
- const v = contestJSON.medal[k];
1058
- {
1059
- const award = [];
1060
- let rank = 1;
1061
- const work = (key, medalType) => {
1062
- if (Object.keys(v).includes(key)) {
1059
+ if (typeof contestJSON.medal === "string") ; else {
1060
+ for (const k in contestJSON.medal) {
1061
+ const v = contestJSON.medal[k];
1062
+ {
1063
+ const award = [];
1064
+ let rank = 1;
1065
+ const work = (key, medalType) => {
1066
+ if (Object.keys(v).includes(key)) {
1067
+ const a = new Award();
1068
+ a.medalType = medalType;
1069
+ a.minRank = rank;
1070
+ rank += Number(v[key]);
1071
+ a.maxRank = rank - 1;
1072
+ award.push(a);
1073
+ }
1074
+ };
1075
+ work("gold", MedalType.GOLD);
1076
+ work("silver", MedalType.SILVER);
1077
+ work("bronze", MedalType.BRONZE);
1078
+ {
1063
1079
  const a = new Award();
1064
- a.medalType = medalType;
1080
+ a.medalType = MedalType.HONORABLE;
1065
1081
  a.minRank = rank;
1066
- rank += Number(v[key]);
1067
- a.maxRank = rank - 1;
1082
+ a.maxRank = 1061109567;
1068
1083
  award.push(a);
1069
1084
  }
1070
- };
1071
- work("gold", MedalType.GOLD);
1072
- work("silver", MedalType.SILVER);
1073
- work("bronze", MedalType.BRONZE);
1074
- {
1075
- const a = new Award();
1076
- a.medalType = MedalType.HONORABLE;
1077
- a.minRank = rank;
1078
- a.maxRank = 1061109567;
1079
- award.push(a);
1085
+ c.awards.set(k, award);
1080
1086
  }
1081
- c.awards.set(k, award);
1082
1087
  }
1083
1088
  }
1084
1089
  })();
@@ -1190,11 +1195,13 @@ class RankStatistics {
1190
1195
  this.teamSolvedNum = [];
1191
1196
  this.teamSolvedNumIndex = [];
1192
1197
  this.maxSolvedProblems = 0;
1198
+ this.effectiveTeamNum = 0;
1193
1199
  }
1194
1200
  reset() {
1195
1201
  this.teamSolvedNum = [];
1196
1202
  this.teamSolvedNumIndex = [];
1197
1203
  this.maxSolvedProblems = 0;
1204
+ this.effectiveTeamNum = 0;
1198
1205
  }
1199
1206
  getTeamSolvedNumIndex(solvedNum) {
1200
1207
  return this.teamSolvedNumIndex[solvedNum] ?? 0;
@@ -1420,6 +1427,8 @@ class Rank {
1420
1427
  this.teams.sort(Team.compare);
1421
1428
  this.buildTeamRank();
1422
1429
  this.buildOrgRank();
1430
+ this.rankStatistics.effectiveTeamNum = this.teams.filter((t) => t.isEffectiveTeam).length;
1431
+ this.buildAwards();
1423
1432
  this.teams.forEach((t) => t.calcAwards(this.contest.awards?.get(this.options.group)));
1424
1433
  this.teams.forEach((t) => t.postProcessPlaceChartPoints());
1425
1434
  })();
@@ -1496,6 +1505,41 @@ class Rank {
1496
1505
  res.sort();
1497
1506
  return res;
1498
1507
  }
1508
+ buildAwards() {
1509
+ if (this.contest.medal === "ccpc") {
1510
+ this.contest.awards = /* @__PURE__ */ new Map();
1511
+ const tot = this.rankStatistics.effectiveTeamNum;
1512
+ const award = [];
1513
+ const gold = new Award();
1514
+ const silver = new Award();
1515
+ const bronze = new Award();
1516
+ {
1517
+ gold.medalType = MedalType.GOLD;
1518
+ gold.minRank = 1;
1519
+ gold.maxRank = Math.ceil(tot * 0.1);
1520
+ if (gold.maxRank >= gold.minRank) {
1521
+ award.push(gold);
1522
+ }
1523
+ }
1524
+ {
1525
+ silver.medalType = MedalType.SILVER;
1526
+ silver.minRank = gold.maxRank + 1;
1527
+ silver.maxRank = Math.ceil(tot * 0.3);
1528
+ if (silver.maxRank >= silver.minRank) {
1529
+ award.push(silver);
1530
+ }
1531
+ }
1532
+ {
1533
+ bronze.medalType = MedalType.BRONZE;
1534
+ bronze.minRank = silver.maxRank + 1;
1535
+ bronze.maxRank = Math.ceil(tot * 0.6);
1536
+ if (bronze.maxRank >= bronze.minRank) {
1537
+ award.push(bronze);
1538
+ }
1539
+ }
1540
+ this.contest.awards.set("official", award);
1541
+ }
1542
+ }
1499
1543
  filterTeamByOrg(team) {
1500
1544
  const o = this.options;
1501
1545
  if (o.enableFilterTeamsByGroup) {
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { TimeUnit, 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';
1
+ import { TimeUnit, SubmissionStatus, Submission as Submission$1, Submissions as Submissions$1, BalloonColor, Problem as Problem$1, Problems as Problems$1, Lang, CalculationOfPenalty, StatusTimeDisplay, MedalPreset, 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';
@@ -133,7 +133,7 @@ declare class Contest {
133
133
  problemsMap: Map<string, Problem>;
134
134
  statusTimeDisplay: StatusTimeDisplay;
135
135
  badge?: string;
136
- medal?: Record<string, Record<string, number>>;
136
+ medal?: Record<string, Record<string, number>> | MedalPreset;
137
137
  awards?: Awards;
138
138
  organization?: string;
139
139
  group: Map<string, Group>;
@@ -187,6 +187,7 @@ declare class Team {
187
187
  get penaltyToMinute(): number;
188
188
  get dirt(): number;
189
189
  get membersToString(): string | undefined;
190
+ get isEffectiveTeam(): boolean;
190
191
  calcSolvedData(options: ContestOptions): void;
191
192
  calcAwards(awards?: Award[]): void;
192
193
  isEqualRank(otherTeam: Team): boolean;
@@ -201,6 +202,7 @@ declare class RankStatistics {
201
202
  teamSolvedNum: Array<number>;
202
203
  teamSolvedNumIndex: Array<number>;
203
204
  maxSolvedProblems: number;
205
+ effectiveTeamNum: number;
204
206
  constructor();
205
207
  reset(): void;
206
208
  getTeamSolvedNumIndex(solvedNum: number): number;
@@ -259,6 +261,7 @@ declare class Rank {
259
261
  buildTeamRank(): void;
260
262
  buildOrgRank(): void;
261
263
  buildOrganizations(): string[];
264
+ buildAwards(): void;
262
265
  filterTeamByOrg(team: Team): boolean;
263
266
  getSubmissions(): Submissions;
264
267
  buildBalloons(): void;
package/dist/index.mjs CHANGED
@@ -626,6 +626,9 @@ class Team {
626
626
  }
627
627
  return this.members?.join(", ");
628
628
  }
629
+ get isEffectiveTeam() {
630
+ return this.solvedProblemNum > 0;
631
+ }
629
632
  calcSolvedData(options) {
630
633
  this.solvedProblemNum = 0;
631
634
  this.attemptedProblemNum = 0;
@@ -1022,32 +1025,34 @@ function createContest(contestJSON) {
1022
1025
  return;
1023
1026
  }
1024
1027
  c.awards = /* @__PURE__ */ new Map();
1025
- for (const k in contestJSON.medal) {
1026
- const v = contestJSON.medal[k];
1027
- {
1028
- const award = [];
1029
- let rank = 1;
1030
- const work = (key, medalType) => {
1031
- if (Object.keys(v).includes(key)) {
1028
+ if (typeof contestJSON.medal === "string") ; else {
1029
+ for (const k in contestJSON.medal) {
1030
+ const v = contestJSON.medal[k];
1031
+ {
1032
+ const award = [];
1033
+ let rank = 1;
1034
+ const work = (key, medalType) => {
1035
+ if (Object.keys(v).includes(key)) {
1036
+ const a = new Award();
1037
+ a.medalType = medalType;
1038
+ a.minRank = rank;
1039
+ rank += Number(v[key]);
1040
+ a.maxRank = rank - 1;
1041
+ award.push(a);
1042
+ }
1043
+ };
1044
+ work("gold", MedalType.GOLD);
1045
+ work("silver", MedalType.SILVER);
1046
+ work("bronze", MedalType.BRONZE);
1047
+ {
1032
1048
  const a = new Award();
1033
- a.medalType = medalType;
1049
+ a.medalType = MedalType.HONORABLE;
1034
1050
  a.minRank = rank;
1035
- rank += Number(v[key]);
1036
- a.maxRank = rank - 1;
1051
+ a.maxRank = 1061109567;
1037
1052
  award.push(a);
1038
1053
  }
1039
- };
1040
- work("gold", MedalType.GOLD);
1041
- work("silver", MedalType.SILVER);
1042
- work("bronze", MedalType.BRONZE);
1043
- {
1044
- const a = new Award();
1045
- a.medalType = MedalType.HONORABLE;
1046
- a.minRank = rank;
1047
- a.maxRank = 1061109567;
1048
- award.push(a);
1054
+ c.awards.set(k, award);
1049
1055
  }
1050
- c.awards.set(k, award);
1051
1056
  }
1052
1057
  }
1053
1058
  })();
@@ -1159,11 +1164,13 @@ class RankStatistics {
1159
1164
  this.teamSolvedNum = [];
1160
1165
  this.teamSolvedNumIndex = [];
1161
1166
  this.maxSolvedProblems = 0;
1167
+ this.effectiveTeamNum = 0;
1162
1168
  }
1163
1169
  reset() {
1164
1170
  this.teamSolvedNum = [];
1165
1171
  this.teamSolvedNumIndex = [];
1166
1172
  this.maxSolvedProblems = 0;
1173
+ this.effectiveTeamNum = 0;
1167
1174
  }
1168
1175
  getTeamSolvedNumIndex(solvedNum) {
1169
1176
  return this.teamSolvedNumIndex[solvedNum] ?? 0;
@@ -1389,6 +1396,8 @@ class Rank {
1389
1396
  this.teams.sort(Team.compare);
1390
1397
  this.buildTeamRank();
1391
1398
  this.buildOrgRank();
1399
+ this.rankStatistics.effectiveTeamNum = this.teams.filter((t) => t.isEffectiveTeam).length;
1400
+ this.buildAwards();
1392
1401
  this.teams.forEach((t) => t.calcAwards(this.contest.awards?.get(this.options.group)));
1393
1402
  this.teams.forEach((t) => t.postProcessPlaceChartPoints());
1394
1403
  })();
@@ -1465,6 +1474,41 @@ class Rank {
1465
1474
  res.sort();
1466
1475
  return res;
1467
1476
  }
1477
+ buildAwards() {
1478
+ if (this.contest.medal === "ccpc") {
1479
+ this.contest.awards = /* @__PURE__ */ new Map();
1480
+ const tot = this.rankStatistics.effectiveTeamNum;
1481
+ const award = [];
1482
+ const gold = new Award();
1483
+ const silver = new Award();
1484
+ const bronze = new Award();
1485
+ {
1486
+ gold.medalType = MedalType.GOLD;
1487
+ gold.minRank = 1;
1488
+ gold.maxRank = Math.ceil(tot * 0.1);
1489
+ if (gold.maxRank >= gold.minRank) {
1490
+ award.push(gold);
1491
+ }
1492
+ }
1493
+ {
1494
+ silver.medalType = MedalType.SILVER;
1495
+ silver.minRank = gold.maxRank + 1;
1496
+ silver.maxRank = Math.ceil(tot * 0.3);
1497
+ if (silver.maxRank >= silver.minRank) {
1498
+ award.push(silver);
1499
+ }
1500
+ }
1501
+ {
1502
+ bronze.medalType = MedalType.BRONZE;
1503
+ bronze.minRank = silver.maxRank + 1;
1504
+ bronze.maxRank = Math.ceil(tot * 0.6);
1505
+ if (bronze.maxRank >= bronze.minRank) {
1506
+ award.push(bronze);
1507
+ }
1508
+ }
1509
+ this.contest.awards.set("official", award);
1510
+ }
1511
+ }
1468
1512
  filterTeamByOrg(team) {
1469
1513
  const o = this.options;
1470
1514
  if (o.enableFilterTeamsByGroup) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xcpcio/core",
3
- "version": "0.33.1",
3
+ "version": "0.34.1",
4
4
  "description": "XCPCIO Core",
5
5
  "author": "Dup4 <lyuzhi.pan@gmail.com>",
6
6
  "license": "MIT",
@@ -46,7 +46,7 @@
46
46
  "lodash": "^4.17.21",
47
47
  "string-width": "^6.1.0",
48
48
  "xlsx-js-style": "^1.2.0",
49
- "@xcpcio/types": "0.33.1"
49
+ "@xcpcio/types": "0.34.1"
50
50
  },
51
51
  "devDependencies": {
52
52
  "@babel/types": "^7.22.4",
package/src/contest.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { Contest as IContest, Image, StatusTimeDisplay } from "@xcpcio/types";
1
+ import type { Contest as IContest, Image, MedalPreset, StatusTimeDisplay } from "@xcpcio/types";
2
2
  import { ContestState } from "@xcpcio/types";
3
3
 
4
4
  import type { Problem, Problems } from "./problem";
@@ -28,7 +28,7 @@ export class Contest {
28
28
  statusTimeDisplay: StatusTimeDisplay;
29
29
 
30
30
  badge?: string;
31
- medal?: Record<string, Record<string, number>>;
31
+ medal?: Record<string, Record<string, number>> | MedalPreset;
32
32
  awards?: Awards;
33
33
  organization?: string;
34
34
 
@@ -217,37 +217,42 @@ export function createContest(contestJSON: IContest): Contest {
217
217
 
218
218
  c.awards = new Map<string, Award[]>();
219
219
 
220
- for (const k in contestJSON.medal) {
221
- const v = contestJSON.medal[k];
220
+ if (typeof contestJSON.medal === "string") {
221
+ // eslint-disable-next-line no-empty
222
+ {}
223
+ } else {
224
+ for (const k in contestJSON.medal) {
225
+ const v = contestJSON.medal[k];
222
226
 
223
- {
224
- const award: Award[] = [];
225
-
226
- let rank = 1;
227
- const work = (key: string, medalType: MedalType) => {
228
- if (Object.keys(v).includes(key)) {
227
+ {
228
+ const award: Award[] = [];
229
+
230
+ let rank = 1;
231
+ const work = (key: string, medalType: MedalType) => {
232
+ if (Object.keys(v).includes(key)) {
233
+ const a = new Award();
234
+ a.medalType = medalType;
235
+ a.minRank = rank;
236
+ rank += Number(v[key]);
237
+ a.maxRank = rank - 1;
238
+ award.push(a);
239
+ }
240
+ };
241
+
242
+ work("gold", MedalType.GOLD);
243
+ work("silver", MedalType.SILVER);
244
+ work("bronze", MedalType.BRONZE);
245
+
246
+ {
229
247
  const a = new Award();
230
- a.medalType = medalType;
248
+ a.medalType = MedalType.HONORABLE;
231
249
  a.minRank = rank;
232
- rank += Number(v[key]);
233
- a.maxRank = rank - 1;
250
+ a.maxRank = 0x3F3F3F3F;
234
251
  award.push(a);
235
252
  }
236
- };
237
-
238
- work("gold", MedalType.GOLD);
239
- work("silver", MedalType.SILVER);
240
- work("bronze", MedalType.BRONZE);
241
253
 
242
- {
243
- const a = new Award();
244
- a.medalType = MedalType.HONORABLE;
245
- a.minRank = rank;
246
- a.maxRank = 0x3F3F3F3F;
247
- award.push(a);
254
+ c.awards.set(k, award);
248
255
  }
249
-
250
- c.awards.set(k, award);
251
256
  }
252
257
  }
253
258
  })();
@@ -3,16 +3,22 @@ export class RankStatistics {
3
3
  teamSolvedNumIndex: Array<number>;
4
4
  maxSolvedProblems: number;
5
5
 
6
+ effectiveTeamNum: number;
7
+
6
8
  constructor() {
7
9
  this.teamSolvedNum = [];
8
10
  this.teamSolvedNumIndex = [];
9
11
  this.maxSolvedProblems = 0;
12
+
13
+ this.effectiveTeamNum = 0;
10
14
  }
11
15
 
12
16
  reset() {
13
17
  this.teamSolvedNum = [];
14
18
  this.teamSolvedNumIndex = [];
15
19
  this.maxSolvedProblems = 0;
20
+
21
+ this.effectiveTeamNum = 0;
16
22
  }
17
23
 
18
24
  getTeamSolvedNumIndex(solvedNum: number): number {
package/src/rank.ts CHANGED
@@ -10,6 +10,7 @@ import { Submission } from "./submission";
10
10
  import { TeamProblemStatistics } from "./problem";
11
11
  import { RankStatistics } from "./rank-statistics";
12
12
  import { Balloon, type Balloons } from "./balloon";
13
+ import { Award, MedalType } from "./award";
13
14
 
14
15
  export interface SelectOptionItem {
15
16
  value: string;
@@ -342,6 +343,9 @@ export class Rank {
342
343
  this.buildTeamRank();
343
344
  this.buildOrgRank();
344
345
 
346
+ this.rankStatistics.effectiveTeamNum = this.teams.filter(t => t.isEffectiveTeam).length;
347
+ this.buildAwards();
348
+
345
349
  this.teams.forEach(t => t.calcAwards(this.contest.awards?.get(this.options.group)));
346
350
  this.teams.forEach(t => t.postProcessPlaceChartPoints());
347
351
  })();
@@ -440,6 +444,48 @@ export class Rank {
440
444
  return res;
441
445
  }
442
446
 
447
+ buildAwards() {
448
+ if (this.contest.medal === "ccpc") {
449
+ this.contest.awards = new Map<string, Award[]>();
450
+
451
+ const tot = this.rankStatistics.effectiveTeamNum;
452
+ const award: Award[] = [];
453
+
454
+ const gold = new Award();
455
+ const silver = new Award();
456
+ const bronze = new Award();
457
+
458
+ {
459
+ gold.medalType = MedalType.GOLD;
460
+ gold.minRank = 1;
461
+ gold.maxRank = Math.ceil(tot * 0.1);
462
+ if (gold.maxRank >= gold.minRank) {
463
+ award.push(gold);
464
+ }
465
+ }
466
+
467
+ {
468
+ silver.medalType = MedalType.SILVER;
469
+ silver.minRank = gold.maxRank + 1;
470
+ silver.maxRank = Math.ceil(tot * 0.3);
471
+ if (silver.maxRank >= silver.minRank) {
472
+ award.push(silver);
473
+ }
474
+ }
475
+
476
+ {
477
+ bronze.medalType = MedalType.BRONZE;
478
+ bronze.minRank = silver.maxRank + 1;
479
+ bronze.maxRank = Math.ceil(tot * 0.6);
480
+ if (bronze.maxRank >= bronze.minRank) {
481
+ award.push(bronze);
482
+ }
483
+ }
484
+
485
+ this.contest.awards.set("official", award);
486
+ }
487
+ }
488
+
443
489
  filterTeamByOrg(team: Team) {
444
490
  const o = this.options;
445
491
 
package/src/team.ts CHANGED
@@ -127,6 +127,10 @@ export class Team {
127
127
  return this.members?.join(", ");
128
128
  }
129
129
 
130
+ get isEffectiveTeam() {
131
+ return this.solvedProblemNum > 0;
132
+ }
133
+
130
134
  calcSolvedData(options: ContestOptions) {
131
135
  this.solvedProblemNum = 0;
132
136
  this.attemptedProblemNum = 0;