Files
tavolo/docker-compose.yml
T
woggioni d9cdba33a1 Add hand-end scoring summary screen with acknowledgement
After each hand of an unfinished match the game now pauses in a new
hand_end phase instead of dealing immediately:

- engine: hand_points gains an 'award' map (which team won each category),
  _end_hand stops at hand_end with a deadline, new acknowledge_hand deals
  the next hand once all four players have acked; plays are rejected while
  the summary is up
- state: acked seats, hand_end_deadline and hand_ack_timeout are persisted
  and exposed in the personalized view (also on the finished state, so the
  final hand is explained before the result)
- ws: new {"action": "ack"}; a per-hand timer force-deals the next hand
  after HAND_ACK_TIMEOUT_SECONDS (new env var, default 30s) so an away
  player cannot stall the match
- web: modal explaining each category in plain language with icons (card
  images for denara/settebello/primiera), team-coloured rows, running
  totals with progress bars, an 'Understood — next hand' button that turns
  into 'Waiting for …' plus an auto-continue countdown; the final screen
  shows the last hand's breakdown too

Verified in the browser against the compose stack: hand played to
completion, summary rendered (including a carte tie), ack from all four
players dealt the next hand live, and the auto-continue path fired when
nobody acked. 60 backend tests + mypy + cargo tests green.
2026-09-16 21:46:01 +08:00

109 lines
3.5 KiB
YAML

services:
postgres:
image: postgres:18-alpine
environment:
POSTGRES_DB: scopa
POSTGRES_USER: scopa
POSTGRES_PASSWORD: scopa
ports:
- "5432:5432"
volumes:
- pgdata:/var/lib/postgresql
healthcheck:
test: ["CMD-SHELL", "pg_isready -U scopa"]
interval: 5s
timeout: 3s
retries: 10
# Mock OIDC provider (navikt/mock-oauth2-server). Zero manual setup:
# interactive login accepts any username (no password). Pre-configured
# players: alice, bob, carol, dave; any other username works too.
# The mock does not validate clients, so any client id/secret works.
#
# It listens on 8180 both inside and outside the network so the OIDC
# issuer URL (http://mockoauth:8180/scopa) is identical for
# container-to-container calls and for browser redirects (via the
# /etc/hosts entry documented in the README).
mockoauth:
# Derived image baking dev/mockoauth/config.json in (see
# dev/mockoauth/Dockerfile) — a bind mount would not work against
# containerized docker daemons.
build: ./server/dev/mockoauth
environment:
SERVER_PORT: "8180"
LOG_LEVEL: INFO
ports:
- "8180:8180"
# The JRE image has no usable healthcheck tooling; gate the app on the
# discovery endpoint being served instead.
mockoauth-init:
image: curlimages/curl
depends_on:
- mockoauth
entrypoint: >
/bin/sh -c "
until curl -sf http://mockoauth:8180/scopa/.well-known/openid-configuration > /dev/null; do
echo 'waiting for mockoauth...'; sleep 2;
done
"
# Sessions + live game state. No volume: sessions are disposable (worst
# case, users log in again) and games in progress have a TTL.
redis:
image: redis:8-alpine
ports:
- "6379:6379"
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 5s
timeout: 3s
retries: 10
# One-shot: applies pending aerich migrations before the app starts
# (build cache makes the second build of the same Dockerfile instant).
db-migrate:
build:
context: .
dockerfile: server/Dockerfile
# aerich reads [tool.aerich] from /app/pyproject.toml (default config
# file) and finds migrations in ./migrations relative to working_dir.
working_dir: /app
command: ["aerich", "upgrade"]
environment:
DATABASE_URL: postgres://scopa:scopa@postgres:5432/scopa
depends_on:
postgres:
condition: service_healthy
scopa:
build:
context: .
dockerfile: server/Dockerfile
depends_on:
postgres:
condition: service_healthy
db-migrate:
condition: service_completed_successfully
mockoauth-init:
condition: service_completed_successfully
redis:
condition: service_healthy
environment:
DATABASE_URL: postgres://scopa:scopa@postgres:5432/scopa
# By default the app and browsers reach the mock IdP under the same
# name (see README /etc/hosts note); override OIDC_ISSUER and
# OIDC_REDIRECT_URI to use a real provider or a different host port.
OIDC_ISSUER: ${OIDC_ISSUER:-http://mockoauth:8180/scopa}
# The mock OIDC server does not validate clients: any id/secret works.
OIDC_CLIENT_ID: scopa
OIDC_CLIENT_SECRET: ${OIDC_CLIENT_SECRET:-dev-secret}
OIDC_REDIRECT_URI: ${OIDC_REDIRECT_URI:-http://localhost:8080/auth/callback}
REDIS_URL: redis://redis:6379/0
HAND_ACK_TIMEOUT_SECONDS: ${HAND_ACK_TIMEOUT_SECONDS:-30}
ports:
- "127.0.0.1:${APP_PORT:-8080}:8080"
volumes:
pgdata: