Переработан интерфейс программы, расчёт занчений в процессе исправления.
This commit is contained in:
@@ -0,0 +1,208 @@
|
||||
"""
|
||||
Модель данных проекта для сохранения/загрузки в JSON
|
||||
"""
|
||||
|
||||
from typing import List, Dict, Optional
|
||||
from dataclasses import dataclass, asdict
|
||||
from datetime import datetime
|
||||
import json
|
||||
|
||||
|
||||
@dataclass
|
||||
class ReagentData:
|
||||
"""Данные реагента"""
|
||||
name: str
|
||||
percentage: float
|
||||
unit: str
|
||||
conversion_factor: float
|
||||
dilution_factor: float
|
||||
|
||||
def to_dict(self) -> Dict:
|
||||
return asdict(self)
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls, data: Dict) -> 'ReagentData':
|
||||
return cls(
|
||||
name=data['name'],
|
||||
percentage=data['percentage'],
|
||||
unit=data['unit'],
|
||||
conversion_factor=data.get('conversion_factor', 1.0),
|
||||
dilution_factor=data.get('dilution_factor', 1.0)
|
||||
)
|
||||
|
||||
|
||||
@dataclass
|
||||
class FactorData:
|
||||
"""Данные фактора эксперимента"""
|
||||
name: str
|
||||
center: float
|
||||
low: float
|
||||
high: float
|
||||
step: float
|
||||
step_type: str
|
||||
unit: str
|
||||
percentage: Optional[float] = None
|
||||
dilution_factor: Optional[float] = None
|
||||
|
||||
def to_dict(self) -> Dict:
|
||||
d = asdict(self)
|
||||
# Удаляем None значения
|
||||
return {k: v for k, v in d.items() if v is not None}
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls, data: Dict) -> 'FactorData':
|
||||
return cls(
|
||||
name=data['name'],
|
||||
center=data['center'],
|
||||
low=data['low'],
|
||||
high=data['high'],
|
||||
step=data.get('step', 0),
|
||||
step_type=data.get('step_type', 'абс'),
|
||||
unit=data.get('unit', ''),
|
||||
percentage=data.get('percentage'),
|
||||
dilution_factor=data.get('dilution_factor')
|
||||
)
|
||||
|
||||
|
||||
@dataclass
|
||||
class ResponseData:
|
||||
"""Данные отклика эксперимента"""
|
||||
name: str
|
||||
unit: str
|
||||
|
||||
def to_dict(self) -> Dict:
|
||||
return asdict(self)
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls, data: Dict) -> 'ResponseData':
|
||||
return cls(
|
||||
name=data['name'],
|
||||
unit=data.get('unit', '')
|
||||
)
|
||||
|
||||
|
||||
@dataclass
|
||||
class ExperimentResultsData:
|
||||
"""Результаты эксперимента"""
|
||||
design: List[Dict] # План эксперимента
|
||||
results: List[List[float]] # Результаты измерений
|
||||
responses: List[ResponseData] # Отклики
|
||||
|
||||
def to_dict(self) -> Dict:
|
||||
return {
|
||||
'design': self.design,
|
||||
'results': self.results,
|
||||
'responses': [r.to_dict() for r in self.responses]
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls, data: Dict) -> 'ExperimentResultsData':
|
||||
return cls(
|
||||
design=data['design'],
|
||||
results=data['results'],
|
||||
responses=[ResponseData.from_dict(r) for r in data['responses']]
|
||||
)
|
||||
|
||||
|
||||
@dataclass
|
||||
class ProjectData:
|
||||
"""Полные данные проекта"""
|
||||
# Информация о проекте
|
||||
project_name: str
|
||||
created_at: str
|
||||
modified_at: str
|
||||
version: str = "1.0"
|
||||
|
||||
# Данные калькулятора сред
|
||||
medium_total_volume: float = 1000.0
|
||||
medium_volume_unit: str = "мл"
|
||||
medium_solvent: str = "Вода"
|
||||
medium_reagents: List[ReagentData] = None
|
||||
|
||||
# Данные эксперимента
|
||||
experiment_factors: List[FactorData] = None
|
||||
experiment_responses: List[ResponseData] = None
|
||||
experiment_center_points: int = 3
|
||||
experiment_randomize: bool = True
|
||||
experiment_results: Optional[ExperimentResultsData] = None
|
||||
|
||||
def __post_init__(self):
|
||||
if self.medium_reagents is None:
|
||||
self.medium_reagents = []
|
||||
if self.experiment_factors is None:
|
||||
self.experiment_factors = []
|
||||
if self.experiment_responses is None:
|
||||
self.experiment_responses = []
|
||||
|
||||
def to_dict(self) -> Dict:
|
||||
"""Конвертирует в словарь для JSON"""
|
||||
return {
|
||||
'project_info': {
|
||||
'name': self.project_name,
|
||||
'created_at': self.created_at,
|
||||
'modified_at': self.modified_at,
|
||||
'version': self.version
|
||||
},
|
||||
'medium_calculator': {
|
||||
'total_volume': self.medium_total_volume,
|
||||
'volume_unit': self.medium_volume_unit,
|
||||
'solvent': self.medium_solvent,
|
||||
'reagents': [r.to_dict() for r in self.medium_reagents]
|
||||
},
|
||||
'experiment': {
|
||||
'factors': [f.to_dict() for f in self.experiment_factors],
|
||||
'responses': [r.to_dict() for r in self.experiment_responses],
|
||||
'center_points': self.experiment_center_points,
|
||||
'randomize': self.experiment_randomize,
|
||||
'results': self.experiment_results.to_dict() if self.experiment_results else None
|
||||
}
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls, data: Dict) -> 'ProjectData':
|
||||
"""Создаёт объект из словаря"""
|
||||
project_info = data.get('project_info', {})
|
||||
medium = data.get('medium_calculator', {})
|
||||
experiment = data.get('experiment', {})
|
||||
|
||||
# Создаём объект
|
||||
obj = cls(
|
||||
project_name=project_info.get('name', 'Новый проект'),
|
||||
created_at=project_info.get('created_at', datetime.now().isoformat()),
|
||||
modified_at=project_info.get('modified_at', datetime.now().isoformat()),
|
||||
version=project_info.get('version', '1.0'),
|
||||
medium_total_volume=medium.get('total_volume', 1000.0),
|
||||
medium_volume_unit=medium.get('volume_unit', 'мл'),
|
||||
medium_solvent=medium.get('solvent', 'Вода'),
|
||||
medium_reagents=[ReagentData.from_dict(r) for r in medium.get('reagents', [])],
|
||||
experiment_factors=[FactorData.from_dict(f) for f in experiment.get('factors', [])],
|
||||
experiment_responses=[ResponseData.from_dict(r) for r in experiment.get('responses', [])],
|
||||
experiment_center_points=experiment.get('center_points', 3),
|
||||
experiment_randomize=experiment.get('randomize', True),
|
||||
experiment_results=ExperimentResultsData.from_dict(experiment['results'])
|
||||
if experiment.get('results') else None
|
||||
)
|
||||
return obj
|
||||
|
||||
def save_to_file(self, filename: str):
|
||||
"""Сохраняет проект в JSON файл"""
|
||||
self.modified_at = datetime.now().isoformat()
|
||||
with open(filename, 'w', encoding='utf-8') as f:
|
||||
json.dump(self.to_dict(), f, ensure_ascii=False, indent=2)
|
||||
|
||||
@classmethod
|
||||
def load_from_file(cls, filename: str) -> 'ProjectData':
|
||||
"""Загружает проект из JSON файла"""
|
||||
with open(filename, 'r', encoding='utf-8') as f:
|
||||
data = json.load(f)
|
||||
return cls.from_dict(data)
|
||||
|
||||
|
||||
def create_new_project(name: str = "Новый проект") -> ProjectData:
|
||||
"""Создаёт новый проект с текущей датой"""
|
||||
now = datetime.now().isoformat()
|
||||
return ProjectData(
|
||||
project_name=name,
|
||||
created_at=now,
|
||||
modified_at=now
|
||||
)
|
||||
Reference in New Issue
Block a user