Skip to content

Commit e216c2c

Browse files
authored
Merge pull request #261 from cc004/dev
Dev
2 parents b1ae891 + b208942 commit e216c2c

19 files changed

Lines changed: 684 additions & 228 deletions

autopcr/core/datamgr.py

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -596,6 +596,76 @@ def is_quest_cleared(self, quest: int) -> bool:
596596
def is_quest_sweepable(self, quest: int) -> bool:
597597
return quest in self.quest_dict and self.quest_dict[quest].clear_flg == 3
598598

599+
def get_talent_quest_single(self, talent_id: int) -> str:
600+
max_quest_id = self.cleared_talent_quest_ids.get(talent_id, 0)
601+
quest = "0-0" if max_quest_id == 0 else f"{db.quest_name[max_quest_id][4:]}"
602+
return quest
603+
604+
def get_talent_quest_info(self) -> str:
605+
msg = []
606+
for talent_id in sorted([area.talent_id for area in db.talent_quest_area_data.values()]):
607+
talent_name = db.talents[talent_id].talent_name
608+
msg.append(f"{talent_name}{self.get_talent_quest_single(talent_id)}")
609+
return "/".join(msg)
610+
611+
def get_talent_level_single(self, talent_info: TalentLevelInfo) -> str:
612+
material = db.talent_level_material[talent_info.talent_id]
613+
cur_point = talent_info.total_point
614+
up_point = talent_info.total_point + self.get_inventory((material.reward_type, material.item_id)) * material.point
615+
info = f"{db.get_talent_level(cur_point)}"
616+
if True and cur_point != up_point: # always show for pretty format
617+
info += f"→{db.get_talent_level(up_point)}"
618+
return info
619+
620+
def get_talent_level_info(self) -> str:
621+
msg = []
622+
for talent_info in self.princess_knight_info.talent_level_info_list:
623+
msg.append(f"{db.talents[talent_info.talent_id].talent_name}{self.get_talent_level_single(talent_info)}")
624+
return "/".join(msg)
625+
626+
def get_talent_skill_info(self) -> str:
627+
page = 0 if not self.princess_knight_info.talent_skill_last_enhanced_page_node_list else db.talent_skill_node[self.princess_knight_info.talent_skill_last_enhanced_page_node_list[0].node_id].page_num
628+
joined_nodes = flow(self.princess_knight_info.talent_skill_last_enhanced_page_node_list) \
629+
.where(lambda x: db.talent_skill_node[x.node_id].is_joined_node()) \
630+
.to_list()
631+
max_joined_node = max(joined_nodes, key=lambda x: x.node_id, default=TalentSkillNodeInfo(node_id=1))
632+
joined_node_after = flow(self.princess_knight_info.talent_skill_last_enhanced_page_node_list) \
633+
.where(lambda x: x.node_id > max_joined_node.node_id) \
634+
.group_by(lambda x: db.talent_skill_node[x.node_id].pos_x) \
635+
.to_dict(lambda g: g.key, lambda g: g.to_list())
636+
joined_node_after_max = {pos: max(nodes, key=lambda x: x.node_id) for pos, nodes in joined_node_after.items()}
637+
638+
prefix = f"第{page}页 第{len(joined_nodes)}合流"
639+
msg = []
640+
if not joined_node_after and joined_nodes:
641+
prefix += f"[{max_joined_node.enhance_level}级]"
642+
elif joined_node_after:
643+
for pos, nodes in joined_node_after.items():
644+
msg.append(f"{db.talent_skill_node[nodes[0].node_id].pos()}{len(nodes)}[{joined_node_after_max[pos].enhance_level}级]")
645+
646+
info = prefix + " " + "/".join(msg)
647+
info += f"(余{self.get_inventory(db.xinyou)})"
648+
return info
649+
650+
def get_master_skill_info(self) -> str:
651+
cur_node_id = self.princess_knight_info.team_skill_latest_node.node_id
652+
up_node_id = cur_node_id
653+
num = self.get_inventory(db.master_fragment) + self.get_inventory(db.master_ffragment) // 100
654+
next_id = sorted([k for k in db.team_skill_node if k > cur_node_id])
655+
for node_id in next_id:
656+
tot = 0
657+
for enhance_level_id in db.team_skill_node[node_id].enhance_level_ids():
658+
tot += db.team_skill_enhance_level[enhance_level_id].consume_num
659+
if num >= tot:
660+
num -= tot
661+
up_node_id = node_id
662+
663+
info = f"MP{cur_node_id}"
664+
if True and cur_node_id != up_node_id: # always show for pretty format
665+
info += f"→{up_node_id}"
666+
info += f"(余{num})"
667+
return info
668+
599669
async def request(self, request: Request[TResponse], next: RequestHandler) -> TResponse:
600670
resp = await next.request(request)
601671
if resp:

autopcr/core/pcrclient.py

Lines changed: 56 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1281,59 +1281,62 @@ async def serlize_reward(self, reward_list: List[InventoryInfo], target: Union[I
12811281
result.append(f"{db.get_inventory_name_san(target)}x0({self.data.get_inventory(target)})")
12821282
return '\n'.join(result) if result else "无"
12831283

1284-
async def serialize_unit_info(self, unit_data: Union[UnitData, UnitDataLight]) -> Tuple[bool, str]:
1285-
info = []
1286-
ok = True
1287-
def add_info(prefix, cur, expect = None):
1288-
if expect:
1289-
nonlocal ok
1290-
info.append(f'{prefix}:{cur}/{expect}')
1291-
ok &= (cur == expect)
1292-
else:
1293-
info.append(f'{prefix}:{cur}')
1294-
unit_id = unit_data.id
1295-
add_info("等级", unit_data.unit_level, db.team_max_level)
1296-
if unit_data.battle_rarity:
1297-
add_info("星级", f"{unit_data.battle_rarity}-{unit_data.unit_rarity}")
1298-
else:
1299-
add_info("星级", f"{unit_data.unit_rarity}")
1300-
add_info("品级", unit_data.promotion_level, db.equip_max_rank)
1301-
for id, union_burst in enumerate(unit_data.union_burst):
1302-
if union_burst.skill_level:
1303-
add_info(f"ub{id}", union_burst.skill_level, unit_data.unit_level)
1304-
for id, skill in enumerate(unit_data.main_skill):
1305-
if skill.skill_level:
1306-
add_info(f"skill{id}", skill.skill_level, unit_data.unit_level)
1307-
for id, skill in enumerate(unit_data.ex_skill):
1308-
if skill.skill_level:
1309-
add_info(f"ex{id}", skill.skill_level, unit_data.unit_level)
1310-
equip_info = []
1311-
for id, equip in enumerate(unit_data.equip_slot):
1312-
equip_id = getattr(db.unit_promotion[unit_id][unit_data.promotion_level], f'equip_slot_{id + 1}')
1313-
if not equip.is_slot:
1314-
if equip_id != 999999:
1315-
equip_info.append('-')
1316-
ok = False
1317-
else:
1318-
equip_info.append('*')
1319-
else:
1320-
star = db.get_equip_star_from_pt(equip_id, equip.enhancement_pt)
1321-
ok &= (star == 5)
1322-
equip_info.append(str(star))
1323-
equip_info = '/'.join(equip_info)
1324-
add_info("装备", equip_info)
1325-
1326-
for id, equip in enumerate(unit_data.unique_equip_slot):
1327-
equip_slot = id + 1
1328-
have_unique = (equip_slot in db.unit_unique_equip and unit_id in db.unit_unique_equip[equip_slot])
1329-
max_level = 0 if not have_unique else db.unique_equipment_max_level[equip_slot]
1330-
if have_unique:
1331-
if not equip.is_slot:
1332-
add_info(f"专武{id}", '-', max_level)
1333-
else:
1334-
add_info(f"专武{id}", db.get_unique_equip_level_from_pt(equip_slot, equip.enhancement_pt), max_level)
1335-
1336-
return ok, ' '.join(info)
1284+
def unit_info_to_dict(self, unit_id: int) -> Dict:
1285+
unit_data = {
1286+
"星级": "无",
1287+
"等级": "无",
1288+
"品级": "无",
1289+
"装备": "无",
1290+
"UB": 0,
1291+
"S1": 0,
1292+
"S2": 0,
1293+
"EX": 0,
1294+
"剧情": "无",
1295+
"专武1": "无",
1296+
"专武2": "无",
1297+
"普碎数": "无",
1298+
"金碎数": "无",
1299+
}
1300+
1301+
read_story = set(self.data.read_story_ids)
1302+
if unit_id in self.data.unit:
1303+
unitinfo = self.data.unit[unit_id]
1304+
rank = f"R{unitinfo.promotion_level}"
1305+
equip = ''.join('-' if not solt.is_slot else str(solt.enhancement_level) for solt in unitinfo.equip_slot)
1306+
kizuna_unit = set()
1307+
for story in db.chara2story[unit_id]:
1308+
if story.story_id in db.story_detail:
1309+
kizuna_unit.add(db.story_detail[story.story_id].requirement_id)
1310+
1311+
love = []
1312+
for other in kizuna_unit:
1313+
if other not in db.unlock_unit_condition: continue
1314+
unit_name = db.get_unit_name(other)
1315+
other_id = other // 100
1316+
love_level = self.data.unit_love_data[other_id].love_level if other_id in self.data.unit_love_data else 0
1317+
unit_story = [story.story_id for story in db.unit_story if story.story_group_id == other_id]
1318+
total_storys = len(unit_story)
1319+
read_storys = len([story for story in unit_story if story in read_story])
1320+
love.append(f"{unit_name}好感{love_level}({read_storys}/{total_storys})")
1321+
love_str = '\n'.join(love) if love else "无"
1322+
1323+
unit_data.update({
1324+
"星级": f"{unitinfo.unit_rarity}★",
1325+
"等级": unitinfo.unit_level,
1326+
"品级": rank,
1327+
"装备": equip,
1328+
"UB": unitinfo.union_burst[0].skill_level if unitinfo.union_burst else "无",
1329+
"S1": unitinfo.main_skill[0].skill_level if unitinfo.main_skill else "无",
1330+
"S2": unitinfo.main_skill[1].skill_level if len(unitinfo.main_skill) > 1 else "无",
1331+
"EX": unitinfo.ex_skill[0].skill_level if unitinfo.ex_skill else "无",
1332+
"剧情": love_str,
1333+
"专武1": "未实装" if not unitinfo.unique_equip_slot else "无" if not unitinfo.unique_equip_slot[0].is_slot else unitinfo.unique_equip_slot[0].enhancement_level,
1334+
"专武2": "未实装" if len(unitinfo.unique_equip_slot) < 2 else "无" if not unitinfo.unique_equip_slot[1].is_slot else unitinfo.unique_equip_slot[1].enhancement_level,
1335+
"普碎数": self.data.get_inventory((eInventoryType.Item, db.unit_to_memory[unit_id])) if unit_id in db.unit_to_memory else "无",
1336+
"金碎数": self.data.get_inventory((eInventoryType.Item, db.unit_to_pure_memory[unit_id])) if unit_id in db.unit_to_pure_memory else "无",
1337+
})
1338+
1339+
return unit_data
13371340

13381341
async def recover_challenge(self, quest: int):
13391342
req = QuestRecoverChallengeRequest()

autopcr/db/database.py

Lines changed: 45 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -764,6 +764,14 @@ def event_story_detail(self) -> List[EventStoryDetail]:
764764
.to_list()
765765
)
766766

767+
@lazy_property
768+
def story_detail(self) -> Dict[int, StoryDetail]:
769+
with self.dbmgr.session() as db:
770+
return (
771+
StoryDetail.query(db)
772+
.to_dict(lambda x: x.story_id, lambda x: x)
773+
)
774+
767775
@lazy_property
768776
def unit_story(self) -> List[StoryDetail]:
769777
with self.dbmgr.session() as db:
@@ -1554,17 +1562,50 @@ def experience_knight_rank(self) -> Dict[int, ExperienceKnightRank]:
15541562
@lazy_property
15551563
def talents(self) -> Dict[int, Talent]:
15561564
with self.dbmgr.session() as db:
1557-
return Talent.query(db).to_dict(lambda x: x.talent_id, lambda x: x)
1565+
return (
1566+
Talent.query(db)
1567+
.to_dict(lambda x: x.talent_id, lambda x: x)
1568+
)
1569+
1570+
@lazy_property
1571+
def talent_level_material(self) -> Dict[int, TalentLevelMaterial]:
1572+
with self.dbmgr.session() as db:
1573+
return (
1574+
TalentLevelMaterial.query(db)
1575+
.to_dict(lambda x: x.talent_id, lambda x: x)
1576+
)
15581577

15591578
@lazy_property
15601579
def talent_skill_node(self) -> Dict[int, TalentSkillNode]:
15611580
with self.dbmgr.session() as db:
1562-
return TalentSkillNode.query(db).to_dict(lambda x: x.node_id, lambda x: x)
1581+
return (
1582+
TalentSkillNode.query(db)
1583+
.to_dict(lambda x: x.node_id, lambda x: x)
1584+
)
1585+
1586+
@lazy_property
1587+
def team_skill_enhance_level(self) -> Dict[int, TeamSkillEnhanceLevel]:
1588+
with self.dbmgr.session() as db:
1589+
return (
1590+
TeamSkillEnhanceLevel.query(db)
1591+
.to_dict(lambda x: x.enhance_level_id, lambda x: x)
1592+
)
1593+
1594+
@lazy_property
1595+
def team_skill_node(self) -> Dict[int, TeamSkillNode]:
1596+
with self.dbmgr.session() as db:
1597+
return (
1598+
TeamSkillNode.query(db)
1599+
.to_dict(lambda x: x.node_id, lambda x: x)
1600+
)
15631601

15641602
@lazy_property
15651603
def experience_talent_level(self) -> Dict[int, ExperienceTalentLevel]:
15661604
with self.dbmgr.session() as db:
1567-
return ExperienceTalentLevel.query(db).to_dict(lambda x: x.talent_level, lambda x: x)
1605+
return (
1606+
ExperienceTalentLevel.query(db)
1607+
.to_dict(lambda x: x.talent_level, lambda x: x)
1608+
)
15681609

15691610
def get_ex_equip_star_from_pt(self, id: int, pt: int) -> int:
15701611
rarity = self.get_ex_equip_rarity(id)
@@ -2209,7 +2250,7 @@ def unit_unique_equip_level_candidate(self, equip_slot: int) -> List[int]:
22092250
return list(range(st, self.unique_equipment_max_level[equip_slot] + 1))
22102251

22112252
def last_normal_quest(self) -> List[int]:
2212-
quest_ids = sorted(self.normal_quest_data.keys(), reverse=True)
2253+
quest_ids = sorted([k for k, v in self.normal_quest_data.items() if self.parse_time(v.start_time) <= apiclient.datetime] , reverse=True)
22132254
return quest_ids[:5]
22142255
last_start_time = flow(self.normal_quest_data.values()) \
22152256
.where(lambda x: db.parse_time(x.start_time) <= apiclient.datetime) \

autopcr/db/methods.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,3 +195,17 @@ def pos(self) -> str:
195195
elif self.pos_x == 8:
196196
return "右"
197197
return "未知"
198+
199+
@method
200+
class TeamSkillNode(models.TeamSkillNode):
201+
def enhance_level_ids(self) -> Iterator[int]:
202+
if self.enhance_level_id_1 != 0:
203+
yield self.enhance_level_id_1
204+
if self.enhance_level_id_2 != 0:
205+
yield self.enhance_level_id_2
206+
if self.enhance_level_id_3 != 0:
207+
yield self.enhance_level_id_3
208+
if self.enhance_level_id_4 != 0:
209+
yield self.enhance_level_id_4
210+
if self.enhance_level_id_5 != 0:
211+
yield self.enhance_level_id_5

autopcr/http_server/validator.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,8 +90,8 @@ def enable_manual_validator():
9090
def usermgr_load(qid: str, readonly=False):
9191
result = usermgr_load_legacy(qid, readonly=readonly)
9292
accountmgr_load_legacy = result.load
93-
def accountmgr_load(account: str = "", readonly=False):
94-
result = accountmgr_load_legacy(account=account, readonly=readonly)
93+
def accountmgr_load(account: str = "", readonly=False, force_use_all=False):
94+
result = accountmgr_load_legacy(account=account, readonly=readonly, force_use_all=force_use_all)
9595
async def post_login():
9696
validate_dict[qid].append(ValidateInfo(status="ok"))
9797
account_aenter_legacy = result._do_aenter

autopcr/module/accountmgr.py

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -231,9 +231,12 @@ def is_clan_battle_forbidden(self):
231231
return self._parent._parent.is_clan_battle_forbidden(username)
232232

233233
class AccountBatch(Account):
234-
def __init__(self, parent: 'AccountManager', qid: str, accounts: str = BATCHINFO, readonly: bool = False):
234+
def __init__(self, parent: 'AccountManager', qid: str, accounts: str = BATCHINFO, readonly: bool = False, force_use_all: bool = False):
235235
super().__init__(parent, qid, accounts, readonly)
236-
self.enable_account = sorted(set([x for x in self.data.batch_accounts]) & set(self._parent.accounts()))
236+
if force_use_all:
237+
self.enable_account = sorted(list(self._parent.accounts()))
238+
else:
239+
self.enable_account = sorted(set([x for x in self.data.batch_accounts]) & set(self._parent.accounts()))
237240

238241
def generate_info(self):
239242
accounts = list(self.enable_account)
@@ -264,22 +267,26 @@ async def do_from_key_pre(alias: str):
264267
ret_list = [x.get_result() for x in resps]
265268
ret = copy(ret_list[0])
266269
ret.log = '\n'.join(f"==={name}===\n{x.log}" for name, x in zip(alias, ret_list) if x.log)
270+
ret.status = eResultStatus.ERROR if any(x.status == eResultStatus.ERROR for x in ret_list) else eResultStatus.WARNING if any(x.status == eResultStatus.WARNING for x in ret_list) else eResultStatus.SUCCESS
267271
if any(r.table.header for r in ret_list):
268272
ret.table.header = next(r.table.header for r in ret_list)
269-
ret.table.header = ["昵称"] + ret.table.header
273+
ret.table.header = ["昵称", '状态'] + ret.table.header
270274
ret.table.data = [
271-
{**d, '昵称': name}
275+
{**d, '昵称': name, '状态': f"#{x.status.value}"}
272276
for name, x in zip(alias, ret_list)
273277
if x.table
274278
for d in x.table.data
275279
]
276280
else:
277-
ret.table.header = ["昵称", "结果"]
281+
ret.table.header = ["昵称", "状态", "结果"]
278282
ret.table.data = [
279-
{'昵称': name, '结果': x.log}
283+
{
284+
'昵称': name,
285+
'状态': f"#{x.status.value}",
286+
'结果': x.log
287+
}
280288
for name, x in zip(alias, ret_list)
281289
]
282-
ret.status = eResultStatus.ERROR if any(x.status == eResultStatus.ERROR for x in ret_list) else eResultStatus.WARNING if any(x.status == eResultStatus.WARNING for x in ret_list) else eResultStatus.SUCCESS
283290
all = await self.save_single_result(key, ret)
284291
resps = [all] + resps
285292
self.data.single_result[key] = resps
@@ -342,11 +349,11 @@ def set_password(self, password: str):
342349
def validate_password(self, password: str) -> bool:
343350
return self.secret.password == password
344351

345-
def load(self, account: str = "", readonly = False) -> Account:
352+
def load(self, account: str = "", readonly = False, force_use_all: bool = False) -> Account:
346353
if not AccountManager.pathsyntax.fullmatch(account):
347354
raise AccountException(f'非法账户名{account}')
348355
if account == BATCHINFO:
349-
return AccountBatch(self, self.qid, account, readonly = readonly)
356+
return AccountBatch(self, self.qid, account, readonly = readonly, force_use_all = force_use_all)
350357
if not account:
351358
account = self.secret.default_account
352359
if not account and len(list(self.accounts())) == 1:

0 commit comments

Comments
 (0)