diff --git a/src/main/java/club/joylink/rtss/services/draftData/DraftMapCiDataGeneratorImpl.java b/src/main/java/club/joylink/rtss/services/draftData/DraftMapCiDataGeneratorImpl.java index dafbcda0c..8211f84d3 100644 --- a/src/main/java/club/joylink/rtss/services/draftData/DraftMapCiDataGeneratorImpl.java +++ b/src/main/java/club/joylink/rtss/services/draftData/DraftMapCiDataGeneratorImpl.java @@ -5,7 +5,22 @@ import club.joylink.rtss.simulation.cbtc.build.SimulationBuilder; import club.joylink.rtss.simulation.cbtc.constant.SignalAspect; import club.joylink.rtss.simulation.cbtc.constant.SignalModel; import club.joylink.rtss.simulation.cbtc.data.CalculateService; -import club.joylink.rtss.simulation.cbtc.data.map.*; +import club.joylink.rtss.simulation.cbtc.data.map.AutoSignal; +import club.joylink.rtss.simulation.cbtc.data.map.Cycle; +import club.joylink.rtss.simulation.cbtc.data.map.DestinationCodeDefinition; +import club.joylink.rtss.simulation.cbtc.data.map.ESP; +import club.joylink.rtss.simulation.cbtc.data.map.MapElement; +import club.joylink.rtss.simulation.cbtc.data.map.PSD; +import club.joylink.rtss.simulation.cbtc.data.map.Route; +import club.joylink.rtss.simulation.cbtc.data.map.RouteFls; +import club.joylink.rtss.simulation.cbtc.data.map.RouteOverlap; +import club.joylink.rtss.simulation.cbtc.data.map.Section; +import club.joylink.rtss.simulation.cbtc.data.map.SectionPath; +import club.joylink.rtss.simulation.cbtc.data.map.Signal; +import club.joylink.rtss.simulation.cbtc.data.map.Stand; +import club.joylink.rtss.simulation.cbtc.data.map.Station; +import club.joylink.rtss.simulation.cbtc.data.map.Switch; +import club.joylink.rtss.simulation.cbtc.data.map.SwitchElement; import club.joylink.rtss.simulation.cbtc.data.support.RoutePath; import club.joylink.rtss.simulation.cbtc.exception.SimulationException; import club.joylink.rtss.simulation.cbtc.exception.SimulationExceptionType; @@ -14,7 +29,28 @@ import club.joylink.rtss.vo.map.CiGenerateResultVO; import club.joylink.rtss.vo.map.MapCiGenerateConfig; import club.joylink.rtss.vo.map.MapRoutingSectionNewVO; import club.joylink.rtss.vo.map.MapVO; -import club.joylink.rtss.vo.map.logic.*; +import club.joylink.rtss.vo.map.logic.MapAutoReentryVO; +import club.joylink.rtss.vo.map.logic.MapAutoSignalNewVO; +import club.joylink.rtss.vo.map.logic.MapDestinationCodeDefinitionVO; +import club.joylink.rtss.vo.map.logic.MapOverlapVO; +import club.joylink.rtss.vo.map.logic.MapRouteFlankProtectionNewVO; +import club.joylink.rtss.vo.map.logic.MapRouteNewVO; +import club.joylink.rtss.vo.map.logic.MapRoutingDataVO; +import club.joylink.rtss.vo.map.logic.MapSignalApproachSectionVO; +import club.joylink.rtss.vo.map.logic.MapStationRunLevelVO; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Stack; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.Function; +import java.util.stream.Collectors; import lombok.Getter; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; @@ -23,11 +59,6 @@ import org.springframework.transaction.annotation.Transactional; import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; -import java.util.*; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.function.Function; -import java.util.stream.Collectors; - @Slf4j @Service public class DraftMapCiDataGeneratorImpl implements DraftMapCiDataGenerator { @@ -281,7 +312,7 @@ public class DraftMapCiDataGeneratorImpl implements DraftMapCiDataGenerator { List signalList = deviceMap.values().stream() .filter(mapElement -> mapElement.getDeviceType().equals(MapElement.DeviceType.SIGNAL)) .map(mapElement -> ((Signal) mapElement)) - .filter(signal -> !signal.getInterlockStation().isDepot()) +// .filter(signal -> !signal.getInterlockStation().isDepot()) .collect(Collectors.toList()); // 获取所有道岔 List switchList = deviceMap.values().stream() @@ -318,7 +349,7 @@ public class DraftMapCiDataGeneratorImpl implements DraftMapCiDataGenerator { if (Objects.nonNull(autoSignal)) { autoSignalList.add(autoSignal); } - } else if (signal.isProtectionSignal()) { + } else if (signal.isProtectionSignal() || signal.isShunting2()) { // 防护信号机,生成进路 if (config.isLikeHa1()) { generatedRouteList.addAll(this.generateRouteLikeHa1(signal, routeCodeGenerator, overlapMap, @@ -1450,6 +1481,9 @@ public class DraftMapCiDataGeneratorImpl implements DraftMapCiDataGenerator { case BW: route.setAspect(SignalAspect.W); break; + case YRW: + route.setAspect(SignalAspect.W); + break; default: throw BusinessExceptionAssertEnum.DATA_ERROR.exception(String.format("信号机[%s]型号[%s]不正确", start.debugStr(), start.getSignalModel())); diff --git a/src/main/java/club/joylink/rtss/services/draftData/RoutingGenerator.java b/src/main/java/club/joylink/rtss/services/draftData/RoutingGenerator.java index 9f6676ac8..7feed6ca2 100644 --- a/src/main/java/club/joylink/rtss/services/draftData/RoutingGenerator.java +++ b/src/main/java/club/joylink/rtss/services/draftData/RoutingGenerator.java @@ -1,14 +1,26 @@ package club.joylink.rtss.services.draftData; -import club.joylink.rtss.simulation.cbtc.data.map.*; +import club.joylink.rtss.simulation.cbtc.data.map.AutoSignal; +import club.joylink.rtss.simulation.cbtc.data.map.MapElement; +import club.joylink.rtss.simulation.cbtc.data.map.Route; +import club.joylink.rtss.simulation.cbtc.data.map.Routing; +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.vo.map.logic.MapRoutingDataVO; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.stream.Collectors; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; -import java.util.*; -import java.util.stream.Collectors; - /** * 交路生成 */ @@ -122,7 +134,7 @@ public class RoutingGenerator { if (signal == null) { Section base = section; for (int i = 0; i < 10; i++) { - Section next = base.getSectionOf(right); + Section next = base.findNextRunningSectionBaseRealSwitch(right); if (next == null) { // 可能到尽头了 return; } diff --git a/src/main/java/club/joylink/rtss/services/project/DeviceServiceImpl.java b/src/main/java/club/joylink/rtss/services/project/DeviceServiceImpl.java index 24db7052d..32a0ce6c0 100644 --- a/src/main/java/club/joylink/rtss/services/project/DeviceServiceImpl.java +++ b/src/main/java/club/joylink/rtss/services/project/DeviceServiceImpl.java @@ -1188,8 +1188,8 @@ public class DeviceServiceImpl implements DeviceService { section.setCreateTime(now); SandTableSectionConfigVO configVO = new SandTableSectionConfigVO(mapSectionNewVO.getCode(), mapSectionNewVO.getSrCode()); - section.setConfig(JsonUtils.writeValueAsString(configVO)); ngyFillTime(configVO, mapSectionNewVO); + section.setConfig(JsonUtils.writeValueAsString(configVO)); list.add(section); } } @@ -1213,7 +1213,8 @@ public class DeviceServiceImpl implements DeviceService { private void ngyFillTime(SandTableSectionConfigVO configVO, MapSectionNewVO section) { Float headDelayTime = null; Float tailDelayTime = null; - if (section.isStandTrack() || section.isReentryTrack() || section.isTransferTrack()) { + if (section.isStandTrack() || section.isReentryTrack() || section.isTransferTrack() + || section.isParkingTrack()) { if (section.isStandTrack()) { tailDelayTime = 1f; } else { diff --git a/src/main/java/club/joylink/rtss/services/publishData/PublishMapDataHandler.java b/src/main/java/club/joylink/rtss/services/publishData/PublishMapDataHandler.java index 2df6d1aae..f9cb9124f 100644 --- a/src/main/java/club/joylink/rtss/services/publishData/PublishMapDataHandler.java +++ b/src/main/java/club/joylink/rtss/services/publishData/PublishMapDataHandler.java @@ -280,7 +280,13 @@ public class PublishMapDataHandler { MapGraphDataNewVO data = JsonUtils.read(map.getGraphData(), MapGraphDataNewVO.class); for (MapSectionNewVO section : data.getSectionList()) { if (section.getLengthFact() != null && section.getLengthFact() != 0) { - section.setLengthFact(section.getLengthFact() * multiple); + if (section.isStandTrack() || section.isParkingTrack()) { + section.setLengthFact(140f); + } else if (section.isSwitchSection()) { + section.setLengthFact(30f); + } else { + section.setLengthFact(1000f); + } } } map.setGraphData(JsonUtils.writeValueAsString(data)); diff --git a/src/main/java/club/joylink/rtss/services/runplan/RunPlanRoutingService.java b/src/main/java/club/joylink/rtss/services/runplan/RunPlanRoutingService.java index 9f445780d..5b1bfeb83 100644 --- a/src/main/java/club/joylink/rtss/services/runplan/RunPlanRoutingService.java +++ b/src/main/java/club/joylink/rtss/services/runplan/RunPlanRoutingService.java @@ -18,10 +18,24 @@ import club.joylink.rtss.vo.AccountVO; import club.joylink.rtss.vo.client.PageVO; import club.joylink.rtss.vo.client.runplan.RunPlanTripVO; import club.joylink.rtss.vo.client.runplan.RunPlanVO; -import club.joylink.rtss.vo.client.runplan.user.*; +import club.joylink.rtss.vo.client.runplan.user.RunPlanParkingTimeVO; +import club.joylink.rtss.vo.client.runplan.user.RunPlanRoutingQueryVO; +import club.joylink.rtss.vo.client.runplan.user.RunPlanRoutingSection; +import club.joylink.rtss.vo.client.runplan.user.RunPlanRoutingVO; +import club.joylink.rtss.vo.client.runplan.user.RunPlanRunlevelVO; +import club.joylink.rtss.vo.client.runplan.user.RunPlanUserConfigVO; import club.joylink.rtss.vo.map.MapVO; import com.github.pagehelper.Page; import com.github.pagehelper.PageHelper; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.stream.Collectors; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -29,230 +43,258 @@ import org.springframework.transaction.annotation.Transactional; import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; -import java.util.*; -import java.util.stream.Collectors; - @Service @Slf4j public class RunPlanRoutingService implements IRunPlanRoutingService { - @Autowired - private RunPlanRoutingDAO runPlanRoutingDAO; + @Autowired + private RunPlanRoutingDAO runPlanRoutingDAO; - @Autowired - private RunPlanDraftDAO runPlanDraftDAO; + @Autowired + private RunPlanDraftDAO runPlanDraftDAO; - @Autowired - private IRunPlanRunlevelService planRunlevelService; + @Autowired + private IRunPlanRunlevelService planRunlevelService; - @Autowired - private IRunPlanParktimeService planParktimeService; + @Autowired + private IRunPlanParktimeService planParktimeService; - @Autowired - private IRunPlanUserConfigService planConfigService; + @Autowired + private IRunPlanUserConfigService planConfigService; - @Autowired - private IMapService iMapService; + @Autowired + private IMapService iMapService; - @Transactional - @Override - public void createUserRouting(RunPlanRoutingVO routingVO) { - BusinessExceptionAssertEnum.DATA_ALREADY_EXIST.assertNotTrue(routingDataExist(routingVO), "交路数据重复"); - MapVO map = this.iMapService.getMapDetail(routingVO.getMapId()); - SimulationBuilder.SimulationDeviceBuildResult buildResult = SimulationBuilder.checkAndBuildMapDeviceData(map); - if (map.getCheckConfig().isCheck()) { - BusinessExceptionAssertEnum.DATA_ERROR.assertCollectionEmpty(buildResult.getErrMsgList(), - "地图基础数据校验不通过"); + @Transactional + @Override + public void createUserRouting(RunPlanRoutingVO routingVO) { + BusinessExceptionAssertEnum.DATA_ALREADY_EXIST.assertNotTrue(routingDataExist(routingVO), + "交路数据重复"); + MapVO map = this.iMapService.getMapDetail(routingVO.getMapId()); + SimulationBuilder.SimulationDeviceBuildResult buildResult = SimulationBuilder.checkAndBuildMapDeviceData( + map); + if (map.getCheckConfig().isCheck()) { + BusinessExceptionAssertEnum.DATA_ERROR.assertCollectionEmpty(buildResult.getErrMsgList(), + "地图基础数据校验不通过"); + } + Map deviceMap = buildResult.getDeviceMap(); + setRoutingType(routingVO, deviceMap); + RunPlanRouting routing = routingVO.convert2Entity(); + runPlanRoutingDAO.insert(routing); + createRoutingRefData(deviceMap, routingVO); + if (Objects.equals(RunPlanRoutingVO.UserRoutingType.LOOP, routingVO.getRoutingType())) { + RunPlanRoutingVO routingDataLoop = routingVO.getRoutingDataLoop(); + try { + generateUserRoutingSections(routingDataLoop, deviceMap); + } catch (BaseException e) { + return; + } + if (routingDataExist(routingDataLoop)) { + return; + } + Section endSection = (Section) deviceMap.get(routingDataLoop.getEndSectionCode()); + routingDataLoop.setDestinationCode(endSection.getDestinationCode()); + runPlanRoutingDAO.insert(routingDataLoop.convert2Entity()); + createRoutingRefData(deviceMap, routingDataLoop); + } + } + + @Override + @Transactional + public void createDefaultRoutings(List defaultRoutings) { + if (CollectionUtils.isEmpty(defaultRoutings)) { + return; + } + MapVO map = this.iMapService.getMapDetail(defaultRoutings.get(0).getMapId()); + SimulationBuilder.SimulationDeviceBuildResult buildResult = SimulationBuilder.checkAndBuildMapDeviceData( + map); +// BusinessExceptionAssertEnum.DATA_ERROR.assertCollectionEmpty(buildResult.getErrMsgList(), "地图基础数据校验不通过"); + if (CollectionUtils.isEmpty(buildResult.getErrMsgList())) { + Map deviceMap = buildResult.getDeviceMap(); + defaultRoutings.forEach(routingVO -> { + routingVO.setUserId(null); + if (routingDataExist(routingVO)) { + return; } - Map deviceMap = buildResult.getDeviceMap(); setRoutingType(routingVO, deviceMap); RunPlanRouting routing = routingVO.convert2Entity(); runPlanRoutingDAO.insert(routing); - createRoutingRefData(deviceMap, routingVO); - if (Objects.equals(RunPlanRoutingVO.UserRoutingType.LOOP, routingVO.getRoutingType())) { - RunPlanRoutingVO routingDataLoop = routingVO.getRoutingDataLoop(); - try { - generateUserRoutingSections(routingDataLoop, deviceMap); - }catch (BaseException e){ - return; - } - if (routingDataExist(routingDataLoop)) return; - Section endSection = (Section) deviceMap.get(routingDataLoop.getEndSectionCode()); - routingDataLoop.setDestinationCode(endSection.getDestinationCode()); - runPlanRoutingDAO.insert(routingDataLoop.convert2Entity()); - createRoutingRefData(deviceMap, routingDataLoop); - } + }); } + } - @Override - @Transactional - public void createDefaultRoutings(List defaultRoutings) { - if (CollectionUtils.isEmpty(defaultRoutings)) return; - MapVO map = this.iMapService.getMapDetail(defaultRoutings.get(0).getMapId()); - SimulationBuilder.SimulationDeviceBuildResult buildResult = SimulationBuilder.checkAndBuildMapDeviceData(map); -// BusinessExceptionAssertEnum.DATA_ERROR.assertCollectionEmpty(buildResult.getErrMsgList(), "地图基础数据校验不通过"); - if (CollectionUtils.isEmpty(buildResult.getErrMsgList())) { - Map deviceMap = buildResult.getDeviceMap(); - defaultRoutings.forEach(routingVO -> { - routingVO.setUserId(null); - if (routingDataExist(routingVO)) return; - setRoutingType(routingVO, deviceMap); - RunPlanRouting routing = routingVO.convert2Entity(); - runPlanRoutingDAO.insert(routing); - }); - } + @Override + @Transactional + public void syncDefaultRoutingRefData(Long userId, Long mapId) { + List defaultRoutingVOs = getDefaultRoutings(mapId); + if (CollectionUtils.isEmpty(defaultRoutingVOs)) { + return; } - - @Override - @Transactional - public void syncDefaultRoutingRefData(Long userId, Long mapId) { - List defaultRoutingVOs = getDefaultRoutings(mapId); - if (CollectionUtils.isEmpty(defaultRoutingVOs)) return; - SimulationBuilder.SimulationDeviceBuildResult buildResult = SimulationBuilder.checkAndBuildMapDeviceData(this.iMapService.getMapDetail(mapId)); - BusinessExceptionAssertEnum.DATA_ERROR.assertCollectionEmpty(buildResult.getErrMsgList(), "地图基础数据校验不通过"); - Map deviceMap = buildResult.getDeviceMap(); - //根据默认交路生成站间运行等级、停站时间、折返数据 - Set levelList = new HashSet<>(100); - Set parkingTimeList = new HashSet<>(30); - RunPlanUserConfigVO userConfig = planConfigService.getConfig(userId, mapId); - Map reentryData; - if (Objects.nonNull(userConfig)) { - reentryData = userConfig.getConfig().getReentryData(); - } else { - RunPlanUserConfigVO.Config config = new RunPlanUserConfigVO.Config(); - reentryData = config.getReentryData(); - userConfig = new RunPlanUserConfigVO(mapId, userId, config); - } - defaultRoutingVOs.forEach(routingVO -> { - routingVO.setUserId(userId); - List levels = RunPlanRunlevelVO.runLevelsFromRouting(routingVO); - levelList.addAll(levels.stream().filter(l -> { - Section startSection = (Section) deviceMap.get(l.getStartSectionCode()); - Section endSection = (Section) deviceMap.get(l.getEndSectionCode()); - if ((startSection.isTurnBackTrack() && !startSection.isStandTrack()) - || (endSection.isTurnBackTrack() && !endSection.isStandTrack())) { - return false; - } - return true; - }).collect(Collectors.toList())); - - List parkingTimeVOS = RunPlanParkingTimeVO.parkingTimeFromRouting(routingVO); - parkingTimeVOS.forEach(p -> { - if (((Section) deviceMap.get(p.getSectionCode())).isStandTrack()) { - parkingTimeList.add(p); - } - }); - - setStationReentryTime(deviceMap, reentryData, routingVO); - } - ); - //先简单插入新数据 - List levels = planRunlevelService.queryUserRunLevels(userId, mapId); - levelList.removeAll(levels); - levelList.forEach(l -> { + SimulationBuilder.SimulationDeviceBuildResult buildResult = SimulationBuilder.checkAndBuildMapDeviceData( + this.iMapService.getMapDetail(mapId)); + BusinessExceptionAssertEnum.DATA_ERROR.assertCollectionEmpty(buildResult.getErrMsgList(), + "地图基础数据校验不通过"); + Map deviceMap = buildResult.getDeviceMap(); + //根据默认交路生成站间运行等级、停站时间、折返数据 + Set levelList = new HashSet<>(100); + Set parkingTimeList = new HashSet<>(30); + RunPlanUserConfigVO userConfig = planConfigService.getConfig(userId, mapId); + Map reentryData; + if (Objects.nonNull(userConfig)) { + reentryData = userConfig.getConfig().getReentryData(); + } else { + RunPlanUserConfigVO.Config config = new RunPlanUserConfigVO.Config(); + reentryData = config.getReentryData(); + userConfig = new RunPlanUserConfigVO(mapId, userId, config); + } + defaultRoutingVOs.forEach(routingVO -> { + routingVO.setUserId(userId); + List levels = RunPlanRunlevelVO.runLevelsFromRouting(routingVO); + levelList.addAll(levels.stream().filter(l -> { Section startSection = (Section) deviceMap.get(l.getStartSectionCode()); Section endSection = (Section) deviceMap.get(l.getEndSectionCode()); - if ((startSection.isStandTrack() && endSection.isTransferTrack()) || (endSection.isStandTrack() && startSection.isTransferTrack())) { - Float distance; - try { - distance = CalculateService.calculateDistance(startSection, endSection, l.getRight()); - } catch (SimulationException e) { - distance = CalculateService.calculateDistance(startSection, endSection, !l.getRight()); - } - l.setDistance(distance); - l.generateDefaultRunLevel(); - planRunlevelService.createUserRunlevel(l); - return; + if ((startSection.isTurnBackTrack() && !startSection.isStandTrack()) + || (endSection.isTurnBackTrack() && !endSection.isStandTrack())) { + return false; } - Float distance = CalculateService.calculateDistance(startSection, endSection, l.getRight()); - l.setDistance(distance); - l.generateDefaultRunLevel(); - planRunlevelService.createUserRunlevel(l); - }); - List parktimes = planParktimeService.queryUserParktimes(userId, mapId); - parkingTimeList.removeAll(parktimes); - parkingTimeList.forEach(p -> { - planParktimeService.createUserParktime(p); - }); - planConfigService.saveConfig(userId, mapId, userConfig.getConfig()); - } + return true; + }).collect(Collectors.toList())); - private void setStationReentryTime(Map deviceMap, Map reentryData, RunPlanRoutingVO routingVO) { - Section startSection = (Section) deviceMap.get(routingVO.getStartSectionCode()); - if (startSection.isTurnBackTrack()) { - reentryData.putIfAbsent(routingVO.getStartStationCode(), new RunPlanUserConfigVO.ReentryTime(120, 210, 45, 45)); + List parkingTimeVOS = RunPlanParkingTimeVO.parkingTimeFromRouting( + routingVO); + parkingTimeVOS.forEach(p -> { + if (((Section) deviceMap.get(p.getSectionCode())).isStandTrack()) { + parkingTimeList.add(p); + } + }); + + setStationReentryTime(deviceMap, reentryData, routingVO); } - Section endSection = (Section) deviceMap.get(routingVO.getEndSectionCode()); - if (endSection.isTurnBackTrack()) { - reentryData.putIfAbsent(routingVO.getEndStationCode(), new RunPlanUserConfigVO.ReentryTime(120, 210, 45, 45)); + ); + //先简单插入新数据 + List levels = planRunlevelService.queryUserRunLevels(userId, mapId); + levelList.removeAll(levels); + levelList.forEach(l -> { + Section startSection = (Section) deviceMap.get(l.getStartSectionCode()); + Section endSection = (Section) deviceMap.get(l.getEndSectionCode()); + if ((startSection.isStandTrack() && endSection.isTransferTrack()) || ( + endSection.isStandTrack() && startSection.isTransferTrack())) { + Float distance; + try { + distance = CalculateService.calculateDistance(startSection, endSection, l.getRight()); + } catch (SimulationException e) { + distance = CalculateService.calculateDistance(startSection, endSection, !l.getRight()); } - } + l.setDistance(distance); + l.generateDefaultRunLevel(); + planRunlevelService.createUserRunlevel(l); + return; + } + Float distance = CalculateService.calculateDistance(startSection, endSection, l.getRight()); + l.setDistance(distance); + l.generateDefaultRunLevel(); + planRunlevelService.createUserRunlevel(l); + }); + List parktimes = planParktimeService.queryUserParktimes(userId, mapId); + parkingTimeList.removeAll(parktimes); + parkingTimeList.forEach(p -> { + planParktimeService.createUserParktime(p); + }); + planConfigService.saveConfig(userId, mapId, userConfig.getConfig()); + } - private void createRoutingRefData(Map deviceMap, RunPlanRoutingVO routingVO) { - generateUserRunlevels(routingVO, deviceMap); - generateUserParktimes(routingVO, deviceMap); - generateUserStationReentryTimes(routingVO, deviceMap); + private void setStationReentryTime(Map deviceMap, + Map reentryData, RunPlanRoutingVO routingVO) { + Section startSection = (Section) deviceMap.get(routingVO.getStartSectionCode()); + if (startSection.isTurnBackTrack()) { + reentryData.putIfAbsent(routingVO.getStartStationCode(), + new RunPlanUserConfigVO.ReentryTime(120, 210, 45, 45)); } + Section endSection = (Section) deviceMap.get(routingVO.getEndSectionCode()); + if (endSection.isTurnBackTrack()) { + reentryData.putIfAbsent(routingVO.getEndStationCode(), + new RunPlanUserConfigVO.ReentryTime(120, 210, 45, 45)); + } + } - @Override - public RunPlanRoutingVO generateUserRoutingData(RunPlanRoutingVO routingVO) { - MapVO map = this.iMapService.getMapDetail(routingVO.getMapId()); - SimulationBuilder.SimulationDeviceBuildResult buildResult = SimulationBuilder.checkAndBuildMapDeviceData(map); - BusinessExceptionAssertEnum.DATA_ERROR.assertCollectionEmpty(buildResult.getErrMsgList(), - "地图基础数据校验不通过"); - Map deviceMap = buildResult.getDeviceMap(); - generateUserRoutingSections(routingVO, deviceMap); - return routingVO; - } + private void createRoutingRefData(Map deviceMap, RunPlanRoutingVO routingVO) { + generateUserRunlevels(routingVO, deviceMap); + generateUserParktimes(routingVO, deviceMap); + generateUserStationReentryTimes(routingVO, deviceMap); + } - @Override - public List queryRoutes(Long mapId, RunPlanRoutingQueryVO queryVO, AccountVO user) { - return getUserRoutingBy(user.getId(), mapId).stream() - .filter(routing -> Objects.equals(routing.getDestinationCode(), queryVO.getDestinationCode())) - .collect(Collectors.toList()); - } + @Override + public RunPlanRoutingVO generateUserRoutingData(RunPlanRoutingVO routingVO) { + MapVO map = this.iMapService.getMapDetail(routingVO.getMapId()); + SimulationBuilder.SimulationDeviceBuildResult buildResult = SimulationBuilder.checkAndBuildMapDeviceData( + map); + BusinessExceptionAssertEnum.DATA_ERROR.assertCollectionEmpty(buildResult.getErrMsgList(), + "地图基础数据校验不通过"); + Map deviceMap = buildResult.getDeviceMap(); + generateUserRoutingSections(routingVO, deviceMap); + return routingVO; + } - private void generateUserRoutingSections(RunPlanRoutingVO routingVO, Map deviceMap) { - Section startSection = (Section) deviceMap.get(routingVO.getStartSectionCode()); - Section endSection = (Section) deviceMap.get(routingVO.getEndSectionCode()); - //中间经停所有站台轨 - List
passingStandTrack = CalculateService.findPassingStandTrack(startSection, endSection, routingVO.getRight()); - BusinessExceptionAssertEnum.OPERATION_NOT_SUPPORTED.assertNotNull(passingStandTrack, - String.format("没有找到线路方向[%s]的中间经停区段,是否需要更换方向/手动添加/直接保存交路", routingVO.getRight() ? "右向" : "左向")); - LinkedList parkSectionCodeList = passingStandTrack.stream().map(section -> new RunPlanRoutingSection(section.getStation().getCode(), section.getCode())).collect(Collectors.toCollection(LinkedList::new)); - parkSectionCodeList.addFirst(new RunPlanRoutingSection(routingVO.getStartStationCode(), routingVO.getStartSectionCode())); - parkSectionCodeList.addLast(new RunPlanRoutingSection(routingVO.getEndStationCode(), routingVO.getEndSectionCode())); - routingVO.setParkSectionCodeList(parkSectionCodeList); - } + @Override + public List queryRoutes(Long mapId, RunPlanRoutingQueryVO queryVO, + AccountVO user) { + return getUserRoutingBy(user.getId(), mapId).stream() + .filter( + routing -> Objects.equals(routing.getDestinationCode(), queryVO.getDestinationCode())) + .collect(Collectors.toList()); + } - @Override - public RunPlanRoutingVO getUserRouting(Long routingId) { - RunPlanRouting routing = getRunPlanRoutingData(routingId); - return RunPlanRoutingVO.convert2VO(routing); - } + private void generateUserRoutingSections(RunPlanRoutingVO routingVO, + Map deviceMap) { + Section startSection = (Section) deviceMap.get(routingVO.getStartSectionCode()); + Section endSection = (Section) deviceMap.get(routingVO.getEndSectionCode()); + //中间经停所有站台轨 + List
passingStandTrack = CalculateService.findPassingStandTrack(startSection, + endSection, routingVO.getRight()); + BusinessExceptionAssertEnum.OPERATION_NOT_SUPPORTED.assertNotNull(passingStandTrack, + String.format("没有找到线路方向[%s]的中间经停区段,是否需要更换方向/手动添加/直接保存交路", + routingVO.getRight() ? "右向" : "左向")); + LinkedList parkSectionCodeList = passingStandTrack.stream().map( + section -> new RunPlanRoutingSection(section.getStation().getCode(), section.getCode())) + .collect(Collectors.toCollection(LinkedList::new)); + parkSectionCodeList.addFirst(new RunPlanRoutingSection(routingVO.getStartStationCode(), + routingVO.getStartSectionCode())); + parkSectionCodeList.addLast( + new RunPlanRoutingSection(routingVO.getEndStationCode(), routingVO.getEndSectionCode())); + routingVO.setParkSectionCodeList(parkSectionCodeList); + } - @Transactional - @Override - public void updateUserRouting(Long routingId, RunPlanRoutingVO routingVO) { - MapVO map = this.iMapService.getMapDetail(routingVO.getMapId()); - SimulationBuilder.SimulationDeviceBuildResult buildResult = SimulationBuilder.checkAndBuildMapDeviceData(map); - BusinessExceptionAssertEnum.DATA_ERROR.assertCollectionEmpty(buildResult.getErrMsgList(), - "地图基础数据校验不通过"); - Map deviceMap = buildResult.getDeviceMap(); - setRoutingType(routingVO, deviceMap); - RunPlanRouting newRouting = routingVO.convert2Entity(); - newRouting.setId(routingId); - RunPlanRouting routing = getRunPlanRoutingData(routingId); - if(Objects.equals(routing.getSectionData(),JsonUtils.writeValueAsString(routingVO.getParkSectionCodeList()))){ - runPlanRoutingDAO.updateByPrimaryKey(newRouting); - return; - } - BusinessExceptionAssertEnum.DATA_ALREADY_EXIST.assertNotTrue(routingDataExist(routingVO), "交路数据重复"); - runPlanRoutingDAO.updateByPrimaryKeyWithBLOBs(newRouting); - generateUserRunlevels(routingVO, deviceMap); - generateUserParktimes(routingVO, deviceMap); - generateUserStationReentryTimes(routingVO, deviceMap); + @Override + public RunPlanRoutingVO getUserRouting(Long routingId) { + RunPlanRouting routing = getRunPlanRoutingData(routingId); + return RunPlanRoutingVO.convert2VO(routing); + } + + @Transactional + @Override + public void updateUserRouting(Long routingId, RunPlanRoutingVO routingVO) { + MapVO map = this.iMapService.getMapDetail(routingVO.getMapId()); + SimulationBuilder.SimulationDeviceBuildResult buildResult = SimulationBuilder.checkAndBuildMapDeviceData( + map); + BusinessExceptionAssertEnum.DATA_ERROR.assertCollectionEmpty(buildResult.getErrMsgList(), + "地图基础数据校验不通过"); + Map deviceMap = buildResult.getDeviceMap(); + setRoutingType(routingVO, deviceMap); + RunPlanRouting newRouting = routingVO.convert2Entity(); + newRouting.setId(routingId); + RunPlanRouting routing = getRunPlanRoutingData(routingId); + if (Objects.equals(routing.getSectionData(), + JsonUtils.writeValueAsString(routingVO.getParkSectionCodeList()))) { + runPlanRoutingDAO.updateByPrimaryKey(newRouting); + return; } + BusinessExceptionAssertEnum.DATA_ALREADY_EXIST.assertNotTrue(routingDataExist(routingVO), + "交路数据重复"); + runPlanRoutingDAO.updateByPrimaryKeyWithBLOBs(newRouting); + generateUserRunlevels(routingVO, deviceMap); + generateUserParktimes(routingVO, deviceMap); + generateUserStationReentryTimes(routingVO, deviceMap); + } private void setRoutingType(RunPlanRoutingVO routingVO, Map deviceMap) { Section startSection = (Section) deviceMap.get(routingVO.getStartSectionCode()); @@ -268,175 +310,200 @@ public class RunPlanRoutingService implements IRunPlanRoutingService { } } - private void generateUserParktimes(RunPlanRoutingVO routingVO, Map deviceMap) { - List parkingTimeVOS = RunPlanParkingTimeVO.parkingTimeFromRouting(routingVO); - parkingTimeVOS.forEach(p -> { - if (((Section) deviceMap.get(p.getSectionCode())).isStandTrack()) { - planParktimeService.createUserParktime(p); - } - }); - } + private void generateUserParktimes(RunPlanRoutingVO routingVO, + Map deviceMap) { + List parkingTimeVOS = RunPlanParkingTimeVO.parkingTimeFromRouting( + routingVO); + parkingTimeVOS.forEach(p -> { + if (((Section) deviceMap.get(p.getSectionCode())).isStandTrack()) { + planParktimeService.createUserParktime(p); + } + }); + } - private void generateUserRunlevels(RunPlanRoutingVO routingVO, Map deviceMap) { - List levels = RunPlanRunlevelVO.runLevelsFromRouting(routingVO); - levels.forEach(l -> { - Section startSection = (Section) deviceMap.get(l.getStartSectionCode()); - Section endSection = (Section) deviceMap.get(l.getEndSectionCode()); - if ((startSection.isTurnBackTrack() && !startSection.isStandTrack()) - || (endSection.isTurnBackTrack() && !endSection.isStandTrack())) { - return; - } - if ((startSection.isStandTrack() && endSection.isTransferTrack()) || (endSection.isStandTrack() && startSection.isTransferTrack())) { - Float distance; - try { - distance = CalculateService.calculateDistance(startSection, endSection, l.getRight()); - } catch (SimulationException e) { - distance = CalculateService.calculateDistance(startSection, endSection, !l.getRight()); - } - l.setDistance(distance); - l.generateDefaultRunLevel(); - planRunlevelService.createUserRunlevel(l); - return; - } - Float distance = CalculateService.calculateDistance(startSection, endSection, l.getRight()); - l.setDistance(distance); - l.generateDefaultRunLevel(); - planRunlevelService.createUserRunlevel(l); - }); - } - - private void generateUserStationReentryTimes(RunPlanRoutingVO routingVO, Map deviceMap) { - RunPlanUserConfigVO userConfig = planConfigService.getConfig(routingVO.getUserId(), routingVO.getMapId()); - Map reentryData; - if (Objects.nonNull(userConfig)) { - reentryData = userConfig.getConfig().getReentryData(); - }else{ - RunPlanUserConfigVO.Config config = new RunPlanUserConfigVO.Config(); - reentryData = config.getReentryData(); - userConfig = new RunPlanUserConfigVO( routingVO.getMapId(),routingVO.getUserId(),config); + private void generateUserRunlevels(RunPlanRoutingVO routingVO, + Map deviceMap) { + List levels = RunPlanRunlevelVO.runLevelsFromRouting(routingVO); + levels.forEach(l -> { + Section startSection = (Section) deviceMap.get(l.getStartSectionCode()); + Section endSection = (Section) deviceMap.get(l.getEndSectionCode()); + if ((startSection.isTurnBackTrack() && !startSection.isStandTrack()) + || (endSection.isTurnBackTrack() && !endSection.isStandTrack())) { + return; + } + if ((startSection.isStandTrack() && endSection.isTransferTrack()) || ( + endSection.isStandTrack() && startSection.isTransferTrack())) { + Float distance; + try { + distance = CalculateService.calculateDistance(startSection, endSection, l.getRight()); + } catch (SimulationException e) { + distance = CalculateService.calculateDistance(startSection, endSection, !l.getRight()); } - //交路是折返轨的一头 设置折返时间 - setStationReentryTime(deviceMap, reentryData, routingVO); - planConfigService.saveConfig(routingVO.getUserId(), routingVO.getMapId(),userConfig.getConfig()); + l.setDistance(distance); + l.generateDefaultRunLevel(); + planRunlevelService.createUserRunlevel(l); + return; + } + Float distance = CalculateService.calculateDistance(startSection, endSection, l.getRight()); + l.setDistance(distance); + l.generateDefaultRunLevel(); + planRunlevelService.createUserRunlevel(l); + }); + } + + private void generateUserStationReentryTimes(RunPlanRoutingVO routingVO, + Map deviceMap) { + RunPlanUserConfigVO userConfig = planConfigService.getConfig(routingVO.getUserId(), + routingVO.getMapId()); + Map reentryData; + if (Objects.nonNull(userConfig)) { + reentryData = userConfig.getConfig().getReentryData(); + } else { + RunPlanUserConfigVO.Config config = new RunPlanUserConfigVO.Config(); + reentryData = config.getReentryData(); + userConfig = new RunPlanUserConfigVO(routingVO.getMapId(), routingVO.getUserId(), config); } + //交路是折返轨的一头 设置折返时间 + setStationReentryTime(deviceMap, reentryData, routingVO); + planConfigService.saveConfig(routingVO.getUserId(), routingVO.getMapId(), + userConfig.getConfig()); + } - @Override - public void deleteUserRouting(Long routingId) { - runPlanRoutingDAO.deleteByPrimaryKey(routingId); + @Override + public void deleteUserRouting(Long routingId) { + runPlanRoutingDAO.deleteByPrimaryKey(routingId); + } + + @Override + @Transactional + public void deleteDefaultRouting(Long mapId) { + RunPlanRoutingExample example = new RunPlanRoutingExample(); + example.createCriteria().andMapIdEqualTo(mapId).andUserIdIsNull(); + runPlanRoutingDAO.deleteByExample(example); + } + + @Override + public PageVO queryPagedUserRouting(Long userId, Long mapId, + RunPlanRoutingQueryVO queryVO) { + PageHelper.startPage(queryVO.getPageNum(), queryVO.getPageSize()); + RunPlanRoutingExample example = new RunPlanRoutingExample(); + example.setOrderByClause("user_id DESC,id"); + RunPlanRoutingExample.Criteria criteria = example.createCriteria(); + criteria.andMapIdEqualTo(mapId).andUserIdEqualTo(userId); + RunPlanRoutingExample.Criteria or = example.or(); + or.andMapIdEqualTo(mapId).andUserIdIsNull(); + if (StringUtils.hasText(queryVO.getStartStationCode())) { + criteria.andStartStationCodeEqualTo(queryVO.getStartStationCode()); + or.andStartStationCodeEqualTo(queryVO.getStartStationCode()); } - - @Override - @Transactional - public void deleteDefaultRouting(Long mapId) { - RunPlanRoutingExample example = new RunPlanRoutingExample(); - example.createCriteria().andMapIdEqualTo(mapId).andUserIdIsNull(); - runPlanRoutingDAO.deleteByExample(example); + if (StringUtils.hasText(queryVO.getEndStationCode())) { + criteria.andEndStationCodeEqualTo(queryVO.getEndStationCode()); + or.andEndStationCodeEqualTo(queryVO.getEndStationCode()); } - - @Override - public PageVO queryPagedUserRouting(Long userId, Long mapId, RunPlanRoutingQueryVO queryVO) { - PageHelper.startPage(queryVO.getPageNum(), queryVO.getPageSize()); - RunPlanRoutingExample example = new RunPlanRoutingExample(); - example.setOrderByClause("user_id DESC,id"); - RunPlanRoutingExample.Criteria criteria = example.createCriteria(); - criteria.andMapIdEqualTo(mapId).andUserIdEqualTo(userId); - RunPlanRoutingExample.Criteria or = example.or(); - or.andMapIdEqualTo(mapId).andUserIdIsNull(); - if (StringUtils.hasText(queryVO.getStartStationCode())) { - criteria.andStartStationCodeEqualTo(queryVO.getStartStationCode()); - or.andStartStationCodeEqualTo(queryVO.getStartStationCode()); - } - if (StringUtils.hasText(queryVO.getEndStationCode())) { - criteria.andEndStationCodeEqualTo(queryVO.getEndStationCode()); - or.andEndStationCodeEqualTo(queryVO.getEndStationCode()); - } - if (StringUtils.hasText(queryVO.getStartSectionCode())) { - criteria.andStartSectionCodeEqualTo(queryVO.getStartSectionCode()); - or.andStartSectionCodeEqualTo(queryVO.getStartSectionCode()); - } - if (StringUtils.hasText(queryVO.getEndSectionCode())) { - criteria.andEndSectionCodeEqualTo(queryVO.getEndSectionCode()); - or.andEndSectionCodeEqualTo(queryVO.getEndSectionCode()); - } - Page page = (Page) runPlanRoutingDAO.selectByExampleWithBLOBs(example); - List routingVOList = page.getResult().stream().map(RunPlanRoutingVO::convert2VO).collect(Collectors.toList()); - return PageVO.convert(page, routingVOList); + if (StringUtils.hasText(queryVO.getStartSectionCode())) { + criteria.andStartSectionCodeEqualTo(queryVO.getStartSectionCode()); + or.andStartSectionCodeEqualTo(queryVO.getStartSectionCode()); } - - public List getDefaultRoutings(Long mapId) { - RunPlanRoutingExample example = new RunPlanRoutingExample(); - example.createCriteria().andMapIdEqualTo(mapId).andUserIdIsNull(); - List runPlanRoutings = runPlanRoutingDAO.selectByExampleWithBLOBs(example); - return RunPlanRoutingVO.convert2VOList(runPlanRoutings); + if (StringUtils.hasText(queryVO.getEndSectionCode())) { + criteria.andEndSectionCodeEqualTo(queryVO.getEndSectionCode()); + or.andEndSectionCodeEqualTo(queryVO.getEndSectionCode()); } + Page page = (Page) runPlanRoutingDAO.selectByExampleWithBLOBs( + example); + List routingVOList = page.getResult().stream() + .map(RunPlanRoutingVO::convert2VO).collect(Collectors.toList()); + return PageVO.convert(page, routingVOList); + } + + public List getDefaultRoutings(Long mapId) { + RunPlanRoutingExample example = new RunPlanRoutingExample(); + example.createCriteria().andMapIdEqualTo(mapId).andUserIdIsNull(); + List runPlanRoutings = runPlanRoutingDAO.selectByExampleWithBLOBs(example); + return RunPlanRoutingVO.convert2VOList(runPlanRoutings); + } - @Override - public List getUserRoutingBy(Long userId, Long mapId) { - RunPlanRoutingExample example = new RunPlanRoutingExample(); - example.createCriteria().andMapIdEqualTo(mapId).andUserIdEqualTo(userId); - example.or().andMapIdEqualTo(mapId).andUserIdIsNull(); - List runPlanRoutings = runPlanRoutingDAO.selectByExample(example); - return RunPlanRoutingVO.convert2VOList(runPlanRoutings,this.iMapService.getMapDetail(mapId)); + @Override + public List getUserRoutingBy(Long userId, Long mapId) { + RunPlanRoutingExample example = new RunPlanRoutingExample(); + example.createCriteria().andMapIdEqualTo(mapId).andUserIdEqualTo(userId); + example.or().andMapIdEqualTo(mapId).andUserIdIsNull(); + List runPlanRoutings = runPlanRoutingDAO.selectByExample(example); + return RunPlanRoutingVO.convert2VOList(runPlanRoutings, this.iMapService.getMapDetail(mapId)); + } + + @Override + public List getUserRoutingByType(Long userId, Long mapId, + RunPlanRoutingVO.UserRoutingType routingType) { + RunPlanRoutingExample example = new RunPlanRoutingExample(); + example.createCriteria().andMapIdEqualTo(mapId).andUserIdEqualTo(userId) + .andTypeEqualTo(routingType.name()); + example.or().andMapIdEqualTo(mapId).andUserIdIsNull().andTypeEqualTo(routingType.name()); + List runPlanRoutings = runPlanRoutingDAO.selectByExampleWithBLOBs(example); + return RunPlanRoutingVO.convert2VOList(runPlanRoutings, this.iMapService.getMapDetail(mapId)); + } + + @Override + public RunPlanRoutingVO queryUserRoutingBySDTNumber(Long userId, Long planId, String SDTNumber) { + RunPlanVO planVO = this.getRunPlanById(planId); + RunPlanTripVO trip = planVO.getTripList().stream() + .filter(tripVO -> tripVO.getSDTNumberNew().equals(SDTNumber)) + .findFirst() + .orElseThrow(() -> BusinessExceptionAssertEnum.DATA_NOT_EXIST.exception()); + RunPlanRoutingExample example = new RunPlanRoutingExample(); + example.createCriteria().andMapIdEqualTo(planVO.getMapId()).andUserIdEqualTo(userId) + .andStartSectionCodeEqualTo(trip.getStartSectionCode()) + .andEndSectionCodeEqualTo(trip.getEndSectionCode()); + example.or().andMapIdEqualTo(planVO.getMapId()).andUserIdIsNull() + .andStartSectionCodeEqualTo(trip.getStartSectionCode()) + .andEndSectionCodeEqualTo(trip.getEndSectionCode()); + List runPlanRoutings = runPlanRoutingDAO.selectByExampleWithBLOBs(example); + if (CollectionUtils.isEmpty(runPlanRoutings)) { + return null; } + return RunPlanRoutingVO.convert2VO(runPlanRoutings.get(0), + this.iMapService.getMapDetail(planVO.getMapId())); + } - @Override - public List getUserRoutingByType(Long userId, Long mapId, RunPlanRoutingVO.UserRoutingType routingType) { - RunPlanRoutingExample example = new RunPlanRoutingExample(); - example.createCriteria().andMapIdEqualTo(mapId).andUserIdEqualTo(userId).andTypeEqualTo(routingType.name()); - example.or().andMapIdEqualTo(mapId).andUserIdIsNull().andTypeEqualTo(routingType.name()); - List runPlanRoutings = runPlanRoutingDAO.selectByExampleWithBLOBs(example); - return RunPlanRoutingVO.convert2VOList(runPlanRoutings,this.iMapService.getMapDetail(mapId)); + @Override + public RunPlanRoutingVO queryUserRoutingById(Long userId, Long mapId, Long routingId) { + RunPlanRouting runPlanRouting = getRunPlanRoutingData(routingId); + return RunPlanRoutingVO.convert2VO(runPlanRouting, this.iMapService.getMapDetail(mapId)); + } + + @Override + public List getRoutingSectionDataBy(Long userId, Long routingId) { + RunPlanRouting routing = runPlanRoutingDAO.selectByPrimaryKey(routingId); + if (Objects.isNull(routing)) { + return Collections.emptyList(); } + return RunPlanRoutingVO.convert2VO(routing).getParkSectionCodeList(); + } - @Override - public RunPlanRoutingVO queryUserRoutingBySDTNumber(Long userId, Long planId, String SDTNumber) { - RunPlanVO planVO = this.getRunPlanById(planId); - RunPlanTripVO trip = planVO.getTripList().stream() - .filter(tripVO -> tripVO.getSDTNumberNew().equals(SDTNumber)) - .findFirst() - .orElseThrow(() -> BusinessExceptionAssertEnum.DATA_NOT_EXIST.exception()); - RunPlanRoutingExample example = new RunPlanRoutingExample(); - example.createCriteria().andMapIdEqualTo(planVO.getMapId()).andUserIdEqualTo(userId).andStartSectionCodeEqualTo(trip.getStartSectionCode()).andEndSectionCodeEqualTo(trip.getEndSectionCode()); - example.or().andMapIdEqualTo(planVO.getMapId()).andUserIdIsNull().andStartSectionCodeEqualTo(trip.getStartSectionCode()).andEndSectionCodeEqualTo(trip.getEndSectionCode()); - List runPlanRoutings = runPlanRoutingDAO.selectByExampleWithBLOBs(example); - if (CollectionUtils.isEmpty(runPlanRoutings)) return null; - return RunPlanRoutingVO.convert2VO(runPlanRoutings.get(0), this.iMapService.getMapDetail(planVO.getMapId())); - } - - @Override - public RunPlanRoutingVO queryUserRoutingById(Long userId, Long mapId, Long routingId) { - RunPlanRouting runPlanRouting = getRunPlanRoutingData(routingId); - return RunPlanRoutingVO.convert2VO(runPlanRouting,this.iMapService.getMapDetail(mapId)); - } - - @Override - public List getRoutingSectionDataBy(Long userId, Long routingId) { - RunPlanRouting routing = runPlanRoutingDAO.selectByPrimaryKey(routingId); - if (Objects.isNull(routing)) return Collections.emptyList(); - return RunPlanRoutingVO.convert2VO(routing).getParkSectionCodeList(); - } - - - private boolean routingDataExist(RunPlanRoutingVO routingVO) { - return runPlanRoutingDAO.countUserRoutingBySectionData(routingVO.getUserId(), routingVO.getMapId(), JsonUtils.writeValueAsString(routingVO.getParkSectionCodeList())) > 0; - } - - private RunPlanRouting getRunPlanRoutingData(Long routingId) { - RunPlanRouting routing = runPlanRoutingDAO.selectByPrimaryKey(routingId); - BusinessExceptionAssertEnum.DATA_NOT_EXIST.assertNotNull(routing, String.format("交路[%s]不存在", routingId)); - return routing; - } - - private RunPlanVO getRunPlanById(Long planId) { - RunPlanDraft runPlanDraft = this.runPlanDraftDAO.selectByPrimaryKey(planId); - BusinessExceptionAssertEnum.DATA_NOT_EXIST.assertNotNull(runPlanDraft); - RunPlanVO runPlanVO = new RunPlanVO(runPlanDraft); - if (StringUtils.hasText(runPlanDraft.getTrips())) { - runPlanVO.setTripList(JsonUtils.read(runPlanDraft.getTrips(), JsonUtils.getCollectionType(List.class, RunPlanTripVO.class))); - } else { - runPlanVO.setTripList(new ArrayList<>()); - } - return runPlanVO; + + private boolean routingDataExist(RunPlanRoutingVO routingVO) { + return + runPlanRoutingDAO.countUserRoutingBySectionData(routingVO.getUserId(), routingVO.getMapId(), + JsonUtils.writeValueAsString(routingVO.getParkSectionCodeList())) > 0; + } + + private RunPlanRouting getRunPlanRoutingData(Long routingId) { + RunPlanRouting routing = runPlanRoutingDAO.selectByPrimaryKey(routingId); + BusinessExceptionAssertEnum.DATA_NOT_EXIST.assertNotNull(routing, + String.format("交路[%s]不存在", routingId)); + return routing; + } + + private RunPlanVO getRunPlanById(Long planId) { + RunPlanDraft runPlanDraft = this.runPlanDraftDAO.selectByPrimaryKey(planId); + BusinessExceptionAssertEnum.DATA_NOT_EXIST.assertNotNull(runPlanDraft); + RunPlanVO runPlanVO = new RunPlanVO(runPlanDraft); + if (StringUtils.hasText(runPlanDraft.getTrips())) { + runPlanVO.setTripList(JsonUtils.read(runPlanDraft.getTrips(), + JsonUtils.getCollectionType(List.class, RunPlanTripVO.class))); + } else { + runPlanVO.setTripList(new ArrayList<>()); } + return runPlanVO; + } } diff --git a/src/main/java/club/joylink/rtss/simulation/cbtc/ATP/ground/AtpSectionService.java b/src/main/java/club/joylink/rtss/simulation/cbtc/ATP/ground/AtpSectionService.java index 202c1969e..86b521aa9 100644 --- a/src/main/java/club/joylink/rtss/simulation/cbtc/ATP/ground/AtpSectionService.java +++ b/src/main/java/club/joylink/rtss/simulation/cbtc/ATP/ground/AtpSectionService.java @@ -9,15 +9,14 @@ import club.joylink.rtss.simulation.cbtc.data.map.Signal; import club.joylink.rtss.simulation.cbtc.data.map.Switch; import club.joylink.rtss.simulation.cbtc.data.support.SectionPosition; import club.joylink.rtss.simulation.cbtc.data.vr.VirtualRealityTrain; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; -import org.springframework.util.CollectionUtils; - import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Set; import java.util.stream.Collectors; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; /** * 地面ATP逻辑循环 @@ -26,226 +25,235 @@ import java.util.stream.Collectors; @Component public class AtpSectionService { - /** - * 收集列车接近信号机消息并发送给CI - */ - public void changeSignalModeByTrainApproach(Simulation simulation, - List onlineTrainList, - Map> trainAtpSectionMap) { - List signalList = simulation.getRepository().getSignalList(); - signalList.forEach(signal -> { - int a = 0; // 列车接近信号消息:0-无车接近,1-通信车接近,2-非通信车接近 - for (VirtualRealityTrain train : onlineTrainList) { - List
atpSectionList = trainAtpSectionMap.get(train.getGroupNumber()); - List
physicalList = this.convert2PhysicalSectionList(atpSectionList); - if (train.isCommunicable() && signal.containsApproachAtpSection(atpSectionList)) { //存在通信车接近,继续 - a = 1; - } else if (!train.isCommunicable() && signal.containsApproachPhysicalSection(physicalList)) { //存在非通信车接近,结束 - a = 2; - break; - } - } - if (1 == a) { // 只有通信车接近 - if(!signal.getSignalModel().getGuideAspect().equals(signal.getAspect())) { - signal.changeToCbtcMode(); - } - } else if (2 == a) { // 有非通信车接近 - signal.changeToBackupMode(); - } - signal.updateApproachLock();//更新信号机接近锁闭状态 - }); - } + /** + * 收集列车接近信号机消息并发送给CI + */ + public void changeSignalModeByTrainApproach(Simulation simulation, + List onlineTrainList, + Map> trainAtpSectionMap) { + List signalList = simulation.getRepository().getSignalList(); + signalList.forEach(signal -> { + int a = 0; // 列车接近信号消息:0-无车接近,1-通信车接近,2-非通信车接近 + for (VirtualRealityTrain train : onlineTrainList) { + List
atpSectionList = trainAtpSectionMap.get(train.getGroupNumber()); + List
physicalList = this.convert2PhysicalSectionList(atpSectionList); + if (train.isCommunicable() && signal.containsApproachAtpSection( + atpSectionList)) { //存在通信车接近,继续 + a = 1; + } else if (!train.isCommunicable() && signal.containsApproachPhysicalSection( + physicalList)) { //存在非通信车接近,结束 + a = 2; + break; + } + } + if (1 == a) { // 只有通信车接近 + if (!signal.getSignalModel().getGuideAspect().equals(signal.getAspect())) { + signal.changeToCbtcMode(); + } + } else if (2 == a) { // 有非通信车接近 + signal.changeToBackupMode(); + } + signal.updateApproachLock();//更新信号机接近锁闭状态 + }); + } - private List
convert2PhysicalSectionList(List
sectionList) { - List
physicalList = new ArrayList<>(); - sectionList.forEach(section -> { - if (section.isPhysical()) { - physicalList.add(section); - } else if (section.isLogicSection()) { - if (!physicalList.contains(section.getParent())) { - physicalList.add(section.getParent()); - } - } - }); - return physicalList; - } + private List
convert2PhysicalSectionList(List
sectionList) { + List
physicalList = new ArrayList<>(); + sectionList.forEach(section -> { + if (section.isPhysical()) { + physicalList.add(section); + } else if (section.isLogicSection()) { + if (!physicalList.contains(section.getParent())) { + physicalList.add(section.getParent()); + } + } + }); + return physicalList; + } - /** - * ATP区段列车占用检测并设置 - * - * @param simulation - * @param train - * @return - */ - public List
atpSectionOccupyCheck(Simulation simulation, VirtualRealityTrain train) { - List
atpSectionList = new ArrayList<>(); - boolean right = train.isRight(); - SectionPosition trainHeadPosition = train.getHeadPosition(); - SimulationDataRepository repository = simulation.getRepository(); - MapConfig config = repository.getConfig(); - boolean switchSingleHandle = config.isSwitchSingleHandle(); - boolean isRailway = config.isRailway(); // 大铁逻辑 - if (train.isCommunicable() || isRailway) { // 通信车占用 或者 大铁配置 - // 车尾位置追加不确定性距离:(速度*2)m - SectionPosition trainTailPosition = CalculateService - .calculateNextPositionByStartAndLen(trainHeadPosition, !right, train.getLen() + train.getSpeed() * 2, false); - atpSectionList = CalculateService.getAtpSections(trainHeadPosition, trainTailPosition, - right, switchSingleHandle); - List
removes = new ArrayList<>(); - for (Section atpSection : atpSectionList) { - Section axle = atpSection; - Section parent = atpSection.getParent(); - if (parent != null) { - axle = parent; - } - if (axle.isAxleCounter() && (!axle.isNctOccupied() || Section.AxleFault.FAULT.equals(axle.getFault()))) { - removes.add(atpSection); - continue; - } + /** + * ATP区段列车占用检测并设置 + * + * @param simulation + * @param train + * @return + */ + public List
atpSectionOccupyCheck(Simulation simulation, VirtualRealityTrain train) { + List
atpSectionList = new ArrayList<>(); + boolean right = train.isRight(); + SectionPosition trainHeadPosition = train.getHeadPosition(); + SimulationDataRepository repository = simulation.getRepository(); + MapConfig config = repository.getConfig(); + boolean switchSingleHandle = config.isSwitchSingleHandle(); + boolean isRailway = config.isRailway(); // 大铁逻辑 + if (train.isCommunicable() || isRailway) { // 通信车占用 或者 大铁配置 + // 车尾位置追加不确定性距离:(速度*2)m + SectionPosition trainTailPosition = CalculateService + .calculateNextPositionByStartAndLen(trainHeadPosition, !right, + train.getLen() + train.getSpeed() * 2, false); + atpSectionList = CalculateService.getAtpSections(trainHeadPosition, trainTailPosition, + right, switchSingleHandle); + List
removes = new ArrayList<>(); + for (Section atpSection : atpSectionList) { + Section axle = atpSection; + Section parent = atpSection.getParent(); + if (parent != null) { + axle = parent; + } + if (axle.isAxleCounter() && (!axle.isNctOccupied() || Section.AxleFault.FAULT.equals( + axle.getFault()))) { + removes.add(atpSection); + continue; + } // atpSection.communicateTrainOccupy(right); - } - if (!removes.isEmpty()) { - atpSectionList.removeAll(removes); - } - } else { // 非通信车 - List
sectionList = repository.queryTrainOccupySectionList(train.getGroupNumber()); - if (!CollectionUtils.isEmpty(sectionList)) { - for (Section section : sectionList) { - if (section.isSwitchAxleCounterSection()) { - Section switchSection = section.getLogicList().get(0); - atpSectionList.addAll(switchSection.getSwitchAxleSectionsBySwitchPosition()); - continue; - } - if (CollectionUtils.isEmpty(section.getLogicList())) { - atpSectionList.add(section); - } else { - atpSectionList.addAll(section.getLogicList()); - } - } - } - //将列车占压的物理区段及其关联的逻辑区段全部设为非通信车占用 + } + if (!removes.isEmpty()) { + atpSectionList.removeAll(removes); + } + } else { // 非通信车 + List
sectionList = repository.queryTrainOccupySectionList(train.getGroupNumber()); + if (!CollectionUtils.isEmpty(sectionList)) { + for (Section section : sectionList) { + if (section.isSwitchAxleCounterSection()) { + Section switchSection = section.getLogicList().get(0); + atpSectionList.addAll(switchSection.getSwitchAxleSectionsBySwitchPosition()); + continue; + } + if (CollectionUtils.isEmpty(section.getLogicList())) { + atpSectionList.add(section); + } else { + atpSectionList.addAll(section.getLogicList()); + } + } + } + //将列车占压的物理区段及其关联的逻辑区段全部设为非通信车占用 // atpSectionList.forEach(atpSection -> atpSection.nonCommunicateTrainOccupy(right)); - } - return atpSectionList; } + return atpSectionList; + } - /** - * ARB检测 - * - * @param simulation - * @param section - * @param sectionList - */ - public void sectionARBCheck(Simulation simulation, Section section, List
sectionList) { - //目前ARB故障才会导致ARB判定 - if (Section.AxleFault.ARB.equals(section.getFault()) && section.getVirtualAxleCounter().isOccupy()) { - if (!sectionList.contains(section)) { - section.judgeAsARB(); - } else { - section.setFault(Section.AxleFault.FAULT); - } - } else if (Section.AxleFault.FAULT.equals(section.getFault()) && section.getVirtualAxleCounter().isOccupy()) { - section.judgeAsNctOccupied(simulation); - } - if (/*!section.isInvalid() &&*/ section.isNctOccupied()) { - if (!sectionList.contains(section)) { - section.judgeAsNctOccupied(simulation); - } - } - //ARB故障恢复判断 - if (Section.AxleFault.ARB.equals(section.getFault()) && !section.getVirtualAxleCounter().isOccupy()) { - Section.AxleFault.ARB.fix(section); - } + /** + * ARB检测 + * + * @param simulation + * @param section + * @param sectionList + */ + public void sectionARBCheck(Simulation simulation, Section section, List
sectionList) { + //目前ARB故障才会导致ARB判定 + if (Section.AxleFault.ARB.equals(section.getFault()) && section.getVirtualAxleCounter() + .isOccupy()) { + if (!sectionList.contains(section)) { + section.judgeAsARB(); + } else { + section.setFault(Section.AxleFault.FAULT); + } + } else if (Section.AxleFault.FAULT.equals(section.getFault()) && section.getVirtualAxleCounter() + .isOccupy()) { + section.judgeAsNctOccupied(simulation); } + if (/*!section.isInvalid() &&*/ section.isNctOccupied()) { + section.judgeAsNctOccupied(simulation); + } + //ARB故障恢复判断 + if (Section.AxleFault.ARB.equals(section.getFault()) && !section.getVirtualAxleCounter() + .isOccupy()) { + Section.AxleFault.ARB.fix(section); + } + } - /** - * 获取非通信车可能存在的范围 - * - * @param simulation - * @param trainList - * @return - */ - public List
getTrainExistAxleSectionsUnderDelay(Simulation simulation, List trainList) { - List
list = new ArrayList<>(); - for (VirtualRealityTrain train : trainList) { - //只统计非通信车 - if (train.isCommunicable()) - continue; - boolean right = train.isRight(); - SectionPosition headPosition = train.getHeadPosition(); - float offset = 50; - SectionPosition head = CalculateService - .calculateNextPositionByStartAndLen(headPosition, right, offset, false); - // 考虑列车最大可能占用区间,用于判断ARB区段 - SectionPosition tail = CalculateService - .calculateNextPositionByStartAndLen(headPosition, - !right, train.getLen() + offset, false); - List
sectionList = CalculateService.getTrainOccupyAxleSection(head, tail, right); - if (!CollectionUtils.isEmpty(sectionList)) { - for (Section section : sectionList) { - if (!list.contains(section)) { - list.add(section); - } - } - } else { - log.warn(String.format("列车[%s]没有存在范围的计轴区段", - train.getGroupNumber())); - } + /** + * 获取非通信车可能存在的范围 + * + * @param simulation + * @param trainList + * @return + */ + public List
getTrainExistAxleSectionsUnderDelay(Simulation simulation, + List trainList) { + List
list = new ArrayList<>(); + for (VirtualRealityTrain train : trainList) { + //只统计非通信车 + if (train.isCommunicable()) { + continue; + } + boolean right = train.isRight(); + SectionPosition headPosition = train.getHeadPosition(); + float offset = 50; + SectionPosition head = CalculateService + .calculateNextPositionByStartAndLen(headPosition, right, offset, false); + // 考虑列车最大可能占用区间,用于判断ARB区段 + SectionPosition tail = CalculateService + .calculateNextPositionByStartAndLen(headPosition, + !right, train.getLen() + offset, false); + List
sectionList = CalculateService.getTrainOccupyAxleSection(head, tail, right); + if (!CollectionUtils.isEmpty(sectionList)) { + for (Section section : sectionList) { + if (!list.contains(section)) { + list.add(section); + } } - return list; + } else { + log.warn(String.format("列车[%s]没有存在范围的计轴区段", + train.getGroupNumber())); + } } + return list; + } - public void removeOfflineTrainOccupySections(Simulation simulation, List onlineTrainList) { - // 移除已经下线的列车占用区段数据 - SimulationDataRepository repository = simulation.getRepository(); - Set oldTOSKeyList = repository.queryTrainOccupySectionKeys(); - Set currentTrainCodeList = onlineTrainList.stream() - .map(VirtualRealityTrain::getGroupNumber) - .collect(Collectors.toSet()); - oldTOSKeyList.removeAll(currentTrainCodeList); - oldTOSKeyList.forEach(groupNumber -> { - List
sections = repository.queryTrainOccupySectionList(groupNumber); - sections.forEach(section -> { - section.getVirtualAxleCounter().clear(); - section.clearOccupy(); - }); - repository.deleteTrainOccupySectionList(groupNumber); - }); - } + public void removeOfflineTrainOccupySections(Simulation simulation, + List onlineTrainList) { + // 移除已经下线的列车占用区段数据 + SimulationDataRepository repository = simulation.getRepository(); + Set oldTOSKeyList = repository.queryTrainOccupySectionKeys(); + Set currentTrainCodeList = onlineTrainList.stream() + .map(VirtualRealityTrain::getGroupNumber) + .collect(Collectors.toSet()); + oldTOSKeyList.removeAll(currentTrainCodeList); + oldTOSKeyList.forEach(groupNumber -> { + List
sections = repository.queryTrainOccupySectionList(groupNumber); + sections.forEach(section -> { + section.getVirtualAxleCounter().clear(); + section.clearOccupy(); + }); + repository.deleteTrainOccupySectionList(groupNumber); + }); + } - /** - * isSwitchSingleHandle 为TRUE的情况下,获取区段列表 - * - * @param section 区段 - * @param right 列车行驶方向 - * @return 区段列表 - */ - private List
handleSingleSwitchPosition(Section section, boolean right) { - List
atpSectionList = new ArrayList<>(); - // 道岔列表 - List relSwitchList = section.getRelSwitchList(); - // 反位情况下 - Switch relSwitch = null; - if (relSwitchList.stream().anyMatch(Switch::isPosR)) { - relSwitch = relSwitchList.stream().filter(Switch::isPosR).findFirst().orElse(null); - } else { - relSwitch = relSwitchList.stream().filter(Switch::isPosN).findFirst().orElse(null); - //relSwitchList.forEach(relSwitch -> atpSectionList.addAll(relSwitch.getSectionsByPosition())); - } - if (relSwitch != null) { - // 反位前区段列表 - Section nextSection = relSwitch.getA(); - do { - atpSectionList.add(0, nextSection); - nextSection = nextSection.getNextRunningSectionOf(!right); - } while (nextSection.getRelSwitch() != null && relSwitchList.contains(nextSection.getRelSwitch())); - // 反位后区段列表 - nextSection = relSwitch.getA().getNextRunningSectionOf(right); - while (nextSection != null && relSwitchList.contains(nextSection.getRelSwitch())) { - atpSectionList.add(nextSection); - nextSection = nextSection.getNextRunningSectionOf(right); - } - } - return atpSectionList; + /** + * isSwitchSingleHandle 为TRUE的情况下,获取区段列表 + * + * @param section 区段 + * @param right 列车行驶方向 + * @return 区段列表 + */ + private List
handleSingleSwitchPosition(Section section, boolean right) { + List
atpSectionList = new ArrayList<>(); + // 道岔列表 + List relSwitchList = section.getRelSwitchList(); + // 反位情况下 + Switch relSwitch = null; + if (relSwitchList.stream().anyMatch(Switch::isPosR)) { + relSwitch = relSwitchList.stream().filter(Switch::isPosR).findFirst().orElse(null); + } else { + relSwitch = relSwitchList.stream().filter(Switch::isPosN).findFirst().orElse(null); + //relSwitchList.forEach(relSwitch -> atpSectionList.addAll(relSwitch.getSectionsByPosition())); } + if (relSwitch != null) { + // 反位前区段列表 + Section nextSection = relSwitch.getA(); + do { + atpSectionList.add(0, nextSection); + nextSection = nextSection.getNextRunningSectionOf(!right); + } while (nextSection.getRelSwitch() != null && relSwitchList.contains( + nextSection.getRelSwitch())); + // 反位后区段列表 + nextSection = relSwitch.getA().getNextRunningSectionOf(right); + while (nextSection != null && relSwitchList.contains(nextSection.getRelSwitch())) { + atpSectionList.add(nextSection); + nextSection = nextSection.getNextRunningSectionOf(right); + } + } + return atpSectionList; + } } diff --git a/src/main/java/club/joylink/rtss/simulation/cbtc/ATS/service/AtsTrainService.java b/src/main/java/club/joylink/rtss/simulation/cbtc/ATS/service/AtsTrainService.java index 3a9907a4d..c4e688b2a 100644 --- a/src/main/java/club/joylink/rtss/simulation/cbtc/ATS/service/AtsTrainService.java +++ b/src/main/java/club/joylink/rtss/simulation/cbtc/ATS/service/AtsTrainService.java @@ -11,7 +11,14 @@ import club.joylink.rtss.simulation.cbtc.Simulation; import club.joylink.rtss.simulation.cbtc.constant.TrainType; 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.MapElement; +import club.joylink.rtss.simulation.cbtc.data.map.Route; +import club.joylink.rtss.simulation.cbtc.data.map.Routing; +import club.joylink.rtss.simulation.cbtc.data.map.Section; +import club.joylink.rtss.simulation.cbtc.data.map.SectionRunPath; +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.StationPlan; import club.joylink.rtss.simulation.cbtc.data.plan.TripPlan; import club.joylink.rtss.simulation.cbtc.data.support.RoutePath; @@ -24,16 +31,20 @@ import club.joylink.rtss.simulation.cbtc.exception.SimulationExceptionType; import club.joylink.rtss.simulation.cbtc.onboard.ATP.ATPService; import club.joylink.rtss.simulation.cbtc.onboard.ATP.OnboardAtpApiService; import club.joylink.rtss.vo.client.operation.DriveParamVO; +import java.time.LocalTime; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.stream.Collectors; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; -import java.time.LocalTime; -import java.util.*; -import java.util.stream.Collectors; - /** * ATS列车服务 */ @@ -183,12 +194,12 @@ public class AtsTrainService { StationPlan stationPlan = planList.get(i); List routePaths = repository.queryRoutePathsByEndAndContainsSection(stationPlan.getSection(), phySection); if (!CollectionUtils.isEmpty(routePaths)) { - nextPlan = stationPlan; if (routePaths.get(0).isRight() != tripPlan.isRight()) { break; } - } else { - break; + nextPlan = stationPlan; +// } else { +// break; } } if (Objects.isNull(nextPlan)) { diff --git a/src/main/java/club/joylink/rtss/simulation/cbtc/CI/device/CiSignalControlService.java b/src/main/java/club/joylink/rtss/simulation/cbtc/CI/device/CiSignalControlService.java index a7eff5087..b76604dc6 100644 --- a/src/main/java/club/joylink/rtss/simulation/cbtc/CI/device/CiSignalControlService.java +++ b/src/main/java/club/joylink/rtss/simulation/cbtc/CI/device/CiSignalControlService.java @@ -5,6 +5,7 @@ import club.joylink.rtss.simulation.cbtc.constant.SignalAspect; import club.joylink.rtss.simulation.cbtc.data.map.Signal; import club.joylink.rtss.simulation.cbtc.data.vr.VirtualRealitySignal; import club.joylink.rtss.simulation.cbtc.device.virtual.VirtualRealityDeviceService; +import java.util.Objects; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -22,10 +23,10 @@ public class CiSignalControlService { * @return */ private boolean couldOpenLogicAspect(Signal signal, SignalAspect aspect) { - if(signal.getSignalModel().getGuideAspect().equals(aspect)) { + if (Objects.equals(signal.getSignalModel().getGuideAspect(), aspect)) { return false; } - if (signal.getSignalModel().getDefaultAspect().equals(aspect)) { + if (Objects.equals(signal.getSignalModel().getDefaultAspect(), aspect)) { return true; } // else if (aspect.equals(signal.getSignalModel().getGuideAspect()) && signal.isHigherThanGuideLevel()) { 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 89632d387..14b526b2e 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 @@ -3,24 +3,66 @@ package club.joylink.rtss.simulation.cbtc.build; import club.joylink.rtss.constants.BusinessConsts; import club.joylink.rtss.exception.BusinessExceptionAssertEnum; import club.joylink.rtss.simulation.cbtc.constant.SignalModel; -import club.joylink.rtss.simulation.cbtc.data.map.*; +import club.joylink.rtss.simulation.cbtc.data.map.AutoSignal; +import club.joylink.rtss.simulation.cbtc.data.map.Catenary; +import club.joylink.rtss.simulation.cbtc.data.map.DirectionRod; +import club.joylink.rtss.simulation.cbtc.data.map.DisStation; +import club.joylink.rtss.simulation.cbtc.data.map.ESP; +import club.joylink.rtss.simulation.cbtc.data.map.MapElement; +import club.joylink.rtss.simulation.cbtc.data.map.PSD; +import club.joylink.rtss.simulation.cbtc.data.map.Responder; +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.Server; +import club.joylink.rtss.simulation.cbtc.data.map.Signal; +import club.joylink.rtss.simulation.cbtc.data.map.Stand; +import club.joylink.rtss.simulation.cbtc.data.map.Station; +import club.joylink.rtss.simulation.cbtc.data.map.Switch; +import club.joylink.rtss.simulation.cbtc.data.map.ZC; import club.joylink.rtss.simulation.cbtc.data.support.SectionPosition; import club.joylink.rtss.simulation.cbtc.data.support.StationTurnBackStrategyOption; -import club.joylink.rtss.simulation.cbtc.data.vr.*; -import club.joylink.rtss.vo.map.MapCISwitchVO; +import club.joylink.rtss.simulation.cbtc.data.vr.VirtualRealityDevice; +import club.joylink.rtss.simulation.cbtc.data.vr.VirtualRealityGate; +import club.joylink.rtss.simulation.cbtc.data.vr.VirtualRealityPsl; +import club.joylink.rtss.simulation.cbtc.data.vr.VirtualRealityScreenDoor; +import club.joylink.rtss.simulation.cbtc.data.vr.VirtualRealitySectionAxleCounter; +import club.joylink.rtss.simulation.cbtc.data.vr.VirtualRealitySignal; +import club.joylink.rtss.simulation.cbtc.data.vr.VirtualRealitySwitch; +import club.joylink.rtss.simulation.cbtc.data.vr.VirtualRealityTrain; import club.joylink.rtss.vo.map.MapGraphDataNewVO; import club.joylink.rtss.vo.map.MapVO; import club.joylink.rtss.vo.map.RealLineConfigVO; -import club.joylink.rtss.vo.map.graph.*; +import club.joylink.rtss.vo.map.graph.MapDirectionRodVO; +import club.joylink.rtss.vo.map.graph.MapESPVO; +import club.joylink.rtss.vo.map.graph.MapPSDVO; +import club.joylink.rtss.vo.map.graph.MapPowerLineVO; +import club.joylink.rtss.vo.map.graph.MapResponderVO; +import club.joylink.rtss.vo.map.graph.MapSectionNewVO; +import club.joylink.rtss.vo.map.graph.MapSignalNewVO; +import club.joylink.rtss.vo.map.graph.MapStationNewVO; +import club.joylink.rtss.vo.map.graph.MapStationStandNewVO; +import club.joylink.rtss.vo.map.graph.MapSwitchVO; +import club.joylink.rtss.vo.map.graph.MapTrainModelVO; +import club.joylink.rtss.vo.map.graph.MapTrainVO; +import club.joylink.rtss.vo.map.graph.MapTurnBackStrategyVO; +import club.joylink.rtss.vo.map.graph.MapZcVO; import club.joylink.rtss.vo.map.logic.MapDisStationNewVO; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.Set; +import java.util.function.Function; +import java.util.stream.Collectors; import lombok.extern.slf4j.Slf4j; import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; -import java.util.*; -import java.util.function.Function; -import java.util.stream.Collectors; - /** * 地图设备校验/构建器 */ @@ -289,22 +331,22 @@ public class MapDeviceBuilder { .filter(mapElement -> Objects.equals(mapElement.getDeviceType(), MapElement.DeviceType.STATION)) .map(mapElement -> ((Station) mapElement)) .collect(Collectors.toList()); - stations.forEach(station -> { - if (station.isDepot()) { // 是车辆段/停车场 - if (CollectionUtils.isEmpty(station.getTransferList())) { - errMsgList.add(String.format("车站[%s(%s)]是停车场/车辆段,却没有找到任何转换轨", - station.getName(), station.getCode())); - } - } else if (station.isTurnBack()) {//是折返站 - if (CollectionUtils.isEmpty(station.getTurnBackList())) { - errMsgList.add(String.format("车站[%s(%s)]是折返站,却没有任何折返区段关联", - station.getName(), station.getCode())); - } -// if (CollectionUtils.isEmpty(station.getTbStrategyMap())) { -// errMsgList.add(String.format("车站[%s(%s)]是折返站,却没有折返策略")); +// stations.forEach(station -> { +// if (station.isDepot()) { // 是车辆段/停车场 +// if (CollectionUtils.isEmpty(station.getTransferList())) { +// errMsgList.add(String.format("车站[%s(%s)]是停车场/车辆段,却没有找到任何转换轨", +// station.getName(), station.getCode())); // } - } - }); +// } else if (station.isTurnBack()) {//是折返站 +// if (CollectionUtils.isEmpty(station.getTurnBackList())) { +// errMsgList.add(String.format("车站[%s(%s)]是折返站,却没有任何折返区段关联", +// station.getName(), station.getCode())); +// } +//// if (CollectionUtils.isEmpty(station.getTbStrategyMap())) { +//// errMsgList.add(String.format("车站[%s(%s)]是折返站,却没有折返策略")); +//// } +// } +// }); } /** @@ -1040,6 +1082,10 @@ public class MapDeviceBuilder { if (section.isStandTrack() && !section.isNormalStandTrack()) { errMsgList.add(String.format("区段[%s]不是正常站台的站台轨,却设置了站台轨属性", section.debugStr())); } + //为了兼容中航的奇葩沙盘 + if (section.isTransferTrack() && section.isTurnBackTrack()) { + continue; + } if (section.isTransferTrack() && (section.getStation() == null || !section.getStation().isDepot())) { errMsgList.add(String.format("区段[%s]所属车站不是车辆段/停车场车站,却设置了转换轨属性", section.debugStr())); } diff --git a/src/main/java/club/joylink/rtss/simulation/cbtc/device/real/udp/SandTableTrainController.java b/src/main/java/club/joylink/rtss/simulation/cbtc/device/real/udp/SandTableTrainController.java index 728655169..90c1e97ff 100644 --- a/src/main/java/club/joylink/rtss/simulation/cbtc/device/real/udp/SandTableTrainController.java +++ b/src/main/java/club/joylink/rtss/simulation/cbtc/device/real/udp/SandTableTrainController.java @@ -6,6 +6,7 @@ import club.joylink.rtss.entity.MapDataExample; import club.joylink.rtss.entity.MapDataWithBLOBs; import club.joylink.rtss.simulation.cbtc.GroupSimulationService; import club.joylink.rtss.simulation.cbtc.Simulation; +import club.joylink.rtss.simulation.cbtc.device.real.udp.ngy.service.NgyTrainServiceImpl; import club.joylink.rtss.simulation.cbtc.device.real.udp.sr.service.SrTrainServiceImpl; import club.joylink.rtss.simulation.cbtc.device.real.udp.thailand.service.ThailandTrainServiceImpl; import club.joylink.rtss.util.JsonUtils; @@ -26,6 +27,8 @@ public class SandTableTrainController { private ThailandTrainServiceImpl thailandTrainService; @Autowired private SrTrainServiceImpl srTrainService; + @Autowired + private NgyTrainServiceImpl ngyTrainService; @PutMapping("/{simulationId}/control") public void control(@PathVariable String simulationId, String groupNumber, boolean right, @@ -38,6 +41,9 @@ public class SandTableTrainController { case ProjectCode.SR_SANDBOX: srTrainService.controlTrain(simulationId, groupNumber, right, speed); break; + case ProjectCode.NGY_SAND_TABLE: + ngyTrainService.controlTrain(simulationId, groupNumber, right, speed); + break; default: } } diff --git a/src/main/java/club/joylink/rtss/simulation/cbtc/device/real/udp/UDPClient.java b/src/main/java/club/joylink/rtss/simulation/cbtc/device/real/udp/UDPClient.java index 3fcc613f6..d690f9e87 100644 --- a/src/main/java/club/joylink/rtss/simulation/cbtc/device/real/udp/UDPClient.java +++ b/src/main/java/club/joylink/rtss/simulation/cbtc/device/real/udp/UDPClient.java @@ -11,7 +11,6 @@ import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.DatagramPacket; import io.netty.channel.socket.nio.NioDatagramChannel; import java.net.InetSocketAddress; -import java.time.LocalDateTime; import java.util.concurrent.ConcurrentLinkedQueue; import lombok.Getter; import lombok.extern.slf4j.Slf4j; @@ -60,7 +59,6 @@ public class UDPClient implements ApplicationRunner { public void write(InetSocketAddress addr, byte[] msg) { if (msg != null) { msgQueue.add(new Msg(addr, msg)); - System.out.println(LocalDateTime.now()); } } diff --git a/src/main/java/club/joylink/rtss/simulation/cbtc/device/real/udp/handler/UDPMessageHandler.java b/src/main/java/club/joylink/rtss/simulation/cbtc/device/real/udp/handler/UDPMessageHandler.java index 1df8d60f8..1b30daadb 100644 --- a/src/main/java/club/joylink/rtss/simulation/cbtc/device/real/udp/handler/UDPMessageHandler.java +++ b/src/main/java/club/joylink/rtss/simulation/cbtc/device/real/udp/handler/UDPMessageHandler.java @@ -5,21 +5,30 @@ import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.SimpleChannelInboundHandler; import io.netty.channel.socket.DatagramPacket; +import java.net.InetSocketAddress; +import java.util.HashMap; +import java.util.Map; +import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import java.net.InetSocketAddress; - +@Slf4j @Component public class UDPMessageHandler extends SimpleChannelInboundHandler { @Autowired private UDPRealDeviceThread udpRealDeviceThread; + Map map = new HashMap<>(); + @Override protected void channelRead0(ChannelHandlerContext ctx, DatagramPacket datagramPacket) { InetSocketAddress sender = datagramPacket.sender(); String ip = sender.getHostString(); int port = sender.getPort(); + long time = System.currentTimeMillis(); + map.putIfAbsent(port, time); + log.info("{}::{}",port, time - map.get(port)); + map.put(port, time); ByteBuf content = datagramPacket.content(); udpRealDeviceThread.handleData(ip, port, content); } diff --git a/src/main/java/club/joylink/rtss/simulation/cbtc/device/real/udp/ngy/service/NgySectionServiceImpl.java b/src/main/java/club/joylink/rtss/simulation/cbtc/device/real/udp/ngy/service/NgySectionServiceImpl.java index be555c039..be106c36f 100644 --- a/src/main/java/club/joylink/rtss/simulation/cbtc/device/real/udp/ngy/service/NgySectionServiceImpl.java +++ b/src/main/java/club/joylink/rtss/simulation/cbtc/device/real/udp/ngy/service/NgySectionServiceImpl.java @@ -33,6 +33,30 @@ public class NgySectionServiceImpl implements UDPRealDeviceService { @Override public void run(Simulation simulation, UDPLowConfig udpLowConfig, RealDeviceConfig realDevice) { +// // TODO: 2023/7/5 模拟计轴占压数据 +// List trainList = simulation.getRepository().getOnlineTrainList(); +// LocalDateTime now = LocalDateTime.now(); +// for (VirtualRealityTrain train : trainList) { +// LocalDateTime time = map.computeIfAbsent(train, K -> now.plusSeconds(7)); +// Section section = train.getHeadPosition().getSection(); +// VirtualRealitySectionAxleCounter currentAxle = section.findAxle(); +// if (!train.isStop() && !now.isBefore(time)) { +// Section nextSection = section.getNextRunningSectionOf(train.isRight()); +// if (nextSection == null) { +// continue; +// } +// VirtualRealitySectionAxleCounter nextAxle = nextSection.findAxle(); +// if (nextAxle != currentAxle) { +// nextAxle.occupied(train.isRight()); +// currentAxle.setOccupy(false); +// } +// if (section.isFunctionTrack()) { +// map.put(train, time.plusSeconds(7)); +// } else { +// map.put(train, time.plusSeconds(2)); +// } +// } +// } } @Override @@ -71,11 +95,11 @@ public class NgySectionServiceImpl implements UDPRealDeviceService { config.setTimesOfRelease(0); axle.setOccupy(true); } else if (n == 85) { -// config.setTimesOfRelease(config.getTimesOfRelease() + 1); -// if (config.getTimesOfRelease() > 2) { //连续3次该计轴都是无占用状态,才视为确实无占用 - config.setTimesOfRelease(0); - axle.clear(); -// } + config.setTimesOfRelease(config.getTimesOfRelease() + 1); + if (config.getTimesOfRelease() > 1) { //连续2次该计轴都是无占用状态,才视为确实无占用 + config.setTimesOfRelease(0); + axle.clear(); + } } } } diff --git a/src/main/java/club/joylink/rtss/simulation/cbtc/device/real/udp/ngy/service/NgyTrainServiceImpl.java b/src/main/java/club/joylink/rtss/simulation/cbtc/device/real/udp/ngy/service/NgyTrainServiceImpl.java index 329e429ca..bd4d35091 100644 --- a/src/main/java/club/joylink/rtss/simulation/cbtc/device/real/udp/ngy/service/NgyTrainServiceImpl.java +++ b/src/main/java/club/joylink/rtss/simulation/cbtc/device/real/udp/ngy/service/NgyTrainServiceImpl.java @@ -21,10 +21,10 @@ import club.joylink.rtss.simulation.cbtc.device.real.udp.UDPClient; import club.joylink.rtss.simulation.cbtc.device.real.udp.UDPLowConfig; import club.joylink.rtss.simulation.cbtc.device.real.udp.UDPRealDeviceService; import club.joylink.rtss.simulation.cbtc.device.real.udp.config.SandTableSectionConfig; +import club.joylink.rtss.simulation.cbtc.device.real.udp.config.SandTableSectionConfigVO; import club.joylink.rtss.simulation.cbtc.device.real.udp.config.SandTableTrainConfig; import club.joylink.rtss.simulation.cbtc.onboard.ATP.ATPService; import club.joylink.rtss.simulation.cbtc.robot.SimulationRobotService; -import club.joylink.rtss.vo.client.project.thailand.ThailandSectionConfigVO; import io.netty.buffer.ByteBuf; import java.time.LocalDateTime; import java.util.Objects; @@ -32,6 +32,7 @@ import java.util.Optional; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import org.springframework.util.StringUtils; @Slf4j @Service @@ -99,6 +100,11 @@ public class NgyTrainServiceImpl implements UDPRealDeviceService { udpClient.write(udpLowConfig.getAddr(), data); //清除状态 config.updateHeadSection(null); + //设置停站时间 + simulation.getRepository().getStandList().forEach(stand -> { + stand.setParkingTime(10); + stand.setParkingAlwaysValid(true); + }); } @Override @@ -163,10 +169,11 @@ public class NgyTrainServiceImpl implements UDPRealDeviceService { if (previousSection != null && !previousSection.isOccupied()) { delayOfNano = (long) (sectionConfig.getConfigVO().getTailDelayTime() * rate); } - } else { //未设置则认为车头占压即刻停车 - delayOfNano = 0L; + } else { //未设置 + delayOfNano = (long) (0 * rate); } if (delayOfNano != null) { + System.out.printf("设置延时%s%d%n", headSection.getName(), delayOfNano); config.setTimeOfArriveStopPoint(now.plusNanos(delayOfNano)); } } @@ -179,11 +186,11 @@ public class NgyTrainServiceImpl implements UDPRealDeviceService { if (stopPosition != null && stopPosition.getSection().equals(headSection)) { train.setHeadPosition(stopPosition); } else { - float offset = right ? headSection.getMaxOffset() : 0; + float offset = headSection.getEndOffsetByDirection(right); train.setHeadPosition(new SectionPosition(headSection, offset)); } } - //更新速度。由于沙盘对延时要求很高,机器人驾驶逻辑频率有点低,所以选择不利用机器人驾驶的逻辑 + if (config.getManualGear() != null) { return; } @@ -193,6 +200,22 @@ public class NgyTrainServiceImpl implements UDPRealDeviceService { return; } } + // 列车停站判断调头 + if (train.isParkingAt()) { + TrainInfo trainInfo = simulation.getRepository() + .findSupervisedTrainByGroup(train.getGroupNumber()); + if (trainInfo != null) { + if (StringUtils.hasText(trainInfo.getEstimatedArriveStandTrack())) { + Section target = simulation.getRepository() + .getByCode(trainInfo.getEstimatedArriveStandTrack(), Section.class); + if (CalculateService.isTargetSectionOnDirectionExist(headSection, !right, target) + && !Objects.equals(target, headSection)) { + atpService.turnDirectionImmediately(train); + } + } + } + } + //更新速度。由于沙盘对延时要求很高,机器人驾驶逻辑频率有点低,所以选择不利用机器人驾驶的逻辑 if (stopPosition != null) { Float distance = CalculateService.calculateDistance(train.getHeadPosition(), stopPosition, right, false); @@ -206,14 +229,6 @@ public class NgyTrainServiceImpl implements UDPRealDeviceService { train.setSpeed(lowSpeed); return; } - if (stopPosition.getSection().isStandTrack()) { - Section stopPreviousSection = stopPosition.getSection().getNextRunningSectionOf(!right); - if (stopPreviousSection != null && Objects.equals(stopPreviousSection.findAxle(), - headSection.findAxle())) { //当前车头在站台轨的前一个计轴区段 - train.setSpeed(lowSpeed); - return; - } - } train.setSpeed(highSpeed); } else { train.setSpeed(0); @@ -258,7 +273,7 @@ public class NgyTrainServiceImpl implements UDPRealDeviceService { gear = (int) Math.ceil(speedKmPh / 10); gear = Math.max(1, gear); } - if (train.isRight()) { //档位1-5是正向,6-10是反向 + if (!train.isRight()) { //档位1-5是正向,6-10是反向 gear += 5; } } @@ -276,96 +291,39 @@ public class NgyTrainServiceImpl implements UDPRealDeviceService { /** * 此方法用于调试,调试完成后方法内的数据请保存到项目设备配置 */ - public void fill(Section section, ThailandSectionConfigVO configVO) { + public void fill(Section section, SandTableSectionConfigVO configVO) { Float headDelayTime = null; Float tailDelayTime = null; - if (section.isStandTrack()) { //站台轨默认为车尾出清立即停车 - headDelayTime = 5f; + if (section.isFunctionTrack()) { + if (section.isStandTrack()) { + tailDelayTime = 1f; + } else { + tailDelayTime = 0f; + } + } else { + headDelayTime = 2f; } switch (section.getCode()) { - case "T233": //X302G - headDelayTime = 7.3f; + case "T68": // 43G + tailDelayTime = 1.4f; break; - case "T232": //X303G - headDelayTime = 6.5f; + case "T62": //37G + tailDelayTime = 0.8f; break; - case "T231": //X304G - headDelayTime = 5.5f; + case "T35": //9G + tailDelayTime = 1.3f; break; - case "T178": //4站-3G - headDelayTime = 5.2f; + case "T33": //5G + tailDelayTime = 0.9f; break; - case "T177": //4站-IG - headDelayTime = 5.4f; + case "T5": //8G + tailDelayTime = 0.8f; break; - case "T175": //4站-IIG - headDelayTime = 6.6f; + case "T7": //12G + tailDelayTime = 0.6f; break; - case "T174": //4站-4G - headDelayTime = 6.2f; - break; - case "T176": //4站-6G - headDelayTime = 5.9f; - break; - case "T179": //4站-5G - headDelayTime = 6.5f; - break; - case "T123": //3站-3G - headDelayTime = 5.2f; - break; - case "T122": //3站-IG - headDelayTime = 5.3f; - break; - case "T121": //3站-IIG - headDelayTime = 5.9f; - break; - case "T120": //3站-4G - headDelayTime = 5.5f; - break; - case "T78": //2站-IG - headDelayTime = 5.5f; - break; - case "T77": //2站-IIG - headDelayTime = 5.9f; - break; - case "T76": //2站-4G - headDelayTime = 5.7f; - break; - case "T22": //1站-1G - headDelayTime = 5.3f; - break; - case "T23": //1站-IIG - headDelayTime = 5.1f; - break; - case "T27": //1站-5G - headDelayTime = 4.9f; - break; - case "T26": //1站-3G - headDelayTime = 4.8f; - break; - case "T24": //1站-4G - headDelayTime = 5.1f; - break; - case "T25": //1站-6G - headDelayTime = 5.1f; - break; - case "T145": //QX04 - headDelayTime = 1.9f; - break; - case "T146": //QS04 - headDelayTime = 2.7f; - break; - case "T104": //QX03 - tailDelayTime = 0f; - break; - case "T105": //QS03 - tailDelayTime = 0f; - break; - case "T62": //QX02 - tailDelayTime = 0f; - break; - case "T63": //QS02 - tailDelayTime = 0f; + case "T45": //24G + tailDelayTime = 0.8f; break; } configVO.setHeadDelayTime(headDelayTime); @@ -382,10 +340,10 @@ public class NgyTrainServiceImpl implements UDPRealDeviceService { atpService.turnDirectionImmediately(train); } train.setRobotTargetPosition(null); //终止机器人司机驾驶 - //加减速 - if (train.isEB()) { - return; - } +// //加减速 +// if (train.isEB()) { +// return; +// } atpService.changeGear(train, VirtualRealityTrain.Handwheel.MANUAL); int manualGear = speed / 10; config.setManualGear(manualGear); diff --git a/src/main/java/club/joylink/rtss/simulation/cbtc/robot/SimulationRobotService.java b/src/main/java/club/joylink/rtss/simulation/cbtc/robot/SimulationRobotService.java index 2517a20b1..b354c8f53 100644 --- a/src/main/java/club/joylink/rtss/simulation/cbtc/robot/SimulationRobotService.java +++ b/src/main/java/club/joylink/rtss/simulation/cbtc/robot/SimulationRobotService.java @@ -196,11 +196,11 @@ public class SimulationRobotService { doBreakMax(simulation, train); } } else if (train.isRobotNeedRun() && (train.isRMMode() - || train.isNRMMode())) { //CM应当根据推荐速度驾驶,待实现 + || train.isNRMMode())) { //CM应当根据推荐速度驾驶,待实现 VirtualRealityTrain linkTrain = train.getLinkTrain(); if (linkTrain == null) { Optional targetPositionOptional = calculateTargetPosition(simulation, - train); + train); targetPositionOptional.ifPresent(tp -> robotDrive(simulation, driver, train, tp)); } else { robotDrive(simulation, driver, train, train.getRobotTargetPosition()); @@ -256,7 +256,8 @@ public class SimulationRobotService { SignalAspect throughAspect = robotDriveParam.getThroughSignalAspect(); Section section = headPosition.getSection(); - if (throughSignal != null && !Objects.equals(section, throughSignal.getSection())) { //当车头与要越过的信号机不在同一区段 + if (throughSignal != null && !Objects.equals(section, + throughSignal.getSection())) { //当车头与要越过的信号机不在同一区段 throughSignal = null; throughAspect = null; robotDriveParam.setThrough(DriveParamVO.NO); @@ -268,40 +269,35 @@ public class SimulationRobotService { // 车头在正常的站台上 if (section.isNormalStandTrack() && !section.equals(train.getParkSection())) { //正常站台轨且未在此处停过车 // 如果计划停车区段为空或者计划停车区段中有包含当前区段 - if (CollectionUtils.isEmpty(plannedParkingSections) || plannedParkingSections.contains(section)) { + if (CollectionUtils.isEmpty(plannedParkingSections) || plannedParkingSections.contains( + section)) { SectionPosition stopPosition = section.buildStopPointPosition(right); - if (targetPosition == null || stopPosition.isAheadOf(targetPosition, right)) { + if (targetPosition == null || stopPosition.isAheadOf(targetPosition, !right)) { // 如果头部位置偏移小于停车点位置偏移,目标点为当前停车点 - if (headPosition.getOffset() < (section.getStopPointByDirection(right) + SimulationConstants.PARK_POINT_MAX_OFFSET)) { //防止意外开过站后无法发车 + if (headPosition.getOffset() < (section.getStopPointByDirection(right) + + SimulationConstants.PARK_POINT_MAX_OFFSET)) { //防止意外开过站后无法发车 targetPosition = stopPosition; } } } } - // 取禁止信号前停车位置与当前目标停车位置中更近的一个 - Signal signal = section.getSignalOf(right); - if (signal != null && !signal.isShunting()) { // 信号机不为调车信号机 - VirtualRealitySignal vrSignal = signal.getVirtualSignal(); - SectionPosition signalPosition = signal.getPosition(); - if (vrSignal != null && (i != 0 || signalPosition.isAheadOf(headPosition, right))) { //有实体信号机且列车未越过信号机 - if (Objects.equals(vrSignal.getAspect(), signal.getDefaultAspect()) //禁止信号 - || Objects.equals(vrSignal.getAspect(), signal.getGuideAspect())) { //引导信号 - if (!Objects.equals(signal, throughSignal) || !Objects.equals(vrSignal.getAspect(), throughAspect)) { - SectionPosition noPassPosition = CalculateService.calculateNextPositionByStartAndLen(signalPosition, !right, 2, true); - if (targetPosition == null || noPassPosition.isAheadOf(targetPosition, right)) { - targetPosition = noPassPosition; - } - } - } + targetPosition = updateTargetPositionOfSignal(headPosition, right, + throughSignal, throughAspect, section, i, targetPosition, train.isParkingAt()); + + Section tempSection = section.findNextRunningSectionBaseRealSwitch(right); + if (tempSection != null && tempSection.isOccupied()) { + SectionPosition newTP = CalculateService.calculateNextPositionByStartAndLen( + new SectionPosition(section, section.getEndOffsetByDirection(!right)), !right, 2, true); + if (targetPosition == null || newTP.isAheadOf(targetPosition, !right)) { + targetPosition = newTP; } } - if (targetPosition == null) { - if (selectedPosition != null && section.equals(selectedPosition.getSection())) { //不会有比选定位置更靠前的停车点了 + if (selectedPosition != null && section.equals( + selectedPosition.getSection())) { //不会有比选定位置更靠前的停车点了 targetPosition = selectedPosition; } else { - Section tempSection = section.findNextRunningSectionBaseRealSwitch(right); if (tempSection == null) { //到了轨道尽头,目标位置为尽头向内10m targetPosition = new SectionPosition(section, right ? section.getLen() - 10 : 10); } else { @@ -310,13 +306,13 @@ public class SimulationRobotService { } } else { if (selectedPosition != null) { - if (selectedPosition.isAheadOf(targetPosition, right)) { + if (selectedPosition.isAheadOf(targetPosition, !right)) { targetPosition = selectedPosition; } else { break; } } - if (selectedPosition != null && selectedPosition.isAheadOf(targetPosition, right)) { + if (selectedPosition != null && selectedPosition.isAheadOf(targetPosition, !right)) { targetPosition = selectedPosition; } else { @@ -329,7 +325,53 @@ public class SimulationRobotService { if (targetPosition == null) { //上方的区段遍历完后,即没有找到目标区段,也没有找到轨道尽头 targetPosition = new SectionPosition(section, right ? 0 : section.getMaxOffset()); } - return Optional.ofNullable(targetPosition); + return Optional.of(targetPosition); + } + + /** + * 获取以信号机为依据的目标位置 + * + * @param i 区段的索引 + * @return 如果计算出的targetPosition比参数中的更近,则返回新的,否则返回原来的 + */ + private SectionPosition updateTargetPositionOfSignal(SectionPosition headPosition, boolean right, + Signal throughSignal, SignalAspect throughAspect, Section section, int i, + SectionPosition targetPosition, boolean parking) { + Signal signal = section.getSignalOf(right); + if (signal == null || signal.isShunting()) { + return targetPosition; + } + VirtualRealitySignal vrSignal = signal.getVirtualSignal(); + SectionPosition signalPosition = signal.getPosition(); + if (vrSignal == null || (i == 0 && headPosition.isAheadOf(signalPosition, right))) { + //解释下||后面的条件,如果i!=0,则车头位置一定不可能在信号机前方,即i==0只是为了减少计算,对结果没有影响 + return targetPosition; + } + if (targetPosition != null && signalPosition.isAheadOf(targetPosition, right)) { + //只要目标位置没有越过信号机,则没必要一定和信号机保持2m距离 + return targetPosition; + } + if (!Objects.equals(vrSignal.getAspect(), signal.getDefaultAspect()) + && !Objects.equals(vrSignal.getAspect(), signal.getGuideAspect())) { //非禁止/引导信号 + return targetPosition; + } + if (Objects.equals(signal, throughSignal) + && Objects.equals(vrSignal.getAspect(), throughAspect)) { + return targetPosition; + } + if (parking && section.equals(headPosition.getSection())) { //避免停站结束后向前移动到信号机前 + return headPosition; + } + if (section.isFunctionTrack() || section.isParkingTrack()) { //如果无法越过信号机,则停在停车点而非信号机前 + return new SectionPosition(section, section.getStopPointByDirection(right)); + } + SectionPosition newPosition = CalculateService.calculateNextPositionByStartAndLen( + signalPosition, !right, 2, true); + if (targetPosition == null || newPosition.isAheadOf(targetPosition, !right)) { + return newPosition; + } else { + return targetPosition; + } } private void releaseEB(Simulation simulation, SimulationMember driver, diff --git a/src/main/java/club/joylink/rtss/vo/client/project/ProjectDeviceVO.java b/src/main/java/club/joylink/rtss/vo/client/project/ProjectDeviceVO.java index f5c779178..689a0b038 100644 --- a/src/main/java/club/joylink/rtss/vo/client/project/ProjectDeviceVO.java +++ b/src/main/java/club/joylink/rtss/vo/client/project/ProjectDeviceVO.java @@ -30,6 +30,10 @@ import club.joylink.rtss.simulation.cbtc.device.real.modbustcp.zjd.ZjdPsdConfig; import club.joylink.rtss.simulation.cbtc.device.real.modbustcp.zjd.ZjdPslConfig; import club.joylink.rtss.simulation.cbtc.device.real.udp.UDPClientConfig; import club.joylink.rtss.simulation.cbtc.device.real.udp.UDPLowConfig; +import club.joylink.rtss.simulation.cbtc.device.real.udp.config.SandTableSectionConfig; +import club.joylink.rtss.simulation.cbtc.device.real.udp.config.SandTableSignalConfig; +import club.joylink.rtss.simulation.cbtc.device.real.udp.config.SandTableSwitchConfig; +import club.joylink.rtss.simulation.cbtc.device.real.udp.config.SandTableTrainConfig; import club.joylink.rtss.simulation.cbtc.device.real.udp.sr.config.SrSectionConfig; import club.joylink.rtss.simulation.cbtc.device.real.udp.sr.config.SrSignalConfig; import club.joylink.rtss.simulation.cbtc.device.real.udp.sr.config.SrSwitchConfig; @@ -147,12 +151,43 @@ public class ProjectDeviceVO { case "GXSD": { return gxsdDeviceConfigConvert(voList); } + case ProjectCode.NGY_SAND_TABLE: { + return sandTableDeviceConfigConvert(voList); + } } } return list; } + private static List sandTableDeviceConfigConvert( + List voList) { + List list = new ArrayList<>(); + for (ProjectDeviceVO deviceVO : voList) { + switch (deviceVO.getType()) { + case UDP_LOW: + list.add(new UDPLowConfig(deviceVO)); + break; + case UDP_CLIENT: + list.add(new UDPClientConfig(deviceVO)); + break; + case SIGNAL: + list.add(new SandTableSignalConfig(deviceVO)); + break; + case SECTION: + list.add(new SandTableSectionConfig(deviceVO)); + break; + case SWITCH: + list.add(new SandTableSwitchConfig(deviceVO)); + break; + case TRAIN: + list.add(new SandTableTrainConfig(deviceVO)); + break; + } + } + return list; + } + private static List thailandSandboxDeviceConfigConvert( List voList) { List list = new ArrayList<>();