implemented #184: leagueleaders, with various stats, reading sql commands from external hotloading file in /data

This commit is contained in:
Sakimori 2021-02-04 02:49:23 -05:00
parent 9f5e2bb19a
commit 468a1e67e7
3 changed files with 92 additions and 0 deletions

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)

View file

@ -415,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

@ -880,6 +880,28 @@ 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()
stat_embed = league.stat_embed(stat_name)
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]"
@ -1118,6 +1140,7 @@ commands = [
StartLeagueCommand(),
LeaguePauseCommand(),
LeagueDisplayCommand(),
LeagueLeadersCommand(),
LeagueDivisionDisplayCommand(),
LeagueWildcardCommand(),
LeagueScheduleCommand(),