Add: 增加了使用一键退役的支持

- 增加了根据设置选择切换函数的装饰器
- 增加了ADB截图和点击的设置, 默认使用ADB截图, uiautomator2点击
- 更新了assets.py文件, 上次commit忘记了
This commit is contained in:
LmeSzinc 2020-04-14 12:26:57 +08:00
parent ad73de92dd
commit 91e83271a4
16 changed files with 138 additions and 13 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

View File

Before

Width:  |  Height:  |  Size: 7.2 KiB

After

Width:  |  Height:  |  Size: 7.2 KiB

View File

@ -36,6 +36,7 @@ enable_low_hp_withdraw = no
scout_hp_difference_threshold = 0.2
low_hp_withdraw_threshold = 0.2
enable_retirement = yes
use_one_click_retirement = no
retire_mode = retire_10
retire_n = yes
retire_r = no
@ -78,6 +79,8 @@ command = emulator
serial = 127.0.0.1:62001
package_name = com.bilibili.azurlane
enable_perspective_error_image_save = no
use_adb_screenshot = yes
use_adb_control = no
[Daily]
enable_daily_mission = yes

68
module/base/decorator.py Normal file
View File

@ -0,0 +1,68 @@
from functools import wraps
import numpy as np
from module.logger import logger
class Config:
"""
Decorator that calls different function with a same name according to config.
func_list likes:
func_list = {
'func1': [
{'options': {'ENABLE': True}, 'func': 1},
{'options': {'ENABLE': False}, 'func': 1}
]
}
"""
func_list = {}
@classmethod
def when(cls, **kwargs):
"""
Args:
**kwargs: Any option in AzurLaneConfig.
Examples:
@Config.when(USE_ONE_CLICK_RETIREMENT=True)
def retire_ships(self, amount=None, rarity=None):
pass
@Config.when(USE_ONE_CLICK_RETIREMENT=False)
def retire_ships(self, amount=None, rarity=None):
pass
"""
options = kwargs
def decorate(func):
name = func.__name__
data = {'options': options, 'func': func}
if name not in cls.func_list:
cls.func_list[name] = [data]
else:
cls.func_list[name].append(data)
@wraps(func)
def wrapper(self, *args, **kwargs):
"""
Args:
self: ModuleBase instance.
*args:
**kwargs:
"""
for record in cls.func_list[name]:
flag = [self.config.__getattribute__(key) == value for key, value in record['options'].items()]
if not np.all(flag):
continue
return record['func'](self, *args, **kwargs)
logger.warning(f'No option fits for {name}, using the last define func.')
return func(self, *args, **kwargs)
return wrapper
return decorate

View File

@ -146,9 +146,10 @@ def main(ini_name=''):
# 退役选项
retire = setting_parser.add_argument_group('退役设置', '')
retire.add_argument('--启用退役', default=default('--启用退役'), choices=['', ''])
retire.add_argument('--使用一键退役', default=default('--使用一键退役'), choices=['', ''])
retire.add_argument('--退役方案', default=default('--退役方案'), choices=['退役全部', '退役10个'])
rarity = retire.add_argument_group('退役稀有度', '暂不支持舰种选择')
rarity = retire.add_argument_group('退役稀有度', '暂不支持舰种选择, 使用一键退役时忽略以下选项')
rarity.add_argument('--退役白皮', default=default('--退役白皮'), choices=['', ''], help='N')
rarity.add_argument('--退役蓝皮', default=default('--退役蓝皮'), choices=['', ''], help='R')
rarity.add_argument('--退役紫皮', default=default('--退役紫皮'), choices=['', ''], help='SR')
@ -208,9 +209,13 @@ def main(ini_name=''):
emulator.add_argument('--设备', default=default('--设备'), help='例如 127.0.0.1:62001')
emulator.add_argument('--包名', default=default('--包名'), help='如果不是Biliibli国服, 或者使用了非官方客户端, 需修改')
debug = emulator_parser.add_argument_group('调试', '')
debug = emulator_parser.add_argument_group('调试设置', '')
debug.add_argument('--保存透视识别出错的图像', default=default('--保存透视识别出错的图像'), choices=['', ''])
adb = emulator_parser.add_argument_group('ADB设置', '')
adb.add_argument('--使用ADB截图', default=default('--使用ADB截图'), choices=['', ''], help='建议开启, 能减少CPU占用')
adb.add_argument('--使用ADB点击', default=default('--使用ADB点击'), choices=['', ''], help='建议关闭, 能加快点击速度')
# ==========每日任务==========
daily_parser = subs.add_parser('每日任务困难演习')

