1
0
mirror of https://github.com/TheFunny/ArisuAutoSweeper synced 2025-12-16 22:05:12 +00:00

Compare commits

...

8 Commits

30 changed files with 518 additions and 18 deletions

View File

@ -12,8 +12,8 @@
The script is still under active development. The following features have been implemented:
- [x] **Cafe** Claim rewards / Interact / Second cafe
- [x] **Circle** Claim AP
- [x] **Cafe** Claim rewards / Interact / Second floor
- [x] **Club** Claim AP
- [x] **Mailbox** Claim rewards
- [x] **Tactical Challenge** Claim rewards / Auto battle

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

View File

@ -205,8 +205,8 @@
"help": "Auto adjust cafe interface for better student interaction"
},
"SecondCafe": {
"name": "Second Cafe",
"help": "Enable auto switch to second cafe and perform interaction"
"name": "Second Floor",
"help": "JP server only\nEnable auto switch to second floor and perform interaction"
}
},
"TacticalChallenge": {

View File

@ -206,7 +206,7 @@
},
"SecondCafe": {
"name": "第二咖啡厅",
"help": "自动切换第二咖啡厅进行互动点击"
"help": "仅支持日服\n自动切换第二咖啡厅进行互动点击"
}
},
"TacticalChallenge": {

View File

@ -863,8 +863,8 @@ class Connection(ConnectionAttr):
# Auto package detection
if len(packages) == 0:
logger.critical(f'No Star Rail package found, '
f'please confirm Star Rail has been installed on device "{self.serial}"')
logger.critical(f'No Blue Archive package found, '
f'please confirm Blue Archive has been installed on device "{self.serial}"')
raise RequestHumanTakeover
if len(packages) == 1:
logger.info('Auto package detection found only one package, using it')
@ -877,6 +877,6 @@ class Connection(ConnectionAttr):
# set_server(self.package)
else:
logger.critical(
f'Multiple Star Rail packages found, auto package detection cannot decide which to choose, '
f'Multiple Blue Archive packages found, auto package detection cannot decide which to choose, '
'please copy one of the available devices listed above to Alas.Emulator.PackageName')
raise RequestHumanTakeover

View File

@ -12,6 +12,7 @@ ACCOUNT_INFO_CHECK = ButtonWrapper(
color=(193, 201, 210),
button=(108, 11, 235, 36),
),
en=None,
)
BACK = ButtonWrapper(
name='BACK',
@ -22,6 +23,7 @@ BACK = ButtonWrapper(
color=(93, 118, 164),
button=(34, 19, 81, 56),
),
en=None,
)
BOUNTY_CHECK = ButtonWrapper(
name='BOUNTY_CHECK',
@ -32,6 +34,7 @@ BOUNTY_CHECK = ButtonWrapper(
color=(150, 164, 177),
button=(107, 10, 158, 37),
),
en=None,
)
CAFE_CHECK = ButtonWrapper(
name='CAFE_CHECK',
@ -42,6 +45,7 @@ CAFE_CHECK = ButtonWrapper(
color=(188, 197, 205),
button=(264, 11, 337, 35),
),
en=None,
)
CIRCLE_CHECK = ButtonWrapper(
name='CIRCLE_CHECK',
@ -52,6 +56,7 @@ CIRCLE_CHECK = ButtonWrapper(
color=(195, 203, 211),
button=(107, 11, 211, 36),
),
en=None,
)
COMMISSIONS_CHECK = ButtonWrapper(
name='COMMISSIONS_CHECK',
@ -62,6 +67,7 @@ COMMISSIONS_CHECK = ButtonWrapper(
color=(146, 160, 174),
button=(107, 10, 158, 37),
),
en=None,
)
CRAFTING_CHECK = ButtonWrapper(
name='CRAFTING_CHECK',
@ -72,6 +78,7 @@ CRAFTING_CHECK = ButtonWrapper(
color=(200, 208, 215),
button=(108, 10, 214, 37),
),
en=None,
)
GACHA_CHECK = ButtonWrapper(
name='GACHA_CHECK',
@ -82,6 +89,7 @@ GACHA_CHECK = ButtonWrapper(
color=(135, 148, 164),
button=(159, 10, 210, 37),
),
en=None,
)
HOME = ButtonWrapper(
name='HOME',
@ -92,6 +100,7 @@ HOME = ButtonWrapper(
color=(168, 182, 205),
button=(1218, 8, 1253, 41),
),
en=None,
)
LOADING_CHECK = ButtonWrapper(
name='LOADING_CHECK',
@ -102,6 +111,7 @@ LOADING_CHECK = ButtonWrapper(
color=(173, 196, 219),
button=(1084, 659, 1120, 674),
),
en=None,
)
MAIL_CHECK = ButtonWrapper(
name='MAIL_CHECK',
@ -112,6 +122,7 @@ MAIL_CHECK = ButtonWrapper(
color=(205, 212, 219),
button=(108, 9, 186, 37),
),
en=None,
)
MAIN_GO_TO_CAFE = ButtonWrapper(
name='MAIN_GO_TO_CAFE',
@ -122,6 +133,7 @@ MAIN_GO_TO_CAFE = ButtonWrapper(
color=(156, 209, 233),
button=(81, 638, 102, 668),
),
en=None,
)
MAIN_GO_TO_CIRCLE = ButtonWrapper(
name='MAIN_GO_TO_CIRCLE',
@ -132,6 +144,7 @@ MAIN_GO_TO_CIRCLE = ButtonWrapper(
color=(131, 204, 234),
button=(540, 631, 583, 660),
),
en=None,
)
MAIN_GO_TO_CRAFTING = ButtonWrapper(
name='MAIN_GO_TO_CRAFTING',
@ -142,6 +155,7 @@ MAIN_GO_TO_CRAFTING = ButtonWrapper(
color=(192, 229, 241),
button=(665, 622, 693, 664),
),
en=None,
)
MAIN_GO_TO_GACHA = ButtonWrapper(
name='MAIN_GO_TO_GACHA',
@ -152,6 +166,7 @@ MAIN_GO_TO_GACHA = ButtonWrapper(
color=(157, 219, 241),
button=(900, 623, 924, 670),
),
en=None,
)
MAIN_GO_TO_MAIL = ButtonWrapper(
name='MAIN_GO_TO_MAIL',
@ -162,6 +177,7 @@ MAIN_GO_TO_MAIL = ButtonWrapper(
color=(94, 121, 166),
button=(1130, 29, 1156, 49),
),
en=None,
)
MAIN_GO_TO_MOMOTALK = ButtonWrapper(
name='MAIN_GO_TO_MOMOTALK',
@ -172,6 +188,7 @@ MAIN_GO_TO_MOMOTALK = ButtonWrapper(
color=(255, 219, 227),
button=(154, 134, 177, 158),
),
en=None,
)
MAIN_GO_TO_PURCHASE = ButtonWrapper(
name='MAIN_GO_TO_PURCHASE',
@ -182,6 +199,7 @@ MAIN_GO_TO_PURCHASE = ButtonWrapper(
color=(172, 214, 239),
button=(148, 204, 183, 253),
),
en=None,
)
MAIN_GO_TO_SCHEDULE = ButtonWrapper(
name='MAIN_GO_TO_SCHEDULE',
@ -192,6 +210,7 @@ MAIN_GO_TO_SCHEDULE = ButtonWrapper(
color=(149, 194, 222),
button=(194, 638, 216, 672),
),
en=None,
)
MAIN_GO_TO_SHOP = ButtonWrapper(
name='MAIN_GO_TO_SHOP',
@ -202,6 +221,7 @@ MAIN_GO_TO_SHOP = ButtonWrapper(
color=(146, 208, 235),
button=(773, 630, 816, 667),
),
en=None,
)
MAIN_GO_TO_TASK = ButtonWrapper(
name='MAIN_GO_TO_TASK',
@ -212,6 +232,7 @@ MAIN_GO_TO_TASK = ButtonWrapper(
color=(226, 207, 203),
button=(52, 220, 78, 248),
),
en=None,
)
MAIN_GO_TO_WORK = ButtonWrapper(
name='MAIN_GO_TO_WORK',
@ -222,6 +243,7 @@ MAIN_GO_TO_WORK = ButtonWrapper(
color=(135, 149, 169),
button=(1167, 605, 1241, 632),
),
en=None,
)
MISSION_CHECK = ButtonWrapper(
name='MISSION_CHECK',
@ -232,6 +254,7 @@ MISSION_CHECK = ButtonWrapper(
color=(188, 197, 206),
button=(108, 12, 183, 36),
),
en=None,
)
MOMOTALK_CHECK = ButtonWrapper(
name='MOMOTALK_CHECK',
@ -242,6 +265,7 @@ MOMOTALK_CHECK = ButtonWrapper(
color=(253, 211, 219),
button=(144, 107, 169, 130),
),
en=None,
)
MOMOTALK_GO_TO_MAIN = ButtonWrapper(
name='MOMOTALK_GO_TO_MAIN',
@ -252,6 +276,7 @@ MOMOTALK_GO_TO_MAIN = ButtonWrapper(
color=(252, 182, 194),
button=(1108, 105, 1134, 131),
),
en=None,
)
SCHEDULE_CHECK = ButtonWrapper(
name='SCHEDULE_CHECK',
@ -262,6 +287,7 @@ SCHEDULE_CHECK = ButtonWrapper(
color=(188, 197, 206),
button=(108, 12, 159, 36),
),
en=None,
)
SCHOOL_EXCHANGE_CHECK = ButtonWrapper(
name='SCHOOL_EXCHANGE_CHECK',
@ -272,6 +298,7 @@ SCHOOL_EXCHANGE_CHECK = ButtonWrapper(
color=(134, 149, 164),
button=(107, 11, 158, 36),
),
en=None,
)
SHOP_CHECK = ButtonWrapper(
name='SHOP_CHECK',
@ -282,6 +309,7 @@ SHOP_CHECK = ButtonWrapper(
color=(200, 208, 215),
button=(108, 10, 212, 36),
),
en=None,
)
STORY_CHECK = ButtonWrapper(
name='STORY_CHECK',
@ -292,6 +320,7 @@ STORY_CHECK = ButtonWrapper(
color=(194, 203, 211),
button=(108, 11, 157, 36),
),
en=None,
)
TACTICAL_CHALLENGE_CHECK = ButtonWrapper(
name='TACTICAL_CHALLENGE_CHECK',
@ -302,6 +331,7 @@ TACTICAL_CHALLENGE_CHECK = ButtonWrapper(
color=(129, 145, 161),
button=(107, 11, 133, 37),
),
en=None,
)
TASK_CHECK = ButtonWrapper(
name='TASK_CHECK',
@ -312,6 +342,7 @@ TASK_CHECK = ButtonWrapper(
color=(189, 198, 207),
button=(109, 12, 155, 36),
),
en=None,
)
WORK_CHECK = ButtonWrapper(
name='WORK_CHECK',
@ -322,6 +353,7 @@ WORK_CHECK = ButtonWrapper(
color=(164, 175, 187),
button=(107, 10, 185, 38),
),
en=None,
)
WORK_GO_TO_BOUNTY = ButtonWrapper(
name='WORK_GO_TO_BOUNTY',
@ -332,6 +364,7 @@ WORK_GO_TO_BOUNTY = ButtonWrapper(
color=(165, 181, 208),
button=(669, 412, 765, 436),
),
en=None,
)
WORK_GO_TO_COMMISSIONS = ButtonWrapper(
name='WORK_GO_TO_COMMISSIONS',
@ -342,6 +375,7 @@ WORK_GO_TO_COMMISSIONS = ButtonWrapper(
color=(165, 179, 204),
button=(655, 494, 751, 518),
),
en=None,
)
WORK_GO_TO_MISSION = ButtonWrapper(
name='WORK_GO_TO_MISSION',
@ -352,6 +386,7 @@ WORK_GO_TO_MISSION = ButtonWrapper(
color=(165, 178, 204),
button=(720, 160, 803, 199),
),
en=None,
)
WORK_GO_TO_SCHOOL_EXCHANGE = ButtonWrapper(
name='WORK_GO_TO_SCHOOL_EXCHANGE',
@ -362,6 +397,7 @@ WORK_GO_TO_SCHOOL_EXCHANGE = ButtonWrapper(
color=(165, 179, 204),
button=(641, 575, 758, 599),
),
en=None,
)
WORK_GO_TO_STORY = ButtonWrapper(
name='WORK_GO_TO_STORY',
@ -372,6 +408,7 @@ WORK_GO_TO_STORY = ButtonWrapper(
color=(191, 201, 219),
button=(995, 163, 1032, 197),
),
en=None,
)
WORK_GO_TO_TACTICAL_CHALLENGE = ButtonWrapper(
name='WORK_GO_TO_TACTICAL_CHALLENGE',
@ -382,4 +419,5 @@ WORK_GO_TO_TACTICAL_CHALLENGE = ButtonWrapper(
color=(159, 174, 200),
button=(1012, 535, 1151, 562),
),
en=None,
)

View File

@ -12,6 +12,7 @@ AFFECTION_LEVEL_UP = ButtonWrapper(
color=(208, 223, 243),
button=(882, 244, 1176, 476),
),
en=None,
)
AP_EXCEED = ButtonWrapper(
name='AP_EXCEED',
@ -22,6 +23,7 @@ AP_EXCEED = ButtonWrapper(
color=(139, 153, 168),
button=(535, 494, 746, 565),
),
en=None,
)
DAILY_NEWS = ButtonWrapper(
name='DAILY_NEWS',
@ -32,6 +34,7 @@ DAILY_NEWS = ButtonWrapper(
color=(150, 204, 253),
button=(1128, 89, 1156, 117),
),
en=None,
)
DAILY_REWARD = ButtonWrapper(
name='DAILY_REWARD',
@ -42,6 +45,7 @@ DAILY_REWARD = ButtonWrapper(
color=(203, 227, 237),
button=(920, 632, 1140, 712),
),
en=None,
)
GET_NEW_STUDENT = ButtonWrapper(
name='GET_NEW_STUDENT',
@ -52,6 +56,7 @@ GET_NEW_STUDENT = ButtonWrapper(
color=(125, 132, 92),
button=(934, 643, 1263, 714),
),
en=None,
)
GET_REWARD = ButtonWrapper(
name='GET_REWARD',
@ -62,6 +67,7 @@ GET_REWARD = ButtonWrapper(
color=(230, 222, 93),
button=(675, 623, 870, 695),
),
en=None,
)
GET_REWARD_SKIP = ButtonWrapper(
name='GET_REWARD_SKIP',
@ -72,6 +78,7 @@ GET_REWARD_SKIP = ButtonWrapper(
color=(197, 200, 205),
button=(1137, 34, 1243, 65),
),
en=None,
)
ITEM_EXPIRED = ButtonWrapper(
name='ITEM_EXPIRED',
@ -82,6 +89,7 @@ ITEM_EXPIRED = ButtonWrapper(
color=(131, 145, 162),
button=(537, 487, 742, 553),
),
en=None,
)
NETWORK_RECONNECT = ButtonWrapper(
name='NETWORK_RECONNECT',
@ -92,6 +100,7 @@ NETWORK_RECONNECT = ButtonWrapper(
color=(78, 138, 169),
button=(663, 467, 870, 537),
),
en=None,
)
NETWORK_RECONNECT_OK = ButtonWrapper(
name='NETWORK_RECONNECT_OK',
@ -102,4 +111,5 @@ NETWORK_RECONNECT_OK = ButtonWrapper(
color=(91, 165, 196),
button=(665, 468, 870, 536),
),
en=None,
)

View File

@ -12,6 +12,7 @@ BOX_CAFE = ButtonWrapper(
color=(175, 181, 186),
button=(33, 130, 1247, 569),
),
en=None,
)
CAFE_FIRST = ButtonWrapper(
name='CAFE_FIRST',
@ -22,6 +23,7 @@ CAFE_FIRST = ButtonWrapper(
color=(111, 127, 147),
button=(82, 152, 136, 175),
),
en=None,
)
CAFE_SECOND = ButtonWrapper(
name='CAFE_SECOND',
@ -32,6 +34,7 @@ CAFE_SECOND = ButtonWrapper(
color=(110, 126, 146),
button=(219, 152, 279, 175),
),
en=None,
)
CHANGE_CAFE_NOT_SELECTED = ButtonWrapper(
name='CHANGE_CAFE_NOT_SELECTED',
@ -42,6 +45,7 @@ CHANGE_CAFE_NOT_SELECTED = ButtonWrapper(
color=(185, 193, 203),
button=(84, 89, 178, 109),
),
en=None,
)
CHANGE_CAFE_SELECTED = ButtonWrapper(
name='CHANGE_CAFE_SELECTED',
@ -52,6 +56,7 @@ CHANGE_CAFE_SELECTED = ButtonWrapper(
color=(82, 105, 130),
button=(40, 87, 191, 112),
),
en=None,
)
CHECK_REWARD = ButtonWrapper(
name='CHECK_REWARD',
@ -62,6 +67,7 @@ CHECK_REWARD = ButtonWrapper(
color=(82, 105, 129),
button=(1086, 607, 1225, 685),
),
en=None,
)
CLICKABLE_TEMPLATE = ButtonWrapper(
name='CLICKABLE_TEMPLATE',
@ -72,6 +78,7 @@ CLICKABLE_TEMPLATE = ButtonWrapper(
color=(79, 65, 1),
button=(619, 332, 660, 387),
),
en=None,
)
GET_REWARD = ButtonWrapper(
name='GET_REWARD',
@ -82,6 +89,7 @@ GET_REWARD = ButtonWrapper(
color=(159, 133, 48),
button=(546, 494, 735, 563),
),
en=None,
)
GET_REWARD_CLOSE = ButtonWrapper(
name='GET_REWARD_CLOSE',
@ -92,6 +100,7 @@ GET_REWARD_CLOSE = ButtonWrapper(
color=(172, 179, 188),
button=(970, 134, 996, 160),
),
en=None,
)
GOT_REWARD = ButtonWrapper(
name='GOT_REWARD',
@ -102,6 +111,7 @@ GOT_REWARD = ButtonWrapper(
color=(209, 210, 209),
button=(561, 501, 718, 556),
),
en=None,
)
INVENTORY = ButtonWrapper(
name='INVENTORY',
@ -112,6 +122,7 @@ INVENTORY = ButtonWrapper(
color=(198, 205, 213),
button=(1130, 94, 1156, 120),
),
en=None,
)
MOMOTALK_CLOSE = ButtonWrapper(
name='MOMOTALK_CLOSE',
@ -122,6 +133,7 @@ MOMOTALK_CLOSE = ButtonWrapper(
color=(252, 182, 194),
button=(824, 82, 850, 108),
),
en=None,
)
OCR_CAFE = ButtonWrapper(
name='OCR_CAFE',
@ -132,6 +144,7 @@ OCR_CAFE = ButtonWrapper(
color=(87, 107, 129),
button=(1103, 642, 1202, 672),
),
en=None,
)
STUDENT_LIST = ButtonWrapper(
name='STUDENT_LIST',
@ -142,4 +155,5 @@ STUDENT_LIST = ButtonWrapper(
color=(145, 157, 172),
button=(545, 423, 738, 495),
),
en=None,
)

