@xcpcio/board-app 0.67.0 → 0.69.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 (74) hide show
  1. package/dist/404.html +1 -1
  2. package/dist/assets/Balloon.vue_vue_type_script_setup_true_lang-Sj-cL614.js +1 -0
  3. package/dist/assets/{Board-3MaXb78m.js → Board-C0zJhHEW.js} +53 -53
  4. package/dist/assets/{Board-G4heBgt6.css → Board-C89Lc-cb.css} +1 -1
  5. package/dist/assets/ContestStateBadge-Ca1yQNIp.js +1 -0
  6. package/dist/assets/{ContestStateBadge-BqhxSQpe.css → ContestStateBadge-D6uf8wH-.css} +1 -1
  7. package/dist/assets/Countdown-ZQg-bBRY.js +1 -0
  8. package/dist/assets/DataSourceInput.vue_vue_type_script_setup_true_lang-C6HL3fY0.js +1 -0
  9. package/dist/assets/{Footer-Bg_bSWjB.js → Footer-CAomb6my.js} +1 -1
  10. package/dist/assets/{NavBar-cB_AhYzY.js → NavBar-Do8RKB2v.js} +1 -1
  11. package/dist/assets/{Resolver-CcJz6DBo.js → Resolver-BPB9h7gc.js} +1 -1
  12. package/dist/assets/{RightArrowIcon-DaCeCqSH.js → RightArrowIcon-DuOWMa-n.js} +1 -1
  13. package/dist/assets/{TheInput.vue_vue_type_script_setup_true_lang-B8H-RmO4.js → TheInput.vue_vue_type_script_setup_true_lang-ZjoJkW08.js} +1 -1
  14. package/dist/assets/{Tooltip.vue_vue_type_script_setup_true_lang-CrvtqC16.js → Tooltip.vue_vue_type_script_setup_true_lang-BbIuQhDK.js} +1 -1
  15. package/dist/assets/_...all_-CiMTFS4S.js +6 -0
  16. package/dist/assets/_...all_-Dnc7hEh8.js +1 -0
  17. package/dist/assets/{_name_-DjTA6573.js → _name_-kvDcY7mv.js} +1 -1
  18. package/dist/assets/{about-jasx0wKW.js → about-I0_zdVBr.js} +1 -1
  19. package/dist/assets/board-DleCXIV-.js +1 -0
  20. package/dist/assets/{board-layout-DPzrecxe.js → board-layout-DdpeYwD9.js} +1 -1
  21. package/dist/assets/constant-Cm3DZI7p.js +1 -0
  22. package/dist/assets/{dayjs-ErfWoYIs.js → dayjs-BXuNiorQ.js} +1 -1
  23. package/dist/assets/{default-Dn8tKbdq.js → default-BspNxIYy.js} +1 -1
  24. package/dist/assets/{headless-CRpCRK1t.js → headless-BFnXywBl.js} +1 -1
  25. package/dist/assets/{home-CQBa08cQ.js → home-C5PTLQV1.js} +1 -1
  26. package/dist/assets/index-B8VDZSd7.js +1 -0
  27. package/dist/assets/{index-D1ZL4-kn.js → index-B_CylyiQ.js} +1 -1
  28. package/dist/assets/{index-BhjhJlKm.js → index-C-qbv-8J.js} +4 -4
  29. package/dist/assets/index-C8l06iUk.js +1 -0
  30. package/dist/assets/index-CSCaWMnm.js +1 -0
  31. package/dist/assets/{index-layout-D5b_XfR0.js → index-layout-B6cy-Dj6.js} +1 -1
  32. package/dist/assets/{index-k7I8Lr2-.js → index-m4ABc5Ia.js} +2 -2
  33. package/dist/assets/{pagination-R1BztuTi.js → pagination-DIZIRNnQ.js} +1 -1
  34. package/dist/assets/{person-C-v09Xnw.js → person-DejsqD_x.js} +1 -1
  35. package/dist/assets/query-CNUp1Nzk.js +39 -0
  36. package/dist/assets/rank-DnkB7_S5.js +1 -0
  37. package/dist/assets/{test-e-qOmGRY.js → test-BR_eu1W9.js} +1 -1
  38. package/dist/assets/{use-vmodel-B41hlwAY.js → use-vmodel-BkR1prci.js} +1 -1
  39. package/dist/assets/useQueryBoardData-B69wI8AO.js +1 -0
  40. package/dist/assets/{user-Ht_z1r54.js → user-BPyN6UOY.js} +1 -1
  41. package/dist/assets/{virtual_pwa-register-ddBGe6v9.js → virtual_pwa-register-izUz_SWx.js} +1 -1
  42. package/dist/index.html +1 -1
  43. package/dist/sw.js +1 -1
  44. package/package.json +3 -3
  45. package/src/auto-imports.d.ts +19 -4
  46. package/src/components/CustomBalloon.vue +1 -3
  47. package/src/components/CustomBoard.vue +1 -3
  48. package/src/components/CustomCountdown.vue +1 -3
  49. package/src/components/CustomResolver.vue +1 -3
  50. package/src/components/DataSourceInput.vue +1 -3
  51. package/src/components/board/Board.vue +5 -20
  52. package/src/components/board/OptionsModal.vue +1 -1
  53. package/src/components/board/Progress.vue +1 -2
  54. package/src/components/board/SecondLevelMenu.vue +1 -2
  55. package/src/components/board/Utility.vue +1 -2
  56. package/src/composables/query.ts +46 -6
  57. package/src/composables/rating.ts +6 -2
  58. package/src/composables/useRouteQueryWithoutParam.ts +157 -0
  59. package/src/pages/[...all].vue +1 -7
  60. package/src/pages/index.vue +1 -2
  61. package/dist/assets/Balloon.vue_vue_type_script_setup_true_lang-DfFF1Ks0.js +0 -1
  62. package/dist/assets/ContestStateBadge-Dx5wEApj.js +0 -1
  63. package/dist/assets/Countdown-Bl6KQRW4.js +0 -1
  64. package/dist/assets/DataSourceInput.vue_vue_type_script_setup_true_lang-DHdSK4c6.js +0 -1
  65. package/dist/assets/_...all_-CT8hHVGU.js +0 -6
  66. package/dist/assets/_...all_-DZI0_2zk.js +0 -1
  67. package/dist/assets/board-WB70DN-I.js +0 -1
  68. package/dist/assets/constant-zXGoeSUs.js +0 -1
  69. package/dist/assets/contest-BrTkYMuZ.js +0 -39
  70. package/dist/assets/index-D2yB4w8u.js +0 -1
  71. package/dist/assets/index-DePS8wRD.js +0 -1
  72. package/dist/assets/index-DrRCpPOR.js +0 -1
  73. package/dist/assets/query-Ci5JHK5f.js +0 -1
  74. package/dist/assets/rank-CzDyEdMa.js +0 -1
