Elm Line Charts Part III: Lines and the Chart

This is the last installment of a series describing how to configure an Elm LineChart. In the previous post I used a viewmodel to configure an axis, so this post will cover how to use lists of those viewmodels to plot the rest of the chart.

Converting to the ViewModel

I want this line chart to have three lines based on my ChartModel from the previous post, and I know I'm starting with a model that has a list of Hospitalizations, so I'll start with ways to convert between the two.

icuBeds: List Hospitalization -> List ChartModel
icuBeds days =
    List.map (\d -> d.icuBedsTotal/d.icuBedsTotalCapacity
                    |> \ratio -> ratio * 100
                    |> ChartModel  d.date)
                  days

nonIcuBeds: List Hospitalization -> List ChartModel
nonIcuBeds days =
    List.map (\d -> d.acuteNonIcuBedsTotal/d.acuteNonIcuBedsTotalCapacity
                  |> \ratio -> ratio * 100
                  |> ChartModel d.date
             )
        days

ventilators : List Hospitalization -> List ChartModel
ventilators days =
    List.map (\d -> d.ventilatorsTotal/d.ventilatorsTotalCapacity
                    |> \ratio -> ratio * 100
                    |> ChartModel d.date)
                  days

All I'm doing here is taking different fields from Hospitalization, converting to a percent, and piping out to a ChartModel. I've configured this for each of the three percentages I want on my chart.

Draw the Rest of the Owl

I'm happy with the rest of the defaults and they don't generaly need a ton of explanation, so I'm just going to dump this pile of code unceremoniously here so that I can paste it someplace else when I need it.

chart : Time.Zone -> List Hospitalization -> Html Msg
chart zone days =
    LineChart.viewCustom
        { x = xAxisConfig zone
        , y = Axis.default 400 "Volume" .val
        , area = Area.default
        , container = Container.default "hospitalization-raw-chart"
        , interpolation = Interpolation.default
        , intersection = Intersection.default
        , legends = Legends.default
        , events = Events.default
        , junk = Junk.default
        , grid = Grid.default
        , line = Line.default
        , dots = Dots.default
        }
        [ LineChart.line Colors.blue Dots.none "ICU Beds" (icuBeds days)
        , LineChart.line Colors.purple Dots.none "Acute Non-ICU Beds"
            (nonIcuBeds days)
        , LineChart.line Colors.red Dots.none "Ventilators" (ventilators days)
        ]

As you can see you plug in your time zone and some default values and a list of lines based on the functions defined above and give it a good stir.

In all seriousness, the important thing here is to use viewCustom rather than fiddle with making the numbered signatures work. (One thing I absolutely do not understand is the way that Elm deals with parametric polymorphism by putting numbers in the signatures. Elm, you are flawed and I love you anyway.)