Skip to content

Commit

Permalink
Moved age groups timeline rendering to a common module (#770)
Browse files Browse the repository at this point in the history
  • Loading branch information
breki committed Dec 24, 2020
1 parent b7d2fae commit 01c8a80
Show file tree
Hide file tree
Showing 4 changed files with 99 additions and 98 deletions.
55 changes: 2 additions & 53 deletions src/visualizations/AgeGroupsTimelineViz/Rendering.fs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
[<RequireQualifiedAccess>]
module AgeGroupsTimelineViz.Rendering

open System
open DataAnalysis.DatedTypes
open DataAnalysis.AgeGroupsTimeline
open DataVisualization.ChartingTypes
open Synthesis
Expand Down Expand Up @@ -43,58 +41,9 @@ let update (msg: Msg) (state: State) : State * Cmd<Msg> =
{ state with RangeSelectionButtonIndex = buttonIndex }, Cmd.none

let renderChartOptions state dispatch =

// map state data into a list needed for calculateCasesByAgeTimeline
let totalCasesByAgeGroupsList =
state.Data
|> List.map (fun point -> (point.Date, point.StatePerAgeToDate))

let totalCasesByAgeGroups =
mapDateTuplesListToArray totalCasesByAgeGroupsList

// calculate complete merged timeline
let timeline = calculateCasesByAgeTimeline totalCasesByAgeGroups

// get keys of all age groups
let allGroupsKeys = listAgeGroups timeline

let mapPoint
(startDate: DateTime)
(daysFromStartDate: int)
(cases: CasesInAgeGroupForDay) =
let date = startDate |> Days.add daysFromStartDate

pojo {|
x = date |> jsTime12h :> obj
y = cases
date = I18N.tOptions "days.longerDate" {| date = date |}
|}

let mapAllPoints (groupTimeline: CasesInAgeGroupTimeline) =
let startDate = groupTimeline.StartDate
let timelineArray = groupTimeline.Data

timelineArray
|> Array.mapi (fun i cases -> mapPoint startDate i cases)

// generate all series
let allSeries =
allGroupsKeys
|> List.mapi (fun index ageGroupKey ->
let points =
timeline
|> extractTimelineForAgeGroup
ageGroupKey state.Metrics.MetricsType
|> mapAllPoints

pojo {|
visible = true
name = ageGroupKey.Label
color = AgeGroup.ColorOfAgeGroup index
data = points
|}
)
|> List.toArray
getAgeGroupTimelineAllSeriesData
state.Data state.Metrics.CasesMetricsType

let onRangeSelectorButtonClick(buttonIndex: int) =
let res (_ : Event) =
Expand Down
49 changes: 5 additions & 44 deletions src/visualizations/AgeGroupsTimelineViz/Synthesis.fs
Original file line number Diff line number Diff line change
@@ -1,68 +1,29 @@
module AgeGroupsTimelineViz.Synthesis

open DataAnalysis.AgeGroupsTimeline
open DataAnalysis.DatedTypes
open DataVisualization.ChartingTypes
open Types
open System.Collections.Generic
open System.Text
open Fable.Core
open JsInterop

type CasesInAgeGroupForDay = int
type CasesInAgeGroupTimeline = DatedArray<CasesInAgeGroupForDay>
type CasesInAgeGroupSeries = {
AgeGroupKey: AgeGroupKey
Timeline: CasesInAgeGroupTimeline
}

type AllCasesInAgeGroupSeries = IDictionary<AgeGroupKey, CasesInAgeGroupSeries>


type DisplayMetricsType = NewCases | ActiveCases
type DisplayMetrics = {
Id: string
MetricsType: DisplayMetricsType
CasesMetricsType: CasesMetricsType
ChartType: ChartType
}

let availableDisplayMetrics = [|
{ Id = "newCases"; MetricsType = NewCases
{ Id = "newCases"; CasesMetricsType = NewCases
ChartType = StackedBarNormal }
{ Id = "newCasesRelative"; MetricsType = NewCases
{ Id = "newCasesRelative"; CasesMetricsType = NewCases
ChartType = StackedBarPercent }
{ Id = "activeCases"; MetricsType = ActiveCases
{ Id = "activeCases"; CasesMetricsType = ActiveCases
ChartType = StackedBarNormal }
{ Id = "activeCasesRelative"; MetricsType = ActiveCases
{ Id = "activeCasesRelative"; CasesMetricsType = ActiveCases
ChartType = StackedBarPercent }
|]

let listAgeGroups (timeline: CasesByAgeGroupsTimeline): AgeGroupKey list =
timeline.Data.[0]
|> List.map (fun group -> group.GroupKey)
|> List.sortBy (fun groupKey -> groupKey.AgeFrom)

let extractTimelineForAgeGroup
ageGroupKey
(metricsType: DisplayMetricsType)
(casesTimeline: CasesByAgeGroupsTimeline)
: CasesInAgeGroupTimeline =

let newCasesTimeline =
casesTimeline
|> mapDatedArrayItems (fun dayGroupsData ->
let dataForGroup =
dayGroupsData
|> List.find(fun group -> group.GroupKey = ageGroupKey)
dataForGroup.All
|> Utils.optionToInt
)
match metricsType with
| NewCases -> newCasesTimeline
| ActiveCases ->
newCasesTimeline
|> mapDatedArray (Statistics.calculateWindowedSumInt 14)

let tooltipFormatter jsThis =
let points: obj[] = jsThis?points

Expand Down
88 changes: 88 additions & 0 deletions src/visualizations/DataAnalysis/AgeGroupsTimeline.fs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
module DataAnalysis.AgeGroupsTimeline

open System
open System.Collections.Generic
open DataAnalysis.DatedTypes
open Types
open Highcharts

type CasesByAgeGroupsForDay = AgeGroupsList

Expand Down Expand Up @@ -86,3 +88,89 @@ let calculateCasesByAgeTimeline
}
// skip initial and trailing days without any cases
|> trimDatedArray thereAreNoCases

let listAgeGroups (timeline: CasesByAgeGroupsTimeline): AgeGroupKey list =
timeline.Data.[0]
|> List.map (fun group -> group.GroupKey)
|> List.sortBy (fun groupKey -> groupKey.AgeFrom)

type CasesInAgeGroupForDay = int
type CasesInAgeGroupTimeline = DatedArray<CasesInAgeGroupForDay>
type CasesInAgeGroupSeries = {
AgeGroupKey: AgeGroupKey
Timeline: CasesInAgeGroupTimeline
}

type CasesMetricsType = NewCases | ActiveCases

let extractTimelineForAgeGroup
ageGroupKey
(casesMetricsType: CasesMetricsType)
(casesTimeline: CasesByAgeGroupsTimeline)
: CasesInAgeGroupTimeline =

let newCasesTimeline =
casesTimeline
|> mapDatedArrayItems (fun dayGroupsData ->
let dataForGroup =
dayGroupsData
|> List.find(fun group -> group.GroupKey = ageGroupKey)
dataForGroup.All
|> Utils.optionToInt
)
match casesMetricsType with
| NewCases -> newCasesTimeline
| ActiveCases ->
newCasesTimeline
|> mapDatedArray (Statistics.calculateWindowedSumInt 14)

let getAgeGroupTimelineAllSeriesData
(statsData: StatsData)
(casesMetricsType: CasesMetricsType) =
let totalCasesByAgeGroupsList =
statsData
|> List.map (fun point -> (point.Date, point.StatePerAgeToDate))

let totalCasesByAgeGroups =
mapDateTuplesListToArray totalCasesByAgeGroupsList

// calculate complete merged timeline
let timeline = calculateCasesByAgeTimeline totalCasesByAgeGroups

// get keys of all age groups
let allGroupsKeys = listAgeGroups timeline

let mapPoint
(startDate: DateTime)
(daysFromStartDate: int)
(cases: CasesInAgeGroupForDay) =
let date = startDate |> Days.add daysFromStartDate

pojo {|
x = date |> jsTime12h :> obj
y = cases
date = I18N.tOptions "days.longerDate" {| date = date |}
|}

let mapAllPoints (groupTimeline: CasesInAgeGroupTimeline) =
let startDate = groupTimeline.StartDate
let timelineArray = groupTimeline.Data

timelineArray
|> Array.mapi (fun i cases -> mapPoint startDate i cases)

allGroupsKeys
|> List.mapi (fun index ageGroupKey ->
let points =
timeline
|> extractTimelineForAgeGroup ageGroupKey casesMetricsType
|> mapAllPoints

pojo {|
visible = true
name = ageGroupKey.Label
color = AgeGroup.ColorOfAgeGroup index
data = points
|}
)
|> List.toArray
5 changes: 4 additions & 1 deletion src/visualizations/DeceasedViz/Synthesis.fs
Original file line number Diff line number Diff line change
Expand Up @@ -130,8 +130,11 @@ let renderAllHospitalSeriesData state =

hospitalSeries |> Array.map renderSeriesData

let renderAllAgeGroupsSeriesData state =
invalidOp "todo"

let renderAllSeriesData state =
match state.Page.MetricsType with
| HospitalMetricsType -> renderAllHospitalSeriesData state
| AgeGroupsMetricsType -> invalidOp "todo"
| AgeGroupsMetricsType -> renderAllAgeGroupsSeriesData state
| _ -> invalidOp "todo"

0 comments on commit 01c8a80

Please sign in to comment.