class_name PRDConfigManager extends RefCounted ## Менеджер конфигурации для системы контроля ПРД ## Загружает и управляет настройками из JSON-конфигурации #region CONSTANTS const CONFIG_PATH = "user://config/setting_prd_control.json" const DEFAULT_CONFIG_PATH = "res://config/setting_prd_control.json" const CONFIG_VERSION = "1.0.0" # Версия конфигурации - увеличивать при изменениях #endregion #region PRIVATE_VARIABLES var _config_data: Dictionary # Все данные конфигурации var _device_constants: Dictionary # Константы устройств var _base_configs: Dictionary # Базовые конфигурации var _device_configs: Dictionary # Конфигурации устройств var _data_indices: Dictionary # Индексы данных var _fs_keys: Dictionary # Ключи ФС (функциональных систем) var _temperature_constants: Dictionary # Константы температуры var _ems_input_bits_config: Dictionary # Конфигурация битов ввода ЭМС var _fs_rules: Array # Правила ФС var _is_loaded: bool = false # Флаг успешной загрузки var _current_version: String = "" # Текущая версия загруженной конфигурации #endregion #region INITIALIZATION func _init() -> void: """Инициализация менеджера конфигурации""" _load_configuration() #endregion #region PUBLIC_API ## Проверяет, успешно ли загружена конфигурация func is_loaded() -> bool: return _is_loaded ## Возвращает текущую версию загруженной конфигурации func get_config_version() -> String: return _current_version ## Проверяет, актуальна ли конфигурация func is_config_up_to_date() -> bool: return _current_version == CONFIG_VERSION ## Возвращает все данные конфигурации func get_config_data() -> Dictionary: return _config_data.duplicate(true) ## Возвращает константы устройств func get_device_constants() -> Dictionary: return _device_constants.duplicate(true) ## Возвращает базовые конфигурации func get_base_configs() -> Dictionary: return _base_configs.duplicate(true) ## Возвращает конфигурации устройств func get_device_configs() -> Dictionary: return _device_configs.duplicate(true) ## Возвращает индексы данных func get_data_indices() -> Dictionary: return _data_indices.duplicate(true) ## Возвращает ключи ФС func get_fs_keys() -> Dictionary: return _fs_keys.duplicate(true) ## Возвращает константы температуры func get_temperature_constants() -> Dictionary: return _temperature_constants.duplicate(true) ## Возвращает конфигурацию битов ввода ЭМС func get_ems_input_bits_config() -> Dictionary: return _ems_input_bits_config.duplicate(true) ## Возвращает правила ФС func get_fs_rules() -> Array: return _fs_rules.duplicate(true) ## Возвращает индекс данных по ключу func get_data_index(key: String) -> int: return _data_indices.get(key, -1) #endregion #region PRIVATE_METHODS ## Загружает конфигурацию из JSON файла func _load_configuration() -> void: if not _ensure_config_exists(): _is_loaded = false return var config_file = FileAccess.open(CONFIG_PATH, FileAccess.READ) if config_file: var json_text = config_file.get_as_text() config_file.close() var json = JSON.new() var parse_result = json.parse(json_text) if parse_result == OK: _config_data = json.data _current_version = _config_data.get("config_version", "0.0.0") _parse_config_data() _is_loaded = true else: push_error("Ошибка разбора JSON конфигурации: " + json.get_error_message()) _is_loaded = false else: push_error("Ошибка загрузки файла конфигурации: " + CONFIG_PATH) _is_loaded = false ## Парсит данные конфигурации по секциям func _parse_config_data() -> void: _device_constants = _convert_numbers(_config_data.get("device_constants", {})) _base_configs = _convert_numbers(_config_data.get("base_configs", {})) _device_configs = _convert_numbers(_config_data.get("device_configs", {})) _data_indices = _convert_numbers(_config_data.get("data_indices", {})) _fs_keys = _convert_numbers(_config_data.get("fs_keys", {})) _temperature_constants = _convert_numbers(_config_data.get("temperature_constants", {})) _ems_input_bits_config = _convert_numbers(_config_data.get("ems_input_bits_config", {})) _fs_rules = _convert_numbers(_config_data.get("fs_rules", [])) ## Конвертирует числовые значения в правильные типы (float -> int если возможно) static func _convert_numbers(value): if value is float: # Конвертируем float в int если нет дробной части if value == int(value): return int(value) return value elif value is Dictionary: var result = {} for key in value: result[key] = _convert_numbers(value[key]) return result elif value is Array: var result = [] for item in value: result.append(_convert_numbers(item)) return result else: return value ## Обеспечивает существование файла конфигурации ## Создает папку и копирует дефолтный файл если нужно func _ensure_config_exists() -> bool: # Создаем папку конфигурации если не существует DirAccess.make_dir_recursive_absolute("user://config") # Проверяем, нужно ли обновить конфигурацию if _should_update_config(): return _update_config() # Если файл уже существует - все ок if FileAccess.file_exists(CONFIG_PATH): return true # Если дефолтного файла нет - ошибка if not FileAccess.file_exists(DEFAULT_CONFIG_PATH): return false # Копируем дефолтный конфиг в user директорию return _copy_default_config() ## Проверяет, нужно ли обновить конфигурацию func _should_update_config() -> bool: # Если файла конфигурации нет - нужно создать if not FileAccess.file_exists(CONFIG_PATH): return true # Проверяем версию существующей конфигурации var config_file = FileAccess.open(CONFIG_PATH, FileAccess.READ) if config_file: var json_text = config_file.get_as_text() config_file.close() var json = JSON.new() if json.parse(json_text) == OK: var existing_version = json.data.get("config_version", "0.0.0") # Сравниваем версии return _compare_versions(existing_version, CONFIG_VERSION) < 0 else: # Если ошибка парсинга - нужно обновить return true return false ## Сравнивает две версии (semantic versioning) ## Возвращает -1 если version1 < version2, 0 если равны, 1 если version1 > version2 static func _compare_versions(version1: String, version2: String) -> int: var v1_parts = version1.split(".") var v2_parts = version2.split(".") for i in range(max(v1_parts.size(), v2_parts.size())): var v1_part = int(v1_parts[i]) if i < v1_parts.size() else 0 var v2_part = int(v2_parts[i]) if i < v2_parts.size() else 0 if v1_part < v2_part: return -1 elif v1_part > v2_part: return 1 return 0 ## Обновляет конфигурацию до актуальной версии func _update_config() -> bool: # Создаем резервную копию старой конфигурации if FileAccess.file_exists(CONFIG_PATH): var backup_path = CONFIG_PATH + ".backup_v" + _current_version DirAccess.copy_absolute(CONFIG_PATH, backup_path) print("Создана резервная копия: ", backup_path) # Копируем актуальную конфигурацию return _copy_default_config() ## Копирует дефолтную конфигурацию в user директорию func _copy_default_config() -> bool: if not FileAccess.file_exists(DEFAULT_CONFIG_PATH): push_error("Дефолтный файл конфигурации не найден: " + DEFAULT_CONFIG_PATH) return false var src := FileAccess.open(DEFAULT_CONFIG_PATH, FileAccess.READ) var dst := FileAccess.open(CONFIG_PATH, FileAccess.WRITE) if src == null or dst == null: push_error("Ошибка копирования конфигурации") return false dst.store_string(src.get_as_text()) src.close() dst.close() return true #endregion