Prediction hero now shows ranked TOP PICK and 2ND PICK with EV per unit
bet (P(win)*2.9 - 1). Bet Size Advisor panel shows Kelly criterion
fraction (capped 25%), best chair with confidence, and historical bet
rank insight (how often lowest/highest-bet chair wins).
Live Market Sentiment section tracks whale trend (top 5 bettors by amount)
and public trend (total pool distribution) in real-time via WebSocket,
mirroring the live dashboard. Notes highlight agreement/divergence between
model pick and crowd favorite.
Historical crowd analysis cards show how often the most-bet, mid-bet, and
least-bet chairs actually won across all games.
Round result flash now includes whale/public pick accuracy alongside the
model prediction result. user_bet WebSocket events are tracked to build
per-round bettor profiles for whale analysis.
- WebSocket connection shows live game state (round #, phase, bets per
chair, pot) in a persistent bar at the top of predictions page
- Prediction cards now display current bet amounts per chair
- Round results flash HIT/MISS against the Bayesian prediction
- New "Last 20 Predictions vs Actual" table with per-game probabilities,
predicted vs actual winner, and running accuracy
- Predictions auto-refresh after each round ends
- Fix winning cards chart: use taller container (480px) and dedicated
scales config for horizontal bar rendering
- Add _last_n_predictions() helper to db.py for detailed per-game
prediction history with game numbers
Bayesian next-chair predictor (Markov chains, base rate, streak regression),
statistical tests (chi-squared, runs test, autocorrelation), theory
backtesting with rolling accuracy, and card-level analysis (value/suit
distribution, face card frequency, top winning cards).
New /patterns page with 9 analyses: chair win bias, bet rank
correlations, hand type distributions, pot size buckets, streaks,
hourly patterns, and recent-vs-overall comparison. Also adds a
standalone analyze.py CLI script for terminal output.
CHAIRS mapping was {1:A, 2:B, 3:C} but the API's country field has
1=C and 3=A. Fixed the mapping in backend and both frontends, added a
startup migration to swap A↔C columns in existing DB data, corrected
multiIf SQL queries that hardcoded the wrong winner→column mapping,
and moved _save_round() to the ENDED status block so hot/cold stats
reflect the latest round immediately.