server/src/Server.hs

81 lines
2.2 KiB
Haskell
Raw Normal View History

2018-04-11 13:25:24 +02:00
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE TypeSynonymInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE DeriveGeneric #-}
2018-04-11 13:25:24 +02:00
module Server (
T(..)
2018-04-11 13:25:24 +02:00
, disconnect
, join
, logIn
, logOut
, new
, setStatus
2018-04-11 13:25:24 +02:00
) where
import Data.Map ((!?), Map, adjust, delete, insert, lookupMax)
import qualified Data.Map as Map (empty)
import Data.Aeson (ToJSON(..))
2018-04-11 13:25:24 +02:00
import qualified Data (RW(..))
import qualified Player (Key(..), Name, Session(..), Status(..))
2018-04-11 13:25:24 +02:00
type Keys = Map Player.Name Player.Key
type Names = Map Player.Key Player.Name
type Sessions = Map Player.Key Player.Session
2018-04-11 13:25:24 +02:00
data T = T {
keys :: Keys
, names :: Names
, sessions :: Sessions
2018-04-11 13:25:24 +02:00
}
instance Data.RW Keys T where
update f server@(T {keys}) = server {keys = f keys}
2018-04-11 13:25:24 +02:00
instance Data.RW Names T where
update f server@(T {names}) = server {names = f names}
2018-04-11 13:25:24 +02:00
instance Data.RW Sessions T where
update f server@(T {sessions}) = server {sessions = f sessions}
2018-04-11 13:25:24 +02:00
instance ToJSON T where
toJSON = toJSON . names
toEncoding = toEncoding . names
2018-04-11 13:25:24 +02:00
new :: T
new = T {
keys = Map.empty
, names = Map.empty
, sessions = Map.empty
2018-04-11 13:25:24 +02:00
}
join :: Player.Session -> T -> IO (T, Player.Key)
join session server@(T {sessions}) =
return (Data.update (insert key session) server, key)
2018-04-11 13:25:24 +02:00
where
key = Player.Key $ maybe 0 (\(Player.Key n, _) -> n+1) $ lookupMax sessions
2018-04-11 13:25:24 +02:00
disconnect :: Player.Key -> T -> T
disconnect key =
Data.update (delete key :: Sessions -> Sessions) . logOut key
2018-04-11 13:25:24 +02:00
logIn :: Player.Name -> Player.Key -> T -> Either String T
logIn name key server =
Data.update (insert name key) .
Data.update (insert key name) .
setStatus (Player.LoggedIn True) key <$>
maybe (Right server) (\_-> Left "This name is already registered") (keys server !? name)
logOut :: Player.Key -> T -> T
logOut key server =
maybe
server
(\name ->
Data.update (delete key :: Names -> Names) $
setStatus (Player.LoggedIn False) key $
Data.update (delete name :: Keys -> Keys) server)
(names server !? key)
2018-04-11 13:25:24 +02:00
setStatus :: Player.Status -> Player.Key -> T -> T
setStatus status key =
Data.update (adjust (Data.set status) key :: Sessions -> Sessions)