Skip to content

Commit

Permalink
Merge remote-tracking branch 'parent/main'
Browse files Browse the repository at this point in the history
# Conflicts:
#	autopcr/util/arena.py
  • Loading branch information
666dechaoge committed Sep 3, 2024
2 parents 41460a2 + 96ce4b3 commit 3ca71d2
Show file tree
Hide file tree
Showing 10 changed files with 190 additions and 74 deletions.
4 changes: 2 additions & 2 deletions autopcr/core/pcrclient.py
Original file line number Diff line number Diff line change
Expand Up @@ -660,14 +660,14 @@ async def receive_all(self):
req.type = 1
await self.request(req)

async def serlize_gacha_reward(self, gacha: GachaReward):
async def serlize_gacha_reward(self, gacha: GachaReward, gacha_id: int = 0):
res = ""
if gacha.new_unit:
res += f"NEW: \n" + '\n'.join([db.get_inventory_name(item) for item in gacha.new_unit]) + '\n'
if gacha.unit_rarity:
res += ' '.join(["★"*i + f"x{cnt}" for i, cnt in gacha.unit_rarity.items()]) + '\n'
if gacha.prize_rarity:
res += ' '.join([f"{i}" + f"x{cnt}" for i, cnt in gacha.prize_rarity.items()]) + '\n'
res += ' '.join([f"{db.get_gacha_prize_name(gacha_id, i)}" + f"x{cnt}" for i, cnt in gacha.prize_rarity.items()]) + '\n'

res += await self.serlize_reward(gacha.reward_list)

Expand Down
29 changes: 25 additions & 4 deletions autopcr/db/database.py
Original file line number Diff line number Diff line change
Expand Up @@ -534,7 +534,18 @@ def update(self, dbmgr: dbmgr):
PrizegachaDatum.query(db)
.to_dict(lambda x: x.prizegacha_id, lambda x: x)
)


self.prizegacha_sp_data: Dict[int, Dict[int, PrizegachaSpDatum]] = (
PrizegachaSpDatum.query(db)
.group_by(lambda x: x.gacha_id)
.to_dict(lambda x: x.key, lambda x: x.to_dict(lambda x: x.rarity, lambda x: x))
)

self.prizegacha_sp_detail: Dict[int, PrizegachaSpDetail] = (
PrizegachaSpDetail.query(db)
.to_dict(lambda x: x.disp_rarity, lambda x: x)
)

