fix calculation

main
Cizz22 12 months ago
parent a8610b3a2d
commit 5995a42b5f

@ -10,11 +10,11 @@ from src.overhaul_scope.service import get_all
from .schema import CalculationTimeConstrainsParametersRead, CalculationTimeConstrainsParametersRetrive, CalculationTimeConstrainsParametersCreate, CalculationTimeConstrainsRead
from .service import get_calculation_by_reference_and_parameter, get_calculation_result, get_overhaul_cost_by_time_chart, get_corrective_cost_time_chart, create_param_and_data, get_calculation_data_by_id, create_calculation_result_service, get_avg_cost_by_asset
from src.scope_equipment.service import get_by_assetnum
from fastapi import HTTPException, status
async def get_create_calculation_parameters(*, db_session: DbSession, calculation_id: str):
if calculation_id is not None:
calculation = get_calculation_data_by_id(calculation_id)
calculation = await get_calculation_data_by_id(calculation_id=calculation_id, db_session=db_session)
if not calculation:
raise HTTPException(
@ -64,9 +64,8 @@ async def create_calculation(*, db_session: DbSession, calculation_time_constrai
calculation_data = await create_param_and_data(
db_session=db_session, calculation_param_in=calculation_time_constrains_in, created_by=created_by)
results = await create_calculation_result_service(db_session=db_session, calculation_id=calculation_data.id)
results = await create_calculation_result_service(db_session=db_session, calculation=calculation_data)
return results

@ -2,7 +2,7 @@
from enum import Enum
from typing import List, Optional, Union
from sqlalchemy import UUID, Column, Float, ForeignKey, Integer, String, JSON, Numeric
from sqlalchemy import UUID, Column, Float, ForeignKey, Integer, String, JSON, Numeric, Boolean
from sqlalchemy.orm import relationship
from src.database.core import Base, DbSession
from src.models import DefaultMixin, IdentityMixin, TimeStampMixin, UUIDMixin
@ -145,5 +145,6 @@ class CalculationEquipmentResult(Base, DefaultMixin):
service_cost = Column(Float, nullable=False)
calculation_data_id = Column(UUID(as_uuid=True), ForeignKey('oh_tr_calculation_data.id'), nullable=True)
optimum_day = Column(Integer, default=1)
is_included = Column(Boolean, default=True)

@ -74,6 +74,7 @@ class EquipmentResult(CalculationTimeConstrainsBase):
class CalculationTimeConstrainsRead(CalculationTimeConstrainsBase):
id: Union[UUID, str]
reference: UUID
scope: str
results: List[CalculationResultsRead]
equipment_results: List[EquipmentResult]
optimum_oh: Any

@ -2,6 +2,7 @@ from typing import List, Optional, Tuple
from uuid import UUID
import numpy as np
from sqlalchemy import and_, func, select
from sqlalchemy.engine import result
from sqlalchemy.orm import joinedload
from src.database.core import DbSession
from src.overhaul_activity.service import get_all_by_session_id
@ -12,15 +13,34 @@ from .model import CalculationParam, OverhaulReferenceType, CalculationData, Cal
from fastapi import HTTPException, status
from src.overhaul_scope.service import get_by_scope_name, get
from src.scope_equipment.service import get_by_assetnum
from src.overhaul_scope.service import get as get_scope
from .schema import CalculationResultsRead
def get_overhaul_cost_by_time_chart(overhaul_cost: float, days: int) -> list:
def get_overhaul_cost_by_time_chart(overhaul_cost: float, days: int) -> np.ndarray:
"""
Calculate decreasing overhaul costs over time using exponential decay.
Args:
overhaul_cost (float): Initial overhaul cost
days (int): Number of days to calculate cost for
Returns:
np.ndarray: Array of daily costs with exponential decay
Raises:
ValueError: If overhaul_cost is negative or days is not positive
"""
if overhaul_cost < 0:
raise ValueError("Overhaul cost cannot be negative")
if days <= 0:
raise ValueError("Days must be positive")
exponents = np.arange(0, days)
results = overhaul_cost / (2 ** exponents)
results = np.where(np.isfinite(results), results, 0)
return results
def get_corrective_cost_time_chart(material_cost: float, service_cost: float, days: int) -> Tuple[np.ndarray, np.ndarray]:
day_points = np.arange(0, days)
@ -63,6 +83,7 @@ async def create_param_and_data(*, db_session: DbSession, calculation_param_in:
async def get_calculation_result(db_session: DbSession, calculation_id: str):
days=365
scope_calculation = await get_calculation_data_by_id(db_session=db_session, calculation_id=calculation_id)
if not scope_calculation:
raise HTTPException(
@ -70,21 +91,54 @@ async def get_calculation_result(db_session: DbSession, calculation_id: str):
detail="A data with this id does not exist.",
)
scope_overhaul = await get_scope(db_session=db_session, overhaul_session_id=scope_calculation.overhaul_session_id)
if not scope_overhaul:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="A data with this id does not exist.",
)
calculation_results = []
for i in range(days):
result = {
"overhaul_cost": 0,
"corrective_cost": 0,
"num_failures": 0,
"day": i + 1
}
for eq in scope_calculation.equipment_results:
if not eq.is_included:
continue
result["corrective_cost"] += float(eq.corrective_costs[i])
result["overhaul_cost"] += float(eq.overhaul_costs[i])
result["num_failures"] += int(eq.daily_failures[i])
calculation_results.append(CalculationResultsRead(**result))
# Check if calculation already exist
return CalculationTimeConstrainsRead(
id=scope_calculation.id,
reference=scope_calculation.overhaul_session_id,
results=scope_calculation.results,
scope=scope_overhaul.type,
results=calculation_results,
optimum_oh=scope_calculation.optimum_oh_day,
equipment_results=scope_calculation.equipment_results
)
async def get_calculation_data_by_id(db_session: DbSession, calculation_id) -> CalculationData:
stmt = select(CalculationData).filter(CalculationData.id ==
calculation_id).options(joinedload(CalculationData.results), joinedload(CalculationData.equipment_results))
result = await db_session.execute(stmt)
stmt = select(CalculationData).filter(
CalculationData.id == calculation_id
).options(
joinedload(CalculationData.equipment_results), joinedload(CalculationData.parameter)
)
result = await db_session.execute(stmt)
return result.unique().scalar()
@ -149,20 +203,22 @@ async def get_calculation_data_by_id(db_session: DbSession, calculation_id) -> C
async def create_calculation_result_service(
db_session: DbSession,
calculation_id: UUID,
calculation: CalculationData,
) -> CalculationTimeConstrainsRead:
days = 365 # Changed to 365 days as per requirement
calculation = await get_calculation_data_by_id(db_session=db_session, calculation_id=calculation_id)
# Get all equipment for this calculation session
equipments = await get_all_by_session_id(db_session=db_session, overhaul_session_id=calculation.overhaul_session_id)
scope = await get_scope(db_session=db_session, overhaul_session_id=calculation.overhaul_session_id)
calculation_data = await get_calculation_data_by_id(db_session=db_session, calculation_id=calculation.id)
# Calculate overhaul costs once since it's shared
overhaul_cost_points = get_overhaul_cost_by_time_chart(
calculation.parameter.overhaul_cost,
calculation_data.parameter.overhaul_cost,
days=days
)
# Store results for each equipment
equipment_results: List[CalculationEquipmentResult] = []
total_corrective_costs = np.zeros(days)
@ -181,13 +237,6 @@ async def create_calculation_result_service(
equipment_optimum_index = np.argmin(equipment_total_cost)
equipment_failure_sum = sum(daily_failures[:equipment_optimum_index])
equipment_optimum = OptimumResult(
overhaul_cost=float(overhaul_cost_points[equipment_optimum_index]),
corrective_cost=float(corrective_costs[equipment_optimum_index]),
num_failures=int(equipment_failure_sum),
days=int(equipment_optimum_index + 1)
)
equipment_results.append(CalculationEquipmentResult(
corrective_costs=corrective_costs.tolist(),
overhaul_costs=overhaul_cost_points.tolist(),
@ -205,6 +254,7 @@ async def create_calculation_result_service(
db_session.add_all(equipment_results)
# Calculate optimum points using total costs
total_cost = total_corrective_costs + overhaul_cost_points
optimum_oh_index = np.argmin(total_cost)
@ -217,31 +267,30 @@ async def create_calculation_result_service(
days=int(optimum_oh_index + 1)
)
# Create calculation results for database
calculation_results = []
for i in range(days):
result = CalculationResult(
parameter_id=calculation.parameter_id,
calculation_data_id=calculation.id,
day=(i + 1),
corrective_cost=float(total_corrective_costs[i]),
overhaul_cost=float(overhaul_cost_points[i]),
num_failures=int(total_daily_failures[i]),
)
calculation_results.append(result)
# # Create calculation results for database
# calculation_results = []
# for i in range(days):
# result = CalculationResult(
# parameter_id=calculation.parameter_id,
# calculation_data_id=calculation.id,
# day=(i + 1),
# corrective_cost=float(total_corrective_costs[i]),
# overhaul_cost=float(overhaul_cost_points[i]),
# num_failures=int(total_daily_failures[i]),
# )
# calculation_results.append(result)
# Update calculation with optimum day
calculation.optimum_oh_day = optimum.days
# Save to database
db_session.add_all(calculation_results)
await db_session.commit()
# Return results including individual equipment data
return CalculationTimeConstrainsRead(
id=calculation.id,
reference=calculation.overhaul_session_id,
results=calculation_results,
scope=scope.type,
results=[],
optimum_oh=optimum,
equipment_results=equipment_results
)

Loading…
Cancel
Save