Skip to content

feat(aa): AA planner — era rules, validation engine, saved plans, .aa export - #176

Merged
VortexUK merged 1 commit into
mainfrom
feature/aa-planner
Jul 20, 2026
Merged

feat(aa): AA planner — era rules, validation engine, saved plans, .aa export#176
VortexUK merged 1 commit into
mainfrom
feature/aa-planner

Conversation

@VortexUK

Copy link
Copy Markdown
Owner

Summary

The full AA planner stack, user-tested locally across several rounds.

Era rules (data)

  • Per-xpac node visibility in aa_limits.json/aas.db (visible_rows + idempotent migration): pre-SF eras hide class rows 5–6 and subclass rows 16/19 — verified against live Wuoshi census (300 max-AA characters, zero spent points beyond those rows). The AA tab hides off-era nodes via the shared filterTreeForEra.
  • /api/aa/config gains visible_rows + an ?xpac= override; /api/aa/plan-trees resolves a subclass's class/subclass/shadows/heroic tree ids (shadows + heroic mined from live census; a test cross-checks the shadows mapping against node classifications so a rebuild reshuffle fails loudly).

Planner ("Planner" mode on the character AA tab)

  • Pure validation engine: point-cost-weighted, self-exclusive thresholds (line / tree / global / parent-rank), the flat 100/tree cap (confirmed in census maxpointsperlevelnode data), separate adventure/tradeskill pools, no-stranding removals, and the structural shadows section gate (5 points in the section above — absent from census node data).
  • Interactive tree: click to spend, right-click to refund, locked greying, unmet requirements shown in the node tooltip + status line.
  • Era dropdown (KoS→DoV) re-plans under any era's cap/trees/rows — including trees the character's census record doesn't carry yet (shadows/heroic ahead of the server's era).
  • Saved plans in users.db (owner-scoped SQL, 20/character, profanity-screened names, structural payload validation) with always-minted share slugs → read-only /aa-plan/{slug} page rendering under the plan's saved era.
  • In-game .aa export from the planner, the Current AAs view (current + in-game profiles), and the share page. Format reverse-engineered from a real in-game export (committed as the reference sample; all 47 node/tree pairs match aas.db). Purchase order is emitted by replaying the plan through the engine so the in-game loader never jams; unreachable ranks are skipped with a warning.

Rendering + fixes

  • Per-node backdrop sprites (CSS sprite math mirroring image/aa_tree.py) restore subclass/shadows icon chrome.
  • <select> added to the no-Preflight base reset (UA chrome leaked into every dropdown).
  • The 422 handler now jsonable_encoders pydantic errors (latent crash, first hit by a raising field_validator).

Testing

  • Backend: 20 new/extended tests (era round-trip + old-schema migration, committed-db curation pins, config ?xpac=, plan-trees resolution + shadows cross-check, aa_plans CRUD/ownership/sharing/validation). Full suite 1602 passed, pyright clean.
  • Frontend: 40+ new tests (engine rules incl. shadows gating + no-stranding, spend-order legality, .aa XML shape, planner interactions, era dropdown, resolver merge, era filter). Full suite 243 passed, tsc clean, build green.
  • Manually driven end-to-end by the maintainer: era switching, TSO shadows reveal, blocked-click reasons, share links, and .aa downloads.

🤖 Generated with Claude Code

… export

Era data (aas.db + aa_limits.json):
- Per-xpac node visibility curation: pre-Sentinel's-Fate eras hide class
  rows 5-6 and subclass rows 16/19 (verified against live Wuoshi census —
  300 max-AA chars have zero spent points beyond those rows). aa_limits
  gains a visible_rows column (idempotent migration); xpac_limits returns
  it; /api/aa/config exposes it and accepts ?xpac= for era overrides.
- The AA tab hides off-era nodes via the shared filterTreeForEra helper.
- /api/aa/plan-trees resolves a subclass's class/subclass/shadows/heroic
  tree ids (shadows + heroic mined from live census — every shadows tree
  is named "Shadows" with no class field; a test cross-checks the mapping
  against node classifications so a rebuild reshuffle fails loudly).

Planner (character AA tab "Planner" mode):
- Pure validation engine: thresholds count AA points spent (rank × cost),
  self-exclusive unlock counters (line/tree/global/parent-rank), the flat
  100/tree cap (confirmed in census maxpointsperlevelnode data), separate
  adventure/tradeskill pools, and no-stranding removals (refunds re-validate
  everything taken). Shadows section gating (5 pts in the section above) is
  structural — not in census node data — and lives in the engine.
- Interactive AATree: click spend / right-click refund, locked greying,
  unmet requirements shown in the node tooltip and the status line.
- Era dropdown (KoS→DoV): re-plans under any era's cap/trees/rows; the
  resolver offers trees the character's census record doesn't carry yet
  (e.g. shadows when era-planning TSO on an EoF server).
- Saved plans: users.db aa_plans (owner-scoped in SQL, 20/character,
  name profanity-screened, structural payload validation) with always-
  minted share slugs; read-only /aa-plan/{slug} share page rendering under
  the plan's saved era with split adventure/tradeskill point totals.
- .aa spec export (planner + current AAs + in-game profiles + share page):
  the game's own Save/Load XML format, reverse-engineered from a real
  export (scripts/dev/Menludiir_templar_dps.aa — all 47 node/tree pairs
  match aas.db). Purchase order is emitted by replaying the plan through
  the engine so every line is legal when the in-game loader replays it;
  unreachable ranks are skipped with a UI warning.

Rendering + fixes:
- Per-node backdrop sprites (bg_sprite.png CSS sprite math mirroring
  image/aa_tree.py) — subclass/shadows/heroic trees regain their icon
  chrome; class trees unchanged.
- <select> added to the no-Preflight base reset (UA chrome was leaking
  into every dropdown; first spotted on the era select).
- 422 handler now jsonable_encodes pydantic errors (field_validator
  ValueErrors crashed the response serialiser — latent, first hit by the
  aa_plans validators).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@VortexUK
VortexUK merged commit acefbd9 into main Jul 20, 2026
6 checks passed
@VortexUK
VortexUK deleted the feature/aa-planner branch July 20, 2026 23:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant