From ada5dc4c6ff30ee39f2b4d145675800e0b9410e9 Mon Sep 17 00:00:00 2001 From: Jury Razumau Date: Sun, 10 Mar 2024 22:06:46 +0100 Subject: [PATCH] adjust position for teams below teams without rosters --- scripts/tournament.py | 45 ++++++++++++-- tests/test_missing_rosters_adjustment.py | 77 ++++++++++++++++++++++++ 2 files changed, 118 insertions(+), 4 deletions(-) create mode 100644 tests/test_missing_rosters_adjustment.py diff --git a/scripts/tournament.py b/scripts/tournament.py index 2ad856f..02dea6d 100644 --- a/scripts/tournament.py +++ b/scripts/tournament.py @@ -1,6 +1,6 @@ import pandas as pd import numpy as np -from typing import Any, Tuple, Set +from typing import Any, Tuple, Set, List, Dict import numpy.typing as npt from .constants import ( D2_MULTIPLIER, @@ -85,9 +85,12 @@ def __init__( if len(team_data["teamMembers"]) == 0 ] if teams_without_players: - raise EmptyTournamentException( - f"There are {len(teams_without_players)} teams without any players. First such team: {teams_without_players[0]}." - ) + if len(teams_without_players) == len(teams): + raise EmptyTournamentException("All teams have no players") + + print(f"Adjusting for missing rosters in tournament {self.id}") + teams = self.adjust_for_missing_rosters(teams_without_players, teams) + self.data = pd.DataFrame(teams.values()) self.data["heredity"] = self.continuity_rule.counts( self.data.n_base, self.data.n_legs, self.data.name == self.data.current_name @@ -199,3 +202,37 @@ def tournament_type_to_coeff(ttype: int) -> float: if ttype in models.TRNMT_TYPES: return SYNCHRONOUS_TOURNAMENT_COEFFICIENT raise Exception(f"tournament type {ttype} is not supported!") + + @staticmethod + def adjust_for_missing_rosters(teams_without_rosters: List[int], teams: Dict): + if not teams_without_rosters: + return teams + + positions_without_rosters = [ + team["position"] + for team_id, team in teams.items() + if team_id in teams_without_rosters + ] + + for team_id, team in teams.items(): + if team_id in teams_without_rosters: + continue + + teams_above_without_roster = len( + [pos for pos in positions_without_rosters if pos < team["position"]] + ) + + teams_in_same_position = len( + [pos for pos in positions_without_rosters if pos == team["position"]] + ) + + if teams_above_without_roster: + team["position"] -= teams_above_without_roster + + if teams_in_same_position: + team["position"] -= teams_in_same_position / 2.0 + + for team_id in teams_without_rosters: + del teams[team_id] + + return teams diff --git a/tests/test_missing_rosters_adjustment.py b/tests/test_missing_rosters_adjustment.py new file mode 100644 index 0000000..6f0e333 --- /dev/null +++ b/tests/test_missing_rosters_adjustment.py @@ -0,0 +1,77 @@ +import unittest +from dotenv import load_dotenv + +load_dotenv("../.env.test") + +import django + +django.setup() + +from scripts.tournament import Tournament + + +class TestMissingRostersAdjustment(unittest.TestCase): + def setUp(self): + self.teams = { + 1: {"position": 1}, + 2: {"position": 2}, + 3: {"position": 3}, + } + + self.more_teams = { + 1: {"position": 1}, + 2: {"position": 2}, + 3: {"position": 3.5}, + 4: {"position": 3.5}, + 5: {"position": 5}, + 6: {"position": 6}, + } + + def test_no_missing_rosters_(self): + teams = Tournament.adjust_for_missing_rosters([], self.teams) + self.assertEqual(teams, self.teams) + + def test_missing_roster_middle(self): + teams = Tournament.adjust_for_missing_rosters([2], self.teams) + expected = { + 1: {"position": 1}, + 3: {"position": 2}, + } + self.assertEqual(expected, teams) + + def test_missing_roster_last_place(self): + teams = Tournament.adjust_for_missing_rosters([3], self.teams) + expected = { + 1: {"position": 1}, + 2: {"position": 2}, + } + self.assertEqual(expected, teams) + + def test_missing_roster_first_place(self): + teams = Tournament.adjust_for_missing_rosters([1], self.teams) + expected = { + 2: {"position": 1}, + 3: {"position": 2}, + } + self.assertEqual(expected, teams) + + def test_multiple_missing_rosters(self): + updated_teams = Tournament.adjust_for_missing_rosters([2, 5], self.more_teams) + expected = { + 1: {"position": 1}, + 3: {"position": 2.5}, + 4: {"position": 2.5}, + 6: {"position": 4}, + } + self.assertEqual(expected, updated_teams) + + def test_missing_roster_shared_position(self): + updated_teams = Tournament.adjust_for_missing_rosters([4], self.more_teams) + expected = { + 1: {"position": 1}, + 2: {"position": 2}, + 3: {"position": 3}, + 5: {"position": 4}, + 6: {"position": 5}, + } + self.assertEqual(expected, updated_teams)