234 lines
8.5 KiB
Python
234 lines
8.5 KiB
Python
from datetime import datetime
|
|
|
|
import cv2
|
|
import numpy as np
|
|
|
|
from mower.models import secret_front
|
|
from mower.solvers.infra.base_mixin import BaseMixin
|
|
from mower.solvers.infra.enter_room import EnterRoomSolver
|
|
from mower.solvers.infra.filter import RIIC_Filter
|
|
from mower.utils import config
|
|
from mower.utils.character_recognize import (
|
|
match_portrait,
|
|
operator_room_select,
|
|
)
|
|
from mower.utils.graph import SceneGraphSolver
|
|
from mower.utils.image import cropimg
|
|
from mower.utils.log import logger
|
|
from mower.utils.scene import Scene
|
|
from mower.utils.vector import sa, va
|
|
|
|
|
|
class RIIC_ChooseSolver(SceneGraphSolver, BaseMixin):
|
|
def run(self, room: str, agent_list: list, wait_time: float = 0) -> bool:
|
|
self.room = room
|
|
self.agent_list = agent_list
|
|
self.wait_time = wait_time
|
|
self.wait_choose = {}
|
|
self.choosed = []
|
|
self.cleard = False
|
|
self.filter = RIIC_Filter()
|
|
self.swipe_time = 0
|
|
self.first_filter = True
|
|
self.in_adjust = False
|
|
self.tmp_data = {}
|
|
self.tmp_checked = {}
|
|
self.start_time = datetime.now()
|
|
self.success = False
|
|
self.check_room()
|
|
try:
|
|
return super().run()
|
|
except ValueError as e:
|
|
logger.error(e.__traceback__)
|
|
return False
|
|
|
|
def riic_agent_choose(self):
|
|
if (
|
|
len(list(set(self.choosed) & set(self.agent_list))) == len(self.agent_list)
|
|
and len(self.agent_list) > 1
|
|
):
|
|
if self.check_agent_order():
|
|
return True
|
|
else:
|
|
return
|
|
|
|
if self.first_filter:
|
|
if self.first_filter:
|
|
self.filter.run(技能=False)
|
|
self.first_filter = False
|
|
choosed_pos = self.get_agent_pos()
|
|
if choosed_pos:
|
|
if len(self.agent_list) > 1:
|
|
self.tap_element("choose_agent/clear", interval=0.1)
|
|
else:
|
|
tap_pos = choosed_pos.popitem()[1][0]
|
|
self.tap(self.tap(va(tap_pos, (100, 100))), interval=0.1)
|
|
self.first_filter = False
|
|
return
|
|
|
|
if len(self.wait_choose) > 0:
|
|
logger.debug(f"待选名单{self.wait_choose}")
|
|
choosed_pos = self.get_agent_pos()
|
|
for name, pos in list(self.wait_choose.items()):
|
|
if name in list(choosed_pos):
|
|
if len(self.agent_list) == 1:
|
|
return True
|
|
self.choosed.append(name)
|
|
del self.wait_choose[name]
|
|
else:
|
|
logger.info(f"tap:{name},{pos}")
|
|
self.tap(va(pos[0], (100, 100)), interval=0.2)
|
|
logger.debug(f"待选名单{self.wait_choose}")
|
|
return
|
|
agents = dict(operator_room_select(config.recog.img))
|
|
if set(agents.keys()).issubset(self.tmp_data.keys()):
|
|
self.swipe_time = self.swipe_time + 1
|
|
if self.swipe_time > 3:
|
|
raise ValueError("选择干员失败 滑动次数过多")
|
|
else:
|
|
self.swipe_time = 0
|
|
|
|
self.tmp_data = agents
|
|
logger.info(agents)
|
|
intersection = list(set(agents.keys()) & set(self.agent_list))
|
|
|
|
if intersection:
|
|
for i in intersection:
|
|
if i not in self.choosed:
|
|
self.wait_choose[i] = agents[i]
|
|
if self.wait_choose:
|
|
return
|
|
else:
|
|
# 加一个判断最右
|
|
self.swipe_noinertia((1000, 540), (-1900, 0), interval=0.1)
|
|
|
|
def check_agent_order(self):
|
|
choosed_agents = self.get_agent_pos(no_number=False)
|
|
logger.info(f"{choosed_agents}{self.agent_list}")
|
|
if len(choosed_agents) < len(self.agent_list):
|
|
if self.in_adjust is False:
|
|
self.filter.run(未进驻=None)
|
|
return False
|
|
|
|
agents = dict(operator_room_select(config.recog.img))
|
|
for i in self.agent_list:
|
|
self.tap(va(agents[i][0], (100, 0)), interval=0)
|
|
# 盲点结束等一下
|
|
self.sleep()
|
|
return False
|
|
|
|
elif len(choosed_agents) == len(self.agent_list):
|
|
for i in self.agent_list:
|
|
if choosed_agents[i][0] != (self.agent_list.index(i)) + 1:
|
|
self.tap_element("choose_agent/clear", interval=0.5)
|
|
self.in_adjust = True
|
|
return False
|
|
return True
|
|
|
|
def check_with_number(self, img, height=60):
|
|
_, im_w, _ = img.shape
|
|
img = cropimg(img, ((0, 0), (im_w, 100)))
|
|
kernel = np.ones((9, 9), np.uint8)
|
|
img = cv2.cvtColor(img, cv2.COLOR_RGB2HSV)
|
|
img = cv2.inRange(img, (0, 0, 200), (225, 15, 255))
|
|
|
|
img = cv2.erode(img, kernel)
|
|
img = cv2.dilate(img, kernel)
|
|
contours, _ = cv2.findContours(img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
|
|
rect = [cv2.boundingRect(c) for c in contours]
|
|
rect.sort(key=lambda c: c[0])
|
|
value = 0
|
|
for x, y, w, h in rect:
|
|
digit = cropimg(img, ((x, y), (x + w, y + h)))
|
|
digit = cv2.copyMakeBorder(
|
|
digit, 10, 10, 10, 10, cv2.BORDER_CONSTANT, None, (0,)
|
|
)
|
|
|
|
if digit.shape[0] < 65 or digit.shape[1] < 40:
|
|
continue
|
|
score = []
|
|
kernel = np.ones((2, 2), np.uint8)
|
|
for i in range(10):
|
|
im = secret_front[i]
|
|
default_height = 25
|
|
if height and height != default_height:
|
|
scale = default_height / height
|
|
digit_1 = cv2.resize(digit, None, None, scale, scale)
|
|
|
|
im = cv2.dilate(im, kernel=kernel)
|
|
result = cv2.matchTemplate(digit_1, im, cv2.TM_SQDIFF_NORMED)
|
|
min_val, _, _, _ = cv2.minMaxLoc(result)
|
|
score.append(min_val)
|
|
value = value * 10 + score.index(min(score))
|
|
return value
|
|
|
|
def get_agent_pos(self, no_number=True):
|
|
res = {}
|
|
img = cv2.cvtColor(config.recog.img, cv2.COLOR_RGB2HSV)
|
|
img = cv2.inRange(img, (90, 200, 120), (200, 255, 255))
|
|
contours, _ = cv2.findContours(img, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
|
|
segments = []
|
|
for contour in contours:
|
|
if cv2.contourArea(contour) < 40000 or cv2.contourArea(contour) > 100000:
|
|
continue
|
|
x, y, w, h = cv2.boundingRect(contour)
|
|
segments.append(((x, y + 100), (x + w, y + h - 200)))
|
|
logger.debug(f"segments:{segments}")
|
|
|
|
opear = match_portrait(config.recog.gray, segment=segments)
|
|
if no_number:
|
|
return list(dict(opear).keys())
|
|
if len(self.agent_list) > 1:
|
|
for i in opear:
|
|
res[i[0]] = [
|
|
self.check_with_number(
|
|
cropimg(config.recog.img, sa([i[1][0], i[1][1]], (0, -100)))
|
|
),
|
|
i[1],
|
|
]
|
|
else:
|
|
for i in opear:
|
|
res[i[0]] = i[1]
|
|
|
|
return res
|
|
|
|
def check_wait_time(self) -> float:
|
|
return max(
|
|
self.wait_time - (datetime.now() - self.start_time).total_seconds(), 0
|
|
)
|
|
|
|
def check_room(self):
|
|
if (
|
|
(scene := self.scene()) == Scene.INFRA_DETAILS
|
|
) and not EnterRoomSolver().detect_room() == self.room:
|
|
EnterRoomSolver().run(self.room)
|
|
elif (
|
|
scene in [Scene.ORDER_LIST, Scene.FACTORY_ROOMS]
|
|
and not self.detect_room_inside() == self.room
|
|
):
|
|
EnterRoomSolver().run(self.room)
|
|
|
|
def transition(self) -> bool:
|
|
if (scene := self.scene()) == Scene.RIIC_OPERATOR_SELECT:
|
|
if self.riic_agent_choose():
|
|
self.sleep(self.check_wait_time())
|
|
self.tap_element("confirm_blue")
|
|
self.success = True
|
|
elif self.find("room_detail"):
|
|
if self.success:
|
|
return True
|
|
else:
|
|
self.tap((1600, 200))
|
|
elif scene in [Scene.ORDER_LIST, Scene.FACTORY_ROOMS]:
|
|
if self.success:
|
|
return True
|
|
else:
|
|
self.tap((500, 970))
|
|
elif scene == Scene.INFRA_ARRANGE_ORDER:
|
|
self.scene_graph_step(Scene.RIIC_OPERATOR_SELECT)
|
|
elif scene == Scene.INFRA_ARRANGE_CONFIRM:
|
|
self.scene_graph_step(Scene.RIIC_OPERATOR_SELECT)
|
|
elif scene in self.waiting_scene:
|
|
self.waiting_solver()
|
|
else:
|
|
EnterRoomSolver().run(self.room)
|