11380

1 
{


2 
Glicko2, as described in http://www.glicko.net/glicko/glicko2.pdf


3 
}


4 


5 
module OfficialServer.Glicko2 where


6 


7 
data RatingData = RatingData {


8 
ratingValue


9 
, rD


10 
, volatility :: Double


11 
}


12 
data GameData = GameData {


13 
opponentRating :: RatingData,


14 
gameScore :: Double


15 
}


16 


17 
τ, ε :: Double

11390

18 
τ = 0.2

11380

19 
ε = 0.000001


20 


21 
g_φ :: Double > Double


22 
g_φ φ = 1 / sqrt (1 + 3 * φ^2 / pi^2)


23 


24 
calcE :: RatingData > GameData > (Double, Double, Double)


25 
calcE oldRating (GameData oppRating s) = (


26 
1 / (1 + exp (g_φᵢ * (μᵢ  μ)))


27 
, g_φᵢ


28 
, s


29 
)


30 
where


31 
μ = (ratingValue oldRating  1500) / 173.7178


32 
φ = rD oldRating / 173.7178


33 
μᵢ = (ratingValue oppRating  1500) / 173.7178


34 
φᵢ = rD oppRating / 173.7178


35 
g_φᵢ = g_φ φᵢ


36 


37 

11390

38 
calcNewRating :: RatingData > [GameData] > (Int, RatingData)


39 
calcNewRating oldRating [] = (0, RatingData (ratingValue oldRating) (173.7178 * sqrt (φ ^ 2 + σ ^ 2)) σ)

11381

40 
where


41 
φ = rD oldRating / 173.7178


42 
σ = volatility oldRating


43 

11390

44 
calcNewRating oldRating games = (length games, RatingData (173.7178 * μ' + 1500) (173.7178 * sqrt φ'sqr) σ')

11380

45 
where


46 
_Es = map (calcE oldRating) games


47 
υ = 1 / sum (map υ_p _Es)


48 
υ_p (_Eᵢ, g_φᵢ, _) = g_φᵢ ^ 2 * _Eᵢ * (1  _Eᵢ)


49 
_Δ = υ * part1


50 
part1 = sum (map _Δ_p _Es)


51 
_Δ_p (_Eᵢ, g_φᵢ, sᵢ) = g_φᵢ * (sᵢ  _Eᵢ)


52 


53 
μ = (ratingValue oldRating  1500) / 173.7178


54 
φ = rD oldRating / 173.7178


55 
σ = volatility oldRating


56 


57 
a = log (σ ^ 2)


58 
f :: Double > Double


59 
f x = exp x * (_Δ ^ 2  φ ^ 2  υ  exp x) / 2 / (φ ^ 2 + υ + exp x) ^ 2  (x  a) / τ ^ 2


60 


61 
_A = a


62 
_B = if _Δ ^ 2 > φ ^ 2 + υ then log (_Δ ^ 2  φ ^ 2  υ) else head . dropWhile ((>) 0 . f) . map (\k > a  k * τ) $ [1 ..]


63 
fA = f _A


64 
fB = f _B


65 
σ' = (\(_A, _, _, _) > exp (_A / 2)) . head . dropWhile (\(_A, _, _B, _) > abs (_B  _A) > ε) $ iterate step5 (_A, fA, _B, fB)


66 
step5 (_A, fA, _B, fB) = let _C = _A + (_A  _B) * fA / (fB  fA); fC = f _C in


67 
if fC * fB < 0 then (_B, fB, _C, fC) else (_A, fA / 2, _C, fC)


68 


69 
φ'sqr = 1 / (1 / (φ ^ 2 + σ' ^ 2) + 1 / υ)


70 
μ' = μ + φ'sqr * part1
