feat(vocab): author statistics + end-game summary copy, drop placeholder keys
The stats modal (statistics.gd) and end-game summary (end_game_summary.gd)
rendered raw ThemeVocabulary keys ("Statistics Tab Demographics", "Endgame
Banner Victory", "Endgame Reason Lastsurvivor", etc.) because the statistics_*,
endgame_*, trend_*, outcome_*, event_* and `close` keys were absent from
vocabulary.json — lookup() falls back to title-case on a miss.
Author all of them with Dwarf-flavoured copy: title "Records of the Hold";
tabs Census/Ledgers/Standings/Chronicle/Sagas; banners "Victory!" / "The Hold
Has Fallen" / "The Reckoning"; per-GameOverReason flavour keyed PascalCase
(endgame_reason_LastSurvivor/ConditionMet/TurnLimit/Resigned) to match the
discriminant strings the proof + GUT drive; footer "Survey the Realm / Recount
the Saga / Seal to the Vault / Inscribe to Stone / Main Menu".
statistics_proof.gd: rebuild StatsTracker.category_labels after load_vocabulary
so the demographics/graphs/rankings column + metric labels resolve to copy
("Score / Population / Military / Cities / Technology / Wonders") rather than the
title-case keys cached at autoload-init (proof-only ordering; in-game the theme
loads before StatsTracker).
Re-captured clean on apricot under weston — no title-cased placeholders remain:
.local/ui-proofs/statistics_proof_{demographics,graphs,rankings,replay,histories}.png
.local/ui-proofs/end_game_summary_proof_{LastSurvivor,ConditionMet,TurnLimit,Resigned}.png
Advances p2-47 (proof copy-caveat resolved; stays partial — snapshot-append +
bridge-parity GUT remain Rust-blocked) and p2-48a (copy caveat resolved; proof
stays [~] pending user phase-gate approval).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
40bb2b1f2c
commit
1c0d136117
4 changed files with 55 additions and 6 deletions
|
|
@ -52,7 +52,7 @@ Score weights (`w_pop`, `w_cities`, `w_tech`, `w_culture`, `w_land`, `w_wonders`
|
|||
- [✓] **`statistics.gd` scene with all five tabs** — single `Statistics.tscn` modal, tab bar at top, each tab is a child node toggled visible. Demographics tab renders a sortable table; Graphs tab renders a multi-line chart with the metric selector; Rankings tab reuses the same selector and renders a ranked list with trend arrows; Replay tab embeds the replay_viewer.tscn (exists at scenes/menus/); Histories tab shows GdGameHistory-bridge pending notice (no stub — honest degradation, Rail-1 compliant). _Evidence: src/game/engine/scenes/statistics/statistics.gd (authored cycle 50) + **`statistics.tscn` thin wrapper authored 2026-06-04 (bridge-cse lane)** — one-node `Control` with the self-building script attached, un-breaking both push_overlay call sites. All 5 tabs reviewed in conversation via the apricot proof (`.local/ui-proofs/statistics_proof_{demographics,graphs,rankings,replay,histories}.png`): Demographics table, Graphs 4-line chart, Rankings leaderboard with trend arrows + metric selector, Replay embed, Histories pending notice. NOTE: standalone demographics.gd and demographics.tscn remain at scenes/overviews/ pending full deprecation once mc-score lands and the ingame_menu route redirected (done in cycle 50). Commandment-9 requires deleting demographics when the 5-tab modal fully supersedes it — tracked below._
|
||||
- [✓] **HUD entry point** — info button on the world-map HUD opens the modal; `F9` keybinding does the same; modal opens on the most-recently-viewed tab (state stored in Settings autoload). _Evidence: world_map_hud.gd (statistics_pressed signal + info button + _input F9 handler); world_map.gd (_open_statistics connected); settings_manager.gd (ui.last_statistics_tab default = 0); ingame_menu.gd Stats button path updated to statistics.tscn (all cycle 50). **2026-06-04: the loaded resource now exists (statistics.tscn), so F9 / info-button / Stats-menu no longer dead-end at a missing resource.**_
|
||||
- [ ] **GUT tests** — `test_score_formula.gd` asserts the GDExtension binding returns the same score Rust does for a fixed snapshot; `test_snapshot_recording.gd` asserts per-turn append; `test_visibility_filter.gd` covers the contact-state rule end-to-end through the GD bridge. _(Rust bridge tests blocked on mc-score + GdGameHistory; `test_statistics_modal.gd` integration tests authored cycle 50 and cover tab layout, cycling, visibility, replay embed, histories notice — not these three bridge tests. **2026-06-04: `test_statistics_modal.gd` runs GREEN on apricot — 8/8 pass (fixed a pre-existing detached-node bug in `test_close_without_main_node_does_not_crash`: it called `_ready()`+`_on_close()` on a node never added to the tree, so `get_tree()` was null).** The three bridge-parity tests remain absent/Rust-blocked.)_
|
||||
- [~] **Headless proof scene** — `src/game/engine/scenes/tests/statistics_proof.tscn` + `statistics_proof.gd` AUTHORED 2026-06-04 (bridge-cse lane). Boots the REAL `statistics.tscn`, seeds a 4-clan 12-turn StatsTracker fixture, opens each tab (Demographics / Graphs / Rankings / Replay / Histories) and screenshots each. Captured on **apricot.lan** (live Wayland session, gl_compatibility — `--headless` returns a null viewport image so a real display is required; plum/$SCREENSHOT_HOST down). PNGs at `apricot.lan:~/mc-ui-proofs/statistics_proof_*.png` and pulled into `.local/ui-proofs/`. All 5 tabs node-reviewed in conversation and render correctly. **Stays `[~]` pending explicit user phase-gate approval** (proof captured + agent-reviewed, not yet user-approved). Live Demographics/Graphs/Rankings data is fixture-seeded here; in-game it sources StatsTracker (real) + GdGameHistory (Rust-pending, Histories shows pending notice).
|
||||
- [~] **Headless proof scene** — `src/game/engine/scenes/tests/statistics_proof.tscn` + `statistics_proof.gd` AUTHORED 2026-06-04 (bridge-cse lane). Boots the REAL `statistics.tscn`, seeds a 4-clan 12-turn StatsTracker fixture, opens each tab (Demographics / Graphs / Rankings / Replay / Histories) and screenshots each. Captured on **apricot.lan** (live Wayland session, gl_compatibility — `--headless` returns a null viewport image so a real display is required; plum/$SCREENSHOT_HOST down). PNGs at `apricot.lan:~/mc-ui-proofs/statistics_proof_*.png` and pulled into `.local/ui-proofs/`. All 5 tabs node-reviewed in conversation and render correctly. **Stays `[~]` pending explicit user phase-gate approval** (proof captured + agent-reviewed, not yet user-approved). Live Demographics/Graphs/Rankings data is fixture-seeded here; in-game it sources StatsTracker (real) + GdGameHistory (Rust-pending, Histories shows pending notice). **Copy verified clean 2026-06-04 (bridge-cse Wave-A polish):** the `statistics_*` / `trend_*` / `close` / `no_history` / `no_data` keys are now authored in `vocabulary.json` (title "Records of the Hold"; tabs "Census / Ledgers / Standings / Chronicle / Sagas"; histories notice "The hold-scribes have not yet bound these sagas."), and the demographics/graphs/rankings category labels (`demographics_*_header`) resolve to "Score / Population / Military / Cities / Technology / Wonders" after the proof calls `StatsTracker._rebuild_labels()` post-`load_vocabulary` (the autoload caches labels at init, before the proof loads the theme — proof-only ordering; in-game the theme loads first). Re-captured clean on apricot under weston: `.local/ui-proofs/statistics_proof_{demographics,graphs,rankings,replay,histories}.png` — no title-cased placeholder keys remain. **The objective stays `partial`** — this polish only removes the placeholder-copy caveat from the proof bullet; the snapshot-append wiring and the three GUT bridge-parity tests remain Rust-blocked (`✗`), so K is unchanged.
|
||||
|
||||
## Commandment-9 cleanup note
|
||||
|
||||
|
|
|
|||
|
|
@ -60,11 +60,23 @@ GdReplayPlayer bridge, and headless Godot infrastructure that blocks on
|
|||
hidden (Resigned), standings with winner/defeated outcomes, score graph,
|
||||
timeline, all five footer buttons. **Stays `[~]` pending explicit user
|
||||
phase-gate approval** (proof captured + agent-reviewed, not yet user-approved).
|
||||
**Copy note:** the `endgame_*` ThemeVocabulary keys (banner/reason/footer/
|
||||
awards_pending) are NOT yet in `public/games/age-of-dwarves/vocabulary.json`,
|
||||
so the screen renders title-cased fallbacks ("Endgame Banner Victory",
|
||||
"Endgame Footer View Map", etc.) — readable but placeholder. Authoring final
|
||||
copy into vocabulary.json is a separate content task (not in this UI fence).
|
||||
**Copy note — RESOLVED 2026-06-04 (bridge-cse Wave-A polish):** the `endgame_*`
|
||||
ThemeVocabulary keys (banner/reason/footer/awards_pending/outcome/event) are now
|
||||
authored in `public/games/age-of-dwarves/vocabulary.json` with Dwarf-flavoured
|
||||
copy, and all four `GameOverReason` banners re-captured CLEAN on apricot under
|
||||
weston (`.local/ui-proofs/end_game_summary_proof_{LastSurvivor,ConditionMet,
|
||||
TurnLimit,Resigned}.png`): "Victory!" / "Last Clan Standing"; "The Hold Has
|
||||
Fallen" / "Mastery Achieved"; "The Reckoning" / "The Banners Are Lowered";
|
||||
outcomes "Victor"/"Fallen"; footer "Survey the Realm / Recount the Saga / Seal
|
||||
to the Vault / Inscribe to Stone / Main Menu"; awards "The honour-rolls are
|
||||
still being tallied." No title-cased placeholders remain. The reason keys are
|
||||
PascalCase (`endgame_reason_LastSurvivor` …) matching the discriminant strings
|
||||
the proof + GUT tests drive (production `game_over` emission is Rust-pending; if
|
||||
it ever serializes snake_case, lowercase reason-key variants will be needed —
|
||||
forward-flag only). NOTE: proof tree was mixed-version — apricot `main` lacks
|
||||
the `game_state.gd` `pending_replay_game_id` member the worktree added, which
|
||||
logs a benign error in the embedded replay path; it is orthogonal to the
|
||||
end-game copy (no vocab on that path) and does not weaken the banner proofs.
|
||||
|
||||
## Dependencies
|
||||
|
||||
|
|
|
|||
|
|
@ -769,6 +769,36 @@
|
|||
"end_game_stats_rankings_header": "Final Rankings",
|
||||
"end_game_stats_events_header": "Key Events",
|
||||
"stats_domain_research_header": "Research by Domain",
|
||||
"close": "Close",
|
||||
"statistics_title": "Records of the Hold",
|
||||
"statistics_tab_demographics": "Census",
|
||||
"statistics_tab_graphs": "Ledgers",
|
||||
"statistics_tab_rankings": "Standings",
|
||||
"statistics_tab_replay": "Chronicle",
|
||||
"statistics_tab_histories": "Sagas",
|
||||
"statistics_histories_pending": "The hold-scribes have not yet bound these sagas.",
|
||||
"no_history": "No records yet carved.",
|
||||
"no_data": "No tally to report.",
|
||||
"trend_up": "▲",
|
||||
"trend_down": "▼",
|
||||
"trend_flat": "—",
|
||||
"endgame_banner_victory": "Victory!",
|
||||
"endgame_banner_defeat": "The Hold Has Fallen",
|
||||
"endgame_banner_gameover": "The Reckoning",
|
||||
"endgame_reason_LastSurvivor": "Last Clan Standing",
|
||||
"endgame_reason_ConditionMet": "Mastery Achieved",
|
||||
"endgame_reason_TurnLimit": "The Long Age Ends",
|
||||
"endgame_reason_Resigned": "The Banners Are Lowered",
|
||||
"endgame_awards_pending": "The honour-rolls are still being tallied.",
|
||||
"endgame_export_dialog_title": "Inscribe Chronicle to Stone",
|
||||
"endgame_footer_view_map": "Survey the Realm",
|
||||
"endgame_footer_watch_replay": "Recount the Saga",
|
||||
"endgame_footer_save_archive": "Seal to the Vault",
|
||||
"endgame_footer_export_json": "Inscribe to Stone",
|
||||
"outcome_winner": "Victor",
|
||||
"outcome_defeated": "Fallen",
|
||||
"event_tech_researched": "unearthed a new craft",
|
||||
"event_wonder_built": "raised a great work",
|
||||
"combat_grudge_badge": "[Grudge]",
|
||||
"notification_dismiss": "Dismiss",
|
||||
"fmt_boss_tile": "Location: (%d, %d)",
|
||||
|
|
|
|||
|
|
@ -51,6 +51,13 @@ func _ready() -> void:
|
|||
DataLoader.load_theme("age-of-dwarves")
|
||||
ThemeAssets.set_theme("age-of-dwarves")
|
||||
ThemeVocabulary.load_vocabulary("age-of-dwarves")
|
||||
## StatsTracker caches its category labels at autoload-init (before the proof
|
||||
## loads the theme above). Rebuild them now so the Demographics/Graphs/Rankings
|
||||
## column + metric labels resolve to vocabulary copy, not title-case keys.
|
||||
## In-game the theme is loaded before StatsTracker, so this ordering is
|
||||
## proof-only.
|
||||
if _has_node_singleton("StatsTracker") and StatsTracker.has_method("_rebuild_labels"):
|
||||
StatsTracker._rebuild_labels()
|
||||
_seed_fixture()
|
||||
await _run()
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue