feat: add Zenith strategy and move latency tracing
Build and Push Docker Container / build-and-push (push) Successful in 2m18s

- Register Zenith 1.1 with balanced duel verdicts and forced-outcome overrides.
- Prioritize permanent-trail space in Constrictor and health-aware hazard routes.
- Deduct executor queue delays and return fallback directions on move timeouts.
- Correlate response headers, replay timings, and sampled structured trace logs.
- Move shared metrics publication off the response path without losing local counts.
- Allow configurable tournament opponents and add a psql helper recipe.
- Preserve empty latency values through compact replay encoding and migration.
- Update Arena game links and use default assets for missing customizations.
- Cover strategy, HTTP lifecycle, tracing, replay codecs, and dashboard behavior.
- Validate with 260 passing Python tests, 4 skips, and 2 passing JavaScript tests.
This commit is contained in:
2026-11-05 01:11:31 +01:00
parent 39a7a53873
commit a2414f0b3d
26 changed files with 758 additions and 45 deletions
+43
View File
@@ -0,0 +1,43 @@
"""Fast request-local fallback and queue-aware worker budgeting."""
from time import perf_counter
def fallback_move(state):
board = state['board']
mine = state['you']
head = mine['head']
occupied = {(p['x'], p['y']) for s in board['snakes'] for p in s['body']}
food = {(p['x'], p['y']) for p in board.get('food', [])}
hazards = {(p['x'], p['y']) for p in board.get('hazards', [])}
ranked = []
for name, (dx, dy) in (('up', (0, 1)), ('down', (0, -1)), ('left', (-1, 0)), ('right', (1, 0))):
point = head['x'] + dx, head['y'] + dy
if not (0 <= point[0] < board['width'] and 0 <= point[1] < board['height']):
continue
if point in occupied:
continue
danger = any(
s['id'] != mine['id'] and len(s['body']) >= len(mine['body'])
and abs(s['head']['x'] - point[0]) + abs(s['head']['y'] - point[1]) == 1
for s in board['snakes']
)
ranked.append((not danger, point not in hazards or point in food, name))
return max(ranked)[-1] if ranked else 'up'
def run_budgeted_move(board, deadline, fallback, trace=None, submitted=None):
"""Deduct executor queue wait before the strategy starts its own clock."""
started = perf_counter()
if trace is not None:
trace.set(executor_queue_ms=round((started - submitted) * 1000, 3), worker_started=True)
remaining = int((deadline - started) * 1000)
if remaining <= 40:
if trace is not None:
trace.set(worker_skipped=True)
return fallback
original_timeout = board.timeout
try:
board.timeout = min(original_timeout, remaining)
return board.snake_neat_make_a_move()
finally:
board.timeout = original_timeout
if trace is not None:
trace.set(strategy_ms=round((perf_counter() - started) * 1000, 3), worker_finished=True)