Add: synthesize_amount_set()

This commit is contained in:
LmeSzinc 2024-06-12 23:12:45 +08:00
parent fc8ce808ca
commit 3783066cd7
5 changed files with 175 additions and 1 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

View File

@ -248,6 +248,7 @@ class AdaptiveScroll(Scroll):
'prominence': 30, 'prominence': 30,
'wlen': wlen, 'wlen': wlen,
'width': 2, 'width': 2,
# 'distance': wlen / 2,
} }
parameters.update(self.parameters) parameters.update(self.parameters)
peaks, _ = signal.find_peaks(image, **parameters) peaks, _ = signal.find_peaks(image, **parameters)

View File

@ -83,3 +83,13 @@ SYNTHESIZE_PLUS = ButtonWrapper(
button=(1125, 567, 1155, 589), 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
View 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

View File

@ -1,16 +1,18 @@
import cv2 import cv2
import numpy as np import numpy as np
import module.config.server as server
from module.base.decorator import cached_property from module.base.decorator import cached_property
from module.base.timer import Timer from module.base.timer import Timer
from module.base.utils import SelectedGrids, color_similarity_2d, crop, image_size from module.base.utils import SelectedGrids, color_similarity_2d, crop, image_size
from module.exception import ScriptError from module.exception import ScriptError
from module.logger import logger 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.base.page import page_synthesize
from tasks.combat.obtain import CombatObtain from tasks.combat.obtain import CombatObtain
from tasks.item.assets.assets_item_synthesize import * from tasks.item.assets.assets_item_synthesize import *
from tasks.item.inventory import InventoryManager 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 import ITEM_CLASSES, ItemCalyx, ItemTrace
from tasks.planner.keywords.classes import ItemBase from tasks.planner.keywords.classes import ItemBase
from tasks.planner.model import ObtainedAmmount from tasks.planner.model import ObtainedAmmount
@ -332,6 +334,18 @@ class Synthesize(CombatObtain):
logger.error(f'Unexpected switch_row={switch_row} during loop') logger.error(f'Unexpected switch_row={switch_row} during loop')
return False 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__': if __name__ == '__main__':