From e646435e049309673a8b44f38066833e6c661fc8 Mon Sep 17 00:00:00 2001 From: tiger_zhou <123456> Date: Thu, 1 Sep 2022 13:57:43 +0800 Subject: [PATCH 1/9] =?UTF-8?q?=E8=BD=A6=E5=8A=A1=E7=AE=A1=E7=90=86?= =?UTF-8?q?=E7=BB=88=E7=AB=AF=E5=8A=9F=E8=83=BD=E4=BB=A3=E7=A0=81=E8=B0=83?= =?UTF-8?q?=E6=95=B4=E5=8F=8A=E8=AE=A1=E5=88=92=E6=94=AF=E6=8C=81=E8=82=A1?= =?UTF-8?q?=E9=81=93=EF=BC=8C=E5=87=BA=E5=85=A5=E5=8F=A3=E4=B8=8E=E7=AB=99?= =?UTF-8?q?=E7=BB=86=E4=B8=8D=E4=B8=80=E8=87=B4=E7=9A=84=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../BusinessExceptionAssertEnum.java | 2 +- .../cbtc/CTC/data/CascoControl.java | 9 + .../cbtc/CTC/data/CtcEffectRepository.java | 10 + .../cbtc/CTC/data/TrackSection.java | 11 +- .../fck/CtcManageIOGateOperateHandler.java | 2 +- .../cbtc/CTC/param/CtcRunPlanParam.java | 16 + .../cbtc/CTC/service/CTCService.java | 21 +- .../cbtc/CTC/service/CascoControlService.java | 289 +++++++++++++++--- .../CTC/service/runplan/CtcManageService.java | 46 ++- .../cbtc/build/SimulationBuilder.java | 63 +++- 10 files changed, 402 insertions(+), 67 deletions(-) diff --git a/src/main/java/club/joylink/rtss/exception/BusinessExceptionAssertEnum.java b/src/main/java/club/joylink/rtss/exception/BusinessExceptionAssertEnum.java index 4cfdfacc0..cdd11fe61 100644 --- a/src/main/java/club/joylink/rtss/exception/BusinessExceptionAssertEnum.java +++ b/src/main/java/club/joylink/rtss/exception/BusinessExceptionAssertEnum.java @@ -32,7 +32,7 @@ public enum BusinessExceptionAssertEnum implements BusinessExceptionAssert { OPERATION_REPEAT(10016, "operation repeat"), SIMULATION_EXCEPTION_FOR_SHOW(10017, ""), //错误信息用于展示给仿真用户 OPERATION_FAIL(10018, "操作失败"), - + STATION_DETAIL_NOT_FOUND_RD_PLAN_ITEM(10019,"站细卡控未找到对应的接发车计划"), DATA_ERROR(11000, "data error"), REPEAT_RUN_PLAN_FROM_CTC_UPDATE_DATA(11200,"repeat run plan"), diff --git a/src/main/java/club/joylink/rtss/simulation/cbtc/CTC/data/CascoControl.java b/src/main/java/club/joylink/rtss/simulation/cbtc/CTC/data/CascoControl.java index a9a3de98e..4dcc2f6aa 100644 --- a/src/main/java/club/joylink/rtss/simulation/cbtc/CTC/data/CascoControl.java +++ b/src/main/java/club/joylink/rtss/simulation/cbtc/CTC/data/CascoControl.java @@ -8,6 +8,7 @@ import lombok.NoArgsConstructor; import java.util.ArrayList; import java.util.List; +import java.util.Objects; @Data @NoArgsConstructor @@ -17,6 +18,14 @@ public class CascoControl { private Route route; private List errorList = new ArrayList<>(); private String tripNum; +// private boolean force; + public CascoControl(Simulation simulation, Station station, Route route, String tripNum/*,Boolean force*/) { + this.simulation = simulation; + this.station = station; + this.route = route; + this.tripNum = tripNum; +// this.force = Objects.isNull(force) ? false : force.booleanValue(); + } public void addErrorMsg(String msg){ this.errorList.add(msg); diff --git a/src/main/java/club/joylink/rtss/simulation/cbtc/CTC/data/CtcEffectRepository.java b/src/main/java/club/joylink/rtss/simulation/cbtc/CTC/data/CtcEffectRepository.java index a52f7e2fe..7cfec11c3 100644 --- a/src/main/java/club/joylink/rtss/simulation/cbtc/CTC/data/CtcEffectRepository.java +++ b/src/main/java/club/joylink/rtss/simulation/cbtc/CTC/data/CtcEffectRepository.java @@ -73,6 +73,14 @@ public class CtcEffectRepository { */ private final Map updateReguarTrainLineMap = new ConcurrentHashMap<>(); + /** + * 股道更新区域(从生效区来的数据) + */ + private final Map updateStationTrackSectionMap = new ConcurrentHashMap<>(); + /** + * 出入口更新区域(从生效区来的数据) + */ + private final Map updateDoorMap = new ConcurrentHashMap<>(); /** * 获取生效区的运行计划 * @@ -576,5 +584,7 @@ public class CtcEffectRepository { this.doorRepository.clear(); this.regularTrainLineMap.clear(); updateReguarTrainLineMap.clear(); + updateStationTrackSectionMap.clear(); + this.updateDoorMap.clear(); } } diff --git a/src/main/java/club/joylink/rtss/simulation/cbtc/CTC/data/TrackSection.java b/src/main/java/club/joylink/rtss/simulation/cbtc/CTC/data/TrackSection.java index fd46e4cea..02fcff98d 100644 --- a/src/main/java/club/joylink/rtss/simulation/cbtc/CTC/data/TrackSection.java +++ b/src/main/java/club/joylink/rtss/simulation/cbtc/CTC/data/TrackSection.java @@ -11,7 +11,7 @@ import lombok.Setter; @Setter @Getter @NoArgsConstructor -public class TrackSection { +public class TrackSection implements Cloneable { /** * 编码 */ @@ -122,4 +122,13 @@ public class TrackSection { public enum StandType { NO, LOW, HIGH } + + public TrackSection clone() { + try { + return (TrackSection) super.clone(); + } catch (CloneNotSupportedException e) { + e.printStackTrace(); + } + return null; + } } diff --git a/src/main/java/club/joylink/rtss/simulation/cbtc/CTC/operation/fck/CtcManageIOGateOperateHandler.java b/src/main/java/club/joylink/rtss/simulation/cbtc/CTC/operation/fck/CtcManageIOGateOperateHandler.java index 19ae2224b..bbc998abb 100644 --- a/src/main/java/club/joylink/rtss/simulation/cbtc/CTC/operation/fck/CtcManageIOGateOperateHandler.java +++ b/src/main/java/club/joylink/rtss/simulation/cbtc/CTC/operation/fck/CtcManageIOGateOperateHandler.java @@ -46,7 +46,7 @@ public class CtcManageIOGateOperateHandler { @OperateHandlerMapping(type = Operation.Type.STATION_IO_GATE_PUBLISH) public void publist(Simulation simulation, String stationCode){ - ctcManageService.publishData(simulation, CtcRepository.CtcFZKType.STATION_DETAIL,stationCode); + ctcManageService.publishData(simulation, CtcRepository.CtcFZKType.IO_GATE,stationCode); } } diff --git a/src/main/java/club/joylink/rtss/simulation/cbtc/CTC/param/CtcRunPlanParam.java b/src/main/java/club/joylink/rtss/simulation/cbtc/CTC/param/CtcRunPlanParam.java index 13eaac5fa..453792f3e 100644 --- a/src/main/java/club/joylink/rtss/simulation/cbtc/CTC/param/CtcRunPlanParam.java +++ b/src/main/java/club/joylink/rtss/simulation/cbtc/CTC/param/CtcRunPlanParam.java @@ -232,6 +232,7 @@ public class CtcRunPlanParam implements Cloneable { * 运行计划车次信息 * private String tripNumber; */ + this.tripNumber = tl.getArriveTipNum(); /** @@ -449,6 +450,21 @@ public class CtcRunPlanParam implements Cloneable { return p; } + +/* public boolean getTrackDiscordant(){ + if(Objects.isNull(trackDiscordant)){ + return false; + } + return this.trackDiscordant.booleanValue(); + } + + public boolean getEntryOutDiscordant(){ + if(Objects.isNull(entryOutDiscordant)){ + return false; + } + return this.entryOutDiscordant.booleanValue(); + }*/ + /** * 初始化车次信息 */ diff --git a/src/main/java/club/joylink/rtss/simulation/cbtc/CTC/service/CTCService.java b/src/main/java/club/joylink/rtss/simulation/cbtc/CTC/service/CTCService.java index 7e3960c50..38f5a9562 100644 --- a/src/main/java/club/joylink/rtss/simulation/cbtc/CTC/service/CTCService.java +++ b/src/main/java/club/joylink/rtss/simulation/cbtc/CTC/service/CTCService.java @@ -2,10 +2,7 @@ package club.joylink.rtss.simulation.cbtc.CTC.service; import club.joylink.rtss.exception.BusinessExceptionAssertEnum; import club.joylink.rtss.simulation.cbtc.CI.CiApiService; -import club.joylink.rtss.simulation.cbtc.CTC.data.CtcEffectRepository; -import club.joylink.rtss.simulation.cbtc.CTC.data.CtcRepository; -import club.joylink.rtss.simulation.cbtc.CTC.data.CtcStationRunPlanLog; -import club.joylink.rtss.simulation.cbtc.CTC.data.RouteSequence; +import club.joylink.rtss.simulation.cbtc.CTC.data.*; import club.joylink.rtss.simulation.cbtc.Simulation; import club.joylink.rtss.simulation.cbtc.data.map.*; import org.springframework.beans.factory.annotation.Autowired; @@ -13,6 +10,7 @@ import org.springframework.stereotype.Component; import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; +import javax.annotation.Resource; import java.time.LocalTime; import java.time.format.DateTimeFormatter; import java.util.*; @@ -23,7 +21,8 @@ import java.util.stream.Collectors; public class CTCService { @Autowired private CiApiService ciApiService; - + @Resource + private CascoControlService cascoControlService; /** * 创建了新的运行计划item */ @@ -161,7 +160,12 @@ public class CTCService { line.setAutoTrigger(trigger); } - + private List cascoControl(CascoControl cc,boolean force){ + if(Objects.equals(true,force)){ + return Collections.emptyList(); + } + return this.cascoControlService.checkCascoControlRoute(cc); + } /** * * @param simulation @@ -179,6 +183,11 @@ public class CTCService { List conflictInfo = new ArrayList<>(); CtcRepository ctcRepository = simulation.getCtcRepository(); + CascoControl cc = new CascoControl(simulation,station,route,tripNumber); + List errCCMsg = this.cascoControl(cc,Objects.isNull(force) ? false:force.booleanValue());//站细卡控 + if(Objects.equals(false,CollectionUtils.isEmpty(errCCMsg))){ + return errCCMsg; + } if (StringUtils.hasText(tripNumber) && !Objects.equals(true, force)) { //列车进路防错办 List lines = ctcRepository.findRouteSequenceLines(station.getCode(), tripNumber); if (!CollectionUtils.isEmpty(lines)) { diff --git a/src/main/java/club/joylink/rtss/simulation/cbtc/CTC/service/CascoControlService.java b/src/main/java/club/joylink/rtss/simulation/cbtc/CTC/service/CascoControlService.java index 884116f61..b3b590d06 100644 --- a/src/main/java/club/joylink/rtss/simulation/cbtc/CTC/service/CascoControlService.java +++ b/src/main/java/club/joylink/rtss/simulation/cbtc/CTC/service/CascoControlService.java @@ -1,20 +1,27 @@ package club.joylink.rtss.simulation.cbtc.CTC.service; -import club.joylink.rtss.simulation.cbtc.CTC.data.CascoControl; -import club.joylink.rtss.simulation.cbtc.CTC.data.CtcEffectRepository; -import club.joylink.rtss.simulation.cbtc.CTC.data.CtcRepository; -import club.joylink.rtss.simulation.cbtc.CTC.data.CtcStationRunPlanLog; +import club.joylink.rtss.exception.BusinessException; +import club.joylink.rtss.exception.BusinessExceptionAssertEnum; +import club.joylink.rtss.simulation.cbtc.CI.data.StationDirection; +import club.joylink.rtss.simulation.cbtc.CTC.data.*; import club.joylink.rtss.simulation.cbtc.Simulation; +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.Station; +import com.google.common.base.Strings; +import com.google.common.collect.Lists; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.apache.ibatis.annotations.Case; import org.springframework.stereotype.Service; +import org.springframework.util.CollectionUtils; +import org.springframework.util.StringUtils; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Optional; -import java.util.function.Function; -import java.util.stream.Collectors; +import java.util.*; + +import static club.joylink.rtss.simulation.cbtc.CTC.data.TrackSection.DirectionType; @Service @Slf4j @@ -29,59 +36,249 @@ public class CascoControlService { Station station = cc.getStation(); Simulation simulation = cc.getSimulation(); String stationCode = station.getCode(); + CtcRepository ctcRepository = simulation.getCtcRepository(); CtcEffectRepository effectRepository = ctcRepository.getCtcEffectRepository(); - Map runPlanLogMap = simulation.getCtcRepository().getSimulationRunPlanMap().get(stationCode); - Optional runPlanLogOptional = null; - if(Objects.nonNull(runPlanLogMap) && !runPlanLogMap.isEmpty()){ - runPlanLogOptional = this.checkForRunPlan(cc); + List errMsgList = cc.getErrorList(); + boolean isDepart = cc.getRoute().getType() == Route.Type.DEPARTURE; + CtcStationRunPlanLog runPlanLog; + try{ + //在TDCS界面创建进路如果车次号没有在计划中就直接返回,先按照之前的逻辑运行 + runPlanLog = this.checkForRunPlan(cc); + }catch (BusinessException e){ + log.error("站明检测失败 msg:" + e.getMessage(),e); + log.error(e.getMessage() + " errorCode:[{}]",e.getCode()); + return Collections.emptyList(); } -// List allRunPlanLogList = runPlanLogMap.values().stream().filter(d->d.getChangeType() == null && d.isSign()).collect(Collectors.toList()); + CtcStationRunPlanLog.RunPlanItem runPlan = this.findRunPlanFromPlan(isDepart,runPlanLog,errMsgList); + if(Objects.isNull(runPlan)){ + String depart = this.departToChar(isDepart); + String msg = String.format("未找到行车计划的接发车计划 车站[%s] 车次[%s] [%s]", runPlanLog.getStation().getCode(), runPlanLog.getTripNumber(),depart); + log.error(msg); + errMsgList.add(msg); + return errMsgList; + } + CtcEffectRepository.StationDoorRepository doorRepository = effectRepository.getUpdateDoorMap().get(stationCode); + CtcEffectRepository.StationTrackSectionRepository stationTrackRepository = effectRepository.getUpdateStationTrackSectionMap().get(stationCode); + CtcEffectRepository.RegularTrainLineRepository regularTrainLineRepository = effectRepository.getUpdateReguarTrainLineMap().get(stationCode); - CtcEffectRepository.StationDoorRepository doorRepository = effectRepository.getDoorRepository().get(stationCode); - if(Objects.nonNull(doorRepository)){ - if(runPlanLogOptional.isPresent()){ - - } - return cc.getErrorList(); + if(Objects.isNull(doorRepository)){ + String msg = String.format("未找到对应的出入口站细数据,车站[%s]",stationCode); + log.error(msg); + return Lists.newArrayList(msg); + } + if(Objects.isNull(stationTrackRepository)){ + String msg = String.format("未找到对应的股道站细数据,车站[%s]",stationCode); + log.error(msg); + return Lists.newArrayList(msg); } - - CtcEffectRepository.StationTrackSectionRepository stationTrackRepository = effectRepository.getStationTrackSectionMap().get(stationCode); - if(Objects.nonNull(stationTrackRepository)){ - - } - return null; + this.checkRegularTrainLine(isDepart,runPlan,regularTrainLineRepository,runPlanLog,errMsgList); + this.doorCheckDetail(isDepart,runPlan,doorRepository,runPlanLog,errMsgList); + this.checkStationTrackDetail(isDepart,runPlan,stationTrackRepository,runPlanLog,errMsgList); + return errMsgList; } - private Optional checkForRunPlan(/*List allRunPlanLogList,*/CascoControl cc){ - CtcStationRunPlanLog runPlanLog = cc.getSimulation().getCtcRepository().getRunPlan(cc.getStation().getCode(),cc.getTripNum()); - if(Objects.isNull(runPlanLog)){ - cc.addErrorMsg(String.format("未在计划中找到对应的车次[%s]",cc.getTripNum())); + private boolean trackAndDoor(Boolean d){ + return Objects.isNull(d) ? false: d.booleanValue(); + } + + /** + * 根据接发车获取行车计划的接发车计划 + * @param isDepart + * @param runPlanLog + * @param errMsgList + * @return + */ + private CtcStationRunPlanLog.RunPlanItem findRunPlanFromPlan(boolean isDepart,CtcStationRunPlanLog runPlanLog,List errMsgList){ + CtcStationRunPlanLog.RunPlanItem runPlan = runPlanLog.getArriveRunPlan(); + if(isDepart){ + runPlan = runPlanLog.getDepartRunPlan(); } - if(!Objects.isNull(runPlanLog.getChangeType()) && !runPlanLog.isSign()){ - cc.addErrorMsg(String.format("未在计划中找到对应的车次[%s]",cc.getTripNum())); - } - return Optional.of(runPlanLog); - /*Map tripNumMap = allRunPlanLogList.stream().collect(Collectors.toMap(CtcStationRunPlanLog::getTripNumber, Function.identity(),(v1,v2)->v1)); - CtcStationRunPlanLog runPlanLog = tripNumMap.get(cc.getTripNum()); - if(Objects.isNull(runPlanLog)){ - cc.addErrorMsg(String.format("未在计划中找到对应的车次[%s]",cc.getTripNum())); + /*if(Objects.isNull(runPlan)){ + String msg = String.format("未找到行车计划的接发车计划 车站[%s] 车次[%s] [%s]", runPlanLog.getStation().getCode(), runPlanLog.getTripNumber(),depart); + log.error(msg); + errMsgList.add(msg); + BusinessExceptionAssertEnum.STATION_DETAIL_NOT_FOUND_RD_PLAN_ITEM.assertNotNull(runPlan,msg); }*/ + return runPlan; } - private void checkCascoForStationTrack(CtcEffectRepository.StationTrackSectionRepository stationTrackRepository){ - + /** + * 根据车辆计划(接发车,车次)查找对应更新区的车辆固定径路数据 + * @param isDepart + * @param regularTrainLineRepository + * @param runPlanLog + * @param errMsg + */ + private void checkRegularTrainLine(boolean isDepart,CtcStationRunPlanLog.RunPlanItem runPlan,CtcEffectRepository.RegularTrainLineRepository regularTrainLineRepository,CtcStationRunPlanLog runPlanLog,List errMsg){ + if(Objects.isNull(regularTrainLineRepository) || Objects.equals(true,CollectionUtils.isEmpty(errMsg))){ + log.error(""); + return; + } + final String tripNum = runPlan.getTripNumber(); + RegularTrainLine rtl = regularTrainLineRepository.getDataMap().values().stream().filter(d->{ + String tmpNum = d.getArriveTipNum(); + if(isDepart){ + tmpNum = d.getLeaveTipNum(); + } + return Objects.equals(tripNum,tmpNum); + }).findFirst().orElse(null); + if(Objects.isNull(rtl)){ + return; + } + StationDirection sd = rtl.getEnter(); + if(isDepart){ + sd = rtl.getOut(); + } + if(Objects.equals(false,trackAndDoor(runPlanLog.getTrackDiscordant())) && !Objects.equals(runPlan.getTrackSection().getCode(),rtl.getMasterStand().getCode())){ + //股道不一致检测 + errMsg.add("股道固定径路不一致"); + } + if(Objects.equals(false,trackAndDoor(runPlanLog.getEntryOutDiscordant())) && !Objects.equals(runPlan.getStationDirection().getCode(),sd.getCode())){ + //出入口不一致检测 + errMsg.add("出入口固定径路不一致"); + } } - private void checkCascoForDoor(CtcEffectRepository.StationDoorRepository doorRepository,CtcStationRunPlanLog runPlanLog){ - CtcStationRunPlanLog.RunPlanItem departPlan = runPlanLog.getDepartRunPlan(); - CtcStationRunPlanLog.RunPlanItem arrivePlan = runPlanLog.getArriveRunPlan(); - if(Objects.nonNull(departPlan)){ + /** + * 获取对应的执行计划 + * @param cc + * @return + */ + private CtcStationRunPlanLog checkForRunPlan(CascoControl cc){ + String stationCode = cc.getStation().getCode(); + String tripNum = cc.getTripNum(); + CtcStationRunPlanLog runPlanLog = cc.getSimulation().getCtcRepository().getRunPlan(stationCode,tripNum); + return runPlanLog; + } + /** + * 检测接发计划与股道接发车方向是否一致 + * @param isDepart + * @param stationTrackRepository + * @param runPlanLog + * @param errMsg + */ + private void checkStationTrackDetail(boolean isDepart,CtcStationRunPlanLog.RunPlanItem runPlan,CtcEffectRepository.StationTrackSectionRepository stationTrackRepository,CtcStationRunPlanLog runPlanLog,List errMsg){ + if(!CollectionUtils.isEmpty(errMsg)){ + return; + } + String departChar = this.departToChar(isDepart); + Section masterSection = runPlan.getTrackSection(); + TrackSection ts = stationTrackRepository.getDataMap().get(masterSection.getCode()); + if(Objects.isNull(ts)){ + String d = String.format("未找到对应的股道[%s],车站[%s],车号[%s],股道[%s]",departChar,runPlanLog.getStation().getCode(),runPlanLog.getTripNumber(),masterSection.getCode()); + log.error(d); + errMsg.add(d); + return; } - if(Objects.nonNull(arrivePlan)){ + checkStationTrackForTransfinite(ts,runPlanLog,errMsg,departChar); + checkStationTrackForTrainType(ts,runPlanLog,errMsg); + } + + /** + * 行车计划股道超限检测 + * @param ts + * @param runPlanLog + * @param errMsg + * @param departChar + */ + private void checkStationTrackForTransfinite(TrackSection ts,CtcStationRunPlanLog runPlanLog,List errMsg,String departChar){ + if(Objects.isNull(runPlanLog.getTransfinite())){ + return; } + CtcStationRunPlanLog.TransfiniteType sTT = ts.getTransfinite(); + //大于一级超限 + boolean transfiniteThanMoreOne =(runPlanLog.getTransfinite() == CtcStationRunPlanLog.TransfiniteType.TRANSFINITE_TWO_LEVEL || + runPlanLog.getTransfinite() == CtcStationRunPlanLog.TransfiniteType.TRANSFINITE_SUPER); + //大于二级超限 + boolean trainfiniteThanMoreTwo = runPlanLog.getTransfinite() == CtcStationRunPlanLog.TransfiniteType.TRANSFINITE_SUPER; + String d = null; + if(sTT == CtcStationRunPlanLog.TransfiniteType.NO && runPlanLog.getTransfinite() != CtcStationRunPlanLog.TransfiniteType.NO){ + //股道不能超限,但是计划超限 + d = String.format("股道[%s],车站[%s],车次[%s],[%s],不支持超限,但行车计划超限[%s]",ts.getCode(),runPlanLog.getStation().getCode(),runPlanLog.getTripNumber(),departChar,runPlanLog.getTransfinite()); + }else if(sTT == CtcStationRunPlanLog.TransfiniteType.TRANSFINITE_ONE_LEVEL && transfiniteThanMoreOne){ + //股道是一级超限,但是计划是二级或是超级 + d = String.format("股道[%s],车站[%s],车次[%s],[%s],一级超限,但行车计划超限[%s]",ts.getCode(),runPlanLog.getStation().getCode(),runPlanLog.getTripNumber(),departChar,runPlanLog.getTransfinite()); + }else if(sTT == CtcStationRunPlanLog.TransfiniteType.TRANSFINITE_TWO_LEVEL && trainfiniteThanMoreTwo){ + //股道是二级超限,但是计划是超级 + d = String.format("股道[%s],车站[%s],车次[%s],[%s],二级超限,但行车计划超限[%s]",ts.getCode(),runPlanLog.getStation().getCode(),runPlanLog.getTripNumber(),departChar,runPlanLog.getTransfinite()); + } + if(Objects.equals(false,Strings.isNullOrEmpty(d))){ + log.error(d); + errMsg.add(d); + } + } + + /** + * 行车计划股道列车类型检测 + * @param ts + * @param runPlanLog + * @param errMsg + */ + private void checkStationTrackForTrainType(TrackSection ts,CtcStationRunPlanLog runPlanLog,List errMsg){ + boolean trainTypeMatch = false; + TrackSection.TrainType tt = ts.getTrainType(); + switch (tt){ + case PASSENGER: + trainTypeMatch = Objects.equals(false,runPlanLog.isPassengerTrain()); + break; + case GOODS_VAN: + trainTypeMatch = Objects.equals(true,runPlanLog.isPassengerTrain()); + break; + default: + break; + } + if(trainTypeMatch){ + String d = String.format("计划列车类型与股道类型不匹配,股道[%s] 股道区段[%s] 设置列车类型[%s],列车类型[%s]",ts.getCode(),ts.getSectionCode(),tt,runPlanLog.isPassengerTrain()?"客":"货"); + errMsg.add(d); + } + } + + /** + * 计划与出入口检测明细 + * @param isDepart 是否是发车计划 + * @param doorRepository + * @param runPlanLog + */ + private void doorCheckDetail(boolean isDepart,CtcStationRunPlanLog.RunPlanItem runPlan,CtcEffectRepository.StationDoorRepository doorRepository,CtcStationRunPlanLog runPlanLog,List errMsgList){ + if(!CollectionUtils.isEmpty(errMsgList)){ + return; + } + String depart = this.departToChar(isDepart); + StationDirection sd = runPlan.getStationDirection(); + StationDirection doorDir = doorRepository.getDataMap().get(sd.getCode()); + if(Objects.isNull(doorDir)){ + errMsgList.add(String.format("根据计划方向[%s] 没有找到出入口[%s]数据,车站[%s],车次[%s]" + ,depart,sd.getCode(),runPlanLog.getStation().getCode(),runPlanLog.getTripNumber())); + } + + boolean isTransfinite = Objects.nonNull(runPlanLog.getTransfinite()) && runPlanLog.getTransfinite() != CtcStationRunPlanLog.TransfiniteType.NO; + + if(!doorDir.isAllowOverrun() && isTransfinite){ + // 出入口不能超限,但是计划超限 + errMsgList.add(String.format("出入口[%s],[%s]不允许超限,但是计划超限,车站[%s],车次[%s]" + ,sd.getCode(),depart,runPlanLog.getStation().getCode(),runPlanLog.getTripNumber())); + return; + } + if(!doorDir.isTravelTrain() && Objects.equals(true,runPlanLog.isPassengerTrain())){ + //出入口不支持客车,但是计划是客车 + errMsgList.add(String.format("出入口[%s],[%s]不允许客车,车站[%s],车次[%s]" + ,sd.getCode(),depart,runPlanLog.getStation().getCode(),runPlanLog.getTripNumber())); + return; + } + + if(!doorDir.isGoodsTrain() && Objects.equals(false,runPlanLog.isPassengerTrain())){ + //出入口不支持货车,但是计划是货车 + errMsgList.add(String.format("出入口[%s],[%s]不允许货车,车站[%s],车次[%s]" + ,sd.getCode(),depart,runPlanLog.getStation().getCode(),runPlanLog.getTripNumber())); + return; + } + } + + private String departToChar(boolean isDepart){ + return isDepart ? "发":"接"; } } diff --git a/src/main/java/club/joylink/rtss/simulation/cbtc/CTC/service/runplan/CtcManageService.java b/src/main/java/club/joylink/rtss/simulation/cbtc/CTC/service/runplan/CtcManageService.java index 38b4c3c01..45d412a64 100644 --- a/src/main/java/club/joylink/rtss/simulation/cbtc/CTC/service/runplan/CtcManageService.java +++ b/src/main/java/club/joylink/rtss/simulation/cbtc/CTC/service/runplan/CtcManageService.java @@ -418,19 +418,53 @@ public class CtcManageService { */ public void stationUpdateFromEffect(Simulation simulation, String stationCode){ BusinessExceptionAssertEnum.DATA_ERROR.assertNotTrue(Objects.isNull(stationCode), String.format("车站号不能为空")); - CtcEffectRepository effectRepository = simulation.getCtcRepository().getCtcEffectRepository(); - CtcEffectRepository.RegularTrainLineRepository regularTrainLineRepository = effectRepository.getRegularTrainLineMap().get(stationCode); + CtcEffectRepository repository = simulation.getCtcRepository().getCtcEffectRepository(); + CtcEffectRepository.RegularTrainLineRepository regularTrainLineRepository = repository.getRegularTrainLineMap().get(stationCode); boolean isEmptyData = Objects.isNull(regularTrainLineRepository) || regularTrainLineRepository.getDataMap().isEmpty(); - BusinessExceptionAssertEnum.DATA_ERROR.assertNotTrue(isEmptyData, String.format("当前生效区没有数据,无法更新")); +// BusinessExceptionAssertEnum.DATA_ERROR.assertNotTrue(isEmptyData, String.format("当前生效区没有数据,无法更新")); + CtcEffectRepository.StationTrackSectionRepository sourceStationTrack = repository.getStationTrackSectionMap().get(stationCode); + CtcEffectRepository.StationDoorRepository sourceDoor = repository.getDoorRepository().get(stationCode); + if(Objects.nonNull(sourceStationTrack)){ + CtcEffectRepository.StationTrackSectionRepository stationTrack = repository.getUpdateStationTrackSectionMap().get(stationCode); + if(Objects.isNull(stationTrack)){ + stationTrack = new CtcEffectRepository.StationTrackSectionRepository(); + repository.getUpdateStationTrackSectionMap().put(stationCode,stationTrack); + } + if(stationTrack.version() != sourceStationTrack.version()){ + stationTrack.resetVersion(sourceStationTrack.version()); + for (TrackSection value : sourceStationTrack.getDataMap().values()) { + stationTrack.save(value.clone()); + } + } + + } + if(Objects.nonNull(sourceDoor)){ + CtcEffectRepository.StationDoorRepository door = repository.getUpdateDoorMap().get(stationCode); + if(Objects.isNull(door)){ + door = new CtcEffectRepository.StationDoorRepository(); + repository.getUpdateDoorMap().put(stationCode,door); + } + if(door.version() != sourceDoor.version()){ + door.resetVersion(sourceDoor.version()); + for (StationDirection d : sourceDoor.getDataMap().values()) { + door.save(d.clone()); + } + } + + } + if(Objects.equals(true,isEmptyData)){ + return; + } CtcEffectRepository.RegularTrainLineRepository updateRepository = simulation.getCtcRepository().getCtcEffectRepository().getUpdateReguarTrainLineMap().get(stationCode); if(Objects.isNull(updateRepository)){ updateRepository = new CtcEffectRepository.RegularTrainLineRepository(); simulation.getCtcRepository().getCtcEffectRepository().getUpdateReguarTrainLineMap().put(stationCode,updateRepository); } + if(updateRepository.version() != regularTrainLineRepository.version()){ updateRepository.resetVersion(regularTrainLineRepository.version()); for (RegularTrainLine val : regularTrainLineRepository.getDataMap().values()) { - updateRepository.save(val); + updateRepository.save(val.clone()); } }else{ BusinessExceptionAssertEnum.DATA_ERROR.assertNotTrue(true, String.format("当前生效区与更新区的版本一致,无法更新")); @@ -446,8 +480,12 @@ public class CtcManageService { public FZkVO> loadUpdateRegularTrainLineList(Simulation simulation, String stationCode){ BusinessExceptionAssertEnum.SYSTEM_EXCEPTION.assertNotTrue(Objects.isNull(stationCode), String.format("车站号不能为空")); CtcEffectRepository repository = simulation.getCtcRepository().getCtcEffectRepository(); + CtcEffectRepository.RegularTrainLineRepository tLRepository = repository.getUpdateReguarTrainLineMap().get(stationCode); + + + List list = this.loadRegularTrainLineData(tLRepository); return FZkVO.of(CollectionUtils.isEmpty(list)?0:tLRepository.version(),list); } diff --git a/src/main/java/club/joylink/rtss/simulation/cbtc/build/SimulationBuilder.java b/src/main/java/club/joylink/rtss/simulation/cbtc/build/SimulationBuilder.java index eb34db8eb..8ac858ea5 100644 --- a/src/main/java/club/joylink/rtss/simulation/cbtc/build/SimulationBuilder.java +++ b/src/main/java/club/joylink/rtss/simulation/cbtc/build/SimulationBuilder.java @@ -3,6 +3,7 @@ package club.joylink.rtss.simulation.cbtc.build; import club.joylink.rtss.entity.Ibp; import club.joylink.rtss.simulation.cbtc.CI.data.StationDirection; import club.joylink.rtss.simulation.cbtc.CTC.data.*; + import club.joylink.rtss.simulation.cbtc.Simulation; import club.joylink.rtss.simulation.cbtc.data.CalculateService; import club.joylink.rtss.simulation.cbtc.data.SimulationDataRepository; @@ -349,36 +350,82 @@ public class SimulationBuilder { Map stationTrackRepositoryMap = ctcRepository.getCtcManageRepository().getTrackSectionRepository(); Map doorRepository = ctcRepository.getCtcManageRepository().getDoorRepository(); + Map effectStationTrackMap = ctcRepository.getCtcEffectRepository().getStationTrackSectionMap(); + Map effectDoorMap = ctcRepository.getCtcEffectRepository().getDoorRepository(); + + + Map updateStationTrackMap = ctcRepository.getCtcEffectRepository().getUpdateStationTrackSectionMap(); + Map updateDoorMap = ctcRepository.getCtcEffectRepository().getUpdateDoorMap(); + for (Station station : stationList) { String stationCode = station.getCode(); CtcEffectRepository.StationTrackSectionRepository rep = stationTrackRepositoryMap.get(stationCode); CtcEffectRepository.StationDoorRepository doorRep = doorRepository.get(stationCode); if(rep == null){ rep = new CtcEffectRepository.StationTrackSectionRepository(); + rep.incrementVersionOne(); stationTrackRepositoryMap.put(stationCode,rep); } if(doorRep == null){ doorRep = new CtcEffectRepository.StationDoorRepository(); + doorRep.incrementVersionOne(); doorRepository.put(stationCode,doorRep); } for (StationDirection sd : station.getStationDirectionMap().values()) { -// StationIOGate ioGate = new StationIOGate(); -// ioGate.setCode(sd.getCode()); -// ioGate.setIoName(sd.getName()); -// ioGate.setDirection(sd.getLabelEnum()); - doorRep.save(sd.clone()); } for (Stand stand : station.getAllStandList()) { TrackSection ts = new TrackSection(stand.getSection()); - rep.save(ts); } } - - + //复制编辑区的股道,出入口到生效,编辑区 + copyEditToTargetForStationTrack(stationTrackRepositoryMap,effectStationTrackMap); + copyEditToTargetForStationTrack(stationTrackRepositoryMap,updateStationTrackMap); + copyEditToTargetForDoor(doorRepository,effectDoorMap); + copyEditToTargetForDoor(doorRepository,updateDoorMap); } + private static void copyEditToTargetForStationTrack(Map source, Map target){ + for (Map.Entry entry : source.entrySet()) { + String stationCode = entry.getKey(); + CtcEffectRepository.StationTrackSectionRepository val = entry.getValue(); + CtcEffectRepository.StationTrackSectionRepository targetRepository = target.get(stationCode); + if(Objects.isNull(targetRepository)){ + targetRepository = new CtcEffectRepository.StationTrackSectionRepository(); + targetRepository.resetVersion(val.version()); + target.put(stationCode,targetRepository); + } + for (Map.Entry valEntry : val.getDataMap().entrySet()) { + String code = valEntry.getKey(); + TrackSection vals = valEntry.getValue(); + targetRepository.getDataMap().put(code,vals); + } + + } + } + private static void copyEditToTargetForDoor(Map source, Map target){ + for (Map.Entry entry : source.entrySet()) { + String stationCode = entry.getKey(); + CtcEffectRepository.StationDoorRepository val = entry.getValue(); + CtcEffectRepository.StationDoorRepository targetRepository = target.get(stationCode); + if(Objects.isNull(targetRepository)){ + targetRepository = new CtcEffectRepository.StationDoorRepository(); + targetRepository.resetVersion(val.version()); + target.put(stationCode,targetRepository); + } + for (Map.Entry valEntry : val.getDataMap().entrySet()) { + String code = valEntry.getKey(); + StationDirection vals = valEntry.getValue(); + targetRepository.getDataMap().put(code,vals); + } + + } + } + + + + public static List checkRunPlanAndBuildLostRoutePaths(Map> serverTripMap, Map> routePathMap) { Map errMsgMap = new HashMap<>(); From efb101d281e3b93410925e60df7f97db5f2fa62d Mon Sep 17 00:00:00 2001 From: tiger_zhou <123456> Date: Thu, 1 Sep 2022 17:31:38 +0800 Subject: [PATCH 2/9] =?UTF-8?q?=E8=BD=A6=E5=8A=A1=E7=AE=A1=E7=90=86?= =?UTF-8?q?=E7=BB=88=E7=AB=AF=E5=8A=9F=E8=83=BD=E4=BB=A3=E7=A0=81=E8=B0=83?= =?UTF-8?q?=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cbtc/CTC/service/CTCService.java | 1 + .../cbtc/CTC/service/CascoControlService.java | 204 +++++++++++------- .../cbtc/build/SimulationBuilder.java | 3 +- 3 files changed, 129 insertions(+), 79 deletions(-) diff --git a/src/main/java/club/joylink/rtss/simulation/cbtc/CTC/service/CTCService.java b/src/main/java/club/joylink/rtss/simulation/cbtc/CTC/service/CTCService.java index 38f5a9562..ecf0602a0 100644 --- a/src/main/java/club/joylink/rtss/simulation/cbtc/CTC/service/CTCService.java +++ b/src/main/java/club/joylink/rtss/simulation/cbtc/CTC/service/CTCService.java @@ -186,6 +186,7 @@ public class CTCService { CascoControl cc = new CascoControl(simulation,station,route,tripNumber); List errCCMsg = this.cascoControl(cc,Objects.isNull(force) ? false:force.booleanValue());//站细卡控 if(Objects.equals(false,CollectionUtils.isEmpty(errCCMsg))){ + //站细检测错误的信息 return errCCMsg; } if (StringUtils.hasText(tripNumber) && !Objects.equals(true, force)) { //列车进路防错办 diff --git a/src/main/java/club/joylink/rtss/simulation/cbtc/CTC/service/CascoControlService.java b/src/main/java/club/joylink/rtss/simulation/cbtc/CTC/service/CascoControlService.java index b3b590d06..a76e36a90 100644 --- a/src/main/java/club/joylink/rtss/simulation/cbtc/CTC/service/CascoControlService.java +++ b/src/main/java/club/joylink/rtss/simulation/cbtc/CTC/service/CascoControlService.java @@ -33,30 +33,50 @@ public class CascoControlService { * @return */ public List checkCascoControlRoute(CascoControl cc){ - Station station = cc.getStation(); Simulation simulation = cc.getSimulation(); - String stationCode = station.getCode(); + CheckData checkData = this.findCheckData(cc,simulation.getCtcRepository().getCtcEffectRepository()); + if(checkData.isJustReturn()){ + //说明没有行车计划需要立刻返回 + return Collections.emptyList(); + } + if(Objects.equals(false,StringUtils.isEmpty(cc.getErrorList()))){ + return cc.getErrorList(); + } + this.checkRegularTrainLine(checkData,cc.getErrorList()); + this.doorCheckDetail(checkData,cc.getErrorList()); + this.checkStationTrackDetail(checkData,cc.getErrorList()); + return cc.getErrorList(); + } - CtcRepository ctcRepository = simulation.getCtcRepository(); - CtcEffectRepository effectRepository = ctcRepository.getCtcEffectRepository(); - List errMsgList = cc.getErrorList(); + + /** + * 获取检测固定径路,出入口,股道必要的参数数据 + * @param cc + * @param effectRepository + * @return + */ + private CheckData findCheckData(CascoControl cc,CtcEffectRepository effectRepository){ + String stationCode = cc.getStation().getCode(); + CheckData data = new CheckData(); boolean isDepart = cc.getRoute().getType() == Route.Type.DEPARTURE; + data.setDepart(isDepart); CtcStationRunPlanLog runPlanLog; try{ //在TDCS界面创建进路如果车次号没有在计划中就直接返回,先按照之前的逻辑运行 runPlanLog = this.checkForRunPlan(cc); }catch (BusinessException e){ - log.error("站明检测失败 msg:" + e.getMessage(),e); log.error(e.getMessage() + " errorCode:[{}]",e.getCode()); - return Collections.emptyList(); + data.setJustReturn(true); + return data; } - CtcStationRunPlanLog.RunPlanItem runPlan = this.findRunPlanFromPlan(isDepart,runPlanLog,errMsgList); + + CtcStationRunPlanLog.RunPlanItem runPlan = this.findRunPlanFromPlan(isDepart,runPlanLog); if(Objects.isNull(runPlan)){ - String depart = this.departToChar(isDepart); + String depart = data.departToChar(); String msg = String.format("未找到行车计划的接发车计划 车站[%s] 车次[%s] [%s]", runPlanLog.getStation().getCode(), runPlanLog.getTripNumber(),depart); log.error(msg); - errMsgList.add(msg); - return errMsgList; + cc.addErrorMsg(msg); + return data; } CtcEffectRepository.StationDoorRepository doorRepository = effectRepository.getUpdateDoorMap().get(stationCode); CtcEffectRepository.StationTrackSectionRepository stationTrackRepository = effectRepository.getUpdateStationTrackSectionMap().get(stationCode); @@ -65,20 +85,22 @@ public class CascoControlService { if(Objects.isNull(doorRepository)){ String msg = String.format("未找到对应的出入口站细数据,车站[%s]",stationCode); log.error(msg); - return Lists.newArrayList(msg); + cc.addErrorMsg(msg); + return data; } if(Objects.isNull(stationTrackRepository)){ String msg = String.format("未找到对应的股道站细数据,车站[%s]",stationCode); log.error(msg); - return Lists.newArrayList(msg); + cc.addErrorMsg(msg); + return data; } - - this.checkRegularTrainLine(isDepart,runPlan,regularTrainLineRepository,runPlanLog,errMsgList); - this.doorCheckDetail(isDepart,runPlan,doorRepository,runPlanLog,errMsgList); - this.checkStationTrackDetail(isDepart,runPlan,stationTrackRepository,runPlanLog,errMsgList); - return errMsgList; + data.setRunPlanLog(runPlanLog); + data.setRunPlan(runPlan); + data.setStationTrackRepository(stationTrackRepository); + data.setDoorRepository(doorRepository); + data.setRegularTrainLineRepository(regularTrainLineRepository); + return data; } - private boolean trackAndDoor(Boolean d){ return Objects.isNull(d) ? false: d.booleanValue(); } @@ -87,56 +109,59 @@ public class CascoControlService { * 根据接发车获取行车计划的接发车计划 * @param isDepart * @param runPlanLog - * @param errMsgList * @return */ - private CtcStationRunPlanLog.RunPlanItem findRunPlanFromPlan(boolean isDepart,CtcStationRunPlanLog runPlanLog,List errMsgList){ + private CtcStationRunPlanLog.RunPlanItem findRunPlanFromPlan(boolean isDepart,CtcStationRunPlanLog runPlanLog){ CtcStationRunPlanLog.RunPlanItem runPlan = runPlanLog.getArriveRunPlan(); if(isDepart){ runPlan = runPlanLog.getDepartRunPlan(); } - /*if(Objects.isNull(runPlan)){ - String msg = String.format("未找到行车计划的接发车计划 车站[%s] 车次[%s] [%s]", runPlanLog.getStation().getCode(), runPlanLog.getTripNumber(),depart); - log.error(msg); - errMsgList.add(msg); - BusinessExceptionAssertEnum.STATION_DETAIL_NOT_FOUND_RD_PLAN_ITEM.assertNotNull(runPlan,msg); - }*/ return runPlan; } + /** * 根据车辆计划(接发车,车次)查找对应更新区的车辆固定径路数据 - * @param isDepart - * @param regularTrainLineRepository - * @param runPlanLog + * @param checkData * @param errMsg */ - private void checkRegularTrainLine(boolean isDepart,CtcStationRunPlanLog.RunPlanItem runPlan,CtcEffectRepository.RegularTrainLineRepository regularTrainLineRepository,CtcStationRunPlanLog runPlanLog,List errMsg){ + private void checkRegularTrainLine(CheckData checkData,List errMsg){ + CtcEffectRepository.RegularTrainLineRepository regularTrainLineRepository = checkData.getRegularTrainLineRepository(); if(Objects.isNull(regularTrainLineRepository) || Objects.equals(true,CollectionUtils.isEmpty(errMsg))){ - log.error(""); + log.error("未找到固定径路的数据车站[{}],车次[{}],方向[{}]",checkData.getRunPlanLog().getStation().getCode(),checkData.getRunPlan().getTripNumber(),checkData.departToChar()); return; } - final String tripNum = runPlan.getTripNumber(); + //根据接发车获取对应的列车固定径路的数据 + final String tripNum = checkData.runPlan.getTripNumber(); RegularTrainLine rtl = regularTrainLineRepository.getDataMap().values().stream().filter(d->{ String tmpNum = d.getArriveTipNum(); - if(isDepart){ + if(checkData.isDepart()){ tmpNum = d.getLeaveTipNum(); } return Objects.equals(tripNum,tmpNum); }).findFirst().orElse(null); if(Objects.isNull(rtl)){ + log.error("未找到列车的固定径路 车站[{}],对应车次[{}],方向[{}]",checkData.runPlan.getStation().getCode(),tripNum,checkData.departToChar()); return; } StationDirection sd = rtl.getEnter(); - if(isDepart){ + if(checkData.isDepart()){ sd = rtl.getOut(); } - if(Objects.equals(false,trackAndDoor(runPlanLog.getTrackDiscordant())) && !Objects.equals(runPlan.getTrackSection().getCode(),rtl.getMasterStand().getCode())){ + boolean trackSectionEQ = Objects.equals(checkData.runPlan.getTrackSection().getCode(),rtl.getMasterStand().getCode()); + boolean doorEQ = Objects.equals(checkData.runPlan.getStationDirection().getCode(),sd.getCode()); + //检测运行股道与固定径路是否一致 + if(Objects.equals(false,trackAndDoor(checkData.runPlanLog.getTrackDiscordant())) && Objects.equals(false,trackSectionEQ)){ //股道不一致检测 - errMsg.add("股道固定径路不一致"); + log.error("检测股道是否一致 计划车站[{}],计划股道[{}],径路车站[{}],径路股道[{}],车次[{}],方向[{}],固定径路[{}]",checkData.runPlan.getStation().getCode() + ,checkData.runPlan.getTrackSection().getCode(),rtl.getStation().getCode(),rtl.getMasterStand().getCode(),checkData.runPlan.getTripNumber(),checkData.departToChar(),rtl.getCode()); + errMsg.add(String.format("运行股道固定径路[%s]不一致",rtl.getMasterStand().getName())); } - if(Objects.equals(false,trackAndDoor(runPlanLog.getEntryOutDiscordant())) && !Objects.equals(runPlan.getStationDirection().getCode(),sd.getCode())){ + //检测出入口与固定径路是否一致 + if(Objects.equals(false,trackAndDoor(checkData.runPlanLog.getEntryOutDiscordant())) && Objects.equals(false,doorEQ)){ //出入口不一致检测 - errMsg.add("出入口固定径路不一致"); + log.error("检测出入口是否一致 计划车站[{}],计划股道[{}],径路车站[{}],径路股道[{}],车次[{}],方向[{}],固定径路[{}]",checkData.runPlan.getStation().getCode() + ,checkData.runPlan.getTrackSection().getCode(),rtl.getStation().getCode(),rtl.getMasterStand().getCode(),checkData.runPlan.getTripNumber(),checkData.departToChar(),rtl.getCode()); + errMsg.add(String.format("运行出入口固定径路[%s]不一致",sd.getName())); } } @@ -154,27 +179,25 @@ public class CascoControlService { /** * 检测接发计划与股道接发车方向是否一致 - * @param isDepart - * @param stationTrackRepository - * @param runPlanLog + * @param checkData * @param errMsg */ - private void checkStationTrackDetail(boolean isDepart,CtcStationRunPlanLog.RunPlanItem runPlan,CtcEffectRepository.StationTrackSectionRepository stationTrackRepository,CtcStationRunPlanLog runPlanLog,List errMsg){ + private void checkStationTrackDetail(CheckData checkData,List errMsg){ if(!CollectionUtils.isEmpty(errMsg)){ return; } - String departChar = this.departToChar(isDepart); - Section masterSection = runPlan.getTrackSection(); - TrackSection ts = stationTrackRepository.getDataMap().get(masterSection.getCode()); + String departChar = checkData.departToChar(); + Section masterSection = checkData.runPlan.getTrackSection(); + TrackSection ts = checkData.stationTrackRepository.getDataMap().get(masterSection.getCode()); if(Objects.isNull(ts)){ - String d = String.format("未找到对应的股道[%s],车站[%s],车号[%s],股道[%s]",departChar,runPlanLog.getStation().getCode(),runPlanLog.getTripNumber(),masterSection.getCode()); + String d = String.format("未找到对应的股道 方向[%s],车站[%s],车号[%s],股道[%s]",departChar,checkData.runPlanLog.getStation().getCode(),checkData.runPlanLog.getTripNumber(),masterSection.getCode()); log.error(d); errMsg.add(d); return; } - checkStationTrackForTransfinite(ts,runPlanLog,errMsg,departChar); - checkStationTrackForTrainType(ts,runPlanLog,errMsg); + checkStationTrackForTransfinite(ts,checkData.runPlanLog,errMsg,departChar); + checkStationTrackForTrainType(ts,checkData.runPlanLog,errMsg); } /** @@ -194,20 +217,24 @@ public class CascoControlService { runPlanLog.getTransfinite() == CtcStationRunPlanLog.TransfiniteType.TRANSFINITE_SUPER); //大于二级超限 boolean trainfiniteThanMoreTwo = runPlanLog.getTransfinite() == CtcStationRunPlanLog.TransfiniteType.TRANSFINITE_SUPER; - String d = null; + String logMsg = null; + String msg = null; if(sTT == CtcStationRunPlanLog.TransfiniteType.NO && runPlanLog.getTransfinite() != CtcStationRunPlanLog.TransfiniteType.NO){ //股道不能超限,但是计划超限 - d = String.format("股道[%s],车站[%s],车次[%s],[%s],不支持超限,但行车计划超限[%s]",ts.getCode(),runPlanLog.getStation().getCode(),runPlanLog.getTripNumber(),departChar,runPlanLog.getTransfinite()); + logMsg = String.format("车站[%s],股道[%s],车次[%s],方向[%s],不支持超限,但行车计划超限[%s]",runPlanLog.getStation().getCode(),ts.getCode(),runPlanLog.getTripNumber(),departChar,runPlanLog.getTransfinite()); + msg = String.format("车站[%s],股道[%s] 不支持超限",runPlanLog.getStation().getName(),ts.getName()); }else if(sTT == CtcStationRunPlanLog.TransfiniteType.TRANSFINITE_ONE_LEVEL && transfiniteThanMoreOne){ //股道是一级超限,但是计划是二级或是超级 - d = String.format("股道[%s],车站[%s],车次[%s],[%s],一级超限,但行车计划超限[%s]",ts.getCode(),runPlanLog.getStation().getCode(),runPlanLog.getTripNumber(),departChar,runPlanLog.getTransfinite()); + logMsg = String.format("车站[%s],股道[%s],车次[%s],方向[%s],一级超限,但行车计划超限[%s]",runPlanLog.getStation().getCode(),ts.getCode(),runPlanLog.getTripNumber(),departChar,runPlanLog.getTransfinite()); + msg = String.format("车站[%s],股道[%s] 只支持一级超限",runPlanLog.getStation().getName(),ts.getName()); }else if(sTT == CtcStationRunPlanLog.TransfiniteType.TRANSFINITE_TWO_LEVEL && trainfiniteThanMoreTwo){ //股道是二级超限,但是计划是超级 - d = String.format("股道[%s],车站[%s],车次[%s],[%s],二级超限,但行车计划超限[%s]",ts.getCode(),runPlanLog.getStation().getCode(),runPlanLog.getTripNumber(),departChar,runPlanLog.getTransfinite()); + logMsg = String.format("车站[%s],股道[%s],车次[%s],方向[%s],二级超限,但行车计划超限[%s]",runPlanLog.getStation().getCode(),ts.getCode(),runPlanLog.getTripNumber(),departChar,runPlanLog.getTransfinite()); + msg = String.format("车站[%s],股道[%s] 只支持二级超限",runPlanLog.getStation().getName(),ts.getName()); } - if(Objects.equals(false,Strings.isNullOrEmpty(d))){ - log.error(d); - errMsg.add(d); + if(Objects.equals(false,Strings.isNullOrEmpty(logMsg))){ + log.error(logMsg); + errMsg.add(msg); } } @@ -222,9 +249,11 @@ public class CascoControlService { TrackSection.TrainType tt = ts.getTrainType(); switch (tt){ case PASSENGER: + //检测客车,但是计划中不是客车 trainTypeMatch = Objects.equals(false,runPlanLog.isPassengerTrain()); break; case GOODS_VAN: + //检测货车,但是计划中不是货车 trainTypeMatch = Objects.equals(true,runPlanLog.isPassengerTrain()); break; default: @@ -232,53 +261,72 @@ public class CascoControlService { } if(trainTypeMatch){ String d = String.format("计划列车类型与股道类型不匹配,股道[%s] 股道区段[%s] 设置列车类型[%s],列车类型[%s]",ts.getCode(),ts.getSectionCode(),tt,runPlanLog.isPassengerTrain()?"客":"货"); - errMsg.add(d); + log.error(d); + errMsg.add(String.format("计划列车类型与股道类型不匹配")); } } /** * 计划与出入口检测明细 - * @param isDepart 是否是发车计划 - * @param doorRepository - * @param runPlanLog + * @param checkData + * @param errMsgList */ - private void doorCheckDetail(boolean isDepart,CtcStationRunPlanLog.RunPlanItem runPlan,CtcEffectRepository.StationDoorRepository doorRepository,CtcStationRunPlanLog runPlanLog,List errMsgList){ + private void doorCheckDetail(CheckData checkData,List errMsgList){ if(!CollectionUtils.isEmpty(errMsgList)){ return; } - String depart = this.departToChar(isDepart); - StationDirection sd = runPlan.getStationDirection(); - StationDirection doorDir = doorRepository.getDataMap().get(sd.getCode()); + String depart = checkData.departToChar(); + StationDirection sd = checkData.runPlan.getStationDirection(); + StationDirection doorDir = checkData.doorRepository.getDataMap().get(sd.getCode()); if(Objects.isNull(doorDir)){ - errMsgList.add(String.format("根据计划方向[%s] 没有找到出入口[%s]数据,车站[%s],车次[%s]" - ,depart,sd.getCode(),runPlanLog.getStation().getCode(),runPlanLog.getTripNumber())); + String d = String.format("根据计划方向[%s] 没有找到出入口数据 出入口[%s],车站[%s],车次[%s]" + ,depart,sd.getCode(),checkData.runPlanLog.getStation().getCode(),checkData.runPlanLog.getTripNumber()); + log.error(d); + errMsgList.add("未找到计划方向对应的出入口数据"); } - boolean isTransfinite = Objects.nonNull(runPlanLog.getTransfinite()) && runPlanLog.getTransfinite() != CtcStationRunPlanLog.TransfiniteType.NO; + boolean isTransfinite = Objects.nonNull(checkData.runPlanLog.getTransfinite()) && checkData.runPlanLog.getTransfinite() != CtcStationRunPlanLog.TransfiniteType.NO; if(!doorDir.isAllowOverrun() && isTransfinite){ // 出入口不能超限,但是计划超限 - errMsgList.add(String.format("出入口[%s],[%s]不允许超限,但是计划超限,车站[%s],车次[%s]" - ,sd.getCode(),depart,runPlanLog.getStation().getCode(),runPlanLog.getTripNumber())); + String d = String.format("出入口方向[%s],车站[%s]不允许超限,但是计划超限,车站[%s],车次[%s]" + ,sd.getCode(),depart,checkData.runPlanLog.getStation().getCode(),checkData.runPlanLog.getTripNumber()); + log.error(d); + errMsgList.add(String.format("出入口[%s]不允许超限",doorDir.getName())); return; } - if(!doorDir.isTravelTrain() && Objects.equals(true,runPlanLog.isPassengerTrain())){ + if(!doorDir.isTravelTrain() && Objects.equals(true,checkData.runPlanLog.isPassengerTrain())){ //出入口不支持客车,但是计划是客车 - errMsgList.add(String.format("出入口[%s],[%s]不允许客车,车站[%s],车次[%s]" - ,sd.getCode(),depart,runPlanLog.getStation().getCode(),runPlanLog.getTripNumber())); + String d = String.format("出入口方向[%s],车站[%s]不允许客车,车站[%s],车次[%s]" + ,sd.getCode(),depart,checkData.runPlanLog.getStation().getCode(),checkData.runPlanLog.getTripNumber()); + log.error(d); + errMsgList.add(String.format("出入口[%s]不支持接发客车",doorDir.getName())); return; } - if(!doorDir.isGoodsTrain() && Objects.equals(false,runPlanLog.isPassengerTrain())){ + if(!doorDir.isGoodsTrain() && Objects.equals(false,checkData.runPlanLog.isPassengerTrain())){ //出入口不支持货车,但是计划是货车 - errMsgList.add(String.format("出入口[%s],[%s]不允许货车,车站[%s],车次[%s]" - ,sd.getCode(),depart,runPlanLog.getStation().getCode(),runPlanLog.getTripNumber())); + String d=String.format("出入口[%s],[%s]不允许货车,车站[%s],车次[%s]" + ,sd.getCode(),depart,checkData.runPlanLog.getStation().getCode(),checkData.runPlanLog.getTripNumber()); + log.error(d); + errMsgList.add(String.format("出入口[%s]不支持接发货车",doorDir.getName())); return; } } - private String departToChar(boolean isDepart){ - return isDepart ? "发":"接"; - } + @Data + @NoArgsConstructor + public static class CheckData{ + private CtcStationRunPlanLog runPlanLog; + private CtcStationRunPlanLog.RunPlanItem runPlan; + private CtcEffectRepository.StationDoorRepository doorRepository; + private CtcEffectRepository.StationTrackSectionRepository stationTrackRepository; + private CtcEffectRepository.RegularTrainLineRepository regularTrainLineRepository; + private boolean justReturn; + private boolean isDepart; + public String departToChar(){ + return isDepart ? "发":"接"; + } + } } diff --git a/src/main/java/club/joylink/rtss/simulation/cbtc/build/SimulationBuilder.java b/src/main/java/club/joylink/rtss/simulation/cbtc/build/SimulationBuilder.java index 8ac858ea5..94eb3a7c0 100644 --- a/src/main/java/club/joylink/rtss/simulation/cbtc/build/SimulationBuilder.java +++ b/src/main/java/club/joylink/rtss/simulation/cbtc/build/SimulationBuilder.java @@ -379,9 +379,10 @@ public class SimulationBuilder { rep.save(ts); } } - //复制编辑区的股道,出入口到生效,编辑区 + //复制编辑区的股道数据到生效,编辑区 copyEditToTargetForStationTrack(stationTrackRepositoryMap,effectStationTrackMap); copyEditToTargetForStationTrack(stationTrackRepositoryMap,updateStationTrackMap); + //复制编辑区的出入口数据到生效,编辑区 copyEditToTargetForDoor(doorRepository,effectDoorMap); copyEditToTargetForDoor(doorRepository,updateDoorMap); } From 5e4d85443d56cc611643315ab0abbaef9bd79f26 Mon Sep 17 00:00:00 2001 From: tiger_zhou <123456> Date: Thu, 1 Sep 2022 18:03:06 +0800 Subject: [PATCH 3/9] =?UTF-8?q?=E8=BD=A6=E5=8A=A1=E7=AE=A1=E7=90=86?= =?UTF-8?q?=E7=BB=88=E7=AB=AF=E5=8A=9F=E8=83=BD=E4=BB=A3=E7=A0=81=E8=B0=83?= =?UTF-8?q?=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cbtc/CTC/service/CascoControlService.java | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/src/main/java/club/joylink/rtss/simulation/cbtc/CTC/service/CascoControlService.java b/src/main/java/club/joylink/rtss/simulation/cbtc/CTC/service/CascoControlService.java index a76e36a90..f9767b8cf 100644 --- a/src/main/java/club/joylink/rtss/simulation/cbtc/CTC/service/CascoControlService.java +++ b/src/main/java/club/joylink/rtss/simulation/cbtc/CTC/service/CascoControlService.java @@ -1,27 +1,22 @@ package club.joylink.rtss.simulation.cbtc.CTC.service; import club.joylink.rtss.exception.BusinessException; -import club.joylink.rtss.exception.BusinessExceptionAssertEnum; import club.joylink.rtss.simulation.cbtc.CI.data.StationDirection; import club.joylink.rtss.simulation.cbtc.CTC.data.*; import club.joylink.rtss.simulation.cbtc.Simulation; 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.Station; import com.google.common.base.Strings; -import com.google.common.collect.Lists; -import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.apache.ibatis.annotations.Case; import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; -import java.util.*; - -import static club.joylink.rtss.simulation.cbtc.CTC.data.TrackSection.DirectionType; +import java.util.Collections; +import java.util.List; +import java.util.Objects; @Service @Slf4j @@ -183,7 +178,7 @@ public class CascoControlService { * @param errMsg */ private void checkStationTrackDetail(CheckData checkData,List errMsg){ - if(!CollectionUtils.isEmpty(errMsg)){ + if(Objects.equals(false,CollectionUtils.isEmpty(errMsg))){ return; } String departChar = checkData.departToChar(); From 8e6060eaa258e18a8fb60843891e7c188558f81d Mon Sep 17 00:00:00 2001 From: weizhihong Date: Thu, 1 Sep 2022 18:39:33 +0800 Subject: [PATCH 4/9] =?UTF-8?q?=E3=80=90=E4=BC=98=E5=8C=96=E5=AE=9E?= =?UTF-8?q?=E8=AE=AD=E5=8A=A0=E8=BD=BD=E9=80=9F=E5=BA=A6=EF=BC=8C=E7=BB=93?= =?UTF-8?q?=E6=9D=9F=E5=90=8E=E7=9B=B4=E6=8E=A5=E8=8E=B7=E5=8F=96=E4=B8=8B?= =?UTF-8?q?=E4=B8=80=E6=AD=A5=E3=80=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../services/training2/Training2Service.java | 70 +++++++++++++++---- 1 file changed, 55 insertions(+), 15 deletions(-) diff --git a/src/main/java/club/joylink/rtss/services/training2/Training2Service.java b/src/main/java/club/joylink/rtss/services/training2/Training2Service.java index e8b38a246..e8f07ada5 100644 --- a/src/main/java/club/joylink/rtss/services/training2/Training2Service.java +++ b/src/main/java/club/joylink/rtss/services/training2/Training2Service.java @@ -72,23 +72,14 @@ public class Training2Service { return; } // 获取运行步骤 - Step2 step = training2.getCurrentRunStep(); - if (step == null) { // 步骤已经运行完毕 - training2.finish(); - // 发送实训完成消息 - sendTrainingFinish(training2, simulation); + Step2 step = getNextStepAndCheckTrainingStatus(training2, simulation); + if (step == null) { return; } - // 步骤是否已经触发 - // 没有触发则检查触发状态,如果可以触发则继续,不能触发则返回 - if (!Step2.StepStatus.isAlreadyTrigger(step.getStepStatus()) && !step.doTriggerVail()) { + // 尝试触发步骤 + if (!tryTriggerStep(step, simulation)) { return; } - // 发送步骤提示信息 - if (!step.isPrompt()) { - step.setPrompt(true); // 标识已发送过消息 - sendStepTips(step, simulation); - } // 获取步骤中未完成的操作 Operation2 operation2 = step.getCurrentRunOperation(); // 操作全部完成的情况,检查步骤完成条件 @@ -126,7 +117,7 @@ public class Training2Service { sendOperationFinish(operation2, simulation); // 如果是最后一步,直接检查步骤有没有完成 if (step.getOperations().indexOf(operation2) == (step.getOperations().size() - 1) && completion) { - checkTrainStepCompletion(step, simulation); + checkStepCompletionAndSendNext(step, simulation); } } } @@ -283,7 +274,7 @@ public class Training2Service { } } if (result) { - checkTrainStepCompletion(step, simulation); // 直接检查步骤是否完成 + checkStepCompletionAndSendNext(step, simulation); // 直接检查步骤是否完成 } // 恢复前端运行 pauseOrStartSimulation(simulation, false); @@ -492,6 +483,55 @@ public class Training2Service { sendStepFinish(step, simulation); } + /** + * 获取实训下一步未执行的步骤,如果实训已结束则返回null + */ + private Step2 getNextStepAndCheckTrainingStatus(Training2 training2, Simulation simulation) { + // 获取运行步骤 + Step2 nextStep = training2.getCurrentRunStep(); + if (nextStep == null) { // 步骤已经运行完毕 + training2.finish(); + // 发送实训完成消息 + sendTrainingFinish(training2, simulation); + return null; + } + return nextStep; + } + + /** + * 尝试触发步骤,如果触发返回true,可以继续,未触发返回false + */ + private boolean tryTriggerStep(Step2 step, Simulation simulation) { + // 步骤是否已经触发 + // 没有触发则检查触发状态,如果可以触发则继续,不能触发则返回 + if (!Step2.StepStatus.isAlreadyTrigger(step.getStepStatus()) && !step.doTriggerVail()) { + return false; + } + // 发送步骤提示信息 + if (!step.isPrompt()) { + step.setPrompt(true); // 标识已发送过消息 + sendStepTips(step, simulation); + } + return true; + } + + /** + * 直接完成并尝试触发下一步 + */ + private void checkStepCompletionAndSendNext(Step2 step, Simulation simulation) { + boolean result = step.doCompletionVail(); + if (result) { + // 发送步骤完成信息 + sendStepFinish(step, simulation); + // 获取运行步骤 + Step2 nextStep = getNextStepAndCheckTrainingStatus(simulation.getTraining2(), simulation); + if (nextStep == null) { + return; + } + tryTriggerStep(nextStep, simulation); + } + } + /** * 暂停、恢复实训 */ From 98742d923a3d33bf113953c770f03658cfa32712 Mon Sep 17 00:00:00 2001 From: tiger_zhou <123456> Date: Fri, 2 Sep 2022 09:31:19 +0800 Subject: [PATCH 5/9] =?UTF-8?q?=E8=BD=A6=E5=8A=A1=E7=AE=A1=E7=90=86?= =?UTF-8?q?=E7=BB=88=E7=AB=AF=E5=8A=9F=E8=83=BD=E4=BB=A3=E7=A0=81=E8=B0=83?= =?UTF-8?q?=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../joylink/rtss/simulation/cbtc/CTC/data/CascoControl.java | 1 + .../rtss/simulation/cbtc/CTC/service/CascoControlService.java | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/club/joylink/rtss/simulation/cbtc/CTC/data/CascoControl.java b/src/main/java/club/joylink/rtss/simulation/cbtc/CTC/data/CascoControl.java index 4dcc2f6aa..59d6c2178 100644 --- a/src/main/java/club/joylink/rtss/simulation/cbtc/CTC/data/CascoControl.java +++ b/src/main/java/club/joylink/rtss/simulation/cbtc/CTC/data/CascoControl.java @@ -13,6 +13,7 @@ import java.util.Objects; @Data @NoArgsConstructor public class CascoControl { + private Simulation simulation; private Station station; private Route route; diff --git a/src/main/java/club/joylink/rtss/simulation/cbtc/CTC/service/CascoControlService.java b/src/main/java/club/joylink/rtss/simulation/cbtc/CTC/service/CascoControlService.java index f9767b8cf..3f07f7655 100644 --- a/src/main/java/club/joylink/rtss/simulation/cbtc/CTC/service/CascoControlService.java +++ b/src/main/java/club/joylink/rtss/simulation/cbtc/CTC/service/CascoControlService.java @@ -24,7 +24,7 @@ public class CascoControlService { /** * - * @param cc + * @param cc 卡控参数 * @return */ public List checkCascoControlRoute(CascoControl cc){ From 8d195c5367b1317d7095e5309c76bfa562aa204a Mon Sep 17 00:00:00 2001 From: weizhihong Date: Fri, 2 Sep 2022 11:10:22 +0800 Subject: [PATCH 6/9] =?UTF-8?q?=E3=80=90=E5=89=8D=E7=AB=AF=E9=87=8D?= =?UTF-8?q?=E5=A4=8D=E7=82=B9=E5=87=BB=E6=97=B6=E3=80=81=E5=90=8E=E7=AB=AF?= =?UTF-8?q?=E6=8A=A5=E9=94=99=E9=97=AE=E9=A2=98=E3=80=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../services/training2/Training2Service.java | 170 ++++++++++++------ .../simulation/cbtc/training2/Operation2.java | 5 +- .../rtss/simulation/cbtc/training2/Step2.java | 6 +- 3 files changed, 128 insertions(+), 53 deletions(-) diff --git a/src/main/java/club/joylink/rtss/services/training2/Training2Service.java b/src/main/java/club/joylink/rtss/services/training2/Training2Service.java index e8f07ada5..d0aa1243a 100644 --- a/src/main/java/club/joylink/rtss/services/training2/Training2Service.java +++ b/src/main/java/club/joylink/rtss/services/training2/Training2Service.java @@ -34,6 +34,7 @@ import org.springframework.util.StringUtils; import java.util.HashMap; import java.util.Map; import java.util.Objects; +import java.util.concurrent.Semaphore; import java.util.function.Consumer; @Service @@ -66,6 +67,16 @@ public class Training2Service { @Autowired private StompMessageService stompMessageService; + /** + * 完成步骤接口信号量 + */ + private Semaphore completeStepSemaphore = new Semaphore(1); + + /** + * 完成操作接口信号量 + */ + private Semaphore completeOperationSemaphore = new Semaphore(1); + public void run(Simulation simulation) { Training2 training2 = simulation.getTraining2(); if (training2 == null || !training2.isStarted() || training2.isFinish()) { @@ -81,47 +92,19 @@ public class Training2Service { return; } // 获取步骤中未完成的操作 - Operation2 operation2 = step.getCurrentRunOperation(); - // 操作全部完成的情况,检查步骤完成条件 + Operation2 operation2 = getOperationAndTryTrigger(step, simulation); if (operation2 == null) { - // TODO 后续判断步骤完成情况 - checkTrainStepCompletion(step, simulation); return; } - // 操作是否已触发 - // 没有触发则检查触发状态,如果可以触发则继续,不能触发则返回(同步骤) - if (!Step2.StepStatus.isAlreadyTrigger(operation2.getStatus()) && !operation2.doTriggerVail()) { + // 尝试执行操作 + if (!tryDoOperation(simulation, step, operation2)) { return; } - boolean isRobot = step.getSimulationMember().isRobot(); // 角色是否是机器人 - boolean isClient = operation2 instanceof Operation2.ClientOperation2; // 客户端操作 - // 未操作过 - if (Step2.StepStatus.isUndo(operation2.getStatus())) { - if (isRobot) { - if (isClient) { // 客户端操作 - operation2.doOperated(); - } else { // 仿真操 - Operation2.SimOperation2 simOperation2 = (Operation2.SimOperation2) operation2; - atsOperationDispatcher.execute(simulation, step.getSimulationMember(), - simOperation2.getOperationType().name(), simOperation2.getParams()); - } - } else { // 非机器人,暂停仿真等待用户操作 - pauseOrStartSimulation(simulation, true); - return; - } - } - // 运行阶段,判断是否完成 - if (Step2.StepStatus.isRunning(operation2.getStatus())) { - boolean completion = operation2.doCompletion(); - // 发送操作完成信息 - sendOperationFinish(operation2, simulation); - // 如果是最后一步,直接检查步骤有没有完成 - if (step.getOperations().indexOf(operation2) == (step.getOperations().size() - 1) && completion) { - checkStepCompletionAndSendNext(step, simulation); - } - } + // 操作运行阶段,判断是否完成 + tryCompleteOperation(simulation, step, operation2); } + /** * 预览实训草稿 */ @@ -263,21 +246,32 @@ public class Training2Service { if (Objects.equals(user.getId(), step.getSimulationMember().getId())) { throw new SimulationException(SimulationExceptionType.Invalid_Operation, "无权限操作"); } - boolean result = true; - for (Operation2 operation2 : step.getOperations()) { - if (operation2 instanceof Operation2.ClientOperation2) { // 前端操作,直接判断结果 - operation2.doOperated(); - operation2.doCompletion(); - } else { - result = false; - break; + try { + if (!step.isCompletion()) { + completeStepSemaphore.acquire(); // 控制多次请求 + if (!step.isCompletion()) { //二次判断 + boolean result = true; + for (Operation2 operation2 : step.getOperations()) { + if (operation2 instanceof Operation2.ClientOperation2) { // 前端操作,直接判断结果 + operation2.doOperated(); + operation2.doCompletion(); + } else { + result = false; + break; + } + } + if (result) { + checkStepCompletionAndSendNext(step, simulation); // 直接检查步骤是否完成 + } + // 恢复前端运行 + pauseOrStartSimulation(simulation, false); + } } + } catch (InterruptedException e) { + throw new RuntimeException(e); + } finally { + completeStepSemaphore.release(); } - if (result) { - checkStepCompletionAndSendNext(step, simulation); // 直接检查步骤是否完成 - } - // 恢复前端运行 - pauseOrStartSimulation(simulation, false); return 1; } @@ -307,9 +301,21 @@ public class Training2Service { if (operation == null) { throw new SimulationException(SimulationExceptionType.Invalid_Operation, "不存在操作"); } - operation.doOperated(); - // 恢复前端运行 - pauseOrStartSimulation(simulation, false); + try { + if (!Step2.StepStatus.isCompletion(operation.getStatus())) { + completeOperationSemaphore.acquire(); + if (!Step2.StepStatus.isCompletion(operation.getStatus())) { + operation.doOperated(); //操作过后 + tryCompleteOperation(simulation, step, operation); // 尝试完成 + // 恢复前端运行 + pauseOrStartSimulation(simulation, false); + } + } + } catch (InterruptedException e) { + throw new RuntimeException(e); + } finally { + completeOperationSemaphore.release(); + } return 1; } @@ -515,6 +521,66 @@ public class Training2Service { return true; } + /** + * 获取步骤中操作,并尝试触发 + */ + private Operation2 getOperationAndTryTrigger(Step2 step, Simulation simulation) { + // 获取步骤中未完成的操作 + Operation2 operation2 = step.getCurrentRunOperation(); + // 操作全部完成的情况,检查步骤完成条件 + if (operation2 == null) { + // TODO 后续判断步骤完成情况 + checkTrainStepCompletion(step, simulation); + return null; + } + // 操作是否已触发 + // 没有触发则检查触发状态,如果可以触发则继续,不能触发则返回(同步骤) + if (!Step2.StepStatus.isAlreadyTrigger(operation2.getStatus()) && !operation2.doTriggerVail()) { + return null; + } + return operation2; + } + + /** + * 尝试操作动作 + */ + private boolean tryDoOperation(Simulation simulation, Step2 step, Operation2 operation2) { + boolean isRobot = step.getSimulationMember().isRobot(); // 角色是否是机器人 + boolean isClient = operation2 instanceof Operation2.ClientOperation2; // 客户端操作 + // 未操作过 + if (Step2.StepStatus.isUndo(operation2.getStatus())) { + if (isRobot) { + if (isClient) { // 客户端操作 + operation2.doOperated(); + } else { // 仿真操 + Operation2.SimOperation2 simOperation2 = (Operation2.SimOperation2) operation2; + atsOperationDispatcher.execute(simulation, step.getSimulationMember(), + simOperation2.getOperationType().name(), simOperation2.getParams()); + } + return true; + } else { // 非机器人,暂停仿真等待用户操作 + pauseOrStartSimulation(simulation, true); + return false; + } + } + return true; + } + + /** + * 尝试完成操作 + */ + private void tryCompleteOperation(Simulation simulation, Step2 step, Operation2 operation2) { + if (Step2.StepStatus.isRunning(operation2.getStatus())) { + boolean completion = operation2.doCompletion(); + // 发送操作完成信息 + sendOperationFinish(operation2, simulation); + // 如果是最后一步,直接检查步骤有没有完成 + if (step.getOperations().indexOf(operation2) == (step.getOperations().size() - 1) && completion) { + checkStepCompletionAndSendNext(step, simulation); + } + } + } + /** * 直接完成并尝试触发下一步 */ @@ -528,7 +594,9 @@ public class Training2Service { if (nextStep == null) { return; } - tryTriggerStep(nextStep, simulation); + if (tryTriggerStep(nextStep, simulation)) { + getOperationAndTryTrigger(nextStep, simulation); + } } } diff --git a/src/main/java/club/joylink/rtss/simulation/cbtc/training2/Operation2.java b/src/main/java/club/joylink/rtss/simulation/cbtc/training2/Operation2.java index 575b2156c..e68ea9ec1 100644 --- a/src/main/java/club/joylink/rtss/simulation/cbtc/training2/Operation2.java +++ b/src/main/java/club/joylink/rtss/simulation/cbtc/training2/Operation2.java @@ -84,8 +84,11 @@ public abstract class Operation2 { if (!result) { // 未失败 result = doSuccessVail(); } - if (result) { + // 这里开始时间为空是因为前端触发太快导致,线程还未走操作触发操作 + if (result && this.startTime != null) { this.remainTime = this.operatedTime.getNano() - this.startTime.getNano(); + } else { + this.remainTime = 0; } return result; } diff --git a/src/main/java/club/joylink/rtss/simulation/cbtc/training2/Step2.java b/src/main/java/club/joylink/rtss/simulation/cbtc/training2/Step2.java index 426576622..8247b8b4a 100644 --- a/src/main/java/club/joylink/rtss/simulation/cbtc/training2/Step2.java +++ b/src/main/java/club/joylink/rtss/simulation/cbtc/training2/Step2.java @@ -156,7 +156,11 @@ public class Step2 { */ public void completionAndCalculate() { // 整步骤完成耗费时间 - this.remainTime = LocalDateTime.now().getNano() - this.startTime.getNano(); + if (this.startTime != null) { + this.remainTime = LocalDateTime.now().getNano() - this.startTime.getNano(); + } else { + this.remainTime = 0; + } // 操作错误总数 this.count = this.operations.stream().mapToInt(o -> o.getCount().get()).sum(); } From 24866371753468362bebbfa6b1c1c7699a494cc9 Mon Sep 17 00:00:00 2001 From: weizhihong Date: Fri, 2 Sep 2022 15:59:05 +0800 Subject: [PATCH 7/9] =?UTF-8?q?=E3=80=90=E4=B8=AA=E4=BA=BA=E8=8D=89?= =?UTF-8?q?=E7=A8=BF=E6=B7=BB=E5=8A=A0=E6=97=B6=E9=87=8D=E5=90=8D=E5=88=A4?= =?UTF-8?q?=E6=96=AD=E3=80=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../joylink/rtss/services/training2/Training2DraftService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/club/joylink/rtss/services/training2/Training2DraftService.java b/src/main/java/club/joylink/rtss/services/training2/Training2DraftService.java index c085312e9..19490163a 100644 --- a/src/main/java/club/joylink/rtss/services/training2/Training2DraftService.java +++ b/src/main/java/club/joylink/rtss/services/training2/Training2DraftService.java @@ -54,7 +54,7 @@ public class Training2DraftService { public CreateTraining2RspVo createTraining(CreateTraining2ReqVo req, AccountVO user) { //校验是否已经有同名的实训 DraftTraining2Example example = new DraftTraining2Example(); - example.createCriteria().andNameEqualTo(req.getName()); + example.createCriteria().andCreatorIdEqualTo(user.getId()).andNameEqualTo(req.getName()); List check = this.trainingDao.selectByExample(example); BusinessExceptionAssertEnum.SYSTEM_EXCEPTION.assertCollectionEmpty(check, "实训已经存在"); // From 84955a996b427d2d260942be479419ee81ae8af9 Mon Sep 17 00:00:00 2001 From: weizhihong Date: Fri, 2 Sep 2022 16:48:43 +0800 Subject: [PATCH 8/9] =?UTF-8?q?=E3=80=90=E8=8D=89=E7=A8=BF=E5=90=8C?= =?UTF-8?q?=E5=90=8D=E6=A3=80=E9=AA=8C=E3=80=81=E5=8F=91=E5=B8=83=E5=90=8C?= =?UTF-8?q?=E5=90=8D=E6=A3=80=E9=AA=8C=E3=80=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Training2DraftPublishService.java | 23 ++++++++++--------- .../training2/Training2DraftService.java | 2 +- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/src/main/java/club/joylink/rtss/services/training2/Training2DraftPublishService.java b/src/main/java/club/joylink/rtss/services/training2/Training2DraftPublishService.java index e10adc7e1..a7fb0efdf 100644 --- a/src/main/java/club/joylink/rtss/services/training2/Training2DraftPublishService.java +++ b/src/main/java/club/joylink/rtss/services/training2/Training2DraftPublishService.java @@ -9,6 +9,7 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; + import java.util.List; /** @@ -18,7 +19,7 @@ import java.util.List; @Slf4j public class Training2DraftPublishService { @Autowired - private DraftTraining2DAO trainingDao; + private DraftTraining2DAO trainingDao; @Autowired private PublishedTraining2DAO publishedDao; @@ -26,22 +27,22 @@ public class Training2DraftPublishService { * 草稿发布 */ @Transactional(rollbackFor = Exception.class) - public void draftPublish(TrainingDraftPublishReqVo req,Long userId){ - Long draftId=Long.valueOf(req.getDraftId()); - DraftTraining2Example dtExample=new DraftTraining2Example(); + public void draftPublish(TrainingDraftPublishReqVo req, Long userId) { + Long draftId = Long.valueOf(req.getDraftId()); + DraftTraining2Example dtExample = new DraftTraining2Example(); dtExample.createCriteria().andCreatorIdEqualTo(userId).andIdEqualTo(draftId); - List dtFinds= this.trainingDao.selectByExampleWithBLOBs(dtExample); - BusinessExceptionAssertEnum.SYSTEM_EXCEPTION.assertTrue(null!=dtFinds&&!dtFinds.isEmpty(),"实训草稿不存在"); - DraftTraining2WithBLOBs draft = dtFinds.get(0); + List dtFinds = this.trainingDao.selectByExampleWithBLOBs(dtExample); + BusinessExceptionAssertEnum.SYSTEM_EXCEPTION.assertTrue(null != dtFinds && !dtFinds.isEmpty(), "实训草稿不存在"); + DraftTraining2WithBLOBs draft = dtFinds.get(0); // PublishedTraining2WithBLOBs pub = Training2Convertor.convertFrom(draft); //根据要发布的草稿名称来查找已发布的实训 //如果以有同名的则会被覆盖 - PublishedTraining2Example ptExample=new PublishedTraining2Example(); - ptExample.createCriteria().andNameEqualTo(draft.getName()); - List ptFinds= this.publishedDao.selectByExample(ptExample); + PublishedTraining2Example ptExample = new PublishedTraining2Example(); + ptExample.createCriteria().andNameEqualTo(draft.getName()).andMapIdEqualTo(draft.getMapId()); + List ptFinds = this.publishedDao.selectByExample(ptExample); // - if(null!=ptFinds&&!ptFinds.isEmpty()){//已发布实训存在时则直接删除 + if (null != ptFinds && !ptFinds.isEmpty()) {//已发布实训存在时则直接删除 this.publishedDao.deleteByExample(ptExample); } //发布 diff --git a/src/main/java/club/joylink/rtss/services/training2/Training2DraftService.java b/src/main/java/club/joylink/rtss/services/training2/Training2DraftService.java index 19490163a..e76437db0 100644 --- a/src/main/java/club/joylink/rtss/services/training2/Training2DraftService.java +++ b/src/main/java/club/joylink/rtss/services/training2/Training2DraftService.java @@ -54,7 +54,7 @@ public class Training2DraftService { public CreateTraining2RspVo createTraining(CreateTraining2ReqVo req, AccountVO user) { //校验是否已经有同名的实训 DraftTraining2Example example = new DraftTraining2Example(); - example.createCriteria().andCreatorIdEqualTo(user.getId()).andNameEqualTo(req.getName()); + example.createCriteria().andCreatorIdEqualTo(user.getId()).andNameEqualTo(req.getName()).andMapIdEqualTo(req.getMapId()); List check = this.trainingDao.selectByExample(example); BusinessExceptionAssertEnum.SYSTEM_EXCEPTION.assertCollectionEmpty(check, "实训已经存在"); // From b0ed14c484f0518ba222749c5fe90286b8b01285 Mon Sep 17 00:00:00 2001 From: weizhihong Date: Fri, 2 Sep 2022 17:29:03 +0800 Subject: [PATCH 9/9] =?UTF-8?q?=E3=80=90=E5=8C=BA=E6=AE=B5=E6=95=85?= =?UTF-8?q?=E9=9A=9C=E7=B1=BB=E5=9E=8B=E5=8F=8D=E5=BA=8F=E5=88=97=E5=8C=96?= =?UTF-8?q?=E9=97=AE=E9=A2=98=E3=80=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../rtss/simulation/cbtc/data/map/MayOutOfOrderDevice.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/java/club/joylink/rtss/simulation/cbtc/data/map/MayOutOfOrderDevice.java b/src/main/java/club/joylink/rtss/simulation/cbtc/data/map/MayOutOfOrderDevice.java index c86c77d21..f8560e933 100644 --- a/src/main/java/club/joylink/rtss/simulation/cbtc/data/map/MayOutOfOrderDevice.java +++ b/src/main/java/club/joylink/rtss/simulation/cbtc/data/map/MayOutOfOrderDevice.java @@ -41,6 +41,7 @@ public abstract class MayOutOfOrderDevice extends StatusDevice { @JsonSubTypes.Type(value = Section.AxleFault.class, name = "Section$AxleFault$2"), @JsonSubTypes.Type(value = Section.AxleFault.class, name = "Section$AxleFault$3"), @JsonSubTypes.Type(value = Section.AxleFault.class, name = "Section$AxleFault$4"), + @JsonSubTypes.Type(value = Section.AxleFault.class, name = "Section$AxleFault$5"), @JsonSubTypes.Type(value = Stand.Fault.class, name = "Stand$Fault$1"), @JsonSubTypes.Type(value = Stand.Fault.class, name = "Stand$Fault$2"), @JsonSubTypes.Type(value = Stand.Fault.class, name = "Stand$Fault$3"), @@ -57,7 +58,9 @@ public abstract class MayOutOfOrderDevice extends StatusDevice { return false; device.setFault(this); return true; - }; + } + + ; default void fix(MayOutOfOrderDevice device) { if (this.equals(device.fault))