gameServer/Votes.hs
author nemo
Sun, 04 Jan 2015 00:44:14 -0500
branch0.9.21
changeset 10743 1d16c5414fee
parent 10464 d08611b52000
child 10786 712283ed86e0
permissions -rw-r--r--
Intent is to allow filtering by arbitrary flag combinations. This isn't actually working yet. No idea why. It seems it should. Tired though, so will look at it tomorrow.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
10464
d08611b52000 Added two copyrights on gameServer
Gianfranco Costamagna <costamagnagianfranco@yahoo.it>
parents: 10392
diff changeset
     1
{-
d08611b52000 Added two copyrights on gameServer
Gianfranco Costamagna <costamagnagianfranco@yahoo.it>
parents: 10392
diff changeset
     2
 * Hedgewars, a free turn based strategy game
d08611b52000 Added two copyrights on gameServer
Gianfranco Costamagna <costamagnagianfranco@yahoo.it>
parents: 10392
diff changeset
     3
 * Copyright (c) 2004-2014 Andrey Korotaev <unC0Rr@gmail.com>
d08611b52000 Added two copyrights on gameServer
Gianfranco Costamagna <costamagnagianfranco@yahoo.it>
parents: 10392
diff changeset
     4
 *
d08611b52000 Added two copyrights on gameServer
Gianfranco Costamagna <costamagnagianfranco@yahoo.it>
parents: 10392
diff changeset
     5
 * This program is free software; you can redistribute it and/or modify
d08611b52000 Added two copyrights on gameServer
Gianfranco Costamagna <costamagnagianfranco@yahoo.it>
parents: 10392
diff changeset
     6
 * it under the terms of the GNU General Public License as published by
d08611b52000 Added two copyrights on gameServer
Gianfranco Costamagna <costamagnagianfranco@yahoo.it>
parents: 10392
diff changeset
     7
 * the Free Software Foundation; version 2 of the License
d08611b52000 Added two copyrights on gameServer
Gianfranco Costamagna <costamagnagianfranco@yahoo.it>
parents: 10392
diff changeset
     8
 *
d08611b52000 Added two copyrights on gameServer
Gianfranco Costamagna <costamagnagianfranco@yahoo.it>
parents: 10392
diff changeset
     9
 * This program is distributed in the hope that it will be useful,
d08611b52000 Added two copyrights on gameServer
Gianfranco Costamagna <costamagnagianfranco@yahoo.it>
parents: 10392
diff changeset
    10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
d08611b52000 Added two copyrights on gameServer
Gianfranco Costamagna <costamagnagianfranco@yahoo.it>
parents: 10392
diff changeset
    11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
d08611b52000 Added two copyrights on gameServer
Gianfranco Costamagna <costamagnagianfranco@yahoo.it>
parents: 10392
diff changeset
    12
 * GNU General Public License for more details.
d08611b52000 Added two copyrights on gameServer
Gianfranco Costamagna <costamagnagianfranco@yahoo.it>
parents: 10392
diff changeset
    13
 *
d08611b52000 Added two copyrights on gameServer
Gianfranco Costamagna <costamagnagianfranco@yahoo.it>
parents: 10392
diff changeset
    14
 * You should have received a copy of the GNU General Public License
d08611b52000 Added two copyrights on gameServer
Gianfranco Costamagna <costamagnagianfranco@yahoo.it>
parents: 10392
diff changeset
    15
 * along with this program; if not, write to the Free Software
d08611b52000 Added two copyrights on gameServer
Gianfranco Costamagna <costamagnagianfranco@yahoo.it>
parents: 10392
diff changeset
    16
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
d08611b52000 Added two copyrights on gameServer
Gianfranco Costamagna <costamagnagianfranco@yahoo.it>
parents: 10392
diff changeset
    17
 \-}
d08611b52000 Added two copyrights on gameServer
Gianfranco Costamagna <costamagnagianfranco@yahoo.it>
parents: 10392
diff changeset
    18
