改写战斗中替换group的逻辑

This commit is contained in:
Elaina 2024-10-13 01:24:58 +08:00
commit 7f89eb0db8
3890 changed files with 82290 additions and 0 deletions

View file

@ -0,0 +1,116 @@
from datetime import datetime
import cv2
from mower.models import riic_base_digits
from mower.solvers.infra.base_mixin import BaseMixin
from mower.solvers.infra.drone import DroneSolver
from mower.solvers.infra.enter_room import EnterRoomSolver
from mower.utils import config
from mower.utils import typealias as tp
from mower.utils.digit_reader import DigitReader
from mower.utils.graph import SceneGraphSolver
from mower.utils.image import cropimg, thres2
from mower.utils.log import logger
from .check_current_product import CheckCurrentProductSolver
from .choose_product import ChooseProductSolver
from .get_remain_time import GetRemainTimeSolver
from .wait_for_product import WaitForProductSolver
production_time = {
"经验": 180 * 60,
"赤金": 72 * 60,
"源石碎片": 60 * 60,
"先锋双芯片": 60 * 60,
"狙击双芯片": 60 * 60,
"医疗双芯片": 60 * 60,
"术师双芯片": 60 * 60,
"近卫双芯片": 60 * 60,
"重装双芯片": 60 * 60,
"辅助双芯片": 60 * 60,
"特种双芯片": 60 * 60,
}
class SwitchProductSolver(SceneGraphSolver, BaseMixin):
def run(self, room, tar_product, only_get_time=False):
logger.info(f"Start:切换产物 房间:{room} 目标产物:{tar_product}")
EnterRoomSolver().run(room, detail=False)
# 检查当前产物
cur_product = CheckCurrentProductSolver().run(room)
logger.info(f"当前产物:{cur_product}")
if cur_product == tar_product:
logger.info("当前产物已为目标产物")
return True
# 读取当前无人机数量避免重复开关
cur_drone_count = DigitReader().get_drone(config.recog.gray)
# 读取生产速度
speed = self.read_speed()
# 获取无人机加速的剩余时间
remain_time = GetRemainTimeSolver().run(room)
if only_get_time:
return remain_time % production_time[cur_product] / speed
# 使用无人机加速
start_time = datetime.now()
drone_count = remain_time % production_time[cur_product] // 180
logger.info(f"应使用无人机数量:{drone_count}")
if not DroneSolver().run(room, drone_count, cur_count=cur_drone_count):
return False
# 等待产物完成
wait_time = max(
remain_time % production_time[cur_product] % 180 / speed
- (datetime.now() - start_time).total_seconds(),
0,
)
logger.info(f"等待时间:{wait_time}")
WaitForProductSolver().run(room, wait_time)
# 选择目标产物
if not ChooseProductSolver().run(room, tar_product):
return False
return True
def number(self, scope: tp.Scope, height: int, thres: int) -> int:
"数字识别"
img = cropimg(config.recog.gray, scope)
default_height = 25
if height != default_height:
scale = 25 / height
img = cv2.resize(img, None, None, scale, scale)
img = thres2(img, thres)
img = cv2.bitwise_not(img)
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 = ""
for x, y, w, h in rect:
if h < 8 and w < 8:
value += "."
continue
elif h < 20 and w < 20:
continue
digit = cropimg(img, ((x, y), (x + w, y + h)))
digit = cv2.copyMakeBorder(
digit, 10, 10, 10, 10, cv2.BORDER_CONSTANT, None, (0,)
)
score = []
for i in range(10):
im = riic_base_digits[i]
result = cv2.matchTemplate(digit, im, cv2.TM_SQDIFF_NORMED)
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
score.append(min_val)
value += str(score.index(min(score)))
return value
def read_speed(self) -> float:
speed1 = self.number(((1185, 955), (1255, 977)), 17, 120)
speed2 = self.number(((1285, 955), (1355, 977)), 17, 150)
return float(speed1) + float(speed2) + 1.0

View file

