@xcpcio/board-app 0.35.0 → 0.36.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/assets/Board-33697790.js +3 -0
- package/dist/assets/Board-95c6af0c.css +1 -0
- package/dist/assets/{DataSourceInput.vue_vue_type_script_setup_true_lang-b7257fab.js → DataSourceInput.vue_vue_type_script_setup_true_lang-5bb85145.js} +1 -1
- package/dist/assets/{TheInput.vue_vue_type_script_setup_true_lang-fe810a28.js → TheInput.vue_vue_type_script_setup_true_lang-f86a88cd.js} +1 -1
- package/dist/assets/{_...all_-5cef394f.js → _...all_-bf870fe0.js} +1 -1
- package/dist/assets/{_name_-526d8339.js → _name_-f5cba217.js} +1 -1
- package/dist/assets/{about-cd4f21bd.js → about-abf94800.js} +1 -1
- package/dist/assets/{board-1be19815.js → board-b333d178.js} +1 -1
- package/dist/assets/{board-layout-b82c69d2.js → board-layout-a5085987.js} +1 -1
- package/dist/assets/{headless-b9942007.js → headless-c50b4591.js} +1 -1
- package/dist/assets/{home-4af354b3.js → home-dde093aa.js} +1 -1
- package/dist/assets/{index-bed92a26.css → index-03c128b2.css} +2 -2
- package/dist/assets/{index-5e5a2093.js → index-084a197d.js} +60 -138
- package/dist/assets/{index-0ce86bd1.js → index-6999b738.js} +1 -1
- package/dist/assets/{index-a020bfea.js → index-dbac5f19.js} +1 -1
- package/dist/assets/{index-layout-cb03751a.js → index-layout-bf0bad87.js} +1 -1
- package/dist/assets/{test-8c3726ee.js → test-cb214810.js} +1 -1
- package/dist/assets/{useQueryBoardData-82598023.js → useQueryBoardData-eb47ec82.js} +1 -1
- package/dist/assets/{user-87de2ef4.js → user-203ba27e.js} +1 -1
- package/dist/assets/{virtual_pwa-register-f7f8a2da.js → virtual_pwa-register-4551dbd6.js} +1 -1
- package/dist/index.html +1 -1
- package/dist/sw.js +1 -1
- package/package.json +3 -3
- package/src/auto-imports.d.ts +6 -0
- package/src/components/board/AnimatedSubmissionBlock.vue +85 -0
- package/src/components/board/AnimatedSubmissionsModal.vue +79 -76
- package/src/components/board/Board.vue +39 -21
- package/src/components/board/ProblemBlock.vue +2 -3
- package/src/components/board/Progress.vue +2 -2
- package/src/components/board/TeamProblemBlock.vue +6 -3
- package/src/components.d.ts +1 -0
- package/src/composables/color.ts +17 -1
- package/src/composables/type.ts +13 -0
- package/src/styles/color.css +10 -0
- package/dist/assets/Board-8241725a.js +0 -3
- package/dist/assets/Board-fd82c4fe.css +0 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import _ from "lodash";
|
|
3
3
|
import { useRouteQuery } from "@vueuse/router";
|
|
4
|
-
import { onKeyStroke } from "@vueuse/core";
|
|
4
|
+
import { onKeyStroke, useIntervalFn, useNow } from "@vueuse/core";
|
|
5
5
|
|
|
6
6
|
import { Rank, RankOptions, createContest, createSubmissions, createTeams, getTimeDiff } from "@xcpcio/core";
|
|
7
7
|
import type { Contest, Submissions, Teams } from "@xcpcio/core";
|
|
@@ -23,7 +23,7 @@ const contestData = ref({} as Contest);
|
|
|
23
23
|
const teamsData = ref([] as Teams);
|
|
24
24
|
const submissionsData = ref([] as Submissions);
|
|
25
25
|
const rank = ref({} as Rank);
|
|
26
|
-
const now =
|
|
26
|
+
const now = useNow();
|
|
27
27
|
const rankOptions = ref(new RankOptions());
|
|
28
28
|
|
|
29
29
|
const enableAutoScroll = ref(false);
|
|
@@ -60,15 +60,28 @@ function onChangeCurrentGroup(nextGroup: string) {
|
|
|
60
60
|
rankOptions.value.setGroup(currentGroupFromRouteQuery.value);
|
|
61
61
|
})();
|
|
62
62
|
|
|
63
|
+
const replayStartTime = useRouteQuery("replay-start-time", 0, { transform: Number });
|
|
64
|
+
|
|
65
|
+
const isReBuildRank = ref(false);
|
|
63
66
|
function reBuildRank(options = { force: false }) {
|
|
64
67
|
if (enableAutoScroll.value && options.force === false) {
|
|
65
68
|
return;
|
|
66
69
|
}
|
|
67
70
|
|
|
71
|
+
if (isReBuildRank.value === true) {
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
isReBuildRank.value = true;
|
|
76
|
+
|
|
68
77
|
const newRank = new Rank(contestData.value, teamsData.value, submissionsData.value);
|
|
69
78
|
newRank.options = _.cloneDeep(rankOptions.value);
|
|
79
|
+
newRank.setReplayTime(replayStartTime.value);
|
|
80
|
+
|
|
70
81
|
newRank.buildRank();
|
|
71
82
|
rank.value = newRank;
|
|
83
|
+
|
|
84
|
+
isReBuildRank.value = false;
|
|
72
85
|
}
|
|
73
86
|
|
|
74
87
|
const { data, isError, error } = useQueryBoardData(props.dataSourceUrl ?? route.path, now);
|
|
@@ -92,28 +105,38 @@ watch(data, async () => {
|
|
|
92
105
|
firstLoaded.value = true;
|
|
93
106
|
});
|
|
94
107
|
|
|
95
|
-
|
|
96
|
-
watch(rankOptions.value, () => {
|
|
108
|
+
function dynamicReBuildRank() {
|
|
97
109
|
if (firstLoaded.value === false) {
|
|
98
110
|
return;
|
|
99
111
|
}
|
|
100
112
|
|
|
113
|
+
reBuildRank();
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
watch(rankOptions.value, () => {
|
|
101
117
|
if (!rank.value.options.isNeedReBuildRank(rankOptions.value)) {
|
|
102
118
|
rank.value.options = _.cloneDeep(rankOptions.value);
|
|
103
119
|
return;
|
|
104
120
|
}
|
|
105
121
|
|
|
106
|
-
|
|
107
|
-
return;
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
isReBuildRank.value = true;
|
|
111
|
-
|
|
112
|
-
reBuildRank();
|
|
113
|
-
|
|
114
|
-
isReBuildRank.value = false;
|
|
122
|
+
dynamicReBuildRank();
|
|
115
123
|
});
|
|
116
124
|
|
|
125
|
+
{
|
|
126
|
+
const { pause, resume } = useIntervalFn(() => {
|
|
127
|
+
dynamicReBuildRank();
|
|
128
|
+
}, 1000);
|
|
129
|
+
|
|
130
|
+
watch(replayStartTime, () => {
|
|
131
|
+
if (replayStartTime.value === 0) {
|
|
132
|
+
pause();
|
|
133
|
+
} else {
|
|
134
|
+
dynamicReBuildRank();
|
|
135
|
+
resume();
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
|
|
117
140
|
const typeMenuList = ref<Array<Item>>([
|
|
118
141
|
{
|
|
119
142
|
title: "type_menu.rank",
|
|
@@ -231,12 +254,12 @@ onKeyStroke("S", (_e) => {
|
|
|
231
254
|
}, { dedupe: false });
|
|
232
255
|
|
|
233
256
|
const startTime = computed(() => {
|
|
234
|
-
const time = rank.value.contest.
|
|
257
|
+
const time = rank.value.contest.getStartTime().format("YYYY-MM-DD HH:mm:ss");
|
|
235
258
|
return `${t("standings.start_time")}${t("common.colon")}${time}`;
|
|
236
259
|
});
|
|
237
260
|
|
|
238
261
|
const endTime = computed(() => {
|
|
239
|
-
const time = rank.value.contest.
|
|
262
|
+
const time = rank.value.contest.getEndTime().format("YYYY-MM-DD HH:mm:ss");
|
|
240
263
|
return `${t("standings.end_time")}${t("common.colon")}${time}`;
|
|
241
264
|
});
|
|
242
265
|
|
|
@@ -262,12 +285,7 @@ const pausedTime = computed(() => {
|
|
|
262
285
|
return getTimeDiff(rank.value.options.timestamp);
|
|
263
286
|
});
|
|
264
287
|
|
|
265
|
-
const setNowIntervalId = setInterval(() => {
|
|
266
|
-
now.value = new Date();
|
|
267
|
-
}, 1000);
|
|
268
|
-
|
|
269
288
|
onUnmounted(() => {
|
|
270
|
-
clearInterval(setNowIntervalId);
|
|
271
289
|
clearAutoScrollInterval();
|
|
272
290
|
});
|
|
273
291
|
|
|
@@ -340,7 +358,7 @@ const widthClass = "sm:w-[1260px] xl:w-screen";
|
|
|
340
358
|
<div class="w-[92%]">
|
|
341
359
|
<div class="flex font-bold font-mono">
|
|
342
360
|
<div class="float-left">
|
|
343
|
-
{{ startTime }}<sup class="pl-0.5">{{ rank.contest.
|
|
361
|
+
{{ startTime }}<sup class="pl-0.5">{{ rank.contest.getStartTime().format("z") }}</sup>
|
|
344
362
|
</div>
|
|
345
363
|
<div class="flex-1">
|
|
346
364
|
<ContestStateBadge
|
|
@@ -117,8 +117,8 @@ function startDrag(event: MouseEvent) {
|
|
|
117
117
|
}
|
|
118
118
|
|
|
119
119
|
function getTimeScroll() {
|
|
120
|
-
const startTime = props.rank!.contest.
|
|
121
|
-
const endTime = props.rank!.contest.
|
|
120
|
+
const startTime = props.rank!.contest.getStartTime();
|
|
121
|
+
const endTime = props.rank!.contest.getEndTime();
|
|
122
122
|
|
|
123
123
|
const gap = endTime.unix() - startTime.unix();
|
|
124
124
|
const target = Math.floor(gap * barWidth.value * 0.01);
|
|
@@ -80,9 +80,12 @@ function getProblemColorClass(p: TeamProblemStatistics): string {
|
|
|
80
80
|
justify-center items-center
|
|
81
81
|
@click="onClick"
|
|
82
82
|
>
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
83
|
+
<div>
|
|
84
|
+
{{ getProblemSign(p) }}
|
|
85
|
+
</div>
|
|
86
|
+
<div>
|
|
87
|
+
{{ getProblemShow(p) }}
|
|
88
|
+
</div>
|
|
86
89
|
</div>
|
|
87
90
|
|
|
88
91
|
<div>
|
package/src/components.d.ts
CHANGED
|
@@ -7,6 +7,7 @@ export {}
|
|
|
7
7
|
|
|
8
8
|
declare module 'vue' {
|
|
9
9
|
export interface GlobalComponents {
|
|
10
|
+
AnimatedSubmissionBlock: typeof import('./components/board/AnimatedSubmissionBlock.vue')['default']
|
|
10
11
|
AnimatedSubmissionsModal: typeof import('./components/board/AnimatedSubmissionsModal.vue')['default']
|
|
11
12
|
Badge: typeof import('./components/board/Badge.vue')['default']
|
|
12
13
|
Balloon: typeof import('./components/Balloon.vue')['default']
|
package/src/composables/color.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { MedalType } from "@xcpcio/core";
|
|
2
|
-
import type { Team } from "@xcpcio/core";
|
|
2
|
+
import type { Submission, Team } from "@xcpcio/core";
|
|
3
3
|
|
|
4
4
|
export function getMedalColor(team: Team): { backgroundColor: string, color: string } | undefined {
|
|
5
5
|
const color = {
|
|
@@ -29,3 +29,19 @@ export function getMedalColor(team: Team): { backgroundColor: string, color: str
|
|
|
29
29
|
|
|
30
30
|
return undefined;
|
|
31
31
|
}
|
|
32
|
+
|
|
33
|
+
export function getStandingsStatusColor(submission: Submission) {
|
|
34
|
+
if (submission.isFirstSolved) {
|
|
35
|
+
return "#3db03d";
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (submission.isAccepted()) {
|
|
39
|
+
return "#e1ffb5";
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (submission.isPending()) {
|
|
43
|
+
return "#c8d6fa";
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return "#ffd0d0";
|
|
47
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Problem, Submission, Team } from "@xcpcio/core";
|
|
2
|
+
|
|
3
|
+
export interface AnimatedSubmissionBlockItem {
|
|
4
|
+
submission: Submission,
|
|
5
|
+
team: Team,
|
|
6
|
+
problem: Problem,
|
|
7
|
+
displayName: string,
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export enum LastBlockDisplayType {
|
|
11
|
+
SUBMISSION_STATUS,
|
|
12
|
+
SUBMIT_TIMESTAMP,
|
|
13
|
+
}
|
package/src/styles/color.css
CHANGED
|
@@ -23,6 +23,11 @@ html {
|
|
|
23
23
|
--theme-status-unknown: #000;
|
|
24
24
|
--theme-status-undefined: var(--theme-status-unknown);
|
|
25
25
|
|
|
26
|
+
--theme-standings-first-solve: #3db03d;
|
|
27
|
+
--theme-standings-correct: #e1ffb5;
|
|
28
|
+
--theme-standings-incorrect: #ffd0d0;
|
|
29
|
+
--theme-standings-pending: #c8d6fa;
|
|
30
|
+
|
|
26
31
|
--theme-resolver-ac: #5eb95e;
|
|
27
32
|
--theme-resolver-wa: #dd514c;
|
|
28
33
|
--theme-resolver-pending: #607D8B;
|
|
@@ -56,4 +61,9 @@ html.dark {
|
|
|
56
61
|
--theme-status-skipped: #78909C;
|
|
57
62
|
--theme-status-unknown: #fff;
|
|
58
63
|
--theme-status-undefined: var(--theme-status-unknown);
|
|
64
|
+
|
|
65
|
+
--theme-standings-first-solve: #3db03d;
|
|
66
|
+
--theme-standings-correct: #e1ffb5;
|
|
67
|
+
--theme-standings-incorrect: #ffd0d0;
|
|
68
|
+
--theme-standings-pending: #c8d6fa;
|
|
59
69
|
}
|