Last active
May 5, 2024 22:07
-
-
Save mikeyakymenko/f931d36b3f0259b534c642fd2f8f9911 to your computer and use it in GitHub Desktop.
schedule unbalanced season (sports)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from app.core.constants import Directions | |
class SeasonSchedule: | |
def __init__(self, units, season_shift=None): | |
self.units = units | |
self.north_units = [unit for unit in units if unit['division'] == Directions.North.value] | |
self.south_units = [unit for unit in units if unit['division'] == Directions.South.value] | |
self.season_shift = list(range(5)) if season_shift is None else season_shift | |
self.weeks = [] | |
self.games = set() | |
@staticmethod | |
def swap_game_units(unit_a, unit_b, swap): | |
if swap: | |
return tuple([unit_a, unit_b]) | |
else: | |
return tuple([unit_b, unit_a]) | |
def generate_games(self): | |
""" | |
mappings we need to iterate teams, initial is freeze, | |
cross division will be used for last two weeks. | |
""" | |
initial_map = self.season_shift.copy() | |
cross_division_map = self.season_shift.copy() | |
mapping = initial_map.copy() | |
""" | |
units_numbers is amount of units in group basically hard coded, doesn't matter for now | |
we'll use this number as iterator | |
""" | |
units_numbers = len(self.north_units) | |
""" | |
this is a division without rest, we'll use it as iterator as well | |
""" | |
middle = units_numbers // 2 | |
""" | |
iterate first 5 weeks / rounds | |
""" | |
for i in range(units_numbers): | |
""" | |
week which we'll fulfill | |
""" | |
games_round = [] | |
""" | |
here will happened magic. So we'll remove first element from list | |
and make list with 4 team slip it into two more list and reverse one | |
full [0, 1, 2, 3, 4] | |
and pick orphan | |
[1, 2, 3, 4] | |
orphan 0 | |
map1 [1, 2] | |
map2 [4, 3] | |
""" | |
orphan = mapping.pop(0) | |
map1 = mapping[:middle] | |
map2 = mapping[middle:] | |
map2.reverse() | |
""" | |
for each group we have 2 games, because we remove one from list. | |
so orphan variable we need only to rebuild next map of indexes | |
to pickup orphan teams which do not have opponent from group we use loop | |
iterator for weeks which is i | |
each week have 5 games, four of them is is 2 games for each group using loop | |
iterator j | |
so | |
map1 [1, 2] | |
map2 [4, 3] | |
become list picks by indexes | |
north_units[1] - north_units[2] | |
north_units[4] - north_units[3] | |
and same for south | |
""" | |
for j in range(middle): | |
""" | |
2 games for north group | |
""" | |
game_division_north = self.swap_game_units( | |
unit_a=self.north_units[map1[j]], | |
unit_b=self.north_units[map2[j]], | |
swap=i % 2 == 1 | |
) | |
""" | |
2 games for south group | |
""" | |
game_division_south = self.swap_game_units( | |
unit_a=self.south_units[map1[j]], | |
unit_b=self.south_units[map2[j]], | |
swap=i % 2 == 1 | |
) | |
""" | |
if conditions just check if game not exist | |
btw we do not handle error ;) | |
""" | |
if game_division_north not in self.games: | |
self.games.add(game_division_north) | |
games_round.append(game_division_north) | |
if game_division_south not in self.games: | |
self.games.add(game_division_south) | |
games_round.append(game_division_south) | |
""" | |
game of round orphans | |
""" | |
game_cross_division = tuple([ | |
self.north_units[i], | |
self.south_units[i] | |
]) | |
if game_cross_division not in self.games: | |
self.games.add(game_cross_division) | |
games_round.append(game_cross_division) | |
""" | |
restore mapping by adding orphan to the end of list | |
and makes teams round | |
[1, 2, 3, 4, 0] | |
""" | |
mapping.append(orphan) | |
""" | |
add the games_round/week to the season list | |
""" | |
self.weeks.append(games_round) | |
for i in range(2): | |
""" | |
week which we'll fulfill | |
""" | |
games_round = [] | |
""" | |
week which we'll fulfill | |
manipulate the cross divisoin mapping | |
[0, 1, 2, 3, 4] become [1, 2, 3, 4, 0] | |
use initial_map to iterate 5 games in week and pick north teams | |
north [0, 1, 2, 3, 4] | |
south [1, 2, 3, 4, 0] | |
in loop iterator as k we pick teams from their pools | |
north_units[k=0] - south_units[k=1] | |
north_units[k=1] - south_units[k=2] | |
etc... | |
""" | |
cross_division_map.insert(0, cross_division_map.pop()) | |
for k in initial_map: | |
additional_game = self.swap_game_units( | |
unit_a=self.north_units[initial_map[k]], | |
unit_b=self.south_units[cross_division_map[k]], | |
swap=k % 2 == 1 | |
) | |
if additional_game not in self.games: | |
self.games.add(additional_game) | |
games_round.append(additional_game) | |
self.weeks.append(games_round) | |
"""get data""" | |
def get_weeks(self): | |
return self.weeks | |
"""print weeks with games""" | |
def print_weeks(self): | |
for week_index, week in enumerate(self.weeks): | |
print(f'week {week_index + 1} 👇') | |
for game in week: | |
print(tuple([dict(game[0]), dict(game[1])])) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment