diff --git a/card_creation.py b/card_creation.py
new file mode 100644
index 0000000..7a4016f
--- /dev/null
+++ b/card_creation.py
@@ -0,0 +1,3608 @@
+import copy
+import math
+import pathlib
+import sys
+import csv
+import logging
+import datetime
+import asyncio
+
+from db_calls_card_creation import *
+from creation_helpers import *
+import calcs_pitcher as p
+import calcs_batter as b
+import calcs_defense as d
+
+date = f'{datetime.datetime.now().year}-{datetime.datetime.now().month}-{datetime.datetime.now().day}'
+log_level = logging.INFO
+logging.basicConfig(
+ filename=f'logs/{date}.log',
+ format='%(asctime)s - card-creation - %(levelname)s - %(message)s',
+ level=log_level
+)
+
+
+"""
+Data Links:
+ Baserunning: https://www.baseball-reference.com/leagues/majors/2022-baserunning-batting.shtml
+ Defense: https://www.baseball-reference.com/leagues/majors/2022-specialpos_p-fielding.shtml
+ All 9 positions plus OF
+ Pitcher Peripherals: https://www.baseball-reference.com/leagues/majors/2022-standard-pitching.shtml
+ Pitching & Batting: https://www.fangraphs.com/leaders/splits-leaderboards
+"""
+
+
+async def main(argv):
+ cardset_name = input(f'What is the name of this Cardset? ')
+ # cardset_name = '2022 Live'
+ cardset = Cardset.get_or_none(fn.Lower(Cardset.set_title) == cardset_name.lower())
+ testing = False
+
+ if not cardset:
+ create_cardset = input(f'There is no cardset named **{cardset_name}**. Should I create it (y/n)? ')
+ if create_cardset.lower() in YES:
+ cardset = Cardset(set_title=cardset_name)
+ cardset.save()
+ print(f'Got it! Now on to the cards.')
+ else:
+ print(f'Okay, see you next time.')
+ return
+
+ now = datetime.datetime.now()
+ output_path = pathlib.Path(f'card-output/{cardset.set_title} Cardset/')
+ input_path = f'data-input/{cardset.set_title} Cardset/'
+
+ game_count = 0
+ while (game_count <= 0) or (game_count > 162):
+ game_count = int(input(f'How many games out of 162 have been played? '))
+ season_pct = game_count / 162
+ print(f'season_pct: {season_pct}')
+
+ # Get stat csv
+ print(f'Your input files should be located in data-input/{cardset.set_title} Cardset/')
+ await asyncio.sleep(1)
+
+ lets_go = input(f'Should I run pitchers (y/n)? ')
+ if lets_go in YES:
+ existing_columns = CardColumns.delete().where(
+ CardColumns.id.endswith(f'-{cardset.id}') & CardColumns.p_ratings.is_null(False)
+ ).execute()
+ existing_pitchers = PitcherRatings.delete().where(PitcherRatings.cardset == cardset).execute()
+ # ratings_guide = [[
+ # 'name', 'sba-id', 'hr-vL', 'bp-hr-vL', 'tr-vL', 'do***-vL', 'do**-vL', 'do-cf-vL', 'si**-vL', 'si*-vL',
+ # 'si-cf-vL', 'bp-si-vL', 'hbp-vL', 'bb-vL', 'so-vL', 'fo-b-cf-vL', 'fo-b-slap-vL', 'gb-a-vL', 'gb-c-vL',
+ # 'gb-x-p-vL', 'gb-x-c-vL', 'gb-x-1b-vL', 'gb-x-2b-vL', 'gb-x-3b-vL', 'gb-x-ss-vL', 'gb-x-lf-vL',
+ # 'gb-x-cf-vL', 'gb-x-rf-vL',
+ # 'hr-vR', 'bp-hr-vR', 'tr-vR', 'do***-vR', 'do**-vR', 'do-cf-vR', 'si**-vR', 'si*-vR',
+ # 'si-cf-vR', 'bp-si-vR', 'hbp-vR', 'bb-vR', 'so-vR', 'fo-b-cf-vR', 'fo-b-slap-vR', 'gb-a-vR', 'gb-c-vR',
+ # 'gb-x-p-vR', 'gb-x-c-vR', 'gb-x-1b-vR', 'gb-x-2b-vR', 'gb-x-3b-vR', 'gb-x-ss-vR', 'gb-x-lf-vR',
+ # 'gb-x-cf-vR', 'gb-x-rf-vR'
+ # ]]
+ # card_columns = [[
+ # 'name', 'sba_id', 'hand', 'vl_one_2d6', 'vl_one_results', 'vl_one_splits', 'vl_two_2d6', 'vl_two_results',
+ # 'vl_two_splits', 'vl_three_2d6', 'vl_three_results', 'vl_three_splits', 'vr_one_2d6', 'vr_one_results',
+ # 'vr_one_splits', 'vr_two_2d6', 'vr_two_results', 'vr_two_splits', 'vr_three_2d6', 'vr_three_results',
+ # 'vr_three_splits'
+ # ]]
+ # rg_headers = ['name', 'hand', 'hr', 'bp-hr', 'tr', 'do***', 'do**', 'do-cf', 'si**', 'si*', 'si-cf', 'bp-si',
+ # 'hbp', 'bb', 'so', 'fo-cf', 'fo-slap', 'gb-a', 'gb-c', 'gb-x-p', 'gb-x-c', 'gb-x-1b', 'gb-x-2b',
+ # 'gb-x-3b', 'gb-x-ss', 'gb-x-lf', 'gb-x-cf', 'gb-x-rf']
+
+ """
+ Process pitcher stats into raw chances
+ """
+ count_pitchers = 0
+ with open(f'{input_path}pitcher-stats.csv', 'r') as file:
+ reader = csv.reader(file)
+
+ for row in reader:
+ try:
+ player = Player.get_or_none(Player.fg_id == int(row[0]))
+ if testing:
+ print(f'player fg_id: {int(row[0])} / player: {player}')
+ if player is not None and (('Promo' in cardset.set_title) or (int(row[5]) >= 30 and int(row[38]) >= 45)):
+ chance_data_vl = {
+ 'id': f'{player.sba_id}-vL-{cardset.id}',
+ 'player_id': player.sba_id,
+ 'cardset_id': cardset.id,
+ 'vs_hand': 'vL',
+ 'is_prep': True,
+ 'homerun': 0,
+ 'bp_homerun': 0,
+ 'triple': 0,
+ 'double_three': 0,
+ 'double_two': 0,
+ 'double_cf': 0,
+ 'single_two': 0,
+ 'single_one': 0,
+ 'single_center': 0,
+ 'bp_single': 0,
+ 'hbp': 0,
+ 'walk': 0,
+ 'strikeout': 0,
+ 'fo_slap': 0,
+ 'fo_center': 0,
+ 'groundout_a': 0,
+ 'groundout_b': 0,
+ 'xcheck_p': 0,
+ 'xcheck_c': 0,
+ 'xcheck_1b': 0,
+ 'xcheck_2b': 0,
+ 'xcheck_3b': 0,
+ 'xcheck_ss': 0,
+ 'xcheck_lf': 0,
+ 'xcheck_cf': 0,
+ 'xcheck_rf': 0,
+ }
+ chance_data_vr = {
+ 'id': f'{player.sba_id}-vR-{cardset.id}',
+ 'player_id': player.sba_id,
+ 'cardset_id': cardset.id,
+ 'vs_hand': 'vR',
+ 'is_prep': True,
+ 'homerun': 0,
+ 'bp_homerun': 0,
+ 'triple': 0,
+ 'double_three': 0,
+ 'double_two': 0,
+ 'double_cf': 0,
+ 'single_two': 0,
+ 'single_one': 0,
+ 'single_center': 0,
+ 'bp_single': 0,
+ 'hbp': 0,
+ 'walk': 0,
+ 'strikeout': 0,
+ 'fo_slap': 0,
+ 'fo_center': 0,
+ 'groundout_a': 0,
+ 'groundout_b': 0,
+ 'xcheck_p': 0,
+ 'xcheck_c': 0,
+ 'xcheck_1b': 0,
+ 'xcheck_2b': 0,
+ 'xcheck_3b': 0,
+ 'xcheck_ss': 0,
+ 'xcheck_lf': 0,
+ 'xcheck_cf': 0,
+ 'xcheck_rf': 0,
+ }
+
+ # Get total num hits v both
+ total_hit_mod = 5 # originally 9 to account for x-hits
+ raw_hits_vl = mround(float(row[17]) * 108)
+ raw_hits_vr = mround(float(row[50]) * 108)
+ hits_vl = max(raw_hits_vl - total_hit_mod, 5)
+ hits_vr = max(raw_hits_vr - total_hit_mod, 5)
+ soft_rate_vl = p.soft_rate(float(row[34]))
+ soft_rate_vr = p.soft_rate(float(row[67]))
+ med_rate_vl = p.med_rate(float(row[35]))
+ med_rate_vr = p.med_rate(float(row[68]))
+ hard_rate_vl = p.hard_rate(float(row[36]))
+ hard_rate_vr = p.hard_rate(float(row[69]))
+
+ # Get Singles
+ tot_singles_vl, tot_singles_vr = p.all_singles(row, hits_vl, hits_vr)
+ total_xbh_vl = mround(hits_vl - tot_singles_vl)
+ total_xbh_vr = mround(hits_vr - tot_singles_vr)
+
+ # BPSI
+ bpsi_vl, bpsi_vr = p.bp_singles(tot_singles_vl, tot_singles_vr)
+ chance_data_vl['bp_single'] = bpsi_vl
+ chance_data_vr['bp_single'] = bpsi_vr
+ tot_singles_vl = mround(tot_singles_vl - bpsi_vl)
+ tot_singles_vr = mround(tot_singles_vr - bpsi_vr)
+
+ # SI**
+ si2_vl, si2_vr = p.wh_singles(tot_singles_vl, tot_singles_vr, hard_rate_vl, hard_rate_vr)
+ chance_data_vl['single_two'] = si2_vl
+ chance_data_vr['single_two'] = si2_vr
+ tot_singles_vl = mround(tot_singles_vl - si2_vl)
+ tot_singles_vr = mround(tot_singles_vr - si2_vr)
+
+ # SI*
+ si1_vl, si1_vr = p.one_singles(tot_singles_vl, tot_singles_vr, soft_rate_vl, soft_rate_vr)
+ chance_data_vl['single_one'] = si1_vl
+ chance_data_vr['single_one'] = si1_vr
+ tot_singles_vl = mround(tot_singles_vl - si1_vl)
+ tot_singles_vr = mround(tot_singles_vr - si1_vr)
+
+ # SI(cf)
+ chance_data_vl['single_center'] = tot_singles_vl
+ chance_data_vr['single_center'] = tot_singles_vr
+
+ # Home Runs
+ hr_rate_vl = p.hr_per_fb_rate(float(row[28]))
+ hr_rate_vr = p.hr_per_fb_rate(float(row[61]))
+ hr_vl = mround(hits_vl * (float(row[12]) / float(row[7])))
+ hr_vr = mround(hits_vr * (float(row[45]) / float(row[40])))
+
+ bphr_vl, bphr_vr = p.bp_homerun(hr_vl, hr_vr, hr_rate_vl, hr_rate_vr)
+ chance_data_vl['bp_homerun'] = bphr_vl
+ chance_data_vr['bp_homerun'] = bphr_vr
+ chance_data_vl['homerun'] = mround(hr_vl - bphr_vl)
+ chance_data_vr['homerun'] = mround(hr_vr - bphr_vr)
+
+ total_xbh_vl = mround(total_xbh_vl - hr_vl)
+ total_xbh_vr = mround(total_xbh_vr - hr_vr)
+
+ non_hrs_vl = float(row[8]) + float(row[9])
+ non_hrs_vr = float(row[41]) + float(row[42])
+ triple_per_23b_vl = (float(row[9]) / non_hrs_vl) if non_hrs_vl > 0 else 0
+ triple_per_23b_br = (float(row[42]) / non_hrs_vr) if non_hrs_vr > 0 else 0
+
+ tr_vl, tr_vr = p.triples(total_xbh_vl, total_xbh_vr, triple_per_23b_vl, triple_per_23b_br)
+ chance_data_vl['triple'] = tr_vl
+ chance_data_vr['triple'] = tr_vr
+
+ doubles_vl = mround(total_xbh_vl - tr_vl)
+ doubles_vr = mround(total_xbh_vr - tr_vr)
+
+ ts_doubles_vl, ts_doubles_vr = p.two_doubles(doubles_vl, doubles_vr, soft_rate_vl, soft_rate_vr)
+ chance_data_vl['double_two'] = ts_doubles_vl
+ chance_data_vr['double_two'] = ts_doubles_vr
+ chance_data_vl['double_cf'] = mround(doubles_vl - ts_doubles_vl)
+ chance_data_vr['double_cf'] = mround(doubles_vr - ts_doubles_vr)
+
+ if testing:
+ print(f'vl hits: {hits_vl} / vr hits: {hits_vr}')
+ print(f'xbh vl: {total_xbh_vl}\nxbh vr: {total_xbh_vr}')
+ print(f'final hits vl: {p.total_chances(chance_data_vl)} / '
+ f'final hits vr: {p.total_chances(chance_data_vr)}')
+
+ other_ob_vl = mround((float(row[18]) - float(row[17])) * 108)
+ other_ob_vr = mround((float(row[51]) - float(row[50])) * 108)
+ hbp_per_walk_vl = p.hbp_rate(float(row[15]), float(row[13]))
+ hbp_per_walk_vr = p.hbp_rate(float(row[48]), float(row[46]))
+
+ chance_data_vl['hbp'] = p.hbps(other_ob_vl, hbp_per_walk_vl)
+ chance_data_vr['hbp'] = p.hbps(other_ob_vr, hbp_per_walk_vr)
+ chance_data_vl['walk'] = mround(other_ob_vl - chance_data_vl['hbp'])
+ chance_data_vr['walk'] = mround(other_ob_vr - chance_data_vr['hbp'])
+
+ if testing:
+ print(f'ob vl: {p.total_chances(chance_data_vl)}\nob vr: {p.total_chances(chance_data_vr)}')
+
+ chance_data_vl['xcheck_p'] = p.xchecks('p')
+ chance_data_vl['xcheck_c'] = p.xchecks('c')
+ chance_data_vl['xcheck_1b'] = p.xchecks('1b')
+ chance_data_vl['xcheck_2b'] = p.xchecks('2b')
+ chance_data_vl['xcheck_3b'] = p.xchecks('3b')
+ chance_data_vl['xcheck_ss'] = p.xchecks('ss')
+ chance_data_vl['xcheck_lf'] = p.xchecks('lf')
+ chance_data_vl['xcheck_cf'] = p.xchecks('cf')
+ chance_data_vl['xcheck_rf'] = p.xchecks('rf')
+ chance_data_vr['xcheck_p'] = p.xchecks('p')
+ chance_data_vr['xcheck_c'] = p.xchecks('c')
+ chance_data_vr['xcheck_1b'] = p.xchecks('1b')
+ chance_data_vr['xcheck_2b'] = p.xchecks('2b')
+ chance_data_vr['xcheck_3b'] = p.xchecks('3b')
+ chance_data_vr['xcheck_ss'] = p.xchecks('ss')
+ chance_data_vr['xcheck_lf'] = p.xchecks('lf')
+ chance_data_vr['xcheck_cf'] = p.xchecks('cf')
+ chance_data_vr['xcheck_rf'] = p.xchecks('rf')
+
+ all_outs_vl = mround(108 - p.total_chances(chance_data_vl))
+ all_outs_vr = mround(108 - p.total_chances(chance_data_vr))
+
+ if testing:
+ print(f'total vl: {p.total_chances(chance_data_vl)}\ntotal vr: {p.total_chances(chance_data_vr)}\n'
+ f'outs vl: {all_outs_vl}\nouts vr: {all_outs_vr}')
+
+ so_pct_vl = float(row[16]) / (
+ float(row[5]) - float(row[7]) - float(row[13]) - float(row[14]) - float(row[15])
+ )
+ so_pct_vr = float(row[49]) / (
+ float(row[38]) - float(row[40]) - float(row[46]) - float(row[47]) - float(row[48])
+ )
+
+ # so_vl = mround(all_outs_vl * so_pct_vl * 1.2)
+ # so_vr = mround(all_outs_vr * so_pct_vr * 1.2)
+ so_vl = mround(all_outs_vl * so_pct_vl)
+ so_vr = mround(all_outs_vr * so_pct_vr)
+ chance_data_vl['strikeout'] = so_vl
+ chance_data_vr['strikeout'] = so_vr
+
+ rem_outs_vl = mround(all_outs_vl - so_vl)
+ rem_outs_vr = mround(all_outs_vr - so_vr)
+
+ fly_pct_vl = float(row[26]) / (float(row[26]) + float(row[25]))
+ fly_pct_vr = float(row[59]) / (float(row[59]) + float(row[58]))
+ all_fly_vl = mround(rem_outs_vl * fly_pct_vl)
+ all_fly_vr = mround(rem_outs_vr * fly_pct_vr)
+ opp_fly_vl = float(row[33]) / (float(row[33]) + float(row[32]))
+ opp_fly_vr = float(row[66]) / (float(row[66]) + float(row[65]))
+
+ chance_data_vl['fo_slap'] = p.oppo_fly(all_fly_vl, opp_fly_vl)
+ chance_data_vr['fo_slap'] = p.oppo_fly(all_fly_vr, opp_fly_vr)
+ chance_data_vl['fo_center'] = mround(all_fly_vl - chance_data_vl['fo_slap'])
+ chance_data_vr['fo_center'] = mround(all_fly_vr - chance_data_vr['fo_slap'])
+
+ go_vl = mround(rem_outs_vl - all_fly_vl)
+ go_vr = mround(rem_outs_vr - all_fly_vr)
+ chance_data_vl['groundout_a'] = p.groundball_a(go_vl, float(row[35]))
+ chance_data_vr['groundout_a'] = p.groundball_a(go_vr, float(row[68]))
+ chance_data_vl['groundout_b'] = mround(go_vl - chance_data_vl['groundout_a'])
+ chance_data_vr['groundout_b'] = mround(go_vr - chance_data_vr['groundout_a'])
+
+ if testing:
+ print(f'total vl: {p.total_chances(chance_data_vl)}\ntotal vr: {p.total_chances(chance_data_vr)}')
+ print(f'{row[2]}\nvl: {chance_data_vl}\nvr: {chance_data_vr}')
+
+ this_line = PitcherRatings.create(**chance_data_vl)
+ this_line.save()
+ this_line = PitcherRatings.create(**chance_data_vr)
+ this_line.save()
+
+ """
+ Process pitcher chances into card output and ratings guide
+ """
+
+ bat_hand = player.hand
+ tba = {
+ 'vL': {
+ 'bp-si': {
+ 'value': chance_data_vl['bp_single'],
+ 'string': '▼BP-SI',
+ 'bold': True,
+ 'actual': 0
+ },
+ 'si-cf': {
+ 'value': chance_data_vl['single_center'],
+ 'string': 'SINGLE (cf)',
+ 'sm-string': 'SI (cf)',
+ 'bold': True,
+ 'actual': 0
+ },
+ 'si*': {
+ 'value': chance_data_vl['single_one'],
+ 'string': 'SINGLE*',
+ 'sm-string': 'SI*',
+ 'bold': True,
+ 'actual': 0
+ },
+ 'si**': {
+ 'value': chance_data_vl['single_two'],
+ 'string': 'SINGLE**',
+ 'sm-string': 'SI**',
+ 'bold': True,
+ 'actual': 0
+ },
+ 'bp-hr': {
+ 'value': chance_data_vl['bp_homerun'],
+ 'string': '◆BP-HR',
+ 'bold': True,
+ 'actual': 0
+ },
+ 'hr': {
+ 'value': chance_data_vl['homerun'],
+ 'string': 'HOMERUN',
+ 'sm-string': 'HR',
+ 'bold': True,
+ 'actual': 0
+ },
+ 'tr': {
+ 'value': chance_data_vl['triple'],
+ 'string': 'TRIPLE',
+ 'sm-string': 'TR',
+ 'bold': True,
+ 'actual': 0
+ },
+ 'do**': {
+ 'value': chance_data_vl['double_two'],
+ 'string': 'DOUBLE**',
+ 'sm-string': 'DO**',
+ 'bold': True,
+ 'actual': 0
+ },
+ 'do***': {
+ 'value': chance_data_vl['double_three'],
+ 'string': 'DOUBLE***',
+ 'sm-string': 'DO***',
+ 'bold': True,
+ 'actual': 0
+ },
+ 'do-cf': {
+ 'value': chance_data_vl['double_cf'],
+ 'string': f'DOUBLE (cf)',
+ 'sm-string': f'DO (cf)',
+ 'bold': True,
+ 'actual': 0
+ },
+ 'hbp': {
+ 'value': chance_data_vl['hbp'],
+ 'string': 'HBP',
+ 'bold': True,
+ 'actual': 0
+ },
+ 'bb': {
+ 'value': chance_data_vl['walk'],
+ 'string': 'WALK',
+ 'bold': True,
+ 'actual': 0
+ },
+ 'so': {
+ 'value': chance_data_vl['strikeout'],
+ 'string': 'strikeout',
+ # 'sm-string': 'so',
+ 'bold': False,
+ 'actual': 0,
+ },
+ 'fo-slap': {
+ 'value': chance_data_vl['fo_slap'],
+ 'string': f'fly (lf) B',
+ 'sm-string': f'fly (lf) B',
+ 'bold': False,
+ 'actual': 0
+ },
+ 'fo-cf': {
+ 'value': chance_data_vl['fo_center'],
+ 'string': f'fly (cf) B',
+ 'sm-string': f'fly (cf) B',
+ 'bold': False,
+ 'actual': 0
+ },
+ 'gb-a': {
+ 'value': chance_data_vl['groundout_a'],
+ 'string': f'gb (2b) A',
+ 'bold': False,
+ 'actual': 0
+ },
+ 'gb-c': {
+ 'value': chance_data_vl['groundout_b'],
+ 'string': f'gb (3b) B',
+ 'bold': False,
+ 'actual': 0
+ },
+ 'gb-x-p': {
+ 'value': chance_data_vl['xcheck_p'],
+ 'string': 'GB (p) X',
+ 'bold': False,
+ 'actual': 0
+ },
+ 'gb-x-c': {
+ 'value': chance_data_vl['xcheck_c'],
+ 'string': 'CATCH-X',
+ 'bold': False,
+ 'actual': 0
+ },
+ 'gb-x-1b': {
+ 'value': chance_data_vl['xcheck_1b'],
+ 'string': 'GB (1b) X',
+ 'bold': False,
+ 'actual': 0
+ },
+ 'gb-x-2b': {
+ 'value': chance_data_vl['xcheck_2b'],
+ 'string': 'GB (2b) X',
+ 'bold': False,
+ 'actual': 0
+ },
+ 'gb-x-3b': {
+ 'value': chance_data_vl['xcheck_3b'],
+ 'string': 'GB (3b) X',
+ 'bold': False,
+ 'actual': 0
+ },
+ 'gb-x-ss': {
+ 'value': chance_data_vl['xcheck_ss'],
+ 'string': 'GB (ss) X',
+ 'bold': False,
+ 'actual': 0
+ },
+ 'gb-x-lf': {
+ 'value': chance_data_vl['xcheck_lf'],
+ 'string': 'FLY (lf) X',
+ 'bold': False,
+ 'actual': 0
+ },
+ 'gb-x-cf': {
+ 'value': chance_data_vl['xcheck_cf'],
+ 'string': 'FLY (cf) X',
+ 'bold': False,
+ 'actual': 0
+ },
+ 'gb-x-rf': {
+ 'value': chance_data_vl['xcheck_rf'],
+ 'string': 'FLY (rf) X',
+ 'bold': False,
+ 'actual': 0
+ },
+ 'fatigue': 0
+ },
+ 'vR': {
+ 'bp-si': {
+ 'value': chance_data_vr['bp_single'],
+ 'string': '▼BP-SI',
+ 'bold': True,
+ 'actual': 0
+ },
+ 'si-cf': {
+ 'value': chance_data_vr['single_center'],
+ 'string': 'SINGLE (cf)',
+ 'sm-string': 'SI (cf)',
+ 'bold': True,
+ 'actual': 0
+ },
+ 'si*': {
+ 'value': chance_data_vr['single_one'],
+ 'string': 'SINGLE*',
+ 'sm-string': 'SI*',
+ 'bold': True,
+ 'actual': 0
+ },
+ 'si**': {
+ 'value': chance_data_vr['single_two'],
+ 'string': 'SINGLE**',
+ 'sm-string': 'SI**',
+ 'bold': True,
+ 'actual': 0
+ },
+ 'bp-hr': {
+ 'value': chance_data_vr['bp_homerun'],
+ 'string': '◆BP-HR',
+ 'bold': True,
+ 'actual': 0
+ },
+ 'hr': {
+ 'value': chance_data_vr['homerun'],
+ 'string': 'HOMERUN',
+ 'sm-string': 'HR',
+ 'bold': True,
+ 'actual': 0
+ },
+ 'tr': {
+ 'value': chance_data_vr['triple'],
+ 'string': 'TRIPLE',
+ 'sm-string': 'TR',
+ 'bold': True,
+ 'actual': 0
+ },
+ 'do**': {
+ 'value': chance_data_vr['double_two'],
+ 'string': 'DOUBLE**',
+ 'sm-string': 'DO**',
+ 'bold': True,
+ 'actual': 0
+ },
+ 'do***': {
+ 'value': chance_data_vr['double_three'],
+ 'string': 'DOUBLE***',
+ 'sm-string': 'DO***',
+ 'bold': True,
+ 'actual': 0
+ },
+ 'do-cf': {
+ 'value': chance_data_vr['double_cf'],
+ 'string': f'DOUBLE (cf)',
+ 'sm-string': f'DO (cf)',
+ 'bold': True,
+ 'actual': 0
+ },
+ 'hbp': {
+ 'value': chance_data_vr['hbp'],
+ 'string': 'HBP',
+ 'bold': True,
+ 'actual': 0
+ },
+ 'bb': {
+ 'value': chance_data_vr['walk'],
+ 'string': 'WALK',
+ 'bold': True,
+ 'actual': 0
+ },
+ 'so': {
+ 'value': chance_data_vr['strikeout'],
+ 'string': 'strikeout',
+ # 'sm-string': 'so',
+ 'bold': False,
+ 'actual': 0,
+ },
+ 'fo-slap': {
+ 'value': chance_data_vr['fo_slap'],
+ 'string': f'fly (rf) B',
+ 'sm-string': f'fly (rf) B',
+ 'bold': False,
+ 'actual': 0
+ },
+ 'fo-cf': {
+ 'value': chance_data_vr['fo_center'],
+ 'string': f'fly (cf) B',
+ 'bold': False,
+ 'actual': 0
+ },
+ 'gb-a': {
+ 'value': chance_data_vr['groundout_a'],
+ 'string': f'gb (ss) A',
+ 'bold': False,
+ 'actual': 0
+ },
+ 'gb-c': {
+ 'value': chance_data_vr['groundout_b'],
+ 'string': f'gb (1b) B',
+ 'bold': False,
+ 'actual': 0
+ },
+ 'gb-x-p': {
+ 'value': chance_data_vr['xcheck_p'],
+ 'string': 'GB (p) X',
+ 'bold': False,
+ 'actual': 0
+ },
+ 'gb-x-c': {
+ 'value': chance_data_vr['xcheck_c'],
+ 'string': 'CATCH-X',
+ 'bold': False,
+ 'actual': 0
+ },
+ 'gb-x-1b': {
+ 'value': chance_data_vr['xcheck_1b'],
+ 'string': 'GB (1b) X',
+ 'bold': False,
+ 'actual': 0
+ },
+ 'gb-x-2b': {
+ 'value': chance_data_vr['xcheck_2b'],
+ 'string': 'GB (2b) X',
+ 'bold': False,
+ 'actual': 0
+ },
+ 'gb-x-3b': {
+ 'value': chance_data_vr['xcheck_3b'],
+ 'string': 'GB (3b) X',
+ 'bold': False,
+ 'actual': 0
+ },
+ 'gb-x-ss': {
+ 'value': chance_data_vr['xcheck_ss'],
+ 'string': 'GB (ss) X',
+ 'bold': False,
+ 'actual': 0
+ },
+ 'gb-x-lf': {
+ 'value': chance_data_vr['xcheck_lf'],
+ 'string': 'FLY (lf) X',
+ 'bold': False,
+ 'actual': 0
+ },
+ 'gb-x-cf': {
+ 'value': chance_data_vr['xcheck_cf'],
+ 'string': 'FLY (cf) X',
+ 'bold': False,
+ 'actual': 0
+ },
+ 'gb-x-rf': {
+ 'value': chance_data_vr['xcheck_rf'],
+ 'string': 'FLY (rf) X',
+ 'bold': False,
+ 'actual': 0
+ },
+ 'fatigue': 0
+ }
+ }
+ results = copy.deepcopy(BLANK_RESULTS)
+
+ def column_output():
+ card_output = {}
+
+ for hand in ['vL', 'vR']:
+ for col in ['1', '2', '3']:
+ card_output[f'{hand.lower()}_{get_col(col)}_2d6'] = ''
+ card_output[f'{hand.lower()}_{get_col(col)}_results'] = ''
+ card_output[f'{hand.lower()}_{get_col(col)}_splits'] = ''
+
+ for hand in ['vL', 'vR']:
+ for col in ['1', '2', '3']:
+ int_results = {}
+ for x in results[hand][col]:
+ try:
+ int_results[int(x)] = results[hand][col][x]
+ except ValueError as e:
+ if testing:
+ print(f'skipping {x} in column_output')
+
+ if testing: print(f'{int_results}')
+
+ sorted_results = {
+ row_num: int_results[row_num] for row_num in sorted(int_results.keys())
+ }
+ for line in sorted_results:
+ if testing: print(f'\nsorted_results: {sorted_results}\nline: {line}')
+ if sorted_results[line]["result"]:
+ card_output[f'{hand.lower()}_{get_col(col)}_2d6'] += \
+ f'{results[hand][col][str(line)]["2d6"]}\n'
+ card_output[f'{hand.lower()}_{get_col(col)}_results'] += \
+ f'{results[hand][col][str(line)]["result"]}\n'
+ card_output[f'{hand.lower()}_{get_col(col)}_splits'] += \
+ f'{results[hand][col][str(line)]["splits"]}\n'
+
+ return card_output
+
+ def add_full_result(vs_hand, tba_data, is_good, chances, plus_fatigue=False):
+ all_cols = []
+ good_col = player.offense_col
+ if is_good:
+ if good_col == 1:
+ second = random.choice([2, 3])
+ all_cols = [1, second, 3 if second == 2 else 2]
+ elif good_col == 2:
+ second = random.choice([1, 3])
+ all_cols = [2, second, 3 if second == 1 else 1]
+ elif good_col == 3:
+ second = random.choice([1, 2])
+ all_cols = [3, second, 1 if second == 1 else 2]
+ else:
+ if good_col == 1:
+ f_col = random.choice([2, 3])
+ all_cols = [f_col, 3 if f_col == 2 else 2, 1]
+ elif good_col == 2:
+ f_col = random.choice([1, 3])
+ all_cols = [f_col, 3 if f_col == 1 else 1, 2]
+ elif good_col == 3:
+ f_col = random.choice([1, 2])
+ all_cols = [f_col, 1 if f_col == 1 else 2, 3]
+
+ if chances == 6:
+ for column in all_cols:
+ if not results[vs_hand][f'{column}']['7']['result']:
+ results[vs_hand][f'{column}']['7'] = result_data(tba_data, 7, fatigue=plus_fatigue)
+ return chances
+ if not results[vs_hand][f'{column}']['6']['result'] and not \
+ results[vs_hand][f'{column}']['2']['result']:
+ results[vs_hand][f'{column}']['6'] = result_data(tba_data, 6, fatigue=plus_fatigue)
+ results[vs_hand][f'{column}']['2'] = result_data(tba_data, 2, fatigue=plus_fatigue)
+ return chances
+ if not results[vs_hand][f'{column}']['8']['result'] and not \
+ results[vs_hand][f'{column}']['12']['result']:
+ results[vs_hand][f'{column}']['8'] = result_data(tba_data, 8, fatigue=plus_fatigue)
+ results[vs_hand][f'{column}']['12'] = result_data(tba_data, 12,
+ fatigue=plus_fatigue)
+ return chances
+ if not results[vs_hand][f'{column}']['6']['result'] and not \
+ results[vs_hand][f'{column}']['12']['result']:
+ results[vs_hand][f'{column}']['6'] = result_data(tba_data, 6, fatigue=plus_fatigue)
+ results[vs_hand][f'{column}']['12'] = result_data(tba_data, 12,
+ fatigue=plus_fatigue)
+ return chances
+ if not results[vs_hand][f'{column}']['8']['result'] and not \
+ results[vs_hand][f'{column}']['2']['result']:
+ results[vs_hand][f'{column}']['8'] = result_data(tba_data, 8, fatigue=plus_fatigue)
+ results[vs_hand][f'{column}']['2'] = result_data(tba_data, 2, fatigue=plus_fatigue)
+ return chances
+
+ # No matches
+ return 0
+
+ elif chances == 5:
+ for column in all_cols:
+ if not results[vs_hand][f'{column}']['6']['result']:
+ results[vs_hand][f'{column}']['6'] = result_data(tba_data, 6, fatigue=plus_fatigue)
+ return chances
+ if not results[vs_hand][f'{column}']['8']['result']:
+ results[vs_hand][f'{column}']['8'] = result_data(tba_data, 8, fatigue=plus_fatigue)
+ return chances
+ if not results[vs_hand][f'{column}']['3']['result'] and not \
+ results[vs_hand][f'{column}']['4']['result']:
+ results[vs_hand][f'{column}']['3'] = result_data(tba_data, 3, fatigue=plus_fatigue)
+ results[vs_hand][f'{column}']['4'] = result_data(tba_data, 4, fatigue=plus_fatigue)
+ return chances
+ if not results[vs_hand][f'{column}']['3']['result'] and not \
+ results[vs_hand][f'{column}']['10']['result']:
+ results[vs_hand][f'{column}']['3'] = result_data(tba_data, 3, fatigue=plus_fatigue)
+ results[vs_hand][f'{column}']['10'] = result_data(tba_data, 10,
+ fatigue=plus_fatigue)
+ return chances
+ if not results[vs_hand][f'{column}']['4']['result'] and not \
+ results[vs_hand][f'{column}']['11']['result']:
+ results[vs_hand][f'{column}']['4'] = result_data(tba_data, 4, fatigue=plus_fatigue)
+ results[vs_hand][f'{column}']['11'] = result_data(tba_data, 11,
+ fatigue=plus_fatigue)
+ return chances
+ if not results[vs_hand][f'{column}']['10']['result'] and not \
+ results[vs_hand][f'{column}']['11']['result']:
+ results[vs_hand][f'{column}']['10'] = result_data(tba_data, 10,
+ fatigue=plus_fatigue)
+ results[vs_hand][f'{column}']['11'] = result_data(tba_data, 11,
+ fatigue=plus_fatigue)
+ return chances
+
+ # No matches
+ return 0
+
+ elif chances == 4:
+ for column in all_cols:
+ if not results[vs_hand][f'{column}']['5']['result']:
+ results[vs_hand][f'{column}']['5'] = result_data(tba_data, 5, fatigue=plus_fatigue)
+ return chances
+ if not results[vs_hand][f'{column}']['9']['result']:
+ results[vs_hand][f'{column}']['9'] = result_data(tba_data, 9, fatigue=plus_fatigue)
+ return chances
+ if not results[vs_hand][f'{column}']['3']['result'] and not \
+ results[vs_hand][f'{column}']['11']['result']:
+ results[vs_hand][f'{column}']['3'] = result_data(tba_data, 3, fatigue=plus_fatigue)
+ results[vs_hand][f'{column}']['11'] = result_data(tba_data, 11,
+ fatigue=plus_fatigue)
+ return chances
+ if not results[vs_hand][f'{column}']['2']['result'] and not \
+ results[vs_hand][f'{column}']['4']['result']:
+ results[vs_hand][f'{column}']['2'] = result_data(tba_data, 2, fatigue=plus_fatigue)
+ results[vs_hand][f'{column}']['4'] = result_data(tba_data, 4, fatigue=plus_fatigue)
+ return chances
+ if not results[vs_hand][f'{column}']['10']['result'] and not \
+ results[vs_hand][f'{column}']['12']['result']:
+ results[vs_hand][f'{column}']['10'] = result_data(tba_data, 10,
+ fatigue=plus_fatigue)
+ results[vs_hand][f'{column}']['12'] = result_data(tba_data, 12,
+ fatigue=plus_fatigue)
+ return chances
+ if not results[vs_hand][f'{column}']['2']['result'] and not \
+ results[vs_hand][f'{column}']['10']['result']:
+ results[vs_hand][f'{column}']['2'] = result_data(tba_data, 2, fatigue=plus_fatigue)
+ results[vs_hand][f'{column}']['10'] = result_data(tba_data, 10,
+ fatigue=plus_fatigue)
+ return chances
+ if not results[vs_hand][f'{column}']['10']['result'] and not \
+ results[vs_hand][f'{column}']['4']['result']:
+ results[vs_hand][f'{column}']['10'] = result_data(tba_data, 10,
+ fatigue=plus_fatigue)
+ results[vs_hand][f'{column}']['4'] = result_data(tba_data, 4, fatigue=plus_fatigue)
+ return chances
+
+ return 0
+
+ elif chances == 3:
+ for column in all_cols:
+ if not results[vs_hand][f'{column}']['4']['result']:
+ results[vs_hand][f'{column}']['4'] = result_data(tba_data, 4, fatigue=plus_fatigue)
+ return chances
+ if not results[vs_hand][f'{column}']['10']['result']:
+ results[vs_hand][f'{column}']['10'] = result_data(tba_data, 10,
+ fatigue=plus_fatigue)
+ return chances
+ if not results[vs_hand][f'{column}']['2']['result'] and not \
+ results[vs_hand][f'{column}']['3']['result']:
+ results[vs_hand][f'{column}']['2'] = result_data(tba_data, 2, fatigue=plus_fatigue)
+ results[vs_hand][f'{column}']['3'] = result_data(tba_data, 3, fatigue=plus_fatigue)
+ return chances
+ if not results[vs_hand][f'{column}']['2']['result'] and not \
+ results[vs_hand][f'{column}']['11']['result']:
+ results[vs_hand][f'{column}']['2'] = result_data(tba_data, 2, fatigue=plus_fatigue)
+ results[vs_hand][f'{column}']['11'] = result_data(tba_data, 11,
+ fatigue=plus_fatigue)
+ return chances
+ if not results[vs_hand][f'{column}']['12']['result'] and not \
+ results[vs_hand][f'{column}']['3']['result']:
+ results[vs_hand][f'{column}']['12'] = result_data(tba_data, 12,
+ fatigue=plus_fatigue)
+ results[vs_hand][f'{column}']['3'] = result_data(tba_data, 3, fatigue=plus_fatigue)
+ return chances
+ if not results[vs_hand][f'{column}']['12']['result'] and not \
+ results[vs_hand][f'{column}']['11']['result']:
+ results[vs_hand][f'{column}']['12'] = result_data(tba_data, 12,
+ fatigue=plus_fatigue)
+ results[vs_hand][f'{column}']['11'] = result_data(tba_data, 11,
+ fatigue=plus_fatigue)
+ return chances
+
+ return 0
+
+ elif chances == 2:
+ for column in all_cols:
+ if not results[vs_hand][f'{column}']['3']['result']:
+ results[vs_hand][f'{column}']['3'] = result_data(tba_data, 3, fatigue=plus_fatigue)
+ return chances
+ if not results[vs_hand][f'{column}']['11']['result']:
+ results[vs_hand][f'{column}']['11'] = result_data(tba_data, 11,
+ fatigue=plus_fatigue)
+ return chances
+ if not results[vs_hand][f'{column}']['2']['result'] and not \
+ results[vs_hand][f'{column}']['12']['result']:
+ results[vs_hand][f'{column}']['2'] = result_data(tba_data, 2, fatigue=plus_fatigue)
+ results[vs_hand][f'{column}']['12'] = result_data(tba_data, 12,
+ fatigue=plus_fatigue)
+ return chances
+
+ return 0
+
+ elif chances == 1:
+ for column in all_cols:
+ if not results[vs_hand][f'{column}']['2']['result']:
+ results[vs_hand][f'{column}']['2'] = result_data(tba_data, 2, fatigue=plus_fatigue)
+ return chances
+ if not results[vs_hand][f'{column}']['12']['result']:
+ results[vs_hand][f'{column}']['12'] = result_data(tba_data, 12,
+ fatigue=plus_fatigue)
+ return chances
+ return 0
+
+ def add_split_result(vs_hand, tba_data_top, tba_data_bottom, chances_top, is_good=None):
+ all_cols = []
+ good_col = player.offense_col
+
+ if is_good is None:
+ if good_col == 1:
+ f_col = random.choice([2, 3])
+ all_cols = [f_col, 1, 3 if f_col == 2 else 2]
+ elif good_col == 2:
+ f_col = random.choice([1, 3])
+ all_cols = [f_col, 2, 3 if f_col == 1 else 1]
+ elif good_col == 3:
+ f_col = random.choice([1, 2])
+ all_cols = [f_col, 3, 1 if f_col == 1 else 2]
+
+ elif is_good:
+ if good_col == 1:
+ second = random.choice([2, 3])
+ all_cols = [1, second, 3 if second == 2 else 2]
+ elif good_col == 2:
+ second = random.choice([1, 3])
+ all_cols = [2, second, 3 if second == 1 else 1]
+ elif good_col == 3:
+ second = random.choice([1, 2])
+ all_cols = [3, second, 1 if second == 1 else 2]
+
+ else:
+ if good_col == 1:
+ f_col = random.choice([2, 3])
+ all_cols = [f_col, 3 if f_col == 2 else 2, 1]
+ elif good_col == 2:
+ f_col = random.choice([1, 3])
+ all_cols = [f_col, 3 if f_col == 1 else 1, 2]
+ elif good_col == 3:
+ f_col = random.choice([1, 2])
+ all_cols = [f_col, 1 if f_col == 1 else 2, 3]
+
+ legal_2d6 = legal_splits(chances_top)
+ for column in all_cols:
+ if results[vs_hand][f'{column}']['splits'] < 3:
+ for y in legal_2d6:
+ if tba_data_bottom['value'] >= y['bad_chances'] and not \
+ results[vs_hand][f'{column}'][f'{y["2d6"]}']['result']:
+ results[vs_hand][f'{column}'][f'{y["2d6"]}'] = \
+ result_data(tba_data_top, y["2d6"], tba_data_bottom, y["incs"])
+ results[vs_hand][f'{column}']['splits'] += 1
+ return y['bad_chances']
+
+ if testing: print(f'Legal 2d6: {legal_2d6}')
+ if testing: print(f'Could not find a legal spot for:\n{tba_data_top}\n{tba_data_bottom}')
+ return None
+
+ def assign_chances(
+ res_key: str, vs_hand: str, remainder_keys: list[str], allow_retry: bool, rollover_key: str,
+ is_good: bool, force_whole: bool = False):
+ retries = 0 if allow_retry else 1
+
+ if testing: print(f'starting {res_key}: {tba[vs_hand][res_key]["value"]}')
+ # If not even int, add_split_result with less than half of total chances
+ total_chances = mround(tba[vs_hand][res_key]['value'])
+ # chance_remainder = mround(total_chances - math.floor(total_chances))
+
+ # If total chance is a whole number, do easy assignments first
+ if int(total_chances) - total_chances == 0 or force_whole or tba[vs_hand][res_key]['value'] > 2:
+ if testing: print(f'{tba[vs_hand][res_key]["value"]} {res_key}s being placed')
+ if (res_key == 'so' or res_key == 'gb-a' or res_key == 'gb-c' or 'fo' in res_key) and \
+ tba[vs_hand]['fatigue'] < 10:
+ num_added = add_full_result(
+ vs_hand,
+ tba[vs_hand][res_key],
+ is_good,
+ min(math.floor(tba[vs_hand][res_key]['value']),
+ min(6, 10 - tba[vs_hand]['fatigue'])),
+ plus_fatigue=True
+ )
+ tba[vs_hand]['fatigue'] += num_added if num_added else 0
+
+ elif tba[vs_hand][res_key]['value'] > 9.5:
+ num_added = add_full_result(vs_hand, tba[vs_hand][res_key], is_good, 6)
+
+ elif tba[vs_hand][res_key]['value'] > 7.5:
+ num_added = add_full_result(vs_hand, tba[vs_hand][res_key], is_good, 5)
+
+ elif res_key == 'bp-si' and tba[vs_hand]['bp-si']['value'] > 4.5:
+ num_added = add_full_result(vs_hand, tba[vs_hand][res_key], is_good,
+ random.randint(3, 5))
+
+ elif tba[vs_hand][res_key]['value'] > 5.5:
+ num_added = add_full_result(vs_hand, tba[vs_hand][res_key], is_good, 4)
+
+ else:
+ num_added = add_full_result(
+ vs_hand,
+ tba[vs_hand][res_key],
+ is_good,
+ int(tba[vs_hand][res_key]['value'])
+ )
+ if not num_added and int(tba[vs_hand][res_key]['value']) > 1:
+ num_added = add_full_result(
+ vs_hand,
+ tba[vs_hand][res_key],
+ is_good,
+ int(tba[vs_hand][res_key]['value'] - 1)
+ )
+ if not num_added and int(tba[vs_hand][res_key]['value']) > 2:
+ num_added = add_full_result(
+ vs_hand,
+ tba[vs_hand][res_key],
+ is_good,
+ int(tba[vs_hand][res_key]['value'] - 2)
+ )
+ if not num_added and int(tba[vs_hand][res_key]['value']) > 3:
+ num_added = add_full_result(
+ vs_hand,
+ tba[vs_hand][res_key],
+ is_good,
+ int(tba[vs_hand][res_key]['value'] - 3)
+ )
+ if not num_added and int(tba[vs_hand][res_key]['value']) > 4:
+ num_added = add_full_result(
+ vs_hand,
+ tba[vs_hand][res_key],
+ is_good,
+ int(tba[vs_hand][res_key]['value'] - 4)
+ )
+
+ if num_added:
+ tba[vs_hand][res_key]['value'] = mround(tba[vs_hand][res_key]['value'] - num_added)
+ tba[vs_hand][res_key]['actual'] = mround(tba[vs_hand][res_key]['actual'] + num_added)
+ return
+
+ elif retries == 0:
+ if testing: print(f'retry # {retries} for {res_key} for {player.name} {vs_hand}')
+ return
+
+ else:
+ if tba[vs_hand][rollover_key]['value'] >= 1:
+ t_value = 1
+ else:
+ t_value = .05
+ if testing: print(f'Transferring {t_value} {res_key} to {rollover_key}')
+ tba[vs_hand][rollover_key]['value'] = mround(
+ tba[vs_hand][rollover_key]['value'] + t_value)
+ tba[vs_hand][res_key]['value'] = mround(tba[vs_hand][res_key]['value'] - t_value)
+ return
+
+ # Else start dicing up the chances
+ else:
+ # if retries == 0 and total_chances > 3:
+ # chance_remainder = mround(
+ # math.ceil(total_chances / 2) - (total_chances - math.floor(total_chances))
+ # )
+ # else:
+ # chance_remainder = mround(total_chances - math.floor(total_chances))
+
+ chance_remainder = mround(total_chances - math.floor(total_chances))
+ if testing: print(f'chance_remainder: {chance_remainder}')
+
+ # if mround(chance_remainder) != 0 and mround(chance_remainder) > .5:
+ # TO ROLL BACK, UNDO ABOVE COMMEND AND TAB ALL BELOW CODE IN ONCE
+ top_chances = None
+ bottom_key = None
+ bottom_result = None
+
+ """
+ If this result cannot take any splits (but has extra results pass the remainder to the rollover and
+ come back to assign_chances with a whole number
+ """
+ if len(remainder_keys) == 0:
+ # print(f'in the remainder_keys check for {res_key} / rounding down from '
+ # f'{tba[vs_hand][res_key]["value"]} to '
+ # f'{mround(math.floor(tba[vs_hand][res_key]["value"]))}')
+ tba[vs_hand][res_key]['value'] = mround(math.floor(tba[vs_hand][res_key]['value']))
+ # print(f'confirming end val: {tba[vs_hand][res_key]["value"]}')
+ tba[vs_hand][rollover_key]['value'] = mround(
+ tba[vs_hand][rollover_key]['value'] + chance_remainder
+ )
+ return
+
+ for rem_key in remainder_keys:
+ if mround(tba[vs_hand][rem_key]['value']) >= mround(1 - chance_remainder):
+ bottom_key = rem_key
+ bottom_result = tba[vs_hand][rem_key]
+ break
+
+ if not bottom_key:
+ if tba[vs_hand][rollover_key]['value'] > 1:
+ t_value = 1
+ else:
+ t_value = .05
+ if testing: print(f'Transferring {t_value} {res_key} to {rollover_key}')
+
+ tba[vs_hand][res_key]['value'] = mround(tba[vs_hand][res_key]['value'] - t_value)
+ tba[vs_hand][rollover_key]['value'] = mround(
+ tba[vs_hand][rollover_key]['value'] + t_value
+ )
+ return
+ # raise ValueError(
+ # f'Could not find a second result for a {res_key} split for {player.name} {vHand}')
+
+ bottom_chances = None
+ if tba[vs_hand][res_key]['value'] > 4:
+ top_chances = mround(3 + chance_remainder)
+ if testing: print(f'checking top_chances: {top_chances}')
+ bottom_chances = add_split_result(
+ vs_hand, tba[vs_hand][res_key], bottom_result, top_chances, is_good
+ )
+
+ elif tba[vs_hand][res_key]['value'] > 3:
+ top_chances = mround(2 + chance_remainder)
+ if testing: print(f'checking top_chances: {top_chances}')
+ bottom_chances = add_split_result(
+ vs_hand, tba[vs_hand][res_key], bottom_result, top_chances, is_good
+ )
+
+ elif tba[vs_hand][res_key]['value'] > 2:
+ top_chances = mround(1 + chance_remainder)
+ if testing: print(f'checking top_chances: {top_chances}')
+ bottom_chances = add_split_result(
+ vs_hand, tba[vs_hand][res_key], bottom_result, top_chances, is_good
+ )
+
+ if not bottom_chances:
+ top_chances = mround(chance_remainder)
+ if testing: print(f'checking top_chances: {top_chances}')
+ bottom_chances = add_split_result(
+ vs_hand, tba[vs_hand][res_key], bottom_result, top_chances, is_good
+ )
+
+ if not bottom_chances and tba[vs_hand][res_key]['value'] > 3:
+ top_chances = mround(.5 + chance_remainder)
+ if testing: print(f'checking top_chances: {top_chances}')
+ bottom_chances = add_split_result(
+ vs_hand, tba[vs_hand][res_key], bottom_result, top_chances, is_good
+ )
+
+ if not bottom_chances and tba[vs_hand][res_key]['value'] > 3:
+ top_chances = mround(.7 + chance_remainder)
+ if testing: print(f'checking top_chances: {top_chances}')
+ bottom_chances = add_split_result(
+ vs_hand, tba[vs_hand][res_key], bottom_result, top_chances, is_good
+ )
+
+ if not bottom_chances and chance_remainder > 0.15:
+ top_chances = mround(chance_remainder - 0.15)
+ if testing: print(f'checking top_chances: {top_chances}')
+ bottom_chances = add_split_result(
+ vs_hand, tba[vs_hand][res_key], bottom_result, top_chances, is_good
+ )
+
+ if not bottom_chances and chance_remainder > 0.05:
+ top_chances = mround(chance_remainder - 0.05)
+ if testing: print(f'checking top_chances: {top_chances}')
+ bottom_chances = add_split_result(
+ vs_hand, tba[vs_hand][res_key], bottom_result, top_chances, is_good
+ )
+
+ if testing: print(f'{res_key} chances: {mround(top_chances)} / split with {bottom_result}')
+
+ if bottom_chances:
+ tba[vs_hand][res_key]['value'] = mround(tba[vs_hand][res_key]['value'] - top_chances)
+ tba[vs_hand][res_key]['actual'] = mround(tba[vs_hand][res_key]['actual'] + top_chances)
+ tba[vs_hand][bottom_key]['value'] = mround(
+ tba[vs_hand][bottom_key]['value'] - bottom_chances)
+ tba[vs_hand][bottom_key]['actual'] = mround(
+ tba[vs_hand][bottom_key]['actual'] + bottom_chances
+ )
+ if testing: print(
+ f'placed {top_chances} {res_key}s and {bottom_chances} {bottom_result["string"]}s for '
+ f'{player.name} {vs_hand}\n\n')
+ return
+
+ elif retries == 0:
+ retries += 1
+ if testing: print(f'retry # {retries} for {res_key} for {player.name} {vs_hand}')
+ return
+
+ else:
+ if tba[vs_hand][rollover_key]['value'] > 1:
+ t_value = 1
+ else:
+ t_value = .05
+ if testing: print(f'Transferring {t_value} {res_key} to {rollover_key}')
+ tba[vs_hand][res_key]['value'] = mround(tba[vs_hand][res_key]['value'] - t_value)
+ tba[vs_hand][rollover_key]['value'] = mround(
+ tba[vs_hand][rollover_key]['value'] + t_value
+ )
+ return
+
+ def gap_filler(vs_hand, res_key: str):
+ for col in ['1', '2', '3']:
+ total_filler = 0
+ for b_row in ['2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12']:
+ # print(f'checking {col}-{b_row} {vs_hand} for a None: {results[vs_hand][col][b_row]["result"]}')
+ if not results[vs_hand][col][b_row]['result']:
+ chances = chances_from_row(b_row)
+ total_filler += chances
+ tba[vs_hand][res_key]['actual'] = mround(
+ tba[vs_hand][res_key]['actual'] + chances
+ )
+ results[vs_hand][col][b_row] = result_data(tba[vs_hand][res_key], b_row)
+ if testing:
+ print(f'total filler: {total_filler}')
+
+ # Build vl results then vR
+ for vHand in ['vL', 'vR']:
+ # Refactored bp-hr
+ retries = False
+ while tba[vHand]['bp-hr']['value'] > 0:
+ assign_chances(
+ res_key='bp-hr',
+ vs_hand=vHand,
+ remainder_keys=[],
+ allow_retry=retries,
+ rollover_key='do-cf',
+ is_good=True
+ )
+ retries = False
+
+ # Fatigue results
+ retries = False
+ while tba[vHand]['so']['value'] >= 1 and tba[vHand]['fatigue'] < 10:
+ assign_chances(
+ res_key='so',
+ vs_hand=vHand,
+ remainder_keys=[],
+ allow_retry=retries,
+ rollover_key='',
+ is_good=False,
+ force_whole=True
+ )
+ if tba[vHand]['fatigue'] < 10 and tba[vHand]['gb-a']['value'] >= 1:
+ assign_chances(
+ res_key='gb-a',
+ vs_hand=vHand,
+ remainder_keys=[],
+ allow_retry=retries,
+ rollover_key='',
+ is_good=False,
+ force_whole=True
+ )
+ if tba[vHand]['fatigue'] < 10 and tba[vHand]['gb-c']['value'] >= 1:
+ assign_chances(
+ res_key='gb-c',
+ vs_hand=vHand,
+ remainder_keys=[],
+ allow_retry=retries,
+ rollover_key='',
+ is_good=False,
+ force_whole=True
+ )
+ if tba[vHand]['fatigue'] < 10 and tba[vHand]['fo-slap']['value'] >= 1:
+ assign_chances(
+ res_key='fo-slap',
+ vs_hand=vHand,
+ remainder_keys=[],
+ allow_retry=retries,
+ rollover_key=f'fo-cf',
+ is_good=False
+ )
+ if tba[vHand]['fatigue'] <= 10 and tba[vHand]['fo-cf']['value'] >= 1:
+ assign_chances(
+ res_key='fo-cf',
+ vs_hand=vHand,
+ remainder_keys=[],
+ allow_retry=retries,
+ rollover_key=f'gb-c',
+ is_good=False
+ )
+
+ # Refactored gb-x-p
+ retries = False
+ while tba[vHand]['gb-x-p']['value'] > 0:
+ assign_chances(
+ res_key='gb-x-p',
+ vs_hand=vHand,
+ remainder_keys=[],
+ allow_retry=retries,
+ rollover_key='',
+ is_good=False
+ )
+ retries = False
+
+ # Refactored gb-x-c
+ retries = False
+ while tba[vHand]['gb-x-c']['value'] > 0:
+ assign_chances(
+ res_key='gb-x-c',
+ vs_hand=vHand,
+ remainder_keys=[],
+ allow_retry=retries,
+ rollover_key='',
+ is_good=False
+ )
+ retries = False
+
+ # Refactored gb-x-1b
+ retries = False
+ while tba[vHand]['gb-x-1b']['value'] > 0:
+ assign_chances(
+ res_key='gb-x-1b',
+ vs_hand=vHand,
+ remainder_keys=[],
+ allow_retry=retries,
+ rollover_key='',
+ is_good=False
+ )
+ retries = False
+
+ # Refactored gb-x-2b
+ retries = False
+ while tba[vHand]['gb-x-2b']['value'] > 0:
+ assign_chances(
+ res_key='gb-x-2b',
+ vs_hand=vHand,
+ remainder_keys=[],
+ allow_retry=retries,
+ rollover_key='',
+ is_good=False
+ )
+ retries = False
+
+ # Refactored gb-x-3b
+ retries = False
+ while tba[vHand]['gb-x-3b']['value'] > 0:
+ assign_chances(
+ res_key='gb-x-3b',
+ vs_hand=vHand,
+ remainder_keys=[],
+ allow_retry=retries,
+ rollover_key='',
+ is_good=False
+ )
+ retries = False
+
+ # Refactored gb-x-ss
+ retries = False
+ while tba[vHand]['gb-x-ss']['value'] > 0:
+ assign_chances(
+ res_key='gb-x-ss',
+ vs_hand=vHand,
+ remainder_keys=[],
+ allow_retry=retries,
+ rollover_key='',
+ is_good=False
+ )
+ retries = False
+
+ # Refactored gb-x-lf
+ retries = False
+ while tba[vHand]['gb-x-lf']['value'] > 0:
+ assign_chances(
+ res_key='gb-x-lf',
+ vs_hand=vHand,
+ remainder_keys=[],
+ allow_retry=retries,
+ rollover_key='',
+ is_good=False
+ )
+ retries = False
+
+ # Refactored gb-x-cf
+ retries = False
+ while tba[vHand]['gb-x-cf']['value'] > 0:
+ assign_chances(
+ res_key='gb-x-cf',
+ vs_hand=vHand,
+ remainder_keys=[],
+ allow_retry=retries,
+ rollover_key='',
+ is_good=False
+ )
+ retries = False
+
+ # Refactored gb-x-rf
+ retries = False
+ while tba[vHand]['gb-x-rf']['value'] > 0:
+ assign_chances(
+ res_key='gb-x-rf',
+ vs_hand=vHand,
+ remainder_keys=[],
+ allow_retry=retries,
+ rollover_key='',
+ is_good=False
+ )
+ retries = False
+
+ # Refactored bp-si
+ retries = True
+ while tba[vHand]['bp-si']['value'] > 0:
+ assign_chances(
+ res_key='bp-si',
+ vs_hand=vHand,
+ remainder_keys=[],
+ allow_retry=retries,
+ rollover_key=f'si*',
+ is_good=False
+ )
+ retries = False
+
+ # Refactored so
+ retries = False
+ while tba[vHand]['so']['value'] > 0:
+ assign_chances(
+ res_key='so',
+ vs_hand=vHand,
+ remainder_keys=[],
+ allow_retry=retries,
+ rollover_key='gb-c',
+ is_good=False
+ )
+ retries = False
+
+ # Refactored hbp
+ retries = False
+ while tba[vHand]['hbp']['value'] > 0:
+ assign_chances(
+ res_key='hbp',
+ vs_hand=vHand,
+ remainder_keys=[],
+ allow_retry=retries,
+ rollover_key=f'bb',
+ is_good=True
+ )
+ retries = False
+
+ # Refactored hr
+ retries = True
+ while tba[vHand]['hr']['value'] > 0:
+ assign_chances(
+ res_key='hr',
+ vs_hand=vHand,
+ remainder_keys=['tr', 'do-cf', 'fo-slap', 'fo-cf'],
+ allow_retry=retries,
+ rollover_key=f'do-cf',
+ is_good=True
+ )
+ retries = False
+
+ # Refactored si-cf
+ retries = False
+ while tba[vHand]['si-cf']['value'] > 0:
+ assign_chances(
+ res_key='si-cf',
+ vs_hand=vHand,
+ remainder_keys=['gb-c', 'gb-a'],
+ allow_retry=retries,
+ rollover_key=f'si*',
+ is_good=True
+ )
+ retries = False
+
+ # Refactored tr
+ retries = False
+ while tba[vHand]['tr']['value'] > 0:
+ assign_chances(
+ res_key='tr',
+ vs_hand=vHand,
+ remainder_keys=['do-cf', 'si**', 'fo-cf', 'fo-slap'],
+ allow_retry=retries,
+ rollover_key=f'do-cf',
+ is_good=True
+ )
+ retries = False
+
+ # Refactored do***
+ retries = True
+ while tba[vHand]['do***']['value'] > 0:
+ assign_chances(
+ res_key='do***',
+ vs_hand=vHand,
+ remainder_keys=['do-cf', 'si**', 'fo-cf', 'fo-slap'],
+ allow_retry=retries,
+ rollover_key=f'do-cf',
+ is_good=True
+ )
+ retries = False
+
+ # Refactored do**
+ retries = True
+ while tba[vHand]['do**']['value'] > 0:
+ assign_chances(
+ res_key='do**',
+ vs_hand=vHand,
+ remainder_keys=['si**', 'fo-cf', 'fo-slap', 'gb-c'],
+ allow_retry=retries,
+ rollover_key=f'do-cf',
+ is_good=True
+ )
+ retries = False
+
+ # Refactored do-cf
+ retries = True
+ while tba[vHand]['do-cf']['value'] > 0:
+ assign_chances(
+ res_key='do-cf',
+ vs_hand=vHand,
+ remainder_keys=[f'fo-slap', 'fo-cf', 'gb-c'],
+ allow_retry=retries,
+ rollover_key=f'si**',
+ is_good=True
+ )
+ retries = False
+
+ # Refactored si**
+ retries = True
+ while tba[vHand]['si**']['value'] > 0:
+ assign_chances(
+ res_key='si**',
+ vs_hand=vHand,
+ remainder_keys=['gb-a', 'gb-c'],
+ allow_retry=retries,
+ rollover_key=f'si*',
+ is_good=True
+ )
+ retries = False
+
+ # Refactored si*
+ retries = True
+ while tba[vHand]['si*']['value'] > 0:
+ assign_chances(
+ res_key='si*',
+ vs_hand=vHand,
+ remainder_keys=['gb-c', 'gb-a'],
+ allow_retry=retries,
+ rollover_key=f'bb',
+ is_good=False
+ )
+ retries = False
+
+ # Refactored bb
+ retries = False
+ while tba[vHand]['bb']['value'] > 0:
+ assign_chances(
+ res_key='bb',
+ vs_hand=vHand,
+ remainder_keys=['so'],
+ allow_retry=retries,
+ rollover_key=f'gb-c',
+ is_good=True
+ )
+ retries = False
+
+ # Refactored fo-slap
+ retries = False
+ while tba[vHand]['fo-slap']['value'] > 0:
+ assign_chances(
+ res_key='fo-slap',
+ vs_hand=vHand,
+ remainder_keys=['fo-cf'],
+ allow_retry=retries,
+ rollover_key=f'fo-cf',
+ is_good=False
+ )
+ retries = False
+
+ # Refactored fo-cf
+ retries = False
+ while tba[vHand]['fo-cf']['value'] > 0:
+ assign_chances(
+ res_key='fo-cf',
+ vs_hand=vHand,
+ remainder_keys=[],
+ allow_retry=retries,
+ rollover_key=f'gb-c',
+ is_good=False
+ )
+ retries = False
+
+ # Refactored gb-b
+ retries = False
+ while tba[vHand]['gb-c']['value'] > 0:
+ assign_chances(
+ res_key='gb-c',
+ vs_hand=vHand,
+ remainder_keys=['gb-a'],
+ allow_retry=retries,
+ rollover_key=f'gb-a',
+ is_good=False
+ )
+ retries = False
+
+ # Refactored gb-a
+ retries = False
+ while tba[vHand]['gb-a']['value'] > 0:
+ assign_chances(
+ res_key='gb-a',
+ vs_hand=vHand,
+ remainder_keys=[],
+ allow_retry=retries,
+ rollover_key=f'so',
+ is_good=False
+ )
+ retries = False
+
+ """
+ Whatever result is last should be run through the gap_filler()
+ """
+
+ if testing: print(f'filling in gaps with gb-a')
+ gap_filler(vHand, 'fo-cf')
+
+ if testing:
+ print(f'\n\n******\n\n{player.name} Results:\n{results}\n{tba}')
+ else:
+ print(f'Completed {player.name}')
+ col_output = column_output()
+ if testing: print(f'\n\ncol_output:\n{col_output}\n\n')
+
+ # # Prep csv pitcher lines
+ # logging.info(f'prepping pitcher lines')
+ # card_columns.append(
+ # [player.name, player.sba_id, bat_hand,
+ # col_output['vl_one_2d6'], col_output['vl_one_results'], col_output['vl_one_splits'],
+ # col_output['vl_two_2d6'], col_output['vl_two_results'], col_output['vl_two_splits'],
+ # col_output['vl_three_2d6'], col_output['vl_three_results'], col_output['vl_three_splits'],
+ # col_output['vr_one_2d6'], col_output['vr_one_results'], col_output['vr_one_splits'],
+ # col_output['vr_two_2d6'], col_output['vr_two_results'], col_output['vr_two_splits'],
+ # col_output['vr_three_2d6'], col_output['vr_three_results'], col_output['vr_three_splits']]
+ # )
+
+ for hand in ['vL', 'vR']:
+ logging.info(f'inserting pitcher ratings')
+ p_ratings = {
+ 'id': f'{player.sba_id}-{hand}-{cardset.id}',
+ 'player': player,
+ 'cardset': cardset,
+ 'vs_hand': hand,
+ 'is_prep': False,
+ 'homerun': mround(tba[hand]['hr']['actual']),
+ 'bp_homerun': mround(tba[hand]['bp-hr']['actual']),
+ 'triple': mround(tba[hand]['tr']['actual']),
+ 'double_three': mround(tba[hand]['do***']['actual']),
+ 'double_two': mround(tba[hand]['do**']['actual']),
+ 'double_cf': mround(tba[hand]['do-cf']['actual']),
+ 'single_two': mround(tba[hand]['si**']['actual']),
+ 'single_one': mround(tba[hand]['si*']['actual']),
+ 'single_center': mround(tba[hand]['si-cf']['actual']),
+ 'bp_single': mround(tba[hand]['bp-si']['actual']),
+ 'hbp': mround(tba[hand]['hbp']['actual']),
+ 'walk': mround(tba[hand]['bb']['actual']),
+ 'strikeout': mround(tba[hand]['so']['actual']),
+ 'fo_slap': mround(tba[hand]['fo-slap']['actual']),
+ 'fo_center': mround(tba[hand]['fo-cf']['actual']),
+ 'groundout_a': mround(tba[hand]['gb-a']['actual']),
+ 'groundout_b': mround(tba[hand]['gb-c']['actual']),
+ 'xcheck_p': mround(tba[hand]['gb-x-p']['actual']),
+ 'xcheck_c': mround(tba[hand]['gb-x-c']['actual']),
+ 'xcheck_1b': mround(tba[hand]['gb-x-1b']['actual']),
+ 'xcheck_2b': mround(tba[hand]['gb-x-2b']['actual']),
+ 'xcheck_3b': mround(tba[hand]['gb-x-3b']['actual']),
+ 'xcheck_ss': mround(tba[hand]['gb-x-ss']['actual']),
+ 'xcheck_lf': mround(tba[hand]['gb-x-lf']['actual']),
+ 'xcheck_cf': mround(tba[hand]['gb-x-cf']['actual']),
+ 'xcheck_rf': mround(tba[hand]['gb-x-rf']['actual'])
+ }
+
+ count_hits = (
+ p_ratings['homerun'] + p_ratings['bp_homerun'] / 2 + p_ratings['triple'] +
+ p_ratings['double_three'] + p_ratings['double_two'] + p_ratings['double_cf'] +
+ p_ratings['single_two'] + p_ratings['single_one'] +
+ p_ratings['single_center'] + p_ratings['bp_single'] / 2 +
+ (p_ratings['xcheck_p'] + p_ratings['xcheck_c'] + p_ratings['xcheck_1b'] +
+ p_ratings['xcheck_2b'] + p_ratings['xcheck_3b'] + p_ratings['xcheck_ss'] +
+ p_ratings['xcheck_lf'] + p_ratings['xcheck_cf'] + p_ratings['xcheck_rf']) * .3
+ )
+
+ p_ratings['avg'] = count_hits / 108
+ p_ratings['obp'] = (
+ count_hits + p_ratings['hbp'] + p_ratings['walk']
+ ) / 108
+ p_ratings['slg'] = (
+ (p_ratings['homerun'] * 4) + (p_ratings['triple'] * 3) +
+ ((p_ratings['bp_homerun'] + p_ratings['double_three'] + p_ratings['double_two'] +
+ p_ratings['double_cf']) * 2) +
+ p_ratings['single_two'] + p_ratings['single_one'] + p_ratings['single_center'] +
+ p_ratings['bp_single'] / 2 +
+ (p_ratings['xcheck_p'] + p_ratings['xcheck_c'] + p_ratings['xcheck_1b'] +
+ p_ratings['xcheck_2b'] + p_ratings['xcheck_3b'] + p_ratings['xcheck_ss'] +
+ p_ratings['xcheck_lf'] + p_ratings['xcheck_cf'] + p_ratings['xcheck_rf']) * .3
+ ) / 108
+
+ PitcherRatings.insert(p_ratings).on_conflict_replace().execute()
+
+ logging.info(f'inserting pitcher columns')
+ this_columns = {
+ 'id': f'{player.sba_id}-{hand}-{cardset.id}',
+ 'player': player,
+ 'hand': bat_hand,
+ 'p_ratings_id': f'{player.sba_id}-{hand}-{cardset.id}',
+ 'one_dice': col_output[f'{hand.lower()}_one_2d6'],
+ 'one_results': col_output[f'{hand.lower()}_one_results'],
+ 'one_splits': col_output[f'{hand.lower()}_one_splits'],
+ 'two_dice': col_output[f'{hand.lower()}_two_2d6'],
+ 'two_results': col_output[f'{hand.lower()}_two_results'],
+ 'two_splits': col_output[f'{hand.lower()}_two_splits'],
+ 'three_dice': col_output[f'{hand.lower()}_three_2d6'],
+ 'three_results': col_output[f'{hand.lower()}_three_results'],
+ 'three_splits': col_output[f'{hand.lower()}_three_splits']
+ }
+ CardColumns.insert(this_columns).on_conflict_replace().execute()
+
+ # # Prep csv ratings guide
+ # logging.info(f'prepping pitcher ratings guide')
+ # rg_line = [player.name, bat_hand]
+ # for hand in ['vL', 'vR']:
+ # for x in rg_headers:
+ # if x not in ['name', 'hand']:
+ # rg_line.append(mround(tba[hand][x]['actual']))
+ # ratings_guide.append(rg_line)
+ logging.info(f'completed {player.name}')
+
+ count_pitchers += 1
+
+ # No player match
+ else:
+ logging.error(f'Could not match fangraph player id {row[0]}')
+ print(f'Could not match fangraph player id {row[0]}')
+ except Exception as e:
+ logging.error(f'Failed to process pitcher {row[0]} ({row[2]}): {type(e)}: {e}')
+ print(f'Failed to process pitcher {row[0]} ({row[2]})')
+
+ print(f'Processed {count_pitchers} pitcher stat lines into chances...')
+
+ """
+ Export card output to csv for Component Studio
+ """
+ # # Removed since output has own script now
+ # try:
+ # output_path.mkdir(parents=True)
+ # except FileExistsError as e:
+ # print(f'Directory {output_path} already exists')
+ # write_to_csv(output_path, f'pitcher-ratings-guide-{now.strftime("%Y-%m-%d-%f")}', ratings_guide)
+ # write_to_csv(output_path, f'pitcher-card-columns-{now.strftime("%Y-%m-%d-%f")}', card_columns)
+
+ """
+ END OF PITCHERS
+ """
+
+ lets_go = input(f'Should I run batters (y/n)? ')
+ if lets_go in YES:
+ # https://www.baseball-reference.com/leagues/majors/2022-baserunning-batting.shtml
+ with open(f'{input_path}baserunning-data.csv', 'r') as file:
+ reader = csv.reader(file)
+
+ for row in reader:
+ player = Player.get_or_none(Player.br_id == row[36])
+ if player:
+ dupe = BatterData.delete().where(
+ (BatterData.player == player) & (BatterData.cardset == cardset)
+ ).execute()
+
+ stealing = b.stealing(
+ int(row[8]), int(row[12]), int(row[13]), int(row[14]), int(row[15]), season_pct
+ )
+ this_data = BatterData(
+ player=player,
+ cardset=cardset,
+ stealing=b.stealing_line(stealing),
+ st_low=stealing[0],
+ st_high=stealing[1],
+ st_auto=stealing[2],
+ st_jump=stealing[3],
+ running=b.running(row[26]),
+ hit_and_run='C',
+ bunting='C'
+ )
+ this_data.save()
+
+ else:
+ logging.error(f'Could not match bbref id {row[36]}')
+ print(f'Could not match bbref id {row[36]}')
+
+ existing_columns = CardColumns.delete().where(
+ CardColumns.id.endswith(f'-{cardset.id}') & CardColumns.b_ratings.is_null(False)
+ ).execute()
+ existing_batters = BatterRatings.delete().where(BatterRatings.cardset == cardset).execute()
+
+ # rg_headers = ['name', 'hand', 'hr', 'bp-hr', 'tr', 'do***', 'do**', 'do-pull', 'si**', 'si*', 'si-cf', 'bp-si',
+ # 'hbp', 'bb', 'so', 'lo', 'po', 'fo-a', 'fo-bq', 'fo-lf-b', 'fo-rf-b', 'gb-a', 'gb-b', 'gb-c']
+ # ratings_guide = [[
+ # 'name', 'hand', 'hr-vL', 'bp-hr-vL', 'tr-vL', 'do***-vL', 'do**-vL', 'do-pull-vL', 'si**-vL', 'si*-vL',
+ # 'si-cf-vL', 'bp-si-vL', 'hbp-vL', 'bb-vL', 'so-vL', 'lo-vL', 'po-vL', 'fo-a-vL', 'fo-bq-vL', 'fo-lf-b-vL',
+ # 'fo-rf-b-vL', 'gb-a-vL', 'gb-b-vL', 'gb-c-vL', 'hr-vR', 'bp-hr-vR', 'tr-vR', 'do***-vR', 'do**-vR',
+ # 'do-pull-vR', 'si**-vR', 'si*-vR', 'si-cf-vR', 'bp-si-vR', 'hbp-vR', 'bb-vR', 'so-vR', 'lo-vR', 'po-vR',
+ # 'fo-a-vR', 'fo-bq-vR', 'fo-lf-b-vR', 'fo-rf-b-vR', 'gb-a-vR', 'gb-b-vR', 'gb-c-vR'
+ # ]]
+ # all_results = [['name', 'sba_id', 'hand', 'vl_one_2d6', 'vl_one_results', 'vl_one_splits',
+ # 'vl_two_2d6', 'vl_two_results', 'vl_two_splits',
+ # 'vl_three_2d6', 'vl_three_results', 'vl_three_splits',
+ # 'vr_one_2d6', 'vr_one_results', 'vr_one_splits',
+ # 'vr_two_2d6', 'vr_two_results', 'vr_two_splits',
+ # 'vr_three_2d6', 'vr_three_results', 'vr_three_splits']]
+
+ with open(f'{input_path}batter-stats.csv', 'r') as file:
+ reader = csv.reader(file)
+
+ for row in reader:
+ player = Player.get_or_none(Player.fg_id == int(row[0]))
+ if player and (('Promo' in cardset.set_title) or ('Major League' in cardset.set_title) or
+ (int(row[5]) >= 28 and int(row[39]) >= 58)):
+ chance_data_vl = {
+ 'id': f'{player.sba_id}-vL-{cardset.id}-bat',
+ 'player_id': player.sba_id,
+ 'cardset_id': cardset.id,
+ 'vs_hand': 'vL',
+ 'is_prep': True,
+ 'homerun': 0,
+ 'bp_homerun': 0,
+ 'triple': 0,
+ 'double_three': 0,
+ 'double_two': 0,
+ 'double_pull': 0,
+ 'single_two': 0,
+ 'single_one': 0,
+ 'single_center': 0,
+ 'bp_single': 0,
+ 'hbp': 0,
+ 'walk': 0,
+ 'strikeout': 0,
+ 'lineout': 0,
+ 'popout': 0,
+ 'flyout_a': 0,
+ 'flyout_bq': 0,
+ 'flyout_lf_b': 0,
+ 'flyout_rf_b': 0,
+ 'groundout_a': 0,
+ 'groundout_b': 0,
+ 'groundout_c': 0,
+ }
+ chance_data_vr = {
+ 'id': f'{player.sba_id}-vR-{cardset.id}-bat',
+ 'player_id': player.sba_id,
+ 'cardset_id': cardset.id,
+ 'vs_hand': 'vR',
+ 'is_prep': True,
+ 'homerun': 0,
+ 'bp_homerun': 0,
+ 'triple': 0,
+ 'double_three': 0,
+ 'double_two': 0,
+ 'double_pull': 0,
+ 'single_two': 0,
+ 'single_one': 0,
+ 'single_center': 0,
+ 'bp_single': 0,
+ 'hbp': 0,
+ 'walk': 0,
+ 'strikeout': 0,
+ 'lineout': 0,
+ 'popout': 0,
+ 'flyout_a': 0,
+ 'flyout_bq': 0,
+ 'flyout_lf_b': 0,
+ 'flyout_rf_b': 0,
+ 'groundout_a': 0,
+ 'groundout_b': 0,
+ 'groundout_c': 0,
+ }
+ bat_hand = player.hand
+
+ # Turn sheets workflow into code here
+
+ offense_mod = 1.2
+ all_hits_vl = mround(108 * offense_mod * float(row[23]))
+ all_hits_vr = mround(108 * offense_mod * float(row[57]))
+
+ hard_rate_vl = float(row[38])
+ hard_rate_vr = float(row[72])
+ med_rate_vl = float(row[37])
+ med_rate_vr = float(row[71])
+ soft_rate_vl = float(row[36])
+ soft_rate_vr = float(row[70])
+
+ if int(row[7]) == 0:
+ all_singles_vl = 0.0
+ else:
+ all_singles_vl = mround(all_hits_vl * (float(row[8]) / float(row[7])))
+ if int(row[41]) == 0:
+ all_singles_vr = 0.0
+ else:
+ all_singles_vr = mround(all_hits_vr * (float(row[42]) / float(row[41])))
+
+ chance_data_vl['bp_single'] = b.bp_singles(all_singles_vl)
+ chance_data_vr['bp_single'] = b.bp_singles(all_singles_vr)
+
+ chance_data_vl['single_two'] = b.wh_singles(
+ mround(all_singles_vl - chance_data_vl['bp_single']), hard_rate_vl
+ )
+ chance_data_vr['single_two'] = b.wh_singles(
+ mround(all_singles_vr - chance_data_vr['bp_single']), hard_rate_vr
+ )
+
+ chance_data_vl['single_one'] = b.one_singles(
+ mround(all_singles_vl - chance_data_vl['bp_single'] - chance_data_vl['single_two']),
+ ifh_rate=float(row[31]),
+ force_rem=True if chance_data_vl['single_two'] == 0 else False
+ )
+ chance_data_vr['single_one'] = b.one_singles(
+ mround(all_singles_vr - chance_data_vr['bp_single'] - chance_data_vr['single_two']),
+ ifh_rate=float(row[65]),
+ force_rem=True if chance_data_vr['single_two'] == 0 else False
+ )
+
+ chance_data_vl['single_center'] = mround(
+ all_singles_vl - chance_data_vl['bp_single'] - chance_data_vl['single_two'] -
+ chance_data_vl['single_one']
+ )
+ chance_data_vr['single_center'] = mround(
+ all_singles_vr - chance_data_vr['bp_single'] - chance_data_vr['single_two'] -
+ chance_data_vr['single_one']
+ )
+
+ total_singles_vl = (
+ chance_data_vl['bp_single'] + chance_data_vl['single_two'] + chance_data_vl['single_one'] +
+ chance_data_vl['single_center']
+ )
+ total_singles_vr = (
+ chance_data_vr['bp_single'] + chance_data_vr['single_two'] + chance_data_vr['single_one'] +
+ chance_data_vr['single_center']
+ )
+ rem_hits_vl = all_hits_vl - total_singles_vl
+ rem_hits_vr = all_hits_vr - total_singles_vr
+
+ all_hr_vl = b.all_homeruns(rem_hits_vl, all_hits_vl, float(row[11]), float(row[7]), float(row[8]))
+ all_hr_vr = b.all_homeruns(
+ rem_hits_vr, all_hits_vr, float(row[45]), float(row[41]), float(row[42])
+ )
+
+ chance_data_vl['homerun'] = b.nd_homeruns(all_hr_vl, float(row[30]))
+ chance_data_vr['homerun'] = b.nd_homeruns(all_hr_vr, float(row[64]))
+ chance_data_vl['bp_homerun'] = mround(all_hr_vl - chance_data_vl['homerun'])
+ chance_data_vr['bp_homerun'] = mround(all_hr_vr - chance_data_vr['homerun'])
+
+ total_hr_vl = mround(chance_data_vl['homerun'] + chance_data_vl['bp_homerun'])
+ total_hr_vr = mround(chance_data_vr['homerun'] + chance_data_vr['bp_homerun'])
+
+ all_xbh_vl = mround(all_hits_vl - total_singles_vl - total_hr_vl)
+ all_xbh_vr = mround(all_hits_vr - total_singles_vr - total_hr_vr)
+
+ chance_data_vl['triple'] = b.triples(
+ all_xbh_vl, float(row[10]), float(row[9])
+ )
+ chance_data_vr['triple'] = b.triples(
+ all_xbh_vr, float(row[44]), float(row[43])
+ )
+
+ all_doubles_vl = mround(all_xbh_vl - chance_data_vl['triple'])
+ all_doubles_vr = mround(all_xbh_vr - chance_data_vr['triple'])
+
+ chance_data_vl['double_two'] = b.two_doubles(all_doubles_vl, soft_rate_vl)
+ chance_data_vr['double_two'] = b.two_doubles(all_doubles_vr, soft_rate_vr)
+ chance_data_vl['double_pull'] = mround(all_doubles_vl - chance_data_vl['double_two'])
+ chance_data_vr['double_pull'] = mround(all_doubles_vr - chance_data_vr['double_two'])
+
+ total_doubles_vl = mround(chance_data_vl['double_two'] + chance_data_vl['double_pull'])
+ total_doubles_vr = mround(chance_data_vr['double_two'] + chance_data_vr['double_pull'])
+
+ other_ob_vl = mround(108 * offense_mod * ((float(row[14]) + float(row[17])) / float(row[5])))
+ other_ob_vr = mround(108 * offense_mod * ((float(row[48]) + float(row[51])) / float(row[39])))
+
+ chance_data_vl['hbp'] = b.hit_by_pitch(other_ob_vl, float(row[17]), float(row[14]))
+ chance_data_vr['hbp'] = b.hit_by_pitch(other_ob_vr, float(row[51]), float(row[48]))
+ chance_data_vl['walk'] = mround(other_ob_vl - chance_data_vl['hbp'])
+ chance_data_vr['walk'] = mround(other_ob_vr - chance_data_vr['hbp'])
+
+ all_outs_vl = mround(108 - all_hits_vl - other_ob_vl)
+ all_outs_vr = mround(108 - all_hits_vr - other_ob_vr)
+
+ chance_data_vl['strikeout'] = b.strikeouts(all_outs_vl, float(row[16]) / float(row[5]))
+ chance_data_vr['strikeout'] = b.strikeouts(all_outs_vr, float(row[50]) / float(row[39]))
+
+ rem_outs_vl = mround(all_outs_vl - chance_data_vl['strikeout'])
+ rem_outs_vr = mround(all_outs_vr - chance_data_vr['strikeout'])
+
+ lineouts_vl = max(mround(rem_outs_vl * float(row[26])), 1)
+ lineouts_vr = max(mround(rem_outs_vr * float(row[60])), 1)
+ chance_data_vl['popout'] = b.popouts(lineouts_vl - 1, float(row[29]))
+ chance_data_vr['popout'] = b.popouts(lineouts_vr - 1, float(row[63]))
+ chance_data_vl['lineout'] = mround(lineouts_vl - chance_data_vl['popout'])
+ chance_data_vr['lineout'] = mround(lineouts_vr - chance_data_vr['popout'])
+
+ rem_outs_vl = mround(rem_outs_vl - chance_data_vl['lineout'] - chance_data_vl['popout'])
+ rem_outs_vr = mround(rem_outs_vr - chance_data_vr['lineout'] - chance_data_vr['popout'])
+ flyouts_vl = mround(rem_outs_vl * float(row[28]))
+ flyouts_vr = mround(rem_outs_vr * float(row[62]))
+
+ chance_data_vl['flyout_a'] = b.flyout_a(flyouts_vl, hard_rate_vl)
+ chance_data_vr['flyout_a'] = b.flyout_a(flyouts_vr, hard_rate_vr)
+ rem_flyouts_vl = mround(flyouts_vl - chance_data_vl['flyout_a'])
+ rem_flyouts_vr = mround(flyouts_vr - chance_data_vr['flyout_a'])
+ chance_data_vl['flyout_bq'] = b.flyout_bq(rem_flyouts_vl, soft_rate_vl)
+ chance_data_vr['flyout_bq'] = b.flyout_bq(rem_flyouts_vr, soft_rate_vr)
+ rem_flyouts_vl = mround(flyouts_vl - chance_data_vl['flyout_bq'])
+ rem_flyouts_vr = mround(flyouts_vr - chance_data_vr['flyout_bq'])
+ chance_data_vl['flyout_lf_b'] = b.flyout_b(
+ rem_flyouts_vl,
+ float(row[33]) if bat_hand.lower() == 'r' else float(row[35]),
+ float(row[34])
+ )
+ chance_data_vr['flyout_lf_b'] = b.flyout_b(
+ rem_flyouts_vr,
+ float(row[67]) if bat_hand.lower() == 'r' else float(row[69]),
+ float(row[68])
+ )
+ chance_data_vl['flyout_rf_b'] = mround(rem_flyouts_vl - chance_data_vl['flyout_lf_b'])
+ chance_data_vr['flyout_rf_b'] = mround(rem_flyouts_vr - chance_data_vr['flyout_lf_b'])
+
+ rem_outs_vl = mround(rem_outs_vl - flyouts_vl)
+ rem_outs_vr = mround(rem_outs_vr - flyouts_vr)
+ groundouts_vl = mround(rem_outs_vl)
+ groundouts_vr = mround(rem_outs_vr)
+
+ chance_data_vl['groundout_a'] = b.groundball_a(groundouts_vl, float(row[20]), float(row[6]))
+ chance_data_vr['groundout_a'] = b.groundball_a(groundouts_vr, float(row[54]), float(row[40]))
+ chance_data_vl['groundout_c'] = b.groundball_c(
+ groundouts_vl - chance_data_vl['groundout_a'], med_rate_vl
+ )
+ chance_data_vr['groundout_c'] = b.groundball_c(
+ groundouts_vr - chance_data_vr['groundout_a'], med_rate_vr
+ )
+ chance_data_vl['groundout_b'] = mround(
+ groundouts_vl - chance_data_vl['groundout_a'] - chance_data_vl['groundout_c']
+ )
+ chance_data_vr['groundout_b'] = mround(
+ groundouts_vr - chance_data_vr['groundout_a'] - chance_data_vr['groundout_c']
+ )
+
+ if testing:
+ print(f'vL: {chance_data_vl}\nvR: {chance_data_vr}')
+ print(f'total chances vL: {b.total_chances(chance_data_vl)} / '
+ f'vR: {b.total_chances(chance_data_vr)}')
+
+ BatterRatings.insert(chance_data_vl).on_conflict_replace().execute()
+ BatterRatings.insert(chance_data_vr).on_conflict_replace().execute()
+
+ b_data = BatterData.select().where(
+ (BatterData.player == player) & (BatterData.cardset == cardset)
+ ).limit(1)
+ if b_data.count() == 1:
+ babip = (all_hits_vl + all_hits_vr - all_hr_vl - all_hr_vr) / \
+ (216 - chance_data_vl['strikeout'] - chance_data_vr['strikeout'] +
+ chance_data_vl['flyout_lf_b'] + chance_data_vr['flyout_lf_b'] - all_hr_vl - all_hr_vr)
+
+ if babip >= .35:
+ hnr = 'A'
+ elif babip >= .3:
+ hnr = 'B'
+ elif babip >= .225:
+ hnr = 'C'
+ else:
+ hnr = 'D'
+
+ b_data[0].hit_and_run = hnr
+ b_data[0].save()
+ else:
+ print(f'No BatterData for {player.name}')
+
+ """
+ Process batter chances into card output
+ """
+
+ bat_hand = player.hand
+ tba = {
+ 'vL': {
+ 'bp-si': {
+ 'value': chance_data_vl['bp_single'],
+ 'string': '▼BP-SI',
+ 'bold': True,
+ 'actual': 0
+ },
+ 'si-cf': {
+ 'value': chance_data_vl['single_center'],
+ 'string': 'SINGLE (cf)',
+ 'sm-string': 'SI (cf)',
+ 'bold': True,
+ 'actual': 0
+ },
+ 'si*': {
+ 'value': chance_data_vl['single_one'],
+ 'string': 'SINGLE*',
+ 'sm-string': 'SI*',
+ 'bold': True,
+ 'actual': 0
+ },
+ 'si**': {
+ 'value': chance_data_vl['single_two'],
+ 'string': 'SINGLE**',
+ 'sm-string': 'SI**',
+ 'bold': True,
+ 'actual': 0
+ },
+ 'bp-hr': {
+ 'value': chance_data_vl['bp_homerun'],
+ 'string': '◆BP-HR',
+ 'bold': True,
+ 'actual': 0
+ },
+ 'hr': {
+ 'value': chance_data_vl['homerun'],
+ 'string': 'HOMERUN',
+ 'sm-string': 'HR',
+ 'bold': True,
+ 'actual': 0
+ },
+ 'tr': {
+ 'value': chance_data_vl['triple'],
+ 'string': 'TRIPLE',
+ 'sm-string': 'TR',
+ 'bold': True,
+ 'actual': 0
+ },
+ 'do**': {
+ 'value': chance_data_vl['double_two'],
+ 'string': 'DOUBLE**',
+ 'sm-string': 'DO**',
+ 'bold': True,
+ 'actual': 0
+ },
+ 'do***': {
+ 'value': chance_data_vl['double_three'],
+ 'string': 'DOUBLE***',
+ 'sm-string': 'DO***',
+ 'bold': True,
+ 'actual': 0
+ },
+ 'do-pull': {
+ 'value': chance_data_vl['double_pull'],
+ 'string': f'DOUBLE ({"rf" if bat_hand == "L" else "lf"})',
+ 'sm-string': f'DO ({"rf" if bat_hand == "L" else "lf"})',
+ 'bold': True,
+ 'actual': 0
+ },
+ 'hbp': {
+ 'value': chance_data_vl['hbp'],
+ 'string': 'HBP',
+ 'bold': True,
+ 'actual': 0
+ },
+ 'bb': {
+ 'value': chance_data_vl['walk'],
+ 'string': 'WALK',
+ 'bold': True,
+ 'actual': 0
+ },
+ 'so': {
+ 'value': chance_data_vl['strikeout'],
+ 'string': 'strikeout',
+ 'bold': False,
+ 'actual': 0
+ },
+ 'lo': {
+ 'value': chance_data_vl['lineout'],
+ 'string': f'lineout ({"ss" if bat_hand == "L" else "2b"})',
+ 'sm-string': f'lo ({"ss" if bat_hand == "L" else "2b"})',
+ 'bold': False,
+ 'actual': 0
+ },
+ 'po': {
+ 'value': chance_data_vl['popout'],
+ 'string': f'popout ({"2b" if bat_hand == "L" else "ss"})',
+ 'bold': False,
+ 'actual': 0
+ },
+ 'fo-a': {
+ 'value': chance_data_vl['flyout_a'],
+ 'string': f'fly (cf) A',
+ 'bold': False,
+ 'actual': 0
+ },
+ 'fo-bq': {
+ 'value': chance_data_vl['flyout_bq'],
+ 'string': f'fly (cf) B?',
+ 'bold': False,
+ 'actual': 0
+ },
+ 'fo-lf-b': {
+ 'value': chance_data_vl['flyout_lf_b'],
+ 'string': f'fly (lf) B',
+ 'bold': False,
+ 'actual': 0
+ },
+ 'fo-rf-b': {
+ 'value': chance_data_vl['flyout_rf_b'],
+ 'string': f'fly (rf) B',
+ 'bold': False,
+ 'actual': 0
+ },
+ 'gb-a': {
+ 'value': chance_data_vl['groundout_a'],
+ 'string': f'gb ({"2b" if bat_hand == "L" else "ss"}) A',
+ 'bold': False,
+ 'actual': 0
+ },
+ 'gb-b': {
+ 'value': chance_data_vl['groundout_b'],
+ 'string': f'gb ({"ss" if bat_hand == "L" else "2b"}) B',
+ 'bold': False,
+ 'actual': 0
+ },
+ 'gb-c': {
+ 'value': chance_data_vl['groundout_c'],
+ 'string': f'gb ({"3b" if bat_hand == "L" else "1b"}) B',
+ 'bold': False,
+ 'actual': 0
+ }
+ },
+ 'vR': {
+ 'bp-si': {
+ 'value': chance_data_vr['bp_single'],
+ 'string': '▼BP-SI',
+ 'bold': True,
+ 'actual': 0
+ },
+ 'si-cf': {
+ 'value': chance_data_vr['single_center'],
+ 'string': 'SINGLE (cf)',
+ 'sm-string': 'SI (cf)',
+ 'bold': True,
+ 'actual': 0
+ },
+ 'si*': {
+ 'value': chance_data_vr['single_one'],
+ 'string': 'SINGLE*',
+ 'sm-string': 'SI*',
+ 'bold': True,
+ 'actual': 0
+ },
+ 'si**': {
+ 'value': chance_data_vr['single_two'],
+ 'string': 'SINGLE**',
+ 'sm-string': 'SI**',
+ 'bold': True,
+ 'actual': 0
+ },
+ 'bp-hr': {
+ 'value': chance_data_vr['bp_homerun'],
+ 'string': '◆BP-HR',
+ 'bold': True,
+ 'actual': 0
+ },
+ 'hr': {
+ 'value': chance_data_vr['homerun'],
+ 'string': 'HOMERUN',
+ 'sm-string': 'HR',
+ 'bold': True,
+ 'actual': 0
+ },
+ 'tr': {
+ 'value': chance_data_vr['triple'],
+ 'string': 'TRIPLE',
+ 'sm-string': 'TR',
+ 'bold': True,
+ 'actual': 0
+ },
+ 'do**': {
+ 'value': chance_data_vr['double_two'],
+ 'string': 'DOUBLE**',
+ 'sm-string': 'DO**',
+ 'bold': True,
+ 'actual': 0
+ },
+ 'do***': {
+ 'value': chance_data_vr['double_three'],
+ 'string': 'DOUBLE***',
+ 'sm-string': 'DO***',
+ 'bold': True,
+ 'actual': 0
+ },
+ 'do-pull': {
+ 'value': chance_data_vr['double_pull'],
+ 'string': f'DOUBLE ({"rf" if bat_hand == "L" else "lf"})',
+ 'sm-string': f'DO ({"rf" if bat_hand == "L" else "lf"})',
+ 'bold': True,
+ 'actual': 0
+ },
+ 'hbp': {
+ 'value': chance_data_vr['hbp'],
+ 'string': 'HBP',
+ 'bold': True,
+ 'actual': 0
+ },
+ 'bb': {
+ 'value': chance_data_vr['walk'],
+ 'string': 'WALK',
+ 'bold': True,
+ 'actual': 0
+ },
+ 'so': {
+ 'value': chance_data_vr['strikeout'],
+ 'string': 'strikeout',
+ 'bold': False,
+ 'actual': 0
+ },
+ 'lo': {
+ 'value': chance_data_vr['lineout'],
+ 'string': f'lineout ({"ss" if bat_hand == "L" else "2b"})',
+ 'sm-string': f'lo ({"ss" if bat_hand == "L" else "2b"})',
+ 'bold': False,
+ 'actual': 0
+ },
+ 'po': {
+ 'value': chance_data_vr['popout'],
+ 'string': f'popout ({"2b" if bat_hand == "L" else "ss"})',
+ 'bold': False,
+ 'actual': 0
+ },
+ 'fo-a': {
+ 'value': chance_data_vr['flyout_a'],
+ 'string': f'fly (cf) A',
+ 'bold': False,
+ 'actual': 0
+ },
+ 'fo-bq': {
+ 'value': chance_data_vr['flyout_bq'],
+ 'string': f'fly (cf) B?',
+ 'bold': False,
+ 'actual': 0
+ },
+ 'fo-lf-b': {
+ 'value': chance_data_vr['flyout_lf_b'],
+ 'string': f'fly (lf) B',
+ 'bold': False,
+ 'actual': 0
+ },
+ 'fo-rf-b': {
+ 'value': chance_data_vr['flyout_rf_b'],
+ 'string': f'fly (rf) B',
+ 'bold': False,
+ 'actual': 0
+ },
+ 'gb-a': {
+ 'value': chance_data_vr['groundout_a'],
+ 'string': f'gb ({"2b" if bat_hand == "L" else "ss"}) A',
+ 'bold': False,
+ 'actual': 0
+ },
+ 'gb-b': {
+ 'value': chance_data_vr['groundout_b'],
+ 'string': f'gb ({"ss" if bat_hand == "L" else "2b"}) B',
+ 'bold': False,
+ 'actual': 0
+ },
+ 'gb-c': {
+ 'value': chance_data_vr['groundout_c'],
+ 'string': f'gb ({"3b" if bat_hand == "L" else "1b"}) B',
+ 'bold': False,
+ 'actual': 0
+ }
+ }
+ }
+ results = copy.deepcopy(BLANK_RESULTS)
+
+ def column_output():
+ card_output = {}
+
+ for hand in ['vL', 'vR']:
+ for col in ['1', '2', '3']:
+ card_output[f'{hand.lower()}_{get_col(col)}_2d6'] = ''
+ card_output[f'{hand.lower()}_{get_col(col)}_results'] = ''
+ card_output[f'{hand.lower()}_{get_col(col)}_splits'] = ''
+
+ for hand in ['vL', 'vR']:
+ for col in ['1', '2', '3']:
+ int_results = {}
+ for x in results[hand][col]:
+ try:
+ int_results[int(x)] = results[hand][col][x]
+ except ValueError as e:
+ if testing:
+ print(f'skipping {x} in column_output')
+
+ if testing: print(f'{int_results}')
+
+ sorted_results = {
+ row_num: int_results[row_num] for row_num in sorted(int_results.keys())
+ }
+ for line in sorted_results:
+ if testing: print(f'\nsorted_results: {sorted_results}\nline: {line}')
+ if sorted_results[line]["result"]:
+ card_output[f'{hand.lower()}_{get_col(col)}_2d6'] += \
+ f'{results[hand][col][str(line)]["2d6"]}\n'
+ card_output[f'{hand.lower()}_{get_col(col)}_results'] += \
+ f'{results[hand][col][str(line)]["result"]}\n'
+ card_output[f'{hand.lower()}_{get_col(col)}_splits'] += \
+ f'{results[hand][col][str(line)]["splits"]}\n'
+
+ return card_output
+
+ def add_full_result(vs_hand, tba_data, is_good, chances):
+ all_cols = []
+ good_col = player.offense_col
+ if is_good:
+ if good_col == 1:
+ second = random.choice([2, 3])
+ all_cols = [1, second, 3 if second == 2 else 2]
+ elif good_col == 2:
+ second = random.choice([1, 3])
+ all_cols = [2, second, 3 if second == 1 else 1]
+ elif good_col == 3:
+ second = random.choice([1, 2])
+ all_cols = [3, second, 1 if second == 1 else 2]
+ else:
+ if good_col == 1:
+ f_col = random.choice([2, 3])
+ all_cols = [f_col, 3 if f_col == 2 else 2, 1]
+ elif good_col == 2:
+ f_col = random.choice([1, 3])
+ all_cols = [f_col, 3 if f_col == 1 else 1, 2]
+ elif good_col == 3:
+ f_col = random.choice([1, 2])
+ all_cols = [f_col, 1 if f_col == 1 else 2, 3]
+
+ if chances == 6:
+ for column in all_cols:
+ if not results[vs_hand][f'{column}']['7']['result']:
+ results[vs_hand][f'{column}']['7'] = result_data(tba_data, 7)
+ return chances
+ if not results[vs_hand][f'{column}']['6']['result'] and not \
+ results[vs_hand][f'{column}']['2']['result']:
+ results[vs_hand][f'{column}']['6'] = result_data(tba_data, 6)
+ results[vs_hand][f'{column}']['2'] = result_data(tba_data, 2)
+ return chances
+ if not results[vs_hand][f'{column}']['8']['result'] and not \
+ results[vs_hand][f'{column}']['12']['result']:
+ results[vs_hand][f'{column}']['8'] = result_data(tba_data, 8)
+ results[vs_hand][f'{column}']['12'] = result_data(tba_data, 12)
+ return chances
+ if not results[vs_hand][f'{column}']['6']['result'] and not \
+ results[vs_hand][f'{column}']['12']['result']:
+ results[vs_hand][f'{column}']['6'] = result_data(tba_data, 6)
+ results[vs_hand][f'{column}']['12'] = result_data(tba_data, 12)
+ return chances
+ if not results[vs_hand][f'{column}']['8']['result'] and not \
+ results[vs_hand][f'{column}']['2']['result']:
+ results[vs_hand][f'{column}']['8'] = result_data(tba_data, 8)
+ results[vs_hand][f'{column}']['2'] = result_data(tba_data, 2)
+ return chances
+
+ # No matches
+ return 0
+
+ elif chances == 5:
+ for column in all_cols:
+ if not results[vs_hand][f'{column}']['6']['result']:
+ results[vs_hand][f'{column}']['6'] = result_data(tba_data, 6)
+ return chances
+ if not results[vs_hand][f'{column}']['8']['result']:
+ results[vs_hand][f'{column}']['8'] = result_data(tba_data, 8)
+ return chances
+ if not results[vs_hand][f'{column}']['3']['result'] and not \
+ results[vs_hand][f'{column}']['4']['result']:
+ results[vs_hand][f'{column}']['3'] = result_data(tba_data, 3)
+ results[vs_hand][f'{column}']['4'] = result_data(tba_data, 4)
+ return chances
+ if not results[vs_hand][f'{column}']['3']['result'] and not \
+ results[vs_hand][f'{column}']['10']['result']:
+ results[vs_hand][f'{column}']['3'] = result_data(tba_data, 3)
+ results[vs_hand][f'{column}']['10'] = result_data(tba_data, 10)
+ return chances
+ if not results[vs_hand][f'{column}']['4']['result'] and not \
+ results[vs_hand][f'{column}']['11']['result']:
+ results[vs_hand][f'{column}']['4'] = result_data(tba_data, 4)
+ results[vs_hand][f'{column}']['11'] = result_data(tba_data, 11)
+ return chances
+ if not results[vs_hand][f'{column}']['10']['result'] and not \
+ results[vs_hand][f'{column}']['11']['result']:
+ results[vs_hand][f'{column}']['10'] = result_data(tba_data, 10)
+ results[vs_hand][f'{column}']['11'] = result_data(tba_data, 11)
+ return chances
+
+ # No matches
+ return 0
+
+ elif chances == 4:
+ for column in all_cols:
+ if not results[vs_hand][f'{column}']['5']['result']:
+ results[vs_hand][f'{column}']['5'] = result_data(tba_data, 5)
+ return chances
+ if not results[vs_hand][f'{column}']['9']['result']:
+ results[vs_hand][f'{column}']['9'] = result_data(tba_data, 9)
+ return chances
+ if not results[vs_hand][f'{column}']['3']['result'] and not \
+ results[vs_hand][f'{column}']['11']['result']:
+ results[vs_hand][f'{column}']['3'] = result_data(tba_data, 3)
+ results[vs_hand][f'{column}']['11'] = result_data(tba_data, 11)
+ return chances
+ if not results[vs_hand][f'{column}']['2']['result'] and not \
+ results[vs_hand][f'{column}']['4']['result']:
+ results[vs_hand][f'{column}']['2'] = result_data(tba_data, 2)
+ results[vs_hand][f'{column}']['4'] = result_data(tba_data, 4)
+ return chances
+ if not results[vs_hand][f'{column}']['10']['result'] and not \
+ results[vs_hand][f'{column}']['12']['result']:
+ results[vs_hand][f'{column}']['10'] = result_data(tba_data, 10)
+ results[vs_hand][f'{column}']['12'] = result_data(tba_data, 12)
+ return chances
+ if not results[vs_hand][f'{column}']['2']['result'] and not \
+ results[vs_hand][f'{column}']['10']['result']:
+ results[vs_hand][f'{column}']['2'] = result_data(tba_data, 2)
+ results[vs_hand][f'{column}']['10'] = result_data(tba_data, 10)
+ return chances
+ if not results[vs_hand][f'{column}']['10']['result'] and not \
+ results[vs_hand][f'{column}']['4']['result']:
+ results[vs_hand][f'{column}']['10'] = result_data(tba_data, 10)
+ results[vs_hand][f'{column}']['4'] = result_data(tba_data, 4)
+ return chances
+
+ return 0
+
+ elif chances == 3:
+ for column in all_cols:
+ if not results[vs_hand][f'{column}']['4']['result']:
+ results[vs_hand][f'{column}']['4'] = result_data(tba_data, 4)
+ return chances
+ if not results[vs_hand][f'{column}']['10']['result']:
+ results[vs_hand][f'{column}']['10'] = result_data(tba_data, 10)
+ return chances
+ if not results[vs_hand][f'{column}']['2']['result'] and not \
+ results[vs_hand][f'{column}']['3']['result']:
+ results[vs_hand][f'{column}']['2'] = result_data(tba_data, 2)
+ results[vs_hand][f'{column}']['3'] = result_data(tba_data, 3)
+ return chances
+ if not results[vs_hand][f'{column}']['2']['result'] and not \
+ results[vs_hand][f'{column}']['11']['result']:
+ results[vs_hand][f'{column}']['2'] = result_data(tba_data, 2)
+ results[vs_hand][f'{column}']['11'] = result_data(tba_data, 11)
+ return chances
+ if not results[vs_hand][f'{column}']['12']['result'] and not \
+ results[vs_hand][f'{column}']['3']['result']:
+ results[vs_hand][f'{column}']['12'] = result_data(tba_data, 12)
+ results[vs_hand][f'{column}']['3'] = result_data(tba_data, 3)
+ return chances
+ if not results[vs_hand][f'{column}']['12']['result'] and not \
+ results[vs_hand][f'{column}']['11']['result']:
+ results[vs_hand][f'{column}']['12'] = result_data(tba_data, 12)
+ results[vs_hand][f'{column}']['11'] = result_data(tba_data, 11)
+ return chances
+
+ return 0
+
+ elif chances == 2:
+ for column in all_cols:
+ if not results[vs_hand][f'{column}']['3']['result']:
+ results[vs_hand][f'{column}']['3'] = result_data(tba_data, 3)
+ return chances
+ if not results[vs_hand][f'{column}']['11']['result']:
+ results[vs_hand][f'{column}']['11'] = result_data(tba_data, 11)
+ return chances
+ if not results[vs_hand][f'{column}']['2']['result'] and not \
+ results[vs_hand][f'{column}']['12']['result']:
+ results[vs_hand][f'{column}']['2'] = result_data(tba_data, 2)
+ results[vs_hand][f'{column}']['12'] = result_data(tba_data, 12)
+ return chances
+
+ return 0
+
+ elif chances == 1:
+ for column in all_cols:
+ if not results[vs_hand][f'{column}']['2']['result']:
+ results[vs_hand][f'{column}']['2'] = result_data(tba_data, 2)
+ return chances
+ if not results[vs_hand][f'{column}']['12']['result']:
+ results[vs_hand][f'{column}']['12'] = result_data(tba_data, 12)
+ return chances
+ return 0
+
+ def add_split_result(vs_hand, tba_data_top, tba_data_bottom, chances_top, is_good=None):
+ all_cols = []
+ good_col = player.offense_col
+
+ if is_good is None:
+ if good_col == 1:
+ f_col = random.choice([2, 3])
+ all_cols = [f_col, 1, 3 if f_col == 2 else 2]
+ elif good_col == 2:
+ f_col = random.choice([1, 3])
+ all_cols = [f_col, 2, 3 if f_col == 1 else 1]
+ elif good_col == 3:
+ f_col = random.choice([1, 2])
+ all_cols = [f_col, 3, 1 if f_col == 1 else 2]
+
+ elif is_good:
+ if good_col == 1:
+ second = random.choice([2, 3])
+ all_cols = [1, second, 3 if second == 2 else 2]
+ elif good_col == 2:
+ second = random.choice([1, 3])
+ all_cols = [2, second, 3 if second == 1 else 1]
+ elif good_col == 3:
+ second = random.choice([1, 2])
+ all_cols = [3, second, 1 if second == 1 else 2]
+
+ else:
+ if good_col == 1:
+ f_col = random.choice([2, 3])
+ all_cols = [f_col, 3 if f_col == 2 else 2, 1]
+ elif good_col == 2:
+ f_col = random.choice([1, 3])
+ all_cols = [f_col, 3 if f_col == 1 else 1, 2]
+ elif good_col == 3:
+ f_col = random.choice([1, 2])
+ all_cols = [f_col, 1 if f_col == 1 else 2, 3]
+
+ legal_2d6 = legal_splits(chances_top)
+ for column in all_cols:
+ if results[vs_hand][f'{column}']['splits'] < 3:
+ for y in legal_2d6:
+ if tba_data_bottom['value'] >= y['bad_chances'] and not \
+ results[vs_hand][f'{column}'][f'{y["2d6"]}']['result']:
+ results[vs_hand][f'{column}'][f'{y["2d6"]}'] = \
+ result_data(tba_data_top, y["2d6"], tba_data_bottom, y["incs"])
+ results[vs_hand][f'{column}']['splits'] += 1
+ return y['bad_chances']
+
+ if testing: print(f'Legal 2d6: {legal_2d6}')
+ if testing: print(f'Could not find a legal spot for:\n{tba_data_top}\n{tba_data_bottom}')
+ return None
+
+ def assign_chances(
+ res_key: str, vs_hand: str, remainder_keys: list[str], allow_retry: bool, rollover_key: str,
+ is_good: bool, force_whole: bool = False):
+ retries = 0 if allow_retry else 1
+
+ if testing: print(f'starting {res_key}: {tba[vs_hand][res_key]["value"]}')
+ # If not even int, add_split_result with less than half of total chances
+ total_chances = mround(tba[vs_hand][res_key]['value'])
+ # chance_remainder = mround(total_chances - math.floor(total_chances))
+
+ # If total chance is a whole number, do easy assignments first
+ if int(total_chances) - total_chances == 0 or force_whole or tba[vs_hand][res_key]['value'] > 2:
+ if testing: print(f'{tba[vs_hand][res_key]["value"]} {res_key}s being placed')
+ if tba[vs_hand][res_key]['value'] > 9.5:
+ num_added = add_full_result(vs_hand, tba[vs_hand][res_key], is_good, 6)
+
+ elif tba[vs_hand][res_key]['value'] > 7.5:
+ num_added = add_full_result(vs_hand, tba[vs_hand][res_key], is_good, 5)
+
+ elif tba[vs_hand][res_key]['value'] > 5.5:
+ num_added = add_full_result(vs_hand, tba[vs_hand][res_key], is_good, 4)
+
+ else:
+ num_added = add_full_result(
+ vs_hand,
+ tba[vs_hand][res_key],
+ is_good,
+ int(tba[vs_hand][res_key]['value'])
+ )
+
+ if num_added:
+ tba[vs_hand][res_key]['value'] = mround(tba[vs_hand][res_key]['value'] - num_added)
+ tba[vs_hand][res_key]['actual'] = mround(tba[vs_hand][res_key]['actual'] + num_added)
+ return
+
+ elif retries == 0:
+ if testing: print(f'retry # {retries} for {res_key} for {player.name} {vs_hand}')
+ return
+
+ else:
+ if tba[vs_hand][rollover_key]['value'] >= 1:
+ t_value = 1
+ else:
+ t_value = .05
+ if testing: print(f'Transferring {t_value} {res_key} to {rollover_key}')
+ tba[vs_hand][rollover_key]['value'] = mround(tba[vs_hand][rollover_key]['value'] + t_value)
+ tba[vs_hand][res_key]['value'] = mround(tba[vs_hand][res_key]['value'] - t_value)
+ return
+
+ # Else start dicing up the chances
+ else:
+ # if retries == 0 and total_chances > 3:
+ # chance_remainder = mround(
+ # math.ceil(total_chances / 2) - (total_chances - math.floor(total_chances))
+ # )
+ # else:
+ # chance_remainder = mround(total_chances - math.floor(total_chances))
+
+ chance_remainder = mround(total_chances - math.floor(total_chances))
+ if testing: print(f'chance_remainder: {chance_remainder}')
+
+ # if mround(chance_remainder) != 0 and mround(chance_remainder) > .5:
+ # TO ROLL BACK, UNDO ABOVE COMMEND AND TAB ALL BELOW CODE IN ONCE
+ top_chances = None
+ bottom_key = None
+ bottom_result = None
+
+ """
+ If this result cannot take any splits (but has extra results pass the remainder to the rollover and
+ come back to assign_chances with a whole number
+ """
+ if len(remainder_keys) == 0:
+ tba[vs_hand][res_key]['value'] = mround(math.floor(tba[vs_hand][res_key]['value']))
+ tba[vs_hand][rollover_key]['value'] = mround(
+ tba[vs_hand][rollover_key]['value'] + chance_remainder
+ )
+ return
+
+ for rem_key in remainder_keys:
+ if mround(tba[vs_hand][rem_key]['value']) >= mround(1 - chance_remainder):
+ bottom_key = rem_key
+ bottom_result = tba[vs_hand][rem_key]
+ break
+
+ if not bottom_key:
+ if tba[vs_hand][rollover_key]['value'] > 1:
+ t_value = 1
+ else:
+ t_value = .05
+ if testing: print(f'Transferring {t_value} {res_key} to {rollover_key}')
+
+ tba[vs_hand][res_key]['value'] = mround(tba[vs_hand][res_key]['value'] - t_value)
+ tba[vs_hand][rollover_key]['value'] = mround(
+ tba[vs_hand][rollover_key]['value'] + t_value
+ )
+ return
+ # raise ValueError(
+ # f'Could not find a second result for a {res_key} split for {player.name} {vHand}')
+
+ bottom_chances = None
+ if tba[vs_hand][res_key]['value'] > 4:
+ top_chances = mround(3 + chance_remainder)
+ if testing: print(f'checking top_chances: {top_chances}')
+ bottom_chances = add_split_result(
+ vs_hand, tba[vs_hand][res_key], bottom_result, top_chances, is_good
+ )
+
+ elif tba[vs_hand][res_key]['value'] > 3:
+ top_chances = mround(2 + chance_remainder)
+ if testing: print(f'checking top_chances: {top_chances}')
+ bottom_chances = add_split_result(
+ vs_hand, tba[vs_hand][res_key], bottom_result, top_chances, is_good
+ )
+
+ elif tba[vs_hand][res_key]['value'] > 2:
+ top_chances = mround(1 + chance_remainder)
+ if testing: print(f'checking top_chances: {top_chances}')
+ bottom_chances = add_split_result(
+ vs_hand, tba[vs_hand][res_key], bottom_result, top_chances, is_good
+ )
+
+ if not bottom_chances:
+ top_chances = mround(chance_remainder)
+ if testing: print(f'checking top_chances: {top_chances}')
+ bottom_chances = add_split_result(
+ vs_hand, tba[vs_hand][res_key], bottom_result, top_chances, is_good
+ )
+
+ if not bottom_chances and tba[vs_hand][res_key]['value'] > 3:
+ top_chances = mround(.5 + chance_remainder)
+ if testing: print(f'checking top_chances: {top_chances}')
+ bottom_chances = add_split_result(
+ vs_hand, tba[vs_hand][res_key], bottom_result, top_chances, is_good
+ )
+
+ if not bottom_chances and tba[vs_hand][res_key]['value'] > 3:
+ top_chances = mround(.7 + chance_remainder)
+ if testing: print(f'checking top_chances: {top_chances}')
+ bottom_chances = add_split_result(
+ vs_hand, tba[vs_hand][res_key], bottom_result, top_chances, is_good
+ )
+
+ if not bottom_chances and chance_remainder > 0.15:
+ top_chances = mround(chance_remainder - 0.15)
+ if testing: print(f'checking top_chances: {top_chances}')
+ bottom_chances = add_split_result(
+ vs_hand, tba[vs_hand][res_key], bottom_result, top_chances, is_good
+ )
+
+ if not bottom_chances and chance_remainder > 0.05:
+ top_chances = mround(chance_remainder - 0.05)
+ if testing: print(f'checking top_chances: {top_chances}')
+ bottom_chances = add_split_result(
+ vs_hand, tba[vs_hand][res_key], bottom_result, top_chances, is_good
+ )
+
+ if testing: print(f'{res_key} chances: {mround(top_chances)} / split with {bottom_result}')
+
+ if bottom_chances:
+ tba[vs_hand][res_key]['value'] = mround(tba[vs_hand][res_key]['value'] - top_chances)
+ tba[vs_hand][res_key]['actual'] = mround(tba[vs_hand][res_key]['actual'] + top_chances)
+ tba[vs_hand][bottom_key]['value'] = mround(
+ tba[vs_hand][bottom_key]['value'] - bottom_chances)
+ tba[vs_hand][bottom_key]['actual'] = mround(
+ tba[vs_hand][bottom_key]['actual'] + bottom_chances
+ )
+ if testing: print(
+ f'placed {top_chances} {res_key}s and {bottom_chances} {bottom_result["string"]}s for '
+ f'{player.name} {vs_hand}\n\n')
+ return
+
+ elif retries == 0:
+ retries += 1
+ if testing: print(f'retry # {retries} for {res_key} for {player.name} {vs_hand}')
+ return
+
+ else:
+ if tba[vs_hand][rollover_key]['value'] > 1:
+ t_value = 1
+ else:
+ t_value = .05
+ if testing: print(f'Transferring {t_value} {res_key} to {rollover_key}')
+ tba[vs_hand][res_key]['value'] = mround(tba[vs_hand][res_key]['value'] - t_value)
+ tba[vs_hand][rollover_key]['value'] = mround(
+ tba[vs_hand][rollover_key]['value'] + t_value
+ )
+ return
+
+ def gap_filler(vs_hand, res_key: str):
+ for col in ['1', '2', '3']:
+ for b_row in ['2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12']:
+ # print(f'checking {col}-{b_row} {vs_hand} for a None: {results[vs_hand][col][b_row]["result"]}')
+ if not results[vs_hand][col][b_row]['result']:
+ chances = chances_from_row(b_row)
+ tba[vs_hand][res_key]['actual'] = mround(
+ tba[vs_hand][res_key]['actual'] + chances
+ )
+ results[vs_hand][col][b_row] = result_data(tba[vs_hand][res_key], b_row)
+
+ # Build vl results then vR
+ for vHand in ['vL', 'vR']:
+ # Refactored bp-hr
+ retries = False
+ while tba[vHand]['bp-hr']['value'] > 0:
+ assign_chances(
+ res_key='bp-hr',
+ vs_hand=vHand,
+ remainder_keys=[],
+ allow_retry=retries,
+ rollover_key='do-pull',
+ is_good=True
+ )
+ retries = False
+
+ # Refactored fo-a
+ retries = False
+ while tba[vHand]['fo-a']['value'] > 0:
+ assign_chances(
+ res_key='fo-a',
+ vs_hand=vHand,
+ remainder_keys=[],
+ allow_retry=retries,
+ rollover_key=f'{"fo-lf-b" if bat_hand == "R" else "fo-rf-b"}',
+ is_good=False
+ )
+ retries = False
+
+ # Refactored si-cf
+ retries = False
+ while tba[vHand]['si-cf']['value'] > 0:
+ assign_chances(
+ res_key='si-cf',
+ vs_hand=vHand,
+ remainder_keys=[],
+ allow_retry=retries,
+ rollover_key=f'si*',
+ is_good=True
+ )
+ retries = False
+
+ # Refactored bp-si
+ retries = True
+ while tba[vHand]['bp-si']['value'] > 0:
+ assign_chances(
+ res_key='bp-si',
+ vs_hand=vHand,
+ remainder_keys=[],
+ allow_retry=retries,
+ rollover_key=f'si*',
+ is_good=False
+ )
+ retries = False
+
+ # Refactored hbp
+ retries = False
+ while tba[vHand]['hbp']['value'] > 0:
+ assign_chances(
+ res_key='hbp',
+ vs_hand=vHand,
+ remainder_keys=[],
+ allow_retry=retries,
+ rollover_key=f'bb',
+ is_good=True
+ )
+ retries = False
+
+ # Refactored hr
+ retries = True
+ while tba[vHand]['hr']['value'] > 0:
+ assign_chances(
+ res_key='hr',
+ vs_hand=vHand,
+ remainder_keys=['tr', 'do-pull', f'fo-{get_of(bat_hand, vHand)}-b',
+ f'fo-{get_of(bat_hand, vHand, pull_side=False)}-b'],
+ allow_retry=retries,
+ rollover_key=f'do-pull',
+ is_good=True
+ )
+ retries = False
+
+ # Refactored tr
+ retries = False
+ while tba[vHand]['tr']['value'] > 0:
+ assign_chances(
+ res_key='tr',
+ vs_hand=vHand,
+ remainder_keys=['do-pull', 'si**', f'fo-{get_of(bat_hand, vHand)}-b',
+ f'fo-{get_of(bat_hand, vHand, pull_side=False)}-b'],
+ allow_retry=retries,
+ rollover_key=f'do-pull',
+ is_good=True
+ )
+ retries = False
+
+ # Refactored do***
+ retries = True
+ while tba[vHand]['do***']['value'] > 0:
+ assign_chances(
+ res_key='do***',
+ vs_hand=vHand,
+ remainder_keys=['si**', f'fo-{get_of(bat_hand, vHand, pull_side=False)}-b',
+ f'fo-{get_of(bat_hand, vHand)}-b', 'lo', 'gb-c'],
+ allow_retry=retries,
+ rollover_key=f'do-pull',
+ is_good=True
+ )
+ retries = False
+
+ # Refactored do**
+ retries = True
+ while tba[vHand]['do**']['value'] > 0:
+ assign_chances(
+ res_key='do**',
+ vs_hand=vHand,
+ remainder_keys=['si**', f'fo-{get_of(bat_hand, vHand, pull_side=False)}-b',
+ f'fo-{get_of(bat_hand, vHand)}-b', 'lo', 'gb-c'],
+ allow_retry=retries,
+ rollover_key=f'do-pull',
+ is_good=True
+ )
+ retries = False
+
+ # Refactored do**
+ retries = True
+ while tba[vHand]['do-pull']['value'] > 0:
+ assign_chances(
+ res_key='do-pull',
+ vs_hand=vHand,
+ remainder_keys=[f'fo-{get_of(bat_hand, vHand)}-b', 'lo', 'gb-c'],
+ allow_retry=retries,
+ rollover_key=f'si**',
+ is_good=True
+ )
+ retries = False
+
+ # Refactored si**
+ retries = True
+ while tba[vHand]['si**']['value'] > 0:
+ assign_chances(
+ res_key='si**',
+ vs_hand=vHand,
+ remainder_keys=['lo', 'gb-a', 'gb-b', 'gb-c', 'po'],
+ allow_retry=retries,
+ rollover_key=f'si*',
+ is_good=True
+ )
+ retries = False
+
+ # Refactored si*
+ retries = True
+ while tba[vHand]['si*']['value'] > 0:
+ assign_chances(
+ res_key='si*',
+ vs_hand=vHand,
+ remainder_keys=['gb-c', 'gb-b', 'gb-a', 'lo', 'po'],
+ allow_retry=retries,
+ rollover_key=f'gb-c',
+ is_good=False
+ )
+ retries = False
+
+ # Refactored bb
+ retries = False
+ while tba[vHand]['bb']['value'] > 0:
+ assign_chances(
+ res_key='bb',
+ vs_hand=vHand,
+ remainder_keys=['so'],
+ allow_retry=retries,
+ rollover_key=f'gb-c',
+ is_good=True
+ )
+ retries = False
+
+ # Refactored so
+ retries = False
+ while tba[vHand]['so']['value'] > 0:
+ assign_chances(
+ res_key='so',
+ vs_hand=vHand,
+ remainder_keys=[],
+ allow_retry=retries,
+ rollover_key='po',
+ is_good=False
+ )
+ retries = False
+
+ # TODO: Add support for the lomax
+
+ # Refactored lo
+ # retries = False
+ # assign_chances(
+ # res_key='lo',
+ # vHand=vHand,
+ # remainder_keys=['gb-a'],
+ # allow_retry=retries,
+ # rollover_key=f'po',
+ # is_good=False
+ # )
+
+ while tba[vHand]['lo']['value'] > 0:
+ assign_chances(
+ res_key='lo',
+ vs_hand=vHand,
+ remainder_keys=[],
+ allow_retry=retries,
+ rollover_key=f'po',
+ is_good=False
+ )
+ retries = False
+
+ # Refactored po
+ retries = False
+ while tba[vHand]['po']['value'] > 0:
+ assign_chances(
+ res_key='po',
+ vs_hand=vHand,
+ remainder_keys=[],
+ allow_retry=retries,
+ rollover_key=f'so',
+ is_good=False
+ )
+ retries = False
+
+ # Refactored fo-lf-b
+ retries = False
+ while tba[vHand]['fo-lf-b']['value'] > 0:
+ assign_chances(
+ res_key='fo-lf-b',
+ vs_hand=vHand,
+ remainder_keys=[],
+ allow_retry=retries,
+ rollover_key=f'fo-rf-b',
+ is_good=False
+ )
+ retries = False
+
+ # Refactored fo-rf-b
+ retries = False
+ while tba[vHand]['fo-rf-b']['value'] > 0:
+ assign_chances(
+ res_key='fo-rf-b',
+ vs_hand=vHand,
+ remainder_keys=[],
+ allow_retry=retries,
+ rollover_key=f'fo-bq',
+ is_good=False
+ )
+ retries = False
+
+ # Refactored fo-bq
+ retries = False
+ while tba[vHand]['fo-bq']['value'] > 0:
+ assign_chances(
+ res_key='fo-bq',
+ vs_hand=vHand,
+ remainder_keys=[],
+ allow_retry=retries,
+ rollover_key=f'gb-c',
+ is_good=False
+ )
+ retries = False
+
+ # Refactored gb-c
+ retries = False
+ while tba[vHand]['gb-c']['value'] > 0:
+ assign_chances(
+ res_key='gb-c',
+ vs_hand=vHand,
+ remainder_keys=[],
+ allow_retry=retries,
+ rollover_key=f'gb-b',
+ is_good=False
+ )
+ retries = False
+
+ # Refactored gb-b
+ retries = False
+ while tba[vHand]['gb-b']['value'] > 0:
+ assign_chances(
+ res_key='gb-b',
+ vs_hand=vHand,
+ remainder_keys=['gb-a'],
+ allow_retry=retries,
+ rollover_key=f'gb-a',
+ is_good=False
+ )
+ retries = False
+
+ # # Refactored gb-a
+ # retries = False
+ # while tba[vHand]['gb-a']['value'] > 0:
+ # assign_chances(
+ # res_key='gb-a',
+ # vs_hand=vHand,
+ # remainder_keys=[],
+ # allow_retry=retries,
+ # rollover_key=f'so',
+ # is_good=False
+ # )
+ # retries = False
+
+ """
+ Whatever result is last should be run through the gap_filler()
+ """
+
+ if testing: print(f'filling in gaps with gb-a')
+ gap_filler(vHand, 'gb-a')
+
+ if testing:
+ print(f'\n\n******\n\n{player.name} Results:\n{results}\n{tba}')
+ # else:
+ # print(f'Completed {player.name}')
+ col_output = column_output()
+ if testing: print(f'\n\ncol_output:\n{col_output}\n\n')
+
+ # # Prep csv batter lines
+ # all_results.append(
+ # [player.name, player.sba_id, bat_hand,
+ # col_output['vl_one_2d6'], col_output['vl_one_results'], col_output['vl_one_splits'],
+ # col_output['vl_two_2d6'], col_output['vl_two_results'], col_output['vl_two_splits'],
+ # col_output['vl_three_2d6'], col_output['vl_three_results'], col_output['vl_three_splits'],
+ # col_output['vr_one_2d6'], col_output['vr_one_results'], col_output['vr_one_splits'],
+ # col_output['vr_two_2d6'], col_output['vr_two_results'], col_output['vr_two_splits'],
+ # col_output['vr_three_2d6'], col_output['vr_three_results'], col_output['vr_three_splits']]
+ # )
+
+ for hand in ['vL', 'vR']:
+ b_ratings = {
+ 'id': f'{player.sba_id}-{hand}-{cardset.id}',
+ 'player': player,
+ 'cardset': cardset,
+ 'vs_hand': hand,
+ 'is_prep': False,
+ 'homerun': mround(tba[hand]['hr']['actual']),
+ 'bp_homerun': mround(tba[hand]['bp-hr']['actual']),
+ 'triple': mround(tba[hand]['tr']['actual']),
+ 'double_three': mround(tba[hand]['do***']['actual']),
+ 'double_two': mround(tba[hand]['do**']['actual']),
+ 'double_pull': mround(tba[hand]['do-pull']['actual']),
+ 'single_two': mround(tba[hand]['si**']['actual']),
+ 'single_one': mround(tba[hand]['si*']['actual']),
+ 'single_center': mround(tba[hand]['si-cf']['actual']),
+ 'bp_single': mround(tba[hand]['bp-si']['actual']),
+ 'hbp': mround(tba[hand]['hbp']['actual']),
+ 'walk': mround(tba[hand]['bb']['actual']),
+ 'strikeout': mround(tba[hand]['so']['actual']),
+ 'lineout': mround(tba[hand]['lo']['actual']),
+ 'popout': mround(tba[hand]['po']['actual']),
+ 'flyout_a': mround(tba[hand]['fo-a']['actual']),
+ 'flyout_bq': mround(tba[hand]['fo-bq']['actual']),
+ 'flyout_lf_b': mround(tba[hand]['fo-lf-b']['actual']),
+ 'flyout_rf_b': mround(tba[hand]['fo-rf-b']['actual']),
+ 'groundout_a': mround(tba[hand]['gb-a']['actual']),
+ 'groundout_b': mround(tba[hand]['gb-b']['actual']),
+ 'groundout_c': mround(tba[hand]['gb-c']['actual'])
+ }
+
+ count_hits = (
+ b_ratings['homerun'] + b_ratings['bp_homerun'] / 2 + b_ratings['triple'] +
+ b_ratings['double_three'] + b_ratings['double_two'] +
+ b_ratings['double_pull'] + b_ratings['single_two'] + b_ratings['single_one'] +
+ b_ratings['single_center'] + b_ratings['bp_single'] / 2
+ )
+
+ b_ratings['avg'] = count_hits / 108
+ b_ratings['obp'] = (
+ count_hits + b_ratings['hbp'] + b_ratings['walk']
+ ) / 108
+ b_ratings['slg'] = (
+ (b_ratings['homerun'] * 4) + (b_ratings['triple'] * 3) +
+ ((b_ratings['bp_homerun'] + b_ratings['double_three'] + b_ratings['double_two'] +
+ b_ratings['double_pull']) * 2) +
+ b_ratings['single_two'] + b_ratings['single_one'] + b_ratings['single_center'] +
+ b_ratings['bp_single'] / 2
+ ) / 108
+
+ BatterRatings.insert(b_ratings).on_conflict_replace().execute()
+
+ this_columns = {
+ 'id': f'{player.sba_id}-{hand}-{cardset.id}',
+ 'player': player,
+ 'hand': player.hand,
+ 'b_ratings_id': f'{player.sba_id}-{hand}-{cardset.id}',
+ 'one_dice': col_output[f'{hand.lower()}_one_2d6'],
+ 'one_results': col_output[f'{hand.lower()}_one_results'],
+ 'one_splits': col_output[f'{hand.lower()}_one_splits'],
+ 'two_dice': col_output[f'{hand.lower()}_two_2d6'],
+ 'two_results': col_output[f'{hand.lower()}_two_results'],
+ 'two_splits': col_output[f'{hand.lower()}_two_splits'],
+ 'three_dice': col_output[f'{hand.lower()}_three_2d6'],
+ 'three_results': col_output[f'{hand.lower()}_three_results'],
+ 'three_splits': col_output[f'{hand.lower()}_three_splits']
+ }
+ CardColumns.insert(this_columns).on_conflict_replace().execute()
+
+ # # Prep csv ratings guide
+ # rg_line = [player.name, bat_hand]
+ # for hand in ['vL', 'vR']:
+ # for x in rg_headers:
+ # if x not in ['name', 'hand']:
+ # rg_line.append(mround(tba[hand][x]['actual']))
+ # ratings_guide.append(rg_line)
+
+ # No player match
+ else:
+ logging.error(f'Could not match player id {row[0]}')
+ print(f'Could not match player id {row[0]}')
+
+ # # https://www.baseball-reference.com/leagues/majors/2021-standard-batting.shtml
+ # with open('baserunning-data.csv', 'r') as file:
+ # reader = csv.reader(file)
+ #
+ # for row in reader:
+ # player = Player.get_or_none(Player.br_id == row[36])
+ # if player:
+
+ """
+ Export card output to csv for Component Studio
+ """
+ # # Removed since output has own script now
+ # write_to_csv(output_path, f'batter-ratings-guide-{now.strftime("%Y-%m-%d-%f")}', ratings_guide)
+ # write_to_csv(output_path, f'batter-card-columns-{now.strftime("%Y-%m-%d-%f")}', all_results)
+
+ lets_go = input(f'Should I run fielders (y/n)? ')
+ if lets_go in YES:
+ # https://www.baseball-reference.com/leagues/majors/2022-specialpos_p-fielding.shtml
+ with open(f'{input_path}defense-p.csv', 'r') as file:
+ reader = csv.reader(file)
+
+ for row in reader:
+ player = Player.get_or_none(Player.br_id == row[29])
+ if player and row[15] != '' and row[12] != '':
+ # Build Position object and save
+ this_pos = Position(
+ player=player,
+ cardset=cardset,
+ position='P',
+ innings=int(float(row[8])),
+ range=d.range_pitcher(int(row[15]), season_pct),
+ error=d.error_pitcher(int(row[12]), int(row[9]), season_pct=season_pct),
+ )
+ dupe = Position.delete().where(
+ (Position.player == player) & (Position.cardset == cardset)
+ ).execute()
+ this_pos.save()
+
+ spow, rpow = d.pow_ratings(d.innings_float(row[8]), int(row[6]), int(row[5]))
+ this_pit = PitcherData(
+ player=player,
+ cardset=cardset,
+ hold=d.hold_pitcher(row[27], int(row[28]), season_pct),
+ starter_rating=spow,
+ relief_rating=rpow
+ )
+ dupe = PitcherData.delete().where(
+ (PitcherData.player == player) & (PitcherData.cardset == cardset)
+ ).execute()
+ this_pit.save()
+
+ if int(row[6]) >= int(row[5]) * .1:
+ sp_pos = Position(
+ player=player,
+ cardset=cardset,
+ position='SP',
+ innings=int(float(row[8])) * (int(row[6]) / int(row[5])),
+ range=69,
+ error=420
+ )
+ sp_pos.save()
+ if int(row[6]) <= int(row[5]) * .8:
+ rp_pos = Position(
+ player=player,
+ cardset=cardset,
+ position='RP',
+ innings=int(float(row[8])) * (1 - (int(row[6]) / int(row[5]))),
+ range=69,
+ error=420
+ )
+ rp_pos.save()
+
+ # No player match
+ else:
+ logging.error(f'Could not match bbref id {row[29]}')
+ print(f'Could not match bbref id {row[29]}')
+
+ # https://www.baseball-reference.com/leagues/majors/2022-standard-pitching.shtml
+ with open(f'{input_path}pitcher-data.csv', 'r') as file:
+ reader = csv.reader(file)
+
+ for row in reader:
+ player = Player.get_or_none(Player.br_id == row[35])
+ if player:
+ all_data = PitcherData.select().where(
+ (PitcherData.player == player) & (PitcherData.cardset == cardset)
+ ).limit(1)
+ try:
+ this_data = all_data[0]
+ except Exception as e:
+ logging.error(f'Could not find existing PitcherData for {player.name}')
+
+ if this_data:
+ closer_rating = p.closer_rating(int(row[11]), int(row[14]), int(row[9]))
+ this_data.balk = p.balks(int(row[24]), int(float(row[15])), season_pct)
+ this_data.wild_pitch = p.wild_pitches(int(row[25]), int(float(row[15])), season_pct)
+ this_data.closer_rating = closer_rating
+ this_data.batting = f'1W{player.hand}-C'
+ this_data.save()
+
+ if closer_rating != 'N':
+ cp_pos = Position(
+ player=player,
+ cardset=cardset,
+ position='CP',
+ innings=1,
+ range=69,
+ error=420
+ )
+ cp_pos.save()
+
+ else:
+ logging.error(f'Could not match bbref id {row[35]}')
+ print(f'Could not match bbref id {row[35]}')
+
+ with open(f'{input_path}defense-c.csv', 'r') as file:
+ reader = csv.reader(file)
+ curr_pos = 'C'
+
+ for row in reader:
+ player = Player.get_or_none(Player.br_id == row[34])
+ if player:
+ # Build Position object and save
+ this_pos = Position(
+ player=player,
+ cardset=cardset,
+ position=curr_pos,
+ innings=int(float(row[8])),
+ range=d.range_catcher(int(row[17]), season_pct),
+ error=d.error_catcher(int(row[12]), int(row[9]), season_pct),
+ arm=d.arm_catcher(row[33], int(row[25]), season_pct),
+ pb=d.pb_catcher(int(row[29]), int(float(row[8])), season_pct),
+ overthrow=d.ot_catcher(int(row[12]), int(row[9]), season_pct)
+ )
+ dupe = Position.delete().where(
+ (Position.player == player) & (Position.cardset == cardset) & (Position.position == curr_pos)
+ ).execute()
+ this_pos.save()
+
+ # No player match
+ else:
+ logging.error(f'Could not match bbref id {row[34]}')
+ print(f'Could not match bbref id {row[34]}')
+
+ with open(f'{input_path}defense-1b.csv', 'r') as file:
+ reader = csv.reader(file)
+ curr_pos = '1B'
+
+ for row in reader:
+ player = Player.get_or_none(Player.br_id == row[29])
+ if player and row[24] != '' and row[18] != '':
+ # Build Position object and save
+ this_pos = Position(
+ player=player,
+ cardset=cardset,
+ position=curr_pos,
+ innings=int(float(row[8])),
+ range=d.range_first_base(int(row[24]), int(row[18]), season_pct),
+ error=d.error_first_base(int(row[12]), int(row[9]), season_pct),
+ )
+ dupe = Position.delete().where(
+ (Position.player == player) & (Position.cardset == cardset) & (Position.position == curr_pos)
+ ).execute()
+ this_pos.save()
+
+ # No player match
+ else:
+ logging.error(f'Could not match bbref id {row[29]}')
+ print(f'Could not match bbref id {row[29]}')
+
+ with open(f'{input_path}defense-2b.csv', 'r') as file:
+ reader = csv.reader(file)
+ curr_pos = '2B'
+
+ for row in reader:
+ player = Player.get_or_none(Player.br_id == row[29])
+ if player and row[25] != '' and row[18] != '':
+ # Build Position object and save
+ this_pos = Position(
+ player=player,
+ cardset=cardset,
+ position=curr_pos,
+ innings=int(float(row[8])),
+ range=d.range_second_base(int(row[25]), int(row[18]), season_pct),
+ error=d.error_second_base(int(row[12]), int(row[9]), season_pct),
+ )
+ dupe = Position.delete().where(
+ (Position.player == player) & (Position.cardset == cardset) & (Position.position == curr_pos)
+ ).execute()
+ this_pos.save()
+
+ # No player match
+ else:
+ p_err = f'{player.name if player else "player not found"}'
+ logging.error(f'Could not match bbref id {row[29]}')
+ print(f'Could not match bbref id {row[29]} / player: {p_err} / row[27]: {row[25]} / '
+ f'row[20]: {row[18]}')
+
+ with open(f'{input_path}defense-3b.csv', 'r') as file:
+ reader = csv.reader(file)
+ curr_pos = '3B'
+
+ for row in reader:
+ player = Player.get_or_none(Player.br_id == row[29])
+ if player and row[24] != '' and row[18] != '':
+ # Build Position object and save
+ this_pos = Position(
+ player=player,
+ cardset=cardset,
+ position=curr_pos,
+ innings=int(float(row[8])),
+ range=d.range_third_base(int(row[24]), int(row[18]), season_pct),
+ error=d.error_third_base(int(row[12]), int(row[9]), season_pct),
+ )
+ dupe = Position.delete().where(
+ (Position.player == player) & (Position.cardset == cardset) & (Position.position == curr_pos)
+ ).execute()
+ this_pos.save()
+
+ # No player match
+ else:
+ logging.error(f'Could not match bbref id {row[29]}')
+ print(f'Could not match bbref id {row[29]}')
+
+ with open(f'{input_path}defense-ss.csv', 'r') as file:
+ reader = csv.reader(file)
+ curr_pos = 'SS'
+
+ for row in reader:
+ player = Player.get_or_none(Player.br_id == row[29])
+ if player and row[25] != '' and row[18] != '':
+ # Build Position object and save
+ this_pos = Position(
+ player=player,
+ cardset=cardset,
+ position=curr_pos,
+ innings=int(float(row[8])),
+ range=d.range_shortstop(int(row[25]), int(row[18]), season_pct),
+ error=d.error_shortstop(int(row[12]), int(row[9]), season_pct),
+ )
+ dupe = Position.delete().where(
+ (Position.player == player) & (Position.cardset == cardset) & (Position.position == curr_pos)
+ ).execute()
+ this_pos.save()
+
+ # No player match
+ else:
+ logging.error(f'Could not match bbref id {row[29]}')
+ print(f'Could not match bbref id {row[29]}')
+
+ with open(f'{input_path}defense-lf.csv', 'r') as file:
+ reader = csv.reader(file)
+ curr_pos = 'LF'
+
+ for row in reader:
+ player = Player.get_or_none(Player.br_id == row[26])
+ if player and row[22] != '':
+ # Build Position object and save
+ this_pos = Position(
+ player=player,
+ cardset=cardset,
+ position=curr_pos,
+ innings=int(float(row[8])),
+ range=d.range_left_field(int(row[19]), season_pct),
+ error='69',
+ arm=row[22]
+ )
+ dupe = Position.delete().where(
+ (Position.player == player) & (Position.cardset == cardset) & (Position.position == curr_pos)
+ ).execute()
+ this_pos.save()
+
+ # No player match
+ else:
+ logging.error(f'Could not match bbref id {row[26]}')
+ print(f'Could not match bbref id {row[26]}')
+
+ with open(f'{input_path}defense-cf.csv', 'r') as file:
+ reader = csv.reader(file)
+ curr_pos = 'CF'
+
+ for row in reader:
+ player = Player.get_or_none(Player.br_id == row[26])
+ if player and row[22] != '':
+ # Build Position object and save
+ this_pos = Position(
+ player=player,
+ cardset=cardset,
+ position=curr_pos,
+ innings=int(float(row[8])),
+ range=d.range_center_field(int(row[19]), season_pct),
+ error='69',
+ arm=row[22]
+ )
+ dupe = Position.delete().where(
+ (Position.player == player) & (Position.cardset == cardset) & (Position.position == curr_pos)
+ ).execute()
+ this_pos.save()
+
+ # No player match
+ else:
+ logging.error(f'Could not match bbref id {row[26]}')
+ print(f'Could not match bbref id {row[26]}')
+
+ with open(f'{input_path}defense-rf.csv', 'r') as file:
+ reader = csv.reader(file)
+ curr_pos = 'RF'
+
+ for row in reader:
+ player = Player.get_or_none(Player.br_id == row[26])
+ if player and row[22] != '':
+ # Build Position object and save
+ this_pos = Position(
+ player=player,
+ cardset=cardset,
+ position=curr_pos,
+ innings=int(float(row[8])),
+ range=d.range_right_field(int(row[19]), season_pct),
+ error='69',
+ arm=row[22]
+ )
+ dupe = Position.delete().where(
+ (Position.player == player) & (Position.cardset == cardset) & (Position.position == curr_pos)
+ ).execute()
+ this_pos.save()
+
+ # No player match
+ else:
+ logging.error(f'Could not match bbref id {row[26]}')
+ print(f'Could not match bbref id {row[26]}')
+
+ with open(f'{input_path}defense-of.csv', 'r') as file:
+ reader = csv.reader(file)
+
+ for row in reader:
+ player = Player.get_or_none(Player.br_id == row[26])
+ all_of = Position.select().where(
+ (Position.player == player) & (Position.cardset == cardset) & (Position.position.contains("F"))
+ )
+ all_arms = [int(x.arm) for x in all_of]
+ if player and row[25] != '' and row[18] != '':
+ # Build Position object and save
+ this_pos = Position(
+ player=player,
+ cardset=cardset,
+ position='OF',
+ innings=int(float(row[8])),
+ range=69,
+ error=d.error_outfield(int(row[12]), int(row[9]), season_pct),
+ arm=d.arm_outfield(all_arms)
+ )
+ dupe = Position.delete().where(
+ (Position.player == player) & (Position.cardset == cardset) & (Position.position == 'OF')
+ ).execute()
+ this_pos.save()
+
+ # No player match
+ else:
+ logging.error(f'Could not match bbref id {row[26]}')
+ print(f'Could not match bbref id {row[26]}')
+
+if __name__ == '__main__':
+ asyncio.run(main(sys.argv[1:]))
diff --git a/card_output.py b/card_output.py
new file mode 100644
index 0000000..99bf6e7
--- /dev/null
+++ b/card_output.py
@@ -0,0 +1,314 @@
+import asyncio
+import datetime
+import logging
+import pathlib
+import sys
+
+from db_calls_card_creation import *
+from creation_helpers import get_position_string, write_to_csv, ordered_positions, defense_rg, ordered_pitching_positions
+
+date = f'{datetime.datetime.now().year}-{datetime.datetime.now().month}-{datetime.datetime.now().day}'
+log_level = logging.INFO
+logging.basicConfig(
+ filename=f'logs/{date}.log',
+ format='%(asctime)s - card-creation - %(levelname)s - %(message)s',
+ level=log_level
+)
+
+
+def get_batter_rarity(total_ops):
+ if total_ops < .7:
+ return 'Replacement'
+ elif total_ops < .8:
+ return 'Reserve'
+ elif total_ops < .9:
+ return 'Starter'
+ elif total_ops < 1:
+ return 'All-Star'
+ elif total_ops < 1.2:
+ return 'MVP'
+ else:
+ return 'HoF'
+
+
+def get_pitcher_rarity(total_ops, s_rat):
+ if s_rat > 3:
+ if total_ops <= .4:
+ return 'HoF'
+ elif total_ops <= .475:
+ return 'MVP'
+ elif total_ops <= .53:
+ return 'All-Star'
+ elif total_ops <= .6:
+ return 'Starter'
+ elif total_ops <= .675:
+ return 'Reserve'
+ else:
+ return 'Replacement'
+ else:
+ if total_ops <= .325:
+ return 'HoF'
+ elif total_ops <= .4:
+ return 'MVP'
+ elif total_ops <= .475:
+ return 'All-Star'
+ elif total_ops <= .55:
+ return 'Starter'
+ elif total_ops <= .625:
+ return 'Reserve'
+ else:
+ return 'Replacement'
+
+
+async def main(argv):
+ cardset_name = input(f'What is the name of this Cardset? ')
+ # cardset_name = '2022 Live'
+ cardset = Cardset.get_or_none(fn.Lower(Cardset.set_title) == cardset_name.lower())
+
+ if not cardset:
+ print(f'There is no cardset named **{cardset_name}**.')
+ return
+ else:
+ print(f'Got it! Starting on the {cardset.set_title} cardset.')
+
+ now = datetime.datetime.now()
+ output_path = pathlib.Path(f'card-output/{cardset.set_title} Cardset/')
+ if not output_path.exists():
+ output_path.mkdir(parents=True, exist_ok=True)
+
+ all_players = Player.select()
+ batter_output = [[
+ 'name', 'hand', 'rarity', 'pos', 'stealing', 'bunt', 'hnr', 'running', 'vl-2d6-1', 'vl-results-1',
+ 'vl-splits-1', 'vl-2d6-2', 'vl-results-2', 'vl-splits-2', 'vl-2d6-3', 'vl-results-3', 'vl-splits-3', 'vr-2d6-1',
+ 'vr-results-1', 'vr-splits-1', 'vr-2d6-2', 'vr-results-2', 'vr-splits-2', 'vr-2d6-3', 'vr-results-3',
+ 'vr-splits-3'
+ ]]
+ batter_rg_output = [[
+ 'sba_id', 'cardset_id', 'player_name', 'hand', 'vl_hr', 'vl_bphr', 'vl_tr', 'vl_do3', 'vl_do2', 'vl_doP',
+ 'vl_si2', 'vl_si1', 'vl_siC', 'vl_bpsi', 'vl_hbp', 'vl_bb', 'vl_k', 'vl_lo', 'vl_po', 'vl_flya', 'vl_flybq',
+ 'vl_flylfb', 'vl_flyrfb', 'vl_gba', 'vl_gbb', 'vl_gbc', 'vr_hr', 'vr_bphr', 'vr_tr', 'vr_do3', 'vr_do2',
+ 'vr_doP', 'vr_si2', 'vr_si1', 'vr_siC', 'vr_bpsi', 'vr_hbp', 'vr_bb', 'vr_k', 'vr_lo', 'vr_po', 'vr_flya',
+ 'vr_flybq', 'vr_flylfb', 'vr_flyrfb', 'vr_gba', 'vr_gbb', 'vr_gbc'
+ ]]
+ baserunning_output = [[
+ 'name', 'running', 'st-high', 'st-low', 'auto-jump', 'jump'
+ ]]
+ pitcher_output = [[
+ 'name', 'hand', 'rarity', 'starter', 'reliever', 'closer', 'hold', 'batting', 'balk', 'wp', 'defense', 'vl-2d6-1',
+ 'vl-results-1', 'vl-splits-1', 'vl-2d6-2', 'vl-results-2', 'vl-splits-2', 'vl-2d6-3', 'vl-results-3',
+ 'vl-splits-3', 'vr-2d6-1', 'vr-results-1', 'vr-splits-1', 'vr-2d6-2', 'vr-results-2', 'vr-splits-2', 'vr-2d6-3',
+ 'vr-results-3', 'vr-splits-3'
+ ]]
+ pitcher_peripherals_output = [[
+ 'name', 'starter', 'reliever', 'closer', 'hold', 'balk', 'wp'
+ ]]
+ pitcher_rg_output = [[
+ 'sba-id', 'cardset-id', 'player-name', 'hand', 'hr-vL', 'bp-hr-vL', 'tr-vL', 'do***-vL', 'do**-vL', 'do-cf-vL',
+ 'si**-vL', 'si*-vL', 'si-cf-vL', 'bp-si-vL', 'hbp-vL', 'bb-vL', 'so-vL', 'fo-b-cf-vL', 'fo-b-slap-vL',
+ 'gb-a-vL', 'gb-c-vL', 'gb-x-p-vL', 'gb-x-c-vL', 'gb-x-1b-vL', 'gb-x-2b-vL', 'gb-x-3b-vL', 'gb-x-ss-vL',
+ 'gb-x-lf-vL', 'gb-x-cf-vL', 'gb-x-rf-vL', 'hr-vR', 'bp-hr-vR', 'tr-vR', 'do***-vR', 'do**-vR', 'do-cf-vR',
+ 'si**-vR', 'si*-vR', 'si-cf-vR', 'bp-si-vR', 'hbp-vR', 'bb-vR', 'so-vR', 'fo-b-cf-vR', 'fo-b-slap-vR',
+ 'gb-a-vR', 'gb-c-vR', 'gb-x-p-vR', 'gb-x-c-vR', 'gb-x-1b-vR', 'gb-x-2b-vR', 'gb-x-3b-vR', 'gb-x-ss-vR',
+ 'gb-x-lf-vR', 'gb-x-cf-vR', 'gb-x-rf-vR'
+ ]]
+ player_json_output = [[
+ 'sba-id', 'name', '', 'fg-id', 'bbref-id', '', '', '', 'cardset-id'
+ ]]
+ defense_rg_output = [[
+ 'full name', 'p-rat', 'c-rat', '1b-rat', '2b-rat', '3b-rat', 'ss-rat', 'lf-rat', 'cf-rat', 'rf-rat', 'p-e',
+ 'c-e', '1b-e', '2b-e', '3b-e', 'ss-e', 'lf-e', 'cf-e', 'rf-e', 'of-arm', 'c-arm', 'c-throw', 'c-pb', 'p-wp',
+ 'p-bk'
+ ]]
+
+ print(f'Found {all_players.count()} players in this cardset...')
+ for player in all_players:
+ b_lines = CardColumns.select().where(
+ CardColumns.b_ratings.is_null(False) & (CardColumns.player == player) &
+ CardColumns.b_ratings.endswith(f'{cardset.id}')
+ )
+
+ this_output = [player.name, player.hand]
+ if b_lines.count() == 2:
+ vl_line = None
+ vr_line = None
+ for line in b_lines:
+ this_columns = [
+ line.one_dice, line.one_results, line.one_splits, line.two_dice, line.two_results, line.two_splits,
+ line.three_dice, line.three_results, line.three_splits
+ ]
+ if 'vL' in line.b_ratings.id:
+ vl_line = this_columns
+ else:
+ vr_line = this_columns
+
+ vl_ratings = BatterRatings.get_or_none(
+ BatterRatings.player == player, BatterRatings.cardset == cardset, BatterRatings.vs_hand == 'vL',
+ BatterRatings.is_prep == 0
+ )
+ vr_ratings = BatterRatings.get_or_none(
+ BatterRatings.player == player, BatterRatings.cardset == cardset, BatterRatings.vs_hand == 'vR',
+ BatterRatings.is_prep == 0
+ )
+
+ # Calculate rarity
+ ops_vl = vl_ratings.obp + vl_ratings.slg
+ ops_vr = vr_ratings.obp + vr_ratings.slg
+ total_ops = (ops_vl + ops_vr + min(ops_vl, ops_vr)) / 3
+ rarity = get_batter_rarity(total_ops)
+
+ this_json = [
+ player.sba_id, player.name, None, player.fg_id, player.br_id, None, None, None, cardset.id, rarity, None
+ ]
+ this_output.append(rarity)
+
+ batter_rg_output.append([
+ player.sba_id, cardset.id, player.name, player.hand, vl_ratings.homerun, vl_ratings.bp_homerun,
+ vl_ratings.triple, vl_ratings.double_three, vl_ratings.double_two, vl_ratings.double_pull,
+ vl_ratings.single_two, vl_ratings.single_one, vl_ratings.single_center, vl_ratings.bp_single,
+ vl_ratings.hbp, vl_ratings.walk, vl_ratings.strikeout, vl_ratings.lineout, vl_ratings.popout,
+ vl_ratings.flyout_a, vl_ratings.flyout_bq, vl_ratings.flyout_lf_b, vl_ratings.flyout_rf_b,
+ vl_ratings.groundout_a, vl_ratings.groundout_b, vl_ratings.groundout_c, vr_ratings.homerun, vr_ratings.bp_homerun,
+ vr_ratings.triple, vr_ratings.double_three, vr_ratings.double_two, vr_ratings.double_pull,
+ vr_ratings.single_two, vr_ratings.single_one, vr_ratings.single_center, vr_ratings.bp_single,
+ vr_ratings.hbp, vr_ratings.walk, vr_ratings.strikeout, vr_ratings.lineout, vr_ratings.popout,
+ vr_ratings.flyout_a, vr_ratings.flyout_bq, vr_ratings.flyout_lf_b, vr_ratings.flyout_rf_b,
+ vr_ratings.groundout_a, vr_ratings.groundout_b, vr_ratings.groundout_c, rarity
+ ])
+
+ all_positions = Position.select().where((Position.player == player) & (Position.cardset == cardset))
+ pos_list = [x for x in all_positions]
+ position_string = get_position_string(pos_list, inc_p=False)
+ this_json.extend(ordered_positions(pos_list))
+ player_json_output.append(this_json)
+
+ this_batter_data = BatterData.get_or_none(BatterData.player == player, BatterData.cardset == cardset)
+ if this_batter_data:
+ baserunning_output.append([
+ player.name, this_batter_data.running, this_batter_data.st_high, this_batter_data.st_low,
+ "Y" if this_batter_data.st_auto else "N", this_batter_data.st_jump
+ ])
+
+ this_output.extend([
+ position_string, this_batter_data.stealing, this_batter_data.bunting, this_batter_data.hit_and_run,
+ this_batter_data.running
+ ])
+ this_output.extend(vl_line)
+ this_output.extend(vr_line)
+
+ batter_output.append(this_output)
+
+ p_lines = CardColumns.select().where(
+ CardColumns.p_ratings.is_null(False) & (CardColumns.player == player) &
+ CardColumns.p_ratings.endswith(f'{cardset.id}')
+ )
+ # if p_lines.count() > 0:
+ # print(f'player: {player.name}')
+ # print(f'p_lines ({p_lines.count()}): {p_lines}')
+
+ this_output = [player.name, player.hand]
+ if p_lines.count() == 2:
+ vr_line = None
+ vl_line = None
+
+ for line in p_lines:
+ this_columns = [
+ line.one_dice, line.one_results, line.one_splits, line.two_dice, line.two_results, line.two_splits,
+ line.three_dice, line.three_results, line.three_splits
+ ]
+ if 'vL' in line.p_ratings.id:
+ vl_line = this_columns
+ else:
+ vr_line = this_columns
+
+ if vr_line is not None and vl_line is not None:
+ this_data = PitcherData.get_or_none(PitcherData.player == player, PitcherData.cardset_id == cardset.id)
+ if this_data:
+ pitcher_peripherals_output.append([
+ player.name, this_data.starter_rating, this_data.relief_rating, this_data.closer_rating,
+ this_data.hold, this_data.wild_pitch, this_data.balk
+ ])
+
+ vl_ratings = PitcherRatings.get_or_none(
+ PitcherRatings.player == player, PitcherRatings.cardset == cardset,
+ PitcherRatings.vs_hand == 'vL', PitcherRatings.is_prep == 0
+ )
+ vr_ratings = PitcherRatings.get_or_none(
+ PitcherRatings.player == player, PitcherRatings.cardset == cardset,
+ PitcherRatings.vs_hand == 'vR', PitcherRatings.is_prep == 0
+ )
+
+ # Calculate rarity
+ ops_vl = vl_ratings.obp + vl_ratings.slg
+ ops_vr = vr_ratings.obp + vr_ratings.slg
+ total_ops = (ops_vl + ops_vr + min(ops_vl, ops_vr)) / 3
+ rarity = get_pitcher_rarity(total_ops, this_data.starter_rating)
+
+ this_json = [
+ player.sba_id, player.name, None, player.fg_id, player.br_id, None, None, None, cardset.id,
+ rarity, None
+ ]
+
+ this_output.extend([
+ rarity, this_data.starter_rating, this_data.relief_rating, this_data.closer_rating,
+ this_data.hold, this_data.batting, this_data.balk, this_data.wild_pitch
+ ])
+
+ pitcher_rg_output.append([
+ player.sba_id, cardset.id, player.name, player.hand, vl_ratings.homerun, vl_ratings.bp_homerun,
+ vl_ratings.triple, vl_ratings.double_three, vl_ratings.double_two, vl_ratings.double_cf,
+ vl_ratings.single_two, vl_ratings.single_one, vl_ratings.single_center, vl_ratings.bp_single,
+ vl_ratings.hbp, vl_ratings.walk, vl_ratings.strikeout, vl_ratings.fo_center, vl_ratings.fo_slap,
+ vl_ratings.groundout_a, vl_ratings.groundout_b, vl_ratings.xcheck_p, vl_ratings.xcheck_c,
+ vl_ratings.xcheck_1b, vl_ratings.xcheck_2b, vl_ratings.xcheck_3b, vl_ratings.xcheck_ss,
+ vl_ratings.xcheck_lf, vl_ratings.xcheck_cf, vl_ratings.xcheck_rf,
+ vr_ratings.homerun, vr_ratings.bp_homerun,
+ vr_ratings.triple, vr_ratings.double_three, vr_ratings.double_two, vr_ratings.double_cf,
+ vr_ratings.single_two, vr_ratings.single_one, vr_ratings.single_center, vr_ratings.bp_single,
+ vr_ratings.hbp, vr_ratings.walk, vr_ratings.strikeout, vr_ratings.fo_center, vr_ratings.fo_slap,
+ vr_ratings.groundout_a, vr_ratings.groundout_b, vr_ratings.xcheck_p, vr_ratings.xcheck_c,
+ vr_ratings.xcheck_1b, vr_ratings.xcheck_2b, vr_ratings.xcheck_3b, vr_ratings.xcheck_ss,
+ vr_ratings.xcheck_lf, vr_ratings.xcheck_cf, vr_ratings.xcheck_rf
+ ])
+
+ p_def = Position.get_or_none(
+ (Position.player == player) & (Position.cardset_id == cardset.id) & (Position.position == 'P')
+ )
+ if p_def:
+ this_output.append(f'p-{p_def.range}e{p_def.error}')
+ this_output.extend(vl_line)
+ this_output.extend(vr_line)
+
+ pitcher_output.append(this_output)
+ all_p_def = Position.select().where(
+ ((Position.player == player) & (Position.cardset == cardset)) & (
+ (Position.position == 'SP') | (Position.position == 'RP') |
+ (Position.position == 'CP')
+ )
+ )
+ pos_list = [x for x in all_p_def]
+ ordered_roles = ordered_pitching_positions(pos_list)
+ this_json.extend(ordered_roles)
+ player_json_output.append(this_json)
+
+ all_pos = Position.select().where(
+ (Position.player == player) & (Position.cardset == cardset)
+ )
+ if all_pos.count() > 0:
+ this_data = [player.name]
+ this_data.extend(defense_rg(all_pos))
+ defense_rg_output.append(this_data)
+
+ print(f'Done processing players; outputting to {output_path}')
+ write_to_csv(output_path, f'batter-card-output-{now.strftime("%Y-%m-%d-%f")}', batter_output)
+ write_to_csv(output_path, f'batter-rg-output-{now.strftime("%Y-%m-%d-%f")}', batter_rg_output)
+ write_to_csv(output_path, f'batter-baserunning-{now.strftime("%Y-%m-%d-%f")}', baserunning_output)
+ write_to_csv(output_path, f'pitcher-card-output-{now.strftime("%Y-%m-%d-%f")}', pitcher_output)
+ write_to_csv(output_path, f'pitcher-peripherals-{now.strftime("%Y-%m-%d-%f")}', pitcher_peripherals_output)
+ write_to_csv(output_path, f'pitcher-rg-output-{now.strftime("%Y-%m-%d-%f")}', pitcher_rg_output)
+ write_to_csv(output_path, f'player-json-{now.strftime("%Y-%m-%d-%f")}', player_json_output)
+ write_to_csv(output_path, f'defense-rg-{now.strftime("%Y-%m-%d-%f")}', defense_rg_output)
+ print(f'All done!')
+
+
+if __name__ == '__main__':
+ asyncio.run(main(sys.argv[1:]))
diff --git a/creation_helpers.py b/creation_helpers.py
new file mode 100644
index 0000000..3f5cb4c
--- /dev/null
+++ b/creation_helpers.py
@@ -0,0 +1,687 @@
+import csv
+import random
+import logging
+from db_calls_card_creation import *
+
+D20_CHANCES = {
+ '2': {
+ 'chances': 1,
+ 'inc': .05
+ },
+ '3': {
+ 'chances': 2,
+ 'inc': .1
+ },
+ '4': {
+ 'chances': 3,
+ 'inc': .15
+ },
+ '5': {
+ 'chances': 4,
+ 'inc': .2
+ },
+ '6': {
+ 'chances': 5,
+ 'inc': .25
+ },
+ '7': {
+ 'chances': 6,
+ 'inc': .3
+ },
+ '8': {
+ 'chances': 5,
+ 'inc': .25
+ },
+ '9': {
+ 'chances': 4,
+ 'inc': .2
+ },
+ '10': {
+ 'chances': 3,
+ 'inc': .15
+ },
+ '11': {
+ 'chances': 2,
+ 'inc': .1
+ },
+ '12': {
+ 'chances': 1,
+ 'inc': .05
+ }
+ }
+BLANK_RESULTS = {
+ 'vL': {
+ '1': {
+ '2': {
+ 'result': None,
+ 'splits': None,
+ '2d6': None
+ },
+ '3': {
+ 'result': None,
+ 'splits': None,
+ '2d6': None
+ },
+ '4': {
+ 'result': None,
+ 'splits': None,
+ '2d6': None
+ },
+ '5': {
+ 'result': None,
+ 'splits': None,
+ '2d6': None
+ },
+ '6': {
+ 'result': None,
+ 'splits': None,
+ '2d6': None
+ },
+ '7': {
+ 'result': None,
+ 'splits': None,
+ '2d6': None
+ },
+ '8': {
+ 'result': None,
+ 'splits': None,
+ '2d6': None
+ },
+ '9': {
+ 'result': None,
+ 'splits': None,
+ '2d6': None
+ },
+ '10': {
+ 'result': None,
+ 'splits': None,
+ '2d6': None
+ },
+ '11': {
+ 'result': None,
+ 'splits': None,
+ '2d6': None
+ },
+ '12': {
+ 'result': None,
+ 'splits': None,
+ '2d6': None
+ },
+ 'splits': 0
+ },
+ '2': {
+ '2': {
+ 'result': None,
+ 'splits': None,
+ '2d6': None
+ },
+ '3': {
+ 'result': None,
+ 'splits': None,
+ '2d6': None
+ },
+ '4': {
+ 'result': None,
+ 'splits': None,
+ '2d6': None
+ },
+ '5': {
+ 'result': None,
+ 'splits': None,
+ '2d6': None
+ },
+ '6': {
+ 'result': None,
+ 'splits': None,
+ '2d6': None
+ },
+ '7': {
+ 'result': None,
+ 'splits': None,
+ '2d6': None
+ },
+ '8': {
+ 'result': None,
+ 'splits': None,
+ '2d6': None
+ },
+ '9': {
+ 'result': None,
+ 'splits': None,
+ '2d6': None
+ },
+ '10': {
+ 'result': None,
+ 'splits': None,
+ '2d6': None
+ },
+ '11': {
+ 'result': None,
+ 'splits': None,
+ '2d6': None
+ },
+ '12': {
+ 'result': None,
+ 'splits': None,
+ '2d6': None
+ },
+ 'splits': 0
+ },
+ '3': {
+ '2': {
+ 'result': None,
+ 'splits': None,
+ '2d6': None
+ },
+ '3': {
+ 'result': None,
+ 'splits': None,
+ '2d6': None
+ },
+ '4': {
+ 'result': None,
+ 'splits': None,
+ '2d6': None
+ },
+ '5': {
+ 'result': None,
+ 'splits': None,
+ '2d6': None
+ },
+ '6': {
+ 'result': None,
+ 'splits': None,
+ '2d6': None
+ },
+ '7': {
+ 'result': None,
+ 'splits': None,
+ '2d6': None
+ },
+ '8': {
+ 'result': None,
+ 'splits': None,
+ '2d6': None
+ },
+ '9': {
+ 'result': None,
+ 'splits': None,
+ '2d6': None
+ },
+ '10': {
+ 'result': None,
+ 'splits': None,
+ '2d6': None
+ },
+ '11': {
+ 'result': None,
+ 'splits': None,
+ '2d6': None
+ },
+ '12': {
+ 'result': None,
+ 'splits': None,
+ '2d6': None
+ },
+ 'splits': 0
+ }
+ },
+ 'vR': {
+ '1': {
+ '2': {
+ 'result': None,
+ 'splits': None,
+ '2d6': None
+ },
+ '3': {
+ 'result': None,
+ 'splits': None,
+ '2d6': None
+ },
+ '4': {
+ 'result': None,
+ 'splits': None,
+ '2d6': None
+ },
+ '5': {
+ 'result': None,
+ 'splits': None,
+ '2d6': None
+ },
+ '6': {
+ 'result': None,
+ 'splits': None,
+ '2d6': None
+ },
+ '7': {
+ 'result': None,
+ 'splits': None,
+ '2d6': None
+ },
+ '8': {
+ 'result': None,
+ 'splits': None,
+ '2d6': None
+ },
+ '9': {
+ 'result': None,
+ 'splits': None,
+ '2d6': None
+ },
+ '10': {
+ 'result': None,
+ 'splits': None,
+ '2d6': None
+ },
+ '11': {
+ 'result': None,
+ 'splits': None,
+ '2d6': None
+ },
+ '12': {
+ 'result': None,
+ 'splits': None,
+ '2d6': None
+ },
+ 'splits': 0
+ },
+ '2': {
+ '2': {
+ 'result': None,
+ 'splits': None,
+ '2d6': None
+ },
+ '3': {
+ 'result': None,
+ 'splits': None,
+ '2d6': None
+ },
+ '4': {
+ 'result': None,
+ 'splits': None,
+ '2d6': None
+ },
+ '5': {
+ 'result': None,
+ 'splits': None,
+ '2d6': None
+ },
+ '6': {
+ 'result': None,
+ 'splits': None,
+ '2d6': None
+ },
+ '7': {
+ 'result': None,
+ 'splits': None,
+ '2d6': None
+ },
+ '8': {
+ 'result': None,
+ 'splits': None,
+ '2d6': None
+ },
+ '9': {
+ 'result': None,
+ 'splits': None,
+ '2d6': None
+ },
+ '10': {
+ 'result': None,
+ 'splits': None,
+ '2d6': None
+ },
+ '11': {
+ 'result': None,
+ 'splits': None,
+ '2d6': None
+ },
+ '12': {
+ 'result': None,
+ 'splits': None,
+ '2d6': None
+ },
+ 'splits': 0
+ },
+ '3': {
+ '2': {
+ 'result': None,
+ 'splits': None,
+ '2d6': None
+ },
+ '3': {
+ 'result': None,
+ 'splits': None,
+ '2d6': None
+ },
+ '4': {
+ 'result': None,
+ 'splits': None,
+ '2d6': None
+ },
+ '5': {
+ 'result': None,
+ 'splits': None,
+ '2d6': None
+ },
+ '6': {
+ 'result': None,
+ 'splits': None,
+ '2d6': None
+ },
+ '7': {
+ 'result': None,
+ 'splits': None,
+ '2d6': None
+ },
+ '8': {
+ 'result': None,
+ 'splits': None,
+ '2d6': None
+ },
+ '9': {
+ 'result': None,
+ 'splits': None,
+ '2d6': None
+ },
+ '10': {
+ 'result': None,
+ 'splits': None,
+ '2d6': None
+ },
+ '11': {
+ 'result': None,
+ 'splits': None,
+ '2d6': None
+ },
+ '12': {
+ 'result': None,
+ 'splits': None,
+ '2d6': None
+ },
+ 'splits': 0
+ }
+ }
+}
+TESTING = False
+YES = ['y', 'yes', 'yeet', 'please', 'yeah']
+
+
+def mround(x, prec=2, base=.05):
+ return round(base * round(float(x) / base), prec)
+
+
+def chances_from_row(row_num):
+ if row_num == '2' or row_num == '12':
+ return 1
+ if row_num == '3' or row_num == '11':
+ return 2
+ if row_num == '4' or row_num == '10':
+ return 3
+ if row_num == '5' or row_num == '9':
+ return 4
+ if row_num == '6' or row_num == '8':
+ return 5
+ if row_num == '7':
+ return 6
+ raise ValueError(f'No chance count found for row_num {row_num}')
+
+
+def legal_splits(tot_chances):
+ legal_2d6 = []
+ for x in D20_CHANCES:
+ num_incs = mround(tot_chances) / D20_CHANCES[x]['inc']
+ if num_incs - int(num_incs) == 0 and int(20 - num_incs) > 0:
+ legal_2d6.append({
+ '2d6': int(x),
+ 'incs': int(num_incs),
+ 'bad_chances': mround(D20_CHANCES[x]['chances'] * (int(20 - num_incs) / 20)),
+ 'bad_incs': int(20 - num_incs)
+ })
+
+ random.shuffle(legal_2d6)
+ # if TESTING: print(f'tot_chances: {myround(tot_chances)}')
+ # if TESTING: print(f'legal_2d6: {legal_2d6}')
+ return legal_2d6
+
+
+def result_string(tba_data, row_num, split_min=None, split_max=None):
+ bold1 = f'{"" if tba_data["bold"] else ""}'
+ bold2 = f'{"" if tba_data["bold"] else ""}'
+ row_string = f'{" " if int(row_num) < 10 else ""}{row_num}'
+ if TESTING: print(f'adding {tba_data["string"]} to row {row_num} / '
+ f'split_min: {split_min} / split_max: {split_max}')
+
+ # No splits; standard result
+ if not split_min:
+ return f'{bold1}{row_string}-{tba_data["string"]}{bold2}'
+
+ # With splits
+ split_nums = f'{split_min if split_min != 20 else ""}{"-" if split_min != 20 else ""}{split_max}'
+ data_string = tba_data["sm-string"] if "sm-string" in tba_data.keys() else tba_data["string"]
+ spaces = 18 - len(data_string) - len(split_nums)
+ if 'WALK' in data_string:
+ spaces -= 3
+ elif 'SI**' in data_string:
+ spaces += 1
+ elif 'DO*' in data_string:
+ spaces -= 1
+ elif 'DO*' in data_string:
+ spaces -= 2
+ elif 'so' in data_string:
+ spaces += 3
+ elif 'gb' in data_string:
+ spaces -= 3
+
+ if TESTING: print(f'len(tba_data["string"]): {len(data_string)} / len(split_nums): {len(split_nums)} '
+ f'spaces: {spaces}')
+ if split_min == 1 or split_min is None:
+ row_output = f'{row_string}-'
+ else:
+ row_output = ' '
+ if TESTING: print(f'row_output: {row_output}')
+ return f'{bold1}{row_output}{data_string}{" " * spaces}{split_nums}{bold2}'
+
+
+def result_data(tba_data, row_num, tba_data_bottom=None, top_split_max=None, fatigue=False):
+ ret_data = {}
+ top_bold1 = f'{"" if tba_data["bold"] else ""}'
+ top_bold2 = f'{"" if tba_data["bold"] else ""}'
+ bot_bold1 = None
+ bot_bold2 = None
+ if tba_data_bottom:
+ bot_bold1 = f'{"" if tba_data_bottom["bold"] else ""}'
+ bot_bold2 = f'{"" if tba_data_bottom["bold"] else ""}'
+
+ if tba_data_bottom is None:
+ ret_data['2d6'] = f'{top_bold1}{int(row_num)}-{top_bold2}'
+ ret_data['splits'] = f'{top_bold1}{top_bold2}'
+ ret_data['result'] = f'{top_bold1}' \
+ f'{tba_data["string"]}{" •" if fatigue else ""}' \
+ f'{top_bold2}'
+ else:
+ ret_data['2d6'] = f'{top_bold1}{int(row_num)}-{top_bold2}\n'
+ ret_data['splits'] = f'{top_bold1}1{"-" if top_split_max != 1 else ""}' \
+ f'{top_split_max if top_split_max != 1 else ""}{top_bold2}\n' \
+ f'{bot_bold1}{top_split_max+1}{"-20" if top_split_max != 19 else ""}{bot_bold2}'
+ ret_data['result'] = \
+ f'{top_bold1}{tba_data["sm-string"] if "sm-string" in tba_data.keys() else tba_data["string"]}' \
+ f'{top_bold2}\n' \
+ f'{bot_bold1}' \
+ f'{tba_data_bottom["sm-string"] if "sm-string" in tba_data_bottom.keys() else tba_data_bottom["string"]}' \
+ f'{bot_bold2}'
+
+ return ret_data
+
+
+def get_of(batter_hand, pitcher_hand, pull_side=True):
+ if batter_hand == 'R':
+ return 'lf' if pull_side else 'rf'
+
+ if batter_hand == 'L':
+ return 'rf' if pull_side else 'lf'
+
+ if batter_hand == 'S':
+ if pitcher_hand == 'L':
+ return 'rf' if pull_side else 'rf'
+ else:
+ return 'lf' if pull_side else 'lf'
+
+
+def get_col(col_num):
+ if col_num == '1':
+ return 'one'
+ if col_num == '2':
+ return 'two'
+ if col_num == '3':
+ return 'three'
+
+
+def write_to_csv(output_path, file_name: str, row_data: list):
+ # Build the csv output
+ fpath = (output_path / f'{file_name}').with_suffix('.csv')
+ logging.info(f'Printing following data to {file_name}:\n\n{row_data}')
+ with fpath.open(mode='w+', newline='', encoding='utf-8') as csv_File:
+ writer = csv.writer(csv_File)
+ writer.writerows(row_data)
+
+
+def get_position_string(all_pos: list, inc_p: bool):
+ if len(all_pos) == 0:
+ return 'dh'
+
+ of_arm = None
+ of_error = None
+ of_innings = None
+ lf_range = None
+ lf_innings = 0
+ cf_range = None
+ cf_innings = 0
+ rf_range = None
+ rf_innings = 0
+
+ all_def = []
+
+ for x in all_pos:
+ if x.position == 'OF':
+ of_arm = f'{"+" if "-" not in x.arm else ""}{x.arm}'
+ of_error = x.error
+ of_innings = x.innings
+ elif x.position == 'CF':
+ cf_range = x.range
+ cf_innings = x.innings
+ elif x.position == 'LF':
+ lf_range = x.range
+ lf_innings = x.innings
+ elif x.position == 'RF':
+ rf_range = x.range
+ rf_innings = x.innings
+ elif x.position == 'C':
+ all_def.append((f'c-{x.range}({x.arm}) e{x.error} T-{x.overthrow}(pb-{x.pb})', x.innings))
+ elif 'P' in x.position and not inc_p:
+ pass
+ else:
+ all_def.append((f'{x.position.lower()}-{x.range}e{x.error}', x.innings))
+
+ if of_arm is not None:
+ all_of = []
+ if lf_innings > 0:
+ all_of.append((lf_range, lf_innings, 'lf'))
+ if cf_innings > 0:
+ all_of.append((cf_range, cf_innings, 'cf'))
+ if rf_innings > 0:
+ all_of.append((rf_range, rf_innings, 'rf'))
+
+ if len(all_of) > 0:
+ all_of.sort(key=lambda y: y[1], reverse=True)
+ out_string = f'{all_of[0][2]}-{all_of[0][0]}({of_arm})e{of_error}'
+ if len(all_of) == 2:
+ out_string += f', {all_of[1][2]}-{all_of[1][0]}e{of_error}'
+ if len(all_of) == 3:
+ out_string += f', {all_of[2][2]}-{all_of[2][0]}e{of_error}'
+ all_def.append((out_string, of_innings))
+
+ all_def.sort(key=lambda z: z[1], reverse=True)
+
+ final_defense = ''
+ for x in all_def:
+ if len(final_defense) > 0:
+ final_defense += f', '
+ final_defense += f'{x[0]}'
+
+ return final_defense
+
+
+def ordered_positions(all_pos: list) -> list:
+ all_def = []
+
+ for x in all_pos:
+ if x.position not in ['OF', 'P', 'SP', 'RP', 'CP']:
+ all_def.append((x.innings, x.position))
+
+ all_def.sort(key=lambda y: y[0], reverse=True)
+ return [x[1] for x in all_def]
+
+
+def ordered_pitching_positions(all_pos: list) -> list:
+ all_def = []
+
+ for x in all_pos:
+ if x.position in ['SP', 'RP', 'CP']:
+ all_def.append((x.innings, x.position))
+
+ all_def.sort(key=lambda y: y[0], reverse=True)
+ return [x[1] for x in all_def]
+
+
+def defense_rg(all_pos: list) -> list:
+ rg_data = [
+ None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None,
+ None, None, None, None, None, None
+ ]
+ all_pitcher = True
+ for line in all_pos:
+ if 'P' not in line.position:
+ all_pitcher = False
+ break
+
+ for line in all_pos:
+ if line.position == 'P' and all_pitcher:
+ this_pit = PitcherData.get_or_none(PitcherData.player == line.player, PitcherData.cardset == line.cardset)
+ if this_pit:
+ rg_data[0] = line.range
+ rg_data[9] = line.error
+ rg_data[22] = this_pit.wild_pitch
+ rg_data[23] = this_pit.balk
+ elif line.position == 'C':
+ rg_data[1] = line.range
+ rg_data[10] = line.error
+ rg_data[19] = line.arm
+ rg_data[20] = line.overthrow
+ rg_data[21] = line.pb
+ elif line.position == '1B':
+ rg_data[2] = line.range
+ rg_data[11] = line.error
+ elif line.position == '2B':
+ rg_data[3] = line.range
+ rg_data[12] = line.error
+ elif line.position == '3B':
+ rg_data[4] = line.range
+ rg_data[13] = line.error
+ elif line.position == 'SS':
+ rg_data[5] = line.range
+ rg_data[14] = line.error
+ elif line.position == 'LF':
+ rg_data[6] = line.range
+ elif line.position == 'CF':
+ rg_data[7] = line.range
+ elif line.position == 'RF':
+ rg_data[8] = line.range
+ elif line.position == 'OF':
+ rg_data[15] = line.error
+ rg_data[16] = line.error
+ rg_data[17] = line.error
+ rg_data[18] = line.arm
+
+ return rg_data
+