Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added assets/cn/awaken/OCR_SHIP_EXP.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/cn/os/FLEET_FLAGSHIP.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 10 additions & 0 deletions config/template.json
Original file line number Diff line number Diff line change
Expand Up @@ -1869,6 +1869,11 @@
"Fleet": 1,
"Submarine": false
},
"OpsiCheckLeveling": {
"TargetLevel": 0,
"LastRun": "2020-01-01 00:00:00",
"DelayAfterFull": false
},
"Storage": {
"Storage": {}
}
Expand All @@ -1889,6 +1894,11 @@
"Fleet": 1,
"Submarine": false
},
"OpsiCheckLeveling": {
"TargetLevel": 0,
"LastRun": "2020-01-01 00:00:00",
"DelayAfterFull": false
},
"Storage": {
"Storage": {}
}
Expand Down
45 changes: 45 additions & 0 deletions dev_tools/ship_exp_extract.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
from dev_tools.utils import LuaLoader


class ShipEXP:
def __init__(self):
self.ship_exp = [0] * 125 # Initialize a list for levels 0 to 125
data = LOADER.load('sharecfg/ship_level.lua')
total_exp = 0
for index, exp in data.items():
if not isinstance(index, int) or index >= 124:
continue
total_exp += exp['exp']
self.ship_exp[exp['level']] = total_exp

def encode(self):
lines = []
lines.append('# This file is auto-generated by dev_tools/ship_exp_extract.py.')
lines.append('# Do not edit this file manually.')
lines.append('')
lines.append('LIST_SHIP_EXP = [')
for exp in self.ship_exp:
lines.append(f' {exp},')
lines.append(']')
return lines

def write(self, file):
print(f'writing {file}')
with open(file, 'w', encoding='utf-8') as f:
for text in self.encode():
f.write(text + '\n')


"""
This is an auto-tool to extract accumulative ship leveling exp for operation siren leveling check.

Git clone https://github.com/AzurLaneTools/AzurLaneLuaScripts, to get the decrypted scripts.
Arguments:
FILE: Path to repository, such as 'xxx/AzurLaneLuaScripts'
SAVE: File to save, 'module/os/ship_exp.py'
"""
FOLDER = '../AzurLaneLuaScripts/'
SAVE = 'module/os/ship_exp_data.py'

