Added baserunning ai notes
Added get_batter_card to gameplay_queries
This commit is contained in:
parent
c7b45aecf4
commit
7015fb3125
@ -438,6 +438,8 @@ class Gameplay(commands.Cog):
|
||||
content=f'Creating this game for {t_role.mention}:\n{this_game}'
|
||||
)
|
||||
|
||||
# TODO: add new-game exhibition, unlimited, and ranked
|
||||
|
||||
@commands.command(name='force-endgame', help='Mod: Force a game to end without stats')
|
||||
async def force_end_game_command(self, ctx: commands.Context):
|
||||
with Session(engine) as session:
|
||||
|
||||
@ -15,7 +15,7 @@ from exceptions import *
|
||||
from helpers import DEFENSE_LITERAL, SBA_COLOR, get_channel
|
||||
from in_game.game_helpers import legal_check
|
||||
from in_game.gameplay_models import BattingCard, Game, Lineup, PositionRating, RosterLink, Team, Play
|
||||
from in_game.gameplay_queries import get_available_batters, get_position, get_available_pitchers, get_card_or_none, get_channel_game_or_none, get_db_ready_decisions, get_db_ready_plays, get_game_lineups, get_last_team_play, get_one_lineup, get_player_id_from_dict, get_player_name_from_dict, get_player_or_none, get_sorted_lineups, get_team_or_none, get_players_last_pa, post_game_rewards
|
||||
from in_game.gameplay_queries import get_available_batters, get_batter_card, get_position, get_available_pitchers, get_card_or_none, get_channel_game_or_none, get_db_ready_decisions, get_db_ready_plays, get_game_lineups, get_last_team_play, get_one_lineup, get_player_id_from_dict, get_player_name_from_dict, get_player_or_none, get_sorted_lineups, get_team_or_none, get_players_last_pa, post_game_rewards
|
||||
from in_game.managerai_responses import DefenseResponse
|
||||
from utilities.buttons import ButtonOptions, Confirm, ask_confirm
|
||||
from utilities.dropdown import DropdownView, SelectBatterSub, SelectStartingPitcher, SelectViewDefense
|
||||
@ -151,7 +151,7 @@ async def get_scorebug_embed(session: Session, this_game: Game, full_length: boo
|
||||
good_jump = '2-11'
|
||||
else:
|
||||
good_jump = '2-12'
|
||||
steal_string = f'{"*" if batting_card.steal_auto else ""}{good_jump}/- ({batting_card.steal_high}-{batting_card.steal_low})'
|
||||
steal_string = f'{"`*`" if batting_card.steal_auto else ""}{good_jump}/- ({batting_card.steal_high}-{batting_card.steal_low})'
|
||||
return steal_string
|
||||
|
||||
baserunner_string = ''
|
||||
@ -201,8 +201,21 @@ async def get_scorebug_embed(session: Session, this_game: Game, full_length: boo
|
||||
cat_string = f'{curr_play.catcher.player.name_card_link('batter')}\nArm: {catcher_rating.arm}'
|
||||
embed.add_field(name='Catcher', value=cat_string)
|
||||
|
||||
ai_note = curr_play.ai_note
|
||||
logger.info(f'gameplay_models - Game.get_scorebug_embed - ai_note: {ai_note}')
|
||||
if curr_play.ai_is_batting and curr_play.on_base_code > 0:
|
||||
if curr_play.on_base_code in [2, 4]:
|
||||
to_base = 3
|
||||
elif curr_play.on_base_code in [1, 5]:
|
||||
to_base = 2
|
||||
else:
|
||||
to_base = 4
|
||||
|
||||
jump_resp = curr_play.managerai.check_jump(session, this_game, to_base=to_base)
|
||||
ai_note = jump_resp.ai_note
|
||||
else:
|
||||
def_align = curr_play.managerai.defense_alignment(session, this_game)
|
||||
ai_note = def_align.ai_note
|
||||
logger.info(f'gameplay_models - get_scorebug_embed - ai_note: {ai_note}')
|
||||
|
||||
if len(ai_note) > 0:
|
||||
gm_name = this_game.home_team.gmname if this_game.ai_team == 'home' else this_game.away_team.gmname
|
||||
embed.add_field(name=f'{gm_name} will...', value=ai_note, inline=False)
|
||||
@ -1276,6 +1289,13 @@ async def check_uncapped_advance(session: Session, interaction: discord.Interact
|
||||
outfielder = await show_outfield_cards(session, interaction, this_play)
|
||||
logger.info(f'throw from {outfielder.player.name_with_desc}')
|
||||
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}')
|
||||
safe_range = None
|
||||
|
||||
# Either there is no AI team or the AI is pitching
|
||||
if not this_game.ai_team or not this_play.ai_is_batting:
|
||||
@ -1287,6 +1307,8 @@ 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)
|
||||
logger.info(f'throw_resp: {throw_resp}')
|
||||
@ -1303,6 +1325,9 @@ async def check_uncapped_advance(session: Session, interaction: discord.Interact
|
||||
await asyncio.sleep(1)
|
||||
return this_play
|
||||
|
||||
else:
|
||||
await interaction.channel.send(content=f'{outfielder.player.name} is throwing {TO_BASE[lead_base]}!')
|
||||
|
||||
else:
|
||||
throw_for_lead = await ask_confirm(
|
||||
interaction=interaction,
|
||||
@ -1326,36 +1351,44 @@ 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:
|
||||
view = Confirm(responders=[interaction.user], timeout=60, label_type='yes')
|
||||
view.confirm.label = 'Home Plate' if lead_base == 4 else 'Third Base'
|
||||
view.cancel.label = 'Third Base' if trail_base == 3 else 'Second Base'
|
||||
|
||||
ai_throw_lead = False
|
||||
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:
|
||||
question = await interaction.channel.send(
|
||||
f'The {def_team.sname} will throw for the trail runner if both:\n- {trail_runner.player.name}\'s safe range is {throw_resp.trail_max_safe} or lower\n- {trail_runner.player.name}\'s safe range is lower than {lead_runner.player.name}\'s by at least {abs(throw_resp.trail_max_safe_delta)}.\n\nIs the throw going {TO_BASE[lead_base]} or {TO_BASE[trail_base]}?',
|
||||
view=view
|
||||
)
|
||||
|
||||
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:
|
||||
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
|
||||
else:
|
||||
logger.info(f'defense throwing at lead runner {AT_BASE[lead_base]}')
|
||||
await interaction.channel.send(f'**{outfielder.player.name}** will throw {TO_BASE[lead_base]}!')
|
||||
ai_throw_lead = True
|
||||
throw_lead = True
|
||||
|
||||
else:
|
||||
view = Confirm(responders=[interaction.user], timeout=60, label_type='yes')
|
||||
view.confirm.label = 'Home Plate' if lead_base == 4 else 'Third Base'
|
||||
view.cancel.label = 'Third Base' if trail_base == 3 else 'Second Base'
|
||||
question = await interaction.channel.send(
|
||||
f'Is the throw going {TO_BASE[lead_base]} or {TO_BASE[trail_base]}?',
|
||||
view=view
|
||||
)
|
||||
|
||||
if not ai_throw_lead:
|
||||
await view.wait()
|
||||
elif ai_throw_lead:
|
||||
view.value = True
|
||||
throw_lead = await view.wait()
|
||||
|
||||
# Throw is going to lead runner
|
||||
if view.value:
|
||||
if throw_lead:
|
||||
try:
|
||||
await question.delete()
|
||||
except (discord.NotFound, UnboundLocalError):
|
||||
@ -1376,8 +1409,10 @@ async def check_uncapped_advance(session: Session, interaction: discord.Interact
|
||||
|
||||
runner_thrown_out = await ask_confirm(
|
||||
interaction=interaction,
|
||||
question='Was **{trail_runner.player.name}** thrown out {AT_BASE[trail_base]}?',
|
||||
label_type='yes'
|
||||
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
|
||||
@ -1408,8 +1443,10 @@ async def check_uncapped_advance(session: Session, interaction: discord.Interact
|
||||
# Ball is going to lead base, ask if safe
|
||||
runner_thrown_out = await ask_confirm(
|
||||
interaction=interaction,
|
||||
question=f'Was **{lead_runner.player.name}** thrown out {AT_BASE[lead_base]}?',
|
||||
label_type='yes'
|
||||
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
|
||||
@ -1437,18 +1474,32 @@ 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)
|
||||
|
||||
is_lead_running = await ask_confirm(
|
||||
runner_held = await ask_confirm(
|
||||
interaction=interaction,
|
||||
question=f'**{lead_runner.player.name}** will advance {TO_BASE[lead_base]} if the safe range is {run_resp.min_safe} or higher.\n\nIs **{lead_runner.player.name}** attempting to advance?',
|
||||
question=f'Was **{lead_runner.player.name}** held before the pitch?',
|
||||
label_type='yes'
|
||||
)
|
||||
safe_range = runner_bc.running + of_rating.arm - 1
|
||||
if runner_held:
|
||||
safe_range -= 1
|
||||
else:
|
||||
safe_range += 1
|
||||
|
||||
if not is_lead_running:
|
||||
if this_play.starting_outs == 2:
|
||||
safe_range += 2
|
||||
|
||||
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
|
||||
|
||||
is_defense_throwing = await ask_confirm(
|
||||
interaction=interaction,
|
||||
question=f'Is the defense throwing {TO_BASE[lead_base]} for {lead_runner.player.name}?',
|
||||
question=f'{lead_runner.player.name} is advancing {TO_BASE[lead_base]} with a safe range of **1->{safe_range}**! Is the defense throwing?',
|
||||
label_type='yes'
|
||||
)
|
||||
|
||||
@ -1467,7 +1518,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!',
|
||||
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}!',
|
||||
)
|
||||
is_throwing_lead = await ask_confirm(
|
||||
interaction=interaction,
|
||||
@ -1518,6 +1569,9 @@ async def check_uncapped_advance(session: Session, interaction: discord.Interact
|
||||
|
||||
return this_play
|
||||
|
||||
else:
|
||||
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(
|
||||
interaction=interaction,
|
||||
@ -1776,7 +1830,7 @@ async def bunts(session: Session, interaction: discord.Interaction, this_play: P
|
||||
|
||||
lead_runner_out = await ask_confirm(
|
||||
interaction=interaction,
|
||||
question=f'{runner.player.name}\'s safe range is **1 -> {runner.card.batterscouting.battingcard.running - 4 + def_pos.range}**. Is the runner out {AT_BASE[lead_base]}?',
|
||||
question=f'{runner.player.name}\'s safe range is **1->{runner.card.batterscouting.battingcard.running - 4 + def_pos.range}**. Is the runner out {AT_BASE[lead_base]}?',
|
||||
custom_confirm_label=f'Out {AT_BASE[lead_base]}',
|
||||
custom_cancel_label=f'Safe {AT_BASE[lead_base]}'
|
||||
)
|
||||
@ -2981,7 +3035,8 @@ def gb_result_4(session: Session, this_play: Play):
|
||||
this_play = advance_runners(session, this_play, 1)
|
||||
|
||||
this_play.ab, this_play.outs = 1, 1
|
||||
this_play.on_first_final = 1
|
||||
this_play.on_first_final = None
|
||||
this_play.batter_final = 1
|
||||
|
||||
return this_play
|
||||
|
||||
@ -3071,7 +3126,7 @@ async def gb_decide(session: Session, this_play: Play, interaction: discord.Inte
|
||||
else:
|
||||
is_lead_running = await ask_confirm(
|
||||
interaction,
|
||||
f'Is {runner.card.player.name} attempting to advance {TO_BASE[advance_base]} with a 1-{safe_range} safe range?',
|
||||
f'Is **{runner.card.player.name}** attempting to advance {TO_BASE[advance_base]} with a **1-{safe_range}** safe range?',
|
||||
label_type='yes',
|
||||
delete_question=False
|
||||
)
|
||||
|
||||
@ -298,7 +298,8 @@ class ManagerAi(ManagerAiBase, table=True):
|
||||
|
||||
return True
|
||||
|
||||
def check_jump(self, session: Session, this_game: Game, to_base: Literal[2, 3, 4]) -> JumpResponse | None:
|
||||
def check_jump(self, session: Session, this_game: Game, to_base: Literal[2, 3, 4]) -> JumpResponse:
|
||||
logger.info(f'Checking jump to {to_base} in Game {this_game.id}')
|
||||
this_resp = JumpResponse()
|
||||
this_play = this_game.current_play_or_none(session)
|
||||
if this_play is None:
|
||||
@ -309,7 +310,16 @@ class ManagerAi(ManagerAiBase, table=True):
|
||||
if this_game.ai_team == 'home':
|
||||
run_diff = run_diff * -1
|
||||
|
||||
pitcher_hold = this_play.pitcher.card.pitcherscouting.pitchingcard.hold
|
||||
catcher_defense = session.exec(select(PositionRating).where(PositionRating.player_id == this_play.catcher.player_id, PositionRating.position == 'C', PositionRating.variant == this_play.catcher.card.variant)).one()
|
||||
catcher_hold = catcher_defense.arm
|
||||
battery_hold = pitcher_hold + catcher_hold
|
||||
|
||||
if to_base == 2:
|
||||
runner = this_play.on_first
|
||||
if runner is None:
|
||||
log_exception(CardNotFoundException, f'Attempted to check a jump to 2nd base, but no runner found on first.')
|
||||
|
||||
match self.steal:
|
||||
case 10:
|
||||
this_resp.min_safe = 12 + num_outs
|
||||
@ -322,14 +332,36 @@ class ManagerAi(ManagerAiBase, table=True):
|
||||
case self.steal if self.steal > 2 and num_outs < 2 and run_diff <= 5:
|
||||
this_resp.min_safe = 16 + num_outs
|
||||
case _:
|
||||
this_resp = 17 + num_outs
|
||||
this_resp.min_safe = 17 + num_outs
|
||||
|
||||
if self.steal > 7 and num_outs < 2 and run_diff <= 5:
|
||||
this_resp.run_if_auto_jump = True
|
||||
elif self.steal < 5:
|
||||
this_resp.must_auto_jump = True
|
||||
|
||||
runner_card = runner.card.batterscouting.battingcard
|
||||
if this_resp.run_if_auto_jump and runner_card.steal_auto:
|
||||
this_resp.ai_note = f'- WILL SEND **{runner.player.name}** to second!'
|
||||
|
||||
elif this_resp.must_auto_jump and not runner_card.steal_auto:
|
||||
this_resp.ai_note = f''
|
||||
|
||||
else:
|
||||
jump_safe_range = runner_card.steal_high + battery_hold
|
||||
nojump_safe_range = runner_card.steal_low + battery_hold
|
||||
logger.info(f'jump_safe_range: {jump_safe_range} / nojump_safe_range: {nojump_safe_range}')
|
||||
|
||||
if this_resp.min_safe <= nojump_safe_range:
|
||||
this_resp.ai_note = f'- SEND **{runner.player.name}** to second!'
|
||||
|
||||
elif this_resp.min_safe <= jump_safe_range:
|
||||
this_resp.ai_note = f'- SEND **{runner.player.name}** to second if they get the jump'
|
||||
|
||||
elif to_base == 3:
|
||||
runner = this_play.on_second
|
||||
if runner is None:
|
||||
log_exception(CardNotFoundException, f'Attempted to check a jump to 3rd base, but no runner found on second.')
|
||||
|
||||
match self.steal:
|
||||
case 10:
|
||||
this_resp.min_safe = 12 + num_outs
|
||||
@ -341,16 +373,41 @@ class ManagerAi(ManagerAiBase, table=True):
|
||||
if self.steal == 10 and num_outs < 2 and run_diff <= 5:
|
||||
this_resp.run_if_auto_jump = True
|
||||
elif self.steal <= 5:
|
||||
this_resp.must_auto_jump = True
|
||||
this_resp.must_auto_jump = True
|
||||
|
||||
runner_card = runner.card.batterscouting.battingcard
|
||||
if this_resp.run_if_auto_jump and runner_card.steal_auto:
|
||||
this_resp.ai_note = f'- SEND **{runner.player.name}** to third!'
|
||||
|
||||
elif this_resp.must_auto_jump and not runner_card.steal_auto:
|
||||
pass
|
||||
|
||||
else:
|
||||
jump_safe_range = runner_card.steal_low + battery_hold
|
||||
logger.info(f'jump_safe_range: {jump_safe_range}')
|
||||
|
||||
if this_resp.min_safe <= jump_safe_range:
|
||||
this_resp.ai_note = f'- SEND **{runner.player.name}** to third!'
|
||||
|
||||
elif run_diff in [-1, 0]:
|
||||
runner = this_play.on_third
|
||||
if runner is None:
|
||||
log_exception(CardNotFoundException, f'Attempted to check a jump to home, but no runner found on third.')
|
||||
|
||||
if self.steal == 10:
|
||||
this_resp.min_safe = 5
|
||||
elif self.steal > 5:
|
||||
this_resp.min_safe = 7
|
||||
elif this_play.inning_num > 7 and self.steal >= 5:
|
||||
this_resp.min_safe = 6
|
||||
this_resp.min_safe = 6
|
||||
elif self.steal > 5:
|
||||
this_resp.min_safe = 7
|
||||
|
||||
runner_card = runner.card.batterscouting.battingcard
|
||||
jump_safe_range = runner_card.steal_low - 9
|
||||
|
||||
if this_resp.min_safe <= jump_safe_range:
|
||||
this_resp.ai_note = f'- SEND **{runner.player.name}** to third!'
|
||||
|
||||
logger.info(f'Returning jump resp to game {this_game.id}: {this_resp}')
|
||||
return this_resp
|
||||
|
||||
def tag_from_second(self, session: Session, this_game: Game) -> TagResponse:
|
||||
@ -402,7 +459,6 @@ class ManagerAi(ManagerAiBase, table=True):
|
||||
|
||||
return this_resp
|
||||
|
||||
|
||||
def throw_at_uncapped(self, session: Session, this_game: Game) -> ThrowResponse:
|
||||
this_resp = ThrowResponse()
|
||||
this_play = this_game.current_play_or_none(session)
|
||||
@ -577,6 +633,63 @@ class ManagerAi(ManagerAiBase, table=True):
|
||||
|
||||
return this_resp
|
||||
|
||||
# @property
|
||||
# def ai_note(self) -> str: # TODO: test these three functions with specific OBCs
|
||||
# if self.inning_half == 'top':
|
||||
# if self.game.ai_team == 'away':
|
||||
# return self.batting_ai_note
|
||||
# else:
|
||||
# return self.pitching_ai_note
|
||||
# else:
|
||||
# if self.game.ai_team == 'away':
|
||||
# return self.pitching_ai_note
|
||||
# else:
|
||||
# return self.batting_ai_note
|
||||
|
||||
# @property
|
||||
# def batting_ai_note(self) -> str:
|
||||
# ai_note = '' # TODO: migrate Manager AI to their own local model
|
||||
|
||||
# return ai_note
|
||||
|
||||
# @property
|
||||
# def pitching_ai_note(self) -> str:
|
||||
# def_alignment = self.defense_alignment(session)
|
||||
# ai_note = ''
|
||||
# # Holding Baserunners
|
||||
# if self.starting_outs == 2 and self.on_base_code > 0:
|
||||
# if self.on_base_code == 1:
|
||||
# ai_note += f'- hold {self.on_first.player.name}\n'
|
||||
# elif self.on_base_code == 2:
|
||||
# ai_note += f'- hold {self.on_second.player.name}\n'
|
||||
# elif self.on_base_code in [4, 5, 7]:
|
||||
# ai_note += f'- hold {self.on_first.player.name} on first\n'
|
||||
# # elif self.on_base_code == 5:
|
||||
# # ai_note += f'- hold the runner on first\n'
|
||||
# elif self.on_base_code == 6:
|
||||
# ai_note += f'- hold {self.on_second.player.name} on 2nd\n'
|
||||
# elif self.on_base_code in [1, 5]:
|
||||
# runner = self.on_first.player
|
||||
# if self.on_first.card.batterscouting.battingcard.steal_auto:
|
||||
# ai_note += f'- hold {runner.name} on 1st\n'
|
||||
# elif self.on_base_code in [2, 4]:
|
||||
# if self.on_second.card.batterscouting.battingcard.steal_low + max(self.pitcher.card.pitcherscouting.pitchingcard.hold, 5) >= 14:
|
||||
# ai_note += f'- hold {self.on_second.player.name} on 2nd\n'
|
||||
|
||||
# # Defensive Alignment
|
||||
# if self.on_third and self.starting_outs < 2:
|
||||
# if self.could_walkoff:
|
||||
# ai_note += f'- play the outfield and infield in'
|
||||
# elif abs(self.away_score - self.home_score) <= 3:
|
||||
# ai_note += f'- play the whole infield in\n'
|
||||
# else:
|
||||
# ai_note += f'- play the corners in\n'
|
||||
|
||||
# if len(ai_note) == 0 and self.on_base_code > 0:
|
||||
# ai_note += f'- play straight up\n'
|
||||
|
||||
# return ai_note
|
||||
|
||||
|
||||
class CardsetBase(SQLModel):
|
||||
id: int | None = Field(default=None, primary_key=True)
|
||||
@ -1048,62 +1161,6 @@ class Play(PlayBase, table=True):
|
||||
|
||||
return game_string
|
||||
|
||||
@property
|
||||
def pitching_ai_note(self) -> str:
|
||||
ai_note = ''
|
||||
# Holding Baserunners
|
||||
if self.starting_outs == 2 and self.on_base_code > 0:
|
||||
if self.on_base_code == 1:
|
||||
ai_note += f'- hold {self.on_first.player.name}\n'
|
||||
elif self.on_base_code == 2:
|
||||
ai_note += f'- hold {self.on_second.player.name}\n'
|
||||
elif self.on_base_code in [4, 5, 7]:
|
||||
ai_note += f'- hold {self.on_first.player.name} on first\n'
|
||||
# elif self.on_base_code == 5:
|
||||
# ai_note += f'- hold the runner on first\n'
|
||||
elif self.on_base_code == 6:
|
||||
ai_note += f'- hold {self.on_second.player.name} on 2nd\n'
|
||||
elif self.on_base_code in [1, 5]:
|
||||
runner = self.on_first.player
|
||||
if self.on_first.card.batterscouting.battingcard.steal_auto:
|
||||
ai_note += f'- hold {runner.name} on 1st\n'
|
||||
elif self.on_base_code in [2, 4]:
|
||||
if self.on_second.card.batterscouting.battingcard.steal_low + max(self.pitcher.card.pitcherscouting.pitchingcard.hold, 5) >= 14:
|
||||
ai_note += f'- hold {self.on_second.player.name} on 2nd\n'
|
||||
|
||||
# Defensive Alignment
|
||||
if self.on_third and self.starting_outs < 2:
|
||||
if self.could_walkoff:
|
||||
ai_note += f'- play the outfield and infield in'
|
||||
elif abs(self.away_score - self.home_score) <= 3:
|
||||
ai_note += f'- play the whole infield in\n'
|
||||
else:
|
||||
ai_note += f'- play the corners in\n'
|
||||
|
||||
if len(ai_note) == 0 and self.on_base_code > 0:
|
||||
ai_note += f'- play straight up\n'
|
||||
|
||||
return ai_note
|
||||
|
||||
@property
|
||||
def batting_ai_note(self) -> str:
|
||||
ai_note = '' # TODO: migrate Manager AI to their own local model
|
||||
|
||||
return ai_note
|
||||
|
||||
@property
|
||||
def ai_note(self) -> str: # TODO: test these three functions with specific OBCs
|
||||
if self.inning_half == 'top':
|
||||
if self.game.ai_team == 'away':
|
||||
return self.batting_ai_note
|
||||
else:
|
||||
return self.pitching_ai_note
|
||||
else:
|
||||
if self.game.ai_team == 'away':
|
||||
return self.pitching_ai_note
|
||||
else:
|
||||
return self.batting_ai_note
|
||||
|
||||
@property
|
||||
def ai_is_batting(self) -> bool:
|
||||
if self.game.ai_team is None:
|
||||
|
||||
@ -854,3 +854,13 @@ def get_available_batters(session: Session, this_game: Game, this_team: Team) ->
|
||||
logger.info(f'batters: {batters}')
|
||||
|
||||
return batters
|
||||
|
||||
|
||||
def get_batter_card(this_card: Card = None, this_lineup: Lineup = None) -> BattingCard:
|
||||
if this_card is not None:
|
||||
logger.info(f'Getting batter card for {this_card.player.name}')
|
||||
return this_card.batterscouting.battingcard
|
||||
if this_lineup is not None:
|
||||
logger.info(f'Getting batter card for {this_lineup.player.name}')
|
||||
return this_lineup.card.batterscouting.battingcard
|
||||
log_exception(KeyError, 'Either a Card or Lineup must be provided to get_batter_card')
|
||||
|
||||
Loading…
Reference in New Issue
Block a user