Repo is now a monorepo:
- server/: the kaya backend, unchanged in behaviour, plus:
- GET /api/me for SPA session detection
- last_move recorded on every play and broadcast in the game state, so
clients can show who played which card the moment they play it
- legal_moves per hand card for the player on turn (rules stay
server-side)
- static catch-all route serving the compiled SPA with index.html
fallback; Tortoise context now bound only for /api/* requests
- configurable OIDC post-login/logout redirects for dev against trunk
- web/: Sycamore 0.9 + WASM frontend (trunk): login via the OIDC flow,
lobby (create match / join by code), live game page over websocket with
card images (CC0 woodcut napoletane deck), capture picker, move banner,
game-over overlay, match history and leaderboard pages
- server/Dockerfile gains a rust+trunk stage building web/dist; the single
app image serves the SPA; compose builds from the repo root with
overridable ports/OIDC env
Verified end-to-end against the compose stack: four OIDC logins, game
creation, three joins by code, websocket play with broadcasts to all
players and out-of-turn rejection. 51 backend tests, mypy and cargo tests
all green.
63 lines
1.9 KiB
Markdown
63 lines
1.9 KiB
Markdown
# scopa
|
|
|
|
Multiplayer **scopone scientifico** — the four-player, fixed-partnership
|
|
Italian card game — as a web application:
|
|
|
|
- **`server/`** — backend: Python + [kaya](https://github.com/woggioni/kaya)
|
|
framework, OIDC login, live games in Redis, match statistics in Postgres.
|
|
See [server/README.md](server/README.md).
|
|
- **`web/`** — frontend: Rust + [Sycamore](https://sycamore.dev) compiled to
|
|
WebAssembly, built with [Trunk](https://trunkrs.dev). 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/scopa`, add a host entry once:
|
|
|
|
```sh
|
|
echo "127.0.0.1 mockoauth" | sudo tee -a /etc/hosts
|
|
```
|
|
|
|
## Development
|
|
|
|
Backend (from `server/`):
|
|
|
|
```sh
|
|
cd server
|
|
python3 -m venv .venv
|
|
.venv/bin/pip install -r requirements.txt
|
|
.venv/bin/pip install -e '.[dev]'
|
|
.venv/bin/python -m unittest discover -s tests -t .
|
|
.venv/bin/mypy src
|
|
```
|
|
|
|
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_POST_LOGIN_REDIRECT=http://localhost:8000/ \
|
|
OIDC_POST_LOGOUT_REDIRECT=http://localhost:8000/ \
|
|
.venv/bin/granian --host 127.0.0.1 --port 8080 scopa.app:app
|
|
```
|
|
|
|
Card images are committed under `web/assets/cards/`; `web/fetch-cards.sh`
|
|
re-downloads them if needed.
|