From 60f5f0c94ca4528b0a179256c8c0f8d7bb2e4320 Mon Sep 17 00:00:00 2001 From: Felipe Gomes de Melo Date: Thu, 7 Aug 2025 15:18:03 -0300 Subject: [PATCH] Fix match sorting algorithm (#1314) This PR alters the match scheduling logic Now, the algorithm schedules all matches for each stage in sequence (i.e. all matches from stage A, then all matches from stage B). Matches from stage items inside a single stage are interleaved. To guarantee that the correct order is followed, rounds are sorted according to their id. Lower round id are scheduled first. Fix #1312 --- backend/bracket/logic/planning/matches.py | 52 ++++++++++------------- 1 file changed, 23 insertions(+), 29 deletions(-) diff --git a/backend/bracket/logic/planning/matches.py b/backend/bracket/logic/planning/matches.py index 8bca54fa..fa02ccae 100644 --- a/backend/bracket/logic/planning/matches.py +++ b/backend/bracket/logic/planning/matches.py @@ -29,47 +29,41 @@ async def schedule_all_unscheduled_matches( if len(stages) < 1 or len(courts) < 1: return - stage = stages[0] - stage_items = sorted(stage.stage_items, key=lambda x: x.name) + time_last_match_from_previous_stage = tournament.start_time + position_last_match_from_previous_stage = 0 - # First schedule all matches from the first stage - for i, stage_item in enumerate(stage_items): - court = courts[min(i, len(courts) - 1)] - start_time = tournament.start_time - position_in_schedule = 0 - for round_ in stage_item.rounds: - for match in round_.matches: - if match.start_time is None and match.position_in_schedule is None: - await sql_reschedule_match_and_determine_duration_and_margin( - court.id, - start_time, - position_in_schedule, - match, - tournament, - ) + for stage in stages: + stage_items = sorted(stage.stage_items, key=lambda x: x.name) - start_time += timedelta(minutes=match.duration_minutes) - position_in_schedule += 1 + stage_start_time = time_last_match_from_previous_stage + stage_position_in_schedule = position_last_match_from_previous_stage - # Then, all other stages - for stage in stages[1:]: - start_time = tournament.start_time - position_in_schedule = 0 - for stage_item in stage.stage_items: - for round_ in stage_item.rounds: + for i, stage_item in enumerate(stage_items): + court = courts[min(i, len(courts) - 1)] + start_time = stage_start_time + position_in_schedule = stage_position_in_schedule + for round_ in sorted(stage_item.rounds, key=lambda r: r.id): for match in round_.matches: - start_time += timedelta(minutes=match.duration_minutes) - position_in_schedule += 1 - if match.start_time is None and match.position_in_schedule is None: await sql_reschedule_match_and_determine_duration_and_margin( - courts[-1].id, + court.id, start_time, position_in_schedule, match, tournament, ) + start_time += timedelta(minutes=match.duration_minutes) + position_in_schedule += 1 + + time_last_match_from_previous_stage = max( + time_last_match_from_previous_stage, start_time + ) + + position_last_match_from_previous_stage = max( + position_last_match_from_previous_stage, position_in_schedule + ) + await update_start_times_of_matches(tournament_id)