feat(spells): #11 SpellTable - hydrate metadata from spells.csv at startup

New SpellMetadata + SpellTable. Loads docs/research/data/spells.csv at
GameWindow construction (3,956 spells x 11 useful fields including
Family for buff stacking which issue #6 needs). The CSV is copied to
bin/<config>/net10.0/data/spells.csv via the csproj <None Include>
entry; SpellTable.LoadFromCsv resolves relative to AppContext.BaseDirectory.

Hand-rolled CSV parser handles RFC 4180 quoted fields with embedded
commas (the Description column) + escaped double-quotes ("" -> ").
No external CsvHelper dep. Falls back to SpellTable.Empty + console
warning if the file is missing (tooling contexts).

Spellbook now accepts an optional SpellTable in its constructor +
exposes TryGetMetadata(spellId, out SpellMetadata). When the table is
absent (legacy `new Spellbook()` calls), TryGetMetadata returns false
gracefully so existing tests keep passing.

GameWindow:
  - SpellTable field initialized via LoadSpellTable() helper that
    handles the missing-file case + emits the spells: loaded N entries
    log line.
  - SpellBook field constructor-initialized with the loaded SpellTable
    so TryGetMetadata works for the live session.

10 new tests (SpellTableTests):
  - Empty table behavior
  - Header-only loads to empty
  - Single row populates all metadata
  - Quoted Description with embedded commas
  - Blank lines skipped
  - Bad-spell-id rows silently skipped (third-party data is messy)
  - Unknown spell-id lookup returns false
  - ParseRow primitive: simple comma split, quoted-field with comma,
    escaped double-quote.

Total tests: 818 -> 828.

Closes #11. Phase G (issue #6 — fold enchantment buffs into vital max
via EnchantmentMath using SpellTable.Family for stacking) unblocked.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Erik 2026-04-25 17:48:43 +02:00
parent 83b020499b
commit 4ceac5cb40
7 changed files with 463 additions and 23 deletions

View file

@ -177,32 +177,18 @@ Copy this block when adding a new issue:
---
## #11 — Spell metadata loader (`spells.csv``SpellTable`)
**Status:** OPEN
**Severity:** LOW (unblocks issue #6's stacking aggregation; also adds tooltip / icon / school metadata for future panels)
**Filed:** 2026-04-25
**Component:** core / spells
**Description:** `docs/research/data/spells.csv` (3,956 spells × 35 cols) has all the per-spell metadata the existing `Spellbook` lacks: `Name`, `School`, `Family` (buff stacking bucket), `IconId`, `Mana`, `Duration`, `IsDebuff`, `IsFellowship`, `Description`. Need a `SpellTable` loader that hydrates a `Dictionary<uint, SpellMetadata>` at startup so `Spellbook.TryGetMetadata(spellId, out)` works.
**Root cause / status:** Issue #6 (vital max ignores enchantment buffs) needs `Family` to do correct stacking aggregation (only one buff per family wins; highest generation). That field comes only from `spells.csv`.
**Files:**
- `src/AcDream.Core/Spells/SpellMetadata.cs` (new record).
- `src/AcDream.Core/Spells/SpellTable.cs` (new loader).
- `src/AcDream.App/Rendering/GameWindow.cs` (load at OnLoad).
- `src/AcDream.App/AcDream.App.csproj` (`<None Update>` to copy CSV to bin output).
- `src/AcDream.Core/Spells/Spellbook.cs` (accept optional `SpellTable`, expose `TryGetMetadata`).
**Acceptance:** Launch with `ACDREAM_DEVTOOLS=1` shows console line `spells: loaded 3956 entries from spells.csv`. `Spellbook.TryGetMetadata(spellId, out)` returns valid record for active enchantment lookups.
---
---
# Recently closed
## #11 — [DONE 2026-04-25] Spell metadata loader (spells.csv → SpellTable)
**Closed:** 2026-04-25
**Commit:** `feat(spells): #11 SpellTable — hydrate metadata from spells.csv at startup`
**Resolution:** Added `SpellMetadata` record + `SpellTable` CSV loader (hand-rolled RFC 4180-ish parser for the quoted Description column with embedded commas). Wired into `Spellbook` constructor as optional metadata source; `Spellbook.TryGetMetadata(spellId, out)` returns the static record when found. `GameWindow` loads `data/spells.csv` from bin output at construction (file copied via `<None Include>` in `AcDream.App.csproj` from `docs/research/data/spells.csv`). Falls back to `SpellTable.Empty` + console warning if the file is missing (e.g. tooling contexts). 10 new tests covering: empty table, header-only, simple row, quoted description with commas, blank lines skipped, bad spell-id rows skipped, lookup hit/miss, RFC 4180 escaped-quote parsing.
---
## #9 — [DONE 2026-04-25] Address-correction sweep on `acclient_function_map.md`
**Closed:** 2026-04-25