Spaces:
Sleeping
Sleeping
| /** | |
| * Extract stream info (Tin, Tout, mdot, cp, CP, Q) from a stream object, | |
| * checking multiple fallback sources in the same order as the original | |
| * Streamlit app: | |
| * 1. stream_values / product_values dict | |
| * 2. properties/values mapping (prop1→val1 …) | |
| * 3. top-level temp_in / temp_out / mdot / cp | |
| */ | |
| export interface StreamInfo { | |
| tin: number | null; | |
| tout: number | null; | |
| mdot: number | null; | |
| cp: number | null; | |
| CP: number | null; | |
| Q: number | null; | |
| type: 'hot' | 'cold' | null; | |
| density: string | null; | |
| pressure: string | null; | |
| water_in: string | null; | |
| water_out: string | null; | |
| } | |
| function tryFloat(v: unknown): number | null { | |
| if (v == null || v === '') return null; | |
| const n = Number(v); | |
| return isNaN(n) ? null : n; | |
| } | |
| export function extractStreamInfo(stream: Record<string, any>): StreamInfo { | |
| const sv: Record<string, any> = | |
| stream.stream_values || stream.product_values || {}; | |
| const properties: Record<string, string> = stream.properties || {}; | |
| const values: Record<string, string> = stream.values || {}; | |
| let tin: number | null = null; | |
| let tout: number | null = null; | |
| let mdot: number | null = null; | |
| let cpVal: number | null = null; | |
| let cpDirect: number | null = null; | |
| // 1. stream_values | |
| if (sv.Tin != null) tin = tryFloat(sv.Tin); | |
| if (sv.Tout != null) tout = tryFloat(sv.Tout); | |
| if (sv['ṁ'] != null) mdot = tryFloat(sv['ṁ']); | |
| if (sv.cp != null) cpVal = tryFloat(sv.cp); | |
| if (sv.CP != null) cpDirect = tryFloat(sv.CP); | |
| // 2. properties / values mapping (prop1→val1, prop2→val2 …) | |
| for (const [pk, pname] of Object.entries(properties)) { | |
| const vk = pk.replace('prop', 'val'); | |
| const v = values[vk]; | |
| if (!v) continue; | |
| if (pname === 'Tin' && tin == null) tin = tryFloat(v); | |
| else if (pname === 'Tout' && tout == null) tout = tryFloat(v); | |
| else if (pname === 'ṁ' && mdot == null) mdot = tryFloat(v); | |
| else if (pname === 'cp' && cpVal == null) cpVal = tryFloat(v); | |
| else if (pname === 'CP' && cpDirect == null) cpDirect = tryFloat(v); | |
| } | |
| // 3. top-level fallback | |
| if (tin == null) tin = tryFloat(stream.temp_in); | |
| if (tout == null) tout = tryFloat(stream.temp_out); | |
| if (mdot == null) mdot = tryFloat(stream.mdot); | |
| if (cpVal == null) cpVal = tryFloat(stream.cp); | |
| const density = sv.Density || null; | |
| const pressure = sv.Pressure || null; | |
| const water_in = sv['Water Content In'] || null; | |
| const water_out = sv['Water Content Out'] || null; | |
| // Compute CP (heat capacity flow rate) | |
| let CP: number | null = | |
| cpDirect ?? (mdot != null && cpVal != null ? mdot * cpVal : null); | |
| // Compute Q | |
| const Q = | |
| CP != null && tin != null && tout != null | |
| ? Math.abs(CP * (tout - tin)) | |
| : null; | |
| // Stream type | |
| const type: 'hot' | 'cold' | null = | |
| tin != null && tout != null ? (tin > tout ? 'hot' : 'cold') : null; | |
| return { tin, tout, mdot, cp: cpVal, CP, Q, type, density, pressure, water_in, water_out }; | |
| } | |