#!/usr/bin/env python3 """ Database Validation Script for Paper Dynasty Card Generation Checks for common errors in card database before uploading: - Negative groundball_b values (causes gameplay crashes) - Invalid percentage ranges (>100 or <0) - NULL values in required fields Usage: python validate_database.py """ import sqlite3 import sys from pathlib import Path from typing import List, Tuple, Dict class ValidationError: def __init__(self, table: str, issue: str, count: int, examples: List[Dict]): self.table = table self.issue = issue self.count = count self.examples = examples def __str__(self): lines = [f"❌ {self.table}: {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 validate_batting_cards(cursor: sqlite3.Cursor) -> List[ValidationError]: """Validate batting cards table""" errors = [] # Check 1: Negative groundball_b values cursor.execute(""" SELECT player_name, card_id, groundball_b, rarity FROM batting_cards WHERE groundball_b < 0 ORDER BY groundball_b ASC LIMIT 10 """) negative_gb = cursor.fetchall() if negative_gb: count = cursor.execute("SELECT COUNT(*) FROM batting_cards WHERE groundball_b < 0").fetchone()[0] examples = [ f"{name} (ID: {card_id}, GB-B: {gb}, Rarity: {rarity})" for name, card_id, gb, rarity in negative_gb ] errors.append(ValidationError("batting_cards", "Negative groundball_b values", count, examples)) # Check 2: Invalid percentage ranges (0-100) # Adjust column names based on actual schema percentage_columns = ['strikeout', 'walk', 'homerun'] # Add more as needed for col in percentage_columns: try: cursor.execute(f""" SELECT player_name, card_id, {col} FROM batting_cards WHERE {col} < 0 OR {col} > 100 LIMIT 10 """) invalid_pct = cursor.fetchall() if invalid_pct: count = cursor.execute(f"SELECT COUNT(*) FROM batting_cards WHERE {col} < 0 OR {col} > 100").fetchone()[0] examples = [f"{name} (ID: {card_id}, {col}: {val})" for name, card_id, val in invalid_pct] errors.append(ValidationError("batting_cards", f"Invalid {col} percentage", count, examples)) except sqlite3.OperationalError: # Column might not exist - skip pass return errors def validate_pitching_cards(cursor: sqlite3.Cursor) -> List[ValidationError]: """Validate pitching cards table""" errors = [] # Check: Invalid percentage ranges percentage_columns = ['strikeout', 'walk', 'homerun'] # Add more as needed for col in percentage_columns: try: cursor.execute(f""" SELECT player_name, card_id, {col} FROM pitching_cards WHERE {col} < 0 OR {col} > 100 LIMIT 10 """) invalid_pct = cursor.fetchall() if invalid_pct: count = cursor.execute(f"SELECT COUNT(*) FROM pitching_cards WHERE {col} < 0 OR {col} > 100").fetchone()[0] examples = [f"{name} (ID: {card_id}, {col}: {val})" for name, card_id, val in invalid_pct] errors.append(ValidationError("pitching_cards", f"Invalid {col} percentage", count, examples)) except sqlite3.OperationalError: # Column might not exist - skip pass return errors def get_card_counts(cursor: sqlite3.Cursor) -> Dict[str, int]: """Get total card counts""" batting_count = cursor.execute("SELECT COUNT(*) FROM batting_cards").fetchone()[0] pitching_count = cursor.execute("SELECT COUNT(*) FROM pitching_cards").fetchone()[0] return {"batting": batting_count, "pitching": pitching_count} def main(): if len(sys.argv) != 2: print("Usage: python validate_database.py ") sys.exit(1) db_path = Path(sys.argv[1]) if not db_path.exists(): print(f"❌ Database not found: {db_path}") sys.exit(1) print(f"🔍 Validating database: {db_path}") print() # Connect to database conn = sqlite3.connect(db_path) cursor = conn.cursor() # Get card counts counts = get_card_counts(cursor) print(f"📊 Total Cards:") print(f" - Batting: {counts['batting']}") print(f" - Pitching: {counts['pitching']}") print() # Run validations all_errors = [] all_errors.extend(validate_batting_cards(cursor)) all_errors.extend(validate_pitching_cards(cursor)) # Report results 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 in database") sys.exit(0) if __name__ == "__main__": main()