1
0
mirror of https://github.com/avitex/elixir-glicko synced 2025-04-18 13:49:57 +00:00

Convert Player (v1/v2) and Result to structs

In an effort to give names to core concepts in the library, replace the
current way of passing around tuples (of varying length and content)
with appropriately named structs.

As a consequence of creating `Player.{V1, V2}` and `Result`, a variety
of functions that extracted values out of the tuples have either been
removed or changed to access struct fields instead.
This commit is contained in:
Mikael Muszynski 2020-02-05 05:15:20 +01:00
parent ca76ae6f9a
commit ce08ab5e24
6 changed files with 151 additions and 157 deletions

View File

@ -8,30 +8,30 @@ defmodule Glicko do
Get a player's new rating after a series of matches in a rating period. Get a player's new rating after a series of matches in a rating period.
iex> results = [Result.new(Player.new_v1([rating: 1400, rating_deviation: 30]), :win), iex> results = [Result.new(%Player.V1{rating: 1400, rating_deviation: 30}, :win),
...> Result.new(Player.new_v1([rating: 1550, rating_deviation: 100]), :loss), ...> Result.new(%Player.V1{rating: 1550, rating_deviation: 100}, :loss),
...> Result.new(Player.new_v1([rating: 1700, rating_deviation: 300]), :loss)] ...> Result.new(%Player.V1{rating: 1700, rating_deviation: 300}, :loss)]
iex> player = Player.new_v1([rating: 1500, rating_deviation: 200]) iex> player = %Player.V1{rating: 1500, rating_deviation: 200}
iex> Glicko.new_rating(player, results, [system_constant: 0.5]) iex> Glicko.new_rating(player, results, [system_constant: 0.5])
{1464.0506705393013, 151.51652412385727} %Player.V1{rating: 1464.0506705393013, rating_deviation: 151.51652412385727}
Get a player's new rating when they haven't played within a rating period. Get a player's new rating when they haven't played within a rating period.
iex> player = Player.new_v1([rating: 1500, rating_deviation: 200]) iex> player = %Player.V1{rating: 1500, rating_deviation: 200}
iex> Glicko.new_rating(player, [], [system_constant: 0.5]) iex> Glicko.new_rating(player, [], [system_constant: 0.5])
{1.5e3, 200.27141669877065} %Player.V1{rating: 1.5e3, rating_deviation: 200.27141669877065}
Calculate the probability of a player winning against an opponent. Calculate the probability of a player winning against an opponent.
iex> player = Player.new_v1 iex> player = %Player.V1{}
iex> opponent = Player.new_v1 iex> opponent = %Player.V1{}
iex> Glicko.win_probability(player, opponent) iex> Glicko.win_probability(player, opponent)
0.5 0.5
Calculate the probability of a player drawing against an opponent. Calculate the probability of a player drawing against an opponent.
iex> player = Player.new_v1 iex> player = %Player.V1{}
iex> opponent = Player.new_v1 iex> opponent = %Player.V1{}
iex> Glicko.draw_probability(player, opponent) iex> Glicko.draw_probability(player, opponent)
1.0 1.0
@ -117,24 +117,33 @@ defmodule Glicko do
Player.t() Player.t()
def new_rating(player, results, opts \\ []) def new_rating(player, results, opts \\ [])
def new_rating(player, results, opts) when tuple_size(player) == 3 do def new_rating(%Player.V2{} = player, results, opts) do
do_new_rating(player, results, opts) do_new_rating(player, results, opts)
end end
def new_rating(player, results, opts) when tuple_size(player) == 2 do def new_rating(%Player.V1{} = player, results, opts) do
player player
|> Player.to_v2() |> Player.to_v2()
|> do_new_rating(results, opts) |> do_new_rating(results, opts)
|> Player.to_v1() |> Player.to_v1()
end end
defp do_new_rating({player_r, player_pre_rd, player_v}, [], _) do defp do_new_rating(%Player.V2{} = player, [], _) do
player_post_rd = calc_player_post_base_rd(:math.pow(player_pre_rd, 2), player_v) player_post_rd =
calc_player_post_base_rd(:math.pow(player.rating_deviation, 2), player.volatility)
{player_r, player_post_rd, player_v} %{player | rating_deviation: player_post_rd}
end end
defp do_new_rating({player_pre_r, player_pre_rd, player_pre_v}, results, opts) do defp do_new_rating(
%Player.V2{
rating: player_pre_r,
rating_deviation: player_pre_rd,
volatility: player_pre_v
},
results,
opts
) do
sys_const = Keyword.get(opts, :system_constant, @default_system_constant) sys_const = Keyword.get(opts, :system_constant, @default_system_constant)
conv_tol = Keyword.get(opts, :convergence_tolerance, @default_convergence_tolerance) conv_tol = Keyword.get(opts, :convergence_tolerance, @default_convergence_tolerance)
@ -184,23 +193,24 @@ defmodule Glicko do
player_post_rd = calc_new_player_rating_deviation(player_post_base_rd, variance_est) player_post_rd = calc_new_player_rating_deviation(player_post_base_rd, variance_est)
player_post_r = calc_new_player_rating(results_effect, player_pre_r, player_post_rd) player_post_r = calc_new_player_rating(results_effect, player_pre_r, player_post_rd)
{player_post_r, player_post_rd, player_post_v} %Player.V2{
rating: player_post_r,
rating_deviation: player_post_rd,
volatility: player_post_v
}
end end
defp result_calculations(results, player_pre_r) do defp result_calculations(results, player_pre_r) do
{variance_estimate_acc, result_effect_acc} = {variance_estimate_acc, result_effect_acc} =
Enum.reduce(results, {0.0, 0.0}, fn result, {variance_estimate_acc, result_effect_acc} -> Enum.reduce(results, {0.0, 0.0}, fn result, {variance_estimate_acc, result_effect_acc} ->
opponent_rd_g = opponent_rd_g = calc_g(result.rating_deviation)
result
|> Result.opponent_rating_deviation()
|> calc_g
win_probability = calc_e(player_pre_r, Result.opponent_rating(result), opponent_rd_g) win_probability = calc_e(player_pre_r, result.rating, opponent_rd_g)
{ {
variance_estimate_acc + variance_estimate_acc +
:math.pow(opponent_rd_g, 2) * win_probability * (1 - win_probability), :math.pow(opponent_rd_g, 2) * win_probability * (1 - win_probability),
result_effect_acc + opponent_rd_g * (Result.score(result) - win_probability) result_effect_acc + opponent_rd_g * (result.score - win_probability)
} }
end) end)

View File

@ -6,104 +6,92 @@ defmodule Glicko.Player do
Create a *v1* player with the default values for an unrated player. Create a *v1* player with the default values for an unrated player.
iex> Player.new_v1 iex> %Player.V1{}
{1.5e3, 350.0} %Player.V1{rating: 1.5e3, rating_deviation: 350.0}
Create a *v2* player with the default values for an unrated player. Create a *v2* player with the default values for an unrated player.
iex> Player.new_v2 iex> %Player.V2{}
{0.0, 2.014761872416068, 0.06} %Player.V2{rating: 0.0, rating_deviation: 2.014761872416068, volatility: 0.06}
Create a player with custom values. Create a player with custom values.
iex> Player.new_v2([rating: 3.0, rating_deviation: 2.0, volatility: 0.05]) iex> %Player.V2{rating: 3.0, rating_deviation: 2.0, volatility: 0.05}
{3.0, 2.0, 0.05} %Player.V2{rating: 3.0, rating_deviation: 2.0, volatility: 0.05}
Convert a *v2* player to a *v1*. Note this drops the volatility. Convert a *v2* player to a *v1*. Note this drops the volatility.
iex> Player.new_v2 |> Player.to_v1 iex> %Player.V2{} |> Player.to_v1
{1.5e3, 350.0} %Player.V1{rating: 1.5e3, rating_deviation: 350.0}
Convert a *v1* player to a *v2*. Convert a *v1* player to a *v2*.
iex> Player.new_v1 |> Player.to_v2(0.06) iex> %Player.V1{} |> Player.to_v2(0.06)
{0.0, 2.014761872416068, 0.06} %Player.V2{rating: 0.0, rating_deviation: 2.014761872416068, volatility: 0.06}
Note calling `to_v1` with a *v1* player or likewise with `to_v2` and a *v2* player Note calling `to_v1` with a *v1* player or likewise with `to_v2` and a *v2* player
will pass-through unchanged. The volatility arg in this case is ignored. will pass-through unchanged. The volatility arg in this case is ignored.
iex> player_v2 = Player.new_v2 iex> player_v2 = %Player.V2{}
iex> player_v2 == Player.to_v2(player_v2) iex> player_v2 == Player.to_v2(player_v2)
true true
""" """
defmodule V1 do
@initial_rating 1500.0
@initial_rating_deviation 350.0
@type t :: %__MODULE__{
rating: float(),
rating_deviation: float()
}
defstruct rating: @initial_rating,
rating_deviation: @initial_rating_deviation
end
defmodule V2 do
@magic_version_scale 173.7178
@magic_version_scale_rating 1500.0
@v1_initial_rating 1500.0
@v1_initial_rating_deviation 350.0
@initial_rating (@v1_initial_rating - @magic_version_scale_rating) / @magic_version_scale
@initial_rating_deviation @v1_initial_rating_deviation / @magic_version_scale
@initial_volatility 0.06
@type t :: %__MODULE__{
rating: float(),
rating_deviation: float(),
volatility: float()
}
defstruct rating: @initial_rating,
rating_deviation: @initial_rating_deviation,
volatility: @initial_volatility
end
@magic_version_scale 173.7178 @magic_version_scale 173.7178
@magic_version_scale_rating 1500.0 @magic_version_scale_rating 1500.0
@type t :: v1 | v2 @type t :: v1 | v2
@type v1 :: {rating, rating_deviation} @type v1 :: V1.t()
@type v2 :: {rating, rating_deviation, volatility} @type v2 :: V2.t()
@type version :: :v1 | :v2 @type version :: :v1 | :v2
@type rating :: float @type rating :: float
@type rating_deviation :: float @type rating_deviation :: float
@type volatility :: float @type volatility :: float
@doc """
The recommended initial rating value for a new player.
"""
@spec initial_rating(version) :: rating
def initial_rating(_version = :v1), do: 1500.0
def initial_rating(_version = :v2) do
:v1 |> initial_rating |> scale_rating_to(:v2)
end
@doc """
The recommended initial rating deviation value for a new player.
"""
@spec initial_rating_deviation(version) :: rating_deviation
def initial_rating_deviation(_version = :v1), do: 350.0
def initial_rating_deviation(_version = :v2) do
:v1 |> initial_rating_deviation |> scale_rating_deviation_to(:v2)
end
@doc """ @doc """
The recommended initial volatility value for a new player. The recommended initial volatility value for a new player.
""" """
@spec initial_volatility :: volatility @spec initial_volatility :: volatility
def initial_volatility, do: 0.06 def initial_volatility, do: 0.06
@doc """
Creates a new v1 player.
If not overriden, will use the default values for an unrated player.
"""
@spec new_v1(rating: rating, rating_deviation: rating_deviation) :: v1
def new_v1(opts \\ []) when is_list(opts) do
{
Keyword.get(opts, :rating, initial_rating(:v1)),
Keyword.get(opts, :rating_deviation, initial_rating_deviation(:v1))
}
end
@doc """
Creates a new v2 player.
If not overriden, will use default values for an unrated player.
"""
@spec new_v2(rating: rating, rating_deviation: rating_deviation, volatility: volatility) :: v2
def new_v2(opts \\ []) when is_list(opts) do
{
Keyword.get(opts, :rating, initial_rating(:v2)),
Keyword.get(opts, :rating_deviation, initial_rating_deviation(:v2)),
Keyword.get(opts, :volatility, initial_volatility())
}
end
@doc """ @doc """
Converts a v2 player to a v1. Converts a v2 player to a v1.
@ -112,12 +100,12 @@ defmodule Glicko.Player do
Note the volatility field used in a v2 player will be lost in the conversion. Note the volatility field used in a v2 player will be lost in the conversion.
""" """
@spec to_v1(player :: t) :: v1 @spec to_v1(player :: t) :: v1
def to_v1({rating, rating_deviation}), do: {rating, rating_deviation} def to_v1(%V1{} = player), do: player
def to_v1({rating, rating_deviation, _}) do def to_v1(%V2{rating: rating, rating_deviation: rating_deviation}) do
{ %V1{
rating |> scale_rating_to(:v1), rating: scale_rating_to(rating, :v1),
rating_deviation |> scale_rating_deviation_to(:v1) rating_deviation: scale_rating_deviation_to(rating_deviation, :v1)
} }
end end
@ -129,53 +117,52 @@ defmodule Glicko.Player do
@spec to_v2(player :: t, volatility :: volatility) :: v2 @spec to_v2(player :: t, volatility :: volatility) :: v2
def to_v2(player, volatility \\ initial_volatility()) def to_v2(player, volatility \\ initial_volatility())
def to_v2({rating, rating_deviation, volatility}, _volatility), def to_v2(%V1{rating: rating, rating_deviation: rating_deviation}, volatility) do
do: {rating, rating_deviation, volatility} %V2{
rating: scale_rating_to(rating, :v2),
def to_v2({rating, rating_deviation}, volatility) do rating_deviation: scale_rating_deviation_to(rating_deviation, :v2),
{ volatility: volatility
rating |> scale_rating_to(:v2),
rating_deviation |> scale_rating_deviation_to(:v2),
volatility
} }
end end
def to_v2(%V2{} = player, _volatility) do
player
end
@doc """ @doc """
A version agnostic method for getting a player's rating. A version agnostic method for getting a player's rating.
""" """
@spec rating(player :: t, as_version :: version) :: rating @spec rating(player :: t, as_version :: version) :: rating
def rating(player, as_version \\ nil) def rating(player, as_version \\ nil)
def rating({rating, _}, nil), do: rating def rating(%_{rating: rating}, nil), do: rating
def rating({rating, _, _}, nil), do: rating def rating(%V1{rating: rating}, :v1), do: rating
def rating({rating, _}, :v1), do: rating def rating(%V2{rating: rating}, :v2), do: rating
def rating({rating, _}, :v2), do: rating |> scale_rating_to(:v2) def rating(%V1{rating: rating}, :v2), do: rating |> scale_rating_to(:v2)
def rating({rating, _, _}, :v1), do: rating |> scale_rating_to(:v1) def rating(%V2{rating: rating}, :v1), do: rating |> scale_rating_to(:v1)
def rating({rating, _, _}, :v2), do: rating
@doc """ @doc """
A version agnostic method for getting a player's rating deviation. A version agnostic method for getting a player's rating deviation.
""" """
@spec rating_deviation(player :: t, as_version :: version) :: rating_deviation @spec rating_deviation(player :: t, as_version :: version) :: rating_deviation
def rating_deviation(player, as_version \\ nil) def rating_deviation(player, as_version \\ nil)
def rating_deviation({_, rating_deviation}, nil), do: rating_deviation def rating_deviation(%V1{rating_deviation: rating_deviation}, nil), do: rating_deviation
def rating_deviation({_, rating_deviation, _}, nil), do: rating_deviation def rating_deviation(%V2{rating_deviation: rating_deviation}, nil), do: rating_deviation
def rating_deviation({_, rating_deviation}, :v1), do: rating_deviation def rating_deviation(%V1{rating_deviation: rating_deviation}, :v1), do: rating_deviation
def rating_deviation(%V2{rating_deviation: rating_deviation}, :v2), do: rating_deviation
def rating_deviation({_, rating_deviation}, :v2), def rating_deviation(%V1{rating_deviation: rating_deviation}, :v2),
do: rating_deviation |> scale_rating_deviation_to(:v2) do: rating_deviation |> scale_rating_deviation_to(:v2)
def rating_deviation({_, rating_deviation, _}, :v1), def rating_deviation(%V2{rating_deviation: rating_deviation}, :v1),
do: rating_deviation |> scale_rating_deviation_to(:v1) do: rating_deviation |> scale_rating_deviation_to(:v1)
def rating_deviation({_, rating_deviation, _}, :v2), do: rating_deviation
@doc """ @doc """
A version agnostic method for getting a player's volatility. A version agnostic method for getting a player's volatility.
""" """
@spec volatility(player :: t, default_volatility :: volatility) :: volatility @spec volatility(player :: t, default_volatility :: volatility) :: volatility
def volatility(player, default_volatility \\ initial_volatility()) def volatility(player, default_volatility \\ initial_volatility())
def volatility({_, _}, default_volatility), do: default_volatility def volatility(%V1{}, default_volatility), do: default_volatility
def volatility({_, _, volatility}, _), do: volatility def volatility(%V2{volatility: volatility}, _), do: volatility
@doc """ @doc """
A convenience function for summarizing a player's strength as a 95% A convenience function for summarizing a player's strength as a 95%

View File

@ -4,17 +4,21 @@ defmodule Glicko.Result do
## Usage ## Usage
iex> opponent = Player.new_v2 iex> opponent = %Player.V2{}
iex> Result.new(opponent, 1.0) iex> Result.new(opponent, 1.0)
{0.0, 2.014761872416068, 1.0} %Result{rating: 0.0, rating_deviation: 2.014761872416068, score: 1.0}
iex> Result.new(opponent, :draw) # With shortcut iex> Result.new(opponent, :draw) # With shortcut
{0.0, 2.014761872416068, 0.5} %Result{rating: 0.0, rating_deviation: 2.014761872416068, score: 0.5}
""" """
alias Glicko.Player alias Glicko.Player
@type t :: {Player.rating(), Player.rating_deviation(), score} @type t :: %__MODULE__{
rating: Player.rating(),
rating_deviation: Player.rating_deviation(),
score: score
}
@type score :: float @type score :: float
@type score_shortcut :: :loss | :draw | :win @type score_shortcut :: :loss | :draw | :win
@ -22,6 +26,8 @@ defmodule Glicko.Result do
@score_shortcut_map %{loss: 0.0, draw: 0.5, win: 1.0} @score_shortcut_map %{loss: 0.0, draw: 0.5, win: 1.0}
@score_shortcuts Map.keys(@score_shortcut_map) @score_shortcuts Map.keys(@score_shortcut_map)
defstruct [:rating, :rating_deviation, :score]
@doc """ @doc """
Creates a new result from an opponent rating, opponent rating deviation and score. Creates a new result from an opponent rating, opponent rating deviation and score.
@ -31,12 +37,17 @@ defmodule Glicko.Result do
""" """
@spec new(Player.rating(), Player.rating_deviation(), score | score_shortcut) :: t @spec new(Player.rating(), Player.rating_deviation(), score | score_shortcut) :: t
def new(opponent_rating, opponent_rating_deviation, score) when is_number(score) do def new(opponent_rating, opponent_rating_deviation, score) when is_number(score) do
{opponent_rating, opponent_rating_deviation, score} %__MODULE__{
rating: opponent_rating,
rating_deviation: opponent_rating_deviation,
score: score
}
end end
def new(opponent_rating, opponent_rating_deviation, score_type) def new(opponent_rating, opponent_rating_deviation, score_type)
when is_atom(score_type) and score_type in @score_shortcuts do when is_atom(score_type) and score_type in @score_shortcuts do
{opponent_rating, opponent_rating_deviation, Map.fetch!(@score_shortcut_map, score_type)} score = Map.fetch!(@score_shortcut_map, score_type)
new(opponent_rating, opponent_rating_deviation, score)
end end
@doc """ @doc """
@ -48,22 +59,4 @@ defmodule Glicko.Result do
def new(opponent, score) do def new(opponent, score) do
new(Player.rating(opponent, :v2), Player.rating_deviation(opponent, :v2), score) new(Player.rating(opponent, :v2), Player.rating_deviation(opponent, :v2), score)
end end
@doc """
Convenience function for accessing an opponent's rating.
"""
@spec opponent_rating(result :: Result.t()) :: Player.rating()
def opponent_rating(_result = {rating, _, _}), do: rating
@doc """
Convenience function for accessing an opponent's rating deviation.
"""
@spec opponent_rating_deviation(result :: Result.t()) :: Player.rating_deviation()
def opponent_rating_deviation(_result = {_, rating_deviation, _}), do: rating_deviation
@doc """
Convenience function for accessing the score.
"""
@spec score(result :: Result.t()) :: score
def score(_result = {_, _, score}), do: score
end end

