forge_api.py:
- Split Nightmare Arena into its own action (separate legendary counts, no rate)
- Dwarf-Multi: /player & /player-detail accept names= to union multiple accounts
- Arena/Nightmare leaderboard: "Most legendarys" sort; luckiest/unluckiest now
legendary-per-attempt ratio (no floor, >=1 always beats 0)
forge_stats.js:
- Sub-tabs restructured to Leaderboard (default) + Totals; Item Tables moved under
Totals as "Dwarf" (first); Combine Accounts moved into the lookup
- Combined-account dwarf items are clickable for level distribution
- Nightmare shows legendarys like arena; sort options gated per drop action
app.py:
- VIP backend + Space-side sidecar (vip_lookup.js reads world_10 VIPLeaderboard via
authenticated lookup account), /vip-status + /ingest-vip
index.html:
- VIP badge (no star), Thorns/Freeze formula cards, forge_stats.js cache bump
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
5 days ago
forge_api: periodic forge-DB hot-reload (no restart needed)
The DB connection was cached for the whole process, so a freshly uploaded
forge_stats.db only showed up after a Space restart -> forge/actions could
look stale for a long time. Now _conn() checks every ~30min (FORGE_DB_RELOAD_TTL)
whether the dataset has a new revision and, if so, a background thread downloads
it and atomically swaps the connection + invalidates the DB-derived caches.
No request blocks; the old DB serves until the swap and closes by refcount.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
6 days ago
forge stats: bind to account id across renames (aggregate over username+aliases)
Forge/elf/enhance/etc. stats were keyed by player NAME (the compact DB's player_id
is just a name index), so a rename split a player's history. Now the player view
resolves the looked-up name -> the account's full name set (current username +
leaderboard aliases, same resolver the power-series uses) and aggregates
player_action / player_detail / luck across all those local ids. Rename-proof and
id-bound, matching the power/level/gold history. Unknown/not-on-leaderboard names
fall back to single-name (unchanged). app.py injects the resolver into forge_api
(no circular import). Verified on the live compact DB: single lookup unchanged,
two-name aggregation sums exactly, luck+detail OK.
Known follow-up: the /forge/leaderboard ranking tab still ranks per name (a renamed
player can appear twice); grouping the whole board by id is a separate change.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Reworked the forge lucky/unlucky to match how players think about it,
all computed per-player in forge_api at query time (no DB rebuild):
- Per-action LUCK = percent over/under expected, shown ONLY for dwarf,
elf, pet_enhance (there the odds are clean; dwarf/elf via the logged
luck% incl. Fortune, pet via per-pet rate). smelt/enchant/downgrade
get no luck chip -- their odds depend on free/paid & player level
which the logs don't record. arena shows only the legendary count.
- VALUE per action (dwarf/elf/pet) + the OVERALL "lucky/unlucky" is now
value-weighted over dwarf+elf+pet: realized vs expected value, input
always lost, output only on success (dwarf -> item L+1, elf -> the
legendary L1, pet -> the XPet). Elf is included. Weighted so a failed
expensive elf/L9 legendary dominates and cheap noise doesn't.
- New forge_prices.json (bundled price snapshot) + ELF/PET recipes let
the API price the value swings without a price service. Global bucket
rates cached from…
Two fixes to the forge lucky/unlucky calculation:
1) Per-action luck for smelt/enchant/downgrade/pet was expected =
attempts x GLOBAL rate, but success depends on the bucket (smelt:
ore 20-70%, enchant: type, ...). A Coal-heavy smelter looked "+50
lucky" purely from ore mix. Now bucket-standardized (like dwarf's
per-rarity/level), in build_stats.py -- pure selection bias removed.
2) The combined score pooled dwarf/elf/pet/arena as an equal statistical
z-score, ignoring stakes. Now VALUE-weighted: per event contribution =
stake x (outcome - p), pooled Z = sum / sqrt(sum stake^2 p(1-p)).
Stake = coins at risk: dwarf=item@level, elf=10x input@L5-epic,
pet=10x normal-pet, arena=avg legendary value. A failed L9 legendary
or burned elf dominates; cheap smelts are noise.
forge_api is backward-compatible: falls back to the old count-based
overall when the DB lacks the new vluck_num/vluck_var columns, so the
forge tab keeps working until the rebuilt DB is uploaded.…