diff --git a/tournaments/models/match.py b/tournaments/models/match.py index 08a4b42..856f13d 100644 --- a/tournaments/models/match.py +++ b/tournaments/models/match.py @@ -423,6 +423,37 @@ class Match(TournamentSubModel): return timezone.now() > self.start_date return False + def will_start(self): + """ + Returns True if match will start within the next hour + """ + if self.disabled or self.end_date: + return False + + # Check start_date first + if self.start_date: + now = timezone.now() + time_until_start = (self.start_date - now).total_seconds() + return 0 < time_until_start <= 3600 # Within 1 hour (3600 seconds) + + # Check planned_start_date as fallback + if self.planned_start_date: + now = timezone.now() + time_until_start = (self.planned_start_date - now).total_seconds() + return 0 < time_until_start <= 3600 # Within 1 hour (3600 seconds) + + return False + + def is_ongoing(self): + """ + Returns True if match has started but not finished + """ + if self.disabled: + return False + + # Match is ongoing if it has started but hasn't ended + return self.started() and self.end_date is None + def should_appear(self): if self.disabled is True: return False diff --git a/tournaments/models/tournament.py b/tournaments/models/tournament.py index a9a0566..f94885f 100644 --- a/tournaments/models/tournament.py +++ b/tournaments/models/tournament.py @@ -1031,6 +1031,72 @@ class Tournament(BaseModel): def will_start_soon(self, hour_delta=2): return self.has_started(hour_delta=hour_delta) + def has_ongoing_matches(self): + """ + Returns True if tournament has any matches that are currently ongoing + """ + # Check matches in rounds + for round_obj in self.rounds.all(): + for match in round_obj.matches.all(): + if match.is_ongoing(): + return True + + # Check matches in group stages + for group_stage in self.group_stages.all(): + for match in group_stage.matches.all(): + if match.is_ongoing(): + return True + + return False + + def has_matches_starting_soon(self): + """ + Returns True if tournament has any matches starting within the next hour + """ + # Check matches in rounds + for round_obj in self.rounds.all(): + for match in round_obj.matches.all(): + if match.will_start(): + return True + + # Check matches in group stages + for group_stage in self.group_stages.all(): + for match in group_stage.matches.all(): + if match.will_start(): + return True + + return False + + def get_next_match_start_time(self): + """ + Returns the datetime of the earliest upcoming match, or None if no upcoming matches + """ + next_times = [] + + # Check matches in rounds + for round_obj in self.rounds.all(): + for match in round_obj.matches.all(): + if match.disabled or match.end_date: + continue + + if match.start_date and match.start_date > timezone.now(): + next_times.append(match.start_date) + elif match.planned_start_date and match.planned_start_date > timezone.now(): + next_times.append(match.planned_start_date) + + # Check matches in group stages + for group_stage in self.group_stages.all(): + for match in group_stage.matches.all(): + if match.disabled or match.end_date: + continue + + if match.start_date and match.start_date > timezone.now(): + next_times.append(match.start_date) + elif match.planned_start_date and match.planned_start_date > timezone.now(): + next_times.append(match.planned_start_date) + + return min(next_times) if next_times else None + def are_teams_positioned(self): teams = self.team_registrations.all() filtered_teams = [t for t in teams if t.is_positioned()] diff --git a/tournaments/templates/tournaments/broadcast/broadcasted_auto_event.html b/tournaments/templates/tournaments/broadcast/broadcasted_auto_event.html deleted file mode 100644 index cf8a9f7..0000000 --- a/tournaments/templates/tournaments/broadcast/broadcasted_auto_event.html +++ /dev/null @@ -1,263 +0,0 @@ - - - {% load static %} - {% load qr_code %} - -
- {% include 'tournaments/broadcast/base_head.html' %} - - - -
-