<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Tournament Bracket</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="round-indicator">Round: <span id="roundNumber">1</span></div>
<div class="tournament-container">
<div class="vertical-section" id="leftSection"></div>
<div class="vertical-section" id="rightSection"></div>
</div>
<div class="final-round" id="finalRound"></div>
<div class="controls">
<button id="nextRoundBtn" class="next-round-btn">Next Round</button>
</div>
<div class="winner-screen" id="winnerScreen">
<h1 class="winner-title">Tournament Winner!</h1>
<div class="winner-color" id="winnerColor"></div>
</div>
<script src="index.js"></script>
</body>
</html>
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
min-height: 100vh;
background-color: #1a1a1a;
color: #ffffff;
padding: 20px;
font-family: Arial, sans-serif;
margin: 0 auto;
width: 100%;
}
.tournament-container {
display: flex;
gap: 40px;
margin-bottom: 20px;
justify-content: center;
}
.vertical-section {
display: flex;
flex-direction: column;
justify-content: space-around;
gap: 20px;
}
.matchup {
display: flex;
align-items: center;
background: #2d2d2d;
padding: 10px;
box-shadow: 0 2px 5px rgba(0,0,0,0.3);
}
.participant {
width: 50px;
height: 50px;
transition: all 0.3s ease;
}
.vs {
margin: 0 10px;
font-weight: bold;
color: #ffffff;
}
.winner {
transform: scale(1.1);
box-shadow: 0 0 10px rgba(0,0,0,0.5);
}
.controls {
margin-top: 20px;
}
.next-round-btn {
padding: 10px 20px;
font-size: 16px;
background-color: #4CAF50;
color: white;
border: none;
cursor: pointer;
transition: background-color 0.3s;
}
.next-round-btn:hover {
background-color: #45a049;
}
.next-round-btn:disabled {
background-color: #333333;
cursor: not-allowed;
}
.round-indicator {
margin-bottom: 20px;
font-size: 24px;
color: #ffffff;
text-align: center;
}
.winner-screen {
display: none;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0,0,0,0.9);
justify-content: center;
align-items: center;
flex-direction: column;
gap: 20px;
z-index: 1000;
}
.winner-screen.active {
display: flex;
}
.winner-title {
font-size: 32px;
color: #ffffff;
text-align: center;
}
.winner-color {
width: 100px;
height: 100px;
margin: 20px;
}
.final-round {
display: flex;
justify-content: center;
margin-top: 20px;
}
.restart-btn {
padding: 10px 20px;
font-size: 16px;
margin-top: 20px;
cursor: pointer;
background-color: #4CAF50;
color: white;
border: none;
border-radius: 4px;
}
.restart-btn:hover {
background-color: #45a049;
}
class Tournament {
constructor() {
this.colors = ['green', 'red', 'blue', 'yellow'];
this.currentRound = 1;
this.matches = [];
this.usedColors = [];
this.init();
}
init() {
this.createMatches();
this.render();
this.setupControls();
}
createMatches() {
this.matches = [];
this.usedColors = []; // Reset used colors for each round
const matchCount = this.currentRound === 1 ? 8 : Math.pow(2, 4 - this.currentRound);
for (let i = 0; i < matchCount; i++) {
let player1Color = this.getUniqueColor();
let player2Color = this.getUniqueColor(player1Color); // Ensure player 2 gets a unique color
this.matches.push({
player1: { color: player1Color },
player2: { color: player2Color }
});
}
}
getUniqueColor(excludeColor = null) {
let availableColors = this.colors.filter(color => !this.usedColors.includes(color) && color !== excludeColor);
if (availableColors.length === 0) {
// Reset the used colors and try again if there are no more available colors
this.usedColors = [];
availableColors = this.colors.filter(color => color !== excludeColor);
}
const color = availableColors[Math.floor(Math.random() * availableColors.length)];
this.usedColors.push(color);
return color;
}
progressRound() {
if (this.matches.length === 1) {
this.showWinner(this.matches[0].player1.color);
return;
}
this.currentRound++;
this.createMatches();
this.render();
if (this.matches.length === 1) {
this.showFinalRound();
}
}
render() {
document.getElementById('roundNumber').textContent = this.currentRound;
const left = document.getElementById('leftSection');
const right = document.getElementById('rightSection');
left.innerHTML = '';
right.innerHTML = '';
if (this.matches.length > 1) {
const half = this.matches.length / 2;
this.matches.forEach((match, i) => {
const el = this.createMatchElement(match);
(i < half ? left : right).appendChild(el);
});
}
}
createMatchElement(match) {
return createElement('div', 'matchup', [
createElement('div', 'participant', [], match.player1.color),
createElement('span', 'vs', ['VS']),
createElement('div', 'participant', [], match.player2.color)
]);
}
showFinalRound() {
const match = this.matches[0];
document.getElementById('finalRound').innerHTML = this.createMatchElement(match).outerHTML;
}
showWinner(color) {
const screen = document.getElementById('winnerScreen');
screen.innerHTML = `
<h1 class="winner-title">Tournament Winner!</h1>
<div class="winner-color" style="background-color: ${color}"></div>
<button id="restartBtn">Restart Tournament</button>
`;
screen.classList.add('active');
document.getElementById('nextRoundBtn').disabled = true;
document.getElementById('restartBtn').onclick = () => this.restart();
}
restart() {
this.currentRound = 1;
document.getElementById('winnerScreen').classList.remove('active');
document.getElementById('nextRoundBtn').disabled = false;
document.getElementById('finalRound').innerHTML = '';
this.init();
}
setupControls() {
const btn = document.getElementById('nextRoundBtn');
btn.replaceWith(btn.cloneNode(true));
document.getElementById('nextRoundBtn').onclick = () => this.progressRound();
}
}
// Helper function to create DOM elements
function createElement(tag, className, children = [], backgroundColor = null) {
const el = document.createElement(tag);
el.className = className;
if (backgroundColor) el.style.backgroundColor = backgroundColor;
children.forEach(child => {
if (typeof child === 'string') el.textContent = child;
else el.appendChild(child);
});
return el;
}
new Tournament();