View File

@ -5,6 +5,7 @@ from enum import Enum
from module.logger import logger
from module.base.timer import Timer
from module.base.button import ClickButton
from module.base.decorator import Config
from module.base.utils.utils import area_offset
from module.ocr.ocr import Digit
from module.ui.switch import Switch
@ -33,6 +34,8 @@ class CafeStatus(Enum):
class Cafe(UI):
template = CLICKABLE_TEMPLATE
@staticmethod
def merge_points(points, threshold=3):
if len(points) <= 1:
@ -63,7 +66,7 @@ class Cafe(UI):
def _match_clickable_points(self, image, threshold=0.8):
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
template = cv2.cvtColor(self.btn.matched_button.image, cv2.COLOR_BGR2GRAY)
template = cv2.cvtColor(self.template.matched_button.image, cv2.COLOR_BGR2GRAY)
res = cv2.matchTemplate(image, template, cv2.TM_CCOEFF_NORMED)
loc = np.where(res >= threshold)
@ -78,11 +81,11 @@ class Cafe(UI):
points = self.merge_points(points)
if not points:
return []
area = area_offset((0, 0, self.btn.width, self.btn.height), offset)
area = area_offset((0, 0, self.template.width, self.template.height), offset)
return [
ClickButton(
button=area_offset(area, offset=point),
name=self.btn.name
name=self.template.name
)
for point in points
]
@ -188,15 +191,23 @@ class Cafe(UI):
logger.warning(f'Invalid status: {status}')
return status
@Config.when(Emulator_GameLanguage='jp')
def is_second_cafe_on(self):
return self.config.Cafe_SecondCafe
@Config.when(Emulator_GameLanguage=None)
def is_second_cafe_on(self):
return False
is_second_cafe_on = property(is_second_cafe_on)
def run(self):
self.btn = CLICKABLE_TEMPLATE
self.click = 0
self.check = 0
is_reward_on = self.config.Cafe_Reward
is_touch_on = self.config.Cafe_Touch
self.is_adjust_on = self.config.Cafe_AutoAdjust
is_second_cafe_on = self.config.Cafe_SecondCafe
self.ui_ensure(page_cafe)
@ -240,7 +251,7 @@ class Cafe(UI):
is_reset = True
continue
if is_second_cafe_on and not is_second and status == CafeStatus.FINISHED:
if self.is_second_cafe_on and not is_second and status == CafeStatus.FINISHED:
if not SWITCH_CAFE.appear(main=self):
logger.warning('Cafe switch not found')
continue
@ -266,11 +277,14 @@ class Cafe(UI):
logger.attr('Status', status)
status = self._handle_cafe(status)
if not is_second_cafe_on:
if not self.is_second_cafe_on:
if status is CafeStatus.FINISHED:
logger.info('Second cafe is not supported or disabled')
logger.info('Cafe finished')
break
else:
if is_second and status is CafeStatus.FINISHED:
logger.info('Cafe finished')
break
self.config.task_delay(server_update=True, minute=180)

