GameServer.Achievements (game_server_core v1.0.959)

Copy Markdown

The Achievements context.

Manages achievement definitions and user progress/unlocks.

Usage

# Create an achievement (admin)
{:ok, ach} = Achievements.create_achievement(%{
  slug: "first_lobby",
  title: "Welcome!",
  description: "Join your first lobby",
  progress_target: 1
})

# Unlock a one-shot achievement
{:ok, ua} = Achievements.unlock_achievement(user_id, "first_lobby")

# Increment progress on a multi-step achievement
{:ok, ua} = Achievements.increment_progress(user_id, "chat_100", 1)
# auto-unlocks when progress >= progress_target

# List achievements (with user progress if user_id provided)
achievements = Achievements.list_achievements(user_id: user_id, page: 1, page_size: 25)

Summary

Functions

Returns a changeset for tracking achievement changes (used by forms).

Count achievements (for pagination). Supports :include_hidden, :filter, and :user_id.

Count all achievements (including hidden), for admin dashboard.

Count all user achievement unlock records.

Count hidden achievements.

Count unlocked achievements for a user.

Count distinct users who have unlocked at least one achievement.

Creates a new achievement definition.

Returns achievement statistics for the admin dashboard.

Deletes an achievement and all related user progress.

Get an achievement by ID.

Get an achievement by slug.

Get a user's progress on a specific achievement.

Grant achievement to user by slug (admin convenience, calls unlock_achievement).

Increment progress on an achievement for a user. Automatically unlocks when progress reaches the target.

Lists all achievements, optionally with user progress.

Lists all achievements unlocked by a user.

Reset a user's progress on a specific achievement (admin use).

Revoke an achievement from a user. Deletes the user_achievement record entirely.

Subscribe to global achievement events (new definitions, updates, unlocks).

Unlock an achievement for a user by slug. If it's a progress-based achievement, sets progress to the target and marks it as unlocked.

Get unlock percentage for an achievement (0.0 to 100.0).

Updates an achievement definition.

Functions

change_achievement(achievement, attrs \\ %{})

@spec change_achievement(GameServer.Achievements.Achievement.t(), map()) ::
  Ecto.Changeset.t()

Returns a changeset for tracking achievement changes (used by forms).

count_achievements(opts \\ [])

@spec count_achievements(keyword()) :: non_neg_integer()

Count achievements (for pagination). Supports :include_hidden, :filter, and :user_id.

count_all_achievements()

@spec count_all_achievements() :: non_neg_integer()

Count all achievements (including hidden), for admin dashboard.

count_all_unlocks()

@spec count_all_unlocks() :: non_neg_integer()

Count all user achievement unlock records.

count_hidden_achievements()

@spec count_hidden_achievements() :: non_neg_integer()

Count hidden achievements.

count_user_achievements(user_id)

@spec count_user_achievements(integer()) :: non_neg_integer()

Count unlocked achievements for a user.

count_users_with_unlocks()

@spec count_users_with_unlocks() :: non_neg_integer()

Count distinct users who have unlocked at least one achievement.

create_achievement(attrs)

@spec create_achievement(map()) ::
  {:ok, GameServer.Achievements.Achievement.t()} | {:error, Ecto.Changeset.t()}

Creates a new achievement definition.

dashboard_stats()

@spec dashboard_stats() :: map()

Returns achievement statistics for the admin dashboard.

Returns a map with:

  • hidden — number of hidden achievements
  • users_with_unlocks — users who unlocked at least one
  • avg_unlocks_per_user — average unlocks per user (among users who have any)
  • most_unlocked{slug, title, count} of the most-unlocked achievement
  • least_unlocked{slug, title, count} of the least-unlocked achievement (with at least 1 unlock)

delete_achievement(achievement)

Deletes an achievement and all related user progress.

get_achievement(id)

@spec get_achievement(integer()) :: GameServer.Achievements.Achievement.t() | nil

Get an achievement by ID.

get_achievement_by_slug(slug)

@spec get_achievement_by_slug(String.t()) ::
  GameServer.Achievements.Achievement.t() | nil

Get an achievement by slug.

get_user_achievement(user_id, achievement_id)

@spec get_user_achievement(integer(), integer()) ::
  GameServer.Achievements.UserAchievement.t() | nil

Get a user's progress on a specific achievement.

grant_achievement(user_id, slug)

@spec grant_achievement(integer(), String.t()) ::
  {:ok, GameServer.Achievements.UserAchievement.t()} | {:error, atom()}

Grant achievement to user by slug (admin convenience, calls unlock_achievement).

increment_progress(user_id, slug, amount \\ 1)

@spec increment_progress(integer(), String.t(), pos_integer()) ::
  {:ok, GameServer.Achievements.UserAchievement.t()} | {:error, atom()}

Increment progress on an achievement for a user. Automatically unlocks when progress reaches the target.

Returns {:ok, user_achievement}.

list_achievements(opts \\ [])

@spec list_achievements(keyword()) :: [map()]

Lists all achievements, optionally with user progress.

Options

  • :user_id — if provided, includes user progress/unlock status
  • :page — page number (default: 1)
  • :page_size — items per page (default: 25)
  • :include_hidden — if true, include hidden achievements (default: false)

list_user_achievements(user_id, opts \\ [])

@spec list_user_achievements(
  integer(),
  keyword()
) :: [GameServer.Achievements.UserAchievement.t()]

Lists all achievements unlocked by a user.

reset_user_achievement(user_id, achievement_id)

@spec reset_user_achievement(integer(), integer()) ::
  {:ok, GameServer.Achievements.UserAchievement.t() | :not_found}
  | {:error, Ecto.Changeset.t()}

Reset a user's progress on a specific achievement (admin use).

revoke_achievement(user_id, achievement_id)

@spec revoke_achievement(integer(), integer()) ::
  {:ok, GameServer.Achievements.UserAchievement.t()} | {:error, atom()}

Revoke an achievement from a user. Deletes the user_achievement record entirely.

subscribe_achievements()

@spec subscribe_achievements() :: :ok | {:error, term()}

Subscribe to global achievement events (new definitions, updates, unlocks).

unlock_achievement(user_id, slug)

@spec unlock_achievement(integer(), String.t() | integer()) ::
  {:ok, GameServer.Achievements.UserAchievement.t()} | {:error, atom()}

Unlock an achievement for a user by slug. If it's a progress-based achievement, sets progress to the target and marks it as unlocked.

Returns {:ok, user_achievement} or {:error, reason}.

unlock_percentage(achievement_id)

@spec unlock_percentage(integer()) :: float()

Get unlock percentage for an achievement (0.0 to 100.0).

update_achievement(achievement, attrs)

@spec update_achievement(GameServer.Achievements.Achievement.t(), map()) ::
  {:ok, GameServer.Achievements.Achievement.t()} | {:error, Ecto.Changeset.t()}

Updates an achievement definition.