Spaces:
Paused
Paused
| from __future__ import annotations | |
| import re | |
| from dataclasses import dataclass | |
| from typing import Iterable | |
| _SPLIT_RE = re.compile(r"[,;\n\r]+") | |
| _VALUE_PREFIXES = ( | |
| "dynamic_analog", | |
| "dynamic_string", | |
| "dynamic_level", | |
| "dynamic_dict", | |
| "dynamic_equipment_dict", | |
| ) | |
| _INDICATOR_PREFIXES = ( | |
| "dynamic_status", | |
| "dynamic_asutp_status_indicator", | |
| ) | |
| def split_visual_names(value: object) -> list[str]: | |
| parts = [ | |
| part.strip() | |
| for part in _SPLIT_RE.split(str(value or "")) | |
| if part and part.strip() | |
| ] | |
| seen: set[str] = set() | |
| ordered: list[str] = [] | |
| for part in parts: | |
| key = part.lower() | |
| if key in seen: | |
| continue | |
| seen.add(key) | |
| ordered.append(part) | |
| return ordered | |
| def _normalized_static_names(known_static_names: Iterable[str] | None = None) -> set[str]: | |
| return { | |
| str(name or "").strip().lower() | |
| for name in (known_static_names or ()) | |
| if str(name or "").strip() | |
| } | |
| def visual_name_role(name: str, *, known_static_names: Iterable[str] | None = None) -> str: | |
| normalized = str(name or "").strip().lower() | |
| if not normalized: | |
| return "other" | |
| known_statics = _normalized_static_names(known_static_names) | |
| if normalized in known_statics: | |
| return "static" | |
| if any(normalized.startswith(prefix) for prefix in _INDICATOR_PREFIXES): | |
| return "indicator" | |
| if any(normalized.startswith(prefix) for prefix in _VALUE_PREFIXES): | |
| return "value" | |
| if normalized.startswith("dynamic_"): | |
| return "equipment_widget" | |
| return "static" | |
| class VisualSpec: | |
| ordered: tuple[str, ...] | |
| statics: tuple[str, ...] | |
| value_widgets: tuple[str, ...] | |
| indicator_widgets: tuple[str, ...] | |
| equipment_widgets: tuple[str, ...] | |
| def widgets(self) -> tuple[str, ...]: | |
| return self.value_widgets + self.indicator_widgets + self.equipment_widgets | |
| def is_composite(self) -> bool: | |
| return bool(self.statics) and bool(self.widgets) | |
| def primary_category(self) -> str: | |
| if self.value_widgets: | |
| return "value" | |
| if self.indicator_widgets: | |
| return "indicator" | |
| if self.statics or self.equipment_widgets: | |
| return "equipment" | |
| return "other" | |
| def parse_visual_spec(value: object, *, known_static_names: Iterable[str] | None = None) -> VisualSpec: | |
| ordered = split_visual_names(value) | |
| statics: list[str] = [] | |
| value_widgets: list[str] = [] | |
| indicator_widgets: list[str] = [] | |
| equipment_widgets: list[str] = [] | |
| for part in ordered: | |
| role = visual_name_role(part, known_static_names=known_static_names) | |
| if role == "static": | |
| statics.append(part) | |
| elif role == "value": | |
| value_widgets.append(part) | |
| elif role == "indicator": | |
| indicator_widgets.append(part) | |
| elif role == "equipment_widget": | |
| equipment_widgets.append(part) | |
| return VisualSpec( | |
| ordered=tuple(ordered), | |
| statics=tuple(statics), | |
| value_widgets=tuple(value_widgets), | |
| indicator_widgets=tuple(indicator_widgets), | |
| equipment_widgets=tuple(equipment_widgets), | |
| ) | |