Docs / Leaderboards & tournaments

Leaderboards & tournaments

Score tables with multiple scoring modes and time windows. Tournaments wrap leaderboards with seasonal resets, brackets, and prize distribution.

Leaderboard models

  • Monotonic — keeps the highest score submitted per player (e.g. “best lap”).
  • Cumulative — sums submissions (e.g. “total XP”).
  • Windowed — same as above but with a rolling time window (weekly / monthly) that resets automatically.

Submitting scores

game.leaderboard.submit("arena:weekly", player_id, kills)
asobi_leaderboard_server:submit(<<"arena:weekly">>, PlayerId, Kills).

Reading

for _, e in ipairs(game.leaderboard.top("arena:weekly", 10)) do
    print(e.rank, e.player_id, e.score)
end
local my_rank = game.leaderboard.rank("arena:weekly", player_id)
local near    = game.leaderboard.around("arena:weekly", player_id, 5)
Top        = asobi_leaderboard_server:top(<<"arena:weekly">>, 10),
{ok, Rank} = asobi_leaderboard_server:rank(<<"arena:weekly">>, PlayerId),
Near       = asobi_leaderboard_server:around(<<"arena:weekly">>, PlayerId, 5).

REST

GET  /api/v1/leaderboards/:id                  Top N entries
GET  /api/v1/leaderboards/:id/around/:player   Entries around a player
POST /api/v1/leaderboards/:id                  Submit a score

Starting a board

Boards are lazily spawned on first use — the first call to submit/top/rank with a board ID starts a dedicated asobi_leaderboard_server process. You can also start one eagerly:

{ok, _Pid} = asobi_leaderboard_sup:start_board(<<"arena:weekly">>).

Tournaments

A tournament wraps a leaderboard with a time window and prize pool. Tournaments are created by inserting a row via asobi_repo and then booting a server under asobi_tournament_sup:

GET  /api/v1/tournaments               List active tournaments
GET  /api/v1/tournaments/:id           Get tournament details
POST /api/v1/tournaments/:id/join      Join a tournament
{ok, _Pid} = asobi_tournament_sup:start_tournament(#{
    tournament_id => <<"arena:2026-w17">>,
    leaderboard   => <<"arena:weekly">>
}).

Seasons

Seasons wrap longer lifecycles (weekly competitive, monthly events). When a season ends, leaderboards tied to it reset and archive snapshots are persisted for history queries.

Where next?