All files / owid-grapher/grapher/stackedCharts StackedUtils.ts

100% Statements 41/41
100% Branches 17/17
100% Functions 2/2
100% Lines 41/41

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 531x 1x 1x 1x 1x 1x 1x 20x 20x 40x 20x 73x 73x 73x 73x 73x 20x 20x 20x 1x 1x 1x 1x 1x 1x 20x 20x 20x 20x 20x 20x 20x 20x 20x 40x 40x 40x 40x 146x 146x 146x                        
import { flatten, keyBy, sortNumeric, uniq } from "../../clientUtils/Util"
import { StackedPointPositionType, StackedSeries } from "./StackedConstants"
 
// This method shift up the Y Values of a Series with Points in place.
// Todo: use a lib?
export const stackSeries = <PositionType extends StackedPointPositionType>(
    seriesArr: readonly StackedSeries<PositionType>[]
): readonly StackedSeries<PositionType>[] => {
    seriesArr.forEach((series, seriesIndex) => {
        if (!seriesIndex) return // The first series does not need to be shifted
        series.points.forEach((point, pointIndex) => {
            const pointBelowThisOne =
                seriesArr[seriesIndex - 1].points[pointIndex]
            point.valueOffset =
                pointBelowThisOne.value + pointBelowThisOne.valueOffset
        })
    })
    return seriesArr
}
 
// Adds a Y = 0 value for each missing x value (where X is usually Time)
export const withMissingValuesAsZeroes = <
    PositionType extends StackedPointPositionType
>(
    seriesArr: readonly StackedSeries<PositionType>[]
): StackedSeries<PositionType>[] => {
    const allXValuesSorted = sortNumeric(
        uniq(
            flatten(seriesArr.map((series) => series.points)).map(
                (point) => point.position
            )
        )
    )
    return seriesArr.map((series) => {
        const pointsByPosition = keyBy(series.points, "position")
        return {
            ...series,
            points: allXValuesSorted.map((position) => {
                const point = pointsByPosition[position]
                const value = point?.value ?? 0
                const time = point?.time ?? 0
                return {
                    time,
                    position,
                    value,
                    valueOffset: 0,
                    fake: !point,
                }
            }),
        }
    })
}