Merge remote-tracking branch 'origin/test-training2' into test-training2

This commit is contained in:
tiger_zhou 2022-09-07 17:19:13 +08:00
commit b42794e45b
18 changed files with 561 additions and 187 deletions

View File

@ -4,6 +4,8 @@ import club.joylink.rtss.dao.DraftTraining2DAO;
import club.joylink.rtss.dao.PublishedTraining2DAO; import club.joylink.rtss.dao.PublishedTraining2DAO;
import club.joylink.rtss.entity.training2.DraftTraining2WithBLOBs; import club.joylink.rtss.entity.training2.DraftTraining2WithBLOBs;
import club.joylink.rtss.entity.training2.PublishedTraining2WithBLOBs; import club.joylink.rtss.entity.training2.PublishedTraining2WithBLOBs;
import club.joylink.rtss.services.training2.index.IndexAlgorithmService;
import club.joylink.rtss.simulation.cbtc.ATS.ATSMessageCollectAndDispatcher;
import club.joylink.rtss.simulation.cbtc.ATS.operation.AtsOperationDispatcher; import club.joylink.rtss.simulation.cbtc.ATS.operation.AtsOperationDispatcher;
import club.joylink.rtss.simulation.cbtc.GroupSimulationCache; import club.joylink.rtss.simulation.cbtc.GroupSimulationCache;
import club.joylink.rtss.simulation.cbtc.GroupSimulationService; import club.joylink.rtss.simulation.cbtc.GroupSimulationService;
@ -19,6 +21,7 @@ import club.joylink.rtss.simulation.cbtc.script.ScriptBO;
import club.joylink.rtss.simulation.cbtc.training2.Operation2; import club.joylink.rtss.simulation.cbtc.training2.Operation2;
import club.joylink.rtss.simulation.cbtc.training2.Step2; import club.joylink.rtss.simulation.cbtc.training2.Step2;
import club.joylink.rtss.simulation.cbtc.training2.Training2; import club.joylink.rtss.simulation.cbtc.training2.Training2;
import club.joylink.rtss.simulation.cbtc.training2.index.Index;
import club.joylink.rtss.util.JsonUtils; import club.joylink.rtss.util.JsonUtils;
import club.joylink.rtss.vo.AccountVO; import club.joylink.rtss.vo.AccountVO;
import club.joylink.rtss.vo.LoginUserInfoVO; import club.joylink.rtss.vo.LoginUserInfoVO;
@ -46,7 +49,7 @@ import java.util.function.Consumer;
public class Training2Service { public class Training2Service {
public static final String EXECUTE_JOB_NAME = "Training2"; public static final String EXECUTE_JOB_NAME = "Training2";
public static final String SCORING_JOB_NAME = "Training2Scoring"; public static final String SCORING_JOB_NAME = "Training2Scoring";
public static final String INDEX_JOB_NAME = "Training2Index_%d"; public static final String INDEX_JOB_NAME = "Training2Index";
public static final int RATE = 1000; public static final int RATE = 1000;
@Autowired @Autowired
@ -76,15 +79,18 @@ public class Training2Service {
@Autowired @Autowired
private ApplicationContext applicationContext; private ApplicationContext applicationContext;
@Autowired
private ATSMessageCollectAndDispatcher atsMessageCollectAndDispatcher;
/** /**
* 完成步骤接口信号量 * 完成步骤接口信号量
*/ */
private Semaphore completeStepSemaphore = new Semaphore(1); private final Semaphore completeStepSemaphore = new Semaphore(1);
/** /**
* 完成操作接口信号量 * 完成操作接口信号量
*/ */
private Semaphore completeOperationSemaphore = new Semaphore(1); private final Semaphore completeOperationSemaphore = new Semaphore(1);
/** /**
* 实训运行 * 实训运行
@ -92,6 +98,8 @@ public class Training2Service {
public void run(Simulation simulation) { public void run(Simulation simulation) {
Training2 training2 = simulation.getTraining2(); Training2 training2 = simulation.getTraining2();
if (training2 == null || !training2.isStarted() || training2.isFinish()) { if (training2 == null || !training2.isStarted() || training2.isFinish()) {
// 结束并移除运行任务
removeTrainingJob(simulation);
return; return;
} }
// 获取运行步骤 // 获取运行步骤
@ -193,18 +201,16 @@ public class Training2Service {
if (training2 == null) { if (training2 == null) {
throw new SimulationException(SimulationExceptionType.Invalid_Operation, "实训数据不存在"); throw new SimulationException(SimulationExceptionType.Invalid_Operation, "实训数据不存在");
} }
if (training2.isNeedReloadScenes()) { if (training2.isNeedReloadScenes() && !StringUtils.isEmpty(training2.getBgSceneJson())) {
simulationLifeCycleService.pause(simulation); groupSimulationService.loadScenes(simulation.getId(), training2.getBgSceneJson());
} else {
// 重置仿真状态 // 重置仿真状态
groupSimulationService.planOver(group); simulationLifeCycleService.reset(simulation);
if (!StringUtils.isEmpty(training2.getBgSceneJson())) { atsMessageCollectAndDispatcher.collectAllAndSend(simulation);
groupSimulationService.loadScenes(simulation.getId(), training2.getBgSceneJson());
}
} }
// 增加实训任务 // 增加实训任务
training2.start(mode); training2.start(mode);
addTrainingJob(simulation, training2); addTrainingJob(simulation, training2);
simulationLifeCycleService.resume(simulation);
} }
/** /**
@ -223,7 +229,7 @@ public class Training2Service {
// 创建者退出则清理实训 // 创建者退出则清理实训
if (simulation.getCreator().getId().equals(user.getId())) { if (simulation.getCreator().getId().equals(user.getId())) {
training2.finish(); training2.finish();
removeTrainingJob(simulation, training2); removeTrainingJob(simulation);
} }
scoreMap = training2.mark(); scoreMap = training2.mark();
} else { } else {
@ -250,7 +256,7 @@ public class Training2Service {
if (step == null) { if (step == null) {
throw new SimulationException(SimulationExceptionType.Invalid_Operation, "不存在步骤"); throw new SimulationException(SimulationExceptionType.Invalid_Operation, "不存在步骤");
} }
if (Objects.equals(user.getId(), step.getSimulationMember().getId())) { if (!Objects.equals(String.valueOf(user.getId()), step.getSimulationMember().getUserId())) {
throw new SimulationException(SimulationExceptionType.Invalid_Operation, "无权限操作"); throw new SimulationException(SimulationExceptionType.Invalid_Operation, "无权限操作");
} }
try { try {
@ -300,7 +306,7 @@ public class Training2Service {
if (step == null) { if (step == null) {
throw new SimulationException(SimulationExceptionType.Invalid_Operation, "不存在步骤"); throw new SimulationException(SimulationExceptionType.Invalid_Operation, "不存在步骤");
} }
if (Objects.equals(user.getId(), step.getSimulationMember().getId())) { if (!Objects.equals(String.valueOf(user.getId()), step.getSimulationMember().getUserId())) {
throw new SimulationException(SimulationExceptionType.Invalid_Operation, "无权限操作"); throw new SimulationException(SimulationExceptionType.Invalid_Operation, "无权限操作");
} }
Operation2 operation = step.getOperations().stream().filter(o -> Objects.equals(o.getId(), id)) Operation2 operation = step.getOperations().stream().filter(o -> Objects.equals(o.getId(), id))
@ -364,11 +370,15 @@ public class Training2Service {
} }
// 操作完成后,如果是测验模式则仿真启动 // 操作完成后,如果是测验模式则仿真启动
pauseOrStartSimulation(simulation, false); pauseOrStartSimulation(simulation, false);
// 检查是否要计算指标
if (!CollectionUtils.isEmpty(training2.getIndexList())) { if (!CollectionUtils.isEmpty(training2.getIndexList())) {
training2.getIndexList().stream() training2.getIndexList().stream()
.filter(index -> !index.getType().isContinuity() .filter(index -> !index.isContinuity() && !CollectionUtils.isEmpty(index.getOperationType())
&& Objects.equals(simOperation2.getOperationType(), index.getType().getOperationType())) && index.getOperationType().contains(simOperation2.getOperationType())
.forEach(index -> training2.getIndexAlgorithmMap().get(index.getId()).calculation(simulation, null)); && training2.getIndexAlgorithmMap().containsKey(index.name())
)
.forEach(index -> training2.getIndexAlgorithmMap().get(index.name())
.calculation(simulation, simOperation2.getParams()));
} }
} }
} }
@ -651,7 +661,7 @@ public class Training2Service {
/** /**
* 移除实训任务 * 移除实训任务
*/ */
private void removeTrainingJob(Simulation simulation, Training2 training2) { private void removeTrainingJob(Simulation simulation) {
if (simulation.getJobMap().containsKey(SCORING_JOB_NAME)) { if (simulation.getJobMap().containsKey(SCORING_JOB_NAME)) {
simulation.removeJob(SCORING_JOB_NAME); //移除打分监视任务 simulation.removeJob(SCORING_JOB_NAME); //移除打分监视任务
} }
@ -659,14 +669,8 @@ public class Training2Service {
simulation.removeJob(EXECUTE_JOB_NAME); //移除实训执行任务 simulation.removeJob(EXECUTE_JOB_NAME); //移除实训执行任务
} }
// 去除指标计算任务 // 去除指标计算任务
if (training2 != null && !CollectionUtils.isEmpty(training2.getIndexList())) { if (simulation.getJobMap().containsKey(INDEX_JOB_NAME)) {
training2.getIndexList().stream().filter(index -> index.getType().isContinuity()) simulation.removeJob(INDEX_JOB_NAME);
.forEach(index -> {
String jobName = String.format(INDEX_JOB_NAME, index.getId());
if (simulation.getJobMap().containsKey(jobName)) {
simulation.removeJob(jobName); //移除指标执行任务
}
});
} }
} }
@ -674,18 +678,19 @@ public class Training2Service {
* 增加实训任务 * 增加实训任务
*/ */
private void addTrainingJob(Simulation simulation, Training2 training2) { private void addTrainingJob(Simulation simulation, Training2 training2) {
removeTrainingJob(simulation, training2); // 移除后再添加
removeTrainingJob(simulation);
simulation.addJobIfAbsent(EXECUTE_JOB_NAME, () -> this.run(simulation), RATE); simulation.addJobIfAbsent(EXECUTE_JOB_NAME, () -> this.run(simulation), RATE);
// 增加指标计算任务 // 增加指标计算任务
if (training2 != null && !CollectionUtils.isEmpty(training2.getIndexList())) { if (training2 != null && !CollectionUtils.isEmpty(training2.getIndexList())) {
training2.getIndexList().stream().filter(index -> index.getType().isContinuity()) Map<String, IndexAlgorithmService> trainIndexServiceMap = training2.getIndexAlgorithmMap();
.forEach(index -> { simulation.addJobIfAbsent(INDEX_JOB_NAME, () ->
String jobName = String.format(INDEX_JOB_NAME, index.getId()); training2.getIndexList().stream().filter(Index::isContinuity).forEach(index -> {
if (!simulation.getJobMap().containsKey(jobName)) { if (trainIndexServiceMap.containsKey(index.name())) {
simulation.addJobIfAbsent(jobName, trainIndexServiceMap.get(index.name()).calculation(simulation);
() -> training2.getIndexAlgorithmMap().get(index.getId()).calculation(simulation, null), RATE); //移除指标执行任务 }
} })
}); , RATE);
} }
} }

View File

@ -1,37 +1,30 @@
package club.joylink.rtss.services.training2.index; package club.joylink.rtss.services.training2.index;
import club.joylink.rtss.simulation.cbtc.Simulation; import club.joylink.rtss.simulation.cbtc.Simulation;
import org.springframework.util.CollectionUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.Map; import java.util.Map;
/** /**
* 指标计算统计接口 * 指标计算统计接口
*/ */
public abstract class IndexAlgorithmService<T> { public interface IndexAlgorithmService<R> {
/**
* 统计的指标结果
*/
private List<T> indexValList = new ArrayList<>();
/** /**
* 运行时计算 * 没参数计算
*/ */
public abstract void calculation(Simulation simulation, Map<String, Object> params); default void calculation(Simulation simulation) {
}
/**
* 操作触发时带有参数性
*/
default void calculation(Simulation simulation, Map<String, Object> params) {
}
/** /**
* 结束时统计 * 结束时统计
*/ */
public abstract T statistics(); R statistics();
/**
* 清理统计数据
*/
public void reset() {
if (!CollectionUtils.isEmpty(indexValList)) {
this.indexValList.clear();
}
}
} }

View File

@ -3,22 +3,22 @@ package club.joylink.rtss.services.training2.index.impl;
import club.joylink.rtss.services.training2.index.IndexAlgorithmService; import club.joylink.rtss.services.training2.index.IndexAlgorithmService;
import club.joylink.rtss.simulation.cbtc.Simulation; import club.joylink.rtss.simulation.cbtc.Simulation;
import club.joylink.rtss.simulation.cbtc.training2.index.IndexTestValue; import club.joylink.rtss.simulation.cbtc.training2.index.IndexTestValue;
import lombok.extern.slf4j.Slf4j;
import java.util.Map;
/** /**
* 持续性测试指标 * 指标计算统计实现
*/ */
public class IndexAlgorithmTestService extends IndexAlgorithmService<IndexTestValue> { @Slf4j
public class IndexAlgorithmTestService implements IndexAlgorithmService<IndexTestValue> {
@Override @Override
public void calculation(Simulation simulation, Map<String, Object> params) { public void calculation(Simulation simulation) {
System.out.println(this.hashCode() + " 计算"); log.info(this.getClass().getSimpleName() + "[" + this.hashCode() + "]任务持续 计算");
} }
@Override @Override
public IndexTestValue statistics() { public IndexTestValue statistics() {
System.out.println(this.hashCode() + "统计"); log.info(this.getClass().getSimpleName() + "[" + this.hashCode() + "] 统计");
return null; return null;
} }
} }

View File

@ -0,0 +1,25 @@
package club.joylink.rtss.services.training2.index.impl;
import club.joylink.rtss.services.training2.index.IndexAlgorithmService;
import club.joylink.rtss.simulation.cbtc.Simulation;
import club.joylink.rtss.simulation.cbtc.training2.index.IndexTestValue;
import lombok.extern.slf4j.Slf4j;
import java.util.Map;
/**
* 指标计算统计实现
*/
@Slf4j
public class IndexTriggeredTestService implements IndexAlgorithmService<IndexTestValue> {
@Override
public void calculation(Simulation simulation, Map<String, Object> params) {
log.info(this.getClass().getSimpleName() + "[" + this.hashCode() + "]操作触发 计算");
}
@Override
public IndexTestValue statistics() {
log.info(this.getClass().getSimpleName() + "[" + this.hashCode() + "] 统计");
return null;
}
}

View File

@ -64,7 +64,7 @@ public class DisCmd {
/** /**
* 调度命令类型 * 调度命令类型
*/ */
private Type type; private Type type = Type.Undefined;
/** /**
* 调度命令正文 * 调度命令正文
*/ */
@ -84,10 +84,11 @@ public class DisCmd {
* 调度命令类型 * 调度命令类型
*/ */
public enum Type { public enum Type {
Undefined,
/** /**
* 正常调度命令 * 正常调度命令
*/ */
NORMAL, Normal,
; ;
} }

View File

@ -62,7 +62,7 @@ public class DisCmdRcvCompany {
/** /**
* 最终受令端对于调度命令的状态 * 最终受令端对于调度命令的状态
*/ */
private Status state; private Status state = Status.Undefined;
/** /**
* 最终受令端对于调度命令的接收时间 * 最终受令端对于调度命令的接收时间
*/ */
@ -73,12 +73,13 @@ public class DisCmdRcvCompany {
private LocalDateTime signTime; private LocalDateTime signTime;
/** /**
* 最终受令端对于调度命令的实际签收人 * 最终受令端对于调度命令的实际签收人
* @see SimulationMember#getUserId()
*/ */
private SimulationMember signByReal; private String signByReal;
/** /**
* 无线调度命令的中转站对调度命令的状态 * 无线调度命令的中转站对调度命令的状态
*/ */
private TransStatus transStatus; private TransStatus transStatus = TransStatus.Undefined;
/** /**
* 无线调度命令的中转站对调度命令的接收时间 * 无线调度命令的中转站对调度命令的接收时间
*/ */
@ -111,6 +112,7 @@ public class DisCmdRcvCompany {
* 发令单位类型 * 发令单位类型
*/ */
public enum Type { public enum Type {
Undefined,
Dispatcher,//调度台 Dispatcher,//调度台
Station,//车站 Station,//车站
Train,//无线 Train,//无线
@ -122,6 +124,7 @@ public class DisCmdRcvCompany {
* 受令单位对于调度命令的状态 * 受令单位对于调度命令的状态
*/ */
public enum Status { public enum Status {
Undefined,
Received,//接收 Received,//接收
Signed,//签收 Signed,//签收
; ;
@ -131,6 +134,7 @@ public class DisCmdRcvCompany {
* 无线调度命令时中转站对于调度命令的状态 * 无线调度命令时中转站对于调度命令的状态
*/ */
public enum TransStatus { public enum TransStatus {
Undefined,
Received,//接收 Received,//接收
Sent,//发送 Sent,//发送
; ;

View File

@ -12,7 +12,7 @@ public class DisCmdSendCompany {
/** /**
* 发令单位类型 * 发令单位类型
*/ */
private Type type; private Type type = Type.Undefined;
/** /**
* 发令单位名称 * 发令单位名称
*/ */
@ -29,7 +29,7 @@ public class DisCmdSendCompany {
/** /**
* 调度命令对应发令单的状态 * 调度命令对应发令单的状态
*/ */
private Status state; private Status state = Status.Undefined;
/** /**
* 发令时间 * 发令时间
*/ */
@ -48,6 +48,7 @@ public class DisCmdSendCompany {
* 发令单位类型 * 发令单位类型
*/ */
public enum Type { public enum Type {
Undefined,
Dispatcher,//调度台 Dispatcher,//调度台
Station,//车站 Station,//车站
; ;
@ -57,6 +58,7 @@ public class DisCmdSendCompany {
* 发令单位对调度命令的状态 * 发令单位对调度命令的状态
*/ */
public enum Status { public enum Status {
Undefined,
Cache,//缓存 Cache,//缓存
Send,//发送 Send,//发送
Signed,//签收完成(所有受令者签收完成) Signed,//签收完成(所有受令者签收完成)

View File

@ -4,10 +4,12 @@ import club.joylink.rtss.exception.BusinessExceptionAssertEnum;
import club.joylink.rtss.simulation.cbtc.CTC.data.CtcRepository; import club.joylink.rtss.simulation.cbtc.CTC.data.CtcRepository;
import club.joylink.rtss.simulation.cbtc.CTC.rail.cmd.convertor.DisCmdConvertor; import club.joylink.rtss.simulation.cbtc.CTC.rail.cmd.convertor.DisCmdConvertor;
import club.joylink.rtss.simulation.cbtc.CTC.rail.cmd.vo.DisCmdHolderEnum; import club.joylink.rtss.simulation.cbtc.CTC.rail.cmd.vo.DisCmdHolderEnum;
import club.joylink.rtss.simulation.cbtc.CTC.rail.cmd.vo.DisCmdVo; import club.joylink.rtss.simulation.cbtc.CTC.rail.cmd.vo.DisCmdRspVo;
import club.joylink.rtss.simulation.cbtc.CTC.rail.cmd.vo.DisCmdSrcVo;
import club.joylink.rtss.simulation.cbtc.CTC.rail.cmd.vo.FindAllDisCmdForHolderRspVo; import club.joylink.rtss.simulation.cbtc.CTC.rail.cmd.vo.FindAllDisCmdForHolderRspVo;
import club.joylink.rtss.simulation.cbtc.Simulation; import club.joylink.rtss.simulation.cbtc.Simulation;
import club.joylink.rtss.simulation.cbtc.data.map.Station; import club.joylink.rtss.simulation.cbtc.data.map.Station;
import club.joylink.rtss.simulation.cbtc.data.vr.VirtualRealityTrain;
import club.joylink.rtss.simulation.cbtc.member.SimulationMember; import club.joylink.rtss.simulation.cbtc.member.SimulationMember;
import club.joylink.rtss.vo.client.SocketMessageVO; import club.joylink.rtss.vo.client.SocketMessageVO;
import club.joylink.rtss.vo.client.factory.SocketMessageFactory; import club.joylink.rtss.vo.client.factory.SocketMessageFactory;
@ -37,9 +39,14 @@ public class DisCmdService {
/** /**
* 保存调度命令,保存到发送方缓存箱(保存到仓库) * 保存调度命令,保存到发送方缓存箱(保存到仓库)
*/ */
public void save(Simulation simulation,DisCmd disCmd){ public void save(Simulation simulation, DisCmdSrcVo disCmdVo){
// DisCmd disCmd = DisCmdConvertor.convert(disCmdVo);
CtcRepository ctcRepository = simulation.getCtcRepository(); CtcRepository ctcRepository = simulation.getCtcRepository();
//为受令记录生成id
disCmd.getRcvCompanies().forEach(rc->{
rc.setId(String.valueOf(ctcRepository.getDisCmdRcvCompanyIdGenerator().getAndIncrement()));
});
//
ctcRepository.getDisCmdMap().put(disCmd.getCode(),disCmd); ctcRepository.getDisCmdMap().put(disCmd.getCode(),disCmd);
// //
disCmd.getSendCompany().setState(DisCmdSendCompany.Status.Cache); disCmd.getSendCompany().setState(DisCmdSendCompany.Status.Cache);
@ -157,7 +164,7 @@ public class DisCmdService {
// //
rc.setState(DisCmdRcvCompany.Status.Signed); rc.setState(DisCmdRcvCompany.Status.Signed);
rc.setSignTime(this.getNow(simulation)); rc.setSignTime(this.getNow(simulation));
rc.setSignByReal(signer); rc.setSignByReal(signer.getUserId());
} }
/** /**
* 监控调度命令 * 监控调度命令
@ -181,8 +188,6 @@ public class DisCmdService {
} }
} }
//todo: 根据监控向前端推送其他通知 //todo: 根据监控向前端推送其他通知
}); });
} }
@ -260,7 +265,7 @@ public class DisCmdService {
} }
// //
if(hasCmd){ if(hasCmd){
DisCmdVo cmdVo = DisCmdConvertor.convert(cmd); DisCmdRspVo cmdVo = DisCmdConvertor.convert(cmd);
rsp.getCmdMap().put(cmdVo.getCode(),cmdVo); rsp.getCmdMap().put(cmdVo.getCode(),cmdVo);
} }
@ -274,11 +279,12 @@ public class DisCmdService {
* 注意如果向列控服务器推送通知则系统自动处理通知签收 * 注意如果向列控服务器推送通知则系统自动处理通知签收
*/ */
private void sendNotifyToRcvCompany(Simulation simulation,DisCmdRcvCompany rc){ private void sendNotifyToRcvCompany(Simulation simulation,DisCmdRcvCompany rc){
DisCmdVo disCmdVo = DisCmdConvertor.convert(this.find(simulation,rc.getDisCmdCode())); DisCmdRspVo disCmdVo = DisCmdConvertor.convert(this.find(simulation,rc.getDisCmdCode()));
disCmdVo.setRcId(rc.getId());
// //
WebSocketMessage<DisCmdVo.WsMsgType, DisCmdVo> messageBody WebSocketMessage<DisCmdRspVo.WsMsgType, DisCmdRspVo> messageBody
= new WebSocketMessage<>(DisCmdVo.WsMsgType.ADD, disCmdVo); = new WebSocketMessage<>(DisCmdRspVo.WsMsgType.ADD, disCmdVo);
SocketMessageVO<WebSocketMessage<DisCmdVo.WsMsgType, DisCmdVo>> message SocketMessageVO<WebSocketMessage<DisCmdRspVo.WsMsgType, DisCmdRspVo>> message
= SocketMessageFactory.buildDispatchCommandMessage2(simulation.getId(), messageBody); = SocketMessageFactory.buildDispatchCommandMessage2(simulation.getId(), messageBody);
// //
if(DisCmdRcvCompany.Type.Station.equals(rc.getType())){//向车站的相关成员发送通知 if(DisCmdRcvCompany.Type.Station.equals(rc.getType())){//向车站的相关成员发送通知
@ -288,6 +294,25 @@ public class DisCmdService {
.collect(Collectors.toSet()); .collect(Collectors.toSet());
stompMessageService.sendToUser(receiverUserIds,message); stompMessageService.sendToUser(receiverUserIds,message);
} }
}else if(DisCmdRcvCompany.Type.Dispatcher.equals(rc.getType())){
//todo: 调度台暂时没有
log.warn("==>>调度台不存在,不能推送通知!");
}else if(DisCmdRcvCompany.Type.Tsr.equals(rc.getType())){
//todo: 列控服务器暂时没有
log.warn("==>>列控服务器不存在,不能推送通知!");
}else if(DisCmdRcvCompany.Type.Train.equals(rc.getType())){
//车次号
String trainNum = rc.getTrainNum();
//机车号
String trainCode = rc.getTrainCode();
List<VirtualRealityTrain> trains = simulation.getRepository().getOnlineTrainList().stream().filter(tr->{return tr.getTripNumber().equals(trainNum);}).collect(Collectors.toList());
if(null!=trains&&!trains.isEmpty()){
VirtualRealityTrain train = trains.get(0);
//查找该次列车的司机向司机推送通知
Set<String> receiverUserIds = simulation.getSimulationMembersByDevice(train).stream().map(club.joylink.rtss.simulation.SimulationMember::getUserId)
.collect(Collectors.toSet());
stompMessageService.sendToUser(receiverUserIds,message);
}
} }
} }
/** /**
@ -299,6 +324,7 @@ public class DisCmdService {
*/ */
private boolean checkTrainInStation(Simulation simulation,String trainNum,String trainCode,String stationCode){ private boolean checkTrainInStation(Simulation simulation,String trainNum,String trainCode,String stationCode){
//todo //todo
return true; return true;
} }
/** /**

View File

@ -5,20 +5,115 @@ import club.joylink.rtss.simulation.cbtc.CTC.rail.cmd.DisCmdRcvCompany;
import club.joylink.rtss.simulation.cbtc.CTC.rail.cmd.DisCmdSendCompany; import club.joylink.rtss.simulation.cbtc.CTC.rail.cmd.DisCmdSendCompany;
import club.joylink.rtss.simulation.cbtc.CTC.rail.cmd.vo.DisCmdRcvCompanyVo; import club.joylink.rtss.simulation.cbtc.CTC.rail.cmd.vo.DisCmdRcvCompanyVo;
import club.joylink.rtss.simulation.cbtc.CTC.rail.cmd.vo.DisCmdSendCompanyVo; import club.joylink.rtss.simulation.cbtc.CTC.rail.cmd.vo.DisCmdSendCompanyVo;
import club.joylink.rtss.simulation.cbtc.CTC.rail.cmd.vo.DisCmdVo; import club.joylink.rtss.simulation.cbtc.CTC.rail.cmd.vo.DisCmdRspVo;
import club.joylink.rtss.simulation.cbtc.CTC.rail.cmd.vo.DisCmdSrcVo;
import java.util.stream.Collectors;
public class DisCmdConvertor { public class DisCmdConvertor {
public static DisCmdVo convert(DisCmd from){ public static DisCmdRspVo convert(DisCmd from){
DisCmdRspVo to = new DisCmdRspVo();
return null; to.setAuthState(from.getAuthState());
to.setCode(from.getCode());
to.setAuthTime(from.getAuthTime());
to.setContent(from.getContent());
to.setChiefOnDuty(from.getChiefOnDuty());
to.setChiefOnDutyAuth(from.getChiefOnDutyAuth());
to.setDesigner(from.getDesigner());
to.setSender(from.getSender());
to.setDailyPlanNum(from.getDailyPlanNum());
to.setFinishedTime(from.getFinishedTime());
to.setReviewer(from.getReviewer());
to.setSendTime(from.getSendTime());
to.setTitle(from.getTitle());
to.setTransitId(from.getTransitId());
to.setType(from.getType().name());
to.setSendCompany(DisCmdConvertor.convert(from.getSendCompany()));
return to;
} }
public static DisCmdSendCompanyVo convert(DisCmdSendCompany from){ public static DisCmdSendCompanyVo convert(DisCmdSendCompany from){
DisCmdSendCompanyVo to = new DisCmdSendCompanyVo();
return null; to.setDisCmdCode(from.getDisCmdCode());
to.setCode(from.getCode());
to.setName(from.getName());
to.setSendTime(from.getSendTime());
to.setType(from.getType().name());
to.setState(from.getState().name());
to.setSignedTime(from.getSignedTime());
return to;
}
public static DisCmdSendCompany convert(DisCmdSendCompanyVo from){
DisCmdSendCompany to = new DisCmdSendCompany();
to.setDisCmdCode(from.getDisCmdCode());
to.setCode(from.getCode());
to.setName(from.getName());
to.setSendTime(from.getSendTime());
to.setType(DisCmdSendCompany.Type.valueOf(from.getType()));
to.setState(DisCmdSendCompany.Status.valueOf(from.getState()));
to.setSignedTime(from.getSignedTime());
return to;
} }
public static DisCmdRcvCompanyVo convert(DisCmdRcvCompany from){ public static DisCmdRcvCompanyVo convert(DisCmdRcvCompany from){
DisCmdRcvCompanyVo to = new DisCmdRcvCompanyVo();
return null; to.setDisCmdCode(from.getDisCmdCode());
to.setDisCode(from.getDisCode());
to.setId(from.getId());
to.setName(from.getName());
to.setState(from.getState().name());
to.setSignByReal(from.getSignByReal());
to.setReceiveTime(from.getReceiveTime());
to.setSignTime(from.getSignTime());
to.setStationCode(from.getStationCode());
to.setTrainCode(from.getTrainCode());
to.setTrainViaGsmR(from.getTrainViaGsmR());
to.setTrainNum(from.getTrainNum());
to.setTransReceiveTime(from.getTransReceiveTime());
to.setTransStationCode(from.getTransStationCode());
to.setTsrCode(from.getTsrCode());
to.setTransSendTime(from.getTransSendTime());
to.setType(from.getType().name());
to.setTransStatus(from.getTransStatus().name());
return to;
}
public static DisCmdRcvCompany convert(DisCmdRcvCompanyVo from){
DisCmdRcvCompany to = new DisCmdRcvCompany();
to.setDisCmdCode(from.getDisCmdCode());
to.setDisCode(from.getDisCode());
to.setId(from.getId());
to.setName(from.getName());
to.setState(DisCmdRcvCompany.Status.valueOf(from.getState()));
to.setSignByReal(from.getSignByReal());
to.setReceiveTime(from.getReceiveTime());
to.setSignTime(from.getSignTime());
to.setStationCode(from.getStationCode());
to.setTrainCode(from.getTrainCode());
to.setTrainViaGsmR(from.getTrainViaGsmR());
to.setTrainNum(from.getTrainNum());
to.setTransReceiveTime(from.getTransReceiveTime());
to.setTransStationCode(from.getTransStationCode());
to.setTsrCode(from.getTsrCode());
to.setTransSendTime(from.getTransSendTime());
to.setType(DisCmdRcvCompany.Type.valueOf(from.getType()));
to.setTransStatus(DisCmdRcvCompany.TransStatus.valueOf(from.getTransStatus()));
return to;
}
public static DisCmd convert(DisCmdSrcVo from){
DisCmd to = new DisCmd();
to.setAuthState(from.getAuthState());
to.setCode(from.getCode());
to.setContent(from.getContent());
to.setChiefOnDuty(from.getChiefOnDuty());
to.setChiefOnDutyAuth(from.getChiefOnDutyAuth());
to.setDesigner(from.getDesigner());
to.setSender(from.getSender());
to.setDailyPlanNum(from.getDailyPlanNum());
to.setReviewer(from.getReviewer());
to.setTitle(from.getTitle());
to.setTransitId(from.getTransitId());
to.setType(DisCmd.Type.valueOf(from.getType()));
//
to.setSendCompany(DisCmdConvertor.convert(from.getSendCompany()));
to.setRcvCompanies(from.getRcvCompanies().stream().map(rcVo->{return DisCmdConvertor.convert(rcVo);}).collect(Collectors.toList()));
return to;
} }
} }

View File

@ -1,14 +1,95 @@
package club.joylink.rtss.simulation.cbtc.CTC.rail.cmd.vo; package club.joylink.rtss.simulation.cbtc.CTC.rail.cmd.vo;
import club.joylink.rtss.simulation.cbtc.CTC.rail.cmd.DisCmdRcvCompany;
import club.joylink.rtss.simulation.cbtc.member.SimulationMember;
import lombok.Data; import lombok.Data;
import java.time.LocalDateTime;
/** /**
* 受令单位 * 受令单位
*/ */
@Data @Data
public class DisCmdRcvCompanyVo { public class DisCmdRcvCompanyVo {
/** /**
* 调度命令号(唯一) * 调度命令号(唯一)
*/ */
private String disCmdCode; private String disCmdCode;
/**
* 唯一id,受令单位记录id
*/
private String id;
/**
* 受令单位类型
* @see DisCmdRcvCompany.Type
*/
private String type = "Undefined";
/**
* 受令单位名称
*/
private String name;
//////////////////受令者/////////////////////
/**
* 车站受令者code
*/
private String stationCode;
/**
* 调度台受令者code
*/
private String disCode;
/**
* 列控服务器受令者code
*/
private String tsrCode;
//////////////////受令者train////////////////////////
/**
* 无线调度命令true-通过手机移动网络直接发送false-通过车站专有网络发送
*/
private Boolean trainViaGsmR = true;
/**
* 中转车站code
* <p>
* 当trainViaGsmR=false时不为空
*/
private String transStationCode;
/**
* 车次号
*/
private String trainNum;
/**
* 机车号(train code)
*/
private String trainCode;
/////////////////////运行时数据//////////////////
/**
* 最终受令端对于调度命令的状态
* @see DisCmdRcvCompany.Status
*/
private String state = "Undefined";
/**
* 最终受令端对于调度命令的接收时间
*/
private LocalDateTime receiveTime;
/**
* 最终受令端对于调度命令的签收时间
*/
private LocalDateTime signTime;
/**
* 最终受令端对于调度命令的实际签收人id
* @see SimulationMember#getUserId()
*/
private String signByReal;
/**
* 无线调度命令的中转站对调度命令的状态
* @see DisCmdRcvCompany.TransStatus
*/
private String transStatus = "Undefined";
/**
* 无线调度命令的中转站对调度命令的接收时间
*/
private LocalDateTime transReceiveTime;
/**
* 无线调度命令的中转站对调度命令的发送时间
*/
private LocalDateTime transSendTime;
} }

View File

@ -0,0 +1,101 @@
package club.joylink.rtss.simulation.cbtc.CTC.rail.cmd.vo;
import club.joylink.rtss.simulation.cbtc.CTC.rail.cmd.DisCmd;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
/**
* 响应给客户端调度命令记录
*/
@Data
public class DisCmdRspVo {
/**
* 标题
*/
private String title;
/**
* 调度命令号(唯一)
*/
private String code;
/**
* 中转识别号
*/
private String transitId;
/**
* 发令时间
*/
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime sendTime;
/**
* 发令人
*/
private String sender;
/**
* 授权时间
*/
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime authTime;
/**
* 值班主任(仿真成员)
*/
private String chiefOnDuty;
/**
* 需值班主任授权
*/
private Boolean chiefOnDutyAuth = false;
/**
* 授权状态
*/
private String authState;
/**
* 定稿时间
*/
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime finishedTime;
/**
* 审核人(仿真成员)
*/
private String reviewer;
/**
* 日计划号
*/
private String dailyPlanNum;
/**
* 拟令人(起草者设计者)
*/
private String designer;
/**
* 调度命令类型
* @see DisCmd.Type
*/
private String type = "Undefined";
/**
* 调度命令正文
*/
private String content;
///////////////////////////////////////
/**
* 发令单位
*/
private DisCmdSendCompanyVo sendCompany;
///////////////////////////////////////
/**
* 受令单位记录唯一id仅在向前端推送通知时有效
*/
private String rcId;
////////////////////////////////////////
/**
* webSocket消息类型
*/
public enum WsMsgType {
ALL,
ADD,
UPDATE,
DELETE,
}
}

View File

@ -1,14 +1,50 @@
package club.joylink.rtss.simulation.cbtc.CTC.rail.cmd.vo; package club.joylink.rtss.simulation.cbtc.CTC.rail.cmd.vo;
import club.joylink.rtss.simulation.cbtc.CTC.rail.cmd.DisCmdSendCompany;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data; import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
/** /**
* 发令单位 * 发令单位
*/ */
@Data @Data
public class DisCmdSendCompanyVo { public class DisCmdSendCompanyVo {
/**
* 发令单位类型
* @see DisCmdSendCompany.Type
*/
private String type = "Undefined";
/**
* 发令单位名称
*/
private String name;
/**
* 发令单位code
*/
private String code;
/** /**
* 调度命令号(唯一) * 调度命令号(唯一)
*/ */
private String disCmdCode; private String disCmdCode;
//////////////////运行时数据////////////////
/**
* 调度命令对应发令单的状态
* @see DisCmdSendCompany.Status
*/
private String state = "Undefined";
/**
* 发令时间
*/
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime sendTime;
/**
* 签收完成时间
*/
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime signedTime;
} }

View File

@ -0,0 +1,70 @@
package club.joylink.rtss.simulation.cbtc.CTC.rail.cmd.vo;
import club.joylink.rtss.simulation.cbtc.CTC.rail.cmd.DisCmd;
import lombok.Data;
import java.util.List;
/**
* 创建调度命令的源客户端(调度台或车站)发送来的调度命令原始信息
*/
@Data
public class DisCmdSrcVo {
/**
* 标题
*/
private String title;
/**
* 调度命令号(唯一)
*/
private String code;
/**
* 中转识别号
*/
private String transitId;
/**
* 发令人
*/
private String sender;
/**
* 值班主任(仿真成员)
*/
private String chiefOnDuty;
/**
* 需值班主任授权
*/
private Boolean chiefOnDutyAuth = false;
/**
* 授权状态
*/
private String authState;
/**
* 审核人(仿真成员)
*/
private String reviewer;
/**
* 日计划号
*/
private String dailyPlanNum;
/**
* 拟令人(起草者设计者)
*/
private String designer;
/**
* 调度命令类型
* @see DisCmd.Type
*/
private String type = "Undefined";
/**
* 调度命令正文
*/
private String content;
///////////////////////////////////////
/**
* 发令单位
*/
private DisCmdSendCompanyVo sendCompany;
/**
* 受令单位列表
*/
private List<DisCmdRcvCompanyVo> rcvCompanies;
}

View File

@ -1,25 +0,0 @@
package club.joylink.rtss.simulation.cbtc.CTC.rail.cmd.vo;
import lombok.Data;
@Data
public class DisCmdVo {
/**
* 标题
*/
private String title;
/**
* 调度命令号(唯一)
*/
private String code;
///////////////////////////////////////
/**
* webSocket消息类型
*/
public enum WsMsgType {
ALL,
ADD,
UPDATE,
DELETE,
}
}

View File

@ -28,7 +28,7 @@ public class FindAllDisCmdForHolderRspVo {
/** /**
* 调度命令列表 * 调度命令列表
*/ */
private Map<String, DisCmdVo> cmdMap = new HashMap<>(); private Map<String, DisCmdRspVo> cmdMap = new HashMap<>();
/** /**
* 调度命令发令单位 * 调度命令发令单位
*/ */

View File

@ -14,6 +14,7 @@ import club.joylink.rtss.vo.client.training2.ScoringRuleVO;
import club.joylink.rtss.vo.client.training2.Step2VO; import club.joylink.rtss.vo.client.training2.Step2VO;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import org.springframework.beans.BeanUtils;
import org.springframework.util.CollectionUtils; import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
@ -95,7 +96,7 @@ public class Training2 {
/** /**
* 指标处理逻辑 * 指标处理逻辑
*/ */
private Map<Integer, IndexAlgorithmService> indexAlgorithmMap; private Map<String, IndexAlgorithmService> indexAlgorithmMap;
public Training2(DraftTraining2WithBLOBs draftTraining2, Simulation simulation) { public Training2(DraftTraining2WithBLOBs draftTraining2, Simulation simulation) {
this.id = draftTraining2.getId(); this.id = draftTraining2.getId();
@ -126,29 +127,6 @@ public class Training2 {
ExpressionVO evo = JsonUtils.read(draftTraining2.getFailureConditionJson(), ExpressionVO.class); ExpressionVO evo = JsonUtils.read(draftTraining2.getFailureConditionJson(), ExpressionVO.class);
this.failureCondition = evo.convert2BO(simulation.getRepository()); this.failureCondition = evo.convert2BO(simulation.getRepository());
} }
Index index1 = new Index();
index1.setId(1);
index1.setName("指标1");
index1.setType(Index.Type.TRIGGERED_TEST_INDEX);
Index index2 = new Index();
index2.setId(2);
index2.setName("指标2");
index2.setType(Index.Type.CONTINUITY_TEST_INDEX);
this.indexList = (Arrays.asList(index1, index2));
if (!CollectionUtils.isEmpty(this.indexList)) {
this.indexAlgorithmMap = new HashMap<>(this.indexList.size());
this.indexList.stream().forEach(index -> {
try {
IndexAlgorithmService service =
(IndexAlgorithmService) index.getType().getAlgorithmService().getDeclaredConstructor().newInstance();
this.indexAlgorithmMap.put(index.getId(), service);
} catch (Exception e) {
}
});
} else {
this.indexAlgorithmMap = new HashMap<>();
}
} }
public void start(ScriptBO.Mode mode) { public void start(ScriptBO.Mode mode) {
@ -237,8 +215,12 @@ public class Training2 {
this.steps.forEach(Step2::reset); this.steps.forEach(Step2::reset);
} }
// 重置时清空 // 重置时清空
if (!CollectionUtils.isEmpty(this.indexAlgorithmMap)) { if (!CollectionUtils.isEmpty(this.indexList)) {
this.indexAlgorithmMap.forEach((k, v) -> v.reset()); this.indexAlgorithmMap = new HashMap<>(this.indexList.size());
this.indexList.forEach(index -> this.indexAlgorithmMap.put(index.name(),
BeanUtils.instantiateClass(index.getAlgorithmService(), IndexAlgorithmService.class)));
} else {
this.indexAlgorithmMap = new HashMap<>();
} }
} }

View File

@ -1,57 +1,35 @@
package club.joylink.rtss.simulation.cbtc.training2.index; package club.joylink.rtss.simulation.cbtc.training2.index;
import club.joylink.rtss.services.training2.index.impl.IndexAlgorithmTestService; import club.joylink.rtss.services.training2.index.impl.IndexAlgorithmTestService;
import club.joylink.rtss.services.training2.index.impl.IndexTriggeredTestService;
import club.joylink.rtss.simulation.cbtc.ATS.operation.Operation; import club.joylink.rtss.simulation.cbtc.ATS.operation.Operation;
import lombok.Getter; import lombok.Getter;
import lombok.Setter;
import java.util.Arrays;
import java.util.List;
@Getter @Getter
@Setter public enum Index {
public class Index { TRIGGERED_TEST_INDEX("触发式测试指标", "", false,
private int id; IndexTriggeredTestService.class, Arrays.asList(Operation.Type.Signal_Set_Route)),
/** CONTINUITY_TEST_INDEX("连续式测试指标", "", true,
* 指标名称 IndexAlgorithmTestService.class, null),
*/ ;
private String name;
/** private final String name; // 指标名称
* 指标描述 private final String description; // 指标说明
*/ private final boolean continuity; // 频率 ture:连续性计算false:触发性计算
private String description;
/** private final Class<?> algorithmService; // 指标计算统计service类名
* 指标类型
*/
private Type type;
@Getter private final List<Operation.Type> operationType; // 触发式指标事件类型
public enum Type {
/**
* 触发式测试指标
*/
TRIGGERED_TEST_INDEX(1, IndexAlgorithmTestService.class, Operation.Type.Signal_Set_Route),
/** Index(String name, String description, boolean continuity, Class<?> algorithmService, List<Operation.Type> operationType) {
* 连续式测试指标 this.name = name;
*/ this.description = description;
CONTINUITY_TEST_INDEX(0, IndexAlgorithmTestService.class, null), this.continuity = continuity;
; this.algorithmService = algorithmService;
this.operationType = operationType;
private int rate; // 频率 0:连续性计算1:触发性计算
private Class algorithmService; // 指标计算统计service类名
private Operation.Type operationType; // 触发式指标事件类型
Type(int rate, Class algorithmService, Operation.Type operationType) {
this.rate = rate;
this.algorithmService = algorithmService;
this.operationType = operationType;
}
public boolean isContinuity() {
return this.rate == 0;
}
} }
} }

View File

@ -6,7 +6,7 @@ import club.joylink.rtss.simulation.cbtc.CTC.data.Ticket;
import club.joylink.rtss.simulation.cbtc.CTC.data.vo.BusyBoardVO; import club.joylink.rtss.simulation.cbtc.CTC.data.vo.BusyBoardVO;
import club.joylink.rtss.simulation.cbtc.CTC.data.vo.CtcStationRunPlanLogVO; import club.joylink.rtss.simulation.cbtc.CTC.data.vo.CtcStationRunPlanLogVO;
import club.joylink.rtss.simulation.cbtc.CTC.data.vo.RailDispatchCommandVO; import club.joylink.rtss.simulation.cbtc.CTC.data.vo.RailDispatchCommandVO;
import club.joylink.rtss.simulation.cbtc.CTC.rail.cmd.vo.DisCmdVo; import club.joylink.rtss.simulation.cbtc.CTC.rail.cmd.vo.DisCmdRspVo;
import club.joylink.rtss.simulation.cbtc.Simulation; import club.joylink.rtss.simulation.cbtc.Simulation;
import club.joylink.rtss.simulation.cbtc.communication.vo.TrainPosition; import club.joylink.rtss.simulation.cbtc.communication.vo.TrainPosition;
import club.joylink.rtss.simulation.cbtc.conversation.Conversation; import club.joylink.rtss.simulation.cbtc.conversation.Conversation;
@ -440,8 +440,8 @@ public class SocketMessageFactory {
/** /**
* CTC调度命令消息2 * CTC调度命令消息2
*/ */
public static SocketMessageVO<WebSocketMessage<DisCmdVo.WsMsgType, DisCmdVo>> buildDispatchCommandMessage2 public static SocketMessageVO<WebSocketMessage<DisCmdRspVo.WsMsgType, DisCmdRspVo>> buildDispatchCommandMessage2
(String simulationId, WebSocketMessage<DisCmdVo.WsMsgType, DisCmdVo> message) { (String simulationId, WebSocketMessage<DisCmdRspVo.WsMsgType, DisCmdRspVo> message) {
return build(WebSocketMessageType.SIMULATION_RAIL_CTC_DISPATCH_COMMAND, simulationId, message); return build(WebSocketMessageType.SIMULATION_RAIL_CTC_DISPATCH_COMMAND, simulationId, message);
} }