@ -0,0 +1,49 @@
from datetime import datetime, timedelta
from mower.solvers.infra.base_mixin import BaseMixin
from mower.solvers.infra.enter_room import EnterRoomSolver
from mower.utils import config
from mower.utils.graph import SceneGraphSolver
from mower.utils.recognize import Scene
from .utils import product
class CheckCurrentProductSolver(SceneGraphSolver, BaseMixin):
def run(self, room) -> None:
self.room = room
if (
self.scene() == Scene.FACTORY_ROOMS
and not self.detect_room_inside() == self.room
):
EnterRoomSolver().run(self.room, detail=False)
self.wait_start()
super().run()
return self.res
def timeout(self) -> bool:
return datetime.now() > self.start_time + timedelta(seconds=5)
def wait_start(self):
self.start_time = datetime.now()
def check_product(self) -> str:
for p in product:
if self.find(f"product/{p}"):
return p
def transition(self) -> bool:
if (scene := self.scene()) == Scene.INFRA_DETAILS:
self.wait_start()
self.ctap((200, 1000), 1, config.screenshot_avg / 1000)
elif scene == Scene.FACTORY_ROOMS:
if res := self.check_product():
self.res = res
return True
elif self.timeout():
self.res = None
return True
elif scene in self.waiting_scene:
self.waiting_solver()
else:
EnterRoomSolver().run(self.room, detail=False)

View file

@ -0,0 +1,119 @@
from datetime import datetime, timedelta
import cv2
from mower.models import riic_base_digits
from mower.solvers.infra.enter_room import EnterRoomSolver
from mower.utils import config
from mower.utils import typealias as tp
from mower.utils.email import send_message
from mower.utils.graph import SceneGraphSolver
from mower.utils.image import cmatch, cropimg, loadres, thres2
from mower.utils.log import logger
from mower.utils.recognize import Scene
production_index = {
"经验": [0, 1],
"赤金": [1, 0],
"源石碎片": [3, 0],
"先锋双芯片": [2, 0],
"狙击双芯片": [2, 5],
"医疗双芯片": [2, 6],
"术师双芯片": [2, 2],
"近卫双芯片": [2, 4],
"重装双芯片": [2, 1],
"辅助双芯片": [2, 3],
"特种双芯片": [2, 7],
}
first_pos = [((180, 215 + 140 * i), (190, 225 + 140 * i)) for i in range(4)]
second_pos = [(500 + 742 * j, 200 + 270 * i) for j in range(2) for i in range(4)]
class ChooseProductSolver(SceneGraphSolver):
def run(self, room, tar_product) -> bool:
self.room = room
self.tar_product = tar_product
self.first_pos = first_pos[production_index[self.tar_product][0]]
self.second_pos = second_pos[production_index[self.tar_product][1]]
self.success = False
self.num_flag = False
self.wait_start()
super().run()
return self.success
def be_choosen(self) -> bool:
img = cropimg(config.recog.img, self.first_pos)
res = loadres("product_be_choosen")
return cmatch(img, res, 60)
def timeout(self) -> bool:
return datetime.now() > self.start_time + timedelta(seconds=10)
def wait_start(self):
self.start_time = datetime.now()
def number(self, scope: tp.Scope, height: int, thres: int) -> int:
"数字识别"
img = cropimg(config.recog.gray, scope)
default_height = 25
if height != default_height:
scale = 25 / height
img = cv2.resize(img, None, None, scale, scale)
img = thres2(img, thres)
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,)
)
score = []
for i in range(10):
im = riic_base_digits[i]
result = cv2.matchTemplate(digit, im, cv2.TM_SQDIFF_NORMED)
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
score.append(min_val)
value = value * 10 + score.index(min(score))
return value
def transition(self) -> bool:
if (scene := self.scene()) == Scene.INFRA_DETAILS:
self.ctap((200, 1000), 1, config.screenshot_avg / 1000)
elif scene == Scene.FACTORY_ROOMS:
if self.success:
return True
elif self.find("reload_check"):
if self.num_flag:
self.ctap((1400, 850), 1, config.screenshot_avg / 1000)
elif self.timeout():
logger.warning("切换成功,剩余材料不足1")
send_message(f"切换成功,剩余材料不足1:{self.room}", level="WARNING")
self.num_flag = True
else:
self.tap((1450, 300))
if self.number(((1306, 462), (1391, 521)), 50, 200) != 1:
self.num_flag = True
else:
self.tap((1750, 400))
elif scene == Scene.CHOOSE_PRODUCT:
if self.find("icon_notification_black"):
logger.warning("切换产物材料不足")
send_message(f"切换产物材料不足:{self.room}", level="WARNING")
return True
elif not self.be_choosen():
self.tap(self.get_pos(self.first_pos))
else:
self.tap(self.second_pos)
elif scene == Scene.PRODUCT_SWITCHING_CONFIRM:
self.tap_element("double_confirm/main", x_rate=1)
self.success = True
elif scene in self.waiting_scene:
self.waiting_solver()
else:
EnterRoomSolver().run(self.room, detail=False)

