Implement multi-sessions for players

This commit is contained in:
Tissevert 2019-12-17 15:01:33 +01:00
parent 09e6f6a5e9
commit 96424bfa2e
3 changed files with 24 additions and 12 deletions

View file

@ -18,7 +18,7 @@ receive :: Message.FromClient -> Session.Status -> App.T ()
receive (Message.Hello {Message.name}) Nothing = do receive (Message.Hello {Message.name}) Nothing = do
sessionID <- asks App.sessionID sessionID <- asks App.sessionID
playerID <- App.exec (Server.register sessionID) playerID <- App.exec (Server.register [sessionID])
room <- App.get Server.room room <- App.get Server.room
Messaging.send $ Message.Welcome room playerID Messaging.send $ Message.Welcome room playerID
App.update (Server.update sessionID $ Session.setPlayer playerID name) App.update (Server.update sessionID $ Session.setPlayer playerID name)

View file

@ -41,7 +41,7 @@ sendToSessions sessions obj = do
sendTo :: [KoiKoi.PlayerID] -> Message.T -> App.T () sendTo :: [KoiKoi.PlayerID] -> Message.T -> App.T ()
sendTo playerIDs obj = do sendTo playerIDs obj = do
sessions <- App.get $ Server.sessionsWhere selectedPlayer sessions <- App.get $ Server.sessionsWhere selectedPlayer
sendToSessions (elems sessions) obj sendToSessions (foldl (++) [] sessions) obj
where where
selectedPlayer playerID _ = Set.member playerID $ Set.fromList playerIDs selectedPlayer playerID _ = Set.member playerID $ Set.fromList playerIDs

View file

@ -16,8 +16,8 @@ module Server (
, update , update
) where ) where
import Data.Map (Map, (!), (!?), adjust, delete, insert) import Data.Map (Map, (!), (!?), adjust, delete, insert, mapMaybe)
import qualified Data.Map as Map (empty, lookup, mapMaybeWithKey) import qualified Data.Map as Map (empty, foldlWithKey, lookup)
import Data.Text (Text) import Data.Text (Text)
import Hanafuda.KoiKoi (PlayerID) import Hanafuda.KoiKoi (PlayerID)
import Hanafuda.Message (Room) import Hanafuda.Message (Room)
@ -28,7 +28,7 @@ import qualified RW (RW(..))
import qualified Session (ID, T(..), setPlayer) import qualified Session (ID, T(..), setPlayer)
import System.Random (Random(..)) import System.Random (Random(..))
type SessionIDs = Map PlayerID Session.ID type SessionIDs = Map PlayerID [Session.ID]
type Sessions = Map Session.ID Session.T type Sessions = Map Session.ID Session.T
data T = T { data T = T {
keys :: Keys.T keys :: Keys.T
@ -52,15 +52,27 @@ new = getKeys >>= \keys -> return $ T {
} }
room :: T -> Room room :: T -> Room
room = fmap Player.name . select (\_ -> Session.player) room = mapMaybe keepName . select (\_ -> Session.player)
where
keepName [] = Nothing
keepName (player:_) = Just $ Player.name player
select :: (PlayerID -> Session.T -> Maybe a) -> T -> Map PlayerID a push :: Ord k => k -> v -> Map k [v] -> Map k [v]
push key value m =
(maybe (insert key [value]) (insert key . (value:)) $ Map.lookup key m) m
select :: (PlayerID -> Session.T -> Maybe a) -> T -> Map PlayerID [a]
select selector (T {sessionIDsByPlayerID, sessions}) = select selector (T {sessionIDsByPlayerID, sessions}) =
Map.mapMaybeWithKey selected sessionIDsByPlayerID where Map.foldlWithKey (\accumulator playerID sessionIDs ->
selected playerID sessionID = foldl (\acc ->
Map.lookup sessionID sessions >>= selector playerID maybe acc (\v -> push playerID v acc) . selected playerID
) accumulator sessionIDs
) Map.empty sessionIDsByPlayerID
where
selected playerID sessionID =
Map.lookup sessionID sessions >>= selector playerID
sessionsWhere :: (PlayerID -> Session.T -> Bool) -> T -> Map PlayerID Session.T sessionsWhere :: (PlayerID -> Session.T -> Bool) -> T -> Map PlayerID [Session.T]
sessionsWhere predicate = select selectorOfPredicate where sessionsWhere predicate = select selectorOfPredicate where
selectorOfPredicate playerID session = selectorOfPredicate playerID session =
if predicate playerID session then Just session else Nothing if predicate playerID session then Just session else Nothing
@ -79,7 +91,7 @@ update keyID updator =
logIn :: Text -> PlayerID -> Session.ID -> T -> T logIn :: Text -> PlayerID -> Session.ID -> T -> T
logIn name playerID sessionID = logIn name playerID sessionID =
RW.update (insert playerID sessionID) . RW.update (push playerID sessionID) .
update sessionID (Session.setPlayer playerID name) update sessionID (Session.setPlayer playerID name)
logOut :: Session.ID -> T -> T logOut :: Session.ID -> T -> T