Merge pull request #1 from Sakimori/indev

Indev
This commit is contained in:
bufar 2021-02-04 16:44:49 -05:00 committed by GitHub
commit ed90af78d7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 348 additions and 48 deletions

View file

@ -132,6 +132,7 @@ these folks are helping me a *ton* via patreon, and i cannot possibly thank them
- Ryan Littleton
- Evie Diver
- iliana etaoin
- yooori
## Attribution

View file

@ -32,10 +32,12 @@ def all_weathers():
weathers_dic = {
#"Supernova" : weather("Supernova", "🌟"),
#"Midnight": weather("Midnight", "🕶"),
"Slight Tailwind": weather("Slight Tailwind", "🏌️‍♀️"),
#"Slight Tailwind": weather("Slight Tailwind", "🏌️‍♀️"),
"Heavy Snow": weather("Heavy Snow", ""),
"Twilight" : weather("Twilight", "👻"),
"Thinned Veil" : weather("Thinned Veil", "🌌")
"Thinned Veil" : weather("Thinned Veil", "🌌"),
"Heat Wave" : weather("Heat Wave", "🌄"),
"Drizzle" : weather("Drizzle", "🌧")
}
return weathers_dic
@ -114,6 +116,11 @@ class team(object):
else:
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):
total_stars = 0
for _player in self.lineup:
@ -152,6 +159,21 @@ class team(object):
else:
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):
if len(self.lineup) < 20:
self.lineup.append(new_player)
@ -169,7 +191,7 @@ class team(object):
def set_pitcher(self, rotation_slot = None, use_lineup = False):
temp_rotation = self.rotation.copy()
if use_lineup:
for batter in self.rotation:
for batter in self.lineup:
temp_rotation.append(batter)
if rotation_slot is None:
self.pitcher = random.choice(temp_rotation)
@ -616,6 +638,25 @@ class game(object):
offense_team.lineup_position += 1 #put next batter up
if self.outs >= 3:
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
@ -635,6 +676,12 @@ class game(object):
self.over = True
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):
rounds = math.ceil(this_team.lineup_position / len(this_team.lineup))
position = random.randint(0, len(this_team.lineup)-1)

View file

@ -3,6 +3,7 @@ import sqlite3 as sql
data_dir = "data"
league_dir = "leagues"
statements_file = os.path.join(data_dir, "sql_statements.xvi")
def create_connection(league_name):
#create connection, create db if doesn't exist
@ -21,6 +22,45 @@ def create_connection(league_name):
print("oops, db connection no work")
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):
#create connection, create db if doesn't exist
conn = None
@ -129,6 +169,19 @@ def add_stats(league_name, player_game_stats_list):
conn.commit()
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):
if league_exists(league_name):
conn = create_connection(league_name)
@ -168,6 +221,13 @@ def season_save(league):
if "." in 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):
if league_exists(league_name):
with os.scandir(os.path.join(data_dir, league_dir, league_name)) as folder:

View file

@ -102,6 +102,14 @@ class league_structure(object):
teams += teams_list
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):
teams = []
if subleague_name in self.league.keys():
@ -201,7 +209,7 @@ class league_structure(object):
if extra_teams != []:
if len(extra_teams) % 2 == 0:
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():
@ -323,6 +331,30 @@ class league_structure(object):
this_embed.set_footer(text=f"Standings as of day {self.day-1} / {self.season_length()}")
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):
this_embed = Embed(color=Color.purple(), title=f"{self.name} Wildcard Race")
standings = {}
@ -383,6 +415,22 @@ class league_structure(object):
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):
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):

View file

@ -172,11 +172,24 @@ def update_loop():
state["batter"] = "-"
elif this_game.top_of_inning:
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:
if this_game.inning >= this_game.max_innings:
if this_game.teams["home"].score > this_game.teams["away"].score:
this_game.victory_lap = True
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.":
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():
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."
if this_game.last_update[1] > 0:
updatestring += f"{this_game.last_update[1]} runs scored!"
state["bases"] = this_game.named_bases()

View file

@ -1,7 +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, season_save
from league_storage import league_exists, season_save, season_restart
from the_draft import Draft, DRAFT_ROUNDS
from flask import Flask
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"]:
await msg.channel.send("You're not authorized to mess with this team. Sorry, boss.")
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:
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.")
if team.find_player(player_name)[2] is None or len(team.find_player(player_name)[2]) <= 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
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:
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')
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):
name = "startleague"
@ -842,6 +823,9 @@ Plays a league with a given name, provided that league has been saved on the web
except ValueError:
await msg.channel.send("Chief, we need a games per hour number between 1 and 12. We think that's reasonable.")
return
except IndexError:
await msg.channel.send("We need a games per hour number in the second line.")
return
if league_exists(league_name):
league = leagues.load_league_file(league_name)
@ -896,6 +880,60 @@ class LeagueDisplayCommand(Command):
else:
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):
name = "leaguewildcard"
template = "m;leaguewildcard [league name]"
@ -976,18 +1014,25 @@ class LeagueScheduleCommand(Command):
description = "Sends an embed with the given league's schedule for the next 4 series."
async def execute(self, msg, command):
league_name = command.strip()
league_name = command.split("\n")[0].strip()
if league_exists(league_name):
league = leagues.load_league_file(league_name)
current_series = league.day_to_series_num(league.day)
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]
for day in days:
if str(current_series+day) in league.schedule.keys():
schedule_text = ""
teams = league.team_names_in_league()
for game in league.schedule[str(current_series+day)]:
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:
@ -995,6 +1040,83 @@ class LeagueScheduleCommand(Command):
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)
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 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 = [
IntroduceCommand(),
@ -1023,15 +1145,18 @@ commands = [
StartLeagueCommand(),
LeaguePauseCommand(),
LeagueDisplayCommand(),
LeagueLeadersCommand(),
LeagueDivisionDisplayCommand(),
LeagueWildcardCommand(),
LeagueScheduleCommand(),
LeagueTeamScheduleCommand(),
LeagueRegenerateScheduleCommand(),
LeagueForceStopCommand(),
CreditCommand(),
RomanCommand(),
HelpCommand(),
StartDraftCommand(),
DraftPlayerCommand(),
DebugLeagueStart(),
DebugLeagueDisplay()
DraftPlayerCommand()
]
client = discord.Client()
@ -1294,6 +1419,9 @@ def prepare_game(newgame, league = None, weather_name = None):
if newgame.weather.name == "Heavy Snow":
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)
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
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"
embed.add_field(name="Rotation:", value=rotation_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)
return embed