feat: NTE gear optimizer web app
Client-side optimizer for Neverness to Everness console builds. Imports a gear export from nte-history-exporter, keeps it in IndexedDB, and solves for the best module placement per character or across a team. - domain/: pure ports of the Python research scripts (shapes, cartridges, board tiling, stats, scoring, set bonuses, Arc effects, sheet prediction). No DOM, no storage imports, so they stay worker-safe and Node-testable. - solver/: single-character solve with branch and bound, plus a three-phase team solve (portfolio, leximin, column generation) over disjoint item sets. Runs in a Worker when one can be constructed, inline otherwise. - db/: three storage tiers selected by use rather than feature detection, fail-closed import validation, and undo that restores both sides of a steal. - ui/: React 19 views for items, characters and teams; the board is drawn as the deliverable rather than a score. - Two build targets: a hosted bundle and a single self-contained nte.html with no external requests. Values the model cannot measure are reported as unavailable rather than guessed: cartridge set bonuses, the level 80 base-stat multiplier, and the distinction between "optimal for this packing" and globally optimal. 145 tests, tsc clean, both build targets clean. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
commit
91952b1745
157 changed files with 92600 additions and 0 deletions
58
README.md
Normal file
58
README.md
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
# nte-optimizer
|
||||
|
||||
Gear optimizer for *Neverness to Everness*. Static site, no server, no account.
|
||||
|
||||
It imports the JSON that [`nte-exporter`](../nte-exporter) writes during a normal
|
||||
capture run, and recommends what to equip on whom — drawn onto each character's
|
||||
console grid.
|
||||
|
||||
## Running it
|
||||
|
||||
```sh
|
||||
npm ci
|
||||
npm run dev # development
|
||||
npm run build # dist/index.html — the normal build
|
||||
npm run build:single # dist/nte.html — one file, works over file://
|
||||
npm test
|
||||
```
|
||||
|
||||
`dist/` is **committed on purpose**. In three years, when `npm ci` fails on some
|
||||
transitive native module, `python3 -m http.server -d dist` will still work. The
|
||||
source build is the convenience; the committed output is the artifact.
|
||||
|
||||
## Layout
|
||||
|
||||
| path | what lives there |
|
||||
|---|---|
|
||||
| `data-src/` | raw everness mirrors, Arc classifications, guide data. Committed, not shipped. |
|
||||
| `tools/` | build-time scripts. Output goes to `src/generated/`, also committed. |
|
||||
| `src/domain/` | **pure.** No DOM, no IndexedDB, no imports from `ui/`, `db/` or `state/`. |
|
||||
| `src/solver/` | same rule. Chunked generators, so they run in a worker or inline unchanged. |
|
||||
| `src/db/` | schema, migrations, import, persistence adapters. |
|
||||
| `src/ui/` | React. Four tabs and a hash router. |
|
||||
|
||||
The `domain/` and `solver/` rule is what makes them worker-safe, Node-testable
|
||||
and diffable against the Python they were ported from. Keep it.
|
||||
|
||||
## Two things that are easy to get wrong
|
||||
|
||||
**Ported rules were expensive to derive and break in ways that still look
|
||||
plausible.** Before touching anything in `domain/`, read
|
||||
`~/Apps/nte-research/WIREFORMAT.md` and the "facts worth not re-deriving"
|
||||
section of `RESUME.md`. Builds are 6, 7 or 8 modules and never always 7; the
|
||||
console trait is not always CRIT DMG or Type III; a transposed board renders
|
||||
correctly on a symmetric grid.
|
||||
|
||||
**The model has measured gaps, and the app is built to show them rather than
|
||||
hide them.** Set bonus values are unknown and contribute nothing. The base-stat
|
||||
multiplier has never been read at level 80. A `proven` build is optimal for its
|
||||
packing and cartridge, not globally. Every one of those is surfaced in the UI on
|
||||
purpose — if you find yourself replacing one with a plausible number, don't.
|
||||
|
||||
## Degraded modes
|
||||
|
||||
Opening `dist/nte.html` from the filesystem gives the page an opaque origin, so
|
||||
IndexedDB, workers, `fetch` and module scripts are all unavailable. The app
|
||||
handles this behind two interfaces it never sees through — `PersistenceAdapter`
|
||||
(IndexedDB → localStorage → memory) and `SolverHost` (worker → inline) — and
|
||||
shows a banner when storage is not durable. Artwork is not carried in that build.
|
||||
Loading…
Add table
Add a link
Reference in a new issue