| <!DOCTYPE html>
|
| <html lang="en">
|
| <head>
|
| <meta charset="UTF-8" />
|
| <meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
| <title>World Model Track Leaderboard | GigaBrain Challenge 2026</title>
|
| <script src="https://cdn.tailwindcss.com"></script>
|
| <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;600;700&display=swap" rel="stylesheet">
|
| <style>
|
| body { font-family: 'Inter', sans-serif; scroll-behavior: smooth; }
|
| .glass { background: rgba(255, 255, 255, 0.7); backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px); }
|
| </style>
|
| </head>
|
| <body class="bg-gray-50 text-gray-800">
|
| <div class="min-h-screen">
|
| <header class="relative overflow-hidden bg-gradient-to-br from-slate-900 via-slate-800 to-green-700 text-white">
|
| <div class="absolute inset-0 opacity-20"></div>
|
| <div class="relative max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-12">
|
| <div>
|
| <div>
|
| <p class="text-sm uppercase tracking-[0.2em] text-green-200">GigaBrain Challenge 2026 · Track 2</p>
|
| <h1 class="text-4xl md:text-5xl font-bold mt-3">World Model Track Leaderboard</h1>
|
| <p class="mt-4 text-green-100 text-lg max-w-3xl">
|
| Official leaderboard for the GigaBrain Challenge 2026 World Model Track.
|
| </p>
|
| <div class="mt-6 flex flex-wrap gap-3">
|
| <a href="mailto:gigabrainchallenge@163.com?subject=World%20Model%20Track%20Submission" class="inline-flex items-center gap-2 rounded-full bg-green-500 hover:bg-green-600 px-5 py-2.5 text-sm font-semibold shadow">
|
| Submit your run
|
| </a>
|
| <a href="#leaderboard" class="inline-flex items-center gap-2 rounded-full bg-white/10 px-5 py-2.5 text-sm font-semibold text-white ring-1 ring-white/30 hover:bg-white/20">
|
| View rankings
|
| </a>
|
| </div>
|
| </div>
|
| </div>
|
| </div>
|
| </header>
|
|
|
| <main class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-12 space-y-10">
|
| <section class="grid gap-6 md:grid-cols-3">
|
| <div class="bg-white rounded-2xl shadow-sm border border-gray-100 p-6">
|
| <div class="text-sm font-semibold text-green-700 uppercase tracking-wide">Accepted evidence</div>
|
| <p class="mt-2 text-gray-700">Submit by email to <a class="text-green-700 underline" href="mailto:gigabrainchallenge@163.com">gigabrainchallenge@163.com</a> with your ZIP package and metadata JSON (max ZIP size: 200 MB).</p>
|
| </div>
|
| <div class="bg-white rounded-2xl shadow-sm border border-gray-100 p-6">
|
| <div class="text-sm font-semibold text-green-700 uppercase tracking-wide">Submission format</div>
|
| <p class="mt-2 text-gray-700">Zip your run package with the task/episode folder structure shown in the Submission section. Maximum ZIP file size is 200 MB.</p>
|
| </div>
|
| <div class="bg-white rounded-2xl shadow-sm border border-gray-100 p-6">
|
| <div class="text-sm font-semibold text-green-700 uppercase tracking-wide">Update cadence</div>
|
| <p class="mt-2 text-gray-700">Submissions ingest daily, verification weekly, leaderboard publish weekly (UTC).</p>
|
| </div>
|
| </section>
|
|
|
| <section id="leaderboard" class="bg-white rounded-2xl shadow-sm border border-gray-100 p-6">
|
| <div class="flex flex-col md:flex-row md:items-center md:justify-between gap-4 mb-5">
|
| <div>
|
| <h2 class="text-2xl font-bold text-gray-900">Leaderboard</h2>
|
| </div>
|
| <div class="flex flex-wrap gap-2">
|
| <input id="search-input" type="text" placeholder="Search team or model" class="rounded-full border border-gray-300 px-4 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-green-500" />
|
| <button id="sort-score" class="inline-flex items-center gap-2 rounded-full bg-green-50 px-4 py-2 text-sm font-semibold text-green-700 ring-1 ring-inset ring-green-200 hover:bg-green-100">Sort: best score</button>
|
| <button id="sort-updated" class="inline-flex items-center gap-2 rounded-full bg-gray-100 px-4 py-2 text-sm font-semibold text-gray-700 ring-1 ring-inset ring-gray-200 hover:bg-gray-200">Sort: latest</button>
|
| </div>
|
| </div>
|
| <p id="load-state" class="text-sm text-gray-500 mb-3">Loading results.json...</p>
|
| <div class="overflow-x-auto">
|
| <table class="min-w-full divide-y divide-gray-200">
|
| <thead class="bg-gray-50">
|
| <tr>
|
| <th class="px-4 py-3 text-left text-xs font-semibold text-gray-600 uppercase tracking-wide">Rank</th>
|
| <th class="px-4 py-3 text-left text-xs font-semibold text-gray-600 uppercase tracking-wide">Team / Model</th>
|
| <th class="px-4 py-3 text-left text-xs font-semibold text-gray-600 uppercase tracking-wide">Round 1</th>
|
| <th class="px-4 py-3 text-left text-xs font-semibold text-gray-600 uppercase tracking-wide">Round 2</th>
|
| <th class="px-4 py-3 text-left text-xs font-semibold text-gray-600 uppercase tracking-wide">Round 3</th>
|
| <th class="px-4 py-3 text-left text-xs font-semibold text-gray-600 uppercase tracking-wide">Best</th>
|
| <th class="px-4 py-3 text-left text-xs font-semibold text-gray-600 uppercase tracking-wide">Submitted</th>
|
| <th class="px-4 py-3 text-left text-xs font-semibold text-gray-600 uppercase tracking-wide">Status</th>
|
| </tr>
|
| </thead>
|
| <tbody id="table-body" class="divide-y divide-gray-100 bg-white"></tbody>
|
| </table>
|
| </div>
|
| </section>
|
|
|
| <section id="submit" class="bg-white rounded-2xl shadow-sm border border-gray-100 p-6 space-y-5">
|
| <h3 class="text-2xl font-bold text-gray-900">Submission</h3>
|
| <div class="flex flex-wrap gap-3">
|
| <a href="mailto:gigabrainchallenge@163.com?subject=World%20Model%20Track%20Submission" class="inline-flex items-center gap-2 rounded-full bg-green-600 px-5 py-3 text-sm font-semibold text-white shadow hover:bg-green-700">
|
| Submit via email
|
| </a>
|
| <a href="#schema" class="inline-flex items-center gap-2 rounded-full bg-gray-100 px-4 py-2.5 text-sm font-semibold text-gray-800 ring-1 ring-inset ring-gray-200 hover:bg-gray-200">
|
| View JSON schema
|
| </a>
|
| </div>
|
| <div class="grid md:grid-cols-3 gap-4">
|
| <div class="bg-green-50 border border-green-100 rounded-xl p-4">
|
| <h4 class="text-sm font-semibold text-green-800 uppercase tracking-wide">Step 1</h4>
|
| <p class="mt-2 text-sm text-green-900">Prepare videos, metadata JSON, and contact details.</p>
|
| </div>
|
| <div class="bg-blue-50 border border-blue-100 rounded-xl p-4">
|
| <h4 class="text-sm font-semibold text-blue-800 uppercase tracking-wide">Step 2</h4>
|
| <p class="mt-2 text-sm text-blue-900">Email your ZIP package and metadata JSON to gigabrainchallenge@163.com with team/contact information.</p>
|
| </div>
|
| <div class="bg-amber-50 border border-amber-100 rounded-xl p-4">
|
| <h4 class="text-sm font-semibold text-amber-800 uppercase tracking-wide">Step 3</h4>
|
| <p class="mt-2 text-sm text-amber-900">Ensure each ZIP attachment is 200 MB or less. We verify evidence and publish validated results in weekly leaderboard updates.</p>
|
| </div>
|
| </div>
|
| <div class="bg-gray-900 text-gray-100 rounded-xl p-4 overflow-x-auto text-sm">
|
| <pre>outputs/
|
| --video_quality_eval/
|
| --task1/
|
| --episode_0.mp4
|
| --...
|
| --...
|
| --evaluator_test/
|
| --task1/
|
| --episode_0.mp4
|
| --...
|
| --...</pre>
|
| </div>
|
| </section>
|
|
|
| <section id="schema" class="bg-white rounded-2xl shadow-sm border border-gray-100 p-6">
|
| <h3 class="text-2xl font-bold text-gray-900 mb-3">Submission JSON schema</h3>
|
| <div class="bg-gray-900 text-gray-100 rounded-xl p-4 overflow-x-auto text-sm">
|
| <pre>{
|
| "team_name": "Your Team Name",
|
| "contact_email": "team@example.com",
|
| "affiliation": "Example University",
|
| "model_name": "Your Model Name",
|
| "model_version": "v1.1",
|
| "eval_setting": "Open-vocab tabletop; seed=5; 50 episodes",
|
| "composite_score": 89.3,
|
| "videos": [
|
| { "label": "long-horizon demo", "url": "https://huggingface.co/spaces/your-space/video1" }
|
| ],
|
| "notes": "Any deviations from reference protocol."
|
| }</pre>
|
| </div>
|
| </section>
|
|
|
| <section class="bg-white rounded-2xl shadow-sm border border-gray-100 p-6 space-y-3">
|
| <h3 class="text-2xl font-bold text-gray-900">Ranking updates and governance</h3>
|
| <ul class="list-disc list-inside text-gray-700 space-y-2">
|
| <li><span class="font-semibold">Ingest daily:</span> new submissions are queued.</li>
|
| <li><span class="font-semibold">Validate weekly:</span> videos and metadata are checked.</li>
|
| <li><span class="font-semibold">Publish weekly:</span> rankings refresh after validation.</li>
|
| <li><span class="font-semibold">Tie-break:</span> best score, then earlier submission.</li>
|
| </ul>
|
| </section>
|
| </main>
|
| </div>
|
|
|
| <script>
|
| let rows = [];
|
| let sortBy = 'score';
|
|
|
| function escapeHtml(s) {
|
| return String(s ?? '')
|
| .replace(/&/g, '&')
|
| .replace(/</g, '<')
|
| .replace(/>/g, '>')
|
| .replace(/"/g, '"')
|
| .replace(/'/g, ''');
|
| }
|
|
|
| const ROUND_KEYS = ['score(round1)', 'score(round2)', 'score(round3)'];
|
|
|
| function formatRoundScore(v) {
|
| if (v === null || v === undefined || v === '') return 'N/A';
|
| const n = Number(v);
|
| if (Number.isNaN(n)) return 'N/A';
|
| return String(parseFloat(n.toFixed(2)));
|
| }
|
|
|
|
|
| function getBestScoreSortValue(item) {
|
| if (item.best_score != null && item.best_score !== '') {
|
| const b = Number(item.best_score);
|
| if (!Number.isNaN(b)) return b;
|
| }
|
| const rounds = ROUND_KEYS.map((k) => item[k]).filter((v) => v !== null && v !== undefined && v !== '');
|
| const nums = rounds.map(Number).filter((n) => !Number.isNaN(n));
|
| if (nums.length) return Math.max(...nums);
|
| if (item.composite != null && item.composite !== '') {
|
| const c = Number(item.composite);
|
| if (!Number.isNaN(c)) return c;
|
| }
|
| return Number.NEGATIVE_INFINITY;
|
| }
|
|
|
| function renderTable() {
|
| const tbody = document.getElementById('table-body');
|
| const scoreBtn = document.getElementById('sort-score');
|
| const latestBtn = document.getElementById('sort-updated');
|
| if (scoreBtn && latestBtn) {
|
| if (sortBy === 'score') {
|
| scoreBtn.classList.remove('bg-gray-100', 'text-gray-700', 'ring-gray-200');
|
| scoreBtn.classList.add('bg-green-50', 'text-green-700', 'ring-green-200');
|
| latestBtn.classList.remove('bg-green-50', 'text-green-700', 'ring-green-200');
|
| latestBtn.classList.add('bg-gray-100', 'text-gray-700', 'ring-gray-200');
|
| } else {
|
| latestBtn.classList.remove('bg-gray-100', 'text-gray-700', 'ring-gray-200');
|
| latestBtn.classList.add('bg-green-50', 'text-green-700', 'ring-green-200');
|
| scoreBtn.classList.remove('bg-green-50', 'text-green-700', 'ring-green-200');
|
| scoreBtn.classList.add('bg-gray-100', 'text-gray-700', 'ring-gray-200');
|
| }
|
| }
|
| const q = (document.getElementById('search-input')?.value || '').toLowerCase().trim();
|
| let filtered = rows.filter((r) => {
|
| const text = `${r.team || ''} ${r.model || ''}`.toLowerCase();
|
| return !q || text.includes(q);
|
| });
|
|
|
| filtered.sort((a, b) => {
|
| if (sortBy === 'latest') return new Date(b.submitted || 0) - new Date(a.submitted || 0);
|
| return getBestScoreSortValue(b) - getBestScoreSortValue(a);
|
| });
|
|
|
| tbody.innerHTML = filtered.map((item, idx) => {
|
| const r1 = formatRoundScore(item['score(round1)']);
|
| const r2 = formatRoundScore(item['score(round2)']);
|
| const r3 = formatRoundScore(item['score(round3)']);
|
| let bestDisplay;
|
| if (item.best_score != null && item.best_score !== '') {
|
| const b = Number(item.best_score);
|
| bestDisplay = Number.isNaN(b) ? 'N/A' : formatRoundScore(item.best_score);
|
| } else {
|
| const sortVal = getBestScoreSortValue(item);
|
| bestDisplay = sortVal === Number.NEGATIVE_INFINITY ? 'N/A' : formatRoundScore(sortVal);
|
| }
|
| return `
|
| <tr class="${idx % 2 === 0 ? 'bg-white' : 'bg-gray-50'}">
|
| <td class="px-4 py-3 text-sm font-semibold text-gray-900">${idx + 1}</td>
|
| <td class="px-4 py-3">
|
| <div class="text-sm font-semibold text-gray-900">${escapeHtml(item.team)}</div>
|
| <div class="text-xs text-gray-600">${escapeHtml(item.model)} · ${escapeHtml(item.version)}</div>
|
| </td>
|
| <td class="px-4 py-3 text-sm text-gray-900 tabular-nums">${escapeHtml(r1)}</td>
|
| <td class="px-4 py-3 text-sm text-gray-900 tabular-nums">${escapeHtml(r2)}</td>
|
| <td class="px-4 py-3 text-sm text-gray-900 tabular-nums">${escapeHtml(r3)}</td>
|
| <td class="px-4 py-3 text-sm font-semibold text-gray-900 tabular-nums">${escapeHtml(bestDisplay)}</td>
|
| <td class="px-4 py-3 text-sm text-gray-600">${escapeHtml(item.submitted)}</td>
|
| <td class="px-4 py-3 text-xs"><span class="inline-flex rounded-full bg-green-100 px-2 py-1 font-semibold text-green-800">${escapeHtml(item.status || 'pending')}</span></td>
|
| </tr>
|
| `;
|
| }).join('');
|
|
|
| if (!filtered.length) {
|
| tbody.innerHTML = '<tr><td colspan="8" class="px-4 py-8 text-center text-sm text-gray-500">No leaderboard rows match your search.</td></tr>';
|
| }
|
| }
|
|
|
| async function init() {
|
| const state = document.getElementById('load-state');
|
| try {
|
| const res = await fetch('./results.json', { cache: 'no-store' });
|
| if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
| rows = await res.json();
|
| state.textContent = `Loaded ${rows.length} rows from results.json`;
|
| } catch (err) {
|
| rows = [];
|
| state.textContent = `Failed to load results.json (${String(err)}).`;
|
| }
|
| renderTable();
|
| }
|
|
|
| document.getElementById('sort-score')?.addEventListener('click', () => {
|
| sortBy = 'score';
|
| renderTable();
|
| });
|
|
|
| document.getElementById('sort-updated')?.addEventListener('click', () => {
|
| sortBy = 'latest';
|
| renderTable();
|
| });
|
|
|
| document.getElementById('search-input')?.addEventListener('input', renderTable);
|
|
|
| init();
|
| </script>
|
| </body>
|
| </html>
|
|
|