mirror of
https://github.com/LmeSzinc/StarRailCopilot.git
synced 2024-11-22 00:35:34 +00:00
Add: synthesize_amount_set()
This commit is contained in:
parent
fc8ce808ca
commit
3783066cd7
BIN
assets/share/item/synthesize/SYNTHESIZE_SLIDER.png
Normal file
BIN
assets/share/item/synthesize/SYNTHESIZE_SLIDER.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 7.0 KiB |
@ -248,6 +248,7 @@ class AdaptiveScroll(Scroll):
|
||||
'prominence': 30,
|
||||
'wlen': wlen,
|
||||
'width': 2,
|
||||
# 'distance': wlen / 2,
|
||||
}
|
||||
parameters.update(self.parameters)
|
||||
peaks, _ = signal.find_peaks(image, **parameters)
|
||||
|
@ -83,3 +83,13 @@ SYNTHESIZE_PLUS = ButtonWrapper(
|
||||
button=(1125, 567, 1155, 589),
|
||||
),
|
||||
)
|
||||
SYNTHESIZE_SLIDER = ButtonWrapper(
|
||||
name='SYNTHESIZE_SLIDER',
|
||||
share=Button(
|
||||
file='./assets/share/item/synthesize/SYNTHESIZE_SLIDER.png',
|
||||
area=(660, 575, 1070, 581),
|
||||
search=(640, 555, 1090, 601),
|
||||
color=(118, 96, 77),
|
||||
button=(660, 575, 1070, 581),
|
||||
),
|
||||
)
|
||||
|
149
tasks/item/slider.py
Normal file
149
tasks/item/slider.py
Normal file
@ -0,0 +1,149 @@
|
||||
import numpy as np
|
||||
from scipy import signal
|
||||
|
||||
from module.base.button import ButtonWrapper, ClickButton
|
||||
from module.base.timer import Timer
|
||||
from module.base.utils import rgb2gray
|
||||
from module.exception import ScriptError
|
||||
from module.logger import logger
|
||||
from tasks.base.ui import UI
|
||||
|
||||
|
||||
class Slider:
|
||||
def __init__(
|
||||
self,
|
||||
main: UI,
|
||||
slider: ButtonWrapper,
|
||||
parameters: dict = None,
|
||||
background=5
|
||||
):
|
||||
"""
|
||||
Args:
|
||||
main:
|
||||
slider: Slider button
|
||||
parameters (dict): Parameters passing to scipy.find_peaks
|
||||
background (int):
|
||||
"""
|
||||
self.main = main
|
||||
self.slider = slider
|
||||
|
||||
if parameters is None:
|
||||
parameters = {}
|
||||
self.parameters = parameters
|
||||
self.background = background
|
||||
|
||||
# Actual slider area
|
||||
self.area = self.slider.area
|
||||
|
||||
def cal_slider(self):
|
||||
"""
|
||||
Slider always have its left side fixed, right side movable depending on the maximum number
|
||||
Calculate the right side, similar to AdaptiveScroll.match_color
|
||||
"""
|
||||
area = self.slider.area
|
||||
area = (area[0], area[1] - self.background, area[2], area[3] + self.background)
|
||||
image = self.main.image_crop(area, copy=False)
|
||||
image = rgb2gray(image)
|
||||
image = image.flatten('F')
|
||||
wlen = area[3] - area[1]
|
||||
total = area[2] - area[0]
|
||||
|
||||
parameters = {
|
||||
'prominence': 15,
|
||||
'wlen': wlen,
|
||||
'width': 4,
|
||||
'distance': wlen / 2,
|
||||
}
|
||||
parameters.update(self.parameters)
|
||||
peaks, _ = signal.find_peaks(image, **parameters)
|
||||
peaks //= wlen
|
||||
|
||||
# Ignore non-continuous peaks, which may be the letter to the right of slider
|
||||
try:
|
||||
right = np.where(np.diff(peaks) >= 3)[0][0]
|
||||
peaks = peaks[:right + 1]
|
||||
except IndexError:
|
||||
pass
|
||||
# Calculate actual slider area
|
||||
try:
|
||||
length = peaks[-1]
|
||||
self.area = (area[0], area[1], area[0] + length + 1, area[3])
|
||||
except IndexError:
|
||||
length = total
|
||||
self.area = self.slider.area
|
||||
logger.info(f'Slider length: {length}/{total}')
|
||||
|
||||
def set(self, value: int, total: int, skip_first_screenshot=True):
|
||||
"""
|
||||
Args:
|
||||
value: Value to set
|
||||
total: Maximum amount of slider
|
||||
skip_first_screenshot:
|
||||
|
||||
Returns:
|
||||
bool: If success
|
||||
"""
|
||||
logger.info(f'Slider set {value}/{total}')
|
||||
if value > total:
|
||||
raise ScriptError(f'Slider.set value {value} > total {total}')
|
||||
if total <= 0:
|
||||
raise ScriptError(f'Slider.set total {total} <= 0')
|
||||
if value <= 0:
|
||||
raise ScriptError(f'Slider.set value {value} <= 0')
|
||||
if value == total == 1:
|
||||
logger.info('Slider set total==1, no need to set')
|
||||
return True
|
||||
# if value == 1:
|
||||
# logger.info('Slider set value==1, no need to set')
|
||||
# return True
|
||||
|
||||
self.cal_slider()
|
||||
|
||||
# 18px is the width of controller
|
||||
length = self.area[2] - self.area[0] - 18
|
||||
|
||||
left = int((value - 2) / (total - 1) * length) + self.area[0]
|
||||
right = int((value - 1) / (total - 1) * length) + self.area[0]
|
||||
if right <= left:
|
||||
right = left + 1
|
||||
# 10px is the radius of slider controller
|
||||
# When you somewhere on the slider, left edge of controller is where you click
|
||||
# if right - left < 10:
|
||||
# logger.info('Setting high maximum slider')
|
||||
# left -= 10
|
||||
# right -= 10
|
||||
|
||||
# Limit in slider
|
||||
left = max(min(self.area[2] - 1, left), self.area[0])
|
||||
right = max(min(self.area[2], right), self.area[0] + 1)
|
||||
# Click the right half
|
||||
left = int((left + right) / 2)
|
||||
button = ClickButton(
|
||||
(left, self.area[1], right, self.area[3]),
|
||||
name=f'Slider_{value}_{total}')
|
||||
# Pad click area to search
|
||||
pad = 15
|
||||
detect = (right - pad, self.area[1], right + pad, self.area[3])
|
||||
logger.info(f'Controller button={button.button}, detect={detect}')
|
||||
|
||||
interval = Timer(1, count=3)
|
||||
trial = 0
|
||||
while 1:
|
||||
if skip_first_screenshot:
|
||||
skip_first_screenshot = False
|
||||
else:
|
||||
self.main.device.screenshot()
|
||||
|
||||
# End
|
||||
if trial > 3:
|
||||
logger.warning('Slider.set failed after 3 trial')
|
||||
return False
|
||||
if self.main.image_color_count(detect, color=(255, 255, 255), threshold=221, count=50):
|
||||
logger.info('Slider set done')
|
||||
return True
|
||||
|
||||
# Click
|
||||
if interval.reached():
|
||||
self.main.device.click(button)
|
||||
interval.reset()
|
||||
trial += 1
|
@ -1,16 +1,18 @@
|
||||
import cv2
|
||||
import numpy as np
|
||||
|
||||
import module.config.server as server
|
||||
from module.base.decorator import cached_property
|
||||
from module.base.timer import Timer
|
||||
from module.base.utils import SelectedGrids, color_similarity_2d, crop, image_size
|
||||
from module.exception import ScriptError
|
||||
from module.logger import logger
|
||||
from module.ocr.ocr import Ocr
|
||||
from module.ocr.ocr import Digit, Ocr
|
||||
from tasks.base.page import page_synthesize
|
||||
from tasks.combat.obtain import CombatObtain
|
||||
from tasks.item.assets.assets_item_synthesize import *
|
||||
from tasks.item.inventory import InventoryManager
|
||||
from tasks.item.slider import Slider
|
||||
from tasks.planner.keywords import ITEM_CLASSES, ItemCalyx, ItemTrace
|
||||
from tasks.planner.keywords.classes import ItemBase
|
||||
from tasks.planner.model import ObtainedAmmount
|
||||
@ -332,6 +334,18 @@ class Synthesize(CombatObtain):
|
||||
logger.error(f'Unexpected switch_row={switch_row} during loop')
|
||||
return False
|
||||
|
||||
def synthesize_amount_set(self, value: int, total: int):
|
||||
"""
|
||||
Args:
|
||||
value: Value to set
|
||||
total: Maximum amount of slider
|
||||
"""
|
||||
logger.hr('Synthesize amount set', level=2)
|
||||
slider = Slider(main=self, slider=SYNTHESIZE_SLIDER)
|
||||
slider.set(value, total)
|
||||
ocr = Digit(SYNTHESIZE_AMOUNT, lang=server.lang)
|
||||
self.ui_ensure_index(
|
||||
value, letter=ocr, next_button=SYNTHESIZE_PLUS, prev_button=SYNTHESIZE_MINUS, interval=(0.1, 0.2))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
Loading…
Reference in New Issue
Block a user