--------------------------------------------------------------------------------

module Codeforces.Types.Rank where

import           Codeforces.Types.Common

import           Data.Text                      ( Text )

--------------------------------------------------------------------------------

data RankColor = Gray | Green | Cyan | Blue | Violet | Orange | Red
    deriving (RankColor -> RankColor -> Bool
(RankColor -> RankColor -> Bool)
-> (RankColor -> RankColor -> Bool) -> Eq RankColor
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: RankColor -> RankColor -> Bool
$c/= :: RankColor -> RankColor -> Bool
== :: RankColor -> RankColor -> Bool
$c== :: RankColor -> RankColor -> Bool
Eq, Int -> RankColor -> ShowS
[RankColor] -> ShowS
RankColor -> String
(Int -> RankColor -> ShowS)
-> (RankColor -> String)
-> ([RankColor] -> ShowS)
-> Show RankColor
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [RankColor] -> ShowS
$cshowList :: [RankColor] -> ShowS
show :: RankColor -> String
$cshow :: RankColor -> String
showsPrec :: Int -> RankColor -> ShowS
$cshowsPrec :: Int -> RankColor -> ShowS
Show)

type RatingBounds = (Rating, Rating)

data Rank = Rank
    { Rank -> Text
rankName   :: Text
    , Rank -> RankColor
rankColor  :: RankColor
    , Rank -> RatingBounds
rankBounds :: RatingBounds
    }
    deriving (Rank -> Rank -> Bool
(Rank -> Rank -> Bool) -> (Rank -> Rank -> Bool) -> Eq Rank
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Rank -> Rank -> Bool
$c/= :: Rank -> Rank -> Bool
== :: Rank -> Rank -> Bool
$c== :: Rank -> Rank -> Bool
Eq, Int -> Rank -> ShowS
[Rank] -> ShowS
Rank -> String
(Int -> Rank -> ShowS)
-> (Rank -> String) -> ([Rank] -> ShowS) -> Show Rank
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Rank] -> ShowS
$cshowList :: [Rank] -> ShowS
show :: Rank -> String
$cshow :: Rank -> String
showsPrec :: Int -> Rank -> ShowS
$cshowsPrec :: Int -> Rank -> ShowS
Show)

-- | A list of all Codeforces ranks.
ranks :: [Rank]
ranks :: [Rank]
ranks =
    [ Text -> RankColor -> RatingBounds -> Rank
Rank Text
"Newbie"                    RankColor
Gray   (Int
0   , Int
1199)
    , Text -> RankColor -> RatingBounds -> Rank
Rank Text
"Pupil"                     RankColor
Green  (Int
1200, Int
1399)
    , Text -> RankColor -> RatingBounds -> Rank
Rank Text
"Specialist"                RankColor
Cyan   (Int
1400, Int
1599)
    , Text -> RankColor -> RatingBounds -> Rank
Rank Text
"Expert"                    RankColor
Blue   (Int
1600, Int
1899)
    , Text -> RankColor -> RatingBounds -> Rank
Rank Text
"Candidate Master"          RankColor
Violet (Int
1900, Int
2099)
    , Text -> RankColor -> RatingBounds -> Rank
Rank Text
"Master"                    RankColor
Orange (Int
2100, Int
2299)
    , Text -> RankColor -> RatingBounds -> Rank
Rank Text
"International Master"      RankColor
Orange (Int
2300, Int
2399)
    , Text -> RankColor -> RatingBounds -> Rank
Rank Text
"Grandmaster"               RankColor
Red    (Int
2400, Int
2599)
    , Text -> RankColor -> RatingBounds -> Rank
Rank Text
"International Grandmaster" RankColor
Red    (Int
2600, Int
2899)
    , Text -> RankColor -> RatingBounds -> Rank
Rank Text
"Legendary Grandmaster"     RankColor
Red    (Int
2900, Int
9999)
    ]

-- | Finds the 'Rank' that matches the supplied rating.
getRank :: Rating -> Rank
getRank :: Int -> Rank
getRank Int
x = [Rank] -> Rank
forall a. [a] -> a
head ([Rank] -> Rank) -> [Rank] -> Rank
forall a b. (a -> b) -> a -> b
$ (Rank -> Bool) -> [Rank] -> [Rank]
forall a. (a -> Bool) -> [a] -> [a]
filter Rank -> Bool
withinRankBounds [Rank]
ranks
  where
    withinRankBounds :: Rank -> Bool
withinRankBounds Rank {RatingBounds
Text
RankColor
rankBounds :: RatingBounds
rankColor :: RankColor
rankName :: Text
rankBounds :: Rank -> RatingBounds
rankColor :: Rank -> RankColor
rankName :: Rank -> Text
..} = RatingBounds -> Int
forall a b. (a, b) -> a
fst RatingBounds
rankBounds Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
x Bool -> Bool -> Bool
&& Int
x Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= RatingBounds -> Int
forall a b. (a, b) -> b
snd RatingBounds
rankBounds

--------------------------------------------------------------------------------