Skip to content
This repository has been archived by the owner on Jun 9, 2022. It is now read-only.

Commit

Permalink
ADD - Export unit info model to json (#33)
Browse files Browse the repository at this point in the history
Signed-off-by: RaenonX <[email protected]>
  • Loading branch information
RaenonX committed May 20, 2021
1 parent dca22f5 commit af0fafc
Show file tree
Hide file tree
Showing 24 changed files with 295 additions and 39 deletions.
2 changes: 2 additions & 0 deletions dlparse/export/entry/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
"""Data entry classes for the exported data."""
from .base import * # noqa
from .chara_info import CharaInfoEntry
from .dragon_info import DragonInfoEntry
from .enum import ConditionEnumEntry, EnumEntry
from .ex_ability import CharaExAbiltiesEntry
from .skill_atk import CharaAttackingSkillEntry
Expand Down
1 change: 1 addition & 0 deletions dlparse/export/entry/base/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@
from .entry import CsvExportableEntryBase, HashableEntryBase, JsonExportableEntryBase
from .skill import SkillExportEntryBase
from .text import TextEntry
from .unit_info import UnitInfoEntryBase
2 changes: 2 additions & 0 deletions dlparse/export/entry/base/unit_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
if TYPE_CHECKING:
from dlparse.mono.manager import AssetManager

__all__ = ("UnitInfoEntryBase",)

T = TypeVar("T", bound=UnitEntry)


Expand Down
30 changes: 30 additions & 0 deletions dlparse/export/entry/chara_info.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
"""Entry of a character info."""
from dataclasses import dataclass, field
from typing import Any

from dlparse.enums import Weapon
from dlparse.mono.asset import CharaDataEntry
from .base import UnitInfoEntryBase

__all__ = ("CharaInfoEntry",)


@dataclass
class CharaInfoEntry(UnitInfoEntryBase[CharaDataEntry]):
"""Chara info entry class."""

weapon: Weapon = field(init=False)

has_unique_dragon: bool = field(init=False)

def __post_init__(self):
super().__post_init__()

self.weapon = self.unit_data.weapon
self.has_unique_dragon = self.unit_data.has_unique_dragon

def to_json_entry(self) -> dict[str, Any]:
return super().to_json_entry() | {
"weapon": self.weapon.value,
"hasUniqueDragon": self.has_unique_dragon
}
12 changes: 12 additions & 0 deletions dlparse/export/entry/dragon_info.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
"""Entry of a dragon info."""
from dataclasses import dataclass

from dlparse.mono.asset import DragonDataEntry
from .base import UnitInfoEntryBase

__all__ = ("DragonInfoEntry",)


@dataclass
class DragonInfoEntry(UnitInfoEntryBase[DragonDataEntry]):
"""Dragon info entry class."""
4 changes: 4 additions & 0 deletions dlparse/export/funcs/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,7 @@
from .skill_atk import export_atk_skill_as_json, export_atk_skills_as_entries
from .skill_identifiers import export_skill_identifiers_as_entry_dict, export_skill_identifiers_as_json
from .skill_sup import export_sup_skill_as_json, export_sup_skills_as_entries
from .unit_info import (
export_chara_info_as_entries, export_chara_info_as_json,
export_dragon_info_as_entries, export_dragon_info_as_json,
)
4 changes: 2 additions & 2 deletions dlparse/export/funcs/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ def export_transform_skill_entries(
# Get all skills and iterate them
skill_identifiers = chara_data.get_skill_id_entries(asset_manager, include_dragon=include_dragon)
for id_entry in skill_identifiers:
chara_name = chara_data.get_chara_name(asset_manager.asset_text_multi)
chara_name = chara_data.get_name(asset_manager.asset_text_multi)

# Transform every skill data
try:
Expand Down Expand Up @@ -79,7 +79,7 @@ def export_skill_entries(

skipped_messages: list[str] = []

for chara_data in asset_manager.asset_chara_data.playable_chara_data:
for chara_data in asset_manager.asset_chara_data.playable_data:
entries, messages = skill_entry_parse_fn(chara_data, asset_manager, skip_unparsable, include_dragon)

ret.extend(entries)
Expand Down
2 changes: 1 addition & 1 deletion dlparse/export/funcs/collect_enum.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ def collect_ability_data_buff_param(
"""Collect buff parameters from the transformed ability data for each character and compose an image path map."""
units: set[BuffParameter] = set()

for chara_data in asset_manager.asset_chara_data.playable_chara_data:
for chara_data in asset_manager.asset_chara_data.playable_data:
units.update(effect_unit.parameter for effect_unit in transform_fn(chara_data).effect_units)

# Sort the buff paramters by its value to ensure the order will not change frequently,
Expand Down
4 changes: 2 additions & 2 deletions dlparse/export/funcs/ex_ability.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ def export_ex_abilities_as_entries(
entries: list[CharaExAbiltiesEntry] = []
skipped_messages: list[str] = []

for chara_data in asset_manager.asset_chara_data.playable_chara_data:
for chara_data in asset_manager.asset_chara_data.playable_data:
ex_data = asset_manager.transformer_ability.transform_ex_ability(chara_data.ex_id_at_max_level)
chained_ex_data = asset_manager.transformer_ability.transform_chained_ex_ability(
chara_data.cex_id_at_max_level
Expand All @@ -33,7 +33,7 @@ def export_ex_abilities_as_entries(
if skip_unparsable:
skipped_messages.append(
f"[EX Ability] EX ID #{chara_data.ex_id_at_max_level} CEX ID #{chara_data.cex_id_at_max_level}) "
f"of {chara_data.get_chara_name(asset_manager.asset_text_multi)} ({chara_data.id}): {ex}"
f"of {chara_data.get_name(asset_manager.asset_text_multi)} ({chara_data.id}): {ex}"
)
continue

Expand Down
79 changes: 79 additions & 0 deletions dlparse/export/funcs/unit_info.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
"""Functions to export unit info, including characters and dragons."""
from dlparse.errors import (
AbilityConditionUnconvertibleError, AbilityLimitDataNotFoundError, AbilityOnSkillUnconvertibleError,
AbilityVariantUnconvertibleError,
)
from dlparse.export.entry import CharaInfoEntry, DragonInfoEntry
from dlparse.mono.manager import AssetManager
from .base import export_as_json, print_skipped_messages

__all__ = (
"export_chara_info_as_entries", "export_chara_info_as_json",
"export_dragon_info_as_entries", "export_dragon_info_as_json",
)


def export_chara_info_as_entries(
asset_manager: AssetManager, /, skip_unparsable: bool = True
) -> list[CharaInfoEntry]:
"""Export all character info as entries."""
entries: list[CharaInfoEntry] = []
skipped_messages: list[str] = []

for chara_data in asset_manager.asset_chara_data.playable_data:
try:
entries.append(CharaInfoEntry(
asset_manager=asset_manager, unit_data=chara_data
))
except (AbilityOnSkillUnconvertibleError, AbilityConditionUnconvertibleError,
AbilityVariantUnconvertibleError, AbilityLimitDataNotFoundError) as ex:
if skip_unparsable:
skipped_messages.append(
f"[Chara Info] Character ID #{chara_data.id} "
f"({chara_data.get_name(asset_manager.asset_text_multi)})"
)
continue

raise ex

print_skipped_messages(skipped_messages)

return entries


def export_chara_info_as_json(file_path: str, asset_manager: AssetManager, /, skip_unparsable: bool = True):
"""Export all character info as json."""
export_as_json(export_chara_info_as_entries(asset_manager, skip_unparsable=skip_unparsable), file_path)


def export_dragon_info_as_entries(
asset_manager: AssetManager, /, skip_unparsable: bool = True
) -> list[DragonInfoEntry]:
"""Export all character info as entries."""
entries: list[DragonInfoEntry] = []
skipped_messages: list[str] = []

for dragon_data in asset_manager.asset_dragon_data.playable_data:
try:
entries.append(DragonInfoEntry(
asset_manager=asset_manager, unit_data=dragon_data
))
except (AbilityOnSkillUnconvertibleError, AbilityConditionUnconvertibleError,
AbilityVariantUnconvertibleError, AbilityLimitDataNotFoundError) as ex:
if skip_unparsable:
skipped_messages.append(
f"[Dragon Info] Dragon ID #{dragon_data.id} "
f"({dragon_data.get_name(asset_manager.asset_text_multi)})"
)
continue

raise ex

print_skipped_messages(skipped_messages)

return entries


def export_dragon_info_as_json(file_path: str, asset_manager: AssetManager, /, skip_unparsable: bool = True):
"""Export all character info as json."""
export_as_json(export_dragon_info_as_entries(asset_manager, skip_unparsable=skip_unparsable), file_path)
2 changes: 1 addition & 1 deletion dlparse/mono/asset/extension/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@
from .named import NamedEntry
from .skill import SkillEntry
from .skill_discovery import SkillDiscoverableEntry, SkillIdEntry, SkillIdentifierLabel
from .unit import UnitEntry
from .unit import UnitAsset, UnitEntry
from .varied import VariedEntry
14 changes: 14 additions & 0 deletions dlparse/mono/asset/extension/named.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
"""Interface for the named entry."""
from abc import ABC
from dataclasses import dataclass
from typing import TYPE_CHECKING

from dlparse.enums import Language
from dlparse.errors import TextLabelNotFoundError

if TYPE_CHECKING:
from dlparse.mono.asset import TextAssetMultilingual

__all__ = ("NamedEntry",)

Expand All @@ -21,3 +28,10 @@ def name_labels(self) -> list[str]:
Note that the first one should be used first to get the character name. The order matters.
"""
return [self.name_label_2, self.name_label]

def get_name(self, text_asset: "TextAssetMultilingual", language: Language = Language.JP) -> str:
"""Get the unit name in ``language``."""
try:
return text_asset.get_text(language.value, self.name_label_2)
except TextLabelNotFoundError:
return text_asset.get_text(language.value, self.name_label)
21 changes: 18 additions & 3 deletions dlparse/mono/asset/extension/unit.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
"""Interface for various units. This includes character and dragon."""
"""Interface for various types of units. This includes character and dragon."""
from abc import ABC
from dataclasses import dataclass
from datetime import datetime
from typing import Generic, TypeVar

from dlparse.enums import Element
from dlparse.mono.asset.base import MasterEntryBase
from dlparse.mono.asset.base import MasterAssetBase, MasterEntryBase
from .named import NamedEntry
from .varied import VariedEntry

__all__ = ("UnitEntry",)
__all__ = ("UnitEntry", "UnitAsset")


@dataclass
Expand All @@ -23,7 +24,21 @@ class UnitEntry(NamedEntry, VariedEntry, MasterEntryBase, ABC):

release_date: datetime

is_playable: bool

@property
def icon_name(self) -> str:
"""Get the name of the character icon, excluding the file extension."""
return f"{self.base_id}_{self.variation_id:02}_r{self.rarity:02}"


T = TypeVar("T", bound=UnitEntry)


class UnitAsset(Generic[T], MasterAssetBase[T], ABC):
"""Interface for an asset that contains unit entries."""

@property
def playable_data(self) -> list[T]:
"""Get all playable units.."""
return [data for data in self if data.is_playable]
22 changes: 4 additions & 18 deletions dlparse/mono/asset/master/chara_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,12 @@
from datetime import datetime
from typing import Optional, TYPE_CHECKING, TextIO, Union

from dlparse.enums import Element, Language, SkillNumber, Weapon
from dlparse.errors import InvalidSkillNumError, NoUniqueDragonError, TextLabelNotFoundError
from dlparse.enums import Element, SkillNumber, Weapon
from dlparse.errors import InvalidSkillNumError, NoUniqueDragonError
from dlparse.mono.asset.base import MasterAssetBase, MasterEntryBase, MasterParserBase
from dlparse.mono.asset.extension import SkillDiscoverableEntry, SkillIdEntry, UnitEntry
from dlparse.mono.asset.extension import SkillDiscoverableEntry, SkillIdEntry, UnitAsset, UnitEntry
from .dragon_data import DRAGON_SKILL_MAX_LEVEL, DragonDataAsset, DragonDataEntry
from .skill_data import CHARA_SKILL_MAX_LEVEL
from .text_label import TextAssetMultilingual

if TYPE_CHECKING:
from dlparse.mono.manager import AssetManager
Expand Down Expand Up @@ -117,7 +116,6 @@ class CharaDataEntry(UnitEntry, SkillDiscoverableEntry, MasterEntryBase):

is_dragon_drive: bool
"""Bellina, etc."""
is_playable: bool

unique_weapon_id: int

Expand Down Expand Up @@ -331,13 +329,6 @@ def max_skill_level(self, skill_num: SkillNumber):

raise InvalidSkillNumError(skill_num)

def get_chara_name(self, text_asset: TextAssetMultilingual, language: Language = Language.JP) -> str:
"""Get the name of the character."""
try:
return text_asset.get_text(language.value, self.name_label_2)
except TextLabelNotFoundError:
return text_asset.get_text(language.value, self.name_label)

def get_dragon_data(self, dragon_asset: DragonDataAsset) -> DragonDataEntry:
"""
Get the unique dragon data of this character.
Expand Down Expand Up @@ -449,7 +440,7 @@ class SkillReverseSearchResult:
skill_id_entry: SkillIdEntry


class CharaDataAsset(MasterAssetBase[CharaDataEntry]):
class CharaDataAsset(UnitAsset[CharaDataEntry], MasterAssetBase[CharaDataEntry]):
"""Character data asset class."""

asset_file_name = "CharaData.json"
Expand Down Expand Up @@ -504,11 +495,6 @@ def get_chara_data_by_skill_id(
# Chara data not found, returns ``None``
return None

@property
def playable_chara_data(self) -> list[CharaDataEntry]:
"""Get all character data of the playable characters."""
return [data for data in self if data.is_playable]


class CharaDataParser(MasterParserBase[CharaDataEntry]):
"""Class to parse the character data file."""
Expand Down
7 changes: 4 additions & 3 deletions dlparse/mono/asset/master/dragon_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

from dlparse.enums import Element
from dlparse.mono.asset.base import MasterAssetBase, MasterEntryBase, MasterParserBase
from dlparse.mono.asset.extension import SkillEntry, UnitEntry, VariedEntry
from dlparse.mono.asset.extension import SkillEntry, UnitAsset, UnitEntry, VariedEntry

__all__ = ("DragonDataEntry", "DragonDataAsset", "DRAGON_SKILL_MAX_LEVEL")

Expand Down Expand Up @@ -51,11 +51,12 @@ def parse_raw(cls, data: dict[str, Union[str, int]]) -> "DragonDataEntry":
ability_id_2_lv5=data["_Abilities25"],
cv_en_label=data["_CvInfoEn"],
cv_jp_label=data["_CvInfo"],
release_date=cls.parse_datetime(data["_ReleaseStartDate"])
release_date=cls.parse_datetime(data["_ReleaseStartDate"]),
is_playable=bool(data["_IsPlayable"])
)


class DragonDataAsset(MasterAssetBase[DragonDataEntry]):
class DragonDataAsset(UnitAsset[DragonDataEntry], MasterAssetBase[DragonDataEntry]):
"""Dragon data asset class."""

asset_file_name = "DragonData.json"
Expand Down
2 changes: 1 addition & 1 deletion script_chara_overview.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ def chara_skill_overview(chara_id):
id_label for skill_id_entry in skill_id_entries for id_label in skill_id_entry.skill_identifier_labels
]

print(f"{chara_data.get_chara_name(_asset_manager.asset_text_multi)} ({chara_id})")
print(f"{chara_data.get_name(_asset_manager.asset_text_multi)} ({chara_id})")
print()
print(f"Skill Identifiers available: {' / '.join(skill_identifiers)}")
if chara_data.has_unique_dragon:
Expand Down
2 changes: 1 addition & 1 deletion script_diff.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ def check_diff_internal(left: "MasterAssetBase", right: "MasterAssetBase", title
if isinstance(data, SkillDataEntry):
print(f"- {diff_id} ({manager.asset_text.to_text(data.name_label)})")
elif isinstance(data, CharaDataEntry):
print(f"- {diff_id} ({data.get_chara_name(manager.asset_text_multi)})")
print(f"- {diff_id} ({data.get_name(manager.asset_text_multi)})")
else:
print(f"- {diff_id}")

Expand Down
2 changes: 1 addition & 1 deletion tests/test_anomaly_check/test_transform/test_ability.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ def test_transform_all_character_ability(transformer_ability: AbilityTransformer
# Not checking all abilities in the ability asset directly
# because there are some unused or deprecated ability inside.
# We don't want to spend time handling unused things.
for chara_data in asset_manager.asset_chara_data.playable_chara_data:
for chara_data in asset_manager.asset_chara_data.playable_data:
for ability_id in chara_data.ability_ids_all_level:
counter += 1

Expand Down
2 changes: 1 addition & 1 deletion tests/test_anomaly_check/test_transform/test_atk.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
@pytest.mark.holistic
def test_transform_all_attack_skills(transformer_skill: SkillTransformer, asset_manager: AssetManager):
skill_ids: list[int] = []
for chara_data in asset_manager.asset_chara_data.playable_chara_data:
for chara_data in asset_manager.asset_chara_data.playable_data:
skill_ids.extend([
skill_entry.skill_id for skill_entry
in chara_data.get_skill_id_entries(asset_manager, include_dragon=False)
Expand Down
Loading

0 comments on commit af0fafc

Please sign in to comment.