packages feed

caliper-0.1.0.0: src/Caliper/Syntax/Transform.hs

module Caliper.Syntax.Transform where

import Data.Function
import Data.List.NonEmpty qualified as NE
import Data.Map qualified as M
import Data.Maybe
import Data.Text qualified as T
import Data.Time.Clock
import Data.Time.LocalTime

import Caliper.Syntax.Ast

data TagPredicate
  = HasKeyValue T.Text T.Text
  | Negate TagPredicate

applyTagPredicate :: TagPredicate -> M.Map T.Text (NE.NonEmpty T.Text) -> Bool
applyTagPredicate (HasKeyValue k v) = maybe False (v `elem`) . M.lookup k
applyTagPredicate (Negate f) = not . applyTagPredicate f

sumDuration :: (Foldable f, Functor f) => f ResolvedEntry -> NominalDiffTime
sumDuration = sum . fmap entrySpan

filterByTags :: [TagPredicate] -> [ResolvedEntry] -> [ResolvedEntry]
filterByTags = foldr ((.) . filterByTag) id

filterByTag :: TagPredicate -> [ResolvedEntry] -> [ResolvedEntry]
filterByTag p = filter (applyTagPredicate p . entryMetadata)

{- | Precondition: input entries must be sorted in ascending order in absolute time
We group by perceived day, that is, the local day experienced in a given timezone
-}
groupEntriesByDay :: [ResolvedEntry] -> [NE.NonEmpty ResolvedEntry]
groupEntriesByDay = NE.groupBy ((==) `on` localDay . zonedTimeToLocalTime . entryStart)

entriesAfter :: LocalTime -> [ResolvedEntry] -> [ResolvedEntry]
entriesAfter thres = mapMaybe $ \e ->
  let ZonedTime l tz = entryStart e
      e' = e {entryStart = ZonedTime (max l thres) tz}
  in  if entrySpan e' > 0 then Just e' else Nothing

entriesBefore :: LocalTime -> [ResolvedEntry] -> [ResolvedEntry]
entriesBefore thres = mapMaybe $ \e ->
  let ZonedTime l tz = entryEnd e
      e' = e {entryEnd = ZonedTime (min l thres) tz}
  in  if entrySpan e' > 0 then Just e' else Nothing