(rows: Record<string, unknown>[], spec: ChartSpec)
| 258 | } |
| 259 | |
| 260 | function buildHeatmapData(rows: Record<string, unknown>[], spec: ChartSpec): HeatmapChartRenderData { |
| 261 | const xField = spec.encoding.x! |
| 262 | const yField = spec.encoding.y! |
| 263 | const valueField = spec.encoding.value! |
| 264 | const xLabels: string[] = [] |
| 265 | const yLabels: string[] = [] |
| 266 | const xIndex = new Map<string, number>() |
| 267 | const yIndex = new Map<string, number>() |
| 268 | const values = new Map<string, number>() |
| 269 | |
| 270 | for (const row of rows) { |
| 271 | const xLabel = toLabel(row[xField]) |
| 272 | const yLabel = toLabel(row[yField]) |
| 273 | let xi = xIndex.get(xLabel) |
| 274 | if (xi === undefined) { |
| 275 | xi = xLabels.length |
| 276 | xIndex.set(xLabel, xi) |
| 277 | xLabels.push(xLabel) |
| 278 | } |
| 279 | let yi = yIndex.get(yLabel) |
| 280 | if (yi === undefined) { |
| 281 | yi = yLabels.length |
| 282 | yIndex.set(yLabel, yi) |
| 283 | yLabels.push(yLabel) |
| 284 | } |
| 285 | const key = `${xi}:${yi}` |
| 286 | values.set(key, (values.get(key) ?? 0) + toNumber(row[valueField], valueField)) |
| 287 | } |
| 288 | |
| 289 | const data: Array<[number, number, number]> = [] |
| 290 | for (const [key, value] of values.entries()) { |
| 291 | const [x, y] = key.split(':').map(Number) |
| 292 | data.push([x, y, value]) |
| 293 | } |
| 294 | |
| 295 | return { xLabels, yLabels, data } |
| 296 | } |
| 297 | |
| 298 | export function buildChartPayload( |
| 299 | rows: Record<string, unknown>[], |
no test coverage detected