@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 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.timestamp;
1327
+ problemStatistics.lastSubmitTimestamp = s.timestampToSecond;
1267
1328
  problemStatistics.totalCount++;
1268
1329
  if (s.isAccepted()) {
1269
1330
  problemStatistics.isSolved = true;
1270
- problemStatistics.solvedTimestamp = s.timestamp;
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.timestamp;
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.timestamp <= this.options.timestamp
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.timestamp;
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.timestamp;
1297
+ problemStatistics.lastSubmitTimestamp = s.timestampToSecond;
1237
1298
  problemStatistics.totalCount++;
1238
1299
  if (s.isAccepted()) {
1239
1300
  problemStatistics.isSolved = true;
1240
- problemStatistics.solvedTimestamp = s.timestamp;
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.timestamp;
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.timestamp <= this.options.timestamp
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.timestamp;
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.27.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.27.0"
47
+ "@xcpcio/types": "0.28.0"
48
48
  },
49
49
  "devDependencies": {
50
50
  "@babel/types": "^7.22.4",
@@ -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.timestamp;
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.timestamp;
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.timestamp;
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.timestamp <= this.options.timestamp,
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.timestamp;
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