import type { SignalRow, ChartConfig } from '@/lib/types'; import type { TimeMode } from '@/lib/types'; const MAX_SERIES = 80; export interface SeriesData { keys: string[]; allXs: number[]; data: (number | undefined)[][]; } export function buildSeriesData( rows: SignalRow[], signalType: ChartConfig['signal_type'], timeMode: TimeMode, ): SeriesData | null { const seriesMap = new Map>(); for (const row of rows) { for (const [sig, val] of [ ['green', row.green], ['red', row.red], ] as ['green' | 'red', number | undefined][]) { if (signalType !== 'both' && signalType !== sig) continue; if (val === undefined) continue; const key = `${row.combinator}::${row.item_key}::${sig}`; const x = timeMode === 'tick' ? parseInt(row.game_tick, 10) : new Date(row.real_time).getTime() / 1000; if (!seriesMap.has(key)) seriesMap.set(key, new Map()); seriesMap.get(key)!.set(x, val); } } if (seriesMap.size === 0) return null; const keys = [...seriesMap.keys()].slice(0, MAX_SERIES); const allXs = [...new Set(keys.flatMap((k) => [...seriesMap.get(k)!.keys()]))].sort( (a, b) => a - b, ); const data = keys.map((k) => { const m = seriesMap.get(k)!; return allXs.map((x) => m.get(x)); // undefined = gap }); return { keys, allXs, data }; }