diff --git a/src/components/TournamentBracket.vue b/src/components/TournamentBracket.vue index b87c909..6b6916f 100644 --- a/src/components/TournamentBracket.vue +++ b/src/components/TournamentBracket.vue @@ -180,7 +180,6 @@ const generateSingleEliminationBracket = async () => { const totalPlayers = Math.pow(2, tournament.value.rounds); const shuffled = [...tournament.value.participants].sort(() => Math.random() - 0.5); - // 获取最新的报名数据 const latestData = await getSignUpResultList(); const filteredData = latestData.filter(item => item.tournament_id == tournament.value.id); @@ -189,21 +188,25 @@ const generateSingleEliminationBracket = async () => { } // 生成第一轮比赛 - const firstRoundMatches = totalPlayers / 2; - for (let i = 0; i < firstRoundMatches; i++) { + const firstRoundMatchesCount = totalPlayers / 2; + for (let i = 0; i < firstRoundMatchesCount; i++) { const p1 = shuffled[i * 2]; const p2 = shuffled[i * 2 + 1]; let winner = null; let decided = false; - if (p1 && !p2) { + + if (p1 && !p2) { // p1 gets a bye winner = p1; decided = true; - } else if (!p1 && p2) { + } else if (!p1 && p2) { // p2 gets a bye winner = p2; decided = true; + } else if (!p1 && !p2) { // double bye + winner = null; // Winner is null for a double bye + decided = true; } + // If p1 && p2, winner is null, decided is false (normal match) - // 获取选手的最新数据 const p1Latest = p1 ? filteredData.find(item => item.id === p1.id) : null; const p2Latest = p2 ? filteredData.find(item => item.id === p2.id) : null; @@ -214,9 +217,10 @@ const generateSingleEliminationBracket = async () => { participant1: p1, participant2: p2, winner, - score1: decided && p1 && !p2 ? 1 : (p1Latest?.win || 0), - score2: decided && !p1 && p2 ? 1 : (p2Latest?.win || 0), - decided + score1: decided && winner === p1 ? 1 : (p1Latest?.win || 0), // Score 1 for bye winner, else existing or 0 + score2: decided && winner === p2 ? 1 : (p2Latest?.win || 0), // Score 1 for bye winner, else existing or 0 + decided, + // participantXResolved flags are not needed for round 1 matches as they are resolved by definition or play }); } @@ -228,8 +232,10 @@ const generateSingleEliminationBracket = async () => { id: `${r}-${i + 1}`, round: r, matchNumber: i + 1, - participant1: null, - participant2: null, + participant1: null, // Placeholder, will be filled by previous round's winner + participant2: null, // Placeholder + participant1Resolved: false, // New flag + participant2Resolved: false, // New flag winner: null, score1: null, score2: null, @@ -237,6 +243,14 @@ const generateSingleEliminationBracket = async () => { }); } } + + // 处理第一轮中的轮空晋级 + const firstRoundActualMatches = tournament.value.matches.filter(m => m.round === 1); + for (const match of firstRoundActualMatches) { + if (match.decided) { // If the match was decided (bye, double bye) + updateNextRound(match); // Propagate its result (winner could be player or null) + } + } }; const drawConnections = () => { @@ -357,37 +371,72 @@ async function confirmScore(match) { emit('refreshPlayers'); } -const updateNextRound = (match) => { - if (!match.decided) return; - - if (match.round === tournament.value.rounds) { +const updateNextRound = (currentDecidedMatch) => { + if (!currentDecidedMatch.decided) { // Winner can be null (e.g. double bye) + console.warn("updateNextRound called on non-decided match", currentDecidedMatch); return; } - const nextRound = match.round + 1; - const nextMatchIndex = Math.floor((match.matchNumber - 1) / 2); - const nextMatch = tournament.value.matches.find(m => m.round === nextRound && m.matchNumber === nextMatchIndex + 1); - - if (!nextMatch) return; - - if ((match.matchNumber - 1) % 2 === 0) { - nextMatch.participant1 = match.winner; - } else { - nextMatch.participant2 = match.winner; + if (currentDecidedMatch.round === tournament.value.rounds) { + return; // This was the final match or a match in the final round } - if ((nextMatch.participant1 && !nextMatch.participant2) || (!nextMatch.participant1 && nextMatch.participant2)) { - nextMatch.winner = nextMatch.participant1 || nextMatch.participant2; - nextMatch.score1 = nextMatch.participant1 ? 1 : 0; - nextMatch.score2 = nextMatch.participant2 ? 1 : 0; - nextMatch.decided = true; - updateNextRound(nextMatch); - } else { - nextMatch.winner = null; - nextMatch.score1 = null; - nextMatch.score2 = null; - nextMatch.decided = false; + const nextRound = currentDecidedMatch.round + 1; + const nextMatchIndexInRound = Math.floor((currentDecidedMatch.matchNumber - 1) / 2); + const nextMatch = tournament.value.matches.find(m => m.round === nextRound && m.matchNumber === nextMatchIndexInRound + 1); + + if (!nextMatch) { + console.error("Could not find next match for", currentDecidedMatch); + return; } + + const isFeederForParticipant1 = (currentDecidedMatch.matchNumber - 1) % 2 === 0; + + if (isFeederForParticipant1) { + nextMatch.participant1 = currentDecidedMatch.winner; // Winner might be null + nextMatch.participant1Resolved = true; + } else { + nextMatch.participant2 = currentDecidedMatch.winner; // Winner might be null + nextMatch.participant2Resolved = true; + } + + // Only proceed if both participant slots for nextMatch are resolved + if (nextMatch.participant1Resolved && nextMatch.participant2Resolved) { + const p1 = nextMatch.participant1; + const p2 = nextMatch.participant2; + + if (p1 && !p2) { // p1 advances due to p2 being a bye (null) + nextMatch.winner = p1; + nextMatch.score1 = 1; // Convention for bye win + nextMatch.score2 = 0; + nextMatch.decided = true; + } else if (!p1 && p2) { // p2 advances due to p1 being a bye (null) + nextMatch.winner = p2; + nextMatch.score1 = 0; + nextMatch.score2 = 1; // Convention for bye win + nextMatch.decided = true; + } else if (!p1 && !p2) { // Double bye in this nextMatch + nextMatch.winner = null; // No winner advances + nextMatch.score1 = 0; + nextMatch.score2 = 0; + nextMatch.decided = true; // This "match" is decided as a double bye + } else if (p1 && p2) { // Both participants are actual players, match is ready to be played + nextMatch.winner = null; + nextMatch.score1 = null; // Or 0, depending on display preference for undecided matches + nextMatch.score2 = null; // Or 0 + nextMatch.decided = false; + } else { + // This case should ideally not be reached if logic is correct + console.warn("Unexpected state in updateNextRound for nextMatch:", nextMatch); + nextMatch.decided = false; // Default to not decided to prevent erroneous propagation + } + + // If nextMatch itself was decided (due to byes), propagate its result further + if (nextMatch.decided) { + updateNextRound(nextMatch); + } + } + // If only one participant is resolved, wait for the other feeder match to complete. }; const calculateFinalRanking = () => {