#!/usr/bin/env python3 """ Database Validation Script for Paper Dynasty Card Generation Checks for common errors in card data via the API before deployment: - Missing batting or pitching cards for a cardset - Players with no corresponding card record - Rarity distribution sanity check Usage: python validate_database.py [--cardset-id 24] [--env prod] """ import sys import argparse from pathlib import Path from typing import List, Dict sys.path.insert(0, str(Path(__file__).parent.parent)) from api_client import PaperDynastyAPI class ValidationError: def __init__(self, entity: str, issue: str, count: int, examples: List[str]): self.entity = entity self.issue = issue self.count = count self.examples = examples def __str__(self): lines = [f"❌ {self.entity}: {self.issue} ({self.count} records)"] for example in self.examples[:5]: # Show max 5 examples lines.append(f" - {example}") if self.count > 5: lines.append(f" ... and {self.count - 5} more") return "\n".join(lines) def get_card_counts(api: PaperDynastyAPI, cardset_id: int) -> Dict[str, int]: """Get total card counts for the cardset from the API""" batting = api.get("battingcards", params=[("cardset_id", cardset_id)]) pitching = api.get("pitchingcards", params=[("cardset_id", cardset_id)]) return { "batting": batting.get("count", 0), "pitching": pitching.get("count", 0), } def validate_card_counts(api: PaperDynastyAPI, cardset_id: int) -> List[ValidationError]: """Check that batting and pitching cards exist for the cardset""" errors = [] counts = get_card_counts(api, cardset_id) if counts["batting"] == 0: errors.append(ValidationError( "battingcards", f"No batting cards found for cardset {cardset_id}", 0, [] )) if counts["pitching"] == 0: errors.append(ValidationError( "pitchingcards", f"No pitching cards found for cardset {cardset_id}", 0, [] )) return errors def validate_player_coverage(api: PaperDynastyAPI, cardset_id: int) -> List[ValidationError]: """Check that every player in the cardset has at least one card""" errors = [] try: players = api.list_players(cardset_id=cardset_id) except Exception as e: errors.append(ValidationError("players", f"Could not fetch players: {e}", 0, [])) return errors if not players: errors.append(ValidationError( "players", f"No players found for cardset {cardset_id}", 0, [] )) return errors batting_data = api.get("battingcards", params=[("cardset_id", cardset_id)]) pitching_data = api.get("pitchingcards", params=[("cardset_id", cardset_id)]) batting_player_ids = { c["player"]["player_id"] for c in batting_data.get("cards", []) if c.get("player") } pitching_player_ids = { c["player"]["player_id"] for c in pitching_data.get("cards", []) if c.get("player") } all_card_player_ids = batting_player_ids | pitching_player_ids uncovered = [ p for p in players if p["player_id"] not in all_card_player_ids ] if uncovered: examples = [ f"{p.get('p_name', 'Unknown')} (ID: {p['player_id']}, rarity: {p.get('rarity', {}).get('name', '?') if isinstance(p.get('rarity'), dict) else p.get('rarity', '?')})" for p in uncovered ] errors.append(ValidationError( "players", "Players with no batting or pitching card", len(uncovered), examples )) return errors def main(): parser = argparse.ArgumentParser( description="Validate Paper Dynasty card data via the API" ) parser.add_argument( "--cardset-id", type=int, default=24, help="Cardset ID to validate (default: 24, the live cardset)" ) parser.add_argument( "--env", choices=["prod", "dev"], default="prod", help="API environment (default: prod)" ) args = parser.parse_args() api = PaperDynastyAPI(environment=args.env) print(f"🔍 Validating cardset {args.cardset_id} ({args.env})") print() counts = get_card_counts(api, args.cardset_id) print(f"📊 Total Cards:") print(f" - Batting: {counts['batting']}") print(f" - Pitching: {counts['pitching']}") print() all_errors = [] all_errors.extend(validate_card_counts(api, args.cardset_id)) all_errors.extend(validate_player_coverage(api, args.cardset_id)) if all_errors: print("❌ VALIDATION FAILED") print() for error in all_errors: print(error) print() print(f"Total issues: {len(all_errors)}") sys.exit(1) else: print("✅ VALIDATION PASSED") print("No errors found") sys.exit(0) if __name__ == "__main__": main()