()
- for (const r of telemetry) map.set(r.slot_start, { ...(map.get(r.slot_start) ?? {}), tel: r })
- for (const r of pvSlots) map.set(r.interval_start, { ...(map.get(r.interval_start) ?? {}), pv: r })
- for (const r of baselineSlots) map.set(r.interval_start, { ...(map.get(r.interval_start) ?? {}), base: r })
+ for (const r of telemetry) {
+ map.set(r.slot_start, { ...(map.get(r.slot_start) ?? {}), tel: r })
+ }
+ for (const r of pvSlots) {
+ map.set(r.interval_start, { ...(map.get(r.interval_start) ?? {}), pv: r })
+ }
+ for (const r of baselineSlots) {
+ map.set(r.interval_start, { ...(map.get(r.interval_start) ?? {}), base: r })
+ }
return map
}, [telemetry, pvSlots, baselineSlots])
@@ -211,8 +220,11 @@ export default function ForecastVsActual() {
byDay.set(day, arr)
}
return [...byDay.entries()]
- .sort((a, b) => a[0].localeCompare(b[0]))
- .map(([day, points]) => ({ day, points }))
+ .sort((a, b) => b[0].localeCompare(a[0]))
+ .map(([day, points]) => ({
+ day,
+ points: points.sort((p, q) => new Date(p.k).getTime() - new Date(q.k).getTime()),
+ }))
}, [byInterval, metric])
const title = metric === 'pv' ? 'FVE (výroba)' : metric === 'load' ? 'Spotřeba (bazál)' : 'Síť (signed)'
@@ -270,6 +282,15 @@ export default function ForecastVsActual() {
)}
+ {siteReady && siteId != null ? (
+
+ Legenda: plná šedá = skutečnost z telemetrie (15m CA),{' '}
+ čárkovaná žlutá = předpověď (FVE: Open‑Meteo/pvlib; spotřeba: baseline
+ z historie), tečkovaná světlá = korigovaná FVE (delta profil z historie).
+ U sítě zatím nemáme samostatnou „předpověď“ řady (jen skutečnost).
+
+ ) : null}
+
{error ? (
{error}