1
0
mirror of https://github.com/avitex/elixir-glicko synced 2024-11-24 20:19:57 +00:00

Add function to calculate draw probability

This commit is contained in:
avitex 2017-11-29 14:00:18 +11:00
parent bb097fc5de
commit 3d5a8e4f89
2 changed files with 69 additions and 22 deletions

View File

@ -28,6 +28,13 @@ defmodule Glicko do
iex> Glicko.win_probability(player, opponent)
0.5
Calculate the probability of a player drawing against an opponent.
iex> player = Player.new_v1
iex> opponent = Player.new_v1
iex> Glicko.draw_probability(player, opponent)
1.0
"""
alias __MODULE__.{
@ -41,7 +48,7 @@ defmodule Glicko do
@type new_rating_opts :: [system_constant: float, convergence_tolerance: float]
@doc """
Calculates the probability of a player winning against an opponent from a player and an opponent.
Calculates the probability of a player winning against an opponent.
Returns a value between `0.0` and `1.0`.
"""
@ -62,6 +69,28 @@ defmodule Glicko do
calc_e(player_rating, opponent_rating, calc_g(opponent_rating_deviation))
end
@doc """
Calculates the probability of a player drawing against an opponent.
Returns a value between `0.0` and `1.0`.
"""
@spec draw_probability(player :: Player.t, opponent :: Player.t) :: float
def draw_probability(player, opponent) do
draw_probability(player |> Player.rating(:v2), opponent |> Player.rating(:v2), opponent |> Player.rating_deviation(:v2))
end
@doc """
Calculates the probability of a player drawing against an opponent from a player rating, opponent rating and opponent rating deviation.
Values provided for the player rating, opponent rating and opponent rating deviation must be *v2* based.
Returns a value between `0.0` and `1.0`.
"""
@spec draw_probability(player_rating :: Player.rating, opponent_rating :: Player.rating, opponent_rating_deviation :: Player.rating_deviation) :: float
def draw_probability(player_rating, opponent_rating, opponent_rating_deviation) do
1 - abs(win_probability(player_rating, opponent_rating, opponent_rating_deviation) - 0.5) / 0.5
end
@doc """
Generate a new rating from an existing rating and a series (or lack) of results.

View File

@ -22,7 +22,8 @@ defmodule GlickoTest do
@valid_player_rating_deviation_after_no_results 200.2714 |> Player.scale_rating_deviation_to(:v2)
test "new rating (with results)" do
describe "new rating" do
test "with results" do
player = Glicko.new_rating(@player, @results, [system_constant: 0.5])
assert_in_delta Player.rating(player), @valid_player_rating_after_results, 1.0e-4
@ -30,21 +31,38 @@ defmodule GlickoTest do
assert_in_delta Player.volatility(player), @valid_player_volatility_after_results, 1.0e-5
end
test "new rating (no results)" do
test "no results" do
player = Glicko.new_rating(@player, [])
assert_in_delta Player.rating_deviation(player), @valid_player_rating_deviation_after_no_results, 1.0e-4
end
end
test "win probability with same ratings" do
describe "win probability" do
test "with same ratings" do
assert Glicko.win_probability(Player.new_v1, Player.new_v1) == 0.5
end
test "win probability with better opponent" do
test "with better opponent" do
assert Glicko.win_probability(Player.new_v1([rating: 1500]), Player.new_v1([rating: 1600])) < 0.5
end
test "win probability with better player" do
test "with better player" do
assert Glicko.win_probability(Player.new_v1([rating: 1600]), Player.new_v1([rating: 1500])) > 0.5
end
end
describe "draw probability" do
test "with same ratings" do
assert Glicko.draw_probability(Player.new_v1, Player.new_v1) == 1
end
test "with better opponent" do
assert Glicko.draw_probability(Player.new_v1([rating: 1500]), Player.new_v1([rating: 1600])) < 1
end
test "with better player" do
assert Glicko.draw_probability(Player.new_v1([rating: 1600]), Player.new_v1([rating: 1500])) < 1
end
end
end