standings and wildcard commands added

This commit is contained in:
Sakimori 2021-01-14 23:39:08 -05:00
parent 6b56c87bef
commit 333476548d
2 changed files with 196 additions and 67 deletions

View File

@ -13,6 +13,7 @@ class league_structure(object):
self.historic = False self.historic = False
self.owner = None self.owner = None
self.season = 1 self.season = 1
self.autoplay = -1
def setup(self, league_dic, division_games = 1, inter_division_games = 1, inter_league_games = 1, games_per_hour = 2): def setup(self, league_dic, division_games = 1, inter_division_games = 1, inter_league_games = 1, games_per_hour = 2):
self.league = league_dic # { subleague name : { division name : [team object] } } self.league = league_dic # { subleague name : { division name : [team object] } }
@ -182,6 +183,22 @@ class league_structure(object):
scheduled = True scheduled = True
day += 1 day += 1
def division_standings(self, division, standings):
def sorter(team_in_list):
if team_in_list[2] == 0 and team_in_list[1] == 0:
return (0, team_in_list[3])
return (team_in_list[1]/(team_in_list[1]+team_in_list[2]), team_in_list[3])
teams = division.copy()
for index in range(0, len(teams)):
this_team = teams[index]
teams[index] = [this_team, standings[teams[index].name]["wins"], standings[teams[index].name]["losses"], standings[teams[index].name]["run_diff"], 0]
teams.sort(key=sorter, reverse=True)
return teams
def standings_embed(self): def standings_embed(self):
this_embed = Embed(color=Color.purple(), title=self.name) this_embed = Embed(color=Color.purple(), title=self.name)
standings = {} standings = {}
@ -191,21 +208,54 @@ class league_structure(object):
this_embed.add_field(name="Subleague:", value=f"**{subleague}**", inline = False) this_embed.add_field(name="Subleague:", value=f"**{subleague}**", inline = False)
for division in iter(self.league[subleague].keys()): for division in iter(self.league[subleague].keys()):
this_embed.add_field(name="Division:", value=f"**{division}**", inline = False) this_embed.add_field(name="Division:", value=f"**{division}**", inline = False)
teams = self.league[subleague][division].copy() teams = self.division_standings(self.league[subleague][division], standings)
for index in range(0, len(teams)):
this_team = teams[index]
teams[index] = (this_team, standings[teams[index].name]["wins"], standings[teams[index].name]["losses"], standings[teams[index].name]["run_diff"],)
def sorter(team_in_list): for index in range(0, len(teams)):
return (team_in_list[1], team_in_list[3]) if index == self.constraints["division_leaders"] - 1:
teams.sort(key=sorter, reverse=True) teams[index][4] = "-"
else:
games_behind = ((teams[self.constraints["division_leaders"] - 1][1] - teams[index][1]) + (teams[index][2] - teams[self.constraints["division_leaders"] - 1][2]))/2
teams[index][4] = games_behind
for this_team in teams: for this_team in teams:
this_embed.add_field(name=this_team[0].name, value=f"{this_team[1]} - {this_team[2]} Diff: {this_team[3]}", inline = False) if this_team[2] != 0 or this_team[1] != 0:
this_embed.add_field(name=this_team[0].name, value=f"{this_team[1]} - {this_team[2]} WR: {round(this_team[1]/(this_team[1]+this_team[2]), 3)} GB: {this_team[4]}", inline = False)
else:
this_embed.add_field(name=this_team[0].name, value=f"{this_team[1]} - {this_team[2]} WR: - GB: {this_team[4]}", inline = False)
this_embed.set_footer(text=f"Standings as of day {self.day-1}") this_embed.set_footer(text=f"Standings as of day {self.day-1}")
return this_embed return this_embed
def wildcard_embed(self):
this_embed = Embed(color=Color.purple(), title=f"{self.name} Wildcard Race")
standings = {}
for team_name, wins, losses, run_diff in league_db.get_standings(self.name):
standings[team_name] = {"wins" : wins, "losses" : losses, "run_diff" : run_diff}
for subleague in iter(self.league.keys()):
this_embed.add_field(name="Subleague:", value=f"**{subleague}**", inline = False)
subleague_array = []
for division in iter(self.league[subleague].keys()):
this_div = [this_team for this_team, wins, losses, diff, gb in self.division_standings(self.league[subleague][division], standings)[self.constraints["division_leaders"]:]]
subleague_array += this_div
teams = self.division_standings(subleague_array, standings)
for index in range(0, len(teams)):
if index == self.constraints["wild_cards"] - 1:
teams[index][4] = "-"
else:
games_behind = ((teams[self.constraints["wild_cards"] - 1][1] - teams[index][1]) + (teams[index][2] - teams[self.constraints["wild_cards"] - 1][2]))/2
teams[index][4] = games_behind
for this_team in teams:
if this_team[2] != 0 or this_team[1] != 0:
this_embed.add_field(name=this_team[0].name, value=f"{this_team[1]} - {this_team[2]} WR: {round(this_team[1]/(this_team[1]+this_team[2]), 3)} GB: {this_team[4]}", inline = False)
else:
this_embed.add_field(name=this_team[0].name, value=f"{this_team[1]} - {this_team[2]} WR: - GB: {this_team[4]}", inline = False)
this_embed.set_footer(text=f"Wildcard standings as of day {self.day-1}")
return this_embed
class tournament(object): class tournament(object):
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): 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.name = name
@ -330,6 +380,7 @@ def load_league_file(league_name):
this_league.day = state_dic["day"] this_league.day = state_dic["day"]
this_league.schedule = state_dic["schedule"] this_league.schedule = state_dic["schedule"]
this_league.constraints = state_dic["constraints"]
this_league.game_length = state_dic["game_length"] this_league.game_length = state_dic["game_length"]
this_league.series_length = state_dic["series_length"] this_league.series_length = state_dic["series_length"]
this_league.owner = state_dic["owner"] this_league.owner = state_dic["owner"]

