| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254 |
- # -*- coding: utf-8 -*-
- """
- Composite Conditions - Kombiniert mehrere Conditions.
- """
- from typing import Any
- from trixy_core.scheduler.condition.base import Condition
- class AndCondition(Condition):
- """
- Prüft ob ALLE Sub-Conditions erfüllt sind.
- Beispiel:
- - AndCondition([TimeRangeCondition(...), DayOfWeekCondition(...)])
- """
- def __init__(
- self,
- conditions: list[Condition],
- name: str | None = None,
- invert: bool = False,
- ):
- """
- Initialisiert die Condition.
- Args:
- conditions: Liste von Sub-Conditions
- name: Condition-Name
- invert: Ergebnis invertieren
- """
- super().__init__(name, invert)
- if not conditions:
- raise ValueError("AndCondition benötigt mindestens eine Condition")
- self._conditions = list(conditions)
- @property
- def conditions(self) -> list[Condition]:
- """Sub-Conditions."""
- return list(self._conditions)
- def add_condition(self, condition: Condition) -> None:
- """Fügt Condition hinzu."""
- self._conditions.append(condition)
- def remove_condition(self, condition: Condition) -> bool:
- """Entfernt Condition."""
- try:
- self._conditions.remove(condition)
- return True
- except ValueError:
- return False
- def _evaluate(self, context: dict) -> bool:
- """Prüft ob alle Conditions erfüllt sind."""
- if not self._conditions:
- return True
- return all(c.evaluate(context) for c in self._conditions)
- @classmethod
- def display_name(cls) -> str:
- """Anzeigename fuer die TUI."""
- return "UND-Bedingung"
- def to_dict(self) -> dict:
- """Konvertiert zu Dictionary."""
- return {
- **self._base_dict(),
- "conditions": [c.to_dict() for c in self._conditions],
- }
- class OrCondition(Condition):
- """
- Prüft ob MINDESTENS EINE Sub-Condition erfüllt ist.
- Beispiel:
- - OrCondition([StateCondition(...), BooleanCondition(...)])
- """
- def __init__(
- self,
- conditions: list[Condition],
- name: str | None = None,
- invert: bool = False,
- ):
- """
- Initialisiert die Condition.
- Args:
- conditions: Liste von Sub-Conditions
- name: Condition-Name
- invert: Ergebnis invertieren
- """
- super().__init__(name, invert)
- if not conditions:
- raise ValueError("OrCondition benötigt mindestens eine Condition")
- self._conditions = list(conditions)
- self._matched_condition: Condition | None = None
- @property
- def conditions(self) -> list[Condition]:
- """Sub-Conditions."""
- return list(self._conditions)
- @property
- def matched_condition(self) -> Condition | None:
- """Zuletzt gematchte Condition."""
- return self._matched_condition
- def add_condition(self, condition: Condition) -> None:
- """Fügt Condition hinzu."""
- self._conditions.append(condition)
- def remove_condition(self, condition: Condition) -> bool:
- """Entfernt Condition."""
- try:
- self._conditions.remove(condition)
- return True
- except ValueError:
- return False
- def _evaluate(self, context: dict) -> bool:
- """Prüft ob mindestens eine Condition erfüllt ist."""
- if not self._conditions:
- return False
- for condition in self._conditions:
- if condition.evaluate(context):
- self._matched_condition = condition
- return True
- self._matched_condition = None
- return False
- @classmethod
- def display_name(cls) -> str:
- """Anzeigename fuer die TUI."""
- return "ODER-Bedingung"
- def to_dict(self) -> dict:
- """Konvertiert zu Dictionary."""
- return {
- **self._base_dict(),
- "conditions": [c.to_dict() for c in self._conditions],
- }
- class NotCondition(Condition):
- """
- Invertiert eine Condition.
- Beispiel:
- - NotCondition(StateCondition("system_mode", "maintenance"))
- → Nur wenn NICHT im Wartungsmodus
- Hinweis: Kann auch über invert=True bei anderen Conditions erreicht werden.
- """
- def __init__(
- self,
- condition: Condition,
- name: str | None = None,
- ):
- """
- Initialisiert die Condition.
- Args:
- condition: Zu invertierende Condition
- name: Condition-Name
- """
- # NOT Condition hat kein eigenes invert
- super().__init__(name, invert=False)
- self._condition = condition
- @property
- def condition(self) -> Condition:
- """Innere Condition."""
- return self._condition
- def _evaluate(self, context: dict) -> bool:
- """Invertiert das Ergebnis der inneren Condition."""
- return not self._condition.evaluate(context)
- @classmethod
- def display_name(cls) -> str:
- """Anzeigename fuer die TUI."""
- return "NICHT-Bedingung"
- def to_dict(self) -> dict:
- """Konvertiert zu Dictionary."""
- return {
- **self._base_dict(),
- "condition": self._condition.to_dict(),
- }
- class XorCondition(Condition):
- """
- Prüft ob GENAU EINE Sub-Condition erfüllt ist.
- Beispiel:
- - XorCondition([ConditionA, ConditionB])
- → Nur wenn A oder B, aber nicht beide
- """
- def __init__(
- self,
- conditions: list[Condition],
- name: str | None = None,
- invert: bool = False,
- ):
- """
- Initialisiert die Condition.
- Args:
- conditions: Liste von Sub-Conditions
- name: Condition-Name
- invert: Ergebnis invertieren
- """
- super().__init__(name, invert)
- if len(conditions) < 2:
- raise ValueError("XorCondition benötigt mindestens zwei Conditions")
- self._conditions = list(conditions)
- @property
- def conditions(self) -> list[Condition]:
- """Sub-Conditions."""
- return list(self._conditions)
- @classmethod
- def display_name(cls) -> str:
- """Anzeigename fuer die TUI."""
- return "XOR-Bedingung"
- def _evaluate(self, context: dict) -> bool:
- """Prüft ob genau eine Condition erfüllt ist."""
- results = [c.evaluate(context) for c in self._conditions]
- return sum(results) == 1
- def to_dict(self) -> dict:
- """Konvertiert zu Dictionary."""
- return {
- **self._base_dict(),
- "conditions": [c.to_dict() for c in self._conditions],
- }
|