self.campaign_gacha: Dict[int, CampaignFreegacha] = (
CampaignFreegacha.query(db)
.to_dict(lambda x: x.campaign_id, lambda x: x)
Expand Down Expand Up @@ -884,9 +895,12 @@ def get_open_secret_dungeon_area(self) -> int:
return schedule[0]

def parse_time(self, time: str) -> datetime.datetime:
if time.count(':') == 1: # 怎么以前没有秒的
time += ":00"
return datetime.datetime.strptime(time, '%Y/%m/%d %H:%M:%S')
for timeformat in ['%Y/%m/%d %H:%M:%S', '%Y/%m/%d %H:%M', '%Y-%m-%dT%H:%M:%S.%fZ']:
try:
return datetime.datetime.strptime(time, timeformat)
except:
pass
raise ValueError(f"无法解析时间:{time}")

def parse_time_safe(self, time: str) -> datetime.datetime:
return datetime.datetime.strptime(time, '%Y%m%d%H%M%S')
Expand Down Expand Up @@ -1020,4 +1034,11 @@ def last_normal_quest_candidate(self):
.select(lambda x: f"{x.quest_id}: {x.quest_name.split(' ')[1]}") \
.to_list()

def get_gacha_prize_name(self, gacha_id: int, prize_rarity: int) -> str:
if gacha_id in self.prizegacha_sp_data:
prize_rarity = self.prizegacha_sp_data[gacha_id][prize_rarity].disp_rarity
if prize_rarity in self.prizegacha_sp_detail:
return self.prizegacha_sp_detail[prize_rarity].name
return f"{prize_rarity}等奖"

db = database()
1 change: 1 addition & 0 deletions autopcr/module/modules/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@
tool_modules = [
# cook_pudding,
unit_promote,
missing_unit,
get_need_equip,
get_normal_quest_recommand,
get_need_memory,
Expand Down
10 changes: 5 additions & 5 deletions autopcr/module/modules/autosweep.py
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ def get_max_times(self, client: pcrclient, quest_id: int) -> int:
return 5

unique_equip_2_pure_memory_id = [
(32025, 1), # 水女仆
(32025, 2), # 水女仆,女仆
(32046, 1), # 水猫剑
(32048, 1), # 水子龙
(32060, 1), # 黑猫
Expand Down Expand Up @@ -356,8 +356,8 @@ async def get_start_quest(self, client: pcrclient) -> List[Tuple[int, int]]:
if is_start_run_time:
self._log(f"刷取start关卡")
for tab in client.data.user_my_quest:
for x in tab.skip_list:
if tab.tab_name == 'start':
if tab.tab_name == 'start':
for x in tab.skip_list:
quest.append((x, tab.skip_count))
return quest

Expand All @@ -367,8 +367,8 @@ async def get_loop_quest(self, client: pcrclient) -> List[Tuple[int, int]]:
if is_loop_run_time:
self._log(f"刷取loop关卡")
for tab in client.data.user_my_quest:
for x in tab.skip_list:
if tab.tab_name == 'loop':
if tab.tab_name == 'loop':
for x in tab.skip_list:
quest.append((x, tab.skip_count))
return quest

Expand Down
4 changes: 2 additions & 2 deletions autopcr/module/modules/gacha.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ async def do_task(self, client: pcrclient):
self._log("使用十连")
gacha_reward += await client.exec_gacha_aware(gacha, 10, eGachaDrawType.Monthly_Free_Multi, 1, 0)

reward = await client.serlize_gacha_reward(gacha_reward)
reward = await client.serlize_gacha_reward(gacha_reward, gacha.id)
if reward != "无":
self._log(reward)
point = client.data.gacha_point[gacha.exchange_id].current_point if gacha.exchange_id in client.data.gacha_point else 0
Expand Down Expand Up @@ -115,4 +115,4 @@ async def do_task(self, client: pcrclient):
gacha_reward += await client.exec_gacha_aware(target_gacha, 10, eGachaDrawType.Campaign10Shot, cnt, res.campaign_info.campaign_id)
cnt -= 1

self._log(await client.serlize_gacha_reward(gacha_reward))
self._log(await client.serlize_gacha_reward(gacha_reward, target_gacha.id))
2 changes: 1 addition & 1 deletion autopcr/module/modules/shop.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ def buy_kind(self) -> List[str]: return self.get_config('normal_shop_buy_kind')
@default(False)
class limit_shop(shop_buyer):
def _exp_count(self): return 999000 if "经验药水" in self.get_config('limit_shop_buy_kind') else 0
def _equip_count(self): return 999000 if "装备" in self.get_config('limit_shop_buy_kind') else 0
def _equip_count(self): return 999000 if "装备" in self.get_config('limit_shop_buy_kind') else -999000
def coin_limit(self) -> int: return self.get_config('limit_shop_buy_coin_limit')
def system_id(self) -> eSystemId: return eSystemId.LIMITED_SHOP
def reset_count(self) -> int: return 0
Expand Down
52 changes: 33 additions & 19 deletions autopcr/module/modules/tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,27 @@ async def read_drama(psy_top_resp: PsyTopResponse):
if is_abort: raise AbortError("")
if is_skip: raise SkipError("")


@description('来进行赛博抽卡')
@description('看看你缺了什么角色')
@name('查缺角色')
@default(True)
class missing_unit(Module):
async def do_task(self, client: pcrclient):
missing_unit = set(db.unlock_unit_condition.keys()) - set(client.data.unit.keys())
if not missing_unit:
self._log("全图鉴玩家!你竟然没有缺少的角色!")
else:
limit_unit = set(id for id in missing_unit if db.unit_data[id].is_limited)
resident_unit = missing_unit - limit_unit
self._log(f"缺少{len(missing_unit)}个角色,其中{len(limit_unit)}个限定角色,{len(resident_unit)}个常驻角色")
if limit_unit:
self._log(f"==限定角色==" )
self._log('\n'.join(db.get_unit_name(id) for id in limit_unit))
self._log('')
if resident_unit:
self._log(f"==常驻角色==" )
self._log('\n'.join(db.get_unit_name(id) for id in resident_unit))

@description('警告!真抽!抽到出指NEW出保底角色,或达天井停下来,如果已有保底角色,就不会NEW!意味着就是一井!')
@name('抽卡')
@booltype("single_ticket", "用单抽券", False)
@singlechoice("pool_id", "池子", "", db.get_cur_gacha)
Expand Down Expand Up @@ -136,7 +155,7 @@ async def do_task(self, client: pcrclient):
raise
finally:
self._log(f"抽取了{cnt}{'十连' if not single_ticket else '单抽'}")
self._log(await client.serlize_gacha_reward(reward))
self._log(await client.serlize_gacha_reward(reward, target_gacha.id))
point = client.data.gacha_point[target_gacha.exchange_id].current_point if target_gacha.exchange_id in client.data.gacha_point else 0
self._log(f"当前pt为{point}")

Expand Down Expand Up @@ -262,11 +281,11 @@ async def do_task(self, client: pcrclient):

rank_id = list(range(len(attack)))
best_team_id = await self.choose_best_team(attack, rank_id, client)
if best_team_id >= 0: # it always be the first one now
if best_team_id >= 0 and best_team_id < len(attack):
self._log(f"选择第{best_team_id + 1}支队伍作为进攻方队伍")
await self.update_deck(attack[best_team_id], client)
else:
self._log("未找到合适队伍,请自行选择")
self._warn(f"队伍只有{len(attack)}支,无法选择第{best_team_id + 1}支队伍作为进攻方队伍")

attack_str = self.present_attack(attack[:max(8, best_team_id + 1)])
msg = [defend_str, "-------", attack_str]
Expand All @@ -275,6 +294,7 @@ async def do_task(self, client: pcrclient):
@description('查询jjc回刺阵容,并自动设置进攻队伍,对手排名=0则查找对战纪录第一条刺人的,<0则查找对战纪录,-1表示第一条,-2表示第二条,以此类推')
@name('jjc回刺查询')
@default(True)
@inttype("opponent_jjc_attack_team_id", "选择阵容", 1, [i for i in range(1, 10)])
@inttype("opponent_jjc_rank", "对手排名", -1, [i for i in range(-20, 101)])
class jjc_back(Arena):

Expand All @@ -297,11 +317,8 @@ def present_attack(self, attack: List[ArenaQueryResult]) -> str:
return msg

async def choose_best_team(self, team: List[ArenaQueryResult], rank_id: List[int], client: pcrclient) -> int:
all_have = [id for id in rank_id if all(
unit.id in client.data.unit and
client.data.unit[unit.id].promotion_level > 7
for unit in team[id].atk)]
return -1 if not all_have else all_have[0]
id = int(self.get_config("opponent_jjc_attack_team_id")) - 1
return id

async def update_deck(self, units: ArenaQueryResult, client: pcrclient):
units_id = [unit.id for unit in units.atk]
Expand All @@ -313,7 +330,7 @@ async def update_deck(self, units: ArenaQueryResult, client: pcrclient):

under_rank_bonus_unit = [unit for unit in units_id if client.data.unit[unit].promotion_level < db.equip_max_rank - 1]
if under_rank_bonus_unit:
self._warn(f"警告{'|'.join([db.get_unit_name(unit_id) for unit_id in under_rank_bonus_unit])}无品级加成")
self._warn(f"无品级加成{''.join([db.get_unit_name(unit_id) for unit_id in under_rank_bonus_unit])}")

await client.deck_update(ePartyType.ARENA, units_id)

Expand Down Expand Up @@ -349,6 +366,7 @@ async def get_attack_team(self, defen: List[int]) -> List[ArenaQueryResult]:
@description('查询pjjc回刺阵容,并自动设置进攻队伍,对手排名=0则查找对战纪录第一条刺人的,<0则查找对战纪录,-1表示第一条,-2表示第二条,以此类推')
@name('pjjc回刺查询')
@default(True)
@inttype("opponent_pjjc_attack_team_id", "选择阵容", 1, [i for i in range(1, 10)])
@inttype("opponent_pjjc_rank", "对手排名", -1, [i for i in range(-20, 101)])
class pjjc_back(Arena):
def target_rank(self) -> int:
Expand All @@ -361,7 +379,7 @@ def present_defend(self, defen: List[List[int]]) -> str:
return msg

def present_attack(self, attack: List[List[ArenaQueryResult]]) -> str:
msg = [ArenaQuery.str_result(x) for x in attack]
msg = [f"第{id + 1}对策\n{ArenaQuery.str_result(x)}" for id, x in enumerate(attack)]
msg = '\n\n'.join(msg)
return msg

Expand All @@ -372,12 +390,8 @@ async def self_rank(self, client: pcrclient) -> int:
return (await client.get_grand_arena_info()).grand_arena_info.rank

async def choose_best_team(self, team: List[List[ArenaQueryResult]], rank_id: List[int], client: pcrclient) -> int:
all_have = [id for id in rank_id if all(
unit.id in client.data.unit and
client.data.unit[unit.id].promotion_level > 7
for units in team[id]
for unit in units.atk)]
return -1 if not all_have else all_have[0]
id = int(self.get_config("opponent_pjjc_attack_team_id")) - 1
return id

async def update_deck(self, units: List[ArenaQueryResult], client: pcrclient):
units_id = [[uni.id for uni in unit.atk] for unit in units]
Expand All @@ -392,7 +406,7 @@ async def update_deck(self, units: List[ArenaQueryResult], client: pcrclient):
under_rank_bonus_unit = [uni_id for unit_id in units_id for uni_id in unit_id if
client.data.unit[uni_id].promotion_level < db.equip_max_rank - 1]
if under_rank_bonus_unit:
self._warn(f"警告{'|'.join([db.get_unit_name(unit_id) for unit_id in under_rank_bonus_unit])}无品级加成")
self._warn(f"无品级加成{''.join([db.get_unit_name(unit_id) for unit_id in under_rank_bonus_unit])}")

deck_list = []
for i, unit_id in enumerate(units_id):
Expand Down
82 changes: 41 additions & 41 deletions autopcr/util/arena.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
from typing import List, Set, Tuple
import json, asyncio, time, os
import json, asyncio, time
from os.path import join, exists
from random import random, choice, sample
from math import log
from random import choice, sample, choices

from ..model.custom import PLACEHOLDER, ArenaQueryType, ArenaQueryUnit, ArenaRegion, ArenaQueryResult, ArenaQueryResponse
from . import aiorequests
from . import aiorequests, pcrdapi

try:
from hoshino.modules.priconne.arena.arena import curpath as CACHE_DIR
Expand All @@ -32,46 +31,41 @@ def __init__(self):
with open(self.timepath, 'r', encoding="utf-8") as fp:
self.buffer = json.load(fp)

def __get_query_ip(self):
query_ip = os.getenv('QUERY_IP', None)
if query_ip:
return query_ip
else:
return "https://api.pcrdfans.com/x/v1/search"
_endpoint = 'https://api.pcrdfans.com/x/v1/search'
_headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36 Edg/126.0.0.0",
"Referer": "https://pcrdfans.com/",
"Origin": "https://pcrdfans.com",
"Accept": "*/*",
"Content-Type": "application/json; charset=utf-8",
"Authorization": "",
"Host": "api.pcrdfans.com",
}

@staticmethod
def _getNonce():
return ''.join(choices("0123456789abcdefghijklmnopqrstuvwxyz", k=16))

def __get_query_header(self):
return {
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.87 Safari/537.36",
"authorization": self.__get_auth_key(),
}
@staticmethod
def _getTs():
return int(time.time())

def __get_auth_key(self):
key = ""
try:
from hoshino.config.priconne import arena
key = arena.AUTH_KEY
except:
from ..constants import AUTH_KEY
key = AUTH_KEY
if not key:
key = os.getenv('AUTH_KEY', None)
if not key:
raise ValueError("请配置key")
return key

def __get_query_payload(self, units, region):
timestamp = int(time.time())
@staticmethod
def _get_query_payload(units, region):
return {
"_sign": "a",
"def": units,
"nonce": "a",
"language": 0,
"nonce": ArenaQuery._getNonce(),
"page": 1,
"sort": 1,
"ts": timestamp,
"region": region,
"sort": 1,
"ts": ArenaQuery._getTs()
}

@staticmethod
def _dumps(x):
return json.dumps(x, ensure_ascii=False).replace(' ', '')

def save_buffer(self):
with open(self.timepath, 'w', encoding="utf-8") as fp:
json.dump(self.buffer, fp, ensure_ascii=False, indent=4)
Expand Down Expand Up @@ -125,10 +119,12 @@ async def do_query(self, units: List[int], region: ArenaRegion) -> List[ArenaQue
async with self.querylock:
await asyncio.sleep(1)
try:
data = ArenaQuery._get_query_payload(units, region)
data['_sign'] = pcrdapi.sign(ArenaQuery._dumps(data), data['nonce'])
resp = await aiorequests.post(
self.__get_query_ip(),
headers=self.__get_query_header(),
json=self.__get_query_payload(units, region),
ArenaQuery._endpoint,
headers=ArenaQuery._headers,
data=ArenaQuery._dumps(data).encode('utf8'),
timeout=5,
)
res = await resp.json()
Expand Down Expand Up @@ -265,14 +261,18 @@ async def get_multi_attack(self, available_unit: Set[int], defens: List[List[int
def str_result(self, result: List[ArenaQueryResult]):
msg = ""
from ..db.database import db
for ret in result:
for id, ret in enumerate(result):
head = f"{id}. {db.format_time(db.parse_time(ret.updated))}"
tail = f"{ret.up}/{ret.down}"
if ret.query_type == ArenaQueryType.APPROXIMATION:
tail += f"(近似解)"
elif ret.query_type == ArenaQueryType.PLACEHOLDER:
tail = f"凑解"
msg += f'''【{" ".join([db.get_unit_name(unit.id) for unit in ret.atk])}{tail}\n'''
comment = '\n'.join([f" | {db.format_time(db.parse_time(c.date))}: {c.msg.strip()}" for c in ret.comment[:3] if c.msg.strip()]) if ret.comment else " | 无评论"
msg += f'''{head}:【{" ".join([db.get_unit_name(unit.id) for unit in ret.atk])}{tail}
{comment}
'''

return msg

instance = ArenaQuery()
instance = ArenaQuery()
Loading

0 comments on commit 3ca71d2

Please sign in to comment.