content: {-# LANGUAGE OverloadedStrings #-}
  {-# LANGUAGE QuasiQuotes #-}
  
  --
  -- Based on the Elm VegaLite TimeTests.elm as of version 1.12.0
  --
  
  module TimeTests (testSpecs) where
  
  import Data.Aeson (Value)
  import Data.Aeson.QQ.Simple (aesonQQ)
  
  import Graphics.Vega.VegaLite
  
  import Prelude hiding (filter)
  
  testSpecs :: [(String, VegaLite)]
  testSpecs = [ ("timeYear", timeYear)
              , ("timeQuarter", timeQuarter)
              , ("timeQuarterMonth", timeQuarterMonth)
              , ("timeMonth", timeMonth)
              , ("timeMonthDate", timeMonthDate)
              , ("timeDate", timeDate)
              , ("timeYearMonthDateHours", timeYearMonthDateHours)
              , ("timeYearMonthDateHoursMinutes", timeYearMonthDateHoursMinutes)
              , ("timeYearMonthDateHoursMinutesSeconds", timeYearMonthDateHoursMinutesSeconds)
              , ("timeDay", timeDay)
              , ("timeHours", timeHours)
              , ("timeHoursMinutes", timeHoursMinutes)
              , ("timeHoursMinutesSeconds", timeHoursMinutesSeconds)
              , ("timeMinutes", timeMinutes)
              , ("timeMinutesSeconds", timeMinutesSeconds)
              , ("localTime", localTime)
              , ("utcTime", utcTime)
              , ("monthAggregate", monthAggregate)
              , ("withBar", withBar)
              , ("timeBand", timeBand)
              , ("withBarOrdinal", withBarOrdinal)
              , ("timeUnitTransform", timeUnitTransform)
              , ("parseAsUTC", parseAsUTC)
              , ("parseAsLocal", parseAsLocal)
              , ("parseAsFormat", parseAsFormat)
              , ("outputAsUTC", outputAsUTC)
              , ("outputScaledAsUTC", outputScaledAsUTC)
              , ("customizeStep", customizeStep)
              , ("nestedTime1", nestedTime1)
              , ("nestedTime2", nestedTime2)
              ]
  
  
  timeByUnit :: BaseTimeUnit -> VegaLite
  timeByUnit btu =
      let
          dataVals =
              dataFromUrl "https://gicentre.github.io/data/tests/timeTest.tsv" []
  
          enc =
              encoding
                  . position X [ PName "date", PmType Temporal, PTimeUnit (TU btu) ]
                  . position Y [ PName "temperature", PmType Quantitative
                               , PAggregate Mean, PScale [ SZero False ] ]
      in
      toVegaLite [ width 800, dataVals, enc []
                 , mark Line [ MStrokeWidth 0.2 ] ]
  
  
  timeYear :: VegaLite
  timeYear = timeByUnit Year
  
  
  timeQuarter :: VegaLite
  timeQuarter = timeByUnit Quarter
  
  
  timeQuarterMonth :: VegaLite
  timeQuarterMonth = timeByUnit QuarterMonth
  
  
  timeMonth :: VegaLite
  timeMonth = timeByUnit Month
  
  
  timeMonthDate :: VegaLite
  timeMonthDate = timeByUnit MonthDate
  
  
  timeDate :: VegaLite
  timeDate = timeByUnit Date
  
  
  timeYearMonthDateHours :: VegaLite
  timeYearMonthDateHours = timeByUnit YearMonthDateHours
  
  
  timeYearMonthDateHoursMinutes :: VegaLite
  timeYearMonthDateHoursMinutes = timeByUnit YearMonthDateHoursMinutes
  
  
  timeYearMonthDateHoursMinutesSeconds :: VegaLite
  timeYearMonthDateHoursMinutesSeconds =
      timeByUnit YearMonthDateHoursMinutesSeconds
  
  
  timeDay :: VegaLite
  timeDay = timeByUnit Day
  
  
  timeHours :: VegaLite
  timeHours = timeByUnit Hours
  
  
  timeHoursMinutes :: VegaLite
  timeHoursMinutes = timeByUnit HoursMinutes
  
  
  timeHoursMinutesSeconds :: VegaLite
  timeHoursMinutesSeconds = timeByUnit HoursMinutesSeconds
  
  
  timeMinutes :: VegaLite
  timeMinutes = timeByUnit Minutes
  
  
  timeMinutesSeconds :: VegaLite
  timeMinutesSeconds = timeByUnit MinutesSeconds
  
  -- TODO: Add milliseconds example
  -- | SecondsMilliseconds
  -- | Milliseconds
  
  
  data Date
      = Local
      | UTC
  
  
  parseTime :: Date -> VegaLite
  parseTime dType =
      let
          format =
              case dType of
                  Local ->
                      FoDate "%d %b %Y %H:%M"
  
                  UTC ->
                      FoUtc "%d %b %Y %H:%M"
  
          tu =
              case dType of
                  Local ->
                      PTimeUnit (TU YearMonthDateHours)
  
                  UTC ->
                      PTimeUnit (Utc YearMonthDateHours)
  
          timeScale =
              case dType of
                  Local ->
                      PScale [ SType ScTime ]
  
                  UTC ->
                      PScale [ SType ScUtc ]
  
          dataVals =
              dataFromColumns [ Parse [ ( "date", format ) ] ]
                  . dataColumn "date" (Strings [ "28 Oct 2017 22:00", "28 Oct 2017 23:00", "29 Oct 2017 00:00", "29 Oct 2017 01:00", "29 Oct 2017 02:00", "29 Oct 2017 03:00", "29 Oct 2017 04:00" ])
                  . dataColumn "value" (Numbers [ 1, 2, 3, 4, 5, 6, 7 ])
  
          enc =
              encoding
                  . position X [ PName "date", PmType Temporal
                               , tu, timeScale
                               , PAxis [ AxFormat "%d %b %H:%M" ] ]
                  . position Y [ PName "value", PmType Quantitative ]
                  . size [ MNumber 500 ]
      in
      toVegaLite [ width 800, dataVals [], enc [], mark Circle [] ]
  
  
  localTime :: VegaLite
  localTime = parseTime Local
  
  
  utcTime :: VegaLite
  utcTime = parseTime UTC
  
  
  -- examples from the documentation
  --
  -- https://vega.github.io/vega-lite/docs/timeunit.html
  
  seattleTemps :: Data
  seattleTemps = dataFromUrl "https://vega.github.io/vega-lite/data/seattle-temps.csv" []
  
  seattleWeather :: Data
  seattleWeather = dataFromUrl "https://vega.github.io/vega-lite/data/seattle-weather.csv" []
  
  
  monthAggregate :: VegaLite
  monthAggregate =
    let enc = encoding
              . position X [ PName "date"
                           , PTimeUnit (TU Month)
                           , PmType Temporal
                           ]
              . position Y [ PName "temp"
                           , PAggregate Mean
                           , PmType Quantitative ]
  
    in toVegaLite
          [ seattleTemps
          , mark Line [MInterpolate Monotone]
          , enc []
          ]
  
  
  withBar :: VegaLite
  withBar =
    let enc = encoding
              . position X [ PName "date"
                           , PTimeUnit (TU Month)
                           , PmType Temporal
                           ]
              . position Y [ PName "precipitation"
                           , PAggregate Mean
                           , PmType Quantitative ]
  
    in toVegaLite
          [ seattleWeather
          , mark Bar []
          , enc []
          ]
  
  
  -- https://vega.github.io/vega-lite/docs/timeunit.html#time-units-band
  
  timeBand :: VegaLite
  timeBand =
    let enc = encoding
              . position X [ PName "date", PTimeUnit (TU Month)
                           , PmType Temporal, PBand 0.5 ]
              . position Y [ PName "temp", PAggregate Mean
                           , PmType Quantitative ]
  
    in toVegaLite
          [ width 400
          , seattleTemps
          , enc []
          , mark Line [ MPoint (PMMarker [ MFill "black" ]) ]
          ]
  
  
  -- https://vega.github.io/vega-lite/docs/timeunit.html#time-unit-with-ordinal-fields
  
  withBarOrdinal :: VegaLite
  withBarOrdinal =
    let enc = encoding
              . position X [ PName "date"
                           , PTimeUnit (TU Month)
                           , PmType Ordinal
                           ]
              . position Y [ PName "precipitation"
                           , PAggregate Mean
                           , PmType Quantitative ]
  
    in toVegaLite
          [ seattleWeather
          , mark Bar []
          , enc []
          ]
  
  
  -- https://vega.github.io/vega-lite/docs/timeunit.html#transform
  
  timeUnitTransform :: VegaLite
  timeUnitTransform =
    let enc = encoding
              . position X [ PName "month"
                           , PmType Temporal
                           , PAxis [AxFormat "%b"]
                           ]
              . position Y [ PName "temp_max"
                           , PAggregate Max
                           , PmType Quantitative ]
  
    in toVegaLite
          [ seattleWeather
          , mark Line []
          , transform (timeUnitAs (TU Month) "date" "month" [])
          , enc []
          ]
  
  
  -- https://vega.github.io/vega-lite/docs/timeunit.html#input
  
  parseAsUTC :: VegaLite
  parseAsUTC =
    toVegaLite [ dataFromColumns []
                 . dataColumn "date" (Strings ["2011-10-10", "2011-10-12"])
                 $ []
               , mark Point []
               , encoding
                 . position Y [ PName "date"
                              , PmType Ordinal
                              , PTimeUnit (Utc Hours)
                              , PAxis [AxTitle "time"]
                              ]
                 $ []
               ]
  
  
  parseAsLocal :: VegaLite
  parseAsLocal =
    toVegaLite [ dataFromColumns []
                 . dataColumn "date" (Strings ["10 Oct 2011 22:48:00", "11 Oct 2022 23:00:00"])
                 $ []
               , mark Point []
               , encoding
                 . position Y [ PName "date"
                              , PmType Ordinal
                              , PTimeUnit (TU HoursMinutes)
                              , PAxis [AxTitle "time"]
                              ]
                 $ []
               ]
  
  
  parseAsFormat :: VegaLite
  parseAsFormat =
    toVegaLite [ dataFromColumns [Parse [("date", FoUtc "%d %b %Y %H:%M:%S")]]
                 . dataColumn "date" (Strings ["10 Oct 2011 22:48:00", "11 Oct 2022 23:00:00"])
                 $ []
               , mark Point []
               , encoding
                 . position Y [ PName "date"
                              , PmType Ordinal
                              , PTimeUnit (TU HoursMinutes)
                              , PAxis [AxTitle "time"]
                              ]
                 $ []
               ]
  
  
  -- https://vega.github.io/vega-lite/docs/timeunit.html#output
  
  exampleData :: Data
  exampleData =
    dataFromColumns []
    . dataColumn "date" (Strings [ "Sun, 01 Jan 2012 23:00:00"
                                 , "Sun, 02 Jan 2012 00:00:00"
                                 , "Sun, 02 Jan 2012 01:00:00"
                                 , "Sun, 02 Jan 2012 02:00:00"
                                 , "Sun, 02 Jan 2012 03:00:00"
                                 ])
  
    . dataColumn "price" (Numbers [150, 100, 170, 165, 200])
    $ []
  
  
  outputAsUTC :: VegaLite
  outputAsUTC =
    toVegaLite [ exampleData
               , mark Line []
               , encoding
                 . position X [ PName "date"
                              , PmType Temporal
                              , PTimeUnit (Utc YearMonthDateHoursMinutes)
                              , PAxis [AxLabelAngle 15]
                              ]
                 . position Y [ PName "price"
                              , PmType Quantitative
                              ]
                 $ []
               ]
  
  
  outputScaledAsUTC :: VegaLite
  outputScaledAsUTC =
    toVegaLite [ exampleData
               , mark Line []
               , encoding
                 . position X [ PName "date"
                              , PmType Temporal
                              , PTimeUnit (TU YearMonthDateHoursMinutes)
                              , PScale [SType ScUtc]
                              , PAxis [AxLabelAngle 15]
                              ]
                 . position Y [ PName "price"
                              , PmType Quantitative
                              ]
                 $ []
               ]
  
  
  -- https://vega.github.io/vega-lite/docs/timeunit.html#example-customizing-step
  
  customizeStep :: VegaLite
  customizeStep =
    toVegaLite [ dataFromColumns []
                 . dataColumn "date" (Strings [ "Sun, 01 Jan 2012 00:00:00"
                                              , "Sun, 01 Jan 2012 00:01:00"
                                              , "Sun, 01 Jan 2012 00:02:00"
                                              , "Sun, 01 Jan 2012 00:03:00"
                                              , "Sun, 01 Jan 2012 00:04:00"
                                              , "Sun, 01 Jan 2012 00:05:00"
                                              , "Sun, 01 Jan 2012 00:06:00"
                                              , "Sun, 01 Jan 2012 00:07:00"
                                              , "Sun, 01 Jan 2012 00:08:00"
                                              , "Sun, 01 Jan 2012 00:09:00"
                                              , "Sun, 01 Jan 2012 00:10:00"
                                              , "Sun, 01 Jan 2012 00:11:00"
                                              , "Sun, 01 Jan 2012 00:12:00"
                                              , "Sun, 01 Jan 2012 00:13:00"
                                              , "Sun, 01 Jan 2012 00:14:00"
                                              , "Sun, 01 Jan 2012 00:15:00"
                                              ])
                 . dataColumn "distance" (Numbers [ 1
                                                  , 1
                                                  , 2
                                                  , 1
                                                  , 4
                                                  , 2
                                                  , 5
                                                  , 2
                                                  , 6
                                                  , 4
                                                  , 1
                                                  , 1
                                                  , 3
                                                  , 0
                                                  , 2
                                                  , 3
                                                  ])
                 $ []
               , mark Bar []
               , encoding
                 . position X [ PName "date"
                              , PmType Temporal
                              , PTimeUnit (TUStep 5 Minutes)
                              ]
                 . position Y [ PName "distance"
                              , PmType Quantitative
                              , PAggregate Sum
                              ]
                 $ []
               ]
  
  
  embeddedData, flattenedData :: Value
  embeddedData = [aesonQQ|
  [
     {"histo": {"date": "Sun, 02 Jan 2012 00:00:00", "price": 150}},
     {"histo": {"date": "Sun, 02 Jan 2012 00:00:00", "price": 100}},
     {"histo": {"date": "Sun, 02 Jan 2012 01:00:00", "price": 170}},
     {"histo": {"date": "Sun, 02 Jan 2012 02:00:00", "price": 165}},
     {"histo": {"date": "Sun, 02 Jan 2012 03:00:00", "price": 200}}
  ]
  |]
    
  flattenedData = [aesonQQ|
  [
     {"date": "Sun, 02 Jan 2012 00:00:00", "price": 150},
     {"date": "Sun, 02 Jan 2012 00:00:00", "price": 100},
     {"date": "Sun, 02 Jan 2012 01:00:00", "price": 170},
     {"date": "Sun, 02 Jan 2012 02:00:00", "price": 165},
     {"date": "Sun, 02 Jan 2012 03:00:00", "price": 200}
  ]
  |]
    
  
  -- https://github.com/vega/vega-lite/issues/5662
  
  nestedTime :: Value -> FieldName -> FieldName -> VegaLite
  nestedTime jData xname yname =
    let desc = "Google's stock price over time."
        dvals = dataFromJson jData []
        
    in toVegaLite [ description desc
                  , dvals
                  , mark Line []
                  , encoding
                    . position X [ PName xname
                                 , PmType Temporal
                                 , PTimeUnit (TU YearMonthDateHoursMinutes)
                                 , PScale [SType ScUtc]
                                 ]
                    . position Y [ PName yname
                                 , PmType Quantitative
                                 ]
                    $ []
                  ]
  
    
  nestedTime1, nestedTime2 :: VegaLite
  nestedTime1 = nestedTime embeddedData "histo.date" "histo.price"
  nestedTime2 = nestedTime flattenedData "date" "price"
  