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

-- | Virtual contest/rating command.
module Codeforces.App.Commands.VirtualCmd
    ( virtualRating
    ) where

import           Codeforces.API
import           Codeforces.App.Format
import           Codeforces.Error

import           Control.Monad.Trans.Class
import           Control.Monad.Trans.Except

import qualified Data.Text                     as T
import qualified Data.Text.IO                  as T

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

virtualRating :: ContestId -> Handle -> Points -> Int -> IO ()
virtualRating :: ContestId -> Handle -> Points -> Int -> IO ()
virtualRating ContestId
cId Handle
h Points
pts Int
pen = IO (Either CodeforcesError ()) -> IO ()
forall a. IO (Either CodeforcesError a) -> IO ()
handleE (IO (Either CodeforcesError ()) -> IO ())
-> IO (Either CodeforcesError ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ ExceptT CodeforcesError IO () -> IO (Either CodeforcesError ())
forall e (m :: * -> *) a. ExceptT e m a -> m (Either e a)
runExceptT (ExceptT CodeforcesError IO () -> IO (Either CodeforcesError ()))
-> ExceptT CodeforcesError IO () -> IO (Either CodeforcesError ())
forall a b. (a -> b) -> a -> b
$ do
    (User
u, Maybe VirtualResult
mRes) <- IO (Either ResponseError (User, Maybe VirtualResult))
-> ExceptT CodeforcesError IO (User, Maybe VirtualResult)
forall a.
IO (Either ResponseError a) -> ExceptT CodeforcesError IO a
handleAPI (IO (Either ResponseError (User, Maybe VirtualResult))
 -> ExceptT CodeforcesError IO (User, Maybe VirtualResult))
-> IO (Either ResponseError (User, Maybe VirtualResult))
-> ExceptT CodeforcesError IO (User, Maybe VirtualResult)
forall a b. (a -> b) -> a -> b
$ ContestId
-> Handle
-> Points
-> Int
-> IO (Either ResponseError (User, Maybe VirtualResult))
calculateVirtualResult ContestId
cId Handle
h Points
pts Int
pen

    case Maybe VirtualResult
mRes of
        Maybe VirtualResult
Nothing  -> CodeforcesError -> ExceptT CodeforcesError IO ()
forall (m :: * -> *) e a. Monad m => e -> ExceptT e m a
throwE CodeforcesError
VirtualNoResult
        Just VirtualResult
res -> IO () -> ExceptT CodeforcesError IO ()
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (IO () -> ExceptT CodeforcesError IO ())
-> IO () -> ExceptT CodeforcesError IO ()
forall a b. (a -> b) -> a -> b
$ User -> VirtualResult -> IO ()
printVirtualRes User
u VirtualResult
res

printVirtualRes :: User -> VirtualResult -> IO ()
printVirtualRes :: User -> VirtualResult -> IO ()
printVirtualRes User
u VirtualResult {Points
Int
virtualSeed :: VirtualResult -> Points
virtualDelta :: VirtualResult -> Int
virtualRank :: VirtualResult -> Int
virtualSeed :: Points
virtualDelta :: Int
virtualRank :: Int
..} = do
    Points -> Int -> IO ()
printRankings Points
virtualSeed Int
virtualRank

    String -> IO ()
putStrLn String
""
    String -> IO ()
putStrLn String
"Rating change:"

    let currRating :: Int
currRating = User -> Int
userRating User
u
    let currRank :: Rank
currRank   = Int -> Rank
getRank Int
currRating
    let newRating :: Int
newRating  = Int
currRating Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
virtualDelta
    let newRank :: Rank
newRank    = Int -> Rank
getRank Int
newRating

    String -> IO ()
putStrLn (String -> IO ()) -> String -> IO ()
forall a b. (a -> b) -> a -> b
$ [String] -> String
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [String
"  (", Int -> String
forall a. Show a => a -> String
show Int
currRating, String
" -> ", Int -> String
forall a. Show a => a -> String
show Int
newRating, String
")"]
    String -> IO ()
putStrLn String
""

    Text -> IO ()
T.putStrLn (Text -> IO ()) -> Text -> IO ()
forall a b. (a -> b) -> a -> b
$ [Text] -> Text
T.concat [Text
"  ", Text
indent, Int -> Text
diffColored Int
virtualDelta]
    String -> IO ()
putStrLn String
""

    let handle :: Text
handle = Handle -> Text
unHandle (User -> Handle
userHandle User
u)
        desc :: Text
desc   = if Rank
currRank Rank -> Rank -> Bool
forall a. Eq a => a -> a -> Bool
== Rank
newRank
            then [Text] -> Text
T.concat
                [ Text
"Would remain "
                , Rank -> Text
rankName Rank
currRank
                , Text
" "
                , RankColor -> Text -> Text
rankColored (Rank -> RankColor
rankColor Rank
currRank) Text
handle
                ]
            else [Text] -> Text
T.concat
                [ Text
"Would become "
                , Rank -> Text
rankName Rank
newRank
                , Text
": "
                , RankColor -> Text -> Text
rankColored (Rank -> RankColor
rankColor Rank
currRank) Text
handle
                , Text
" -> "
                , RankColor -> Text -> Text
rankColored (Rank -> RankColor
rankColor Rank
newRank) Text
handle
                ]
    Text -> IO ()
T.putStrLn (Text -> IO ()) -> Text -> IO ()
forall a b. (a -> b) -> a -> b
$ [Text] -> Text
T.concat [Text
"  ", Text
desc, Text
"\n"]

printRankings :: Seed -> Int -> IO ()
printRankings :: Points -> Int -> IO ()
printRankings Points
seed Int
rank = do
    String -> IO ()
putStrLn String
""
    String -> IO ()
putStrLn (String -> IO ()) -> String -> IO ()
forall a b. (a -> b) -> a -> b
$ String
"Expected ranking: " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show (Points -> Int
forall a b. (RealFrac a, Integral b) => a -> b
round Points
seed :: Int)
    String -> IO ()
putStrLn (String -> IO ()) -> String -> IO ()
forall a b. (a -> b) -> a -> b
$ String
"Actual ranking:   " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show Int
rank

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