Skip to content

Commit

Permalink
✨ Support starrail new characters
Browse files Browse the repository at this point in the history
  • Loading branch information
omg-xtao authored Feb 6, 2024
1 parent 240774f commit b4d66a7
Showing 1 changed file with 179 additions and 2 deletions.
181 changes: 179 additions & 2 deletions simnet/models/starrail/chronicle/characters.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,25 @@
"""Starrail chronicle character."""
from typing import List, Optional
from typing import List, Optional, Any, Dict

from pydantic import validator

from simnet.models.base import APIModel

from .. import character

__all__ = [
"StarRailEquipment",
"Rank",
"RelicProp",
"Relic",
"Rank",
"CharacterProp",
"SkillStage",
"Skill",
"StarRailDetailCharacter",
"EquipWiki",
"PropertyInfo",
"RecommendProperty",
"RelicProperty",
"StarRailDetailCharacters",
]

Expand All @@ -25,6 +35,14 @@ class StarRailEquipment(APIModel):
icon: str


class RelicProp(APIModel):
"""Character relic property."""

property_type: int
times: int
value: str


class Relic(APIModel):
"""Character relic."""

Expand All @@ -35,6 +53,8 @@ class Relic(APIModel):
desc: str
icon: str
rarity: int
main_property: RelicProp
properties: List[RelicProp]


class Rank(APIModel):
Expand All @@ -48,6 +68,47 @@ class Rank(APIModel):
is_unlocked: bool


class CharacterProp(APIModel):
"""Character property."""

property_type: int
base: str
add: str
final: str

@property
def show_add(self) -> bool:
"""Show add."""
return self.add not in ["0.0", "0.0%", "0"]


class SkillStage(APIModel):
"""Character skill stage."""

desc: str
name: str
level: int
remake: str
item_url: str
is_activated: bool
is_rank_work: bool


class Skill(APIModel):
"""Character skill."""

point_id: int
point_type: int
item_url: str
level: int
is_activated: bool
is_rank_work: bool
pre_point: int
anchor: str
remake: str
skill_stages: List[SkillStage]


class StarRailDetailCharacter(character.StarRailPartialCharacter):
"""StarRail character with equipment and relics."""

Expand All @@ -56,9 +117,125 @@ class StarRailDetailCharacter(character.StarRailPartialCharacter):
relics: List[Relic]
ornaments: List[Relic]
ranks: List[Rank]
properties: List[CharacterProp]
skills: List[Skill]
base_type: int
figure_path: str

@property
def skills_map(self) -> List[List[Skill]]:
"""Map skills."""
data = []
skills = self.skills.copy()
for skill in skills.copy():
if skill.pre_point == 0:
data.append([skill])
skills.remove(skill)
while True:
for skill in skills.copy():
for item in data:
item_ids = [i.point_id for i in item]
if skill.pre_point in item_ids and skill.point_id not in item_ids:
item.append(skill)
skills.remove(skill)
break
if not skills:
break
new_data = []
for item in data:
if len(item) < 2:
continue
new_data.append(sorted(item, key=lambda x: x.point_id))
return new_data

@property
def skills_single(self) -> List[Skill]:
"""Single skills."""
map_ids = []
for item in self.skills_map:
map_ids.extend([i.point_id for i in item])
return [i for i in self.skills if i.point_id not in map_ids][5:]

@property
def skills_main(self) -> List[Skill]:
"""Main skills."""
return self.skills[:4]


class EquipWiki(APIModel):
"""Equipment wiki."""

id: int
url: str


class PropertyInfo(APIModel):
"""Property info."""

property_type: int
name: str
icon: str
property_name_relic: str
property_name_filter: str


class RecommendProperty(APIModel):
"""Recommend property."""

id: int
recommend_relic_properties: List[int]
custom_relic_properties: List[int]
is_custom_property_valid: bool


class RelicProperty(APIModel):
"""Relic property."""

property_type: int
modify_property_type: int


class StarRailDetailCharacters(APIModel):
"""StarRail characters."""

avatar_list: List[StarRailDetailCharacter]
equip_wiki: List[EquipWiki]
property_info: List[PropertyInfo]
recommend_property: List[RecommendProperty]
relic_properties: List[RelicProperty]

@staticmethod
def _parse(v: Dict[str, Any], key: str = None, value_key: str = None) -> List[Dict[str, Any]]:
"""Parse dict to list."""
new_list = []
for k, value in v.items():
if isinstance(value, str):
v_ = {value_key: value}
else:
v_ = value
if key:
v_[key] = k
new_list.append(v_)
return new_list

@validator("equip_wiki", pre=True)
def parse_equip_wiki(cls, v: Dict[str, str]) -> List[Dict[str, str]]:
"""Parse equip wiki."""
return cls._parse(v, "id", "url")

@validator("property_info", pre=True)
def parse_property_info(cls, v: Dict[str, Any]) -> List[Dict[str, Any]]:
"""Parse property info."""
return cls._parse(v)

@validator("recommend_property", pre=True)
def parse_recommend_property(cls, v: Dict[str, Any]) -> List[Dict[str, Any]]:
"""Parse recommend property."""
return cls._parse(v, "id")

def get_recommend_property_by_cid(self, character_id: int) -> Optional[RecommendProperty]:
"""Get recommend property by character id."""
for i in self.recommend_property:
if i.id == character_id:
return i
return None

0 comments on commit b4d66a7

Please sign in to comment.