LOADER = LuaLoader(FOLDER)
ShipEXP().write(SAVE)
1 change: 1 addition & 0 deletions module/awaken/assets.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,6 @@
COST_CHIP = Button(area={'cn': (610, 375, 670, 435), 'en': (610, 375, 670, 435), 'jp': (610, 375, 670, 435), 'tw': (610, 375, 670, 435)}, color={'cn': (157, 188, 190), 'en': (157, 188, 190), 'jp': (157, 188, 190), 'tw': (157, 188, 190)}, button={'cn': (610, 375, 670, 435), 'en': (610, 375, 670, 435), 'jp': (610, 375, 670, 435), 'tw': (610, 375, 670, 435)}, file={'cn': './assets/cn/awaken/COST_CHIP.png', 'en': './assets/cn/awaken/COST_CHIP.png', 'jp': './assets/cn/awaken/COST_CHIP.png', 'tw': './assets/cn/awaken/COST_CHIP.png'})
COST_COIN = Button(area={'cn': (499, 373, 559, 433), 'en': (499, 373, 559, 433), 'jp': (499, 373, 559, 433), 'tw': (499, 373, 559, 433)}, color={'cn': (219, 180, 83), 'en': (219, 180, 83), 'jp': (219, 180, 83), 'tw': (219, 180, 83)}, button={'cn': (499, 373, 559, 433), 'en': (499, 373, 559, 433), 'jp': (499, 373, 559, 433), 'tw': (499, 373, 559, 433)}, file={'cn': './assets/cn/awaken/COST_COIN.png', 'en': './assets/cn/awaken/COST_COIN.png', 'jp': './assets/cn/awaken/COST_COIN.png', 'tw': './assets/cn/awaken/COST_COIN.png'})
LEVEL_UP = Button(area={'cn': (804, 282, 897, 304), 'en': (864, 286, 910, 302), 'jp': (807, 284, 893, 303), 'tw': (805, 282, 893, 304)}, color={'cn': (141, 167, 216), 'en': (130, 158, 213), 'jp': (141, 171, 208), 'tw': (147, 179, 219)}, button={'cn': (804, 282, 897, 304), 'en': (864, 286, 910, 302), 'jp': (807, 284, 893, 303), 'tw': (805, 282, 893, 304)}, file={'cn': './assets/cn/awaken/LEVEL_UP.png', 'en': './assets/en/awaken/LEVEL_UP.png', 'jp': './assets/jp/awaken/LEVEL_UP.png', 'tw': './assets/tw/awaken/LEVEL_UP.png'})
OCR_SHIP_EXP = Button(area={'cn': (1102, 276, 1250, 306), 'en': (1102, 276, 1250, 306), 'jp': (1102, 276, 1250, 306), 'tw': (1102, 276, 1250, 306)}, color={'cn': (255, 255, 255), 'en': (255, 255, 255), 'jp': (255, 255, 255), 'tw': (255, 255, 255)}, button={'cn': (1102, 276, 1250, 306), 'en': (1102, 276, 1250, 306), 'jp': (1102, 276, 1250, 306), 'tw': (1102, 276, 1250, 306)}, file={'cn': './assets/cn/awaken/OCR_SHIP_EXP.png', 'en': './assets/cn/awaken/OCR_SHIP_EXP.png', 'jp': './assets/cn/awaken/OCR_SHIP_EXP.png', 'tw': './assets/cn/awaken/OCR_SHIP_EXP.png'})
OCR_SHIP_LEVEL = Button(area={'cn': (757, 283, 799, 319), 'en': (757, 283, 799, 319), 'jp': (746, 279, 798, 317), 'tw': (757, 283, 799, 319)}, color={'cn': (115, 130, 142), 'en': (115, 130, 142), 'jp': (122, 116, 116), 'tw': (115, 130, 142)}, button={'cn': (757, 283, 799, 319), 'en': (757, 283, 799, 319), 'jp': (746, 279, 798, 317), 'tw': (757, 283, 799, 319)}, file={'cn': './assets/cn/awaken/OCR_SHIP_LEVEL.png', 'en': './assets/cn/awaken/OCR_SHIP_LEVEL.png', 'jp': './assets/jp/awaken/OCR_SHIP_LEVEL.png', 'tw': './assets/cn/awaken/OCR_SHIP_LEVEL.png'})
SHIP_LEVEL_CHECK = Button(area={'cn': (706, 298, 742, 315), 'en': (706, 298, 742, 315), 'jp': (703, 293, 734, 314), 'tw': (706, 298, 742, 315)}, color={'cn': (171, 162, 193), 'en': (171, 162, 193), 'jp': (125, 119, 116), 'tw': (171, 162, 193)}, button={'cn': (706, 298, 742, 315), 'en': (706, 298, 742, 315), 'jp': (703, 293, 734, 314), 'tw': (706, 298, 742, 315)}, file={'cn': './assets/cn/awaken/SHIP_LEVEL_CHECK.png', 'en': './assets/cn/awaken/SHIP_LEVEL_CHECK.png', 'jp': './assets/jp/awaken/SHIP_LEVEL_CHECK.png', 'tw': './assets/cn/awaken/SHIP_LEVEL_CHECK.png'})
2 changes: 2 additions & 0 deletions module/campaign/os_run.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ def opsi_daily(self):
def opsi_meowfficer_farming(self):
try:
campaign = self.load_campaign()
campaign.os_check_leveling()
campaign.os_meowfficer_farming()
except ActionPointLimit:
if get_os_reset_remain() > 0:
Expand All @@ -59,6 +60,7 @@ def opsi_meowfficer_farming(self):
def opsi_hazard1_leveling(self):
try:
campaign = self.load_campaign()
campaign.os_check_leveling()
campaign.os_hazard1_leveling()
except ActionPointLimit:
self.config.task_delay(server_update=True)
Expand Down
30 changes: 30 additions & 0 deletions module/config/argument/args.json
Original file line number Diff line number Diff line change
Expand Up @@ -9063,6 +9063,21 @@
"value": false
}
},
"OpsiCheckLeveling": {
"TargetLevel": {
"type": "input",
"value": 0
},
"LastRun": {
"type": "datetime",
"value": "2020-01-01 00:00:00",
"validate": "datetime"
},
"DelayAfterFull": {
"type": "checkbox",
"value": false
}
},
"Storage": {
"Storage": {
"type": "storage",
Expand Down Expand Up @@ -9136,6 +9151,21 @@
"display": "hide"
}
},
"OpsiCheckLeveling": {
"TargetLevel": {
"type": "input",
"value": 0
},
"LastRun": {
"type": "datetime",
"value": "2020-01-01 00:00:00",
"validate": "datetime"
},
"DelayAfterFull": {
"type": "checkbox",
"value": false
}
},
"Storage": {
"Storage": {
"type": "storage",
Expand Down
4 changes: 4 additions & 0 deletions module/config/argument/argument.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -731,6 +731,10 @@ OpsiHazard1Leveling:
TargetZone:
value: 0
option: [ 0, 44, 22 ]
OpsiCheckLeveling:
TargetLevel: 0
LastRun: 2020-01-01 00:00:00
DelayAfterFull: false

# ==================== Tools ====================

Expand Down
2 changes: 2 additions & 0 deletions module/config/argument/task.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -318,10 +318,12 @@ Opsi:
- Scheduler
- OpsiMeowfficerFarming
- OpsiFleet
- OpsiCheckLeveling
OpsiHazard1Leveling:
- Scheduler
- OpsiHazard1Leveling
- OpsiFleet
- OpsiCheckLeveling
OpsiCrossMonth:
- Scheduler

Expand Down
5 changes: 5 additions & 0 deletions module/config/config_generated.py
Original file line number Diff line number Diff line change
Expand Up @@ -435,6 +435,11 @@ class GeneratedConfig:
# Group `OpsiHazard1Leveling`
OpsiHazard1Leveling_TargetZone = 0 # 0, 44, 22

# Group `OpsiCheckLeveling`
OpsiCheckLeveling_TargetLevel = 0
OpsiCheckLeveling_LastRun = datetime.datetime(2020, 1, 1, 0, 0)
OpsiCheckLeveling_DelayAfterFull = False

# Group `Daemon`
Daemon_EnterMap = True

Expand Down
18 changes: 18 additions & 0 deletions module/config/i18n/en-US.json
Original file line number Diff line number Diff line change
Expand Up @@ -2543,6 +2543,24 @@
"22": "22 | NA Ocean SW Sector B"
}
},
"OpsiCheckLeveling": {
"_info": {
"name": "Daily Leveling Check",
"help": "Check if all ships in current fleet have received enough experience to reach the target level\nIf yes, then Alas will push a message.\n'Error notify config' should be set first."
},
"TargetLevel": {
"name": "Push when all ships received enough experience to reach target level X",
"help": "0 means no limit"
},
"LastRun": {
"name": "Last Check Time",
"help": "Automatically updated with the last check time, generally does not need to be modified"
},
"DelayAfterFull": {
"name": "Delay task when target level reached",
"help": ""
}
},
"Daemon": {
"_info": {
"name": "Semi-auto Clicking",
Expand Down
18 changes: 18 additions & 0 deletions module/config/i18n/ja-JP.json
Original file line number Diff line number Diff line change
Expand Up @@ -2543,6 +2543,24 @@
"22": "22"
}
},
"OpsiCheckLeveling": {
"_info": {
"name": "OpsiCheckLeveling._info.name",
"help": "OpsiCheckLeveling._info.help"
},
"TargetLevel": {
"name": "OpsiCheckLeveling.TargetLevel.name",
"help": "OpsiCheckLeveling.TargetLevel.help"
},
"LastRun": {
"name": "OpsiCheckLeveling.LastRun.name",
"help": "OpsiCheckLeveling.LastRun.help"
},
"DelayAfterFull": {
"name": "OpsiCheckLeveling.DelayAfterFull.name",
"help": "OpsiCheckLeveling.DelayAfterFull.help"
}
},
"Daemon": {
"_info": {
"name": "Daemon._info.name",
Expand Down
18 changes: 18 additions & 0 deletions module/config/i18n/zh-CN.json
Original file line number Diff line number Diff line change
Expand Up @@ -2543,6 +2543,24 @@
"22": "22 | NA海域西南B"
}
},
"OpsiCheckLeveling": {
"_info": {
"name": "每日经验检测",
"help": "检测出击舰队所有船是否已经获取满经验,是的话则发送一条推送消息\n需要先设置“错误推送设置”"
},
"TargetLevel": {
"name": "所有舰船获取到可升级至X级的经验后推送",
"help": "0表示不限制等级"
},
"LastRun": {
"name": "上次检查时间",
"help": "记录上一次检查的时间以防止任务重复运行,检查间隔为1天,这个数值是自动记录的,一般不需要修改"
},
"DelayAfterFull": {
"name": "到达目标等级后推迟任务",
"help": ""
}
},
"Daemon": {
"_info": {
"name": "半自动点击",
Expand Down
18 changes: 18 additions & 0 deletions module/config/i18n/zh-TW.json
Original file line number Diff line number Diff line change
Expand Up @@ -2543,6 +2543,24 @@
"22": "22 | NA海域西南B"
}
},
"OpsiCheckLeveling": {
"_info": {
"name": "每日經驗檢測",
"help": "檢測出擊艦隊所有艦是否已經獲得滿經驗,若是則發送一條推送消息\n需要先設定「錯誤推送設定」"
},
"TargetLevel": {
"name": "所有艦船獲得到可升級至 X 級的經驗後推送",
"help": "0 表示不限制等級"
},
"LastRun": {
"name": "上次檢查時間",
"help": "記錄上一次檢查的時間以防止任務重複運行,檢查間隔為1天,該數值是自動記錄的,一般不需要修改"
},
"DelayAfterFull": {
"name": "達到目標等級後延遲任務",
"help": ""
}
},
"Daemon": {
"_info": {
"name": "半自動點擊",
Expand Down
1 change: 1 addition & 0 deletions module/os/assets.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
FLEET_BAR = Button(area={'cn': (145, 414, 345, 616), 'en': (145, 414, 345, 616), 'jp': (145, 414, 346, 617), 'tw': (145, 414, 346, 616)}, color={'cn': (152, 171, 192), 'en': (144, 161, 179), 'jp': (150, 168, 188), 'tw': (152, 172, 194)}, button={'cn': (145, 414, 345, 616), 'en': (145, 414, 345, 616), 'jp': (145, 414, 346, 617), 'tw': (145, 414, 346, 616)}, file={'cn': './assets/cn/os/FLEET_BAR.png', 'en': './assets/en/os/FLEET_BAR.png', 'jp': './assets/jp/os/FLEET_BAR.png', 'tw': './assets/tw/os/FLEET_BAR.png'})
FLEET_CHOOSE = Button(area={'cn': (270, 636, 345, 699), 'en': (144, 636, 238, 699), 'jp': (245, 642, 329, 691), 'tw': (247, 642, 337, 690)}, color={'cn': (112, 189, 245), 'en': (119, 165, 239), 'jp': (122, 187, 245), 'tw': (118, 183, 237)}, button={'cn': (270, 636, 345, 699), 'en': (144, 636, 238, 699), 'jp': (245, 642, 329, 691), 'tw': (247, 642, 337, 690)}, file={'cn': './assets/cn/os/FLEET_CHOOSE.png', 'en': './assets/en/os/FLEET_CHOOSE.png', 'jp': './assets/jp/os/FLEET_CHOOSE.png', 'tw': './assets/tw/os/FLEET_CHOOSE.png'})
FLEET_EMP_DEBUFF = Button(area={'cn': (137, 144, 175, 167), 'en': (137, 144, 175, 167), 'jp': (137, 144, 175, 167), 'tw': (137, 144, 175, 167)}, color={'cn': (180, 167, 191), 'en': (180, 167, 191), 'jp': (180, 167, 191), 'tw': (180, 167, 191)}, button={'cn': (137, 144, 175, 167), 'en': (137, 144, 175, 167), 'jp': (137, 144, 175, 167), 'tw': (137, 144, 175, 167)}, file={'cn': './assets/cn/os/FLEET_EMP_DEBUFF.png', 'en': './assets/en/os/FLEET_EMP_DEBUFF.png', 'jp': './assets/jp/os/FLEET_EMP_DEBUFF.png', 'tw': './assets/tw/os/FLEET_EMP_DEBUFF.png'})
FLEET_FLAGSHIP = Button(area={'cn': (14, 122, 108, 215), 'en': (14, 122, 108, 215), 'jp': (14, 122, 108, 215), 'tw': (14, 122, 108, 215)}, color={'cn': (255, 255, 255), 'en': (255, 255, 255), 'jp': (255, 255, 255), 'tw': (255, 255, 255)}, button={'cn': (14, 122, 108, 215), 'en': (14, 122, 108, 215), 'jp': (14, 122, 108, 215), 'tw': (14, 122, 108, 215)}, file={'cn': './assets/cn/os/FLEET_FLAGSHIP.png', 'en': './assets/cn/os/FLEET_FLAGSHIP.png', 'jp': './assets/cn/os/FLEET_FLAGSHIP.png', 'tw': './assets/cn/os/FLEET_FLAGSHIP.png'})
GLOBE_GOTO_MAP = Button(area={'cn': (37, 29, 83, 75), 'en': (37, 29, 83, 75), 'jp': (37, 29, 83, 75), 'tw': (37, 29, 83, 75)}, color={'cn': (112, 119, 157), 'en': (112, 119, 157), 'jp': (112, 119, 157), 'tw': (112, 119, 157)}, button={'cn': (37, 29, 83, 75), 'en': (37, 29, 83, 75), 'jp': (37, 29, 83, 75), 'tw': (37, 29, 83, 75)}, file={'cn': './assets/cn/os/GLOBE_GOTO_MAP.png', 'en': './assets/en/os/GLOBE_GOTO_MAP.png', 'jp': './assets/jp/os/GLOBE_GOTO_MAP.png', 'tw': './assets/tw/os/GLOBE_GOTO_MAP.png'})
MAP_EXIT = Button(area={'cn': (1147, 637, 1280, 699), 'en': (1148, 641, 1280, 699), 'jp': (1147, 637, 1280, 699), 'tw': (1147, 639, 1280, 703)}, color={'cn': (47, 35, 42), 'en': (32, 20, 20), 'jp': (58, 34, 34), 'tw': (55, 46, 43)}, button={'cn': (1147, 637, 1280, 699), 'en': (1148, 641, 1280, 699), 'jp': (1147, 637, 1280, 699), 'tw': (1147, 639, 1280, 703)}, file={'cn': './assets/cn/os/MAP_EXIT.png', 'en': './assets/en/os/MAP_EXIT.png', 'jp': './assets/jp/os/MAP_EXIT.png', 'tw': './assets/tw/os/MAP_EXIT.png'})
MAP_GOTO_GLOBE = Button(area={'cn': (1069, 641, 1260, 695), 'en': (1069, 641, 1260, 691), 'jp': (1064, 636, 1265, 699), 'tw': (1069, 641, 1260, 694)}, color={'cn': (212, 140, 140), 'en': (212, 140, 140), 'jp': (207, 132, 132), 'tw': (213, 143, 143)}, button={'cn': (1069, 641, 1260, 695), 'en': (1069, 641, 1260, 691), 'jp': (1064, 636, 1265, 699), 'tw': (1069, 641, 1260, 694)}, file={'cn': './assets/cn/os/MAP_GOTO_GLOBE.png', 'en': './assets/en/os/MAP_GOTO_GLOBE.png', 'jp': './assets/jp/os/MAP_GOTO_GLOBE.png', 'tw': './assets/tw/os/MAP_GOTO_GLOBE.png'})
Expand Down
2 changes: 2 additions & 0 deletions module/os/operation_siren.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from module.os.config import OSConfig
from module.os.tasks.abyssal import OpsiAbyssal
from module.os.tasks.archive import OpsiArchive
from module.os.tasks.check_leveling import OpsiCheckLeveling
from module.os.tasks.cross_month import OpsiCrossMonth
from module.os.tasks.daily import OpsiDaily
from module.os.tasks.explore import OpsiExplore
Expand All @@ -27,6 +28,7 @@ class OperationSiren(
OpsiMonthBoss,
OpsiExplore,
OpsiCrossMonth,
OpsiCheckLeveling,
):
"""
Operation Siren main class that combines all task modules.
Expand Down
83 changes: 83 additions & 0 deletions module/os/ship_exp.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import re

from module.awaken.assets import OCR_SHIP_LEVEL, OCR_SHIP_EXP
from module.base.timer import Timer
from module.logger import logger
from module.ocr.ocr import Ocr, Digit


class ShipLevel(Digit):
def after_process(self, result):
result = super().after_process(result)
if result < 1 or result > 125:
logger.warning('Unexpected ship level')
result = 0
return result


class ShipExp(Ocr):
def __init__(self, buttons, lang='azur_lane', letter=(255, 255, 255), threshold=64, alphabet='0123456789IDSBM/',
name=None):
super().__init__(buttons, lang=lang, letter=letter, threshold=threshold, alphabet=alphabet, name=name)

def after_process(self, result):
result = super().after_process(result)
result = result.replace('I', '1').replace('D', '0').replace('S', '5')
result = result.replace('B', '8')
return result

def ocr(self, image, direct_ocr=False):
"""
Do OCR on a exp info, such as `100000/205000` or `3000000/Max`.

Args:
image:
direct_ocr:

Returns:
list, int: exp digit, or a list of it.
"""
result_list = super().ocr(image, direct_ocr=direct_ocr)
result = result_list[0] if isinstance(result_list, list) else result_list

result = re.search(r'(\d+)/', result)
if result:
result = [int(s) for s in result.groups()]
current = int(result[0])
return current
else:
logger.warning(f'Unexpected ocr result: {result_list}')
return 0

def ship_info_get_level_exp(main, skip_first_screenshot=True):
"""
Get ship level and exp from image.

Args:
image: Image to do OCR on.

Returns:
ShipLevel: Ship level and exp.
"""
ocr_exp = ShipExp(OCR_SHIP_EXP, name='ShipExp')
ocr_level = ShipLevel(OCR_SHIP_LEVEL, name='ShipLevel')
timeout = Timer(2, count=4).start()
level = 0
exp = 0
while 1:
if skip_first_screenshot:
skip_first_screenshot = False
else:
main.device.screenshot()

level = ocr_level.ocr(main.device.image)
exp = ocr_exp.ocr(main.device.image)

if timeout.reached():
logger.warning('ship_info_get_level_exp timeout')
return level, exp
if level > 0:
if exp > 0:
return level, exp
else:
continue
Loading