@xcpcio/core 0.39.1 → 0.40.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
@@ -527,6 +527,7 @@ class ProblemStatistics {
527
527
  this.submittedNum = 0;
528
528
  this.attemptedNum = 0;
529
529
  this.ignoreNum = 0;
530
+ this.se = 0;
530
531
  this.firstSolveSubmissions = [];
531
532
  this.lastSolveSubmissions = [];
532
533
  }
@@ -537,6 +538,7 @@ class ProblemStatistics {
537
538
  this.submittedNum = 0;
538
539
  this.attemptedNum = 0;
539
540
  this.ignoreNum = 0;
541
+ this.se = 0;
540
542
  this.firstSolveSubmissions = [];
541
543
  this.lastSolveSubmissions = [];
542
544
  }
@@ -546,6 +548,11 @@ class ProblemStatistics {
546
548
  }
547
549
  return calcDirt(this.attemptedNum, this.acceptedNum);
548
550
  }
551
+ calcSE(totalTeams) {
552
+ const res = (totalTeams - this.acceptedNum) / totalTeams;
553
+ this.se = Math.round(res * 100) / 100;
554
+ return this.se;
555
+ }
549
556
  }
550
557
  class Problem {
551
558
  constructor() {
@@ -666,6 +673,7 @@ class Team {
666
673
  this.submissions = [];
667
674
  this.placeChartPoints = [];
668
675
  this.awards = [];
676
+ this.se = 0;
669
677
  }
670
678
  reset() {
671
679
  this.rank = 0;
@@ -681,15 +689,11 @@ class Team {
681
689
  this.submissions = [];
682
690
  this.placeChartPoints = [];
683
691
  this.awards = [];
692
+ this.se = 0;
684
693
  }
685
694
  get penaltyToMinute() {
686
695
  return Math.floor(this.penalty / 60);
687
696
  }
688
- get dirt() {
689
- const attemptedNum = this.attemptedProblemNum;
690
- const solvedNum = this.solvedProblemNum;
691
- return calcDirt(attemptedNum, solvedNum);
692
- }
693
697
  get isUnofficial() {
694
698
  return this.group.includes("unofficial");
695
699
  }
@@ -719,6 +723,27 @@ class Team {
719
723
  get isEffectiveTeam() {
720
724
  return this.solvedProblemNum > 0;
721
725
  }
726
+ get dirt() {
727
+ const attemptedNum = this.attemptedProblemNum;
728
+ const solvedNum = this.solvedProblemNum;
729
+ return calcDirt(attemptedNum, solvedNum);
730
+ }
731
+ calcSE(totalTeams) {
732
+ let acceptedProblemNums = 0;
733
+ let total = 0;
734
+ this.problemStatistics.forEach((p) => {
735
+ if (p.isSolved) {
736
+ acceptedProblemNums += 1;
737
+ total += p.problem.statistics.acceptedNum;
738
+ }
739
+ });
740
+ if (totalTeams === 0 || acceptedProblemNums === 0) {
741
+ return 0;
742
+ }
743
+ const res = (acceptedProblemNums * totalTeams - total) / totalTeams / acceptedProblemNums;
744
+ this.se = Math.round(res * 100) / 100;
745
+ return this.se;
746
+ }
722
747
  calcSolvedData(options) {
723
748
  this.solvedProblemNum = 0;
724
749
  this.attemptedProblemNum = 0;
@@ -1289,12 +1314,14 @@ class RankStatistics {
1289
1314
  this.teamSolvedNumIndex = [];
1290
1315
  this.maxSolvedProblems = 0;
1291
1316
  this.effectiveTeamNum = 0;
1317
+ this.totalTeamNum = 0;
1292
1318
  }
1293
1319
  reset() {
1294
1320
  this.teamSolvedNum = [];
1295
1321
  this.teamSolvedNumIndex = [];
1296
1322
  this.maxSolvedProblems = 0;
1297
1323
  this.effectiveTeamNum = 0;
1324
+ this.totalTeamNum = 0;
1298
1325
  }
1299
1326
  getTeamSolvedNumIndex(solvedNum) {
1300
1327
  return this.teamSolvedNumIndex[solvedNum] ?? 0;
@@ -1374,16 +1401,19 @@ class Rank {
1374
1401
  this.teams = ___default.cloneDeep(teams);
1375
1402
  this.teamsMap = new Map(this.teams.map((t) => [t.id, t]));
1376
1403
  this.submissions = ___default.cloneDeep(submissions).sort(Submission.compare);
1377
- this.submissions.forEach((s) => {
1404
+ {
1378
1405
  const o = this.contest.options;
1379
- s.timestampUnit = o.submissionTimestampUnit;
1380
- if (s.time) {
1381
- o.submissionHasTimeField = true;
1382
- }
1383
- if (s.language) {
1384
- o.submissionHasLanguageField = true;
1385
- }
1386
- });
1406
+ const timestampUnit = ___default.cloneDeep(o.submissionTimestampUnit);
1407
+ this.submissions.forEach((s) => {
1408
+ s.timestampUnit = timestampUnit;
1409
+ if (s.time) {
1410
+ o.submissionHasTimeField = true;
1411
+ }
1412
+ if (s.language) {
1413
+ o.submissionHasLanguageField = true;
1414
+ }
1415
+ });
1416
+ }
1387
1417
  this.submissionsMap = new Map(this.submissions.map((s) => [s.id, s]));
1388
1418
  this.organizations = this.buildOrganizations();
1389
1419
  this.originTeams = this.teams.map((t) => t);
@@ -1525,6 +1555,9 @@ class Rank {
1525
1555
  this.buildTeamRank();
1526
1556
  this.buildOrgRank();
1527
1557
  this.rankStatistics.effectiveTeamNum = this.teams.filter((t) => t.isEffectiveTeam).length;
1558
+ this.rankStatistics.totalTeamNum = this.teams.length;
1559
+ this.teams.forEach((t) => t.calcSE(this.rankStatistics.totalTeamNum));
1560
+ this.contest.problems.forEach((p) => p.statistics.calcSE(this.rankStatistics.totalTeamNum));
1528
1561
  this.buildAwards();
1529
1562
  this.teams.forEach((t) => t.calcAwards(this.contest.awards?.get(this.options.group)));
1530
1563
  this.teams.forEach((t) => t.postProcessPlaceChartPoints());
package/dist/index.d.ts CHANGED
@@ -39,9 +39,11 @@ declare class ProblemStatistics {
39
39
  ignoreNum: number;
40
40
  firstSolveSubmissions: Submissions;
41
41
  lastSolveSubmissions: Submissions;
42
+ se: number;
42
43
  constructor();
43
44
  reset(): void;
44
45
  get dirt(): number;
46
+ calcSE(totalTeams: number): number;
45
47
  }
46
48
  declare class Problem {
47
49
  id: string;
@@ -195,15 +197,17 @@ declare class Team {
195
197
  placeChartPoints: Array<PlaceChartPointData>;
196
198
  awards: MedalType[];
197
199
  location?: string;
200
+ se: number;
198
201
  constructor();
199
202
  reset(): void;
200
203
  get penaltyToMinute(): number;
201
- get dirt(): number;
202
204
  get isUnofficial(): boolean;
203
205
  get isGirl(): boolean;
204
206
  get membersToArray(): string[];
205
207
  get membersToString(): string | undefined;
206
208
  get isEffectiveTeam(): boolean;
209
+ get dirt(): number;
210
+ calcSE(totalTeams: number): number;
207
211
  calcSolvedData(options: ContestOptions): void;
208
212
  calcAwards(awards?: Award[]): void;
209
213
  isEqualRank(otherTeam: Team): boolean;
@@ -219,6 +223,7 @@ declare class RankStatistics {
219
223
  teamSolvedNumIndex: Array<number>;
220
224
  maxSolvedProblems: number;
221
225
  effectiveTeamNum: number;
226
+ totalTeamNum: number;
222
227
  constructor();
223
228
  reset(): void;
224
229
  getTeamSolvedNumIndex(solvedNum: number): number;
package/dist/index.mjs CHANGED
@@ -496,6 +496,7 @@ class ProblemStatistics {
496
496
  this.submittedNum = 0;
497
497
  this.attemptedNum = 0;
498
498
  this.ignoreNum = 0;
499
+ this.se = 0;
499
500
  this.firstSolveSubmissions = [];
500
501
  this.lastSolveSubmissions = [];
501
502
  }
@@ -506,6 +507,7 @@ class ProblemStatistics {
506
507
  this.submittedNum = 0;
507
508
  this.attemptedNum = 0;
508
509
  this.ignoreNum = 0;
510
+ this.se = 0;
509
511
  this.firstSolveSubmissions = [];
510
512
  this.lastSolveSubmissions = [];
511
513
  }
@@ -515,6 +517,11 @@ class ProblemStatistics {
515
517
  }
516
518
  return calcDirt(this.attemptedNum, this.acceptedNum);
517
519
  }
520
+ calcSE(totalTeams) {
521
+ const res = (totalTeams - this.acceptedNum) / totalTeams;
522
+ this.se = Math.round(res * 100) / 100;
523
+ return this.se;
524
+ }
518
525
  }
519
526
  class Problem {
520
527
  constructor() {
@@ -635,6 +642,7 @@ class Team {
635
642
  this.submissions = [];
636
643
  this.placeChartPoints = [];
637
644
  this.awards = [];
645
+ this.se = 0;
638
646
  }
639
647
  reset() {
640
648
  this.rank = 0;
@@ -650,15 +658,11 @@ class Team {
650
658
  this.submissions = [];
651
659
  this.placeChartPoints = [];
652
660
  this.awards = [];
661
+ this.se = 0;
653
662
  }
654
663
  get penaltyToMinute() {
655
664
  return Math.floor(this.penalty / 60);
656
665
  }
657
- get dirt() {
658
- const attemptedNum = this.attemptedProblemNum;
659
- const solvedNum = this.solvedProblemNum;
660
- return calcDirt(attemptedNum, solvedNum);
661
- }
662
666
  get isUnofficial() {
663
667
  return this.group.includes("unofficial");
664
668
  }
@@ -688,6 +692,27 @@ class Team {
688
692
  get isEffectiveTeam() {
689
693
  return this.solvedProblemNum > 0;
690
694
  }
695
+ get dirt() {
696
+ const attemptedNum = this.attemptedProblemNum;
697
+ const solvedNum = this.solvedProblemNum;
698
+ return calcDirt(attemptedNum, solvedNum);
699
+ }
700
+ calcSE(totalTeams) {
701
+ let acceptedProblemNums = 0;
702
+ let total = 0;
703
+ this.problemStatistics.forEach((p) => {
704
+ if (p.isSolved) {
705
+ acceptedProblemNums += 1;
706
+ total += p.problem.statistics.acceptedNum;
707
+ }
708
+ });
709
+ if (totalTeams === 0 || acceptedProblemNums === 0) {
710
+ return 0;
711
+ }
712
+ const res = (acceptedProblemNums * totalTeams - total) / totalTeams / acceptedProblemNums;
713
+ this.se = Math.round(res * 100) / 100;
714
+ return this.se;
715
+ }
691
716
  calcSolvedData(options) {
692
717
  this.solvedProblemNum = 0;
693
718
  this.attemptedProblemNum = 0;
@@ -1258,12 +1283,14 @@ class RankStatistics {
1258
1283
  this.teamSolvedNumIndex = [];
1259
1284
  this.maxSolvedProblems = 0;
1260
1285
  this.effectiveTeamNum = 0;
1286
+ this.totalTeamNum = 0;
1261
1287
  }
1262
1288
  reset() {
1263
1289
  this.teamSolvedNum = [];
1264
1290
  this.teamSolvedNumIndex = [];
1265
1291
  this.maxSolvedProblems = 0;
1266
1292
  this.effectiveTeamNum = 0;
1293
+ this.totalTeamNum = 0;
1267
1294
  }
1268
1295
  getTeamSolvedNumIndex(solvedNum) {
1269
1296
  return this.teamSolvedNumIndex[solvedNum] ?? 0;
@@ -1343,16 +1370,19 @@ class Rank {
1343
1370
  this.teams = _.cloneDeep(teams);
1344
1371
  this.teamsMap = new Map(this.teams.map((t) => [t.id, t]));
1345
1372
  this.submissions = _.cloneDeep(submissions).sort(Submission.compare);
1346
- this.submissions.forEach((s) => {
1373
+ {
1347
1374
  const o = this.contest.options;
1348
- s.timestampUnit = o.submissionTimestampUnit;
1349
- if (s.time) {
1350
- o.submissionHasTimeField = true;
1351
- }
1352
- if (s.language) {
1353
- o.submissionHasLanguageField = true;
1354
- }
1355
- });
1375
+ const timestampUnit = _.cloneDeep(o.submissionTimestampUnit);
1376
+ this.submissions.forEach((s) => {
1377
+ s.timestampUnit = timestampUnit;
1378
+ if (s.time) {
1379
+ o.submissionHasTimeField = true;
1380
+ }
1381
+ if (s.language) {
1382
+ o.submissionHasLanguageField = true;
1383
+ }
1384
+ });
1385
+ }
1356
1386
  this.submissionsMap = new Map(this.submissions.map((s) => [s.id, s]));
1357
1387
  this.organizations = this.buildOrganizations();
1358
1388
  this.originTeams = this.teams.map((t) => t);
@@ -1494,6 +1524,9 @@ class Rank {
1494
1524
  this.buildTeamRank();
1495
1525
  this.buildOrgRank();
1496
1526
  this.rankStatistics.effectiveTeamNum = this.teams.filter((t) => t.isEffectiveTeam).length;
1527
+ this.rankStatistics.totalTeamNum = this.teams.length;
1528
+ this.teams.forEach((t) => t.calcSE(this.rankStatistics.totalTeamNum));
1529
+ this.contest.problems.forEach((p) => p.statistics.calcSE(this.rankStatistics.totalTeamNum));
1497
1530
  this.buildAwards();
1498
1531
  this.teams.forEach((t) => t.calcAwards(this.contest.awards?.get(this.options.group)));
1499
1532
  this.teams.forEach((t) => t.postProcessPlaceChartPoints());
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xcpcio/core",
3
- "version": "0.39.1",
3
+ "version": "0.40.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.39.1"
49
+ "@xcpcio/types": "0.40.1"
50
50
  },
51
51
  "devDependencies": {
52
52
  "@babel/types": "^7.22.4",
package/src/problem.ts CHANGED
@@ -17,6 +17,8 @@ export class ProblemStatistics {
17
17
  firstSolveSubmissions: Submissions;
18
18
  lastSolveSubmissions: Submissions;
19
19
 
20
+ se: number;
21
+
20
22
  constructor() {
21
23
  this.acceptedNum = 0;
22
24
  this.rejectedNum = 0;
@@ -26,6 +28,8 @@ export class ProblemStatistics {
26
28
  this.attemptedNum = 0;
27
29
  this.ignoreNum = 0;
28
30
 
31
+ this.se = 0;
32
+
29
33
  this.firstSolveSubmissions = [];
30
34
  this.lastSolveSubmissions = [];
31
35
  }
@@ -39,6 +43,8 @@ export class ProblemStatistics {
39
43
  this.attemptedNum = 0;
40
44
  this.ignoreNum = 0;
41
45
 
46
+ this.se = 0;
47
+
42
48
  this.firstSolveSubmissions = [];
43
49
  this.lastSolveSubmissions = [];
44
50
  }
@@ -50,6 +56,13 @@ export class ProblemStatistics {
50
56
 
51
57
  return calcDirt(this.attemptedNum, this.acceptedNum);
52
58
  }
59
+
60
+ calcSE(totalTeams: number) {
61
+ const res = (totalTeams - this.acceptedNum) / totalTeams;
62
+ this.se = Math.round(res * 100) / 100;
63
+
64
+ return this.se;
65
+ }
53
66
  }
54
67
 
55
68
  export class Problem {
@@ -5,12 +5,16 @@ export class RankStatistics {
5
5
 
6
6
  effectiveTeamNum: number;
7
7
 
8
+ totalTeamNum: number;
9
+
8
10
  constructor() {
9
11
  this.teamSolvedNum = [];
10
12
  this.teamSolvedNumIndex = [];
11
13
  this.maxSolvedProblems = 0;
12
14
 
13
15
  this.effectiveTeamNum = 0;
16
+
17
+ this.totalTeamNum = 0;
14
18
  }
15
19
 
16
20
  reset() {
@@ -19,6 +23,8 @@ export class RankStatistics {
19
23
  this.maxSolvedProblems = 0;
20
24
 
21
25
  this.effectiveTeamNum = 0;
26
+
27
+ this.totalTeamNum = 0;
22
28
  }
23
29
 
24
30
  getTeamSolvedNumIndex(solvedNum: number): number {
package/src/rank.ts CHANGED
@@ -147,19 +147,21 @@ export class Rank {
147
147
 
148
148
  this.submissions = _.cloneDeep(submissions).sort(Submission.compare);
149
149
 
150
- this.submissions.forEach((s) => {
150
+ {
151
151
  const o = this.contest.options;
152
+ const timestampUnit = _.cloneDeep(o.submissionTimestampUnit);
153
+ this.submissions.forEach((s) => {
154
+ s.timestampUnit = timestampUnit;
152
155
 
153
- s.timestampUnit = o.submissionTimestampUnit;
154
-
155
- if (s.time) {
156
- o.submissionHasTimeField = true;
157
- }
156
+ if (s.time) {
157
+ o.submissionHasTimeField = true;
158
+ }
158
159
 
159
- if (s.language) {
160
- o.submissionHasLanguageField = true;
161
- }
162
- });
160
+ if (s.language) {
161
+ o.submissionHasLanguageField = true;
162
+ }
163
+ });
164
+ }
163
165
 
164
166
  this.submissionsMap = new Map(this.submissions.map(s => [s.id, s]));
165
167
 
@@ -349,6 +351,9 @@ export class Rank {
349
351
  this.buildOrgRank();
350
352
 
351
353
  this.rankStatistics.effectiveTeamNum = this.teams.filter(t => t.isEffectiveTeam).length;
354
+ this.rankStatistics.totalTeamNum = this.teams.length;
355
+ this.teams.forEach(t => t.calcSE(this.rankStatistics.totalTeamNum));
356
+ this.contest.problems.forEach(p => p.statistics.calcSE(this.rankStatistics.totalTeamNum));
352
357
  this.buildAwards();
353
358
 
354
359
  this.teams.forEach(t => t.calcAwards(this.contest.awards?.get(this.options.group)));
package/src/team.ts CHANGED
@@ -54,6 +54,8 @@ export class Team {
54
54
 
55
55
  location?: string;
56
56
 
57
+ se: number;
58
+
57
59
  constructor() {
58
60
  this.id = "";
59
61
  this.name = "";
@@ -83,6 +85,8 @@ export class Team {
83
85
  this.placeChartPoints = [];
84
86
 
85
87
  this.awards = [];
88
+
89
+ this.se = 0;
86
90
  }
87
91
 
88
92
  reset() {
@@ -106,19 +110,14 @@ export class Team {
106
110
  this.placeChartPoints = [];
107
111
 
108
112
  this.awards = [];
113
+
114
+ this.se = 0;
109
115
  }
110
116
 
111
117
  get penaltyToMinute() {
112
118
  return Math.floor(this.penalty / 60);
113
119
  }
114
120
 
115
- get dirt() {
116
- const attemptedNum = this.attemptedProblemNum;
117
- const solvedNum = this.solvedProblemNum;
118
-
119
- return calcDirt(attemptedNum, solvedNum);
120
- }
121
-
122
121
  get isUnofficial() {
123
122
  return this.group.includes("unofficial");
124
123
  }
@@ -157,6 +156,34 @@ export class Team {
157
156
  return this.solvedProblemNum > 0;
158
157
  }
159
158
 
159
+ get dirt() {
160
+ const attemptedNum = this.attemptedProblemNum;
161
+ const solvedNum = this.solvedProblemNum;
162
+
163
+ return calcDirt(attemptedNum, solvedNum);
164
+ }
165
+
166
+ calcSE(totalTeams: number) {
167
+ let acceptedProblemNums = 0;
168
+ let total = 0;
169
+
170
+ this.problemStatistics.forEach((p) => {
171
+ if (p.isSolved) {
172
+ acceptedProblemNums += 1;
173
+ total += p.problem.statistics.acceptedNum;
174
+ }
175
+ });
176
+
177
+ if (totalTeams === 0 || acceptedProblemNums === 0) {
178
+ return 0;
179
+ }
180
+
181
+ const res = (acceptedProblemNums * totalTeams - total) / totalTeams / acceptedProblemNums;
182
+ this.se = Math.round(res * 100) / 100;
183
+
184
+ return this.se;
185
+ }
186
+
160
187
  calcSolvedData(options: ContestOptions) {
161
188
  this.solvedProblemNum = 0;
162
189
  this.attemptedProblemNum = 0;