1257 lines
60 KiB
Python
1257 lines
60 KiB
Python
import math
|
|
|
|
import discord
|
|
from discord import app_commands
|
|
from discord.ext import commands
|
|
from peewee import IntegrityError
|
|
|
|
from typing import Optional, Literal
|
|
import logging
|
|
|
|
from helpers import SBA_PLAYERS_ROLE_NAME, PD_PLAYERS_ROLE_NAME, random_conf_gif, SBA_SEASON, PD_SEASON, LOGO, \
|
|
get_team_embed, Confirm, get_pos_abbrev, SBA_COLOR
|
|
from gameplay_helpers import *
|
|
from db_calls import get_one_team, get_one_player
|
|
from db_calls_gameplay import StratGame, StratPlay, StratLineup, get_one_game, pd_get_one_team, post_game, patch_game, \
|
|
get_game_team, post_lineups, pd_get_card_by_id, make_sub, get_player, player_link, get_team_lineups, \
|
|
get_current_play, post_play, get_one_lineup, advance_runners, patch_play, complete_play, get_batting_stats, \
|
|
get_pitching_stats, undo_play, get_latest_play, advance_one_runner, get_play_by_num
|
|
|
|
|
|
class Gameplay(commands.Cog):
|
|
def __init__(self, bot):
|
|
self.bot = bot
|
|
|
|
async def cog_command_error(self, ctx, error):
|
|
await ctx.send(f'{error}\n\nRun !help <command_name> to see the command requirements')
|
|
|
|
async def slash_error(self, ctx, error):
|
|
await ctx.send(f'{error}')
|
|
|
|
def get_scorebug(self, home_team, away_team, curr_play):
|
|
occupied = '●'
|
|
unoccupied = '○'
|
|
|
|
first_base = unoccupied if not curr_play.on_first else occupied
|
|
second_base = unoccupied if not curr_play.on_second else occupied
|
|
third_base = unoccupied if not curr_play.on_third else occupied
|
|
half = '▲' if curr_play.inning_half == 'Top' else '▼'
|
|
inning = f'{half} {curr_play.inning_num}'
|
|
outs = f'{curr_play.starting_outs} Out{"s" if curr_play.starting_outs != 1 else ""}'
|
|
|
|
game_string = f'```\n' \
|
|
f'{away_team["abbrev"]: ^4}{curr_play.away_score: ^3} {second_base}' \
|
|
f'{inning: >10}\n' \
|
|
f'{home_team["abbrev"]: ^4}{curr_play.home_score: ^3} {third_base} {first_base}' \
|
|
f'{outs: >8}\n```'
|
|
|
|
return game_string
|
|
|
|
async def get_game_state(self, game: StratGame) -> dict:
|
|
curr_play = get_current_play(game.id)
|
|
if curr_play is None:
|
|
latest_play = get_latest_play(game.id)
|
|
if not latest_play:
|
|
away_lineup = await get_team_lineups(game.id, game.away_team_id)
|
|
home_lineup = await get_team_lineups(game.id, game.home_team_id)
|
|
|
|
if len(away_lineup) == 0 or len(home_lineup) == 0:
|
|
game_state = {
|
|
'error': True,
|
|
'away_lineup': away_lineup,
|
|
'home_lineup': home_lineup
|
|
}
|
|
return game_state
|
|
else:
|
|
curr_play = post_play({
|
|
'game_id': game.id,
|
|
'play_num': 1,
|
|
'batter_id': get_one_lineup(game.id, game.away_team_id, batting_order=1).id,
|
|
'pitcher_id': get_one_lineup(game.id, game.home_team_id, position='P').id,
|
|
'on_base_code': 0,
|
|
'inning_half': 'Top',
|
|
'inning_num': 1,
|
|
'batting_order': 1,
|
|
'starting_outs': 0,
|
|
'away_score': 0,
|
|
'home_score': 0
|
|
})
|
|
else:
|
|
patch_play(latest_play.id, complete=False)
|
|
curr_play = latest_play
|
|
|
|
game_state = {'error': False, 'curr_play': curr_play}
|
|
|
|
away_team = await get_game_team(game, team_id=game.away_team_id)
|
|
home_team = await get_game_team(game, team_id=game.home_team_id)
|
|
game_state['away_team'] = away_team
|
|
game_state['home_team'] = home_team
|
|
|
|
scorebug = self.get_scorebug(home_team, away_team, game_state['curr_play'])
|
|
game_state['scorebug'] = scorebug
|
|
|
|
batter = await get_player(game, game_state['curr_play'].batter)
|
|
litmus = 0
|
|
try:
|
|
pitcher = await get_player(game, game_state['curr_play'].pitcher)
|
|
litmus = 1
|
|
catcher = await get_player(
|
|
game,
|
|
get_one_lineup(
|
|
game.id,
|
|
team_id=game.away_team_id if game_state['curr_play'].inning_half == 'Top' else game.home_team_id,
|
|
position='C'
|
|
)
|
|
)
|
|
except Exception as e:
|
|
logging.info(f'ERROR: {e} / TYPE: {type(e)}')
|
|
away_lineup = await get_team_lineups(game.id, game.away_team_id)
|
|
home_lineup = await get_team_lineups(game.id, game.home_team_id)
|
|
if litmus == 0:
|
|
error_message = f'Please sub in a pitcher to continue'
|
|
else:
|
|
error_message = f'Please sub in a catcher to continue'
|
|
|
|
game_state['error'] = True
|
|
game_state['error_message'] = error_message
|
|
game_state['away_lineup'] = away_lineup
|
|
game_state['home_lineup'] = home_lineup
|
|
return game_state
|
|
|
|
game_state['batter'] = batter
|
|
game_state['pitcher'] = pitcher
|
|
game_state['catcher'] = catcher
|
|
|
|
return game_state
|
|
|
|
async def get_game_state_embed(self, game: StratGame, full_length=True):
|
|
game_state = await self.get_game_state(game)
|
|
|
|
logging.info(f'game_state: {game_state}')
|
|
|
|
embed = get_team_embed(
|
|
f'{game_state["away_team"]["sname"]} @ {game_state["home_team"]["sname"]}',
|
|
team=game_state['home_team'],
|
|
thumbnail=False
|
|
)
|
|
if abs(game_state['curr_play'].home_score - game_state['curr_play'].away_score) >= 10:
|
|
embed.description = 'Mercy rule in effect'
|
|
|
|
if game.is_pd:
|
|
embed.set_footer(text=f'PD Season {PD_SEASON}', icon_url=LOGO)
|
|
|
|
embed.add_field(name='Game State', value=game_state['scorebug'], inline=False)
|
|
|
|
if game_state['error']:
|
|
# embed = discord.Embed(
|
|
# title='Current Lineups',
|
|
# color=int(SBA_COLOR, 16)
|
|
# )
|
|
embed.add_field(name='Away Team',
|
|
value=game_state['away_lineup'] if len(game_state['away_lineup']) else 'None, yet')
|
|
embed.add_field(name='Home Team',
|
|
value=game_state['home_lineup'] if len(game_state['home_lineup']) else 'None, yet')
|
|
if game_state['error_message']:
|
|
embed.set_footer(text=game_state['error_message'], icon_url=LOGO)
|
|
|
|
return embed
|
|
|
|
pitcher_string = f'{player_link(game, game_state["pitcher"])}'
|
|
batter_string = f'{player_link(game, game_state["batter"])}'
|
|
|
|
all_bat_stats = get_batting_stats(game.id, lineup_id=game_state['curr_play'].batter.id)
|
|
if len(all_bat_stats):
|
|
b_s = all_bat_stats[0]
|
|
batter_string += f'\n{b_s["pl_hit"]}-{b_s["pl_ab"]}'
|
|
for num, stat in [
|
|
(b_s['pl_double'], '2B'), (b_s['pl_triple'], '3B'), (b_s['pl_homerun'], 'HR'), (b_s['pl_rbi'], 'RBI'),
|
|
(b_s['pl_bb'], 'BB'), (b_s['pl_hbp'], 'HBP'), (b_s['pl_ibb'], 'IBB'), (b_s['pl_so'], 'K'),
|
|
(b_s['pl_gidp'], 'GIDP'), (b_s['pl_bpfo'], 'BPFO'), (b_s['pl_bplo'], 'BPLO')
|
|
]:
|
|
if num:
|
|
batter_string += f', {num if num > 1 else ""}{" " if num > 1 else ""}{stat}'
|
|
|
|
all_pit_stats = get_pitching_stats(game.id, lineup_id=game_state['curr_play'].pitcher.id)
|
|
if len(all_pit_stats):
|
|
p_s = all_pit_stats[0]
|
|
pitcher_string += f'\n{math.floor(p_s["pl_outs"]/3)}.{p_s["pl_outs"] % 3} IP'
|
|
for num, stat in [
|
|
(p_s['pl_runs'], 'R'), (p_s['pl_hit'], 'H'), (p_s['pl_homerun'], 'HR'), (p_s['pl_so'], 'K'),
|
|
(p_s['pl_bb'], 'BB'), (p_s['pl_hbp'], 'HBP'), (p_s['pl_wild_pitch'], 'WP'), (p_s['pl_balk'], 'BK'),
|
|
]:
|
|
if num:
|
|
pitcher_string += f', {num} {stat}'
|
|
if stat == 'R' and num != p_s['pl_eruns']:
|
|
pitcher_string += f', {p_s["pl_eruns"]} ER'
|
|
|
|
# embed.add_field(name='Matchup', value=f'Pitcher: \nvs\nBatter: ', inline=False)
|
|
embed.add_field(name='Pitcher', value=f'{pitcher_string}')
|
|
embed.add_field(name='Batter', value=f'{batter_string}')
|
|
embed.set_thumbnail(url=game_state["pitcher"]["image"])
|
|
embed.set_image(url=game_state["batter"]["image"])
|
|
|
|
baserunner_string = ''
|
|
if game_state['curr_play'].on_first:
|
|
runner = await get_player(game, game_state['curr_play'].on_first)
|
|
baserunner_string += f'On First: {player_link(game, runner)}\n'
|
|
if game_state['curr_play'].on_second:
|
|
runner = await get_player(game, game_state['curr_play'].on_second)
|
|
baserunner_string += f'On Second: {player_link(game, runner)}\n'
|
|
if game_state['curr_play'].on_third:
|
|
runner = await get_player(game, game_state['curr_play'].on_third)
|
|
baserunner_string += f'On Third: {player_link(game, runner)}\n'
|
|
embed.add_field(
|
|
name='Baserunners', value=baserunner_string if len(baserunner_string) > 0 else 'None', inline=False
|
|
)
|
|
|
|
if not full_length:
|
|
return embed
|
|
|
|
away_lineup = await get_team_lineups(game.id, game.away_team_id)
|
|
home_lineup = await get_team_lineups(game.id, game.home_team_id)
|
|
embed.add_field(name=f'{game_state["away_team"]["abbrev"]} Lineup', value=away_lineup)
|
|
embed.add_field(name=f'{game_state["home_team"]["abbrev"]} Lineup', value=home_lineup)
|
|
return embed
|
|
|
|
@commands.hybrid_command(name='newgame', help='Start a new baseball game')
|
|
@commands.has_any_role(SBA_PLAYERS_ROLE_NAME, PD_PLAYERS_ROLE_NAME)
|
|
async def new_game_command(
|
|
self, ctx: commands.Context, away_team_abbrev: str, home_team_abbrev: str, week_num: int,
|
|
game_num: Optional[int] = None, is_pd: Optional[bool] = False):
|
|
conflict = get_one_game(channel_id=ctx.channel.id, active=True)
|
|
if conflict:
|
|
await ctx.send(f'Ope. There is already a game going on in this channel. Please wait for it to complete '
|
|
f'before starting a new one.')
|
|
return
|
|
|
|
if is_pd:
|
|
away_team = pd_get_one_team(away_team_abbrev)
|
|
home_team = pd_get_one_team(home_team_abbrev)
|
|
if ctx.author.id not in [away_team['gmid'], home_team['gmid']]:
|
|
await ctx.send('You can only start a new game if you GM one of the teams.')
|
|
return
|
|
else:
|
|
away_team = await get_one_team(away_team_abbrev)
|
|
home_team = await get_one_team(home_team_abbrev)
|
|
if ctx.author.id not in [away_team['gmid'], away_team['gmid2'], home_team['gmid'], home_team['gmid2']]:
|
|
await ctx.send('You can only start a new game if you GM one of the teams.')
|
|
return
|
|
|
|
post_game({
|
|
'away_team_id': away_team['id'],
|
|
'home_team_id': home_team['id'],
|
|
'week_num': week_num,
|
|
'game_num': game_num,
|
|
'channel_id': ctx.channel.id,
|
|
'active': True,
|
|
'is_pd': is_pd
|
|
})
|
|
|
|
await ctx.send(random_conf_gif())
|
|
|
|
@commands.hybrid_command(name='endgame', help='End game in this channel')
|
|
@commands.has_any_role(SBA_PLAYERS_ROLE_NAME, PD_PLAYERS_ROLE_NAME)
|
|
async def end_game_command(self, ctx: commands.Context):
|
|
this_game = get_one_game(channel_id=ctx.channel.id, active=True)
|
|
if not this_game:
|
|
await ctx.send(f'Ope, I don\'t see a game in this channel.')
|
|
return
|
|
|
|
patch_game(this_game.id, active=False)
|
|
|
|
# TODO: create result sheet and submit stats
|
|
if this_game.is_pd:
|
|
# Build the statlines
|
|
# Submit the scorecard
|
|
# Post a notification to PD for rewards
|
|
pass
|
|
else:
|
|
# Send stats to sheets
|
|
# Post sheets link
|
|
pass
|
|
|
|
await ctx.send(random_conf_gif())
|
|
|
|
@app_commands.command(
|
|
name='setlineup',
|
|
description='Set starting lineup for game in this channel; Player Name for SBa games / Card ID for PD games',
|
|
)
|
|
@app_commands.describe(
|
|
order_1_player='SBa: Player Name; PD: Card #',
|
|
order_1_pos='C for Catcher, 1B for first base, P for pitcher, etc.',
|
|
order_2_player='SBa: Player Name; PD: Card #',
|
|
order_2_pos='C for Catcher, 1B for first base, P for pitcher, etc.',
|
|
order_3_player='SBa: Player Name; PD: Card #',
|
|
order_3_pos='C for Catcher, 1B for first base, P for pitcher, etc.',
|
|
order_4_player='SBa: Player Name; PD: Card #',
|
|
order_4_pos='C for Catcher, 1B for first base, P for pitcher, etc.',
|
|
order_5_player='SBa: Player Name; PD: Card #',
|
|
order_5_pos='C for Catcher, 1B for first base, P for pitcher, etc.',
|
|
order_6_player='SBa: Player Name; PD: Card #',
|
|
order_6_pos='C for Catcher, 1B for first base, P for pitcher, etc.',
|
|
order_7_player='SBa: Player Name; PD: Card #',
|
|
order_7_pos='C for Catcher, 1B for first base, P for pitcher, etc.',
|
|
order_8_player='SBa: Player Name; PD: Card #',
|
|
order_8_pos='C for Catcher, 1B for first base, P for pitcher, etc.',
|
|
order_9_player='SBa: Player Name; PD: Card #',
|
|
order_9_pos='C for Catcher, 1B for first base, P for pitcher, etc.',
|
|
order_10_player='SBa: Player Name; PD: Card #; only used with a DH',
|
|
order_10_pos='P for pitcher; only used with a DH'
|
|
)
|
|
@app_commands.checks.has_any_role(SBA_PLAYERS_ROLE_NAME, PD_PLAYERS_ROLE_NAME)
|
|
async def set_lineup_command(
|
|
self, interaction: discord.Interaction, team_abbrev: str, order_1_player: str, order_1_pos: str,
|
|
order_2_player: str, order_2_pos: str, order_3_player: str, order_3_pos: str, order_4_player: str,
|
|
order_4_pos: str, order_5_player: str, order_5_pos: str, order_6_player: str, order_6_pos: str,
|
|
order_7_player: str, order_7_pos: str, order_8_player: str, order_8_pos: str, order_9_player: str,
|
|
order_9_pos: str, order_10_player: Optional[str] = None, order_10_pos: Optional[str] = 'P'):
|
|
this_game = get_one_game(channel_id=interaction.channel_id, active=True)
|
|
if not this_game:
|
|
await interaction.response.send_message(f'I dont\'t see an active game in this channel!')
|
|
return
|
|
|
|
owner_team = await get_game_team(this_game, interaction.user.id)
|
|
lineup_team = await get_game_team(this_game, team_abbrev=team_abbrev)
|
|
|
|
if not owner_team['id'] in [this_game.away_team_id, this_game.home_team_id]:
|
|
await interaction.response.send_message('Bruh. Only GMs of the active teams can set lineups.')
|
|
return
|
|
if not lineup_team['id'] in [this_game.away_team_id, this_game.home_team_id]:
|
|
await interaction.response.send_message(f'I do not see {lineup_team["sname"]} in this game. Please check the team abbrev and '
|
|
f'try again')
|
|
return
|
|
|
|
existing_lineups = await get_team_lineups(this_game.id, lineup_team['id'])
|
|
if not existing_lineups or not len(existing_lineups):
|
|
await interaction.response.send_message(
|
|
f'It looks like the {lineup_team["sname"]} already have a lineup. Run `/substitution` to make changes.'
|
|
)
|
|
return
|
|
|
|
await interaction.response.defer()
|
|
|
|
all_lineups = []
|
|
all_pos = []
|
|
lineup_data = [
|
|
(order_1_player, order_1_pos), (order_2_player, order_2_pos), (order_3_player, order_3_pos),
|
|
(order_4_player, order_4_pos), (order_5_player, order_5_pos), (order_6_player, order_6_pos),
|
|
(order_7_player, order_7_pos), (order_8_player, order_8_pos), (order_9_player, order_9_pos),
|
|
(order_10_player, order_10_pos)
|
|
]
|
|
for index, pair in enumerate(lineup_data):
|
|
if not pair[0]:
|
|
break
|
|
|
|
if pair[1].upper() not in all_pos:
|
|
all_pos.append(pair[1].upper())
|
|
else:
|
|
raise SyntaxError(f'You have more than one {pair[1].upper()} in this lineup. Please update and set the '
|
|
f'lineup again.')
|
|
|
|
if this_game.is_pd:
|
|
this_card = pd_get_card_by_id(int(pair[0]))
|
|
if this_card['team']['id'] != lineup_team['id']:
|
|
raise SyntaxError(f'Easy there, champ. Looks like card ID {pair[0]} belongs to the '
|
|
f'{this_card["team"]["sname"]}. Try again with only cards you own.')
|
|
player_id = this_card['player']['id']
|
|
card_id = pair[0]
|
|
else:
|
|
this_player = await get_one_player(pair[0], season=SBA_SEASON)
|
|
if this_player['team']['id'] != lineup_team['id']:
|
|
raise SyntaxError(f'Easy there, champ. Looks like {pair[0]} is on '
|
|
f'{this_player["team"]["sname"]}. Try again with only your own players.')
|
|
player_id = this_player['id']
|
|
card_id = None
|
|
|
|
this_lineup = {
|
|
'game_id': this_game.id,
|
|
'team_id': lineup_team['id'],
|
|
'player_id': player_id,
|
|
'card_id': card_id,
|
|
'position': pair[1].upper(),
|
|
'batting_order': index + 1,
|
|
'after_play': 0
|
|
}
|
|
|
|
all_lineups.append(this_lineup)
|
|
|
|
logging.info(f'Setting lineup for {owner_team["sname"]} in {"PD" if this_game.is_pd else "SBa"} game')
|
|
post_lineups(all_lineups)
|
|
|
|
try:
|
|
await interaction.edit_original_message(content=None, embed=await self.get_game_state_embed(this_game))
|
|
except IntegrityError as e:
|
|
logging.info(f'Unable to pull game_state for game_id {this_game.id} until both lineups are in: {e}')
|
|
await interaction.response.send_message(f'Game state will be posted once both lineups are in')
|
|
return
|
|
|
|
@commands.hybrid_command(
|
|
name='substitution',
|
|
help='Make a lineup substitution; Player Name for SBa games / Card ID for PD games',
|
|
aliases=['sub']
|
|
)
|
|
@app_commands.describe(
|
|
new_player='For SBa game: enter the Player Name; for PD game: enter the Card ID (a number)')
|
|
@commands.has_any_role(SBA_PLAYERS_ROLE_NAME, PD_PLAYERS_ROLE_NAME)
|
|
async def substitution_command(
|
|
self, ctx: commands.Context, team_abbrev: str, order_number: int, new_player: str, new_pos: str):
|
|
this_game = get_one_game(channel_id=ctx.channel.id, active=True)
|
|
if not this_game:
|
|
await ctx.send(f'I dont\'t see an active game in this channel!')
|
|
return
|
|
|
|
owner_team = await get_game_team(this_game, ctx.author.id)
|
|
lineup_team = await get_game_team(this_game, team_abbrev=team_abbrev)
|
|
|
|
if not owner_team['id'] in [this_game.away_team_id, this_game.home_team_id]:
|
|
await ctx.send('Bruh. Only GMs of the active teams can set lineups.')
|
|
return
|
|
|
|
if not lineup_team['id'] in [this_game.away_team_id, this_game.home_team_id]:
|
|
await ctx.send(f'I do not see {lineup_team["sname"]} in this game. Please check the team abbrev and '
|
|
f'try again')
|
|
return
|
|
|
|
if this_game.is_pd:
|
|
this_card = pd_get_card_by_id(int(new_player))
|
|
if this_card["team"]["id"] != lineup_team['id']:
|
|
raise SyntaxError(f'Easy there, champ. Looks like card ID {new_player} belongs to the '
|
|
f'{this_card["team"]["sname"]}. Try again with only cards you own.')
|
|
player_id = this_card['player']['id']
|
|
card_id = new_player
|
|
else:
|
|
this_player = await get_one_player(new_player, season=SBA_SEASON)
|
|
if this_player['team']['id'] != lineup_team['id']:
|
|
raise SyntaxError(f'Easy there, champ. Looks like {new_player} is on '
|
|
f'{this_player["team"]["sname"]}. Try again with only your own players.')
|
|
player_id = this_player['id']
|
|
card_id = None
|
|
|
|
curr_play = get_current_play(this_game.id)
|
|
this_lineup = {
|
|
'game_id': this_game.id,
|
|
'team_id': lineup_team['id'],
|
|
'player_id': player_id,
|
|
'card_id': card_id,
|
|
'position': new_pos,
|
|
'batting_order': order_number,
|
|
'after_play': curr_play.play_num - 1
|
|
}
|
|
|
|
make_sub(this_lineup)
|
|
await ctx.send(content=None, embed=await self.get_game_state_embed(this_game))
|
|
|
|
@commands.hybrid_command(name='gamestate', help='Post the current game state', aliases=['gs'])
|
|
@commands.has_any_role(SBA_PLAYERS_ROLE_NAME, PD_PLAYERS_ROLE_NAME)
|
|
async def game_state_command(self, ctx: commands.Context, include_lineups: bool = True):
|
|
this_game = get_one_game(channel_id=ctx.channel.id, active=True)
|
|
if not this_game:
|
|
await ctx.send(f'I dont\'t see an active game in this channel!')
|
|
return
|
|
|
|
await ctx.send(content=None, embed=await self.get_game_state_embed(this_game, full_length=include_lineups))
|
|
|
|
async def checks_log_play(self, ctx: commands.Context) -> (Optional[StratGame], Optional[dict], Optional[StratPlay]):
|
|
this_game = get_one_game(channel_id=ctx.channel.id, active=True)
|
|
# if not this_game:
|
|
# return False, False, False
|
|
|
|
owner_team = await get_game_team(this_game, ctx.author.id)
|
|
if not owner_team['id'] in [this_game.away_team_id, this_game.home_team_id]:
|
|
await ctx.send('Bruh. Only GMs of the active teams can log plays.')
|
|
# return this_game, False, False
|
|
|
|
this_play = get_current_play(this_game.id)
|
|
if this_play.locked:
|
|
await ctx.send(f'Looks like this play is already being advanced. Please wait to log the next play.')
|
|
if not this_play.pitcher:
|
|
await ctx.send(f'Please sub in a pitcher before logging a new play.')
|
|
this_play = None
|
|
|
|
return this_game, owner_team, this_play
|
|
|
|
@commands.hybrid_group(name='log-onbase', help='Log a base hit in this channel\'s game')
|
|
@commands.has_any_role(SBA_PLAYERS_ROLE_NAME, PD_PLAYERS_ROLE_NAME)
|
|
async def log_onbase(self, ctx: commands.Context):
|
|
if ctx.invoked_subcommand is None:
|
|
await ctx.send('No play details listed. Type `/log-onbase` to see available commands.')
|
|
|
|
@log_onbase.command(name='single-wellhit', help='Batter to first; runners advance two bases',
|
|
aliases=['siwh', 'si**', '1b**', '1bwh'])
|
|
async def log_single_wh_command(self, ctx: commands.Context):
|
|
this_game, owner_team, this_play = await self.checks_log_play(ctx)
|
|
if False in (this_game, owner_team, this_play):
|
|
return
|
|
|
|
single_wellhit(this_play)
|
|
|
|
await ctx.send(content=None, embed=await self.get_game_state_embed(this_game, full_length=False))
|
|
|
|
@log_onbase.command(name='single-onestar', help='Batter to first; runners advance one base', aliases=['si*', '1b*'])
|
|
async def log_single_command(self, ctx: commands.Context):
|
|
this_game, owner_team, this_play = await self.checks_log_play(ctx)
|
|
if False in (this_game, owner_team, this_play):
|
|
return
|
|
|
|
single_onestar(this_play)
|
|
|
|
await ctx.send(content=None, embed=await self.get_game_state_embed(this_game, full_length=False))
|
|
|
|
@log_onbase.command(name='ballpark-single', help='Batter to first; runners advance one base',
|
|
aliases=['bpsi', 'bp1b'])
|
|
async def log_ballpark_single_command(self, ctx: commands.Context):
|
|
this_game, owner_team, this_play = await self.checks_log_play(ctx)
|
|
if False in (this_game, owner_team, this_play):
|
|
return
|
|
|
|
patch_play(this_play.id, locked=True)
|
|
advance_runners(this_play.id, num_bases=1)
|
|
patch_play(this_play.id, pa=1, ab=1, hit=1, bp1b=1)
|
|
complete_play(this_play.id, batter_to_base=1)
|
|
|
|
await ctx.send(content=None, embed=await self.get_game_state_embed(this_game, full_length=False))
|
|
|
|
@log_onbase.command(name='single-uncapped', help='Batter to first; runners may attempt to advance a second base',
|
|
aliases=['si', '1b'])
|
|
async def log_single_uncapped_command(self, ctx: commands.Context):
|
|
this_game, owner_team, this_play = await self.checks_log_play(ctx)
|
|
if False in (this_game, owner_team, this_play):
|
|
return
|
|
|
|
patch_play(this_play.id, locked=True, pa=1, ab=1, hit=1)
|
|
advance_runners(this_play.id, 1)
|
|
this_play = get_current_play(this_game.id)
|
|
batter_to_base = 1
|
|
|
|
logging.info(f'this_play: {this_play}')
|
|
# Handle runner starting at second
|
|
if this_play.on_second:
|
|
this_runner = await get_player(this_game, this_play.on_second)
|
|
view = Confirm(responders=[ctx.author], timeout=60)
|
|
question = await ctx.send(f'Was {this_runner["name"]} sent home?', view=view)
|
|
await view.wait()
|
|
|
|
if view.value:
|
|
await question.delete()
|
|
view_two = Confirm(responders=[ctx.author], timeout=60)
|
|
question = await ctx.send(content=f'Was {this_runner["name"]} safe at the plate?', view=view_two)
|
|
await view_two.wait()
|
|
|
|
if view_two.value:
|
|
advance_one_runner(this_play.id, from_base=2, num_bases=2)
|
|
this_play = patch_play(this_play.id, rbi=this_play.rbi + 1)
|
|
else:
|
|
this_play = patch_play(this_play.id, on_second_final=99, outs=this_play.outs + 1)
|
|
|
|
await question.delete()
|
|
else:
|
|
await question.delete()
|
|
|
|
logging.info(f'this_play: {this_play}')
|
|
# Handle runner starting at first
|
|
if this_play.on_first and (not this_play.on_second or this_play.on_second_final != 3):
|
|
this_runner = await get_player(this_game, this_play.on_first)
|
|
view = Confirm(responders=[ctx.author], timeout=60)
|
|
question = await ctx.send(f'Was {this_runner["name"]} sent to third?', view=view)
|
|
await view.wait()
|
|
|
|
if view.value:
|
|
await question.delete()
|
|
view_two = Confirm(responders=[ctx.author], timeout=60)
|
|
question = await ctx.send(content=f'Was {this_runner["name"]} safe at third?', view=view_two)
|
|
await view_two.wait()
|
|
|
|
if view_two.value:
|
|
advance_one_runner(this_play.id, from_base=1, num_bases=2)
|
|
this_play = get_current_play(this_game.id)
|
|
else:
|
|
this_play = patch_play(this_play.id, on_second_final=99, outs=1)
|
|
|
|
await question.delete()
|
|
else:
|
|
await question.delete()
|
|
|
|
logging.info(f'this_play: {this_play}')
|
|
# Handle batter runner if either runner from first or runner from second advanced
|
|
if (this_play.on_first and this_play.on_first_final != 2) or \
|
|
(this_play.on_second and this_play.on_second_final != 3):
|
|
batter = await get_player(this_game, this_play.batter)
|
|
view = Confirm(responders=[ctx.author], timeout=60)
|
|
question = await ctx.send(content=f'Was {batter["name"]} sent to second?', view=view)
|
|
await view.wait()
|
|
|
|
if view.value:
|
|
await question.delete()
|
|
view_two = Confirm(responders=[ctx.author], timeout=60)
|
|
question = await ctx.send(content=f'Was {batter["name"]} safe at second?', view=view_two)
|
|
await view_two.wait()
|
|
|
|
if view_two.value:
|
|
batter_to_base = 2
|
|
|
|
await question.delete()
|
|
else:
|
|
await question.delete()
|
|
|
|
logging.info(f'this_play: {this_play}')
|
|
complete_play(this_play.id, batter_to_base=batter_to_base)
|
|
await ctx.send(content=None, embed=await self.get_game_state_embed(this_game, full_length=False))
|
|
|
|
@log_onbase.command(name='double-twostar', help='Batter to second; runners advance two bases',
|
|
aliases=['do**', '2b**'])
|
|
async def log_double_command(self, ctx: commands.Context):
|
|
this_game, owner_team, this_play = await self.checks_log_play(ctx)
|
|
if False in (this_game, owner_team, this_play):
|
|
return
|
|
|
|
double_twostar(this_play)
|
|
|
|
await ctx.send(content=None, embed=await self.get_game_state_embed(this_game, full_length=False))
|
|
|
|
@log_onbase.command(name='double-uncapped', help='Batter to second; runners may attempt to advance a third base',
|
|
aliases=['do', '2b'])
|
|
async def log_double_uncapped_command(self, ctx: commands.Context):
|
|
this_game, owner_team, this_play = await self.checks_log_play(ctx)
|
|
if False in (this_game, owner_team, this_play):
|
|
return
|
|
|
|
patch_play(this_play.id, locked=True, pa=1, ab=1, hit=1, double=1)
|
|
|
|
batter_to_base = 2
|
|
if this_play.on_first:
|
|
this_runner = await get_player(this_game, this_play.on_first)
|
|
view = Confirm(responders=[ctx.author], timeout=60)
|
|
question = await ctx.send(f'Was {this_runner["name"]} sent home?', view=view)
|
|
await view.wait()
|
|
|
|
if view.value:
|
|
await question.delete()
|
|
view_two = Confirm(responders=[ctx.author], timeout=60)
|
|
question = await ctx.send(content=f'Was {this_runner["name"]} safe at the plate?', view=view_two)
|
|
await view_two.wait()
|
|
|
|
if view_two.value:
|
|
advance_runners(this_play.id, num_bases=3)
|
|
else:
|
|
patch_play(this_play.id, on_first_final=99, outs=1)
|
|
|
|
await question.delete()
|
|
batter = await get_player(this_game, this_play.batter)
|
|
view_three = Confirm(responders=[ctx.author], timeout=60)
|
|
question = await ctx.send(
|
|
content=f'Did {batter["name"]} attempt the advance to third?', view=view_three
|
|
)
|
|
await view_three.wait()
|
|
|
|
if view_three.value:
|
|
await question.delete()
|
|
view_four = Confirm(responders=[ctx.author], timeout=60)
|
|
question = await ctx.send(content=f'Was {batter["name"]} safe at third?', view=view_four)
|
|
await view_four.wait()
|
|
|
|
if view_four.value:
|
|
batter_to_base = 3
|
|
await question.delete()
|
|
else:
|
|
advance_runners(this_play.id, num_bases=2)
|
|
await question.delete()
|
|
|
|
complete_play(this_play.id, batter_to_base=batter_to_base)
|
|
await ctx.send(content=None, embed=await self.get_game_state_embed(this_game, full_length=False))
|
|
|
|
@log_onbase.command(name='double-threestar', help='Batter to second; runners advance three bases',
|
|
aliases=['dowh', 'do***'])
|
|
async def log_double_wh_command(self, ctx: commands.Context):
|
|
this_game, owner_team, this_play = await self.checks_log_play(ctx)
|
|
if False in (this_game, owner_team, this_play):
|
|
return
|
|
|
|
double_threestar(this_play)
|
|
|
|
await ctx.send(content=None, embed=await self.get_game_state_embed(this_game, full_length=False))
|
|
|
|
@log_onbase.command(name='triple', help='Batter to third; all runners score', aliases=['tr', '3b'])
|
|
async def log_triple_command(self, ctx: commands.Context):
|
|
this_game, owner_team, this_play = await self.checks_log_play(ctx)
|
|
if False in (this_game, owner_team, this_play):
|
|
return
|
|
|
|
triple(this_play)
|
|
|
|
await ctx.send(content=None, embed=await self.get_game_state_embed(this_game, full_length=False))
|
|
|
|
@log_onbase.command(name='homerun', help='Batter scores; all runners score', aliases=['hr', 'dong'])
|
|
async def log_homerun_command(self, ctx: commands.Context):
|
|
this_game, owner_team, this_play = await self.checks_log_play(ctx)
|
|
if False in (this_game, owner_team, this_play):
|
|
return
|
|
|
|
patch_play(this_play.id, locked=True)
|
|
advance_runners(this_play.id, num_bases=4)
|
|
patch_play(this_play.id, pa=1, ab=1, hit=1, homerun=1)
|
|
complete_play(this_play.id)
|
|
|
|
await ctx.send(content=None, embed=await self.get_game_state_embed(this_game, full_length=False))
|
|
|
|
@log_onbase.command(name='ballpark-homerun', help='Batter scores; all runners score', aliases=['bp-hr', 'bp-dong'])
|
|
async def log_homerun_command(self, ctx: commands.Context):
|
|
this_game, owner_team, this_play = await self.checks_log_play(ctx)
|
|
if False in (this_game, owner_team, this_play):
|
|
return
|
|
|
|
patch_play(this_play.id, locked=True)
|
|
advance_runners(this_play.id, num_bases=3)
|
|
patch_play(this_play.id, pa=1, ab=1, hit=1, homerun=1, bphr=1)
|
|
complete_play(this_play.id)
|
|
|
|
await ctx.send(content=None, embed=await self.get_game_state_embed(this_game, full_length=False))
|
|
|
|
@log_onbase.command(name='walk', help='Batter to first; runners advance if forced', aliases=['bb'])
|
|
async def log_walk_command(self, ctx: commands.Context):
|
|
this_game, owner_team, this_play = await self.checks_log_play(ctx)
|
|
if False in (this_game, owner_team, this_play):
|
|
return
|
|
|
|
patch_play(this_play.id, locked=True)
|
|
advance_runners(this_play.id, num_bases=1, only_forced=True)
|
|
patch_play(this_play.id, pa=1, walk=1)
|
|
complete_play(this_play.id, batter_to_base=1)
|
|
|
|
await ctx.send(content=None, embed=await self.get_game_state_embed(this_game, full_length=False))
|
|
|
|
@log_onbase.command(name='intentional-walk', help='Batter to first; runners advance if forced', aliases=['ibb'])
|
|
async def log_int_walk_command(self, ctx: commands.Context):
|
|
this_game, owner_team, this_play = await self.checks_log_play(ctx)
|
|
if False in (this_game, owner_team, this_play):
|
|
return
|
|
|
|
patch_play(this_play.id, locked=True)
|
|
advance_runners(this_play.id, num_bases=1, only_forced=True)
|
|
patch_play(this_play.id, pa=1, ibb=1)
|
|
complete_play(this_play.id, batter_to_base=1)
|
|
|
|
await ctx.send(content=None, embed=await self.get_game_state_embed(this_game, full_length=False))
|
|
|
|
@log_onbase.command(name='hit-by-pitch', help='Batter to first; runners advance if forced', aliases=['hbp'])
|
|
async def log_hit_by_pitch_command(self, ctx: commands.Context):
|
|
this_game, owner_team, this_play = await self.checks_log_play(ctx)
|
|
if False in (this_game, owner_team, this_play):
|
|
return
|
|
|
|
patch_play(this_play.id, locked=True)
|
|
advance_runners(this_play.id, num_bases=1, only_forced=True)
|
|
patch_play(this_play.id, pa=1, hbp=1)
|
|
complete_play(this_play.id, batter_to_base=1)
|
|
|
|
await ctx.send(content=None, embed=await self.get_game_state_embed(this_game, full_length=False))
|
|
|
|
@commands.hybrid_group(name='log-out', help='Log an out result in this channel\'s game')
|
|
@commands.has_any_role(SBA_PLAYERS_ROLE_NAME, PD_PLAYERS_ROLE_NAME)
|
|
async def log_out(self, ctx: commands.Context):
|
|
if ctx.invoked_subcommand is None:
|
|
await ctx.send('No play details listed. Type `/log-out` to see available commands.')
|
|
|
|
@log_out.command(name='popout', help='Batter out; runners hold', aliases=['po'])
|
|
async def log_popout_command(self, ctx: commands.Context):
|
|
this_game, owner_team, this_play = await self.checks_log_play(ctx)
|
|
if False in (this_game, owner_team, this_play):
|
|
return
|
|
|
|
patch_play(this_play.id, locked=True, pa=1, ab=1, outs=1)
|
|
advance_runners(this_play.id, num_bases=0)
|
|
complete_play(this_play.id)
|
|
await ctx.send(content=None, embed=await self.get_game_state_embed(this_game, full_length=False))
|
|
|
|
@log_out.command(name='strikeout', help='Batter out; runners hold', aliases=['so', 'k'])
|
|
async def log_strikeout_command(self, ctx: commands.Context):
|
|
this_game, owner_team, this_play = await self.checks_log_play(ctx)
|
|
if False in (this_game, owner_team, this_play):
|
|
return
|
|
|
|
patch_play(this_play.id, locked=True, pa=1, ab=1, outs=1, so=1)
|
|
advance_runners(this_play.id, num_bases=0)
|
|
complete_play(this_play.id)
|
|
await ctx.send(content=None, embed=await self.get_game_state_embed(this_game, full_length=False))
|
|
|
|
@log_out.command(name='lineout', help='Batter out; runners hold', aliases=['lo'])
|
|
async def log_lineout_command(self, ctx: commands.Context):
|
|
this_game, owner_team, this_play = await self.checks_log_play(ctx)
|
|
if False in (this_game, owner_team, this_play):
|
|
return
|
|
|
|
patch_play(this_play.id, locked=True, pa=1, ab=1, outs=1)
|
|
advance_runners(this_play.id, num_bases=0)
|
|
complete_play(this_play.id)
|
|
await ctx.send(content=None, embed=await self.get_game_state_embed(this_game, full_length=False))
|
|
|
|
@log_out.command(name='sac-bunt', help='Batter out; runners advance one base', aliases=['sacb', 'bunt'])
|
|
async def log_sac_bunt_command(self, ctx: commands.Context):
|
|
this_game, owner_team, this_play = await self.checks_log_play(ctx)
|
|
if False in (this_game, owner_team, this_play):
|
|
return
|
|
|
|
patch_play(this_play.id, locked=True)
|
|
advance_runners(this_play.id, num_bases=1)
|
|
patch_play(this_play.id, pa=1, sac=1, outs=1)
|
|
complete_play(this_play.id)
|
|
|
|
await ctx.send(content=None, embed=await self.get_game_state_embed(this_game, full_length=False))
|
|
|
|
@log_out.command(name='caught-stealing', help='One base runner is caught stealing', aliases=['cs'])
|
|
@app_commands.describe(
|
|
attempted_base='The base number the runner attempted to steal; 2 for 2nd, 3 for 3rd, 3 for home')
|
|
async def log_caught_stealing_command(self, ctx: commands.Context, attempted_base: int):
|
|
this_game, owner_team, this_play = await self.checks_log_play(ctx)
|
|
if False in (this_game, owner_team, this_play):
|
|
return
|
|
|
|
patch_play(this_play.id, locked=True)
|
|
catcher = get_one_lineup(
|
|
this_game.id, team_id=this_play.pitcher.team_id, position='C'
|
|
)
|
|
|
|
if attempted_base == 4 and this_play.on_third:
|
|
patch_play(
|
|
this_play.id, cs=1, on_third_final=99, runner_id=this_play.on_third.id,
|
|
catcher_id=catcher.id, outs=1
|
|
)
|
|
elif attempted_base == 3 and this_play.on_second:
|
|
if not this_play.on_third:
|
|
patch_play(
|
|
this_play.id, cs=1, on_second_final=99, runner_id=this_play.on_second.id,
|
|
catcher_id=catcher.id, outs=1
|
|
)
|
|
else:
|
|
this_runner = await get_player(this_game, this_play.on_second)
|
|
await ctx.send(f'Ope. Looks like {this_runner["name"]} is blocked by the runner at third.')
|
|
return
|
|
elif attempted_base == 2 and this_play.on_first:
|
|
if not this_play.on_second:
|
|
patch_play(
|
|
this_play.id, cs=1, on_first_final=99, runner_id=this_play.on_first.id,
|
|
catcher_id=catcher.id, outs=1
|
|
)
|
|
else:
|
|
this_runner = await get_player(this_game, this_play.on_first)
|
|
await ctx.send(f'Ope. Looks like {this_runner["name"]} is blocked by the runner at second.')
|
|
return
|
|
else:
|
|
await ctx.send(f'Uh oh - I don\'t see a runner there to steal the bag.')
|
|
return
|
|
|
|
complete_play(this_play.id)
|
|
await ctx.send(content=None, embed=await self.get_game_state_embed(this_game, full_length=False))
|
|
|
|
@log_out.command(name='flyball-a', help='Batter out; all runners advance', aliases=['flya'])
|
|
async def log_flyballa_command(self, ctx: commands.Context):
|
|
this_game, owner_team, this_play = await self.checks_log_play(ctx)
|
|
if False in (this_game, owner_team, this_play):
|
|
return
|
|
|
|
patch_play(this_play.id, locked=True, pa=1, ab=1, outs=1)
|
|
if this_play.starting_outs < 2:
|
|
advance_runners(this_play.id, 1)
|
|
if this_play.on_third:
|
|
patch_play(this_play.id, ab=0)
|
|
|
|
complete_play(this_play.id)
|
|
await ctx.send(content=None, embed=await self.get_game_state_embed(this_game, full_length=False))
|
|
|
|
@log_out.command(name='flyball-b', help='Batter out; runner on third scores', aliases=['flyb'])
|
|
async def log_flyballb_command(self, ctx: commands.Context):
|
|
this_game, owner_team, this_play = await self.checks_log_play(ctx)
|
|
if False in (this_game, owner_team, this_play):
|
|
return
|
|
|
|
patch_play(this_play.id, locked=True, pa=1, ab=1, outs=1)
|
|
advance_runners(this_play.id, num_bases=0)
|
|
if this_play.starting_outs < 2 and this_play.on_third:
|
|
patch_play(this_play.id, ab=0, rbi=1)
|
|
advance_one_runner(this_play.id, from_base=3, num_bases=1)
|
|
|
|
if this_play.starting_outs < 2 and this_play.on_second:
|
|
view = Confirm(responders=[ctx.author], timeout=60)
|
|
question = await ctx.send('Did the runner on second advance?', view=view)
|
|
await view.wait()
|
|
|
|
if view.value:
|
|
advance_one_runner(this_play.id, from_base=2, num_bases=1)
|
|
await question.edit(view=None)
|
|
else:
|
|
await question.delete()
|
|
|
|
complete_play(this_play.id)
|
|
await ctx.send(content=None, embed=await self.get_game_state_embed(this_game, full_length=False))
|
|
|
|
@log_out.command(name='flyball-bq', help='Batter out; runner on third may attempt to score', aliases=['flyb?'])
|
|
async def log_flyballbq_command(self, ctx: commands.Context):
|
|
this_game, owner_team, this_play = await self.checks_log_play(ctx)
|
|
if False in (this_game, owner_team, this_play):
|
|
return
|
|
|
|
patch_play(this_play.id, locked=True, pa=1, ab=1, outs=1)
|
|
advance_runners(this_play.id, num_bases=0)
|
|
if this_play.starting_outs < 2 and this_play.on_third:
|
|
view = Confirm(responders=[ctx.author], timeout=60)
|
|
question = await ctx.send('Did the runner on third advance?', view=view)
|
|
await view.wait()
|
|
|
|
if view.value:
|
|
advance_one_runner(this_play.id, from_base=3, num_bases=1)
|
|
patch_play(this_play.id, ab=0, rbi=1)
|
|
await question.edit(view=None)
|
|
else:
|
|
await question.delete()
|
|
|
|
complete_play(this_play.id)
|
|
await ctx.send(content=None, embed=await self.get_game_state_embed(this_game, full_length=False))
|
|
|
|
@log_out.command(name='flyball-c', help='Batter out; no runners advance', aliases=['flyc'])
|
|
async def log_flyballc_command(self, ctx: commands.Context):
|
|
this_game, owner_team, this_play = await self.checks_log_play(ctx)
|
|
if False in (this_game, owner_team, this_play):
|
|
return
|
|
|
|
patch_play(this_play.id, locked=True, pa=1, ab=1, outs=1)
|
|
advance_runners(this_play.id, num_bases=0)
|
|
complete_play(this_play.id)
|
|
await ctx.send(content=None, embed=await self.get_game_state_embed(this_game, full_length=False))
|
|
|
|
@commands.hybrid_group(name='log-play', help='Log a result in this channel\'s game')
|
|
@commands.has_any_role(SBA_PLAYERS_ROLE_NAME, PD_PLAYERS_ROLE_NAME)
|
|
async def log_play(self, ctx: commands.Context):
|
|
if ctx.invoked_subcommand is None:
|
|
await ctx.send('No play details listed. Type `/log` to see available commands.')
|
|
|
|
@log_play.command(name='undo-play', help='Remove the most recent play from the log', aliases=['undo', 'rollback'])
|
|
async def log_undo_play_command(self, ctx: commands.Context):
|
|
this_game, owner_team, this_play = await self.checks_log_play(ctx)
|
|
if False in (this_game, owner_team, this_play):
|
|
return
|
|
|
|
undo_play(this_play.id)
|
|
undo_play(get_current_play(this_game.id).id)
|
|
complete_play(get_current_play(this_game.id).id, batter_to_base=get_latest_play(this_game.id).batter_final)
|
|
await ctx.send(content=None, embed=await self.get_game_state_embed(this_game, full_length=False))
|
|
|
|
@log_play.command(name='stolen-base', help='One base runner steals a base', aliases=['sb'])
|
|
@app_commands.describe(stolen_base='The base number stolen by the runner; 2 for 2nd, 3 for 3rd, 4 for home')
|
|
async def log_stolen_base_command(self, ctx: commands.Context, stolen_base: int):
|
|
this_game, owner_team, this_play = await self.checks_log_play(ctx)
|
|
if False in (this_game, owner_team, this_play):
|
|
return
|
|
|
|
patch_play(this_play.id, locked=True)
|
|
catcher = get_one_lineup(
|
|
this_game.id, team_id=this_play.pitcher.team_id, position='C'
|
|
)
|
|
|
|
if stolen_base == 4 and this_play.on_third:
|
|
patch_play(
|
|
this_play.id, sb=1, on_third_final=4, runner_id=this_play.on_third.id, catcher_id=catcher.id
|
|
)
|
|
elif stolen_base == 3 and this_play.on_second:
|
|
if not this_play.on_third:
|
|
patch_play(
|
|
this_play.id, sb=1, on_second_final=3, runner_id=this_play.on_second.id, catcher_id=catcher.id
|
|
)
|
|
else:
|
|
this_runner = await get_player(this_game, this_play.on_second)
|
|
await ctx.send(f'Ope. Looks like {this_runner["name"]} is blocked by the runner at third.')
|
|
patch_play(this_play.id, locked=False)
|
|
return
|
|
elif stolen_base == 2 and this_play.on_first:
|
|
if not this_play.on_second:
|
|
patch_play(
|
|
this_play.id, sb=1, on_first_final=2, runner_id=this_play.on_first.id, catcher_id=catcher.id
|
|
)
|
|
else:
|
|
this_runner = await get_player(this_game, this_play.on_first)
|
|
await ctx.send(f'Ope. Looks like {this_runner["name"]} is blocked by the runner at second.')
|
|
patch_play(this_play.id, locked=False)
|
|
return
|
|
else:
|
|
await ctx.send(f'Uh oh - I don\'t see a runner there to steal the bag.')
|
|
patch_play(this_play.id, locked=False)
|
|
return
|
|
|
|
complete_play(this_play.id)
|
|
await ctx.send(content=None, embed=await self.get_game_state_embed(this_game, full_length=False))
|
|
|
|
@log_play.command(name='wild-pitch', help='All runners advance one base', aliases=['wp'])
|
|
async def log_wild_pitch_command(self, ctx: commands.Context):
|
|
this_game, owner_team, this_play = await self.checks_log_play(ctx)
|
|
if False in (this_game, owner_team, this_play):
|
|
return
|
|
|
|
advance_runners(this_play.id, 1)
|
|
patch_play(this_play.id, rbi=0, wp=1)
|
|
complete_play(this_play.id)
|
|
|
|
@log_play.command(name='passed-ball', help='All runners advance one base', aliases=['pb'])
|
|
async def log_passed_ball_command(self, ctx: commands.Context):
|
|
this_game, owner_team, this_play = await self.checks_log_play(ctx)
|
|
if False in (this_game, owner_team, this_play):
|
|
return
|
|
|
|
advance_runners(this_play.id, 1)
|
|
patch_play(this_play.id, rbi=0, pb=1)
|
|
complete_play(this_play.id)
|
|
|
|
@log_play.command(name='balk', help='All runners advance one base', aliases=['bk'])
|
|
async def log_balk_command(self, ctx: commands.Context):
|
|
this_game, owner_team, this_play = await self.checks_log_play(ctx)
|
|
if False in (this_game, owner_team, this_play):
|
|
return
|
|
|
|
advance_runners(this_play.id, 1)
|
|
patch_play(this_play.id, rbi=0, balk=1)
|
|
complete_play(this_play.id)
|
|
|
|
@log_play.command(name='pickoff', help='One baserunner is out on the basepaths', aliases=['pick'])
|
|
async def log_pickoff_command(self, ctx: commands.Context, from_base: int):
|
|
this_game, owner_team, this_play = await self.checks_log_play(ctx)
|
|
if False in (this_game, owner_team, this_play):
|
|
return
|
|
|
|
patch_play(this_play.id, locked=True)
|
|
|
|
if from_base == 3 and this_play.on_third:
|
|
patch_play(this_play.id, on_third_final=99, runner_id=this_play.on_third.id, outs=1)
|
|
elif from_base == 2 and this_play.on_second:
|
|
patch_play(this_play.id, on_second_final=99, runner_id=this_play.on_second.id, outs=1)
|
|
elif from_base == 1 and this_play.on_first:
|
|
patch_play(this_play.id, on_first_final=99, runner_id=this_play.on_first.id, outs=1)
|
|
else:
|
|
await ctx.send(f'Uh oh - I don\'t see a runner there to be picked off.')
|
|
patch_play(this_play.id, locked=False)
|
|
return
|
|
|
|
complete_play(this_play.id)
|
|
await ctx.send(content=None, embed=await self.get_game_state_embed(this_game, full_length=False))
|
|
|
|
@commands.hybrid_group(name='show-card', help='Display an active player\'s card')
|
|
@commands.has_any_role(SBA_PLAYERS_ROLE_NAME, PD_PLAYERS_ROLE_NAME)
|
|
async def show_player(self, ctx: commands.Context):
|
|
if ctx.invoked_subcommand is None:
|
|
await ctx.send('No player details listed. Type `/show-player` to see available commands.')
|
|
|
|
@show_player.command(name='defense', help='Display a defender\'s player card', aliases=['pick'])
|
|
async def show_defense_command(
|
|
self, ctx: commands.Context, position: Literal[
|
|
'Catcher', 'First Base', 'Second Base', 'Third Base', 'Shortstop', 'Left Field', 'Center Field',
|
|
'Right Field']):
|
|
this_game, owner_team, this_play = await self.checks_log_play(ctx)
|
|
if False in (this_game, owner_team, this_play):
|
|
return
|
|
|
|
defender = await get_player(
|
|
game=this_game,
|
|
lineup_member=get_one_lineup(
|
|
this_game.id, team_id=this_play.pitcher.team_id, position=get_pos_abbrev(position)
|
|
)
|
|
)
|
|
|
|
embed = get_team_embed(f'{defender["team"]["sname"]} {position}', defender['team'])
|
|
embed.description = f'{defender["name"]}'
|
|
embed.set_image(url=defender['image'])
|
|
if this_game.is_pd:
|
|
embed.set_footer(text=f'PD Season {PD_SEASON}', icon_url=LOGO)
|
|
|
|
await ctx.send(content=None, embed=embed)
|
|
|
|
@log_out.command(name='groundball-a', help='Potential double play ground ball', aliases=['gba'])
|
|
async def log_groundballa_command(self, ctx: commands.Context):
|
|
this_game, owner_team, this_play = await self.checks_log_play(ctx)
|
|
if False in (this_game, owner_team, this_play):
|
|
return
|
|
|
|
batter_to_base = None
|
|
patch_play(this_play.id, locked=True)
|
|
if this_play.starting_outs == 2 or this_play.on_base_code == 0:
|
|
patch_play(this_play.id, pa=1, ab=1, outs=1)
|
|
else:
|
|
if this_play.on_base_code == 1:
|
|
runner = await get_player(this_game, this_play.on_first)
|
|
view = Confirm(responders=[ctx.author], timeout=60)
|
|
question = await ctx.send(f'Is {runner["name"]} out at second on the double play?', view=view)
|
|
await view.wait()
|
|
|
|
if view.value:
|
|
await question.delete()
|
|
patch_play(this_play.id, on_first_final=False, pa=1, ab=1, outs=2)
|
|
else:
|
|
await question.delete()
|
|
await ctx.send(f'Okay so it wasn\'t a gb A then? Go ahead and log a new play.')
|
|
patch_play(this_play.id, locked=False)
|
|
return
|
|
|
|
elif this_play.on_base_code == 7:
|
|
runner = await get_player(this_game, this_play.on_third)
|
|
view = Confirm(responders=[ctx.author], timeout=60)
|
|
question = await ctx.send(f'Is {runner["name"]} out on the home-to-first double play?', view=view)
|
|
await view.wait()
|
|
|
|
if view.value:
|
|
await question.delete()
|
|
advance_runners(this_play.id, 1)
|
|
patch_play(this_play.id, on_third_final=False, pa=1, ab=1, outs=2, rbi=0)
|
|
else:
|
|
await question.delete()
|
|
runner = await get_player(this_game, this_play.on_second)
|
|
view = Confirm(responders=[ctx.author], timeout=60)
|
|
question = await ctx.send(f'Is {runner["name"]} out at second on the double play?', view=view)
|
|
await view.wait()
|
|
|
|
if view.value():
|
|
await question.delete()
|
|
advance_runners(this_play.id, 1)
|
|
patch_play(this_play.id, on_first_final=False, pa=1, ab=1, outs=2, rbi=0)
|
|
else:
|
|
await question.delete()
|
|
await ctx.send(f'Okay so it wasn\'t a gb A then? Go ahead and log a new play.')
|
|
patch_play(this_play.id, locked=False)
|
|
return
|
|
|
|
else:
|
|
num_outs = 1
|
|
bases = ['third', 'second', 'first']
|
|
|
|
for count, x in enumerate([this_play.on_third, this_play.on_second, this_play.on_first]):
|
|
if x:
|
|
runner = await get_player(this_game, x)
|
|
view = Confirm(responders=[ctx.author], timeout=60)
|
|
question = await ctx.send(
|
|
f'Did {runner["name"]} advance from {bases[count]} on the play?', view=view
|
|
)
|
|
await view.wait()
|
|
|
|
num_bases = 0
|
|
if view.value:
|
|
await question.delete()
|
|
advance_one_runner(this_play.id, from_base=3 - count, num_bases=1)
|
|
else:
|
|
await question.delete()
|
|
view = Confirm(responders=[ctx.author], timeout=60)
|
|
question = await ctx.send(f'Was {runner["name"]} doubled off?', view=view)
|
|
await view.wait()
|
|
|
|
if view.value:
|
|
await question.delete()
|
|
if count == 0:
|
|
patch_play(this_play.id, on_third_final=False)
|
|
elif count == 1:
|
|
patch_play(this_play.id, on_second_final=False)
|
|
else:
|
|
patch_play(this_play.id, on_first_final=False)
|
|
num_outs += 1
|
|
else:
|
|
await question.delete()
|
|
if count == 0:
|
|
patch_play(this_play.id, on_third_final=3)
|
|
elif count == 1:
|
|
patch_play(this_play.id, on_second_final=2)
|
|
else:
|
|
patch_play(this_play.id, on_first_final=1)
|
|
|
|
if this_play.on_third:
|
|
batter = await get_player(this_game, this_play.batter)
|
|
view = Confirm(responders=[ctx.author], timeout=60)
|
|
question = await ctx.send(
|
|
f'Is {batter["name"]} out at first?', view=view
|
|
)
|
|
await view.wait()
|
|
|
|
if view.value:
|
|
await question.delete()
|
|
else:
|
|
await question.delete()
|
|
num_outs -= 1
|
|
batter_to_base = 1
|
|
|
|
patch_play(this_play.id, pa=1, ab=1, outs=num_outs)
|
|
|
|
complete_play(this_play.id, batter_to_base=batter_to_base)
|
|
await ctx.send(content=None, embed=await self.get_game_state_embed(this_game, full_length=False))
|
|
|
|
@log_play.command(name='xcheck', help='Defender makes an x-check')
|
|
async def log_xcheck_command(self, ctx: commands.Context, position: Literal[
|
|
'Catcher', 'First Base', 'Second Base', 'Third Base', 'Shortstop', 'Left Field', 'Center Field',
|
|
'Right Field'], hit_allowed: Literal['out', 'single*', 'single**', 'double**', 'double***', 'triple'],
|
|
error_allowed: Literal['out', '1 base', '2 bases', '3 bases']):
|
|
this_game, owner_team, this_play = await self.checks_log_play(ctx)
|
|
if False in (this_game, owner_team, this_play):
|
|
return
|
|
|
|
pos = get_pos_abbrev(position)
|
|
defender = get_one_lineup(
|
|
this_game.id, team_id=this_play.pitcher.team_id, position=pos
|
|
)
|
|
logging.info(f'defender: {defender}')
|
|
patch_play(this_play.id, defender_id=defender.id, error=1 if error_allowed != 'out' else 0, check_pos=pos)
|
|
|
|
# Not hit and no error
|
|
if hit_allowed == 'out' and error_allowed == 'out':
|
|
await ctx.send(f'Just logged the x-check! Please log the resulting play to continue (e.g. \'flyball-b\' or '
|
|
f'\'groundball-a\')')
|
|
return
|
|
|
|
# Hit and error
|
|
if hit_allowed != 'out' and error_allowed != 'out':
|
|
batter_to_base = 1
|
|
if hit_allowed == 'triple':
|
|
triple(this_play, comp_play=False)
|
|
elif 'double' in hit_allowed:
|
|
double_threestar(this_play, comp_play=False)
|
|
if error_allowed == '1 base':
|
|
batter_to_base = 3
|
|
elif error_allowed == '3 bases':
|
|
batter_to_base = 4
|
|
# 2 base error is the only one handled differently between doubles
|
|
elif hit_allowed == 'double***':
|
|
batter_to_base = 4
|
|
else:
|
|
batter_to_base = 3
|
|
# Both singles are handled the same
|
|
else:
|
|
single_wellhit(this_play, comp_play=False)
|
|
if error_allowed == '1 base':
|
|
batter_to_base = 2
|
|
else:
|
|
batter_to_base = 3
|
|
|
|
complete_play(this_play.id, batter_to_base=batter_to_base)
|
|
|
|
# Either hit or error
|
|
num_bases = None
|
|
if error_allowed == 'out':
|
|
if hit_allowed == 'single*':
|
|
single_onestar(this_play)
|
|
elif hit_allowed == 'single**':
|
|
single_wellhit(this_play)
|
|
elif hit_allowed == 'double**':
|
|
double_twostar(this_play)
|
|
elif hit_allowed == 'double***':
|
|
double_threestar(this_play)
|
|
elif hit_allowed == 'triple':
|
|
triple(this_play)
|
|
else:
|
|
if error_allowed == '1 base':
|
|
num_bases = 1
|
|
elif error_allowed == '2 bases':
|
|
num_bases = 2
|
|
elif error_allowed == '3 bases':
|
|
num_bases = 3
|
|
|
|
advance_runners(this_play.id, num_bases=num_bases, is_error=True)
|
|
complete_play(this_play.id, batter_to_base=num_bases)
|
|
|
|
await ctx.send(content=None, embed=await self.get_game_state_embed(this_game, full_length=False))
|
|
|
|
# TODO: ground balls
|
|
|
|
|
|
async def setup(bot):
|
|
await bot.add_cog(Gameplay(bot))
|
|
|