import type { BracketState, Candidate, ChoiceSide, Match } from './types'; export function buildMatches(pool: Candidate[]): Match[] { const matches: Match[] = []; for (let index = 0; index < pool.length; index += 2) { matches.push({ left: pool[index], right: pool[index + 1] || null, winner: pool[index + 1] ? null : pool[index] }); } return matches; } export function createBracket(candidates: Candidate[]): BracketState { return { round: 1, pool: [...candidates], matches: buildMatches(candidates), eliminated: [], decisions: [], offset: 0 }; } export function chooseMatch(state: BracketState, matchIndex: number, side: ChoiceSide): { state: BracketState; finished: boolean } { const match = state.matches[matchIndex]; if (!match?.right || match.winner) return { state, finished: false }; const winner = side === 'right' ? match.right : match.left; const loser = side === 'right' ? match.left : match.right; const matches = state.matches.map((item, index) => index === matchIndex ? { ...item, winner } : item ); let next = { ...state, matches, eliminated: [loser, ...state.eliminated], decisions: [...state.decisions, { round: state.round, left_id: match.left.id, right_id: match.right.id, winner_id: winner.id }] }; if (matches.every(item => item.winner)) { const pool = matches.map(item => item.winner).filter((item): item is Candidate => Boolean(item)); if (pool.length === 1) return { state: { ...next, pool }, finished: true }; next = { ...next, round: state.round + 1, pool, matches: buildMatches(pool), offset: 0 }; } return { state: next, finished: false }; } export function firstOpenMatch(state: BracketState): number { return state.matches.findIndex(match => match.right && !match.winner); }