packages feed

chart-cli-0.1.0.0: src/Types.hs

{-# LANGUAGE ExistentialQuantification #-}
{-# LANGUAGE StandaloneDeriving #-}
module Types where

import qualified Data.Text as T
import Data.Dates
import Data.Time
import Data.Time.Calendar
import Data.Time.LocalTime
import Data.Colour
import Graphics.Rendering.Chart

data ParseOptions = ParseOptions {
      poHeader :: Bool
    , poSeparator :: T.Text
    , poIndex :: Bool
  }
  deriving (Eq, Show)

data Value =
    Number Double
  | Index PlotIndex
  | Date { toTime :: LocalTime }
  deriving (Eq, Show, Ord)

toDouble :: Value -> Double
toDouble (Number x) = x
toDouble (Index i) = toValue i
toDouble (Date dt) = error $ "can't convert date/time to double"

toIndex :: Value -> PlotIndex
toIndex (Number x) = PlotIndex $ round x
toIndex (Index i) = i
toINdex (Date dt) = error $ "can't convert date/time to index"

data Column =
    NumberColumn T.Text
  | DateColumn T.Text
  deriving (Eq, Show)

data ChartData = ChartData {
      chtTitle :: T.Text
    , chtBackground :: Colour Double
    , chtForeground :: Colour Double
    , chtLegend :: Bool
    , chtColumns :: [Column]
    , chtValues :: [[Value]]
  }
  deriving (Eq, Show)

deriving instance Eq PlotBarsStyle

data ChartConfig =
    Line
  | Bar { barStyle :: PlotBarsStyle }
  | Area
  | Points
  deriving (Eq, Show)

data AnyChart =
    LineChart [PlotLines Value Double]
  | BarChart (PlotBars Value Double)
  | AreaChart [PlotFillBetween Value Double]
  | PointsChart [PlotPoints Value Double]

toLocalTime :: DateTime -> LocalTime
toLocalTime dt =
  let localDay = fromGregorian (fromIntegral $ year dt) (month dt) (day dt)
      time = TimeOfDay (hour dt) (minute dt) (fromIntegral $ second dt)
  in  LocalTime localDay time

mapAxisData :: (x -> y) -> (y -> x) -> AxisData x -> AxisData y
mapAxisData to from axis =
  axis {
      _axis_viewport = \range x -> _axis_viewport axis range (from x)
    , _axis_tropweiv = \range d -> to (_axis_tropweiv axis range d)
    , _axis_ticks = [(to x, d) | (x, d) <- _axis_ticks axis]
    , _axis_labels = [[(to x, s) | (x, s) <- pairs] | pairs <- _axis_labels axis]
    , _axis_grid = map to (_axis_grid axis)
  }

instance PlotValue Value where
  toValue (Number x) = x
  toValue (Date dt) = toValue dt
  toValue (Index i) = toValue i

  fromValue x = Number x
  
  autoAxis = \list ->
    case list of
      [] -> mapAxisData Number toDouble $ autoAxis $ map toDouble list
      (Number x : _) -> mapAxisData Number toDouble $ autoAxis $ map toDouble list
      (Date dt : _) -> mapAxisData Date toTime $ autoAxis $ map toTime list
      (Index i : _) -> mapAxisData Index toIndex $ autoAxis $ map toIndex list

data CmdLine = CmdLine {
      cmdOutput :: FilePath
    , cmdChart :: ChartConfig
    , cmdParse :: ParseOptions
    , cmdTitle :: Maybe String
    , cmdWidth :: Int
    , cmdHeight :: Int
    , cmdBackground :: Colour Double
    , cmdForeground :: Colour Double
    , cmdLegend :: Bool
    , cmdInput :: Maybe FilePath
  }
  deriving (Show)