View File

@ -12,4 +12,5 @@ GET_REWARD_AP = ButtonWrapper(
color=(198, 206, 213),
button=(543, 457, 735, 524),
),
en=None,
)

View File

@ -12,6 +12,7 @@ LOGIN_CONFIRM = ButtonWrapper(
color=(211, 215, 220),
button=(990, 354, 1232, 506),
),
en=None,
)
LOGIN_LOADING = ButtonWrapper(
name='LOGIN_LOADING',
@ -22,6 +23,7 @@ LOGIN_LOADING = ButtonWrapper(
color=(8, 66, 96),
button=(34, 682, 60, 707),
),
en=None,
)
UPDATE = ButtonWrapper(
name='UPDATE',
@ -32,4 +34,5 @@ UPDATE = ButtonWrapper(
color=(183, 192, 201),
button=(666, 527, 872, 595),
),
en=None,
)

View File

@ -12,6 +12,7 @@ MAIL_RECEIVE = ButtonWrapper(
color=(174, 151, 53),
button=(1043, 640, 1226, 701),
),
en=None,
)
MAIL_RECEIVED = ButtonWrapper(
name='MAIL_RECEIVED',
@ -22,4 +23,5 @@ MAIL_RECEIVED = ButtonWrapper(
color=(195, 196, 196),
button=(1085, 657, 1186, 685),
),
en=None,
)

View File

@ -12,4 +12,5 @@ SCROLL = ButtonWrapper(
color=(198, 214, 210),
button=(742, 136, 1101, 671),
),
en=None,
)

View File

