Skip to content

Commit c0a719c

Browse files
authored
Merge pull request #296 from chzhong/feature/basic-info
基本信息显示优化+Python 3.8 兼容
2 parents 17f02e3 + 63dfdc3 commit c0a719c

5 files changed

Lines changed: 169 additions & 18 deletions

File tree

autopcr/core/datamgr.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -605,6 +605,8 @@ def get_shop_gold(self, shop_id: int) -> int:
605605
return self.get_inventory((eInventoryType.Item, 90010))
606606
elif shop_id == eSystemId.EX_EQUIPMENT_ACCESSORY_SHOP: # EX饰品店
607607
return self.get_inventory((eInventoryType.Item, 90011))
608+
elif shop_id == eSystemId.CONNECT_SHOP: # 连结商店
609+
return self.get_inventory((eInventoryType.Item, 90012))
608610
else:
609611
raise ValueError(f"未知的商店{shop_id}")
610612

autopcr/db/database.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ class database():
6969
sun_ball: ItemType = (eInventoryType.Item, 25014)
7070
dark_ball: ItemType = (eInventoryType.Item, 25015)
7171
ex_rainbow_enhance_pt: ItemType = (eInventoryType.Item, 26202)
72+
ex_rainbow_enhance_ball: ItemType = (eInventoryType.Item, 26203)
7273

7374
def __init__(self):
7475
self.dbmgr: Optional[dbmgr] = None

autopcr/module/modules/daily.py

Lines changed: 119 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
from ...db.database import db
1010
from ...model.enums import *
1111
from ...util.questutils import *
12+
from ...util.format_number import format_number
1213

1314
@description('仅开启时生效,氪体数将取满足条件的最大值,禅模式指不执行体力相关的功能,仅在清日常生效,单项执行将忽略。庆典包括其倍数,加速期间的所有倍数判断均x2')
1415
@name("全局配置")
@@ -279,27 +280,130 @@ async def do_task(self, client: pcrclient):
279280
await client.receive_grand_arena_reward()
280281
self._log(f"pjjc币x{info.reward_info.count}")
281282

