plate-config-app/app/services/light_modes_service.py

90 lines
3.0 KiB
Python
Raw Permalink 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.

"""Сервис загрузки конфигураций подсветки из .lm файлов (TOML-формат).
Папка light_modes/ лежит рядом с исполняемым файлом (или рядом с main.py
при разработке). Каждый .lm файл описывает один игровой проект и содержит:
- base_command — базовая команда (например "85", "8")
- has_duration — (опционально) true если формат XXYY (XX=эффект, YY=время)
- [[effects]] — список эффектов с полями code (int) и name (str)
"""
from __future__ import annotations
import sys
import tomllib
from dataclasses import dataclass, field
from pathlib import Path
@dataclass
class LightEffect:
"""Один эффект подсветки."""
code: int
name: str
@dataclass
class LightMode:
"""Конфигурация подсветки для одного игрового проекта."""
project_name: str
base_command: str
has_duration: bool = False
effects: list[LightEffect] = field(default_factory=list)
def _get_light_modes_dir() -> Path:
"""Определить путь к папке light_modes/.
При запуске из .exe (PyInstaller) — рядом с exe-файлом.
При запуске из исходников — рядом с корнем проекта.
"""
if getattr(sys, "frozen", False):
base = Path(sys.executable).parent
else:
base = Path(__file__).resolve().parent.parent.parent
return base / "light_modes"
def load_light_mode(path: Path) -> LightMode | None:
"""Загрузить один .lm файл. Возвращает None при ошибке."""
try:
data = tomllib.loads(path.read_text(encoding="utf-8"))
except Exception:
return None
base_command = data.get("base_command", "")
has_duration = data.get("has_duration", False)
effects: list[LightEffect] = []
for entry in data.get("effects", []):
code = entry.get("code")
name = entry.get("name", "")
if code is not None:
effects.append(LightEffect(code=int(code), name=str(name)))
project_name = path.stem # имя файла без расширения
return LightMode(
project_name=project_name,
base_command=str(base_command),
has_duration=bool(has_duration),
effects=effects,
)
def load_all_light_modes() -> list[LightMode]:
"""Загрузить все .lm файлы из папки light_modes/."""
modes_dir = _get_light_modes_dir()
if not modes_dir.is_dir():
return []
modes: list[LightMode] = []
for lm_file in sorted(modes_dir.glob("*.lm")):
mode = load_light_mode(lm_file)
if mode is not None:
modes.append(mode)
return modes
def get_light_modes_dir() -> Path:
"""Публичный доступ к пути папки (для UI «Открыть папку»)."""
return _get_light_modes_dir()