@xcpcio/core 0.27.0 → 0.28.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 +66 -5
- package/dist/index.d.ts +10 -1
- package/dist/index.mjs +66 -5
- package/package.json +2 -2
- package/src/contest-options.ts +13 -1
- package/src/rank.ts +20 -5
- package/src/submission.ts +67 -1
package/dist/index.cjs
CHANGED
|
@@ -755,6 +755,7 @@ class Submission {
|
|
|
755
755
|
this.teamId = "";
|
|
756
756
|
this.problemId = "";
|
|
757
757
|
this.timestamp = 0;
|
|
758
|
+
this.timestampUnit = "second";
|
|
758
759
|
}
|
|
759
760
|
isAccepted() {
|
|
760
761
|
return isAccepted(this.status);
|
|
@@ -769,8 +770,46 @@ class Submission {
|
|
|
769
770
|
return isNotCalculatedPenaltyStatus(this.status);
|
|
770
771
|
}
|
|
771
772
|
get timestampToMinute() {
|
|
773
|
+
if (this.timestampUnit === "nanosecond") {
|
|
774
|
+
return Math.floor(this.timestamp / 60 / 1e3 / 1e3 / 1e3);
|
|
775
|
+
}
|
|
776
|
+
if (this.timestampUnit === "microsecond") {
|
|
777
|
+
return Math.floor(this.timestamp / 60 / 1e3 / 1e3);
|
|
778
|
+
}
|
|
779
|
+
if (this.timestampUnit === "millisecond") {
|
|
780
|
+
return Math.floor(this.timestamp / 60 / 1e3);
|
|
781
|
+
}
|
|
772
782
|
return Math.floor(this.timestamp / 60);
|
|
773
783
|
}
|
|
784
|
+
get timestampToSecond() {
|
|
785
|
+
if (this.timestampUnit === "nanosecond") {
|
|
786
|
+
return Math.floor(this.timestamp / 1e3 / 1e3 / 1e3);
|
|
787
|
+
}
|
|
788
|
+
if (this.timestampUnit === "microsecond") {
|
|
789
|
+
return Math.floor(this.timestamp / 1e3 / 1e3);
|
|
790
|
+
}
|
|
791
|
+
if (this.timestampUnit === "millisecond") {
|
|
792
|
+
return Math.floor(this.timestamp / 1e3);
|
|
793
|
+
}
|
|
794
|
+
return this.timestamp;
|
|
795
|
+
}
|
|
796
|
+
get timestampDisplayFormatWithSecond() {
|
|
797
|
+
const second = this.timestampToSecond;
|
|
798
|
+
const h = Math.floor(second / 3600);
|
|
799
|
+
const m = Math.floor(second % 3600 / 60);
|
|
800
|
+
const s = second % 60;
|
|
801
|
+
const f = (x) => x.toString().padStart(2, "0");
|
|
802
|
+
const res = `${f(h)}:${f(m)}:${f(s)}`;
|
|
803
|
+
return res;
|
|
804
|
+
}
|
|
805
|
+
get timestampDisplayFormatWithMilliSecond() {
|
|
806
|
+
let res = this.timestampDisplayFormatWithSecond;
|
|
807
|
+
if (this.timestampUnit === "millisecond") {
|
|
808
|
+
const fl = (this.timestamp % 1e3).toString().padEnd(3, "0");
|
|
809
|
+
res += `.${fl}`;
|
|
810
|
+
}
|
|
811
|
+
return res;
|
|
812
|
+
}
|
|
774
813
|
static compare(lhs, rhs) {
|
|
775
814
|
if (lhs.timestamp !== rhs.timestamp) {
|
|
776
815
|
return lhs.timestamp - rhs.timestamp;
|
|
@@ -794,6 +833,12 @@ function createSubmission(submissionJSON) {
|
|
|
794
833
|
s.timestamp = submissionJSON.timestamp;
|
|
795
834
|
s.status = stringToSubmissionStatus(submissionJSON.status);
|
|
796
835
|
s.isIgnore = submissionJSON.is_ignore ?? false;
|
|
836
|
+
if (submissionJSON.time) {
|
|
837
|
+
s.time = submissionJSON.time;
|
|
838
|
+
}
|
|
839
|
+
if (submissionJSON.language) {
|
|
840
|
+
s.language = submissionJSON.language;
|
|
841
|
+
}
|
|
797
842
|
return s;
|
|
798
843
|
}
|
|
799
844
|
function createSubmissions(submissionsJSON) {
|
|
@@ -829,6 +874,9 @@ class Group {
|
|
|
829
874
|
class ContestOptions {
|
|
830
875
|
constructor() {
|
|
831
876
|
this.calculationOfPenalty = "in_minutes";
|
|
877
|
+
this.submissionTimestampUnit = "second";
|
|
878
|
+
this.submissionHasTimeField = false;
|
|
879
|
+
this.submissionHasLanguageField = false;
|
|
832
880
|
}
|
|
833
881
|
}
|
|
834
882
|
function createContestOptions(contestOptionsJSON = {}) {
|
|
@@ -837,6 +885,9 @@ function createContestOptions(contestOptionsJSON = {}) {
|
|
|
837
885
|
if (j.calculation_of_penalty) {
|
|
838
886
|
o.calculationOfPenalty = j.calculation_of_penalty;
|
|
839
887
|
}
|
|
888
|
+
if (j.submission_timestamp_unit) {
|
|
889
|
+
o.submissionTimestampUnit = j.submission_timestamp_unit;
|
|
890
|
+
}
|
|
840
891
|
return o;
|
|
841
892
|
}
|
|
842
893
|
|
|
@@ -1190,6 +1241,16 @@ class Rank {
|
|
|
1190
1241
|
this.teams = ___default.cloneDeep(teams);
|
|
1191
1242
|
this.teamsMap = new Map(this.teams.map((t) => [t.id, t]));
|
|
1192
1243
|
this.submissions = ___default.cloneDeep(submissions).sort(Submission.compare);
|
|
1244
|
+
this.submissions.forEach((s) => {
|
|
1245
|
+
const o = this.contest.options;
|
|
1246
|
+
s.timestampUnit = o.submissionTimestampUnit;
|
|
1247
|
+
if (s.time) {
|
|
1248
|
+
o.submissionHasTimeField = true;
|
|
1249
|
+
}
|
|
1250
|
+
if (s.language) {
|
|
1251
|
+
o.submissionHasLanguageField = true;
|
|
1252
|
+
}
|
|
1253
|
+
});
|
|
1193
1254
|
this.submissionsMap = new Map(this.submissions.map((s) => [s.id, s]));
|
|
1194
1255
|
this.organizations = this.buildOrganizations();
|
|
1195
1256
|
this.originTeams = this.teams.map((t) => t);
|
|
@@ -1263,11 +1324,11 @@ class Rank {
|
|
|
1263
1324
|
return;
|
|
1264
1325
|
}
|
|
1265
1326
|
problemStatistics.isSubmitted = true;
|
|
1266
|
-
problemStatistics.lastSubmitTimestamp = s.
|
|
1327
|
+
problemStatistics.lastSubmitTimestamp = s.timestampToSecond;
|
|
1267
1328
|
problemStatistics.totalCount++;
|
|
1268
1329
|
if (s.isAccepted()) {
|
|
1269
1330
|
problemStatistics.isSolved = true;
|
|
1270
|
-
problemStatistics.solvedTimestamp = s.
|
|
1331
|
+
problemStatistics.solvedTimestamp = s.timestampToSecond;
|
|
1271
1332
|
problem.statistics.acceptedNum++;
|
|
1272
1333
|
problem.statistics.attemptedNum += problemStatistics.failedCount + 1;
|
|
1273
1334
|
if (problem.statistics.firstSolveSubmissions.length === 0 || problem.statistics.firstSolveSubmissions[problem.statistics.firstSolveSubmissions.length - 1].timestamp === s.timestamp) {
|
|
@@ -1279,7 +1340,7 @@ class Rank {
|
|
|
1279
1340
|
}
|
|
1280
1341
|
problem.statistics.lastSolveSubmissions.push(s);
|
|
1281
1342
|
team.lastSolvedProblem = problem;
|
|
1282
|
-
team.lastSolvedProblemTimestamp = s.
|
|
1343
|
+
team.lastSolvedProblemTimestamp = s.timestampToSecond;
|
|
1283
1344
|
}
|
|
1284
1345
|
if (s.isRejected()) {
|
|
1285
1346
|
problemStatistics.failedCount++;
|
|
@@ -1400,7 +1461,7 @@ class Rank {
|
|
|
1400
1461
|
return this.submissions;
|
|
1401
1462
|
}
|
|
1402
1463
|
return this.submissions.filter(
|
|
1403
|
-
(s) => s.
|
|
1464
|
+
(s) => s.timestampToSecond <= this.options.timestamp
|
|
1404
1465
|
).sort(Submission.compare);
|
|
1405
1466
|
}
|
|
1406
1467
|
buildBalloons() {
|
|
@@ -1423,7 +1484,7 @@ class Rank {
|
|
|
1423
1484
|
}
|
|
1424
1485
|
if (s.isAccepted()) {
|
|
1425
1486
|
problemStatistics.isSolved = true;
|
|
1426
|
-
problemStatistics.solvedTimestamp = s.
|
|
1487
|
+
problemStatistics.solvedTimestamp = s.timestampToSecond;
|
|
1427
1488
|
const b = new Balloon();
|
|
1428
1489
|
b.team = team;
|
|
1429
1490
|
b.problem = problem;
|
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, 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, 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';
|
|
@@ -8,6 +8,9 @@ declare class Submission {
|
|
|
8
8
|
teamId: string;
|
|
9
9
|
problemId: string;
|
|
10
10
|
timestamp: number;
|
|
11
|
+
timestampUnit: TimeUnit;
|
|
12
|
+
time?: number;
|
|
13
|
+
language?: string;
|
|
11
14
|
status: SubmissionStatus;
|
|
12
15
|
isIgnore: boolean;
|
|
13
16
|
constructor();
|
|
@@ -16,6 +19,9 @@ declare class Submission {
|
|
|
16
19
|
isPending(): boolean;
|
|
17
20
|
isNotCalculatedPenaltyStatus(): boolean;
|
|
18
21
|
get timestampToMinute(): number;
|
|
22
|
+
get timestampToSecond(): number;
|
|
23
|
+
get timestampDisplayFormatWithSecond(): string;
|
|
24
|
+
get timestampDisplayFormatWithMilliSecond(): string;
|
|
19
25
|
static compare(lhs: Submission, rhs: Submission): number;
|
|
20
26
|
}
|
|
21
27
|
type Submissions = Array<Submission>;
|
|
@@ -106,6 +112,9 @@ type Awards = Map<string, Award[]>;
|
|
|
106
112
|
|
|
107
113
|
declare class ContestOptions {
|
|
108
114
|
calculationOfPenalty: CalculationOfPenalty;
|
|
115
|
+
submissionTimestampUnit: TimeUnit;
|
|
116
|
+
submissionHasTimeField: boolean;
|
|
117
|
+
submissionHasLanguageField: boolean;
|
|
109
118
|
constructor();
|
|
110
119
|
}
|
|
111
120
|
|
package/dist/index.mjs
CHANGED
|
@@ -725,6 +725,7 @@ class Submission {
|
|
|
725
725
|
this.teamId = "";
|
|
726
726
|
this.problemId = "";
|
|
727
727
|
this.timestamp = 0;
|
|
728
|
+
this.timestampUnit = "second";
|
|
728
729
|
}
|
|
729
730
|
isAccepted() {
|
|
730
731
|
return isAccepted(this.status);
|
|
@@ -739,8 +740,46 @@ class Submission {
|
|
|
739
740
|
return isNotCalculatedPenaltyStatus(this.status);
|
|
740
741
|
}
|
|
741
742
|
get timestampToMinute() {
|
|
743
|
+
if (this.timestampUnit === "nanosecond") {
|
|
744
|
+
return Math.floor(this.timestamp / 60 / 1e3 / 1e3 / 1e3);
|
|
745
|
+
}
|
|
746
|
+
if (this.timestampUnit === "microsecond") {
|
|
747
|
+
return Math.floor(this.timestamp / 60 / 1e3 / 1e3);
|
|
748
|
+
}
|
|
749
|
+
if (this.timestampUnit === "millisecond") {
|
|
750
|
+
return Math.floor(this.timestamp / 60 / 1e3);
|
|
751
|
+
}
|
|
742
752
|
return Math.floor(this.timestamp / 60);
|
|
743
753
|
}
|
|
754
|
+
get timestampToSecond() {
|
|
755
|
+
if (this.timestampUnit === "nanosecond") {
|
|
756
|
+
return Math.floor(this.timestamp / 1e3 / 1e3 / 1e3);
|
|
757
|
+
}
|
|
758
|
+
if (this.timestampUnit === "microsecond") {
|
|
759
|
+
return Math.floor(this.timestamp / 1e3 / 1e3);
|
|
760
|
+
}
|
|
761
|
+
if (this.timestampUnit === "millisecond") {
|
|
762
|
+
return Math.floor(this.timestamp / 1e3);
|
|
763
|
+
}
|
|
764
|
+
return this.timestamp;
|
|
765
|
+
}
|
|
766
|
+
get timestampDisplayFormatWithSecond() {
|
|
767
|
+
const second = this.timestampToSecond;
|
|
768
|
+
const h = Math.floor(second / 3600);
|
|
769
|
+
const m = Math.floor(second % 3600 / 60);
|
|
770
|
+
const s = second % 60;
|
|
771
|
+
const f = (x) => x.toString().padStart(2, "0");
|
|
772
|
+
const res = `${f(h)}:${f(m)}:${f(s)}`;
|
|
773
|
+
return res;
|
|
774
|
+
}
|
|
775
|
+
get timestampDisplayFormatWithMilliSecond() {
|
|
776
|
+
let res = this.timestampDisplayFormatWithSecond;
|
|
777
|
+
if (this.timestampUnit === "millisecond") {
|
|
778
|
+
const fl = (this.timestamp % 1e3).toString().padEnd(3, "0");
|
|
779
|
+
res += `.${fl}`;
|
|
780
|
+
}
|
|
781
|
+
return res;
|
|
782
|
+
}
|
|
744
783
|
static compare(lhs, rhs) {
|
|
745
784
|
if (lhs.timestamp !== rhs.timestamp) {
|
|
746
785
|
return lhs.timestamp - rhs.timestamp;
|
|
@@ -764,6 +803,12 @@ function createSubmission(submissionJSON) {
|
|
|
764
803
|
s.timestamp = submissionJSON.timestamp;
|
|
765
804
|
s.status = stringToSubmissionStatus(submissionJSON.status);
|
|
766
805
|
s.isIgnore = submissionJSON.is_ignore ?? false;
|
|
806
|
+
if (submissionJSON.time) {
|
|
807
|
+
s.time = submissionJSON.time;
|
|
808
|
+
}
|
|
809
|
+
if (submissionJSON.language) {
|
|
810
|
+
s.language = submissionJSON.language;
|
|
811
|
+
}
|
|
767
812
|
return s;
|
|
768
813
|
}
|
|
769
814
|
function createSubmissions(submissionsJSON) {
|
|
@@ -799,6 +844,9 @@ class Group {
|
|
|
799
844
|
class ContestOptions {
|
|
800
845
|
constructor() {
|
|
801
846
|
this.calculationOfPenalty = "in_minutes";
|
|
847
|
+
this.submissionTimestampUnit = "second";
|
|
848
|
+
this.submissionHasTimeField = false;
|
|
849
|
+
this.submissionHasLanguageField = false;
|
|
802
850
|
}
|
|
803
851
|
}
|
|
804
852
|
function createContestOptions(contestOptionsJSON = {}) {
|
|
@@ -807,6 +855,9 @@ function createContestOptions(contestOptionsJSON = {}) {
|
|
|
807
855
|
if (j.calculation_of_penalty) {
|
|
808
856
|
o.calculationOfPenalty = j.calculation_of_penalty;
|
|
809
857
|
}
|
|
858
|
+
if (j.submission_timestamp_unit) {
|
|
859
|
+
o.submissionTimestampUnit = j.submission_timestamp_unit;
|
|
860
|
+
}
|
|
810
861
|
return o;
|
|
811
862
|
}
|
|
812
863
|
|
|
@@ -1160,6 +1211,16 @@ class Rank {
|
|
|
1160
1211
|
this.teams = _.cloneDeep(teams);
|
|
1161
1212
|
this.teamsMap = new Map(this.teams.map((t) => [t.id, t]));
|
|
1162
1213
|
this.submissions = _.cloneDeep(submissions).sort(Submission.compare);
|
|
1214
|
+
this.submissions.forEach((s) => {
|
|
1215
|
+
const o = this.contest.options;
|
|
1216
|
+
s.timestampUnit = o.submissionTimestampUnit;
|
|
1217
|
+
if (s.time) {
|
|
1218
|
+
o.submissionHasTimeField = true;
|
|
1219
|
+
}
|
|
1220
|
+
if (s.language) {
|
|
1221
|
+
o.submissionHasLanguageField = true;
|
|
1222
|
+
}
|
|
1223
|
+
});
|
|
1163
1224
|
this.submissionsMap = new Map(this.submissions.map((s) => [s.id, s]));
|
|
1164
1225
|
this.organizations = this.buildOrganizations();
|
|
1165
1226
|
this.originTeams = this.teams.map((t) => t);
|
|
@@ -1233,11 +1294,11 @@ class Rank {
|
|
|
1233
1294
|
return;
|
|
1234
1295
|
}
|
|
1235
1296
|
problemStatistics.isSubmitted = true;
|
|
1236
|
-
problemStatistics.lastSubmitTimestamp = s.
|
|
1297
|
+
problemStatistics.lastSubmitTimestamp = s.timestampToSecond;
|
|
1237
1298
|
problemStatistics.totalCount++;
|
|
1238
1299
|
if (s.isAccepted()) {
|
|
1239
1300
|
problemStatistics.isSolved = true;
|
|
1240
|
-
problemStatistics.solvedTimestamp = s.
|
|
1301
|
+
problemStatistics.solvedTimestamp = s.timestampToSecond;
|
|
1241
1302
|
problem.statistics.acceptedNum++;
|
|
1242
1303
|
problem.statistics.attemptedNum += problemStatistics.failedCount + 1;
|
|
1243
1304
|
if (problem.statistics.firstSolveSubmissions.length === 0 || problem.statistics.firstSolveSubmissions[problem.statistics.firstSolveSubmissions.length - 1].timestamp === s.timestamp) {
|
|
@@ -1249,7 +1310,7 @@ class Rank {
|
|
|
1249
1310
|
}
|
|
1250
1311
|
problem.statistics.lastSolveSubmissions.push(s);
|
|
1251
1312
|
team.lastSolvedProblem = problem;
|
|
1252
|
-
team.lastSolvedProblemTimestamp = s.
|
|
1313
|
+
team.lastSolvedProblemTimestamp = s.timestampToSecond;
|
|
1253
1314
|
}
|
|
1254
1315
|
if (s.isRejected()) {
|
|
1255
1316
|
problemStatistics.failedCount++;
|
|
@@ -1370,7 +1431,7 @@ class Rank {
|
|
|
1370
1431
|
return this.submissions;
|
|
1371
1432
|
}
|
|
1372
1433
|
return this.submissions.filter(
|
|
1373
|
-
(s) => s.
|
|
1434
|
+
(s) => s.timestampToSecond <= this.options.timestamp
|
|
1374
1435
|
).sort(Submission.compare);
|
|
1375
1436
|
}
|
|
1376
1437
|
buildBalloons() {
|
|
@@ -1393,7 +1454,7 @@ class Rank {
|
|
|
1393
1454
|
}
|
|
1394
1455
|
if (s.isAccepted()) {
|
|
1395
1456
|
problemStatistics.isSolved = true;
|
|
1396
|
-
problemStatistics.solvedTimestamp = s.
|
|
1457
|
+
problemStatistics.solvedTimestamp = s.timestampToSecond;
|
|
1397
1458
|
const b = new Balloon();
|
|
1398
1459
|
b.team = team;
|
|
1399
1460
|
b.problem = problem;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xcpcio/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.28.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.
|
|
47
|
+
"@xcpcio/types": "0.28.0"
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
50
|
"@babel/types": "^7.22.4",
|
package/src/contest-options.ts
CHANGED
|
@@ -1,10 +1,18 @@
|
|
|
1
|
-
import type { CalculationOfPenalty, ContestOptions as IContestOptions } from "@xcpcio/types";
|
|
1
|
+
import type { CalculationOfPenalty, ContestOptions as IContestOptions, TimeUnit } from "@xcpcio/types";
|
|
2
2
|
|
|
3
3
|
export class ContestOptions {
|
|
4
4
|
calculationOfPenalty: CalculationOfPenalty;
|
|
5
|
+
submissionTimestampUnit: TimeUnit;
|
|
6
|
+
|
|
7
|
+
submissionHasTimeField: boolean;
|
|
8
|
+
submissionHasLanguageField: boolean;
|
|
5
9
|
|
|
6
10
|
constructor() {
|
|
7
11
|
this.calculationOfPenalty = "in_minutes";
|
|
12
|
+
this.submissionTimestampUnit = "second";
|
|
13
|
+
|
|
14
|
+
this.submissionHasTimeField = false;
|
|
15
|
+
this.submissionHasLanguageField = false;
|
|
8
16
|
}
|
|
9
17
|
}
|
|
10
18
|
|
|
@@ -16,5 +24,9 @@ export function createContestOptions(contestOptionsJSON: IContestOptions = {}):
|
|
|
16
24
|
o.calculationOfPenalty = j.calculation_of_penalty;
|
|
17
25
|
}
|
|
18
26
|
|
|
27
|
+
if (j.submission_timestamp_unit) {
|
|
28
|
+
o.submissionTimestampUnit = j.submission_timestamp_unit;
|
|
29
|
+
}
|
|
30
|
+
|
|
19
31
|
return o;
|
|
20
32
|
}
|
package/src/rank.ts
CHANGED
|
@@ -136,6 +136,21 @@ export class Rank {
|
|
|
136
136
|
this.teamsMap = new Map(this.teams.map(t => [t.id, t]));
|
|
137
137
|
|
|
138
138
|
this.submissions = _.cloneDeep(submissions).sort(Submission.compare);
|
|
139
|
+
|
|
140
|
+
this.submissions.forEach((s) => {
|
|
141
|
+
const o = this.contest.options;
|
|
142
|
+
|
|
143
|
+
s.timestampUnit = o.submissionTimestampUnit;
|
|
144
|
+
|
|
145
|
+
if (s.time) {
|
|
146
|
+
o.submissionHasTimeField = true;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
if (s.language) {
|
|
150
|
+
o.submissionHasLanguageField = true;
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
|
|
139
154
|
this.submissionsMap = new Map(this.submissions.map(s => [s.id, s]));
|
|
140
155
|
|
|
141
156
|
this.organizations = this.buildOrganizations();
|
|
@@ -233,12 +248,12 @@ export class Rank {
|
|
|
233
248
|
}
|
|
234
249
|
|
|
235
250
|
problemStatistics.isSubmitted = true;
|
|
236
|
-
problemStatistics.lastSubmitTimestamp = s.
|
|
251
|
+
problemStatistics.lastSubmitTimestamp = s.timestampToSecond;
|
|
237
252
|
problemStatistics.totalCount++;
|
|
238
253
|
|
|
239
254
|
if (s.isAccepted()) {
|
|
240
255
|
problemStatistics.isSolved = true;
|
|
241
|
-
problemStatistics.solvedTimestamp = s.
|
|
256
|
+
problemStatistics.solvedTimestamp = s.timestampToSecond;
|
|
242
257
|
|
|
243
258
|
problem.statistics.acceptedNum++;
|
|
244
259
|
problem.statistics.attemptedNum += problemStatistics.failedCount + 1;
|
|
@@ -258,7 +273,7 @@ export class Rank {
|
|
|
258
273
|
problem.statistics.lastSolveSubmissions.push(s);
|
|
259
274
|
|
|
260
275
|
team.lastSolvedProblem = problem;
|
|
261
|
-
team.lastSolvedProblemTimestamp = s.
|
|
276
|
+
team.lastSolvedProblemTimestamp = s.timestampToSecond;
|
|
262
277
|
}
|
|
263
278
|
|
|
264
279
|
if (s.isRejected()) {
|
|
@@ -412,7 +427,7 @@ export class Rank {
|
|
|
412
427
|
}
|
|
413
428
|
|
|
414
429
|
return this.submissions.filter(s =>
|
|
415
|
-
s.
|
|
430
|
+
s.timestampToSecond <= this.options.timestamp,
|
|
416
431
|
).sort(Submission.compare);
|
|
417
432
|
}
|
|
418
433
|
|
|
@@ -443,7 +458,7 @@ export class Rank {
|
|
|
443
458
|
|
|
444
459
|
if (s.isAccepted()) {
|
|
445
460
|
problemStatistics.isSolved = true;
|
|
446
|
-
problemStatistics.solvedTimestamp = s.
|
|
461
|
+
problemStatistics.solvedTimestamp = s.timestampToSecond;
|
|
447
462
|
|
|
448
463
|
const b = new Balloon();
|
|
449
464
|
b.team = team;
|
package/src/submission.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Submission as ISubmission, Submissions as ISubmissions } from "@xcpcio/types";
|
|
1
|
+
import type { Submission as ISubmission, Submissions as ISubmissions, TimeUnit } from "@xcpcio/types";
|
|
2
2
|
import { SubmissionStatus } from "@xcpcio/types";
|
|
3
3
|
|
|
4
4
|
import {
|
|
@@ -14,6 +14,10 @@ export class Submission {
|
|
|
14
14
|
teamId: string;
|
|
15
15
|
problemId: string;
|
|
16
16
|
timestamp: number;
|
|
17
|
+
timestampUnit: TimeUnit;
|
|
18
|
+
|
|
19
|
+
time?: number;
|
|
20
|
+
language?: string;
|
|
17
21
|
|
|
18
22
|
status = SubmissionStatus.UNKNOWN;
|
|
19
23
|
isIgnore = false;
|
|
@@ -23,6 +27,7 @@ export class Submission {
|
|
|
23
27
|
this.teamId = "";
|
|
24
28
|
this.problemId = "";
|
|
25
29
|
this.timestamp = 0;
|
|
30
|
+
this.timestampUnit = "second";
|
|
26
31
|
}
|
|
27
32
|
|
|
28
33
|
isAccepted() {
|
|
@@ -42,9 +47,62 @@ export class Submission {
|
|
|
42
47
|
}
|
|
43
48
|
|
|
44
49
|
get timestampToMinute() {
|
|
50
|
+
if (this.timestampUnit === "nanosecond") {
|
|
51
|
+
return Math.floor(this.timestamp / 60 / 1000 / 1000 / 1000);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (this.timestampUnit === "microsecond") {
|
|
55
|
+
return Math.floor(this.timestamp / 60 / 1000 / 1000);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (this.timestampUnit === "millisecond") {
|
|
59
|
+
return Math.floor(this.timestamp / 60 / 1000);
|
|
60
|
+
}
|
|
61
|
+
|
|
45
62
|
return Math.floor(this.timestamp / 60);
|
|
46
63
|
}
|
|
47
64
|
|
|
65
|
+
get timestampToSecond() {
|
|
66
|
+
if (this.timestampUnit === "nanosecond") {
|
|
67
|
+
return Math.floor(this.timestamp / 1000 / 1000 / 1000);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (this.timestampUnit === "microsecond") {
|
|
71
|
+
return Math.floor(this.timestamp / 1000 / 1000);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (this.timestampUnit === "millisecond") {
|
|
75
|
+
return Math.floor(this.timestamp / 1000);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return this.timestamp;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
get timestampDisplayFormatWithSecond(): string {
|
|
82
|
+
const second = this.timestampToSecond;
|
|
83
|
+
|
|
84
|
+
const h = Math.floor(second / 3600);
|
|
85
|
+
const m = Math.floor(second % 3600 / 60);
|
|
86
|
+
const s = second % 60;
|
|
87
|
+
|
|
88
|
+
const f = (x: number) => x.toString().padStart(2, "0");
|
|
89
|
+
|
|
90
|
+
const res = `${f(h)}:${f(m)}:${f(s)}`;
|
|
91
|
+
|
|
92
|
+
return res;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
get timestampDisplayFormatWithMilliSecond(): string {
|
|
96
|
+
let res = this.timestampDisplayFormatWithSecond;
|
|
97
|
+
|
|
98
|
+
if (this.timestampUnit === "millisecond") {
|
|
99
|
+
const fl = (this.timestamp % 1000).toString().padEnd(3, "0");
|
|
100
|
+
res += `.${fl}`;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return res;
|
|
104
|
+
}
|
|
105
|
+
|
|
48
106
|
static compare(lhs: Submission, rhs: Submission): number {
|
|
49
107
|
if (lhs.timestamp !== rhs.timestamp) {
|
|
50
108
|
return lhs.timestamp - rhs.timestamp;
|
|
@@ -76,6 +134,14 @@ export function createSubmission(submissionJSON: ISubmission): Submission {
|
|
|
76
134
|
s.status = stringToSubmissionStatus(submissionJSON.status);
|
|
77
135
|
s.isIgnore = submissionJSON.is_ignore ?? false;
|
|
78
136
|
|
|
137
|
+
if (submissionJSON.time) {
|
|
138
|
+
s.time = submissionJSON.time;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
if (submissionJSON.language) {
|
|
142
|
+
s.language = submissionJSON.language;
|
|
143
|
+
}
|
|
144
|
+
|
|
79
145
|
return s;
|
|
80
146
|
}
|
|
81
147
|
|