# Tunisian Rami — Online (Open / Progressive-Melds Variant)
Real-time multiplayer web app for **Tunisian Rami** (the Maghreb version of Rummy),
open / progressive-melds variant. Server is authoritative; clients never receive
other players' hands or the contents of the stock.
## Stack
- **Backend** — Java 21, Spring Boot 3.3, Maven. STOMP over WebSocket for gameplay,
REST for the lobby. In-memory room registry (MVP — no database).
- **Frontend** — Angular 22 (standalone components), `@stomp/stompjs`, `sockjs-client`.
## Repo layout
```
backend/ Spring Boot app.
- com.tunisianrami.engine ← pure Java, ZERO Spring imports
- com.tunisianrami.web ← REST lobby + room registry + bot
- com.tunisianrami.ws ← STOMP config, controllers, DTOs
frontend/ Angular app (lobby, game table, STOMP wiring).
```
The `engine` package is intentionally framework-free: card model, deck, melds,
turn-by-turn state machine, multi-round orchestration, and scoring all live
there and have ~80 dedicated JUnit tests around them.
## Run
### Prereqs
- JDK 21 (Eclipse Temurin recommended)
- Maven 3.9+
- Node 22.22+ or 24+ (Angular CLI 22 requires it)
- Angular CLI: `npm install -g @angular/cli`
On Windows with Scoop:
```
scoop bucket add java
scoop install temurin21-jdk maven nodejs-lts
npm install -g @angular/cli
```
### Backend
```
cd backend
mvn test # run all JUnit tests (107 of them)
mvn spring-boot:run # start on
localhost
```
### Frontend
```
cd frontend
npm install
ng serve # dev server on
localhost
# proxies /api and /ws to localhost:8080
```
Then open **two browser tabs** on `
localhost`:
1. Tab A creates a room, sees a 6-character code, becomes host.
2. Tab B joins with that code.
3. (Optional) Host clicks **Add bot** to fill the room with a CPU player.
4. Host clicks **Start game** — both tabs flip to the table.
5. The current-turn tab can draw / meld / lay off / joker-swap / discard.
6. Reload either …