【实训跳转至目标步骤功能】

This commit is contained in:
weizhihong 2023-05-12 15:46:58 +08:00
parent aace990217
commit 5073f9f788
5 changed files with 124 additions and 33 deletions

View File

@ -99,4 +99,14 @@ public class SimulationTrainingV2Controller {
public void drawTraining(@PathVariable String group, @PathVariable Long trainingId) {
training2Service.drawTraining(group, trainingId);
}
/**
* 加载实训到第{stepId}
* @param group 仿真ID
* @param stepId 步数ID
*/
@PutMapping("/{group}/jumpTo/{stepId}")
public void jumpToStep(@PathVariable String group, @PathVariable Long stepId){
training2Service.jumpToStep(group, stepId);
}
}

View File

@ -9,9 +9,6 @@ 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.Operation;
import club.joylink.rtss.simulation.cbtc.*;
import club.joylink.rtss.simulation.cbtc.conversation.Conversation;
import club.joylink.rtss.simulation.cbtc.conversation.ConversationManagerService;
import club.joylink.rtss.simulation.cbtc.conversation.ConversationMessage;
import club.joylink.rtss.simulation.cbtc.data.map.Switch;
import club.joylink.rtss.simulation.cbtc.data.vo.ConversationMessageVO;
import club.joylink.rtss.simulation.cbtc.data.vo.Training2MessageVO;
@ -26,7 +23,6 @@ import club.joylink.rtss.simulation.cbtc.member.MemberManager;
import club.joylink.rtss.simulation.cbtc.member.SimulationMember;
import club.joylink.rtss.simulation.cbtc.script.ScriptBO;
import club.joylink.rtss.simulation.cbtc.training2.Operation2;
import club.joylink.rtss.simulation.cbtc.training2.ScoringRule2;
import club.joylink.rtss.simulation.cbtc.training2.Step2;
import club.joylink.rtss.simulation.cbtc.training2.Training2;
import club.joylink.rtss.simulation.cbtc.training2.index.Index;
@ -37,7 +33,6 @@ import club.joylink.rtss.vo.LoginUserInfoVO;
import club.joylink.rtss.vo.client.SocketMessageVO;
import club.joylink.rtss.vo.client.WebSocketMessageType;
import club.joylink.rtss.vo.client.factory.SocketMessageFactory;
import club.joylink.rtss.vo.client.training2.ScoringRuleVO;
import club.joylink.rtss.vo.paper.PaperTrainAnswerDetail;
import club.joylink.rtss.websocket.StompMessageService;
import lombok.extern.slf4j.Slf4j;
@ -48,6 +43,8 @@ import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestAttribute;
import java.util.*;
import java.util.concurrent.Semaphore;
@ -151,6 +148,18 @@ public class Training2Service {
Step2 step = getNextStepAndCheckTrainingStatus(training2, simulation);
// 如果步骤执行完毕 或者 步骤内操作全部是前端操作则直接返回交于前端操作 || step.allClientOperation()
if (step == null) {
if (training2.haveJumpStep()) { // 当跳转步骤是最后一步时结束需要做额外清空
clearJumpStep(simulation);
}
return;
}
// 因为是跳转前端不需要操作直接置成成功
if (training2.isJumpStep(step)) {
step.getOperations().forEach(Operation2::doSuccessVail);
}
// 如果跳转到目标步骤停止加速并置空跳转步骤
if (training2.haveJumpStep() && !training2.isJumpStep(step)) {
clearJumpStep(simulation);
return;
}
// 尝试触发步骤
@ -247,20 +256,7 @@ public class Training2Service {
if (training2 == null) {
throw new SimulationException(SimulationExceptionType.Invalid_Operation, "实训数据不存在");
}
if (!StringUtils.isEmpty(training2.getBgSceneJson())) {
if (training2.isNeedReloadScenes()) {
groupSimulationService.loadScenes(simulation.getId(), training2.getBgSceneJson());
}
} else {
// 重置仿真状态
simulationService.reset(simulation.getId());
}
atsMessageCollectAndDispatcher.collectAllAndSend(simulation);
// 增加实训任务
training2.start(mode);
addTrainingJob(simulation, training2);
// 启动仿真
simulationLifeCycleService.resume(simulation);
doStartTraining(mode, simulation, training2);
}
/**
@ -437,6 +433,9 @@ public class Training2Service {
simCommand2.doCompletion();
startFlag = Boolean.TRUE;
}
if (training2.getJumpToStep() != null) { // 处于跳转状态下下边步骤不执行
return;
}
// 指令执行后启动仿真
if (simulation.isPause() && startFlag) {
simulation.start();
@ -538,6 +537,26 @@ public class Training2Service {
sendSimulationConversation(simulation);
}
/**
* 加载实训到第几步
* @param group 仿真
* @param stepId 实训步数ID
*/
public void jumpToStep(String group, Long stepId) {
Simulation simulation = groupSimulationCache.getSimulationByGroup(group);
Training2 training2 = simulation.getTraining2();
try {
Step2 step2 = training2.getStep(stepId.intValue()); // 跳转目标步骤
training2.setJumpToStep(step2);
doStartTraining(null, simulation, training2); // 开始执行
simulation.updateSpeed(Simulation.MAX_SPEED);
} catch (Exception e) {
log.error("loadTrainingToStep is error", e);
training2.finish();
removeTrainingJob(simulation);
}
}
/**
* 实训时创建仿真对象
*/
@ -591,7 +610,8 @@ public class Training2Service {
*/
private boolean checkTrainStepCompletion(Step2 step, Simulation simulation) {
boolean result = step.doCompletionVail();
if (result) {
// 如果实在跳过过程中不需要发消息信息
if (result && !simulation.getTraining2().isJumpStep(step)) {
// 发送步骤完成信息
applicationContext.publishEvent(new SimulationStepFinishEvent(this, simulation, step));
}
@ -635,8 +655,8 @@ public class Training2Service {
}
}
}
// 发送步骤提示信息
if (!step.isPrompt()) {
// 发送步骤提示信息,需要跳过步骤不发消息
if (!step.isPrompt() && !simulation.getTraining2().isJumpStep(step)) {
step.setPrompt(true); // 标识已发送过消息
applicationContext.publishEvent(new SimulationStepTipEvent(this, simulation, step));
}
@ -676,7 +696,7 @@ public class Training2Service {
isExec = (simCurTime == operation2.getSimTime() || operation2.getSimTime() < simCurTime);
}
if (isExec) {
if (isRobot || operation2.isSpecial()) { // 特殊操作直接执行
if (isRobot || operation2.isSpecial() || simulation.getTraining2().isJumpStep(step)) { // 特殊操作直接执行
atsOperationDispatcher.execute(simulation, step.getSimulationMember(), operation2.getOperationType().name()
, operation2.getParams());
return true;
@ -782,17 +802,19 @@ public class Training2Service {
ConversationMessageVO message = (ConversationMessageVO) event.getResult();
String source = String.valueOf(simOperation2.getParams().get("content"));
String target = message.getContent();
boolean doCompletion = false;
if (CONVERSATION_TEXT_LIST.contains(event.getOperate())) {
if (Objects.equals(source,target)) {
simOperation2.doOperated();
}
doCompletion = Objects.equals(source,target);
} else {
boolean result = StrUtils.isMatch(source, target, 20);
if (result) {
simOperation2.doOperated();
}
// 发送步骤完成信息
applicationContext.publishEvent(new SimulationTrainingAudioEvent(this, simulation, step, simOperation2, result));
doCompletion = StrUtils.isMatch(source, target, 20);
}
if (doCompletion) {
simOperation2.doOperated();
simOperation2.doCompletion();
}
// 发送步骤完成信息
if (!simulation.getTraining2().isJumpStep(step)) {
applicationContext.publishEvent(new SimulationTrainingAudioEvent(this, simulation, step, simOperation2, doCompletion));
}
}
@ -866,4 +888,39 @@ public class Training2Service {
}
}
/**
* 开始执行实训
*
* @param mode 模式
* @param simulation 仿真
* @param training2 实训
*/
private void doStartTraining(ScriptBO.Mode mode, Simulation simulation, Training2 training2) {
if (!StringUtils.isEmpty(training2.getBgSceneJson())) {
if (training2.isNeedReloadScenes() && training2.getJumpToStep() != null) {
groupSimulationService.loadScenes(simulation.getId(), training2.getBgSceneJson());
}
} else {
// 重置仿真状态
simulationService.reset(simulation.getId());
}
if (training2.getJumpToStep() == null) { // 跳转步骤时不需要发送初始状态减小交互
atsMessageCollectAndDispatcher.collectAllAndSend(simulation);
}
// 增加实训任务
training2.start(mode);
addTrainingJob(simulation, training2);
// 启动仿真
simulationLifeCycleService.resume(simulation);
}
/**
* 清除当前实训跳转步骤信息
*/
private void clearJumpStep(Simulation simulation) {
simulation.updateSpeed(Simulation.MIN_SPEED);
simulation.getTraining2().setJumpToStep(null);
simulation.getTraining2().finish();
}
}

View File

@ -55,7 +55,7 @@ public class AtsAlarmService {
Simulation simulation = event.getSimulation();
DeviceFaultInfo deviceFaultInfo = event.getDeviceFaultInfo();
List<AtsAlarm> list = simulation.getRepository().getAlarmList().stream()
.filter(atsAlarm -> !atsAlarm.getRecovered() && atsAlarm.getDeviceCode().equals(deviceFaultInfo.getCode()))
.filter(atsAlarm -> (atsAlarm.getRecovered() == null || !atsAlarm.getRecovered()) && atsAlarm.getDeviceCode().equals(deviceFaultInfo.getCode()))
.peek(atsAlarm -> atsAlarm.recover(simulation.getCorrectSystemTime()))
.collect(Collectors.toList());
SocketMessageVO<Collection<AtsAlarm>> messageVO = SocketMessageFactory

View File

@ -122,6 +122,10 @@ public abstract class Operation2 {
this.operatedTime = LocalDateTime.now();
}
public boolean isSuccess() {
return Step2.StepStatus.isSuccess(this.status);
}
public void reset() {
this.startTime = null;
this.operatedTime = null;

View File

@ -104,6 +104,10 @@ public class Training2 {
*/
private Map<String, IndexAlgorithmService> indexAlgorithmMap;
/**
* 跳转至第几步
*/
private Step2 jumpToStep;
public Training2(DraftTraining2WithBLOBs draftTraining2, Simulation simulation) {
this.id = draftTraining2.getId();
@ -232,6 +236,22 @@ public class Training2 {
return Type.SCENE.equals(this.type);
}
/**
* 是否是跳转步骤
*
* @return true | false
*/
public boolean isJumpStep(Step2 step) {
if (jumpToStep == null) {
return false;
}
return steps.indexOf(step) <= steps.indexOf(jumpToStep);
}
public boolean haveJumpStep() {
return jumpToStep != null;
}
private void resetStepAndIndex() {
if (this.steps != null) {
this.steps.forEach(Step2::reset);