gameServer/JoinsMonitor.hs
author sheepluva
Sun, 19 Jan 2014 13:41:11 +0100
changeset 10016 59a6d65fcb60
parent 10005 800d1bd9021a
child 10090 a471a7bbc339
permissions -rw-r--r--
(experimental) make the mysterious borders around land/hats/etc that appear on zoom vanish note: not applied to everything yet note: I'll probably merge the two functions that do the same thing (one for 1darray, one for 2darray representation of pixels) into a single function

{-# LANGUAGE BangPatterns #-}

module JoinsMonitor(
    JoinsMonitor
    , newJoinMonitor
    , cleanup
    , joinsSentry
    ) where

import qualified Data.Map as Map
import Data.Time
import Data.IORef
import qualified Data.ByteString as B
import Data.Maybe
import Control.Monad

newtype JoinsMonitor = JoinsMonitor (IORef (Map.Map B.ByteString [UTCTime]))


newJoinMonitor :: IO JoinsMonitor
newJoinMonitor = do
    ioref <- newIORef Map.empty
    return (JoinsMonitor ioref)


cleanup :: JoinsMonitor -> UTCTime -> IO ()
cleanup (JoinsMonitor ref) time = modifyIORef ref f
    where
        f = Map.mapMaybe (\v -> let v' = takeWhile (\t -> diffUTCTime time t < 60*60) v in if null v' then Nothing else Just v')


joinsSentry :: JoinsMonitor -> B.ByteString -> UTCTime -> IO Bool
joinsSentry (JoinsMonitor ref) host time = do
    m <- readIORef ref
    let lastJoins = map (diffUTCTime time) $ Map.findWithDefault [] host m
    let last30sec = length $ takeWhile (< 30) lastJoins
    let last2min = length $ takeWhile (< 120) lastJoins
    let last10min = length $ takeWhile (< 600) lastJoins
    let pass = last30sec < 2 && last2min < 4 && last10min < 6

    when pass $ writeIORef ref $ Map.alter (Just . (:) time . fromMaybe []) host m

    return pass