1
0
mirror of https://gitee.com/sui-feng-cb/AzurLaneAutoScript1 synced 2026-03-12 00:28:20 +08:00
Files
AzurLaneAutoScript/module/dorm/dorm.py

254 lines
8.6 KiB
Python
Raw Normal View History

import re
from PIL import Image
from module.base.button import ButtonGrid
from module.base.filter import Filter
from module.base.mask import Mask
from module.base.timer import Timer
from module.base.utils import *
from module.dorm.assets import *
from module.logger import logger
from module.ocr.ocr import Digit, DigitCounter
from module.template.assets import TEMPLATE_DORM_COIN, TEMPLATE_DORM_LOVE
from module.ui.assets import DORM_CHECK, DORM_TROPHY_CONFIRM, DORM_INFO
from module.ui.page import page_dorm, page_dormmenu
from module.ui.ui import UI
MASK_DORM = Mask(file='./assets/mask/MASK_DORM.png')
DORM_CAMERA_SWIPE = (300, 250)
DORM_CAMERA_RANDOM = (-20, -20, 20, 20)
FEED_RECORD = ('RewardRecord', 'dorm_feed')
COLLECT_RECORD = ('RewardRecord', 'dorm_collect')
FOOD = ButtonGrid(origin=(298, 375), delta=(156, 0), button_shape=(112, 66), grid_shape=(6, 1), name='FOOD')
FOOD_AMOUNT = ButtonGrid(
origin=(343, 411), delta=(156, 0), button_shape=(70, 33), grid_shape=(6, 1), name='FOOD_AMOUNT')
OCR_FOOD = Digit(FOOD_AMOUNT.buttons, letter=(255, 255, 255), threshold=128, name='OCR_DORM_FOOD')
OCR_FILL = DigitCounter(OCR_DORM_FILL, letter=(255, 247, 247), threshold=128, name='OCR_DORM_FILL')
class Food:
def __init__(self, feed, amount):
self.feed = feed
self.amount = amount
def __str__(self):
return f'Food_{self.feed}'
def __eq__(self, other):
return str(self) == str(other)
FOOD_FEED_AMOUNT = [1000, 2000, 3000, 5000, 10000, 20000]
FOOD_FILTER = Filter(regex=re.compile('(\d+)'), attr=['feed'])
class RewardDorm(UI):
def _dorm_receive_click(self):
"""
Click coins and loves in dorm.
Returns:
int: Receive count.
Pages:
in: page_dorm
out: page_dorm, with info_bar
"""
image = MASK_DORM.apply(np.array(self.device.image))
image = Image.fromarray(image)
loves = TEMPLATE_DORM_LOVE.match_multi(image, name='DORM_LOVE')
coins = TEMPLATE_DORM_COIN.match_multi(image, name='DORM_COIN')
logger.info(f'Dorm loves: {len(loves)}, Dorm coins: {len(coins)}')
count = 0
for button in loves:
count += 1
# Disable click record check, because may have too many coins or loves.
self.device.click(button, record_check=False)
self.device.sleep((0.5, 0.8))
for button in coins:
count += 1
self.device.click(button, record_check=False)
self.device.sleep((0.5, 0.8))
return count
def _dorm_receive(self):
"""
Click all coins and loves on current screen.
Zoom-out dorm to detect coins and loves, because swipes in dorm may treat as dragging ships.
Coordinates here doesn't matter too much.
Pages:
in: page_dorm, without info_bar
out: page_dorm, without info_bar
"""
for _ in range(2):
logger.info('Dorm zoom out')
# Left hand down
x, y = random_rectangle_point((33, 228, 234, 469))
self.device.minitouch_builder.down(x, y, contact_id=1).commit()
self.device.minitouch_send()
# Right hand swipe
# Need to avoid drop-down menu in android, which is 38 px.
p1, p2 = random_rectangle_vector(
(-700, 450), box=(247, 45, 1045, 594), random_range=(-50, -50, 50, 50), padding=0)
self.device._drag_minitouch(p1, p2, point_random=(0, 0, 0, 0))
# Left hand up
self.device.minitouch_builder.up(contact_id=1).commit()
self.device.minitouch_send()
# Collect
for n in range(3):
self.device.screenshot()
# Close trophies info
if self.appear(DORM_TROPHY_CONFIRM, offset=(30, 30)):
self.ui_click(DORM_TROPHY_CONFIRM, check_button=DORM_CHECK, skip_first_screenshot=True)
self.device.screenshot()
# Close DORM_INFO. Usually, it was handled in ui_ensure(), but sometimes not.
if self.appear(DORM_INFO, offset=(30, 30)):
self.ui_click(DORM_INFO, check_button=DORM_CHECK, skip_first_screenshot=True)
self.device.screenshot()
if self._dorm_receive_click():
self.ensure_no_info_bar()
continue
else:
break
def _dorm_has_food(self, button):
return np.min(rgb2gray(np.array(self.image_area(button)))) < 127
def _dorm_feed_click(self, button, count):
"""
Args:
button (Button): Food button.
count (int): Food use count.
Pages:
in: DORM_FEED_CHECK
"""
logger.info(f'Dorm feed {button} x {count}')
if count <= 3:
for _ in range(count):
self.device.click(button)
self.device.sleep((0.5, 0.8))
else:
# Long tap to feed. This requires minitouch.
timeout = Timer(count // 5 + 5).start()
x, y = random_rectangle_point(button.button)
self.device.minitouch_builder.down(x, y).commit()
self.device.minitouch_send()
while 1:
self.device.minitouch_builder.move(x, y).commit().wait(10)
self.device.minitouch_send()
self.device.screenshot()
if not self._dorm_has_food(button) \
or self.handle_info_bar() \
or self.handle_popup_cancel('dorm_feed'):
break
if timeout.reached():
logger.warning('Wait dorm feed timeout')
break
self.device.minitouch_builder.up().commit()
self.device.minitouch_send()
2021-04-06 21:59:25 +08:00
while 1:
self.device.screenshot()
if self.handle_popup_cancel('dorm_feed'):
continue
# End
if self.appear(DORM_FEED_CHECK, offset=(20, 20)):
break
def _dorm_feed_once(self):
"""
Returns:
bool: If executed.
Pages:
in: DORM_FEED_CHECK
"""
self.device.screenshot()
self.handle_info_bar()
has_food = [self._dorm_has_food(button) for button in FOOD.buttons]
amount = OCR_FOOD.ocr(self.device.image)
amount = [a if hf else 0 for a, hf in zip(amount, has_food)]
food = [Food(feed=f, amount=a) for f, a in zip(FOOD_FEED_AMOUNT, amount)]
_, fill, _ = OCR_FILL.ocr(self.device.image)
logger.info(f'Dorm food: {[f.amount for f in food]}, to fill: {fill}')
FOOD_FILTER.load(self.config.Dorm_FeedFilter)
for selected in FOOD_FILTER.apply(food):
button = FOOD.buttons[food.index(selected)]
if selected.amount > 0 and fill > selected.feed:
count = min(fill // selected.feed, selected.amount)
self._dorm_feed_click(button=button, count=count)
return True
return False
def _dorm_feed(self):
"""
Returns:
int: Executed count.
Pages:
in: DORM_FEED_CHECK
"""
logger.hr('Dorm feed')
for n in range(10):
if not self._dorm_feed_once():
logger.info('Dorm feed finished')
return n
logger.warning('Dorm feed run count reached')
return 10
def dorm_run(self, feed=True, collect=True):
"""
Pages:
in: Any page
out: page_dorm
"""
if not feed and not collect:
return
self.ui_ensure(page_dormmenu)
if not self.appear(DORM_RED_DOT, offset=(30, 30)):
logger.info('Nothing to collect. Dorm collecting skipped.')
collect = False
if not feed:
return
self.ui_goto(page_dorm, skip_first_screenshot=True)
if collect:
self._dorm_receive()
if feed:
self.ui_click(click_button=DORM_FEED_ENTER, appear_button=DORM_CHECK, check_button=DORM_FEED_CHECK,
skip_first_screenshot=True)
self._dorm_feed()
self.ui_click(click_button=DORM_FEED_ENTER, appear_button=DORM_FEED_CHECK, check_button=DORM_CHECK,
skip_first_screenshot=True)
def run(self):
"""
Pages:
in: Any page
out: page_dorm
"""
if not self.config.Dorm_Feed and not self.config.Dorm_Collect:
self.config.Scheduler_Enable = False
self.config.task_stop()
self.dorm_run(feed=self.config.Dorm_Feed, collect=self.config.Dorm_Collect)
self.config.task_delay(success=True)