Compare commits
34 Commits
v0.1.1
...
447b32e487
| Author | SHA1 | Date | |
|---|---|---|---|
|
447b32e487
|
|||
|
12ede66b04
|
|||
|
95942dd64d
|
|||
|
51b14b57e6
|
|||
|
7c76fc90b5
|
|||
|
227610fdf3
|
|||
|
a8fea1bac3
|
|||
|
4f3908bc9d
|
|||
|
7b2c3bb165
|
|||
|
2f4d64e5d0
|
|||
| 9e5fd34b79 | |||
| 5487338dc6 | |||
| e5a914e80f | |||
| f21a97e08d | |||
| b4c47e2de2 | |||
| 34208763aa | |||
|
c3354cf4f5
|
|||
|
81abba0270
|
|||
|
acea188931
|
|||
|
b0621b48e6
|
|||
|
1b83b7077f
|
|||
|
f1e3cd9810
|
|||
|
f91fc2c55d
|
|||
|
d82e206463
|
|||
|
db813c9efb
|
|||
|
9d3b5ceff8
|
|||
|
b83db6bc35
|
|||
|
2e4a1f144b
|
|||
|
f7444e29dc
|
|||
|
1113094cf5
|
|||
|
60e6710181
|
|||
|
9708ec05d7
|
|||
|
77f0ded95f
|
|||
|
937a7c63e8
|
@@ -0,0 +1,40 @@
|
||||
<img width="150" height="150" align="left" style="float: left; margin: 0 10px 0 0;" alt="AAS icon" src="docs/resources/aas_icon.svg"/>
|
||||
|
||||
# ArisuAutoSweeper
|
||||
|
||||
**Blue Archive Automation Script**
|
||||
|
||||
**| English | [简体中文](README.md) |**
|
||||
|
||||

