paper-dynasty-card-creation/analyze_cardset_rarity.py
Cal Corum 96f3721780 CLAUDE: Add S3 upload script and cardset analysis tools
- Add check_cards_and_upload.py: Fetches card images from API and uploads to AWS S3
  - Uses persistent aiohttp session for efficient connection reuse
  - Supports cache-busting query parameters (?d=date) for Discord compatibility
  - S3 URL structure: cards/cardset-{id:03d}/player-{id}/{type}card.png
  - Configurable upload and player URL update flags

- Add analyze_cardset_rarity.py: Analyzes players by franchise and rarity
  - Groups batters, pitchers, and combined totals
  - Displays counts for all rarity tiers by franchise
  - Provides comprehensive breakdown of cardset composition

- Add rank_pitching_staffs.py: Ranks teams 1-30 by pitching staff quality
  - Point system based on rarity tiers (HoF=5, MVP=4, AS=3, etc.)
  - Shows detailed rosters for top 5 and bottom 5 teams
  - Useful for balance analysis and cardset evaluation

- Update CLAUDE.md with new scripts documentation

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-09 06:11:16 -06:00

182 lines
5.4 KiB
Python

import asyncio
from collections import defaultdict
from db_calls import db_get
async def analyze_cardset_rarity(cardset_id: int = 27):
"""Analyze players by franchise and rarity for a given cardset."""
print(f'Fetching players from cardset {cardset_id}...\n')
# Fetch all players from the cardset
p_query = await db_get(
'players',
params=[('cardset_id', cardset_id), ('inc_dex', False)]
)
if not p_query or p_query['count'] == 0:
print(f'No players found for cardset {cardset_id}')
return
players = p_query['players']
print(f'Found {len(players)} players\n')
# First pass: collect all unique rarity names
all_rarities = set()
for player in players:
rarity_obj = player.get('rarity', {})
if isinstance(rarity_obj, dict):
rarity_name = rarity_obj.get('name')
if rarity_name:
all_rarities.add(rarity_name)
sorted_rarities = sorted(all_rarities, key=lambda x: (
{'Common': 0, 'Uncommon': 1, 'Rare': 2, 'Epic': 3, 'Legend': 4,
'Starter': 0, 'Bench': 1, 'All-Star': 2, 'MVP': 3, 'Hall of Fame': 4}.get(x, 99), x
))
print(f'Found rarities: {sorted_rarities}\n')
# Group players by franchise and rarity
franchise_data = defaultdict(lambda: {
'batters': defaultdict(int),
'pitchers': defaultdict(int),
'combined': defaultdict(int)
})
for player in players:
franchise = player.get('franchise', 'Unknown')
rarity_obj = player.get('rarity', {})
# Extract rarity name from rarity object
if isinstance(rarity_obj, dict):
rarity = rarity_obj.get('name', 'Unknown')
else:
rarity = str(rarity_obj) if rarity_obj else 'Unknown'
# Determine if batter or pitcher based on positions
positions = []
for i in range(1, 9):
pos = player.get(f'pos_{i}')
if pos:
positions.append(pos)
is_pitcher = any(pos in ['SP', 'RP', 'CP'] for pos in positions)
if is_pitcher:
franchise_data[franchise]['pitchers'][rarity] += 1
else:
franchise_data[franchise]['batters'][rarity] += 1
franchise_data[franchise]['combined'][rarity] += 1
# Sort franchises alphabetically
sorted_franchises = sorted(franchise_data.keys())
# Print batters
print('=' * 100)
print('BATTERS BY FRANCHISE AND RARITY')
print('=' * 100)
# Build header dynamically
header = f'{"Franchise":<20}'
for rarity in sorted_rarities:
header += f' {rarity:<12}'
header += f' {"Total":<10}'
print(header)
print('-' * 100)
batter_totals = defaultdict(int)
for franchise in sorted_franchises:
batters = franchise_data[franchise]['batters']
total = sum(batters.values())
if total > 0:
row = f'{franchise:<20}'
for rarity in sorted_rarities:
count = batters.get(rarity, 0)
row += f' {count:<12}'
batter_totals[rarity] += count
row += f' {total:<10}'
batter_totals['Total'] += total
print(row)
print('-' * 100)
total_row = f'{"TOTAL":<20}'
for rarity in sorted_rarities:
total_row += f' {batter_totals[rarity]:<12}'
total_row += f' {batter_totals["Total"]:<10}'
print(total_row)
# Print pitchers
print('\n' + '=' * 100)
print('PITCHERS BY FRANCHISE AND RARITY')
print('=' * 100)
header = f'{"Franchise":<20}'
for rarity in sorted_rarities:
header += f' {rarity:<12}'
header += f' {"Total":<10}'
print(header)
print('-' * 100)
pitcher_totals = defaultdict(int)
for franchise in sorted_franchises:
pitchers = franchise_data[franchise]['pitchers']
total = sum(pitchers.values())
if total > 0:
row = f'{franchise:<20}'
for rarity in sorted_rarities:
count = pitchers.get(rarity, 0)
row += f' {count:<12}'
pitcher_totals[rarity] += count
row += f' {total:<10}'
pitcher_totals['Total'] += total
print(row)
print('-' * 100)
total_row = f'{"TOTAL":<20}'
for rarity in sorted_rarities:
total_row += f' {pitcher_totals[rarity]:<12}'
total_row += f' {pitcher_totals["Total"]:<10}'
print(total_row)
# Print combined
print('\n' + '=' * 100)
print('COMBINED (BATTERS + PITCHERS) BY FRANCHISE AND RARITY')
print('=' * 100)
header = f'{"Franchise":<20}'
for rarity in sorted_rarities:
header += f' {rarity:<12}'
header += f' {"Total":<10}'
print(header)
print('-' * 100)
combined_totals = defaultdict(int)
for franchise in sorted_franchises:
combined = franchise_data[franchise]['combined']
total = sum(combined.values())
row = f'{franchise:<20}'
for rarity in sorted_rarities:
count = combined.get(rarity, 0)
row += f' {count:<12}'
combined_totals[rarity] += count
row += f' {total:<10}'
combined_totals['Total'] += total
print(row)
print('-' * 100)
total_row = f'{"TOTAL":<20}'
for rarity in sorted_rarities:
total_row += f' {combined_totals[rarity]:<12}'
total_row += f' {combined_totals["Total"]:<10}'
print(total_row)
print('=' * 100)
if __name__ == '__main__':
asyncio.run(analyze_cardset_rarity(27))