|
|
|
@ -7,87 +7,153 @@ from src.database.core import DbSession
|
|
|
|
from src.scope_equipment.model import ScopeEquipment
|
|
|
|
from src.scope_equipment.model import ScopeEquipment
|
|
|
|
from src.scope_equipment.service import get_by_scope_name
|
|
|
|
from src.scope_equipment.service import get_by_scope_name
|
|
|
|
from src.scope_equipment_job.service import get_equipment_level_by_no
|
|
|
|
from src.scope_equipment_job.service import get_equipment_level_by_no
|
|
|
|
|
|
|
|
from datetime import datetime, timedelta
|
|
|
|
|
|
|
|
|
|
|
|
async def get_all_target_reliability(
|
|
|
|
|
|
|
|
*, db_session: DbSession, scope_name: str, eaf_threshold: float = 100.0
|
|
|
|
|
|
|
|
):
|
|
|
|
|
|
|
|
"""Get all overhaul overview with EAF values that sum to 100%, aggregated by system."""
|
|
|
|
|
|
|
|
equipments = await get_by_scope_name(db_session=db_session, scope_name=scope_name)
|
|
|
|
|
|
|
|
equipment_system = await get_equipment_level_by_no(db_session=db_session, level=1)
|
|
|
|
|
|
|
|
equipment_subsystem = await get_equipment_level_by_no(
|
|
|
|
|
|
|
|
db_session=db_session, level=2
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# If no equipments found, return empty list
|
|
|
|
|
|
|
|
if not equipments:
|
|
|
|
|
|
|
|
return []
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import random
|
|
|
|
import random
|
|
|
|
|
|
|
|
from typing import List
|
|
|
|
n = len(equipments)
|
|
|
|
from .utils import generate_down_periods
|
|
|
|
base_value = 100 / n # Even distribution as base
|
|
|
|
|
|
|
|
|
|
|
|
# async def get_all_target_reliability(
|
|
|
|
# Generate EAF values with ±30% variation from base
|
|
|
|
# *, db_session: DbSession, scope_name: str, eaf_threshold: float = 100.0
|
|
|
|
eaf_values = [
|
|
|
|
# ):
|
|
|
|
base_value + random.uniform(-0.3 * base_value, 0.3 * base_value)
|
|
|
|
# """Get all overhaul overview with EAF values that sum to 100%, aggregated by system."""
|
|
|
|
for _ in range(n)
|
|
|
|
# equipments = await get_by_scope_name(db_session=db_session, scope_name=scope_name)
|
|
|
|
]
|
|
|
|
# equipment_system = await get_equipment_level_by_no(db_session=db_session, level=1)
|
|
|
|
|
|
|
|
# equipment_subsystem = await get_equipment_level_by_no(
|
|
|
|
# Normalize to ensure sum is 100
|
|
|
|
# db_session=db_session, level=2
|
|
|
|
total = sum(eaf_values)
|
|
|
|
# )
|
|
|
|
eaf_values = [(v * 100 / total) for v in eaf_values]
|
|
|
|
|
|
|
|
|
|
|
|
# # If no equipments found, return empty list
|
|
|
|
# Create result array of dictionaries
|
|
|
|
# if not equipments:
|
|
|
|
result = [
|
|
|
|
# return []
|
|
|
|
{
|
|
|
|
|
|
|
|
"id": equipment.id,
|
|
|
|
# import random
|
|
|
|
"assetnum": equipment.assetnum,
|
|
|
|
|
|
|
|
"location_tag": equipment.master_equipment.location_tag,
|
|
|
|
# n = len(equipments)
|
|
|
|
"name": equipment.master_equipment.name,
|
|
|
|
# base_value = 100 / n # Even distribution as base
|
|
|
|
"parent_id": equipment.master_equipment.parent_id, # Add parent_id to identify the system
|
|
|
|
|
|
|
|
"eaf": round(eaf, 4), # Add EAF value
|
|
|
|
# # Generate EAF values with ±30% variation from base
|
|
|
|
}
|
|
|
|
# eaf_values = [
|
|
|
|
for equipment, eaf in zip(equipments, eaf_values)
|
|
|
|
# base_value + random.uniform(-0.3 * base_value, 0.3 * base_value)
|
|
|
|
]
|
|
|
|
# for _ in range(n)
|
|
|
|
|
|
|
|
# ]
|
|
|
|
# Group equipment by system
|
|
|
|
|
|
|
|
sub_system = {
|
|
|
|
# # Normalize to ensure sum is 100
|
|
|
|
subsystem.id: subsystem.parent_id for subsystem in equipment_subsystem
|
|
|
|
# total = sum(eaf_values)
|
|
|
|
}
|
|
|
|
# eaf_values = [(v * 100 / total) for v in eaf_values]
|
|
|
|
systems = {
|
|
|
|
|
|
|
|
system.id: {"name": system.name, "total_eaf": 0, "equipments": []}
|
|
|
|
# # Create result array of dictionaries
|
|
|
|
for system in equipment_system
|
|
|
|
# result = [
|
|
|
|
}
|
|
|
|
# {
|
|
|
|
|
|
|
|
# "id": equipment.id,
|
|
|
|
for equipment in result:
|
|
|
|
# "assetnum": equipment.assetnum,
|
|
|
|
if equipment["parent_id"] in sub_system:
|
|
|
|
# "location_tag": equipment.master_equipment.location_tag,
|
|
|
|
systems[sub_system[equipment["parent_id"]]]["equipments"].append(equipment)
|
|
|
|
# "name": equipment.master_equipment.name,
|
|
|
|
systems[sub_system[equipment["parent_id"]]]["total_eaf"] += equipment["eaf"]
|
|
|
|
# "parent_id": equipment.master_equipment.parent_id, # Add parent_id to identify the system
|
|
|
|
|
|
|
|
# "eaf": round(eaf, 4), # Add EAF value
|
|
|
|
# Convert the systems dictionary to a list of aggregated results
|
|
|
|
# }
|
|
|
|
aggregated_result = [
|
|
|
|
# for equipment, eaf in zip(equipments, eaf_values)
|
|
|
|
{
|
|
|
|
# ]
|
|
|
|
"system_id": system_id,
|
|
|
|
|
|
|
|
"system_name": system_data["name"],
|
|
|
|
# # Group equipment by system
|
|
|
|
"total_eaf": round(system_data["total_eaf"], 4),
|
|
|
|
# sub_system = {
|
|
|
|
"equipments": system_data["equipments"],
|
|
|
|
# subsystem.id: subsystem.parent_id for subsystem in equipment_subsystem
|
|
|
|
}
|
|
|
|
# }
|
|
|
|
for system_id, system_data in systems.items()
|
|
|
|
# systems = {
|
|
|
|
]
|
|
|
|
# system.id: {"name": system.name, "total_eaf": 0, "equipments": []}
|
|
|
|
|
|
|
|
# for system in equipment_system
|
|
|
|
# Sort the aggregated result by total_eaf in descending order
|
|
|
|
# }
|
|
|
|
aggregated_result.sort(key=lambda x: x["total_eaf"], reverse=True)
|
|
|
|
|
|
|
|
|
|
|
|
# for equipment in result:
|
|
|
|
# Filter systems up to the threshold
|
|
|
|
# if equipment["parent_id"] in sub_system:
|
|
|
|
cumulative_eaf = 0
|
|
|
|
# systems[sub_system[equipment["parent_id"]]]["equipments"].append(equipment)
|
|
|
|
filtered_aggregated_result = []
|
|
|
|
# systems[sub_system[equipment["parent_id"]]]["total_eaf"] += equipment["eaf"]
|
|
|
|
|
|
|
|
|
|
|
|
for system in aggregated_result:
|
|
|
|
# # Convert the systems dictionary to a list of aggregated results
|
|
|
|
cumulative_eaf += system["total_eaf"]
|
|
|
|
# aggregated_result = [
|
|
|
|
filtered_aggregated_result.append(system)
|
|
|
|
# {
|
|
|
|
|
|
|
|
# "system_id": system_id,
|
|
|
|
if cumulative_eaf >= eaf_threshold:
|
|
|
|
# "system_name": system_data["name"],
|
|
|
|
|
|
|
|
# "total_eaf": round(system_data["total_eaf"], 4),
|
|
|
|
|
|
|
|
# "equipments": system_data["equipments"],
|
|
|
|
|
|
|
|
# }
|
|
|
|
|
|
|
|
# for system_id, system_data in systems.items()
|
|
|
|
|
|
|
|
# ]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# # Sort the aggregated result by total_eaf in descending order
|
|
|
|
|
|
|
|
# aggregated_result.sort(key=lambda x: x["total_eaf"], reverse=True)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# # Filter systems up to the threshold
|
|
|
|
|
|
|
|
# cumulative_eaf = 0
|
|
|
|
|
|
|
|
# filtered_aggregated_result = []
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# for system in aggregated_result:
|
|
|
|
|
|
|
|
# cumulative_eaf += system["total_eaf"]
|
|
|
|
|
|
|
|
# filtered_aggregated_result.append(system)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# if cumulative_eaf >= eaf_threshold:
|
|
|
|
|
|
|
|
# break
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# return filtered_aggregated_result
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_eaf_timeline(eaf_input: float, oh_session_id: str) -> List[dict]:
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
Generate a timeline of EAF values based on input parameters.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
|
|
|
eaf_input (float): EAF value to check against thresholds
|
|
|
|
|
|
|
|
oh_session_id (str): OH session identifier
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
|
|
set[dict]: Set of dictionaries containing dates and their EAF values
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
# Define EAF thresholds
|
|
|
|
|
|
|
|
MIN_EAF = 0.3
|
|
|
|
|
|
|
|
MAX_EAF = 0.8
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Dummy OH session dates
|
|
|
|
|
|
|
|
oh_session_start = datetime(2024, 1, 1)
|
|
|
|
|
|
|
|
oh_session_end = datetime(2026, 7, 30)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Initialize result set
|
|
|
|
|
|
|
|
results = []
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Determine date range based on EAF input
|
|
|
|
|
|
|
|
if MIN_EAF <= eaf_input <= MAX_EAF:
|
|
|
|
|
|
|
|
start_date = oh_session_start
|
|
|
|
|
|
|
|
end_date = oh_session_end
|
|
|
|
|
|
|
|
elif eaf_input < MIN_EAF:
|
|
|
|
|
|
|
|
# If below minimum, extend end date by 2 months weeks
|
|
|
|
|
|
|
|
start_date = oh_session_start
|
|
|
|
|
|
|
|
end_date = oh_session_end + timedelta(days=360)
|
|
|
|
|
|
|
|
else: # eaf_input > MAX_EAF
|
|
|
|
|
|
|
|
# If above maximum, reduce end date by 1 month
|
|
|
|
|
|
|
|
start_date = oh_session_start
|
|
|
|
|
|
|
|
end_date = oh_session_end - timedelta(days=180)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Generate random down periods
|
|
|
|
|
|
|
|
down_periods = generate_down_periods(start_date, end_date, 10)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Generate daily entries
|
|
|
|
|
|
|
|
current_date = start_date
|
|
|
|
|
|
|
|
while current_date <= end_date:
|
|
|
|
|
|
|
|
# Convert date to string format
|
|
|
|
|
|
|
|
date_str = current_date.strftime('%Y-%m-%d')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Set default EAF value to 1 (system up)
|
|
|
|
|
|
|
|
eaf_value = 1.0
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Check if current date is in any down period
|
|
|
|
|
|
|
|
for period_start, period_end in down_periods:
|
|
|
|
|
|
|
|
if period_start <= current_date <= period_end:
|
|
|
|
|
|
|
|
eaf_value = 0.2
|
|
|
|
break
|
|
|
|
break
|
|
|
|
|
|
|
|
|
|
|
|
return filtered_aggregated_result
|
|
|
|
# Add entry to timeline
|
|
|
|
|
|
|
|
results.append({
|
|
|
|
|
|
|
|
'date': date_str,
|
|
|
|
|
|
|
|
'eaf_value': eaf_value
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
current_date += timedelta(days=1)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return results
|
|
|
|
|