@ -0,0 +1,148 @@
from module.base.button import Button, ButtonWrapper
# This file was auto-generated, do not modify it manually. To generate:
# ``` python -m dev_tools.button_extract ```
CHECK_SWEEP = ButtonWrapper(
name='CHECK_SWEEP',
jp=Button(
file='./assets/jp/stage/sweep/CHECK_SWEEP.png',
area=(638, 188, 722, 212),
search=(618, 168, 742, 232),
color=(174, 184, 197),
button=(638, 188, 722, 212),
),
en=None,
)
ENTER = ButtonWrapper(
name='ENTER',
jp=Button(
file='./assets/jp/stage/sweep/ENTER.png',
area=(791, 514, 1080, 568),
search=(771, 494, 1100, 588),
color=(223, 207, 68),
button=(791, 514, 1080, 568),
),
en=None,
)
EXIT = ButtonWrapper(
name='EXIT',
jp=Button(
file='./assets/jp/stage/sweep/EXIT.png',
area=(1114, 127, 1141, 154),
search=(1094, 107, 1161, 174),
color=(185, 193, 203),
button=(1114, 127, 1141, 154),
),
en=None,
)
MAX = ButtonWrapper(
name='MAX',
jp=Button(
file='./assets/jp/stage/sweep/MAX.png',
area=(1054, 279, 1111, 321),
search=(1034, 259, 1131, 341),
color=(216, 222, 228),
button=(1054, 279, 1111, 321),
),
en=None,
)
MIN = ButtonWrapper(
name='MIN',
jp=Button(
file='./assets/jp/stage/sweep/MIN.png',
area=(760, 278, 816, 322),
search=(740, 258, 836, 342),
color=(194, 194, 194),
button=(760, 278, 816, 322),
),
en=None,
)
MINUS = ButtonWrapper(
name='MINUS',
jp=Button(
file='./assets/jp/stage/sweep/MINUS.png',
area=(838, 279, 876, 320),
search=(818, 259, 896, 340),
color=(221, 222, 222),
button=(838, 279, 876, 320),
),
en=None,
)
OCR_NUM = ButtonWrapper(
name='OCR_NUM',
jp=Button(
file='./assets/jp/stage/sweep/OCR_NUM.png',
area=(896, 281, 975, 323),
search=(876, 261, 995, 343),
color=(81, 94, 113),
button=(896, 281, 975, 323),
),
en=None,
)
PLUS = ButtonWrapper(
name='PLUS',
jp=Button(
file='./assets/jp/stage/sweep/PLUS.png',
area=(995, 278, 1034, 322),
search=(975, 258, 1054, 342),
color=(233, 243, 246),
button=(995, 278, 1034, 322),
),
en=None,
)
SKIP_OK_LOWER = ButtonWrapper(
name='SKIP_OK_LOWER',
jp=Button(
file='./assets/jp/stage/sweep/SKIP_OK_LOWER.png',
area=(541, 551, 740, 616),
search=(521, 531, 760, 636),
color=(112, 212, 247),
button=(541, 551, 740, 616),
),
en=None,
)
SKIP_OK_UPPER = ButtonWrapper(
name='SKIP_OK_UPPER',
jp=Button(
file='./assets/jp/stage/sweep/SKIP_OK_UPPER.png',
area=(542, 474, 738, 545),
search=(522, 454, 758, 565),
color=(112, 212, 248),
button=(542, 474, 738, 545),
),
en=None,
)
SKIP_SKIP = ButtonWrapper(
name='SKIP_SKIP',
jp=Button(
file='./assets/jp/stage/sweep/SKIP_SKIP.png',
area=(545, 475, 736, 540),
search=(525, 455, 756, 560),
color=(110, 207, 243),
button=(545, 475, 736, 540),
),
en=None,
)
SWEEP = ButtonWrapper(
name='SWEEP',
jp=Button(
file='./assets/jp/stage/sweep/SWEEP.png',
area=(796, 385, 1067, 427),
search=(776, 365, 1087, 447),
color=(109, 202, 235),
button=(796, 385, 1067, 427),
),
en=None,
)
SWEEP_CONFIRM = ButtonWrapper(
name='SWEEP_CONFIRM',
jp=Button(
file='./assets/jp/stage/sweep/SWEEP_CONFIRM.png',
area=(611, 147, 669, 177),
search=(591, 127, 689, 197),
color=(143, 156, 170),
button=(664, 470, 871, 534),
),
en=None,
)

View File

@ -43,7 +43,8 @@ class StageList:
def __hash__(self):
return hash(self.name)
def _get_indexes(self) -> list[int]:
@property
def _indexes(self) -> list[int]:
return list(map(lambda x: int(x.ocr_text), self.current_indexes))
def load_stage_indexes(self, main: ModuleBase):
@ -53,7 +54,7 @@ class StageList:
if not self.current_indexes:
logger.warning(f'No valid index in {self.index_ocr.name}')
return
indexes = self._get_indexes()
indexes = self._indexes
self.current_index_min = min(indexes)
self.current_index_max = max(indexes)
@ -119,7 +120,7 @@ class StageList:
timeout=Timer(1.5, 5)
)
indexes = self._get_indexes()
indexes = self._indexes
if indexes and last_indexes == set(indexes):
logger.warning(f'No more index {index}')
return False

254
tasks/stage/sweep.py Normal file
View File

