Пример #1
0
 def _alas_thread_update_config(self) -> None:
     modified = {}
     valid = []
     invalid = []
     while self.alive:
         try:
             d = self.modified_config_queue.get(timeout=10)
             config_name = self.alas_name
         except queue.Empty:
             continue
         modified[self.idx_to_path[d["name"]]] = parse_pin_value(d["value"])
         while True:
             try:
                 d = self.modified_config_queue.get(timeout=1)
                 modified[self.idx_to_path[d["name"]]] = parse_pin_value(
                     d["value"])
             except queue.Empty:
                 config = read_file(filepath_config(config_name))
                 for k, v in modified.copy().items():
                     validate = deep_get(self.ALAS_ARGS, k + ".validate")
                     if not len(str(v)):
                         default = deep_get(self.ALAS_ARGS, k + ".value")
                         deep_set(config, k, default)
                         valid.append(self.path_to_idx[k])
                         modified[k] = default
                     elif not validate or re_fullmatch(validate, v):
                         deep_set(config, k, v)
                         valid.append(self.path_to_idx[k])
                     else:
                         modified.pop(k)
                         invalid.append(self.path_to_idx[k])
                         logger.warning(
                             f"Invalid value {v} for key {k}, skip saving.")
                         # toast(t("Gui.Toast.InvalidConfigValue").format(
                         #       t('.'.join(k.split('.')[1:] + ['name']))),
                         #       duration=0, position='right', color='warn')
                 self.pin_remove_invalid_mark(valid)
                 self.pin_set_invalid_mark(invalid)
                 if modified:
                     toast(
                         t("Gui.Toast.ConfigSaved"),
                         duration=1,
                         position="right",
                         color="success",
                     )
                     logger.info(
                         f"Save config {filepath_config(config_name)}, {dict_to_kv(modified)}"
                     )
                     write_file(filepath_config(config_name), config)
                 modified.clear()
                 valid.clear()
                 invalid.clear()
                 break
Пример #2
0
    def set_group(self, group, arg_dict, config, task):
        group_name = group[0]
        with use_scope(f'group_{group_name}'):
            put_text(t(f"{group_name}._info.name"))
            group_help = t(f"{group_name}._info.help")
            if group_help != "":
                put_text(group_help)
            put_html('<hr class="hr-group">')

            for arg, d in deep_iter(arg_dict, depth=1):
                arg = arg[0]
                arg_type = d['type']
                if arg_type == 'disable':
                    continue
                value = deep_get(config, f'{task}.{group_name}.{arg}',
                                 d['value'])
                value = str(value) if isinstance(value, datetime) else value

                # Option
                options = deep_get(d, 'option', None)
                if options:
                    option = []
                    for opt in options:
                        o = {
                            "label": t(f"{group_name}.{arg}.{opt}"),
                            "value": opt
                        }
                        if value == opt:
                            o["selected"] = True
                        option.append(o)
                else:
                    option = None

                # Help
                arg_help = t(f"{group_name}.{arg}.help")
                if arg_help == "" or not arg_help:
                    arg_help = None

                # Invalid feedback
                invalid_feedback = t("Gui.Text.InvalidFeedBack").format(
                    d['value'])

                get_output(
                    arg_type=arg_type,
                    name=self.path_to_idx[f"{task}.{group_name}.{arg}"],
                    title=t(f"{group_name}.{arg}.name"),
                    arg_help=arg_help,
                    value=value,
                    options=option,
                    invalid_feedback=invalid_feedback,
                ).show()
Пример #3
0
    def _os_explore_task_delay(self):
        """
        Delay other OpSi tasks during os_explore
        """
        logger.info('Delay other OpSi tasks during OpsiExplore')
        next_run = self.config.Scheduler_NextRun
        for task in [
                'OpsiObscure', 'OpsiAbyssal', 'OpsiStronghold',
                'OpsiMeowfficerFarming'
        ]:
            keys = f'{task}.Scheduler.NextRun'
            current = deep_get(self.config.data,
                               keys=keys,
                               default=datetime(2020, 1, 1, 0, 0))
            if current < next_run:
                logger.info(f'Delay task `{task}` to {next_run}')
                self.config.modified[keys] = next_run

        # ResetActionPointPreserve
        # Unbound attribute, default to 500
        preserve = self.config.OpsiMeowfficerFarming_ActionPointPreserve
        logger.info(
            f'Set OpsiMeowfficerFarming.ActionPointPreserve to {preserve}')
        self.config.modified[
            'OpsiMeowfficerFarming.OpsiMeowfficerFarming.ActionPointPreserve'] = preserve

        self.config.update()
