Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
ee61e9a923
11
database.py
11
database.py
|
@ -62,7 +62,8 @@ def initialcheck():
|
||||||
counter integer PRIMARY KEY,
|
counter integer PRIMARY KEY,
|
||||||
name text NOT NULL,
|
name text NOT NULL,
|
||||||
team_json_string text NOT NULL,
|
team_json_string text NOT NULL,
|
||||||
timestamp text NOT NULL
|
timestamp text NOT NULL,
|
||||||
|
owner_id integer
|
||||||
); """
|
); """
|
||||||
|
|
||||||
if conn is not None:
|
if conn is not None:
|
||||||
|
@ -190,14 +191,14 @@ def get_user_player(user):
|
||||||
conn.close()
|
conn.close()
|
||||||
return player
|
return player
|
||||||
|
|
||||||
def save_team(name, team_json_string):
|
def save_team(name, team_json_string, user_id):
|
||||||
conn = create_connection()
|
conn = create_connection()
|
||||||
try:
|
try:
|
||||||
if conn is not None:
|
if conn is not None:
|
||||||
c = conn.cursor()
|
c = conn.cursor()
|
||||||
store_string = """ INSERT INTO teams(name, team_json_string, timestamp)
|
store_string = """ INSERT INTO teams(name, team_json_string, timestamp, owner_id)
|
||||||
VALUES (?,?, ?) """
|
VALUES (?,?, ?, ?) """
|
||||||
c.execute(store_string, (re.sub('[^A-Za-z0-9 ]+', '', name), team_json_string, datetime.datetime.now(datetime.timezone.utc))) #this regex removes all non-standard characters
|
c.execute(store_string, (re.sub('[^A-Za-z0-9 ]+', '', name), team_json_string, datetime.datetime.now(datetime.timezone.utc), user_id)) #this regex removes all non-standard characters
|
||||||
conn.commit()
|
conn.commit()
|
||||||
conn.close()
|
conn.close()
|
||||||
return True
|
return True
|
||||||
|
|
92
games.py
92
games.py
|
@ -26,7 +26,7 @@ class appearance_outcomes(Enum):
|
||||||
strikeoutswinging = "strikes out swinging."
|
strikeoutswinging = "strikes out swinging."
|
||||||
groundout = "grounds out to"
|
groundout = "grounds out to"
|
||||||
flyout = "flies out to"
|
flyout = "flies out to"
|
||||||
fielderschoice = "reaches on fielder's choice."
|
fielderschoice = "reaches on fielder's choice. {} is out at {} base." #requires .format(player, base_string)
|
||||||
doubleplay = "grounds into a double play!"
|
doubleplay = "grounds into a double play!"
|
||||||
sacrifice = "hits a sacrifice fly towards"
|
sacrifice = "hits a sacrifice fly towards"
|
||||||
walk = "draws a walk."
|
walk = "draws a walk."
|
||||||
|
@ -182,19 +182,28 @@ class game(object):
|
||||||
else:
|
else:
|
||||||
outcome["text"] = appearance_outcomes.walk
|
outcome["text"] = appearance_outcomes.walk
|
||||||
|
|
||||||
if self.bases[1] is not None and hitnum < -1.3 and self.outs != 2:
|
if self.bases[1] is not None and hitnum < -2 and self.outs != 2:
|
||||||
outcome["text"] = appearance_outcomes.doubleplay
|
outcome["text"] = appearance_outcomes.doubleplay
|
||||||
outcome["defender"] = ""
|
outcome["defender"] = ""
|
||||||
|
|
||||||
for base in self.bases.values():
|
#for base in self.bases.values():
|
||||||
if base is not None:
|
#if base is not None:
|
||||||
fc_flag = True
|
#fc_flag = True
|
||||||
|
|
||||||
if fc_flag and self.outs < 2:
|
runners = [(0,self.get_batter())]
|
||||||
if 0 <= hitnum and hitnum < 1.5:
|
for base in range(1,4):
|
||||||
|
if self.bases[base] == None:
|
||||||
|
break
|
||||||
|
runners.append((base, self.bases[base]))
|
||||||
|
outcome["runners"] = runners #list of consecutive baserunners: (base number, player object)
|
||||||
|
|
||||||
|
if self.outs < 2 and len(runners) > 1: #fielder's choice replaces not great groundouts if any forceouts are present
|
||||||
|
def_stat = random_star_gen("defense_stars", defender)
|
||||||
|
if -1.5 <= hitnum and hitnum < -0.5: #poorly hit groundouts
|
||||||
outcome["text"] = appearance_outcomes.fielderschoice
|
outcome["text"] = appearance_outcomes.fielderschoice
|
||||||
outcome["defender"] = ""
|
outcome["defender"] = ""
|
||||||
elif 2.5 <= hitnum:
|
|
||||||
|
if 2.5 <= hitnum and self.outs < 2: #well hit flyouts can lead to sacrifice flies/advanced runners
|
||||||
if self.bases[2] is not None or self.bases[3] is not None:
|
if self.bases[2] is not None or self.bases[3] is not None:
|
||||||
outcome["advance"] = True
|
outcome["advance"] = True
|
||||||
else:
|
else:
|
||||||
|
@ -230,22 +239,50 @@ class game(object):
|
||||||
self.bases[3] = None
|
self.bases[3] = None
|
||||||
runs = 1
|
runs = 1
|
||||||
if self.bases[2] is not None:
|
if self.bases[2] is not None:
|
||||||
run_roll = random.gauss(math.erf(random_star_gen("baserunning_stars", self.bases[2])-def_stat)-.5,1.5)
|
run_roll = random.gauss(2*math.erf((random_star_gen("baserunning_stars", self.bases[2])-def_stat)/4)-1,3)
|
||||||
if run_roll > 0:
|
if run_roll > 2:
|
||||||
self.bases[3] = self.bases[2]
|
self.bases[3] = self.bases[2]
|
||||||
self.bases[2] = None
|
self.bases[2] = None
|
||||||
return runs
|
return runs
|
||||||
|
|
||||||
elif outcome["text"] == appearance_outcomes.fielderschoice:
|
elif outcome["text"] == appearance_outcomes.fielderschoice:
|
||||||
for base in range(3, 0, -1):
|
furthest_base, runner = outcome["runners"].pop() #get furthest baserunner
|
||||||
if self.bases[base] is not None:
|
self.bases[furthest_base] = None
|
||||||
self.fc_out = self.bases[base]
|
outcome["fc_out"] = (runner.name, base_string(furthest_base+1)) #runner thrown out
|
||||||
for movebase in range(base,1,-1):
|
for index in range(0,len(outcome["runners"])):
|
||||||
self.bases[movebase] = self.bases[movebase-1]
|
base, this_runner = outcome["runners"].pop()
|
||||||
break
|
self.bases[base+1] = this_runner #includes batter, at base 0
|
||||||
self.bases[1] = self.get_batter()
|
if self.bases[3] is not None and furthest_base == 1: #fielders' choice with runners on the corners
|
||||||
|
self.bases[3] = None
|
||||||
|
return 1
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
elif outcome["text"] == appearance_outcomes.groundout or outcome["text"] == appearance_outcomes.doubleplay:
|
||||||
|
runs = 0
|
||||||
|
if self.bases[3] is not None:
|
||||||
|
runs += 1
|
||||||
|
self.bases[3] = None
|
||||||
|
if self.bases[2] is not None:
|
||||||
|
run_roll = random.gauss(2*math.erf((random_star_gen("baserunning_stars", self.bases[2])-def_stat)/4)-1,3)
|
||||||
|
if run_roll > 1.5:
|
||||||
|
self.bases[3] = self.bases[2]
|
||||||
|
self.bases[2] = None
|
||||||
|
if self.bases[1] is not None: #double plays set this to None before this call
|
||||||
|
run_roll = random.gauss(2*math.erf((random_star_gen("baserunning_stars", self.bases[1])-def_stat)/4)-1,3)
|
||||||
|
if run_roll < 2 or self.bases[2] is not None: #if runner can't make it or if baserunner blocking on second, convert to fielder's choice
|
||||||
|
outcome["text"] == appearance_outcomes.fielderschoice
|
||||||
|
runners = [(0,self.get_batter())]
|
||||||
|
for base in range(1,4):
|
||||||
|
if self.bases[base] == None:
|
||||||
|
break
|
||||||
|
runners.append((base, self.bases[base]))
|
||||||
|
outcome["runners"] = runners #rebuild consecutive runners
|
||||||
|
return runs + self.baserunner_check(defender, outcome) #run again as fielder's choice instead
|
||||||
|
else:
|
||||||
|
self.bases[2] = self.bases[1]
|
||||||
|
self.bases[1] = None
|
||||||
|
return runs
|
||||||
|
|
||||||
elif outcome["ishit"]:
|
elif outcome["ishit"]:
|
||||||
runs = 0
|
runs = 0
|
||||||
if outcome["text"] == appearance_outcomes.single:
|
if outcome["text"] == appearance_outcomes.single:
|
||||||
|
@ -354,15 +391,20 @@ class game(object):
|
||||||
self.get_pitcher().game_stats["outs_pitched"] += 2
|
self.get_pitcher().game_stats["outs_pitched"] += 2
|
||||||
self.outs += 2
|
self.outs += 2
|
||||||
self.bases[1] = None
|
self.bases[1] = None
|
||||||
|
if self.outs < 3:
|
||||||
|
scores_to_add += self.baserunner_check(defender, result)
|
||||||
|
self.get_batter().game_stats["rbis"] -= scores_to_add #remove the fake rbi from the player in advance
|
||||||
|
|
||||||
elif result["text"] == appearance_outcomes.fielderschoice:
|
elif result["text"] == appearance_outcomes.fielderschoice or result["text"] == appearance_outcomes.groundout:
|
||||||
self.get_pitcher().game_stats["outs_pitched"] += 1
|
self.get_pitcher().game_stats["outs_pitched"] += 1
|
||||||
self.outs += 1
|
self.outs += 1
|
||||||
|
if self.outs < 3:
|
||||||
scores_to_add += self.baserunner_check(defender, result)
|
scores_to_add += self.baserunner_check(defender, result)
|
||||||
|
|
||||||
elif "advance" in result.keys():
|
elif "advance" in result.keys():
|
||||||
self.get_pitcher().game_stats["outs_pitched"] += 1
|
self.get_pitcher().game_stats["outs_pitched"] += 1
|
||||||
self.outs += 1
|
self.outs += 1
|
||||||
|
if self.outs < 3:
|
||||||
if self.bases[3] is not None:
|
if self.bases[3] is not None:
|
||||||
self.get_batter().game_stats["sacrifices"] += 1
|
self.get_batter().game_stats["sacrifices"] += 1
|
||||||
scores_to_add += self.baserunner_check(defender, result)
|
scores_to_add += self.baserunner_check(defender, result)
|
||||||
|
@ -479,11 +521,11 @@ def get_team(name):
|
||||||
except:
|
except:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def save_team(this_team):
|
def save_team(this_team, user_id):
|
||||||
try:
|
try:
|
||||||
this_team.prepare_for_save()
|
this_team.prepare_for_save()
|
||||||
team_json_string = jsonpickle.encode(this_team, keys=True)
|
team_json_string = jsonpickle.encode(this_team, keys=True)
|
||||||
db.save_team(this_team.name, team_json_string)
|
db.save_team(this_team.name, team_json_string, user_id)
|
||||||
return True
|
return True
|
||||||
except:
|
except:
|
||||||
return None
|
return None
|
||||||
|
@ -501,3 +543,13 @@ def search_team(search_term):
|
||||||
this_team = jsonpickle.decode(team_pickle[0], keys=True, classes=team)
|
this_team = jsonpickle.decode(team_pickle[0], keys=True, classes=team)
|
||||||
teams.append(this_team)
|
teams.append(this_team)
|
||||||
return teams
|
return teams
|
||||||
|
|
||||||
|
def base_string(base):
|
||||||
|
if base == 1:
|
||||||
|
return "first"
|
||||||
|
elif base == 2:
|
||||||
|
return "second"
|
||||||
|
elif base == 3:
|
||||||
|
return "third"
|
||||||
|
elif base == 4:
|
||||||
|
return "fourth"
|
|
@ -28,6 +28,17 @@ Our avatar was graciously provided to us, with permission, by @HetreaSky on Twit
|
||||||
"""
|
"""
|
||||||
await msg.channel.send(text)
|
await msg.channel.send(text)
|
||||||
|
|
||||||
|
class CountActiveGamesCommand(Command):
|
||||||
|
name = "countactivegames"
|
||||||
|
template = ""
|
||||||
|
description = ""
|
||||||
|
|
||||||
|
def isauthorized(self, user):
|
||||||
|
return user.id in config()["owners"]
|
||||||
|
|
||||||
|
async def execute(self, msg, command):
|
||||||
|
await msg.channel.send(f"There's {len(gamesarray)} active games right now, boss.")
|
||||||
|
|
||||||
class RomanCommand(Command):
|
class RomanCommand(Command):
|
||||||
name = "roman"
|
name = "roman"
|
||||||
template = "m;roman [number]"
|
template = "m;roman [number]"
|
||||||
|
@ -98,10 +109,7 @@ class StartGameCommand(Command):
|
||||||
- the third is the number of innings, which must be greater than 2."""
|
- the third is the number of innings, which must be greater than 2."""
|
||||||
|
|
||||||
async def execute(self, msg, command):
|
async def execute(self, msg, command):
|
||||||
if len(gamesarray) > 45:
|
if config()["game_freeze"]:
|
||||||
await msg.channel.send("We're running 45 games and we doubt Discord will be happy with any more. These edit requests don't come cheap.")
|
|
||||||
return
|
|
||||||
elif config()["game_freeze"]:
|
|
||||||
await msg.channel.send("Patch incoming. We're not allowing new games right now.")
|
await msg.channel.send("Patch incoming. We're not allowing new games right now.")
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -126,7 +134,15 @@ class StartGameCommand(Command):
|
||||||
|
|
||||||
if team1 is not None and team2 is not None:
|
if team1 is not None and team2 is not None:
|
||||||
game = games.game(msg.author.name, team1, team2, length=innings)
|
game = games.game(msg.author.name, team1, team2, length=innings)
|
||||||
game_task = asyncio.create_task(watch_game(msg.channel, game))
|
channel = msg.channel
|
||||||
|
user_mention = msg.author.mention
|
||||||
|
await msg.delete()
|
||||||
|
if len(gamesarray) >= 45:
|
||||||
|
await channel.send(f"We're running 45 games right now, and Discord probably isn't very pleased about it. You're at #{len(gamesqueue)+1} in the list.\nWe'll ping you when it's ready, chief.")
|
||||||
|
gamesqueue.append((channel, game, user_mention))
|
||||||
|
return
|
||||||
|
|
||||||
|
game_task = asyncio.create_task(watch_game(channel, game))
|
||||||
await game_task
|
await game_task
|
||||||
|
|
||||||
class SetupGameCommand(Command):
|
class SetupGameCommand(Command):
|
||||||
|
@ -143,7 +159,7 @@ class SetupGameCommand(Command):
|
||||||
return
|
return
|
||||||
|
|
||||||
for game in gamesarray:
|
for game in gamesarray:
|
||||||
if game[0].name == msg.author.name:
|
if game.name == msg.author.name:
|
||||||
await msg.channel.send("You've already got a game in progress! Wait a tick, boss.")
|
await msg.channel.send("You've already got a game in progress! Wait a tick, boss.")
|
||||||
return
|
return
|
||||||
try:
|
try:
|
||||||
|
@ -236,6 +252,7 @@ class HelpCommand(Command):
|
||||||
|
|
||||||
commands = [
|
commands = [
|
||||||
IntroduceCommand(),
|
IntroduceCommand(),
|
||||||
|
CountActiveGamesCommand(),
|
||||||
IdolizeCommand(),
|
IdolizeCommand(),
|
||||||
ShowIdolCommand(),
|
ShowIdolCommand(),
|
||||||
ShowPlayerCommand(),
|
ShowPlayerCommand(),
|
||||||
|
@ -252,6 +269,7 @@ commands = [
|
||||||
|
|
||||||
client = discord.Client()
|
client = discord.Client()
|
||||||
gamesarray = []
|
gamesarray = []
|
||||||
|
gamesqueue = []
|
||||||
setupmessages = {}
|
setupmessages = {}
|
||||||
|
|
||||||
def config():
|
def config():
|
||||||
|
@ -473,11 +491,7 @@ async def watch_game(channel, game):
|
||||||
await asyncio.sleep(1)
|
await asyncio.sleep(1)
|
||||||
await embed.pin()
|
await embed.pin()
|
||||||
await asyncio.sleep(1)
|
await asyncio.sleep(1)
|
||||||
use_emoji_names = True
|
gamesarray.append(newgame)
|
||||||
for game in gamesarray:
|
|
||||||
if game[1]:
|
|
||||||
use_emoji_names = False
|
|
||||||
gamesarray.append((newgame,use_emoji_names))
|
|
||||||
pause = 0
|
pause = 0
|
||||||
top_of_inning = True
|
top_of_inning = True
|
||||||
victory_lap = False
|
victory_lap = False
|
||||||
|
@ -525,6 +539,10 @@ async def watch_game(channel, game):
|
||||||
if newgame.last_update[0]["defender"] != "":
|
if newgame.last_update[0]["defender"] != "":
|
||||||
punc = ". "
|
punc = ". "
|
||||||
|
|
||||||
|
if "fc_out" in newgame.last_update[0].keys():
|
||||||
|
name, base_string = newgame.last_update[0]['fc_out']
|
||||||
|
updatestring = f"{newgame.last_update[0]['batter']} {newgame.last_update[0]['text'].value.format(name, base_string)} {newgame.last_update[0]['defender']}{punc}"
|
||||||
|
else:
|
||||||
updatestring = f"{newgame.last_update[0]['batter']} {newgame.last_update[0]['text'].value} {newgame.last_update[0]['defender']}{punc}"
|
updatestring = f"{newgame.last_update[0]['batter']} {newgame.last_update[0]['text'].value} {newgame.last_update[0]['defender']}{punc}"
|
||||||
if newgame.last_update[1] > 0:
|
if newgame.last_update[1] > 0:
|
||||||
updatestring += f"{newgame.last_update[1]} runs scored!"
|
updatestring += f"{newgame.last_update[1]} runs scored!"
|
||||||
|
@ -560,9 +578,9 @@ async def watch_game(channel, game):
|
||||||
pause -= 1
|
pause -= 1
|
||||||
await asyncio.sleep(6)
|
await asyncio.sleep(6)
|
||||||
|
|
||||||
title_string = f"{newgame.teams['away'].name} at {newgame.teams['home'].name} ended after {newgame.inning} innings"
|
title_string = f"{newgame.teams['away'].name} at {newgame.teams['home'].name} ended after {newgame.inning-1} innings"
|
||||||
if newgame.inning > (newgame.max_innings - 1): #if extra innings
|
if (newgame.inning - 1) > newgame.max_innings: #if extra innings
|
||||||
title_string += f" with {newgame.inning - (newgame.max_innings-1)} extra innings."
|
title_string += f" with {newgame.inning - (newgame.max_innings+1)} extra innings."
|
||||||
else:
|
else:
|
||||||
title_string += "."
|
title_string += "."
|
||||||
|
|
||||||
|
@ -584,9 +602,20 @@ async def watch_game(channel, game):
|
||||||
await embed.edit(content=None, embed=final_embed)
|
await embed.edit(content=None, embed=final_embed)
|
||||||
|
|
||||||
await embed.unpin()
|
await embed.unpin()
|
||||||
gamesarray.pop(gamesarray.index((newgame,use_emoji_names))) #cleanup is important!
|
gamesarray.pop(gamesarray.index(newgame)) #cleanup is important!
|
||||||
newgame.add_stats()
|
newgame.add_stats()
|
||||||
del newgame
|
del newgame
|
||||||
|
if len(gamesqueue) > 0:
|
||||||
|
channel, game, user_mention = gamesqueue.pop(0)
|
||||||
|
queue_task = asyncio.create_task(play_from_queue(channel, game, user_mention))
|
||||||
|
await queue_task
|
||||||
|
|
||||||
|
async def play_from_queue(channel, game, user_mention):
|
||||||
|
await channel.send(f"{user_mention}, your game's ready.")
|
||||||
|
game_task = asyncio.create_task(watch_game(channel, game))
|
||||||
|
await game_task
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def build_team_embed(team):
|
def build_team_embed(team):
|
||||||
embed = discord.Embed(color=discord.Color.purple(), title=team.name)
|
embed = discord.Embed(color=discord.Color.purple(), title=team.name)
|
||||||
|
@ -652,7 +681,7 @@ async def save_team_batch(message, command):
|
||||||
react, user = await client.wait_for('reaction_add', timeout=20.0, check=react_check)
|
react, user = await client.wait_for('reaction_add', timeout=20.0, check=react_check)
|
||||||
if react.emoji == "👍":
|
if react.emoji == "👍":
|
||||||
await message.channel.send("You got it, chief. Saving now.")
|
await message.channel.send("You got it, chief. Saving now.")
|
||||||
games.save_team(newteam)
|
games.save_team(newteam, message.author.id)
|
||||||
await message.channel.send("Saved! Thank you for flying Air Matteo. We hope you had a pleasant data entry.")
|
await message.channel.send("Saved! Thank you for flying Air Matteo. We hope you had a pleasant data entry.")
|
||||||
return
|
return
|
||||||
elif react.emoji == "👎":
|
elif react.emoji == "👎":
|
||||||
|
@ -698,8 +727,10 @@ async def team_pages(msg, all_teams, search_term=None):
|
||||||
react, user = await client.wait_for('reaction_add', timeout=60.0, check=react_check)
|
react, user = await client.wait_for('reaction_add', timeout=60.0, check=react_check)
|
||||||
if react.emoji == "◀" and current_page > 0:
|
if react.emoji == "◀" and current_page > 0:
|
||||||
current_page -= 1
|
current_page -= 1
|
||||||
|
await react.remove(user)
|
||||||
elif react.emoji == "▶" and current_page < (page_max-1):
|
elif react.emoji == "▶" and current_page < (page_max-1):
|
||||||
current_page += 1
|
current_page += 1
|
||||||
|
await react.remove(user)
|
||||||
await teams_list.edit(embed=pages[current_page])
|
await teams_list.edit(embed=pages[current_page])
|
||||||
except asyncio.TimeoutError:
|
except asyncio.TimeoutError:
|
||||||
return
|
return
|
||||||
|
|
Loading…
Reference in New Issue
Block a user