создан механизм для создания меню для разных сравнений через drap-and-drop

This commit is contained in:
2026-08-20 12:29:07 +03:00
parent 3f2d5caa4a
commit 81fd030846
6 changed files with 727 additions and 22 deletions

View File

@@ -34,9 +34,19 @@ DEFAULT_CONFIG: dict[str, Any] = {
"prematch_groups": [],
"prematch_buttons": [],
"quick_panel_selectors": [],
"player_selection_panels": [],
}
DEFAULT_HOCKEY_PLAYER_SELECTION_PANELS: list[dict[str, Any]] = [
{"id": "compare_home", "label": "Сравнение · левая команда", "description": "Два игрока левой команды", "slots": 2, "rule": "home", "sync_selected_player": False, "collapsed_default": True, "sort_order": 0, "enabled": True},
{"id": "compare_away", "label": "Сравнение · правая команда", "description": "Два игрока правой команды", "slots": 2, "rule": "away", "sync_selected_player": False, "collapsed_default": True, "sort_order": 10, "enabled": True},
{"id": "compare_mixed", "label": "Сравнение · разные команды", "description": "По одному игроку каждой команды", "slots": 2, "rule": "different_teams", "sync_selected_player": False, "collapsed_default": True, "sort_order": 20, "enabled": True},
{"id": "three_stars", "label": "3 звезды", "description": "Три игрока для финального титра", "slots": 3, "rule": "any", "sync_selected_player": False, "collapsed_default": True, "sort_order": 30, "enabled": True},
{"id": "selected_player", "label": "Выбранный игрок", "description": "Один игрок для подписи / индивидуального титра", "slots": 1, "rule": "any", "sync_selected_player": True, "collapsed_default": True, "sort_order": 40, "enabled": True},
]
class UIBuilderManager:
"""JSON settings storage with atomic writes and rolling backups."""
@@ -546,10 +556,49 @@ class UIBuilderManager:
"enabled": bool(selector.get("enabled", True)),
})
raw_player_selection_panels = config.get("player_selection_panels") if isinstance(config.get("player_selection_panels"), list) else None
if raw_player_selection_panels is None:
raw_player_selection_panels = deepcopy(DEFAULT_HOCKEY_PLAYER_SELECTION_PANELS) if ("player_selection_panels" not in config and UIBuilderManager._is_hockey_config(config)) else []
normalized_player_selection_panels: list[dict[str, Any]] = []
seen_player_panel_ids: set[str] = set()
allowed_player_panel_rules = {"any", "home", "away", "different_teams"}
for panel_index, panel in enumerate(raw_player_selection_panels[:16]):
if not isinstance(panel, dict):
continue
raw_id = re.sub(r"[^A-Za-z0-9_]+", "_", str(panel.get("id") or f"players_{panel_index + 1}").strip())[:48].strip("_")
panel_id = raw_id or f"players_{panel_index + 1}"
if not re.match(r"^[A-Za-z]", panel_id):
panel_id = f"p_{panel_id}"[:48]
base_id = panel_id
suffix = 2
while panel_id in seen_player_panel_ids:
panel_id = f"{base_id}_{suffix}"[:48]
suffix += 1
seen_player_panel_ids.add(panel_id)
try:
slots = max(1, min(6, int(panel.get("slots") or 1)))
except (TypeError, ValueError):
slots = 1
rule = str(panel.get("rule") or "any").strip().lower()
if rule not in allowed_player_panel_rules:
rule = "any"
normalized_player_selection_panels.append({
"id": panel_id,
"label": str(panel.get("label") or f"Игроки {panel_index + 1}")[:80],
"description": str(panel.get("description") or "")[:300],
"slots": slots,
"rule": rule,
"sync_selected_player": bool(panel.get("sync_selected_player", False)),
"collapsed_default": bool(panel.get("collapsed_default", True)),
"sort_order": int(panel.get("sort_order") if str(panel.get("sort_order", "")).lstrip("-").isdigit() else panel_index * 10),
"enabled": bool(panel.get("enabled", True)),
})
result["components"] = normalized_components
result["triggers"] = normalized_triggers
result["shortcut_sequences"] = normalized_shortcut_sequences
result["prematch_groups"] = sorted(normalized_prematch_groups, key=lambda item: (item["sort_order"], item["label"]))
result["prematch_buttons"] = sorted(normalized_prematch_buttons, key=lambda item: (item.get("group_id", ""), item["sort_order"], item["label"]))
result["quick_panel_selectors"] = sorted(normalized_quick_panel_selectors, key=lambda item: (item.get("group_id", ""), item["sort_order"], item["label"]))
result["player_selection_panels"] = sorted(normalized_player_selection_panels, key=lambda item: (item["sort_order"], item["label"]))
return result