282-
@description('展示基本信息')
283+
_USER_INFO_DISPLAY_ORDER = (
284+
'玛娜', '心碎', '星球杯', '星幽碎片', '属性球', '大师碎片', '炼金点数',
285+
'香水', '扫荡券', '加速券', '大师币', '连结币',
286+
)
287+
288+
@description('展示基本信息,固定显示玩家名、体力、等级、钻石、母猪石、全角色战力,可自定义显示其他信息')
283289
@name('基本信息')
284290
@default(True)
291+
@multichoice(
292+
"user_info_display", "显示信息",
293+
['心碎', '星幽碎片', '炼金点数', '香水'],
294+
['玛娜', '心碎', '星球杯', '星幽碎片', '属性球', '大师碎片', '炼金点数', '香水', '扫荡券', '加速券', '大师币', '连结币']
295+
)
285296
class user_info(Module):
297+
def _collect_optional_info(self, client: pcrclient, display_items: set[str]) -> dict[str, str]:
298+
data = client.data
299+
inv = data.get_inventory
300+
301+
def fmt(n: int, **kwargs) -> str:
302+
return format_number(n, **kwargs)
303+
304+
def fmt_heart() -> str:
305+
heart = inv(db.heart)
306+
xinsui = inv(db.xinsui)
307+
if heart > 0:
308+
return f"{fmt(xinsui)}(大心 {fmt(heart)})"
309+
return fmt(xinsui)
310+
311+
def fmt_balls() -> str:
312+
items = [
313+
db.fire_ball,
314+
db.water_ball,
315+
db.wind_ball,
316+
db.sun_ball,
317+
db.dark_ball,
318+
]
319+
return '/'.join(fmt(inv(item)) for item in items)
320+
321+
def fmt_master_fragment() -> str:
322+
master = inv(db.master_fragment)
323+
master_f = inv(db.master_ffragment)
324+
if master_f > 0:
325+
return f"{master}(残片 {master_f})"
326+
return str(master)
327+
328+
handlers = {
329+
'玛娜': lambda: fmt(
330+
data.gold.gold_id_free + data.gold.gold_id_pay,
331+
scale='亿',
332+
decimals=1,
333+
separator='no',
334+
),
335+
'心碎': fmt_heart,
336+
'星球杯': lambda: fmt(inv(db.xingqiubei)),
337+
'星幽碎片': lambda: fmt(inv(db.xinyou)),
338+
'母猪石': lambda: fmt(inv((eInventoryType.Item, 90005))),
339+
'属性球': fmt_balls,
340+
'大师碎片': fmt_master_fragment,
341+
'炼金点数': lambda: fmt(
342+
inv(db.ex_rainbow_enhance_pt),
343+
scale='万',
344+
decimals=0,
345+
separator='no',
346+
),
347+
'香水': lambda: str(inv(db.ex_rainbow_enhance_ball)),
348+
'扫荡券': lambda: fmt(inv((eInventoryType.Item, 23001))),
349+
'加速券': lambda: str(inv(db.travel_speed_up_paper)),
350+
'大师币': lambda: fmt(
351+
inv((eInventoryType.Item, 90008)),
352+
scale='万',
353+
decimals=1,
354+
separator='no',
355+
),
356+
'连结币': lambda: str(inv((eInventoryType.Item, 90012))),
357+
}
358+
359+
return {
360+
key: handlers[key]()
361+
for key in _USER_INFO_DISPLAY_ORDER
362+
if key in display_items and key in handlers
363+
}
364+
365+
def _log_optional_info(self, optional_info: dict[str, str], pig: int) -> None:
366+
keys = [k for k in _USER_INFO_DISPLAY_ORDER if k in optional_info]
367+
368+
line2_items = [
369+
f"{key}{optional_info[key]}"
370+
for key in keys[:2]
371+
]
372+
line2_items.append(f"母猪石{format_number(pig)}")
373+
self._log(' '.join(line2_items))
374+
375+
for i in range(2, len(keys), 3):
376+
line_items = [
377+
f"{key}{optional_info[key]}"
378+
for key in keys[i:i + 3]
379+
]
380+
self._log(' '.join(line_items))
381+
286382
async def do_task(self, client: pcrclient):
383+
data = client.data
287384
now = db.format_time(apiclient.datetime)
288-
name = client.data.user_name
289-
level = client.data.team_level
290-
stamina = client.data.stamina
291-
max_stamina = db.team_info[client.data.team_level].max_stamina
292-
jewel = client.data.jewel.free_jewel
293-
mana = client.data.gold.gold_id_free
294-
sweep_ticket = client.data.get_inventory((eInventoryType.Item, 23001))
295-
pig = client.data.get_inventory((eInventoryType.Item, 90005))
296-
tot_power = sum([client.data.get_unit_power(unit) for unit in client.data.unit])
385+
display_items = set(self.get_config('user_info_display'))
386+
387+
name = data.user_name
388+
level = data.team_level
389+
stamina = data.stamina
390+
max_stamina = db.team_info[level].max_stamina
391+
jewel = data.jewel.free_jewel + data.jewel.jewel
392+
pig = data.get_inventory((eInventoryType.Item, 90005))
393+
total_power = sum(data.get_unit_power(unit) for unit in data.unit)
297394

