Added range embeds to uncapped hits
Update gbA with runner on 3rd
This commit is contained in:
parent
c3c88af14a
commit
fa109442c2
@ -1,5 +1,6 @@
|
|||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
|
import copy
|
||||||
import logging
|
import logging
|
||||||
import discord
|
import discord
|
||||||
from discord import SelectOption
|
from discord import SelectOption
|
||||||
@ -10,7 +11,7 @@ from sqlalchemy import delete
|
|||||||
from typing import Literal
|
from typing import Literal
|
||||||
|
|
||||||
from api_calls import db_delete, db_get, db_post
|
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 exceptions import *
|
||||||
from helpers import DEFENSE_LITERAL, SBA_COLOR, get_channel
|
from helpers import DEFENSE_LITERAL, SBA_COLOR, get_channel
|
||||||
from in_game.game_helpers import legal_check
|
from in_game.game_helpers import legal_check
|
||||||
@ -35,6 +36,13 @@ AT_BASE = {
|
|||||||
3: 'at third',
|
3: 'at third',
|
||||||
4: 'at home'
|
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:
|
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
|
this_game = this_play.game
|
||||||
outfielder = await show_outfield_cards(session, interaction, this_play)
|
outfielder = await show_outfield_cards(session, interaction, this_play)
|
||||||
logger.info(f'throw from {outfielder.player.name_with_desc}')
|
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
|
def_team = this_play.pitcher.team
|
||||||
runner_bc = get_batter_card(this_lineup=lead_runner)
|
runner_bc = get_batter_card(this_lineup=lead_runner)
|
||||||
of_rating = await get_position(session, this_card=outfielder.card, position=outfielder.position)
|
of_rating = await get_position(session, this_card=outfielder.card, position=outfielder.position)
|
||||||
defense_embed = def_team.embed
|
c_rating = await get_position(session, this_play.catcher.card, position='C')
|
||||||
defense_embed.description = f'{outfielder.player.name}\'s Throw'
|
runner_embed = this_play.batter.team.embed
|
||||||
trail_bc = get_batter_card(this_lineup=trail_runner)
|
runner_embed.add_field(name=f'{outfielder.position} Arm', value=f'{"+" if of_rating.arm > 0 else ""}{of_rating.arm}')
|
||||||
logger.info(f'trail runner batting card: {trail_bc}')
|
|
||||||
safe_range = None
|
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
|
# Either there is no AI team or the AI is pitching
|
||||||
if not this_game.ai_team or not this_play.ai_is_batting:
|
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(
|
is_lead_running = await ask_confirm(
|
||||||
interaction=interaction,
|
interaction=interaction,
|
||||||
question=f'Is **{lead_runner.player.name}** being sent {TO_BASE[lead_base]}?',
|
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:
|
if is_lead_running:
|
||||||
throw_resp = None
|
throw_resp = None
|
||||||
def_alignment = this_play.managerai.defense_alignment(session, this_play.game)
|
|
||||||
|
|
||||||
if this_game.ai_team:
|
if this_game.ai_team:
|
||||||
throw_resp = this_play.managerai.throw_at_uncapped(session, this_game)
|
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
|
return this_play
|
||||||
|
|
||||||
else:
|
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:
|
else:
|
||||||
throw_for_lead = await ask_confirm(
|
throw_for_lead = await ask_confirm(
|
||||||
@ -1366,24 +1603,13 @@ async def check_uncapped_advance(session: Session, interaction: discord.Interact
|
|||||||
label_type='yes'
|
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
|
# Trail runner is advancing
|
||||||
if trail_advancing:
|
if trail_advancing:
|
||||||
trail_safe = trail_bc.running - 5 + of_rating.arm
|
|
||||||
logger.info(f'trail_safe: {trail_safe}')
|
|
||||||
throw_lead = False
|
throw_lead = False
|
||||||
if this_game.ai_team:
|
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]}')
|
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]}!')
|
await interaction.channel.send(f'**{outfielder.player.name}** will throw {TO_BASE[trail_base]}!')
|
||||||
throw_lead = False
|
throw_lead = False
|
||||||
@ -1404,10 +1630,12 @@ async def check_uncapped_advance(session: Session, interaction: discord.Interact
|
|||||||
|
|
||||||
# Throw is going to lead runner
|
# Throw is going to lead runner
|
||||||
if throw_lead:
|
if throw_lead:
|
||||||
|
logger.info(f'Throw is going to lead base')
|
||||||
try:
|
try:
|
||||||
await question.delete()
|
await question.delete()
|
||||||
except (discord.NotFound, UnboundLocalError):
|
except (discord.NotFound, UnboundLocalError):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
if this_play.on_first == trail_runner:
|
if this_play.on_first == trail_runner:
|
||||||
this_play.on_first_final += 1
|
this_play.on_first_final += 1
|
||||||
elif this_play.batter == trail_runner:
|
elif this_play.batter == trail_runner:
|
||||||
@ -1422,16 +1650,12 @@ async def check_uncapped_advance(session: Session, interaction: discord.Interact
|
|||||||
except (discord.NotFound, UnboundLocalError):
|
except (discord.NotFound, UnboundLocalError):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
runner_thrown_out = await ask_confirm(
|
await interaction.channel.send(content=None, embeds=this_roll.embeds)
|
||||||
interaction=interaction,
|
runner_thrown_out = await out_at_base(trail_safe_range, trail_runner, trail_base)
|
||||||
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]}'
|
|
||||||
)
|
|
||||||
|
|
||||||
# Trail runner is thrown out
|
# Trail runner is thrown out
|
||||||
if runner_thrown_out:
|
if runner_thrown_out:
|
||||||
|
logger.info(f'logging one one additional out for trail runner')
|
||||||
# Log out on play
|
# Log out on play
|
||||||
this_play.outs += 1
|
this_play.outs += 1
|
||||||
|
|
||||||
@ -1442,7 +1666,9 @@ async def check_uncapped_advance(session: Session, interaction: discord.Interact
|
|||||||
this_play.batter_final = None
|
this_play.batter_final = None
|
||||||
|
|
||||||
# Advance lead runner extra base
|
# Advance lead runner extra base
|
||||||
|
logger.info(f'advancing lead runner')
|
||||||
if this_play.on_second == lead_runner:
|
if this_play.on_second == lead_runner:
|
||||||
|
logger.info(f'run scored from second')
|
||||||
this_play.rbi += 1
|
this_play.rbi += 1
|
||||||
this_play.on_second_final = 4
|
this_play.on_second_final = 4
|
||||||
log_run_scored(session, lead_runner, this_play)
|
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:
|
elif this_play.on_first == lead_runner:
|
||||||
this_play.on_first_final += 1
|
this_play.on_first_final += 1
|
||||||
if this_play.on_first_final > 3:
|
if this_play.on_first_final > 3:
|
||||||
|
logger.info(f'run scored from first')
|
||||||
this_play.rbi += 1
|
this_play.rbi += 1
|
||||||
log_run_scored(session, lead_runner, this_play)
|
log_run_scored(session, lead_runner, this_play)
|
||||||
|
|
||||||
return this_play
|
return this_play
|
||||||
|
|
||||||
# Ball is going to lead base, ask if safe
|
# Ball is going to lead base, ask if safe
|
||||||
runner_thrown_out = await ask_confirm(
|
await interaction.channel.send(content=None, embeds=this_roll.embeds)
|
||||||
interaction=interaction,
|
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)
|
||||||
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]}'
|
|
||||||
)
|
|
||||||
|
|
||||||
# Lead runner is thrown out
|
# Lead runner is thrown out
|
||||||
if runner_thrown_out:
|
if runner_thrown_out:
|
||||||
@ -1489,29 +1711,61 @@ async def check_uncapped_advance(session: Session, interaction: discord.Interact
|
|||||||
elif this_play.ai_is_batting:
|
elif this_play.ai_is_batting:
|
||||||
run_resp = this_play.managerai.uncapped_advance(session, this_game, lead_base, trail_base)
|
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,
|
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'
|
label_type='yes'
|
||||||
)
|
)
|
||||||
safe_range = runner_bc.running + of_rating.arm - 1
|
if lead_runner_held:
|
||||||
if runner_held:
|
lead_safe_range -= 1
|
||||||
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:
|
else:
|
||||||
safe_range += 1
|
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 this_play.starting_outs == 2:
|
if lead_safe_range > run_resp.min_safe:
|
||||||
safe_range += 2
|
logger.info(f'AI is not advancing with lead runner')
|
||||||
|
|
||||||
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:
|
|
||||||
return this_play
|
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(
|
is_defense_throwing = await ask_confirm(
|
||||||
interaction=interaction,
|
interaction=interaction,
|
||||||
question=f'{lead_runner.player.name} is advancing {TO_BASE[lead_base]} with a safe range of **1->{safe_range}**! Is the defense throwing?',
|
question=f'{lead_runner.player.name} is advancing {TO_BASE[lead_base]} with a safe range of **1->{safe_range}**! Is the defense throwing?',
|
||||||
@ -1533,7 +1787,7 @@ async def check_uncapped_advance(session: Session, interaction: discord.Interact
|
|||||||
# Human throw is not being cut off
|
# Human throw is not being cut off
|
||||||
if run_resp.send_trail:
|
if run_resp.send_trail:
|
||||||
await interaction.channel.send(
|
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(
|
is_throwing_lead = await ask_confirm(
|
||||||
interaction=interaction,
|
interaction=interaction,
|
||||||
@ -1554,23 +1808,22 @@ async def check_uncapped_advance(session: Session, interaction: discord.Interact
|
|||||||
|
|
||||||
# Throw is going to trail runner
|
# Throw is going to trail runner
|
||||||
else:
|
else:
|
||||||
is_trail_out = await ask_confirm(
|
runner_thrown_out = await out_at_base(trail_safe_range, trail_runner, trail_base)
|
||||||
interaction=interaction,
|
|
||||||
question=f'Was **{trail_runner.player.name}** thrown out {AT_BASE[trail_base]}?',
|
|
||||||
label_type='yes'
|
|
||||||
)
|
|
||||||
|
|
||||||
if is_trail_out:
|
if runner_thrown_out:
|
||||||
|
logger.info(f'Runner was thrown out')
|
||||||
# Log out on play
|
# Log out on play
|
||||||
this_play.outs += 1
|
this_play.outs += 1
|
||||||
|
|
||||||
# Remove trail runner
|
# Remove trail runner
|
||||||
|
logger.info(f'Remove trail runner')
|
||||||
if this_play.on_first == trail_runner:
|
if this_play.on_first == trail_runner:
|
||||||
this_play.on_first_final = None
|
this_play.on_first_final = None
|
||||||
else:
|
else:
|
||||||
this_play.batter_final = None
|
this_play.batter_final = None
|
||||||
|
|
||||||
# Advance lead runner extra base
|
# Advance lead runner extra base
|
||||||
|
logger.info(f'Advance lead runner extra base')
|
||||||
if this_play.on_second == lead_runner:
|
if this_play.on_second == lead_runner:
|
||||||
this_play.rbi += 1
|
this_play.rbi += 1
|
||||||
this_play.on_second_final = 4
|
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]}.')
|
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
|
# 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,
|
interaction=interaction,
|
||||||
question=f'Was **{lead_runner.player.name}** thrown out {AT_BASE[lead_base]}?',
|
question=f'Was **{lead_runner.player.name}** thrown out {AT_BASE[lead_base]}?',
|
||||||
label_type='yes',
|
label_type='yes',
|
||||||
)
|
)
|
||||||
|
|
||||||
# Lead runner is thrown out
|
# Lead runner is thrown out
|
||||||
if is_lead_out:
|
if runner_thrown_out:
|
||||||
logger.info(f'Lead runner is thrown out.')
|
logger.info(f'Lead runner is thrown out.')
|
||||||
this_play.outs += 1
|
this_play.outs += 1
|
||||||
|
|
||||||
if this_play.on_second == lead_runner:
|
if this_play.on_second == lead_runner:
|
||||||
logger.info(f'setting lead runner on_second_final')
|
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:
|
elif this_play.on_first == lead_runner:
|
||||||
logger.info(f'setting lead runner on_first')
|
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:
|
else:
|
||||||
log_exception(LineupsMissingException, f'Could not find lead runner to set final destination')
|
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}')
|
logger.warning(f'Deleting lineup IDs: {new_player_ids}')
|
||||||
session.exec(delete(Lineup).where(Lineup.id.in_(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()
|
session.commit()
|
||||||
|
|
||||||
try:
|
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']):
|
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']:
|
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(
|
to_right_side = await ask_confirm(
|
||||||
interaction,
|
interaction,
|
||||||
question=f'Was that ball hit to either 1B or 2B?',
|
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)
|
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']:
|
elif this_play.on_base_code in [3, 6] and groundball_letter in ['a', 'b']:
|
||||||
to_mif = await ask_confirm(
|
logger.info(f'Groundball {groundball_letter} with runner on third')
|
||||||
interaction,
|
def_alignment = this_play.managerai.defense_alignment(session, this_play.game)
|
||||||
question=f'Was that ball hit to either 2B or SS?',
|
|
||||||
label_type='yes'
|
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_5(session, this_play, to_mif)
|
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:
|
else:
|
||||||
this_play = await gb_letter(session, interaction, this_play, groundball_letter.upper(), 'None', False)
|
this_play = await gb_letter(session, interaction, this_play, groundball_letter.upper(), 'None', False)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user