Added range embeds to uncapped hits

Update gbA with runner on 3rd
This commit is contained in:
Cal Corum 2024-12-26 07:04:00 -06:00
parent c3c88af14a
commit fa109442c2

View File

@ -1,5 +1,6 @@
import asyncio
import copy
import logging
import discord
from discord import SelectOption
@ -10,7 +11,7 @@ from sqlalchemy import delete
from typing import Literal
from api_calls import db_delete, db_get, db_post
from dice import d_twenty_roll, frame_plate_check, sa_fielding_roll
from dice import DTwentyRoll, d_twenty_roll, frame_plate_check, sa_fielding_roll
from exceptions import *
from helpers import DEFENSE_LITERAL, SBA_COLOR, get_channel
from in_game.game_helpers import legal_check
@ -35,6 +36,13 @@ AT_BASE = {
3: 'at third',
4: 'at home'
}
RANGE_CHECKS = {
1: 3,
2: 7,
3: 11,
4: 15,
5: 19
}
async def get_scorebug_embed(session: Session, this_game: Game, full_length: bool = True, classic: bool = True) -> discord.Embed:
@ -1303,17 +1311,247 @@ async def check_uncapped_advance(session: Session, interaction: discord.Interact
this_game = this_play.game
outfielder = await show_outfield_cards(session, interaction, this_play)
logger.info(f'throw from {outfielder.player.name_with_desc}')
this_roll = d_twenty_roll(this_play.batter.team, this_play.game)
block_roll = d_twenty_roll(this_play.catcher.team, this_play.game)
def_team = this_play.pitcher.team
runner_bc = get_batter_card(this_lineup=lead_runner)
of_rating = await get_position(session, this_card=outfielder.card, position=outfielder.position)
defense_embed = def_team.embed
defense_embed.description = f'{outfielder.player.name}\'s Throw'
trail_bc = get_batter_card(this_lineup=trail_runner)
logger.info(f'trail runner batting card: {trail_bc}')
c_rating = await get_position(session, this_play.catcher.card, position='C')
runner_embed = this_play.batter.team.embed
runner_embed.add_field(name=f'{outfielder.position} Arm', value=f'{"+" if of_rating.arm > 0 else ""}{of_rating.arm}')
safe_range = None
def_alignment = this_play.managerai.defense_alignment(session, this_play.game)
lead_bc = get_batter_card(this_lineup=lead_runner)
logger.info(f'lead runner batting card: {lead_bc}')
lead_safe_range = lead_bc.running + of_rating.arm
logger.info(f'lead_safe_range: {lead_safe_range}')
# Build lead runner embed
lead_runner_embed = copy.deepcopy(runner_embed)
lead_runner_embed.title = f'{lead_runner.player.name} To {"Home" if lead_base == 4 else "Third"}'
lead_runner_embed.description = f'{outfielder.team.abbrev} {outfielder.position} {outfielder.player.name}\'s Throw'
lead_runner_embed.add_field(name=f'Runner Speed', value=lead_runner.card.batterscouting.battingcard.running)
if this_play.starting_outs == 2:
logger.info(f'Adding 2 for 2 outs')
lead_safe_range += 2
lead_runner_embed.add_field(name='2-Out Mod', value=f'+2')
if lead_base == 3 and outfielder.position != 'CF':
of_mod = -2 if outfielder.position == 'LF' else 2
logger.info(f'{outfielder.position} to 3B mod: {of_mod}')
lead_safe_range += of_mod
lead_runner_embed.add_field(name=f'{outfielder.position} Mod', value=f'{"+" if of_mod > 0 else ""}{of_mod}')
logger.info(f'lead_runner_embed: {lead_runner_embed}')
# Build trail runner embed
trail_runner_embed = copy.deepcopy(runner_embed)
trail_bc = get_batter_card(this_lineup=trail_runner)
trail_runner_embed.title = f'{trail_runner.player.name} To {"Third" if trail_base == 3 else "Second"}'
trail_runner_embed.description = f'{outfielder.team.abbrev} {outfielder.position} {outfielder.player.name}\'s Throw'
trail_runner_embed.add_field(name=f'Runner Speed', value=trail_bc.running)
logger.info(f'trail runner batting card: {trail_bc}')
trail_safe_range = trail_bc.running - 5 + of_rating.arm
logger.info(f'trail_safe_range: {trail_safe_range}')
if trail_base == 3 and outfielder.position != 'CF':
of_mod = 2 if outfielder.position == 'LF' else -2
logger.info(f'{outfielder.position} to 3B mod: {of_mod}')
trail_safe_range += of_mod
trail_runner_embed.add_field(name=f'{outfielder.position} Mod', value=f'{"+" if of_mod > 0 else ""}{of_mod}', inline=False)
trail_runner_embed.add_field(name='Trail Runner', value='-5')
def at_home_strings(safe_range: int):
safe_string = f'1{" - " if safe_range > 1 else ""}'
if safe_range > 1:
if safe_range <= 20:
safe_string += f'{safe_range - 1}'
else:
safe_string += f'20'
if safe_range == 20:
out_string = 'None'
catcher_string = '20'
elif safe_range > 20:
out_string = 'None'
catcher_string = 'None'
elif safe_range == 19:
out_string = 'None'
catcher_string = '19 - 20'
elif safe_range == 18:
out_string = f'20'
catcher_string = '18 - 19'
else:
out_string = f'{safe_range + 2} - 20'
catcher_string = f'{safe_range} - {safe_range + 1}'
logger.info(f'safe: {safe_string} / catcher: {catcher_string} / out: {out_string}')
return {'safe': safe_string, 'catcher': catcher_string, 'out': out_string}
def at_third_strings(safe_range: int):
safe_string = f'1{" - " if safe_range > 1 else ""}'
if safe_range > 1:
if safe_range <= 20:
safe_string += f'{safe_range}'
else:
safe_string += f'20'
if safe_range > 19:
out_string = '20'
else:
out_string = f'{safe_range + 1} - 20'
logger.info(f'safe: {safe_string} / out: {out_string}')
return {'safe': safe_string, 'out': out_string}
async def out_at_home(safe_range: int):
if this_roll.d_twenty in [safe_range, safe_range + 1]:
logger.info(f'Roll of {this_roll.d_twenty} is a catcher check with safe range of {safe_range}')
is_block_plate = await ask_confirm(
interaction,
question=f'Looks like **{this_play.catcher.player.name}** has a chance to block the plate! Is that correct?',
label_type='yes',
delete_question=False
)
if is_block_plate:
logger.info(f'Looks like a block the plate check')
await interaction.channel.send(content=None, embeds=block_roll.embeds)
if block_roll.d_twenty > RANGE_CHECKS[c_rating]:
logger.info(f'Roll of {this_roll.d_twenty} is OUT {AT_BASE[4]}')
runner_thrown_out = True
q_text = f'Looks like **{lead_runner.player.name}** is OUT {AT_BASE[4]}!'
else:
logger.info(f'Roll of {this_roll.d_twenty} is SAFE {AT_BASE[4]}')
runner_thrown_out = False
q_text = f'Looks like **{lead_runner.player.name}** is SAFE {AT_BASE[4]}!'
else:
runner_thrown_out = await ask_confirm(
interaction=interaction,
question=f'Was **{lead_runner.player.name}** thrown out {AT_BASE[4]}?',
label_type='yes',
)
else:
logger.info(f'Roll of {this_roll.d_twenty} has a clear result with safe range of {safe_range}')
if this_roll.d_twenty > safe_range:
logger.info(f'Roll of {this_roll.d_twenty} is OUT {AT_BASE[4]}')
runner_thrown_out = True
q_text = f'Looks like **{lead_runner.player.name}** is OUT {AT_BASE[4]}!'
else:
logger.info(f'Roll of {this_roll.d_twenty} is SAFE {AT_BASE[4]}')
runner_thrown_out = False
q_text = f'Looks like **{lead_runner.player.name}** is SAFE {AT_BASE[4]}!'
is_correct = await ask_confirm(
interaction,
question=f'{q_text} Is that correct?',
label_type='yes',
delete_question=False
)
if not is_correct:
logger.warning(f'{interaction.user.name} says call is incorrect; runner is {"not " if runner_thrown_out else ""}thrown out')
runner_thrown_out = not runner_thrown_out
return runner_thrown_out
async def out_at_base(safe_range: int, this_runner: Lineup, this_base: int):
if this_roll.d_twenty > safe_range:
logger.info(f'Roll of {this_roll.d_twenty} is OUT {AT_BASE[this_base]}')
runner_thrown_out = True
q_text = f'Looks like **{this_runner.player.name}** is OUT {AT_BASE[this_base]}!'
else:
logger.info(f'Roll of {this_roll.d_twenty} is SAFE {AT_BASE[this_base]}')
runner_thrown_out = False
q_text = f'Looks like **{this_runner.player.name}** is SAFE {AT_BASE[this_base]}!'
is_correct = await ask_confirm(
interaction,
question=f'{q_text} Is that correct?',
label_type='yes',
delete_question=False
)
if not is_correct:
logger.warning(f'{interaction.user.name} says call is incorrect; runner is {"not " if runner_thrown_out else ""}thrown out')
runner_thrown_out = not runner_thrown_out
return runner_thrown_out
# Either there is no AI team or the AI is pitching
if not this_game.ai_team or not this_play.ai_is_batting:
# Build lead runner embed
# Check for lead runner hold
if (lead_runner == this_play.on_second and def_alignment.hold_second) or (lead_runner == this_play.on_first and def_alignment.hold_first):
lead_safe_range -= 1
logger.info(f'Lead runner was held, -1 to safe range: {lead_safe_range}')
lead_runner_embed.add_field(name='Runner Held', value='-1')
else:
logger.info(f'Lead runner was not held, +1 to safe range: {lead_safe_range}')
lead_safe_range += 1
lead_runner_embed.add_field(name='Runner Not Held', value='+1')
lead_runner_embed.add_field(name='', value='', inline=False)
if lead_base == 4:
logger.info(f'lead base is 4, building strings')
lead_strings = at_home_strings(lead_safe_range)
lead_runner_embed.add_field(name='Safe Range', value=lead_strings['safe'])
lead_runner_embed.add_field(name='Catcher Check', value=lead_strings['catcher'])
lead_runner_embed.add_field(name='Out Range', value=lead_strings['out'])
else:
logger.info(f'lead base is 3, building strings')
lead_strings = at_third_strings(lead_safe_range)
lead_runner_embed.add_field(name='Safe Range', value=lead_strings['safe'])
lead_runner_embed.add_field(name='Out Range', value=lead_strings['out'])
# Build trail runner embed
if (trail_runner == this_play.on_first and def_alignment.hold_first):
trail_safe_range -= 1
logger.info(f'Trail runner was held, -1 to safe range: {trail_safe_range}')
trail_runner_embed.add_field(name='Runner Held', value='-1')
elif (trail_runner == this_play.on_first and not def_alignment.hold_first):
trail_safe_range += 1
logger.info(f'Trail runner was not held, +1 to safe range: {trail_safe_range}')
trail_runner_embed.add_field(name='Runner Not Held', value='+1')
else:
logger.info('Trail runner was not from first base, no hold modifier')
trail_runner_embed.add_field(name='', value='', inline=False)
logger.info(f'Building strings for trail runner')
safe_string = f'1{" - " if trail_safe_range > 1 else ""}'
if trail_safe_range > 1:
if trail_safe_range < 20:
safe_string += f'{trail_safe_range}'
else:
logger.info(f'capping safe range at 19')
trail_safe_range = 19
safe_string += f'19'
out_string = f'{trail_safe_range + 1} - 20'
logger.info(f'safe: {safe_string} / out: {out_string}')
trail_runner_embed.add_field(name='Safe Range', value=safe_string)
trail_runner_embed.add_field(name='Out Range', value=out_string)
await interaction.channel.send(embeds=[lead_runner_embed, trail_runner_embed])
is_lead_running = await ask_confirm(
interaction=interaction,
question=f'Is **{lead_runner.player.name}** being sent {TO_BASE[lead_base]}?',
@ -1322,7 +1560,6 @@ async def check_uncapped_advance(session: Session, interaction: discord.Interact
if is_lead_running:
throw_resp = None
def_alignment = this_play.managerai.defense_alignment(session, this_play.game)
if this_game.ai_team:
throw_resp = this_play.managerai.throw_at_uncapped(session, this_game)
@ -1341,7 +1578,7 @@ async def check_uncapped_advance(session: Session, interaction: discord.Interact
return this_play
else:
await interaction.channel.send(content=f'{outfielder.player.name} is throwing {TO_BASE[lead_base]}!')
await interaction.channel.send(content=f'**{outfielder.player.name}** is throwing {TO_BASE[lead_base]}!')
else:
throw_for_lead = await ask_confirm(
@ -1358,7 +1595,7 @@ async def check_uncapped_advance(session: Session, interaction: discord.Interact
this_play.on_second_final = 4
log_run_scored(session, lead_runner, this_play)
return this_play
# Human runner is advancing, defense is throwing
trail_advancing = await ask_confirm(
interaction=interaction,
@ -1366,24 +1603,13 @@ async def check_uncapped_advance(session: Session, interaction: discord.Interact
label_type='yes'
)
lead_bc = get_batter_card(this_lineup=lead_runner)
logger.info(f'lead runner batting card: {lead_bc}')
lead_safe_range = lead_bc.running + of_rating.arm + 1
if lead_runner == this_play.on_second:
lead_safe_range -= 2 if def_alignment.hold_second else 0
elif lead_runner == this_play.on_first:
lead_safe_range -= 2 if def_alignment.hold_first else 0
logger.info(f'lead_safe_range: {lead_safe_range}')
# Trail runner is advancing
if trail_advancing:
trail_safe = trail_bc.running - 5 + of_rating.arm
logger.info(f'trail_safe: {trail_safe}')
throw_lead = False
if this_game.ai_team:
if throw_resp.at_trail_runner and trail_safe <= throw_resp.trail_max_safe and trail_safe <= throw_resp.trail_max_safe_delta - lead_safe_range:
if throw_resp.at_trail_runner and trail_safe_range <= throw_resp.trail_max_safe and trail_safe_range <= throw_resp.trail_max_safe_delta - lead_safe_range:
logger.info(f'defense throwing at trail runner {AT_BASE[trail_base]}')
await interaction.channel.send(f'**{outfielder.player.name}** will throw {TO_BASE[trail_base]}!')
throw_lead = False
@ -1404,10 +1630,12 @@ async def check_uncapped_advance(session: Session, interaction: discord.Interact
# Throw is going to lead runner
if throw_lead:
logger.info(f'Throw is going to lead base')
try:
await question.delete()
except (discord.NotFound, UnboundLocalError):
pass
if this_play.on_first == trail_runner:
this_play.on_first_final += 1
elif this_play.batter == trail_runner:
@ -1422,16 +1650,12 @@ async def check_uncapped_advance(session: Session, interaction: discord.Interact
except (discord.NotFound, UnboundLocalError):
pass
runner_thrown_out = await ask_confirm(
interaction=interaction,
question=f'**{trail_runner.player.name}**\'s safe range is 1 -> {trail_safe} - were they thrown out {AT_BASE[trail_base]}?',
label_type='yes',
custom_confirm_label=f'Out {AT_BASE[trail_base]}',
custom_cancel_label=f'Safe {AT_BASE[trail_base]}'
)
await interaction.channel.send(content=None, embeds=this_roll.embeds)
runner_thrown_out = await out_at_base(trail_safe_range, trail_runner, trail_base)
# Trail runner is thrown out
if runner_thrown_out:
logger.info(f'logging one one additional out for trail runner')
# Log out on play
this_play.outs += 1
@ -1442,7 +1666,9 @@ async def check_uncapped_advance(session: Session, interaction: discord.Interact
this_play.batter_final = None
# Advance lead runner extra base
logger.info(f'advancing lead runner')
if this_play.on_second == lead_runner:
logger.info(f'run scored from second')
this_play.rbi += 1
this_play.on_second_final = 4
log_run_scored(session, lead_runner, this_play)
@ -1450,19 +1676,15 @@ async def check_uncapped_advance(session: Session, interaction: discord.Interact
elif this_play.on_first == lead_runner:
this_play.on_first_final += 1
if this_play.on_first_final > 3:
logger.info(f'run scored from first')
this_play.rbi += 1
log_run_scored(session, lead_runner, this_play)
return this_play
# Ball is going to lead base, ask if safe
runner_thrown_out = await ask_confirm(
interaction=interaction,
question=f'**{lead_runner.player.name}**\'s safe range is 1 -> {lead_safe_range} - were they thrown out {AT_BASE[lead_base]}?',
label_type='yes',
custom_confirm_label=f'Out {AT_BASE[lead_base]}',
custom_cancel_label=f'Safe {AT_BASE[lead_base]}'
)
await interaction.channel.send(content=None, embeds=this_roll.embeds)
runner_thrown_out = await out_at_home(lead_safe_range) if lead_base == 4 else await out_at_base(lead_safe_range, lead_runner, lead_base)
# Lead runner is thrown out
if runner_thrown_out:
@ -1489,28 +1711,60 @@ async def check_uncapped_advance(session: Session, interaction: discord.Interact
elif this_play.ai_is_batting:
run_resp = this_play.managerai.uncapped_advance(session, this_game, lead_base, trail_base)
runner_held = await ask_confirm(
lead_runner_held = await ask_confirm(
interaction=interaction,
question=f'Was **{lead_runner.player.name}** held before the pitch?',
question=f'Was **{lead_runner.player.name}** held at {"second" if lead_runner == this_play.on_second else "first"} before the pitch?',
label_type='yes'
)
safe_range = runner_bc.running + of_rating.arm - 1
if runner_held:
safe_range -= 1
if lead_runner_held:
lead_safe_range -= 1
lead_runner_embed.add_field(name='Runner Held', value='-1')
logger.info(f'runner was held, -1 to lead safe range: {lead_safe_range}')
else:
safe_range += 1
if this_play.starting_outs == 2:
safe_range += 2
lead_safe_range += 1
lead_runner_embed.add_field(name='Runner Not Held', value='+1')
logger.info(f'runner was not held, +1 to lead safe range: {lead_safe_range}')
if lead_base == 3:
if outfielder.position == 'RF':
safe_range += 2
elif outfielder.position == 'LF':
safe_range -= 2
if safe_range > run_resp.min_safe:
if lead_safe_range > run_resp.min_safe:
logger.info(f'AI is not advancing with lead runner')
return this_play
logger.info(f'Building embeds')
lead_runner_embed.add_field(name='', value='', inline=False)
if lead_base == 4:
logger.info(f'lead base is 4, building strings')
lead_strings = at_home_strings(lead_safe_range)
lead_runner_embed.add_field(name='Safe Range', value=lead_strings['safe'])
lead_runner_embed.add_field(name='Catcher Check', value=lead_strings['catcher'])
lead_runner_embed.add_field(name='Out Range', value=lead_strings['out'])
else:
logger.info(f'lead base is 3, building strings')
lead_strings = at_third_strings(lead_safe_range)
lead_runner_embed.add_field(name='Safe Range', value=lead_strings['safe'])
lead_runner_embed.add_field(name='Out Range', value=lead_strings['out'])
if trail_runner == this_play.on_first:
trail_runner_held = await ask_confirm(
interaction=interaction,
question=f'Was **{trail_runner.player.name}** held at first before the pitch?',
label_type='yes'
)
logger.info(f'Trail runner held: {trail_runner_held}')
if trail_runner_held:
trail_runner_embed.add_field(name='Runner Held', value=f'-1')
trail_safe_range -= 1
logger.info(f'Trail runner held, -1 to safe range: {trail_safe_range}')
else:
trail_runner_embed.add_field(name='Runner Not Held', value='+1')
trail_safe_range += 1
logger.info(f'Trail runner not held, +1 to safe range: {trail_safe_range}')
await interaction.channel.send(embeds=[lead_runner_embed, trail_runner_embed])
is_defense_throwing = await ask_confirm(
interaction=interaction,
@ -1533,7 +1787,7 @@ async def check_uncapped_advance(session: Session, interaction: discord.Interact
# Human throw is not being cut off
if run_resp.send_trail:
await interaction.channel.send(
f'**{trail_runner.player.name}** is advancing {TO_BASE[trail_base]} as the trail runner with a safe range of 1->{trail_bc.running - 5 + of_rating.arm}!',
f'**{trail_runner.player.name}** is advancing {TO_BASE[trail_base]} as the trail runner!',
)
is_throwing_lead = await ask_confirm(
interaction=interaction,
@ -1554,23 +1808,22 @@ async def check_uncapped_advance(session: Session, interaction: discord.Interact
# Throw is going to trail runner
else:
is_trail_out = await ask_confirm(
interaction=interaction,
question=f'Was **{trail_runner.player.name}** thrown out {AT_BASE[trail_base]}?',
label_type='yes'
)
runner_thrown_out = await out_at_base(trail_safe_range, trail_runner, trail_base)
if is_trail_out:
if runner_thrown_out:
logger.info(f'Runner was thrown out')
# Log out on play
this_play.outs += 1
# Remove trail runner
logger.info(f'Remove trail runner')
if this_play.on_first == trail_runner:
this_play.on_first_final = None
else:
this_play.batter_final = None
# Advance lead runner extra base
logger.info(f'Advance lead runner extra base')
if this_play.on_second == lead_runner:
this_play.rbi += 1
this_play.on_second_final = 4
@ -1588,23 +1841,25 @@ async def check_uncapped_advance(session: Session, interaction: discord.Interact
await interaction.channel.send(content=f'**{trail_runner.player.name}** is NOT trailing to {TO_BASE[trail_base]}.')
# Ball is going to lead base, ask if safe
is_lead_out = await ask_confirm(
logger.info(f'Throw is going to lead base')
runner_thrown_out = await out_at_home(lead_safe_range) if lead_base == 4 else await out_at_base(lead_safe_range, trail_runner, trail_base)
runner_thrown_out = await ask_confirm(
interaction=interaction,
question=f'Was **{lead_runner.player.name}** thrown out {AT_BASE[lead_base]}?',
label_type='yes',
)
# Lead runner is thrown out
if is_lead_out:
if runner_thrown_out:
logger.info(f'Lead runner is thrown out.')
this_play.outs += 1
if this_play.on_second == lead_runner:
logger.info(f'setting lead runner on_second_final')
this_play.on_second_final = None if is_lead_out else lead_base
this_play.on_second_final = None if runner_thrown_out else lead_base
elif this_play.on_first == lead_runner:
logger.info(f'setting lead runner on_first')
this_play.on_first_final = None if is_lead_out else lead_base
this_play.on_first_final = None if runner_thrown_out else lead_base
else:
log_exception(LineupsMissingException, f'Could not find lead runner to set final destination')
@ -2393,8 +2648,6 @@ def undo_play(session: Session, this_play: Play):
logger.warning(f'Deleting lineup IDs: {new_player_ids}')
session.exec(delete(Lineup).where(Lineup.id.in_(new_player_ids)))
# TODO: check for runners that scored in previous play, find their last AB, and set run and e_run to 0
session.commit()
try:
@ -2901,6 +3154,7 @@ async def manual_end_game(session: Session, interaction: discord.Interaction, th
async def groundballs(session: Session, interaction: discord.Interaction, this_play: Play, groundball_letter: Literal['a', 'b', 'c']):
if this_play.on_base_code == 2 and groundball_letter in ['a', 'b']:
logger.info(f'Groundball {groundball_letter} with runner on second')
to_right_side = await ask_confirm(
interaction,
question=f'Was that ball hit to either 1B or 2B?',
@ -2909,12 +3163,38 @@ async def groundballs(session: Session, interaction: discord.Interaction, this_p
this_play = gb_result_6(session, this_play, to_right_side)
elif this_play.on_base_code in [3, 6] and groundball_letter in ['a', 'b']:
to_mif = await ask_confirm(
interaction,
question=f'Was that ball hit to either 2B or SS?',
label_type='yes'
)
this_play = gb_result_5(session, this_play, to_mif)
logger.info(f'Groundball {groundball_letter} with runner on third')
def_alignment = this_play.managerai.defense_alignment(session, this_play.game)
if this_play.game.ai_team is not None and this_play.pitcher.team.is_ai and def_alignment.infield_in:
logger.info(f'AI on defense, hit to MIF, playing in')
this_play = gb_result_7(session, this_play)
else:
logger.info(f'Checking if hit to MIF')
to_mif = await ask_confirm(
interaction,
question=f'Was that ball hit to either 2B or SS?',
label_type='yes'
)
if not to_mif:
logger.info(f'Not to a MIF, gb 7')
this_play = gb_result_7(session, this_play)
else:
logger.info(f'AI batting, hit to MIF')
mif_playing_in = await ask_confirm(
interaction,
question=f'Were they playing in?',
label_type='yes',
)
if mif_playing_in:
logger.info(f'playing in, gb 7')
this_play = gb_result_7(session, this_play)
else:
logger.info(f'playing back, gb 5')
this_play = gb_result_5(session, this_play, to_mif)
else:
this_play = await gb_letter(session, interaction, this_play, groundball_letter.upper(), 'None', False)