simetri.helpers.modifiers

  1from random import random, choice
  2import inspect
  3
  4from ..graphics.all_enums import Control, State
  5
  6
  7class Modifier:
  8    """Used to modify the properties of a Batch object.
  9
 10    Attributes:
 11        function (callable): The function to modify the property.
 12        life_span (int): The number of times the modifier can be applied.
 13        randomness (float or callable): Determines the randomness of the modification.
 14        condition (bool or callable): Condition to apply the modification.
 15        state (State): The current state of the modifier.
 16        _d_state (dict): Mapping of control states to modifier states.
 17        count (int): Counter for the number of times the modifier has been applied.
 18        args (tuple): Additional arguments for the function.
 19        kwargs (dict): Additional keyword arguments for the function.
 20    """
 21
 22    def __init__(
 23        self, function, life_span=10000, randomness=1.0, condition=True, *args, **kwargs
 24    ):
 25        """
 26        Args:
 27            function (callable): The function to modify the property.
 28            life_span (int, optional): The number of times the modifier can be applied. Defaults to 10000.
 29            randomness (float or callable, optional): Determines the randomness of the modification. Defaults to 1.0.
 30            condition (bool or callable, optional): Condition to apply the modification. Defaults to True.
 31            *args: Additional arguments for the function.
 32            **kwargs: Additional keyword arguments for the function.
 33        """
 34        self.function = function  # it can be a list of functions
 35        signature = inspect.signature(function)
 36        self.n_func_args = len(signature.parameters)
 37        self.life_span = life_span
 38        self.randomness = randomness
 39        self.condition = condition
 40        self.state = State.INITIAL
 41        self._d_state = {
 42            Control.INITIAL: State.INITIAL,
 43            Control.STOP: State.STOPPED,
 44            Control.PAUSE: State.PAUSED,
 45            Control.RESUME: State.RUNNING,
 46            Control.RESTART: State.RESTARTING,
 47        }
 48        self.count = 0
 49        self.args = args
 50        self.kwargs = kwargs
 51
 52    def __repr__(self):
 53        """Returns a string representation of the Modifier object.
 54
 55        Returns:
 56            str: String representation of the Modifier object.
 57        """
 58        return (
 59            f"Modifier(function:{self.function}, lifespan:{self.life_span},"
 60            f"randomness:{self.randomness})"
 61        )
 62
 63    def __str__(self):
 64        """Returns a string representation of the Modifier object.
 65
 66        Returns:
 67            str: String representation of the Modifier object.
 68        """
 69        return self.__repr__()
 70
 71    def set_state(self, control):
 72        """Sets the state of the modifier based on the control value.
 73
 74        Args:
 75            control (Control): The control value to set the state.
 76        """
 77        self.state = self._d_state[control]
 78
 79    def get_value(self, obj, target, *args, **kwargs):
 80        """Gets the value from an object or callable.
 81
 82        Args:
 83            obj (object or callable): The object or callable to get the value from.
 84            target (object): The target object.
 85            *args: Additional arguments for the callable.
 86            **kwargs: Additional keyword arguments for the callable.
 87
 88        Returns:
 89            object: The value obtained from the object or callable.
 90        """
 91        if callable(obj):
 92            res = obj(target, *args, **kwargs)
 93            if res in Control:
 94                self.set_state(res)
 95        else:
 96            res = obj
 97        return res
 98
 99    def apply(self, element):
