commit
15231d9299
@ -0,0 +1,57 @@ |
||||
{% load static %} |
||||
|
||||
<div class="cell medium-12 large-3 my-block"> |
||||
<div class="bubble"> |
||||
<div> |
||||
{% for team in match.teams %} |
||||
<div class="match-result {% cycle 'bottom-border' '' %}"> |
||||
<div class="player"> |
||||
{% if team.id %} |
||||
<a href="{% url 'team-details' tournament.id team.id %}" class="player-link"> |
||||
{% endif %} |
||||
|
||||
{% if team.is_lucky_loser or team.walk_out == 1 %} |
||||
<div class="overlay-text"> |
||||
{% if team.is_lucky_loser %}(LL){% elif team.walk_out == 1 %}(WO){% endif %} |
||||
</div> |
||||
{% endif %} |
||||
|
||||
{% for name in team.names %} |
||||
<div class="semibold{% if team.walk_out == 1 %} strikethrough{% endif %}{% if team.is_winner %} winner{% endif %}"> |
||||
{% if name|length > 0 %} |
||||
{{ name }} |
||||
{% else %} |
||||
|
||||
{% endif %} |
||||
</div> |
||||
{% endfor %} |
||||
{% if team.id %} |
||||
</a> |
||||
{% endif %} |
||||
</div> |
||||
|
||||
{% if match.has_walk_out %} |
||||
<span class="score ws w60px"> |
||||
{% if team.is_walk_out %}WO{% endif %} |
||||
</span> |
||||
{% elif match.should_show_scores %} |
||||
<div class="scores"> |
||||
{% for score in team.scores %} |
||||
<span class="score ws {% if score.tiebreak %}w35px{% else %}w30px{% endif %}{% if team.is_winner %} winner{% endif %}"> |
||||
{{ score.main }} |
||||
{% if score.tiebreak %} |
||||
<sup>{{ score.tiebreak }}</sup> |
||||
{% endif %} |
||||
</span> |
||||
{% endfor %} |
||||
</div> |
||||
{% elif not tournament.hide_weight and team.weight %} |
||||
<span class="score ws numbers">{{ team.weight }}</span> |
||||
{% endif %} |
||||
</div> |
||||
|
||||
{% endfor %} |
||||
|
||||
</div> |
||||
</div> |
||||
</div> |
||||
@ -0,0 +1,40 @@ |
||||
{% 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' %} |
||||
|
||||
{% if tournament.display_matches or tournament.display_group_stages %} |
||||
|
||||
{% regroup match_groups.matches by start_date|date:"l d F Y" as matches_by_date %} |
||||
|
||||
{% for date in matches_by_date %} |
||||
|
||||
{% regroup date.list by start_date|date:"H:i" as matches_by_hour %} |
||||
|
||||
{% for hour_group in matches_by_hour %} |
||||
<h1 class="club my-block topmargin20">{{ date.grouper }} {{ hour_group.grouper }}</h1> |
||||
|
||||
{% regroup hour_group.list by court_index as matches_by_court %} |
||||
|
||||
<div class="grid-x"> |
||||
{% for court in matches_by_court|dictsort:"grouper" %} |
||||
{% for match_data in court.list %} |
||||
{% with match=match_data.match %} |
||||
{% include 'tournaments/match_cell.html' %} |
||||
{% endwith %} |
||||
{% endfor %} |
||||
{% endfor %} |
||||
</div> |
||||
{% endfor %} |
||||
{% endfor %} |
||||
|
||||
|
||||
{% endif %} |
||||
{% endif %} |
||||
{% endblock %} |
||||
@ -0,0 +1,417 @@ |
||||
{% 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 %} |
||||
Loading…
Reference in new issue