- Add Sippie Swartzel custom batter profile (0.820 OPS, SS/RF, no HR power) - Update Kalin Young profile (0.891 OPS, All-Star rarity) - Update Admiral Ball Traits profile with innings field - Fix S3 cache-busting to include Unix timestamp for same-day updates - Add pd_cards/core/upload.py and scouting.py modules - Add custom card submission scripts and documentation - Add uv.lock for dependency tracking
204 lines
6.2 KiB
Python
204 lines
6.2 KiB
Python
"""
|
|
Submit Kalin Young updates to Paper Dynasty Database
|
|
|
|
Updates:
|
|
- BattingCardRatings: +1.55 walks/singles, -3.10 strikeouts (both splits)
|
|
- CardPositions: RF Range 2/Error 6, LF Range 4/Error 6
|
|
- Target OPS: 0.880 (from 0.837)
|
|
|
|
Does NOT upload to AWS - user will review first.
|
|
"""
|
|
|
|
import asyncio
|
|
from db_calls import db_get, db_put, db_patch
|
|
from datetime import datetime
|
|
|
|
# Player info
|
|
PLAYER_ID = 13009
|
|
BATTINGCARD_ID = 6072
|
|
CARDSET_ID = 29
|
|
|
|
# New ratings (from kalin_young_preview.py)
|
|
NEW_RATINGS = {
|
|
'L': { # vs LHP
|
|
'battingcard_id': BATTINGCARD_ID,
|
|
'vs_hand': 'L',
|
|
'homerun': 2.05,
|
|
'bp_homerun': 2.00,
|
|
'triple': 0.00,
|
|
'double_three': 0.00,
|
|
'double_two': 6.00,
|
|
'double_pull': 2.35,
|
|
'single_two': 5.05,
|
|
'single_one': 5.10,
|
|
'single_center': 5.80, # +1.55
|
|
'bp_single': 5.00,
|
|
'walk': 16.05, # +1.55
|
|
'hbp': 1.00,
|
|
'strikeout': 15.40, # -3.10
|
|
'lineout': 15.00,
|
|
'popout': 0.00,
|
|
'flyout_a': 0.00,
|
|
'flyout_bq': 0.75,
|
|
'flyout_lf_b': 3.65,
|
|
'flyout_rf_b': 3.95,
|
|
'groundout_a': 3.95,
|
|
'groundout_b': 10.00,
|
|
'groundout_c': 4.90,
|
|
'pull_rate': 0.33,
|
|
'center_rate': 0.37,
|
|
'slap_rate': 0.30,
|
|
},
|
|
'R': { # vs RHP
|
|
'battingcard_id': BATTINGCARD_ID,
|
|
'vs_hand': 'R',
|
|
'homerun': 2.10,
|
|
'bp_homerun': 1.00,
|
|
'triple': 1.25,
|
|
'double_three': 0.00,
|
|
'double_two': 6.35,
|
|
'double_pull': 1.80,
|
|
'single_two': 5.40,
|
|
'single_one': 4.95,
|
|
'single_center': 6.05, # +1.55
|
|
'bp_single': 5.00,
|
|
'walk': 14.55, # +1.55
|
|
'hbp': 2.00,
|
|
'strikeout': 17.90, # -3.10
|
|
'lineout': 12.00,
|
|
'popout': 1.00,
|
|
'flyout_a': 0.00,
|
|
'flyout_bq': 0.50,
|
|
'flyout_lf_b': 4.10,
|
|
'flyout_rf_b': 4.00,
|
|
'groundout_a': 4.00,
|
|
'groundout_b': 5.00,
|
|
'groundout_c': 9.05,
|
|
'pull_rate': 0.25,
|
|
'center_rate': 0.40,
|
|
'slap_rate': 0.35,
|
|
}
|
|
}
|
|
|
|
# New defensive positions
|
|
NEW_POSITIONS = [
|
|
{
|
|
'player_id': PLAYER_ID,
|
|
'position': 'RF',
|
|
'range': 2, # was 3
|
|
'error': 6, # was 7
|
|
'arm': 0,
|
|
'fielding_pct': None
|
|
},
|
|
{
|
|
'player_id': PLAYER_ID,
|
|
'position': 'LF',
|
|
'range': 4,
|
|
'error': 6, # was 7
|
|
'arm': 0,
|
|
'fielding_pct': None
|
|
}
|
|
]
|
|
|
|
|
|
def calc_ops(r):
|
|
"""Calculate OPS from ratings dict."""
|
|
avg = (r['homerun'] + r['bp_homerun']/2 + r['triple'] + r['double_three'] +
|
|
r['double_two'] + r['double_pull'] + r['single_two'] + r['single_one'] +
|
|
r['single_center'] + r['bp_single']/2) / 108
|
|
obp = avg + (r['hbp'] + r['walk']) / 108
|
|
slg = (r['homerun']*4 + r['bp_homerun']*2 + r['triple']*3 +
|
|
(r['double_three'] + r['double_two'] + r['double_pull'])*2 +
|
|
r['single_two'] + r['single_one'] + r['single_center'] + r['bp_single']/2) / 108
|
|
return obp + slg
|
|
|
|
|
|
def verify_total(r):
|
|
"""Verify ratings sum to 108."""
|
|
return sum([
|
|
r['homerun'], r['bp_homerun'], r['triple'],
|
|
r['double_three'], r['double_two'], r['double_pull'],
|
|
r['single_two'], r['single_one'], r['single_center'], r['bp_single'],
|
|
r['walk'], r['hbp'], r['strikeout'],
|
|
r['lineout'], r['popout'],
|
|
r['flyout_a'], r['flyout_bq'], r['flyout_lf_b'], r['flyout_rf_b'],
|
|
r['groundout_a'], r['groundout_b'], r['groundout_c']
|
|
])
|
|
|
|
|
|
async def main():
|
|
"""Update Kalin Young's batting card ratings and defensive positions."""
|
|
|
|
print("\n" + "="*70)
|
|
print("UPDATING KALIN YOUNG IN DATABASE")
|
|
print("="*70)
|
|
print(f"\nPlayer ID: {PLAYER_ID}")
|
|
print(f"BattingCard ID: {BATTINGCARD_ID}")
|
|
|
|
# Verify totals
|
|
print("\nVerifying ratings totals...")
|
|
for hand, ratings in NEW_RATINGS.items():
|
|
total = verify_total(ratings)
|
|
ops = calc_ops(ratings)
|
|
print(f" vs {hand}HP: Total={total:.2f}, OPS={ops:.3f}")
|
|
if abs(total - 108.0) > 0.01:
|
|
print(f" ⚠ WARNING: Total is not 108!")
|
|
return
|
|
|
|
# Calculate combined OPS
|
|
ops_vl = calc_ops(NEW_RATINGS['L'])
|
|
ops_vr = calc_ops(NEW_RATINGS['R'])
|
|
total_ops = (ops_vl + ops_vr + min(ops_vl, ops_vr)) / 3
|
|
print(f" Combined OPS: {total_ops:.3f}")
|
|
|
|
# Step 1: Update BattingCardRatings
|
|
print("\nUpdating BattingCardRatings...")
|
|
ratings_list = [NEW_RATINGS['L'], NEW_RATINGS['R']]
|
|
ratings_payload = {'ratings': ratings_list}
|
|
|
|
try:
|
|
result = await db_put('battingcardratings', payload=ratings_payload, timeout=10)
|
|
print(f" ✓ Updated ratings: {result}")
|
|
except Exception as e:
|
|
print(f" ✗ Error updating ratings: {e}")
|
|
return
|
|
|
|
# Step 2: Update CardPositions
|
|
print("\nUpdating CardPositions...")
|
|
positions_payload = {'positions': NEW_POSITIONS}
|
|
|
|
try:
|
|
result = await db_put('cardpositions', payload=positions_payload, timeout=10)
|
|
print(f" ✓ Updated positions: {result}")
|
|
except Exception as e:
|
|
print(f" ✗ Error updating positions: {e}")
|
|
return
|
|
|
|
# Summary
|
|
print("\n" + "="*70)
|
|
print("✓ KALIN YOUNG UPDATED SUCCESSFULLY!")
|
|
print("="*70)
|
|
print(f"\nPlayer ID: {PLAYER_ID}")
|
|
print(f"Cardset: 2005 Custom (ID: {CARDSET_ID})")
|
|
print(f"\nRating Changes:")
|
|
print(f" Walk vL: 14.50 → 16.05 (+1.55)")
|
|
print(f" Walk vR: 13.00 → 14.55 (+1.55)")
|
|
print(f" Single (Center) vL: 4.25 → 5.80 (+1.55)")
|
|
print(f" Single (Center) vR: 4.50 → 6.05 (+1.55)")
|
|
print(f" Strikeout vL: 18.50 → 15.40 (-3.10)")
|
|
print(f" Strikeout vR: 21.00 → 17.90 (-3.10)")
|
|
print(f"\nOPS: 0.837 → {total_ops:.3f}")
|
|
print(f"\nDefensive Updates:")
|
|
print(f" RF: Range 3→2, Error 7→6, Arm 0")
|
|
print(f" LF: Range 4, Error 7→6, Arm 0")
|
|
print(f"\n⚠️ AWS upload skipped - review card first:")
|
|
now = datetime.now()
|
|
release_date = f"{now.year}-{now.month}-{now.day}"
|
|
print(f" PNG: https://pd.manticorum.com/api/v2/players/{PLAYER_ID}/battingcard?d={release_date}")
|
|
print(f" HTML: https://pd.manticorum.com/api/v2/players/{PLAYER_ID}/battingcard?d={release_date}&html=true")
|
|
print("")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
asyncio.run(main())
|