mardi 23 avril 2019

Sport league Scheduling: Uneven distributed matchups

I'm currently trying to create schedules for different leagues. I have read questions on round robin and am also able to create a schedule for a season with a first an a second half. However, what I'm trying to achieve is:

  • Leagues with 16 or 32 teams
  • 64 games per season (in 16 teams leagues play every opponent 4x, in 32 team leagues play every opponent twice)
  • Four to seven Games per day
  • No multiple games per team per day
  • Even distribution of home and away games
  • Games on consecutive days are possible, but not more than two in a row

What have I tried so far? As a first step, I created a list of all possible matchups with itertools:

import itertools

p = ['A0', 'A1', 'A2', 'A3', 'A4', 'A5', 'A6', 'A7', 'A8', 'A9', 'A10', 'A11', 'A12', 'A13', 'A14', 'A15', 'A16', 'A17', 'A18', 'A19', 'A20', 'A21', 'A22', 'A23', 'A24', 'A25', 'A26', 'A27', 'A28', 'A29', 'A30', 'A31']

f = list(itertools.combinations(p, 2))

# [('A0', 'A1'), ('A0', 'A2'), ('A0', 'A3'), ... ]

From here on, I might chose a wrong path, deciding to work with indexes. Hence, I created a list of lists c, where every sub-list is a copy of f. The list f is represented n times in c depending on the size of the league (16 teams: 4x; 32 teams: 2x).

import itertools
import random

def get_correct_ind(list_of_lists):
    if len(list_of_lists[0]) == 0:
        return 1
    else:
        return 0

def get_a_matchup(list_of_lists):
    corr_ind = get_correct_ind(list_of_lists)
    list_length = len(list_of_lists[corr_ind])-1

    if list_length == 0:
        choice_ind = 0
    else:
        choice_ind = random.randint(0,list_length)

    choice = list_of_lists[corr_ind][choice_ind]
    meta = {'corr_ind':corr_ind, 'choice_ind':choice_ind}
    return choice,meta

# 16 teams:
f = list(itertools.combinations(p, 2))
g = list(itertools.combinations(p, 2))

c = [f, g]

day = 0
schedule = {}
cond1 = True
while cond1:
    if len(c[0]) == 0 and len(c[1]) == 0: cond1 = False
    day += 1

    matchups_today = []
    how_many_games_today = random.randint(4,7)

    counter = 0
    cond2 = True
    while cond2:
        counter += 1
        if counter == how_many_games_today: cond2 = False

        matchup,meta = get_a_matchup(c)

        invalid = False
        for team in matchup:
            if invalid: break
            for existing_matchup in matchups_today:
                if invalid: break
                if team in existing_matchup:
                    invalid = True
                    break

        if not invalid:
            matchups_today.append(matchup)
            c[meta['corr_ind']].pop(meta['choice_ind'])

    schedule[day] = matchups_today

As you can see, this approach is getting messy very quickly and doesn't even consider even distribution of home/away games, the rule of no more than two games in a row for each team and is also producing an error in this line: choice_ind = random.randint(0,list_length) (ValueError: empty range for randrange() (0,0, 0)) which I don't get as I control if list_length equals zero. Any help/hint on how to proceed best would be appreciated.




Aucun commentaire:

Enregistrer un commentaire