Add encounter condition support with rate display

Add a `condition` column to RouteEncounter for time-of-day, weather,
and season variants. Seed loader expands `conditions` dict into
per-condition rows. EncounterModal shows condition filter tabs with
per-condition encounter rates, and displays rates for all standard
encounter methods (walk, surf, fishing, etc.).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-14 22:42:49 +01:00
parent a482b27bca
commit 9029f1632a
12 changed files with 436 additions and 151 deletions

View File

@@ -1,11 +1,11 @@
---
# nuzlocke-tracker-oqfo
title: Improve encounter rate display for time/weather variants
status: todo
status: in-progress
type: feature
priority: normal
created_at: 2026-02-10T14:04:27Z
updated_at: 2026-02-14T21:17:00Z
updated_at: 2026-02-14T21:39:34Z
---
## Problem
@@ -25,59 +25,18 @@ Extend the data model and UI to support conditional encounter rates, so users ca
## Design
### Seed data format
Add an optional `conditions` field to encounter entries. When absent, the encounter has a flat rate (Gen 1/3/6 — no change needed). When present, it replaces `encounter_rate` with per-condition rates:
```json
{
"pokeapi_id": 163,
"pokemon_name": "Hoothoot",
"method": "walk",
"encounter_rate": null,
"conditions": {
"night": 50,
"morning": 10,
"day": 0
},
"min_level": 2,
"max_level": 5
}
```
For games without variant rates, the existing flat `encounter_rate` field is used unchanged.
### Backend changes
1. **New model `RouteEncounterCondition`** (one-to-many from `RouteEncounter`):
- `id`, `route_encounter_id` (FK), `condition` (string), `encounter_rate` (int)
- Conditions are free-form strings: `"morning"`, `"day"`, `"night"`, `"rain"`, `"spring"`, etc.
2. **`RouteEncounter` model**: keep `encounter_rate` as nullable — null when conditions exist, populated when flat.
3. **Seed loader**: detect `conditions` key in JSON, create `RouteEncounterCondition` rows accordingly.
4. **API**: include conditions in route encounter responses (nested array under each encounter).
### Frontend changes
1. **AdminRouteDetail**: show conditions as sub-rows or a tooltip when hovering the rate column.
2. **EncounterModal**: group by condition context when relevant (e.g. tabs for morning/day/night).
3. **Type updates**: extend `RouteEncounter` type with optional `conditions: { condition: string, encounterRate: number }[]`.
Added a nullable `condition` column to `RouteEncounter` with a functional unique index using `COALESCE(condition, '')` to handle NULL uniqueness. Seed JSON supports an optional `conditions` dict that expands into per-condition DB rows.
## Checklist
- [ ] Update seed JSON schema: add optional `conditions` field to encounter entries
- [ ] Create `RouteEncounterCondition` model with migration
- [ ] Make `RouteEncounter.encounter_rate` nullable
- [ ] Update seed loader to handle `conditions` entries
- [ ] Update API serialization to include conditions
- [ ] Update frontend types (`RouteEncounter`)
- [ ] Update AdminRouteDetail to display condition-based rates
- [ ] Update EncounterModal to show conditions contextually
- [ ] Update seed data for at least one game per variant type (HG/SS, B/W, Sw/Sh) as proof of concept
- [ ] Keep simple display for games with flat rates (no regression)
## Considerations
- For Nuzlocke play, availability ("appears during rain") matters more than exact percentages — consider a simplified view option
- Keep UI uncluttered for simple cases (Gen 1/3/6)
- Condition strings should use a consistent vocabulary (define an enum or reference list)
- Seed data updates for all games can be done incrementally after the infrastructure is in place
- [x] Update seed JSON schema: add optional `conditions` field to encounter entries
- [x] Add `condition` column to `RouteEncounter` model with migration
- [x] Update seed loader to handle `conditions` entries (expands dict into rows)
- [x] Update API serialization to include `condition` field
- [x] Update export endpoint to include `condition` field
- [x] Update frontend types (`RouteEncounter`, admin input types)
- [x] Update AdminRouteDetail to display condition column (shown only when conditions exist)
- [x] Update EncounterModal to show conditions contextually
- [x] Update seed data for HeartGold Route 29 as proof of concept (morning/day/night)
- [x] Keep simple display for games with flat rates (no regression)
- [ ] Update seed data for remaining games with variant encounters (incremental)