|
||||
|
||||
## Features
|
||||
|
||||
The script is still under active development. The following features have been implemented:
|
||||
|
||||
- [x] **Cafe** Claim rewards / Interact / Second floor
|
||||
- [x] **Club** Claim AP
|
||||
- [x] **Mailbox** Claim rewards
|
||||
- [x] **Tactical Challenge** Claim rewards / Auto battle
|
||||
|
||||
_Currently only supports JP server._
|
||||
|
||||
## Relative projects
|
||||
|
||||
- [AzurLaneAutoScript](https://github.com/LmeSzinc/AzurLaneAutoScript): Azur Lane auto script
|
||||
- [StarRailCopilot](https://github.com/LmeSzinc/StarRailCopilot): A bot for Honkai: Star Rail, based on the next
|
||||
generation of ALAS framework
|
||||
|
||||
Some Blue Archive auto scripts:
|
||||
|
||||
- [BAAuto](https://github.com/RedDeadDepresso/BAAuto): Blue Archive Automation Script
|
||||
- [BlueArchiveAutoScript](https://github.com/pur1fying/blue_archive_auto_script): BAAS, used to implement Blue Archive
|
||||
automation
|
||||
- [MBA](https://github.com/MaaAssistantArknights/MBA): BA assistant based on the new architecture of MAA
|
||||
|
||||
## Acknowledgements
|
||||
|
||||
Thanks to [6bir](https://github.com/6bir) for the icon design.
|
||||
|
||||
Thanks to [Alas](https://github.com/LmeSzinc/AzurLaneAutoScript) and [SRC](https://github.com/LmeSzinc/StarRailCopilot)
|
||||
for the development framework.
|
||||
@@ -0,0 +1,38 @@
|
||||
<img width="150" height="150" align="left" style="float: left; margin: 0 10px 0 0;" alt="AAS icon" src="docs/resources/aas_icon.svg"/>
|
||||
|
||||
# ArisuAutoSweeper
|
||||
|
||||
**蔚蓝档案自动化脚本**
|
||||
|
||||
**| [English](README.en.md) | 简体中文 |**
|
||||
|
||||

|
||||
|
||||
## 功能
|
||||
|
||||
当前脚本还在活跃开发中,已经实现的功能有:
|
||||
|
||||
- [x] **咖啡厅** 领取奖励 / 互动 / 第二咖啡厅
|
||||
- [x] **公会** 领取体力
|
||||
- [x] **邮箱** 领取奖励
|
||||
- [x] **战术对抗赛** 领取奖励 / 自动战斗
|
||||
|
||||
_目前仅支持日服。_
|
||||
|
||||
## 相关项目
|
||||
|
||||
- [AzurLaneAutoScript](https://github.com/LmeSzinc/AzurLaneAutoScript): 碧蓝航线自动化脚本
|
||||
- [StarRailCopilot](https://github.com/LmeSzinc/StarRailCopilot): 崩坏:星穹铁道脚本,基于下一代Alas框架
|
||||
|
||||
一些蔚蓝档案脚本:
|
||||
|
||||
- [BAAuto](https://github.com/RedDeadDepresso/BAAuto): 蔚蓝档案自动脚本
|
||||
- [BlueArchiveAutoScript](https://github.com/pur1fying/blue_archive_auto_script): BAAS,用于实现蔚蓝档案自动化
|
||||
- [MBA](https://github.com/MaaAssistantArknights/MBA): 基于 MAA 全新架构的 BA 小助手
|
||||
|
||||
## 鸣谢
|
||||
|
||||
感谢 [6bir](https://github.com/6bir) 为本项目设计的图标。
|
||||
|
||||
感谢 [Alas](https://github.com/LmeSzinc/AzurLaneAutoScript) 以及 [SRC](https://github.com/LmeSzinc/StarRailCopilot)
|
||||
提供的开发框架。
|
||||
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 6.6 KiB |
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 5.4 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 6.2 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 5.7 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 3.9 KiB |
|
After Width: | Height: | Size: 5.4 KiB |
|
After Width: | Height: | Size: 7.6 KiB |
|
After Width: | Height: | Size: 5.2 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 9.5 KiB |
|
After Width: | Height: | Size: 8.0 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 5.5 KiB |
|
After Width: | Height: | Size: 6.0 KiB |
|
After Width: | Height: | Size: 5.2 KiB |
|
After Width: | Height: | Size: 4.4 KiB |
|
After Width: | Height: | Size: 4.5 KiB |
|
After Width: | Height: | Size: 4.6 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 6.3 KiB |
@@ -1,8 +1,8 @@
|
||||
Deploy:
|
||||
Git:
|
||||
# URL of AzurLaneAutoScript repository
|
||||
# [CN user] Use 'cn' to get update from git-over-cdn service
|
||||
# [Other] Use 'global' to get update from https://github.com/TheFunny/ArisuAutoSrcipt
|
||||
# [CN user] Use 'cn' to get update from self-hosted git service
|
||||
# [Other] Use 'global' to get update from https://github.com/TheFunny/ArisuAutoSweeper
|
||||
Repository: cn
|
||||
# Branch of Alas
|
||||
# [Developer] Use 'dev', 'app', etc, to try new features
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
Deploy:
|
||||
Git:
|
||||
# URL of AzurLaneAutoScript repository
|
||||
# [CN user] Use 'cn' to get update from git-over-cdn service
|
||||
# [Other] Use 'global' to get update from https://github.com/TheFunny/ArisuAutoSrcipt
|
||||
# [CN user] Use 'cn' to get update from self-hosted git service
|
||||
# [Other] Use 'global' to get update from https://github.com/TheFunny/ArisuAutoSweeper
|
||||
Repository: global
|
||||
# Branch of Alas
|
||||
# [Developer] Use 'dev', 'app', etc, to try new features
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
Deploy:
|
||||
Git:
|
||||
# URL of AzurLaneAutoScript repository
|
||||
# [CN user] Use 'cn' to get update from git-over-cdn service
|
||||
# [Other] Use 'global' to get update from https://github.com/TheFunny/ArisuAutoSrcipt
|
||||
# [CN user] Use 'cn' to get update from self-hosted git service
|
||||
# [Other] Use 'global' to get update from https://github.com/TheFunny/ArisuAutoSweeper
|
||||
Repository: 'global'
|
||||
# Branch of Alas
|
||||
# [Developer] Use 'dev', 'app', etc, to try new features
|
||||
|
||||
|
After Width: | Height: | Size: 36 KiB |
|
After Width: | Height: | Size: 199 KiB |
|
After Width: | Height: | Size: 215 KiB |
@@ -11,7 +11,8 @@
|
||||
"value": "auto",
|
||||
"option": [
|
||||
"auto",
|
||||
"JP-Official"
|
||||
"JP-Official",
|
||||
"OVERSEA-Global"
|
||||
]
|
||||
},
|
||||
"GameLanguage": {
|
||||
@@ -19,7 +20,8 @@
|
||||
"value": "auto",
|
||||
"option": [
|
||||
"auto",
|
||||
"jp"
|
||||
"jp",
|
||||
"en"
|
||||
]
|
||||
},
|
||||
"ScreenshotMethod": {
|
||||
|
||||
@@ -23,7 +23,7 @@ Emulator:
|
||||
option: [ auto, ]
|
||||
GameLanguage:
|
||||
value: auto
|
||||
option: [ auto, jp ]
|
||||
option: [ auto, jp, en ]
|
||||
ScreenshotMethod:
|
||||
value: auto
|
||||
option: [ auto, ADB, ADB_nc, uiautomator2, aScreenCap, aScreenCap_nc, DroidCast, DroidCast_raw, scrcpy ]
|
||||
|
||||
@@ -17,8 +17,8 @@ class GeneratedConfig:
|
||||
|
||||
# Group `Emulator`
|
||||
Emulator_Serial = 'auto'
|
||||
Emulator_PackageName = 'auto' # auto, JP-Official
|
||||
Emulator_GameLanguage = 'auto' # auto, jp
|
||||
Emulator_PackageName = 'auto' # auto, JP-Official, OVERSEA-Global
|
||||
Emulator_GameLanguage = 'auto' # auto, jp, en
|
||||
Emulator_ScreenshotMethod = 'auto' # auto, ADB, ADB_nc, uiautomator2, aScreenCap, aScreenCap_nc, DroidCast, DroidCast_raw, scrcpy
|
||||
Emulator_ControlMethod = 'MaaTouch' # minitouch, MaaTouch
|
||||
Emulator_AdbRestart = False
|
||||
|
||||
@@ -1,93 +1,95 @@
|
||||
{
|
||||
"Menu": {
|
||||
"Alas": {
|
||||
"name": "Menu.Alas.name",
|
||||
"help": "Menu.Alas.help"
|
||||
"name": "AAS",
|
||||
"help": ""
|
||||
},
|
||||
"Daily": {
|
||||
"name": "Menu.Daily.name",
|
||||
"help": "Menu.Daily.help"
|
||||
"name": "Daily",
|
||||
"help": ""
|
||||
}
|
||||
},
|
||||
"Task": {
|
||||
"Alas": {
|
||||
"name": "Task.Alas.name",
|
||||
"help": "Task.Alas.help"
|
||||
"name": "AAS Settings",
|
||||
"help": ""
|
||||
},
|
||||
"Restart": {
|
||||
"name": "Task.Restart.name",
|
||||
"help": "Task.Restart.help"
|
||||
"name": "Error Handling",
|
||||
"help": ""
|
||||
},
|
||||
"Cafe": {
|
||||
"name": "Task.Cafe.name",
|
||||
"help": "Task.Cafe.help"
|
||||
"name": "Cafe",
|
||||
"help": ""
|
||||
},
|
||||
"Mail": {
|
||||
"name": "Task.Mail.name",
|
||||
"help": "Task.Mail.help"
|
||||
"name": "Mailbox",
|
||||
"help": ""
|
||||
},
|
||||
"Circle": {
|
||||
"name": "Task.Circle.name",
|
||||
"help": "Task.Circle.help"
|
||||
"name": "Club",
|
||||
"help": ""
|
||||
},
|
||||
"TacticalChallenge": {
|
||||
"name": "Task.TacticalChallenge.name",
|
||||
"help": "Task.TacticalChallenge.help"
|
||||
"name": "Tactical Challenge",
|
||||
"help": ""
|
||||
},
|
||||
"DataUpdate": {
|
||||
"name": "Task.DataUpdate.name",
|
||||
"help": "Task.DataUpdate.help"
|
||||
"name": "Dashboard Upd",
|
||||
"help": ""
|
||||
}
|
||||
},
|
||||
"Scheduler": {
|
||||
"_info": {
|
||||
"name": "Scheduler._info.name",
|
||||
"help": "Scheduler._info.help"
|
||||
"name": "Scheduler",
|
||||
"help": ""
|
||||
},
|
||||
"Enable": {
|
||||
"name": "Scheduler.Enable.name",
|
||||
"help": "Scheduler.Enable.help",
|
||||
"True": "True",
|
||||
"name": "Enable Task",
|
||||
"help": "Join this task to scheduler.",
|
||||
"True": "Enabled",
|
||||
"False": "False"
|
||||
},
|
||||
"NextRun": {
|
||||
"name": "Scheduler.NextRun.name",
|
||||
"help": "Scheduler.NextRun.help"
|
||||
"name": "Next Run",
|
||||
"help": "Updated automatically after completing the task to set next scheduled run, typically not manually modified\nHowever you can force immediate scheduling if you clear this text field"
|
||||
},
|
||||
"Command": {
|
||||
"name": "Scheduler.Command.name",
|
||||
"help": "Scheduler.Command.help"
|
||||
"name": "Command",
|
||||
"help": ""
|
||||
},
|
||||
"ServerUpdate": {
|
||||
"name": "Scheduler.ServerUpdate.name",
|
||||
"help": "Scheduler.ServerUpdate.help"
|
||||
"name": "Server Update",
|
||||
"help": "Series of server refresh time(s) as to when this task will next run, this is automatically converted to respective time zone, generally do not need to modify"
|
||||
}
|
||||
},
|
||||
"Emulator": {
|
||||
"_info": {
|
||||
"name": "Emulator._info.name",
|
||||
"help": "Emulator._info.help"
|
||||
"name": "Emulator Settings",
|
||||
"help": ""
|
||||
},
|
||||
"Serial": {
|
||||
"name": "Emulator.Serial.name",
|
||||
"help": "Emulator.Serial.help"
|
||||
"name": "Serial",
|
||||
"help": "Common emulator Serial can be queried in the list below\nUse \"auto\" to auto-detect emulators, but if multiple emulators are running or use emulators that do not support auto-detect, \"auto\" cannot be used and serial must be filled in manually\nDefault serial for select emulators:\n- BlueStacks 127.0.0.1:5555\n- BlueStacks4 Hyper-V use \"bluestacks4-hyperv\", \"bluestacks4-hyperv-2\" for multi instance, and so on\n- BlueStacks5 Hyper-V use \"bluestacks5-hyperv\", \"bluestacks5-hyperv-1\" for multi instance, and so on\n- NoxPlayer 127.0.0.1:62001\n- NoxPlayer64bit 127.0.0.1:59865\n- MuMuPlayer/MuMuPlayer X 127.0.0.1:7555\n- MuMuPlayer12 127.0.0.1:16384\n- MemuPlayer 127.0.0.1:21503\n- LDPlayer emulator-5554 or 127.0.0.1:5555\n- WSA use \"wsa-0\" to make the game run in the background, which needs to be controlled or closed by third-party software\nIf there are multiple emulator instances running, the default is reserved for one of them and the others will use different serials to avoid conflicts\nOpen console.bat and run `adb devices` to find them or follow the emulator's official tutorial"
|
||||
},
|
||||
"PackageName": {
|
||||
"name": "Emulator.PackageName.name",
|
||||
"help": "Emulator.PackageName.help",
|
||||
"auto": "auto",
|
||||
"JP-Official": "JP-Official"
|
||||
"name": "Game Server",
|
||||
"help": "Can't distinguish different regions of oversea servers, please select the server manually.",
|
||||
"auto": "Auto-detect",
|
||||
"JP-Official": "[JP]-Official",
|
||||
"OVERSEA-Global": "[OVERSEA]-Global"
|
||||
},
|
||||
"GameLanguage": {
|
||||
"name": "Emulator.GameLanguage.name",
|
||||
"help": "Emulator.GameLanguage.help",
|
||||
"auto": "auto",
|
||||
"jp": "jp"
|
||||
"name": "In-game Text Language",
|
||||
"help": "",
|
||||
"auto": "Auto-detect",
|
||||
"jp": "Japanese",
|
||||
"en": "English"
|
||||
},
|
||||
"ScreenshotMethod": {
|
||||
"name": "Emulator.ScreenshotMethod.name",
|
||||
"help": "Emulator.ScreenshotMethod.help",
|
||||
"auto": "auto",
|
||||
"name": "Screenshot Method",
|
||||
"help": "When using auto-select, a benchmark will be performed and automatically changed to the fastest screenshot method.\nGeneral speed: DroidCast_raw >> aScreenCap_nc > ADB_nc >>> aScreenCap > uiautomator2 ~= ADB.\nRun Tools - Performance Test to find the fastest method.",
|
||||
"auto": "Auto-select the fastest",
|
||||
"ADB": "ADB",
|
||||
"ADB_nc": "ADB_nc",
|
||||
"uiautomator2": "uiautomator2",
|
||||
@@ -98,127 +100,127 @@
|
||||
"scrcpy": "scrcpy"
|
||||
},
|
||||
"ControlMethod": {
|
||||
"name": "Emulator.ControlMethod.name",
|
||||
"help": "Emulator.ControlMethod.help",
|
||||
"name": "Control Method",
|
||||
"help": "Speed: MaaTouch = minitouch >>> uiautomator2 ~= ADB\nMaaTouch is recommended",
|
||||
"minitouch": "minitouch",
|
||||
"MaaTouch": "MaaTouch"
|
||||
},
|
||||
"AdbRestart": {
|
||||
"name": "Emulator.AdbRestart.name",
|
||||
"help": "Emulator.AdbRestart.help"
|
||||
"name": "Try to restart adb when no device found",
|
||||
"help": ""
|
||||
}
|
||||
},
|
||||
"EmulatorInfo": {
|
||||
"_info": {
|
||||
"name": "EmulatorInfo._info.name",
|
||||
"help": "EmulatorInfo._info.help"
|
||||
"name": "Emulator Settings",
|
||||
"help": "The following values are auto-filled according to \"Serial\", if you don’t understand, please don't modify them"
|
||||
},
|
||||
"Emulator": {
|
||||
"name": "EmulatorInfo.Emulator.name",
|
||||
"help": "EmulatorInfo.Emulator.help",
|
||||
"auto": "auto",
|
||||
"NoxPlayer": "NoxPlayer",
|
||||
"NoxPlayer64": "NoxPlayer64",
|
||||
"BlueStacks4": "BlueStacks4",
|
||||
"BlueStacks5": "BlueStacks5",
|
||||
"BlueStacks4HyperV": "BlueStacks4HyperV",
|
||||
"BlueStacks5HyperV": "BlueStacks5HyperV",
|
||||
"LDPlayer3": "LDPlayer3",
|
||||
"LDPlayer4": "LDPlayer4",
|
||||
"LDPlayer9": "LDPlayer9",
|
||||
"MuMuPlayer": "MuMuPlayer",
|
||||
"MuMuPlayerX": "MuMuPlayerX",
|
||||
"MuMuPlayer12": "MuMuPlayer12",
|
||||
"MEmuPlayer": "MEmuPlayer"
|
||||
"name": "Emulator Type",
|
||||
"help": "",
|
||||
"auto": "Auto-detect",
|
||||
"NoxPlayer": "Nox Player",
|
||||
"NoxPlayer64": "Nox Player 64bit",
|
||||
"BlueStacks4": "BlueStacks 4",
|
||||
"BlueStacks5": "BlueStacks 5",
|
||||
"BlueStacks4HyperV": "BlueStacks 4 Hyper-V",
|
||||
"BlueStacks5HyperV": "BlueStacks 5 Hyper-V",
|
||||
"LDPlayer3": "LD Player 3",
|
||||
"LDPlayer4": "LD Player 4",
|
||||
"LDPlayer9": "LD Player 9",
|
||||
"MuMuPlayer": "MuMu Player",
|
||||
"MuMuPlayerX": "MuMu Player X",
|
||||
"MuMuPlayer12": "MuMu Player 12",
|
||||
"MEmuPlayer": "MEmu Player"
|
||||
},
|
||||
"name": {
|
||||
"name": "EmulatorInfo.name.name",
|
||||
"help": "EmulatorInfo.name.help"
|
||||
"name": "Emulator Instance Name",
|
||||
"help": ""
|
||||
},
|
||||
"path": {
|
||||
"name": "EmulatorInfo.path.name",
|
||||
"help": "EmulatorInfo.path.help"
|
||||
"name": "Emulator Installation Path",
|
||||
"help": ""
|
||||
}
|
||||
},
|
||||
"Error": {
|
||||
"_info": {
|
||||
"name": "Error._info.name",
|
||||
"help": "Error._info.help"
|
||||
"name": "Debug Settings",
|
||||
"help": ""
|
||||
},
|
||||
"Restart": {
|
||||
"name": "Error.Restart.name",
|
||||
"help": "Error.Restart.help",
|
||||
"game": "game",
|
||||
"game_emulator": "game_emulator"
|
||||
"name": "Restart Game on Error",
|
||||
"help": "",
|
||||
"game": "Restart game",
|
||||
"game_emulator": "Restart emulator and game"
|
||||
},
|
||||
"SaveError": {
|
||||
"name": "Error.SaveError.name",
|
||||
"help": "Error.SaveError.help"
|
||||
"name": "Record Exception",
|
||||
"help": "Records exception and log into directory for review or sharing"
|
||||
},
|
||||
"ScreenshotLength": {
|
||||
"name": "Error.ScreenshotLength.name",
|
||||
"help": "Error.ScreenshotLength.help"
|
||||
"name": "Record Screenshot(s)",
|
||||
"help": "Number of screenshots saved when exception occurs"
|
||||
},
|
||||
"OnePushConfig": {
|
||||
"name": "Error.OnePushConfig.name",
|
||||
"help": "Error.OnePushConfig.help"
|
||||
"name": "Error notify config",
|
||||
"help": "When AAS cannot handle exception, send a message through Onepush. Configuration document: \nhttps://github.com/LmeSzinc/AzurLaneAutoScript/wiki/Onepush-configuration-%5BEN%5D"
|
||||
}
|
||||
},
|
||||
"Optimization": {
|
||||
"_info": {
|
||||
"name": "Optimization._info.name",
|
||||
"help": "Optimization._info.help"
|
||||
"name": "Optimization Settings",
|
||||
"help": ""
|
||||
},
|
||||
"ScreenshotInterval": {
|
||||
"name": "Optimization.ScreenshotInterval.name",
|
||||
"help": "Optimization.ScreenshotInterval.help"
|
||||
"name": "Take Screenshots Every X Second(s)",
|
||||
"help": "Minimum interval between 2 screenshots, limited in 0.1 ~ 0.3, can help reduce CPU on high-end PCs"
|
||||
},
|
||||
"CombatScreenshotInterval": {
|
||||
"name": "Optimization.CombatScreenshotInterval.name",
|
||||
"help": "Optimization.CombatScreenshotInterval.help"
|
||||
"name": "Take Screenshots Every X Second(s) In Combat",
|
||||
"help": "Minimum interval between 2 screenshots, limited in 0.1 ~ 1.0, can help reduce CPU during battle"
|
||||
},
|
||||
"WhenTaskQueueEmpty": {
|
||||
"name": "Optimization.WhenTaskQueueEmpty.name",
|
||||
"help": "Optimization.WhenTaskQueueEmpty.help",
|
||||
"stay_there": "stay_there",
|
||||
"goto_main": "goto_main",
|
||||
"close_game": "close_game"
|
||||
"name": "When Task Queue is Empty",
|
||||
"help": "Close AL when there are no pending tasks, can help reduce CPU",
|
||||
"stay_there": "Stay There",
|
||||
"goto_main": "Goto Main Page",
|
||||
"close_game": "Close Game"
|
||||
}
|
||||
},
|
||||
"Cafe": {
|
||||
"_info": {
|
||||
"name": "Cafe._info.name",
|
||||
"help": "Cafe._info.help"
|
||||
"name": "Cafe Settings",
|
||||
"help": ""
|
||||
},
|
||||
"Reward": {
|
||||
"name": "Cafe.Reward.name",
|
||||
"help": "Cafe.Reward.help"
|
||||
"name": "Claim Reward",
|
||||
"help": ""
|
||||
},
|
||||
"Touch": {
|
||||
"name": "Cafe.Touch.name",
|
||||
"help": "Cafe.Touch.help"
|
||||
"name": "Student Interaction",
|
||||
"help": "Auto detect intractable student and tap"
|
||||
},
|
||||
"AutoAdjust": {
|
||||
"name": "Cafe.AutoAdjust.name",
|
||||
"help": "Cafe.AutoAdjust.help"
|
||||
"name": "Interface Auto Adjustment",
|
||||
"help": "Auto adjust cafe interface for better student interaction"
|
||||
},
|
||||
"SecondCafe": {
|
||||
"name": "Cafe.SecondCafe.name",
|
||||
"help": "Cafe.SecondCafe.help"
|
||||
"name": "Second Floor",
|
||||
"help": "JP server only\nEnable auto switch to second floor and perform interaction"
|
||||
}
|
||||
},
|
||||
"TacticalChallenge": {
|
||||
"_info": {
|
||||
"name": "TacticalChallenge._info.name",
|
||||
"help": "TacticalChallenge._info.help"
|
||||
"name": "Tactical Challenge Settings",
|
||||
"help": ""
|
||||
},
|
||||
"PlayerSelect": {
|
||||
"name": "TacticalChallenge.PlayerSelect.name",
|
||||
"help": "TacticalChallenge.PlayerSelect.help",
|
||||
"0": "0",
|
||||
"1": "1",
|
||||
"2": "2",
|
||||
"3": "3"
|
||||
"name": "Select Player",
|
||||
"help": "",
|
||||
"0": "Random",
|
||||
"1": "First",
|
||||
"2": "Second",
|
||||
"3": "Third"
|
||||
}
|
||||
},
|
||||
"ItemStorage": {
|
||||
@@ -227,118 +229,118 @@
|
||||
"help": "ItemStorage._info.help"
|
||||
},
|
||||
"AP": {
|
||||
"name": "ItemStorage.AP.name",
|
||||
"help": "ItemStorage.AP.help"
|
||||
"name": "AP",
|
||||
"help": ""
|
||||
},
|
||||
"Credit": {
|
||||
"name": "ItemStorage.Credit.name",
|
||||
"help": "ItemStorage.Credit.help"
|
||||
"name": "Credit",
|
||||
"help": ""
|
||||
},
|
||||
"Pyroxene": {
|
||||
"name": "ItemStorage.Pyroxene.name",
|
||||
"help": "ItemStorage.Pyroxene.help"
|
||||
"name": "Pyroxene",
|
||||
"help": ""
|
||||
}
|
||||
},
|
||||
"Gui": {
|
||||
"Aside": {
|
||||
"Install": "Gui.Aside.Install",
|
||||
"Home": "Gui.Aside.Home",
|
||||
"Develop": "Gui.Aside.Develop",
|
||||
"Performance": "Gui.Aside.Performance",
|
||||
"Setting": "Gui.Aside.Setting",
|
||||
"AddAlas": "Gui.Aside.AddAlas"
|
||||
"Install": "Install",
|
||||
"Home": "Home",
|
||||
"Develop": "Develop",
|
||||
"Performance": "Perf.",
|
||||
"Setting": "Settings",
|
||||
"AddAlas": "Add"
|
||||
},
|
||||
"Button": {
|
||||
"Start": "Gui.Button.Start",
|
||||
"Stop": "Gui.Button.Stop",
|
||||
"ScrollON": "Gui.Button.ScrollON",
|
||||
"ScrollOFF": "Gui.Button.ScrollOFF",
|
||||
"ClearLog": "Gui.Button.ClearLog",
|
||||
"Setting": "Gui.Button.Setting",
|
||||
"CheckUpdate": "Gui.Button.CheckUpdate",
|
||||
"ClickToUpdate": "Gui.Button.ClickToUpdate",
|
||||
"RetryUpdate": "Gui.Button.RetryUpdate",
|
||||
"CancelUpdate": "Gui.Button.CancelUpdate"
|
||||
"Start": "Start",
|
||||
"Stop": "Stop",
|
||||
"ScrollON": "Auto Scroll ON",
|
||||
"ScrollOFF": "Auto Scroll OFF",
|
||||
"ClearLog": "Clear Log",
|
||||
"Setting": "Setting",
|
||||
"CheckUpdate": "Check update",
|
||||
"ClickToUpdate": "Click to update",
|
||||
"RetryUpdate": "Retry update",
|
||||
"CancelUpdate": "Cancel update"
|
||||
},
|
||||
"Toast": {
|
||||
"DisableTranslateMode": "Gui.Toast.DisableTranslateMode",
|
||||
"ConfigSaved": "Gui.Toast.ConfigSaved",
|
||||
"AlasIsRunning": "Gui.Toast.AlasIsRunning",
|
||||
"ClickToUpdate": "Gui.Toast.ClickToUpdate"
|
||||
"DisableTranslateMode": "Click here to disable translate mode",
|
||||
"ConfigSaved": "Config saved",
|
||||
"AlasIsRunning": "Scheduler is already running",
|
||||
"ClickToUpdate": "New update available, click here to update"
|
||||
},
|
||||
"Status": {
|
||||
"Running": "Gui.Status.Running",
|
||||
"Inactive": "Gui.Status.Inactive",
|
||||
"Warning": "Gui.Status.Warning",
|
||||
"Updating": "Gui.Status.Updating"
|
||||
"Running": "Running",
|
||||
"Inactive": "Inactive",
|
||||
"Warning": "Warning",
|
||||
"Updating": "Waiting Update"
|
||||
},
|
||||
"MenuAlas": {
|
||||
"Overview": "Gui.MenuAlas.Overview",
|
||||
"Log": "Gui.MenuAlas.Log"
|
||||
"Overview": "Overview",
|
||||
"Log": "Logs"
|
||||
},
|
||||
"MenuDevelop": {
|
||||
"HomePage": "Gui.MenuDevelop.HomePage",
|
||||
"Translate": "Gui.MenuDevelop.Translate",
|
||||
"Update": "Gui.MenuDevelop.Update",
|
||||
"Remote": "Gui.MenuDevelop.Remote",
|
||||
"Utils": "Gui.MenuDevelop.Utils"
|
||||
"HomePage": "Home",
|
||||
"Translate": "Translate",
|
||||
"Update": "Updater",
|
||||
"Remote": "Remote access",
|
||||
"Utils": "Utils"
|
||||
},
|
||||
"Overview": {
|
||||
"Scheduler": "Gui.Overview.Scheduler",
|
||||
"Log": "Gui.Overview.Log",
|
||||
"Running": "Gui.Overview.Running",
|
||||
"Pending": "Gui.Overview.Pending",
|
||||
"Waiting": "Gui.Overview.Waiting",
|
||||
"NoTask": "Gui.Overview.NoTask"
|
||||
"Scheduler": "Scheduler",
|
||||
"Log": "Log",
|
||||
"Running": "Running",
|
||||
"Pending": "Pending",
|
||||
"Waiting": "Waiting",
|
||||
"NoTask": "No Task"
|
||||
},
|
||||
"Dashboard": {
|
||||
"NoData": "Gui.Dashboard.NoData",
|
||||
"TimeError": "Gui.Dashboard.TimeError",
|
||||
"JustNow": "Gui.Dashboard.JustNow",
|
||||
"MinutesAgo": "Gui.Dashboard.MinutesAgo",
|
||||
"HoursAgo": "Gui.Dashboard.HoursAgo",
|
||||
"DaysAgo": "Gui.Dashboard.DaysAgo",
|
||||
"LongTimeAgo": "Gui.Dashboard.LongTimeAgo"
|
||||
"NoData": "no data",
|
||||
"TimeError": "time error",
|
||||
"JustNow": "just now",
|
||||
"MinutesAgo": "{time}min ago",
|
||||
"HoursAgo": "{time}h ago",
|
||||
"DaysAgo": "{time}d ago",
|
||||
"LongTimeAgo": "long time ago"
|
||||
},
|
||||
"AddAlas": {
|
||||
"PopupTitle": "Gui.AddAlas.PopupTitle",
|
||||
"NewName": "Gui.AddAlas.NewName",
|
||||
"CopyFrom": "Gui.AddAlas.CopyFrom",
|
||||
"Confirm": "Gui.AddAlas.Confirm",
|
||||
"FileExist": "Gui.AddAlas.FileExist",
|
||||
"InvalidChar": "Gui.AddAlas.InvalidChar",
|
||||
"InvalidPrefixTemplate": "Gui.AddAlas.InvalidPrefixTemplate"
|
||||
"PopupTitle": "Add new config",
|
||||
"NewName": "New name",
|
||||
"CopyFrom": "Copy from existing config",
|
||||
"Confirm": "Add",
|
||||
"FileExist": "A config with the same name exists, please choose another one",
|
||||
"InvalidChar": "Config name cannot contain any of the following characters: .\\/:*?\"<>|",
|
||||
"InvalidPrefixTemplate": "Config name cannot start with 'template'"
|
||||
},
|
||||
"Update": {
|
||||
"UpToDate": "Gui.Update.UpToDate",
|
||||
"HaveUpdate": "Gui.Update.HaveUpdate",
|
||||
"UpdateStart": "Gui.Update.UpdateStart",
|
||||
"UpdateWait": "Gui.Update.UpdateWait",
|
||||
"UpdateRun": "Gui.Update.UpdateRun",
|
||||
"UpdateSuccess": "Gui.Update.UpdateSuccess",
|
||||
"UpdateFailed": "Gui.Update.UpdateFailed",
|
||||
"UpdateChecking": "Gui.Update.UpdateChecking",
|
||||
"UpdateCancel": "Gui.Update.UpdateCancel",
|
||||
"UpdateFinish": "Gui.Update.UpdateFinish",
|
||||
"Local": "Gui.Update.Local",
|
||||
"Upstream": "Gui.Update.Upstream",
|
||||
"Author": "Gui.Update.Author",
|
||||
"Time": "Gui.Update.Time",
|
||||
"Message": "Gui.Update.Message",
|
||||
"DisabledWarn": "Gui.Update.DisabledWarn",
|
||||
"DetailedHistory": "Gui.Update.DetailedHistory"
|
||||
"UpToDate": "Latest version",
|
||||
"HaveUpdate": "A new version is available",
|
||||
"UpdateStart": "Start update",
|
||||
"UpdateWait": "Waiting for all AAS complete current task",
|
||||
"UpdateRun": "Updating",
|
||||
"UpdateSuccess": "Update succeeded, restarting",
|
||||
"UpdateFailed": "Update failed. Logs can be found in ./log/*_gui.txt",
|
||||
"UpdateChecking": "Checking for updates",
|
||||
"UpdateCancel": "Update canceled, restarting AAS",
|
||||
"UpdateFinish": "Update succeeded, please restart manually",
|
||||
"Local": "Local",
|
||||
"Upstream": "Upstream",
|
||||
"Author": "Author",
|
||||
"Time": "Commit time",
|
||||
"Message": "Commit message",
|
||||
"DisabledWarn": "Updater module is disabled. You need to manually restart AAS to update",
|
||||
"DetailedHistory": "Detailed Commit History"
|
||||
},
|
||||
"Remote": {
|
||||
"Running": "Gui.Remote.Running",
|
||||
"NotRunning": "Gui.Remote.NotRunning",
|
||||
"NotEnable": "Gui.Remote.NotEnable",
|
||||
"EntryPoint": "Gui.Remote.EntryPoint",
|
||||
"ConfigureHint": "Gui.Remote.ConfigureHint",
|
||||
"SSHNotInstall": "Gui.Remote.SSHNotInstall"
|
||||
"Running": "Remote access on",
|
||||
"NotRunning": "Not running, server disconnected or offline",
|
||||
"NotEnable": "Disabled, set webui password in deploy.yaml and enable remote access",
|
||||
"EntryPoint": "Entry point:",
|
||||
"ConfigureHint": "Configuration tutorial:",
|
||||
"SSHNotInstall": "No SSH command in your system. Please refer to the tutorial to download or install one"
|
||||
},
|
||||
"Text": {
|
||||
"InvalidFeedBack": "Gui.Text.InvalidFeedBack",
|
||||
"Clear": "Gui.Text.Clear"
|
||||
"InvalidFeedBack": "Invalid format. Example: {0}",
|
||||
"Clear": "Clear"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -76,13 +76,15 @@
|
||||
"name": "游戏服务器",
|
||||
"help": "无法区分国际服的不同地区,请手动选择服务器",
|
||||
"auto": "自动检测",
|
||||
"JP-Official": "[日服]-官服"
|
||||
"JP-Official": "[日服]-官服",
|
||||
"OVERSEA-Global": "[国际服]-全球"
|
||||
},
|
||||
"GameLanguage": {
|
||||
"name": "游戏内文本语言",
|
||||
"help": "",
|
||||
"auto": "自动检测",
|
||||
"jp": "日语"
|
||||
"jp": "日语",
|
||||
"en": "英语"
|
||||
},
|
||||
"ScreenshotMethod": {
|
||||
"name": "模拟器截图方案",
|
||||
@@ -204,7 +206,7 @@
|
||||
},
|
||||
"SecondCafe": {
|
||||
"name": "第二咖啡厅",
|
||||
"help": "自动切换第二咖啡厅进行互动点击"
|
||||
"help": "仅支持日服\n自动切换第二咖啡厅进行互动点击"
|
||||
}
|
||||
},
|
||||
"TacticalChallenge": {
|
||||
@@ -313,19 +315,19 @@
|
||||
"UpToDate": "已是最新版本",
|
||||
"HaveUpdate": "有新版本可用",
|
||||
"UpdateStart": "开始更新",
|
||||
"UpdateWait": "等待所有 Alas 完成当前任务",
|
||||
"UpdateWait": "等待所有 AAS 完成当前任务",
|
||||
"UpdateRun": "更新中",
|
||||
"UpdateSuccess": "更新成功,正在重启",
|
||||
"UpdateFailed": "更新失败,可在./log/*_gui.txt中找到错误日志",
|
||||
"UpdateChecking": "检查更新中",
|
||||
"UpdateCancel": "取消更新,重启 Alas 中",
|
||||
"UpdateCancel": "取消更新,重启 AAS 中",
|
||||
"UpdateFinish": "更新成功,请手动重启",
|
||||
"Local": "本地",
|
||||
"Upstream": "上游仓库",
|
||||
"Author": "作者",
|
||||
"Time": "提交时间",
|
||||
"Message": "提交信息",
|
||||
"DisabledWarn": "更新模块未启用,你需要手动重启 Alas 进行更新",
|
||||
"DisabledWarn": "更新模块未启用,你需要手动重启 AAS 进行更新",
|
||||
"DetailedHistory": "详细提交历史"
|
||||
},
|
||||
"Remote": {
|
||||
|
||||
@@ -5,9 +5,10 @@ Use 'import module.config.server as server' to import, don't use 'from xxx impor
|
||||
lang = 'jp' # Setting default to cn, will avoid errors when using dev_tools
|
||||
server = 'JP-Official'
|
||||
|
||||
VALID_LANG = ['jp']
|
||||
VALID_LANG = ['jp', 'en']
|
||||
VALID_SERVER = {
|
||||
'JP-Official': 'com.YostarJP.BlueArchive'
|
||||
'JP-Official': 'com.YostarJP.BlueArchive',
|
||||
'OVERSEA-Global': 'com.nexon.bluearchive',
|
||||
}
|
||||
VALID_PACKAGE = set(list(VALID_SERVER.values()))
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ from module.config.atomicwrites import atomic_write
|
||||
LANGUAGES = ['zh-CN', 'en-US']
|
||||
SERVER_TO_TIMEZONE = {
|
||||
'JP-Official': timedelta(hours=9),
|
||||
'OVERSEA-Global': timedelta(hours=0),
|
||||
}
|
||||
DEFAULT_TIME = datetime(2020, 1, 1, 0, 0)
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -172,7 +172,7 @@ class Control(Hermit, Minitouch, Scrcpy, MaaTouch):
|
||||
self.click(ClickButton(button=area_offset(point_random, p2), name=name))
|
||||
|
||||
# just used in cafe
|
||||
def pinch(self, box=(33, 130, 1247, 569), name='PINCH'):
|
||||
def pinch(self, box=(35, 130, 1250, 560), name='PINCH'):
|
||||
self.handle_control_check(name)
|
||||
middle_point = (box[0] + box[2]) // 2, (box[1] + box[3]) // 2
|
||||
width = box[2] - middle_point[0]
|
||||
|
||||
@@ -1110,7 +1110,7 @@ class AlasGUI(Frame):
|
||||
"""
|
||||
AAS is a free open source software, if you paid for AAS from any channel, please refund.
|
||||
AAS 是一款免费开源软件,如果你在任何渠道付费购买了AAS,请退款。
|
||||
Project repository 项目地址:`https://github.com/TheFunny/ArisuAutoSrcipt`
|
||||
Project repository 项目地址:`https://github.com/TheFunny/ArisuAutoSweeper`
|
||||
"""
|
||||
).style("text-align: center")
|
||||
|
||||
|
||||
@@ -376,7 +376,7 @@ def add_css(filepath):
|
||||
|
||||
|
||||
def _read(path):
|
||||
with open(path, "r") as f:
|
||||
with open(path, "r", encoding="utf-8") as f:
|
||||
return f.read()
|
||||
|
||||
|
||||
|
||||
@@ -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,
|
||||
)
|
||||
|
||||
@@ -12,6 +12,18 @@ AFFECTION_LEVEL_UP = ButtonWrapper(
|
||||
color=(208, 223, 243),
|
||||
button=(882, 244, 1176, 476),
|
||||
),
|
||||
en=None,
|
||||
)
|
||||
AP_EXCEED = ButtonWrapper(
|
||||
name='AP_EXCEED',
|
||||
jp=Button(
|
||||
file='./assets/jp/base/popup/AP_EXCEED.png',
|
||||
area=(610, 124, 669, 153),
|
||||
search=(590, 104, 689, 173),
|
||||
color=(139, 153, 168),
|
||||
button=(535, 494, 746, 565),
|
||||
),
|
||||
en=None,
|
||||
)
|
||||
DAILY_NEWS = ButtonWrapper(
|
||||
name='DAILY_NEWS',
|
||||
@@ -22,16 +34,18 @@ DAILY_NEWS = ButtonWrapper(
|
||||
color=(150, 204, 253),
|
||||
button=(1128, 89, 1156, 117),
|
||||
),
|
||||
en=None,
|
||||
)
|
||||
DAILY_REWARD = ButtonWrapper(
|
||||
name='DAILY_REWARD',
|
||||
jp=Button(
|
||||
file='./assets/jp/base/popup/DAILY_REWARD.png',
|
||||
area=(854, 117, 1008, 165),
|
||||
search=(834, 97, 1028, 185),
|
||||
color=(178, 167, 112),
|
||||
area=(416, 165, 434, 216),
|
||||
search=(396, 145, 454, 236),
|
||||
color=(203, 227, 237),
|
||||
button=(920, 632, 1140, 712),
|
||||
),
|
||||
en=None,
|
||||
)
|
||||
GET_NEW_STUDENT = ButtonWrapper(
|
||||
name='GET_NEW_STUDENT',
|
||||
@@ -42,6 +56,7 @@ GET_NEW_STUDENT = ButtonWrapper(
|
||||
color=(125, 132, 92),
|
||||
button=(934, 643, 1263, 714),
|
||||
),
|
||||
en=None,
|
||||
)
|
||||
GET_REWARD = ButtonWrapper(
|
||||
name='GET_REWARD',
|
||||
@@ -52,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',
|
||||
@@ -62,6 +78,18 @@ GET_REWARD_SKIP = ButtonWrapper(
|
||||
color=(197, 200, 205),
|
||||
button=(1137, 34, 1243, 65),
|
||||
),
|
||||
en=None,
|
||||
)
|
||||
ITEM_EXPIRED = ButtonWrapper(
|
||||
name='ITEM_EXPIRED',
|
||||
jp=Button(
|
||||
file='./assets/jp/base/popup/ITEM_EXPIRED.png',
|
||||
area=(612, 147, 668, 175),
|
||||
search=(592, 127, 688, 195),
|
||||
color=(131, 145, 162),
|
||||
button=(537, 487, 742, 553),
|
||||
),
|
||||
en=None,
|
||||
)
|
||||
NETWORK_RECONNECT = ButtonWrapper(
|
||||
name='NETWORK_RECONNECT',
|
||||
@@ -72,4 +100,16 @@ NETWORK_RECONNECT = ButtonWrapper(
|
||||
color=(78, 138, 169),
|
||||
button=(663, 467, 870, 537),
|
||||
),
|
||||
en=None,
|
||||
)
|
||||
NETWORK_RECONNECT_OK = ButtonWrapper(
|
||||
name='NETWORK_RECONNECT_OK',
|
||||
jp=Button(
|
||||
file='./assets/jp/base/popup/NETWORK_RECONNECT_OK.png',
|
||||
area=(744, 487, 791, 515),
|
||||
search=(724, 467, 811, 535),
|
||||
color=(91, 165, 196),
|
||||
button=(665, 468, 870, 536),
|
||||
),
|
||||
en=None,
|
||||
)
|
||||
|
||||
@@ -65,6 +65,8 @@ class PopupHandler(ModuleBase):
|
||||
def handle_network_reconnect(self, interval=5) -> bool:
|
||||
if self.appear_then_click(NETWORK_RECONNECT, interval=interval):
|
||||
return True
|
||||
if self.appear_then_click(NETWORK_RECONNECT_OK, interval=interval):
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
@@ -85,3 +87,15 @@ class PopupHandler(ModuleBase):
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def handle_ap_exceed(self, interval=5) -> bool:
|
||||
if self.appear_then_click(AP_EXCEED, interval=interval):
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def handle_item_expired(self, interval=5) -> bool:
|
||||
if self.appear_then_click(ITEM_EXPIRED, interval=interval):
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
@@ -343,6 +343,10 @@ class UI(MainPage):
|
||||
return True
|
||||
if self.handle_new_student():
|
||||
return True
|
||||
if self.handle_ap_exceed():
|
||||
return True
|
||||
if self.handle_item_expired():
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
@@ -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,16 +67,18 @@ CHECK_REWARD = ButtonWrapper(
|
||||
color=(82, 105, 129),
|
||||
button=(1086, 607, 1225, 685),
|
||||
),
|
||||
en=None,
|
||||
)
|
||||
CLICKABLE_TEMPLATE = ButtonWrapper(
|
||||
name='CLICKABLE_TEMPLATE',
|
||||
jp=Button(
|
||||
file='./assets/jp/cafe/CLICKABLE_TEMPLATE.png',
|
||||
area=(0, 0, 42, 56),
|
||||
search=(0, 0, 62, 76),
|
||||
color=(77, 63, 1),
|
||||
button=(0, 0, 42, 56),
|
||||
area=(619, 332, 660, 387),
|
||||
search=(599, 312, 680, 407),
|
||||
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,29 @@ GOT_REWARD = ButtonWrapper(
|
||||
color=(209, 210, 209),
|
||||
button=(561, 501, 718, 556),
|
||||
),
|
||||
en=None,
|
||||
)
|
||||
INVENTORY = ButtonWrapper(
|
||||
name='INVENTORY',
|
||||
jp=Button(
|
||||
file='./assets/jp/cafe/INVENTORY.png',
|
||||
area=(553, 94, 725, 122),
|
||||
search=(533, 74, 745, 142),
|
||||
color=(198, 205, 213),
|
||||
button=(1130, 94, 1156, 120),
|
||||
),
|
||||
en=None,
|
||||
)
|
||||
MOMOTALK_CLOSE = ButtonWrapper(
|
||||
name='MOMOTALK_CLOSE',
|
||||
jp=Button(
|
||||
file='./assets/jp/cafe/MOMOTALK_CLOSE.png',
|
||||
area=(824, 82, 850, 108),
|
||||
search=(804, 62, 870, 128),
|
||||
color=(252, 182, 194),
|
||||
button=(824, 82, 850, 108),
|
||||
),
|
||||
en=None,
|
||||
)
|
||||
OCR_CAFE = ButtonWrapper(
|
||||
name='OCR_CAFE',
|
||||
@@ -112,6 +144,7 @@ OCR_CAFE = ButtonWrapper(
|
||||
color=(87, 107, 129),
|
||||
button=(1103, 642, 1202, 672),
|
||||
),
|
||||
en=None,
|
||||
)
|
||||
STUDENT_LIST = ButtonWrapper(
|
||||
name='STUDENT_LIST',
|
||||
@@ -122,4 +155,5 @@ STUDENT_LIST = ButtonWrapper(
|
||||
color=(145, 157, 172),
|
||||
button=(545, 423, 738, 495),
|
||||
),
|
||||
en=None,
|
||||
)
|
||||
|
||||
@@ -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,25 +66,26 @@ class Cafe(UI):
|
||||
|
||||
def _match_clickable_points(self, image, threshold=0.8):
|
||||
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
|
||||
template = self.btn.matched_button.image
|
||||
template = cv2.cvtColor(template, 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)
|
||||
return [point for point in zip(*loc[::-1])]
|
||||
|
||||
def _get_clickable_buttons(self, threshold=0.8, offset=(0, 0)):
|
||||
image = cv2.copyMakeBorder(self.device.image, 20, 20, 10, 80, cv2.BORDER_CONSTANT, value=(0, 0, 0))
|
||||
image = self.device.image
|
||||
h, w = image.shape[:2]
|
||||
image = cv2.rectangle(image, (0, 10), (w - 25, h - 10), (0, 0, 0), 50)
|
||||
image = self._extract_clickable_from_image(image)
|
||||
points = self._match_clickable_points(image, threshold)
|
||||
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
|
||||
]
|
||||
@@ -120,6 +124,13 @@ class Cafe(UI):
|
||||
logger.attr('Reward', num)
|
||||
return num
|
||||
|
||||
def _cafe_additional(self) -> bool:
|
||||
if self.appear_then_click(INVENTORY):
|
||||
return True
|
||||
if self.appear_then_click(MOMOTALK_CLOSE):
|
||||
return True
|
||||
return False
|
||||
|
||||
def _handle_cafe(self, status):
|
||||
match status:
|
||||
case CafeStatus.STUDENT_LIST:
|
||||
@@ -180,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)
|
||||
|
||||
@@ -206,7 +225,7 @@ class Cafe(UI):
|
||||
|
||||
self.device.screenshot()
|
||||
|
||||
if self.ui_additional():
|
||||
if self.ui_additional() or self._cafe_additional():
|
||||
continue
|
||||
|
||||
if not loading_timer.reached():
|
||||
@@ -232,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
|
||||
@@ -258,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)
|
||||
|
||||
@@ -12,4 +12,5 @@ GET_REWARD_AP = ButtonWrapper(
|
||||
color=(198, 206, 213),
|
||||
button=(543, 457, 735, 524),
|
||||
),
|
||||
en=None,
|
||||
)
|
||||
|
||||
@@ -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,4 +23,16 @@ LOGIN_LOADING = ButtonWrapper(
|
||||
color=(8, 66, 96),
|
||||
button=(34, 682, 60, 707),
|
||||
),
|
||||
en=None,
|
||||
)
|
||||
UPDATE = ButtonWrapper(
|
||||
name='UPDATE',
|
||||
jp=Button(
|
||||
file='./assets/jp/login/UPDATE.png',
|
||||
area=(526, 87, 756, 117),
|
||||
search=(506, 67, 776, 137),
|
||||
color=(183, 192, 201),
|
||||
button=(666, 527, 872, 595),
|
||||
),
|
||||
en=None,
|
||||
)
|
||||
|
||||
@@ -3,8 +3,7 @@ from module.exception import GameNotRunningError
|
||||
from module.logger import logger
|
||||
from tasks.base.page import page_main
|
||||
from tasks.base.ui import UI
|
||||
# from tasks.login.assets.assets_login import LOGIN_CONFIRM, USER_AGREEMENT_ACCEPT, LOGIN_LOADING
|
||||
from tasks.login.assets.assets_login import LOGIN_CONFIRM, LOGIN_LOADING
|
||||
from tasks.login.assets.assets_login import LOGIN_CONFIRM, LOGIN_LOADING, UPDATE
|
||||
|
||||
|
||||
class Login(UI):
|
||||
@@ -77,6 +76,8 @@ class Login(UI):
|
||||
# continue
|
||||
# if self.handle_popup_confirm():
|
||||
# continue
|
||||
if self.appear_then_click(UPDATE):
|
||||
continue
|
||||
if self.ui_additional():
|
||||
continue
|
||||
|
||||
|
||||
@@ -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,
|
||||
)
|
||||
|
||||
@@ -12,4 +12,5 @@ SCROLL = ButtonWrapper(
|
||||
color=(198, 214, 210),
|
||||
button=(742, 136, 1101, 671),
|
||||
),
|
||||
en=None,
|
||||
)
|
||||
|
||||
@@ -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,
|
||||
)
|
||||
@@ -0,0 +1,182 @@
|
||||
import cv2
|
||||
import numpy as np
|
||||
|
||||
from module.base.base import ModuleBase
|
||||
from module.base.button import ButtonWrapper, ClickButton
|
||||
from module.base.timer import Timer
|
||||
from module.base.utils import area_pad, area_size, area_offset, random_rectangle_vector_opted
|
||||
from module.logger import logger
|
||||
from module.ocr.ocr import Ocr
|
||||
|
||||
|
||||
class StageList:
|
||||
drag_vector_range = (0.65, 0.85)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
name,
|
||||
area_stage: ButtonWrapper,
|
||||
area_index: ButtonWrapper,
|
||||
area_item: ButtonWrapper,
|
||||
button_enter: ButtonWrapper,
|
||||
drag_direction: str = "down"
|
||||
):
|
||||
self.name = name
|
||||
self.stage = area_stage
|
||||
self.index_ocr = Ocr(area_index, lang='en')
|
||||
self.stage_item = area_item.button
|
||||
self.enter = button_enter
|
||||
self.drag_direction = drag_direction
|
||||
|
||||
self.current_index_min = 1
|
||||
self.current_index_max = 1
|
||||
self.current_indexes = []
|
||||
|
||||
def __str__(self):
|
||||
return f'StageList({self.name})'
|
||||
|
||||
__repr__ = __str__
|
||||
|
||||
def __eq__(self, other):
|
||||
return str(self) == str(other)
|
||||
|
||||
def __hash__(self):
|
||||
return hash(self.name)
|
||||
|
||||
@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):
|
||||
self.current_indexes = list(
|
||||
filter(lambda x: x.ocr_text.isdigit(), self.index_ocr.detect_and_ocr(main.device.image))
|
||||
)
|
||||
if not self.current_indexes:
|
||||
logger.warning(f'No valid index in {self.index_ocr.name}')
|
||||
return
|
||||
indexes = self._indexes
|
||||
|
||||
self.current_index_min = min(indexes)
|
||||
self.current_index_max = max(indexes)
|
||||
logger.attr(self.index_ocr.name, f'Index range: {self.current_index_min} - {self.current_index_max}')
|
||||
|
||||
def drag_page(self, direction: str, main: ModuleBase, vector_range=None, reverse=False):
|
||||
"""
|
||||
Args:
|
||||
direction: up, down
|
||||
main:
|
||||
vector_range (tuple[float, float]):
|
||||
reverse (bool):
|
||||
"""
|
||||
if vector_range is None:
|
||||
vector_range = self.drag_vector_range
|
||||
vector = np.random.uniform(*vector_range)
|
||||
width, height = area_size(self.stage.button)
|
||||
if direction == 'up':
|
||||
vector = (0, vector * height)
|
||||
elif direction == 'down':
|
||||
vector = (0, -vector * height)
|
||||
else:
|
||||
logger.warning(f'Unknown drag direction: {direction}')
|
||||
return
|
||||
|
||||
if reverse:
|
||||
vector = (-vector[0], -vector[1])
|
||||
p1, p2 = random_rectangle_vector_opted(vector, box=self.stage.button)
|
||||
main.device.drag(p1, p2, name=f'{self.name}_DRAG')
|
||||
|
||||
def insight_index(self, index: int, main: ModuleBase, skip_first_screenshot=True) -> bool:
|
||||
"""
|
||||
Args:
|
||||
index:
|
||||
main:
|
||||
skip_first_screenshot:
|
||||
|
||||
Returns:
|
||||
If success
|
||||
"""
|
||||
logger.info(f'Insight index: {index}')
|
||||
last_indexes: set[int] = set()
|
||||
|
||||
while 1:
|
||||
if skip_first_screenshot:
|
||||
skip_first_screenshot = False
|
||||
else:
|
||||
main.device.screenshot()
|
||||
|
||||
self.load_stage_indexes(main=main)
|
||||
|
||||
if self.current_index_min <= index <= self.current_index_max:
|
||||
break
|
||||
|
||||
if index < self.current_index_min:
|
||||
self.drag_page(self.drag_direction, main, reverse=True)
|
||||
elif index > self.current_index_max:
|
||||
self.drag_page(self.drag_direction, main)
|
||||
|
||||
main.wait_until_stable(
|
||||
self.stage.button,
|
||||
timer=Timer(0, 0),
|
||||
timeout=Timer(1.5, 5)
|
||||
)
|
||||
|
||||
indexes = self._indexes
|
||||
if indexes and last_indexes == set(indexes):
|
||||
logger.warning(f'No more index {index}')
|
||||
return False
|
||||
last_indexes = set(indexes)
|
||||
|
||||
return True
|
||||
|
||||
@staticmethod
|
||||
def _match_clickable_points(image, template, threshold=0.85):
|
||||
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
|
||||
template = cv2.cvtColor(template, cv2.COLOR_BGR2GRAY)
|
||||
|
||||
res = cv2.matchTemplate(image, template, cv2.TM_CCOEFF_NORMED)
|
||||
loc = np.where(res >= threshold)
|
||||
return [point for point in zip(*loc[::-1])]
|
||||
|
||||
def select_index_enter(
|
||||
self,
|
||||
index: int,
|
||||
main: ModuleBase,
|
||||
insight: bool = True,
|
||||
skip_first_screenshot: bool = True,
|
||||
interval: int = 5
|
||||
) -> bool:
|
||||
if insight and not self.insight_index(index, main, skip_first_screenshot):
|
||||
return False
|
||||
logger.info(f'Select index: {index}')
|
||||
click_interval = Timer(interval)
|
||||
load_index_interval = Timer(1)
|
||||
while 1:
|
||||
if skip_first_screenshot:
|
||||
skip_first_screenshot = False
|
||||
else:
|
||||
main.device.screenshot()
|
||||
|
||||
if load_index_interval.reached_and_reset():
|
||||
self.load_stage_indexes(main=main)
|
||||
|
||||
index_box = next(filter(lambda x: int(x.ocr_text) == index, self.current_indexes), None)
|
||||
|
||||
if index_box is None:
|
||||
logger.warning(f'No index {index} in {self.index_ocr.name}')
|
||||
return False
|
||||
|
||||
stage_item_box = area_pad((0, 0, *area_size(self.stage_item)))
|
||||
search_box = area_offset(stage_item_box, index_box.box[:2])
|
||||
search_image = main.image_crop(search_box)
|
||||
points = self._match_clickable_points(search_image, self.enter.matched_button.image)
|
||||
|
||||
if not points:
|
||||
logger.warning(f'No clickable {self.enter.name}')
|
||||
return False
|
||||
|
||||
point = area_offset((0, 0, *area_size(self.enter.button)), points[0])
|
||||
click_button = ClickButton(area_offset(point, search_box[:2]), name=self.enter.name)
|
||||
|
||||
if click_interval.reached_and_reset():
|
||||
main.device.click(click_button)
|
||||
return True
|
||||
@@ -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
|
||||
@@ -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,
|
||||
)
|
||||
|
||||
@@ -116,8 +116,8 @@ class TacticalChallenge(UI):
|
||||
if self.appear_then_click(CHALLENGE_LOSE):
|
||||
return TCStatus.LOSE
|
||||
case TCStatus.WIN | TCStatus.LOSE:
|
||||
if self.appear(CHALLENGE_WIN) or self.appear(CHALLENGE_LOSE):
|
||||
return TCStatus.RESULT
|
||||
if self.appear_then_click(CHALLENGE_WIN) or self.appear_then_click(CHALLENGE_LOSE):
|
||||
return status
|
||||
is_valid, ticket = self._get_ticket()
|
||||
if not is_valid:
|
||||
return status
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
Deploy:
|
||||
Git:
|
||||
# URL of AzurLaneAutoScript repository
|
||||
# [CN user] Use 'cn' to get update from git-over-cdn service
|
||||
# [Other] Use 'global' to get update from https://github.com/TheFunny/ArisuAutoSrcipt
|
||||
# [CN user] Use 'cn' to get update from self-hosted git service
|
||||
# [Other] Use 'global' to get update from https://github.com/TheFunny/ArisuAutoSweeper
|
||||
Repository: {{repository}}
|
||||
# Branch of Alas
|
||||
# [Developer] Use 'dev', 'app', etc, to try new features
|
||||
|
||||