mirror of
https://github.com/LmeSzinc/StarRailCopilot.git
synced 2024-11-30 19:31:56 +00:00
5434209893
- this was causing error when triggered app restart
606 lines
21 KiB
Python
606 lines
21 KiB
Python
import codecs
|
|
import configparser
|
|
import copy
|
|
import os
|
|
from datetime import timezone
|
|
|
|
import cv2
|
|
import numpy as np
|
|
from PIL import Image
|
|
|
|
import module.config.server as server
|
|
from module.base.timer import *
|
|
from module.config.dictionary import *
|
|
from module.logger import logger
|
|
|
|
|
|
class AzurLaneConfig:
|
|
"""
|
|
Basic Config.
|
|
"""
|
|
CONFIG_FILE = ''
|
|
config = configparser.ConfigParser(interpolation=None)
|
|
start_time = datetime.now()
|
|
|
|
SERVER = server.server
|
|
logger.attr('Server', SERVER)
|
|
|
|
"""
|
|
Fleet
|
|
"""
|
|
ENABLE_FLEET_CONTROL = True
|
|
# Fleet 1-6, if empty use 0.
|
|
_FLEET_1 = 1
|
|
FLEET_2 = 2
|
|
FLEET_3 = 3
|
|
# Formation 1-3.
|
|
_FLEET_1_FORMATION = 2
|
|
FLEET_2_FORMATION = 2
|
|
FLEET_3_FORMATION = 2
|
|
# Fleet step 1-6
|
|
_FLEET_1_STEP = 3
|
|
FLEET_2_STEP = 2
|
|
FLEET_3_STEP = 3
|
|
# Fleet 1-2, if empty use 0.
|
|
SUBMARINE = 0
|
|
|
|
USING_SPARE_FLEET = False
|
|
|
|
@property
|
|
def FLEET_1(self):
|
|
return self.FLEET_3 if self.USING_SPARE_FLEET else self._FLEET_1
|
|
|
|
@FLEET_1.setter
|
|
def FLEET_1(self, value):
|
|
self._FLEET_1 = value
|
|
|
|
@property
|
|
def FLEET_1_FORMATION(self):
|
|
return self.FLEET_3_FORMATION if self.USING_SPARE_FLEET else self._FLEET_1_FORMATION
|
|
|
|
@FLEET_1_FORMATION.setter
|
|
def FLEET_1_FORMATION(self, value):
|
|
self._FLEET_1_FORMATION = value
|
|
|
|
@property
|
|
def FLEET_1_STEP(self):
|
|
return self.FLEET_3_STEP if self.USING_SPARE_FLEET else self._FLEET_1_STEP
|
|
|
|
@FLEET_1_STEP.setter
|
|
def FLEET_1_STEP(self, value):
|
|
self._FLEET_1_STEP = value
|
|
|
|
"""
|
|
module.assets
|
|
"""
|
|
ASSETS_FOLDER = './assets'
|
|
|
|
"""
|
|
module.base
|
|
"""
|
|
COLOR_SIMILAR_THRESHOLD = 10
|
|
BUTTON_OFFSET = 30
|
|
BUTTON_MATCH_SIMILARITY = 0.85
|
|
SLEEP_AFTER_CLICK = 0
|
|
WAIT_BEFORE_SAVING_SCREEN_SHOT = 1
|
|
|
|
"""
|
|
module.combat
|
|
"""
|
|
ENABLE_SAVE_GET_ITEMS = True
|
|
ENABLE_MAP_FLEET_LOCK = True
|
|
SUBMARINE_MODE = ''
|
|
SUBMARINE_CALL_AT_BOSS = False
|
|
COMBAT_AUTO_MODE = 'combat_auto'
|
|
COMBAT_SCREENSHOT_INTERVAL = 2
|
|
|
|
"""
|
|
module.combat.hp_balance
|
|
"""
|
|
ENABLE_HP_BALANCE = False
|
|
ENABLE_LOW_HP_WITHDRAW = True
|
|
SCOUT_HP_DIFFERENCE_THRESHOLD = 0.2
|
|
SCOUT_HP_WEIGHTS = [1000, 1000, 1000]
|
|
EMERGENCY_REPAIR_SINGLE_THRESHOLD = 0.3
|
|
EMERGENCY_REPAIR_HOLE_THRESHOLD = 0.6
|
|
LOW_HP_WITHDRAW_THRESHOLD = 0.2
|
|
|
|
"""
|
|
module.campaign
|
|
"""
|
|
CAMPAIGN_NAME = 'default'
|
|
CAMPAIGN_MODE = 'normal'
|
|
|
|
ENABLE_STOP_CONDITION = True
|
|
ENABLE_FAST_FORWARD = True
|
|
STOP_IF_OIL_LOWER_THAN = 5000
|
|
STOP_IF_COUNT_GREATER_THAN = 0
|
|
STOP_IF_TIME_REACH = 0
|
|
STOP_IF_TRIGGER_EMOTION_LIMIT = False
|
|
STOP_IF_DOCK_FULL = False
|
|
|
|
ENABLE_MAP_CLEAR_MODE = False
|
|
CLEAR_MODE_STOP_CONDITION = 'map_green' # map_green, map_3_star, map_100
|
|
MAP_STAR_CLEAR_ALL = 3
|
|
MAP_CLEAR_ALL_THIS_TIME = False
|
|
|
|
"""
|
|
module.event
|
|
"""
|
|
EVENT_NAME = ''
|
|
CAMPAIGN_EVENT = ''
|
|
EVENT_NAME_AB = ''
|
|
|
|
"""
|
|
module.combat.emotion
|
|
"""
|
|
ENABLE_EMOTION_REDUCE = True
|
|
IGNORE_LOW_EMOTION_WARN = False
|
|
EMOTION_LIMIT_TRIGGERED = False
|
|
TIME_FORMAT = '%Y-%m-%d_%H:%M:%S'
|
|
# 20, 30, 40, 50, 60
|
|
FLEET_1_RECOVER_PER_HOUR = 50
|
|
FLEET_1_EMOTION_LIMIT = 120
|
|
FLEET_2_RECOVER_PER_HOUR = 20
|
|
FLEET_2_EMOTION_LIMIT = 50
|
|
FLEET_3_RECOVER_PER_HOUR = 20
|
|
FLEET_3_EMOTION_LIMIT = 50
|
|
|
|
"""
|
|
module.device
|
|
"""
|
|
SERIAL = ''
|
|
PACKAGE_NAME = ''
|
|
COMMAND = ''
|
|
USE_ADB_SCREENSHOT = True
|
|
USE_ADB_CONTROL = False
|
|
SCREEN_SHOT_SAVE_FOLDER_BASE = './screenshot'
|
|
SCREEN_SHOT_SAVE_FOLDER = ''
|
|
SCREEN_SHOT_SAVE_INTERVAL = 5 # Seconds between two save. Saves in the interval will be dropped.
|
|
|
|
"""
|
|
module.daily
|
|
"""
|
|
ENABLE_DAILY_MISSION = True
|
|
FLEET_DAILY = 3
|
|
FLEET_DAILY_EQUIPMENT = [1, 1, 1, 1, 1, 1]
|
|
DAILY_CHOOSE = {
|
|
4: 1, # 商船护送
|
|
5: 1, # 海域突进
|
|
1: 2, # 战术研修, 1航空 2炮击 3雷击
|
|
2: 1, # 斩首行动
|
|
3: 1, # 破交作战
|
|
}
|
|
|
|
"""
|
|
module.hard
|
|
"""
|
|
ENABLE_HARD_CAMPAIGN = True
|
|
HARD_CAMPAIGN = '10-4'
|
|
FLEET_HARD = 1
|
|
FLEET_HARD_EQUIPMENT = [1, 1, 1, 1, 1, 1]
|
|
|
|
"""
|
|
module.exercise
|
|
"""
|
|
ENABLE_EXERCISE = True
|
|
EXERCISE_CHOOSE_MODE = 'max_exp'
|
|
EXERCISE_PRESERVE = 0
|
|
LOW_HP_THRESHOLD = 0.40
|
|
LOW_HP_CONFIRM_WAIT = 1.0
|
|
OPPONENT_CHALLENGE_TRIAL = 1
|
|
EXERCISE_FLEET_EQUIPMENT = [1, 1, 1, 1, 1, 1]
|
|
|
|
"""
|
|
error_log
|
|
"""
|
|
PERSPECTIVE_ERROR_LOG_FOLDER = './log/perspective_error'
|
|
ERROR_LOG_FOLDER = './log/error'
|
|
ENABLE_ERROR_LOG_AND_SCREENSHOT_SAVE = True
|
|
ENABLE_PERSPECTIVE_ERROR_IMAGE_SAVE = False
|
|
|
|
"""
|
|
module.map.fleet
|
|
"""
|
|
MAP_HAS_AMBUSH = True
|
|
MAP_HAS_FLEET_STEP = False
|
|
MAP_HAS_MOVABLE_ENEMY = False
|
|
MAP_HAS_SIREN = False
|
|
MAP_HAS_DYNAMIC_RED_BORDER = False
|
|
MAP_HAS_MAP_STORY = False # event_20200521_cn(穹顶下的圣咏曲) adds after-combat story.
|
|
MAP_HAS_WALL = False # event_20200521_cn(穹顶下的圣咏曲) adds wall between grids.
|
|
MAP_SIREN_MOVE_WAIT = 1.5 # The enemy moving takes about 1.2 ~ 1.5s.
|
|
MAP_SIREN_TEMPLATE = ['1', '2', '3', 'DD']
|
|
MAP_SIREN_COUNT = 0
|
|
MAP_MYSTERY_HAS_CARRIER = False
|
|
MAP_GRID_CENTER_TOLERANCE = 0.1
|
|
|
|
POOR_MAP_DATA = False
|
|
FLEET_BOSS = 2
|
|
CAMERA_SWIPE_MULTIPLY_X = 200
|
|
CAMERA_SWIPE_MULTIPLY_Y = 140
|
|
|
|
"""
|
|
module.retire
|
|
"""
|
|
ENABLE_RETIREMENT = True
|
|
USE_ONE_CLICK_RETIREMENT = False
|
|
RETIREMENT_METHOD = 'one_click_retire' # enhance, old_retire, one_click_retire
|
|
ENHANCE_FAVOURITE = False
|
|
DOCK_FULL_TRIGGERED = False
|
|
RETIRE_AMOUNT = 'all' # all, 10
|
|
RETIRE_N = True
|
|
RETIRE_R = False
|
|
RETIRE_SR = False
|
|
RETIRE_SSR = False
|
|
|
|
"""
|
|
module.map.perspective
|
|
"""
|
|
# Screen
|
|
SCREEN_SIZE = (1280, 720)
|
|
DETECTING_AREA = (123, 55, 1280, 720)
|
|
SCREEN_CENTER = (SCREEN_SIZE[0] / 2, SCREEN_SIZE[1] / 2)
|
|
MID_Y = SCREEN_CENTER[1]
|
|
# UI mask
|
|
UI_MASK_FILE = './module/map/ui_mask.png'
|
|
UI_MASK_PIL = Image.open(UI_MASK_FILE).convert('L')
|
|
UI_MASK = np.array(UI_MASK_PIL)
|
|
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
|
|
UI_MASK_STROKE = cv2.erode(UI_MASK, kernel).astype('uint8')
|
|
|
|
# Parameters for scipy.signal.find_peaks
|
|
# https://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.find_peaks.html
|
|
INTERNAL_LINES_FIND_PEAKS_PARAMETERS = {
|
|
'height': (150, 255 - 40),
|
|
'width': (0.9, 10),
|
|
'prominence': 10,
|
|
'distance': 35,
|
|
}
|
|
EDGE_LINES_FIND_PEAKS_PARAMETERS = {
|
|
'height': (255 - 24, 255),
|
|
'prominence': 10,
|
|
'distance': 50,
|
|
# 'width': (0, 7),
|
|
'wlen': 1000
|
|
}
|
|
# Parameters for cv2.HoughLines
|
|
INTERNAL_LINES_HOUGHLINES_THRESHOLD = 75
|
|
EDGE_LINES_HOUGHLINES_THRESHOLD = 75
|
|
# Parameters for lines pre-cleansing
|
|
HORIZONTAL_LINES_THETA_THRESHOLD = 0.005
|
|
VERTICAL_LINES_THETA_THRESHOLD = 18
|
|
TRUST_EDGE_LINES = False # True to use edge to crop inner, false to use inner to crop edge
|
|
# Parameters for perspective calculating
|
|
VANISH_POINT_RANGE = ((540, 740), (-3000, -1000))
|
|
DISTANCE_POINT_X_RANGE = ((-3200, -1600),)
|
|
# Parameters for line cleansing
|
|
COINCIDENT_POINT_ENCOURAGE_DISTANCE = 3
|
|
ERROR_LINES_TOLERANCE = (-10, 10)
|
|
MID_DIFF_RANGE_H = (129 - 3, 129 + 3)
|
|
MID_DIFF_RANGE_V = (129 - 3, 129 + 3)
|
|
|
|
"""
|
|
module.daemon
|
|
"""
|
|
ENABLE_SEMI_MAP_PREPARATION = True
|
|
ENABLE_SEMI_STORY_SKIP = True
|
|
|
|
"""
|
|
module.reward
|
|
"""
|
|
ENABLE_REWARD = True
|
|
REWARD_INTERVAL = 20
|
|
REWARD_LAST_TIME = datetime.now()
|
|
ENABLE_OIL_REWARD = True
|
|
ENABLE_COIN_REWARD = True
|
|
ENABLE_MISSION_REWARD = True
|
|
ENABLE_COMMISSION_REWARD = True
|
|
ENABLE_TACTICAL_REWARD = True
|
|
|
|
COMMISSION_PRIORITY = {
|
|
'major_comm': 0,
|
|
'daily_comm': 100,
|
|
'extra_drill': 20,
|
|
'extra_part': 60,
|
|
'extra_cube': 80,
|
|
'extra_oil': 90,
|
|
'extra_book': 70,
|
|
'urgent_drill': 45,
|
|
'urgent_part': 95,
|
|
'urgent_book': 145,
|
|
'urgent_box': 195,
|
|
'urgent_cube': 165,
|
|
'urgent_gem': 205,
|
|
'urgent_ship': 155,
|
|
'expire_shorter_than_2': 11,
|
|
'expire_longer_than_6': -11,
|
|
'duration_shorter_than_2': 11,
|
|
'duration_longer_than_6': -11,
|
|
}
|
|
COMMISSION_TIME_LIMIT = 0
|
|
|
|
TACTICAL_BOOK_TIER = 2
|
|
TACTICAL_EXP_FIRST = True
|
|
TACTICAL_BOOK_TIER_NIGHT = 3
|
|
TACTICAL_EXP_FIRST_NIGHT = False
|
|
TACTICAL_NIGHT_RANGE = future_time_range('23:30-06:30') # (Night start, night end), datetime.datetime instance.
|
|
|
|
"""
|
|
C_7_2_mystery_farming
|
|
"""
|
|
C72_BOSS_FLEET_STEP_ON_A3 = True
|
|
|
|
"""
|
|
C_12_2_leveling
|
|
"""
|
|
C122_S3_TOLERANCE = 0
|
|
|
|
"""
|
|
C_12_4_leveling
|
|
"""
|
|
C124_NON_S3_ENTER_TOLERANCE = 1
|
|
C124_NON_S3_WITHDRAW_TOLERANCE = 0
|
|
C124_AMMO_PICK_UP = 3
|
|
|
|
def create_folder(self):
|
|
for folder in [self.ASSETS_FOLDER, self.PERSPECTIVE_ERROR_LOG_FOLDER, self.ERROR_LOG_FOLDER]:
|
|
if folder and not os.path.exists(folder):
|
|
os.mkdir(folder)
|
|
self.SCREEN_SHOT_SAVE_FOLDER = self.SCREEN_SHOT_SAVE_FOLDER_BASE + '/' + self.CAMPAIGN_NAME
|
|
if self.ENABLE_SAVE_GET_ITEMS and len(self.SCREEN_SHOT_SAVE_FOLDER_BASE.strip()):
|
|
for folder in [self.SCREEN_SHOT_SAVE_FOLDER_BASE, self.SCREEN_SHOT_SAVE_FOLDER]:
|
|
if folder and not os.path.exists(folder):
|
|
os.mkdir(folder)
|
|
|
|
def merge(self, other):
|
|
"""
|
|
Args:
|
|
other (AzurLaneConfig, Config):
|
|
|
|
Returns:
|
|
AzurLaneConfig
|
|
"""
|
|
config = copy.copy(self)
|
|
for attr in dir(config):
|
|
if attr.endswith('__'):
|
|
continue
|
|
if hasattr(other, attr):
|
|
value = other.__getattribute__(attr)
|
|
if value is not None:
|
|
config.__setattr__(attr, value)
|
|
|
|
return config
|
|
|
|
def load_config_file(self, name='main'):
|
|
self.CONFIG_FILE = f'./config/{name}.ini'
|
|
self.config.read_file(codecs.open(self.CONFIG_FILE, "r", "utf8"))
|
|
self.load_from_config(self.config)
|
|
self.config_check()
|
|
|
|
def config_check(self):
|
|
if self.FLEET_1 == self.FLEET_2:
|
|
logger.warning(f'Mob fleet [{self.FLEET_1}] and boss fleet [{self.FLEET_2}] is the same')
|
|
logger.warning('They should to be set to different fleets')
|
|
exit(1)
|
|
if self.COMMAND.lower() == 'main' and self.CAMPAIGN_NAME.startswith('campaign_'):
|
|
if int(self.CAMPAIGN_NAME.split('_')[1]) >= 7 and self.FLEET_2 == 0:
|
|
logger.warning('You should use 2 fleets from chapter 7 to 13')
|
|
logger.warning(f'Current: mob fleet [{self.FLEET_1}], boss fleet [{self.FLEET_2}]')
|
|
exit(1)
|
|
|
|
def save(self):
|
|
self.config.write(codecs.open(self.CONFIG_FILE, "w+", "utf8"))
|
|
|
|
def load_from_config(self, config):
|
|
"""
|
|
Args:
|
|
config(configparser.ConfigParser):
|
|
"""
|
|
self.COMMAND = config.get('Command', 'command')
|
|
|
|
# Emulator
|
|
option = config['Emulator']
|
|
self.SERIAL = option['serial']
|
|
self.PACKAGE_NAME = option['package_name'].strip()
|
|
self.ENABLE_ERROR_LOG_AND_SCREENSHOT_SAVE = to_bool(option['enable_error_log_and_screenshot_save'])
|
|
self.ENABLE_PERSPECTIVE_ERROR_IMAGE_SAVE = to_bool(option['enable_perspective_error_image_save'])
|
|
self.USE_ADB_SCREENSHOT = to_bool(option['use_adb_screenshot'])
|
|
self.USE_ADB_CONTROL = to_bool(option['use_adb_control'])
|
|
self.COMBAT_SCREENSHOT_INTERVAL = float(option['combat_screenshot_interval'])
|
|
|
|
option = config['Setting']
|
|
# Stop condition
|
|
self.ENABLE_STOP_CONDITION = to_bool(option['enable_stop_condition'])
|
|
self.ENABLE_FAST_FORWARD = to_bool(option['enable_fast_forward'])
|
|
self.STOP_IF_COUNT_GREATER_THAN = int(option['if_count_greater_than'])
|
|
if not option['if_time_reach'].isdigit():
|
|
self.STOP_IF_TIME_REACH = future_time(option['if_time_reach'])
|
|
else:
|
|
self.STOP_IF_TIME_REACH = 0
|
|
self.STOP_IF_OIL_LOWER_THAN = int(option['if_oil_lower_than'])
|
|
self.STOP_IF_TRIGGER_EMOTION_LIMIT = to_bool(option['if_trigger_emotion_control'])
|
|
self.STOP_IF_DOCK_FULL = to_bool(option['if_dock_full'])
|
|
# Fleet
|
|
self.ENABLE_FLEET_CONTROL = to_bool(option['enable_fleet_control'])
|
|
self.ENABLE_MAP_FLEET_LOCK = to_bool(option['enable_map_fleet_lock'])
|
|
for n in ['1', '2', '3']:
|
|
self.__setattr__(f'FLEET_{n}', int(option[f'fleet_index_{n}']) if to_bool(option[f'fleet_index_{n}']) else 0)
|
|
self.__setattr__(f'FLEET_{n}_FORMATION', int(option[f'fleet_formation_{n}'].split('_')[1]))
|
|
self.__setattr__(f'FLEET_{n}_STEP', int(option[f'fleet_step_{n}']))
|
|
self.COMBAT_AUTO_MODE = option['combat_auto_mode']
|
|
self.SUBMARINE = int(option['fleet_index_4']) if to_bool(option['fleet_index_4']) else 0
|
|
self.SUBMARINE_MODE = option['submarine_mode']
|
|
self.SUBMARINE_CALL_AT_BOSS = option['submarine_mode'] == 'when_boss_combat_boss_appear'
|
|
# Emotion
|
|
self.ENABLE_EMOTION_REDUCE = to_bool(option['enable_emotion_reduce'])
|
|
self.IGNORE_LOW_EMOTION_WARN = to_bool(option['ignore_low_emotion_warn'])
|
|
for n in ['1', '2', '3']:
|
|
recover = dic_emotion_recover[option[f'emotion_recover_{n}']]
|
|
recover += 10 if to_bool(option[f'hole_fleet_married_{n}']) else 0
|
|
self.__setattr__(f'FLEET_{n}_RECOVER_PER_HOUR', recover)
|
|
self.__setattr__(f'FLEET_{n}_EMOTION_LIMIT', dic_emotion_limit[option[f'emotion_control_{n}']])
|
|
# HP balance, save get items -> combat
|
|
self.ENABLE_HP_BALANCE = to_bool(option['enable_hp_balance'])
|
|
self.ENABLE_LOW_HP_WITHDRAW = to_bool(option['enable_low_hp_withdraw'])
|
|
self.SCOUT_HP_DIFFERENCE_THRESHOLD = float(option['scout_hp_difference_threshold'])
|
|
self.SCOUT_HP_WEIGHTS = to_list(option['scout_hp_weights'])
|
|
self.EMERGENCY_REPAIR_SINGLE_THRESHOLD = float(option['emergency_repair_single_threshold'])
|
|
self.EMERGENCY_REPAIR_HOLE_THRESHOLD = float(option['emergency_repair_hole_threshold'])
|
|
self.LOW_HP_WITHDRAW_THRESHOLD = float(option['low_hp_withdraw_threshold'])
|
|
self.ENABLE_SAVE_GET_ITEMS = to_bool(option['enable_drop_screenshot'])
|
|
self.SCREEN_SHOT_SAVE_FOLDER_BASE = option['drop_screenshot_folder']
|
|
# Retirement
|
|
self.ENABLE_RETIREMENT = to_bool(option['enable_retirement'])
|
|
self.RETIREMENT_METHOD = option['retire_method']
|
|
self.RETIRE_AMOUNT = option['retire_amount'].split('_')[1]
|
|
self.ENHANCE_FAVOURITE = to_bool(option['enhance_favourite'])
|
|
for r in ['n', 'r', 'sr', 'ssr']:
|
|
self.__setattr__(f'RETIRE_{r.upper()}', to_bool(option[f'retire_{r}']))
|
|
# Clear mode
|
|
self.ENABLE_MAP_CLEAR_MODE = to_bool(option['enable_map_clear_mode'])
|
|
self.CLEAR_MODE_STOP_CONDITION = option['clear_mode_stop_condition']
|
|
star = option['map_star_clear_all']
|
|
self.MAP_STAR_CLEAR_ALL = int(star.split('_')[1]) if star.startswith('index_') else 0
|
|
|
|
# Reward
|
|
option = config['Reward']
|
|
self.REWARD_INTERVAL = int(option['reward_interval'])
|
|
for attr in ['enable_reward', 'enable_oil_reward', 'enable_coin_reward', 'enable_mission_reward', 'enable_commission_reward', 'enable_tactical_reward']:
|
|
self.__setattr__(attr.upper(), to_bool(option[attr]))
|
|
if not option['commission_time_limit'].isdigit():
|
|
self.COMMISSION_TIME_LIMIT = future_time(option['commission_time_limit'])
|
|
else:
|
|
self.COMMISSION_TIME_LIMIT = 0
|
|
for attr in self.COMMISSION_PRIORITY.keys():
|
|
self.COMMISSION_PRIORITY[attr] = int(option[attr])
|
|
self.TACTICAL_NIGHT_RANGE = future_time_range(option['tactical_night_range'])
|
|
self.TACTICAL_BOOK_TIER = int(option['tactical_book_tier'])
|
|
self.TACTICAL_EXP_FIRST = to_bool(option['tactical_exp_first'])
|
|
self.TACTICAL_BOOK_TIER_NIGHT = int(option['tactical_book_tier_night'])
|
|
self.TACTICAL_EXP_FIRST_NIGHT = to_bool(option['tactical_exp_first_night'])
|
|
|
|
option = config['Main']
|
|
self.CAMPAIGN_MODE = option['campaign_mode']
|
|
self.CAMPAIGN_NAME = option['main_stage']
|
|
self.CAMPAIGN_NAME = 'campaign_' + self.CAMPAIGN_NAME.replace('-', '_')
|
|
|
|
option = config['Daily']
|
|
for n in ['daily_mission', 'hard_campaign', 'exercise']:
|
|
self.__setattr__(f'ENABLE_{n.upper()}', option[f'enable_{n}'])
|
|
# Daily mission
|
|
self.ENABLE_DAILY_MISSION = to_bool(option['enable_daily_mission'])
|
|
for n in [1, 2, 4, 5]:
|
|
self.DAILY_CHOOSE[n] = dic_daily[option[f'daily_mission_{n}']]
|
|
self.FLEET_DAILY = int(option['daily_fleet'])
|
|
self.FLEET_DAILY_EQUIPMENT = to_list(option['daily_equipment'])
|
|
# Hard
|
|
self.ENABLE_HARD_CAMPAIGN = to_bool(option['enable_hard_campaign'])
|
|
self.HARD_CAMPAIGN = option['hard_campaign']
|
|
self.FLEET_HARD = int(option['hard_fleet'])
|
|
self.FLEET_HARD_EQUIPMENT = to_list(option['hard_equipment'])
|
|
# Exercise
|
|
self.ENABLE_EXERCISE = to_bool(option['enable_exercise'])
|
|
self.EXERCISE_CHOOSE_MODE = option['exercise_choose_mode']
|
|
self.EXERCISE_PRESERVE = int(option['exercise_preserve'])
|
|
self.OPPONENT_CHALLENGE_TRIAL = int(option['exercise_try'])
|
|
self.LOW_HP_THRESHOLD = float(option['exercise_hp_threshold'])
|
|
self.LOW_HP_CONFIRM_WAIT = float(option['exercise_low_hp_confirm'])
|
|
self.EXERCISE_FLEET_EQUIPMENT = to_list(option['exercise_equipment'])
|
|
|
|
# Event
|
|
option = config['Event']
|
|
self.EVENT_NAME = option['event_name']
|
|
if 'sp' in ''.join(os.listdir(f'./campaign/{self.EVENT_NAME}')):
|
|
self.CAMPAIGN_EVENT = option['sp_stage']
|
|
else:
|
|
self.CAMPAIGN_EVENT = option['event_stage']
|
|
|
|
# Event_daily_ab
|
|
option = config['Event_daily_ab']
|
|
self.EVENT_NAME_AB = option['event_name_ab']
|
|
|
|
# Semi_auto
|
|
option = config['Semi_auto']
|
|
self.ENABLE_SEMI_MAP_PREPARATION = to_bool(option['enable_semi_map_preparation'])
|
|
self.ENABLE_SEMI_STORY_SKIP = to_bool(option['enable_semi_story_skip'])
|
|
|
|
# C_7_2_mystery_farming
|
|
option = config['C72_mystery_farming']
|
|
self.C72_BOSS_FLEET_STEP_ON_A3 = to_bool(option['boss_fleet_step_on_a3'])
|
|
if self.COMMAND.lower() == 'c72_mystery_farming' and not self.C72_BOSS_FLEET_STEP_ON_A3:
|
|
self.FLEET_2 = 0
|
|
|
|
# C_12_2_leveling
|
|
option = config['C122_leveling']
|
|
self.C122_S3_TOLERANCE = int(option['s3_enemy_tolerance'])
|
|
|
|
# C_12_4_leveling
|
|
option = config['C124_leveling']
|
|
self.C124_NON_S3_ENTER_TOLERANCE = int(option['non_s3_enemy_enter_tolerance'])
|
|
self.C124_NON_S3_WITHDRAW_TOLERANCE = int(option['non_s3_enemy_withdraw_tolerance'])
|
|
self.C124_AMMO_PICK_UP = int(option['ammo_pick_up_124'])
|
|
|
|
def get_server_timezone(self):
|
|
if self.SERVER == 'en':
|
|
return -7
|
|
elif self.SERVER == 'cn':
|
|
return 8
|
|
elif self.SERVER == 'jp':
|
|
return 9
|
|
else:
|
|
return 8
|
|
|
|
def get_server_last_update(self, since):
|
|
"""
|
|
Args:
|
|
since (tuple(int)): Update hour in Azurlane, such as (0, 12, 18,).
|
|
|
|
Returns:
|
|
datetime.datetime
|
|
"""
|
|
d = datetime.now(timezone.utc).astimezone()
|
|
diff = d.utcoffset() // timedelta(seconds=1) // 3600 - self.get_server_timezone()
|
|
since = np.sort((np.array(since) + diff) % 24)
|
|
update = sorted([past_time(f'{t}:00') for t in since])[-1]
|
|
return update
|
|
|
|
def record_executed_since(self, option, since):
|
|
"""
|
|
Args:
|
|
option (tuple(str)): (Section, Option), such as ('DailyRecord', 'exercise').
|
|
since (tuple(int)): Update hour in Azurlane, such as (0, 12, 18,).
|
|
|
|
Returns:
|
|
bool: If got a record after last game update.
|
|
"""
|
|
record = datetime.strptime(self.config.get(*option), self.TIME_FORMAT)
|
|
update = self.get_server_last_update(since)
|
|
|
|
logger.attr(f'{option[0]}_{option[1]}', f'Record time: {record}')
|
|
logger.attr(f'{option[0]}_{option[1]}', f'Last update: {update}')
|
|
return record > update
|
|
|
|
def triggered_app_restart(self):
|
|
if self.get_server_last_update(since=(0,)) > self.start_time:
|
|
logger.hr('Triggered restart new day')
|
|
return True
|
|
else:
|
|
return False
|
|
|
|
def record_save(self, option):
|
|
record = datetime.strftime(datetime.now(), self.TIME_FORMAT)
|
|
self.config.set(option[0], option[1], record)
|
|
self.save()
|
|
|
|
def __init__(self, ini_name='alas'):
|
|
"""
|
|
Args:
|
|
ini_name (str): Config to load.
|
|
"""
|
|
self.load_config_file(ini_name)
|
|
|
|
self.create_folder()
|
|
|
|
# cfg = AzurLaneConfig()
|