feat: AI-game refinements (GCG, your_turn, admin, metrics)
CI / changes (pull_request) Successful in 2s
CI / unit (pull_request) Successful in 9s
CI / integration (pull_request) Successful in 13s
CI / ui (pull_request) Successful in 49s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 1m7s
CI / changes (pull_request) Successful in 2s
CI / unit (pull_request) Successful in 9s
CI / integration (pull_request) Successful in 13s
CI / ui (pull_request) Successful in 49s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 1m7s
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").
This commit is contained in:
@@ -101,15 +101,22 @@ func phaseOf(moveCount int) string {
|
||||
}
|
||||
}
|
||||
|
||||
// recordStarted counts one started game of variant.
|
||||
func (m *gameMetrics) recordStarted(ctx context.Context, v engine.Variant) {
|
||||
m.started.Add(ctx, 1, variantAttr(v))
|
||||
// recordStarted counts one started game of variant, split by whether it is an
|
||||
// honest-AI game (the vs_ai attribute), so AI and human games chart separately.
|
||||
func (m *gameMetrics) recordStarted(ctx context.Context, v engine.Variant, vsAI bool) {
|
||||
m.started.Add(ctx, 1, gameKindAttr(v, vsAI))
|
||||
}
|
||||
|
||||
// recordAbandoned counts one seat dropped by the turn-timeout sweeper in a game of
|
||||
// variant.
|
||||
func (m *gameMetrics) recordAbandoned(ctx context.Context, v engine.Variant) {
|
||||
m.abandoned.Add(ctx, 1, variantAttr(v))
|
||||
// variant, split by the vs_ai attribute (an AI game's abandon is the 7-day rule).
|
||||
func (m *gameMetrics) recordAbandoned(ctx context.Context, v engine.Variant, vsAI bool) {
|
||||
m.abandoned.Add(ctx, 1, gameKindAttr(v, vsAI))
|
||||
}
|
||||
|
||||
// gameKindAttr is the (variant, vs_ai) attribute set shared by the started and
|
||||
// abandoned counters so AI and human games are split on the same labels.
|
||||
func gameKindAttr(v engine.Variant, vsAI bool) metric.MeasurementOption {
|
||||
return metric.WithAttributes(attribute.String("variant", v.String()), attribute.Bool("vs_ai", vsAI))
|
||||
}
|
||||
|
||||
// variantAttr is the shared "variant" attribute option, usable for both Record and
|
||||
|
||||
Reference in New Issue
Block a user