xp_calculator.ex 1.2 KB
Newer Older
nikolauska's avatar
nikolauska committed
1
defmodule CodeStats.XP.XPCalculator do
Mikko Ahlroth's avatar
Mikko Ahlroth committed
2 3 4 5
  @moduledoc """
  Calculations for levels based on XP.
  """

6
  @level_factor 0.025
Mikko Ahlroth's avatar
Mikko Ahlroth committed
7 8 9

  @doc """
  Get the level based on given XP.
10 11 12 13 14 15 16 17 18

      iex> CodeStats.XP.XPCalculator.get_level(0)
      0

      iex> CodeStats.XP.XPCalculator.get_level(6400)
      2

      iex> CodeStats.XP.XPCalculator.get_level(-1000)
      0
Mikko Ahlroth's avatar
Mikko Ahlroth committed
19
  """
Mikko Ahlroth's avatar
Mikko Ahlroth committed
20
  @spec get_level(integer()) :: integer()
21
  def get_level(xp) when xp > 0 do
Mikko Ahlroth's avatar
Mikko Ahlroth committed
22 23 24 25
    Float.floor(@level_factor * :math.sqrt(xp))
    |> trunc
  end

26 27
  def get_level(xp) when xp <= 0, do: 0

Mikko Ahlroth's avatar
Mikko Ahlroth committed
28 29 30
  @doc """
  Get the amount of XP required to reach the next level from the given level.
  """
Mikko Ahlroth's avatar
Mikko Ahlroth committed
31
  @spec get_next_level_xp(integer()) :: integer()
Mikko Ahlroth's avatar
Mikko Ahlroth committed
32 33 34 35 36 37 38 39
  def get_next_level_xp(level) do
    :math.pow(Float.ceil((level + 1) / @level_factor), 2)
    |> trunc
  end

  @doc """
  Get the progress to the next level in percentage.
  """
Mikko Ahlroth's avatar
Mikko Ahlroth committed
40
  @spec get_level_progress(integer()) :: integer()
Mikko Ahlroth's avatar
Mikko Ahlroth committed
41 42 43 44 45
  def get_level_progress(xp) do
    level = get_level(xp)
    current_level_xp = get_next_level_xp(level - 1)
    next_level_xp = get_next_level_xp(level)

46
    have_xp = xp - current_level_xp
Mikko Ahlroth's avatar
Mikko Ahlroth committed
47
    needed_xp = next_level_xp - current_level_xp
48 49

    Float.round(have_xp / needed_xp * 100)
Mikko Ahlroth's avatar
Mikko Ahlroth committed
50 51 52
    |> trunc
  end
end