mirror of
https://github.com/PaiGramTeam/genshin-wiki.git
synced 2024-11-23 08:00:59 +00:00
🚧 building...
This commit is contained in:
parent
7e957ccea8
commit
fb77ca0569
@ -1,8 +1,78 @@
|
||||
from humps import camelize
|
||||
from datetime import datetime
|
||||
|
||||
from utils.model import BaseConfig, BaseModel
|
||||
# noinspection PyPep8Naming
|
||||
from enum import Enum as E
|
||||
from typing import Any, TYPE_CHECKING, Type
|
||||
|
||||
from databases import Database
|
||||
|
||||
# noinspection PyPep8Naming
|
||||
from ormar import (
|
||||
BaseField,
|
||||
Enum as ENUM,
|
||||
Model as _Model,
|
||||
ModelMeta as _ModelMeta,
|
||||
String as STRING,
|
||||
)
|
||||
from sqlalchemy import MetaData
|
||||
|
||||
from utils import json
|
||||
|
||||
try:
|
||||
import regex as re
|
||||
except ImportError:
|
||||
import re
|
||||
|
||||
if TYPE_CHECKING:
|
||||
pass
|
||||
|
||||
__all__ = ("Model", "String", "Enum")
|
||||
|
||||
DATABASE_URL = "sqlite:///data/db.sqlite"
|
||||
database = Database(DATABASE_URL)
|
||||
metadata = MetaData()
|
||||
|
||||
|
||||
class DataModel(BaseModel):
|
||||
class Config(BaseConfig):
|
||||
alias_generator = lambda x: camelize(x.removesuffix("TextHashMap"))
|
||||
class ModelMeta(_ModelMeta):
|
||||
database = database
|
||||
metadata = metadata
|
||||
|
||||
|
||||
class Model(_Model):
|
||||
class Config(_Model.Config):
|
||||
json_dumps = json.dumps
|
||||
json_loads = json.loads
|
||||
json_encoders = {datetime: lambda v: v.timestamp()}
|
||||
|
||||
|
||||
class String(STRING):
|
||||
def __new__(
|
||||
cls,
|
||||
*,
|
||||
max_length: int = 255,
|
||||
min_length: int = None,
|
||||
regex: str = None,
|
||||
**kwargs: Any,
|
||||
) -> BaseField:
|
||||
return super().__new__(
|
||||
cls=STRING,
|
||||
max_length=max_length,
|
||||
min_length=min_length,
|
||||
regex=regex,
|
||||
**kwargs,
|
||||
)
|
||||
|
||||
|
||||
class Enum(ENUM):
|
||||
def __new__(cls, enum_class: Type[E], **kwargs: Any) -> BaseField:
|
||||
return super().__new__(
|
||||
cls,
|
||||
**{
|
||||
**kwargs,
|
||||
**{
|
||||
k: v
|
||||
for k, v in locals().items()
|
||||
if k not in ["cls", "__class__", "kwargs"]
|
||||
},
|
||||
},
|
||||
)
|
||||
|
2
model/avatar/__init__.py
Normal file
2
model/avatar/__init__.py
Normal file
@ -0,0 +1,2 @@
|
||||
from model.avatar._avatar import *
|
||||
from model.avatar._talente import *
|
@ -6,6 +6,16 @@ from utils.model import BaseModel
|
||||
if TYPE_CHECKING:
|
||||
from model.item import Item
|
||||
|
||||
__all__ = (
|
||||
"Avatar",
|
||||
"AvatarBirth",
|
||||
"AvatarInfo",
|
||||
"AvatarConstellation",
|
||||
"AvatarPromote",
|
||||
"Seuyu",
|
||||
"ItemCount",
|
||||
)
|
||||
|
||||
|
||||
class AvatarBirth(BaseModel):
|
||||
"""角色生日"""
|
||||
@ -46,7 +56,7 @@ class AvatarInfo(BaseModel):
|
||||
"""声优"""
|
||||
|
||||
|
||||
class AvatarItem(BaseModel):
|
||||
class ItemCount(BaseModel):
|
||||
item: "Item"
|
||||
"""物品"""
|
||||
count: int
|
||||
@ -63,43 +73,10 @@ class AvatarPromote(BaseModel):
|
||||
|
||||
coin: int = 0
|
||||
"""摩拉"""
|
||||
items: list[AvatarItem]
|
||||
items: list[ItemCount] = []
|
||||
"""突破所需材料"""
|
||||
|
||||
|
||||
class AvatarSkill(BaseModel):
|
||||
name: str
|
||||
"""技能名称"""
|
||||
description: str
|
||||
"""技能描述"""
|
||||
promote_level: int = 0
|
||||
"""所需突破等级"""
|
||||
icon: str
|
||||
"""图标"""
|
||||
|
||||
|
||||
class AvatarActiveSkill(AvatarSkill):
|
||||
"""角色主动技能"""
|
||||
|
||||
CD: float
|
||||
"""冷却时间"""
|
||||
max_charge_num: int
|
||||
"""技能最大储存次数"""
|
||||
|
||||
|
||||
class AvatarPassiveSkill(AvatarSkill):
|
||||
"""角色被动技能"""
|
||||
|
||||
|
||||
class AvatarSkills(BaseModel):
|
||||
attack_skill: AvatarActiveSkill
|
||||
"""普通攻击"""
|
||||
energy_skill: AvatarActiveSkill
|
||||
"""元素爆发"""
|
||||
proud_skills: list[AvatarSkill]
|
||||
"""被动技能"""
|
||||
|
||||
|
||||
class AvatarConstellation(BaseModel):
|
||||
"""角色命座"""
|
||||
|
103
model/avatar/_talente.py
Normal file
103
model/avatar/_talente.py
Normal file
@ -0,0 +1,103 @@
|
||||
from utils.model import BaseModel
|
||||
from typing import ClassVar
|
||||
|
||||
__all__ = (
|
||||
"Talent",
|
||||
"CombatTalent",
|
||||
"NormalAttack",
|
||||
"ElementalBurst",
|
||||
"ElementalSkill",
|
||||
"AlternateSprint",
|
||||
"PassiveTalent",
|
||||
"AscensionPassive",
|
||||
"FirstAscensionPassive",
|
||||
"FourthAscensionPassive",
|
||||
"UtilityPassive",
|
||||
"MiscellaneousPassive",
|
||||
"AvatarTalents",
|
||||
)
|
||||
|
||||
|
||||
class Talent(BaseModel):
|
||||
name: str
|
||||
"""天赋名称"""
|
||||
description: str
|
||||
"""天赋描述"""
|
||||
icon: str
|
||||
"""图标"""
|
||||
level: int = 0
|
||||
"""解锁等级"""
|
||||
|
||||
params: list[float] = []
|
||||
"""数值参数列表"""
|
||||
|
||||
|
||||
class CombatTalent(Talent):
|
||||
"""战斗天赋"""
|
||||
|
||||
cooldown: float = 0
|
||||
"""冷却时间"""
|
||||
|
||||
|
||||
class NormalAttack(CombatTalent):
|
||||
"""普通攻击"""
|
||||
|
||||
|
||||
class ElementalSkill(CombatTalent):
|
||||
"""元素战技"""
|
||||
|
||||
|
||||
class ElementalBurst(CombatTalent):
|
||||
"""元素爆发"""
|
||||
|
||||
|
||||
class AlternateSprint(CombatTalent):
|
||||
"""冲刺技能"""
|
||||
|
||||
|
||||
class PassiveTalent(Talent):
|
||||
"""被动天赋"""
|
||||
|
||||
|
||||
class AscensionPassive(PassiveTalent):
|
||||
"""突破被动天赋"""
|
||||
|
||||
ascension: ClassVar[int]
|
||||
|
||||
|
||||
class FirstAscensionPassive(AscensionPassive):
|
||||
"""第一次突破被动天赋"""
|
||||
|
||||
ascension = 1
|
||||
|
||||
|
||||
class FourthAscensionPassive(AscensionPassive):
|
||||
"""第四次突破被动天赋"""
|
||||
|
||||
ascension = 4
|
||||
|
||||
|
||||
class UtilityPassive(PassiveTalent):
|
||||
"""实用被动天赋"""
|
||||
|
||||
|
||||
class MiscellaneousPassive(PassiveTalent):
|
||||
"""杂项被动天赋"""
|
||||
|
||||
|
||||
class AvatarTalents(BaseModel):
|
||||
"""角色天赋"""
|
||||
|
||||
normal_attack: NormalAttack
|
||||
"""普通攻击"""
|
||||
elemental_skill: ElementalSkill
|
||||
"""元素战技"""
|
||||
elemental_burst: ElementalBurst
|
||||
"""元素爆发"""
|
||||
alternate_sprint: AlternateSprint | None = None
|
||||
"""冲刺技能"""
|
||||
|
||||
first_ascension_passive: FirstAscensionPassive
|
||||
fourth_ascension_passive: FourthAscensionPassive
|
||||
utility_passive: UtilityPassive | None = None
|
||||
miscellaneous_passive: MiscellaneousPassive | None = None
|
@ -1,7 +1,7 @@
|
||||
from model.enums import ItemType, MaterialType
|
||||
|
||||
from model.enums import FoodQuality
|
||||
from utils.model import BaseModel
|
||||
from model._base import Model as BaseModel
|
||||
|
||||
|
||||
class Item(BaseModel):
|
||||
@ -9,8 +9,6 @@ class Item(BaseModel):
|
||||
"""ID"""
|
||||
name: str
|
||||
"""名称"""
|
||||
family: str
|
||||
"""种类"""
|
||||
type: str | None
|
||||
"""类型"""
|
||||
icon: str
|
||||
|
89
run.py
89
run.py
@ -1,98 +1,21 @@
|
||||
import asyncio
|
||||
|
||||
from model.enums import ItemType, MaterialType
|
||||
from model.item import Material, Namecard
|
||||
from utils.const import PROJECT_ROOT
|
||||
from utils.context import ContextManager
|
||||
from utils.manager import ResourceManager
|
||||
from utils.text import Text
|
||||
from scripts.avatar import parse_avatar_data
|
||||
from scripts.item import parse_item_data
|
||||
from utils.typedefs import Lang
|
||||
import ujson as json
|
||||
|
||||
OUTPUT_DIR = PROJECT_ROOT / "data"
|
||||
OUTPUT_DIR.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
|
||||
# noinspection PyShadowingBuiltins
|
||||
async def parse_item_data(resource: ResourceManager):
|
||||
from model.item import Food, FoodQuality, Item
|
||||
|
||||
json_data = resource.fetch("MaterialExcelConfigData")
|
||||
data_list = []
|
||||
|
||||
for item_data in json_data:
|
||||
id = item_data["id"]
|
||||
name = Text(item_data["nameTextMapHash"])
|
||||
family = item_data.get("materialType", "")
|
||||
rarity = item_data.get("rankLevel")
|
||||
type = Text(item_data["typeDescTextMapHash"])
|
||||
icon = item_data["icon"]
|
||||
description = Text(item_data["descTextMapHash"])
|
||||
special = Text(item_data["specialDescTextMapHash"]) or None
|
||||
item_type = ItemType(item_data["itemType"].removeprefix("ITEM_"))
|
||||
|
||||
base_kwargs = {
|
||||
"id": id,
|
||||
"name": name,
|
||||
"family": family,
|
||||
"rarity": rarity,
|
||||
"type": type,
|
||||
"icon": icon,
|
||||
"description": description,
|
||||
"item_type": item_type,
|
||||
}
|
||||
if special is not None:
|
||||
base_kwargs["special_description"] = special
|
||||
|
||||
if pics := list(filter(lambda x: x, item_data["picPath"])):
|
||||
item = Namecard(pictures=pics, **base_kwargs)
|
||||
elif "materialType" in item_data: # 材料
|
||||
material_type = MaterialType(
|
||||
item_data["materialType"].removeprefix("MATERIAL_")
|
||||
)
|
||||
item = Material(material_type=material_type, **base_kwargs)
|
||||
elif "foodQuality" in item_data: # 食物
|
||||
quality = FoodQuality(
|
||||
item_data["foodQuality"].removeprefix("FOOD_QUALITY_").title()
|
||||
)
|
||||
effect = Text(item_data["effectDescTextMapHash"])
|
||||
item = Food(quality=quality, effect=effect, **base_kwargs)
|
||||
else:
|
||||
item = Item(**base_kwargs)
|
||||
data_list.append(item.dict(exclude_none=True))
|
||||
|
||||
item_data_file = OUTPUT_DIR / "item.json"
|
||||
with open(item_data_file, "w", encoding="utf-8") as f:
|
||||
f.write(json.dumps(data_list, ensure_ascii=False))
|
||||
breakpoint()
|
||||
|
||||
|
||||
async def fetch_parse_data(lang: Lang):
|
||||
with ContextManager().with_context(
|
||||
"resource_manager", ResourceManager(lang=lang)
|
||||
) as resource_manager:
|
||||
try:
|
||||
await parse_item_data(resource_manager)
|
||||
except Exception as e:
|
||||
breakpoint()
|
||||
async def parse(lang: Lang):
|
||||
await parse_item_data(lang)
|
||||
await parse_avatar_data(lang)
|
||||
|
||||
|
||||
async def main():
|
||||
task_list = []
|
||||
for lang in Lang.__args__:
|
||||
task = asyncio.create_task(fetch_parse_data(lang=lang))
|
||||
task_list.append(task)
|
||||
await asyncio.gather(*task_list)
|
||||
await parse(lang)
|
||||
|
||||
|
||||
def __main__():
|
||||
import asyncio
|
||||
|
||||
import sys
|
||||
|
||||
if (3, 10) >= sys.version_info >= (3, 8) and sys.platform.startswith("win"):
|
||||
asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
|
||||
|
||||
loop = asyncio.new_event_loop()
|
||||
loop.run_until_complete(main())
|
||||
|
||||
|
0
scripts/__init__.py
Normal file
0
scripts/__init__.py
Normal file
44
scripts/_base.py
Normal file
44
scripts/_base.py
Normal file
@ -0,0 +1,44 @@
|
||||
import asyncio
|
||||
from abc import ABC, abstractmethod
|
||||
from asyncio import Task
|
||||
|
||||
targets: list["Target"] = []
|
||||
|
||||
|
||||
class Target(ABC):
|
||||
_task: Task | None = None
|
||||
|
||||
@property
|
||||
def task(self) -> Task:
|
||||
return self._task
|
||||
|
||||
def __init__(self):
|
||||
targets.append(self)
|
||||
|
||||
async def __async_init__(self) -> None:
|
||||
pass
|
||||
|
||||
async def __async_del__(self) -> None:
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
async def run(self) -> None:
|
||||
pass
|
||||
|
||||
async def _run(self) -> None:
|
||||
await self.__async_init__()
|
||||
await self.run()
|
||||
await self.__async_del__()
|
||||
|
||||
async def run_in_background(self) -> Task:
|
||||
self._task = asyncio.create_task(self._run())
|
||||
return self._task
|
||||
|
||||
|
||||
async def waiting_for_done():
|
||||
task_list: list[Task] = []
|
||||
for target in targets:
|
||||
if target.task is not None and not target.task.done():
|
||||
task_list.append(target.task)
|
||||
|
||||
await asyncio.gather(*task_list)
|
7
scripts/avatar.py
Normal file
7
scripts/avatar.py
Normal file
@ -0,0 +1,7 @@
|
||||
from utils.typedefs import Lang
|
||||
|
||||
from utils.manager import ResourceManager
|
||||
|
||||
|
||||
async def parse_avatar_data(lang: Lang):
|
||||
...
|
19
scripts/item.py
Normal file
19
scripts/item.py
Normal file
@ -0,0 +1,19 @@
|
||||
from model.enums import ItemType
|
||||
from utils.manager import ResourceManager
|
||||
from utils.typedefs import Lang
|
||||
|
||||
|
||||
# noinspection PyShadowingBuiltins
|
||||
async def parse_item_data(lang: Lang):
|
||||
manager = ResourceManager(lang=lang)
|
||||
json_data = manager.fetch("MaterialExcelConfigData")
|
||||
for data in json_data:
|
||||
id = data["id"]
|
||||
name = manager.get_text(data["nameTextMapHash"])
|
||||
type = manager.get_text(data["typeDescTextMapHash"])
|
||||
icon = data["icon"]
|
||||
rarity = data["rankLevel"]
|
||||
description = manager.get_text(data["descTextMapHash"])
|
||||
special_description = manager.get_text(data["specialDescTextMapHash"])
|
||||
item_type = ItemType(data["itemType"].removeprefix('ITEM_'))
|
||||
breakpoint()
|
Loading…
Reference in New Issue
Block a user