南昌工学院沙盘项目特殊改动

This commit is contained in:
joylink_zhangsai 2023-08-21 21:11:50 +08:00
parent 99ecac0318
commit 5634ab0a39
16 changed files with 1005 additions and 747 deletions

View File

@ -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.SignalAspect;
import club.joylink.rtss.simulation.cbtc.constant.SignalModel; import club.joylink.rtss.simulation.cbtc.constant.SignalModel;
import club.joylink.rtss.simulation.cbtc.data.CalculateService; 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.data.support.RoutePath;
import club.joylink.rtss.simulation.cbtc.exception.SimulationException; import club.joylink.rtss.simulation.cbtc.exception.SimulationException;
import club.joylink.rtss.simulation.cbtc.exception.SimulationExceptionType; 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.MapCiGenerateConfig;
import club.joylink.rtss.vo.map.MapRoutingSectionNewVO; import club.joylink.rtss.vo.map.MapRoutingSectionNewVO;
import club.joylink.rtss.vo.map.MapVO; 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.Getter;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; 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.CollectionUtils;
import org.springframework.util.StringUtils; 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 @Slf4j
@Service @Service
public class DraftMapCiDataGeneratorImpl implements DraftMapCiDataGenerator { public class DraftMapCiDataGeneratorImpl implements DraftMapCiDataGenerator {
@ -281,7 +312,7 @@ public class DraftMapCiDataGeneratorImpl implements DraftMapCiDataGenerator {
List<Signal> signalList = deviceMap.values().stream() List<Signal> signalList = deviceMap.values().stream()
.filter(mapElement -> mapElement.getDeviceType().equals(MapElement.DeviceType.SIGNAL)) .filter(mapElement -> mapElement.getDeviceType().equals(MapElement.DeviceType.SIGNAL))
.map(mapElement -> ((Signal) mapElement)) .map(mapElement -> ((Signal) mapElement))
.filter(signal -> !signal.getInterlockStation().isDepot()) // .filter(signal -> !signal.getInterlockStation().isDepot())
.collect(Collectors.toList()); .collect(Collectors.toList());
// 获取所有道岔 // 获取所有道岔
List<Switch> switchList = deviceMap.values().stream() List<Switch> switchList = deviceMap.values().stream()
@ -318,7 +349,7 @@ public class DraftMapCiDataGeneratorImpl implements DraftMapCiDataGenerator {
if (Objects.nonNull(autoSignal)) { if (Objects.nonNull(autoSignal)) {
autoSignalList.add(autoSignal); autoSignalList.add(autoSignal);
} }
} else if (signal.isProtectionSignal()) { } else if (signal.isProtectionSignal() || signal.isShunting2()) {
// 防护信号机生成进路 // 防护信号机生成进路
if (config.isLikeHa1()) { if (config.isLikeHa1()) {
generatedRouteList.addAll(this.generateRouteLikeHa1(signal, routeCodeGenerator, overlapMap, generatedRouteList.addAll(this.generateRouteLikeHa1(signal, routeCodeGenerator, overlapMap,
@ -1450,6 +1481,9 @@ public class DraftMapCiDataGeneratorImpl implements DraftMapCiDataGenerator {
case BW: case BW:
route.setAspect(SignalAspect.W); route.setAspect(SignalAspect.W);
break; break;
case YRW:
route.setAspect(SignalAspect.W);
break;
default: default:
throw BusinessExceptionAssertEnum.DATA_ERROR.exception(String.format("信号机[%s]型号[%s]不正确", throw BusinessExceptionAssertEnum.DATA_ERROR.exception(String.format("信号机[%s]型号[%s]不正确",
start.debugStr(), start.getSignalModel())); start.debugStr(), start.getSignalModel()));

View File

@ -1,14 +1,26 @@
package club.joylink.rtss.services.draftData; 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 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 lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils; import org.springframework.util.CollectionUtils;
import java.util.*;
import java.util.stream.Collectors;
/** /**
* 交路生成 * 交路生成
*/ */
@ -122,7 +134,7 @@ public class RoutingGenerator {
if (signal == null) { if (signal == null) {
Section base = section; Section base = section;
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++) {
Section next = base.getSectionOf(right); Section next = base.findNextRunningSectionBaseRealSwitch(right);
if (next == null) { // 可能到尽头了 if (next == null) { // 可能到尽头了
return; return;
} }

View File

@ -1188,8 +1188,8 @@ public class DeviceServiceImpl implements DeviceService {
section.setCreateTime(now); section.setCreateTime(now);
SandTableSectionConfigVO configVO = new SandTableSectionConfigVO(mapSectionNewVO.getCode(), SandTableSectionConfigVO configVO = new SandTableSectionConfigVO(mapSectionNewVO.getCode(),
mapSectionNewVO.getSrCode()); mapSectionNewVO.getSrCode());
section.setConfig(JsonUtils.writeValueAsString(configVO));
ngyFillTime(configVO, mapSectionNewVO); ngyFillTime(configVO, mapSectionNewVO);
section.setConfig(JsonUtils.writeValueAsString(configVO));
list.add(section); list.add(section);
} }
} }
@ -1213,7 +1213,8 @@ public class DeviceServiceImpl implements DeviceService {
private void ngyFillTime(SandTableSectionConfigVO configVO, MapSectionNewVO section) { private void ngyFillTime(SandTableSectionConfigVO configVO, MapSectionNewVO section) {
Float headDelayTime = null; Float headDelayTime = null;
Float tailDelayTime = null; Float tailDelayTime = null;
if (section.isStandTrack() || section.isReentryTrack() || section.isTransferTrack()) { if (section.isStandTrack() || section.isReentryTrack() || section.isTransferTrack()
|| section.isParkingTrack()) {
if (section.isStandTrack()) { if (section.isStandTrack()) {
tailDelayTime = 1f; tailDelayTime = 1f;
} else { } else {

View File

@ -280,7 +280,13 @@ public class PublishMapDataHandler {
MapGraphDataNewVO data = JsonUtils.read(map.getGraphData(), MapGraphDataNewVO.class); MapGraphDataNewVO data = JsonUtils.read(map.getGraphData(), MapGraphDataNewVO.class);
for (MapSectionNewVO section : data.getSectionList()) { for (MapSectionNewVO section : data.getSectionList()) {
if (section.getLengthFact() != null && section.getLengthFact() != 0) { 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)); map.setGraphData(JsonUtils.writeValueAsString(data));

View File

@ -18,10 +18,24 @@ import club.joylink.rtss.vo.AccountVO;
import club.joylink.rtss.vo.client.PageVO; import club.joylink.rtss.vo.client.PageVO;
import club.joylink.rtss.vo.client.runplan.RunPlanTripVO; import club.joylink.rtss.vo.client.runplan.RunPlanTripVO;
import club.joylink.rtss.vo.client.runplan.RunPlanVO; 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 club.joylink.rtss.vo.map.MapVO;
import com.github.pagehelper.Page; import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper; 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 lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@ -29,230 +43,258 @@ import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils; import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import java.util.*;
import java.util.stream.Collectors;
@Service @Service
@Slf4j @Slf4j
public class RunPlanRoutingService implements IRunPlanRoutingService { public class RunPlanRoutingService implements IRunPlanRoutingService {
@Autowired @Autowired
private RunPlanRoutingDAO runPlanRoutingDAO; private RunPlanRoutingDAO runPlanRoutingDAO;
@Autowired @Autowired
private RunPlanDraftDAO runPlanDraftDAO; private RunPlanDraftDAO runPlanDraftDAO;
@Autowired @Autowired
private IRunPlanRunlevelService planRunlevelService; private IRunPlanRunlevelService planRunlevelService;
@Autowired @Autowired
private IRunPlanParktimeService planParktimeService; private IRunPlanParktimeService planParktimeService;
@Autowired @Autowired
private IRunPlanUserConfigService planConfigService; private IRunPlanUserConfigService planConfigService;
@Autowired @Autowired
private IMapService iMapService; private IMapService iMapService;
@Transactional @Transactional
@Override @Override
public void createUserRouting(RunPlanRoutingVO routingVO) { public void createUserRouting(RunPlanRoutingVO routingVO) {
BusinessExceptionAssertEnum.DATA_ALREADY_EXIST.assertNotTrue(routingDataExist(routingVO), "交路数据重复"); BusinessExceptionAssertEnum.DATA_ALREADY_EXIST.assertNotTrue(routingDataExist(routingVO),
MapVO map = this.iMapService.getMapDetail(routingVO.getMapId()); "交路数据重复");
SimulationBuilder.SimulationDeviceBuildResult buildResult = SimulationBuilder.checkAndBuildMapDeviceData(map); MapVO map = this.iMapService.getMapDetail(routingVO.getMapId());
if (map.getCheckConfig().isCheck()) { SimulationBuilder.SimulationDeviceBuildResult buildResult = SimulationBuilder.checkAndBuildMapDeviceData(
BusinessExceptionAssertEnum.DATA_ERROR.assertCollectionEmpty(buildResult.getErrMsgList(), map);
"地图基础数据校验不通过"); if (map.getCheckConfig().isCheck()) {
BusinessExceptionAssertEnum.DATA_ERROR.assertCollectionEmpty(buildResult.getErrMsgList(),
"地图基础数据校验不通过");
}
Map<String, MapElement> 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<RunPlanRoutingVO> 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<String, MapElement> deviceMap = buildResult.getDeviceMap();
defaultRoutings.forEach(routingVO -> {
routingVO.setUserId(null);
if (routingDataExist(routingVO)) {
return;
} }
Map<String, MapElement> deviceMap = buildResult.getDeviceMap();
setRoutingType(routingVO, deviceMap); setRoutingType(routingVO, deviceMap);
RunPlanRouting routing = routingVO.convert2Entity(); RunPlanRouting routing = routingVO.convert2Entity();
runPlanRoutingDAO.insert(routing); 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 @Override
@Transactional @Transactional
public void createDefaultRoutings(List<RunPlanRoutingVO> defaultRoutings) { public void syncDefaultRoutingRefData(Long userId, Long mapId) {
if (CollectionUtils.isEmpty(defaultRoutings)) return; List<RunPlanRoutingVO> defaultRoutingVOs = getDefaultRoutings(mapId);
MapVO map = this.iMapService.getMapDetail(defaultRoutings.get(0).getMapId()); if (CollectionUtils.isEmpty(defaultRoutingVOs)) {
SimulationBuilder.SimulationDeviceBuildResult buildResult = SimulationBuilder.checkAndBuildMapDeviceData(map); return;
// BusinessExceptionAssertEnum.DATA_ERROR.assertCollectionEmpty(buildResult.getErrMsgList(), "地图基础数据校验不通过");
if (CollectionUtils.isEmpty(buildResult.getErrMsgList())) {
Map<String, MapElement> deviceMap = buildResult.getDeviceMap();
defaultRoutings.forEach(routingVO -> {
routingVO.setUserId(null);
if (routingDataExist(routingVO)) return;
setRoutingType(routingVO, deviceMap);
RunPlanRouting routing = routingVO.convert2Entity();
runPlanRoutingDAO.insert(routing);
});
}
} }
SimulationBuilder.SimulationDeviceBuildResult buildResult = SimulationBuilder.checkAndBuildMapDeviceData(
@Override this.iMapService.getMapDetail(mapId));
@Transactional BusinessExceptionAssertEnum.DATA_ERROR.assertCollectionEmpty(buildResult.getErrMsgList(),
public void syncDefaultRoutingRefData(Long userId, Long mapId) { "地图基础数据校验不通过");
List<RunPlanRoutingVO> defaultRoutingVOs = getDefaultRoutings(mapId); Map<String, MapElement> deviceMap = buildResult.getDeviceMap();
if (CollectionUtils.isEmpty(defaultRoutingVOs)) return; //根据默认交路生成站间运行等级停站时间折返数据
SimulationBuilder.SimulationDeviceBuildResult buildResult = SimulationBuilder.checkAndBuildMapDeviceData(this.iMapService.getMapDetail(mapId)); Set<RunPlanRunlevelVO> levelList = new HashSet<>(100);
BusinessExceptionAssertEnum.DATA_ERROR.assertCollectionEmpty(buildResult.getErrMsgList(), "地图基础数据校验不通过"); Set<RunPlanParkingTimeVO> parkingTimeList = new HashSet<>(30);
Map<String, MapElement> deviceMap = buildResult.getDeviceMap(); RunPlanUserConfigVO userConfig = planConfigService.getConfig(userId, mapId);
//根据默认交路生成站间运行等级停站时间折返数据 Map<String, RunPlanUserConfigVO.ReentryTime> reentryData;
Set<RunPlanRunlevelVO> levelList = new HashSet<>(100); if (Objects.nonNull(userConfig)) {
Set<RunPlanParkingTimeVO> parkingTimeList = new HashSet<>(30); reentryData = userConfig.getConfig().getReentryData();
RunPlanUserConfigVO userConfig = planConfigService.getConfig(userId, mapId); } else {
Map<String, RunPlanUserConfigVO.ReentryTime> reentryData; RunPlanUserConfigVO.Config config = new RunPlanUserConfigVO.Config();
if (Objects.nonNull(userConfig)) { reentryData = config.getReentryData();
reentryData = userConfig.getConfig().getReentryData(); userConfig = new RunPlanUserConfigVO(mapId, userId, config);
} else { }
RunPlanUserConfigVO.Config config = new RunPlanUserConfigVO.Config(); defaultRoutingVOs.forEach(routingVO -> {
reentryData = config.getReentryData(); routingVO.setUserId(userId);
userConfig = new RunPlanUserConfigVO(mapId, userId, config); List<RunPlanRunlevelVO> levels = RunPlanRunlevelVO.runLevelsFromRouting(routingVO);
} levelList.addAll(levels.stream().filter(l -> {
defaultRoutingVOs.forEach(routingVO -> {
routingVO.setUserId(userId);
List<RunPlanRunlevelVO> 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<RunPlanParkingTimeVO> parkingTimeVOS = RunPlanParkingTimeVO.parkingTimeFromRouting(routingVO);
parkingTimeVOS.forEach(p -> {
if (((Section) deviceMap.get(p.getSectionCode())).isStandTrack()) {
parkingTimeList.add(p);
}
});
setStationReentryTime(deviceMap, reentryData, routingVO);
}
);
//先简单插入新数据
List<RunPlanRunlevelVO> levels = planRunlevelService.queryUserRunLevels(userId, mapId);
levelList.removeAll(levels);
levelList.forEach(l -> {
Section startSection = (Section) deviceMap.get(l.getStartSectionCode()); Section startSection = (Section) deviceMap.get(l.getStartSectionCode());
Section endSection = (Section) deviceMap.get(l.getEndSectionCode()); Section endSection = (Section) deviceMap.get(l.getEndSectionCode());
if ((startSection.isStandTrack() && endSection.isTransferTrack()) || (endSection.isStandTrack() && startSection.isTransferTrack())) { if ((startSection.isTurnBackTrack() && !startSection.isStandTrack())
Float distance; || (endSection.isTurnBackTrack() && !endSection.isStandTrack())) {
try { return false;
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()); return true;
l.setDistance(distance); }).collect(Collectors.toList()));
l.generateDefaultRunLevel();
planRunlevelService.createUserRunlevel(l);
});
List<RunPlanParkingTimeVO> parktimes = planParktimeService.queryUserParktimes(userId, mapId);
parkingTimeList.removeAll(parktimes);
parkingTimeList.forEach(p -> {
planParktimeService.createUserParktime(p);
});
planConfigService.saveConfig(userId, mapId, userConfig.getConfig());
}
private void setStationReentryTime(Map<String, MapElement> deviceMap, Map<String, RunPlanUserConfigVO.ReentryTime> reentryData, RunPlanRoutingVO routingVO) { List<RunPlanParkingTimeVO> parkingTimeVOS = RunPlanParkingTimeVO.parkingTimeFromRouting(
Section startSection = (Section) deviceMap.get(routingVO.getStartSectionCode()); routingVO);
if (startSection.isTurnBackTrack()) { parkingTimeVOS.forEach(p -> {
reentryData.putIfAbsent(routingVO.getStartStationCode(), new RunPlanUserConfigVO.ReentryTime(120, 210, 45, 45)); 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<RunPlanRunlevelVO> 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<RunPlanParkingTimeVO> parktimes = planParktimeService.queryUserParktimes(userId, mapId);
parkingTimeList.removeAll(parktimes);
parkingTimeList.forEach(p -> {
planParktimeService.createUserParktime(p);
});
planConfigService.saveConfig(userId, mapId, userConfig.getConfig());
}
private void createRoutingRefData(Map<String, MapElement> deviceMap, RunPlanRoutingVO routingVO) { private void setStationReentryTime(Map<String, MapElement> deviceMap,
generateUserRunlevels(routingVO, deviceMap); Map<String, RunPlanUserConfigVO.ReentryTime> reentryData, RunPlanRoutingVO routingVO) {
generateUserParktimes(routingVO, deviceMap); Section startSection = (Section) deviceMap.get(routingVO.getStartSectionCode());
generateUserStationReentryTimes(routingVO, deviceMap); 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 private void createRoutingRefData(Map<String, MapElement> deviceMap, RunPlanRoutingVO routingVO) {
public RunPlanRoutingVO generateUserRoutingData(RunPlanRoutingVO routingVO) { generateUserRunlevels(routingVO, deviceMap);
MapVO map = this.iMapService.getMapDetail(routingVO.getMapId()); generateUserParktimes(routingVO, deviceMap);
SimulationBuilder.SimulationDeviceBuildResult buildResult = SimulationBuilder.checkAndBuildMapDeviceData(map); generateUserStationReentryTimes(routingVO, deviceMap);
BusinessExceptionAssertEnum.DATA_ERROR.assertCollectionEmpty(buildResult.getErrMsgList(), }
"地图基础数据校验不通过");
Map<String, MapElement> deviceMap = buildResult.getDeviceMap();
generateUserRoutingSections(routingVO, deviceMap);
return routingVO;
}
@Override @Override
public List<RunPlanRoutingVO> queryRoutes(Long mapId, RunPlanRoutingQueryVO queryVO, AccountVO user) { public RunPlanRoutingVO generateUserRoutingData(RunPlanRoutingVO routingVO) {
return getUserRoutingBy(user.getId(), mapId).stream() MapVO map = this.iMapService.getMapDetail(routingVO.getMapId());
.filter(routing -> Objects.equals(routing.getDestinationCode(), queryVO.getDestinationCode())) SimulationBuilder.SimulationDeviceBuildResult buildResult = SimulationBuilder.checkAndBuildMapDeviceData(
.collect(Collectors.toList()); map);
} BusinessExceptionAssertEnum.DATA_ERROR.assertCollectionEmpty(buildResult.getErrMsgList(),
"地图基础数据校验不通过");
Map<String, MapElement> deviceMap = buildResult.getDeviceMap();
generateUserRoutingSections(routingVO, deviceMap);
return routingVO;
}
private void generateUserRoutingSections(RunPlanRoutingVO routingVO, Map<String, MapElement> deviceMap) { @Override
Section startSection = (Section) deviceMap.get(routingVO.getStartSectionCode()); public List<RunPlanRoutingVO> queryRoutes(Long mapId, RunPlanRoutingQueryVO queryVO,
Section endSection = (Section) deviceMap.get(routingVO.getEndSectionCode()); AccountVO user) {
//中间经停所有站台轨 return getUserRoutingBy(user.getId(), mapId).stream()
List<Section> passingStandTrack = CalculateService.findPassingStandTrack(startSection, endSection, routingVO.getRight()); .filter(
BusinessExceptionAssertEnum.OPERATION_NOT_SUPPORTED.assertNotNull(passingStandTrack, routing -> Objects.equals(routing.getDestinationCode(), queryVO.getDestinationCode()))
String.format("没有找到线路方向[%s]的中间经停区段,是否需要更换方向/手动添加/直接保存交路", routingVO.getRight() ? "右向" : "左向")); .collect(Collectors.toList());
LinkedList<RunPlanRoutingSection> 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 private void generateUserRoutingSections(RunPlanRoutingVO routingVO,
public RunPlanRoutingVO getUserRouting(Long routingId) { Map<String, MapElement> deviceMap) {
RunPlanRouting routing = getRunPlanRoutingData(routingId); Section startSection = (Section) deviceMap.get(routingVO.getStartSectionCode());
return RunPlanRoutingVO.convert2VO(routing); Section endSection = (Section) deviceMap.get(routingVO.getEndSectionCode());
} //中间经停所有站台轨
List<Section> passingStandTrack = CalculateService.findPassingStandTrack(startSection,
endSection, routingVO.getRight());
BusinessExceptionAssertEnum.OPERATION_NOT_SUPPORTED.assertNotNull(passingStandTrack,
String.format("没有找到线路方向[%s]的中间经停区段,是否需要更换方向/手动添加/直接保存交路",
routingVO.getRight() ? "右向" : "左向"));
LinkedList<RunPlanRoutingSection> 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
@Override public RunPlanRoutingVO getUserRouting(Long routingId) {
public void updateUserRouting(Long routingId, RunPlanRoutingVO routingVO) { RunPlanRouting routing = getRunPlanRoutingData(routingId);
MapVO map = this.iMapService.getMapDetail(routingVO.getMapId()); return RunPlanRoutingVO.convert2VO(routing);
SimulationBuilder.SimulationDeviceBuildResult buildResult = SimulationBuilder.checkAndBuildMapDeviceData(map); }
BusinessExceptionAssertEnum.DATA_ERROR.assertCollectionEmpty(buildResult.getErrMsgList(),
"地图基础数据校验不通过"); @Transactional
Map<String, MapElement> deviceMap = buildResult.getDeviceMap(); @Override
setRoutingType(routingVO, deviceMap); public void updateUserRouting(Long routingId, RunPlanRoutingVO routingVO) {
RunPlanRouting newRouting = routingVO.convert2Entity(); MapVO map = this.iMapService.getMapDetail(routingVO.getMapId());
newRouting.setId(routingId); SimulationBuilder.SimulationDeviceBuildResult buildResult = SimulationBuilder.checkAndBuildMapDeviceData(
RunPlanRouting routing = getRunPlanRoutingData(routingId); map);
if(Objects.equals(routing.getSectionData(),JsonUtils.writeValueAsString(routingVO.getParkSectionCodeList()))){ BusinessExceptionAssertEnum.DATA_ERROR.assertCollectionEmpty(buildResult.getErrMsgList(),
runPlanRoutingDAO.updateByPrimaryKey(newRouting); "地图基础数据校验不通过");
return; Map<String, MapElement> deviceMap = buildResult.getDeviceMap();
} setRoutingType(routingVO, deviceMap);
BusinessExceptionAssertEnum.DATA_ALREADY_EXIST.assertNotTrue(routingDataExist(routingVO), "交路数据重复"); RunPlanRouting newRouting = routingVO.convert2Entity();
runPlanRoutingDAO.updateByPrimaryKeyWithBLOBs(newRouting); newRouting.setId(routingId);
generateUserRunlevels(routingVO, deviceMap); RunPlanRouting routing = getRunPlanRoutingData(routingId);
generateUserParktimes(routingVO, deviceMap); if (Objects.equals(routing.getSectionData(),
generateUserStationReentryTimes(routingVO, deviceMap); 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<String, MapElement> deviceMap) { private void setRoutingType(RunPlanRoutingVO routingVO, Map<String, MapElement> deviceMap) {
Section startSection = (Section) deviceMap.get(routingVO.getStartSectionCode()); Section startSection = (Section) deviceMap.get(routingVO.getStartSectionCode());
@ -268,175 +310,200 @@ public class RunPlanRoutingService implements IRunPlanRoutingService {
} }
} }
private void generateUserParktimes(RunPlanRoutingVO routingVO, Map<String, MapElement> deviceMap) { private void generateUserParktimes(RunPlanRoutingVO routingVO,
List<RunPlanParkingTimeVO> parkingTimeVOS = RunPlanParkingTimeVO.parkingTimeFromRouting(routingVO); Map<String, MapElement> deviceMap) {
parkingTimeVOS.forEach(p -> { List<RunPlanParkingTimeVO> parkingTimeVOS = RunPlanParkingTimeVO.parkingTimeFromRouting(
if (((Section) deviceMap.get(p.getSectionCode())).isStandTrack()) { routingVO);
planParktimeService.createUserParktime(p); parkingTimeVOS.forEach(p -> {
} if (((Section) deviceMap.get(p.getSectionCode())).isStandTrack()) {
}); planParktimeService.createUserParktime(p);
} }
});
}
private void generateUserRunlevels(RunPlanRoutingVO routingVO, Map<String, MapElement> deviceMap) { private void generateUserRunlevels(RunPlanRoutingVO routingVO,
List<RunPlanRunlevelVO> levels = RunPlanRunlevelVO.runLevelsFromRouting(routingVO); Map<String, MapElement> deviceMap) {
levels.forEach(l -> { List<RunPlanRunlevelVO> levels = RunPlanRunlevelVO.runLevelsFromRouting(routingVO);
Section startSection = (Section) deviceMap.get(l.getStartSectionCode()); levels.forEach(l -> {
Section endSection = (Section) deviceMap.get(l.getEndSectionCode()); Section startSection = (Section) deviceMap.get(l.getStartSectionCode());
if ((startSection.isTurnBackTrack() && !startSection.isStandTrack()) Section endSection = (Section) deviceMap.get(l.getEndSectionCode());
|| (endSection.isTurnBackTrack() && !endSection.isStandTrack())) { if ((startSection.isTurnBackTrack() && !startSection.isStandTrack())
return; || (endSection.isTurnBackTrack() && !endSection.isStandTrack())) {
} return;
if ((startSection.isStandTrack() && endSection.isTransferTrack()) || (endSection.isStandTrack() && startSection.isTransferTrack())) { }
Float distance; if ((startSection.isStandTrack() && endSection.isTransferTrack()) || (
try { endSection.isStandTrack() && startSection.isTransferTrack())) {
distance = CalculateService.calculateDistance(startSection, endSection, l.getRight()); Float distance;
} catch (SimulationException e) { try {
distance = CalculateService.calculateDistance(startSection, endSection, !l.getRight()); distance = CalculateService.calculateDistance(startSection, endSection, l.getRight());
} } catch (SimulationException e) {
l.setDistance(distance); distance = CalculateService.calculateDistance(startSection, endSection, !l.getRight());
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<String, MapElement> deviceMap) {
RunPlanUserConfigVO userConfig = planConfigService.getConfig(routingVO.getUserId(), routingVO.getMapId());
Map<String, RunPlanUserConfigVO.ReentryTime> 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);
} }
//交路是折返轨的一头 设置折返时间 l.setDistance(distance);
setStationReentryTime(deviceMap, reentryData, routingVO); l.generateDefaultRunLevel();
planConfigService.saveConfig(routingVO.getUserId(), routingVO.getMapId(),userConfig.getConfig()); 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<String, MapElement> deviceMap) {
RunPlanUserConfigVO userConfig = planConfigService.getConfig(routingVO.getUserId(),
routingVO.getMapId());
Map<String, RunPlanUserConfigVO.ReentryTime> 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 @Override
public void deleteUserRouting(Long routingId) { public void deleteUserRouting(Long routingId) {
runPlanRoutingDAO.deleteByPrimaryKey(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<RunPlanRoutingVO> 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())) {
@Override criteria.andEndStationCodeEqualTo(queryVO.getEndStationCode());
@Transactional or.andEndStationCodeEqualTo(queryVO.getEndStationCode());
public void deleteDefaultRouting(Long mapId) {
RunPlanRoutingExample example = new RunPlanRoutingExample();
example.createCriteria().andMapIdEqualTo(mapId).andUserIdIsNull();
runPlanRoutingDAO.deleteByExample(example);
} }
if (StringUtils.hasText(queryVO.getStartSectionCode())) {
@Override criteria.andStartSectionCodeEqualTo(queryVO.getStartSectionCode());
public PageVO<RunPlanRoutingVO> queryPagedUserRouting(Long userId, Long mapId, RunPlanRoutingQueryVO queryVO) { or.andStartSectionCodeEqualTo(queryVO.getStartSectionCode());
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<RunPlanRouting> page = (Page<RunPlanRouting>) runPlanRoutingDAO.selectByExampleWithBLOBs(example);
List<RunPlanRoutingVO> routingVOList = page.getResult().stream().map(RunPlanRoutingVO::convert2VO).collect(Collectors.toList());
return PageVO.convert(page, routingVOList);
} }
if (StringUtils.hasText(queryVO.getEndSectionCode())) {
public List<RunPlanRoutingVO> getDefaultRoutings(Long mapId) { criteria.andEndSectionCodeEqualTo(queryVO.getEndSectionCode());
RunPlanRoutingExample example = new RunPlanRoutingExample(); or.andEndSectionCodeEqualTo(queryVO.getEndSectionCode());
example.createCriteria().andMapIdEqualTo(mapId).andUserIdIsNull();
List<RunPlanRouting> runPlanRoutings = runPlanRoutingDAO.selectByExampleWithBLOBs(example);
return RunPlanRoutingVO.convert2VOList(runPlanRoutings);
} }
Page<RunPlanRouting> page = (Page<RunPlanRouting>) runPlanRoutingDAO.selectByExampleWithBLOBs(
example);
List<RunPlanRoutingVO> routingVOList = page.getResult().stream()
.map(RunPlanRoutingVO::convert2VO).collect(Collectors.toList());
return PageVO.convert(page, routingVOList);
}
public List<RunPlanRoutingVO> getDefaultRoutings(Long mapId) {
RunPlanRoutingExample example = new RunPlanRoutingExample();
example.createCriteria().andMapIdEqualTo(mapId).andUserIdIsNull();
List<RunPlanRouting> runPlanRoutings = runPlanRoutingDAO.selectByExampleWithBLOBs(example);
return RunPlanRoutingVO.convert2VOList(runPlanRoutings);
}
@Override @Override
public List<RunPlanRoutingVO> getUserRoutingBy(Long userId, Long mapId) { public List<RunPlanRoutingVO> getUserRoutingBy(Long userId, Long mapId) {
RunPlanRoutingExample example = new RunPlanRoutingExample(); RunPlanRoutingExample example = new RunPlanRoutingExample();
example.createCriteria().andMapIdEqualTo(mapId).andUserIdEqualTo(userId); example.createCriteria().andMapIdEqualTo(mapId).andUserIdEqualTo(userId);
example.or().andMapIdEqualTo(mapId).andUserIdIsNull(); example.or().andMapIdEqualTo(mapId).andUserIdIsNull();
List<RunPlanRouting> runPlanRoutings = runPlanRoutingDAO.selectByExample(example); List<RunPlanRouting> runPlanRoutings = runPlanRoutingDAO.selectByExample(example);
return RunPlanRoutingVO.convert2VOList(runPlanRoutings,this.iMapService.getMapDetail(mapId)); return RunPlanRoutingVO.convert2VOList(runPlanRoutings, this.iMapService.getMapDetail(mapId));
}
@Override
public List<RunPlanRoutingVO> 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<RunPlanRouting> 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<RunPlanRouting> runPlanRoutings = runPlanRoutingDAO.selectByExampleWithBLOBs(example);
if (CollectionUtils.isEmpty(runPlanRoutings)) {
return null;
} }
return RunPlanRoutingVO.convert2VO(runPlanRoutings.get(0),
this.iMapService.getMapDetail(planVO.getMapId()));
}
@Override @Override
public List<RunPlanRoutingVO> getUserRoutingByType(Long userId, Long mapId, RunPlanRoutingVO.UserRoutingType routingType) { public RunPlanRoutingVO queryUserRoutingById(Long userId, Long mapId, Long routingId) {
RunPlanRoutingExample example = new RunPlanRoutingExample(); RunPlanRouting runPlanRouting = getRunPlanRoutingData(routingId);
example.createCriteria().andMapIdEqualTo(mapId).andUserIdEqualTo(userId).andTypeEqualTo(routingType.name()); return RunPlanRoutingVO.convert2VO(runPlanRouting, this.iMapService.getMapDetail(mapId));
example.or().andMapIdEqualTo(mapId).andUserIdIsNull().andTypeEqualTo(routingType.name()); }
List<RunPlanRouting> runPlanRoutings = runPlanRoutingDAO.selectByExampleWithBLOBs(example);
return RunPlanRoutingVO.convert2VOList(runPlanRoutings,this.iMapService.getMapDetail(mapId)); @Override
public List<RunPlanRoutingSection> 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) { private boolean routingDataExist(RunPlanRoutingVO routingVO) {
RunPlanVO planVO = this.getRunPlanById(planId); return
RunPlanTripVO trip = planVO.getTripList().stream() runPlanRoutingDAO.countUserRoutingBySectionData(routingVO.getUserId(), routingVO.getMapId(),
.filter(tripVO -> tripVO.getSDTNumberNew().equals(SDTNumber)) JsonUtils.writeValueAsString(routingVO.getParkSectionCodeList())) > 0;
.findFirst() }
.orElseThrow(() -> BusinessExceptionAssertEnum.DATA_NOT_EXIST.exception());
RunPlanRoutingExample example = new RunPlanRoutingExample(); private RunPlanRouting getRunPlanRoutingData(Long routingId) {
example.createCriteria().andMapIdEqualTo(planVO.getMapId()).andUserIdEqualTo(userId).andStartSectionCodeEqualTo(trip.getStartSectionCode()).andEndSectionCodeEqualTo(trip.getEndSectionCode()); RunPlanRouting routing = runPlanRoutingDAO.selectByPrimaryKey(routingId);
example.or().andMapIdEqualTo(planVO.getMapId()).andUserIdIsNull().andStartSectionCodeEqualTo(trip.getStartSectionCode()).andEndSectionCodeEqualTo(trip.getEndSectionCode()); BusinessExceptionAssertEnum.DATA_NOT_EXIST.assertNotNull(routing,
List<RunPlanRouting> runPlanRoutings = runPlanRoutingDAO.selectByExampleWithBLOBs(example); String.format("交路[%s]不存在", routingId));
if (CollectionUtils.isEmpty(runPlanRoutings)) return null; return routing;
return RunPlanRoutingVO.convert2VO(runPlanRoutings.get(0), this.iMapService.getMapDetail(planVO.getMapId())); }
}
private RunPlanVO getRunPlanById(Long planId) {
@Override RunPlanDraft runPlanDraft = this.runPlanDraftDAO.selectByPrimaryKey(planId);
public RunPlanRoutingVO queryUserRoutingById(Long userId, Long mapId, Long routingId) { BusinessExceptionAssertEnum.DATA_NOT_EXIST.assertNotNull(runPlanDraft);
RunPlanRouting runPlanRouting = getRunPlanRoutingData(routingId); RunPlanVO runPlanVO = new RunPlanVO(runPlanDraft);
return RunPlanRoutingVO.convert2VO(runPlanRouting,this.iMapService.getMapDetail(mapId)); if (StringUtils.hasText(runPlanDraft.getTrips())) {
} runPlanVO.setTripList(JsonUtils.read(runPlanDraft.getTrips(),
JsonUtils.getCollectionType(List.class, RunPlanTripVO.class)));
@Override } else {
public List<RunPlanRoutingSection> getRoutingSectionDataBy(Long userId, Long routingId) { runPlanVO.setTripList(new ArrayList<>());
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;
} }
return runPlanVO;
}
} }

View File

@ -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.map.Switch;
import club.joylink.rtss.simulation.cbtc.data.support.SectionPosition; import club.joylink.rtss.simulation.cbtc.data.support.SectionPosition;
import club.joylink.rtss.simulation.cbtc.data.vr.VirtualRealityTrain; 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.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
/** /**
* 地面ATP逻辑循环 * 地面ATP逻辑循环
@ -26,226 +25,235 @@ import java.util.stream.Collectors;
@Component @Component
public class AtpSectionService { public class AtpSectionService {
/** /**
* 收集列车接近信号机消息并发送给CI * 收集列车接近信号机消息并发送给CI
*/ */
public void changeSignalModeByTrainApproach(Simulation simulation, public void changeSignalModeByTrainApproach(Simulation simulation,
List<VirtualRealityTrain> onlineTrainList, List<VirtualRealityTrain> onlineTrainList,
Map<String, List<Section>> trainAtpSectionMap) { Map<String, List<Section>> trainAtpSectionMap) {
List<Signal> signalList = simulation.getRepository().getSignalList(); List<Signal> signalList = simulation.getRepository().getSignalList();
signalList.forEach(signal -> { signalList.forEach(signal -> {
int a = 0; // 列车接近信号消息0-无车接近1-通信车接近2-非通信车接近 int a = 0; // 列车接近信号消息0-无车接近1-通信车接近2-非通信车接近
for (VirtualRealityTrain train : onlineTrainList) { for (VirtualRealityTrain train : onlineTrainList) {
List<Section> atpSectionList = trainAtpSectionMap.get(train.getGroupNumber()); List<Section> atpSectionList = trainAtpSectionMap.get(train.getGroupNumber());
List<Section> physicalList = this.convert2PhysicalSectionList(atpSectionList); List<Section> physicalList = this.convert2PhysicalSectionList(atpSectionList);
if (train.isCommunicable() && signal.containsApproachAtpSection(atpSectionList)) { //存在通信车接近继续 if (train.isCommunicable() && signal.containsApproachAtpSection(
a = 1; atpSectionList)) { //存在通信车接近继续
} else if (!train.isCommunicable() && signal.containsApproachPhysicalSection(physicalList)) { //存在非通信车接近结束 a = 1;
a = 2; } else if (!train.isCommunicable() && signal.containsApproachPhysicalSection(
break; physicalList)) { //存在非通信车接近结束
} a = 2;
} break;
if (1 == a) { // 只有通信车接近 }
if(!signal.getSignalModel().getGuideAspect().equals(signal.getAspect())) { }
signal.changeToCbtcMode(); if (1 == a) { // 只有通信车接近
} if (!signal.getSignalModel().getGuideAspect().equals(signal.getAspect())) {
} else if (2 == a) { // 有非通信车接近 signal.changeToCbtcMode();
signal.changeToBackupMode(); }
} } else if (2 == a) { // 有非通信车接近
signal.updateApproachLock();//更新信号机接近锁闭状态 signal.changeToBackupMode();
}); }
} signal.updateApproachLock();//更新信号机接近锁闭状态
});
}
private List<Section> convert2PhysicalSectionList(List<Section> sectionList) { private List<Section> convert2PhysicalSectionList(List<Section> sectionList) {
List<Section> physicalList = new ArrayList<>(); List<Section> physicalList = new ArrayList<>();
sectionList.forEach(section -> { sectionList.forEach(section -> {
if (section.isPhysical()) { if (section.isPhysical()) {
physicalList.add(section); physicalList.add(section);
} else if (section.isLogicSection()) { } else if (section.isLogicSection()) {
if (!physicalList.contains(section.getParent())) { if (!physicalList.contains(section.getParent())) {
physicalList.add(section.getParent()); physicalList.add(section.getParent());
} }
} }
}); });
return physicalList; return physicalList;
} }
/** /**
* ATP区段列车占用检测并设置 * ATP区段列车占用检测并设置
* *
* @param simulation * @param simulation
* @param train * @param train
* @return * @return
*/ */
public List<Section> atpSectionOccupyCheck(Simulation simulation, VirtualRealityTrain train) { public List<Section> atpSectionOccupyCheck(Simulation simulation, VirtualRealityTrain train) {
List<Section> atpSectionList = new ArrayList<>(); List<Section> atpSectionList = new ArrayList<>();
boolean right = train.isRight(); boolean right = train.isRight();
SectionPosition trainHeadPosition = train.getHeadPosition(); SectionPosition trainHeadPosition = train.getHeadPosition();
SimulationDataRepository repository = simulation.getRepository(); SimulationDataRepository repository = simulation.getRepository();
MapConfig config = repository.getConfig(); MapConfig config = repository.getConfig();
boolean switchSingleHandle = config.isSwitchSingleHandle(); boolean switchSingleHandle = config.isSwitchSingleHandle();
boolean isRailway = config.isRailway(); // 大铁逻辑 boolean isRailway = config.isRailway(); // 大铁逻辑
if (train.isCommunicable() || isRailway) { // 通信车占用 或者 大铁配置 if (train.isCommunicable() || isRailway) { // 通信车占用 或者 大铁配置
// 车尾位置追加不确定性距离(速度*2)m // 车尾位置追加不确定性距离(速度*2)m
SectionPosition trainTailPosition = CalculateService SectionPosition trainTailPosition = CalculateService
.calculateNextPositionByStartAndLen(trainHeadPosition, !right, train.getLen() + train.getSpeed() * 2, false); .calculateNextPositionByStartAndLen(trainHeadPosition, !right,
atpSectionList = CalculateService.getAtpSections(trainHeadPosition, trainTailPosition, train.getLen() + train.getSpeed() * 2, false);
right, switchSingleHandle); atpSectionList = CalculateService.getAtpSections(trainHeadPosition, trainTailPosition,
List<Section> removes = new ArrayList<>(); right, switchSingleHandle);
for (Section atpSection : atpSectionList) { List<Section> removes = new ArrayList<>();
Section axle = atpSection; for (Section atpSection : atpSectionList) {
Section parent = atpSection.getParent(); Section axle = atpSection;
if (parent != null) { Section parent = atpSection.getParent();
axle = parent; if (parent != null) {
} axle = parent;
if (axle.isAxleCounter() && (!axle.isNctOccupied() || Section.AxleFault.FAULT.equals(axle.getFault()))) { }
removes.add(atpSection); if (axle.isAxleCounter() && (!axle.isNctOccupied() || Section.AxleFault.FAULT.equals(
continue; axle.getFault()))) {
} removes.add(atpSection);
continue;
}
// atpSection.communicateTrainOccupy(right); // atpSection.communicateTrainOccupy(right);
} }
if (!removes.isEmpty()) { if (!removes.isEmpty()) {
atpSectionList.removeAll(removes); atpSectionList.removeAll(removes);
} }
} else { // 非通信车 } else { // 非通信车
List<Section> sectionList = repository.queryTrainOccupySectionList(train.getGroupNumber()); List<Section> sectionList = repository.queryTrainOccupySectionList(train.getGroupNumber());
if (!CollectionUtils.isEmpty(sectionList)) { if (!CollectionUtils.isEmpty(sectionList)) {
for (Section section : sectionList) { for (Section section : sectionList) {
if (section.isSwitchAxleCounterSection()) { if (section.isSwitchAxleCounterSection()) {
Section switchSection = section.getLogicList().get(0); Section switchSection = section.getLogicList().get(0);
atpSectionList.addAll(switchSection.getSwitchAxleSectionsBySwitchPosition()); atpSectionList.addAll(switchSection.getSwitchAxleSectionsBySwitchPosition());
continue; continue;
} }
if (CollectionUtils.isEmpty(section.getLogicList())) { if (CollectionUtils.isEmpty(section.getLogicList())) {
atpSectionList.add(section); atpSectionList.add(section);
} else { } else {
atpSectionList.addAll(section.getLogicList()); atpSectionList.addAll(section.getLogicList());
} }
} }
} }
//将列车占压的物理区段及其关联的逻辑区段全部设为非通信车占用 //将列车占压的物理区段及其关联的逻辑区段全部设为非通信车占用
// atpSectionList.forEach(atpSection -> atpSection.nonCommunicateTrainOccupy(right)); // atpSectionList.forEach(atpSection -> atpSection.nonCommunicateTrainOccupy(right));
}
return atpSectionList;
} }
return atpSectionList;
}
/** /**
* ARB检测 * ARB检测
* *
* @param simulation * @param simulation
* @param section * @param section
* @param sectionList * @param sectionList
*/ */
public void sectionARBCheck(Simulation simulation, Section section, List<Section> sectionList) { public void sectionARBCheck(Simulation simulation, Section section, List<Section> sectionList) {
//目前ARB故障才会导致ARB判定 //目前ARB故障才会导致ARB判定
if (Section.AxleFault.ARB.equals(section.getFault()) && section.getVirtualAxleCounter().isOccupy()) { if (Section.AxleFault.ARB.equals(section.getFault()) && section.getVirtualAxleCounter()
if (!sectionList.contains(section)) { .isOccupy()) {
section.judgeAsARB(); if (!sectionList.contains(section)) {
} else { section.judgeAsARB();
section.setFault(Section.AxleFault.FAULT); } else {
} section.setFault(Section.AxleFault.FAULT);
} else if (Section.AxleFault.FAULT.equals(section.getFault()) && section.getVirtualAxleCounter().isOccupy()) { }
section.judgeAsNctOccupied(simulation); } else if (Section.AxleFault.FAULT.equals(section.getFault()) && section.getVirtualAxleCounter()
} .isOccupy()) {
if (/*!section.isInvalid() &&*/ section.isNctOccupied()) { section.judgeAsNctOccupied(simulation);
if (!sectionList.contains(section)) {
section.judgeAsNctOccupied(simulation);
}
}
//ARB故障恢复判断
if (Section.AxleFault.ARB.equals(section.getFault()) && !section.getVirtualAxleCounter().isOccupy()) {
Section.AxleFault.ARB.fix(section);
}
} }
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 simulation
* @param trainList * @param trainList
* @return * @return
*/ */
public List<Section> getTrainExistAxleSectionsUnderDelay(Simulation simulation, List<VirtualRealityTrain> trainList) { public List<Section> getTrainExistAxleSectionsUnderDelay(Simulation simulation,
List<Section> list = new ArrayList<>(); List<VirtualRealityTrain> trainList) {
for (VirtualRealityTrain train : trainList) { List<Section> list = new ArrayList<>();
//只统计非通信车 for (VirtualRealityTrain train : trainList) {
if (train.isCommunicable()) //只统计非通信车
continue; if (train.isCommunicable()) {
boolean right = train.isRight(); continue;
SectionPosition headPosition = train.getHeadPosition(); }
float offset = 50; boolean right = train.isRight();
SectionPosition head = CalculateService SectionPosition headPosition = train.getHeadPosition();
.calculateNextPositionByStartAndLen(headPosition, right, offset, false); float offset = 50;
// 考虑列车最大可能占用区间用于判断ARB区段 SectionPosition head = CalculateService
SectionPosition tail = CalculateService .calculateNextPositionByStartAndLen(headPosition, right, offset, false);
.calculateNextPositionByStartAndLen(headPosition, // 考虑列车最大可能占用区间用于判断ARB区段
!right, train.getLen() + offset, false); SectionPosition tail = CalculateService
List<Section> sectionList = CalculateService.getTrainOccupyAxleSection(head, tail, right); .calculateNextPositionByStartAndLen(headPosition,
if (!CollectionUtils.isEmpty(sectionList)) { !right, train.getLen() + offset, false);
for (Section section : sectionList) { List<Section> sectionList = CalculateService.getTrainOccupyAxleSection(head, tail, right);
if (!list.contains(section)) { if (!CollectionUtils.isEmpty(sectionList)) {
list.add(section); for (Section section : sectionList) {
} if (!list.contains(section)) {
} list.add(section);
} else { }
log.warn(String.format("列车[%s]没有存在范围的计轴区段",
train.getGroupNumber()));
}
} }
return list; } else {
log.warn(String.format("列车[%s]没有存在范围的计轴区段",
train.getGroupNumber()));
}
} }
return list;
}
public void removeOfflineTrainOccupySections(Simulation simulation, List<VirtualRealityTrain> onlineTrainList) { public void removeOfflineTrainOccupySections(Simulation simulation,
// 移除已经下线的列车占用区段数据 List<VirtualRealityTrain> onlineTrainList) {
SimulationDataRepository repository = simulation.getRepository(); // 移除已经下线的列车占用区段数据
Set<String> oldTOSKeyList = repository.queryTrainOccupySectionKeys(); SimulationDataRepository repository = simulation.getRepository();
Set<String> currentTrainCodeList = onlineTrainList.stream() Set<String> oldTOSKeyList = repository.queryTrainOccupySectionKeys();
.map(VirtualRealityTrain::getGroupNumber) Set<String> currentTrainCodeList = onlineTrainList.stream()
.collect(Collectors.toSet()); .map(VirtualRealityTrain::getGroupNumber)
oldTOSKeyList.removeAll(currentTrainCodeList); .collect(Collectors.toSet());
oldTOSKeyList.forEach(groupNumber -> { oldTOSKeyList.removeAll(currentTrainCodeList);
List<Section> sections = repository.queryTrainOccupySectionList(groupNumber); oldTOSKeyList.forEach(groupNumber -> {
sections.forEach(section -> { List<Section> sections = repository.queryTrainOccupySectionList(groupNumber);
section.getVirtualAxleCounter().clear(); sections.forEach(section -> {
section.clearOccupy(); section.getVirtualAxleCounter().clear();
}); section.clearOccupy();
repository.deleteTrainOccupySectionList(groupNumber); });
}); repository.deleteTrainOccupySectionList(groupNumber);
} });
}
/** /**
* isSwitchSingleHandle 为TRUE的情况下获取区段列表 * isSwitchSingleHandle 为TRUE的情况下获取区段列表
* *
* @param section 区段 * @param section 区段
* @param right 列车行驶方向 * @param right 列车行驶方向
* @return 区段列表 * @return 区段列表
*/ */
private List<Section> handleSingleSwitchPosition(Section section, boolean right) { private List<Section> handleSingleSwitchPosition(Section section, boolean right) {
List<Section> atpSectionList = new ArrayList<>(); List<Section> atpSectionList = new ArrayList<>();
// 道岔列表 // 道岔列表
List<Switch> relSwitchList = section.getRelSwitchList(); List<Switch> relSwitchList = section.getRelSwitchList();
// 反位情况下 // 反位情况下
Switch relSwitch = null; Switch relSwitch = null;
if (relSwitchList.stream().anyMatch(Switch::isPosR)) { if (relSwitchList.stream().anyMatch(Switch::isPosR)) {
relSwitch = relSwitchList.stream().filter(Switch::isPosR).findFirst().orElse(null); relSwitch = relSwitchList.stream().filter(Switch::isPosR).findFirst().orElse(null);
} else { } else {
relSwitch = relSwitchList.stream().filter(Switch::isPosN).findFirst().orElse(null); relSwitch = relSwitchList.stream().filter(Switch::isPosN).findFirst().orElse(null);
//relSwitchList.forEach(relSwitch -> atpSectionList.addAll(relSwitch.getSectionsByPosition())); //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;
} }
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;
}
} }

View File

@ -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.constant.TrainType;
import club.joylink.rtss.simulation.cbtc.data.CalculateService; import club.joylink.rtss.simulation.cbtc.data.CalculateService;
import club.joylink.rtss.simulation.cbtc.data.SimulationDataRepository; 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.StationPlan;
import club.joylink.rtss.simulation.cbtc.data.plan.TripPlan; import club.joylink.rtss.simulation.cbtc.data.plan.TripPlan;
import club.joylink.rtss.simulation.cbtc.data.support.RoutePath; import club.joylink.rtss.simulation.cbtc.data.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.ATPService;
import club.joylink.rtss.simulation.cbtc.onboard.ATP.OnboardAtpApiService; import club.joylink.rtss.simulation.cbtc.onboard.ATP.OnboardAtpApiService;
import club.joylink.rtss.vo.client.operation.DriveParamVO; 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 lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils; import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import java.time.LocalTime;
import java.util.*;
import java.util.stream.Collectors;
/** /**
* ATS列车服务 * ATS列车服务
*/ */
@ -183,12 +194,12 @@ public class AtsTrainService {
StationPlan stationPlan = planList.get(i); StationPlan stationPlan = planList.get(i);
List<RoutePath> routePaths = repository.queryRoutePathsByEndAndContainsSection(stationPlan.getSection(), phySection); List<RoutePath> routePaths = repository.queryRoutePathsByEndAndContainsSection(stationPlan.getSection(), phySection);
if (!CollectionUtils.isEmpty(routePaths)) { if (!CollectionUtils.isEmpty(routePaths)) {
nextPlan = stationPlan;
if (routePaths.get(0).isRight() != tripPlan.isRight()) { if (routePaths.get(0).isRight() != tripPlan.isRight()) {
break; break;
} }
} else { nextPlan = stationPlan;
break; // } else {
// break;
} }
} }
if (Objects.isNull(nextPlan)) { if (Objects.isNull(nextPlan)) {

View File

@ -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.map.Signal;
import club.joylink.rtss.simulation.cbtc.data.vr.VirtualRealitySignal; import club.joylink.rtss.simulation.cbtc.data.vr.VirtualRealitySignal;
import club.joylink.rtss.simulation.cbtc.device.virtual.VirtualRealityDeviceService; import club.joylink.rtss.simulation.cbtc.device.virtual.VirtualRealityDeviceService;
import java.util.Objects;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@ -22,10 +23,10 @@ public class CiSignalControlService {
* @return * @return
*/ */
private boolean couldOpenLogicAspect(Signal signal, SignalAspect aspect) { private boolean couldOpenLogicAspect(Signal signal, SignalAspect aspect) {
if(signal.getSignalModel().getGuideAspect().equals(aspect)) { if (Objects.equals(signal.getSignalModel().getGuideAspect(), aspect)) {
return false; return false;
} }
if (signal.getSignalModel().getDefaultAspect().equals(aspect)) { if (Objects.equals(signal.getSignalModel().getDefaultAspect(), aspect)) {
return true; return true;
} }
// else if (aspect.equals(signal.getSignalModel().getGuideAspect()) && signal.isHigherThanGuideLevel()) { // else if (aspect.equals(signal.getSignalModel().getGuideAspect()) && signal.isHigherThanGuideLevel()) {

View File

@ -3,24 +3,66 @@ package club.joylink.rtss.simulation.cbtc.build;
import club.joylink.rtss.constants.BusinessConsts; import club.joylink.rtss.constants.BusinessConsts;
import club.joylink.rtss.exception.BusinessExceptionAssertEnum; import club.joylink.rtss.exception.BusinessExceptionAssertEnum;
import club.joylink.rtss.simulation.cbtc.constant.SignalModel; 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.SectionPosition;
import club.joylink.rtss.simulation.cbtc.data.support.StationTurnBackStrategyOption; import club.joylink.rtss.simulation.cbtc.data.support.StationTurnBackStrategyOption;
import club.joylink.rtss.simulation.cbtc.data.vr.*; import club.joylink.rtss.simulation.cbtc.data.vr.VirtualRealityDevice;
import club.joylink.rtss.vo.map.MapCISwitchVO; 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.MapGraphDataNewVO;
import club.joylink.rtss.vo.map.MapVO; import club.joylink.rtss.vo.map.MapVO;
import club.joylink.rtss.vo.map.RealLineConfigVO; 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 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 lombok.extern.slf4j.Slf4j;
import org.springframework.util.CollectionUtils; import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils; 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)) .filter(mapElement -> Objects.equals(mapElement.getDeviceType(), MapElement.DeviceType.STATION))
.map(mapElement -> ((Station) mapElement)) .map(mapElement -> ((Station) mapElement))
.collect(Collectors.toList()); .collect(Collectors.toList());
stations.forEach(station -> { // stations.forEach(station -> {
if (station.isDepot()) { // 是车辆段/停车场 // if (station.isDepot()) { // 是车辆段/停车场
if (CollectionUtils.isEmpty(station.getTransferList())) { // if (CollectionUtils.isEmpty(station.getTransferList())) {
errMsgList.add(String.format("车站[%s(%s)]是停车场/车辆段,却没有找到任何转换轨", // errMsgList.add(String.format("车站[%s(%s)]是停车场/车辆段,却没有找到任何转换轨",
station.getName(), station.getCode())); // 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)]是折返站,却没有折返策略"));
// } // }
} // } 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()) { if (section.isStandTrack() && !section.isNormalStandTrack()) {
errMsgList.add(String.format("区段[%s]不是正常站台的站台轨,却设置了站台轨属性", section.debugStr())); errMsgList.add(String.format("区段[%s]不是正常站台的站台轨,却设置了站台轨属性", section.debugStr()));
} }
//为了兼容中航的奇葩沙盘
if (section.isTransferTrack() && section.isTurnBackTrack()) {
continue;
}
if (section.isTransferTrack() && (section.getStation() == null || !section.getStation().isDepot())) { if (section.isTransferTrack() && (section.getStation() == null || !section.getStation().isDepot())) {
errMsgList.add(String.format("区段[%s]所属车站不是车辆段/停车场车站,却设置了转换轨属性", section.debugStr())); errMsgList.add(String.format("区段[%s]所属车站不是车辆段/停车场车站,却设置了转换轨属性", section.debugStr()));
} }

View File

@ -6,6 +6,7 @@ import club.joylink.rtss.entity.MapDataExample;
import club.joylink.rtss.entity.MapDataWithBLOBs; import club.joylink.rtss.entity.MapDataWithBLOBs;
import club.joylink.rtss.simulation.cbtc.GroupSimulationService; import club.joylink.rtss.simulation.cbtc.GroupSimulationService;
import club.joylink.rtss.simulation.cbtc.Simulation; 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.sr.service.SrTrainServiceImpl;
import club.joylink.rtss.simulation.cbtc.device.real.udp.thailand.service.ThailandTrainServiceImpl; import club.joylink.rtss.simulation.cbtc.device.real.udp.thailand.service.ThailandTrainServiceImpl;
import club.joylink.rtss.util.JsonUtils; import club.joylink.rtss.util.JsonUtils;
@ -26,6 +27,8 @@ public class SandTableTrainController {
private ThailandTrainServiceImpl thailandTrainService; private ThailandTrainServiceImpl thailandTrainService;
@Autowired @Autowired
private SrTrainServiceImpl srTrainService; private SrTrainServiceImpl srTrainService;
@Autowired
private NgyTrainServiceImpl ngyTrainService;
@PutMapping("/{simulationId}/control") @PutMapping("/{simulationId}/control")
public void control(@PathVariable String simulationId, String groupNumber, boolean right, public void control(@PathVariable String simulationId, String groupNumber, boolean right,
@ -38,6 +41,9 @@ public class SandTableTrainController {
case ProjectCode.SR_SANDBOX: case ProjectCode.SR_SANDBOX:
srTrainService.controlTrain(simulationId, groupNumber, right, speed); srTrainService.controlTrain(simulationId, groupNumber, right, speed);
break; break;
case ProjectCode.NGY_SAND_TABLE:
ngyTrainService.controlTrain(simulationId, groupNumber, right, speed);
break;
default: default:
} }
} }

View File

@ -11,7 +11,6 @@ import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.DatagramPacket; import io.netty.channel.socket.DatagramPacket;
import io.netty.channel.socket.nio.NioDatagramChannel; import io.netty.channel.socket.nio.NioDatagramChannel;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.time.LocalDateTime;
import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.ConcurrentLinkedQueue;
import lombok.Getter; import lombok.Getter;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@ -60,7 +59,6 @@ public class UDPClient implements ApplicationRunner {
public void write(InetSocketAddress addr, byte[] msg) { public void write(InetSocketAddress addr, byte[] msg) {
if (msg != null) { if (msg != null) {
msgQueue.add(new Msg(addr, msg)); msgQueue.add(new Msg(addr, msg));
System.out.println(LocalDateTime.now());
} }
} }

View File

@ -5,21 +5,30 @@ import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler; import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.socket.DatagramPacket; 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.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import java.net.InetSocketAddress; @Slf4j
@Component @Component
public class UDPMessageHandler extends SimpleChannelInboundHandler<DatagramPacket> { public class UDPMessageHandler extends SimpleChannelInboundHandler<DatagramPacket> {
@Autowired @Autowired
private UDPRealDeviceThread udpRealDeviceThread; private UDPRealDeviceThread udpRealDeviceThread;
Map<Integer, Long> map = new HashMap<>();
@Override @Override
protected void channelRead0(ChannelHandlerContext ctx, DatagramPacket datagramPacket) { protected void channelRead0(ChannelHandlerContext ctx, DatagramPacket datagramPacket) {
InetSocketAddress sender = datagramPacket.sender(); InetSocketAddress sender = datagramPacket.sender();
String ip = sender.getHostString(); String ip = sender.getHostString();
int port = sender.getPort(); 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(); ByteBuf content = datagramPacket.content();
udpRealDeviceThread.handleData(ip, port, content); udpRealDeviceThread.handleData(ip, port, content);
} }

View File

@ -33,6 +33,30 @@ public class NgySectionServiceImpl implements UDPRealDeviceService {
@Override @Override
public void run(Simulation simulation, UDPLowConfig udpLowConfig, RealDeviceConfig realDevice) { public void run(Simulation simulation, UDPLowConfig udpLowConfig, RealDeviceConfig realDevice) {
// // TODO: 2023/7/5 模拟计轴占压数据
// List<VirtualRealityTrain> 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 @Override
@ -71,11 +95,11 @@ public class NgySectionServiceImpl implements UDPRealDeviceService {
config.setTimesOfRelease(0); config.setTimesOfRelease(0);
axle.setOccupy(true); axle.setOccupy(true);
} else if (n == 85) { } else if (n == 85) {
// config.setTimesOfRelease(config.getTimesOfRelease() + 1); config.setTimesOfRelease(config.getTimesOfRelease() + 1);
// if (config.getTimesOfRelease() > 2) { //连续3次该计轴都是无占用状态才视为确实无占用 if (config.getTimesOfRelease() > 1) { //连续2次该计轴都是无占用状态才视为确实无占用
config.setTimesOfRelease(0); config.setTimesOfRelease(0);
axle.clear(); axle.clear();
// } }
} }
} }
} }

View File

@ -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.UDPLowConfig;
import club.joylink.rtss.simulation.cbtc.device.real.udp.UDPRealDeviceService; 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.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.device.real.udp.config.SandTableTrainConfig;
import club.joylink.rtss.simulation.cbtc.onboard.ATP.ATPService; import club.joylink.rtss.simulation.cbtc.onboard.ATP.ATPService;
import club.joylink.rtss.simulation.cbtc.robot.SimulationRobotService; import club.joylink.rtss.simulation.cbtc.robot.SimulationRobotService;
import club.joylink.rtss.vo.client.project.thailand.ThailandSectionConfigVO;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.Objects; import java.util.Objects;
@ -32,6 +32,7 @@ import java.util.Optional;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
@Slf4j @Slf4j
@Service @Service
@ -99,6 +100,11 @@ public class NgyTrainServiceImpl implements UDPRealDeviceService {
udpClient.write(udpLowConfig.getAddr(), data); udpClient.write(udpLowConfig.getAddr(), data);
//清除状态 //清除状态
config.updateHeadSection(null); config.updateHeadSection(null);
//设置停站时间
simulation.getRepository().getStandList().forEach(stand -> {
stand.setParkingTime(10);
stand.setParkingAlwaysValid(true);
});
} }
@Override @Override
@ -163,10 +169,11 @@ public class NgyTrainServiceImpl implements UDPRealDeviceService {
if (previousSection != null && !previousSection.isOccupied()) { if (previousSection != null && !previousSection.isOccupied()) {
delayOfNano = (long) (sectionConfig.getConfigVO().getTailDelayTime() * rate); delayOfNano = (long) (sectionConfig.getConfigVO().getTailDelayTime() * rate);
} }
} else { //未设置则认为车头占压即刻停车 } else { //未设置
delayOfNano = 0L; delayOfNano = (long) (0 * rate);
} }
if (delayOfNano != null) { if (delayOfNano != null) {
System.out.printf("设置延时%s%d%n", headSection.getName(), delayOfNano);
config.setTimeOfArriveStopPoint(now.plusNanos(delayOfNano)); config.setTimeOfArriveStopPoint(now.plusNanos(delayOfNano));
} }
} }
@ -179,11 +186,11 @@ public class NgyTrainServiceImpl implements UDPRealDeviceService {
if (stopPosition != null && stopPosition.getSection().equals(headSection)) { if (stopPosition != null && stopPosition.getSection().equals(headSection)) {
train.setHeadPosition(stopPosition); train.setHeadPosition(stopPosition);
} else { } else {
float offset = right ? headSection.getMaxOffset() : 0; float offset = headSection.getEndOffsetByDirection(right);
train.setHeadPosition(new SectionPosition(headSection, offset)); train.setHeadPosition(new SectionPosition(headSection, offset));
} }
} }
//更新速度由于沙盘对延时要求很高机器人驾驶逻辑频率有点低所以选择不利用机器人驾驶的逻辑
if (config.getManualGear() != null) { if (config.getManualGear() != null) {
return; return;
} }
@ -193,6 +200,22 @@ public class NgyTrainServiceImpl implements UDPRealDeviceService {
return; 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) { if (stopPosition != null) {
Float distance = CalculateService.calculateDistance(train.getHeadPosition(), stopPosition, Float distance = CalculateService.calculateDistance(train.getHeadPosition(), stopPosition,
right, false); right, false);
@ -206,14 +229,6 @@ public class NgyTrainServiceImpl implements UDPRealDeviceService {
train.setSpeed(lowSpeed); train.setSpeed(lowSpeed);
return; 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); train.setSpeed(highSpeed);
} else { } else {
train.setSpeed(0); train.setSpeed(0);
@ -258,7 +273,7 @@ public class NgyTrainServiceImpl implements UDPRealDeviceService {
gear = (int) Math.ceil(speedKmPh / 10); gear = (int) Math.ceil(speedKmPh / 10);
gear = Math.max(1, gear); gear = Math.max(1, gear);
} }
if (train.isRight()) { //档位1-5是正向6-10是反向 if (!train.isRight()) { //档位1-5是正向6-10是反向
gear += 5; 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 headDelayTime = null;
Float tailDelayTime = null; Float tailDelayTime = null;
if (section.isStandTrack()) { //站台轨默认为车尾出清立即停车 if (section.isFunctionTrack()) {
headDelayTime = 5f; if (section.isStandTrack()) {
tailDelayTime = 1f;
} else {
tailDelayTime = 0f;
}
} else {
headDelayTime = 2f;
} }
switch (section.getCode()) { switch (section.getCode()) {
case "T233": //X302G case "T68": // 43G
headDelayTime = 7.3f; tailDelayTime = 1.4f;
break; break;
case "T232": //X303G case "T62": //37G
headDelayTime = 6.5f; tailDelayTime = 0.8f;
break; break;
case "T231": //X304G case "T35": //9G
headDelayTime = 5.5f; tailDelayTime = 1.3f;
break; break;
case "T178": //4站-3G case "T33": //5G
headDelayTime = 5.2f; tailDelayTime = 0.9f;
break; break;
case "T177": //4站-IG case "T5": //8G
headDelayTime = 5.4f; tailDelayTime = 0.8f;
break; break;
case "T175": //4站-IIG case "T7": //12G
headDelayTime = 6.6f; tailDelayTime = 0.6f;
break; break;
case "T174": //4站-4G case "T45": //24G
headDelayTime = 6.2f; tailDelayTime = 0.8f;
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;
break; break;
} }
configVO.setHeadDelayTime(headDelayTime); configVO.setHeadDelayTime(headDelayTime);
@ -382,10 +340,10 @@ public class NgyTrainServiceImpl implements UDPRealDeviceService {
atpService.turnDirectionImmediately(train); atpService.turnDirectionImmediately(train);
} }
train.setRobotTargetPosition(null); //终止机器人司机驾驶 train.setRobotTargetPosition(null); //终止机器人司机驾驶
//加减速 // //加减速
if (train.isEB()) { // if (train.isEB()) {
return; // return;
} // }
atpService.changeGear(train, VirtualRealityTrain.Handwheel.MANUAL); atpService.changeGear(train, VirtualRealityTrain.Handwheel.MANUAL);
int manualGear = speed / 10; int manualGear = speed / 10;
config.setManualGear(manualGear); config.setManualGear(manualGear);

View File

@ -196,11 +196,11 @@ public class SimulationRobotService {
doBreakMax(simulation, train); doBreakMax(simulation, train);
} }
} else if (train.isRobotNeedRun() && (train.isRMMode() } else if (train.isRobotNeedRun() && (train.isRMMode()
|| train.isNRMMode())) { //CM应当根据推荐速度驾驶待实现 || train.isNRMMode())) { //CM应当根据推荐速度驾驶待实现
VirtualRealityTrain linkTrain = train.getLinkTrain(); VirtualRealityTrain linkTrain = train.getLinkTrain();
if (linkTrain == null) { if (linkTrain == null) {
Optional<SectionPosition> targetPositionOptional = calculateTargetPosition(simulation, Optional<SectionPosition> targetPositionOptional = calculateTargetPosition(simulation,
train); train);
targetPositionOptional.ifPresent(tp -> robotDrive(simulation, driver, train, tp)); targetPositionOptional.ifPresent(tp -> robotDrive(simulation, driver, train, tp));
} else { } else {
robotDrive(simulation, driver, train, train.getRobotTargetPosition()); robotDrive(simulation, driver, train, train.getRobotTargetPosition());
@ -256,7 +256,8 @@ public class SimulationRobotService {
SignalAspect throughAspect = robotDriveParam.getThroughSignalAspect(); SignalAspect throughAspect = robotDriveParam.getThroughSignalAspect();
Section section = headPosition.getSection(); Section section = headPosition.getSection();
if (throughSignal != null && !Objects.equals(section, throughSignal.getSection())) { //当车头与要越过的信号机不在同一区段 if (throughSignal != null && !Objects.equals(section,
throughSignal.getSection())) { //当车头与要越过的信号机不在同一区段
throughSignal = null; throughSignal = null;
throughAspect = null; throughAspect = null;
robotDriveParam.setThrough(DriveParamVO.NO); robotDriveParam.setThrough(DriveParamVO.NO);
@ -268,40 +269,35 @@ public class SimulationRobotService {
// 车头在正常的站台上 // 车头在正常的站台上
if (section.isNormalStandTrack() && !section.equals(train.getParkSection())) { //正常站台轨且未在此处停过车 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); 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; targetPosition = stopPosition;
} }
} }
} }
} }
// 取禁止信号前停车位置与当前目标停车位置中更近的一个 targetPosition = updateTargetPositionOfSignal(headPosition, right,
Signal signal = section.getSignalOf(right); throughSignal, throughAspect, section, i, targetPosition, train.isParkingAt());
if (signal != null && !signal.isShunting()) { // 信号机不为调车信号机
VirtualRealitySignal vrSignal = signal.getVirtualSignal(); Section tempSection = section.findNextRunningSectionBaseRealSwitch(right);
SectionPosition signalPosition = signal.getPosition(); if (tempSection != null && tempSection.isOccupied()) {
if (vrSignal != null && (i != 0 || signalPosition.isAheadOf(headPosition, right))) { //有实体信号机且列车未越过信号机 SectionPosition newTP = CalculateService.calculateNextPositionByStartAndLen(
if (Objects.equals(vrSignal.getAspect(), signal.getDefaultAspect()) //禁止信号 new SectionPosition(section, section.getEndOffsetByDirection(!right)), !right, 2, true);
|| Objects.equals(vrSignal.getAspect(), signal.getGuideAspect())) { //引导信号 if (targetPosition == null || newTP.isAheadOf(targetPosition, !right)) {
if (!Objects.equals(signal, throughSignal) || !Objects.equals(vrSignal.getAspect(), throughAspect)) { targetPosition = newTP;
SectionPosition noPassPosition = CalculateService.calculateNextPositionByStartAndLen(signalPosition, !right, 2, true);
if (targetPosition == null || noPassPosition.isAheadOf(targetPosition, right)) {
targetPosition = noPassPosition;
}
}
}
} }
} }
if (targetPosition == null) { if (targetPosition == null) {
if (selectedPosition != null && section.equals(selectedPosition.getSection())) { //不会有比选定位置更靠前的停车点了 if (selectedPosition != null && section.equals(
selectedPosition.getSection())) { //不会有比选定位置更靠前的停车点了
targetPosition = selectedPosition; targetPosition = selectedPosition;
} else { } else {
Section tempSection = section.findNextRunningSectionBaseRealSwitch(right);
if (tempSection == null) { //到了轨道尽头目标位置为尽头向内10m if (tempSection == null) { //到了轨道尽头目标位置为尽头向内10m
targetPosition = new SectionPosition(section, right ? section.getLen() - 10 : 10); targetPosition = new SectionPosition(section, right ? section.getLen() - 10 : 10);
} else { } else {
@ -310,13 +306,13 @@ public class SimulationRobotService {
} }
} else { } else {
if (selectedPosition != null) { if (selectedPosition != null) {
if (selectedPosition.isAheadOf(targetPosition, right)) { if (selectedPosition.isAheadOf(targetPosition, !right)) {
targetPosition = selectedPosition; targetPosition = selectedPosition;
} else { } else {
break; break;
} }
} }
if (selectedPosition != null && selectedPosition.isAheadOf(targetPosition, right)) { if (selectedPosition != null && selectedPosition.isAheadOf(targetPosition, !right)) {
targetPosition = selectedPosition; targetPosition = selectedPosition;
} else { } else {
@ -329,7 +325,53 @@ public class SimulationRobotService {
if (targetPosition == null) { //上方的区段遍历完后即没有找到目标区段也没有找到轨道尽头 if (targetPosition == null) { //上方的区段遍历完后即没有找到目标区段也没有找到轨道尽头
targetPosition = new SectionPosition(section, right ? 0 : section.getMaxOffset()); 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, private void releaseEB(Simulation simulation, SimulationMember driver,

View File

@ -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.modbustcp.zjd.ZjdPslConfig;
import club.joylink.rtss.simulation.cbtc.device.real.udp.UDPClientConfig; 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.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.SrSectionConfig;
import club.joylink.rtss.simulation.cbtc.device.real.udp.sr.config.SrSignalConfig; import club.joylink.rtss.simulation.cbtc.device.real.udp.sr.config.SrSignalConfig;
import club.joylink.rtss.simulation.cbtc.device.real.udp.sr.config.SrSwitchConfig; import club.joylink.rtss.simulation.cbtc.device.real.udp.sr.config.SrSwitchConfig;
@ -147,12 +151,43 @@ public class ProjectDeviceVO {
case "GXSD": { case "GXSD": {
return gxsdDeviceConfigConvert(voList); return gxsdDeviceConfigConvert(voList);
} }
case ProjectCode.NGY_SAND_TABLE: {
return sandTableDeviceConfigConvert(voList);
}
} }
} }
return list; return list;
} }
private static List<RealDeviceConfig> sandTableDeviceConfigConvert(
List<ProjectDeviceVO> voList) {
List<RealDeviceConfig> 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<RealDeviceConfig> thailandSandboxDeviceConfigConvert( private static List<RealDeviceConfig> thailandSandboxDeviceConfigConvert(
List<ProjectDeviceVO> voList) { List<ProjectDeviceVO> voList) {
List<RealDeviceConfig> list = new ArrayList<>(); List<RealDeviceConfig> list = new ArrayList<>();