@xcpcio/board-app 0.6.4 → 0.13.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/.eslintrc.json +6 -0
- package/LICENSE +1 -1
- package/README.md +13 -30
- package/cypress.config.ts +14 -0
- package/dist/_headers +3 -0
- package/dist/about.html +11 -0
- package/dist/assets/_...all_-27c7ae93.css +1 -0
- package/dist/assets/_...all_-d56798b5.js +3 -0
- package/dist/assets/_name_-8eab6137.js +1 -0
- package/dist/assets/about-a8cb8700.js +11 -0
- package/dist/assets/app-37f77a84.js +65 -0
- package/dist/assets/board-layout-deaedfc1.js +1 -0
- package/dist/assets/en-caedd340.js +1 -0
- package/dist/assets/home-49c336e5.js +1 -0
- package/dist/assets/index-a270cacd.css +5 -0
- package/dist/assets/index-layout-d65c80ea.js +1 -0
- package/dist/assets/test-0a3d6f7a.js +1 -0
- package/dist/assets/user-108782a1.js +1 -0
- package/dist/assets/virtual_pwa-register-1c1b9161.js +1 -0
- package/dist/assets/workbox-window.prod.es5-a7b12eab.js +2 -0
- package/dist/assets/zh-CN-86269804.js +1 -0
- package/dist/favicon-dark.svg +1 -0
- package/dist/favicon.svg +1 -0
- package/dist/index.html +1 -171
- package/dist/manifest.webmanifest +1 -0
- package/dist/pwa-192x192.png +0 -0
- package/dist/pwa-512x512.png +0 -0
- package/dist/robots.txt +4 -0
- package/dist/safari-pinned-tab.svg +41 -0
- package/dist/sitemap.xml +1 -0
- package/dist/ssr-manifest.json +486 -0
- package/dist/sw.js +1 -0
- package/dist/test.html +1 -0
- package/dist/workbox-b8d87ee1.js +1 -0
- package/package.json +94 -50
- package/public/_headers +3 -0
- package/public/favicon-dark.svg +1 -0
- package/public/favicon.svg +1 -0
- package/public/pwa-192x192.png +0 -0
- package/public/pwa-512x512.png +0 -0
- package/public/safari-pinned-tab.svg +41 -0
- package/src/App.vue +33 -0
- package/src/auto-imports.d.ts +909 -0
- package/src/components/ContestIndex.vue +227 -0
- package/src/components/Footer.vue +94 -0
- package/src/components/GoBack.vue +22 -0
- package/src/components/NavBar.vue +152 -0
- package/src/components/SearchInput.vue +50 -0
- package/src/components/TheCounter.vue +19 -0
- package/src/components/TheInput.vue +20 -0
- package/src/components/board/Balloon.vue +5 -0
- package/src/components/board/Board.vue +396 -0
- package/src/components/board/BottomStatistics.vue +159 -0
- package/src/components/board/ContestStateBadge.vue +41 -0
- package/src/components/board/Export.vue +75 -0
- package/src/components/board/Modal.vue +107 -0
- package/src/components/board/ModalMenu.vue +64 -0
- package/src/components/board/OptionsModal.vue +179 -0
- package/src/components/board/Progress.less +442 -0
- package/src/components/board/Progress.vue +229 -0
- package/src/components/board/SecondLevelMenu.vue +190 -0
- package/src/components/board/Standings.less +1162 -0
- package/src/components/board/Standings.vue +154 -0
- package/src/components/board/StandingsAnnotate.vue +38 -0
- package/src/components/board/Statistics.vue +77 -0
- package/src/components/board/SubmissionsTable.vue +312 -0
- package/src/components/board/SubmissionsTableModal.vue +52 -0
- package/src/components/board/TeamAwards.vue +93 -0
- package/src/components/board/TeamInfoModal.vue +128 -0
- package/src/components/board/TeamProblemBlock.vue +100 -0
- package/src/components/board/TeamUI.vue +161 -0
- package/src/components/board/Utility.vue +28 -0
- package/src/components/icon/GirlIcon.vue +80 -0
- package/src/components/icon/RightArrowIcon.vue +26 -0
- package/src/components/icon/StarIcon.vue +19 -0
- package/src/components/table/TablePagination.vue +108 -0
- package/src/components.d.ts +44 -0
- package/src/composables/dark.ts +4 -0
- package/src/composables/pagination.ts +81 -0
- package/src/composables/statistics.ts +280 -0
- package/src/composables/useLocalStorage.ts +29 -0
- package/src/composables/useQueryBoardData.ts +43 -0
- package/src/composables/utils.ts +11 -0
- package/src/layouts/board-layout.vue +14 -0
- package/src/layouts/default.vue +10 -0
- package/src/layouts/home.vue +12 -0
- package/src/layouts/index-layout.vue +15 -0
- package/src/main.ts +36 -0
- package/src/modules/README.md +11 -0
- package/src/modules/i18n.ts +52 -0
- package/src/modules/nprogress.ts +15 -0
- package/src/modules/pinia.ts +18 -0
- package/src/modules/pwa.ts +15 -0
- package/src/modules/toast.ts +10 -0
- package/src/pages/[...all].vue +34 -0
- package/src/pages/about.md +21 -0
- package/src/pages/hi/[name].vue +50 -0
- package/src/pages/index.vue +129 -0
- package/src/pages/test.vue +57 -0
- package/src/shims.d.ts +16 -0
- package/src/stores/user.ts +36 -0
- package/src/styles/color.css +51 -0
- package/src/styles/main.css +30 -0
- package/src/styles/markdown.css +28 -0
- package/src/styles/submission-status.css +123 -0
- package/src/types.ts +3 -0
- package/tsconfig.json +39 -0
- package/uno.config.ts +65 -0
- package/vite.config.ts +176 -0
- package/dist/favicon.ico +0 -0
- package/dist/umi.00ae29f6.js +0 -1
- package/dist/umi.bd64c248.css +0 -1
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { MedalType, type Team } from "@xcpcio/core";
|
|
3
|
+
|
|
4
|
+
const props = defineProps<{
|
|
5
|
+
team: Team,
|
|
6
|
+
}>();
|
|
7
|
+
|
|
8
|
+
const team = computed(() => props.team);
|
|
9
|
+
|
|
10
|
+
const firstSolvedProblems = computed(() => {
|
|
11
|
+
return props.team.problemStatistics.filter((p) => {
|
|
12
|
+
if (p.isFirstSolved) {
|
|
13
|
+
return true;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
return false;
|
|
17
|
+
});
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
interface Medal {
|
|
21
|
+
text: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const medal = computed((): Medal | null => {
|
|
25
|
+
const awards = props.team.awards;
|
|
26
|
+
|
|
27
|
+
if (awards.includes(MedalType.GOLD)) {
|
|
28
|
+
return {
|
|
29
|
+
text: "Gold",
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (awards.includes(MedalType.SILVER)) {
|
|
34
|
+
return {
|
|
35
|
+
text: "Silver",
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (awards.includes(MedalType.BRONZE)) {
|
|
40
|
+
return {
|
|
41
|
+
text: "Bronze",
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (awards.includes(MedalType.HONORABLE)) {
|
|
46
|
+
return {
|
|
47
|
+
text: "Honorable",
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return null;
|
|
52
|
+
});
|
|
53
|
+
</script>
|
|
54
|
+
|
|
55
|
+
<template>
|
|
56
|
+
<div
|
|
57
|
+
text-gray-900 dark:text-white
|
|
58
|
+
text-xl
|
|
59
|
+
font-mono font-semibold italic
|
|
60
|
+
flex flex-col gap-2
|
|
61
|
+
justify-center
|
|
62
|
+
>
|
|
63
|
+
<div>
|
|
64
|
+
Team Rank: {{ team.rank }}
|
|
65
|
+
</div>
|
|
66
|
+
|
|
67
|
+
<div
|
|
68
|
+
v-if="team.organization && team.organizationRank !== -1"
|
|
69
|
+
>
|
|
70
|
+
School Rank: {{ team.organizationRank }}
|
|
71
|
+
</div>
|
|
72
|
+
|
|
73
|
+
<div
|
|
74
|
+
v-if="firstSolvedProblems.length"
|
|
75
|
+
flex flex-col gap-2
|
|
76
|
+
>
|
|
77
|
+
<template
|
|
78
|
+
v-for="p in firstSolvedProblems"
|
|
79
|
+
:key="p.problem.id"
|
|
80
|
+
>
|
|
81
|
+
<div>
|
|
82
|
+
First Solved Problem {{ p.problem.label }}
|
|
83
|
+
</div>
|
|
84
|
+
</template>
|
|
85
|
+
</div>
|
|
86
|
+
|
|
87
|
+
<div
|
|
88
|
+
v-if="medal"
|
|
89
|
+
>
|
|
90
|
+
{{ medal.text }} Medal
|
|
91
|
+
</div>
|
|
92
|
+
</div>
|
|
93
|
+
</template>
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { Chart } from "highcharts-vue";
|
|
3
|
+
|
|
4
|
+
import type { Rank, Team } from "@xcpcio/core";
|
|
5
|
+
|
|
6
|
+
const props = defineProps<{
|
|
7
|
+
isHidden: boolean,
|
|
8
|
+
|
|
9
|
+
rank: Rank,
|
|
10
|
+
team: Team,
|
|
11
|
+
}>();
|
|
12
|
+
|
|
13
|
+
const emit = defineEmits(["update:isHidden"]);
|
|
14
|
+
|
|
15
|
+
const isHidden = computed({
|
|
16
|
+
get() {
|
|
17
|
+
return props.isHidden;
|
|
18
|
+
},
|
|
19
|
+
set(value) {
|
|
20
|
+
emit("update:isHidden", value);
|
|
21
|
+
},
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
const currentType = ref("submissions");
|
|
25
|
+
|
|
26
|
+
const rank = computed(() => props.rank);
|
|
27
|
+
const team = computed(() => props.team);
|
|
28
|
+
|
|
29
|
+
const headerTitle = computed(() => {
|
|
30
|
+
let res = "";
|
|
31
|
+
|
|
32
|
+
if (rank.value.contest.organization && team.value.organization.length > 0) {
|
|
33
|
+
res += `${team.value.organization} - `;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
res += `${team.value.name}`;
|
|
37
|
+
|
|
38
|
+
if (team.value.members) {
|
|
39
|
+
res += ` - ${team.value.members}`;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (team.value.coach) {
|
|
43
|
+
res += ` - ${team.value.coach}(coach)`;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return res;
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
const TYPE_SUBMISSIONS = "submissions";
|
|
50
|
+
const TYPE_STATISTICS = "statistics";
|
|
51
|
+
const TYPE_AWARDS = "awards";
|
|
52
|
+
const types = [TYPE_SUBMISSIONS, TYPE_STATISTICS, TYPE_AWARDS];
|
|
53
|
+
</script>
|
|
54
|
+
|
|
55
|
+
<template>
|
|
56
|
+
<Modal
|
|
57
|
+
v-model:isHidden="isHidden"
|
|
58
|
+
>
|
|
59
|
+
<template #header>
|
|
60
|
+
<div
|
|
61
|
+
w-full max-w-screen-xl
|
|
62
|
+
px-4 mx-auto lg:px-12
|
|
63
|
+
>
|
|
64
|
+
<div
|
|
65
|
+
relative overflow-hidden
|
|
66
|
+
bg-white dark:bg-gray-800
|
|
67
|
+
>
|
|
68
|
+
<div
|
|
69
|
+
flex flex-col items-center justify-between
|
|
70
|
+
md:flex-row
|
|
71
|
+
space-y-3 md:space-y-0 md:space-x-4
|
|
72
|
+
>
|
|
73
|
+
<h3
|
|
74
|
+
text-gray-900 dark:text-white
|
|
75
|
+
text-xl
|
|
76
|
+
font-sans font-semibold italic
|
|
77
|
+
>
|
|
78
|
+
{{ headerTitle }}
|
|
79
|
+
</h3>
|
|
80
|
+
|
|
81
|
+
<ModalMenu
|
|
82
|
+
v-model:current-type="currentType"
|
|
83
|
+
:types="types"
|
|
84
|
+
/>
|
|
85
|
+
</div>
|
|
86
|
+
</div>
|
|
87
|
+
</div>
|
|
88
|
+
</template>
|
|
89
|
+
|
|
90
|
+
<div
|
|
91
|
+
w-full
|
|
92
|
+
font-bold font-mono
|
|
93
|
+
flex items-center justify-center
|
|
94
|
+
>
|
|
95
|
+
<div
|
|
96
|
+
v-if="currentType === TYPE_SUBMISSIONS"
|
|
97
|
+
w-full
|
|
98
|
+
class="mt-[-12px]"
|
|
99
|
+
>
|
|
100
|
+
<SubmissionsTable
|
|
101
|
+
w-full
|
|
102
|
+
:rank="rank"
|
|
103
|
+
:submissions="team.submissions"
|
|
104
|
+
:page-size="8"
|
|
105
|
+
:remove-border="true"
|
|
106
|
+
/>
|
|
107
|
+
</div>
|
|
108
|
+
|
|
109
|
+
<div
|
|
110
|
+
v-if="currentType === TYPE_STATISTICS"
|
|
111
|
+
w-full
|
|
112
|
+
>
|
|
113
|
+
<Chart
|
|
114
|
+
:options="getTeamPlaceChart(rank, team)"
|
|
115
|
+
/>
|
|
116
|
+
</div>
|
|
117
|
+
|
|
118
|
+
<div
|
|
119
|
+
v-if="currentType === TYPE_AWARDS"
|
|
120
|
+
w-full
|
|
121
|
+
>
|
|
122
|
+
<TeamAwards
|
|
123
|
+
:team="team"
|
|
124
|
+
/>
|
|
125
|
+
</div>
|
|
126
|
+
</div>
|
|
127
|
+
</Modal>
|
|
128
|
+
</template>
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { Rank, Team, TeamProblemStatistics } from "@xcpcio/core";
|
|
3
|
+
|
|
4
|
+
const props = defineProps<{
|
|
5
|
+
rank: Rank,
|
|
6
|
+
team: Team,
|
|
7
|
+
p: TeamProblemStatistics,
|
|
8
|
+
}>();
|
|
9
|
+
|
|
10
|
+
const hiddenModal = ref(true);
|
|
11
|
+
function onClick() {
|
|
12
|
+
hiddenModal.value = false;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const rank = computed(() => props.rank);
|
|
16
|
+
const team = computed(() => props.team);
|
|
17
|
+
const p = computed(() => props.p);
|
|
18
|
+
|
|
19
|
+
function getProblemSign(p: TeamProblemStatistics): string {
|
|
20
|
+
if (p.isSolved) {
|
|
21
|
+
return "+";
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
if (p.isWrongAnswer) {
|
|
25
|
+
return "-";
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (p.isPending) {
|
|
29
|
+
return `? ${p.pendingCount}`;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return "";
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function getProblemShow(p: TeamProblemStatistics): string {
|
|
36
|
+
let res = "";
|
|
37
|
+
|
|
38
|
+
if (!p.isUnSubmitted) {
|
|
39
|
+
res += `${p.failedCount + Number(p.isSolved)}`;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if ((p.isSolved && rank.value.contest.statusTimeDisplay.correct)
|
|
43
|
+
|| (p.isPending && rank.value.contest.statusTimeDisplay.pending)
|
|
44
|
+
|| (p.isWrongAnswer && rank.value.contest.statusTimeDisplay.incorrect)) {
|
|
45
|
+
res += `/${Math.floor(p.lastSubmitTimestamp / 60)}`;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return res;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function getProblemColorClass(p: TeamProblemStatistics): string {
|
|
52
|
+
if (p.isFirstSolved) {
|
|
53
|
+
return "first-solve";
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
if (p.isSolved) {
|
|
57
|
+
return "correct";
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (p.isWrongAnswer) {
|
|
61
|
+
return "incorrect";
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (p.isPending) {
|
|
65
|
+
return "pending";
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return "unattempted";
|
|
69
|
+
}
|
|
70
|
+
</script>
|
|
71
|
+
|
|
72
|
+
<template>
|
|
73
|
+
<td
|
|
74
|
+
class="stnd"
|
|
75
|
+
:class="[getProblemColorClass(p)]"
|
|
76
|
+
>
|
|
77
|
+
<div
|
|
78
|
+
cursor-pointer
|
|
79
|
+
@click="onClick"
|
|
80
|
+
>
|
|
81
|
+
{{ getProblemSign(p) }}
|
|
82
|
+
<br>
|
|
83
|
+
{{ getProblemShow(p) }}
|
|
84
|
+
</div>
|
|
85
|
+
|
|
86
|
+
<div>
|
|
87
|
+
<SubmissionsTableModal
|
|
88
|
+
v-if="!hiddenModal"
|
|
89
|
+
v-model:isHidden="hiddenModal"
|
|
90
|
+
:rank="rank"
|
|
91
|
+
:team="team"
|
|
92
|
+
:p="p"
|
|
93
|
+
/>
|
|
94
|
+
</div>
|
|
95
|
+
</td>
|
|
96
|
+
</template>
|
|
97
|
+
|
|
98
|
+
<style scoped lang="less">
|
|
99
|
+
@import "./Standings.less";
|
|
100
|
+
</style>
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { MedalType } from "@xcpcio/core";
|
|
3
|
+
import type { Rank, Team } from "@xcpcio/core";
|
|
4
|
+
|
|
5
|
+
const props = defineProps<{
|
|
6
|
+
ix: number,
|
|
7
|
+
rank: Rank,
|
|
8
|
+
team: Team,
|
|
9
|
+
isFilter?: boolean;
|
|
10
|
+
}>();
|
|
11
|
+
|
|
12
|
+
const el = ref(null);
|
|
13
|
+
const isVisible = useElementVisibility(el);
|
|
14
|
+
|
|
15
|
+
const hiddenTeamInfoModal = ref(true);
|
|
16
|
+
function onClickTeamInfoModal() {
|
|
17
|
+
hiddenTeamInfoModal.value = false;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const rank = computed(() => props.rank);
|
|
21
|
+
const team = computed(() => props.team);
|
|
22
|
+
|
|
23
|
+
function getStandClassName(t: Team, isRankField = false): string {
|
|
24
|
+
if (props.isFilter) {
|
|
25
|
+
return "filter-team";
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (isRankField) {
|
|
29
|
+
if (t.awards.includes(MedalType.GOLD)) {
|
|
30
|
+
return "gold";
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (t.awards.includes(MedalType.SILVER)) {
|
|
34
|
+
return "silver";
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (t.awards.includes(MedalType.BRONZE)) {
|
|
38
|
+
return "bronze";
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (t.awards.includes(MedalType.HONORABLE)) {
|
|
42
|
+
return "honorable";
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return `stand${(rank.value.rankStatistics.maxSolvedProblems - t.solvedProblemNum) % 2}${(t.rank - 1) % 2}`;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function isRenderByVisible() {
|
|
50
|
+
// Some teams in the header may have rendering anomalies,
|
|
51
|
+
// so force the first 32 teams to render regardless of their visibility
|
|
52
|
+
// when rank rebuild trigger by drag the progress bar
|
|
53
|
+
return isVisible.value || props.ix < 32;
|
|
54
|
+
}
|
|
55
|
+
</script>
|
|
56
|
+
|
|
57
|
+
<template>
|
|
58
|
+
<tr
|
|
59
|
+
ref="el"
|
|
60
|
+
class="h-10"
|
|
61
|
+
:class="[props.isFilter ? 'filter-team' : '']"
|
|
62
|
+
>
|
|
63
|
+
<td
|
|
64
|
+
v-if="isRenderByVisible()"
|
|
65
|
+
class="stnd"
|
|
66
|
+
:class="[getStandClassName(team, true)]"
|
|
67
|
+
>
|
|
68
|
+
{{ team.rank }}
|
|
69
|
+
</td>
|
|
70
|
+
<td
|
|
71
|
+
v-if="rank.contest.badge && isRenderByVisible()"
|
|
72
|
+
class="empty flex items-center justify-center"
|
|
73
|
+
>
|
|
74
|
+
<img
|
|
75
|
+
:src="['data:image/png;base64,', team.badge?.base64].join('')"
|
|
76
|
+
alt=""
|
|
77
|
+
class="h-8 w-8"
|
|
78
|
+
>
|
|
79
|
+
</td>
|
|
80
|
+
<td
|
|
81
|
+
v-if="rank.contest.organization && isRenderByVisible()"
|
|
82
|
+
class="stnd"
|
|
83
|
+
:class="[getStandClassName(team)]"
|
|
84
|
+
>
|
|
85
|
+
<div flex>
|
|
86
|
+
<div class="float-left pl-2 font-serif">
|
|
87
|
+
<div v-if="team.organizationRank > -1">
|
|
88
|
+
{{ team.organizationRank }}
|
|
89
|
+
</div>
|
|
90
|
+
</div>
|
|
91
|
+
<div class="flex-1">
|
|
92
|
+
{{ team.organization }}
|
|
93
|
+
</div>
|
|
94
|
+
<div class="float-right" />
|
|
95
|
+
</div>
|
|
96
|
+
</td>
|
|
97
|
+
|
|
98
|
+
<td
|
|
99
|
+
v-if="isRenderByVisible()"
|
|
100
|
+
class="stnd"
|
|
101
|
+
:class="[getStandClassName(team)]"
|
|
102
|
+
>
|
|
103
|
+
<div
|
|
104
|
+
cursor-pointer
|
|
105
|
+
@click="onClickTeamInfoModal"
|
|
106
|
+
>
|
|
107
|
+
<span>{{ team.name }}</span>
|
|
108
|
+
<StarIcon v-if="team.group.includes('unofficial')" inline-block />
|
|
109
|
+
<GirlIcon v-if="team.group.includes('girl')" inline-block />
|
|
110
|
+
</div>
|
|
111
|
+
|
|
112
|
+
<div>
|
|
113
|
+
<TeamInfoModal
|
|
114
|
+
v-if="!hiddenTeamInfoModal"
|
|
115
|
+
v-model:isHidden="hiddenTeamInfoModal"
|
|
116
|
+
:rank="rank"
|
|
117
|
+
:team="team"
|
|
118
|
+
/>
|
|
119
|
+
</div>
|
|
120
|
+
</td>
|
|
121
|
+
|
|
122
|
+
<td
|
|
123
|
+
v-if="isRenderByVisible()"
|
|
124
|
+
class="stnd"
|
|
125
|
+
:class="[getStandClassName(team)]"
|
|
126
|
+
>
|
|
127
|
+
{{ team.solvedProblemNum }}
|
|
128
|
+
</td>
|
|
129
|
+
|
|
130
|
+
<td
|
|
131
|
+
v-if="isRenderByVisible()"
|
|
132
|
+
class="stnd"
|
|
133
|
+
:class="[getStandClassName(team)]"
|
|
134
|
+
>
|
|
135
|
+
{{ team.penaltyToMinute }}
|
|
136
|
+
</td>
|
|
137
|
+
|
|
138
|
+
<template
|
|
139
|
+
v-for="p in team.problemStatistics"
|
|
140
|
+
:key="p.problem.id"
|
|
141
|
+
>
|
|
142
|
+
<TeamProblemBlock
|
|
143
|
+
v-if="isRenderByVisible()"
|
|
144
|
+
:rank="rank"
|
|
145
|
+
:team="team"
|
|
146
|
+
:p="p"
|
|
147
|
+
/>
|
|
148
|
+
</template>
|
|
149
|
+
<td
|
|
150
|
+
v-if="isRenderByVisible()"
|
|
151
|
+
class="stnd"
|
|
152
|
+
:class="[getStandClassName(team)]"
|
|
153
|
+
>
|
|
154
|
+
{{ `${team.dict}%` }}
|
|
155
|
+
</td>
|
|
156
|
+
</tr>
|
|
157
|
+
</template>
|
|
158
|
+
|
|
159
|
+
<style scoped lang="less">
|
|
160
|
+
@import "./Standings.less";
|
|
161
|
+
</style>
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
// const props = defineProps<{
|
|
3
|
+
// rank: Rank,
|
|
4
|
+
// }>();
|
|
5
|
+
|
|
6
|
+
const { t } = useI18n();
|
|
7
|
+
|
|
8
|
+
const route = useRoute();
|
|
9
|
+
|
|
10
|
+
const resolverUrl = computed(() => {
|
|
11
|
+
return `https://resolver.xcpcio.com/resolver?xcpcio-data-source=${route.path}`;
|
|
12
|
+
});
|
|
13
|
+
</script>
|
|
14
|
+
|
|
15
|
+
<template>
|
|
16
|
+
<div
|
|
17
|
+
flex w-full mt-4
|
|
18
|
+
>
|
|
19
|
+
<a
|
|
20
|
+
btn
|
|
21
|
+
:href="resolverUrl"
|
|
22
|
+
target="_blank"
|
|
23
|
+
title="Resolver"
|
|
24
|
+
>
|
|
25
|
+
{{ t("type_menu.resolver") }}
|
|
26
|
+
</a>
|
|
27
|
+
</div>
|
|
28
|
+
</template>
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="color-gray-700 dark:color-gray-200">
|
|
3
|
+
<svg
|
|
4
|
+
t="1685666543416"
|
|
5
|
+
class="icon"
|
|
6
|
+
viewBox="0 0 1024 1024"
|
|
7
|
+
version="1.1"
|
|
8
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
9
|
+
p-id="3736"
|
|
10
|
+
width="16"
|
|
11
|
+
height="16"
|
|
12
|
+
>
|
|
13
|
+
<path
|
|
14
|
+
d="M661.333333 662.613333c0.213333 82.133333 28.8 169.386667 64 169.386667v170.666667H298.666667v-170.666667c35.2 0 63.786667-87.253333 64-169.386667a176.256 176.256 0 0 1 21.333333-1.28h21.333333c0 35.413333 47.786667 64 106.666667 64s106.666667-28.586667 106.666667-64h21.333333a176.256 176.256 0 0 1 21.333333 1.28z"
|
|
15
|
+
fill="#F3596B"
|
|
16
|
+
p-id="3737"
|
|
17
|
+
/>
|
|
18
|
+
<path
|
|
19
|
+
d="M810.666667 832v170.666667h-85.333334v-170.666667c-35.2 0-63.786667-87.253333-64-169.386667A170.666667 170.666667 0 0 1 810.666667 832zM362.666667 662.613333c-0.213333 82.133333-28.8 169.386667-64 169.386667v170.666667h-85.333334v-170.666667a170.666667 170.666667 0 0 1 149.333334-169.386667z"
|
|
20
|
+
fill="#FFD0AA"
|
|
21
|
+
p-id="3738"
|
|
22
|
+
/>
|
|
23
|
+
<path
|
|
24
|
+
d="M704 320v-85.333333c0-94.293333-97.706667-170.666667-192-170.666667a42.794667 42.794667 0 0 1 42.666667-42.666667h128a128 128 0 0 1 128 128v234.666667s0 85.333333 85.333333 85.333333c0 0-93.226667 134.613333-228.48 6.186667a166.229333 166.229333 0 0 0 13.866667-49.066667L682.666667 426.666667h21.333333a42.666667 42.666667 0 0 0 0-85.333334h-21.333333v-21.333333z"
|
|
25
|
+
fill="#FFCA6B"
|
|
26
|
+
p-id="3739"
|
|
27
|
+
/>
|
|
28
|
+
<path
|
|
29
|
+
d="M704 234.666667H320c0-94.293333 97.706667-170.666667 192-170.666667s192 76.373333 192 170.666667z"
|
|
30
|
+
fill="#FFCA6B"
|
|
31
|
+
p-id="3740"
|
|
32
|
+
/>
|
|
33
|
+
<path
|
|
34
|
+
d="M704 234.666667v85.333333H320v-85.333333h384z"
|
|
35
|
+
fill="#F3596B"
|
|
36
|
+
p-id="3741"
|
|
37
|
+
/>
|
|
38
|
+
<path
|
|
39
|
+
d="M746.666667 384a42.794667 42.794667 0 0 1-42.666667 42.666667h-21.333333l-1.28-0.213334A172.8 172.8 0 0 0 682.666667 405.333333v-64h21.333333a42.794667 42.794667 0 0 1 42.666667 42.666667zM341.333333 405.333333a172.8 172.8 0 0 0 1.28 21.12L341.333333 426.666667h-21.333333a42.666667 42.666667 0 0 1 0-85.333334h21.333333zM618.666667 661.333333c0 35.413333-47.786667 64-106.666667 64s-106.666667-28.586667-106.666667-64a42.794667 42.794667 0 0 0 42.666667-42.666666v-55.04a171.712 171.712 0 0 0 128 0V618.666667a42.794667 42.794667 0 0 0 42.666667 42.666666z"
|
|
40
|
+
fill="#FFD0AA"
|
|
41
|
+
p-id="3742"
|
|
42
|
+
/>
|
|
43
|
+
<path
|
|
44
|
+
d="M682.666667 341.333333v64a172.8 172.8 0 0 1-1.28 21.12 166.229333 166.229333 0 0 1-13.866667 49.066667A170.474667 170.474667 0 0 1 576 563.626667 170.538667 170.538667 0 0 1 341.333333 405.333333v-85.333333h341.333334z"
|
|
45
|
+
fill="#FFD0AA"
|
|
46
|
+
p-id="3743"
|
|
47
|
+
/>
|
|
48
|
+
<path
|
|
49
|
+
d="M810.666667 1024H213.333333a21.333333 21.333333 0 0 1-21.333333-21.333333v-170.666667a192.213333 192.213333 0 0 1 192-192h21.333333a21.333333 21.333333 0 0 0 21.333334-21.333333v-64h42.666666v64a64 64 0 0 1-64 64h-21.333333a149.504 149.504 0 0 0-149.333333 149.333333v149.333333h554.666666v-149.333333a149.504 149.504 0 0 0-149.333333-149.333333h-21.333333a64 64 0 0 1-64-64v-64h42.666666v64a21.333333 21.333333 0 0 0 21.333334 21.333333h21.333333a192.213333 192.213333 0 0 1 192 192v170.666667a21.333333 21.333333 0 0 1-21.333333 21.333333z"
|
|
50
|
+
fill="#2A3244"
|
|
51
|
+
p-id="3744"
|
|
52
|
+
/>
|
|
53
|
+
<path
|
|
54
|
+
d="M512 597.333333a192.234667 192.234667 0 0 1-192-192v-85.333333a21.333333 21.333333 0 0 1 21.333333-21.333333h341.333334a21.333333 21.333333 0 0 1 21.333333 21.333333v85.333333a192.234667 192.234667 0 0 1-192 192z m-149.333333-256v64a149.333333 149.333333 0 0 0 298.666666 0v-64z"
|
|
55
|
+
fill="#2A3244"
|
|
56
|
+
p-id="3745"
|
|
57
|
+
/>
|
|
58
|
+
<path
|
|
59
|
+
d="M704 448h-21.333333v-42.666667h21.333333a21.333333 21.333333 0 0 0 0-42.666666h-21.333333v-42.666667h21.333333a64 64 0 0 1 0 128zM341.333333 448h-21.333333a64 64 0 0 1 0-128h21.333333v42.666667h-21.333333a21.333333 21.333333 0 0 0 0 42.666666h21.333333z"
|
|
60
|
+
fill="#2A3244"
|
|
61
|
+
p-id="3746"
|
|
62
|
+
/>
|
|
63
|
+
<path
|
|
64
|
+
d="M704 341.333333H320a21.333333 21.333333 0 0 1-21.333333-21.333333v-85.333333a21.333333 21.333333 0 0 1 21.333333-21.333334h384a21.333333 21.333333 0 0 1 21.333333 21.333334v85.333333a21.333333 21.333333 0 0 1-21.333333 21.333333z m-362.666667-42.666666h341.333334v-42.666667H341.333333z"
|
|
65
|
+
fill="#2A3244"
|
|
66
|
+
p-id="3747"
|
|
67
|
+
/>
|
|
68
|
+
<path
|
|
69
|
+
d="M725.333333 234.666667h-42.666666c0-84.096-91.733333-149.333333-170.666667-149.333334s-170.666667 65.237333-170.666667 149.333334h-42.666666c0-109.888 112.618667-192 213.333333-192s213.333333 82.112 213.333333 192z"
|
|
70
|
+
fill="#2A3244"
|
|
71
|
+
p-id="3748"
|
|
72
|
+
/>
|
|
73
|
+
<path
|
|
74
|
+
d="M783.616 552.32c-46.122667 0-92.266667-22.805333-137.365333-67.904l30.165333-30.165333c39.701333 39.701333 78.613333 58.389333 115.648 55.018666a114.282667 114.282667 0 0 0 60.8-26.026666A105.92 105.92 0 0 1 789.333333 384V149.333333a106.794667 106.794667 0 0 0-106.666666-106.666666h-128a21.333333 21.333333 0 0 0-21.333334 21.333333h-42.666666a64 64 0 0 1 64-64h128a149.504 149.504 0 0 1 149.333333 149.333333v234.666667a60.842667 60.842667 0 0 0 64 64 21.333333 21.333333 0 0 1 17.536 33.472 174.72 174.72 0 0 1-117.333333 70.250667 130.133333 130.133333 0 0 1-12.586667 0.597333zM512 746.666667c-71.765333 0-128-37.482667-128-85.333334h42.666667c0 20.138667 36.48 42.666667 85.333333 42.666667s85.333333-22.528 85.333333-42.666667h42.666667c0 47.850667-56.234667 85.333333-128 85.333334zM746.666667 1002.666667h-42.666667v-154.709334c-43.968-23.274667-64-117.333333-64-186.624h42.666667c0 85.333333 29.866667 148.842667 42.666666 149.333334a22.08 22.08 0 0 1 21.333334 21.333333zM320 1002.666667h-42.666667v-170.666667a21.333333 21.333333 0 0 1 21.333334-21.333333c12.8-0.490667 42.666667-64 42.666666-149.333334h42.666667c0 69.354667-20.032 163.349333-64 186.624z"
|
|
75
|
+
fill="#2A3244"
|
|
76
|
+
p-id="3749"
|
|
77
|
+
/>
|
|
78
|
+
</svg>
|
|
79
|
+
</div>
|
|
80
|
+
</template>
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="color-gray-700 dark:color-gray-200">
|
|
3
|
+
<svg
|
|
4
|
+
stroke="currentColor"
|
|
5
|
+
fill="currentColor"
|
|
6
|
+
strokeWidth="0"
|
|
7
|
+
viewBox="0 0 1024 1024"
|
|
8
|
+
version="1.1"
|
|
9
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
10
|
+
p-id="1161"
|
|
11
|
+
width="30"
|
|
12
|
+
height="30"
|
|
13
|
+
>
|
|
14
|
+
<path
|
|
15
|
+
d="M837.9904 570.0608H124.5696a29.0304 29.0304 0 0 1-29.0304-29.0304V482.9696a29.0304 29.0304 0 0 1 29.0304-29.0304h713.4208z"
|
|
16
|
+
fill="currentColor"
|
|
17
|
+
p-id="1162"
|
|
18
|
+
/>
|
|
19
|
+
<path
|
|
20
|
+
d="M561.3056 808.96l-40.96-40.96a28.928 28.928 0 0 1 0-40.96l215.04-215.04-215.04-215.04a28.9792 28.9792 0 0 1 0-40.96l40.96-40.96a28.9792 28.9792 0 0 1 40.96 0l296.96 296.96-296.96 296.96a28.9792 28.9792 0 0 1-40.96 0z"
|
|
21
|
+
fill="currentColor"
|
|
22
|
+
p-id="1163"
|
|
23
|
+
/>
|
|
24
|
+
</svg>
|
|
25
|
+
</div>
|
|
26
|
+
</template>
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="color-gray-700 dark:color-gray-200">
|
|
3
|
+
<svg
|
|
4
|
+
t="1685845881484"
|
|
5
|
+
class="icon"
|
|
6
|
+
viewBox="0 0 1024 1024"
|
|
7
|
+
version="1.1"
|
|
8
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
9
|
+
p-id="4847"
|
|
10
|
+
width="16"
|
|
11
|
+
height="16"
|
|
12
|
+
>
|
|
13
|
+
<path
|
|
14
|
+
d="M785.352203 933.397493c-4.074805 0-8.151657-0.970094-11.833513-3.007497l-261.311471-142.488225L250.942821 930.388972c-8.343015 4.559852-18.527982 3.8814-26.28669-1.599428-7.760754-5.5279-11.640108-14.987343-10.088776-24.347524l47.578622-285.365306L72.563154 429.470355c-6.594185-6.547113-8.971325-16.295128-6.110161-25.122167 2.814092-8.850575 10.379395-15.397688 19.546172-16.949021l285.512662-47.577598 118.529557-236.989529c4.172019-8.391111 12.803607-13.701047 22.165836-13.701047 9.359158 0 17.992793 5.309936 22.163789 13.701047l118.529557 236.989529 285.511639 47.577598c9.217942 1.551332 16.73208 8.051373 19.593244 16.949021 2.813069 8.875135 0.48607 18.575054-6.109138 25.122167L762.264369 619.077737l47.577598 285.365306c1.50119 9.360182-2.37714 18.819624-10.087753 24.347524C795.487028 931.797042 790.394033 933.397493 785.352203 933.397493zM512.206196 734.747153c4.073782 0 8.196683 0.968048 11.880585 3.006474l228.379431 124.545574-41.268916-247.634983c-1.308809-7.90504 1.257643-16.005532 6.932899-21.63167l164.55787-164.555823-250.398934-41.709961c-7.855922-1.308809-14.549368-6.304589-18.140149-13.408381l-101.942787-203.915249"
|
|
15
|
+
p-id="4848"
|
|
16
|
+
/>
|
|
17
|
+
</svg>
|
|
18
|
+
</div>
|
|
19
|
+
</template>
|