"""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" GAME_FILES = ["firered", "leafgreen", "emerald", "heartgold", "soulsilver"] 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 enc_count = await upsert_route_encounters( session, route_id, route["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!")