diff --git a/.claude/ops-rework/check_prod_missing_ratings.py b/.claude/ops-rework/check_prod_missing_ratings.py
index 176f23d..0397b87 100644
--- a/.claude/ops-rework/check_prod_missing_ratings.py
+++ b/.claude/ops-rework/check_prod_missing_ratings.py
@@ -1,8 +1,14 @@
import asyncio
+import sys
+from pathlib import Path
+
import aiohttp
import pandas as pd
-AUTH_TOKEN = {"Authorization": "Bearer Tp3aO3jhYve5NJF1IqOmJTmk"}
+# Add project root so we can import db_calls
+sys.path.insert(0, str(Path(__file__).resolve().parents[2]))
+from db_calls import AUTH_TOKEN
+
PROD_URL = "https://pd.manticorum.com/api"
diff --git a/.env.example b/.env.example
new file mode 100644
index 0000000..44c592a
--- /dev/null
+++ b/.env.example
@@ -0,0 +1,2 @@
+# Paper Dynasty API
+PD_API_TOKEN=your-bearer-token-here
diff --git a/batters/calcs_batter.py b/batters/calcs_batter.py
index 0693d0f..b039041 100644
--- a/batters/calcs_batter.py
+++ b/batters/calcs_batter.py
@@ -573,7 +573,7 @@ def stealing_line(steal_data: dict):
else:
good_jump = "2-12"
- return f'{"*" if sd[2] else ""}{good_jump}/- ({sd[1] if sd[1] else "-"}-{sd[0] if sd[0] else "-"})'
+ return f"{'*' if sd[2] else ''}{good_jump}/- ({sd[1] if sd[1] else '-'}-{sd[0] if sd[0] else '-'})"
def running(extra_base_pct: str):
@@ -583,7 +583,7 @@ def running(extra_base_pct: str):
xb_pct = float(extra_base_pct.strip("%")) / 80
except Exception as e:
logger.error(f"calcs_batter running - {e}")
- xb_pct = 20
+ return 8
return max(min(round(6 + (10 * xb_pct)), 17), 8)
@@ -693,11 +693,11 @@ def get_batter_ratings(df_data) -> List[dict]:
logger.debug(
f"all on base: {vl.hbp + vl.walk + vl.total_hits()} / all chances: {vl.total_chances()}"
- f'{"*******ERROR ABOVE*******" if vl.hbp + vl.walk + vl.total_hits() != vl.total_chances() else ""}'
+ f"{'*******ERROR ABOVE*******' if vl.hbp + vl.walk + vl.total_hits() != vl.total_chances() else ''}"
)
logger.debug(
f"all on base: {vr.hbp + vr.walk + vr.total_hits()} / all chances: {vr.total_chances()}"
- f'{"*******ERROR ABOVE*******" if vr.hbp + vr.walk + vr.total_hits() != vr.total_chances() else ""}'
+ f"{'*******ERROR ABOVE*******' if vr.hbp + vr.walk + vr.total_hits() != vr.total_chances() else ''}"
)
vl.calculate_strikeouts(df_data["SO_vL"], df_data["AB_vL"], df_data["H_vL"])
diff --git a/creation_helpers.py b/creation_helpers.py
index f1081e0..117c6ea 100644
--- a/creation_helpers.py
+++ b/creation_helpers.py
@@ -533,7 +533,7 @@ def get_pitching_peripherals(season: int):
row_data.append(player_id)
if len(headers) == 0:
col_names.append("key_bbref")
- except Exception:
+ except KeyError:
pass
row_data.append(cell.text)
if len(headers) == 0:
@@ -595,21 +595,21 @@ def legal_splits(tot_chances):
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}'
+ 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"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}'
+ 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}'
+ 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"]
)
@@ -618,10 +618,10 @@ def result_string(tba_data, row_num, split_min=None, split_max=None):
spaces -= 3
elif "SI**" in data_string:
spaces += 1
+ elif "DO**" in data_string:
+ spaces -= 2
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:
@@ -638,41 +638,39 @@ def result_string(tba_data, row_num, split_min=None, split_max=None):
row_output = " "
if TESTING:
print(f"row_output: {row_output}")
- return f'{bold1}{row_output}{data_string}{" " * spaces}{split_nums}{bold2}'
+ 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 ""}'
+ 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 ""}'
+ 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}"
+ f"{top_bold1}{tba_data['string']}{' •' if fatigue else ''}{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}'
+ 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_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"{tba_data_bottom['sm-string'] if 'sm-string' in tba_data_bottom.keys() else tba_data_bottom['string']}"
f"{bot_bold2}"
)
@@ -688,9 +686,9 @@ def get_of(batter_hand, pitcher_hand, pull_side=True):
if batter_hand == "S":
if pitcher_hand == "L":
- return "rf" if pull_side else "rf"
+ return "lf" if pull_side else "rf"
else:
- return "lf" if pull_side else "lf"
+ return "rf" if pull_side else "lf"
def get_col(col_num):
@@ -729,7 +727,7 @@ def get_position_string(all_pos: list, inc_p: bool):
for x in all_pos:
if x.position == "OF":
- of_arm = f'{"+" if "-" not in x.arm else ""}{x.arm}'
+ of_arm = f"{'+' if '-' not in x.arm else ''}{x.arm}"
of_error = x.error
of_innings = x.innings
elif x.position == "CF":
@@ -744,7 +742,7 @@ def get_position_string(all_pos: list, inc_p: bool):
elif x.position == "C":
all_def.append(
(
- f'c-{x.range}({"+" if int(x.arm) >= 0 else ""}{x.arm}) e{x.error} T-{x.overthrow}(pb-{x.pb})',
+ f"c-{x.range}({'+' if int(x.arm) >= 0 else ''}{x.arm}) e{x.error} T-{x.overthrow}(pb-{x.pb})",
x.innings,
)
)
@@ -1079,7 +1077,7 @@ def mlbteam_and_franchise(mlbam_playerid):
p_data["franchise"] = normalize_franchise(data["currentTeam"]["name"])
else:
logger.error(
- f'Could not set team for {mlbam_playerid}; received {data["currentTeam"]["name"]}'
+ f"Could not set team for {mlbam_playerid}; received {data['currentTeam']['name']}"
)
else:
logger.error(
@@ -1222,5 +1220,5 @@ def get_hand(df_data):
else:
return "R"
except Exception:
- logger.error(f'Error in get_hand for {df_data["Name"]}')
+ logger.error(f"Error in get_hand for {df_data['Name']}")
return "R"
diff --git a/db_calls.py b/db_calls.py
index ae3d4a9..7cb3c33 100644
--- a/db_calls.py
+++ b/db_calls.py
@@ -1,10 +1,18 @@
+import os
+
import aiohttp
import pybaseball as pb
+from dotenv import load_dotenv
from typing import Literal
from exceptions import logger
-AUTH_TOKEN = {"Authorization": "Bearer Tp3aO3jhYve5NJF1IqOmJTmk"}
+load_dotenv()
+
+_token = os.environ.get("PD_API_TOKEN")
+if not _token:
+ raise EnvironmentError("PD_API_TOKEN environment variable is required")
+AUTH_TOKEN = {"Authorization": f"Bearer {_token}"}
DB_URL = "https://pd.manticorum.com/api"
master_debug = True
alt_database = None
@@ -25,7 +33,7 @@ def param_char(other_params):
def get_req_url(
endpoint: str, api_ver: int = 2, object_id: int = None, params: list = None
):
- req_url = f'{DB_URL}/v{api_ver}/{endpoint}{"/" if object_id is not None else ""}{object_id if object_id is not None else ""}'
+ req_url = f"{DB_URL}/v{api_ver}/{endpoint}{'/' if object_id is not None else ''}{object_id if object_id is not None else ''}"
if params:
other_params = False
@@ -39,11 +47,11 @@ def get_req_url(
def log_return_value(log_string: str):
if master_debug:
logger.info(
- f'return: {log_string[:1200]}{" [ S N I P P E D ]" if len(log_string) > 1200 else ""}\n'
+ f"return: {log_string[:1200]}{' [ S N I P P E D ]' if len(log_string) > 1200 else ''}\n"
)
else:
logger.debug(
- f'return: {log_string[:1200]}{" [ S N I P P E D ]" if len(log_string) > 1200 else ""}\n'
+ f"return: {log_string[:1200]}{' [ S N I P P E D ]' if len(log_string) > 1200 else ''}\n"
)
@@ -183,4 +191,4 @@ def get_player_data(
def player_desc(this_player) -> str:
if this_player["p_name"] in this_player["description"]:
return this_player["description"]
- return f'{this_player["description"]} {this_player["p_name"]}'
+ return f"{this_player['description']} {this_player['p_name']}"
diff --git a/pitchers/creation.py b/pitchers/creation.py
index 064627d..09f38ad 100644
--- a/pitchers/creation.py
+++ b/pitchers/creation.py
@@ -196,8 +196,8 @@ async def create_new_players(
{
"p_name": f"{f_name} {l_name}",
"cost": NEW_PLAYER_COST,
- "image": f'{card_base_url}/{df_data["player_id"]}/'
- f'pitchingcard{urllib.parse.quote("?d=")}{release_dir}',
+ "image": f"{card_base_url}/{df_data['player_id']}/"
+ f"pitchingcard{urllib.parse.quote('?d=')}{release_dir}",
"mlbclub": CLUB_LIST[df_data["Tm_vL"]],
"franchise": FRANCHISE_LIST[df_data["Tm_vL"]],
"cardset_id": cardset["id"],
@@ -268,7 +268,7 @@ async def calculate_pitching_cards(
def create_pitching_card(df_data):
logger.info(
- f'Creating pitching card for {df_data["name_first"]} {df_data["name_last"]} / fg ID: {df_data["key_fangraphs"]}'
+ f"Creating pitching card for {df_data['name_first']} {df_data['name_last']} / fg ID: {df_data['key_fangraphs']}"
)
pow_data = cde.pow_ratings(
float(df_data["Inn_def"]), df_data["GS"], df_data["G"]
@@ -298,11 +298,11 @@ async def calculate_pitching_cards(
int(df_data["GF"]), int(df_data["SV"]), int(df_data["G"])
),
"hand": df_data["pitch_hand"],
- "batting": f'#1W{df_data["pitch_hand"]}-C',
+ "batting": f"#1W{df_data['pitch_hand']}-C",
}
)
except Exception as e:
- logger.error(f'Skipping fg ID {df_data["key_fangraphs"]} due to: {e}')
+ logger.error(f"Skipping fg ID {df_data['key_fangraphs']} due to: {e}")
print("Calculating pitching cards...")
pitching_stats.apply(create_pitching_card, axis=1)
@@ -333,7 +333,7 @@ async def create_position(
def create_pit_position(df_data):
if df_data["key_bbref"] in df_p.index:
- logger.debug(f'Running P stats for {df_data["p_name"]}')
+ logger.debug(f"Running P stats for {df_data['p_name']}")
pit_positions.append(
{
"player_id": int(df_data["player_id"]),
@@ -355,7 +355,7 @@ async def create_position(
try:
pit_positions.append(
{
- "player_id": int(df_data["key_bbref"]),
+ "player_id": int(float(df_data["player_id"])),
"position": "P",
"innings": 1,
"range": 5,
@@ -364,7 +364,7 @@ async def create_position(
)
except Exception:
logger.error(
- f'Could not create pitcher position for {df_data["key_bbref"]}'
+ f"Could not create pitcher position for {df_data['key_bbref']}"
)
print("Calculating pitcher fielding lines now...")
@@ -386,7 +386,7 @@ async def calculate_pitcher_ratings(pitching_stats: pd.DataFrame, post_pitchers:
pitching_ratings.extend(cpi.get_pitcher_ratings(df_data))
except Exception:
logger.error(
- f'Could not create a pitching card for {df_data["key_fangraphs"]}'
+ f"Could not create a pitching card for {df_data['key_fangraphs']}"
)
print("Calculating card ratings...")
@@ -525,8 +525,8 @@ async def post_player_updates(
[
(
"image",
- f'{card_base_url}/{df_data["player_id"]}/pitchingcard'
- f'{urllib.parse.quote("?d=")}{release_dir}',
+ f"{card_base_url}/{df_data['player_id']}/pitchingcard"
+ f"{urllib.parse.quote('?d=')}{release_dir}",
)
]
)
diff --git a/pyproject.toml b/pyproject.toml
index 82ec9b4..c19e0ee 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -23,6 +23,8 @@ dependencies = [
"pydantic>=2.9.0",
# AWS
"boto3>=1.35.0",
+ # Environment
+ "python-dotenv>=1.0.0",
# Scraping
"beautifulsoup4>=4.12.0",
"lxml>=5.0.0",
diff --git a/retrosheet_data.py b/retrosheet_data.py
index 6f41501..8b18204 100644
--- a/retrosheet_data.py
+++ b/retrosheet_data.py
@@ -67,7 +67,7 @@ START_DATE = 20050403 # YYYYMMDD format - 2005 Opening Day
# END_DATE = 20050531 # YYYYMMDD format - May PotM
END_DATE = 20050731 # End of July 2005
POST_DATA = True
-LAST_WEEK_RATIO = 0.0 if PLAYER_DESCRIPTION == "Live" else 0.0
+LAST_WEEK_RATIO = 0.0
LAST_TWOWEEKS_RATIO = 0.0
LAST_MONTH_RATIO = 0.0
diff --git a/scripts/supabase_doodling.py b/scripts/supabase_doodling.py
deleted file mode 100644
index 068fa02..0000000
--- a/scripts/supabase_doodling.py
+++ /dev/null
@@ -1,75 +0,0 @@
-from typing import Literal
-import requests
-from exceptions import logger, log_exception
-
-AUTH_TOKEN = {
- "Authorization": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImNucGhwbnV2aGp2cXprY2J3emRrIiwicm9sZSI6InNlcnZpY2Vfcm9sZSIsImlhdCI6MTc0NTgxMTc4NCwiZXhwIjoyMDYxMzg3Nzg0fQ.7dG_y2zU2PajBwTD8vut5GcWf3CSaZePkYW_hMf0fVg",
- "apikey": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImNucGhwbnV2aGp2cXprY2J3emRrIiwicm9sZSI6InNlcnZpY2Vfcm9sZSIsImlhdCI6MTc0NTgxMTc4NCwiZXhwIjoyMDYxMzg3Nzg0fQ.7dG_y2zU2PajBwTD8vut5GcWf3CSaZePkYW_hMf0fVg",
-}
-DB_URL = "https://cnphpnuvhjvqzkcbwzdk.supabase.co/rest/v1"
-
-
-def get_req_url(endpoint: str, params: list = None):
- req_url = f"{DB_URL}/{endpoint}?"
-
- if params:
- other_params = False
- for x in params:
- req_url += f'{"&" if other_params else "?"}{x[0]}={x[1]}'
- other_params = True
-
- return req_url
-
-
-def log_return_value(log_string: str, log_type: Literal["info", "debug"]):
- if log_type == "info":
- logger.info(
- f'return: {log_string[:1200]}{" [ S N I P P E D ]" if len(log_string) > 1200 else ""}\n'
- )
- else:
- logger.debug(
- f'return: {log_string[:1200]}{" [ S N I P P E D ]" if len(log_string) > 1200 else ""}\n'
- )
-
-
-def db_get(
- endpoint: str,
- params: dict = None,
- limit: int = 1000,
- offset: int = 0,
- none_okay: bool = True,
- timeout: int = 3,
-):
- req_url = f"{DB_URL}/{endpoint}?limit={limit}&offset={offset}"
- logger.info(f"HTTP GET: {req_url}, params: {params}")
-
- response = requests.request("GET", req_url, params=params, headers=AUTH_TOKEN)
- logger.info(response)
-
- if response.status_code != requests.codes.ok:
- log_exception(Exception, response.text)
-
- data = response.json()
- if isinstance(data, list) and len(data) == 0:
- if none_okay:
- return None
- else:
- log_exception(Exception, "Query returned no results and none_okay = False")
-
- return data
-
- # async with aiohttp.ClientSession(headers=AUTH_TOKEN) as session:
- # async with session.get(req_url) as r:
- # logger.info(f'session info: {r}')
- # if r.status == 200:
- # js = await r.json()
- # log_return_value(f'{js}')
- # return js
- # elif none_okay:
- # e = await r.text()
- # logger.error(e)
- # return None
- # else:
- # e = await r.text()
- # logger.error(e)
- # raise ValueError(f'DB: {e}')
diff --git a/tests/test_helpers.py b/tests/test_helpers.py
index 875d8ab..83d4268 100644
--- a/tests/test_helpers.py
+++ b/tests/test_helpers.py
@@ -1,10 +1,4 @@
-from creation_helpers import pd_positions_df, mround, sanitize_chance_output
-
-
-def test_positions_df():
- cardset_19_pos = pd_positions_df(19)
-
- assert True == True
+from creation_helpers import mround, sanitize_chance_output
def test_mround():