View File

@ -8,12 +8,12 @@ defmodule GlickoTest do
doctest Glicko doctest Glicko
@player [rating: 1500, rating_deviation: 200] |> Player.new_v1() |> Player.to_v2() @player %Player.V1{rating: 1500, rating_deviation: 200} |> Player.to_v2()
@results [ @results [
Result.new(Player.new_v1(rating: 1400, rating_deviation: 30), :win), Result.new(%Player.V1{rating: 1400, rating_deviation: 30}, :win),
Result.new(Player.new_v1(rating: 1550, rating_deviation: 100), :loss), Result.new(%Player.V1{rating: 1550, rating_deviation: 100}, :loss),
Result.new(Player.new_v1(rating: 1700, rating_deviation: 300), :loss) Result.new(%Player.V1{rating: 1700, rating_deviation: 300}, :loss)
] ]
@valid_player_rating_after_results 1464.06 |> Player.scale_rating_to(:v2) @valid_player_rating_after_results 1464.06 |> Player.scale_rating_to(:v2)
@ -47,31 +47,31 @@ defmodule GlickoTest do
describe "win probability" do describe "win probability" do
test "with same ratings" do test "with same ratings" do
assert Glicko.win_probability(Player.new_v1(), Player.new_v1()) == 0.5 assert Glicko.win_probability(%Player.V1{}, %Player.V1{}) == 0.5
end end
test "with better opponent" do test "with better opponent" do
assert Glicko.win_probability(Player.new_v1(rating: 1500), Player.new_v1(rating: 1600)) < assert Glicko.win_probability(%Player.V1{rating: 1500}, %Player.V1{rating: 1600}) <
0.5 0.5
end end
test "with better player" do test "with better player" do
assert Glicko.win_probability(Player.new_v1(rating: 1600), Player.new_v1(rating: 1500)) > assert Glicko.win_probability(%Player.V1{rating: 1600}, %Player.V1{rating: 1500}) >
0.5 0.5
end end
end end
describe "draw probability" do describe "draw probability" do
test "with same ratings" do test "with same ratings" do
assert Glicko.draw_probability(Player.new_v1(), Player.new_v1()) == 1 assert Glicko.draw_probability(%Player.V1{}, %Player.V1{}) == 1
end end
test "with better opponent" do test "with better opponent" do
assert Glicko.draw_probability(Player.new_v1(rating: 1500), Player.new_v1(rating: 1600)) < 1 assert Glicko.draw_probability(%Player.V1{rating: 1500}, %Player.V1{rating: 1600}) < 1
end end
test "with better player" do test "with better player" do
assert Glicko.draw_probability(Player.new_v1(rating: 1600), Player.new_v1(rating: 1500)) < 1 assert Glicko.draw_probability(%Player.V1{rating: 1600}, %Player.V1{rating: 1500}) < 1
end end
end end
end end