View File

@ -562,7 +562,12 @@ class StartTournamentCommand(Command):
if team == None: if team == None:
await msg.channel.send(f"We couldn't find {name}. Try again?") await msg.channel.send(f"We couldn't find {name}. Try again?")
return return
team_dic[team] = {"wins": 0} add = True
for extant_team in team_dic.keys():
if extant_team.name == team.name:
add = False
if add:
team_dic[team] = {"wins": 0}
channel = msg.channel channel = msg.channel
await msg.delete() await msg.delete()
@ -754,26 +759,39 @@ class DebugLeagueDisplay(Command):
class StartLeagueCommand(Command): class StartLeagueCommand(Command):
name = "startleague" name = "startleague"
template = "m;startleague [league name]" template = "m;startleague [league name]\n[games per hour]"
description = """Optional flag: `--queue X` or `-q X` to play X number of series before stopping. description = """Optional flag for the first line: `--queue X` or `-q X` to play X number of series before stopping.
Plays a league with a given name, provided that league has been saved on the website.""" Plays a league with a given name, provided that league has been saved on the website. The games per hour sets how often the games will start. (e.g. GPH 2 will start games at X:00 and X:30)"""
async def execute(self, msg, command): async def execute(self, msg, command):
league_name = command.split("-")[0].strip() league_name = command.split("-")[0].split("\n")[0].strip()
autoplay = None autoplay = None
try:
try:
if "--queue " in command: if "--queue " in command:
autoplay = int(command.split("--queue ")[1]) autoplay = int(command.split("--queue ")[1].split("\n")[0])
elif "-q " in command: elif "-q " in command:
autoplay = int(command.split("-q ")[1]) autoplay = int(command.split("-q ")[1].split("\n")[0])
if autoplay is not None and autoplay <= 0: if autoplay is not None and autoplay <= 0:
raise ValueError raise ValueError
elif autoplay is None: elif autoplay is None:
autoplay = -1 autoplay = -1
except: command = command.split("\n")[1]
except ValueError:
await msg.channel.send("Sorry boss, the queue flag needs a natural number. Any whole number over 0 will do just fine.") await msg.channel.send("Sorry boss, the queue flag needs a natural number. Any whole number over 0 will do just fine.")
return return
except IndexError:
await msg.channel.send("We need a games per hour number in the second line.")
return
try:
gph = int(command.strip())
if gph < 1 or gph > 12:
raise ValueError
except ValueError:
await msg.channel.send("Chief, we need a games per hour number between 1 and 12. We think that's reasonable.")
return
if league_exists(league_name): if league_exists(league_name):
league = leagues.load_league_file(league_name) league = leagues.load_league_file(league_name)
@ -784,10 +802,50 @@ Plays a league with a given name, provided that league has been saved on the web
if active_league.name == league.name: if active_league.name == league.name:
await msg.channel.send("That league is already running, boss. Patience is a virtue, you know.") await msg.channel.send("That league is already running, boss. Patience is a virtue, you know.")
return return
await start_league_day(msg.channel, league, autoplay = autoplay) league.autoplay = autoplay
league.games_per_hour = gph
await start_league_day(msg.channel, league)
else: else:
await msg.channel.send("Couldn't find that league, boss. Did you save it on the website?") await msg.channel.send("Couldn't find that league, boss. Did you save it on the website?")
class LeagueDisplayCommand(Command):
name = "leaguestandings"
template = "m;leaguestandings [league name]"
description = "Displays the current standings for the given league."
async def execute(self, msg, command):
if league_exists(command.strip()):
league = leagues.load_league_file(command.strip())
await msg.channel.send(embed=league.standings_embed())
else:
await msg.channel.send("Can't find that league, boss.")
class LeagueWildcardCommand(Command):
name = "leaguewildcard"
template = "m;leaguewildcard [league name]"
description = "Displays the current wildcard race for the given league, if the league has wildcard slots."
async def execute(self, msg, command):
if league_exists(command.strip()):
league = leagues.load_league_file(command.strip())
if league.constraints["wild_cards"] > 0:
await msg.channel.send(embed=league.wildcard_embed())
else:
await msg.channel.send("That league doesn't have wildcards, boss.")
else:
await msg.channel.send("Can't find that league, boss.")
class LeaguePauseCommand(Command):
name = "pauseleague"
template = "m;pauseleague [league name]"
descripton = "Tells a currently running league to stop running automatically after the current series."
async def execute(self, msg, command):
league_name = command.strip()
for active_league in active_leagues:
if active_league.name == league_name:
active_league.autoplay = 0
await msg.channel.send(f"Loud and clear, chief. {league_name} will stop after this series is over.")
commands = [ commands = [
IntroduceCommand(), IntroduceCommand(),
CountActiveGamesCommand(), CountActiveGamesCommand(),
@ -809,6 +867,9 @@ commands = [
StartGameCommand(), StartGameCommand(),
StartTournamentCommand(), StartTournamentCommand(),
StartLeagueCommand(), StartLeagueCommand(),
LeaguePauseCommand(),
LeagueDisplayCommand(),
LeagueWildcardCommand(),
StartRandomGameCommand(), StartRandomGameCommand(),
CreditCommand(), CreditCommand(),
RomanCommand(), RomanCommand(),
@ -1152,7 +1213,7 @@ async def tourney_round_watcher(channel, tourney, games_list, filter_url, finals
try: try:
for i in range(0, len(games_list)): for i in range(0, len(games_list)):
game, key = games_list[i] game, key = games_list[i]
if game.over and main_controller.master_games_dic[key][1]["end_delay"] <= 8: if game.over and ((key in main_controller.master_games_dic.keys() and main_controller.master_games_dic[key][1]["end_delay"] <= 8) or not key in main_controller.master_games_dic.keys()):
if game.teams['home'].name not in wins_in_series.keys(): if game.teams['home'].name not in wins_in_series.keys():
wins_in_series[game.teams["home"].name] = 0 wins_in_series[game.teams["home"].name] = 0
if game.teams['away'].name not in wins_in_series.keys(): if game.teams['away'].name not in wins_in_series.keys():
@ -1406,7 +1467,7 @@ async def game_watcher():
this_array = gamesarray.copy() this_array = gamesarray.copy()
for i in range(0,len(this_array)): for i in range(0,len(this_array)):
game, channel, user, key = this_array[i] game, channel, user, key = this_array[i]
if game.over and main_controller.master_games_dic[key][1]["end_delay"] <= 8: if game.over and ((key in main_controller.master_games_dic.keys() and main_controller.master_games_dic[key][1]["end_delay"] <= 8) or not key in main_controller.master_games_dic.keys()):
final_embed = game_over_embed(game) final_embed = game_over_embed(game)
if isinstance(user, str): if isinstance(user, str):
await channel.send(f"A game started by {user} just ended.") await channel.send(f"A game started by {user} just ended.")
@ -1452,7 +1513,7 @@ def get_team_fuzzy_search(team_name):
team = teams[0] team = teams[0]
return team return team
async def start_league_day(channel, league, autoplay = 1): async def start_league_day(channel, league):
current_games = [] current_games = []
games_to_start = league.schedule[str(league.day_to_series_num(league.day))] games_to_start = league.schedule[str(league.day_to_series_num(league.day))]
@ -1490,12 +1551,12 @@ async def start_league_day(channel, league, autoplay = 1):
await channel.send(f"The day {league.day} series of the {league.name} is starting now, at {config()['simmadome_url']+ext}") await channel.send(f"The day {league.day} series of the {league.name} is starting now, at {config()['simmadome_url']+ext}")
last = False last = False
await league_day_watcher(channel, league, current_games, config()['simmadome_url']+ext, autoplay, last) await league_day_watcher(channel, league, current_games, config()['simmadome_url']+ext, last)
async def league_day_watcher(channel, league, games_list, filter_url, autoplay, last = False): async def league_day_watcher(channel, league, games_list, filter_url, last = False):
league.active = True league.active = True
autoplay -= 1 league.autoplay -= 1
if league not in active_leagues: if league not in active_leagues:
active_leagues.append(league) active_leagues.append(league)
series_results = {} series_results = {}
@ -1503,49 +1564,50 @@ async def league_day_watcher(channel, league, games_list, filter_url, autoplay,
while league.active: while league.active:
queued_games = [] queued_games = []
while len(games_list) > 0: while len(games_list) > 0:
#try: try:
for i in range(0, len(games_list)): for i in range(0, len(games_list)):
game, key = games_list[i] game, key = games_list[i]
if game.over and main_controller.master_games_dic[key][1]["end_delay"] <= 8: if game.over and ((key in main_controller.master_games_dic.keys() and main_controller.master_games_dic[key][1]["end_delay"] <= 8) or not key in main_controller.master_games_dic.keys()):
if game.teams['home'].name not in series_results.keys(): if game.teams['home'].name not in series_results.keys():
series_results[game.teams["home"].name] = {} series_results[game.teams["home"].name] = {}
series_results[game.teams["home"].name]["wins"] = 0 series_results[game.teams["home"].name]["wins"] = 0
series_results[game.teams["home"].name]["losses"] = 0 series_results[game.teams["home"].name]["losses"] = 0
series_results[game.teams["home"].name]["run_diff"] = 0 series_results[game.teams["home"].name]["run_diff"] = 0
if game.teams['away'].name not in series_results.keys(): if game.teams['away'].name not in series_results.keys():
series_results[game.teams["away"].name] = {} series_results[game.teams["away"].name] = {}
series_results[game.teams["away"].name]["wins"] = 0 series_results[game.teams["away"].name]["wins"] = 0
series_results[game.teams["away"].name]["losses"] = 0 series_results[game.teams["away"].name]["losses"] = 0
series_results[game.teams["away"].name]["run_diff"] = 0 series_results[game.teams["away"].name]["run_diff"] = 0
winner_name = game.teams['home'].name if game.teams['home'].score > game.teams['away'].score else game.teams['away'].name winner_name = game.teams['home'].name if game.teams['home'].score > game.teams['away'].score else game.teams['away'].name
loser_name = game.teams['away'].name if game.teams['home'].score > game.teams['away'].score else game.teams['home'].name loser_name = game.teams['away'].name if game.teams['home'].score > game.teams['away'].score else game.teams['home'].name
rd = int(math.fabs(game.teams['home'].score - game.teams['away'].score)) rd = int(math.fabs(game.teams['home'].score - game.teams['away'].score))
series_results[winner_name]["wins"] += 1 series_results[winner_name]["wins"] += 1
series_results[winner_name]["run_diff"] += rd series_results[winner_name]["run_diff"] += rd
winner_dic = {"wins" : 1, "run_diff" : rd} winner_dic = {"wins" : 1, "run_diff" : rd}
series_results[loser_name]["losses"] += 1 series_results[loser_name]["losses"] += 1
series_results[loser_name]["run_diff"] -= rd series_results[loser_name]["run_diff"] -= rd
loser_dic = {"losses" : 1, "run_diff" : -rd} loser_dic = {"losses" : 1, "run_diff" : -rd}
league.add_stats_from_game(game.get_team_specific_stats()) league.add_stats_from_game(game.get_team_specific_stats())
league.update_standings({winner_name : winner_dic, loser_name : loser_dic}) league.update_standings({winner_name : winner_dic, loser_name : loser_dic})
leagues.save_league(league) leagues.save_league(league)
final_embed = game_over_embed(game) final_embed = game_over_embed(game)
final_embed.add_field(name="Series score:", value=f"{series_results[game.teams['away'].name]['wins']} - {series_results[game.teams['home'].name]['wins']}") final_embed.add_field(name="Day:", value=league.day)
await channel.send(f"A {league.name} game just ended!") final_embed.add_field(name="Series score:", value=f"{series_results[game.teams['away'].name]['wins']} - {series_results[game.teams['home'].name]['wins']}")
await channel.send(embed=final_embed) await channel.send(f"A {league.name} game just ended!")
if series_results[winner_name]["wins"] + series_results[winner_name]["losses"] < league.series_length: await channel.send(embed=final_embed)
queued_games.append(game) if series_results[winner_name]["wins"] + series_results[winner_name]["losses"] < league.series_length:
games_list.pop(i) queued_games.append(game)
break games_list.pop(i)
#except: break
#print("something went wrong in league_day_watcher") except:
await asyncio.sleep(1) print("something went wrong in league_day_watcher")
await asyncio.sleep(2)
league.day += 1 league.day += 1
if len(queued_games) > 0: if len(queued_games) > 0:
@ -1555,8 +1617,16 @@ async def league_day_watcher(channel, league, games_list, filter_url, autoplay,
validminutes = [int((60 * div)/league.games_per_hour) for div in range(0,league.games_per_hour)] validminutes = [int((60 * div)/league.games_per_hour) for div in range(0,league.games_per_hour)]
for i in range(0, len(validminutes)): for i in range(0, len(validminutes)):
if now.minute > validminutes[i]: if now.minute > validminutes[i]:
if i <= len(validminutes)-2: if i <= len(validminutes)-3:
delta = datetime.timedelta(minutes= (validminutes[i+1] - now.minute)) if validminutes[i+1] == now.minute:
delta = datetime.timedelta(minutes= (validminutes[i+2] - now.minute))
else:
delta = datetime.timedelta(minutes= (validminutes[i+1] - now.minute))
elif i <= len(validminutes)-2:
if validminutes[i+1] == now.minute:
delta = datetime.timedelta(minutes= (60 - now.minute))
else:
delta = datetime.timedelta(minutes= (validminutes[i+1] - now.minute))
else: else:
delta = datetime.timedelta(minutes= (60 - now.minute)) delta = datetime.timedelta(minutes= (60 - now.minute))
@ -1576,7 +1646,7 @@ async def league_day_watcher(channel, league, games_list, filter_url, autoplay,
if last or autoplay == 0: #if this series was the last of the season OR number of series to autoplay has been reached if last or league.autoplay == 0: #if this series was the last of the season OR number of series to autoplay has been reached
await channel.send(embed=league.standings_embed()) await channel.send(embed=league.standings_embed())
await channel.send(f"The {league.name} is no longer autoplaying.") await channel.send(f"The {league.name} is no longer autoplaying.")
leagues.save_league(league) leagues.save_league(league)
@ -1588,8 +1658,16 @@ async def league_day_watcher(channel, league, games_list, filter_url, autoplay,
validminutes = [int((60 * div)/league.games_per_hour) for div in range(0,league.games_per_hour)] validminutes = [int((60 * div)/league.games_per_hour) for div in range(0,league.games_per_hour)]
for i in range(0, len(validminutes)): for i in range(0, len(validminutes)):
if now.minute > validminutes[i]: if now.minute > validminutes[i]:
if i < len(validminutes)-2: if i <= len(validminutes)-3:
delta = datetime.timedelta(minutes= (validminutes[i+1] - now.minute)) if validminutes[i+1] == now.minute:
delta = datetime.timedelta(minutes= (validminutes[i+2] - now.minute))
else:
delta = datetime.timedelta(minutes= (validminutes[i+1] - now.minute))
elif i <= len(validminutes)-2:
if validminutes[i+1] == now.minute:
delta = datetime.timedelta(minutes= (60 - now.minute))
else:
delta = datetime.timedelta(minutes= (validminutes[i+1] - now.minute))
else: else:
delta = datetime.timedelta(minutes= (60 - now.minute)) delta = datetime.timedelta(minutes= (60 - now.minute))
@ -1601,7 +1679,7 @@ async def league_day_watcher(channel, league, games_list, filter_url, autoplay,
await channel.send(f"""This {league.name} series is now complete! The next series will be starting in {int(wait_seconds/60)} minutes.""") await channel.send(f"""This {league.name} series is now complete! The next series will be starting in {int(wait_seconds/60)} minutes.""")
await asyncio.sleep(wait_seconds) await asyncio.sleep(wait_seconds)
await start_league_day(channel, league, autoplay) await start_league_day(channel, league)
async def continue_league_series(league, queue, games_list, series_results): async def continue_league_series(league, queue, games_list, series_results):
for oldgame in queue: for oldgame in queue: