Assuming you have python (and installed pandas for it):
import math
import pandas as pd
import random
pd.options.mode.chained_assignment = None
#teams = ['A','B','C','D','E','F','G','H']
#teams = ['A','B','C','D','E','F','G','H','I']
teams = ['A','B','C','D','E','F','G','H','I','J','K','L','M']
df_teams = pd.DataFrame(teams,columns=['team_number'])
def createOneMatchPerTeam(df_team_list, starting_match_index):
df_teams = df_team_list.copy()
df_teams['rand_match'] = [ random.randint(1,len(teams)) for k in df_teams.index]
df_teams.sort_values(by=['rand_match'], inplace=True)
df_teams['rand_match_rank'] = df_teams['rand_match'].rank(ascending=False,method='first')
df_teams['MatchNum'] = [ math.floor((df_teams.iloc[k]['rand_match_rank'] - 1) / 4.0) for k in df_teams.index]
match_num_list = df_teams.MatchNum.unique()
match_num_list.sort()
df_matches = None
cur_match_index = 0
for match_num in match_num_list:
df_match_teams = df_teams.query("MatchNum == " + str(match_num))
if len(df_match_teams) == 4:
df_match_teams['rand_team'] = [ random.randint(0,len(df_match_teams)-1) for k in df_match_teams.index]
df_match_teams.sort_values(by=['rand_team'], inplace=True)
df_match_teams['rand_team_rank'] = df_match_teams['rand_team'].rank(ascending=False,method='first')
df_match_teams['rand_team_rank'] = df_match_teams['rand_team_rank'].astype(int)
#df_match_teams['TeamNum'] = [ math.floor((df_match_teams.iloc[k]['rand_team_rank'] - 1) / 2.0) for k in df_match_teams.index]
d_match = dict()
d_match['match_num'] = starting_match_index + cur_match_index
cur_match_index = cur_match_index + 1
d_match['red1'] = df_match_teams.query("rand_team_rank==1").iloc[0]['team_number']
d_match['red2'] = df_match_teams.query("rand_team_rank==2").iloc[0]['team_number']
d_match['blue1'] = df_match_teams.query("rand_team_rank==3").iloc[0]['team_number']
d_match['blue2'] = df_match_teams.query("rand_team_rank==4").iloc[0]['team_number']
if df_matches is None:
df_matches = pd.DataFrame.from_dict([d_match])
else:
df_matches = df_matches.append(pd.DataFrame.from_dict([d_match]))
else:
print("Need to fill in teams for match " + str(match_num))
df_matches['match_num'] = df_matches['match_num'].astype(int)
return df_matches
def createRandomSchedule(df_team_list, min_num_matches):
df_team = df_team_list
num_teams = df_team.shape[0]
num_teams_per_batch = math.floor(num_teams / 4) * 4
df_team_match_count = df_team[['team_number']]
df_team_match_count['match_count'] = 0
loop_count = 0
df_matches = None
while df_team_match_count.match_count.min() < min_num_matches:
if 'rand' in df_team_match_count.columns:
df_team_match_count.drop(columns=['rand','match_count_plus_rand'])
df_team_match_count['rand'] = [ random.random() for k in df_team_match_count.index]
df_team_match_count['match_count_plus_rand'] = df_team_match_count['match_count'] + df_team_match_count['rand']
df_team_match_count.sort_values(by=['match_count','match_count_plus_rand'],ascending=[True,True], inplace=True)
df_team_match_count['rand_match_count_rank'] = df_team_match_count['match_count_plus_rand'].rank(ascending=True,method='first')
df_team_match_count['rand_match_count_rank'] = df_team_match_count['rand_match_count_rank'].astype(int)
df_team_nums_this_batch = df_team_match_count.query("rand_match_count_rank <= " + str(num_teams_per_batch))
df_teams_batch = df_team_nums_this_batch[['team_number']].join(df_team.set_index('team_number'),on='team_number')
df_teams_batch.reset_index(inplace=True)
if df_matches is None:
df_matches = createOneMatchPerTeam(df_teams_batch, 1)
else:
df_matches = df_matches.append(createOneMatchPerTeam(df_teams_batch, (num_teams_per_batch / 4) * loop_count + 1))
loop_count = loop_count + 1
df_team_match_count.loc[df_team_match_count['team_number'].isin(df_team_nums_this_batch['team_number'].to_list()), 'match_count'] += 1
return df_matches
print(createRandomSchedule(df_teams,10))
Nothing especially fancy here - nothing to prevent back-to-back matches, prevent duplicative pairings, etc.