import hashlib from typing import Sequence import pandas as pd import yaml from fastapi import HTTPException from sqlalchemy.future import select from db.crud import create, update, get_by_id, update_exp from db.models import LoadParameters, RecyclingParameters from db.models.experiment_parameters_model import ExperimentParameters from db.postgres_db_connection import async_session_postgres from macros_generator import load_calculation, recycling_calculation async def get_exp_parameters_by_category(category_id: int) -> Sequence[ExperimentParameters]: async with async_session_postgres() as session: result = await session.execute( select(ExperimentParameters).where(ExperimentParameters.experiment_category_id == category_id) ) return result.scalars().all() async def get_exp_parameters_by_exp_hash(exp_hash: str) -> Sequence[ExperimentParameters]: async with async_session_postgres() as session: result = await session.execute( select(ExperimentParameters).where(ExperimentParameters.experiment_hash == exp_hash) ) return result.scalars().all() def generate_experiment_hash(data: dict) -> str: """Генерация уникального хеша на основе данных эксперимента""" hash_input = f"{data['outer_blades_count']}_{data['outer_blades_length']}_{data['outer_blades_angle']}_{data['middle_blades_count']}_{data['load']}_{data['recycling_level']}" return hashlib.sha256(hash_input.encode()).hexdigest() async def save_experiment_to_db(df: pd.DataFrame): for _, row in df.iterrows(): try: # Преобразуем load и recycling_level в соответствующие id load = int(row['load']) recycling = int(row['recycling_level']) # Генерация хеша для experiment_hash experiment_hash = generate_experiment_hash(row) exp = await create( ExperimentParameters, outer_blades_count=int(row['outer_blades_count']), outer_blades_length=float(row['outer_blades_length']), outer_blades_angle=float(row['outer_blades_angle']), middle_blades_count=int(row['middle_blades_count']), load_id=None, recycling_id=None, experiment_hash=experiment_hash, oxidizer_temp=float(row['oxidizer_temp']), experiment_category_id=experiment_category_id ) await process_and_save_experiment_data(exp.id, load, recycling) except Exception as e: print(f"Ошибка при сохранении данных: {e}") raise HTTPException(status_code=500, detail=f"Ошибка при сохранении данных: {e}") async def process_and_save_experiment_data(id: int, load: float, recycling_level: float) -> dict: try: experiment = await get_by_id(ExperimentParameters, id) if experiment is None: raise HTTPException(status_code=404, detail=f"ExperimentParameters с id {id} не найден.") yaml_file_path = "config.yaml" with open(yaml_file_path, "r", encoding="utf-8") as file: data = yaml.safe_load(file) diameters = data["parameters"]["diameters"] dict_load = load_calculation(load, diameters, None) primary_air_consumption = dict_load["primary_air_consumption"] secondary_air_consumption = dict_load["secondary_air_consumption"] gas_inlet_consumption = dict_load["gas_inlet_consumption"] alpha = dict_load["alpha"] gas_consumption = dict_load["gas_consumption"] air_consumption = dict_load["air_consumption"] dict_recycling = recycling_calculation(alpha, gas_consumption, air_consumption, recycling_level) co2 = dict_recycling["CO2"] n2 = dict_recycling["N2"] h2o = dict_recycling["H2O"] o2 = dict_recycling["O2"] load_params = await create( LoadParameters, load=int(load), primary_air_consumption=primary_air_consumption, secondary_air_consumption=secondary_air_consumption, gas_inlet_consumption=gas_inlet_consumption ) recycling_params = await create( RecyclingParameters, load_id=load_params.id, recycling_level=int(recycling_level), co2=co2, n2=n2, h2o=h2o, o2=o2 ) await update_exp( ExperimentParameters, id=experiment.id, updated_data={ "load_id": load_params.id, "recycling_id": recycling_params.id } ) return { "message": "Данные успешно обработаны и сохранены.", "load_parameters": load_params, "recycling_parameters": recycling_params } except Exception as e: raise HTTPException(status_code=500, detail=f"An error occurred: {str(e)}")