Spaces:
Running
Running
dylanebert
commited on
Commit
·
5679415
1
Parent(s):
160a21b
support alternative display names
Browse files- src/routes/+page.svelte +2 -3
- src/routes/Leaderboard.svelte +11 -3
- src/routes/ModelDetails.svelte +9 -12
- src/routes/Viewer.svelte +11 -3
- src/routes/Vote.svelte +11 -2
- src/routes/utils/Config.ts +6 -0
- src/routes/utils/getConfig.ts +8 -0
src/routes/+page.svelte
CHANGED
@@ -12,14 +12,14 @@
|
|
12 |
}
|
13 |
|
14 |
let currentView: "Leaderboard" | "Vote" | "ModelDetails" | "Viewer" | "About" = "Vote";
|
15 |
-
let selectedEntry: { name: string
|
16 |
let selectedScene: Scene | null = null;
|
17 |
|
18 |
function goHome() {
|
19 |
window.location.href = "/";
|
20 |
}
|
21 |
|
22 |
-
function showModelDetails(entry: { name: string
|
23 |
selectedEntry = entry;
|
24 |
currentView = "ModelDetails";
|
25 |
}
|
@@ -55,7 +55,6 @@
|
|
55 |
{:else if currentView === "ModelDetails" && selectedEntry}
|
56 |
<ModelDetails
|
57 |
modelName={selectedEntry.name}
|
58 |
-
modelPath={selectedEntry.path}
|
59 |
onBack={() => (currentView = "Leaderboard")}
|
60 |
onSceneClick={showScene}
|
61 |
/>
|
|
|
12 |
}
|
13 |
|
14 |
let currentView: "Leaderboard" | "Vote" | "ModelDetails" | "Viewer" | "About" = "Vote";
|
15 |
+
let selectedEntry: { name: string } | null = null;
|
16 |
let selectedScene: Scene | null = null;
|
17 |
|
18 |
function goHome() {
|
19 |
window.location.href = "/";
|
20 |
}
|
21 |
|
22 |
+
function showModelDetails(entry: { name: string }) {
|
23 |
selectedEntry = entry;
|
24 |
currentView = "ModelDetails";
|
25 |
}
|
|
|
55 |
{:else if currentView === "ModelDetails" && selectedEntry}
|
56 |
<ModelDetails
|
57 |
modelName={selectedEntry.name}
|
|
|
58 |
onBack={() => (currentView = "Leaderboard")}
|
59 |
onSceneClick={showScene}
|
60 |
/>
|
src/routes/Leaderboard.svelte
CHANGED
@@ -1,12 +1,14 @@
|
|
1 |
<script lang="ts">
|
2 |
import { onMount } from "svelte";
|
3 |
import { ProgressBarRound } from "carbon-icons-svelte";
|
|
|
4 |
|
5 |
interface Entry {
|
6 |
name: string;
|
7 |
rank: number;
|
8 |
score: number;
|
9 |
votes: number;
|
|
|
10 |
}
|
11 |
|
12 |
export let onEntryClick: (entry: Entry) => void;
|
@@ -23,9 +25,15 @@
|
|
23 |
},
|
24 |
});
|
25 |
const data = (await response.json()) as Entry[];
|
26 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
27 |
|
28 |
-
leaderboard =
|
29 |
};
|
30 |
|
31 |
onMount(async () => {
|
@@ -39,7 +47,7 @@
|
|
39 |
<button class="grid-item" on:click={() => onEntryClick(entry)}>
|
40 |
<img src={`${baseUrl}/${entry.name}/thumbnail.png`} alt={entry.name} class="thumbnail" />
|
41 |
<div class="ranking">{entry.rank}</div>
|
42 |
-
<div class="title">{entry.
|
43 |
<div class="score-container">
|
44 |
<div class="score">
|
45 |
<span class="label">Score:</span>
|
|
|
1 |
<script lang="ts">
|
2 |
import { onMount } from "svelte";
|
3 |
import { ProgressBarRound } from "carbon-icons-svelte";
|
4 |
+
import { getConfig } from "./utils/getConfig";
|
5 |
|
6 |
interface Entry {
|
7 |
name: string;
|
8 |
rank: number;
|
9 |
score: number;
|
10 |
votes: number;
|
11 |
+
displayName?: string;
|
12 |
}
|
13 |
|
14 |
export let onEntryClick: (entry: Entry) => void;
|
|
|
25 |
},
|
26 |
});
|
27 |
const data = (await response.json()) as Entry[];
|
28 |
+
const entriesWithDisplayNames = await Promise.all(
|
29 |
+
data.map(async (entry) => {
|
30 |
+
const config = await getConfig(entry.name);
|
31 |
+
return { ...entry, displayName: config.DisplayName || entry.name };
|
32 |
+
}),
|
33 |
+
);
|
34 |
+
entriesWithDisplayNames.sort((a, b) => a.rank - b.rank);
|
35 |
|
36 |
+
leaderboard = entriesWithDisplayNames;
|
37 |
};
|
38 |
|
39 |
onMount(async () => {
|
|
|
47 |
<button class="grid-item" on:click={() => onEntryClick(entry)}>
|
48 |
<img src={`${baseUrl}/${entry.name}/thumbnail.png`} alt={entry.name} class="thumbnail" />
|
49 |
<div class="ranking">{entry.rank}</div>
|
50 |
+
<div class="title">{entry.displayName}</div>
|
51 |
<div class="score-container">
|
52 |
<div class="score">
|
53 |
<span class="label">Score:</span>
|
src/routes/ModelDetails.svelte
CHANGED
@@ -1,6 +1,8 @@
|
|
1 |
<script lang="ts">
|
2 |
import { onMount } from "svelte";
|
3 |
import { ProgressBarRound, ArrowLeft } from "carbon-icons-svelte";
|
|
|
|
|
4 |
|
5 |
interface Scene {
|
6 |
name: string;
|
@@ -8,18 +10,13 @@
|
|
8 |
thumbnail: string;
|
9 |
}
|
10 |
|
11 |
-
interface Config {
|
12 |
-
Model: string;
|
13 |
-
Space: string;
|
14 |
-
Paper: string;
|
15 |
-
}
|
16 |
-
|
17 |
export let modelName: string;
|
18 |
export let onBack: () => void;
|
19 |
export let onSceneClick: (scene: Scene) => void;
|
20 |
|
21 |
let scenes: Scene[] = [];
|
22 |
let config: Config;
|
|
|
23 |
|
24 |
async function fetchScenes() {
|
25 |
scenes = [];
|
@@ -44,14 +41,14 @@
|
|
44 |
return acc;
|
45 |
}, []);
|
46 |
|
47 |
-
|
48 |
-
|
49 |
-
config = (await configResponse.json()) as Config;
|
50 |
|
51 |
scenes = [...scenes];
|
52 |
}
|
53 |
|
54 |
-
function isValidUrl(url: string): boolean {
|
|
|
55 |
try {
|
56 |
new URL(url);
|
57 |
return true;
|
@@ -69,7 +66,7 @@
|
|
69 |
</div>
|
70 |
<div class="spacer" />
|
71 |
<button class="title-button" on:click={fetchScenes}>
|
72 |
-
<h2 class="muted">{
|
73 |
</button>
|
74 |
<div class="desktop-spacer" />
|
75 |
</div>
|
@@ -99,7 +96,7 @@
|
|
99 |
<a class="muted" href={config.Paper} target="_blank">
|
100 |
{config.Paper.replace("https://huggingface.co/papers/", "").replace(
|
101 |
"https://arxiv.org/abs/",
|
102 |
-
""
|
103 |
)}
|
104 |
</a>
|
105 |
</div>
|
|
|
1 |
<script lang="ts">
|
2 |
import { onMount } from "svelte";
|
3 |
import { ProgressBarRound, ArrowLeft } from "carbon-icons-svelte";
|
4 |
+
import { getConfig } from "./utils/getConfig";
|
5 |
+
import type { Config } from "./utils/Config";
|
6 |
|
7 |
interface Scene {
|
8 |
name: string;
|
|
|
10 |
thumbnail: string;
|
11 |
}
|
12 |
|
|
|
|
|
|
|
|
|
|
|
|
|
13 |
export let modelName: string;
|
14 |
export let onBack: () => void;
|
15 |
export let onSceneClick: (scene: Scene) => void;
|
16 |
|
17 |
let scenes: Scene[] = [];
|
18 |
let config: Config;
|
19 |
+
let displayName: string;
|
20 |
|
21 |
async function fetchScenes() {
|
22 |
scenes = [];
|
|
|
41 |
return acc;
|
42 |
}, []);
|
43 |
|
44 |
+
config = await getConfig(modelName);
|
45 |
+
displayName = config.DisplayName || modelName;
|
|
|
46 |
|
47 |
scenes = [...scenes];
|
48 |
}
|
49 |
|
50 |
+
function isValidUrl(url: string | undefined): boolean {
|
51 |
+
if (!url) return false;
|
52 |
try {
|
53 |
new URL(url);
|
54 |
return true;
|
|
|
66 |
</div>
|
67 |
<div class="spacer" />
|
68 |
<button class="title-button" on:click={fetchScenes}>
|
69 |
+
<h2 class="muted">{displayName || "Loading..."}</h2>
|
70 |
</button>
|
71 |
<div class="desktop-spacer" />
|
72 |
</div>
|
|
|
96 |
<a class="muted" href={config.Paper} target="_blank">
|
97 |
{config.Paper.replace("https://huggingface.co/papers/", "").replace(
|
98 |
"https://arxiv.org/abs/",
|
99 |
+
"",
|
100 |
)}
|
101 |
</a>
|
102 |
</div>
|
src/routes/Viewer.svelte
CHANGED
@@ -3,6 +3,8 @@
|
|
3 |
import type { IViewer } from "./viewers/IViewer";
|
4 |
import { createViewer } from "./viewers/ViewerFactory";
|
5 |
import { ArrowLeft, Cube, WatsonHealth3DPrintMesh } from "carbon-icons-svelte";
|
|
|
|
|
6 |
|
7 |
interface Scene {
|
8 |
name: string;
|
@@ -20,9 +22,11 @@
|
|
20 |
let loadingBarFill: HTMLDivElement;
|
21 |
|
22 |
let viewer: IViewer;
|
|
|
23 |
|
24 |
async function loadScene() {
|
25 |
overlay.style.display = "flex";
|
|
|
26 |
viewer = await createViewer(scene.url, canvas, (progress) => {
|
27 |
loadingBarFill.style.width = `${progress * 100}%`;
|
28 |
});
|
@@ -78,9 +82,13 @@
|
|
78 |
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
79 |
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
80 |
<h2>
|
81 |
-
|
82 |
-
|
83 |
-
|
|
|
|
|
|
|
|
|
84 |
</h2>
|
85 |
</button>
|
86 |
<div class="desktop-spacer" />
|
|
|
3 |
import type { IViewer } from "./viewers/IViewer";
|
4 |
import { createViewer } from "./viewers/ViewerFactory";
|
5 |
import { ArrowLeft, Cube, WatsonHealth3DPrintMesh } from "carbon-icons-svelte";
|
6 |
+
import type { Config } from "./utils/Config";
|
7 |
+
import { getConfig } from "./utils/getConfig";
|
8 |
|
9 |
interface Scene {
|
10 |
name: string;
|
|
|
22 |
let loadingBarFill: HTMLDivElement;
|
23 |
|
24 |
let viewer: IViewer;
|
25 |
+
let displayName: string;
|
26 |
|
27 |
async function loadScene() {
|
28 |
overlay.style.display = "flex";
|
29 |
+
displayName = (await getConfig(modelName)).DisplayName || modelName;
|
30 |
viewer = await createViewer(scene.url, canvas, (progress) => {
|
31 |
loadingBarFill.style.width = `${progress * 100}%`;
|
32 |
});
|
|
|
82 |
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
83 |
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
84 |
<h2>
|
85 |
+
{#if displayName}
|
86 |
+
<span class="muted" on:click={onBack}>{displayName}/</span>{scene.name.length > 16
|
87 |
+
? `${scene.name.slice(0, 16)}...`
|
88 |
+
: scene.name}
|
89 |
+
{:else}
|
90 |
+
Loading...
|
91 |
+
{/if}
|
92 |
</h2>
|
93 |
</button>
|
94 |
<div class="desktop-spacer" />
|
src/routes/Vote.svelte
CHANGED
@@ -3,14 +3,17 @@
|
|
3 |
import type { IViewer } from "./viewers/IViewer";
|
4 |
import { createViewer } from "./viewers/ViewerFactory";
|
5 |
import { Cube, WatsonHealth3DPrintMesh } from "carbon-icons-svelte";
|
|
|
6 |
|
7 |
interface Data {
|
8 |
input: string;
|
9 |
input_path: string;
|
10 |
model1: string;
|
11 |
model1_path: string;
|
|
|
12 |
model2: string;
|
13 |
model2_path: string;
|
|
|
14 |
}
|
15 |
|
16 |
let viewerA: IViewer;
|
@@ -78,6 +81,12 @@
|
|
78 |
const model1_path = `${baseUrl}${data.model1_path}`;
|
79 |
const model2_path = `${baseUrl}${data.model2_path}`;
|
80 |
|
|
|
|
|
|
|
|
|
|
|
|
|
81 |
try {
|
82 |
[viewerA, viewerB] = await Promise.all([
|
83 |
createViewer(model1_path, canvasA, (progress) => {
|
@@ -214,7 +223,7 @@
|
|
214 |
<div bind:this={loadingBarFillA} class="loading-bar-fill" />
|
215 |
</div>
|
216 |
</div>
|
217 |
-
<div bind:this={voteOverlayA} class="vote-overlay">{data.
|
218 |
<canvas bind:this={canvasA} class="viewer-canvas" id="canvas1"> </canvas>
|
219 |
<div class="stats">
|
220 |
{#if viewerA}
|
@@ -253,7 +262,7 @@
|
|
253 |
<div bind:this={loadingBarFillB} class="loading-bar-fill" />
|
254 |
</div>
|
255 |
</div>
|
256 |
-
<div bind:this={voteOverlayB} class="vote-overlay">{data.
|
257 |
<canvas bind:this={canvasB} class="viewer-canvas" id="canvas2"></canvas>
|
258 |
<div class="stats">
|
259 |
{#if viewerB}
|
|
|
3 |
import type { IViewer } from "./viewers/IViewer";
|
4 |
import { createViewer } from "./viewers/ViewerFactory";
|
5 |
import { Cube, WatsonHealth3DPrintMesh } from "carbon-icons-svelte";
|
6 |
+
import { getConfig } from "./utils/getConfig";
|
7 |
|
8 |
interface Data {
|
9 |
input: string;
|
10 |
input_path: string;
|
11 |
model1: string;
|
12 |
model1_path: string;
|
13 |
+
model1_displayName: string;
|
14 |
model2: string;
|
15 |
model2_path: string;
|
16 |
+
model2_displayName: string;
|
17 |
}
|
18 |
|
19 |
let viewerA: IViewer;
|
|
|
81 |
const model1_path = `${baseUrl}${data.model1_path}`;
|
82 |
const model2_path = `${baseUrl}${data.model2_path}`;
|
83 |
|
84 |
+
const config1 = await getConfig(data.model1);
|
85 |
+
const config2 = await getConfig(data.model2);
|
86 |
+
|
87 |
+
data.model1_displayName = config1.DisplayName || data.model1;
|
88 |
+
data.model2_displayName = config2.DisplayName || data.model2;
|
89 |
+
|
90 |
try {
|
91 |
[viewerA, viewerB] = await Promise.all([
|
92 |
createViewer(model1_path, canvasA, (progress) => {
|
|
|
223 |
<div bind:this={loadingBarFillA} class="loading-bar-fill" />
|
224 |
</div>
|
225 |
</div>
|
226 |
+
<div bind:this={voteOverlayA} class="vote-overlay">{data.model1_displayName}</div>
|
227 |
<canvas bind:this={canvasA} class="viewer-canvas" id="canvas1"> </canvas>
|
228 |
<div class="stats">
|
229 |
{#if viewerA}
|
|
|
262 |
<div bind:this={loadingBarFillB} class="loading-bar-fill" />
|
263 |
</div>
|
264 |
</div>
|
265 |
+
<div bind:this={voteOverlayB} class="vote-overlay">{data.model2_displayName}</div>
|
266 |
<canvas bind:this={canvasB} class="viewer-canvas" id="canvas2"></canvas>
|
267 |
<div class="stats">
|
268 |
{#if viewerB}
|
src/routes/utils/Config.ts
ADDED
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
export interface Config {
|
2 |
+
Model?: string;
|
3 |
+
Space?: string;
|
4 |
+
Paper?: string;
|
5 |
+
DisplayName?: string;
|
6 |
+
}
|
src/routes/utils/getConfig.ts
ADDED
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import type { Config } from "./Config";
|
2 |
+
|
3 |
+
export async function getConfig(modelName: string): Promise<Config> {
|
4 |
+
const configUrl = `https://huggingface.co/datasets/dylanebert/3d-arena/resolve/main/outputs/${modelName}/config.json`;
|
5 |
+
const configResponse = await fetch(configUrl);
|
6 |
+
const config = await configResponse.json();
|
7 |
+
return config;
|
8 |
+
}
|