@xcpcio/core 0.32.0 → 0.33.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 +36 -13
- package/dist/index.d.ts +6 -3
- package/dist/index.mjs +35 -14
- package/package.json +6 -2
- package/src/balloon.ts +4 -0
- package/src/problem.ts +20 -19
- package/src/rank.ts +2 -2
- package/src/utils/color.ts +19 -0
- package/src/utils/index.ts +1 -0
package/dist/index.cjs
CHANGED
|
@@ -15,6 +15,8 @@ const relativeTime = require('dayjs/plugin/relativeTime');
|
|
|
15
15
|
const _ = require('lodash');
|
|
16
16
|
const XLSX = require('xlsx-js-style');
|
|
17
17
|
const stringWidth = require('string-width');
|
|
18
|
+
const colorDiff = require('color-diff');
|
|
19
|
+
const chroma = require('chroma-js');
|
|
18
20
|
|
|
19
21
|
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e["default"] : e; }
|
|
20
22
|
|
|
@@ -42,6 +44,7 @@ const relativeTime__default = /*#__PURE__*/_interopDefaultLegacy(relativeTime);
|
|
|
42
44
|
const ___default = /*#__PURE__*/_interopDefaultLegacy(_);
|
|
43
45
|
const XLSX__namespace = /*#__PURE__*/_interopNamespace(XLSX);
|
|
44
46
|
const stringWidth__default = /*#__PURE__*/_interopDefaultLegacy(stringWidth);
|
|
47
|
+
const chroma__default = /*#__PURE__*/_interopDefaultLegacy(chroma);
|
|
45
48
|
|
|
46
49
|
function stringToSubmissionStatus(status) {
|
|
47
50
|
status = status.toUpperCase().replace(" ", "_");
|
|
@@ -462,6 +465,21 @@ function calcDirt(attemptedNum, solvedNum) {
|
|
|
462
465
|
return Math.floor((attemptedNum - solvedNum) * 100 / attemptedNum);
|
|
463
466
|
}
|
|
464
467
|
|
|
468
|
+
function getWhiteOrBlackColor(background) {
|
|
469
|
+
const [R, G, B] = chroma__default(background).rgb();
|
|
470
|
+
const color = { R, G, B };
|
|
471
|
+
const palette = [
|
|
472
|
+
{ R: 0, G: 0, B: 0 },
|
|
473
|
+
{ R: 255, G: 255, B: 255 }
|
|
474
|
+
];
|
|
475
|
+
const f = colorDiff.furthest(color, palette);
|
|
476
|
+
if (f.R === 0 && f.G === 0 && f.B === 0) {
|
|
477
|
+
return "#000";
|
|
478
|
+
} else {
|
|
479
|
+
return "#fff";
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
|
|
465
483
|
class ProblemStatistics {
|
|
466
484
|
constructor() {
|
|
467
485
|
this.acceptedNum = 0;
|
|
@@ -496,6 +514,10 @@ class Problem {
|
|
|
496
514
|
this.label = "";
|
|
497
515
|
this.name = "";
|
|
498
516
|
this.statistics = new ProblemStatistics();
|
|
517
|
+
this.balloonColor = {
|
|
518
|
+
background_color: "#a0f0a0",
|
|
519
|
+
color: "#000"
|
|
520
|
+
};
|
|
499
521
|
}
|
|
500
522
|
}
|
|
501
523
|
function createProblem(problemJSON) {
|
|
@@ -505,20 +527,14 @@ function createProblem(problemJSON) {
|
|
|
505
527
|
p.name = problemJSON.name ?? "";
|
|
506
528
|
p.timeLimit = problemJSON.time_limit;
|
|
507
529
|
p.memoryLimit = problemJSON.memory_limit;
|
|
508
|
-
|
|
530
|
+
if (problemJSON.balloon_color) {
|
|
531
|
+
p.balloonColor = ___default.cloneDeep(problemJSON.balloon_color);
|
|
532
|
+
}
|
|
533
|
+
p.balloonColor.color = getWhiteOrBlackColor(p.balloonColor.background_color);
|
|
509
534
|
return p;
|
|
510
535
|
}
|
|
511
536
|
function createProblems(problemsJSON) {
|
|
512
|
-
return problemsJSON.map((pJSON) =>
|
|
513
|
-
const p = new Problem();
|
|
514
|
-
p.id = pJSON.id;
|
|
515
|
-
p.label = pJSON.label;
|
|
516
|
-
p.name = pJSON.name ?? "";
|
|
517
|
-
p.timeLimit = pJSON.time_limit;
|
|
518
|
-
p.memoryLimit = pJSON.memory_limit;
|
|
519
|
-
p.balloonColor = pJSON.balloon_color;
|
|
520
|
-
return p;
|
|
521
|
-
});
|
|
537
|
+
return problemsJSON.map((pJSON) => createProblem(pJSON));
|
|
522
538
|
}
|
|
523
539
|
function createProblemsByProblemIds(problemIds, balloonColors) {
|
|
524
540
|
const problems = problemIds.map((label, index) => {
|
|
@@ -529,9 +545,12 @@ function createProblemsByProblemIds(problemIds, balloonColors) {
|
|
|
529
545
|
});
|
|
530
546
|
if (balloonColors !== void 0 && balloonColors !== null) {
|
|
531
547
|
for (const index in balloonColors) {
|
|
532
|
-
problems[index].balloonColor = balloonColors[index];
|
|
548
|
+
problems[index].balloonColor = ___default.cloneDeep(balloonColors[index]);
|
|
533
549
|
}
|
|
534
550
|
}
|
|
551
|
+
problems.forEach((p) => {
|
|
552
|
+
p.balloonColor.color = getWhiteOrBlackColor(p.balloonColor.background_color);
|
|
553
|
+
});
|
|
535
554
|
return problems;
|
|
536
555
|
}
|
|
537
556
|
class TeamProblemStatistics {
|
|
@@ -871,6 +890,9 @@ class Balloon {
|
|
|
871
890
|
get key() {
|
|
872
891
|
return `balloon-${this.team.id}-${this.problem.id}`;
|
|
873
892
|
}
|
|
893
|
+
static compare(lhs, rhs) {
|
|
894
|
+
return Submission.compare(lhs.submission, rhs.submission);
|
|
895
|
+
}
|
|
874
896
|
}
|
|
875
897
|
|
|
876
898
|
class Group {
|
|
@@ -1190,7 +1212,7 @@ class RankOptions {
|
|
|
1190
1212
|
this.filterOrganizationMap = /* @__PURE__ */ new Map();
|
|
1191
1213
|
this.filterTeams = [];
|
|
1192
1214
|
this.filterTeamMap = /* @__PURE__ */ new Map();
|
|
1193
|
-
this.
|
|
1215
|
+
this.enableAnimatedSubmissions = false;
|
|
1194
1216
|
}
|
|
1195
1217
|
setWidth(width, contest) {
|
|
1196
1218
|
this.width = width;
|
|
@@ -1646,6 +1668,7 @@ exports.createTeams = createTeams;
|
|
|
1646
1668
|
exports.getImageSource = getImageSource;
|
|
1647
1669
|
exports.getTimeDiff = getTimeDiff;
|
|
1648
1670
|
exports.getTimestamp = getTimestamp;
|
|
1671
|
+
exports.getWhiteOrBlackColor = getWhiteOrBlackColor;
|
|
1649
1672
|
exports.isAccepted = isAccepted;
|
|
1650
1673
|
exports.isNotCalculatedPenaltyStatus = isNotCalculatedPenaltyStatus;
|
|
1651
1674
|
exports.isPending = isPending;
|
package/dist/index.d.ts
CHANGED
|
@@ -47,7 +47,7 @@ declare class Problem {
|
|
|
47
47
|
name: string;
|
|
48
48
|
timeLimit?: string;
|
|
49
49
|
memoryLimit?: string;
|
|
50
|
-
balloonColor
|
|
50
|
+
balloonColor: BalloonColor;
|
|
51
51
|
statistics: ProblemStatistics;
|
|
52
52
|
constructor();
|
|
53
53
|
}
|
|
@@ -83,6 +83,8 @@ declare class TeamProblemStatistics {
|
|
|
83
83
|
|
|
84
84
|
declare function calcDirt(attemptedNum: number, solvedNum: number): number;
|
|
85
85
|
|
|
86
|
+
declare function getWhiteOrBlackColor(background: string): "#000" | "#fff";
|
|
87
|
+
|
|
86
88
|
declare function createDayJS(time?: Date | string | number | undefined): dayjs.Dayjs;
|
|
87
89
|
declare function getTimestamp(time: number | dayjs.Dayjs): number;
|
|
88
90
|
declare function getTimeDiff(seconds: number): string;
|
|
@@ -210,6 +212,7 @@ declare class Balloon {
|
|
|
210
212
|
submission: Submission;
|
|
211
213
|
constructor();
|
|
212
214
|
get key(): string;
|
|
215
|
+
static compare(lhs: Balloon, rhs: Balloon): number;
|
|
213
216
|
}
|
|
214
217
|
type Balloons = Array<Balloon>;
|
|
215
218
|
|
|
@@ -227,7 +230,7 @@ declare class RankOptions {
|
|
|
227
230
|
filterOrganizationMap: Map<string, SelectOptionItem>;
|
|
228
231
|
filterTeams: Array<SelectOptionItem>;
|
|
229
232
|
filterTeamMap: Map<string, SelectOptionItem>;
|
|
230
|
-
|
|
233
|
+
enableAnimatedSubmissions: boolean;
|
|
231
234
|
constructor();
|
|
232
235
|
setWidth(width: number, contest: Contest): void;
|
|
233
236
|
disableFilterSubmissionByTimestamp(): void;
|
|
@@ -321,4 +324,4 @@ declare function isRejected(status: SubmissionStatus): boolean;
|
|
|
321
324
|
declare function isPending(status: SubmissionStatus): boolean;
|
|
322
325
|
declare function isNotCalculatedPenaltyStatus(status: SubmissionStatus): boolean;
|
|
323
326
|
|
|
324
|
-
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 };
|
|
327
|
+
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, getWhiteOrBlackColor, isAccepted, isNotCalculatedPenaltyStatus, isPending, isRejected, isValidMedalType, stringToSubmissionStatus };
|
package/dist/index.mjs
CHANGED
|
@@ -12,6 +12,8 @@ import relativeTime from 'dayjs/plugin/relativeTime';
|
|
|
12
12
|
import _ from 'lodash';
|
|
13
13
|
import * as XLSX from 'xlsx-js-style';
|
|
14
14
|
import stringWidth from 'string-width';
|
|
15
|
+
import { furthest } from 'color-diff';
|
|
16
|
+
import chroma from 'chroma-js';
|
|
15
17
|
|
|
16
18
|
function stringToSubmissionStatus(status) {
|
|
17
19
|
status = status.toUpperCase().replace(" ", "_");
|
|
@@ -432,6 +434,21 @@ function calcDirt(attemptedNum, solvedNum) {
|
|
|
432
434
|
return Math.floor((attemptedNum - solvedNum) * 100 / attemptedNum);
|
|
433
435
|
}
|
|
434
436
|
|
|
437
|
+
function getWhiteOrBlackColor(background) {
|
|
438
|
+
const [R, G, B] = chroma(background).rgb();
|
|
439
|
+
const color = { R, G, B };
|
|
440
|
+
const palette = [
|
|
441
|
+
{ R: 0, G: 0, B: 0 },
|
|
442
|
+
{ R: 255, G: 255, B: 255 }
|
|
443
|
+
];
|
|
444
|
+
const f = furthest(color, palette);
|
|
445
|
+
if (f.R === 0 && f.G === 0 && f.B === 0) {
|
|
446
|
+
return "#000";
|
|
447
|
+
} else {
|
|
448
|
+
return "#fff";
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
|
|
435
452
|
class ProblemStatistics {
|
|
436
453
|
constructor() {
|
|
437
454
|
this.acceptedNum = 0;
|
|
@@ -466,6 +483,10 @@ class Problem {
|
|
|
466
483
|
this.label = "";
|
|
467
484
|
this.name = "";
|
|
468
485
|
this.statistics = new ProblemStatistics();
|
|
486
|
+
this.balloonColor = {
|
|
487
|
+
background_color: "#a0f0a0",
|
|
488
|
+
color: "#000"
|
|
489
|
+
};
|
|
469
490
|
}
|
|
470
491
|
}
|
|
471
492
|
function createProblem(problemJSON) {
|
|
@@ -475,20 +496,14 @@ function createProblem(problemJSON) {
|
|
|
475
496
|
p.name = problemJSON.name ?? "";
|
|
476
497
|
p.timeLimit = problemJSON.time_limit;
|
|
477
498
|
p.memoryLimit = problemJSON.memory_limit;
|
|
478
|
-
|
|
499
|
+
if (problemJSON.balloon_color) {
|
|
500
|
+
p.balloonColor = _.cloneDeep(problemJSON.balloon_color);
|
|
501
|
+
}
|
|
502
|
+
p.balloonColor.color = getWhiteOrBlackColor(p.balloonColor.background_color);
|
|
479
503
|
return p;
|
|
480
504
|
}
|
|
481
505
|
function createProblems(problemsJSON) {
|
|
482
|
-
return problemsJSON.map((pJSON) =>
|
|
483
|
-
const p = new Problem();
|
|
484
|
-
p.id = pJSON.id;
|
|
485
|
-
p.label = pJSON.label;
|
|
486
|
-
p.name = pJSON.name ?? "";
|
|
487
|
-
p.timeLimit = pJSON.time_limit;
|
|
488
|
-
p.memoryLimit = pJSON.memory_limit;
|
|
489
|
-
p.balloonColor = pJSON.balloon_color;
|
|
490
|
-
return p;
|
|
491
|
-
});
|
|
506
|
+
return problemsJSON.map((pJSON) => createProblem(pJSON));
|
|
492
507
|
}
|
|
493
508
|
function createProblemsByProblemIds(problemIds, balloonColors) {
|
|
494
509
|
const problems = problemIds.map((label, index) => {
|
|
@@ -499,9 +514,12 @@ function createProblemsByProblemIds(problemIds, balloonColors) {
|
|
|
499
514
|
});
|
|
500
515
|
if (balloonColors !== void 0 && balloonColors !== null) {
|
|
501
516
|
for (const index in balloonColors) {
|
|
502
|
-
problems[index].balloonColor = balloonColors[index];
|
|
517
|
+
problems[index].balloonColor = _.cloneDeep(balloonColors[index]);
|
|
503
518
|
}
|
|
504
519
|
}
|
|
520
|
+
problems.forEach((p) => {
|
|
521
|
+
p.balloonColor.color = getWhiteOrBlackColor(p.balloonColor.background_color);
|
|
522
|
+
});
|
|
505
523
|
return problems;
|
|
506
524
|
}
|
|
507
525
|
class TeamProblemStatistics {
|
|
@@ -841,6 +859,9 @@ class Balloon {
|
|
|
841
859
|
get key() {
|
|
842
860
|
return `balloon-${this.team.id}-${this.problem.id}`;
|
|
843
861
|
}
|
|
862
|
+
static compare(lhs, rhs) {
|
|
863
|
+
return Submission.compare(lhs.submission, rhs.submission);
|
|
864
|
+
}
|
|
844
865
|
}
|
|
845
866
|
|
|
846
867
|
class Group {
|
|
@@ -1160,7 +1181,7 @@ class RankOptions {
|
|
|
1160
1181
|
this.filterOrganizationMap = /* @__PURE__ */ new Map();
|
|
1161
1182
|
this.filterTeams = [];
|
|
1162
1183
|
this.filterTeamMap = /* @__PURE__ */ new Map();
|
|
1163
|
-
this.
|
|
1184
|
+
this.enableAnimatedSubmissions = false;
|
|
1164
1185
|
}
|
|
1165
1186
|
setWidth(width, contest) {
|
|
1166
1187
|
this.width = width;
|
|
@@ -1581,4 +1602,4 @@ class Resolver extends Rank {
|
|
|
1581
1602
|
}
|
|
1582
1603
|
}
|
|
1583
1604
|
|
|
1584
|
-
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 };
|
|
1605
|
+
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, getWhiteOrBlackColor, isAccepted, isNotCalculatedPenaltyStatus, isPending, isRejected, isValidMedalType, stringToSubmissionStatus };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xcpcio/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.33.1",
|
|
4
4
|
"description": "XCPCIO Core",
|
|
5
5
|
"author": "Dup4 <lyuzhi.pan@gmail.com>",
|
|
6
6
|
"license": "MIT",
|
|
@@ -40,14 +40,18 @@
|
|
|
40
40
|
"dist"
|
|
41
41
|
],
|
|
42
42
|
"dependencies": {
|
|
43
|
+
"chroma-js": "^2.4.2",
|
|
44
|
+
"color-diff": "^1.4.0",
|
|
43
45
|
"dayjs": "^1.11.8",
|
|
44
46
|
"lodash": "^4.17.21",
|
|
45
47
|
"string-width": "^6.1.0",
|
|
46
48
|
"xlsx-js-style": "^1.2.0",
|
|
47
|
-
"@xcpcio/types": "0.
|
|
49
|
+
"@xcpcio/types": "0.33.1"
|
|
48
50
|
},
|
|
49
51
|
"devDependencies": {
|
|
50
52
|
"@babel/types": "^7.22.4",
|
|
53
|
+
"@types/chroma-js": "^2.4.2",
|
|
54
|
+
"@types/color-diff": "^1.2.3",
|
|
51
55
|
"@types/lodash": "^4.14.195",
|
|
52
56
|
"@types/node": "^17.0.45",
|
|
53
57
|
"@typescript-eslint/eslint-plugin": "^5.59.9",
|
package/src/balloon.ts
CHANGED
|
@@ -16,6 +16,10 @@ export class Balloon {
|
|
|
16
16
|
get key() {
|
|
17
17
|
return `balloon-${this.team.id}-${this.problem.id}`;
|
|
18
18
|
}
|
|
19
|
+
|
|
20
|
+
static compare(lhs: Balloon, rhs: Balloon): number {
|
|
21
|
+
return Submission.compare(lhs.submission, rhs.submission);
|
|
22
|
+
}
|
|
19
23
|
}
|
|
20
24
|
|
|
21
25
|
export type Balloons = Array<Balloon>;
|
package/src/problem.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
import _ from "lodash";
|
|
2
|
+
|
|
1
3
|
import type { BalloonColor, Problem as IProblem, Problems as IProblems } from "@xcpcio/types";
|
|
2
4
|
|
|
3
5
|
import type { Submissions } from "./submission";
|
|
4
|
-
import { calcDirt } from "./utils";
|
|
6
|
+
import { calcDirt, getWhiteOrBlackColor } from "./utils";
|
|
5
7
|
|
|
6
8
|
export class ProblemStatistics {
|
|
7
9
|
acceptedNum: number;
|
|
@@ -59,7 +61,7 @@ export class Problem {
|
|
|
59
61
|
timeLimit?: string;
|
|
60
62
|
memoryLimit?: string;
|
|
61
63
|
|
|
62
|
-
balloonColor
|
|
64
|
+
balloonColor: BalloonColor;
|
|
63
65
|
|
|
64
66
|
statistics: ProblemStatistics;
|
|
65
67
|
|
|
@@ -70,6 +72,11 @@ export class Problem {
|
|
|
70
72
|
this.name = "";
|
|
71
73
|
|
|
72
74
|
this.statistics = new ProblemStatistics();
|
|
75
|
+
|
|
76
|
+
this.balloonColor = {
|
|
77
|
+
background_color: "#a0f0a0",
|
|
78
|
+
color: "#000",
|
|
79
|
+
};
|
|
73
80
|
}
|
|
74
81
|
}
|
|
75
82
|
|
|
@@ -86,27 +93,17 @@ export function createProblem(problemJSON: IProblem): Problem {
|
|
|
86
93
|
p.timeLimit = problemJSON.time_limit;
|
|
87
94
|
p.memoryLimit = problemJSON.memory_limit;
|
|
88
95
|
|
|
89
|
-
|
|
96
|
+
if (problemJSON.balloon_color) {
|
|
97
|
+
p.balloonColor = _.cloneDeep(problemJSON.balloon_color);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
p.balloonColor.color = getWhiteOrBlackColor(p.balloonColor.background_color as string);
|
|
90
101
|
|
|
91
102
|
return p;
|
|
92
103
|
}
|
|
93
104
|
|
|
94
105
|
export function createProblems(problemsJSON: IProblems): Problems {
|
|
95
|
-
return problemsJSON.map(
|
|
96
|
-
const p = new Problem();
|
|
97
|
-
|
|
98
|
-
p.id = pJSON.id;
|
|
99
|
-
p.label = pJSON.label;
|
|
100
|
-
|
|
101
|
-
p.name = pJSON.name ?? "";
|
|
102
|
-
|
|
103
|
-
p.timeLimit = pJSON.time_limit;
|
|
104
|
-
p.memoryLimit = pJSON.memory_limit;
|
|
105
|
-
|
|
106
|
-
p.balloonColor = pJSON.balloon_color;
|
|
107
|
-
|
|
108
|
-
return p;
|
|
109
|
-
});
|
|
106
|
+
return problemsJSON.map(pJSON => createProblem(pJSON));
|
|
110
107
|
}
|
|
111
108
|
|
|
112
109
|
export function createProblemsByProblemIds(problemIds: string[], balloonColors?: BalloonColor[]): Problems {
|
|
@@ -120,10 +117,14 @@ export function createProblemsByProblemIds(problemIds: string[], balloonColors?:
|
|
|
120
117
|
|
|
121
118
|
if (balloonColors !== undefined && balloonColors !== null) {
|
|
122
119
|
for (const index in balloonColors) {
|
|
123
|
-
problems[index].balloonColor = balloonColors[index];
|
|
120
|
+
problems[index].balloonColor = _.cloneDeep(balloonColors[index]);
|
|
124
121
|
}
|
|
125
122
|
}
|
|
126
123
|
|
|
124
|
+
problems.forEach((p) => {
|
|
125
|
+
p.balloonColor.color = getWhiteOrBlackColor(p.balloonColor.background_color as string);
|
|
126
|
+
});
|
|
127
|
+
|
|
127
128
|
return problems;
|
|
128
129
|
}
|
|
129
130
|
|
package/src/rank.ts
CHANGED
|
@@ -29,7 +29,7 @@ export class RankOptions {
|
|
|
29
29
|
filterTeams: Array<SelectOptionItem>;
|
|
30
30
|
filterTeamMap: Map<string, SelectOptionItem>;
|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
enableAnimatedSubmissions: boolean;
|
|
33
33
|
|
|
34
34
|
constructor() {
|
|
35
35
|
this.enableFilterSubmissionsByTimestamp = false;
|
|
@@ -45,7 +45,7 @@ export class RankOptions {
|
|
|
45
45
|
this.filterTeams = [];
|
|
46
46
|
this.filterTeamMap = new Map<string, SelectOptionItem>();
|
|
47
47
|
|
|
48
|
-
this.
|
|
48
|
+
this.enableAnimatedSubmissions = false;
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
setWidth(width: number, contest: Contest) {
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { furthest } from "color-diff";
|
|
2
|
+
import chroma from "chroma-js";
|
|
3
|
+
|
|
4
|
+
export function getWhiteOrBlackColor(background: string) {
|
|
5
|
+
const [R, G, B] = chroma(background).rgb();
|
|
6
|
+
const color = { R, G, B };
|
|
7
|
+
const palette = [
|
|
8
|
+
{ R: 0, G: 0, B: 0 },
|
|
9
|
+
{ R: 255, G: 255, B: 255 },
|
|
10
|
+
];
|
|
11
|
+
|
|
12
|
+
const f = furthest(color, palette);
|
|
13
|
+
|
|
14
|
+
if (f.R === 0 && f.G === 0 && f.B === 0) {
|
|
15
|
+
return "#000";
|
|
16
|
+
} else {
|
|
17
|
+
return "#fff";
|
|
18
|
+
}
|
|
19
|
+
}
|
package/src/utils/index.ts
CHANGED