import type { SignalRow, ChartConfig, 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) => { const m = seriesMap.get(k); return m ? [...m.keys()] : []; }), ), ].sort((a, b) => a - b); const data = keys.map((k) => { const m = seriesMap.get(k); return m ? allXs.map((x) => m.get(x)) : []; // undefined = gap }); return { keys, allXs, data }; }