Config
rating({
games: [
{ key: "duel", algorithm: "elo", xp: { win: 20, draw: 10, loss: 5 } },
],
serverAuthoritative: true,
recordScope: "rating:record",
})| Game field | Default | |
|---|---|---|
key | — | A URL path segment |
algorithm | — | elo · glicko · trueskill · your own id |
players | 2 | Must be within the algorithm’s supported range |
pool | the game key | Name one to share a ladder |
xp | — | Per outcome |
levels | — | Worst to best. Classified on read |
hideSkill | false | Still drives matchmaking |
sharedRoomCounts | false | Whether a game with a friend earns XP |
algoParams | — | Validated by the algorithm |
Top level: serverAuthoritative (default true), recordScope, basePath (default /rating). Which algorithm to name is the algorithms; what pool does is pools; the calls are Using Rating. Refusals carry an ordinary error code.
Algorithms
| Players | Teams | Skill number | Main dial | |
|---|---|---|---|---|
elo | 2 | no | The rating | K, default 32 |
glicko | 2 | no | rating − 2·RD | τ, default 0.5 |
trueskill | 2+ | yes | μ − 3·σ | β, τ, draw probability |
Validated at assembly, not at the first result.
A pool is rated by exactly one algorithm, and changing it is a new pool rather than a migration.
Routes
| Route | Verified by |
|---|---|
POST /rating/games/:game/outcomes | user + record scope when server-authoritative |
GET /rating/games/:game/me | user |
GET /rating/games/:game/players/:userId | user |
No public surface. Without auth composed, every route denies.
The outcome body
{ "ranks": { "u1": 1, "u2": 2 } }Finishing place per user id. 1 wins; ties share a place.
Nothing else — pool from config, algorithm from the pool, timestamp from the server.
The table
pithy_rating_ratings — one row per (pool, player).
| Column | |
|---|---|
| The algorithm’s state blob | Validated against the recorded algorithm on read |
| Skill | Indexed — a matchmaking bucket is a range read |
| XP | Monotonic |
| Games played | |
| Updated at |
No board table, no history table, no config in the database.
Bindings
| Binding | Kind |
|---|---|
DB | D1 |
pithy add rating writes it into every environment. Nothing needs provisioning beyond the database you already have.
Error codes
| Code | |
|---|---|
rating/game_not_found | |
rating/pool_not_found | |
rating/record_forbidden | Server-authoritative, and no record scope |
rating/unknown_algorithm | |
rating/unsupported_player_count | Caught on deploy, not at the first result |
rating/invalid_params | The algorithm refused them |
Registering your own
registerRatingAlgorithm(yourAlgorithm) in your Worker entry, before the capability assembles.
Declare an id, a params schema with defaults, a state schema, supported player counts, and pure initial, update and skill functions.