Util.hs
module Frontend.Util where
import Prelude
import Data.Argonaut.Core (Json)
import Data.Argonaut.Decode (JsonDecodeError, decodeJson, (.:))
import Data.Array (filter, length, zip, (..))
import Data.DateTime (DateTime, Time(..), adjust, diff, modifyTime, setMillisecond, setMinute, setSecond)
import Data.DateTime.Instant (fromDateTime, instant, toDateTime, unInstant)
import Data.Either (Either, either, note)
import Data.Formatter.DateTime (formatDateTime)
import Data.Int (floor, toNumber)
import Data.Maybe (Maybe, fromMaybe)
import Data.Newtype (unwrap)
import Data.Time.Duration (Days(..), Hours(..), Milliseconds(..), Seconds(..))
import Data.Traversable (sequence, traverse)
import Data.Tuple (Tuple)
import Effect.Aff (Aff, error, makeAff)
import Graphics.Canvas (CanvasImageSource, tryLoadImage)
import Halogen.HTML as HH
import Halogen.HTML.Properties as HP
classes :: forall r i. Array String -> HH.IProp (class :: String | r) i
classes = HP.classes <<< map HH.ClassName
formatDateTime' :: DateTime -> String
formatDateTime' = either identity identity <<< formatDateTime "YYYY-MM-DD HH:mm:ss.SS"
datetimeToSeconds :: DateTime -> Number
datetimeToSeconds = (_ / 1000.0) <<< unwrap <<< unInstant <<< fromDateTime
secondsToDateTime :: Number -> Maybe DateTime
secondsToDateTime = map toDateTime <<< instant <<< Milliseconds <<< (_ * 1000.0)
-- TODO: convert stuff to local time
-- getTimezoneOffset $ fromDateTime start
midnightBefore :: DateTime -> DateTime
midnightBefore = modifyTime (const $ Time bottom bottom bottom bottom)
hourBefore :: DateTime -> DateTime
hourBefore = modifyTime (setMinute bottom <<< setSecond bottom <<< setMillisecond bottom)
daysInInterval :: DateTime -> DateTime -> Array DateTime
daysInInterval start end = do
let
midnight = midnightBefore start
duration = diff end midnight :: Days
nDays = floor (unwrap duration)
fromMaybe [] <<< sequence $
0 .. nDays <#> \n ->
adjust (Days (toNumber n)) midnight
hoursInInterval :: DateTime -> DateTime -> DateTime -> Array DateTime
hoursInInterval current start end = do
let
midnight = midnightBefore current
hours = 0 .. 23 <#> Hours <<< toNumber
hoursDT = fromMaybe [] <<< sequence $ hours <#> \n -> adjust n midnight
filter (\a -> (unwrap (a `diff` start :: Hours) >= -1.0) && a <= end) hoursDT
decodeTimestamps :: Json -> Either JsonDecodeError (Array Number)
decodeTimestamps json = do
o <- decodeJson json
contents <- o .: "Ok"
decodeJson contents >>= traverse decodeJson
formatDuration :: Seconds -> String
formatDuration (Seconds t) = let
h = floor $ t / 3600.0
m = floor (t / 60.0) - h * 60
s = floor t - h * 3600 - m * 60
in show h <> "h " <> show m <> "m " <> show s <> "s"
loadImage :: String -> Aff CanvasImageSource
loadImage url = do
makeAff \cont -> do
tryLoadImage url \msource ->
note (error $ "Failed to load image from \"" <> url <> "\"") msource # cont
mempty
enumerate :: forall a. Array a -> Array (Tuple Int a)
enumerate a = zip (0 .. (length a - 1)) a