feat: implement RBD simulation endpoint with persistence and parameter customization

main
Cizz22 2 months ago
parent 8eb04ab699
commit 474d76ff05

@ -11,10 +11,36 @@ from src.database.core import DbSession, CollectorDbSession
from src.auth.service import Token from src.auth.service import Token
from src.models import StandardResponse from src.models import StandardResponse
from pydantic import BaseModel, Field
from .service import run_rbd_simulation, get_simulation_results, identify_worst_eaf_contributors from .service import run_rbd_simulation, get_simulation_results, identify_worst_eaf_contributors
from .schema import OptimizationResult, TargetReliabiltiyQuery from .schema import OptimizationResult, TargetReliabiltiyQuery
router = APIRouter() router = APIRouter()
class SimulateRequest(BaseModel):
duration: int = Field(17520, description="Simulation duration in hours")
oh_duration: int = Field(1200, description="Overhaul duration in hours")
oh_session_id: str = Field(..., description="Overhaul session ID")
@router.post("/simulate", response_model=StandardResponse)
async def start_simulation(
token: Token,
db_session: DbSession,
payload: SimulateRequest
):
"""Start RBD simulation for target reliability."""
token_str = token.token if hasattr(token, 'token') else str(token)
result = await run_rbd_simulation(
sim_hours=payload.duration,
oh_duration=payload.oh_duration,
oh_session_id=payload.oh_session_id,
db_session=db_session,
token=token_str
)
return StandardResponse(
data={"simulation_id": result.get("data")},
message=result.get("message", "Simulation started successfully")
)
# @router.get("", response_model=StandardResponse[List[Dict]]) # @router.get("", response_model=StandardResponse[List[Dict]])
# async def get_target_reliability( # async def get_target_reliability(
@ -51,6 +77,7 @@ async def get_target_reliability(
duration = params.duration duration = params.duration
simulation_id = params.simulation_id simulation_id = params.simulation_id
cut_hours = params.cut_hours cut_hours = params.cut_hours
oh_duration = params.oh_duration
if not oh_session_id: if not oh_session_id:
raise HTTPException( raise HTTPException(
@ -113,7 +140,7 @@ async def get_target_reliability(
collector_db=collector_db, collector_db=collector_db,
simulation_id=simulation_id, simulation_id=simulation_id,
duration=duration, duration=duration,
po_duration=1200, po_duration=oh_duration,
cut_hours=float(cut_hours) cut_hours=float(cut_hours)
) )

@ -70,6 +70,7 @@ class TargetReliabiltiyQuery(DefultBase):
duration: int = Field(17520) duration: int = Field(17520)
simulation_id: Optional[str] = Field(None) simulation_id: Optional[str] = Field(None)
cut_hours:int = Field(0) cut_hours:int = Field(0)
oh_duration: int = Field(1200)
# { # {
# "overview": { # "overview": {

@ -1,7 +1,7 @@
import math import math
from typing import Optional, List from typing import Optional, List
from dataclasses import dataclass from dataclasses import dataclass
from sqlalchemy import Delete, Select from sqlalchemy import Delete, Select, select
import httpx import httpx
from src.auth.service import CurrentUser from src.auth.service import CurrentUser
from src.config import RBD_SERVICE_API from src.config import RBD_SERVICE_API
@ -21,17 +21,32 @@ from src.overhaul_activity.service import get_standard_scope_by_session_id
client = httpx.AsyncClient(timeout=300.0) client = httpx.AsyncClient(timeout=300.0)
async def run_rbd_simulation(*, sim_hours: int, token): from src.calculation_time_constrains.model import CalculationData
async def run_rbd_simulation(*, sim_hours: int, oh_duration: int = 1200, oh_session_id: str, db_session: DbSession, token: str):
# Check if a simulation with these parameters already exists
stmt = select(CalculationData).where(
CalculationData.overhaul_session_id == oh_session_id,
CalculationData.analysis_metadata["type"].astext == "target_reliability",
CalculationData.analysis_metadata["sim_hours"].astext == str(sim_hours),
CalculationData.analysis_metadata["oh_duration"].astext == str(oh_duration)
)
result = await db_session.execute(stmt)
existing_calc = result.scalars().first()
if existing_calc and existing_calc.rbd_simulation_id:
return {"data": str(existing_calc.rbd_simulation_id), "status": "success", "message": "Loaded existing simulation"}
sim_data = { sim_data = {
"SimulationName": f"Simulasi TR OH {sim_hours}", "SimulationName": f"Simulasi TR OH {sim_hours}_{oh_duration}",
"SchematicName": "- TJB - Unit 3 -", "SchematicName": "- TJB - Unit 3 -",
"SimSeed": 1, "SimSeed": 1,
"SimDuration": sim_hours, "SimDuration": sim_hours,
"OverhaulInterval": sim_hours - 1201, "OverhaulInterval": max(sim_hours - oh_duration - 1, 1),
"DurationUnit": "UHour", "DurationUnit": "UHour",
"SimNumRun": 1, "SimNumRun": 1,
"IsDefault": False, "IsDefault": False,
"OverhaulDuration": 1200 "OverhaulDuration": oh_duration
} }
headers = { headers = {
@ -44,7 +59,23 @@ async def run_rbd_simulation(*, sim_hours: int, token):
async with httpx.AsyncClient(timeout=300.0) as client: async with httpx.AsyncClient(timeout=300.0) as client:
response = await client.post(rbd_simulation_url, json=sim_data, headers=headers) response = await client.post(rbd_simulation_url, json=sim_data, headers=headers)
response.raise_for_status() response.raise_for_status()
return response.json() resp_json = response.json()
sim_id = resp_json.get("data")
if sim_id:
new_calc = CalculationData(
overhaul_session_id=oh_session_id,
rbd_simulation_id=sim_id,
analysis_metadata={
"type": "target_reliability",
"sim_hours": str(sim_hours),
"oh_duration": str(oh_duration)
}
)
db_session.add(new_calc)
await db_session.commit()
return resp_json
async def get_simulation_results(*, simulation_id: str, token: str): async def get_simulation_results(*, simulation_id: str, token: str):
headers = { headers = {

@ -0,0 +1,6 @@
import asyncio
import httpx
from src.config import RBD_SERVICE_API
async def main():
token = "your_token_here" # I don't have a token. I'll need a token.
Loading…
Cancel
Save