mower-ng/mower/solvers/infra/base_choose.py

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)