CI / Build and push docker image (push) Successful in 4m20s
Replace the Python/kaya server in server/ with a Rust Cargo workspace of three crates mirroring the old layout: tavolo-platform (lobby API, live-game store, websocket endpoint, deadline scheduler, stats/Elo, OIDC sessions), tavolo-scopone (pure scopone scientifico rules plus the platform adapter) and tavolo-app (composition root and the `tavolo` binary with serve/migrate/backfill-elo). The HTTP and WebSocket contracts, error messages, Redis key layout and Postgres schema are unchanged, so the existing web/ frontend and in-flight games keep working. Notable differences: sessions are JSON under tavolo:session: (Python pickle sessions invalidate once), LOGGING_CONFIG is ignored in favour of RUST_LOG, DATABASE_URL must be Postgres, sqlx migrations replace aerich, and OpenTelemetry exports Rust process metrics instead of CPython gc metrics (no Postgres/Redis client instrumentation). Docker Compose and the Kubernetes manifest now run the single Rust image (embedded migrations, /static and /assets served by the app); the release CI keeps building server/Dockerfile. The full test suite (scopone rules, platform store/deadlines/stats/websockets, OIDC login flow, scopone e2e) is ported and runs with cargo test --workspace; Redis/Postgres integration tests are gated on TEST_REDIS_URL/TEST_DATABASE_URL.
94 lines
3.4 KiB
Markdown
94 lines
3.4 KiB
Markdown
# tavolo
|
|
|
|
A platform for multiplayer card games. The first game is **scopone
|
|
scientifico** — the four-player, fixed-partnership Italian card game:
|
|
|
|
- **`server/`** — backend: Rust + [Axum](https://github.com/tokio-rs/axum),
|
|
OIDC login, live games in Redis, match statistics in Postgres. A Cargo
|
|
workspace of three crates: the game-independent `tavolo-platform`, the
|
|
scopone game `tavolo-scopone`, and the `tavolo-app` composition root
|
|
(the `tavolo` binary: `serve`, `migrate`, `backfill-elo`).
|
|
See [server/README.md](server/README.md).
|
|
- **`web/`** — frontend: Rust + [Sycamore](https://sycamore.dev) compiled to
|
|
WebAssembly, built with [Trunk](https://trunkrs.dev) and styled with
|
|
[Bootstrap](https://getbootstrap.com) 5.3 (MIT, vendored under
|
|
`web/vendor/` so builds work offline) plus the custom felt theme in
|
|
`web/theme.css`. Card images are the
|
|
CC0 *woodcut napoletane* deck traced from a 1902 Naples print
|
|
([SONDLecT/woodcut-napoletane](https://github.com/SONDLecT/woodcut-napoletane)).
|
|
|
|
## Run the whole stack
|
|
|
|
```sh
|
|
docker compose up --build
|
|
```
|
|
|
|
Postgres, Redis, a mock OIDC provider (test users `alice`, `bob`, `carol`,
|
|
`dave`), the database migrator and the app all come up together. The app —
|
|
frontend and API — listens on `http://127.0.0.1:8080`.
|
|
|
|
Because both the browser and the app talk to the OIDC issuer at
|
|
`http://mockoauth:8180/tavolo`, add a host entry once:
|
|
|
|
```sh
|
|
echo "127.0.0.1 mockoauth" | sudo tee -a /etc/hosts
|
|
```
|
|
|
|
## Between hands
|
|
|
|
When a hand ends but the match is not decided, the game pauses on a
|
|
**scoring summary screen**: every player sees how each category was won
|
|
(carte, denara, settebello, primiera, scope — plus napola and asso
|
|
pigliatutto when enabled)
|
|
with the running totals and
|
|
must click "Understood" before the next hand is dealt. If someone is away
|
|
the next hand is dealt automatically after `HAND_ACK_TIMEOUT_SECONDS`
|
|
(default 30s). The match-ending hand is explained on the final screen.
|
|
|
|
## On your turn
|
|
|
|
Every turn shows a countdown (`TURN_TIMEOUT_SECONDS`, default 30s). If a
|
|
player does not move — disconnected or fallen asleep — the server plays a
|
|
random legal card for them (randomizing among the legal captures when the
|
|
rules require a capture), so one absent player cannot stall the table.
|
|
|
|
## Development
|
|
|
|
Backend (from `server/`):
|
|
|
|
```sh
|
|
cd server
|
|
cargo test --workspace # unit + integration suites
|
|
cargo run -p tavolo-app # serves on :8080 (Postgres required)
|
|
cargo run -p tavolo-app -- migrate # apply the embedded sqlx migrations
|
|
```
|
|
|
|
The Redis- and Postgres-backed tests run when `TEST_REDIS_URL` /
|
|
`TEST_DATABASE_URL` point at throwaway services (e.g. from
|
|
`docker compose up postgres redis` plus the port mappings) and are skipped
|
|
otherwise.
|
|
|
|
Frontend (from `web/`), with the backend running on :8080:
|
|
|
|
```sh
|
|
cd web
|
|
trunk serve # SPA on http://localhost:8000, /api /auth /ws proxied
|
|
```
|
|
|
|
Trunk proxies `/api`, `/auth` and `/ws` to `127.0.0.1:8080` (see
|
|
`web/Trunk.toml`). For the login redirect to land back on the dev server,
|
|
run the backend with:
|
|
|
|
```sh
|
|
OIDC_0_PROVIDER=default \
|
|
OIDC_0_ISSUER=http://localhost:8180/tavolo \
|
|
OIDC_0_CLIENT_ID=tavolo \
|
|
OIDC_0_REDIRECT_URI=http://localhost:8080/auth/default/callback \
|
|
OIDC_0_POST_LOGIN_REDIRECT=http://localhost:8000/ \
|
|
OIDC_0_POST_LOGOUT_REDIRECT=http://localhost:8000/ \
|
|
cargo run -p tavolo-app
|
|
```
|
|
|
|
Card images are committed under `web/assets/cards/`; `web/fetch-cards.sh`
|
|
re-downloads them if needed.
|