@ -0,0 +1,254 @@
from module.base.base import ModuleBase
from module.base.timer import Timer
from module.logger import logger
from module.ocr.ocr import Digit
from enum import Enum
from tasks.stage.assets.assets_stage_sweep import *
class SweepStatus(Enum):
SELECT = 1
START = 2
CONFIRM = 3
SKIP = 4
END = 5
FINISH = 6
class StageSweep:
def __init__(
self,
name: str,
sweep_num: int,
max_sweep: int,
):
self.name = name
self.sweep_num = sweep_num
self.check: ButtonWrapper = None
self.num: Digit = None
self.plus: ButtonWrapper = None
self.minus: ButtonWrapper = None
self.max: ButtonWrapper = None
self.min: ButtonWrapper = None
self.sweep: ButtonWrapper = None
self.sweep_confirm: ButtonWrapper = None
self.enter: ButtonWrapper = None
self.exit: ButtonWrapper = None
self.skip_skip: ButtonWrapper = None
self.skip_ok_upper: ButtonWrapper = None
self.skip_ok_lower: ButtonWrapper = None
self.set_button()
self.min_sweep = 1
self.max_sweep = max_sweep
self.current_sweep = 0
self.sweep_method = None
self.set_mode()
def __str__(self):
return f'StageSweep({self.name})'
__repr__ = __str__
def __eq__(self, other):
return str(self) == str(other)
def __hash__(self):
return hash(self.name)
def set_button(
self,
button_check: ButtonWrapper = None,
button_num: ButtonWrapper = None,
button_plus: ButtonWrapper = None,
button_minus: ButtonWrapper = None,
button_max: ButtonWrapper = None,
button_min: ButtonWrapper = None,
button_sweep: ButtonWrapper = None,
button_sweep_confirm: ButtonWrapper = None,
button_enter: ButtonWrapper = None,
button_exit: ButtonWrapper = None,
button_skip_skip: ButtonWrapper = None,
button_skip_ok_upper: ButtonWrapper = None,
button_skip_ok_lower: ButtonWrapper = None,
):
self.check = button_check if button_check else CHECK_SWEEP
self.num = Digit(button_num if button_num else OCR_NUM)
self.plus = button_plus if button_plus else PLUS
self.minus = button_minus if button_minus else MINUS
self.max = button_max if button_max else MAX
self.min = button_min if button_min else MIN
self.sweep = button_sweep if button_sweep else SWEEP
self.sweep_confirm = button_sweep_confirm if button_sweep_confirm else SWEEP_CONFIRM
self.enter = button_enter if button_enter else ENTER
self.exit = button_exit if button_exit else EXIT
self.skip_skip = button_skip_skip if button_skip_skip else SKIP_SKIP
self.skip_ok_upper = button_skip_ok_upper if button_skip_ok_upper else SKIP_OK_UPPER
self.skip_ok_lower = button_skip_ok_lower if button_skip_ok_lower else SKIP_OK_LOWER
def set_mode(self, mode: str = None):
if mode is None:
match self.sweep_num:
case 0:
self.sweep_method = self.set_sweep_min
case -1:
self.sweep_method = self.set_sweep_max
case x if x > 0:
self.sweep_method = self.set_sweep_num
case _:
logger.warning(f'Invalid sweep num: {self.sweep_num}')
return
match mode:
case 'max':
self.sweep_method = self.set_sweep_max
case 'min':
self.sweep_method = self.set_sweep_min
case _:
logger.warning(f'Invalid sweep mode: {mode}')
def check_sweep(self, main: ModuleBase):
return main.appear(self.check)
def check_skip(self, main: ModuleBase):
return main.appear(self.skip_skip) or main.appear(self.skip_ok_upper) or main.appear(self.skip_ok_lower)
def load_sweep_num(self, main: ModuleBase):
while 1:
main.device.screenshot()
ocr_result = self.num.detect_and_ocr(main.device.image)
if not ocr_result:
logger.warning(f'No valid num in {self.num.name}')
continue
if len(ocr_result) == 1:
self.current_sweep = int(ocr_result[0].ocr_text)
return
def set_sweep_num(self, main: ModuleBase, skip_first_screenshot=True) -> bool:
num = self.sweep_num
if num < self.min_sweep or num > self.max_sweep:
logger.warning(f'Invalid sweep num: {num}')
return False
logger.info(f'Set sweep num: {num}')
retry = Timer(1, 2)
while 1:
if skip_first_screenshot:
skip_first_screenshot = False
else:
main.device.screenshot()
self.load_sweep_num(main)
if self.current_sweep == num:
logger.info(f'Sweep num reaches {num}')
return True
elif self.current_sweep == 0:
logger.info(f'Current sweep num is 0')
return False
if retry.reached_and_reset():
diff = num - self.current_sweep
button = self.plus if diff > 0 else self.minus
main.device.multi_click(button, abs(diff), interval=(0.2, 0.3))
def set_sweep_max(self, main: ModuleBase, skip_first_screenshot=True):
logger.info(f'Set sweep max: {self.max_sweep}')
retry = Timer(1, 2)
count = 0
while 1:
if skip_first_screenshot:
skip_first_screenshot = False
else:
main.device.screenshot()
self.load_sweep_num(main)
if self.current_sweep == self.max_sweep:
logger.info(f'Sweep max reaches {self.max_sweep}')
return True
elif count == 1 and self.current_sweep != 1:
logger.info("Set sweep max")
return True
elif self.current_sweep == 0:
logger.info(f'Current sweep num is 0')
return False
if retry.reached_and_reset():
main.click_with_interval(self.max, interval=0)
count += 1
continue
if count > 2:
logger.info("Set sweep max")
return True
def set_sweep_min(self, main: ModuleBase, skip_first_screenshot=True):
logger.info(f'Set sweep min: {self.min_sweep}')
retry = Timer(1, 2)
while 1:
if skip_first_screenshot:
skip_first_screenshot = False
else:
main.device.screenshot()
self.load_sweep_num(main)
if self.current_sweep == self.min_sweep:
logger.info(f'Sweep min reaches {self.min_sweep}')
return True
elif self.current_sweep == 0:
logger.info(f'Current sweep num is 0')
return False
if retry.reached_and_reset():
main.click_with_interval(self.min, interval=0)
def do_sweep(self, main: ModuleBase, skip_first_screenshot=True) -> bool:
timer = Timer(0.5, 1)
timer_stable = Timer(0.5, 1).start()
status = SweepStatus.SELECT
while 1:
if not timer_stable.reached():
continue
if skip_first_screenshot:
skip_first_screenshot = False
else:
main.device.screenshot()
if timer.reached_and_reset():
logger.attr("Status", status)
match status:
case SweepStatus.SELECT:
if self.sweep_method(main, skip_first_screenshot):
status = SweepStatus.START
else:
return False
case SweepStatus.START:
main.appear_then_click(self.sweep, interval=1)
if main.appear(self.sweep_confirm):
status = SweepStatus.CONFIRM
case SweepStatus.CONFIRM:
main.appear_then_click(self.sweep_confirm, interval=1)
if self.check_skip(main):
status = SweepStatus.SKIP
case SweepStatus.SKIP:
main.appear_then_click(self.skip_skip)
main.appear_then_click(self.skip_ok_upper)
main.appear_then_click(self.skip_ok_lower)
if self.check_sweep(main):
status = SweepStatus.END
case SweepStatus.END:
main.appear_then_click(self.exit, interval=1)
if not main.appear(self.check):
status = SweepStatus.FINISH
case SweepStatus.FINISH:
pass
case _:
logger.warning(f'Invalid status: {status}')
return False
if status == SweepStatus.FINISH:
logger.info(f'Sweep finish')
return True

