@xcpcio/board-app 0.31.1 → 0.33.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.
Files changed (46) hide show
  1. package/dist/assets/Board-5815574f.js +3 -0
  2. package/dist/assets/Board-99a6e425.css +1 -0
  3. package/dist/assets/{DataSourceInput.vue_vue_type_script_setup_true_lang-b87eba77.js → DataSourceInput.vue_vue_type_script_setup_true_lang-3a011309.js} +1 -1
  4. package/dist/assets/{TheInput.vue_vue_type_script_setup_true_lang-079f8c80.js → TheInput.vue_vue_type_script_setup_true_lang-c4669f90.js} +1 -1
  5. package/dist/assets/{_...all_-019b03b8.js → _...all_-9575471a.js} +1 -1
  6. package/dist/assets/{_name_-6a3b59a1.js → _name_-c49901a2.js} +1 -1
  7. package/dist/assets/{about-f9061b17.js → about-9ae6988f.js} +1 -1
  8. package/dist/assets/{board-6d208112.js → board-039c3f4a.js} +1 -1
  9. package/dist/assets/{board-layout-5590c53f.js → board-layout-b556ae6f.js} +1 -1
  10. package/dist/assets/{headless-94485ccd.js → headless-c2f93337.js} +1 -1
  11. package/dist/assets/{home-e847177d.js → home-281261c3.js} +1 -1
  12. package/dist/assets/index-39ee8a2c.css +1 -0
  13. package/dist/assets/index-a501b47e.js +1 -0
  14. package/dist/assets/index-b8d0230b.js +338 -0
  15. package/dist/assets/index-ca39a150.js +1 -0
  16. package/dist/assets/{index-d429549a.css → index-e63239d5.css} +1 -1
  17. package/dist/assets/{index-layout-3f26f613.js → index-layout-7e38f172.js} +1 -1
  18. package/dist/assets/{test-24dab276.js → test-b15602ea.js} +1 -1
  19. package/dist/assets/{useQueryBoardData-b6644ecd.js → useQueryBoardData-fc6b78c1.js} +1 -1
  20. package/dist/assets/{user-7a10fa8c.js → user-5cfcf268.js} +1 -1
  21. package/dist/assets/{virtual_pwa-register-41acaeb8.js → virtual_pwa-register-7426d7cc.js} +1 -1
  22. package/dist/index.html +1 -122
  23. package/dist/sw.js +1 -1
  24. package/package.json +4 -3
  25. package/src/auto-imports.d.ts +4 -1
  26. package/src/components/Balloon.vue +2 -2
  27. package/src/components/BalloonBlock.vue +3 -14
  28. package/src/components/Countdown.vue +0 -7
  29. package/src/components/board/AnimatedSubmissionsModal.vue +144 -0
  30. package/src/components/board/Board.vue +17 -8
  31. package/src/components/board/BottomStatistics.vue +2 -2
  32. package/src/components/board/OptionsModal.vue +30 -0
  33. package/src/components/board/ProblemBlock.vue +4 -2
  34. package/src/components/board/SubmissionsTable.vue +2 -4
  35. package/src/components/board/TeamUI.vue +4 -4
  36. package/src/components/board/Utility.vue +15 -15
  37. package/src/components.d.ts +1 -0
  38. package/src/composables/color.ts +31 -0
  39. package/src/styles/submission-status-background.css +123 -0
  40. package/vite.config.ts +16 -0
  41. package/dist/assets/Board-3c31679a.css +0 -1
  42. package/dist/assets/Board-ce0a2c6c.js +0 -3
  43. package/dist/assets/index-3735f4c2.js +0 -1
  44. package/dist/assets/index-4b46c3f4.js +0 -1
  45. package/dist/assets/index-622de38d.css +0 -1
  46. package/dist/assets/index-7a9bcf50.js +0 -205
