Stats
Screen states, calculation rules, data sources, and progress behavior for repertoire analysis.
Purpose and access
Stats evaluate a saved study against a selected pool of real games. The studied side is assumed to remember and always play its prepared move. Opponent replies are weighted by their frequency in the selected Lirep or Lichess Explorer source.
Both the Stats list and detail page require Lichess sign-in. Show a sign-in prompt when signed out and “Study not found” when a requested ID is unavailable to the account.
Stats list
- Load the account's studies. When there are none, show empty White and Black opening groups.
- Group study cards by studied side. Each card shows the study name, side, opening moves, and expected score as a percentage (or a dash if not calculated).
- Every card links to its study detail page, including cards without a calculated score. Calculations are started from the detail page; the list has no Calculate/Recalculate button or job sequence.
Study detail screen
Open at stat.html?id={studyId}. Show the tier badge and legend toggle, study name, and Playing White/Black badge. Show win probability, expected evaluation, and practice knowledge cards, then calculation actions, Explorer settings, and coverage chart. Win probability, expected evaluation, and coverage identify a custom starting point when set.
Metric cards
- Win probability shows win and loss percentages (draws are the remainder), plus expected score: a win = 1, draw = 0.5, loss = 0, from the studied side's perspective. Include source, evaluated-position count, and timestamp. The expected-score tier badge is gold at 60%+, silver at 55%+, bronze at 50%+, and below breakeven under 50%.
- Expected evaluation at the end of prep is a weighted Stockfish score in pawns from the studied side's POV, formatted to two decimals with a sign. Display forced-mate labels for capped mate values and calculation time. If end positions lacked an engine evaluation, they contribute 0.00 and the card states how many misses occurred. Older server-calculated summaries are marked as legacy until recalculated locally.
- Practice knowledge shows average recall across positions, or an empty state if there is no practice data. Empty calculation metrics show a dash and “Not calculated yet.” The tier legend explains score thresholds.
Calculation definitions
Expected score and coverage
These are exclusively Opening Explorer-derived; never approximate them with engine scores. Walk from the effective starting node. At a studied-side turn, follow its sole prepared child. If preparation ends on the studied side's turn, use that position's Explorer W/D/L score as a neutral fallback. At an opponent turn, fetch that position's move list and weight each listed move by its game count divided by the total listed games. Recurse through prepared replies; for a reply absent from the tree, use that move's own W/D/L result from Explorer and stop that branch. A terminal result inside the tree is exact (win 1, draw .5, loss 0). If there are no Explorer games, use neutral expected score .5.
Coverage tracks probability mass that remains inside the tree under the same opponent move weights. Start at 1.0. Studied-side moves preserve mass; opponent moves split it by frequency; mass on an unprepared reply exits the book. Record the remaining mass after each opponent move. Thus coverage can only drop on opponent replies. The tooltip also reports the number of tree moves/branches represented at that depth, a structural count rather than a weighted count.
Expected evaluation
Use the same weighted tree walk and studied-side perfect-play assumption, but assign leaves an engine evaluation. When an opponent reply leaves the tree, evaluate the resulting position and weight it by that reply's real frequency. If a studied-side leaf or position with no usable Explorer games is reached, evaluate the current position. Checkmate is represented by ±100,000 centipawns; draws are 0. Store evaluations in White's POV, then convert to the studied side's POV for the result. Display cp as pawns (cp / 100).
Explorer move lists are capped by Lichess (roughly the top dozen moves), so rare omitted moves are not separately modeled. A custom start node changes the calculation root only; it does not trim or renumber the tree. Coverage move numbers are relative to that start node and the chart identifies which opponent move each point follows.
Three independent actions
Update evaluations
This browser action discovers only the FENs required at the frontier of the expected-evaluation walk, starting at the effective starting node. Follow prepared moves and fetch opponent replies via /api/explorer. The frontier includes nonterminal studied-side leaves, opponent positions with no listed games, and positions after unprepared opponent replies; terminal positions need no engine score. Reuse this account's cached FEN evaluations on this device and run local Stockfish only for missing FENs. Store each completed White-POV centipawn value in browser IndexedDB immediately, so interrupted runs can resume. Do not analyze unrelated tree nodes or save new evaluations to the backend.
Show “Finding required positions…” while walking the tree and Explorer, then show how many of the required positions are already available and how many need calculation. Show exact progress for remaining engine work and report “Already up to date” when there is none.
Update win probability
Start a backend job that calculates expected score and coverage from Explorer data. It does not call Stockfish or Cloud Eval. Save only its fields and timestamp, independently of expected evaluation. Explorer lookups use a persistent cross-study cache with a 24-hour TTL.
Update expected evaluation
In the browser, discover and evaluate any missing frontier FENs using the same local flow as Update evaluations, then perform the Explorer-weighted tree walk locally. It works without running Update evaluations first. A position without a usable engine score contributes 0.00 and is counted in evalMisses; there is no Cloud Eval fallback. Send only evalCp, evalMisses, and the selected explorerSettings to synchronous POST /api/studies/{id}/expected-eval. The backend saves the study summary and settings, not per-position evaluations; it runs neither an engine nor a job for this action.
Each detail-page action runs independently and updates its own result/timestamp without clearing the other. All three action buttons are disabled while any one runs. Only the win-probability action starts a backend job: poll GET /api/jobs/{jobId} about every 400 ms, estimating progress from tree size because the actual total is unknown. The two local actions show discovery and then exact engine-work progress. On failure, show the message beside the relevant bar and re-enable the actions.
Explorer settings
Show the study's editable settings on the detail page, including Lirep/Lichess data source. Lirep uses its local rated-game archive and has no Masters database; Lichess offers Players and Masters. Changing the controls alone does not trigger calculation. The next win-probability or expected-evaluation action sends the selected settings and saves them as the study's new settings (not a temporary preview), so subsequent views and calculations use them.
- Players or Masters database. Masters disables rating and speed controls.
- For Players, select a fixed rating threshold; that bucket and every higher bucket are included. A new study's picker starts pre-selected at the signed-in player's own bracket (Reference rating order Rapid, Blitz, Classical; default 1500 if unrated), but it's a one-time default like any other saved setting, not a mode that keeps tracking the player's rating.
- Bullet, Blitz, Rapid, and Classical checkboxes; default to Blitz, Rapid, Classical, and always require at least one speed.
Coverage chart and caching
Render a responsive line chart with percentage on the vertical axis and the studied opponent's move number on the horizontal axis. Hovering near the line shows opponent move number, coverage percentage, and number of remembered moves at that depth. If no coverage is stored, show an explanatory empty state and require recalculation to populate it.
Explorer responses and per-user rating buckets persist in backend SQLite across restarts; Explorer responses are shared across studies/accounts for identical queries and expire after 24 hours. Engine evaluations are keyed by username and FEN in browser IndexedDB, per account and per device, not synced. Clearing browser data forces recomputation; when IndexedDB is unavailable (including private modes that block it), evaluations last only for the current page/tab visit. On loading a study, legacy server-side evals.byNode values are imported into the local FEN cache where absent. An older database may still contain the unused cloud_eval_cache table, but new databases do not create it. The /api/studies/{id}/evals and /api/eval-cache/lookup endpoints have been removed. Backend win-probability job progress is in-memory and does not survive a process restart. Live Explorer 429 errors fail fast with a wait-a-minute message.
Interpretation and limits
- Expected score reports game results, not engine quality. It can disagree with expected evaluation; this is intentional.
- All results assume perfect memorization and one prepared move at each studied-side decision. They do not model mistakes by the user.
- Opponent frequencies reflect the selected current pool, not move quality. Sparse data, capped move lists, and changes in current ratings affect estimates.
- Local Stockfish is fixed-depth and runs on the user's device. Missing local evaluations contribute 0 and are reported; no Cloud Eval fallback is used.
- Recalculation is manual because Explorer requests and local engine searches may take time. Update win probability and Update expected evaluation persist selected Explorer settings; Update evaluations uses the current selection only to discover frontier positions.