import json import os from datetime import datetime from typing import Dict, List, Any, Optional from dataclasses import asdict, dataclass import pandas as pd # =============================================================== # CONFIG MANAGEMENT SYSTEM # =============================================================== @dataclass class SimulatorConfig: """Конфигурация симулятора для сохранения и загрузки""" name: str description: str created_at: str # Настройки генератора max_history_orders: int = 5 increment_difficulty: int = 2 energy_chance: int = 90 requirement_weights: str = "70,30" reduction_factor: int = 3 increase_factor: int = 5 # Симуляция iteration_count: int = 100 initial_energy: int = 10000 # Данные цепочек (JSON сериализованные) chain_data: List[Dict[str, Any]] = None energy_rewards_data: List[Dict[str, Any]] = None item_rewards_data: List[Dict[str, Any]] = None def to_dict(self) -> Dict[str, Any]: return asdict(self) @classmethod def from_dict(cls, data: Dict[str, Any]) -> 'SimulatorConfig': return cls(**data) class ConfigManager: """Менеджер конфигураций симулятора""" def __init__(self, config_dir: str = "configs"): self.config_dir = config_dir self.ensure_config_dir() def ensure_config_dir(self): """Создает директорию для конфигураций если её нет""" if not os.path.exists(self.config_dir): os.makedirs(self.config_dir) def save_config(self, config: SimulatorConfig) -> str: """Сохраняет конфигурацию в файл""" filename = f"{config.name.replace(' ', '_').lower()}_{datetime.now().strftime('%Y%m%d_%H%M%S')}.json" filepath = os.path.join(self.config_dir, filename) with open(filepath, 'w', encoding='utf-8') as f: json.dump(config.to_dict(), f, indent=2, ensure_ascii=False) return filepath def load_config(self, filepath: str) -> SimulatorConfig: """Загружает конфигурацию из файла""" with open(filepath, 'r', encoding='utf-8') as f: data = json.load(f) return SimulatorConfig.from_dict(data) def list_configs(self) -> List[Dict[str, str]]: """Возвращает список доступных конфигураций""" configs = [] if not os.path.exists(self.config_dir): return configs for filename in os.listdir(self.config_dir): if filename.endswith('.json'): filepath = os.path.join(self.config_dir, filename) try: config = self.load_config(filepath) configs.append({ 'name': config.name, 'description': config.description, 'created_at': config.created_at, 'filepath': filepath }) except Exception as e: print(f"Error loading config {filename}: {e}") return sorted(configs, key=lambda x: x['created_at'], reverse=True) def delete_config(self, filepath: str) -> bool: """Удаляет конфигурацию""" try: os.remove(filepath) return True except Exception as e: print(f"Error deleting config: {e}") return False def create_config_from_ui_state( name: str, description: str, chain_df, energy_rewards_df, item_rewards_df, max_history: int, increment_diff: int, energy_chance: int, req_weights: str, reduction_factor: int, increase_factor: int, iteration_count: int, initial_energy: int ) -> SimulatorConfig: """Создает конфигурацию из состояния UI""" # Преобразуем DataFrames в JSON-сериализуемые структуры chain_data = chain_df.to_dict('records') if chain_df is not None and not chain_df.empty else [] energy_rewards_data = energy_rewards_df.to_dict('records') if energy_rewards_df is not None and not energy_rewards_df.empty else [] item_rewards_data = item_rewards_df.to_dict('records') if item_rewards_df is not None and not item_rewards_df.empty else [] return SimulatorConfig( name=name, description=description, created_at=datetime.now().isoformat(), max_history_orders=max_history, increment_difficulty=increment_diff, energy_chance=energy_chance, requirement_weights=req_weights, reduction_factor=reduction_factor, increase_factor=increase_factor, iteration_count=iteration_count, initial_energy=initial_energy, chain_data=chain_data, energy_rewards_data=energy_rewards_data, item_rewards_data=item_rewards_data ) def apply_config_to_ui(config: SimulatorConfig): """Применяет конфигурацию к состоянию UI""" # Восстанавливаем DataFrames chain_df = pd.DataFrame(config.chain_data) if config.chain_data else pd.DataFrame(columns=['ChainId', 'MergeItemId', 'RequirementWeight', 'RewardDifficulty']) energy_rewards_df = pd.DataFrame(config.energy_rewards_data) if config.energy_rewards_data else pd.DataFrame(columns=['DifficultyScore', 'Amount']) item_rewards_df = pd.DataFrame(config.item_rewards_data) if config.item_rewards_data else pd.DataFrame(columns=['DifficultyScore', 'Amount', 'MergeItemId', 'RewardWeight', 'ReductionFactor']) return ( chain_df, config.max_history_orders, config.increment_difficulty, config.energy_chance, config.requirement_weights, config.reduction_factor, config.increase_factor, energy_rewards_df, item_rewards_df, config.iteration_count, config.initial_energy )