YOVI is a web platform for playing Game Y — an abstract strategy board game where players compete to connect all three sides of a triangular board. The project is developed as part of the Software Architecture (ASW) course at the University of Oviedo.
🎮 Play here: https://yovi.13.63.89.84.sslip.io
| Name | GitHub | |
|---|---|---|
| Ana Pérez Bango | @AnaPB8 | UO294100@uniovi.es |
| Adriana García Suárez | @Adrigarsu | UO300042@uniovi.es |
The project follows a microservices architecture with five independent services orchestrated via Docker Compose and exposed through an NGINX reverse proxy:
yovi_en2c/
├── webapp/ # React + TypeScript frontend (SPA)
├── users/ # Node.js + Express user management service
├── authentication/ # Node.js + Express JWT authentication service
├── gateway/ # Node.js + Express API gateway
├── gamey/ # Rust game engine and bot service
├── botapi/ # Interoperability API (bot vs bot)
├── nginx/ # Reverse proxy
└── docs/ # Architecture documentation (Arc42 + ADRs)
Browser -> NGINX (80/443)
├── / -> webapp
├── /api -> gateway -> services (users, auth, gamey)
└── /interop -> botapi -> gamey
NGINX handles:
-
HTTPS termination (production)
-
HTTP → HTTPS redirect
-
routing
-
The gateway is used only by the webapp to access backend services.
-
The interop API is independent and communicates directly with
gamey.
- User registration and login with JWT-based authentication
- Play Game Y vs AI bot with 5 difficulty levels
- Variable board sizes configurable by the user
- Match history and game results stored in MongoDB
- Internationalization (i18n) — English and Spanish supported
- Public REST API for external bots using YEN notation
- Bot interoperability API for cross-team competitions
- Monitoring with Prometheus and Grafana
A single-page application (SPA) built with Vite, React, and TypeScript.
src/App.tsx— Main router with all application routessrc/LoginForm.tsx— Login form with JWT token handlingsrc/RegistrationForm.tsx— User registration formsrc/Home.tsx— Home dashboard with session verificationsrc/Game.tsx— Main game board componentsrc/SelectDifficulty.tsx— Bot difficulty selection screensrc/GameFinished.tsx— End of game screen (win/loss/draw)src/i18n/— Internationalization module (ES/EN)Dockerfile— Docker image definition
A REST API built with Node.js and Express, connected to MongoDB.
users-service.js— Main service filemodels/User.js— Mongoose user schemamodels/GameResult.js— Mongoose game result schemadb.js— MongoDB connection setup
Endpoints:
| Method | Route | Description |
|---|---|---|
POST |
/createuser |
Create a new user |
GET |
/users/:username |
Get user by username |
GET |
/users |
List all users |
POST |
/gameresult |
Save a game result |
GET |
/history/:username |
Get match history for a user |
GET |
/ranking |
Top 10 players by wins |
GET |
/health |
Health check |
A Node.js service responsible for JWT token generation and validation.
auth-service.js— Main service file
Endpoints:
| Method | Route | Description |
|---|---|---|
POST |
/register |
Validate credentials and create user via users service |
POST |
/login |
Authenticate user and return JWT |
GET |
/verify |
Verify a JWT token |
GET |
/health |
Health check |
A Node.js + Express API gateway — the single entry point for all external requests. Routes traffic to the appropriate internal service.
gateway-service.js— Main gateway file
Routes:
| Method | Route | Forwards to |
|---|---|---|
POST |
/game/new |
gamey — create new game |
POST |
/game/pvb/move |
gamey — player vs bot move |
POST |
/game/bot/choose |
gamey — bot move selection |
GET |
/game/status |
gamey — health check |
POST |
/register |
authentication service |
POST |
/login |
authentication service |
GET |
/verify |
authentication service |
A Rust service implementing all Game Y logic: move validation, win condition detection, and AI bot strategies.
src/main.rs— Binary entry point (CLI and server modes)src/lib.rs— Library exportssrc/core/— Core game types: board, coordinates (barycentric), players, movessrc/bot/— Bot trait (YBot), registry, and all strategy implementationssrc/notation/— YEN (Y Exchange Notation) serialization/deserializationsrc/game_server/— Axum HTTP server with REST endpointsCargo.toml— Project manifest
Available bot strategies:
| Bot ID | Difficulty | Algorithm |
|---|---|---|
random_bot |
— | Random valid move |
heuristic_bot |
Easy | Side connection heuristic |
minimax_bot |
Medium | Minimax (depth 3) |
alfa_beta_bot |
Hard | Minimax with alpha-beta pruning |
monte_carlo_hard |
Expert | Monte Carlo Tree Search |
monte_carlo_extreme |
Extreme | Monte Carlo Tree Search (more iterations) |
Game API endpoints (prefix /v1):
| Method | Route | Description |
|---|---|---|
GET |
/status |
Health check |
POST |
/game/new |
Create a new game, returns YEN |
POST |
/v1/game/pvb/{bot_id} |
Player move + bot response |
POST |
/v1/ybot/choose/{bot_id} |
Request bot move coordinates |
All game state is exchanged in YEN (Y Exchange Notation) — a JSON format inspired by chess FEN:
{
"size": 5,
"turn": 0,
"players": ["B", "R"],
"layout": "B/BR/.R./..../....."
}A Node.js + Express service that enables bot vs bot interoperability between teams.
This API acts as a bridge between external bots and the internal gamey engine, allowing:
- external bots to play against our bots
- our bots to play against other teams' APIs
It follows a standardized contract based on YEN (Y Exchange Notation).
Key responsibilities:
- expose public HTTP endpoints
- manage active games (in-memory)
- connect to remote APIs
- translate requests to
gamey - orchestrate game flow
Base public URL (deployment): https://yovi.13.63.89.84.sslip.io/interop
| Method | Route | Description |
|---|---|---|
POST |
/games |
Create a new local game |
GET |
/games/{id} |
Get game state |
POST |
/games/{id}/play |
Play a move |
POST |
/play |
Stateless move |
GET |
/health |
Health check |
| Method | Route | Description |
|---|---|---|
POST |
/remote-games/create |
Create remote game |
POST |
/remote-games/connect |
Connect to existing game |
GET |
/remote-games/{id} |
Get session info |
POST |
/remote-games/{id}/play-turn |
Play remote turn |
curl -X POST "https://yovi.13.63.89.84.sslip.io/interop/games" \
-H "Content-Type: application/json" \
-d '{"size":3,"bot_id":"random_bot"}'{
"size": 3,
"turn": 0,
"players": ["B", "R"],
"layout": "./../..."
}Requires Docker and Docker Compose.
1. Set up environment variables:
Create a .env file in the root directory:
MONGODB_URI=mongodb+srv://<user>:<password>@cluster.mongodb.net/yovi
JWT_SECRET=your_secret_key_here
JWT_EXPIRES=24h2. Build and start all services:
docker-compose up --build3. Access the application:
| Service | Internal Port | External Access |
|---|---|---|
| Web application | 80/443 | https://yovi.13.63.89.84.sslip.io |
| Web application | 80 | via nginx (/) |
| Gateway API | 8080 | via nginx (/api) |
| botapi | 4001 | via nginx (/interop) |
| Users service | 3000 | internal |
| Auth service | 5000 | internal |
| Game engine | 4000 | internal |
| Prometheus | 9090 | http://localhost:9090 |
| Grafana | 9091 | http://localhost:9091 |
You need Node.js, npm, and Rust installed.
1. Users service:
cd users
npm install
npm start
# Available at http://localhost:30002. Authentication service:
cd authentication
npm install
npm start
# Available at http://localhost:50003. Gateway:
cd gateway
npm install
npm start
# Available at http://localhost:80804. Game engine:
cd gamey
cargo run -- --mode server --port 4000
# Available at http://localhost:40005. Web application:
cd webapp
npm install
npm run dev
# Available at http://localhost:5173npm run dev # Start development server
npm test # Run unit tests
npm run test:e2e # Run end-to-end tests (Playwright)
npm run build # Production buildnpm start # Start the service
npm test # Run testscargo build # Build the project
cargo test # Run all tests
cargo run # Run in CLI mode (human vs human)
cargo run -- --mode server --port 4000 # Run as HTTP server
cargo doc --open # Generate and open documentationThe system follows a microservices architecture with NGINX as the single external entry point. The gateway is used for webapp traffic, while the interop API provides a separate access path for external bots.
For detailed architecture documentation, see the project wiki and the Architecture Decision Records (ADRs).
