Added Reaction to basic ratings

This commit is contained in:
Cal Corum 2023-10-27 12:54:54 -05:00
parent 58a0d10226
commit d3c4e4b575

View File

@ -1,11 +1,13 @@
from fastapi import APIRouter, Depends, HTTPException, Query, Response
from scipy import stats
from typing import Literal, Optional, List
import logging
import pandas as pd
import pydantic
from pydantic import validator, root_validator
from ..db_engine import db, BattingCardRatings, model_to_dict, chunked, BattingCard, Player, query_to_csv, Team
from ..db_engine import db, BattingCardRatings, model_to_dict, chunked, BattingCard, Player, query_to_csv, Team, \
CardPosition
from ..dependencies import oauth2_scheme, valid_token, LOG_DATA
logging.basicConfig(
@ -138,17 +140,7 @@ async def get_card_ratings(
return return_val
@router.get('/scouting')
async def get_card_scouting(team_id: int, ts: str, cardset_id: list = Query(default=None)):
this_team = Team.get_or_none(Team.id == team_id)
logging.debug(f'Team: {this_team} / has_guide: {this_team.has_guide}')
if this_team is None or ts != this_team.team_hash() or this_team.has_guide != 1:
logging.warning(f'Team_id {team_id} attempted to pull ratings')
db.close()
return 'Your team does not have the ratings guide enabled. If you have purchased a copy ping Cal to ' \
'make sure it is enabled on your team. If you are interested you can pick it up here (thank you!): ' \
'https://ko-fi.com/manticorum/shop'
def get_scouting_dfs(cardset_id: list = None):
all_ratings = BattingCardRatings.select()
if cardset_id is not None:
set_players = Player.select(Player.player_id).where(Player.cardset_id << cardset_id)
@ -178,14 +170,192 @@ async def get_card_scouting(team_id: int, ts: str, cardset_id: list = Query(defa
vr = pd.DataFrame(vr_vals)
db.close()
output = pd.merge(vl, vr, on='player_id', suffixes=('_vl', '_vr'))
bat_df = pd.merge(vl, vr, on='player_id', suffixes=('_vl', '_vr')).set_index('player_id', drop=False)
# output['Range P'] = ''
# output['Range C'] = ''
# output['Range 1B'] = ''
# output['Range 2B'] = ''
# output['Range 3B'] = ''
# output['Range SS'] = ''
# output['Range LF'] = ''
# output['Range CF'] = ''
# output['Range RF'] = ''
# output['Error P'] = ''
# output['Error C'] = ''
# output['Error 1B'] = ''
# output['Error 2B'] = ''
# output['Error 3B'] = ''
# output['Error SS'] = ''
# output['Error LF'] = ''
# output['Error CF'] = ''
# output['Error RF'] = ''
# output['Arm C'] = ''
# output['Throw C'] = ''
# output['PB C'] = ''
# output['Arm OF'] = ''
logging.info(f'bat_df: {bat_df}')
positions = CardPosition.select()
if cardset_id is not None:
set_players = Player.select(Player.player_id).where(Player.cardset_id << cardset_id)
positions = positions.where(CardPosition.player << set_players)
series_list = []
for pos_code in ['P', 'C', '1B', '2B', '3B', 'SS', 'LF', 'CF', 'RF']:
series_list.append(pd.Series(
dict([(x.player.player_id, x.range) for x in positions.where(CardPosition.position == pos_code)]),
name=f'Range {pos_code}'
))
series_list.append(pd.Series(
dict([(x.player.player_id, x.error) for x in positions.where(CardPosition.position == pos_code)]),
name=f'Error {pos_code}'
))
# bat_df.join(pd.Series(
# dict([(x.player.player_id, x.range) for x in positions.where(CardPosition.position == pos_code)]),
# name=f'Range {pos_code}'
# ))
# bat_df.join(pd.Series(
# dict([(x.player.player_id, x.error) for x in positions.where(CardPosition.position == pos_code)]),
# name=f'Error {pos_code}'
# ))
series_list.append(pd.Series(
dict([(x.player.player_id, x.arm) for x in positions.where(CardPosition.position << ['LF', 'CF', 'RF'])]),
name=f'Arm OF'
))
series_list.append(pd.Series(
dict([(x.player.player_id, x.arm) for x in positions.where(CardPosition.position == 'C')]),
name=f'Arm C'
))
series_list.append(pd.Series(
dict([(x.player.player_id, x.pb) for x in positions.where(CardPosition.position == 'C')]),
name=f'PB C'
))
series_list.append(pd.Series(
dict([(x.player.player_id, x.overthrow) for x in positions.where(CardPosition.position == 'C')]),
name=f'Throw C'
))
logging.info(f'series_list: {series_list}')
# for x in positions:
# if x.position != 'DH':
# output.at[f'{x.player.player_id}', f'Range {x.position}'] = x.range # vals in .at list are reversed
# output.at[f'{x.player.player_id}', f'Error {x.position}'] = x.error
# if x.position in ['LF', 'CF', 'RF']:
# output.at[f'{x.player.player_id}', f'Arm OF'] = x.arm
# if x.position == 'C':
# output.at[f'{x.player.player_id}', f'Arm C'] = x.arm
# output.at[f'{x.player.player_id}', f'PB C'] = x.pb
# output.at[f'{x.player.player_id}', f'Throw C'] = x.overthrow
return bat_df.join(series_list)
@router.get('/scouting')
async def get_card_scouting(team_id: int, ts: str, cardset_id: list = Query(default=None)):
this_team = Team.get_or_none(Team.id == team_id)
logging.debug(f'Team: {this_team} / has_guide: {this_team.has_guide}')
if this_team is None or ts != this_team.team_hash() or this_team.has_guide != 1:
logging.warning(f'Team_id {team_id} attempted to pull ratings')
db.close()
return 'Your team does not have the ratings guide enabled. If you have purchased a copy ping Cal to ' \
'make sure it is enabled on your team. If you are interested you can pick it up here (thank you!): ' \
'https://ko-fi.com/manticorum/shop'
# all_ratings = BattingCardRatings.select()
# if cardset_id is not None:
# set_players = Player.select(Player.player_id).where(Player.cardset_id << cardset_id)
# set_cards = BattingCard.select(BattingCard.id).where(BattingCard.player << set_players)
# all_ratings = all_ratings.where(BattingCardRatings.battingcard << set_cards)
#
# vl_query = all_ratings.where(BattingCardRatings.vs_hand == 'L')
# vr_query = all_ratings.where(BattingCardRatings.vs_hand == 'R')
#
# vl_vals = [model_to_dict(x) for x in vl_query]
# for x in vl_vals:
# x.update(x['battingcard'])
# x['player_id'] = x['battingcard']['player']['player_id']
# x['player_name'] = x['battingcard']['player']['p_name']
# x['rarity'] = x['battingcard']['player']['rarity']['name']
# x['cardset_id'] = x['battingcard']['player']['cardset']['id']
# x['cardset_name'] = x['battingcard']['player']['cardset']['name']
# del x['battingcard']
# del x['player']
#
# vr_vals = [model_to_dict(x) for x in vr_query]
# for x in vr_vals:
# x['player_id'] = x['battingcard']['player']['player_id']
# del x['battingcard']
#
# vl = pd.DataFrame(vl_vals)
# vr = pd.DataFrame(vr_vals)
# db.close()
output = get_scouting_dfs(cardset_id)
first = ['player_id', 'player_name', 'cardset_name', 'rarity', 'hand', 'variant']
exclude = first + ['id_vl', 'id_vr', 'vs_hand_vl', 'vs_hand_vr']
output = output[first + [col for col in output.columns if col not in exclude]].sort_values(by=['player_id'])
output = output[first + [col for col in output.columns if col not in exclude]]
# output = output.sort_values(by=['player_id'])
return Response(content=pd.DataFrame(output).to_csv(index=False), media_type='text/csv')
@router.get('/basic')
async def get_basic_scouting(cardset_id: list = Query(default=None)):
raw_data = get_scouting_dfs(cardset_id)
logging.info(f'output: {raw_data}')
def get_raw_speed(df_data):
speed_raw = df_data['running'] / 20 + df_data['steal_jump']
if df_data['steal_auto']:
speed_raw += 0.5
return speed_raw
raw_data['speed_raw'] = raw_data.apply(get_raw_speed, axis=1)
raw_data['speed_rank'] = raw_data['speed_raw'].rank(pct=True)
raw_data['Speed'] = round(raw_data['speed_rank'] * 100)
def get_raw_steal(df_data):
return (
((df_data['steal_high'] / 20) + (df_data['steal_low'] / 20)) * df_data['steal_jump']
)
raw_data['steal_raw'] = raw_data.apply(get_raw_steal, axis=1)
raw_data['steal_rank'] = raw_data['steal_raw'].rank(pct=True)
raw_data['Steal'] = round(raw_data['steal_rank'] * 100)
def get_raw_reaction(df_data):
raw_total = 0
for pos_range in [df_data['Range C'], df_data['Range 1B'], df_data['Range 2B'], df_data['Range 3B'],
df_data['Range SS'], df_data['Range LF'], df_data['Range CF'], df_data['Range RF']]:
if pd.notna(pos_range):
raw_total += 10 ** (5 - pos_range)
return raw_total
raw_data['reaction_raw'] = raw_data.apply(get_raw_reaction, axis=1)
raw_data['reaction_rank'] = raw_data['reaction_raw'].rank(pct=True)
raw_data['Reaction'] = round(raw_data['reaction_rank'] * 100)
def get_raw_arm(df_data):
of_arm = None
# get top of pos
# Neg arm * -5 / (6 - Pos arm) * 3
# apply pos multiplier (rf: 1.5, cf: 1, lf: 0.5)
# add value by pos (rf: (6-rf_range) * 4, cf: (6-cf_range) * 3,lf: (6-lf_range) * 2)
if_arm = None
# 100 - (50 - ((6-3b_range) * 5) + (6-ss_range) * 4 + (6-2b_range) * 3 + (6-1b_range) )
c_arm = None
# -5: 100
# (10 - c_arm) * 3 + (20 - c_pb) + (20 - c_overthrow) - c_error + 20
output = raw_data[['player_id', 'player_name', 'cardset_name', 'Speed', 'Steal', 'Reaction']]
# raw_data.sort_values(by=['player_id'], inplace=True)
return Response(content=output.to_csv(index=True), media_type='text/csv')
@router.get('/{ratings_id}')
async def get_one_rating(ratings_id: int, token: str = Depends(oauth2_scheme)):
if not valid_token(token):