Source code for cosapp.core.time
import abc
import logging
from numbers import Number
from cosapp.patterns import Singleton, Observer, Subject
logger = logging.getLogger(__name__)
[docs]class TimeManager(Subject):
"""Observer pattern subject notifying its observers when time changes"""
def __new__(cls, *args, **kwargs):
return super().__new__(cls, TimeObserver)
def __init__(self, t: Number = 0):
super().__init__()
self.__time = t
@property
def time(self) -> Number:
"""Current simulation time"""
return self.__time
@time.setter
def time(self, t: Number):
logger.info(f"Time = {t:.5g} s")
dt = t - self.__time
self.__time = t
self.notify(dt)
[docs] def reset(self, t: Number = 0):
"""Reset time to a chosen value, without notifying observers"""
self.__time = t
[docs]class UniversalClock(TimeManager, metaclass=Singleton):
"""Unique (singleton) time manager"""
def __repr__(self) -> str:
return f"Universal time manager @ t = {self.time}"
[docs]class TimeObserver(Observer):
"""
Abstract time observer.
Concrete derived classes must implement abstract method '_update'.
"""
def __init__(self, sign_in=True):
super().__init__()
if sign_in:
self.observe()
[docs] def observe(self):
"""Sign in as observer of the universal time manager"""
clock = UniversalClock()
super().observe(clock)
[docs] def observes(self) -> bool:
"""Bool: has object signed up as an observer?"""
clock = UniversalClock()
return super().observes(clock)
@property
def t(self) -> Number:
"""Current simulation time - alias for time"""
return self.time
@property
def time(self) -> Number:
"""Current simulation time"""
return UniversalClock().time
@abc.abstractmethod
def _update(self, dt: Number) -> None:
"""Specifies how object must update when notified a time step of `dt`"""
pass