"""Seed runner — reads JSON files and upserts into the database.""" import json from pathlib import Path from sqlalchemy import func, select from sqlalchemy.ext.asyncio import AsyncSession from app.core.database import async_session from app.models.game import Game from app.models.pokemon import Pokemon from app.models.route import Route from app.models.route_encounter import RouteEncounter from app.seeds.loader import ( upsert_evolutions, upsert_games, upsert_pokemon, upsert_route_encounters, upsert_routes, ) DATA_DIR = Path(__file__).parent / "data" # All Gen 1-9 games GAME_FILES = [ # Gen 1 "red", "blue", "yellow", # Gen 2 "gold", "silver", "crystal", # Gen 3 "ruby", "sapphire", "emerald", "firered", "leafgreen", # Gen 4 "diamond", "pearl", "platinum", "heartgold", "soulsilver", # Gen 5 "black", "white", "black-2", "white-2", # Gen 6 "x", "y", "omega-ruby", "alpha-sapphire", # Gen 7 "sun", "moon", "ultra-sun", "ultra-moon", "lets-go-pikachu", "lets-go-eevee", # Gen 8 "sword", "shield", "brilliant-diamond", "shining-pearl", "legends-arceus", # Gen 9 "scarlet", "violet", ] def load_json(filename: str) -> list[dict]: path = DATA_DIR / filename with open(path) as f: return json.load(f) async def seed(): """Run the full seed process.""" print("Starting seed...") async with async_session() as session: async with session.begin(): # 1. Upsert games games_data = load_json("games.json") slug_to_id = await upsert_games(session, games_data) print(f"Games: {len(slug_to_id)} upserted") # 2. Upsert Pokemon pokemon_data = load_json("pokemon.json") dex_to_id = await upsert_pokemon(session, pokemon_data) print(f"Pokemon: {len(dex_to_id)} upserted") # 3. Per game: upsert routes and encounters total_routes = 0 total_encounters = 0 for game_slug in GAME_FILES: game_id = slug_to_id.get(game_slug) if game_id is None: print(f"Warning: game '{game_slug}' not found, skipping") continue routes_data = load_json(f"{game_slug}.json") route_map = await upsert_routes(session, game_id, routes_data) total_routes += len(route_map) for route in routes_data: route_id = route_map.get(route["name"]) if route_id is None: print(f" Warning: route '{route['name']}' not found") continue # Parent routes may have empty encounters if route["encounters"]: enc_count = await upsert_route_encounters( session, route_id, route["encounters"], dex_to_id ) total_encounters += enc_count # Handle child routes for child in route.get("children", []): child_id = route_map.get(child["name"]) if child_id is None: print(f" Warning: child route '{child['name']}' not found") continue enc_count = await upsert_route_encounters( session, child_id, child["encounters"], dex_to_id ) total_encounters += enc_count print(f" {game_slug}: {len(route_map)} routes") print(f"\nTotal routes: {total_routes}") print(f"Total encounters: {total_encounters}") # 4. Upsert evolutions evolutions_path = DATA_DIR / "evolutions.json" if evolutions_path.exists(): evolutions_data = load_json("evolutions.json") evo_count = await upsert_evolutions(session, evolutions_data, dex_to_id) print(f"Evolutions: {evo_count} upserted") else: print("No evolutions.json found, skipping evolutions") print("Seed complete!") async def verify(): """Run post-seed verification checks.""" print("\n--- Verification ---") async with async_session() as session: # Overall counts games_count = (await session.execute(select(func.count(Game.id)))).scalar() pokemon_count = (await session.execute(select(func.count(Pokemon.id)))).scalar() routes_count = (await session.execute(select(func.count(Route.id)))).scalar() enc_count = (await session.execute(select(func.count(RouteEncounter.id)))).scalar() print(f"Games: {games_count}") print(f"Pokemon: {pokemon_count}") print(f"Routes: {routes_count}") print(f"Route Encounters: {enc_count}") # Per-game breakdown result = await session.execute( select(Game.name, func.count(Route.id)) .join(Route, Route.game_id == Game.id) .group_by(Game.name) .order_by(Game.name) ) print("\nRoutes per game:") for row in result: print(f" {row[0]}: {row[1]}") # Per-game encounter counts result = await session.execute( select(Game.name, func.count(RouteEncounter.id)) .join(Route, Route.game_id == Game.id) .join(RouteEncounter, RouteEncounter.route_id == Route.id) .group_by(Game.name) .order_by(Game.name) ) print("\nEncounters per game:") for row in result: print(f" {row[0]}: {row[1]}") print("\nVerification complete!")