fix json broadcast livematch crash

redesign-tournament-list
Raz 8 months ago
parent 3b94a6f8fa
commit d7c3a0c639
  1. 1
      tournaments/models/match.py
  2. 23
      tournaments/templates/tournaments/bracket_match_cell.html
  3. 151
      tournaments/templates/tournaments/tournament_bracket.html
  4. 4
      tournaments/views.py

@ -480,7 +480,6 @@ class LiveMatch:
"group_stage_name": self.group_stage_name,
"format": self.format,
"disabled": self.disabled,
"start_date": self.start_date,
"court_index": self.court_index
}

@ -2,16 +2,7 @@
<div class="cell medium-12 large-3 my-block">
<div class="bubble">
<div class="flex-row">
<label class="matchtitle">{{ match.title }}</label>
{% if not match.ended %}
<label class="right-label minor-info bold">{{ match.court }}</label>
{% endif %}
</div>
<div>
{% for team in match.teams %}
<div class="match-result {% cycle 'bottom-border' '' %}">
<div class="player">
@ -62,19 +53,5 @@
{% endfor %}
</div>
<div class="status-container {% if not match.ended and match.started %}running{% endif %}">
<div class="flex-row top-margin">
<label class="left-label minor-info bold">
{% if match.show_time_indication %}
{{ match.time_indication }}
{% endif %}
</label>
<label class="right-label minor-info">
{% if not match.ended %}
{{ match.format }}
{% endif %}
</label>
</div>
</div>
</div>
</div>

@ -18,6 +18,8 @@
<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>
@ -34,6 +36,7 @@ function renderBracket() {
const rounds = [];
const matchPositions = [];
// Group matches by round
Array.from(matchTemplates).forEach(template => {
const roundIndex = parseInt(template.dataset.matchRound);
@ -54,53 +57,121 @@ function renderBracket() {
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`);
matchPositions[roundIndex] = [];
// 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;
if (roundIndex >= finalRoundIndex - 1) {
if (roundCount > 5) {
titleDiv.style.transform = `translateX(-50%)`;
if (roundIndex >= finalRoundIndex + 2) {
titleDiv.style.transform = `translateX(-100%)`;
}
}
}
titleDiv.appendChild(nameSpan);
titleDiv.appendChild(formatSpan);
roundDiv.appendChild(titleDiv);
// Create matches container
const matchesContainer = document.createElement('div');
matchesContainer.className = 'matches-container';
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;
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;
}
const currentMatchesCount = roundMatches.length;
if (roundIndex > finalRoundIndex) {
matchDiv.classList.add('reverse-bracket');
top = matchPositions[roundCount - roundIndex - 1][matchIndex];
nextMatchDistance = baseDistance * Math.pow(2, rounds.length - roundIndex - 1);
} else {
nextMatchDistance = baseDistance * Math.pow(2, roundIndex);
}
if (roundIndex === 0) {
top = matchIndex * (matchHeight + matchSpacing);
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
top = matchPositions[0][index < 0 ? 0 : index];
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;
nextMatchDistance = baseDistance * Math.pow(2, roundIndex);
}
} 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) {
@ -121,7 +192,7 @@ function renderBracket() {
}
if (roundIndex === finalRoundIndex - 2 || roundIndex === finalRoundIndex + 2) {
nextMatchDistance = (nextMatchDistance - baseDistance);
nextMatchDistance = nextMatchDistance - baseDistance;
}
else if (roundIndex == finalRoundIndex - 1 || roundIndex == finalRoundIndex + 1) {
nextMatchDistance = baseDistance;
@ -139,7 +210,6 @@ function renderBracket() {
if (roundIndex == finalRoundIndex - 1) {
const matchDiv2 = document.createElement('div');
matchDiv2.className = 'butterfly-match';
matchDiv2.style.position = 'absolute';
if (roundCount > 5) {
matchDiv2.style.transform = `translateX(-50%)`;
}
@ -147,11 +217,10 @@ function renderBracket() {
matchDiv2.classList.add('semi-final');
matchDiv2.style.setProperty('--next-match-distance', `${baseDistance}px`);
matchDiv2.style.top = `${top}px`;
matchDiv2.innerHTML = `
`;
roundDiv.appendChild(matchDiv2);
matchDiv2.innerHTML = `<div class="match-content">${rounds[0][0].innerHTML}</div>`;
matchesContainer.appendChild(matchDiv2); // Append to matchesContainer instead of roundDiv
}
roundDiv.appendChild(matchDiv);
matchesContainer.appendChild(matchDiv); // Append to matchesContainer instead of roundDiv
});
bracket.appendChild(roundDiv);
@ -163,7 +232,6 @@ function renderBracket() {
<style>
.butterfly-match.same-level::before {
display: none;
}
@ -185,10 +253,38 @@ function renderBracket() {
position: relative;
}
.round-title {
width: 100%;
margin-top: 20px;
text-align: center;
font-weight: bold;
}
.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); /* 300px for match + 20px on each side for lines */
flex-shrink: 0; /* Prevents rounds from shrinking */
width: var(--match-width);
flex-shrink: 0;
}
.butterfly-match {
@ -211,9 +307,8 @@ function renderBracket() {
content: "";
position: absolute;
left: calc(100% + 20px); /* After horizontal line */
top: -4px;
width: 2px;
height: calc(var(--next-match-distance));
height: calc((var(--next-match-distance)) / 2);
background: #666;
}
@ -243,7 +338,7 @@ function renderBracket() {
content: "";
position: absolute;
left: calc(0% - 20px); /* After horizontal line */
top: calc(50% + 2px);
top: 50%;
width: 2px;
height: calc((var(--next-match-distance)) / 2);
background: #666;

@ -985,7 +985,7 @@ def tournament_bracket(request, tournament_id):
# Add first half of each round (from last to semi-finals)
for round in main_rounds:
matches = round.match_set.all().order_by('index')
matches = round.match_set.filter(disabled=False).order_by('index')
if matches:
if len(matches) > 1:
@ -1007,7 +1007,7 @@ def tournament_bracket(request, tournament_id):
serializable_match_groups.append(match_group)
for round in main_rounds_reversed:
matches = round.match_set.all().order_by('index')
matches = round.match_set.filter(disabled=False).order_by('index')
if matches:
if len(matches) > 1:
midpoint = int(len(matches) / 2)

Loading…
Cancel
Save