2023-05-22 12:20:31 +00:00
|
|
|
from dataclasses import dataclass
|
2023-07-06 14:41:16 +00:00
|
|
|
from functools import cached_property
|
2023-05-30 18:20:45 +00:00
|
|
|
from typing import ClassVar
|
2023-05-22 12:20:31 +00:00
|
|
|
|
2023-07-06 14:41:16 +00:00
|
|
|
from module.exception import ScriptError
|
2024-05-08 13:46:53 +00:00
|
|
|
from module.ocr.keyword import Keyword, parse_name
|
2023-05-22 12:20:31 +00:00
|
|
|
|
|
|
|
|
2023-06-16 20:24:13 +00:00
|
|
|
@dataclass(repr=False)
|
2023-05-22 12:20:31 +00:00
|
|
|
class DungeonNav(Keyword):
|
2023-05-30 18:20:45 +00:00
|
|
|
instances: ClassVar = {}
|
2023-05-22 12:20:31 +00:00
|
|
|
|
|
|
|
|
2023-06-16 20:24:13 +00:00
|
|
|
@dataclass(repr=False)
|
2023-05-22 12:20:31 +00:00
|
|
|
class DungeonTab(Keyword):
|
2023-05-30 18:20:45 +00:00
|
|
|
instances: ClassVar = {}
|
2023-06-12 16:43:57 +00:00
|
|
|
|
|
|
|
|
2023-06-16 20:24:13 +00:00
|
|
|
@dataclass(repr=False)
|
2023-06-12 16:43:57 +00:00
|
|
|
class DungeonList(Keyword):
|
|
|
|
instances: ClassVar = {}
|
|
|
|
|
2024-05-11 10:21:28 +00:00
|
|
|
dungeon_id: int
|
2024-02-06 19:05:46 +00:00
|
|
|
plane_id: int
|
|
|
|
|
|
|
|
@cached_property
|
|
|
|
def plane(self):
|
|
|
|
"""
|
|
|
|
Returns:
|
|
|
|
MapPlane: MapPlane object or None
|
|
|
|
"""
|
|
|
|
from tasks.map.keywords import MapPlane
|
|
|
|
return MapPlane.find_plane_id(self.plane_id)
|
|
|
|
|
2024-02-06 21:24:46 +00:00
|
|
|
@cached_property
|
|
|
|
def world(self):
|
|
|
|
"""
|
|
|
|
Returns:
|
|
|
|
MapWorld: MapWorld object or None
|
|
|
|
"""
|
|
|
|
if self.plane is not None:
|
|
|
|
return self.plane.world
|
|
|
|
else:
|
|
|
|
return None
|
|
|
|
|
2023-07-06 14:41:16 +00:00
|
|
|
@cached_property
|
2023-06-12 16:43:57 +00:00
|
|
|
def is_Calyx_Golden(self):
|
|
|
|
return 'Calyx_Golden' in self.name
|
|
|
|
|
2024-02-06 20:36:17 +00:00
|
|
|
@cached_property
|
|
|
|
def is_Calyx_Golden_Memories(self):
|
|
|
|
return 'Calyx_Golden_Memories' in self.name
|
|
|
|
|
|
|
|
@cached_property
|
|
|
|
def is_Calyx_Golden_Aether(self):
|
|
|
|
return 'Calyx_Golden_Aether' in self.name
|
|
|
|
|
|
|
|
@cached_property
|
|
|
|
def is_Calyx_Golden_Treasures(self):
|
|
|
|
return 'Calyx_Golden_Treasures' in self.name
|
|
|
|
|
2023-07-06 14:41:16 +00:00
|
|
|
@cached_property
|
2023-06-12 16:43:57 +00:00
|
|
|
def is_Calyx_Crimson(self):
|
|
|
|
return 'Calyx_Crimson' in self.name
|
|
|
|
|
2024-02-06 20:36:17 +00:00
|
|
|
@cached_property
|
|
|
|
def Calyx_Crimson_Path(self):
|
|
|
|
"""
|
|
|
|
Returns:
|
|
|
|
RoguePath: RoguePath object or None
|
|
|
|
"""
|
|
|
|
if not self.is_Calyx_Crimson:
|
|
|
|
return None
|
|
|
|
from tasks.rogue.keywords import RoguePath
|
|
|
|
for path in RoguePath.instances.values():
|
|
|
|
if path.name in self.name:
|
|
|
|
return path
|
2024-12-09 16:07:52 +00:00
|
|
|
# elif path.name == 'The_Harmony' and 'Harmony' in self.name:
|
|
|
|
# return path
|
2024-02-06 20:36:17 +00:00
|
|
|
return None
|
|
|
|
|
2023-08-27 09:13:05 +00:00
|
|
|
@cached_property
|
|
|
|
def is_Calyx(self):
|
|
|
|
return self.is_Calyx_Golden or self.is_Calyx_Crimson
|
|
|
|
|
2023-07-06 14:41:16 +00:00
|
|
|
@cached_property
|
2023-06-12 16:43:57 +00:00
|
|
|
def is_Stagnant_Shadow(self):
|
|
|
|
return 'Stagnant_Shadow' in self.name
|
|
|
|
|
2024-02-06 20:36:17 +00:00
|
|
|
@cached_property
|
|
|
|
def Stagnant_Shadow_Combat_Type(self):
|
|
|
|
"""
|
|
|
|
Returns:
|
|
|
|
CombatType: CombatType object or None
|
|
|
|
"""
|
|
|
|
if not self.is_Stagnant_Shadow:
|
|
|
|
return None
|
|
|
|
from tasks.dungeon.keywords import DungeonDetailed
|
|
|
|
detail = DungeonDetailed.find_name(self.name)
|
|
|
|
if detail is None:
|
|
|
|
return None
|
|
|
|
from tasks.character.keywords import CombatType
|
|
|
|
for type_ in CombatType.instances.values():
|
|
|
|
if type_.cn in detail.cn[:10]:
|
|
|
|
return type_
|
|
|
|
return None
|
|
|
|
|
2023-07-06 14:41:16 +00:00
|
|
|
@cached_property
|
2023-06-12 16:43:57 +00:00
|
|
|
def is_Cavern_of_Corrosion(self):
|
|
|
|
return 'Cavern_of_Corrosion' in self.name
|
|
|
|
|
2023-07-06 14:41:16 +00:00
|
|
|
@cached_property
|
2023-06-12 16:43:57 +00:00
|
|
|
def is_Echo_of_War(self):
|
|
|
|
return 'Echo_of_War' in self.name
|
|
|
|
|
2023-07-06 14:41:16 +00:00
|
|
|
@cached_property
|
2023-06-12 16:43:57 +00:00
|
|
|
def is_Simulated_Universe(self):
|
|
|
|
return 'Simulated_Universe' in self.name
|
2023-06-14 16:15:14 +00:00
|
|
|
|
2024-06-30 16:38:37 +00:00
|
|
|
@cached_property
|
|
|
|
def is_Ornament_Extraction(self):
|
|
|
|
# Farm Ornament_Extraction from Ornament_Extraction_xxx
|
|
|
|
return 'Divergent_Universe' in self.name
|
|
|
|
|
2023-07-06 14:41:16 +00:00
|
|
|
@cached_property
|
2023-06-29 04:56:05 +00:00
|
|
|
def is_Forgotten_Hall(self):
|
2023-09-22 17:29:42 +00:00
|
|
|
for word in [
|
|
|
|
'Forgotten_Hall',
|
|
|
|
'Memory_of_Chaos',
|
|
|
|
'Last_Vestiges',
|
|
|
|
'Navis_Astriger',
|
|
|
|
]:
|
|
|
|
if word in self.name:
|
|
|
|
return True
|
|
|
|
return False
|
2023-06-29 16:32:33 +00:00
|
|
|
|
2023-12-27 12:41:57 +00:00
|
|
|
@cached_property
|
|
|
|
def is_Pure_Fiction(self):
|
|
|
|
for word in [
|
|
|
|
'Pure_Fiction',
|
|
|
|
]:
|
|
|
|
if word in self.name:
|
|
|
|
return True
|
|
|
|
return False
|
|
|
|
|
2023-07-06 14:41:16 +00:00
|
|
|
@cached_property
|
2023-06-17 16:13:21 +00:00
|
|
|
def is_daily_dungeon(self):
|
|
|
|
return self.is_Calyx_Golden or self.is_Calyx_Crimson or self.is_Stagnant_Shadow or self.is_Cavern_of_Corrosion
|
|
|
|
|
2023-07-06 14:41:16 +00:00
|
|
|
@cached_property
|
2023-06-17 16:13:21 +00:00
|
|
|
def is_weekly_dungeon(self):
|
|
|
|
return self.is_Echo_of_War
|
|
|
|
|
2023-07-06 14:41:16 +00:00
|
|
|
@cached_property
|
|
|
|
def dungeon_nav(self) -> DungeonNav:
|
|
|
|
import tasks.dungeon.keywords.nav as KEYWORDS_DUNGEON_NAV
|
|
|
|
if self.is_Simulated_Universe:
|
|
|
|
return KEYWORDS_DUNGEON_NAV.Simulated_Universe
|
2024-06-30 16:38:37 +00:00
|
|
|
if self.is_Ornament_Extraction:
|
|
|
|
return KEYWORDS_DUNGEON_NAV.Ornament_Extraction
|
2023-07-06 14:41:16 +00:00
|
|
|
if self.is_Calyx_Golden:
|
|
|
|
return KEYWORDS_DUNGEON_NAV.Calyx_Golden
|
|
|
|
if self.is_Calyx_Crimson:
|
|
|
|
return KEYWORDS_DUNGEON_NAV.Calyx_Crimson
|
|
|
|
if self.is_Stagnant_Shadow:
|
|
|
|
return KEYWORDS_DUNGEON_NAV.Stagnant_Shadow
|
|
|
|
if self.is_Cavern_of_Corrosion:
|
|
|
|
return KEYWORDS_DUNGEON_NAV.Cavern_of_Corrosion
|
|
|
|
if self.is_Echo_of_War:
|
|
|
|
return KEYWORDS_DUNGEON_NAV.Echo_of_War
|
|
|
|
if self.is_Forgotten_Hall:
|
|
|
|
return KEYWORDS_DUNGEON_NAV.Forgotten_Hall
|
2023-12-27 12:41:57 +00:00
|
|
|
if self.is_Pure_Fiction:
|
|
|
|
return KEYWORDS_DUNGEON_NAV.Pure_Fiction
|
2023-07-06 14:41:16 +00:00
|
|
|
|
|
|
|
raise ScriptError(f'Cannot convert {self} to DungeonNav, please check keyword extractions')
|
|
|
|
|
2023-12-27 16:50:31 +00:00
|
|
|
@cached_property
|
|
|
|
def rogue_theme(self) -> str:
|
|
|
|
"""
|
|
|
|
Returns:
|
|
|
|
'rogue' for normal simulated universe farmed every week
|
|
|
|
'dlc' for special rogue theme
|
|
|
|
'' for non-rogue
|
|
|
|
"""
|
|
|
|
if self.is_Simulated_Universe:
|
|
|
|
if self.name.startswith('Simulated_Universe_World'):
|
|
|
|
return 'rogue'
|
|
|
|
else:
|
|
|
|
return 'dlc'
|
|
|
|
else:
|
|
|
|
return ''
|
|
|
|
|
2024-05-11 10:21:28 +00:00
|
|
|
@classmethod
|
|
|
|
def find_dungeon_id(cls, dungeon_id):
|
|
|
|
"""
|
|
|
|
Args:
|
|
|
|
dungeon_id:
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
DungeonList: DungeonList object or None
|
|
|
|
"""
|
|
|
|
for instance in cls.instances.values():
|
|
|
|
if instance.dungeon_id == dungeon_id:
|
|
|
|
return instance
|
|
|
|
return None
|
|
|
|
|
2024-05-08 13:46:53 +00:00
|
|
|
@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
|
|
|
|
|
|
|
|
|
2023-06-16 20:24:13 +00:00
|
|
|
@dataclass(repr=False)
|
2023-06-14 16:15:14 +00:00
|
|
|
class DungeonEntrance(Keyword):
|
|
|
|
instances: ClassVar = {}
|
2023-10-09 03:36:56 +00:00
|
|
|
|
|
|
|
|
|
|
|
@dataclass(repr=False)
|
|
|
|
class DungeonDetailed(Keyword):
|
|
|
|
instances: ClassVar = {}
|