Skip to content

Instantly share code, notes, and snippets.

@mikeyakymenko
Last active May 5, 2024 22:07
Show Gist options
  • Save mikeyakymenko/f931d36b3f0259b534c642fd2f8f9911 to your computer and use it in GitHub Desktop.
Save mikeyakymenko/f931d36b3f0259b534c642fd2f8f9911 to your computer and use it in GitHub Desktop.
schedule unbalanced season (sports)
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