/** Parsování `planning_run.solver_params` z GET /plan/current (run je celý JSON řádek). */ export type PlanMaskSlot = { allow_charge: boolean allow_discharge_export: boolean } export type PlanSolverSnapshot = { chargeAcquisitionKwh: number | null chargeAcquisitionCutoffAt: string | null masksByIso: Map chargeMaskCount: number exportMaskCount: number } function recordBool(v: unknown): boolean { return v === true } function recordNumber(v: unknown): number | null { if (v == null) return null const n = Number(v) return Number.isFinite(n) ? n : null } function recordString(v: unknown): string | null { return typeof v === 'string' && v.length > 0 ? v : null } export function parsePlanSolverSnapshot( run: Record | null | undefined, ): PlanSolverSnapshot | null { if (run == null) return null const raw = run.solver_params if (raw == null || typeof raw !== 'object') return null const sp = raw as Record const inputs = sp.inputs != null && typeof sp.inputs === 'object' ? (sp.inputs as Record) : null const masksByIso = new Map() const masks = sp.masks if (Array.isArray(masks)) { for (const m of masks) { if (m == null || typeof m !== 'object') continue const row = m as Record const slot = recordString(row.slot) if (slot == null) continue masksByIso.set(slot, { allow_charge: recordBool(row.allow_charge), allow_discharge_export: recordBool(row.allow_discharge_export), }) } } let chargeMaskCount = 0 let exportMaskCount = 0 for (const v of masksByIso.values()) { if (v.allow_charge) chargeMaskCount += 1 if (v.allow_discharge_export) exportMaskCount += 1 } return { chargeAcquisitionKwh: inputs ? recordNumber(inputs.charge_acquisition_buy_czk_kwh) : null, chargeAcquisitionCutoffAt: inputs ? recordString(inputs.charge_acquisition_cutoff_at) : null, masksByIso, chargeMaskCount, exportMaskCount, } } export function maskForInterval( snapshot: PlanSolverSnapshot | null, intervalStartIso: string, ): PlanMaskSlot | null { if (snapshot == null) return null return snapshot.masksByIso.get(intervalStartIso) ?? null }