StarRailCopilot/module/config/config.py

397 lines
12 KiB
Python
Raw Normal View History

2020-03-28 17:22:46 +00:00
import codecs
import configparser
import copy
import os
from datetime import datetime, timedelta
import numpy as np
from PIL import Image
from module.config.dictionary import *
from module.logger import logger
class AzurLaneConfig:
"""
Basic Config.
"""
CONFIG_FILE = ''
config = configparser.ConfigParser(interpolation=None)
"""
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 1-2, if empty use 0.
SUBMARINE = 0
FLEET_CHECKED = False
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
"""
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_HP_BALANCE = False
ENABLE_MAP_FLEET_LOCK = True
SUBMARINE_MODE = ''
SUBMARINE_CALL_AT_BOSS = False
"""
module.campaign
"""
CAMPAIGN_NAME = 'default'
CAMPAIGN_MODE = 'normal'
ENABLE_STOP_CONDITION = 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
"""
module.event
"""
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 = '127.0.0.1:62001'
COMMAND = ''
USE_ADB_SREENSHOT = False
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
"""
ERROR_LOG_FOLDER = './log/error'
"""
module.map.fleet
"""
MAP_HAS_AMBUSH = False
"""
module.retire
"""
ENABLE_RETIREMENT = True
RETIRE_MODE = '10' # 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 = np.array(Image.open(UI_MASK_FILE).convert('L'))
# 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': 2,
'prominence': 10,
'distance': 35,
}
EDGE_LINES_FIND_PEAKS_PARAMETERS = {
'height': (255 - 24, 255),
'prominence': 10,
'distance': 50,
'width': (0, 7),
2020-03-28 17:22:46 +00:00
'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
# Parameters for perspective calculating
VANISH_POINT_RANGE = ((540, 740), (-3000, -1000))
DISTANCE_POINT_X_RANGE = ((-3200, -1600),)
# Parameters for line cleansing
ERROR_LINES_TOLERANCE = (-10, 10)
MID_DIFF_RANGE = (129 - 3, 129 + 3)
COINCIDENT_POINT_RANGE = (
(
-abs(ERROR_LINES_TOLERANCE[0]) * MID_DIFF_RANGE[1],
# SCREEN_SIZE[0] + ERROR_LINES_TOLERANCE[1] * MID_DIFF_RANGE[1]
200
),
MID_DIFF_RANGE
)
"""
module.daemon
"""
ENABLE_SEMI_MAP_PREPARATION = True
ENABLE_SEMI_STORY_SKIP = True
"""
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):
self.SCREEN_SHOT_SAVE_FOLDER = self.SCREEN_SHOT_SAVE_FOLDER_BASE + '/' + self.CAMPAIGN_NAME
for folder in [self.SCREEN_SHOT_SAVE_FOLDER_BASE, self.ASSETS_FOLDER, self.SCREEN_SHOT_SAVE_FOLDER, self.ERROR_LOG_FOLDER]:
if 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)
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')
option = config['Setting']
# Serial
self.SERIAL = option['serial']
# Stop condition
self.ENABLE_STOP_CONDITION = to_bool(option['enable_stop_condition'])
self.STOP_IF_COUNT_GREATER_THAN = int(option['if_count_greater_than'])
if not option['if_time_reach'].isdigit():
hour, minute = [int(x) for x in option['if_time_reach'].split(':')]
limit = datetime.now().replace(hour=hour, minute=minute, second=0, microsecond=0)
limit = limit + timedelta(1) if limit < datetime.now() else limit
self.STOP_IF_TIME_REACH = limit
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'])
for n in ['1', '2', '3']:
self.__setattr__(f'FLEET_{n}', int(option[f'fleet_index_{n}']))
self.__setattr__(f'FLEET_{n}_FORMATION', int(option[f'fleet_formation_{n}'].split('_')[1]))
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_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.RETIRE_MODE = option['retire_mode'].split('_')[1]
for r in ['n', 'r', 'sr', 'ssr']:
self.__setattr__(f'RETIRE_{r.upper()}', to_bool(option[f'retire_{r}']))
option = config['Main']
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 = equip(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 = equip(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 = equip(option['exercise_equipment'])
# Event
option = config['Event']
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_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 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)
since = np.array(since)
hour = since[since <= datetime.now().hour][-1]
update = datetime.now().replace(hour=hour, minute=0, second=0, microsecond=0)
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 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, conf='main'):
"""
Args:
conf (str): Config to load.
"""
self.load_config_file(conf)
self.create_folder()
# cfg = AzurLaneConfig()