diff --git a/src/main/java/club/joylink/rtss/services/paper/PaperUserService.java b/src/main/java/club/joylink/rtss/services/paper/PaperUserService.java index 9546d5870..e91cd416c 100644 --- a/src/main/java/club/joylink/rtss/services/paper/PaperUserService.java +++ b/src/main/java/club/joylink/rtss/services/paper/PaperUserService.java @@ -24,8 +24,13 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.CollectionUtils; +import org.springframework.util.SocketUtils; import org.springframework.util.StringUtils; +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.text.DecimalFormat; +import java.text.NumberFormat; import java.time.Duration; import java.time.LocalDateTime; import java.util.*; @@ -172,6 +177,7 @@ public class PaperUserService { long paperTime = Duration.between(paper.getStartTime(), now).toMinutes();//实际做题时长min for (PaperUserQuestion uq : userQuestionList) { PaperRule rule = ruleIdMap.get(uq.getRuleId()); + switch (PaperQType.GroupType.getItem(uq.getType())) { case Common: scoreCommon += calculateCommonScore(uq, rule);break; @@ -204,16 +210,26 @@ public class PaperUserService { * 获取题的最终得分 */ private int calculateCommonScore(PaperUserQuestion puq, PaperRule rule) { -// PaperQuestionExample example = new PaperQuestionExample(); -// example.createCriteria().andIdEqualTo(puq.getQuestionId()); -// PaperQuestion question = pagerQuestionDAO.selectByExample(example).get(0); if (PaperQuestionState.Right.equals(PaperQuestionState.getItem(puq.getState()))) {//题答对时 -// PaperRule rule = ruleMap.get(this.getPaperQuestionType(question)); return rule.getScore(); } return 0; } + public static int getPercentage(double score,int sumScore,int ruleScore) { + if(score >= sumScore){ + return ruleScore; + } + int d = sumScore * 100; + if(sumScore >=10){ + d = sumScore ; + } + double t = score / d; + if(t <=0.5){ + return (int)Math.round(t * ruleScore); + } + return (int)Math.floor(t * ruleScore); + } /** * 获取题的最终得分 @@ -226,12 +242,9 @@ public class PaperUserService { return 0; } PaperSubmitAnswerReqVo.AnswerDetail answerDetail = JsonUtils.read(puq.getTmpAnswer(),PaperSubmitAnswerReqVo.AnswerDetail.class); - double sumScore = answerDetail.getTrainDetail().stream().mapToDouble(PaperTrainAnswerDetail::getScore).sum(); - double dd = sumScore / (rule.getScore() * 100); - if(dd > 0){ - return (int)Math.round(dd); - } - return 0; + int sumScore = answerDetail.getSumScore(); + double totalScore = answerDetail.getTrainDetail().stream().mapToDouble(PaperTrainAnswerDetail::getScore).sum(); + return getPercentage(totalScore,sumScore,rule.getScore()); } return 0; } diff --git a/src/main/java/club/joylink/rtss/services/paper/PaperUserSubmitAnswerService.java b/src/main/java/club/joylink/rtss/services/paper/PaperUserSubmitAnswerService.java index 9f6e6d735..807ca05a7 100644 --- a/src/main/java/club/joylink/rtss/services/paper/PaperUserSubmitAnswerService.java +++ b/src/main/java/club/joylink/rtss/services/paper/PaperUserSubmitAnswerService.java @@ -10,8 +10,6 @@ import club.joylink.rtss.entity.paper.PaperUserQuestion; import club.joylink.rtss.entity.paper.PaperUserQuestionExample; import club.joylink.rtss.entity.paper.question.PaperQuestion; import club.joylink.rtss.entity.paper.question.PaperQuestionExample; -import club.joylink.rtss.entity.training2.PublishedTraining2; -import club.joylink.rtss.exception.BusinessExceptionAssert; import club.joylink.rtss.exception.BusinessExceptionAssertEnum; import club.joylink.rtss.exception.PaperExceptionAssert; import club.joylink.rtss.services.training2.Training2PublishService; @@ -21,10 +19,8 @@ import club.joylink.rtss.vo.client.training2.ScoringRuleVO; import club.joylink.rtss.vo.client.training2.Step2VO; import club.joylink.rtss.vo.paper.*; import club.joylink.rtss.vo.training2.publish.PublishedTraining2DetailRspVo; -import com.google.common.base.Joiner; import com.google.common.base.Splitter; import com.google.common.base.Strings; -import com.google.common.collect.Lists; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -78,24 +74,22 @@ public class PaperUserSubmitAnswerService { rsp.setPqId(req.getPqId()); rsp.setType(req.getType()); rsp.setSubType(req.getSubType()); - String tmpAnswer = null; + TrainAnswerVO answerVO; + BusinessExceptionAssertEnum.DATA_INVALID.assertTrue(Objects.nonNull(req.getType()),"未知的考试类型"); //处理用户提交的答案 if(req.getType() == PaperQType.GroupType.Common){ - rsp.setResult(submitCommonAnswer(puq, req)); - tmpAnswer = this.getAnswerFromSubmit(req); - }else if(req.getType() == PaperQType.GroupType.Training){ + answerVO = submitCommonAnswer(puq, req); + }else{ BusinessExceptionAssertEnum.ARGUMENT_ILLEGAL.assertNotTrue((req.getSubType() != PaperQType.SubType.Single && req.getSubType() != PaperQType.SubType.Scene),String.format("未知答题类型[%s]",req.getSubType())); - TrainAnswerVO answerVO = this.submitTrainingAnswer(req,puq); - rsp.setResult(answerVO.getState()); - tmpAnswer = JsonUtils.writeValueAsString(answerVO.getDetail()); + answerVO = this.submitTrainingAnswer(req,puq); } + rsp.setResult(answerVO.getState()); //记录用户答题情况 PaperUserQuestion record = new PaperUserQuestion(); record.setId(puq.getId()); record.setState(rsp.getResult().getValue()); - record.setTmpAnswer(tmpAnswer); + record.setTmpAnswer(answerVO.getDetailStr()); paperUserQuestionDAO.updateByPrimaryKeySelective(record); - // return rsp; } @@ -112,7 +106,7 @@ public class PaperUserSubmitAnswerService { // PaperExceptionAssert.PuqCanSubmit.assertTrue(PaperQuestionState.Undo.equals(PaperQuestionState.getItem(puq.getState())), "只有未做的题才能提交答案"); } - private TrainAnswerVO submitTrainingAnswer(PaperSubmitAnswerReqVo reqVo,PaperUserQuestion puq){ + private TrainAnswerVO submitTrainingAnswer(PaperSubmitAnswerReqVo reqVo,PaperUserQuestion puq){ BusinessExceptionAssertEnum.DATA_NOT_EXIST.assertNotTrue(Strings.isNullOrEmpty(reqVo.getTrainAnswerDetail().getCosplayMemberId()),"实训考试没有对应的角色"); BusinessExceptionAssertEnum.DATA_NOT_EXIST.assertNotTrue(CollectionUtils.isEmpty(reqVo.getTrainAnswerDetail().getTrainDetail()),"实训考试没有对应的操作"); BusinessExceptionAssertEnum.DATA_NOT_EXIST.assertNotTrue(reqVo.getTrainAnswerDetail().getTrainDetail().stream().anyMatch(d->Objects.isNull(d.getStepId())),"实训步骤id不能为空"); @@ -126,7 +120,7 @@ public class PaperUserSubmitAnswerService { }else if(reqVo.getSubType() == PaperQType.SubType.Scene){ return this.submitTrainingAnswerForScene(detailVO,reqVo); } - return new TrainAnswerVO(PaperQuestionState.Wrong, null); + return new TrainAnswerVO(PaperQuestionState.Wrong, null); } /** @@ -135,13 +129,13 @@ public class PaperUserSubmitAnswerService { * * @return */ - private TrainAnswerVO submitTrainingAnswerForSingle(PaperSubmitAnswerReqVo req,PublishedTraining2DetailRspVo trainDetailVO/*List allStepList,PaperUserQuestion puq*/) { + private TrainAnswerVO submitTrainingAnswerForSingle(PaperSubmitAnswerReqVo req, PublishedTraining2DetailRspVo trainDetailVO/*List allStepList,PaperUserQuestion puq*/) { BusinessExceptionAssertEnum.DATA_ERROR.assertTrue(StringUtils.hasText(trainDetailVO.getStepJson()),"场景实训没有对应的操作步骤"); List allStepList = JsonUtils.readCollection(trainDetailVO.getStepJson(),ArrayList.class, Step2VO.class); List cosplayStepList = allStepList.stream().filter(d->Objects.equals(d.getMemberId(),req.getTrainAnswerDetail().getCosplayMemberId())).collect(Collectors.toList()); if(req.getTrainAnswerDetail().getTrainDetail().size() != cosplayStepList.size()){ - return new TrainAnswerVO(PaperQuestionState.Wrong, req.getTrainAnswerDetail()); + return new TrainAnswerVO<>(PaperQuestionState.Wrong, req.getTrainAnswerDetail()); } if(req.getTrainAnswerDetail().getTrainDetail().stream().allMatch(PaperTrainAnswerDetail::isSuccess)){ return new TrainAnswerVO(PaperQuestionState.Right, req.getTrainAnswerDetail()); @@ -162,12 +156,12 @@ public class PaperUserSubmitAnswerService { Map answerDetailMap = answerDetailList.stream().collect(Collectors.toMap(d->d.getStepId().toString(),Function.identity())); List resultAnswerDetailList = new ArrayList<>(allDetailVOList.size()); + int sumScore = allDetailVOList.stream().mapToInt(d->(int)d.getScore()).sum(); for (ScoringRuleVO.DetailVO detailVO : allDetailVOList) { PaperTrainAnswerDetail answerDetail = answerDetailMap.get(detailVO.getElementId()); if(Objects.nonNull(answerDetail)){ answerDetail.setScore(detailVO.getScore()); - }else{ answerDetail = new PaperTrainAnswerDetail(); answerDetail.setScore(0F); @@ -176,6 +170,7 @@ public class PaperUserSubmitAnswerService { } resultAnswerDetailList.add(answerDetail); } + req.getTrainAnswerDetail().setSumScore(sumScore); req.getTrainAnswerDetail().setTrainDetail(resultAnswerDetailList); return new TrainAnswerVO(PaperQuestionState.SECEN_CUL,req.getTrainAnswerDetail()); @@ -183,7 +178,7 @@ public class PaperUserSubmitAnswerService { /** * 处理理论题答案 */ - private PaperQuestionState submitCommonAnswer(PaperUserQuestion puq, PaperSubmitAnswerReqVo req) { + private TrainAnswerVO submitCommonAnswer(PaperUserQuestion puq, PaperSubmitAnswerReqVo req) { //题目 PaperQuestionExample pqExample = new PaperQuestionExample(); pqExample.createCriteria().andIdEqualTo(puq.getQuestionId()); @@ -192,7 +187,12 @@ public class PaperUserSubmitAnswerService { final String qAn = this.getAnswerFromQuestion(pq); final String sAn = this.getAnswerFromSubmit(req); // - return qAn.equals(sAn) ? PaperQuestionState.Right : PaperQuestionState.Wrong; + PaperQuestionState qState = PaperQuestionState.Wrong; + if(qAn.equals(sAn)){ + qState = PaperQuestionState.Right; + } + TrainAnswerVO vo = new TrainAnswerVO(qState,sAn); + return vo; } private String getAnswerFromQuestion(PaperQuestion pq) { diff --git a/src/main/java/club/joylink/rtss/simulation/cbtc/ATS/operation/handler/StationOperateHandler.java b/src/main/java/club/joylink/rtss/simulation/cbtc/ATS/operation/handler/StationOperateHandler.java index dc57e1b21..5777a95f2 100644 --- a/src/main/java/club/joylink/rtss/simulation/cbtc/ATS/operation/handler/StationOperateHandler.java +++ b/src/main/java/club/joylink/rtss/simulation/cbtc/ATS/operation/handler/StationOperateHandler.java @@ -323,10 +323,6 @@ public class StationOperateHandler { /** * 车站状态选择切换 - * @param simulation 仿真实体 - * @param stationCode 车站编码 - * @param routeSetMode 排路方式 - * @param planControl 计划控制 */ @OperateHandlerMapping(type = Operation.Type.Station_Switch_Route_Set_Model) public List switchRouteSetModel(Simulation simulation, List routeSetModeParams) { diff --git a/src/main/java/club/joylink/rtss/simulation/cbtc/ATS/service/AtsStationService.java b/src/main/java/club/joylink/rtss/simulation/cbtc/ATS/service/AtsStationService.java index 892d2aaa0..a4ded4ce5 100644 --- a/src/main/java/club/joylink/rtss/simulation/cbtc/ATS/service/AtsStationService.java +++ b/src/main/java/club/joylink/rtss/simulation/cbtc/ATS/service/AtsStationService.java @@ -27,6 +27,7 @@ import org.springframework.stereotype.Component; import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; +import java.time.LocalDateTime; import java.time.LocalTime; import java.util.*; import java.util.stream.Collectors; @@ -616,6 +617,15 @@ public class AtsStationService { logList.add(String.format("车站【%s(%s)】 禁止转换", station.getName(), station.getCode())); } else { applyOperation.setApplyDateTime(simulation.getCorrectSystemTime()); + if (applyOperation.isCenterApplication()) { // 如果中心请求,需要车站同意 + applyOperation.setApprovalMember(Arrays.asList(station.getController())); + } else { // 车站同意需要中心同意 + applyOperation.setApprovalMember( + simulation.getSimulationMembers().stream() + .filter(s -> Objects.equals(s.getType(), SimulationMember.Type.DISPATCHER)) + .collect(Collectors.toList()) + ); + } station.setOperationModeApplication(applyOperation); } } else { // 非分散自律抛出异常 @@ -654,7 +664,7 @@ public class AtsStationService { } /** - * + * 发送申请转换操作模式申请 * @param simulation * @param station */ @@ -668,29 +678,27 @@ public class AtsStationService { station.setOperationModeApplication(null); return; } - SimulationMember simulationMember = null; - if (modeApplication.isCenterApplication()) { // 如果中心请求 - simulationMember = station.getController(); - } else { - simulationMember = simulation.getSimulationMembers().stream() - .filter(s -> Objects.equals(s.getType(), SimulationMember.Type.DISPATCHER)) - .findFirst().orElse(null); - } - if (simulationMember == null) { + if (CollectionUtils.isEmpty(modeApplication.getApprovalMember())) { return; - } else if (simulationMember.isRobot()) { - doOperationModeSwitch(station); - } else { - SocketMessageVO socketMessageVO = - SocketMessageFactory.build(WebSocketMessageType.Simulation_Operation_Mode_Apply, simulation.getId(), modeApplication); - stompMessageService.sendToUser(Set.of(simulationMember.getUserId()), socketMessageVO); + } + Set userSet = modeApplication.getApprovalMember().stream() + .filter(m -> !m.isRobot()).map(club.joylink.rtss.simulation.SimulationMember::getUserId).collect(Collectors.toSet()); + if (!CollectionUtils.isEmpty(userSet)) { + Map messageMap = new HashMap<>(); + messageMap.put("source", modeApplication.getSource()); + messageMap.put("target", modeApplication.getTarget()); + messageMap.put("applyMember", modeApplication.getApplicationMember().getId()); + messageMap.put("applyDateTime", modeApplication.getApplyDateTime()); + SocketMessageVO> socketMessageVO = + SocketMessageFactory.build(WebSocketMessageType.Simulation_Operation_Mode_Apply, simulation.getId(), messageMap); + stompMessageService.sendToUser(userSet, socketMessageVO); } } /** * 操作模式直接转换 */ - private void doOperationModeSwitch(Station station) { + public void doOperationModeSwitch(Station station) { Station.OperationModeApplication applyOperation = station.getOperationModeApplication(); station.setOperationMode(applyOperation.getTarget()); station.setOperationModeApplication(null); diff --git a/src/main/java/club/joylink/rtss/simulation/cbtc/CI/CiLogic.java b/src/main/java/club/joylink/rtss/simulation/cbtc/CI/CiLogic.java index eef107055..dd860f334 100644 --- a/src/main/java/club/joylink/rtss/simulation/cbtc/CI/CiLogic.java +++ b/src/main/java/club/joylink/rtss/simulation/cbtc/CI/CiLogic.java @@ -1,5 +1,6 @@ package club.joylink.rtss.simulation.cbtc.CI; +import club.joylink.rtss.simulation.cbtc.ATS.service.AtsStationService; import club.joylink.rtss.simulation.cbtc.CI.device.CiDeviceStatusCollector; import club.joylink.rtss.simulation.cbtc.CI.device.CiRouteService; import club.joylink.rtss.simulation.cbtc.CI.device.CiService; @@ -36,6 +37,9 @@ public class CiLogic { @Autowired private StationDirectionService stationDirectionService; + @Autowired + private AtsStationService atsStationService; + public void runForTrainPosition(Simulation simulation){ // 采集真实设备状态 deviceStatusCollector.collect(simulation); @@ -62,6 +66,8 @@ public class CiLogic { if (simulation.getRepository().getConfig().isRailway()) { // 车站 simulation.getRepository().getStationList().stream().forEach(station -> { + // 车站站控操作模式转换 + atsStationService.replyOperationMode(simulation, station); // 允许自律状态刷新 station.refreshAllowAutonomyStatus(); // 接、发辅助按钮倒计时刷新 diff --git a/src/main/java/club/joylink/rtss/simulation/cbtc/data/map/Station.java b/src/main/java/club/joylink/rtss/simulation/cbtc/data/map/Station.java index 53d03fa66..2d8d07d5f 100644 --- a/src/main/java/club/joylink/rtss/simulation/cbtc/data/map/Station.java +++ b/src/main/java/club/joylink/rtss/simulation/cbtc/data/map/Station.java @@ -595,8 +595,16 @@ public class Station extends MayOutOfOrderDevice { */ private OperationMode target; + /** + * 申请人 + */ private SimulationMember applicationMember; + /** + * 审批人 + */ + private List approvalMember; + private LocalDateTime applyDateTime; public OperationModeApplication(SimulationMember applicantMember, OperationMode source, OperationMode target) { @@ -642,6 +650,16 @@ public class Station extends MayOutOfOrderDevice { return stationApplication && centerToShunt(); } + /** + * 审批人全部是机器人 + */ + public boolean isRobotApproval() { + if (CollectionUtils.isEmpty(approvalMember)) { + return false; + } + return approvalMember.stream().allMatch(SimulationMember::isRobot); + } + /** * 中心与调车相互转换 */ diff --git a/src/main/java/club/joylink/rtss/simulation/cbtc/data/storage/device/StorageStation.java b/src/main/java/club/joylink/rtss/simulation/cbtc/data/storage/device/StorageStation.java index e87bf5f91..db277d984 100644 --- a/src/main/java/club/joylink/rtss/simulation/cbtc/data/storage/device/StorageStation.java +++ b/src/main/java/club/joylink/rtss/simulation/cbtc/data/storage/device/StorageStation.java @@ -15,9 +15,11 @@ import lombok.Setter; import java.time.LocalDateTime; import java.time.LocalTime; +import java.util.List; import java.util.Map; import java.util.Objects; import java.util.concurrent.atomic.AtomicInteger; +import java.util.stream.Collectors; @Getter @Setter @@ -196,6 +198,11 @@ public class StorageStation extends StorageStatusDevice { */ private String applicationMemberId; + /** + * 审批者ID + */ + private List approvalMemberIds; + private LocalDateTime applyDateTime; public static OperationModeApplicationStorage convert2Storage(Station.OperationModeApplication application) { @@ -207,13 +214,16 @@ public class StorageStation extends StorageStatusDevice { storage.setSource(application.getSource()); storage.setTarget(application.getTarget()); storage.setApplyDateTime(application.getApplyDateTime()); + storage.setApprovalMemberIds(application.getApprovalMember().stream().map(SimulationMember::getId).collect(Collectors.toList())); return storage; } public Station.OperationModeApplication recover2Simulation(Simulation simulation){ SimulationMember simulationMember = simulation.getSimulationMemberById(applicationMemberId); + List approvalMember = approvalMemberIds.stream().map(simulation::getSimulationMemberById).collect(Collectors.toList()); Station.OperationModeApplication application =new Station.OperationModeApplication(simulationMember, source, target); application.setApplyDateTime(applyDateTime); + application.setApprovalMember(approvalMember); return application; } } diff --git a/src/main/java/club/joylink/rtss/simulation/cbtc/robot/SimulationRobotService.java b/src/main/java/club/joylink/rtss/simulation/cbtc/robot/SimulationRobotService.java index ad98e0f06..89f2d30e7 100644 --- a/src/main/java/club/joylink/rtss/simulation/cbtc/robot/SimulationRobotService.java +++ b/src/main/java/club/joylink/rtss/simulation/cbtc/robot/SimulationRobotService.java @@ -570,9 +570,16 @@ public class SimulationRobotService { if (simulation.getScript() != null && simulation.getScript().isBgSet()) { return; } - simulation.getRepository().getStationList().stream().filter(station -> station.getOperationModeApplication() != null) - .forEach(station -> atsStationService.replyOperationMode(simulation, station)); + // 实训场景模式,已设置背景处于编制状态的实训,不做自动转换处理 + Training2 training2 = simulation.getTraining2(); + if (training2 != null && training2.isScene() && StringUtils.hasText(training2.getBgSceneJson()) && !training2.isRunning()) { + return; + } + simulation.getRepository().getStationList().stream() + .filter(station -> station.getOperationModeApplication() != null && station.getOperationModeApplication().isRobotApproval()) + .forEach(station -> atsStationService.doOperationModeSwitch(station)); } + private void doControlBySpeedCurve(Simulation simulation, VirtualRealityTrain train, SpeedCurve speedCurve, float remainDistance) { if (speedCurve.equals(SpeedCurve.ZERO)) { this.doBreakMax(simulation, train); diff --git a/src/main/java/club/joylink/rtss/vo/paper/PaperSubmitAnswerReqVo.java b/src/main/java/club/joylink/rtss/vo/paper/PaperSubmitAnswerReqVo.java index 17a55e827..b12fb39f0 100644 --- a/src/main/java/club/joylink/rtss/vo/paper/PaperSubmitAnswerReqVo.java +++ b/src/main/java/club/joylink/rtss/vo/paper/PaperSubmitAnswerReqVo.java @@ -51,6 +51,7 @@ public class PaperSubmitAnswerReqVo { @Data public static class AnswerDetail{ private String cosplayMemberId; + private int sumScore; private List trainDetail; } } diff --git a/src/main/java/club/joylink/rtss/vo/paper/TrainAnswerVO.java b/src/main/java/club/joylink/rtss/vo/paper/TrainAnswerVO.java index edf61eae1..4554f1f1f 100644 --- a/src/main/java/club/joylink/rtss/vo/paper/TrainAnswerVO.java +++ b/src/main/java/club/joylink/rtss/vo/paper/TrainAnswerVO.java @@ -1,15 +1,27 @@ package club.joylink.rtss.vo.paper; +import club.joylink.rtss.util.JsonUtils; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import java.util.List; +import java.util.Objects; @Data @AllArgsConstructor @NoArgsConstructor -public class TrainAnswerVO { +public class TrainAnswerVO { private PaperQuestionState state; - private PaperSubmitAnswerReqVo.AnswerDetail detail; + private V detail; + + public String getDetailStr(){ + if(Objects.isNull(detail)){ + return null; + } + if(this.detail instanceof String){ + return this.detail.toString(); + } + return JsonUtils.writeValueAsString(this.detail); + } }