|
|
|
@ -50,7 +50,10 @@ function renderBracket() { |
|
|
|
bracket.appendChild(firstMatch); |
|
|
|
bracket.appendChild(firstMatch); |
|
|
|
const matchHeight = firstMatch.offsetHeight; |
|
|
|
const matchHeight = firstMatch.offsetHeight; |
|
|
|
const matchSpacing = 10; |
|
|
|
const matchSpacing = 10; |
|
|
|
|
|
|
|
const baseDistance = matchHeight + matchSpacing; |
|
|
|
bracket.innerHTML = ''; |
|
|
|
bracket.innerHTML = ''; |
|
|
|
|
|
|
|
const roundCount = rounds.length; |
|
|
|
|
|
|
|
const finalRoundIndex = (roundCount - 1) / 2; |
|
|
|
|
|
|
|
|
|
|
|
rounds.forEach((roundMatches, roundIndex) => { |
|
|
|
rounds.forEach((roundMatches, roundIndex) => { |
|
|
|
const roundDiv = document.createElement('div'); |
|
|
|
const roundDiv = document.createElement('div'); |
|
|
|
@ -63,19 +66,74 @@ function renderBracket() { |
|
|
|
matchDiv.style.position = 'absolute'; |
|
|
|
matchDiv.style.position = 'absolute'; |
|
|
|
const isDisabled = matchTemplate.dataset.disabled === 'true'; |
|
|
|
const isDisabled = matchTemplate.dataset.disabled === 'true'; |
|
|
|
let top; |
|
|
|
let top; |
|
|
|
if (roundIndex === 0) { |
|
|
|
let left; |
|
|
|
|
|
|
|
let right; |
|
|
|
|
|
|
|
let nextMatchDistance = baseDistance; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Check if this round has only one match |
|
|
|
|
|
|
|
const isSingleMatchRound = roundMatches.length === 1; |
|
|
|
|
|
|
|
if (isSingleMatchRound) { |
|
|
|
|
|
|
|
matchDiv.classList.add('single-match-round'); |
|
|
|
|
|
|
|
nextMatchDistance = 0; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (roundIndex === 0 || roundIndex === rounds.length - 1) { |
|
|
|
top = matchIndex * (matchHeight + matchSpacing); |
|
|
|
top = matchIndex * (matchHeight + matchSpacing); |
|
|
|
|
|
|
|
if (roundIndex === rounds.length - 1) { |
|
|
|
|
|
|
|
nextMatchDistance = baseDistance * Math.pow(2, rounds.length - roundIndex - 1); |
|
|
|
|
|
|
|
matchDiv.classList.add('reverse-bracket'); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
const previousRoundMatches = rounds[roundIndex - 1].length; |
|
|
|
|
|
|
|
const currentRoundMatches = roundMatches.length; |
|
|
|
|
|
|
|
if (currentRoundMatches === previousRoundMatches || roundIndex == finalRoundIndex + 1) { |
|
|
|
|
|
|
|
// Same number of matches as previous round |
|
|
|
|
|
|
|
top = matchPositions[roundIndex - 2][matchIndex]; |
|
|
|
|
|
|
|
nextMatchDistance = 0; |
|
|
|
|
|
|
|
} else if (roundIndex == finalRoundIndex) { |
|
|
|
|
|
|
|
top = matchPositions[roundIndex - 3][1 + matchIndex]; |
|
|
|
|
|
|
|
nextMatchDistance = baseDistance; |
|
|
|
|
|
|
|
} else if (currentRoundMatches > previousRoundMatches) { |
|
|
|
|
|
|
|
// Bracket is reversed - matches are splitting instead of combining |
|
|
|
|
|
|
|
const parentIndex = Math.floor(matchIndex / 2); |
|
|
|
|
|
|
|
if (parentIndex < matchPositions[roundIndex - 1].length) { |
|
|
|
|
|
|
|
const parentPos = matchPositions[roundIndex - 1][parentIndex]; |
|
|
|
|
|
|
|
// Calculate offset based on whether it's an even or odd match |
|
|
|
|
|
|
|
const offset = (matchIndex % 2 === 0) ? -baseDistance : baseDistance; |
|
|
|
|
|
|
|
top = parentPos + offset; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
nextMatchDistance = baseDistance * Math.pow(2, rounds.length - roundIndex - 1); |
|
|
|
|
|
|
|
matchDiv.classList.add('reverse-bracket'); |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
|
|
|
|
// Normal case where matches are combining |
|
|
|
const parentIndex1 = matchIndex * 2; |
|
|
|
const parentIndex1 = matchIndex * 2; |
|
|
|
const parentIndex2 = parentIndex1 + 1; |
|
|
|
const parentIndex2 = parentIndex1 + 1; |
|
|
|
const parentPos1 = matchPositions[roundIndex - 1][parentIndex1]; |
|
|
|
const parentPos1 = matchPositions[roundIndex - 1][parentIndex1]; |
|
|
|
const parentPos2 = matchPositions[roundIndex - 1][parentIndex2]; |
|
|
|
const parentPos2 = matchPositions[roundIndex - 1][parentIndex2]; |
|
|
|
top = (parentPos1 + parentPos2) / 2; |
|
|
|
top = (parentPos1 + parentPos2) / 2; |
|
|
|
|
|
|
|
nextMatchDistance = !isSingleMatchRound ? baseDistance * Math.pow(2, roundIndex) : 0; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
const baseDistance = matchHeight + matchSpacing; |
|
|
|
if (roundIndex >= finalRoundIndex - 1) { |
|
|
|
const distance = baseDistance * Math.pow(2, roundIndex); |
|
|
|
matchDiv.style.transform = `translateX(-50%)`; |
|
|
|
matchDiv.style.setProperty('--next-match-distance', `${distance}px`); |
|
|
|
if (roundIndex >= finalRoundIndex + 2) { |
|
|
|
|
|
|
|
matchDiv.style.transform = `translateX(-100%)`; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (roundIndex == finalRoundIndex - 1) { |
|
|
|
|
|
|
|
matchDiv.classList.add('inward'); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (roundIndex == finalRoundIndex + 1) { |
|
|
|
|
|
|
|
matchDiv.classList.add('outward'); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (roundIndex == 1 || roundIndex == roundCount - 2) { |
|
|
|
|
|
|
|
nextMatchDistance = nextMatchDistance / 2; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
matchDiv.style.setProperty('--next-match-distance', `${nextMatchDistance}px`); |
|
|
|
matchDiv.style.top = `${top}px`; |
|
|
|
matchDiv.style.top = `${top}px`; |
|
|
|
matchPositions[roundIndex][matchIndex] = top; |
|
|
|
matchPositions[roundIndex][matchIndex] = top; |
|
|
|
|
|
|
|
|
|
|
|
@ -84,6 +142,19 @@ function renderBracket() { |
|
|
|
<div class="match-content ${isDisabled ? 'disabled' : ''}">${matchTemplate.innerHTML}</div> |
|
|
|
<div class="match-content ${isDisabled ? 'disabled' : ''}">${matchTemplate.innerHTML}</div> |
|
|
|
`; |
|
|
|
`; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (roundIndex == finalRoundIndex - 1) { |
|
|
|
|
|
|
|
const matchDiv2 = document.createElement('div'); |
|
|
|
|
|
|
|
matchDiv2.className = 'butterfly-match'; |
|
|
|
|
|
|
|
matchDiv2.style.position = 'absolute'; |
|
|
|
|
|
|
|
matchDiv2.style.transform = `translateX(-50%)`; |
|
|
|
|
|
|
|
matchDiv2.classList.add('inward'); |
|
|
|
|
|
|
|
matchDiv2.classList.add('semi-final'); |
|
|
|
|
|
|
|
matchDiv2.style.setProperty('--next-match-distance', `${baseDistance}px`); |
|
|
|
|
|
|
|
matchDiv2.style.top = `${top}px`; |
|
|
|
|
|
|
|
matchDiv2.innerHTML = ` |
|
|
|
|
|
|
|
`; |
|
|
|
|
|
|
|
roundDiv.appendChild(matchDiv2); |
|
|
|
|
|
|
|
} |
|
|
|
roundDiv.appendChild(matchDiv); |
|
|
|
roundDiv.appendChild(matchDiv); |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
@ -95,6 +166,13 @@ function renderBracket() { |
|
|
|
</script> |
|
|
|
</script> |
|
|
|
|
|
|
|
|
|
|
|
<style> |
|
|
|
<style> |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.butterfly-match.same-level::before { |
|
|
|
|
|
|
|
display: none; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Adjust styling for matches with single parent */ |
|
|
|
.match-content.disabled { |
|
|
|
.match-content.disabled { |
|
|
|
visibility: hidden; |
|
|
|
visibility: hidden; |
|
|
|
} |
|
|
|
} |
|
|
|
@ -113,7 +191,8 @@ function renderBracket() { |
|
|
|
|
|
|
|
|
|
|
|
.butterfly-round { |
|
|
|
.butterfly-round { |
|
|
|
position: relative; |
|
|
|
position: relative; |
|
|
|
width: 25%; /* 300px for match + 20px on each side for lines */ |
|
|
|
width: 15%; /* 300px for match + 20px on each side for lines */ |
|
|
|
|
|
|
|
flex-shrink: 0; /* Prevents rounds from shrinking */ |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
.butterfly-match { |
|
|
|
.butterfly-match { |
|
|
|
@ -132,6 +211,16 @@ function renderBracket() { |
|
|
|
background: #666; |
|
|
|
background: #666; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.semi-final::after { |
|
|
|
|
|
|
|
content: ""; |
|
|
|
|
|
|
|
position: absolute; |
|
|
|
|
|
|
|
left: calc(100% + 20px); /* After horizontal line */ |
|
|
|
|
|
|
|
top: -4px; |
|
|
|
|
|
|
|
width: 2px; |
|
|
|
|
|
|
|
height: calc(var(--next-match-distance)); |
|
|
|
|
|
|
|
background: #666; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* Vertical line connecting pair of matches */ |
|
|
|
/* Vertical line connecting pair of matches */ |
|
|
|
.butterfly-match:nth-child(2n+1)::before { |
|
|
|
.butterfly-match:nth-child(2n+1)::before { |
|
|
|
content: ""; |
|
|
|
content: ""; |
|
|
|
@ -153,6 +242,27 @@ function renderBracket() { |
|
|
|
background: #666; |
|
|
|
background: #666; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Vertical line connecting pair of matches */ |
|
|
|
|
|
|
|
.butterfly-match.reverse-bracket:nth-child(2n+1)::before { |
|
|
|
|
|
|
|
content: ""; |
|
|
|
|
|
|
|
position: absolute; |
|
|
|
|
|
|
|
left: calc(0% - 20px); /* After horizontal line */ |
|
|
|
|
|
|
|
top: calc(50% + 2px); |
|
|
|
|
|
|
|
width: 2px; |
|
|
|
|
|
|
|
height: calc((var(--next-match-distance)) / 2); |
|
|
|
|
|
|
|
background: #666; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.butterfly-match.reverse-bracket:nth-child(2n)::before { |
|
|
|
|
|
|
|
content: ""; |
|
|
|
|
|
|
|
position: absolute; |
|
|
|
|
|
|
|
left: calc(0% - 20px); |
|
|
|
|
|
|
|
bottom: 50%; /* Account for half of horizontal line height */ |
|
|
|
|
|
|
|
width: 2px; |
|
|
|
|
|
|
|
height: calc((var(--next-match-distance)) / 2); /* Add half of horizontal line height */ |
|
|
|
|
|
|
|
background: #666; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* Horizontal line to next round match */ |
|
|
|
/* Horizontal line to next round match */ |
|
|
|
.butterfly-match .incoming-line { |
|
|
|
.butterfly-match .incoming-line { |
|
|
|
position: absolute; |
|
|
|
position: absolute; |
|
|
|
@ -163,17 +273,18 @@ function renderBracket() { |
|
|
|
background: #666; |
|
|
|
background: #666; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* Hide incoming line for first round */ |
|
|
|
.inward .incoming-line { |
|
|
|
.butterfly-round:first-child .incoming-line { |
|
|
|
|
|
|
|
display: none; |
|
|
|
display: none; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* Hide outgoing lines for last round */ |
|
|
|
.butterfly-match.outward::after { |
|
|
|
.butterfly-round:last-child .butterfly-match::after, |
|
|
|
|
|
|
|
.butterfly-round:last-child .butterfly-match::before { |
|
|
|
|
|
|
|
display: none; |
|
|
|
display: none; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.butterfly-round:last-child .butterfly-match::after, |
|
|
|
|
|
|
|
.butterfly-round:first-child .incoming-line { |
|
|
|
|
|
|
|
display: none; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
</style> |
|
|
|
</style> |
|
|
|
|
|
|
|
|
|
|
|
|