--- # nuzlocke-tracker-u7i9 title: Combine sub-areas into single locations status: completed type: feature priority: normal created_at: 2026-02-05T14:27:13Z updated_at: 2026-02-06T09:56:11Z parent: nuzlocke-tracker-f5ob --- Some game locations have multiple encounter tables (e.g. Mount Moon 1F, Mount Moon B1F, Mount Moon B2F) but are treated as a single location for Nuzlocke first-encounter rules. Needs a concept of 'location groups' — a parent location that contains multiple sub-areas, each with their own encounter table. For Nuzlocke purposes, the first encounter in *any* sub-area of the group counts as that location's encounter. ## Implementation Summary Added hierarchical route grouping so locations like Mt. Moon (with floors 1F, B1F, B2F) are treated as a single location for Nuzlocke first-encounter rules. The first encounter in ANY sub-area counts as that location's encounter. ### Changes Made 1. **Database Migration** (`c3d4e5f6a7b8_add_route_grouping.py`) - Added nullable `parent_route_id` column with self-referential FK (CASCADE delete) 2. **Backend Model** (`backend/src/app/models/route.py`) - Added `parent_route_id` field - Added self-referential `parent` and `children` relationships 3. **Backend Schemas** (`backend/src/app/schemas/game.py`) - Added `parent_route_id` to `RouteResponse`, `RouteCreate`, `RouteUpdate` - Added `RouteWithChildrenResponse` with nested children 4. **Backend API - Games** (`backend/src/app/api/games.py`) - Updated `list_game_routes` to support hierarchical response (default) or flat list (`?flat=true`) 5. **Backend API - Encounters** (`backend/src/app/api/encounters.py`) - Added validation: cannot create encounter on parent route (400 error) - Added validation: cannot create encounter if sibling already has one (409 error) 6. **Frontend Types** (`frontend/src/types/game.ts`) - Added `parentRouteId` to `Route` interface - Added `RouteWithChildren` interface 7. **Frontend Page** (`frontend/src/pages/RunEncounters.tsx`) - Added `organizeRoutes()` helper to build hierarchy from flat list - Added `getGroupEncounter()` to check if any child has an encounter - Updated progress counter to count groups (not individual sub-routes) - Added collapsible `RouteGroup` component - Sibling routes are disabled after one has an encounter 8. **Seed Data** (`backend/src/app/seeds/fetch_pokeapi.py`) - Updated to automatically detect grouped locations from PokeAPI's location/location-area structure - Parent routes have empty encounters; children have actual encounters - 70 parent routes with 315 child routes across all games 9. **Seed Loader** (`backend/src/app/seeds/loader.py`, `run.py`) - Updated `upsert_routes` to handle hierarchical structure with parent_route_id - Updated seed runner to process child route encounters ## Considerations - [x] Data model: add a parent_route_id or location_group concept to the Route model - [x] Seed data: identify which routes should be grouped (automatically derived from PokeAPI location/area structure) - [x] Encounter tracking: when logging an encounter in a sub-area, mark the whole group as visited - [x] Route list UI: show grouped locations as collapsible sections