feat(export): toCSV emits context line + subject group cell

This commit is contained in:
Experiments DB Dev
2026-07-19 13:28:32 -04:00
parent 600323f40a
commit 958666580f
2 changed files with 77 additions and 16 deletions
+28 -5
View File
@@ -206,12 +206,35 @@ function escapeCsvCell(value) {
return /[",\n]/.test(s) ? `"${s.replace(/"/g, '""')}"` : s;
}
// Serialize a matrix to an RFC-4180-ish CSV string (LF line endings).
// First column is the date; remaining columns follow matrix.columns order.
// Serialize a matrix to an RFC-4180-ish CSV string (LF line endings):
// <pinned label>,<pinned value>
// (blank line)
// [Group,<group per subject column>] -- only when groupAxis === 'col'
// <corner>[,Group?],<column headers...>
// <row label>[,group?],<values...>
export function toCSV(matrix) {
const header = ['Date', ...matrix.columns.map((c) => c.header)].map(escapeCsvCell).join(',');
const lines = matrix.rows.map((r) => [r.date, ...r.values].map(escapeCsvCell).join(','));
return [header, ...lines].join('\n');
const lines = [];
lines.push([matrix.context.label, matrix.context.value].map(escapeCsvCell).join(','));
lines.push('');
if (matrix.groupAxis === 'col') {
const groupRow = ['Group', ...matrix.columns.map((c) => c.group ?? '—')];
lines.push(groupRow.map(escapeCsvCell).join(','));
}
const header = matrix.groupAxis === 'row'
? ['Group', matrix.corner, ...matrix.columns.map((c) => c.label)]
: [matrix.corner, ...matrix.columns.map((c) => c.label)];
lines.push(header.map(escapeCsvCell).join(','));
for (const r of matrix.rows) {
const lead = matrix.groupAxis === 'row'
? [r.member.group ?? '—', r.member.label]
: [r.member.label];
lines.push([...lead, ...r.values].map(escapeCsvCell).join(','));
}
return lines.join('\n');
}
// Build a download filename from the experiment title and parameter label.