finished implementing tournaments, slowed game ticks to 8 seconds

This commit is contained in:
Sakimori 2021-01-03 23:18:45 -05:00
parent 63db3ba1be
commit ff582d8709
4 changed files with 203 additions and 55 deletions

View File

@ -185,11 +185,10 @@ class team(object):
for this_player in self.rotation:
for stat in this_player.game_stats.keys():
this_player.game_stats[stat] = 0
return True
return self
def finalize(self):
if self.is_ready():
if self.pitcher is None:
self.set_pitcher()
while len(self.lineup) <= 4:
self.lineup.append(random.choice(self.lineup))

View File

@ -20,14 +20,25 @@ class division(object):
self.teams = {} #key: team object, value: {wins; rd (run diff)}
class tournament(object):
def __init__(self, name, team_dic, series_length = 5, max_innings = 9):
def __init__(self, name, team_dic, series_length = 5, finals_series_length = 7, max_innings = 9, id = None, secs_between_games = 300, secs_between_rounds = 600):
self.name = name
self.teams = team_dic #same format as division, wins/losses will be used for seeding later
self.bracket = None
self.results = None
self.series_length = series_length
self.finals_length = finals_series_length
self.game_length = max_innings
self.active = False
self.delay = secs_between_games
self.round_delay = secs_between_rounds
self.finals = False
self.id = id
if id is None:
self.id = random.randint(1111,9999)
else:
self.id = id
def build_bracket(self, random_sort = False, by_wins = False):
teams_list = list(self.teams.keys()).copy()
@ -46,12 +57,12 @@ class tournament(object):
teams_list.sort(key=sorter, reverse=True)
bracket_layers = int(math.ceil(math.log(len(teams_list), 2)))
empty_slots = int(math.pow(2, bracket_layers) - len(teams_list))
for i in range(0, empty_slots):
teams_list.append(None)
print(teams_list)
previous_bracket_layer = teams_list.copy()
for i in range(0, bracket_layers - 1):
@ -60,19 +71,27 @@ class tournament(object):
if pair % 2 == 0: #if even number
this_layer.insert(0+int(pair/2), [previous_bracket_layer.pop(0), previous_bracket_layer.pop(-1)]) #every other pair goes at front of list, moving forward
else:
this_layer.insert(0-int((1+pair)/2), [previous_bracket_layer.pop(0), previous_bracket_layer.pop(-1)]) #every other pair goes at end of list, moving backward
this_layer.insert(0-int((1+pair)/2), [previous_bracket_layer.pop(int(len(previous_bracket_layer)/2)-1), previous_bracket_layer.pop(int(len(previous_bracket_layer)/2))]) #every other pair goes at end of list, moving backward
previous_bracket_layer = this_layer
print(previous_bracket_layer)
self.bracket = bracket(previous_bracket_layer, bracket_layers)
self.bracket.get_bottom_row()
def round_check(self):
if self.bracket.depth == 1:
self.finals = True
return True
else:
return False
class bracket(object):
this_bracket = []
def __init__(self, bracket_list, depth):
self.this_bracket = bracket_list
self.depth = depth
self.bottom_row = []
def get_bottom_row(self):
self.depth = 1
self.bottom_row = []
self.dive(self.this_bracket)
return self.bottom_row
@ -81,4 +100,28 @@ class bracket(object):
if not isinstance(branch[0], list): #if it's a pair of games
self.bottom_row.append(branch)
else:
self.depth += 1
return self.dive(branch[0]), self.dive(branch[1])
#def set_winners(self, branch, winners_list):
#new_bracket =
def set_winners_dive(self, winners_list, index = 0, branch = None, parent = None):
if branch is None:
branch = self.this_bracket.copy()
if not isinstance(branch[0], list): #if it's a pair of games
if branch[0].name in winners_list or branch[1] is None:
winner = branch[0]
if parent is not None:
parent[index] = winner
elif branch[1].name in winners_list:
winner = branch[1]
if parent is not None:
parent[index] = winner
else:
self.set_winners_dive(winners_list, index = 0, branch = branch[0], parent = branch)
self.set_winners_dive(winners_list, index = 1, branch = branch[1], parent = branch)
if parent is None:
self.this_bracket = branch
return branch

View File

@ -153,4 +153,4 @@ def update_loop():
})
socketio.emit("states_update", data_to_send)
time.sleep(6)
time.sleep(8)

View File

