Spaces:
Running
Running
| /** | |
| * Utility to export the current project state to a CSV file. | |
| * Synchronized with the StreamDataTable and ActionBar. | |
| */ | |
| import type { ProjectState } from '../types/project'; | |
| import { extractStreamInfo } from './streamInfo'; | |
| export function exportProjectToCsv(state: ProjectState) { | |
| const rows: string[][] = []; | |
| const header = [ | |
| 'Process', | |
| 'Subprocess', | |
| 'Stream Name', | |
| 'Type', | |
| 'Tin', | |
| 'Tout', | |
| 'ṁ', | |
| 'cp', | |
| 'CP', | |
| 'Q (kW)', | |
| 'Lat', | |
| 'Lon', | |
| 'Hours', | |
| 'Water In', | |
| 'Water Out', | |
| 'Density', | |
| 'Pressure', | |
| 'Notes', | |
| ]; | |
| rows.push(header); | |
| (state.proc_groups || []).forEach((subIdxs, gIdx) => { | |
| const gName = state.proc_group_names?.[gIdx] || `Process ${gIdx + 1}`; | |
| const gCoord = state.proc_group_coordinates?.[gIdx] || {}; | |
| subIdxs.forEach((si) => { | |
| const sub = state.processes[si]; | |
| if (!sub) return; | |
| const notes = sub.extra_info?.notes || ''; | |
| const lat = String(sub.lat || gCoord.lat || ''); | |
| const lon = String(sub.lon || gCoord.lon || ''); | |
| const hours = sub.hours || gCoord.hours || ''; | |
| const water_in = sub.extra_info?.water_content_in || ''; | |
| const water_out = sub.extra_info?.water_content_out || ''; | |
| const density = sub.extra_info?.density || ''; | |
| const pressure = sub.extra_info?.pressure || ''; | |
| // Add streams for this subprocess | |
| if (!sub.streams?.length && !sub.children?.length) { | |
| rows.push([gName, sub.name, '', '', '', '', '', '', '', '', lat, lon, hours, water_in, water_out, density, pressure, notes]); | |
| } else { | |
| (sub.streams || []).forEach((s) => { | |
| const si = extractStreamInfo(s as any); | |
| rows.push([ | |
| gName, | |
| sub.name, | |
| s.name, | |
| si.type || '', | |
| String(si.tin ?? ''), | |
| String(si.tout ?? ''), | |
| String(si.mdot ?? ''), | |
| String(si.cp ?? ''), | |
| String(si.CP ?? ''), | |
| si.Q ? si.Q.toFixed(1) : '', | |
| lat, | |
| lon, | |
| hours, | |
| String(si.water_in || water_in), | |
| String(si.water_out || water_out), | |
| String(si.density || density), | |
| String(si.pressure || pressure), | |
| notes, | |
| ]); | |
| }); | |
| // Also add streams for sub-subprocesses (children) | |
| (sub.children || []).forEach((child) => { | |
| const c_notes = child.extra_info?.notes || notes || ''; | |
| const c_lat = String(child.lat || sub.lat || gCoord.lat || ''); | |
| const c_lon = String(child.lon || sub.lon || gCoord.lon || ''); | |
| const c_hours = child.hours || hours || ''; | |
| const c_water_in = child.extra_info?.water_content_in || water_in || ''; | |
| const c_water_out = child.extra_info?.water_content_out || water_out || ''; | |
| const c_density = child.extra_info?.density || density || ''; | |
| const c_pressure = child.extra_info?.pressure || pressure || ''; | |
| const c_name = `${sub.name} › ${child.name}`; | |
| if (!(child.streams || []).length) { | |
| rows.push([gName, c_name, '', '', '', '', '', '', '', '', c_lat, c_lon, c_hours, c_water_in, c_water_out, c_density, c_pressure, c_notes]); | |
| } else { | |
| (child.streams || []).forEach((s) => { | |
| const si = extractStreamInfo(s as any); | |
| rows.push([ | |
| gName, | |
| c_name, | |
| s.name, | |
| si.type || '', | |
| String(si.tin ?? ''), | |
| String(si.tout ?? ''), | |
| String(si.mdot ?? ''), | |
| String(si.cp ?? ''), | |
| String(si.CP ?? ''), | |
| si.Q ? si.Q.toFixed(1) : '', | |
| c_lat, | |
| c_lon, | |
| c_hours, | |
| String(si.water_in || c_water_in), | |
| String(si.water_out || c_water_out), | |
| String(si.density || c_density), | |
| String(si.pressure || c_pressure), | |
| c_notes, | |
| ]); | |
| }); | |
| } | |
| }); | |
| } | |
| }); | |
| }); | |
| const csv = rows.map((r) => r.map((c) => `"${c}"`).join(',')).join('\n'); | |
| const blob = new Blob([csv], { type: 'text/csv' }); | |
| const url = URL.createObjectURL(blob); | |
| const a = document.createElement('a'); | |
| a.href = url; | |
| a.download = `heattransplan_export_${new Date().toISOString().slice(0, 10)}.csv`; | |
| a.click(); | |
| URL.revokeObjectURL(url); | |
| } | |