fix broadcast layout

sync_v2
Raz 6 months ago
parent 6d92dbd491
commit 7742fde718
  1. 16
      tournaments/models/match.py
  2. 6
      tournaments/models/player_registration.py
  3. 3
      tournaments/models/round.py
  4. 6
      tournaments/models/team_registration.py
  5. 8
      tournaments/models/team_score.py
  6. 4
      tournaments/models/tournament.py
  7. 114
      tournaments/static/tournaments/js/tournament_bracket.js
  8. 10
      tournaments/templates/tournaments/broadcast/broadcasted_bracket.html

@ -184,7 +184,7 @@ class Match(SideStoreModel):
def is_ready(self):
return self.team_scores.count() == 2
def live_teams(self, hide_names=False):
def live_teams(self, hide_names=False, short_names=False):
#print('player names from match')
##return map(lambda ts: ts.player_names(), self.team_scores.all())
# List to hold the names of the teams
@ -247,7 +247,7 @@ class Match(SideStoreModel):
teams.append(team)
elif len(team_scores) == 1:
# Only one team score, handle missing one
existing_team = team_scores[0].live_team(self)
existing_team = team_scores[0].live_team(self, short_names=short_names)
if (self.group_stage):
teams.append(existing_team)
names = ["Équipe de poule"]
@ -287,19 +287,19 @@ class Match(SideStoreModel):
elif len(team_scores) == 2:
# Both team scores present
teams.extend([team_score.live_team(self) for team_score in team_scores])
teams.extend([team_score.live_team(self, short_names=short_names) for team_score in team_scores])
if self.round is not None and self.round.parent is None:
pos1 = team_scores[0].team_registration.bracket_position if hasattr(team_scores[0], 'team_registration') and team_scores[0].team_registration else None
pos2 = team_scores[1].team_registration.bracket_position if hasattr(team_scores[1], 'team_registration') and team_scores[1].team_registration else None
if pos1 is not None and pos2 is not None and pos1 // 2 == self.index and pos2 // 2 == self.index:
if pos1 > pos2:
teams = [team_scores[1].live_team(self), team_scores[0].live_team(self)]
teams = [team_scores[1].live_team(self, short_names=short_names), team_scores[0].live_team(self, short_names=short_names)]
else:
teams = [team_scores[0].live_team(self), team_scores[1].live_team(self)]
teams = [team_scores[0].live_team(self, short_names=short_names), team_scores[1].live_team(self, short_names=short_names)]
else:
teams.extend([team_score.live_team(self) for team_score in team_scores if team_score.walk_out != 1])
teams.extend([team_score.live_team(self, short_names=short_names) for team_score in team_scores if team_score.walk_out != 1])
return teams
@ -426,7 +426,7 @@ class Match(SideStoreModel):
else:
return self.round.tournament.short_full_name()
def live_match(self, hide_teams=False, event_mode=False):
def live_match(self, hide_teams=False, event_mode=False, short_names=False):
title = self.computed_name()
date = self.formatted_start_date()
time_indication = self.time_indication()
@ -447,7 +447,7 @@ class Match(SideStoreModel):
livematch = LiveMatch(self.index, title, date, time_indication, court, self.started(), ended, group_stage_name, live_format, self.start_date, self.court_index, self.disabled, bracket_name, self.should_show_lucky_loser_status(), tournament_title)
for team in self.live_teams(hide_teams):
for team in self.live_teams(hide_teams, short_names):
livematch.add_team(team)
return livematch

@ -62,11 +62,11 @@ class PlayerRegistration(SideStoreModel):
def name(self):
return f"{self.first_name} {self.last_name}"
def shortened_name(self):
def shortened_name(self, forced=False):
name = self.name()
if len(name) > 20 and self.first_name:
if (len(name) > 20 or forced) and self.first_name:
name = f"{self.first_name[0]}. {self.last_name}"
if len(name) > 20:
if len(name) > 20 or forced:
name_parts = self.last_name.split(" ")
name = f"{self.first_name[0]}. {name_parts[0]}"
return name

@ -179,7 +179,8 @@ class Round(SideStoreModel):
name=name,
matches=first_half_matches,
round_id=self.id,
round_index=self.index
round_index=self.index,
short_names=True
)
return match_group

@ -72,7 +72,7 @@ class TeamRegistration(SideStoreModel):
else:
return self.player_names_as_list()
def shortened_team_names(self):
def shortened_team_names(self, forced=False):
if self.name:
return [self.name] #add an empty line if it's a team name
else:
@ -85,9 +85,9 @@ class TeamRegistration(SideStoreModel):
else:
return ['Place réservée']
elif len(players) == 1:
return [players[0].shortened_name()]
return [players[0].shortened_name(forced=forced)]
else:
return [pr.shortened_name() for pr in players]
return [pr.shortened_name(forced=forced) for pr in players]
@property
def players_sorted_by_rank(self):

@ -49,10 +49,10 @@ class TeamScore(SideStoreModel):
else:
return "--"
def shortened_team_names(self):
def shortened_team_names(self, forced=False):
names = []
if self.team_registration:
names = self.team_registration.shortened_team_names()
names = self.team_registration.shortened_team_names(forced=forced)
return names
def team_names(self):
@ -109,7 +109,7 @@ class TeamScore(SideStoreModel):
scores = self.scores()
return sum(scores)
def live_team(self, match):
def live_team(self, match, short_names=False):
if self.team_registration:
id = self.team_registration.id
image = self.team_registration.logo
@ -123,7 +123,7 @@ class TeamScore(SideStoreModel):
image = None
weight= None
is_winner = False
names = self.shortened_team_names()
names = self.shortened_team_names(forced=short_names)
scores = self.parsed_scores()
walk_out = self.walk_out
is_lucky_loser = self.lucky_loser is not None

