content: {-# LANGUAGE OverloadedStrings #-}
  
  --
  -- Based on the Elm VegaLite GalleryMulti.elm (from development of version
  -- 1.13.0)
  --
  module Gallery.Multi (testSpecs) where
  
  import Graphics.Vega.VegaLite
  
  import Prelude hiding (filter, lookup, repeat)
  
  testSpecs :: [(String, VegaLite)]
  testSpecs = [ ("multi1", multi1)
              , ("multi2", multi2)
              , ("multi3", multi3)
              , ("multi4", multi4)
              , ("multi5", multi5)
              , ("multi6", multi6)
              , ("multi7", multi7)
              , ("multi8", multi8)
              , ("selectandzoom", selectAndZoom)
              ]
  
  
  multi1 :: VegaLite
  multi1 =
      let
          des =
              description "Overview and detail."
  
          sel =
              selection . select "myBrush" Interval [ Encodings [ ChX ] ]
  
          enc1 =
              encoding
                  . position X
                      [ PName "date"
                      , PmType Temporal
                      , PScale [ SDomainOpt (DSelection "myBrush") ]
                      , PAxis [ AxNoTitle ]
                      ]
                  . position Y [ PName "price", PmType Quantitative ]
  
          spec1 =
              asSpec [ width 500, mark Area [], enc1 [] ]
  
          enc2 =
              encoding
                  . position X [ PName "date", PmType Temporal, PAxis [ AxFormat "%Y" ] ]
                  . position Y
                      [ PName "price"
                      , PmType Quantitative
                      , PAxis [ AxTickCount 3, AxGrid False ]
                      ]
  
          spec2 =
              asSpec [ width 480, height 60, sel [], mark Area [], enc2 [] ]
      in
      toVegaLite
          [ des
          , dataFromUrl "https://vega.github.io/vega-lite/data/sp500.csv" []
          , vConcat [ spec1, spec2 ]
          ]
  
  
  multi2 :: VegaLite
  multi2 =
      let
          des =
              description "Cross-filter."
  
          trans =
              transform
                  . calculateAs "hours(datum.date)" "time"
  
          sel =
              selection . select "myBrush" Interval [ Encodings [ ChX ] ]
  
          selTrans =
              transform
                  . filter (FSelection "myBrush")
  
          encPosition =
              encoding
                  . position X
                      [ PRepeat Column
                      , PmType Quantitative
                      , PBin [ MaxBins 20 ]
                      ]
                  . position Y [ PAggregate Count, PmType Quantitative ]
  
          spec1 =
              asSpec [ sel [], mark Bar [] ]
  
          spec2 =
              asSpec [ selTrans [], mark Bar [], encoding (color [ MString "goldenrod" ] []) ]
  
          spec =
              asSpec
                  [ des
                  , dataFromUrl "https://vega.github.io/vega-lite/data/flights-2k.json" [ Parse [ ( "date", FoDate "" ) ] ]
                  , trans []
                  , encPosition []
                  , layer [ spec1, spec2 ]
                  ]
      in
      toVegaLite
          [ repeat [ ColumnFields [ "distance", "delay", "time" ] ]
          , specification spec
          ]
  
  
  multi3 :: VegaLite
  multi3 =
      let
          des =
              description "Scatterplot matrix"
  
          sel =
              selection
                  . select "myBrush"
                      Interval
                      [ On "[mousedown[event.shiftKey], window:mouseup] > window:mousemove!"
                      , Translate "[mousedown[event.shiftKey], window:mouseup] > window:mousemove!"
                      , Zoom "wheel![event.shiftKey]"
                      , ResolveSelections Union
                      ]
                  . select "grid"
                      Interval
                      [ BindScales
                      , Translate "[mousedown[!event.shiftKey], window:mouseup] > window:mousemove!"
                      , Zoom "wheel![event.shiftKey]"
                      , ResolveSelections Global
                      ]
  
          enc =
              encoding
                  . position X [ PRepeat Column, PmType Quantitative ]
                  . position Y [ PRepeat Row, PmType Quantitative ]
                  . color
                      [ MSelectionCondition (SelectionName "myBrush")
                          [ MName "Origin", MmType Nominal ]
                          [ MString "grey" ]
                      ]
  
          spec =
              asSpec
                  [ dataFromUrl "https://vega.github.io/vega-lite/data/cars.json" []
                  , mark Point []
                  , sel []
                  , enc []
                  ]
      in
      toVegaLite
          [ des
          , repeat
              [ RowFields [ "Horsepower", "Acceleration", "Miles_per_Gallon" ]
              , ColumnFields [ "Miles_per_Gallon", "Acceleration", "Horsepower" ]
              ]
          , specification spec
          ]
  
  
  multi4 :: VegaLite
  multi4 =
      let
          des =
              description "A dashboard with cross-highlighting"
  
          selTrans =
              transform
                  . filter (FSelection "myPts")
  
          encPosition =
              encoding
                  . position X [ PName "IMDB_Rating", PmType Quantitative, PBin [ MaxBins 10 ] ]
                  . position Y [ PName "Rotten_Tomatoes_Rating", PmType Quantitative, PBin [ MaxBins 10 ] ]
  
          colLegend = [ LTitle "All Movies"
                      , LDirection Horizontal
                      , LGradientLength 120
                      ]
          enc1 =
              encoding
                  . color [ MAggregate Count, MmType Quantitative, MLegend colLegend ]
  
          -- removed width as not valid in Vega-Lite 4.1.1
          spec1 =
              asSpec [ {- width 300, -} mark Rect [], enc1 [] ]
  
          enc2 =
              encoding
                  . size [ MAggregate Count, MmType Quantitative, MLegend [ LTitle "In Selected Category" ] ]
                  . color [ MString "#666" ]
  
          spec2 =
              asSpec [ selTrans [], mark Point [], enc2 [] ]
  
          heatSpec =
              asSpec [ encPosition [], layer [ spec1, spec2 ] ]
  
          sel =
              selection . select "myPts" Single [ Encodings [ ChX ] ]
  
          barSpec =
              asSpec [ width 330, height 120, mark Bar [], sel [], encBar [] ]
  
          encBar =
              encoding
                  . position X [ PName "Major_Genre", PmType Nominal, PAxis [ AxLabelAngle (-40) ] ]
                  . position Y [ PAggregate Count, PmType Quantitative ]
                  . color
                      [ MSelectionCondition (SelectionName "myPts")
                          [ MString "steelblue" ]
                          [ MString "grey" ]
                      ]
  
          config =
              configure . configuration (RangeStyle [ RHeatmap "greenblue" ])
  
          res =
              resolve
                  . resolution (RLegend [ ( ChColor, Independent ), ( ChSize, Independent ) ])
      in
      toVegaLite
          [ des
          , dataFromUrl "https://vega.github.io/vega-lite/data/movies.json" []
          , vConcat [ heatSpec, barSpec ]
          , res []
          , config []
          ]
  
  
  multi5 :: VegaLite
  multi5 =
      let
          des =
              description "A dashboard with cross-highlighting"
  
          spec1 =
              asSpec
                  [ width 600, height 300, mark Point [], sel1 [], trans1 [], enc1 [] ]
  
          sel1 =
              selection . select "myBrush" Interval [ Encodings [ ChX ] ]
  
          trans1 =
              transform . filter (FSelection "myClick")
  
          weatherColors =
              categoricalDomainMap
                  [ ( "sun", "#e7ba52" )
                  , ( "fog", "#c7c7c7" )
                  , ( "drizzle", "#aec7ea" )
                  , ( "rain", "#1f77b4" )
                  , ( "snow", "#9467bd" )
                  ]
  
          enc1 =
              encoding
                  . position X
                      [ PName "date"
                      , PmType Temporal
                      , PTimeUnit (TU MonthDate)
                      , PAxis [ AxTitle "Date", AxFormat "%b" ]
                      ]
                  . position Y
                      [ PName "temp_max"
                      , PmType Quantitative
                      , PScale [ SDomain (DNumbers [ -5, 40 ]) ]
                      , PAxis [ AxTitle "Maximum Daily Temperature (C)" ]
                      ]
                  . color
                      [ MSelectionCondition (SelectionName "myBrush")
                          [ MName "weather"
                          , MTitle "Weather"
                          , MmType Nominal
                          , MScale weatherColors
                          ]
                          [ MString "#cfdebe" ]
                      ]
                  . size
                      [ MName "precipitation"
                      , MmType Quantitative
                      , MScale [ SDomain (DNumbers [ -1, 50 ]) ]
                      ]
  
          spec2 =
              asSpec [ width 600, mark Bar [], sel2 [], trans2 [], enc2 [] ]
  
          sel2 =
              selection . select "myClick" Multi [ Encodings [ ChColor ] ]
  
          trans2 =
              transform . filter (FSelection "myBrush")
  
          enc2 =
              encoding
                  . position X [ PAggregate Count, PmType Quantitative ]
                  . position Y [ PName "weather", PmType Nominal ]
                  . color
                      [ MSelectionCondition (SelectionName "myClick")
                          [ MName "weather"
                          , MmType Nominal
                          , MScale weatherColors
                          ]
                          [ MString "#acbf98" ]
                      ]
      in
      toVegaLite
          [ title "Seattle Weather, 2012-2015" []
          , des
          , dataFromUrl "https://vega.github.io/vega-lite/data/seattle-weather.csv" []
          , vConcat [ spec1, spec2 ]
          ]
  
  
  multi6 :: VegaLite
  multi6 =
      let
          desc =
              description "Drag a rectangular brush to show (first 20) selected points in a table."
  
          dvals =
              dataFromUrl "https://vega.github.io/vega-lite/data/cars.json"
  
          trans =
              transform
                  . window [ ( [ WOp RowNumber ], "rowNumber" ) ] []
  
          sel =
              selection
                  . select "brush" Interval []
  
          encPoint =
              encoding
                  . position X [ PName "Horsepower", PmType Quantitative ]
                  . position Y [ PName "Miles_per_Gallon", PmType Quantitative ]
                  . color
                      [ MSelectionCondition (SelectionName "brush")
                          [ MName "Cylinders", MmType Ordinal ]
                          [ MString "grey" ]
                      ]
  
          specPoint =
              asSpec [ sel [], mark Point [], encPoint [] ]
  
          tableTrans =
              transform
                  . filter (FSelection "brush")
                  . window [ ( [ WOp Rank ], "rank" ) ] []
                  . filter (FLessThan "rank" (Number 20))
  
          encHPText =
              encoding
                  . position Y [ PName "rowNumber", PmType Ordinal, PAxis [] ]
                  . text [ TName "Horsepower", TmType Nominal ]
  
          specHPText =
              asSpec [ title "Engine power" [], tableTrans [], mark Text [], encHPText [] ]
  
          encMPGText =
              encoding
                  . position Y [ PName "rowNumber", PmType Ordinal, PAxis [] ]
                  . text [ TName "Miles_per_Gallon", TmType Nominal ]
  
          specMPGText =
              asSpec [ title "Efficiency (mpg)" [], tableTrans [], mark Text [], encMPGText [] ]
  
          encOriginText =
              encoding
                  . position Y [ PName "rowNumber", PmType Ordinal, PAxis [] ]
                  . text [ TName "Origin", TmType Nominal ]
  
          specOriginText =
              asSpec [ title "Country of origin" [], tableTrans [], mark Text [], encOriginText [] ]
  
          res =
              resolve
                  . resolution (RLegend [ ( ChColor, Independent ) ])
  
          cfg =
              configure
                  . configuration (ViewStyle [ ViewNoStroke ])
      in
      toVegaLite
          [ desc, cfg [], dvals [], trans [], res [], hConcat [ specPoint, specHPText, specMPGText, specOriginText ] ]
  
  
  multi7 :: VegaLite
  multi7 =
    let des = description "One dot per airport in the US overlayed on geoshape"
  
        cfg = configure
              . configuration (ViewStyle [ ViewNoStroke ])
  
        backdropSpec =
          asSpec
          [ dataFromUrl "https://vega.github.io/vega-lite/data/us-10m.json" [ TopojsonFeature "states" ]
          , mark Geoshape [ MFill "#ddd", MStroke "#fff" ]
          ]
  
        airportData =
          dataFromUrl "https://vega.github.io/vega-lite/data/airports.csv" []
        flightData =
          dataFromUrl "https://vega.github.io/vega-lite/data/flights-airport.csv" []
  
        lineTrans =
          transform
          . filter (FSelection "mySelection")
          . lookup "origin" airportData "iata" (LuAs "o")
          . lookup "destination" airportData "iata" (LuAs "d")
  
        lineEnc =
          encoding
          . position Longitude [ PName "o.longitude", PmType Quantitative ]
          . position Latitude [ PName "o.latitude", PmType Quantitative ]
          . position Longitude2 [ PName "d.longitude" ]
          . position Latitude2 [ PName "d.latitude" ]
  
        lineSpec =
          asSpec
          [ flightData
          , lineTrans []
          , lineEnc []
          , mark Rule [ MColor "black", MOpacity 0.35 ]
          ]
  
        airportTrans =
          transform
          . aggregate [ opAs Count "" "routes" ] [ "origin" ]
          . lookup "origin" airportData "iata"
                (LuFields [ "name", "state", "latitude", "longitude" ])
          . filter (FExpr "datum.state !== 'PR' && datum.state !== 'VI'")
  
        airportEnc =
          encoding
          . position Longitude [ PName "longitude", PmType Quantitative ]
          . position Latitude [ PName "latitude", PmType Quantitative ]
          . size [ MName "routes", MmType Quantitative, MScale [ SRange (RNumbers [ 0, 1000 ]) ], MLegend [] ]
          . order [ OName "routes", OmType Quantitative, OSort [ Descending ] ]
          . tooltip [ TName "name", TmType Nominal ]
  
        sel =
          selection
          . select "mySelection" Single [ On "mouseover", Nearest True, Empty, Fields [ "origin" ] ]
  
        airportSpec =
          asSpec
          [ flightData
          , airportTrans []
          , sel []
          , mark Circle []
          , airportEnc []
          ]
  
    in toVegaLite
          [ des
          , cfg []
          , width 900
          , height 500
          , projection [ PrType AlbersUsa ]
          , layer [ backdropSpec, lineSpec, airportSpec ]
          ]
  
  
  multi8 :: VegaLite
  multi8 =
    let dvals = dataFromUrl "https://vega.github.io/vega-lite/data/flights-5k.json"
                [ Parse [ ( "date", FoDate "" ) ] ]
  
        trans = transform
                . calculateAs "hours(datum.date) + minutes(datum.date) / 60" "time"
        sel = selection
              . select "brush" Interval [ Encodings [ ChX ]
                                        , SInitInterval
                                          (Just (Number 6, Number 12))
                                          Nothing
                                        ]
  
        enc1 = encoding
               . position X [ PName "time"
                            , PBin [ MaxBins 30 ]
                            , PmType Quantitative ]
               . position Y [ PAggregate Count, PmType Quantitative ]
        spec1 = asSpec [ width 963, height 100, sel [], enc1 [], mark Bar [] ]
  
        enc2 = encoding
               . position X [ PName "time"
                            , PBin [ MaxBins 30, SelectionExtent "brush" ]
                            , PmType Quantitative ]
               . position Y [ PAggregate Count, PmType Quantitative ]
        spec2 = asSpec [ width 963, height 100, enc2 [], mark Bar [] ]
  
    in toVegaLite [ dvals, trans [], vConcat [ spec1, spec2 ] ]
  
  
  -- interval selection in one plot to zoom in in second plot.
  --
  selectAndZoom :: VegaLite
  selectAndZoom =
    let plot1 = asSpec [ encoding
                         . position X [ PName "theta", PmType Quantitative, PAxis [] ]
                         . position Y [ PName "y", PmType Quantitative, PAxis [] ]
                         $ []
                       , mark Line []
                       , selection
                         . select "brush" Interval [ Encodings [ChX, ChY]
                                                   , SInitInterval (Just xr) (Just yr)
                                                   ]
                         $ []
                       ]
  
        xr = (Number 0.2, Number 6)
        yr = (Number (-0.8), Number 0.8)
  
        xscale = [ SDomainOpt (DSelectionField "brush" "theta") ]
        yscale = [ SDomainOpt (DSelectionChannel "brush" ChY) ]
  
        plot2 = asSpec [ encoding
                         . position X [ PName "theta", PmType Quantitative, PScale xscale ]
                         . position Y [ PName "y", PmType Quantitative, PScale yscale ]
                         $ []
                       , mark Circle []
                       ]
  
    in toVegaLite [ dataSequenceAs 0 6.28 0.1 "theta"
                  , transform
                    . calculateAs "cos(datum.theta)" "y"
                    $ []
                  , vConcat [plot1, plot2]
                  ]
  