PaiGram/plugins/genshin/model/converters/enka.py

198 lines
7.8 KiB
Python
Raw Normal View History

from decimal import Decimal
from enkanetwork import (
CharacterInfo as EnkaCharacterInfo,
CharacterStats as EnkaCharacterStats,
StatsPercentage,
Equipments,
EquipmentsType,
EquipType,
EquipmentsStats,
DigitType as EnkaDigitType,
)
from plugins.genshin.model import (
CharacterInfo,
Digit,
DigitType,
CharacterStats,
WeaponInfo,
WeaponType,
Artifact,
ArtifactPosition,
ArtifactAttribute,
ArtifactAttributeType,
)
from plugins.genshin.model.metadata import Metadata
metadata = Metadata()
class EnkaConverter:
@classmethod
def to_weapon_type(cls, type_str: str) -> WeaponType:
if type_str == "WEAPON_BOW":
return WeaponType.BOW
if type_str == "WEAPON_CATALYST":
return WeaponType.CATALYST
if type_str == "WEAPON_CLAYMORE":
return WeaponType.CLAYMORE
if type_str == "WEAPON_POLE":
return WeaponType.POLEARM
if type_str == "WEAPON_SWORD_ONE_HAND":
return WeaponType.SWORD
if type_str == "单手剑":
return WeaponType.SWORD
raise ValueError(f"Unknown weapon type: {type_str}")
@classmethod
def to_weapon_info(cls, equipment: Equipments) -> WeaponInfo:
if equipment.type != EquipmentsType.WEAPON:
raise ValueError(f"Not weapon equipment type: {equipment.type}")
weapon_data = metadata.weapon_metadata.get(str(equipment.id))
if not weapon_data:
raise ValueError(f"Unknown weapon id: {equipment.id}")
return WeaponInfo(
id=equipment.id,
weapon=weapon_data["route"],
type=cls.to_weapon_type(weapon_data["type"]),
level=equipment.level,
max_level=equipment.max_level,
refinement=equipment.refinement,
ascension=equipment.ascension,
)
@classmethod
def to_artifact_attribute_type(cls, prop_id: str) -> ArtifactAttributeType: # skipcq: PY-R1000
if prop_id == "FIGHT_PROP_HP":
return ArtifactAttributeType.HP
if prop_id == "FIGHT_PROP_ATTACK":
return ArtifactAttributeType.ATK
if prop_id == "FIGHT_PROP_DEFENSE":
return ArtifactAttributeType.DEF
if prop_id == "FIGHT_PROP_HP_PERCENT":
return ArtifactAttributeType.HP_PERCENT
if prop_id == "FIGHT_PROP_ATTACK_PERCENT":
return ArtifactAttributeType.ATK_PERCENT
if prop_id == "FIGHT_PROP_DEFENSE_PERCENT":
return ArtifactAttributeType.DEF_PERCENT
if prop_id == "FIGHT_PROP_ELEMENT_MASTERY":
return ArtifactAttributeType.ELEMENTAL_MASTERY
if prop_id == "FIGHT_PROP_CHARGE_EFFICIENCY":
return ArtifactAttributeType.ENERGY_RECHARGE
if prop_id == "FIGHT_PROP_CRITICAL":
return ArtifactAttributeType.CRIT_RATE
if prop_id == "FIGHT_PROP_CRITICAL_HURT":
return ArtifactAttributeType.CRIT_DMG
if prop_id == "FIGHT_PROP_HEAL_ADD":
return ArtifactAttributeType.HEALING_BONUS
if prop_id == "FIGHT_PROP_FIRE_ADD_HURT":
return ArtifactAttributeType.PYRO_DMG_BONUS
if prop_id == "FIGHT_PROP_WATER_ADD_HURT":
return ArtifactAttributeType.HYDRO_DMG_BONUS
if prop_id == "FIGHT_PROP_ELEC_ADD_HURT":
return ArtifactAttributeType.ELECTRO_DMG_BONUS
if prop_id == "FIGHT_PROP_ICE_ADD_HURT":
return ArtifactAttributeType.CRYO_DMG_BONUS
if prop_id == "FIGHT_PROP_WIND_ADD_HURT":
return ArtifactAttributeType.ANEMO_DMG_BONUS
if prop_id == "FIGHT_PROP_ROCK_ADD_HURT":
return ArtifactAttributeType.GEO_DMG_BONUS
if prop_id == "FIGHT_PROP_GRASS_ADD_HURT":
return ArtifactAttributeType.DENDRO_DMG_BONUS
if prop_id == "FIGHT_PROP_PHYSICAL_ADD_HURT":
return ArtifactAttributeType.PHYSICAL_DMG_BONUS
raise ValueError(f"Unknown artifact attribute type: {prop_id}")
@classmethod
def to_artifact_attribute(cls, equip_stat: EquipmentsStats) -> ArtifactAttribute:
return ArtifactAttribute(
type=cls.to_artifact_attribute_type(equip_stat.prop_id),
digit=Digit(
value=Decimal(equip_stat.value),
type=DigitType.PERCENT if equip_stat.type == EnkaDigitType.PERCENT else DigitType.NUMERIC,
),
)
@classmethod
def to_artifact_position(cls, equip_type: EquipType) -> ArtifactPosition:
if equip_type == EquipType.Flower:
return ArtifactPosition.FLOWER
if equip_type == EquipType.Feather:
return ArtifactPosition.PLUME
if equip_type == EquipType.Sands:
return ArtifactPosition.SANDS
if equip_type == EquipType.Goblet:
return ArtifactPosition.GOBLET
if equip_type == EquipType.Circlet:
return ArtifactPosition.CIRCLET
raise ValueError(f"Unknown artifact position: {equip_type}")
@classmethod
def to_artifact(cls, equipment: Equipments) -> Artifact:
if equipment.type != EquipmentsType.ARTIFACT:
raise ValueError(f"Not artifact equipment type: {equipment.type}")
artifact_data = next(
(
data
for data in metadata.artifacts_metadata.values()
if data["name"] == equipment.detail.artifact_name_set
),
None,
)
if not artifact_data:
raise ValueError(f"Unknown artifact: {equipment}")
return Artifact(
id=artifact_data["id"],
set=artifact_data["route"],
position=cls.to_artifact_position(equipment.detail.artifact_type),
level=equipment.level,
rarity=equipment.detail.rarity,
main_attribute=cls.to_artifact_attribute(equipment.detail.mainstats),
sub_attributes=[cls.to_artifact_attribute(stat) for stat in equipment.detail.substats],
)
@classmethod
def to_character_stats(cls, character_stats: EnkaCharacterStats) -> CharacterStats:
return CharacterStats(
**{
stat: Digit(
value=Decimal(value.value),
type=DigitType.PERCENT if isinstance(value, StatsPercentage) else DigitType.NUMERIC,
)
for stat, value in character_stats._iter() # pylint: disable=W0212
}
)
@classmethod
def to_character(cls, character_info: EnkaCharacterInfo) -> str:
character_id = str(character_info.id)
if character_id in ("10000005", "10000007"):
character_id += f"-{character_info.element.name.lower()}"
character_data = metadata.characters_metadata.get(character_id)
if not character_data:
raise ValueError(f"Unknown character: {character_info.name}\n{character_info}")
return character_data["route"]
@classmethod
def to_character_info(cls, character_info: EnkaCharacterInfo) -> CharacterInfo:
weapon_equip = next((equip for equip in character_info.equipments if equip.type == EquipmentsType.WEAPON), None)
artifacts_equip = [equip for equip in character_info.equipments if equip.type == EquipmentsType.ARTIFACT]
return CharacterInfo(
id=character_info.id,
character=cls.to_character(character_info),
rarity=character_info.rarity,
weapon_info=cls.to_weapon_info(weapon_equip) if weapon_equip else None,
artifacts=[cls.to_artifact(equip) for equip in artifacts_equip],
level=character_info.level,
max_level=character_info.max_level,
ascension=character_info.ascension,
constellation=character_info.constellations_unlocked,
skills=[skill.level for skill in character_info.skills],
stats=cls.to_character_stats(character_info.stats),
)