From d2a944128792ee37ae6792d3301a14acbd5b1ec2 Mon Sep 17 00:00:00 2001 From: Ilia Denisov Date: Mon, 15 Jun 2026 20:49:49 +0200 Subject: [PATCH] feat: AI-game refinements (GCG, your_turn, admin, metrics) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Follow-ups on the honest-AI game, same PR: - GCG export labels the robot seat "AI" instead of its pool name (ExportGCG overrides via accounts.IsRobot); the in-app 🤖 is unchanged. - vs_ai games emit no your_turn (the robot replies instantly, so it would be redundant); opponent_moved still advances the UI. - Admin console shows the AI flag: a 🤖 column in /games and an "AI game" line on the game card (GameRow/GameDetailView gain VsAI). - games_started_total / games_abandoned_total gain a vs_ai attribute; the Grafana Game-domain dashboard splits started/abandoned into human and AI panels. Tests: metrics unit (vs_ai split); integration (no your_turn, GCG "AI"). --- PRERELEASE.md | 8 ++ .../templates/pages/game_detail.gohtml | 1 + .../adminconsole/templates/pages/games.gohtml | 6 +- backend/internal/adminconsole/views.go | 6 +- backend/internal/game/metrics.go | 19 +++-- backend/internal/game/metrics_test.go | 24 +++--- backend/internal/game/service.go | 30 +++++--- backend/internal/game/types.go | 8 +- backend/internal/inttest/ai_game_test.go | 75 +++++++++++++++++++ .../internal/server/handlers_admin_console.go | 4 +- deploy/grafana/dashboards/game-domain.json | 20 +++-- docs/ARCHITECTURE.md | 6 +- 12 files changed, 166 insertions(+), 41 deletions(-) diff --git a/PRERELEASE.md b/PRERELEASE.md index 6c6365e..d0b81dc 100644 --- a/PRERELEASE.md +++ b/PRERELEASE.md @@ -503,3 +503,11 @@ Then Stage 18. - **Schema/wire change → a contour DB wipe** after merge (`DROP SCHEMA backend CASCADE` + restart, the R1/R3 pattern). Bake-back: `docs/ARCHITECTURE.md`, `docs/FUNCTIONAL.md` (+`_ru`), `docs/UI_DESIGN.md`, `backend/README.md`, Go Doc comments. + - **Post-review refinements (owner, same PR):** (1) the **GCG export labels the robot seat "AI"** rather + than its human-like pool name (`ExportGCG` overrides the name via `accounts.IsRobot`; the in-app 🤖 is + unchanged); (2) honest-AI games **emit no `your_turn`** — the robot replies instantly, so the signal + would arrive with the move and be pointless; `opponent_moved` still advances the UI; (3) the **admin + console surfaces the AI flag** — a **🤖 column** in `/games` and an "AI game" line on the game card + (`GameRow`/`GameDetailView` gain `VsAI`); (4) `games_started_total` / `games_abandoned_total` gain a + **`vs_ai`** attribute and the Grafana *Game domain* dashboard splits started/abandoned into **human** + and **AI** panels. diff --git a/backend/internal/adminconsole/templates/pages/game_detail.gohtml b/backend/internal/adminconsole/templates/pages/game_detail.gohtml index 068b1a6..08316b1 100644 --- a/backend/internal/adminconsole/templates/pages/game_detail.gohtml +++ b/backend/internal/adminconsole/templates/pages/game_detail.gohtml @@ -7,6 +7,7 @@
  • Variant {{.Variant}}
  • Dictionary {{.DictVersion}}
  • Status {{.Status}}{{if .EndReason}} ({{.EndReason}}){{end}}
  • +
  • AI game {{if .VsAI}}🤖 yes{{else}}no{{end}}
  • Players {{.Players}}
  • To move seat {{.ToMove}}
  • Moves {{.MoveCount}}
  • diff --git a/backend/internal/adminconsole/templates/pages/games.gohtml b/backend/internal/adminconsole/templates/pages/games.gohtml index 4a958fd..e6ab08e 100644 --- a/backend/internal/adminconsole/templates/pages/games.gohtml +++ b/backend/internal/adminconsole/templates/pages/games.gohtml @@ -8,11 +8,11 @@ finished - + {{range .Items}} - -{{else}}{{end}} + +{{else}}{{end}}
    GameVariantStatusPlayersUpdated
    GameVariantStatus🤖PlayersUpdated
    {{.ID}}{{.Variant}}{{.Status}}{{.Players}}{{.UpdatedAt}}
    no games
    {{.ID}}{{.Variant}}{{.Status}}{{if .VsAI}}🤖{{end}}{{.Players}}{{.UpdatedAt}}
    no games