From 50b24a0db677257b4726830c4d866223acaa95c6 Mon Sep 17 00:00:00 2001 From: Tissevert Date: Tue, 5 Nov 2019 18:14:24 +0100 Subject: [PATCH] Add a Player type back and slowly start separating SessionIDs (temporary) and PlayerID (permanent) --- hanafuda-webapp.cabal | 3 ++- src/App.hs | 15 +++++------ src/Messaging.hs | 6 ++--- src/Player.hs | 11 ++++++++ src/Server.hs | 62 +++++++++++++++++-------------------------- src/Session.hs | 17 +++++------- 6 files changed, 54 insertions(+), 60 deletions(-) create mode 100644 src/Player.hs diff --git a/hanafuda-webapp.cabal b/hanafuda-webapp.cabal index 679e911..bf8ceeb 100644 --- a/hanafuda-webapp.cabal +++ b/hanafuda-webapp.cabal @@ -24,9 +24,10 @@ executable hanafudapi other-modules: App , Automaton , Config + , Game , Keys , Messaging - , Game + , Player , RW , Server , Session diff --git a/src/App.hs b/src/App.hs index f0d80cb..c8d6a56 100644 --- a/src/App.hs +++ b/src/App.hs @@ -15,14 +15,13 @@ module App ( import Control.Concurrent (MVar, modifyMVar, putMVar, readMVar, takeMVar) import Control.Monad.Reader (ReaderT(..), ask, asks, lift) import Data.Map ((!)) -import Hanafuda.KoiKoi (PlayerID) import Network.WebSockets (Connection) import qualified Server (T(..)) -import qualified Session (T(..)) +import qualified Session (ID, T(..)) data Context = Context { mServer :: MVar Server.T - , playerID :: PlayerID + , sessionID :: Session.ID } type T a = ReaderT Context IO a @@ -30,20 +29,20 @@ type T a = ReaderT Context IO a server :: T Server.T server = asks mServer >>= lift . readMVar -get :: PlayerID -> T Session.T -get playerID = - (! playerID) . Server.sessions <$> server +get :: Session.ID -> T Session.T +get sessionID = + (! sessionID) . Server.sessions <$> server current :: T Session.T current = do - asks playerID >>= get + asks sessionID >>= get connection :: T Connection connection = Session.connection <$> current debug :: String -> T () debug message = - show <$> asks playerID + show <$> asks sessionID >>= lift . putStrLn . (++ ' ':message) try :: (Server.T -> Either String Server.T) -> T (Maybe String) diff --git a/src/Messaging.hs b/src/Messaging.hs index 0b7e8d2..0a9ec5a 100644 --- a/src/Messaging.hs +++ b/src/Messaging.hs @@ -39,8 +39,8 @@ sendTo playerIDs obj = do send :: Message.T -> App.T () send obj = do - playerID <- asks App.playerID - sendTo [playerID] obj + sessionID <- asks App.sessionID + sendTo [sessionID] obj broadcast :: Message.T -> App.T () broadcast obj = @@ -49,7 +49,7 @@ broadcast obj = relay :: FromClient -> (Message.T -> App.T ()) -> App.T () relay message f = do App.debug "Relaying" - (\from -> f $ Relay {from, message}) =<< asks App.playerID + (\from -> f $ Relay {from, message}) =<< asks App.sessionID receive :: App.T FromClient receive = do diff --git a/src/Player.hs b/src/Player.hs new file mode 100644 index 0000000..98b2ef1 --- /dev/null +++ b/src/Player.hs @@ -0,0 +1,11 @@ +module Player ( + T(..) + ) where + +import Data.Text (Text) +import Hanafuda.KoiKoi (PlayerID) + +data T = T { + playerID :: PlayerID + , name :: Text + } deriving (Show) diff --git a/src/Server.hs b/src/Server.hs index 1caab15..a106805 100644 --- a/src/Server.hs +++ b/src/Server.hs @@ -16,31 +16,23 @@ module Server ( import Data.Map (Map, (!), (!?), adjust, delete, insert, lookupMax) 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.ID (ID) import Hanafuda.KoiKoi (PlayerID) -import Hanafuda.Message (Room) import Keys (getKeys) import qualified Keys (T) +import qualified Player (T(..)) import qualified RW (RW(..)) -import qualified Session (ID, Status(..), T(..), Update) +import qualified Session (ID, T(..), Update) -type Names = Set Text +type Players = Map PlayerID Session.ID type Sessions = Map Session.ID Session.T data T = T { - names :: Names - , players :: Room + keys :: Keys.T + , players :: Players , sessions :: Sessions - , keys :: Keys.T } -instance RW.RW Names T where - get = names - set names server = server {names} - -instance RW.RW Room T where +instance RW.RW Players T where get = players set players server = server {players} @@ -50,43 +42,37 @@ instance RW.RW Sessions T where new :: IO T new = getKeys >>= \keys -> return $ T { - names = Set.empty + keys , players = Map.empty , sessions = Map.empty - , keys } register :: forall a b. (Enum a, Ord a, RW.RW (Map a b) T) => b -> T -> (T, a) register x server = - let playerID = maybe (toEnum 0) (\(n, _) -> succ n) $ lookupMax $ (RW.get server :: Map a b) in - (RW.update (insert playerID x) server, playerID) + let newID = maybe (toEnum 0) (\(n, _) -> succ n) $ lookupMax $ (RW.get server :: Map a b) in + (RW.update (insert newID x) server, newID) get :: forall a b. (Ord a, RW.RW (Map a b) T) => a -> T -> b -get playerID server = (RW.get server :: Map a b) ! playerID +get keyID server = (RW.get server :: Map a b) ! keyID update :: forall a b. (Ord a, RW.RW (Map a b) T) => a -> (b -> b) -> T -> T -update playerID updator = - RW.update (adjust updator playerID :: Map a b -> Map a b) +update keyID updator = + RW.update (adjust updator keyID :: Map a b -> Map a b) disconnect :: Session.ID -> T -> T disconnect sessionID = RW.update (delete sessionID :: Sessions -> Sessions) . logOut sessionID -logIn :: Text -> PlayerID -> T -> Either String T -logIn name playerID server = - RW.update (Set.insert name) . - RW.update (insert playerID name) . - update playerID (RW.set $ Session.Status True :: Session.Update) <$> - if name `member` names server - then Left "This name is already registered" - else Right server +logIn :: Text -> PlayerID -> Session.ID -> T -> T +logIn name playerID sessionID = + RW.update (insert playerID sessionID) . + update sessionID (RW.set $ Just player :: Session.Update) + where + player = Player.T {Player.playerID, Player.name} -logOut :: PlayerID -> T -> T -logOut playerID server = - maybe - server - (\playerName -> - RW.update (delete playerID :: Room -> Room) $ - update playerID (RW.set $ Session.Status False :: Session.Update) $ - RW.update (Set.delete playerName :: Names -> Names) server) - (players server !? playerID) +logOut :: Session.ID -> T -> T +logOut sessionID server = + case (sessions server !? sessionID) >>= Session.player of + Nothing -> server + Just player -> + RW.update (delete (Player.playerID player) :: Players -> Players) server diff --git a/src/Session.hs b/src/Session.hs index 763d370..4320de3 100644 --- a/src/Session.hs +++ b/src/Session.hs @@ -1,8 +1,8 @@ {-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE MultiParamTypeClasses #-} +{-# LANGUAGE FlexibleInstances #-} module Session ( ID - , Status(..) , T(..) , Update , open @@ -10,25 +10,22 @@ module Session ( import qualified Hanafuda.ID as Hanafuda (ID) import Network.WebSockets (Connection) +import qualified Player (T) import qualified RW (RW(..)) -newtype Status = Status { - loggedIn :: Bool - } deriving (Show) - data T = T { connection :: Connection - , status :: Status + , player :: Maybe Player.T } type ID = Hanafuda.ID T type Update = T -> T -instance RW.RW Status T where - get = status - set status session = session {status} +instance RW.RW (Maybe Player.T) T where + get = player + set player session = session {player} open :: Connection -> T open connection = T { connection - , status = Status False + , player = Nothing }