def _TriggerAnnouncement (self, announcementMethodName: str, preemptive: bool, *announcementArgs, **announcementKwargs) -> None: for announcer in Director.GetAllAnnouncers(): # type: typing.Type[Director.Announcer] readReportLockIdentifier = None # type: typing.Optional[str] readReportLockReference = None # type: typing.Any if self.LimitErrors: readReportLockIdentifier = __name__ + ":" + str(Python.GetLineNumber()) # type: str readReportLockReference = announcer try: if not announcer.Enabled: continue if not announcer.Host.IsLoaded() and not announcer.Reliable: continue if preemptive != announcer.Preemptive: continue announcementMethod = getattr(announcer, announcementMethodName) # type: typing.Callable except Exception: from NeonOcean.S4.Main import Debug Debug.Log("Failed to read the announcer at '" + Types.GetFullName(announcer) + "' when triggering the announcement '" + announcementMethodName + "'.", announcer.Host.Namespace, Debug.LogLevels.Exception, group = announcer.Host.Namespace, owner = __name__, lockIdentifier = readReportLockIdentifier, lockReference = readReportLockReference) return else: if readReportLockIdentifier is not None: from NeonOcean.S4.Main import Debug Debug.Unlock(readReportLockIdentifier, readReportLockReference) callReportLockIdentifier = None # type: typing.Optional[str] callReportLockReference = None # type: typing.Any if self.LimitErrors: callReportLockIdentifier = __name__ + ":" + str(Python.GetLineNumber()) # type: str callReportLockReference = announcer try: if self.AnnouncementCallWrapper is None: announcementMethod(*announcementArgs, **announcementKwargs) else: self.AnnouncementCallWrapper(announcementMethod, *announcementArgs, **announcementKwargs) except Exception: from NeonOcean.S4.Main import Debug Debug.Log("Failed to trigger the announcement '" + announcementMethodName + "' for '" + Types.GetFullName(announcer) + "'.", announcer.Host.Namespace, Debug.LogLevels.Exception, group = announcer.Host.Namespace, owner = __name__, lockIdentifier = callReportLockIdentifier, lockReference = callReportLockReference) return else: if callReportLockIdentifier is not None: from NeonOcean.S4.Main import Debug Debug.Unlock(callReportLockIdentifier, callReportLockReference)
def VerifySystems( reproductiveSystems: typing.Optional[typing.Iterable[ ReproductionShared.ReproductiveSystem]] = None ) -> None: """ Verify that all specified reproductive systems should exist and that their values are valid. :param reproductiveSystems: All reproductive systems that need to be verified. If this is None the function will go through all registered reproductive systems. :type reproductiveSystems: typing.Iterable[ReproductionShared.ReproductiveSystem] | None """ if reproductiveSystems is None: reproductiveSystems = GetAllSystems(automaticallyUpdate=False) for reproductiveSystem in reproductiveSystems: # type: ReproductionShared.ReproductiveSystem reportLockIdentifier = __name__ + ":" + str( Python.GetLineNumber()) # type: str reportLockReference = reproductiveSystem try: if not reproductiveSystem.ShouldExist: UnregisterReproductiveSystem(reproductiveSystem) continue reproductiveSystem.Verify() except: Debug.Log("Failed to verify a reproductive system.\n" + reproductiveSystem.DebugInformation, This.Mod.Namespace, Debug.LogLevels.Exception, group=This.Mod.Namespace, owner=__name__, lockIdentifier=reportLockIdentifier, lockReference=reportLockReference) else: Debug.Unlock(reportLockIdentifier, reportLockReference)
def GetUpdateTicks( maximumTick: int, reproductiveSystems: typing.Optional[typing.Iterable[ ReproductionShared.ReproductiveSystem]] = None ) -> typing.Dict[int, typing.List[ReproductionShared.ReproductiveSystem]]: """ Get a dictionary of ticks paired with lists of reproductive systems that should update on them. :param maximumTick: Planned updates beyond this tick will be ignored. :type maximumTick: int :param reproductiveSystems: The reproductive systems to get an update tick for. If this is None the function will go through all registered reproductive systems. :type reproductiveSystems: typing.Iterable[ReproductionShared.ReproductiveSystem] | None """ if reproductiveSystems is None: reproductiveSystems = GetAllSystems() updateTicks = dict( ) # type: typing.Dict[int, typing.List[ReproductionShared.ReproductiveSystem]] for reproductiveSystem in reproductiveSystems: # type: ReproductionShared.ReproductiveSystem reportLockIdentifier = __name__ + ":" + str( Python.GetLineNumber()) # type: str reportLockReference = reproductiveSystem try: planUpdateArguments = reproductiveSystem.PlanUpdate() plannedTick = planUpdateArguments.RequestedTick if plannedTick is None or plannedTick >= maximumTick: plannedTick = maximumTick plannedTickSystems = updateTicks.get( plannedTick, None ) # type: typing.Optional[typing.List[ReproductionShared.ReproductiveSystem]] if plannedTickSystems is None: plannedTickSystems = list() updateTicks[plannedTick] = plannedTickSystems plannedTickSystems.append(reproductiveSystem) except: Debug.Log("Failed to plan the update of a reproductive system\n." + reproductiveSystem.DebugInformation, This.Mod.Namespace, Debug.LogLevels.Exception, group=This.Mod.Namespace, owner=__name__, lockIdentifier=reportLockIdentifier, lockReference=reportLockReference) else: Debug.Unlock(reportLockIdentifier, reportLockReference) return updateTicks
def _plannedUpdateCallback (alarmHandle: alarms.AlarmHandle) -> None: if not This.Mod.IsLoaded(): return reportLockIdentifier = __name__ + ":UpdateCallback" # type: str try: Reproduction.UpdateSystems(plannedSystems) # TODO log the time taken? except: Debug.Log("Reproduction planned update callback failed.", This.Mod.Namespace, Debug.LogLevels.Exception, group = This.Mod.Namespace, owner = __name__, lockIdentifier = reportLockIdentifier) else: Debug.Unlock(reportLockIdentifier) try: _plannedUpdateAlarms.remove(alarmHandle) except ValueError: pass
def _StandardUpdateCallback (alarmHandle: alarms.AlarmHandle) -> None: if not This.Mod.IsLoaded(): return reportLockIdentifier = __name__ + ":UpdateCallback" # type: str try: Reproduction.UpdateSystems() # TODO log the time taken? updateTicks = Reproduction.GetUpdateTicks(_standardUpdateInterval) # type: typing.Dict[int, typing.List[ReproductionShared.ReproductiveSystem]] for plannedTick, plannedSystems in updateTicks.items(): # type: int, typing.List[ReproductionShared.ReproductiveSystem] if plannedTick >= _standardUpdateInterval: continue alarmTimeSpan = date_and_time.TimeSpan(plannedTick) plannedUpdateAlarm = alarms.add_alarm(sys.modules[__name__], alarmTimeSpan, _CreatePlannedUpdateCallback(plannedSystems)) _plannedUpdateAlarms.append(plannedUpdateAlarm) except: Debug.Log("Reproduction standard update callback failed.", This.Mod.Namespace, Debug.LogLevels.Exception, group = This.Mod.Namespace, owner = __name__, lockIdentifier = reportLockIdentifier) else: Debug.Unlock(reportLockIdentifier)
def SimulateSystems( ticks: int, reproductiveSystems: typing.Optional[typing.Iterable[ ReproductionShared.ReproductiveSystem]] = None ) -> None: """ Simulate this many ticks in the specified reproductive systems. All out of date reproductive systems will be updated before simulating. :param ticks: The number of ticks to simulate. :type ticks: int :param reproductiveSystems: All reproductive systems that need to be simulated. If this is None the function will go through all registered reproductive systems. :type reproductiveSystems: typing.Iterable[ReproductionShared.ReproductiveSystem] | None """ if not isinstance(ticks, int): raise Exceptions.IncorrectTypeException(ticks, "ticks", (int, )) if reproductiveSystems is None: reproductiveSystems = GetAllSystems() for reproductiveSystem in reproductiveSystems: # type: ReproductionShared.ReproductiveSystem reportLockIdentifier = __name__ + ":" + str( Python.GetLineNumber()) # type: str reportLockReference = reproductiveSystem try: reproductiveSystem.Simulate(ticks) except: Debug.Log("Failed to simulate a reproductive system\n." + reproductiveSystem.DebugInformation, This.Mod.Namespace, Debug.LogLevels.Exception, group=This.Mod.Namespace, owner=__name__, lockIdentifier=reportLockIdentifier, lockReference=reportLockReference) else: Debug.Unlock(reportLockIdentifier, reportLockReference)
def UpdateSystems( reproductiveSystems: typing.Optional[typing.Iterable[ ReproductionShared.ReproductiveSystem]] = None ) -> None: """ Update all specified reproductive systems. :param reproductiveSystems: All reproductive systems that need to be updated. If this is None the function will go through all registered reproductive systems. :type reproductiveSystems: typing.Iterable[ReproductionShared.ReproductiveSystem] | None """ if reproductiveSystems is None: reproductiveSystems = GetAllSystems(automaticallyUpdate=False) if len(reproductiveSystems) == 0: return updateTimedRoll = random.random() # type: float updateTimedProbability = 0.125 # type: float maximumSavedUpdateTimes = 200 # type: int if len(_fullUpdateTimes) == 0: updateTimed = True else: updateTimed = len( _fullUpdateTimes ) != maximumSavedUpdateTimes and updateTimedRoll <= updateTimedProbability # type: bool if updateTimed: fullUpdateStartTime = time.time() # type: typing.Optional[float] chosenTimedSystem = random.choice( reproductiveSystems ) # type: typing.Optional[ReproductionShared.ReproductiveSystem] else: fullUpdateStartTime = None # type: typing.Optional[float] chosenTimedSystem = None # type: typing.Optional[ReproductionShared.ReproductiveSystem] for reproductiveSystem in reproductiveSystems: # type: ReproductionShared.ReproductiveSystem reportLockIdentifier = __name__ + ":" + str( Python.GetLineNumber()) # type: str reportLockReference = reproductiveSystem if updateTimed and reproductiveSystem is chosenTimedSystem: individualUpdateStartTime = time.time( ) # type: typing.Optional[float] else: individualUpdateStartTime = None # type: typing.Optional[float] try: if reproductiveSystem.ShouldUpdate: reproductiveSystem.Update() except: Debug.Log("Failed to update a reproductive system\n." + reproductiveSystem.DebugInformation, This.Mod.Namespace, Debug.LogLevels.Exception, group=This.Mod.Namespace, owner=__name__, lockIdentifier=reportLockIdentifier, lockReference=reportLockReference) else: Debug.Unlock(reportLockIdentifier, reportLockReference) if individualUpdateStartTime is not None: _individualUpdateTimes.append(time.time() - individualUpdateStartTime) if fullUpdateStartTime is not None: _fullUpdateTimes.append(time.time() - fullUpdateStartTime)