From cbcb950d781613dadd424c322250d938ee90ada9 Mon Sep 17 00:00:00 2001 From: Sakimori Date: Wed, 13 Jan 2021 19:20:58 -0500 Subject: [PATCH] implemented league saving and loading --- games.py | 2 +- league_storage.py | 26 +++++++++ leagues.py | 44 ++++++++++++-- the_prestige.py | 146 +++++++++++++++++++++++++++------------------- 4 files changed, 151 insertions(+), 67 deletions(-) diff --git a/games.py b/games.py index 6b2c99c..d917bca 100644 --- a/games.py +++ b/games.py @@ -173,7 +173,7 @@ class team(object): if rotation_slot is None: self.pitcher = random.choice(temp_rotation) else: - self.pitcher = temp_rotation[rotation_slot % len(temp_rotation)] + self.pitcher = temp_rotation[(rotation_slot-1) % len(temp_rotation)] def is_ready(self): try: diff --git a/league_storage.py b/league_storage.py index 902b372..63a7fe7 100644 --- a/league_storage.py +++ b/league_storage.py @@ -78,6 +78,7 @@ def init_league_db(league): "game_length" : league.game_length, "series_length" : league.series_length, "games_per_hour" : league.games_per_hour, + "owner" : None, "historic" : False } if not os.path.exists(os.path.dirname(os.path.join(data_dir, league_dir, league.name, f"{league.name}.state"))): @@ -88,6 +89,20 @@ def init_league_db(league): conn.commit() conn.close() +def save_league(league): + if league_exists(league.name): + state_dic = { + "day" : league.day, + "schedule" : league.schedule, + "game_length" : league.game_length, + "series_length" : league.series_length, + "games_per_hour" : league.games_per_hour, + "owner" : league.owner, + "historic" : league.historic + } + with open(os.path.join(data_dir, league_dir, league.name, f"{league.name}.state"), "w") as state_file: + json.dump(state_dic, state_file, indent=4) + def add_stats(league_name, player_game_stats_list): conn = create_connection(league_name) if conn is not None: @@ -122,6 +137,17 @@ def update_standings(league_name, update_dic): conn.commit() conn.close() +def get_standings(league_name): + if league_exists(league_name): + conn = create_connection(league_name) + if conn is not None: + c = conn.cursor() + + c.execute("SELECT name, wins, losses, run_diff FROM teams",) + standings_array = c.fetchall() + conn.close() + return standings_array + def league_exists(league_name): diff --git a/leagues.py b/leagues.py index 44dcf27..b685d8a 100644 --- a/leagues.py +++ b/leagues.py @@ -10,6 +10,8 @@ league_dir = "leagues" class league_structure(object): def __init__(self, name): self.name = name + self.historic = False + self.owner = None def setup(self, league_dic, division_games = 1, inter_division_games = 1, inter_league_games = 1, games_per_hour = 2): self.league = league_dic #key: subleague, value: {division : team_name} @@ -33,7 +35,7 @@ class league_structure(object): def last_series_check(self): - return str(math.ceil((self.day)/self.series_length) + 1) in self.schedule.keys() + return str(math.ceil((self.day)/self.series_length) + 1) not in self.schedule.keys() def day_to_series_num(self, day): return math.ceil((self.day)/self.series_length) @@ -164,19 +166,43 @@ class league_structure(object): day = 1 while not scheduled: found = False - if day in self.schedule.keys(): - for game_on_day in self.schedule[day]: + if str(day) in self.schedule.keys(): + for game_on_day in self.schedule[str(day)]: for team in game: if team in game_on_day: found = True if not found: - self.schedule[day].append(game) + self.schedule[str(day)].append(game) scheduled = True else: - self.schedule[day] = [game] + self.schedule[str(day)] = [game] scheduled = True day += 1 + def standings_embed(self): + this_embed = Embed(color=Color.purple(), title=self.name) + 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) + for division in iter(self.league[subleague].keys()): + this_embed.add_field(name="Division:", value=f"**{division}**", inline = False) + teams = self.league[subleague][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"],) + + def sorter(team_in_list): + return (team_in_list[1], team_in_list[3]) + teams.sort(key=sorter, reverse=True) + + 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) + + this_embed.set_footer(text=f"Standings as of day {self.day-1}") + return this_embed + 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): self.name = name @@ -289,6 +315,8 @@ def save_league(this_league): league_json_string = jsonpickle.encode(this_league.league, keys=True) json.dump(league_json_string, league_file, indent=4) return True + else: + league_db.save_league(this_league) def load_league_file(league_name): if league_db.league_exists(league_name): @@ -298,4 +326,10 @@ def load_league_file(league_name): this_league.league = jsonpickle.decode(json.load(league_file), keys=True, classes=team) with open(os.path.join(data_dir, league_dir, league_name, f"{this_league.name}.state")) as state_file: state_dic = json.load(state_file) + + this_league.day = state_dic["day"] + this_league.schedule = state_dic["schedule"] + this_league.game_length = state_dic["game_length"] + this_league.series_length = state_dic["series_length"] + this_league.owner = state_dic["owner"] return this_league \ No newline at end of file diff --git a/the_prestige.py b/the_prestige.py index a86eabf..a805b93 100644 --- a/the_prestige.py +++ b/the_prestige.py @@ -1,6 +1,7 @@ import discord, json, math, os, roman, games, asyncio, random, main_controller, threading, time, urllib, leagues, datetime import database as db import onomancer as ono +from league_storage import league_exists from the_draft import Draft, DRAFT_ROUNDS from flask import Flask from uuid import uuid4 @@ -137,9 +138,9 @@ class StartGameCommand(Command): league = command.split("\n")[0].split("--league ")[1].split("-")[0].strip() try: if "-d " in command.split("\n")[0]: - day = int(command.split("\n")[0].split("-d ")[1].split("-")[0].strip())-1 + day = int(command.split("\n")[0].split("-d ")[1].split("-")[0].strip()) elif "--day " in command.split("\n")[0]: - day = int(command.split("\n")[0].split("--day ")[1].split("-")[0].strip())-1 + day = int(command.split("\n")[0].split("--day ")[1].split("-")[0].strip()) except ValueError: await msg.channel.send("Make sure you put an integer after the -d flag.") return @@ -724,26 +725,36 @@ class StartDraftCommand(Command): raise SlowDraftError('Too slow') return draft_message -class DebugLeague(Command): - name = "league" +class DebugLeagueStart(Command): + name = "startleague" async def execute(self, msg, command): - league = leagues.league_structure("test2") - league.setup({ - "nL" : { - "nL west" : [get_team_fuzzy_search("lockpicks"), get_team_fuzzy_search("liches")], - "nL east" : [get_team_fuzzy_search("bethesda soft"), get_team_fuzzy_search("traverse city")] - }, - "aL" : { - "aL west" : [get_team_fuzzy_search("deep space"), get_team_fuzzy_search("phoenix")], - "aL east" : [get_team_fuzzy_search("cheyenne mountain"), get_team_fuzzy_search("tarot dragons")] - } - }, division_games=6, inter_division_games=3, inter_league_games=3, games_per_hour = 12) - league.generate_schedule() - leagues.save_league(league) - await start_league_day(msg.channel, league, autoplay = 1) + if not league_exists("test2"): + league = leagues.league_structure("test2") + league.setup({ + "nL" : { + "nL west" : [get_team_fuzzy_search("lockpicks"), get_team_fuzzy_search("liches")], + "nL east" : [get_team_fuzzy_search("bethesda soft"), get_team_fuzzy_search("traverse city")] + }, + "aL" : { + "aL west" : [get_team_fuzzy_search("deep space"), get_team_fuzzy_search("phoenix")], + "aL east" : [get_team_fuzzy_search("cheyenne mountain"), get_team_fuzzy_search("tarot dragons")] + } + }, division_games=6, inter_division_games=3, inter_league_games=3, games_per_hour = 12) + league.generate_schedule() + leagues.save_league(league) + else: + league = leagues.load_league_file("test2") + await start_league_day(msg.channel, league, autoplay = 2) +class DebugLeagueDisplay(Command): + name = "displayleague" + async def execute(self, msg, command): + if league_exists("test2"): + league = leagues.load_league_file("test2") + await msg.channel.send(embed=league.standings_embed()) + commands = [ @@ -772,7 +783,8 @@ commands = [ HelpCommand(), StartDraftCommand(), DraftPlayerCommand(), - DebugLeague() + DebugLeagueStart(), + DebugLeagueDisplay() ] client = discord.Client() @@ -1408,7 +1420,7 @@ def get_team_fuzzy_search(team_name): async def start_league_day(channel, league, autoplay = 1): current_games = [] - games_to_start = league.schedule[league.day_to_series_num(league.day)] + games_to_start = league.schedule[str(league.day_to_series_num(league.day))] if league.game_length is None: game_length = games.config()["default_length"] else: @@ -1417,10 +1429,11 @@ async def start_league_day(channel, league, autoplay = 1): for pair in games_to_start: if pair[0] is not None and pair[1] is not None: away = get_team_fuzzy_search(pair[0]) - away.set_pitcher(rotation_slot=league.day-1) + away.set_pitcher(rotation_slot=league.day) home = get_team_fuzzy_search(pair[1]) + home.set_pitcher(rotation_slot=league.day) - this_game = games.game(away.prepare_for_save().finalize(), home.prepare_for_save().finalize(), length = game_length) + this_game = games.game(away.finalize(), home.finalize(), length = game_length) this_game, state_init = prepare_game(this_game) state_init["is_league"] = True @@ -1439,7 +1452,7 @@ async def start_league_day(channel, league, autoplay = 1): last = True else: - await channel.send(f"The next 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 await league_day_watcher(channel, league, current_games, config()['simmadome_url']+ext, autoplay, last) @@ -1454,41 +1467,47 @@ async def league_day_watcher(channel, league, games_list, filter_url, autoplay, while league.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"] <= 8: - if game.teams['home'].name not in series_results.keys(): - series_results[game.teams["home"].name] = {} - series_results[game.teams["home"].name]["wins"] = 0 - series_results[game.teams["home"].name]["losses"] = 0 - series_results[game.teams["home"].name]["run_diff"] = 0 - if game.teams['away'].name not in series_results.keys(): - series_results[game.teams["away"].name] = {} - series_results[game.teams["away"].name]["wins"] = 0 - series_results[game.teams["away"].name]["losses"] = 0 - series_results[game.teams["away"].name]["run_diff"] = 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"] <= 8: + if game.teams['home'].name not in series_results.keys(): + series_results[game.teams["home"].name] = {} + series_results[game.teams["home"].name]["wins"] = 0 + series_results[game.teams["home"].name]["losses"] = 0 + series_results[game.teams["home"].name]["run_diff"] = 0 + if game.teams['away'].name not in series_results.keys(): + series_results[game.teams["away"].name] = {} + series_results[game.teams["away"].name]["wins"] = 0 + series_results[game.teams["away"].name]["losses"] = 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 - 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)) + 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 + rd = int(math.fabs(game.teams['home'].score - game.teams['away'].score)) - series_results[winner_name]["wins"] += 1 - series_results[winner_name]["run_diff"] += rd - series_results[loser_name]["losses"] += 1 - series_results[loser_name]["run_diff"] -= rd + series_results[winner_name]["wins"] += 1 + series_results[winner_name]["run_diff"] += rd - league.add_stats_from_game(game.get_team_specific_stats()) + winner_dic = {"wins" : 1, "run_diff" : rd} - final_embed = game_over_embed(game) - await channel.send(f"A {league.name} game just ended!") - await channel.send(embed=final_embed) - if series_results[winner_name]["wins"] + series_results[winner_name]["losses"] < league.series_length: - queued_games.append(game) - games_list.pop(i) - break - except: - print("something went wrong in league_day_watcher") + series_results[loser_name]["losses"] += 1 + series_results[loser_name]["run_diff"] -= rd + + loser_dic = {"losses" : 1, "run_diff" : -rd} + + league.add_stats_from_game(game.get_team_specific_stats()) + league.update_standings({winner_name : winner_dic, loser_name : loser_dic}) + leagues.save_league(league) + final_embed = game_over_embed(game) + await channel.send(f"A {league.name} game just ended!") + await channel.send(embed=final_embed) + if series_results[winner_name]["wins"] + series_results[winner_name]["losses"] < league.series_length: + queued_games.append(game) + games_list.pop(i) + break + #except: + #print("something went wrong in league_day_watcher") await asyncio.sleep(1) league.day += 1 @@ -1499,16 +1518,18 @@ 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)] for i in range(0, len(validminutes)): if now.minute > validminutes[i]: - if i < len(validminutes)-1: + if i <= len(validminutes)-1: delta = datetime.timedelta(minutes= (validminutes[i+1] - now.minute)) else: delta = datetime.timedelta(minutes= (60 - now.minute)) - next_start = (now + delta).replace(microsecond=0) + next_start = (now + delta).replace(second=0, microsecond=0) wait_seconds = (next_start - now).seconds - - await channel.send(f"The next batch of games for the {league.name} will start in {int(wait_seconds/60)} minutes.") + leagues.save_league(league) + await channel.send(embed=league.standings_embed()) + await channel.send(f"The day {league.day} games for the {league.name} will start in {math.ceil(wait_seconds/60)} minutes.") + leagues.save_league(league) await asyncio.sleep(wait_seconds) await channel.send(f"A {league.name} series is continuing now at {filter_url}") games_list = await continue_league_series(league, queued_games, games_list, series_results) @@ -1516,10 +1537,11 @@ async def league_day_watcher(channel, league, games_list, filter_url, autoplay, league.active = False - league.update_standings(series_results) - if last or autoplay <= 0: #if this series was the last of the season OR number of series to autoplay has been reached - #needs some kind of notification that it's over here + + if last or 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(f"The {league.name} is no longer autoplaying.") active_leagues.pop(active_leagues.index(league)) return @@ -1536,6 +1558,8 @@ async def league_day_watcher(channel, league, games_list, filter_url, autoplay, next_start = (now + delta).replace(microsecond=0) wait_seconds = (next_start - now).seconds + leagues.save_league(league) + await channel.send(embed=league.standings_embed()) 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)