PaiGram/plugins/genshin/model/base.py

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

206 lines
7.9 KiB
Python
Raw Normal View History

from decimal import Decimal
from enum import Enum
from typing import Optional, List, NewType
2024-11-30 14:32:07 +00:00
from pydantic import field_validator, BaseModel, Field, ValidationInfo
# TODO: 考虑自动生成Enum
Character = NewType("Character", str)
Weapon = NewType("Weapon", str)
Set = NewType("Set", str)
class DigitType(Enum):
NUMERIC = "numeric"
PERCENT = "percent"
class Digit(BaseModel):
type: DigitType
value: Decimal
class WeaponType(Enum):
BOW = "bow"
CLAYMORE = "claymore"
CATALYST = "catalyst"
POLEARM = "polearm"
SWORD = "sword"
class ArtifactPosition(Enum):
FLOWER = "flower"
PLUME = "plume"
SANDS = "sands"
GOBLET = "goblet"
CIRCLET = "circlet"
class ArtifactAttributeType(Enum):
HP = "hp"
ATK = "atk"
DEF = "def"
HP_PERCENT = "hp_percent"
ATK_PERCENT = "atk_percent"
DEF_PERCENT = "def_percent"
ELEMENTAL_MASTERY = "elemental_mastery"
ENERGY_RECHARGE = "energy_recharge"
CRIT_RATE = "crit_rate"
CRIT_DMG = "crit_dmg"
HEALING_BONUS = "healing_bonus"
PYRO_DMG_BONUS = "pyro_dmg_bonus"
HYDRO_DMG_BONUS = "hydro_dmg_bonus"
DENDRO_DMG_BONUS = "dendro_dmg_bonus"
ELECTRO_DMG_BONUS = "electro_dmg_bonus"
ANEMO_DMG_BONUS = "anemo_dmg_bonus"
CRYO_DMG_BONUS = "cryo_dmg_bonus"
GEO_DMG_BONUS = "geo_dmg_bonus"
PHYSICAL_DMG_BONUS = "physical_dmg_bonus"
class ArtifactAttribute(BaseModel):
type: ArtifactAttributeType
digit: Digit
class WeaponInfo(BaseModel):
id: int = 0
weapon: Weapon = ""
type: WeaponType
level: int = 0
max_level: int = 0
refinement: int = 0
ascension: int = 0
2024-11-30 14:32:07 +00:00
@field_validator("max_level")
@classmethod
def validate_max_level(cls, v, info: ValidationInfo):
if v == 0:
2024-11-30 14:32:07 +00:00
return info.data["level"]
if v < info.data["level"]:
raise ValueError("max_level must be greater than or equal to level")
return v
2024-11-30 14:32:07 +00:00
@field_validator("refinement")
@classmethod
def validate_refinement(cls, v):
if v < 0 or v > 5:
raise ValueError("refinement must be between 1 and 5")
return v
class Artifact(BaseModel):
id: int = 0
set: Set = ""
position: ArtifactPosition
level: int = 0
rarity: int = 0
main_attribute: ArtifactAttribute
sub_attributes: List[ArtifactAttribute] = []
2024-11-30 14:32:07 +00:00
@field_validator("level")
@classmethod
def validate_level(cls, v):
if v < 0 or v > 20:
raise ValueError("level must be between 0 and 20")
return v
2024-11-30 14:32:07 +00:00
@field_validator("rarity")
@classmethod
def validate_rarity(cls, v):
if v < 0 or v > 5:
raise ValueError("rarity must be between 0 and 5")
return v
2024-11-30 14:32:07 +00:00
@field_validator("sub_attributes")
@classmethod
def validate_sub_attributes(cls, v):
if len(v) > 4:
raise ValueError("sub_attributes must not be greater than 4")
return v
class CharacterStats(BaseModel):
BASE_HP: Digit = Digit(type=DigitType.NUMERIC, value=Decimal(0))
HP: Digit = Field(Digit(type=DigitType.NUMERIC, value=Decimal(0)), alias="FIGHT_PROP_HP")
HP_PERCENT: Digit = Field(Digit(type=DigitType.PERCENT, value=Decimal(0)), alias="FIGHT_PROP_HP_PERCENT")
BASE_ATTACK: Digit = Field(Digit(type=DigitType.NUMERIC, value=Decimal(0)), alias="FIGHT_PROP_BASE_ATTACK")
ATTACK: Digit = Field(Digit(type=DigitType.NUMERIC, value=Decimal(0)), alias="FIGHT_PROP_ATTACK")
ATTACK_PERCENT: Digit = Field(Digit(type=DigitType.PERCENT, value=Decimal(0)), alias="FIGHT_PROP_ATTACK_PERCENT")
BASE_DEFENSE: Digit = Field(Digit(type=DigitType.NUMERIC, value=Decimal(0)), alias="FIGHT_PROP_BASE_DEFENSE")
DEFENSE: Digit = Field(Digit(type=DigitType.NUMERIC, value=Decimal(0)), alias="FIGHT_PROP_DEFENSE")
DEFENSE_PERCENT: Digit = Field(Digit(type=DigitType.PERCENT, value=Decimal(0)), alias="FIGHT_PROP_DEFENSE_PERCENT")
ELEMENTAL_MASTERY: Digit = Field(
Digit(type=DigitType.NUMERIC, value=Decimal(0)), alias="FIGHT_PROP_ELEMENT_MASTERY"
)
CRIT_RATE: Digit = Field(Digit(type=DigitType.PERCENT, value=Decimal(0)), alias="FIGHT_PROP_CRITICAL")
CRIT_DMG: Digit = Field(Digit(type=DigitType.PERCENT, value=Decimal(0)), alias="FIGHT_PROP_CRITICAL_HURT")
HEALING_BONUS: Digit = Field(Digit(type=DigitType.PERCENT, value=Decimal(0)), alias="FIGHT_PROP_HEAL_ADD")
INCOMING_HEALING_BONUS: Digit = Field(
Digit(type=DigitType.PERCENT, value=Decimal(0)), alias="FIGHT_PROP_HEALED_ADD"
)
ENERGY_RECHARGE: Digit = Field(
Digit(type=DigitType.PERCENT, value=Decimal(0)), alias="FIGHT_PROP_CHARGE_EFFICIENCY"
)
CD_REDUCTION: Digit = Field(
Digit(type=DigitType.NUMERIC, value=Decimal(0)), alias="FIGHT_PROP_SKILL_CD_MINUS_RATIO"
)
SHIELD_STRENGTH: Digit = Field(
Digit(type=DigitType.NUMERIC, value=Decimal(0)), alias="FIGHT_PROP_SHIELD_COST_MINUS_RATIO"
)
PYRO_DMG_BONUS: Digit = Field(Digit(type=DigitType.PERCENT, value=Decimal(0)), alias="FIGHT_PROP_FIRE_ADD_HURT")
PYRO_RES: Digit = Field(Digit(type=DigitType.PERCENT, value=Decimal(0)), alias="FIGHT_PROP_FIRE_SUB_HURT")
HYDRO_DMG_BONUS: Digit = Field(Digit(type=DigitType.PERCENT, value=Decimal(0)), alias="FIGHT_PROP_WATER_ADD_HURT")
HYDRO_RES: Digit = Field(Digit(type=DigitType.PERCENT, value=Decimal(0)), alias="FIGHT_PROP_WATER_SUB_HURT")
DENDRO_DMG_BONUS: Digit = Field(Digit(type=DigitType.PERCENT, value=Decimal(0)), alias="FIGHT_PROP_GRASS_ADD_HURT")
DENDRO_RES: Digit = Field(Digit(type=DigitType.PERCENT, value=Decimal(0)), alias="FIGHT_PROP_GRASS_SUB_HURT")
ELECTRO_DMG_BONUS: Digit = Field(Digit(type=DigitType.PERCENT, value=Decimal(0)), alias="FIGHT_PROP_ELEC_ADD_HURT")
ELECTRO_RES: Digit = Field(Digit(type=DigitType.PERCENT, value=Decimal(0)), alias="FIGHT_PROP_ELEC_SUB_HURT")
ANEMO_DMG_BONUS: Digit = Field(Digit(type=DigitType.PERCENT, value=Decimal(0)), alias="FIGHT_PROP_WIND_ADD_HURT")
ANEMO_RES: Digit = Field(Digit(type=DigitType.PERCENT, value=Decimal(0)), alias="FIGHT_PROP_WIND_SUB_HURT")
CRYO_DMG_BONUS: Digit = Field(Digit(type=DigitType.PERCENT, value=Decimal(0)), alias="FIGHT_PROP_ICE_ADD_HURT")
CRYO_RES: Digit = Field(Digit(type=DigitType.PERCENT, value=Decimal(0)), alias="FIGHT_PROP_ICE_SUB_HURT")
GEO_DMG_BONUS: Digit = Field(Digit(type=DigitType.PERCENT, value=Decimal(0)), alias="FIGHT_PROP_ROCK_ADD_HURT")
GEO_RES: Digit = Field(Digit(type=DigitType.PERCENT, value=Decimal(0)), alias="FIGHT_PROP_ROCK_SUB_HURT")
PHYSICAL_DMG_BONUS: Digit = Field(
Digit(type=DigitType.PERCENT, value=Decimal(0)), alias="FIGHT_PROP_PHYSICAL_SUB_HURT"
)
PHYSICAL_RES: Digit = Field(Digit(type=DigitType.PERCENT, value=Decimal(0)), alias="FIGHT_PROP_PHYSICAL_ADD_HURT")
CURRENT_HP: Digit = Field(Digit(type=DigitType.NUMERIC, value=Decimal(0)), alias="FIGHT_PROP_CUR_HP")
MAX_HP: Digit = Field(Digit(type=DigitType.NUMERIC, value=Decimal(0)), alias="FIGHT_PROP_MAX_HP")
CURRENT_ATTACK: Digit = Field(Digit(type=DigitType.NUMERIC, value=Decimal(0)), alias="FIGHT_PROP_CUR_ATTACK")
CURRENT_DEFENSE: Digit = Field(Digit(type=DigitType.NUMERIC, value=Decimal(0)), alias="FIGHT_PROP_CUR_DEFENSE")
class CharacterInfo(BaseModel):
id: int = 0
character: Character = ""
weapon_info: Optional[WeaponInfo] = None
artifacts: List[Artifact] = []
level: int = 0
max_level: int = 0
constellation: int = 0
ascension: int = 0
skills: List[int] = []
rarity: int = 0
stats: CharacterStats = CharacterStats()
2024-11-30 14:32:07 +00:00
@field_validator("max_level")
@classmethod
def validate_max_level(cls, v, info: ValidationInfo):
if v == 0:
2024-11-30 14:32:07 +00:00
return info.data["level"]
if v < info.data["level"]:
raise ValueError("max_level must be greater than or equal to level")
return v
2024-11-30 14:32:07 +00:00
@field_validator("skills")
@classmethod
def validate_skills(cls, v):
if len(v) > 3:
raise ValueError("skills must not be greater than 3")
return v