from __future__ import annotations from gibil.classes.models import NetPowerForecastPoint, NetPowerForecastRun, PowerForecastRun class NetPowerForecaster: """Combines production and usage curves into expected and interval net power.""" def combine( self, solar_run: PowerForecastRun, load_run: PowerForecastRun, ) -> NetPowerForecastRun: load_by_target = {point.target_at: point for point in load_run.points} points: list[NetPowerForecastPoint] = [] for solar_point in solar_run.points: load_point = load_by_target.get(solar_point.target_at) if load_point is None: continue points.append( NetPowerForecastPoint( target_at=solar_point.target_at, horizon_minutes=solar_point.horizon_minutes, expected_net_power_w=( solar_point.p50_power_w - load_point.p50_power_w ), safe_net_power_w=( solar_point.p10_power_w - load_point.p90_power_w ), p10_net_power_w=( solar_point.p10_power_w - load_point.p90_power_w ), p50_net_power_w=( solar_point.p50_power_w - load_point.p50_power_w ), p90_net_power_w=( solar_point.p90_power_w - load_point.p10_power_w ), solar_p50_power_w=solar_point.p50_power_w, load_p50_power_w=load_point.p50_power_w, solar_p10_power_w=solar_point.p10_power_w, solar_p90_power_w=solar_point.p90_power_w, load_p10_power_w=load_point.p10_power_w, load_p90_power_w=load_point.p90_power_w, ) ) return NetPowerForecastRun( issued_at=solar_run.issued_at, source="baseline_net_forecaster", points=points, )