Add FullCard/CardColumn/CardResult models and card builder pipeline
- card_layout.py: Port PlayResult, PLAY_RESULTS, EXACT_CHANCES, get_chances(), CardResult, CardColumn, FullCard, FullBattingCard, FullPitchingCard from database/app/card_creation.py. card_output() uses col_* key names. get_chances() always returns Decimal to avoid float/Decimal type errors. - batters/card_builder.py: Port get_batter_card_data() algorithm as build_batter_full_cards(ratings_vl, ratings_vr, offense_col, player_id, hand). assign_bchances() returns float tuples for compatibility with float-based BattingCardRatingsModel fields. - pitchers/card_builder.py: Port get_pitcher_card_data() algorithm as build_pitcher_full_cards(). assign_pchances() returns float tuples. Includes card.add_fatigue() at end of each card iteration. - batters/calcs_batter.py: Integrate card builder in get_batter_ratings(). After computing raw ratings, call build_batter_full_cards() and merge 9 col_* rendered column fields into each ratings dict. Lazy import to avoid circular dependency. - pitchers/calcs_pitcher.py: Same integration for get_pitcher_ratings(). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
parent
7c967b6119
commit
a72abc01a3
@ -622,4 +622,17 @@ def get_batter_ratings(df_data) -> List[dict]:
|
||||
else:
|
||||
logger.debug(f'total chances: {vr_total_chances}')
|
||||
|
||||
return [vl.custom_to_dict(), vr.custom_to_dict()]
|
||||
vl_dict = vl.custom_to_dict()
|
||||
vr_dict = vr.custom_to_dict()
|
||||
|
||||
try:
|
||||
from batters.card_builder import build_batter_full_cards
|
||||
vl_card, vr_card = build_batter_full_cards(
|
||||
vl, vr, int(df_data['offense_col']), int(df_data['player_id']), df_data['bat_hand']
|
||||
)
|
||||
vl_dict.update(vl_card.card_output())
|
||||
vr_dict.update(vr_card.card_output())
|
||||
except Exception as e:
|
||||
logger.warning(f'Card layout builder failed for {df_data.name}: {e}')
|
||||
|
||||
return [vl_dict, vr_dict]
|
||||
|
||||
802
batters/card_builder.py
Normal file
802
batters/card_builder.py
Normal file
@ -0,0 +1,802 @@
|
||||
"""
|
||||
Batter card-building algorithm, ported from database/app/card_creation.py (~lines 1357-2226).
|
||||
|
||||
Converts BattingCardRatingsModel instances (vL and vR) into FullBattingCard objects
|
||||
that represent the physical card layout.
|
||||
"""
|
||||
import copy
|
||||
import math
|
||||
import logging
|
||||
from decimal import Decimal
|
||||
|
||||
from card_layout import FullBattingCard, PLAY_RESULTS, PlayResult, EXACT_CHANCES, get_chances
|
||||
from batters.calcs_batter import BattingCardRatingsModel
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def build_batter_full_cards(
|
||||
ratings_vl: BattingCardRatingsModel,
|
||||
ratings_vr: BattingCardRatingsModel,
|
||||
offense_col: int,
|
||||
player_id: int,
|
||||
hand: str, # player's batting hand: 'R', 'L', or 'S'
|
||||
) -> tuple:
|
||||
"""Build vL and vR FullBattingCard objects from pre-calculated ratings.
|
||||
|
||||
Returns (vl_card, vr_card).
|
||||
"""
|
||||
player_binary = player_id % 2
|
||||
|
||||
vl = FullBattingCard(offense_col=offense_col, alt_direction=player_binary)
|
||||
vr = FullBattingCard(offense_col=offense_col, alt_direction=player_binary)
|
||||
|
||||
def assign_bchances(this_card, play, chances, secondary_play=None):
|
||||
r_data = this_card.add_result(play, chances, secondary_play)
|
||||
if r_data:
|
||||
return float(r_data[0]), float(r_data[1])
|
||||
else:
|
||||
for x in EXACT_CHANCES:
|
||||
if x < math.floor(chances):
|
||||
r_data = this_card.add_result(play, Decimal(math.floor(chances)), secondary_play)
|
||||
if r_data:
|
||||
return float(r_data[0]), float(r_data[1])
|
||||
break
|
||||
if x < chances:
|
||||
r_data = this_card.add_result(play, x, secondary_play)
|
||||
if r_data:
|
||||
return float(r_data[0]), float(r_data[1])
|
||||
return 0, 0
|
||||
|
||||
def get_pullside_of(vs_hand):
|
||||
if hand == 'L':
|
||||
return 'rf'
|
||||
elif hand == 'R':
|
||||
return 'lf'
|
||||
elif vs_hand == 'L':
|
||||
return 'lf'
|
||||
else:
|
||||
return 'rf'
|
||||
|
||||
def get_preferred_mif(ratings):
|
||||
if hand == 'L' and ratings.slap_rate > .24:
|
||||
return 'ss'
|
||||
elif hand == 'L' or (hand == 'R' and ratings.slap_rate > .24):
|
||||
return '2b'
|
||||
else:
|
||||
return 'ss'
|
||||
|
||||
for card, data, vs_hand in [
|
||||
(vl, copy.deepcopy(ratings_vl), 'L'),
|
||||
(vr, copy.deepcopy(ratings_vr), 'R'),
|
||||
]:
|
||||
logger.info(f'\n\nBeginning v{vs_hand}')
|
||||
|
||||
new_ratings = BattingCardRatingsModel(
|
||||
battingcard_id=data.battingcard_id,
|
||||
bat_hand=data.bat_hand,
|
||||
vs_hand=vs_hand,
|
||||
hard_rate=data.hard_rate,
|
||||
med_rate=data.med_rate,
|
||||
soft_rate=data.soft_rate,
|
||||
pull_rate=data.pull_rate,
|
||||
center_rate=data.center_rate,
|
||||
slap_rate=data.slap_rate,
|
||||
)
|
||||
pull_of = get_pullside_of(vs_hand)
|
||||
pref_mif = get_preferred_mif(data)
|
||||
|
||||
# BP Homerun
|
||||
res_chances = data.bp_homerun
|
||||
while res_chances > 0:
|
||||
ch = get_chances(res_chances)
|
||||
r_val = assign_bchances(card, PLAY_RESULTS['bp-hr'], ch)
|
||||
logger.debug(f'Returned batting chances: {r_val[0]} / {r_val[1]}\n')
|
||||
res_chances -= r_val[0]
|
||||
new_ratings.bp_homerun += r_val[0]
|
||||
|
||||
# HBP
|
||||
retries = 0
|
||||
res_chances = data.hbp
|
||||
while res_chances > 0:
|
||||
if res_chances < 1 or retries > 0:
|
||||
break
|
||||
ch = get_chances(res_chances)
|
||||
r_val = assign_bchances(card, PlayResult(full_name='HBP', short_name='HBP'), ch)
|
||||
logger.debug(f'Returned batting chances: {r_val[0]} / {r_val[1]}\n')
|
||||
res_chances -= r_val[0]
|
||||
new_ratings.hbp += r_val[0]
|
||||
if r_val[0] == 0:
|
||||
retries += 1
|
||||
|
||||
# Homerun
|
||||
retries = 0
|
||||
res_chances = data.homerun
|
||||
while res_chances > 0:
|
||||
if res_chances < 1 or retries > 0:
|
||||
if data.double_pull > 0:
|
||||
data.double_pull += res_chances
|
||||
elif data.double_two > 0:
|
||||
data.double_two += res_chances
|
||||
elif data.triple > 0:
|
||||
data.triple += res_chances
|
||||
elif data.single_two > 0:
|
||||
data.single_two += res_chances
|
||||
elif data.single_center > 0:
|
||||
data.single_center += res_chances
|
||||
break
|
||||
|
||||
ch = get_chances(res_chances)
|
||||
if data.double_pull > (data.flyout_rf_b + data.flyout_lf_b) and data.double_pull > max(1 - ch, 0):
|
||||
secondary = PLAY_RESULTS[f'do-{pull_of}']
|
||||
elif data.flyout_lf_b > data.flyout_rf_b and data.flyout_lf_b > max(1 - ch, 0):
|
||||
secondary = PLAY_RESULTS['fly-lf']
|
||||
elif data.flyout_rf_b > max(1 - ch, 0):
|
||||
secondary = PLAY_RESULTS['fly-rf']
|
||||
elif data.double_pull > max(1 - ch, 0):
|
||||
secondary = PLAY_RESULTS[f'do-{pull_of}']
|
||||
elif data.double_three > max(1 - ch, 0):
|
||||
secondary = PLAY_RESULTS['do***']
|
||||
elif data.double_two > max(1 - ch, 0):
|
||||
secondary = PLAY_RESULTS['do**']
|
||||
elif data.triple > max(1 - ch, 0):
|
||||
secondary = PLAY_RESULTS['tr']
|
||||
else:
|
||||
secondary = None
|
||||
|
||||
r_val = assign_bchances(card, PLAY_RESULTS['hr'], ch, secondary)
|
||||
logger.debug(f'Returned batting chances: {r_val[0]} / {r_val[1]}\n')
|
||||
res_chances -= r_val[0]
|
||||
new_ratings.homerun += r_val[0]
|
||||
if r_val[1] > 0:
|
||||
if secondary.short_name[:4] == 'DO (':
|
||||
data.double_pull -= r_val[1]
|
||||
new_ratings.double_pull += r_val[1]
|
||||
elif 'lf' in secondary.short_name:
|
||||
data.flyout_lf_b -= r_val[1]
|
||||
new_ratings.flyout_lf_b += r_val[1]
|
||||
elif 'rf' in secondary.short_name:
|
||||
data.flyout_rf_b -= r_val[1]
|
||||
new_ratings.flyout_rf_b += r_val[1]
|
||||
elif '***' in secondary.short_name:
|
||||
data.double_three -= r_val[1]
|
||||
new_ratings.double_three += r_val[1]
|
||||
elif '**' in secondary.short_name:
|
||||
data.double_two -= r_val[1]
|
||||
new_ratings.double_two += r_val[1]
|
||||
elif 'TR' in secondary.short_name:
|
||||
data.triple -= r_val[1]
|
||||
new_ratings.triple += r_val[1]
|
||||
|
||||
if r_val[0] == 0:
|
||||
retries += 1
|
||||
|
||||
# Triple
|
||||
retries = 0
|
||||
res_chances = data.triple
|
||||
while res_chances > 0:
|
||||
if res_chances < 1 or retries > 0:
|
||||
if data.double_pull > 0:
|
||||
data.double_pull += res_chances
|
||||
elif data.double_two > 0:
|
||||
data.double_two += res_chances
|
||||
elif data.single_two > 0:
|
||||
data.single_two += res_chances
|
||||
elif data.single_center > 0:
|
||||
data.single_center += res_chances
|
||||
elif data.single_one > 0:
|
||||
data.single_one += res_chances
|
||||
break
|
||||
|
||||
ch = get_chances(res_chances)
|
||||
if data.single_two > max(1 - ch, 0):
|
||||
secondary = PLAY_RESULTS['si**']
|
||||
elif data.flyout_lf_b > max(1 - ch, 0):
|
||||
secondary = PLAY_RESULTS['fly-lf']
|
||||
elif data.flyout_rf_b > max(1 - ch, 0):
|
||||
secondary = PLAY_RESULTS['fly-rf']
|
||||
elif data.double_pull > max(1 - ch, 0):
|
||||
secondary = PLAY_RESULTS[f'do-{pull_of}']
|
||||
elif data.double_three > max(1 - ch, 0):
|
||||
secondary = PLAY_RESULTS['do***']
|
||||
elif data.double_two > max(1 - ch, 0):
|
||||
secondary = PLAY_RESULTS['do**']
|
||||
else:
|
||||
secondary = None
|
||||
|
||||
r_val = assign_bchances(card, PLAY_RESULTS['tr'], ch, secondary)
|
||||
logger.debug(f'Returned batting chances: {r_val[0]} / {r_val[1]}\n')
|
||||
res_chances -= r_val[0]
|
||||
new_ratings.triple += r_val[0]
|
||||
if r_val[1] > 0:
|
||||
if 'DO (' in secondary.short_name:
|
||||
data.double_pull -= r_val[1]
|
||||
new_ratings.double_pull += r_val[1]
|
||||
elif 'lf' in secondary.short_name:
|
||||
data.flyout_lf_b -= r_val[1]
|
||||
new_ratings.flyout_lf_b += r_val[1]
|
||||
elif 'rf' in secondary.short_name:
|
||||
data.flyout_rf_b -= r_val[1]
|
||||
new_ratings.flyout_rf_b += r_val[1]
|
||||
elif '***' in secondary.short_name:
|
||||
data.double_three -= r_val[1]
|
||||
new_ratings.double_three += r_val[1]
|
||||
elif 'SI' in secondary.short_name:
|
||||
data.single_two -= r_val[1]
|
||||
new_ratings.single_two += r_val[1]
|
||||
elif '**' in secondary.short_name:
|
||||
data.double_two -= r_val[1]
|
||||
new_ratings.double_two += r_val[1]
|
||||
|
||||
if r_val[0] == 0:
|
||||
retries += 1
|
||||
|
||||
# Double***
|
||||
retries = 0
|
||||
res_chances = data.double_three
|
||||
while res_chances > 0:
|
||||
if res_chances < 1 or retries > 0:
|
||||
if data.double_pull > 0:
|
||||
data.double_pull += res_chances
|
||||
elif data.double_two > 0:
|
||||
data.double_two += res_chances
|
||||
elif data.single_two > 0:
|
||||
data.single_two += res_chances
|
||||
elif data.single_center > 0:
|
||||
data.single_center += res_chances
|
||||
elif data.single_one > 0:
|
||||
data.single_one += res_chances
|
||||
break
|
||||
|
||||
ch = get_chances(res_chances)
|
||||
if data.single_two > max(1 - ch, 0):
|
||||
secondary = PLAY_RESULTS['si**']
|
||||
elif data.flyout_lf_b > max(1 - ch, 0):
|
||||
secondary = PLAY_RESULTS['fly-lf']
|
||||
elif data.flyout_rf_b > max(1 - ch, 0):
|
||||
secondary = PLAY_RESULTS['fly-rf']
|
||||
elif data.double_pull > max(1 - ch, 0):
|
||||
secondary = PLAY_RESULTS[f'do-{pull_of}']
|
||||
elif data.double_two > max(1 - ch, 0):
|
||||
secondary = PLAY_RESULTS['do**']
|
||||
else:
|
||||
secondary = None
|
||||
|
||||
r_val = assign_bchances(card, PLAY_RESULTS['do***'], ch, secondary)
|
||||
logger.debug(f'Returned batting chances: {r_val[0]} / {r_val[1]}\n')
|
||||
res_chances -= r_val[0]
|
||||
new_ratings.double_three += r_val[0]
|
||||
if r_val[1] > 0:
|
||||
if 'DO (' in secondary.short_name:
|
||||
data.double_pull -= r_val[1]
|
||||
new_ratings.double_pull += r_val[1]
|
||||
elif 'lf' in secondary.short_name:
|
||||
data.flyout_lf_b -= r_val[1]
|
||||
new_ratings.flyout_lf_b += r_val[1]
|
||||
elif 'rf' in secondary.short_name:
|
||||
data.flyout_rf_b -= r_val[1]
|
||||
new_ratings.flyout_rf_b += r_val[1]
|
||||
elif 'SI' in secondary.short_name:
|
||||
data.single_two -= r_val[1]
|
||||
new_ratings.single_two += r_val[1]
|
||||
elif '**' in secondary.short_name:
|
||||
data.double_two -= r_val[1]
|
||||
new_ratings.double_two += r_val[1]
|
||||
|
||||
if r_val[0] == 0:
|
||||
retries += 1
|
||||
|
||||
# Double pull-side
|
||||
retries = 0
|
||||
res_chances = data.double_pull
|
||||
while res_chances > 0:
|
||||
if res_chances < 1 or retries > 0:
|
||||
if data.double_two > 0:
|
||||
data.double_two += res_chances
|
||||
elif data.single_two > 0:
|
||||
data.single_two += res_chances
|
||||
elif data.single_center > 0:
|
||||
data.single_center += res_chances
|
||||
elif data.single_one > 0:
|
||||
data.single_one += res_chances
|
||||
break
|
||||
|
||||
ch = get_chances(res_chances)
|
||||
if data.flyout_lf_b > max(1 - ch, 0):
|
||||
secondary = PlayResult(full_name=f'fly (lf) B', short_name=f'fly B')
|
||||
elif data.flyout_rf_b > max(1 - ch, 0):
|
||||
secondary = PlayResult(full_name=f'fly (rf) B', short_name=f'fly b')
|
||||
elif data.single_one > max(1 - ch, 0):
|
||||
secondary = PLAY_RESULTS['si*']
|
||||
elif data.single_two > max(1 - ch, 0):
|
||||
secondary = PLAY_RESULTS['si**']
|
||||
else:
|
||||
secondary = None
|
||||
|
||||
r_val = assign_bchances(card, PLAY_RESULTS[f'do-{pull_of}'], ch, secondary)
|
||||
logger.debug(f'Returned batting chances: {r_val[0]} / {r_val[1]}\n')
|
||||
res_chances -= r_val[0]
|
||||
new_ratings.double_pull += r_val[0]
|
||||
if r_val[1] > 0:
|
||||
if 'lf' in secondary.full_name:
|
||||
data.flyout_lf_b -= r_val[1]
|
||||
new_ratings.flyout_lf_b += r_val[1]
|
||||
elif 'rf' in secondary.full_name:
|
||||
data.flyout_rf_b -= r_val[1]
|
||||
new_ratings.flyout_rf_b += r_val[1]
|
||||
elif '***' in secondary.short_name:
|
||||
data.double_three -= r_val[1]
|
||||
new_ratings.double_three += r_val[1]
|
||||
elif 'SI' in secondary.short_name:
|
||||
data.single_two -= r_val[1]
|
||||
new_ratings.single_two += r_val[1]
|
||||
elif '**' in secondary.short_name:
|
||||
data.double_two -= r_val[1]
|
||||
new_ratings.double_two += r_val[1]
|
||||
|
||||
if r_val[0] == 0:
|
||||
retries += 1
|
||||
|
||||
# Double**
|
||||
retries = 0
|
||||
res_chances = data.double_two
|
||||
while res_chances > 0:
|
||||
if res_chances < 1 or retries > 0:
|
||||
if data.single_two > 0:
|
||||
data.single_two += res_chances
|
||||
elif data.single_center > 0:
|
||||
data.single_center += res_chances
|
||||
elif data.single_one > 0:
|
||||
data.single_one += res_chances
|
||||
elif data.walk > 0:
|
||||
data.walk += res_chances
|
||||
break
|
||||
|
||||
ch = get_chances(res_chances)
|
||||
if data.single_two > max(1 - ch, 0):
|
||||
secondary = PLAY_RESULTS['si**']
|
||||
elif data.single_center > max(1 - ch, 0):
|
||||
secondary = PLAY_RESULTS['si-cf']
|
||||
elif data.flyout_lf_b > max(1 - ch, 0):
|
||||
secondary = PLAY_RESULTS['fly-lf']
|
||||
elif data.flyout_rf_b > max(1 - ch, 0):
|
||||
secondary = PLAY_RESULTS['fly-rf']
|
||||
else:
|
||||
secondary = None
|
||||
|
||||
r_val = assign_bchances(card, PLAY_RESULTS['do**'], ch, secondary)
|
||||
logger.debug(f'Returned batting chances: {r_val[0]} / {r_val[1]}\n')
|
||||
res_chances -= r_val[0]
|
||||
new_ratings.double_two += r_val[0]
|
||||
if r_val[1] > 0:
|
||||
if 'lf' in secondary.full_name:
|
||||
data.flyout_lf_b -= r_val[1]
|
||||
new_ratings.flyout_lf_b += r_val[1]
|
||||
elif 'rf' in secondary.full_name:
|
||||
data.flyout_rf_b -= r_val[1]
|
||||
new_ratings.flyout_rf_b += r_val[1]
|
||||
elif 'SI' in secondary.short_name:
|
||||
data.single_two -= r_val[1]
|
||||
new_ratings.single_two += r_val[1]
|
||||
|
||||
if r_val[0] == 0:
|
||||
retries += 1
|
||||
|
||||
# Single**
|
||||
retries = 0
|
||||
res_chances = data.single_two
|
||||
while res_chances > 0:
|
||||
if res_chances < 1 or retries > 0:
|
||||
if data.single_center > 0:
|
||||
data.single_center += res_chances
|
||||
elif data.single_one > 0:
|
||||
data.single_one += res_chances
|
||||
elif data.walk > 0:
|
||||
data.walk += res_chances
|
||||
break
|
||||
|
||||
ch = get_chances(res_chances)
|
||||
if data.groundout_a > max(1 - ch, 0):
|
||||
secondary = PlayResult(full_name=f'gb ({pref_mif}) A', short_name=f'gb ({pref_mif}) A')
|
||||
elif data.groundout_b > max(1 - ch, 0):
|
||||
secondary = PlayResult(full_name=f'gb ({pref_mif}) B', short_name=f'gb ({pref_mif}) B')
|
||||
elif data.groundout_c > max(1 - ch, 0):
|
||||
secondary = PlayResult(full_name=f'gb ({pref_mif}) C', short_name=f'gb ({pref_mif}) C')
|
||||
elif data.lineout > max(1 - ch, 0):
|
||||
secondary = PlayResult(full_name=f'lo ({pref_mif})', short_name=f'lo ({pref_mif})')
|
||||
else:
|
||||
secondary = None
|
||||
|
||||
r_val = assign_bchances(card, PLAY_RESULTS['si**'], ch, secondary)
|
||||
logger.debug(f'Returned batting chances: {r_val[0]} / {r_val[1]}\n')
|
||||
res_chances -= r_val[0]
|
||||
new_ratings.single_two += r_val[0]
|
||||
if r_val[1] > 0:
|
||||
if 'C' in secondary.short_name:
|
||||
data.groundout_c -= r_val[1]
|
||||
new_ratings.groundout_c += r_val[1]
|
||||
elif 'B' in secondary.short_name:
|
||||
data.groundout_b -= r_val[1]
|
||||
new_ratings.groundout_b += r_val[1]
|
||||
elif 'A' in secondary.short_name:
|
||||
data.groundout_a -= r_val[1]
|
||||
new_ratings.groundout_a += r_val[1]
|
||||
elif 'lo' in secondary.short_name:
|
||||
data.lineout -= r_val[1]
|
||||
new_ratings.lineout += r_val[1]
|
||||
|
||||
if r_val[0] == 0:
|
||||
retries += 1
|
||||
|
||||
# Single (cf)
|
||||
retries = 0
|
||||
res_chances = data.single_center
|
||||
while res_chances > 0:
|
||||
if res_chances < 1 or retries > 0:
|
||||
if data.single_one > 0:
|
||||
data.single_one += res_chances
|
||||
elif data.walk > 0:
|
||||
data.walk += res_chances
|
||||
break
|
||||
|
||||
ch = get_chances(res_chances)
|
||||
if data.flyout_bq > max(1 - ch, 0):
|
||||
secondary = PlayResult(full_name=f'fly B?', short_name=f'fly B?')
|
||||
elif data.flyout_lf_b > max(1 - ch, 0) and data.flyout_lf_b > data.flyout_rf_b:
|
||||
secondary = PlayResult(full_name=f'fly (LF) B', short_name=f'fly B')
|
||||
elif data.flyout_rf_b > max(1 - ch, 0):
|
||||
secondary = PlayResult(full_name=f'fly (RF) B', short_name=f'fly B')
|
||||
elif data.flyout_lf_b > max(1 - ch, 0):
|
||||
secondary = PlayResult(full_name=f'fly (LF) B', short_name=f'fly B')
|
||||
elif data.lineout > max(1 - ch, 0):
|
||||
secondary = PlayResult(full_name=f'lo ({pref_mif})', short_name=f'lo ({pref_mif})')
|
||||
else:
|
||||
secondary = None
|
||||
|
||||
r_val = assign_bchances(card, PLAY_RESULTS['si-cf'], ch, secondary)
|
||||
logger.debug(f'Returned batting chances: {r_val[0]} / {r_val[1]}\n')
|
||||
res_chances -= r_val[0]
|
||||
new_ratings.single_center += r_val[0]
|
||||
if r_val[1] > 0:
|
||||
if '?' in secondary.short_name:
|
||||
data.flyout_bq -= r_val[1]
|
||||
new_ratings.flyout_bq += r_val[1]
|
||||
elif 'LF' in secondary.full_name:
|
||||
data.flyout_lf_b -= r_val[1]
|
||||
new_ratings.flyout_lf_b += r_val[1]
|
||||
elif 'RF' in secondary.full_name:
|
||||
data.flyout_rf_b -= r_val[1]
|
||||
new_ratings.flyout_rf_b += r_val[1]
|
||||
elif 'lo' in secondary.short_name:
|
||||
data.lineout -= r_val[1]
|
||||
new_ratings.lineout += r_val[1]
|
||||
|
||||
if r_val[0] == 0:
|
||||
retries += 1
|
||||
|
||||
# Single*
|
||||
retries = 0
|
||||
res_chances = data.single_one
|
||||
while res_chances > 0:
|
||||
if res_chances < 1 or retries > 0:
|
||||
if data.walk > 0:
|
||||
data.walk += res_chances
|
||||
break
|
||||
|
||||
ch = get_chances(res_chances)
|
||||
if data.groundout_c > max(1 - ch, 0):
|
||||
secondary = PlayResult(full_name=f'gb ({pref_mif}) C', short_name=f'gb ({pref_mif}) C')
|
||||
elif data.groundout_b > max(1 - ch, 0):
|
||||
secondary = PlayResult(full_name=f'gb ({pref_mif}) B', short_name=f'gb ({pref_mif}) B')
|
||||
elif data.groundout_a > max(1 - ch, 0):
|
||||
secondary = PlayResult(full_name=f'gb ({pref_mif}) A', short_name=f'gb ({pref_mif}) A')
|
||||
elif data.lineout > max(1 - ch, 0):
|
||||
secondary = PlayResult(full_name=f'lo ({pref_mif})', short_name=f'lo ({pref_mif})')
|
||||
else:
|
||||
secondary = None
|
||||
|
||||
r_val = assign_bchances(card, PLAY_RESULTS['si*'], ch, secondary)
|
||||
logger.debug(f'Returned batting chances: {r_val[0]} / {r_val[1]}\n')
|
||||
res_chances -= r_val[0]
|
||||
new_ratings.single_one += r_val[0]
|
||||
if r_val[1] > 0:
|
||||
if 'C' in secondary.short_name:
|
||||
data.groundout_c -= r_val[1]
|
||||
new_ratings.groundout_c += r_val[1]
|
||||
elif 'B' in secondary.short_name:
|
||||
data.groundout_b -= r_val[1]
|
||||
new_ratings.groundout_b += r_val[1]
|
||||
elif 'A' in secondary.short_name:
|
||||
data.groundout_a -= r_val[1]
|
||||
new_ratings.groundout_a += r_val[1]
|
||||
elif 'lo' in secondary.short_name:
|
||||
data.lineout -= r_val[1]
|
||||
new_ratings.lineout += r_val[1]
|
||||
|
||||
if r_val[0] == 0:
|
||||
retries += 1
|
||||
|
||||
# Walk
|
||||
retries = 0
|
||||
res_chances = data.walk
|
||||
while res_chances >= 1:
|
||||
if res_chances < 1 or retries > 0:
|
||||
break
|
||||
|
||||
ch = get_chances(res_chances)
|
||||
if data.strikeout > max(1 - ch, 0):
|
||||
secondary = PlayResult(full_name=f'strikeout', short_name=f'so')
|
||||
else:
|
||||
secondary = None
|
||||
|
||||
r_val = assign_bchances(card, PLAY_RESULTS['walk'], ch, secondary)
|
||||
logger.debug(f'Returned batting chances: {r_val[0]} / {r_val[1]}\n')
|
||||
res_chances -= r_val[0]
|
||||
new_ratings.walk += r_val[0]
|
||||
if r_val[1] > 0:
|
||||
data.strikeout -= r_val[1]
|
||||
new_ratings.strikeout += r_val[1]
|
||||
|
||||
if r_val[0] == 0:
|
||||
retries += 1
|
||||
|
||||
# BP Single
|
||||
retries = 0
|
||||
res_chances = data.bp_single
|
||||
while res_chances > 0:
|
||||
if res_chances < 1 or retries > 0:
|
||||
break
|
||||
|
||||
ch = get_chances(res_chances)
|
||||
r_val = assign_bchances(card, PLAY_RESULTS['bp-si'], ch)
|
||||
logger.debug(f'Returned batting chances: {r_val[0]} / {r_val[1]}\n')
|
||||
res_chances -= r_val[0]
|
||||
new_ratings.bp_single += r_val[0]
|
||||
|
||||
if r_val[0] == 0:
|
||||
retries += 1
|
||||
|
||||
# Special lomax result
|
||||
r_val = assign_bchances(
|
||||
card, PlayResult(full_name=f'lo ({pref_mif}) max', short_name=f'lo ({pref_mif}) max'), Decimal(1))
|
||||
logger.debug(f'Returned batting chances: {r_val[0]} / {r_val[1]}\n')
|
||||
data.lineout -= r_val[0]
|
||||
new_ratings.lineout += r_val[0]
|
||||
|
||||
# Popout
|
||||
retries = 0
|
||||
res_chances = data.popout
|
||||
while res_chances >= 1:
|
||||
if res_chances < 1 or retries > 0:
|
||||
break
|
||||
|
||||
ch = get_chances(res_chances)
|
||||
this_if = '2b' if pref_mif == 'ss' else 'ss'
|
||||
r_val = assign_bchances(
|
||||
card,
|
||||
PlayResult(full_name=f'popout ({this_if})', short_name=f'popout ({this_if})'),
|
||||
Decimal(math.floor(ch))
|
||||
)
|
||||
logger.debug(f'Returned batting chances: {r_val[0]} / {r_val[1]}\n')
|
||||
|
||||
if r_val[0] == 0:
|
||||
data.lineout += res_chances
|
||||
break
|
||||
else:
|
||||
res_chances -= r_val[0]
|
||||
new_ratings.popout += r_val[0]
|
||||
|
||||
# Flyout A
|
||||
retries = 0
|
||||
res_chances = data.flyout_a
|
||||
while res_chances >= 1:
|
||||
if res_chances < 1 or retries > 0:
|
||||
break
|
||||
|
||||
ch = get_chances(res_chances)
|
||||
r_val = assign_bchances(
|
||||
card, PlayResult(full_name=f'fly (cf) A', short_name=f'fly (cf) A'), Decimal(math.floor(ch)))
|
||||
logger.debug(f'Returned batting chances: {r_val[0]} / {r_val[1]}\n')
|
||||
|
||||
if r_val[0] == 0:
|
||||
data.strikeout += res_chances if data.strikeout > 2 else 0
|
||||
break
|
||||
else:
|
||||
res_chances -= r_val[0]
|
||||
new_ratings.flyout_a += r_val[0]
|
||||
|
||||
# Flyout LF B
|
||||
retries = 0
|
||||
res_chances = data.flyout_lf_b
|
||||
while res_chances >= 1:
|
||||
if res_chances < 1 or retries > 0:
|
||||
break
|
||||
|
||||
ch = get_chances(res_chances)
|
||||
r_val = assign_bchances(
|
||||
card, PlayResult(full_name=f'fly (lf) B', short_name=f'fly (lf) B'), Decimal(math.floor(ch)))
|
||||
logger.debug(f'Returned batting chances: {r_val[0]} / {r_val[1]}\n')
|
||||
|
||||
if r_val[0] == 0:
|
||||
data.strikeout += res_chances if data.strikeout > 2 else 0
|
||||
break
|
||||
else:
|
||||
res_chances -= r_val[0]
|
||||
new_ratings.flyout_lf_b += r_val[0]
|
||||
|
||||
# Flyout RF B
|
||||
retries = 0
|
||||
res_chances = data.flyout_rf_b
|
||||
while res_chances >= 1:
|
||||
if res_chances < 1 or retries > 0:
|
||||
break
|
||||
|
||||
ch = get_chances(res_chances)
|
||||
r_val = assign_bchances(
|
||||
card, PlayResult(full_name=f'fly (rf) B', short_name=f'fly (rf) B'), Decimal(math.floor(ch)))
|
||||
logger.debug(f'Returned batting chances: {r_val[0]} / {r_val[1]}\n')
|
||||
|
||||
if r_val[0] == 0:
|
||||
data.strikeout += res_chances if data.strikeout > 2 else 0
|
||||
break
|
||||
else:
|
||||
res_chances -= r_val[0]
|
||||
new_ratings.flyout_rf_b += r_val[0]
|
||||
|
||||
# Groundout A
|
||||
count_gb = 0
|
||||
|
||||
def get_gb_if():
|
||||
if count_gb % 4 == 1:
|
||||
return pref_mif
|
||||
elif count_gb % 4 == 2:
|
||||
return '2b' if pref_mif == 'ss' else 'ss'
|
||||
elif count_gb % 4 == 3:
|
||||
return '1b' if pref_mif == '2b' else 'p'
|
||||
else:
|
||||
return '3b' if pref_mif == 'ss' else 'p'
|
||||
|
||||
retries = 0
|
||||
res_chances = data.groundout_a
|
||||
while res_chances >= 1:
|
||||
if res_chances < 1 or retries > 0:
|
||||
break
|
||||
|
||||
count_gb += 1
|
||||
this_if = get_gb_if()
|
||||
ch = get_chances(res_chances)
|
||||
r_val = assign_bchances(
|
||||
card, PlayResult(full_name=f'gb ({this_if}) A', short_name=f'gb ({this_if}) A'),
|
||||
Decimal(math.floor(ch)))
|
||||
logger.debug(f'Returned batting chances: {r_val[0]} / {r_val[1]}\n')
|
||||
|
||||
if r_val[0] == 0:
|
||||
data.groundout_b += res_chances
|
||||
break
|
||||
else:
|
||||
res_chances -= r_val[0]
|
||||
new_ratings.groundout_a += r_val[0]
|
||||
|
||||
# Groundout B
|
||||
retries = 0
|
||||
res_chances = data.groundout_b
|
||||
while res_chances >= 1:
|
||||
if res_chances < 1 or retries > 0:
|
||||
break
|
||||
|
||||
count_gb += 1
|
||||
this_if = get_gb_if()
|
||||
ch = get_chances(res_chances)
|
||||
r_val = assign_bchances(
|
||||
card, PlayResult(full_name=f'gb ({this_if}) B', short_name=f'gb ({this_if}) B'),
|
||||
Decimal(math.floor(ch)))
|
||||
logger.debug(f'Returned batting chances: {r_val[0]} / {r_val[1]}\n')
|
||||
|
||||
if r_val[0] == 0:
|
||||
data.groundout_c += res_chances
|
||||
break
|
||||
else:
|
||||
res_chances -= r_val[0]
|
||||
new_ratings.groundout_b += r_val[0]
|
||||
|
||||
# Groundout C
|
||||
retries = 0
|
||||
res_chances = data.groundout_c
|
||||
while res_chances >= 1:
|
||||
if res_chances < 1 or retries > 0:
|
||||
break
|
||||
|
||||
count_gb += 1
|
||||
this_if = get_gb_if()
|
||||
ch = get_chances(res_chances)
|
||||
r_val = assign_bchances(
|
||||
card, PlayResult(full_name=f'gb ({this_if}) C', short_name=f'gb ({this_if}) C'),
|
||||
Decimal(math.floor(ch)))
|
||||
logger.debug(f'Returned batting chances: {r_val[0]} / {r_val[1]}\n')
|
||||
|
||||
if r_val[0] == 0:
|
||||
data.strikeout += res_chances
|
||||
break
|
||||
else:
|
||||
res_chances -= r_val[0]
|
||||
new_ratings.groundout_c += r_val[0]
|
||||
|
||||
# Lineout
|
||||
retries = 0
|
||||
res_chances = data.lineout
|
||||
while res_chances >= 1:
|
||||
if res_chances < 1 or retries > 0:
|
||||
break
|
||||
|
||||
ch = get_chances(res_chances)
|
||||
this_if = '3b' if pref_mif == 'ss' else '1b'
|
||||
r_val = assign_bchances(
|
||||
card,
|
||||
PlayResult(full_name=f'lineout ({this_if})', short_name=f'lineout ({this_if})'),
|
||||
Decimal(math.floor(ch))
|
||||
)
|
||||
logger.debug(f'Returned batting chances: {r_val[0]} / {r_val[1]}\n')
|
||||
|
||||
if r_val[0] == 0:
|
||||
break
|
||||
else:
|
||||
res_chances -= r_val[0]
|
||||
new_ratings.lineout += r_val[0]
|
||||
|
||||
# Strikeout
|
||||
retries = 0
|
||||
res_chances = data.strikeout
|
||||
while res_chances >= 1:
|
||||
if res_chances < 1 or retries > 0:
|
||||
break
|
||||
|
||||
ch = get_chances(res_chances)
|
||||
r_val = assign_bchances(
|
||||
card, PlayResult(full_name=f'strikeout', short_name=f'strikeout'), Decimal(math.floor(ch)))
|
||||
logger.debug(f'Returned batting chances: {r_val[0]} / {r_val[1]}\n')
|
||||
|
||||
if r_val[0] == 0:
|
||||
break
|
||||
else:
|
||||
res_chances -= r_val[0]
|
||||
new_ratings.strikeout += r_val[0]
|
||||
|
||||
# Filler loop — fill any remaining empty card slots
|
||||
plays = sorted(
|
||||
[(data.strikeout, 'so'), (data.lineout, 'lo'), (data.groundout_c, 'gb'), (data.popout, 'po')],
|
||||
key=lambda z: z[0],
|
||||
reverse=True
|
||||
)
|
||||
count_filler = -1
|
||||
while not card.is_complete():
|
||||
count_filler += 1
|
||||
this_play = plays[count_filler % 4]
|
||||
if this_play[1] == 'so':
|
||||
play_res = PlayResult(full_name=f'strikeout', short_name=f'strikeout')
|
||||
elif this_play[1] == 'lo':
|
||||
this_if = '3b' if pref_mif == 'ss' else '1b'
|
||||
play_res = PlayResult(full_name=f'lineout ({this_if})', short_name=f'lineout ({this_if})')
|
||||
elif this_play[1] == 'gb':
|
||||
count_gb += 1
|
||||
this_if = get_gb_if()
|
||||
play_res = PlayResult(full_name=f'gb ({this_if}) C', short_name=f'gb ({this_if}) C')
|
||||
else:
|
||||
play_res = PlayResult(full_name=f'popout (c)', short_name=f'popout (c)')
|
||||
|
||||
logger.debug(f'Send Card Fill\n{play_res}')
|
||||
r_raw = card.card_fill(play_res)
|
||||
r_val = (float(r_raw[0]), float(r_raw[1]))
|
||||
logger.debug(f'Returned batting chances: {r_val[0]} / {r_val[1]}\n')
|
||||
|
||||
if this_play[1] == 'so':
|
||||
new_ratings.strikeout += r_val[0]
|
||||
elif this_play[1] == 'lo':
|
||||
new_ratings.lineout += r_val[0]
|
||||
elif this_play[1] == 'gb':
|
||||
new_ratings.groundout_c += r_val[0]
|
||||
else:
|
||||
new_ratings.popout += r_val[0]
|
||||
|
||||
new_ratings.calculate_rate_stats()
|
||||
|
||||
return vl, vr
|
||||
1015
card_layout.py
Normal file
1015
card_layout.py
Normal file
File diff suppressed because it is too large
Load Diff
@ -376,7 +376,20 @@ def get_pitcher_ratings(df_data) -> List[dict]:
|
||||
logger.info(f'vL: Total chances: {vl.total_chances()}')
|
||||
logger.info(f'vR: Total chances: {vr.total_chances()}')
|
||||
|
||||
return [vl.custom_to_dict(), vr.custom_to_dict()]
|
||||
vl_dict = vl.custom_to_dict()
|
||||
vr_dict = vr.custom_to_dict()
|
||||
|
||||
try:
|
||||
from pitchers.card_builder import build_pitcher_full_cards
|
||||
vl_card, vr_card = build_pitcher_full_cards(
|
||||
vl, vr, int(df_data['offense_col']), int(df_data['player_id']), df_data['pitch_hand']
|
||||
)
|
||||
vl_dict.update(vl_card.card_output())
|
||||
vr_dict.update(vr_card.card_output())
|
||||
except Exception as e:
|
||||
logger.warning(f'Card layout builder failed for {df_data.name}: {e}')
|
||||
|
||||
return [vl_dict, vr_dict]
|
||||
|
||||
|
||||
def total_chances(chance_data):
|
||||
|
||||
712
pitchers/card_builder.py
Normal file
712
pitchers/card_builder.py
Normal file
@ -0,0 +1,712 @@
|
||||
import copy
|
||||
import math
|
||||
import logging
|
||||
from decimal import Decimal
|
||||
|
||||
from card_layout import FullPitchingCard, PLAY_RESULTS, PlayResult, EXACT_CHANCES, get_chances
|
||||
from pitchers.calcs_pitcher import PitchingCardRatingsModel
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def build_pitcher_full_cards(
|
||||
ratings_vl: PitchingCardRatingsModel,
|
||||
ratings_vr: PitchingCardRatingsModel,
|
||||
offense_col: int,
|
||||
player_id: int,
|
||||
hand: str,
|
||||
) -> tuple:
|
||||
"""Build vL and vR FullPitchingCard objects from pre-calculated ratings.
|
||||
|
||||
Returns (vl_card, vr_card).
|
||||
"""
|
||||
player_binary = player_id % 2
|
||||
|
||||
vl = FullPitchingCard(offense_col=offense_col, alt_direction=player_binary)
|
||||
vr = FullPitchingCard(offense_col=offense_col, alt_direction=player_binary)
|
||||
|
||||
def assign_pchances(this_card, play, chances, secondary_play=None):
|
||||
r_data = this_card.add_result(play, chances, secondary_play)
|
||||
if r_data:
|
||||
return float(r_data[0]), float(r_data[1])
|
||||
else:
|
||||
for x in EXACT_CHANCES + [Decimal('0.95')]:
|
||||
if x < math.floor(chances - Decimal('0.05')):
|
||||
r_data = this_card.add_result(play, Decimal(math.floor(chances)), secondary_play)
|
||||
if r_data:
|
||||
return float(r_data[0]), float(r_data[1])
|
||||
break
|
||||
if x < chances and secondary_play is not None:
|
||||
r_data = this_card.add_result(play, x, secondary_play)
|
||||
if r_data:
|
||||
return float(r_data[0]), float(r_data[1])
|
||||
return 0, 0
|
||||
|
||||
def get_preferred_mif(ratings):
|
||||
if hand == 'L' and ratings.vs_hand == 'L':
|
||||
return 'ss'
|
||||
elif hand == 'L' or (hand == 'R' and ratings.vs_hand == 'R'):
|
||||
return '2b'
|
||||
else:
|
||||
return 'ss'
|
||||
|
||||
for card, data, vs_hand in [
|
||||
(vl, copy.deepcopy(ratings_vl), 'L'),
|
||||
(vr, copy.deepcopy(ratings_vr), 'R'),
|
||||
]:
|
||||
new_ratings = PitchingCardRatingsModel(
|
||||
pitchingcard_id=data.pitchingcard_id,
|
||||
pit_hand=data.pit_hand,
|
||||
vs_hand=vs_hand,
|
||||
hard_rate=data.hard_rate,
|
||||
med_rate=data.med_rate,
|
||||
soft_rate=data.soft_rate,
|
||||
xcheck_p=0.0, xcheck_c=0.0, xcheck_1b=0.0, xcheck_2b=0.0,
|
||||
xcheck_3b=0.0, xcheck_ss=0.0, xcheck_lf=0.0, xcheck_cf=0.0, xcheck_rf=0.0,
|
||||
)
|
||||
|
||||
res_chances = data.bp_homerun
|
||||
while res_chances > 0:
|
||||
ch = get_chances(res_chances)
|
||||
r_val = assign_pchances(card, PLAY_RESULTS['bp-hr'], ch)
|
||||
res_chances -= r_val[0]
|
||||
new_ratings.bp_homerun += r_val[0]
|
||||
|
||||
res_chances = data.hbp
|
||||
while res_chances > 0:
|
||||
ch = get_chances(res_chances)
|
||||
r_val = assign_pchances(card, PlayResult(full_name='HBP', short_name='HBP'), ch)
|
||||
res_chances -= r_val[0]
|
||||
new_ratings.hbp += r_val[0]
|
||||
if r_val[0] == 0:
|
||||
break
|
||||
|
||||
res_chances = data.xcheck_p
|
||||
while res_chances > 0:
|
||||
ch = get_chances(res_chances)
|
||||
r_val = assign_pchances(card, PlayResult(full_name='GB (p) X', short_name='GB (p) X'), ch)
|
||||
res_chances -= r_val[0]
|
||||
new_ratings.xcheck_p += r_val[0]
|
||||
|
||||
res_chances = data.xcheck_c
|
||||
while res_chances > 0:
|
||||
ch = get_chances(res_chances)
|
||||
r_val = assign_pchances(card, PlayResult(full_name='CATCH X', short_name='CATCH X'), ch)
|
||||
res_chances -= r_val[0]
|
||||
new_ratings.xcheck_c += r_val[0]
|
||||
|
||||
res_chances = data.xcheck_1b
|
||||
while res_chances > 0:
|
||||
ch = get_chances(res_chances)
|
||||
r_val = assign_pchances(card, PlayResult(full_name='GB (1b) X', short_name='GB (1b) X'), ch)
|
||||
res_chances -= r_val[0]
|
||||
new_ratings.xcheck_1b += r_val[0]
|
||||
|
||||
res_chances = data.xcheck_3b
|
||||
while res_chances > 0:
|
||||
ch = get_chances(res_chances)
|
||||
r_val = assign_pchances(card, PlayResult(full_name='GB (3b) X', short_name='GB (3b) X'), ch)
|
||||
res_chances -= r_val[0]
|
||||
new_ratings.xcheck_3b += r_val[0]
|
||||
|
||||
res_chances = data.xcheck_rf
|
||||
while res_chances > 0:
|
||||
ch = get_chances(res_chances)
|
||||
r_val = assign_pchances(card, PlayResult(full_name='FLY (rf) X', short_name='FLY (rf) X'), ch)
|
||||
res_chances -= r_val[0]
|
||||
new_ratings.xcheck_rf += r_val[0]
|
||||
|
||||
res_chances = data.xcheck_lf
|
||||
while res_chances > 0:
|
||||
ch = get_chances(res_chances)
|
||||
r_val = assign_pchances(card, PlayResult(full_name='FLY (lf) X', short_name='FLY (lf) X'), ch)
|
||||
res_chances -= r_val[0]
|
||||
new_ratings.xcheck_lf += r_val[0]
|
||||
|
||||
res_chances = data.xcheck_2b
|
||||
while res_chances > 0:
|
||||
ch = get_chances(res_chances)
|
||||
r_val = assign_pchances(card, PlayResult(full_name='GB (2b) X', short_name='GB (2b) X'), ch)
|
||||
res_chances -= r_val[0]
|
||||
new_ratings.xcheck_2b += r_val[0]
|
||||
|
||||
res_chances = data.xcheck_cf
|
||||
while res_chances > 0:
|
||||
ch = get_chances(res_chances)
|
||||
r_val = assign_pchances(card, PlayResult(full_name='FLY (cf) X', short_name='FLY (cf) X'), ch)
|
||||
res_chances -= r_val[0]
|
||||
new_ratings.xcheck_cf += r_val[0]
|
||||
|
||||
res_chances = data.xcheck_ss
|
||||
while res_chances > 0:
|
||||
ch = get_chances(res_chances)
|
||||
r_val = assign_pchances(card, PlayResult(full_name='GB (ss) X', short_name='GB (ss) X'), ch)
|
||||
res_chances -= r_val[0]
|
||||
new_ratings.xcheck_ss += r_val[0]
|
||||
|
||||
res_chances = data.walk
|
||||
while res_chances >= 1:
|
||||
ch = get_chances(res_chances)
|
||||
if data.strikeout > max(1 - ch, 0):
|
||||
secondary = PlayResult(full_name='strikeout', short_name='so')
|
||||
else:
|
||||
secondary = None
|
||||
|
||||
r_val = assign_pchances(card, PLAY_RESULTS['walk'], ch, secondary)
|
||||
res_chances -= r_val[0]
|
||||
new_ratings.walk += r_val[0]
|
||||
if r_val[1] > 0:
|
||||
data.strikeout -= r_val[1]
|
||||
new_ratings.strikeout += r_val[1]
|
||||
|
||||
if r_val[0] == 0:
|
||||
break
|
||||
|
||||
res_chances = data.homerun
|
||||
retries = 0
|
||||
while res_chances > 0:
|
||||
if res_chances < 1 or retries > 0:
|
||||
if data.double_cf > 0:
|
||||
data.double_cf += res_chances
|
||||
elif data.double_two > 0:
|
||||
data.double_two += res_chances
|
||||
elif data.triple > 0:
|
||||
data.triple += res_chances
|
||||
elif data.single_two > 0:
|
||||
data.single_two += res_chances
|
||||
elif data.single_center > 0:
|
||||
data.single_center += res_chances
|
||||
elif data.single_center > 0:
|
||||
data.single_center += res_chances
|
||||
break
|
||||
|
||||
ch = get_chances(res_chances)
|
||||
if data.double_cf > (data.flyout_rf_b + data.flyout_lf_b) and data.double_cf > max(1 - ch, 0):
|
||||
secondary = PLAY_RESULTS['do-cf']
|
||||
elif data.flyout_cf_b > max(1 - ch, 0):
|
||||
secondary = PLAY_RESULTS['fly-cf']
|
||||
elif data.flyout_lf_b > data.flyout_rf_b and data.flyout_lf_b > max(1 - ch, 0):
|
||||
secondary = PLAY_RESULTS['fly-lf']
|
||||
elif data.flyout_rf_b > max(1 - ch, 0):
|
||||
secondary = PLAY_RESULTS['fly-rf']
|
||||
elif data.double_cf > max(1 - ch, 0):
|
||||
secondary = PLAY_RESULTS['do-cf']
|
||||
elif data.double_three > max(1 - ch, 0):
|
||||
secondary = PLAY_RESULTS['do***']
|
||||
elif data.double_two > max(1 - ch, 0):
|
||||
secondary = PLAY_RESULTS['do**']
|
||||
elif data.triple > max(1 - ch, 0):
|
||||
secondary = PLAY_RESULTS['tr']
|
||||
else:
|
||||
secondary = None
|
||||
|
||||
r_val = assign_pchances(card, PLAY_RESULTS['hr'], ch, secondary)
|
||||
res_chances -= r_val[0]
|
||||
new_ratings.homerun += r_val[0]
|
||||
if r_val[1] > 0:
|
||||
if 'DO (' in secondary.short_name:
|
||||
data.double_cf -= r_val[1]
|
||||
new_ratings.double_cf += r_val[1]
|
||||
elif 'lf' in secondary.short_name:
|
||||
data.flyout_lf_b -= r_val[1]
|
||||
new_ratings.flyout_lf_b += r_val[1]
|
||||
elif 'cf' in secondary.short_name:
|
||||
data.flyout_cf_b -= r_val[1]
|
||||
new_ratings.flyout_cf_b += r_val[1]
|
||||
elif 'rf' in secondary.short_name:
|
||||
data.flyout_rf_b -= r_val[1]
|
||||
new_ratings.flyout_rf_b += r_val[1]
|
||||
elif '***' in secondary.short_name:
|
||||
data.double_three -= r_val[1]
|
||||
new_ratings.double_three += r_val[1]
|
||||
elif '**' in secondary.short_name:
|
||||
data.double_two -= r_val[1]
|
||||
new_ratings.double_two += r_val[1]
|
||||
elif 'TR' in secondary.short_name:
|
||||
data.triple -= r_val[1]
|
||||
new_ratings.triple += r_val[1]
|
||||
|
||||
if r_val[0] == 0:
|
||||
retries += 1
|
||||
|
||||
res_chances = data.triple
|
||||
retries = 0
|
||||
while res_chances > 0:
|
||||
if res_chances < 1 or retries > 0:
|
||||
if data.double_cf > 0:
|
||||
data.double_cf += res_chances
|
||||
elif data.double_two > 0:
|
||||
data.double_two += res_chances
|
||||
elif data.single_two > 0:
|
||||
data.single_two += res_chances
|
||||
elif data.single_center > 0:
|
||||
data.single_center += res_chances
|
||||
elif data.single_one > 0:
|
||||
data.single_one += res_chances
|
||||
break
|
||||
|
||||
ch = get_chances(res_chances)
|
||||
if data.single_two > max(1 - ch, 0):
|
||||
secondary = PLAY_RESULTS['si**']
|
||||
elif data.flyout_cf_b > max(1 - ch, 0):
|
||||
secondary = PLAY_RESULTS['fly-cf']
|
||||
elif data.flyout_lf_b > max(1 - ch, 0):
|
||||
secondary = PLAY_RESULTS['fly-lf']
|
||||
elif data.flyout_rf_b > max(1 - ch, 0):
|
||||
secondary = PLAY_RESULTS['fly-rf']
|
||||
elif data.double_cf > max(1 - ch, 0):
|
||||
secondary = PLAY_RESULTS['do-cf']
|
||||
elif data.double_three > max(1 - ch, 0):
|
||||
secondary = PLAY_RESULTS['do***']
|
||||
elif data.double_two > max(1 - ch, 0):
|
||||
secondary = PLAY_RESULTS['do**']
|
||||
else:
|
||||
secondary = None
|
||||
|
||||
r_val = assign_pchances(card, PLAY_RESULTS['tr'], ch, secondary)
|
||||
res_chances -= r_val[0]
|
||||
new_ratings.triple += r_val[0]
|
||||
if r_val[1] > 0:
|
||||
if 'DO (' in secondary.short_name:
|
||||
data.double_cf -= r_val[1]
|
||||
new_ratings.double_cf += r_val[1]
|
||||
elif 'lf' in secondary.short_name:
|
||||
data.flyout_lf_b -= r_val[1]
|
||||
new_ratings.flyout_lf_b += r_val[1]
|
||||
elif 'cf' in secondary.short_name:
|
||||
data.flyout_cf_b -= r_val[1]
|
||||
new_ratings.flyout_cf_b += r_val[1]
|
||||
elif 'rf' in secondary.short_name:
|
||||
data.flyout_rf_b -= r_val[1]
|
||||
new_ratings.flyout_rf_b += r_val[1]
|
||||
elif '***' in secondary.short_name:
|
||||
data.double_three -= r_val[1]
|
||||
new_ratings.double_three += r_val[1]
|
||||
elif 'SI' in secondary.short_name:
|
||||
data.single_two -= r_val[1]
|
||||
new_ratings.single_two += r_val[1]
|
||||
elif '**' in secondary.short_name:
|
||||
data.double_two -= r_val[1]
|
||||
new_ratings.double_two += r_val[1]
|
||||
|
||||
if r_val[0] == 0:
|
||||
retries += 1
|
||||
|
||||
res_chances = data.double_three
|
||||
retries = 0
|
||||
while res_chances > 0:
|
||||
if res_chances < 1 or retries > 0:
|
||||
if data.double_cf > 0:
|
||||
data.double_cf += res_chances
|
||||
elif data.double_two > 0:
|
||||
data.double_two += res_chances
|
||||
elif data.single_two > 0:
|
||||
data.single_two += res_chances
|
||||
elif data.single_center > 0:
|
||||
data.single_center += res_chances
|
||||
elif data.single_one > 0:
|
||||
data.single_one += res_chances
|
||||
break
|
||||
|
||||
ch = get_chances(res_chances)
|
||||
if data.single_two > max(1 - ch, 0):
|
||||
secondary = PLAY_RESULTS['si**']
|
||||
elif data.flyout_cf_b > max(1 - ch, 0):
|
||||
secondary = PLAY_RESULTS['fly-cf']
|
||||
elif data.flyout_lf_b > max(1 - ch, 0):
|
||||
secondary = PLAY_RESULTS['fly-lf']
|
||||
elif data.flyout_rf_b > max(1 - ch, 0):
|
||||
secondary = PLAY_RESULTS['fly-rf']
|
||||
elif data.double_cf > max(1 - ch, 0):
|
||||
secondary = PLAY_RESULTS['do-cf']
|
||||
elif data.double_two > max(1 - ch, 0):
|
||||
secondary = PLAY_RESULTS['do**']
|
||||
else:
|
||||
secondary = None
|
||||
|
||||
r_val = assign_pchances(card, PLAY_RESULTS['do***'], ch, secondary)
|
||||
res_chances -= r_val[0]
|
||||
new_ratings.double_three += r_val[0]
|
||||
if r_val[1] > 0:
|
||||
if 'DO (' in secondary.short_name:
|
||||
data.double_cf -= r_val[1]
|
||||
new_ratings.double_cf += r_val[1]
|
||||
elif 'lf' in secondary.short_name:
|
||||
data.flyout_lf_b -= r_val[1]
|
||||
new_ratings.flyout_lf_b += r_val[1]
|
||||
elif 'cf' in secondary.short_name:
|
||||
data.flyout_cf_b -= r_val[1]
|
||||
new_ratings.flyout_cf_b += r_val[1]
|
||||
elif 'rf' in secondary.short_name:
|
||||
data.flyout_rf_b -= r_val[1]
|
||||
new_ratings.flyout_rf_b += r_val[1]
|
||||
elif 'SI' in secondary.short_name:
|
||||
data.single_two -= r_val[1]
|
||||
new_ratings.single_two += r_val[1]
|
||||
elif '**' in secondary.short_name:
|
||||
data.double_two -= r_val[1]
|
||||
new_ratings.double_two += r_val[1]
|
||||
|
||||
if r_val[0] == 0:
|
||||
retries += 1
|
||||
|
||||
res_chances = data.double_cf
|
||||
retries = 0
|
||||
while res_chances > 0:
|
||||
if res_chances < 1 or retries > 0:
|
||||
if data.double_two > 0:
|
||||
data.double_two += res_chances
|
||||
elif data.single_two > 0:
|
||||
data.single_two += res_chances
|
||||
elif data.single_center > 0:
|
||||
data.single_center += res_chances
|
||||
elif data.single_one > 0:
|
||||
data.single_one += res_chances
|
||||
break
|
||||
|
||||
ch = get_chances(res_chances)
|
||||
if data.flyout_cf_b > max(1 - ch, 0):
|
||||
secondary = PlayResult(full_name='fly (cf) B', short_name='fly B')
|
||||
elif data.flyout_lf_b > max(1 - ch, 0):
|
||||
secondary = PlayResult(full_name='fly (lf) B', short_name='fly B')
|
||||
elif data.flyout_rf_b > max(1 - ch, 0):
|
||||
secondary = PlayResult(full_name='fly (rf) B', short_name='fly b')
|
||||
elif data.single_one > max(1 - ch, 0):
|
||||
secondary = PLAY_RESULTS['si*']
|
||||
elif data.single_two > max(1 - ch, 0):
|
||||
secondary = PLAY_RESULTS['si**']
|
||||
else:
|
||||
secondary = None
|
||||
|
||||
r_val = assign_pchances(card, PLAY_RESULTS['do-cf'], ch, secondary)
|
||||
res_chances -= r_val[0]
|
||||
new_ratings.double_cf += r_val[0]
|
||||
if r_val[1] > 0:
|
||||
if 'lf' in secondary.full_name:
|
||||
data.flyout_lf_b -= r_val[1]
|
||||
new_ratings.flyout_lf_b += r_val[1]
|
||||
elif 'rf' in secondary.full_name:
|
||||
data.flyout_rf_b -= r_val[1]
|
||||
new_ratings.flyout_rf_b += r_val[1]
|
||||
elif 'cf' in secondary.full_name:
|
||||
data.flyout_cf_b -= r_val[1]
|
||||
new_ratings.flyout_cf_b += r_val[1]
|
||||
elif '***' in secondary.short_name:
|
||||
data.double_three -= r_val[1]
|
||||
new_ratings.double_three += r_val[1]
|
||||
elif 'SI' in secondary.short_name:
|
||||
data.single_two -= r_val[1]
|
||||
new_ratings.single_two += r_val[1]
|
||||
elif '**' in secondary.short_name:
|
||||
data.double_two -= r_val[1]
|
||||
new_ratings.double_two += r_val[1]
|
||||
|
||||
if r_val[0] == 0:
|
||||
retries += 1
|
||||
|
||||
res_chances = data.double_two
|
||||
retries = 0
|
||||
while res_chances > 0:
|
||||
if res_chances < 1 or retries > 0:
|
||||
if data.single_two > 0:
|
||||
data.single_two += res_chances
|
||||
elif data.single_center > 0:
|
||||
data.single_center += res_chances
|
||||
elif data.single_one > 0:
|
||||
data.single_one += res_chances
|
||||
elif data.walk > 0:
|
||||
data.walk += res_chances
|
||||
break
|
||||
|
||||
ch = get_chances(res_chances)
|
||||
if data.single_two > max(1 - ch, 0):
|
||||
secondary = PLAY_RESULTS['si**']
|
||||
elif data.single_center > max(1 - ch, 0):
|
||||
secondary = PLAY_RESULTS['si-cf']
|
||||
elif data.flyout_cf_b > max(1 - ch, 0):
|
||||
secondary = PLAY_RESULTS['fly-cf']
|
||||
elif data.flyout_lf_b > max(1 - ch, 0):
|
||||
secondary = PLAY_RESULTS['fly-lf']
|
||||
elif data.flyout_rf_b > max(1 - ch, 0):
|
||||
secondary = PLAY_RESULTS['fly-rf']
|
||||
else:
|
||||
secondary = None
|
||||
|
||||
r_val = assign_pchances(card, PLAY_RESULTS['do**'], ch, secondary)
|
||||
res_chances -= r_val[0]
|
||||
new_ratings.double_two += r_val[0]
|
||||
if r_val[1] > 0:
|
||||
if 'lf' in secondary.full_name:
|
||||
data.flyout_lf_b -= r_val[1]
|
||||
new_ratings.flyout_lf_b += r_val[1]
|
||||
elif 'rf' in secondary.full_name:
|
||||
data.flyout_rf_b -= r_val[1]
|
||||
new_ratings.flyout_rf_b += r_val[1]
|
||||
elif 'cf' in secondary.full_name:
|
||||
data.flyout_cf_b -= r_val[1]
|
||||
new_ratings.flyout_cf_b += r_val[1]
|
||||
elif 'SI' in secondary.short_name:
|
||||
data.single_two -= r_val[1]
|
||||
new_ratings.single_two += r_val[1]
|
||||
|
||||
if r_val[0] == 0:
|
||||
retries += 1
|
||||
|
||||
res_chances = data.single_two
|
||||
retries = 0
|
||||
while res_chances > 0:
|
||||
if res_chances < 1 or retries > 0:
|
||||
if data.single_center > 0:
|
||||
data.single_center += res_chances
|
||||
elif data.single_one > 0:
|
||||
data.single_one += res_chances
|
||||
elif data.walk > 0:
|
||||
data.walk += res_chances
|
||||
break
|
||||
|
||||
pref_mif = get_preferred_mif(new_ratings)
|
||||
ch = get_chances(res_chances)
|
||||
if data.groundout_a > max(1 - ch, 0):
|
||||
temp_mif = get_preferred_mif(new_ratings)
|
||||
pref_mif = 'ss' if temp_mif == '2b' else '2b'
|
||||
secondary = PlayResult(full_name=f'gb ({pref_mif}) A', short_name=f'gb ({pref_mif}) A')
|
||||
elif data.groundout_b > max(1 - ch, 0):
|
||||
secondary = PlayResult(full_name=f'gb ({pref_mif}) B', short_name=f'gb ({pref_mif}) B')
|
||||
elif data.flyout_cf_b > max(1 - ch, 0):
|
||||
secondary = PLAY_RESULTS['fly-cf']
|
||||
elif data.flyout_lf_b > max(1 - ch, 0):
|
||||
secondary = PLAY_RESULTS['fly-lf']
|
||||
elif data.flyout_rf_b > max(1 - ch, 0):
|
||||
secondary = PLAY_RESULTS['fly-rf']
|
||||
else:
|
||||
secondary = None
|
||||
|
||||
r_val = assign_pchances(card, PLAY_RESULTS['si**'], ch, secondary)
|
||||
res_chances -= r_val[0]
|
||||
new_ratings.single_two += r_val[0]
|
||||
if r_val[1] > 0:
|
||||
if 'B' in secondary.short_name:
|
||||
data.groundout_b -= r_val[1]
|
||||
new_ratings.groundout_b += r_val[1]
|
||||
elif 'A' in secondary.short_name:
|
||||
data.groundout_a -= r_val[1]
|
||||
new_ratings.groundout_a += r_val[1]
|
||||
elif 'lf' in secondary.full_name:
|
||||
data.flyout_lf_b -= r_val[1]
|
||||
new_ratings.flyout_lf_b += r_val[1]
|
||||
elif 'rf' in secondary.full_name:
|
||||
data.flyout_rf_b -= r_val[1]
|
||||
new_ratings.flyout_rf_b += r_val[1]
|
||||
elif 'cf' in secondary.full_name:
|
||||
data.flyout_cf_b -= r_val[1]
|
||||
|
||||
if r_val[0] == 0:
|
||||
retries += 1
|
||||
|
||||
res_chances = data.single_center
|
||||
retries = 0
|
||||
while res_chances > 0:
|
||||
if res_chances < 1 or retries > 0:
|
||||
if data.single_one > 0:
|
||||
data.single_one += res_chances
|
||||
elif data.walk > 0:
|
||||
data.walk += res_chances
|
||||
break
|
||||
|
||||
ch = get_chances(res_chances)
|
||||
if data.flyout_cf_b > max(1 - ch, 0):
|
||||
secondary = PlayResult(full_name='fly (cf) B', short_name='fly B')
|
||||
elif data.flyout_lf_b > max(1 - ch, 0) and data.flyout_lf_b > data.flyout_rf_b:
|
||||
secondary = PlayResult(full_name='fly (lf) B', short_name='fly B')
|
||||
elif data.flyout_rf_b > max(1 - ch, 0):
|
||||
secondary = PlayResult(full_name='fly (rf) B', short_name='fly B')
|
||||
elif data.flyout_lf_b > max(1 - ch, 0):
|
||||
secondary = PlayResult(full_name='fly (lf) B', short_name='fly B')
|
||||
else:
|
||||
secondary = None
|
||||
|
||||
r_val = assign_pchances(card, PLAY_RESULTS['si-cf'], ch, secondary)
|
||||
res_chances -= r_val[0]
|
||||
new_ratings.single_center += r_val[0]
|
||||
if r_val[1] > 0:
|
||||
if 'CF' in secondary.short_name:
|
||||
data.flyout_cf_b -= r_val[1]
|
||||
new_ratings.flyout_cf_b += r_val[1]
|
||||
elif 'LF' in secondary.full_name:
|
||||
data.flyout_lf_b -= r_val[1]
|
||||
new_ratings.flyout_lf_b += r_val[1]
|
||||
elif 'RF' in secondary.full_name:
|
||||
data.flyout_rf_b -= r_val[1]
|
||||
new_ratings.flyout_rf_b += r_val[1]
|
||||
|
||||
if r_val[0] == 0:
|
||||
retries += 1
|
||||
|
||||
res_chances = data.single_one
|
||||
retries = 0
|
||||
while res_chances > 0:
|
||||
if res_chances < 1 or retries > 0:
|
||||
if data.walk > 0:
|
||||
data.walk += res_chances
|
||||
break
|
||||
|
||||
pref_mif = get_preferred_mif(new_ratings)
|
||||
ch = get_chances(res_chances)
|
||||
if data.groundout_b > max(1 - ch, 0):
|
||||
secondary = PlayResult(full_name=f'gb ({pref_mif}) B', short_name=f'gb ({pref_mif}) B')
|
||||
elif data.groundout_a > max(1 - ch, 0):
|
||||
temp_mif = get_preferred_mif(new_ratings)
|
||||
pref_mif = 'ss' if temp_mif == '2b' else '2b'
|
||||
secondary = PlayResult(full_name=f'gb ({pref_mif}) A', short_name=f'gb ({pref_mif}) A')
|
||||
else:
|
||||
secondary = None
|
||||
|
||||
r_val = assign_pchances(card, PLAY_RESULTS['si*'], ch, secondary)
|
||||
res_chances -= r_val[0]
|
||||
new_ratings.single_one += r_val[0]
|
||||
if r_val[1] > 0:
|
||||
if 'B' in secondary.short_name:
|
||||
data.groundout_b -= r_val[1]
|
||||
new_ratings.groundout_b += r_val[1]
|
||||
elif 'A' in secondary.short_name:
|
||||
data.groundout_a -= r_val[1]
|
||||
new_ratings.groundout_a += r_val[1]
|
||||
|
||||
if r_val[0] == 0:
|
||||
retries += 1
|
||||
|
||||
res_chances = data.bp_single
|
||||
retries = 0
|
||||
while res_chances > 0:
|
||||
if retries > 0:
|
||||
break
|
||||
ch = get_chances(res_chances)
|
||||
r_val = assign_pchances(card, PLAY_RESULTS['bp-si'], ch)
|
||||
res_chances -= r_val[0]
|
||||
new_ratings.bp_single += r_val[0]
|
||||
if r_val[0] == 0:
|
||||
retries += 1
|
||||
|
||||
res_chances = data.strikeout
|
||||
retries = 0
|
||||
while res_chances > 0:
|
||||
if retries > 0:
|
||||
break
|
||||
ch = get_chances(res_chances)
|
||||
r_val = assign_pchances(card, PlayResult(full_name='strikeout', short_name='so'), ch)
|
||||
res_chances -= r_val[0]
|
||||
new_ratings.strikeout += r_val[0]
|
||||
if r_val[0] == 0:
|
||||
retries += 1
|
||||
|
||||
res_chances = data.flyout_cf_b
|
||||
retries = 0
|
||||
while res_chances > 0:
|
||||
if retries > 0:
|
||||
break
|
||||
ch = get_chances(res_chances)
|
||||
r_val = assign_pchances(card, PLAY_RESULTS['fly-cf'], ch)
|
||||
res_chances -= r_val[0]
|
||||
new_ratings.flyout_cf_b += r_val[0]
|
||||
if r_val[0] == 0:
|
||||
retries += 1
|
||||
|
||||
res_chances = data.flyout_lf_b
|
||||
retries = 0
|
||||
while res_chances > 0:
|
||||
if retries > 0:
|
||||
break
|
||||
ch = get_chances(res_chances)
|
||||
r_val = assign_pchances(card, PLAY_RESULTS['fly-lf'], ch)
|
||||
res_chances -= r_val[0]
|
||||
new_ratings.flyout_lf_b += r_val[0]
|
||||
if r_val[0] == 0:
|
||||
retries += 1
|
||||
|
||||
res_chances = data.flyout_rf_b
|
||||
retries = 0
|
||||
while res_chances > 0:
|
||||
if retries > 0:
|
||||
break
|
||||
ch = get_chances(res_chances)
|
||||
r_val = assign_pchances(card, PLAY_RESULTS['fly-rf'], ch)
|
||||
res_chances -= r_val[0]
|
||||
new_ratings.flyout_rf_b += r_val[0]
|
||||
if r_val[0] == 0:
|
||||
retries += 1
|
||||
|
||||
res_chances = data.groundout_a
|
||||
retries = 0
|
||||
while res_chances > 0:
|
||||
if retries > 0:
|
||||
break
|
||||
|
||||
temp_mif = get_preferred_mif(new_ratings)
|
||||
pref_mif = 'ss' if temp_mif == '2b' else '2b'
|
||||
ch = get_chances(res_chances)
|
||||
r_val = assign_pchances(
|
||||
card,
|
||||
PlayResult(full_name=f'gb ({pref_mif}) A', short_name=f'gb ({pref_mif}) A'),
|
||||
ch,
|
||||
)
|
||||
res_chances -= r_val[0]
|
||||
new_ratings.groundout_a += r_val[0]
|
||||
|
||||
if r_val[0] == 0:
|
||||
retries += 1
|
||||
|
||||
res_chances = data.groundout_b
|
||||
retries = 0
|
||||
while res_chances > 0:
|
||||
if retries > 0:
|
||||
break
|
||||
|
||||
pref_mif = get_preferred_mif(new_ratings)
|
||||
ch = get_chances(res_chances)
|
||||
r_val = assign_pchances(
|
||||
card,
|
||||
PlayResult(full_name=f'gb ({pref_mif}) B', short_name=f'gb ({pref_mif}) B'),
|
||||
ch,
|
||||
)
|
||||
res_chances -= r_val[0]
|
||||
new_ratings.groundout_b += r_val[0]
|
||||
|
||||
if r_val[0] == 0:
|
||||
retries += 1
|
||||
|
||||
plays = sorted(
|
||||
[(data.strikeout, 'so'), (data.groundout_a, 'gb'), (data.flyout_lf_b, 'lf'), (data.flyout_rf_b, 'rf')],
|
||||
key=lambda z: z[0],
|
||||
reverse=True,
|
||||
)
|
||||
count_filler = -1
|
||||
pref_mif = get_preferred_mif(new_ratings)
|
||||
while not card.is_complete():
|
||||
count_filler += 1
|
||||
this_play = plays[count_filler % 4]
|
||||
if this_play[1] == 'so':
|
||||
play_res = PlayResult(full_name='strikeout', short_name='strikeout')
|
||||
elif this_play[1] == 'gb':
|
||||
this_if = '3b' if pref_mif == 'ss' else '1b'
|
||||
play_res = PlayResult(full_name=f'gb ({this_if}) A', short_name=f'gb ({this_if}) A')
|
||||
elif this_play[1] == 'lf':
|
||||
play_res = PLAY_RESULTS['fly-lf']
|
||||
else:
|
||||
play_res = PLAY_RESULTS['fly-rf']
|
||||
|
||||
r_raw = card.card_fill(play_res)
|
||||
r_val = (float(r_raw[0]), float(r_raw[1]))
|
||||
|
||||
if this_play[1] == 'so':
|
||||
new_ratings.strikeout += r_val[0]
|
||||
elif this_play[1] == 'gb':
|
||||
new_ratings.groundout_a += r_val[0]
|
||||
elif this_play[1] == 'lf':
|
||||
new_ratings.flyout_lf_b += r_val[0]
|
||||
else:
|
||||
new_ratings.flyout_rf_b += r_val[0]
|
||||
|
||||
card.add_fatigue()
|
||||
new_ratings.calculate_rate_stats()
|
||||
|
||||
return vl, vr
|
||||
Loading…
Reference in New Issue
Block a user