10058
4ed428389c4e - Implement /callvote
unc0rr
parents: 10049
diff changeset
    19
{-# LANGUAGE OverloadedStrings #-}
10049
ca11d122f54e Oops, forgot this
unc0rr
parents:
diff changeset
    20
module Votes where
ca11d122f54e Oops, forgot this
unc0rr
parents:
diff changeset
    21
ca11d122f54e Oops, forgot this
unc0rr
parents:
diff changeset
    22
import Control.Monad.Reader
10216
6928a323097f Fix build
unc0rr
parents: 10215
diff changeset
    23
import Control.Monad.State.Strict
10049
ca11d122f54e Oops, forgot this
unc0rr
parents:
diff changeset
    24
import ServerState
10058
4ed428389c4e - Implement /callvote
unc0rr
parents: 10049
diff changeset
    25
import qualified Data.ByteString.Char8 as B
10081
0af84e5cbd4d Implement 'voted' function
unc0rr
parents: 10058
diff changeset
    26
import qualified Data.List as L
10195
d1c23bb73346 - Room save/load into/from file
unc0rr
parents: 10090
diff changeset
    27
import qualified Data.Map as Map
10058
4ed428389c4e - Implement /callvote
unc0rr
parents: 10049
diff changeset
    28
import Data.Maybe
4ed428389c4e - Implement /callvote
unc0rr
parents: 10049
diff changeset
    29
-------------------
4ed428389c4e - Implement /callvote
unc0rr
parents: 10049
diff changeset
    30
import Utils
4ed428389c4e - Implement /callvote
unc0rr
parents: 10049
diff changeset
    31
import CoreTypes
4ed428389c4e - Implement /callvote
unc0rr
parents: 10049
diff changeset
    32
import HandlerUtils
10392
5012e1f9e893 - Support for pausing multiplayer games
alfadur
parents: 10218
diff changeset
    33
import EngineInteraction
10049
ca11d122f54e Oops, forgot this
unc0rr
parents:
diff changeset
    34
10081
0af84e5cbd4d Implement 'voted' function
unc0rr
parents: 10058
diff changeset
    35
0af84e5cbd4d Implement 'voted' function
unc0rr
parents: 10058
diff changeset
    36
voted :: Bool -> Reader (ClientIndex, IRnC) [Action]
0af84e5cbd4d Implement 'voted' function
unc0rr
parents: 10058
diff changeset
    37
voted vote = do
0af84e5cbd4d Implement 'voted' function
unc0rr
parents: 10058
diff changeset
    38
    cl <- thisClient
0af84e5cbd4d Implement 'voted' function
unc0rr
parents: 10058
diff changeset
    39
    rm <- thisRoom
0af84e5cbd4d Implement 'voted' function
unc0rr
parents: 10058
diff changeset
    40
    uid <- liftM clUID thisClient
0af84e5cbd4d Implement 'voted' function
unc0rr
parents: 10058
diff changeset
    41
10392
5012e1f9e893 - Support for pausing multiplayer games
alfadur
parents: 10218
diff changeset
    42
    case voting rm of
5012e1f9e893 - Support for pausing multiplayer games
alfadur
parents: 10218
diff changeset
    43
        Nothing -> 
5012e1f9e893 - Support for pausing multiplayer games
alfadur
parents: 10218
diff changeset
    44
            return [AnswerClients [sendChan cl] ["CHAT", "[server]", loc "There's no voting going on"]]
5012e1f9e893 - Support for pausing multiplayer games
alfadur
parents: 10218
diff changeset
    45
        Just voting ->
5012e1f9e893 - Support for pausing multiplayer games
alfadur
parents: 10218
diff changeset
    46
            if uid `L.notElem` entitledToVote voting then
5012e1f9e893 - Support for pausing multiplayer games
alfadur
parents: 10218
diff changeset
    47
                return []
5012e1f9e893 - Support for pausing multiplayer games
alfadur
parents: 10218
diff changeset
    48
            else if uid `L.elem` map fst (votes voting) then
5012e1f9e893 - Support for pausing multiplayer games
alfadur
parents: 10218
diff changeset
    49
                return [AnswerClients [sendChan cl] ["CHAT", "[server]", loc "You already have voted"]]
5012e1f9e893 - Support for pausing multiplayer games
alfadur
parents: 10218
diff changeset
    50
            else
5012e1f9e893 - Support for pausing multiplayer games
alfadur
parents: 10218
diff changeset
    51
                actOnVoting $ voting{votes = (uid, vote):votes voting}
5012e1f9e893 - Support for pausing multiplayer games
alfadur
parents: 10218
diff changeset
    52
      
10087
5ba891578621 Implement kick voting
unc0rr
parents: 10081
diff changeset
    53
    where
5ba891578621 Implement kick voting
unc0rr
parents: 10081
diff changeset
    54
    actOnVoting :: Voting -> Reader (ClientIndex, IRnC) [Action]
5ba891578621 Implement kick voting
unc0rr
parents: 10081
diff changeset
    55
    actOnVoting vt = do
10212
5fb3bb2de9d2 Some fixes to voting + small refactoring
unc0rr
parents: 10195
diff changeset
    56
        let (pro, contra) = L.partition snd $ votes vt
10392
5012e1f9e893 - Support for pausing multiplayer games
alfadur
parents: 10218
diff changeset
    57
        let totalV = length $ entitledToVote vt 
5012e1f9e893 - Support for pausing multiplayer games
alfadur
parents: 10218
diff changeset
    58
        let successV = totalV `div` 2 + 1
10087
5ba891578621 Implement kick voting
unc0rr
parents: 10081
diff changeset
    59
10392
5012e1f9e893 - Support for pausing multiplayer games
alfadur
parents: 10218
diff changeset
    60
        if length contra > totalV - successV then
10087
5ba891578621 Implement kick voting
unc0rr
parents: 10081
diff changeset
    61
            closeVoting
10392
5012e1f9e893 - Support for pausing multiplayer games
alfadur
parents: 10218
diff changeset
    62
        else if length pro >= successV then do
10215
26fc5502ba22 - Fix applying vote result
unc0rr
parents: 10212
diff changeset
    63
            a <- act $ voteType vt
26fc5502ba22 - Fix applying vote result
unc0rr
parents: 10212
diff changeset
    64
            c <- closeVoting
26fc5502ba22 - Fix applying vote result
unc0rr
parents: 10212
diff changeset
    65
            return $ c ++ a
10087
5ba891578621 Implement kick voting
unc0rr
parents: 10081
diff changeset
    66
        else
5ba891578621 Implement kick voting
unc0rr
parents: 10081
diff changeset
    67
            return [ModifyRoom $ \r -> r{voting = Just vt}]
5ba891578621 Implement kick voting
unc0rr
parents: 10081
diff changeset
    68
5ba891578621 Implement kick voting
unc0rr
parents: 10081
diff changeset
    69
    closeVoting = do
5ba891578621 Implement kick voting
unc0rr
parents: 10081
diff changeset
    70
        chans <- roomClientsChans
5ba891578621 Implement kick voting
unc0rr
parents: 10081
diff changeset
    71
        return [
5ba891578621 Implement kick voting
unc0rr
parents: 10081
diff changeset
    72
            AnswerClients chans ["CHAT", "[server]", loc "Voting closed"]
5ba891578621 Implement kick voting
unc0rr
parents: 10081
diff changeset
    73
            , ModifyRoom (\r -> r{voting = Nothing})
5ba891578621 Implement kick voting
unc0rr
parents: 10081
diff changeset
    74
            ]
5ba891578621 Implement kick voting
unc0rr
parents: 10081
diff changeset
    75
5ba891578621 Implement kick voting
unc0rr
parents: 10081
diff changeset
    76
    act (VoteKick nickname) = do
5ba891578621 Implement kick voting
unc0rr
parents: 10081
diff changeset
    77
        (thisClientId, rnc) <- ask
5ba891578621 Implement kick voting
unc0rr
parents: 10081
diff changeset
    78
        maybeClientId <- clientByNick nickname
5ba891578621 Implement kick voting
unc0rr
parents: 10081
diff changeset
    79
        rm <- thisRoom
5ba891578621 Implement kick voting
unc0rr
parents: 10081
diff changeset
    80
        let kickId = fromJust maybeClientId
5ba891578621 Implement kick voting
unc0rr
parents: 10081
diff changeset
    81
        let kickCl = rnc `client` kickId
5ba891578621 Implement kick voting
unc0rr
parents: 10081
diff changeset
    82
        let sameRoom = clientRoom rnc thisClientId == clientRoom rnc kickId
5ba891578621 Implement kick voting
unc0rr
parents: 10081
diff changeset
    83
        return
5ba891578621 Implement kick voting
unc0rr
parents: 10081
diff changeset
    84
            [KickRoomClient kickId |
5ba891578621 Implement kick voting
unc0rr
parents: 10081
diff changeset
    85
                isJust maybeClientId
5ba891578621 Implement kick voting
unc0rr
parents: 10081
diff changeset
    86
                && sameRoom
5ba891578621 Implement kick voting
unc0rr
parents: 10081
diff changeset
    87
                && ((isNothing $ gameInfo rm) || teamsInGame kickCl == 0)
5ba891578621 Implement kick voting
unc0rr
parents: 10081
diff changeset
    88
            ]
10195
d1c23bb73346 - Room save/load into/from file
unc0rr
parents: 10090
diff changeset
    89
    act (VoteMap roomSave) = do
d1c23bb73346 - Room save/load into/from file
unc0rr
parents: 10090
diff changeset
    90
        rm <- thisRoom
d1c23bb73346 - Room save/load into/from file
unc0rr
parents: 10090
diff changeset
    91
        let rs = Map.lookup roomSave (roomSaves rm)
d1c23bb73346 - Room save/load into/from file
unc0rr
parents: 10090
diff changeset
    92
        case rs of
d1c23bb73346 - Room save/load into/from file
unc0rr
parents: 10090
diff changeset
    93
             Nothing -> return []
10218
1d7112ccb3e9 Send updated info on map switched by voting
unc0rr
parents: 10216
diff changeset
    94
             Just (mp, p) -> do
1d7112ccb3e9 Send updated info on map switched by voting
unc0rr
parents: 10216
diff changeset
    95
                 cl <- thisClient
1d7112ccb3e9 Send updated info on map switched by voting
unc0rr
parents: 10216
diff changeset
    96
                 chans <- roomClientsChans
1d7112ccb3e9 Send updated info on map switched by voting
unc0rr
parents: 10216
diff changeset
    97
                 let a = map (replaceChans chans) $ answerFullConfigParams cl mp p
1d7112ccb3e9 Send updated info on map switched by voting
unc0rr
parents: 10216
diff changeset
    98
                 return $ 
1d7112ccb3e9 Send updated info on map switched by voting
unc0rr
parents: 10216
diff changeset
    99
                    (ModifyRoom $ \r -> r{params = p, mapParams = mp})
1d7112ccb3e9 Send updated info on map switched by voting
unc0rr
parents: 10216
diff changeset
   100
                    : SendUpdateOnThisRoom
1d7112ccb3e9 Send updated info on map switched by voting
unc0rr
parents: 10216
diff changeset
   101
                    : a
1d7112ccb3e9 Send updated info on map switched by voting
unc0rr
parents: 10216
diff changeset
   102
        where
1d7112ccb3e9 Send updated info on map switched by voting
unc0rr
parents: 10216
diff changeset
   103
            replaceChans chans (AnswerClients _ msg) = AnswerClients chans msg
1d7112ccb3e9 Send updated info on map switched by voting
unc0rr
parents: 10216
diff changeset
   104
            replaceChans _ a = a
10392
5012e1f9e893 - Support for pausing multiplayer games
alfadur
parents: 10218
diff changeset
   105
    act (VotePause) = do
5012e1f9e893 - Support for pausing multiplayer games
alfadur
parents: 10218
diff changeset
   106
        rm <- thisRoom
5012e1f9e893 - Support for pausing multiplayer games
alfadur
parents: 10218
diff changeset
   107
        chans <- roomClientsChans
5012e1f9e893 - Support for pausing multiplayer games
alfadur
parents: 10218
diff changeset
   108
        let modifyGameInfo f room  = room{gameInfo = fmap f $ gameInfo room}
5012e1f9e893 - Support for pausing multiplayer games
alfadur
parents: 10218
diff changeset
   109
        return [ModifyRoom (modifyGameInfo $ \g -> g{isPaused = not $ isPaused g}),
5012e1f9e893 - Support for pausing multiplayer games
alfadur
parents: 10218
diff changeset
   110
                AnswerClients chans ["CHAT", "[server]", "Pause toggled"],
5012e1f9e893 - Support for pausing multiplayer games
alfadur
parents: 10218
diff changeset
   111
                AnswerClients chans ["EM", toEngineMsg "I"]]
10081
0af84e5cbd4d Implement 'voted' function
unc0rr
parents: 10058
diff changeset
   112
10049
ca11d122f54e Oops, forgot this
unc0rr
parents:
diff changeset
   113
ca11d122f54e Oops, forgot this
unc0rr
parents:
diff changeset
   114
startVote :: VoteType -> Reader (ClientIndex, IRnC) [Action]
10058
4ed428389c4e - Implement /callvote
unc0rr
parents: 10049
diff changeset
   115
startVote vt = do
4ed428389c4e - Implement /callvote
unc0rr
parents: 10049
diff changeset
   116
    (ci, rnc) <- ask
10090
a471a7bbc339 - Start work on flood detector
unc0rr
parents: 10087
diff changeset
   117
    --cl <- thisClient
10058
4ed428389c4e - Implement /callvote
unc0rr
parents: 10049
diff changeset
   118
    rm <- thisRoom
4ed428389c4e - Implement /callvote
unc0rr
parents: 10049
diff changeset
   119
    chans <- roomClientsChans
4ed428389c4e - Implement /callvote
unc0rr
parents: 10049
diff changeset
   120
4ed428389c4e - Implement /callvote
unc0rr
parents: 10049
diff changeset
   121
    let uids = map (clUID . client rnc) . roomClients rnc $ clientRoom rnc ci
4ed428389c4e - Implement /callvote
unc0rr
parents: 10049
diff changeset
   122
4ed428389c4e - Implement /callvote
unc0rr
parents: 10049
diff changeset
   123
    if isJust $ voting rm then
4ed428389c4e - Implement /callvote
unc0rr
parents: 10049
diff changeset
   124
        return []
4ed428389c4e - Implement /callvote
unc0rr
parents: 10049
diff changeset
   125
    else
10212
5fb3bb2de9d2 Some fixes to voting + small refactoring
unc0rr
parents: 10195
diff changeset
   126
        return [
5fb3bb2de9d2 Some fixes to voting + small refactoring
unc0rr
parents: 10195
diff changeset
   127
            ModifyRoom (\r -> r{voting = Just (newVoting vt){entitledToVote = uids}})
5fb3bb2de9d2 Some fixes to voting + small refactoring
unc0rr
parents: 10195
diff changeset
   128
            , AnswerClients chans ["CHAT", "[server]", B.concat [loc "New voting started", ": ", voteInfo vt]]
5fb3bb2de9d2 Some fixes to voting + small refactoring
unc0rr
parents: 10195
diff changeset
   129
            , ReactCmd ["VOTE", "YES"]
10215
26fc5502ba22 - Fix applying vote result
unc0rr
parents: 10212
diff changeset
   130
        ]
10081
0af84e5cbd4d Implement 'voted' function
unc0rr
parents: 10058
diff changeset
   131
10049
ca11d122f54e Oops, forgot this
unc0rr
parents:
diff changeset
   132
10215
26fc5502ba22 - Fix applying vote result
unc0rr
parents: 10212
diff changeset
   133
checkVotes :: StateT ServerState IO [Action]
26fc5502ba22 - Fix applying vote result
unc0rr
parents: 10212
diff changeset
   134
checkVotes = do
26fc5502ba22 - Fix applying vote result
unc0rr
parents: 10212
diff changeset
   135
    rnc <- gets roomsClients
10216
6928a323097f Fix build
unc0rr
parents: 10215
diff changeset
   136
    liftM concat $ io $ do
10215
26fc5502ba22 - Fix applying vote result
unc0rr
parents: 10212
diff changeset
   137
        ris <- allRoomsM rnc
10216
6928a323097f Fix build
unc0rr
parents: 10215
diff changeset
   138
        mapM (check rnc) ris
10215
26fc5502ba22 - Fix applying vote result
unc0rr
parents: 10212
diff changeset
   139
    where
26fc5502ba22 - Fix applying vote result
unc0rr
parents: 10212
diff changeset
   140
        check rnc ri = do
26fc5502ba22 - Fix applying vote result
unc0rr
parents: 10212
diff changeset
   141
            e <- room'sM rnc voting ri
26fc5502ba22 - Fix applying vote result
unc0rr
parents: 10212
diff changeset
   142
            case e of
26fc5502ba22 - Fix applying vote result
unc0rr
parents: 10212
diff changeset
   143
                 Just rv -> do
26fc5502ba22 - Fix applying vote result
unc0rr
parents: 10212
diff changeset
   144
                     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
   145
                     if voteTTL rv == 0 then do
10216
6928a323097f Fix build
unc0rr
parents: 10215
diff changeset
   146
                        chans <- liftM (map sendChan) $ roomClientsM rnc ri
10215
26fc5502ba22 - Fix applying vote result
unc0rr
parents: 10212
diff changeset
   147
                        return [AnswerClients chans ["CHAT", "[server]", loc "Voting expired"]]
26fc5502ba22 - Fix applying vote result
unc0rr
parents: 10212
diff changeset
   148
                        else
26fc5502ba22 - Fix applying vote result
unc0rr
parents: 10212
diff changeset
   149
                        return []
10216
6928a323097f Fix build
unc0rr
parents: 10215
diff changeset
   150
                 Nothing -> return []
10058
4ed428389c4e - Implement /callvote
unc0rr
parents: 10049
diff changeset
   151
10081
0af84e5cbd4d Implement 'voted' function
unc0rr
parents: 10058
diff changeset
   152
10058
4ed428389c4e - Implement /callvote
unc0rr
parents: 10049
diff changeset
   153
voteInfo :: VoteType -> B.ByteString
4ed428389c4e - Implement /callvote
unc0rr
parents: 10049
diff changeset
   154
voteInfo (VoteKick n) = B.concat [loc "kick", " ", n]
10195
d1c23bb73346 - Room save/load into/from file
unc0rr
parents: 10090
diff changeset
   155
voteInfo (VoteMap n) = B.concat [loc "map", " ", n]
10392
5012e1f9e893 - Support for pausing multiplayer games
alfadur
parents: 10218
diff changeset
   156
voteInfo (VotePause) = B.concat [loc "pause"]