module Language.Nomyx.Events (
Event(..),
EventNumber,
EventData(..),
InputData(..),
Msg,
MsgData,
onEvent, onEvent_, onEventOnce,
delEvent, delAllEvents,
sendMessage, sendMessage_,
onMessage, onMessageOnce,
schedule, schedule_, schedule', schedule'_,
getCurrentTime,
oneWeek, oneDay, oneHour, oneMinute
) where
import Language.Nomyx.Expression
import Data.Typeable
import Control.Monad.State
import Data.List
import Data.Time hiding (getCurrentTime)
import Data.Time.Recurrence hiding (filter)
import Safe
onEvent :: (Typeable e, Show e, Eq e) => Event e -> ((EventNumber, EventData e) -> Nomex ()) -> Nomex EventNumber
onEvent = OnEvent
onEvent_ :: forall e. (Typeable e, Show e, Eq e) => Event e -> (EventData e -> Nomex ()) -> Nomex EventNumber
onEvent_ e h = OnEvent e (\(_, d) -> h d)
onEventOnce :: (Typeable e, Show e, Eq e) => Event e -> (EventData e -> Nomex ()) -> Nomex EventNumber
onEventOnce e h = do
let handler (en, ed) = delEvent en >> h ed
OnEvent e handler
delEvent :: EventNumber -> Nomex Bool
delEvent = DelEvent
delAllEvents :: (Typeable e, Show e, Eq e) => Event e -> Nomex ()
delAllEvents = DelAllEvents
sendMessage :: (Typeable a, Show a) => Msg a -> a -> Nomex ()
sendMessage = SendMessage
sendMessage_ :: Msg () -> Nomex ()
sendMessage_ m = SendMessage m ()
onMessage :: (Typeable m, Show m) => Msg m -> (MsgData m -> Nomex ()) -> Nomex EventNumber
onMessage = onEvent_
onMessageOnce :: (Typeable m, Show m) => Msg m -> (MsgData m -> Nomex ()) -> Nomex EventNumber
onMessageOnce = onEventOnce
schedule :: Schedule Freq -> (UTCTime -> Nomex ()) -> Nomex ()
schedule sched f = do
now <- liftEffect getCurrentTime
let next = head $ starting now sched
if next == now then executeAndScheduleNext (f . timeData) sched (TimeData now)
else void $ onEventOnce (Time next) $ executeAndScheduleNext (f . timeData) sched
executeAndScheduleNext :: (EventData Time -> Nomex ()) -> Schedule Freq -> EventData Time -> Nomex ()
executeAndScheduleNext f sched now = do
f now
let rest = drop 1 $ starting (timeData now) sched
when (rest /= []) $ void $ onEventOnce (Time $ head rest) $ executeAndScheduleNext f sched
schedule_ :: Schedule Freq -> Nomex () -> Nomex ()
schedule_ ts f = schedule ts (const f)
schedule' :: [UTCTime] -> (UTCTime -> Nomex ()) -> Nomex ()
schedule' sched f = do
let sched' = sort sched
now <- liftEffect getCurrentTime
let nextMay = headMay $ filter (>=now) sched'
case nextMay of
Just next -> if next == now then executeAndScheduleNext' (f . timeData) sched' (TimeData now)
else void $ onEventOnce (Time next) $ executeAndScheduleNext' (f . timeData) sched'
Nothing -> return ()
executeAndScheduleNext' :: (EventData Time -> Nomex ()) -> [UTCTime] -> EventData Time -> Nomex ()
executeAndScheduleNext' f sched now = do
f now
let rest = drop 1 sched
when (rest /= []) $ void $ onEventOnce (Time $ head rest) $ executeAndScheduleNext' f sched
schedule'_ :: [UTCTime] -> Nomex () -> Nomex ()
schedule'_ ts f = schedule' ts (const f)
getCurrentTime :: NomexNE UTCTime
getCurrentTime = CurrentTime
oneWeek, oneDay, oneHour, oneMinute :: NominalDiffTime
oneWeek = 7 * oneDay
oneDay = 24 * oneHour
oneHour = 60 * oneMinute
oneMinute = 60