Update index.html
Browse files- index.html +111 -158
index.html
CHANGED
@@ -16,9 +16,9 @@
|
|
16 |
<script type="text/javascript">
|
17 |
const { useState, useEffect } = React;
|
18 |
|
19 |
-
const INTRO_VIDEO_DATASET = "imstevenpmwork/hackaton_closure";
|
20 |
|
21 |
-
/* Extract rank & team from filename "<rank>-<team
|
22 |
function parseRankTeam(path) {
|
23 |
const name = path.split("/").pop();
|
24 |
const m = name.match(/^(\d+)-(\d+)-/);
|
@@ -30,189 +30,142 @@
|
|
30 |
const [videos, setVideos] = useState([]);
|
31 |
const [teamDatasets, setTeamDatasets] = useState({});
|
32 |
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
}
|
47 |
-
} catch (e) {
|
48 |
-
console.error("Could not load intro video", e);
|
49 |
-
}
|
50 |
}
|
|
|
51 |
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
const
|
82 |
-
|
83 |
-
const
|
84 |
-
if (
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
}
|
91 |
-
});
|
92 |
-
setTeamDatasets(map);
|
93 |
-
}
|
94 |
|
95 |
-
|
96 |
-
|
|
|
97 |
}, []);
|
98 |
|
|
|
99 |
return React.createElement(
|
100 |
"div",
|
101 |
{ className: "min-h-screen py-10 px-4 max-w-3xl mx-auto" },
|
102 |
-
|
|
|
103 |
React.createElement(
|
104 |
"h1",
|
105 |
-
{
|
106 |
-
className:
|
107 |
-
"text-center text-4xl font-bold text-white mb-6 drop-shadow-lg",
|
108 |
-
},
|
109 |
"LeRobot Worldwide Hackathon – Winners"
|
110 |
),
|
111 |
-
|
|
|
112 |
React.createElement(
|
113 |
"p",
|
114 |
-
{
|
115 |
-
className:
|
116 |
-
"text-white text-center whitespace-pre-line mb-6 leading-relaxed",
|
117 |
-
},
|
118 |
[
|
119 |
-
React.createElement(
|
120 |
-
"span",
|
121 |
-
{ key: "bold", className: "font-bold" },
|
122 |
-
"🏆 €15,000 in robotics hardware prizes in collaboration with Seeedstudio"
|
123 |
-
),
|
124 |
" to support prizes for 10 winning teams and help us celebrate open-source robotics on a global scale! "
|
125 |
]
|
126 |
),
|
127 |
-
|
|
|
128 |
React.createElement(
|
129 |
"p",
|
130 |
-
{
|
131 |
-
className:
|
132 |
-
"text-white text-center whitespace-pre-line mb-10 leading-relaxed",
|
133 |
-
},
|
134 |
`🙌 Here’s a sneak peek at the prizes up for grabs in collaboration with SeeedStudio:\n\n🥇 1st to 3rd place teams: 1 Hope Jr Arm & 1 LeKiwi per team\n\n🥈 4th and 5th place teams: 1 Hope Jr Arm per team\n\n🥉 6th to 24th place teams: 1 LeKiwi per team\n\n🥉 25th to 30th place teams: 1 SO-101 per team\n\nA huge shoutout to everyone for your hard work and passion! It was truly tough to pick the top 30 – there were so many amazing demo videos, and we’re absolutely blown away. We also had a lot of laughs along the way!`
|
135 |
),
|
136 |
-
|
|
|
137 |
React.createElement(
|
138 |
"div",
|
139 |
{ className: "flex justify-center items-center gap-6 mb-10" },
|
140 |
-
React.createElement("img", {
|
141 |
-
|
142 |
-
alt: "Seeed Studio logo",
|
143 |
-
className: "h-12 w-auto",
|
144 |
-
}),
|
145 |
-
React.createElement("img", {
|
146 |
-
src: "hf.png",
|
147 |
-
alt: "Hugging Face logo",
|
148 |
-
className: "h-12 w-auto",
|
149 |
-
})
|
150 |
),
|
151 |
-
|
152 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
153 |
React.createElement(
|
154 |
-
"
|
155 |
-
{ className: "mb-
|
156 |
-
|
157 |
-
|
158 |
-
{ className: "sr-only" },
|
159 |
-
"Intro video"
|
160 |
-
),
|
161 |
-
React.createElement("video", {
|
162 |
-
src: introSrc,
|
163 |
-
controls: true,
|
164 |
-
className: "w-full rounded-xl shadow-2xl mb-10",
|
165 |
-
})
|
166 |
),
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
"
|
171 |
-
|
172 |
-
|
173 |
-
"
|
174 |
-
{
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
"span",
|
181 |
-
{ className: "text-base font-normal text-white/80" },
|
182 |
-
`– Team ${video.team ?? "?"}`
|
183 |
-
)
|
184 |
-
),
|
185 |
-
React.createElement("video", {
|
186 |
-
src: video.url,
|
187 |
-
controls: true,
|
188 |
-
className: "w-full rounded-xl shadow-2xl",
|
189 |
-
}),
|
190 |
-
teamDatasets[video.team] &&
|
191 |
-
React.createElement(
|
192 |
-
"div",
|
193 |
-
{ className: "mt-2 space-y-1" },
|
194 |
-
teamDatasets[video.team].map((url, j) =>
|
195 |
-
React.createElement(
|
196 |
-
"a",
|
197 |
-
{
|
198 |
-
key: j,
|
199 |
-
href: url,
|
200 |
-
target: "_blank",
|
201 |
-
className:
|
202 |
-
"text-sm text-blue-200 underline hover:text-white",
|
203 |
-
},
|
204 |
-
`Dataset: ${url.split("=")[1]}`
|
205 |
-
)
|
206 |
-
)
|
207 |
-
)
|
208 |
-
)
|
209 |
-
),
|
210 |
-
/* Sponsors */
|
211 |
React.createElement(
|
212 |
"div",
|
213 |
-
{
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
|
|
|
|
|
|
|
|
|
16 |
<script type="text/javascript">
|
17 |
const { useState, useEffect } = React;
|
18 |
|
19 |
+
const INTRO_VIDEO_DATASET = "imstevenpmwork/hackaton_closure";
|
20 |
|
21 |
+
/* Extract rank & team from filename "<rank>-<team>-... .mp4" */
|
22 |
function parseRankTeam(path) {
|
23 |
const name = path.split("/").pop();
|
24 |
const m = name.match(/^(\d+)-(\d+)-/);
|
|
|
30 |
const [videos, setVideos] = useState([]);
|
31 |
const [teamDatasets, setTeamDatasets] = useState({});
|
32 |
|
33 |
+
/* -------- fetch intro video once -------- */
|
34 |
+
async function loadIntro() {
|
35 |
+
if (!INTRO_VIDEO_DATASET) return;
|
36 |
+
try {
|
37 |
+
const res = await fetch(
|
38 |
+
`https://datasets-server.huggingface.co/rows?dataset=${INTRO_VIDEO_DATASET}&config=default&split=train&offset=0&limit=1`
|
39 |
+
);
|
40 |
+
const json = await res.json();
|
41 |
+
const row = json.rows?.[0]?.row || {};
|
42 |
+
const url = row.video || Object.values(row).find((v) => typeof v === "string" && v.endsWith(".mp4"));
|
43 |
+
if (url) setIntroSrc(url.startsWith("http") ? url : `https://huggingface.co/datasets/${INTRO_VIDEO_DATASET}/resolve/main/${url}`);
|
44 |
+
} catch (err) {
|
45 |
+
console.error("Intro video load failed", err);
|
|
|
|
|
|
|
|
|
46 |
}
|
47 |
+
}
|
48 |
|
49 |
+
/* -------- fetch ranked videos & dataset links -------- */
|
50 |
+
async function loadMainContent() {
|
51 |
+
/* videos */
|
52 |
+
const treeRes = await fetch(
|
53 |
+
"https://huggingface.co/api/datasets/maringetxway/all-winners/tree/main"
|
54 |
+
);
|
55 |
+
const tree = await treeRes.json();
|
56 |
+
const ranked = tree
|
57 |
+
.filter((f) => f.path.endsWith(".mp4"))
|
58 |
+
.map((f) => {
|
59 |
+
const { rank, team } = parseRankTeam(f.path);
|
60 |
+
return {
|
61 |
+
url: `https://huggingface.co/datasets/maringetxway/all-winners/resolve/main/${encodeURIComponent(
|
62 |
+
f.path
|
63 |
+
)}`,
|
64 |
+
rank,
|
65 |
+
team,
|
66 |
+
};
|
67 |
+
})
|
68 |
+
.sort((a, b) => a.rank - b.rank);
|
69 |
+
setVideos(ranked);
|
70 |
+
|
71 |
+
/* dataset visualisers per team */
|
72 |
+
const dsRes = await fetch(
|
73 |
+
"https://huggingface.co/api/datasets?author=maringetxway"
|
74 |
+
);
|
75 |
+
const dsList = await dsRes.json();
|
76 |
+
const map = {};
|
77 |
+
dsList.forEach(({ id }) => {
|
78 |
+
const m = id.match(/maringetxway\/team[_-]?(\d+)/i);
|
79 |
+
if (m) {
|
80 |
+
const t = +m[1];
|
81 |
+
if (!map[t]) map[t] = [];
|
82 |
+
map[t].push(`https://huggingface.co/spaces/lerobot/visualize_dataset?dataset=${id}`);
|
83 |
+
}
|
84 |
+
});
|
85 |
+
setTeamDatasets(map);
|
86 |
+
}
|
|
|
|
|
|
|
|
|
87 |
|
88 |
+
useEffect(() => {
|
89 |
+
loadIntro();
|
90 |
+
loadMainContent();
|
91 |
}, []);
|
92 |
|
93 |
+
/* ---------- JSX via React.createElement ---------- */
|
94 |
return React.createElement(
|
95 |
"div",
|
96 |
{ className: "min-h-screen py-10 px-4 max-w-3xl mx-auto" },
|
97 |
+
|
98 |
+
/* ====== HEADING ====== */
|
99 |
React.createElement(
|
100 |
"h1",
|
101 |
+
{ className: "text-center text-4xl font-bold text-white mb-6 drop-shadow-lg" },
|
|
|
|
|
|
|
102 |
"LeRobot Worldwide Hackathon – Winners"
|
103 |
),
|
104 |
+
|
105 |
+
/* ====== INTRO ====== */
|
106 |
React.createElement(
|
107 |
"p",
|
108 |
+
{ className: "text-white text-center whitespace-pre-line mb-6 leading-relaxed" },
|
|
|
|
|
|
|
109 |
[
|
110 |
+
React.createElement("span", { key: "b", className: "font-bold" }, "🏆 €15,000 in robotics hardware prizes in collaboration with Seeedstudio"),
|
|
|
|
|
|
|
|
|
111 |
" to support prizes for 10 winning teams and help us celebrate open-source robotics on a global scale! "
|
112 |
]
|
113 |
),
|
114 |
+
|
115 |
+
/* ====== PRIZE BREAKDOWN ====== */
|
116 |
React.createElement(
|
117 |
"p",
|
118 |
+
{ className: "text-white text-center whitespace-pre-line mb-10 leading-relaxed" },
|
|
|
|
|
|
|
119 |
`🙌 Here’s a sneak peek at the prizes up for grabs in collaboration with SeeedStudio:\n\n🥇 1st to 3rd place teams: 1 Hope Jr Arm & 1 LeKiwi per team\n\n🥈 4th and 5th place teams: 1 Hope Jr Arm per team\n\n🥉 6th to 24th place teams: 1 LeKiwi per team\n\n🥉 25th to 30th place teams: 1 SO-101 per team\n\nA huge shoutout to everyone for your hard work and passion! It was truly tough to pick the top 30 – there were so many amazing demo videos, and we’re absolutely blown away. We also had a lot of laughs along the way!`
|
120 |
),
|
121 |
+
|
122 |
+
/* ====== LOGOS ====== */
|
123 |
React.createElement(
|
124 |
"div",
|
125 |
{ className: "flex justify-center items-center gap-6 mb-10" },
|
126 |
+
React.createElement("img", { src: "seeedstudio.png", alt: "Seeed Studio logo", className: "h-12 w-auto" }),
|
127 |
+
React.createElement("img", { src: "hf.png", alt: "Hugging Face logo", className: "h-12 w-auto" })
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
128 |
),
|
129 |
+
|
130 |
+
/* ====== INTRO VIDEO (optional) ====== */
|
131 |
+
(introSrc ? React.createElement(
|
132 |
+
"section",
|
133 |
+
{ className: "mb-16" },
|
134 |
+
React.createElement("video", { src: introSrc, controls: true, className: "w-full rounded-xl shadow-2xl mb-10" })
|
135 |
+
) : null),
|
136 |
+
|
137 |
+
/* ====== RANKED VIDEOS ====== */
|
138 |
+
...videos.map((v, i) => React.createElement(
|
139 |
+
"section",
|
140 |
+
{ key: i, className: "mb-16" },
|
141 |
React.createElement(
|
142 |
+
"h2",
|
143 |
+
{ className: "text-2xl font-semibold text-white mb-4 flex items-center gap-2" },
|
144 |
+
`#${v.rank}`,
|
145 |
+
React.createElement("span", { className: "text-base font-normal text-white/80" }, `– Team ${v.team ?? "?"}`)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
146 |
),
|
147 |
+
React.createElement("video", { src: v.url, controls: true, className: "w-full rounded-xl shadow-2xl" }),
|
148 |
+
teamDatasets[v.team] ? React.createElement(
|
149 |
+
"div",
|
150 |
+
{ className: "mt-2 space-y-1" },
|
151 |
+
...teamDatasets[v.team].map((url, j) => React.createElement(
|
152 |
+
"a",
|
153 |
+
{ key: j, href: url, target: "_blank", className: "text-sm text-blue-200 underline hover:text-white" },
|
154 |
+
`Dataset: ${url.split("=")[1]}`
|
155 |
+
))
|
156 |
+
) : null
|
157 |
+
)),
|
158 |
+
|
159 |
+
/* ====== SPONSORS ====== */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
160 |
React.createElement(
|
161 |
"div",
|
162 |
+
{ className: "bg-white rounded-xl shadow-lg p-8 mt-20 flex justify-center" },
|
163 |
+
React.createElement("img", { src: "sponsors.png", alt: "Sponsors", className: "max-w-full h-auto" })
|
164 |
+
)
|
165 |
+
);
|
166 |
+
}
|
167 |
+
|
168 |
+
ReactDOM.createRoot(document.getElementById("root")).render(React.createElement(App));
|
169 |
+
</script>
|
170 |
+
</body>
|
171 |
+
</html>
|