add prog to website

sync_v2
Raz 6 months ago
parent 3b48d22473
commit 96fe35a742
  1. 43
      tournaments/migrations/0122_groupstage_planned_start_date_and_more.py
  2. 1
      tournaments/models/group_stage.py
  3. 9
      tournaments/models/match.py
  4. 1
      tournaments/models/round.py
  5. 112
      tournaments/models/tournament.py
  6. 5
      tournaments/static/tournaments/css/style.css
  7. 3
      tournaments/templates/tournaments/navigation_tournament.html
  8. 46
      tournaments/templates/tournaments/prog.html
  9. 30
      tournaments/views.py

File diff suppressed because one or more lines are too long

@ -15,6 +15,7 @@ class GroupStage(SideStoreModel):
size = models.IntegerField(default=4)
format = models.IntegerField(default=FederalMatchCategory.NINE_GAMES, choices=FederalMatchCategory.choices, null=True, blank=True)
start_date = models.DateTimeField(null=True, blank=True)
planned_start_date = models.DateTimeField(null=True, blank=True)
name = models.CharField(max_length=200, null=True, blank=True)
step = models.IntegerField(default=0)

@ -14,6 +14,7 @@ class Match(SideStoreModel):
group_stage = models.ForeignKey(GroupStage, null=True, blank=True, on_delete=models.SET_NULL, related_name='matches')
name = models.CharField(max_length=200, null=True, blank=True)
start_date = models.DateTimeField(null=True, blank=True)
planned_start_date = models.DateTimeField(null=True, blank=True)
end_date = models.DateTimeField(null=True, blank=True)
index = models.IntegerField(default=0)
#order = models.IntegerField(default=0)
@ -183,7 +184,7 @@ class Match(SideStoreModel):
def is_ready(self):
return self.team_scores.count() == 2
def live_teams(self):
def live_teams(self, hide_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
@ -196,7 +197,7 @@ class Match(SideStoreModel):
loser_top_match = self.loser_precedent_match(True)
loser_bottom_match = self.loser_precedent_match(False)
if len(team_scores) == 0:
if len(team_scores) == 0 or hide_names is True:
if (self.round and self.round.parent is None and self.round.tournament.rounds.filter(parent__isnull=True, group_stage_loser_bracket=False).count() - 1 == self.round.index):
names = ["Qualifié"]
@ -419,7 +420,7 @@ class Match(SideStoreModel):
# _minutes = int((_seconds % 3600) / 60)
# return f"{_hours:02d}h{_minutes:02d}min"
def live_match(self):
def live_match(self, hide_teams=False):
title = self.computed_name()
date = self.formatted_start_date()
time_indication = self.time_indication()
@ -436,7 +437,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())
for team in self.live_teams():
for team in self.live_teams(hide_teams):
livematch.add_team(team)
return livematch

@ -9,6 +9,7 @@ class Round(SideStoreModel):
parent = models.ForeignKey('self', blank=True, null=True, on_delete=models.SET_NULL, related_name='children')
format = models.IntegerField(default=FederalMatchCategory.NINE_GAMES, choices=FederalMatchCategory.choices, null=True, blank=True)
start_date = models.DateTimeField(null=True, blank=True)
planned_start_date = models.DateTimeField(null=True, blank=True)
group_stage_loser_bracket = models.BooleanField(default=False)
loser_bracket_mode = models.IntegerField(default=0)

@ -90,6 +90,8 @@ class Tournament(BaseModel):
is_corporate_tournament = models.BooleanField(default=False)
is_template = models.BooleanField(default=False)
animation_type = models.IntegerField(default=AnimationType.TOURNAMENT, choices=AnimationType.choices)
publish_prog = models.BooleanField(default=False)
show_teams_in_prog = models.BooleanField(default=False)
def delete_dependencies(self):
for team_registration in self.team_registrations.all():
@ -562,9 +564,9 @@ class Tournament(BaseModel):
return groups
def create_match_group(self, name, matches, round_id=None, round_index=None):
def create_match_group(self, name, matches, round_id=None, round_index=None, hide_teams=False):
matches = list(matches)
live_matches = [match.live_match() for match in matches]
live_matches = [match.live_match(hide_teams) 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]
@ -887,6 +889,15 @@ class Tournament(BaseModel):
return self.has_team_registrations()
return False
def display_prog(self):
if self.end_date is not None:
return True
if self.publish_prog:
return True
if self.has_started():
return True
return False
def has_team_registrations(self):
return self.team_registrations.count() > 0
@ -1895,6 +1906,103 @@ class Tournament(BaseModel):
return teams_processed
def planned_matches_by_day(self, day=None):
"""
Collect all matches from tournaments and group them by their planned_start_date.
Parameters:
- day: Optional date string in format 'YYYY-MM-DD'. If provided, returns matches for that day only.
Returns:
- days: List of unique days found (datetime.date objects)
- match_groups: Dictionary of match groups by date and hour or just for the selected day
"""
# Get all matches from rounds and group stages - use a set to avoid duplicates
all_matches = set()
# Get matches only from top-level rounds to avoid duplicates
for round in self.rounds.filter(parent=None).all():
round_matches = round.get_matches_recursive(False)
# Add to set using IDs to avoid duplicates
for match in round_matches:
all_matches.add(match)
# Get matches from group stages
for group_stage in self.group_stages.all():
for match in group_stage.matches.all():
all_matches.add(match)
# Filter matches with planned_start_date - convert back to list
planned_matches = [match for match in all_matches if match.planned_start_date and not match.disabled]
if not planned_matches:
return [], []
# Group matches by day
matches_by_day = {}
days = set()
for match in planned_matches:
# Convert to local time zone
local_date = timezone.localtime(match.planned_start_date)
day_key = local_date.date()
days.add(day_key)
if day_key not in matches_by_day:
matches_by_day[day_key] = []
matches_by_day[day_key].append(match)
# Sort days
sorted_days = sorted(list(days))
# If specific day requested, filter to that day
selected_day = None
if day:
try:
# Parse the day string to a date object
selected_day = datetime.strptime(day, '%Y-%m-%d').date()
if selected_day not in days:
selected_day = sorted_days[0] if sorted_days else None
except (ValueError, TypeError):
selected_day = sorted_days[0] if sorted_days else None
else:
selected_day = sorted_days[0] if sorted_days else None
# Create match groups for the selected day
match_groups = []
if selected_day and selected_day in matches_by_day:
# Group matches by hour
matches_by_hour = {}
for match in matches_by_day[selected_day]:
local_time = timezone.localtime(match.planned_start_date)
hour_key = local_time.strftime('%H:%M')
if hour_key not in matches_by_hour:
matches_by_hour[hour_key] = []
matches_by_hour[hour_key].append(match)
hide_teams = self.show_teams_in_prog == False
# Create match groups for each hour
for hour, matches in sorted(matches_by_hour.items()):
# Sort matches by court if available
matches.sort(key=lambda m: (m.court_index if m.court_index is not None else 999))
local_date = matches[0].local_start_date()
formatted_name = formats.date_format(local_date, format='l j F à H:i').capitalize()
mg = self.create_match_group(
name=formatted_name,
matches=matches,
round_id=None,
round_index=None,
hide_teams=hide_teams
)
match_groups.append(mg)
return sorted_days, match_groups
class MatchGroup:

@ -202,6 +202,11 @@ tr {
font-weight: 600;
}
.mybox.active {
background-color: #f39200;
color: #ffffff;
}
@media (max-width: 80em) {
font-size: 0.8em;
padding: 0px;

@ -1,6 +1,9 @@
<nav class="margin10">
<a href="{% url 'tournament-info' tournament.id %}" class="topmargin5 orange">Informations</a>
{% if tournament.display_prog %}
<a href="{% url 'tournament-prog' tournament.id %}" class="topmargin5 orange">Programmation</a>
{% endif %}
{% if tournament.display_matches and tournament.has_bracket %}
<a href="{% url 'tournament-bracket' tournament.id %}" class="topmargin5 orange">Tableau</a>

@ -1,40 +1,36 @@
{% extends 'tournaments/base.html' %}
{% block head_title %}Matchs du {{ tournament.display_name }}{% endblock %}
{% block head_title %}Programmation{% endblock %}
{% block first_title %}{{ tournament.event.display_name }}{% endblock %}
{% block second_title %}{{ tournament.display_name }}{% endblock %}
{% block second_title %}Programmation{% endblock %}
{% block content %}
{% include 'tournaments/navigation_tournament.html' %}
{% 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 padding10 topmargin20">{{ date.grouper }} {{ hour_group.grouper }}</h1>
{% regroup hour_group.list by court_index as matches_by_court %}
{% if days %}
<nav class="margin10">
{% for day in days %}
<a href="{% url 'tournament-prog' tournament.id %}?day={{ day|date:'Y-m-d' }}" class="mybox topmargin5 {% if selected_day == day|date:'Y-m-d' %}active{% endif %}">
{{ day|date:"l d F"|capfirst }}
</a>
{% endfor %}
</nav>
{% if match_groups %}
{% for match_group in match_groups %}
<h1 class="club padding10 topmargin20">{{ match_group.name }}</h1>
<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 %}
{% for match in match_group.matches %}
{% include 'tournaments/match_cell.html' %}
{% endfor %}
</div>
{% endfor %}
{% endfor %}
{% else %}
<p class="padding10 topmargin20">Aucun match planifié pour cette journée.</p>
{% endif %}
{% else %}
<p class="padding10 topmargin20">Aucun match planifié pour ce tournoi.</p>
{% endif %}
{% endif %}
{% endblock %}

@ -989,27 +989,21 @@ def get_butterfly_bracket_view_context(tournament, parent_round=None, double_but
def tournament_prog(request, tournament_id):
tournament = get_object_or_404(Tournament, id=tournament_id)
# Get matches from all_groups
match_groups = tournament.all_groups(broadcasted=False)
# Flatten matches and add necessary attributes
all_matches = []
for group in match_groups:
for match in group.matches:
if match.start_date: # Only include matches with start dates
all_matches.append({
'start_date': match.start_date,
'court_index': match.court_index,
# Add other match attributes needed for match_cell.html
'match': match
})
# Sort matches by date and court
all_matches.sort(key=lambda x: (x['start_date'], x['court_index'] or 999))
# Get the day parameter from the request, if present
day_param = request.GET.get('day', None)
# Get days and match groups using our new method
days, match_groups = tournament.planned_matches_by_day(day=day_param)
# Format days for template
formatted_days = [day.strftime('%Y-%m-%d') for day in days]
context = {
'tournament': tournament,
'match_groups': {'matches': all_matches}
'match_groups': match_groups,
'days': days,
'formatted_days': formatted_days,
'selected_day': day_param or (days[0].strftime('%Y-%m-%d') if days else None)
}
return render(request, 'tournaments/prog.html', context)

Loading…
Cancel
Save