feat: enhance forecast retrieval by adding trending data and improving simulation queries

main
Cizz22 1 week ago
parent 042e11b06a
commit 3f41cd06e6

@ -536,16 +536,20 @@ async def get_forecast_eaf(
oh_interval = hours_between(oh_date, next_oh_date) oh_interval = hours_between(oh_date, next_oh_date)
duration = 168 if time_range == "weekly" else 720 duration = 168 if time_range == "weekly" else 720
end_date = now + timedelta(hours=duration) end_date = now + timedelta(hours=duration)
duration_simulation = hours_between(oh_date, end_date) # OffSet = hours already elapsed since last OH (current equipment age).
# SimDuration = only the forecast window (next 7 or 30 days).
# This way calculate_plant_eaf gets EAF/EFOR for just the upcoming period,
# not a cumulative average from last OH to now.
offset_hours = max(hours_between(oh_date, now), 0)
project = await get_project(db_session=db_session) project = await get_project(db_session=db_session)
# 5. Create Simulation Request # 5. Create Simulation Request
sim_in = SimulationInput( sim_in = SimulationInput(
SchematicName="- TJB - Unit 3 -", SchematicName="- TJB - Unit 3 -",
SimulationName=f"Simulation_{time_range}_{now.strftime('%Y%m%d')}", SimulationName=f"Simulation_{time_range}_{now.strftime('%Y%m%d')}",
SimDuration=duration_simulation, SimDuration=duration,
DurationUnit="UHour", DurationUnit="UHour",
OffSet=0, OffSet=offset_hours,
SimSeed=99, SimSeed=99,
SimNumRun=1, SimNumRun=1,
IsDefault=False, IsDefault=False,
@ -576,7 +580,8 @@ async def get_forecast_eaf(
forecast_msg = ( forecast_msg = (
f"Forecast simulation started via Temporal. " f"Forecast simulation started via Temporal. "
f"Period: {oh_date.strftime('%Y-%m-%d')} to {end_date.strftime('%Y-%m-%d')}" f"Period: {now.strftime('%Y-%m-%d')} to {end_date.strftime('%Y-%m-%d')} "
f"(offset {offset_hours}h from last OH on {oh_date.strftime('%Y-%m-%d')})"
) )
return StandardResponse( return StandardResponse(

@ -1100,7 +1100,7 @@ async def get_forecast_trending(
if pt: if pt:
points.append(pt) points.append(pt)
if len(points) >= limit: if points:
return points return points
# --- Pass 2: any completed sim, bucket by week/month --- # --- Pass 2: any completed sim, bucket by week/month ---
@ -1119,7 +1119,7 @@ async def get_forecast_trending(
buckets[bucket] = sim buckets[bucket] = sim
sorted_sims = [sim for _, sim in sorted(buckets.items(), key=lambda x: x[0])] sorted_sims = [sim for _, sim in sorted(buckets.items(), key=lambda x: x[0])]
sorted_sims = sorted_sims[-limit:] # keep last `limit` buckets sorted_sims = sorted_sims[-limit:]
fallback_points = [] fallback_points = []
for sim in sorted_sims: for sim in sorted_sims:
@ -1127,4 +1127,4 @@ async def get_forecast_trending(
if pt: if pt:
fallback_points.append(pt) fallback_points.append(pt)
return fallback_points if fallback_points else points return fallback_points

@ -9,6 +9,7 @@ from src.aeros_simulation.model import AerosSimulation
from src.aeros_simulation.service import ( from src.aeros_simulation.service import (
get_calc_result_by, get_calc_result_by,
get_default_simulation, get_default_simulation,
get_forecast_trending,
get_simulation_by_id, get_simulation_by_id,
get_simulation_node_by, get_simulation_node_by,
) )
@ -131,9 +132,13 @@ async def get_model_data(*, db_session: DbSession, simulation_id: Optional[UUID]
"WTP": 98, "WTP": 98,
} }
# Fetch Forecasts # Fetch Forecasts - latest single point (for summary cards)
forecast_weekly = await get_latest_sim_results_by_pattern(db_session, "Simulation_weekly_%") forecast_weekly_latest = await get_latest_sim_results_by_pattern(db_session, "Simulation_weekly_%")
forecast_monthly = await get_latest_sim_results_by_pattern(db_session, "Simulation_monthly_%") forecast_monthly_latest = await get_latest_sim_results_by_pattern(db_session, "Simulation_monthly_%")
# Fetch Forecast Trending - historical arrays for both weekly and monthly
forecast_weekly_trending = await get_forecast_trending(db_session=db_session, time_range="weekly", limit=12)
forecast_monthly_trending = await get_forecast_trending(db_session=db_session, time_range="monthly", limit=12)
return { return {
"id": str(simulation.id), "id": str(simulation.id),
@ -158,8 +163,10 @@ async def get_model_data(*, db_session: DbSession, simulation_id: Optional[UUID]
"Real_Derating": Derating "Real_Derating": Derating
}, },
"powerplant_reliability": powerplant_reliability, "powerplant_reliability": powerplant_reliability,
"forecast_weekly": forecast_weekly, "forecast_weekly": forecast_weekly_latest,
"forecast_monthly": forecast_monthly "forecast_monthly": forecast_monthly_latest,
"forecast_weekly_trending": forecast_weekly_trending,
"forecast_monthly_trending": forecast_monthly_trending,
} }
async def get_latest_sim_results_by_pattern(db_session: DbSession, pattern: str): async def get_latest_sim_results_by_pattern(db_session: DbSession, pattern: str):
@ -167,7 +174,7 @@ async def get_latest_sim_results_by_pattern(db_session: DbSession, pattern: str)
from src.aeros_simulation.model import AerosSimulation, AerosSimulationCalcResult, AerosNode from src.aeros_simulation.model import AerosSimulation, AerosSimulationCalcResult, AerosNode
from src.aeros_simulation.service import get_plant_calc_result from src.aeros_simulation.service import get_plant_calc_result
query = select(AerosSimulation).where(AerosSimulation.simulation_name.like(pattern)).order_by(AerosSimulation.created_at.desc()).limit(1) query = select(AerosSimulation).where(AerosSimulation.simulation_name.like(pattern)).where(AerosSimulation.status == "completed").order_by(AerosSimulation.created_at.desc()).limit(1)
result = await db_session.execute(query) result = await db_session.execute(query)
simulation = result.scalars().first() simulation = result.scalars().first()

Loading…
Cancel
Save