I am making an eight team double-elimination tournament bracket and am currently working on the logic side of things.
I have eight teams and I am tracking their wins and losses. My goal is to separate teams with 0 losses (winners), 1 loss (losers), and 2 losses (eliminated-ers) – and create matchups within their category (teams with 0 losses would only play teams with 0 losses, teams with 1 loss would only play teams with 1 loss, and so on), until the championship which would obviously be between a “winner” team and a “loser” team with the first to 2 losses being eliminated.
I am currently thinking about using arrays to hold each category, but I don’t know if there is anything else out there that I can use so I am open to suggestions 🙂
Since wins and losses are determined by button clicks, I have a simple button program I created 🙂 (Currently it does have a bug where a team without a matchup after the first click is unclickable and considered undefined)
const teams = [{
name: "Chaos Coordinators",
wins: 0,
losses: 0
}, {
name: "Sofa King Awesome",
wins: 0,
losses: 0
}, {
name: "The Nerd Herd",
wins: 0,
losses: 0
}, {
name: "The Laughing Stock",
wins: 0,
losses: 0
}, {
name: "Brainy Bunch Gone Wild",
wins: 0,
losses: 0
}, {
name: "Cereal Killers",
wins: 0,
losses: 0
}, {
name: "Jimmie Crickets",
wins: 0,
losses: 0
}, {
name: "The Mismatched Socks",
wins: 0,
losses: 0
}];
// DOM helpers
const el = (sel, par = document) => par.querySelector(sel);
const elNew = (tag, prop) => Object.assign(document.createElement(tag), prop);
// App
const maxLosses = 2; // Max losses
const elTeamButtons = el("#team-buttons");
let winners = [];
let losers = [];
let eliminated = [];
const updateButton = (team) => {
console.log("Updating button for team:", team.name); // Log button update
const text = team.losses >= maxLosses ? "Eliminated" : `Wins: ${team.wins} - Losses: ${team.losses}`;
team.button.textContent = `${team.name} - ${text}`;
team.button.disabled = team.losses >= maxLosses;
team.button.classList.toggle("is-eliminated", team.losses >= maxLosses);
// Update color based on status
if (team.losses === 0) {
team.button.style.backgroundColor = "green"; // Winner
team.button.style.color = "white"; // Ensure text is visible
} else if (team.losses === 1) {
team.button.style.backgroundColor = "yellow"; // Loser
team.button.style.color = "black"; // Ensure text is visible
} else {
team.button.style.backgroundColor = "red"; // Eliminated
team.button.style.color = "white"; // Ensure text is visible
}
};
const updateScore = (team, win, loss) => {
console.log("Updating score for:", team.name); // Check if this logs correctly
team.wins += win;
team.losses += loss;
console.log("Wins:", team.wins, "Losses:", team.losses); // Log new values
updateButton(team);
if (team.opponent) {
team.opponent.losses += 1;
console.log("Opponent losses:", team.opponent.losses); // Log opponent's losses
updateButton(team.opponent);
}
groupTeams(teams);
makeMatches();
};
const groupTeams = (array) => {
winners = [];
losers = [];
eliminated = [];
array.forEach(team => {
if (team.losses === 0) {
winners.push(team);
} else if (team.losses === 1) {
losers.push(team);
} else {
eliminated.push(team);
}
});
console.log("Winners:", winners);
console.log("Losers:", losers);
console.log("Eliminated:", eliminated);
};
const makeMatches = () => {
elTeamButtons.innerHTML = ""; // Cleanup
console.log("Creating matches for:", winners, losers); // Log teams before creating buttons
const logMatches = (group) => {
group.forEach((team, i, teams) => {
team.opponent = teams[i + (i % 2 === 0 ? 1 : -1)];
if (i % 2 === 0) {
console.log(`Match: ${team.name} vs ${team.opponent.name}`);
}
});
};
// Create buttons for winners
winners.forEach((team, i, teams) => {
team.opponent = teams[i + (i % 2 === 0 ? 1 : -1)];
console.log("Creating button for winner:", team.name); // Log team info
team.button = elNew("button", {
className: "team-button",
onclick() {
console.log("Button clicked for team:", team.name); // Log button click
if (team.opponent) {
// Assume each button click represents a win for the clicked team and a loss for the opponent
updateScore(team, 1, 0); // 1 win, 0 loss for the clicked team
}
}
});
updateButton(team); // Initial button text
elTeamButtons.append(team.button);
});
// Create buttons for losers
losers.forEach((team, i, teams) => {
team.opponent = teams[i + (i % 2 === 0 ? 1 : -1)];
console.log("Creating button for loser:", team.name); // Log team info
team.button = elNew("button", {
className: "team-button",
onclick() {
console.log("Button clicked for team:", team.name); // Log button click
if (team.opponent) {
// Assume each button click represents a win for the clicked team and a loss for the opponent
updateScore(team, 1, 0); // 1 win, 0 loss for the clicked team
}
}
});
updateButton(team); // Initial button text
elTeamButtons.append(team.button);
});
// Log current matches and waiting teams
console.log("Current matches:");
logMatches(winners);
logMatches(losers);
const waitingTeams = winners.concat(losers).filter((_, i, teams) => i % 2 !== 0);
console.log("Teams waiting for a matchup:", waitingTeams.map(team => team.name));
};
// Function to Reset Teams to Initial State
function resetTeams() {
// Reset wins and losses to their initial state if needed
teams.forEach(team => {
team.wins = 0;
team.losses = 0;
});
// Recreate matches with updated state
groupTeams(teams);
makeMatches();
}
// Initialize and Setup Event Listeners
console.log("Initializing matches...");
groupTeams(teams);
makeMatches();
console.log("Matches initialized.");
el("#resetButton").addEventListener("click", resetTeams);
* {
margin: 0;
box-sizing: border-box;
}
#team-buttons {
position: relative;
border: 1px solid #888;
display: flex;
flex-flow: row wrap;
padding: 0.5em;
gap: 0.5em;
& .team-button {
flex: 0 0 calc(50% - 0.3em);
padding: 1em;
&.is-eliminated {
/* color: #f008; */
color: red;
cursor: not-allowed;
}
}
}
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Styled Buttons</title>
</head>
<body>
<button id="resetButton">RESET</button>
<div id="team-buttons"></div>
</body>
So I guess my question is three-fold:
What is the best way to separate the different types of teams (eliminated-ers, winners, and losers)?
What is the best way to push these types of teams into “rounds” based on the combined number of wins and losses (so I can have separate rules for a championship)?
And finally, am I going about this completely the wrong way? Any programming concepts I should look in to?
P.S. please please please do not write code for me. I am just starting programming and I want to learn 🙂 so any nudge in the right direction whether it be documentation or other posts on the overflow or any other resources would be greatly appreciated 🙂 this post has no intention of fleecing answers off of people.