View file

@ -0,0 +1,80 @@
import cv2
from mower.models import riic_base_digits
from mower.solvers.infra.base_mixin import BaseMixin
from mower.solvers.infra.enter_room import EnterRoomSolver
from mower.utils import config
from mower.utils import typealias as tp
from mower.utils.graph import SceneGraphSolver
from mower.utils.image import cropimg, thres2
from mower.utils.recognize import Scene
class GetRemainTimeSolver(SceneGraphSolver, BaseMixin):
"""
返回剩余时间,换算为秒
"""
def run(
self,
room: str,
):
self.room = room
if (
self.scene() == Scene.FACTORY_ROOMS
and not self.detect_room_inside() == self.room
):
EnterRoomSolver().run(self.room, detail=False)
super().run()
return self.res
def number(self, scope: tp.Scope, height: int, thres: int) -> str:
"数字识别"
img = cropimg(config.recog.gray, scope)
default_height = 25
if height != default_height:
scale = 25 / height
img = cv2.resize(img, None, None, scale, scale)
img = thres2(img, thres)
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 = ""
for x, y, w, h in rect:
if h < 7 and w < 7:
value += ":"
continue
digit = cropimg(img, ((x, y), (x + w, y + h)))
digit = cv2.copyMakeBorder(
digit, 10, 10, 10, 10, cv2.BORDER_CONSTANT, None, (0,)
)
score = []
for i in range(10):
im = riic_base_digits[i]
result = cv2.matchTemplate(digit, im, cv2.TM_SQDIFF_NORMED)
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
score.append(min_val)
value += str(score.index(min(score)))
return value
def read_remain_time(self) -> int:
h, m, s = self.number(((758, 670), (960, 705)), 30, 100).split("::")
return int(h) * 3600 + int(m) * 60 + int(s)
def transition(self) -> bool:
if (scene := self.scene()) == Scene.INFRA_DETAILS:
self.ctap((200, 1000), 1, config.screenshot_avg / 1000)
elif scene == Scene.FACTORY_ROOMS:
if pos := self.find("factory_accelerate"):
self.tap(pos)
elif scene == Scene.DRONE_ACCELERATE:
if res := self.read_remain_time():
self.res = res
return True
elif scene in self.waiting_scene:
self.waiting_solver()
else:
EnterRoomSolver().run(self.room, detail=False)

View file

@ -0,0 +1,13 @@
product = [
"经验",
"赤金",
"源石碎片",
"先锋双芯片",
"狙击双芯片",
"医疗双芯片",
"术师双芯片",
"近卫双芯片",
"重装双芯片",
"辅助双芯片",
"特种双芯片",
]

View file

@ -0,0 +1,36 @@
from datetime import datetime, timedelta
from mower.solvers.infra.base_mixin import BaseMixin
from mower.solvers.infra.enter_room import EnterRoomSolver
from mower.utils import config
from mower.utils.graph import SceneGraphSolver
from mower.utils.recognize import Scene
class WaitForProductSolver(SceneGraphSolver, BaseMixin):
def run(self, room, wait_time) -> None:
self.room = room
self.wait_start()
self.sleep(wait_time)
super().run()
def timeout(self) -> bool:
return datetime.now() > self.start_time + timedelta(seconds=180)
def wait_start(self):
self.start_time = datetime.now()
def transition(self) -> bool:
if (scene := self.scene()) == Scene.INFRA_DETAILS:
self.ctap((200, 1000), 1, config.screenshot_avg / 1000)
elif scene == Scene.FACTORY_ROOMS:
if self.detect_product_complete():
return True
elif self.timeout():
return True
else:
self.tap((1750, 950))
elif scene in self.waiting_scene:
self.waiting_solver()
else:
EnterRoomSolver().run(self.room, detail=False)