298395
if stamina >= max_stamina:
299-
self._warn(f"体力爆了!")
300-
self._log(f"{name} 体力{stamina}({max_stamina}) 等级{level} 钻石{jewel}")
301-
self._log(f"玛那{mana} 扫荡券{sweep_ticket} 母猪石{pig}")
302-
self._log(f"全角色战力:{tot_power}")
303-
self._log(f"已氪体数:{client.data.recover_stamina_exec_count}")
396+
self._warn("体力爆了!")
397+
398+
optional_info = self._collect_optional_info(client, display_items)
399+
400+
self._log(
401+
f"{name} 体力{stamina}({max_stamina}) "
402+
f"等级{level} 钻石{format_number(jewel)}"
403+
)
404+
self._log_optional_info(optional_info, pig)
405+
406+
self._log(f"全角色战力:{format_number(total_power)}")
407+
self._log(f"已氪体数:{data.recover_stamina_exec_count}")
304408
self._log(f"清日常时间:{now}")
305409

autopcr/util/format_number.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
from typing import Literal, Optional
2+
3+
SCALES = {
4+
'亿': [('亿', 10 ** 8), ('万', 10 ** 4)],
5+
'万': [('万', 10 ** 4)],
6+
'b': [('b', 10 ** 9), ('m', 10 ** 6), ('k', 10 ** 3)],
7+
'm': [('m', 10 ** 6), ('k', 10 ** 3)],
8+
'k': [('k', 10 ** 3)],
9+
}
10+
11+
def _trim_float(s: str) -> str:
12+
return s.rstrip('0').rstrip('.') if '.' in s else s
13+
14+
def _add_separator(s: str, val: int, mode: Literal['auto', 'no', 'yes']) -> str:
15+
if mode == 'no':
16+
return s
17+
18+
use_separator = mode == 'yes' or abs(val) >= 100_000
19+
if not use_separator:
20+
return s
21+
22+
if '.' in s:
23+
int_part, frac_part = s.split('.', 1)
24+
return f"{int(int_part):,}.{frac_part}"
25+
26+
return f"{int(s):,}"
27+
28+
def format_number(
29+
val: int,
30+
scale: Optional[Literal['k', 'm', 'b', '万', '亿']] = None,
31+
decimals: int = 2,
32+
separator: Literal['auto', 'no', 'yes'] = 'auto',
33+
) -> str:
34+
if scale is None:
35+
return _add_separator(str(int(val)), val, separator)
36+
37+
for suffix, div in SCALES[scale]:
38+
if abs(val) >= div:
39+
num = val / div
40+
s = _trim_float(f"{num:.{decimals}f}")
41+
return _add_separator(s, val, separator) + suffix
42+
43+
return _add_separator(str(int(val)), val, separator)
44+

autopcr/util/unit_recognizer.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from dataclasses import dataclass
77
from io import BytesIO
88
from pathlib import Path
9-
from typing import Dict, List, Optional, Tuple
9+
from typing import Dict, List, Optional, Tuple, OrderedDict as OrderedDictType
1010

1111
import cv2
1212
import numpy as np
@@ -41,7 +41,7 @@ def __init__(self):
4141
self._hist_centered_arr: np.ndarray = np.empty((0, 0), dtype=np.float32)
4242
self._hist_norm_arr: np.ndarray = np.empty((0,), dtype=np.float32)
4343
self._template_scaled_cache: Dict[int, List[np.ndarray]] = {}
44-
self._unit_result_cache: OrderedDict[bytes, Tuple[int, int]] = OrderedDict()
44+
self._unit_result_cache: OrderedDictType[bytes, Tuple[int, int]] = OrderedDict()
4545
self._unit_result_cache_max = 4096
4646
self.init = False
4747
self.ver = None
@@ -222,7 +222,7 @@ def _legacy_split_last_col_recs(recs: List[Tuple[int, int, int, int]]) -> Tuple[
222222
return remaining, last_col_recs
223223

224224
@staticmethod
225-
def _save_lru_result(cache: OrderedDict[bytes, Tuple[int, int]], key: bytes, value: Tuple[int, int], max_size: int):
225+
def _save_lru_result(cache: OrderedDictType[bytes, Tuple[int, int]], key: bytes, value: Tuple[int, int], max_size: int):
226226
cache[key] = value
227227
cache.move_to_end(key)
228228
if len(cache) > max_size:

0 commit comments

Comments
 (0)