import importlib from collections.abc import Sequence from functools import cache import re from sqlalchemy.orm import Session from database.models import EmblemData, OathData, OathSuitData, OathSuitSkillData, PrimerData, EquData, SuitData, EnchantData, JadeData from database.connect import get_db_engine as get_engine from core.basic.equipment_registry import EquipmentRegistry def parse_to_number_list(info: str, default: Sequence[float] = (0,)) -> list[float]: return list(default) if not info else [float(i) for i in info.split(',')] def parse_to_string_list(info: str, default: Sequence[str] = ('',)) -> list[str]: return list(default) if not info else [i for i in info.split(',')] def parse_to_int_list(info: str, default: Sequence[int] = (0,)) -> list[int]: return list(default) if not info else [int(i) for i in info.split(',')] class Equ: id: str name: str rarity: str itemType: str itemDetailType: str suit: list[str] Point: list[float] | float categorize: str imageUrl: str detail: str bufferDetail: str STR: list[float] | float INT: list[float] | float Vitality: list[float] | float Spirit: list[float] | float AtkP: list[float] | float AtkM: list[float] | float AtkI: list[float] | float SkillAttack: list[float] | float Attack: list[float] | float Buffer: list[float] | float max_adaptation: int effectDamage: list[float] def __init__(self, **kwargs): self.__dict__.update(kwargs) def adapt(self, adaptation: int = 0): """调适 Args: adaptation (int): 调适等级 """ temp = self.__dict__.copy() keys = [key for key in EquData.__dict__.keys() if key[0].isupper()] for attr in keys: value = getattr(self, attr) temp[attr] = value[min(adaptation, len(value) - 1)] if isinstance(value, list) else value return Equ(**temp) class Suit: id: int suitId: int suitName: str rarity: str name: str point: int level: int count: int imageUrl: str SkillAttack: float Attack: float def __init__(self, **kwargs): self.__dict__.update(kwargs) class Equipments: def __init__(self, version='0'): self.version = version self.engine = get_engine(version) try: self.equs: list[Equ] = [] self.oaths: list[Oath] = [] self.oath_dict: dict[str, Oath] = {} # self.stones: list[Equ] = [] self.funs = self.init_func() self.equ_dict: dict[str, Equ] = {} # self.stone_dict: dict[str, Equ] = {} self.jades = [] self.enchants = [] self.emblems = [] self.suits: list[Suit] = [] self.suit_dict: dict[str, Suit] = {} self.suit_id_dict: dict[str, Suit] = {} self.oath_suits: list[OathSuit] = [] self.oath_suit_dict: dict[str, OathSuit] = {} self.init_equs() self.init_suits() self.init_enchants() # self.init_stones() self.init_emblem() self.init_jades() self.init_oaths() self.init_oath_suits() finally: self.engine.dispose() self.engine = None def init_equs(self): """从数据库中获取所有装备信息""" with Session(self.engine) as session: db_list = session.query(EquData).all() keys = [key for key in EquData.__dict__.keys() if key[0].isupper()] + ['suit'] for item in db_list: max_adaptation = 0 item.id = str(item.id) for attr in keys: if attr == 'suit': value = parse_to_number_list(getattr(item, attr), []) value = [str(int(i)) for i in value] else: value = parse_to_number_list(getattr(item, attr)) if attr != 'suit': max_adaptation = max(max_adaptation, len(value) - 1) setattr(item, attr, value) equ_dict = {k: v for k, v in item.__dict__.items() if not k.startswith('_')} equ_dict['max_adaptation'] = max_adaptation effect_damage = re.findall(r'(?:伤害量|攻击力) : ([\d,]+)%', equ_dict.get('detail', '') if equ_dict.get('detail', '') else '') equ_dict['effectDamage'] = [float(i.replace(',', '')) for i in effect_damage] if effect_damage else [] equ = Equ(**equ_dict) self.equs.append(equ) self.equ_dict[equ.id] = equ # def init_stones(self): # """从数据库中获取所有装备信息""" # with Session(self.engine) as session: # db_list = session.query(StoneData).all() # keys = [key for key in StoneData.__dict__.keys() if key[0].isupper()] + ['suit'] # for item in db_list: # max_adaptation = 0 # item.id = str(item.id) # for attr in keys: # if attr == 'suit': # value = parse_to_number_list(getattr(item, attr), []) # value = [str(int(i)) for i in value] # else: # value = parse_to_number_list(getattr(item, attr)) # max_adaptation = max(max_adaptation, len(value) - 1) # setattr(item, attr, value) # stone_dict = {k: v for k, v in item.__dict__.items() if not k.startswith('_')} # stone_dict['max_adaptation'] = max_adaptation # stone = Equ(**stone_dict) # self.stones.append(stone) # self.stone_dict[stone.id] = stone def init_suits(self): """从数据库中获取所有套装信息""" with Session(self.engine) as session: db_list = session.query(SuitData).all() for item in db_list: lvs = len(item.point.split(',')) suits = {k: v for k, v in item.__dict__.items() if not k.startswith('_')} for i in range(1, lvs + 1): suit = {k: v for k, v in suits.items()} suit['point'] = int(suit['point'].split(',')[i - 1]) suit['level'] = i skillAttaks = parse_to_number_list(suit['SkillAttack'], [0]) suit['SkillAttack'] = 0 if i - 1 >= len(skillAttaks) else skillAttaks[i - 1] attacks = parse_to_number_list(suit['Attack'], [0]) suit['Attack'] = 0 if i - 1 >= len(attacks) else attacks[i - 1] buffers = parse_to_number_list(suit['Buffer'], [0]) suit['Buffer'] = 0 if i - 1 >= len(buffers) else buffers[i - 1] effect_damage = re.findall(r'(?:伤害量|攻击力) : ([\d,]+)%', suit.get('value', '') if suit.get('value', '') else '') suit['effectDamage'] = [float(i.replace(',', '')) for i in effect_damage] if effect_damage else [] suit_obj = Suit(**suit) self.suits.append(suit_obj) self.suit_dict.setdefault(str(suit['suitId']), []).append(suit_obj) self.suit_id_dict[str(suit_obj.id)] = suit_obj pass pass def init_enchants(self): """从数据库中获取所有附魔信息""" with Session(self.engine) as session: db_list = session.query(EnchantData).all() for item in db_list: enchant = {k: v for k, v in item.__dict__.items() if not k.startswith('_')} enchant['position'] = [] if enchant['itemType'] is None else enchant['itemType'].split(',') enchant['categorize'] = [] if enchant['categorize'] is None else enchant['categorize'].split(',') del enchant['itemType'] self.enchants.append(enchant) pass pass def init_emblem(self): """从数据库中获取所有徽章信息""" with Session(self.engine) as session: db_list = session.query(EmblemData).all() for item in db_list: emblem = {k: v for k, v in item.__dict__.items() if not k.startswith('_')} # emblem['position'] = [] if emblem['itemType'] is None else emblem['itemType'].split(',') # emblem['categorize'] = [] if emblem['categorize'] is None else emblem['categorize'].split(',') # del emblem['itemType'] self.emblems.append(emblem) pass pass def init_jades(self): """从数据库中获取所有辟邪玉信息""" with Session(self.engine) as session: db_list = session.query(JadeData).all() for item in db_list: jade = {k: v for k, v in item.__dict__.items() if not k.startswith('_')} self.jades.append(jade) pass pass def init_oaths(self): """从数据库中获取所有誓约信息""" with Session(self.engine) as session: db_list_1 = session.query(OathData).all() db_list_2 = session.query(PrimerData).all() keys = [key for key in OathData.__dict__.keys() if key[0].isupper()] for item in db_list_1 + db_list_2: max_adaptation = 0 item.id = str(item.id) if item.wearUrl is None: item.wearUrl = item.imageUrl for attr in keys: value = parse_to_number_list(getattr(item, attr)) max_adaptation = max(max_adaptation, len(value) - 1) setattr(item, attr, value) for attr in ['wearUrl', 'position', 'suit']: value = [] if getattr(item, attr) is None else getattr(item, attr).split(',') setattr(item, attr, value) oath_dict = {k: v for k, v in item.__dict__.items() if not k.startswith('_')} oath_dict['max_adaptation'] = max_adaptation oath = Oath(**oath_dict) self.oaths.append(oath) self.oath_dict[oath.id] = oath def init_oath_suits(self): """从数据库中获取所有誓约套装信息""" with Session(self.engine) as session: db_list = session.query(OathSuitData).all() db_skills_list = session.query(OathSuitSkillData).all() skill_list = [] for item in db_skills_list: lvs = len(item.SkillAttack.split(',')) skills = {k: v for k, v in item.__dict__.items() if not k.startswith('_')} for i in range(1, lvs + 1): skill = {k: v for k, v in skills.items()} skillAttacks = parse_to_number_list(skill['SkillAttack'], [0]) skill['SkillAttack'] = 0 if i - 1 >= len(skillAttacks) else skillAttacks[i - 1] attacks = parse_to_number_list(skill['Attack'], [0]) skill['Attack'] = 0 if i - 1 >= len(attacks) else attacks[i - 1] buffers = parse_to_number_list(skill['Buffer'], [0]) skill['Buffer'] = 0 if i - 1 >= len(buffers) else buffers[i - 1] skill['level'] = i effect_damage = re.findall(r'(?:伤害量|攻击力) : ([\d,]+)%', skill.get('value', '') if skill.get('value', '') else '') skill['effectDamage'] = [float(i.replace(',', '')) for i in effect_damage] if effect_damage else [] skill_obj = OathSuitSkill(**skill) skill_list.append(skill_obj) for item in db_list: lvs = len(item.point.split(',')) suits = {k: v for k, v in item.__dict__.items() if not k.startswith('_')} for i in range(1, lvs + 1): suit = {k: v for k, v in suits.items()} suit['points'] = suit['point'] suit['point'] = int(suit['point'].split(',')[i - 1]) skills = [x for x in skill_list if x.suitId == suit['suitId'] and x.key == suit['key'] and x.level == i] suit['level'] = i skillAttaks = parse_to_number_list(suit['SkillAttack'], [0]) suit['SkillAttack'] = (0 if len(skillAttaks) == 0 else skillAttaks[0]) if i - 1 >= len(skillAttaks) else skillAttaks[i - 1] attacks = parse_to_number_list(suit['Attack'], [0]) suit['Attack'] = (0 if len(attacks) == 0 else attacks[0]) if i - 1 >= len(attacks) else attacks[i - 1] buffers = parse_to_number_list(suit['Buffer'], [0]) suit['Buffer'] = (0 if len(buffers) == 0 else buffers[0]) if i - 1 >= len(buffers) else buffers[i - 1] suit['skills'] = [OathSuitSkill(**{k: v for k, v in skill.__dict__.items() if not k.startswith('_')}) for skill in skills] oath_suit = OathSuit(**suit) self.oath_suits.append(oath_suit) self.oath_suit_dict.setdefault(str(suit['suitId']), []).append(oath_suit) pass pass def init_func(self): """根据装备版本加载装备效果""" try: funs = importlib.import_module(f'core.equipment.version_{self.version}') except Exception: funs = importlib.import_module('core.equipment.version_0') return funs @cache def get_suit_info(self, suitId: str | int, point: int = 0, count: int = 0) -> list[Suit]: """根据套装点数返回对应适用的套装属性\n 新套装只需要传入suitID和point即可,count默认为0\n 老套装需要传入suitID和count即可,point默认为0 """ if suitId not in self.suit_dict: return [] # 先筛选出点数小于等于point和数量小于等于count的套装 suits: list[Suit] = [suit for suit in self.suit_dict[str(suitId)] if suit.point <= point and suit.count <= count] result: dict[int, Suit] = {} # 取每种count套装中点数最高的 for suit in suits: if suit.count not in result or suit.point > result[suit.count].point: result[suit.count] = suit return list(result.values()) @cache def get_oath_suit_info(self, suitId: str | int, point: int = 0, count: int = 0) -> list['OathSuit']: """根据套装点数返回对应适用的誓约套装属性\n 新套装只需要传入suitID和point即可,count默认为0\n 老套装需要传入suitID和count即可,point默认为0 """ if suitId not in self.oath_suit_dict: return [] # 先筛选出点数小于等于point和数量小于等于count的套装 suits: list[OathSuit] = [suit for suit in self.oath_suit_dict[str(suitId)] if suit.point <= point and suit.count <= count] result: dict[int, OathSuit] = {} # 取每种count套装中点数最高的 for suit in suits: if suit.count not in result or suit.point > result[suit.count].point: result[suit.count] = suit return list(result.values()) class EquEffect: name: str = '' """装备技能名称""" icon: str = '' """技能图标""" cd: float = 0 """技能冷却时间""" data: float = 0 """伤害量""" def __init__(self, name: str, icon: str, cd: float, data: float): self.name = name self.icon = icon self.cd = cd self.data = data class Oath: id: str name: str rarity: str position: list[str] suit: list[str] Point: list[float] | float categorize: str imageUrl: str detail: str bufferDetail: str STR: list[float] | float INT: list[float] | float Vitality: list[float] | float Spirit: list[float] | float AtkP: list[float] | float AtkM: list[float] | float AtkI: list[float] | float SkillAttack: list[float] | float Attack: list[float] | float Buffer: list[float] | float wearUrl: list[str] max_adaptation: int itemType: str itemDetailType: str effectDamage: list[float] def __init__(self, **kwargs): self.__dict__.update(kwargs) def adapt(self, adaptation: int = 0): """调适 Args: adaptation (int): 调适等级 """ temp = self.__dict__.copy() keys = [key for key in OathData.__dict__.keys() if key[0].isupper()] for attr in keys: value = getattr(self, attr) temp[attr] = value[min(adaptation, len(value) - 1)] if isinstance(value, list) else value return Oath(**temp) class OathSuitSkill: id: int key: str suitId: int suitName: str skillId: int name: str rarity: str imageUrl: str SkillAttack: float Attack: float Buffer: float value: str bufferValue: str level: int effectDamage: list[float] def __init__(self, **kwargs): for key in ['SkillAttack', 'Attack', 'Buffer']: if kwargs.get(key) is None: kwargs[key] = 0 self.__dict__.update(kwargs) class OathSuit: id: int key: str suitId: int suitName: str rarity: str name: str point: int points: str level: int count: int imageUrl: str SkillAttack: float Attack: float Buffer: float skills: list[OathSuitSkill] def __init__(self, **kwargs): self.__dict__.update(kwargs) _equipment_registry = EquipmentRegistry(Equipments) def get_equipment(version: str = '0') -> Equipments: return _equipment_registry.get(version)