Files
dcalc/backend/core/basic/equipment.py
T
2026-06-29 01:34:57 +08:00

435 lines
16 KiB
Python

import importlib
from collections.abc import Sequence
from functools import cache
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
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
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]
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
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
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
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
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)