1import type { ChartDataset, ChartType } from "chart.js"; 2import type { Data, Series } from "../types/chart.js"; 3import type { Metric, Metrics, Range } from "../types/data.js"; 4 5export interface Mapper<T = number> { 6 rangeLabel: (metric: Metric<unknown>) => string; 7 sampledRanges: (metrics: Metrics<T>) => Record<string, Range>; 8 standard: (value: Metric<T>) => Series[]; 9 sampled: (value: Metric<T[]>, range: Range | null) => Series[]; 10} 11 12/** 13 * Converts `Metrics` to the corresponding chart data structures. 14 */ 15export class ChartDataTransforms { 16 17 static mapToSeries(metrics: Metrics<number>, mapper: Mapper<number>, normalize: boolean = false): Series[] { 18 const series: Series[] = []; 19 const standard = metrics.standard; 20 const sampled = metrics.sampled; 21 // Builds ranges for distribution. 22 let ranges: Record<string, Range> = {}; 23 if (normalize) { 24 ranges = mapper.sampledRanges(metrics); 25 } 26 // Builds series. 27 if (standard) { 28 for (let i = 0; i < standard.length; i += 1) { 29 const metric = standard[i]; 30 const mapped = mapper.standard(metric); 31 series.push(...mapped); 32 } 33 } 34 if (sampled) { 35 for (let i = 0; i < sampled.length; i += 1) { 36 const metric = sampled[i]; 37 const mapped = mapper.sampled(metric, ranges[mapper.rangeLabel(metric)]); 38 series.push(...mapped); 39 } 40 } 41 return series; 42 } 43 44 static mapToDataset(series: Series[]): Data { 45 let xmax = 0; 46 let datasets: ChartDataset[] = []; 47 for (let i = 0; i < series.length; i += 1) { 48 xmax = Math.max(xmax, series[i].data.length); 49 datasets.push(ChartDataTransforms.chartDataset(series[i])); 50 } 51 const chartData: Data = { 52 labels: ChartDataTransforms.xrange(xmax), 53 datasets: datasets 54 }; 55 return chartData; 56 } 57 58 private static chartDataset<T extends ChartType>(series: Series): ChartDataset { 59 return { 60 label: series.descriptiveLabel, 61 type: series.type, 62 data: series.data, 63 ...series.options 64 }; 65 } 66 67 private static xrange(xmax: number): number[] { 68 let range = []; 69 for (let i = 1; i <= xmax; i += 1) { 70 range.push(i); 71 } 72 return range; 73 } 74} 75