2

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
  • 60 games per season (in 16 teams leagues play every opponent 4x, in 32 team leagues play every opponent twice)
  • Five to eight 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).

Edit:

A little update as I'm still working on this:

  • I implemented the even distribution of home/away games
  • The script is now returning an actual schedule with 5 to 8 games per day, although with exceptions

See the following code for a 32 teams league:

import itertools
import random

def get_current_list(c):
    if c[0] != 0:
        if len(c[0]) != 0:
            return 0
        if len(c[0]) == 0 and len(c[1]) != 0:
            return 1
    else:
        return 1

def check_list_status(c,cl):
    if len(c[cl]) < 9:
        return True
    else:
        return False

def get_matchup(c, cl):
    games_today = []
    how_many_games_today = random.randint(5,8)
    
    error = False
    for game in range(how_many_games_today):
        game_not_found = True
        
        counter = 0
        while game_not_found:
            list_length = len(c[cl])
            index = list_length - 1

            counter += 1
            if counter > 100:
                error = True
                break
            
            choice_index = random.randint(0,index)

            choice = c[cl][choice_index]

            invalid = False
            for t_d in games_today:
                if choice[0] in t_d or choice[1] in t_d:
                    invalid = True
                    break
                else:
                    invalid = False

            if not invalid:
                games_today.append(choice)
                c[cl].pop(choice_index)
                game_not_found = False
            else:
                continue

        if error: break
    if error:
        list_ind_max = len(c[cl]) - 1
        single_ind = random.randint(0,list_ind_max)
        games_today = [c[cl][single_ind]]
        c[cl].pop(single_ind)

    return games_today,c

def finish_this_list(c, current_list):
    ret_list = []
    for x in c[current_list]:
        ret_list.append(x)

    c[current_list] = 0
    return c[current_list],c

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))
g = list(itertools.combinations(p, 2))
g = [x[::-1] for x in g]

c = [f, g]

schedule = {}
condition1 = True
day = 0

while condition1:
    day += 1

    current_list = get_current_list(c)
    last_round = check_list_status(c,current_list)

    if not last_round:
        todays_matchups,c = get_matchup(c, current_list)
        schedule[day] = todays_matchups
    else:
        schedule[day],c = finish_this_list(c, current_list)
        if current_list == 1:
            condition1 = False

print(schedule)

However, as you can see, this approach is a bit messy and still doesn't consider the rule of no more than two games in a row for each team. Moreover, I implemented some workarounds that don't feel very pythonic. Especially the counter in the main function to prevent ending up in an endless loop (if the script isn't able to find another matchup that doesn't include a team that is already playing on that day) and how the script manages if there are just a few entries left in the list (right now it's taking everything as one last day if there are less than nine entries in the list, although there could be a team playing twice on that day) appear to me like they need improvement.

Any help/hint on how to proceed best would be appreciated.

Community
  • 1
  • 1
trotta
  • 1,232
  • 1
  • 16
  • 23

0 Answers0