615 lines
23 KiB
Java
615 lines
23 KiB
Java
package com.hivekion.room.bean;
|
|
|
|
import cn.hutool.extra.spring.SpringUtil;
|
|
import com.alibaba.fastjson2.JSON;
|
|
import com.alibaba.fastjson2.JSONArray;
|
|
import com.alibaba.fastjson2.JSONObject;
|
|
import com.hivekion.Global;
|
|
import com.hivekion.baseData.entity.Scenario;
|
|
import com.hivekion.baseData.service.ScenarioService;
|
|
import com.hivekion.common.MultiPointGeoPosition;
|
|
import com.hivekion.common.entity.ResponseCmdInfo;
|
|
import com.hivekion.common.redis.RedisUtil;
|
|
import com.hivekion.common.uuid.IdUtils;
|
|
import com.hivekion.enums.WsCmdTypeEnum;
|
|
import com.hivekion.room.RoomManager;
|
|
import com.hivekion.room.func.TaskAction;
|
|
import com.hivekion.scenario.entity.ScenarioResource;
|
|
import com.hivekion.scenario.entity.ScenarioTask;
|
|
import com.hivekion.scenario.service.impl.BattleSupplierServiceImpl;
|
|
import com.hivekion.scenario.service.impl.ScenarioResourceServiceImpl;
|
|
import com.hivekion.scenario.service.impl.ScenarioTaskServiceImpl;
|
|
import com.hivekion.statistic.bean.EditScenarioInfo;
|
|
import com.hivekion.statistic.bean.ScenarioInfo;
|
|
import com.hivekion.statistic.bean.StatisticBean;
|
|
import com.hivekion.statistic.service.impl.StatisticServiceImpl;
|
|
import com.hivekion.supplier.entity.SupplierRequest;
|
|
import com.hivekion.supplier.service.impl.SupplierRequestServiceImpl;
|
|
import com.hivekion.team.entity.Teaminfo;
|
|
import com.hivekion.team.service.impl.TeaminfoServiceImpl;
|
|
import java.math.BigDecimal;
|
|
import java.math.RoundingMode;
|
|
import java.time.LocalDateTime;
|
|
import java.util.ArrayList;
|
|
import java.util.HashMap;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.Map.Entry;
|
|
import java.util.NavigableMap;
|
|
import java.util.TreeMap;
|
|
import java.util.concurrent.Executors;
|
|
import java.util.concurrent.ScheduledExecutorService;
|
|
import java.util.concurrent.ThreadFactory;
|
|
import java.util.concurrent.TimeUnit;
|
|
import java.util.concurrent.atomic.AtomicBoolean;
|
|
import java.util.concurrent.atomic.AtomicInteger;
|
|
import java.util.concurrent.atomic.AtomicLong;
|
|
import java.util.concurrent.atomic.AtomicReference;
|
|
import lombok.extern.slf4j.Slf4j;
|
|
import org.apache.commons.lang3.StringUtils;
|
|
import org.springframework.core.env.Environment;
|
|
import org.springframework.web.reactive.function.client.WebClient;
|
|
|
|
/**
|
|
* [类的简要说明]
|
|
* <p>
|
|
* [详细描述,可选]
|
|
* <p>
|
|
*
|
|
* @author LiDongYU
|
|
* @since 2025/7/22
|
|
*/
|
|
@Slf4j
|
|
public abstract class AbtParentTask implements TaskAction {
|
|
|
|
|
|
protected final AtomicBoolean taskFinishedStatus = new AtomicBoolean(false);
|
|
/**
|
|
* 油料消耗速率
|
|
*/
|
|
protected double fuelConsumption = 0;
|
|
protected double fuelThreshold = 0;
|
|
/**
|
|
* 开始点坐标
|
|
*/
|
|
private final AtomicReference<Double> startPoint = new AtomicReference<>();
|
|
/**
|
|
* 距离和坐标的对应关系
|
|
*/
|
|
protected final TreeMap<Double, Coordinate> distanceInfoMap = new TreeMap<>();
|
|
//任务数据
|
|
protected final ScenarioTask scenarioTask;
|
|
//房间ID
|
|
protected final String roomId;
|
|
//http请求
|
|
protected WebClient webClient = WebClient.create();
|
|
|
|
protected final AtomicReference<Coordinate> coordinateReference = new AtomicReference<>();
|
|
/**
|
|
* 需求产生标志
|
|
*/
|
|
private final AtomicBoolean requestFlag = new AtomicBoolean(false);
|
|
private StatisticBean statisticBean;
|
|
|
|
|
|
public AbtParentTask(ScenarioTask scenarioTask, String roomId) {
|
|
this.scenarioTask = scenarioTask;
|
|
this.roomId = roomId;
|
|
Scenario scenario = SpringUtil.getBean(ScenarioService.class)
|
|
.getScenarioById(scenarioTask.getScenarioId());
|
|
statisticBean = SpringUtil.getBean(StatisticServiceImpl.class)
|
|
.statistic(scenarioTask.getResourceId());
|
|
initEnv();
|
|
}
|
|
|
|
public void addScheduledExecutorServiceRefenceToRoom(
|
|
ScheduledExecutorService scheduledExecutorService) {
|
|
RoomManager.addFuture(scheduledExecutorService, this.roomId);
|
|
}
|
|
|
|
@Override
|
|
public void doSomeThing() {
|
|
|
|
}
|
|
|
|
@Override
|
|
public String getId() {
|
|
return scenarioTask.getId();
|
|
}
|
|
|
|
@Override
|
|
public String getType() {
|
|
return scenarioTask.getTaskType();
|
|
}
|
|
|
|
//获取房间的持续时间
|
|
public long getDuringTime() {
|
|
return RoomManager.getRoomDuringTime(this.roomId);
|
|
}
|
|
|
|
//获取房间状态
|
|
public boolean getRoomStatus() {
|
|
return RoomManager.isRunning(roomId);
|
|
}
|
|
|
|
public void createBattleTaskOnTimingHandle(BizTaskOnTiming bizTaskOnTiming) {
|
|
ScheduledExecutorService schedule = Executors.newScheduledThreadPool(
|
|
1);
|
|
schedule.scheduleWithFixedDelay(() -> {
|
|
bizTaskOnTiming.execTask();
|
|
}, 0, 1, TimeUnit.SECONDS);
|
|
//房间统一管理定时器;房间关闭后,定时器销毁
|
|
addScheduledExecutorServiceRefenceToRoom(schedule);
|
|
}
|
|
|
|
/**
|
|
* 初始化环境
|
|
*/
|
|
private void initEnv() {
|
|
try {
|
|
//获取油品消耗规则
|
|
String fuelConsumptionStr = SpringUtil.getBean(Environment.class)
|
|
.getProperty("fuel.spreed");
|
|
|
|
fuelConsumption = Double.parseDouble(fuelConsumptionStr == null ? "0" : fuelConsumptionStr);
|
|
fuelThreshold = Double.parseDouble(SpringUtil.getBean(Environment.class)
|
|
.getProperty("fuel.warn", "0"));
|
|
|
|
log.info("初始化::{}-油料消耗速度::{},油料最低阈值::{},当前油料::{}",
|
|
this.scenarioTask.getResourceId(),
|
|
fuelConsumptionStr, fuelThreshold, getCurrentFuel());
|
|
|
|
} catch (Exception e) {
|
|
log.error("init env exception", e);
|
|
}
|
|
|
|
}
|
|
|
|
protected void initPath() {
|
|
try {
|
|
log.info("init path");
|
|
String url = SpringUtil.getBean(Environment.class).getProperty("path.planning.url");
|
|
String params = url + "?"
|
|
+ "profile=car"
|
|
+ "&point=" + scenarioTask.getFromLat() + ","
|
|
+ scenarioTask.getFromLng()
|
|
+ "&point=" + scenarioTask.getToLat() + ","
|
|
+ scenarioTask.getToLng()
|
|
+ "&points_encoded=false"
|
|
+ "&algorithm=alternative_route&alternative_route.max_paths=3";
|
|
log.info("params:;{}", params);
|
|
Room room = RoomManager.getRoom(this.roomId);
|
|
Map<String, ScenarioResource> resourceMap = room.getScenarioResourceMap();
|
|
//获取路线信息
|
|
String result = webClient.get().uri(params)
|
|
.retrieve()
|
|
.bodyToMono(String.class)
|
|
.block();
|
|
log.info("init path finished ::{}", result);
|
|
JSONObject pointJson = JSON.parseObject(result);
|
|
//获取路径点
|
|
if (pointJson != null) {
|
|
JSONObject pointsObj = pointJson.getJSONArray("paths").getJSONObject(0)
|
|
.getJSONObject("points");
|
|
JSONArray coordinates = pointsObj.getJSONArray("coordinates");
|
|
//组装信息
|
|
Map<String, Object> dataMap = new HashMap<>();
|
|
dataMap.put("resourceId", scenarioTask.getResourceId());
|
|
dataMap.put("points", coordinates);
|
|
dataMap.put("teamType", resourceMap.get(this.scenarioTask.getResourceId()).getType());
|
|
if (RoomManager.getRoom(roomId) != null) {
|
|
RoomManager.getRoom(roomId)
|
|
.addResourcePath(this.scenarioTask.getResourceId(), coordinates);
|
|
}
|
|
//推送路径任务
|
|
Global.sendCmdInfoQueue.add(
|
|
ResponseCmdInfo.create(WsCmdTypeEnum.PATH_INIT.getCode(), roomId,
|
|
scenarioTask.getScenarioId(), dataMap));
|
|
|
|
SpringUtil.getBean(RedisUtil.class).hset(
|
|
scenarioTask.getScenarioId() + "-" + roomId + "-" + scenarioTask.getResourceId(),
|
|
"init_path", JSON.toJSONString(coordinates));
|
|
|
|
//计算各个点的累计距离和坐标的对应关系
|
|
double beforeLng = Double.parseDouble(scenarioTask.getFromLng());
|
|
double beforeLat = Double.parseDouble(scenarioTask.getFromLat());
|
|
double total = 0;
|
|
for (int i = 0; i < coordinates.size(); i++) {
|
|
JSONArray coordinate = coordinates.getJSONArray(i);
|
|
Double lng = coordinate.getDouble(0);
|
|
|
|
Double lat = coordinate.getDouble(1);
|
|
|
|
double distance = MultiPointGeoPosition.haversine(beforeLat, beforeLng, lat, lng);
|
|
//当前总距离
|
|
total = total + distance;
|
|
//定义坐标对象
|
|
Coordinate coordinateInfo = new Coordinate();
|
|
coordinateInfo.setLat(lat);
|
|
coordinateInfo.setLng(lng);
|
|
|
|
//记录距离和数组列表直接的索引关系
|
|
distanceInfoMap.put(total, coordinateInfo);
|
|
|
|
beforeLng = lng;
|
|
beforeLat = lat;
|
|
|
|
}
|
|
log.info("路线节点个数::{},总距离::{}",distanceInfoMap.size(),distanceInfoMap.lastKey());
|
|
//设置第一个开始位置
|
|
startPoint.set(distanceInfoMap.firstKey());
|
|
}
|
|
|
|
} catch (Exception e) {
|
|
log.error("error::", e);
|
|
}
|
|
}
|
|
|
|
protected void updatePath(double speed, TaskAction duringAction, TaskAction finishedAction) {
|
|
AtomicLong duringTime = new AtomicLong(0);
|
|
ScheduledExecutorService schedule = Executors.newScheduledThreadPool(
|
|
1);
|
|
schedule.scheduleWithFixedDelay(() -> {
|
|
|
|
try {
|
|
Room room = RoomManager.getRoom(this.roomId);
|
|
if (room == null || room.isTimeExpired()) {
|
|
log.error("房间不存在或者已经到达想定结束时间");
|
|
return;
|
|
}
|
|
|
|
if (this.getRoomStatus()) {
|
|
//自动生成的任务不需要判断油量;不要在生成新的任务
|
|
|
|
if (!"general".equals(scenarioTask.getFromSource())) {
|
|
double currentFuel = getCurrentFuel();
|
|
double totalFuel = statisticBean.getFuel().getTotal();
|
|
|
|
if (currentFuel <= 0 || totalFuel <= 0) {
|
|
log.error("{}:油量为零停止移动", this.scenarioTask.getResourceId());
|
|
return;
|
|
}
|
|
|
|
|
|
if (currentFuel * 100 / totalFuel < fuelThreshold && !requestFlag.get()) {
|
|
log.error("{}-油料不足,需要补充,新建需求和任务", scenarioTask.getResourceId());
|
|
|
|
requestFlag.set(true);
|
|
//需要产生需求
|
|
produceFuelRequest();
|
|
//产生任务
|
|
produceTask(currentFuel);
|
|
return;
|
|
}
|
|
if (currentFuel * 100 / totalFuel < fuelThreshold) {
|
|
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (distanceInfoMap.isEmpty()) {
|
|
return;
|
|
}
|
|
|
|
if (duringAction != null) {
|
|
duringAction.doSomeThing();
|
|
}
|
|
|
|
//跑动距离
|
|
double distance = duringTime.getAndAdd(RoomManager.getMag(roomId)) * speed;
|
|
|
|
//获取大与此距离的第一个路线点key
|
|
Entry<Double, Coordinate> endPoint = distanceInfoMap.ceilingEntry(distance);
|
|
if (endPoint == null) {
|
|
endPoint = distanceInfoMap.lastEntry();
|
|
}
|
|
log.info("当前距离{}",distance);
|
|
//ws数据
|
|
List<double[]> dataList = new ArrayList<>();
|
|
HashMap<Object, Object> dataMap = new HashMap<>();
|
|
dataMap.put("resourceId", scenarioTask.getResourceId());
|
|
dataMap.put("points", dataList);
|
|
|
|
if (Double.compare(distance, endPoint.getKey()) < 0) {
|
|
//获取小于最大值的第一个key
|
|
Double lowerKey = distanceInfoMap.lowerKey(endPoint.getKey());
|
|
if (lowerKey == null) {
|
|
lowerKey = endPoint.getKey();
|
|
}
|
|
|
|
NavigableMap<Double, Coordinate> subPathMap = distanceInfoMap.subMap(startPoint.get(),
|
|
true, lowerKey, true);
|
|
for (Double key : subPathMap.keySet()) {
|
|
Coordinate coordinate = subPathMap.get(key);
|
|
dataList.add(new double[]{coordinate.getLng(), coordinate.getLat()});
|
|
}
|
|
double diff = distance - lowerKey;
|
|
|
|
//插入值
|
|
double[] insertPoints = MultiPointGeoPosition.pointAlong(
|
|
distanceInfoMap.get(lowerKey).getLat(), distanceInfoMap.get(lowerKey).getLng(),
|
|
endPoint.getValue().getLat(), endPoint.getValue().getLng(), diff);
|
|
|
|
dataList.add(new double[]{insertPoints[1], insertPoints[0]});
|
|
|
|
Coordinate coordinate = new Coordinate();
|
|
coordinate.setLat(insertPoints[0]);
|
|
coordinate.setLng(insertPoints[1]);
|
|
distanceInfoMap.put(distance, coordinate);
|
|
startPoint.set(distance);
|
|
coordinateReference.set(coordinate);
|
|
SpringUtil.getBean(RedisUtil.class).hset(
|
|
scenarioTask.getScenarioId() + "-" + roomId + "-" + scenarioTask.getResourceId(),
|
|
"position", JSON.toJSONString(coordinate));
|
|
|
|
Global.sendCmdInfoQueue.add(
|
|
ResponseCmdInfo.create(WsCmdTypeEnum.PATH_UPDATE.getCode(), roomId,
|
|
scenarioTask.getScenarioId(), dataMap));
|
|
|
|
//修改位置信息
|
|
|
|
EditScenarioInfo editScenarioInfo = getEditScenarioInfo(
|
|
this.scenarioTask.getResourceId());
|
|
editScenarioInfo.getJbxx().getTeam().setLat(coordinate.getLat() + "");
|
|
editScenarioInfo.getJbxx().getTeam().setLng(coordinate.getLng() + "");
|
|
setEditScenarioInfo(editScenarioInfo, scenarioTask.getResourceId());
|
|
pushStatus(scenarioTask.getResourceId());
|
|
|
|
} else if (Double.compare(distance, endPoint.getKey()) == 0) {
|
|
NavigableMap<Double, Coordinate> subPathMap = distanceInfoMap.subMap(startPoint.get(),
|
|
true, endPoint.getKey(), true);
|
|
for (Double key : subPathMap.keySet()) {
|
|
Coordinate coordinate = subPathMap.get(key);
|
|
dataList.add(new double[]{coordinate.getLng(), coordinate.getLat()});
|
|
}
|
|
coordinateReference.set(endPoint.getValue());
|
|
startPoint.set(endPoint.getKey());
|
|
Global.sendCmdInfoQueue.add(
|
|
ResponseCmdInfo.create(WsCmdTypeEnum.PATH_UPDATE.getCode(), roomId,
|
|
scenarioTask.getScenarioId(), dataMap));
|
|
|
|
} else {
|
|
if (finishedAction != null) {
|
|
finishedAction.doSomeThing();
|
|
}
|
|
taskFinishedStatus.set(true);
|
|
//完成路径
|
|
Global.sendCmdInfoQueue.add(
|
|
ResponseCmdInfo.create(WsCmdTypeEnum.PATH_FINISHED.getCode(), roomId,
|
|
scenarioTask.getScenarioId(), dataMap));
|
|
//任务终止
|
|
schedule.shutdown();
|
|
}
|
|
|
|
|
|
}
|
|
} catch (Exception e) {
|
|
log.error("error::", e);
|
|
}
|
|
|
|
|
|
}, 0, 1, TimeUnit.SECONDS);
|
|
|
|
//房间统一管理定时器;房间关闭后,定时器销毁
|
|
addScheduledExecutorServiceRefenceToRoom(schedule);
|
|
}
|
|
|
|
private RedisUtil redisUtil;
|
|
|
|
protected EditScenarioInfo getEditScenarioInfo(String resourceId) {
|
|
String updJsonStr = (String) SpringUtil.getBean(RedisUtil.class).hget(
|
|
this.scenarioTask.getScenarioId() + "-" + roomId + "-" + resourceId,
|
|
"updScenarioInfo");
|
|
return JSON.parseObject(updJsonStr, EditScenarioInfo.class);
|
|
}
|
|
|
|
protected void setEditScenarioInfo(EditScenarioInfo editScenarioInfo, String resourceId) {
|
|
SpringUtil.getBean(RedisUtil.class).hset(
|
|
this.scenarioTask.getScenarioId() + "-" + roomId + "-" + resourceId,
|
|
"updScenarioInfo", JSON.toJSONString(editScenarioInfo));
|
|
}
|
|
|
|
//统一推送方法
|
|
protected void pushStatus(String resourceId) {
|
|
if (StringUtils.isBlank(resourceId)) {
|
|
return;
|
|
}
|
|
if (redisUtil == null) {
|
|
redisUtil = SpringUtil.getBean(RedisUtil.class);
|
|
}
|
|
String jsonStr = (String) redisUtil.hget(
|
|
this.scenarioTask.getScenarioId() + "-" + roomId + "-" + scenarioTask.getResourceId(),
|
|
"scenarioInfo");
|
|
ResponseCmdInfo<String> respObj = new ResponseCmdInfo<>();
|
|
respObj.setData(jsonStr);
|
|
respObj.setRoom(roomId);
|
|
respObj.setScenarioId(scenarioTask.getScenarioId());
|
|
respObj.setCmdType("scenarioInfo");
|
|
Global.sendCmdInfoQueue.add(respObj);
|
|
String updJsonStr = (String) redisUtil.hget(
|
|
this.scenarioTask.getScenarioId() + "-" + roomId + "-" + scenarioTask.getResourceId(),
|
|
"updScenarioInfo");
|
|
EditScenarioInfo editScenarioInfo = JSON.parseObject(updJsonStr, EditScenarioInfo.class);
|
|
//设置食品
|
|
editScenarioInfo.getJbxx().getFood().setCurrent(new BigDecimal( editScenarioInfo.getJbxx().getFood().getCurrent()).setScale(3,
|
|
RoundingMode.HALF_UP).doubleValue());
|
|
//设置油
|
|
editScenarioInfo.getJbxx().getFuel().setCurrent(new BigDecimal( editScenarioInfo.getJbxx().getFuel().getCurrent()).setScale(3,
|
|
RoundingMode.HALF_UP).doubleValue());
|
|
//设置弹药
|
|
editScenarioInfo.getJbxx().getAmmunition().setCurrent(new BigDecimal( editScenarioInfo.getJbxx().getAmmunition().getCurrent()).setScale(3,
|
|
RoundingMode.HALF_UP).doubleValue());
|
|
//设置药材
|
|
editScenarioInfo.getJbxx().getMedical().setCurrent(new BigDecimal( editScenarioInfo.getJbxx().getMedical().getCurrent()).setScale(3,
|
|
RoundingMode.HALF_UP).doubleValue());
|
|
//设置水
|
|
editScenarioInfo.getJbxx().getWater().setCurrent(new BigDecimal( editScenarioInfo.getJbxx().getWater().getCurrent()).setScale(3,
|
|
RoundingMode.HALF_UP).doubleValue());
|
|
|
|
|
|
ResponseCmdInfo<String> respUpdObj = new ResponseCmdInfo<>();
|
|
respUpdObj.setData(JSON.toJSONString(editScenarioInfo));
|
|
respUpdObj.setRoom(roomId);
|
|
respUpdObj.setScenarioId(scenarioTask.getScenarioId());
|
|
respUpdObj.setCmdType("updScenarioInfo");
|
|
Global.sendCmdInfoQueue.add(respUpdObj);
|
|
}
|
|
|
|
protected double getCurrentFuel() {
|
|
Object statisticObj = SpringUtil.getBean(RedisUtil.class).hget(
|
|
scenarioTask.getScenarioId() + "-" + roomId + "-" + scenarioTask.getResourceId(),
|
|
"scenarioInfo");
|
|
|
|
if (statisticObj != null) {
|
|
ScenarioInfo scenarioInfo = JSON.parseObject(statisticObj.toString(), ScenarioInfo.class);
|
|
return scenarioInfo.getFuel().getCurrent();
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
private void produceFuelRequest() {
|
|
log.info("{}-产生油料保障需求", this.scenarioTask.getResourceId());
|
|
SupplierRequest supplierRequest = new SupplierRequest();
|
|
supplierRequest.setId(IdUtils.simpleUUID());
|
|
supplierRequest.setFromResourceId(scenarioTask.getResourceId());
|
|
supplierRequest.setSupplierNum(String.valueOf(statisticBean.getFuel().getTotal()));
|
|
supplierRequest.setSupplierType("fuel");
|
|
supplierRequest.setGeneralTime(LocalDateTime.now());
|
|
supplierRequest.setLat(scenarioTask.getToLat());
|
|
supplierRequest.setLng(scenarioTask.getToLng());
|
|
supplierRequest.setHandleFlag(1);
|
|
SpringUtil.getBean(SupplierRequestServiceImpl.class).save(supplierRequest);
|
|
}
|
|
|
|
private void produceTask(double fuel) {
|
|
try {
|
|
Map<Integer, Teaminfo> teamInfoMap = SpringUtil.getBean(TeaminfoServiceImpl.class)
|
|
.teamInfoMap();
|
|
|
|
log.info("{}-产生自动保障任务", this.scenarioTask.getResourceId());
|
|
List<ScenarioResource> resourceList = SpringUtil.getBean(BattleSupplierServiceImpl.class)
|
|
.selectSupplierResource(scenarioTask.getResourceId());
|
|
log.info("{}-可选保障分队长度{}", scenarioTask.getResourceId(), resourceList.size());
|
|
if (!resourceList.isEmpty()) {
|
|
ScenarioResource supplierResource = null;
|
|
// 找出油料保障分队
|
|
for (ScenarioResource resource : resourceList) {
|
|
|
|
Teaminfo teaminfo = teamInfoMap.get(resource.getResourceId());
|
|
|
|
if ("SUPPLIER_FUEL".equals(teaminfo.getRoleCode())) {
|
|
supplierResource = resource;
|
|
|
|
break;
|
|
}
|
|
}
|
|
if (supplierResource == null) {
|
|
log.error("找不到对应的油料保障分队");
|
|
return;
|
|
}
|
|
//找出油料仓库
|
|
List<ScenarioResource> resources = SpringUtil.getBean(ScenarioResourceServiceImpl.class)
|
|
.selectResourceByRoleCode(scenarioTask.getScenarioId(), "WARE_FUEL_HOUSE");
|
|
if (resources.isEmpty()) {
|
|
log.error("找不到油料仓库");
|
|
return;
|
|
}
|
|
|
|
produceMoveTask(supplierResource, resources.get(0), this.coordinateReference.get(), fuel);
|
|
|
|
|
|
} else {
|
|
log.error("{}-没有保障分队可以选择", scenarioTask.getResourceId());
|
|
}
|
|
} catch (Exception e) {
|
|
log.error("produceTask exception", e);
|
|
}
|
|
|
|
}
|
|
|
|
private void produceMoveTask(ScenarioResource supplierResource, ScenarioResource fuelResource,
|
|
Coordinate coordinate, double minusFuel) {
|
|
ScenarioTask task = new ScenarioTask();
|
|
task.setId(IdUtils.simpleUUID());
|
|
task.setScenarioId(scenarioTask.getScenarioId());
|
|
task.setResourceId(supplierResource.getId());
|
|
task.setTaskType("1");
|
|
task.setName("油料保障任务-移动第一节点(自动)");
|
|
task.setFromLat(supplierResource.getLat());
|
|
task.setFromLng(supplierResource.getLng());
|
|
task.setToLat(fuelResource.getLat());
|
|
task.setToLng(fuelResource.getLng());
|
|
task.setStartTime(LocalDateTime.now());
|
|
task.setFromSource("general");
|
|
log.info("油料保障任务-移动resourceId::{}", supplierResource.getId());
|
|
SpringUtil.getBean(ScenarioTaskServiceImpl.class).save(task);
|
|
MoveTask moveTask = new MoveTask(task, this.roomId, new TaskAction() {
|
|
@Override
|
|
public void doSomeThing() {
|
|
if(coordinate!=null){
|
|
//创建一个送达任务
|
|
log.info("目标地址::{},{}",coordinate.getLat(),coordinate.getLng());
|
|
|
|
ScenarioTask task = new ScenarioTask();
|
|
task.setId(IdUtils.simpleUUID());
|
|
task.setScenarioId(scenarioTask.getScenarioId());
|
|
task.setResourceId(supplierResource.getId());
|
|
task.setTaskType("6");
|
|
task.setName("油料保障任务-移动第二节点(自动)");
|
|
task.setInsureResourceId(scenarioTask.getResourceId());
|
|
task.setSupplierNum(statisticBean.getFuel().getTotal() - minusFuel);
|
|
task.setToLat(coordinate.getLat() + "");
|
|
task.setToLng(coordinate.getLng() + "");
|
|
task.setStartTime(LocalDateTime.now());
|
|
task.setFromLat(fuelResource.getLat());
|
|
task.setFromLng(fuelResource.getLng());
|
|
task.setFromSource("general");
|
|
SpringUtil.getBean(ScenarioTaskServiceImpl.class).save(task);
|
|
SupplierTask supplierTask = new SupplierTask(task, roomId);
|
|
RoomManager.addAction(roomId, 0, supplierTask);
|
|
}else{
|
|
log.error("没有目标地址");
|
|
}
|
|
|
|
}
|
|
|
|
@Override
|
|
public String getId() {
|
|
return "";
|
|
}
|
|
|
|
@Override
|
|
public String getType() {
|
|
return "";
|
|
}
|
|
});
|
|
//立即执行
|
|
RoomManager.addAction(roomId, 0, moveTask);
|
|
}
|
|
|
|
}
|
|
|
|
interface BizTaskOnTiming {
|
|
|
|
public void execTask();
|
|
}
|
|
|
|
// 自定义线程工厂
|
|
class CustomThreadFactory implements ThreadFactory {
|
|
|
|
private final AtomicInteger threadNumber = new AtomicInteger(1);
|
|
private final String namePrefix;
|
|
|
|
public CustomThreadFactory(String namePrefix) {
|
|
this.namePrefix = namePrefix + "-thread-";
|
|
}
|
|
|
|
@Override
|
|
public Thread newThread(Runnable r) {
|
|
Thread thread = new Thread(r, namePrefix + threadNumber.getAndIncrement());
|
|
thread.setDaemon(false); // 设置为非守护线程
|
|
thread.setPriority(Thread.NORM_PRIORITY);
|
|
return thread;
|
|
}
|
|
|
|
} |