diff --git a/autopcr/core/datamgr.py b/autopcr/core/datamgr.py index 29dbd47f..64e45176 100644 --- a/autopcr/core/datamgr.py +++ b/autopcr/core/datamgr.py @@ -120,26 +120,42 @@ def get_campaign_times(self, condition_func) -> int: times = [db.get_campaign_times(campaign_id) for campaign_id in self.campaign_list if condition_func(campaign_id)] if not times: return 0 - assert(len(times) == 1) - return int(times[0] // 1000) + times = max(times) + return int(times) def get_heart_piece_campaign_times(self) -> int: - return self.get_campaign_times(db.is_heart_piece_campaign) + return self.get_campaign_times(db.is_heart_piece_campaign) // 1000 def get_star_cup_campaign_times(self) -> int: - return self.get_campaign_times(db.is_star_cup_campaign) + return self.get_campaign_times(db.is_star_cup_campaign) // 1000 def get_normal_quest_campaign_times(self) -> int: - return self.get_campaign_times(db.is_normal_quest_campaign) + return self.get_campaign_times(db.is_normal_quest_campaign) // 1000 def get_hard_quest_campaign_times(self) -> int: - return self.get_campaign_times(db.is_hard_quest_campaign) + return self.get_campaign_times(db.is_hard_quest_campaign) // 1000 def get_very_hard_quest_campaign_times(self) -> int: - return self.get_campaign_times(db.is_very_hard_quest_campaign) + return self.get_campaign_times(db.is_very_hard_quest_campaign) // 1000 def get_dungeon_mana_campaign_times(self) -> int: - return self.get_campaign_times(db.is_dungeon_mana_campaign) + return self.get_campaign_times(db.is_dungeon_mana_campaign) // 1000 + + def get_quest_stamina_half_campaign_times(self, quest: int) -> int: + func = lambda campaign_id: \ + ( + db.is_normal_quest(quest) and db.is_normal_quest_stamina_half_campaign(campaign_id) + or db.is_hard_quest(quest) and db.is_hard_quest_stamina_half_campaign(campaign_id) + or db.is_very_hard_quest(quest) and db.is_very_hard_quest_stamina_half_campaign(campaign_id) + or db.is_heart_piece_quest(quest) and db.is_heart_piece_stamina_half_campaign(campaign_id) + or db.is_star_cup_quest(quest) and db.is_star_cup_stamina_half_campaign(campaign_id) + or db.is_hatsune_normal_quest(quest) and db.is_hatsune_normal_quest_stamina_half_campaign(campaign_id) + or db.is_hatsune_hard_quest(quest) and db.is_hatsune_hard_quest_stamina_half_campaign(campaign_id) + or db.is_shiori_normal_quest(quest) and db.is_shiori_normal_quest_stamina_half_campaign(campaign_id) + or db.is_shiori_hard_quest(quest) and db.is_shiori_hard_quest_stamina_half_campaign(campaign_id) + ) \ + and db.is_effective_scope_in_campaign(quest, campaign_id) + return self.get_campaign_times(func) def clear_inventory(self): self._inventory.clear() diff --git a/autopcr/core/pcrclient.py b/autopcr/core/pcrclient.py index ed3cdbdf..b95d5d1c 100644 --- a/autopcr/core/pcrclient.py +++ b/autopcr/core/pcrclient.py @@ -6,7 +6,7 @@ from .datamgr import datamgr from ..db.database import db from typing import Tuple, Union -import typing +import typing, math class pcrclient(apiclient): def __init__(self, sdk: sdkclient, *args, **kwargs): @@ -797,9 +797,11 @@ async def quest_skip_aware(self, quest: int, times: int, recover: bool = False, info = db.quest_info[quest] + stamina_coefficient = self.data.get_quest_stamina_half_campaign_times(quest) + if not stamina_coefficient: stamina_coefficient = 100 result: List[InventoryInfo] = [] async def skip(times): - while self.data.stamina < info.stamina * times: + while self.data.stamina < int(math.floor((info.stamina * (stamina_coefficient / 100)))) * times: if self.stamina_recover_cnt > self.data.recover_stamina_exec_count: await self.recover_stamina() else: @@ -844,55 +846,6 @@ async def skip(times): return result - ''' - async def hatsune_quest_skip_aware(self, event: int, quest: int, times: int, recover: bool = False, is_total: bool = False): - name = db.quest_name[quest] - if not quest in self.data.hatsune_quest_dict[event]: - raise AbortError(f"任务{name}未通关或不存在") - qinfo = self.data.hatsune_quest_dict[event][quest] - if qinfo.clear_flag != 3: - raise AbortError(f"任务{name}未三星") - info = db.quest_info[quest] - async def skip(times): - if self.data.stamina < info[1] * times: - if self.keys.get('buy_stamina_passive', 0) > self.data.recover_stamina_exec_count: - await self.recover_stamina() - else: - raise SkipError(f"任务{name}体力不足") - return await self.hatsune_quest_skip(event, quest, times) - result: List[InventoryInfo] = [] - if info[0]: - if is_total: - times -= qinfo.daily_clear_count - max_times = ((self.data.recover_max_time(quest) if recover else 0) + 1) * info[0] - qinfo.daily_clear_count - times = min(times, max_times) - if times <= 0: - raise SkipError(f"任务{name}已达最大次数") - remain = info[0] * (qinfo.daily_recovery_count + 1) - qinfo.daily_clear_count - while times > 0: - if remain == 0: - await self.recover_challenge(quest) - remain = info[0] - t = min(times, remain) - resp = await skip(t) - if resp.quest_result_list: - for result_list in resp.quest_result_list: - result = result + result_list.reward_list - if resp.bonus_reward_list: - result = result + resp.bonus_reward_list - times -= t - remain -= t - else: - resp = await skip(times) - if resp.quest_result_list: - for result_list in resp.quest_result_list: - result = result + result_list.reward_list - if resp.bonus_reward_list: - result = result + resp.bonus_reward_list - - return result - ''' - async def refresh(self): req = HomeIndexRequest() req.message_id = 1 diff --git a/autopcr/db/database.py b/autopcr/db/database.py index 53212868..b5fd1d67 100644 --- a/autopcr/db/database.py +++ b/autopcr/db/database.py @@ -138,7 +138,12 @@ def update(self, dbmgr: dbmgr): HatsuneSchedule.query(db) .to_dict(lambda x: x.event_id, lambda x: x) ) - + + self.campaign_beginner_data: Dict[int, CampaignBeginnerDatum] = ( + CampaignBeginnerDatum.query(db) + .to_dict(lambda x: x.beginner_id, lambda x: x) + ) + self.campaign_schedule: Dict[int, CampaignSchedule] = ( CampaignSchedule.query(db) .to_dict(lambda x: x.id, lambda x: x) @@ -700,9 +705,18 @@ def is_star_cup_quest(self, quest_id: int) -> bool: def is_hatsune_quest(self, quest_id: int) -> bool: return quest_id // 1000000 == 10 + def is_hatsune_normal_quest(self, quest_id: int) -> bool: + return self.is_hatsune_quest(quest_id) and (quest_id // 100) % 10 == 1 + + def is_hatsune_hard_quest(self, quest_id: int) -> bool: + return self.is_hatsune_quest(quest_id) and (quest_id // 100) % 10 == 2 + def is_shiori_quest(self, quest_id: int) -> bool: return quest_id // 1000000 == 20 + def is_shiori_normal_quest(self, quest_id: int) -> bool: + return self.is_shiori_quest(quest_id) and (quest_id // 100) % 10 == 1 + def is_shiori_hard_quest(self, quest_id: int) -> bool: return self.is_shiori_quest(quest_id) and (quest_id // 100) % 10 == 2 @@ -721,6 +735,37 @@ def is_hard_quest_campaign(self, campaign_id: int) -> bool: def is_very_hard_quest_campaign(self, campaign_id: int) -> bool: return self.campaign_schedule[campaign_id].campaign_category == eCampaignCategory.ITEM_DROP_AMOUNT_VERY_HARD + def is_normal_quest_stamina_half_campaign(self, campaign_id: int) -> bool: + return self.campaign_schedule[campaign_id].campaign_category == eCampaignCategory.HALF_STAMINA_NORMAL \ + or self.campaign_schedule[campaign_id].campaign_category == eCampaignCategory.HALF_STAMINA_BOTH + + def is_hard_quest_stamina_half_campaign(self, campaign_id: int) -> bool: + return self.campaign_schedule[campaign_id].campaign_category == eCampaignCategory.HALF_STAMINA_HARD \ + or self.campaign_schedule[campaign_id].campaign_category == eCampaignCategory.HALF_STAMINA_BOTH + + def is_very_hard_quest_stamina_half_campaign(self, campaign_id: int) -> bool: + return self.campaign_schedule[campaign_id].campaign_category == eCampaignCategory.HALF_STAMINA_VERY_HARD + + def is_heart_piece_stamina_half_campaign(self, campaign_id: int) -> bool: + return self.campaign_schedule[campaign_id].campaign_category == eCampaignCategory.HALF_STAMINA_UNIQUE_EQUIP + + def is_star_cup_stamina_half_campaign(self, campaign_id: int) -> bool: + return self.campaign_schedule[campaign_id].campaign_category == eCampaignCategory.HALF_STAMINA_HIGH_RARITY_EQUIP + + def is_hatsune_normal_quest_stamina_half_campaign(self, campaign_id: int) -> bool: + return self.campaign_schedule[campaign_id].campaign_category == eCampaignCategory.HALF_STAMINA_HATSUNE_NORMAL \ + or self.campaign_schedule[campaign_id].campaign_category == eCampaignCategory.HALF_STAMINA_HATSUNE_BOTH + + def is_hatsune_hard_quest_stamina_half_campaign(self, campaign_id: int) -> bool: + return self.campaign_schedule[campaign_id].campaign_category == eCampaignCategory.HALF_STAMINA_HATSUNE_HARD \ + or self.campaign_schedule[campaign_id].campaign_category == eCampaignCategory.HALF_STAMINA_HATSUNE_BOTH + + def is_shiori_normal_quest_stamina_half_campaign(self, campaign_id: int) -> bool: + return self.campaign_schedule[campaign_id].campaign_category == eCampaignCategory.HALF_STAMINA_SHIORI_NORMAL + + def is_shiori_hard_quest_stamina_half_campaign(self, campaign_id: int) -> bool: + return self.campaign_schedule[campaign_id].campaign_category == eCampaignCategory.HALF_STAMINA_SHIORI_HARD + def is_dungeon_mana_campaign(self, campaign_id: int) -> bool: return self.campaign_schedule[campaign_id].campaign_category == eCampaignCategory.GOLD_DROP_AMOUNT_DUNGEON @@ -810,6 +855,13 @@ def is_campaign(self, campaign: str, now: Union[None, datetime.datetime] = None) raise ValueError(f"不支持的庆典查询:{campaign}") return campaign_list[campaign]() + def is_effective_scope_in_campaign(self, quest_id: int, campaign_id: int) -> bool: + beginner_id = self.campaign_schedule[campaign_id].beginner_id + if beginner_id == 0: return True + id_from = self.campaign_beginner_data[beginner_id].id_from + id_to = self.campaign_beginner_data[beginner_id].id_to + return id_from <= quest_id and quest_id <= id_to + def is_clan_battle_time(self, now: Union[None, datetime.datetime] = None) -> bool: schedule = [(db.parse_time(schedule.start_time), db.parse_time(schedule.end_time)) for schedule in self.clan_battle_period.values()]