def run(self):
        try:
            for randomizer in self.randomizers:
                local_status_steps_left = randomizer.step_count()
                local_status = Status()

                def local_status_fn(_, descr):
                    nonlocal local_status_steps_left
                    if descr != Status.DONE_SPECIAL_STR:
                        if local_status_steps_left > 0:
                            local_status_steps_left -= 1
                        self.status.step(descr)
                    else:
                        for i in range(local_status_steps_left):
                            self.status.step('Randomizing...')

                local_status.subscribe(local_status_fn)
                randomizer.run(local_status)
            self.status.step('Saving scripts...')
            save_scripts(self.rom, self.static_data)
        except BaseException as error:
            logger.error("Exception during randomization.", exc_info=error)
            self.error = sys.exc_info()

        with self.lock:
            self.done = True
            self.status.done()
Esempio n. 2
0
    async def on_message(self, message):
        decoded_message = json.loads(message)
        logger.debug(f'{self.request.remote_ip}: Sent msg.')
        try:
            if not self.randomization_is_running:
                if decoded_message['action'] == 'start':
                    logger.info(f'{self.request.remote_ip}: Sent start request.')
                    self.randomization_is_running = True
                    config = ConfigFileLoader.load_from_dict(decoded_message['config'])
                    rom = RomStorage.roms[self.request.remote_ip]
                    seed = get_effective_seed(config['seed'])
                    random.seed(seed)
                    status = Status()

                    def update_fn(progress, desc):
                        logger.debug(f'{self.request.remote_ip}: {round((progress - 1 / randomizer.total_steps * 100))}: {desc}')
                        if desc == Status.DONE_SPECIAL_STR:
                            self.write_message(json.dumps(
                                {'status': 'progress', 'step': progress - 1, 'totalSteps': randomizer.total_steps,
                                 'message': "Randomizing complete!", 'seed': seed}))
                        else:
                            self.write_message(json.dumps(
                                {'status': 'progress', 'step': progress - 1, 'totalSteps': randomizer.total_steps,
                                 'message': desc, 'seed': seed}))

                    def check_done():
                        if not randomizer.is_done():
                            return True
                        logger.debug(f'{self.request.remote_ip}: Check done!')
                        if randomizer.error:
                            traceback_str = ''.join(traceback.format_exception(*randomizer.error))
                            logger.error(f'{self.request.remote_ip}: ERROR: {traceback_str}')
                            self.write_message(json.dumps(
                                {'status': 'error',
                                 'message': f"Error: {traceback_str}", 'seed': seed}))
                        else:
                            logger.info(f'{self.request.remote_ip}: DONE!')
                            self.write_message(json.dumps(
                                {'status': 'done', 'step': randomizer.total_steps, 'totalSteps': randomizer.total_steps,
                                 'message': "Randomization complete!", 'seed': seed}))
                        return False

                    status.subscribe(lambda a, b: WebserverFrontend.run_on_main_thread(partial(update_fn, a, b)))
                    randomizer = RandomizerThread(status, rom, config, seed, WebserverFrontend())

                    WebserverFrontend.run_timeout(0.1, check_done)

                    randomizer.start()
        except BaseException as ex:
            self.randomization_is_running = False
            tb = traceback.format_exc()
            print(tb)
            await self.write_message(json.dumps({'status': 'error', 'message': f"Fatal error: {ex}\n{tb}"}))
Esempio n. 3
0
    def on_randomize_clicked(self, *args):
        if self.chosen_file is None:
            self.display_error("Please choose an input file.")
            return

        dialog = Gtk.FileChooserNative.new(
            "Output ROM filename...",
            self.window,
            Gtk.FileChooserAction.SAVE,
            None, None
        )

        filter_nds = Gtk.FileFilter()
        filter_nds.set_name("Nintendo DS ROMs (*.nds)")
        filter_nds.add_mime_type("application/x-nintendo-ds-rom")
        filter_nds.add_pattern("*.nds")
        dialog.add_filter(filter_nds)

        response = dialog.run()
        out_fn = dialog.get_filename()
        dialog.destroy()

        if response == Gtk.ResponseType.ACCEPT:
            clear_script_cache()
            if '.' not in out_fn:
                out_fn += '.nds'
            try:
                self.builder.get_object('progress_close').set_sensitive(False)
                progress_bar: Gtk.ProgressBar = self.builder.get_object('progress_bar')
                progress_label: Gtk.Label = self.builder.get_object('progress_label')
                progress_diag: Gtk.Dialog = self.builder.get_object('progress')
                progress_diag.set_title('Randomizing...')

                def update_fn(progress, desc):
                    progress_bar.set_fraction((progress - 1) / randomizer.total_steps)
                    if desc == Status.DONE_SPECIAL_STR:
                        progress_label.set_text("Randomizing complete!")
                    else:
                        progress_label.set_text(f"{floor((progress - 1) / randomizer.total_steps * 100)}%: {desc}")

                def check_done():
                    if not randomizer.is_done():
                        return True
                    self.builder.get_object('progress_close').set_sensitive(True)
                    if randomizer.error:
                        img: Gtk.Image = self.builder.get_object('img_portrait_duskako')
                        img.set_from_file(os.path.join(data_dir(), 'duskako_sad.png'))
                        traceback_str = ''.join(traceback.format_exception(*randomizer.error))
                        progress_label.set_text(f"Error: {traceback_str}")
                        progress_diag.set_title('Randomizing failed!')
                    else:
                        rom.saveToFile(out_fn)
                        img: Gtk.Image = self.builder.get_object('img_portrait_duskako')
                        img.set_from_file(os.path.join(data_dir(), 'duskako_happy.png'))
                        progress_label.set_text("Randomizing complete!")
                        progress_diag.set_title('Randomizing complete!')
                    return False

                rom = NintendoDSRom.fromFile(self.chosen_file)
                status = Status()
                status.subscribe(lambda a, b: GLib.idle_add(partial(update_fn, a, b)))
                config = self.ui_reader.read()
                # Set the seed
                seed = get_effective_seed(config['seed'])
                random.seed(seed)
                self.builder.get_object('seed_label').set_text('Your Seed: ' + str(seed))
                randomizer = RandomizerThread(status, rom, config, seed)
                randomizer.start()

                # SHOW DIALOG
                img: Gtk.Image = self.builder.get_object('img_portrait_duskako')
                img.set_from_file(os.path.join(data_dir(), 'duskako_neutral.png'))

                GLib.timeout_add(100, check_done)

                progress_diag.run()
            except BaseException as ex:
                tb = traceback.format_exc()
                print(tb)
                self.display_error(f"Error: {ex}\n{tb}")
                return