commit
ed90af78d7
|
@ -132,6 +132,7 @@ these folks are helping me a *ton* via patreon, and i cannot possibly thank them
|
||||||
- Ryan Littleton
|
- Ryan Littleton
|
||||||
- Evie Diver
|
- Evie Diver
|
||||||
- iliana etaoin
|
- iliana etaoin
|
||||||
|
- yooori
|
||||||
|
|
||||||
## Attribution
|
## Attribution
|
||||||
|
|
||||||
|
|
53
games.py
53
games.py
|
@ -32,10 +32,12 @@ def all_weathers():
|
||||||
weathers_dic = {
|
weathers_dic = {
|
||||||
#"Supernova" : weather("Supernova", "🌟"),
|
#"Supernova" : weather("Supernova", "🌟"),
|
||||||
#"Midnight": weather("Midnight", "🕶"),
|
#"Midnight": weather("Midnight", "🕶"),
|
||||||
"Slight Tailwind": weather("Slight Tailwind", "🏌️♀️"),
|
#"Slight Tailwind": weather("Slight Tailwind", "🏌️♀️"),
|
||||||
"Heavy Snow": weather("Heavy Snow", "❄"),
|
"Heavy Snow": weather("Heavy Snow", "❄"),
|
||||||
"Twilight" : weather("Twilight", "👻"),
|
"Twilight" : weather("Twilight", "👻"),
|
||||||
"Thinned Veil" : weather("Thinned Veil", "🌌")
|
"Thinned Veil" : weather("Thinned Veil", "🌌"),
|
||||||
|
"Heat Wave" : weather("Heat Wave", "🌄"),
|
||||||
|
"Drizzle" : weather("Drizzle", "🌧")
|
||||||
}
|
}
|
||||||
return weathers_dic
|
return weathers_dic
|
||||||
|
|
||||||
|
@ -114,6 +116,11 @@ class team(object):
|
||||||
else:
|
else:
|
||||||
return (None, None, None)
|
return (None, None, None)
|
||||||
|
|
||||||
|
def find_player_spec(self, name, roster):
|
||||||
|
for s_index in range(0,len(roster)):
|
||||||
|
if roster[s_index].name == name:
|
||||||
|
return (roster[s_index], s_index)
|
||||||
|
|
||||||
def average_stars(self):
|
def average_stars(self):
|
||||||
total_stars = 0
|
total_stars = 0
|
||||||
for _player in self.lineup:
|
for _player in self.lineup:
|
||||||
|
@ -151,6 +158,21 @@ class team(object):
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def slide_player_spec(self, this_player_name, new_spot, roster):
|
||||||
|
index = None
|
||||||
|
for s_index in range(0,len(roster)):
|
||||||
|
if roster[s_index].name == this_player_name:
|
||||||
|
index = s_index
|
||||||
|
this_player = roster[s_index]
|
||||||
|
if index is None:
|
||||||
|
return False
|
||||||
|
elif new_spot <= len(roster):
|
||||||
|
roster.pop(index)
|
||||||
|
roster.insert(new_spot-1, this_player)
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
def add_lineup(self, new_player):
|
def add_lineup(self, new_player):
|
||||||
if len(self.lineup) < 20:
|
if len(self.lineup) < 20:
|
||||||
|
@ -169,7 +191,7 @@ class team(object):
|
||||||
def set_pitcher(self, rotation_slot = None, use_lineup = False):
|
def set_pitcher(self, rotation_slot = None, use_lineup = False):
|
||||||
temp_rotation = self.rotation.copy()
|
temp_rotation = self.rotation.copy()
|
||||||
if use_lineup:
|
if use_lineup:
|
||||||
for batter in self.rotation:
|
for batter in self.lineup:
|
||||||
temp_rotation.append(batter)
|
temp_rotation.append(batter)
|
||||||
if rotation_slot is None:
|
if rotation_slot is None:
|
||||||
self.pitcher = random.choice(temp_rotation)
|
self.pitcher = random.choice(temp_rotation)
|
||||||
|
@ -616,6 +638,25 @@ class game(object):
|
||||||
offense_team.lineup_position += 1 #put next batter up
|
offense_team.lineup_position += 1 #put next batter up
|
||||||
if self.outs >= 3:
|
if self.outs >= 3:
|
||||||
self.flip_inning()
|
self.flip_inning()
|
||||||
|
if self.weather.name == "Heat Wave":
|
||||||
|
if self.top_of_inning:
|
||||||
|
self.weather.home_pitcher = self.get_pitcher()
|
||||||
|
if self.inning >= self.weather.counter_home:
|
||||||
|
self.weather.counter_home = self.weather.counter_home - (self.weather.counter_home % 5) + 5 + random.randint(1,4) #rounds down to last 5, adds up to next 5. then adds a random number 2<=x<=5 to determine next pitcher
|
||||||
|
tries = 0
|
||||||
|
while self.get_pitcher() == self.weather.home_pitcher and tries < 3:
|
||||||
|
self.teams["home"].set_pitcher(use_lineup = True)
|
||||||
|
tries += 1
|
||||||
|
|
||||||
|
|
||||||
|
else:
|
||||||
|
self.weather.away_pitcher = self.get_pitcher()
|
||||||
|
if self.inning >= self.weather.counter_away:
|
||||||
|
self.weather.counter_away = self.weather.counter_away - (self.weather.counter_away % 5) + 5 + random.randint(1,4)
|
||||||
|
tries = 0
|
||||||
|
while self.get_pitcher() == self.weather.away_pitcher and tries < 3:
|
||||||
|
self.teams["away"].set_pitcher(use_lineup = True)
|
||||||
|
tries += 1
|
||||||
|
|
||||||
|
|
||||||
return (result, scores_to_add) #returns ab information and scores
|
return (result, scores_to_add) #returns ab information and scores
|
||||||
|
@ -635,6 +676,12 @@ class game(object):
|
||||||
self.over = True
|
self.over = True
|
||||||
self.top_of_inning = not self.top_of_inning
|
self.top_of_inning = not self.top_of_inning
|
||||||
|
|
||||||
|
if self.weather.name == "Drizzle":
|
||||||
|
if self.top_of_inning:
|
||||||
|
self.bases[2] = self.teams["away"].lineup[(self.teams["away"].lineup_position-1) % len(self.teams["away"].lineup)]
|
||||||
|
else:
|
||||||
|
self.bases[2] = self.teams["home"].lineup[(self.teams["home"].lineup_position-1) % len(self.teams["home"].lineup)]
|
||||||
|
|
||||||
def pitcher_insert(self, this_team):
|
def pitcher_insert(self, this_team):
|
||||||
rounds = math.ceil(this_team.lineup_position / len(this_team.lineup))
|
rounds = math.ceil(this_team.lineup_position / len(this_team.lineup))
|
||||||
position = random.randint(0, len(this_team.lineup)-1)
|
position = random.randint(0, len(this_team.lineup)-1)
|
||||||
|
|
|
@ -3,6 +3,7 @@ import sqlite3 as sql
|
||||||
|
|
||||||
data_dir = "data"
|
data_dir = "data"
|
||||||
league_dir = "leagues"
|
league_dir = "leagues"
|
||||||
|
statements_file = os.path.join(data_dir, "sql_statements.xvi")
|
||||||
|
|
||||||
def create_connection(league_name):
|
def create_connection(league_name):
|
||||||
#create connection, create db if doesn't exist
|
#create connection, create db if doesn't exist
|
||||||
|
@ -21,6 +22,45 @@ def create_connection(league_name):
|
||||||
print("oops, db connection no work")
|
print("oops, db connection no work")
|
||||||
return conn
|
return conn
|
||||||
|
|
||||||
|
def statements():
|
||||||
|
if not os.path.exists(os.path.dirname(statements_file)):
|
||||||
|
os.makedirs(os.path.dirname(statements_file))
|
||||||
|
if not os.path.exists(statements_file):
|
||||||
|
#generate default statements: bat_base and pitch_base to be appended with a relevant ORDER BY statement
|
||||||
|
config_dic = {
|
||||||
|
"bat_base" : """SELECT name, team_name,
|
||||||
|
plate_appearances - (walks_taken + sacrifices) as ABs,
|
||||||
|
ROUND(hits*1.0 / (plate_appearances - (walks_taken + sacrifices)*1.0),3) as BA,
|
||||||
|
ROUND(total_bases*1.0 / (plate_appearances - (walks_taken + sacrifices)*1.0),3) as SLG,
|
||||||
|
ROUND((walks_taken + hits)*1.0/plate_appearances*1.0,3) as OBP,
|
||||||
|
ROUND((walks_taken + hits)*1.0/plate_appearances*1.0,3) + ROUND(total_bases*1.0 / (plate_appearances - (walks_taken + sacrifices)*1.0),3) as OPS
|
||||||
|
FROM stats WHERE plate_appearances > 8""",
|
||||||
|
"avg" : ["ORDER BY BA DESC;", "bat_base"],
|
||||||
|
"slg" : ["ORDER BY SLG DESC;", "bat_base"],
|
||||||
|
"obp" : ["ORDER BY OBP DESC;", "bat_base"],
|
||||||
|
"ops" : ["ORDER BY OPS DESC;", "bat_base"],
|
||||||
|
"pitch_base" : """SELECT name, team_name,
|
||||||
|
ROUND(((outs_pitched*1.0)/3.0),1) as IP,
|
||||||
|
ROUND(runs_allowed*27.0/(outs_pitched*1.0),3) as ERA,
|
||||||
|
ROUND((walks_allowed+hits_allowed)*3.0/(outs_pitched*1.0),3) as WHIP,
|
||||||
|
ROUND(walks_allowed*27.0/(outs_pitched*1.0),3) as BBper9,
|
||||||
|
ROUND(strikeouts_given*27.0/(outs_pitched*1.0),3) as Kper9,
|
||||||
|
ROUND(strikeouts_given*1.0/walks_allowed*1.0,3) as KperBB
|
||||||
|
FROM stats WHERE outs_pitched > 20
|
||||||
|
""",
|
||||||
|
"era" : ["ORDER BY ERA ASC;", "pitch_base"],
|
||||||
|
"whip" : ["ORDER BY WHIP ASC;", "pitch_base"],
|
||||||
|
"kper9" : ["ORDER BY Kper9 DESC;", "pitch_base"],
|
||||||
|
"bbper9" : ["ORDER BY BBper9 ASC;", "pitch_base"],
|
||||||
|
"kperbb" : ["ORDER BY KperBB DESC;", "pitch_base"]
|
||||||
|
}
|
||||||
|
with open(statements_file, "w") as config_file:
|
||||||
|
json.dump(config_dic, config_file, indent=4)
|
||||||
|
return config_dic
|
||||||
|
else:
|
||||||
|
with open(statements_file) as config_file:
|
||||||
|
return json.load(config_file)
|
||||||
|
|
||||||
def create_season_connection(league_name, season_num):
|
def create_season_connection(league_name, season_num):
|
||||||
#create connection, create db if doesn't exist
|
#create connection, create db if doesn't exist
|
||||||
conn = None
|
conn = None
|
||||||
|
@ -129,6 +169,19 @@ def add_stats(league_name, player_game_stats_list):
|
||||||
conn.commit()
|
conn.commit()
|
||||||
conn.close()
|
conn.close()
|
||||||
|
|
||||||
|
def get_stats(league_name, stat, is_batter=True):
|
||||||
|
conn = create_connection(league_name)
|
||||||
|
stats = None
|
||||||
|
if conn is not None:
|
||||||
|
conn.row_factory = sql.Row
|
||||||
|
c=conn.cursor()
|
||||||
|
|
||||||
|
if stat in statements().keys():
|
||||||
|
c.execute(statements()[statements()[stat][1]]+"\n"+statements()[stat][0])
|
||||||
|
stats = c.fetchall()
|
||||||
|
conn.close()
|
||||||
|
return stats
|
||||||
|
|
||||||
def update_standings(league_name, update_dic):
|
def update_standings(league_name, update_dic):
|
||||||
if league_exists(league_name):
|
if league_exists(league_name):
|
||||||
conn = create_connection(league_name)
|
conn = create_connection(league_name)
|
||||||
|
@ -168,6 +221,13 @@ def season_save(league):
|
||||||
if "." in item.name:
|
if "." in item.name:
|
||||||
os.rename(os.path.join(data_dir, league_dir, league.name, item.name), os.path.join(new_dir, item.name))
|
os.rename(os.path.join(data_dir, league_dir, league.name, item.name), os.path.join(new_dir, item.name))
|
||||||
|
|
||||||
|
def season_restart(league):
|
||||||
|
if league_exists(league.name):
|
||||||
|
with os.scandir(os.path.join(data_dir, league_dir, league.name)) as folder:
|
||||||
|
for item in folder:
|
||||||
|
if "." in item.name:
|
||||||
|
os.remove(os.path.join(data_dir, league_dir, league.name, item.name))
|
||||||
|
|
||||||
def get_past_standings(league_name, season_num):
|
def get_past_standings(league_name, season_num):
|
||||||
if league_exists(league_name):
|
if league_exists(league_name):
|
||||||
with os.scandir(os.path.join(data_dir, league_dir, league_name)) as folder:
|
with os.scandir(os.path.join(data_dir, league_dir, league_name)) as folder:
|
||||||
|
|
50
leagues.py
50
leagues.py
|
@ -102,6 +102,14 @@ class league_structure(object):
|
||||||
teams += teams_list
|
teams += teams_list
|
||||||
return teams
|
return teams
|
||||||
|
|
||||||
|
def team_names_in_league(self):
|
||||||
|
teams = []
|
||||||
|
for division in self.league.values():
|
||||||
|
for teams_list in division.values():
|
||||||
|
for team in teams_list:
|
||||||
|
teams.append(team.name)
|
||||||
|
return teams
|
||||||
|
|
||||||
def teams_in_subleague(self, subleague_name):
|
def teams_in_subleague(self, subleague_name):
|
||||||
teams = []
|
teams = []
|
||||||
if subleague_name in self.league.keys():
|
if subleague_name in self.league.keys():
|
||||||
|
@ -201,7 +209,7 @@ class league_structure(object):
|
||||||
if extra_teams != []:
|
if extra_teams != []:
|
||||||
if len(extra_teams) % 2 == 0:
|
if len(extra_teams) % 2 == 0:
|
||||||
for index in range(0, int(len(extra_teams)/2)):
|
for index in range(0, int(len(extra_teams)/2)):
|
||||||
matchups.append([extra_teams[index], extra_teams[index+1]])
|
matchups.append([extra_teams[index].name, extra_teams[index+1].name])
|
||||||
|
|
||||||
|
|
||||||
for subleague in league.keys():
|
for subleague in league.keys():
|
||||||
|
@ -323,6 +331,30 @@ class league_structure(object):
|
||||||
this_embed.set_footer(text=f"Standings as of day {self.day-1} / {self.season_length()}")
|
this_embed.set_footer(text=f"Standings as of day {self.day-1} / {self.season_length()}")
|
||||||
return this_embed
|
return this_embed
|
||||||
|
|
||||||
|
def standings_embed_div(self, division, div_name):
|
||||||
|
this_embed = Embed(color=Color.purple(), title=f"{self.name} Season {self.season}")
|
||||||
|
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}
|
||||||
|
teams = self.division_standings(division, standings)
|
||||||
|
|
||||||
|
for index in range(0, len(teams)):
|
||||||
|
if index == self.constraints["division_leaders"] - 1:
|
||||||
|
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
|
||||||
|
teams_string = ""
|
||||||
|
for this_team in teams:
|
||||||
|
if this_team[2] != 0 or this_team[1] != 0:
|
||||||
|
teams_string += f"**{this_team[0].name}\n**{this_team[1]} - {this_team[2]} WR: {round(this_team[1]/(this_team[1]+this_team[2]), 3)} GB: {this_team[4]}\n\n"
|
||||||
|
else:
|
||||||
|
teams_string += f"**{this_team[0].name}\n**{this_team[1]} - {this_team[2]} WR: - GB: {this_team[4]}\n\n"
|
||||||
|
|
||||||
|
this_embed.add_field(name=f"{div_name} Division:", value=teams_string, inline = False)
|
||||||
|
this_embed.set_footer(text=f"Standings as of day {self.day-1} / {self.season_length()}")
|
||||||
|
return this_embed
|
||||||
|
|
||||||
def wildcard_embed(self):
|
def wildcard_embed(self):
|
||||||
this_embed = Embed(color=Color.purple(), title=f"{self.name} Wildcard Race")
|
this_embed = Embed(color=Color.purple(), title=f"{self.name} Wildcard Race")
|
||||||
standings = {}
|
standings = {}
|
||||||
|
@ -383,6 +415,22 @@ class league_structure(object):
|
||||||
|
|
||||||
return tournaments
|
return tournaments
|
||||||
|
|
||||||
|
def stat_embed(self, stat_name):
|
||||||
|
this_embed = Embed(color=Color.purple(), title=f"{self.name} Season {self.season} {stat_name} Leaders")
|
||||||
|
stats = league_db.get_stats(self.name, stat_name.lower())
|
||||||
|
if stats is None:
|
||||||
|
return None
|
||||||
|
else:
|
||||||
|
stat_names = list(stats[0].keys())[2:]
|
||||||
|
for index in range(0, min(10,len(stats))):
|
||||||
|
this_row = list(stats[index])
|
||||||
|
player_name = this_row.pop(0)
|
||||||
|
content_string = f"**{this_row.pop(0)}**\n"
|
||||||
|
for stat_index in range(0, len(this_row)):
|
||||||
|
content_string += f"**{stat_names[stat_index]}**: {str(this_row[stat_index])}; "
|
||||||
|
this_embed.add_field(name=player_name, value=content_string, inline=False)
|
||||||
|
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):
|
||||||
|
|
|
@ -172,11 +172,24 @@ def update_loop():
|
||||||
state["batter"] = "-"
|
state["batter"] = "-"
|
||||||
elif this_game.top_of_inning:
|
elif this_game.top_of_inning:
|
||||||
state["update_text"] = f"Top of {this_game.inning}. {this_game.teams['away'].name} batting!"
|
state["update_text"] = f"Top of {this_game.inning}. {this_game.teams['away'].name} batting!"
|
||||||
|
if this_game.weather.name == "Drizzle":
|
||||||
|
state["update_emoji"] = "🌧"
|
||||||
|
state["update_text"] += f' Due to inclement weather, {this_game.teams["away"].lineup[(this_game.teams["away"].lineup_position-1) % len(this_game.teams["away"].lineup)].name} is placed on second base.'
|
||||||
|
elif this_game.weather.name == "Heat Wave" and hasattr(this_game.weather, "home_pitcher") and this_game.weather.home_pitcher.name != state["pitcher"]:
|
||||||
|
state["update_emoji"] = "🌄"
|
||||||
|
state["update_text"] += f' {this_game.weather.home_pitcher} is exhausted from the heat. {state["pitcher"]} is forced to pitch!'
|
||||||
|
|
||||||
else:
|
else:
|
||||||
if this_game.inning >= this_game.max_innings:
|
if this_game.inning >= this_game.max_innings:
|
||||||
if this_game.teams["home"].score > this_game.teams["away"].score:
|
if this_game.teams["home"].score > this_game.teams["away"].score:
|
||||||
this_game.victory_lap = True
|
this_game.victory_lap = True
|
||||||
state["update_text"] = f"Bottom of {this_game.inning}. {this_game.teams['home'].name} batting!"
|
state["update_text"] = f"Bottom of {this_game.inning}. {this_game.teams['home'].name} batting!"
|
||||||
|
if this_game.weather.name == "Drizzle":
|
||||||
|
state["update_emoji"] = "🌧"
|
||||||
|
state["update_text"] += f' Due to inclement weather, {this_game.teams["home"].lineup[(this_game.teams["home"].lineup_position-1) % len(this_game.teams["home"].lineup)].name} is placed on second base.'
|
||||||
|
elif this_game.weather.name == "Heat Wave" and hasattr(this_game.weather, "away_pitcher") and this_game.weather.away_pitcher.name != state["pitcher"]:
|
||||||
|
state["update_emoji"] = "🌄"
|
||||||
|
state["update_text"] += f' {this_game.weather.away_pitcher} is exhausted from the heat. {state["pitcher"]} is forced to pitch!'
|
||||||
|
|
||||||
elif state["update_pause"] != 1 and test_string != "Game not started.":
|
elif state["update_pause"] != 1 and test_string != "Game not started.":
|
||||||
if "steals" in this_game.last_update[0].keys():
|
if "steals" in this_game.last_update[0].keys():
|
||||||
|
@ -225,6 +238,8 @@ def update_loop():
|
||||||
elif "error" in this_game.last_update[0].keys():
|
elif "error" in this_game.last_update[0].keys():
|
||||||
state["update_emoji"] = "👻"
|
state["update_emoji"] = "👻"
|
||||||
state["update_text"] = f"{this_game.last_update[0]['batter']}'s hit goes ethereal, and {this_game.last_update[0]['defender']} can't catch it! {this_game.last_update[0]['batter']} reaches base safely."
|
state["update_text"] = f"{this_game.last_update[0]['batter']}'s hit goes ethereal, and {this_game.last_update[0]['defender']} can't catch it! {this_game.last_update[0]['batter']} reaches base safely."
|
||||||
|
if this_game.last_update[1] > 0:
|
||||||
|
updatestring += f"{this_game.last_update[1]} runs scored!"
|
||||||
|
|
||||||
state["bases"] = this_game.named_bases()
|
state["bases"] = this_game.named_bases()
|
||||||
|
|
||||||
|
|
217
the_prestige.py
217
the_prestige.py
|
@ -1,7 +1,7 @@
|
||||||
import discord, json, math, os, roman, games, asyncio, random, main_controller, threading, time, urllib, leagues, datetime
|
import discord, json, math, os, roman, games, asyncio, random, main_controller, threading, time, urllib, leagues, datetime
|
||||||
import database as db
|
import database as db
|
||||||
import onomancer as ono
|
import onomancer as ono
|
||||||
from league_storage import league_exists, season_save
|
from league_storage import league_exists, season_save, season_restart
|
||||||
from the_draft import Draft, DRAFT_ROUNDS
|
from the_draft import Draft, DRAFT_ROUNDS
|
||||||
from flask import Flask
|
from flask import Flask
|
||||||
from uuid import uuid4
|
from uuid import uuid4
|
||||||
|
@ -370,13 +370,26 @@ class MovePlayerCommand(Command):
|
||||||
if owner_id != msg.author.id and msg.author.id not in config()["owners"]:
|
if owner_id != msg.author.id and msg.author.id not in config()["owners"]:
|
||||||
await msg.channel.send("You're not authorized to mess with this team. Sorry, boss.")
|
await msg.channel.send("You're not authorized to mess with this team. Sorry, boss.")
|
||||||
return
|
return
|
||||||
elif not team.slide_player(player_name, new_pos):
|
|
||||||
await msg.channel.send("You either gave us a number that was bigger than your current roster, or we couldn't find the player on the team. Try again.")
|
|
||||||
return
|
|
||||||
else:
|
else:
|
||||||
await msg.channel.send(embed=build_team_embed(team))
|
if team.find_player(player_name)[2] is None or len(team.find_player(player_name)[2]) <= new_pos:
|
||||||
games.update_team(team)
|
await msg.channel.send("You either gave us a number that was bigger than your current roster, or we couldn't find the player on the team. Try again.")
|
||||||
await msg.channel.send("Paperwork signed, stamped, copied, and faxed up to the goddess. Xie's pretty quick with this stuff.")
|
return
|
||||||
|
|
||||||
|
if "batter" in command.split("\n")[0].lower():
|
||||||
|
roster = team.lineup
|
||||||
|
elif "pitcher" in command.split("\n")[0].lower():
|
||||||
|
roster = team.rotation
|
||||||
|
else:
|
||||||
|
roster = None
|
||||||
|
|
||||||
|
if (roster is not None and team.slide_player_spec(player_name, new_pos, roster)) or (roster is None and team.slide_player(player_name, new_pos)):
|
||||||
|
await msg.channel.send(embed=build_team_embed(team))
|
||||||
|
games.update_team(team)
|
||||||
|
await msg.channel.send("Paperwork signed, stamped, copied, and faxed up to the goddess. Xie's pretty quick with this stuff.")
|
||||||
|
else:
|
||||||
|
await msg.channel.send("You either gave us a number that was bigger than your current roster, or we couldn't find the player on the team. Try again.")
|
||||||
|
return
|
||||||
|
|
||||||
except IndexError:
|
except IndexError:
|
||||||
await msg.channel.send("Four lines, remember? Command, then team, then name, and finally, new spot on the lineup or rotation.")
|
await msg.channel.send("Four lines, remember? Command, then team, then name, and finally, new spot on the lineup or rotation.")
|
||||||
|
|
||||||
|
@ -769,38 +782,6 @@ class StartDraftCommand(Command):
|
||||||
raise SlowDraftError('Too slow')
|
raise SlowDraftError('Too slow')
|
||||||
return draft_message
|
return draft_message
|
||||||
|
|
||||||
class DebugLeagueStart(Command):
|
|
||||||
name = "startdebugleague"
|
|
||||||
|
|
||||||
async def execute(self, msg, command):
|
|
||||||
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)
|
|
||||||
|
|
||||||
class DebugLeagueDisplay(Command):
|
|
||||||
name = "displaydebugleague"
|
|
||||||
|
|
||||||
async def execute(self, msg, command):
|
|
||||||
if league_exists("Midseries"):
|
|
||||||
league = leagues.load_league_file("Midseries")
|
|
||||||
league.champion = "Butts"
|
|
||||||
leagues.save_league(league)
|
|
||||||
season_save(league)
|
|
||||||
league.season_reset()
|
|
||||||
|
|
||||||
await msg.channel.send(embed=league.past_standings(1))
|
|
||||||
|
|
||||||
|
|
||||||
class StartLeagueCommand(Command):
|
class StartLeagueCommand(Command):
|
||||||
name = "startleague"
|
name = "startleague"
|
||||||
|
@ -842,6 +823,9 @@ Plays a league with a given name, provided that league has been saved on the web
|
||||||
except ValueError:
|
except ValueError:
|
||||||
await msg.channel.send("Chief, we need a games per hour number between 1 and 12. We think that's reasonable.")
|
await msg.channel.send("Chief, we need a games per hour number between 1 and 12. We think that's reasonable.")
|
||||||
return
|
return
|
||||||
|
except IndexError:
|
||||||
|
await msg.channel.send("We need a games per hour number in the second line.")
|
||||||
|
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)
|
||||||
|
@ -896,6 +880,60 @@ class LeagueDisplayCommand(Command):
|
||||||
else:
|
else:
|
||||||
await msg.channel.send("Can't find that league, boss.")
|
await msg.channel.send("Can't find that league, boss.")
|
||||||
|
|
||||||
|
class LeagueLeadersCommand(Command):
|
||||||
|
name = "leagueleaders"
|
||||||
|
template = "m;leagueleaders [league name]\n[stat name/abbreviation]"
|
||||||
|
description = "Displays a league's leaders in the given stats. A list of the allowed stats can be found on the github readme."
|
||||||
|
|
||||||
|
async def execute(self, msg, command):
|
||||||
|
if league_exists(command.split("\n")[0].strip()):
|
||||||
|
league = leagues.load_league_file(command.split("\n")[0].strip())
|
||||||
|
stat_name = command.split("\n")[1].strip()
|
||||||
|
try:
|
||||||
|
stat_embed = league.stat_embed(stat_name)
|
||||||
|
except IndexError:
|
||||||
|
await msg.channel.send("Nobody's played enough games to get meaningful stats in that category yet, chief. Try again after the next game or two.")
|
||||||
|
return
|
||||||
|
|
||||||
|
if stat_embed is None:
|
||||||
|
await msg.channel.send("We don't know what that stat is, chief.")
|
||||||
|
return
|
||||||
|
try:
|
||||||
|
await msg.channel.send(embed=stat_embed)
|
||||||
|
return
|
||||||
|
except:
|
||||||
|
await msg.channel.send("Nobody's played enough games to get meaningful stats in that category yet, chief. Try again after the next game or two.")
|
||||||
|
return
|
||||||
|
|
||||||
|
await msg.channel.send("Can't find that league, boss.")
|
||||||
|
|
||||||
|
class LeagueDivisionDisplayCommand(Command):
|
||||||
|
name = "divisionstandings"
|
||||||
|
template = "m;divisionstandings [league name]\n[team name]"
|
||||||
|
description = "Displays the current standings for the given division in the given league."
|
||||||
|
|
||||||
|
async def execute(self, msg, command):
|
||||||
|
if league_exists(command.split("\n")[0].strip()):
|
||||||
|
league = leagues.load_league_file(command.split("\n")[0].strip())
|
||||||
|
division_name = command.split("\n")[1].strip()
|
||||||
|
division = None
|
||||||
|
for subleague in iter(league.league.keys()):
|
||||||
|
for div in iter(league.league[subleague].keys()):
|
||||||
|
if div == division_name:
|
||||||
|
division = league.league[subleague][div]
|
||||||
|
if division is None:
|
||||||
|
await msg.channel.send("Chief, that division doesn't exist in that league.")
|
||||||
|
return
|
||||||
|
|
||||||
|
try:
|
||||||
|
await msg.channel.send(embed=league.standings_embed_div(division, division_name))
|
||||||
|
except ValueError:
|
||||||
|
await msg.channel.send("Give us a proper number, boss.")
|
||||||
|
#except TypeError:
|
||||||
|
#await msg.channel.send("That season hasn't been played yet, chief.")
|
||||||
|
else:
|
||||||
|
await msg.channel.send("Can't find that league, boss.")
|
||||||
|
|
||||||
class LeagueWildcardCommand(Command):
|
class LeagueWildcardCommand(Command):
|
||||||
name = "leaguewildcard"
|
name = "leaguewildcard"
|
||||||
template = "m;leaguewildcard [league name]"
|
template = "m;leaguewildcard [league name]"
|
||||||
|
@ -976,18 +1014,60 @@ class LeagueScheduleCommand(Command):
|
||||||
description = "Sends an embed with the given league's schedule for the next 4 series."
|
description = "Sends an embed with the given league's schedule for the next 4 series."
|
||||||
|
|
||||||
async def execute(self, msg, command):
|
async def execute(self, msg, command):
|
||||||
league_name = command.strip()
|
league_name = command.split("\n")[0].strip()
|
||||||
if league_exists(league_name):
|
if league_exists(league_name):
|
||||||
league = leagues.load_league_file(league_name)
|
league = leagues.load_league_file(league_name)
|
||||||
current_series = league.day_to_series_num(league.day)
|
current_series = league.day_to_series_num(league.day)
|
||||||
if str(current_series+1) in league.schedule.keys():
|
if str(current_series+1) in league.schedule.keys():
|
||||||
sched_embed = discord.Embed(title=f"{league.name}'s Schedule:")
|
sched_embed = discord.Embed(title=f"{league.name}'s Schedule:", color=discord.Color.magenta())
|
||||||
days = [0,1,2,3]
|
days = [0,1,2,3]
|
||||||
for day in days:
|
for day in days:
|
||||||
if str(current_series+day) in league.schedule.keys():
|
if str(current_series+day) in league.schedule.keys():
|
||||||
schedule_text = ""
|
schedule_text = ""
|
||||||
|
teams = league.team_names_in_league()
|
||||||
for game in league.schedule[str(current_series+day)]:
|
for game in league.schedule[str(current_series+day)]:
|
||||||
schedule_text += f"**{game[0]}** @ **{game[1]}**\n"
|
schedule_text += f"**{game[0]}** @ **{game[1]}**\n"
|
||||||
|
teams.pop(teams.index(game[0]))
|
||||||
|
teams.pop(teams.index(game[1]))
|
||||||
|
if len(teams) > 0:
|
||||||
|
schedule_text += "Resting:\n"
|
||||||
|
for team in teams:
|
||||||
|
schedule_text += f"**{team}**\n"
|
||||||
|
sched_embed.add_field(name=f"Days {((current_series+day-1)*league.series_length) + 1} - {(current_series+day)*(league.series_length)}", value=schedule_text, inline = False)
|
||||||
|
await msg.channel.send(embed=sched_embed)
|
||||||
|
else:
|
||||||
|
await msg.channel.send("That league's already finished with this season, boss.")
|
||||||
|
else:
|
||||||
|
await msg.channel.send("We can't find that league. Typo?")
|
||||||
|
|
||||||
|
class LeagueTeamScheduleCommand(Command):
|
||||||
|
name = "teamschedule"
|
||||||
|
template = "m;teamschedule [league name]\n[team name]"
|
||||||
|
description = "Sends an embed with the given team's schedule in the given league for the next 7 series."
|
||||||
|
|
||||||
|
async def execute(self, msg, command):
|
||||||
|
league_name = command.split("\n")[0].strip()
|
||||||
|
team_name = command.split("\n")[1].strip()
|
||||||
|
team = get_team_fuzzy_search(team_name)
|
||||||
|
if league_exists(league_name):
|
||||||
|
league = leagues.load_league_file(league_name)
|
||||||
|
current_series = league.day_to_series_num(league.day)
|
||||||
|
|
||||||
|
if team.name not in league.team_names_in_league():
|
||||||
|
await msg.channel.send("Can't find that team in that league, chief.")
|
||||||
|
return
|
||||||
|
|
||||||
|
if str(current_series+1) in league.schedule.keys():
|
||||||
|
sched_embed = discord.Embed(title=f"{team.name}'s Schedule for the {league.name}:", color=discord.Color.purple())
|
||||||
|
days = [0,1,2,3,4,5,6]
|
||||||
|
for day in days:
|
||||||
|
if str(current_series+day) in league.schedule.keys():
|
||||||
|
schedule_text = ""
|
||||||
|
for game in league.schedule[str(current_series+day)]:
|
||||||
|
if team.name in game:
|
||||||
|
schedule_text += f"**{game[0]}** @ **{game[1]}**"
|
||||||
|
if schedule_text == "":
|
||||||
|
schedule_text += "Resting"
|
||||||
sched_embed.add_field(name=f"Days {((current_series+day-1)*league.series_length) + 1} - {(current_series+day)*(league.series_length)}", value=schedule_text, inline = False)
|
sched_embed.add_field(name=f"Days {((current_series+day-1)*league.series_length) + 1} - {(current_series+day)*(league.series_length)}", value=schedule_text, inline = False)
|
||||||
await msg.channel.send(embed=sched_embed)
|
await msg.channel.send(embed=sched_embed)
|
||||||
else:
|
else:
|
||||||
|
@ -995,6 +1075,48 @@ class LeagueScheduleCommand(Command):
|
||||||
else:
|
else:
|
||||||
await msg.channel.send("We can't find that league. Typo?")
|
await msg.channel.send("We can't find that league. Typo?")
|
||||||
|
|
||||||
|
class LeagueRegenerateScheduleCommand(Command):
|
||||||
|
name = "leagueseasonreset"
|
||||||
|
template = "m;leagueseasonreset [league name]"
|
||||||
|
description = "Completely scraps the given league's current season, resetting everything to day 1 of the current season. Requires ownership."
|
||||||
|
|
||||||
|
async def execute(self, msg, command):
|
||||||
|
league_name = command.split("\n")[0].strip()
|
||||||
|
if league_exists(league_name):
|
||||||
|
league = leagues.load_league_file(league_name)
|
||||||
|
if (league.owner is not None and msg.author.id in league.owner) or (league.owner is not None and msg.author.id in config()["owners"]):
|
||||||
|
await msg.channel.send("You got it, boss. Give us two seconds and a bucket of white-out.")
|
||||||
|
season_restart(league)
|
||||||
|
league.season -= 1
|
||||||
|
league.season_reset()
|
||||||
|
await asyncio.sleep(1)
|
||||||
|
await msg.channel.send("Done and dusted. Go ahead and start the league again whenever you want.")
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
await msg.channel.send("That league isn't yours, boss.")
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
await msg.channel.send("We can't find that league. Typo?")
|
||||||
|
|
||||||
|
class LeagueForceStopCommand(Command):
|
||||||
|
name = "leagueforcestop"
|
||||||
|
template = "m;leagueforcestop [league name]"
|
||||||
|
description = "Halts a league and removes it from the list of currently running leagues. To be used in the case of crashed loops."
|
||||||
|
|
||||||
|
def isauthorized(self, user):
|
||||||
|
return user.id in config()["owners"]
|
||||||
|
|
||||||
|
async def execute(self, msg, command):
|
||||||
|
league_name = command.split("\n")[0].strip()
|
||||||
|
for index in range(0,len(active_leagues)):
|
||||||
|
if active_leagues[index].name == league_name:
|
||||||
|
active_leagues.pop(index)
|
||||||
|
await msg.channel.send("League halted, boss. We hope you did that on purpose.")
|
||||||
|
return
|
||||||
|
await msg.channel.send("That league either doesn't exist or isn't in the active list. So, huzzah?")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
commands = [
|
commands = [
|
||||||
IntroduceCommand(),
|
IntroduceCommand(),
|
||||||
|
@ -1023,15 +1145,18 @@ commands = [
|
||||||
StartLeagueCommand(),
|
StartLeagueCommand(),
|
||||||
LeaguePauseCommand(),
|
LeaguePauseCommand(),
|
||||||
LeagueDisplayCommand(),
|
LeagueDisplayCommand(),
|
||||||
|
LeagueLeadersCommand(),
|
||||||
|
LeagueDivisionDisplayCommand(),
|
||||||
LeagueWildcardCommand(),
|
LeagueWildcardCommand(),
|
||||||
LeagueScheduleCommand(),
|
LeagueScheduleCommand(),
|
||||||
|
LeagueTeamScheduleCommand(),
|
||||||
|
LeagueRegenerateScheduleCommand(),
|
||||||
|
LeagueForceStopCommand(),
|
||||||
CreditCommand(),
|
CreditCommand(),
|
||||||
RomanCommand(),
|
RomanCommand(),
|
||||||
HelpCommand(),
|
HelpCommand(),
|
||||||
StartDraftCommand(),
|
StartDraftCommand(),
|
||||||
DraftPlayerCommand(),
|
DraftPlayerCommand()
|
||||||
DebugLeagueStart(),
|
|
||||||
DebugLeagueDisplay()
|
|
||||||
]
|
]
|
||||||
|
|
||||||
client = discord.Client()
|
client = discord.Client()
|
||||||
|
@ -1294,6 +1419,9 @@ def prepare_game(newgame, league = None, weather_name = None):
|
||||||
if newgame.weather.name == "Heavy Snow":
|
if newgame.weather.name == "Heavy Snow":
|
||||||
newgame.weather.counter_away = random.randint(0,len(newgame.teams['away'].lineup)-1)
|
newgame.weather.counter_away = random.randint(0,len(newgame.teams['away'].lineup)-1)
|
||||||
newgame.weather.counter_home = random.randint(0,len(newgame.teams['home'].lineup)-1)
|
newgame.weather.counter_home = random.randint(0,len(newgame.teams['home'].lineup)-1)
|
||||||
|
elif newgame.weather.name == "Heat Wave":
|
||||||
|
newgame.weather.counter_away = random.randint(2,4)
|
||||||
|
newgame.weather.counter_home = random.randint(2,4)
|
||||||
return newgame, state_init
|
return newgame, state_init
|
||||||
|
|
||||||
async def start_tournament_round(channel, tourney, seeding = None):
|
async def start_tournament_round(channel, tourney, seeding = None):
|
||||||
|
@ -1547,6 +1675,7 @@ def build_team_embed(team):
|
||||||
rotation_string += f"{player.name} {player.star_string('pitching_stars')}\n"
|
rotation_string += f"{player.name} {player.star_string('pitching_stars')}\n"
|
||||||
embed.add_field(name="Rotation:", value=rotation_string, inline = False)
|
embed.add_field(name="Rotation:", value=rotation_string, inline = False)
|
||||||
embed.add_field(name="Lineup:", value=lineup_string, inline = False)
|
embed.add_field(name="Lineup:", value=lineup_string, inline = False)
|
||||||
|
embed.add_field(name="█a██:", value=str(abs(hash(team.name)) % (10 ** 4)))
|
||||||
embed.set_footer(text=team.slogan)
|
embed.set_footer(text=team.slogan)
|
||||||
return embed
|
return embed
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue