add real-time game data, prediction history, and fix winning cards chart

- 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
This commit is contained in:
2026-02-25 23:25:49 +05:00
parent b07b073cc0
commit 4903b6943a
2 changed files with 302 additions and 25 deletions

View File

@@ -1217,14 +1217,39 @@ def _backtest_theories(winners):
}
def _last_n_predictions(winners, n=20):
"""Get detailed prediction vs actual for the last N games."""
warmup = 30
if len(winners) <= warmup:
return []
start = max(warmup, len(winners) - n)
results = []
for i in range(start, len(winners)):
history = winners[:i]
actual = winners[i]
m1, _ = _markov_matrix_1(history)
m2, _ = _markov_matrix_2(history)
pred, _ = _bayesian_prediction(history, m1, m2)
predicted = max(CHAIR_LABELS, key=lambda c: pred[c])
results.append({
"index": i,
"predicted": predicted,
"actual": actual,
"correct": predicted == actual,
"probs": {c: round(pred[c], 4) for c in CHAIR_LABELS},
})
return results
@_with_lock
def get_prediction_analysis() -> dict:
"""Run all prediction/game-theory analysis and return results."""
client = get_client()
# Query 1: Full winner sequence
result = client.query("SELECT winner FROM games ORDER BY game_no ASC")
winners = [config.CHAIRS.get(r[0], "?") for r in result.result_rows]
# Query 1: Full winner sequence with game numbers
result = client.query("SELECT game_no, winner FROM games ORDER BY game_no ASC")
game_nos = [r[0] for r in result.result_rows if config.CHAIRS.get(r[1], "?") in CHAIR_LABELS]
winners = [config.CHAIRS.get(r[1], "?") for r in result.result_rows]
winners = [w for w in winners if w in CHAIR_LABELS] # filter unknowns
# Query 2: Card data for last 500 games
@@ -1252,6 +1277,13 @@ def get_prediction_analysis() -> dict:
# Backtesting
backtest = _backtest_theories(winners)
# Last 20 prediction vs actual
last_20_raw = _last_n_predictions(winners, 20)
# Attach game_nos to last_20
for entry in last_20_raw:
idx = entry["index"]
entry["game_no"] = game_nos[idx] if idx < len(game_nos) else 0
# Card analysis
card_values = _card_value_distribution(cards_data)
face_cards = _face_card_frequency(cards_data)
@@ -1261,6 +1293,7 @@ def get_prediction_analysis() -> dict:
return {
"total_games": len(winners),
"last_winners": winners[-10:] if len(winners) >= 10 else winners,
"last_20_predictions": last_20_raw,
"prediction": prediction,
"signals": signals,
"markov1": {"matrix": markov1, "counts": {k: dict(v) for k, v in markov1_counts.items()}},