gabraken commited on
Commit
b8912e3
·
1 Parent(s): c5be6f3

Store results

Browse files
Files changed (2) hide show
  1. backend/main.py +23 -6
  2. backend/stats.py +6 -2
backend/main.py CHANGED
@@ -49,7 +49,7 @@ from fastapi.middleware.cors import CORSMiddleware
49
  from fastapi.staticfiles import StaticFiles
50
  from fastapi.responses import FileResponse
51
 
52
- from game.bot import BOT_PLAYER_ID, BotPlayer
53
  from game.commands import ActionType
54
  from game.engine import GameEngine
55
  from game.map import MAP_LANDMARKS
@@ -75,16 +75,33 @@ log = logging.getLogger(__name__)
75
 
76
  def _record_game_over(room, winner_id: str, winner_name: str) -> None:
77
  """Persist stats for tutorial completion or PvP win."""
78
- # Never record a bot or tutorial dummy win in the leaderboard
79
- if winner_id in (BOT_PLAYER_ID, TUTORIAL_DUMMY_ID):
80
  return
81
  import time as _time
82
  duration = int(_time.time() - room.started_at) if room and room.started_at else None
83
  engine = engines.get(room.room_id) if room else None
84
  is_tutorial = bool(engine and engine.state.is_tutorial) if engine else False
85
  event_type = "tutorial_complete" if is_tutorial else "game_won"
86
- # Resolve opponent name for PvP matches
87
- opponent_name: str | None = None
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
88
  if not is_tutorial and engine:
89
  for pid, pstate in engine.state.players.items():
90
  if pid != winner_id and pid != BOT_PLAYER_ID:
@@ -92,7 +109,7 @@ def _record_game_over(room, winner_id: str, winner_name: str) -> None:
92
  break
93
  # If opponent was the bot, label it
94
  if opponent_name is None and any(pid == BOT_PLAYER_ID for pid in engine.state.players):
95
- opponent_name = "Bot"
96
  try:
97
  _stats.record(winner_name, event_type, duration, opponent_name)
98
  log.info("Stat recorded: %s %s vs %s %ss", winner_name, event_type, opponent_name, duration)
 
49
  from fastapi.staticfiles import StaticFiles
50
  from fastapi.responses import FileResponse
51
 
52
+ from game.bot import BOT_PLAYER_ID, BOT_PLAYER_NAME, BotPlayer
53
  from game.commands import ActionType
54
  from game.engine import GameEngine
55
  from game.map import MAP_LANDMARKS
 
75
 
76
  def _record_game_over(room, winner_id: str, winner_name: str) -> None:
77
  """Persist stats for tutorial completion or PvP win."""
78
+ # Never record tutorial dummy wins
79
+ if winner_id == TUTORIAL_DUMMY_ID:
80
  return
81
  import time as _time
82
  duration = int(_time.time() - room.started_at) if room and room.started_at else None
83
  engine = engines.get(room.room_id) if room else None
84
  is_tutorial = bool(engine and engine.state.is_tutorial) if engine else False
85
  event_type = "tutorial_complete" if is_tutorial else "game_won"
86
+
87
+ # When the bot wins, record the match with the human opponent so it appears
88
+ # in match history — bot wins are excluded from the leaderboard in stats.py
89
+ if winner_id == BOT_PLAYER_ID:
90
+ opponent_name: str | None = None
91
+ if engine:
92
+ for pid, pstate in engine.state.players.items():
93
+ if pid != BOT_PLAYER_ID:
94
+ opponent_name = pstate.player_name
95
+ break
96
+ try:
97
+ _stats.record(BOT_PLAYER_NAME, event_type, duration, opponent_name)
98
+ log.info("Stat recorded: %s %s vs %s %ss", BOT_PLAYER_NAME, event_type, opponent_name, duration)
99
+ except Exception:
100
+ log.exception("Failed to record stat")
101
+ return
102
+
103
+ # Resolve opponent name for PvP/bot matches
104
+ opponent_name = None
105
  if not is_tutorial and engine:
106
  for pid, pstate in engine.state.players.items():
107
  if pid != winner_id and pid != BOT_PLAYER_ID:
 
109
  break
110
  # If opponent was the bot, label it
111
  if opponent_name is None and any(pid == BOT_PLAYER_ID for pid in engine.state.players):
112
+ opponent_name = BOT_PLAYER_NAME
113
  try:
114
  _stats.record(winner_name, event_type, duration, opponent_name)
115
  log.info("Stat recorded: %s %s vs %s %ss", winner_name, event_type, opponent_name, duration)
backend/stats.py CHANGED
@@ -87,8 +87,11 @@ def get_tutorial_leaderboard(limit: int = 50) -> list[dict]:
87
  return [dict(r) for r in rows]
88
 
89
 
 
 
 
90
  def get_wins_leaderboard(limit: int = 50) -> list[dict]:
91
- """Most 1v1 wins, ordered by win count then best time."""
92
  with _connect() as conn:
93
  rows = conn.execute(
94
  """
@@ -98,11 +101,12 @@ def get_wins_leaderboard(limit: int = 50) -> list[dict]:
98
  MAX(recorded_at) AS last_at
99
  FROM player_stats
100
  WHERE event_type = 'game_won'
 
101
  GROUP BY player_name
102
  ORDER BY wins DESC, best_s ASC NULLS LAST
103
  LIMIT ?
104
  """,
105
- (limit,),
106
  ).fetchall()
107
  return [dict(r) for r in rows]
108
 
 
87
  return [dict(r) for r in rows]
88
 
89
 
90
+ _BOT_PLAYER_NAME = "Bot IA"
91
+
92
+
93
  def get_wins_leaderboard(limit: int = 50) -> list[dict]:
94
+ """Most 1v1 wins, ordered by win count then best time. Bots are excluded."""
95
  with _connect() as conn:
96
  rows = conn.execute(
97
  """
 
101
  MAX(recorded_at) AS last_at
102
  FROM player_stats
103
  WHERE event_type = 'game_won'
104
+ AND player_name != ?
105
  GROUP BY player_name
106
  ORDER BY wins DESC, best_s ASC NULLS LAST
107
  LIMIT ?
108
  """,
109
+ (_BOT_PLAYER_NAME, limit),
110
  ).fetchall()
111
  return [dict(r) for r in rows]
112