@ -427,25 +427,38 @@ class AssignOwnerCommand(Command):
class StartTournamentCommand(Command):
name = "starttournament"
template = "m;starttournament"
description = "We'll DM you and get your own tournament set up. Just follow our instructions and we'll be right as rain."
template = """m;starttournament
[tournament name]
[list of teams, each on a new line]"""
description = "Starts a tournament with the teams given. Byes will be given to teams to allow for numbers other than powers of two. The current tournament format is:\nBest of 5 until the finals, which are Best of 7"
async def execute(self, msg, command):
test_bracket = {
games.get_team("Milwaukee Lockpicks") : {"wins": 10, "rd": 0},
games.get_team("Madagascar Penguins") : {"wins": 2, "rd": 0},
games.get_team("Twin Cities Evening") : {"wins": 1, "rd": 0},
games.get_team("Washington State Houses") : {"wins": 9, "rd": 0},
games.get_team("Appalachian Underground") : {"wins": 8, "rd": 0},
games.get_team("Pacific2 Rams") : {"wins": 3, "rd": 0},
games.get_team("New Jersey Radio") : {"wins": 45, "rd": 0},
games.get_team("Moline Jolenes") : {"wins": 44, "rd": 0},
games.get_team("California Commissioners") : {"wins": 41, "rd": 0},
games.get_team("Pigeons Reckoning") : {"wins": 45, "rd": 0},
games.get_team("Kernow Technologists") : {"wins": 42, "rd": 0}
}
tourney = leagues.tournament("Test Tourney", test_bracket, max_innings=3)
tourney.build_bracket(by_wins=True)
to_parse = command.split("\n")[0]
if "--rounddelay " in to_parse:
try:
round_delay = int(to_parse.split("--rounddelay ")[1].split(" ")[0])
except ValueError:
await msg.channel.send("The delay between rounds should be a whole number.")
return
if round_delay < 1 or round_delay > 120:
await msg.channel.send("The delay between rounds has to be between 1 and 120 minutes.")
else:
round_delay = 10
tourney_name = command.split("\n")[1]
list_of_team_names = command.split("\n")[2:]
team_dic = {}
for name in list_of_team_names:
team = get_team_fuzzy_search(name.strip())
if team == None:
await msg.channel.send(f"We couldn't find {name}. Try again?")
return
team_dic[team] = {"wins": 0}
id = random.randint(1111,9999)
tourney = leagues.tournament(tourney_name, team_dic, id=id, secs_between_rounds = round_delay * 60)
tourney.build_bracket(random_sort = True)
await start_tournament_round(msg.channel, tourney)
@ -477,7 +490,7 @@ commands = [
client = discord.Client()
gamesarray = []
gamesqueue = []
active_tournaments = []
setupmessages = {}
thread1 = threading.Thread(target=main_controller.update_loop)
@ -684,6 +697,9 @@ async def watch_game(channel, newgame, user = None, league = None):
discrim_string = league
state_init["is_league"] = True
elif user is not None:
if isinstance(user, str):
discrim_string = f"Started by {user}"
else:
discrim_string = f"Started by {user.name}"
state_init["is_league"] = False
else:
@ -739,13 +755,12 @@ async def start_tournament_round(channel, tourney, seeding = None):
for pair in games_to_start:
if pair[0] is not None and pair[1] is not None:
this_game = games.game(pair[0].finalize(), pair[1].finalize(), length = tourney.game_length)
this_game = games.game(pair[0].prepare_for_save().finalize(), pair[1].prepare_for_save().finalize(), length = tourney.game_length)
this_game, state_init = prepare_game(this_game)
state_init["is_league"] = True
state_init["title"] = f"{tourney.name}: Round of {len(games_to_start)*2}"
state_init["title"] = f"0 - 0"
discrim_string = tourney.name
print(discrim_string)
timestamp = str(time.time() * 1000.0 + random.randint(0,3000))
current_games.append((this_game, timestamp))
@ -753,28 +768,100 @@ async def start_tournament_round(channel, tourney, seeding = None):
ext = "?league=" + urllib.parse.quote_plus(tourney.name)
if tourney.round_check(): #if finals
await channel.send(f"The {tourney.name} finals are starting now, at {config()['simmadome_url']+ext}")
finals = True
else:
await channel.send(f"{len(current_games)} games started for the {tourney.name} tournament, at {config()['simmadome_url']+ext}")
await tourney_watcher(channel, tourney, current_games)
finals = False
await tourney_round_watcher(channel, tourney, current_games, config()['simmadome_url']+ext, finals)
async def continue_tournament_series(tourney, queue, games_list, wins_in_series):
for oldgame in queue:
away_team = games.get_team(oldgame.teams["away"].name)
home_team = games.get_team(oldgame.teams["home"].name)
this_game = games.game(away_team.finalize(), home_team.finalize(), length = tourney.game_length)
this_game, state_init = prepare_game(this_game)
async def tourney_watcher(channel, tourney, games_list):
state_init["is_league"] = True
state_init["title"] = f"{wins_in_series[oldgame.teams['away'].name]} - {wins_in_series[oldgame.teams['home'].name]}"
discrim_string = tourney.name
timestamp = str(time.time() * 1000.0 + random.randint(0,3000))
games_list.append((this_game, timestamp))
main_controller.master_games_dic[timestamp] = (this_game, state_init, discrim_string)
return games_list
async def tourney_round_watcher(channel, tourney, games_list, filter_url, finals = False):
tourney.active = True
active_tournaments.append(tourney)
wins_in_series = {}
winner_list = []
while tourney.active:
queued_games = []
while len(games_list) > 0:
try:
for i in range(0, len(games_list)):
game, key = games_list[i]
if game.over and main_controller.master_games_dic[key][1]["end_delay"] <= 9:
if game.teams['home'].name not in wins_in_series.keys():
wins_in_series[game.teams["home"].name] = 0
if game.teams['away'].name not in wins_in_series.keys():
wins_in_series[game.teams["away"].name] = 0
winner_name = game.teams['home'].name if game.teams['home'].score > game.teams['away'].score else game.teams['away'].name
if winner_name in wins_in_series.keys():
wins_in_series[winner_name] += 1
else:
wins_in_series[winner_name] = 1
final_embed = game_over_embed(game)
await channel.send(f"A {tourney.name} game just ended!")
await channel.send(embed=final_embed)
if wins_in_series[winner_name] >= int((tourney.series_length+1)/2) and not finals:
winner_list.append(winner_name)
elif wins_in_series[winner_name] >= int((tourney.finals_length+1)/2):
winner_list.append(winner_name)
else:
queued_games.append(game)
games_list.pop(i)
break
except:
print("something went wrong in tourney_watcher")
await asyncio.sleep(4)
if len(queued_games) > 0:
await channel.send(f"The next batch of games for {tourney.name} will start in {int(tourney.delay/60)} minutes.")
await asyncio.sleep(tourney.delay)
await channel.send(f"{len(queued_games)} games for {tourney.name}, starting at {filter_url}")
games_list = await continue_tournament_series(tourney, queued_games, games_list, wins_in_series)
else:
tourney.active = False
await channel.send(f"This round of games for {tourney.name} is now complete!")
if finals: #if this last round was finals
embed = discord.Embed(color = discord.Color.dark_purple(), title = f"{winner_list[0]} win the {tourney.name} finals!")
await channel.send(embed=embed)
active_tournaments.pop(active_tournaments.index(tourney))
return
tourney.bracket.set_winners_dive(winner_list)
winners_string = ""
for game in tourney.bracket.get_bottom_row():
winners_string += f"{game[0].name}\n{game[1].name}\n"
await channel.send(f"""
This round of games for {tourney.name} is now complete! The next round will be starting in {int(tourney.round_delay/60)} minutes.
Advancing teams:
{winners_string}""")
await asyncio.sleep(tourney.round_delay)
await start_tournament_round(channel, tourney)
async def team_delete_confirm(channel, team, owner):
@ -843,8 +930,8 @@ def team_from_collection(newteam_json):
raise CommandError("We've given you 100 characters for the slogan. Discord puts limits on us and thus, we put limits on you. C'est la vie.")
if len(newteam_json["lineup"]) > 20:
raise CommandError("20 players in the lineup, maximum. We're being really generous here.")
if not len(newteam_json["rotation"]) == 1:
raise CommandError("One and only one pitcher per team, thanks.")
if not len(newteam_json["rotation"]) > 8:
raise CommandError("8 pitchers on the rotation, max. That's a *lot* of pitchers.")
for player in newteam_json["lineup"] + newteam_json["rotation"]:
if len(player["name"]) > 70:
raise CommandError(f"{player['name']} is too long, chief. 70 or less.")
@ -1003,4 +1090,23 @@ def get_team_fuzzy_search(team_name):
team = teams[0]
return team
#test_bracket = {
# "Milwaukee Lockpicks" : {"wins": 4, "rd": 0},
# "Madagascar Penguins" : {"wins": 2, "rd": 0},
# "Twin Cities Evening" : {"wins": 1, "rd": 0},
# "Washington State Houses" : {"wins": 9, "rd": 0},
# "Appalachian Underground" : {"wins": 8, "rd": 0},
# "Pacific2 Rams" : {"wins": 3, "rd": 0},
# "New Jersey Radio" : {"wins": 11, "rd": 0},
# "Moline Jolenes" : {"wins": 6, "rd": 0},
# "California Commissioners" : {"wins": 10, "rd": 0},
# "Pigeons Reckoning" : {"wins": 7, "rd": 0},
# "Kernow Technologists" : {"wins": 5, "rd": 0}
# }
#tourney = leagues.tournament("Test Tourney", test_bracket, max_innings=3)
#tourney.build_bracket(by_wins=True)
#tourney.bracket.set_winners_dive(['Twin Cities Evening','Madagascar Penguins', 'Pacific2 Rams'])
#print(tourney.bracket.this_bracket)
client.run(config()["token"])