Packages
game_server_sdk
1.0.1078
1.0.1082
1.0.1079
1.0.1078
1.0.1077
1.0.1076
1.0.1075
1.0.1074
1.0.1073
1.0.1070
1.0.1068
1.0.1067
1.0.1063
1.0.1059
1.0.1058
1.0.1057
1.0.1056
1.0.1055
1.0.1050
1.0.1049
1.0.1048
1.0.1047
1.0.1046
1.0.1044
1.0.1043
1.0.1042
1.0.1041
1.0.1040
1.0.1039
1.0.1038
1.0.1034
1.0.1033
1.0.1029
1.0.1028
1.0.1026
1.0.1025
1.0.1024
1.0.1023
1.0.1022
1.0.1021
1.0.1020
1.0.1019
1.0.1018
1.0.1017
1.0.1016
1.0.1015
1.0.1014
1.0.1013
1.0.1012
1.0.1011
1.0.1009
1.0.1008
1.0.1007
1.0.1006
1.0.1005
1.0.1004
1.0.1003
1.0.1001
1.0.999
1.0.998
1.0.997
1.0.996
1.0.995
1.0.994
1.0.993
1.0.992
1.0.991
1.0.990
1.0.989
1.0.988
1.0.987
1.0.986
1.0.985
1.0.984
1.0.983
1.0.982
1.0.981
1.0.980
1.0.979
1.0.978
1.0.977
1.0.976
1.0.975
1.0.974
1.0.973
1.0.972
1.0.971
1.0.970
1.0.969
1.0.968
1.0.967
1.0.966
1.0.965
1.0.964
1.0.963
1.0.962
1.0.961
1.0.959
1.0.958
1.0.956
1.0.951
1.0.950
1.0.943
1.0.942
1.0.941
1.0.940
1.0.938
1.0.936
1.0.935
1.0.931
1.0.929
1.0.928
1.0.927
1.0.926
1.0.925
1.0.924
1.0.923
1.0.921
1.0.920
1.0.919
1.0.918
1.0.917
1.0.916
1.0.911
1.0.910
1.0.902
1.0.899
1.0.898
1.0.897
1.0.896
1.0.894
1.0.893
1.0.891
1.0.890
1.0.889
1.0.888
1.0.887
1.0.886
1.0.885
1.0.884
1.0.883
1.0.882
1.0.881
1.0.880
1.0.879
1.0.878
1.0.877
1.0.26
1.0.25
1.0.22
1.0.21
1.0.20
1.0.19
1.0.15
1.0.14
1.0.13
1.0.12
1.0.10
1.0.9
1.0.8
1.0.7
1.0.6
1.0.5
1.0.4
1.0.3
1.0.2
1.0.1
1.0.0
0.1.0
SDK for GameServer hooks development. Provides type specs, documentation, and IDE autocomplete for GameServer modules without requiring the full server.
Current section
Files
Jump to
Current section
Files
lib/game_server/tournaments.ex
defmodule GameServer.Tournaments do
@moduledoc ~S"""
Bracket tournaments: registration → seeded single-elimination draw → timed
rounds → champions. See TOURNAMENT_DESIGN.md.
Core owns the structure (registration, seeding, rounds, deadlines,
advancement, recurrence). Gameplay and judgment belong to the game: when a
match becomes playable the `tournament_match_ready` hook fires, the game
plays it however it wants (a lobby, solo runs, anything) and reports the
verdict with `resolve_match/2`. Unresolved matches past their deadline_at fire
`tournament_match_expired` for the game to adjudicate; the tournament's
`deadline_policy` applies only if it doesn't.
Realtime: entry leaders receive `{:tournament_event, event, payload}` on the
`"tournaments:user:<user_id>"` PubSub topic (forwarded by the user channel
as `tournament_*` events).
**Note:** This is an SDK stub. Calling these functions will raise an error.
The actual implementation runs on the GameServer.
"""
@doc ~S"""
Applies any due state transition to one tournament and returns the current
row. Called lazily from API paths and periodically from `tick/0`.
"""
@spec advance_lifecycle(GameServer.Tournaments.Tournament.t(), DateTime.t()) ::
GameServer.Tournaments.Tournament.t()
def advance_lifecycle(_tournament, _now) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
nil
_ ->
raise "GameServer.Tournaments.advance_lifecycle/2 is a stub - only available at runtime on GameServer"
end
end
@doc ~S"""
Rounds needed to win a bracket of `size` slots (2→1, 4→2, 8→3).
"""
@spec bracket_rounds(pos_integer()) :: pos_integer()
def bracket_rounds(_size) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
0
_ ->
raise "GameServer.Tournaments.bracket_rounds/1 is a stub - only available at runtime on GameServer"
end
end
@doc ~S"""
Smallest power of two seating `n` entries, min 2, capped at `max`.
"""
@spec bracket_size_for(pos_integer(), pos_integer()) :: pos_integer()
def bracket_size_for(_n, _max) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
0
_ ->
raise "GameServer.Tournaments.bracket_size_for/2 is a stub - only available at runtime on GameServer"
end
end
@doc ~S"""
Cancels a tournament (terminal, no hooks fired, no recurrence spawn).
"""
@spec cancel_tournament(GameServer.Tournaments.Tournament.t()) ::
{:ok, GameServer.Tournaments.Tournament.t()} | {:error, term()}
def cancel_tournament(_tournament) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
{:ok, %GameServer.Tournaments.Tournament{id: "", slug: "", title: "", description: "", state: "scheduled", registration_opens_at: nil, starts_at: nil, ends_at: nil, recur: nil, max_entries: nil, team_size: 1, bracket_size: 8, round_window_sec: 3600, deadline_policy: "forfeit_both", metadata: %{}, inserted_at: ~U[1970-01-01 00:00:00Z], updated_at: ~U[1970-01-01 00:00:00Z]}}
_ ->
raise "GameServer.Tournaments.cancel_tournament/1 is a stub - only available at runtime on GameServer"
end
end
@doc false
@spec change_tournament(GameServer.Tournaments.Tournament.t(), map()) :: Ecto.Changeset.t()
def change_tournament(_tournament, _attrs) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
nil
_ ->
raise "GameServer.Tournaments.change_tournament/2 is a stub - only available at runtime on GameServer"
end
end
@doc false
@spec count_brackets(Ecto.UUID.t()) :: non_neg_integer()
def count_brackets(_tournament_id) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
0
_ ->
raise "GameServer.Tournaments.count_brackets/1 is a stub - only available at runtime on GameServer"
end
end
@doc ~S"""
Counts entries. Accepts the same `:state` and `:search` options as the listing.
"""
@spec count_entries(
Ecto.UUID.t(),
keyword()
) :: non_neg_integer()
def count_entries(_tournament_id, _opts) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
0
_ ->
raise "GameServer.Tournaments.count_entries/2 is a stub - only available at runtime on GameServer"
end
end
@doc ~S"""
Counts distinct tournament slugs.
"""
@spec count_tournament_groups() :: non_neg_integer()
def count_tournament_groups() do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
0
_ ->
raise "GameServer.Tournaments.count_tournament_groups/0 is a stub - only available at runtime on GameServer"
end
end
@doc false
@spec count_tournaments(keyword()) :: non_neg_integer()
def count_tournaments(_opts) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
0
_ ->
raise "GameServer.Tournaments.count_tournaments/1 is a stub - only available at runtime on GameServer"
end
end
@doc false
@spec create_tournament(map()) ::
{:ok, GameServer.Tournaments.Tournament.t()} | {:error, Ecto.Changeset.t()}
def create_tournament(_attrs) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
{:ok, %GameServer.Tournaments.Tournament{id: "", slug: "", title: "", description: "", state: "scheduled", registration_opens_at: nil, starts_at: nil, ends_at: nil, recur: nil, max_entries: nil, team_size: 1, bracket_size: 8, round_window_sec: 3600, deadline_policy: "forfeit_both", metadata: %{}, inserted_at: ~U[1970-01-01 00:00:00Z], updated_at: ~U[1970-01-01 00:00:00Z]}}
_ ->
raise "GameServer.Tournaments.create_tournament/1 is a stub - only available at runtime on GameServer"
end
end
@doc false
@spec delete_tournament(GameServer.Tournaments.Tournament.t()) ::
{:ok, GameServer.Tournaments.Tournament.t()} | {:error, term()}
def delete_tournament(_tournament) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
{:ok, %GameServer.Tournaments.Tournament{id: "", slug: "", title: "", description: "", state: "scheduled", registration_opens_at: nil, starts_at: nil, ends_at: nil, recur: nil, max_entries: nil, team_size: 1, bracket_size: 8, round_window_sec: 3600, deadline_policy: "forfeit_both", metadata: %{}, inserted_at: ~U[1970-01-01 00:00:00Z], updated_at: ~U[1970-01-01 00:00:00Z]}}
_ ->
raise "GameServer.Tournaments.delete_tournament/1 is a stub - only available at runtime on GameServer"
end
end
@doc ~S"""
Entries by id, for rendering a bracket without loading the whole field.
"""
@spec entries_by_id(Ecto.UUID.t(), [Ecto.UUID.t()]) :: %{
required(Ecto.UUID.t()) => GameServer.Tournaments.Entry.t()
}
def entries_by_id(_tournament_id, _entry_ids) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
nil
_ ->
raise "GameServer.Tournaments.entries_by_id/2 is a stub - only available at runtime on GameServer"
end
end
@doc false
@spec get_bracket(Ecto.UUID.t(), integer()) :: GameServer.Tournaments.Bracket.t() | nil
def get_bracket(_tournament_id, _index) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
if :erlang.phash2(make_ref(), 2) == 0, do: nil, else: %GameServer.Tournaments.Bracket{id: "", tournament_id: "", index: 0, size: 8, inserted_at: ~U[1970-01-01 00:00:00Z]}
_ ->
raise "GameServer.Tournaments.get_bracket/2 is a stub - only available at runtime on GameServer"
end
end
@doc false
@spec get_entry(Ecto.UUID.t(), Ecto.UUID.t()) :: GameServer.Tournaments.Entry.t() | nil
def get_entry(_tournament_id, _leader_id) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
if :erlang.phash2(make_ref(), 2) == 0, do: nil, else: %GameServer.Tournaments.Entry{id: "", tournament_id: "", leader_id: "", seed: nil, bracket_index: nil, wins: 0, state: "registered", metadata: %{}, inserted_at: ~U[1970-01-01 00:00:00Z], updated_at: ~U[1970-01-01 00:00:00Z]}
_ ->
raise "GameServer.Tournaments.get_entry/2 is a stub - only available at runtime on GameServer"
end
end
@doc false
@spec get_match(Ecto.UUID.t()) :: GameServer.Tournaments.Match.t() | nil
def get_match(_match_id) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
if :erlang.phash2(make_ref(), 2) == 0, do: nil, else: %GameServer.Tournaments.Match{id: "", tournament_id: "", bracket_index: 0, round: 1, slot: 0, a_entry_id: nil, b_entry_id: nil, winner_entry_id: nil, ready_at: nil, expired_at: nil, resolved_at: nil, deadline_at: ~U[1970-01-01 00:00:00Z], metadata: %{}, inserted_at: ~U[1970-01-01 00:00:00Z], updated_at: ~U[1970-01-01 00:00:00Z]}
_ ->
raise "GameServer.Tournaments.get_match/1 is a stub - only available at runtime on GameServer"
end
end
@doc false
@spec get_tournament(Ecto.UUID.t()) :: GameServer.Tournaments.Tournament.t() | nil
def get_tournament(_id) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
if :erlang.phash2(make_ref(), 2) == 0, do: nil, else: %GameServer.Tournaments.Tournament{id: "", slug: "", title: "", description: "", state: "scheduled", registration_opens_at: nil, starts_at: nil, ends_at: nil, recur: nil, max_entries: nil, team_size: 1, bracket_size: 8, round_window_sec: 3600, deadline_policy: "forfeit_both", metadata: %{}, inserted_at: ~U[1970-01-01 00:00:00Z], updated_at: ~U[1970-01-01 00:00:00Z]}
_ ->
raise "GameServer.Tournaments.get_tournament/1 is a stub - only available at runtime on GameServer"
end
end
@doc false
@spec get_tournament!(Ecto.UUID.t()) :: GameServer.Tournaments.Tournament.t()
def get_tournament!(_id) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
nil
_ ->
raise "GameServer.Tournaments.get_tournament!/1 is a stub - only available at runtime on GameServer"
end
end
@doc ~S"""
The current occurrence for a slug: the latest one that is not finished or
cancelled, falling back to the most recent row.
"""
@spec get_tournament_by_slug(String.t()) :: GameServer.Tournaments.Tournament.t() | nil
def get_tournament_by_slug(_slug) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
if :erlang.phash2(make_ref(), 2) == 0, do: nil, else: %GameServer.Tournaments.Tournament{id: "", slug: "", title: "", description: "", state: "scheduled", registration_opens_at: nil, starts_at: nil, ends_at: nil, recur: nil, max_entries: nil, team_size: 1, bracket_size: 8, round_window_sec: 3600, deadline_policy: "forfeit_both", metadata: %{}, inserted_at: ~U[1970-01-01 00:00:00Z], updated_at: ~U[1970-01-01 00:00:00Z]}
_ ->
raise "GameServer.Tournaments.get_tournament_by_slug/1 is a stub - only available at runtime on GameServer"
end
end
@doc ~S"""
Registers `user` as an entry leader. Runs the `before_tournament_register`
pipeline (games gate/charge entry there) and fires
`after_tournament_register` on success.
"""
@spec join_tournament(GameServer.Accounts.User.t(), GameServer.Tournaments.Tournament.t()) ::
{:ok, GameServer.Tournaments.Entry.t()} | {:error, term()}
def join_tournament(_user, _tournament) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
{:ok, %GameServer.Tournaments.Entry{id: "", tournament_id: "", leader_id: "", seed: nil, bracket_index: nil, wins: 0, state: "registered", metadata: %{}, inserted_at: ~U[1970-01-01 00:00:00Z], updated_at: ~U[1970-01-01 00:00:00Z]}}
_ ->
raise "GameServer.Tournaments.join_tournament/2 is a stub - only available at runtime on GameServer"
end
end
@doc ~S"""
Withdraws `user`'s entry. Only before the draw; `before_tournament_leave` can veto.
"""
@spec leave_tournament(GameServer.Accounts.User.t(), GameServer.Tournaments.Tournament.t()) ::
{:ok, GameServer.Tournaments.Tournament.t()} | {:error, term()}
def leave_tournament(_user, _tournament) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
{:ok, %GameServer.Tournaments.Tournament{id: "", slug: "", title: "", description: "", state: "scheduled", registration_opens_at: nil, starts_at: nil, ends_at: nil, recur: nil, max_entries: nil, team_size: 1, bracket_size: 8, round_window_sec: 3600, deadline_policy: "forfeit_both", metadata: %{}, inserted_at: ~U[1970-01-01 00:00:00Z], updated_at: ~U[1970-01-01 00:00:00Z]}}
_ ->
raise "GameServer.Tournaments.leave_tournament/2 is a stub - only available at runtime on GameServer"
end
end
@doc ~S"""
Brackets for a tournament. Options: `:page`, `:page_size`.
"""
@spec list_brackets(
Ecto.UUID.t(),
keyword()
) :: [GameServer.Tournaments.Bracket.t()]
def list_brackets(_tournament_id, _opts) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
[]
_ ->
raise "GameServer.Tournaments.list_brackets/2 is a stub - only available at runtime on GameServer"
end
end
@doc ~S"""
Entries for a tournament, oldest first (registration order = seed rank).
Options: `:page`, `:page_size` (capped at 100), `:state`, plus
* `:search` — filter by leader name (display name or username)
* `:preload_leader` — preload the leader, for callers that render names
* `:order` — `:bracket` groups drawn entries by bracket and seed instead
"""
@spec list_entries(
Ecto.UUID.t(),
keyword()
) :: [GameServer.Tournaments.Entry.t()]
def list_entries(_tournament_id, _opts) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
[]
_ ->
raise "GameServer.Tournaments.list_entries/2 is a stub - only available at runtime on GameServer"
end
end
@doc ~S"""
Matches for a tournament, bracket-major order.
Options: `:bracket_index` (single bracket), `:bracket_indexes` (several).
"""
@spec list_matches(
Ecto.UUID.t(),
keyword()
) :: [GameServer.Tournaments.Match.t()]
def list_matches(_tournament_id, _opts) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
[]
_ ->
raise "GameServer.Tournaments.list_matches/2 is a stub - only available at runtime on GameServer"
end
end
@doc ~S"""
Every occurrence of a slug, newest first.
"""
@spec list_occurrences(String.t()) :: [GameServer.Tournaments.Tournament.t()]
def list_occurrences(_slug) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
[]
_ ->
raise "GameServer.Tournaments.list_occurrences/1 is a stub - only available at runtime on GameServer"
end
end
@doc ~S"""
Tournaments grouped by slug — one entry per tournament *type*, the way
leaderboard seasons are grouped.
Each group carries the newest occurrence's title/description, the id of the
occurrence to open by default (the live one, else the newest), and how many
editions exist.
"""
@spec list_tournament_groups(keyword()) :: [map()]
def list_tournament_groups(_opts) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
%{}
_ ->
raise "GameServer.Tournaments.list_tournament_groups/1 is a stub - only available at runtime on GameServer"
end
end
@doc false
@spec list_tournaments(keyword()) :: [GameServer.Tournaments.Tournament.t()]
def list_tournaments(_opts) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
[]
_ ->
raise "GameServer.Tournaments.list_tournaments/1 is a stub - only available at runtime on GameServer"
end
end
@doc ~S"""
The match a slot reaches in `round` (standard folding).
"""
@spec match_index(non_neg_integer(), pos_integer()) :: non_neg_integer()
def match_index(_slot, _round) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
0
_ ->
raise "GameServer.Tournaments.match_index/2 is a stub - only available at runtime on GameServer"
end
end
@doc ~S"""
The match struct with tournament and both entries preloaded (hook payload).
"""
@spec match_payload(GameServer.Tournaments.Tournament.t(), GameServer.Tournaments.Match.t()) ::
GameServer.Tournaments.Match.t()
def match_payload(_tournament, _match) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
nil
_ ->
raise "GameServer.Tournaments.match_payload/2 is a stub - only available at runtime on GameServer"
end
end
@doc ~S"""
The caller's current unresolved match (their entry filled in a slot), if any.
"""
@spec my_match(GameServer.Tournaments.Tournament.t(), Ecto.UUID.t()) ::
GameServer.Tournaments.Match.t() | nil
def my_match(_tournament, _user_id) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
if :erlang.phash2(make_ref(), 2) == 0, do: nil, else: %GameServer.Tournaments.Match{id: "", tournament_id: "", bracket_index: 0, round: 1, slot: 0, a_entry_id: nil, b_entry_id: nil, winner_entry_id: nil, ready_at: nil, expired_at: nil, resolved_at: nil, deadline_at: ~U[1970-01-01 00:00:00Z], metadata: %{}, inserted_at: ~U[1970-01-01 00:00:00Z], updated_at: ~U[1970-01-01 00:00:00Z]}
_ ->
raise "GameServer.Tournaments.my_match/2 is a stub - only available at runtime on GameServer"
end
end
@doc ~S"""
Reopens a cancelled tournament.
A tournament that was never drawn goes back to `registration`; one that
already has a bracket resumes at `running`, so an accidental cancel does not
throw away the draw. Any due transition is applied immediately afterwards.
"""
@spec reopen_tournament(GameServer.Tournaments.Tournament.t()) ::
{:ok, GameServer.Tournaments.Tournament.t()} | {:error, term()}
def reopen_tournament(_tournament) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
{:ok, %GameServer.Tournaments.Tournament{id: "", slug: "", title: "", description: "", state: "scheduled", registration_opens_at: nil, starts_at: nil, ends_at: nil, recur: nil, max_entries: nil, team_size: 1, bracket_size: 8, round_window_sec: 3600, deadline_policy: "forfeit_both", metadata: %{}, inserted_at: ~U[1970-01-01 00:00:00Z], updated_at: ~U[1970-01-01 00:00:00Z]}}
_ ->
raise "GameServer.Tournaments.reopen_tournament/1 is a stub - only available at runtime on GameServer"
end
end
@doc ~S"""
Records the verdict for a match: the winning entry's id, or `:no_winner`
(double forfeit — the next round's seat stays empty and cascades as a bye).
First write wins; anything later returns `{:error, :already_resolved}`. The
`before_tournament_result` pipeline can veto, leaving the match open.
"""
@spec resolve_match(Ecto.UUID.t(), Ecto.UUID.t() | :no_winner) ::
{:ok, GameServer.Tournaments.Match.t()} | {:error, term()}
def resolve_match(_match_id, _winner) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
{:ok, %GameServer.Tournaments.Match{id: "", tournament_id: "", bracket_index: 0, round: 1, slot: 0, a_entry_id: nil, b_entry_id: nil, winner_entry_id: nil, ready_at: nil, expired_at: nil, resolved_at: nil, deadline_at: ~U[1970-01-01 00:00:00Z], metadata: %{}, inserted_at: ~U[1970-01-01 00:00:00Z], updated_at: ~U[1970-01-01 00:00:00Z]}}
_ ->
raise "GameServer.Tournaments.resolve_match/2 is a stub - only available at runtime on GameServer"
end
end
@doc ~S"""
Unix-independent deadline_at for `round`, anchored to `starts_at`.
"""
@spec round_deadline(GameServer.Tournaments.Tournament.t(), pos_integer()) :: DateTime.t()
def round_deadline(_tournament, _round) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
nil
_ ->
raise "GameServer.Tournaments.round_deadline/2 is a stub - only available at runtime on GameServer"
end
end
@doc ~S"""
Matches in `round` of a bracket of `size` slots.
"""
@spec round_matches(pos_integer(), pos_integer()) :: pos_integer()
def round_matches(_size, _round) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
0
_ ->
raise "GameServer.Tournaments.round_matches/2 is a stub - only available at runtime on GameServer"
end
end
@doc ~S"""
When `round` becomes playable (its window start).
"""
@spec round_opens_at(GameServer.Tournaments.Tournament.t(), pos_integer()) :: DateTime.t()
def round_opens_at(_tournament, _round) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
nil
_ ->
raise "GameServer.Tournaments.round_opens_at/2 is a stub - only available at runtime on GameServer"
end
end
@doc ~S"""
Standard single-elimination seeding order for a power-of-two `size`:
slot `i` holds this seed rank (1-based); top seeds are spread apart.
"""
@spec standard_seed_order(pos_integer()) :: [pos_integer()]
def standard_seed_order(_size) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
0
_ ->
raise "GameServer.Tournaments.standard_seed_order/1 is a stub - only available at runtime on GameServer"
end
end
@doc ~S"""
Final (or current) placements: champions first, then by wins.
"""
@spec standings(GameServer.Tournaments.Tournament.t()) :: map()
def standings(_tournament) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
%{}
_ ->
raise "GameServer.Tournaments.standings/1 is a stub - only available at runtime on GameServer"
end
end
@doc ~S"""
Aggregate counts for the admin dashboard.
Four grouped/filtered queries, all index-backed (`tournaments.state`,
`tournament_entries.state`, and the partial `tournament_matches` index on
open matches).
"""
@spec stats() :: %{
tournaments: map(),
entries: map(),
matches: %{total: non_neg_integer(), open: non_neg_integer(), overdue: non_neg_integer()}
}
def stats() do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
nil
_ ->
raise "GameServer.Tournaments.stats/0 is a stub - only available at runtime on GameServer"
end
end
@doc ~S"""
Periodic driver, called by `GameServer.Tournaments.Ticker`. Runs every
transition, match-ready firing, deadline_at sweep, and recurrence spawn that is
due. Serialized cluster-wide so hooks fire once.
"""
@spec tick(DateTime.t()) :: :ok
def tick(_now) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
:ok
_ ->
raise "GameServer.Tournaments.tick/1 is a stub - only available at runtime on GameServer"
end
end
@doc ~S"""
Deep-merges `map` into the match's metadata (game scratch space).
Serialized per match and merged recursively so concurrent writers touching
different nested keys (e.g. each player's run under `"runs"`) never clobber
each other.
"""
@spec update_match_metadata(Ecto.UUID.t(), map()) ::
{:ok, GameServer.Tournaments.Match.t()} | {:error, term()}
def update_match_metadata(_match_id, _map) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
{:ok, %GameServer.Tournaments.Match{id: "", tournament_id: "", bracket_index: 0, round: 1, slot: 0, a_entry_id: nil, b_entry_id: nil, winner_entry_id: nil, ready_at: nil, expired_at: nil, resolved_at: nil, deadline_at: ~U[1970-01-01 00:00:00Z], metadata: %{}, inserted_at: ~U[1970-01-01 00:00:00Z], updated_at: ~U[1970-01-01 00:00:00Z]}}
_ ->
raise "GameServer.Tournaments.update_match_metadata/2 is a stub - only available at runtime on GameServer"
end
end
@doc false
@spec update_tournament(GameServer.Tournaments.Tournament.t(), map()) ::
{:ok, GameServer.Tournaments.Tournament.t()} | {:error, Ecto.Changeset.t()}
def update_tournament(_tournament, _attrs) do
case Application.get_env(:game_server_sdk, :stub_mode, :raise) do
:placeholder ->
{:ok, %GameServer.Tournaments.Tournament{id: "", slug: "", title: "", description: "", state: "scheduled", registration_opens_at: nil, starts_at: nil, ends_at: nil, recur: nil, max_entries: nil, team_size: 1, bracket_size: 8, round_window_sec: 3600, deadline_policy: "forfeit_both", metadata: %{}, inserted_at: ~U[1970-01-01 00:00:00Z], updated_at: ~U[1970-01-01 00:00:00Z]}}
_ ->
raise "GameServer.Tournaments.update_tournament/2 is a stub - only available at runtime on GameServer"
end
end
end