Esempio n. 1
0
 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
     }
Esempio n. 2
0
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
    }
Esempio n. 3
0
    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