Standardize formatting with black and apply ruff auto-fixes. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
360 lines
11 KiB
Python
360 lines
11 KiB
Python
"""
|
|
Submit Tony Smehrik to Paper Dynasty Database
|
|
|
|
Custom pitcher with:
|
|
- Hand: Left
|
|
- Position: SP/RP (starter_rating: 5, relief_rating: 5)
|
|
- Combined OPS: 0.585
|
|
- OPS vs L: 0.465 (dominant same-side)
|
|
- OPS vs R: 0.645 (weaker opposite-side)
|
|
- K-rate vs L: ~20% (average)
|
|
- K-rate vs R: ~8% (very low)
|
|
- FB% vs L: ~44% (average)
|
|
- FB% vs R: ~56% (high)
|
|
- Team: Custom Ballplayers
|
|
- Cardset ID: 29
|
|
|
|
NO AWS UPLOAD - preview via PD API first
|
|
"""
|
|
|
|
import asyncio
|
|
from datetime import datetime
|
|
from db_calls import db_get, db_post, db_patch, db_put
|
|
from custom_cards.tony_smehrik_preview import calculate_pitcher_rating
|
|
|
|
# Configuration
|
|
CARDSET_ID = 29
|
|
CARDSET_NAME = "2005 Custom"
|
|
SEASON = 2005
|
|
PLAYER_DESCRIPTION = "2005 Custom"
|
|
|
|
# Player info
|
|
PLAYER_NAME_FIRST = "Tony"
|
|
PLAYER_NAME_LAST = "Smehrik"
|
|
HAND = "L"
|
|
STARTER_RATING = 5
|
|
RELIEF_RATING = 5
|
|
CLOSER_RATING = None
|
|
|
|
|
|
async def main():
|
|
"""Create Tony Smehrik pitcher card in database."""
|
|
|
|
print("\n" + "=" * 70)
|
|
print("SUBMITTING TONY SMEHRIK TO DATABASE")
|
|
print("=" * 70)
|
|
|
|
# Step 1: Calculate ratings (same as preview)
|
|
print("\nCalculating ratings...")
|
|
pit_hand = "L"
|
|
|
|
vl = calculate_pitcher_rating(
|
|
vs_hand="L",
|
|
pit_hand=pit_hand,
|
|
avg=0.185,
|
|
obp=0.240,
|
|
slg=0.225,
|
|
bb_pct=0.055,
|
|
k_pct=0.20,
|
|
hr_per_hit=0.04,
|
|
triple_per_hit=0.02,
|
|
double_per_hit=0.22,
|
|
fb_pct=0.35,
|
|
gb_pct=0.45,
|
|
hard_pct=0.30,
|
|
med_pct=0.50,
|
|
soft_pct=0.20,
|
|
oppo_pct=0.26,
|
|
hr_fb_pct=0.06,
|
|
)
|
|
|
|
vr = calculate_pitcher_rating(
|
|
vs_hand="R",
|
|
pit_hand=pit_hand,
|
|
avg=0.245,
|
|
obp=0.305,
|
|
slg=0.340,
|
|
bb_pct=0.075,
|
|
k_pct=0.08,
|
|
hr_per_hit=0.07,
|
|
triple_per_hit=0.02,
|
|
double_per_hit=0.24,
|
|
fb_pct=0.45,
|
|
gb_pct=0.35,
|
|
hard_pct=0.34,
|
|
med_pct=0.46,
|
|
soft_pct=0.20,
|
|
oppo_pct=0.26,
|
|
hr_fb_pct=0.09,
|
|
)
|
|
|
|
# Apply same manual adjustments as preview
|
|
# HR adjustments: half of all OB chances go to HR
|
|
vl_total_hits = (
|
|
vl["homerun"]
|
|
+ vl["bp_homerun"]
|
|
+ vl["triple"]
|
|
+ vl["double_three"]
|
|
+ vl["double_two"]
|
|
+ vl["double_cf"]
|
|
+ vl["single_two"]
|
|
+ vl["single_one"]
|
|
+ vl["single_center"]
|
|
+ vl["bp_single"]
|
|
)
|
|
vl_total_ob = vl_total_hits + vl["walk"] + vl["hbp"]
|
|
vl_hr_total = vl_total_ob / 2
|
|
vl["bp_homerun"] = round(vl_hr_total / 2)
|
|
vl["homerun"] = round((vl_hr_total - vl["bp_homerun"]) * 20) / 20
|
|
vl["hbp"] = 1.0
|
|
|
|
vr_total_hits = (
|
|
vr["homerun"]
|
|
+ vr["bp_homerun"]
|
|
+ vr["triple"]
|
|
+ vr["double_three"]
|
|
+ vr["double_two"]
|
|
+ vr["double_cf"]
|
|
+ vr["single_two"]
|
|
+ vr["single_one"]
|
|
+ vr["single_center"]
|
|
+ vr["bp_single"]
|
|
)
|
|
vr_total_ob = vr_total_hits + vr["walk"] + vr["hbp"]
|
|
vr_hr_total = vr_total_ob / 2
|
|
vr["bp_homerun"] = round(vr_hr_total / 2)
|
|
vr["homerun"] = round((vr_hr_total - vr["bp_homerun"]) * 20) / 20
|
|
vr["hbp"] = 1.0
|
|
|
|
# Reduce singles to compensate for HR increase
|
|
vl_new_hr_total = vl["homerun"] + vl["bp_homerun"]
|
|
vl_hr_increase = vl_new_hr_total
|
|
vl_singles_to_reduce = vl_hr_increase
|
|
reduce_from_one = min(vl["single_one"], vl_singles_to_reduce)
|
|
vl["single_one"] -= reduce_from_one
|
|
vl_singles_to_reduce -= reduce_from_one
|
|
reduce_from_two = min(vl["single_two"], vl_singles_to_reduce)
|
|
vl["single_two"] -= reduce_from_two
|
|
vl_singles_to_reduce -= reduce_from_two
|
|
reduce_from_bp = min(vl["bp_single"], vl_singles_to_reduce)
|
|
vl["bp_single"] -= reduce_from_bp
|
|
vl_singles_to_reduce -= reduce_from_bp
|
|
if vl_singles_to_reduce > 0:
|
|
vl["double_cf"] = max(0, vl["double_cf"] - vl_singles_to_reduce)
|
|
|
|
vr_new_hr_total = vr["homerun"] + vr["bp_homerun"]
|
|
vr_old_hr_total = 0.80 + 1.00
|
|
vr_hr_increase = vr_new_hr_total - vr_old_hr_total
|
|
vr_singles_to_reduce = vr_hr_increase
|
|
reduce_from_one = min(vr["single_one"], vr_singles_to_reduce)
|
|
vr["single_one"] -= reduce_from_one
|
|
vr_singles_to_reduce -= reduce_from_one
|
|
reduce_from_two = min(vr["single_two"], vr_singles_to_reduce)
|
|
vr["single_two"] -= reduce_from_two
|
|
vr_singles_to_reduce -= reduce_from_two
|
|
reduce_from_bp = min(vr["bp_single"], vr_singles_to_reduce)
|
|
vr["bp_single"] -= reduce_from_bp
|
|
vr_singles_to_reduce -= reduce_from_bp
|
|
if vr_singles_to_reduce > 0:
|
|
vr["double_cf"] = max(0, vr["double_cf"] - vr_singles_to_reduce)
|
|
|
|
# Force BP-SI values
|
|
vl["bp_single"] = 5.0
|
|
vr["bp_single"] = 3.0
|
|
|
|
# Adjust strikeouts to hit 108
|
|
for rating in [vl, vr]:
|
|
total = sum(
|
|
[
|
|
rating["homerun"],
|
|
rating["bp_homerun"],
|
|
rating["triple"],
|
|
rating["double_three"],
|
|
rating["double_two"],
|
|
rating["double_cf"],
|
|
rating["single_two"],
|
|
rating["single_one"],
|
|
rating["single_center"],
|
|
rating["bp_single"],
|
|
rating["hbp"],
|
|
rating["walk"],
|
|
rating["strikeout"],
|
|
rating["flyout_lf_b"],
|
|
rating["flyout_cf_b"],
|
|
rating["flyout_rf_b"],
|
|
rating["groundout_a"],
|
|
rating["groundout_b"],
|
|
rating["xcheck_p"],
|
|
rating["xcheck_c"],
|
|
rating["xcheck_1b"],
|
|
rating["xcheck_2b"],
|
|
rating["xcheck_3b"],
|
|
rating["xcheck_ss"],
|
|
rating["xcheck_lf"],
|
|
rating["xcheck_cf"],
|
|
rating["xcheck_rf"],
|
|
]
|
|
)
|
|
diff = 108 - total
|
|
rating["strikeout"] = round((rating["strikeout"] + diff) * 20) / 20
|
|
|
|
# Calculate OPS for verification
|
|
ops_vl = vl["obp"] + vl["slg"]
|
|
ops_vr = vr["obp"] + vr["slg"]
|
|
combined_ops = (ops_vr + ops_vl + max(ops_vl, ops_vr)) / 3
|
|
|
|
print(f" OPS vs L: {ops_vl:.3f}")
|
|
print(f" OPS vs R: {ops_vr:.3f}")
|
|
print(f" Combined OPS: {combined_ops:.3f}")
|
|
|
|
# Step 2: Verify cardset exists
|
|
print(f"\nVerifying cardset '{CARDSET_NAME}' (ID: {CARDSET_ID})...")
|
|
c_query = await db_get("cardsets", params=[("id", CARDSET_ID)])
|
|
if c_query["count"] == 0:
|
|
print(f" ERROR: Cardset ID {CARDSET_ID} not found!")
|
|
return
|
|
print(" ✓ Cardset verified")
|
|
|
|
# Step 3: Create Player record
|
|
print("\nCreating Player record...")
|
|
now = datetime.now()
|
|
release_date = f"{now.year}-{now.month}-{now.day}"
|
|
bbref_id = f"custom_{PLAYER_NAME_LAST.lower()}{PLAYER_NAME_FIRST[0].lower()}01"
|
|
|
|
player_payload = {
|
|
"p_name": f"{PLAYER_NAME_FIRST} {PLAYER_NAME_LAST}",
|
|
"cost": "100", # Default cost
|
|
"image": "change-me",
|
|
"mlbclub": "Custom Ballplayers",
|
|
"franchise": "Custom Ballplayers",
|
|
"cardset_id": CARDSET_ID,
|
|
"set_num": 99999,
|
|
"rarity_id": 3, # Starter rarity
|
|
"pos_1": "SP",
|
|
"pos_2": "RP",
|
|
"description": PLAYER_DESCRIPTION,
|
|
"bbref_id": bbref_id,
|
|
"fangr_id": 0,
|
|
"mlbplayer_id": None,
|
|
"is_custom": True,
|
|
}
|
|
|
|
player = await db_post("players", payload=player_payload)
|
|
player_id = player["player_id"]
|
|
print(f" ✓ Created Player ID: {player_id}")
|
|
|
|
# Update player with API image URL for preview
|
|
api_image_url = f"https://pd.manticorum.com/api/v2/players/{player_id}/pitchingcard?d={release_date}"
|
|
await db_patch("players", object_id=player_id, params=[("image", api_image_url)])
|
|
print(" ✓ Updated Player with API image URL")
|
|
|
|
# Step 4: Create PitchingCard
|
|
print("\nCreating PitchingCard...")
|
|
pitching_card_payload = {
|
|
"cards": [
|
|
{
|
|
"player_id": player_id,
|
|
"key_bbref": bbref_id,
|
|
"key_fangraphs": 0,
|
|
"key_mlbam": 0,
|
|
"key_retro": "",
|
|
"name_first": PLAYER_NAME_FIRST,
|
|
"name_last": PLAYER_NAME_LAST,
|
|
"hand": HAND,
|
|
"starter_rating": STARTER_RATING,
|
|
"relief_rating": RELIEF_RATING,
|
|
"closer_rating": CLOSER_RATING,
|
|
}
|
|
]
|
|
}
|
|
|
|
await db_put("pitchingcards", payload=pitching_card_payload, timeout=10)
|
|
|
|
# Get the created card ID
|
|
pc_query = await db_get("pitchingcards", params=[("player_id", player_id)])
|
|
pitchingcard_id = pc_query["cards"][0]["id"]
|
|
print(f" ✓ Created PitchingCard ID: {pitchingcard_id}")
|
|
|
|
# Step 5: Create PitchingCardRatings
|
|
print("\nCreating PitchingCardRatings...")
|
|
|
|
# Build ratings payload (remove display-only fields)
|
|
def build_rating_payload(rating, pitchingcard_id):
|
|
return {
|
|
"pitchingcard_id": pitchingcard_id,
|
|
"vs_hand": rating["vs_hand"],
|
|
"homerun": rating["homerun"],
|
|
"bp_homerun": rating["bp_homerun"],
|
|
"triple": rating["triple"],
|
|
"double_three": rating["double_three"],
|
|
"double_two": rating["double_two"],
|
|
"double_cf": rating["double_cf"],
|
|
"single_two": rating["single_two"],
|
|
"single_one": rating["single_one"],
|
|
"single_center": rating["single_center"],
|
|
"bp_single": rating["bp_single"],
|
|
"hbp": rating["hbp"],
|
|
"walk": rating["walk"],
|
|
"strikeout": rating["strikeout"],
|
|
"flyout_lf_b": rating["flyout_lf_b"],
|
|
"flyout_cf_b": rating["flyout_cf_b"],
|
|
"flyout_rf_b": rating["flyout_rf_b"],
|
|
"groundout_a": rating["groundout_a"],
|
|
"groundout_b": rating["groundout_b"],
|
|
"xcheck_p": rating["xcheck_p"],
|
|
"xcheck_c": rating["xcheck_c"],
|
|
"xcheck_1b": rating["xcheck_1b"],
|
|
"xcheck_2b": rating["xcheck_2b"],
|
|
"xcheck_3b": rating["xcheck_3b"],
|
|
"xcheck_ss": rating["xcheck_ss"],
|
|
"xcheck_lf": rating["xcheck_lf"],
|
|
"xcheck_cf": rating["xcheck_cf"],
|
|
"xcheck_rf": rating["xcheck_rf"],
|
|
}
|
|
|
|
ratings_payload = {
|
|
"ratings": [
|
|
build_rating_payload(vl, pitchingcard_id),
|
|
build_rating_payload(vr, pitchingcard_id),
|
|
]
|
|
}
|
|
|
|
await db_put("pitchingcardratings", payload=ratings_payload, timeout=10)
|
|
print(" ✓ Created ratings for vs L and vs R")
|
|
|
|
# Step 6: Create CardPositions
|
|
print("\nCreating CardPositions...")
|
|
positions_payload = {
|
|
"positions": [
|
|
{
|
|
"player_id": player_id,
|
|
"position": "P",
|
|
}
|
|
]
|
|
}
|
|
|
|
await db_put("cardpositions", payload=positions_payload, timeout=10)
|
|
print(" ✓ Created position record: P")
|
|
|
|
# Summary
|
|
print("\n" + "=" * 70)
|
|
print("✓ TONY SMEHRIK CREATED SUCCESSFULLY!")
|
|
print("=" * 70)
|
|
print(f"\nPlayer ID: {player_id}")
|
|
print(f"PitchingCard ID: {pitchingcard_id}")
|
|
print(f"Cardset: {CARDSET_NAME} (ID: {CARDSET_ID})")
|
|
print(f"Hand: {HAND}")
|
|
print(f"Starter Rating: {STARTER_RATING} | Relief Rating: {RELIEF_RATING}")
|
|
print("\nOffensive Profile (OPS Against):")
|
|
print(f" vs LHB: .185/.240/.225 ({ops_vl:.3f} OPS)")
|
|
print(f" vs RHB: .245/.305/.340 ({ops_vr:.3f} OPS)")
|
|
print(f" Combined: {combined_ops:.3f}")
|
|
print("\nPreview card (NO S3 upload yet):")
|
|
print(f" PNG: {api_image_url}")
|
|
print(f" HTML: {api_image_url}&html=true")
|
|
print("")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
asyncio.run(main())
|