Skip to content

Add Idol Deck Sorter tool - #58

Open
12problems wants to merge 2 commits into
mainfrom
idol-deck-sorter
Open

Add Idol Deck Sorter tool#58
12problems wants to merge 2 commits into
mainfrom
idol-deck-sorter

Conversation

@12problems

Copy link
Copy Markdown

What

New tool at /idol-deck-sorter (linked from Tools in the nav): build an arbitrary deck — via a visual card grid or a text box — and see how the modded Idol joker's algorithm would score, sort, and weight it, without needing a real game/seed.

  • Deck builder: 52-card sprite grid, kept live in sync with a text box that accepts either a new hand-typeable shorthand (4x KH-steel-foil, 10H-goldseal, etc.) or the site's existing canonical suit-rank-enh-edition-seal deck string — so a deck copied from a parsed log's View deck can be pasted straight in.
  • Result: reuses the log parser's felt-track visualization (now extracted into a shared IdolRollTrack component so both features stay in sync), plus an interactive roll slider since there's no real seed to draw from, plus a full per-card score table with an expandable breakdown showing every term's equation with the actual numbers plugged in.
  • Algorithm: src/lib/idol-sort.ts is a TypeScript port of reset_idol_card() from TheOrder.lua, built against PR #527's proposed weight changes rather than current dev, since that's confirmed to land. Every weight constant is a single named export with a comment on what PR527 changed, so a future mod tweak is a one-line edit. The algorithm also accepts a full override of every coefficient (IdolSortWeights) so the same deck can be re-simulated against different values — the UI for that is built (weights-panel.tsx) but hidden behind a SHOW_WEIGHTS_PANEL flag in page.tsx for now.

Why the log parser also changed

Two small shared-code extractions so the new tool doesn't duplicate existing logic:

  • idol-hit.tsx's previously-private felt-track components moved to src/components/idol-roll-track.tsx (pure relocation, no behavior change) — both the log parser and the new tool render from the same place now.
  • deck-view.tsx's sprite-atlas positioning moved to src/shared/card-sprite.ts (also pure relocation) so the new deck grid renders pixel-identical card art.
  • deck-utils.ts's ENHANCEMENT_NAMES/EDITION_NAMES/SEAL_NAMES are now exported (were already there, just not exported) so the new deck grid and weights panel can reuse the same display names.

Testing

  • 140 tests (82 new), including a hand-verified fixture checked against the ported formulas by hand before writing it, and a second independent hand-check done live against the running app (matched exactly).
  • bun run typecheck and bunx biome check . clean on every file this PR touches.
  • Verified live in-browser: grid↔text sync in both directions (including pasting a canonical string), format switching, empty/all-stone-deck states, roll slider + score table + expandable equations, and confirmed the log parser's existing Idol Hits section still renders identically after the extraction.

🤖 Generated with Claude Code

12problems and others added 2 commits August 13, 2026 23:25
Lets a user build an arbitrary deck (visual card grid, kept in sync with a
text box that accepts a new hand-typeable shorthand or the site's existing
canonical deck string) and see how the modded Idol joker's algorithm would
score, sort, and weight it, including an interactive roll and a full
per-card score breakdown with the equations plugged in.

- src/lib/idol-sort.ts: TypeScript port of reset_idol_card() from
  Balatro-Multiplayer's TheOrder.lua, built against PR #527's proposed
  weight changes (not yet merged, confirmed to land). Every coefficient is
  bundled into an IdolSortWeights object so it can be overridden and
  re-simulated against the same deck (currently wired through but the
  tuning UI is hidden — see below).
- Extracted src/components/idol-roll-track.tsx out of the log parser's
  idol-hit.tsx (previously private) so both features share one
  implementation of the felt-track visualization instead of duplicating it.
- Extracted src/shared/cards.ts and src/shared/card-sprite.ts (rank/suit
  ordering and sprite-atlas positioning) so the new deck grid renders
  identically to the log parser's deck viewer without a second copy.
- New route at /idol-deck-sorter, linked from the Tools nav menu.

The scoring-weights tuning panel is fully implemented (state, UI, and the
equation breakdown all read live weights) but hidden behind a
SHOW_WEIGHTS_PANEL flag in page.tsx for now — flip it to re-enable, no
other changes needed.

140 tests added/passing, typecheck and biome clean.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
FACE_RANKS in shared/cards.ts wrongly included 'A'. Checked against
Steamodded's actual rank registrations (src/game_object.lua in
Steamodded/smods): Jack, Queen, and King are registered with `face = true`;
Ace gets `nominal = 11` and `face_nominal = 0.4` (sort-order tiebreaking
only) but no `face` flag, so TheOrder.lua's `if rank_obj.face then ...`
check is false for it. Both the ported algorithm and the tool's UI copy
("face (J/Q/K/A)") assumed otherwise.

- FACE_RANKS is now ['J', 'Q', 'K'], with a comment pointing at the source
  so it doesn't regress.
- Fixed the two UI strings that said "(J/Q/K/A)".
- Fixed the hand-verified idol-sort.test.ts fixture, which had an Ace-heavy
  deck and was asserting the buggy 0.055 face bonus / 2.555 total score for
  it — corrected to 0 / 2.5 (the sort order and every other entry's numbers
  were unaffected).
- Added regression coverage: an Ace-skewed deck gets no face bonus, the
  identical shape with Jacks does, Queens/Kings also do, plus a direct
  cards.test.ts asserting FACE_RANKS' exact contents.

Verified live: the same 5x A♠ deck that scored 2.555 now scores 2.500, and
the score breakdown correctly reads "not a face rank (J/Q/K) -> 0" for it.

148 tests passing, typecheck and biome clean.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
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