paper-dynasty-card-creation/regenerate_lefty_cards.py
Cal Corum cc5f93eb66 Fix critical asterisk regression in player names
CRITICAL BUG FIX: Removed code that was appending asterisks to left-handed
players' names and hash symbols to switch hitters' names in production.

## Changes

### Core Fix (retrosheet_data.py)
- Removed name_suffix code from new_player_payload() (lines 1103-1108)
- Players names now stored cleanly without visual indicators
- Affected 20 left-handed batters in 2005 Live cardset

### New Utility Scripts
- fix_player_names.py: PATCH player names to remove symbols (uses 'name' param)
- check_player_names.py: Verify all players for asterisks/hashes
- regenerate_lefty_cards.py: Update image URLs with cache-busting dates
- upload_lefty_cards_to_s3.py: Fetch fresh cards and upload to S3

### Documentation (CRITICAL - READ BEFORE WORKING WITH CARDS)
- docs/LESSONS_LEARNED_ASTERISK_REGRESSION.md: Comprehensive guide
  * API parameter is 'name' NOT 'p_name'
  * Card generation caching requires timestamp cache-busting
  * S3 keys must not include query parameters
  * Player names only in 'players' table
  * Never append visual indicators to stored data

- CLAUDE.md: Added critical warnings section at top

## Key Learnings
1. API param for player name is 'name', not 'p_name'
2. Cards are cached - use timestamp in ?d= parameter
3. S3 keys != S3 URLs (no query params in keys)
4. Fix data BEFORE generating/uploading cards
5. Visual indicators belong in UI, not database

## Impact
- Fixed 20 player records in production
- Regenerated and uploaded 20 clean cards to S3
- Documented to prevent future regressions

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-24 14:38:04 -06:00

73 lines
2.2 KiB
Python

"""
Regenerate cards for the 20 left-handed players whose names were just fixed
Updates image URLs with tomorrow's date to bust cache
"""
import asyncio
import datetime
from db_calls import db_patch, DB_URL
# List of player IDs that were fixed
FIXED_PLAYER_IDS = [
13015, # Terrence Long
13017, # Jeremy Reed
13020, # Ben Broussard
13030, # Carlos Pena
13032, # Scott Podsednik
13034, # AJ Pierzynski
13037, # Brian Schneider
13045, # Justin Morneau
13047, # BJ Surhoff
13048, # Jay Gibbons
13053, # Eric Hinske
13058, # Chad Tracy
13062, # Dave Roberts
13068, # Daryle Ward
13070, # Jim Edmonds
13071, # Larry Walker
13077, # Adam Dunn
13082, # Mike Lamb
13084, # Larry Bigbie
13090, # Rafael Palmeiro
]
async def regenerate_cards():
# Tomorrow's date for cache busting
tomorrow = datetime.date.today() + datetime.timedelta(days=1)
release_date = f'{tomorrow.year}-{tomorrow.month}-{tomorrow.day}'
print(f"Regenerating cards with release date: {release_date}\n")
success_count = 0
error_count = 0
for player_id in FIXED_PLAYER_IDS:
try:
# Build new image URL with tomorrow's date
batting_card_url = f'{DB_URL}/v2/players/{player_id}/battingcard?d={release_date}'
print(f"Updating player {player_id}...")
# PATCH the player with new image URL
result = await db_patch('players', object_id=player_id, params=[('image', batting_card_url)])
if 'player_id' in result or 'id' in result:
print(f" ✅ Success - {result.get('p_name', 'Unknown')}")
success_count += 1
else:
print(f" ❌ Failed: {result}")
error_count += 1
except Exception as e:
print(f" ❌ Error: {e}")
error_count += 1
print(f"\n{'='*60}")
print(f"SUMMARY")
print(f"{'='*60}")
print(f"Successfully updated: {success_count} players")
print(f"Errors: {error_count} players")
print(f"Total: {len(FIXED_PLAYER_IDS)} players")
print(f"{'='*60}")
if __name__ == '__main__':
asyncio.run(regenerate_cards())