Skip to content
This repository was archived by the owner on Mar 21, 2020. It is now read-only.

Commit cb81ade

Browse files
tonyd256Tony DiPasquale
authored andcommitted
Add hash map for persisting channel state
1 parent cef43fd commit cb81ade

File tree

10 files changed

+74
-9
lines changed

10 files changed

+74
-9
lines changed

docker-compose.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ web:
33
command: cabal run
44
environment:
55
SLACK_API_TOKEN: "xoxb-4375956194-kvlljrTk9LWIi5RxhqfrScu4"
6+
LONG_ALPHA: 0.2
7+
SHORT_ALPHA: 0.8
68
stdin_open: true
79
tty: true
810
volumes:

fomobot.cabal

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ executable fomobot
3434
, wuss
3535
, mtl
3636
, monad-loops
37+
, hashmap
38+
, time
3739

3840
hs-source-dirs: src
3941
default-language: Haskell2010

src/FOMObot/App.hs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import System.Environment (getEnv)
66
import Data.Maybe (fromJust)
77
import Network.URI (parseURI)
88
import Control.Monad.Trans (liftIO)
9-
import Control.Monad.State (get, modify)
9+
import Control.Monad.State (get)
1010
import qualified Data.Text as T
1111
import Data.List (find)
1212

@@ -21,19 +21,20 @@ import FOMObot.Types.BotConfig
2121

2222
runApp :: Bot ()
2323
runApp = do
24-
state <- get
25-
2624
message@Message{..} <- receiveMessage
2725
printMessage message
26+
updateState message
2827
alertFOMOChannel _text
28+
state <- get
2929
liftIO $ print $ "state: " ++ (show state)
30-
modify (+1)
3130

3231
initApp :: IO ()
3332
initApp = do
3433
token <- T.pack <$> getEnv "SLACK_API_TOKEN"
3534
response <- rtmStartResponse token
36-
let partialConfig = BotConfig (getFOMOChannelID response) (_selfID response)
35+
longAlpha <- read <$> getEnv "LONG_ALPHA"
36+
shortAlpha <- read <$> getEnv "SHORT_ALPHA"
37+
let partialConfig = BotConfig (getFOMOChannelID response) (_selfID response) longAlpha shortAlpha
3738
let uri = fromJust $ parseURI $ _url response
3839
runSecureClient uri partialConfig runApp
3940
where

src/FOMObot/Helpers/Bot.hs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,23 @@ module FOMObot.Helpers.Bot
33
, printMessage
44
, sendMessage
55
, alertFOMOChannel
6+
, updateState
67
) where
78

89
import Control.Monad.Trans (liftIO)
10+
import Control.Monad.State (modify)
911
import Control.Monad.Reader (ask)
1012
import Control.Monad.Loops (untilJust)
1113
import Data.Aeson (decode, encode)
14+
import Data.HashMap (member, insert, adjust)
1215
import qualified Network.WebSockets as WS
1316

1417
import FOMObot.Types.Message
1518
import FOMObot.Types.Bot
1619
import FOMObot.Types.BotConfig
20+
import FOMObot.Types.ChannelState
21+
import FOMObot.Helpers.Time
22+
import FOMObot.Helpers.MovingAverage
1723

1824
receiveMessage :: Bot Message
1925
receiveMessage = do
@@ -43,3 +49,22 @@ alertFOMOChannel message = (sendMessage message) =<< _channelID <$> ask
4349

