diff --git a/src/main/java/club/joylink/rtss/simulation/cbtc/ATS/ATSLogicLoop.java b/src/main/java/club/joylink/rtss/simulation/cbtc/ATS/ATSLogicLoop.java index 934ef09a0..c1c87b019 100644 --- a/src/main/java/club/joylink/rtss/simulation/cbtc/ATS/ATSLogicLoop.java +++ b/src/main/java/club/joylink/rtss/simulation/cbtc/ATS/ATSLogicLoop.java @@ -3,7 +3,6 @@ package club.joylink.rtss.simulation.cbtc.ATS; import club.joylink.rtss.simulation.cbtc.ATS.service.AtsStandService; import club.joylink.rtss.simulation.cbtc.ATS.service.AtsStationService; import club.joylink.rtss.simulation.cbtc.ATS.service.AtsTrainMonitorService; -import club.joylink.rtss.simulation.cbtc.ATS.tools.TrainOutboundLoadTool; import club.joylink.rtss.simulation.cbtc.Simulation; import club.joylink.rtss.simulation.cbtc.constant.SimulationConstants; import club.joylink.rtss.simulation.cbtc.constant.SimulationModule; @@ -24,11 +23,8 @@ public class ATSLogicLoop { private AtsStationService atsStationService; @Autowired private AtsTrainMonitorService atsTrainMonitorService; - @Autowired - private TrainOutboundLoadTool trainOutboundLoadTool; public void run(Simulation simulation) { - this.trainOutboundLoadTool.loadOutboundTrain(simulation); this.atsStandService.countDown(simulation); this.atsTrainMonitorService.monitor(simulation); this.atsStationService.updateFieldThatChangeOverTime(simulation); diff --git a/src/main/java/club/joylink/rtss/simulation/cbtc/ATS/operation/handler/TrainOperateHandler.java b/src/main/java/club/joylink/rtss/simulation/cbtc/ATS/operation/handler/TrainOperateHandler.java index f64706942..5f517df23 100644 --- a/src/main/java/club/joylink/rtss/simulation/cbtc/ATS/operation/handler/TrainOperateHandler.java +++ b/src/main/java/club/joylink/rtss/simulation/cbtc/ATS/operation/handler/TrainOperateHandler.java @@ -50,7 +50,7 @@ public class TrainOperateHandler { SimulationDataRepository repository = simulation.getRepository(); List onlineTrainList = repository.getOnlineTrainList(); VirtualRealityTrain train = repository - .getTrain(serviceNumber, tripNumber); + .getTrain(simulation, serviceNumber, tripNumber); for (VirtualRealityTrain online : onlineTrainList) { if (Objects.equals(train, online)) { throw new SimulationException(SimulationExceptionType.Operation_Handle_FAIL, diff --git a/src/main/java/club/joylink/rtss/simulation/cbtc/ATS/service/AtsTrainLoadService.java b/src/main/java/club/joylink/rtss/simulation/cbtc/ATS/service/AtsTrainLoadService.java index 3f4287d5c..880150e46 100644 --- a/src/main/java/club/joylink/rtss/simulation/cbtc/ATS/service/AtsTrainLoadService.java +++ b/src/main/java/club/joylink/rtss/simulation/cbtc/ATS/service/AtsTrainLoadService.java @@ -510,7 +510,10 @@ public class AtsTrainLoadService { SimulationDataRepository repository = simulation.getRepository(); for (VirtualRealityTrain train : loadedList) { // 构建监控列车信息 - TrainInfo trainInfo = new TrainInfo(train.getGroupNumber()); + TrainInfo trainInfo = simulation.getRepository().getTrainInfoMap().get(train.getGroupNumber()); + if (trainInfo == null) { + trainInfo = new TrainInfo(train.getGroupNumber()); + } TripPlan tripPlan = repository.getTripPlan(train.getServiceNumber(), train.getTripNumber()); trainInfo.init(tripPlan, repository.getConfig()); List stationPlanList = tripPlan.getPlanList(); @@ -739,7 +742,7 @@ public class AtsTrainLoadService { break; } TripPlan tripPlan = trainLoadParam2.getTripPlan(); - VirtualRealityTrain train = repository.getTrain(tripPlan.getServiceNumber(), tripPlan.getTripNumber()); + VirtualRealityTrain train = repository.getTrain(simulation, tripPlan.getServiceNumber(), tripPlan.getTripNumber()); if (loadedTrainList.contains(train)) { throw new SimulationException(SimulationExceptionType.System_Fault, String.format("加载计划[%s|%s|%s]和[%s|%s|%s]使用列车重复", @@ -824,7 +827,7 @@ public class AtsTrainLoadService { List allTripPlanList = repository.getAllTripPlanList(); allTripPlanList.forEach(tripPlan -> { if (!systemTime.isBefore(tripPlan.getStartTime())) { - tripPlan.dispatch(); + tripPlan.departure(); tripPlan.finishStationPlanOf(systemTime); } }); diff --git a/src/main/java/club/joylink/rtss/simulation/cbtc/ATS/service/stage/AtsHeadTrainStageService.java b/src/main/java/club/joylink/rtss/simulation/cbtc/ATS/service/stage/AtsHeadTrainStageService.java index eb17ba6a2..49dab3722 100644 --- a/src/main/java/club/joylink/rtss/simulation/cbtc/ATS/service/stage/AtsHeadTrainStageService.java +++ b/src/main/java/club/joylink/rtss/simulation/cbtc/ATS/service/stage/AtsHeadTrainStageService.java @@ -3,9 +3,11 @@ package club.joylink.rtss.simulation.cbtc.ATS.service.stage; import club.joylink.rtss.simulation.cbtc.ATS.service.AtsStandService; import club.joylink.rtss.simulation.cbtc.ATS.service.AtsTrainService; import club.joylink.rtss.simulation.cbtc.Simulation; -import club.joylink.rtss.simulation.cbtc.data.CalculateService; import club.joylink.rtss.simulation.cbtc.data.SimulationDataRepository; -import club.joylink.rtss.simulation.cbtc.data.map.*; +import club.joylink.rtss.simulation.cbtc.data.map.DestinationCodeDefinition; +import club.joylink.rtss.simulation.cbtc.data.map.Section; +import club.joylink.rtss.simulation.cbtc.data.map.Stand; +import club.joylink.rtss.simulation.cbtc.data.map.StationRunLevel; import club.joylink.rtss.simulation.cbtc.data.support.RoutePath; import club.joylink.rtss.simulation.cbtc.data.support.SectionPosition; import club.joylink.rtss.simulation.cbtc.data.vo.TrainInfo; @@ -13,9 +15,7 @@ import club.joylink.rtss.simulation.cbtc.onboard.ATP.ATPService; import club.joylink.rtss.simulation.cbtc.onboard.ATP.OnboardAtpApiService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import org.springframework.stereotype.Repository; import org.springframework.util.CollectionUtils; -import org.springframework.util.StringUtils; import java.util.Comparator; import java.util.List; @@ -87,7 +87,11 @@ public class AtsHeadTrainStageService implements AtsStageService { */ private void handleArriveDestination(Simulation simulation, TrainInfo trainInfo) { // 先回库,后设置为人工车 - trainInfo.finishPlanPrepareInbound(); + if (simulation.getRepository().getConfig().isHandleDepot()) { + trainInfo.finishPlanPrepareEnterDepot(); + } else { + trainInfo.finishPlanPrepareInbound(); + } if (simulation.getRepository().getConfig().isSetManualWhenHeadTrainArriveTarget()) { atsTrainService.setManualTrain(simulation, trainInfo.getGroupNumber()); } diff --git a/src/main/java/club/joylink/rtss/simulation/cbtc/ATS/service/stage/AtsManualTrainStageService.java b/src/main/java/club/joylink/rtss/simulation/cbtc/ATS/service/stage/AtsManualTrainStageService.java index c0c3c5180..f6d4b7193 100644 --- a/src/main/java/club/joylink/rtss/simulation/cbtc/ATS/service/stage/AtsManualTrainStageService.java +++ b/src/main/java/club/joylink/rtss/simulation/cbtc/ATS/service/stage/AtsManualTrainStageService.java @@ -4,7 +4,6 @@ import club.joylink.rtss.simulation.cbtc.Simulation; import club.joylink.rtss.simulation.cbtc.data.SimulationDataRepository; import club.joylink.rtss.simulation.cbtc.data.map.Section; import club.joylink.rtss.simulation.cbtc.data.plan.TripPlan; -import club.joylink.rtss.simulation.cbtc.data.support.RoutePath; import club.joylink.rtss.simulation.cbtc.data.vo.TrainInfo; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -25,12 +24,12 @@ public class AtsManualTrainStageService implements AtsStageService { @Override public void handleTransferTrackParking(Simulation simulation, TrainInfo trainInfo, Section parkSection) { - SimulationDataRepository repository = simulation.getRepository(); - List routePathList = repository.queryRoutePathsByEnd(parkSection); - boolean in = false; // 回库?出库? - if (routePathList.get(0).isRight() == trainInfo.getRight().booleanValue()) { - in = true; - } +// SimulationDataRepository repository = simulation.getRepository(); +// List routePathList = repository.queryRoutePathsByEnd(parkSection); + boolean in = trainInfo.isInbound(); // 回库? +// if (routePathList.get(0).isRight() == trainInfo.getRight().booleanValue()) { +// in = true; +// } if (!in) { // 出库,查询计划,是否此轨道有出库计划 if (simulation.isPlanRunning()) { this.checkAndApplyTripPlan(simulation, trainInfo, parkSection); @@ -69,7 +68,7 @@ public class AtsManualTrainStageService implements AtsStageService { } if (systemTime.toLocalTime().plusMinutes(10).isAfter(tripPlan.getStartTime())) { this.planTrainStageService.updateTripPlan(simulation, trainInfo, tripPlan); - tripPlan.dispatch(); + tripPlan.departure(); this.realRunRecordService.recordTrainRealRun(simulation, trainInfo, parkSection.getStation(), parkSection, true); break; diff --git a/src/main/java/club/joylink/rtss/simulation/cbtc/ATS/service/stage/AtsPlanTrainStageService.java b/src/main/java/club/joylink/rtss/simulation/cbtc/ATS/service/stage/AtsPlanTrainStageService.java index 9c4606b00..a5edae484 100644 --- a/src/main/java/club/joylink/rtss/simulation/cbtc/ATS/service/stage/AtsPlanTrainStageService.java +++ b/src/main/java/club/joylink/rtss/simulation/cbtc/ATS/service/stage/AtsPlanTrainStageService.java @@ -2,6 +2,7 @@ package club.joylink.rtss.simulation.cbtc.ATS.service.stage; import club.joylink.rtss.exception.BusinessExceptionAssertEnum; import club.joylink.rtss.simulation.cbtc.ATS.service.AtsStandService; +import club.joylink.rtss.simulation.cbtc.ATS.service.AtsTrainService; import club.joylink.rtss.simulation.cbtc.Simulation; import club.joylink.rtss.simulation.cbtc.data.SimulationDataRepository; import club.joylink.rtss.simulation.cbtc.data.map.*; @@ -34,22 +35,31 @@ public class AtsPlanTrainStageService implements AtsStageService { private AtsStandService atsStandService; @Autowired private OnboardAtpApiService onboardAtpApiService; + @Autowired + private AtsTrainService atsTrainService; @Override public void handleTransferTrackParking(Simulation simulation, TrainInfo trainInfo, Section parkSection) { SimulationDataRepository repository = simulation.getRepository(); TripPlan tripPlan = repository.getTripPlan(trainInfo.getServiceNumber(), trainInfo.getTripNumber()); - List routePathList = repository.queryRoutePathsByEnd(parkSection); - if (routePathList.get(0).isRight() == trainInfo.getRight()) { //准备回库 - if (!parkSection.isTurnBackTrack()) { //针对上饶沙盘 - trainInfo.finishPlanPrepareInbound(); - } - } else if (tripPlan.getEndSection().equals(parkSection) || +// List routePathList = repository.queryRoutePathsByEnd(parkSection); +// if (routePathList.get(0).isRight() == trainInfo.getRight()) { //准备回库 +// if (!parkSection.isTurnBackTrack()) { //针对上饶沙盘 +// trainInfo.finishPlanPrepareInbound(); +// } +// } else 没看懂为啥有这部分逻辑,先注掉 + if (tripPlan.getEndSection().equals(parkSection) || tripPlan.getEndSection().getStation().equals(parkSection.getStation())) { // 列车到达计划终点,准备回库 - if (!parkSection.isTurnBackTrack()) { //针对上饶沙盘 - trainInfo.finishPlanPrepareInbound(); + if (simulation.getRepository().getConfig().isHandleDepot()) { + trainInfo.finishPlanPrepareEnterDepot(); + } else { + if (!parkSection.isTurnBackTrack()) { //针对上饶沙盘 + trainInfo.finishPlanPrepareInbound(); + } } + //转人工车 + atsTrainService.setManualTrain(simulation, trainInfo.getGroupNumber()); } else if (tripPlan.getStartSection().equals(parkSection)) { // 出库列车 if (trainInfo.getPlanStandTrack() != null) { diff --git a/src/main/java/club/joylink/rtss/simulation/cbtc/ATS/service/stage/AtsTrainStageHandler.java b/src/main/java/club/joylink/rtss/simulation/cbtc/ATS/service/stage/AtsTrainStageHandler.java index 5bd9e853f..5ca99eaa7 100644 --- a/src/main/java/club/joylink/rtss/simulation/cbtc/ATS/service/stage/AtsTrainStageHandler.java +++ b/src/main/java/club/joylink/rtss/simulation/cbtc/ATS/service/stage/AtsTrainStageHandler.java @@ -39,6 +39,8 @@ public class AtsTrainStageHandler { public void handleInbound(Simulation simulation, TrainInfo train) { SimulationDataRepository repository = simulation.getRepository(); int deleteRemain = train.getDeleteRemain(); + if (deleteRemain < 0) //以该条件作为列车入库是要进入车辆段而不是消失的标记 + return; deleteRemain -= SimulationModule.ATS.getRateMs(); if (deleteRemain <= 0) { // 删除列车 repository.deleteOnlineTrain(train.getGroupNumber()); diff --git a/src/main/java/club/joylink/rtss/simulation/cbtc/SimulationLifeCycleServiceImpl.java b/src/main/java/club/joylink/rtss/simulation/cbtc/SimulationLifeCycleServiceImpl.java index ee4c3b8ed..7b9d41db2 100644 --- a/src/main/java/club/joylink/rtss/simulation/cbtc/SimulationLifeCycleServiceImpl.java +++ b/src/main/java/club/joylink/rtss/simulation/cbtc/SimulationLifeCycleServiceImpl.java @@ -14,15 +14,18 @@ import club.joylink.rtss.simulation.cbtc.build.SimulationBuilder; import club.joylink.rtss.simulation.cbtc.command.VoiceCommandBO; import club.joylink.rtss.simulation.cbtc.communication.Joylink3DMessageService; import club.joylink.rtss.simulation.cbtc.data.SimulationDataRepository; -import club.joylink.rtss.simulation.cbtc.data.map.Station; import club.joylink.rtss.simulation.cbtc.data.plan.SchedulingTrainPlan; -import club.joylink.rtss.simulation.cbtc.data.vr.VirtualRealityIbp; import club.joylink.rtss.simulation.cbtc.data.vr.VirtualRealityTrain; -import club.joylink.rtss.simulation.cbtc.depot.DepotLoadService; +import club.joylink.rtss.simulation.cbtc.depot.DepotService; import club.joylink.rtss.simulation.cbtc.device.real.modbustcp.SimulationRealDeviceConnectManager; import club.joylink.rtss.simulation.cbtc.device.virtual.VRDeviceLogicLoop; import club.joylink.rtss.simulation.cbtc.device.virtual.VRTrainRunningService; -import club.joylink.rtss.simulation.cbtc.event.*; +import club.joylink.rtss.simulation.cbtc.event.SimulationCreateSuccessEvent; +import club.joylink.rtss.simulation.cbtc.event.SimulationErrorEvent; +import club.joylink.rtss.simulation.cbtc.event.SimulationPauseEvent; +import club.joylink.rtss.simulation.cbtc.event.SimulationResetEvent; +import club.joylink.rtss.simulation.cbtc.event.SimulationResumeEvent; +import club.joylink.rtss.simulation.cbtc.event.SimulationRunPlanReloadEvent; import club.joylink.rtss.simulation.cbtc.exception.SimulationException; import club.joylink.rtss.simulation.cbtc.exception.SimulationExceptionType; import club.joylink.rtss.simulation.cbtc.fault.FaultGenerator; @@ -31,10 +34,6 @@ import club.joylink.rtss.simulation.cbtc.onboard.ATP.ATPLogicLoop; import club.joylink.rtss.simulation.cbtc.onboard.TrainTargetUpdateService; import club.joylink.rtss.simulation.cbtc.robot.RobotLogicLoop; import club.joylink.rtss.simulation.rt.iscs.IscsStatusPublisher; -import club.joylink.rtss.util.JsonUtils; -import club.joylink.rtss.vo.client.ibp.IbpData; -import club.joylink.rtss.vo.client.ibp.IbpQueryVO; -import club.joylink.rtss.vo.client.ibp.IbpVO; import club.joylink.rtss.vo.client.runplan.RunPlanVO; import club.joylink.rtss.vo.client.schedulingNew.SchedulingPlanNewVO; import lombok.extern.slf4j.Slf4j; @@ -112,7 +111,7 @@ public class SimulationLifeCycleServiceImpl implements SimulationLifeCycleServic private IbpService ibpService; @Autowired - private DepotLoadService depotLoadService; + private DepotService depotService; @Override public Simulation create(SimulationBuildParams params, String group) { @@ -126,7 +125,7 @@ public class SimulationLifeCycleServiceImpl implements SimulationLifeCycleServic simulation.addMessagePublisher(new IscsStatusPublisher(simulation)); // 初始化设备状态 this.deviceStatusService.init(simulation); - depotLoadService.loadDepotTrain(simulation); + depotService.loadDepotTrain(simulation); // 初始化成员 this.memberManager.init(simulation); // 初始化语音指令 @@ -141,6 +140,7 @@ public class SimulationLifeCycleServiceImpl implements SimulationLifeCycleServic private void addJobs(Simulation simulation) { atsLogicLoop.addJobs(simulation); atpLogicLoop.addJobs(simulation); + depotService.addJobs(simulation); trainTargetUpdateService.addJobs(simulation); vrTrainRunningService.addJobs(simulation); this.ciLogic.addJobs(simulation); @@ -220,7 +220,7 @@ public class SimulationLifeCycleServiceImpl implements SimulationLifeCycleServic // } // 初始化设备状态 this.deviceStatusService.init(simulation); - depotLoadService.loadDepotTrain(simulation); + depotService.loadDepotTrain(simulation); // Map oldMemberMap = simulation.getMemberMap(); // Simulation build = SimulationBuilder.build(simulation.getBuildParams()); // simulation.resetFrom(build); diff --git a/src/main/java/club/joylink/rtss/simulation/cbtc/build/MapDeviceBuilder.java b/src/main/java/club/joylink/rtss/simulation/cbtc/build/MapDeviceBuilder.java index 1654aa0e5..7c876f550 100644 --- a/src/main/java/club/joylink/rtss/simulation/cbtc/build/MapDeviceBuilder.java +++ b/src/main/java/club/joylink/rtss/simulation/cbtc/build/MapDeviceBuilder.java @@ -318,13 +318,22 @@ public class MapDeviceBuilder { }); /* ZC和区段相互赋值 */ // ZC - if (graphData.getZcList().size() == 1) { + if (graphData.getZcList().size() == 1 && CollectionUtils.isEmpty(graphData.getZcList().get(0).getManagedSectionList())) { + //线路的【ZC只有一个】且【ZC没有设置关联区段】时,自动关联全线计轴区段 MapZcVO mapZcVO = graphData.getZcList().get(0); ZC zc = (ZC) elementMap.get(mapZcVO.getCode()); - physicalSectionList.forEach(section -> { - zc.addSection(section); - section.addZc(zc); - }); + elementMap.values().stream() + .filter(element -> element instanceof Section) + .map(element -> (Section) element) + .filter(Section::isAxleCounter) + .forEach(section -> { + zc.addSection(section); + section.addZc(zc); + }); +// physicalSectionList.forEach(section -> { +// zc.addSection(section); +// section.addZc(zc); +// }); } else { graphData.getZcList().forEach(mapZcVO -> { if (mapZcVO.isNoService()) @@ -338,15 +347,20 @@ public class MapDeviceBuilder { Section section = (Section) elementMap.get(sectionCode); BusinessExceptionAssertEnum.SYSTEM_EXCEPTION.assertNotNull(section, String.format("ZC[%s]关联的区段[%s]不存在", zc.getCode(), sectionCode)); - if (section.isPhysical()) { - section.addZc(zc); - zc.addSection(section); - } else if (section.isSwitchAxleCounterSection() || section.isCross()) { - section.getLogicList().forEach(logic -> { - logic.addZc(zc); - zc.addSection(logic); - }); + Section axleCounterSection = section.findAxleCounterSection(); + if (axleCounterSection != null) { + axleCounterSection.addZc(zc); + zc.addSection(axleCounterSection); } +// if (section.isPhysical()) { +// section.addZc(zc); +// zc.addSection(section); +// } else if (section.isSwitchAxleCounterSection() || section.isCross()) { +// section.getLogicList().forEach(logic -> { +// logic.addZc(zc); +// zc.addSection(logic); +// }); +// } } } }); diff --git a/src/main/java/club/joylink/rtss/simulation/cbtc/build/SchedulingBuilder.java b/src/main/java/club/joylink/rtss/simulation/cbtc/build/SchedulingBuilder.java index 14e25b6ee..c1e4890fd 100644 --- a/src/main/java/club/joylink/rtss/simulation/cbtc/build/SchedulingBuilder.java +++ b/src/main/java/club/joylink/rtss/simulation/cbtc/build/SchedulingBuilder.java @@ -3,6 +3,7 @@ package club.joylink.rtss.simulation.cbtc.build; import club.joylink.rtss.simulation.cbtc.Simulation; import club.joylink.rtss.simulation.cbtc.data.SimulationDataRepository; import club.joylink.rtss.simulation.cbtc.data.map.MapElement; +import club.joylink.rtss.simulation.cbtc.data.map.Station; import club.joylink.rtss.simulation.cbtc.data.plan.SchedulingTrainPlan; import club.joylink.rtss.simulation.cbtc.data.plan.TripPlan; import club.joylink.rtss.simulation.cbtc.data.vr.VirtualRealityTrain; @@ -72,19 +73,34 @@ public class SchedulingBuilder { trainList.size(), schedulingPlanList.size())); } // 分配列车到派班计划 - LinkedList trainQueue = new LinkedList<>(trainList); - Map serverTrainMap = new HashMap<>(); - for (int i = 0; i < schedulingPlanList.size(); i++) { - SchedulingTrainPlan schedulingTrainPlan = schedulingPlanList.get(i); - String serviceNumber = schedulingTrainPlan.getOutDepotTrip().getServiceNumber(); - VirtualRealityTrain train = serverTrainMap.get(serviceNumber); - if (Objects.nonNull(train)) { - schedulingTrainPlan.setGroupNumber(train.getGroupNumber()); - } else { - train = trainQueue.poll(); - serverTrainMap.put(serviceNumber, train); + if (simulation.getRepository().getConfig().isHandleDepot()) { + Map> map = new HashMap<>(); + for (VirtualRealityTrain train : trainList) { + Queue queue = map.computeIfAbsent(train.getDepotStation(), key -> new LinkedList<>()); + queue.add(train); + } + Map serverTrainMap = new HashMap<>(); + for (SchedulingTrainPlan schedulingTrainPlan : schedulingPlanList) { + String serviceNumber = schedulingTrainPlan.getOutDepotTrip().getServiceNumber(); + VirtualRealityTrain train = serverTrainMap.get(serviceNumber); + if (Objects.isNull(train)) { + train = map.get(schedulingTrainPlan.getOutDepotTrip().getStartSection().getStation()).poll(); + serverTrainMap.put(serviceNumber, train); + } + schedulingTrainPlan.setGroupNumber(train.getGroupNumber()); + } + } else { + LinkedList trainQueue = new LinkedList<>(trainList); + Map serverTrainMap = new HashMap<>(); + for (SchedulingTrainPlan schedulingTrainPlan : schedulingPlanList) { + String serviceNumber = schedulingTrainPlan.getOutDepotTrip().getServiceNumber(); + VirtualRealityTrain train = serverTrainMap.get(serviceNumber); + if (Objects.isNull(train)) { + train = trainQueue.poll(); + serverTrainMap.put(serviceNumber, train); + } + schedulingTrainPlan.setGroupNumber(train.getGroupNumber()); } - schedulingTrainPlan.setGroupNumber(train.getGroupNumber()); } repository.setSchedulingTrainPlanList(schedulingPlanList); return schedulingPlanList; diff --git a/src/main/java/club/joylink/rtss/simulation/cbtc/build/SimulationBuilder.java b/src/main/java/club/joylink/rtss/simulation/cbtc/build/SimulationBuilder.java index 8c2664ca8..12ff17feb 100644 --- a/src/main/java/club/joylink/rtss/simulation/cbtc/build/SimulationBuilder.java +++ b/src/main/java/club/joylink/rtss/simulation/cbtc/build/SimulationBuilder.java @@ -1,416 +1,492 @@ -package club.joylink.rtss.simulation.cbtc.build; - -import club.joylink.rtss.entity.Ibp; -import club.joylink.rtss.simulation.cbtc.Simulation; -import club.joylink.rtss.simulation.cbtc.data.CalculateService; -import club.joylink.rtss.simulation.cbtc.data.SimulationDataRepository; -import club.joylink.rtss.simulation.cbtc.data.map.*; -import club.joylink.rtss.simulation.cbtc.data.plan.TerminalDeparturePlan; -import club.joylink.rtss.simulation.cbtc.data.plan.TripPlan; -import club.joylink.rtss.simulation.cbtc.data.support.RoutePath; -import club.joylink.rtss.simulation.cbtc.data.vr.VirtualRealityDevice; -import club.joylink.rtss.simulation.cbtc.data.vr.VirtualRealityIbp; -import club.joylink.rtss.util.JsonUtils; -import club.joylink.rtss.vo.client.ibp.IbpData; -import club.joylink.rtss.vo.client.runplan.RunPlanVO; -import club.joylink.rtss.vo.client.schedulingNew.SchedulingPlanNewVO; -import club.joylink.rtss.vo.map.logic.MapStationParkingTimeVO; -import club.joylink.rtss.vo.map.MapVO; -import club.joylink.rtss.vo.map.RealLineConfigVO; -import lombok.Getter; -import lombok.Setter; -import lombok.extern.slf4j.Slf4j; -import org.springframework.util.CollectionUtils; - -import javax.swing.text.Element; -import java.util.*; -import java.util.function.Function; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -@Slf4j -public class SimulationBuilder { - - /** - * 构造仿真对象 - */ - public static Simulation build(String group, SimulationBuildParams buildParams) { - Simulation simulation = new Simulation(group); - simulation.setBuildParams(buildParams); - if (Objects.nonNull(buildParams.getLoginUserInfo())) { - simulation.setProject(buildParams.getLoginUserInfo().getProject()); - } - // 线路配置参数 - simulation.getRepository().setConfig(buildConfig(buildParams.getMap().getConfigVO())); - simulation.getRepository().getConfig() - .setRouteLikeHa1(buildParams.getMap().getGraphDataNew().getGenerateConfig().isLikeHa1()); - simulation.getRepository().getConfig() - .setOverlapSettingByTrigger(buildParams.getMap().getGraphDataNew().getGenerateConfig().isOverlapSettingByTrigger()); - simulation.getRepository().getConfig() - .setSharingECStations(buildParams.getMap().getGraphDataNew().getGenerateConfig().getSharingECStations()); - simulation.getRepository().getConfig() - .setHandleDepot(buildParams.getMap().getGraphDataNew().getGenerateConfig().isHandleDepot()); - // 地图数据构建 - SimulationDeviceBuildResult mapDataBuildResult = checkAndBuildMapData(buildParams.getMap()); - // ibp数据构建 - buildIbpData(mapDataBuildResult, buildParams.getMap().getIbpList()); - simulation.getRepository().setDeviceMap(mapDataBuildResult.getDeviceMap()); - simulation.getRepository().setSectionArriveNearMap(mapDataBuildResult.sectionArriveNearMap); - simulation.getRepository().setVrDeviceMap(mapDataBuildResult.getVrDeviceMap()); -// simulation.getRepository().setRouteUnitMap(mapDataBuildResult.getRouteUnitMap()); - simulation.getRepository().setRoutePathMap(mapDataBuildResult.getRoutePathMap()); - simulation.getRepository().setDestinationMap(mapDataBuildResult.getDestinationMap()); - simulation.getRepository().setRoutingList(mapDataBuildResult.getRoutingList()); -// simulation.getRepository().setRunLevelList(mapDataBuildResult.getRunLevelList()); - simulation.getRepository().getCatenaryMap().putAll(mapDataBuildResult.getCatenaryMap()); - simulation.getRepository().getSectionRespondersMap().putAll(mapDataBuildResult.getSectionRespondersMap()); - simulation.getRepository().setParkingTracksMap(mapDataBuildResult.getParkingTracksMap()); -// simulation.getRepository().setParkTimeMap(mapDataBuildResult.getParkTimeMap()); - UserConfigDataBuilder.buildRunLevel(simulation.getRepository(), buildParams.getUserRunLevelList(), - buildParams.getMap(), mapDataBuildResult.getErrMsgList()); - UserConfigDataBuilder.buildParkTime(simulation.getRepository(), buildParams.getUserParkTimeList(), - buildParams.getMap(), mapDataBuildResult.getErrMsgList()); - if (!CollectionUtils.isEmpty(mapDataBuildResult.getErrMsgList())) { // 存在数据异常 - mapDataBuildResult.getErrMsgList().forEach(errMsg -> log.warn(String.format("地图数据异常:%s", errMsg))); - simulation.setMapDataError(true); - simulation.addDataErrMsgs(mapDataBuildResult.getErrMsgList()); - } - // 加载运行图 - checkAndLoadRunPlan(simulation, buildParams.getRunPlan()); - // 加载派班计划 - checkAndLoadSchedulingPlan(simulation, buildParams.getSchedulingPlan()); - return simulation; - } - - private static void buildIbpData(SimulationDeviceBuildResult mapDataBuildResult, List ibpList) { - if (CollectionUtils.isEmpty(ibpList)) - return; - Map deviceMap = mapDataBuildResult.getDeviceMap(); - Map vrDeviceMap = mapDataBuildResult.getVrDeviceMap(); - Map ibpMap = ibpList.stream().collect(Collectors.toMap(Ibp::getStationCode, Function.identity())); - List collect = deviceMap.values().stream() - .filter(element -> MapElement.DeviceType.STATION.equals(element.getDeviceType())) - .map(element -> (Station) element).collect(Collectors.toList()); - collect.forEach(station -> { - //构建添加IBP - Ibp ibp = ibpMap.get(station.getCode()); - if (ibp == null) - ibp = ibpMap.get(null); - if (ibp != null) { - IbpData ibpData = JsonUtils.read(ibp.getData(), IbpData.class); - VirtualRealityIbp vrIbp = new VirtualRealityIbp(station.getCode() + "_IBP", station.getName() + "_IBP", ibpData, station); - station.setVrIbp(vrIbp); - deviceMap.put(vrIbp.getCode(), vrIbp); - vrDeviceMap.put(vrIbp.getCode(), vrIbp); - } - }); - } - - private static boolean isOverlapSettingByTrigger(Map deviceMap) { - for (MapElement mapElement : deviceMap.values()) { - if (mapElement.getDeviceType().equals(MapElement.DeviceType.OVERLAP)) { - if (!CollectionUtils.isEmpty(((RouteOverlap) mapElement).getTriggerPathList())) { - return true; - } else { - return false; - } - } - } - return false; - } - - /** - * 检查并加载派班计划 - * @param simulation - * @param schedulingPlan - */ - public static void checkAndLoadSchedulingPlan(Simulation simulation, SchedulingPlanNewVO schedulingPlan) { - if (simulation.isMapDataError() || simulation.isPlanDataError()) { - return; - } - if (Objects.isNull(schedulingPlan)) { - // 如果没有加载计划,生成默认的加载计划 - if (!simulation.isMapDataError() && simulation.isPlanLoaded() && !simulation.isPlanDataError()) { // 地图数据和运行计划加载成功的情况下 - log.info(String.format("地图[%s(%s)]没有派班计划,生成默认派班计划使用", - simulation.getBuildParams().getMap().getName(), - simulation.getBuildParams().getMap().getId())); - SchedulingBuilder.generateSchedulingPlan(simulation); - } - } else { - SchedulingBuilder.loadSchedulingPlan(simulation, schedulingPlan); - } - } - - /** - * 检查并加载运行计划 - * @param simulation - * @param runPlan - * @return - */ - public static void checkAndLoadRunPlan(Simulation simulation, RunPlanVO runPlan) { - if (simulation.isMapDataError()) { - // 地图逻辑数据有问题,不加载 - log.info(String.format("仿真地图[%s(%s)]数据有问题,不执行运行计划加载", - simulation.getBuildParams().getMap().getName(), - simulation.getBuildParams().getMap().getId())); - return; - } - if (Objects.nonNull(runPlan)) { - RunPlanBuilder.RunPlanBuildResult runPlanBuildResult = - RunPlanBuilder.buildRunDiagram(simulation.getRepository().getDeviceMap(), runPlan); - simulation.setPlanLoaded(true); - if (!CollectionUtils.isEmpty(runPlanBuildResult.getErrMsgList())) { // 数据异常 - runPlanBuildResult.getErrMsgList().forEach(errMsg -> log.warn(String.format("运行图数据异常:%s", errMsg))); - simulation.setPlanDataError(true); - simulation.addDataErrMsgs(runPlanBuildResult.getErrMsgList()); - } else { - simulation.getRepository().setServiceTripsMap(runPlanBuildResult.getServerTripMap()); - simulation.getRepository().setStandTripMap(runPlanBuildResult.getStandTripMap()); - simulation.getRepository().setEndTripMap(runPlanBuildResult.getEndTripMap()); - // 校验运行计划和路径单元 - List errMsgList = checkRunPlanAndBuildLostRoutePaths(runPlanBuildResult.getServerTripMap(), - simulation.getRepository().getRoutePathMap()); - if (!errMsgList.isEmpty()) { - simulation.setMapDataError(true); - simulation.addDataErrMsgs(errMsgList); - } -// // 构建终端发车计划 -// TerminalPlanBuildResult terminalPlanBuildResult = buildTerminalPlan(simulation.getRepository(), runPlanBuildResult.getServerTripMap()); -// if (!CollectionUtils.isEmpty(terminalPlanBuildResult.getErrMsgList())) { -// simulation.setMapDataError(true); -// simulation.addDataErrMsgs(terminalPlanBuildResult.getErrMsgList()); -// } else { -// simulation.getRepository().setTerminalDeparturePlanMap(terminalPlanBuildResult.getTerminalPlanMap()); -// } - } - } else { - simulation.addDataErrMsg("运行图为空"); - } - } - - public static List checkRunPlanAndBuildLostRoutePaths(Map> serverTripMap, - Map> routePathMap) { - Map errMsgMap = new HashMap<>(); - for (List tripPlanList : serverTripMap.values()) { - for (TripPlan tripPlan : tripPlanList) { - List
allViaSectionList = tripPlan.getAllViaStoppedSectionList(); - for (int i = 1; i < allViaSectionList.size(); i++) { - Section start = allViaSectionList.get(i - 1); - Section end = allViaSectionList.get(i); - String key = RoutePath.buildKey(start, end); - if (!routePathMap.containsKey(key)) { - // 路径不存在,尝试构建 - List routePaths = CalculateService.queryRoutePathsOnDirection(start, end, tripPlan.isRight(), 10); - if (CollectionUtils.isEmpty(routePaths)) { - // 计划方向路径未找到,反向尝试 - routePaths = CalculateService.queryRoutePathsOnDirection(start, end, !tripPlan.isRight(), 10); - } - if (CollectionUtils.isEmpty(routePaths)) { - // 依然未找到 - errMsgMap.put(key, String.format("从[%s]->[%s]无法到达,请检查运行图和联锁数据是否正确", - start.debugStr(), end.debugStr())); - } else { - // 找到,保存 - log.info(String.format("运行图从[%s]->[%s]没有站间运行数据,根据路径查询找到并生成默认的路径单元", - start.debugStr(), end.debugStr())); - for (RoutePath routePath : routePaths) { - routePath.calculateDistance(); - } - routePathMap.put(key, routePaths); - } - } - } - } - } - return new ArrayList<>(errMsgMap.values()); - } - -// private static List checkRunPlanAndBuildLostRouteUnit(Map> serverTripMap, -// Map routeUnitMap) { -// Map errMsgMap = new HashMap<>(); -// for (List tripPlanList : serverTripMap.values()) { -// for (TripPlan tripPlan : tripPlanList) { -// List
allViaSectionList = tripPlan.getAllViaSectionList(); -// for (int i = 1; i < allViaSectionList.size(); i++) { -// Section start = allViaSectionList.get(i - 1); -// Section end = allViaSectionList.get(i); -// String key = RouteUnit.buildKey(start, end); -// if (!routeUnitMap.containsKey(key)) { -// // 尝试构建 -// List errList = new ArrayList<>(); -// RouteUnit routeUnit = InterlockBuilder2.findAndBuildRouteUnit(start, end, tripPlan.isRight(), errList); -// if (Objects.isNull(routeUnit)) { -// // 反向再尝试 -// routeUnit = InterlockBuilder2.findAndBuildRouteUnit(start, end, !tripPlan.isRight(), errList); -// } -// if (Objects.nonNull(routeUnit)) { -// log.warn(String.format("运行图从[%s(%s)]到[%s(%s)]没有站间运行数据,根据路径查询找到并生成默认的路径单元", -// start.getName(), start.getCode(), end.getName(), end.getCode())); -// routeUnitMap.put(key, routeUnit); -// } else { -// errMsgMap.put(key, String.format("从[%s(%s)]到[%s(%s)]无法到达,请检查运行图和联锁数据是否正确", -// start.getName(), start.getCode(), end.getName(), end.getCode())); -// } -// } -// } -// } -// } -// return new ArrayList<>(errMsgMap.values()); -// } - - private static TerminalPlanBuildResult buildTerminalPlan(SimulationDataRepository repository, Map> serverTripMap) { - TerminalPlanBuildResult result = new TerminalPlanBuildResult(); - List errMsgList = result.getErrMsgList(); - Map terminalPlanMap = result.getTerminalPlanMap(); - serverTripMap.values().forEach(tripPlanList -> - tripPlanList.forEach(tripPlan -> { - Section startSection = tripPlan.getStartSection(); - TerminalDeparturePlan terminalPlan = terminalPlanMap.get(startSection.getCode()); - if (Objects.isNull(terminalPlan)) { - terminalPlan = new TerminalDeparturePlan(startSection.getCode()); - terminalPlanMap.put(startSection.getCode(), terminalPlan); - } - terminalPlan.addTripPlan(tripPlan); - })); - terminalPlanMap.values().forEach(terminalDeparturePlan -> - terminalDeparturePlan.getPlanList().sort((plan1, plan2) -> { - return plan1.getStartTime().compareTo(plan2.getStartTime()); - })); - return result; - } - - public static MapConfig buildConfig(RealLineConfigVO configVO) { - MapConfig mapConfig = new MapConfig(); - if (Objects.nonNull(configVO)) { - mapConfig.copyConfigBy(configVO); - } - return mapConfig; - } - - /** - * 地图基础数据检查和构建 - * @param map - * @return - */ - public static SimulationDeviceBuildResult checkAndBuildBasicMapData(MapVO map) { - SimulationDeviceBuildResult mapDataBuildResult = new SimulationDeviceBuildResult(); - MapDeviceBuilder.checkAndBuildMapDeviceData(map.getGraphDataNew(), mapDataBuildResult); - return mapDataBuildResult; - } - - /** - * 地图数据逻辑检查和构建 - * - * @param map - * @return - */ - public static SimulationDeviceBuildResult checkAndBuildMapData(MapVO map) { - SimulationDeviceBuildResult mapDataBuildResult = new SimulationDeviceBuildResult(); - MapDeviceBuilder.checkAndBuildMapDeviceData(map.getGraphDataNew(), mapDataBuildResult); - if (CollectionUtils.isEmpty(mapDataBuildResult.getErrMsgList())) { // 基础数据没有问题,再构建逻辑数据 -// InterlockBuilder.checkAndBuildMapCILogicData(map.getLogicDataNew(), mapDataBuildResult); - InterlockBuilder2.checkAndBuildMapCILogicData(map.getLogicDataNew(), mapDataBuildResult); - List parkingTimeList = map.getLogicDataNew().getParkingTimeList(); - if (CollectionUtils.isEmpty(parkingTimeList)) { - mapDataBuildResult.errMsgList.add("无停站时间数据"); - } - } - return mapDataBuildResult; - } - - public static SimulationDeviceBuildResult checkAndBuildMapDeviceData(MapVO map) { - SimulationDeviceBuildResult mapDataBuildResult = new SimulationDeviceBuildResult(); - MapDeviceBuilder.checkAndBuildMapDeviceData(map.getGraphDataNew(), mapDataBuildResult); - return mapDataBuildResult; - } - - @Getter - public static class TerminalPlanBuildResult { - private Map terminalPlanMap; - - private List errMsgList; - - public TerminalPlanBuildResult() { - this.terminalPlanMap = new HashMap<>(); - this.errMsgList = new ArrayList<>(); - } - } - - /** - * 地图数据构建结果 - */ - @Getter - public static class SimulationDeviceBuildResult { - /** - * 地图设备map - * key-设备code - * val-设备对象 - */ - private Map deviceMap; - - /** - * 虚拟真实设备map - * key-设备code - * val-虚拟真实设备对象 - */ - private Map vrDeviceMap; - - /** - * 目的地码定义map - * key-目的地码code - */ - private Map destinationMap = new HashMap<>(); - - /** - * 交路列表 - */ - @Setter - private List routingList; - - /** - * 站间运行等级列表 - */ - @Setter - private List runLevelList; - -// /** -// * 路径单元map -// */ -// private Map routeUnitMap; - - /** - * 路径map - */ - private Map> routePathMap; - - /** - * 接触网map - * key-sectionCode - */ - private Map> catenaryMap = new HashMap<>(); - - private Map> sectionRespondersMap; - - /** 默认停站时间map */ - private Map parkTimeMap = new HashMap<>(); - - @Setter - Map> sectionArriveNearMap; - - Map> parkingTracksMap = new HashMap<>(); - - /** - * 数据错误信息列表 - */ - private List errMsgList; - - public SimulationDeviceBuildResult() { - this.deviceMap = new HashMap<>(); - this.vrDeviceMap = new HashMap<>(); -// this.routeUnitMap = new HashMap<>(); - this.routePathMap = new HashMap<>(); - this.sectionRespondersMap = new HashMap<>(); - this.errMsgList = new ArrayList<>(); - } - } -} +package club.joylink.rtss.simulation.cbtc.build; + +import club.joylink.rtss.entity.Ibp; +import club.joylink.rtss.simulation.cbtc.Simulation; +import club.joylink.rtss.simulation.cbtc.data.CalculateService; +import club.joylink.rtss.simulation.cbtc.data.SimulationDataRepository; +import club.joylink.rtss.simulation.cbtc.data.map.*; +import club.joylink.rtss.simulation.cbtc.data.plan.TerminalDeparturePlan; +import club.joylink.rtss.simulation.cbtc.data.plan.TripPlan; +import club.joylink.rtss.simulation.cbtc.data.support.RoutePath; +import club.joylink.rtss.simulation.cbtc.data.vr.VirtualRealityDevice; +import club.joylink.rtss.simulation.cbtc.data.vr.VirtualRealityIbp; +import club.joylink.rtss.util.JsonUtils; +import club.joylink.rtss.vo.client.ibp.IbpData; +import club.joylink.rtss.vo.client.runplan.RunPlanVO; +import club.joylink.rtss.vo.client.schedulingNew.SchedulingPlanNewVO; +import club.joylink.rtss.vo.map.logic.MapStationParkingTimeVO; +import club.joylink.rtss.vo.map.MapVO; +import club.joylink.rtss.vo.map.RealLineConfigVO; +import lombok.Getter; +import lombok.Setter; +import lombok.extern.slf4j.Slf4j; +import org.springframework.util.CollectionUtils; +import java.util.*; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.Function; +import java.util.stream.Collectors; + +@Slf4j +public class SimulationBuilder { + + /** + * 构造仿真对象 + */ + public static Simulation build(String group, SimulationBuildParams buildParams) { + Simulation simulation = new Simulation(group); + simulation.setBuildParams(buildParams); + if (Objects.nonNull(buildParams.getLoginUserInfo())) { + simulation.setProject(buildParams.getLoginUserInfo().getProject()); + } + // 线路配置参数 + simulation.getRepository().setConfig(buildConfig(buildParams.getMap().getConfigVO())); + simulation.getRepository().getConfig() + .setRouteLikeHa1(buildParams.getMap().getGraphDataNew().getGenerateConfig().isLikeHa1()); + simulation.getRepository().getConfig() + .setOverlapSettingByTrigger(buildParams.getMap().getGraphDataNew().getGenerateConfig().isOverlapSettingByTrigger()); + simulation.getRepository().getConfig() + .setSharingECStations(buildParams.getMap().getGraphDataNew().getGenerateConfig().getSharingECStations()); + simulation.getRepository().getConfig() + .setHandleDepot(buildParams.getMap().getGraphDataNew().getGenerateConfig().isHandleDepot()); + // 地图数据构建 + SimulationDeviceBuildResult mapDataBuildResult = checkAndBuildMapData(buildParams.getMap()); + // ibp数据构建 + buildIbpData(mapDataBuildResult, buildParams.getMap().getIbpList()); + simulation.getRepository().setDeviceMap(mapDataBuildResult.getDeviceMap()); + simulation.getRepository().setSectionArriveNearMap(mapDataBuildResult.sectionArriveNearMap); + simulation.getRepository().setVrDeviceMap(mapDataBuildResult.getVrDeviceMap()); +// simulation.getRepository().setRouteUnitMap(mapDataBuildResult.getRouteUnitMap()); + simulation.getRepository().setRoutePathMap(mapDataBuildResult.getRoutePathMap()); + simulation.getRepository().setDestinationMap(mapDataBuildResult.getDestinationMap()); + simulation.getRepository().setRoutingList(mapDataBuildResult.getRoutingList()); +// simulation.getRepository().setRunLevelList(mapDataBuildResult.getRunLevelList()); + simulation.getRepository().getCatenaryMap().putAll(mapDataBuildResult.getCatenaryMap()); + simulation.getRepository().getSectionRespondersMap().putAll(mapDataBuildResult.getSectionRespondersMap()); + simulation.getRepository().setParkingTracksMap(mapDataBuildResult.getParkingTracksMap()); +// simulation.getRepository().setParkTimeMap(mapDataBuildResult.getParkTimeMap()); + UserConfigDataBuilder.buildRunLevel(simulation.getRepository(), buildParams.getUserRunLevelList(), + buildParams.getMap(), mapDataBuildResult.getErrMsgList()); + UserConfigDataBuilder.buildParkTime(simulation.getRepository(), buildParams.getUserParkTimeList(), + buildParams.getMap(), mapDataBuildResult.getErrMsgList()); + if (!CollectionUtils.isEmpty(mapDataBuildResult.getErrMsgList())) { // 存在数据异常 + mapDataBuildResult.getErrMsgList().forEach(errMsg -> log.warn(String.format("地图数据异常:%s", errMsg))); + simulation.setMapDataError(true); + simulation.addDataErrMsgs(mapDataBuildResult.getErrMsgList()); + } + // 加载运行图 + checkAndLoadRunPlan(simulation, buildParams.getRunPlan()); + // 加载派班计划 + checkAndLoadSchedulingPlan(simulation, buildParams.getSchedulingPlan()); + // 加载车辆段route path + loadDepotInOutRoutePath(simulation); + return simulation; + } + + /** + * 加载进出depot的route path + */ + private static void loadDepotInOutRoutePath(Simulation simulation) { + // 仿真车辆段站台停车轨列表 + Map> parkingTracksMap = simulation.getRepository().getParkingTracksMap(); + if (CollectionUtils.isEmpty(parkingTracksMap)) { + return; + } + final Map> srps = simulation.getRepository().getRoutePathMap(); + parkingTracksMap.forEach((station, secs) -> { + if (station.isDepot()) {// 车站为车辆段 + List
transferList = station.getTransferList();// 转换轨列表 + if (!CollectionUtils.isEmpty(transferList)) { + transferList.forEach(transSec -> { + // 停车轨到转换轨 + secs.forEach(parkSec -> { + final String rpKey = RoutePath.buildKey(parkSec, transSec); + List nrp = tryFindRoutePathForOutByDirection(parkSec, transSec, 20); + List srp = srps.get(rpKey); + if (null == srp) { + srp = new ArrayList(); + srps.put(rpKey, srp); + } + if (!CollectionUtils.isEmpty(nrp)) { + srp.addAll(nrp); + } + }); + // 转换轨到停车轨 + secs.forEach(parkSec -> { + final String rpKey = RoutePath.buildKey(transSec, parkSec); + List nrp = tryFindRoutePathByDirection(transSec, parkSec, 20); + List srp = srps.get(rpKey); + if (null == srp) { + srp = new ArrayList(); + srps.put(rpKey, srp); + } + if (!CollectionUtils.isEmpty(nrp)) { + srp.addAll(nrp); + } + }); + }); + } else { + log.info("仿真数据有问题,车辆段[{}]没有转换轨", station.getName()); + } + } + }); + } + + /** + * 当方向未知时,起点终点不变,不同方向搜索route path + */ + private static List tryFindRoutePathForOutByDirection(Section start, Section end, int iterTimes) { + List r = tryFindRoutePathByDirection(start, end, iterTimes); + if (r.size() == 2) { + return r.stream().sorted((RoutePath r1, RoutePath r2) -> { + return r1.getSignalList().size() - r2.getSignalList().size(); + }).findFirst().stream().collect(Collectors.toList()); + + } else if (r.size() > 2) { + log.warn("获取车辆段从停车轨到转换轨的路径, routeKey = {} , 路径数量大于2异常 !!!"); + } + return r; + } + + /** + * 当方向未知时,起点终点不变,不同方向搜索route path + */ + private static List tryFindRoutePathByDirection(Section start, Section end, int iterTimes) { + List r = CalculateService.queryRoutePathsOnDirection(start, end, true, iterTimes); + if (!CollectionUtils.isEmpty(r)) { + return r; + } else { + return CalculateService.queryRoutePathsOnDirection(start, end, false, iterTimes); + } + } + private static void buildIbpData(SimulationDeviceBuildResult mapDataBuildResult, List ibpList) { + if (CollectionUtils.isEmpty(ibpList)) + return; + Map deviceMap = mapDataBuildResult.getDeviceMap(); + Map vrDeviceMap = mapDataBuildResult.getVrDeviceMap(); + Map ibpMap = ibpList.stream().collect(Collectors.toMap(Ibp::getStationCode, Function.identity())); + List collect = deviceMap.values().stream() + .filter(element -> MapElement.DeviceType.STATION.equals(element.getDeviceType())) + .map(element -> (Station) element).collect(Collectors.toList()); + collect.forEach(station -> { + //构建添加IBP + Ibp ibp = ibpMap.get(station.getCode()); + if (ibp == null) + ibp = ibpMap.get(null); + if (ibp != null) { + IbpData ibpData = JsonUtils.read(ibp.getData(), IbpData.class); + VirtualRealityIbp vrIbp = new VirtualRealityIbp(station.getCode() + "_IBP", station.getName() + "_IBP", ibpData, station); + station.setVrIbp(vrIbp); + deviceMap.put(vrIbp.getCode(), vrIbp); + vrDeviceMap.put(vrIbp.getCode(), vrIbp); + } + }); + } + + private static boolean isOverlapSettingByTrigger(Map deviceMap) { + for (MapElement mapElement : deviceMap.values()) { + if (mapElement.getDeviceType().equals(MapElement.DeviceType.OVERLAP)) { + if (!CollectionUtils.isEmpty(((RouteOverlap) mapElement).getTriggerPathList())) { + return true; + } else { + return false; + } + } + } + return false; + } + + /** + * 检查并加载派班计划 + * @param simulation + * @param schedulingPlan + */ + public static void checkAndLoadSchedulingPlan(Simulation simulation, SchedulingPlanNewVO schedulingPlan) { + if (simulation.isMapDataError() || simulation.isPlanDataError()) { + return; + } + if (Objects.isNull(schedulingPlan)) { + // 如果没有加载计划,生成默认的加载计划 + if (!simulation.isMapDataError() && simulation.isPlanLoaded() && !simulation.isPlanDataError()) { // 地图数据和运行计划加载成功的情况下 + log.info(String.format("地图[%s(%s)]没有派班计划,生成默认派班计划使用", + simulation.getBuildParams().getMap().getName(), + simulation.getBuildParams().getMap().getId())); + SchedulingBuilder.generateSchedulingPlan(simulation); + } + } else { + SchedulingBuilder.loadSchedulingPlan(simulation, schedulingPlan); + } + } + + /** + * 检查并加载运行计划 + * @param simulation + * @param runPlan + * @return + */ + public static void checkAndLoadRunPlan(Simulation simulation, RunPlanVO runPlan) { + if (simulation.isMapDataError()) { + // 地图逻辑数据有问题,不加载 + log.info(String.format("仿真地图[%s(%s)]数据有问题,不执行运行计划加载", + simulation.getBuildParams().getMap().getName(), + simulation.getBuildParams().getMap().getId())); + return; + } + if (Objects.nonNull(runPlan)) { + RunPlanBuilder.RunPlanBuildResult runPlanBuildResult = + RunPlanBuilder.buildRunDiagram(simulation.getRepository().getDeviceMap(), runPlan); + simulation.setPlanLoaded(true); + if (!CollectionUtils.isEmpty(runPlanBuildResult.getErrMsgList())) { // 数据异常 + runPlanBuildResult.getErrMsgList().forEach(errMsg -> log.warn(String.format("运行图数据异常:%s", errMsg))); + simulation.setPlanDataError(true); + simulation.addDataErrMsgs(runPlanBuildResult.getErrMsgList()); + } else { + simulation.getRepository().setServiceTripsMap(runPlanBuildResult.getServerTripMap()); + simulation.getRepository().setStandTripMap(runPlanBuildResult.getStandTripMap()); + simulation.getRepository().setEndTripMap(runPlanBuildResult.getEndTripMap()); + // 校验运行计划和路径单元 + List errMsgList = checkRunPlanAndBuildLostRoutePaths(runPlanBuildResult.getServerTripMap(), + simulation.getRepository().getRoutePathMap()); + if (!errMsgList.isEmpty()) { + simulation.setMapDataError(true); + simulation.addDataErrMsgs(errMsgList); + } +// // 构建终端发车计划 +// TerminalPlanBuildResult terminalPlanBuildResult = buildTerminalPlan(simulation.getRepository(), runPlanBuildResult.getServerTripMap()); +// if (!CollectionUtils.isEmpty(terminalPlanBuildResult.getErrMsgList())) { +// simulation.setMapDataError(true); +// simulation.addDataErrMsgs(terminalPlanBuildResult.getErrMsgList()); +// } else { +// simulation.getRepository().setTerminalDeparturePlanMap(terminalPlanBuildResult.getTerminalPlanMap()); +// } + } + } else { + simulation.addDataErrMsg("运行图为空"); + } + } + + public static List checkRunPlanAndBuildLostRoutePaths(Map> serverTripMap, + Map> routePathMap) { + Map errMsgMap = new HashMap<>(); + for (List tripPlanList : serverTripMap.values()) { + for (TripPlan tripPlan : tripPlanList) { + List
allViaSectionList = tripPlan.getAllViaStoppedSectionList(); + for (int i = 1; i < allViaSectionList.size(); i++) { + Section start = allViaSectionList.get(i - 1); + Section end = allViaSectionList.get(i); + String key = RoutePath.buildKey(start, end); + if (!routePathMap.containsKey(key)) { + // 路径不存在,尝试构建 + List routePaths = CalculateService.queryRoutePathsOnDirection(start, end, tripPlan.isRight(), 10); + if (CollectionUtils.isEmpty(routePaths)) { + // 计划方向路径未找到,反向尝试 + routePaths = CalculateService.queryRoutePathsOnDirection(start, end, !tripPlan.isRight(), 10); + } + if (CollectionUtils.isEmpty(routePaths)) { + // 依然未找到 + errMsgMap.put(key, String.format("从[%s]->[%s]无法到达,请检查运行图和联锁数据是否正确", + start.debugStr(), end.debugStr())); + } else { + // 找到,保存 + log.info(String.format("运行图从[%s]->[%s]没有站间运行数据,根据路径查询找到并生成默认的路径单元", + start.debugStr(), end.debugStr())); + for (RoutePath routePath : routePaths) { + routePath.calculateDistance(); + } + routePathMap.put(key, routePaths); + } + } + } + } + } + return new ArrayList<>(errMsgMap.values()); + } + +// private static List checkRunPlanAndBuildLostRouteUnit(Map> serverTripMap, +// Map routeUnitMap) { +// Map errMsgMap = new HashMap<>(); +// for (List tripPlanList : serverTripMap.values()) { +// for (TripPlan tripPlan : tripPlanList) { +// List
allViaSectionList = tripPlan.getAllViaSectionList(); +// for (int i = 1; i < allViaSectionList.size(); i++) { +// Section start = allViaSectionList.get(i - 1); +// Section end = allViaSectionList.get(i); +// String key = RouteUnit.buildKey(start, end); +// if (!routeUnitMap.containsKey(key)) { +// // 尝试构建 +// List errList = new ArrayList<>(); +// RouteUnit routeUnit = InterlockBuilder2.findAndBuildRouteUnit(start, end, tripPlan.isRight(), errList); +// if (Objects.isNull(routeUnit)) { +// // 反向再尝试 +// routeUnit = InterlockBuilder2.findAndBuildRouteUnit(start, end, !tripPlan.isRight(), errList); +// } +// if (Objects.nonNull(routeUnit)) { +// log.warn(String.format("运行图从[%s(%s)]到[%s(%s)]没有站间运行数据,根据路径查询找到并生成默认的路径单元", +// start.getName(), start.getCode(), end.getName(), end.getCode())); +// routeUnitMap.put(key, routeUnit); +// } else { +// errMsgMap.put(key, String.format("从[%s(%s)]到[%s(%s)]无法到达,请检查运行图和联锁数据是否正确", +// start.getName(), start.getCode(), end.getName(), end.getCode())); +// } +// } +// } +// } +// } +// return new ArrayList<>(errMsgMap.values()); +// } + + private static TerminalPlanBuildResult buildTerminalPlan(SimulationDataRepository repository, Map> serverTripMap) { + TerminalPlanBuildResult result = new TerminalPlanBuildResult(); + List errMsgList = result.getErrMsgList(); + Map terminalPlanMap = result.getTerminalPlanMap(); + serverTripMap.values().forEach(tripPlanList -> + tripPlanList.forEach(tripPlan -> { + Section startSection = tripPlan.getStartSection(); + TerminalDeparturePlan terminalPlan = terminalPlanMap.get(startSection.getCode()); + if (Objects.isNull(terminalPlan)) { + terminalPlan = new TerminalDeparturePlan(startSection.getCode()); + terminalPlanMap.put(startSection.getCode(), terminalPlan); + } + terminalPlan.addTripPlan(tripPlan); + })); + terminalPlanMap.values().forEach(terminalDeparturePlan -> + terminalDeparturePlan.getPlanList().sort((plan1, plan2) -> { + return plan1.getStartTime().compareTo(plan2.getStartTime()); + })); + return result; + } + + public static MapConfig buildConfig(RealLineConfigVO configVO) { + MapConfig mapConfig = new MapConfig(); + if (Objects.nonNull(configVO)) { + mapConfig.copyConfigBy(configVO); + } + return mapConfig; + } + + /** + * 地图基础数据检查和构建 + * @param map + * @return + */ + public static SimulationDeviceBuildResult checkAndBuildBasicMapData(MapVO map) { + SimulationDeviceBuildResult mapDataBuildResult = new SimulationDeviceBuildResult(); + MapDeviceBuilder.checkAndBuildMapDeviceData(map.getGraphDataNew(), mapDataBuildResult); + return mapDataBuildResult; + } + + /** + * 地图数据逻辑检查和构建 + * + * @param map + * @return + */ + public static SimulationDeviceBuildResult checkAndBuildMapData(MapVO map) { + SimulationDeviceBuildResult mapDataBuildResult = new SimulationDeviceBuildResult(); + MapDeviceBuilder.checkAndBuildMapDeviceData(map.getGraphDataNew(), mapDataBuildResult); + if (CollectionUtils.isEmpty(mapDataBuildResult.getErrMsgList())) { // 基础数据没有问题,再构建逻辑数据 +// InterlockBuilder.checkAndBuildMapCILogicData(map.getLogicDataNew(), mapDataBuildResult); + InterlockBuilder2.checkAndBuildMapCILogicData(map.getLogicDataNew(), mapDataBuildResult); + List parkingTimeList = map.getLogicDataNew().getParkingTimeList(); + if (CollectionUtils.isEmpty(parkingTimeList)) { + mapDataBuildResult.errMsgList.add("无停站时间数据"); + } + } + return mapDataBuildResult; + } + + public static SimulationDeviceBuildResult checkAndBuildMapDeviceData(MapVO map) { + SimulationDeviceBuildResult mapDataBuildResult = new SimulationDeviceBuildResult(); + MapDeviceBuilder.checkAndBuildMapDeviceData(map.getGraphDataNew(), mapDataBuildResult); + return mapDataBuildResult; + } + + @Getter + public static class TerminalPlanBuildResult { + private Map terminalPlanMap; + + private List errMsgList; + + public TerminalPlanBuildResult() { + this.terminalPlanMap = new HashMap<>(); + this.errMsgList = new ArrayList<>(); + } + } + + /** + * 地图数据构建结果 + */ + @Getter + public static class SimulationDeviceBuildResult { + /** + * 地图设备map + * key-设备code + * val-设备对象 + */ + private Map deviceMap; + + /** + * 虚拟真实设备map + * key-设备code + * val-虚拟真实设备对象 + */ + private Map vrDeviceMap; + + /** + * 目的地码定义map + * key-目的地码code + */ + private Map destinationMap = new HashMap<>(); + + /** + * 交路列表 + */ + @Setter + private List routingList; + + /** + * 站间运行等级列表 + */ + @Setter + private List runLevelList; + +// /** +// * 路径单元map +// */ +// private Map routeUnitMap; + + /** + * 路径map + */ + private Map> routePathMap; + + /** + * 接触网map + * key-sectionCode + */ + private Map> catenaryMap = new HashMap<>(); + + private Map> sectionRespondersMap; + + /** 默认停站时间map */ + private Map parkTimeMap = new HashMap<>(); + + @Setter + Map> sectionArriveNearMap; + + Map> parkingTracksMap = new HashMap<>(); + + /** + * 数据错误信息列表 + */ + private List errMsgList; + + public SimulationDeviceBuildResult() { + this.deviceMap = new HashMap<>(); + this.vrDeviceMap = new HashMap<>(); +// this.routeUnitMap = new HashMap<>(); + this.routePathMap = new HashMap<>(); + this.sectionRespondersMap = new HashMap<>(); + this.errMsgList = new ArrayList<>(); + } + } +} diff --git a/src/main/java/club/joylink/rtss/simulation/cbtc/constant/SimulationConstants.java b/src/main/java/club/joylink/rtss/simulation/cbtc/constant/SimulationConstants.java index b51987081..c7d5a4a77 100644 --- a/src/main/java/club/joylink/rtss/simulation/cbtc/constant/SimulationConstants.java +++ b/src/main/java/club/joylink/rtss/simulation/cbtc/constant/SimulationConstants.java @@ -105,6 +105,9 @@ public interface SimulationConstants { */ int ROUTE_SETTING_TIMEOUT = 20; + /** 停车场/车辆段循环逻辑频率(单位ms) */ + int DEPOT_LOOP_RATE = 1000; + /** * 获取仿真运行计划日期(运营日) * @return diff --git a/src/main/java/club/joylink/rtss/simulation/cbtc/constant/SimulationModule.java b/src/main/java/club/joylink/rtss/simulation/cbtc/constant/SimulationModule.java index ebd81a5bd..fc438e63d 100644 --- a/src/main/java/club/joylink/rtss/simulation/cbtc/constant/SimulationModule.java +++ b/src/main/java/club/joylink/rtss/simulation/cbtc/constant/SimulationModule.java @@ -43,6 +43,8 @@ public enum SimulationModule { DRIVE_POSITION(SimulationConstants.TRAIN_DRIVE_POSITION_SYNC_RATE), /** 剧本演出模块 */ SCRIPT(SimulationConstants.SCRIPT_LOOP_RATE), + /** 停车场/车辆段模块 */ + DEPOT(SimulationConstants.DEPOT_LOOP_RATE), /** 故障模块 */ FAULT(SimulationConstants.FAULT_GENERATE_RATE), diff --git a/src/main/java/club/joylink/rtss/simulation/cbtc/data/SimulationDataRepository.java b/src/main/java/club/joylink/rtss/simulation/cbtc/data/SimulationDataRepository.java index 395769321..7a23174ed 100644 --- a/src/main/java/club/joylink/rtss/simulation/cbtc/data/SimulationDataRepository.java +++ b/src/main/java/club/joylink/rtss/simulation/cbtc/data/SimulationDataRepository.java @@ -2,6 +2,7 @@ package club.joylink.rtss.simulation.cbtc.data; import club.joylink.rtss.exception.BusinessExceptionAssertEnum; import club.joylink.rtss.simulation.cbtc.ATS.data.AtsAlarm; +import club.joylink.rtss.simulation.cbtc.Simulation; import club.joylink.rtss.simulation.cbtc.communication.vo.TrainHmiDisplay; import club.joylink.rtss.simulation.cbtc.data.map.*; import club.joylink.rtss.simulation.cbtc.data.plan.RealRun; @@ -226,6 +227,10 @@ public class SimulationDataRepository { */ private Map> parkingTracksMap = new HashMap<>(); + private List outboundPlanList = new ArrayList<>(); + + private List inboundPlanList = new ArrayList<>(); + /** * 间隔时间/s */ @@ -586,12 +591,13 @@ public class SimulationDataRepository { return this.serviceTripsMap.get(serviceNumber); } - public VirtualRealityTrain getTrain(String serviceNumber, String tripNumber) { + public VirtualRealityTrain getTrain(Simulation simulation, String serviceNumber, String tripNumber) { VirtualRealityTrain train = this.queryTrain(serviceNumber, tripNumber); if (Objects.isNull(train)) { throw new SimulationException(SimulationExceptionType.System_Fault, String.format("服务车次[%s|%s]找不到派班的列车", serviceNumber, tripNumber)); - } else if (this.usedTrainMap.containsKey(train.getGroupNumber())) { + } else if (!simulation.getRepository().getConfig().isHandleDepot() + && this.usedTrainMap.containsKey(train.getGroupNumber())) { throw new SimulationException(SimulationExceptionType.System_Fault, String.format("列车[%s]已经被使用", train.getGroupNumber())); } diff --git a/src/main/java/club/joylink/rtss/simulation/cbtc/data/map/Section.java b/src/main/java/club/joylink/rtss/simulation/cbtc/data/map/Section.java index ff1dccae2..10ed5ed9b 100644 --- a/src/main/java/club/joylink/rtss/simulation/cbtc/data/map/Section.java +++ b/src/main/java/club/joylink/rtss/simulation/cbtc/data/map/Section.java @@ -12,10 +12,7 @@ import lombok.Getter; import lombok.Setter; import org.springframework.util.CollectionUtils; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Objects; +import java.util.*; /** * 区段 @@ -165,7 +162,7 @@ public class Section extends DelayUnlockDevice { /** * 所属zc */ - private List zcs = new ArrayList<>(); + private Set zcs = new HashSet<>(); // ------------------状态属性--------------------- @@ -1148,10 +1145,15 @@ public class Section extends DelayUnlockDevice { * 任意一个zc正常工作 */ public boolean anyZcWorking() { - if (!CollectionUtils.isEmpty(zcs)) { - return zcs.stream().anyMatch(zc -> !zc.isFault()); + Section axleCounterSection = this.findAxleCounterSection(); + if (axleCounterSection != null && !CollectionUtils.isEmpty(axleCounterSection.getZcs())) { + return axleCounterSection.getZcs().stream().anyMatch(zc -> !zc.isFault()); } return false; +// if (!CollectionUtils.isEmpty(zcs)) { +// return zcs.stream().anyMatch(zc -> !zc.isFault()); +// } +// return false; } public void setInvalid(boolean invalid) { diff --git a/src/main/java/club/joylink/rtss/simulation/cbtc/data/map/ZC.java b/src/main/java/club/joylink/rtss/simulation/cbtc/data/map/ZC.java index f5d31d790..58f959294 100644 --- a/src/main/java/club/joylink/rtss/simulation/cbtc/data/map/ZC.java +++ b/src/main/java/club/joylink/rtss/simulation/cbtc/data/map/ZC.java @@ -1,11 +1,10 @@ package club.joylink.rtss.simulation.cbtc.data.map; import lombok.Getter; -import lombok.Setter; -import java.util.ArrayList; -import java.util.List; +import java.util.HashSet; import java.util.Objects; +import java.util.Set; /** * 区域控制器 @@ -13,7 +12,7 @@ import java.util.Objects; @Getter public class ZC extends MayOutOfOrderDevice { - private List
sections = new ArrayList<>(); + private Set
sections = new HashSet<>(); public ZC(String code, String name) { super(code, name, DeviceType.ZC); diff --git a/src/main/java/club/joylink/rtss/simulation/cbtc/data/plan/TripPlan.java b/src/main/java/club/joylink/rtss/simulation/cbtc/data/plan/TripPlan.java index 99947c05e..7dfcbc5c7 100644 --- a/src/main/java/club/joylink/rtss/simulation/cbtc/data/plan/TripPlan.java +++ b/src/main/java/club/joylink/rtss/simulation/cbtc/data/plan/TripPlan.java @@ -232,11 +232,20 @@ public class TripPlan { return false; } + /** + * 按计划发车 + */ + public void departure() { + this.departure = true; + if (this.isOutbound()) { + this.dispatched = true; + } + } + /** * 按计划派发 */ - public void dispatch() { - this.departure = true; + public void dispatched() { if (this.isOutbound()) { this.dispatched = true; } diff --git a/src/main/java/club/joylink/rtss/simulation/cbtc/data/vo/TrainInfo.java b/src/main/java/club/joylink/rtss/simulation/cbtc/data/vo/TrainInfo.java index 8f1f5562b..e564cd0e9 100644 --- a/src/main/java/club/joylink/rtss/simulation/cbtc/data/vo/TrainInfo.java +++ b/src/main/java/club/joylink/rtss/simulation/cbtc/data/vo/TrainInfo.java @@ -532,7 +532,7 @@ public class TrainInfo extends MapElement { } public synchronized void applyNewTripPlan(TripPlan tripPlan) { - tripPlan.dispatch(); + tripPlan.departure(); this.serviceNumber = tripPlan.getServiceNumber(); this.tripNumber = tripPlan.getTripNumber(); this.destinationCode = tripPlan.getDestinationCode(); @@ -586,11 +586,22 @@ public class TrainInfo extends MapElement { this.routing = routing; } + /** + * 准备回库(消失) + */ public void finishPlanPrepareInbound() { this.inbound = true; this.deleteRemain = 5 * 1000; } + /** + * 准备进入车辆段 + */ + public void finishPlanPrepareEnterDepot() { + this.inbound = true; + this.deleteRemain = -1; + } + public void updateDeleteRemain(int deleteRemain) { this.deleteRemain = deleteRemain; } diff --git a/src/main/java/club/joylink/rtss/simulation/cbtc/depot/DepotLoadService.java b/src/main/java/club/joylink/rtss/simulation/cbtc/depot/DepotLoadService.java deleted file mode 100644 index 80b7d4990..000000000 --- a/src/main/java/club/joylink/rtss/simulation/cbtc/depot/DepotLoadService.java +++ /dev/null @@ -1,45 +0,0 @@ -package club.joylink.rtss.simulation.cbtc.depot; - -import club.joylink.rtss.simulation.cbtc.Simulation; -import club.joylink.rtss.simulation.cbtc.data.map.Section; -import club.joylink.rtss.simulation.cbtc.data.map.Station; -import club.joylink.rtss.simulation.cbtc.data.support.SectionPosition; -import club.joylink.rtss.simulation.cbtc.data.vo.TrainInfo; -import club.joylink.rtss.simulation.cbtc.data.vr.VirtualRealityTrain; -import org.springframework.stereotype.Component; - -import java.util.Comparator; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.stream.Collectors; - -@Component -public class DepotLoadService { - - public void loadDepotTrain(Simulation simulation) { - if (!simulation.getRepository().getConfig().isHandleDepot()) { - return; - } - Map> parkingTracksMap = simulation.getRepository().getParkingTracksMap(); - simulation.getRepository().getAllVrTrain().stream() - .collect(Collectors.groupingBy(VirtualRealityTrain::getDepotStation)) - .forEach((station, trainList) -> { - List
sections = parkingTracksMap.get(station); - // 先加载内侧的停车轨 - sections.sort(Comparator.comparing(section -> - Objects.isNull(section.getLeftSection()) || Objects.isNull(section.getRightSection()))); - boolean right = sections.get(sections.size() - 1).getLeftSection() == null; - for (int i = 0, trainListSize = trainList.size(); i < trainListSize; i++) { - VirtualRealityTrain train = trainList.get(i); - Section section = sections.get(i); - train.initManualTrain(new SectionPosition(section, section.getStopPointByDirection(right)), right); - train.parkingAt(section); - TrainInfo trainInfo = TrainInfo.constructManualTrain(train); - trainInfo.tracking(train); - simulation.getRepository().addOnlineTrain(train); - simulation.getRepository().addTrainInfo(trainInfo); - } - }); - } -} diff --git a/src/main/java/club/joylink/rtss/simulation/cbtc/depot/DepotService.java b/src/main/java/club/joylink/rtss/simulation/cbtc/depot/DepotService.java new file mode 100644 index 000000000..d260867c1 --- /dev/null +++ b/src/main/java/club/joylink/rtss/simulation/cbtc/depot/DepotService.java @@ -0,0 +1,235 @@ +package club.joylink.rtss.simulation.cbtc.depot; + +import club.joylink.rtss.simulation.cbtc.ATS.tools.TrainOutboundLoadTool; +import club.joylink.rtss.simulation.cbtc.CI.device.CiRouteService; +import club.joylink.rtss.simulation.cbtc.GroupSimulationService; +import club.joylink.rtss.simulation.cbtc.Simulation; +import club.joylink.rtss.simulation.cbtc.command.CommandBO; +import club.joylink.rtss.simulation.cbtc.command.CommandInitiateVO; +import club.joylink.rtss.simulation.cbtc.constant.SimulationConstants; +import club.joylink.rtss.simulation.cbtc.constant.SimulationModule; +import club.joylink.rtss.simulation.cbtc.data.map.Route; +import club.joylink.rtss.simulation.cbtc.data.map.Section; +import club.joylink.rtss.simulation.cbtc.data.map.Signal; +import club.joylink.rtss.simulation.cbtc.data.map.Station; +import club.joylink.rtss.simulation.cbtc.data.plan.SchedulingTrainPlan; +import club.joylink.rtss.simulation.cbtc.data.support.RoutePath; +import club.joylink.rtss.simulation.cbtc.data.support.SectionPosition; +import club.joylink.rtss.simulation.cbtc.data.vo.TrainInfo; +import club.joylink.rtss.simulation.cbtc.data.vr.VirtualRealityTrain; +import club.joylink.rtss.simulation.cbtc.member.SimulationMember; +import club.joylink.rtss.simulation.cbtc.onboard.ATP.ATPService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.time.LocalDateTime; +import java.util.Comparator; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.stream.Collectors; + +@Component +public class DepotService { + + @Autowired + private CiRouteService ciRouteService; + + @Autowired + private TrainOutboundLoadTool trainOutboundLoadTool; + + @Autowired + private GroupSimulationService groupSimulationService; + + @Autowired + private ATPService atpService; + + public void loadDepotTrain(Simulation simulation) { + if (!simulation.getRepository().getConfig().isHandleDepot()) { + return; + } + Map> parkingTracksMap = simulation.getRepository().getParkingTracksMap(); + simulation.getRepository().getAllVrTrain().stream() + .collect(Collectors.groupingBy(VirtualRealityTrain::getDepotStation)) + .forEach((station, trainList) -> { + List
sections = parkingTracksMap.get(station); + // 先加载内侧的停车轨 + sections.sort(Comparator.comparing(section -> + Objects.isNull(section.getLeftSection()) || Objects.isNull(section.getRightSection()))); + boolean right = sections.get(sections.size() - 1).getLeftSection() == null; + for (int i = 0, trainListSize = trainList.size(); i < trainListSize; i++) { + VirtualRealityTrain train = trainList.get(i); + Section section = sections.get(i); + train.initManualTrain(new SectionPosition(section, section.getStopPointByDirection(right)), right); + train.parkingAt(section); + train.initAsRM(); + TrainInfo trainInfo = TrainInfo.constructManualTrain(train); + trainInfo.tracking(train); + simulation.getRepository().addOnlineTrain(train); + simulation.getRepository().addTrainInfo(trainInfo); + } + }); + } + + public void addJobs(Simulation simulation) { + simulation.addJob(SimulationModule.DEPOT.name(), () -> this.run(simulation), SimulationConstants.DEPOT_LOOP_RATE); + } + + private void run(Simulation simulation) { + if (!simulation.isPlanRunning()) { + return; + } + if (!simulation.getRepository().getConfig().isHandleDepot()) { + trainOutboundLoadTool.loadOutboundTrain(simulation); + } else { + timeToDeparture(simulation); + backToParking(simulation); + settingRouteAndMoving(simulation); + arriveDestination(simulation); + } + } + + /** + * 根据时间筛选,从停车轨自动发车 + * @param simulation + */ + private void timeToDeparture(Simulation simulation) { + LocalDateTime systemTime = simulation.getSystemTime(); + for (SchedulingTrainPlan schedulingTrainPlan : simulation.getRepository().getSchedulingTrainPlanList()) { + if (schedulingTrainPlan.getOutDepotTrip().isDispatched()) { + continue; + } + if (schedulingTrainPlan.getOutDepotTrip().getStartTime().minusMinutes(10).isBefore(systemTime.toLocalTime())) { + if (!simulation.getRepository().getOutboundPlanList().contains(schedulingTrainPlan)) { + simulation.getRepository().getOutboundPlanList().add(schedulingTrainPlan); + schedulingTrainPlan.getOutDepotTrip().dispatched(); + } + } + } + } + + /** + * 筛选入库 + * @param simulation + */ + private void backToParking(Simulation simulation) { + for (VirtualRealityTrain train : simulation.getRepository().getOnlineTrainList()) { + if (!train.isParkingAt()) { + continue; + } + Section section = train.getHeadPosition().getSection(); + if (!section.isTransferTrack()) { + continue; + } + for (SchedulingTrainPlan schedulingTrainPlan : simulation.getRepository().getSchedulingTrainPlanList()) { + if (!schedulingTrainPlan.getInDepotTrip().getEndSection().equals(section)) { + continue; + } + if (!train.getGroupNumber().equals(schedulingTrainPlan.getGroupNumber())) { + continue; + } + if (!schedulingTrainPlan.getInDepotTrip().getEndTime().minusMinutes(10) + .isBefore(simulation.getSystemTime().toLocalTime())) { + continue; + } + if (!simulation.getRepository().getInboundPlanList().contains(schedulingTrainPlan)) { + train.initAsRM(); + simulation.getRepository().getInboundPlanList().add(schedulingTrainPlan); + break; + } + } + } + } + + /** + * 列车排进路并运行 + * @param simulation + */ + private void settingRouteAndMoving(Simulation simulation) { + for (SchedulingTrainPlan schedulingTrainPlan : simulation.getRepository().getOutboundPlanList()) { + moving(simulation, schedulingTrainPlan.getGroupNumber(), schedulingTrainPlan.getOutDepotTrip().getStartSection()); + } + for (SchedulingTrainPlan schedulingTrainPlan : simulation.getRepository().getInboundPlanList()) { + Section endSection = schedulingTrainPlan.getInDepotTrip().getEndSection(); + for (Section section : simulation.getRepository().getParkingTracksMap().get(endSection.getStation())) { + if (section.isOccupied()) { + continue; + } + if (section.getLeftSection() == null || section.getRightSection() == null) { + moving(simulation, schedulingTrainPlan.getGroupNumber(), section); + } else if (section.getLeftSection().isParkingTrack() && !section.getLeftSection().isOccupied()) { + moving(simulation, schedulingTrainPlan.getGroupNumber(), section.getLeftSection()); + } else if (section.getRightSection().isParkingTrack() && !section.getRightSection().isOccupied()) { + moving(simulation, schedulingTrainPlan.getGroupNumber(), section.getRightSection()); + } else { + moving(simulation, schedulingTrainPlan.getGroupNumber(), section); + } + break; + } + } + } + + private void moving(Simulation simulation, String groupNumber, Section endSection) { + VirtualRealityTrain train = simulation.getRepository().getVRByCode(groupNumber, VirtualRealityTrain.class); + Section startSection = train.getHeadPosition().getSection(); + List routePaths = simulation.getRepository().queryRoutePaths(startSection, endSection); + if (routePaths == null || routePaths.isEmpty()) { + return; + } + RoutePath routePath = routePaths.get(0); + Section lastSection = routePath.getEnd(); + train.setRobotTargetPosition(new SectionPosition(lastSection, lastSection.getStopPointByDirection(routePath.isRight()))); + for (Signal signal : routePath.getSignalList()) { + for (Route route : signal.getRouteList()) { + if (routePath.getRouteList().contains(route)) { + if (route.isSetting()) { + return; + } + if (route.isLock()) { + break; + } + ciRouteService.setRoute(simulation, route); + return; + } + } + } + } + + /** + * 判断运行列车是否到达转换轨并升级 + * @param simulation + */ + private void arriveDestination(Simulation simulation) { + for (Iterator iterator = simulation.getRepository().getOutboundPlanList().iterator(); iterator.hasNext(); ) { + SchedulingTrainPlan schedulingTrainPlan = iterator.next(); + String groupNumber = schedulingTrainPlan.getGroupNumber(); + VirtualRealityTrain train = simulation.getRepository().getVRByCode(groupNumber, VirtualRealityTrain.class); + if (train.getSpeed() == 0 + && train.getHeadPosition().getSection().equals(schedulingTrainPlan.getOutDepotTrip().getStartSection()) + && train.getTailPosition().getSection().equals(schedulingTrainPlan.getOutDepotTrip().getStartSection())) { + // 到达 + iterator.remove(); + // 升级 + SimulationMember member = simulation.getSimulationMembersByDevice(train).get(0); + Map param = new HashMap<>(); + param.put("preselectionMode", "AM_C"); + CommandInitiateVO commandInitiateVO = new CommandInitiateVO(CommandBO.CommandType.Change_Preselection_Mode, + member.getId(), param); + groupSimulationService.command(simulation, commandInitiateVO, member); + } + } + for (Iterator iterator = simulation.getRepository().getInboundPlanList().iterator(); iterator.hasNext(); ) { + SchedulingTrainPlan schedulingTrainPlan = iterator.next(); + String groupNumber = schedulingTrainPlan.getGroupNumber(); + VirtualRealityTrain train = simulation.getRepository().getVRByCode(groupNumber, VirtualRealityTrain.class); + if (train.getSpeed() == 0 && train.getHeadPosition().getSection().isParkingTrack() + && train.getTailPosition().getSection().isParkingTrack()) { + // 到达 + iterator.remove(); + atpService.turnDirectionImmediately(train); + } + } + } +}