# Path: controller/actor.py
# class PoupoolModel(Machine):
# 
#     def __init__(self, *args, **kwargs):
#         kwargs.setdefault("before_state_change", []).extend(["do_cancel", self.__update_state_time])
#         super().__init__(
#             auto_transitions=False,
#             ignore_invalid_triggers=True,
#             *args,
#             **kwargs
#         )
#         self.__state_time = None
# 
#     def __update_state_time(self):
#         self.__state_time = datetime.now()
# 
#     def get_time_in_state(self):
#         return datetime.now() - self.__state_time
# 
# Path: controller/actor.py
# class PoupoolActor(pykka.ThreadingActor):
# 
#     def __init__(self):
#         super().__init__()
#         self._proxy = self.actor_ref.proxy()
#         self.__timer = None
# 
#     def on_failure(self, exception_type, exception_value, traceback):
#         # The actor is going to die
#         logger.fatal(exception_type, exception_value, traceback)
# 
#     def on_stop(self):
#         self.do_cancel()
# 
#     def get_actor(self, name):
#         fsm = pykka.ActorRegistry.get_by_class_name(name)
#         if fsm:
#             return fsm[0].proxy()
#         logger.critical("Actor %s not found!!!" % name)
#         return None
# 
#     def __do_cancel(self):
#         if self.__timer:
#             self.__timer.cancel()
#             self.__timer = None
# 
#     def do_cancel(self):
#         self.__do_cancel()
# 
#     def do_delay(self, delay, method, *args, **kwargs):
#         assert type(method) == str
#         assert delay >= 0
#         # Stop an already running timer
#         self.__do_cancel()
#         func = getattr(self._proxy, method)
#         if delay > 0:
#             self.__timer = Timer(delay, func.defer, *args, **kwargs)
#             self.__timer.start()
#         else:
#             func.defer(*args, **kwargs)
# 
# Path: controller/util.py
# def constrain(x, out_min, out_max):
#     return min(max(x, out_min), out_max)
# 
# class Timer(object):
# 
#     def __init__(self, name):
#         self.__duration = timedelta()
#         self.__name = name
#         self.__last = None
#         self.__last_print = datetime(2000, 1, 1)
#         self.__delay = timedelta()
# 
#     @property
#     def duration(self):
#         return self.__duration
# 
#     @duration.setter
#     def duration(self, value):
#         self.__duration = value
# 
#     @property
#     def remaining(self):
#         return max(timedelta(), self.__delay - self.__duration)
# 
#     @property
#     def delay(self):
#         return self.__delay
# 
#     @delay.setter
#     def delay(self, value):
#         self.__delay = value
#         self.reset()
# 
#     def clear(self):
#         self.__last = None
# 
#     def reset(self):
#         self.clear()
#         self.__duration = timedelta()
# 
#     def update(self, now, factor=1):
#         if self.__last is not None:
#             self.__duration += factor * (now - self.__last)
#             remaining = max(timedelta(), self.delay - self.__duration)
#             if self.__last_print + timedelta(seconds=20) <= now:
#                 logger.debug("(%s) Timer: %s Remaining: %s" %
#                              (self.__name, self.__duration, remaining))
#                 self.__last_print = now
#         self.__last = now
# 
#     def elapsed(self):
#         return self.__duration >= self.__delay
# 
# Path: controller/config.py
# class Config:
#     def __init__(self, config_files):
#     def __getitem__(self, pair):
# def as_list(value, type_cast=int):


import time
import logging
from datetime import datetime, timedelta
from .actor import PoupoolModel
from .actor import PoupoolActor
from .util import constrain, Timer
from .config import config
                    self.__duration = 0
                    self.__state = False
                    self.__pump.off()
            else:
                self.__security_duration.update(datetime.now(), 0)
                security_ok = not self.__security_duration.elapsed()
                if self.__duration >= duty_off and duty_off != self.period and security_ok:
                    self.__duration = 0
                    self.__state = True
                    self.__pump.on()
        if datetime.now() > self.__security_reset:
            self.__security_duration.reset()
            self.__security_reset += timedelta(days=1)
        self.__last = now
        self.do_delay(1, self.do_run.__name__)


class PController(object):

    def __init__(self, pterm=0.1, scale=1.0):
        self.setpoint = 0
        self.current = 0
        self.pterm = pterm
        self.__scale = scale

    def compute(self):
        error = self.setpoint - self.current
        return constrain((self.pterm * self.__scale) * error, 0, 1)



