Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(contest): support acc #97

Merged
merged 4 commits into from
Dec 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changes/fix-acc.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"algohub": patch:fix
---

Fixed accuracy calculation in the contest.
10 changes: 10 additions & 0 deletions src/scripts/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import type {
Contest,
CreateContest,
ContestProblem,
ContestRank,
} from "./types";

export interface Response<D> {
Expand Down Expand Up @@ -237,3 +238,12 @@ export const fetchContest = async (id: string, auth: Credentials) => {
return handleAxiosError(AxiosError.from(error));
}
};

export const fetchRanks = async (id: string, auth: Credentials) => {
try {
const response = await axios.post(`/contest/rank/${id}`, auth);
return response.data as Response<ContestRank[]>;
} catch (error) {
return handleAxiosError(AxiosError.from(error));
}
}
13 changes: 13 additions & 0 deletions src/scripts/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -162,4 +162,17 @@ export interface ContestProblem {
solved: boolean;
submittedCount: number;
acceptedCount: number;
accuracy?: number;
}

export interface RankData {
name: string;
problem_id: string;
accepted: boolean;
wrongs: number;
}

export interface ContestRank {
id: string;
details: RankData[];
}
59 changes: 48 additions & 11 deletions src/views/contest/[id].vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { onMounted, onUnmounted, ref } from 'vue';
import * as api from '@/scripts/api';
import { useRoute } from 'vue-router';
import { useAccountStore, useThemeStore } from '@/scripts/store';
import { Contest, ContestProblem } from '@/scripts/types';
import { Contest, ContestProblem, ContestRank } from '@/scripts/types';
import { useToast } from 'primevue';

const route = useRoute();
Expand All @@ -27,7 +27,7 @@ onMounted(async () => {
if (!res.success) {
return toast.add({ severity: 'error', summary: 'Error', detail: res.message });
}
problems.value = res.data;
problems.value = res.data?.map((problem) => { return { ...problem, accuracy: problem.acceptedCount / problem.submittedCount } });
duration.value = calcDateDiff(new Date(contest.value?.start_time!), new Date(contest.value?.end_time!))

loading.value = false;
Expand All @@ -43,12 +43,26 @@ const notEnded = () => {
}
const path = ref([{ label: 'Contests' }])

const togglePanel = (panel: string) => {
const selectedPanel = ref('contest')
const togglePanel = async (panel: string) => {
selectedPanel.value = panel
switch (panel) {
case 'problem':
case 'ranks':
await onToggleRanking();
}
}

const ranks = ref<ContestRank[]>();
const onToggleRanking = async () => {
console.log('toggle ranking')
const res = await api.fetchRanks(id, accountStore.auth!);
if (!res.success) {
return toast.add({ severity: 'error', summary: 'Error', detail: res.message });
}
ranks.value = res.data;
console.log(ranks.value)
}

function calcTimeDiff(start: Date, now: Date) {
const startTimeStamp = start.getTime();
const endTimeStamp = now.getTime();
Expand Down Expand Up @@ -95,16 +109,17 @@ onUnmounted(() => {
<div class="w-full flex flex-1 flex-row">
<div class="bg-gray-100 dark:bg-zinc-900 border-r-[1.5px] dark:border-zinc-700">
<div class="py-3 flex flex-col gap-4 sticky top-0 bottom-0 z-30 items-center">
<Button @click="togglePanel('problem')" pt:label:class="text-xs" label="Problem" icon="pi pi-code"
size="small" iconPos="top" plain text></Button>
<Button @click="togglePanel('records')" pt:label:class="text-xs" label="Records" icon="pi pi-file"
<Button @click="togglePanel('contest')" pt:label:class="text-xs" label="Contest" icon="pi pi-code"
size="small" iconPos="top" plain text></Button>
<!-- <Button @click="togglePanel('records')" pt:label:class="text-xs" label="Records" icon="pi pi-file"
size="small" iconPos="top" plain text disabled></Button> -->
<Button
@click="toast.add({ severity: 'info', summary: 'Coming Soon', detail: 'Ranking is still under beta and never fully tested, this may not work as expected.', life: 3000 });"
pt:label:class="text-xs" label="Ranks" icon="pi pi-chart-line" size="small" iconPos="top" plain
text></Button>
</div>
</div>
<div class="flex flex-col w-full h-full p-10 gap-8">
<Message severity="warn">This feature is still under <code>beta</code> testing, and may not work as
expected.
</Message>
<div v-if="selectedPanel === 'contest'" class="flex flex-col w-full h-full p-10 gap-8">
<Message v-if="contest?.announcement" severity="info">{{ contest?.announcement }}</Message>
<div class="flex flex-row flex-wrap gap-4">
<Panel class="hidden sm:flex" pt:header:class="!hidden" pt:content:class="!p-0">
Expand Down Expand Up @@ -173,6 +188,7 @@ onUnmounted(() => {
</Column>
<Column field="acceptedCount" header="Accepted" sortable></Column>
<Column field="submittedCount" header="Submitted" sortable></Column>
<Column field="accuracy" header="Accuracy" sortable></Column>
<Column field="solved" header="Status" sortable>
<template #body="slotProps">
<div class="flex items-center justify-center rounded-full w-[1.5em] h-[1.5em]"
Expand All @@ -185,6 +201,27 @@ onUnmounted(() => {
</template>
</Panel>
</div>
<div v-else-if="selectedPanel === 'ranks'" class="flex flex-col w-full h-full p-10 gap-8">
<Message severity="warn">Ranking is still under <code>beta</code> and never fully tested, this may not
work as expected.
</Message>
<Panel class="w-full h-full mt-4">
<template #header>
<div>Ranks</div>
</template>
<template #default>
<DataTable v-if="ranks && ranks.length > 0" :value="ranks">
<Column field="id" header="UserID"></Column>
<Column v-for="detail in ranks[0].details" :key="detail.name" :header="detail.name"
field="details">
<template #body="slotProps">
{{ slotProps }}
</template>
</Column>
</DataTable>
</template>
</Panel>
</div>
</div>
</div>
</template>
Loading