Files
courtside/scripts/seed-demo.js
T
bkvargyasandClaude Fable 5.1 1956d25061 Team-name links to team pages, court timing and next-up per court, desk link in footer
Every team name on the board links to /t/<slug>/teams/<id>. Court cards show
average game time, minutes played and the next match predicted for that court
with its expected ready time; the queue shows clock times too. Team schedules
show scores from the team's own perspective. Release 0.3.1.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01MB7nCCAscYsb3zzkT6LHZi
2026-09-04 01:48:54 +00:00

65 lines
3.6 KiB
JavaScript

// Creates a demo tournament in the database so a fresh install has something to look at.
// Run with the server STOPPED (the server keeps state in memory and writes it back):
// DB_PATH=./data/courtside.sqlite node scripts/seed-demo.js
// Options: --stage=pool (default, mid pool play) | --stage=bracket (single elim in progress)
// | --stage=double (double elim in progress)
import { fileURLToPath } from 'node:url';
import { dirname, join } from 'node:path';
import { Store } from '../server/store.js';
import { Registry } from '../server/state.js';
const here = dirname(fileURLToPath(import.meta.url));
const args = Object.fromEntries(process.argv.slice(2).map(a => a.replace(/^--/, '').split('=')));
const STAGE = args.stage ?? 'pool';
const DB_PATH = process.env.DB_PATH ?? join(here, '..', 'data', 'courtside.sqlite');
const store = new Store(DB_PATH);
const registry = new Registry(store);
if (registry.get('demo-labor-day-2s')) { console.log('Demo tournament already exists at /t/demo-labor-day-2s'); process.exit(0); }
const { t, engine } = registry.create({ slug: 'demo-labor-day-2s', name: 'Demo Labor Day 2s', date: '2026-09-07', courtCount: 2, rules: { teamSize: 2, pointsTo: 21, winBy: 2, cap: 25 }, notes: 'Demo data. Scores are made up.' });
const names = ['Net Gains', 'Block Party', 'Sunburnt', 'Dig It', 'Kiss My Ace', 'Setting Ducks', 'The Spikers', 'Sandbaggers', 'Serves You Right', 'Bump Chumps', 'Ace Holes', 'Beach Please'];
for (const n of names) t.registerTeam({ name: n, players: 2, captain: 'Captain' });
t.closeRegistration();
t.generatePools(4);
let clock = Date.now() - 90 * 60_000;
engine.now = () => clock; t.now = engine.now;
engine.start();
// play the first seven matches so there are standings, then leave two live with a running score
let seed = 11;
const rnd = () => ((seed = (seed * 1664525 + 1013904223) >>> 0) / 2 ** 32);
for (let i = 0; i < 7; i++) {
const c = engine.courts.find(c => c.matchId);
clock += (12 + rnd() * 6) * 60_000;
const hi = 21, lo = Math.floor(8 + rnd() * 12);
engine.recordResult(c.matchId, [rnd() < 0.5 ? [hi, lo] : [lo, hi]]);
}
if (STAGE !== 'pool') {
// finish pool play, build the bracket, decide a few bracket matches
while (engine.courts.some(c => c.matchId) && t.matches.filter(m => m.stage === 'pool' && m.status === 'pending').length + engine.courts.filter(c => c.matchId).length > 0) {
const c = engine.courts.find(c => c.matchId); if (!c) break;
clock += (12 + rnd() * 6) * 60_000;
const lo = Math.floor(8 + rnd() * 12);
engine.recordResult(c.matchId, [rnd() < 0.5 ? [21, lo] : [lo, 21]]);
}
const seeded = t.advanceFromPools({ perPool: 2, wildcards: 2 });
t.generateBracket(seeded, { type: STAGE === 'double' ? 'double' : 'single', thirdPlace: STAGE !== 'double' });
engine.tick();
for (let i = 0; i < (STAGE === 'double' ? 5 : 3); i++) {
const c = engine.courts.find(c => c.matchId); if (!c) break;
clock += (12 + rnd() * 6) * 60_000;
const lo = Math.floor(8 + rnd() * 12);
engine.recordResult(c.matchId, [rnd() < 0.5 ? [21, lo] : [lo, 21]]);
}
}
const live = engine.courts.filter(c => c.matchId).map(c => t.match(c.matchId));
if (live[0]) { live[0].live = [14, 11]; live[0].startedAt = Date.now() - 9 * 60_000; }
if (live[1]) { live[1].live = [7, 9]; live[1].startedAt = Date.now() - 5 * 60_000; }
for (const c of engine.courts) if (c.matchId) c.startedAt = t.match(c.matchId).startedAt;
t.banner = 'Demo tournament — scores are simulated';
engine.now = () => Date.now(); t.now = engine.now;
registry.persist(t.slug);
store.close();
console.log(`Seeded demo at /t/${t.slug}. Team codes: ${[...t.teams.values()].slice(0, 3).map(x => `${x.name}=${x.code}`).join(', ')}`);