# Path: backend/components/clock.py
# class Clock:
#     """Holds actual time. 
#     Notifies about actual time
#     Notifies about week day"""
# 
#     _is_initialized = False
#     _instance = None
# 
#     def __new__(cls, *args, **kwargs):
#         if not cls._instance:
#             cls._instance = super().__new__(cls, *args, **kwargs)
#         return cls._instance
# 
#     def __init__(self, ):
#         if not Clock._is_initialized:
#             Clock._is_initialized = True
#             self.objects_to_notify_weekday = set()
#             self.objects_to_notify_time = set()
# 
#             self.now = None
#             self.minute = None
#             self.weekday = None
# 
#             self.system_start = time.time()
# 
#     def subscribe_for_weekday(self, who):
#         self.objects_to_notify_weekday.add(who)
# 
#     def subscribe_for_minute(self, who):
#         self.objects_to_notify_time.add(who)
# 
#     def notify_minute(self):
#         self.minute = self.now.minute
#         for _object in self.objects_to_notify_time:
#             _object.notify(self.now)
# 
#     def notify_weekday(self):
#         self.weekday = self.now.weekday()
#         for _object in self.objects_to_notify_weekday:
#             _object.notify(self.weekday)
# 
#     def evaluate_time(self, ):
#         """Evaluates current time. If minutes or day changes it notifies related objects"""
#         self.now = datetime.datetime.now()
#         
#         if self.now.minute != self.minute:
#             self.notify_minute()
# 
#         if self.weekday != self.now.weekday():
#             self.notify_weekday()
# 
#     def get_seconds(self):
#         return time.time() - self.system_start
# 
#     def get_millis(self):
#         return (time.time() - self.system_start)*1000
# 
#     def restart(self):
#         self.system_start = time.time()
# 
# Path: backend/components/element.py
# class Element(BaseComponent):
# 
#     table_name = "elements"
#     COL_MODULE_ID, COL_REG,  = 3, 4,
#     column_headers_and_types = BaseComponent.column_headers_and_types + [['module_id', 'integer'], ['register', 'integer']]
# 
#     items = {}
# 
#     def __init__(self, *args):
#         super().__init__(args[0], Et(args[1]), args[2])  # inicjalizuj id type, name
#         Element.items[self.id] = self        
#         self.value = None
#         self.module_id = args[Element.COL_MODULE_ID]
#         self.reg_id = args[Element.COL_REG]
#         self.objects_to_notify = set()
#         self.new_val_flag = False
# 
#     def subscribe(self, who):
#         self.objects_to_notify.add(who)
# 
#     def notify_objects(self, ):
#         for _object in self.objects_to_notify:
#             _object.notify(self.value)
# 
#     def __str__(self, ):
#         return "".join([super().__str__(), "\tvalue: ", str(self.value)])
# 
# class OutputElement(Element):
#  
#     types = {Et.led, Et.heater, Et.ventilator, Et.blind}
# 
#     defualt_priority = 15
#     items = {}
# 
#     def __init__(self, *args):
#         super().__init__(*args)
#         OutputElement.items[self.id] = self
#         self.desired_value = 0
#         self.setter_priority = OutputElement.defualt_priority  # Default priority can be overriden by everybody
# 
#     def set_desired_value(self, value, priority, set_flag=False):
# 
#         if priority <= self.setter_priority:
#             self.desired_value = value
# 
#             if set_flag:
#                 self.setter_priority = priority
#             else: 
#                 self.setter_priority = self.defualt_priority
# 
#             return True
# 
#         else:
#             return False
# 
#     def __str__(self, ):
#         return "".join([super().__str__(), "\tdesired_value: ", str(self.desired_value)])
# 
#     @staticmethod
#     def str():
#         string = "\n"
#         for element in OutputElement.items.values():
#             el_str = str(element) 
#             string += el_str + "\n"
# 
#         return string


import operator
from backend.components.clock import Clock
from backend.components.element import Element, OutputElement
                'sat': 5,
                'sun': 6, }
    clock = Clock()
    items = {}

    def __init__(self, _id, name, dep_str):
        self.id = _id
        Dependancy.items[self.id] = self

        self.name = name
        self.dep_str = dep_str
        self.conditions = []  # Conditions which make the cause
        self.effects = []     # Effects which will happen after condition changes from False to True

        self.num_of_conds = 0
        self.num_of_effect = 0

        self.prev_cause_result = False

        self.cause_str, self.effects_str = dep_str.split(Dependancy.cause_effect_sep)
        self.cause_template = ''  # evaluated conditions are applied to it. Finnally template goes to eval()
               
    def run(self, ):
        """Evaluates cause. If it is true and prev result is false it notifies all efects.
       When the cause changes from True to false it restores effects to initial state """
      
        cause_result = self._evaluate_cause()
        
        if cause_result and not self.prev_cause_result:  # if the cause changes from False to True
            for effect in self.effects:

# Path: backend/components/clock.py
# class Clock:
#     """Holds actual time. 
#     Notifies about actual time
#     Notifies about week day"""
# 
#     _is_initialized = False
#     _instance = None
# 
#     def __new__(cls, *args, **kwargs):
#         if not cls._instance:
#             cls._instance = super().__new__(cls, *args, **kwargs)
#         return cls._instance
# 
#     def __init__(self, ):
#         if not Clock._is_initialized:
#             Clock._is_initialized = True
#             self.objects_to_notify_weekday = set()
#             self.objects_to_notify_time = set()
# 
#             self.now = None
#             self.minute = None
#             self.weekday = None
# 
#             self.system_start = time.time()
# 
#     def subscribe_for_weekday(self, who):
#         self.objects_to_notify_weekday.add(who)
# 
#     def subscribe_for_minute(self, who):
#         self.objects_to_notify_time.add(who)
# 
#     def notify_minute(self):
#         self.minute = self.now.minute
#         for _object in self.objects_to_notify_time:
#             _object.notify(self.now)
# 
#     def notify_weekday(self):
#         self.weekday = self.now.weekday()
#         for _object in self.objects_to_notify_weekday:
#             _object.notify(self.weekday)
# 
#     def evaluate_time(self, ):
#         """Evaluates current time. If minutes or day changes it notifies related objects"""
#         self.now = datetime.datetime.now()
#         
#         if self.now.minute != self.minute:
#             self.notify_minute()
# 
#         if self.weekday != self.now.weekday():
#             self.notify_weekday()
# 
#     def get_seconds(self):
#         return time.time() - self.system_start
# 
#     def get_millis(self):
#         return (time.time() - self.system_start)*1000
# 
#     def restart(self):
#         self.system_start = time.time()
# 
# Path: backend/components/element.py
# class Element(BaseComponent):
# 
#     table_name = "elements"
#     COL_MODULE_ID, COL_REG,  = 3, 4,
#     column_headers_and_types = BaseComponent.column_headers_and_types + [['module_id', 'integer'], ['register', 'integer']]
# 
#     items = {}
# 
#     def __init__(self, *args):
#         super().__init__(args[0], Et(args[1]), args[2])  # inicjalizuj id type, name
#         Element.items[self.id] = self        
#         self.value = None
#         self.module_id = args[Element.COL_MODULE_ID]
#         self.reg_id = args[Element.COL_REG]
#         self.objects_to_notify = set()
#         self.new_val_flag = False
# 
#     def subscribe(self, who):
#         self.objects_to_notify.add(who)
# 
#     def notify_objects(self, ):
#         for _object in self.objects_to_notify:
#             _object.notify(self.value)
# 
#     def __str__(self, ):
#         return "".join([super().__str__(), "\tvalue: ", str(self.value)])
# 
# class OutputElement(Element):
#  
#     types = {Et.led, Et.heater, Et.ventilator, Et.blind}
# 
#     defualt_priority = 15
#     items = {}
# 
#     def __init__(self, *args):
#         super().__init__(*args)
#         OutputElement.items[self.id] = self
#         self.desired_value = 0
#         self.setter_priority = OutputElement.defualt_priority  # Default priority can be overriden by everybody
# 
#     def set_desired_value(self, value, priority, set_flag=False):
# 
#         if priority <= self.setter_priority:
#             self.desired_value = value
# 
#             if set_flag:
#                 self.setter_priority = priority
#             else: 
#                 self.setter_priority = self.defualt_priority
# 
#             return True
# 
#         else:
#             return False
# 
#     def __str__(self, ):
#         return "".join([super().__str__(), "\tdesired_value: ", str(self.desired_value)])
# 
#     @staticmethod
#     def str():
#         string = "\n"
#         for element in OutputElement.items.values():
#             el_str = str(element) 
#             string += el_str + "\n"
# 
#         return string


# Path: backend/components/dependancy.py
import operator
from backend.components.clock import Clock
from backend.components.element import Element, OutputElement

                'sat': 5,
                'sun': 6, }
    clock = Clock()
    items = {}

    def __init__(self, _id, name, dep_str):
        self.id = _id
        Dependancy.items[self.id] = self

        self.name = name
        self.dep_str = dep_str
        self.conditions = []  # Conditions which make the cause
        self.effects = []     # Effects which will happen after condition changes from False to True

        self.num_of_conds = 0
        self.num_of_effect = 0

        self.prev_cause_result = False

        self.cause_str, self.effects_str = dep_str.split(Dependancy.cause_effect_sep)
        self.cause_template = ''  # evaluated conditions are applied to it. Finnally template goes to eval()
               
    def run(self, ):
        """Evaluates cause. If it is true and prev result is false it notifies all efects.
       When the cause changes from True to false it restores effects to initial state """
      
        cause_result = self._evaluate_cause()
        
        if cause_result and not self.prev_cause_result:  # if the cause changes from False to True
            for effect in self.effects:

                effect.start(self.clock.get_millis())