Пример #4
0
    def next_key():
        if V.idx + 1 > total:
            V.idx = -1

        V.idx += 1

        if V.untranslated_only:
            while True:
                # print(V.idx)
                key = deep_get(dict_lang[V.lang], list_path[V.idx])
                if list_path[V.idx] == key or list_path[V.idx].split(
                        '.')[2] == key:
                    break
                else:
                    V.idx += 1
                if V.idx + 1 > total:
                    V.idx = 0
                    break

        (V.group, V.arg, V.key) = tuple(list_path[V.idx].split('.'))
        V.group_idx = list_group.index(V.group)
        V.arg_idx = list_arg.index(V.arg, V.group_idx)
        V.args = list(dict_lang["zh-CN"][V.group].keys())
        V.key_idx = list_key.index(V.key, V.arg_idx)
        V.keys = list(dict_lang["zh-CN"][V.group][V.arg].keys())
Пример #5
0
    def _save_config(self, modified: Dict[str, str], config_name: str) -> None:
        try:
            valid = []
            invalid = []
            config = State.config_updater.read_file(config_name)
            for k, v in modified.copy().items():
                valuetype = deep_get(self.ALAS_ARGS, k + ".valuetype")
                v = parse_pin_value(v, valuetype)
                validate = deep_get(self.ALAS_ARGS, k + ".validate")
                if not len(str(v)):
                    default = deep_get(self.ALAS_ARGS, k + ".value")
                    deep_set(config, k, default)
                    valid.append(self.path_to_idx[k])
                    modified[k] = default
                elif not validate or re_fullmatch(validate, v):
                    deep_set(config, k, v)
                    valid.append(self.path_to_idx[k])

                    # update Emotion Record if Emotion Value is changed
                    if "Emotion" in k and "Value" in k:
                        k = k.split(".")
                        k[-1] = k[-1].replace("Value", "Record")
                        k = ".".join(k)
                        v = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
                        modified[k] = v
                        deep_set(config, k, v)
                        valid.append(self.path_to_idx[k])
                        pin[self.path_to_idx[k]] = v
                else:
                    modified.pop(k)
                    invalid.append(self.path_to_idx[k])
                    logger.warning(f"Invalid value {v} for key {k}, skip saving.")
            self.pin_remove_invalid_mark(valid)
            self.pin_set_invalid_mark(invalid)
            if modified:
                toast(
                    t("Gui.Toast.ConfigSaved"),
                    duration=1,
                    position="right",
                    color="success",
                )
                logger.info(
                    f"Save config {filepath_config(config_name)}, {dict_to_kv(modified)}"
                )
                State.config_updater.write_file(config_name, config)
        except Exception as e:
            logger.exception(e)
Пример #6
0
    def update_form():
        input_update('arg', options=V.args, value=V.arg)
        input_update('key', options=V.keys, value=V.key)
        for L in LANGUAGES:
            input_update(L,
                         value=deep_get(dict_lang[L],
                                        f'{V.group}.{V.arg}.{V.key}',
                                        'Key not found!'))

        old = deep_get(dict_lang[V.lang], f'{V.group}.{V.arg}.{V.key}',
                       'Key not found!')
        input_update(
            V.lang,
            value=None if V.clear else old,
            help_text=f'{V.group}.{V.arg}.{V.key}',
            placeholder=old,
        )
Пример #7
0
    def loop(self):
        logger.set_file_logger(self.config_name)
        logger.info(f'Start scheduler loop: {self.config_name}')
        is_first = True
        failure_record = {}

        while 1:
            if self.stop_event is not None:
                if self.stop_event.is_set():
                    logger.info("Update event detected")
                    logger.info(f"Alas [{self.config_name}] exited.")
                    break
            task = self.get_next_task()

            # Skip first restart
            if is_first and task == 'Restart':
                logger.info('Skip task `Restart` at scheduler start')
                self.config.task_delay(server_update=True)
                del self.__dict__['config']
                continue

            # Run
            logger.info(f'Scheduler: Start task `{task}`')
            self.device.stuck_record_clear()
            self.device.click_record_clear()
            self.device.screenshot()
            logger.hr(task, level=0)
            success = self.run(inflection.underscore(task))
            logger.info(f'Scheduler: End task `{task}`')
            is_first = False

            # Check failures
            failed = deep_get(failure_record, keys=task, default=0)
            failed = 0 if success else failed + 1
            deep_set(failure_record, keys=task, value=failed)
            if failed >= 3:
                logger.critical(f"Task `{task}` failed 3 or more times.")
                logger.critical(
                    "Possible reason #1: You haven't used it correctly. "
                    "Please read the help text of the options.")
                logger.critical(
                    "Possible reason #2: There is a problem with this task. "
                    "Please contact developers or try to fix it yourself.")
                logger.critical('Request human takeover')
                exit(1)

            if success:
                del self.__dict__['config']
                continue
            elif self.config.Error_HandleError:
                # self.config.task_delay(success=False)
                del self.__dict__['config']
                continue
            else:
                break
