module Ranking.Glicko.Inference ( predict
, predictBoX
, BoX
, boX
, fromBoX) where
import Ranking.Glicko.Core
import Ranking.Glicko.Types
import Data.Coerce (coerce)
import Statistics.Distribution
import Statistics.Distribution.Normal
predict :: Player 1
-> Player 1
-> Double
predict :: Player 1 -> Player 1 -> Double
predict Player 1
pla Player 1
plb = NormalDistribution -> Double -> Double
forall d. Distribution d => d -> Double -> Double
cumulative NormalDistribution
dist (Double
ra Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
rb)
where Player { playerRating :: forall (version :: Nat). Player version -> Double
playerRating = Double
ra, playerDev :: forall (version :: Nat). Player version -> Double
playerDev = Double
da } = Player 1 -> Player 2
oldToNew Player 1
pla
Player { playerRating :: forall (version :: Nat). Player version -> Double
playerRating = Double
rb, playerDev :: forall (version :: Nat). Player version -> Double
playerDev = Double
db } = Player 1 -> Player 2
oldToNew Player 1
plb
dist :: NormalDistribution
dist = Double -> Double -> NormalDistribution
normalDistr Double
0 (Double
1 Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
da Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
db)
newtype BoX = BoX Integer
deriving Int -> BoX -> ShowS
[BoX] -> ShowS
BoX -> String
(Int -> BoX -> ShowS)
-> (BoX -> String) -> ([BoX] -> ShowS) -> Show BoX
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [BoX] -> ShowS
$cshowList :: [BoX] -> ShowS
show :: BoX -> String
$cshow :: BoX -> String
showsPrec :: Int -> BoX -> ShowS
$cshowsPrec :: Int -> BoX -> ShowS
Show
boX :: Integer -> Maybe BoX
boX :: Integer -> Maybe BoX
boX Integer
n = if Integer -> Bool
forall a. Integral a => a -> Bool
odd Integer
n Bool -> Bool -> Bool
&& Integer
0 Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
< Integer
n Bool -> Bool -> Bool
&& Integer
n Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
<= Integer
11
then BoX -> Maybe BoX
forall a. a -> Maybe a
Just (BoX -> Maybe BoX) -> BoX -> Maybe BoX
forall a b. (a -> b) -> a -> b
$ Integer -> BoX
BoX Integer
n
else Maybe BoX
forall a. Maybe a
Nothing
fromBoX :: BoX -> Integer
fromBoX :: BoX -> Integer
fromBoX = BoX -> Integer
coerce
{-# INLINE fromBoX #-}
predictBoX :: BoX -> Player 1 -> Player 1 -> Double
predictBoX :: BoX -> Player 1 -> Player 1 -> Double
predictBoX BoX
n Player 1
p1 Player 1
p2 =
[Double] -> Double
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum ([Double] -> Double) -> [Double] -> Double
forall a b. (a -> b) -> a -> b
$ (Integer -> Double) -> [Integer] -> [Double]
forall a b. (a -> b) -> [a] -> [b]
map (\Integer
i -> Integer -> Double
forall a. Num a => Integer -> a
fromInteger ((Integer
z Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ Integer
i) Integer -> Integer -> Integer
`choose` Integer
i) Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
pDouble -> Integer -> Double
forall a b. (Num a, Integral b) => a -> b -> a
^Integer
w Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
qDouble -> Integer -> Double
forall a b. (Num a, Integral b) => a -> b -> a
^Integer
i) [Integer
0..Integer
z]
where p :: Double
p = Player 1 -> Player 1 -> Double
predict Player 1
p1 Player 1
p2
q :: Double
q = Double
1 Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
p
w :: Integer
w = (Integer
n' Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ Integer
1) Integer -> Integer -> Integer
forall a. Integral a => a -> a -> a
`div` Integer
2
z :: Integer
z = Integer
w Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- Integer
1
n' :: Integer
n' = BoX -> Integer
fromBoX BoX
n
choose :: Integer -> Integer -> Integer
Integer
n choose :: Integer -> Integer -> Integer
`choose` Integer
k
| Integer
k Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
> Integer
n = Integer
0
| Integer
k' Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== Integer
0 = Integer
1
| Bool
otherwise = Integer
p1 Integer -> Integer -> Integer
forall a. Integral a => a -> a -> a
`div` Integer
p2
where k' :: Integer
k' = Integer -> Integer -> Integer
forall a. Ord a => a -> a -> a
min Integer
k (Integer
n Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- Integer
k)
p1 :: Integer
p1 = [Integer] -> Integer
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
product ([Integer] -> Integer)
-> ([Integer] -> [Integer]) -> [Integer] -> Integer
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Integer -> Integer) -> [Integer] -> [Integer]
forall a b. (a -> b) -> [a] -> [b]
map (\Integer
i -> Integer
n Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- Integer
i) ([Integer] -> Integer) -> [Integer] -> Integer
forall a b. (a -> b) -> a -> b
$ [Integer
0..Integer
k' Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- Integer
1]
p2 :: Integer
p2 = [Integer] -> Integer
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
product [Integer
1..Integer
k']