100        """Applies the modifier to an element.
101
102        If a function returns a control value, it will be applied to the modifier.
103        Control.STOP, Control.PAUSE, Control.RESUME, and Control.RESTART are the only control values.
104        Functions should have the following signature:
105        def funct(target, modifier, *args, **kwargs):
106
107        Args:
108            element (object): The element to apply the modifier to.
109        """
110        if self.can_continue(element):
111            if self.n_func_args == 1:
112                self.function(element)
113            else:
114                self.function(element, self, *self.args, **self.kwargs)
115            self._update_state()
116        else:
117            self.state = State.STOPPED
118
119    def can_continue(self, target):
120        """Checks if the modifier can continue to be applied.
121
122        Args:
123            target (object): The target object.
124
125        Returns:
126            bool: True if the modifier can continue, False otherwise.
127        """
128        if callable(self.randomness):
129            randomness = self.get_value(self.randomness, target)
130        elif type(self.randomness) == float:
131            randomness = self.randomness >= random()
132        elif type(self.randomness) in [list, tuple]:
133            randomness = choice(self.randomness)
134
135        if callable(self.condition):
136            condition = self.get_value(self.condition, target)
137        else:
138            condition = self.condition
139
140        if callable(self.life_span):
141            life_span = self.get_value(self.life_span, target)
142        else:
143            life_span = self.life_span
144
145        if life_span > 0 and condition and randomness:
146            if self.state in [State.INITIAL, State.RUNNING, State.RESTARTING]:
147                res = True
148            else:
149                res = False
150        else:
151            res = False
152        return res
153
154    def _update_state(self):
155        """Updates the state of the modifier based on its life span and count."""
156        self.count += 1
157        if self.count == 1:
158            self.state = State.RUNNING
159        if self.life_span > 0:
160            if self.state == State.RESTARTING:
161                self.state = State.RUNNING
162            elif self.state == State.RUNNING:
163                self.life_span -= 1
164                if self.life_span == 0:
165                    self.state = State.STOPPED
166        else:
167            self.state = State.STOPPED
168
169    def stop(self):
170        """Stops the modifier."""
171        self.state = State.STOPPED
class Modifier:
  8class Modifier:
  9    """Used to modify the properties of a Batch object.
 10
 11    Attributes:
 12        function (callable): The function to modify the property.
 13        life_span (int): The number of times the modifier can be applied.
 14        randomness (float or callable): Determines the randomness of the modification.
 15        condition (bool or callable): Condition to apply the modification.
 16        state (State): The current state of the modifier.
 17        _d_state (dict): Mapping of control states to modifier states.
 18        count (int): Counter for the number of times the modifier has been applied.
 19        args (tuple): Additional arguments for the function.
 20        kwargs (dict): Additional keyword arguments for the function.
 21    """
 22
 23    def __init__(
 24        self, function, life_span=10000, randomness=1.0, condition=True, *args, **kwargs
 25    ):
 26        """
 27        Args:
 28            function (callable): The function to modify the property.
 29            life_span (int, optional): The number of times the modifier can be applied. Defaults to 10000.
 30            randomness (float or callable, optional): Determines the randomness of the modification. Defaults to 1.0.
 31            condition (bool or callable, optional): Condition to apply the modification. Defaults to True.
 32            *args: Additional arguments for the function.
 33            **kwargs: Additional keyword arguments for the function.
 34        """
 35        self.function = function  # it can be a list of functions
 36        signature = inspect.signature(function)
 37        self.n_func_args = len(signature.parameters)
 38        self.life_span = life_span
 39        self.randomness = randomness
 40        self.condition = condition
 41        self.state = State.INITIAL
 42        self._d_state = {
 43            Control.INITIAL: State.INITIAL,
 44            Control.STOP: State.STOPPED,
 45            Control.PAUSE: State.PAUSED,
 46            Control.RESUME: State.RUNNING,
 47            Control.RESTART: State.RESTARTING,
 48        }
 49        self.count = 0
 50        self.args = args
 51        self.kwargs = kwargs
 52
 53    def __repr__(self):
 54        """Returns a string representation of the Modifier object.
 55
 56        Returns:
 57            str: String representation of the Modifier object.
 58        """
 59        return (
 60            f"Modifier(function:{self.function}, lifespan:{self.life_span},"
 61            f"randomness:{self.randomness})"
 62        )
 63
 64    def __str__(self):
 65        """Returns a string representation of the Modifier object.
 66
 67        Returns:
 68            str: String representation of the Modifier object.
 69        """
 70        return self.__repr__()
 71
 72    def set_state(self, control):
 73        """Sets the state of the modifier based on the control value.
 74
 75        Args:
 76            control (Control): The control value to set the state.
 77        """
 78        self.state = self._d_state[control]
 79
 80    def get_value(self, obj, target, *args, **kwargs):
 81        """Gets the value from an object or callable.
 82
 83        Args:
 84            obj (object or callable): The object or callable to get the value from.
 85            target (object): The target object.
 86            *args: Additional arguments for the callable.
 87            **kwargs: Additional keyword arguments for the callable.
 88
 89        Returns:
 90            object: The value obtained from the object or callable.
 91        """
 92        if callable(obj):
 93            res = obj(target, *args, **kwargs)
 94            if res in Control:
 95                self.set_state(res)
 96        else:
 97            res = obj
 98        return res
 99
