mower-ng/mower/solvers/mini_base.py
zhbaor 402ec94b0e
Some checks failed
ci/woodpecker/push/check_format Pipeline failed
mini_base移除无用的EnterRoomSolver.run()
2024-12-09 10:38:42 +08:00

185 lines
6.6 KiB
Python

import math
from datetime import datetime, timedelta
from pydantic import BaseModel
from mower.data import base_room_list
from mower.solvers.infra.drone import DroneSolver
from mower.solvers.infra.enter_room import EnterRoomSolver
from mower.solvers.infra.get_agent_from_room import GetAgentFromRoomSolver
from mower.solvers.infra.get_order_remaining_time import GetOrderRemainingTimeSolver
from mower.solvers.infra.reload import ReloadSolver
from mower.solvers.infra.run_order import RunOrderSolver
from mower.solvers.infra.run_order.read_original_order_remaining_time import (
ReadOriginalOrderRemainTimeSolver,
)
from mower.solvers.infra.todo_list import TodoListSolver
from mower.utils import config
from mower.utils.config.plan import Facility
from mower.utils.digit_reader import get_drone
from mower.utils.log import logger
from mower.utils.scheduler import scheduler
class RunOrderRoomInfo(BaseModel):
time: datetime | None = None
"订单生成时间"
room: str
"房间名"
plan: list[str]
"但书/龙舌兰/佩佩的位置"
dynamic: list[str] = []
"跑单时的干员安排"
class RunOrderInfo:
def __init__(self):
"""根据排班表获取跑单信息"""
self.data: list[RunOrderRoomInfo] = []
# 读排班表,找到替换组包含跑单干员的房间,生成跑单计划
run_order_op = ["但书", "龙舌兰", "佩佩"]
for room in base_room_list:
if not room.startswith("room_"):
continue
facility: Facility = getattr(config.plan.plan1, room)
run_order_room = False
run_order_plan = []
for plan in facility.plans: # 站内位置
op = ""
for rep in plan.replacement: # 一个位置的替换
if rep in run_order_op:
run_order_room = True
op = rep
break
run_order_plan.append(op)
if run_order_room:
self.data.append(RunOrderRoomInfo(room=room, plan=run_order_plan))
logger.info(f"跑单房间:{[i.room for i in self.data]}")
def update(self):
"""读订单剩余时间和房间内的干员"""
for i, info in enumerate(self.data):
if info.time is not None:
continue
logger.info(f"读取房间{info.room}的信息")
info.time = (
timedelta(seconds=GetOrderRemainingTimeSolver().run(info.room))
+ datetime.now()
)
info.dynamic = info.plan.copy()
if "" in info.plan:
current = GetAgentFromRoomSolver().run(info.room)
for i, op in enumerate(current):
if info.plan[i] == "":
info.dynamic[i] = op["agent"]
self.data.sort(key=lambda x: x.time)
for r in self.data:
logger.info(f"房间{r.room}的跑单时间为{r.time},干员安排{r.dynamic}")
class MiniBase:
"""
只保存干员心情数据,根据历史与当前心情数据无状态地生成任务
1. 收产物
2. 跑单
- 没有订单就继续
- 有一笔订单在前置时间以内就跑这一单
- 有多笔订单在前置时间以内,按时间用无人机跑前面几单
3. 读取干员信息
4. 换班
- 修正与排班表不一致的地方
- 休息好的干员换上来
- 心情低的干员安排休息
- 肥鸭充能
5. 无人机加速、搓玉补货
6. 生成任务
- 跑单
- 肥鸭充能
- 心情恢复结束
- 暖机干员下班
"""
solver_name = "基建·青春版"
def run(self):
self.run_order = RunOrderInfo()
pre_delay = timedelta(minutes=config.conf.run_order_delay)
# 1. 收产物
TodoListSolver().run()
# 2. 跑单
self.run_order.update()
# 立即跑单
for info in self.run_order.data:
threshold = datetime.now() + pre_delay
if info.time < threshold:
RunOrderSolver().run(room=info.room, agent_list=info.dynamic)
info.time = None
else:
break
# 3. 读取干员信息,先不管以前的数据
# op_data = {}
# for room in base_room_list:
# op_data[room] = GetAgentFromRoomSolver().run(room)
# 4. 换班
# 5. 无人机加速(仅支持制造站)
DroneSolver().run(config.conf.drone_room)
# 搓玉补货
if config.conf.reload_room != "":
for room in config.conf.reload_room.split(","):
ReloadSolver().run(room)
# 6. 生成任务
# 重新读订单时间
self.run_order.update()
# 拉开时间接近的订单
# 倒序遍历,依次加速较早的订单
rev_iter = reversed(self.run_order.data)
task_b = next(rev_iter)
for task_a in rev_iter:
# delta为至少需要加速的时间
delta = task_a.time + pre_delay - task_b.time
if delta <= timedelta():
continue
# 如果现在距加速之后不足跑单前置时间,所有更早的站无人机跑单
if task_b.time - pre_delay < datetime.now():
for info in self.run_order.data:
if info == task_b:
break
RunOrderSolver().run(
room=info.room, agent_list=info.dynamic, drone=True
)
info.time = None
self.run_order.update()
break
# 无人机拉开间隔
EnterRoomSolver().run(task_a.room, detail=False)
total = get_drone(config.recog.gray)
time_no_efficiency = timedelta(
seconds=ReadOriginalOrderRemainTimeSolver().run(task_a.room)
)
time_with_efficiency = task_a.time - datetime.now()
efficiency = round(time_no_efficiency / time_with_efficiency, 2)
time_per_drone = timedelta(minutes=3) / efficiency
drone = math.ceil(delta / time_per_drone)
DroneSolver().run(task_a.room, drone, cur_count=total)
task_a.time = (
timedelta(seconds=GetOrderRemainingTimeSolver().run(task_a.room))
+ datetime.now()
)
task_b = task_a
scheduler.register_one_time(
solver="mower.solvers.mini_base.MiniBase",
time=self.run_order.data[0].time - pre_delay,
)
return True