def as_dict(self): fields = {'sim_duration', 'slot_length', 'tick_length', 'market_count', 'ticks_per_slot', 'total_ticks', 'cloud_coverage', 'max_panel_power_W'} return { k: format_interval(v) if isinstance(v, Duration) else v for k, v in self.__dict__.items() if k in fields }
def simulation_info(simulation): current_time = format_interval(simulation.area.current_tick * simulation.area.config.tick_length, show_day=False) return { 'config': simulation.area.config.as_dict(), 'finished': simulation.finished, 'aborted': simulation.is_stopped, 'current_tick': simulation.area.current_tick, 'current_time': current_time, 'current_date': simulation.area.now.format('%Y-%m-%d'), 'paused': simulation.paused, 'slowdown': simulation.slowdown }
def run(self, resume=False) -> (Period, duration): if resume: log.critical("Resuming simulation") self._info() self.is_stopped = False config = self.simulation_config tick_lengths_s = config.tick_length.total_seconds() slot_count = int(config.duration / config.slot_length) + 1 while True: self.ready.wait() self.ready.clear() if resume: # FIXME: Fix resume time calculation if self.run_start is None or self.paused_time is None: raise RuntimeError("Can't resume without saved state") slot_resume, tick_resume = divmod(self.area.current_tick, config.ticks_per_slot) else: self.run_start = DateTime.now(tz=TIME_ZONE) self.paused_time = 0 slot_resume = tick_resume = 0 try: with NonBlockingConsole() as console: for slot_no in range(slot_resume, slot_count - 1): run_duration = (DateTime.now(tz=TIME_ZONE) - self.run_start - duration(seconds=self.paused_time)) log.error( "Slot %d of %d (%2.0f%%) - %s elapsed, ETA: %s", slot_no + 1, slot_count, (slot_no + 1) / slot_count * 100, run_duration, run_duration / (slot_no + 1) * slot_count) if self.is_stopped: log.error("Received stop command.") sleep(5) break for tick_no in range(tick_resume, config.ticks_per_slot): # reset tick_resume after possible resume tick_resume = 0 self._handle_input(console) self.paused_time += self._handle_paused(console) tick_start = time.monotonic() log.debug( "Tick %d of %d in slot %d (%2.0f%%)", tick_no + 1, config.ticks_per_slot, slot_no + 1, (tick_no + 1) / config.ticks_per_slot * 100, ) with page_lock: self.area.tick(is_root_area=True) tick_length = time.monotonic() - tick_start if self.slowdown and tick_length < tick_lengths_s: # Simulation runs faster than real time but a slowdown was # requested tick_diff = tick_lengths_s - tick_length diff_slowdown = tick_diff * self.slowdown / 10000 log.debug("Slowdown: %.4f", diff_slowdown) self._handle_input(console, diff_slowdown) with page_lock: self.endpoint_buffer.update_stats( self.area, self.status) self.redis_connection.publish_intermediate_results( self.endpoint_buffer) run_duration = (DateTime.now(tz=TIME_ZONE) - self.run_start - duration(seconds=self.paused_time)) paused_duration = duration(seconds=self.paused_time) self.redis_connection.publish_results(self.endpoint_buffer) if not self.is_stopped: log.error( "Run finished in %s%s / %.2fx real time", run_duration, " ({} paused)".format(paused_duration) if paused_duration else "", config.duration / (run_duration - paused_duration)) if not self.exit_on_finish: log.error("REST-API still running at %s", self.api_url) if self.export_on_finish: export = ExportAndPlot( self.area, self.export_path, DateTime.now(tz=TIME_ZONE).isoformat()) json_dir = os.path.join(export.directory, "aggregated_results") mkdir_from_str(json_dir) for key, value in self.endpoint_buffer.generate_result_report( ).items(): json_file = os.path.join(json_dir, key) with open(json_file, 'w') as outfile: json.dump(value, outfile) if self.use_repl: self._start_repl() elif self.reset_on_finish: log.error("Automatically restarting simulation in %s", format_interval(self.reset_on_finish_wait)) self._handle_input( console, self.reset_on_finish_wait.in_seconds()) def _reset(): self.reset(sync=False) self.paused = False t = Thread(target=_reset) t.start() t.join() continue elif self.exit_on_finish: self._handle_input( console, self.exit_on_finish_wait.in_seconds()) log.error("Terminating. (--exit-on-finish set.)") break else: log.info("Ctrl-C to quit") while True: self._handle_input(console, 0.5) break except _SimulationInterruped: self.interrupted.set() except KeyboardInterrupt: break