paper-dynasty-card-creation/validate_negative_values.py
2025-11-10 15:02:28 -06:00

111 lines
3.7 KiB
Python

#!/usr/bin/env python3
"""
Comprehensive validation script to check for negative values in batting cards.
Checks all numeric fields that should never be negative.
"""
import asyncio
from db_calls import db_get
async def validate_batting_cards(cardset_id=27):
"""Check all batting cards for negative values in any field."""
print(f'Checking batting cards for cardset {cardset_id}...')
print('=' * 70)
# Get all batting cards for the cardset directly
batting_cards_response = await db_get('battingcards', params=[('cardset', cardset_id)])
if not batting_cards_response:
print(f'❌ No response from battingcards endpoint for cardset {cardset_id}')
return False
# Extract batting cards list - API returns 'cards' key
batting_cards = batting_cards_response.get('cards', [])
if not batting_cards:
print(f'❌ No batting cards found for cardset {cardset_id}')
return False
print(f'Found {len(batting_cards)} batting cards in cardset')
print()
# Check all cards
all_errors = []
cards_checked = 0
for card in batting_cards:
cards_checked += 1
card_id = card.get('id', 'Unknown')
# Extract player info
player_info = card.get('player', {})
player_name = player_info.get('p_name', 'Unknown')
player_id = player_info.get('player_id', 'Unknown')
# Check all numeric fields
for field, value in card.items():
# Skip non-numeric or None values
if value is None or not isinstance(value, (int, float)):
continue
# Skip IDs and other fields that can be negative or are not relevant
if field in ['id', 'player_id', 'cardset', 'variant']:
continue
# Check for negative values in fields that should be non-negative
if value < 0:
# Most baseball stats should be >= 0
all_errors.append({
'card_id': card_id,
'player_name': player_name,
'player_id': player_id,
'field': field,
'value': value
})
print(f'Checked {cards_checked} batting cards')
print()
if all_errors:
print(f'❌ VALIDATION ERRORS FOUND: {len(all_errors)} negative values')
print('=' * 70)
# Group by player
by_player = {}
for error in all_errors:
player_key = f"{error['player_id']} - {error['player_name']}"
if player_key not in by_player:
by_player[player_key] = []
by_player[player_key].append(error)
print(f'\nAffected players: {len(by_player)}')
print()
for player_key, player_errors in sorted(by_player.items()):
print(f"{player_key}:")
for error in player_errors:
print(f" - Card {error['card_id']}: {error['field']} = {error['value']}")
print()
print('=' * 70)
print('🛑 DO NOT PROCEED WITH S3 UPLOAD')
print('These negative values will cause gameplay crashes!')
print()
print('Next steps:')
print('1. Identify root cause in card generation code')
print('2. Fix the calculation bug')
print('3. Re-run card generation (Step 2)')
print('4. Re-run this validation')
return False
else:
print('✅ No negative values found in any batting card fields')
print('✅ DATABASE VALIDATION PASSED')
print()
print('Safe to proceed with S3 upload (Step 6)')
return True
if __name__ == '__main__':
result = asyncio.run(validate_batting_cards(27))
exit(0 if result else 1)