Early pass at matchup sim and added is_fatigued to Lineup
This commit is contained in:
parent
76e990390b
commit
701e89eaf2
@ -2768,7 +2768,7 @@ class Gameplay(commands.Cog):
|
||||
@app_commands.describe(
|
||||
new_player='Enter the Card ID (a number)',
|
||||
batting_order='Only enter this if you are forfeiting the DH')
|
||||
@commands.has_any_role(SBA_PLAYERS_ROLE_NAME)
|
||||
@commands.has_any_role(PD_PLAYERS_ROLE_NAME)
|
||||
async def sub_pitcher_command(
|
||||
self, interaction: discord.Interaction, new_player: int,
|
||||
batting_order: Literal['this-spot', '1', '2', '3', '4', '5', '6', '7', '8', '9'] = None):
|
||||
@ -2861,6 +2861,14 @@ class Gameplay(commands.Cog):
|
||||
embed=await self.initialize_play_plus_embed(this_game)
|
||||
)
|
||||
|
||||
# @group_substitution.command(name='forfeit-dh', description='Have the pitcher bat in the DH spot')
|
||||
# @commands.has_any_role(PD_PLAYERS_ROLE_NAME)
|
||||
# async def sub_forfeitdh_command(self, interaction: discord.Interaction):
|
||||
# this_game, owner_team, this_play = await self.checks_log_interaction(interaction)
|
||||
# if False in (this_game, owner_team, this_play):
|
||||
# return
|
||||
#
|
||||
|
||||
@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):
|
||||
|
||||
@ -18,12 +18,19 @@ from discord.ext.commands import Greedy
|
||||
|
||||
import gauntlets
|
||||
import helpers
|
||||
# import in_game.data_cache
|
||||
# import in_game.simulations
|
||||
# import in_game
|
||||
# # from in_game import data_cache, simulations
|
||||
from in_game.data_cache import get_pd_pitchingcard, get_pd_battingcard, get_pd_player
|
||||
from in_game.simulations import get_pos_embeds, get_result
|
||||
from db_calls import db_get, db_post, db_patch, get_team_by_abbrev
|
||||
from helpers import PD_PLAYERS_ROLE_NAME, IMAGES, PD_SEASON, random_conf_gif, fuzzy_player_search, ALL_MLB_TEAMS, \
|
||||
fuzzy_search, get_channel, display_cards, get_card_embeds, get_team_embed, cardset_search, get_blank_team_card, \
|
||||
get_team_by_owner, get_rosters, get_roster_sheet, legal_channel, random_conf_word, embed_pagination, get_cal_user, \
|
||||
team_summary_embed, SelectView, SelectPaperdexCardset, SelectPaperdexTeam
|
||||
|
||||
|
||||
# date = f'{datetime.datetime.now().year}-{datetime.datetime.now().month}-{datetime.datetime.now().day}'
|
||||
# logging.basicConfig(
|
||||
# filename=f'logs/{date}.log',
|
||||
@ -1589,6 +1596,53 @@ class Players(commands.Cog):
|
||||
this_player = await get_one_player(player_name)
|
||||
logging.debug(f'this_player: {this_player}')
|
||||
|
||||
@app_commands.command(name='matchup', description='Simulate a matchup between a pitcher and batter')
|
||||
@app_commands.describe(
|
||||
pitcher_id='The pitcher\'s player_id',
|
||||
batter_id='The batter\'s player_id'
|
||||
)
|
||||
async def matchup_command(self, interaction: discord.Interaction, pitcher_id: int, batter_id: int):
|
||||
await interaction.response.defer()
|
||||
try:
|
||||
pit_card = await get_pd_pitchingcard(pitcher_id)
|
||||
except KeyError as e:
|
||||
await interaction.edit_original_response(
|
||||
content=f'I could not find a pitcher card for player_id {pitcher_id}'
|
||||
)
|
||||
return
|
||||
try:
|
||||
bat_card = await get_pd_battingcard(batter_id)
|
||||
except KeyError as e:
|
||||
await interaction.edit_original_response(
|
||||
content=f'I could not find a batter card for player_id {batter_id}'
|
||||
)
|
||||
return
|
||||
|
||||
this_pitcher = await get_pd_player(pitcher_id)
|
||||
this_batter = await get_pd_player(batter_id)
|
||||
|
||||
# view = helpers.ButtonOptions(
|
||||
# responders=[interaction.user], timeout=60,
|
||||
# labels=['Reroll', None, None, None, None]
|
||||
# )
|
||||
|
||||
await interaction.edit_original_response(
|
||||
content=None,
|
||||
embeds=get_pos_embeds(this_pitcher, this_batter, pit_card, bat_card),
|
||||
# view=view
|
||||
)
|
||||
# await view.wait()
|
||||
#
|
||||
# if view.value:
|
||||
# await question.delete()
|
||||
# if view.value == 'Tagged Up':
|
||||
# advance_one_runner(this_play.id, from_base=2, num_bases=1)
|
||||
# elif view.value == 'Out at 3rd':
|
||||
# num_outs += 1
|
||||
# patch_play(this_play.id, on_second_final=False, outs=num_outs)
|
||||
# else:
|
||||
# await question.delete()
|
||||
|
||||
|
||||
async def setup(bot):
|
||||
await bot.add_cog(Players(bot))
|
||||
|
||||
@ -13,7 +13,7 @@ from dataclasses import dataclass
|
||||
|
||||
from helpers import SBA_SEASON, PD_SEASON, get_player_url, get_sheets
|
||||
from db_calls import db_get
|
||||
from in_game.data_cache import get_pd_player
|
||||
from in_game.data_cache import get_pd_player, CardPosition, BattingCard
|
||||
|
||||
db = SqliteDatabase(
|
||||
'storage/gameplay.db',
|
||||
@ -149,308 +149,6 @@ class ManagerAi(BaseModel):
|
||||
decide_throw = IntegerField(default=5)
|
||||
|
||||
|
||||
class StratManagerAi(pydantic.BaseModel):
|
||||
id: int
|
||||
name: str
|
||||
steal: int = 5
|
||||
running: int = 5
|
||||
hold: int = 5
|
||||
catcher_throw: int = 5
|
||||
uncapped_home: int = 5
|
||||
uncapped_third: int = 5
|
||||
uncapped_trail: int = 5
|
||||
bullpen_matchup: int = 5
|
||||
behind_aggression: int = 5
|
||||
ahead_aggression: int = 5
|
||||
decide_throw: int = 5
|
||||
|
||||
"""
|
||||
Rating Rule of Thumb:
|
||||
1: Least Aggressive
|
||||
5: Average
|
||||
10: Most Aggressive
|
||||
"""
|
||||
|
||||
# def __init__(self, **data) -> None:
|
||||
# super().__init__(**data)
|
||||
#
|
||||
# seed = random.randint(1, 100)
|
||||
# if seed > 95:
|
||||
# self.steal = 10
|
||||
# self.running = 10
|
||||
# self.uncapped_third = 10
|
||||
# self.uncapped_home = 10
|
||||
# self.uncapped_trail = 10
|
||||
# self.behind_aggression = 10
|
||||
# self.ahead_aggression = 10
|
||||
# elif seed > 80:
|
||||
# self.steal = 8
|
||||
# self.running = 8
|
||||
# self.uncapped_third = 8
|
||||
# self.uncapped_home = 8
|
||||
# self.uncapped_trail = 8
|
||||
# self.behind_aggression = 8
|
||||
# self.ahead_aggression = 5
|
||||
# elif seed <= 40:
|
||||
# self.steal = 3
|
||||
# self.running = 3
|
||||
# self.uncapped_third = 3
|
||||
# self.uncapped_home = 3
|
||||
# self.uncapped_trail = 3
|
||||
# self.behind_aggression = 5
|
||||
# self.ahead_aggression = 3
|
||||
# elif seed <= 15:
|
||||
# self.steal = 1
|
||||
# self.running = 1
|
||||
# self.uncapped_third = 1
|
||||
# self.uncapped_home = 1
|
||||
# self.uncapped_trail = 1
|
||||
# self.behind_aggression = 3
|
||||
# self.ahead_aggression = 1
|
||||
|
||||
def check_jump(self, to_base: int, outs: int) -> Optional[str]:
|
||||
"""Returns a string to be appended to the AI note"""
|
||||
|
||||
steal_base = f'attempt to steal'
|
||||
if to_base == 2 or to_base == 3:
|
||||
if self.steal == 10:
|
||||
if to_base == 2:
|
||||
return f'{steal_base} second if the runner has an ***** auto-jump or the safe range is 13+'
|
||||
else:
|
||||
steal_range = 13
|
||||
elif self.steal >= 8:
|
||||
steal_range = 14
|
||||
elif self.steal >= 5:
|
||||
steal_range = 15
|
||||
elif self.steal >= 3:
|
||||
steal_range = 16
|
||||
else:
|
||||
steal_range = 17
|
||||
|
||||
if outs == 2:
|
||||
steal_range += 1
|
||||
elif outs == 0:
|
||||
steal_range -= 1
|
||||
|
||||
return f'{steal_base} {"second" if to_base == 2 else "third"} if their safe range is {steal_range}+'
|
||||
|
||||
else:
|
||||
return None
|
||||
|
||||
def tag_from_second(self, outs: int) -> str:
|
||||
"""Returns a string to be posted ahead of tag up message"""
|
||||
|
||||
tag_base = f'attempt to tag up if their safe range is'
|
||||
if self.running >= 8:
|
||||
tag_range = 5
|
||||
elif self.running >= 5:
|
||||
tag_range = 10
|
||||
else:
|
||||
tag_range = 12
|
||||
|
||||
if outs == 2:
|
||||
tag_range += 3
|
||||
elif outs == 0:
|
||||
tag_range -= 2
|
||||
|
||||
return f'{tag_base} {tag_range}+'
|
||||
|
||||
def tag_from_third(self, outs: int) -> str:
|
||||
"""Returns a string to be posted with the tag up message"""
|
||||
|
||||
tag_base = f'attempt to tag up if their safe range is'
|
||||
if self.running >= 8:
|
||||
tag_range = 8
|
||||
elif self.running >= 5:
|
||||
tag_range = 10
|
||||
else:
|
||||
tag_range = 12
|
||||
|
||||
if outs == 2:
|
||||
tag_range -= 2
|
||||
elif outs == 0:
|
||||
tag_range += 2
|
||||
|
||||
return f'{tag_base} {tag_range}+'
|
||||
|
||||
def uncapped_advance(self, to_base: int, outs: int) -> str:
|
||||
"""Returns a string to be posted with the advancement message"""
|
||||
|
||||
advance_base = f'attempt to advance if their safe range is'
|
||||
|
||||
if to_base == 3:
|
||||
if self.uncapped_third >= 8:
|
||||
advance_range = 14
|
||||
elif self.uncapped_third >= 5:
|
||||
advance_range = 18
|
||||
else:
|
||||
return f'not attempt to advance'
|
||||
|
||||
if outs == 2:
|
||||
advance_range += 2
|
||||
|
||||
else:
|
||||
if self.uncapped_home >= 8:
|
||||
advance_range = 8
|
||||
elif self.uncapped_home >= 5:
|
||||
advance_range = 10
|
||||
else:
|
||||
advance_range = 12
|
||||
|
||||
if outs == 2:
|
||||
advance_range -= 2
|
||||
elif outs == 0:
|
||||
advance_range += 3
|
||||
|
||||
return f'{advance_base} {advance_range}+'
|
||||
|
||||
def trail_advance(self, to_base: int, outs: int, sent_home: bool = False) -> str:
|
||||
"""Returns a string to be posted with the advancement message"""
|
||||
|
||||
advance_base = f'attempt to advance if their safe range is'
|
||||
if sent_home:
|
||||
if self.uncapped_trail >= 8:
|
||||
return 'attempt to advance'
|
||||
elif self.uncapped_trail >= 5:
|
||||
if outs == 2:
|
||||
return 'attempt to advance'
|
||||
else:
|
||||
advance_range = 14
|
||||
else:
|
||||
return 'not attempt to advance'
|
||||
|
||||
else:
|
||||
if self.uncapped_trail >= 8:
|
||||
advance_range = 14
|
||||
else:
|
||||
advance_range = 16
|
||||
|
||||
return f'{advance_base} {advance_range}+'
|
||||
|
||||
def throw_lead_runner(self, to_base: int, outs: int) -> str:
|
||||
"""Returns a string to be posted with the throw message"""
|
||||
|
||||
return 'throw for the lead runner'
|
||||
|
||||
def throw_which_runner(self, to_base: int, outs: int) -> str:
|
||||
"""Returns a string to be posted with the throw message"""
|
||||
|
||||
if to_base == 4:
|
||||
return 'throw for the lead runner'
|
||||
else:
|
||||
return 'throw for the lead runner if their safe range is 14-'
|
||||
|
||||
def gb_decide_advance(self, starting_outs: int, run_lead: int):
|
||||
"""Returns a string to be posted with the advancement message"""
|
||||
|
||||
advance_base = f'attempt to advance if their safe range is'
|
||||
if self.running >= 8:
|
||||
advance_range = 10
|
||||
elif self.running >= 5:
|
||||
advance_range = 13
|
||||
else:
|
||||
advance_range = 16
|
||||
|
||||
if starting_outs == 1:
|
||||
advance_range += 3
|
||||
|
||||
if run_lead >= 4:
|
||||
advance_range -= 3
|
||||
elif run_lead < 0:
|
||||
advance_range += 3
|
||||
|
||||
return f'{advance_base} {min(advance_range, 20)}+'
|
||||
|
||||
def gb_decide_throw(self, starting_outs: int, run_lead: int):
|
||||
"""Returns a string to be posted with the advancement message"""
|
||||
|
||||
throw_base = f'throw for the lead runner if their safe range is'
|
||||
if self.decide_throw >= 8:
|
||||
throw_range = 13
|
||||
elif self.decide_throw >= 5:
|
||||
throw_range = 10
|
||||
else:
|
||||
throw_range = 8
|
||||
|
||||
if starting_outs == 1:
|
||||
throw_range -= 3
|
||||
|
||||
if run_lead >= 4:
|
||||
throw_range -= 3
|
||||
elif run_lead < 0:
|
||||
throw_range += 3
|
||||
|
||||
return f'{throw_base} {max(throw_range, 0)}-'
|
||||
|
||||
def go_to_reliever(
|
||||
self, this_play, tot_allowed: int, is_starter: bool = False) -> bool:
|
||||
run_lead = this_play.ai_run_diff()
|
||||
obc = this_play.on_base_code
|
||||
logging.info(f'db_calls_gameplay - StratManagerAi - ID: {self.id} - go_to_reliever: '
|
||||
f'outs: {this_play.starting_outs}, obc: {obc}, run_lead: {run_lead}, '
|
||||
f'tot_allowed: {tot_allowed}')
|
||||
|
||||
lead_target = run_lead if is_starter else 3
|
||||
|
||||
# AI up big
|
||||
if tot_allowed < 5 and is_starter:
|
||||
logging.info(f'db_calls_gameplay - StratManagerAi - ID: {self.id} - go_to_reliever: False / code 1')
|
||||
return False
|
||||
elif run_lead > 5 or (run_lead > 2 and self.ahead_aggression > 5):
|
||||
if tot_allowed <= lead_target or obc <= 3 or (this_play.starting_outs == 2 and not is_starter):
|
||||
logging.info(f'db_calls_gameplay - StratManagerAi - ID: {self.id} - go_to_reliever: False / code 2')
|
||||
return False
|
||||
elif run_lead > 2 or (run_lead >= 0 and self.ahead_aggression > 5):
|
||||
if tot_allowed < lead_target or obc <= 1 or (this_play.starting_outs == 2 and not is_starter):
|
||||
logging.info(f'db_calls_gameplay - StratManagerAi - ID: {self.id} - go_to_reliever: False / code 3')
|
||||
return False
|
||||
elif run_lead >= 0 or (run_lead >= -2 and self.behind_aggression > 5):
|
||||
if tot_allowed < 5 or obc <= run_lead or (this_play.starting_outs == 2 and not is_starter):
|
||||
logging.info(f'db_calls_gameplay - StratManagerAi - ID: {self.id} - go_to_reliever: False / code 4')
|
||||
return False
|
||||
elif run_lead >= -3 and self.behind_aggression > 5:
|
||||
if tot_allowed < 5 and obc <= 1:
|
||||
logging.info(f'db_calls_gameplay - StratManagerAi - ID: {self.id} - go_to_reliever: False / code 5')
|
||||
return False
|
||||
elif run_lead <= -5:
|
||||
if is_starter and this_play.inning_num <= 3:
|
||||
logging.info(f'db_calls_gameplay - StratManagerAi - ID: {self.id} - go_to_reliever: False / code 6')
|
||||
return False
|
||||
if this_play.starting_outs != 0:
|
||||
logging.info(f'db_calls_gameplay - StratManagerAi - ID: {self.id} - go_to_reliever: False / code 7')
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
|
||||
def convert_strat_manager(manager: ManagerAi) -> StratManagerAi:
|
||||
manager_dict = model_to_dict(manager)
|
||||
return StratManagerAi(**manager_dict)
|
||||
|
||||
|
||||
def get_manager(game) -> Optional[StratManagerAi]:
|
||||
if not game.ai_team:
|
||||
return None
|
||||
|
||||
# manager_ai_id = game.home_team_id if game.ai_team == 'home' else game.away_team_id
|
||||
# manager_ai_id = 1
|
||||
team_id = game.home_team_id if game.ai_team == 'home' else game.away_team_id
|
||||
manager_ai_id = ((datetime.datetime.now().day * team_id) % 3) + 1
|
||||
if manager_ai_id > 3 or manager_ai_id < 1:
|
||||
manager_ai_id = 1
|
||||
logging.debug(f'manager id: {manager_ai_id} for game {game}')
|
||||
|
||||
try:
|
||||
this_manager = ManagerAi.get_by_id(manager_ai_id)
|
||||
except Exception as e:
|
||||
e_message = f'Could not find manager id {manager_ai_id}'
|
||||
logging.error(f'{e_message}: {type(e)}: {e}')
|
||||
raise KeyError(f'Could not find this AI manager\'s playbook')
|
||||
|
||||
return convert_strat_manager(this_manager)
|
||||
|
||||
|
||||
def load_ai():
|
||||
all_ai = [
|
||||
{'name': 'Basic'}
|
||||
@ -669,6 +367,7 @@ class Lineup(BaseModel):
|
||||
replacing_id = IntegerField(null=True)
|
||||
active = BooleanField(default=True)
|
||||
variant = IntegerField(default=0)
|
||||
is_fatigued = BooleanField(null=True)
|
||||
|
||||
|
||||
@dataclass
|
||||
@ -684,6 +383,7 @@ class StratLineup:
|
||||
active: bool = True
|
||||
card_id: int = None
|
||||
variant: int = 0
|
||||
is_fatigued: bool = None
|
||||
|
||||
|
||||
def convert_stratlineup(lineup: Lineup) -> StratLineup:
|
||||
@ -781,7 +481,7 @@ def post_lineups(lineups: list):
|
||||
|
||||
|
||||
def patch_lineup(lineup_id, active: Optional[bool] = None, position: Optional[str] = None,
|
||||
replacing_id: Optional[int] = None) -> StratLineup:
|
||||
replacing_id: Optional[int] = None, is_fatigued: Optional[bool] = None) -> StratLineup:
|
||||
this_lineup = Lineup.get_by_id(lineup_id)
|
||||
if active is not None:
|
||||
this_lineup.active = active
|
||||
@ -789,6 +489,8 @@ def patch_lineup(lineup_id, active: Optional[bool] = None, position: Optional[st
|
||||
this_lineup.position = position
|
||||
if replacing_id is not None:
|
||||
this_lineup.replacing_id = replacing_id
|
||||
if is_fatigued is not None:
|
||||
this_lineup.is_fatigued = is_fatigued
|
||||
this_lineup.save()
|
||||
|
||||
# return_lineup = model_to_dict(this_lineup)
|
||||
@ -2443,5 +2145,312 @@ def get_pitching_decisions(game: StratGame, db_game_id: int):
|
||||
# f'```'
|
||||
|
||||
|
||||
class StratManagerAi(pydantic.BaseModel):
|
||||
id: int
|
||||
name: str
|
||||
steal: int = 5
|
||||
running: int = 5
|
||||
hold: int = 5
|
||||
catcher_throw: int = 5
|
||||
uncapped_home: int = 5
|
||||
uncapped_third: int = 5
|
||||
uncapped_trail: int = 5
|
||||
bullpen_matchup: int = 5
|
||||
behind_aggression: int = 5
|
||||
ahead_aggression: int = 5
|
||||
decide_throw: int = 5
|
||||
|
||||
"""
|
||||
Rating Rule of Thumb:
|
||||
1: Least Aggressive
|
||||
5: Average
|
||||
10: Most Aggressive
|
||||
"""
|
||||
|
||||
# def __init__(self, **data) -> None:
|
||||
# super().__init__(**data)
|
||||
#
|
||||
# seed = random.randint(1, 100)
|
||||
# if seed > 95:
|
||||
# self.steal = 10
|
||||
# self.running = 10
|
||||
# self.uncapped_third = 10
|
||||
# self.uncapped_home = 10
|
||||
# self.uncapped_trail = 10
|
||||
# self.behind_aggression = 10
|
||||
# self.ahead_aggression = 10
|
||||
# elif seed > 80:
|
||||
# self.steal = 8
|
||||
# self.running = 8
|
||||
# self.uncapped_third = 8
|
||||
# self.uncapped_home = 8
|
||||
# self.uncapped_trail = 8
|
||||
# self.behind_aggression = 8
|
||||
# self.ahead_aggression = 5
|
||||
# elif seed <= 40:
|
||||
# self.steal = 3
|
||||
# self.running = 3
|
||||
# self.uncapped_third = 3
|
||||
# self.uncapped_home = 3
|
||||
# self.uncapped_trail = 3
|
||||
# self.behind_aggression = 5
|
||||
# self.ahead_aggression = 3
|
||||
# elif seed <= 15:
|
||||
# self.steal = 1
|
||||
# self.running = 1
|
||||
# self.uncapped_third = 1
|
||||
# self.uncapped_home = 1
|
||||
# self.uncapped_trail = 1
|
||||
# self.behind_aggression = 3
|
||||
# self.ahead_aggression = 1
|
||||
|
||||
def check_jump(self, to_base: int, outs: int) -> Optional[str]:
|
||||
"""Returns a string to be appended to the AI note"""
|
||||
|
||||
steal_base = f'attempt to steal'
|
||||
if to_base == 2 or to_base == 3:
|
||||
if self.steal == 10:
|
||||
if to_base == 2:
|
||||
return f'{steal_base} second if the runner has an ***** auto-jump or the safe range is 13+'
|
||||
else:
|
||||
steal_range = 13
|
||||
elif self.steal >= 8:
|
||||
steal_range = 14
|
||||
elif self.steal >= 5:
|
||||
steal_range = 15
|
||||
elif self.steal >= 3:
|
||||
steal_range = 16
|
||||
else:
|
||||
steal_range = 17
|
||||
|
||||
if outs == 2:
|
||||
steal_range += 1
|
||||
elif outs == 0:
|
||||
steal_range -= 1
|
||||
|
||||
return f'{steal_base} {"second" if to_base == 2 else "third"} if their safe range is {steal_range}+'
|
||||
|
||||
else:
|
||||
return None
|
||||
|
||||
def tag_from_second(self, outs: int) -> str:
|
||||
"""Returns a string to be posted ahead of tag up message"""
|
||||
|
||||
tag_base = f'attempt to tag up if their safe range is'
|
||||
if self.running >= 8:
|
||||
tag_range = 5
|
||||
elif self.running >= 5:
|
||||
tag_range = 10
|
||||
else:
|
||||
tag_range = 12
|
||||
|
||||
if outs == 2:
|
||||
tag_range += 3
|
||||
elif outs == 0:
|
||||
tag_range -= 2
|
||||
|
||||
return f'{tag_base} {tag_range}+'
|
||||
|
||||
def tag_from_third(self, outs: int) -> str:
|
||||
"""Returns a string to be posted with the tag up message"""
|
||||
|
||||
tag_base = f'attempt to tag up if their safe range is'
|
||||
if self.running >= 8:
|
||||
tag_range = 8
|
||||
elif self.running >= 5:
|
||||
tag_range = 10
|
||||
else:
|
||||
tag_range = 12
|
||||
|
||||
if outs == 2:
|
||||
tag_range -= 2
|
||||
elif outs == 0:
|
||||
tag_range += 2
|
||||
|
||||
return f'{tag_base} {tag_range}+'
|
||||
|
||||
def uncapped_advance(self, to_base: int, outs: int) -> str:
|
||||
"""Returns a string to be posted with the advancement message"""
|
||||
|
||||
advance_base = f'attempt to advance if their safe range is'
|
||||
|
||||
if to_base == 3:
|
||||
if self.uncapped_third >= 8:
|
||||
advance_range = 14
|
||||
elif self.uncapped_third >= 5:
|
||||
advance_range = 18
|
||||
else:
|
||||
return f'not attempt to advance'
|
||||
|
||||
if outs == 2:
|
||||
advance_range += 2
|
||||
|
||||
else:
|
||||
if self.uncapped_home >= 8:
|
||||
advance_range = 8
|
||||
elif self.uncapped_home >= 5:
|
||||
advance_range = 10
|
||||
else:
|
||||
advance_range = 12
|
||||
|
||||
if outs == 2:
|
||||
advance_range -= 2
|
||||
elif outs == 0:
|
||||
advance_range += 3
|
||||
|
||||
return f'{advance_base} {advance_range}+'
|
||||
|
||||
# def uncapped_advance_runner(self, this_play: StratPlay, to_base: int, runner: BattingCard, defender_pos: CardPosition, modifier: int = -1):
|
||||
# total_mod = modifier + defender_pos.arm
|
||||
# if to_base == 3:
|
||||
|
||||
|
||||
def trail_advance(self, to_base: int, outs: int, sent_home: bool = False) -> str:
|
||||
"""Returns a string to be posted with the advancement message"""
|
||||
|
||||
advance_base = f'attempt to advance if their safe range is'
|
||||
if sent_home:
|
||||
if self.uncapped_trail >= 8:
|
||||
return 'attempt to advance'
|
||||
elif self.uncapped_trail >= 5:
|
||||
if outs == 2:
|
||||
return 'attempt to advance'
|
||||
else:
|
||||
advance_range = 14
|
||||
else:
|
||||
return 'not attempt to advance'
|
||||
|
||||
else:
|
||||
if self.uncapped_trail >= 8:
|
||||
advance_range = 14
|
||||
else:
|
||||
advance_range = 16
|
||||
|
||||
return f'{advance_base} {advance_range}+'
|
||||
|
||||
def throw_lead_runner(self, to_base: int, outs: int) -> str:
|
||||
"""Returns a string to be posted with the throw message"""
|
||||
|
||||
return 'throw for the lead runner'
|
||||
|
||||
def throw_which_runner(self, to_base: int, outs: int) -> str:
|
||||
"""Returns a string to be posted with the throw message"""
|
||||
|
||||
if to_base == 4:
|
||||
return 'throw for the lead runner'
|
||||
else:
|
||||
return 'throw for the lead runner if their safe range is 14-'
|
||||
|
||||
def gb_decide_advance(self, starting_outs: int, run_lead: int):
|
||||
"""Returns a string to be posted with the advancement message"""
|
||||
|
||||
advance_base = f'attempt to advance if their safe range is'
|
||||
if self.running >= 8:
|
||||
advance_range = 10
|
||||
elif self.running >= 5:
|
||||
advance_range = 13
|
||||
else:
|
||||
advance_range = 16
|
||||
|
||||
if starting_outs == 1:
|
||||
advance_range += 3
|
||||
|
||||
if run_lead >= 4:
|
||||
advance_range -= 3
|
||||
elif run_lead < 0:
|
||||
advance_range += 3
|
||||
|
||||
return f'{advance_base} {min(advance_range, 20)}+'
|
||||
|
||||
def gb_decide_throw(self, starting_outs: int, run_lead: int):
|
||||
"""Returns a string to be posted with the advancement message"""
|
||||
|
||||
throw_base = f'throw for the lead runner if their safe range is'
|
||||
if self.decide_throw >= 8:
|
||||
throw_range = 13
|
||||
elif self.decide_throw >= 5:
|
||||
throw_range = 10
|
||||
else:
|
||||
throw_range = 8
|
||||
|
||||
if starting_outs == 1:
|
||||
throw_range -= 3
|
||||
|
||||
if run_lead >= 4:
|
||||
throw_range -= 3
|
||||
elif run_lead < 0:
|
||||
throw_range += 3
|
||||
|
||||
return f'{throw_base} {max(throw_range, 0)}-'
|
||||
|
||||
def go_to_reliever(
|
||||
self, this_play, tot_allowed: int, is_starter: bool = False) -> bool:
|
||||
run_lead = this_play.ai_run_diff()
|
||||
obc = this_play.on_base_code
|
||||
logging.info(f'db_calls_gameplay - StratManagerAi - ID: {self.id} - go_to_reliever: '
|
||||
f'outs: {this_play.starting_outs}, obc: {obc}, run_lead: {run_lead}, '
|
||||
f'tot_allowed: {tot_allowed}')
|
||||
|
||||
lead_target = run_lead if is_starter else 3
|
||||
|
||||
# AI up big
|
||||
if tot_allowed < 5 and is_starter:
|
||||
logging.info(f'db_calls_gameplay - StratManagerAi - ID: {self.id} - go_to_reliever: False / code 1')
|
||||
return False
|
||||
elif run_lead > 5 or (run_lead > 2 and self.ahead_aggression > 5):
|
||||
if tot_allowed <= lead_target or obc <= 3 or (this_play.starting_outs == 2 and not is_starter):
|
||||
logging.info(f'db_calls_gameplay - StratManagerAi - ID: {self.id} - go_to_reliever: False / code 2')
|
||||
return False
|
||||
elif run_lead > 2 or (run_lead >= 0 and self.ahead_aggression > 5):
|
||||
if tot_allowed < lead_target or obc <= 1 or (this_play.starting_outs == 2 and not is_starter):
|
||||
logging.info(f'db_calls_gameplay - StratManagerAi - ID: {self.id} - go_to_reliever: False / code 3')
|
||||
return False
|
||||
elif run_lead >= 0 or (run_lead >= -2 and self.behind_aggression > 5):
|
||||
if tot_allowed < 5 or obc <= run_lead or (this_play.starting_outs == 2 and not is_starter):
|
||||
logging.info(f'db_calls_gameplay - StratManagerAi - ID: {self.id} - go_to_reliever: False / code 4')
|
||||
return False
|
||||
elif run_lead >= -3 and self.behind_aggression > 5:
|
||||
if tot_allowed < 5 and obc <= 1:
|
||||
logging.info(f'db_calls_gameplay - StratManagerAi - ID: {self.id} - go_to_reliever: False / code 5')
|
||||
return False
|
||||
elif run_lead <= -5:
|
||||
if is_starter and this_play.inning_num <= 3:
|
||||
logging.info(f'db_calls_gameplay - StratManagerAi - ID: {self.id} - go_to_reliever: False / code 6')
|
||||
return False
|
||||
if this_play.starting_outs != 0:
|
||||
logging.info(f'db_calls_gameplay - StratManagerAi - ID: {self.id} - go_to_reliever: False / code 7')
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
|
||||
def convert_strat_manager(manager: ManagerAi) -> StratManagerAi:
|
||||
manager_dict = model_to_dict(manager)
|
||||
return StratManagerAi(**manager_dict)
|
||||
|
||||
|
||||
def get_manager(game) -> Optional[StratManagerAi]:
|
||||
if not game.ai_team:
|
||||
return None
|
||||
|
||||
# manager_ai_id = game.home_team_id if game.ai_team == 'home' else game.away_team_id
|
||||
# manager_ai_id = 1
|
||||
team_id = game.home_team_id if game.ai_team == 'home' else game.away_team_id
|
||||
manager_ai_id = ((datetime.datetime.now().day * team_id) % 3) + 1
|
||||
if manager_ai_id > 3 or manager_ai_id < 1:
|
||||
manager_ai_id = 1
|
||||
logging.debug(f'manager id: {manager_ai_id} for game {game}')
|
||||
|
||||
try:
|
||||
this_manager = ManagerAi.get_by_id(manager_ai_id)
|
||||
except Exception as e:
|
||||
e_message = f'Could not find manager id {manager_ai_id}'
|
||||
logging.error(f'{e_message}: {type(e)}: {e}')
|
||||
raise KeyError(f'Could not find this AI manager\'s playbook')
|
||||
|
||||
return convert_strat_manager(this_manager)
|
||||
|
||||
|
||||
db.close()
|
||||
|
||||
|
||||
@ -5,7 +5,7 @@ import random
|
||||
|
||||
# import data_cache
|
||||
from db_calls_gameplay import StratPlay, StratGame, get_one_lineup, get_manager, get_team_lineups, \
|
||||
get_last_inning_end_play, make_sub, get_player, StratLineup, get_pitching_stats, patch_play
|
||||
get_last_inning_end_play, make_sub, get_player, StratLineup, get_pitching_stats, patch_play, patch_lineup
|
||||
from db_calls import db_get, db_post
|
||||
from peewee import *
|
||||
from typing import Optional, Literal
|
||||
@ -726,6 +726,13 @@ async def check_pitching_sub(this_play: StratPlay, ai_team: dict):
|
||||
|
||||
|
||||
async def is_pitcher_fatigued(this_play: StratPlay) -> bool:
|
||||
# Check Lineup object for 'is_fatigued'
|
||||
# If yes, return True
|
||||
# Else, check for fatigue below
|
||||
# If fatigued, patch Lineup object with 'is_fatigued'
|
||||
if this_play.pitcher.is_fatigued:
|
||||
return True
|
||||
|
||||
used_pitchers = await get_team_lineups(
|
||||
game_id=this_play.game.id,
|
||||
team_id=this_play.pitcher.team_id,
|
||||
@ -753,10 +760,10 @@ async def is_pitcher_fatigued(this_play: StratPlay) -> bool:
|
||||
|
||||
# Check starter fatigue
|
||||
if len(used_pitchers) == 1:
|
||||
if ps['pl_eruns'] >= 7:
|
||||
if ps['pl_runs'] >= 7:
|
||||
logging.info(f'ai_manager - is_pitcher_fatigued: starter allowed 7+, returning True')
|
||||
return True
|
||||
elif ps['pl_eruns'] >= 6:
|
||||
elif ps['pl_runs'] >= 6:
|
||||
logging.info(f'ai_manager - is_pitcher_fatigued: starter allowed 6+, checking for fatigue')
|
||||
f_query = get_pitching_stats(
|
||||
this_play.game.id,
|
||||
@ -765,8 +772,9 @@ async def is_pitcher_fatigued(this_play: StratPlay) -> bool:
|
||||
)
|
||||
if f_query[0]['pl_in_runs'] >= 6:
|
||||
logging.info(f'ai_manager - is_pitcher_fatigued: starter allowed 6 in 2, returning True')
|
||||
patch_lineup(this_play.pitcher.id, is_fatigued=True)
|
||||
return True
|
||||
elif ps['pl_eruns'] >= 5:
|
||||
elif ps['pl_runs'] >= 5:
|
||||
logging.info(f'ai_manager - is_pitcher_fatigued: starter allowed 5+, checking for fatigue')
|
||||
f_query = get_pitching_stats(
|
||||
this_play.game.id,
|
||||
@ -775,6 +783,7 @@ async def is_pitcher_fatigued(this_play: StratPlay) -> bool:
|
||||
)
|
||||
if f_query[0]['pl_in_runs'] >= 5:
|
||||
logging.info(f'ai_manager - is_pitcher_fatigued: starter allowed 5 in 1, returning True')
|
||||
patch_lineup(this_play.pitcher.id, is_fatigued=True)
|
||||
return True
|
||||
|
||||
innof_work = math.ceil((ps['pl_outs'] + 1) / 3)
|
||||
@ -795,9 +804,11 @@ async def is_pitcher_fatigued(this_play: StratPlay) -> bool:
|
||||
|
||||
elif innof_work > pof_weakness:
|
||||
patch_play(this_play.id, in_pow=True)
|
||||
patch_lineup(this_play.pitcher.id, is_fatigued=True)
|
||||
return True
|
||||
|
||||
logging.info(f'ai_manager - is_pitcher_fatigued: beyond point of weakness, fatigued, returning True')
|
||||
patch_lineup(this_play.pitcher.id, is_fatigued=True)
|
||||
return True
|
||||
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user