Add database schema with SQLAlchemy async + Alembic migrations

Set up PostgreSQL database layer with async SQLAlchemy 2.0 and asyncpg driver.
Implements 6 core tables (games, routes, pokemon, route_encounters, nuzlocke_runs,
encounters) with foreign keys, indexes, and an initial Alembic migration.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Julian Tabel
2026-02-05 13:29:34 +01:00
parent a87d2ef523
commit d94364d6ce
19 changed files with 649 additions and 19 deletions

View File

@@ -1,11 +1,11 @@
---
# nuzlocke-tracker-l7e3
title: Database Schema Design
status: todo
status: completed
type: task
priority: normal
created_at: 2026-02-04T15:46:54Z
updated_at: 2026-02-04T15:47:23Z
updated_at: 2026-02-05T12:29:19Z
parent: nuzlocke-tracker-f5ob
blocking:
- nuzlocke-tracker-bkhs
@@ -15,21 +15,27 @@ blocking:
Design and implement the database schema for persistent storage.
## Decisions
- **Database**: PostgreSQL 16 (already in docker-compose)
- **ORM**: SQLAlchemy 2.0 (async) with asyncpg driver
- **Migrations**: Alembic
- **Async**: Full async — asyncpg + async SQLAlchemy sessions
## Checklist
- [ ] Choose database (PostgreSQL, SQLite, MongoDB, etc.)
- [ ] Set up database connection and ORM/query builder
- [ ] Design and create tables/collections:
- [ ] Games (id, name, generation, region)
- [ ] Routes (id, name, game_id, order, encounter_method)
- [ ] Pokemon (national_dex, name, types, sprite_url)
- [ ] RouteEncounters (route_id, pokemon_id, encounter_rate)
- [ ] NuzlockeRuns (id, game_id, settings, started_at, status)
- [ ] Encounters (id, run_id, route_id, pokemon_id, nickname, status, caught_at)
- [ ] Set up migrations system
- [x] Choose database (PostgreSQL)
- [x] Set up database connection and ORM/query builder (SQLAlchemy 2.0 async + asyncpg)
- [x] Design and create tables/collections:
- [x] Games (id, name, slug, generation, region, box_art_url, release_year)
- [x] Routes (id, name, game_id, order)
- [x] Pokemon (id, national_dex, name, types[], sprite_url)
- [x] RouteEncounters (id, route_id, pokemon_id, encounter_method, encounter_rate) — unique(route, pokemon, method)
- [x] NuzlockeRuns (id, game_id, name, status, rules jsonb, started_at, completed_at)
- [x] Encounters (id, run_id, route_id, pokemon_id, nickname, status, catch_level, faint_level, caught_at)
- [x] Set up migrations system (Alembic)
- [ ] Add seed data for initial games/routes/Pokémon
- [ ] Create indexes for common queries
- [x] Create indexes for common queries (FK indexes on routes, route_encounters, nuzlocke_runs, encounters; status index on nuzlocke_runs)
## Notes
- Consider SQLite for simplicity in MVP, can migrate later
- Use foreign keys for referential integrity
- Status fields should be enums
- Status fields should be enums
- Use PostgreSQL enums or check constraints for status/type fields

View File

@@ -0,0 +1,11 @@
---
# nuzlocke-tracker-rkyc
title: 'Shiny Clause & Dupes Clause: Multi-Encounter Per Route'
status: draft
type: feature
priority: low
created_at: 2026-02-05T12:25:19Z
updated_at: 2026-02-05T12:25:19Z
---
Allow multiple encounters per route when shiny clause or dupes clause is active. Shiny clause lets a player catch a shiny regardless of first-encounter rule. Dupes clause lets them re-roll if the first encounter is a species already caught. Requires frontend logic to add additional encounters to a route and backend validation.