diff --git a/database.py b/database.py index 5a63ff8..311c3ed 100644 --- a/database.py +++ b/database.py @@ -333,7 +333,7 @@ def search_teams(search_string): conn = create_connection() if conn is not None: c = conn.cursor() - c.execute("SELECT team_json_string FROM teams WHERE name LIKE ?",(re.sub('[^A-Za-z0-9 %]+', '', f"%{search_string}%"),)) + c.execute("SELECT team_json_string, counter FROM teams WHERE name LIKE ?",(re.sub('[^A-Za-z0-9 %]+', '', f"%{search_string}%"),)) team_json_strings = c.fetchall() conn.close() return team_json_strings diff --git a/games.py b/games.py index 8371337..455e2bd 100644 --- a/games.py +++ b/games.py @@ -1,5 +1,6 @@ import json, random, os, math, jsonpickle, weather import database as db +from league_storage import get_mods, get_team_mods from gametext import base_string, appearance_outcomes, game_strings_base data_dir = "data" @@ -79,6 +80,10 @@ class player(object): stars = half_star + 0.5 self.stlats[key] = stars + def apply_mods(self, mod_dic): + for stat in iter(mod_dic.keys()): + self.stlats[stat] = self.stlats[stat] + mod_dic[stat] + class team(object): def __init__(self): @@ -190,6 +195,14 @@ class team(object): self.pitcher = None return (len(self.lineup) >= 1 and len(self.rotation) > 0) + def apply_team_mods(self, league_name): + mod_dic = get_team_mods(league_name, self.name) + if mod_dic != {} and mod_dic != None: + for player_name in iter(mod_dic.keys()): + this_player = self.find_player(player_name)[0] + if this_player is not None: + this_player.apply_mods(mod_dic[player_name]) + def prepare_for_save(self): self.lineup_position = 0 self.score = 0 diff --git a/league_storage.py b/league_storage.py index af8ef4a..37f840e 100644 --- a/league_storage.py +++ b/league_storage.py @@ -17,6 +17,14 @@ def create_connection(league_name): # enable write-ahead log for performance and resilience conn.execute('pragma journal_mode=wal') + modifications_table_check_string = """ CREATE TABLE IF NOT EXISTS mods ( + counter integer PRIMARY KEY, + name text NOT NULL, + team_name text NOT NULL, + modifications_json text + );""" + conn.execute(modifications_table_check_string) + return conn except: print("oops, db connection no work") @@ -124,10 +132,18 @@ def init_league_db(league): run_diff integer DEFAULT 0 ); """ + modifications_table_check_string = """ CREATE TABLE IF NOT EXISTS mods ( + counter integer PRIMARY KEY, + name text NOT NULL, + team_name text NOT NULL, + modifications_json text + );""" + if conn is not None: c = conn.cursor() c.execute(player_stats_table_check_string) c.execute(teams_table_check_string) + c.execute(modifications_table_check_string) for team in league.teams_in_league(): c.execute("INSERT INTO teams (name) VALUES (?)", (team.name,)) @@ -195,6 +211,63 @@ def get_stats(league_name, stat, is_batter=True, day = 10): conn.close() return stats +def get_mods(league_name, player:str, team:str): + """returns a player's modifications dict""" + conn = create_connection(league_name) + if conn is not None: + c = conn.cursor() + c.execute("SELECT * FROM stats WHERE name=? AND team_name=?", (player, team)) #check stats table to make sure player actually exists in the league + row = c.fetchone() + if row is None: + return False + c.execute("SELECT modifications_json FROM mods WHERE name=? AND team_name=?", (player, team)) + mod_string = c.fetchone() + if mod_string is None: + return None + mods = json.loads(mod_string[0]) + conn.close() + return mods + return False + +def get_team_mods(league_name, team:str): + """returns a dictionary of player modifications belonging to a team""" + conn = create_connection(league_name) + if conn is not None: + c = conn.cursor() + c.execute("SELECT * FROM stats WHERE team_name=?", (team,)) #check stats table to make sure team actually exists in the league + row = c.fetchone() + if row is None: + return False + c.execute("SELECT name, modifications_json FROM mods WHERE team_name=?",(team,)) + rows = c.fetchall() + if len(rows) == 0: + return None + mods_dic = {} + for row in rows: + mods_dic[row[0]] = json.loads(row[1]) + return mods_dic + +def set_mods(league_name, player:str, team:str, modifications:dict): + """Overwrites a player's modifications with an entirely new set""" + conn = create_connection(league_name) + if conn is not None: + c = conn.cursor() + c.execute("SELECT * FROM stats WHERE name=? AND team_name=?", (player, team)) #check stats table to make sure player actually exists in the league + row = c.fetchone() + if row is None: + return False + mod_string = json.dumps(modifications) + c.execute("SELECT counter FROM mods WHERE name=? AND team_name=?", (player, team)) #check stats table to make sure player actually exists in the league + counter = c.fetchone() + if counter is None: + c.execute("INSERT INTO mods(name, team_name, modifications_json) VALUES (?,?,?)", (player, team, mod_string)) + else: + c.execute("UPDATE mods SET modifications_json = ? WHERE counter=?", (mod_string, counter)) + conn.commit() + conn.close + return True + return False + def update_standings(league_name, update_dic): if league_exists(league_name): conn = create_connection(league_name) diff --git a/the_prestige.py b/the_prestige.py index 9c21645..cd2cf4d 100644 --- a/the_prestige.py +++ b/the_prestige.py @@ -1,7 +1,7 @@ import discord, json, math, os, roman, games, asyncio, random, main_controller, threading, time, urllib, leagues, datetime, gametext, real_players import database as db import onomancer as ono -from league_storage import league_exists, season_save, season_restart +from league_storage import league_exists, season_save, season_restart, get_mods, get_team_mods, set_mods from the_draft import Draft from flask import Flask from uuid import uuid4 @@ -643,6 +643,7 @@ class DraftFlagsCommand(Command): --wait or -w: Sets the timeout, in seconds, to wait for draftees to pick a player. --chaos or -c: The percentage of onomancer names in the pool. Higher numbers mean less real names, but faster pool generation. Accepts any number between 0 and 1. """ + await msg.channel.send(text) class StartDraftCommand(Command): name = "startdraft" @@ -896,6 +897,36 @@ Not every team will play every series, due to how the scheduling algorithm is co else: raise CommandError("Couldn't find that league, boss. Did you save it on the website?") +class LeagueSetPlayerModifiersCommand(Command): + name = "setplayermods" + template = "m;setplayermods [league name]\n[team name]\n[player name]\n4 numbers, seperated by a space, for batting pitching baserunning defense" + description = "Set a pack of modifiers to a specific player in your league. Commissioners only." + + async def execute(self, msg, command, flags): + if league_exists(command.split("\n")[0].strip()): + try: + league = leagues.load_league_file(command.split("\n")[0].strip()) + except IndexError: + raise CommandError("League name goes on the second line now, boss.") + else: + raise CommandError("Can't find that league, boss.") + + try: + team_name = command.split("\n")[1].strip() + player_name = command.split("\n")[2].strip() + mods_text_list = command.split("\n")[3].strip().split(" ") + keys = ["batting_stars", "pitching_stars", "baserunning_stars", "defense_stars"] + mod_dic = {} + for i in range(0,4): + mod_dic[keys[i]] = float(mods_text_list[i]) + set_mods(league.name, player_name, team_name, mod_dic) + await msg.channel.send("You got it, boss. Divine intervention, served by yours truly.") + except IndexError: + raise CommandError("You didn't give us enough info, chief. Check the help text.") + #except ValueError: + #raise CommandError("Those modifiers didn't make a lick of sense. Try again with sensible numbers this time.") + + class LeagueSubscribeCommand(Command): name = "leaguesub" template = "m;leaguesub [league name]" @@ -1542,6 +1573,7 @@ commands = [ OBLResetCommand(), LeagueClaimCommand(), LeagueAddOwnersCommand(), + LeagueSetPlayerModifiersCommand(), StartLeagueCommand(), LeagueSubscribeCommand(), LeaguePauseCommand(), @@ -1841,6 +1873,9 @@ def prepare_game(newgame, league = None, weather_name = None): state_init["is_league"] = False else: state_init["is_league"] = True + newgame.teams['away'].apply_team_mods(league.name) + newgame.teams['home'].apply_team_mods(league.name) + return newgame, state_init @@ -2345,9 +2380,8 @@ async def start_league_day(channel, league, partial = False): this_game = games.game(away.finalize(), home.finalize(), length = game_length) this_game.weather = league.get_weather_now(home.name)(this_game) - this_game, state_init = prepare_game(this_game) + this_game, state_init = prepare_game(this_game, league=league) - state_init["is_league"] = True if not partial: series_string = "Series score:" state_init["title"] = f"{series_string} 0 - 0" @@ -2562,9 +2596,8 @@ async def continue_league_series(league, queue, games_list, series_results, miss home_team.set_pitcher(rotation_slot=league.day) this_game = games.game(away_team.finalize(), home_team.finalize(), length = league.game_length) this_game.weather = league.get_weather_now(home_team.name)(this_game) - this_game, state_init = prepare_game(this_game) + this_game, state_init = prepare_game(this_game, league=league) - state_init["is_league"] = True series_string = f"Series score:" if missed <= 0: