@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.
Files changed (36) hide show
  1. package/dist/assets/Board-33697790.js +3 -0
  2. package/dist/assets/Board-95c6af0c.css +1 -0
  3. 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
  4. 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
  5. package/dist/assets/{_...all_-5cef394f.js → _...all_-bf870fe0.js} +1 -1
  6. package/dist/assets/{_name_-526d8339.js → _name_-f5cba217.js} +1 -1
  7. package/dist/assets/{about-cd4f21bd.js → about-abf94800.js} +1 -1
  8. package/dist/assets/{board-1be19815.js → board-b333d178.js} +1 -1
  9. package/dist/assets/{board-layout-b82c69d2.js → board-layout-a5085987.js} +1 -1
  10. package/dist/assets/{headless-b9942007.js → headless-c50b4591.js} +1 -1
  11. package/dist/assets/{home-4af354b3.js → home-dde093aa.js} +1 -1
  12. package/dist/assets/{index-bed92a26.css → index-03c128b2.css} +2 -2
  13. package/dist/assets/{index-5e5a2093.js → index-084a197d.js} +60 -138
  14. package/dist/assets/{index-0ce86bd1.js → index-6999b738.js} +1 -1
  15. package/dist/assets/{index-a020bfea.js → index-dbac5f19.js} +1 -1
  16. package/dist/assets/{index-layout-cb03751a.js → index-layout-bf0bad87.js} +1 -1
  17. package/dist/assets/{test-8c3726ee.js → test-cb214810.js} +1 -1
  18. package/dist/assets/{useQueryBoardData-82598023.js → useQueryBoardData-eb47ec82.js} +1 -1
  19. package/dist/assets/{user-87de2ef4.js → user-203ba27e.js} +1 -1
  20. package/dist/assets/{virtual_pwa-register-f7f8a2da.js → virtual_pwa-register-4551dbd6.js} +1 -1
  21. package/dist/index.html +1 -1
  22. package/dist/sw.js +1 -1
  23. package/package.json +3 -3
  24. package/src/auto-imports.d.ts +6 -0
  25. package/src/components/board/AnimatedSubmissionBlock.vue +85 -0
  26. package/src/components/board/AnimatedSubmissionsModal.vue +79 -76
  27. package/src/components/board/Board.vue +39 -21
  28. package/src/components/board/ProblemBlock.vue +2 -3
  29. package/src/components/board/Progress.vue +2 -2
  30. package/src/components/board/TeamProblemBlock.vue +6 -3
  31. package/src/components.d.ts +1 -0
  32. package/src/composables/color.ts +17 -1
  33. package/src/composables/type.ts +13 -0
  34. package/src/styles/color.css +10 -0
  35. package/dist/assets/Board-8241725a.js +0 -3
  36. 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 = ref(new Date());
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
- const isReBuildRank = ref(false);
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
- if (isReBuildRank.value === true) {
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.startTime.format("YYYY-MM-DD HH:mm:ss");
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.endTime.format("YYYY-MM-DD HH:mm:ss");
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.startTime.format("z") }}</sup>
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
@@ -30,9 +30,8 @@ const balloonColor = computed(() => problem.value.balloonColor);
30
30
  >
31
31
  <div
32
32
  cursor-pointer
33
- flex
34
- flex-col justify-center
35
- items-center
33
+ flex flex-col
34
+ justify-center items-center
36
35
  @click="onClick"
37
36
  >
38
37
  <div>
@@ -117,8 +117,8 @@ function startDrag(event: MouseEvent) {
117
117
  }
118
118
 
119
119
  function getTimeScroll() {
120
- const startTime = props.rank!.contest.startTime;
121
- const endTime = props.rank!.contest.endTime;
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
- {{ getProblemSign(p) }}
84
- <br>
85
- {{ getProblemShow(p) }}
83
+ <div>
84
+ {{ getProblemSign(p) }}
85
+ </div>
86
+ <div>
87
+ {{ getProblemShow(p) }}
88
+ </div>
86
89
  </div>
87
90
 
88
91
  <div>
@@ -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']
@@ -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
+ }
@@ -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
  }