2018-04-11 13:25:24 +02:00
|
|
|
{-# LANGUAGE NamedFieldPuns #-}
|
|
|
|
{-# LANGUAGE FlexibleInstances #-}
|
|
|
|
{-# LANGUAGE TypeSynonymInstances #-}
|
|
|
|
{-# LANGUAGE MultiParamTypeClasses #-}
|
2018-04-12 23:01:40 +02:00
|
|
|
{-# LANGUAGE DeriveGeneric #-}
|
2018-04-11 13:25:24 +02:00
|
|
|
module Server (
|
2018-04-12 23:01:40 +02:00
|
|
|
T(..)
|
2018-04-11 13:25:24 +02:00
|
|
|
, disconnect
|
|
|
|
, join
|
|
|
|
, logIn
|
|
|
|
, logOut
|
|
|
|
, new
|
2018-04-12 23:01:40 +02:00
|
|
|
, setStatus
|
2018-04-11 13:25:24 +02:00
|
|
|
) where
|
|
|
|
|
2018-04-12 23:01:40 +02:00
|
|
|
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(..))
|
2018-04-12 23:01:40 +02:00
|
|
|
import qualified Player (Key(..), Name, Session(..), Status(..))
|
2018-04-11 13:25:24 +02:00
|
|
|
|
2018-04-12 23:01:40 +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 {
|
2018-04-12 23:01:40 +02:00
|
|
|
keys :: Keys
|
|
|
|
, names :: Names
|
|
|
|
, sessions :: Sessions
|
2018-04-11 13:25:24 +02:00
|
|
|
}
|
|
|
|
|
2018-04-12 23:01:40 +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
|
|
|
|
2018-04-12 23:01:40 +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
|
|
|
|
2018-04-12 23:01:40 +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
|
2018-04-12 23:01:40 +02:00
|
|
|
toJSON = toJSON . names
|
|
|
|
toEncoding = toEncoding . names
|
2018-04-11 13:25:24 +02:00
|
|
|
|
|
|
|
new :: T
|
|
|
|
new = T {
|
2018-04-12 23:01:40 +02:00
|
|
|
keys = Map.empty
|
|
|
|
, names = Map.empty
|
|
|
|
, sessions = Map.empty
|
2018-04-11 13:25:24 +02:00
|
|
|
}
|
|
|
|
|
2018-04-12 23:01:40 +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
|
2018-04-12 23:01:40 +02:00
|
|
|
key = Player.Key $ maybe 0 (\(Player.Key n, _) -> n+1) $ lookupMax sessions
|
2018-04-11 13:25:24 +02:00
|
|
|
|
2018-04-12 23:01:40 +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
|
|
|
|
2018-04-12 23:01:40 +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
|
|
|
|
2018-04-12 23:01:40 +02:00
|
|
|
setStatus :: Player.Status -> Player.Key -> T -> T
|
|
|
|
setStatus status key =
|
|
|
|
Data.update (adjust (Data.set status) key :: Sessions -> Sessions)
|