100    def apply(self, element):
101        """Applies the modifier to an element.
102
103        If a function returns a control value, it will be applied to the modifier.
104        Control.STOP, Control.PAUSE, Control.RESUME, and Control.RESTART are the only control values.
105        Functions should have the following signature:
106        def funct(target, modifier, *args, **kwargs):
107
108        Args:
109            element (object): The element to apply the modifier to.
110        """
111        if self.can_continue(element):
112            if self.n_func_args == 1:
113                self.function(element)
114            else:
115                self.function(element, self, *self.args, **self.kwargs)
116            self._update_state()
117        else:
118            self.state = State.STOPPED
119
120    def can_continue(self, target):
121        """Checks if the modifier can continue to be applied.
122
123        Args:
124            target (object): The target object.
125
126        Returns:
127            bool: True if the modifier can continue, False otherwise.
128        """
129        if callable(self.randomness):
130            randomness = self.get_value(self.randomness, target)
131        elif type(self.randomness) == float:
132            randomness = self.randomness >= random()
133        elif type(self.randomness) in [list, tuple]:
134            randomness = choice(self.randomness)
135
136        if callable(self.condition):
137            condition = self.get_value(self.condition, target)
138        else:
139            condition = self.condition
140
141        if callable(self.life_span):
142            life_span = self.get_value(self.life_span, target)
143        else:
144            life_span = self.life_span
145
146        if life_span > 0 and condition and randomness:
147            if self.state in [State.INITIAL, State.RUNNING, State.RESTARTING]:
148                res = True
149            else:
150                res = False
151        else:
152            res = False
153        return res
154
155    def _update_state(self):
156        """Updates the state of the modifier based on its life span and count."""
157        self.count += 1
158        if self.count == 1:
159            self.state = State.RUNNING
160        if self.life_span > 0:
161            if self.state == State.RESTARTING:
162                self.state = State.RUNNING
163            elif self.state == State.RUNNING:
164                self.life_span -= 1
165                if self.life_span == 0:
166                    self.state = State.STOPPED
167        else:
168            self.state = State.STOPPED
169
170    def stop(self):
171        """Stops the modifier."""
172        self.state = State.STOPPED

Used to modify the properties of a Batch object.

Attributes:
  • function (callable): The function to modify the property.
  • life_span (int): The number of times the modifier can be applied.
  • randomness (float or callable): Determines the randomness of the modification.
  • condition (bool or callable): Condition to apply the modification.
  • state (State): The current state of the modifier.
  • _d_state (dict): Mapping of control states to modifier states.
  • count (int): Counter for the number of times the modifier has been applied.
  • args (tuple): Additional arguments for the function.
  • kwargs (dict): Additional keyword arguments for the function.
Modifier( function, life_span=10000, randomness=1.0, condition=True, *args, **kwargs)
23    def __init__(
24        self, function, life_span=10000, randomness=1.0, condition=True, *args, **kwargs
25    ):
26        """
27        Args:
28            function (callable): The function to modify the property.
29            life_span (int, optional): The number of times the modifier can be applied. Defaults to 10000.
30            randomness (float or callable, optional): Determines the randomness of the modification. Defaults to 1.0.
31            condition (bool or callable, optional): Condition to apply the modification. Defaults to True.
32            *args: Additional arguments for the function.
33            **kwargs: Additional keyword arguments for the function.
34        """
35        self.function = function  # it can be a list of functions
36        signature = inspect.signature(function)
37        self.n_func_args = len(signature.parameters)
38        self.life_span = life_span
39        self.randomness = randomness
40        self.condition = condition
41        self.state = State.INITIAL
42        self._d_state = {
43            Control.INITIAL: State.INITIAL,
44            Control.STOP: State.STOPPED,
45            Control.PAUSE: State.PAUSED,
46            Control.RESUME: State.RUNNING,
47            Control.RESTART: State.RESTARTING,
48        }
49        self.count = 0
50        self.args = args
51        self.kwargs = kwargs
Arguments:
  • function (callable): The function to modify the property.
  • life_span (int, optional): The number of times the modifier can be applied. Defaults to 10000.
  • randomness (float or callable, optional): Determines the randomness of the modification. Defaults to 1.0.
  • condition (bool or callable, optional): Condition to apply the modification. Defaults to True.
  • *args: Additional arguments for the function.
  • **kwargs: Additional keyword arguments for the function.
