SIMNet/simnet/models/genshin/chronicle/characters.py
2024-10-15 16:28:24 +08:00

223 lines
6.4 KiB
Python

from typing import List, Dict, TYPE_CHECKING
from pydantic import Field, validator
from simnet.models.base import APIModel
from simnet.models.genshin.character import BaseCharacter
if TYPE_CHECKING:
from simnet.models.genshin.chronicle.character_detail import GenshinDetailCharacter
__all__ = (
"Artifact",
"ArtifactSet",
"ArtifactSetEffect",
"Character",
"CharacterWeapon",
"Constellation",
"Outfit",
"PartialCharacter",
)
class PartialCharacter(BaseCharacter):
"""
Represents a Genshin Impact character without any equipment.
Attributes:
level (int): The character's level.
friendship (int): The character's friendship level (also known as fetter).
constellation (int): The number of constellations that are currently active for the character.
"""
icon: str = Field(alias="image")
level: int
friendship: int = Field(alias="fetter")
constellation: int = Field(alias="actived_constellation_num")
class CharacterWeapon(APIModel):
"""
Represents a character's equipped weapon.
Attributes:
id (int): The weapon's ID number.
icon (str): The URL of the weapon's icon.
name (str): The name of the weapon.
rarity (int): The rarity (number of stars) of the weapon.
description (str): The description of the weapon.
level (int): The level of the weapon.
type (str): The type of the weapon (e.g. Sword, Bow, etc.).
ascension (int): The ascension level of the weapon.
refinement (int): The refinement level of the weapon.
"""
id: int
icon: str
name: str
rarity: int
description: str = Field(alias="desc")
level: int
type: str = Field(alias="type_name")
ascension: int = Field(alias="promote_level")
refinement: int = Field(alias="affix_level")
class ArtifactSetEffect(APIModel):
"""
Represents the effect of an artifact set.
Attributes:
pieces (int): The number of artifact pieces required to activate the effect.
effect (str): The description of the effect.
enabled (bool): Whether the effect is currently enabled for the character's equipped artifacts.
Defaults to False.
"""
pieces: int = Field(alias="activation_number")
effect: str
enabled: bool = False
class ArtifactSet(APIModel):
"""
Represents an artifact set.
Attributes:
id (int): The artifact set's ID number.
name (str): The name of the artifact set.
effects (List[ArtifactSetEffect]): The effects of the artifact set.
"""
id: int
name: str
effects: List[ArtifactSetEffect] = Field(alias="affixes")
class Artifact(APIModel):
"""
Represents a character's equipped artifact.
Attributes:
id (int): The artifact's ID number.
icon (str): The URL of the artifact's icon.
name (str): The name of the artifact.
pos_name (str): The name of the artifact's position (e.g. Flower of Life, Plume of Death, etc.).
pos (int): The position of the artifact (1-5).
rarity (int): The rarity (number of stars) of the artifact.
level (int): The level of the artifact.
set (ArtifactSet): The artifact set that the artifact belongs to.
"""
id: int
icon: str
name: str
pos_name: str
pos: int
rarity: int
level: int
set: ArtifactSet
class Constellation(APIModel):
"""
Represents a character constellation.
Attributes:
id (int): The ID number of the constellation.
icon (str): The URL of the constellation's icon.
pos (int): The position of the constellation (1-6).
name (str): The name of the constellation.
effect (str): The description of the effect.
activated (bool): Whether the constellation is currently activated. Defaults to False.
"""
id: int
icon: str
pos: int
name: str
effect: str
activated: bool = Field(alias="is_actived")
@property
def scaling(self) -> bool:
"""Returns whether the constellation is simply for talent scaling."""
return "U" in self.icon
class Outfit(APIModel):
"""
Represents an outfit of a character.
Attributes:
id (int): The ID number of the outfit.
icon (str): The URL of the outfit's icon.
name (str): The name of the outfit.
"""
id: int
icon: str
name: str
class Character(PartialCharacter):
"""
Represents a Genshin Impact character with equipment.
Attributes:
weapon (CharacterWeapon): The character's equipped weapon.
artifacts (List[Artifact]): The character's equipped artifacts.
constellations (List[Constellation]): The character's constellations.
outfits (List[Outfit]): The character's outfits.
"""
weapon: CharacterWeapon
artifacts: List[Artifact] = Field(alias="reliquaries")
constellations: List[Constellation]
outfits: List[Outfit] = Field(alias="costumes")
@validator("artifacts")
def add_artifact_effect_enabled(cls, artifacts: List[Artifact]) -> List[Artifact]:
"""
Determines which artifact set effects are enabled for the character's equipped artifacts.
Args:
artifacts (List[Artifact]): The character's equipped artifacts.
Returns:
List[Artifact]: The character's equipped artifacts with their corresponding artifact set effects enabled if
applicable.
"""
sets: Dict[int, List[Artifact]] = {}
for arti in artifacts:
sets.setdefault(arti.set.id, []).append(arti)
for artifact in artifacts:
for effect in artifact.set.effects:
if effect.pieces <= len(sets[artifact.set.id]):
effect.enabled = True
return artifacts
@staticmethod
def from_detail(data: "GenshinDetailCharacter") -> "Character":
"""
Creates a Character instance from a GenshinDetailCharacter instance.
Args:
data (GenshinDetailCharacter): The detailed character data.
Returns:
Character: A Character instance with the provided detailed data.
"""
base_data = data.base.dict(by_alias=True)
if "weapon" in base_data:
del base_data["weapon"]
return Character(
**base_data,
weapon=data.weapon,
reliquaries=data.artifacts,
constellations=data.constellations,
costumes=data.costumes,
)