@@ -38,7 +38,6 @@ declare global {
38
38
  const debouncedWatch: typeof import('@vueuse/core')['debouncedWatch']
39
39
  const defineAsyncComponent: typeof import('vue')['defineAsyncComponent']
40
40
  const defineComponent: typeof import('vue')['defineComponent']
41
- const downloadSingleFile: typeof import('./composables/utils')['downloadSingleFile']
42
41
  const eagerComputed: typeof import('@vueuse/core')['eagerComputed']
43
42
  const effectScope: typeof import('vue')['effectScope']
44
43
  const extendRef: typeof import('@vueuse/core')['extendRef']
@@ -47,10 +46,12 @@ declare global {
47
46
  const getDataSourceUrl: typeof import('./composables/query')['getDataSourceUrl']
48
47
  const getLocalStorageKeyForFilterOrganizations: typeof import('./composables/useLocalStorage')['getLocalStorageKeyForFilterOrganizations']
49
48
  const getLocalStorageKeyForFilterTeams: typeof import('./composables/useLocalStorage')['getLocalStorageKeyForFilterTeams']
49
+ const getMedalColor: typeof import('./composables/color')['getMedalColor']
50
50
  const getProblemChart: typeof import('./composables/statistics')['getProblemChart']
51
51
  const getSubmitChart: typeof import('./composables/statistics')['getSubmitChart']
52
52
  const getTeamChart: typeof import('./composables/statistics')['getTeamChart']
53
53
  const getTeamPlaceChart: typeof import('./composables/statistics')['getTeamPlaceChart']
54
+ const getWhiteOrBlackColor: typeof import('./composables/color')['getWhiteOrBlackColor']
54
55
  const h: typeof import('vue')['h']
55
56
  const ignorableWatch: typeof import('@vueuse/core')['ignorableWatch']
56
57
  const inject: typeof import('vue')['inject']
@@ -357,6 +358,7 @@ declare module 'vue' {
357
358
  readonly getDataSourceUrl: UnwrapRef<typeof import('./composables/query')['getDataSourceUrl']>
358
359
  readonly getLocalStorageKeyForFilterOrganizations: UnwrapRef<typeof import('./composables/useLocalStorage')['getLocalStorageKeyForFilterOrganizations']>
359
360
  readonly getLocalStorageKeyForFilterTeams: UnwrapRef<typeof import('./composables/useLocalStorage')['getLocalStorageKeyForFilterTeams']>
361
+ readonly getMedalColor: UnwrapRef<typeof import('./composables/color')['getMedalColor']>
360
362
  readonly getProblemChart: UnwrapRef<typeof import('./composables/statistics')['getProblemChart']>
361
363
  readonly getSubmitChart: UnwrapRef<typeof import('./composables/statistics')['getSubmitChart']>
362
364
  readonly getTeamChart: UnwrapRef<typeof import('./composables/statistics')['getTeamChart']>
@@ -658,6 +660,7 @@ declare module '@vue/runtime-core' {
658
660
  readonly getDataSourceUrl: UnwrapRef<typeof import('./composables/query')['getDataSourceUrl']>
659
661
  readonly getLocalStorageKeyForFilterOrganizations: UnwrapRef<typeof import('./composables/useLocalStorage')['getLocalStorageKeyForFilterOrganizations']>
660
662
  readonly getLocalStorageKeyForFilterTeams: UnwrapRef<typeof import('./composables/useLocalStorage')['getLocalStorageKeyForFilterTeams']>
663
+ readonly getMedalColor: UnwrapRef<typeof import('./composables/color')['getMedalColor']>
661
664
  readonly getProblemChart: UnwrapRef<typeof import('./composables/statistics')['getProblemChart']>
662
665
  readonly getSubmitChart: UnwrapRef<typeof import('./composables/statistics')['getSubmitChart']>
663
666
  readonly getTeamChart: UnwrapRef<typeof import('./composables/statistics')['getTeamChart']>
@@ -1,5 +1,5 @@
1
1
  <script setup lang="ts">
2
- import { Rank, createContest, createSubmissions, createTeams } from "@xcpcio/core";
2
+ import { Balloon, Rank, createContest, createSubmissions, createTeams } from "@xcpcio/core";
3
3
  import type { Contest, Submissions, Teams } from "@xcpcio/core";
4
4
  import type { Contest as IContest, Submissions as ISubmissions, Teams as ITeams } from "@xcpcio/types";
5
5
 
@@ -43,7 +43,7 @@ watch(data, async () => {
43
43
  });
44
44
 
45
45
  const balloons = computed(() => {
46
- return rank.value.balloons;
46
+ return rank.value.balloons.sort(Balloon.compare).reverse().slice(0, 256);
47
47
  });
48
48
 
49
49
  const setNowIntervalId = setInterval(() => {
@@ -1,6 +1,5 @@
1
1
  <script setup lang="ts">
2
2
  import type { Balloon, Team } from "@xcpcio/core";
3
- import type { ThemeColor } from "@xcpcio/types";
4
3
 
5
4
  const props = defineProps<{
6
5
  index: number;
@@ -18,17 +17,7 @@ function showTeamName(team: Team) {
18
17
  return sections.filter(s => s).join(" - ");
19
18
  }
20
19
 
21
- function getColor(c: ThemeColor): string {
22
- if (typeof c === "string") {
23
- return c;
24
- }
25
-
26
- if (isDark && c?.dark) {
27
- return c.dark;
28
- }
29
-
30
- return c.light;
31
- }
20
+ const balloonColor = computed(() => balloon.value.problem.balloonColor);
32
21
  </script>
33
22
 
34
23
  <template>
@@ -47,12 +36,12 @@ function getColor(c: ThemeColor): string {
47
36
  w-20
48
37
  flex flex-shrink-0 justify-center items-center
49
38
  :style="{
50
- backgroundColor: getColor(balloon.problem?.balloonColor?.background_color ?? 'rgba(0, 0, 0, 0.5)'),
39
+ backgroundColor: balloonColor.background_color,
51
40
  }"
52
41
  >
53
42
  <div
54
43
  :style="{
55
- color: getColor(balloon.problem?.balloonColor?.color ?? '#fff'),
44
+ color: balloonColor.color,
56
45
  }"
57
46
  >
58
47
  {{ balloon.problem.label }}
@@ -68,13 +68,6 @@ onUnmounted(() => {
68
68
  items-center justify-center
69
69
  font-mono
70
70
  >
71
- <div
72
- mt-20
73
- text-5xl
74
- >
75
- {{ contest.name }}
76
- </div>
77
-
78
71
  <div
79
72
  mt-20
80
73
  text-6xl
@@ -0,0 +1,144 @@
1
+ <script setup lang="ts">
2
+ import type { Problem, Rank, Team } from "@xcpcio/core";
3
+ import { Submission } from "@xcpcio/core";
4
+ import { SubmissionStatusToSimpleString } from "@xcpcio/types";
5
+
6
+ import { getMedalColor } from "~/composables/color";
7
+
8
+ const props = defineProps<{
9
+ rank: Rank,
10
+ }>();
11
+
12
+ interface Item {
13
+ submission: Submission,
14
+ team: Team,
15
+ problem: Problem,
16
+ displayName: string,
17
+ }
18
+
19
+ const rank = computed(() => props.rank);
20
+ const submissions = computed(() => {
21
+ const ss = rank.value.getSubmissions().sort(Submission.compare).reverse();
22
+
23
+ const res: Item[] = [];
24
+
25
+ let cnt = 0;
26
+ const need = 16;
27
+ for (let i = 0; i < ss.length && cnt < need; i++) {
28
+ const s = ss[i];
29
+ const teamId = s.teamId;
30
+ const problemId = s.problemId;
31
+
32
+ const team = rank.value.teamsMap.get(teamId);
33
+
34
+ if (!team) {
35
+ continue;
36
+ }
37
+
38
+ if (rank.value.filterTeamByOrg(team)) {
39
+ continue;
40
+ }
41
+
42
+ const problem = rank.value.contest.problemsMap.get(problemId);
43
+ if (!problem) {
44
+ continue;
45
+ }
46
+
47
+ let displayName = team.name;
48
+
49
+ if (team.organization) {
50
+ displayName = `${team.organization} - ${displayName}`;
51
+ }
52
+
53
+ res.push({
54
+ submission: s,
55
+ team,
56
+ problem,
57
+ displayName,
58
+ });
59
+
60
+ ++cnt;
61
+ }
62
+
63
+ return res.reverse();
64
+ });
65
+ </script>
66
+
67
+ <template>
68
+ <div
69
+ absolute fixed z-99
70
+ bottom-4 left-4
71
+ opacity-90
72
+ >
73
+ <div
74
+ flex flex-col
75
+ >
76
+ <div>
77
+ <template
78
+ v-for="s in submissions"
79
+ :key="s.id"
80
+ >
81
+ <div
82
+ w-104
83
+ h-6
84
+ bg-slate-800 text-gray-200
85
+ font-mono
86
+ flex flex-row
87
+ justify-center items-center
88
+ >
89
+ <div
90
+ w-10
91
+ :style="getMedalColor(s.team)"
92
+ flex
93
+ justify-center items-center
94
+ >
95
+ <div>
96
+ {{ s.team.rank }}
97
+ </div>
98
+ </div>
99
+
100
+ <div
101
+ pl-1
102
+ w-80
103
+ truncate
104
+ >
105
+ {{ s.displayName }}
106
+ </div>
107
+
108
+ <div
109
+ w-5
110
+ >
111
+ {{ s.team.solvedProblemNum }}
112
+ </div>
113
+
114
+ <div
115
+ w-8
116
+ border-b-4
117
+ flex justify-center
118
+ :style="{
119
+ borderColor: s.problem.balloonColor.background_color,
120
+ }"
121
+ >
122
+ {{ s.problem.label }}
123
+ </div>
124
+
125
+ <div
126
+ w-10
127
+ flex justify-center
128
+ :class="[s.submission.status]"
129
+ :style="{
130
+ color: '#000',
131
+ }"
132
+ >
133
+ {{ SubmissionStatusToSimpleString[s.submission.status] }}
134
+ </div>
135
+ </div>
136
+ </template>
137
+ </div>
138
+ </div>
139
+ </div>
140
+ </template>
141
+
142
+ <style scoped lang="less">
143
+ @import "../../styles/submission-status-background.css";
144
+ </style>
@@ -280,7 +280,8 @@ const widthClass = "sm:w-[1260px] xl:w-screen";
280
280
  <div v-if="!firstLoaded">
281
281
  <div
282
282
  :class="[wrapperWidthClass]"
283
- flex flex-col gap-4 justify-center items-center
283
+ flex flex-col gap-4
284
+ justify-center items-center
284
285
  >
285
286
  <div>
286
287
  {{ t("common.loading") }}...
@@ -457,14 +458,22 @@ const widthClass = "sm:w-[1260px] xl:w-screen";
457
458
  </div>
458
459
  </div>
459
460
  </div>
460
- </div>
461
461
 
462
- <OptionsModal
463
- v-if="!isHiddenOptionsModal"
464
- v-model:is-hidden="isHiddenOptionsModal"
465
- v-model:rank-options="rankOptions"
466
- :rank="rank"
467
- />
462
+ <div
463
+ v-if="rankOptions.enableAnimatedSubmissions"
464
+ >
465
+ <AnimatedSubmissionsModal
466
+ :rank="rank"
467
+ />
468
+ </div>
469
+
470
+ <OptionsModal
471
+ v-if="!isHiddenOptionsModal"
472
+ v-model:is-hidden="isHiddenOptionsModal"
473
+ v-model:rank-options="rankOptions"
474
+ :rank="rank"
475
+ />
476
+ </div>
468
477
  </div>
469
478
  </template>
470
479
 
@@ -54,7 +54,7 @@ function getFirstSolved(p: ProblemStatistics): string {
54
54
  return "Null";
55
55
  }
56
56
 
57
- const t = Math.floor(p.firstSolveSubmissions[0].timestamp / 60);
57
+ const t = p.firstSolveSubmissions[0].timestampToMinute;
58
58
  return `${t}`;
59
59
  }
60
60
 
@@ -63,7 +63,7 @@ function getLastSolved(p: ProblemStatistics): string {
63
63
  return "Null";
64
64
  }
65
65
 
66
- const t = Math.floor(p.lastSolveSubmissions[0].timestamp / 60);
66
+ const t = p.lastSolveSubmissions[0].timestampToMinute;
67
67
  return `${t}`;
68
68
  }
69
69
  </script>
@@ -40,6 +40,8 @@ const title = computed(() => {
40
40
  return t("type_menu.options");
41
41
  });
42
42
 
43
+ const enableAnimatedSubmissions = ref(rankOptions.value.enableAnimatedSubmissions);
44
+
43
45
  const orgOptions = computed(() => {
44
46
  const res = rank.value.organizations.map((o) => {
45
47
  return {
@@ -93,6 +95,8 @@ function onConfirm() {
93
95
  localStorage.setItem(localStorageKeyForFilterOrganizations, JSON.stringify(orgSelectedItems.value));
94
96
  localStorage.setItem(localStorageKeyForFilterTeams, JSON.stringify(teamsSelectedItems.value));
95
97
 
98
+ rankOptions.value.enableAnimatedSubmissions = enableAnimatedSubmissions.value;
99
+
96
100
  onCancel();
97
101
  }
98
102
  </script>
@@ -150,6 +154,32 @@ function onConfirm() {
150
154
  </div>
151
155
  </div>
152
156
 
157
+ <div
158
+ flex flex-col
159
+ w-full
160
+ >
161
+ <div
162
+ flex
163
+ mb-2
164
+ >
165
+ Feature
166
+ </div>
167
+
168
+ <div
169
+ flex flex-row
170
+ >
171
+ <label class="relative inline-flex items-center cursor-pointer">
172
+ <input
173
+ v-model="enableAnimatedSubmissions"
174
+ type="checkbox"
175
+ class="sr-only peer"
176
+ >
177
+ <div class="w-11 h-6 bg-gray-200 peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-blue-300 dark:peer-focus:ring-blue-800 rounded-full peer dark:bg-gray-700 peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all dark:border-gray-600 peer-checked:bg-blue-600" />
178
+ <span class="ml-3 text-sm font-medium text-gray-900 dark:text-gray-300">Animated Submissions</span>
179
+ </label>
180
+ </div>
181
+ </div>
182
+
153
183
  <div
154
184
  mt-2
155
185
  w-full
@@ -13,6 +13,8 @@ function onClick() {
13
13
 
14
14
  const rank = computed(() => props.rank);
15
15
  const problem = computed(() => props.problem);
16
+
17
+ const balloonColor = computed(() => problem.value.balloonColor);
16
18
  </script>
17
19
 
18
20
  <template>
@@ -22,8 +24,8 @@ const problem = computed(() => props.problem);
22
24
  text-center
23
25
  style="width: 3rem;"
24
26
  :style="{
25
- 'background-color': problem.balloonColor?.background_color,
26
- 'color': problem.balloonColor?.color,
27
+ 'background-color': balloonColor.background_color,
28
+ 'color': balloonColor.color,
27
29
  }"
28
30
  >
29
31
  <div
@@ -244,11 +244,9 @@ function getProblemLabelColorStyle(s: Submission) {
244
244
  return undefined;
245
245
  }
246
246
 
247
- const b = p.balloonColor;
248
-
249
247
  return {
250
- backgroundColor: b.background_color as string,
251
- color: b.color as string,
248
+ backgroundColor: p.balloonColor.background_color,
249
+ color: p.balloonColor.color,
252
250
  };
253
251
  }
254
252
  </script>
@@ -21,10 +21,6 @@ const rank = computed(() => props.rank);
21
21
  const team = computed(() => props.team);
22
22
 
23
23
  function getStandClassName(t: Team, isRankField = false): string {
24
- if (props.isFilter) {
25
- return "filter-team";
26
- }
27
-
28
24
  if (isRankField) {
29
25
  if (t.awards.includes(MedalType.GOLD)) {
30
26
  return "gold";
@@ -43,6 +39,10 @@ function getStandClassName(t: Team, isRankField = false): string {
43
39
  }
44
40
  }
45
41
 
42
+ if (props.isFilter) {
43
+ return "filter-team";
44
+ }
45
+
46
46
  const solvedProblemIndex = (rank.value.rankStatistics.getTeamSolvedNumIndex(t.solvedProblemNum) - 1) % 2;
47
47
  const rankIndex = (t.rank - 1) % 2;
48
48
 
@@ -26,15 +26,6 @@ function goCountdown() {
26
26
  w-full
27
27
  flex mt-4 gap-4
28
28
  >
29
- <a
30
- btn
31
- :href="resolverUrl"
32
- target="_blank"
33
- title="Resolver"
34
- >
35
- {{ t("type_menu.resolver") }}
36
- </a>
37
-
38
29
  <button
39
30
  btn
40
31
  title="Balloon"
@@ -45,10 +36,10 @@ function goCountdown() {
45
36
 
46
37
  <button
47
38
  btn
48
- title="Countdown"
49
- @click="goCountdown"
39
+ title="Submissions"
40
+ disabled="true"
50
41
  >
51
- {{ t('type_menu.countdown') }}
42
+ {{ t('type_menu.submissions') }}
52
43
  </button>
53
44
  </div>
54
45
 
@@ -56,12 +47,21 @@ function goCountdown() {
56
47
  w-full
57
48
  flex mt-4 gap-4
58
49
  >
50
+ <a
51
+ btn
52
+ :href="resolverUrl"
53
+ target="_blank"
54
+ title="Resolver"
55
+ >
56
+ {{ t("type_menu.resolver") }}
57
+ </a>
58
+
59
59
  <button
60
60
  btn
61
- title="Submissions"
62
- disabled="true"
61
+ title="Countdown"
62
+ @click="goCountdown"
63
63
  >
64
- {{ t('type_menu.submissions') }}
64
+ {{ t('type_menu.countdown') }}
65
65
  </button>
66
66
  </div>
67
67
  </template>
@@ -7,6 +7,7 @@ export {}
7
7
 
8
8
  declare module 'vue' {
9
9
  export interface GlobalComponents {
10
+ AnimatedSubmissionsModal: typeof import('./components/board/AnimatedSubmissionsModal.vue')['default']
10
11
  Badge: typeof import('./components/board/Badge.vue')['default']
11
12
  Balloon: typeof import('./components/Balloon.vue')['default']
12
13
  BalloonBlock: typeof import('./components/BalloonBlock.vue')['default']
@@ -0,0 +1,31 @@
1
+ import { MedalType } from "@xcpcio/core";
2
+ import type { Team } from "@xcpcio/core";
3
+
4
+ export function getMedalColor(team: Team): { backgroundColor: string, color: string } | undefined {
5
+ const color = {
6
+ backgroundColor: "#fff",
7
+ color: "#000",
8
+ };
9
+
10
+ if (team.awards.includes(MedalType.GOLD)) {
11
+ color.backgroundColor = "#fff566";
12
+ return color;
13
+ }
14
+
15
+ if (team.awards.includes(MedalType.SILVER)) {
16
+ color.backgroundColor = "#ffadd2";
17
+ return color;
18
+ }
19
+
20
+ if (team.awards.includes(MedalType.BRONZE)) {
21
+ color.backgroundColor = "#f0c0a0";
22
+ return color;
23
+ }
24
+
25
+ if (team.awards.includes(MedalType.HONORABLE)) {
26
+ color.backgroundColor = "#e6f7ff";
27
+ return color;
28
+ }
29
+
30
+ return undefined;
31
+ }
@@ -0,0 +1,123 @@
1
+ .PENDING {
2
+ background-color: var(--theme-status-pending);
3
+ }
4
+
5
+ .WAITING {
6
+ background-color: var(--theme-status-waiting);
7
+ }
8
+
9
+ .PREPARING {
10
+ background-color: var(--theme-status-preparing);
11
+ }
12
+
13
+ .COMPILING {
14
+ background-color: var(--theme-status-compiling);
15
+ }
16
+
17
+ .RUNNING {
18
+ background-color: var(--theme-status-running);
19
+ }
20
+
21
+ .JUDGING {
22
+ background-color: var(--theme-status-running);
23
+ }
24
+
25
+ .FROZEN {
26
+ background-color: var(--theme-status-pending);
27
+ }
28
+
29
+
30
+ .ACCEPTED {
31
+ background-color: var(--theme-status-accepted);
32
+ }
33
+
34
+ .CORRECT {
35
+ background-color: var(--theme-status-accepted);
36
+ }
37
+
38
+ .PARTIALLY_CORRECT {
39
+ background-color: var(--theme-status-partially-correct);
40
+ }
41
+
42
+
43
+ .REJECTED {
44
+ background-color: var(--theme-status-wrong-answer);
45
+ }
46
+
47
+ .WRONG_ANSWER {
48
+ background-color: var(--theme-status-wrong-answer);
49
+ }
50
+
51
+
52
+ .COMPILATION_ERROR {
53
+ background-color: var(--theme-status-compilation-error);
54
+ }
55
+
56
+ .PRESENTATION_ERROR {
57
+ background-color: var(--theme-status-compilation-error);
58
+ }
59
+
60
+
61
+ .RUNTIME_ERROR {
62
+ background-color: var(--theme-status-runtime-error);
63
+ }
64
+
65
+ .TIME_LIMIT_EXCEEDED {
66
+ background-color: var(--theme-status-time-limit-exceeded);
67
+ }
68
+
69
+ .MEMORY_LIMIT_EXCEEDED {
70
+ background-color: var(--theme-status-memory-limit-exceeded);
71
+ }
72
+
73
+ .OUTPUT_LIMIT_EXCEEDED {
74
+ background-color: var(--theme-status-output-limit-exceeded);
75
+ }
76
+
77
+ .IDLENESS_LIMIT_EXCEEDED {
78
+ background-color: var(--theme-status-output-limit-exceeded);
79
+ }
80
+
81
+ .HACKED {
82
+ background-color: var(--theme-status-wrong-answer);
83
+ }
84
+
85
+ .JUDGEMENT_FAILED {
86
+ background-color: var(--theme-status-judgement-failed);
87
+ }
88
+
89
+ .CONFIGURATION_ERROR {
90
+ background-color: var(--theme-status-configuration-error);
91
+ }
92
+
93
+ .FILE_ERROR {
94
+ background-color: var(--theme-status-file-error);
95
+ }
96
+
97
+ .SYSTEM_ERROR {
98
+ background-color: var(--theme-status-system-error);
99
+ }
100
+
101
+ .CANCELED {
102
+ background-color: var(--theme-status-canceled);
103
+ }
104
+
105
+ .SKIPPED {
106
+ background-color: var(--theme-status-skipped);
107
+ }
108
+
109
+ .SECURITY_VIOLATED {
110
+ background-color: var(--theme-status-judgement-failed);
111
+ }
112
+
113
+ .DENIAL_OF_JUDGEMENT {
114
+ background-color: var(--theme-status-judgement-failed);
115
+ }
116
+
117
+ .UNKNOWN {
118
+ background-color: var(--theme-status-unknown);
119
+ }
120
+
121
+ .UNDEFINED {
122
+ background-color: var(--theme-status-undefined);
123
+ }
package/vite.config.ts CHANGED
@@ -16,6 +16,7 @@ import Unocss from "unocss/vite";
16
16
  import Shiki from "markdown-it-shiki";
17
17
  import VueMacros from "unplugin-vue-macros/vite";
18
18
  import WebfontDownload from "vite-plugin-webfont-dl";
19
+ import { createHtmlPlugin } from "vite-plugin-html";
19
20
 
20
21
  import packageJSON from "./package.json";
21
22
 
@@ -138,6 +139,21 @@ export default defineConfig({
138
139
 
139
140
  // https://github.com/webfansplz/vite-plugin-vue-devtools
140
141
  VueDevTools(),
142
+
143
+ // https://github.com/vbenjs/vite-plugin-html
144
+ createHtmlPlugin({
145
+ minify: {
146
+ collapseWhitespace: true,
147
+ keepClosingSlash: true,
148
+ removeComments: true,
149
+ removeRedundantAttributes: true,
150
+ removeScriptTypeAttributes: true,
151
+ removeStyleLinkTypeAttributes: true,
152
+ useShortDoctype: true,
153
+ minifyCSS: true,
154
+ minifyJS: true,
155
+ },
156
+ }),
141
157
  ],
142
158
 
143
159
  // https://github.com/vitest-dev/vitest