Add after_route_name to boss battle export/seed pipeline
Exports now include after_route_name (resolved from the route FK), and the seed loader resolves it back to an ID on import. Also adds a draft bean for displaying encounter-less locations. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,19 @@
|
||||
---
|
||||
# nuzlocke-tracker-xa5k
|
||||
title: Display encounter-less locations for egg hatching
|
||||
status: draft
|
||||
type: feature
|
||||
created_at: 2026-02-08T14:49:50Z
|
||||
updated_at: 2026-02-08T14:49:50Z
|
||||
---
|
||||
|
||||
Some routes/locations don't have wild encounters but are still relevant for gameplay — particularly for hatching eggs. Currently these locations are hidden or not useful in the run view since they have no encounters to log.
|
||||
|
||||
Add support for displaying locations that have no encounters in the run view, so players can track egg hatches or other location-based events there.
|
||||
|
||||
## Checklist
|
||||
|
||||
- [ ] Determine how encounter-less routes should appear in the run view (e.g. different visual treatment, no encounter status dot)
|
||||
- [ ] Update route filtering logic to include routes without encounters when relevant
|
||||
- [ ] Add ability to log an egg hatch at a location (new encounter type or dedicated UI)
|
||||
- [ ] Consider whether these locations need an admin-side flag (e.g. `show_without_encounters`) or if all routes should always be visible
|
||||
@@ -127,6 +127,7 @@ async def export_game_bosses(
|
||||
.where(BossBattle.version_group_id == game.version_group_id)
|
||||
.options(
|
||||
selectinload(BossBattle.pokemon).selectinload(BossPokemon.pokemon),
|
||||
selectinload(BossBattle.after_route),
|
||||
)
|
||||
.order_by(BossBattle.order)
|
||||
)
|
||||
@@ -143,6 +144,7 @@ async def export_game_bosses(
|
||||
"badge_image_url": b.badge_image_url,
|
||||
"level_cap": b.level_cap,
|
||||
"order": b.order,
|
||||
"after_route_name": b.after_route.name if b.after_route else None,
|
||||
"location": b.location,
|
||||
"section": b.section,
|
||||
"sprite_url": b.sprite_url,
|
||||
|
||||
@@ -211,10 +211,19 @@ async def upsert_bosses(
|
||||
version_group_id: int,
|
||||
bosses: list[dict],
|
||||
dex_to_id: dict[int, int],
|
||||
route_name_to_id: dict[str, int] | None = None,
|
||||
) -> int:
|
||||
"""Upsert boss battles for a version group, return count of bosses upserted."""
|
||||
count = 0
|
||||
for boss in bosses:
|
||||
# Resolve after_route_name to an ID
|
||||
after_route_id = None
|
||||
after_route_name = boss.get("after_route_name")
|
||||
if after_route_name and route_name_to_id:
|
||||
after_route_id = route_name_to_id.get(after_route_name)
|
||||
if after_route_id is None:
|
||||
print(f" Warning: route '{after_route_name}' not found for boss '{boss['name']}'")
|
||||
|
||||
# Upsert the boss battle on (version_group_id, order) conflict
|
||||
stmt = insert(BossBattle).values(
|
||||
version_group_id=version_group_id,
|
||||
@@ -225,6 +234,7 @@ async def upsert_bosses(
|
||||
badge_image_url=boss.get("badge_image_url"),
|
||||
level_cap=boss["level_cap"],
|
||||
order=boss["order"],
|
||||
after_route_id=after_route_id,
|
||||
location=boss["location"],
|
||||
section=boss.get("section"),
|
||||
sprite_url=boss.get("sprite_url"),
|
||||
@@ -237,6 +247,7 @@ async def upsert_bosses(
|
||||
"badge_name": boss.get("badge_name"),
|
||||
"badge_image_url": boss.get("badge_image_url"),
|
||||
"level_cap": boss["level_cap"],
|
||||
"after_route_id": after_route_id,
|
||||
"location": boss["location"],
|
||||
"section": boss.get("section"),
|
||||
"sprite_url": boss.get("sprite_url"),
|
||||
|
||||
@@ -68,6 +68,7 @@ async def seed():
|
||||
# 4. Per version group: upsert routes once, then encounters per game
|
||||
total_routes = 0
|
||||
total_encounters = 0
|
||||
route_maps_by_vg: dict[int, dict[str, int]] = {}
|
||||
|
||||
for vg_slug, vg_info in vg_data.items():
|
||||
vg_id = vg_slug_to_id[vg_slug]
|
||||
@@ -87,6 +88,7 @@ async def seed():
|
||||
|
||||
# Upsert routes once per version group
|
||||
route_map = await upsert_routes(session, vg_id, routes_data)
|
||||
route_maps_by_vg[vg_id] = route_map
|
||||
total_routes += len(route_map)
|
||||
print(f" {vg_slug}: {len(route_map)} routes")
|
||||
|
||||
@@ -147,7 +149,8 @@ async def seed():
|
||||
if not bosses_data:
|
||||
continue
|
||||
|
||||
boss_count = await upsert_bosses(session, vg_id, bosses_data, dex_to_id)
|
||||
route_name_to_id = route_maps_by_vg.get(vg_id, {})
|
||||
boss_count = await upsert_bosses(session, vg_id, bosses_data, dex_to_id, route_name_to_id)
|
||||
total_bosses += boss_count
|
||||
print(f" {vg_slug}: {boss_count} bosses")
|
||||
|
||||
@@ -416,6 +419,7 @@ async def _export_bosses(session: AsyncSession, vg_data: dict):
|
||||
.where(BossBattle.version_group_id == vg.id)
|
||||
.options(
|
||||
selectinload(BossBattle.pokemon).selectinload(BossPokemon.pokemon),
|
||||
selectinload(BossBattle.after_route),
|
||||
)
|
||||
.order_by(BossBattle.order)
|
||||
)
|
||||
@@ -434,6 +438,7 @@ async def _export_bosses(session: AsyncSession, vg_data: dict):
|
||||
"badge_image_url": b.badge_image_url,
|
||||
"level_cap": b.level_cap,
|
||||
"order": b.order,
|
||||
"after_route_name": b.after_route.name if b.after_route else None,
|
||||
"location": b.location,
|
||||
"section": b.section,
|
||||
"sprite_url": b.sprite_url,
|
||||
|
||||
Reference in New Issue
Block a user