View File

@ -5,25 +5,30 @@ defmodule Glicko.PlayerTest do
doctest Player doctest Player
@valid_v1_base {1.0, 2.0} @valid_v1_base %Player.V1{rating: 1.0, rating_deviation: 2.0}
@valid_v2_base {1.0, 2.0, 3.0} @valid_v2_base %Player.V2{rating: 1.0, rating_deviation: 2.0, volatility: 3.0}
test "create v1" do test "create v1" do
assert @valid_v1_base == Player.new_v1(rating: 1.0, rating_deviation: 2.0) assert @valid_v1_base == %Player.V1{rating: 1.0, rating_deviation: 2.0}
end end
test "create v2" do test "create v2" do
assert @valid_v2_base == Player.new_v2(rating: 1.0, rating_deviation: 2.0, volatility: 3.0) assert @valid_v2_base == %Player.V2{rating: 1.0, rating_deviation: 2.0, volatility: 3.0}
end end
test "convert player v1 -> v2" do test "convert player v1 -> v2" do
assert {Player.scale_rating_to(1.0, :v2), Player.scale_rating_deviation_to(2.0, :v2), 3.0} == assert %Player.V2{
Player.to_v2(@valid_v1_base, 3.0) rating: Player.scale_rating_to(1.0, :v2),
rating_deviation: Player.scale_rating_deviation_to(2.0, :v2),
volatility: 3.0
} == Player.to_v2(@valid_v1_base, 3.0)
end end
test "convert player v2 -> v1" do test "convert player v2 -> v1" do
assert {Player.scale_rating_to(1.0, :v1), Player.scale_rating_deviation_to(2.0, :v1)} == assert %Player.V1{
Player.to_v1(@valid_v2_base) rating: Player.scale_rating_to(1.0, :v1),
rating_deviation: Player.scale_rating_deviation_to(2.0, :v1)
} == Player.to_v1(@valid_v2_base)
end end
test "convert player v1 -> v1" do test "convert player v1 -> v1" do
@ -52,8 +57,7 @@ defmodule Glicko.PlayerTest do
test "rating interval" do test "rating interval" do
assert {rating_low, rating_high} = assert {rating_low, rating_high} =
[rating: 1850, rating_deviation: 50] %Player.V2{rating: 1850, rating_deviation: 50}
|> Player.new_v2()
|> Player.rating_interval() |> Player.rating_interval()
assert_in_delta rating_low, 1750, 0.1 assert_in_delta rating_low, 1750, 0.1

View File

@ -8,7 +8,7 @@ defmodule Glicko.ResultTest do
doctest Result doctest Result
@opponent Player.new_v2() @opponent %Player.V2{}
@valid_game_result Result.new(@opponent, 0.0) @valid_game_result Result.new(@opponent, 0.0)