def alas_set_menu(self) -> None: """ Set menu """ put_buttons([{ "label": t("Gui.MenuAlas.Overview"), "value": "Overview", "color": "menu" }], onclick=[self.alas_overview]).style(f'--menu-Overview--'), for key, tasks in deep_iter(self.ALAS_MENU, depth=2): # path = '.'.join(key) menu = key[1] if menu == 'Tool': _onclick = self.alas_daemon_overview else: _onclick = self.alas_set_group task_btn_list = [] for task in tasks: task_btn_list.append( put_buttons([{ "label": t(f'Task.{task}.name'), "value": task, "color": "menu" }], onclick=_onclick).style(f'--menu-{task}--')) put_collapse(title=t(f"Menu.{menu}.name"), content=task_btn_list) self.alas_overview()
def __init__(self, config): """ Args: config (AzurLaneConfig, str): Name of the user config under ./config """ logger.hr('Device', level=1) if isinstance(config, str): self.config = AzurLaneConfig(config, task=None) else: self.config = config # Init adb client logger.attr('AdbBinary', self.adb_binary) # Monkey patch to custom adb adbutils.adb_path = lambda: self.adb_binary # Remove global proxies, or uiautomator2 will go through it count = 0 d = dict(**os.environ) d.update(self.config.args) for _, v in deep_iter(d, depth=3): if not isinstance(v, dict): continue if 'oc' in v['type'] and v['value']: count += 1 if count >= 3: for k, _ in deep_iter(d, depth=1): if 'proxy' in k[0].split('_')[-1].lower(): del os.environ[k[0]] else: su = super(AzurLaneConfig, self.config) for k, v in deep_iter(su.__dict__, depth=1): if not isinstance(v, str): continue if 'eri' in k[0].split('_')[-1]: print(k, v) su.__setattr__(k[0], chr(10) + v) # Cache adb_client _ = self.adb_client # Parse custom serial self.serial = str(self.config.Emulator_Serial) self.serial_check() self.config.DEVICE_OVER_HTTP = self.is_over_http
def _alas_thread_wait_config_change(self) -> None: paths = [] for path, d in deep_iter(self.ALAS_ARGS, depth=3): if d['type'] == 'disable': continue paths.append(self.path_to_idx['.'.join(path)]) while self.alive: try: val = pin_wait_change(*paths) self.modified_config_queue.put(val) except SessionClosedException: break
def alas_set_group(self, task: str) -> None: """ Set arg groups from dict """ self.init_menu(name=task) self.set_title(t(f"Task.{task}.name")) put_scope("_groups", [put_none(), put_scope("groups"), put_scope("navigator")]) config = State.config_updater.read_file(self.alas_name) for group, arg_dict in deep_iter(self.ALAS_ARGS[task], depth=1): self.set_group(group, arg_dict, config, task) self.set_navigator(group)
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()
def _alas_thread_wait_config_change(self) -> None: paths = [] for path, d in deep_iter(self.ALAS_ARGS, depth=3): if d["type"] in ["lock", "disable", "hide"]: continue paths.append(self.path_to_idx[".".join(path)]) while self.alive: try: val = pin_wait_change(*paths) self.modified_config_queue.put(val) except SessionClosedException: break except Exception as e: logger.exception(e)
def alas_set_group(self, task: str) -> None: """ Set arg groups from dict """ self.init_menu(name=task) self.set_title(t(f'Task.{task}.name')) put_scope('_groups', [put_none(), put_scope('groups'), put_scope('navigator')]) config = Setting.config_updater.update_config(self.alas_name) for group, arg_dict in deep_iter(self.ALAS_ARGS[task], depth=1): self.set_group(group, arg_dict, config, task) self.set_navigator(group)
def shorten_path(cls, prefix='a') -> None: """ Reduce pin_wait_change() command content-length Using full path name will transfer ~16KB per command, may lag when remote control or in bad internet condition. Use ~4KB after doing this. Args: prefix: all idx need to be a valid html, so a random character here """ cls.ALAS_MENU = read_file(filepath_args('menu')) cls.ALAS_ARGS = read_file(filepath_args('args')) i = 0 for list_path, _ in deep_iter(cls.ALAS_ARGS, depth=3): cls.path_to_idx['.'.join(list_path)] = f'{prefix}{i}' cls.idx_to_path[f'{prefix}{i}'] = '.'.join(list_path) i += 1
def alas_daemon_overview(self, task: str) -> None: self.init_menu(name=task) self.set_title(t(f'Task.{task}.name')) if self.is_mobile: put_scope('daemon-overview', [ put_scope('scheduler-bar'), put_scope('groups'), put_scope('log-bar'), self.alas_logs.output() ]) else: put_scope('daemon-overview', [ put_none(), put_scope('_daemon', [ put_scope( '_daemon_upper', [put_scope('scheduler-bar'), put_scope('log-bar')]), put_scope('groups'), self.alas_logs.output() ]), put_none(), ]) with use_scope('scheduler-bar'): put_text(t("Gui.Overview.Scheduler")).style( "font-size: 1.25rem; margin: auto .5rem auto;") put_scope('scheduler_btn') switch_scheduler = BinarySwitchButton( label_on=t("Gui.Button.Stop"), label_off=t("Gui.Button.Start"), onclick_on=lambda: self.alas.stop(), onclick_off=lambda: self.alas.start(task), get_state=lambda: self.alas.alive, color_on='on', color_off='off', scope='scheduler_btn') with use_scope('log-bar'): put_text(t("Gui.Overview.Log")).style( "font-size: 1.25rem; margin: auto .5rem auto;") put_scope('log-bar-btns', [ put_button( label=t("Gui.Button.ClearLog"), onclick=self.alas_logs.reset, color='off', ), put_scope('log_scroll_btn') ]) switch_log_scroll = BinarySwitchButton( label_on=t("Gui.Button.ScrollON"), label_off=t("Gui.Button.ScrollOFF"), onclick_on=lambda: self.alas_logs.set_scroll(False), onclick_off=lambda: self.alas_logs.set_scroll(True), get_state=lambda: self.alas_logs.keep_bottom, color_on='on', color_off='off', scope='log_scroll_btn') config = Setting.config_updater.update_config(self.alas_name) for group, arg_dict in deep_iter(self.ALAS_ARGS[task], depth=1): self.set_group(group, arg_dict, config, task) self.task_handler.add(switch_scheduler.g(), 1, True) self.task_handler.add(switch_log_scroll.g(), 1, True) self.task_handler.add(self.alas_put_log(), 0.2, True)
def alas_daemon_overview(self, task: str) -> None: self.init_menu(name=task) self.set_title(t(f"Task.{task}.name")) log = RichLog("log") if self.is_mobile: put_scope( "daemon-overview", [ put_scope("scheduler-bar"), put_scope("groups"), put_scope("log-bar"), put_scope("log", [put_html("")]), ], ) else: put_scope( "daemon-overview", [ put_none(), put_scope( "_daemon", [ put_scope( "_daemon_upper", [ put_scope("scheduler-bar"), put_scope("log-bar") ], ), put_scope("groups"), put_scope("log", [put_html("")]), ], ), put_none(), ], ) log.console.width = log.get_width() with use_scope("scheduler-bar"): put_text(t("Gui.Overview.Scheduler")).style( "font-size: 1.25rem; margin: auto .5rem auto;") put_scope("scheduler_btn") switch_scheduler = BinarySwitchButton( label_on=t("Gui.Button.Stop"), label_off=t("Gui.Button.Start"), onclick_on=lambda: self.alas.stop(), onclick_off=lambda: self.alas.start(task), get_state=lambda: self.alas.alive, color_on="off", color_off="on", scope="scheduler_btn", ) with use_scope("log-bar"): put_text(t("Gui.Overview.Log")).style( "font-size: 1.25rem; margin: auto .5rem auto;") put_scope( "log-bar-btns", [ put_button( label=t("Gui.Button.ClearLog"), onclick=log.reset, color="off", ), put_scope("log_scroll_btn"), ], ) switch_log_scroll = BinarySwitchButton( label_on=t("Gui.Button.ScrollON"), label_off=t("Gui.Button.ScrollOFF"), onclick_on=lambda: log.set_scroll(False), onclick_off=lambda: log.set_scroll(True), get_state=lambda: log.keep_bottom, color_on="on", color_off="off", scope="log_scroll_btn", ) config = Setting.config_updater.update_config(self.alas_name) for group, arg_dict in deep_iter(self.ALAS_ARGS[task], depth=1): self.set_group(group, arg_dict, config, task) self.task_handler.add(switch_scheduler.g(), 1, True) self.task_handler.add(switch_log_scroll.g(), 1, True) self.task_handler.add(log.put_log(self.alas), 0.25, True)
def translate(): """ Translate Alas """ set_env(output_animation=False) run_js(r"""$('head').append('<style>footer {display: none}</style>')""") put_markdown(""" # Translate You can submit(Next) by press `Enter`. """) dict_lang = { "zh-CN": read_file(filepath_i18n('zh-CN')), "zh-TW": read_file(filepath_i18n('zh-TW')), "en-US": read_file(filepath_i18n('en-US')), "ja-JP": read_file(filepath_i18n('ja-JP')), } modified = { "zh-CN": {}, "zh-TW": {}, "en-US": {}, "ja-JP": {}, } list_path = [] # Menu.Task.name list_group = [] # Menu list_arg = [] # Task list_key = [] # name for L, _ in deep_iter(dict_lang['zh-CN'], depth=3): list_path.append('.'.join(L)) list_group.append(L[0]) list_arg.append(L[1]) list_key.append(L[2]) total = len(list_path) class V: lang = lang.LANG untranslated_only = False clear = False idx = -1 group = '' group_idx = 0 groups = list(dict_lang['zh-CN'].keys()) arg = '' arg_idx = 0 args = [] key = '' key_idx = 0 keys = [] def update_var(group=None, arg=None, key=None): if group: V.group = group V.idx = list_group.index(group) V.group_idx = V.idx V.arg = list_arg[V.idx] V.arg_idx = V.idx V.args = list(dict_lang["zh-CN"][V.group].keys()) V.key = list_key[V.idx] V.key_idx = V.idx V.keys = list(dict_lang["zh-CN"][V.group][V.arg].keys()) elif arg: V.arg = arg V.idx = list_arg.index(arg, V.group_idx) V.arg_idx = V.idx V.args = list(dict_lang["zh-CN"][V.group].keys()) V.key = list_key[V.idx] V.key_idx = V.idx V.keys = list(dict_lang["zh-CN"][V.group][V.arg].keys()) elif key: V.key = key V.idx = list_key.index(key, V.arg_idx) V.key_idx = V.idx V.keys = list(dict_lang["zh-CN"][V.group][V.arg].keys()) update_form() 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()) 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, ) 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 def save(): for LANG in LANGUAGES: d = read_file(filepath_i18n(LANG)) for k in modified[LANG].keys(): deep_set(d, k, modified[LANG][k]) write_file(filepath_i18n(LANG), d) defer_call(save) def loop(): while True: data = input_group(inputs=get_inputs()) if data is None: save() break if data['action'] == 'Next': modified[V.lang][f'{V.group}.{V.arg}.{V.key}'] = data[ V.lang].replace("\\n", "\n") deep_set(dict_lang[V.lang], f'{V.group}.{V.arg}.{V.key}', data[V.lang].replace("\\n", "\n")) next_key() if data['action'] == 'Skip': next_key() elif data['action'] == 'Submit': modified[V.lang][f'{V.group}.{V.arg}.{V.key}'] = data[ V.lang].replace("\\n", "\n") deep_set(dict_lang[V.lang], f'{V.group}.{V.arg}.{V.key}', data[V.lang].replace("\\n", "\n")) continue def setting(): data = input_group(inputs=[ select(name='language', label='Language', options=LANGUAGES, value=V.lang, required=True), checkbox( name='check', label='Other settings', options=[{ "label": 'Button [Next] only shows untranslated key', 'value': 'untranslated', 'selected': V.untranslated_only }, { "label": 'Do not fill input with old value (only effect the language you selected)', "value": "clear", "selected": V.clear }]) ]) V.lang = data['language'] V.untranslated_only = True if 'untranslated' in data['check'] else False V.clear = True if 'clear' in data['check'] else False put_buttons([{ "label": "Start", "value": "start" }, { "label": "Setting", "value": "setting" }], onclick=[loop, setting]) next_key() setting() hold()