MergeBalanceTools / config_manager.py
aigurletov's picture
mcp
18cbfa9
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
)