---
# 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