mirror of
https://github.com/LmeSzinc/StarRailCopilot.git
synced 2024-11-30 03:16:08 +00:00
Merge pull request #30 from LmeSzinc/master
Dev: word template extractor
This commit is contained in:
commit
abeed8a2b7
@ -26,7 +26,7 @@ MAP.wall_data = """
|
|||||||
· · | · · · | · · · · | · · · | · · ,
|
· · | · · · | · · · · | · · · | · · ,
|
||||||
| | | | ,
|
| | | | ,
|
||||||
· · | · · · | · · · · | · · · | · · ,
|
· · | · · · | · · · · | · · · | · · ,
|
||||||
+---+ +---+ +----+ +---+ ,
|
+---+ +---+ +---+ +---+ ,
|
||||||
· · · | · · · · · · · · | · · · ,
|
· · · | · · · · · · · · | · · · ,
|
||||||
| | ,
|
| | ,
|
||||||
· · · | · · · · · · · · | · · · ,
|
· · · | · · · · · · · · | · · · ,
|
||||||
|
@ -37,7 +37,7 @@ MAP.wall_data = """
|
|||||||
· · | · · · | · · · · | · · · | · · ,
|
· · | · · · | · · · · | · · · | · · ,
|
||||||
| | | | ,
|
| | | | ,
|
||||||
· · | · · · | · · · · | · · · | · · ,
|
· · | · · · | · · · · | · · · | · · ,
|
||||||
+---+ +---+ +----+ +---+ ,
|
+---+ +---+ +---+ +---+ ,
|
||||||
· · · | · · · · · · · · | · · · ,
|
· · · | · · · · · · · · | · · · ,
|
||||||
| | ,
|
| | ,
|
||||||
· · · | · · · · · · · · | · · · ,
|
· · · | · · · · · · · · | · · · ,
|
||||||
|
@ -2,11 +2,11 @@
|
|||||||
command = Daily
|
command = Daily
|
||||||
|
|
||||||
[Setting]
|
[Setting]
|
||||||
enable_stop_condition = yes
|
enable_stop_condition = no
|
||||||
enable_fast_forward = yes
|
enable_fast_forward = yes
|
||||||
if_count_greater_than = 0
|
if_count_greater_than = 0
|
||||||
if_time_reach = 0
|
if_time_reach = 0
|
||||||
if_oil_lower_than = 2000
|
if_oil_lower_than = 0
|
||||||
if_trigger_emotion_control = no
|
if_trigger_emotion_control = no
|
||||||
if_dock_full = no
|
if_dock_full = no
|
||||||
enable_fleet_control = yes
|
enable_fleet_control = yes
|
||||||
@ -25,14 +25,14 @@ fleet_index_4 = do_not_use
|
|||||||
submarine_mode = do_not_use
|
submarine_mode = do_not_use
|
||||||
enable_emotion_reduce = yes
|
enable_emotion_reduce = yes
|
||||||
ignore_low_emotion_warn = no
|
ignore_low_emotion_warn = no
|
||||||
emotion_recover_1 = dormitory_floor_2
|
emotion_recover_1 = not_in_dormitory
|
||||||
emotion_control_1 = keep_high_emotion
|
emotion_control_1 = avoid_yellow_face
|
||||||
hole_fleet_married_1 = no
|
hole_fleet_married_1 = no
|
||||||
emotion_recover_2 = not_in_dormitory
|
emotion_recover_2 = not_in_dormitory
|
||||||
emotion_control_2 = avoid_yellow_face
|
emotion_control_2 = avoid_yellow_face
|
||||||
hole_fleet_married_2 = no
|
hole_fleet_married_2 = no
|
||||||
emotion_recover_3 = dormitory_floor_1
|
emotion_recover_3 = not_in_dormitory
|
||||||
emotion_control_3 = keep_high_emotion
|
emotion_control_3 = avoid_yellow_face
|
||||||
hole_fleet_married_3 = no
|
hole_fleet_married_3 = no
|
||||||
enable_hp_balance = no
|
enable_hp_balance = no
|
||||||
enable_low_hp_withdraw = no
|
enable_low_hp_withdraw = no
|
||||||
@ -156,11 +156,11 @@ ammo_pick_up_124 = 3
|
|||||||
command = c124_leveling
|
command = c124_leveling
|
||||||
|
|
||||||
[EmotionRecord]
|
[EmotionRecord]
|
||||||
fleet_1_emotion = 150
|
fleet_1_emotion = 119
|
||||||
fleet_1_savetime = 2020-01-01_00:00:00
|
fleet_1_savetime = 2020-01-01_00:00:00
|
||||||
fleet_2_emotion = 119
|
fleet_2_emotion = 119
|
||||||
fleet_2_savetime = 2020-01-01_00:00:00
|
fleet_2_savetime = 2020-01-01_00:00:00
|
||||||
fleet_3_emotion = 150
|
fleet_3_emotion = 119
|
||||||
fleet_3_savetime = 2020-01-01_00:00:00
|
fleet_3_savetime = 2020-01-01_00:00:00
|
||||||
|
|
||||||
[DailyRecord]
|
[DailyRecord]
|
||||||
|
278
dev_tools/slpp.py
Normal file
278
dev_tools/slpp.py
Normal file
@ -0,0 +1,278 @@
|
|||||||
|
import re
|
||||||
|
import sys
|
||||||
|
from numbers import Number
|
||||||
|
|
||||||
|
import six
|
||||||
|
|
||||||
|
|
||||||
|
"""
|
||||||
|
SLPP is a simple lua-python data structures parser.
|
||||||
|
|
||||||
|
This is my fork of SLPP, https://github.com/LmeSzinc/slpp
|
||||||
|
Origin repository here, https://github.com/SirAnthony/slpp
|
||||||
|
|
||||||
|
I found some error in it
|
||||||
|
lua example: '{点={2={0={叫={醒={我={this=true}}}}}}}'
|
||||||
|
wrong result: {'点': {2: [{'叫': {'醒': {'我': {'this': True}}}}]}}
|
||||||
|
fixed result: {'点': {2: {0: {'叫': {'醒': {'我': {'this': True}}}}}}}
|
||||||
|
|
||||||
|
They seems to treat this as a feature not a bug, https://github.com/SirAnthony/slpp/issues/21
|
||||||
|
So I made my own fork for Alas.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
ERRORS = {
|
||||||
|
'unexp_end_string': u'Unexpected end of string while parsing Lua string.',
|
||||||
|
'unexp_end_table': u'Unexpected end of table while parsing Lua string.',
|
||||||
|
'mfnumber_minus': u'Malformed number (no digits after initial minus).',
|
||||||
|
'mfnumber_dec_point': u'Malformed number (no digits after decimal point).',
|
||||||
|
'mfnumber_sci': u'Malformed number (bad scientific format).',
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def sequential(lst):
|
||||||
|
length = len(lst)
|
||||||
|
if length == 0 or lst[0] != 0:
|
||||||
|
return False
|
||||||
|
for i in range(length):
|
||||||
|
if i + 1 < length:
|
||||||
|
if lst[i] + 1 != lst[i + 1]:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
class ParseError(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class SLPP(object):
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.text = ''
|
||||||
|
self.ch = ''
|
||||||
|
self.at = 0
|
||||||
|
self.len = 0
|
||||||
|
self.depth = 0
|
||||||
|
self.space = re.compile('\s', re.M)
|
||||||
|
self.alnum = re.compile('\w', re.M)
|
||||||
|
self.newline = '\n'
|
||||||
|
self.tab = '\t'
|
||||||
|
|
||||||
|
def decode(self, text):
|
||||||
|
if not text or not isinstance(text, six.string_types):
|
||||||
|
return
|
||||||
|
reg = re.compile('--.*$', re.M)
|
||||||
|
text = reg.sub('', text, 0)
|
||||||
|
self.text = text
|
||||||
|
self.at, self.ch, self.depth = 0, '', 0
|
||||||
|
self.len = len(text)
|
||||||
|
self.next_chr()
|
||||||
|
result = self.value()
|
||||||
|
return result
|
||||||
|
|
||||||
|
def encode(self, obj):
|
||||||
|
self.depth = 0
|
||||||
|
return self.__encode(obj)
|
||||||
|
|
||||||
|
def __encode(self, obj):
|
||||||
|
s = ''
|
||||||
|
tab = self.tab
|
||||||
|
newline = self.newline
|
||||||
|
|
||||||
|
if isinstance(obj, str):
|
||||||
|
s += '"%s"' % obj.replace(r'"', r'\"')
|
||||||
|
elif six.PY2 and isinstance(obj, unicode):
|
||||||
|
s += '"%s"' % obj.encode('utf-8').replace(r'"', r'\"')
|
||||||
|
elif six.PY3 and isinstance(obj, bytes):
|
||||||
|
s += '"{}"'.format(''.join(r'\x{:02x}'.format(c) for c in obj))
|
||||||
|
elif isinstance(obj, bool):
|
||||||
|
s += str(obj).lower()
|
||||||
|
elif obj is None:
|
||||||
|
s += 'nil'
|
||||||
|
elif isinstance(obj, Number):
|
||||||
|
s += str(obj)
|
||||||
|
elif isinstance(obj, (list, tuple, dict)):
|
||||||
|
self.depth += 1
|
||||||
|
if len(obj) == 0 or (not isinstance(obj, dict) and len([
|
||||||
|
x for x in obj
|
||||||
|
if isinstance(x, Number) or (isinstance(x, six.string_types) and len(x) < 10)
|
||||||
|
]) == len(obj)):
|
||||||
|
newline = tab = ''
|
||||||
|
dp = tab * self.depth
|
||||||
|
s += "%s{%s" % (tab * (self.depth - 2), newline)
|
||||||
|
if isinstance(obj, dict):
|
||||||
|
key = '[%s]' if all(isinstance(k, int) for k in obj.keys()) else '%s'
|
||||||
|
contents = [dp + (key + ' = %s') % (k, self.__encode(v)) for k, v in obj.items()]
|
||||||
|
s += (',%s' % newline).join(contents)
|
||||||
|
else:
|
||||||
|
s += (',%s' % newline).join(
|
||||||
|
[dp + self.__encode(el) for el in obj])
|
||||||
|
self.depth -= 1
|
||||||
|
s += "%s%s}" % (newline, tab * self.depth)
|
||||||
|
return s
|
||||||
|
|
||||||
|
def white(self):
|
||||||
|
while self.ch:
|
||||||
|
if self.space.match(self.ch):
|
||||||
|
self.next_chr()
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
|
||||||
|
def next_chr(self):
|
||||||
|
if self.at >= self.len:
|
||||||
|
self.ch = None
|
||||||
|
return None
|
||||||
|
self.ch = self.text[self.at]
|
||||||
|
self.at += 1
|
||||||
|
return True
|
||||||
|
|
||||||
|
def value(self):
|
||||||
|
self.white()
|
||||||
|
if not self.ch:
|
||||||
|
return
|
||||||
|
if self.ch == '{':
|
||||||
|
return self.object()
|
||||||
|
if self.ch == "[":
|
||||||
|
self.next_chr()
|
||||||
|
if self.ch in ['"', "'", '[']:
|
||||||
|
return self.string(self.ch)
|
||||||
|
if self.ch.isdigit() or self.ch == '-':
|
||||||
|
return self.number()
|
||||||
|
return self.word()
|
||||||
|
|
||||||
|
def string(self, end=None):
|
||||||
|
s = ''
|
||||||
|
start = self.ch
|
||||||
|
if end == '[':
|
||||||
|
end = ']'
|
||||||
|
if start in ['"', "'", '[']:
|
||||||
|
while self.next_chr():
|
||||||
|
if self.ch == end:
|
||||||
|
self.next_chr()
|
||||||
|
if start != "[" or self.ch == ']':
|
||||||
|
return s
|
||||||
|
if self.ch == '\\' and start == end:
|
||||||
|
self.next_chr()
|
||||||
|
if self.ch != end:
|
||||||
|
s += '\\'
|
||||||
|
s += self.ch
|
||||||
|
raise ParseError(ERRORS['unexp_end_string'])
|
||||||
|
|
||||||
|
def object(self):
|
||||||
|
o = {}
|
||||||
|
k = None
|
||||||
|
idx = 0
|
||||||
|
self.depth += 1
|
||||||
|
self.next_chr()
|
||||||
|
self.white()
|
||||||
|
if self.ch and self.ch == '}':
|
||||||
|
self.depth -= 1
|
||||||
|
self.next_chr()
|
||||||
|
return o # Exit here
|
||||||
|
else:
|
||||||
|
while self.ch:
|
||||||
|
self.white()
|
||||||
|
if self.ch == '{':
|
||||||
|
o[idx] = self.object()
|
||||||
|
idx += 1
|
||||||
|
continue
|
||||||
|
elif self.ch == '}':
|
||||||
|
self.depth -= 1
|
||||||
|
self.next_chr()
|
||||||
|
if k is not None:
|
||||||
|
o[idx] = k
|
||||||
|
if len([key for key in o if isinstance(key, six.string_types + (int, float, bool, tuple))]) == 0:
|
||||||
|
so = sorted([key for key in o])
|
||||||
|
if sequential(so):
|
||||||
|
ar = []
|
||||||
|
for key in o:
|
||||||
|
ar.insert(key, o[key])
|
||||||
|
o = ar
|
||||||
|
return o # or here
|
||||||
|
else:
|
||||||
|
if self.ch == ',':
|
||||||
|
self.next_chr()
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
k = self.value()
|
||||||
|
if self.ch == ']':
|
||||||
|
self.next_chr()
|
||||||
|
self.white()
|
||||||
|
ch = self.ch
|
||||||
|
if ch in ('=', ','):
|
||||||
|
self.next_chr()
|
||||||
|
self.white()
|
||||||
|
if ch == '=':
|
||||||
|
o[k] = self.value()
|
||||||
|
else:
|
||||||
|
o[idx] = k
|
||||||
|
idx += 1
|
||||||
|
k = None
|
||||||
|
raise ParseError(ERRORS['unexp_end_table']) # Bad exit here
|
||||||
|
|
||||||
|
words = {'true': True, 'false': False, 'nil': None}
|
||||||
|
|
||||||
|
def word(self):
|
||||||
|
s = ''
|
||||||
|
if self.ch != '\n':
|
||||||
|
s = self.ch
|
||||||
|
self.next_chr()
|
||||||
|
while self.ch is not None and self.alnum.match(self.ch) and s not in self.words:
|
||||||
|
s += self.ch
|
||||||
|
self.next_chr()
|
||||||
|
return self.words.get(s, s)
|
||||||
|
|
||||||
|
def number(self):
|
||||||
|
def next_digit(err):
|
||||||
|
n = self.ch
|
||||||
|
self.next_chr()
|
||||||
|
if not self.ch or not self.ch.isdigit():
|
||||||
|
raise ParseError(err)
|
||||||
|
return n
|
||||||
|
|
||||||
|
n = ''
|
||||||
|
try:
|
||||||
|
if self.ch == '-':
|
||||||
|
n += next_digit(ERRORS['mfnumber_minus'])
|
||||||
|
n += self.digit()
|
||||||
|
if n == '0' and self.ch in ['x', 'X']:
|
||||||
|
n += self.ch
|
||||||
|
self.next_chr()
|
||||||
|
n += self.hex()
|
||||||
|
else:
|
||||||
|
if self.ch and self.ch == '.':
|
||||||
|
n += next_digit(ERRORS['mfnumber_dec_point'])
|
||||||
|
n += self.digit()
|
||||||
|
if self.ch and self.ch in ['e', 'E']:
|
||||||
|
n += self.ch
|
||||||
|
self.next_chr()
|
||||||
|
if not self.ch or self.ch not in ('+', '-'):
|
||||||
|
raise ParseError(ERRORS['mfnumber_sci'])
|
||||||
|
n += next_digit(ERRORS['mfnumber_sci'])
|
||||||
|
n += self.digit()
|
||||||
|
except ParseError:
|
||||||
|
t, e = sys.exc_info()[:2]
|
||||||
|
print(e)
|
||||||
|
return 0
|
||||||
|
try:
|
||||||
|
return int(n, 0)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
return float(n)
|
||||||
|
|
||||||
|
def digit(self):
|
||||||
|
n = ''
|
||||||
|
while self.ch and self.ch.isdigit():
|
||||||
|
n += self.ch
|
||||||
|
self.next_chr()
|
||||||
|
return n
|
||||||
|
|
||||||
|
def hex(self):
|
||||||
|
n = ''
|
||||||
|
while self.ch and (self.ch in 'ABCDEFabcdef' or self.ch.isdigit()):
|
||||||
|
n += self.ch
|
||||||
|
self.next_chr()
|
||||||
|
return n
|
||||||
|
|
||||||
|
|
||||||
|
slpp = SLPP()
|
46
dev_tools/word_template_extractor.py
Normal file
46
dev_tools/word_template_extractor.py
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
import re
|
||||||
|
|
||||||
|
from dev_tools.slpp import slpp
|
||||||
|
|
||||||
|
"""
|
||||||
|
This file is used to extract `word_template.lua`, aka, the blacklist words file.
|
||||||
|
|
||||||
|
Git clone the repository here, https://github.com/Dimbreath/AzurLaneData, to get the decrypted scripts.
|
||||||
|
Then put your filepath here, like `<your_folder>/<server>/sharecfg/word_template.lua`
|
||||||
|
Server list: en-US, ja-JP, ko-KR, zh-CN, zh-TW
|
||||||
|
"""
|
||||||
|
file = ''
|
||||||
|
count = 0
|
||||||
|
with open(file, 'r', encoding='utf-8') as f:
|
||||||
|
text = f.read()
|
||||||
|
|
||||||
|
|
||||||
|
def extract(dic, word_list):
|
||||||
|
"""
|
||||||
|
Args:
|
||||||
|
dic (dict):
|
||||||
|
word_list (list[str]):
|
||||||
|
"""
|
||||||
|
global count
|
||||||
|
for word, data in dic.items():
|
||||||
|
word = str(word)
|
||||||
|
if data.get('this', False):
|
||||||
|
new = word_list + [word]
|
||||||
|
new = ''.join(new)
|
||||||
|
count += 1
|
||||||
|
print(new)
|
||||||
|
else:
|
||||||
|
new = word_list + [word]
|
||||||
|
extract(data, word_list=new)
|
||||||
|
|
||||||
|
|
||||||
|
# CN server
|
||||||
|
for result in re.findall('word_template = (.*?)return', text, re.DOTALL):
|
||||||
|
pg = slpp.decode(result)
|
||||||
|
extract(pg, word_list=[])
|
||||||
|
# Other server
|
||||||
|
for result in re.findall('uv0\.{0,1}(.*?)end', text, re.DOTALL):
|
||||||
|
pg = slpp.decode('{%s}' % result)
|
||||||
|
extract(pg, word_list=[])
|
||||||
|
|
||||||
|
print(f'Total count: {count}')
|
@ -17,7 +17,7 @@ class Equipment(InfoHandler):
|
|||||||
equipment_has_take_on = False
|
equipment_has_take_on = False
|
||||||
|
|
||||||
def _view_swipe(self, distance, check_button=EQUIPMENT_OPEN):
|
def _view_swipe(self, distance, check_button=EQUIPMENT_OPEN):
|
||||||
swipe_timer = Timer(3, count=5)
|
swipe_timer = Timer(5, count=10)
|
||||||
SWIPE_CHECK.load_color(self.device.image)
|
SWIPE_CHECK.load_color(self.device.image)
|
||||||
while 1:
|
while 1:
|
||||||
if not swipe_timer.started() or swipe_timer.reached():
|
if not swipe_timer.started() or swipe_timer.reached():
|
||||||
|
@ -80,12 +80,12 @@ class ExerciseCombat(HpDaemon, OpponentChoose, ExerciseEquipment):
|
|||||||
show_hp_timer.reset()
|
show_hp_timer.reset()
|
||||||
self._show_hp()
|
self._show_hp()
|
||||||
|
|
||||||
if self.appear_then_click(QUIT_CONFIRM, offset=True, interval=1):
|
if self.appear_then_click(QUIT_CONFIRM, offset=True, interval=5):
|
||||||
success = False
|
success = False
|
||||||
end = True
|
end = True
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if self.appear_then_click(QUIT_RECONFIRM, offset=True, interval=1):
|
if self.appear_then_click(QUIT_RECONFIRM, offset=True, interval=5):
|
||||||
self.interval_reset(QUIT_CONFIRM)
|
self.interval_reset(QUIT_CONFIRM)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
@ -38,7 +38,9 @@ class EnemySearchingHandler(InfoHandler):
|
|||||||
def is_in_stage(self):
|
def is_in_stage(self):
|
||||||
if not self.appear(IN_STAGE, offset=(10, 10)):
|
if not self.appear(IN_STAGE, offset=(10, 10)):
|
||||||
return False
|
return False
|
||||||
if self.stage_entrance is not None and not self.appear(self.stage_entrance, threshold=30):
|
if self.stage_entrance is not None \
|
||||||
|
and self.stage_entrance.area \
|
||||||
|
and not self.appear(self.stage_entrance, threshold=30):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
Loading…
Reference in New Issue
Block a user