@ -571,9 +571,9 @@ class Tournament(BaseModel):
return groups
def create_match_group(self, name, matches, round_id=None, round_index=None, hide_teams=False, event_mode=False):
def create_match_group(self, name, matches, round_id=None, round_index=None, hide_teams=False, event_mode=False, short_names=False):
matches = list(matches)
live_matches = [match.live_match(hide_teams, event_mode) for match in matches]
live_matches = [match.live_match(hide_teams, event_mode, short_names) for match in matches]
# Filter out matches that have a start_date of None
valid_matches = [match for match in matches if match.start_date is not None]

@ -443,64 +443,64 @@ function renderBracket(options) {
bracket.appendChild(roundDiv);
});
if (isBroadcast == false || isBroadcast == undefined) {
setTimeout(() => {
const roundDivs = document.querySelectorAll(".butterfly-round");
// First, find the maximum bottom position across all rounds
let globalMaxBottom = 0;
roundDivs.forEach((roundDiv) => {
const matches = roundDiv.querySelectorAll(".butterfly-match");
matches.forEach((match) => {
const bottom = match.offsetTop + match.offsetHeight;
if (bottom > globalMaxBottom) {
globalMaxBottom = bottom;
}
});
});
// Now create and position footers for all rounds at the same y-position
roundDivs.forEach((roundDiv, index) => {
// Get the match templates from this round to extract data
const roundMatches = rounds[index] || [];
if (roundMatches.length > 0) {
const firstMatchTemplate = roundMatches[0].closest(".match-template");
const roundId = firstMatchTemplate.dataset.roundId;
const realRoundIndex = firstMatchTemplate.dataset.roundIndex;
if (realRoundIndex > 1) {
// Create footer div
const footerDiv = document.createElement("div");
footerDiv.className = "round-footer";
footerDiv.style.width = `${responsiveMatchWidth}px`;
footerDiv.style.paddingBottom = "40px";
footerDiv.style.textAlign = "center";
// Create footer content
let linkSpan = document.createElement("a");
linkSpan.className = "small styled-link";
linkSpan.textContent = "accès au tableau de classement";
if (roundId) {
linkSpan.href = `/tournament/${tournamentId}/round/${roundId}/bracket/`;
linkSpan.style.cursor = "pointer";
}
// if (isBroadcast == false || isBroadcast == undefined) {
// setTimeout(() => {
// const roundDivs = document.querySelectorAll(".butterfly-round");
// // First, find the maximum bottom position across all rounds
// let globalMaxBottom = 0;
// roundDivs.forEach((roundDiv) => {
// const matches = roundDiv.querySelectorAll(".butterfly-match");
// matches.forEach((match) => {
// const bottom = match.offsetTop + match.offsetHeight;
// if (bottom > globalMaxBottom) {
// globalMaxBottom = bottom;
// }
// });
// });
// // Now create and position footers for all rounds at the same y-position
// roundDivs.forEach((roundDiv, index) => {
// // Get the match templates from this round to extract data
// const roundMatches = rounds[index] || [];
// if (roundMatches.length > 0) {
// const firstMatchTemplate = roundMatches[0].closest(".match-template");
// const roundId = firstMatchTemplate.dataset.roundId;
// const realRoundIndex = firstMatchTemplate.dataset.roundIndex;
// if (realRoundIndex > 1) {
// // Create footer div
// const footerDiv = document.createElement("div");
// footerDiv.className = "round-footer";
// footerDiv.style.width = `${responsiveMatchWidth}px`;
// footerDiv.style.paddingBottom = "40px";
// footerDiv.style.textAlign = "center";
// // Create footer content
// let linkSpan = document.createElement("a");
// linkSpan.className = "small styled-link";
// linkSpan.textContent = "accès au tableau de classement";
// if (roundId) {
// linkSpan.href = `/tournament/${tournamentId}/round/${roundId}/bracket/`;
// linkSpan.style.cursor = "pointer";
// }
footerDiv.appendChild(linkSpan);
// footerDiv.appendChild(linkSpan);
// Create a container that will sit at the same position for all rounds
const footerContainer = document.createElement("div");
footerContainer.style.position = "absolute";
footerContainer.style.top = `${globalMaxBottom}px`; // Same position for all footers
footerContainer.style.width = "100%";
footerContainer.appendChild(footerDiv);
// // Create a container that will sit at the same position for all rounds
// const footerContainer = document.createElement("div");
// footerContainer.style.position = "absolute";
// footerContainer.style.top = `${globalMaxBottom}px`; // Same position for all footers
// footerContainer.style.width = "100%";
// footerContainer.appendChild(footerDiv);
// Add to the round div
const matchesContainer =
roundDiv.querySelector(".matches-container");
matchesContainer.appendChild(footerContainer);
}
}
});
}, 100);
}
// // Add to the round div
// const matchesContainer =
// roundDiv.querySelector(".matches-container");
// matchesContainer.appendChild(footerContainer);
// }
// }
// });
// }, 1000);
// }
}

@ -4,6 +4,7 @@
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
<link rel="stylesheet" href="{% static 'tournaments/css/foundation.min.css' %}" />
<link rel="stylesheet" href="{% static 'tournaments/css/basics.css' %}" />
<link rel="stylesheet" href="{% static 'tournaments/css/style.css' %}" />
@ -108,6 +109,15 @@
</head>
<body>
<div x-data="{
loop() {
this.fetchAndRenderBracket()
setInterval(() => {
this.fetchAndRenderBracket()
}, 15000)
},
}" x-init="loop()">
<header>
<div id="screen-size-overlay">
<div class="left-content bubble-header screen-size-overlay">

Loading…
Cancel
Save