{- | Module : Codec.Goat.Story Description : High-level time series API Copyright : (c) Daniel Lovasko, 2016-2017 License : BSD3 Maintainer : Daniel Lovasko Stability : stable Portability : portable The Story type provides an easy-to-use high-level interface to a time series object. This module implements the building of the time series structure and enables interval queries that return value points. -} module Codec.Goat.Story ( Story(..) , storyAppend , storyDump , storyNew , storyQuery ) where import Data.Word import Codec.Goat.Fluid import Codec.Goat.TimeFrame import Codec.Goat.Util import Codec.Goat.ValueFrame -- | Representation of a time series object. The constructor arguments are -- as follows: -- * time window size -- * current time window number -- * times fluid -- * values fluid data Story = Story Word32 Word32 (Fluid Word32 TimeFrame) (Fluid Float ValueFrame) -- | Pretty-printing for the Story type. instance Show Story where show (Story wsz win ft fv) = unwords [ "Story" , "wsz=" ++ show wsz , "win=" ++ show win , "times=" ++ show ft , "values=" ++ show fv ] -- | Create a new empty story. The ratio of raw/compressed sections is -- 12/74. These fields will be configurable in the future versions of the -- module. storyNew :: Word32 -- ^ time window size -> Word32 -- ^ current time window number -> Story -- ^ new story storyNew wsz win = Story wsz win (fluidNew (12, 74)) (fluidNew (12, 74)) -- | Add new time/value pair to the story. The function will return -- Nothing in case that the value was invalid (NaN or Infinity) or when -- the time was invalid with respect to previously added times (breaking -- the series monotonicity). storyAppend :: Story -- ^ old story -> (Word32, Float) -- ^ time & value -> Maybe Story -- ^ new story storyAppend (Story wsz win ft fv) (newTime, newValue) | invalid = Nothing | otherwise = Just $ Story wsz win2 newFt newFv where valueInv = isNaN newValue || isInfinite newValue timeInv = maybe True (newTime>) (fluidFirst ft) invalid = valueInv || timeInv newWin = mod newTime wsz win2 = bool win newWin (win == newWin) newFt = fluidAppend (bool ft (fluidShift ft) (newWin == win)) newTime newFv = fluidAppend (bool fv (fluidShift fv) (newWin == win)) newValue -- | Query the story for time/value pairs within the specified time limit. storyQuery :: Story -- ^ story -> (Word32, Word32) -- ^ interval -> [(Word32, Float)] -- ^ times & values storyQuery (Story _ _ ft fv) ival | all (==False) heads = [] | otherwise = zip times values where times = fluidSelect ft heads values = fluidSelect fv heads heads = map (maybe False (inBounds ival)) (fluidHeads ft) -- | Output a list of all time/value pairs stored in the story. storyDump :: Story -- ^ story -> [(Word32, Float)] -- ^ times & values storyDump (Story _ _ ft fv) = zip (fluidDump ft) (fluidDump fv)