seerapi-models 1.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- seerapi_models/__init__.py +244 -0
- seerapi_models/_utils.py +27 -0
- seerapi_models/achievement.py +257 -0
- seerapi_models/battle_effect.py +78 -0
- seerapi_models/build_model/__init__.py +66 -0
- seerapi_models/common.py +406 -0
- seerapi_models/effect.py +119 -0
- seerapi_models/element_type.py +118 -0
- seerapi_models/items/__init__.py +82 -0
- seerapi_models/items/_common.py +95 -0
- seerapi_models/items/enegry_bead.py +93 -0
- seerapi_models/items/equip.py +383 -0
- seerapi_models/items/mintmark_gem.py +267 -0
- seerapi_models/items/skill_activation_item.py +44 -0
- seerapi_models/items/skill_stone.py +150 -0
- seerapi_models/metadata.py +49 -0
- seerapi_models/mintmark.py +448 -0
- seerapi_models/pet/__init__.py +59 -0
- seerapi_models/pet/pet.py +482 -0
- seerapi_models/pet/pet_skin.py +78 -0
- seerapi_models/pet/petbook.py +124 -0
- seerapi_models/pet/soulmark.py +141 -0
- seerapi_models/skill.py +336 -0
- seerapi_models-1.0.0.dist-info/METADATA +120 -0
- seerapi_models-1.0.0.dist-info/RECORD +26 -0
- seerapi_models-1.0.0.dist-info/WHEEL +4 -0
seerapi_models/common.py
ADDED
|
@@ -0,0 +1,406 @@
|
|
|
1
|
+
import inspect
|
|
2
|
+
from typing import (
|
|
3
|
+
TYPE_CHECKING,
|
|
4
|
+
ClassVar,
|
|
5
|
+
Generic,
|
|
6
|
+
TypeVar,
|
|
7
|
+
cast,
|
|
8
|
+
overload,
|
|
9
|
+
)
|
|
10
|
+
from typing_extensions import Self
|
|
11
|
+
|
|
12
|
+
from pydantic import (
|
|
13
|
+
ConfigDict,
|
|
14
|
+
computed_field,
|
|
15
|
+
)
|
|
16
|
+
from sqlalchemy.orm import column_property, declared_attr
|
|
17
|
+
from sqlmodel import JSON, Column, Computed, Field, Integer, Relationship
|
|
18
|
+
|
|
19
|
+
from ._utils import move_to_last
|
|
20
|
+
from .build_model import (
|
|
21
|
+
BaseGeneralModel,
|
|
22
|
+
BaseResModel,
|
|
23
|
+
BaseResModelWithOptionalId,
|
|
24
|
+
ConvertToORM,
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
if TYPE_CHECKING:
|
|
28
|
+
from .effect import PetEffectORM, VariationEffectORM
|
|
29
|
+
from .items import (
|
|
30
|
+
EnergyBeadORM,
|
|
31
|
+
EquipBonusORM,
|
|
32
|
+
GemORM,
|
|
33
|
+
SkillStoneEffectORM,
|
|
34
|
+
SuitBonusORM,
|
|
35
|
+
)
|
|
36
|
+
from .pet import SoulmarkORM
|
|
37
|
+
from .skill import SkillEffectType, SkillEffectTypeORM, SkillORM
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
TResModel = TypeVar('TResModel', bound=BaseResModel)
|
|
41
|
+
_TResModelArg = TypeVar('_TResModelArg', bound=BaseResModel)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class ResourceRef(BaseGeneralModel, Generic[TResModel]):
|
|
45
|
+
"""API资源类"""
|
|
46
|
+
|
|
47
|
+
base_data_url: ClassVar[str] = ''
|
|
48
|
+
|
|
49
|
+
id: int = Field(description='资源ID')
|
|
50
|
+
resource_name: str = Field(description='资源类型名称', exclude=True)
|
|
51
|
+
path: str = Field(default='', description='资源路径', exclude=True)
|
|
52
|
+
|
|
53
|
+
@computed_field(description='资源URL')
|
|
54
|
+
@property
|
|
55
|
+
def url(self) -> str:
|
|
56
|
+
path_parts: list[str] = [
|
|
57
|
+
self.base_data_url,
|
|
58
|
+
self.resource_name,
|
|
59
|
+
str(self.id),
|
|
60
|
+
self.path,
|
|
61
|
+
]
|
|
62
|
+
return '/'.join(path_parts)
|
|
63
|
+
|
|
64
|
+
@classmethod
|
|
65
|
+
def schema_path(cls) -> str:
|
|
66
|
+
return 'common/resource_ref/'
|
|
67
|
+
|
|
68
|
+
@overload
|
|
69
|
+
@classmethod
|
|
70
|
+
def from_model(
|
|
71
|
+
cls,
|
|
72
|
+
model: _TResModelArg,
|
|
73
|
+
*,
|
|
74
|
+
resource_name: str | None = None,
|
|
75
|
+
) -> 'ResourceRef[_TResModelArg]': ...
|
|
76
|
+
|
|
77
|
+
@overload
|
|
78
|
+
@classmethod
|
|
79
|
+
def from_model(
|
|
80
|
+
cls,
|
|
81
|
+
model: type[_TResModelArg],
|
|
82
|
+
*,
|
|
83
|
+
id: int,
|
|
84
|
+
resource_name: str | None = None,
|
|
85
|
+
) -> 'ResourceRef[_TResModelArg]': ...
|
|
86
|
+
|
|
87
|
+
@classmethod
|
|
88
|
+
def from_model(
|
|
89
|
+
cls,
|
|
90
|
+
model: type[_TResModelArg] | _TResModelArg,
|
|
91
|
+
*,
|
|
92
|
+
id: int | None = None,
|
|
93
|
+
resource_name: str | None = None,
|
|
94
|
+
) -> 'ResourceRef[_TResModelArg]':
|
|
95
|
+
if not inspect.isclass(model):
|
|
96
|
+
id = model.id
|
|
97
|
+
if id is None:
|
|
98
|
+
raise ValueError('id is required')
|
|
99
|
+
|
|
100
|
+
resource_name = resource_name or model.resource_name()
|
|
101
|
+
obj = cls(id=id, resource_name=resource_name)
|
|
102
|
+
return cast(ResourceRef[_TResModelArg], obj)
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
class NamedResourceRef(ResourceRef[TResModel]):
|
|
106
|
+
name: str | None = Field(default=None, description='资源名称')
|
|
107
|
+
|
|
108
|
+
@classmethod
|
|
109
|
+
def schema_path(cls) -> str:
|
|
110
|
+
return 'common/named_resource_ref/'
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
class ApiResourceList(BaseGeneralModel, Generic[TResModel]):
|
|
114
|
+
"""API资源列表,兼容RFC 5988的Link标准"""
|
|
115
|
+
|
|
116
|
+
count: int = Field(description='资源数量')
|
|
117
|
+
next: str | None = Field(default=None, description='下一页URL')
|
|
118
|
+
previous: str | None = Field(default=None, description='上一页URL')
|
|
119
|
+
first: str | None = Field(default=None, description='第一页URL')
|
|
120
|
+
last: str | None = Field(default=None, description='最后一页URL')
|
|
121
|
+
results: list[NamedResourceRef[TResModel]] = Field(description='资源列表')
|
|
122
|
+
|
|
123
|
+
@classmethod
|
|
124
|
+
def schema_path(cls) -> str:
|
|
125
|
+
return 'common/api_resource_list/'
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
class EidEffect(BaseResModel, BaseGeneralModel, ConvertToORM['EidEffectORM']):
|
|
129
|
+
# info: str | None = Field(
|
|
130
|
+
# default=None,
|
|
131
|
+
# description='效果描述,当效果描述为空时,该字段为null',
|
|
132
|
+
# )
|
|
133
|
+
args_num: int = Field(
|
|
134
|
+
description='效果需要的参数数量,该值是从使用该效果的资源中推测得出的'
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
@classmethod
|
|
138
|
+
def schema_path(cls) -> str:
|
|
139
|
+
return 'common/eid_effect/'
|
|
140
|
+
|
|
141
|
+
@classmethod
|
|
142
|
+
def resource_name(cls) -> str:
|
|
143
|
+
return 'eid_effect'
|
|
144
|
+
|
|
145
|
+
@classmethod
|
|
146
|
+
def get_orm_model(cls) -> type['EidEffectORM']:
|
|
147
|
+
return EidEffectORM
|
|
148
|
+
|
|
149
|
+
def to_orm(self) -> 'EidEffectORM':
|
|
150
|
+
return EidEffectORM(id=self.id, args_num=self.args_num)
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
class EidEffectORM(EidEffect, table=True):
|
|
154
|
+
in_use: list['EidEffectInUseORM'] = Relationship(back_populates='effect')
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
class EidEffectInUseBase(BaseResModelWithOptionalId):
|
|
158
|
+
effect_args: list[int] | None = Field(
|
|
159
|
+
default=None,
|
|
160
|
+
description='效果参数,当效果参数为空时,该字段为null',
|
|
161
|
+
sa_type=JSON,
|
|
162
|
+
)
|
|
163
|
+
|
|
164
|
+
@classmethod
|
|
165
|
+
def resource_name(cls) -> str:
|
|
166
|
+
return 'eid_effect_in_use'
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
class EidEffectInUse(
|
|
170
|
+
EidEffectInUseBase, BaseGeneralModel, ConvertToORM['EidEffectInUseORM']
|
|
171
|
+
):
|
|
172
|
+
effect: 'ResourceRef[EidEffect]' = Field(description='效果引用')
|
|
173
|
+
|
|
174
|
+
@classmethod
|
|
175
|
+
def schema_path(cls) -> str:
|
|
176
|
+
return 'common/eid_effect_in_use/'
|
|
177
|
+
|
|
178
|
+
@classmethod
|
|
179
|
+
def get_orm_model(cls) -> type['EidEffectInUseORM']:
|
|
180
|
+
return EidEffectInUseORM
|
|
181
|
+
|
|
182
|
+
def to_orm(self) -> 'EidEffectInUseORM':
|
|
183
|
+
return EidEffectInUseORM(
|
|
184
|
+
id=self.id,
|
|
185
|
+
eid=self.effect.id,
|
|
186
|
+
effect_args=self.effect_args,
|
|
187
|
+
)
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
class EidEffectInUseORM(EidEffectInUseBase, table=True):
|
|
191
|
+
eid: int = Field(foreign_key='eid_effect.id')
|
|
192
|
+
effect: 'EidEffectORM' = Relationship(back_populates='in_use')
|
|
193
|
+
# 特性,魂印,装备效果,etc...
|
|
194
|
+
energy_bead: 'EnergyBeadORM' = Relationship(back_populates='effect_in_use')
|
|
195
|
+
soulmark: 'SoulmarkORM' = Relationship(back_populates='effect_in_use')
|
|
196
|
+
pet_effect: 'PetEffectORM' = Relationship(back_populates='effect_in_use')
|
|
197
|
+
variation_effect: 'VariationEffectORM' = Relationship(
|
|
198
|
+
back_populates='effect_in_use'
|
|
199
|
+
)
|
|
200
|
+
equip_bonus: 'EquipBonusORM' = Relationship(back_populates='effect_in_use')
|
|
201
|
+
suit_bonus: 'SuitBonusORM' = Relationship(back_populates='effect_in_use')
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
class SixAttributesBase(BaseResModelWithOptionalId, BaseGeneralModel):
|
|
205
|
+
"""六维属性类"""
|
|
206
|
+
|
|
207
|
+
atk: int = Field(description='攻击')
|
|
208
|
+
def_: int = Field(
|
|
209
|
+
sa_type=Integer,
|
|
210
|
+
sa_column_kwargs={'name': 'def', 'nullable': False},
|
|
211
|
+
description='防御',
|
|
212
|
+
schema_extra={'serialization_alias': 'def'},
|
|
213
|
+
)
|
|
214
|
+
sp_atk: int = Field(description='特攻')
|
|
215
|
+
sp_def: int = Field(description='特防')
|
|
216
|
+
spd: int = Field(description='速度')
|
|
217
|
+
hp: int = Field(description='体力')
|
|
218
|
+
|
|
219
|
+
percent: bool = Field(
|
|
220
|
+
default=False,
|
|
221
|
+
description='该对象描述的是否是百分比加成,如果为true,属性值为省略百分比(%)符号的加成',
|
|
222
|
+
)
|
|
223
|
+
|
|
224
|
+
@classmethod
|
|
225
|
+
def schema_path(cls) -> str:
|
|
226
|
+
return 'common/six_attributes/'
|
|
227
|
+
|
|
228
|
+
@classmethod
|
|
229
|
+
def from_string(
|
|
230
|
+
cls, value: str, *, hp_first: bool = False, percent: bool = False
|
|
231
|
+
) -> Self:
|
|
232
|
+
"""从字符串创建六维属性对象"""
|
|
233
|
+
attributes = value.split(' ')
|
|
234
|
+
if len(attributes) < 6:
|
|
235
|
+
raise ValueError('无效的属性字符串')
|
|
236
|
+
attributes = [int(attribute) for attribute in attributes[0:6]]
|
|
237
|
+
return cls.from_list(attributes, hp_first=hp_first, percent=percent)
|
|
238
|
+
|
|
239
|
+
@classmethod
|
|
240
|
+
def from_list(
|
|
241
|
+
cls, attributes: list[int], *, hp_first: bool = False, percent: bool = False
|
|
242
|
+
) -> Self:
|
|
243
|
+
if len(attributes) < 6:
|
|
244
|
+
raise ValueError('无效的属性列表')
|
|
245
|
+
if hp_first:
|
|
246
|
+
move_to_last(attributes, 0)
|
|
247
|
+
return cls(
|
|
248
|
+
atk=attributes[0],
|
|
249
|
+
def_=attributes[1],
|
|
250
|
+
sp_atk=attributes[2],
|
|
251
|
+
sp_def=attributes[3],
|
|
252
|
+
spd=attributes[4],
|
|
253
|
+
hp=attributes[5],
|
|
254
|
+
percent=percent,
|
|
255
|
+
)
|
|
256
|
+
|
|
257
|
+
def __add__(self, other) -> Self:
|
|
258
|
+
"""两个六维属性相加"""
|
|
259
|
+
cls = type(self)
|
|
260
|
+
if not isinstance(other, cls):
|
|
261
|
+
return self
|
|
262
|
+
return cls(
|
|
263
|
+
atk=self.atk + other.atk,
|
|
264
|
+
def_=self.def_ + other.def_,
|
|
265
|
+
sp_atk=self.sp_atk + other.sp_atk,
|
|
266
|
+
sp_def=self.sp_def + other.sp_def,
|
|
267
|
+
spd=self.spd + other.spd,
|
|
268
|
+
hp=self.hp + other.hp,
|
|
269
|
+
)
|
|
270
|
+
|
|
271
|
+
def __sub__(self, other) -> Self:
|
|
272
|
+
"""两个六维属性相减"""
|
|
273
|
+
cls = type(self)
|
|
274
|
+
if not isinstance(other, cls):
|
|
275
|
+
return self
|
|
276
|
+
return cls(
|
|
277
|
+
atk=self.atk - other.atk,
|
|
278
|
+
def_=self.def_ - other.def_,
|
|
279
|
+
sp_atk=self.sp_atk - other.sp_atk,
|
|
280
|
+
sp_def=self.sp_def - other.sp_def,
|
|
281
|
+
spd=self.spd - other.spd,
|
|
282
|
+
hp=self.hp - other.hp,
|
|
283
|
+
)
|
|
284
|
+
|
|
285
|
+
@classmethod
|
|
286
|
+
def resource_name(cls) -> str:
|
|
287
|
+
return 'six_attributes'
|
|
288
|
+
|
|
289
|
+
|
|
290
|
+
class SixAttributes(
|
|
291
|
+
SixAttributesBase, BaseGeneralModel, ConvertToORM['SixAttributesORM']
|
|
292
|
+
):
|
|
293
|
+
@computed_field
|
|
294
|
+
@property
|
|
295
|
+
def total(self) -> int:
|
|
296
|
+
"""总属性值"""
|
|
297
|
+
return self.atk + self.def_ + self.sp_atk + self.sp_def + self.spd + self.hp
|
|
298
|
+
|
|
299
|
+
@classmethod
|
|
300
|
+
def get_orm_model(cls) -> type['SixAttributesORM']:
|
|
301
|
+
return SixAttributesORM
|
|
302
|
+
|
|
303
|
+
def to_orm(self) -> 'SixAttributesORM':
|
|
304
|
+
return SixAttributesORM(
|
|
305
|
+
atk=self.atk,
|
|
306
|
+
def_=self.def_,
|
|
307
|
+
sp_atk=self.sp_atk,
|
|
308
|
+
sp_def=self.sp_def,
|
|
309
|
+
spd=self.spd,
|
|
310
|
+
hp=self.hp,
|
|
311
|
+
percent=self.percent,
|
|
312
|
+
)
|
|
313
|
+
|
|
314
|
+
|
|
315
|
+
class SixAttributesORM(SixAttributesBase):
|
|
316
|
+
model_config = ConfigDict(ignored_types=(declared_attr,)) # type: ignore
|
|
317
|
+
|
|
318
|
+
@declared_attr
|
|
319
|
+
def total(self): # type: ignore
|
|
320
|
+
return column_property(
|
|
321
|
+
Column(
|
|
322
|
+
Integer,
|
|
323
|
+
Computed('atk + def + sp_atk + sp_def + spd + hp'),
|
|
324
|
+
nullable=False,
|
|
325
|
+
)
|
|
326
|
+
)
|
|
327
|
+
|
|
328
|
+
|
|
329
|
+
class SkillEffectInUseBase(BaseResModelWithOptionalId):
|
|
330
|
+
"""描述一条“使用中的”技能效果"""
|
|
331
|
+
|
|
332
|
+
info: str = Field(description='技能效果描述')
|
|
333
|
+
args: list[int | float] | list[int] | list[float] = Field(
|
|
334
|
+
description='技能效果参数列表',
|
|
335
|
+
sa_type=JSON,
|
|
336
|
+
)
|
|
337
|
+
|
|
338
|
+
@classmethod
|
|
339
|
+
def resource_name(cls) -> str:
|
|
340
|
+
return 'skill_effect_in_use'
|
|
341
|
+
|
|
342
|
+
|
|
343
|
+
class SkillEffectInUse(
|
|
344
|
+
SkillEffectInUseBase, BaseGeneralModel, ConvertToORM['SkillEffectInUseORM']
|
|
345
|
+
):
|
|
346
|
+
effect: 'ResourceRef[SkillEffectType]'
|
|
347
|
+
|
|
348
|
+
@classmethod
|
|
349
|
+
def schema_path(cls) -> str:
|
|
350
|
+
return 'common/skill_effect_in_use/'
|
|
351
|
+
|
|
352
|
+
@classmethod
|
|
353
|
+
def get_orm_model(cls) -> type['SkillEffectInUseORM']:
|
|
354
|
+
return SkillEffectInUseORM
|
|
355
|
+
|
|
356
|
+
def to_orm(self) -> 'SkillEffectInUseORM':
|
|
357
|
+
return SkillEffectInUseORM(
|
|
358
|
+
effect_id=self.effect.id,
|
|
359
|
+
args=self.args,
|
|
360
|
+
info=self.info,
|
|
361
|
+
)
|
|
362
|
+
|
|
363
|
+
|
|
364
|
+
class SkillEffectInUseORM(SkillEffectInUseBase, table=True):
|
|
365
|
+
effect_id: int = Field(foreign_key='skill_effect_type.id')
|
|
366
|
+
effect: 'SkillEffectTypeORM' = Relationship(back_populates='in_use')
|
|
367
|
+
skill: list['SkillORM'] = Relationship(
|
|
368
|
+
sa_relationship_kwargs={
|
|
369
|
+
'secondary': 'skilleffectlink',
|
|
370
|
+
}
|
|
371
|
+
)
|
|
372
|
+
friend_skill: list['SkillORM'] = Relationship(
|
|
373
|
+
sa_relationship_kwargs={
|
|
374
|
+
'secondary': 'skillfriendskilleffectlink',
|
|
375
|
+
}
|
|
376
|
+
)
|
|
377
|
+
gem: list['GemORM'] = Relationship(
|
|
378
|
+
back_populates='skill_effect_in_use',
|
|
379
|
+
sa_relationship_kwargs={
|
|
380
|
+
'secondary': 'gemeffectlink',
|
|
381
|
+
},
|
|
382
|
+
)
|
|
383
|
+
skill_stone_effect: list['SkillStoneEffectORM'] = Relationship(
|
|
384
|
+
back_populates='effect',
|
|
385
|
+
sa_relationship_kwargs={
|
|
386
|
+
'secondary': 'skillstoneeffectlink',
|
|
387
|
+
},
|
|
388
|
+
)
|
|
389
|
+
|
|
390
|
+
|
|
391
|
+
__all__ = [
|
|
392
|
+
'ApiResourceList',
|
|
393
|
+
'EidEffect',
|
|
394
|
+
'EidEffectInUse',
|
|
395
|
+
'EidEffectInUseBase',
|
|
396
|
+
'EidEffectInUseORM',
|
|
397
|
+
'EidEffectORM',
|
|
398
|
+
'NamedResourceRef',
|
|
399
|
+
'ResourceRef',
|
|
400
|
+
'SixAttributes',
|
|
401
|
+
'SixAttributesBase',
|
|
402
|
+
'SixAttributesORM',
|
|
403
|
+
'SkillEffectInUse',
|
|
404
|
+
'SkillEffectInUseBase',
|
|
405
|
+
'SkillEffectInUseORM',
|
|
406
|
+
]
|
seerapi_models/effect.py
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
from sqlmodel import Field, Relationship
|
|
2
|
+
|
|
3
|
+
from seerapi_models.build_model import BaseCategoryModel, BaseResModel, ConvertToORM
|
|
4
|
+
from seerapi_models.common import (
|
|
5
|
+
EidEffectInUse,
|
|
6
|
+
EidEffectInUseORM,
|
|
7
|
+
ResourceRef,
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class EffectSeDataBase(BaseResModel):
|
|
12
|
+
name: str = Field(description='名称')
|
|
13
|
+
desc: str = Field(description='描述')
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class EffectSeData(EffectSeDataBase):
|
|
17
|
+
effect: EidEffectInUse = Field(description='效果')
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class EffectSeDataORM(EffectSeDataBase):
|
|
21
|
+
effect_in_use_id: int | None = Field(
|
|
22
|
+
default=None, foreign_key='eid_effect_in_use.id'
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class VariationEffectBase(BaseResModel):
|
|
27
|
+
@classmethod
|
|
28
|
+
def resource_name(cls) -> str:
|
|
29
|
+
return 'pet_variation'
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class VariationEffect(
|
|
33
|
+
VariationEffectBase, EffectSeData, ConvertToORM['VariationEffectORM']
|
|
34
|
+
):
|
|
35
|
+
"""特质效果"""
|
|
36
|
+
|
|
37
|
+
@classmethod
|
|
38
|
+
def get_orm_model(cls) -> type['VariationEffectORM']:
|
|
39
|
+
return VariationEffectORM
|
|
40
|
+
|
|
41
|
+
def to_orm(self) -> 'VariationEffectORM':
|
|
42
|
+
return VariationEffectORM(
|
|
43
|
+
id=self.id,
|
|
44
|
+
name=self.name,
|
|
45
|
+
desc=self.desc,
|
|
46
|
+
effect_in_use=self.effect.to_orm(),
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
class VariationEffectORM(VariationEffectBase, EffectSeDataORM, table=True):
|
|
51
|
+
effect_in_use: 'EidEffectInUseORM' = Relationship(
|
|
52
|
+
back_populates='variation_effect',
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
class PetEffectBase(EffectSeDataBase):
|
|
57
|
+
star_level: int = Field(description='特性星级')
|
|
58
|
+
|
|
59
|
+
@classmethod
|
|
60
|
+
def resource_name(cls) -> str:
|
|
61
|
+
return 'pet_effect'
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
class PetEffect(PetEffectBase, EffectSeData, ConvertToORM['PetEffectORM']):
|
|
65
|
+
effect_group: ResourceRef['PetEffectGroup'] = Field(
|
|
66
|
+
description='特性组资源引用,同特性的不同星级属于同一组'
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
@classmethod
|
|
70
|
+
def get_orm_model(cls) -> type['PetEffectORM']:
|
|
71
|
+
return PetEffectORM
|
|
72
|
+
|
|
73
|
+
def to_orm(self) -> 'PetEffectORM':
|
|
74
|
+
return PetEffectORM(
|
|
75
|
+
id=self.id,
|
|
76
|
+
name=self.name,
|
|
77
|
+
desc=self.desc,
|
|
78
|
+
effect_in_use=self.effect.to_orm(),
|
|
79
|
+
star_level=self.star_level,
|
|
80
|
+
effect_group_id=self.effect_group.id,
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
class PetEffectORM(PetEffectBase, EffectSeDataORM, table=True):
|
|
85
|
+
effect_in_use: 'EidEffectInUseORM' = Relationship(
|
|
86
|
+
back_populates='pet_effect',
|
|
87
|
+
)
|
|
88
|
+
effect_group_id: int = Field(foreign_key='pet_effect_group.id')
|
|
89
|
+
effect_group: 'PetEffectGroupORM' = Relationship(back_populates='effect')
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
class PetEffectGroupBase(BaseCategoryModel):
|
|
93
|
+
name: str = Field(description='名称')
|
|
94
|
+
|
|
95
|
+
@classmethod
|
|
96
|
+
def resource_name(cls) -> str:
|
|
97
|
+
return 'pet_effect_group'
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
class PetEffectGroup(PetEffectGroupBase, ConvertToORM['PetEffectGroupORM']):
|
|
101
|
+
effect: list[ResourceRef[PetEffect]] = Field(
|
|
102
|
+
default_factory=list, description='特性列表'
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
@classmethod
|
|
106
|
+
def get_orm_model(cls) -> type['PetEffectGroupORM']:
|
|
107
|
+
return PetEffectGroupORM
|
|
108
|
+
|
|
109
|
+
def to_orm(self) -> 'PetEffectGroupORM':
|
|
110
|
+
return PetEffectGroupORM(
|
|
111
|
+
id=self.id,
|
|
112
|
+
name=self.name,
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
class PetEffectGroupORM(PetEffectGroupBase, table=True):
|
|
117
|
+
effect: list['PetEffectORM'] = Relationship(
|
|
118
|
+
back_populates='effect_group',
|
|
119
|
+
)
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
from typing import TYPE_CHECKING
|
|
2
|
+
|
|
3
|
+
from pydantic import computed_field
|
|
4
|
+
from sqlmodel import Boolean, Column, Computed, Field, Relationship
|
|
5
|
+
|
|
6
|
+
from seerapi_models.build_model import BaseResModel, ConvertToORM
|
|
7
|
+
from seerapi_models.common import ResourceRef
|
|
8
|
+
|
|
9
|
+
if TYPE_CHECKING:
|
|
10
|
+
from .items.skill_stone import SkillStoneCategoryORM
|
|
11
|
+
from .pet import PetORM
|
|
12
|
+
from .skill import SkillORM
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class ElementType(BaseResModel, ConvertToORM['ElementTypeORM']):
|
|
16
|
+
name: str = Field(description='属性中文名')
|
|
17
|
+
name_en: str = Field(description='属性英文名')
|
|
18
|
+
|
|
19
|
+
@classmethod
|
|
20
|
+
def resource_name(cls) -> str:
|
|
21
|
+
return 'element_type'
|
|
22
|
+
|
|
23
|
+
@classmethod
|
|
24
|
+
def get_orm_model(cls) -> type['ElementTypeORM']:
|
|
25
|
+
return ElementTypeORM
|
|
26
|
+
|
|
27
|
+
def to_orm(self) -> 'ElementTypeORM':
|
|
28
|
+
return ElementTypeORM(
|
|
29
|
+
id=self.id,
|
|
30
|
+
name=self.name,
|
|
31
|
+
name_en=self.name_en,
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class ElementTypeORM(ElementType, table=True):
|
|
36
|
+
primary_combination: list['TypeCombinationORM'] = Relationship(
|
|
37
|
+
back_populates='primary',
|
|
38
|
+
sa_relationship_kwargs={
|
|
39
|
+
'primaryjoin': 'ElementTypeORM.id == TypeCombinationORM.primary_id',
|
|
40
|
+
'viewonly': True,
|
|
41
|
+
},
|
|
42
|
+
)
|
|
43
|
+
secondary_combination: list['TypeCombinationORM'] = Relationship(
|
|
44
|
+
back_populates='secondary',
|
|
45
|
+
sa_relationship_kwargs={
|
|
46
|
+
'primaryjoin': 'ElementTypeORM.id == TypeCombinationORM.secondary_id',
|
|
47
|
+
'viewonly': True,
|
|
48
|
+
},
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
class TypeCombinationBase(BaseResModel):
|
|
53
|
+
name: str = Field(description='组合类型中文名')
|
|
54
|
+
name_en: str = Field(description='组合类型英文名')
|
|
55
|
+
|
|
56
|
+
@classmethod
|
|
57
|
+
def resource_name(cls) -> str:
|
|
58
|
+
return 'element_type_combination'
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
class TypeCombination(TypeCombinationBase, ConvertToORM['TypeCombinationORM']):
|
|
62
|
+
primary: ResourceRef[ElementType] = Field(description='主属性')
|
|
63
|
+
secondary: ResourceRef[ElementType] | None = Field(
|
|
64
|
+
default=None, description='副属性'
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
@computed_field(description='是否是双属性')
|
|
68
|
+
@property
|
|
69
|
+
def is_double(self) -> bool:
|
|
70
|
+
return self.secondary is not None
|
|
71
|
+
|
|
72
|
+
@classmethod
|
|
73
|
+
def get_orm_model(cls) -> type['TypeCombinationORM']:
|
|
74
|
+
return TypeCombinationORM
|
|
75
|
+
|
|
76
|
+
def to_orm(self) -> 'TypeCombinationORM':
|
|
77
|
+
return TypeCombinationORM(
|
|
78
|
+
id=self.id,
|
|
79
|
+
name=self.name,
|
|
80
|
+
name_en=self.name_en,
|
|
81
|
+
primary_id=self.primary.id,
|
|
82
|
+
secondary_id=self.secondary.id if self.secondary else None,
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
class TypeCombinationORM(TypeCombinationBase, table=True):
|
|
87
|
+
primary_id: int = Field(foreign_key='element_type.id')
|
|
88
|
+
primary: 'ElementTypeORM' = Relationship(
|
|
89
|
+
back_populates='primary_combination',
|
|
90
|
+
sa_relationship_kwargs={
|
|
91
|
+
'primaryjoin': 'TypeCombinationORM.primary_id == ElementTypeORM.id',
|
|
92
|
+
},
|
|
93
|
+
)
|
|
94
|
+
secondary_id: int | None = Field(default=None, foreign_key='element_type.id')
|
|
95
|
+
secondary: ElementTypeORM | None = Relationship(
|
|
96
|
+
back_populates='secondary_combination',
|
|
97
|
+
sa_relationship_kwargs={
|
|
98
|
+
'primaryjoin': 'TypeCombinationORM.secondary_id == ElementTypeORM.id',
|
|
99
|
+
},
|
|
100
|
+
)
|
|
101
|
+
if not TYPE_CHECKING:
|
|
102
|
+
is_double: bool = Field(
|
|
103
|
+
sa_column=Column(
|
|
104
|
+
Boolean,
|
|
105
|
+
Computed('secondary_id IS NOT NULL', persisted=True),
|
|
106
|
+
nullable=False,
|
|
107
|
+
)
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
skill: list['SkillORM'] = Relationship(
|
|
111
|
+
back_populates='type',
|
|
112
|
+
)
|
|
113
|
+
pet: list['PetORM'] = Relationship(
|
|
114
|
+
back_populates='type',
|
|
115
|
+
)
|
|
116
|
+
skill_stone_category: list['SkillStoneCategoryORM'] = Relationship(
|
|
117
|
+
back_populates='type',
|
|
118
|
+
)
|