You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
417 lines
14 KiB
417 lines
14 KiB
{% extends 'tournaments/base.html' %}
|
|
|
|
{% block head_title %}Matchs du {{ tournament.display_name }}{% endblock %}
|
|
{% block first_title %}{{ tournament.event.display_name }}{% endblock %}
|
|
{% block second_title %}{{ tournament.display_name }}{% endblock %}
|
|
|
|
{% block content %}
|
|
|
|
{% if tournament.display_matches %}
|
|
{% include 'tournaments/navigation_tournament.html' %}
|
|
|
|
<div class="butterfly-bracket" id="bracket"></div>
|
|
|
|
<div id="match-templates" style="display: none;">
|
|
{% for match_group in match_groups %}
|
|
{% if match_group.matches %}
|
|
{% for match in match_group.matches %}
|
|
<div data-match-round="{{ forloop.parentloop.counter0 }}"
|
|
data-match-index="{{ forloop.counter0 }}"
|
|
data-disabled="{{ match.disabled|lower }}"
|
|
data-match-group-name="{{ match_group.name }}"
|
|
data-match-format="{{ match.format }}"
|
|
class="match-template">
|
|
{% include 'tournaments/bracket_match_cell.html' %}
|
|
</div>
|
|
{% endfor %}
|
|
{% endif %}
|
|
{% endfor %}
|
|
</div>
|
|
|
|
<script>
|
|
|
|
function renderBracket() {
|
|
const bracket = document.getElementById('bracket');
|
|
const matchTemplates = document.getElementById('match-templates').children;
|
|
const rounds = [];
|
|
const matchPositions = [];
|
|
|
|
|
|
// Group matches by round
|
|
Array.from(matchTemplates).forEach(template => {
|
|
const roundIndex = parseInt(template.dataset.matchRound);
|
|
if (!rounds[roundIndex]) {
|
|
rounds[roundIndex] = [];
|
|
}
|
|
rounds[roundIndex].push(template);
|
|
});
|
|
|
|
// First create a test match to get natural height
|
|
const firstMatch = document.createElement('div');
|
|
firstMatch.className = 'butterfly-match';
|
|
firstMatch.innerHTML = `<div class="match-content">${rounds[0][0].innerHTML}</div>`;
|
|
bracket.appendChild(firstMatch);
|
|
const matchHeight = firstMatch.offsetHeight;
|
|
const matchSpacing = 10;
|
|
const baseDistance = matchHeight + matchSpacing;
|
|
bracket.innerHTML = '';
|
|
const roundCount = rounds.length;
|
|
const finalRoundIndex = (roundCount - 1) / 2;
|
|
let nextMatchDistance = baseDistance;
|
|
let minimumMatchDistance = 1;
|
|
if (rounds[0].length <= 2) {
|
|
minimumMatchDistance = 2
|
|
nextMatchDistance = baseDistance * 2;
|
|
}
|
|
|
|
rounds.forEach((roundMatches, roundIndex) => {
|
|
const roundDiv = document.createElement('div');
|
|
roundDiv.className = 'butterfly-round';
|
|
roundDiv.style.setProperty('--match-width', `${365}px`);
|
|
|
|
// Create title
|
|
const titleDiv = document.createElement('div');
|
|
titleDiv.className = 'round-title';
|
|
|
|
// Get the match group name and format
|
|
const firstMatchTemplate = roundMatches[0].closest('.match-template');
|
|
const matchGroupName = firstMatchTemplate.dataset.matchGroupName;
|
|
const matchFormat = firstMatchTemplate.dataset.matchFormat;
|
|
|
|
const nameSpan = document.createElement('div');
|
|
nameSpan.className = 'round-name';
|
|
nameSpan.textContent = matchGroupName;
|
|
|
|
const formatSpan = document.createElement('div');
|
|
formatSpan.className = 'round-format';
|
|
formatSpan.textContent = matchFormat;
|
|
|
|
titleDiv.appendChild(nameSpan);
|
|
titleDiv.appendChild(formatSpan);
|
|
|
|
// Create matches container
|
|
const matchesContainer = document.createElement('div');
|
|
matchesContainer.className = 'matches-container';
|
|
if (roundIndex >= finalRoundIndex - 1) {
|
|
if (roundCount > 5) {
|
|
matchesContainer.style.transform = `translateX(-50%)`;
|
|
if (roundIndex >= finalRoundIndex + 2) {
|
|
matchesContainer.style.transform = `translateX(-100%)`;
|
|
}
|
|
}
|
|
}
|
|
roundDiv.appendChild(matchesContainer);
|
|
|
|
matchPositions[roundIndex] = [];
|
|
roundMatches.forEach((matchTemplate, matchIndex) => {
|
|
const matchDiv = document.createElement('div');
|
|
matchDiv.className = 'butterfly-match';
|
|
|
|
matchDiv.style.position = 'absolute';
|
|
const isDisabled = matchTemplate.dataset.disabled === 'true';
|
|
let top;
|
|
let left;
|
|
let right;
|
|
const currentMatchesCount = roundMatches.length;
|
|
if (roundIndex > finalRoundIndex) {
|
|
matchDiv.classList.add('reverse-bracket');
|
|
top = matchPositions[roundCount - roundIndex - 1][matchIndex];
|
|
}
|
|
|
|
if (roundIndex === 0) {
|
|
const nextMatchesCount = rounds[roundIndex + 1].length;
|
|
|
|
if (currentMatchesCount == nextMatchesCount) {
|
|
nextMatchDistance = 0;
|
|
}
|
|
top = matchIndex * (matchHeight + matchSpacing) * minimumMatchDistance;
|
|
} else if (roundIndex === roundCount - 1) {
|
|
const nextMatchesCount = rounds[roundIndex - 1].length;
|
|
if (currentMatchesCount == nextMatchesCount) {
|
|
nextMatchDistance = 0;
|
|
}
|
|
} else if (roundIndex == finalRoundIndex) {
|
|
let lgth = matchPositions[0].length / 2;
|
|
let index = lgth + matchIndex - 1;
|
|
// If index goes negative, use 0 instead
|
|
if (matchIndex == 0) {
|
|
top = matchPositions[roundIndex - 1][0] - baseDistance / 2;
|
|
} else {
|
|
top = matchPositions[roundIndex - 1][0] + baseDistance / 2;
|
|
}
|
|
nextMatchDistance = baseDistance;
|
|
} else if (roundIndex < finalRoundIndex) {
|
|
const previousMatchesCount = rounds[roundIndex - 1].length;
|
|
const nextMatchesCount = rounds[roundIndex + 1].length;
|
|
|
|
if (currentMatchesCount == nextMatchesCount) {
|
|
nextMatchDistance = 0;
|
|
} else if (matchPositions.length > roundIndex - 1) {
|
|
nextMatchDistance = (matchPositions[roundIndex - 1][1] - matchPositions[roundIndex - 1][0]);
|
|
nextMatchDistance = nextMatchDistance * (previousMatchesCount / currentMatchesCount);
|
|
}
|
|
|
|
if (currentMatchesCount == previousMatchesCount) {
|
|
top = matchPositions[roundIndex - 1][matchIndex];
|
|
} else {
|
|
const parentIndex1 = matchIndex * 2;
|
|
const parentIndex2 = parentIndex1 + 1;
|
|
const parentPos1 = matchPositions[roundIndex - 1][parentIndex1];
|
|
const parentPos2 = matchPositions[roundIndex - 1][parentIndex2];
|
|
top = (parentPos1 + parentPos2) / 2;
|
|
}
|
|
} else if (roundIndex < roundCount) {
|
|
const nextMatchesCount = rounds[roundIndex - 1].length;
|
|
const previousMatchesCount = rounds[roundIndex + 1].length;
|
|
|
|
if (currentMatchesCount == nextMatchesCount) {
|
|
nextMatchDistance = 0;
|
|
} else if (matchPositions.length > roundCount - roundIndex - 1 - 1) {
|
|
nextMatchDistance = (matchPositions[roundCount - roundIndex - 1 - 1][1] - matchPositions[roundCount - roundIndex - 1 - 1][0]);
|
|
nextMatchDistance = nextMatchDistance * (previousMatchesCount / currentMatchesCount);
|
|
}
|
|
}
|
|
|
|
if (roundIndex >= finalRoundIndex - 1) {
|
|
if (roundCount > 5) {
|
|
if (roundIndex == finalRoundIndex - 1) {
|
|
matchDiv.classList.add('inward');
|
|
}
|
|
if (roundIndex == finalRoundIndex + 1) {
|
|
matchDiv.classList.add('outward');
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
if (roundIndex === finalRoundIndex - 2 || roundIndex === finalRoundIndex + 2) {
|
|
nextMatchDistance = nextMatchDistance - baseDistance;
|
|
}
|
|
else if (roundIndex == finalRoundIndex - 1 || roundIndex == finalRoundIndex + 1) {
|
|
nextMatchDistance = baseDistance;
|
|
}
|
|
|
|
matchDiv.style.setProperty('--next-match-distance', `${nextMatchDistance}px`);
|
|
matchDiv.style.top = `${top}px`;
|
|
matchPositions[roundIndex][matchIndex] = top;
|
|
if (matchIndex === 0) {
|
|
|
|
// // Add logo for final round
|
|
// if (roundIndex == finalRoundIndex) {
|
|
// const logoDiv = document.createElement('div');
|
|
// logoDiv.className = 'round-logo';
|
|
// const logoImg = document.createElement('img');
|
|
// logoImg.src = '/static/tournaments/images/PadelClub_logo_512.png';
|
|
// logoImg.alt = 'PadelClub Logo';
|
|
// logoDiv.appendChild(logoImg);
|
|
// logoDiv.style.transform = `translateX(-50%)`;
|
|
// matchesContainer.appendChild(logoDiv);
|
|
// }
|
|
|
|
|
|
// Position title above the first match
|
|
titleDiv.style.top = `${top - 80}px`; // Adjust the 60px offset as needed
|
|
titleDiv.style.position = 'absolute';
|
|
if (roundIndex == finalRoundIndex - 1) {
|
|
titleDiv.style.marginLeft = '50px';
|
|
} else if (roundIndex == finalRoundIndex + 1) {
|
|
titleDiv.style.marginLeft = '-50px';
|
|
}
|
|
|
|
matchesContainer.appendChild(titleDiv);
|
|
}
|
|
|
|
matchDiv.innerHTML = `
|
|
<div class="incoming-line ${isDisabled ? 'disabled' : ''}"></div>
|
|
<div class="match-content ${isDisabled ? 'disabled' : ''}">${matchTemplate.innerHTML}</div>
|
|
`;
|
|
|
|
if (roundIndex == finalRoundIndex - 1) {
|
|
const matchDiv2 = document.createElement('div');
|
|
matchDiv2.className = 'butterfly-match';
|
|
matchDiv2.classList.add('inward');
|
|
matchDiv2.classList.add('semi-final');
|
|
matchDiv2.style.setProperty('--next-match-distance', `${baseDistance}px`);
|
|
matchDiv2.style.top = `${top}px`;
|
|
matchDiv2.innerHTML = `<div class="match-content">${rounds[0][0].innerHTML}</div>`;
|
|
matchesContainer.appendChild(matchDiv2); // Append to matchesContainer instead of roundDiv
|
|
}
|
|
matchesContainer.appendChild(matchDiv); // Append to matchesContainer instead of roundDiv
|
|
});
|
|
|
|
bracket.appendChild(roundDiv);
|
|
});
|
|
}
|
|
|
|
renderBracket();
|
|
</script>
|
|
|
|
<style>
|
|
.round-logo img {
|
|
width: 50px;
|
|
height: auto;
|
|
display: block;
|
|
margin: 0 auto;
|
|
position: relative;
|
|
top: -100px; /* Increased negative value to move it higher up */
|
|
}
|
|
|
|
.round-logo img {
|
|
width: 100px; /* Adjust size as needed */
|
|
height: auto;
|
|
display: block;
|
|
margin: 0 auto;
|
|
}
|
|
.butterfly-match.same-level::before {
|
|
display: none;
|
|
}
|
|
|
|
/* Adjust styling for matches with single parent */
|
|
.match-content.disabled {
|
|
visibility: hidden;
|
|
}
|
|
|
|
.incoming-line.disabled,
|
|
.butterfly-match:has(.match-content.disabled)::after,
|
|
.butterfly-match:has(.match-content.disabled)::before {
|
|
visibility: hidden;
|
|
}
|
|
|
|
.butterfly-bracket {
|
|
display: flex;
|
|
gap: 40px; /* Increased to account for horizontal lines (20px on each side) */
|
|
position: relative;
|
|
margin-bottom: 80px;
|
|
}
|
|
|
|
|
|
.round-title {
|
|
position: absolute;
|
|
top: 0px; /* Adjust this value to position the title where you want it */
|
|
padding: 5px 10px;
|
|
text-align: center;
|
|
font-weight: bold;
|
|
width: 100%; /* Change from 100% to auto */
|
|
}
|
|
|
|
.round-name {
|
|
font-size: 1.5em; /* Make the round name bigger */
|
|
margin-bottom: 5px;
|
|
}
|
|
|
|
.round-format {
|
|
font-size: 0.9em;
|
|
color: #666;
|
|
}
|
|
|
|
.matches-container {
|
|
position: relative;
|
|
width: 100%;
|
|
flex-grow: 1;
|
|
}
|
|
|
|
.butterfly-round {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
gap: 20px; /* Space between title and matches */
|
|
position: relative;
|
|
width: var(--match-width);
|
|
flex-shrink: 0;
|
|
margin-top: 100px; /* Add padding to account for absolute positioned title */
|
|
}
|
|
|
|
.butterfly-match {
|
|
position: absolute;
|
|
width: 100%;
|
|
}
|
|
|
|
/* Horizontal line after match */
|
|
.butterfly-match::after {
|
|
content: "";
|
|
position: absolute;
|
|
left: 100%; /* Start from end of match cell */
|
|
top: 50%;
|
|
width: 20px;
|
|
height: 2px;
|
|
background: #666;
|
|
}
|
|
|
|
.semi-final::after {
|
|
content: "";
|
|
position: absolute;
|
|
left: calc(100% + 20px); /* After horizontal line */
|
|
width: 2px;
|
|
height: calc((var(--next-match-distance)) / 2);
|
|
background: #666;
|
|
}
|
|
|
|
/* Vertical line connecting pair of matches */
|
|
.butterfly-match:nth-child(2n)::before {
|
|
content: "";
|
|
position: absolute;
|
|
left: calc(100% + 20px); /* After horizontal line */
|
|
top: 50%;
|
|
width: 2px;
|
|
height: calc((var(--next-match-distance)) / 2);
|
|
background: #666;
|
|
}
|
|
|
|
.butterfly-match:nth-child(2n+1)::before {
|
|
content: "";
|
|
position: absolute;
|
|
left: calc(100% + 20px);
|
|
bottom: calc(50% - 2px); /* Account for half of horizontal line height */
|
|
width: 2px;
|
|
height: calc((var(--next-match-distance)) / 2); /* Add half of horizontal line height */
|
|
background: #666;
|
|
}
|
|
|
|
/* Vertical line connecting pair of matches */
|
|
.butterfly-match.reverse-bracket:nth-child(2n)::before {
|
|
content: "";
|
|
position: absolute;
|
|
left: calc(0% - 20px); /* After horizontal line */
|
|
top: 50%;
|
|
width: 2px;
|
|
height: calc((var(--next-match-distance)) / 2);
|
|
background: #666;
|
|
}
|
|
|
|
.butterfly-match.reverse-bracket:nth-child(2n+1)::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 */
|
|
.butterfly-match .incoming-line {
|
|
position: absolute;
|
|
left: -20px;
|
|
top: 50%;
|
|
width: 20px;
|
|
height: 2px;
|
|
background: #666;
|
|
}
|
|
|
|
.inward .incoming-line {
|
|
display: none;
|
|
}
|
|
|
|
.butterfly-match.outward::after {
|
|
display: none;
|
|
}
|
|
|
|
.butterfly-round:last-child .butterfly-match::after,
|
|
.butterfly-round:first-child .incoming-line {
|
|
display: none;
|
|
}
|
|
|
|
</style>
|
|
|
|
{% endif %}
|
|
{% endblock %}
|
|
|