Average player age at registration; age-matched round 1 for bracket-only tournaments
Optional age on signup and the desk. Auto-generated brackets pair neighbours by age with byes spread down the sheet; teams without an age are placed at random, fully random when no ages exist. Release 0.6.0. Co-Authored-By: Claude Fable 5.1 <[email protected]> Claude-Session: https://claude.ai/code/session_01MB7nCCAscYsb3zzkT6LHZi
This commit is contained in:
1 parent
3f60a39e45
commit
103c221a12
10 files changed
+114
-19
No files matched your search
+11
-5
@@ -42,7 +42,7 @@ export function buildRouter({ registry, auth, store }) {
|
||||
try {
|
||||
const team = registry.mutate(slug, t => t.registerTeam({
|
||||
name: body.name, captain: String(body.captain ?? '').trim().slice(0, 60), phone: String(body.phone ?? '').trim().slice(0, 30),
|
||||
players: body.players, playerNames: String(body.playerNames ?? '').split('\n').map(s => s.trim()).filter(Boolean).slice(0, 20),
|
||||
players: body.players, avgAge: body.avgAge, playerNames: String(body.playerNames ?? '').split('\n').map(s => s.trim()).filter(Boolean).slice(0, 20),
|
||||
}));
|
||||
send.redirect(res, `/t/${slug}/team/${team.code}?new=1`);
|
||||
} catch (e) {
|
||||
@@ -176,10 +176,16 @@ export function buildRouter({ registry, auth, store }) {
|
||||
const res = t.generateBracketFromPairs(pairs, { type: body.type === 'double' ? 'double' : 'single', thirdPlace: !!body.thirdPlace });
|
||||
return `${body.type === 'double' ? 'Double' : 'Single'} elimination bracket of ${res.size} built from your pairings`;
|
||||
}
|
||||
const opts = { type: body.type === 'double' ? 'double' : 'single', thirdPlace: !!body.thirdPlace };
|
||||
if (!t.pools.length && body.byAge) {
|
||||
if (t.activeTeams().length < 2) throw new Error('Need at least two teams');
|
||||
const res = t.generateBracketFromPairs(t.pairsByAge(), opts);
|
||||
return `${opts.type === 'double' ? 'Double' : 'Single'} elimination bracket of ${res.size} generated; ${t.hasAges() ? 'round 1 matched by similar average age (teams without an age placed at random)' : 'no ages were given, so round 1 is random'}`;
|
||||
}
|
||||
const seeded = t.pools.length ? t.advanceFromPools({ perPool: +body.perPool || 2, wildcards: +body.wildcards || 0 }) : t.activeTeams().map(x => x.id);
|
||||
if (seeded.length < 2) throw new Error('Need at least two teams');
|
||||
const res = t.generateBracket(seeded, { type: body.type === 'double' ? 'double' : 'single', thirdPlace: !!body.thirdPlace });
|
||||
return `${body.type === 'double' ? 'Double' : 'Single'} elimination bracket of ${res.size} generated with ${seeded.length} teams`;
|
||||
const res = t.generateBracket(seeded, opts);
|
||||
return `${opts.type === 'double' ? 'Double' : 'Single'} elimination bracket of ${res.size} generated with ${seeded.length} teams`;
|
||||
});
|
||||
action('/regenerate', ({ t }) => { if (t.matches.some(m => ['final', 'forfeit'].includes(m.status))) throw new Error('Scores already entered'); t.matches = []; t.pools = []; for (const x of t.teams.values()) x.poolId = null; if (t.phase === 'live') t.phase = 'closed'; t.emit({ type: 'play_cleared' }); return 'Generated play cleared'; });
|
||||
action('/score', ({ t, engine, body, who }) => {
|
||||
@@ -197,10 +203,10 @@ export function buildRouter({ registry, auth, store }) {
|
||||
action('/pushback', ({ engine, body }) => { engine.pushBack(body.match, 2); return 'Pushed back'; });
|
||||
action('/court', ({ engine, body }) => { if (body.op === 'pause') engine.pauseCourt(+body.court, String(body.reason ?? '').slice(0, 60)); else engine.resumeCourt(+body.court); return `Court ${body.court} ${body.op}d`; });
|
||||
action('/team', ({ t, body }) => {
|
||||
if (body.op === 'add') { const team = t.registerTeam({ name: body.name, captain: body.captain, players: body.players }, { force: true }); return `Added ${team.name} (code ${team.code})`; }
|
||||
if (body.op === 'add') { const team = t.registerTeam({ name: body.name, captain: body.captain, players: body.players, avgAge: body.avgAge }, { force: true }); return `Added ${team.name} (code ${team.code})`; }
|
||||
if (body.op === 'remove') { t.removeTeam(body.id); return 'Team removed'; }
|
||||
if (body.op === 'seed') { const list = t.activeTeams().filter(x => x.id !== body.id); list.splice(Math.max(0, +body.seed - 1), 0, t.teams.get(body.id)); t.setSeeds(list.map(x => x.id)); return 'Seeds updated'; }
|
||||
t.updateTeam(body.id, { name: body.name, captain: body.captain, players: body.players }); return 'Team saved';
|
||||
t.updateTeam(body.id, { name: body.name, captain: body.captain, players: body.players, avgAge: body.avgAge }); return 'Team saved';
|
||||
});
|
||||
action('/withdraw', ({ t, engine, body, who }) => { const team = t.teams.get(body.id); if (!team) throw new Error('No such team'); if (t.phase === 'live') engine.withdrawTeam(body.id, { mode: body.mode, actor: who }); else t.withdrawTeam(body.id, { mode: body.mode, actor: who }); return `${team.name} withdrawn (${body.mode})`; });
|
||||
r.post('/admin/t/:slug/delete', async (req, res, { slug }) => {
|
||||
|
||||
Reference in new issue
Block a user