|
<script lang="ts"> |
|
import { onMount } from "svelte"; |
|
import { ProgressBarRound } from "carbon-icons-svelte"; |
|
import { getConfig } from "./utils/getConfig"; |
|
|
|
interface Entry { |
|
name: string; |
|
rank: number; |
|
score: number; |
|
votes: number; |
|
open_source: boolean; |
|
displayName?: string; |
|
} |
|
|
|
export let onEntryClick: (entry: Entry) => void; |
|
export let showOnlyOpenSource: boolean; |
|
|
|
const baseUrl = "https://huggingface.co/datasets/dylanebert/3d-arena/resolve/main/outputs"; |
|
let leaderboard: Entry[] = []; |
|
let filteredLeaderboard: Entry[] = []; |
|
|
|
const fetchLeaderboardData = async () => { |
|
const url = "/api/leaderboard"; |
|
const response = await fetch(url, { |
|
method: "GET", |
|
headers: { |
|
"Cache-Control": "no-cache", |
|
}, |
|
}); |
|
const data = (await response.json()) as Entry[]; |
|
const entriesWithDisplayNames = await Promise.all( |
|
data.map(async (entry) => { |
|
const config = await getConfig(entry.name); |
|
return { ...entry, displayName: config.DisplayName || entry.name }; |
|
}), |
|
); |
|
entriesWithDisplayNames.sort((a, b) => a.rank - b.rank); |
|
|
|
leaderboard = entriesWithDisplayNames; |
|
updateFilteredLeaderboard(); |
|
}; |
|
|
|
const updateFilteredLeaderboard = () => { |
|
filteredLeaderboard = showOnlyOpenSource ? leaderboard.filter((entry) => entry.open_source) : leaderboard; |
|
}; |
|
|
|
$: { |
|
showOnlyOpenSource; |
|
updateFilteredLeaderboard(); |
|
} |
|
|
|
onMount(async () => { |
|
await fetchLeaderboardData(); |
|
}); |
|
</script> |
|
|
|
{#if filteredLeaderboard.length > 0} |
|
<div class="grid"> |
|
{#each filteredLeaderboard as entry, index} |
|
<button class="grid-item" on:click={() => onEntryClick(entry)}> |
|
<img src={`${baseUrl}/${entry.name}/thumbnail.png`} alt={entry.name} class="thumbnail" /> |
|
<div class="ranking">{index + 1}</div> |
|
<div class="title">{entry.displayName}</div> |
|
<div class="score-container"> |
|
<div class="score"> |
|
<span class="label">Score:</span> |
|
{entry.score} |
|
</div> |
|
<div class="votes"> |
|
<span class="label">Votes:</span> |
|
{entry.votes} |
|
</div> |
|
</div> |
|
</button> |
|
{/each} |
|
</div> |
|
{:else} |
|
<div class="loading-container"> |
|
<ProgressBarRound class="loading-icon" /> |
|
<div class="loading-text">Loading...</div> |
|
</div> |
|
{/if} |
|
|