View File

@ -127,7 +127,7 @@ class AzurLaneConfig:
SERIAL = '127.0.0.1:62001'
PACKAGE_NAME = 'com.bilibili.azurlane'
COMMAND = ''
USE_ADB_SCREENSHOT = False
USE_ADB_SCREENSHOT = True
USE_ADB_CONTROL = False
SCREEN_SHOT_SAVE_FOLDER_BASE = './screenshot'
SCREEN_SHOT_SAVE_FOLDER = ''
@ -180,6 +180,7 @@ class AzurLaneConfig:
module.retire
"""
ENABLE_RETIREMENT = True
USE_ONE_CLICK_RETIREMENT = False
DOCK_FULL_TRIGGERED = False
RETIRE_MODE = '10' # all, 10
RETIRE_N = True
@ -332,6 +333,8 @@ class AzurLaneConfig:
self.SERIAL = option['serial']
self.PACKAGE_NAME = option['package_name'].strip()
self.ENABLE_PERSPECTIVE_ERROR_IMAGE_SAVE = to_bool(option['enable_perspective_error_image_save'])
self.USE_ADB_SCREENSHOT = to_bool(option['use_adb_screenshot'])
self.USE_ADB_CONTROL = to_bool(option['use_adb_control'])
option = config['Setting']
# Stop condition
@ -372,6 +375,7 @@ class AzurLaneConfig:
self.SCREEN_SHOT_SAVE_FOLDER_BASE = option['drop_screenshot_folder']
# Retirement
self.ENABLE_RETIREMENT = to_bool(option['enable_retirement'])
self.USE_ONE_CLICK_RETIREMENT = to_bool(option['use_one_click_retirement'])
self.RETIRE_MODE = option['retire_mode'].split('_')[1]
for r in ['n', 'r', 'sr', 'ssr']:
self.__setattr__(f'RETIRE_{r.upper()}', to_bool(option[f'retire_{r}']))

View File

@ -70,6 +70,7 @@ dic_chi_to_eng = {
'先锋血量平衡阈值': 'scout_hp_difference_threshold',
'低血量撤退阈值': 'low_hp_withdraw_threshold',
'启用退役': 'enable_retirement',
'使用一键退役': 'use_one_click_retirement',
'退役方案': 'retire_mode',
'退役白皮': 'retire_n',
'退役蓝皮': 'retire_r',
@ -105,6 +106,8 @@ dic_chi_to_eng = {
'设备': 'serial',
'包名': 'package_name',
'保存透视识别出错的图像': 'enable_perspective_error_image_save',
'使用ADB截图': 'use_adb_screenshot',
'使用ADB点击': 'use_adb_control',
'打每日': 'enable_daily_mission',
'打困难': 'enable_hard_campaign',
'打演习': 'enable_exercise',

View File

@ -10,7 +10,7 @@ FLEET_PREPARATION = Button(area=(981, 575, 1180, 636), color=(235, 185, 114), bu
GET_EMERGENCY_REPAIR = Button(area=(645, 352, 666, 360), color=(255, 255, 255), button=(645, 352, 666, 360), file='./assets/daemon/GET_EMERGENCY_REPAIR.png')
GET_ITEMS = Button(area=(538, 217, 741, 253), color=(160, 192, 248), button=(1120, 643, 1146, 666), file='./assets/daemon/GET_ITEMS.png')
MAP_PREPARATION = Button(area=(853, 488, 1053, 549), color=(235, 186, 114), button=(853, 488, 1053, 549), file='./assets/daemon/MAP_PREPARATION.png')
STORY_CHOOSE = Button(area=(902, 344, 959, 357), color=(98, 122, 156), button=(902, 344, 959, 357), file='./assets/daemon/STORY_CHOOSE.png')
STORY_CHOOSE_2 = Button(area=(903, 388, 959, 399), color=(98, 121, 156), button=(903, 388, 959, 399), file='./assets/daemon/STORY_CHOOSE_2.png')
STORY_CHOOCE = Button(area=(902, 344, 959, 357), color=(98, 122, 156), button=(902, 344, 959, 357), file='./assets/daemon/STORY_CHOOCE.png')
STORY_CHOOCE_2 = Button(area=(903, 388, 959, 399), color=(98, 121, 156), button=(903, 388, 959, 399), file='./assets/daemon/STORY_CHOOCE_2.png')
STORY_SKIP = Button(area=(1216, 676, 1258, 708), color=(148, 159, 178), button=(1180, 30, 1256, 49), file='./assets/daemon/STORY_SKIP.png')
STRATEGY_OPEN = Button(area=(1102, 480, 1178, 482), color=(255, 223, 74), button=(1064, 405, 1093, 483), file='./assets/daemon/STRATEGY_OPEN.png')

View File

@ -45,18 +45,18 @@ class Control(Connection):
return False
def click(self, button, adb=False):
def click(self, button):
"""Method to click a button.
Args:
button (button.Button): AzurLane Button instance.
adb (bool): If use adb.
"""
self.click_record_check(button)
x, y = random_rectangle_point(button.button)
logger.info(
'Click %s @ %s' % (self._point2str(x, y), button)
)
adb = self.config.USE_ADB_CONTROL
if adb:
self._click_adb(x, y)
else:
@ -71,7 +71,7 @@ class Control(Connection):
def _click_adb(self, x, y):
self.adb_shell(['input', 'tap', str(x), str(y)], serial=self.serial)
def multi_click(self, button, n, interval=(0.1, 0.2), adb=False):
def multi_click(self, button, n, interval=(0.1, 0.2)):
click_timer = Timer(0.1)
for _ in range(n):
remain = ensure_time(interval) - click_timer.current()
@ -79,7 +79,7 @@ class Control(Connection):
self.sleep(remain)
click_timer.reset()
self.click(button, adb=adb)
self.click(button)
def long_click(self, button, duration=(1, 1.2)):
"""Method to long click a button.

