Fix: Matching dungeon from map interact

This commit is contained in:
LmeSzinc 2024-05-08 21:46:53 +08:00
parent 423d5351de
commit 9d514f4e9d
3 changed files with 79 additions and 13 deletions

View File

@ -54,6 +54,7 @@ class OcrPlaneName(OcrWhiteLetterOnComplexBackground):
result = result.replace('累塔', '黑塔')
if '星港' in result:
result = '迴星港'
result = result.replace('太司', '太卜司')
result = result.replace(' ', '')

View File

@ -3,7 +3,7 @@ from functools import cached_property
from typing import ClassVar
from module.exception import ScriptError
from module.ocr.keyword import Keyword
from module.ocr.keyword import Keyword, parse_name
@dataclass(repr=False)
@ -183,6 +183,48 @@ class DungeonList(Keyword):
else:
return ''
@classmethod
def find_dungeon_by_string(cls, cn='', en='', **kwargs):
"""
Args:
cn: Any substring in dungeon name
en:
**kwargs: Filter properties, e.g. is_Echo_of_War=True
Returns:
DungeonList: or None
"""
if cn:
string = parse_name(cn)
lang = 'cn'
elif en:
string = parse_name(en)
lang = 'en'
else:
return None
def find(obj: "DungeonList"):
name = obj._keywords_to_find(lang=lang, ignore_punctuation=True)[0]
if string in name:
return True
return False
# From SelectedGrids
def matched(obj):
flag = True
for k, v in kwargs.items():
obj_v = obj.__getattribute__(k)
if type(obj_v) != type(v) or obj_v != v:
flag = False
return flag
dungeons = [grid for grid in cls.instances.values() if find(grid) and matched(grid)]
if len(dungeons) == 1:
return dungeons[0]
else:
return None
@dataclass(repr=False)
class DungeonEntrance(Keyword):

View File

@ -612,23 +612,46 @@ class DungeonUI(DungeonState):
logger.info('No dungeon interact')
return None
self.acquire_lang_checked()
ocr = OcrDungeonList(DUNGEON_COMBAT_INTERACT_TEXT)
result = ocr.detect_and_ocr(self.device.image)
dungeon = None
# Special match names in English
# Second row must have at least 3 characters which is the shortest name "Ire"
# Stangnant Shadow: Shape of
# Quanta
if len(result) == 2 and len(result[1].ocr_text) >= 3:
first, second = result[0].ocr_text, result[1].ocr_text
if re.search(r'Stagnant\s*Shadow', first):
dungeon = DungeonList.find_dungeon_by_string(en=second, is_Stagnant_Shadow=True)
elif re.search(r'Cavern\s*of\s*Corrosion', first):
dungeon = DungeonList.find_dungeon_by_string(en=second, is_Cavern_of_Corrosion=True)
elif re.search(r'Echo\s*of\s*War', first):
dungeon = DungeonList.find_dungeon_by_string(en=second, is_Echo_of_War=True)
elif re.search(r'Calyx[\s(]+Golden', first):
dungeon = DungeonList.find_dungeon_by_string(en=second, is_Calyx_Golden=True, world=self.plane.world)
elif re.search(r'Calyx[\s(]+Crimson', first):
dungeon = DungeonList.find_dungeon_by_string(en=second, is_Calyx_Crimson=True, plane=self.plane)
if dungeon is not None:
logger.attr('DungeonInteract', dungeon)
return dungeon
# Join
result = ' '.join([row.ocr_text for row in result])
# Calyx (Crimson): Bud of XXX -> Bud of XXX
result = re.sub(r'Calyx\s*\(.*?\):*', '', result)
# Stagnant Shadow: Shap XXX -> Shape of XXX
result = re.sub(r'Stagnant\s*Shadow[:\s]*\w*', 'Shape of', result)
# Cavern of Corrosion: Pa XXX -> Path of XXX
result = re.sub(r'Cavern\s*of\s*Corrosion[:\s]*\w*', 'Path of', result)
# Echo of War: XXX -> XXX
result = re.sub(r'Echo\s*of\s*War:*', '', result)
# Divine See -> Divine Seed
result = re.sub(r'Divine\s*\w*', 'Divine Seed', result)
# Destructio Beginning -> Destruction's Beginning
result = re.sub(r"Destruct[a-zA-Z0-9_']*", "Destruction's", result)
# Special match names in Chinese
# Only calyxes need spacial match
if res := re.search(r'(^.+之蕾)', result):
dungeon = DungeonList.find_dungeon_by_string(cn=res.group(1), is_Calyx_Crimson=True, plane=self.plane)
if dungeon is not None:
logger.attr('DungeonInteract', dungeon)
return dungeon
dungeon = DungeonList.find_dungeon_by_string(cn=res.group(1), is_Calyx_Golden=True, world=self.plane.world)
if dungeon is not None:
logger.attr('DungeonInteract', dungeon)
return dungeon
# Dungeons
try: