Upd: add MultiLangFilter

This commit is contained in:
Hengyu 2023-08-11 02:43:06 +08:00
parent 958ffb6dbf
commit 16a88bb164
4 changed files with 89 additions and 40 deletions

View File

@ -101,3 +101,37 @@ class Filter:
# Invalid filter will be ignored.
# Return strange things and make it impossible to match
return ['1nVa1d'] + [None] * (len(self.attr) - 1)
class MultiLangFilter(Filter):
"""
To support multi-language, there might be different correct matches of same object.
"""
def apply_filter_to_obj(self, obj, filter):
"""
Args:
obj (object): In this case, attributes of object are array (instead of plain string).
Any match of element in it will return True
filter (list[str]):
Returns:
bool: If an object satisfy a filter.
"""
for attr, value in zip(self.attr, filter):
if not value:
continue
if not hasattr(obj, attr):
continue
obj_value = obj.__getattribute__(attr)
if isinstance(obj_value, str):
if obj_value.lower() != str(value):
return False
if isinstance(obj_value, list):
for candidate in obj_value:
if str(candidate) == str(value):
return True
return False
return True

View File

@ -3,10 +3,10 @@ from dataclasses import dataclass
from functools import cached_property
from typing import ClassVar
from module.exception import ScriptError
import module.config.server as server
from module.exception import ScriptError
REGEX_PUNCTUATION = re.compile(r'[ ,.\'"“”,。!??·•\-—/\\\n\t()\[\]()「」『』【】]')
REGEX_PUNCTUATION = re.compile(r'[ ,.\'"“”,。:!??·•\-—/\\\n\t()\[\]()「」『』【】《》]')
def parse_name(n):
@ -26,6 +26,7 @@ class Keyword:
"""
Instance attributes and methods
"""
@cached_property
def ch(self) -> str:
return self.cn

View File

@ -2,18 +2,18 @@ import re
import numpy as np
from dev_tools.keyword_extract import UI_LANGUAGES
from module.base.filter import Filter
from module.base.filter import MultiLangFilter
from module.base.timer import Timer
from module.base.utils import area_offset, get_color
from module.logger import logger
from module.ocr.keyword import Keyword
from module.ocr.ocr import Ocr, OcrResultButton, DigitCounter
from tasks.rogue.assets.assets_rogue_blessing import *
from tasks.rogue.keywords import *
from tasks.rogue.preset import *
from tasks.rogue.ui import RogueUI
REGEX_PUNCTUATION = re.compile(r'[ ,.\'"“”,。:!??·•—/()()「」『』【】]')
REGEX_PUNCTUATION = re.compile(r'[ ,.\'"“”,。:!??·•—/()()「」『』【】《》]')
def parse_name(n):
@ -22,44 +22,44 @@ def parse_name(n):
def get_regex_from_keyword_name(keyword, attr_name):
regex_pat = ""
attrs = tuple()
for server in UI_LANGUAGES:
string = ""
for path in keyword.instances.values():
string += f"{parse_name(getattr(path, server))}|"
# some pattern contain each other, make sure each pattern end with "-" or the end of string
regex_pat += f"(?:({string[:-1]})(?:-|$))?"
attrs += (f"{attr_name}_{server}",)
return regex_pat, attrs
string = ""
for instance in keyword.instances.values():
if hasattr(instance, attr_name):
for name in instance.__getattribute__(attr_name):
string += f"{name}|"
# some pattern contain each other, make sure each pattern end with "-" or the end of string
return f"(?:({string[:-1]})(?:-|$))?"
# normal blessing
pattern = ""
BLESSING_FILTER_ATTR = tuple()
PATH_ATTR_NAME = 'path'
path_regex, path_attr = get_regex_from_keyword_name(RoguePath, PATH_ATTR_NAME)
PATH_ATTR_NAME = 'path_name'
path_regex = get_regex_from_keyword_name(RoguePath, PATH_ATTR_NAME)
pattern += path_regex
BLESSING_FILTER_ATTR += path_attr
BLESSING_FILTER_ATTR += (PATH_ATTR_NAME,)
pattern += "([123])?-?"
BLESSING_FILTER_ATTR += ("rarity",)
BLESSING_ATTR_NAME = 'blessing'
blessing_regex, blessing_attr = get_regex_from_keyword_name(RogueBlessing, BLESSING_ATTR_NAME)
BLESSING_ATTR_NAME = 'blessing_name'
blessing_regex = get_regex_from_keyword_name(RogueBlessing, BLESSING_ATTR_NAME)
pattern += blessing_regex
BLESSING_FILTER_ATTR += blessing_attr
BLESSING_FILTER_ATTR += (BLESSING_ATTR_NAME,)
FILETER_REGEX = re.compile(pattern)
BLESSING_FILTER_PRESET = ("reset", "same_path", "random")
BLESSING_FILTER = Filter(FILETER_REGEX, BLESSING_FILTER_ATTR, BLESSING_FILTER_PRESET)
print(FILETER_REGEX)
print(BLESSING_FILTER_ATTR)
print(BLESSING_FILTER_PRESET)
BLESSING_FILTER = MultiLangFilter(FILETER_REGEX, BLESSING_FILTER_ATTR, BLESSING_FILTER_PRESET)
# resonance
RESONANCE_ATTR_NAME = 'resonance'
pattern, RESONANCE_FILTER_ATTR = get_regex_from_keyword_name(RogueResonance, 'resonance')
RESONANCE_ATTR_NAME = 'resonance_name'
pattern = get_regex_from_keyword_name(RogueResonance, 'resonance')
FILETER_REGEX = re.compile(pattern)
RESONANCE_FILTER_PRESET = ("random",)
RESONANCE_FILTER = Filter(FILETER_REGEX, RESONANCE_FILTER_ATTR, RESONANCE_FILTER_PRESET)
RESONANCE_FILTER = MultiLangFilter(FILETER_REGEX, (RESONANCE_ATTR_NAME,), RESONANCE_FILTER_PRESET)
class RogueBuffOcr(Ocr):
@ -226,20 +226,16 @@ class RogueBlessingSelector(RogueBlessingUI):
"""
def apply_filter(self):
paths = RoguePath.instances
def match_ocr_result(matched_keyword: Keyword):
for blessing in self.blessings:
if blessing.matched_keyword == matched_keyword:
return blessing
return None
if not self.blessings:
return []
if isinstance(self.blessings[0].matched_keyword, RogueBlessing):
for blessing in self.blessings:
path = paths[blessing.matched_keyword.path_id]
for server in UI_LANGUAGES:
setattr(blessing, f"{PATH_ATTR_NAME}_{server}", parse_name(getattr(path, server)))
setattr(blessing, f"{BLESSING_ATTR_NAME}_{server}",
parse_name(getattr(blessing.matched_keyword, server)))
setattr(blessing, "rarity", getattr(blessing.matched_keyword, "rarity"))
if self.config.Rogue_PresetBlessingFilter == 'preset-1':
BLESSING_FILTER.load(parse_name(BLESSING_PRESET_1))
if self.config.Rogue_PresetBlessingFilter == 'custom':
@ -248,17 +244,14 @@ class RogueBlessingSelector(RogueBlessingUI):
if isinstance(self.blessings[0].matched_keyword, RogueResonance):
if len(self.blessings) == 1: # resonance can not be reset. So have not choice when there's only one option
return self.blessings
for blessing in self.blessings:
for server in UI_LANGUAGES:
setattr(blessing, f"{RESONANCE_ATTR_NAME}_{server}",
parse_name(getattr(blessing.matched_keyword, server)))
if self.config.Rogue_PresetResonanceFilter == 'preset-1':
RESONANCE_FILTER.load(parse_name(RESONANCE_PRESET_1))
if self.config.Rogue_PresetResonanceFilter == 'custom':
RESONANCE_FILTER.load(parse_name(self.config.Rogue_CustomResonanceFilter))
priority = BLESSING_FILTER.apply(self.blessings)
blessing_keywords = [blessing.matched_keyword for blessing in self.blessings]
priority = BLESSING_FILTER.apply(blessing_keywords)
priority = [option if isinstance(option, str) else match_ocr_result(option) for option in priority]
return priority
def select_blessing(self, priority: list):

View File

@ -1,6 +1,7 @@
from dataclasses import dataclass
from typing import ClassVar
from dev_tools.keyword_extract import UI_LANGUAGES
from module.ocr.keyword import Keyword
@ -10,14 +11,34 @@ class RogueBlessing(Keyword):
path_id: int
rarity: int
@property
def path_name(self):
path = RoguePath.instances[self.path_id]
return path.path_name
@property
def blessing_name(self):
return [self.__getattribute__(f"{server}_parsed")
for server in UI_LANGUAGES if hasattr(self, f"{server}_parsed")]
@dataclass(repr=False)
class RoguePath(Keyword):
instances: ClassVar = {}
@property
def path_name(self):
return [self.__getattribute__(f"{server}_parsed")
for server in UI_LANGUAGES if hasattr(self, f"{server}_parsed")]
@dataclass(repr=False)
class RogueResonance(Keyword):
instances: ClassVar = {}
path_id: int
rarity: int
@property
def resonance_name(self):
return [self.__getattribute__(f"{server}_parsed")
for server in UI_LANGUAGES if hasattr(self, f"{server}_parsed")]