Source: plot.js

class VegaPlotter {
    /**
     * Class for plotting with VegaLite
     * @param {*} patchManager
     * @param {*} onclick
     */
    constructor(patchManager, onclick) {
        this.onclick = onclick;
        this.patchManager = patchManager;
        // Flatten data to a list of datapoints
        this.data = [];
        for (const patch of patchManager.patches.values()) {
            for (const cohort of patch.cohorts.values()) {
                for (const [year, data] of cohort.timeSteps.entries()) {
                    const d = {
                        ...data,
                        ...patchManager.yearData.get(year),
                        positions: undefined
                    };
                    // Convert to date
                    d.Date = new Date(d.Year, 0, 1);
                    this.data.push(d);
                }
            }
        }
    }

    /**
     * Plot cohort values over time
     * @param {*} yField Value to show on the y-axis
     * @param {*} aggregate Optional aggregation (average, median, max, min, or sum)
     * @param {*} colorField Value to use for grouping
     */
    timePlot(yField="Height", aggregate="average", colorField="PID") {
        // Assign the specification to a local variable vlSpec.
        const vlSpec = {
            $schema: "https://vega.github.io/schema/vega-lite/v5.json",
            data: {
                values: this.data
            },
            width: "container", height: 150,
            encoding: {
                x: {
                    field: "Date",
                    type: "temporal",
                    axis: {
                        format: "%Y",
                        title: ""
                    }
                }
            },
            layer: [
                {
                    mark: "line",
                    encoding: {
                        y: {
                            aggregate: aggregate,
                            field: yField,
                            type: "quantitative"
                        },
                        color: {field: colorField, type: "nominal"},
                        tooltip: [
                            {aggregate: aggregate,
                                field: yField,
                                type: "quantitative",
                            },
                            {field: "Date",  type: "temporal", axis: {format: "%Y"}},
                            {field: colorField, type: "nominal"}
                        ],
                    }
                },
                {
                    params: [{
                        name: "index",
                        value: [{x: {year: Math.min(...this.patchManager.years)}}],
                        select: {
                            type: "point",
                            encodings: ["x"],
                            on: "click",
                            nearest: true
                        }
                    }],
                    mark: {type: "point"},
                    encoding: {
                        y: {field: yField, type: "quantitative"},
                        opacity: {value: 0}
                    }
                },
                {
                    transform: [{filter: {and: ["index.Date", {param: "index"}]}}],
                    mark: "rule",
                },
                {
                    transform: [{filter: {and: ["index.Date", {param: "index"}]}}],
                    mark: "text",
                    encoding: {
                        y: {"value": 10},
                        text: {field: "Date", type: "temporal", axis: {format: "%Y"}, fontSize: 30}
                    }
                }
            ],
            config: {text: {align: "right", dx: -5, dy: 5}}
        };

        // Embed the visualization in the container with id `plot`
        // eslint-disable-next-line no-undef
        vegaEmbed("#plot", vlSpec).then(result => {
            result.view.addEventListener("click", (event, item) => {
                this.onclick(item.datum.datum.Year);
            });
        });
    }
}

export {VegaPlotter};