From f1497dd3397e84ffe30994f769b24da2469d02fa Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 16 Apr 2026 20:37:58 +0000 Subject: [PATCH 1/2] Initial plan From b7b2716b7a8a0c31dc8d692c8221669e6343ebb6 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 16 Apr 2026 20:42:11 +0000 Subject: [PATCH 2/2] fix: ignore unplayed 0-0 matches in ranking statistics Agent-Logs-Url: https://github.com/evroon/bracket/sessions/2090264a-3934-47b8-8b1f-2ac6af4c3142 Co-authored-by: evroon <11857441+evroon@users.noreply.github.com> --- backend/bracket/logic/ranking/calculation.py | 5 ++ .../unit_tests/ranking_calculation_test.py | 85 +++++++++++++++++++ 2 files changed, 90 insertions(+) diff --git a/backend/bracket/logic/ranking/calculation.py b/backend/bracket/logic/ranking/calculation.py index 7600ded59..fabd0879e 100644 --- a/backend/bracket/logic/ranking/calculation.py +++ b/backend/bracket/logic/ranking/calculation.py @@ -15,6 +15,10 @@ D = 400 +def match_has_result(match: MatchWithDetailsDefinitive) -> bool: + return not (match.stage_item_input1_score == 0 and match.stage_item_input2_score == 0) + + def set_statistics_for_stage_item_input( team_index: int, stats: defaultdict[StageItemInputId, TeamStatistics], @@ -76,6 +80,7 @@ def determine_ranking_for_stage_item( if not round_.is_draft for match in round_.matches if isinstance(match, MatchWithDetailsDefinitive) + if match_has_result(match) ] for match in matches: for team_index, stage_item_input in enumerate(match.stage_item_inputs): diff --git a/backend/tests/unit_tests/ranking_calculation_test.py b/backend/tests/unit_tests/ranking_calculation_test.py index 60f04914e..a7c936078 100644 --- a/backend/tests/unit_tests/ranking_calculation_test.py +++ b/backend/tests/unit_tests/ranking_calculation_test.py @@ -119,6 +119,91 @@ def test_determine_ranking_for_stage_item_elimination() -> None: } +def test_determine_ranking_for_stage_item_round_robin_ignores_unplayed_match() -> None: + tournament_id = TournamentId(-1) + now = datetime_utc.now() + stage_item_input1 = StageItemInputFinal( + id=StageItemInputId(-1), + team_id=TeamId(-1), + slot=1, + tournament_id=tournament_id, + team=Team(**DUMMY_TEAM1.model_dump(), id=TeamId(-1)), + ) + stage_item_input2 = StageItemInputFinal( + id=StageItemInputId(-2), + team_id=TeamId(-2), + slot=1, + tournament_id=tournament_id, + team=Team(**DUMMY_TEAM2.model_dump(), id=TeamId(-2)), + ) + + ranking = determine_ranking_for_stage_item( + StageItemWithRounds( + rounds=[ + RoundWithMatches( + id=RoundId(-1), + matches=[ + MatchWithDetailsDefinitive( + id=MatchId(-1), + stage_item_input1=stage_item_input1, + stage_item_input2=stage_item_input2, + created=now, + duration_minutes=90, + margin_minutes=15, + round_id=RoundId(-1), + stage_item_input1_score=0, + stage_item_input2_score=0, + stage_item_input1_conflict=False, + stage_item_input2_conflict=False, + ), + MatchWithDetailsDefinitive( + id=MatchId(-2), + stage_item_input1=stage_item_input1, + stage_item_input2=stage_item_input2, + created=now, + duration_minutes=90, + margin_minutes=15, + round_id=RoundId(-1), + stage_item_input1_score=2, + stage_item_input2_score=0, + stage_item_input1_conflict=False, + stage_item_input2_conflict=False, + ), + ], + stage_item_id=StageItemId(-1), + created=now, + is_draft=False, + name="", + ) + ], + inputs=[stage_item_input1, stage_item_input2], + type_name="Round Robin", + team_count=4, + ranking_id=None, + id=StageItemId(-1), + stage_id=StageId(-1), + name="", + created=now, + type=StageType.ROUND_ROBIN, + ), + Ranking( + id=RankingId(-1), + tournament_id=tournament_id, + created=now, + win_points=Decimal("3.5"), + draw_points=Decimal("1.25"), + loss_points=Decimal("0.0"), + add_score_points=False, + position=0, + ), + ) + + assert ranking == { + -2: TeamStatistics(wins=0, draws=0, losses=1, points=Decimal("0.0")), + -1: TeamStatistics(wins=1, draws=0, losses=0, points=Decimal("3.5")), + } + + def test_determine_ranking_for_stage_item_swiss() -> None: tournament_id = TournamentId(-1) now = datetime_utc.now()