package com.ruoyi.buss.controller;
|
|
import com.alibaba.fastjson2.JSONArray;
|
import com.alibaba.fastjson2.JSONObject;
|
import com.ruoyi.buss.domain.DmBerth2;
|
import com.ruoyi.buss.domain.DsTaskList2;
|
import com.ruoyi.buss.domain.dto.ShipGroupDTO;
|
import com.ruoyi.buss.domain.dto.Subdata;
|
import com.ruoyi.buss.domain.dto.TaskRecordList;
|
import com.ruoyi.buss.domain.dto.ZdGroupDTO;
|
import com.ruoyi.buss.service.IDmBerth2Service;
|
import com.ruoyi.buss.service.IDsTaskList2Service;
|
import com.ruoyi.common.annotation.Log;
|
import com.ruoyi.common.core.controller.BaseController;
|
import com.ruoyi.common.core.domain.AjaxResult;
|
import com.ruoyi.common.core.domain.model.LoginUser;
|
import com.ruoyi.common.enums.BusinessType;
|
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
import org.slf4j.Logger;
|
import org.slf4j.LoggerFactory;
|
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.stereotype.Controller;
|
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.RequestBody;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.ResponseBody;
|
|
import java.io.IOException;
|
import java.text.ParseException;
|
import java.text.SimpleDateFormat;
|
import java.util.*;
|
|
/**
|
* 支队级舰船泊位分组逻辑Controller
|
*
|
* @author yl
|
* @date 2025-03-20
|
*/
|
|
@Tag(name = "支队舰船泊位分组")
|
@Controller
|
@RequestMapping("/buss/zd")
|
public class ZdBerthGroupController extends BaseController {
|
private static final Logger log = LoggerFactory.getLogger(ZdBerthGroupController.class);
|
|
private final static SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
|
@Autowired
|
private IDmBerth2Service dmBerthService;
|
|
@Autowired
|
private IDsTaskList2Service dsTaskListService;
|
|
/**
|
* 获取支队码头泊位分组数据结果。
|
*
|
* @return
|
*/
|
@Operation(description = "获取支队泊位分组结果")
|
@Log(title = "支队泊位分组", businessType = BusinessType.INSERT)
|
@PostMapping("/berthgroup")
|
@ResponseBody
|
public AjaxResult getZdBerthGroup(@RequestBody ZdGroupDTO zdGroupDTO) throws IOException {
|
String berthIds = zdGroupDTO.getBerthIds();
|
String berthRuleStr = zdGroupDTO.getBerthGroupRule();
|
String taskIdStr = zdGroupDTO.getTaskId();
|
List<DmBerth2> dmBerthList = dmBerthService.getDmBerthListByIds(berthIds);
|
log.debug("dmBerthList = " + dmBerthList);
|
Integer berthRule = Integer.parseInt(berthRuleStr);
|
|
// 根据用户所属部门ID,查询管辖码头分配的舰艇信息
|
LoginUser sysUser = getLoginUser();
|
Long deptId = sysUser.getDeptId();
|
log.debug("deptId = : " + deptId);
|
List<DsTaskList2> dsTaskListList = dsTaskListService.getDsTaskListByTaskIdAndDeptId(Long.parseLong(taskIdStr), deptId);
|
log.debug("根据任务、部分ID获取码头JT信息DsTaskList = " + dsTaskListList);
|
JSONArray jsonArray = null;
|
switch (berthRule) {
|
case 1:
|
// 按JT型号分组
|
jsonArray = calcZdBerthGroupByJTModel(berthRuleStr, deptId, dmBerthList, dsTaskListList);
|
break;
|
case 2:
|
// 按DY优先分组
|
jsonArray = calcZdBerthGroupByBullet(berthRuleStr, deptId, dmBerthList, dsTaskListList);
|
break;
|
case 3:
|
// 按优先顺序分组
|
jsonArray = calcZdBerthGroupByOrder(berthRuleStr, deptId, dmBerthList, dsTaskListList);
|
break;
|
case 4:
|
// 按人工分组
|
break;
|
default:
|
// 默认按JT型号分组
|
}
|
return AjaxResult.success(jsonArray);
|
}
|
|
/**
|
* 按JT型号分组算法。
|
* @param berthList
|
* @param dsTaskLists
|
* @return
|
*/
|
private JSONArray calcZdBerthGroupByJTModel(String parkingType, Long deptId, List<DmBerth2> berthList, List<DsTaskList2> dsTaskLists) {
|
// 定义每个泊位的最大长度
|
Long[] berthLengths = new Long[berthList.size()];
|
for(int i = 0; i < berthList.size(); i++){
|
berthLengths[i] = berthList.get(i).getBerthLen();
|
}
|
|
// 按型号分组并两两配对
|
Map<String, List<DsTaskList2>> typeShipMap = new HashMap<>();
|
for (DsTaskList2 ship : dsTaskLists) {
|
typeShipMap.computeIfAbsent(ship.getShipType(), k -> new ArrayList<>()).add(ship);
|
}
|
log.debug("typeShipMap =====: " + typeShipMap);
|
|
List<List<DsTaskList2>> shipPairs = new ArrayList<>();
|
for (List<DsTaskList2> shipsOfType : typeShipMap.values()) {
|
for (int i = 0; i < shipsOfType.size(); i += 2) {
|
shipPairs.add(shipsOfType.subList(i, i + 2));
|
}
|
}
|
log.debug("shipPairs =====: " + shipPairs);
|
|
// 按每组中两艘船停靠时间总和从小到大排序
|
shipPairs.sort(Comparator.comparingDouble(pair -> (pair.get(0).getDockTime() == null ? 0:pair.get(0).getDockTime()) + (pair.get(1).getDockTime()==null ? 0:pair.get(1).getDockTime())));
|
|
// 记录每个泊位的当前总停靠时间
|
int[] berthTotalTimes = new int[berthLengths.length];
|
// 记录每组船分配到的泊位
|
int[] pairAssignments = new int[shipPairs.size()];
|
|
// 分配船只到泊位
|
for (int i = 0; i < shipPairs.size(); i++) {
|
List<DsTaskList2> pair = shipPairs.get(i);
|
Double totalLength = pair.get(0).getShipLen(); // 双船并靠,取一艘船长度判断是否能停靠
|
int minTime = Integer.MAX_VALUE;
|
int bestBerth = -1;
|
for (int j = 0; j < berthLengths.length; j++) {
|
if (totalLength <= berthLengths[j]) {
|
Double dockTimeMax = Math.max(pair.get(0).getDockTime() == null ? 0 : pair.get(0).getDockTime(), pair.get(1).getDockTime() == null ? 0 : pair.get(1).getDockTime());
|
int newTime = berthTotalTimes[j] + dockTimeMax.intValue();
|
if (newTime < minTime) {
|
minTime = newTime;
|
bestBerth = j;
|
}
|
}
|
}
|
pairAssignments[i] = bestBerth;
|
berthTotalTimes[bestBerth] = minTime;
|
}
|
|
// 输出结果
|
for (int i = 0; i < shipPairs.size(); i++) {
|
List<DsTaskList2> pair = shipPairs.get(i);
|
log.debug("舰船 " + pair.get(0).getShipNo() + " 和 " + pair.get(1).getShipNo() + "(型号 " + pair.get(0).getShipType() + ")停靠在泊位 " + (pairAssignments[i] + 1));
|
}
|
int totalTime = Arrays.stream(berthTotalTimes).max().getAsInt();
|
log.debug("所有船停靠到离开泊位的总时间最短为: " + totalTime + " 小时");
|
|
log.debug("******** 按泊位号解析依次排列的DsTaskList对象 ********");
|
// 按泊位号解析依次排列的DsTaskList对象
|
// 按照泊位号顺序,计算每个泊位上停靠舰船的对象DsTaskList
|
HashMap<String, List<DsTaskList2>> resultList = new HashMap<>();
|
for (int i = 0; i < pairAssignments.length; i++) {
|
int berthNumber = pairAssignments[i];
|
String berthKey = "" + (berthNumber + 1);
|
List<DsTaskList2> shipsOnBerth = resultList.computeIfAbsent(berthKey, k -> new ArrayList<>());
|
List<DsTaskList2> pair = shipPairs.get(i);
|
shipsOnBerth.addAll(pair);
|
}
|
|
// 输出结果
|
JSONArray rootJSONArray = new JSONArray();
|
if (resultList != null) {
|
Date firstStartDate = new Date(System.currentTimeMillis());
|
Date lastEndDate = new Date(System.currentTimeMillis());
|
Long totalAmmoD = 0L;//总导弹数
|
Long totalAmmoP = 0L;//总炮弹数
|
Long totalAmmoS = 0L;//总鱼水雷数
|
Long totalAmmoO = 0L;//总其他弹药数
|
Double totalWater = 0.0;//总淡水数
|
Double totalWaterP = 0.0;//总纯水数
|
Long totalFood = 0L;//总主副食数
|
Long totalFoodW = 0L;//总桶装水数
|
Long totalFoodO = 0L;//总其他物资数
|
|
for (Map.Entry<String, List<DsTaskList2>> entry : resultList.entrySet()) {
|
JSONObject rootJSONObj = new JSONObject();
|
JSONObject sub1JsonObj = new JSONObject();
|
JSONArray jsonArray = new JSONArray();
|
log.debug("JT型号分组泊位 " + entry.getKey() + " 上停靠的舰船:");
|
sub1JsonObj.put("berthName", entry.getKey());
|
|
JSONArray subJSONArray = new JSONArray();
|
for (int i = 0; i < dsTaskLists.size(); i++) {
|
DsTaskList2 ship = dsTaskLists.get(i);
|
// 更新DsTaskList数据中的泊位编号、泊位名称、并靠策略和补给顺序字段
|
DsTaskList2 updateDsTaskList = new DsTaskList2();
|
updateDsTaskList.setPKID(ship.getPKID());
|
DmBerth2 berthValue = dmBerthService.selectDmBerthByPKID(Long.parseLong(entry.getKey()));
|
updateDsTaskList.setBerthId(berthValue.getPKID());
|
updateDsTaskList.setBerthName(berthValue.getNAME());
|
updateDsTaskList.setParkingType(parkingType);
|
updateDsTaskList.setSupplySeq(String.valueOf(i+1));
|
updateDsTaskList.setDeptId(deptId);
|
log.debug("Update DsTaskList2 PKID =====: " + ship.getPKID());
|
log.debug("Update DsTaskList2 BerthId =====: " + berthValue.getPKID());
|
log.debug("Update DsTaskList2 BerthName =====: " + berthValue.getNAME());
|
log.debug("Update DsTaskList2 ParkingType =====: " + parkingType);
|
log.debug("Update DsTaskList2 SupplySeq =====: " + (i+1));
|
int result = dsTaskListService.updateDsTaskList(updateDsTaskList);
|
log.debug("==================================: " + result);
|
|
totalAmmoD += ship.getAmmoD() == null ? 0 : ship.getAmmoD();
|
totalAmmoP += ship.getAmmoP() == null ? 0 : ship.getAmmoP();
|
totalAmmoS += ship.getAmmoS() == null ? 0 : ship.getAmmoS();
|
totalAmmoO += ship.getAmmoO() == null ? 0 : ship.getAmmoO();
|
|
totalWater += ship.getWATER() == null ? 0 : ship.getWATER();
|
totalWaterP += ship.getWaterP() == null ? 0 : ship.getWaterP();
|
totalFood += ship.getFOOD() == null ? 0 : ship.getFOOD();
|
totalFoodW += ship.getFoodW() == null ? 0 : ship.getFoodW();
|
totalFoodO += ship.getFoodO() == null ? 0 : ship.getFoodO();
|
|
Date startDate = ship.getpSTime(); //计划抵港时间
|
Date endDate = ship.getpETime(); //计划离港时间
|
if (firstStartDate.after(startDate)) {
|
firstStartDate = startDate;
|
}
|
if (lastEndDate.before(endDate)) {
|
lastEndDate = endDate;
|
}
|
log.debug(" - 船名:" + ship.getShipNo() + ",型号:" + ship.getShipType() + ",停靠时间:" + (ship.getDockTime() == null ? 0 : ship.getDockTime()) + " 分钟");
|
|
// 构建JSON对象
|
JSONObject tmpJsonObject = new JSONObject();
|
tmpJsonObject.put("pkId", ship.getPKID());
|
tmpJsonObject.put("taskId", ship.getTaskId());
|
tmpJsonObject.put("shipNo", ship.getShipNo());
|
tmpJsonObject.put("shipType", ship.getShipType());
|
tmpJsonObject.put("tonnage", ship.getTONNAGE());
|
Long level = ship.getLEVEL() == null ? 1L : ship.getLEVEL();
|
if(level == 2L){//先油后弹
|
tmpJsonObject.put("supplySeq", "先油后弹");
|
}else if(level == 3L){//先弹后油
|
tmpJsonObject.put("supplySeq", "先弹后油");
|
}else{
|
tmpJsonObject.put("supplySeq", "同时作业");
|
}
|
tmpJsonObject.put("level", ship.getLEVEL());
|
tmpJsonObject.put("oilB", ship.getOilB() == null ? 0 : ship.getOilB());
|
tmpJsonObject.put("oilG", ship.getOilG() == null ? 0 : ship.getOilG());
|
tmpJsonObject.put("oilA", ship.getOilA() == null ? 0 : ship.getOilA());
|
tmpJsonObject.put("ammoD", ship.getAmmoD() == null ? 0 : ship.getAmmoD());
|
tmpJsonObject.put("ammoP", ship.getAmmoP() == null ? 0 : ship.getAmmoP());
|
tmpJsonObject.put("ammoS", ship.getAmmoS() == null ? 0 : ship.getAmmoS());
|
tmpJsonObject.put("ammoO", ship.getAmmoO() == null ? 0 : ship.getAmmoO());
|
tmpJsonObject.put("water", ship.getWATER() == null ? 0 : ship.getWATER());
|
tmpJsonObject.put("waterP", ship.getWaterP() == null ? 0 : ship.getWaterP());
|
tmpJsonObject.put("food", ship.getFOOD() == null ? 0 : ship.getFOOD());
|
tmpJsonObject.put("foodW", ship.getFoodW() == null ? 0 : ship.getFoodW());
|
tmpJsonObject.put("foodO", ship.getFoodO() == null ? 0 : ship.getFoodO());
|
tmpJsonObject.put("pSTime", ship.getpSTime() == null ? 0 : ship.getpSTime());
|
tmpJsonObject.put("pETime", ship.getpETime() == null ? 0 : ship.getpETime());
|
subJSONArray.add(tmpJsonObject);
|
sub1JsonObj.put("subData", subJSONArray);
|
}
|
jsonArray.add(sub1JsonObj);
|
rootJSONObj.put("parkingType", parkingType);
|
rootJSONObj.put("dsTaskList", jsonArray);
|
rootJSONObj.put("totalAmmoD", totalAmmoD);
|
rootJSONObj.put("totalAmmoP", totalAmmoP);
|
rootJSONObj.put("totalAmmoS", totalAmmoS);
|
rootJSONObj.put("totalAmmoO", totalAmmoO);
|
rootJSONObj.put("totalWater", totalWater);
|
rootJSONObj.put("totalWaterP", totalWaterP);
|
rootJSONObj.put("totalFood", totalFood);
|
rootJSONObj.put("totalFoodW", totalFoodW);
|
rootJSONObj.put("totalFoodO", totalFoodO);
|
rootJSONObj.put("firstStartDate", format.format(firstStartDate));
|
rootJSONObj.put("lastEndDate", format.format(lastEndDate));
|
rootJSONArray.add(rootJSONObj);
|
}
|
}
|
log.debug("************************************************");
|
return rootJSONArray;
|
}
|
|
/**
|
* 按DY优先分组算法。
|
*/
|
private JSONArray calcZdBerthGroupByBullet(String parkingType, Long deptId, List<DmBerth2> berthList, List<DsTaskList2> dsTaskLists) {
|
// 按加油需求、船类型和抵港时间排序
|
dsTaskLists.sort(Comparator.comparing(DsTaskList2::needRefueling).reversed()
|
.thenComparing(DsTaskList2::getShipType)
|
.thenComparing(DsTaskList2::getpSTime));
|
|
// 按同型号 2 艘一组分组
|
List<List<DsTaskList2>> shipGroups = new ArrayList<>();
|
Map<String, List<DsTaskList2>> typeMap = new HashMap<>();
|
for (DsTaskList2 ship : dsTaskLists) {
|
String shipType = ship.getShipType();
|
typeMap.computeIfAbsent(shipType, k -> new ArrayList<>()).add(ship);
|
}
|
for (List<DsTaskList2> shipsOfType : typeMap.values()) {
|
for (int i = 0; i < shipsOfType.size(); i += 2) {
|
if (i + 1 < shipsOfType.size()) {
|
// 确保一组中需要加油的船排在前面
|
if (!shipsOfType.get(i).needRefueling() && shipsOfType.get(i + 1).needRefueling()) {
|
Collections.swap(shipsOfType, i, i + 1);
|
}
|
shipGroups.add(Arrays.asList(shipsOfType.get(i), shipsOfType.get(i + 1)));
|
} else {
|
// 处理单艘剩余的情况
|
shipGroups.add(Collections.singletonList(shipsOfType.get(i)));
|
}
|
}
|
}
|
log.debug("按弹药优先分组shipGroups =====: " + shipGroups);
|
|
Date currentTime = null;
|
try {
|
currentTime = format.parse("2025-03-01 00:00:00");
|
}catch (Exception ex) {
|
ex.printStackTrace();
|
}
|
|
// 对舰船组按停靠结束时间排序
|
shipGroups.sort(Comparator.comparing(group -> {
|
long maxEndTime = 0;
|
for (DsTaskList2 ship : group) {
|
maxEndTime = Math.max(maxEndTime, ship.getpETime().getTime());
|
}
|
return maxEndTime;
|
}));
|
|
// 模拟停靠过程
|
Map<DsTaskList2, DmBerth2> dockingMap = new HashMap<>();
|
Map<DmBerth2, Date> berthAvailableTime = new HashMap<>();
|
for (DmBerth2 berth : berthList) {
|
berthAvailableTime.put(berth, currentTime);
|
}
|
|
for (List<DsTaskList2> group : shipGroups) {
|
DmBerth2 bestBerth = null;
|
Date earliestAvailableTime = null;
|
for (DmBerth2 berth : berthList) {
|
if (canDock(group, berth)) {
|
Date availableTime = berthAvailableTime.get(berth);
|
if (earliestAvailableTime == null || availableTime.before(earliestAvailableTime)) {
|
earliestAvailableTime = availableTime;
|
bestBerth = berth;
|
}
|
}
|
}
|
if (bestBerth != null) {
|
for (DsTaskList2 ship : group) {
|
dockingMap.put(ship, bestBerth);
|
}
|
long startTime = Math.max(group.get(0).getpSTime().getTime(), earliestAvailableTime.getTime());
|
long endTime = 0;
|
for (DsTaskList2 ship : group) {
|
endTime = Math.max(endTime, ship.getpETime().getTime());
|
}
|
berthAvailableTime.put(bestBerth, new Date(endTime));
|
}
|
}
|
|
// 整理输出结果
|
Map<DmBerth2, List<DsTaskList2>> berthShipMap = new LinkedHashMap<>();
|
for (Map.Entry<DsTaskList2, DmBerth2> entry : dockingMap.entrySet()) {
|
DmBerth2 berth = entry.getValue();
|
DsTaskList2 ship = entry.getKey();
|
berthShipMap.computeIfAbsent(berth, k -> new ArrayList<>()).add(ship);
|
}
|
log.debug("berthShipMap ========: " + berthShipMap);
|
|
//****** add BerthShipMap handle ********//
|
// 将 LinkedHashMap 的键值对转移到 List 中
|
List<Map.Entry<DmBerth2, List<DsTaskList2>>> list = new ArrayList<>(berthShipMap.entrySet());
|
|
// 对 List 进行排序
|
Collections.sort(list, new Comparator<Map.Entry<DmBerth2, List<DsTaskList2>>>() {
|
@Override
|
public int compare(Map.Entry<DmBerth2, List<DsTaskList2>> o1, Map.Entry<DmBerth2, List<DsTaskList2>> o2) {
|
return (int) (((o1.getKey().getHarborId() * 100) + o1.getKey().getOrderNum()) - ((o2.getKey().getHarborId() * 100) + o2.getKey().getOrderNum()));
|
}
|
});
|
|
// 将排序后的键值对存于新的 LinkedHashMap 中
|
LinkedHashMap<DmBerth2, List<DsTaskList2>> sortedMap = new LinkedHashMap<>();
|
for (Map.Entry<DmBerth2, List<DsTaskList2>> entry : list) {
|
sortedMap.put(entry.getKey(), entry.getValue());
|
}
|
//***************************************//
|
|
|
// 按分组输出结果
|
/**
|
for (Map.Entry<DmBerth, List<DsTaskList>> entry : berthShipMap.entrySet()) {
|
DmBerth berth = entry.getKey();
|
List<DsTaskList> shipsInBerth = entry.getValue();
|
StringBuilder shipNos = new StringBuilder();
|
String shipType = shipsInBerth.get(0).getShipType();
|
for (int i = 0; i < shipsInBerth.size(); i++) {
|
if (i > 0) {
|
shipNos.append(" 和 ");
|
}
|
shipNos.append(shipsInBerth.get(i).getShipNo());
|
}
|
System.out.println("船 " + shipNos + "(型号 " + shipType + ")停靠在泊位 " + berth.getNAME());
|
}
|
*/
|
|
JSONArray jsonObj = getJSONObject(parkingType, deptId, sortedMap);
|
return jsonObj;
|
}
|
|
private static boolean canDock(List<DsTaskList2> group, DmBerth2 berth) {
|
for (DsTaskList2 ship : group) {
|
if (ship.getShipLen() > berth.getBerthLen()) {
|
return false;
|
}
|
}
|
return true;
|
}
|
|
/**
|
* 按优先顺序分组算法。
|
*/
|
private JSONArray calcZdBerthGroupByOrder(String parkingType, Long deptId, List<DmBerth2> berthList, List<DsTaskList2> dsTaskLists) {
|
// 按优先级、船类型和抵港时间排序
|
dsTaskLists.sort(Comparator.comparing(DsTaskList2::getLEVEL).reversed()
|
.thenComparing(DsTaskList2::getShipType)
|
.thenComparing(DsTaskList2::getpSTime));
|
JSONArray jsonObj = null;
|
try {
|
jsonObj = handleJtGroup(parkingType, deptId, berthList, dsTaskLists);
|
}catch (Exception e) {
|
e.printStackTrace();
|
}
|
return jsonObj;
|
}
|
|
/**
|
* 根据泊位上舰船并排停靠数量,对排序后的舰船进行分组操作,返回各泊位的舰船停靠结果。
|
*
|
* @return
|
*/
|
private JSONArray handleJtGroup(String parkingType, Long deptId, List<DmBerth2> berthList, List<DsTaskList2> dsTaskLists) throws ParseException {
|
// 默认按同型号 2 艘一组分组
|
List<List<DsTaskList2>> shipGroups = new ArrayList<>();
|
Map<String, List<DsTaskList2>> typeMap = new HashMap<>();
|
for (DsTaskList2 ship : dsTaskLists) {
|
String shipType = ship.getShipType();
|
typeMap.computeIfAbsent(shipType, k -> new ArrayList<>()).add(ship);
|
}
|
for (List<DsTaskList2> shipsOfType : typeMap.values()) {
|
for (int i = 0; i < shipsOfType.size(); i += 2) {
|
if (i + 1 < shipsOfType.size()) {
|
// 确保一组中需要加油的船排在前面
|
if (!shipsOfType.get(i).needRefueling() && shipsOfType.get(i + 1).needRefueling()) {
|
Collections.swap(shipsOfType, i, i + 1);
|
}
|
shipGroups.add(Arrays.asList(shipsOfType.get(i), shipsOfType.get(i + 1)));
|
} else {
|
// 处理单艘剩余的情况
|
shipGroups.add(Collections.singletonList(shipsOfType.get(i)));
|
}
|
}
|
}
|
System.out.println("shipGroups =====: " + shipGroups);
|
|
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
Date currentTime = sdf.parse("2025-03-23 00:00:00");
|
|
// 对舰船组按停靠结束时间排序
|
shipGroups.sort(Comparator.comparing(group -> {
|
long maxEndTime = 0;
|
for (DsTaskList2 ship : group) {
|
maxEndTime = Math.max(maxEndTime, ship.getpETime().getTime());
|
}
|
return maxEndTime;
|
}));
|
|
// 模拟停靠过程
|
Map<DsTaskList2, DmBerth2> dockingMap = new HashMap<>();
|
Map<DmBerth2, Date> berthAvailableTime = new HashMap<>();
|
for (DmBerth2 berth : berthList) {
|
berthAvailableTime.put(berth, currentTime);
|
}
|
|
for (List<DsTaskList2> group : shipGroups) {
|
DmBerth2 bestBerth = null;
|
Date earliestAvailableTime = null;
|
for (DmBerth2 berth : berthList) {
|
if (canDock(group, berth)) {
|
Date availableTime = berthAvailableTime.get(berth);
|
if (earliestAvailableTime == null || availableTime.before(earliestAvailableTime)) {
|
earliestAvailableTime = availableTime;
|
bestBerth = berth;
|
}
|
}
|
}
|
if (bestBerth != null) {
|
for (DsTaskList2 ship : group) {
|
dockingMap.put(ship, bestBerth);
|
}
|
long startTime = Math.max(group.get(0).getpSTime().getTime(), earliestAvailableTime.getTime());
|
long endTime = 0;
|
for (DsTaskList2 ship : group) {
|
endTime = Math.max(endTime, ship.getpETime().getTime());
|
}
|
berthAvailableTime.put(bestBerth, new Date(endTime));
|
}
|
}
|
|
// 整理输出结果
|
Map<DmBerth2, List<DsTaskList2>> berthShipMap = new HashMap<>();
|
for (Map.Entry<DsTaskList2, DmBerth2> entry : dockingMap.entrySet()) {
|
DmBerth2 berth = entry.getValue();
|
DsTaskList2 ship = entry.getKey();
|
berthShipMap.computeIfAbsent(berth, k -> new ArrayList<>()).add(ship);
|
}
|
|
// 按分组输出结果
|
// for (Map.Entry<DmBerth2, List<DsTaskList2>> entry : berthShipMap.entrySet()) {
|
// DmBerth2 berth = entry.getKey();
|
// List<DsTaskList2> shipsInBerth = entry.getValue();
|
// StringBuilder shipNos = new StringBuilder();
|
// String shipType = shipsInBerth.get(0).getShipType();
|
// for (int i = 0; i < shipsInBerth.size(); i++) {
|
// if (i > 0) {
|
// shipNos.append(" 和 ");
|
// }
|
// shipNos.append(shipsInBerth.get(i).getShipNo());
|
// }
|
// System.out.println("船 " + shipNos + "(型号 " + shipType + ")停靠在泊位 " + berth.getNAME());
|
// }
|
|
//****** add BerthShipMap handle ********//
|
// 将 LinkedHashMap 的键值对转移到 List 中
|
List<Map.Entry<DmBerth2, List<DsTaskList2>>> list = new ArrayList<>(berthShipMap.entrySet());
|
|
// 对 List 进行排序
|
Collections.sort(list, new Comparator<Map.Entry<DmBerth2, List<DsTaskList2>>>() {
|
@Override
|
public int compare(Map.Entry<DmBerth2, List<DsTaskList2>> o1, Map.Entry<DmBerth2, List<DsTaskList2>> o2) {
|
return o1.getKey().getPKID().compareTo(o2.getKey().getPKID());
|
}
|
});
|
|
// 将排序后的键值对存于新的 LinkedHashMap 中
|
LinkedHashMap<DmBerth2, List<DsTaskList2>> sortedMap = new LinkedHashMap<>();
|
for (Map.Entry<DmBerth2, List<DsTaskList2>> entry : list) {
|
sortedMap.put(entry.getKey(), entry.getValue());
|
}
|
//***************************************//
|
JSONArray jsonObj = getJSONObject(parkingType, deptId, sortedMap);
|
return null;
|
}
|
|
/**
|
* 构建舰船分组的JSON对象。
|
* @param berthShipMap
|
* @return
|
*/
|
private JSONArray getJSONObject(String parkingType, Long deptId, LinkedHashMap<DmBerth2, List<DsTaskList2>> berthShipMap) {
|
JSONArray rootJSONArray = new JSONArray();
|
if(berthShipMap != null) {
|
Long totalAmmoD = 0L;//总导弹数
|
Long totalAmmoP = 0L;//总炮弹数
|
Long totalAmmoS = 0L;//总鱼水雷数
|
Long totalAmmoO = 0L;//总其他弹药数
|
Double totalWater = 0.0;//总淡水数
|
Double totalWaterP = 0.0;//总纯水数
|
Long totalFood = 0L;//总主副食数
|
Long totalFoodW = 0L;//总桶装水数
|
Long totalFoodO = 0L;//总其他物资数
|
Date firstStartDate = new Date(System.currentTimeMillis());
|
Date lastEndDate = new Date(System.currentTimeMillis());
|
|
for (Map.Entry<DmBerth2, List<DsTaskList2>> entry : berthShipMap.entrySet()) {
|
JSONObject rootJSONObj = new JSONObject();
|
JSONArray jsonArray = new JSONArray();
|
JSONObject sub1JsonObj = new JSONObject();
|
List<DsTaskList2> dsTaskLists = entry.getValue();
|
DmBerth2 berthValue = entry.getKey();
|
String berthName = berthValue.getNAME();
|
Long berthId = berthValue.getPKID();
|
Long harborId = berthValue.getHarborId();
|
String harborName = berthValue.getHarborName();
|
sub1JsonObj.put("harborId", harborId);
|
sub1JsonObj.put("harborName", harborName);
|
sub1JsonObj.put("berthId", berthId);
|
sub1JsonObj.put("berthName", berthName);
|
|
// 输出结果
|
if (dsTaskLists != null) {
|
JSONArray subJSONArray = new JSONArray();
|
for (int i = 0; i < dsTaskLists.size(); i++) {
|
DsTaskList2 ship = dsTaskLists.get(i);
|
// 更新DsTaskList数据中的泊位编号、泊位名称、并靠策略和补给顺序字段
|
DsTaskList2 updateDsTaskList = new DsTaskList2();
|
updateDsTaskList.setPKID(ship.getPKID());
|
updateDsTaskList.setBerthId(berthValue.getPKID());
|
updateDsTaskList.setBerthName(berthValue.getNAME());
|
updateDsTaskList.setParkingType(parkingType);
|
updateDsTaskList.setSupplySeq(String.valueOf(i+1));
|
updateDsTaskList.setDeptId(deptId);
|
log.debug("Update DsTaskList2 PKID =====: " + ship.getPKID());
|
log.debug("Update DsTaskList2 BerthId =====: " + berthValue.getPKID());
|
log.debug("Update DsTaskList2 BerthName =====: " + berthValue.getNAME());
|
log.debug("Update DsTaskList2 ParkingType =====: " + parkingType);
|
log.debug("Update DsTaskList2 SupplySeq =====: " + (i+1));
|
int result = dsTaskListService.updateDsTaskList(updateDsTaskList);
|
log.debug("==================================: " + result);
|
|
totalAmmoD += ship.getAmmoD() == null ? 0 : ship.getAmmoO();
|
totalAmmoP += ship.getAmmoP() == null ? 0 : ship.getAmmoP();
|
totalAmmoS += ship.getAmmoS() == null ? 0 : ship.getAmmoS();
|
totalAmmoO += ship.getAmmoO() == null ? 0 : ship.getAmmoO();
|
|
totalWater += ship.getWATER() == null ? 0 : ship.getWATER();
|
totalWaterP += ship.getWaterP() == null ? 0 : ship.getWaterP();
|
totalFood += ship.getFOOD() == null ? 0 : ship.getFOOD();
|
totalFoodW += ship.getFoodW() == null ? 0 : ship.getFoodW();
|
totalFoodO += ship.getFoodO() == null ? 0 : ship.getFoodW();
|
|
Date startDate = ship.getpSTime(); //计划抵港时间
|
Date endDate = ship.getpETime(); //计划离港时间
|
if (firstStartDate.after(startDate)) {
|
firstStartDate = startDate;
|
}
|
if (lastEndDate.before(endDate)) {
|
lastEndDate = endDate;
|
}
|
|
// 构建JSON对象
|
JSONObject tmpJsonObject = new JSONObject();
|
tmpJsonObject.put("pkId", ship.getPKID());
|
tmpJsonObject.put("taskId", ship.getTaskId());
|
tmpJsonObject.put("shipNo", ship.getShipNo());
|
tmpJsonObject.put("shipType", ship.getShipType());
|
tmpJsonObject.put("tonnage", ship.getTONNAGE() == null ? 0 : ship.getTONNAGE());
|
Long level = ship.getLEVEL() == null ? 1L : ship.getLEVEL();
|
if(level == 2L){//先油后弹
|
tmpJsonObject.put("supplySeq", "先油后弹");
|
}else if(level == 3L){//先弹后油
|
tmpJsonObject.put("supplySeq", "先弹后油");
|
}else{
|
tmpJsonObject.put("supplySeq", "同时作业");
|
}
|
tmpJsonObject.put("level", ship.getLEVEL());
|
tmpJsonObject.put("oilB", ship.getOilB() == null ? 0 : ship.getOilB());
|
tmpJsonObject.put("oilG", ship.getOilG() == null ? 0 : ship.getOilG());
|
tmpJsonObject.put("oilA", ship.getOilA() == null ? 0 : ship.getOilA());
|
tmpJsonObject.put("ammoD", ship.getAmmoD() == null ? 0 : ship.getAmmoD());
|
tmpJsonObject.put("ammoP", ship.getAmmoP() == null ? 0 : ship.getAmmoP());
|
tmpJsonObject.put("ammoS", ship.getAmmoS() == null ? 0 : ship.getAmmoS());
|
tmpJsonObject.put("ammoO", ship.getAmmoO() == null ? 0 : ship.getAmmoO());
|
tmpJsonObject.put("water", ship.getWATER() == null ? 0 : ship.getWATER());
|
tmpJsonObject.put("waterP", ship.getWaterP() == null ? 0 : ship.getWaterP());
|
tmpJsonObject.put("food", ship.getFOOD() == null ? 0 : ship.getFOOD());
|
tmpJsonObject.put("foodW", ship.getFoodW() == null ? 0 : ship.getFoodW());
|
tmpJsonObject.put("foodO", ship.getFoodO() == null ? 0 : ship.getFoodO());
|
tmpJsonObject.put("pSTime", ship.getpSTime());
|
tmpJsonObject.put("pETime", ship.getpETime());
|
subJSONArray.add(tmpJsonObject);
|
sub1JsonObj.put("subData", subJSONArray);
|
}
|
}
|
jsonArray.add(sub1JsonObj);
|
rootJSONObj.put("parkingType", parkingType);
|
rootJSONObj.put("dsTaskList", jsonArray);
|
rootJSONObj.put("totalAmmoD", totalAmmoD);
|
rootJSONObj.put("totalAmmoP", totalAmmoP);
|
rootJSONObj.put("totalAmmoS", totalAmmoS);
|
rootJSONObj.put("totalAmmoO", totalAmmoO);
|
rootJSONObj.put("totalWater", totalWater);
|
rootJSONObj.put("totalWaterP", totalWaterP);
|
rootJSONObj.put("totalFood", totalFood);
|
rootJSONObj.put("totalFoodW", totalFoodW);
|
rootJSONObj.put("totalFoodO", totalFoodO);
|
rootJSONObj.put("firstStartDate", format.format(firstStartDate));
|
rootJSONObj.put("lastEndDate", format.format(lastEndDate));
|
rootJSONArray.add(rootJSONObj);
|
}
|
}
|
log.debug("XXXXXX =====: " + rootJSONArray);
|
return rootJSONArray;
|
}
|
|
/**
|
* 按人工分组算法。
|
*/
|
private void calcZdBerthGroupByHandMove(List<DmBerth2> berthList, List<DsTaskList2> dsTaskLists) {
|
|
}
|
|
/**
|
* 获取支队码头泊位分组数据结果。
|
*
|
* @return
|
*/
|
@Operation(description = "修改舰船补给顺序")
|
@Log(title = "修改舰船补给顺序", businessType = BusinessType.INSERT)
|
@PostMapping("/updatelevel")
|
@ResponseBody
|
public AjaxResult updateSupplyLevelBy(Long pkId, Long supplyLevel) {
|
DsTaskList2 dsTaskList2 = new DsTaskList2();
|
dsTaskList2.setPKID(pkId);
|
dsTaskList2.setLEVEL(supplyLevel);
|
try {
|
int result = dsTaskListService.updateDsTaskList(dsTaskList2);
|
if (result > 0) {
|
return AjaxResult.success("PKID = [" + String.valueOf(pkId) + "]记录补给顺序更新成功");
|
} else {
|
return AjaxResult.success("未找到符合条件的记录进行更新");
|
}
|
} catch (Exception ex) {
|
return AjaxResult.error("PKID = [" + String.valueOf(pkId) + "]记录补给顺序更新失败");
|
}
|
}
|
|
@Operation(description = "更新支队分组顺序")
|
@Log(title = "更新支队分组顺序", businessType = BusinessType.INSERT)
|
@PostMapping("/updategroupseq")
|
@ResponseBody
|
public AjaxResult updateShipGroupSeq(@RequestBody List<ShipGroupDTO> shipGroupDTOList){
|
int flag = 0;
|
if(shipGroupDTOList != null && shipGroupDTOList.size() > 0){
|
// 获取所有的泊位信息
|
List<DmBerth2> berth2List = dmBerthService.selectDmBerthList(new DmBerth2());
|
|
for(ShipGroupDTO shipGroupDTO : shipGroupDTOList){
|
// String parkingType = shipGroupDTO.getParkingType();
|
List<TaskRecordList> taskRecordList = shipGroupDTO.getDsTaskList();
|
Long berthId = taskRecordList.get(0).getBerthId();
|
Long harborId = taskRecordList.get(0).getHarborId();
|
List<Subdata> subDataList = taskRecordList.get(0).getSubData();
|
if(subDataList!= null && subDataList.size() > 0){
|
for(int i = 0; i < subDataList.size(); i++){
|
Subdata subdata = subDataList.get(i);
|
Long pkId = subdata.getPkId();
|
String supplySeq = subdata.getSupplySeq();
|
if(supplySeq.equals("同时作业")){
|
supplySeq = "1";
|
}
|
else if(supplySeq.equals("先油后弹")){
|
supplySeq = "2";
|
}if(supplySeq.equals("先弹后油")){
|
supplySeq = "3";
|
}
|
|
// DsTaskList2 dsTaskList = new DsTaskList2();
|
// dsTaskList.setPKID(pkId);
|
DsTaskList2 existDsTaskList = dsTaskListService.selectDsTaskListByPkid(pkId);
|
if(existDsTaskList != null){
|
// Long tempBerthId = existDsTaskList.getBerthId();
|
// Long tempHarborId = existDsTaskList.getHarborId();
|
// String tempSupplySeq = existDsTaskList.getSupplySeq();
|
// if(berthId != tempBerthId || harborId != tempHarborId){
|
DsTaskList2 newDsTaskList = new DsTaskList2();
|
newDsTaskList.setPKID(pkId);
|
newDsTaskList.setHarborId(harborId);
|
newDsTaskList.setBerthId(berthId);
|
newDsTaskList.setSupplySeq(supplySeq);
|
newDsTaskList.setPath(getBerthPathById(berth2List, berthId));
|
int result = dsTaskListService.updateDsTaskList(newDsTaskList);
|
if(result > 0 || result == 0){
|
flag += 1;
|
}
|
// }
|
}
|
}
|
}
|
}
|
if(flag > 0){
|
return AjaxResult.success("支队分组顺序更新成功!");
|
}else{
|
return AjaxResult.success("分组顺序无调整!");
|
}
|
}
|
return AjaxResult.success("支队分组顺序没有变化,未更新!");
|
}
|
|
// 根据ID获取泊位路径信息详情
|
private String getBerthPathById(List<DmBerth2> list, Long id){
|
for(DmBerth2 berth2 : list){
|
if(berth2.getPKID() == id){
|
return berth2.getPath();
|
}
|
}
|
return "";
|
}
|
}
|