@@ -53,7 +53,6 @@ declare global {
53
53
  const getCurrentInstance: typeof import('vue')['getCurrentInstance']
54
54
  const getCurrentScope: typeof import('vue')['getCurrentScope']
55
55
  const getCurrentWatcher: typeof import('vue')['getCurrentWatcher']
56
- const getDataSourceUrl: typeof import('./composables/query')['getDataSourceUrl']
57
56
  const getLocalStorageKeyForFilterOrganizations: typeof import('./composables/useLocalStorage')['getLocalStorageKeyForFilterOrganizations']
58
57
  const getLocalStorageKeyForFilterTeams: typeof import('./composables/useLocalStorage')['getLocalStorageKeyForFilterTeams']
59
58
  const getMedalColor: typeof import('./composables/color')['getMedalColor']
@@ -260,11 +259,18 @@ declare global {
260
259
  const usePreferredReducedTransparency: typeof import('@vueuse/core')['usePreferredReducedTransparency']
261
260
  const usePrevious: typeof import('@vueuse/core')['usePrevious']
262
261
  const useQueryBoardData: typeof import('./composables/useQueryBoardData')['useQueryBoardData']
262
+ const useQueryForBattleOfGiants: typeof import('./composables/query')['useQueryForBattleOfGiants']
263
+ const useQueryForComponent: typeof import('./composables/query')['useQueryForComponent']
264
+ const useQueryForDataSourceUrl: typeof import('./composables/query')['useQueryForDataSourceUrl']
265
+ const useQueryForGroup: typeof import('./composables/query')['useQueryForGroup']
266
+ const useQueryForProgressRatio: typeof import('./composables/query')['useQueryForProgressRatio']
267
+ const useQueryForReplayStartTime: typeof import('./composables/query')['useQueryForReplayStartTime']
268
+ const useQueryForSearch: typeof import('./composables/query')['useQueryForSearch']
263
269
  const useRafFn: typeof import('@vueuse/core')['useRafFn']
264
270
  const useRefHistory: typeof import('@vueuse/core')['useRefHistory']
265
271
  const useResizeObserver: typeof import('@vueuse/core')['useResizeObserver']
266
272
  const useRoute: typeof import('vue-router')['useRoute']
267
- const useRouteQueryForBattleOfGiants: typeof import('./composables/query')['useRouteQueryForBattleOfGiants']
273
+ const useRouteQueryWithoutParam: typeof import('./composables/useRouteQueryWithoutParam')['useRouteQueryWithoutParam']
268
274
  const useRouter: typeof import('vue-router')['useRouter']
269
275
  const useSSRWidth: typeof import('@vueuse/core')['useSSRWidth']
270
276
  const useScreenOrientation: typeof import('@vueuse/core')['useScreenOrientation']
@@ -353,6 +359,9 @@ declare global {
353
359
  // @ts-ignore
354
360
  export type { BoardData } from './composables/useQueryBoardData'
355
361
  import('./composables/useQueryBoardData')
362
+ // @ts-ignore
363
+ export type { RouteQueryValueRaw, RouteHashValueRaw, ReactiveRouteOptions, ReactiveRouteOptionsWithTransform } from './composables/useRouteQueryWithoutParam'
364
+ import('./composables/useRouteQueryWithoutParam')
356
365
  }
357
366
 
358
367
  // for vue template auto import
@@ -407,7 +416,6 @@ declare module 'vue' {
407
416
  readonly getCurrentInstance: UnwrapRef<typeof import('vue')['getCurrentInstance']>
408
417
  readonly getCurrentScope: UnwrapRef<typeof import('vue')['getCurrentScope']>
409
418
  readonly getCurrentWatcher: UnwrapRef<typeof import('vue')['getCurrentWatcher']>
410
- readonly getDataSourceUrl: UnwrapRef<typeof import('./composables/query')['getDataSourceUrl']>
411
419
  readonly getLocalStorageKeyForFilterOrganizations: UnwrapRef<typeof import('./composables/useLocalStorage')['getLocalStorageKeyForFilterOrganizations']>
412
420
  readonly getLocalStorageKeyForFilterTeams: UnwrapRef<typeof import('./composables/useLocalStorage')['getLocalStorageKeyForFilterTeams']>
413
421
  readonly getMedalColor: UnwrapRef<typeof import('./composables/color')['getMedalColor']>
@@ -614,11 +622,18 @@ declare module 'vue' {
614
622
  readonly usePreferredReducedTransparency: UnwrapRef<typeof import('@vueuse/core')['usePreferredReducedTransparency']>
615
623
  readonly usePrevious: UnwrapRef<typeof import('@vueuse/core')['usePrevious']>
616
624
  readonly useQueryBoardData: UnwrapRef<typeof import('./composables/useQueryBoardData')['useQueryBoardData']>
625
+ readonly useQueryForBattleOfGiants: UnwrapRef<typeof import('./composables/query')['useQueryForBattleOfGiants']>
626
+ readonly useQueryForComponent: UnwrapRef<typeof import('./composables/query')['useQueryForComponent']>
627
+ readonly useQueryForDataSourceUrl: UnwrapRef<typeof import('./composables/query')['useQueryForDataSourceUrl']>
628
+ readonly useQueryForGroup: UnwrapRef<typeof import('./composables/query')['useQueryForGroup']>
629
+ readonly useQueryForProgressRatio: UnwrapRef<typeof import('./composables/query')['useQueryForProgressRatio']>
630
+ readonly useQueryForReplayStartTime: UnwrapRef<typeof import('./composables/query')['useQueryForReplayStartTime']>
631
+ readonly useQueryForSearch: UnwrapRef<typeof import('./composables/query')['useQueryForSearch']>
617
632
  readonly useRafFn: UnwrapRef<typeof import('@vueuse/core')['useRafFn']>
618
633
  readonly useRefHistory: UnwrapRef<typeof import('@vueuse/core')['useRefHistory']>
619
634
  readonly useResizeObserver: UnwrapRef<typeof import('@vueuse/core')['useResizeObserver']>
620
635
  readonly useRoute: UnwrapRef<typeof import('vue-router')['useRoute']>
621
- readonly useRouteQueryForBattleOfGiants: UnwrapRef<typeof import('./composables/query')['useRouteQueryForBattleOfGiants']>
636
+ readonly useRouteQueryWithoutParam: UnwrapRef<typeof import('./composables/useRouteQueryWithoutParam')['useRouteQueryWithoutParam']>
622
637
  readonly useRouter: UnwrapRef<typeof import('vue-router')['useRouter']>
623
638
  readonly useSSRWidth: UnwrapRef<typeof import('@vueuse/core')['useSSRWidth']>
624
639
  readonly useScreenOrientation: UnwrapRef<typeof import('@vueuse/core')['useScreenOrientation']>
@@ -1,7 +1,5 @@
1
1
  <script setup lang="ts">
2
- import { getDataSourceUrl } from "@board/composables/query";
3
-
4
- const dataSourceUrl = getDataSourceUrl();
2
+ const dataSourceUrl = useQueryForDataSourceUrl();
5
3
  </script>
6
4
 
7
5
  <template>
@@ -1,7 +1,5 @@
1
1
  <script setup lang="ts">
2
- import { getDataSourceUrl } from "@board/composables/query";
3
-
4
- const dataSourceUrl = getDataSourceUrl();
2
+ const dataSourceUrl = useQueryForDataSourceUrl();
5
3
  </script>
6
4
 
7
5
  <template>
@@ -1,7 +1,5 @@
1
1
  <script setup lang="ts">
2
- import { getDataSourceUrl } from "@board/composables/query";
3
-
4
- const dataSourceUrl = getDataSourceUrl();
2
+ const dataSourceUrl = useQueryForDataSourceUrl();
5
3
  </script>
6
4
 
7
5
  <template>
@@ -1,7 +1,5 @@
1
1
  <script setup lang="ts">
2
- import { getDataSourceUrl } from "@board/composables/query";
3
-
4
- const dataSourceUrl = getDataSourceUrl();
2
+ const dataSourceUrl = useQueryForDataSourceUrl();
5
3
  </script>
6
4
 
7
5
  <template>
@@ -1,9 +1,7 @@
1
1
  <script setup lang="ts">
2
- import { getDataSourceUrl } from "@board/composables/query";
3
-
4
2
  const { t } = useI18n();
5
3
 
6
- const dataSourceUrl = getDataSourceUrl();
4
+ const dataSourceUrl = useQueryForDataSourceUrl();
7
5
  const dataSourceUrlText = "Data Source URL";
8
6
  const dataSourceUrlInput = ref(dataSourceUrl.value);
9
7
 
@@ -3,12 +3,6 @@ import type { Item } from "@board/components/board/SecondLevelMenu.vue";
3
3
  import type { Contest, Submissions, Teams } from "@xcpcio/core";
4
4
  import type { Contest as IContest, Submissions as ISubmissions, Teams as ITeams, Lang } from "@xcpcio/types";
5
5
 
6
- import FilterModal from "@board/components/board/FilterModal.vue";
7
-
8
- import { TITLE_SUFFIX } from "@board/composables/constant";
9
- import { onKeyStroke, useDocumentVisibility, useIntervalFn, useNow } from "@vueuse/core";
10
-
11
- import { useRouteQuery } from "@vueuse/router";
12
6
  import { createContest, createSubmissions, createTeams, getImageSource, getTimeDiff, Rank, RankOptions } from "@xcpcio/core";
13
7
  import { ContestState } from "@xcpcio/types";
14
8
 
@@ -34,10 +28,6 @@ const contestName = ref("");
34
28
 
35
29
  const enableAutoScroll = ref(false);
36
30
 
37
- function fixPath(path: string) {
38
- return path.replaceAll("%2F", "/");
39
- }
40
-
41
31
  (() => {
42
32
  const filterOrganizations = useLocalStorageForFilterOrganizations();
43
33
  const filterTeams = useLocalStorageForFilterTeams();
@@ -52,7 +42,7 @@ function fixPath(path: string) {
52
42
  })();
53
43
 
54
44
  (() => {
55
- const routeQueryForBattleOfGiants = useRouteQueryForBattleOfGiants();
45
+ const routeQueryForBattleOfGiants = useQueryForBattleOfGiants();
56
46
  if (
57
47
  routeQueryForBattleOfGiants.value !== null
58
48
  && routeQueryForBattleOfGiants.value !== undefined
@@ -70,17 +60,12 @@ function onChangeCurrentGroup(nextGroup: string) {
70
60
  rankOptions.value.setGroup(nextGroup);
71
61
  }
72
62
  (() => {
73
- const currentGroupFromRouteQuery = useRouteQuery(
74
- /* name */ "group",
75
- /* defaultValue */ "all",
76
- { transform: String },
77
- );
78
-
63
+ const currentGroupFromRouteQuery = useQueryForGroup();
79
64
  currentGroup.value = currentGroupFromRouteQuery.value;
80
65
  rankOptions.value.setGroup(currentGroupFromRouteQuery.value);
81
66
  })();
82
67
 
83
- const replayStartTime = useRouteQuery("replay-start-time", 0, { transform: Number });
68
+ const replayStartTime = useQueryForReplayStartTime();
84
69
 
85
70
  const isReBuildRank = ref(false);
86
71
  function reBuildRank(options = { force: false }) {
@@ -109,7 +94,7 @@ function updateContestName() {
109
94
  title.value = `${contestName.value} | ${TITLE_SUFFIX}`;
110
95
  }
111
96
 
112
- const { data, isError, error, refetch } = useQueryBoardData(props.dataSourceUrl ?? fixPath(route.path), now);
97
+ const { data, isError, error, refetch } = useQueryBoardData(props.dataSourceUrl ?? route.path, now);
113
98
  watch(data, async () => {
114
99
  if (data.value === null || data.value === undefined) {
115
100
  return;
@@ -420,7 +405,7 @@ const widthClass = "sm:w-[1260px] xl:w-screen";
420
405
  >
421
406
  <div class="max-w-[92%]">
422
407
  <img
423
- :src="getImageSource(rank.contest.banner, `${DATA_HOST}${fixPath(route.path).slice(1)}`)"
408
+ :src="getImageSource(rank.contest.banner, `${DATA_HOST}${route.path.slice(1)}`)"
424
409
  class="w-screen"
425
410
  alt="banner"
426
411
  >
@@ -66,7 +66,7 @@ const teamsOptions = computed(() => {
66
66
  return res;
67
67
  });
68
68
 
69
- const routeQueryForBattleOfGiants = useRouteQueryForBattleOfGiants();
69
+ const routeQueryForBattleOfGiants = useQueryForBattleOfGiants();
70
70
  function persistBattleOfGiants() {
71
71
  if (rankOptions.value.battleOfGiants.persist) {
72
72
  routeQueryForBattleOfGiants.value = rankOptions.value.battleOfGiants.ToBase64();
@@ -1,6 +1,5 @@
1
1
  <script setup lang="ts">
2
2
  import type { Rank, RankOptions } from "@xcpcio/core";
3
- import { useRouteQuery } from "@vueuse/router";
4
3
  import { createDayJS, getTimeDiff } from "@xcpcio/core";
5
4
  import { ContestState } from "@xcpcio/types";
6
5
 
@@ -44,7 +43,7 @@ const isDragging = ref(false);
44
43
  const dragWidth = ref(0);
45
44
  const barWidth = ref(props.width);
46
45
  const barWidthPX = ref(0);
47
- const progressRatio = useRouteQuery("progress-ratio", -1, { transform: Number });
46
+ const progressRatio = useQueryForProgressRatio();
48
47
 
49
48
  const scroll = ref<HTMLElement>(null as unknown as HTMLElement);
50
49
  const mask = ref<HTMLElement>(null as unknown as HTMLElement);
@@ -1,7 +1,6 @@
1
1
  <script setup lang="ts">
2
2
  import type { I18nText } from "@xcpcio/core";
3
3
  import type { Lang } from "@xcpcio/types";
4
- import { useRouteQuery } from "@vueuse/router";
5
4
 
6
5
  export interface Item {
7
6
  title: string | I18nText;
@@ -33,7 +32,7 @@ const defaultType = computed(() => {
33
32
  return props.items?.[0].keyword;
34
33
  });
35
34
 
36
- const currentItemFromRouteQuery = useRouteQuery(
35
+ const currentItemFromRouteQuery = useRouteQueryWithoutParam(
37
36
  props.queryParamName,
38
37
  defaultType.value,
39
38
  { transform: String },
@@ -1,6 +1,5 @@
1
1
  <script setup lang="ts">
2
2
  import type { Rank } from "@xcpcio/core";
3
- import { useRouteQuery } from "@vueuse/router";
4
3
 
5
4
  const props = defineProps<{
6
5
  rank: Rank;
@@ -10,7 +9,7 @@ const { t } = useI18n();
10
9
 
11
10
  const route = useRoute();
12
11
  const router = useRouter();
13
- const component = useRouteQuery("component", "board", { transform: String });
12
+ const component = useQueryForComponent();
14
13
 
15
14
  function goResolver() {
16
15
  if (window.DATA_SOURCE) {
@@ -1,17 +1,57 @@
1
- import { useRouteQuery } from "@vueuse/router";
1
+ import { useRouteQueryWithoutParam } from "./useRouteQueryWithoutParam";
2
2
 
3
- export function getDataSourceUrl() {
4
- return useRouteQuery(
5
- "data-source",
3
+ export function useQueryForSearch() {
4
+ return useRouteQueryWithoutParam(
5
+ "s",
6
6
  "",
7
7
  { transform: String },
8
8
  );
9
9
  }
10
10
 
11
- export function useRouteQueryForBattleOfGiants() {
12
- return useRouteQuery(
11
+ export function useQueryForDataSourceUrl() {
12
+ return useRouteQueryWithoutParam(
13
+ "data-source-url",
14
+ "",
15
+ { transform: String },
16
+ );
17
+ }
18
+
19
+ export function useQueryForGroup() {
20
+ return useRouteQueryWithoutParam(
21
+ "group",
22
+ "all",
23
+ { transform: String },
24
+ );
25
+ }
26
+
27
+ export function useQueryForReplayStartTime() {
28
+ return useRouteQueryWithoutParam(
29
+ "replay-start-time",
30
+ "0",
31
+ { transform: Number },
32
+ );
33
+ }
34
+
35
+ export function useQueryForProgressRatio() {
36
+ return useRouteQueryWithoutParam(
37
+ "progress-ratio",
38
+ -1,
39
+ { transform: Number },
40
+ );
41
+ }
42
+
43
+ export function useQueryForBattleOfGiants() {
44
+ return useRouteQueryWithoutParam(
13
45
  "battle-of-giants",
14
46
  "",
15
47
  { transform: String },
16
48
  );
17
49
  }
50
+
51
+ export function useQueryForComponent() {
52
+ return useRouteQueryWithoutParam(
53
+ "component",
54
+ "board",
55
+ { transform: String },
56
+ );
57
+ }
@@ -1,4 +1,5 @@
1
1
  import type { RatingUser } from "@xcpcio/core";
2
+ import type { Lang } from "@xcpcio/types";
2
3
  import { RatingLevelToString, RatingUtility } from "@xcpcio/core";
3
4
 
4
5
  interface RatingGraphData {
@@ -27,6 +28,9 @@ export function getRatingGraphOptions(
27
28
  ) {
28
29
  const data: RatingGraphData[] = [];
29
30
 
31
+ const { locale } = useI18n();
32
+ const lang = locale.value as unknown as Lang;
33
+
30
34
  {
31
35
  let oldRating = 0;
32
36
  for (const h of ratingUser.ratingHistories) {
@@ -35,10 +39,10 @@ export function getRatingGraphOptions(
35
39
  d.y = h.rating;
36
40
  d.diffRating = getDiffRating(oldRating, h.rating);
37
41
  d.rank = h.rank;
38
- d.contestName = h.contestName;
42
+ d.contestName = h.contestName.getOrDefault(lang);
39
43
  d.link = `/board/${h.contestID}`;
40
44
  d.contestTime = h.contestTime.format("YYYY-MM-DD HH:mm:ss");
41
- d.teamName = h.teamName;
45
+ d.teamName = h.teamName.getOrDefault(lang);
42
46
  d.ratingTitle = RatingLevelToString[RatingUtility.getRatingLevel(h.rating)];
43
47
  data.push(d);
44
48
 
@@ -0,0 +1,157 @@
1
+ import type { MaybeRef, MaybeRefOrGetter, Ref } from "vue";
2
+ import type { RouteParamValueRaw, Router } from "vue-router";
3
+ import { tryOnScopeDispose } from "@vueuse/core";
4
+ import { customRef, nextTick, toValue, watch } from "vue";
5
+ import { useRoute, useRouter } from "vue-router";
6
+
7
+ const _queue = new WeakMap<Router, Map<string, any>>();
8
+
9
+ export type RouteQueryValueRaw = RouteParamValueRaw | string[];
10
+
11
+ export type RouteHashValueRaw = string | null | undefined;
12
+
13
+ export interface ReactiveRouteOptions {
14
+ /**
15
+ * Mode to update the router query, ref is also acceptable
16
+ *
17
+ * @default 'replace'
18
+ */
19
+ mode?: MaybeRef<"replace" | "push">;
20
+
21
+ /**
22
+ * Route instance, use `useRoute()` if not given
23
+ */
24
+ route?: ReturnType<typeof useRoute>;
25
+
26
+ /**
27
+ * Router instance, use `useRouter()` if not given
28
+ */
29
+ router?: ReturnType<typeof useRouter>;
30
+ }
31
+
32
+ export interface ReactiveRouteOptionsWithTransform<V, R> extends ReactiveRouteOptions {
33
+ /**
34
+ * Function to transform data before return, or an object with one or both functions:
35
+ * `get` to transform data before returning, and `set` to transform data before setting
36
+ */
37
+ transform?:
38
+ | ((val: V) => R)
39
+ | ({
40
+ get?: (value: V) => R;
41
+ set?: (value: R) => V;
42
+ });
43
+ }
44
+
45
+ export function useRouteQueryWithoutParam(
46
+ name: string
47
+ ): Ref<undefined | null | string | string[]>;
48
+
49
+ export function useRouteQueryWithoutParam<
50
+ T extends RouteQueryValueRaw = RouteQueryValueRaw,
51
+ K = T,
52
+ >(
53
+ name: string,
54
+ defaultValue?: MaybeRefOrGetter<T>,
55
+ options?: ReactiveRouteOptionsWithTransform<T, K>
56
+ ): Ref<K>;
57
+
58
+ export function useRouteQueryWithoutParam<
59
+ T extends RouteQueryValueRaw = RouteQueryValueRaw,
60
+ K = T,
61
+ >(
62
+ name: string,
63
+ defaultValue?: MaybeRefOrGetter<T>,
64
+ options: ReactiveRouteOptionsWithTransform<T, K> = {},
65
+ ): Ref<K> {
66
+ const {
67
+ mode = "replace",
68
+ route = useRoute(),
69
+ router = useRouter(),
70
+ transform,
71
+ } = options;
72
+
73
+ let transformGet = (value: T) => value as unknown as K;
74
+ let transformSet = (value: K) => value as unknown as T;
75
+
76
+ if (typeof transform === "function") {
77
+ transformGet = transform;
78
+ } else if (transform) {
79
+ if (transform.get) {
80
+ transformGet = transform.get;
81
+ }
82
+ if (transform.set) {
83
+ transformSet = transform.set;
84
+ }
85
+ }
86
+
87
+ if (!_queue.has(router)) {
88
+ _queue.set(router, new Map());
89
+ }
90
+
91
+ const _queriesQueue = _queue.get(router)!;
92
+
93
+ let query = route.query[name] as any;
94
+
95
+ tryOnScopeDispose(() => {
96
+ query = undefined;
97
+ });
98
+
99
+ let _trigger: () => void;
100
+
101
+ const proxy = customRef<any>((track, trigger) => {
102
+ _trigger = trigger;
103
+
104
+ return {
105
+ get() {
106
+ track();
107
+
108
+ return transformGet(query !== undefined ? query : toValue(defaultValue));
109
+ },
110
+ set(v) {
111
+ v = transformSet(v);
112
+
113
+ if (query === v) {
114
+ return;
115
+ }
116
+
117
+ query = (v === toValue(defaultValue)) ? undefined : v;
118
+ _queriesQueue.set(name, (v === toValue(defaultValue)) ? undefined : v);
119
+
120
+ trigger();
121
+
122
+ nextTick(() => {
123
+ if (_queriesQueue.size === 0) {
124
+ return;
125
+ }
126
+
127
+ const newQueries = Object.fromEntries(_queriesQueue.entries());
128
+ _queriesQueue.clear();
129
+
130
+ const { path, query, hash } = route;
131
+
132
+ router[toValue(mode)]({
133
+ path, // replace params with path could fix %2F
134
+ query: { ...query, ...newQueries },
135
+ hash,
136
+ });
137
+ });
138
+ },
139
+ };
140
+ });
141
+
142
+ watch(
143
+ () => route.query[name],
144
+ (v) => {
145
+ if (query === transformGet(v as T)) {
146
+ return;
147
+ }
148
+
149
+ query = v;
150
+
151
+ _trigger();
152
+ },
153
+ { flush: "sync" },
154
+ );
155
+
156
+ return proxy as Ref<K>;
157
+ }
@@ -1,6 +1,4 @@
1
1
  <script setup lang="ts">
2
- import { useRouteQuery } from "@vueuse/router";
3
-
4
2
  const { t } = useI18n();
5
3
  const route = useRoute();
6
4
 
@@ -12,11 +10,7 @@ const contestTypes = [
12
10
  ];
13
11
 
14
12
  const isNotFound = !contestTypes.some(c => route.fullPath.startsWith(`/${c}`));
15
- const component = useRouteQuery(
16
- "component",
17
- "board",
18
- { transform: String },
19
- );
13
+ const component = useQueryForComponent();
20
14
  const dataSource = window.DATA_SOURCE;
21
15
  </script>
22
16
 
@@ -7,7 +7,6 @@ import SearchInput from "@board/components/SearchInput.vue";
7
7
  import { TITLE_SUFFIX } from "@board/composables/constant";
8
8
 
9
9
  import { useFetch } from "@vueuse/core";
10
- import { useRouteQuery } from "@vueuse/router";
11
10
  import { createContestIndexList } from "@xcpcio/core";
12
11
 
13
12
  const { t, locale } = useI18n();
@@ -24,7 +23,7 @@ function genURL() {
24
23
  }
25
24
  const url = ref(genURL());
26
25
 
27
- const s = useRouteQuery<string | null>("s", "", { transform: String });
26
+ const s = useQueryForSearch();
28
27
  const searchText = ref<string | null>(s.value);
29
28
  const searchInputRef = ref<InstanceType<typeof SearchInput> | null>(null);
30
29
 
@@ -1 +0,0 @@
1
- import{d as w,f as _,m as i,p as D,c as n,o as s,q as g,h as e,n as E,b as o,K as h,k as d,A as L,u as N,C as F,F as V,E as z,G as I,s as R}from"./index-BhjhJlKm.js";import{B}from"./constant-zXGoeSUs.js";import{c as U,a as A,B as O,R as q}from"./rank-CzDyEdMa.js";import{c as G}from"./contest-BrTkYMuZ.js";import{u as K}from"./query-Ci5JHK5f.js";const M={flex:"","flex-1":"","flex-col":"","justify-center":"","items-start":""},Q={class:"resolver-team-name",truncate:"","overflow-hidden":""},X={"w-32":"",flex:"","flex-shrink-0":"","flex-row":"","justify-start":"","items-center":""},H=w({__name:"BalloonBlock",props:{index:null,balloon:null},setup(x){const f=x,p=_(()=>f.index),l=_(()=>f.balloon),c=i(null),a=D(c);function v(t){return[t.location,t.organization,t.name].filter(b=>b).join(" - ")}const u=_(()=>l.value.problem.balloonColor);return(t,m)=>(s(),n("div",{ref_key:"el",ref:c,"h-24":""},[e(a)?(s(),n("div",{key:0,"h-24":"",flex:"","flex-row":"","gap-x-4":"","font-mono":"","text-4xl":"",class:E([e(p)%2===0?"bg-resolver-bg-0":"bg-resolver-bg-1"])},[o("div",{"w-20":"",flex:"","flex-shrink-0":"","justify-center":"","items-center":"",style:h({backgroundColor:e(u).background_color})},[o("div",{style:h({color:e(u).color})},d(e(l).problem.label),5)],4),o("div",M,[o("div",Q,d(v(e(l).team)),1),m[0]||(m[0]=o("div",{flex:"","flex-row":"","text-sm":"","items-start":"","gap-x-2":""},null,-1))]),o("div",X,d(e(l).submission.timestampToMinute),1)],2)):g("",!0)],512))}}),J={class:"bg-[#323443]","text-gray-200":"","w-screen":"","h-screen":""},P={key:0},W={flex:"","flex-col":"","justify-center":"","items-center":"","w-screen":"","h-screen":"","text-xl":"",italic:""},Y={key:0},Z={key:1},ee={flex:"","flex-col":"","justify-between":""},re=w({__name:"Balloon",props:{dataSourceUrl:null},setup(x){const f=x,p=L(B),{t:l}=N(),c=i(!1),a=i({}),v=i([]),u=i([]),t=i({}),m=R();function b(){const k=new q(a.value,v.value,u.value);k.buildBalloons(),t.value=k}const{data:r,isError:C,error:j}=K(f.dataSourceUrl,m);F(r,async()=>{r.value===null||r.value===void 0||(a.value=G(r.value?.contest),p.value=`${a.value.name} | ${B}`,v.value=U(r.value?.teams),u.value=A(r.value?.submissions,a.value),b(),c.value=!0)},{immediate:!0});const S=_(()=>t.value.balloons.sort(O.compare).reverse().slice(0,256));return(k,oe)=>{const T=H;return s(),n("div",J,[e(c)?(s(),n("div",Z,[o("div",ee,[(s(!0),n(V,null,z(e(S),(y,$)=>(s(),I(T,{key:y.key,index:$,balloon:y},null,8,["index","balloon"]))),128))])])):(s(),n("div",P,[o("div",W,[o("div",null,d(e(l)("common.loading"))+"... ",1),e(C)?(s(),n("div",Y,d(e(j)),1)):g("",!0)])]))])}}});export{re as _};
@@ -1 +0,0 @@
1
- import{a as u,u as V}from"./contest-BrTkYMuZ.js";import{d as C,f as P,m as r,V as A,D as G,c as v,o as g,b as c,K as N,n as D,h as x,q as E,F as X,k}from"./index-BhjhJlKm.js";import{c as j,g as q}from"./dayjs-ErfWoYIs.js";import{_ as F}from"./_plugin-vue_export-helper-DlAUqK2U.js";function ae(s,e){return s?.url?!e||s.url.startsWith("http")?s.url:`${e}/${s.url}`:s?.base64?`data:image/${s.type??"png"};base64,${s.base64}`:""}const H=C({__name:"Progress",props:{width:null,state:null,needScroll:{type:Boolean},rank:null,rankOptions:null,elapsedTime:null},emits:["update:rank-options"],setup(s,{emit:e}){const t=s,I=e,h=P({get(){return t.rankOptions},set(l){I("update:rank-options",l)}}),M=P(()=>{switch(t.state){case u.PENDING:return"am-progress-bar-secondary";case u.RUNNING:return"am-progress-bar-success";case u.FROZEN:return"am-progress-bar-danger";case u.FINISHED:return"am-progress-bar-primary";case u.PAUSED:return"am-progress-bar-danger"}return""}),n=r(!1),S=r(!1),m=r(0),_=r(t.width),T=r(0),d=V("progress-ratio",-1,{transform:Number}),o=r(null),L=r(null),p=r(null),W=r(null),R=r(null);function U(l){S.value=!0;const f=l.clientX-p.value.offsetLeft,b=w=>{if(!S.value)return;n.value=!0;let a=w.clientX-f;a=Math.max(a,0),a=Math.min(a,o.value.offsetWidth-p.value.offsetWidth);const B=o.value.offsetWidth*Number.parseInt(L.value.style?.width)*.01;a>=B&&(a=B,n.value=!1);let i=0;a>0&&(i=Math.round((a+p.value.offsetWidth)/o.value.offsetWidth*1e4)),i>1e4&&(i=1e4),i===1e4&&(n.value=!1),window.getSelection()?.removeAllRanges(),m.value=i,T.value=a,_.value=i*.01},y=()=>{document.removeEventListener("mouseup",y),document.removeEventListener("mousemove",b),S.value=!1,n.value===!0?(d.value=m.value,h.value?.setWidth(m.value,t.rank.contest)):(d.value=void 0,h.value?.disableFilterSubmissionByTimestamp())};document.addEventListener("mousemove",b),document.addEventListener("mouseup",y)}function z(){const l=t.rank.contest.getStartTime(),f=t.rank.contest.getEndTime(),b=f.unix()-l.unix(),y=Math.floor(b*_.value*.01),w=j(),a=Math.max(0,Math.min(w.unix(),f.unix())-l.unix());return q(Math.min(y,a))}function O(){return n.value===!0?z():t.elapsedTime}function $(){return n.value===!0?`${Math.max(0,T.value)}px`:`max(calc(0%), min(calc(${t.width}%), calc(100% - 10px)))`}return A(()=>{t.needScroll===!0&&(o.value.onmouseenter=()=>{W.value.classList.add("in")},o.value.onmouseleave=()=>{W.value.classList.remove("in")}),d.value!==-1?(n.value=!0,m.value=Math.max(0,Math.min(1e4,d.value)),_.value=m.value*.01,T.value=_.value*.01*o.value.offsetWidth-p.value.offsetWidth,h.value?.setWidth(d.value,t.rank.contest)):h.value?.disableFilterSubmissionByTimestamp()}),G(()=>{}),(l,f)=>(g(),v("div",{ref_key:"scroll",ref:o,class:"am-progress am-progress-striped am-active","w-full":"",style:{position:"relative"}},[c("div",{ref_key:"mask",ref:L,class:D(["am-progress-bar",[x(M)]]),style:N({width:`${t.width}%`})},[t.needScroll?(g(),v(X,{key:0},[c("div",{ref_key:"tooltip",ref:W,class:"tooltip tooltip-top",style:N({marginLeft:"-32px",bottom:"22px",left:$()})},[c("div",{ref_key:"tooltipInner",ref:R,class:"tooltip-inner"},k(O()),513)],4),c("div",{ref_key:"bar",ref:p,class:D(["am-progress-bar am-progress-cursor am-progress-scroll-size z-99",[x(M)]]),style:N({left:$()}),onMousedown:U},null,38)],64)):E("",!0)],6)],512))}}),re=F(H,[["__scopeId","data-v-bb98868b"]]),J={flex:"","flex-row":"","items-center":"","justify-center":""},K={key:0,"ml-2":""},Q={key:1,"ml-2":""},Z=C({__name:"ContestStateBadge",props:{state:null,pendingTime:null,pausedTime:null},setup(s){const e=s;return(t,I)=>(g(),v("div",J,[c("div",{class:D(["label",e.state])},null,2),c("div",null,k(e.state),1),e.pendingTime&&e.state===x(u).PENDING?(g(),v("div",K,k(e.pendingTime),1)):E("",!0),e.pausedTime&&e.state===x(u).PAUSED?(g(),v("div",Q,k(e.pausedTime),1)):E("",!0)]))}}),ne=F(Z,[["__scopeId","data-v-68586c4d"]]);export{ne as _,re as a,ae as g};
@@ -1 +0,0 @@
1
- import{c as x,a as C}from"./contest-BrTkYMuZ.js";import{d as h,u as y,A as S,m as l,C as k,c as o,o as n,h as t,b as a,q as N,k as r,n as d,s as w}from"./index-BhjhJlKm.js";import{c as _}from"./constant-zXGoeSUs.js";import{u as T}from"./query-Ci5JHK5f.js";import{_ as E}from"./_plugin-vue_export-helper-DlAUqK2U.js";const I={class:"bg-[#323443]","text-gray-200":"","w-screen":"","h-screen":""},B={key:0},D={flex:"","flex-col":"","justify-center":"","items-center":"","w-screen":"","h-screen":"","text-xl":"",italic:""},U={key:0},b={key:1},j={flex:"","flex-col":"","items-center":"","justify-center":"","font-mono":""},F={key:0},L={key:1},O=h({__name:"Countdown",props:{dataSourceUrl:null},setup(u){const m=u,{t:f}=y(),p=S(_),s=w(),e=l({}),i=l(!1),{data:c,isError:v,error:g}=T(m.dataSourceUrl,s);return k(c,async()=>{c.value===null||c.value===void 0||(e.value=x(c.value?.contest),p.value=`${e.value.name} | ${_}`,i.value=!0)},{immediate:!0}),(P,V)=>(n(),o("div",I,[t(i)?(n(),o("div",b,[a("div",j,[a("div",{"mt-20":"","text-6xl":"",class:d([t(e).getContestState(t(s)).toString()])},r(t(e).getContestState(t(s))),3),a("div",{"mt-20":"",class:d(["text-[320px]",[t(e).getContestState(t(s)).toString()]])},[t(e).getContestState(t(s))===t(C).PENDING?(n(),o("div",F,r(t(e).getContestPendingTime(t(s))),1)):(n(),o("div",L,r(t(e).getContestElapsedTime(t(s))),1))],2)])])):(n(),o("div",B,[a("div",D,[a("div",null,r(t(f)("common.loading"))+"... ",1),t(v)?(n(),o("div",U,r(t(g)),1)):N("",!0)])]))]))}}),Q=E(O,[["__scopeId","data-v-2d2a8baf"]]);export{Q as _};
@@ -1 +0,0 @@
1
- import{_ as p}from"./TheInput.vue_vue_type_script_setup_true_lang-B8H-RmO4.js";import{d as f,u as _,m as h,g,H as b,c as v,q as S,h as a,o as x,b as t,a as U,a2 as V,z as k,k as l}from"./index-BhjhJlKm.js";import{g as y}from"./query-Ci5JHK5f.js";const w={key:0,class:"flex flex-col items-center"},D={"w-128":""},I=["disabled"],u="Data Source URL",K=f({__name:"DataSourceInput",setup(R){const{t:r}=_(),s=y(),e=h(s.value),c=g(),d=b();function n(){d.push(`${c.fullPath}/?data-source=${e.value.trim()}`)}return(B,o)=>{const i=p;return a(s).length===0?(x(),v("div",w,[t("div",D,[U(i,{modelValue:a(e),"onUpdate:modelValue":o[0]||(o[0]=m=>k(e)?e.value=m:null),"w-full":"",placeholder:u,autocomplete:"false",onKeydown:V(n,["enter"])},null,8,["modelValue"]),t("label",{class:"hidden",for:"input"},l(u))]),o[1]||(o[1]=t("div",{"py-2":""},null,-1)),t("div",null,[t("button",{"m-3":"","text-sm":"",btn:"",disabled:a(e).length===0,onClick:n},l(a(r)("button.go")),9,I)])])):S("",!0)}}});export{K as _};
@@ -1,6 +0,0 @@
1
- import{a as Y,h as W,P as V,_ as X,b as q}from"./pagination-R1BztuTi.js";import{_ as j}from"./Tooltip.vue_vue_type_script_setup_true_lang-CrvtqC16.js";import{d as I,f as p,c as _,o as f,a as x,w,b as o,n as D,h as r,k as v,u as L,G as $,z as O,m as T,q as y,C as K,j as Q,F as Z,E as tt,A as z,B as et,g as st}from"./index-BhjhJlKm.js";import{R as nt,d as C}from"./constant-zXGoeSUs.js";import{I as b,c as F}from"./dayjs-ErfWoYIs.js";import{c as G,P as B}from"./person-C-v09Xnw.js";class E{constructor(){this.rank=0,this.rating=0,this.teamName=new b,this.organization="",this.members=[],this.coaches=[],this.contestID="",this.contestName=new b,this.contestLink="",this.contestTime=F()}toJSON(){return{rank:this.rank,rating:this.rating,teamName:this.teamName.toI18NStringSet(),organization:this.organization,members:this.members.map(t=>t.toIPerson()),coaches:this.coaches.map(t=>t.toIPerson()),contestID:this.contestID,contestName:this.contestName.toI18NStringSet(),contestLink:this.contestLink,contestTime:this.contestTime.toDate()}}static fromJSON(t){typeof t=="string"&&(t=JSON.parse(t));const s=new E;return s.rank=t.rank,s.rating=t.rating,s.teamName=b.fromIText(t.teamName),s.organization=t.organization,s.members=G(t.members),s.coaches=G(t.coaches),s.contestID=t.contestID,s.contestName=b.fromIText(t.contestName),s.contestLink=t.contestLink,s.contestTime=F(t.contestTime),s}}class k{constructor(){this.id="",this.name=new b,this.organization="",this.members=[],this.coaches=[],this.rating=0,this.minRating=1061109567,this.maxRating=-1061109567,this.rank=0,this.oldRating=0,this.seed=1,this.delta=0,this.ratingHistories=[]}UpdateRating(t){this.rating=t,this.minRating=Math.min(this.minRating,t),this.maxRating=Math.max(this.maxRating,t)}toJSON(){return{id:this.id,name:this.name.toI18NStringSet(),organization:this.organization,members:this.members.map(t=>t.toIPerson()),coaches:this.coaches.map(t=>t.toIPerson()),rating:this.rating,minRating:this.minRating,maxRating:this.maxRating,ratingHistories:this.ratingHistories.map(t=>t.toJSON())}}static fromJSON(t){typeof t=="string"&&(t=JSON.parse(t));const s=new k;s.id=t.id,s.name=b.fromIText(t.name),s.organization=t.organization,s.members=t.members.map(a=>B.fromIPerson(a)),s.coaches=t.coaches.map(a=>B.fromIPerson(a)),s.rating=t.rating,s.minRating=t.minRating,s.maxRating=t.maxRating;for(const a of t.ratingHistories)s.ratingHistories.push(E.fromJSON(a));return s}}class at{constructor(){this.users=[]}calculate(){this.calculateInternal()}calcP(t,s){return 1/(1+10**((s.oldRating-t.oldRating)/400))}getExSeed(t,s,a){const i=new k;i.oldRating=s;let e=0;return t.forEach(n=>{n.id!==a.id&&(e+=this.calcP(n,i))}),e}calcRating(t,s,a){let i=1,e=8e3;for(;e-i>1;){const n=Math.floor((i+e)/2);this.getExSeed(t,n,a)<s?e=n:i=n}return i}calculateInternal(){for(let e=0;e<this.users.length;e++){const n=this.users[e];n.seed=1;for(let l=0;l<this.users.length;l++)if(e!==l){const h=this.users[l];n.seed+=this.calcP(h,n)}}let t=0;for(let e=0;e<this.users.length;e++){const n=this.users[e];n.delta=Math.floor((this.calcRating(this.users,Math.sqrt(n.rank*n.seed),n)-n.oldRating)/2),t+=n.delta}let s=Math.floor(-t/this.users.length)-1;for(let e=0;e<this.users.length;e++){const n=this.users[e];n.delta+=s}this.users=this.users.sort((e,n)=>n.oldRating-e.oldRating);const a=Math.min(this.users.length,Math.floor(4*Math.round(Math.sqrt(this.users.length))));let i=0;for(let e=0;e<a;e++)i+=this.users[e].delta;s=Math.min(Math.max(Math.floor(-i/a),-10),0),this.users.forEach(e=>{e.delta+=s,e.UpdateRating(e.oldRating+e.delta)}),this.users=this.users.sort((e,n)=>e.rank-n.rank)}}class P{constructor(){this.id="",this.name=new b,this.baseRating=1500,this.contestIDs=[],this.users=[],this.ranks=[],this.userMap=new Map}buildRating(){for(const t of this.ranks){t.buildRank();const s=new at;for(const a of t.teams){const i=this.generateTeamId(a);let e=null;this.userMap.has(i)?(e=this.userMap.get(i),e.rank=a.rank,e.oldRating=e.rating,s.users.push(e)):(e=new k,e.id=i,e.name=a.name,e.organization=a.organization,e.members=a.members,e.coaches=a.coaches,e.rank=a.rank,e.oldRating=this.baseRating,e.UpdateRating(this.baseRating),this.userMap.set(i,e),this.users.push(e),s.users.push(e));{const n=new E;n.rank=a.rank,n.rating=e.rating,n.teamName=a.name,n.organization=a.organization,n.members=a.members,n.coaches=a.coaches,n.contestID=t.contest.id,n.contestLink=n.contestID,n.contestName=t.contest.name,n.contestTime=t.contest.startTime,e.ratingHistories.push(n)}}s.calculate();for(const a of s.users)a.ratingHistories.at(-1).rating=a.rating}}generateTeamId(t){const s=t.members;return s.length>0?s.map(a=>a.name.getOrDefault().trim()).sort().join("|"):`${t.organization}-${t.name}`}toJSON(){return{id:this.id,name:this.name.toI18NStringSet(),baseRating:this.baseRating,contestIDs:this.contestIDs,users:this.users.map(t=>t.toJSON())}}static fromJSON(t){typeof t=="string"&&(t=JSON.parse(t));const s=new P;s.id=t.id,s.name=b.fromIText(t.name),s.baseRating=t.baseRating,s.contestIDs=t.contestIDs;for(const a of t.users)s.users.push(k.fromJSON(a));return s}}const J={NEWBIE:"Newbie",PUPIL:"Pupil",SPECIALIST:"Specialist",EXPERT:"Expert",CANDIDATE_MASTER:"Candidate Master",MASTER:"Master",INTERNATIONAL_MASTER:"International Master",GRANDMASTER:"Grandmaster",INTERNATIONAL_GRANDMASTER:"International Grandmaster",LEGENDARY_GRANDMASTER:"Legendary Grandmaster"};class A{static getRatingLevel(t){return t>=3e3?"LEGENDARY_GRANDMASTER":t>=2600?"INTERNATIONAL_GRANDMASTER":t>=2400?"GRANDMASTER":t>=2300?"INTERNATIONAL_MASTER":t>=2100?"MASTER":t>=1900?"CANDIDATE_MASTER":t>=1600?"EXPERT":t>=1400?"SPECIALIST":t>=1200?"PUPIL":"NEWBIE"}static getRatingLevelClass(t){if(typeof t=="number")return this.getRatingLevelClass(this.getRatingLevel(t));switch(t){case"NEWBIE":return"user-gray";case"PUPIL":return"user-green";case"SPECIALIST":return"user-cyan";case"EXPERT":return"user-blue";case"CANDIDATE_MASTER":return"user-violet";case"MASTER":return"user-orange";case"INTERNATIONAL_MASTER":return"user-orange";case"GRANDMASTER":return"user-red";case"INTERNATIONAL_GRANDMASTER":return"user-red";case"LEGENDARY_GRANDMASTER":return"user-legendary"}}}const ot={"text-md":""},rt=I({__name:"RatingBadge",props:{rating:null},setup(m){const t=m,s=p(()=>t.rating);return(a,i)=>{const e=j;return f(),_("div",null,[x(e,null,{popper:w(()=>[o("div",ot,v(r(J)[r(A).getRatingLevel(r(s))]),1)]),default:w(()=>[o("div",{"font-mono":"","font-bold":"",class:D(r(A).getRatingLevelClass(r(s)))},v(r(s)),3)]),_:1})])}}});function it(m,t){const s=t-m;return t>m?`+${s.toString()}`:s.toString()}function lt(m){const t=[];{let i=0;for(const e of m.ratingHistories){const n={};n.x=e.contestTime.unix()*1e3,n.y=e.rating,n.diffRating=it(i,e.rating),n.rank=e.rank,n.contestName=e.contestName,n.link=`/board/${e.contestID}`,n.contestTime=e.contestTime.format("YYYY-MM-DD HH:mm:ss"),n.teamName=e.teamName,n.ratingTitle=J[A.getRatingLevel(e.rating)],t.push(n),i=e.rating}}let s=[1200,1400,1600,1900,2100,2300,2400,2600,3e3];{let e=Math.max(0,m.minRating-100),n=m.maxRating+100;for(let l=0;l<s.length;++l)if(s[l]>n){n=s[l];break}for(let l=s.length-1;l>=0;--l)if(s[l]<e){e=s[l];break}e<1200&&(s=[e,...s]),n>3e3&&s.push(n),s=s.filter(l=>l>=e&&l<=n)}return{chart:{type:"line",height:"408px"},title:{text:null},xAxis:{tickWidth:0,gridLineWidth:.4,minRange:720*60*60*1e3,type:"datetime",showFirstLabel:!0,showLastLabel:!0,dateTimeLabelFormats:{month:"%b %Y"}},yAxis:{showEmpty:!1,showFirstLabel:!1,showLastLabel:!1,tickPositions:s,tickWidth:0,gridLineWidth:.6,labels:{enabled:!0,format:"{value}"},title:{text:null},plotBands:[{from:0,to:1199,color:"#CCCCCC"},{from:1200,to:1399,color:"#98FA87"},{from:1400,to:1599,color:"#90DABD"},{from:1600,to:1899,color:"#A9ACF9"},{from:1900,to:2099,color:"#EF91F9"},{from:2100,to:2299,color:"#F7CD91"},{from:2300,to:2399,color:"#F5BD67"},{from:2400,to:2599,color:"#Ef7F7B"},{from:2600,to:2999,color:"#EB483F"},{from:3e3,to:1061109567,color:"#9C1E14"}]},credits:{enabled:!1},plotOptions:{line:{color:"#ffec3d",dataLabels:{enabled:!1},enableMouseTracking:!0,marker:{enabled:!0,fillColor:"#fffb8f"}}},tooltip:{enabled:!0,headerFormat:"",useHTML:!0,shared:!0,shadow:!0,followPointer:!1,followTouchMove:!1,pointFormat:`= {point.y} ({point.diffRating}), {point.ratingTitle}
2
- <br/>Rank: {point.rank}
3
- <br/>TeamName: {point.teamName}
4
- <br/>ContestTime: {point.contestTime}
5
- <br/><a href="{point.link}">{point.contestName}</a>
6
- <br/>`},series:[{showInLegend:!1,allowPointSelect:!0,data:t}]}}const ct={"w-full":"","max-w-screen-xl":"","mx-auto":"","px-4":"","lg:px-8":""},ut={relative:"","overflow-hidden":"","bg-white":"","dark:bg-gray-800":""},mt={flex:"","flex-col":"","items-center":"","justify-between":"","md:flex-row":"","space-y-3":"","md:space-y-0":""},dt={flex:"","flex-row":"","space-x-3":""},gt={"text-gray-900":"","dark:text-white":"","text-2xl":"","font-sans":"","font-semibold":"",italic:""},ht={flex:"","flex-col":"","justify-start":"","items-start":""},ft={"w-full":"","font-bold":"","font-mono":"",flex:"","items-center":"","justify-center":""},pt={"w-full":""},_t=I({__name:"RatingInfoModal",props:{isHidden:{type:Boolean},ratingUser:null},emits:["update:isHidden"],setup(m,{emit:t}){const s=m,a=t,i=p({get(){return s.isHidden},set(d){a("update:isHidden",d)}}),{locale:e}=L(),n=p(()=>e.value),l=p(()=>s.ratingUser),h=p(()=>{let d="";return l.value.organization.length>0&&(d+=`${l.value.organization} - `),d+=`${l.value.name.getOrDefault(n.value)}`,l.value.members.length>0&&(d+=` - ${l.value.members.map(c=>c.name.getOrDefault(n.value)).join(", ")}`),l.value.coaches.length>0&&(d+=` - ${l.value.coaches.map(c=>c.name.getOrDefault(n.value)).join(", ")}(coach)`),d});return(d,c)=>{const R=j,g=Y;return f(),$(g,{"is-hidden":r(i),"onUpdate:isHidden":c[0]||(c[0]=u=>O(i)?i.value=u:null),width:"w-278"},{header:w(()=>[o("div",ct,[o("div",ut,[o("div",mt,[o("div",dt,[x(R,null,{popper:w(()=>[o("div",ht,[o("div",null," TeamID: "+v(r(l).id),1)])]),default:w(()=>[o("h3",gt,v(r(h)),1)]),_:1})])])])])]),default:w(()=>[o("div",ft,[o("div",pt,[x(r(W.Chart),{options:("getRatingGraphOptions"in d?d.getRatingGraphOptions:r(lt))(r(l))},null,8,["options"])])])]),_:1},8,["is-hidden"])}}}),xt={class:"border-b dark:border-gray-600 hover:bg-gray-100 dark:hover:bg-gray-700"},vt={class:"whitespace-nowrap px-4 py-2 text-gray-900 dark:text-white"},Rt={class:"whitespace-nowrap px-4 py-2 text-gray-900 dark:text-white"},bt={class:"whitespace-nowrap px-4 py-2 text-gray-900 dark:text-white"},Tt={class:"whitespace-nowrap px-4 py-2 text-gray-900 dark:text-white"},Nt={class:"whitespace-nowrap px-4 py-2 text-gray-900 dark:text-white"},wt=I({__name:"RatingUserUI",props:{ix:null,ratingUser:null},setup(m){const t=m,s=p(()=>t.ratingUser),{locale:a}=L(),i=p(()=>a.value),e=T(!0);function n(){e.value=!1}return(l,h)=>{const d=_t,c=rt;return f(),_("tr",xt,[o("td",vt,v(r(s).organization),1),o("td",null,[o("div",{class:D(["whitespace-nowrap px-4 py-2 text-gray-900 dark:text-white",r(A).getRatingLevelClass(r(s).rating)]),"cursor-pointer":"",onClick:n},v(r(s).name.getOrDefault(r(i))),3),o("div",null,[r(e)?y("",!0):(f(),$(d,{key:0,"is-hidden":r(e),"onUpdate:isHidden":h[0]||(h[0]=R=>O(e)?e.value=R:null),"rating-user":r(s)},null,8,["is-hidden","rating-user"]))])]),o("td",Rt,v(r(s).members.map(R=>R.name.getOrDefault(r(i)).trim()).join(" ")),1),o("td",bt,[x(c,{rating:r(s).rating},null,8,["rating"])]),o("td",Tt,[x(c,{rating:r(s).maxRating},null,8,["rating"])]),o("td",Nt,[x(c,{rating:r(s).minRating},null,8,["rating"])])])}}}),It={"mx-auto":"","w-full":""},yt={"space-y-3":"",flex:"","flex-col":"","px-4":"","py-3":"","lg:flex-row":"","lg:items-center":"","lg:justify-between":"","lg:space-x-4":"","lg:space-y-0":""},kt={flex:"","flex-shrink-0":"","flex-col":"","md:flex-row":"","md:items-center":"","lg:justify-end":"","space-y-3":"","md:space-x-3":"","md:space-y-0":""},St={"w-108":""},At={class:"overflow-x-auto"},Et={class:"w-full text-left text-sm text-gray-500 dark:text-gray-400","font-medium":"","font-mono":""},Mt=I({__name:"RatingTable",props:{rating:null,pageSize:null,removeBorder:{type:Boolean}},setup(m){const t=m,s=p(()=>t.rating),a=T({organizations:[]}),i=p(()=>{let g=s.value.users.map(u=>u.organization);return g=Array.from(new Set(g)),g.map(u=>({value:u,text:u}))}),e=T([]),n=T({});function l(g,u){e.value=g,n.value=u}const h=p(()=>s.value.users.filter(u=>{const N=a.value;if(N.organizations.length===0)return!0;for(const M of N.organizations)if(M===u.organization)return!0;return!1}));function d(){const g={organizations:[]};g.organizations=e.value.map(u=>u.value),a.value=g}const c=T(new V);c.value.currentPage=0,c.value.pageSize=t.pageSize??20,c.value.totalSize=h.value.length,K(h,()=>{c.value.totalSize=h.value.length,c.value.currentPage>=c.value.totalPage&&(c.value.currentPage=c.value.totalPage-1)});const R=p(()=>h.value.slice(c.value.currentLeft,c.value.currentRight));return(g,u)=>{const N=X,M=wt,U=q;return f(),_("section",null,[o("div",It,[o("div",{relative:"","overflow-hidden":"","bg-white":"","dark:bg-gray-800":"",class:D({"shadow-md":t.removeBorder!==!0,"sm:rounded-sm":t.removeBorder!==!0})},[o("div",yt,[o("div",kt,[o("div",St,[x(N,{options:r(i),"selected-options":r(e),placeholder:"Organization",onSelect:l},null,8,["options","selected-options"])]),o("div",null,[o("button",{type:"button",class:"flex flex-shrink-0 items-center justify-center border border-gray-200 rounded-lg bg-white px-3 py-2 text-sm font-medium text-gray-900 focus:z-10 dark:border-gray-600 dark:bg-gray-800 hover:bg-gray-100 dark:text-gray-400 hover:text-primary-700 focus:outline-none focus:ring-4 focus:ring-gray-200 dark:hover:bg-gray-700 dark:hover:text-white dark:focus:ring-gray-700",onClick:d},[...u[1]||(u[1]=[o("div",{"i-material-symbols-search":"","mr-1":"","h-5":"","w-5":""},null,-1),Q(" Filter ",-1)])])])])]),o("div",At,[o("table",Et,[u[2]||(u[2]=o("thead",{"text-xs":"","bg-gray-50":"","text-gray-700":"","dark:bg-gray-700":"","dark:text-gray-400":""},[o("tr",null,[o("th",{scope:"col",class:"px-4 py-3","w-68":""}," Organization "),o("th",{scope:"col",class:"px-4 py-3","w-128":""}," TeamName "),o("th",{scope:"col",class:"px-4 py-3","w-68":""}," Members "),o("th",{scope:"col",class:"px-4 py-3"}," Rating "),o("th",{scope:"col",class:"px-4 py-3"}," MaxRating "),o("th",{scope:"col",class:"px-4 py-3"}," MinRating ")])],-1)),o("tbody",null,[(f(!0),_(Z,null,tt(r(R),(S,H)=>(f(),$(M,{key:S.id,ix:H,"rating-user":S},null,8,["ix","rating-user"]))),128))])])]),x(U,{pagination:r(c),"onUpdate:pagination":u[0]||(u[0]=S=>O(c)?c.value=S:null)},null,8,["pagination"])],2)])])}}}),Dt={class:"sm:w-[1024px] lg:w-screen","lg:of-x-hidden":"",flex:"","flex-col":"","justify-center":"","items-center":""},Lt={key:0,"mt-4":"","mb-4":"",class:"sm:w-[1000px] lg:w-screen",flex:"","justify-center":"","items-center":""},$t={key:0},Ot={key:1},Pt={key:1,flex:"","flex-col":"","justify-center":"","items-center":""},zt={"text-4xl":"","font-medium":"","font-serif":""},Ct={"mt-4":""},Ft=I({__name:"Rating",props:{id:null},setup(m){const t=m,s=p(()=>t.id);function a(){return`${nt.value}${s.value}/rating.json`}const i=T(a()),e=T({}),{t:n,locale:l}=L(),h=p(()=>l.value);z(C);const{error:d,isFetching:c,isFinished:R}=et(i,{refetch:!0,afterFetch:g=>(e.value=P.fromJSON(g.data),z(`${e.value.name} | ${C}`),g)}).get();return(g,u)=>{const N=Mt;return f(),_("div",Dt,[o("div",null,[r(c)||r(d)?(f(),_("div",Lt,[r(c)?(f(),_("div",$t,v(r(n)("common.loading"))+"... ",1)):y("",!0),r(d)?(f(),_("div",Ot,v(r(d)),1)):y("",!0)])):y("",!0),r(R)?(f(),_("div",Pt,[o("div",zt,v(r(e).name.getOrDefault(r(h))),1),o("div",Ct,[x(N,{rating:r(e),"remove-border":!0},null,8,["rating"])])])):y("",!0)])])}}}),Yt=I({__name:"[...all]",setup(m){const s=st().path.split("/").pop();return(a,i)=>{const e=Ft;return f(),_("div",null,[x(e,{id:r(s)},null,8,["id"])])}}});export{Yt as default};
@@ -1 +0,0 @@
1
- import{d as k,H as R,u as b,r as h,c,o as t,b as m,a as i,k as p,h as o,w as $,j as v,g as N,G as a,q as S}from"./index-BhjhJlKm.js";import{_ as T}from"./Countdown-Bl6KQRW4.js";import{_ as V}from"./Balloon.vue_vue_type_script_setup_true_lang-DfFF1Ks0.js";import{_ as G}from"./Resolver-CcJz6DBo.js";import{_ as A}from"./Board-3MaXb78m.js";import{u as D}from"./contest-BrTkYMuZ.js";import{b as f}from"./route-block-B_A1xBdJ.js";import"./constant-zXGoeSUs.js";import"./query-Ci5JHK5f.js";import"./_plugin-vue_export-helper-DlAUqK2U.js";import"./rank-CzDyEdMa.js";import"./dayjs-ErfWoYIs.js";import"./person-C-v09Xnw.js";import"./pagination-R1BztuTi.js";import"./Tooltip.vue_vue_type_script_setup_true_lang-CrvtqC16.js";import"./TheInput.vue_vue_type_script_setup_true_lang-B8H-RmO4.js";import"./use-vmodel-B41hlwAY.js";import"./ContestStateBadge-Dx5wEApj.js";const E=k({__name:"GoBack",setup(y){const u=R(),{t:s}=b();return(x,r)=>{const e=h("RouterLink");return t(),c("div",null,[m("div",{class:"m-3 text-sm btn",onClick:r[0]||(r[0]=n=>o(u).back())},p(o(s)("button.back")),1),i(e,{class:"m-3 text-sm btn",to:"/"},{default:$(()=>[v(p(o(s)("button.home")),1)]),_:1})])}}}),L={key:0},j={key:1,class:"flex flex-col items-center"},q={key:2},F=k({__name:"[...all]",setup(y){const{t:u}=b(),s=N(),r=!["camp","icpc","ccpc","provincial-contest"].some(_=>s.fullPath.startsWith(`/${_}`)),e=D("component","board",{transform:String}),n=window.DATA_SOURCE;return(_,l)=>{const d=A,B=G,g=V,w=T,C=E;return o(n)?(t(),c("div",L,[o(e)==="board"?(t(),a(d,{key:0,"data-source-url":o(n)},null,8,["data-source-url"])):o(e)==="resolver"?(t(),a(B,{key:1,"data-source-url":o(n)},null,8,["data-source-url"])):o(e)==="balloon"?(t(),a(g,{key:2,"data-source-url":o(n)},null,8,["data-source-url"])):o(e)==="countdown"?(t(),a(w,{key:3,"data-source-url":o(n)},null,8,["data-source-url"])):S("",!0)])):r?(t(),c("div",j,[l[0]||(l[0]=m("div",{"text-4xl":""},[m("div",{"i-carbon-warning":""})],-1)),v(" "+p(o(u)("not-found"))+" ",1),i(C)])):(t(),c("div",q,[i(d)]))}}});typeof f=="function"&&f(F);export{F as default};
@@ -1 +0,0 @@
1
- import{_ as i}from"./Board-3MaXb78m.js";import{_ as u}from"./DataSourceInput.vue_vue_type_script_setup_true_lang-DHdSK4c6.js";import{g as f}from"./query-Ci5JHK5f.js";import{d,c as e,o as t,a as n,q as l,h as a,F as B,G as g}from"./index-BhjhJlKm.js";import{b as c}from"./route-block-B_A1xBdJ.js";import{_ as h}from"./_plugin-vue_export-helper-DlAUqK2U.js";import"./pagination-R1BztuTi.js";import"./Tooltip.vue_vue_type_script_setup_true_lang-CrvtqC16.js";import"./TheInput.vue_vue_type_script_setup_true_lang-B8H-RmO4.js";import"./use-vmodel-B41hlwAY.js";import"./rank-CzDyEdMa.js";import"./contest-BrTkYMuZ.js";import"./dayjs-ErfWoYIs.js";import"./person-C-v09Xnw.js";import"./ContestStateBadge-Dx5wEApj.js";import"./constant-zXGoeSUs.js";const k={key:0},x=d({__name:"CustomBoard",setup(s){const o=f();return(r,b)=>{const _=u,p=i;return t(),e(B,null,[n(_),a(o).length>0?(t(),e("div",k,[n(p,{"data-source-url":a(o)},null,8,["data-source-url"])])):l("",!0)],64)}}}),m={};function C(s,o){const r=x;return t(),g(r)}typeof c=="function"&&c(m);const A=h(m,[["render",C]]);export{A as default};
@@ -1 +0,0 @@
1
- import{f as t}from"./index-BhjhJlKm.js";const a="0.67.0",T="https://github.com/xcpcio/xcpcio",c="8314e7283b",I="https://xcpcio.com",r="Board - XCPCIO",_="Rating - XCPCIO",O="Balloon - XCPCIO",C="Resolver - XCPCIO",e="Countdown - XCPCIO",i=t(()=>window?window.CDN_HOST:""),o=t(()=>window?window.DATA_HOST:""),A=t(()=>o.value.replace("/data/","/rating-data/")),d=t(()=>window?window.DATA_REGION:"");export{a as A,O as B,i as C,o as D,T as G,A as R,r as T,I as X,c as a,d as b,e as c,_ as d,C as e};