server/src/Server.hs

113 lines
3.2 KiB
Haskell
Raw Normal View History

2018-04-11 13:25:24 +02:00
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FlexibleContexts #-}
2018-04-11 13:25:24 +02:00
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE ScopedTypeVariables #-}
2018-04-11 13:25:24 +02:00
module Server (
T(..)
2018-04-11 13:25:24 +02:00
, disconnect
2019-08-12 23:01:08 +02:00
, endGame
, get
2018-04-11 13:25:24 +02:00
, logIn
, logOut
, new
, register
, room
, update
2018-04-11 13:25:24 +02:00
) where
import Data.Map (Map, (!), (!?), adjust, delete, insert, lookupMax, mapWithKey)
import qualified Data.Map as Map (empty)
import Data.Set (Set, member)
import qualified Data.Set as Set (delete, empty, insert)
import Data.Text (Text)
import Hanafuda.KoiKoi (Game, GameID, PlayerID)
import Hanafuda.Message (PlayerStatus(..), Room)
2018-04-11 13:25:24 +02:00
import qualified Data (RW(..))
import qualified Session (Status(..), T(..), Update)
2018-04-11 13:25:24 +02:00
type Names = Set Text
type Players = Map PlayerID Text
type Sessions = Map PlayerID Session.T
type Games = Map GameID Game
2018-04-11 13:25:24 +02:00
data T = T {
names :: Names
, players :: Players
, sessions :: Sessions
, games :: Games
2018-04-11 13:25:24 +02:00
}
instance Data.RW Names T where
get = names
set names server = server {names}
instance Data.RW Players T where
get = players
set players server = server {players}
2018-04-11 13:25:24 +02:00
instance Data.RW Sessions T where
get = sessions
set sessions server = server {sessions}
instance Data.RW Games T where
get = games
set games server = server {games}
export :: Sessions -> PlayerID -> Text -> PlayerStatus
export sessions playerID playerName = PlayerStatus (playerName, alone)
where
alone =
case Session.status (sessions ! playerID) of
Session.LoggedIn True -> True
_ -> False
2018-04-11 13:25:24 +02:00
room :: T -> Room
room (T {players, sessions}) = mapWithKey (export sessions) players
2018-04-11 13:25:24 +02:00
new :: T
new = T {
names = Set.empty
, players = Map.empty
, sessions = Map.empty
, games = Map.empty
2018-04-11 13:25:24 +02:00
}
register :: forall a b. (Enum a, Ord a, Data.RW (Map a b) T) => b -> T -> (T, a)
register x server =
let playerID = maybe (toEnum 0) (\(n, _) -> succ n) $ lookupMax $ (Data.get server :: Map a b) in
(Data.update (insert playerID x) server, playerID)
get :: forall a b. (Ord a, Data.RW (Map a b) T) => a -> T -> b
get playerID server = (Data.get server :: Map a b) ! playerID
2018-04-11 13:25:24 +02:00
update :: forall a b. (Ord a, Data.RW (Map a b) T) => a -> (b -> b) -> T -> T
update playerID updator =
Data.update (adjust updator playerID :: Map a b -> Map a b)
disconnect :: PlayerID -> T -> T
disconnect playerID =
Data.update (delete playerID :: Sessions -> Sessions) . logOut playerID
2018-04-11 13:25:24 +02:00
endGame :: GameID -> T -> T
endGame playerID =
Data.update (delete playerID :: Games -> Games)
2019-08-12 23:01:08 +02:00
logIn :: Text -> PlayerID -> T -> Either String T
logIn name playerID server =
Data.update (Set.insert name) .
Data.update (insert playerID name) .
update playerID (Data.set $ Session.LoggedIn True :: Session.Update) <$>
if name `member` names server
then Left "This name is already registered"
else Right server
logOut :: PlayerID -> T -> T
logOut playerID server =
maybe
server
(\playerName ->
Data.update (delete playerID :: Players -> Players) $
update playerID (Data.set $ Session.LoggedIn False :: Session.Update) $
Data.update (Set.delete playerName :: Names -> Names) server)
(players server !? playerID)