summaryrefslogtreecommitdiff
path: root/web-timeplot/src/data/parse-replay-csv.js
diff options
context:
space:
mode:
authorgrothedev <grothedev@gmail.com>2026-05-29 21:49:20 -0400
committergrothedev <grothedev@gmail.com>2026-05-29 21:49:20 -0400
commit6196004b51a6850909c154f5402ff4858eab479a (patch)
tree126b8bb1600d0a656e0df016e25d08c390f3540e /web-timeplot/src/data/parse-replay-csv.js
parent27dc5849c3eaf4824d79938e7077abdbe2c82e24 (diff)
mv web stuff to root project dirHEADprototypeframeworkmain
Diffstat (limited to 'web-timeplot/src/data/parse-replay-csv.js')
-rw-r--r--web-timeplot/src/data/parse-replay-csv.js108
1 files changed, 0 insertions, 108 deletions
diff --git a/web-timeplot/src/data/parse-replay-csv.js b/web-timeplot/src/data/parse-replay-csv.js
deleted file mode 100644
index b6ce97a..0000000
--- a/web-timeplot/src/data/parse-replay-csv.js
+++ /dev/null
@@ -1,108 +0,0 @@
-function splitRow(line) {
- return line.split(/[;,\t]/).map((value) => value.trim());
-}
-
-function isNumeric(value) {
- return value !== '' && Number.isFinite(Number(value));
-}
-
-function detectHeader(rows) {
- if (rows.length === 0) {
- return { hasHeader: false, headers: [] };
- }
-
- const [firstRow] = rows;
- const hasHeader = firstRow.some((value) => !isNumeric(value));
- return {
- hasHeader,
- headers: hasHeader ? firstRow.map((value) => value.toLowerCase()) : [],
- };
-}
-
-function detectTimeScale(headers) {
- const timeHeader = headers.find((header) => header.includes('time') || header.includes('timestamp'));
- if (!timeHeader) {
- return 1;
- }
-
- if (timeHeader.includes('sec') && !timeHeader.includes('msec') && !timeHeader.includes('ms')) {
- return 1000;
- }
-
- return 1;
-}
-
-function detectColumnIndexes(headers, columnCount) {
- if (headers.length === 0) {
- return {
- timeIndex: columnCount > 1 ? 0 : -1,
- valueIndex: columnCount > 1 ? 1 : 0,
- };
- }
-
- const timeIndex = headers.findIndex((header) => header.includes('time') || header.includes('timestamp'));
- const valueIndex = headers.findIndex((header) => header.includes('value') || header.includes('signal') || header.includes('y'));
-
- return {
- timeIndex,
- valueIndex: valueIndex >= 0 ? valueIndex : (headers.length > 1 ? 1 : 0),
- };
-}
-
-export function parseReplayCsv(text, { sampleRateHz = 60 } = {}) {
- const rows = text
- .split(/\r?\n/)
- .map((line) => line.trim())
- .filter((line) => line && !line.startsWith('#'))
- .map(splitRow)
- .filter((row) => row.some((value) => value !== ''));
-
- if (rows.length === 0) {
- throw new Error('CSV file is empty');
- }
-
- const { hasHeader, headers } = detectHeader(rows);
- const dataRows = hasHeader ? rows.slice(1) : rows;
- const columnCount = rows[0].length;
- const { timeIndex, valueIndex } = detectColumnIndexes(headers, columnCount);
- const timeScale = detectTimeScale(headers);
- const intervalMs = 1000 / Math.max(1, sampleRateHz);
-
- const points = dataRows
- .map((row, index) => {
- const rawValue = row[valueIndex];
- if (!isNumeric(rawValue)) {
- return null;
- }
-
- const parsedValue = Number(rawValue);
- const parsedTime = timeIndex >= 0 && isNumeric(row[timeIndex])
- ? Number(row[timeIndex]) * timeScale
- : index * intervalMs;
-
- return {
- timeMs: parsedTime,
- value: parsedValue,
- };
- })
- .filter(Boolean)
- .sort((left, right) => left.timeMs - right.timeMs);
-
- if (points.length === 0) {
- throw new Error('CSV file did not contain any numeric data points');
- }
-
- const firstTime = points[0].timeMs;
- const normalizedPoints = points.map((point) => ({
- timeMs: point.timeMs - firstTime,
- value: point.value,
- }));
-
- return {
- points: normalizedPoints,
- metadata: {
- pointCount: normalizedPoints.length,
- durationMs: normalizedPoints.at(-1)?.timeMs ?? 0,
- },
- };
-}