function
n_func_args
life_span
randomness
condition
state
count
args
kwargs
def set_state(self, control):
72    def set_state(self, control):
73        """Sets the state of the modifier based on the control value.
74
75        Args:
76            control (Control): The control value to set the state.
77        """
78        self.state = self._d_state[control]

Sets the state of the modifier based on the control value.

Arguments:
  • control (Control): The control value to set the state.
def get_value(self, obj, target, *args, **kwargs):
80    def get_value(self, obj, target, *args, **kwargs):
81        """Gets the value from an object or callable.
82
83        Args:
84            obj (object or callable): The object or callable to get the value from.
85            target (object): The target object.
86            *args: Additional arguments for the callable.
87            **kwargs: Additional keyword arguments for the callable.
88
89        Returns:
90            object: The value obtained from the object or callable.
91        """
92        if callable(obj):
93            res = obj(target, *args, **kwargs)
94            if res in Control:
95                self.set_state(res)
96        else:
97            res = obj
98        return res

Gets the value from an object or callable.

Arguments:
  • obj (object or callable): The object or callable to get the value from.
  • target (object): The target object.
  • *args: Additional arguments for the callable.
  • **kwargs: Additional keyword arguments for the callable.
Returns:

object: The value obtained from the object or callable.

def apply(self, element):
100    def apply(self, element):
101        """Applies the modifier to an element.
102
103        If a function returns a control value, it will be applied to the modifier.
104        Control.STOP, Control.PAUSE, Control.RESUME, and Control.RESTART are the only control values.
105        Functions should have the following signature:
106        def funct(target, modifier, *args, **kwargs):
107
108        Args:
109            element (object): The element to apply the modifier to.
110        """
111        if self.can_continue(element):
112            if self.n_func_args == 1:
113                self.function(element)
114            else:
115                self.function(element, self, *self.args, **self.kwargs)
116            self._update_state()
117        else:
118            self.state = State.STOPPED

Applies the modifier to an element.

If a function returns a control value, it will be applied to the modifier. Control.STOP, Control.PAUSE, Control.RESUME, and Control.RESTART are the only control values. Functions should have the following signature: def funct(target, modifier, args, *kwargs):

Arguments:
  • element (object): The element to apply the modifier to.
def can_continue(self, target):
120    def can_continue(self, target):
121        """Checks if the modifier can continue to be applied.
122
123        Args:
124            target (object): The target object.
125
126        Returns:
127            bool: True if the modifier can continue, False otherwise.
128        """
129        if callable(self.randomness):
130            randomness = self.get_value(self.randomness, target)
131        elif type(self.randomness) == float:
132            randomness = self.randomness >= random()
133        elif type(self.randomness) in [list, tuple]:
134            randomness = choice(self.randomness)
135
136        if callable(self.condition):
137            condition = self.get_value(self.condition, target)
138        else:
139            condition = self.condition
140
141        if callable(self.life_span):
142            life_span = self.get_value(self.life_span, target)
143        else:
144            life_span = self.life_span
145
146        if life_span > 0 and condition and randomness:
147            if self.state in [State.INITIAL, State.RUNNING, State.RESTARTING]:
148                res = True
149            else:
150                res = False
151        else:
152            res = False
153        return res

Checks if the modifier can continue to be applied.

Arguments:
  • target (object): The target object.
Returns:

bool: True if the modifier can continue, False otherwise.

def stop(self):
170    def stop(self):
171        """Stops the modifier."""
172        self.state = State.STOPPED

Stops the modifier.