View File

@ -48,9 +48,9 @@ class Device(Screenshot, Control, AppControl):
self.handle_night_commission()
return super().screenshot()
def click(self, button, adb=False):
def click(self, button):
self.handle_night_commission()
return super().click(button, adb=adb)
return super().click(button)
def swipe(self, vector, box=(123, 159, 1193, 628), random_range=(0, 0, 0, 0), padding=15, duration=(0.1, 0.2)):
self.handle_night_commission()

View File

@ -10,5 +10,9 @@ EQUIP_ENTER = Button(area=(351, 446, 361, 456), color=(252, 251, 252), button=(3
EXERCISE_PREPARATION = Button(area=(543, 539, 741, 599), color=(235, 186, 114), button=(543, 539, 741, 599), file='./assets/exercise/EXERCISE_PREPARATION.png')
NEW_OPPONENT = Button(area=(1065, 340, 1204, 382), color=(129, 166, 220), button=(1065, 340, 1204, 382), file='./assets/exercise/NEW_OPPONENT.png')
OCR_EXERCISE_REMAIN = Button(area=(1148, 145, 1178, 160), color=(105, 148, 107), button=(1148, 145, 1178, 160), file='./assets/exercise/OCR_EXERCISE_REMAIN.png')
OPPONENT_1 = Button(area=(104, 77, 316, 381), color=(101, 117, 136), button=(104, 77, 316, 381), file='./assets/exercise/OPPONENT_1.png')
OPPONENT_2 = Button(area=(348, 77, 560, 381), color=(105, 123, 149), button=(348, 77, 560, 381), file='./assets/exercise/OPPONENT_2.png')
OPPONENT_3 = Button(area=(592, 77, 804, 381), color=(106, 131, 158), button=(592, 77, 804, 381), file='./assets/exercise/OPPONENT_3.png')
OPPONENT_4 = Button(area=(836, 77, 1048, 381), color=(103, 118, 141), button=(836, 77, 1048, 381), file='./assets/exercise/OPPONENT_4.png')
QUIT_CONFIRM = Button(area=(420, 490, 593, 548), color=(199, 122, 114), button=(420, 490, 593, 548), file='./assets/exercise/QUIT_CONFIRM.png')
QUIT_RECONFIRM = Button(area=(703, 492, 877, 550), color=(195, 111, 102), button=(703, 492, 877, 550), file='./assets/exercise/QUIT_RECONFIRM.png')

View File

@ -11,6 +11,7 @@ FLEET_UNLOCKED = Button(area=(1197, 502, 1274, 519), color=(195, 168, 168), butt
FORMATION_1 = Button(area=(1108, 415, 1170, 477), color=(80, 82, 93), button=(1108, 415, 1170, 477), file='./assets/handler/FORMATION_1.png')
FORMATION_2 = Button(area=(1108, 415, 1170, 477), color=(80, 82, 92), button=(1108, 415, 1170, 477), file='./assets/handler/FORMATION_2.png')
FORMATION_3 = Button(area=(1108, 415, 1170, 477), color=(79, 82, 92), button=(1108, 415, 1170, 477), file='./assets/handler/FORMATION_3.png')
FORMATION_LOCATION = Button(area=(145, 115, 437, 159), color=(103, 118, 118), button=(145, 115, 437, 159), file='./assets/handler/FORMATION_LOCATION.png')
GET_AMMO = Button(area=(792, 315, 794, 333), color=(251, 250, 255), button=(792, 315, 794, 333), file='./assets/handler/GET_AMMO.png')
GET_ITEMS_1 = Button(area=(538, 217, 741, 253), color=(160, 192, 248), button=(924, 653, 943, 672), file='./assets/handler/GET_ITEMS_1.png')
GET_MISSION = Button(area=(553, 491, 727, 551), color=(96, 144, 204), button=(553, 491, 727, 551), file='./assets/handler/GET_MISSION.png')

View File

@ -10,6 +10,7 @@ EQUIP_CONFIRM = Button(area=(871, 516, 1044, 573), color=(95, 143, 203), button=
EQUIP_CONFIRM_2 = Button(area=(720, 541, 893, 598), color=(94, 142, 202), button=(720, 541, 893, 598), file='./assets/retire/EQUIP_CONFIRM_2.png')
GET_ITEMS_1_RETIREMENT_SAVE = Button(area=(1031, 656, 1063, 688), color=(49, 44, 54), button=(1031, 656, 1063, 688), file='./assets/retire/GET_ITEMS_1_RETIREMENT_SAVE.png')
IN_RETIREMENT_CHECK = Button(area=(854, 641, 1027, 698), color=(184, 99, 89), button=(854, 641, 1027, 698), file='./assets/retire/IN_RETIREMENT_CHECK.png')
ONE_CLICK_RETIREMENT = Button(area=(639, 641, 811, 698), color=(94, 138, 194), button=(639, 641, 811, 698), file='./assets/retire/ONE_CLICK_RETIREMENT.png')
RETIRE_APPEAR_1 = Button(area=(353, 492, 527, 550), color=(96, 144, 204), button=(353, 492, 527, 550), file='./assets/retire/RETIRE_APPEAR_1.png')
RETIRE_APPEAR_2 = Button(area=(553, 492, 727, 550), color=(94, 143, 204), button=(553, 492, 727, 550), file='./assets/retire/RETIRE_APPEAR_2.png')
RETIRE_APPEAR_3 = Button(area=(753, 492, 927, 550), color=(94, 143, 202), button=(753, 492, 927, 550), file='./assets/retire/RETIRE_APPEAR_3.png')

View File

@ -1,4 +1,5 @@
from module.base.button import ButtonGrid
from module.base.decorator import Config
from module.base.utils import get_color, color_similar
from module.combat.assets import GET_ITEMS_1
from module.handler.info_bar import InfoBarHandler
@ -115,7 +116,7 @@ class Retirement(UI, InfoBarHandler, PopupHandler):
executed = False
while 1:
self.device.screenshot()
if self.config.RETIRE_SR or self.config.RETIRE_SSR:
if self.config.RETIRE_SR or self.config.RETIRE_SSR or self.config.USE_ONE_CLICK_RETIREMENT:
if self.handle_popup_confirm():
continue
if self.appear_then_click(SHIP_CONFIRM, offset=30, interval=2):
@ -172,6 +173,40 @@ class Retirement(UI, InfoBarHandler, PopupHandler):
rarity.add('SSR')
return rarity
@Config.when(USE_ONE_CLICK_RETIREMENT=True)
def retire_ships(self, amount=None, rarity=None):
logger.hr('Retirement')
logger.info('Using one click retirement.')
if amount is None:
amount = self._retire_amount
end = False
total = 0
while 1:
self.handle_info_bar()
while 1:
self.device.screenshot()
if self.appear(SHIP_CONFIRM_2):
break
if self.info_bar_count():
logger.info('No more ships to retire.')
end = True
break
if self.appear_then_click(ONE_CLICK_RETIREMENT, interval=2):
continue
if end:
break
self._retirement_confirm()
total += 10
if total >= amount:
break
logger.info(f'Total retired round: {total // 10}')
return total
@Config.when(USE_ONE_CLICK_RETIREMENT=False)
def retire_ships(self, amount=None, rarity=None):
"""
Args:

View File

@ -10,6 +10,7 @@ COMMISSION_DAILY = Button(area=(35, 132, 67, 186), color=(208, 172, 118), button
COMMISSION_HAS_PENDING = Button(area=(357, 300, 359, 330), color=(86, 201, 173), button=(357, 300, 359, 330), file='./assets/reward/COMMISSION_HAS_PENDING.png')
COMMISSION_NOTICE_AT_CAMPAIGN = Button(area=(1054, 647, 1061, 654), color=(197, 89, 64), button=(1054, 647, 1061, 654), file='./assets/reward/COMMISSION_NOTICE_AT_CAMPAIGN.png')
COMMISSION_START = Button(area=(1028, 322, 1156, 383), color=(229, 175, 113), button=(1028, 322, 1156, 383), file='./assets/reward/COMMISSION_START.png')
COMMISSION_STOP_SCROLLING = Button(area=(115, 236, 179, 487), color=(50, 55, 74), button=(115, 236, 179, 487), file='./assets/reward/COMMISSION_STOP_SCROLLING.png')
COMMISSION_URGENT = Button(area=(35, 231, 68, 281), color=(215, 188, 124), button=(35, 231, 68, 281), file='./assets/reward/COMMISSION_URGENT.png')
EXP_INFO_S_REWARD = Button(area=(498, 140, 557, 154), color=(233, 241, 127), button=(498, 140, 557, 154), file='./assets/reward/EXP_INFO_S_REWARD.png')
MISSION_MULTI = Button(area=(1041, 8, 1101, 39), color=(226, 192, 142), button=(1041, 8, 1101, 39), file='./assets/reward/MISSION_MULTI.png')

View File

@ -85,7 +85,7 @@ class Reward(RewardCommission):
reward = True
continue
if not self.appear(page_reward.check_button):
if not self.appear(page_reward.check_button) or self.info_bar_count():
exit_timer.reset()
continue