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 +