185 lines
6.6 KiB
Python
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
|