Merge branch 'test-training2' of https://git.code.tencent.com/lian-cbtc/rtss-server into test-ncc

 Conflicts:
	rtss/src/main/java/club/joylink/rtss/services/training2/Training2DraftService.java
	rtss/src/main/java/club/joylink/rtss/simulation/cbtc/CI/device/CiRouteService.java
	rtss/src/main/java/club/joylink/rtss/vo/client/mapFunction/RtsMapFunctionDescModifyVO.java
	rtss/src/main/java/club/joylink/rtss/vo/training2/draft/UpdateStepReqVo.java
This commit is contained in:
tiger_zhou 2023-02-20 09:29:54 +08:00
commit 9dcaeba9ca
25 changed files with 290 additions and 303 deletions

View File

@ -109,6 +109,14 @@ public class MapFunctionController {
rtsMapFunctionService.updateGroup(groupMap, user.getId());
}
/**
* 批量修改描述
*/
@PutMapping("/desc/batch")
public void batchModifyDesc(@RequestBody RtsMapFunctionDescModifyVO vo) {
rtsMapFunctionService.batchModifyDesc(vo);
}
@Autowired
private IMapService iMapService;
@Autowired

View File

@ -131,8 +131,8 @@ public class TrainingDraftV2Controller {
*/
@PutMapping("/{group}/{trainingId}/step/update")
public void updateSteps(@PathVariable("group") String group, @PathVariable("trainingId") Long trainingId
, @RequestBody List<Step2VO> step2VOList) {
training2DraftService.updateSteps(group, trainingId, step2VOList);
, @RequestBody UpdateStepReqVo reqParam) {
training2DraftService.updateSteps(group, trainingId, reqParam);
}
/**

View File

@ -1,9 +1,11 @@
package club.joylink.rtss.controller.training2;
import club.joylink.rtss.constants.RoleEnum;
import club.joylink.rtss.controller.advice.AuthenticateInterceptor;
import club.joylink.rtss.controller.advice.Role;
import club.joylink.rtss.services.training2.Training2PublishService;
import club.joylink.rtss.services.training2.Training2TypeEnum;
import club.joylink.rtss.vo.LoginUserInfoVO;
import club.joylink.rtss.vo.client.PageVO;
import club.joylink.rtss.vo.training2.publish.*;
import lombok.extern.slf4j.Slf4j;
@ -68,9 +70,11 @@ public class TrainingV2PublishController {
* @return
*/
@PostMapping("/infos")
public List<PublishedTraining2InfoRspVo> findTrainingListInfos(@RequestBody PublishedTrainingListRspVo vo){
public List<PublishedTraining2InfoRspVo> findTrainingListInfos(@RequestBody PublishedTrainingListRspVo vo
,@RequestAttribute(name = AuthenticateInterceptor.LOGIN_INFO_KEY) LoginUserInfoVO loginUserInfoVO){
//只查询以上架
vo.setState(1);
vo.setOrgId(loginUserInfoVO.getTopOrgId());
return this.publishService.findTrainingInfo(vo);
}
/**

View File

@ -50,4 +50,6 @@ public interface RtsMapFunctionService {
List<String> transferOldData(Long mapId);
void updateGroup(Map<String, List<Long>> groupMap, Long updaterId);
void batchModifyDesc(RtsMapFunctionDescModifyVO vo);
}

View File

@ -323,6 +323,21 @@ public class RtsMapFunctionServiceImpl implements RtsMapFunctionService {
});
}
@Override
public void batchModifyDesc(RtsMapFunctionDescModifyVO vo) {
BusinessExceptionAssertEnum.ARGUMENT_ILLEGAL.assertTrue(StringUtils.hasText(vo.getFunctionName()) || StringUtils.hasText(vo.getOriginalDesc()),
"功能名称和原描述至少填一个");
RtsMapFunctionExample example = new RtsMapFunctionExample();
if (StringUtils.hasText(vo.getFunctionName())) {
example.or().andNameEqualTo(vo.getFunctionName());
}
if (StringUtils.hasText(vo.getOriginalDesc())) {
example.or().andDescEqualTo(vo.getOriginalDesc());
}
rtsMapFunctionDAO.updateByExampleSelective(vo.convert2DB(), example);
}
private RtsMapFunctionCreateVO buildCreateVO(long mapId, String name, String desc, Simulation.Type simType, String group,
Map<SimulationWorkParamVO.Item, String> itemMap, SimulationWorkParamVO.DomConfigVO domConfig) {
RtsMapFunctionCreateVO createVO = new RtsMapFunctionCreateVO();
@ -402,7 +417,7 @@ public class RtsMapFunctionServiceImpl implements RtsMapFunctionService {
private Supplier<RtsMapFunctionCreateVO> getTrainingDesignFunctionSupplier(long mapId, Set<String> systemNameSet, List<String> msgList, String msgPrefix, Simulation.Type simType, Optional<MapMemberVO> dispatcherOptional) {
return () -> {
String name = "实训设计";
String desc = "辅助学员及老师完成自主线路设计的软件系统。设计完成后的线路能够进行校验、修正、列车运行等功能,能有效的帮助老师及学生完成课程设计";
String desc = "可编制单岗位的站场图设备操作或设计多岗位的脚本化场景以供单操实训或场景实训使用";
if (systemNameSet.contains(name)) {
msgList.add(String.format("%s已存在不生成", name));
return null;
@ -427,8 +442,7 @@ public class RtsMapFunctionServiceImpl implements RtsMapFunctionService {
//综合演练
return () -> {
String name = "综合演练";
String desc = "将不同岗位赋予不同的学员端,实现多岗位联合互动培训演练,通过场景脚本化技术,实现处置流程的多变性," +
"所有岗位的交互操作利用软件即可,不受硬件限制,增加实训的灵活性。同时也具备与硬件联动的接口和条件。";
String desc = "实现多岗位联合互动培训演练,以房间为单元,所有岗位人员实时在线参与,以模拟实际地铁运营中正常/非正常情况下的各岗位的处理能力。";
if (systemNameSet.contains(name)) {
msgList.add(String.format("%s已存在不生成", name));
return null;
@ -452,8 +466,7 @@ public class RtsMapFunctionServiceImpl implements RtsMapFunctionService {
private Supplier<RtsMapFunctionCreateVO> getExamFunctionSupplier(long mapId, Set<String> systemNameSet, List<String> msgList, Simulation.Type simType) {
return () -> {
String name = "考试";
String desc = "考试系统模块具有自定义考试规则、自动生成考卷、学员成绩统计、数据曲线分析及题库管理等功能," +
"从实战操作、业务流程、故障模拟及考试规则等多角度出发,形成最符合用户需求的城市轨道交通在线交互实操类考试系统。";
String desc = "从理论、单操实训、场景实训三个方面进行设计、用户可在该功能中在线实时考试,自动评分。";
if (systemNameSet.contains(name)) {
msgList.add(String.format("%s已存在不生成", name));
return null;
@ -470,7 +483,7 @@ public class RtsMapFunctionServiceImpl implements RtsMapFunctionService {
return () -> {
String name = "场景实训";
String desc = "以不同故障场景为剧本,培训各岗位在故障情境下的配合调度能力,包含各个故障场景下的标准应急流程及联动用语。" +
"如缺少人员,可由机器人顶替岗位";
"用户可选择某一角色进行练习,其他岗位由机器人自动应答指令,自动执行信号系统相关操作";
if (systemNameSet.contains(name)) {
msgList.add(String.format("%s已存在不生成", name));
return null;
@ -488,8 +501,7 @@ public class RtsMapFunctionServiceImpl implements RtsMapFunctionService {
private Supplier<RtsMapFunctionCreateVO> getSingleOperationTrainingFunctionSupplier(long mapId, Set<String> systemNameSet, List<String> msgList, Simulation.Type simType) {
return () -> {
String name = "单操实训";
String desc = "针对行调及行值人员的具体功能操作进行解析形成专业实操课程。" +
"单操实训系统具有教学、练习及测验三种模式,能使学员由浅及深,循序渐进的熟练掌握操作流程。";
String desc = "针对行调及行值人员的具体功能操作进行解析形成专业实操课程。单操实训系统具有教学、练习及测验三种模式。";
if (systemNameSet.contains(name)) {
msgList.add(String.format("%s已存在不生成", name));
return null;
@ -507,9 +519,7 @@ public class RtsMapFunctionServiceImpl implements RtsMapFunctionService {
Simulation.Type simType, List<MapMemberVO> mapMemberVOS) {
return () -> {
String name = "模拟驾驶";
String desc = "桌面版模拟驾驶仿真系统,使用鼠标操作。" +
"操作驾驶界面与真实车辆驾驶台保持一致,可完成对列车驾驶的操作动作、技术、规则和技巧的练习。" +
"能够实现与行车调度的联动培训,能够完成司机模拟驾驶培训。";
String desc = "桌面版模拟驾驶仿真系统,操作驾驶界面与真实车辆驾驶台保持一致,可完成对列车驾驶的操作动作、技术、规则和技巧的练习。";
if (systemNameSet.contains(name)) {
msgList.add(String.format("%s已存在不生成", name));
return null;
@ -536,8 +546,7 @@ public class RtsMapFunctionServiceImpl implements RtsMapFunctionService {
//ATS现地工作站
return () -> {
String name = "车站仿真";
String desc = "仿真真实设备集中站/非设备集中站行车值班员岗位操作系统,仿真系统可实现但不限于如下功能:" +
"站场图显示、进路办理/取消、信号控制、道岔操作、限速控制、车站控制模式转换。";
String desc = "车站仿真是面向地铁运营的行车值班员操作技能和专业能力培训的功能,能够实现设备的各种正常操作及常见故障仿真。";
if (systemNameSet.contains(name)) {
msgList.add(String.format("%s已存在不生成", name));
return null;
@ -561,8 +570,7 @@ public class RtsMapFunctionServiceImpl implements RtsMapFunctionService {
Simulation.Type simType, Optional<MapMemberVO> dispatcherOptional) {
return () -> {
String name = "调度仿真";
String desc = "模拟真实行车调度员岗位的操作系统,用于调度员完成调度和运营作业。调度员通过调度终端屏幕," +
"实时了解和掌握列车的实际运行情况,可以在调度工作站上发出指令,用于直接指挥列车运行。";
String desc = "调度仿真是面向地铁运营的行车调度员操作技能和专业能力培训的功能,能够实现设备的各种正常操作及常见故障仿真。";
if (systemNameSet.contains(name)) {
msgList.add(String.format("%s已存在不生成", name));
return null;
@ -670,7 +678,7 @@ public class RtsMapFunctionServiceImpl implements RtsMapFunctionService {
Simulation.Type simType, Optional<MapMemberVO> dispatcherOptional) {
return () -> {
String name = "派班";
String desc = "仿真真实派班员的岗位操作系统,与真实城轨派班员的工作站操控保持一致,学员可根据列车运行图要求和车辆完好情况," +
String desc = "模拟真实派班员的岗位操作系统,与真实城轨派班员的工作站操控保持一致,学员可根据列车运行图要求和车辆完好情况," +
"合理编排好司机每日运用车辆计划,系统也可自动生成派班计划,简化派班计划管理的复杂性。";
if (systemNameSet.contains(name)) {
msgList.add(String.format("%s已存在不生成", name));

View File

@ -90,7 +90,7 @@ public class OrgService implements IOrgService {
PageHelper.startPage(queryVO.getPageNum(), queryVO.getPageSize());
OrgExample example = new OrgExample();
OrgExample.Criteria criteria = example.createCriteria();
criteria.andParentIdIsNull();
criteria.andParentIdIsNull().andStatusEqualTo(BusinessConsts.Org.Status.VALID);
if (StringUtils.hasText(queryVO.getName())) {
criteria.andNameLike(String.format("%%%s%%", queryVO.getName()));
}

View File

@ -142,33 +142,31 @@ public class PermissionSubjectService {
//根据当前用户的项目code 获取所有的mapId
List<Long> projectMapIdList = this.findMapIdByProjectCode(projectCode);
List<SystemAbility> voList = this.systemAbilityService.findSystemAbilityByMapId(List.of(mapId));
List<PermissionSubjectVO> resultList = Lists.newArrayList();
//过滤当前项目的权限
//从当前用户所有权限获取所有权限类型为PROJECT && 数据== 用户项目code && 项目code对应的所有mapId == mapId入参
List<PermissionSubjectVO> projectVOList = subjectVOList.stream()
List<PermissionSubjectVO> projectMapVOList = subjectVOList.stream()
.filter(d->(Objects.equals(d.getPermissionType(), PermissionTypeEnum.PROJECT.getValue()))
&& Objects.equals(d.getPermissionProjectCode(),projectCode.toLowerCase()) && projectMapIdList.contains(mapId))
// && Objects.equals(d.getProjectCode(),projectCode.toLowerCase()) && projectMapIdList.contains(mapId))
.collect(Collectors.toList());
if(!CollectionUtils.isEmpty(projectVOList)){
this.createSystemAbilityVOForProejctOrMap(projectVOList,voList);
return projectVOList;
if(!CollectionUtils.isEmpty(projectMapVOList)){
this.createSystemAbilityVOForProejctOrMap(projectMapVOList,voList);
resultList.addAll(projectMapVOList);
}
//过滤当前线路权限
//当前是否是线路权限
List<PermissionSubjectVO> mapVOList = subjectVOList.stream()
List<PermissionSubjectVO> orgMapVOList = subjectVOList.stream()
.filter(d->(Objects.equals(d.getPermissionType(), PermissionTypeEnum.MAP_ID.getValue()))
&& Objects.equals(d.getMapId(), mapId)).collect(Collectors.toList());
if(!CollectionUtils.isEmpty(mapVOList)){
this.createSystemAbilityVOForProejctOrMap(mapVOList,voList);
return mapVOList;
}else {
//过滤当前线路功能权限
//过滤该用户拥有所有的权限并且mapId = 参数mapId
subjectVOList = subjectVOList.stream().filter(d-> Objects.equals(d.getMapId(), mapId)).collect(Collectors.toList());
this.createSystemAbilityVOForFunction(subjectVOList);
return subjectVOList;
if(!CollectionUtils.isEmpty(orgMapVOList)){
this.createSystemAbilityVOForProejctOrMap(orgMapVOList,voList);
resultList.addAll(orgMapVOList);
}
List<PermissionSubjectVO> abilityMapVOList = subjectVOList.stream().filter(d-> (Objects.equals(d.getPermissionType(), PermissionTypeEnum.MAP_ABILITY.getValue()))
&& Objects.equals(d.getMapId(), mapId)).collect(Collectors.toList());
this.createSystemAbilityVOForFunction(abilityMapVOList);
resultList.addAll(abilityMapVOList);
return resultList;
}
/**

View File

@ -4,7 +4,7 @@ import club.joylink.rtss.dao.DraftTraining2DAO;
import club.joylink.rtss.entity.training2.DraftTraining2;
import club.joylink.rtss.entity.training2.DraftTraining2Example;
import club.joylink.rtss.entity.training2.DraftTraining2WithBLOBs;
import club.joylink.exception.BusinessExceptionAssertEnum;
import club.joylink.rtss.exception.BusinessExceptionAssertEnum;
import club.joylink.rtss.simulation.cbtc.GroupSimulationService;
import club.joylink.rtss.simulation.cbtc.Simulation;
import club.joylink.rtss.simulation.cbtc.SimulationService;
@ -383,7 +383,7 @@ public class Training2DraftService {
* 修改实训所有步骤
*/
@Transactional(rollbackFor = Exception.class)
public void updateSteps(String group, Long trainingId, List<Step2VO> step2VOList) {
public void updateSteps(String group, Long trainingId, UpdateStepReqVo reqParam) {
DraftTraining2WithBLOBs draftTraining2 = trainingDao.selectByPrimaryKey(trainingId);
if (draftTraining2 == null) {
throw new SimulationException(SimulationExceptionType.Data_Not_Exist, "实训不存在");
@ -392,6 +392,7 @@ public class Training2DraftService {
Simulation simulation = this.groupSimulationService.getSimulationByGroup(group);
DraftTraining2WithBLOBs updateObj = new DraftTraining2WithBLOBs();
updateObj.setId(trainingId);
List<Step2VO> step2VOList = reqParam.getStep2VOList();
if (CollectionUtils.isEmpty(step2VOList)) {
updateObj.setStepJson(StringUtil.EMPTY_STRING);
updateObj.setScoringRuleJson(StringUtil.EMPTY_STRING);
@ -404,13 +405,10 @@ public class Training2DraftService {
handleStepId(draftTraining2, step2VOList);
updateObj.setStepJson(JsonUtils.writeValueAsString(step2VOList));
// 扮演者集合
List<String> playerList = step2VOList.stream().
filter(s -> !StringUtils.isEmpty(s.getMemberId())).map(s -> s.getMemberId())
.distinct().sorted().collect(Collectors.toList());
if (CollectionUtils.isEmpty(playerList)) {
if (CollectionUtils.isEmpty(reqParam.getPlayerIdList())) {
throw new SimulationException(SimulationExceptionType.Data_Not_Exist, "错误数据:无扮演者");
}
updateObj.setPlayerIdJson(JsonUtils.writeValueAsString(playerList));
updateObj.setPlayerIdJson(JsonUtils.writeValueAsString(reqParam.getPlayerIdList()));
// 背景
StorageSimulation scenesSaving = new StorageSimulation(simulation, true);
updateObj.setFinalScenesJson(JsonUtils.writeValueAsString(scenesSaving));

View File

@ -234,6 +234,9 @@ public class Training2PublishService {
criteria.andLabelJsonLike(String.format("%%%s%%", label));
}
}
if (reqVO.getOrgId() != null) {
criteria.andOrgIdEqualTo(reqVO.getOrgId());
}
/*if(!CollectionUtils.isEmpty(reqVO.getLabels())){
StringBuilder sqlBuilder = new StringBuilder("(");
List<String> labels = reqVO.getLabels().stream().filter(StringUtils::hasText).distinct().collect(Collectors.toList());

View File

@ -642,20 +642,22 @@ public class Training2Service {
*/
private boolean tryDoOperation(Simulation simulation, Step2 step, Operation2.SimCommand2 operation2) {
boolean isRobot = step.getSimulationMember().isRobot(); // 角色是否是机器人
long simCurTime = simulation.getCorrectSystemTimeStamp();
// 未操作过
if (Step2.StepStatus.isUndo(operation2.getStatus())) {
if (isRobot) {
boolean isExec = true; // 是否要执行
if (operation2.getSimTime() != null && simulation.getTraining2().isScene()) {
isExec = (simCurTime == operation2.getSimTime() || operation2.getSimTime() < simCurTime);
}
if (isExec) {
if (isRobot || operation2.isSpecial()) { // 特殊操作直接执行
atsOperationDispatcher.execute(simulation, step.getSimulationMember(), operation2.getOperationType().name()
, operation2.getParams());
return true;
} else { // 非机器人暂停仿真等待用户操作
if (operation2.getSimTime() != null) {
long simCurTime = simulation.getCorrectSystemTimeStamp();
// 如果时间到达操作时间或者在1s内则暂停仿真
if (simCurTime == operation2.getSimTime() || operation2.getSimTime() < simCurTime) {
simulation.onlyPause();
}
}
} else {
return false;
}
}

View File

@ -628,14 +628,9 @@ public class Operation {
Station_Switch_Control_Operation_Mode(new Label[]{Label.CLIENT},true),
/**
* 分散自律同意转换
* 分散自律同意不同意转换
*/
Station_Agree_Operation_Mode(new Label[]{Label.CLIENT},true),
/**
* 分散自律不同意转换
*/
Station_No_Agree_Operation_Mode(new Label[]{Label.CLIENT},true),
Station_Handle_Operation_Mode_Apply(new Label[]{Label.CLIENT},true),
//--------------------------- 列车 ---------------------------
/**
* 在指定区段加载一辆计划列车本地开发使用

View File

@ -325,31 +325,23 @@ public class StationOperateHandler {
* 车站状态选择切换
*/
@OperateHandlerMapping(type = Operation.Type.Station_Switch_Route_Set_Model)
public List<String> switchRouteSetModel(Simulation simulation, List<RouteModelParam> routeSetModeParams) {
return atsStationService.switchRouteSetModel(simulation, routeSetModeParams);
public void switchRouteSetModel(Simulation simulation, List<RouteModelParam> routeSetModeParams) {
atsStationService.switchRouteSetModel(simulation, routeSetModeParams);
}
/**
* 车站在分散自律时操作模式转换
*/
@OperateHandlerMapping(type = Operation.Type.Station_Switch_Control_Operation_Mode)
public List<String> controlOperationModeSwitch(Simulation simulation, SimulationMember fromMember, List<OperationModeParam> params) {
return atsStationService.controlOperationModeSwitch(simulation, fromMember, params);
public void controlOperationModeSwitch(Simulation simulation, SimulationMember fromMember, List<OperationModeParam> params) {
atsStationService.controlOperationModeSwitch(simulation, fromMember, params);
}
/**
* 分散自律同意转换模式操作
* 分散自律同意不同意转换模式操作
*/
@OperateHandlerMapping(type = Operation.Type.Station_Agree_Operation_Mode)
public void agreeOperationModel(Simulation simulation, List<String> stationCodes) {
atsStationService.agreeOperationMode(simulation, stationCodes);
}
/**
* 分散自律不同意转换模式操作
*/
@OperateHandlerMapping(type = Operation.Type.Station_No_Agree_Operation_Mode)
public void noAgreeOperationModel(Simulation simulation, List<String> stationCodes) {
atsStationService.noAgreeOperationMode(simulation, stationCodes);
@OperateHandlerMapping(type = Operation.Type.Station_Handle_Operation_Mode_Apply)
public void handleOperationModelApply(Simulation simulation, List<String> agreeStationCodes, List<String> noAgreeStationCodes) {
atsStationService.handleOperationModelApply(simulation, agreeStationCodes, noAgreeStationCodes);
}
}

View File

@ -576,7 +576,7 @@ public class AtsStationService {
* @param simulation 仿真实体
* @param routeSetModeParams 转换参数
*/
public List<String> switchRouteSetModel(Simulation simulation, List<RouteModelParam> routeSetModeParams) {
public void switchRouteSetModel(Simulation simulation, List<RouteModelParam> routeSetModeParams) {
List<String> logList = new ArrayList<>(routeSetModeParams.size());
for (RouteModelParam params : routeSetModeParams) {
if (StringUtils.isEmpty(params.getStationCode())) {
@ -593,7 +593,9 @@ public class AtsStationService {
logList.add(String.format("车站【%s%s】不可操作", station.getName(), station.getCode()));
}
}
return logList;
if (!CollectionUtils.isEmpty(logList)) {
throw new SimulationException(SimulationExceptionType.Operation_Handle_FAIL, String.join(";", logList));
}
}
/**
@ -602,23 +604,24 @@ public class AtsStationService {
* @param fromMember 操作角色
* @param params 转换参数
*/
public List<String> controlOperationModeSwitch(Simulation simulation, SimulationMember fromMember, List<OperationModeParam> params) {
public void controlOperationModeSwitch(Simulation simulation, SimulationMember fromMember, List<OperationModeParam> params) {
List<String> logList = new ArrayList<>(params.size());
for (OperationModeParam param : params) {
Station station = getStation(simulation, param.getStationCode());
if (Station.ControlMode.Local.equals(station.getControlMode())) {
Station.OperationModeApplication applyOperation = new Station.OperationModeApplication(fromMember, station.getOperationMode(), param.getTarget());
if (applyOperation.isNoHandle()) {
logList.add(String.format("车站【%s(%s)】 操作方式与目的方式相同不做操作", station.getName(), station.getCode()));
log.info(String.format("车站【%s(%s)】 操作方式与目的方式相同不做操作", station.getName(), station.getCode()));
} else if (applyOperation.isDirectConversion()) { // 如果可以直接转换
doOperationModeSwitch(station);
logList.add(String.format("车站【%s(%s)】 直接转换", station.getName(), station.getCode()));
station.setOperationMode(param.getTarget());
log.info(String.format("车站【%s(%s)】 直接转换", station.getName(), station.getCode()));
} else if (applyOperation.isProhibitConversion()) { // 禁止转换
logList.add(String.format("车站【%s(%s)】 禁止转换", station.getName(), station.getCode()));
} else {
applyOperation.setApplyDateTime(simulation.getCorrectSystemTime());
if (applyOperation.isCenterApplication()) { // 如果中心请求,需要车站同意
applyOperation.setApprovalMember(Arrays.asList(station.getController()));
SimulationMember member = simulation.getSimulationMember(SimulationMember.Type.STATION_SUPERVISOR, station.getCode());
applyOperation.setApprovalMember(Arrays.asList(member));
} else { // 车站同意需要中心同意
applyOperation.setApprovalMember(
simulation.getSimulationMembers().stream()
@ -632,32 +635,27 @@ public class AtsStationService {
logList.add(String.format("车站【%s(%s)】 非分散自律,不可操作", station.getName(), station.getCode()));
}
}
return logList;
if (!CollectionUtils.isEmpty(logList)) {
throw new SimulationException(SimulationExceptionType.Operation_Handle_FAIL, String.join(";", logList));
}
}
/**
* 同意分散自律操作模式转换
* 分散自律同意不同意转换模式操作
*
* @param simulation 仿真
* @param stationCodes 车站编码
* @param agreeStationCodes 同意车站编码
* @param noAgreeStationCodes 不同意车站编码
*/
public void agreeOperationMode(Simulation simulation, List<String> stationCodes) {
stationCodes.forEach(stationCode -> {
public void handleOperationModelApply(Simulation simulation, List<String> agreeStationCodes, List<String> noAgreeStationCodes) {
agreeStationCodes.forEach(stationCode -> {
Station station = getStation(simulation, stationCode);
if (station.getOperationModeApplication() != null) {
doOperationModeSwitch(station);
}
});
}
/**
* 不同意分散自律操作模式转换
*
* @param simulation 仿真
* @param stationCodes 车站编码
*/
public void noAgreeOperationMode(Simulation simulation, List<String> stationCodes) {
stationCodes.forEach(stationCode -> {
// 不同意分散自律操作模式转换
noAgreeStationCodes.forEach(stationCode -> {
Station station = getStation(simulation, stationCode);
station.setOperationModeApplication(null);
});
@ -666,32 +664,48 @@ public class AtsStationService {
/**
* 发送申请转换操作模式申请
* @param simulation
* @param station
*/
public void replyOperationMode(Simulation simulation, Station station) {
public void replyOperationMode(Simulation simulation) {
List<Station> stationList = simulation.getRepository().getStationList();
// 需要给用户发送的申请列表
Map<String, List<Map<String,Object>>> userMessageMap = new HashMap<>(stationList.size());
stationList.stream().filter(station -> {
Station.OperationModeApplication modeApplication = station.getOperationModeApplication();
if (modeApplication == null) {
return;
if (modeApplication== null) {
return false;
}
if (CollectionUtils.isEmpty(modeApplication.getApprovalMember())) {
return false;
}
// 申请超过两分钟
if (simulation.getCorrectSystemTime().isAfter(modeApplication.getApplyDateTime().plusMinutes(2))) {
station.setOperationModeApplication(null);
return;
return false;
}
if (CollectionUtils.isEmpty(modeApplication.getApprovalMember())) {
return;
}
Set<String> userSet = modeApplication.getApprovalMember().stream()
.filter(m -> !m.isRobot()).map(club.joylink.rtss.simulation.SimulationMember::getUserId).collect(Collectors.toSet());
return true;
}).forEach(station -> {
Station.OperationModeApplication modeApplication = station.getOperationModeApplication();
Set<String> userSet = modeApplication.getApprovalMember().stream().filter(m -> !m.isRobot())
.map(club.joylink.rtss.simulation.SimulationMember::getUserId).collect(Collectors.toSet());
if (!CollectionUtils.isEmpty(userSet)) {
Map<String, Object> messageMap = new HashMap<>();
messageMap.put("code", station.getCode());
messageMap.put("source", modeApplication.getSource());
messageMap.put("target", modeApplication.getTarget());
messageMap.put("applyMember", modeApplication.getApplicationMember().getId());
messageMap.put("applyDateTime", modeApplication.getApplyDateTime());
SocketMessageVO<Map<String, Object>> socketMessageVO =
SocketMessageFactory.build(WebSocketMessageType.Simulation_Operation_Mode_Apply, simulation.getId(), messageMap);
stompMessageService.sendToUser(userSet, socketMessageVO);
for (String userId : userSet) {
if (!userMessageMap.containsKey(userId)) {
userMessageMap.put(userId, new ArrayList<>());
}
userMessageMap.get(userId).add(messageMap);
}
}
});
if (!CollectionUtils.isEmpty(userMessageMap)) {
userMessageMap.forEach((k, v) ->
stompMessageService.sendToUser(k,
SocketMessageFactory.build(WebSocketMessageType.Simulation_Operation_Mode_Apply, simulation.getId(), v)));
}
}
@ -700,7 +714,9 @@ public class AtsStationService {
*/
public void doOperationModeSwitch(Station station) {
Station.OperationModeApplication applyOperation = station.getOperationModeApplication();
if (applyOperation != null) {
station.setOperationMode(applyOperation.getTarget());
station.setOperationModeApplication(null);
}
}
}

View File

@ -64,10 +64,10 @@ public class CiLogic {
// 区间灯点灯逻辑
if (simulation.getRepository().getConfig().isRailway()) {
// 车站站控操作模式转换
atsStationService.replyOperationMode(simulation);
// 车站
simulation.getRepository().getStationList().stream().forEach(station -> {
// 车站站控操作模式转换
atsStationService.replyOperationMode(simulation, station);
// 允许自律状态刷新
station.refreshAllowAutonomyStatus();
// 发辅助按钮倒计时刷新

View File

@ -1,6 +1,6 @@
package club.joylink.rtss.simulation.cbtc.CI.device;
import club.joylink.exception.BusinessExceptionAssertEnum;
import club.joylink.rtss.exception.BusinessExceptionAssertEnum;
import club.joylink.rtss.simulation.cbtc.Simulation;
import club.joylink.rtss.simulation.cbtc.constant.SignalAspect;
import club.joylink.rtss.simulation.cbtc.constant.SimulationConstants;
@ -480,7 +480,7 @@ public class CiRouteService {
* 区故解
*/
public void sectionFaultUnlock(Simulation simulation, Section section, Route route) {
if (route != null) {
if (route != null && route.isLock()) {
if (route.getStart().isApproachLock()
|| section.isOverlapLock()
|| route.getSectionList().stream().anyMatch(Section::isOccupied)) {

View File

@ -160,14 +160,14 @@ public class SimulationServiceImpl implements SimulationService {
private List<PermissionSubjectVO> findCanUsedPermission(List<PermissionSubjectVO> newVOLIst, RtsMapFunctionVO functionVO, LoginUserInfoVO loginInfo){
List<PermissionSubjectVO> canUseSubjectList = newVOLIst.stream().filter(d->Objects.equals(true,d.getForever())).collect(Collectors.toList());
if(CollectionUtils.isEmpty(canUseSubjectList)){
List<Long> timeOverIdList = newVOLIst.stream().filter(d->Objects.nonNull(d.getEndTime()) && d.getEndTime().isBefore(LocalDateTime.now()))
List<Long> timeOverIdList = newVOLIst.stream().filter(d->Objects.nonNull(d.getEndTime()) && d.getEndTime().isAfter(LocalDateTime.now()))
.map(d->d.getId())
.collect(Collectors.toList());
canUseSubjectList = newVOLIst.stream().filter(d->!timeOverIdList.contains(d)).collect(Collectors.toList());
if(CollectionUtils.isEmpty(timeOverIdList)){
log.error("mapId[{}],functionId[{}] userId[{}] 权限过期",functionVO.getMapId(),functionVO.getId(),loginInfo.getAccountVO().getId());
return Collections.emptyList();
}
canUseSubjectList = newVOLIst.stream().filter(d->timeOverIdList.contains(d.getId())).collect(Collectors.toList());
}
return canUseSubjectList;
}

View File

@ -176,36 +176,30 @@ public class SimulationRobotService {
doBreakMax(simulation, train);
}
} else if (train.isRobotNeedRun() && (train.isRMMode() || train.isNRMMode())) { //CM应当根据推荐速度驾驶待实现
newRobotDrive(simulation, driver, train);
Optional<SectionPosition> targetPositionOptional = calculateTargetPosition(simulation, train);
targetPositionOptional.ifPresent(tp -> robotDrive(simulation, driver, train, tp));
}
}
}
private void newRobotDrive(Simulation simulation, SimulationMember driver, VirtualRealityTrain train) {
if (!train.isInTheGear(VirtualRealityTrain.Handwheel.MANUAL)) { //确保当前在手动档位
CommandBO.Step step = CommandBO.buildGearChangeStep(train.getGroupNumber(), VirtualRealityTrain.Handwheel.MANUAL);
atsOperationDispatcher.execute(simulation, driver, step.getOperationType().name(), step.getOperationParams());
}
/**
* 计算目标位置
*/
private Optional<SectionPosition> calculateTargetPosition(Simulation simulation, VirtualRealityTrain train) {
DriveParamVO robotDriveParam = train.getRobotDriveParam();
if (train.isEB()) {
if (robotDriveParam.isReleaseEB()) {
releaseEB(simulation, driver, train);
if (!robotDriveParam.isReleaseEB()) { //列车EB了且没有要求解除EB
return Optional.empty();
}
} else {
robotDriveParam.setReleaseEB(false);
}
SectionPosition robotTargetPosition = robotDriveParam.getTargetPosition(); //目标位置
Section robotTargetSection = null; //目标区段
if (robotTargetPosition != null) {
robotTargetSection = robotTargetPosition.getSection();
}
Set<Section> stopSections = new HashSet<>(); //需要停车的区段
Set<Section> plannedParkingSections = new HashSet<>(); //计划中的停车位置当此字段不为空时则计划外的站台轨不停车
SimulationDataRepository repository = simulation.getRepository();
SectionPosition headPosition = train.getHeadPosition();
Section headSection = headPosition.getSection();
if (repository.getConfig().isRailway()) {
boolean right = train.isRight();
if (repository.getConfig().isRailway()) { //如果是大铁线路计划根据运行日志确定要停车的区段
TrainInfo trainInfo = repository.getSupervisedTrainByGroup(train.getGroupNumber());
CtcRepository ctcRepository = simulation.getCtcRepository();
Collection<CtcStationRunPlanLog> runPlans = ctcRepository.findRunPlans(trainInfo.getTripNumber());
@ -215,84 +209,82 @@ public class SimulationRobotService {
if (arriveRunPlan != null) {
Section trackSection = arriveRunPlan.getTrackSection();
if (!Objects.equals(trackSection, train.getParkSection())) {
stopSections.add(trackSection);
plannedParkingSections.add(trackSection);
}
}
CtcStationRunPlanLog.RunPlanItem departRunPlan = runPlan.getDepartRunPlan();
if (departRunPlan != null) {
Section trackSection = departRunPlan.getTrackSection();
if (!Objects.equals(trackSection, train.getParkSection())) {
stopSections.add(trackSection);
plannedParkingSections.add(trackSection);
}
}
}
} else { //无计划车在所有站台轨都停车
//本来是想将所有站台轨都加进来但为了效率考虑只加入列车车头区段如果符合条件的话
if (headSection.isNormalStandTrack() && !Objects.equals(train.getParkSection(), headSection)) {
stopSections.add(headSection);
}
}
}
Signal throughSignal = robotDriveParam.getThroughSignal();
SignalAspect throughAspect = robotDriveParam.getThroughSignalAspect();
/* 自动驾驶逻辑就是在[目标位置][需要停车区段的停车位置][信号禁止位置要越过的信号不算]中找到最近的一个位置作为
自动驾驶的目标位置 */
boolean right = train.isRight();
Section section = headSection;
Section section = headPosition.getSection();
if (throughSignal != null && !Objects.equals(section, throughSignal.getSection())) { //当车头与要越过的信号机不在同一区段
throughSignal = null;
throughAspect = null;
robotDriveParam.setThrough(DriveParamVO.NO);
}
SectionPosition selectedPosition = robotDriveParam.getTargetPosition(); //用户选择的位置
SectionPosition targetPosition = null;
for (int i = 0; i < 10; i++) {
if (section.isNormalStandTrack() && !section.equals(train.getParkSection())) { //正常站台轨且未在此处停过车
if (CollectionUtils.isEmpty(plannedParkingSections) || plannedParkingSections.contains(section)) {
SectionPosition stopPosition = section.buildStopPointPosition(right);
if (targetPosition == null || stopPosition.isAheadOf(targetPosition, right)) {
targetPosition = stopPosition;
}
}
}
// 取禁止信号前停车位置与当前目标停车位置中更近的一个
Signal signal = section.getSignalOf(right);
if (signal != null && !signal.isShunting()) {
VirtualRealitySignal vrSignal = signal.getVirtualSignal();
SectionPosition signalPosition = signal.getPosition();
if (vrSignal != null
&& (i != 0 || signalPosition.isAheadOf(headPosition, right))) { //有实体信号机且列车未越过信号机
if (vrSignal != null && (i != 0 || signalPosition.isAheadOf(headPosition, right))) { //有实体信号机且列车未越过信号机
if (Objects.equals(vrSignal.getAspect(), signal.getDefaultAspect()) //禁止信号
|| Objects.equals(vrSignal.getAspect(), signal.getGuideAspect())) { //引导信号
if (!Objects.equals(signal, throughSignal) || !Objects.equals(vrSignal.getAspect(), throughAspect)) {
targetPosition = CalculateService
SectionPosition noPassPosition = CalculateService
.calculateNextPositionByStartAndLen(signalPosition, !right, 2, true);
if (targetPosition == null || noPassPosition.isAheadOf(targetPosition, right)) {
targetPosition = noPassPosition;
}
}
}
}
//此时拿到了禁止信号的停车位置取其与目标位置间更近的一个
if (Objects.equals(section, robotTargetSection)) { //到目标区段
if (targetPosition == null || targetPosition.isAheadOf(robotTargetPosition, right)) {
targetPosition = robotTargetPosition;
}
}
//再将最近的位置与需要停车的区段的停车点做比较取更近的一个
if (stopSections.contains(section)) {
SectionPosition stopPosition = section.buildStopPointPosition(right);
if (targetPosition == null || targetPosition.isAheadOf(stopPosition, right)) {
targetPosition = stopPosition;
}
}
//如果到轨道尽头目标位置选择尽头向内10m否则继续向后寻找
if (targetPosition == null) {
if (selectedPosition != null && section.equals(selectedPosition.getSection())) { //不会有比选定位置更靠前的停车点了
targetPosition = selectedPosition;
} else {
Section tempSection = section.findNextRunningSectionBaseRealSwitch(right);
if (tempSection == null) {
if (tempSection == null) { //到了轨道尽头目标位置为尽头向内10m
targetPosition = new SectionPosition(section, right ? section.getLen() - 10 : 10);
} else {
section = tempSection;
}
}
} else {
if (selectedPosition != null && selectedPosition.isAheadOf(targetPosition, right)) {
targetPosition = selectedPosition;
}
}
if (targetPosition != null) {
break;
}
}
if (targetPosition == null) {
if (targetPosition == null) { //上方的区段遍历完后即没有找到目标区段也没有找到轨道尽头
targetPosition = new SectionPosition(section, right ? 0 : section.getMaxOffset());
}
robotDrive(simulation, train, targetPosition);
return Optional.ofNullable(targetPosition);
}
private void releaseEB(Simulation simulation, SimulationMember driver, VirtualRealityTrain train) {
@ -315,122 +307,22 @@ public class SimulationRobotService {
}
}
/**
* 大铁机器人自动驾驶目前的驾驶逻辑是针对RM/NRM模式驾驶
* 在确认列车自身状态正确的情况下车门是关闭状态等如果是没有计划的车次则只看信号如果是有计划的车次还需要看计划
*/
private void railRobotDrive(Simulation simulation, VirtualRealityTrain train) {
if (!train.getDoor1().isCloseAndLock() || !train.getDoor2().isCloseAndLock())
return;
SimulationDataRepository repository = simulation.getRepository();
boolean right = train.isRight();
SectionPosition headPosition = train.getHeadPosition();
Section nextSection = headPosition.getSection();
TrainInfo trainInfo = repository.getSupervisedTrainByGroup(train.getGroupNumber());
CtcRepository ctcRepository = simulation.getCtcRepository();
Collection<CtcStationRunPlanLog> runPlans = ctcRepository.findRunPlans(trainInfo.getTripNumber());
Set<Section> tracks = new HashSet<>();
for (CtcStationRunPlanLog runPlan : runPlans) {
CtcStationRunPlanLog.RunPlanItem arriveRunPlan = runPlan.getArriveRunPlan();
if (arriveRunPlan != null)
tracks.add(arriveRunPlan.getTrackSection());
CtcStationRunPlanLog.RunPlanItem departRunPlan = runPlan.getDepartRunPlan();
if (departRunPlan != null)
tracks.add(departRunPlan.getTrackSection());
}
SectionPosition targetPosition = null;
for (int i = 0; i < 10; i++) {
if (tracks.contains(nextSection) && !nextSection.equals(train.getParkSection())) { //这个判断感觉迟早要出问题
targetPosition = nextSection.buildStopPointPosition(right); //站台轨停车点
break;
}
Signal signal = nextSection.getSignalOf(right);
if (signal != null && !signal.isShunting()) { //有同向非通过信号机
SectionPosition signalPosition = signal.getPosition();
VirtualRealitySignal vrSignal = signal.getVirtualSignal();
if (vrSignal != null && !headPosition.isAheadOf(signalPosition, right)) { //有物理信号机并且车头没有越过信号机
if (!SignalAspect.G.equals(vrSignal.getAspect())
&& !SignalAspect.Y.equals(vrSignal.getAspect())
&& !SignalAspect.YY.equals(vrSignal.getAspect())) { //大铁线路暂时默认绿灯和黄/双黄灯是正常通行信号
targetPosition = CalculateService.calculateNextPositionByStartAndLen(signalPosition, !right, 5, true); //信号机前5m处
break;
}
}
}
Section next = nextSection.findNextRunningSectionBaseRealSwitch(right);
if (next == null) {
targetPosition = new SectionPosition(nextSection, right ? nextSection.getLen() - 10 : 10); //轨道尽头10m处
break;
}
nextSection = next;
}
if (targetPosition == null && nextSection != null) {
targetPosition = new SectionPosition(nextSection, right ? 0 : nextSection.getMaxOffset());
}
if (targetPosition != null)
robotDrive(simulation, train, targetPosition);
}
/**
* 机器人根据指令驾驶列车
*/
private void robotDriveByCommand(Simulation simulation, SimulationMember driver, VirtualRealityTrain train) {
SectionPosition targetPosition = train.getRobotTargetPosition();
if (targetPosition == null)
return;
SectionPosition headPosition = train.getHeadPosition();
boolean right = train.isRight();
//检查是否已到达/越过目的地
Float distance = CalculateService.calculateDistanceDoubleDirection(headPosition, targetPosition, right);
if (distance != null && distance < SimulationConstants.PARK_POINT_MAX_OFFSET) {
atoService.doBreakMax(train);
train.setRobotTargetPosition(null);
return;
}
CommandBO command = driver.getCommand();
CommandBO.CommandType commandType = null;
if (command != null) {
commandType = command.getCommandType();
}
if (!CommandBO.CommandType.Drive_Through_The_Guide_Signal.equals(commandType)
&& !CommandBO.CommandType.Drive_Through_The_Red_Light.equals(commandType)) { //非越红灯越引导指令时考虑信号机状态
//判断前方信号机正常开放以控制目标位置
Section nextSection = headPosition.getSection();
for (int i = 0; i < 3; i++) {
if (nextSection.equals(targetPosition.getSection())) //当前区段就是目标区段则不需要考虑区段末端的信号机了
break;
Signal signal = nextSection.getSignalOf(right);
if (signal != null && !Signal.SignalType.SHUNTING.equals(signal.getType())) {
VirtualRealitySignal vrSignal = signal.getVirtualSignal();
if (vrSignal != null &&
(Objects.equals(signal.getGuideAspect(), vrSignal.getAspect())
|| Objects.equals(signal.getDefaultAspect(), vrSignal.getAspect())
|| SignalAspect.No.equals(vrSignal.getAspect()))) { //真实信号机不为null且信号机显示是引导/默认/灭灯
//目标位置修改为信号机前5米
SectionPosition signalPosition = signal.getPosition();
targetPosition = CalculateService.calculateNextPositionByStartAndLen(signalPosition, !right, 5, true);
break;
}
}
nextSection = nextSection.findNextRunningSectionBaseRealSwitch(right);
if (nextSection == null)
break;
}
}
robotDrive(simulation, train, targetPosition);
}
/**
* 机器人驾驶
*
* @param simulation
* @param train
* @param targetPosition
*/
private void robotDrive(Simulation simulation, VirtualRealityTrain train, SectionPosition targetPosition) {
private void robotDrive(Simulation simulation, SimulationMember driver, VirtualRealityTrain train, SectionPosition targetPosition) {
if (!train.isInTheGear(VirtualRealityTrain.Handwheel.MANUAL)) { //确保当前在手动档位
CommandBO.Step step = CommandBO.buildGearChangeStep(train.getGroupNumber(), VirtualRealityTrain.Handwheel.MANUAL);
atsOperationDispatcher.execute(simulation, driver, step.getOperationType().name(), step.getOperationParams());
}
if (train.isEB()) {
if (train.getRobotDriveParam().isReleaseEB()) {
releaseEB(simulation, driver, train);
} else {
return;
}
}
SimulationDataRepository repository = simulation.getRepository();
SectionPosition headPosition = train.getHeadPosition();
boolean right = train.isRight();
@ -438,8 +330,8 @@ public class SimulationRobotService {
if (!train.getDoor1().isCloseAndLock() || !train.getDoor2().isCloseAndLock()) { //如果车门没关
return;
}
/**
* 添加车辆停靠车站时车门关闭后向前行驶一点的问题因为车头偏移与目标偏移大于 @seeSimulationConstants.PARK_POINT_MAX_OFFSET位置故修正逻辑如下
/*
* 添加车辆停靠车站时车门关闭后向前行驶一点的问题因为车头偏移与目标偏移大于 @see SimulationConstants.PARK_POINT_MAX_OFFSET位置故修正逻辑如下
* 判断车辆是否停靠车站没有开发的信号没有新车命令如果有其中一项的条件那么车辆可以启动
* begin 2022-08-15
*/
@ -454,7 +346,7 @@ public class SimulationRobotService {
if(trainPackingForStand && closeSignal && noCommond){
return;
}
/**
/*
* end 2022-08-15
*/
Float distance = CalculateService.calculateDistance(headPosition, targetPosition, right, true);

View File

@ -24,6 +24,9 @@ public abstract class Operation2 {
@Setter
private Expression failureCondition;
@Setter
boolean special;
/**
* 开始时间
*/
@ -151,6 +154,9 @@ public abstract class Operation2 {
if (vo.getFailureCondition() != null) {
this.setFailureCondition(vo.getFailureCondition().convert2BO(simulation.getRepository()));
}
if (vo.getSpecial() != null) {
this.setSpecial(vo.getSpecial());
}
}
}
@ -188,6 +194,9 @@ public abstract class Operation2 {
if (vo.getCompletionCondition() != null) {
this.setCompletionCondition(vo.getCompletionCondition().convert2BO(simulation.getRepository()));
}
if (vo.getSpecial() != null) {
this.setSpecial(vo.getSpecial());
}
}
}
}

View File

@ -325,7 +325,7 @@ public class AccountVO implements Serializable {
this.companyAdmin = orgAdmin;
this.projectCodes = orgVO.getProjectCodes();
} else {
this.companyId = 0L;
this.companyId = null;
this.companyName = null;
this.companyAdmin = false;
this.projectCodes = List.of();

View File

@ -98,7 +98,8 @@ public class SocketMessageFactory {
case Simulation_Scenes_Reload:
case Competition_Practical:
case SIMULATION_RAIL_TICKET:
case Simulation_Alarm: {
case Simulation_Alarm:
case Simulation_Operation_Mode_Apply: {
topicList.add(SimulationSubscribeTopic.Main.buildDestination(group));
break;
}

View File

@ -22,6 +22,8 @@ public class RtsMapFunctionCreateVO {
private String desc;
private String bgUrl;
private String subset;
@NotNull(message = "参数不能为空")
@ -32,6 +34,7 @@ public class RtsMapFunctionCreateVO {
rtsMapFunction.setMapId(mapId);
rtsMapFunction.setName(name);
rtsMapFunction.setDesc(desc);
rtsMapFunction.setBgUrl(bgUrl);
rtsMapFunction.setType(paramVO.getType().name());
rtsMapFunction.setGroup(subset);
rtsMapFunction.setParam(JsonUtils.writeValueAsString(paramVO));

View File

@ -0,0 +1,35 @@
package club.joylink.rtss.vo.client.mapFunction;
import club.joylink.rtss.entity.RtsMapFunction;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
/**
* 地图功能描述修改参数
*/
@Getter
@Setter
@NoArgsConstructor
public class RtsMapFunctionDescModifyVO {
/**
* 功能名称与下面的原描述以或的关系作为更新条件
*/
private String functionName;
/**
* 原描述
*/
private String originalDesc;
/**
* 新描述
*/
private String newDesc;
public RtsMapFunction convert2DB() {
RtsMapFunction entity = new RtsMapFunction();
entity.setDesc(newDesc);
return entity;
}
}

View File

@ -34,6 +34,11 @@ public abstract class Operation2VO {
*/
ExpressionVO failureCondition;
/**
* 特殊操作直接执行
*/
Boolean special;
public abstract Operation2 convert2BO(Simulation simulation);
/**

View File

@ -0,0 +1,14 @@
package club.joylink.rtss.vo.training2.draft;
import club.joylink.rtss.vo.client.training2.Step2VO;
import lombok.Data;
import java.util.List;
@Data
public class UpdateStepReqVo {
private List<Step2VO> step2VOList;
private List<String> playerIdList;
}

View File

@ -21,4 +21,6 @@ public class PublishedTrainingListRspVo extends PageQueryVO {
private String name;
private List<String> labels;
private Integer state;
private Long orgId;
}