Пример #8
0
 def config(self):
     try:
         config = AzurLaneConfig(config_name=self.config_name)
         # Set server before loading any buttons.
         server.server = deep_get(config.data, keys='Alas.Emulator.Server', default='cn')
         return config
     except RequestHumanTakeover:
         logger.critical('Request human takeover')
         exit(1)
     except Exception as e:
         logger.exception(e)
         exit(1)
Пример #9
0
    def run_process(config_name,
                    func: str,
                    q: queue.Queue,
                    e: threading.Event = None) -> None:
        # Setup logger
        set_file_logger(name=config_name)
        set_func_logger(func=q.put)

        # Set server before loading any buttons.
        import module.config.server as server
        from module.config.config import AzurLaneConfig

        AzurLaneConfig.stop_event = e
        config = AzurLaneConfig(config_name=config_name)
        server.server = deep_get(config.data,
                                 keys="Alas.Emulator.Server",
                                 default="cn")
        try:
            # Run alas
            if func == "Alas":
                from alas import AzurLaneAutoScript

                if e is not None:
                    AzurLaneAutoScript.stop_event = e
                AzurLaneAutoScript(config_name=config_name).loop()
            elif func == "Daemon":
                from module.daemon.daemon import AzurLaneDaemon

                AzurLaneDaemon(config=config_name, task="Daemon").run()
            elif func == "OpsiDaemon":
                from module.daemon.os_daemon import AzurLaneDaemon

                AzurLaneDaemon(config=config_name, task="OpsiDaemon").run()
            elif func == "AzurLaneUncensored":
                from module.daemon.uncensored import AzurLaneUncensored

                AzurLaneUncensored(config=config_name,
                                   task="AzurLaneUncensored").run()
            elif func == "Benchmark":
                from module.daemon.benchmark import Benchmark

                Benchmark(config=config_name, task="Benchmark").run()
            elif func == "GameManager":
                from module.daemon.game_manager import GameManager

                GameManager(config=config_name, task="GameManager").run()
            else:
                logger.critical("No function matched")
            logger.info(f"[{config_name}] exited. Reason: Finish\n")
        except Exception as e:
            logger.exception(e)
Пример #10
0
 def is_in_opsi_explore(self):
     """
     Returns:
         bool: If task OpsiExplore is under scheduling.
     """
     enable = deep_get(self.config.data,
                       keys='OpsiExplore.Scheduler.Enable',
                       default=False)
     next_run = deep_get(self.config.data,
                         keys='OpsiExplore.Scheduler.NextRun',
                         default=DEFAULT_TIME)
     next_reset = get_os_next_reset()
     logger.attr('OpsiNextReset', next_reset)
     logger.attr('OpsiExplore', (enable, next_run))
     if enable and next_run < next_reset:
         logger.info(
             'OpsiExplore is still running, accept missions only. '
             'Missions will be finished when OpsiExplore visits every zones, '
             'no need to worry they are left behind.')
         return True
     else:
         logger.info('Not in OpsiExplore, able to do OpsiDaily')
         return False