View File

@ -12,6 +12,7 @@ CHALLENGE_LOSE = ButtonWrapper(
color=(146, 158, 173),
button=(548, 431, 738, 499),
),
en=None,
)
CHALLENGE_WIN = ButtonWrapper(
name='CHALLENGE_WIN',
@ -22,6 +23,7 @@ CHALLENGE_WIN = ButtonWrapper(
color=(151, 165, 180),
button=(549, 495, 737, 563),
),
en=None,
)
GET_REWARD_CREDIT = ButtonWrapper(
name='GET_REWARD_CREDIT',
@ -32,6 +34,7 @@ GET_REWARD_CREDIT = ButtonWrapper(
color=(215, 193, 61),
button=(308, 360, 397, 415),
),
en=None,
)
GET_REWARD_DAILY = ButtonWrapper(
name='GET_REWARD_DAILY',
@ -42,6 +45,7 @@ GET_REWARD_DAILY = ButtonWrapper(
color=(214, 192, 60),
button=(307, 440, 395, 493),
),
en=None,
)
GOT_REWARD_CREDIT = ButtonWrapper(
name='GOT_REWARD_CREDIT',
@ -52,6 +56,7 @@ GOT_REWARD_CREDIT = ButtonWrapper(
color=(203, 205, 204),
button=(308, 358, 398, 416),
),
en=None,
)
GOT_REWARD_DAILY = ButtonWrapper(
name='GOT_REWARD_DAILY',
@ -62,6 +67,7 @@ GOT_REWARD_DAILY = ButtonWrapper(
color=(203, 203, 204),
button=(307, 439, 397, 494),
),
en=None,
)
OCR_TICKET = ButtonWrapper(
name='OCR_TICKET',
@ -72,6 +78,7 @@ OCR_TICKET = ButtonWrapper(
color=(200, 202, 204),
button=(206, 479, 240, 499),
),
en=None,
)
PLAYER_SELECT_FIRST = ButtonWrapper(
name='PLAYER_SELECT_FIRST',
@ -82,6 +89,7 @@ PLAYER_SELECT_FIRST = ButtonWrapper(
color=(191, 202, 207),
button=(558, 179, 1118, 282),
),
en=None,
)
PLAYER_SELECT_SECOND = ButtonWrapper(
name='PLAYER_SELECT_SECOND',
@ -92,6 +100,7 @@ PLAYER_SELECT_SECOND = ButtonWrapper(
color=(192, 203, 208),
button=(554, 336, 1127, 443),
),
en=None,
)
PLAYER_SELECT_THIRD = ButtonWrapper(
name='PLAYER_SELECT_THIRD',
@ -102,6 +111,7 @@ PLAYER_SELECT_THIRD = ButtonWrapper(
color=(194, 206, 211),
button=(557, 495, 1120, 599),
),
en=None,
)
PREPARE_CHALLENGE = ButtonWrapper(
name='PREPARE_CHALLENGE',
@ -112,6 +122,7 @@ PREPARE_CHALLENGE = ButtonWrapper(
color=(148, 161, 175),
button=(561, 548, 723, 598),
),
en=None,
)
SKIP_OFF = ButtonWrapper(
name='SKIP_OFF',
@ -122,6 +133,7 @@ SKIP_OFF = ButtonWrapper(
color=(96, 137, 171),
button=(1088, 582, 1250, 626),
),
en=None,
)
SKIP_ON = ButtonWrapper(
name='SKIP_ON',
@ -132,6 +144,7 @@ SKIP_ON = ButtonWrapper(
color=(99, 177, 212),
button=(1089, 581, 1250, 626),
),
en=None,
)
START_CHALLENGE = ButtonWrapper(
name='START_CHALLENGE',
@ -142,4 +155,5 @@ START_CHALLENGE = ButtonWrapper(
color=(148, 161, 176),
button=(1091, 635, 1246, 704),
),
en=None,
)