import json VOLUME_UNITS = { 'нл': 0.001, # 1 нл = 0.001 мкл 'мкл': 1.0, # базовая единица объёма 'мл': 1000.0, # 1 мл = 1000 мкл 'л': 1000000.0 # 1 л = 1 000 000 мкл } MASS_UNITS = { 'нг': 0.000001, # 1 нг = 0.001 мкг 'мкг': 0.001, # базовая единица массы 'мг': 1.0, # 1 мг = 1000 мкг 'г': 1000.0, # 1 г = 1 000 000 мкг 'кг': 1000000.0 # 1 кг = 1 000 000 000 мкг } class Reagent: def __init__(self, name: str, percentage: float, unit: str, conversion_factor: float = 1.0): self.name = name self.percentage = percentage self.unit = unit self.conversion_factor = conversion_factor def to_dict(self): """Преобразует реагент в словарь для сохранения в JSON""" return { 'name': self.name, 'percentage': self.percentage, 'unit': self.unit, 'conversion_factor': self.conversion_factor } @classmethod def from_dict(cls, data): """Создаёт реагент из словаря, загруженного из JSON""" return cls( name=data['name'], percentage=data['percentage'], unit=data['unit'], conversion_factor=data['conversion_factor'] ) class Model: def __init__(self): self.reagents = [] self.total_amount = 1000.0 # по умолчанию 1000 мл self.amount_unit = "мл" self.solvent = "Вода" def convert_amount(self, amount_mkl_or_mkg: float, target_unit: str, is_volume: bool) -> float: """ Пересчитывает количество из базовых единиц (мкл/мкг) в целевую единицу. Args: amount_mkl_or_mkg: количество в базовых единицах (мкл или мкг) target_unit: целевая единица измерения is_volume: True — объём, False — масса Returns: Количество в целевой единице """ if is_volume: conversion_factor = VOLUME_UNITS.get(target_unit, 1.0) else: conversion_factor = MASS_UNITS.get(target_unit, 1.0) return amount_mkl_or_mkg / conversion_factor def add_reagent(self, reagent: Reagent): """Добавляет реагент в список""" self.reagents.append(reagent) def calculate_amounts(self) -> list: """ Рассчитывает абсолютное количество каждого реагента с учётом единиц измерения. Возвращает список количеств в единицах измерения реагента. """ results = [] for reagent in self.reagents: # Базовый расчёт в процентах от общего количества base_amount = (reagent.percentage / 100) * self.total_amount # Определяем, объём или масса is_volume = reagent.unit in VOLUME_UNITS is_mass = reagent.unit in MASS_UNITS if is_volume: # Переводим общее количество среды в мкл для расчёта total_in_mkl = self.total_amount * VOLUME_UNITS[self.amount_unit] # Расчёт в мкл amount_in_mkl = (reagent.percentage / 100) * total_in_mkl # Переводим обратно в единицы реагента final_amount = self.convert_amount(amount_in_mkl, reagent.unit, True) elif is_mass: # Переводим общее количество среды в мкг для расчёта (если среда в единицах объёма, # предполагаем плотность = 1 г/мл) if self.amount_unit in VOLUME_UNITS: # Предполагаем плотность 1 г/мл: 1 мл ≈ 1 г total_in_mkg = self.total_amount * VOLUME_UNITS[self.amount_unit] # в мкл total_in_mkg *= 1000 # переводим в мкг (1 мкл воды ≈ 1 мкг) else: total_in_mkg = self.total_amount * MASS_UNITS[self.amount_unit] # Расчёт в мкг amount_in_mkg = (reagent.percentage / 100) * total_in_mkg # Переводим в единицы реагента final_amount = self.convert_amount(amount_in_mkg, reagent.unit, False) else: # Если единица неизвестна, возвращаем базовый расчёт final_amount = base_amount results.append(final_amount) return results def get_solvent_info(self) -> dict: """Возвращает информацию о растворителе: процент и количество""" total_percentage = sum(r.percentage for r in self.reagents) solvent_percentage = max(0, 100 - total_percentage) # не меньше 0% solvent_amount = (solvent_percentage / 100) * self.total_amount return { 'percentage': solvent_percentage, 'amount': solvent_amount, 'unit': self.amount_unit } def save_to_file(self, filename: str): """Сохраняет состав среды в JSON‑файл""" data = { 'total_amount': self.total_amount, 'amount_unit': self.amount_unit, 'solvent': self.solvent, 'reagents': [r.to_dict() for r in self.reagents] } with open(filename, 'w', encoding='utf-8') as f: json.dump(data, f, ensure_ascii=False, indent=2) def load_from_file(self, filename: str): """Загружает состав среды из JSON‑файла""" with open(filename, 'r', encoding='utf-8') as f: data = json.load(f) # Восстанавливаем данные модели self.total_amount = data['total_amount'] self.amount_unit = data['amount_unit'] self.solvent = data['solvent'] # Очищаем и заполняем список реагентов self.reagents.clear() for reagent_data in data['reagents']: reagent = Reagent.from_dict(reagent_data) self.reagents.append(reagent)