Merge branch 'master' into phone_cloud
Before Width: | Height: | Size: 8.5 KiB |
BIN
assets/cn/shipyard/SHIPYARD_RESEARCH_IN_PROGRESS.png
Normal file
After Width: | Height: | Size: 3.6 KiB |
Before Width: | Height: | Size: 8.5 KiB |
BIN
assets/en/shipyard/SHIPYARD_RESEARCH_IN_PROGRESS.png
Normal file
After Width: | Height: | Size: 3.6 KiB |
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 6.1 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 8.5 KiB |
BIN
assets/jp/shipyard/SHIPYARD_RESEARCH_IN_PROGRESS.png
Normal file
After Width: | Height: | Size: 3.6 KiB |
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 5.5 KiB |
Before Width: | Height: | Size: 8.5 KiB |
BIN
assets/tw/shipyard/SHIPYARD_RESEARCH_IN_PROGRESS.png
Normal file
After Width: | Height: | Size: 3.6 KiB |
@ -22,5 +22,4 @@ prettytable==2.2.1
|
||||
pypresence==4.2.1
|
||||
rich==11.0.0
|
||||
zerorpc==0.6.3
|
||||
pyzmq==22.3.0
|
||||
atomicwrites
|
||||
pyzmq==22.3.0
|
@ -23,5 +23,4 @@ prettytable==2.2.1
|
||||
pypresence==4.2.1
|
||||
rich==11.0.0
|
||||
zerorpc==0.6.3
|
||||
pyzmq==22.3.0
|
||||
atomicwrites
|
||||
pyzmq==22.3.0
|
@ -672,8 +672,12 @@ def image_left_strip(image, threshold, length):
|
||||
"""
|
||||
brightness = np.mean(image, axis=0)
|
||||
match = np.where(brightness < threshold)[0]
|
||||
|
||||
if len(match):
|
||||
image = image[:, match[0] + length:]
|
||||
left = match[0] + length
|
||||
total = image.shape[1]
|
||||
if left < total:
|
||||
image = image[:, left:]
|
||||
return image
|
||||
|
||||
|
||||
|
236
module/config/atomicwrites.py
Normal file
@ -0,0 +1,236 @@
|
||||
"""
|
||||
Copy-pasted from
|
||||
https://github.com/untitaker/python-atomicwrites
|
||||
"""
|
||||
import contextlib
|
||||
import io
|
||||
import os
|
||||
import sys
|
||||
import tempfile
|
||||
|
||||
try:
|
||||
import fcntl
|
||||
except ImportError:
|
||||
fcntl = None
|
||||
|
||||
# `fspath` was added in Python 3.6
|
||||
try:
|
||||
from os import fspath
|
||||
except ImportError:
|
||||
fspath = None
|
||||
|
||||
__version__ = '1.4.1'
|
||||
|
||||
PY2 = sys.version_info[0] == 2
|
||||
|
||||
text_type = unicode if PY2 else str # noqa
|
||||
|
||||
|
||||
def _path_to_unicode(x):
|
||||
if not isinstance(x, text_type):
|
||||
return x.decode(sys.getfilesystemencoding())
|
||||
return x
|
||||
|
||||
|
||||
DEFAULT_MODE = "wb" if PY2 else "w"
|
||||
|
||||
_proper_fsync = os.fsync
|
||||
|
||||
if sys.platform != 'win32':
|
||||
if hasattr(fcntl, 'F_FULLFSYNC'):
|
||||
def _proper_fsync(fd):
|
||||
# https://lists.apple.com/archives/darwin-dev/2005/Feb/msg00072.html
|
||||
# https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man2/fsync.2.html
|
||||
# https://github.com/untitaker/python-atomicwrites/issues/6
|
||||
fcntl.fcntl(fd, fcntl.F_FULLFSYNC)
|
||||
|
||||
|
||||
def _sync_directory(directory):
|
||||
# Ensure that filenames are written to disk
|
||||
fd = os.open(directory, 0)
|
||||
try:
|
||||
_proper_fsync(fd)
|
||||
finally:
|
||||
os.close(fd)
|
||||
|
||||
|
||||
def _replace_atomic(src, dst):
|
||||
os.rename(src, dst)
|
||||
_sync_directory(os.path.normpath(os.path.dirname(dst)))
|
||||
|
||||
|
||||
def _move_atomic(src, dst):
|
||||
os.link(src, dst)
|
||||
os.unlink(src)
|
||||
|
||||
src_dir = os.path.normpath(os.path.dirname(src))
|
||||
dst_dir = os.path.normpath(os.path.dirname(dst))
|
||||
_sync_directory(dst_dir)
|
||||
if src_dir != dst_dir:
|
||||
_sync_directory(src_dir)
|
||||
else:
|
||||
from ctypes import windll, WinError
|
||||
|
||||
_MOVEFILE_REPLACE_EXISTING = 0x1
|
||||
_MOVEFILE_WRITE_THROUGH = 0x8
|
||||
_windows_default_flags = _MOVEFILE_WRITE_THROUGH
|
||||
|
||||
|
||||
def _handle_errors(rv):
|
||||
if not rv:
|
||||
raise WinError()
|
||||
|
||||
|
||||
def _replace_atomic(src, dst):
|
||||
_handle_errors(windll.kernel32.MoveFileExW(
|
||||
_path_to_unicode(src), _path_to_unicode(dst),
|
||||
_windows_default_flags | _MOVEFILE_REPLACE_EXISTING
|
||||
))
|
||||
|
||||
|
||||
def _move_atomic(src, dst):
|
||||
_handle_errors(windll.kernel32.MoveFileExW(
|
||||
_path_to_unicode(src), _path_to_unicode(dst),
|
||||
_windows_default_flags
|
||||
))
|
||||
|
||||
|
||||
def replace_atomic(src, dst):
|
||||
'''
|
||||
Move ``src`` to ``dst``. If ``dst`` exists, it will be silently
|
||||
overwritten.
|
||||
|
||||
Both paths must reside on the same filesystem for the operation to be
|
||||
atomic.
|
||||
'''
|
||||
return _replace_atomic(src, dst)
|
||||
|
||||
|
||||
def move_atomic(src, dst):
|
||||
'''
|
||||
Move ``src`` to ``dst``. There might a timewindow where both filesystem
|
||||
entries exist. If ``dst`` already exists, :py:exc:`FileExistsError` will be
|
||||
raised.
|
||||
|
||||
Both paths must reside on the same filesystem for the operation to be
|
||||
atomic.
|
||||
'''
|
||||
return _move_atomic(src, dst)
|
||||
|
||||
|
||||
class AtomicWriter(object):
|
||||
'''
|
||||
A helper class for performing atomic writes. Usage::
|
||||
|
||||
with AtomicWriter(path).open() as f:
|
||||
f.write(...)
|
||||
|
||||
:param path: The destination filepath. May or may not exist.
|
||||
:param mode: The filemode for the temporary file. This defaults to `wb` in
|
||||
Python 2 and `w` in Python 3.
|
||||
:param overwrite: If set to false, an error is raised if ``path`` exists.
|
||||
Errors are only raised after the file has been written to. Either way,
|
||||
the operation is atomic.
|
||||
:param open_kwargs: Keyword-arguments to pass to the underlying
|
||||
:py:func:`open` call. This can be used to set the encoding when opening
|
||||
files in text-mode.
|
||||
|
||||
If you need further control over the exact behavior, you are encouraged to
|
||||
subclass.
|
||||
'''
|
||||
|
||||
def __init__(self, path, mode=DEFAULT_MODE, overwrite=False,
|
||||
**open_kwargs):
|
||||
if 'a' in mode:
|
||||
raise ValueError(
|
||||
'Appending to an existing file is not supported, because that '
|
||||
'would involve an expensive `copy`-operation to a temporary '
|
||||
'file. Open the file in normal `w`-mode and copy explicitly '
|
||||
'if that\'s what you\'re after.'
|
||||
)
|
||||
if 'x' in mode:
|
||||
raise ValueError('Use the `overwrite`-parameter instead.')
|
||||
if 'w' not in mode:
|
||||
raise ValueError('AtomicWriters can only be written to.')
|
||||
|
||||
# Attempt to convert `path` to `str` or `bytes`
|
||||
if fspath is not None:
|
||||
path = fspath(path)
|
||||
|
||||
self._path = path
|
||||
self._mode = mode
|
||||
self._overwrite = overwrite
|
||||
self._open_kwargs = open_kwargs
|
||||
|
||||
def open(self):
|
||||
'''
|
||||
Open the temporary file.
|
||||
'''
|
||||
return self._open(self.get_fileobject)
|
||||
|
||||
@contextlib.contextmanager
|
||||
def _open(self, get_fileobject):
|
||||
f = None # make sure f exists even if get_fileobject() fails
|
||||
try:
|
||||
success = False
|
||||
with get_fileobject(**self._open_kwargs) as f:
|
||||
yield f
|
||||
self.sync(f)
|
||||
self.commit(f)
|
||||
success = True
|
||||
finally:
|
||||
if not success:
|
||||
try:
|
||||
self.rollback(f)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
def get_fileobject(self, suffix="", prefix=tempfile.gettempprefix(),
|
||||
dir=None, **kwargs):
|
||||
'''Return the temporary file to use.'''
|
||||
if dir is None:
|
||||
dir = os.path.normpath(os.path.dirname(self._path))
|
||||
descriptor, name = tempfile.mkstemp(suffix=suffix, prefix=prefix,
|
||||
dir=dir)
|
||||
# io.open() will take either the descriptor or the name, but we need
|
||||
# the name later for commit()/replace_atomic() and couldn't find a way
|
||||
# to get the filename from the descriptor.
|
||||
os.close(descriptor)
|
||||
kwargs['mode'] = self._mode
|
||||
kwargs['file'] = name
|
||||
return io.open(**kwargs)
|
||||
|
||||
def sync(self, f):
|
||||
'''responsible for clearing as many file caches as possible before
|
||||
commit'''
|
||||
f.flush()
|
||||
_proper_fsync(f.fileno())
|
||||
|
||||
def commit(self, f):
|
||||
'''Move the temporary file to the target location.'''
|
||||
if self._overwrite:
|
||||
replace_atomic(f.name, self._path)
|
||||
else:
|
||||
move_atomic(f.name, self._path)
|
||||
|
||||
def rollback(self, f):
|
||||
'''Clean up all temporary resources.'''
|
||||
os.unlink(f.name)
|
||||
|
||||
|
||||
def atomic_write(path, writer_cls=AtomicWriter, **cls_kwargs):
|
||||
'''
|
||||
Simple atomic writes. This wraps :py:class:`AtomicWriter`::
|
||||
|
||||
with atomic_write(path) as f:
|
||||
f.write(...)
|
||||
|
||||
:param path: The target path to write to.
|
||||
:param writer_cls: The writer class to use. This parameter is useful if you
|
||||
subclassed :py:class:`AtomicWriter` to change some behavior and want to
|
||||
use that new subclass.
|
||||
|
||||
Additional keyword arguments are passed to the writer class. See
|
||||
:py:class:`AtomicWriter`.
|
||||
'''
|
||||
return writer_cls(path, **cls_kwargs).open()
|
@ -5,10 +5,10 @@ import string
|
||||
from datetime import datetime, timedelta, timezone
|
||||
|
||||
import yaml
|
||||
from atomicwrites import atomic_write
|
||||
from filelock import FileLock
|
||||
|
||||
import module.config.server as server_
|
||||
from module.config.atomicwrites import atomic_write
|
||||
|
||||
LANGUAGES = ['zh-CN', 'en-US', 'ja-JP', 'zh-TW']
|
||||
SERVER_TO_LANG = {
|
||||
|
@ -5,7 +5,7 @@ from module.base.template import Template
|
||||
# Don't modify it manually.
|
||||
|
||||
BATTLE_STATUS_CF = Button(area={'cn': (315, 217, 329, 303), 'en': (367, 238, 373, 274), 'jp': (340, 217, 350, 291), 'tw': (263, 216, 276, 305)}, color={'cn': (255, 242, 133), 'en': (252, 232, 164), 'jp': (255, 247, 143), 'tw': (240, 214, 143)}, button={'cn': (1000, 631, 1055, 689), 'en': (1000, 631, 1055, 689), 'jp': (1000, 631, 1055, 689), 'tw': (1000, 631, 1055, 689)}, file={'cn': './assets/cn/guild/BATTLE_STATUS_CF.png', 'en': './assets/en/guild/BATTLE_STATUS_CF.png', 'jp': './assets/jp/guild/BATTLE_STATUS_CF.png', 'tw': './assets/tw/guild/BATTLE_STATUS_CF.png'})
|
||||
EXP_INFO_CF = Button(area={'cn': (179, 67, 189, 126), 'en': (215, 82, 219, 106), 'jp': (196, 67, 204, 119), 'tw': (144, 66, 153, 127)}, color={'cn': (255, 242, 133), 'en': (252, 231, 160), 'jp': (255, 246, 140), 'tw': (241, 219, 150)}, button={'cn': (1000, 631, 1055, 689), 'en': (1000, 631, 1055, 689), 'jp': (1000, 631, 1055, 689), 'tw': (1000, 631, 1055, 689)}, file={'cn': './assets/cn/guild/EXP_INFO_CF.png', 'en': './assets/en/guild/EXP_INFO_CF.png', 'jp': './assets/jp/guild/EXP_INFO_CF.png', 'tw': './assets/tw/guild/EXP_INFO_CF.png'})
|
||||
EXP_INFO_CF = Button(area={'cn': (179, 67, 189, 126), 'en': (215, 82, 219, 106), 'jp': (196, 67, 204, 119), 'tw': (321, 93, 328, 114)}, color={'cn': (255, 242, 133), 'en': (252, 231, 160), 'jp': (255, 246, 140), 'tw': (255, 255, 159)}, button={'cn': (1000, 631, 1055, 689), 'en': (1000, 631, 1055, 689), 'jp': (1000, 631, 1055, 689), 'tw': (1000, 631, 1055, 689)}, file={'cn': './assets/cn/guild/EXP_INFO_CF.png', 'en': './assets/en/guild/EXP_INFO_CF.png', 'jp': './assets/jp/guild/EXP_INFO_CF.png', 'tw': './assets/tw/guild/EXP_INFO_CF.png'})
|
||||
GUILD_BOSS_AVAILABLE = Button(area={'cn': (1229, 614, 1242, 632), 'en': (1229, 614, 1242, 632), 'jp': (1229, 614, 1242, 632), 'tw': (1229, 614, 1242, 632)}, color={'cn': (58, 100, 61), 'en': (58, 100, 61), 'jp': (40, 70, 53), 'tw': (58, 100, 61)}, button={'cn': (1229, 614, 1242, 632), 'en': (1229, 614, 1242, 632), 'jp': (1229, 614, 1242, 632), 'tw': (1229, 614, 1242, 632)}, file={'cn': './assets/cn/guild/GUILD_BOSS_AVAILABLE.png', 'en': './assets/en/guild/GUILD_BOSS_AVAILABLE.png', 'jp': './assets/jp/guild/GUILD_BOSS_AVAILABLE.png', 'tw': './assets/tw/guild/GUILD_BOSS_AVAILABLE.png'})
|
||||
GUILD_BOSS_ENTER = Button(area={'cn': (1132, 642, 1261, 687), 'en': (1115, 646, 1257, 683), 'jp': (1140, 643, 1261, 687), 'tw': (1144, 642, 1261, 687)}, color={'cn': (71, 156, 246), 'en': (77, 158, 249), 'jp': (80, 161, 242), 'tw': (75, 162, 246)}, button={'cn': (1132, 642, 1261, 687), 'en': (1115, 646, 1257, 683), 'jp': (1140, 643, 1261, 687), 'tw': (1144, 642, 1261, 687)}, file={'cn': './assets/cn/guild/GUILD_BOSS_ENTER.png', 'en': './assets/en/guild/GUILD_BOSS_ENTER.png', 'jp': './assets/jp/guild/GUILD_BOSS_ENTER.png', 'tw': './assets/tw/guild/GUILD_BOSS_ENTER.png'})
|
||||
GUILD_DISPATCH_CLOSE = Button(area={'cn': (1236, 102, 1266, 133), 'en': (1236, 102, 1266, 133), 'jp': (1236, 102, 1266, 133), 'tw': (1236, 102, 1266, 133)}, color={'cn': (88, 39, 38), 'en': (88, 39, 38), 'jp': (88, 39, 38), 'tw': (88, 39, 38)}, button={'cn': (1236, 102, 1266, 133), 'en': (1236, 102, 1266, 133), 'jp': (1236, 102, 1266, 133), 'tw': (1236, 102, 1266, 133)}, file={'cn': './assets/cn/guild/GUILD_DISPATCH_CLOSE.png', 'en': './assets/en/guild/GUILD_DISPATCH_CLOSE.png', 'jp': './assets/jp/guild/GUILD_DISPATCH_CLOSE.png', 'tw': './assets/tw/guild/GUILD_DISPATCH_CLOSE.png'})
|
||||
|
@ -40,6 +40,18 @@ class LoginHandler(Combat):
|
||||
self.device.get_orientation()
|
||||
orientation_timer.reset()
|
||||
|
||||
if self.appear_then_click(LOGIN_CHECK, interval=5):
|
||||
if not login_success:
|
||||
logger.info('Login success')
|
||||
login_success = True
|
||||
|
||||
if self.appear(MAIN_CHECK):
|
||||
if confirm_timer.reached():
|
||||
logger.info('Login to main confirm')
|
||||
break
|
||||
else:
|
||||
confirm_timer.reset()
|
||||
|
||||
if self.handle_get_items():
|
||||
continue
|
||||
if self.handle_get_ship():
|
||||
@ -69,18 +81,6 @@ class LoginHandler(Combat):
|
||||
if self.appear_then_click(GOTO_MAIN, offset=(30, 30), interval=5):
|
||||
continue
|
||||
|
||||
if self.appear_then_click(LOGIN_CHECK, interval=5):
|
||||
if not login_success:
|
||||
logger.info('Login success')
|
||||
login_success = True
|
||||
|
||||
if self.appear(MAIN_CHECK):
|
||||
if confirm_timer.reached():
|
||||
logger.info('Login to main confirm')
|
||||
break
|
||||
else:
|
||||
confirm_timer.reset()
|
||||
|
||||
self.config.start_time = datetime.now()
|
||||
return True
|
||||
|
||||
|
@ -34,7 +34,7 @@ MEOWFFICER_TRAIN_ENTER = Button(area={'cn': (1142, 581, 1258, 651), 'en': (1178,
|
||||
MEOWFFICER_TRAIN_FILL_QUEUE = Button(area={'cn': (780, 548, 859, 567), 'en': (772, 544, 866, 568), 'jp': (779, 547, 859, 569), 'tw': (778, 545, 863, 571)}, color={'cn': (205, 179, 89), 'en': (222, 198, 100), 'jp': (204, 176, 82), 'tw': (213, 187, 95)}, button={'cn': (780, 548, 859, 567), 'en': (772, 544, 866, 568), 'jp': (779, 547, 859, 569), 'tw': (778, 545, 863, 571)}, file={'cn': './assets/cn/meowfficer/MEOWFFICER_TRAIN_FILL_QUEUE.png', 'en': './assets/en/meowfficer/MEOWFFICER_TRAIN_FILL_QUEUE.png', 'jp': './assets/jp/meowfficer/MEOWFFICER_TRAIN_FILL_QUEUE.png', 'tw': './assets/tw/meowfficer/MEOWFFICER_TRAIN_FILL_QUEUE.png'})
|
||||
MEOWFFICER_TRAIN_FINISH_ALL = Button(area={'cn': (784, 551, 870, 576), 'en': (787, 552, 866, 574), 'jp': (777, 547, 860, 569), 'tw': (780, 550, 870, 576)}, color={'cn': (216, 191, 97), 'en': (218, 192, 96), 'jp': (217, 191, 94), 'tw': (213, 188, 99)}, button={'cn': (784, 551, 870, 576), 'en': (787, 552, 866, 574), 'jp': (777, 547, 860, 569), 'tw': (780, 550, 870, 576)}, file={'cn': './assets/cn/meowfficer/MEOWFFICER_TRAIN_FINISH_ALL.png', 'en': './assets/en/meowfficer/MEOWFFICER_TRAIN_FINISH_ALL.png', 'jp': './assets/jp/meowfficer/MEOWFFICER_TRAIN_FINISH_ALL.png', 'tw': './assets/tw/meowfficer/MEOWFFICER_TRAIN_FINISH_ALL.png'})
|
||||
MEOWFFICER_TRAIN_START = Button(area={'cn': (937, 553, 1024, 575), 'en': (921, 552, 1039, 577), 'jp': (930, 551, 1027, 578), 'tw': (930, 551, 1026, 576)}, color={'cn': (209, 183, 91), 'en': (220, 194, 90), 'jp': (210, 184, 87), 'tw': (211, 185, 96)}, button={'cn': (937, 553, 1024, 575), 'en': (921, 552, 1039, 577), 'jp': (930, 551, 1027, 578), 'tw': (930, 551, 1026, 576)}, file={'cn': './assets/cn/meowfficer/MEOWFFICER_TRAIN_START.png', 'en': './assets/en/meowfficer/MEOWFFICER_TRAIN_START.png', 'jp': './assets/jp/meowfficer/MEOWFFICER_TRAIN_START.png', 'tw': './assets/tw/meowfficer/MEOWFFICER_TRAIN_START.png'})
|
||||
OCR_MEOWFFICER = Button(area={'cn': (1046, 672, 1092, 693), 'en': (1054, 673, 1097, 692), 'jp': (1052, 674, 1094, 690), 'tw': (1048, 674, 1091, 692)}, color={'cn': (217, 203, 192), 'en': (210, 194, 182), 'jp': (201, 183, 171), 'tw': (201, 185, 172)}, button={'cn': (1046, 672, 1092, 693), 'en': (1054, 673, 1097, 692), 'jp': (1052, 674, 1094, 690), 'tw': (1048, 674, 1091, 692)}, file={'cn': './assets/cn/meowfficer/OCR_MEOWFFICER.png', 'en': './assets/en/meowfficer/OCR_MEOWFFICER.png', 'jp': './assets/jp/meowfficer/OCR_MEOWFFICER.png', 'tw': './assets/tw/meowfficer/OCR_MEOWFFICER.png'})
|
||||
OCR_MEOWFFICER = Button(area={'cn': (1046, 672, 1092, 693), 'en': (1054, 673, 1097, 692), 'jp': (1046, 672, 1092, 692), 'tw': (1048, 674, 1091, 692)}, color={'cn': (217, 203, 192), 'en': (210, 194, 182), 'jp': (215, 201, 189), 'tw': (201, 185, 172)}, button={'cn': (1046, 672, 1092, 693), 'en': (1054, 673, 1097, 692), 'jp': (1046, 672, 1092, 692), 'tw': (1048, 674, 1091, 692)}, file={'cn': './assets/cn/meowfficer/OCR_MEOWFFICER.png', 'en': './assets/en/meowfficer/OCR_MEOWFFICER.png', 'jp': './assets/jp/meowfficer/OCR_MEOWFFICER.png', 'tw': './assets/tw/meowfficer/OCR_MEOWFFICER.png'})
|
||||
OCR_MEOWFFICER_CAPACITY = Button(area={'cn': (739, 563, 849, 597), 'en': (739, 563, 849, 597), 'jp': (739, 563, 849, 597), 'tw': (739, 563, 849, 597)}, color={'cn': (227, 225, 225), 'en': (227, 225, 225), 'jp': (227, 225, 225), 'tw': (227, 225, 225)}, button={'cn': (739, 563, 849, 597), 'en': (739, 563, 849, 597), 'jp': (739, 563, 849, 597), 'tw': (739, 563, 849, 597)}, file={'cn': './assets/cn/meowfficer/OCR_MEOWFFICER_CAPACITY.png', 'en': './assets/en/meowfficer/OCR_MEOWFFICER_CAPACITY.png', 'jp': './assets/jp/meowfficer/OCR_MEOWFFICER_CAPACITY.png', 'tw': './assets/tw/meowfficer/OCR_MEOWFFICER_CAPACITY.png'})
|
||||
OCR_MEOWFFICER_CHOOSE = Button(area={'cn': (800, 279, 862, 305), 'en': (802, 277, 882, 307), 'jp': (800, 279, 862, 305), 'tw': (800, 279, 862, 305)}, color={'cn': (244, 241, 239), 'en': (247, 245, 243), 'jp': (244, 241, 239), 'tw': (244, 241, 239)}, button={'cn': (800, 279, 862, 305), 'en': (802, 277, 882, 307), 'jp': (800, 279, 862, 305), 'tw': (800, 279, 862, 305)}, file={'cn': './assets/cn/meowfficer/OCR_MEOWFFICER_CHOOSE.png', 'en': './assets/en/meowfficer/OCR_MEOWFFICER_CHOOSE.png', 'jp': './assets/jp/meowfficer/OCR_MEOWFFICER_CHOOSE.png', 'tw': './assets/tw/meowfficer/OCR_MEOWFFICER_CHOOSE.png'})
|
||||
OCR_MEOWFFICER_COINS = Button(area={'cn': (1161, 20, 1261, 48), 'en': (1161, 20, 1261, 48), 'jp': (1161, 20, 1261, 48), 'tw': (1160, 20, 1256, 49)}, color={'cn': (200, 198, 192), 'en': (200, 198, 192), 'jp': (200, 198, 192), 'tw': (200, 198, 192)}, button={'cn': (1161, 20, 1261, 48), 'en': (1161, 20, 1261, 48), 'jp': (1161, 20, 1261, 48), 'tw': (1160, 20, 1256, 49)}, file={'cn': './assets/cn/meowfficer/OCR_MEOWFFICER_COINS.png', 'en': './assets/en/meowfficer/OCR_MEOWFFICER_COINS.png', 'jp': './assets/jp/meowfficer/OCR_MEOWFFICER_COINS.png', 'tw': './assets/tw/meowfficer/OCR_MEOWFFICER_COINS.png'})
|
||||
|
@ -87,6 +87,7 @@ class OSMap(OSFleet, Map, GlobeCamera):
|
||||
self.zone = self.get_globe_pinned_zone()
|
||||
self.zone_config_set()
|
||||
self.os_globe_goto_map()
|
||||
self.zone_init(fallback_init=False)
|
||||
return self.zone
|
||||
|
||||
def globe_goto(self, zone, types=('SAFE', 'DANGEROUS'), refresh=False, stop_if_safe=False):
|
||||
|
@ -55,6 +55,10 @@ class OSMapOperation(MapOrderHandler, MissionHandler, PortHandler, StorageHandle
|
||||
name = name.replace('é', 'e')
|
||||
if 'nvcity' in name: # NY City Port read as 'V' rather than 'Y'
|
||||
name = 'nycity'
|
||||
if 'cibraltar' in name:
|
||||
name = 'gibraltar'
|
||||
if 'pasage' in name:
|
||||
name = 'passage'
|
||||
# `-` is missing
|
||||
name = name.replace('safe', '')
|
||||
name = name.replace('zone', '')
|
||||
@ -133,13 +137,14 @@ class OSMapOperation(MapOrderHandler, MissionHandler, PortHandler, StorageHandle
|
||||
self.config.HOMO_EDGE_COLOR_RANGE = (0, 33)
|
||||
self.config.MAP_ENSURE_EDGE_INSIGHT_CORNER = ''
|
||||
|
||||
def zone_init(self, skip_first_screenshot=True):
|
||||
def zone_init(self, fallback_init=True, skip_first_screenshot=True):
|
||||
"""
|
||||
Wrap get_current_zone(), set self.zone to the current zone.
|
||||
This method must be called after entering a new zone.
|
||||
Handle map events and the animation that zone names appear from the top.
|
||||
|
||||
Args:
|
||||
fallback_init (bool): Whether to get zone from globe map when unable to parse zone name.
|
||||
skip_first_screenshot (bool):
|
||||
|
||||
Returns:
|
||||
@ -180,14 +185,15 @@ class OSMapOperation(MapOrderHandler, MissionHandler, PortHandler, StorageHandle
|
||||
timeout.reset()
|
||||
continue
|
||||
|
||||
logger.warning('Unable to get zone name, get current zone from globe map instead')
|
||||
if hasattr(self, 'get_current_zone_from_globe'):
|
||||
return self.get_current_zone_from_globe()
|
||||
else:
|
||||
logger.warning('OperationSiren.get_current_zone_from_globe() not exists')
|
||||
if not self.is_in_map():
|
||||
logger.warning('Trying to get zone name, but not in OS map')
|
||||
return self.get_current_zone()
|
||||
if fallback_init:
|
||||
logger.warning('Unable to get zone name, get current zone from globe map instead')
|
||||
if hasattr(self, 'get_current_zone_from_globe'):
|
||||
return self.get_current_zone_from_globe()
|
||||
else:
|
||||
logger.warning('OperationSiren.get_current_zone_from_globe() not exists')
|
||||
if not self.is_in_map():
|
||||
logger.warning('Trying to get zone name, but not in OS map')
|
||||
return self.get_current_zone()
|
||||
|
||||
def is_in_special_zone(self):
|
||||
"""
|
||||
|
@ -18,7 +18,6 @@ DETAIL_GENRE_T = Button(area={'cn': (323, 110, 418, 133), 'en': (323, 110, 418,
|
||||
DETAIL_ITEMS_ODD = Button(area={'cn': (408, 447, 422, 525), 'en': (408, 447, 422, 525), 'jp': (408, 447, 422, 525), 'tw': (408, 447, 422, 525)}, color={'cn': (145, 169, 164), 'en': (145, 169, 164), 'jp': (145, 169, 164), 'tw': (145, 169, 164)}, button={'cn': (408, 447, 422, 525), 'en': (408, 447, 422, 525), 'jp': (408, 447, 422, 525), 'tw': (408, 447, 422, 525)}, file={'cn': './assets/cn/research/DETAIL_ITEMS_ODD.png', 'en': './assets/en/research/DETAIL_ITEMS_ODD.png', 'jp': './assets/jp/research/DETAIL_ITEMS_ODD.png', 'tw': './assets/tw/research/DETAIL_ITEMS_ODD.png'})
|
||||
DETAIL_NEXT = Button(area={'cn': (1236, 347, 1257, 374), 'en': (1236, 347, 1257, 374), 'jp': (1236, 347, 1257, 374), 'tw': (1236, 347, 1257, 374)}, color={'cn': (98, 148, 165), 'en': (98, 148, 165), 'jp': (98, 148, 165), 'tw': (98, 148, 165)}, button={'cn': (1236, 347, 1257, 374), 'en': (1236, 347, 1257, 374), 'jp': (1236, 347, 1257, 374), 'tw': (1236, 347, 1257, 374)}, file={'cn': './assets/cn/research/DETAIL_NEXT.png', 'en': './assets/en/research/DETAIL_NEXT.png', 'jp': './assets/jp/research/DETAIL_NEXT.png', 'tw': './assets/tw/research/DETAIL_NEXT.png'})
|
||||
DURATION_DETAIL = Button(area={'cn': (788, 274, 913, 319), 'en': (788, 274, 913, 319), 'jp': (788, 274, 913, 319), 'tw': (788, 274, 913, 319)}, color={'cn': (102, 112, 132), 'en': (102, 112, 132), 'jp': (102, 112, 132), 'tw': (102, 112, 132)}, button={'cn': (788, 274, 913, 319), 'en': (788, 274, 913, 319), 'jp': (788, 274, 913, 319), 'tw': (788, 274, 913, 319)}, file={'cn': './assets/cn/research/DURATION_DETAIL.png', 'en': './assets/en/research/DURATION_DETAIL.png', 'jp': './assets/jp/research/DURATION_DETAIL.png', 'tw': './assets/tw/research/DURATION_DETAIL.png'})
|
||||
DURATION_REMAIN = Button(area={'cn': (622, 579, 732, 613), 'en': (622, 579, 732, 613), 'jp': (622, 579, 732, 613), 'tw': (622, 579, 732, 613)}, color={'cn': (188, 211, 239), 'en': (188, 211, 239), 'jp': (188, 211, 239), 'tw': (188, 211, 239)}, button={'cn': (622, 579, 732, 613), 'en': (622, 579, 732, 613), 'jp': (622, 579, 732, 613), 'tw': (622, 579, 732, 613)}, file={'cn': './assets/cn/research/DURATION_REMAIN.png', 'en': './assets/en/research/DURATION_REMAIN.png', 'jp': './assets/jp/research/DURATION_REMAIN.png', 'tw': './assets/tw/research/DURATION_REMAIN.png'})
|
||||
ENTRANCE_1 = Button(area={'cn': (52, 186, 198, 375), 'en': (52, 186, 198, 375), 'jp': (52, 186, 198, 375), 'tw': (52, 186, 198, 375)}, color={'cn': (110, 162, 216), 'en': (110, 162, 216), 'jp': (110, 162, 216), 'tw': (110, 162, 216)}, button={'cn': (52, 186, 198, 375), 'en': (52, 186, 198, 375), 'jp': (52, 186, 198, 375), 'tw': (52, 186, 198, 375)}, file={'cn': './assets/cn/research/ENTRANCE_1.png', 'en': './assets/en/research/ENTRANCE_1.png', 'jp': './assets/jp/research/ENTRANCE_1.png', 'tw': './assets/tw/research/ENTRANCE_1.png'})
|
||||
ENTRANCE_2 = Button(area={'cn': (296, 157, 465, 376), 'en': (296, 157, 465, 376), 'jp': (296, 157, 465, 376), 'tw': (296, 157, 465, 376)}, color={'cn': (110, 162, 216), 'en': (110, 162, 216), 'jp': (110, 162, 216), 'tw': (110, 162, 216)}, button={'cn': (296, 157, 465, 376), 'en': (296, 157, 465, 376), 'jp': (296, 157, 465, 376), 'tw': (296, 157, 465, 376)}, file={'cn': './assets/cn/research/ENTRANCE_2.png', 'en': './assets/en/research/ENTRANCE_2.png', 'jp': './assets/jp/research/ENTRANCE_2.png', 'tw': './assets/tw/research/ENTRANCE_2.png'})
|
||||
ENTRANCE_3 = Button(area={'cn': (542, 130, 730, 378), 'en': (542, 130, 730, 378), 'jp': (542, 130, 730, 378), 'tw': (542, 130, 730, 378)}, color={'cn': (224, 190, 135), 'en': (224, 190, 135), 'jp': (224, 190, 135), 'tw': (224, 190, 135)}, button={'cn': (542, 130, 730, 378), 'en': (542, 130, 730, 378), 'jp': (542, 130, 730, 378), 'tw': (542, 130, 730, 378)}, file={'cn': './assets/cn/research/ENTRANCE_3.png', 'en': './assets/en/research/ENTRANCE_3.png', 'jp': './assets/jp/research/ENTRANCE_3.png', 'tw': './assets/tw/research/ENTRANCE_3.png'})
|
||||
|
@ -1,6 +1,5 @@
|
||||
import numpy as np
|
||||
|
||||
from module.base.decorator import Config
|
||||
from module.base.timer import Timer
|
||||
from module.base.utils import rgb2gray
|
||||
from module.combat.assets import GET_ITEMS_1, GET_ITEMS_2, GET_ITEMS_3
|
||||
@ -326,38 +325,6 @@ class RewardResearch(ResearchSelector):
|
||||
|
||||
return True
|
||||
|
||||
@Config.when(SERVER='jp')
|
||||
def research_get_remain(self):
|
||||
"""
|
||||
Get remain duration of current project (the one in the middle).
|
||||
|
||||
Returns:
|
||||
float: research project remain time if success
|
||||
None: if failed
|
||||
|
||||
Pages:
|
||||
in: page_research, stable.
|
||||
out: page_research, stable.
|
||||
"""
|
||||
ocr = Duration(DURATION_REMAIN, letter=(255, 255, 255), threshold=64, name='DURATION_REMAIN')
|
||||
|
||||
logger.hr('Research get remain')
|
||||
|
||||
self.interval_clear(MAIN_GOTO_CAMPAIGN)
|
||||
self.ui_ensure_research()
|
||||
|
||||
remain = ocr.ocr(self.device.image)
|
||||
logger.info(f'Research project remain: {remain}')
|
||||
|
||||
seconds = remain.total_seconds()
|
||||
if seconds >= 0:
|
||||
research_duration_remain = seconds / 3600
|
||||
return research_duration_remain
|
||||
else:
|
||||
logger.warning(f'Invalid research duration: {seconds} ')
|
||||
return None
|
||||
|
||||
@Config.when(SERVER=None)
|
||||
def research_get_remain(self):
|
||||
"""
|
||||
Get remain duration of current project from page_reward.
|
||||
|
@ -19,6 +19,7 @@ SHIPYARD_PROGRESS_DEV = Button(area={'cn': (1184, 145, 1273, 175), 'en': (1184,
|
||||
SHIPYARD_PROGRESS_FATE = Button(area={'cn': (1141, 153, 1278, 190), 'en': (1141, 153, 1278, 190), 'jp': (1189, 151, 1267, 188), 'tw': (1141, 153, 1278, 190)}, color={'cn': (82, 85, 89), 'en': (82, 85, 89), 'jp': (120, 121, 125), 'tw': (82, 85, 89)}, button={'cn': (1141, 153, 1278, 190), 'en': (1141, 153, 1278, 190), 'jp': (1189, 151, 1267, 188), 'tw': (1141, 153, 1278, 190)}, file={'cn': './assets/cn/shipyard/SHIPYARD_PROGRESS_FATE.png', 'en': './assets/en/shipyard/SHIPYARD_PROGRESS_FATE.png', 'jp': './assets/jp/shipyard/SHIPYARD_PROGRESS_FATE.png', 'tw': './assets/tw/shipyard/SHIPYARD_PROGRESS_FATE.png'})
|
||||
SHIPYARD_RESEARCH_COMPLETE = Button(area={'cn': (548, 498, 740, 531), 'en': (548, 498, 740, 531), 'jp': (536, 494, 731, 538), 'tw': (548, 498, 740, 531)}, color={'cn': (214, 142, 124), 'en': (214, 142, 124), 'jp': (208, 120, 95), 'tw': (214, 142, 124)}, button={'cn': (548, 498, 740, 531), 'en': (548, 498, 740, 531), 'jp': (536, 494, 731, 538), 'tw': (548, 498, 740, 531)}, file={'cn': './assets/cn/shipyard/SHIPYARD_RESEARCH_COMPLETE.png', 'en': './assets/en/shipyard/SHIPYARD_RESEARCH_COMPLETE.png', 'jp': './assets/jp/shipyard/SHIPYARD_RESEARCH_COMPLETE.png', 'tw': './assets/tw/shipyard/SHIPYARD_RESEARCH_COMPLETE.png'})
|
||||
SHIPYARD_RESEARCH_INCOMPLETE = Button(area={'cn': (616, 490, 740, 531), 'en': (616, 490, 740, 531), 'jp': (614, 493, 735, 521), 'tw': (616, 490, 740, 531)}, color={'cn': (229, 192, 121), 'en': (229, 192, 121), 'jp': (244, 219, 164), 'tw': (229, 192, 121)}, button={'cn': (616, 490, 740, 531), 'en': (616, 490, 740, 531), 'jp': (614, 493, 735, 521), 'tw': (616, 490, 740, 531)}, file={'cn': './assets/cn/shipyard/SHIPYARD_RESEARCH_INCOMPLETE.png', 'en': './assets/en/shipyard/SHIPYARD_RESEARCH_INCOMPLETE.png', 'jp': './assets/jp/shipyard/SHIPYARD_RESEARCH_INCOMPLETE.png', 'tw': './assets/tw/shipyard/SHIPYARD_RESEARCH_INCOMPLETE.png'})
|
||||
SHIPYARD_RESEARCH_IN_PROGRESS = Button(area={'cn': (465, 479, 482, 501), 'en': (465, 479, 482, 501), 'jp': (465, 479, 482, 501), 'tw': (465, 479, 482, 501)}, color={'cn': (105, 135, 173), 'en': (105, 135, 173), 'jp': (105, 135, 173), 'tw': (105, 135, 173)}, button={'cn': (465, 479, 482, 501), 'en': (465, 479, 482, 501), 'jp': (465, 479, 482, 501), 'tw': (465, 479, 482, 501)}, file={'cn': './assets/cn/shipyard/SHIPYARD_RESEARCH_IN_PROGRESS.png', 'en': './assets/en/shipyard/SHIPYARD_RESEARCH_IN_PROGRESS.png', 'jp': './assets/jp/shipyard/SHIPYARD_RESEARCH_IN_PROGRESS.png', 'tw': './assets/tw/shipyard/SHIPYARD_RESEARCH_IN_PROGRESS.png'})
|
||||
SHIPYARD_SERIES_SELECT_CHECK = Button(area={'cn': (567, 209, 717, 228), 'en': (567, 209, 717, 228), 'jp': (566, 210, 718, 228), 'tw': (567, 209, 717, 228)}, color={'cn': (21, 30, 58), 'en': (21, 30, 58), 'jp': (21, 30, 58), 'tw': (21, 30, 58)}, button={'cn': (567, 209, 717, 228), 'en': (567, 209, 717, 228), 'jp': (566, 210, 718, 228), 'tw': (567, 209, 717, 228)}, file={'cn': './assets/cn/shipyard/SHIPYARD_SERIES_SELECT_CHECK.png', 'en': './assets/en/shipyard/SHIPYARD_SERIES_SELECT_CHECK.png', 'jp': './assets/jp/shipyard/SHIPYARD_SERIES_SELECT_CHECK.png', 'tw': './assets/tw/shipyard/SHIPYARD_SERIES_SELECT_CHECK.png'})
|
||||
SHIPYARD_SERIES_SELECT_ENTER = Button(area={'cn': (33, 659, 161, 701), 'en': (34, 659, 160, 700), 'jp': (36, 674, 154, 696), 'tw': (33, 657, 157, 697)}, color={'cn': (91, 110, 155), 'en': (66, 87, 138), 'jp': (112, 126, 161), 'tw': (98, 117, 164)}, button={'cn': (33, 659, 161, 701), 'en': (34, 659, 160, 700), 'jp': (36, 674, 154, 696), 'tw': (33, 657, 157, 697)}, file={'cn': './assets/cn/shipyard/SHIPYARD_SERIES_SELECT_ENTER.png', 'en': './assets/en/shipyard/SHIPYARD_SERIES_SELECT_ENTER.png', 'jp': './assets/jp/shipyard/SHIPYARD_SERIES_SELECT_ENTER.png', 'tw': './assets/tw/shipyard/SHIPYARD_SERIES_SELECT_ENTER.png'})
|
||||
SHIPYARD_TOTAL_DEV = Button(area={'cn': (1086, 429, 1147, 463), 'en': (1091, 426, 1142, 466), 'jp': (1086, 429, 1147, 463), 'tw': (1086, 429, 1147, 463)}, color={'cn': (39, 46, 55), 'en': (45, 48, 55), 'jp': (39, 46, 55), 'tw': (39, 46, 55)}, button={'cn': (1086, 429, 1147, 463), 'en': (1091, 426, 1142, 466), 'jp': (1086, 429, 1147, 463), 'tw': (1086, 429, 1147, 463)}, file={'cn': './assets/cn/shipyard/SHIPYARD_TOTAL_DEV.png', 'en': './assets/en/shipyard/SHIPYARD_TOTAL_DEV.png', 'jp': './assets/jp/shipyard/SHIPYARD_TOTAL_DEV.png', 'tw': './assets/tw/shipyard/SHIPYARD_TOTAL_DEV.png'})
|
||||
|
@ -4,6 +4,7 @@ from module.logger import logger
|
||||
from module.shipyard.assets import *
|
||||
from module.shipyard.ui_globals import *
|
||||
from module.ui.navbar import Navbar
|
||||
from module.ui.assets import SHIPYARD_CHECK
|
||||
from module.ui.ui import UI
|
||||
|
||||
|
||||
@ -126,6 +127,8 @@ class ShipyardUI(UI):
|
||||
Returns:
|
||||
bool whether in appropriate shipyard ui area
|
||||
"""
|
||||
if self.appear(SHIPYARD_CHECK, offset=(20, 20)):
|
||||
return True
|
||||
if self.appear(SHIPYARD_IN_DEV, offset=(20, 20)):
|
||||
return True
|
||||
if self.appear(SHIPYARD_IN_FATE, offset=(20, 20)):
|
||||
@ -336,7 +339,8 @@ class ShipyardUI(UI):
|
||||
Returns:
|
||||
bool whether entered
|
||||
"""
|
||||
if self.appear(SHIPYARD_RESEARCH_INCOMPLETE, offset=(20, 20)):
|
||||
if self.appear(SHIPYARD_RESEARCH_INCOMPLETE, offset=(20, 20)) or \
|
||||
self.appear(SHIPYARD_RESEARCH_IN_PROGRESS, offset=(20, 20)):
|
||||
logger.warning('Cannot enter buy interface, focused '
|
||||
'ship has not yet been fully researched')
|
||||
return False
|
||||
|
@ -78,6 +78,7 @@ class CampaignSos(CampaignRun, CampaignBase):
|
||||
def _sos_signal_select(self, chapter):
|
||||
"""
|
||||
select a SOS signal
|
||||
EN has no scroll bar, so the swipe signal list.
|
||||
|
||||
Args:
|
||||
chapter (int): 3 to 10.
|
||||
@ -139,7 +140,7 @@ class CampaignSos(CampaignRun, CampaignBase):
|
||||
|
||||
for scroll_position in positions:
|
||||
if self._sos_scroll.appear(main=self):
|
||||
self._sos_scroll.set(scroll_position, main=self)
|
||||
self._sos_scroll.set(scroll_position, main=self, distance_check=False)
|
||||
else:
|
||||
logger.info('SOS signal scroll not appear, skip setting scroll position')
|
||||
target_button = self._find_target_chapter(chapter)
|
||||
|
@ -57,7 +57,7 @@ BOOK_FILTER = Filter(
|
||||
'(same)?'
|
||||
'(red|blue|yellow)?'
|
||||
'-?'
|
||||
'(t[123])?'
|
||||
'(t[1234])?'
|
||||
),
|
||||
attr=('same_str', 'genre_str', 'tier_str'),
|
||||
preset=('first',)
|
||||
|
@ -106,7 +106,7 @@ class Scroll:
|
||||
def at_bottom(self, main):
|
||||
return self.cal_position(main) > 0.95
|
||||
|
||||
def set(self, position, main, random_range=(-0.05, 0.05), skip_first_screenshot=True):
|
||||
def set(self, position, main, random_range=(-0.05, 0.05), distance_check=True, skip_first_screenshot=True):
|
||||
"""
|
||||
Set scroll to a specific position.
|
||||
|
||||
@ -114,6 +114,7 @@ class Scroll:
|
||||
position (float, int): 0 to 1.
|
||||
main (ModuleBase):
|
||||
random_range (tuple(int, float)):
|
||||
distance_check (bool): Whether to drop short swipes
|
||||
skip_first_screenshot:
|
||||
"""
|
||||
logger.info(f'{self.name} set to {position}')
|
||||
@ -139,7 +140,7 @@ class Scroll:
|
||||
if self.drag_interval.reached():
|
||||
p1 = random_rectangle_point(self.position_to_screen(current), n=1)
|
||||
p2 = random_rectangle_point(self.position_to_screen(position, random_range=random_range), n=1)
|
||||
main.device.swipe(p1, p2, name=self.name)
|
||||
main.device.swipe(p1, p2, name=self.name, distance_check=distance_check)
|
||||
main.device.sleep(0.3)
|
||||
self.drag_interval.reset()
|
||||
|
||||
|
@ -17,7 +17,8 @@ from module.os_handler.assets import (EXCHANGE_CHECK, RESET_FLEET_PREPARATION,
|
||||
from module.raid.assets import RAID_FLEET_PREPARATION
|
||||
from module.ui.assets import (BACK_ARROW, DORM_FEED_CANCEL, DORM_INFO,
|
||||
DORM_TROPHY_CONFIRM, EVENT_LIST_CHECK, GOTO_MAIN,
|
||||
MEOWFFICER_INFO, MEOWFFICER_GOTO_DORMMENU, META_CHECK,
|
||||
MAIN_GOTO_CAMPAIGN, MEOWFFICER_INFO,
|
||||
MEOWFFICER_GOTO_DORMMENU, META_CHECK,
|
||||
PLAYER_CHECK, SHIPYARD_CHECK, SHOP_GOTO_SUPPLY_PACK)
|
||||
from module.ui.page import (Page, page_academy, page_archives,
|
||||
page_battle_pass, page_build, page_campaign,
|
||||
@ -532,5 +533,7 @@ class UI(InfoHandler):
|
||||
"""
|
||||
if button == MEOWFFICER_GOTO_DORMMENU:
|
||||
self.interval_reset(GET_SHIP)
|
||||
if button == MAIN_GOTO_CAMPAIGN:
|
||||
self.interval_reset(GET_SHIP)
|
||||
if button == SHOP_GOTO_SUPPLY_PACK:
|
||||
self.interval_reset(EXCHANGE_CHECK)
|
||||
|
@ -24,5 +24,4 @@ pypresence==4.2.1
|
||||
alas-webapp==0.3.7
|
||||
rich==11.0.0
|
||||
zerorpc==0.6.3
|
||||
pyzmq==22.3.0
|
||||
atomicwrites
|
||||
pyzmq==22.3.0
|
@ -4,14 +4,13 @@
|
||||
#
|
||||
# pip-compile --annotation-style=line --output-file=requirements.txt requirements-in.txt
|
||||
#
|
||||
adbutils==0.11.0 # via uiautomator2
|
||||
adbutils==0.11.0 # via -r requirements-in.txt, uiautomator2
|
||||
aiofiles==0.7.0 # via -r requirements-in.txt
|
||||
alas-webapp==0.3.7 # via -r requirements-in.txt
|
||||
anyio==1.3.1 # via -r requirements-in.txt
|
||||
apkutils2==1.0.0 # via adbutils
|
||||
asgiref==3.4.1 # via uvicorn
|
||||
async-generator==1.10 # via anyio
|
||||
atomicwrites==1.4.0 # via -r requirements-in.txt
|
||||
cached-property==1.5.2 # via uiautomator2
|
||||
certifi==2021.5.30 # via requests
|
||||
cffi==1.15.0 # via gevent
|
||||
@ -63,7 +62,7 @@ python-dotenv==0.19.0 # via uvicorn
|
||||
pywebio==1.5.2 # via -r requirements-in.txt
|
||||
pywin32==301 # via portalocker
|
||||
pyyaml==5.4.1 # via -r requirements-in.txt, uvicorn
|
||||
pyzmq==22.3.0 # via zerorpc
|
||||
pyzmq==22.3.0 # via -r requirements-in.txt, zerorpc
|
||||
requests==2.18.4 # via adbutils, gluoncv, mxnet, uiautomator2
|
||||
retry==0.9.2 # via adbutils, uiautomator2
|
||||
retrying==1.3.3 # via -r requirements-in.txt
|
||||
|