def _run_node(self, uid): if uid not in self._scheduled_nodes: logger.error('Trying to run a drama node with uid {} that is not scheduled.', uid) return drama_node_inst = self._scheduled_nodes[uid] del self._scheduled_nodes[uid] if not self._enabled: drama_node_inst.cleanup() if is_drama_node_log_enabled(): log_drama_node_scoring(drama_node_inst, DramaNodeLogActions.CANCELED, 'Drama Scheduler is disabled') return if drama_node_inst.cooldown is not None and drama_node_inst.cooldown.cooldown_option != CooldownOption.ON_SCHEDULE and self._is_node_on_cooldown(type(drama_node_inst)): drama_node_inst.cleanup() if is_drama_node_log_enabled(): log_drama_node_scoring(drama_node_inst, DramaNodeLogActions.CANCELED, '{} is currently on cooldown', drama_node_inst) return result = drama_node_inst.run() if result == DramaNodeRunOutcome.SUCCESS_NODE_INCOMPLETE: self._active_nodes[uid] = drama_node_inst elif result == DramaNodeRunOutcome.RESCHEDULED: self._scheduled_nodes[uid] = drama_node_inst else: if is_drama_node_log_enabled(): log_drama_node_scoring(drama_node_inst, DramaNodeLogActions.COMPLETED) drama_node_inst.cleanup()
def score_and_schedule_nodes_gen(self, nodes_to_score, nodes_to_schedule, specific_time=None, time_modifier=TimeSpan.ZERO, timeline=None, gsi_data=None, **additional_drama_node_kwargs): active_household = services.active_household() if active_household is None: return self._update_cooldowns() sim_resolvers = tuple(SingleSimResolver(sim_info) for sim_info in active_household.sim_info_gen()) possible_nodes = [] chosen_node_types = set() for drama_node in nodes_to_score: if not self._is_node_on_cooldown(drama_node) or gsi_data is not None: gsi_data.rejected_nodes.append(GSIRejectedDramaNodeScoringData(drama_node, '{} is on cooldown.', drama_node)) for resolver in sim_resolvers: uid = id_generator.generate_object_id() drama_node_inst = drama_node(uid) result = drama_node_inst.setup(resolver, gsi_data=gsi_data, **additional_drama_node_kwargs) if timeline is not None: yield timeline.run_child(elements.SleepElement(date_and_time.TimeSpan(0))) if not result: drama_node_inst.cleanup() else: score = drama_node_inst.score() if score == 0: if gsi_data is not None: gsi_data.rejected_nodes.append(GSIRejectedDramaNodeScoringData(drama_node, 'Scoring generated a score of 0.', score=score, receiver=drama_node_inst.get_receiver_sim_info(), sender=drama_node_inst.get_sender_sim_info())) drama_node_inst.cleanup() else: if gsi_data is not None: gsi_data.potential_nodes.append(GSIDramaNodeScoringData(drama_node, score, drama_node_inst.get_score_details(), drama_node_inst.get_receiver_sim_info(), drama_node_inst.get_sender_sim_info())) possible_nodes.append((score, drama_node_inst)) if not possible_nodes: return while nodes_to_schedule > 0: while possible_nodes: chosen_node = random.pop_weighted(possible_nodes) if type(chosen_node) in chosen_node_types: if gsi_data is not None: gsi_data.rejected_nodes.append(GSIRejectedDramaNodeScoringData(type(drama_node_inst), 'Could not schedule drama node because a drama node of this type was already scheduled.', score=chosen_node.score(), score_details=chosen_node.get_score_details(), receiver=chosen_node.get_receiver_sim_info(), sender=chosen_node.get_sender_sim_info())) chosen_node.cleanup() else: result = chosen_node.schedule(None, specific_time=specific_time, time_modifier=time_modifier) if timeline is not None: yield timeline.run_child(elements.SleepElement(date_and_time.TimeSpan(0))) if not result: if gsi_data is not None: gsi_data.rejected_nodes.append(GSIRejectedDramaNodeScoringData(type(chosen_node), 'Could not schedule drama node because there are no valid times.', score=chosen_node.score(), score_details=chosen_node.get_score_details(), receiver=chosen_node.get_receiver_sim_info(), sender=chosen_node.get_sender_sim_info())) chosen_node.cleanup() else: if gsi_data is not None: gsi_data.chosen_nodes.append(GSIDramaNodeScoringData(type(chosen_node), chosen_node.score(), chosen_node.get_score_details(), chosen_node.get_receiver_sim_info(), chosen_node.get_sender_sim_info())) self._scheduled_nodes[chosen_node.uid] = chosen_node if chosen_node.cooldown is not None and chosen_node.cooldown.cooldown_option == CooldownOption.ON_SCHEDULE: self.start_cooldown(type(chosen_node)) if is_drama_node_log_enabled(): log_drama_node_scoring(chosen_node, DramaNodeLogActions.SCHEDULED) nodes_to_schedule -= 1 chosen_node_types.add(type(chosen_node)) for (score, drama_node_inst) in possible_nodes: drama_node_inst.cleanup()
def complete_node(self, uid, from_shutdown=False): if uid not in self._active_nodes: return node_inst = self._active_nodes[uid] if is_drama_node_log_enabled(): log_drama_node_scoring(node_inst, DramaNodeLogActions.COMPLETED) node_inst.complete(from_shutdown=from_shutdown) node_inst.cleanup() del self._active_nodes[uid]
def cancel_scheduled_nodes_with_types(self, drama_nodes): node_guids_to_cancel = set(drama_node_type.guid64 for drama_node_type in drama_nodes) for drama_node in list(self._scheduled_nodes.values()): if drama_node.guid64 not in node_guids_to_cancel: continue if is_drama_node_log_enabled(): log_drama_node_scoring(drama_node, DramaNodeLogActions.CANCELED, '{} canceled manually.', drama_node) drama_node.cleanup() del self._scheduled_nodes[drama_node.uid]
def cancel_scheduled_node(self, drama_node_uid): if drama_node_uid not in self._scheduled_nodes: logger.error('Trying to cancel a drama node that is not scheduled. Node id: {}', drama_node_uid) return False drama_node = self._scheduled_nodes[drama_node_uid] if is_drama_node_log_enabled(): log_drama_node_scoring(drama_node, DramaNodeLogActions.CANCELED, '{} canceled manually.', drama_node) drama_node.cleanup() del self._scheduled_nodes[drama_node.uid] return True
def run_node(self, drama_node, resolver, **kwargs): uid = id_generator.generate_object_id() drama_node_inst = drama_node(uid) if not drama_node_inst.setup(resolver, **kwargs): return False drama_node_inst.debug_set_selected_time(services.time_service().sim_now) result = drama_node_inst.run() if result == DramaNodeRunOutcome.SUCCESS_NODE_INCOMPLETE: self._active_nodes[uid] = drama_node_inst elif result == DramaNodeRunOutcome.RESCHEDULED: self._scheduled_nodes[uid] = drama_node_inst elif is_drama_node_log_enabled(): log_drama_node_scoring(drama_node_inst, DramaNodeLogActions.COMPLETED) return True
def schedule_node(self, drama_node, resolver, specific_time=None, drama_inst=None, setup_kwargs={}, **constructor_kwargs): if drama_inst is not None: drama_node_inst = drama_inst else: uid = id_generator.generate_object_id() drama_node_inst = drama_node(uid, **constructor_kwargs) if not drama_node_inst.schedule(resolver, specific_time=specific_time, **setup_kwargs): return if is_drama_node_log_enabled(): log_drama_node_scoring(drama_node_inst, DramaNodeLogActions.SCHEDULED) self._scheduled_nodes[drama_node_inst.uid] = drama_node_inst if drama_node.cooldown is not None and drama_node.cooldown.cooldown_option == CooldownOption.ON_SCHEDULE: self.start_cooldown(drama_node) return drama_node_inst.uid