Files
uarep-ctl/scripts/prd-ctl-config.gd
Maxim 42ed766c58 Merge remote-tracking branch 'sasha80/master' into workflows
# Conflicts:
#	scripts/prd-ctl-config.gd
2026-02-02 10:25:45 +03:00

240 lines
9.5 KiB
GDScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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)
# Копируем актуальную конфигурацию
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