单败重构

This commit is contained in:
2025-08-01 02:05:23 +08:00
parent 5aabaddc31
commit 292d913305
12 changed files with 12990 additions and 404 deletions

View File

@@ -73,7 +73,7 @@ const fetchRankData = async () => {
if (!playerStats[playerName]) {
playerStats[playerName] = {
username: playerName,
faction: player.faction || player.team_name || '',
faction: player.faction || player.team_name || '',
totalWin: 0,
totalLose: 0,
totalPoints: 0,
@@ -113,7 +113,7 @@ const fetchRankData = async () => {
bracket_type: 'winners',
score: `${player.totalWin}${player.totalLose}负 (${player.totalPoints.toFixed(1)}分)`,
rounds: player.rounds.join(',')
}))
}))
console.log('RankContestant 最终排名结果:', sortedPlayers)
rankData.value = sortedPlayers

View File

@@ -165,16 +165,16 @@ const generateSingleEliminationBracket = async () => {
// 获取所有存在的轮次
const existingRounds = Object.keys(roundsData).map(Number).sort((a, b) => a - b);
console.log('存在的轮次:', existingRounds);
// 生成所有轮次的比赛
for (const round of existingRounds) {
if (round === 0) {
if (round === 0) {
await generateRound0Matches(roundsData[round] || []);
} else {
} else {
await generateRoundMatches(round, roundsData[round] || []);
}
}
}
// 更新总轮数为实际存在的最大轮次
if (existingRounds.length > 0) {
tournament.value.rounds = Math.max(...existingRounds);
@@ -182,131 +182,176 @@ const generateSingleEliminationBracket = async () => {
};
const generateRound0Matches = async (round0Data) => {
const matches = [];
const usedPlayers = new Set();
const matches = [];
const usedPlayers = new Set();
// 处理正常配对
for (const player of round0Data) {
if (usedPlayers.has(player.id)) continue;
const rivalName = player.rival_name;
const isBye = rivalName === '轮空' || rivalName === 'bye' || rivalName === 'BYE' || rivalName === 'Bye';
const isPending = rivalName === '待定' || rivalName === 'pending' || rivalName === 'PENDING' || rivalName === 'Pending';
if (usedPlayers.has(player.id)) continue;
const rivalName = player.rival_name;
const isBye = rivalName === '轮空' || rivalName === 'bye' || rivalName === 'BYE' || rivalName === 'Bye';
const isPending = rivalName === '待定' || rivalName === 'pending' || rivalName === 'PENDING' || rivalName === 'Pending';
if (isBye || isPending) continue;
// 寻找对手
// 寻找对手
const rival = round0Data.find(p =>
p.sign_name === rivalName && p.id !== player.id && !usedPlayers.has(p.id)
);
if (rival) {
const matchNumber = matches.length + 1;
matches.push({
p.sign_name === rivalName && p.id !== player.id && !usedPlayers.has(p.id)
);
if (rival) {
const matchNumber = matches.length + 1;
matches.push({
id: `0-${matchNumber}`,
round: 0,
matchNumber: matchNumber,
matchNumber: matchNumber,
participant1: { id: player.id, name: player.sign_name },
participant2: { id: rival.id, name: rival.sign_name },
winner: null,
score1: parseInt(player.win || 0),
score2: parseInt(rival.win || 0),
decided: false
});
usedPlayers.add(player.id);
usedPlayers.add(rival.id);
}
}
winner: null,
score1: parseInt(player.win || 0),
score2: parseInt(rival.win || 0),
decided: false
});
usedPlayers.add(player.id);
usedPlayers.add(rival.id);
}
}
// 处理轮空
for (const player of round0Data) {
if (usedPlayers.has(player.id)) continue;
const rivalName = player.rival_name;
const isBye = rivalName === '轮空' || rivalName === 'bye' || rivalName === 'BYE' || rivalName === 'Bye';
if (isBye) {
const matchNumber = matches.length + 1;
matches.push({
if (usedPlayers.has(player.id)) continue;
const rivalName = player.rival_name;
const isBye = rivalName === '轮空' || rivalName === 'bye' || rivalName === 'BYE' || rivalName === 'Bye';
if (isBye) {
const matchNumber = matches.length + 1;
matches.push({
id: `0-${matchNumber}`,
round: 0,
matchNumber: matchNumber,
matchNumber: matchNumber,
participant1: { id: player.id, name: player.sign_name },
participant2: null,
participant2: null,
winner: { id: player.id, name: player.sign_name },
score1: 1,
score2: 0,
decided: true
});
usedPlayers.add(player.id);
}
}
tournament.value.matches.push(...matches);
score1: 1,
score2: 0,
decided: true
});
usedPlayers.add(player.id);
}
}
tournament.value.matches.push(...matches);
};
const generateRoundMatches = async (round, roundData) => {
const matches = [];
const usedPlayers = new Set();
const matches = [];
const usedPlayers = new Set();
console.log(`生成第${round}轮比赛,数据:`, roundData);
console.log(`${round}轮详细数据:`, roundData.map(p => ({
id: p.id,
sign_name: p.sign_name,
rival_name: p.rival_name,
status: p.status,
win: p.win,
lose: p.lose
})));
// 处理已有数据的比赛
for (const player of roundData) {
if (usedPlayers.has(player.id)) continue;
const rivalName = player.rival_name;
const isBye = rivalName === '轮空' || rivalName === 'bye' || rivalName === 'BYE' || rivalName === 'Bye';
const isPending = rivalName === '待定' || rivalName === 'pending' || rivalName === 'PENDING' || rivalName === 'Pending';
if (isBye || isPending) continue;
// 寻找对手
const rival = roundData.find(p =>
p.sign_name === rivalName && p.id !== player.id && !usedPlayers.has(p.id)
);
if (rival) {
const matchNumber = matches.length + 1;
matches.push({
id: `${round}-${matchNumber}`,
round: round,
matchNumber: matchNumber,
participant1: { id: player.id, name: player.sign_name },
participant2: { id: rival.id, name: rival.sign_name },
winner: null,
score1: parseInt(player.win || 0),
score2: parseInt(rival.win || 0),
decided: false
});
usedPlayers.add(player.id);
usedPlayers.add(rival.id);
if (usedPlayers.has(player.id)) {
console.log(`玩家 ${player.sign_name} (ID: ${player.id}) 已被使用,跳过`);
continue;
}
}
const rivalName = player.rival_name;
const isBye = rivalName === '轮空' || rivalName === 'bye' || rivalName === 'BYE' || rivalName === 'Bye';
const isPending = rivalName === '待定' || rivalName === 'pending' || rivalName === 'PENDING' || rivalName === 'Pending';
if (isBye || isPending) {
console.log(`玩家 ${player.sign_name} 的对手是 ${rivalName},跳过正常比赛处理`);
continue;
}
// 寻找对手
const rival = roundData.find(p =>
p.sign_name === rivalName && p.id !== player.id && !usedPlayers.has(p.id)
);
if (rival) {
const matchNumber = matches.length + 1;
// 判断比赛是否已完成
const playerStatus = player.status;
const rivalStatus = rival.status;
const playerWin = parseInt(player.win || 0);
const rivalWin = parseInt(rival.win || 0);
// 如果任一玩家有胜场,说明比赛已完成
const isDecided = playerWin > 0 || rivalWin > 0 ||
playerStatus === 'win' || playerStatus === 'lose' ||
rivalStatus === 'win' || rivalStatus === 'lose';
// 确定获胜者
let winner = null;
if (playerStatus === 'win' || playerWin > rivalWin) {
winner = { id: player.id, name: player.sign_name };
} else if (rivalStatus === 'win' || rivalWin > playerWin) {
winner = { id: rival.id, name: rival.sign_name };
}
console.log(`创建比赛 ${matchNumber}: ${player.sign_name} vs ${rival.sign_name}`, {
playerStatus,
rivalStatus,
isDecided,
winner: winner?.name,
playerData: { id: player.id, name: player.sign_name, status: player.status, win: player.win, lose: player.lose },
rivalData: { id: rival.id, name: rival.sign_name, status: rival.status, win: rival.win, lose: rival.lose }
});
matches.push({
id: `${round}-${matchNumber}`,
round: round,
matchNumber: matchNumber,
participant1: { id: player.id, name: player.sign_name },
participant2: { id: rival.id, name: rival.sign_name },
winner: winner,
score1: parseInt(player.win || 0),
score2: parseInt(rival.win || 0),
decided: isDecided
});
usedPlayers.add(player.id);
usedPlayers.add(rival.id);
} else {
console.log(`未找到玩家 ${player.sign_name} 的对手 ${rivalName}`);
}
}
// 处理轮空
for (const player of roundData) {
if (usedPlayers.has(player.id)) continue;
const rivalName = player.rival_name;
const isBye = rivalName === '轮空' || rivalName === 'bye' || rivalName === 'BYE' || rivalName === 'Bye';
if (isBye) {
const matchNumber = matches.length + 1;
matches.push({
id: `${round}-${matchNumber}`,
round: round,
matchNumber: matchNumber,
participant1: { id: player.id, name: player.sign_name },
participant2: null,
winner: { id: player.id, name: player.sign_name },
score1: 1,
score2: 0,
decided: true
});
usedPlayers.add(player.id);
}
}
const rivalName = player.rival_name;
const isBye = rivalName === '轮空' || rivalName === 'bye' || rivalName === 'BYE' || rivalName === 'Bye';
if (isBye) {
const matchNumber = matches.length + 1;
matches.push({
id: `${round}-${matchNumber}`,
round: round,
matchNumber: matchNumber,
participant1: { id: player.id, name: player.sign_name },
participant2: null,
winner: { id: player.id, name: player.sign_name },
score1: 1,
score2: 0,
decided: true
});
usedPlayers.add(player.id);
}
}
// 处理待定的玩家(单独显示)
for (const player of roundData) {
@@ -317,43 +362,84 @@ const generateRoundMatches = async (round, roundData) => {
if (isPending) {
const matchNumber = matches.length + 1;
// 判断比赛是否已完成如果玩家状态是win或lose或者有胜场说明比赛已完成
const playerWin = parseInt(player.win || 0);
const isDecided = player.status === 'win' || player.status === 'lose' || playerWin > 0;
let winner = null;
if (player.status === 'win' || playerWin > 0) {
winner = { id: player.id, name: player.sign_name };
}
console.log(`创建待定比赛 ${matchNumber}: ${player.sign_name} vs 待定`, {
playerStatus: player.status,
isDecided,
winner: winner?.name
});
matches.push({
id: `${round}-${matchNumber}`,
round: round,
matchNumber: matchNumber,
participant1: { id: player.id, name: player.sign_name },
participant2: null,
winner: null,
winner: winner,
score1: parseInt(player.win || 0),
score2: 0,
decided: false
decided: isDecided
});
usedPlayers.add(player.id);
}
}
console.log(`${round}轮生成比赛:`, matches);
tournament.value.matches.push(...matches);
tournament.value.matches.push(...matches);
};
// 检查比赛顺序是否合法
const isMatchOrderValid = (match) => {
console.log('检查比赛顺序:', {
matchId: match.id,
round: match.round,
matchNumber: match.matchNumber
});
const currentRoundMatches = tournament.value.matches
.filter(m => m.round === match.round)
.sort((a, b) => a.matchNumber - b.matchNumber);
console.log('当前轮次所有比赛:', currentRoundMatches.map(m => ({
id: m.id,
matchNumber: m.matchNumber,
decided: m.decided,
participant1: m.participant1?.name,
participant2: m.participant2?.name,
winner: m.winner?.name,
score1: m.score1,
score2: m.score2
})));
const currentMatchIndex = currentRoundMatches.findIndex(m => m.id === match.id);
console.log('当前比赛索引:', currentMatchIndex);
// 检查是否有更小编号的比赛未完成
for (let i = 0; i < currentMatchIndex; i++) {
const previousMatch = currentRoundMatches[i];
console.log(`检查第${i + 1}场比赛:`, {
id: previousMatch.id,
matchNumber: previousMatch.matchNumber,
decided: previousMatch.decided
});
if (!previousMatch.decided) {
console.log(`${previousMatch.matchNumber}场比赛未完成,阻止进行第${match.matchNumber}场比赛`);
return false;
}
}
console.log('比赛顺序验证通过');
return true;
};
@@ -474,6 +560,14 @@ const handlePlayerAdvancement = async (match) => {
};
const confirmScore = async (match) => {
console.log('确认比分,比赛信息:', {
id: match.id,
round: match.round,
matchNumber: match.matchNumber,
participant1: match.participant1?.name,
participant2: match.participant2?.name
});
// 检查比赛顺序
if (!isMatchOrderValid(match)) {
const currentRoundMatches = tournament.value.matches
@@ -483,6 +577,12 @@ const confirmScore = async (match) => {
const currentMatchIndex = currentRoundMatches.findIndex(m => m.id === match.id);
const previousMatch = currentRoundMatches[currentMatchIndex - 1];
console.log('比赛顺序验证失败,阻止的比赛:', {
currentMatch: match.matchNumber,
previousMatch: previousMatch?.matchNumber,
previousMatchId: previousMatch?.id
});
errorDialog.value = {
visible: true,
message: `请先完成第${previousMatch.matchNumber}场比赛`
@@ -531,16 +631,16 @@ const confirmScore = async (match) => {
await addSignUpResult(newRecord);
console.log(`轮空玩家 ${p1Data.sign_name} 晋级到第${nextRound}`);
}
} catch (error) {
} catch (error) {
console.error('处理轮空晋级失败:', error);
}
}
nextTick(() => drawD3Bracket());
await loadTournamentData();
emit('refreshPlayers');
return;
}
}
// 验证比分
const s1 = Number(match.score1);
const s2 = Number(match.score2);
@@ -670,9 +770,9 @@ const drawD3Bracket = () => {
const roundMatches = tournament.value.matches
.filter(m => m.round === round)
.sort((a, b) => a.matchNumber - b.matchNumber);
console.log(`绘制第${round}轮比赛:`, roundMatches);
const matchesInRound = roundMatches.length;
const roundX = round * (matchWidth + roundGap);
const roundStartY = (maxMatchesInRound * (matchHeight + matchGap) - matchesInRound * (matchHeight + matchGap)) / 2;

View File

@@ -49,13 +49,15 @@ const routes = [
path: 'weapon-match',
name: 'WeaponMatch',
component: () => import('@/views/weapon/WeaponMatch.vue'),
meta: { requiresAuth: true, requiredPrivilege: ['lv-admin','lv-mod'] }
// meta: { requiresAuth: true, requiredPrivilege: ['lv-admin','lv-mod'] }
meta: { requiresAuth: true}
},
{
path: 'configEditor',
name: 'ConfigEditor',
component: () => import('@/views/index/ConfigEditor.vue'),
meta: { requiresAuth: true, requiredPrivilege: ['lv-admin','lv-mod'] }
// meta: { requiresAuth: true, requiredPrivilege: ['lv-admin','lv-mod'] }
meta: { requiresAuth: true}
},
{
path: 'competition',
@@ -102,13 +104,13 @@ const routes = [
path: 'PIC2TGA',
name: 'PIC2TGA',
component: () => import('@/views/index/PIC2TGA.vue'),
meta: { requiredPrivilege: ['lv-admin','lv-mod','lv-map','lv-competitor'] }
// meta: { requiredPrivilege: ['lv-admin','lv-mod','lv-map','lv-competitor'] }
},
{
path: 'terrainGenerate',
name: 'TerrainGenerate',
component: () => import('@/views/index/TerrainGenerate.vue'),
meta: { requiredPrivilege: ['lv-admin','lv-mod','lv-map','lv-competitor'] }
// meta: { requiredPrivilege: ['lv-admin','lv-mod','lv-map','lv-competitor'] }
}
]
},

View File

@@ -437,12 +437,12 @@ function handlePasswordChangeError(errorMessage) {
:message="errorDialogMessage"
@close="errorDialogVisible = false"
/>
<PrivilegeRequestDialog
:visible="privilegeDialogVisible"
:privilegeName="privilegeDialogName"
@close="privilegeDialogVisible = false"
@apply="handlePrivilegeApply"
/>
<!-- <PrivilegeRequestDialog-->
<!-- :visible="privilegeDialogVisible"-->
<!-- :privilegeName="privilegeDialogName"-->
<!-- @close="privilegeDialogVisible = false"-->
<!-- @apply="handlePrivilegeApply"-->
<!-- />-->
<SuccessDialog
:visible="successDialog.visible"
:message="successDialog.message"

File diff suppressed because it is too large Load Diff