4450
connection :: Bot WS.Connection
4551
connection = _connection <$> ask
52+
53+
updateState :: Message -> Bot ()
54+
updateState message = modify =<< (alterState message) <$> ask
55+
56+
alterState :: Message -> BotConfig -> BotState -> BotState
57+
alterState Message{..} config state
58+
| member _channel state = adjust (updateChannelState config _ts) _channel state
59+
| otherwise = insert _channel newChannelState state
60+
where
61+
newChannelState = ChannelState 1 0 0 _ts
62+
63+
updateChannelState :: BotConfig -> String -> ChannelState -> ChannelState
64+
updateChannelState BotConfig{..} ts ChannelState{..} = ChannelState (_count + 1) longAvg shortAvg ts
65+
where
66+
longAvg = singleExpSmoothing longAlpha _longAvg diff
67+
shortAvg = singleExpSmoothing shortAlpha _shortAvg diff
68+
longAlpha = realToFrac _longAlpha
69+
shortAlpha = realToFrac _shortAlpha
70+
diff = diffTime ts _lastTimeStamp
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
module FOMObot.Helpers.MovingAverage
2+
( singleExpSmoothing
3+
) where
4+
5+
singleExpSmoothing :: Num a => a -> a -> a -> a
6+
singleExpSmoothing alpha avg datum = (1 - alpha) * avg + alpha * datum

src/FOMObot/Helpers/Time.hs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
module FOMObot.Helpers.Time
2+
( diffTime
3+
)where
4+
5+
import Data.Maybe (fromJust)
6+
import Data.Time (parseTimeM, defaultTimeLocale)
7+
import Data.Time.Clock (diffUTCTime, NominalDiffTime)
8+
9+
diffTime :: String -> String -> NominalDiffTime
10+
diffTime ts1 ts2 = fromJust $ diffUTCTime <$> (parse ts1) <*> (parse ts2)
11+
where
12+
parse = parseTimeM True defaultTimeLocale "%s%Q"

src/FOMObot/Types/Bot.hs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,16 @@ module FOMObot.Types.Bot where
33
import Control.Monad (forever, void)
44
import Control.Monad.Reader (ReaderT, runReaderT)
55
import Control.Monad.State (StateT, execStateT)
6+
import Data.HashMap (Map)
67

78
import FOMObot.Types.BotConfig
9+
import FOMObot.Types.ChannelState
810

9-
type Bot = ReaderT BotConfig (StateT Int IO)
11+
type BotState = Map String ChannelState
1012

11-
runBot :: Int -> BotConfig -> Bot () -> IO ()
13+
type Bot = ReaderT BotConfig (StateT BotState IO)
14+
15+
runBot :: BotState -> BotConfig -> Bot () -> IO ()
1216
runBot initialState config bot = void $ execInitialState $ runReaderT foreverBot config
1317
where
1418
foreverBot = forever bot

src/FOMObot/Types/BotConfig.hs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,7 @@ type PartialConfig = WS.Connection -> BotConfig
77
data BotConfig = BotConfig
88
{ _channelID :: String
99
, _botID :: String
10+
, _longAlpha :: Double
11+
, _shortAlpha :: Double
1012
, _connection :: WS.Connection
1113
}

src/FOMObot/Types/ChannelState.hs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
module FOMObot.Types.ChannelState where
2+
3+
import Data.Time.Clock (NominalDiffTime)
4+
5+
data ChannelState = ChannelState
6+
{ _count :: Int
7+
, _longAvg :: NominalDiffTime
8+
, _shortAvg :: NominalDiffTime
9+
, _lastTimeStamp :: String
10+
} deriving (Show)

src/FOMObot/Websockets.hs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import Network.URI (URI(..), uriRegName)
77
import qualified Wuss
88
import qualified Network.WebSockets as WS
99
import qualified Data.Text as T
10+
import Data.HashMap (empty)
1011

1112
import FOMObot.Types.Bot
1213
import FOMObot.Types.BotConfig
@@ -16,8 +17,8 @@ app partialConfig bot connection = do
1617
putStrLn "Connected!"
1718

1819
let config = partialConfig connection
19-
let initialMessageCount = 0
20-
runBot initialMessageCount config bot
20+
let initialState = empty
21+
runBot initialState config bot
2122

2223
WS.sendClose connection $ T.pack "Bye!"
2324

0 commit comments

Comments
 (0)