# Path: controller/actor.py
# class PoupoolModel(Machine):
# 
#     def __init__(self, *args, **kwargs):
#         kwargs.setdefault("before_state_change", []).extend(["do_cancel", self.__update_state_time])
#         super().__init__(
#             auto_transitions=False,
#             ignore_invalid_triggers=True,
#             *args,
#             **kwargs
#         )
#         self.__state_time = None
# 
#     def __update_state_time(self):
#         self.__state_time = datetime.now()
# 
#     def get_time_in_state(self):
#         return datetime.now() - self.__state_time
# 
# Path: controller/actor.py
# class PoupoolActor(pykka.ThreadingActor):
# 
#     def __init__(self):
#         super().__init__()
#         self._proxy = self.actor_ref.proxy()
#         self.__timer = None
# 
#     def on_failure(self, exception_type, exception_value, traceback):
#         # The actor is going to die
#         logger.fatal(exception_type, exception_value, traceback)
# 
#     def on_stop(self):
#         self.do_cancel()
# 
#     def get_actor(self, name):
#         fsm = pykka.ActorRegistry.get_by_class_name(name)
#         if fsm:
#             return fsm[0].proxy()
#         logger.critical("Actor %s not found!!!" % name)
#         return None
# 
#     def __do_cancel(self):
#         if self.__timer:
#             self.__timer.cancel()
#             self.__timer = None
# 
#     def do_cancel(self):
#         self.__do_cancel()
# 
#     def do_delay(self, delay, method, *args, **kwargs):
#         assert type(method) == str
#         assert delay >= 0
#         # Stop an already running timer
#         self.__do_cancel()
#         func = getattr(self._proxy, method)
#         if delay > 0:
#             self.__timer = Timer(delay, func.defer, *args, **kwargs)
#             self.__timer.start()
#         else:
#             func.defer(*args, **kwargs)
# 
# Path: controller/util.py
# def constrain(x, out_min, out_max):
#     return min(max(x, out_min), out_max)
# 
# class Timer(object):
# 
#     def __init__(self, name):
#         self.__duration = timedelta()
#         self.__name = name
#         self.__last = None
#         self.__last_print = datetime(2000, 1, 1)
#         self.__delay = timedelta()
# 
#     @property
#     def duration(self):
#         return self.__duration
# 
#     @duration.setter
#     def duration(self, value):
#         self.__duration = value
# 
#     @property
#     def remaining(self):
#         return max(timedelta(), self.__delay - self.__duration)
# 
#     @property
#     def delay(self):
#         return self.__delay
# 
#     @delay.setter
#     def delay(self, value):
#         self.__delay = value
#         self.reset()
# 
#     def clear(self):
#         self.__last = None
# 
#     def reset(self):
#         self.clear()
#         self.__duration = timedelta()
# 
#     def update(self, now, factor=1):
#         if self.__last is not None:
#             self.__duration += factor * (now - self.__last)
#             remaining = max(timedelta(), self.delay - self.__duration)
#             if self.__last_print + timedelta(seconds=20) <= now:
#                 logger.debug("(%s) Timer: %s Remaining: %s" %
#                              (self.__name, self.__duration, remaining))
#                 self.__last_print = now
#         self.__last = now
# 
#     def elapsed(self):
#         return self.__duration >= self.__delay
# 
# Path: controller/config.py
# class Config:
#     def __init__(self, config_files):
#     def __getitem__(self, pair):
# def as_list(value, type_cast=int):


# Path: controller/disinfection.py
import time
import logging
from datetime import datetime, timedelta
from .actor import PoupoolModel
from .actor import PoupoolActor
from .util import constrain, Timer
from .config import config

                    self.__duration = 0
                    self.__state = False
                    self.__pump.off()
            else:
                self.__security_duration.update(datetime.now(), 0)
                security_ok = not self.__security_duration.elapsed()
                if self.__duration >= duty_off and duty_off != self.period and security_ok:
                    self.__duration = 0
                    self.__state = True
                    self.__pump.on()
        if datetime.now() > self.__security_reset:
            self.__security_duration.reset()
            self.__security_reset += timedelta(days=1)
        self.__last = now
        self.do_delay(1, self.do_run.__name__)


class PController(object):

    def __init__(self, pterm=0.1, scale=1.0):
        self.setpoint = 0
        self.current = 0
        self.pterm = pterm
        self.__scale = scale

    def compute(self):
        error = self.setpoint - self.current
        return constrain((self.pterm * self.__scale) * error, 0, 1)



class Disinfection(PoupoolActor):