进路人工办理优先于自动办理(人工办理进路会将与其冲突的、尚未办理完成的进路取消掉)
This commit is contained in:
parent
4becfd48cb
commit
5eac7cc9be
|
@ -30,40 +30,10 @@ public class SignalOperateHandler {
|
|||
*/
|
||||
@OperateHandlerMapping(type = Operation.Type.Signal_Set_Route)
|
||||
public void settingRoute(Simulation simulation, String routeCode) throws InterruptedException {
|
||||
// Route.CheckFailMessage checkResult = this.ciApiService.routeSettingCheck(simulation, routeCode);
|
||||
// if (checkResult != null)
|
||||
// log.info(checkResult.debugStr());
|
||||
Route.CheckFailMessage checkFailMessage = this.ciApiService.settingRoute(simulation, routeCode);
|
||||
Route.CheckFailMessage checkFailMessage = this.ciApiService.settingRoute(simulation, routeCode,
|
||||
true);
|
||||
BusinessExceptionAssertEnum.SIMULATION_EXCEPTION_FOR_SHOW.assertNull(checkFailMessage,
|
||||
"进路排列失败,被联锁逻辑取消");
|
||||
|
||||
// //等待进路办理完成
|
||||
// LocalDateTime timeoutTime = simulation.getSystemTime().plusSeconds(20);
|
||||
// Route route = simulation.getRepository().getByCode(routeCode, Route.class);
|
||||
// CompletableFuture<Boolean> future = CompletableFuture.supplyAsync(() -> {
|
||||
// while (true) {
|
||||
// if (route.getSettedAspect().equals(route.getStart().getAspect()) ||
|
||||
// (route.isGuideSetting() && route.getStart().isGuideAspect())) {
|
||||
// return true;
|
||||
// }
|
||||
// if (simulation.getSystemTime().isAfter(timeoutTime)) {
|
||||
// return false;
|
||||
// }
|
||||
// try {
|
||||
// Thread.sleep(100);
|
||||
// } catch (InterruptedException e) {
|
||||
// throw new RuntimeException(e);
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
// try {
|
||||
// Boolean success = future.get();
|
||||
// BusinessExceptionAssertEnum.OPERATION_FAIL.assertTrue(success);
|
||||
// } catch (BaseException be) {
|
||||
// throw be;
|
||||
// } catch (Exception e) {
|
||||
// throw BusinessExceptionAssertEnum.SYSTEM_EXCEPTION.exception();
|
||||
// }
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -101,24 +71,9 @@ public class SignalOperateHandler {
|
|||
public void setOverlap(Simulation simulation, String signalCode, String overlapCode) {
|
||||
this.atsRouteService.setOverlap(simulation, signalCode, overlapCode);
|
||||
}
|
||||
// /**
|
||||
// * 取消进路(强制取消进路,无论接近区段是否占用,如果占用延时取消)
|
||||
// * @param simulation
|
||||
// * @param signalCode
|
||||
// */
|
||||
// @OperateHandlerMapping(type = Operation2.Type.Signal_Force_Cancel_Route)
|
||||
// public void forceCancelRoute(Simulation simulation, String signalCode) {
|
||||
// Route route = this.ciApiService.findLockedRouteByStartSignal(simulation, signalCode);
|
||||
// if (Objects.nonNull(route)) {
|
||||
// this.ciApiService.forceUnlockRoute(simulation, route.getCode());
|
||||
// }
|
||||
// }
|
||||
|
||||
/**
|
||||
* 总人解
|
||||
*
|
||||
* @param simulation
|
||||
* @param signalCode
|
||||
*/
|
||||
@OperateHandlerMapping(type = Operation.Type.Signal_Human_Release_Route)
|
||||
public void humanCancel(Simulation simulation, String signalCode) {
|
||||
|
@ -130,9 +85,6 @@ public class SignalOperateHandler {
|
|||
|
||||
/**
|
||||
* 信号封锁
|
||||
*
|
||||
* @param simulation
|
||||
* @param signalCode
|
||||
*/
|
||||
@OperateHandlerMapping(type = Operation.Type.Signal_Block)
|
||||
public void block(Simulation simulation, String signalCode) {
|
||||
|
@ -141,9 +93,6 @@ public class SignalOperateHandler {
|
|||
|
||||
/**
|
||||
* 信号解封
|
||||
*
|
||||
* @param simulation
|
||||
* @param signalCode
|
||||
*/
|
||||
@OperateHandlerMapping(type = Operation.Type.Signal_Unblock)
|
||||
public void unblock(Simulation simulation, String signalCode) {
|
||||
|
@ -152,9 +101,6 @@ public class SignalOperateHandler {
|
|||
|
||||
/**
|
||||
* 进路收人工控
|
||||
*
|
||||
* @param simulation
|
||||
* @param routeCodeList
|
||||
*/
|
||||
@OperateHandlerMapping(type = Operation.Type.Signal_Close_Auto_Setting)
|
||||
public void setRouteHumanControl(Simulation simulation, String signalCode,
|
||||
|
@ -164,9 +110,6 @@ public class SignalOperateHandler {
|
|||
|
||||
/**
|
||||
* 进路交ATS自动控
|
||||
*
|
||||
* @param simulation
|
||||
* @param routeCodeList
|
||||
*/
|
||||
@OperateHandlerMapping(type = Operation.Type.Signal_Open_Auto_Setting)
|
||||
public void setRouteAtsControl(Simulation simulation, String signalCode,
|
||||
|
@ -179,9 +122,7 @@ public class SignalOperateHandler {
|
|||
/**
|
||||
* 冲突进路办理确认
|
||||
*
|
||||
* @param simulation
|
||||
* @param routeCode
|
||||
* @param way 处理方式:1-按计划执行,2-执行冲突进路
|
||||
* @param way 处理方式:1-按计划执行,2-执行冲突进路
|
||||
*/
|
||||
@OperateHandlerMapping(type = Operation.Type.Signal_Conflict_Route_Set_Confirm)
|
||||
public void conflictRouteSetConfirm(Simulation simulation, SimulationMember member,
|
||||
|
@ -192,9 +133,6 @@ public class SignalOperateHandler {
|
|||
|
||||
/**
|
||||
* 信号关灯
|
||||
*
|
||||
* @param simulation
|
||||
* @param signalCode
|
||||
*/
|
||||
@OperateHandlerMapping(type = Operation.Type.Signal_Close_Signal)
|
||||
public void closeSignal(Simulation simulation, String signalCode) {
|
||||
|
@ -203,31 +141,14 @@ public class SignalOperateHandler {
|
|||
|
||||
/**
|
||||
* 信号重开
|
||||
*
|
||||
* @param simulation
|
||||
* @param signalCode
|
||||
*/
|
||||
@OperateHandlerMapping(type = Operation.Type.Signal_Reopen_Signal)
|
||||
public void reopenSignal(Simulation simulation, String signalCode) {
|
||||
this.ciApiService.reopenSignal(simulation, signalCode);
|
||||
}
|
||||
|
||||
// /**
|
||||
// * 办理引导进路
|
||||
// * @param simulation
|
||||
// * @param routeCode
|
||||
// */
|
||||
// @OperateHandlerMapping(type = Operation2.Type.Signal_Route_Guide)
|
||||
// public void settingGuideRoute(Simulation simulation, String routeCode) {
|
||||
// iciSubsystem.settingGuideRoute(simulation, routeCode);
|
||||
// }
|
||||
|
||||
/**
|
||||
* 查找进路控制模式/状态
|
||||
*
|
||||
* @param simulation
|
||||
* @param signalCode
|
||||
* @return
|
||||
*/
|
||||
@OperateHandlerMapping(type = Operation.Type.Signal_Find_Routes_Status)
|
||||
public List<RouteStatus> findRoutesStatus(Simulation simulation, String signalCode) {
|
||||
|
@ -236,9 +157,6 @@ public class SignalOperateHandler {
|
|||
|
||||
/**
|
||||
* 设置联锁自动进路
|
||||
*
|
||||
* @param simulation
|
||||
* @param signalCode
|
||||
*/
|
||||
@OperateHandlerMapping(type = Operation.Type.Signal_Set_CI_Auto)
|
||||
public void setCiAuto(Simulation simulation, String signalCode) {
|
||||
|
@ -247,9 +165,6 @@ public class SignalOperateHandler {
|
|||
|
||||
/**
|
||||
* 取消联锁自动进路
|
||||
*
|
||||
* @param simulation
|
||||
* @param signalCode
|
||||
*/
|
||||
@OperateHandlerMapping(type = Operation.Type.Signal_Cancel_CI_Auto)
|
||||
public void cancelCiAuto(Simulation simulation, String signalCode) {
|
||||
|
@ -257,12 +172,8 @@ public class SignalOperateHandler {
|
|||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 设置联锁自动触发
|
||||
*
|
||||
* @param simulation
|
||||
* @param signalCode
|
||||
*/
|
||||
@OperateHandlerMapping(type = Operation.Type.Signal_Set_CI_Auto_Trigger)
|
||||
public void setCiAutoTrigger(Simulation simulation, String signalCode,
|
||||
|
@ -272,9 +183,6 @@ public class SignalOperateHandler {
|
|||
|
||||
/**
|
||||
* 取消联锁自动触发
|
||||
*
|
||||
* @param simulation
|
||||
* @param signalCode
|
||||
*/
|
||||
@OperateHandlerMapping(type = Operation.Type.Signal_Cancel_CI_Auto_Trigger)
|
||||
public void cancelCiAutoTrigger(Simulation simulation, String signalCode,
|
||||
|
@ -282,26 +190,6 @@ public class SignalOperateHandler {
|
|||
atsRouteService.cancelCiAutoTrigger(simulation, signalCode, routeCodeList);
|
||||
}
|
||||
|
||||
// /**
|
||||
// * 开启进路引导信号
|
||||
// * @param simulation
|
||||
// * @param signalCode
|
||||
// */
|
||||
// @OperateHandlerMapping(type = Operation2.Type.Signal_Open_Guide_Check_Switch)
|
||||
// public void openGuideCheckSwitch(Simulation simulation, String signalCode) {
|
||||
// this.iciSubsystem.openGuideSignalCheckSwitch(simulation, signalCode);
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 开启进路引导信号
|
||||
// * @param simulation
|
||||
// * @param signalCode
|
||||
// */
|
||||
// @OperateHandlerMapping(type = Operation2.Type.Signal_Open_Guide_Check_Route)
|
||||
// public void openGuideCheckRoute(Simulation simulation, String signalCode) {
|
||||
// this.iciSubsystem.openGuideSignalCheckRoute(simulation, signalCode);
|
||||
// }
|
||||
|
||||
/**
|
||||
* 设置自动折返进路
|
||||
*/
|
||||
|
|
|
@ -13,305 +13,326 @@ import club.joylink.rtss.simulation.cbtc.data.status.RouteStatus;
|
|||
import club.joylink.rtss.simulation.cbtc.exception.SimulationException;
|
||||
import club.joylink.rtss.simulation.cbtc.exception.SimulationExceptionType;
|
||||
import club.joylink.rtss.simulation.cbtc.member.SimulationMember;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
public class AtsRouteService {
|
||||
|
||||
@Autowired
|
||||
private CiRouteService routeService;
|
||||
@Autowired
|
||||
private CiRouteService routeService;
|
||||
|
||||
@Autowired
|
||||
private CiApiService ciApiService;
|
||||
@Autowired
|
||||
private CiApiService ciApiService;
|
||||
|
||||
/**
|
||||
* 进路收人工控
|
||||
*
|
||||
* @param simulation
|
||||
* @param signalCode
|
||||
* @param routeCodeList
|
||||
*/
|
||||
public void setRouteHumanControl(Simulation simulation, String signalCode, List<String> routeCodeList) {
|
||||
if (!CollectionUtils.isEmpty(routeCodeList)) {
|
||||
routeCodeList.forEach(routeCode -> {
|
||||
Route route = simulation.getRepository().getByCode(routeCode, Route.class);
|
||||
route.setAtsControl(false);
|
||||
});
|
||||
} else if (StringUtils.hasText(signalCode)) {
|
||||
Signal signal = simulation.getRepository().getByCode(signalCode, Signal.class);
|
||||
List<Route> routeList = signal.getRouteList();
|
||||
if (!CollectionUtils.isEmpty(routeList)) {
|
||||
routeList.forEach(route -> route.setAtsControl(false));
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 进路收人工控
|
||||
*
|
||||
* @param simulation
|
||||
* @param signalCode
|
||||
* @param routeCodeList
|
||||
*/
|
||||
public void setRouteHumanControl(Simulation simulation, String signalCode,
|
||||
List<String> routeCodeList) {
|
||||
if (!CollectionUtils.isEmpty(routeCodeList)) {
|
||||
routeCodeList.forEach(routeCode -> {
|
||||
Route route = simulation.getRepository().getByCode(routeCode, Route.class);
|
||||
route.setAtsControl(false);
|
||||
});
|
||||
} else if (StringUtils.hasText(signalCode)) {
|
||||
Signal signal = simulation.getRepository().getByCode(signalCode, Signal.class);
|
||||
List<Route> routeList = signal.getRouteList();
|
||||
if (!CollectionUtils.isEmpty(routeList)) {
|
||||
routeList.forEach(route -> route.setAtsControl(false));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 进路交自动控
|
||||
*/
|
||||
public void setRouteAtsControl(Simulation simulation, String signalCode,
|
||||
List<String> routeCodeList, List<Boolean> checkConflictList) {
|
||||
SimulationDataRepository repository = simulation.getRepository();
|
||||
if (!CollectionUtils.isEmpty(routeCodeList)) {
|
||||
if (!CollectionUtils.isEmpty(checkConflictList)) {
|
||||
BusinessExceptionAssertEnum.ARGUMENT_ILLEGAL.assertTrue(routeCodeList.size() == checkConflictList.size(),
|
||||
String.format("进路数和是否检查冲突数量不一致:[%s], [%s]",
|
||||
String.join(",", routeCodeList),
|
||||
String.join(",", checkConflictList.stream().map(String::valueOf).collect(Collectors.toList()))));
|
||||
}
|
||||
List<Route> routes = routeCodeList.stream().map(routeCode -> repository.getByCode(routeCode, Route.class)).collect(Collectors.toList());
|
||||
if (repository.getConfig().isSignalHumanControlBeforeSetAtsControlOrCIAutoTrigger()) {
|
||||
routes.stream()
|
||||
.map(Route::getStart)
|
||||
.distinct()
|
||||
.forEach(signal ->
|
||||
BusinessExceptionAssertEnum.OPERATION_NOT_SUPPORTED
|
||||
.assertNotTrue(signal.isCiControl(),
|
||||
String.format("信号机[%s]需处于人工控状态", signal.getCode())));
|
||||
}
|
||||
if (CollectionUtils.isEmpty(checkConflictList)) {
|
||||
routes.forEach(route -> route.setAtsControl(true));
|
||||
} else {
|
||||
for (int i = 0; i < routeCodeList.size(); i++) {
|
||||
Route route = repository.getByCode(routeCodeList.get(i), Route.class);
|
||||
boolean checkConflict = checkConflictList.get(i);
|
||||
route.setAtsControl(true);
|
||||
route.setCheckConflict(checkConflict);
|
||||
}
|
||||
}
|
||||
} else if (StringUtils.hasText(signalCode)) {
|
||||
Signal signal = repository.getByCode(signalCode, Signal.class);
|
||||
if (repository.getConfig().isSignalHumanControlBeforeSetAtsControlOrCIAutoTrigger()) {
|
||||
BusinessExceptionAssertEnum.OPERATION_NOT_SUPPORTED.assertNotTrue(signal.isCiControl(), String.format("信号机[%s]需处于人工控状态", signal.getCode()));
|
||||
}
|
||||
List<Route> routeList = signal.getRouteList();
|
||||
if (!CollectionUtils.isEmpty(routeList)) {
|
||||
routeList.forEach(route -> route.setAtsControl(true));
|
||||
}
|
||||
/**
|
||||
* 进路交自动控
|
||||
*/
|
||||
public void setRouteAtsControl(Simulation simulation, String signalCode,
|
||||
List<String> routeCodeList, List<Boolean> checkConflictList) {
|
||||
SimulationDataRepository repository = simulation.getRepository();
|
||||
if (!CollectionUtils.isEmpty(routeCodeList)) {
|
||||
if (!CollectionUtils.isEmpty(checkConflictList)) {
|
||||
BusinessExceptionAssertEnum.ARGUMENT_ILLEGAL.assertTrue(
|
||||
routeCodeList.size() == checkConflictList.size(),
|
||||
String.format("进路数和是否检查冲突数量不一致:[%s], [%s]",
|
||||
String.join(",", routeCodeList),
|
||||
String.join(",",
|
||||
checkConflictList.stream().map(String::valueOf).collect(Collectors.toList()))));
|
||||
}
|
||||
List<Route> routes = routeCodeList.stream()
|
||||
.map(routeCode -> repository.getByCode(routeCode, Route.class))
|
||||
.collect(Collectors.toList());
|
||||
if (repository.getConfig().isSignalHumanControlBeforeSetAtsControlOrCIAutoTrigger()) {
|
||||
routes.stream()
|
||||
.map(Route::getStart)
|
||||
.distinct()
|
||||
.forEach(signal ->
|
||||
BusinessExceptionAssertEnum.OPERATION_NOT_SUPPORTED
|
||||
.assertNotTrue(signal.isCiControl(),
|
||||
String.format("信号机[%s]需处于人工控状态", signal.getCode())));
|
||||
}
|
||||
if (CollectionUtils.isEmpty(checkConflictList)) {
|
||||
routes.forEach(route -> route.setAtsControl(true));
|
||||
} else {
|
||||
for (int i = 0; i < routeCodeList.size(); i++) {
|
||||
Route route = repository.getByCode(routeCodeList.get(i), Route.class);
|
||||
boolean checkConflict = checkConflictList.get(i);
|
||||
route.setAtsControl(true);
|
||||
route.setCheckConflict(checkConflict);
|
||||
}
|
||||
}
|
||||
} else if (StringUtils.hasText(signalCode)) {
|
||||
Signal signal = repository.getByCode(signalCode, Signal.class);
|
||||
if (repository.getConfig().isSignalHumanControlBeforeSetAtsControlOrCIAutoTrigger()) {
|
||||
BusinessExceptionAssertEnum.OPERATION_NOT_SUPPORTED.assertNotTrue(signal.isCiControl(),
|
||||
String.format("信号机[%s]需处于人工控状态", signal.getCode()));
|
||||
}
|
||||
List<Route> routeList = signal.getRouteList();
|
||||
if (!CollectionUtils.isEmpty(routeList)) {
|
||||
routeList.forEach(route -> route.setAtsControl(true));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询进路状态/模式
|
||||
*/
|
||||
public List<RouteStatus> findRoutesStatus(Simulation simulation, String signalCode) {
|
||||
Signal signal = simulation.getRepository().getByCode(signalCode, Signal.class);
|
||||
List<Route> routeList = signal.getRouteList();
|
||||
return routeList.stream().map(RouteStatus::new).collect(Collectors.toList());
|
||||
/**
|
||||
* 查询进路状态/模式
|
||||
*/
|
||||
public List<RouteStatus> findRoutesStatus(Simulation simulation, String signalCode) {
|
||||
Signal signal = simulation.getRepository().getByCode(signalCode, Signal.class);
|
||||
List<Route> routeList = signal.getRouteList();
|
||||
return routeList.stream().map(RouteStatus::new).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置联锁自动进路
|
||||
*/
|
||||
public void setCiAuto(Simulation simulation, String signalCode) {
|
||||
Signal signal = simulation.getRepository().getByCode(signalCode, Signal.class);
|
||||
if (simulation.getRepository().getConfig().isSetRouteBeforeSetFlt()) {
|
||||
Route lockedRoute = signal.getLockedRoute();
|
||||
if (lockedRoute == null) {
|
||||
throw new SimulationException(SimulationExceptionType.Operation_Handle_FAIL,
|
||||
String.format("信号机[%s(%s)]没有已锁闭进路,不能设置联锁自动进路", signal.getName(),
|
||||
signal.getCode()));
|
||||
}
|
||||
if (!lockedRoute.isFlt()) {
|
||||
throw new SimulationException(SimulationExceptionType.Unsupported_Operation,
|
||||
String.format("进路[%s]不能设置车队进路", lockedRoute.getCode()));
|
||||
}
|
||||
if (lockedRoute.isCiControl()) {
|
||||
throw new SimulationException(SimulationExceptionType.Operation_Conflict,
|
||||
String.format("进路[%s(%s)]自动追踪已开启,不能设置联锁自动进路", lockedRoute.getName(),
|
||||
lockedRoute.getCode()));
|
||||
}
|
||||
lockedRoute.setFleetMode(true);
|
||||
} else {
|
||||
List<Route> routeList = signal.getRouteList();
|
||||
BusinessExceptionAssertEnum.ARGUMENT_ILLEGAL.assertCollectionNotEmpty(routeList,
|
||||
signal.debugStr() + "不是进路始端信号机");
|
||||
// 筛选最适合的进路,筛选逻辑与办理引导时筛选逻辑类似
|
||||
List<Route> fltRoutes = routeList.stream().filter(Route::isFlt).collect(Collectors.toList());
|
||||
BusinessExceptionAssertEnum.ARGUMENT_ILLEGAL.assertCollectionNotEmpty(fltRoutes,
|
||||
signal.debugStr() + "下没有可设置的车队进路");
|
||||
List<Route> collect = fltRoutes.stream()
|
||||
.filter(r -> !r.isTurnBack() && CollectionUtils.isEmpty(r.getSwitchList()))
|
||||
.collect(Collectors.toList());
|
||||
if (CollectionUtils.isEmpty(collect)) {
|
||||
collect = fltRoutes.stream().filter(r -> !r.isTurnBack()).collect(Collectors.toList());
|
||||
}
|
||||
if (CollectionUtils.isEmpty(collect)) {
|
||||
collect = fltRoutes;
|
||||
}
|
||||
Route route = collect.get(0);
|
||||
Route.CheckFailMessage message = routeService.setRoute(simulation, route, route.getAspect(),
|
||||
false);
|
||||
BusinessExceptionAssertEnum.OPERATION_NOT_SUPPORTED.assertNull(message,
|
||||
route.debugStr() + "无法办理");
|
||||
route.setFleetMode(true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置联锁自动进路
|
||||
*/
|
||||
public void setCiAuto(Simulation simulation, String signalCode) {
|
||||
Signal signal = simulation.getRepository().getByCode(signalCode, Signal.class);
|
||||
if (simulation.getRepository().getConfig().isSetRouteBeforeSetFlt()) {
|
||||
Route lockedRoute = signal.getLockedRoute();
|
||||
if (lockedRoute == null) {
|
||||
throw new SimulationException(SimulationExceptionType.Operation_Handle_FAIL,
|
||||
String.format("信号机[%s(%s)]没有已锁闭进路,不能设置联锁自动进路", signal.getName(), signal.getCode()));
|
||||
}
|
||||
if (!lockedRoute.isFlt()) {
|
||||
throw new SimulationException(SimulationExceptionType.Unsupported_Operation,
|
||||
String.format("进路[%s]不能设置车队进路", lockedRoute.getCode()));
|
||||
}
|
||||
if (lockedRoute.isCiControl()) {
|
||||
throw new SimulationException(SimulationExceptionType.Operation_Conflict,
|
||||
String.format("进路[%s(%s)]自动追踪已开启,不能设置联锁自动进路", lockedRoute.getName(), lockedRoute.getCode()));
|
||||
}
|
||||
lockedRoute.setFleetMode(true);
|
||||
} else {
|
||||
List<Route> routeList = signal.getRouteList();
|
||||
BusinessExceptionAssertEnum.ARGUMENT_ILLEGAL.assertCollectionNotEmpty(routeList, signal.debugStr() + "不是进路始端信号机");
|
||||
// 筛选最适合的进路,筛选逻辑与办理引导时筛选逻辑类似
|
||||
List<Route> fltRoutes = routeList.stream().filter(Route::isFlt).collect(Collectors.toList());
|
||||
BusinessExceptionAssertEnum.ARGUMENT_ILLEGAL.assertCollectionNotEmpty(fltRoutes, signal.debugStr() + "下没有可设置的车队进路");
|
||||
List<Route> collect = fltRoutes.stream()
|
||||
.filter(r -> !r.isTurnBack() && CollectionUtils.isEmpty(r.getSwitchList()))
|
||||
.collect(Collectors.toList());
|
||||
if (CollectionUtils.isEmpty(collect)) {
|
||||
collect = fltRoutes.stream().filter(r -> !r.isTurnBack()).collect(Collectors.toList());
|
||||
}
|
||||
if (CollectionUtils.isEmpty(collect)) {
|
||||
collect = fltRoutes;
|
||||
}
|
||||
Route route = collect.get(0);
|
||||
Route.CheckFailMessage message = routeService.setRoute(simulation, route,route.getAspect());
|
||||
BusinessExceptionAssertEnum.OPERATION_NOT_SUPPORTED.assertNull(message, route.debugStr() + "无法办理");
|
||||
route.setFleetMode(true);
|
||||
}
|
||||
/**
|
||||
* 取消联锁自动进路
|
||||
*/
|
||||
public void cancelCiAuto(Simulation simulation, String signalCode) {
|
||||
Signal signal = simulation.getRepository().getByCode(signalCode, Signal.class);
|
||||
Route lockedRoute = signal.getLockedRoute();
|
||||
if (Objects.isNull(lockedRoute)) {
|
||||
throw new SimulationException(SimulationExceptionType.Operation_Handle_FAIL,
|
||||
String.format("信号机[%s(%s)]没有已锁闭进路,不能执行取消联锁自动进路", signal.getName(),
|
||||
signal.getCode()));
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消联锁自动进路
|
||||
*/
|
||||
public void cancelCiAuto(Simulation simulation, String signalCode) {
|
||||
Signal signal = simulation.getRepository().getByCode(signalCode, Signal.class);
|
||||
Route lockedRoute = signal.getLockedRoute();
|
||||
if (Objects.isNull(lockedRoute)) {
|
||||
throw new SimulationException(SimulationExceptionType.Operation_Handle_FAIL,
|
||||
String.format("信号机[%s(%s)]没有已锁闭进路,不能执行取消联锁自动进路", signal.getName(), signal.getCode()));
|
||||
}
|
||||
if (!lockedRoute.isFleetMode()) {
|
||||
throw new SimulationException(SimulationExceptionType.Operation_Repetition, String.format("信号机[%s(%s)]没有打开连锁自动进路,不能取消联锁自动进路", signal.getName(), signal.getCode()));
|
||||
}
|
||||
lockedRoute.setFleetMode(false);
|
||||
if (simulation.getRepository().getConfig().isCancelRouteWhenCancelFlt()) {
|
||||
routeService.unlockRoute(simulation, lockedRoute);
|
||||
}
|
||||
if (!lockedRoute.isFleetMode()) {
|
||||
throw new SimulationException(SimulationExceptionType.Operation_Repetition,
|
||||
String.format("信号机[%s(%s)]没有打开连锁自动进路,不能取消联锁自动进路", signal.getName(),
|
||||
signal.getCode()));
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置联锁自动触发
|
||||
*/
|
||||
public void setCiAutoTrigger(Simulation simulation, String signalCode, List<String> routeCodeList) {
|
||||
SimulationDataRepository repository = simulation.getRepository();
|
||||
List<Route> routeList;
|
||||
if (StringUtils.hasText(signalCode)) {
|
||||
Signal signal = repository.getByCode(signalCode, Signal.class);
|
||||
if (repository.getConfig().isSignalHumanControlBeforeSetAtsControlOrCIAutoTrigger()) {
|
||||
BusinessExceptionAssertEnum.OPERATION_NOT_SUPPORTED.assertNotTrue(signal.isAtsControl(), String.format("信号机[%s]需处于人工控", signal.getCode()));
|
||||
}
|
||||
routeList = signal.getRouteList();
|
||||
} else {
|
||||
routeList = routeCodeList.stream()
|
||||
.map(code -> repository.getByCode(code, Route.class))
|
||||
.collect(Collectors.toList());
|
||||
if (repository.getConfig().isSignalHumanControlBeforeSetAtsControlOrCIAutoTrigger()) {
|
||||
routeList.stream()
|
||||
.map(Route::getStart)
|
||||
.distinct()
|
||||
.forEach(signal ->
|
||||
BusinessExceptionAssertEnum.OPERATION_NOT_SUPPORTED
|
||||
.assertNotTrue(signal.isAtsControl(),
|
||||
String.format("信号机[%s]需处于人工控", signal.getCode())));
|
||||
}
|
||||
}
|
||||
if (!CollectionUtils.isEmpty(routeList)) {
|
||||
routeList.stream().filter(Route::isArs).forEach(route -> {
|
||||
if (route.isFleetMode()) {
|
||||
throw new SimulationException(SimulationExceptionType.Operation_Conflict,
|
||||
String.format("进路[%s(%s)]自动通过已开启,不能设置自动追踪", route.getName(), route.getCode()));
|
||||
}
|
||||
});
|
||||
for (Route route : routeList) {
|
||||
if (route.isArs()) {
|
||||
route.setCiControl(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
lockedRoute.setFleetMode(false);
|
||||
if (simulation.getRepository().getConfig().isCancelRouteWhenCancelFlt()) {
|
||||
routeService.unlockRoute(simulation, lockedRoute);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消联锁自动触发
|
||||
*/
|
||||
public void cancelCiAutoTrigger(Simulation simulation, String signalCode, List<String> routeCodes) {
|
||||
List<Route> routeList;
|
||||
SimulationDataRepository repository = simulation.getRepository();
|
||||
if (StringUtils.hasText(signalCode)) {
|
||||
Signal signal = repository.getByCode(signalCode, Signal.class);
|
||||
routeList = signal.getRouteList();
|
||||
} else {
|
||||
routeList = routeCodes.stream()
|
||||
.map(code -> repository.getByCode(code, Route.class))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
if (!CollectionUtils.isEmpty(routeList)) {
|
||||
for (Route route : routeList) {
|
||||
if (route.isCiControl()) {
|
||||
route.setCiControl(false);
|
||||
route.setAtsControl(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 设置联锁自动触发
|
||||
*/
|
||||
public void setCiAutoTrigger(Simulation simulation, String signalCode,
|
||||
List<String> routeCodeList) {
|
||||
SimulationDataRepository repository = simulation.getRepository();
|
||||
List<Route> routeList;
|
||||
if (StringUtils.hasText(signalCode)) {
|
||||
Signal signal = repository.getByCode(signalCode, Signal.class);
|
||||
if (repository.getConfig().isSignalHumanControlBeforeSetAtsControlOrCIAutoTrigger()) {
|
||||
BusinessExceptionAssertEnum.OPERATION_NOT_SUPPORTED.assertNotTrue(signal.isAtsControl(),
|
||||
String.format("信号机[%s]需处于人工控", signal.getCode()));
|
||||
}
|
||||
routeList = signal.getRouteList();
|
||||
} else {
|
||||
routeList = routeCodeList.stream()
|
||||
.map(code -> repository.getByCode(code, Route.class))
|
||||
.collect(Collectors.toList());
|
||||
if (repository.getConfig().isSignalHumanControlBeforeSetAtsControlOrCIAutoTrigger()) {
|
||||
routeList.stream()
|
||||
.map(Route::getStart)
|
||||
.distinct()
|
||||
.forEach(signal ->
|
||||
BusinessExceptionAssertEnum.OPERATION_NOT_SUPPORTED
|
||||
.assertNotTrue(signal.isAtsControl(),
|
||||
String.format("信号机[%s]需处于人工控", signal.getCode())));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置自动折返进路
|
||||
*
|
||||
* @param simulation
|
||||
* @param cycleCode
|
||||
*/
|
||||
public void setAutoTurnBack(Simulation simulation, String cycleCode) {
|
||||
Cycle cycle = simulation.getRepository().getByCode(cycleCode, Cycle.class);
|
||||
cycle.setSetUp(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消自动折返进路
|
||||
*/
|
||||
public void cancelAutoTurnBack(Simulation simulation, String cycleCode) {
|
||||
Cycle cycle = simulation.getRepository().getByCode(cycleCode, Cycle.class);
|
||||
cycle.setSetUp(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* 总取消
|
||||
*/
|
||||
public void totalCancel(Simulation simulation, String signalCode) {
|
||||
// todo 总取消操作有很多种操作方式,对应不同的按钮,此处都用信号机编号可能不妥
|
||||
Signal signal = simulation.getRepository().getByCode(signalCode, Signal.class);
|
||||
Route lockedRoute = signal.getLockedRoute();
|
||||
if (lockedRoute == null) {
|
||||
throw new SimulationException(SimulationExceptionType.Operation_Handle_FAIL,
|
||||
String.format("信号机[%s(%s)]没有已锁闭进路,无需取消进路", signal.getName(), signal.getCode()));
|
||||
if (!CollectionUtils.isEmpty(routeList)) {
|
||||
routeList.stream().filter(Route::isArs).forEach(route -> {
|
||||
if (route.isFleetMode()) {
|
||||
throw new SimulationException(SimulationExceptionType.Operation_Conflict,
|
||||
String.format("进路[%s(%s)]自动通过已开启,不能设置自动追踪", route.getName(),
|
||||
route.getCode()));
|
||||
}
|
||||
if (!signal.isApproachLock()) { //当接近区段未被占用
|
||||
this.cancelRoute(simulation, signalCode);
|
||||
} else {
|
||||
this.routeService.unlockRoute(simulation, lockedRoute);
|
||||
this.ciApiService.cancelFleetRoute(simulation, lockedRoute.getCode());
|
||||
});
|
||||
for (Route route : routeList) {
|
||||
if (route.isArs()) {
|
||||
route.setCiControl(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消联锁自动触发
|
||||
*/
|
||||
public void cancelCiAutoTrigger(Simulation simulation, String signalCode,
|
||||
List<String> routeCodes) {
|
||||
List<Route> routeList;
|
||||
SimulationDataRepository repository = simulation.getRepository();
|
||||
if (StringUtils.hasText(signalCode)) {
|
||||
Signal signal = repository.getByCode(signalCode, Signal.class);
|
||||
routeList = signal.getRouteList();
|
||||
} else {
|
||||
routeList = routeCodes.stream()
|
||||
.map(code -> repository.getByCode(code, Route.class))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
if (!CollectionUtils.isEmpty(routeList)) {
|
||||
for (Route route : routeList) {
|
||||
if (route.isCiControl()) {
|
||||
route.setCiControl(false);
|
||||
route.setAtsControl(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置自动折返进路
|
||||
*
|
||||
* @param simulation
|
||||
* @param cycleCode
|
||||
*/
|
||||
public void setAutoTurnBack(Simulation simulation, String cycleCode) {
|
||||
Cycle cycle = simulation.getRepository().getByCode(cycleCode, Cycle.class);
|
||||
cycle.setSetUp(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消自动折返进路
|
||||
*/
|
||||
public void cancelAutoTurnBack(Simulation simulation, String cycleCode) {
|
||||
Cycle cycle = simulation.getRepository().getByCode(cycleCode, Cycle.class);
|
||||
cycle.setSetUp(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* 总取消
|
||||
*/
|
||||
public void totalCancel(Simulation simulation, String signalCode) {
|
||||
// todo 总取消操作有很多种操作方式,对应不同的按钮,此处都用信号机编号可能不妥
|
||||
Signal signal = simulation.getRepository().getByCode(signalCode, Signal.class);
|
||||
Route lockedRoute = signal.getLockedRoute();
|
||||
if (lockedRoute == null) {
|
||||
throw new SimulationException(SimulationExceptionType.Operation_Handle_FAIL,
|
||||
String.format("信号机[%s(%s)]没有已锁闭进路,无需取消进路", signal.getName(),
|
||||
signal.getCode()));
|
||||
}
|
||||
if (!signal.isApproachLock()) { //当接近区段未被占用
|
||||
this.cancelRoute(simulation, signalCode);
|
||||
} else {
|
||||
this.routeService.unlockRoute(simulation, lockedRoute);
|
||||
this.ciApiService.cancelFleetRoute(simulation, lockedRoute.getCode());
|
||||
// if (signal.isGuideAspect()) { //如果引导信号开启中
|
||||
// this.ciApiService.closeGuideSignal(simulation, signalCode);
|
||||
// } else if (signal.isClose()) { //如果信号灯关了
|
||||
// } else {
|
||||
// this.ciApiService.closeSignal(simulation, signalCode);
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void cancelRoute(Simulation simulation, String signalCode) {
|
||||
Route route = this.ciApiService.findLockedRouteByStartSignal(simulation, signalCode);
|
||||
if (Objects.nonNull(route)) {
|
||||
BusinessExceptionAssertEnum.OPERATION_FAIL.assertNotTrue(
|
||||
route.isApproachLock(), "进路接近锁闭,无法取消");
|
||||
BusinessExceptionAssertEnum.OPERATION_FAIL.assertNotTrue(
|
||||
route.getStart().isGuideAspect(), "引导进路,需要人解进路");
|
||||
BusinessExceptionAssertEnum.OPERATION_NOT_SUPPORTED.assertNotTrue(route.isFleetMode(),
|
||||
String.format("进路[%s]已开启自动通过进路,无法取消", route.debugStr()));
|
||||
BusinessExceptionAssertEnum.OPERATION_FAIL.assertNotTrue(
|
||||
Objects.nonNull(route.getDelayUnlockDevice()), String.format("进路[%s]已经开启延时取消,无法手动取消", route.debugStr()));
|
||||
this.ciApiService.unlockRoute(simulation, route.getCode());
|
||||
}
|
||||
public void cancelRoute(Simulation simulation, String signalCode) {
|
||||
Route route = this.ciApiService.findLockedRouteByStartSignal(simulation, signalCode);
|
||||
if (Objects.nonNull(route)) {
|
||||
BusinessExceptionAssertEnum.OPERATION_FAIL.assertNotTrue(
|
||||
route.isApproachLock(), "进路接近锁闭,无法取消");
|
||||
BusinessExceptionAssertEnum.OPERATION_FAIL.assertNotTrue(
|
||||
route.getStart().isGuideAspect(), "引导进路,需要人解进路");
|
||||
BusinessExceptionAssertEnum.OPERATION_NOT_SUPPORTED.assertNotTrue(route.isFleetMode(),
|
||||
String.format("进路[%s]已开启自动通过进路,无法取消", route.debugStr()));
|
||||
BusinessExceptionAssertEnum.OPERATION_FAIL.assertNotTrue(
|
||||
Objects.nonNull(route.getDelayUnlockDevice()),
|
||||
String.format("进路[%s]已经开启延时取消,无法手动取消", route.debugStr()));
|
||||
this.ciApiService.unlockRoute(simulation, route.getCode());
|
||||
}
|
||||
}
|
||||
|
||||
public void setOverlap(Simulation simulation, String signalCode, String overlapCode) {
|
||||
if (signalCode == null || overlapCode == null) {
|
||||
throw new SimulationException(SimulationExceptionType.Illegal_Argument);
|
||||
}
|
||||
this.ciApiService.setOverlap(simulation, signalCode, overlapCode);
|
||||
public void setOverlap(Simulation simulation, String signalCode, String overlapCode) {
|
||||
if (signalCode == null || overlapCode == null) {
|
||||
throw new SimulationException(SimulationExceptionType.Illegal_Argument);
|
||||
}
|
||||
this.ciApiService.setOverlap(simulation, signalCode, overlapCode);
|
||||
}
|
||||
|
||||
public void conflictRouteSetConfirm(Simulation simulation, SimulationMember member, String routeCode, int way) {
|
||||
BusinessExceptionAssertEnum.ARGUMENT_ILLEGAL.assertTrue(
|
||||
Route.Conflict_Handle_Way_1 == way || Route.Conflict_Handle_Way_2 == way
|
||||
);
|
||||
Route route = simulation.getRepository().getByCode(routeCode, Route.class);
|
||||
AtsAlarm conflictAlarm = route.getConflictAlarm();
|
||||
if (conflictAlarm != null) {
|
||||
LocalDateTime systemTime = simulation.getCorrectSystemTime();
|
||||
conflictAlarm.confirm(systemTime, member, way);
|
||||
conflictAlarm.recover(systemTime);
|
||||
}
|
||||
public void conflictRouteSetConfirm(Simulation simulation, SimulationMember member,
|
||||
String routeCode, int way) {
|
||||
BusinessExceptionAssertEnum.ARGUMENT_ILLEGAL.assertTrue(
|
||||
Route.Conflict_Handle_Way_1 == way || Route.Conflict_Handle_Way_2 == way
|
||||
);
|
||||
Route route = simulation.getRepository().getByCode(routeCode, Route.class);
|
||||
AtsAlarm conflictAlarm = route.getConflictAlarm();
|
||||
if (conflictAlarm != null) {
|
||||
LocalDateTime systemTime = simulation.getCorrectSystemTime();
|
||||
conflictAlarm.confirm(systemTime, member, way);
|
||||
conflictAlarm.recover(systemTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -581,7 +581,7 @@ public class AtsTrainService {
|
|||
SimulationDataRepository repository = simulation.getRepository();
|
||||
TrainInfo trainInfo = repository.getSupervisedTrainByGroup(groupNumber);
|
||||
routeCodes.forEach(code -> {
|
||||
ciApiService.settingRoute(simulation, code);
|
||||
ciApiService.settingRoute(simulation, code, false);
|
||||
Route route = repository.getByCode(code, Route.class);
|
||||
route.setTrain(trainInfo);
|
||||
});
|
||||
|
|
|
@ -4,237 +4,252 @@ import club.joylink.rtss.exception.BusinessExceptionAssertEnum;
|
|||
import club.joylink.rtss.simulation.cbtc.CI.device.CiRouteService;
|
||||
import club.joylink.rtss.simulation.cbtc.Simulation;
|
||||
import club.joylink.rtss.simulation.cbtc.data.SimulationDataRepository;
|
||||
import club.joylink.rtss.simulation.cbtc.data.map.*;
|
||||
import club.joylink.rtss.simulation.cbtc.data.map.MapConfig;
|
||||
import club.joylink.rtss.simulation.cbtc.data.map.Route;
|
||||
import club.joylink.rtss.simulation.cbtc.data.map.Section;
|
||||
import club.joylink.rtss.simulation.cbtc.data.map.Signal;
|
||||
import club.joylink.rtss.simulation.cbtc.data.map.Stand;
|
||||
import club.joylink.rtss.simulation.cbtc.data.map.Station;
|
||||
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.StationTurnBackStrategyOption;
|
||||
import club.joylink.rtss.simulation.cbtc.data.vo.TrainInfo;
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
@Slf4j
|
||||
public abstract class AtsRouteSelectService {
|
||||
public abstract Route select(Simulation simulation, TrainInfo trainInfo);
|
||||
|
||||
/**
|
||||
* 查询需要触发的进路
|
||||
*
|
||||
* @param simulation
|
||||
* @param turnBackSection 站后折返的折返轨
|
||||
* @return
|
||||
*/
|
||||
public Route queryTriggerRoutes(Simulation simulation, List<Section> targetList,
|
||||
TrainInfo trainInfo, Section turnBackSection) {
|
||||
SimulationDataRepository repository = simulation.getRepository();
|
||||
if (trainInfo.getPlanStandTrack() == null) {
|
||||
return null;
|
||||
}
|
||||
//寻找通向计划区段的进路
|
||||
Section planSection = repository.getByCode(trainInfo.getPlanStandTrack(), Section.class);
|
||||
Section headSection = repository.getByCode(trainInfo.getPhysicalSection(), Section.class);
|
||||
int index = targetList.indexOf(planSection);
|
||||
if (index == -1) {
|
||||
return null;
|
||||
}
|
||||
Section nextPlanSection = null; //下一个计划区段
|
||||
if (index < targetList.size() - 1) {
|
||||
nextPlanSection = targetList.get(index + 1);
|
||||
}
|
||||
List<RoutePath> routePaths = repository.queryRoutePathsByEndAndContainsSection(planSection, headSection);
|
||||
RouteSelectResult result = this.queryTriggerRoutesOfRoutePath(repository, trainInfo, routePaths, nextPlanSection);
|
||||
if (!result.isAllSet()) { //有进路未触发
|
||||
return result.getRoute();
|
||||
}
|
||||
//通向计划区段的进路已全部办理,根据条件尝试向下一个计划区段或站后折返轨办理进路
|
||||
MapConfig config = repository.getConfig();
|
||||
if (!config.isSignalOpenAfterParking() || (headSection.equals(planSection) && trainInfo.isParking())) { //不需要停站就可以开放信号机或者已经在计划区段停站(可以继续向前办理进路)
|
||||
if (nextPlanSection != null) { //计划区段路径未跑完
|
||||
routePaths = repository.queryRoutePaths(planSection, nextPlanSection);
|
||||
if (!CollectionUtils.isEmpty(routePaths)) {
|
||||
return this.queryTriggerRoutesOfRoutePath(repository, trainInfo, routePaths, nextPlanSection).getRoute();
|
||||
}
|
||||
} else if (turnBackSection != null) { //站后折返
|
||||
return queryTriggerRoutes4TurnBack(simulation, planSection, turnBackSection, trainInfo);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
public abstract Route select(Simulation simulation, TrainInfo trainInfo);
|
||||
|
||||
/**
|
||||
* 查询需要触发的进路
|
||||
*
|
||||
* @param simulation
|
||||
* @param turnBackSection 站后折返的折返轨
|
||||
* @return
|
||||
*/
|
||||
public Route queryTriggerRoutes(Simulation simulation, List<Section> targetList,
|
||||
TrainInfo trainInfo, Section turnBackSection) {
|
||||
SimulationDataRepository repository = simulation.getRepository();
|
||||
if (trainInfo.getPlanStandTrack() == null) {
|
||||
return null;
|
||||
}
|
||||
//寻找通向计划区段的进路
|
||||
Section planSection = repository.getByCode(trainInfo.getPlanStandTrack(), Section.class);
|
||||
Section headSection = repository.getByCode(trainInfo.getPhysicalSection(), Section.class);
|
||||
int index = targetList.indexOf(planSection);
|
||||
if (index == -1) {
|
||||
return null;
|
||||
}
|
||||
Section nextPlanSection = null; //下一个计划区段
|
||||
if (index < targetList.size() - 1) {
|
||||
nextPlanSection = targetList.get(index + 1);
|
||||
}
|
||||
List<RoutePath> routePaths = repository.queryRoutePathsByEndAndContainsSection(planSection,
|
||||
headSection);
|
||||
RouteSelectResult result = this.queryTriggerRoutesOfRoutePath(repository, trainInfo, routePaths,
|
||||
nextPlanSection);
|
||||
if (!result.isAllSet()) { //有进路未触发
|
||||
return result.getRoute();
|
||||
}
|
||||
//通向计划区段的进路已全部办理,根据条件尝试向下一个计划区段或站后折返轨办理进路
|
||||
MapConfig config = repository.getConfig();
|
||||
if (!config.isSignalOpenAfterParking() || (headSection.equals(planSection)
|
||||
&& trainInfo.isParking())) { //不需要停站就可以开放信号机或者已经在计划区段停站(可以继续向前办理进路)
|
||||
if (nextPlanSection != null) { //计划区段路径未跑完
|
||||
routePaths = repository.queryRoutePaths(planSection, nextPlanSection);
|
||||
if (!CollectionUtils.isEmpty(routePaths)) {
|
||||
return this.queryTriggerRoutesOfRoutePath(repository, trainInfo, routePaths,
|
||||
nextPlanSection).getRoute();
|
||||
}
|
||||
} else if (turnBackSection != null) { //站后折返
|
||||
return queryTriggerRoutes4TurnBack(simulation, planSection, turnBackSection, trainInfo);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Route queryTriggerRoutes4TurnBack(Simulation simulation, Section standSection, Section tbSection, TrainInfo trainInfo) {
|
||||
SimulationDataRepository repository = simulation.getRepository();
|
||||
MapConfig config = repository.getConfig();
|
||||
if (!config.isStandTbStrategyIsInvalid()) {
|
||||
//根据站台折返策略处理
|
||||
Stand stand = standSection.getStandList().get(0);
|
||||
Stand.TurnBackType typeStrategy = stand.getTypeStrategy();
|
||||
switch (typeStrategy) {
|
||||
case NONE:
|
||||
case AUTO:
|
||||
return null;
|
||||
}
|
||||
public Route queryTriggerRoutes4TurnBack(Simulation simulation, Section standSection,
|
||||
Section tbSection, TrainInfo trainInfo) {
|
||||
SimulationDataRepository repository = simulation.getRepository();
|
||||
MapConfig config = repository.getConfig();
|
||||
if (!config.isStandTbStrategyIsInvalid()) {
|
||||
//根据站台折返策略处理
|
||||
Stand stand = standSection.getStandList().get(0);
|
||||
Stand.TurnBackType typeStrategy = stand.getTypeStrategy();
|
||||
switch (typeStrategy) {
|
||||
case NONE:
|
||||
case AUTO:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
//根据车站折返策略处理
|
||||
Station station = standSection.getStation();
|
||||
StationTurnBackStrategyOption strategy = null;
|
||||
if (station.getTbStrategyId() != null) {
|
||||
strategy = station.getCurrentTurnBackStrategy();
|
||||
}
|
||||
List<Section> tbSectionList = new ArrayList<>();
|
||||
if (Objects.isNull(strategy)) {
|
||||
tbSectionList.add(tbSection);
|
||||
} else {
|
||||
switch (strategy.getType()) {
|
||||
// 按计划
|
||||
case NONE: {
|
||||
tbSectionList.add(tbSection);
|
||||
break;
|
||||
}
|
||||
//根据车站折返策略处理
|
||||
Station station = standSection.getStation();
|
||||
StationTurnBackStrategyOption strategy = null;
|
||||
if (station.getTbStrategyId() != null) {
|
||||
strategy = station.getCurrentTurnBackStrategy();
|
||||
// 仅某个折返轨
|
||||
case ONLY: {
|
||||
tbSectionList.add(strategy.getSectionList().get(0));
|
||||
break;
|
||||
}
|
||||
List<Section> tbSectionList = new ArrayList<>();
|
||||
if (Objects.isNull(strategy)) {
|
||||
tbSectionList.add(tbSection);
|
||||
} else {
|
||||
switch (strategy.getType()) {
|
||||
// 按计划
|
||||
case NONE: {
|
||||
tbSectionList.add(tbSection);
|
||||
break;
|
||||
}
|
||||
// 仅某个折返轨
|
||||
case ONLY: {
|
||||
tbSectionList.add(strategy.getSectionList().get(0));
|
||||
break;
|
||||
}
|
||||
// 折返轨等价
|
||||
case FIRST:
|
||||
case EQUAL: {
|
||||
tbSectionList.addAll(strategy.getSectionList());
|
||||
break;
|
||||
}
|
||||
}
|
||||
// 折返轨等价
|
||||
case FIRST:
|
||||
case EQUAL: {
|
||||
tbSectionList.addAll(strategy.getSectionList());
|
||||
break;
|
||||
}
|
||||
List<RoutePath> list = repository.getRoutePaths(standSection, tbSection);
|
||||
boolean right = list.get(0).isRight();
|
||||
Signal signal = standSection.getSignalOf(right);
|
||||
if (!this.isApproachSignal(repository, trainInfo, signal)) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
List<RoutePath> list = repository.getRoutePaths(standSection, tbSection);
|
||||
boolean right = list.get(0).isRight();
|
||||
Signal signal = standSection.getSignalOf(right);
|
||||
if (!this.isApproachSignal(repository, trainInfo, signal)) {
|
||||
return null;
|
||||
}
|
||||
List<Route> routeList = signal.getRouteList();
|
||||
List<Route> tbRouteList = new ArrayList<>();
|
||||
for (Route route : routeList) {
|
||||
if (route.isTurnBack()) {
|
||||
tbRouteList.add(route);
|
||||
}
|
||||
}
|
||||
if (!tbRouteList.isEmpty()) {
|
||||
routeList = tbRouteList;
|
||||
}
|
||||
routeList = routeList.stream()
|
||||
.filter(route -> !repository.hasSameStartTriggerRoute(trainInfo, route))
|
||||
.filter(route -> route.containSameSection(tbSectionList))
|
||||
.collect(Collectors.toList());
|
||||
Route route = null;
|
||||
for (Route temp : routeList) {
|
||||
List<Section> sectionList = temp.getSectionList();
|
||||
boolean trainOccupy = false;
|
||||
for (Section rs : sectionList) {
|
||||
if (rs.isOccupied()) {
|
||||
trainOccupy = true;
|
||||
break;
|
||||
}
|
||||
List<Route> routeList = signal.getRouteList();
|
||||
List<Route> tbRouteList = new ArrayList<>();
|
||||
for (Route route : routeList) {
|
||||
if (route.isTurnBack()) {
|
||||
tbRouteList.add(route);
|
||||
}
|
||||
}
|
||||
if (trainOccupy) {
|
||||
continue;
|
||||
} else {
|
||||
route = temp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (route != null) {
|
||||
Route.CheckFailMessage check = CiRouteService.routeSetCheck(simulation, route, false,
|
||||
false);
|
||||
if (check != null) {
|
||||
route = null;
|
||||
}
|
||||
}
|
||||
return route;
|
||||
}
|
||||
|
||||
/**
|
||||
* 筛选列车路径
|
||||
*
|
||||
* @param pathList
|
||||
* @return
|
||||
*/
|
||||
public RoutePath selectRoutePath(List<RoutePath> pathList) {
|
||||
if (CollectionUtils.isEmpty(pathList)) {
|
||||
return null;
|
||||
}
|
||||
if (pathList.size() > 1) { // 暂时先选路径中道岔最少的路径
|
||||
pathList.sort(Comparator.comparing(RoutePath::getSwitchCount));
|
||||
}
|
||||
return pathList.get(0);
|
||||
}
|
||||
|
||||
public RouteSelectResult queryTriggerRoutesOfRoutePath(SimulationDataRepository repository,
|
||||
TrainInfo trainInfo, List<RoutePath> routePathList, Section nextPlanSection) {
|
||||
Section section = repository.getByCode(trainInfo.getPhysicalSection(), Section.class); // 列车所在区段
|
||||
List<Route> triggerList = new ArrayList<>();
|
||||
if (!routePathList.isEmpty()) {
|
||||
RoutePath routePath = this.selectRoutePath(routePathList);
|
||||
// 查找可以触发的进路列表
|
||||
boolean ctcLevel = trainInfo.isCtcLevel();
|
||||
List<Signal> signalList = routePath.getSignalList();
|
||||
for (Signal signal : signalList) {
|
||||
Section signalSection = signal.getSection();
|
||||
if (routePath.containsSection(section) &&
|
||||
routePath.getSectionSort(signalSection) < routePath.getSectionSort(section)) {
|
||||
// 列车已越过此信号机
|
||||
continue;
|
||||
}
|
||||
if (!tbRouteList.isEmpty()) {
|
||||
routeList = tbRouteList;
|
||||
if (!ctcLevel && signal.isVirtual()) {
|
||||
continue;
|
||||
}
|
||||
routeList = routeList.stream()
|
||||
.filter(route -> !repository.hasSameStartTriggerRoute(trainInfo, route))
|
||||
.filter(route -> route.containSameSection(tbSectionList))
|
||||
.collect(Collectors.toList());
|
||||
Route route = null;
|
||||
for (Route temp : routeList) {
|
||||
List<Section> sectionList = temp.getSectionList();
|
||||
boolean trainOccupy = false;
|
||||
for (Section rs : sectionList) {
|
||||
if (rs.isOccupied()) {
|
||||
trainOccupy = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (trainOccupy) {
|
||||
continue;
|
||||
if (signal.hasCiAutoTriggerRoute() || signal.hasFleetModeRoute()
|
||||
|| signal.hasNotAtsControlRoute()) { // 以此信号机为始端存在联锁自动进路或联锁自动触发进路或非ATS自动控制进路
|
||||
// 如果信号机正常开放,且进路是路径方向上的进路,继续找,否则返回
|
||||
if (signal.isMainAspect()) {
|
||||
Route lockedRoute = signal.getLockedRoute();
|
||||
if (routePath.isPathRoute(lockedRoute)) {
|
||||
continue;
|
||||
} else {
|
||||
route = temp;
|
||||
break;
|
||||
return new RouteSelectResult(null, false);
|
||||
}
|
||||
} else {
|
||||
return new RouteSelectResult(null, false);
|
||||
}
|
||||
}
|
||||
if (route != null) {
|
||||
Route.CheckFailMessage check = CiRouteService.routeSetCheck(simulation, route, false);
|
||||
if (check != null)
|
||||
route = null;
|
||||
}
|
||||
return route;
|
||||
}
|
||||
|
||||
/**
|
||||
* 筛选列车路径
|
||||
*
|
||||
* @param pathList
|
||||
* @return
|
||||
*/
|
||||
public RoutePath selectRoutePath(List<RoutePath> pathList) {
|
||||
if (CollectionUtils.isEmpty(pathList)) {
|
||||
return null;
|
||||
}
|
||||
if (pathList.size() > 1) { // 暂时先选路径中道岔最少的路径
|
||||
pathList.sort(Comparator.comparing(RoutePath::getSwitchCount));
|
||||
}
|
||||
return pathList.get(0);
|
||||
}
|
||||
|
||||
public RouteSelectResult queryTriggerRoutesOfRoutePath(SimulationDataRepository repository,
|
||||
TrainInfo trainInfo, List<RoutePath> routePathList, Section nextPlanSection) {
|
||||
Section section = repository.getByCode(trainInfo.getPhysicalSection(), Section.class); // 列车所在区段
|
||||
List<Route> triggerList = new ArrayList<>();
|
||||
if (!routePathList.isEmpty()) {
|
||||
RoutePath routePath = this.selectRoutePath(routePathList);
|
||||
// 查找可以触发的进路列表
|
||||
boolean ctcLevel = trainInfo.isCtcLevel();
|
||||
List<Signal> signalList = routePath.getSignalList();
|
||||
for (Signal signal : signalList) {
|
||||
Section signalSection = signal.getSection();
|
||||
if (routePath.containsSection(section) &&
|
||||
routePath.getSectionSort(signalSection) < routePath.getSectionSort(section)) {
|
||||
// 列车已越过此信号机
|
||||
continue;
|
||||
if (this.isApproachSignal(repository, trainInfo, signal)) {
|
||||
// 是信号机接近区段
|
||||
if (signal.isMainAspect()) {
|
||||
if (routePath.isPathRoute(signal.getLockedRoute())) {
|
||||
continue;
|
||||
} else {
|
||||
// 非路径进路办理
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
//筛选可触发的进路
|
||||
for (Route route : routePath.getRouteList()) {
|
||||
TrainInfo other = repository.querySameStartTriggerRouteTrain(trainInfo, route);
|
||||
if (other != null) { // 已经有在排列中的进路,结束
|
||||
log.debug(String.format(String.format("列车[%s]已经触发了信号机[%s]为始端的进路",
|
||||
other.getGroupNumber(), route.getStart().getName())));
|
||||
continue;
|
||||
}
|
||||
if (route.getStart().equals(signal) && !route.isTurnBack() && !triggerList.contains(
|
||||
route) && route.isAtsControl()) {
|
||||
if (repository.getConfig().isRouteLikeHa1()) {
|
||||
if (ctcLevel && route.isAtp()) {
|
||||
triggerList.add(route);
|
||||
} else if (!ctcLevel && route.isGround()) {
|
||||
triggerList.add(route);
|
||||
}
|
||||
} else {
|
||||
triggerList.add(route);
|
||||
}
|
||||
if (!ctcLevel && signal.isVirtual()) {
|
||||
continue;
|
||||
}
|
||||
if (signal.hasCiAutoTriggerRoute() || signal.hasFleetModeRoute() || signal.hasNotAtsControlRoute()) { // 以此信号机为始端存在联锁自动进路或联锁自动触发进路或非ATS自动控制进路
|
||||
// 如果信号机正常开放,且进路是路径方向上的进路,继续找,否则返回
|
||||
if (signal.isMainAspect()) {
|
||||
Route lockedRoute = signal.getLockedRoute();
|
||||
if (routePath.isPathRoute(lockedRoute)) {
|
||||
continue;
|
||||
} else {
|
||||
return new RouteSelectResult(null, false);
|
||||
}
|
||||
} else {
|
||||
return new RouteSelectResult(null, false);
|
||||
}
|
||||
}
|
||||
if (this.isApproachSignal(repository, trainInfo, signal)) {
|
||||
// 是信号机接近区段
|
||||
if (signal.isMainAspect()) {
|
||||
if (routePath.isPathRoute(signal.getLockedRoute())) {
|
||||
continue;
|
||||
} else {
|
||||
// 非路径进路办理
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
//筛选可触发的进路
|
||||
for (Route route : routePath.getRouteList()) {
|
||||
TrainInfo other = repository.querySameStartTriggerRouteTrain(trainInfo, route);
|
||||
if (other != null) { // 已经有在排列中的进路,结束
|
||||
log.debug(String.format(String.format("列车[%s]已经触发了信号机[%s]为始端的进路",
|
||||
other.getGroupNumber(), route.getStart().getName())));
|
||||
continue;
|
||||
}
|
||||
if (route.getStart().equals(signal) && !route.isTurnBack() && !triggerList.contains(route) && route.isAtsControl()) {
|
||||
if (repository.getConfig().isRouteLikeHa1()) {
|
||||
if (ctcLevel && route.isAtp()) {
|
||||
triggerList.add(route);
|
||||
} else if (!ctcLevel && route.isGround()) {
|
||||
triggerList.add(route);
|
||||
}
|
||||
} else {
|
||||
triggerList.add(route);
|
||||
}
|
||||
}
|
||||
}
|
||||
//选择要触发的进路
|
||||
if (triggerList.size() == 1) {
|
||||
return new RouteSelectResult(triggerList.get(0), false);
|
||||
} else if (triggerList.size() > 1) {
|
||||
}
|
||||
}
|
||||
//选择要触发的进路
|
||||
if (triggerList.size() == 1) {
|
||||
return new RouteSelectResult(triggerList.get(0), false);
|
||||
} else if (triggerList.size() > 1) {
|
||||
// if (planSection.equals(triggerList.get(0).getLastRouteSection()) && nextPlanSection != null) {
|
||||
// // 进路是计划站台轨,根据后续计划筛选
|
||||
// List<RoutePath> routePaths = repository.getRoutePaths(planSection, nextPlanSection);
|
||||
|
@ -244,63 +259,68 @@ public abstract class AtsRouteSelectService {
|
|||
// }
|
||||
// }
|
||||
// } else {
|
||||
// 取第一个延续保护道岔定位的
|
||||
Route route = null;
|
||||
for (Route temp : triggerList) {
|
||||
List<SwitchElement> switchList = temp.getOverlap().getFirstPath().getSwitchList();
|
||||
if(null==switchList||switchList.isEmpty()){
|
||||
log.debug("==============================================================================");
|
||||
log.debug("==>>异常进路code = {} name = {}",temp.getCode(),temp.getName());
|
||||
log.debug("==>>异常相关所有进路:");
|
||||
triggerList.forEach(r->{
|
||||
log.debug("==>>进路code={} name={} , 始端信号机code={} name={}",r.getCode(),r.getName(),r.getStart().getCode(),r.getName());
|
||||
});
|
||||
log.debug("==============================================================================");
|
||||
}
|
||||
BusinessExceptionAssertEnum.SYSTEM_EXCEPTION.assertCollectionNotEmpty(switchList,
|
||||
String.format("列车[%s]过滤进路异常:进路不是延续保护差异进路[%s]",
|
||||
trainInfo.getGroupNumber(),
|
||||
triggerList.stream().map(Route::getName).collect(Collectors.joining(","))));
|
||||
if (switchList.get(0).isNormal()) {
|
||||
return new RouteSelectResult(temp, false);
|
||||
} else {
|
||||
route = temp;
|
||||
}
|
||||
}
|
||||
return new RouteSelectResult(route, false);
|
||||
// }
|
||||
}
|
||||
}
|
||||
// 取第一个延续保护道岔定位的
|
||||
Route route = null;
|
||||
for (Route temp : triggerList) {
|
||||
List<SwitchElement> switchList = temp.getOverlap().getFirstPath().getSwitchList();
|
||||
if (null == switchList || switchList.isEmpty()) {
|
||||
log.debug(
|
||||
"==============================================================================");
|
||||
log.debug("==>>异常进路code = {} name = {}", temp.getCode(), temp.getName());
|
||||
log.debug("==>>异常相关所有进路:");
|
||||
triggerList.forEach(r -> {
|
||||
log.debug("==>>进路code={} name={} , 始端信号机code={} name={}", r.getCode(),
|
||||
r.getName(), r.getStart().getCode(), r.getName());
|
||||
});
|
||||
log.debug(
|
||||
"==============================================================================");
|
||||
}
|
||||
return new RouteSelectResult(null, false);
|
||||
BusinessExceptionAssertEnum.SYSTEM_EXCEPTION.assertCollectionNotEmpty(switchList,
|
||||
String.format("列车[%s]过滤进路异常:进路不是延续保护差异进路[%s]",
|
||||
trainInfo.getGroupNumber(),
|
||||
triggerList.stream().map(Route::getName).collect(Collectors.joining(","))));
|
||||
if (switchList.get(0).isNormal()) {
|
||||
return new RouteSelectResult(temp, false);
|
||||
} else {
|
||||
route = temp;
|
||||
}
|
||||
}
|
||||
return new RouteSelectResult(route, false);
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
return new RouteSelectResult(null, true);
|
||||
return new RouteSelectResult(null, false);
|
||||
}
|
||||
}
|
||||
return new RouteSelectResult(null, true);
|
||||
}
|
||||
|
||||
protected boolean isApproachSignal(SimulationDataRepository repository, TrainInfo trainInfo, Signal signal) {
|
||||
boolean ctcLevel = trainInfo.isCtcLevel();
|
||||
Section section = repository.getByCode(trainInfo.getPhysicalSection(), Section.class);
|
||||
Section logicSection = repository.getByCode(trainInfo.getSection(), Section.class);
|
||||
if (logicSection.isSwitchAxleCounterSection() || logicSection.isCross()) {
|
||||
logicSection = section;
|
||||
}
|
||||
if ((ctcLevel && signal.isCtcApproachSection(logicSection.getCode())) ||
|
||||
(!ctcLevel && !signal.isVirtual() && signal.isApproachSection(section.getCode()))) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
protected boolean isApproachSignal(SimulationDataRepository repository, TrainInfo trainInfo,
|
||||
Signal signal) {
|
||||
boolean ctcLevel = trainInfo.isCtcLevel();
|
||||
Section section = repository.getByCode(trainInfo.getPhysicalSection(), Section.class);
|
||||
Section logicSection = repository.getByCode(trainInfo.getSection(), Section.class);
|
||||
if (logicSection.isSwitchAxleCounterSection() || logicSection.isCross()) {
|
||||
logicSection = section;
|
||||
}
|
||||
|
||||
@Getter
|
||||
class RouteSelectResult {
|
||||
private Route route;
|
||||
|
||||
private boolean allSet;
|
||||
|
||||
public RouteSelectResult(Route route, boolean allSet) {
|
||||
this.route = route;
|
||||
this.allSet = allSet;
|
||||
}
|
||||
if ((ctcLevel && signal.isCtcApproachSection(logicSection.getCode())) ||
|
||||
(!ctcLevel && !signal.isVirtual() && signal.isApproachSection(section.getCode()))) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Getter
|
||||
class RouteSelectResult {
|
||||
|
||||
private Route route;
|
||||
|
||||
private boolean allSet;
|
||||
|
||||
public RouteSelectResult(Route route, boolean allSet) {
|
||||
this.route = route;
|
||||
this.allSet = allSet;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,205 +10,213 @@ import club.joylink.rtss.simulation.cbtc.data.plan.StationPlan;
|
|||
import club.joylink.rtss.simulation.cbtc.data.plan.TripPlan;
|
||||
import club.joylink.rtss.simulation.cbtc.data.support.RoutePath;
|
||||
import club.joylink.rtss.simulation.cbtc.data.vo.TrainInfo;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
public class AtsTriggerRouteService {
|
||||
@Autowired
|
||||
private AtsHeadTrainRouteSelectServiceImpl headTrainRouteSelectService;
|
||||
@Autowired
|
||||
private AtsPlanTrainRouteSelectServiceImpl planTrainRouteSelectService;
|
||||
@Autowired
|
||||
private CiApiService ciApiService;
|
||||
|
||||
public void tryTrigger(Simulation simulation, TrainInfo trainInfo) {
|
||||
if (trainInfo.isManualTrain()) { // 人工车不触发
|
||||
return;
|
||||
}
|
||||
if (!trainInfo.isAtsAutoTrigger()) { // 关闭列车自动排列
|
||||
return;
|
||||
}
|
||||
Map<String, Route> atsTriggerRouteMap = trainInfo.getAtsTriggerRouteMap();
|
||||
boolean triggerRoute = triggerRoute(simulation, trainInfo, atsTriggerRouteMap); //触发了进路办理
|
||||
if (!triggerRoute) {
|
||||
AtsRouteSelectService routeSelectService = this.getRouteSelectService(trainInfo);
|
||||
Route route = routeSelectService.select(simulation, trainInfo);
|
||||
if (route != null && route.isAtsControl()) {
|
||||
if (route.getInterlockStation() != null && route.getInterlockStation().isAtsRouteTriggerFault()) {
|
||||
// ATS触发进路故障
|
||||
return;
|
||||
}
|
||||
atsTriggerRouteMap.put(route.getCode(), route);
|
||||
this.trySetRoute(simulation, trainInfo, route);
|
||||
}
|
||||
}
|
||||
@Autowired
|
||||
private AtsHeadTrainRouteSelectServiceImpl headTrainRouteSelectService;
|
||||
@Autowired
|
||||
private AtsPlanTrainRouteSelectServiceImpl planTrainRouteSelectService;
|
||||
@Autowired
|
||||
private CiApiService ciApiService;
|
||||
|
||||
public void tryTrigger(Simulation simulation, TrainInfo trainInfo) {
|
||||
if (trainInfo.isManualTrain()) { // 人工车不触发
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* 尝试触发进路办理
|
||||
*/
|
||||
public boolean triggerRoute(Simulation simulation, TrainInfo trainInfo, Map<String, Route> atsTriggerRouteMap) {
|
||||
if (!atsTriggerRouteMap.isEmpty()) {
|
||||
SimulationDataRepository repository = simulation.getRepository();
|
||||
for (Route route : atsTriggerRouteMap.values()) {
|
||||
if (route.isNormalUnlock()) {
|
||||
if (route.isRouteSection(trainInfo.getPhysicalSection())) {
|
||||
atsTriggerRouteMap.remove(route.getCode());
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (!route.isAtsControl()) {
|
||||
atsTriggerRouteMap.remove(route.getCode());
|
||||
continue;
|
||||
}
|
||||
Signal signal = route.getStart();
|
||||
if (!this.planTrainRouteSelectService.isApproachSignal(repository, trainInfo, signal)) {
|
||||
atsTriggerRouteMap.remove(route.getCode());
|
||||
}
|
||||
if (route.isSetting()) {
|
||||
return true;
|
||||
}
|
||||
if (route.getConflictAlarm() != null) {
|
||||
if (route.isOpenMain()) {
|
||||
route.getConflictAlarm().recover(simulation.getCorrectSystemTime());
|
||||
route.setConflictAlarm(null);
|
||||
continue;
|
||||
} else if (route.isConflictHandleRunAsPlan()) {
|
||||
if (trainInfo.isPlanTrain()) {
|
||||
TripPlan tripPlan = repository.getTripPlan(trainInfo.getServiceNumber(), trainInfo.getTripNumber());
|
||||
AtsPlanTrainRouteSelectServiceImpl.ConflictInfo conflictInfo = this.planTrainRouteSelectService.checkConflict(repository, trainInfo, tripPlan, route);
|
||||
if (conflictInfo != null) {
|
||||
return true;
|
||||
} else {
|
||||
route.getConflictAlarm().recover(simulation.getCorrectSystemTime());
|
||||
route.setConflictAlarm(null);
|
||||
this.trySetRoute(simulation, trainInfo, route);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!route.isOpenMain()) { // 存在未开放的进路,直接返回
|
||||
if (!route.isSetting()) { // 进路未办理,继续尝试办理
|
||||
this.trySetRoute(simulation, trainInfo, route);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
if (!trainInfo.isAtsAutoTrigger()) { // 关闭列车自动排列
|
||||
return;
|
||||
}
|
||||
Map<String, Route> atsTriggerRouteMap = trainInfo.getAtsTriggerRouteMap();
|
||||
boolean triggerRoute = triggerRoute(simulation, trainInfo, atsTriggerRouteMap); //触发了进路办理
|
||||
if (!triggerRoute) {
|
||||
AtsRouteSelectService routeSelectService = this.getRouteSelectService(trainInfo);
|
||||
Route route = routeSelectService.select(simulation, trainInfo);
|
||||
if (route != null && route.isAtsControl()) {
|
||||
if (route.getInterlockStation() != null && route.getInterlockStation()
|
||||
.isAtsRouteTriggerFault()) {
|
||||
// ATS触发进路故障
|
||||
return;
|
||||
}
|
||||
atsTriggerRouteMap.put(route.getCode(), route);
|
||||
this.trySetRoute(simulation, trainInfo, route);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void trySetRoute(Simulation simulation, TrainInfo trainInfo, Route route) {
|
||||
/**
|
||||
* 尝试触发进路办理
|
||||
*/
|
||||
public boolean triggerRoute(Simulation simulation, TrainInfo trainInfo,
|
||||
Map<String, Route> atsTriggerRouteMap) {
|
||||
if (!atsTriggerRouteMap.isEmpty()) {
|
||||
SimulationDataRepository repository = simulation.getRepository();
|
||||
for (Route route : atsTriggerRouteMap.values()) {
|
||||
if (route.isNormalUnlock()) {
|
||||
if (route.isRouteSection(trainInfo.getPhysicalSection())) {
|
||||
atsTriggerRouteMap.remove(route.getCode());
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (!route.isAtsControl()) {
|
||||
return;
|
||||
atsTriggerRouteMap.remove(route.getCode());
|
||||
continue;
|
||||
}
|
||||
Signal signal = route.getStart();
|
||||
if (!this.planTrainRouteSelectService.isApproachSignal(repository, trainInfo, signal)) {
|
||||
atsTriggerRouteMap.remove(route.getCode());
|
||||
}
|
||||
if (route.isSetting()) {
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
if (route.isCheckConflict() && route.getConflictAlarm() != null) {
|
||||
if (!route.isConflictConfirmed() ||
|
||||
route.isConflictHandleRunAsPlan()) {
|
||||
// 进路冲突,且进路检查冲突,且用户未确认或确认按计划执行,不办理,返回
|
||||
return;
|
||||
if (route.getConflictAlarm() != null) {
|
||||
if (route.isOpenMain()) {
|
||||
route.getConflictAlarm().recover(simulation.getCorrectSystemTime());
|
||||
route.setConflictAlarm(null);
|
||||
continue;
|
||||
} else if (route.isConflictHandleRunAsPlan()) {
|
||||
if (trainInfo.isPlanTrain()) {
|
||||
TripPlan tripPlan = repository.getTripPlan(trainInfo.getServiceNumber(),
|
||||
trainInfo.getTripNumber());
|
||||
AtsPlanTrainRouteSelectServiceImpl.ConflictInfo conflictInfo = this.planTrainRouteSelectService.checkConflict(
|
||||
repository, trainInfo, tripPlan, route);
|
||||
if (conflictInfo != null) {
|
||||
return true;
|
||||
} else {
|
||||
route.getConflictAlarm().recover(simulation.getCorrectSystemTime());
|
||||
route.setConflictAlarm(null);
|
||||
this.trySetRoute(simulation, trainInfo, route);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// 判断进路内是否有折返(调头)列车
|
||||
if (this.hasTurnBackTrainInRoute(simulation, trainInfo, route)) {
|
||||
return;
|
||||
if (!route.isOpenMain()) { // 存在未开放的进路,直接返回
|
||||
if (!route.isSetting()) { // 进路未办理,继续尝试办理
|
||||
this.trySetRoute(simulation, trainInfo, route);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
log.debug(String.format("为列车[%s]办理进路[%s]", trainInfo.getGroupNumber(), route.getName()));
|
||||
this.ciApiService.settingRoute(simulation, route.getCode());
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean hasTurnBackTrainInRoute(Simulation simulation, TrainInfo trainInfo, Route route) {
|
||||
SimulationDataRepository repository = simulation.getRepository();
|
||||
List<Section> sectionList = route.getSectionList();
|
||||
for (int i = sectionList.size() - 1; i >= 0; i--) {
|
||||
Section section = sectionList.get(i);
|
||||
if (section.isNctOccupied() || section.isCtOccupied()) {
|
||||
// 根据查询列车
|
||||
List<TrainInfo> trainInfos = repository.queryTrainInfosBySection(section);
|
||||
if (!CollectionUtils.isEmpty(trainInfos)) {
|
||||
for (TrainInfo info : trainInfos) {
|
||||
if (this.isRouteInnerTurnBackTrain(simulation, route, info)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
private void trySetRoute(Simulation simulation, TrainInfo trainInfo, Route route) {
|
||||
if (!route.isAtsControl()) {
|
||||
return;
|
||||
}
|
||||
if (route.isSetting()) {
|
||||
return;
|
||||
}
|
||||
if (route.isCheckConflict() && route.getConflictAlarm() != null) {
|
||||
if (!route.isConflictConfirmed() ||
|
||||
route.isConflictHandleRunAsPlan()) {
|
||||
// 进路冲突,且进路检查冲突,且用户未确认或确认按计划执行,不办理,返回
|
||||
return;
|
||||
}
|
||||
}
|
||||
// 判断进路内是否有折返(调头)列车
|
||||
if (this.hasTurnBackTrainInRoute(simulation, trainInfo, route)) {
|
||||
return;
|
||||
}
|
||||
log.debug(String.format("为列车[%s]办理进路[%s]", trainInfo.getGroupNumber(), route.getName()));
|
||||
this.ciApiService.settingRoute(simulation, route.getCode(), false);
|
||||
}
|
||||
|
||||
private boolean hasTurnBackTrainInRoute(Simulation simulation, TrainInfo trainInfo, Route route) {
|
||||
SimulationDataRepository repository = simulation.getRepository();
|
||||
List<Section> sectionList = route.getSectionList();
|
||||
for (int i = sectionList.size() - 1; i >= 0; i--) {
|
||||
Section section = sectionList.get(i);
|
||||
if (section.isNctOccupied() || section.isCtOccupied()) {
|
||||
// 根据查询列车
|
||||
List<TrainInfo> trainInfos = repository.queryTrainInfosBySection(section);
|
||||
if (!CollectionUtils.isEmpty(trainInfos)) {
|
||||
for (TrainInfo info : trainInfos) {
|
||||
if (this.isRouteInnerTurnBackTrain(simulation, route, info)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean isRouteInnerTurnBackTrain(Simulation simulation, Route route, TrainInfo trainInfo) {
|
||||
if (trainInfo.getRight() != null && trainInfo.getRight().booleanValue() != route.isRight()) {
|
||||
// 列车和进路反向
|
||||
private boolean isRouteInnerTurnBackTrain(Simulation simulation, Route route,
|
||||
TrainInfo trainInfo) {
|
||||
if (trainInfo.getRight() != null && trainInfo.getRight().booleanValue() != route.isRight()) {
|
||||
// 列车和进路反向
|
||||
return true;
|
||||
}
|
||||
if (trainInfo.isTurnBack() && (TrainInfo.TO.equals(trainInfo.getTurnBackStatus()) ||
|
||||
TrainInfo.STOP.equals(trainInfo.getTurnBackStatus()))) { // 折返中
|
||||
return true;
|
||||
}
|
||||
// 暂时先只考虑计划车调头情况
|
||||
if (!trainInfo.isPlanTrain()) {
|
||||
return false;
|
||||
}
|
||||
// 计划车没有下一个计划,可能是加载折返情况
|
||||
if (trainInfo.getPlanStandTrack() == null) {
|
||||
return true;
|
||||
}
|
||||
SimulationDataRepository repository = simulation.getRepository();
|
||||
TripPlan tripPlan = repository.getTripPlan(trainInfo.getServiceNumber(),
|
||||
trainInfo.getTripNumber());
|
||||
List<StationPlan> planList = tripPlan.getPlanList();
|
||||
int size = planList.size();
|
||||
for (int i = 1; i < size; i++) {
|
||||
StationPlan stationPlan = planList.get(i - 1);
|
||||
StationPlan next = planList.get(i);
|
||||
List<RoutePath> currentPaths = repository.getRoutePaths(stationPlan.getSection(),
|
||||
next.getSection());
|
||||
boolean opposite = false;
|
||||
if (next.getSection().getCode().equals(trainInfo.getPlanStandTrack())) {
|
||||
if (i + 1 < size) {
|
||||
List<RoutePath> nextPaths = repository.getRoutePaths(next.getSection(),
|
||||
planList.get(i + 1).getSection());
|
||||
if (currentPaths.get(0).isRight() == nextPaths.get(0).isRight()) {
|
||||
break;
|
||||
} else { // 存在反向
|
||||
opposite = true;
|
||||
}
|
||||
} else {
|
||||
if (next.getSection().equals(tripPlan.getEndSection())) { // 站前折返
|
||||
opposite = true;
|
||||
}
|
||||
}
|
||||
if (opposite) { // 存在反向
|
||||
if (next.getSection().isSameAxle(trainInfo.getPhysicalSection())) { // 已经到达下一站台
|
||||
return true;
|
||||
}
|
||||
if (trainInfo.isTurnBack() && (TrainInfo.TO.equals(trainInfo.getTurnBackStatus()) ||
|
||||
TrainInfo.STOP.equals(trainInfo.getTurnBackStatus()))) { // 折返中
|
||||
return true;
|
||||
}
|
||||
// 暂时先只考虑计划车调头情况
|
||||
if (!trainInfo.isPlanTrain()) {
|
||||
return false;
|
||||
}
|
||||
// 计划车没有下一个计划,可能是加载折返情况
|
||||
if (trainInfo.getPlanStandTrack() == null) {
|
||||
return true;
|
||||
}
|
||||
SimulationDataRepository repository = simulation.getRepository();
|
||||
TripPlan tripPlan = repository.getTripPlan(trainInfo.getServiceNumber(), trainInfo.getTripNumber());
|
||||
List<StationPlan> planList = tripPlan.getPlanList();
|
||||
int size = planList.size();
|
||||
for (int i = 1; i < size; i++) {
|
||||
StationPlan stationPlan = planList.get(i - 1);
|
||||
StationPlan next = planList.get(i);
|
||||
List<RoutePath> currentPaths = repository.getRoutePaths(stationPlan.getSection(), next.getSection());
|
||||
boolean opposite = false;
|
||||
if (next.getSection().getCode().equals(trainInfo.getPlanStandTrack())) {
|
||||
if (i + 1 < size) {
|
||||
List<RoutePath> nextPaths = repository.getRoutePaths(next.getSection(), planList.get(i + 1).getSection());
|
||||
if (currentPaths.get(0).isRight() == nextPaths.get(0).isRight()) {
|
||||
break;
|
||||
} else { // 存在反向
|
||||
opposite = true;
|
||||
}
|
||||
} else {
|
||||
if (next.getSection().equals(tripPlan.getEndSection())) { // 站前折返
|
||||
opposite = true;
|
||||
}
|
||||
}
|
||||
if (opposite) { // 存在反向
|
||||
if (next.getSection().isSameAxle(trainInfo.getPhysicalSection())) { // 已经到达下一站台
|
||||
return true;
|
||||
}
|
||||
for (RoutePath currentPath : currentPaths) {
|
||||
if (currentPath.isEndRouteSection(trainInfo.getPhysicalSection())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
for (RoutePath currentPath : currentPaths) {
|
||||
if (currentPath.isEndRouteSection(trainInfo.getPhysicalSection())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private AtsRouteSelectService getRouteSelectService(TrainInfo trainInfo) {
|
||||
if (trainInfo.isPlanTrain()) {
|
||||
return this.planTrainRouteSelectService;
|
||||
} else if (trainInfo.isHeadCodeTrain()) {
|
||||
return this.headTrainRouteSelectService;
|
||||
}
|
||||
return null;
|
||||
private AtsRouteSelectService getRouteSelectService(TrainInfo trainInfo) {
|
||||
if (trainInfo.isPlanTrain()) {
|
||||
return this.planTrainRouteSelectService;
|
||||
} else if (trainInfo.isHeadCodeTrain()) {
|
||||
return this.headTrainRouteSelectService;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,355 +13,357 @@ import club.joylink.rtss.simulation.cbtc.data.map.Station;
|
|||
*/
|
||||
public interface CiApiService {
|
||||
|
||||
/**
|
||||
* 封锁区段
|
||||
*
|
||||
* @param simulation
|
||||
* @param sectionCode
|
||||
*/
|
||||
void blockadeSection(Simulation simulation, String sectionCode);
|
||||
/**
|
||||
* 封锁区段
|
||||
*
|
||||
* @param simulation
|
||||
* @param sectionCode
|
||||
*/
|
||||
void blockadeSection(Simulation simulation, String sectionCode);
|
||||
|
||||
/**
|
||||
* 解封区段
|
||||
*
|
||||
* @param simulation
|
||||
* @param sectionCode
|
||||
*/
|
||||
void unblockSection(Simulation simulation, String sectionCode);
|
||||
/**
|
||||
* 解封区段
|
||||
*
|
||||
* @param simulation
|
||||
* @param sectionCode
|
||||
*/
|
||||
void unblockSection(Simulation simulation, String sectionCode);
|
||||
|
||||
/**
|
||||
* 封锁信号机
|
||||
*
|
||||
* @param simulation
|
||||
* @param signalCode
|
||||
*/
|
||||
void blockadeSignal(Simulation simulation, String signalCode);
|
||||
/**
|
||||
* 封锁信号机
|
||||
*
|
||||
* @param simulation
|
||||
* @param signalCode
|
||||
*/
|
||||
void blockadeSignal(Simulation simulation, String signalCode);
|
||||
|
||||
/**
|
||||
* 解封信号机
|
||||
*
|
||||
* @param simulation
|
||||
* @param signalCode
|
||||
*/
|
||||
void unblockSignal(Simulation simulation, String signalCode);
|
||||
/**
|
||||
* 解封信号机
|
||||
*
|
||||
* @param simulation
|
||||
* @param signalCode
|
||||
*/
|
||||
void unblockSignal(Simulation simulation, String signalCode);
|
||||
|
||||
/**
|
||||
* 信号关闭
|
||||
*
|
||||
* @param simulation
|
||||
* @param signalCode
|
||||
*/
|
||||
void closeSignal(Simulation simulation, String signalCode);
|
||||
/**
|
||||
* 信号关闭
|
||||
*
|
||||
* @param simulation
|
||||
* @param signalCode
|
||||
*/
|
||||
void closeSignal(Simulation simulation, String signalCode);
|
||||
|
||||
/**
|
||||
* 信号重开
|
||||
*
|
||||
* @param simulation
|
||||
* @param signalCode
|
||||
*/
|
||||
void reopenSignal(Simulation simulation, String signalCode);
|
||||
/**
|
||||
* 信号重开
|
||||
*
|
||||
* @param simulation
|
||||
* @param signalCode
|
||||
*/
|
||||
void reopenSignal(Simulation simulation, String signalCode);
|
||||
|
||||
/**
|
||||
* 转动道岔
|
||||
*
|
||||
* @param simulation
|
||||
* @param switchCode
|
||||
* @return
|
||||
*/
|
||||
SwitchIndication turn(Simulation simulation, String switchCode);
|
||||
/**
|
||||
* 转动道岔
|
||||
*
|
||||
* @param simulation
|
||||
* @param switchCode
|
||||
* @return
|
||||
*/
|
||||
SwitchIndication turn(Simulation simulation, String switchCode);
|
||||
|
||||
/**
|
||||
* 转动道岔到定位
|
||||
*
|
||||
* @param simulation
|
||||
* @param switchCode
|
||||
*/
|
||||
void turn2NormalPosition(Simulation simulation, String switchCode);
|
||||
/**
|
||||
* 转动道岔到定位
|
||||
*
|
||||
* @param simulation
|
||||
* @param switchCode
|
||||
*/
|
||||
void turn2NormalPosition(Simulation simulation, String switchCode);
|
||||
|
||||
/**
|
||||
* 转动道岔到反位
|
||||
*
|
||||
* @param simulation
|
||||
* @param switchCode
|
||||
*/
|
||||
void turn2ReversePosition(Simulation simulation, String switchCode);
|
||||
/**
|
||||
* 转动道岔到反位
|
||||
*
|
||||
* @param simulation
|
||||
* @param switchCode
|
||||
*/
|
||||
void turn2ReversePosition(Simulation simulation, String switchCode);
|
||||
|
||||
/**
|
||||
* 道岔单锁
|
||||
*
|
||||
* @param simulation
|
||||
* @param switchCode
|
||||
*/
|
||||
void singleLockSwitch(Simulation simulation, String switchCode);
|
||||
/**
|
||||
* 道岔单锁
|
||||
*
|
||||
* @param simulation
|
||||
* @param switchCode
|
||||
*/
|
||||
void singleLockSwitch(Simulation simulation, String switchCode);
|
||||
|
||||
/**
|
||||
* 道岔单解
|
||||
*
|
||||
* @param simulation
|
||||
* @param switchCode
|
||||
*/
|
||||
void singleUnlockSwitch(Simulation simulation, String switchCode);
|
||||
/**
|
||||
* 道岔单解
|
||||
*
|
||||
* @param simulation
|
||||
* @param switchCode
|
||||
*/
|
||||
void singleUnlockSwitch(Simulation simulation, String switchCode);
|
||||
|
||||
/**
|
||||
* 封锁道岔
|
||||
*
|
||||
* @param simulation
|
||||
* @param switchCode
|
||||
*/
|
||||
void blockadeSwitch(Simulation simulation, String switchCode);
|
||||
/**
|
||||
* 封锁道岔
|
||||
*
|
||||
* @param simulation
|
||||
* @param switchCode
|
||||
*/
|
||||
void blockadeSwitch(Simulation simulation, String switchCode);
|
||||
|
||||
/**
|
||||
* 封锁道岔及道岔区段
|
||||
*
|
||||
* @param simulation
|
||||
* @param switchCode
|
||||
*/
|
||||
void blockadeSwitchSection(Simulation simulation, String switchCode);
|
||||
/**
|
||||
* 封锁道岔及道岔区段
|
||||
*
|
||||
* @param simulation
|
||||
* @param switchCode
|
||||
*/
|
||||
void blockadeSwitchSection(Simulation simulation, String switchCode);
|
||||
|
||||
/**
|
||||
* 解封道岔
|
||||
*
|
||||
* @param simulation
|
||||
* @param switchCode
|
||||
*/
|
||||
void unblockSwitch(Simulation simulation, String switchCode);
|
||||
/**
|
||||
* 解封道岔
|
||||
*
|
||||
* @param simulation
|
||||
* @param switchCode
|
||||
*/
|
||||
void unblockSwitch(Simulation simulation, String switchCode);
|
||||
|
||||
/**
|
||||
* 解封道岔及道岔区段
|
||||
*
|
||||
* @param simulation
|
||||
* @param switchCode
|
||||
*/
|
||||
void unblockSwitchSection(Simulation simulation, String switchCode);
|
||||
/**
|
||||
* 解封道岔及道岔区段
|
||||
*
|
||||
* @param simulation
|
||||
* @param switchCode
|
||||
*/
|
||||
void unblockSwitchSection(Simulation simulation, String switchCode);
|
||||
|
||||
/**
|
||||
* 进路排列条件检查
|
||||
*
|
||||
* @param simulation
|
||||
* @param routeCode
|
||||
* @return
|
||||
*/
|
||||
Route.CheckFailMessage routeSettingCheck(Simulation simulation, String routeCode);
|
||||
/**
|
||||
* 进路排列条件检查
|
||||
*
|
||||
* @param simulation
|
||||
* @param routeCode
|
||||
* @return
|
||||
*/
|
||||
Route.CheckFailMessage routeSettingCheck(Simulation simulation, String routeCode);
|
||||
|
||||
/**
|
||||
* 排列进路
|
||||
*
|
||||
* @param simulation
|
||||
* @param routeCode
|
||||
* @return
|
||||
*/
|
||||
Route.CheckFailMessage settingRoute(Simulation simulation, String routeCode);
|
||||
/**
|
||||
* 排列进路
|
||||
*
|
||||
* @param manual 是否人工办理
|
||||
* @return 进路办理失败的原因
|
||||
*/
|
||||
Route.CheckFailMessage settingRoute(Simulation simulation, String routeCode, boolean manual);
|
||||
|
||||
/**
|
||||
* 解锁进路/取消进路(无法取消进路接近区段占用的进路)
|
||||
*
|
||||
* @param simulation
|
||||
* @param routeCode
|
||||
*/
|
||||
void unlockRoute(Simulation simulation, String routeCode);
|
||||
/**
|
||||
* 解锁进路/取消进路(无法取消进路接近区段占用的进路)
|
||||
*
|
||||
* @param simulation
|
||||
* @param routeCode
|
||||
*/
|
||||
void unlockRoute(Simulation simulation, String routeCode);
|
||||
|
||||
/**
|
||||
* 解锁进路/取消进路(强制取消进路,无论接近区段是否占用)
|
||||
*
|
||||
* @param simulation
|
||||
* @param routeCode
|
||||
*/
|
||||
void forceUnlockRoute(Simulation simulation, String routeCode);
|
||||
/**
|
||||
* 解锁进路/取消进路(强制取消进路,无论接近区段是否占用)
|
||||
*
|
||||
* @param simulation
|
||||
* @param routeCode
|
||||
*/
|
||||
void forceUnlockRoute(Simulation simulation, String routeCode);
|
||||
|
||||
/**
|
||||
* 人解进路
|
||||
*
|
||||
* @param simulation
|
||||
* @param routeCode
|
||||
*/
|
||||
void humanCancel(Simulation simulation, String routeCode);
|
||||
/**
|
||||
* 人解进路
|
||||
*
|
||||
* @param simulation
|
||||
* @param routeCode
|
||||
*/
|
||||
void humanCancel(Simulation simulation, String routeCode);
|
||||
|
||||
/**
|
||||
* 区故解
|
||||
*
|
||||
* @param simulation
|
||||
* @param sectionCode
|
||||
*/
|
||||
void sectionFaultUnlock(Simulation simulation, String sectionCode);
|
||||
/**
|
||||
* 区故解
|
||||
*
|
||||
* @param simulation
|
||||
* @param sectionCode
|
||||
*/
|
||||
void sectionFaultUnlock(Simulation simulation, String sectionCode);
|
||||
|
||||
/**
|
||||
* 区故解
|
||||
*
|
||||
* @param simulation
|
||||
* @param switchCode
|
||||
*/
|
||||
void switchSectionFaultUnlock(Simulation simulation, String switchCode);
|
||||
/**
|
||||
* 区故解
|
||||
*
|
||||
* @param simulation
|
||||
* @param switchCode
|
||||
*/
|
||||
void switchSectionFaultUnlock(Simulation simulation, String switchCode);
|
||||
|
||||
/**
|
||||
* 取消自动通过进路
|
||||
*
|
||||
* @param simulation
|
||||
* @param routeCode
|
||||
*/
|
||||
void cancelFleetRoute(Simulation simulation, String routeCode);
|
||||
/**
|
||||
* 取消自动通过进路
|
||||
*
|
||||
* @param simulation
|
||||
* @param routeCode
|
||||
*/
|
||||
void cancelFleetRoute(Simulation simulation, String routeCode);
|
||||
|
||||
/**
|
||||
* 根据始端信号机查询锁闭进路
|
||||
*
|
||||
* @param simulation
|
||||
* @param signalCode
|
||||
* @return
|
||||
*/
|
||||
Route findLockedRouteByStartSignal(Simulation simulation, String signalCode);
|
||||
/**
|
||||
* 根据始端信号机查询锁闭进路
|
||||
*
|
||||
* @param simulation
|
||||
* @param signalCode
|
||||
* @return
|
||||
*/
|
||||
Route findLockedRouteByStartSignal(Simulation simulation, String signalCode);
|
||||
|
||||
/**
|
||||
* 开站台屏蔽门
|
||||
*
|
||||
* @param simulation
|
||||
* @param standCode
|
||||
* @param source
|
||||
*/
|
||||
void openScreenDoor(Simulation simulation, String standCode, CiStandService.PsdCommandSource source);
|
||||
/**
|
||||
* 开站台屏蔽门
|
||||
*
|
||||
* @param simulation
|
||||
* @param standCode
|
||||
* @param source
|
||||
*/
|
||||
void openScreenDoor(Simulation simulation, String standCode,
|
||||
CiStandService.PsdCommandSource source);
|
||||
|
||||
/**
|
||||
* 关站台屏蔽门
|
||||
*
|
||||
* @param simulation
|
||||
* @param standCode
|
||||
* @param source
|
||||
*/
|
||||
void closeScreenDoor(Simulation simulation, String standCode, CiStandService.PsdCommandSource source);
|
||||
/**
|
||||
* 关站台屏蔽门
|
||||
*
|
||||
* @param simulation
|
||||
* @param standCode
|
||||
* @param source
|
||||
*/
|
||||
void closeScreenDoor(Simulation simulation, String standCode,
|
||||
CiStandService.PsdCommandSource source);
|
||||
|
||||
/**
|
||||
* 站台扣车,联锁关系处理
|
||||
*
|
||||
* @param simulation
|
||||
* @param standCode
|
||||
* @param center - true:中心扣车,false:车站扣车
|
||||
*/
|
||||
void standHoldTrain(Simulation simulation, String standCode, boolean center);
|
||||
/**
|
||||
* 站台扣车,联锁关系处理
|
||||
*
|
||||
* @param simulation
|
||||
* @param standCode
|
||||
* @param center - true:中心扣车,false:车站扣车
|
||||
*/
|
||||
void standHoldTrain(Simulation simulation, String standCode, boolean center);
|
||||
|
||||
void sysHoldTrain(Simulation simulation, String standCode);
|
||||
void sysHoldTrain(Simulation simulation, String standCode);
|
||||
|
||||
/**
|
||||
* 站台取消扣车,联锁关系处理
|
||||
*
|
||||
* @param simulation
|
||||
* @param standCode
|
||||
* @param center - true:中心扣车,false:车站扣车
|
||||
*/
|
||||
void standHoldTrainCancel(Simulation simulation, String standCode, boolean center);
|
||||
/**
|
||||
* 站台取消扣车,联锁关系处理
|
||||
*
|
||||
* @param simulation
|
||||
* @param standCode
|
||||
* @param center - true:中心扣车,false:车站扣车
|
||||
*/
|
||||
void standHoldTrainCancel(Simulation simulation, String standCode, boolean center);
|
||||
|
||||
void sysHoldTrainCancel(Simulation simulation, String standCode);
|
||||
void sysHoldTrainCancel(Simulation simulation, String standCode);
|
||||
|
||||
void ibpHoldTrain(Simulation simulation, String standCode);
|
||||
void ibpHoldTrain(Simulation simulation, String standCode);
|
||||
|
||||
void ibpHoldTrainCancel(Simulation simulation, String standCode);
|
||||
void ibpHoldTrainCancel(Simulation simulation, String standCode);
|
||||
|
||||
void standHoldTrainCancelAll(Simulation simulation, String standCode);
|
||||
void standHoldTrainCancelAll(Simulation simulation, String standCode);
|
||||
|
||||
/**
|
||||
* 办理引导
|
||||
*
|
||||
* @param simulation
|
||||
* @param signalCode
|
||||
* @param routeCode
|
||||
*/
|
||||
void setGuide(Simulation simulation, String signalCode, String routeCode);
|
||||
/**
|
||||
* 办理引导
|
||||
*
|
||||
* @param simulation
|
||||
* @param signalCode
|
||||
* @param routeCode
|
||||
*/
|
||||
void setGuide(Simulation simulation, String signalCode, String routeCode);
|
||||
|
||||
void setEst(Simulation simulation, ESP esp);
|
||||
void setEst(Simulation simulation, ESP esp);
|
||||
|
||||
void cancelEst(Simulation simulation, ESP esp);
|
||||
void cancelEst(Simulation simulation, ESP esp);
|
||||
|
||||
/**
|
||||
* 重启令解
|
||||
*/
|
||||
void restart(Simulation simulation, Station station);
|
||||
/**
|
||||
* 重启令解
|
||||
*/
|
||||
void restart(Simulation simulation, Station station);
|
||||
|
||||
/**
|
||||
* 释放指令
|
||||
*
|
||||
* @param simulation
|
||||
* @param station
|
||||
*/
|
||||
void release(Simulation simulation, Station station);
|
||||
/**
|
||||
* 释放指令
|
||||
*
|
||||
* @param simulation
|
||||
* @param station
|
||||
*/
|
||||
void release(Simulation simulation, Station station);
|
||||
|
||||
/**
|
||||
* 上电解锁
|
||||
*/
|
||||
void powerOnUnlock(Simulation simulation, Station station);
|
||||
/**
|
||||
* 上电解锁
|
||||
*/
|
||||
void powerOnUnlock(Simulation simulation, Station station);
|
||||
|
||||
/**
|
||||
* 站台紧急停车
|
||||
*/
|
||||
void standEC(Simulation simulation, Stand stand);
|
||||
/**
|
||||
* 站台紧急停车
|
||||
*/
|
||||
void standEC(Simulation simulation, Stand stand);
|
||||
|
||||
/**
|
||||
* 取消站台紧急停车
|
||||
*/
|
||||
void cancelStandEC(Simulation simulation, Stand stand);
|
||||
/**
|
||||
* 取消站台紧急停车
|
||||
*/
|
||||
void cancelStandEC(Simulation simulation, Stand stand);
|
||||
|
||||
/**
|
||||
* 强扳道岔
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
SwitchIndication switchForceTurn(Simulation simulation, String switchCode);
|
||||
/**
|
||||
* 强扳道岔
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
SwitchIndication switchForceTurn(Simulation simulation, String switchCode);
|
||||
|
||||
/**
|
||||
* 计轴预复位
|
||||
*/
|
||||
void axlePreReset(Simulation simulation, String sectionCode);
|
||||
/**
|
||||
* 计轴预复位
|
||||
*/
|
||||
void axlePreReset(Simulation simulation, String sectionCode);
|
||||
|
||||
/**
|
||||
* 道岔计轴预复位
|
||||
*/
|
||||
void switchAxlePreReset(Simulation simulation, String switchCode);
|
||||
/**
|
||||
* 道岔计轴预复位
|
||||
*/
|
||||
void switchAxlePreReset(Simulation simulation, String switchCode);
|
||||
|
||||
/**
|
||||
* 挤岔恢复
|
||||
*/
|
||||
void switchSqueezeRecovery(Simulation simulation, String switchCode);
|
||||
/**
|
||||
* 挤岔恢复
|
||||
*/
|
||||
void switchSqueezeRecovery(Simulation simulation, String switchCode);
|
||||
|
||||
/**
|
||||
* 命令
|
||||
*
|
||||
* @param auto 是否自动模式
|
||||
* @param reserve 是否预留
|
||||
*/
|
||||
void switchCommand(Simulation simulation, String switchCode, Boolean auto, Boolean reserve, Boolean normal);
|
||||
/**
|
||||
* 命令
|
||||
*
|
||||
* @param auto 是否自动模式
|
||||
* @param reserve 是否预留
|
||||
*/
|
||||
void switchCommand(Simulation simulation, String switchCode, Boolean auto, Boolean reserve,
|
||||
Boolean normal);
|
||||
|
||||
/**
|
||||
* 初始化封锁
|
||||
*/
|
||||
void initializeBlock(Simulation simulation, String switchCode);
|
||||
/**
|
||||
* 初始化封锁
|
||||
*/
|
||||
void initializeBlock(Simulation simulation, String switchCode);
|
||||
|
||||
/**
|
||||
* 初始化引导
|
||||
*/
|
||||
void initializeGuide(Simulation simulation, String signalCode);
|
||||
/**
|
||||
* 初始化引导
|
||||
*/
|
||||
void initializeGuide(Simulation simulation, String signalCode);
|
||||
|
||||
/**
|
||||
* 取消引导的初始化
|
||||
*/
|
||||
void cancelGuideInitialization(Simulation simulation, String signalCode);
|
||||
/**
|
||||
* 取消引导的初始化
|
||||
*/
|
||||
void cancelGuideInitialization(Simulation simulation, String signalCode);
|
||||
|
||||
/**
|
||||
* 计轴复位
|
||||
*/
|
||||
void axleReset(Simulation simulation, String sectionCode);
|
||||
/**
|
||||
* 计轴复位
|
||||
*/
|
||||
void axleReset(Simulation simulation, String sectionCode);
|
||||
|
||||
/**
|
||||
* 设置延续保护
|
||||
*
|
||||
* @param simulation
|
||||
* @param signalCode
|
||||
* @param overlapCode
|
||||
*/
|
||||
void setOverlap(Simulation simulation, String signalCode, String overlapCode);
|
||||
/**
|
||||
* 设置延续保护
|
||||
*
|
||||
* @param simulation
|
||||
* @param signalCode
|
||||
* @param overlapCode
|
||||
*/
|
||||
void setOverlap(Simulation simulation, String signalCode, String overlapCode);
|
||||
|
||||
void setOrCancelInterlockRelease(Simulation simulation, Stand stand, boolean release);
|
||||
void setOrCancelInterlockRelease(Simulation simulation, Stand stand, boolean release);
|
||||
|
||||
void switchMasterLock(Simulation simulation, String stationCode, Station.Throat throat);
|
||||
void switchMasterLock(Simulation simulation, String stationCode, Station.Throat throat);
|
||||
|
||||
void switchMasterUnlock(Simulation simulation, String stationCode, Station.Throat throat);
|
||||
void switchMasterUnlock(Simulation simulation, String stationCode, Station.Throat throat);
|
||||
|
||||
void signalTurnOn(Simulation simulation, String signalCode);
|
||||
void signalTurnOn(Simulation simulation, String signalCode);
|
||||
|
||||
void signalTurnOff(Simulation simulation, String signalCode);
|
||||
void signalTurnOff(Simulation simulation, String signalCode);
|
||||
}
|
||||
|
|
|
@ -206,15 +206,16 @@ public class CiApiServiceImpl2 implements CiApiService {
|
|||
@Override
|
||||
public Route.CheckFailMessage routeSettingCheck(Simulation simulation, String routeCode) {
|
||||
Route route = simulation.getRepository().getByCode(routeCode, Route.class);
|
||||
return this.routeService.routeSetCheck(simulation, route, false);
|
||||
return this.routeService.routeSetCheck(simulation, route, false, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Route.CheckFailMessage settingRoute(Simulation simulation, String routeCode) {
|
||||
public Route.CheckFailMessage settingRoute(Simulation simulation, String routeCode,
|
||||
boolean manual) {
|
||||
Route route = simulation.getRepository().getByCode(routeCode, Route.class);
|
||||
//当为一般进路时直接获取信号显示,当为组合进路时信号显示获取到办理子进路时
|
||||
SignalAspect settedAspect = route.isMultiRoute() ? null : route.getAspect();
|
||||
return this.routeService.setRoute(simulation, route, settedAspect);
|
||||
return this.routeService.setRoute(simulation, route, settedAspect, manual);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -256,9 +257,9 @@ public class CiApiServiceImpl2 implements CiApiService {
|
|||
public void sectionFaultUnlock(Simulation simulation, String sectionCode) {
|
||||
Section section = simulation.getRepository().getByCode(sectionCode, Section.class);
|
||||
if (simulation.getRepository().getConfig().isSFUCanOnlyApplyForFaultLockSection()) {
|
||||
if (!section.isFaultLock()) {
|
||||
return;
|
||||
}
|
||||
if (!section.isFaultLock()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (section.isCross()) {
|
||||
Optional<Section> crossLockedSectionOptional = section.getLogicList().stream()
|
||||
|
@ -297,9 +298,9 @@ public class CiApiServiceImpl2 implements CiApiService {
|
|||
@Override
|
||||
public void switchSectionFaultUnlock(Simulation simulation, String switchCode) {
|
||||
Switch aSwitch = simulation.getRepository().getByCode(switchCode, Switch.class);
|
||||
if (!aSwitch.isLocked() && aSwitch.getAllSections().stream().noneMatch(Section::isLocked)) {
|
||||
return;
|
||||
}
|
||||
if (!aSwitch.isLocked() && aSwitch.getAllSections().stream().noneMatch(Section::isLocked)) {
|
||||
return;
|
||||
}
|
||||
List<Route> lockedRouteList = simulation.getRepository().queryAllLockedRoute();
|
||||
Set<Route> lockSwitchRoutes = new HashSet<>();
|
||||
if (aSwitch.isRouteLock()) {
|
||||
|
@ -584,17 +585,17 @@ public class CiApiServiceImpl2 implements CiApiService {
|
|||
|
||||
@Override
|
||||
public void standEC(Simulation simulation, Stand stand) {
|
||||
if (stand.getEsp() == null) {
|
||||
return;
|
||||
}
|
||||
if (stand.getEsp() == null) {
|
||||
return;
|
||||
}
|
||||
stand.getEsp().update(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancelStandEC(Simulation simulation, Stand stand) {
|
||||
if (stand.getEsp() == null) {
|
||||
return;
|
||||
}
|
||||
if (stand.getEsp() == null) {
|
||||
return;
|
||||
}
|
||||
stand.getEsp().update(false);
|
||||
}
|
||||
|
||||
|
@ -680,9 +681,9 @@ public class CiApiServiceImpl2 implements CiApiService {
|
|||
@Override
|
||||
public void axleReset(Simulation simulation, String sectionCode) {
|
||||
VirtualRealitySectionAxleCounter axle = getAxleCounterAndCheck4Reset(simulation, sectionCode);
|
||||
if (!axle.isOccupy()) {
|
||||
return;
|
||||
}
|
||||
if (!axle.isOccupy()) {
|
||||
return;
|
||||
}
|
||||
axle.axleReset();
|
||||
}
|
||||
|
||||
|
|
|
@ -240,7 +240,7 @@ public class CiLogic {
|
|||
MapConfig config = simulation.getRepository().getConfig();
|
||||
if (route.isCiControl()) { // 进路联锁自动触发
|
||||
if (!route.isLock() && !route.isSetting() && ciService.isCiRouteTrigger(simulation, route)) {
|
||||
routeService.setRoute(simulation, route, route.getAspect());
|
||||
routeService.setRoute(simulation, route, route.getAspect(), false);
|
||||
}
|
||||
} else if (route.isFleetMode()) { // 联锁自动进路
|
||||
if (ciService.isCiRouteTrigger(simulation, route)) {
|
||||
|
|
|
@ -40,15 +40,16 @@ public class CiRouteService {
|
|||
/**
|
||||
* 进路排列检查
|
||||
*
|
||||
* @param guide 是引导进路?
|
||||
* @param guide 是引导进路?
|
||||
* @param manual
|
||||
* @return
|
||||
*/
|
||||
public static Route.CheckFailMessage routeSetCheck(Simulation simulation, Route route,
|
||||
boolean guide) {
|
||||
boolean guide, boolean manual) {
|
||||
if (!CollectionUtils.isEmpty(route.getMultiRouteAspects())) {
|
||||
for (Route.MultiRouteAspect multiRouteAspect : route.getMultiRouteAspects()) {
|
||||
Route.CheckFailMessage checkFailMessage = routeSetCheck(simulation,
|
||||
multiRouteAspect.getRoute(), false);
|
||||
multiRouteAspect.getRoute(), false, manual);
|
||||
if (checkFailMessage != null) {
|
||||
return checkFailMessage;
|
||||
}
|
||||
|
@ -111,21 +112,7 @@ public class CiRouteService {
|
|||
// return new Route.CheckFailMessage(Route.CheckFailReason.SectionFaultOccupied, section);
|
||||
// }
|
||||
}
|
||||
//敌对进路
|
||||
List<Route> conflictingRouteList = route.getConflictingRouteList();
|
||||
for (Route conflict : conflictingRouteList) {
|
||||
if (conflict.isSetting() || conflict.isLock()) {
|
||||
return new Route.CheckFailMessage(Route.CheckFailReason.ConflictingRouteSetting,
|
||||
conflict);
|
||||
}
|
||||
}
|
||||
if (start.isCbtcMode()) {
|
||||
// CBTC办理检查
|
||||
// Section firstLogicSection = route.getFirstLogicSection();
|
||||
// if (firstLogicSection.isOccupied()) {
|
||||
// return new Route.CheckFailMessage(Route.CheckFailReason.SectionNotFree, firstLogicSection);
|
||||
// }
|
||||
} else {
|
||||
if (!start.isCbtcMode()) {
|
||||
// 后备办理检查
|
||||
// 区段占用
|
||||
for (Section section : sectionList) {
|
||||
|
@ -140,6 +127,26 @@ public class CiRouteService {
|
|||
failMessage = setSwitchCheck(simulation, sectionPath.getSwitchList(), guide);
|
||||
}
|
||||
}
|
||||
//敌对进路
|
||||
List<Route> conflictingRouteList = route.getConflictingRouteList();
|
||||
for (Route conflict : conflictingRouteList) {
|
||||
if (conflict.isLock()) {
|
||||
return new Route.CheckFailMessage(Route.CheckFailReason.ConflictingRouteSetting,
|
||||
conflict);
|
||||
}
|
||||
if (conflict.isSetting()) {
|
||||
if (manual) {
|
||||
log.warn("进路[{}]被人工办理的进路[{}]取消办理", conflict.debugStr(), route.debugStr());
|
||||
conflict.settingOver(false);
|
||||
conflict.getSwitchList().forEach(se -> {
|
||||
se.getASwitch().checkAndResetUsePosition();
|
||||
});
|
||||
} else {
|
||||
return new Route.CheckFailMessage(Route.CheckFailReason.ConflictingRouteSetting,
|
||||
conflict);
|
||||
}
|
||||
}
|
||||
}
|
||||
return failMessage;
|
||||
}
|
||||
return null;
|
||||
|
@ -206,7 +213,7 @@ public class CiRouteService {
|
|||
*/
|
||||
public void setGuide(Simulation simulation, Route route) {
|
||||
// 进路检查
|
||||
Route.CheckFailMessage failMessage = routeSetCheck(simulation, route, true);
|
||||
Route.CheckFailMessage failMessage = routeSetCheck(simulation, route, true, false);
|
||||
if (failMessage == null) {
|
||||
if (route.isLock() && !route.isFleetMode()) {
|
||||
log.info("进路[{}]已经锁闭", route.debugStr());
|
||||
|
@ -234,11 +241,12 @@ public class CiRouteService {
|
|||
*
|
||||
* @param simulation
|
||||
* @param route
|
||||
* @param manual
|
||||
* @return
|
||||
*/
|
||||
public Route.CheckFailMessage setRoute(Simulation simulation, Route route,
|
||||
SignalAspect settedAspect) {
|
||||
Route.CheckFailMessage failMessage = routeSetCheck(simulation, route, false);
|
||||
SignalAspect settedAspect, boolean manual) {
|
||||
Route.CheckFailMessage failMessage = routeSetCheck(simulation, route, false, manual);
|
||||
if (failMessage == null) {
|
||||
if (route.isLock() && !route.isFleetMode()) {
|
||||
log.info("进路[{}]已经锁闭", route.debugStr());
|
||||
|
@ -326,7 +334,7 @@ public class CiRouteService {
|
|||
Route.MultiRouteAspect routeAspect = multiRouteAspects.get(i);
|
||||
Route subRoute = routeAspect.getRoute();
|
||||
if (!subRoute.isLock()) {
|
||||
setRoute(simulation, subRoute, routeAspect.getAspect());
|
||||
setRoute(simulation, subRoute, routeAspect.getAspect(), false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -85,9 +85,9 @@ public class CTCService {
|
|||
public void finishArrive(Simulation simulation, String stationCode, String tripNumber,
|
||||
LocalTime time) {
|
||||
CtcStationRunPlanLog plan = getCtcStationRunPlan(simulation, stationCode, tripNumber);
|
||||
if (time == null) {
|
||||
time = simulation.getCorrectSystemTime().toLocalTime();
|
||||
}
|
||||
if (time == null) {
|
||||
time = simulation.getCorrectSystemTime().toLocalTime();
|
||||
}
|
||||
plan.finishArrive(time);
|
||||
}
|
||||
|
||||
|
@ -99,9 +99,9 @@ public class CTCService {
|
|||
public void finishDeparture(Simulation simulation, String stationCode, String tripNumber,
|
||||
LocalTime time) {
|
||||
CtcStationRunPlanLog plan = getCtcStationRunPlan(simulation, stationCode, tripNumber);
|
||||
if (time == null) {
|
||||
time = simulation.getCorrectSystemTime().toLocalTime();
|
||||
}
|
||||
if (time == null) {
|
||||
time = simulation.getCorrectSystemTime().toLocalTime();
|
||||
}
|
||||
plan.finishDeparture(time);
|
||||
}
|
||||
|
||||
|
@ -177,9 +177,9 @@ public class CTCService {
|
|||
}
|
||||
}
|
||||
Station station = route.getStart().getStation();
|
||||
if (station == null) {
|
||||
station = route.getStart().getDeviceStation();
|
||||
}
|
||||
if (station == null) {
|
||||
station = route.getStart().getDeviceStation();
|
||||
}
|
||||
|
||||
List<String> conflictInfo = new ArrayList<>();
|
||||
CtcRepository ctcRepository = simulation.getCtcRepository();
|
||||
|
@ -196,10 +196,11 @@ public class CTCService {
|
|||
if (!CollectionUtils.isEmpty(lines)) {
|
||||
boolean b = lines.stream()
|
||||
.noneMatch(line -> Objects.equals(line.getRouteCode(), routeCode));
|
||||
if (b) {
|
||||
conflictInfo.add(
|
||||
String.format("车次[%s]的进路序列中不包含进路[name:%s]", tripNumber, route.getName()));
|
||||
}
|
||||
if (b) {
|
||||
conflictInfo.add(
|
||||
String.format("车次[%s]的进路序列中不包含进路[name:%s]", tripNumber,
|
||||
route.getName()));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (duration != null && !Objects.equals(true, force)) { //调车进路防错办
|
||||
|
@ -216,9 +217,9 @@ public class CTCService {
|
|||
out:
|
||||
for (RouteSequence.Line line : lines) {
|
||||
Route lineRoute = line.getRoute();
|
||||
if (lineRoute == null) {
|
||||
continue;
|
||||
}
|
||||
if (lineRoute == null) {
|
||||
continue;
|
||||
}
|
||||
for (Section section : lineRoute.getSectionList()) {
|
||||
if (sections.contains(section)) {
|
||||
conflictInfo.add(String.format("所选进路[name:%s]与车次[%s]的[name:%s]进路冲突",
|
||||
|
@ -239,14 +240,15 @@ public class CTCService {
|
|||
}
|
||||
}
|
||||
}
|
||||
if (!conflictInfo.isEmpty()) {
|
||||
return conflictInfo;
|
||||
}
|
||||
if (!conflictInfo.isEmpty()) {
|
||||
return conflictInfo;
|
||||
}
|
||||
|
||||
Route.CheckFailMessage checkFailMessage = ciApiService.settingRoute(simulation, routeCode);
|
||||
if (checkFailMessage != null) {
|
||||
throw BusinessExceptionAssertEnum.OPERATION_FAIL.exception(checkFailMessage.debugStr());
|
||||
}
|
||||
Route.CheckFailMessage checkFailMessage = ciApiService.settingRoute(simulation, routeCode,
|
||||
false);
|
||||
if (checkFailMessage != null) {
|
||||
throw BusinessExceptionAssertEnum.OPERATION_FAIL.exception(checkFailMessage.debugStr());
|
||||
}
|
||||
route.setTripNumber(tripNumber);
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -243,7 +243,7 @@ public class Switch extends DelayUnlockDevice {
|
|||
return this.routeLock && this.routes.contains(route);
|
||||
}
|
||||
|
||||
private void checkAndResetUsePosition() {
|
||||
public void checkAndResetUsePosition() {
|
||||
if (this.routeLock || this.fpLock || this.overlapLock ||
|
||||
this.a.isRouteLock() || this.a.isOverlapLock()) {
|
||||
return;
|
||||
|
|
|
@ -19,223 +19,246 @@ import club.joylink.rtss.simulation.cbtc.data.vo.TrainInfo;
|
|||
import club.joylink.rtss.simulation.cbtc.data.vr.VirtualRealityTrain;
|
||||
import club.joylink.rtss.simulation.cbtc.member.SimulationMember;
|
||||
import club.joylink.rtss.simulation.cbtc.onboard.ATP.ATPService;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
import lombok.Getter;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Component
|
||||
public class DepotService {
|
||||
|
||||
@Autowired
|
||||
private CiRouteService ciRouteService;
|
||||
@Autowired
|
||||
private CiRouteService ciRouteService;
|
||||
|
||||
@Autowired
|
||||
private TrainOutboundLoadTool trainOutboundLoadTool;
|
||||
@Autowired
|
||||
private TrainOutboundLoadTool trainOutboundLoadTool;
|
||||
|
||||
@Autowired
|
||||
private GroupSimulationService groupSimulationService;
|
||||
@Autowired
|
||||
private GroupSimulationService groupSimulationService;
|
||||
|
||||
@Autowired
|
||||
private ATPService atpService;
|
||||
@Autowired
|
||||
private AtsOperationDispatcher atsOperationDispatcher;
|
||||
@Autowired
|
||||
private ATPService atpService;
|
||||
@Autowired
|
||||
private AtsOperationDispatcher atsOperationDispatcher;
|
||||
|
||||
public void loadDepotTrain(Simulation simulation) {
|
||||
if (!simulation.getRepository().getConfig().isHandleDepot()) {
|
||||
return;
|
||||
}
|
||||
Map<Station, List<Section>> parkingTracksMap = simulation.getRepository().getParkingTracksMap();
|
||||
simulation.getRepository().getAllVrTrain().stream()
|
||||
.collect(Collectors.groupingBy(VirtualRealityTrain::getDepotStation))
|
||||
.forEach((station, trainList) -> {
|
||||
List<Section> sections = parkingTracksMap.get(station);
|
||||
// 先加载内侧的停车轨
|
||||
sections.sort(Comparator.comparing(section ->
|
||||
Objects.isNull(section.getLeftSection()) || Objects.isNull(section.getRightSection())));
|
||||
boolean right = sections.get(sections.size() - 1).getLeftSection() == null;
|
||||
for (int i = 0, trainListSize = trainList.size(); i < trainListSize; i++) {
|
||||
VirtualRealityTrain train = trainList.get(i);
|
||||
Section section = sections.get(i);
|
||||
train.initManualTrain(new SectionPosition(section, section.getStopPointByDirection(right)), right);
|
||||
train.parkingAt(section);
|
||||
train.initAsRM();
|
||||
TrainInfo trainInfo = TrainInfo.constructManualTrain(train);
|
||||
trainInfo.tracking(train);
|
||||
simulation.getRepository().addOnlineTrain(train);
|
||||
simulation.getRepository().addTrainInfo(trainInfo);
|
||||
}
|
||||
});
|
||||
public void loadDepotTrain(Simulation simulation) {
|
||||
if (!simulation.getRepository().getConfig().isHandleDepot()) {
|
||||
return;
|
||||
}
|
||||
Map<Station, List<Section>> parkingTracksMap = simulation.getRepository().getParkingTracksMap();
|
||||
simulation.getRepository().getAllVrTrain().stream()
|
||||
.collect(Collectors.groupingBy(VirtualRealityTrain::getDepotStation))
|
||||
.forEach((station, trainList) -> {
|
||||
List<Section> sections = parkingTracksMap.get(station);
|
||||
// 先加载内侧的停车轨
|
||||
sections.sort(Comparator.comparing(section ->
|
||||
Objects.isNull(section.getLeftSection()) || Objects.isNull(
|
||||
section.getRightSection())));
|
||||
boolean right = sections.get(sections.size() - 1).getLeftSection() == null;
|
||||
for (int i = 0, trainListSize = trainList.size(); i < trainListSize; i++) {
|
||||
VirtualRealityTrain train = trainList.get(i);
|
||||
Section section = sections.get(i);
|
||||
train.initManualTrain(
|
||||
new SectionPosition(section, section.getStopPointByDirection(right)), right);
|
||||
train.parkingAt(section);
|
||||
train.initAsRM();
|
||||
TrainInfo trainInfo = TrainInfo.constructManualTrain(train);
|
||||
trainInfo.tracking(train);
|
||||
simulation.getRepository().addOnlineTrain(train);
|
||||
simulation.getRepository().addTrainInfo(trainInfo);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void addJobs(Simulation simulation) {
|
||||
simulation.addJob(SimulationModule.DEPOT.name(), () -> this.run(simulation), SimulationConstants.DEPOT_LOOP_RATE);
|
||||
public void addJobs(Simulation simulation) {
|
||||
simulation.addJob(SimulationModule.DEPOT.name(), () -> this.run(simulation),
|
||||
SimulationConstants.DEPOT_LOOP_RATE);
|
||||
}
|
||||
|
||||
private void run(Simulation simulation) {
|
||||
if (!simulation.isPlanRunning()) {
|
||||
return;
|
||||
}
|
||||
|
||||
private void run(Simulation simulation) {
|
||||
if (!simulation.isPlanRunning()) {
|
||||
return;
|
||||
}
|
||||
if (!simulation.getRepository().getConfig().isHandleDepot()) {
|
||||
trainOutboundLoadTool.loadOutboundTrain(simulation);
|
||||
} else {
|
||||
timeToDeparture(simulation);
|
||||
backToParking(simulation);
|
||||
settingRouteAndMoving(simulation);
|
||||
arriveDestination(simulation);
|
||||
}
|
||||
if (!simulation.getRepository().getConfig().isHandleDepot()) {
|
||||
trainOutboundLoadTool.loadOutboundTrain(simulation);
|
||||
} else {
|
||||
timeToDeparture(simulation);
|
||||
backToParking(simulation);
|
||||
settingRouteAndMoving(simulation);
|
||||
arriveDestination(simulation);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据时间筛选,从停车轨自动发车
|
||||
*/
|
||||
private void timeToDeparture(Simulation simulation) {
|
||||
LocalDateTime systemTime = simulation.getSystemTime();
|
||||
for (SchedulingTrainPlan schedulingTrainPlan : simulation.getRepository().getSchedulingTrainPlanList()) {
|
||||
if (schedulingTrainPlan.getOutDepotTrip().isDispatched()) {
|
||||
continue;
|
||||
/**
|
||||
* 根据时间筛选,从停车轨自动发车
|
||||
*/
|
||||
private void timeToDeparture(Simulation simulation) {
|
||||
LocalDateTime systemTime = simulation.getSystemTime();
|
||||
for (SchedulingTrainPlan schedulingTrainPlan : simulation.getRepository()
|
||||
.getSchedulingTrainPlanList()) {
|
||||
if (schedulingTrainPlan.getOutDepotTrip().isDispatched()) {
|
||||
continue;
|
||||
}
|
||||
if (schedulingTrainPlan.getOutDepotTrip().getStartTime().minusMinutes(10)
|
||||
.isBefore(systemTime.toLocalTime())) {
|
||||
schedulingTrainPlan.getOutDepotTrip().dispatched();
|
||||
// 保存信息
|
||||
VirtualRealityTrain train = simulation.getRepository()
|
||||
.getVRByCode(schedulingTrainPlan.getGroupNumber(), VirtualRealityTrain.class);
|
||||
Section startSection = train.getHeadPosition().getSection();
|
||||
Section endSection = schedulingTrainPlan.getOutDepotTrip().getStartSection();
|
||||
List<RoutePath> routePaths = simulation.getRepository()
|
||||
.queryRoutePaths(startSection, endSection);
|
||||
RoutePath routePath = routePaths.get(0);
|
||||
DepotRunningInfo depotRunningInfo = new DepotRunningInfo(endSection, train, routePath,
|
||||
false);
|
||||
simulation.getRepository().getDepotRunningInfoList().add(depotRunningInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 筛选入库
|
||||
*/
|
||||
private void backToParking(Simulation simulation) {
|
||||
for (TrainInfo trainInfo : simulation.getRepository().getTrainInfoMap().values()) {
|
||||
if (trainInfo.isInbound() && trainInfo.isParking()) {
|
||||
VirtualRealityTrain train = simulation.getRepository()
|
||||
.getVRByCode(trainInfo.getGroupNumber(), VirtualRealityTrain.class);
|
||||
if (train.getHeadPosition().getSection().isTransferTrack()
|
||||
&& train.getTailPosition().getSection().isTransferTrack()) {
|
||||
if (simulation.getRepository().getDepotRunningInfoList().stream()
|
||||
.anyMatch(depotRunningInfo -> depotRunningInfo.getTrain().equals(train))) {
|
||||
continue;
|
||||
}
|
||||
train.initAsRM();
|
||||
Section startSection = train.getHeadPosition().getSection();
|
||||
Section endSection = null;
|
||||
for (Section section : simulation.getRepository().getParkingTracksMap()
|
||||
.get(startSection.getStation())) {
|
||||
if (section.isOccupied()) {
|
||||
continue;
|
||||
}
|
||||
if (schedulingTrainPlan.getOutDepotTrip().getStartTime().minusMinutes(10).isBefore(systemTime.toLocalTime())) {
|
||||
schedulingTrainPlan.getOutDepotTrip().dispatched();
|
||||
// 保存信息
|
||||
VirtualRealityTrain train = simulation.getRepository().getVRByCode(schedulingTrainPlan.getGroupNumber(), VirtualRealityTrain.class);
|
||||
Section startSection = train.getHeadPosition().getSection();
|
||||
Section endSection = schedulingTrainPlan.getOutDepotTrip().getStartSection();
|
||||
List<RoutePath> routePaths = simulation.getRepository().queryRoutePaths(startSection, endSection);
|
||||
RoutePath routePath = routePaths.get(0);
|
||||
DepotRunningInfo depotRunningInfo = new DepotRunningInfo(endSection, train, routePath, false);
|
||||
simulation.getRepository().getDepotRunningInfoList().add(depotRunningInfo);
|
||||
if (section.getLeftSection() == null || section.getRightSection() == null) {
|
||||
endSection = section;
|
||||
} else if (section.getLeftSection().isParkingTrack() && !section.getLeftSection()
|
||||
.isOccupied()) {
|
||||
endSection = section.getLeftSection();
|
||||
} else if (section.getRightSection().isParkingTrack() && !section.getRightSection()
|
||||
.isOccupied()) {
|
||||
endSection = section.getRightSection();
|
||||
} else {
|
||||
endSection = section;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 筛选入库
|
||||
*/
|
||||
private void backToParking(Simulation simulation) {
|
||||
for (TrainInfo trainInfo : simulation.getRepository().getTrainInfoMap().values()) {
|
||||
if (trainInfo.isInbound() && trainInfo.isParking()) {
|
||||
VirtualRealityTrain train = simulation.getRepository().getVRByCode(trainInfo.getGroupNumber(), VirtualRealityTrain.class);
|
||||
if (train.getHeadPosition().getSection().isTransferTrack()
|
||||
&& train.getTailPosition().getSection().isTransferTrack()) {
|
||||
if (simulation.getRepository().getDepotRunningInfoList().stream()
|
||||
.anyMatch(depotRunningInfo -> depotRunningInfo.getTrain().equals(train))) {
|
||||
continue;
|
||||
}
|
||||
train.initAsRM();
|
||||
Section startSection = train.getHeadPosition().getSection();
|
||||
Section endSection = null;
|
||||
for (Section section : simulation.getRepository().getParkingTracksMap().get(startSection.getStation())) {
|
||||
if (section.isOccupied()) {
|
||||
continue;
|
||||
}
|
||||
if (section.getLeftSection() == null || section.getRightSection() == null) {
|
||||
endSection = section;
|
||||
} else if (section.getLeftSection().isParkingTrack() && !section.getLeftSection().isOccupied()) {
|
||||
endSection = section.getLeftSection();
|
||||
} else if (section.getRightSection().isParkingTrack() && !section.getRightSection().isOccupied()) {
|
||||
endSection = section.getRightSection();
|
||||
} else {
|
||||
endSection = section;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
// train.setTarget(endSection);
|
||||
List<RoutePath> routePaths = simulation.getRepository().queryRoutePaths(startSection, endSection);
|
||||
if (routePaths == null || routePaths.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
RoutePath routePath = routePaths.get(0);
|
||||
DepotRunningInfo depotRunningInfo = new DepotRunningInfo(endSection, train, routePath, true);
|
||||
simulation.getRepository().getDepotRunningInfoList().add(depotRunningInfo);
|
||||
break;
|
||||
}
|
||||
}
|
||||
List<RoutePath> routePaths = simulation.getRepository()
|
||||
.queryRoutePaths(startSection, endSection);
|
||||
if (routePaths == null || routePaths.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
RoutePath routePath = routePaths.get(0);
|
||||
DepotRunningInfo depotRunningInfo = new DepotRunningInfo(endSection, train, routePath,
|
||||
true);
|
||||
simulation.getRepository().getDepotRunningInfoList().add(depotRunningInfo);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 列车排进路并运行
|
||||
*/
|
||||
private void settingRouteAndMoving(Simulation simulation) {
|
||||
for (DepotRunningInfo depotRunningInfo : simulation.getRepository().getDepotRunningInfoList()) {
|
||||
Section endSection = depotRunningInfo.getEndSection();
|
||||
SectionPosition position = new SectionPosition(endSection, endSection.getStopPointByDirection(depotRunningInfo.getRight()));
|
||||
depotRunningInfo.getTrain().setRobotTargetPosition(position);
|
||||
if (!depotRunningInfo.getRouteList().isEmpty()) {
|
||||
Route route = depotRunningInfo.getRouteList().get(0);
|
||||
if (route.isLock()) {
|
||||
depotRunningInfo.getRouteList().remove(0);
|
||||
}
|
||||
if (!route.isSetting()) {
|
||||
ciRouteService.setRoute(simulation, route,route.getAspect());
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 列车排进路并运行
|
||||
*/
|
||||
private void settingRouteAndMoving(Simulation simulation) {
|
||||
for (DepotRunningInfo depotRunningInfo : simulation.getRepository().getDepotRunningInfoList()) {
|
||||
Section endSection = depotRunningInfo.getEndSection();
|
||||
SectionPosition position = new SectionPosition(endSection,
|
||||
endSection.getStopPointByDirection(depotRunningInfo.getRight()));
|
||||
depotRunningInfo.getTrain().setRobotTargetPosition(position);
|
||||
if (!depotRunningInfo.getRouteList().isEmpty()) {
|
||||
Route route = depotRunningInfo.getRouteList().get(0);
|
||||
if (route.isLock()) {
|
||||
depotRunningInfo.getRouteList().remove(0);
|
||||
}
|
||||
if (!route.isSetting()) {
|
||||
ciRouteService.setRoute(simulation, route, route.getAspect(), false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断运行列车是否到达转换轨并升级
|
||||
*/
|
||||
private void arriveDestination(Simulation simulation) {
|
||||
for (Iterator<DepotRunningInfo> iterator = simulation.getRepository().getDepotRunningInfoList().iterator(); iterator.hasNext(); ) {
|
||||
DepotRunningInfo depotRunningInfo = iterator.next();
|
||||
VirtualRealityTrain train = depotRunningInfo.getTrain();
|
||||
if (depotRunningInfo.isArrival()) {
|
||||
// 到达
|
||||
iterator.remove();
|
||||
if (depotRunningInfo.in) {
|
||||
atpService.turnDirectionImmediately(train);
|
||||
} else {
|
||||
// 升级
|
||||
SimulationMember member = simulation.getSimulationMember(train, SimulationMember.Type.DRIVER);
|
||||
Map<String, Object> param = new HashMap<>();
|
||||
param.put("preselectionMode", VirtualRealityTrain.PreselectionMode.AM_C.name());
|
||||
param.put("groupNumber", train.getGroupNumber());
|
||||
atsOperationDispatcher.execute(simulation, member,
|
||||
Operation.Type.Change_Preselection_Mode.name(), param);
|
||||
/**
|
||||
* 判断运行列车是否到达转换轨并升级
|
||||
*/
|
||||
private void arriveDestination(Simulation simulation) {
|
||||
for (Iterator<DepotRunningInfo> iterator = simulation.getRepository().getDepotRunningInfoList()
|
||||
.iterator(); iterator.hasNext(); ) {
|
||||
DepotRunningInfo depotRunningInfo = iterator.next();
|
||||
VirtualRealityTrain train = depotRunningInfo.getTrain();
|
||||
if (depotRunningInfo.isArrival()) {
|
||||
// 到达
|
||||
iterator.remove();
|
||||
if (depotRunningInfo.in) {
|
||||
atpService.turnDirectionImmediately(train);
|
||||
} else {
|
||||
// 升级
|
||||
SimulationMember member = simulation.getSimulationMember(train,
|
||||
SimulationMember.Type.DRIVER);
|
||||
Map<String, Object> param = new HashMap<>();
|
||||
param.put("preselectionMode", VirtualRealityTrain.PreselectionMode.AM_C.name());
|
||||
param.put("groupNumber", train.getGroupNumber());
|
||||
atsOperationDispatcher.execute(simulation, member,
|
||||
Operation.Type.Change_Preselection_Mode.name(), param);
|
||||
// CommandInitiateVO commandInitiateVO = new CommandInitiateVO(CommandBO.CommandType.Change_Preselection_Mode,
|
||||
// member.getId(), param);
|
||||
// groupSimulationService.command(simulation, commandInitiateVO, member);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Getter
|
||||
public static class DepotRunningInfo {
|
||||
|
||||
private final List<Route> routeList = new ArrayList<>();
|
||||
|
||||
private final Section endSection;
|
||||
|
||||
private final VirtualRealityTrain train;
|
||||
|
||||
private final Boolean right;
|
||||
|
||||
private final Boolean in;
|
||||
|
||||
public DepotRunningInfo(Section endSection, VirtualRealityTrain train, RoutePath routePath,
|
||||
boolean in) {
|
||||
this.endSection = endSection;
|
||||
this.train = train;
|
||||
for (Signal signal : routePath.getSignalList()) {
|
||||
for (Route route : signal.getRouteList()) {
|
||||
if (routePath.getRouteList().contains(route)) {
|
||||
routeList.add(route);
|
||||
}
|
||||
}
|
||||
}
|
||||
this.right = routePath.isRight();
|
||||
this.in = in;
|
||||
}
|
||||
|
||||
@Getter
|
||||
public static class DepotRunningInfo {
|
||||
|
||||
private final List<Route> routeList = new ArrayList<>();
|
||||
|
||||
private final Section endSection;
|
||||
|
||||
private final VirtualRealityTrain train;
|
||||
|
||||
private final Boolean right;
|
||||
|
||||
private final Boolean in;
|
||||
|
||||
public DepotRunningInfo(Section endSection, VirtualRealityTrain train, RoutePath routePath, boolean in) {
|
||||
this.endSection = endSection;
|
||||
this.train = train;
|
||||
for (Signal signal : routePath.getSignalList()) {
|
||||
for (Route route : signal.getRouteList()) {
|
||||
if (routePath.getRouteList().contains(route)) {
|
||||
routeList.add(route);
|
||||
}
|
||||
}
|
||||
}
|
||||
this.right = routePath.isRight();
|
||||
this.in = in;
|
||||
}
|
||||
|
||||
// 列车是否到达终点
|
||||
public boolean isArrival() {
|
||||
return train.getSpeed() == 0 && train.getHeadPosition().getSection().equals(endSection)
|
||||
&& train.getTailPosition().getSection().equals(endSection);
|
||||
}
|
||||
// 列车是否到达终点
|
||||
public boolean isArrival() {
|
||||
return train.getSpeed() == 0 && train.getHeadPosition().getSection().equals(endSection)
|
||||
&& train.getTailPosition().getSection().equals(endSection);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue