gameServer/Votes.hs
author alfadur
Fri, 22 Aug 2014 00:57:07 +0400
changeset 10392 5012e1f9e893
parent 10218 1d7112ccb3e9
child 10464 d08611b52000
permissions -rw-r--r--
- Support for pausing multiplayer games - Some code cleanup
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
10058
4ed428389c4e - Implement /callvote
unc0rr
parents: 10049
diff changeset
     1
{-# LANGUAGE OverloadedStrings #-}
10049
ca11d122f54e Oops, forgot this
unc0rr
parents:
diff changeset
     2
module Votes where
ca11d122f54e Oops, forgot this
unc0rr
parents:
diff changeset
     3
ca11d122f54e Oops, forgot this
unc0rr
parents:
diff changeset
     4
import Control.Monad.Reader
10216
6928a323097f Fix build
unc0rr
parents: 10215
diff changeset
     5
import Control.Monad.State.Strict
10049
ca11d122f54e Oops, forgot this
unc0rr
parents:
diff changeset
     6
import ServerState
10058
4ed428389c4e - Implement /callvote
unc0rr
parents: 10049
diff changeset
     7
import qualified Data.ByteString.Char8 as B
10081
0af84e5cbd4d Implement 'voted' function
unc0rr
parents: 10058
diff changeset
     8
import qualified Data.List as L
10195
d1c23bb73346 - Room save/load into/from file
unc0rr
parents: 10090
diff changeset
     9
import qualified Data.Map as Map
10058
4ed428389c4e - Implement /callvote
unc0rr
parents: 10049
diff changeset
    10
import Data.Maybe
4ed428389c4e - Implement /callvote
unc0rr
parents: 10049
diff changeset
    11
-------------------
4ed428389c4e - Implement /callvote
unc0rr
parents: 10049
diff changeset
    12
import Utils
4ed428389c4e - Implement /callvote
unc0rr
parents: 10049
diff changeset
    13
import CoreTypes
4ed428389c4e - Implement /callvote
unc0rr
parents: 10049
diff changeset
    14
import HandlerUtils
10392
5012e1f9e893 - Support for pausing multiplayer games
alfadur
parents: 10218
diff changeset
    15
import EngineInteraction
10049
ca11d122f54e Oops, forgot this
unc0rr
parents:
diff changeset
    16
10081
0af84e5cbd4d Implement 'voted' function
unc0rr
parents: 10058
diff changeset
    17
0af84e5cbd4d Implement 'voted' function
unc0rr
parents: 10058
diff changeset
    18
voted :: Bool -> Reader (ClientIndex, IRnC) [Action]
0af84e5cbd4d Implement 'voted' function
unc0rr
parents: 10058
diff changeset
    19
voted vote = do
0af84e5cbd4d Implement 'voted' function
unc0rr
parents: 10058
diff changeset
    20
    cl <- thisClient
0af84e5cbd4d Implement 'voted' function
unc0rr
parents: 10058
diff changeset
    21
    rm <- thisRoom
0af84e5cbd4d Implement 'voted' function
unc0rr
parents: 10058
diff changeset
    22
    uid <- liftM clUID thisClient
0af84e5cbd4d Implement 'voted' function
unc0rr
parents: 10058
diff changeset
    23
10392
5012e1f9e893 - Support for pausing multiplayer games
alfadur
parents: 10218
diff changeset
    24
    case voting rm of
5012e1f9e893 - Support for pausing multiplayer games
alfadur
parents: 10218
diff changeset
    25
        Nothing -> 
5012e1f9e893 - Support for pausing multiplayer games
alfadur
parents: 10218
diff changeset
    26
            return [AnswerClients [sendChan cl] ["CHAT", "[server]", loc "There's no voting going on"]]
5012e1f9e893 - Support for pausing multiplayer games
alfadur
parents: 10218
diff changeset
    27
        Just voting ->
5012e1f9e893 - Support for pausing multiplayer games
alfadur
parents: 10218
diff changeset
    28
            if uid `L.notElem` entitledToVote voting then
5012e1f9e893 - Support for pausing multiplayer games
alfadur
parents: 10218
diff changeset
    29
                return []
5012e1f9e893 - Support for pausing multiplayer games
alfadur
parents: 10218
diff changeset
    30
            else if uid `L.elem` map fst (votes voting) then
5012e1f9e893 - Support for pausing multiplayer games
alfadur
parents: 10218
diff changeset
    31
                return [AnswerClients [sendChan cl] ["CHAT", "[server]", loc "You already have voted"]]
5012e1f9e893 - Support for pausing multiplayer games
alfadur
parents: 10218
diff changeset
    32
            else
5012e1f9e893 - Support for pausing multiplayer games
alfadur
parents: 10218
diff changeset
    33
                actOnVoting $ voting{votes = (uid, vote):votes voting}
5012e1f9e893 - Support for pausing multiplayer games
alfadur
parents: 10218
diff changeset
    34
      
10087
5ba891578621 Implement kick voting
unc0rr
parents: 10081
diff changeset
    35
    where
5ba891578621 Implement kick voting
unc0rr
parents: 10081
diff changeset
    36
    actOnVoting :: Voting -> Reader (ClientIndex, IRnC) [Action]
5ba891578621 Implement kick voting
unc0rr
parents: 10081
diff changeset
    37
    actOnVoting vt = do
10212
5fb3bb2de9d2 Some fixes to voting + small refactoring
unc0rr
parents: 10195
diff changeset
    38
        let (pro, contra) = L.partition snd $ votes vt
10392
5012e1f9e893 - Support for pausing multiplayer games
alfadur
parents: 10218
diff changeset
    39
        let totalV = length $ entitledToVote vt 
5012e1f9e893 - Support for pausing multiplayer games
alfadur
parents: 10218
diff changeset
    40
        let successV = totalV `div` 2 + 1
10087
5ba891578621 Implement kick voting
unc0rr
parents: 10081
diff changeset
    41
10392
5012e1f9e893 - Support for pausing multiplayer games
alfadur
parents: 10218
diff changeset
    42
        if length contra > totalV - successV then
10087
5ba891578621 Implement kick voting
unc0rr
parents: 10081
diff changeset
    43
            closeVoting
10392
5012e1f9e893 - Support for pausing multiplayer games
alfadur
parents: 10218
diff changeset
    44
        else if length pro >= successV then do
10215
26fc5502ba22 - Fix applying vote result
unc0rr
parents: 10212
diff changeset
    45
            a <- act $ voteType vt
26fc5502ba22 - Fix applying vote result
unc0rr
parents: 10212
diff changeset
    46
            c <- closeVoting
26fc5502ba22 - Fix applying vote result
unc0rr
parents: 10212
diff changeset
    47
            return $ c ++ a
10087
5ba891578621 Implement kick voting
unc0rr
parents: 10081
diff changeset
    48
        else
5ba891578621 Implement kick voting
unc0rr
parents: 10081
diff changeset
    49
            return [ModifyRoom $ \r -> r{voting = Just vt}]
5ba891578621 Implement kick voting
unc0rr
parents: 10081
diff changeset
    50
5ba891578621 Implement kick voting
unc0rr
parents: 10081
diff changeset
    51
    closeVoting = do
5ba891578621 Implement kick voting
unc0rr
parents: 10081
diff changeset
    52
        chans <- roomClientsChans
5ba891578621 Implement kick voting
unc0rr
parents: 10081
diff changeset
    53
        return [
5ba891578621 Implement kick voting
unc0rr
parents: 10081
diff changeset
    54
            AnswerClients chans ["CHAT", "[server]", loc "Voting closed"]
5ba891578621 Implement kick voting
unc0rr
parents: 10081
diff changeset
    55
            , ModifyRoom (\r -> r{voting = Nothing})
5ba891578621 Implement kick voting
unc0rr
parents: 10081
diff changeset
    56
            ]
5ba891578621 Implement kick voting
unc0rr
parents: 10081
diff changeset
    57
5ba891578621 Implement kick voting
unc0rr
parents: 10081
diff changeset
    58
    act (VoteKick nickname) = do
5ba891578621 Implement kick voting
unc0rr
parents: 10081
diff changeset
    59
        (thisClientId, rnc) <- ask
5ba891578621 Implement kick voting
unc0rr
parents: 10081
diff changeset
    60
        maybeClientId <- clientByNick nickname
5ba891578621 Implement kick voting
unc0rr
parents: 10081
diff changeset
    61
        rm <- thisRoom
5ba891578621 Implement kick voting
unc0rr
parents: 10081
diff changeset
    62
        let kickId = fromJust maybeClientId
5ba891578621 Implement kick voting
unc0rr
parents: 10081
diff changeset
    63
        let kickCl = rnc `client` kickId
5ba891578621 Implement kick voting
unc0rr
parents: 10081
diff changeset
    64
        let sameRoom = clientRoom rnc thisClientId == clientRoom rnc kickId
5ba891578621 Implement kick voting
unc0rr
parents: 10081
diff changeset
    65
        return
5ba891578621 Implement kick voting
unc0rr
parents: 10081
diff changeset
    66
            [KickRoomClient kickId |
5ba891578621 Implement kick voting
unc0rr
parents: 10081
diff changeset
    67
                isJust maybeClientId
5ba891578621 Implement kick voting
unc0rr
parents: 10081
diff changeset
    68
                && sameRoom
5ba891578621 Implement kick voting
unc0rr
parents: 10081
diff changeset
    69
                && ((isNothing $ gameInfo rm) || teamsInGame kickCl == 0)
5ba891578621 Implement kick voting
unc0rr
parents: 10081
diff changeset
    70
            ]
10195
d1c23bb73346 - Room save/load into/from file
unc0rr
parents: 10090
diff changeset
    71
    act (VoteMap roomSave) = do
d1c23bb73346 - Room save/load into/from file
unc0rr
parents: 10090
diff changeset
    72
        rm <- thisRoom
d1c23bb73346 - Room save/load into/from file
unc0rr
parents: 10090
diff changeset
    73
        let rs = Map.lookup roomSave (roomSaves rm)
d1c23bb73346 - Room save/load into/from file
unc0rr
parents: 10090
diff changeset
    74
        case rs of
d1c23bb73346 - Room save/load into/from file
unc0rr
parents: 10090
diff changeset
    75
             Nothing -> return []
10218
1d7112ccb3e9 Send updated info on map switched by voting
unc0rr
parents: 10216
diff changeset
    76
             Just (mp, p) -> do
1d7112ccb3e9 Send updated info on map switched by voting
unc0rr
parents: 10216
diff changeset
    77
                 cl <- thisClient
1d7112ccb3e9 Send updated info on map switched by voting
unc0rr
parents: 10216
diff changeset
    78
                 chans <- roomClientsChans
1d7112ccb3e9 Send updated info on map switched by voting
unc0rr
parents: 10216
diff changeset
    79
                 let a = map (replaceChans chans) $ answerFullConfigParams cl mp p
1d7112ccb3e9 Send updated info on map switched by voting
unc0rr
parents: 10216
diff changeset
    80
                 return $ 
1d7112ccb3e9 Send updated info on map switched by voting
unc0rr
parents: 10216
diff changeset
    81
                    (ModifyRoom $ \r -> r{params = p, mapParams = mp})
1d7112ccb3e9 Send updated info on map switched by voting
unc0rr
parents: 10216
diff changeset
    82
                    : SendUpdateOnThisRoom
1d7112ccb3e9 Send updated info on map switched by voting
unc0rr
parents: 10216
diff changeset
    83
                    : a
1d7112ccb3e9 Send updated info on map switched by voting
unc0rr
parents: 10216
diff changeset
    84
        where
1d7112ccb3e9 Send updated info on map switched by voting
unc0rr
parents: 10216
diff changeset
    85
            replaceChans chans (AnswerClients _ msg) = AnswerClients chans msg
1d7112ccb3e9 Send updated info on map switched by voting
unc0rr
parents: 10216
diff changeset
    86
            replaceChans _ a = a
10392
5012e1f9e893 - Support for pausing multiplayer games
alfadur
parents: 10218
diff changeset
    87
    act (VotePause) = do
5012e1f9e893 - Support for pausing multiplayer games
alfadur
parents: 10218
diff changeset
    88
        rm <- thisRoom
5012e1f9e893 - Support for pausing multiplayer games
alfadur
parents: 10218
diff changeset
    89
        chans <- roomClientsChans
5012e1f9e893 - Support for pausing multiplayer games
alfadur
parents: 10218
diff changeset
    90
        let modifyGameInfo f room  = room{gameInfo = fmap f $ gameInfo room}
5012e1f9e893 - Support for pausing multiplayer games
alfadur
parents: 10218
diff changeset
    91
        return [ModifyRoom (modifyGameInfo $ \g -> g{isPaused = not $ isPaused g}),
5012e1f9e893 - Support for pausing multiplayer games
alfadur
parents: 10218
diff changeset
    92
                AnswerClients chans ["CHAT", "[server]", "Pause toggled"],
5012e1f9e893 - Support for pausing multiplayer games
alfadur
parents: 10218
diff changeset
    93
                AnswerClients chans ["EM", toEngineMsg "I"]]
10081
0af84e5cbd4d Implement 'voted' function
unc0rr
parents: 10058
diff changeset
    94
10049
ca11d122f54e Oops, forgot this
unc0rr
parents:
diff changeset
    95
ca11d122f54e Oops, forgot this
unc0rr
parents:
diff changeset
    96
startVote :: VoteType -> Reader (ClientIndex, IRnC) [Action]
10058
4ed428389c4e - Implement /callvote
unc0rr
parents: 10049
diff changeset
    97
startVote vt = do
4ed428389c4e - Implement /callvote
unc0rr
parents: 10049
diff changeset
    98
    (ci, rnc) <- ask
10090
a471a7bbc339 - Start work on flood detector
unc0rr
parents: 10087
diff changeset
    99
    --cl <- thisClient
10058
4ed428389c4e - Implement /callvote
unc0rr
parents: 10049
diff changeset
   100
    rm <- thisRoom
4ed428389c4e - Implement /callvote
unc0rr
parents: 10049
diff changeset
   101
    chans <- roomClientsChans
4ed428389c4e - Implement /callvote
unc0rr
parents: 10049
diff changeset
   102
4ed428389c4e - Implement /callvote
unc0rr
parents: 10049
diff changeset
   103
    let uids = map (clUID . client rnc) . roomClients rnc $ clientRoom rnc ci
4ed428389c4e - Implement /callvote
unc0rr
parents: 10049
diff changeset
   104
4ed428389c4e - Implement /callvote
unc0rr
parents: 10049
diff changeset
   105
    if isJust $ voting rm then
4ed428389c4e - Implement /callvote
unc0rr
parents: 10049
diff changeset
   106
        return []
4ed428389c4e - Implement /callvote
unc0rr
parents: 10049
diff changeset
   107
    else
10212
5fb3bb2de9d2 Some fixes to voting + small refactoring
unc0rr
parents: 10195
diff changeset
   108
        return [
5fb3bb2de9d2 Some fixes to voting + small refactoring
unc0rr
parents: 10195
diff changeset
   109
            ModifyRoom (\r -> r{voting = Just (newVoting vt){entitledToVote = uids}})
5fb3bb2de9d2 Some fixes to voting + small refactoring
unc0rr
parents: 10195
diff changeset
   110
            , AnswerClients chans ["CHAT", "[server]", B.concat [loc "New voting started", ": ", voteInfo vt]]
5fb3bb2de9d2 Some fixes to voting + small refactoring
unc0rr
parents: 10195
diff changeset
   111
            , ReactCmd ["VOTE", "YES"]
10215
26fc5502ba22 - Fix applying vote result
unc0rr
parents: 10212
diff changeset
   112
        ]
10081
0af84e5cbd4d Implement 'voted' function
unc0rr
parents: 10058
diff changeset
   113
10049
ca11d122f54e Oops, forgot this
unc0rr
parents:
diff changeset
   114
10215
26fc5502ba22 - Fix applying vote result
unc0rr
parents: 10212
diff changeset
   115
checkVotes :: StateT ServerState IO [Action]
26fc5502ba22 - Fix applying vote result
unc0rr
parents: 10212
diff changeset
   116
checkVotes = do
26fc5502ba22 - Fix applying vote result
unc0rr
parents: 10212
diff changeset
   117
    rnc <- gets roomsClients
10216
6928a323097f Fix build
unc0rr
parents: 10215
diff changeset
   118
    liftM concat $ io $ do
10215
26fc5502ba22 - Fix applying vote result
unc0rr
parents: 10212
diff changeset
   119
        ris <- allRoomsM rnc
10216
6928a323097f Fix build
unc0rr
parents: 10215
diff changeset
   120
        mapM (check rnc) ris
10215
26fc5502ba22 - Fix applying vote result
unc0rr
parents: 10212
diff changeset
   121
    where
26fc5502ba22 - Fix applying vote result
unc0rr
parents: 10212
diff changeset
   122
        check rnc ri = do
26fc5502ba22 - Fix applying vote result
unc0rr
parents: 10212
diff changeset
   123
            e <- room'sM rnc voting ri
26fc5502ba22 - Fix applying vote result
unc0rr
parents: 10212
diff changeset
   124
            case e of
26fc5502ba22 - Fix applying vote result
unc0rr
parents: 10212
diff changeset
   125
                 Just rv -> do
26fc5502ba22 - Fix applying vote result
unc0rr
parents: 10212
diff changeset
   126
                     modifyRoom rnc (\r -> r{voting = if voteTTL rv == 0 then Nothing else Just rv{voteTTL = voteTTL rv - 1}}) ri
26fc5502ba22 - Fix applying vote result
unc0rr
parents: 10212
diff changeset
   127
                     if voteTTL rv == 0 then do
10216
6928a323097f Fix build
unc0rr
parents: 10215
diff changeset
   128
                        chans <- liftM (map sendChan) $ roomClientsM rnc ri
10215
26fc5502ba22 - Fix applying vote result
unc0rr
parents: 10212
diff changeset
   129
                        return [AnswerClients chans ["CHAT", "[server]", loc "Voting expired"]]
26fc5502ba22 - Fix applying vote result
unc0rr
parents: 10212
diff changeset
   130
                        else
26fc5502ba22 - Fix applying vote result
unc0rr
parents: 10212
diff changeset
   131
                        return []
10216
6928a323097f Fix build
unc0rr
parents: 10215
diff changeset
   132
                 Nothing -> return []
10058
4ed428389c4e - Implement /callvote
unc0rr
parents: 10049
diff changeset
   133
10081
0af84e5cbd4d Implement 'voted' function
unc0rr
parents: 10058
diff changeset
   134
10058
4ed428389c4e - Implement /callvote
unc0rr
parents: 10049
diff changeset
   135
voteInfo :: VoteType -> B.ByteString
4ed428389c4e - Implement /callvote
unc0rr
parents: 10049
diff changeset
   136
voteInfo (VoteKick n) = B.concat [loc "kick", " ", n]
10195
d1c23bb73346 - Room save/load into/from file
unc0rr
parents: 10090
diff changeset
   137
voteInfo (VoteMap n) = B.concat [loc "map", " ", n]
10392
5012e1f9e893 - Support for pausing multiplayer games
alfadur
parents: 10218
diff changeset
   138
voteInfo (VotePause) = B.concat [loc "pause"]