Stage 17 round 5 (L2): robot play-to-win intent + next-move ETA in the admin game card
CI / changes (pull_request) Successful in 2s
CI / unit (pull_request) Successful in 8s
CI / integration (pull_request) Successful in 11s
CI / ui (pull_request) Successful in 29s
CI / gate (pull_request) Successful in 1s
CI / deploy (pull_request) Successful in 1m14s
CI / changes (pull_request) Successful in 2s
CI / unit (pull_request) Successful in 8s
CI / integration (pull_request) Successful in 11s
CI / ui (pull_request) Successful in 29s
CI / gate (pull_request) Successful in 1s
CI / deploy (pull_request) Successful in 1m14s
The admin game detail now shows, per robot seat, the game's deterministic play-to-win decision (from the bag seed) and — while it is that robot's turn — its scheduled next-move ETA (sampled think-time delay, deferred past the sleep window), plus a caption with the ~40% global target. Wiring: robot.PlayToWin/NextMoveAt/PlayToWinTargetPercent exports, account.IsRobot, game RobotSchedule (seed + turn-start). Tests: NextMoveAt invariants (never early, never in the sleep window), PlayToWin export, and an admin render integration test asserting the intent + ETA + target appear.
This commit is contained in:
@@ -34,6 +34,19 @@ type UserFilter struct {
|
||||
// robotExists is the correlated subquery testing whether account a is a robot.
|
||||
const robotExists = `EXISTS (SELECT 1 FROM backend.identities i WHERE i.account_id = a.account_id AND i.kind = 'robot')`
|
||||
|
||||
// IsRobot reports whether the account is a robot pool member (it carries a robot
|
||||
// identity). The admin console uses it to label a game's robot seats.
|
||||
func (s *Store) IsRobot(ctx context.Context, accountID uuid.UUID) (bool, error) {
|
||||
var ok bool
|
||||
err := s.db.QueryRowContext(ctx,
|
||||
`SELECT EXISTS (SELECT 1 FROM backend.identities WHERE account_id = $1 AND kind = 'robot')`,
|
||||
accountID).Scan(&ok)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("account: is-robot %s: %w", accountID, err)
|
||||
}
|
||||
return ok, nil
|
||||
}
|
||||
|
||||
// userListWhere builds the shared WHERE clause and its positional args (from $1).
|
||||
func userListWhere(f UserFilter) (string, []any) {
|
||||
args := []any{f.Robots}
|
||||
|
||||
Reference in New Issue
Block a user