Files
codex-bot 5051466692
Verify mini program and deploy preview / verify-deploy (push) Successful in 3m9s
feat: redesign typed bracket poster editor
2026-09-20 16:37:35 +08:00

56 lines
1.8 KiB
TypeScript

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);
}