Standardize formatting with black and apply ruff auto-fixes. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
606 lines
22 KiB
Python
606 lines
22 KiB
Python
"""
|
|
Create custom card for Sphealthamus Sphealy Spheal Sr
|
|
Power hitter vs RHP (singles/HRs), patient hitter vs LHP (walks/singles)
|
|
Extreme pull tendency vs RHP (62%), all-fields vs LHP (28%)
|
|
"""
|
|
|
|
import asyncio
|
|
from custom_cards.archetype_definitions import BatterArchetype
|
|
from custom_cards.archetype_calculator import (
|
|
BatterRatingCalculator,
|
|
calculate_total_ops,
|
|
)
|
|
from creation_helpers import mlbteam_and_franchise
|
|
from db_calls import db_get, db_post, db_put, db_patch
|
|
from datetime import datetime
|
|
import random
|
|
|
|
# AWS Configuration
|
|
AWS_BUCKET_NAME = "paper-dynasty"
|
|
AWS_REGION = "us-east-1"
|
|
S3_BASE_URL = f"https://{AWS_BUCKET_NAME}.s3.{AWS_REGION}.amazonaws.com"
|
|
|
|
|
|
async def create_sphealthamus_spheal():
|
|
"""Create Sphealthamus Sphealy Spheal Sr custom card."""
|
|
|
|
print("=" * 70)
|
|
print("CREATING SPHEALTHAMUS SPHEALY SPHEAL SR")
|
|
print("=" * 70)
|
|
|
|
# Player details
|
|
name_first = "Sphealthamus Sphealy"
|
|
name_last = "Spheal Sr"
|
|
hand = "L" # Left-handed batter
|
|
team_abbrev = "SEA" # Placeholder team
|
|
positions = ["1B"] # First baseman
|
|
|
|
# Get team info
|
|
mlb_team_id, franchise_id = mlbteam_and_franchise(team_abbrev)
|
|
|
|
# Cardset setup - Always use cardset 29 for custom characters
|
|
cardset_id = 29
|
|
cardset = {"id": cardset_id, "name": "Custom Characters"}
|
|
season = 2005
|
|
player_description = "05 Custom"
|
|
print(
|
|
f"✓ Using cardset ID: {cardset['id']} - Player description: '{player_description}'"
|
|
)
|
|
|
|
# Create custom archetype for Sphealthamus Sphealy Spheal Sr
|
|
# Target: Combined OPS = 0.850
|
|
# vs RHP: Power (singles + HRs with 3:2 BP-HR:HR ratio), high pull (62%)
|
|
# vs LHP: Patient (walks + singles), low pull (28%)
|
|
|
|
spheal = BatterArchetype(
|
|
name="Sphealthamus Sphealy Spheal Sr",
|
|
description="Power vs RHP, patience vs LHP, extreme splits",
|
|
# VS RHP: Target OPS = ~0.850 (power profile - singles + HRs)
|
|
avg_vs_r=0.260, # Boosted to hit OPS target
|
|
obp_vs_r=0.340, # Boosted to hit OPS target
|
|
slg_vs_r=0.495, # Boosted to hit OPS target
|
|
bb_pct_vs_r=0.09, # Moderate walks
|
|
k_pct_vs_r=0.24, # Higher strikeouts (power hitter)
|
|
# VS LHP: Target OPS = ~0.830 (patient profile - walks + singles)
|
|
avg_vs_l=0.260, # Boosted to hit OPS target
|
|
obp_vs_l=0.375, # Boosted to hit OPS target
|
|
slg_vs_l=0.420, # Boosted to hit OPS target
|
|
bb_pct_vs_l=0.15, # Very high walks
|
|
k_pct_vs_l=0.20, # Fewer strikeouts
|
|
# Power distribution - high HR rate vs RHP, moderate vs LHP
|
|
hr_per_hit=0.15, # High HR rate
|
|
triple_per_hit=0.00, # NO TRIPLES
|
|
double_per_hit=0.20, # Moderate doubles
|
|
# Batted ball profile
|
|
gb_pct=0.40, # Some ground balls
|
|
fb_pct=0.38, # Lots of fly balls (power)
|
|
ld_pct=0.22, # Line drives
|
|
# Batted ball quality - power hitter
|
|
hard_pct=0.40, # Lots of hard contact
|
|
med_pct=0.42, # Medium contact
|
|
soft_pct=0.18, # Some soft contact
|
|
# Spray chart - EXTREME PULL vs RHP, all-fields vs LHP
|
|
pull_pct=0.45, # Will adjust per split
|
|
center_pct=0.32, # Will adjust per split
|
|
oppo_pct=0.23, # Will adjust per split
|
|
# Infield hits
|
|
ifh_pct=0.04, # Low (slow runner)
|
|
# Specific power metrics
|
|
hr_fb_pct=0.16, # Good HR/FB
|
|
# Baserunning - poor speed
|
|
speed_rating=3, # Poor speed
|
|
steal_jump=5, # Below average
|
|
xbt_pct=0.42, # Below average
|
|
# Situational hitting - poor
|
|
hit_run_skill=3, # Poor hit-and-run
|
|
# Defensive profile
|
|
primary_positions=["1B"],
|
|
defensive_rating=5, # Average defender
|
|
)
|
|
|
|
print(f"\n✓ Created custom archetype: {spheal.name}")
|
|
print(
|
|
f" Base stats vR: {spheal.avg_vs_r:.3f}/{spheal.obp_vs_r:.3f}/{spheal.slg_vs_r:.3f} (OPS: {spheal.obp_vs_r + spheal.slg_vs_r:.3f})"
|
|
)
|
|
print(
|
|
f" Base stats vL: {spheal.avg_vs_l:.3f}/{spheal.obp_vs_l:.3f}/{spheal.slg_vs_l:.3f} (OPS: {spheal.obp_vs_l + spheal.slg_vs_l:.3f})"
|
|
)
|
|
|
|
# Calculate ratings
|
|
calc = BatterRatingCalculator(spheal)
|
|
ratings = calc.calculate_ratings(battingcard_id=0) # Temp ID
|
|
baserunning = calc.calculate_baserunning()
|
|
|
|
# Override steal rate to 0.416666 (18-13)
|
|
print("\n✓ Setting steal rate to 0.416666 (18-13)...")
|
|
baserunning["steal_jump"] = 0.416666
|
|
baserunning["steal_high"] = 18
|
|
baserunning["steal_low"] = 13
|
|
|
|
# Override running to 9
|
|
print("✓ Setting running to 9...")
|
|
baserunning["running"] = 9
|
|
|
|
# Override bunting to D
|
|
print("✓ Setting bunting to D...")
|
|
baserunning["bunting"] = "D"
|
|
|
|
# Override hit-and-run to D
|
|
print("✓ Setting hit-and-run to D...")
|
|
baserunning["hit_and_run"] = "D"
|
|
|
|
# Apply randomization to make results look more natural
|
|
print("\n✓ Applying randomization (±0.5) and rounding to 0.05...")
|
|
random.seed(43) # Different seed for different character
|
|
|
|
for rating in ratings:
|
|
# Fields to randomize
|
|
randomize_fields = [
|
|
"homerun",
|
|
"bp_homerun",
|
|
"triple",
|
|
"double_three",
|
|
"double_two",
|
|
"double_pull",
|
|
"single_two",
|
|
"single_one",
|
|
"single_center",
|
|
"walk",
|
|
"hbp",
|
|
"strikeout",
|
|
"lineout",
|
|
"popout",
|
|
"flyout_a",
|
|
"flyout_bq",
|
|
"flyout_lf_b",
|
|
"flyout_rf_b",
|
|
"groundout_a",
|
|
"groundout_b",
|
|
"groundout_c",
|
|
]
|
|
|
|
for field in randomize_fields:
|
|
if rating[field] > 0:
|
|
randomization = random.uniform(-0.5, 0.5)
|
|
new_value = rating[field] + randomization
|
|
rating[field] = round(new_value * 20) / 20
|
|
rating[field] = max(0.05, rating[field])
|
|
|
|
# Fix BP-HR and HBP to whole numbers, remove triples, adjust pull rates
|
|
print("\n✓ Applying custom adjustments...")
|
|
print(" - Setting BP-HR to whole numbers")
|
|
print(" - Setting HBP to whole numbers")
|
|
print(" - Removing all triples")
|
|
print(" - Adjusting pull rates (62% vR, 28% vL)")
|
|
print(" - Setting BP-HR:HR ratio to 3:2 vs RHP")
|
|
|
|
# vs LHP (ratings[0]) - Patient profile
|
|
old_bphr_vl = ratings[0]["bp_homerun"]
|
|
ratings[0]["bp_homerun"] = 1.0 # Fewer BP-HR vs LHP
|
|
ratings[0]["single_center"] += old_bphr_vl - 1.0
|
|
|
|
old_hbp_vl = ratings[0]["hbp"]
|
|
ratings[0]["hbp"] = 1.0
|
|
ratings[0]["single_center"] += old_hbp_vl - 1.0
|
|
|
|
# Remove triples vL
|
|
old_triple_vl = ratings[0]["triple"]
|
|
ratings[0]["triple"] = 0.0
|
|
ratings[0]["single_center"] += old_triple_vl
|
|
|
|
# Remove Double2 vL and move to Walks
|
|
old_double2_vl = ratings[0]["double_two"]
|
|
ratings[0]["double_two"] = 0.0
|
|
ratings[0]["walk"] += old_double2_vl
|
|
|
|
# Set pull rate to 28% vL
|
|
ratings[0]["pull_rate"] = 0.28
|
|
ratings[0]["center_rate"] = 0.40
|
|
ratings[0]["slap_rate"] = 0.32
|
|
|
|
# vs RHP (ratings[1]) - Power profile
|
|
# Add 2 BP-HR and 1.4 HR
|
|
total_hr_chances = ratings[1]["homerun"] + ratings[1]["bp_homerun"]
|
|
ratings[1]["homerun"] = 3.4 # Add 1.4 HR
|
|
ratings[1]["bp_homerun"] = 5.0 # Add 2 BP-HR
|
|
# Redistribute excess
|
|
excess = total_hr_chances - 8.4
|
|
ratings[1]["single_center"] += excess
|
|
|
|
old_hbp_vr = ratings[1]["hbp"]
|
|
ratings[1]["hbp"] = 1.0
|
|
ratings[1]["single_center"] += old_hbp_vr - 1.0
|
|
|
|
# Remove triples vR
|
|
old_triple_vr = ratings[1]["triple"]
|
|
ratings[1]["triple"] = 0.0
|
|
ratings[1]["single_center"] += old_triple_vr
|
|
|
|
# Remove Double2 vR and move to singles
|
|
old_double2_vr = ratings[1]["double_two"]
|
|
ratings[1]["double_two"] = 0.0
|
|
ratings[1]["single_center"] += old_double2_vr
|
|
|
|
# Remove Flyout LF-B vR and move to strikeouts
|
|
old_flyout_lf_vr = ratings[1]["flyout_lf_b"]
|
|
ratings[1]["flyout_lf_b"] = 0.0
|
|
ratings[1]["strikeout"] += old_flyout_lf_vr
|
|
|
|
# Set pull rate to 62% vR
|
|
ratings[1]["pull_rate"] = 0.62
|
|
ratings[1]["center_rate"] = 0.25
|
|
ratings[1]["slap_rate"] = 0.13
|
|
|
|
# Fix total chances to exactly 108.0
|
|
for rating in ratings:
|
|
total = sum(
|
|
[
|
|
rating["homerun"],
|
|
rating["bp_homerun"],
|
|
rating["triple"],
|
|
rating["double_three"],
|
|
rating["double_two"],
|
|
rating["double_pull"],
|
|
rating["single_two"],
|
|
rating["single_one"],
|
|
rating["single_center"],
|
|
rating["bp_single"],
|
|
rating["walk"],
|
|
rating["hbp"],
|
|
rating["strikeout"],
|
|
rating["lineout"],
|
|
rating["popout"],
|
|
rating["flyout_a"],
|
|
rating["flyout_bq"],
|
|
rating["flyout_lf_b"],
|
|
rating["flyout_rf_b"],
|
|
rating["groundout_a"],
|
|
rating["groundout_b"],
|
|
rating["groundout_c"],
|
|
]
|
|
)
|
|
diff = 108.0 - total
|
|
if abs(diff) > 0.01:
|
|
rating["groundout_b"] += diff
|
|
rating["groundout_b"] = round(rating["groundout_b"] * 20) / 20
|
|
|
|
# Adjust groundout ratios to 4:2:1 (A:B:C)
|
|
print("\n✓ Adjusting groundout ratios to 4:2:1 (A:B:C)...")
|
|
for rating in ratings:
|
|
total_groundouts = (
|
|
rating["groundout_a"] + rating["groundout_b"] + rating["groundout_c"]
|
|
)
|
|
rating["groundout_a"] = round(total_groundouts * (4 / 7) * 20) / 20
|
|
rating["groundout_b"] = round(total_groundouts * (2 / 7) * 20) / 20
|
|
rating["groundout_c"] = round(total_groundouts * (1 / 7) * 20) / 20
|
|
|
|
# Set Flyout A to 1.0 and move removed chances to strikeouts
|
|
print("✓ Setting Flyout A to 1.0 both sides...")
|
|
for rating in ratings:
|
|
old_flyout_a = rating["flyout_a"]
|
|
rating["flyout_a"] = 1.0
|
|
rating["strikeout"] += old_flyout_a - 1.0
|
|
|
|
# Rebalance again after adjustments
|
|
for rating in ratings:
|
|
total = sum(
|
|
[
|
|
rating["homerun"],
|
|
rating["bp_homerun"],
|
|
rating["triple"],
|
|
rating["double_three"],
|
|
rating["double_two"],
|
|
rating["double_pull"],
|
|
rating["single_two"],
|
|
rating["single_one"],
|
|
rating["single_center"],
|
|
rating["bp_single"],
|
|
rating["walk"],
|
|
rating["hbp"],
|
|
rating["strikeout"],
|
|
rating["lineout"],
|
|
rating["popout"],
|
|
rating["flyout_a"],
|
|
rating["flyout_bq"],
|
|
rating["flyout_lf_b"],
|
|
rating["flyout_rf_b"],
|
|
rating["groundout_a"],
|
|
rating["groundout_b"],
|
|
rating["groundout_c"],
|
|
]
|
|
)
|
|
diff = 108.0 - total
|
|
if abs(diff) > 0.01:
|
|
rating["groundout_b"] += diff
|
|
rating["groundout_b"] = round(rating["groundout_b"] * 20) / 20
|
|
|
|
# Recalculate rate stats
|
|
for rating in ratings:
|
|
total_hits = (
|
|
rating["homerun"]
|
|
+ rating["bp_homerun"] * 0.5
|
|
+ rating["triple"]
|
|
+ rating["double_three"]
|
|
+ rating["double_two"]
|
|
+ rating["double_pull"]
|
|
+ rating["single_two"]
|
|
+ rating["single_one"]
|
|
+ rating["single_center"]
|
|
+ rating["bp_single"] * 0.5
|
|
)
|
|
rating["avg"] = round(total_hits / 108, 5)
|
|
rating["obp"] = round((total_hits + rating["hbp"] + rating["walk"]) / 108, 5)
|
|
rating["slg"] = round(
|
|
(
|
|
rating["homerun"] * 4
|
|
+ rating["bp_homerun"] * 2
|
|
+ rating["triple"] * 3
|
|
+ (
|
|
rating["double_two"]
|
|
+ rating["double_three"]
|
|
+ rating["double_pull"]
|
|
)
|
|
* 2
|
|
+ rating["single_center"]
|
|
+ rating["single_two"]
|
|
+ rating["single_one"]
|
|
+ rating["bp_single"]
|
|
)
|
|
/ 108,
|
|
5,
|
|
)
|
|
|
|
# Display adjusted ratings
|
|
print("\n" + "=" * 70)
|
|
print("FINAL RATINGS (TWO-COLUMN TABLE)")
|
|
print("=" * 70)
|
|
|
|
vl = ratings[0]
|
|
vr = ratings[1]
|
|
|
|
print(f"\n{'RATING':<25} {'VS LHP':>12} {'VS RHP':>12}")
|
|
print("-" * 50)
|
|
print(f"{'AVG':<25} {vl['avg']:>12.3f} {vr['avg']:>12.3f}")
|
|
print(f"{'OBP':<25} {vl['obp']:>12.3f} {vr['obp']:>12.3f}")
|
|
print(f"{'SLG':<25} {vl['slg']:>12.3f} {vr['slg']:>12.3f}")
|
|
print(f"{'OPS':<25} {vl['obp']+vl['slg']:>12.3f} {vr['obp']+vr['slg']:>12.3f}")
|
|
print()
|
|
print(f"{'HITS':<25}")
|
|
print(f"{' Homerun':<25} {vl['homerun']:>12.1f} {vr['homerun']:>12.1f}")
|
|
print(f"{' BP Homerun':<25} {vl['bp_homerun']:>12.1f} {vr['bp_homerun']:>12.1f}")
|
|
print(f"{' Triple':<25} {vl['triple']:>12.1f} {vr['triple']:>12.1f}")
|
|
print(
|
|
f"{' Double (3B)':<25} {vl['double_three']:>12.1f} {vr['double_three']:>12.1f}"
|
|
)
|
|
print(f"{' Double (2B)':<25} {vl['double_two']:>12.1f} {vr['double_two']:>12.1f}")
|
|
print(
|
|
f"{' Double (Pull)':<25} {vl['double_pull']:>12.1f} {vr['double_pull']:>12.1f}"
|
|
)
|
|
print(f"{' Single (2B)':<25} {vl['single_two']:>12.1f} {vr['single_two']:>12.1f}")
|
|
print(f"{' Single (1B)':<25} {vl['single_one']:>12.1f} {vr['single_one']:>12.1f}")
|
|
print(
|
|
f"{' Single (Center)':<25} {vl['single_center']:>12.1f} {vr['single_center']:>12.1f}"
|
|
)
|
|
print(f"{' BP Single':<25} {vl['bp_single']:>12.1f} {vr['bp_single']:>12.1f}")
|
|
print()
|
|
print(f"{'ON-BASE':<25}")
|
|
print(f"{' Walk':<25} {vl['walk']:>12.1f} {vr['walk']:>12.1f}")
|
|
print(f"{' HBP':<25} {vl['hbp']:>12.1f} {vr['hbp']:>12.1f}")
|
|
print()
|
|
print(f"{'SPRAY CHART':<25}")
|
|
print(f"{' Pull %':<25} {vl['pull_rate']:>11.1%} {vr['pull_rate']:>11.1%}")
|
|
print(f"{' Center %':<25} {vl['center_rate']:>11.1%} {vr['center_rate']:>11.1%}")
|
|
print(f"{' Opposite %':<25} {vl['slap_rate']:>11.1%} {vr['slap_rate']:>11.1%}")
|
|
print()
|
|
|
|
# Calculate and display total OPS
|
|
total_ops = calculate_total_ops(ratings[0], ratings[1], is_pitcher=False)
|
|
print(f"\nTotal OPS: {total_ops:.3f} (Target: 0.850)")
|
|
|
|
print("\nBaserunning:")
|
|
print(
|
|
f" Steal: {baserunning['steal_low']}-{baserunning['steal_high']} (Jump: {baserunning['steal_jump']})"
|
|
)
|
|
print(
|
|
f" Running: {baserunning['running']} Hit-and-Run: {baserunning['hit_and_run']} Bunting: {baserunning['bunting']}"
|
|
)
|
|
|
|
# Summary
|
|
print("\n" + "=" * 70)
|
|
print("SUMMARY")
|
|
print("=" * 70)
|
|
print(f"\nPlayer: Sphealthamus Sphealy Spheal Sr ({hand})")
|
|
print("Position: 1B (Range 5, Error 3)")
|
|
print("Cardset: 29 (Custom Characters)")
|
|
print("Description: 05 Custom")
|
|
print(f"Total OPS: {total_ops:.3f} / 0.850 target")
|
|
print(
|
|
f"Pull Rate: {vl['pull_rate']*100:.0f}% vL / {vr['pull_rate']*100:.0f}% vR (Target: 28% vL, 62% vR)"
|
|
)
|
|
print(
|
|
f"BP-HR:HR ratio vR: {vr['bp_homerun']:.0f}:{vr['homerun']:.0f} (Target: 3:2)"
|
|
)
|
|
|
|
print("\n" + "=" * 70)
|
|
print("DATABASE CREATION")
|
|
print("=" * 70)
|
|
|
|
# Create database records
|
|
bbref_id = f"custom_{name_last.lower().replace(' ', '')}{name_first[0].lower()}01"
|
|
|
|
# Step 1: Create/verify MLBPlayer record
|
|
print("\n✓ Checking for existing MLBPlayer record...")
|
|
mlb_query = await db_get(
|
|
"mlbplayers", params=[("first_name", name_first), ("last_name", name_last)]
|
|
)
|
|
if mlb_query and mlb_query.get("count", 0) > 0:
|
|
mlbplayer_id = mlb_query["players"][0]["id"]
|
|
print(f" Using existing MLBPlayer ID: {mlbplayer_id}")
|
|
else:
|
|
try:
|
|
mlbplayer_payload = {
|
|
"key_bbref": bbref_id,
|
|
"key_fangraphs": 0,
|
|
"key_mlbam": 0,
|
|
"key_retro": "",
|
|
"first_name": name_first,
|
|
"last_name": name_last,
|
|
}
|
|
new_mlbplayer = await db_post("mlbplayers/one", payload=mlbplayer_payload)
|
|
mlbplayer_id = new_mlbplayer["id"]
|
|
print(f" Created MLBPlayer ID: {mlbplayer_id}")
|
|
except ValueError as e:
|
|
print(f" MLBPlayer creation failed: {e}")
|
|
print(" Proceeding without MLBPlayer linkage...")
|
|
mlbplayer_id = None
|
|
|
|
# Step 2: Create or update Player record
|
|
print("\n✓ Checking for existing Player record...")
|
|
now = datetime.now()
|
|
release_date = f"{now.year}-{now.month}-{now.day}"
|
|
|
|
p_query = await db_get(
|
|
"players", params=[("bbref_id", bbref_id), ("cardset_id", cardset["id"])]
|
|
)
|
|
if p_query and p_query.get("count", 0) > 0:
|
|
player_id = p_query["players"][0]["player_id"]
|
|
print(f" Using existing Player ID: {player_id}")
|
|
image_url = f"https://pd.manticorum.com/api/v2/players/{player_id}/battingcard?d={release_date}"
|
|
await db_patch("players", object_id=player_id, params=[("image", image_url)])
|
|
print(" Updated image URL")
|
|
else:
|
|
print(" Creating new Player record...")
|
|
temp_image_url = (
|
|
f"https://pd.manticorum.com/api/v2/players/0/battingcard?d={release_date}"
|
|
)
|
|
|
|
player_payload = {
|
|
"p_name": f"{name_first} {name_last}",
|
|
"bbref_id": bbref_id,
|
|
"fangr_id": 0,
|
|
"strat_code": 0,
|
|
"hand": hand,
|
|
"mlbclub": "Custom Ballplayers",
|
|
"franchise": "Custom Ballplayers",
|
|
"cardset_id": cardset["id"],
|
|
"description": player_description,
|
|
"is_custom": True,
|
|
"cost": 100,
|
|
"rarity_id": 5,
|
|
"image": temp_image_url,
|
|
"set_num": 9999,
|
|
"pos_1": "1B",
|
|
}
|
|
|
|
if mlbplayer_id:
|
|
player_payload["mlbplayer_id"] = mlbplayer_id
|
|
|
|
new_player = await db_post("players", payload=player_payload)
|
|
player_id = new_player["player_id"]
|
|
print(f" Created Player ID: {player_id}")
|
|
|
|
image_url = f"https://pd.manticorum.com/api/v2/players/{player_id}/battingcard?d={release_date}"
|
|
await db_patch("players", object_id=player_id, params=[("image", image_url)])
|
|
print(" Updated with correct image URL")
|
|
|
|
# Step 3: Create BattingCard
|
|
print("\n✓ Creating BattingCard...")
|
|
batting_card_payload = {
|
|
"cards": [
|
|
{
|
|
"player_id": player_id,
|
|
"key_bbref": bbref_id,
|
|
"key_fangraphs": 0,
|
|
"key_mlbam": 0,
|
|
"key_retro": "",
|
|
"name_first": name_first,
|
|
"name_last": name_last,
|
|
"steal_low": baserunning["steal_low"],
|
|
"steal_high": baserunning["steal_high"],
|
|
"steal_auto": baserunning["steal_auto"],
|
|
"steal_jump": baserunning["steal_jump"],
|
|
"hit_and_run": baserunning["hit_and_run"],
|
|
"running": baserunning["running"],
|
|
"hand": hand,
|
|
"bunting": baserunning["bunting"],
|
|
}
|
|
]
|
|
}
|
|
|
|
await db_put("battingcards", payload=batting_card_payload, timeout=10)
|
|
print(" BattingCard created")
|
|
|
|
bc_query = await db_get("battingcards", params=[("player_id", player_id)])
|
|
battingcard_id = bc_query["cards"][0]["id"]
|
|
print(f" BattingCard ID: {battingcard_id}")
|
|
|
|
# Step 4: Create BattingCardRatings
|
|
print("\n✓ Creating BattingCardRatings...")
|
|
for rating in ratings:
|
|
rating["battingcard_id"] = battingcard_id
|
|
|
|
ratings_payload = {"ratings": ratings}
|
|
await db_put("battingcardratings", payload=ratings_payload, timeout=10)
|
|
print(" Ratings created (vL and vR)")
|
|
|
|
# Step 5: Create CardPositions
|
|
print("\n✓ Creating CardPosition (1B)...")
|
|
positions_payload = {
|
|
"positions": [
|
|
{
|
|
"player_id": player_id,
|
|
"variant": 0,
|
|
"position": "1B",
|
|
"innings": 1,
|
|
"range": 5,
|
|
"error": 3,
|
|
}
|
|
]
|
|
}
|
|
|
|
await db_put("cardpositions", payload=positions_payload, timeout=10)
|
|
print(" Position created: 1B (Range 5, Error 3)")
|
|
|
|
# Step 6: Update rarity and cost
|
|
print("\n✓ Updating rarity and cost...")
|
|
target_rarity_id = 3 # Starter
|
|
target_cost = 188
|
|
|
|
await db_patch(
|
|
"players", object_id=player_id, params=[("rarity_id", target_rarity_id)]
|
|
)
|
|
await db_patch("players", object_id=player_id, params=[("cost", target_cost)])
|
|
print(" Rarity set to: Starter (ID 3)")
|
|
print(f" Cost set to: {target_cost}")
|
|
|
|
# Step 7: Skip image generation for now
|
|
print("\n✓ Skipping card image generation and S3 upload (will do after review)...")
|
|
api_image_url = f"https://pd.manticorum.com/api/v2/players/{player_id}/battingcard?d={release_date}"
|
|
s3_url = f"https://{AWS_BUCKET_NAME}.s3.{AWS_REGION}.amazonaws.com/cards/cardset-{cardset['id']:03d}/player-{player_id}/battingcard.png?d={release_date}"
|
|
print(f" Card preview URL: {api_image_url}")
|
|
print(f" Future S3 URL: {s3_url}")
|
|
|
|
print("\n" + "=" * 70)
|
|
print("✅ SUCCESS!")
|
|
print("=" * 70)
|
|
print("\nSphealthamus Sphealy Spheal Sr created successfully!")
|
|
print(f" Player ID: {player_id}")
|
|
print(f" BattingCard ID: {battingcard_id}")
|
|
print(" Position: 1B (Range 5, Error 3)")
|
|
print(" Bunting: D Hit-and-Run: D")
|
|
print(f" Running: {baserunning['running']}")
|
|
print(
|
|
f" Stealing: {baserunning['steal_low']}-{baserunning['steal_high']} ({baserunning['steal_jump']})"
|
|
)
|
|
print(f" Pull Rates: {vl['pull_rate']*100:.0f}% vL, {vr['pull_rate']*100:.0f}% vR")
|
|
print(" Rarity: Starter")
|
|
print(f" Cost: {target_cost}")
|
|
print(f" Total OPS: {total_ops:.3f}")
|
|
print(f"\n Card Preview URL: {api_image_url}")
|
|
print(" (Image not yet uploaded to S3 - awaiting review)")
|
|
print("\n" + "=" * 70)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
asyncio.run(create_sphealthamus_spheal())
|