Пример #11
0
    def run_process(config_name,
                    func: str,
                    q: queue.Queue,
                    e: threading.Event = None) -> None:
        # Setup logger
        qh = QueueHandler(q)
        formatter = logging.Formatter(
            fmt='%(asctime)s.%(msecs)03d | %(levelname)s | %(message)s',
            datefmt='%H:%M:%S')
        webconsole = logging.StreamHandler(stream=qh)
        webconsole.setFormatter(formatter)
        logger.addHandler(webconsole)

        # Set server before loading any buttons.
        import module.config.server as server
        from module.config.config import AzurLaneConfig
        AzurLaneConfig.stop_event = e
        config = AzurLaneConfig(config_name=config_name)
        server.server = deep_get(config.data,
                                 keys='Alas.Emulator.Server',
                                 default='cn')
        try:
            # Run alas
            if func == 'Alas':
                from alas import AzurLaneAutoScript
                if e is not None:
                    AzurLaneAutoScript.stop_event = e
                AzurLaneAutoScript(config_name=config_name).loop()
            elif func == 'Daemon':
                from module.daemon.daemon import AzurLaneDaemon
                AzurLaneDaemon(config=config_name, task='Daemon').run()
            elif func == 'OpsiDaemon':
                from module.daemon.os_daemon import AzurLaneDaemon
                AzurLaneDaemon(config=config_name, task='OpsiDaemon').run()
            elif func == 'AzurLaneUncensored':
                from module.daemon.uncensored import AzurLaneUncensored
                AzurLaneUncensored(config=config_name,
                                   task='AzurLaneUncensored').run()
            elif func == 'Benchmark':
                from module.daemon.benchmark import Benchmark
                Benchmark(config=config_name, task='Benchmark').run()
            elif func == 'GameManager':
                from module.daemon.game_manager import GameManager
                GameManager(config=config_name, task='GameManager').run()
            else:
                logger.critical("No function matched")
            logger.info(f"[{config_name}] exited. Reason: Finish")
        except Exception as e:
            logger.exception(e)
Пример #12
0
    def handle_commission_notice(self):
        """
        Check commission notice.
        If found, stop current task and call commission.

        Raises:
            TaskEnd: If found commission notice.

        Pages:
            in: page_campaign
        """
        if deep_get(self.config.data,
                    keys='Commission.Scheduler.Enable',
                    default=False):
            if self.campaign.commission_notice_show_at_campaign():
                logger.info('Commission notice found')
                self.config.task_call('Commission')
                self.config.task_stop('Commission notice found')
Пример #13
0
    def _disable_tasks(self, tasks):
        """
        Args:
            tasks (list[str]): Task name
        """
        for task in tasks:
            keys = f'{task}.Scheduler.Enable'
            logger.info(f'Disable task `{task}`')
            self.config.modified[keys] = False

        for task in ['GemsFarming']:
            if deep_get(self.config.data,
                        keys=f'{task}.Campaign.Event',
                        default='campaign_main') != 'campaign_main':
                logger.info(f'Reset GemsFarming to 2-4')
                self.config.modified[f'{task}.Campaign.Name'] = '2-4'
                self.config.modified[
                    f'{task}.Campaign.Event'] = 'campaign_main'

        logger.info(f'Reset event time limit')
        self.config.modified['EventGeneral.EventGeneral.TimeLimit'] = datetime(
            2020, 1, 1, 0, 0)

        self.config.update()
Пример #14
0
 def _is_in_os_explore(self):
     return deep_get(self.config.data,
                     keys='OpsiExplore.Scheduler.Enable',
                     default=False)
Пример #15
0
    def get_inputs():
        out = []
        old = deep_get(dict_lang[V.lang], f'{V.group}.{V.arg}.{V.key}',
                       'Key not found!')
        out.append(
            input(
                name=V.lang,
                label=V.lang,
                value=None if V.clear else old,
                help_text=f'{V.group}.{V.arg}.{V.key}',
                placeholder=old,
            ))
        out.append(
            select(name='group',
                   label='Group',
                   options=V.groups,
                   value=V.group,
                   onchange=lambda g: update_var(group=g),
                   required=True))
        out.append(
            select(name='arg',
                   label='Arg',
                   options=V.args,
                   value=V.arg,
                   onchange=lambda a: update_var(arg=a),
                   required=True))
        out.append(
            select(name='key',
                   label='Key',
                   options=V.keys,
                   value=V.key,
                   onchange=lambda k: update_var(key=k),
                   required=True))
        _LANGUAGES = LANGUAGES.copy()
        _LANGUAGES.remove(V.lang)
        for L in _LANGUAGES:
            out.append(
                input(name=L,
                      label=L,
                      readonly=True,
                      value=deep_get(dict_lang[L],
                                     f'{V.group}.{V.arg}.{V.key}',
                                     'Key not found!')))
        out.append(
            actions(name='action',
                    buttons=[
                        {
                            "label": "Next",
                            "value": 'Next',
                            "type": "submit",
                            "color": "success"
                        },
                        {
                            "label": "Next without save",
                            "value": 'Skip',
                            "type": "submit",
                            "color": "secondary"
                        },
                        {
                            "label": "Submit",
                            "value": "Submit",
                            "type": "submit",
                            "color": "primary"
                        },
                        {
                            "label": "Quit and save",
                            "type": "cancel",
                            "color": "secondary"
                        },
                    ]))

        return out