Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 3bda9466b5 |
@@ -0,0 +1,313 @@
|
||||
# NowChess Tournament API
|
||||
|
||||
Swiss-system bot tournaments. Bots are paired by score each round; all bots play every round (no eliminations). Game moves flow through the existing board and bot endpoints — the tournament module only orchestrates pairings, standings, and lifecycle.
|
||||
|
||||
---
|
||||
|
||||
## Base path
|
||||
|
||||
```
|
||||
/api/tournament
|
||||
```
|
||||
|
||||
Routing: `/api/tournament` → `nowchess-tournament-active:8086`
|
||||
|
||||
---
|
||||
|
||||
## Authentication
|
||||
|
||||
All endpoints require a valid JWT (`Authorization: Bearer <token>`).
|
||||
Bot-facing streaming endpoints additionally require the token's subject to match the registered `botId`.
|
||||
|
||||
---
|
||||
|
||||
## Data models
|
||||
|
||||
### Tournament
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "t7kXq2",
|
||||
"name": "Friday Night Bots",
|
||||
"status": "created | started | finished",
|
||||
"rounds": 5,
|
||||
"currentRound": 2,
|
||||
"timeControl": {
|
||||
"limitSeconds": 300,
|
||||
"incrementSeconds": 3
|
||||
},
|
||||
"createdBy": "userId",
|
||||
"createdAt": "2026-05-13T18:00:00Z",
|
||||
"startedAt": "2026-05-13T18:05:00Z",
|
||||
"finishedAt": null
|
||||
}
|
||||
```
|
||||
|
||||
### Standing
|
||||
|
||||
```json
|
||||
{
|
||||
"rank": 1,
|
||||
"botId": "bot_abc",
|
||||
"botName": "StockfishClone",
|
||||
"points": 3.5,
|
||||
"wins": 3,
|
||||
"draws": 1,
|
||||
"losses": 0,
|
||||
"buchholz": 9.0
|
||||
}
|
||||
```
|
||||
|
||||
Tiebreaker: Buchholz score (sum of opponents' points).
|
||||
|
||||
### Pairing
|
||||
|
||||
```json
|
||||
{
|
||||
"round": 2,
|
||||
"whiteBot": "bot_abc",
|
||||
"blackBot": "bot_xyz",
|
||||
"gameId": "j0nPtcjl",
|
||||
"result": "white | black | draw | ongoing"
|
||||
}
|
||||
```
|
||||
|
||||
### TournamentEvent (SSE)
|
||||
|
||||
```json
|
||||
{ "type": "tournamentStarted", "tournamentId": "t7kXq2" }
|
||||
{ "type": "roundStarted", "tournamentId": "t7kXq2", "round": 2 }
|
||||
{ "type": "pairingReady", "tournamentId": "t7kXq2", "round": 2, "gameId": "j0nPtcjl", "color": "white" }
|
||||
{ "type": "roundFinished", "tournamentId": "t7kXq2", "round": 2 }
|
||||
{ "type": "tournamentFinished","tournamentId": "t7kXq2" }
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Endpoints
|
||||
|
||||
### Tournament lifecycle
|
||||
|
||||
#### Create tournament
|
||||
|
||||
```
|
||||
POST /api/tournament
|
||||
```
|
||||
|
||||
Body:
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "Friday Night Bots",
|
||||
"rounds": 5,
|
||||
"timeControl": {
|
||||
"limitSeconds": 300,
|
||||
"incrementSeconds": 3
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Response `201 Created`:
|
||||
|
||||
```json
|
||||
{ "id": "t7kXq2" }
|
||||
```
|
||||
|
||||
The creator becomes the tournament director. Only the director can start and delete the tournament.
|
||||
|
||||
---
|
||||
|
||||
#### Get tournament
|
||||
|
||||
```
|
||||
GET /api/tournament/{tournamentId}
|
||||
```
|
||||
|
||||
Response `200 OK`: `Tournament` object.
|
||||
|
||||
---
|
||||
|
||||
#### List tournaments
|
||||
|
||||
```
|
||||
GET /api/tournament
|
||||
```
|
||||
|
||||
Query params:
|
||||
|
||||
| Param | Type | Default |
|
||||
|----------|---------------------------------|-----------|
|
||||
| `status` | `created\|started\|finished` | (all) |
|
||||
| `limit` | integer (max 50) | 20 |
|
||||
| `offset` | integer | 0 |
|
||||
|
||||
Response `200 OK`:
|
||||
|
||||
```json
|
||||
{
|
||||
"tournaments": [ /* Tournament[] */ ],
|
||||
"total": 42
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### Start tournament
|
||||
|
||||
```
|
||||
POST /api/tournament/{tournamentId}/start
|
||||
```
|
||||
|
||||
Requires at least 2 registered bots. Computes round 1 pairings (random for round 1; score-based from round 2). Creates one game per pairing via `POST /api/board/game`.
|
||||
|
||||
Response `200 OK`: updated `Tournament` object.
|
||||
|
||||
---
|
||||
|
||||
#### Delete tournament
|
||||
|
||||
```
|
||||
DELETE /api/tournament/{tournamentId}
|
||||
```
|
||||
|
||||
Only allowed while `status == "created"`. Response `204 No Content`.
|
||||
|
||||
---
|
||||
|
||||
### Bot registration
|
||||
|
||||
#### Register bot
|
||||
|
||||
```
|
||||
POST /api/tournament/{tournamentId}/bots
|
||||
```
|
||||
|
||||
Registers a bot for the tournament. Must be called before the tournament starts.
|
||||
The token subject must match the bot being registered.
|
||||
|
||||
Body:
|
||||
|
||||
```json
|
||||
{ "botId": "bot_abc" }
|
||||
```
|
||||
|
||||
Response `200 OK`:
|
||||
|
||||
```json
|
||||
{ "botId": "bot_abc", "tournamentId": "t7kXq2" }
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### Unregister bot
|
||||
|
||||
```
|
||||
DELETE /api/tournament/{tournamentId}/bots/{botId}
|
||||
```
|
||||
|
||||
Only allowed while `status == "created"`. Response `204 No Content`.
|
||||
|
||||
---
|
||||
|
||||
#### List registered bots
|
||||
|
||||
```
|
||||
GET /api/tournament/{tournamentId}/bots
|
||||
```
|
||||
|
||||
Response `200 OK`:
|
||||
|
||||
```json
|
||||
{
|
||||
"bots": [
|
||||
{ "botId": "bot_abc", "botName": "StockfishClone" }
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Standings and pairings
|
||||
|
||||
#### Get standings
|
||||
|
||||
```
|
||||
GET /api/tournament/{tournamentId}/standings
|
||||
```
|
||||
|
||||
Response `200 OK`:
|
||||
|
||||
```json
|
||||
{ "standings": [ /* Standing[] */ ] }
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### Get pairings for a round
|
||||
|
||||
```
|
||||
GET /api/tournament/{tournamentId}/rounds/{round}/pairings
|
||||
```
|
||||
|
||||
Response `200 OK`:
|
||||
|
||||
```json
|
||||
{ "pairings": [ /* Pairing[] */ ] }
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Bot streaming
|
||||
|
||||
#### Stream tournament events
|
||||
|
||||
```
|
||||
GET /api/tournament/{tournamentId}/stream
|
||||
```
|
||||
|
||||
Headers: `Accept: text/event-stream`
|
||||
|
||||
Server-Sent Events stream scoped to this tournament. The bot receives `pairingReady` events when it is assigned a game, at which point it should connect to the existing bot game stream:
|
||||
|
||||
```
|
||||
GET /bot/stream/game/{gameId} (existing endpoint)
|
||||
POST /bot/game/{gameId}/move/{uci} (existing endpoint)
|
||||
```
|
||||
|
||||
The tournament module never sends moves — bots do that themselves through the existing bot endpoints.
|
||||
|
||||
---
|
||||
|
||||
## Typical bot flow
|
||||
|
||||
```
|
||||
1. POST /api/tournament # director creates tournament
|
||||
2. POST /api/tournament/{id}/bots # each bot registers
|
||||
3. POST /api/tournament/{id}/start # director starts
|
||||
4. GET /api/tournament/{id}/stream (SSE) # each bot opens stream
|
||||
|
||||
-- per round --
|
||||
5. receive: pairingReady { gameId, color }
|
||||
6. GET /bot/stream/game/{gameId} # existing endpoint
|
||||
7. POST /bot/game/{gameId}/move/{uci} # existing endpoint, repeated
|
||||
-- game ends --
|
||||
|
||||
8. receive: roundFinished
|
||||
9. GET /api/tournament/{id}/standings # optional, inspect scores
|
||||
-- repeat 5–9 for each round --
|
||||
|
||||
10. receive: tournamentFinished
|
||||
11. GET /api/tournament/{id}/standings # final ranking
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Error responses
|
||||
|
||||
| Status | Meaning |
|
||||
|--------|------------------------------------------------------|
|
||||
| 400 | Invalid request body or parameters |
|
||||
| 401 | Missing or invalid JWT |
|
||||
| 403 | Action not allowed (wrong director, wrong bot, etc.) |
|
||||
| 404 | Tournament or bot not found |
|
||||
| 409 | Tournament already started / bot already registered |
|
||||
@@ -0,0 +1,623 @@
|
||||
openapi: 3.0.3
|
||||
info:
|
||||
title: NowChess Tournament API
|
||||
description: |
|
||||
Swiss-system bot tournaments, modelled after the Lichess API style.
|
||||
|
||||
Game moves flow through the existing board and bot endpoints — this module
|
||||
handles pairings, standings, and lifecycle only.
|
||||
|
||||
## Streaming
|
||||
Endpoints marked **NDJSON** return newline-delimited JSON objects
|
||||
(`application/x-ndjson`). Each line is one complete JSON object. The
|
||||
connection stays open until the tournament or round ends.
|
||||
|
||||
## Bot flow
|
||||
```
|
||||
POST /api/tournament # create
|
||||
POST /api/tournament/{id}/join # each bot joins
|
||||
POST /api/tournament/{id}/start # director starts
|
||||
|
||||
GET /api/tournament/{id}/stream (NDJSON) # open before start
|
||||
|
||||
-- per round --
|
||||
receive gameStart { gameId, color }
|
||||
GET /bot/stream/game/{gameId} (existing, NDJSON)
|
||||
POST /bot/game/{gameId}/move/{uci} (existing)
|
||||
-- repeat --
|
||||
|
||||
GET /api/tournament/{id}/results (NDJSON) # final standings
|
||||
```
|
||||
version: 1.0.0
|
||||
|
||||
servers:
|
||||
- url: https://st.nowchess.janis-eccarius.de
|
||||
description: Staging
|
||||
- url: https://nowchess.janis-eccarius.de
|
||||
description: Production
|
||||
- url: http://localhost:8086
|
||||
description: Local
|
||||
|
||||
security:
|
||||
- bearerAuth: []
|
||||
|
||||
tags:
|
||||
- name: Tournament
|
||||
description: Tournament lifecycle
|
||||
- name: Participation
|
||||
description: Join and withdraw
|
||||
- name: Results
|
||||
description: Standings, pairings, and game export
|
||||
- name: Stream
|
||||
description: NDJSON event streams
|
||||
|
||||
paths:
|
||||
|
||||
/api/tournament:
|
||||
get:
|
||||
tags: [Tournament]
|
||||
summary: Get current tournaments
|
||||
description: Returns tournaments grouped by status. No auth required.
|
||||
security: []
|
||||
responses:
|
||||
"200":
|
||||
description: Tournaments by status
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
created:
|
||||
type: array
|
||||
items:
|
||||
$ref: "#/components/schemas/TournamentInfo"
|
||||
started:
|
||||
type: array
|
||||
items:
|
||||
$ref: "#/components/schemas/TournamentInfo"
|
||||
finished:
|
||||
type: array
|
||||
items:
|
||||
$ref: "#/components/schemas/TournamentInfo"
|
||||
|
||||
post:
|
||||
tags: [Tournament]
|
||||
summary: Create a new tournament
|
||||
description: The authenticated user becomes the tournament director.
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/x-www-form-urlencoded:
|
||||
schema:
|
||||
$ref: "#/components/schemas/CreateTournamentForm"
|
||||
responses:
|
||||
"201":
|
||||
description: Tournament created
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Tournament"
|
||||
"400":
|
||||
$ref: "#/components/responses/BadRequest"
|
||||
"401":
|
||||
$ref: "#/components/responses/Unauthorized"
|
||||
|
||||
/api/tournament/{id}:
|
||||
parameters:
|
||||
- $ref: "#/components/parameters/id"
|
||||
|
||||
get:
|
||||
tags: [Tournament]
|
||||
summary: Get a tournament
|
||||
description: Includes the first page of standings in the `standing` field.
|
||||
security: []
|
||||
responses:
|
||||
"200":
|
||||
description: Tournament with embedded standings
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Tournament"
|
||||
"404":
|
||||
$ref: "#/components/responses/NotFound"
|
||||
|
||||
delete:
|
||||
tags: [Tournament]
|
||||
summary: Terminate a tournament
|
||||
description: Only the director may terminate. Only allowed while status is `created`.
|
||||
responses:
|
||||
"204":
|
||||
description: Terminated
|
||||
"401":
|
||||
$ref: "#/components/responses/Unauthorized"
|
||||
"403":
|
||||
$ref: "#/components/responses/Forbidden"
|
||||
"404":
|
||||
$ref: "#/components/responses/NotFound"
|
||||
"409":
|
||||
$ref: "#/components/responses/Conflict"
|
||||
|
||||
/api/tournament/{id}/start:
|
||||
parameters:
|
||||
- $ref: "#/components/parameters/id"
|
||||
|
||||
post:
|
||||
tags: [Tournament]
|
||||
summary: Start the tournament
|
||||
description: |
|
||||
Only the director may start. Requires at least 2 joined bots.
|
||||
Computes round 1 pairings and creates games via `POST /api/board/game`.
|
||||
responses:
|
||||
"200":
|
||||
description: Tournament started
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Tournament"
|
||||
"401":
|
||||
$ref: "#/components/responses/Unauthorized"
|
||||
"403":
|
||||
$ref: "#/components/responses/Forbidden"
|
||||
"404":
|
||||
$ref: "#/components/responses/NotFound"
|
||||
"409":
|
||||
$ref: "#/components/responses/Conflict"
|
||||
|
||||
/api/tournament/{id}/join:
|
||||
parameters:
|
||||
- $ref: "#/components/parameters/id"
|
||||
|
||||
post:
|
||||
tags: [Participation]
|
||||
summary: Join a tournament
|
||||
description: |
|
||||
Register the authenticated bot for the tournament. Only allowed while
|
||||
status is `created`. The token subject must be a bot account.
|
||||
responses:
|
||||
"200":
|
||||
description: Ok
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Ok"
|
||||
"401":
|
||||
$ref: "#/components/responses/Unauthorized"
|
||||
"403":
|
||||
$ref: "#/components/responses/Forbidden"
|
||||
"404":
|
||||
$ref: "#/components/responses/NotFound"
|
||||
"409":
|
||||
$ref: "#/components/responses/Conflict"
|
||||
|
||||
/api/tournament/{id}/withdraw:
|
||||
parameters:
|
||||
- $ref: "#/components/parameters/id"
|
||||
|
||||
post:
|
||||
tags: [Participation]
|
||||
summary: Withdraw from a tournament
|
||||
description: Only allowed while status is `created`.
|
||||
responses:
|
||||
"200":
|
||||
description: Ok
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Ok"
|
||||
"401":
|
||||
$ref: "#/components/responses/Unauthorized"
|
||||
"403":
|
||||
$ref: "#/components/responses/Forbidden"
|
||||
"404":
|
||||
$ref: "#/components/responses/NotFound"
|
||||
"409":
|
||||
$ref: "#/components/responses/Conflict"
|
||||
|
||||
/api/tournament/{id}/results:
|
||||
parameters:
|
||||
- $ref: "#/components/parameters/id"
|
||||
|
||||
get:
|
||||
tags: [Results]
|
||||
summary: Get results as NDJSON stream
|
||||
description: |
|
||||
Streams one `Result` object per line, sorted by rank ascending.
|
||||
Available at any point during or after the tournament.
|
||||
security: []
|
||||
parameters:
|
||||
- name: nb
|
||||
in: query
|
||||
description: Max number of results to stream (default all)
|
||||
schema:
|
||||
type: integer
|
||||
minimum: 1
|
||||
responses:
|
||||
"200":
|
||||
description: NDJSON stream of results
|
||||
content:
|
||||
application/x-ndjson:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Result"
|
||||
"404":
|
||||
$ref: "#/components/responses/NotFound"
|
||||
|
||||
/api/tournament/{id}/round/{round}:
|
||||
parameters:
|
||||
- $ref: "#/components/parameters/id"
|
||||
- name: round
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: integer
|
||||
minimum: 1
|
||||
|
||||
get:
|
||||
tags: [Results]
|
||||
summary: Get pairings for a round
|
||||
security: []
|
||||
responses:
|
||||
"200":
|
||||
description: Pairings for the specified round
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
round:
|
||||
type: integer
|
||||
example: 2
|
||||
pairings:
|
||||
type: array
|
||||
items:
|
||||
$ref: "#/components/schemas/Pairing"
|
||||
"404":
|
||||
$ref: "#/components/responses/NotFound"
|
||||
|
||||
/api/tournament/{id}/export/games:
|
||||
parameters:
|
||||
- $ref: "#/components/parameters/id"
|
||||
|
||||
get:
|
||||
tags: [Results]
|
||||
summary: Export all games
|
||||
description: |
|
||||
Returns all games of the tournament. Accepts both PGN and NDJSON via
|
||||
the `Accept` header.
|
||||
security: []
|
||||
parameters:
|
||||
- name: Accept
|
||||
in: header
|
||||
schema:
|
||||
type: string
|
||||
enum:
|
||||
- application/x-chess-pgn
|
||||
- application/x-ndjson
|
||||
default: application/x-chess-pgn
|
||||
responses:
|
||||
"200":
|
||||
description: Games in the requested format
|
||||
content:
|
||||
application/x-chess-pgn:
|
||||
schema:
|
||||
type: string
|
||||
description: Standard PGN, one game per block
|
||||
application/x-ndjson:
|
||||
schema:
|
||||
$ref: "#/components/schemas/GameExport"
|
||||
"404":
|
||||
$ref: "#/components/responses/NotFound"
|
||||
|
||||
/api/tournament/{id}/stream:
|
||||
parameters:
|
||||
- $ref: "#/components/parameters/id"
|
||||
|
||||
get:
|
||||
tags: [Stream]
|
||||
summary: Stream tournament events
|
||||
description: |
|
||||
NDJSON stream scoped to one tournament. Keep this connection open for
|
||||
the full tournament lifetime.
|
||||
|
||||
On `gameStart` the bot connects to the existing bot endpoints:
|
||||
- `GET /bot/stream/game/{gameId}` — stream game state (existing)
|
||||
- `POST /bot/game/{gameId}/move/{uci}` — submit moves (existing)
|
||||
responses:
|
||||
"200":
|
||||
description: NDJSON event stream
|
||||
content:
|
||||
application/x-ndjson:
|
||||
schema:
|
||||
$ref: "#/components/schemas/TournamentEvent"
|
||||
"401":
|
||||
$ref: "#/components/responses/Unauthorized"
|
||||
"404":
|
||||
$ref: "#/components/responses/NotFound"
|
||||
|
||||
components:
|
||||
|
||||
securitySchemes:
|
||||
bearerAuth:
|
||||
type: http
|
||||
scheme: bearer
|
||||
bearerFormat: JWT
|
||||
|
||||
parameters:
|
||||
id:
|
||||
name: id
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
example: t7kXq2
|
||||
|
||||
schemas:
|
||||
|
||||
Clock:
|
||||
type: object
|
||||
required: [limit, increment]
|
||||
properties:
|
||||
limit:
|
||||
type: integer
|
||||
description: Base time in seconds
|
||||
example: 300
|
||||
increment:
|
||||
type: integer
|
||||
description: Increment per move in seconds
|
||||
example: 3
|
||||
|
||||
Variant:
|
||||
type: object
|
||||
properties:
|
||||
key:
|
||||
type: string
|
||||
example: standard
|
||||
name:
|
||||
type: string
|
||||
example: Standard
|
||||
|
||||
BotRef:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
example: bot_abc
|
||||
name:
|
||||
type: string
|
||||
example: StockfishClone
|
||||
|
||||
Standing:
|
||||
type: object
|
||||
properties:
|
||||
page:
|
||||
type: integer
|
||||
example: 1
|
||||
players:
|
||||
type: array
|
||||
items:
|
||||
$ref: "#/components/schemas/Result"
|
||||
|
||||
TournamentInfo:
|
||||
description: Lightweight tournament summary used in list responses.
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
example: t7kXq2
|
||||
fullName:
|
||||
type: string
|
||||
example: Friday Night Bots Swiss
|
||||
clock:
|
||||
$ref: "#/components/schemas/Clock"
|
||||
variant:
|
||||
$ref: "#/components/schemas/Variant"
|
||||
rated:
|
||||
type: boolean
|
||||
example: true
|
||||
nbPlayers:
|
||||
type: integer
|
||||
example: 8
|
||||
nbRounds:
|
||||
type: integer
|
||||
example: 5
|
||||
createdBy:
|
||||
type: string
|
||||
example: userId
|
||||
startsAt:
|
||||
type: string
|
||||
format: date-time
|
||||
|
||||
Tournament:
|
||||
allOf:
|
||||
- $ref: "#/components/schemas/TournamentInfo"
|
||||
- type: object
|
||||
properties:
|
||||
status:
|
||||
type: string
|
||||
enum: [created, started, finished]
|
||||
example: started
|
||||
round:
|
||||
type: integer
|
||||
description: Current round number
|
||||
example: 2
|
||||
standing:
|
||||
$ref: "#/components/schemas/Standing"
|
||||
winner:
|
||||
description: Present only when status is `finished`
|
||||
allOf:
|
||||
- $ref: "#/components/schemas/BotRef"
|
||||
nullable: true
|
||||
|
||||
CreateTournamentForm:
|
||||
type: object
|
||||
required: [name, nbRounds, clockLimit, clockIncrement]
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
example: Friday Night Bots
|
||||
nbRounds:
|
||||
type: integer
|
||||
minimum: 1
|
||||
example: 5
|
||||
clockLimit:
|
||||
type: integer
|
||||
description: Base time in seconds
|
||||
example: 300
|
||||
clockIncrement:
|
||||
type: integer
|
||||
description: Increment per move in seconds
|
||||
example: 3
|
||||
rated:
|
||||
type: boolean
|
||||
default: true
|
||||
|
||||
Result:
|
||||
type: object
|
||||
properties:
|
||||
rank:
|
||||
type: integer
|
||||
example: 1
|
||||
points:
|
||||
type: number
|
||||
format: double
|
||||
example: 3.5
|
||||
tieBreak:
|
||||
type: number
|
||||
format: double
|
||||
description: Buchholz score (sum of opponents' points)
|
||||
example: 9.0
|
||||
bot:
|
||||
$ref: "#/components/schemas/BotRef"
|
||||
nbGames:
|
||||
type: integer
|
||||
example: 4
|
||||
wins:
|
||||
type: integer
|
||||
example: 3
|
||||
draws:
|
||||
type: integer
|
||||
example: 1
|
||||
losses:
|
||||
type: integer
|
||||
example: 0
|
||||
|
||||
Pairing:
|
||||
type: object
|
||||
properties:
|
||||
round:
|
||||
type: integer
|
||||
example: 2
|
||||
white:
|
||||
$ref: "#/components/schemas/BotRef"
|
||||
black:
|
||||
$ref: "#/components/schemas/BotRef"
|
||||
gameId:
|
||||
type: string
|
||||
example: j0nPtcjl
|
||||
winner:
|
||||
type: string
|
||||
enum: [white, black, draw]
|
||||
nullable: true
|
||||
description: Null while the game is ongoing
|
||||
|
||||
GameExport:
|
||||
description: One game object per NDJSON line.
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
example: j0nPtcjl
|
||||
round:
|
||||
type: integer
|
||||
example: 2
|
||||
white:
|
||||
$ref: "#/components/schemas/BotRef"
|
||||
black:
|
||||
$ref: "#/components/schemas/BotRef"
|
||||
winner:
|
||||
type: string
|
||||
enum: [white, black, draw]
|
||||
nullable: true
|
||||
moves:
|
||||
type: string
|
||||
description: Space-separated UCI moves
|
||||
example: e2e4 e7e5 g1f3
|
||||
|
||||
TournamentEvent:
|
||||
description: |
|
||||
One JSON object per NDJSON line. Discriminate on `type`.
|
||||
|
||||
| type | extra fields |
|
||||
|------|-------------|
|
||||
| `tournamentStarted` | — |
|
||||
| `roundStarted` | `round` |
|
||||
| `gameStart` | `round`, `gameId`, `color` |
|
||||
| `roundFinished` | `round` |
|
||||
| `tournamentFinished` | `winner` |
|
||||
type: object
|
||||
required: [type]
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
enum:
|
||||
- tournamentStarted
|
||||
- roundStarted
|
||||
- gameStart
|
||||
- roundFinished
|
||||
- tournamentFinished
|
||||
round:
|
||||
type: integer
|
||||
example: 2
|
||||
gameId:
|
||||
type: string
|
||||
example: j0nPtcjl
|
||||
color:
|
||||
type: string
|
||||
enum: [white, black]
|
||||
winner:
|
||||
$ref: "#/components/schemas/BotRef"
|
||||
|
||||
Ok:
|
||||
type: object
|
||||
properties:
|
||||
ok:
|
||||
type: boolean
|
||||
example: true
|
||||
|
||||
Error:
|
||||
type: object
|
||||
properties:
|
||||
error:
|
||||
type: string
|
||||
example: tournament already started
|
||||
|
||||
responses:
|
||||
BadRequest:
|
||||
description: Invalid request body or parameters
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Error"
|
||||
Unauthorized:
|
||||
description: Missing or invalid JWT
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Error"
|
||||
Forbidden:
|
||||
description: Action not permitted for this user or bot
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Error"
|
||||
NotFound:
|
||||
description: Tournament not found
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Error"
|
||||
Conflict:
|
||||
description: Conflicting state (e.g. already started, bot already joined)
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Error"
|
||||
Reference in New Issue
Block a user