View models
Every display derivation in one place — labels, ordering, colors, and the 169-class math.
src/lib/api/view-model.ts (postflop) and preflop-view-model.ts (preflop)
turn wire documents into view objects. Components render view objects and
never see wire shapes — so every derivation exists exactly once.
Action colors
ACTION_COLORS in view-model.ts is the single palette for the whole
product:
| Token | Hex | Used for |
|---|---|---|
| fold | #3d72d9 | Fold |
| passive | #3aa657 | Check, call |
| betSm | #e56a4b | Bets < 45% pot |
| betLg | #cc3d31 | Bets 45–90% pot |
| betXl | #93261f | Bets ≥ 90% pot, jams, all-in |
Postflop picks the bet tint from fraction_pot. Preflop tints raises by
escalation level along the line — first raise betSm, 3-bet betLg,
4-bet and beyond (and all-ins) betXl — since preflop raise sizes are
raise-to totals, not pot fractions.
Display order
actionDisplayOrder sorts actions for every bar, matrix cell, and summary:
biggest bet leftmost, then smaller bets, then check/call, fold always at
the right edge. The matrix paints cell bands in this order, so the blue
fold band consistently anchors the right side of every cell.
Labels
actionLabel:Fold,Check,Call 1.5,Bet 28.4 (55%),Raise 4.6 (50%),All-in 100— amounts at one decimal unless a second is significant.- Preflop sizes trim trailing zeros (
r2.3→ "Raise 2.3",r25→ "Raise 25"). - Line labels:
limp→ "Limped pot",srp/srp_btn_bb→ "Single-raised pot" (with the BTN-vs-BB / SB-vs-BB qualifier preflop-side),3bp/3bet_call→ "3-bet pot",4bp/4bet_call→ "4-bet pot",5bet_call→ "5-bet pot".
The 169-class math
src/lib/api/aggregate.ts holds the combinatorics; src/lib/poker/classes.ts
the grid layout:
comboClassmaps a combo id to its class ("AhKh"→"AKs").- Class capacity: pair 6, suited 4, offsuit 12 combos; a full range is 1326.
buildGrid169mirrors the server aggregation exactly (reach-weighted means) — used only for mock data; when a live document is present its server-sentgrid169is authoritative and never recomputed.- Class view numbers:
combos= summed reach weight;weight= share of the class's live combos;rangePct= total combos ÷ 1326.
Postflop node view (toNodeView)
Derives the strategy-browser screen: per-class view strategies with
perCombo drilldowns, range-wide action frequencies and combo counts
(reach-weighted), the facing-bet detection for the pot-odds readout
(pot odds bet/(pot+2·bet), MDF pot/(pot+bet), SPR eff/pot), and
ipWeightsUniform (from meta.ip_weights_uniform, defaulting to true for
tier root).
Preflop screen assembly (assemblePreflopScreen)
The preflop view model walks the line through the pack:
- Start at
rootwith each seat's full range. - At each step, fold the acting seat's arriving range through the strategy
of the action it took (
range × frequencyper class) — so every seat's displayed range is the exact product of its taken-action frequencies. - Track raise escalation for color assignment, accumulate breadcrumb steps, and stop at a decision node or terminal.
- At terminals, resolve the boundary (if heads-up) and both arriving ranges.
It also drives implied-fold navigation: clicking a later seat's action
prepends the intermediate fold tokens to the line.
URL state helpers live here too: preflopHref(depth, line) and the
"" ⇄ "root" line/node_path conversion.
Formatting
src/lib/utils.ts: percentages at one decimal (16.9%), combo counts at one
decimal (223.5), bb amounts as 5.0bb. The app body sets
font-variant-numeric: tabular-nums so every figure aligns.