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

This commit is contained in:
tiger_zhou 2022-09-01 13:58:23 +08:00
commit 4d991d82ab
173 changed files with 14799 additions and 5001 deletions

20
pom.xml
View File

@ -102,13 +102,13 @@
<version>0.2.1</version>
</dependency>
<dependency>
<groupId>com.huawei.sis</groupId>
<artifactId>huaweicloud-java-sdk-sis</artifactId>
<version>1.3.2</version>
<scope>system</scope>
<systemPath>${project.basedir}/libs/huaweicloud-java-sdk-sis-1.3.2.jar</systemPath>
</dependency>
<!-- <dependency>-->
<!-- <groupId>com.huawei.sis</groupId>-->
<!-- <artifactId>huaweicloud-java-sdk-sis</artifactId>-->
<!-- <version>1.3.2</version>-->
<!-- <scope>system</scope>-->
<!-- <systemPath>${project.basedir}/libs/huaweicloud-java-sdk-sis-1.3.2.jar</systemPath>-->
<!-- </dependency>-->
<dependency>
<groupId>com.huawei.apigateway</groupId>
@ -129,7 +129,11 @@
<artifactId>joda-time</artifactId>
<version>2.10.3</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>31.1-jre</version>
</dependency>
</dependencies>
<build>

3
sql/20220825-zhouyin.sql Normal file
View File

@ -0,0 +1,3 @@
-- 出入口方向添加方向属性,需要重新编辑地图中出入口方向的属性
ALTER TABLE `draft_map_station_direction_label`
ADD COLUMN `io_direction` varchar(20) NULL COMMENT '出入口方向';

View File

@ -0,0 +1,48 @@
/*
Navicat Premium Data Transfer
Source Server : walker
Source Server Type : MySQL
Source Server Version : 80029
Source Host : 192.168.3.233:3306
Source Schema : joylink
Target Server Type : MySQL
Target Server Version : 80029
File Encoding : 65001
Date: 30/08/2022 16:02:15
*/
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for draft_training2
-- ----------------------------
DROP TABLE IF EXISTS `draft_training2`;
CREATE TABLE `draft_training2` (
`id` bigint NOT NULL AUTO_INCREMENT,
`name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '实训名称',
`map_id` bigint NULL DEFAULT NULL COMMENT '实训地图id',
`description` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '描述',
`type` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '实训类型(单操 single场景scene',
`label_json` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '标签,用于检索',
`map_location_json` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '地图定位json',
`bg_scene_json` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL COMMENT '初始背景',
`final_scenes_json` mediumtext CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL COMMENT '实训编制完保存为最终场景json数据',
`run_plan_id` bigint NULL DEFAULT NULL COMMENT '运行图id',
`opera_json` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL COMMENT '操作列表json(List<Operation2VO>)',
`step_json` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL COMMENT '步骤列表json(List<Step2VO>的json)',
`scoring_rule_json` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL COMMENT '打分规则列表json(List<ScoringRuleVO>的json)',
`member_json` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL COMMENT '仿真内所有成员',
`player_id_json` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL COMMENT '参演的仿真成员id列表Json',
`failure_condition_json` varchar(555) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '实训失败判定条件',
`creator_id` bigint NULL DEFAULT NULL,
`create_time` datetime NULL DEFAULT NULL,
`update_time` datetime NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE,
INDEX `map_id_index`(`map_id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 36 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;
SET FOREIGN_KEY_CHECKS = 1;

View File

@ -0,0 +1,48 @@
/*
Navicat Premium Data Transfer
Source Server : walker
Source Server Type : MySQL
Source Server Version : 80029
Source Host : 192.168.3.233:3306
Source Schema : joylink
Target Server Type : MySQL
Target Server Version : 80029
File Encoding : 65001
Date: 30/08/2022 16:02:51
*/
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for published_training2
-- ----------------------------
DROP TABLE IF EXISTS `published_training2`;
CREATE TABLE `published_training2` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '已发布实训的id',
`name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '实训名称',
`map_id` bigint NULL DEFAULT NULL COMMENT '实训地图id',
`description` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '实训描述',
`type` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '实训类型(单操 single场景scene',
`label_json` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '标签,用于检索',
`map_location_json` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '地图定位json',
`bg_scene_json` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL COMMENT '初始背景',
`run_plan_id` bigint NULL DEFAULT NULL COMMENT '运行图id',
`opera_json` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL COMMENT '操作列表json(List<Operation2VO>)',
`step_json` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL COMMENT '步骤列表json(List<Step2VO>的json)',
`scoring_rule_json` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL COMMENT '打分规则列表json(List<ScoringRuleVO>的json)',
`member_json` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL COMMENT '仿真内所有成员',
`player_id_json` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL COMMENT '参演的仿真成员id列表Json',
`failure_condition_json` varchar(555) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '实训失败判定条件',
`creator_id` bigint NULL DEFAULT NULL COMMENT '创建者',
`create_time` datetime NULL DEFAULT NULL,
`update_time` datetime NULL DEFAULT NULL,
`state` int NULL DEFAULT NULL COMMENT '已发布实训的状态(0-默认未知1-上架2-下架)',
`final_scenes_json` mediumtext CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL COMMENT '实训编制后的最终场景json数据',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 24 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;
SET FOREIGN_KEY_CHECKS = 1;

View File

@ -61,4 +61,18 @@ public class TaskExecutorConfiguration {
return taskExecutor;
}
/**
* 新实训监控
*/
@Bean("trainingV2Executor")
public TaskExecutor trainExecutor(Environment env) {
ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
taskExecutor.setThreadNamePrefix("ns-training-v2-executor-");
taskExecutor.setCorePoolSize(2);
taskExecutor.setMaxPoolSize(2);
taskExecutor.setQueueCapacity(100);
taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
taskExecutor.initialize();
return taskExecutor;
}
}

View File

@ -4,25 +4,31 @@ import lombok.Getter;
@Getter
public enum MapPrdTypeEnum {
LOCAL("01", "ATS现地工作站"),
CENTER("02", "ATS行调工作站"),
JOINT("03", "综合演练云平台"),
DRIVER("04", "司机模拟驾驶系统"),
SCHEDULING("05", "派班工作站"),
ISCS("06", "ISCS工作站"),
BIG_SCREEN("07", "大屏工作站"),
RUN_PLAN_MAKE("08", "运行图编制工作站"),
DEPOT_IL("09", "车辆段联锁工作站"),
CTC("10", "CTC工作站")
LOCAL("01", "ATS现地工作站", "车站"),
CENTER("02", "ATS行调工作站", "调度台"),
JOINT("03", "综合演练云平台", "综合演练云平台"),
DRIVER("04", "司机模拟驾驶系统", null),
SCHEDULING("05", "派班工作站", null),
ISCS("06", "ISCS工作站", null),
BIG_SCREEN("07", "大屏工作站", null),
RUN_PLAN_MAKE("08", "运行图编制工作站", null),
DEPOT_IL("09", "车辆段联锁工作站", null),
// CTC("10", "CTC工作站")
;
private String code;
private String msg;
MapPrdTypeEnum(String code, String msg) {
/**
* 大铁子系统名称
*/
private String railName;
MapPrdTypeEnum(String code, String msg, String railName) {
this.code = code;
this.msg = msg;
this.railName = railName;
}
public static MapPrdTypeEnum getMapPrdTypeEnumByCode(String code) {

View File

@ -60,6 +60,8 @@ public enum Project {
RICHOR_CXJS,
/** 哈盈达-铁路 */
HYD_RAILWAY,
/** 武汉8号线 */
WH
;
public static boolean isDefault(Project project) {

View File

@ -0,0 +1,97 @@
package club.joylink.rtss.controller.simulation;
import club.joylink.rtss.controller.advice.AuthenticateInterceptor;
import club.joylink.rtss.services.training2.Training2Service;
import club.joylink.rtss.simulation.cbtc.script.ScriptBO;
import club.joylink.rtss.vo.AccountVO;
import club.joylink.rtss.vo.LoginUserInfoVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
/**
* 第二版实训应用接口
*/
@RestController
@RequestMapping("/api/training2Simulation")
public class SimulationTrainingV2Controller {
@Autowired
private Training2Service training2Service;
/**
* 在仿真中演练发布的实训
*/
@PostMapping("/{group}/load/{trainingId}")
public void trainingLoad(@PathVariable String group, @PathVariable Long trainingId
, @RequestAttribute(name = AuthenticateInterceptor.LOGIN_INFO_KEY) LoginUserInfoVO loginUserInfoVO) {
training2Service.trainingLoad(group, trainingId, loginUserInfoVO);
}
/**
* 在仿真中演练草稿实训
*/
@PostMapping("/{group}/load/draft/{trainingId}")
public void trainingDraftLoad(@PathVariable String group, @PathVariable Long trainingId
, @RequestAttribute(name = AuthenticateInterceptor.LOGIN_INFO_KEY) LoginUserInfoVO loginUserInfoVO) {
training2Service.trainingDraftLoad(group, trainingId, loginUserInfoVO);
}
/**
* 预览实训信息
*/
@GetMapping("/preview/draft/{trainingId}")
public String previewDraft(@PathVariable Long trainingId
, @RequestAttribute(name = AuthenticateInterceptor.LOGIN_INFO_KEY) LoginUserInfoVO loginUserInfoVO) {
return training2Service.previewDraft(trainingId, loginUserInfoVO);
}
/**
* 预览实训信息
*/
@GetMapping("/preview/{trainingId}")
public String preview(@PathVariable Long trainingId
, @RequestAttribute(name = AuthenticateInterceptor.LOGIN_INFO_KEY) LoginUserInfoVO loginUserInfoVO) {
return training2Service.preview(trainingId, loginUserInfoVO);
}
/**
* 预览实训信息
*/
@PutMapping("/{group}/start")
public void startTraining2(@PathVariable String group, ScriptBO.Mode mode, @RequestAttribute AccountVO user) {
training2Service.startTraining2(group, mode, user);
}
/**
* 结束实训
*/
@PutMapping("/{group}/finish")
public Float finishTraining2(@PathVariable String group, @RequestAttribute AccountVO user) {
return training2Service.finishTraining2(group, user);
}
/**
* 客户端步骤完成后操作回调
*/
@PutMapping("/{group}/completion/step/{stepId}")
public Integer completionClientStep(@PathVariable String group, @PathVariable Integer stepId, @RequestAttribute AccountVO user) {
return training2Service.completionClientStep(group, stepId, user);
}
/**
* 客户端步骤完成后操作回调
*/
@PutMapping("/{group}/completion/step/{stepId}/operation/{id}")
public Integer completionClientStepOperation(@PathVariable String group, @PathVariable Integer stepId
, @PathVariable Integer id, @RequestAttribute AccountVO user) {
return training2Service.completionClientStepOperation(group, stepId, id, user);
}
/**
* 绘制剧本
*/
@PostMapping("/{group}/draw/{trainingId}")
public void drawTraining(@PathVariable String group, @PathVariable Long trainingId) {
training2Service.drawTraining(group, trainingId);
}
}

View File

@ -0,0 +1,170 @@
package club.joylink.rtss.controller.training2;
import club.joylink.rtss.services.training2.Training2DraftService;
import club.joylink.rtss.simulation.cbtc.training2.ecm.collector.ExpConditionMaterialCollector;
import club.joylink.rtss.simulation.cbtc.training2.ecm.vo.ExpConditionMaterialSrcVo;
import club.joylink.rtss.vo.AccountVO;
import club.joylink.rtss.vo.client.PageVO;
import club.joylink.rtss.vo.client.simulationv1.SimulationMemberVO;
import club.joylink.rtss.vo.client.training2.ScoringRuleVO;
import club.joylink.rtss.vo.client.training2.Step2VO;
import club.joylink.rtss.vo.training2.draft.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.validation.constraints.NotNull;
import java.util.List;
/**
* 实训草稿管理接口
*/
@Slf4j
@RestController
@RequestMapping("/api/v2/draft/training")
public class TrainingDraftV2Controller {
@Autowired
private Training2DraftService training2DraftService;
@Autowired
private ExpConditionMaterialCollector collector;
/**
* 创建实训草稿
*/
@PostMapping("/create")
public CreateTraining2RspVo create(@RequestBody CreateTraining2ReqVo req, @RequestAttribute AccountVO user) {
log.debug("==>>创建实训草稿: mapId = {} , name = {} type = {} des = {}", req.getMapId(), req.getName(), req.getType(), req.getDescription());
return this.training2DraftService.createTraining(req, user);
}
/**
* 删除当前用户的实训草稿
*/
@DeleteMapping
public DeleteTraining2RspVo deleteTrainings(@RequestBody DeleteTraining2ReqVo req, @RequestAttribute AccountVO user) {
return this.training2DraftService.deleteTrainings(req, user);
}
/**
* 分页获取当前用户实训草稿基础信息
*/
@PostMapping("/info/page")
public PageVO<DraftTraining2InfoVo> findTrainingsInfoByPage(@RequestBody DraftTraining2InfoPageReqVo req, @RequestAttribute AccountVO user) {
return this.training2DraftService.findTrainingsInfoByPage(req, user.getId());
}
/**
* 更新当前用户的某个实训草稿(大字段信息)
*/
@PostMapping("/update/content")
public void updateTraining(@RequestBody UpdateDraftTraining2BlobReqVo req, @RequestAttribute AccountVO user) {
this.training2DraftService.updateTrainingBlob(req, user.getId());
}
/**
* 单独更新当前用户的某个实训草稿的初始背景
* <p>
* 背景内容由后端自己生成
*/
@PostMapping("/update/content/background")
public void updateTrainingBackground(@RequestBody UpdateTraining2BackgroudReqVo req, @RequestAttribute AccountVO user) {
this.training2DraftService.updateTrainingBackground(req, user.getId());
}
/**
* 单独重置当前用户的某个实训草稿的初始背景
*/
@PostMapping("/reset/content/background")
public void resetTrainingBackground(@RequestBody ResetTraining2BackgroudReqVo req, @RequestAttribute AccountVO user) {
this.training2DraftService.resetTrainingBackground(req, user.getId());
}
/**
* 更新当前用户实训草稿定位
*/
@PostMapping("/update/content/maplocation")
public void updateTrainingMapLocation(@RequestBody UpdateTraining2MapLocationReqVo req, @RequestAttribute AccountVO user) {
this.training2DraftService.updateTrainingMapLocation(req, user.getId());
}
/**
* 获取实训表达式条件素材
*/
@GetMapping("/expression/materials")
public List<ExpConditionMaterialSrcVo> findTrainingExpressionMaterials() {
return collector.doCollect();
}
/**
* 更新当前用户的某个实训草稿的基础信息
*/
@PostMapping("/update/info")
public void updateTrainingInfo(@RequestBody UpdateDraftTraining2InfoReqVo req, @RequestAttribute AccountVO user) {
this.training2DraftService.updateTrainingInfo(req, user.getId());
}
/**
* 获取当前用户的某个实训草稿的所有信息
*/
@GetMapping("/all/{trainingId}")
public DraftTraining2DetailRspVo findTrainingDetail(@NotNull(message = "实训草稿id不能为空") @PathVariable("trainingId") Long trainingDraftId, @RequestAttribute AccountVO user) {
return this.training2DraftService.findTrainingDetail(trainingDraftId, user.getId());
}
/**
* 查询步骤列表
*/
@GetMapping("/{trainingId}/step/list")
public List<Step2VO> stepList(@PathVariable("trainingId") Long trainingId) {
return training2DraftService.stepList(trainingId);
}
/**
* 修改实训所有步骤
*/
@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);
}
/**
* 清空步骤
*/
@DeleteMapping("/{trainingId}/step/clear")
public void clearStep(@PathVariable("trainingId") Long trainingId) {
training2DraftService.clearStep(trainingId);
}
/**
* 获取所有评分规则
*/
@GetMapping("/{trainingId}/scoringRule/list")
public List<ScoringRuleVO> getScoringRuleVOS(@PathVariable Long trainingId) {
return training2DraftService.getScoringRules(trainingId);
}
/**
* 更新所有评分规则
*/
@PutMapping("/{trainingId}/scoringRule/list")
public void updateScoringRules(@PathVariable Long trainingId, @RequestBody List<ScoringRuleVO> scoringRuleVOS) {
training2DraftService.updateScoringRules(trainingId, scoringRuleVOS);
}
/**
* 获取实训所有成员
*/
@GetMapping("/{trainingId}/member/list")
public List<SimulationMemberVO> getMembers(@PathVariable Long trainingId) {
return training2DraftService.getMembers(trainingId);
}
/**
* 获取实训所有参与者
*/
@GetMapping("/{trainingId}/player/list")
public List<SimulationMemberVO> getPlayers(@PathVariable Long trainingId) {
return training2DraftService.getPlayers(trainingId);
}
}

View File

@ -0,0 +1,26 @@
package club.joylink.rtss.controller.training2;
import club.joylink.rtss.services.training2.Training2DraftPublishService;
import club.joylink.rtss.vo.AccountVO;
import club.joylink.rtss.vo.training2.draft.TrainingDraftPublishReqVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
/**
* 实训草稿发布管理接口
*/
@Slf4j
@RestController
@RequestMapping("/api/v2/draft/training/publish")
public class TrainingDraftV2PublishController {
@Autowired
private Training2DraftPublishService publishService;
/**
* 当前用户发布自己的实训草稿
*/
@PostMapping
public void draftPublish(@RequestBody TrainingDraftPublishReqVo req, @RequestAttribute AccountVO user){
this.publishService.draftPublish(req,user.getId());
}
}

View File

@ -0,0 +1,71 @@
package club.joylink.rtss.controller.training2;
import club.joylink.rtss.services.training2.Training2PublishService;
import club.joylink.rtss.vo.client.PageVO;
import club.joylink.rtss.vo.training2.publish.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* 已发布实训管理接口
*/
@Slf4j
@RestController
@RequestMapping("/api/v2/training/published")
public class TrainingV2PublishController {
@Autowired
private Training2PublishService publishService;
/**
* 已发布实训分页列表
*/
@PostMapping("/page")
public PageVO<PublishedTraining2InfoRspVo> publishedTrainingsPage(@RequestBody PublishedTraining2InfoPageReqVo req){
return this.publishService.publishedTrainingsPage(req);
}
/**
* 已发布实训上架
*/
@PostMapping("/put/on")
public PutOnPublishedTraining2RspVo putOnPublishedTrainings(@RequestBody PutOnPublishedTraining2ReqVo req){
return this.publishService.putOnPublishedTrainings(req);
}
/**
* 已发布实训下架
*/
@PostMapping("/pull/off")
public PullOffPublishedTraining2RspVo pullOffPublishedTrainings(@RequestBody PullOffPublishedTraining2ReqVo req){
return this.publishService.pullOffPublishedTrainings(req);
}
/**
* 删除已发布实训
*/
@DeleteMapping
public DeletePublishedTraining2RspVo deletePublishedTrainings(@RequestBody DeletePublishedTraining2ReqVo req){
return this.publishService.deletePublishedTrainings(req);
}
/**
* 根据mapId查所有的已发布单操实训的基础信息
*/
@GetMapping("/{mapId}/singles")
public List<PublishedTraining2InfoRspVo> findAllSingleTrainingBasicInfo(@PathVariable("mapId") Long mapId){
return this.publishService.findAllSingleTrainingBasicInfoByMapId(mapId);
}
/**
* 根据mapId查所有的已发布场景实训的基础信息
*/
@GetMapping("/{mapId}/scenes")
public List<PublishedTraining2InfoRspVo> findAllSceneTrainingBasicInfo(@PathVariable("mapId") Long mapId){
return this.publishService.findAllSceneTrainingBasicInfoByMapId(mapId);
}
/**
* 根据实训id查该已发布实训的所有信息
*/
@GetMapping("/{trainingId}")
public PublishedTraining2DetailRspVo findTrainingAllInfo(@PathVariable("trainingId") Long trainingId){
return this.publishService.findTrainingAllInfoById(trainingId);
}
}

View File

@ -0,0 +1,42 @@
package club.joylink.rtss.dao;
import java.util.List;
import club.joylink.rtss.entity.training2.DraftTraining2;
import club.joylink.rtss.entity.training2.DraftTraining2Example;
import club.joylink.rtss.entity.training2.DraftTraining2WithBLOBs;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;
@Mapper
@Repository
public interface DraftTraining2DAO {
long countByExample(DraftTraining2Example example);
int deleteByExample(DraftTraining2Example example);
int deleteByPrimaryKey(Long id);
int insert(DraftTraining2WithBLOBs record);
int insertSelective(DraftTraining2WithBLOBs record);
List<DraftTraining2WithBLOBs> selectByExampleWithBLOBs(DraftTraining2Example example);
List<DraftTraining2> selectByExample(DraftTraining2Example example);
DraftTraining2WithBLOBs selectByPrimaryKey(Long id);
int updateByExampleSelective(@Param("record") DraftTraining2WithBLOBs record, @Param("example") DraftTraining2Example example);
int updateByExampleWithBLOBs(@Param("record") DraftTraining2WithBLOBs record, @Param("example") DraftTraining2Example example);
int updateByExample(@Param("record") DraftTraining2 record, @Param("example") DraftTraining2Example example);
int updateByPrimaryKeySelective(DraftTraining2WithBLOBs record);
int updateByPrimaryKeyWithBLOBs(DraftTraining2WithBLOBs record);
int updateByPrimaryKey(DraftTraining2 record);
}

View File

@ -0,0 +1,42 @@
package club.joylink.rtss.dao;
import java.util.List;
import club.joylink.rtss.entity.training2.PublishedTraining2;
import club.joylink.rtss.entity.training2.PublishedTraining2Example;
import club.joylink.rtss.entity.training2.PublishedTraining2WithBLOBs;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;
@Mapper
@Repository
public interface PublishedTraining2DAO {
long countByExample(PublishedTraining2Example example);
int deleteByExample(PublishedTraining2Example example);
int deleteByPrimaryKey(Long id);
int insert(PublishedTraining2WithBLOBs record);
int insertSelective(PublishedTraining2WithBLOBs record);
List<PublishedTraining2WithBLOBs> selectByExampleWithBLOBs(PublishedTraining2Example example);
List<PublishedTraining2> selectByExample(PublishedTraining2Example example);
PublishedTraining2WithBLOBs selectByPrimaryKey(Long id);
int updateByExampleSelective(@Param("record") PublishedTraining2WithBLOBs record, @Param("example") PublishedTraining2Example example);
int updateByExampleWithBLOBs(@Param("record") PublishedTraining2WithBLOBs record, @Param("example") PublishedTraining2Example example);
int updateByExample(@Param("record") PublishedTraining2 record, @Param("example") PublishedTraining2Example example);
int updateByPrimaryKeySelective(PublishedTraining2WithBLOBs record);
int updateByPrimaryKeyWithBLOBs(PublishedTraining2WithBLOBs record);
int updateByPrimaryKey(PublishedTraining2 record);
}

View File

@ -90,6 +90,11 @@ public class DraftMapStationDirection implements Serializable {
* 相对方向
*/
private String relativeLabelEnum;
/**
* 出入口方向
*/
private StationDirection.IODirection ioDirection;
public void generateSectionList() {
if (StringUtils.isEmpty(sectionsCode)) {

View File

@ -0,0 +1,62 @@
package club.joylink.rtss.entity.training2;
import java.io.Serializable;
import java.time.LocalDateTime;
import lombok.Data;
/**
* @author
*
*/
@Data
public class DraftTraining2 implements Serializable {
private Long id;
/**
* 实训名称
*/
private String name;
/**
* 实训地图id
*/
private Long mapId;
/**
* 描述
*/
private String description;
/**
* 实训类型单操 single场景scene
*/
private String type;
/**
* 标签用于检索
*/
private String labelJson;
/**
* 地图定位json
*/
private String mapLocationJson;
/**
* 运行图id
*/
private Long runPlanId;
/**
* 实训失败判定条件
*/
private String failureConditionJson;
private Long creatorId;
private LocalDateTime createTime;
private LocalDateTime updateTime;
private static final long serialVersionUID = 1L;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,48 @@
package club.joylink.rtss.entity.training2;
import java.io.Serializable;
import lombok.Data;
/**
* @author
*
*/
@Data
public class DraftTraining2WithBLOBs extends DraftTraining2 implements Serializable {
/**
* 初始背景
*/
private String bgSceneJson;
/**
* 实训编制完保存为最终场景json数据
*/
private String finalScenesJson;
/**
* 操作列表json(List<Operation2VO>)
*/
private String operaJson;
/**
* 步骤列表json(List<Step2VO>的json)
*/
private String stepJson;
/**
* 打分规则列表json(List<ScoringRuleVO>的json)
*/
private String scoringRuleJson;
/**
* 仿真内所有成员
*/
private String memberJson;
/**
* 参演的仿真成员id列表Json
*/
private String playerIdJson;
private static final long serialVersionUID = 1L;
}

View File

@ -1,24 +1,37 @@
package club.joylink.rtss.entity.training2;
import java.io.Serializable;
import java.time.LocalDateTime;
import lombok.Data;
public class Training2 {
/**
* @author
*
*/
@Data
public class PublishedTraining2 implements Serializable {
/**
* 已发布实训的id
*/
private Long id;
private Long mapId;
/**
* 名称
* 实训名称
*/
private String name;
/**
* 描述
* 实训地图id
*/
private Long mapId;
/**
* 实训描述
*/
private String description;
/**
* 实训类型单操场景
* 实训类型单操 single场景scene
*/
private String type;
@ -33,50 +46,28 @@ public class Training2 {
private String mapLocationJson;
/**
* 初始背景
* 运行图id
*/
private String bgSceneJson;
private Long runPlanId;
/**
* List<Opera> 的json
* 实训失败判定条件
*/
private String operasJson;
private String failureConditionJson;
/**
* List<Step2> 的json
* 创建者
*/
private String stepsJson;
/**
* 评分规则json
*/
private String scoringRuleJson;
/**
* 保存数据时的背景
*/
private String saveSceneJson;
/**
* 仿真内所有成员
*/
private String memberJson;
/**
* 参演的仿真成员
*/
private String playerJson;
/**
* 状态
*/
private String status;
private Long creatorId;
private LocalDateTime createTime;
private Long updaterId;
private LocalDateTime updateTime;
}
/**
* 已发布实训的状态(0-默认未知1-上架2-下架)
*/
private Integer state;
private static final long serialVersionUID = 1L;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,48 @@
package club.joylink.rtss.entity.training2;
import java.io.Serializable;
import lombok.Data;
/**
* @author
*
*/
@Data
public class PublishedTraining2WithBLOBs extends PublishedTraining2 implements Serializable {
/**
* 初始背景
*/
private String bgSceneJson;
/**
* 操作列表json(List<Operation2VO>)
*/
private String operaJson;
/**
* 步骤列表json(List<Step2VO>的json)
*/
private String stepJson;
/**
* 打分规则列表json(List<ScoringRuleVO>的json)
*/
private String scoringRuleJson;
/**
* 仿真内所有成员
*/
private String memberJson;
/**
* 参演的仿真成员id列表Json
*/
private String playerIdJson;
/**
* 实训编制后的最终场景json数据
*/
private String finalScenesJson;
private static final long serialVersionUID = 1L;
}

View File

@ -35,6 +35,7 @@ public enum BusinessExceptionAssertEnum implements BusinessExceptionAssert {
DATA_ERROR(11000, "data error"),
REPEAT_RUN_PLAN_FROM_CTC_UPDATE_DATA(11200,"repeat run plan"),
CI_GENERATE_ERROR(11001, "ci data generate error"),
MAP_PASSENGER_FLOW_DATA_ERROR(11002, "map passenger flow data error"),
DATA_UNIQUE_PROPERTY_REPEAT(11013, "data unique property repeat"),

View File

@ -64,20 +64,18 @@ public class MapSystemService implements IMapSystemService {
public void generateSystem(Long mapId) {
BusinessExceptionAssertEnum.DATA_NOT_EXIST.assertTrue(iMapService.isExist(mapId),
String.format("id为[%s]的地图不存在", mapId));
MapVO mapDetail = iMapService.getMapDetail(mapId);
for (MapPrdTypeEnum value : MapPrdTypeEnum.values()) {
if (MapPrdTypeEnum.CTC.equals(value)) {
MapVO mapDetail = iMapService.getMapDetail(mapId);
if (!mapDetail.getConfigVO().isRailway()) {
continue;
}
}
generate(mapId, value);
boolean railway = mapDetail.getConfigVO().isRailway();
if (railway && value.getRailName() == null)
continue;
generate(mapId, value, railway);
}
}
private void generate(Long mapId, MapPrdTypeEnum value) {
private void generate(Long mapId, MapPrdTypeEnum value, boolean railway) {
MapSystem system = new MapSystem();
system.setName(value.getMsg());
system.setName(railway ? value.getRailName() : value.getMsg());
system.setMapId(mapId);
system.setPrdType(value.getCode());
system.setStatus(StatusEnum.Valid.getCode());
@ -108,7 +106,12 @@ public class MapSystemService implements IMapSystemService {
String.format("id为[%s]的地图不存在", mapId));
MapPrdTypeEnum prdTypeEnum = MapPrdTypeEnum.getMapPrdTypeEnumByCode(prdType);
BusinessExceptionAssertEnum.ARGUMENT_ILLEGAL.assertNotNull(prdTypeEnum);
generate(mapId, prdTypeEnum);
MapVO mapDetail = iMapService.getMapDetail(mapId);
boolean railway = mapDetail.getConfigVO().isRailway();
if (railway && prdTypeEnum.getRailName() == null) {
return;
}
generate(mapId, prdTypeEnum, railway);
}
private boolean isExist(Long mapId, String prdType, String type) {

View File

@ -20,6 +20,7 @@ import club.joylink.rtss.vo.map.graph.MapSignalButtonVO;
import club.joylink.rtss.vo.map.logic.MapRouteNewVO;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@ -132,6 +133,7 @@ public class DraftMapRouteServiceImpl implements DraftMapRouteService {
update.setOverrunList(routeNewVO.getOverrunList());
update.setHoldStandList(routeNewVO.getHoldStandList());
update.setType(routeNewVO.getType());
update.setLeaveSectionWithAspectMap(routeNewVO.getLeaveSectionWithAspectMap());
DraftMapRoute db = update.convert2Draft();
this.draftMapRouteDAO.updateByPrimaryKeyWithBLOBs(db);
}
@ -258,7 +260,9 @@ public class DraftMapRouteServiceImpl implements DraftMapRouteService {
signalMap.values().stream()
.filter(Signal::hasShuntingFunction)
.forEach(signal -> {
generateShuntingRoute(signal, new ArrayList<>(), new ArrayList<>(), routeMap, routeCodeGenerator, routeVOMap, 0);
Assistant assistant = new Assistant(signal, routeCodeGenerator, routeMap, routeVOMap);
assistant.btnCodes.add(signal.getCode());
generateShuntingRoute(assistant, 0);
});
long passStart = System.currentTimeMillis();
System.out.println("生成调车进路耗时:" + (passStart - dioStart));
@ -274,6 +278,18 @@ public class DraftMapRouteServiceImpl implements DraftMapRouteService {
}
}
System.out.println("生成通过进路耗时:" + (System.currentTimeMillis() - passStart));
/* 长调车进路 */
Map<String, List<Route>> startSignalCode_routes_map = routeMap.values().stream()
.filter(route -> Route.Type.SHUNTING.equals(route.getType()))
.collect(Collectors.groupingBy(route -> route.getStart().getCode()));
startSignalCode_routes_map.values().forEach(routes -> {
routes.forEach(route -> {
Assistant assistant = new Assistant(route.getStart(), routeCodeGenerator, routeMap, routeVOMap);
assistant.startSignalCode_routes_map = startSignalCode_routes_map;
assistant.btnCodes.add(route.getStart().getCode());
generateLongShuntingRoute(assistant, route);
});
});
routeVOMap.values().stream().map(MapRouteNewVO::convert2Draft).forEach(draftMapRoute -> {
draftMapRoute.setMapId(mapId);
@ -282,46 +298,101 @@ public class DraftMapRouteServiceImpl implements DraftMapRouteService {
return new ArrayList<>(routeVOMap.values());
}
private void generateShuntingRoute(Signal signal, List<Section> sections, List<SwitchElement> switches,
Map<String, Route> routeMap, DraftMapCiDataGeneratorImpl.CodeGenerator routeCodeGenerator,
Map<String, MapRouteNewVO> routeVOMap, int iter) {
boolean right = signal.isRight();
/**
* 生成长调车进路
*/
private void generateLongShuntingRoute(Assistant assistant, Route route) {
Signal destination = route.getDestination();
assistant.routes.add(route);
if (assistant.routes.size() > 1) {
String startSignalCode = assistant.startSignal.getCode();
String endSignalCode = destination.getCode();
String startEndSignalCode = startSignalCode + endSignalCode;
if (assistant.routeVOMap.containsKey(startEndSignalCode)) {
return;
}
String code = assistant.routeCodeGenerator.next();
String name = "CD_" + assistant.startSignal.getShowName() + "-" + destination.getShowName();
List<MapRouteAspectVO> aspectVOS = assistant.routes.stream()
.map(r -> new MapRouteAspectVO(r.getCode(), getAspectIndex(route.getAspect())))
.collect(Collectors.toList());
MapRouteNewVO routeNewVO = assistant.routeVOMap.get(route.getStart().getCode() + route.getDestination().getCode());
BusinessExceptionAssertEnum.SYSTEM_EXCEPTION.assertNotNull(routeNewVO);
String endBtnCode = routeNewVO.getBtnCodeList().get(routeNewVO.getBtnCodeList().size() - 1);
List<String> btnCodes = Arrays.asList(startSignalCode, endBtnCode);
MapRouteNewVO mapRouteNewVO = MapRouteNewVO.buildMultiRoute(code, name, startSignalCode, aspectVOS, Route.Type.LONG_SHUNTING, btnCodes);
assistant.routeVOMap.put(startEndSignalCode, mapRouteNewVO);
}
if (destination.isRight() != route.isRight()) { //末端信号机同向
return;
}
Map<String, List<Route>> startSignalCode_route_map = assistant.startSignalCode_routes_map;
List<Route> routes = startSignalCode_route_map.get(destination.getCode());
if (CollectionUtils.isEmpty(routes)) {
return;
}
for (Route value : routes) {
generateLongShuntingRoute(assistant.clone(), value);
}
}
/**
* 生成调车进路
*/
private void generateShuntingRoute(Assistant assistant, int iter) {
Signal startSignal = assistant.startSignal;
List<Section> sections = assistant.sections;
List<SwitchElement> switches = assistant.switches;
List<String> btnCodes = assistant.btnCodes;
boolean right = startSignal.isRight();
Section section;
if (CollectionUtils.isEmpty(sections)) {
section = signal.getSection();
section = startSignal.getSection();
section = section.getNextSection(right);
sections.add(section);
} else {
section = sections.get(sections.size() - 1);
}
Signal oppositeDirSignal = null;
Signal destination = null;
while (section != null) {
Signal sameDirSignal = section.getSignalOf(right);
if (sameDirSignal != null) {
Signal odSignal = section.getSignalOf(!right);
if (odSignal != null) { //同向和反向信号机都有
if (odSignal.isReceivingDepartureSignal()) { //反向信号机是接发车信号机
destination = oppositeDirSignal;
} else {
destination = odSignal;
Signal sdSignal = section.getSignalOf(right); //同向信号机
Signal tempOdSignal = section.getSignalOf(!right); //反向信号机
if (sdSignal != null) {
if (tempOdSignal == null) { //仅有同向信号机
assistant.endSignal = sdSignal;
//如果有并置信号机选反向信号机
Section nextSection = section.getNextSection(right);
if (nextSection != null && nextSection.getSignalOf(!right) != null) { //并置信号机
btnCodes.add(nextSection.getSignalOf(!right).getCode());
}
} else {
if (tempOdSignal.isShunting2()) { //如果反向信号机是列车兼调车信号机
assistant.endSignal = tempOdSignal;
} else if (!tempOdSignal.hasShuntingFunction()) { //无调车功能
assistant.endSignal = assistant.odSignal;
} else {
assistant.endSignal = sdSignal;
btnCodes.add(tempOdSignal.getCode());
}
} else { //只有同向信号机
destination = sameDirSignal;
}
} else {
Signal odSignal = section.getSignalOf(!right);
if (odSignal != null) {
if (odSignal.isReceivingDepartureSignal()) { //反向信号机是接发车信号机
destination = oppositeDirSignal;
} else {
oppositeDirSignal = odSignal;
}
} else if (tempOdSignal != null) {
if (tempOdSignal.isShunting2()) { //如果反向信号机是列车兼调车信号机
assistant.endSignal = tempOdSignal;
} else if (!tempOdSignal.hasShuntingFunction()) { //无调车功能
assistant.endSignal = assistant.odSignal;
}
}
if (tempOdSignal != null) //记录最后一个反向信号机
assistant.odSignal = tempOdSignal;
if (destination != null) {
buildShuntingRoute(signal, sections, switches, routeMap, routeCodeGenerator, routeVOMap, right, destination);
if (assistant.endSignal != null) {
if (btnCodes.size() < 2) { //仅添加了始端信号机按钮
btnCodes.add(assistant.endSignal.getCode());
}
buildShuntingRoute(assistant);
break;
}
@ -331,27 +402,26 @@ public class DraftMapRouteServiceImpl implements DraftMapRouteService {
if (section.getNextSection(!right) != null && section.isSwitchTrack()) { //第一个条件是为了排除边缘的道岔轨道
Switch relSwitch = section.getRelSwitch();
if (relSwitch.isA(section)) {
Assistant assistant2 = assistant.clone();
//定位区段
ArrayList<Section> sections2 = new ArrayList<>(sections);
ArrayList<SwitchElement> switches2 = new ArrayList<>(switches);
sections.add(relSwitch.getB());
switches.add(new SwitchElement(relSwitch, true));
Switch linkedSwitch = relSwitch.queryLinkedSwitch();
if (linkedSwitch != null)
switches.add(new SwitchElement(linkedSwitch, true));
generateShuntingRoute(signal, sections, switches, routeMap, routeCodeGenerator, routeVOMap, iter + 1);
generateShuntingRoute(assistant, iter + 1);
//反位区段
sections2.add(relSwitch.getC());
switches2.add(new SwitchElement(relSwitch, false));
assistant2.sections.add(relSwitch.getC());
assistant2.switches.add(new SwitchElement(relSwitch, false));
Switch axleRelSwitch = relSwitch.queryAxleRelatedOtherSwitch();
if (linkedSwitch != null && axleRelSwitch != null) {
Switch linkedAxleRelSwitch = linkedSwitch.queryAxleRelatedOtherSwitch();
Switch axleRelLinkedSwitch = axleRelSwitch.queryLinkedSwitch();
if (linkedAxleRelSwitch != null && linkedAxleRelSwitch.equals(axleRelLinkedSwitch)) {
switches2.add(new SwitchElement(axleRelSwitch, true));
assistant2.switches.add(new SwitchElement(axleRelSwitch, true));
}
}
generateShuntingRoute(signal, sections2, switches2, routeMap, routeCodeGenerator, routeVOMap, iter + 1);
generateShuntingRoute(assistant2, iter + 1);
break;
} else {
next = relSwitch.getA();
@ -379,8 +449,12 @@ public class DraftMapRouteServiceImpl implements DraftMapRouteService {
if (next != null) {
sections.add(next);
} else { //当找到轨道尽头也仅有一个反向信号机时就以这个反向信号机作为终点
if (oppositeDirSignal != null) {
buildShuntingRoute(signal, sections, switches, routeMap, routeCodeGenerator, routeVOMap, right, oppositeDirSignal);
if (assistant.odSignal != null) {
assistant.endSignal = assistant.odSignal;
if (btnCodes.size() < 2) { //仅添加了始端信号机按钮
btnCodes.add(assistant.endSignal.getCode());
}
buildShuntingRoute(assistant);
break;
}
}
@ -391,33 +465,40 @@ public class DraftMapRouteServiceImpl implements DraftMapRouteService {
/**
* 构建调车进路
*/
private void buildShuntingRoute(Signal signal, List<Section> sections, List<SwitchElement> switches,
Map<String, Route> routeMap, DraftMapCiDataGeneratorImpl.CodeGenerator routeCodeGenerator,
Map<String, MapRouteNewVO> routeVOMap, boolean right, Signal destination) {
boolean sameDir = destination.isRight() == signal.isRight();
//更正途经区段
for (int i = sections.size() - 1; i >= 0; i--) {
Section last = sections.get(i);
if (sameDir) { //同向信号机
if (destination.equals(last.getSignalOf(right))) {
break;
}
} else { //反向信号机
if (destination.equals(last.getSignalOf(!right))) {
sections.remove(i);
break;
}
private void buildShuntingRoute(Assistant assistant) {
BusinessExceptionAssertEnum.SYSTEM_EXCEPTION.assertNotNull(assistant.startSignal);
BusinessExceptionAssertEnum.SYSTEM_EXCEPTION.assertNotNull(assistant.endSignal);
BusinessExceptionAssertEnum.SYSTEM_EXCEPTION.assertCollectionNotEmpty(assistant.sections);
BusinessExceptionAssertEnum.SYSTEM_EXCEPTION.assertNotNull(assistant.routeCodeGenerator);
Signal startSignal = assistant.startSignal;
Signal endSignal = assistant.endSignal;
List<Section> sections = assistant.sections;
List<SwitchElement> switches = assistant.switches;
DraftMapCiDataGeneratorImpl.CodeGenerator routeCodeGenerator = assistant.routeCodeGenerator;
Map<String, Route> routeMap = assistant.routeMap;
Map<String, MapRouteNewVO> routeVOMap = assistant.routeVOMap;
//移除末端信号机所在区段之后的所有区段
ListIterator<Section> iterator = sections.listIterator(sections.size());
Section endSection = endSignal.getSection();
while (iterator.hasPrevious()) {
Section s = iterator.previous();
if (endSection.equals(s)) {
break;
} else {
iterator.remove();
}
sections.remove(i);
}
//添加进路
Route route = new Route(routeCodeGenerator.next(), "D_" + signal.getShowName() + "-" + destination.getShowName());
route.setInterlockStation(signal.getInterlockStation());
route.setStart(signal);
route.setDestination(destination);
Route route = new Route(routeCodeGenerator.next(), "D_" + startSignal.getShowName() + "-" + endSignal.getShowName());
route.setInterlockStation(startSignal.getInterlockStation());
route.setStart(startSignal);
route.setDestination(endSignal);
route.setSectionList(sections);
route.setSwitchList(switches);
route.setAspect(SignalAspect.W);
route.setType(Route.Type.SHUNTING);
String startEndSignalCode = route.getStart().getCode() + route.getDestination().getCode();
Route otherRoute = routeMap.get(startEndSignalCode); //同始终端信号机进路
if (otherRoute != null) { //选择反位道岔更少的/反位道岔更靠后的
@ -450,7 +531,7 @@ public class DraftMapRouteServiceImpl implements DraftMapRouteService {
vo.setEndSectionCode(sections.get(sections.size() - 1).getCode());
vo.setSignalAspect(getAspectIndex(selectedRoute.getAspect()));
routeVOMap.put(startEndSignalCode, vo);
vo.setBtnCodeList(Arrays.asList(route.getStart().getCode(), route.getDestination().getCode()));
vo.setBtnCodeList(assistant.btnCodes);
}
private void generatePassRoute(Signal signal, MapSignalButtonVO buttonVO, Map<String, Route> routeMap,
@ -462,6 +543,7 @@ public class DraftMapRouteServiceImpl implements DraftMapRouteService {
routeVO.setStartSignalCode(signal.getCode());
List<MapRouteAspectVO> routeAspectVOS = new ArrayList<>();
routeVO.setRouteAspectList(routeAspectVOS);
routeVO.setType(Route.Type.PASS);
Signal outboundSignal = null; //出站信号机
boolean right = signal.isRight();
@ -475,9 +557,9 @@ public class DraftMapRouteServiceImpl implements DraftMapRouteService {
routeVO.setName("T_" + signal.getShowName() + "-" + destination.getShowName());
String startEndSignalCode = outboundSignal.getCode() + destination.getCode();
MapRouteNewVO departureRoute = routeVOMap.get(startEndSignalCode); //发车进路
BusinessExceptionAssertEnum.SYSTEM_EXCEPTION.assertTrue(departureRoute.getName().startsWith("L"),
BusinessExceptionAssertEnum.SYSTEM_EXCEPTION.assertTrue(departureRoute.isTrainRoute(),
String.format("信号机[%s]的通过进路的发车进路[%s]不是列车进路", signal.getCode(), departureRoute.getCode()));
routeAspectVOS.add(new MapRouteAspectVO(departureRoute.getCode(), departureRoute.getSignalAspect()));
routeAspectVOS.add(new MapRouteAspectVO(departureRoute.getCode(), getAspectIndex(SignalAspect.Y)));
routeVO.setEndSectionCode(departureRoute.getEndSectionCode());
List<MapSignalButtonVO> buttons = signalCode_button_map.get(destination.getCode());
MapSignalButtonVO endButton = buttons.stream().filter(vo -> MapSignalButtonVO.Type.PICK.equals(vo.getType()))
@ -493,7 +575,7 @@ public class DraftMapRouteServiceImpl implements DraftMapRouteService {
BusinessExceptionAssertEnum.SYSTEM_EXCEPTION.assertNotNull(receivingRoute,
String.format("[%s]接车进路不存在", startEndSignalCode));
routeVO.setStartSectionCode(receivingRoute.getStartSectionCode());
routeAspectVOS.add(new MapRouteAspectVO(receivingRoute.getCode(), receivingRoute.getSignalAspect()));
routeAspectVOS.add(new MapRouteAspectVO(receivingRoute.getCode(), getAspectIndex(SignalAspect.GY)));
outboundSignal = section.getSignalOf(right);
BusinessExceptionAssertEnum.SYSTEM_EXCEPTION.assertNotNull(outboundSignal,
String.format("股道[%s]无出站信号机", section.getCode()));
@ -733,4 +815,82 @@ public class DraftMapRouteServiceImpl implements DraftMapRouteService {
example.createCriteria().andMapIdEqualTo(mapId);
draftMapRouteDAO.deleteByExample(example);
}
@AllArgsConstructor
private class Assistant implements Cloneable {
/**
* 始端信号机
*/
public Signal startSignal;
/**
* 终端信号机
*/
public Signal endSignal;
/**
* 最后一个反向信号机
*/
public Signal odSignal;
/**
* 锁闭区段
*/
public List<Section> sections;
/**
* 锁闭道岔
*/
public List<SwitchElement> switches;
/**
* 按钮列表
*/
public List<String> btnCodes;
/**
* 进路Code生成器
*/
public DraftMapCiDataGeneratorImpl.CodeGenerator routeCodeGenerator;
public Map<String, Route> routeMap;
public Map<String, MapRouteNewVO> routeVOMap;
/**
* 组合进路包含的单元进路
*/
public List<Route> routes;
/**
* 仅调车进路
*/
public Map<String, List<Route>> startSignalCode_routes_map;
public Assistant(Signal startSignal, DraftMapCiDataGeneratorImpl.CodeGenerator routeCodeGenerator, Map<String, Route> routeMap, Map<String, MapRouteNewVO> routeVOMap) {
this.startSignal = startSignal;
this.sections = new ArrayList<>();
this.switches = new ArrayList<>();
this.btnCodes = new ArrayList<>();
this.routeCodeGenerator = routeCodeGenerator;
this.routeMap = routeMap;
this.routeVOMap = routeVOMap;
this.routes = new ArrayList<>();
}
@Override
protected Assistant clone() {
Assistant clone;
try {
clone = (Assistant) super.clone();
} catch (CloneNotSupportedException e) {
throw BusinessExceptionAssertEnum.SYSTEM_EXCEPTION.exception(e);
}
clone.sections = new ArrayList<>(this.sections);
clone.switches = new ArrayList<>(this.switches);
clone.btnCodes = new ArrayList<>(this.btnCodes);
clone.routes = new ArrayList<>(this.routes);
return clone;
}
}
}

View File

@ -313,7 +313,7 @@ public class StationGeneratorNew implements GeneratorNew {
// .filter(station -> station.isTurnBack())
// .collect(Collectors.toList());
// tbStationList.forEach(station -> {
// if (Objects.equals(Operation.Type.Station_Set_Turn_Back_Strategy.name(), operateDefinitionVO.getOperateType())) {
// if (Objects.equals(Operation2.Type.Station_Set_Turn_Back_Strategy.name(), operateDefinitionVO.getOperateType())) {
// station.setControlMode(Station.ControlMode.Center);
// trainingVOList.add(build(config, simulation, station,null, operateDefinitionVO));
// // 仿真重置

View File

@ -0,0 +1,19 @@
package club.joylink.rtss.services.training2;
/**
* 已发布实训的状态(0-默认未知1-上架2-下架)
*/
public enum PublishedTraining2StateEnum {
Default(0),//默认未知
PutOn(1),//上架
PullOff(2),//下架
;
private int state;
private PublishedTraining2StateEnum(int state){
this.state=state;
}
public int getState() {
return state;
}
}

View File

@ -0,0 +1,72 @@
package club.joylink.rtss.services.training2;
import club.joylink.rtss.entity.training2.DraftTraining2;
import club.joylink.rtss.entity.training2.DraftTraining2WithBLOBs;
import club.joylink.rtss.entity.training2.PublishedTraining2;
import club.joylink.rtss.entity.training2.PublishedTraining2WithBLOBs;
import club.joylink.rtss.vo.training2.draft.DraftTraining2InfoVo;
import club.joylink.rtss.vo.training2.publish.PublishedTraining2InfoRspVo;
import java.time.LocalDateTime;
public class Training2Convertor {
public static DraftTraining2InfoVo convertFrom(DraftTraining2 dt){
DraftTraining2InfoVo ti=new DraftTraining2InfoVo();
ti.setCreateTime(dt.getCreateTime());
ti.setCreatorId(dt.getCreatorId());
ti.setId(dt.getId());
ti.setDescription(dt.getDescription());
ti.setLabelJson(dt.getLabelJson());
ti.setMapId(dt.getMapId());
ti.setName(dt.getName());
ti.setUpdateTime(dt.getUpdateTime());
ti.setType(dt.getType());
return ti;
}
/**
* 实训草稿转化为已发布实训注意已发布实训的状态为上架且已发布实训的id为空(数据库自动生成)
*/
public static PublishedTraining2WithBLOBs convertFrom(DraftTraining2WithBLOBs from){
PublishedTraining2WithBLOBs pub = new PublishedTraining2WithBLOBs();
//
pub.setState(PublishedTraining2StateEnum.PutOn.getState());
//
pub.setMemberJson(from.getMemberJson());
pub.setBgSceneJson(from.getBgSceneJson());
pub.setFinalScenesJson(from.getFinalScenesJson());
pub.setOperaJson(from.getOperaJson());
pub.setDescription(from.getDescription());
pub.setCreateTime(LocalDateTime.now());
pub.setUpdateTime(LocalDateTime.now());
pub.setCreatorId(from.getCreatorId());
pub.setName(from.getName());
pub.setPlayerIdJson(from.getPlayerIdJson());
pub.setScoringRuleJson(from.getScoringRuleJson());
pub.setStepJson(from.getStepJson());
pub.setFailureConditionJson(from.getFailureConditionJson());
pub.setLabelJson(from.getLabelJson());
pub.setMapId(from.getMapId());
pub.setMapLocationJson(from.getMapLocationJson());
pub.setType(from.getType());
pub.setRunPlanId(from.getRunPlanId());
//
return pub;
}
public static PublishedTraining2InfoRspVo convertFrom(PublishedTraining2 from){
PublishedTraining2InfoRspVo rsp = new PublishedTraining2InfoRspVo();
rsp.setCreateTime(from.getCreateTime());
rsp.setDescription(from.getDescription());
rsp.setCreatorId(from.getCreatorId());
rsp.setId(from.getId());
rsp.setName(from.getName());
rsp.setLabelJson(from.getLabelJson());
rsp.setMapId(from.getMapId());
rsp.setType(from.getType());
rsp.setFailureConditionJson(from.getFailureConditionJson());
rsp.setUpdateTime(from.getUpdateTime());
rsp.setRunPlanId(from.getRunPlanId());
rsp.setMapLocationJson(from.getMapLocationJson());
rsp.setState(from.getState());
return rsp;
}
}

View File

@ -0,0 +1,51 @@
package club.joylink.rtss.services.training2;
import club.joylink.rtss.dao.DraftTraining2DAO;
import club.joylink.rtss.dao.PublishedTraining2DAO;
import club.joylink.rtss.entity.training2.*;
import club.joylink.rtss.exception.BusinessExceptionAssertEnum;
import club.joylink.rtss.vo.training2.draft.TrainingDraftPublishReqVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
/**
* 实训草稿发布业务实现
*/
@Service
@Slf4j
public class Training2DraftPublishService {
@Autowired
private DraftTraining2DAO trainingDao;
@Autowired
private PublishedTraining2DAO publishedDao;
/**
* 草稿发布
*/
@Transactional(rollbackFor = Exception.class)
public void draftPublish(TrainingDraftPublishReqVo req,Long userId){
Long draftId=Long.valueOf(req.getDraftId());
DraftTraining2Example dtExample=new DraftTraining2Example();
dtExample.createCriteria().andCreatorIdEqualTo(userId).andIdEqualTo(draftId);
List<DraftTraining2WithBLOBs> dtFinds= this.trainingDao.selectByExampleWithBLOBs(dtExample);
BusinessExceptionAssertEnum.SYSTEM_EXCEPTION.assertTrue(null!=dtFinds&&!dtFinds.isEmpty(),"实训草稿不存在");
DraftTraining2WithBLOBs draft = dtFinds.get(0);
//
PublishedTraining2WithBLOBs pub = Training2Convertor.convertFrom(draft);
//根据要发布的草稿名称来查找已发布的实训
//如果以有同名的则会被覆盖
PublishedTraining2Example ptExample=new PublishedTraining2Example();
ptExample.createCriteria().andNameEqualTo(draft.getName());
List<PublishedTraining2> ptFinds= this.publishedDao.selectByExample(ptExample);
//
if(null!=ptFinds&&!ptFinds.isEmpty()){//已发布实训存在时则直接删除
this.publishedDao.deleteByExample(ptExample);
}
//发布
this.publishedDao.insertSelective(pub);
}
}

View File

@ -0,0 +1,444 @@
package club.joylink.rtss.services.training2;
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.rtss.exception.BusinessExceptionAssertEnum;
import club.joylink.rtss.simulation.cbtc.GroupSimulationService;
import club.joylink.rtss.simulation.cbtc.Simulation;
import club.joylink.rtss.simulation.cbtc.data.storage.StorageSimulation;
import club.joylink.rtss.simulation.cbtc.exception.SimulationException;
import club.joylink.rtss.simulation.cbtc.exception.SimulationExceptionType;
import club.joylink.rtss.simulation.cbtc.member.SimulationMemberPO;
import club.joylink.rtss.util.JsonUtils;
import club.joylink.rtss.vo.AccountVO;
import club.joylink.rtss.vo.client.PageVO;
import club.joylink.rtss.vo.client.simulationv1.SimulationMemberVO;
import club.joylink.rtss.vo.client.training2.ScoringRuleVO;
import club.joylink.rtss.vo.client.training2.Step2VO;
import club.joylink.rtss.vo.training2.draft.*;
import io.netty.util.internal.StringUtil;
import lombok.extern.slf4j.Slf4j;
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.StringUtils;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
* 实训草稿业务实现
*/
@Service
@Slf4j
public class Training2DraftService {
@Autowired
private DraftTraining2DAO trainingDao;
@Autowired
private GroupSimulationService roupSimulationService;
/**
* 根据基本信息创建实训
*
* @return 返回创建的实训的id
*/
@Transactional(rollbackFor = Exception.class)
public CreateTraining2RspVo createTraining(CreateTraining2ReqVo req, AccountVO user) {
//校验是否已经有同名的实训
DraftTraining2Example example = new DraftTraining2Example();
example.createCriteria().andNameEqualTo(req.getName());
List<DraftTraining2> check = this.trainingDao.selectByExample(example);
BusinessExceptionAssertEnum.SYSTEM_EXCEPTION.assertCollectionEmpty(check, "实训已经存在");
//
DraftTraining2WithBLOBs dt = new DraftTraining2WithBLOBs();
dt.setMapId(req.getMapId());
dt.setName(req.getName());
dt.setCreatorId(user.getId());
dt.setDescription(req.getDescription());
dt.setType(req.getType());
dt.setLabelJson(req.getLabelJson());
dt.setCreateTime(LocalDateTime.now());
dt.setUpdateTime(LocalDateTime.now());
this.trainingDao.insertSelective(dt);
//
List<DraftTraining2> created = this.trainingDao.selectByExample(example);
BusinessExceptionAssertEnum.SYSTEM_EXCEPTION.assertTrue(null != created && created.size() == 1, "创建实训异常");
//
DraftTraining2 tn = created.get(0);
CreateTraining2RspVo rsp = new CreateTraining2RspVo();
rsp.setId(tn.getId());
rsp.setName(tn.getName());
return rsp;
}
/**
* 删除当前用户的实训草稿
*/
@Transactional(rollbackFor = Exception.class)
public DeleteTraining2RspVo deleteTrainings(DeleteTraining2ReqVo req, AccountVO user) {
DeleteTraining2RspVo rsp = new DeleteTraining2RspVo();
rsp.setTrainingDraftIds(new ArrayList<String>());
for (String sId : req.getTrainingDraftIds()) {
long draftId = Long.valueOf(sId);
DraftTraining2Example dex = new DraftTraining2Example();
dex.createCriteria().andIdEqualTo(draftId).andCreatorIdEqualTo(user.getId());
int drt = this.trainingDao.deleteByExample(dex);
if (drt > 0) {
rsp.getTrainingDraftIds().add(sId);
}
}
return rsp;
}
private boolean isExistDraft(Long userId, String draftName) {
DraftTraining2Example example = new DraftTraining2Example();
example.createCriteria().andCreatorIdEqualTo(userId).andNameEqualTo(draftName);
List<DraftTraining2> find = this.trainingDao.selectByExample(example);
return null != find && !find.isEmpty();
}
/**
* 更新用户实训草稿的初始背景
*/
@Transactional(rollbackFor = Exception.class)
public void updateTrainingBackground(UpdateTraining2BackgroudReqVo req, Long userId) {
DraftTraining2Example example = new DraftTraining2Example();
example.createCriteria().andCreatorIdEqualTo(userId).andIdEqualTo(req.getId());
List<DraftTraining2> find = this.trainingDao.selectByExample(example);
BusinessExceptionAssertEnum.SYSTEM_EXCEPTION.assertTrue(null != find && !find.isEmpty(), "实训草稿不存在");
//
DraftTraining2WithBLOBs b = new DraftTraining2WithBLOBs();
//构建背景
String simulationId = req.getGroupId();
Simulation simulation = this.roupSimulationService.getSimulationByGroup(simulationId);
StorageSimulation scenesSaving = new StorageSimulation(simulation, false);
//保存背景
b.setBgSceneJson((JsonUtils.writeValueAsString(scenesSaving)));
b.setMemberJson(JsonUtils.writeValueAsString(SimulationMemberVO.convert2VOList(simulation.getSimulationMembers())));
b.setUpdateTime(LocalDateTime.now());
//
this.trainingDao.updateByExampleSelective(b, example);
}
/**
* 重置用户实训草稿的初始背景
*/
@Transactional(rollbackFor = Exception.class)
public void resetTrainingBackground(ResetTraining2BackgroudReqVo req, Long userId) {
DraftTraining2Example example = new DraftTraining2Example();
example.createCriteria().andCreatorIdEqualTo(userId).andIdEqualTo(req.getId());
List<DraftTraining2> find = this.trainingDao.selectByExample(example);
BusinessExceptionAssertEnum.SYSTEM_EXCEPTION.assertTrue(null != find && !find.isEmpty(), "实训草稿不存在");
//
DraftTraining2WithBLOBs b = new DraftTraining2WithBLOBs();
b.setBgSceneJson("");
b.setUpdateTime(LocalDateTime.now());
//
this.trainingDao.updateByExampleSelective(b, example);
}
/**
* 更新用户实训草稿的地图定位信息
*/
@Transactional(rollbackFor = Exception.class)
public void updateTrainingMapLocation(UpdateTraining2MapLocationReqVo req, Long userId) {
DraftTraining2Example example = new DraftTraining2Example();
example.createCriteria().andCreatorIdEqualTo(userId).andIdEqualTo(req.getId());
List<DraftTraining2> find = this.trainingDao.selectByExample(example);
BusinessExceptionAssertEnum.SYSTEM_EXCEPTION.assertTrue(null != find && !find.isEmpty(), "实训草稿不存在");
//
DraftTraining2WithBLOBs b = new DraftTraining2WithBLOBs();
//
b.setMapLocationJson(req.getMapLocationJson());
b.setUpdateTime(LocalDateTime.now());
//
this.trainingDao.updateByExampleSelective(b, example);
}
/**
* 更新当前用户的实训草稿基础信息
*/
@Transactional(rollbackFor = Exception.class)
public void updateTrainingInfo(UpdateDraftTraining2InfoReqVo req, Long userId) {
DraftTraining2Example example = new DraftTraining2Example();
example.createCriteria().andCreatorIdEqualTo(userId).andIdEqualTo(req.getId());
List<DraftTraining2> find = this.trainingDao.selectByExample(example);
BusinessExceptionAssertEnum.SYSTEM_EXCEPTION.assertTrue(null != find && !find.isEmpty(), "实训草稿不存在");
//
if (null != req.getName()) {
DraftTraining2 the = find.get(0);
if (!req.getName().equals(the.getName())) {//草稿名称变了
BusinessExceptionAssertEnum.SYSTEM_EXCEPTION.assertNotTrue(this.isExistDraft(userId, req.getName()), "名称为 [" + req.getName() + "] 的草稿已经存在");
}
}
//
DraftTraining2WithBLOBs b = new DraftTraining2WithBLOBs();
//
b.setName(req.getName());
b.setDescription(req.getDescription());
b.setType(req.getType());
b.setLabelJson(req.getLabelJson());
//
b.setUpdateTime(LocalDateTime.now());
//
this.trainingDao.updateByExampleSelective(b, example);
}
/**
* 更新当前用户的实训草稿大字段信息
*/
@Transactional(rollbackFor = Exception.class)
public void updateTrainingBlob(UpdateDraftTraining2BlobReqVo req, Long userId) {
DraftTraining2Example example = new DraftTraining2Example();
example.createCriteria().andCreatorIdEqualTo(userId).andIdEqualTo(req.getId());
List<DraftTraining2> find = this.trainingDao.selectByExample(example);
BusinessExceptionAssertEnum.SYSTEM_EXCEPTION.assertTrue(null != find && !find.isEmpty(), "实训草稿不存在");
//
DraftTraining2WithBLOBs b = new DraftTraining2WithBLOBs();
//
b.setMapId(req.getMapId());
b.setBgSceneJson(req.getBgSceneJson());
b.setMapLocationJson(req.getMapLocationJson());
b.setRunPlanId(req.getRunPlanId());
b.setOperaJson(req.getOperaJson());
b.setStepJson(req.getStepJson());
b.setScoringRuleJson(req.getScoringRuleJson());
b.setMemberJson(req.getMemberJson());
b.setPlayerIdJson(req.getPlayerIdJson());
b.setFailureConditionJson(req.getFailureConditionJson());
//
b.setUpdateTime(LocalDateTime.now());
//
this.trainingDao.updateByExampleSelective(b, example);
}
/**
* 获取实训草稿的所有信息
*/
@Transactional(readOnly = true)
public DraftTraining2DetailRspVo findTrainingDetail(Long trainingDraftId, Long userId) {
DraftTraining2Example example = new DraftTraining2Example();
example.createCriteria().andCreatorIdEqualTo(userId).andIdEqualTo(trainingDraftId);
List<DraftTraining2WithBLOBs> bs = this.trainingDao.selectByExampleWithBLOBs(example);
if (null != bs && !bs.isEmpty()) {
DraftTraining2WithBLOBs b = bs.get(0);
DraftTraining2DetailRspVo rsp = new DraftTraining2DetailRspVo();
rsp.setDescription(b.getDescription());
rsp.setFailureConditionJson(b.getFailureConditionJson());
rsp.setCreateTime(b.getCreateTime());
rsp.setCreatorId(b.getCreatorId());
rsp.setLabelJson(b.getLabelJson());
rsp.setMapId(b.getMapId());
rsp.setName(b.getName());
rsp.setId(b.getId());
rsp.setType(b.getType());
rsp.setBgSceneJson(b.getBgSceneJson());
rsp.setMemberJson(b.getMemberJson());
rsp.setOperaJson(b.getOperaJson());
rsp.setStepJson(b.getStepJson());
rsp.setUpdateTime(b.getUpdateTime());
rsp.setPlayerIdJson(b.getPlayerIdJson());
rsp.setMapLocationJson(b.getMapLocationJson());
rsp.setRunPlanId(b.getRunPlanId());
rsp.setScoringRuleJson(b.getScoringRuleJson());
return rsp;
} else {
return null;
}
}
/**
* 分页获取当前用户草稿基础信息
*/
@Transactional(readOnly = true)
public PageVO<DraftTraining2InfoVo> findTrainingsInfoByPage(DraftTraining2InfoPageReqVo req, Long userId) {
PageVO<DraftTraining2InfoVo> page = new PageVO<>();
//
DraftTraining2Example example = new DraftTraining2Example();
DraftTraining2Example.Criteria c = example.createCriteria().andCreatorIdEqualTo(userId);
if (null != req.getMapId()) {
c.andMapIdEqualTo(req.getMapId());
}
//
long sum = this.trainingDao.countByExample(example);
page.setTotal(sum);
page.setPageNum(req.getPageNum());
page.setPageSize(req.getPageSize());
page.setList(new ArrayList<>());
if (sum > 0) {
//1--创建时间 2--更新时间 3--草稿名称默认值为1
String orderBy = "create_time";
switch (req.getOrderBy()) {
case 1:
orderBy = "create_time";
break;
case 2:
orderBy = "update_time";
break;
case 3:
orderBy = "name";
break;
}
long startIndex = (req.getPageNum() - 1) * req.getPageSize();
//
if (req.getDesc()) {
example.setOrderByClause(String.format("%s desc limit %s,%s", orderBy, startIndex, req.getPageSize()));
} else {
example.setOrderByClause(String.format("%s limit %s,%s", orderBy, startIndex, req.getPageSize()));
}
List<DraftTraining2> pContent = this.trainingDao.selectByExample(example);
if (null != pContent) {
pContent.forEach(t -> {
page.getList().add(Training2Convertor.convertFrom(t));
});
}
}
//
return page;
}
/**
* 实训步骤列表
*/
public List<Step2VO> stepList(Long trainingId) {
DraftTraining2WithBLOBs draftTraining2 = trainingDao.selectByPrimaryKey(trainingId);
if (draftTraining2 == null) {
throw new SimulationException(SimulationExceptionType.Data_Not_Exist, "实训不存在");
}
if (StringUtils.isEmpty(draftTraining2.getStepJson())) {
return new ArrayList<>();
} else {
return JsonUtils.readCollection(draftTraining2.getStepJson(), List.class, Step2VO.class);
}
}
/**
* 修改实训所有步骤
*/
public void updateSteps(String group, Long trainingId, List<Step2VO> step2VOList) {
DraftTraining2WithBLOBs draftTraining2 = trainingDao.selectByPrimaryKey(trainingId);
if (draftTraining2 == null) {
throw new SimulationException(SimulationExceptionType.Data_Not_Exist, "实训不存在");
}
// 保存当前背景
Simulation simulation = this.roupSimulationService.getSimulationByGroup(group);
String stepJson;
if (CollectionUtils.isEmpty(step2VOList)) {
stepJson = StringUtil.EMPTY_STRING;
} else {
stepJson = JsonUtils.writeValueAsString(step2VOList);
}
// 扮演者集合
List<String> playerList = step2VOList.stream().
filter(s -> !StringUtils.isEmpty(s.getMemberId())).map(s -> s.getMemberId())
.distinct().collect(Collectors.toList());
if (CollectionUtils.isEmpty(playerList)) {
throw new SimulationException(SimulationExceptionType.Data_Not_Exist, "错误数据:无扮演者");
}
DraftTraining2WithBLOBs updateObj = new DraftTraining2WithBLOBs();
updateObj.setId(trainingId);
updateObj.setStepJson(stepJson);
updateObj.setPlayerIdJson(JsonUtils.writeValueAsString(playerList));
// 背景
StorageSimulation scenesSaving = new StorageSimulation(simulation, false);
updateObj.setFinalScenesJson(JsonUtils.writeValueAsString(scenesSaving));
// 成员信息
List<SimulationMemberPO> simulationMemberPOList = SimulationMemberPO.convertFromBOList(simulation.getSimulationMembers());
updateObj.setMemberJson(JsonUtils.writeValueAsString(simulationMemberPOList));
trainingDao.updateByPrimaryKeySelective(updateObj);
}
/**
* 清空步骤
*/
public void clearStep(Long trainingId) {
DraftTraining2WithBLOBs draftTraining2 = trainingDao.selectByPrimaryKey(trainingId);
if (draftTraining2 == null) {
throw new SimulationException(SimulationExceptionType.Data_Not_Exist, "实训不存在");
}
DraftTraining2WithBLOBs updateObj = new DraftTraining2WithBLOBs();
updateObj.setId(trainingId);
updateObj.setStepJson(StringUtil.EMPTY_STRING);
updateObj.setPlayerIdJson(StringUtil.EMPTY_STRING);
updateObj.setFinalScenesJson(StringUtil.EMPTY_STRING);
trainingDao.updateByPrimaryKeySelective(updateObj);
}
public List<ScoringRuleVO> getScoringRules(Long trainingId) {
DraftTraining2WithBLOBs draftTraining2 = getEntityWithBLOBs(trainingId);
String scoringRuleJson = draftTraining2.getScoringRuleJson();
if (StringUtils.hasText(scoringRuleJson)) {
return JsonUtils.readCollection(scoringRuleJson, List.class, ScoringRuleVO.class);
} else {
return new ArrayList<>();
}
}
public void updateScoringRules(Long trainingId, List<ScoringRuleVO> scoringRuleVOS) {
confirmExist(trainingId);
String json = scoringRuleVOS == null ? "" : JsonUtils.writeValueAsString(scoringRuleVOS);
DraftTraining2WithBLOBs updateEntity = new DraftTraining2WithBLOBs();
updateEntity.setId(trainingId);
updateEntity.setScoringRuleJson(json);
trainingDao.updateByPrimaryKeySelective(updateEntity);
}
private boolean isExist(long id) {
DraftTraining2Example example = new DraftTraining2Example();
example.createCriteria().andIdEqualTo(id);
long count = trainingDao.countByExample(example);
return count > 0;
}
public void confirmExist(long id) {
BusinessExceptionAssertEnum.DATA_NOT_EXIST.assertTrue(isExist(id),
String.format("[id:%s]的实训不存在", id));
}
private DraftTraining2WithBLOBs getEntityWithBLOBs(long id) {
DraftTraining2WithBLOBs entityWithBLOBs = findEntityWithBLOBs(id);
BusinessExceptionAssertEnum.DATA_NOT_EXIST.assertNotNull(entityWithBLOBs,
String.format("[id:%s]的实训不存在", id));
return entityWithBLOBs;
}
private DraftTraining2WithBLOBs findEntityWithBLOBs(long id) {
return trainingDao.selectByPrimaryKey(id);
}
public List<SimulationMemberVO> getMembers(Long trainingId) {
DraftTraining2WithBLOBs entity = getEntityWithBLOBs(trainingId);
String memberJson = entity.getMemberJson();
if (StringUtils.hasText(memberJson)) {
return JsonUtils.readCollection(memberJson, List.class, SimulationMemberVO.class);
} else {
return new ArrayList<>();
}
}
public List<SimulationMemberVO> getPlayers(Long trainingId) {
DraftTraining2WithBLOBs entity = getEntityWithBLOBs(trainingId);
String memberJson = entity.getMemberJson();
String playerIdJson = entity.getPlayerIdJson();
if (!StringUtils.hasText(playerIdJson)) {
return new ArrayList<>();
}
if (!StringUtils.hasText(memberJson)) {
return new ArrayList<>();
}
List<SimulationMemberVO> members = JsonUtils.readCollection(memberJson, List.class, SimulationMemberVO.class);
Map<String, SimulationMemberVO> memberMap = members.stream()
.collect(Collectors.toMap(SimulationMemberVO::getId, Function.identity()));
List<String> playerIds = JsonUtils.readCollection(playerIdJson, List.class, String.class);
return playerIds.stream().map(memberMap::get).collect(Collectors.toList());
}
}

View File

@ -0,0 +1,206 @@
package club.joylink.rtss.services.training2;
import club.joylink.rtss.dao.PublishedTraining2DAO;
import club.joylink.rtss.entity.training2.PublishedTraining2;
import club.joylink.rtss.entity.training2.PublishedTraining2Example;
import club.joylink.rtss.entity.training2.PublishedTraining2WithBLOBs;
import club.joylink.rtss.vo.client.PageVO;
import club.joylink.rtss.vo.training2.publish.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
/**
* 已发布实训管理业务实现
*/
@Service
@Slf4j
public class Training2PublishService {
@Autowired
private PublishedTraining2DAO publishedDao;
/**
* 已发布实训分页列表
*/
@Transactional(readOnly = true)
public PageVO<PublishedTraining2InfoRspVo> publishedTrainingsPage(PublishedTraining2InfoPageReqVo req){
PageVO<PublishedTraining2InfoRspVo> page = new PageVO<>();
PublishedTraining2Example example = new PublishedTraining2Example();
PublishedTraining2Example.Criteria c =example.createCriteria();
if(null!=req.getState()){
c.andStateEqualTo(req.getState());
}
long sum = this.publishedDao.countByExample(example);
page.setTotal(sum);
page.setPageNum(req.getPageNum());
page.setPageSize(req.getPageSize());
page.setList(new ArrayList<>());
//
if(sum>0){
//1--创建时间 2--更新时间 3--草稿名称默认值为1
String orderBy="create_time";
switch(req.getOrderBy()){
case 1:orderBy="create_time";break;
case 2:orderBy="update_time";break;
case 3:orderBy="name";break;
case 4:orderBy="state";break;
}
long startIndex = (req.getPageNum() - 1) * req.getPageSize();
//
if (req.getDesc()) {
example.setOrderByClause(String.format("%s desc limit %s,%s", orderBy,startIndex, req.getPageSize()));
} else {
example.setOrderByClause(String.format("%s limit %s,%s", orderBy,startIndex, req.getPageSize()));
}
//
List<PublishedTraining2> pCt= this.publishedDao.selectByExample(example);
if(null!=pCt){
pCt.forEach(p->{
page.getList().add(Training2Convertor.convertFrom(p));
});
}
}
//
return page;
}
/**
* 已发布实训上架
*/
@Transactional(rollbackFor = Exception.class)
public PutOnPublishedTraining2RspVo putOnPublishedTrainings(PutOnPublishedTraining2ReqVo req){
final PutOnPublishedTraining2RspVo rsp =new PutOnPublishedTraining2RspVo();
rsp.setIds(new ArrayList<>());
req.getIds().forEach(id->{
PublishedTraining2WithBLOBs pub =new PublishedTraining2WithBLOBs();
pub.setId(Long.valueOf(id));
pub.setState(PublishedTraining2StateEnum.PutOn.getState());
pub.setUpdateTime(LocalDateTime.now());
//
PublishedTraining2Example example=new PublishedTraining2Example();
example.createCriteria().andIdEqualTo(pub.getId());
//
int urt= this.publishedDao.updateByExampleSelective(pub,example);
if(urt>0){//记录更新成功的
rsp.getIds().add(id);
}
});
return rsp;
}
/**
* 已发布实训下架
*/
@Transactional(rollbackFor = Exception.class)
public PullOffPublishedTraining2RspVo pullOffPublishedTrainings(PullOffPublishedTraining2ReqVo req){
final PullOffPublishedTraining2RspVo rsp =new PullOffPublishedTraining2RspVo();
rsp.setIds(new ArrayList<>());
req.getIds().forEach(id->{
PublishedTraining2WithBLOBs pub =new PublishedTraining2WithBLOBs();
pub.setId(Long.valueOf(id));
pub.setState(PublishedTraining2StateEnum.PullOff.getState());
pub.setUpdateTime(LocalDateTime.now());
//
PublishedTraining2Example example=new PublishedTraining2Example();
example.createCriteria().andIdEqualTo(pub.getId());
//
int urt= this.publishedDao.updateByExampleSelective(pub,example);
if(urt>0){//记录更新成功的
rsp.getIds().add(id);
}
});
return rsp;
}
/**
* 删除已发布实训
*/
@Transactional(rollbackFor = Exception.class)
public DeletePublishedTraining2RspVo deletePublishedTrainings(DeletePublishedTraining2ReqVo req){
DeletePublishedTraining2RspVo rsp = new DeletePublishedTraining2RspVo();
rsp.setIds(new ArrayList<>());
//
if(null!=req.getIds()){
req.getIds().forEach(id->{
int drt= this.publishedDao.deleteByPrimaryKey(Long.valueOf(id));
if(drt>0){
rsp.getIds().add(id);
}
});
}
//
return rsp;
}
/**
* 根据mapId查找所有的单操实训的基础信息
*/
@Transactional(readOnly = true)
public List<PublishedTraining2InfoRspVo> findAllSingleTrainingBasicInfoByMapId(Long mapId){
List<PublishedTraining2InfoRspVo> rsp =new ArrayList<>();
//
PublishedTraining2Example example = new PublishedTraining2Example();
example.createCriteria().andMapIdEqualTo(mapId).andTypeEqualTo(Training2TypeEnum.single.value());
List<PublishedTraining2> list = this.publishedDao.selectByExample(example);
if(!CollectionUtils.isEmpty(list)){
list.forEach(p->{
rsp.add(Training2Convertor.convertFrom(p));
});
}
//
return rsp;
}
/**
* 根据mapId查找所有的场景实训的基础信息
*/
@Transactional(readOnly = true)
public List<PublishedTraining2InfoRspVo> findAllSceneTrainingBasicInfoByMapId(Long mapId){
List<PublishedTraining2InfoRspVo> rsp =new ArrayList<>();
//
PublishedTraining2Example example = new PublishedTraining2Example();
example.createCriteria().andMapIdEqualTo(mapId).andTypeEqualTo(Training2TypeEnum.scene.value());
List<PublishedTraining2> list = this.publishedDao.selectByExample(example);
if(!CollectionUtils.isEmpty(list)){
list.forEach(p->{
rsp.add(Training2Convertor.convertFrom(p));
});
}
//
return rsp;
}
/**
* 根据已发布实训的id来查询实现的所有信息
*/
@Transactional(readOnly = true)
public PublishedTraining2DetailRspVo findTrainingAllInfoById(Long trainingId){
PublishedTraining2WithBLOBs b= this.publishedDao.selectByPrimaryKey(trainingId);
if(null!=b){
PublishedTraining2DetailRspVo rsp = new PublishedTraining2DetailRspVo();
//
rsp.setDescription(b.getDescription());
rsp.setFailureConditionJson(b.getFailureConditionJson());
rsp.setCreateTime(b.getCreateTime());
rsp.setCreatorId(b.getCreatorId());
rsp.setLabelJson(b.getLabelJson());
rsp.setMapId(b.getMapId());
rsp.setName(b.getName());
rsp.setId(b.getId());
rsp.setType(b.getType());
rsp.setBgSceneJson(b.getBgSceneJson());
rsp.setMemberJson(b.getMemberJson());
rsp.setOperaJson(b.getOperaJson());
rsp.setStepJson(b.getStepJson());
rsp.setUpdateTime(b.getUpdateTime());
rsp.setPlayerIdJson(b.getPlayerIdJson());
rsp.setMapLocationJson(b.getMapLocationJson());
rsp.setRunPlanId(b.getRunPlanId());
rsp.setScoringRuleJson(b.getScoringRuleJson());
rsp.setState(b.getState());
rsp.setFinalScenesJson(b.getFinalScenesJson());
//
return rsp;
}
return null;
}
}

View File

@ -0,0 +1,521 @@
package club.joylink.rtss.services.training2;
import club.joylink.rtss.dao.DraftTraining2DAO;
import club.joylink.rtss.dao.PublishedTraining2DAO;
import club.joylink.rtss.entity.training2.DraftTraining2WithBLOBs;
import club.joylink.rtss.entity.training2.PublishedTraining2WithBLOBs;
import club.joylink.rtss.simulation.cbtc.ATS.operation.AtsOperationDispatcher;
import club.joylink.rtss.simulation.cbtc.GroupSimulationCache;
import club.joylink.rtss.simulation.cbtc.GroupSimulationService;
import club.joylink.rtss.simulation.cbtc.Simulation;
import club.joylink.rtss.simulation.cbtc.SimulationLifeCycleService;
import club.joylink.rtss.simulation.cbtc.event.SimulationOperationEvent;
import club.joylink.rtss.simulation.cbtc.exception.SimulationException;
import club.joylink.rtss.simulation.cbtc.exception.SimulationExceptionType;
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.Step2;
import club.joylink.rtss.simulation.cbtc.training2.Training2;
import club.joylink.rtss.util.JsonUtils;
import club.joylink.rtss.vo.AccountVO;
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.websocket.StompMessageService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.function.Consumer;
@Service
public class Training2Service {
public static final String EXECUTE_JOB_NAME = "Training2";
public static final String SCORING_JOB_NAME = "Training2Scoring";
public static final int RATE = 1000;
@Autowired
private AtsOperationDispatcher atsOperationDispatcher;
@Autowired
private PublishedTraining2DAO training2DAO;
@Autowired
private DraftTraining2DAO draftTrainingDao;
@Autowired
private MemberManager memberManager;
@Autowired
private GroupSimulationService groupSimulationService;
@Autowired
private GroupSimulationCache groupSimulationCache;
@Autowired
private SimulationLifeCycleService simulationLifeCycleService;
@Autowired
private StompMessageService stompMessageService;
public void run(Simulation simulation) {
Training2 training2 = simulation.getTraining2();
if (training2 == null || !training2.isStarted() || training2.isFinish()) {
return;
}
// 获取运行步骤
Step2 step = training2.getCurrentRunStep();
if (step == null) { // 步骤已经运行完毕
training2.finish();
// 发送实训完成消息
sendTrainingFinish(training2, simulation);
return;
}
// 步骤是否已经触发
// 没有触发则检查触发状态如果可以触发则继续不能触发则返回
if (!Step2.StepStatus.isAlreadyTrigger(step.getStepStatus()) && !step.doTriggerVail()) {
return;
}
// 发送步骤提示信息
if (!step.isPrompt()) {
step.setPrompt(true); // 标识已发送过消息
sendStepTips(step, simulation);
}
// 获取步骤中未完成的操作
Operation2 operation2 = step.getCurrentRunOperation();
// 操作全部完成的情况检查步骤完成条件
if (operation2 == null) {
// TODO 后续判断步骤完成情况
checkTrainStepCompletion(step, simulation);
return;
}
// 操作是否已触发
// 没有触发则检查触发状态如果可以触发则继续不能触发则返回(同步骤)
if (!Step2.StepStatus.isAlreadyTrigger(operation2.getStatus()) && !operation2.doTriggerVail()) {
return;
}
boolean isRobot = step.getSimulationMember().isRobot(); // 角色是否是机器人
boolean isClient = operation2 instanceof Operation2.ClientOperation2; // 客户端操作
// 未操作过
if (Step2.StepStatus.isUndo(operation2.getStatus())) {
if (isRobot) {
if (isClient) { // 客户端操作
operation2.doOperated();
} else { // 仿真操
Operation2.SimOperation2 simOperation2 = (Operation2.SimOperation2) operation2;
atsOperationDispatcher.execute(simulation, step.getSimulationMember(),
simOperation2.getOperationType().name(), simOperation2.getParams());
}
} else { // 非机器人暂停仿真等待用户操作
pauseOrStartSimulation(simulation, true);
return;
}
}
// 运行阶段判断是否完成
if (Step2.StepStatus.isRunning(operation2.getStatus())) {
boolean completion = operation2.doCompletion();
// 发送操作完成信息
sendOperationFinish(operation2, simulation);
// 如果是最后一步直接检查步骤有没有完成
if (step.getOperations().indexOf(operation2) == (step.getOperations().size() - 1) && completion) {
checkTrainStepCompletion(step, simulation);
}
}
}
/**
* 预览实训草稿
*/
public String previewDraft(Long trainingId, LoginUserInfoVO loginUserInfoVO) {
DraftTraining2WithBLOBs draftTraining2 = draftTrainingDao.selectByPrimaryKey(trainingId);
if (draftTraining2 == null) {
throw new SimulationException(SimulationExceptionType.Data_Not_Exist, "实训不存在");
}
// 校验数据
trainingDataValid.accept(draftTraining2);
Simulation simulation = createSimulation(draftTraining2.getMapId(), loginUserInfoVO
, Simulation.FunctionalType.SCRIPT_PREVIEW, draftTraining2);
return simulation.getId();
}
/**
* 发布实训预览
*/
public String preview(Long trainingId, LoginUserInfoVO loginUserInfoVO) {
PublishedTraining2WithBLOBs publishedTraining2 = training2DAO.selectByPrimaryKey(trainingId);
if (publishedTraining2 == null) {
throw new SimulationException(SimulationExceptionType.Data_Not_Exist, "实训不存在");
}
DraftTraining2WithBLOBs draftTraining2 = JsonUtils.readCollection(JsonUtils.writeValueAsString(publishedTraining2)
, DraftTraining2WithBLOBs.class);
// 校验数据
trainingDataValid.accept(draftTraining2);
Simulation simulation = createSimulation(draftTraining2.getMapId(), loginUserInfoVO
, Simulation.FunctionalType.SCRIPT_PREVIEW, draftTraining2);
return simulation.getId();
}
/**
* 仿真中加载发布的实训
*/
public void trainingLoad(String group, Long trainingId, LoginUserInfoVO loginUserInfoVO) {
PublishedTraining2WithBLOBs publishedTraining2 = training2DAO.selectByPrimaryKey(trainingId);
if (publishedTraining2 == null) {
throw new SimulationException(SimulationExceptionType.Data_Not_Exist, "实训不存在");
}
DraftTraining2WithBLOBs draftTraining2 = JsonUtils.readCollection(JsonUtils.writeValueAsString(publishedTraining2)
, DraftTraining2WithBLOBs.class);
// 校验数据
trainingDataValid.accept(draftTraining2);
// 仿真加载实训
simulationLoadTraining(group, draftTraining2, loginUserInfoVO);
}
/**
* 仿真中加载草稿实训
*/
public void trainingDraftLoad(String group, Long trainingId, LoginUserInfoVO loginUserInfoVO) {
DraftTraining2WithBLOBs draftTraining2 = draftTrainingDao.selectByPrimaryKey(trainingId);
if (draftTraining2 == null) {
throw new SimulationException(SimulationExceptionType.Data_Not_Exist, "实训不存在");
}
// 校验数据
trainingDataValid.accept(draftTraining2);
// 仿真加载实训
simulationLoadTraining(group, draftTraining2, loginUserInfoVO);
}
/**
* 开启实训
*/
public void startTraining2(String group, ScriptBO.Mode mode, AccountVO user) {
Simulation simulation = groupSimulationCache.getSimulationByGroup(group);
if (simulation == null) {
throw new SimulationException(SimulationExceptionType.Invalid_Operation, "仿真不存在");
}
if (!simulation.getCreator().getId().equals(user.getId())) {
throw new SimulationException(SimulationExceptionType.Invalid_Operation, "无权限开启实训");
}
Training2 training2 = simulation.getTraining2();
if (training2 == null) {
throw new SimulationException(SimulationExceptionType.Invalid_Operation, "实训数据不存在");
}
if (training2.isNeedReloadScenes()) {
simulationLifeCycleService.pause(simulation);
// 重置仿真状态
groupSimulationService.planOver(group);
if (!StringUtils.isEmpty(training2.getBgSceneJson())) {
groupSimulationService.loadScenes(simulation.getId(), training2.getBgSceneJson());
}
}
// 增加任务
if (simulation.getJobMap().containsKey(EXECUTE_JOB_NAME)) {
simulation.removeJob(EXECUTE_JOB_NAME);
}
simulation.addJobIfAbsent(EXECUTE_JOB_NAME, () -> this.run(simulation), RATE);
training2.start(mode);
simulationLifeCycleService.resume(simulation);
}
/**
* 停止实训信息
* <p>
* 2022-08-30 完成实训后取消仿真暂停
*/
public Float finishTraining2(String group, AccountVO user) {
Simulation simulation = groupSimulationCache.getSimulationByGroup(group);
if (simulation == null) {
throw new SimulationException(SimulationExceptionType.Invalid_Operation, "仿真不存在");
}
Training2 training2 = simulation.getTraining2();
Map<String, Float> scoreMap;
if (training2 != null) {
// 创建者退出则清理实训
if (simulation.getCreator().getId().equals(user.getId())) {
training2.finish();
simulation.removeJob(SCORING_JOB_NAME); //移除打分监视任务
simulation.removeJob(EXECUTE_JOB_NAME); //移除实训执行任务
}
scoreMap = training2.mark();
} else {
scoreMap = new HashMap<>();
}
SimulationMember member = simulation.getSimulationMemberByUserId(user.getId());
return scoreMap.get(member.getId());
}
/**
* 客户端完成步骤后回调(针对步骤中全部是客户端操作的)
*/
public Integer completionClientStep(String group, Integer stepId, AccountVO user) {
Simulation simulation = groupSimulationCache.getSimulationByGroup(group);
if (simulation == null) {
throw new SimulationException(SimulationExceptionType.Invalid_Operation, "仿真不存在");
}
Training2 training2 = simulation.getTraining2();
if (training2 == null) {
throw new SimulationException(SimulationExceptionType.Invalid_Operation, "实训数据不存在");
}
Step2 step = training2.getSteps().stream().filter(s -> Objects.equals(s.getId(), stepId))
.findFirst().orElse(null);
if (step == null) {
throw new SimulationException(SimulationExceptionType.Invalid_Operation, "不存在步骤");
}
if (Objects.equals(user.getId(), step.getSimulationMember().getId())) {
throw new SimulationException(SimulationExceptionType.Invalid_Operation, "无权限操作");
}
boolean result = true;
for (Operation2 operation2 : step.getOperations()) {
if (operation2 instanceof Operation2.ClientOperation2) { // 前端操作直接判断结果
operation2.doOperated();
operation2.doCompletion();
} else {
result = false;
break;
}
}
if (result) {
checkTrainStepCompletion(step, simulation); // 直接检查步骤是否完成
}
// 恢复前端运行
pauseOrStartSimulation(simulation, false);
return 1;
}
/**
* 完成步骤中操作
*/
public Integer completionClientStepOperation(String group, Integer stepId
, Integer id, AccountVO user) {
Simulation simulation = groupSimulationCache.getSimulationByGroup(group);
if (simulation == null) {
throw new SimulationException(SimulationExceptionType.Invalid_Operation, "仿真不存在");
}
Training2 training2 = simulation.getTraining2();
if (training2 == null) {
throw new SimulationException(SimulationExceptionType.Invalid_Operation, "实训数据不存在");
}
Step2 step = training2.getSteps().stream().filter(s -> Objects.equals(s.getId(), stepId))
.findFirst().orElse(null);
if (step == null) {
throw new SimulationException(SimulationExceptionType.Invalid_Operation, "不存在步骤");
}
if (Objects.equals(user.getId(), step.getSimulationMember().getId())) {
throw new SimulationException(SimulationExceptionType.Invalid_Operation, "无权限操作");
}
Operation2 operation = step.getOperations().stream().filter(o -> Objects.equals(o.getId(), id))
.findFirst().orElse(null);
if (operation == null) {
throw new SimulationException(SimulationExceptionType.Invalid_Operation, "不存在操作");
}
operation.doOperated();
// 恢复前端运行
pauseOrStartSimulation(simulation, false);
return 1;
}
@Async("trainingV2Executor")
@EventListener
public void handle(SimulationOperationEvent event) {
Simulation simulation = event.getSimulation();
Training2 training2 = simulation.getTraining2();
if (training2 != null && Objects.equals(event.getSuccessful(), true)) {
// 获取运行步骤
Step2 step = training2.getCurrentRunStep();
// 没找到返回
if (step == null) {
return;
}
// 角色不对
if (!event.getMember().equals(step.getSimulationMember())) {
return;
}
// 获取步骤中未完成的操作
Operation2 operation2 = step.getCurrentRunOperation();
if (operation2 == null) {
return;
}
if (operation2 instanceof Operation2.SimOperation2) {
Operation2.SimOperation2 simOperation2 = (Operation2.SimOperation2) operation2;
if (simOperation2.getOperationType().name().equals(event.getOperate())
&& Objects.equals(event.getParams(), simOperation2.getParams())) {
operation2.doOperated(); // 标识已操作过
} else {
// 错误操作数增加
operation2.getCount().incrementAndGet();
// 错误提示
// 发送操作完成信息
sendOperationError(operation2, simulation);
}
// 操作完成后,如果是测验模式则仿真启动
pauseOrStartSimulation(simulation, false);
}
}
}
/**
* 步骤提示
*/
public void sendStepTips(Step2 step, Simulation simulation) {
SocketMessageVO<String> message =
SocketMessageFactory.build(WebSocketMessageType.Simulation_Training_Step_Tip, simulation.getId(), step.getDescription());
stompMessageService.sendToUser(simulation.getSimulationUserIds(), message);
}
/**
* 步骤完成
*/
public void sendStepFinish(Step2 step, Simulation simulation) {
if (Step2.StepStatus.isCompletion(step.getStepStatus())) {
SocketMessageVO<String> message =
SocketMessageFactory.build(WebSocketMessageType.Simulation_Training_Step_Finish, simulation.getId(), "步骤完成");
stompMessageService.sendToUser(simulation.getSimulationUserIds(), message);
}
}
/**
* 操作错误
*/
public void sendOperationError(Operation2 operation2, Simulation simulation) {
SocketMessageVO<String> message =
SocketMessageFactory.build(WebSocketMessageType.Simulation_Training_Operate_Error, simulation.getId(), "操作错误");
stompMessageService.sendToUser(simulation.getSimulationUserIds(), message);
}
/**
* 操作完成
*/
public void sendOperationFinish(Operation2 operation2, Simulation simulation) {
if (Step2.StepStatus.isCompletion(operation2.getStatus())) {
SocketMessageVO<String> message =
SocketMessageFactory.build(WebSocketMessageType.Simulation_Training_Operate_Finish, simulation.getId(), "操作完成");
stompMessageService.sendToUser(simulation.getSimulationUserIds(), message);
}
}
/**
* 实训完成发送消息
*/
public void sendTrainingFinish(Training2 training2, Simulation simulation) {
if (training2.isFinish()) {
SocketMessageVO<String> message =
SocketMessageFactory.build(WebSocketMessageType.Simulation_Training_Finish, simulation.getId(), "实训完成");
stompMessageService.sendToUser(simulation.getSimulationUserIds(), message);
}
}
/**
* 绘制草稿时加载实训背景
* TODO 后续看根据需求是否加载到最后一步
*/
public void drawTraining(String group, Long trainingId) {
DraftTraining2WithBLOBs draftTraining2 = draftTrainingDao.selectByPrimaryKey(trainingId);
if (draftTraining2 == null) {
throw new SimulationException(SimulationExceptionType.Data_Not_Exist, "实训不存在");
}
Simulation simulation = groupSimulationCache.getSimulationByGroup(group);
simulationLifeCycleService.pause(simulation);
// 重置仿真状态
groupSimulationService.planOver(group);
// 场景的时候加载最后背景
String bgSceneJson = draftTraining2.getBgSceneJson();
if (Training2.Type.SCENE.name().equals(draftTraining2.getType())) {
bgSceneJson = StringUtils.isEmpty(draftTraining2.getFinalScenesJson()) ? bgSceneJson
: draftTraining2.getFinalScenesJson();
}
if (!StringUtils.isEmpty(bgSceneJson)) {
groupSimulationService.loadScenes(simulation.getId(), bgSceneJson);
}
}
/**
* 实训时创建仿真对象
*/
private Simulation createSimulation(Long mapId, LoginUserInfoVO loginUserInfoVO
, Simulation.FunctionalType functionalType, DraftTraining2WithBLOBs draftTraining2) {
// 构建仿真,加载背景,
Simulation simulation = groupSimulationService.create(loginUserInfoVO, mapId, null, functionalType);
// 加载实训信息
loadTraining(simulation, draftTraining2, loginUserInfoVO);
return simulation;
}
/**
* 仿真加载实训
* 初始化仿真 - 替换实训信息 - 加载背景
*/
private void simulationLoadTraining(String group, DraftTraining2WithBLOBs draftTraining2, LoginUserInfoVO loginUserInfoVO) {
Simulation simulation = groupSimulationCache.getSimulationByGroup(group);
simulationLifeCycleService.pause(simulation);
// 重置仿真状态
groupSimulationService.planOver(group);
// 加载实训信息
loadTraining(simulation, draftTraining2, loginUserInfoVO);
}
/**
* 加载实训数据
*/
private void loadTraining(Simulation simulation, DraftTraining2WithBLOBs draftTraining2, LoginUserInfoVO loginUserInfoVO) {
Training2 training2 = new Training2(draftTraining2, simulation);
// 没有背景不做加载
if (!StringUtils.isEmpty(training2.getBgSceneJson())) {
groupSimulationService.loadScenes(simulation.getId(), training2.getBgSceneJson());
}
simulation.setTraining2(training2);
// 如果是单操设置为步骤指定角色
if (Training2.Type.SINGLE.equals(training2.getType())) {
String memberId = training2.getPlayerIds().stream().findFirst().orElse(null);
if (memberId == null) {
throw new SimulationException(SimulationExceptionType.Invalid_Operation
, String.format("实训{id:[%s]}没有参训角色", training2.getId()));
} else {
memberManager.playRole(simulation, loginUserInfoVO.getAccountVO().getId(), memberId);
}
}
}
/**
* 判断实训步骤是否完成
*/
private void checkTrainStepCompletion(Step2 step, Simulation simulation) {
step.doCompletionVail();
// 发送步骤完成信息
sendStepFinish(step, simulation);
}
/**
* 暂停恢复实训
*/
private void pauseOrStartSimulation(Simulation simulation, boolean isPause) {
Training2 training2 = simulation.getTraining2();
if (training2 == null) {
return;
}
if (!ScriptBO.Mode.TEST_MODE.equals(training2.getMode())) {
if (isPause) {
simulation.onlyPause();
} else {
simulation.start();
}
}
}
/**
* 检验实训数据是否合规
*/
private Consumer<DraftTraining2WithBLOBs> trainingDataValid = (training) -> {
if (!StringUtils.hasText(training.getPlayerIdJson())) {
throw new SimulationException(SimulationExceptionType.Invalid_Operation
, String.format("实训{id:[%s]}没有参训角色", training.getId()));
}
};
}

View File

@ -0,0 +1,16 @@
package club.joylink.rtss.services.training2;
/**
* 实训类型单操 single场景scene
*/
public enum Training2TypeEnum {
single("single"),
scene("scene"),
;
private String value;
private Training2TypeEnum(String type){
this.value=type;
}
public String value(){
return this.value;
}
}

View File

@ -12,6 +12,8 @@ public interface IVoiceService {
VoiceRecognitionResult voiceRecognition(byte[] bytes, String filePath);
VoiceRecognitionResult voiceRecognition(String fileBase64);
/**
* 语音合成返回文件路径
*

View File

@ -12,6 +12,7 @@ import org.springframework.web.multipart.MultipartFile;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Base64;
/**
* 百度语音识别合成服务
@ -58,6 +59,7 @@ public class BaiduVoiceServiceImpl implements IVoiceService {
* 3314 用户输入错误 音频长度过短 音频长度的len参数不能小于等于4
* 3315 服务端问题 语音服务器处理超时 请将api返回结果反馈至工单论坛或者QQ群
* 3316 用户输入错误 音频转为pcm失败 使用pcm格式或者确认wav和amr的采样率16000单声道 wav文件需要是pcm编码小端序16bits
*
* @param errCode
* @return
*/
@ -115,6 +117,18 @@ public class BaiduVoiceServiceImpl implements IVoiceService {
}
}
@Override
public VoiceRecognitionResult voiceRecognition(String fileBase64) {
try {
String base64 = fileBase64.substring(fileBase64.indexOf("base64,") + "base64,".length());
byte[] bytes = Base64.getDecoder().decode(base64.trim());
String filePath = VoiceFileUtils.saveFile(bytes);
return voiceRecognition(bytes, filePath);
} catch (Exception e) {
throw BusinessExceptionAssertEnum.THIRD_SERVICE_CALL_EXCEPTION.exception(e);
}
}
@Override
public String synthesis(String message, String per) {
try {

View File

@ -1,68 +1,75 @@
package club.joylink.rtss.services.voice.huawei;
import club.joylink.rtss.exception.BusinessExceptionAssertEnum;
import club.joylink.rtss.services.voice.IVoiceService;
import club.joylink.rtss.util.VoiceFileUtils;
import club.joylink.rtss.vo.client.VoiceRecognitionResult;
import com.huawei.sis.bean.AuthInfo;
import com.huawei.sis.bean.SisConfig;
import com.huawei.sis.bean.request.AsrCustomShortRequest;
import com.huawei.sis.bean.response.AsrCustomShortResponse;
import com.huawei.sis.client.AsrCustomizationClient;
import com.huawei.sis.exception.SisException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.util.Base64;
@Slf4j
@Service("HuaWeiVoiceService")
public class HuaweiVoiceServiceImpl implements IVoiceService {
@Override
public String synthesis(String message, String per) {
throw BusinessExceptionAssertEnum.THIRD_SERVICE_CALL_EXCEPTION.exception("功能暂未实现");
}
@Override
public String synthesis(String message) {
return this.synthesis(message, "0");
}
/**
* 华为语音识别配置
*/
private final String ak = "YDUXTXRYGAHGPHAIXZCU";
private final String sk = "Kcbm3sTDCYEou8kGeAhKxfBkgWybIn6IjJyGBX3p";
private final String region = "cn-north-4";
private final String projectId = "0aada8176180f28c2f34c0196f5394e8";
@Override
public VoiceRecognitionResult voiceRecognition(MultipartFile file, String lang) {
String filePath = VoiceFileUtils.saveFile(file);
try {
return voiceRecognition(file.getBytes(), filePath);
} catch (IOException e) {
throw BusinessExceptionAssertEnum.SYSTEM_EXCEPTION.exception("第三方服务调用异常");
}
}
@Override
public VoiceRecognitionResult voiceRecognition(byte[] bytes, String filePath) {
AuthInfo authInfo = new AuthInfo(ak, sk, region, projectId);
SisConfig sisConfig = new SisConfig();
AsrCustomizationClient client = new AsrCustomizationClient(authInfo, sisConfig);
String data = Base64.getEncoder().encodeToString(bytes);
try {
AsrCustomShortRequest request = new AsrCustomShortRequest(data, "pcm16k16bit", "chinese_16k_common");
AsrCustomShortResponse response = client.getAsrShortResponse(request);
return new VoiceRecognitionResult(filePath, response.getResult().getText());
} catch (SisException e) {
throw BusinessExceptionAssertEnum.SYSTEM_EXCEPTION.exception("语音识别失败", e);
}
}
}
//package club.joylink.rtss.services.voice.huawei;
//
//import club.joylink.rtss.exception.BusinessExceptionAssertEnum;
//import club.joylink.rtss.services.voice.IVoiceService;
//import club.joylink.rtss.util.VoiceFileUtils;
//import club.joylink.rtss.vo.client.VoiceRecognitionResult;
//import com.huawei.sis.bean.AuthInfo;
//import com.huawei.sis.bean.SisConfig;
//import com.huawei.sis.bean.request.AsrCustomShortRequest;
//import com.huawei.sis.bean.response.AsrCustomShortResponse;
//import com.huawei.sis.client.AsrCustomizationClient;
//import com.huawei.sis.exception.SisException;
//import lombok.extern.slf4j.Slf4j;
//import org.springframework.stereotype.Service;
//import org.springframework.web.multipart.MultipartFile;
//
//import java.io.IOException;
//import java.util.Base64;
//
//@Slf4j
//@Service("HuaWeiVoiceService")
//public class HuaweiVoiceServiceImpl implements IVoiceService {
//
//
// @Override
// public String synthesis(String message, String per) {
// throw BusinessExceptionAssertEnum.THIRD_SERVICE_CALL_EXCEPTION.exception("功能暂未实现");
// }
//
// @Override
// public String synthesis(String message) {
// return this.synthesis(message, "0");
// }
//
// /**
// * 华为语音识别配置
// */
// private final String ak = "YDUXTXRYGAHGPHAIXZCU";
// private final String sk = "Kcbm3sTDCYEou8kGeAhKxfBkgWybIn6IjJyGBX3p";
// private final String region = "cn-north-4";
// private final String projectId = "0aada8176180f28c2f34c0196f5394e8";
//
// @Override
// public VoiceRecognitionResult voiceRecognition(MultipartFile file, String lang) {
// String filePath = VoiceFileUtils.saveFile(file);
// try {
// return voiceRecognition(file.getBytes(), filePath);
// } catch (IOException e) {
// throw BusinessExceptionAssertEnum.SYSTEM_EXCEPTION.exception("第三方服务调用异常");
// }
// }
//
// @Override
// public VoiceRecognitionResult voiceRecognition(byte[] bytes, String filePath) {
// AuthInfo authInfo = new AuthInfo(ak, sk, region, projectId);
// SisConfig sisConfig = new SisConfig();
// AsrCustomizationClient client = new AsrCustomizationClient(authInfo, sisConfig);
// String data = Base64.getEncoder().encodeToString(bytes);
// try {
// AsrCustomShortRequest request = new AsrCustomShortRequest(data, "pcm16k16bit", "chinese_16k_common");
// AsrCustomShortResponse response = client.getAsrShortResponse(request);
// return new VoiceRecognitionResult(filePath, response.getResult().getText());
// } catch (SisException e) {
// throw BusinessExceptionAssertEnum.SYSTEM_EXCEPTION.exception("语音识别失败", e);
// }
// }
//
// @Override
// public VoiceRecognitionResult voiceRecognition(String fileBase64) {
// String base64 = fileBase64.substring(fileBase64.indexOf("base64,") + "base64,".length());
// byte[] bytes = Base64.getDecoder().decode(base64.trim());
// String filePath = VoiceFileUtils.saveFile(bytes);
// return voiceRecognition(bytes, filePath);
// }
//}

View File

@ -10,6 +10,7 @@ import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.util.Base64;
@Service("XunFeiVoiceService")
public class XunFeiVoiceService implements IVoiceService {
@ -57,6 +58,14 @@ public class XunFeiVoiceService implements IVoiceService {
throw BusinessExceptionAssertEnum.SYSTEM_EXCEPTION.exception("语音识别失败");
}
@Override
public VoiceRecognitionResult voiceRecognition(String fileBase64) {
String base64 = fileBase64.substring(fileBase64.indexOf("base64,") + "base64,".length());
byte[] bytes = Base64.getDecoder().decode(base64.trim());
String filePath = VoiceFileUtils.saveFile(bytes);
return voiceRecognition(bytes, filePath);
}
@Override
public String synthesis(String message, String per) {
return null;

View File

@ -22,7 +22,7 @@ import java.util.stream.Collectors;
@Slf4j
@Getter
public abstract class Simulation<U extends SimulationUser, M extends SimulationMember> extends Watchable {
public abstract class Simulation<U extends SimulationUser, M extends SimulationMember> extends Watchable {
/**
* id
*/
@ -82,8 +82,8 @@ public abstract class Simulation<U extends SimulationUser, M extends Simulation
private Map<String, SimulationRepository> repositoryMap = new ConcurrentHashMap<>();
@Setter
private Map<String, M> simulationMemberMap = new ConcurrentHashMap<>();
private Map<String, U> simulationUserMap = new ConcurrentHashMap<>();
private Map<String, M> simulationMemberMap = new ConcurrentSkipListMap<>(); //2022-08-16 为前端展示成员有序
private Map<String, U> simulationUserMap = new ConcurrentSkipListMap<>();
private List<Operation> operationList = new ArrayList<>();
private Map<String, Map<String, SimulationFaultVO>> deviceFaultMap = new ConcurrentHashMap<>();
@ -127,7 +127,7 @@ public abstract class Simulation<U extends SimulationUser, M extends Simulation
}
}
long period = TimeUnit.MILLISECONDS.toNanos(BASE_RATE) / this.speed;
ScheduledFuture<?> scheduledFuture = EXECUTOR.scheduleAtFixedRate(()->this.logic(),
ScheduledFuture<?> scheduledFuture = EXECUTOR.scheduleAtFixedRate(() -> this.logic(),
0, period, TimeUnit.NANOSECONDS);
this.future = scheduledFuture;
this.updateTimeUpdateSpeed(this.speed);
@ -166,6 +166,7 @@ public abstract class Simulation<U extends SimulationUser, M extends Simulation
/**
* 仿真逻辑是否正在运行中指代逻辑循环帧是否未完成
*
* @return
*/
private boolean isRunning() {
@ -184,6 +185,7 @@ public abstract class Simulation<U extends SimulationUser, M extends Simulation
this.systemTime = systemTime;
this.jobMap.values().forEach(SimulationJob::updateRunTime);
}
public LocalDateTime getSystemTime() {
return this.systemTime;
}
@ -209,8 +211,9 @@ public abstract class Simulation<U extends SimulationUser, M extends Simulation
/**
* 添加定时仿真逻辑循环
*
* @param name 任务名称同时也是id
* @param job 仿真逻辑
* @param job 仿真逻辑
* @param rate 执行频率单位ms
*/
public void addJob(String name, Runnable job, int rate) {
@ -232,8 +235,9 @@ public abstract class Simulation<U extends SimulationUser, M extends Simulation
/**
* 添加固定频率运行的逻辑可能主要是消息推送类逻辑
*
* @param name 任务名称同时也是id
* @param job 仿真逻辑
* @param job 仿真逻辑
* @param rate 执行频率单位ms
*/
public void addFixedRateJob(String name, Runnable job, int rate) {
@ -249,6 +253,7 @@ public abstract class Simulation<U extends SimulationUser, M extends Simulation
/**
* 延时执行逻辑只执行一次
*
* @param job
* @param delay
*/
@ -259,6 +264,7 @@ public abstract class Simulation<U extends SimulationUser, M extends Simulation
/**
* 移除指定仿真任务逻辑循环
*
* @param name
*/
public void removeJob(String name) {
@ -295,6 +301,13 @@ public abstract class Simulation<U extends SimulationUser, M extends Simulation
log.debug(String.format("仿真[%s]暂停", this.id));
}
/**
* 只修改暂停状态
*/
public void onlyPause() {
this.updateState(PAUSE);
}
public int getState() {
return this.state.get();
}
@ -313,6 +326,7 @@ public abstract class Simulation<U extends SimulationUser, M extends Simulation
/**
* 更新仿真速度
*
* @param speed Simulation.MIN_SPEED <= speed <= Simulation.MAX_SPEED
*/
public void updateSpeed(int speed) {

View File

@ -0,0 +1,29 @@
package club.joylink.rtss.simulation.cbtc.ATS;
import club.joylink.rtss.simulation.cbtc.data.map.MapElement;
import club.joylink.rtss.simulation.cbtc.data.map.Station;
import club.joylink.rtss.simulation.cbtc.event.SimulationOperationEvent;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
@Component
public class AtsListener {
/**
* 计数字段名
*/
public static final String COUNT_PARAM_NAME = "_COUNT";
@EventListener
public void handle(SimulationOperationEvent event) {
if (event.getSuccessful() != null)
return;
String countName = (String) event.getParams().get(COUNT_PARAM_NAME);
if (countName == null)
return;
MapElement device = event.getMember().getDevice();
if (device instanceof Station) {
Station station = (Station) device;
station.count(countName);
}
}
}

View File

@ -185,91 +185,19 @@ public class DriverOperateHandler {
simulationRobotService.stopTrain(simulation, simulationMember, groupNumber, eb);
}
/**
* 确认运行至前方站
*/
@OperateHandlerMapping(type = Operation.Type.Drive_Ahead)
public void driveAhead(Simulation simulation, SimulationMember simulationMember, String groupNumber) {
if (!SimulationMember.Type.DRIVER.equals(simulationMember.getType())) {
throw new SimulationException(SimulationExceptionType.Member_Is_Not_Driver);
}
ATPService.driveAhead(simulation, groupNumber);
}
/**
* 进路闭塞法行车
*/
@OperateHandlerMapping(type = Operation.Type.Route_Block_Drive)
public void routeBlockDrive(Simulation simulation, SimulationMember simulationMember, String groupNumber) {
if (!SimulationMember.Type.DRIVER.equals(simulationMember.getType())) {
throw new SimulationException(SimulationExceptionType.Member_Is_Not_Driver);
}
ATPService.routeBlockDrive(simulation, groupNumber);
}
/**
* 越红灯行驶
*/
@OperateHandlerMapping(type = Operation.Type.Drive_Through_The_Red_Light)
public void driveThroughTheRedLight(Simulation simulation, SimulationMember simulationMember, String groupNumber) {
if (!SimulationMember.Type.DRIVER.equals(simulationMember.getType())) {
throw new SimulationException(SimulationExceptionType.Member_Is_Not_Driver);
}
ATPService.driveThroughTheRedLight(simulation, groupNumber);
}
/**
* 越引导信号行驶
*/
@OperateHandlerMapping(type = Operation.Type.Drive_Through_The_Guide_Signal)
public void driveThroughTheGuideSignal(Simulation simulation, SimulationMember simulationMember, String groupNumber) {
if (!SimulationMember.Type.DRIVER.equals(simulationMember.getType())) {
throw new SimulationException(SimulationExceptionType.Member_Is_Not_Driver);
}
ATPService.driveThroughTheGuideSignal(simulation, groupNumber);
}
/**
* 开关门
*/
@OperateHandlerMapping(type = Operation.Type.Open_Or_Close_Door)
public void openOrCloseDoor(Simulation simulation, SimulationMember simulationMember, String groupNumber) {
if (!SimulationMember.Type.DRIVER.equals(simulationMember.getType())) {
throw new SimulationException(SimulationExceptionType.Member_Is_Not_Driver);
}
public void openOrCloseDoor(Simulation simulation, String groupNumber) {
ATPService.openOrCloseDoor(simulation, groupNumber);
}
/**
* 设置限速
*/
@OperateHandlerMapping(type = Operation.Type.Set_Speed_Limit)
public void setSpeedLimit(Simulation simulation, SimulationMember simulationMember, String groupNumber, Float speedLimit) {
if (!SimulationMember.Type.DRIVER.equals(simulationMember.getType())) {
throw new SimulationException(SimulationExceptionType.Member_Is_Not_Driver);
}
ATPService.setSpeedLimit(simulation, groupNumber, speedLimit);
}
/**
* 驾驶至
*/
@OperateHandlerMapping(type = Operation.Type.Drive_To)
public void driveTo(Simulation simulation, SimulationMember simulationMember, String groupNumber, String sectionCode) {
if (!SimulationMember.Type.DRIVER.equals(simulationMember.getType())) {
throw new SimulationException(SimulationExceptionType.Member_Is_Not_Driver);
}
ATPService.driveTo(simulation, groupNumber, sectionCode);
}
/**
* 回库
*/
@OperateHandlerMapping(type = Operation.Type.Inbound)
public void inbound(Simulation simulation, SimulationMember simulationMember, String groupNumber) {
if (!SimulationMember.Type.DRIVER.equals(simulationMember.getType())) {
throw new SimulationException(SimulationExceptionType.Member_Is_Not_Driver);
}
public void inbound(Simulation simulation,String groupNumber) {
ATPService.inbound(simulation, groupNumber);
}
@ -277,11 +205,8 @@ public class DriverOperateHandler {
* 修改预选模式
*/
@OperateHandlerMapping(type = Operation.Type.Change_Preselection_Mode)
public void changePreselectionMode(Simulation simulation, SimulationMember simulationMember, String groupNumber
public void changePreselectionMode(Simulation simulation, String groupNumber
, VirtualRealityTrain.PreselectionMode preselectionMode) {
if (!SimulationMember.Type.DRIVER.equals(simulationMember.getType())) {
throw new SimulationException(SimulationExceptionType.Member_Is_Not_Driver);
}
ATPService.changePreselectionMode(simulation, groupNumber, preselectionMode);
}
@ -289,32 +214,7 @@ public class DriverOperateHandler {
* 转NRM模式
*/
@OperateHandlerMapping(type = Operation.Type.Apply_NRM)
public void applyNRM(Simulation simulation, SimulationMember simulationMember, String groupNumber) {
if (!SimulationMember.Type.DRIVER.equals(simulationMember.getType())) {
throw new SimulationException(SimulationExceptionType.Member_Is_Not_Driver);
}
public void applyNRM(Simulation simulation, String groupNumber) {
ATPService.applyNRM(simulation, groupNumber);
}
/**
* 大铁发车
**/
@OperateHandlerMapping(type = Operation.Type.Depart_Train)
public void departTrain(Simulation simulation, SimulationMember simulationMember, String groupNumber) {
if (!SimulationMember.Type.DRIVER.equals(simulationMember.getType())) {
throw new SimulationException(SimulationExceptionType.Member_Is_Not_Driver);
}
ATPService.departTrain(simulation, groupNumber);
}
/**
* 大铁停车
*/
@OperateHandlerMapping(type = Operation.Type.Parking_Train)
public void parkingTrain(Simulation simulation, SimulationMember simulationMember, String groupNumber) {
if (!SimulationMember.Type.DRIVER.equals(simulationMember.getType())) {
throw new SimulationException(SimulationExceptionType.Member_Is_Not_Driver);
}
ATPService.parkingTrain(simulation, groupNumber);
}
}

View File

@ -78,7 +78,7 @@ public class SignalOperateHandler {
// * @param simulation
// * @param signalCode
// */
// @OperateHandlerMapping(type = Operation.Type.Signal_Force_Cancel_Route)
// @OperateHandlerMapping(type = Operation2.Type.Signal_Force_Cancel_Route)
// public void forceCancelRoute(Simulation simulation, String signalCode) {
// Route route = this.ciApiService.findLockedRouteByStartSignal(simulation, signalCode);
// if (Objects.nonNull(route)) {
@ -185,7 +185,7 @@ public class SignalOperateHandler {
// * @param simulation
// * @param routeCode
// */
// @OperateHandlerMapping(type = Operation.Type.Signal_Route_Guide)
// @OperateHandlerMapping(type = Operation2.Type.Signal_Route_Guide)
// public void settingGuideRoute(Simulation simulation, String routeCode) {
// iciSubsystem.settingGuideRoute(simulation, routeCode);
// }
@ -253,7 +253,7 @@ public class SignalOperateHandler {
// * @param simulation
// * @param signalCode
// */
// @OperateHandlerMapping(type = Operation.Type.Signal_Open_Guide_Check_Switch)
// @OperateHandlerMapping(type = Operation2.Type.Signal_Open_Guide_Check_Switch)
// public void openGuideCheckSwitch(Simulation simulation, String signalCode) {
// this.iciSubsystem.openGuideSignalCheckSwitch(simulation, signalCode);
// }
@ -263,7 +263,7 @@ public class SignalOperateHandler {
// * @param simulation
// * @param signalCode
// */
// @OperateHandlerMapping(type = Operation.Type.Signal_Open_Guide_Check_Route)
// @OperateHandlerMapping(type = Operation2.Type.Signal_Open_Guide_Check_Route)
// public void openGuideCheckRoute(Simulation simulation, String signalCode) {
// this.iciSubsystem.openGuideSignalCheckRoute(simulation, signalCode);
// }

View File

@ -96,7 +96,7 @@ public class SwitchOperateHandler {
}
// /**道岔定操(联动)*/
// @OperateHandlerMapping(type = Operation.Type.Switch_Turn_NP_Chain)
// @OperateHandlerMapping(type = Operation2.Type.Switch_Turn_NP_Chain)
// public void chainTurn2Normal(Simulation simulation, String switchCode) {
// this.turn2Normal(simulation, switchCode);
// SimulationDataRepository repository = simulation.getRepository();
@ -108,7 +108,7 @@ public class SwitchOperateHandler {
// }
// /**道岔反操(联动)*/
// @OperateHandlerMapping(type = Operation.Type.Switch_Turn_RP_Chain)
// @OperateHandlerMapping(type = Operation2.Type.Switch_Turn_RP_Chain)
// public void chainTurn2Reverse(Simulation simulation, String switchCode) {
// this.turn2Reverse(simulation, switchCode);
// SimulationDataRepository repository = simulation.getRepository();
@ -153,7 +153,7 @@ public class SwitchOperateHandler {
}
// /**道岔单锁(联动)*/
// @OperateHandlerMapping(type =Operation.Type.Switch_Single_Lock_Chain)
// @OperateHandlerMapping(type =Operation2.Type.Switch_Single_Lock_Chain)
// public void chainSingleLockSwitch(Simulation simulation, String switchCode) {
// SimulationDataRepository repository = simulation.getRepository();
// Switch aSwitch = repository.getByCode(switchCode, Switch.class);
@ -165,7 +165,7 @@ public class SwitchOperateHandler {
// }
// /**道岔单解(联动)*/
// @OperateHandlerMapping(type =Operation.Type.Switch_Single_Unlock_Chain)
// @OperateHandlerMapping(type =Operation2.Type.Switch_Single_Unlock_Chain)
// public void chainSingleUnlockSwitch(Simulation simulation, String switchCode) {
// SimulationDataRepository repository = simulation.getRepository();
// Switch aSwitch = repository.getByCode(switchCode, Switch.class);

View File

@ -237,7 +237,7 @@ public class TrainOperateHandler {
// /**
// * 删除ID
// */
// @OperateHandlerMapping(type = Operation.Type.Train_Delete_Service_Number)
// @OperateHandlerMapping(type = Operation2.Type.Train_Delete_Service_Number)
// public void deleteServiceNumber(Simulation simulation, String groupNumber) {
// atsTrainService.deleteServiceNumber(simulation, groupNumber);
// }
@ -245,7 +245,7 @@ public class TrainOperateHandler {
// /**
// * 修改目的地码
// */
// @OperateHandlerMapping(type = Operation.Type.Train_Change_Destination_Code)
// @OperateHandlerMapping(type = Operation2.Type.Train_Change_Destination_Code)
// public void changeDestinationCode(Simulation simulation, String groupNumber, String destinationCode) {
// atsTrainService.changeDestinationCode(simulation, groupNumber, destinationCode);
// }
@ -277,6 +277,15 @@ public class TrainOperateHandler {
/**
* 列车托管使用司机的驾驶指令
*/
@OperateHandlerMapping(type = Operation.Type.Train_Drive)
public void drive(Simulation simulation, String groupNumber, DriveParamVO param) {
atsTrainService.trust(simulation, groupNumber, param);
}
/**
* 列车托管使用司机的驾驶指令
* TODO 后续同Train_Trust一起删除
*/
@OperateHandlerMapping(type = Operation.Type.Train_Trust)
public void trust(Simulation simulation, String groupNumber, DriveParamVO param) {
atsTrainService.trust(simulation, groupNumber, param);

View File

@ -1,318 +1,320 @@
package club.joylink.rtss.simulation.cbtc.ATS.service;
import club.joylink.rtss.exception.BusinessExceptionAssertEnum;
import club.joylink.rtss.simulation.cbtc.ATS.data.AtsAlarm;
import club.joylink.rtss.simulation.cbtc.CI.CiApiService;
import club.joylink.rtss.simulation.cbtc.CI.device.CiRouteService;
import club.joylink.rtss.simulation.cbtc.Simulation;
import club.joylink.rtss.simulation.cbtc.data.SimulationDataRepository;
import club.joylink.rtss.simulation.cbtc.data.map.Cycle;
import club.joylink.rtss.simulation.cbtc.data.map.Route;
import club.joylink.rtss.simulation.cbtc.data.map.Signal;
import club.joylink.rtss.simulation.cbtc.data.status.RouteStatus;
import club.joylink.rtss.simulation.cbtc.exception.SimulationException;
import club.joylink.rtss.simulation.cbtc.exception.SimulationExceptionType;
import club.joylink.rtss.simulation.cbtc.member.SimulationMember;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
@Slf4j
@Component
public class AtsRouteService {
@Autowired
private CiRouteService routeService;
@Autowired
private CiApiService ciApiService;
/**
* 进路收人工控
*
* @param simulation
* @param signalCode
* @param routeCodeList
*/
public void setRouteHumanControl(Simulation simulation, String signalCode, List<String> routeCodeList) {
if (!CollectionUtils.isEmpty(routeCodeList)) {
routeCodeList.forEach(routeCode -> {
Route route = simulation.getRepository().getByCode(routeCode, Route.class);
route.setAtsControl(false);
});
} else if (StringUtils.hasText(signalCode)) {
Signal signal = simulation.getRepository().getByCode(signalCode, Signal.class);
List<Route> routeList = signal.getRouteList();
if (!CollectionUtils.isEmpty(routeList)) {
routeList.forEach(route -> route.setAtsControl(false));
}
}
}
/**
* 进路交自动控
*/
public void setRouteAtsControl(Simulation simulation, String signalCode,
List<String> routeCodeList, List<Boolean> checkConflictList) {
SimulationDataRepository repository = simulation.getRepository();
if (!CollectionUtils.isEmpty(routeCodeList)) {
if (!CollectionUtils.isEmpty(checkConflictList)) {
BusinessExceptionAssertEnum.ARGUMENT_ILLEGAL.assertTrue(routeCodeList.size() == checkConflictList.size(),
String.format("进路数和是否检查冲突数量不一致:[%s], [%s]",
String.join(",", routeCodeList),
String.join(",", checkConflictList.stream().map(String::valueOf).collect(Collectors.toList()))));
}
List<Route> routes = routeCodeList.stream().map(routeCode -> repository.getByCode(routeCode, Route.class)).collect(Collectors.toList());
if (repository.getConfig().isSignalHumanControlBeforeSetAtsControlOrCIAutoTrigger()) {
routes.stream()
.map(Route::getStart)
.distinct()
.forEach(signal ->
BusinessExceptionAssertEnum.OPERATION_NOT_SUPPORTED
.assertNotTrue(signal.isCiControl(),
String.format("信号机[%s]需处于人工控状态", signal.getCode())));
}
if (CollectionUtils.isEmpty(checkConflictList)) {
routes.forEach(route -> route.setAtsControl(true));
} else {
for (int i = 0; i < routeCodeList.size(); i++) {
Route route = repository.getByCode(routeCodeList.get(i), Route.class);
boolean checkConflict = checkConflictList.get(i);
route.setAtsControl(true);
route.setCheckConflict(checkConflict);
}
}
} else if (StringUtils.hasText(signalCode)) {
Signal signal = repository.getByCode(signalCode, Signal.class);
if (repository.getConfig().isSignalHumanControlBeforeSetAtsControlOrCIAutoTrigger()) {
BusinessExceptionAssertEnum.OPERATION_NOT_SUPPORTED.assertNotTrue(signal.isCiControl(), String.format("信号机[%s]需处于人工控状态", signal.getCode()));
}
List<Route> routeList = signal.getRouteList();
if (!CollectionUtils.isEmpty(routeList)) {
routeList.forEach(route -> route.setAtsControl(true));
}
}
}
/**
* 查询进路状态/模式
*/
public List<RouteStatus> findRoutesStatus(Simulation simulation, String signalCode) {
Signal signal = simulation.getRepository().getByCode(signalCode, Signal.class);
List<Route> routeList = signal.getRouteList();
return routeList.stream().map(RouteStatus::new).collect(Collectors.toList());
}
/**
* 设置联锁自动进路
*/
public void setCiAuto(Simulation simulation, String signalCode) {
Signal signal = simulation.getRepository().getByCode(signalCode, Signal.class);
if (simulation.getRepository().getConfig().isSetRouteBeforeSetFlt()) {
Route lockedRoute = signal.getLockedRoute();
if (lockedRoute == null) {
throw new SimulationException(SimulationExceptionType.Operation_Handle_FAIL,
String.format("信号机[%s(%s)]没有已锁闭进路,不能设置联锁自动进路", signal.getName(), signal.getCode()));
}
if (!lockedRoute.isFlt()) {
throw new SimulationException(SimulationExceptionType.Unsupported_Operation,
String.format("进路[%s]不能设置车队进路", lockedRoute.getCode()));
}
if (lockedRoute.isCiControl()) {
throw new SimulationException(SimulationExceptionType.Operation_Conflict,
String.format("进路[%s(%s)]自动追踪已开启,不能设置联锁自动进路", lockedRoute.getName(), lockedRoute.getCode()));
}
lockedRoute.setFleetMode(true);
} else {
List<Route> routeList = signal.getRouteList();
BusinessExceptionAssertEnum.ARGUMENT_ILLEGAL.assertCollectionNotEmpty(routeList, signal.debugStr() + "不是进路始端信号机");
// 筛选最适合的进路筛选逻辑与办理引导时筛选逻辑类似
List<Route> fltRoutes = routeList.stream().filter(Route::isFlt).collect(Collectors.toList());
BusinessExceptionAssertEnum.ARGUMENT_ILLEGAL.assertCollectionNotEmpty(fltRoutes, signal.debugStr() + "下没有可设置的车队进路");
List<Route> collect = fltRoutes.stream()
.filter(r -> !r.isTurnBack() && CollectionUtils.isEmpty(r.getSwitchList()))
.collect(Collectors.toList());
if (CollectionUtils.isEmpty(collect)) {
collect = fltRoutes.stream().filter(r -> !r.isTurnBack()).collect(Collectors.toList());
}
if (CollectionUtils.isEmpty(collect)) {
collect = fltRoutes;
}
Route route = collect.get(0);
Route.CheckFailMessage message = routeService.setRoute(simulation, route);
BusinessExceptionAssertEnum.OPERATION_NOT_SUPPORTED.assertNull(message, route.debugStr() + "无法办理");
route.setFleetMode(true);
}
}
/**
* 取消联锁自动进路
*/
public void cancelCiAuto(Simulation simulation, String signalCode) {
Signal signal = simulation.getRepository().getByCode(signalCode, Signal.class);
Route lockedRoute = signal.getLockedRoute();
if (Objects.isNull(lockedRoute)) {
throw new SimulationException(SimulationExceptionType.Operation_Handle_FAIL,
String.format("信号机[%s(%s)]没有已锁闭进路,不能执行取消联锁自动进路", signal.getName(), signal.getCode()));
}
if (!lockedRoute.isFleetMode()) {
throw new SimulationException(SimulationExceptionType.Operation_Repetition, String.format("信号机[%s(%s)]没有打开连锁自动进路,不能取消联锁自动进路", signal.getName(), signal.getCode()));
}
lockedRoute.setFleetMode(false);
if (simulation.getRepository().getConfig().isCancelRouteWhenCancelFlt()) {
routeService.unlockRoute(simulation, lockedRoute);
}
}
/**
* 设置联锁自动触发
*/
public void setCiAutoTrigger(Simulation simulation, String signalCode, List<String> routeCodeList) {
SimulationDataRepository repository = simulation.getRepository();
List<Route> routeList;
if (StringUtils.hasText(signalCode)) {
Signal signal = repository.getByCode(signalCode, Signal.class);
if (repository.getConfig().isSignalHumanControlBeforeSetAtsControlOrCIAutoTrigger()) {
BusinessExceptionAssertEnum.OPERATION_NOT_SUPPORTED.assertNotTrue(signal.isAtsControl(), String.format("信号机[%s]需处于人工控", signal.getCode()));
}
routeList = signal.getRouteList();
} else {
routeList = routeCodeList.stream()
.map(code -> repository.getByCode(code, Route.class))
.collect(Collectors.toList());
if (repository.getConfig().isSignalHumanControlBeforeSetAtsControlOrCIAutoTrigger()) {
routeList.stream()
.map(Route::getStart)
.distinct()
.forEach(signal ->
BusinessExceptionAssertEnum.OPERATION_NOT_SUPPORTED
.assertNotTrue(signal.isAtsControl(),
String.format("信号机[%s]需处于人工控", signal.getCode())));
}
}
if (!CollectionUtils.isEmpty(routeList)) {
routeList.stream().filter(Route::isArs).forEach(route -> {
if (route.isFleetMode()) {
throw new SimulationException(SimulationExceptionType.Operation_Conflict,
String.format("进路[%s(%s)]自动通过已开启,不能设置自动追踪", route.getName(), route.getCode()));
}
// if (route.isCiControl()) {
// throw new SimulationException(SimulationExceptionType.Operation_Repetition, String.format("进路[%s(%s)]自动追踪/连锁自动触发已开启,无需重复设置", route.getName(), route.getCode()));
// }
});
for (Route route : routeList) {
// route.setAtsControl(false);
if (route.isArs())
route.setCiControl(true);
}
}
}
/**
* 取消联锁自动触发
*/
public void cancelCiAutoTrigger(Simulation simulation, String signalCode, List<String> routeCodes) {
List<Route> routeList;
SimulationDataRepository repository = simulation.getRepository();
if (StringUtils.hasText(signalCode)) {
Signal signal = repository.getByCode(signalCode, Signal.class);
routeList = signal.getRouteList();
} else {
routeList = routeCodes.stream()
.map(code -> repository.getByCode(code, Route.class))
.collect(Collectors.toList());
}
if (!CollectionUtils.isEmpty(routeList)) {
for (Route route : routeList) {
if (route.isCiControl()) {
route.setCiControl(false);
route.setAtsControl(false);
}
}
}
}
/**
* 设置自动折返进路
*
* @param simulation
* @param cycleCode
*/
public void setAutoTurnBack(Simulation simulation, String cycleCode) {
Cycle cycle = simulation.getRepository().getByCode(cycleCode, Cycle.class);
cycle.setSetUp(true);
}
/**
* 取消自动折返进路
*/
public void cancelAutoTurnBack(Simulation simulation, String cycleCode) {
Cycle cycle = simulation.getRepository().getByCode(cycleCode, Cycle.class);
cycle.setSetUp(false);
}
/**
* 总取消
*/
public void totalCancel(Simulation simulation, String signalCode) {
// todo 总取消操作有很多种操作方式对应不同的按钮此处都用信号机编号可能不妥
Signal signal = simulation.getRepository().getByCode(signalCode, Signal.class);
Route lockedRoute = signal.getLockedRoute();
if (lockedRoute == null) {
throw new SimulationException(SimulationExceptionType.Operation_Handle_FAIL,
String.format("信号机[%s(%s)]没有已锁闭进路,无需取消进路", signal.getName(), signal.getCode()));
}
if (!signal.isApproachLock()) { //当接近区段未被占用
this.cancelRoute(simulation, signalCode);
} else {
this.routeService.unlockRoute(simulation, lockedRoute);
this.ciApiService.cancelFleetRoute(simulation, lockedRoute.getCode());
// if (signal.isGuideAspect()) { //如果引导信号开启中
// this.ciApiService.closeGuideSignal(simulation, signalCode);
// } else if (signal.isClose()) { //如果信号灯关了
// } else {
// this.ciApiService.closeSignal(simulation, signalCode);
// }
}
}
public void cancelRoute(Simulation simulation, String signalCode) {
Route route = this.ciApiService.findLockedRouteByStartSignal(simulation, signalCode);
if (Objects.nonNull(route)) {
BusinessExceptionAssertEnum.OPERATION_FAIL.assertNotTrue(
route.isApproachLock(), "进路接近锁闭,无法取消");
BusinessExceptionAssertEnum.OPERATION_FAIL.assertNotTrue(
route.getStart().isGuideAspect(), "引导进路,需要人解进路");
BusinessExceptionAssertEnum.OPERATION_NOT_SUPPORTED.assertNotTrue(route.isFleetMode(),
String.format("进路[%s]已开启自动通过进路,无法取消", route.debugStr()));
this.ciApiService.unlockRoute(simulation, route.getCode());
}
}
public void setOverlap(Simulation simulation, String signalCode, String overlapCode) {
if (signalCode == null || overlapCode == null) {
throw new SimulationException(SimulationExceptionType.Illegal_Argument);
}
this.ciApiService.setOverlap(simulation, signalCode, overlapCode);
}
public void conflictRouteSetConfirm(Simulation simulation, SimulationMember member, String routeCode, int way) {
BusinessExceptionAssertEnum.ARGUMENT_ILLEGAL.assertTrue(
Route.Conflict_Handle_Way_1 == way || Route.Conflict_Handle_Way_2 == way
);
Route route = simulation.getRepository().getByCode(routeCode, Route.class);
AtsAlarm conflictAlarm = route.getConflictAlarm();
if (conflictAlarm != null) {
LocalDateTime systemTime = simulation.getCorrectSystemTime();
conflictAlarm.confirm(systemTime, member, way);
conflictAlarm.recover(systemTime);
}
}
}
package club.joylink.rtss.simulation.cbtc.ATS.service;
import club.joylink.rtss.exception.BusinessExceptionAssertEnum;
import club.joylink.rtss.simulation.cbtc.ATS.data.AtsAlarm;
import club.joylink.rtss.simulation.cbtc.CI.CiApiService;
import club.joylink.rtss.simulation.cbtc.CI.device.CiRouteService;
import club.joylink.rtss.simulation.cbtc.Simulation;
import club.joylink.rtss.simulation.cbtc.data.SimulationDataRepository;
import club.joylink.rtss.simulation.cbtc.data.map.Cycle;
import club.joylink.rtss.simulation.cbtc.data.map.Route;
import club.joylink.rtss.simulation.cbtc.data.map.Signal;
import club.joylink.rtss.simulation.cbtc.data.status.RouteStatus;
import club.joylink.rtss.simulation.cbtc.exception.SimulationException;
import club.joylink.rtss.simulation.cbtc.exception.SimulationExceptionType;
import club.joylink.rtss.simulation.cbtc.member.SimulationMember;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
@Slf4j
@Component
public class AtsRouteService {
@Autowired
private CiRouteService routeService;
@Autowired
private CiApiService ciApiService;
/**
* 进路收人工控
*
* @param simulation
* @param signalCode
* @param routeCodeList
*/
public void setRouteHumanControl(Simulation simulation, String signalCode, List<String> routeCodeList) {
if (!CollectionUtils.isEmpty(routeCodeList)) {
routeCodeList.forEach(routeCode -> {
Route route = simulation.getRepository().getByCode(routeCode, Route.class);
route.setAtsControl(false);
});
} else if (StringUtils.hasText(signalCode)) {
Signal signal = simulation.getRepository().getByCode(signalCode, Signal.class);
List<Route> routeList = signal.getRouteList();
if (!CollectionUtils.isEmpty(routeList)) {
routeList.forEach(route -> route.setAtsControl(false));
}
}
}
/**
* 进路交自动控
*/
public void setRouteAtsControl(Simulation simulation, String signalCode,
List<String> routeCodeList, List<Boolean> checkConflictList) {
SimulationDataRepository repository = simulation.getRepository();
if (!CollectionUtils.isEmpty(routeCodeList)) {
if (!CollectionUtils.isEmpty(checkConflictList)) {
BusinessExceptionAssertEnum.ARGUMENT_ILLEGAL.assertTrue(routeCodeList.size() == checkConflictList.size(),
String.format("进路数和是否检查冲突数量不一致:[%s], [%s]",
String.join(",", routeCodeList),
String.join(",", checkConflictList.stream().map(String::valueOf).collect(Collectors.toList()))));
}
List<Route> routes = routeCodeList.stream().map(routeCode -> repository.getByCode(routeCode, Route.class)).collect(Collectors.toList());
if (repository.getConfig().isSignalHumanControlBeforeSetAtsControlOrCIAutoTrigger()) {
routes.stream()
.map(Route::getStart)
.distinct()
.forEach(signal ->
BusinessExceptionAssertEnum.OPERATION_NOT_SUPPORTED
.assertNotTrue(signal.isCiControl(),
String.format("信号机[%s]需处于人工控状态", signal.getCode())));
}
if (CollectionUtils.isEmpty(checkConflictList)) {
routes.forEach(route -> route.setAtsControl(true));
} else {
for (int i = 0; i < routeCodeList.size(); i++) {
Route route = repository.getByCode(routeCodeList.get(i), Route.class);
boolean checkConflict = checkConflictList.get(i);
route.setAtsControl(true);
route.setCheckConflict(checkConflict);
}
}
} else if (StringUtils.hasText(signalCode)) {
Signal signal = repository.getByCode(signalCode, Signal.class);
if (repository.getConfig().isSignalHumanControlBeforeSetAtsControlOrCIAutoTrigger()) {
BusinessExceptionAssertEnum.OPERATION_NOT_SUPPORTED.assertNotTrue(signal.isCiControl(), String.format("信号机[%s]需处于人工控状态", signal.getCode()));
}
List<Route> routeList = signal.getRouteList();
if (!CollectionUtils.isEmpty(routeList)) {
routeList.forEach(route -> route.setAtsControl(true));
}
}
}
/**
* 查询进路状态/模式
*/
public List<RouteStatus> findRoutesStatus(Simulation simulation, String signalCode) {
Signal signal = simulation.getRepository().getByCode(signalCode, Signal.class);
List<Route> routeList = signal.getRouteList();
return routeList.stream().map(RouteStatus::new).collect(Collectors.toList());
}
/**
* 设置联锁自动进路
*/
public void setCiAuto(Simulation simulation, String signalCode) {
Signal signal = simulation.getRepository().getByCode(signalCode, Signal.class);
if (simulation.getRepository().getConfig().isSetRouteBeforeSetFlt()) {
Route lockedRoute = signal.getLockedRoute();
if (lockedRoute == null) {
throw new SimulationException(SimulationExceptionType.Operation_Handle_FAIL,
String.format("信号机[%s(%s)]没有已锁闭进路,不能设置联锁自动进路", signal.getName(), signal.getCode()));
}
if (!lockedRoute.isFlt()) {
throw new SimulationException(SimulationExceptionType.Unsupported_Operation,
String.format("进路[%s]不能设置车队进路", lockedRoute.getCode()));
}
if (lockedRoute.isCiControl()) {
throw new SimulationException(SimulationExceptionType.Operation_Conflict,
String.format("进路[%s(%s)]自动追踪已开启,不能设置联锁自动进路", lockedRoute.getName(), lockedRoute.getCode()));
}
lockedRoute.setFleetMode(true);
} else {
List<Route> routeList = signal.getRouteList();
BusinessExceptionAssertEnum.ARGUMENT_ILLEGAL.assertCollectionNotEmpty(routeList, signal.debugStr() + "不是进路始端信号机");
// 筛选最适合的进路筛选逻辑与办理引导时筛选逻辑类似
List<Route> fltRoutes = routeList.stream().filter(Route::isFlt).collect(Collectors.toList());
BusinessExceptionAssertEnum.ARGUMENT_ILLEGAL.assertCollectionNotEmpty(fltRoutes, signal.debugStr() + "下没有可设置的车队进路");
List<Route> collect = fltRoutes.stream()
.filter(r -> !r.isTurnBack() && CollectionUtils.isEmpty(r.getSwitchList()))
.collect(Collectors.toList());
if (CollectionUtils.isEmpty(collect)) {
collect = fltRoutes.stream().filter(r -> !r.isTurnBack()).collect(Collectors.toList());
}
if (CollectionUtils.isEmpty(collect)) {
collect = fltRoutes;
}
Route route = collect.get(0);
Route.CheckFailMessage message = routeService.setRoute(simulation, route,route.getAspect());
BusinessExceptionAssertEnum.OPERATION_NOT_SUPPORTED.assertNull(message, route.debugStr() + "无法办理");
route.setFleetMode(true);
}
}
/**
* 取消联锁自动进路
*/
public void cancelCiAuto(Simulation simulation, String signalCode) {
Signal signal = simulation.getRepository().getByCode(signalCode, Signal.class);
Route lockedRoute = signal.getLockedRoute();
if (Objects.isNull(lockedRoute)) {
throw new SimulationException(SimulationExceptionType.Operation_Handle_FAIL,
String.format("信号机[%s(%s)]没有已锁闭进路,不能执行取消联锁自动进路", signal.getName(), signal.getCode()));
}
if (!lockedRoute.isFleetMode()) {
throw new SimulationException(SimulationExceptionType.Operation_Repetition, String.format("信号机[%s(%s)]没有打开连锁自动进路,不能取消联锁自动进路", signal.getName(), signal.getCode()));
}
lockedRoute.setFleetMode(false);
if (simulation.getRepository().getConfig().isCancelRouteWhenCancelFlt()) {
routeService.unlockRoute(simulation, lockedRoute);
}
}
/**
* 设置联锁自动触发
*/
public void setCiAutoTrigger(Simulation simulation, String signalCode, List<String> routeCodeList) {
SimulationDataRepository repository = simulation.getRepository();
List<Route> routeList;
if (StringUtils.hasText(signalCode)) {
Signal signal = repository.getByCode(signalCode, Signal.class);
if (repository.getConfig().isSignalHumanControlBeforeSetAtsControlOrCIAutoTrigger()) {
BusinessExceptionAssertEnum.OPERATION_NOT_SUPPORTED.assertNotTrue(signal.isAtsControl(), String.format("信号机[%s]需处于人工控", signal.getCode()));
}
routeList = signal.getRouteList();
} else {
routeList = routeCodeList.stream()
.map(code -> repository.getByCode(code, Route.class))
.collect(Collectors.toList());
if (repository.getConfig().isSignalHumanControlBeforeSetAtsControlOrCIAutoTrigger()) {
routeList.stream()
.map(Route::getStart)
.distinct()
.forEach(signal ->
BusinessExceptionAssertEnum.OPERATION_NOT_SUPPORTED
.assertNotTrue(signal.isAtsControl(),
String.format("信号机[%s]需处于人工控", signal.getCode())));
}
}
if (!CollectionUtils.isEmpty(routeList)) {
routeList.stream().filter(Route::isArs).forEach(route -> {
if (route.isFleetMode()) {
throw new SimulationException(SimulationExceptionType.Operation_Conflict,
String.format("进路[%s(%s)]自动通过已开启,不能设置自动追踪", route.getName(), route.getCode()));
}
// if (route.isCiControl()) {
// throw new SimulationException(SimulationExceptionType.Operation_Repetition, String.format("进路[%s(%s)]自动追踪/连锁自动触发已开启,无需重复设置", route.getName(), route.getCode()));
// }
});
for (Route route : routeList) {
// route.setAtsControl(false);
if (route.isArs())
route.setCiControl(true);
}
}
}
/**
* 取消联锁自动触发
*/
public void cancelCiAutoTrigger(Simulation simulation, String signalCode, List<String> routeCodes) {
List<Route> routeList;
SimulationDataRepository repository = simulation.getRepository();
if (StringUtils.hasText(signalCode)) {
Signal signal = repository.getByCode(signalCode, Signal.class);
routeList = signal.getRouteList();
} else {
routeList = routeCodes.stream()
.map(code -> repository.getByCode(code, Route.class))
.collect(Collectors.toList());
}
if (!CollectionUtils.isEmpty(routeList)) {
for (Route route : routeList) {
if (route.isCiControl()) {
route.setCiControl(false);
route.setAtsControl(false);
}
}
}
}
/**
* 设置自动折返进路
*
* @param simulation
* @param cycleCode
*/
public void setAutoTurnBack(Simulation simulation, String cycleCode) {
Cycle cycle = simulation.getRepository().getByCode(cycleCode, Cycle.class);
cycle.setSetUp(true);
}
/**
* 取消自动折返进路
*/
public void cancelAutoTurnBack(Simulation simulation, String cycleCode) {
Cycle cycle = simulation.getRepository().getByCode(cycleCode, Cycle.class);
cycle.setSetUp(false);
}
/**
* 总取消
*/
public void totalCancel(Simulation simulation, String signalCode) {
// todo 总取消操作有很多种操作方式对应不同的按钮此处都用信号机编号可能不妥
Signal signal = simulation.getRepository().getByCode(signalCode, Signal.class);
Route lockedRoute = signal.getLockedRoute();
if (lockedRoute == null) {
throw new SimulationException(SimulationExceptionType.Operation_Handle_FAIL,
String.format("信号机[%s(%s)]没有已锁闭进路,无需取消进路", signal.getName(), signal.getCode()));
}
if (!signal.isApproachLock()) { //当接近区段未被占用
this.cancelRoute(simulation, signalCode);
} else {
this.routeService.unlockRoute(simulation, lockedRoute);
this.ciApiService.cancelFleetRoute(simulation, lockedRoute.getCode());
// if (signal.isGuideAspect()) { //如果引导信号开启中
// this.ciApiService.closeGuideSignal(simulation, signalCode);
// } else if (signal.isClose()) { //如果信号灯关了
// } else {
// this.ciApiService.closeSignal(simulation, signalCode);
// }
}
}
public void cancelRoute(Simulation simulation, String signalCode) {
Route route = this.ciApiService.findLockedRouteByStartSignal(simulation, signalCode);
if (Objects.nonNull(route)) {
BusinessExceptionAssertEnum.OPERATION_FAIL.assertNotTrue(
route.isApproachLock(), "进路接近锁闭,无法取消");
BusinessExceptionAssertEnum.OPERATION_FAIL.assertNotTrue(
route.getStart().isGuideAspect(), "引导进路,需要人解进路");
BusinessExceptionAssertEnum.OPERATION_NOT_SUPPORTED.assertNotTrue(route.isFleetMode(),
String.format("进路[%s]已开启自动通过进路,无法取消", route.debugStr()));
BusinessExceptionAssertEnum.OPERATION_FAIL.assertNotTrue(
Objects.nonNull(route.getDelayUnlockDevice()), String.format("进路[%s]已经开启延时取消,无法手动取消", route.debugStr()));
this.ciApiService.unlockRoute(simulation, route.getCode());
}
}
public void setOverlap(Simulation simulation, String signalCode, String overlapCode) {
if (signalCode == null || overlapCode == null) {
throw new SimulationException(SimulationExceptionType.Illegal_Argument);
}
this.ciApiService.setOverlap(simulation, signalCode, overlapCode);
}
public void conflictRouteSetConfirm(Simulation simulation, SimulationMember member, String routeCode, int way) {
BusinessExceptionAssertEnum.ARGUMENT_ILLEGAL.assertTrue(
Route.Conflict_Handle_Way_1 == way || Route.Conflict_Handle_Way_2 == way
);
Route route = simulation.getRepository().getByCode(routeCode, Route.class);
AtsAlarm conflictAlarm = route.getConflictAlarm();
if (conflictAlarm != null) {
LocalDateTime systemTime = simulation.getCorrectSystemTime();
conflictAlarm.confirm(systemTime, member, way);
conflictAlarm.recover(systemTime);
}
}
}

View File

@ -86,19 +86,6 @@ public class AtsStationService {
*/
public void applyForStationControl(Simulation simulation, SimulationMember fromMember, List<String> stationCodes) {
this.controlTransfer(simulation, fromMember, stationCodes, Station.ControlMode.Local);
/*//转移角色的目标成员
List<SimulationMember> targetMembers = null;
if(SimulationMember.Type.STATION_SUPERVISOR.equals(fromMember.getType())){
log.debug("现地请求站控");
targetMembers = simulation.findMemberListByRole(SimulationMember.Type.DISPATCHER);
}
else if(SimulationMember.Type.DISPATCHER.equals(fromMember.getType())){
log.debug("行调请求站控");
targetMembers = simulation.findMemberListByRole(SimulationMember.Type.STATION_SUPERVISOR);
}
transferControl(simulation, fromMember, stationCodes, targetMembers, Operation.Type.CM_Apply_For_Station_Control);*/
}
/**
@ -106,23 +93,6 @@ public class AtsStationService {
*/
public void applyForCenterControl(Simulation simulation, SimulationMember fromMember, List<String> stationCodes) {
this.controlTransfer(simulation, fromMember, stationCodes, Station.ControlMode.Center);
/*if(CollectionUtils.isEmpty(stationCodes)){
throw new SimulationException(SimulationExceptionType.Operation_Handle_FAIL, "请求中控的车站不能为空");
}
//转移角色的目标成员
List<SimulationMember> targetMembers = null;
if(SimulationMember.Type.STATION_SUPERVISOR.equals(fromMember.getType())){
log.debug("现地请求中控");
targetMembers = simulation.findMemberListByRole(SimulationMember.Type.DISPATCHER);
}
else if(SimulationMember.Type.DISPATCHER.equals(fromMember.getType())){
log.debug("行调请求中控");
targetMembers = simulation.findMemberListByRole(SimulationMember.Type.STATION_SUPERVISOR);
}
transferControl(simulation, fromMember, stationCodes, targetMembers, Operation.Type.CM_Apply_For_Center_Control);*/
}
/**

View File

@ -460,31 +460,48 @@ public class AtsTrainService {
}
//找要越过的信号机
Section section = headPosition.getSection();
if (param.isThroughRedSignal()) {
if (param.isThroughRedSignal()) { // 越红灯行驶
Signal signal = section.getSignalOf(right);
boolean b = false;
if (signal != null && signal.getPosition().isAheadOf(headPosition, right)) {
VirtualRealitySignal vrSignal = signal.getVirtualSignal();
b = vrSignal != null && vrSignal.getModel().getDefaultAspect().equals(vrSignal.getAspect());
}
BusinessExceptionAssertEnum.OPERATION_FAIL.assertTrue(b, "需要车头所在区段前方有同向信号机,且同向信号机为禁止信号");
BusinessExceptionAssertEnum.OPERATION_FAIL.assertTrue(b, "需要车头所在区段前方有同向信号机,且为禁止信号");
param.setThroughSignal(signal);
param.setThroughSignalAspect(signal.getVirtualSignal().getModel().getDefaultAspect());
} else if (param.isThroughGuideSignal()) {
param.setThroughSignalAspect(signal.getDefaultAspect());
} else if (param.isThroughGuideSignal()) { // 越引导行驶
Signal signal = section.getSignalOf(right);
boolean b = false;
if (signal != null && signal.getPosition().isAheadOf(headPosition, right)) {
VirtualRealitySignal vrSignal = signal.getVirtualSignal();
b = vrSignal != null && vrSignal.getModel().getGuideAspect().equals(vrSignal.getAspect());
}
BusinessExceptionAssertEnum.OPERATION_FAIL.assertTrue(b, "需要车头所在区段前方有同向信号机,且同向信号机为引导信号");
BusinessExceptionAssertEnum.OPERATION_FAIL.assertTrue(b, "需要车头所在区段前方有同向信号机,且为引导信号");
param.setThroughSignal(signal);
param.setThroughSignalAspect(signal.getVirtualSignal().getModel().getDefaultAspect());
} else {
param.setThroughSignalAspect(signal.getGuideAspect());
} else if (param.isDriverNextStand()){ // 行驶至前方车站
// 列车车头所在区段
Section headSection = train.getHeadPosition().getSection();
// 停车目的区段
if (section.isStandTrack()) {
targetPosition = new SectionPosition(headSection, headSection.getStopPointByDirection(train.isRight()));
} else {
targetPosition = train.calculateNextStandStopPosition();
if (targetPosition == null && train.getTarget() != null) {
targetPosition = new SectionPosition(train.getTarget(), train.getTarget().getStopPointByDirection(train.isRight()));
}
BusinessExceptionAssertEnum.OPERATION_NOT_SUPPORTED.assertNotNull(targetPosition, train.debugStr() + "找不到下一个停车点");
}
atpService.changePreselectionMode(train, VirtualRealityTrain.PreselectionMode.RM);
} else if (param.isRouteBlockDriver()) { // 进路闭塞行车
if (!train.isAMMode()) {
atpService.changePreselectionMode(train, VirtualRealityTrain.PreselectionMode.AM_C);
}
}else {
param.setThroughSignal(null);
param.setThroughSignalAspect(null);
}
param.setTargetPosition(targetPosition);
train.setRobotDriveParam(param);
}

View File

@ -248,6 +248,15 @@ public abstract class AtsRouteSelectService {
Route route = null;
for (Route temp : triggerList) {
List<SwitchElement> switchList = temp.getOverlap().getFirstPath().getSwitchList();
if(null==switchList||switchList.isEmpty()){
log.debug("==============================================================================");
log.debug("==>>异常进路code = {} name = {}",temp.getCode(),temp.getName());
log.debug("==>>异常相关所有进路:");
triggerList.forEach(r->{
log.debug("==>>进路code={} name={} , 始端信号机code={} name={}",r.getCode(),r.getName(),r.getStart().getCode(),r.getName());
});
log.debug("==============================================================================");
}
BusinessExceptionAssertEnum.SYSTEM_EXCEPTION.assertCollectionNotEmpty(switchList,
String.format("列车[%s]过滤进路异常:进路不是延续保护差异进路[%s]",
trainInfo.getGroupNumber(),

View File

@ -21,6 +21,10 @@ import java.util.Objects;
@Slf4j
@Component
public class CiLogic {
interface JobName {
String SECTION_STOP_COUNTDOWN = "SECTION_STOP_COUNTDOWN";
}
@Autowired
private CiDeviceStatusCollector deviceStatusCollector;
@Autowired
@ -78,34 +82,76 @@ public class CiLogic {
}
}
/**
* 区段停稳倒计时
*/
public void sectionStopCountDown(Simulation simulation) {
for (Section section : simulation.getRepository().getHasStopCountDownSections()) {
int stopCountDown = section.getStopCountDown();
if (stopCountDown == 0) {
//股道占用且股道有占用
if (section.isOccupied()) {
if (section.getNextRunningSectionOf(false).isOccupied() || section.getNextRunningSectionOf(true).isOccupied()) {
section.readyStartStopCountDown();
}
}
} else {
if (stopCountDown == -1) {
// 股道占用股道两边没有占用股道没有进路锁闭或该进路正在正常解锁
if (section.isOccupied()) {
if ((!section.getNextRunningSectionOf(false).isOccupied()
&& !section.getNextRunningSectionOf(true).isOccupied())
&& (section.getRoute() == null || section.getRoute().isNormalUnlock())) {
section.startStopCountDown();
}
}
} else {
section.setStopCountDown(stopCountDown - SimulationConstants.CI_LOOP_RATE);
if (stopCountDown <= 0) {
section.setStopCountDown(0);
}
}
}
}
}
private void signalMonitor(Simulation simulation, Signal signal) {
signalControlService.controlLightOfSignal(simulation, signal);
//控制通过信号机的显示信号机前第一个区段被占用开红灯第二个区段被占用开黄灯否则开绿灯
if (signal.isPassingSignal()) {
if (simulation.getRepository().getConfig().isRailway()) {
boolean right = signal.isRight();
Section section = signal.getSection();
Section one = section.getNextSection(right);
if (one == null) {
signalControlService.controlSignalAspect(simulation, signal, SignalAspect.G);
return;
}
if (one.isOccupied()) {
signalControlService.controlSignalAspect(simulation, signal, SignalAspect.R);
return;
}
Section two = one.getNextSection(right);
if (two == null) {
signalControlService.controlSignalAspect(simulation, signal, SignalAspect.G);
return;
}
if (two.isOccupied()) {
signalControlService.controlSignalAspect(simulation, signal, SignalAspect.Y);
return;
}
signalControlService.controlSignalAspect(simulation, signal, SignalAspect.G);
if (simulation.getRepository().getConfig().isRailway()) {
railwaySignalMonitor(simulation, signal);
}
}
private void railwaySignalMonitor(Simulation simulation, Signal signal) {
if (signal.isGuideAspect() && signal.getLockedRoute() == null) { //引导总锁后开放的引导信号
if (signal.getRouteList().stream().noneMatch(Route::isAnySwitchMasterLock)) {
signalControlService.controlSignalAspect(simulation, signal, signal.getDefaultAspect());
}
}
if (signal.isPassingSignal()) {
boolean right = signal.isRight();
Section section = signal.getSection();
Section one = section.getNextSection(right);
if (one == null) {
signalControlService.controlSignalAspect(simulation, signal, SignalAspect.G);
return;
}
if (one.isOccupied()) {
signalControlService.controlSignalAspect(simulation, signal, SignalAspect.R);
return;
}
Section two = one.getNextSection(right);
if (two == null) {
signalControlService.controlSignalAspect(simulation, signal, SignalAspect.G);
return;
}
if (two.isOccupied()) {
signalControlService.controlSignalAspect(simulation, signal, SignalAspect.Y);
return;
}
signalControlService.controlSignalAspect(simulation, signal, SignalAspect.G);
}
}
/**
@ -118,11 +164,11 @@ public class CiLogic {
MapConfig config = simulation.getRepository().getConfig();
if (route.isCiControl()) { // 进路联锁自动触发
if (!route.isLock() && !route.isSetting() && ciService.isCiRouteTrigger(simulation, route)) {
routeService.setRoute(simulation, route);
routeService.setRoute(simulation, route, route.getAspect());
}
} else if (route.isFleetMode()) { // 联锁自动进路
if (ciService.isCiRouteTrigger(simulation, route)) {
signalControlService.tryControlSignalAspectAccordingLevel(simulation, route.getStart(), route.getAspect());
signalControlService.tryControlSignalAspectAccordingLevel(simulation, route.getStart(), route.getSettedAspect());
}
}
if (route.isSetting() || route.isLock() || route.isNormalUnlock()) { // 监控中的进路
@ -165,7 +211,7 @@ public class CiLogic {
} else if (start.isDefaultAspect() && !start.isForbidden() && !start.isBlockade() && start.isSupportMainAspect()) {
CiLogic.log.info("进路[{}]联锁条件满足,开放信号", route.debugStr());
signalControlService.tryControlSignalAspectAccordingLevel(simulation,
start, route.getAspect());
start, route.getSettedAspect());
}
} else {
if (route.isOpenMain() && !start.isSupportMainAspect()) {//与联锁显示不同关闭信号
@ -234,5 +280,6 @@ public class CiLogic {
public void addJobs(Simulation simulation) {
simulation.addJob(SimulationModule.CI.name(), () -> run(simulation), SimulationConstants.CI_LOOP_RATE);
simulation.addJob(JobName.SECTION_STOP_COUNTDOWN, () -> sectionStopCountDown(simulation), SimulationConstants.CI_LOOP_RATE);
}
}

View File

@ -19,7 +19,7 @@ import java.util.concurrent.atomic.AtomicInteger;
@Setter
@Getter
@Slf4j
public class StationDirection extends MayOutOfOrderDevice {
public class StationDirection extends MayOutOfOrderDevice implements Cloneable {
/**
* 发辅助默认倒计时 25s
*/
@ -70,6 +70,8 @@ public class StationDirection extends MayOutOfOrderDevice {
* 相对运行方向
*/
private StationDirection relativeStationDirection;
private Station relativeStation;
/**************************************** 初始数据配置信息 **********************************************/
/***************************************** 联锁指示灯状态 ***********************************************/
@ -170,6 +172,7 @@ public class StationDirection extends MayOutOfOrderDevice {
/***************************************** 半自动闭塞按钮状态 ******************************************/
/***************************************** 关联进路信息 ***********************************************/
/**
* 当前进路列表
*/
@ -201,7 +204,32 @@ public class StationDirection extends MayOutOfOrderDevice {
* 默认方向
*/
private Boolean right;
/***************************************** 车务终端管理出入口方向相关属性begin **********************************************/
private IODirection ioDirection;
/**
* 允许超限列车
* 选择/
* 1.普速铁路一般选择有明确不允许超限列
* 车的选择
* 2.高速铁路一般选择200km/h 客货共线铁路
* 根据文件确定
*/
private boolean allowOverrun;
/**
* 允许旅客列车
* 选择/两线多线区间根据行规
* 车运行分工选择
*/
private boolean travelTrain;
/**
* 允许货物列车
* 选择/两线多线区间根据行规
* 车运行分工选择
*/
private boolean goodsTrain;
/***************************************** 车务终端管理出入口方向相关属性begin **********************************************/
// TODO: 待数据统一之后这个构造函数代码可删除 20220714
public StationDirection(String code, String name, DirectionLabelEnum labelEnum) {
this(code, name);
@ -211,7 +239,17 @@ public class StationDirection extends MayOutOfOrderDevice {
this.defaultRunStatus = this.getDefaultReceiveAndDeliver();
this.currentRouteList = getNowRouteList();
}
public StationDirection(String code, String name, DirectionLabelEnum labelEnum,IODirection ioDirection) {
this(code, name);
this.labelEnum = labelEnum;
this.runModel = getDefaultDirectionRunModel();
this.runStatus = this.getDefaultReceiveAndDeliver();
this.defaultRunStatus = this.getDefaultReceiveAndDeliver();
this.currentRouteList = getNowRouteList();
this.ioDirection = ioDirection;
}
public StationDirection(DraftMapStationDirection draftMapStationDirection) {
this(draftMapStationDirection.getCode(), draftMapStationDirection.getName());
this.labelEnum = draftMapStationDirection.getLabelEnum();
@ -220,6 +258,8 @@ public class StationDirection extends MayOutOfOrderDevice {
this.defaultRunStatus = draftMapStationDirection.getRunStatus();
this.currentRouteList = getNowRouteList();
this.isDataConfig = true;
this.ioDirection = draftMapStationDirection.getIoDirection();
}
public StationDirection(String code, String name) {
@ -230,7 +270,14 @@ public class StationDirection extends MayOutOfOrderDevice {
this.deliverRouteList = new ArrayList<>();
this.routeSettingStatusMap = new HashMap<>();
}
public StationDirection clone(){
try {
return (StationDirection)super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return null;
}
@Override
public void reset() {
this.routeSettingStatusMap.clear();
@ -663,4 +710,16 @@ public class StationDirection extends MayOutOfOrderDevice {
// 非自动
N
}
/**
* 出入口方向
*/
public enum IODirection{
DOWN_IN_STATION,
UP_IN_STATION,
DOWN_OUT_STATION,
UP_OUT_STATION,
BOTH_WAY_STATION;
}
}

View File

@ -157,7 +157,7 @@ public class CiSwitchControlService {
}
/**
* 批量转动道岔到指定位置
* 确保道岔位置正确
*/
public boolean ensureSwitchPosCurrent(Simulation simulation, List<SwitchElement> switchElements, boolean guideSetting) {
boolean allOn = true;

View File

@ -0,0 +1,24 @@
package club.joylink.rtss.simulation.cbtc.CTC.data;
import club.joylink.rtss.simulation.cbtc.Simulation;
import club.joylink.rtss.simulation.cbtc.data.map.Route;
import club.joylink.rtss.simulation.cbtc.data.map.Station;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.ArrayList;
import java.util.List;
@Data
@NoArgsConstructor
public class CascoControl {
private Simulation simulation;
private Station station;
private Route route;
private List<String> errorList = new ArrayList<>();
private String tripNum;
public void addErrorMsg(String msg){
this.errorList.add(msg);
}
}

View File

@ -36,6 +36,7 @@ public class CtcEffectRepository {
*/
private final Map<String, CtcStageRunPlanRepository> stationApplyRunPlanMap = new ConcurrentHashMap<>();
/**
* 阶段计划与各车站与生效区
* 下发至车站的运行计划与车站原本计划进行对比只存放不同的数据
@ -55,6 +56,22 @@ public class CtcEffectRepository {
* 车站为key
*/
private final Map<String, StationTrackSectionRepository> stationTrackSectionMap = new ConcurrentHashMap<>();
/**
* 出入口集合
* 车站key
*/
private final Map<String, CtcEffectRepository.StationDoorRepository> doorRepository = new ConcurrentHashMap<>();
/**
* 固定径路集合
* 车站key
*/
private final Map<String, CtcEffectRepository.RegularTrainLineRepository> regularTrainLineMap = new ConcurrentHashMap<>();
/**
* 列车固定经路车站更新区域从生效区来的数据
*/
private final Map<String,CtcEffectRepository.RegularTrainLineRepository> updateReguarTrainLineMap = new ConcurrentHashMap<>();
/**
* 获取生效区的运行计划
@ -108,7 +125,7 @@ public class CtcEffectRepository {
for (Map.Entry<String, CtcRunPlanParam> v : runPlanMap.entrySet()) {
oldPlan = effectRepository.query(v.getValue().getRunPlanCode());
if (oldPlan == null || oldPlan.getVersion().get() < v.getValue().getVersion().get()) {
effectRepository.save(v.getValue().clone());
effectRepository.save(v.getValue());
change = true;
}
}
@ -414,6 +431,16 @@ public class CtcEffectRepository {
public void remove(String code) {
this.dataMap.remove(code);
}
public int version(){
return this.version.get();
}
public int incrementVersionOne(){
return this.version.incrementAndGet();
}
public void resetVersion(int version){
this.version.set(version);
}
}
/**
@ -448,23 +475,59 @@ public class CtcEffectRepository {
*/
@Data
public static class StationDoorRepository extends AbstractWorkspaceRepository<StationDirection> {
private final Map<String, StationDirection> trackSectionMap = new ConcurrentHashMap<>();
@Override
public void save(StationDirection o) {
this.dataMap.put(o.getCode(),o);
}
@Override
public StationDirection query(String code) {
return null;
return this.dataMap.get(code);
}
}
/**
* 固定进路信息
*/
@Data
public static class RegularTrainLineRepository extends AbstractWorkspaceRepository<RegularTrainLine> {
/**
* 保存运行计划
*
* @param runPlanParam 运行计划
*/
public void save(RegularTrainLine runPlanParam) {
this.dataMap.put(runPlanParam.getCode(), runPlanParam.clone());
}
/**
* 获取运行计划参数
*
* @param runPlanCode 运行计划编码
* @return 运行计划
*/
public RegularTrainLine query(String runPlanCode) {
return this.dataMap.get(runPlanCode);
}
/**
* 是否存在
*
* @param code 编码
* @return 存在
*/
public boolean isExit(String code) {
return this.dataMap.containsKey(code);
}
}
/**
* 计划固定进路信息
*/
@Data
public static class StationRunPlanRepository extends AbstractWorkspaceRepository<CtcRunPlanParam> {
/**
* 保存运行计划
@ -510,5 +573,8 @@ public class CtcEffectRepository {
this.stationStageRunPlanMap.clear();
this.stageRunPlanVersionMap.clear();
this.stationTrackSectionMap.clear();
this.doorRepository.clear();
this.regularTrainLineMap.clear();
updateReguarTrainLineMap.clear();
}
}

View File

@ -2,6 +2,8 @@ package club.joylink.rtss.simulation.cbtc.CTC.data;
import club.joylink.rtss.exception.BusinessExceptionAssertEnum;
import club.joylink.rtss.simulation.cbtc.CTC.param.CtcRunPlanParam;
import com.google.common.collect.Maps;
import com.google.common.collect.Tables;
import lombok.Getter;
import lombok.Setter;
import org.springframework.util.StringUtils;
@ -10,6 +12,7 @@ import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
/**
* 车务管理端数据(调度台区段)
@ -34,12 +37,23 @@ public class CtcManageRepository {
* 固定径路集合
* 车站key
*/
private final Map<String, CtcEffectRepository.RegularTrainLineRepository> regularTrainLineMap = new ConcurrentHashMap<>();
/**
* 计划固定径路集合
* 车站key
*/
private final Map<String, CtcEffectRepository.StationRunPlanRepository> runPlanRepository = new ConcurrentHashMap<>();
public void reset() {
this.trackSectionRepository.clear();
this.doorRepository.clear();
this.runPlanRepository.clear();
regularTrainLineMap.clear();
}
/**

View File

@ -12,6 +12,7 @@ import club.joylink.rtss.simulation.cbtc.data.SimulationDataRepository;
import club.joylink.rtss.simulation.cbtc.data.map.MapConfig;
import club.joylink.rtss.simulation.cbtc.data.map.Station;
import club.joylink.rtss.simulation.cbtc.member.SimulationMember;
import com.google.common.base.Strings;
import lombok.Getter;
import org.springframework.util.StringUtils;
@ -54,11 +55,15 @@ public class CtcRepository {
/******************************************* 以上为车务管理终端数据 ****************************************/
/******************************************* 以下为车站终端数据:车站为单位 *******************************************/
/**
* 进路序列id生成器
*/
private AtomicInteger routeSequenceIdGenerator = new AtomicInteger(0);
/**
* 车站-进路序列每个车站都应该有
* k - stationCode
@ -487,4 +492,15 @@ public class CtcRepository {
public boolean routeSequenceMapIsNotEmpty() {
return this.routeSequenceMap.values().stream().anyMatch(RouteSequence::isStatusChange);
}
public String createCode(CtcFZKType type,String group){
int startIndex = routeSequenceIdGenerator.decrementAndGet();
String num = Strings.padStart(startIndex + "",4,'0');
return String.format(group.concat(type.name().concat("%s")),num);
}
public enum CtcFZKType{
STATION_DETAIL,
IO_GATE,
REGULAR_TRAIN;
}
}

View File

@ -0,0 +1,173 @@
package club.joylink.rtss.simulation.cbtc.CTC.data;
import club.joylink.rtss.simulation.cbtc.CI.data.StationDirection;
import club.joylink.rtss.simulation.cbtc.CTC.data.vo.RegularTrainLineVO;
import club.joylink.rtss.simulation.cbtc.data.map.Section;
import club.joylink.rtss.simulation.cbtc.data.map.Stand;
import club.joylink.rtss.simulation.cbtc.data.map.Station;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.Map;
@Data
@NoArgsConstructor
public class RegularTrainLine implements Cloneable {
public RegularTrainLine(RegularTrainLineVO vo){
this.code = vo.getCode();
this.arriveTipNum = vo.getArriveTipNum();
this.leaveTipNum = vo.getLeaveTipNum();
this.arriveTime = vo.getArriveTime();
this.leaveTime = vo.getLeaveTime();
this.appendData = vo.getAppendData();
}
private String code;
/**
* 车站code
*/
private Station station;
/**
* 股道
*/
private Section masterStand;
/**
* 到达车次
*/
private String arriveTipNum;
/**
* 出发车次
*/
private String leaveTipNum;
/**
* 到达时间
*/
private LocalTime arriveTime;
/**
* 出发时间
*/
private LocalTime leaveTime;
/**
* 入口
*/
private StationDirection enter;
/**
* 后方车站
*/
private Station backStation;
/**
* 出口
*/
private StationDirection out;
/**
* 前方车站
*/
private Station fontStation;
/**
* 批量处理车次前缀
* 参数prefixTrain,startTipNum,endTipNum 都不为空的时候认为此次是批量处理
*/
private String prefixTrain;
/**
* 批量处理车次开始
* 参数prefixTrain,startTipNum,endTipNum 都不为空的时候认为此次是批量处理
*/
private Integer startTipNum;
/**
* 批量处理车次结束
* 参数prefixTrain,startTipNum,endTipNum 都不为空的时候认为此次是批量处理
*/
private Integer endTipNum;
/**
*
*/
private Map<AppendDataType, Boolean> appendData;
public RegularTrainLine clone(){
try {
return (RegularTrainLine) super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return null;
}
public enum AppendDataType {
/**
* 技术停点
*/
JISHU_STOP,
/**
* 交令
*/
JIAO_LING,
/**
* 机车
*/
JICHE,
/**
* 货检
*/
HUOJIAN,
/**
* 乘降
*/
CHENGJIANG,
/**
* 摘挂
*/
ZHAIGUA,
/**
* 换乘
*/
HUANCHENG,
/**
* 装卸
*/
ZHUANGXIE,
/**
* 吸污
*/
XIWU,
/**
* 道口
*/
DAOKOU,
/**
* 车号
*/
CHEHAO,
/**
* 上水
*/
SHANGSHUI,
/**
* 列检
*/
LIEJIAN,
/**
* 综控
*/
ZONGKONG,
/**
* 站务
*/
ZHANWU,
/**
* 交票
*/
JIAOPIAO,
/**
* 列尾
*/
LIEWEI,
;
}
}

View File

@ -0,0 +1,67 @@
package club.joylink.rtss.simulation.cbtc.CTC.data;
import club.joylink.rtss.simulation.cbtc.CI.data.StationDirection;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 车站出入口
*/
@Data
@NoArgsConstructor
public class StationIOGate {
public StationIOGate(StationDirection sd){
this.code = sd.getCode();
this.ioName = sd.getName();
this.allowOverrun = sd.isAllowOverrun();
this.travelTrain = sd.isTravelTrain();
this.goodsTrain = sd.isGoodsTrain();
this.ioDirection = sd.getIoDirection();
// this.defaultRunStatus = sd.getRunStatus();
// if(Objects.nonNull(sd.getRelativeStation())){
// this.relativeStationCode = sd.getRelativeStation().getCode();
// this.relativeStationName = sd.getRelativeStation().getName();
// }
}
private String code;
private String ioName;
private String relativeStationName;
private String relativeStationCode;
/**
* 接发车类型
*/
private StationDirection.ReceiveAndDeliverModel defaultRunStatus;
/**
* 出入口方向
* 1.双线自动闭塞区段按进站信号机的行别属性
* 选择下行进站/上行出站/下行出站/上行进站
* 2.单线自动闭塞半自动闭塞区段选择双向
*/
private StationDirection.IODirection ioDirection;
/**
* 允许超限列车
* 选择/
* 1.普速铁路一般选择有明确不允许超限列
* 车的选择
* 2.高速铁路一般选择200km/h 客货共线铁路
* 根据文件确定
*/
private boolean allowOverrun;
/**
* 允许旅客列车
* 选择/两线多线区间根据行规
* 车运行分工选择
*/
private boolean travelTrain;
/**
* 允许货物列车
* 选择/两线多线区间根据行规
* 车运行分工选择
*/
private boolean goodsTrain;
}

View File

@ -2,6 +2,7 @@ package club.joylink.rtss.simulation.cbtc.CTC.data;
import club.joylink.rtss.simulation.cbtc.data.map.Section;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
/**
@ -9,6 +10,7 @@ import lombok.Setter;
*/
@Setter
@Getter
@NoArgsConstructor
public class TrackSection {
/**
* 编码
@ -69,10 +71,24 @@ public class TrackSection {
*/
private boolean military;
public void trainData(TrackSection ts){
ts.name = this.name;
ts.sectionCode = this.sectionCode;
}
public TrackSection(Section section) {
this.code = section.getCode();
this.name = section.getName();
this.sectionCode = section.getCode();
this.initDefault();
}
private void initDefault(){
this.trackNature =TrackNature.RIGHT_TRACK;
this.direction =DirectionType.D;
this.trainType = TrainType.VAN;
this.transfinite = CtcStationRunPlanLog.TransfiniteType.NO;
this.standType = StandType.NO;
}
/**

View File

@ -0,0 +1,20 @@
package club.joylink.rtss.simulation.cbtc.CTC.data.vo;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
public class FZkVO<T> {
private int version;
private T data;
public static <T> FZkVO of(int version,T d){
FZkVO<T> vo = new FZkVO<>();
vo.setVersion(version);
vo.setData(d);
return vo;
}
}

View File

@ -0,0 +1,126 @@
package club.joylink.rtss.simulation.cbtc.CTC.data.vo;
import club.joylink.rtss.simulation.cbtc.CTC.data.RegularTrainLine;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.Map;
import java.util.Objects;
@Data
@NoArgsConstructor
public class RegularTrainLineVO implements Cloneable {
public RegularTrainLineVO(RegularTrainLine rt){
this.code = rt.getCode();
this.stationCode = rt.getStation().getCode();
this.stationName = rt.getStation().getName();
this.masterCode = rt.getMasterStand().getCode();
this.masterName = rt.getMasterStand().getName();
this.arriveTipNum = rt.getArriveTipNum();
this.leaveTipNum = rt.getLeaveTipNum();
this.arriveTime = rt.getArriveTime();
this.leaveTime = rt.getLeaveTime();
if(Objects.nonNull(rt.getEnter())){
this.enterDirCode = rt.getEnter().getCode();
this.enterDirName = rt.getEnter().getName();
}
if(Objects.nonNull(rt.getBackStation())){
this.backStationCode = rt.getBackStation().getCode();
this.backStationName = rt.getBackStation().getName();
}
if(Objects.nonNull(rt.getOut())){
this.outDirCode = rt.getOut().getCode();
this.outDirName = rt.getOut().getName();
}
if(Objects.nonNull(rt.getFontStation())){
this.fontStationCode = rt.getFontStation().getCode();
this.fontStationName = rt.getFontStation().getName();
}
this.appendData = rt.getAppendData();
}
private String code;
/**
* 车站code
*/
private String stationCode;
private String stationName;
/**
* 股道
*/
private String masterCode;
private String masterName;
/**
* 到达车次
*/
private String arriveTipNum;
/**
* 出发车次
*/
private String leaveTipNum;
/**
* 到达时间
*/
private LocalTime arriveTime;
/**
* 出发时间
*/
private LocalTime leaveTime;
/**
* 入口
*/
private String enterDirCode;
private String enterDirName;
/**
* 后方车站
*/
private String backStationCode;
private String backStationName;
/**
* 出口
*/
private String outDirCode;
private String outDirName;
/**
* 前方车站
*/
private String fontStationCode;
private String fontStationName;
/**
* 批量处理车次前缀
* 参数prefixTrain,startTipNum,endTipNum 都不为空的时候认为此次是批量处理
*/
private String prefixTrain;
/**
* 批量处理车次开始
* 参数prefixTrain,startTipNum,endTipNum 都不为空的时候认为此次是批量处理
*/
private Integer startTipNum;
/**
* 批量处理车次结束
* 参数prefixTrain,startTipNum,endTipNum 都不为空的时候认为此次是批量处理
*/
private Integer endTipNum;
/**
*
*/
private Map<RegularTrainLine.AppendDataType, Boolean> appendData;
public RegularTrainLineVO clone() {
try {
return (RegularTrainLineVO) super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return null;
}
}

View File

@ -3,6 +3,8 @@ package club.joylink.rtss.simulation.cbtc.CTC.operation;
import club.joylink.rtss.simulation.cbtc.ATS.operation.Operation;
import club.joylink.rtss.simulation.cbtc.ATS.operation.annotation.OperateHandler;
import club.joylink.rtss.simulation.cbtc.ATS.operation.annotation.OperateHandlerMapping;
import club.joylink.rtss.simulation.cbtc.CTC.data.vo.FZkVO;
import club.joylink.rtss.simulation.cbtc.CTC.data.vo.RegularTrainLineVO;
import club.joylink.rtss.simulation.cbtc.CTC.param.CtcRunPlanParam;
import club.joylink.rtss.simulation.cbtc.CTC.service.runplan.CtcManageService;
import club.joylink.rtss.simulation.cbtc.Simulation;
@ -40,10 +42,10 @@ public class CtcManageOperateHandler {
* @param simulation 仿真实体
* @param stationCode 车站编码
*/
@OperateHandlerMapping(type = Operation.Type.CTC_RELEASE_RUN_PLAN_TO_SIMULATION)
/*@OperateHandlerMapping(type = Operation.Type.CTC_RELEASE_RUN_PLAN_TO_SIMULATION)
public void releaseRunPlanToSimulation(Simulation simulation, String stationCode) {
ctcManageService.releaseRunPlanToEffectAreaMap(simulation, stationCode);
}
}*/
/**
* 导入覆盖车站编辑区行车日志
@ -90,4 +92,38 @@ public class CtcManageOperateHandler {
public void effectRunPlanToSimulation(Simulation simulation, String stationCode) {
ctcManageService.releaseRunPlanToStation(simulation, stationCode);
}
/**
* 固定列车经路更新
* @param simulation
* @param stationCode
*/
@OperateHandlerMapping(type = Operation.Type.REGULAR_TRAIN_LINE_STATION_UPDATE)
public void stationUpdate(Simulation simulation, String stationCode){
this.ctcManageService.stationUpdateFromEffect(simulation,stationCode);
}
/**
*
* @param simulation
* @param stationCode
* @return
*/
@OperateHandlerMapping(type = Operation.Type.REGULAR_TRAIN_LINE_STATION_UPDATE_LIST)
public FZkVO<List<RegularTrainLineVO>> loadUpdateTrainLineData(Simulation simulation, String stationCode){
return this.ctcManageService.loadUpdateRegularTrainLineList(simulation,stationCode);
}
/**
* 加载更新区的固定列车径路到计划中
* @param simulation
* @param stationCode
*/
@OperateHandlerMapping(type = Operation.Type.REGULAR_TRAIN_LINE_STATION_UPDATE_LOAD)
public void loadRegularTrainLineToPlan(Simulation simulation, String stationCode){
this.ctcManageService.loadRegularTrainLineToPlan(simulation,stationCode);
}
}

View File

@ -0,0 +1,52 @@
package club.joylink.rtss.simulation.cbtc.CTC.operation.fck;
import club.joylink.rtss.simulation.cbtc.ATS.operation.Operation;
import club.joylink.rtss.simulation.cbtc.ATS.operation.annotation.OperateHandler;
import club.joylink.rtss.simulation.cbtc.ATS.operation.annotation.OperateHandlerMapping;
import club.joylink.rtss.simulation.cbtc.CTC.data.CtcRepository;
import club.joylink.rtss.simulation.cbtc.CTC.data.StationIOGate;
import club.joylink.rtss.simulation.cbtc.CTC.service.runplan.CtcManageService;
import club.joylink.rtss.simulation.cbtc.Simulation;
import lombok.extern.slf4j.Slf4j;
import javax.annotation.Resource;
import java.util.List;
/**
* 车务管理终端操作--车站出入口
*/
@OperateHandler
@Slf4j
public class CtcManageIOGateOperateHandler {
@Resource
private CtcManageService ctcManageService;
/**
* 车务管理终端车站出入口编辑
* @param simulation
* @param stationCode
* @param ts
*/
@OperateHandlerMapping(type = Operation.Type.STATION_IO_GATE_EDIT)
public void stationIOGateEdit(Simulation simulation, String stationCode, StationIOGate ts){
ctcManageService.editIOGate(simulation,stationCode,ts);
}
/**
* 车务管理终端车站出入口列表
* @param simulation
* @param stationCode
* @return
*/
@OperateHandlerMapping(type = Operation.Type.STATION_IO_GATE_LIST)
public List<StationIOGate> stationIOGateList(Simulation simulation, String stationCode){
return ctcManageService.listIOGate(simulation,stationCode);
}
@OperateHandlerMapping(type = Operation.Type.STATION_IO_GATE_PUBLISH)
public void publist(Simulation simulation, String stationCode){
ctcManageService.publishData(simulation, CtcRepository.CtcFZKType.STATION_DETAIL,stationCode);
}
}

View File

@ -0,0 +1,51 @@
package club.joylink.rtss.simulation.cbtc.CTC.operation.fck;
import club.joylink.rtss.simulation.cbtc.ATS.operation.Operation;
import club.joylink.rtss.simulation.cbtc.ATS.operation.annotation.OperateHandler;
import club.joylink.rtss.simulation.cbtc.ATS.operation.annotation.OperateHandlerMapping;
import club.joylink.rtss.simulation.cbtc.CTC.data.CtcRepository;
import club.joylink.rtss.simulation.cbtc.CTC.data.TrackSection;
import club.joylink.rtss.simulation.cbtc.CTC.service.runplan.CtcManageService;
import club.joylink.rtss.simulation.cbtc.Simulation;
import lombok.extern.slf4j.Slf4j;
import javax.annotation.Resource;
import java.util.List;
/**
* 车务管理终端操作--车站股道
*/
@OperateHandler
@Slf4j
public class CtcManageMasterLineOperateHandler {
@Resource
private CtcManageService ctcManageService;
/**
*车务管理终端股道列表
* @param simulation
* @param stationCode
*/
@OperateHandlerMapping(type = Operation.Type.STATION_DETAIL_LIST)
public List<TrackSection> listMasterLine(Simulation simulation, String stationCode){
return this.ctcManageService.listMasterLine(simulation,stationCode);
}
/**
* 车务管理终端股道修改
* @param simulation
* @param stationCode
* @param ts
*/
@OperateHandlerMapping(type = Operation.Type.STATION_DETAIL_EDIT)
public void editMasterLine(Simulation simulation, String stationCode, TrackSection ts){
ctcManageService.editMasterLine(simulation,stationCode,ts);
}
@OperateHandlerMapping(type = Operation.Type.STATION_DETAIL_PUBLISH)
public void publist(Simulation simulation, String stationCode){
ctcManageService.publishData(simulation, CtcRepository.CtcFZKType.STATION_DETAIL,stationCode);
}
}

View File

@ -0,0 +1,93 @@
package club.joylink.rtss.simulation.cbtc.CTC.operation.fck;
import club.joylink.rtss.simulation.cbtc.ATS.operation.Operation;
import club.joylink.rtss.simulation.cbtc.ATS.operation.annotation.OperateHandler;
import club.joylink.rtss.simulation.cbtc.ATS.operation.annotation.OperateHandlerMapping;
import club.joylink.rtss.simulation.cbtc.CTC.data.CtcRepository;
import club.joylink.rtss.simulation.cbtc.CTC.data.vo.RegularTrainLineVO;
import club.joylink.rtss.simulation.cbtc.CTC.service.runplan.CtcManageService;
import club.joylink.rtss.simulation.cbtc.Simulation;
import lombok.extern.slf4j.Slf4j;
import javax.annotation.Resource;
import java.util.List;
/**
* 车务管理终端操作--固定列车经路
*/
@OperateHandler
@Slf4j
public class CtcManageRegularTrainLineOperateHandler {
@Resource
private CtcManageService ctcManageService;
/**
* 保存固定列车经路
*
* @param simulation 仿真实体
* @param stationCode 车站编码
* @param runPlanParamList 运行计划
*/
@OperateHandlerMapping(type = Operation.Type.REGULAR_TRAIN_LINE_SAVE)
public void saveTrainLine(Simulation simulation, String stationCode, RegularTrainLineVO runPlanParamList) {
this.ctcManageService.editRegularTrain(simulation,stationCode,runPlanParamList,true);
}
@OperateHandlerMapping(type = Operation.Type.REGULAR_TRAIN_LINE_EDIT)
public void editTrainLine(Simulation simulation, String stationCode, RegularTrainLineVO runPlanParamList) {
this.ctcManageService.editRegularTrain(simulation,stationCode,runPlanParamList,false);
}
/**
* 保存固定列车经路批量处理
* @param simulation
* @param stationCode
* @param runPlanParamList
*/
@OperateHandlerMapping(type = Operation.Type.REGULAR_TRAIN_LINE_BATCH)
public void batchSaveTrainLine(Simulation simulation, String stationCode, RegularTrainLineVO runPlanParamList) {
this.ctcManageService.batchSaveRegularTrain(simulation,stationCode,runPlanParamList);
}
/**
* 固定列车经路列表
* @param simulation
* @param stationCode
* @return
*/
@OperateHandlerMapping(type = Operation.Type.REGULAR_TRAIN_LINE_LIST)
public List<RegularTrainLineVO> listTrainLine(Simulation simulation, String stationCode) {
return this.ctcManageService.regularTrainLineList(simulation,stationCode);
}
/**
* 保存固定列车删除
* @param simulation
* @param stationCode
* @param code
*/
@OperateHandlerMapping(type = Operation.Type.REGULAR_TRAIN_LINE_DELETE)
public void delete(Simulation simulation, String stationCode,String code){
this.ctcManageService.delete(simulation,stationCode,code);
}
/**
* 保存固定列车清空
* @param simulation
* @param stationCode
*/
@OperateHandlerMapping(type = Operation.Type.REGULAR_TRAIN_LINE_CLEAR)
public void clear(Simulation simulation, String stationCode){
this.ctcManageService.remove(simulation,stationCode);
}
/**
* 编辑区上传到生效区
* @param simulation
* @param stationCode
*/
@OperateHandlerMapping(type = Operation.Type.REGULAR_TRAIN_LINE_PUBLISH)
public void publish(Simulation simulation, String stationCode){
ctcManageService.publishData(simulation, CtcRepository.CtcFZKType.REGULAR_TRAIN,stationCode);
}
}

View File

@ -1,12 +1,14 @@
package club.joylink.rtss.simulation.cbtc.CTC.param;
import club.joylink.rtss.simulation.cbtc.CTC.data.CtcStationRunPlanLog;
import club.joylink.rtss.simulation.cbtc.CTC.data.RegularTrainLine;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
@ -207,6 +209,231 @@ public class CtcRunPlanParam implements Cloneable {
*/
private boolean receive;
public CtcRunPlanParam(RegularTrainLine tl){
/**
* 运行计划编码
* private String runPlanCode;
*/
/**
* 车站编码
* private String stationCode;
*/
this.stationCode = tl.getStation().getCode();
/**
* 班别
* private String groupNumber;
*/
/**
* 运行计划车次信息
* private String tripNumber;
*/
/**
* 运行计划的默认股道
* private String trackSectionCode;
*/
/**
* 到达股道
* private String arriveSectionCode;
*/
this.arriveSectionCode = tl.getMasterStand().getCode();
/**
* 到达计划时间
* private LocalDateTime arrivePlanTime;
*/
this.arrivePlanTime = tl.getArriveTime().atDate(LocalDate.now());
/**
* 到达时间
* private LocalDateTime arriveTime;
*/
/**
* 到达车次
* private String arriveTripNumber;
*/
this.arriveTripNumber = tl.getArriveTipNum();
/**
* 到达车站
* private String arriveStationCode;
*/
this.arriveStationCode = tl.getStation().getCode();
/**
* 到达方向编码到达口
* private String arriveDirectionCode;
*/
if(Objects.nonNull(tl.getEnter())){
this.arriveDirectionCode = tl.getEnter().getCode();
}
/**
* 始发计划
* private Boolean startRunPlan;
*/
/**
* 发车股道
* private String departSectionCode;
*/
this.departSectionCode = tl.getMasterStand().getCode();
/**
* 发车计划时间
* private LocalDateTime departPlanTime;
*/
this.departPlanTime = tl.getLeaveTime().atDate(LocalDate.now());
/**
* 发车时间
* private LocalDateTime departTime;
*/
/**
* 发车车次
* private String departTripNumber;
*/
this.departTripNumber = tl.getLeaveTipNum();
/**
* 发车车站
* private String departStationCode;
*/
this.departStationCode = tl.getBackStation().getCode();
/**
* 发向方向编码发车口
* private String departDirectionCode;
*/
if(Objects.nonNull(tl.getOut())){
this.departDirectionCode = tl.getOut().getCode();
}
/**
* 终到计划
* private Boolean endRunPlan;
*/
/**
* 状态-1删除0修改1添加
* private int status;
*/
this.status = 1;
/**
* 电力计划
* private Boolean electrical;
*/
/**
* 到达电力
* private Boolean arriveElectrical;
*/
/**
* 出发到达
* private Boolean departElectrical;
*/
/**
* 超限等级
* private CtcStationRunPlanLog.TransfiniteType transfinite;
*/
/**
* 到达超限
* private CtcStationRunPlanLog.TransfiniteType arriveTransfinite;
*/
/**
* 出发超限
* private CtcStationRunPlanLog.TransfiniteType departTransfinite;
*/
/**
* 办理客运
* private Boolean passenger;
*/
/**
* 重点列车
* private Boolean keyTrains;
*/
/**
* 是否军用
* private Boolean military;
*/
/**
* 运行股道与基本径路不一致
* private Boolean trackDiscordant;
*/
/**
* 出入口与基本径路不一致
* private Boolean entryOutDiscordant;
*/
/**
* 记事
* private String remark;
*/
/**
* 晚点原因
* private String lateReason;
*/
/**
* 列车运行计划作业
* private Map<CtcStationRunPlanLog.RunPlanTask, Integer> runPlanTaskMap = new HashMap<>();
*/
/**
* 列车类型
* private TrainType trainType;
*/
/**
* 运行类型
* private RunType runType;
*/
}
/**
* 删除时构造实体
*

View File

@ -2,6 +2,7 @@ package club.joylink.rtss.simulation.cbtc.CTC.service;
import club.joylink.rtss.exception.BusinessExceptionAssertEnum;
import club.joylink.rtss.simulation.cbtc.CI.CiApiService;
import club.joylink.rtss.simulation.cbtc.CTC.data.CtcEffectRepository;
import club.joylink.rtss.simulation.cbtc.CTC.data.CtcRepository;
import club.joylink.rtss.simulation.cbtc.CTC.data.CtcStationRunPlanLog;
import club.joylink.rtss.simulation.cbtc.CTC.data.RouteSequence;
@ -160,6 +161,16 @@ public class CTCService {
line.setAutoTrigger(trigger);
}
/**
*
* @param simulation
* @param routeCode
* @param tripNumber
* @param force
* @param duration
* @return
*/
public List<String> setRoute(Simulation simulation, String routeCode, String tripNumber, Boolean force, Integer duration) {
Route route = simulation.getRepository().getByCode(routeCode, Route.class);
Station station = route.getStart().getStation();

View File

@ -0,0 +1,87 @@
package club.joylink.rtss.simulation.cbtc.CTC.service;
import club.joylink.rtss.simulation.cbtc.CTC.data.CascoControl;
import club.joylink.rtss.simulation.cbtc.CTC.data.CtcEffectRepository;
import club.joylink.rtss.simulation.cbtc.CTC.data.CtcRepository;
import club.joylink.rtss.simulation.cbtc.CTC.data.CtcStationRunPlanLog;
import club.joylink.rtss.simulation.cbtc.Simulation;
import club.joylink.rtss.simulation.cbtc.data.map.Station;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Function;
import java.util.stream.Collectors;
@Service
@Slf4j
public class CascoControlService {
/**
*
* @param cc
* @return
*/
public List<String> checkCascoControlRoute(CascoControl cc){
Station station = cc.getStation();
Simulation simulation = cc.getSimulation();
String stationCode = station.getCode();
CtcRepository ctcRepository = simulation.getCtcRepository();
CtcEffectRepository effectRepository = ctcRepository.getCtcEffectRepository();
Map<String, CtcStationRunPlanLog> runPlanLogMap = simulation.getCtcRepository().getSimulationRunPlanMap().get(stationCode);
Optional<CtcStationRunPlanLog> runPlanLogOptional = null;
if(Objects.nonNull(runPlanLogMap) && !runPlanLogMap.isEmpty()){
runPlanLogOptional = this.checkForRunPlan(cc);
}
// List<CtcStationRunPlanLog> allRunPlanLogList = runPlanLogMap.values().stream().filter(d->d.getChangeType() == null && d.isSign()).collect(Collectors.toList());
CtcEffectRepository.StationDoorRepository doorRepository = effectRepository.getDoorRepository().get(stationCode);
if(Objects.nonNull(doorRepository)){
if(runPlanLogOptional.isPresent()){
}
return cc.getErrorList();
}
CtcEffectRepository.StationTrackSectionRepository stationTrackRepository = effectRepository.getStationTrackSectionMap().get(stationCode);
if(Objects.nonNull(stationTrackRepository)){
}
return null;
}
private Optional<CtcStationRunPlanLog> checkForRunPlan(/*List<CtcStationRunPlanLog> allRunPlanLogList,*/CascoControl cc){
CtcStationRunPlanLog runPlanLog = cc.getSimulation().getCtcRepository().getRunPlan(cc.getStation().getCode(),cc.getTripNum());
if(Objects.isNull(runPlanLog)){
cc.addErrorMsg(String.format("未在计划中找到对应的车次[%s]",cc.getTripNum()));
}
if(!Objects.isNull(runPlanLog.getChangeType()) && !runPlanLog.isSign()){
cc.addErrorMsg(String.format("未在计划中找到对应的车次[%s]",cc.getTripNum()));
}
return Optional.of(runPlanLog);
/*Map<String,CtcStationRunPlanLog> tripNumMap = allRunPlanLogList.stream().collect(Collectors.toMap(CtcStationRunPlanLog::getTripNumber, Function.identity(),(v1,v2)->v1));
CtcStationRunPlanLog runPlanLog = tripNumMap.get(cc.getTripNum());
if(Objects.isNull(runPlanLog)){
cc.addErrorMsg(String.format("未在计划中找到对应的车次[%s]",cc.getTripNum()));
}*/
}
private void checkCascoForStationTrack(CtcEffectRepository.StationTrackSectionRepository stationTrackRepository){
}
private void checkCascoForDoor(CtcEffectRepository.StationDoorRepository doorRepository,CtcStationRunPlanLog runPlanLog){
CtcStationRunPlanLog.RunPlanItem departPlan = runPlanLog.getDepartRunPlan();
CtcStationRunPlanLog.RunPlanItem arrivePlan = runPlanLog.getArriveRunPlan();
if(Objects.nonNull(departPlan)){
}
if(Objects.nonNull(arrivePlan)){
}
}
}

View File

@ -1,21 +1,34 @@
package club.joylink.rtss.simulation.cbtc.CTC.service.runplan;
import club.joylink.rtss.exception.BaseException;
import club.joylink.rtss.exception.BusinessExceptionAssertEnum;
import club.joylink.rtss.simulation.cbtc.CTC.data.CtcManageRepository;
import club.joylink.rtss.simulation.cbtc.CI.data.StationDirection;
import club.joylink.rtss.simulation.cbtc.CTC.data.*;
import club.joylink.rtss.simulation.cbtc.CTC.data.vo.FZkVO;
import club.joylink.rtss.simulation.cbtc.CTC.data.vo.RegularTrainLineVO;
import club.joylink.rtss.simulation.cbtc.CTC.param.CtcRunPlanParam;
import club.joylink.rtss.simulation.cbtc.Simulation;
import club.joylink.rtss.simulation.cbtc.data.SimulationDataRepository;
import club.joylink.rtss.simulation.cbtc.data.map.Section;
import club.joylink.rtss.simulation.cbtc.data.map.Station;
import com.google.common.base.Strings;
import com.google.common.collect.Collections2;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import java.util.List;
import javax.annotation.Resource;
import java.time.LocalTime;
import java.util.*;
@Component
@Slf4j
public class CtcManageService {
@Autowired
@Resource
private CtcStationRunPlanLogService ctcStationRunPlanLogService;
/**
@ -107,7 +120,7 @@ public class CtcManageService {
* @param stationCode 车站编码
*/
public void releaseRunPlanToEffectAreaMap(Simulation simulation, String stationCode) {
// simulation.getCtcRepository().getCtcEffectRepository()
}
/**
@ -119,4 +132,349 @@ public class CtcManageService {
public List<CtcRunPlanParam> pullCtcManageRunPlan(Simulation simulation) {
return simulation.getCtcRepository().getCtcManageRepository().getEditAllRunPlan();
}
/**
* 车务管理终端股道修改
* @param simulation
* @param stationCode
* @param ts
*/
public void editMasterLine(Simulation simulation,String stationCode, TrackSection ts){
BusinessExceptionAssertEnum.DATA_NOT_EXIST
.assertNotTrue(Strings.isNullOrEmpty(ts.getCode()), String.format("未找到对应的站细"));
CtcManageRepository repository = simulation.getCtcRepository().getCtcManageRepository();
CtcEffectRepository.StationTrackSectionRepository trackSectionRepository = repository.getTrackSectionRepository().get(stationCode);
TrackSection obj = trackSectionRepository.query(ts.getCode());
BusinessExceptionAssertEnum.DATA_NOT_EXIST
.assertNotTrue(Objects.isNull(obj), String.format("未找到对应的站细"));
obj.trainData(ts);
trackSectionRepository.save(ts);
}
/**
* 车务管理终端股道列表
* @param simulation
* @param stationCode
* @return
*/
public List<TrackSection> listMasterLine(Simulation simulation,String stationCode){
BusinessExceptionAssertEnum.DATA_ERROR.assertNotTrue(Objects.isNull(stationCode), String.format("车站号不能为空"));
CtcManageRepository repository = simulation.getCtcRepository().getCtcManageRepository();
CtcEffectRepository.StationTrackSectionRepository trackSectionRepository = repository.getTrackSectionRepository().get(stationCode);
if(Objects.isNull(trackSectionRepository) || trackSectionRepository.getDataMap().isEmpty()){
return Collections.emptyList();
}
return Lists.newArrayList(trackSectionRepository.getDataMap().values());
}
/**
* 修改出入口
* @param simulation
* @param stationCode
* @param ts
*/
public void editIOGate(Simulation simulation,String stationCode, StationIOGate ts){
BusinessExceptionAssertEnum.DATA_ERROR.assertNotTrue(Objects.isNull(stationCode), String.format("车站号不能为空"));
CtcManageRepository repository = simulation.getCtcRepository().getCtcManageRepository();
CtcEffectRepository.StationDoorRepository trackSectionRepository = repository.getDoorRepository().get(stationCode);
StationDirection obj = trackSectionRepository.query(ts.getCode());
BusinessExceptionAssertEnum.DATA_ERROR.assertNotTrue(Objects.isNull(obj), String.format("出入口%s未找到无法修改",stationCode));
obj.setAllowOverrun(ts.isAllowOverrun());
obj.setTravelTrain(ts.isTravelTrain());
obj.setGoodsTrain(ts.isGoodsTrain());
trackSectionRepository.save(obj);
}
/**
* 出入口列表
* @param simulation
* @param stationCode
* @return
*/
public List<StationIOGate> listIOGate(Simulation simulation,String stationCode){
BusinessExceptionAssertEnum.DATA_ERROR.assertNotTrue(Objects.isNull(stationCode), String.format("车站号不能为空"));
CtcManageRepository repository = simulation.getCtcRepository().getCtcManageRepository();
CtcEffectRepository.StationDoorRepository doorRepository = repository.getDoorRepository().get(stationCode);
if(Objects.isNull(doorRepository) || doorRepository.getDataMap().isEmpty()){
return Collections.emptyList();
}
List<StationIOGate> gateList = new ArrayList<>();
for (StationDirection value : doorRepository.getDataMap().values()) {
gateList.add(new StationIOGate(value));
}
return gateList;
}
/**
* 固定列车经路添加修改
* @param simulation
* @param stationCode
* @param rt
*/
public void editRegularTrain(Simulation simulation, String stationCode, RegularTrainLineVO rt,boolean isSave){
BusinessExceptionAssertEnum.DATA_ERROR.assertNotTrue(Objects.isNull(stationCode), String.format("车站号不能为空"));
if(!isSave && Strings.isNullOrEmpty(rt.getCode())){
BusinessExceptionAssertEnum.DATA_ERROR.assertNotTrue(Objects.isNull(stationCode), String.format("固定列车径路code 不能为空"));
}
CtcManageRepository repository = simulation.getCtcRepository().getCtcManageRepository();
CtcEffectRepository.RegularTrainLineRepository tLRepository = repository.getRegularTrainLineMap().get(stationCode);
if(tLRepository == null){
tLRepository = new CtcEffectRepository.RegularTrainLineRepository();
repository.getRegularTrainLineMap().put(stationCode,tLRepository);
}
if(Strings.isNullOrEmpty(rt.getCode())){
rt.setCode(simulation.getCtcRepository().createCode(CtcRepository.CtcFZKType.REGULAR_TRAIN,simulation.getId()));
}else{
RegularTrainLine tl = tLRepository.query(rt.getCode());
BusinessExceptionAssertEnum.DATA_ERROR.assertNotTrue(Objects.isNull(tl), String.format("车站%s未找到不能修改",stationCode));
tLRepository.remove(rt.getCode());
}
SimulationDataRepository dataRepository = simulation.getRepository();
RegularTrainLine rtObj = this.regularTrainLineChangeObj(dataRepository,stationCode,rt);
tLRepository.save(rtObj);
}
private RegularTrainLine regularTrainLineChangeObj(SimulationDataRepository dataRepository,String stationCode,RegularTrainLineVO rtvo){
RegularTrainLine rt = new RegularTrainLine(rtvo);
Station station = dataRepository.getByCode(stationCode, Station.class);
Section stand = dataRepository.getByCode(rtvo.getMasterCode(), Section.class);
rt.setStation(station);
rt.setMasterStand(stand);
if(Objects.nonNull(rtvo.getBackStationCode())){
Station backStation = dataRepository.getByCode(rtvo.getBackStationCode(),Station.class);
rt.setBackStation(backStation);
}
if(Objects.nonNull(rtvo.getFontStationCode())){
Station fontStation = dataRepository.getByCode(rtvo.getFontStationCode(),Station.class);
rt.setFontStation(fontStation);
}
if(Objects.nonNull(rtvo.getEnterDirCode())){
StationDirection enter = dataRepository.getByCode(rtvo.getEnterDirCode(),StationDirection.class);
rt.setEnter(enter);
}
if(Objects.nonNull(rtvo.getOutDirCode())){
StationDirection outer = dataRepository.getByCode(rtvo.getOutDirCode(),StationDirection.class);
rt.setOut(outer);
}
return rt;
}
/**
* 固定列车经路批量添加
* @param simulation
* @param stationCode
* @param rt
*/
public void batchSaveRegularTrain(Simulation simulation, String stationCode, RegularTrainLineVO rt){
BusinessExceptionAssertEnum.DATA_ERROR.assertNotTrue(Objects.isNull(stationCode), String.format("车站号不能为空"));
BusinessExceptionAssertEnum.DATA_ERROR.assertNotTrue(Strings.isNullOrEmpty(rt.getPrefixTrain()), String.format("批量添加车次前缀不能为空"));
BusinessExceptionAssertEnum.DATA_ERROR.assertNotTrue((Objects.isNull(rt.getStartTipNum()) || Objects.isNull(rt.getEndTipNum())), String.format("批量添加车次号开始或结束不能为空"));
BusinessExceptionAssertEnum.DATA_ERROR.assertNotTrue(rt.getEndTipNum() < rt.getStartTipNum(), String.format("批量添加车次号结束不能小于车次号开始"));
int min = 0;
for(var start = rt.getStartTipNum() ; start <= rt.getEndTipNum();start++){
RegularTrainLineVO newRt = rt.clone();
String tipNum = rt.getPrefixTrain().concat(start.toString());
newRt.setArriveTipNum(tipNum);
newRt.setLeaveTipNum(tipNum);
//批量处理默认到达离开时间
if(min > 0){
//除了第一次剩下的到达时间晚3分钟
min += 3 * 60;
}
newRt.setArriveTime(LocalTime.ofSecondOfDay(min));
//离开时间加5分钟
min += 5 * 60;
newRt.setLeaveTime(LocalTime.ofSecondOfDay(min));
this.editRegularTrain(simulation,stationCode,newRt,true);
}
}
/**
* 编辑区的列车经路列表
* @param simulation
* @param stationCode
* @return
*/
public List<RegularTrainLineVO> regularTrainLineList(Simulation simulation, String stationCode){
BusinessExceptionAssertEnum.DATA_ERROR.assertNotTrue(Objects.isNull(stationCode), String.format("车站号不能为空"));
CtcManageRepository repository = simulation.getCtcRepository().getCtcManageRepository();
CtcEffectRepository.RegularTrainLineRepository tLRepository = repository.getRegularTrainLineMap().get(stationCode);
return this.loadRegularTrainLineData(tLRepository);
}
private List<RegularTrainLineVO> loadRegularTrainLineData(CtcEffectRepository.RegularTrainLineRepository tLRepository){
if(Objects.isNull(tLRepository) || tLRepository.getDataMap().isEmpty()){
return Collections.emptyList();
}
List<RegularTrainLineVO> voList = new ArrayList<>(tLRepository.getDataMap().values().size());
for (RegularTrainLine value : tLRepository.getDataMap().values()) {
voList.add(new RegularTrainLineVO(value));
}
return voList;
}
/**
* 删除编辑区的列车经路的数据
* @param simulation
* @param stationCode
* @param code
*/
public void delete(Simulation simulation, String stationCode,String code){
BusinessExceptionAssertEnum.DATA_ERROR.assertNotTrue(Objects.isNull(stationCode), String.format("车站号不能为空"));
CtcManageRepository repository = simulation.getCtcRepository().getCtcManageRepository();
CtcEffectRepository.RegularTrainLineRepository tLRepository = repository.getRegularTrainLineMap().get(stationCode);
tLRepository.remove(code);
}
/**
* 清除编辑区的列车经路的数据
* @param simulation
* @param stationCode
*/
public void remove(Simulation simulation, String stationCode){
BusinessExceptionAssertEnum.DATA_ERROR.assertNotTrue(Objects.isNull(stationCode), String.format("车站号不能为空"));
CtcManageRepository repository = simulation.getCtcRepository().getCtcManageRepository();
CtcEffectRepository.RegularTrainLineRepository tLRepository = repository.getRegularTrainLineMap().get(stationCode);
tLRepository.getDataMap().clear();
}
/**
* 编辑区发布到生效区
* @param simulation
* @param fzkType
* @param stationCode
*/
public void publishData(Simulation simulation, CtcRepository.CtcFZKType fzkType, String stationCode){
BusinessExceptionAssertEnum.DATA_ERROR.assertNotTrue(Objects.isNull(stationCode), String.format("车站号不能为空"));
CtcManageRepository ctcManageRepository = simulation.getCtcRepository().getCtcManageRepository();
CtcEffectRepository effectRepository = simulation.getCtcRepository().getCtcEffectRepository();
CtcEffectRepository.AbstractWorkspaceRepository source = null;
CtcEffectRepository.AbstractWorkspaceRepository target = null;
switch (fzkType){
case STATION_DETAIL:
source = ctcManageRepository.getTrackSectionRepository().get(stationCode);
target = effectRepository.getStationTrackSectionMap().get(stationCode);
if(Objects.isNull(source)){
source = new CtcEffectRepository.StationTrackSectionRepository();
ctcManageRepository.getTrackSectionRepository().put(stationCode, (CtcEffectRepository.StationTrackSectionRepository) source);
}
if(Objects.isNull(target)){
target = new CtcEffectRepository.StationTrackSectionRepository();
effectRepository.getStationTrackSectionMap().put(stationCode, (CtcEffectRepository.StationTrackSectionRepository) target);
}
break;
case IO_GATE:
source = ctcManageRepository.getDoorRepository().get(stationCode);
target = effectRepository.getDoorRepository().get(stationCode);
if(Objects.isNull(source)){
source = new CtcEffectRepository.StationDoorRepository();
ctcManageRepository.getDoorRepository().put(stationCode, (CtcEffectRepository.StationDoorRepository) source);
}
if(Objects.isNull(target)){
target = new CtcEffectRepository.StationDoorRepository();
effectRepository.getDoorRepository().put(stationCode, (CtcEffectRepository.StationDoorRepository) target);
}
break;
case REGULAR_TRAIN:
source = ctcManageRepository.getRegularTrainLineMap().get(stationCode);
target = effectRepository.getRegularTrainLineMap().get(stationCode);
if(Objects.isNull(source)){
source = new CtcEffectRepository.RegularTrainLineRepository();
ctcManageRepository.getRegularTrainLineMap().put(stationCode, (CtcEffectRepository.RegularTrainLineRepository) source);
}
if(Objects.isNull(target)){
target = new CtcEffectRepository.RegularTrainLineRepository();
effectRepository.getRegularTrainLineMap().put(stationCode, (CtcEffectRepository.RegularTrainLineRepository) target);
}
break;
default:
BusinessExceptionAssertEnum.DATA_NOT_EXIST.assertNotTrue(true, String.format("未找到要发布的类型type[%s],stationCode[%s]",fzkType,stationCode));
}
this.dataTranFromDraft2Effect(source,target);
}
private void dataTranFromDraft2Effect(CtcEffectRepository.AbstractWorkspaceRepository source,CtcEffectRepository.AbstractWorkspaceRepository target){
int targetVersion = target.incrementVersionOne();
source.resetVersion(targetVersion);
for (Object value : source.getDataMap().values()) {
target.save(value);
}
}
/**
* 固定列车经路更新到车站的更新区
* @param simulation
* @param stationCode
*/
public void stationUpdateFromEffect(Simulation simulation, String stationCode){
BusinessExceptionAssertEnum.DATA_ERROR.assertNotTrue(Objects.isNull(stationCode), String.format("车站号不能为空"));
CtcEffectRepository effectRepository = simulation.getCtcRepository().getCtcEffectRepository();
CtcEffectRepository.RegularTrainLineRepository regularTrainLineRepository = effectRepository.getRegularTrainLineMap().get(stationCode);
boolean isEmptyData = Objects.isNull(regularTrainLineRepository) || regularTrainLineRepository.getDataMap().isEmpty();
BusinessExceptionAssertEnum.DATA_ERROR.assertNotTrue(isEmptyData, String.format("当前生效区没有数据,无法更新"));
CtcEffectRepository.RegularTrainLineRepository updateRepository = simulation.getCtcRepository().getCtcEffectRepository().getUpdateReguarTrainLineMap().get(stationCode);
if(Objects.isNull(updateRepository)){
updateRepository = new CtcEffectRepository.RegularTrainLineRepository();
simulation.getCtcRepository().getCtcEffectRepository().getUpdateReguarTrainLineMap().put(stationCode,updateRepository);
}
if(updateRepository.version() != regularTrainLineRepository.version()){
updateRepository.resetVersion(regularTrainLineRepository.version());
for (RegularTrainLine val : regularTrainLineRepository.getDataMap().values()) {
updateRepository.save(val);
}
}else{
BusinessExceptionAssertEnum.DATA_ERROR.assertNotTrue(true, String.format("当前生效区与更新区的版本一致,无法更新"));
}
}
/**
* 加载更新区固定列车经路的数据
* @param simulation
* @param stationCode
* @return
*/
public FZkVO<List<RegularTrainLineVO>> loadUpdateRegularTrainLineList(Simulation simulation, String stationCode){
BusinessExceptionAssertEnum.SYSTEM_EXCEPTION.assertNotTrue(Objects.isNull(stationCode), String.format("车站号不能为空"));
CtcEffectRepository repository = simulation.getCtcRepository().getCtcEffectRepository();
CtcEffectRepository.RegularTrainLineRepository tLRepository = repository.getUpdateReguarTrainLineMap().get(stationCode);
List<RegularTrainLineVO> list = this.loadRegularTrainLineData(tLRepository);
return FZkVO.of(CollectionUtils.isEmpty(list)?0:tLRepository.version(),list);
}
/**
* 加载更新区的固定列车径路数据到计划中
* @param simulation
* @param stationCode
*/
public void loadRegularTrainLineToPlan(Simulation simulation, String stationCode){
BusinessExceptionAssertEnum.SYSTEM_EXCEPTION.assertNotTrue(Objects.isNull(stationCode), String.format("车站号不能为空"));
CtcEffectRepository repository = simulation.getCtcRepository().getCtcEffectRepository();
CtcEffectRepository.RegularTrainLineRepository tLRepository = repository.getUpdateReguarTrainLineMap().get(stationCode);
boolean isEmptyData = Objects.isNull(tLRepository) || tLRepository.getDataMap().isEmpty();
BusinessExceptionAssertEnum.SYSTEM_EXCEPTION.assertNotTrue(isEmptyData, String.format("当前更新区没有数据,无法加载"));
for (RegularTrainLine val : tLRepository.getDataMap().values()) {
CtcRunPlanParam param = new CtcRunPlanParam(val);
try{
ctcStationRunPlanLogService.saveInfo(simulation,stationCode,param,1);
}catch (BaseException e){
if(e.getCode() == BusinessExceptionAssertEnum.REPEAT_RUN_PLAN_FROM_CTC_UPDATE_DATA.getCode()){
log.error("车站:[{}],入口车次:[{}],出口车次:[{}],固定径路code:[{}] 发布计划发现重复的车次",stationCode,val.getArriveTipNum(),val.getLeaveTipNum(),val.getCode());
}else{
log.error("车站:[{}],入口车次:[{}],出口车次:[{}],固定径路code:[{}] 发布计划发现重复的车次失败 msg:{} ",stationCode,val.getArriveTipNum(),val.getLeaveTipNum(),val.getCode(),e.getVoMessage(),e);
}
}
}
}
}

View File

@ -446,7 +446,7 @@ public class CtcStationRunPlanLogService {
long time = simulation.getCtcRepository().getAllRunPlanList().stream()
.filter(r -> tripNumber.equals(r.getTripNumber()) && stationCode.equals(r.getStation().getCode()))
.count();
BusinessExceptionAssertEnum.DATA_ERROR.assertNotTrue(time > 0, "本站存在相同车次运行记录");
BusinessExceptionAssertEnum.REPEAT_RUN_PLAN_FROM_CTC_UPDATE_DATA.assertNotTrue(time > 0, "本站存在相同车次运行记录");
runPlanParam.generateGroupNumber(time + 1);
runPlanParam.generateRunPlanCode();
// 设置默认的实际时间

View File

@ -49,10 +49,14 @@ public interface GroupSimulationService {
*/
String simulation(Long mapId, String prodCode, LoginUserInfoVO loginUserInfoVO);
/**实训仿真*/
/**
* 实训仿真
*/
String trainingSimulation(Long trainingId, LoginUserInfoVO loginUserInfoVO);
/**考试仿真*/
/**
* 考试仿真
*/
String examSimulation(Long examId, LoginUserInfoVO loginUserInfoVO);
/**
@ -185,10 +189,14 @@ public interface GroupSimulationService {
*/
PlanTripNumberVO planTripInfoByServiceAndTripNumber(String group, String serviceNumber, String tripNumber);
/**故障模式设置*/
/**
* 故障模式设置
*/
Integer setFaultMode(String group, FaultRuleVO ruleVO);
/**获取已设置且自动故障*/
/**
* 获取已设置且自动故障
*/
Set<FaultRuleVO> getTriggerAutoFaults(String group);
/**
@ -255,6 +263,7 @@ public interface GroupSimulationService {
/**
* 获取所有目的地码
*
* @return
*/
List<DestinationCodeVO> getAllDestinationCode(String group);
@ -276,6 +285,7 @@ public interface GroupSimulationService {
/**
* 获取仿真日志
*
* @return
*/
PageVO<SimulationLog> getLog(String group, SimulationLogPagedQueryVO queryVO);

View File

@ -27,6 +27,7 @@ import club.joylink.rtss.simulation.cbtc.command.CommandExecuteService;
import club.joylink.rtss.simulation.cbtc.command.CommandInitiateVO;
import club.joylink.rtss.simulation.cbtc.communication.vo.fault.DeviceFaultInfo;
import club.joylink.rtss.simulation.cbtc.constant.SimulationConstants;
import club.joylink.rtss.simulation.cbtc.conversation.ConversationManagerService;
import club.joylink.rtss.simulation.cbtc.data.SimulationDataRepository;
import club.joylink.rtss.simulation.cbtc.data.map.DestinationCodeDefinition;
import club.joylink.rtss.simulation.cbtc.data.map.MapElement;
@ -148,6 +149,8 @@ public class GroupSimulationServiceImpl implements GroupSimulationService {
private CommandExecuteService commandExecuteService;
@Autowired
private QRCodeManager qrCodeManager;
@Autowired
private ConversationManagerService conversationManagerService;
// /**
// * 创建仿真并进行缓存
// *

View File

@ -27,6 +27,7 @@ import club.joylink.rtss.simulation.cbtc.exception.SimulationExceptionType;
import club.joylink.rtss.simulation.cbtc.member.SimulationMember;
import club.joylink.rtss.simulation.cbtc.member.SimulationUser;
import club.joylink.rtss.simulation.cbtc.script.ScriptBO;
import club.joylink.rtss.simulation.cbtc.training2.Training2;
import club.joylink.rtss.simulation.vo.SimulationInfoVO;
import club.joylink.rtss.vo.AccountVO;
import club.joylink.rtss.vo.client.fault.FaultRuleVO;
@ -87,6 +88,11 @@ public class Simulation extends club.joylink.rtss.simulation.Simulation<Simulati
*/
private ScriptBO script;
/**
* 实训信息
*/
private Training2 training2;
// /**
// * 仿真成员map
// * key-仿真成员id
@ -585,6 +591,9 @@ public class Simulation extends club.joylink.rtss.simulation.Simulation<Simulati
simulationConversationMap.clear();
}
this.logs = null;
if (this.training2 != null) {
training2.reset();
}
}
@Override

View File

@ -1672,7 +1672,8 @@ public class InterlockBuilder2 {
model = new StationDirection(stationDirection);
} else {
// TODO: 待数据统一之后下方构建代码可删除 20220714
model = new StationDirection(stationDirection.getCode(), stationDirection.getName(), stationDirection.getLabelEnum());
// model = new StationDirection(stationDirection.getCode(), stationDirection.getName(), stationDirection.getLabelEnum());
model = new StationDirection(stationDirection.getCode(), stationDirection.getName(), stationDirection.getLabelEnum(),stationDirection.getIoDirection());
}
// 注入信号灯数据
if (!StringUtils.isEmpty(stationDirection.getSignalCode())) {
@ -1700,6 +1701,12 @@ public class InterlockBuilder2 {
}
Station station = (Station) elementMap.get(stationDirection.getStationCode());
model.setStation(station);
if(Objects.nonNull(stationDirection.getRelativeStationCode())){
MapElement relativeStation = elementMap.get(stationDirection.getRelativeStationCode());
if(Objects.nonNull(relativeStation)){
model.setRelativeStation((Station) relativeStation);
}
}
station.getStationDirectionMap().put(model.getLabelEnum(), model);
elementMap.put(model.getCode(), model);
}

View File

@ -1116,6 +1116,7 @@ public class MapDeviceBuilder {
section.setVirtualAxleCounter(axleCounter);
deviceMap.put(axleCounter.getCode(), axleCounter);
}
section.setHasStopCountDown(sectionVO.isHasStopCD());
}
}

View File

@ -1,9 +1,8 @@
package club.joylink.rtss.simulation.cbtc.build;
import club.joylink.rtss.entity.Ibp;
import club.joylink.rtss.simulation.cbtc.CTC.data.CtcEffectRepository;
import club.joylink.rtss.simulation.cbtc.CTC.data.CtcStationRunPlanLog;
import club.joylink.rtss.simulation.cbtc.CTC.data.CtcZoneRepository;
import club.joylink.rtss.simulation.cbtc.CI.data.StationDirection;
import club.joylink.rtss.simulation.cbtc.CTC.data.*;
import club.joylink.rtss.simulation.cbtc.Simulation;
import club.joylink.rtss.simulation.cbtc.data.CalculateService;
import club.joylink.rtss.simulation.cbtc.data.SimulationDataRepository;
@ -330,10 +329,12 @@ public class SimulationBuilder {
*/
public static void buildCtcStationRunPlanLog(Simulation simulation) {
List<Station> stationList = simulation.getRepository().getStationList();
// 调度台
CtcZoneRepository ctcZoneRepository = simulation.getCtcRepository().getCtcZoneRepository();
CtcRepository ctcRepository = simulation.getCtcRepository();
// 生效区
CtcEffectRepository ctcEffectRepository = simulation.getCtcRepository().getCtcEffectRepository();
CtcEffectRepository ctcEffectRepository = ctcRepository.getCtcEffectRepository();
ctcEffectRepository.getStationRunPlanMap().forEach((k, v) -> {
v.getDataMap().forEach((c, r) -> {
// 调度台放入
@ -344,6 +345,38 @@ public class SimulationBuilder {
simulation.getCtcRepository().addRunPlanToSimulationMap(runPlanLog);
});
});
//加载车站股道到编辑区
Map<String, CtcEffectRepository.StationTrackSectionRepository> stationTrackRepositoryMap = ctcRepository.getCtcManageRepository().getTrackSectionRepository();
Map<String, CtcEffectRepository.StationDoorRepository> doorRepository = ctcRepository.getCtcManageRepository().getDoorRepository();
for (Station station : stationList) {
String stationCode = station.getCode();
CtcEffectRepository.StationTrackSectionRepository rep = stationTrackRepositoryMap.get(stationCode);
CtcEffectRepository.StationDoorRepository doorRep = doorRepository.get(stationCode);
if(rep == null){
rep = new CtcEffectRepository.StationTrackSectionRepository();
stationTrackRepositoryMap.put(stationCode,rep);
}
if(doorRep == null){
doorRep = new CtcEffectRepository.StationDoorRepository();
doorRepository.put(stationCode,doorRep);
}
for (StationDirection sd : station.getStationDirectionMap().values()) {
// StationIOGate ioGate = new StationIOGate();
// ioGate.setCode(sd.getCode());
// ioGate.setIoName(sd.getName());
// ioGate.setDirection(sd.getLabelEnum());
doorRep.save(sd.clone());
}
for (Stand stand : station.getAllStandList()) {
TrackSection ts = new TrackSection(stand.getSection());
rep.save(ts);
}
}
}
public static List<String> checkRunPlanAndBuildLostRoutePaths(Map<String, List<TripPlan>> serverTripMap,

View File

@ -234,7 +234,7 @@ public class Joylink3DMessageService {
// vrSwitchList.forEach(vrSwitch -> {
// boolean normal;
// if (vrSwitch.isTurning()) {
// normal = vrSwitch.getCommand().equals(VirtualRealitySwitch.Operation.NP);
// normal = vrSwitch.getCommand().equals(VirtualRealitySwitch.Operation2.NP);
// } else if (vrSwitch.isPosN()) {
// normal = true;
// } else {
@ -247,7 +247,7 @@ public class Joylink3DMessageService {
// vrPsdList.forEach(vrPsd -> {
// boolean open;
// if (vrPsd.isTurning()) {
// open = vrPsd.getCommand().equals(VirtualRealityScreenDoor.Operation.K);
// open = vrPsd.getCommand().equals(VirtualRealityScreenDoor.Operation2.K);
// } else if (vrPsd.isClose()) {
// open = false;
// } else {

View File

@ -107,7 +107,7 @@ public class CompetitionAndScriptManager {
}
// //本地测试用
// if (Objects.equals(unfinishedAction.getType(), ScriptActionBO.ActionType.Conversation)
// || Objects.equals(unfinishedAction.getType(), ScriptActionBO.ActionType.Operation)) {
// || Objects.equals(unfinishedAction.getType(), ScriptActionBO.ActionType.Operation2)) {
// scriptExecuteService.executeAction(simulation, unfinishedAction, correctSystemTime);
// }
return;

View File

@ -4,6 +4,7 @@ import club.joylink.rtss.services.voice.IVoiceService;
import club.joylink.rtss.simulation.cbtc.GroupSimulationCache;
import club.joylink.rtss.simulation.cbtc.Simulation;
import club.joylink.rtss.simulation.cbtc.competition.ScriptExecuteService;
import club.joylink.rtss.simulation.cbtc.data.vo.ConversationMessageVO;
import club.joylink.rtss.simulation.cbtc.data.vo.ConversationVO;
import club.joylink.rtss.simulation.cbtc.event.*;
import club.joylink.rtss.simulation.cbtc.exception.SimulationException;
@ -11,13 +12,18 @@ import club.joylink.rtss.simulation.cbtc.exception.SimulationExceptionType;
import club.joylink.rtss.simulation.cbtc.member.SimulationMember;
import club.joylink.rtss.simulation.cbtc.member.SimulationUser;
import club.joylink.rtss.vo.AccountVO;
import club.joylink.rtss.vo.client.SocketMessageVO;
import club.joylink.rtss.vo.client.VoiceRecognitionResult;
import club.joylink.rtss.vo.client.WebSocketMessageType;
import club.joylink.rtss.vo.client.factory.SocketMessageFactory;
import club.joylink.rtss.websocket.StompMessageService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;
import java.time.LocalDateTime;
@ -44,15 +50,18 @@ public class ConversationManagerService {
@Autowired
private ScriptExecuteService scriptExecuteService;
@Autowired
private StompMessageService stompMessageService;
public ConversationVO getConversationById(String group, String conversationId) {
Simulation simulation = this.groupSimulationCache.getSimulationByGroup(group);
Simulation simulation = groupSimulationCache.getSimulationByGroup(group);
Conversation conversation = simulation.getSimulationConversationById(conversationId);
ConversationVO conversationVO = new ConversationVO(conversation);
return conversationVO;
}
public List<ConversationVO> getAllConversations(String group) {
Simulation simulation = this.groupSimulationCache.getSimulationByGroup(group);
Simulation simulation = groupSimulationCache.getSimulationByGroup(group);
List<Conversation> allConversations = simulation.queryAllConversations();
return ConversationVO.convert2VOList(allConversations);
}
@ -64,13 +73,13 @@ public class ConversationManagerService {
if (CollectionUtils.isEmpty(memberIdList)) {
throw new SimulationException(SimulationExceptionType.Invalid_Operation, "一个人不能开启会话");
}
Simulation simulation = this.groupSimulationCache.getSimulationByGroup(group);
Simulation simulation = groupSimulationCache.getSimulationByGroup(group);
SimulationUser simulationUser = simulation.getSimulationUserById(accountVO.getId());
SimulationMember creator = simulationUser.getPlayedMember();
if (Objects.isNull(creator)) {
throw new SimulationException(SimulationExceptionType.Operation_Handle_FAIL);
}
return this.createConversation(simulation, creator, memberIdList);
return createConversation(simulation, creator, memberIdList);
}
/**
@ -82,7 +91,7 @@ public class ConversationManagerService {
List<SimulationMember> invitedList = new ArrayList<>();
for (String memberId : memberIdList) {
SimulationMember member = simulation.getSimulationMemberById(memberId);
if (this.isMemberConnect2Conversation(simulation, member)) {
if (isMemberConnect2Conversation(simulation, member)) {
throw new SimulationException(SimulationExceptionType.Simulation_Conversation_Member_Busy,
memberId);
}
@ -105,19 +114,19 @@ public class ConversationManagerService {
simulation.addConversation(conversation);
// 会话创建成功事件
SimulationConversationCreateEvent createEvent = new SimulationConversationCreateEvent(this, simulation, conversation);
this.applicationEventPublisher.publishEvent(createEvent);
applicationEventPublisher.publishEvent(createEvent);
return new ConversationVO(conversation);
}
/*---------------------------------- (创建会话)需要被邀请者同意 ----------------------------------*/
public ConversationVO createConversation(String group, AccountVO user, CommunicationObject object, List<String> memberIds) {
Simulation simulation = this.groupSimulationCache.getSimulationByGroup(group);
Simulation simulation = groupSimulationCache.getSimulationByGroup(group);
SimulationUser simulationUser = simulation.getSimulationUserById(user.getId());
SimulationMember creator = simulationUser.getPlayedMember();
if (Objects.isNull(creator)) {
throw new SimulationException(SimulationExceptionType.Operation_Handle_FAIL);
}
return this.createConversation(simulation, creator, object, memberIds);
return createConversation(simulation, creator, object, memberIds);
}
public ConversationVO createConversation(Simulation simulation, SimulationMember creator, CommunicationObject object, List<String> memberIds) {
@ -178,7 +187,7 @@ public class ConversationManagerService {
simulation.addConversation(conversation);
// 会话创建成功事件
SimulationConversationCreateEvent createEvent = new SimulationConversationCreateEvent(this, simulation, conversation);
this.applicationEventPublisher.publishEvent(createEvent);
applicationEventPublisher.publishEvent(createEvent);
// 用户发送会话邀请事件机器人直接连接
List<ConversationMember> memberList = conversation.getMemberList();
for (ConversationMember conversationMember : memberList) {
@ -189,9 +198,9 @@ public class ConversationManagerService {
if (!member.isRobot()) {
log.info(String.format("仿真[%s]会话[%s]邀请成员[%s]事件发布",
simulation.getId(), conversation.getId(), member.toString()));
this.applicationEventPublisher.publishEvent(new SimulationConversationInviteEvent(this, simulation, conversation, member));
applicationEventPublisher.publishEvent(new SimulationConversationInviteEvent(this, simulation, conversation, member));
} else {
this.connect2Conversation(simulation, conversation, member);
connect2Conversation(simulation, conversation, member);
}
}
return new ConversationVO(conversation);
@ -209,10 +218,10 @@ public class ConversationManagerService {
}
public ConversationVO connect2Conversation(String group, AccountVO accountVO, String conversationId) {
Simulation simulation = this.groupSimulationCache.getSimulationByGroup(group);
Simulation simulation = groupSimulationCache.getSimulationByGroup(group);
Conversation conversation = simulation.getSimulationConversationById(conversationId);
SimulationMember member = simulation.getSimulationMemberByUserId(accountVO.getId());
return this.connect2Conversation(simulation, conversation, member);
return connect2Conversation(simulation, conversation, member);
}
public ConversationVO connect2Conversation(Simulation simulation, Conversation conversation, SimulationMember member) {
@ -224,7 +233,7 @@ public class ConversationManagerService {
// 发布用户连接会话事件
SimulationConversationMemberConnectEvent connectEvent =
new SimulationConversationMemberConnectEvent(this, simulation, conversation, member);
this.applicationEventPublisher.publishEvent(connectEvent);
applicationEventPublisher.publishEvent(connectEvent);
return new ConversationVO(conversation);
}
@ -232,10 +241,10 @@ public class ConversationManagerService {
* 结束会话
*/
public void exitConversation(String group, String conversationId, AccountVO accountVO) {
Simulation simulation = this.groupSimulationCache.getSimulationByGroup(group);
Simulation simulation = groupSimulationCache.getSimulationByGroup(group);
Conversation conversation = simulation.getSimulationConversationById(conversationId);
SimulationMember member = simulation.getSimulationMemberByUserId(accountVO.getId());
this.exitConversation(simulation, conversation, member);
exitConversation(simulation, conversation, member);
}
public void exitConversation(Simulation simulation, Conversation conversation, SimulationMember member) {
@ -245,20 +254,20 @@ public class ConversationManagerService {
}
// 发布会话成员退出事件
SimulationConversationExitEvent overEvent = new SimulationConversationExitEvent(this, simulation, conversation, member);
this.applicationEventPublisher.publishEvent(overEvent);
applicationEventPublisher.publishEvent(overEvent);
}
/**
* 仿真用户会话chat
*/
public void chat(String group, String conversationId, AccountVO accountVO, MultipartFile file) {
Simulation simulation = this.groupSimulationCache.getSimulationByGroup(group);
Simulation simulation = groupSimulationCache.getSimulationByGroup(group);
Conversation conversation = simulation.getSimulationConversationById(conversationId);
SimulationMember member = simulation.getSimulationMemberByUserId(accountVO.getId());
VoiceRecognitionResult recognitionResult = this.iVoiceService.voiceRecognition(file, "");
VoiceRecognitionResult recognitionResult = iVoiceService.voiceRecognition(file, "");
String upperCaseResult = recognitionResult.getResult().toUpperCase();
String handledContent = this.simulationVoiceHandler.handle(upperCaseResult);
this.chat(simulation, conversation, member, handledContent, recognitionResult.getFilePath());
String handledContent = simulationVoiceHandler.handle(upperCaseResult);
chat(simulation, conversation, member, handledContent, recognitionResult.getFilePath());
}
public String chat(Simulation simulation, Conversation conversation,
@ -269,7 +278,7 @@ public class ConversationManagerService {
conversation.addMessage(conversationMessage);
// scriptExecuteService.replaceContent4ConversationAction(simulation, conversation, conversationMessage);
SimulationConversationChatEvent chatEvent = new SimulationConversationChatEvent(this, simulation, conversation, conversationMessage);
this.applicationEventPublisher.publishEvent(chatEvent);
applicationEventPublisher.publishEvent(chatEvent);
return id;
}
@ -293,4 +302,118 @@ public class ConversationManagerService {
String path = iVoiceService.synthesis(content, "0");
chat(simulation, conversation, member, content, path);
}
//----------------------------------- 电话会话操作 -------------------------------------
/**
* 打电话
*/
public ConversationVO phoneStart(Simulation simulation, SimulationMember member, CommunicationObject object, List<String> memberIds) {
Set<SimulationMember> members = new LinkedHashSet<>();
if (!CollectionUtils.isEmpty(memberIds)) {
members.addAll(memberIds.stream().map(simulation::getSimulationMemberById).filter(simulationMember -> {
if (Objects.nonNull(simulationMember.getUserId())) {
SimulationUser simulationUser = simulation.querySimulationUserById(simulationMember.getUserId());
return simulationUser.isOnline();
}
return true;
}).collect(Collectors.toList()));
}
if (object != null) {
switch (object) {
case ALL_TRAIN:
members.addAll(simulation.getMemberListByType(SimulationMember.Type.DRIVER));
break;
case ALL_STATION:
members.addAll(simulation.getMemberListByType(SimulationMember.Type.STATION_SUPERVISOR));
break;
default:
throw new SimulationException(SimulationExceptionType.System_Fault, String.format("未知的通讯对象[%s]", object));
}
}
if (CollectionUtils.isEmpty(members)) {
throw new SimulationException(SimulationExceptionType.Illegal_Argument, "会话成员列表为空/成员都不在线");
}
if (members.stream().anyMatch(simulation::isInValidConversation)) {
throw new SimulationException(SimulationExceptionType.System_Fault, "有被邀请的成员正在进行其它通话");
}
Conversation conversation = new Conversation(simulation.getIdGenerator().nextConversationId(),
member, simulation.getSystemTime(), new ArrayList<>(members), object);
simulation.addConversation(conversation);
// 会话创建成功事件
SimulationConversationCreateEvent createEvent = new SimulationConversationCreateEvent(this, simulation, conversation);
applicationEventPublisher.publishEvent(createEvent);
return new ConversationVO(conversation);
}
/**
* 接听电话
*/
public ConversationVO phoneConnect(Simulation simulation, SimulationMember member, String conversationId) {
Conversation conversation = simulation.getSimulationConversationById(conversationId);
return connect2Conversation(simulation, conversation, member);
}
/**
* 接听电话,聊天输入
*/
public void phoneChat(Simulation simulation, SimulationMember member, String id, String content, String audioPath) {
Conversation conversation = simulation.getSimulationConversationById(id);
if (conversation.isOver()) {
throw new SimulationException(SimulationExceptionType.System_Fault, String.format("会话[%s]已经结束", id));
}
if (!conversation.contains(member)) {
throw new SimulationException(SimulationExceptionType.System_Fault, String.format("会话[%s]不包含该成员[%s]", id, member.getId()));
}
String path = audioPath;
if (StringUtils.isEmpty(audioPath)) {
path = iVoiceService.synthesis(content, "0");
}
chat(simulation, conversation, member, content, path);
}
/**
* 电话挂电话
*/
public void phoneExit(Simulation simulation, SimulationMember member, String id) {
Conversation conversation = simulation.getSimulationConversationById(id);
if (conversation.isOver()) {
throw new SimulationException(SimulationExceptionType.System_Fault, String.format("会话[%s]已经结束", id));
}
if (!conversation.contains(member)) {
throw new SimulationException(SimulationExceptionType.System_Fault, String.format("会话[%s]不包含该成员[%s]", id, member.getId()));
}
exitConversation(simulation, conversation, member);
}
//----------------------------------- 消息会话 -------------------------------------
/**
* 文件BASE64编码
*/
public ConversationMessageVO conversationChat(Simulation simulation, SimulationMember member, String fileBase64Str) {
VoiceRecognitionResult recognitionResult = iVoiceService.voiceRecognition(fileBase64Str);
String upperCaseResult = recognitionResult.getResult().toUpperCase();
String handledContent = simulationVoiceHandler.handle(upperCaseResult);
ConversationMessage conversationMessage = new ConversationMessage(simulation.getIdGenerator().nextConversationMessageId(),
member, simulation.getCorrectSystemTime(), handledContent, recognitionResult.getFilePath());
return sendChatMessage(simulation.getId(), simulation.getSimulationUserIds(), conversationMessage);
}
/**
* 会话操作
*/
public ConversationMessageVO conversationChat(Simulation simulation, SimulationMember member, String content, String audioPath) {
ConversationMessage conversationMessage = new ConversationMessage(simulation.getIdGenerator().nextConversationMessageId(),
member, simulation.getCorrectSystemTime(), content, audioPath);
return sendChatMessage(simulation.getId(), simulation.getSimulationUserIds(), conversationMessage);
}
private ConversationMessageVO sendChatMessage(String simulationId, Set<String> userIds, ConversationMessage conversationMessage) {
ConversationMessageVO conversationMessageVO = new ConversationMessageVO(conversationMessage);
SocketMessageVO<ConversationMessageVO> chatMessage =
SocketMessageFactory.build(WebSocketMessageType.Simulation_Conversation_Operation, simulationId, conversationMessageVO);
stompMessageService.sendToUser(userIds, chatMessage);
return conversationMessageVO;
}
}

View File

@ -2,6 +2,7 @@ package club.joylink.rtss.simulation.cbtc.conversation;
import club.joylink.rtss.simulation.cbtc.member.SimulationMember;
import lombok.Getter;
import org.springframework.util.StringUtils;
import java.time.LocalDateTime;
@ -18,6 +19,8 @@ public class ConversationMessage {
private String audioPath;
private MessageType type;
public void setContent(String content) {
this.content = content;
}
@ -28,5 +31,10 @@ public class ConversationMessage {
this.time = systemTime;
this.content = content;
this.audioPath = filePath;
this.type = StringUtils.isEmpty(filePath) ? MessageType.Text : MessageType.Voice;
}
public enum MessageType {
Voice, Text;
}
}

View File

@ -0,0 +1,91 @@
package club.joylink.rtss.simulation.cbtc.conversation;
import club.joylink.rtss.simulation.cbtc.ATS.operation.Operation;
import club.joylink.rtss.simulation.cbtc.ATS.operation.annotation.OperateHandler;
import club.joylink.rtss.simulation.cbtc.ATS.operation.annotation.OperateHandlerMapping;
import club.joylink.rtss.simulation.cbtc.Simulation;
import club.joylink.rtss.simulation.cbtc.data.vo.ConversationMessageVO;
import club.joylink.rtss.simulation.cbtc.data.vo.ConversationVO;
import club.joylink.rtss.simulation.cbtc.member.SimulationMember;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.List;
/**
* 会话操作
*/
@OperateHandler
@Slf4j
public class ConversationOperateHandler {
@Autowired
private ConversationManagerService conversationManagerService;
//-------------------------------- 电话消息操作 ---------------------------------------
/**
* 电话创建电话消息
*/
@OperateHandlerMapping(type = Operation.Type.Conversation_Phone_Start)
public ConversationVO phoneStart(Simulation simulation, SimulationMember member, CommunicationObject object, List<String> memberIds) {
return conversationManagerService.phoneStart(simulation, member, object, memberIds);
}
/**
* 电话接听电话
*/
@OperateHandlerMapping(type = Operation.Type.Conversation_Phone_Connect)
public ConversationVO phoneConnect(Simulation simulation, SimulationMember member, String id) {
return conversationManagerService.phoneConnect(simulation, member, id);
}
/**
* 电话语音消息
*/
@OperateHandlerMapping(type = Operation.Type.Conversation_Phone_Audio)
public void phoneAudio(Simulation simulation, SimulationMember member, String id, String audioPath, String content) {
conversationManagerService.phoneChat(simulation, member, id, content, audioPath);
}
/**
* 电话文字消息
*/
@OperateHandlerMapping(type = Operation.Type.Conversation_Phone_Text)
public void phonePhoneText(Simulation simulation, SimulationMember member, String id, String content) {
conversationManagerService.phoneChat(simulation, member, id, content, null);
}
/**
* 电话挂电话
*/
@OperateHandlerMapping(type = Operation.Type.Conversation_Phone_Exit)
public void phoneExit(Simulation simulation, SimulationMember member, String id) {
conversationManagerService.phoneExit(simulation, member, id);
}
//-------------------------------- 消息操作 ---------------------------------------
/**
* 发送会话消息语音输入
*/
@OperateHandlerMapping(type = Operation.Type.Conversation_Chat_Audio)
public ConversationMessageVO audioChat(Simulation simulation, SimulationMember member, String audioPath, String content) {
return conversationManagerService.conversationChat(simulation, member, content, audioPath);
}
/**
* 发送会话消息文字输入
*/
@OperateHandlerMapping(type = Operation.Type.Conversation_Chat_Text)
public ConversationMessageVO textChat(Simulation simulation, SimulationMember member, String content) {
return conversationManagerService.conversationChat(simulation, member, content, null);
}
/**
* 发送会话消息语音输入Base64格式
*/
@OperateHandlerMapping(type = Operation.Type.Conversation_Chat_Audio_Base64)
public ConversationMessageVO audioBase64(Simulation simulation, SimulationMember member, String fileBase64Str) {
return conversationManagerService.conversationChat(simulation, member, fileBase64Str);
}
}

View File

@ -1248,4 +1248,10 @@ public class SimulationDataRepository {
}
return stream.collect(Collectors.toList());
}
public List<Section> getHasStopCountDownSections() {
return getListByType(MapElement.DeviceType.SECTION, Section.class).stream()
.filter(Section::isHasStopCountDown)
.collect(Collectors.toList());
}
}

View File

@ -10,6 +10,21 @@ public abstract class DelayUnlockDevice extends MayOutOfOrderDevice {
super(code, name, deviceType);
}
public void delayUnlockStart(Route route,MapConfig mc) {
// route.getType() == Type
int baseDelayTime = route.getDelayReleaseTime();
if(mc.isRailway()){
switch (route.getType()){
case DEPARTURE:
case RECEIVING:
baseDelayTime = 180;
break;
case SHUNTING:
baseDelayTime = 30;
}
}
this.remain = baseDelayTime * 1000;
}
public void delayUnlockStart(Route route) {
this.remain = route.getDelayReleaseTime() * 1000;
}

View File

@ -8,6 +8,8 @@ import club.joylink.rtss.simulation.cbtc.data.support.SectionPosition;
import club.joylink.rtss.simulation.cbtc.data.vr.VirtualRealitySectionAxleCounter;
import club.joylink.rtss.simulation.cbtc.exception.SimulationException;
import club.joylink.rtss.simulation.cbtc.exception.SimulationExceptionType;
import club.joylink.rtss.simulation.cbtc.training2.ecm.anno.ExpConditionMaterialAnno;
import club.joylink.rtss.simulation.cbtc.training2.ecm.anno.ExpConditionMaterialSrcAnno;
import lombok.Getter;
import lombok.Setter;
import org.springframework.util.CollectionUtils;
@ -19,6 +21,7 @@ import java.util.*;
*/
@Getter
@Setter
@ExpConditionMaterialSrcAnno(name = "Section")
public class Section extends DelayUnlockDevice {
public Section(String code, String name) {
@ -164,16 +167,23 @@ public class Section extends DelayUnlockDevice {
*/
private Set<ZC> zcs = new HashSet<>();
/**
* 有停稳计时
*/
private boolean hasStopCountDown;
// ------------------状态属性---------------------
/**
* 是否封锁封锁后包含区段的进路不能排列
*/
@ExpConditionMaterialAnno(name = "blockade",type = "boolean",desc = "是否封锁(封锁后,包含区段的进路不能排列)")
private boolean blockade;
/**
* 是否进路锁闭
*/
@ExpConditionMaterialAnno(name = "routeLock",type = "boolean",desc = "是否进路锁闭")
private boolean routeLock;
/**
@ -189,36 +199,43 @@ public class Section extends DelayUnlockDevice {
/**
* 进路延续保护锁闭
*/
@ExpConditionMaterialAnno(name = "overlapLock",type = "boolean",desc = "进路延续保护锁闭")
private boolean overlapLock;
/**
* 通信车占用
*/
@ExpConditionMaterialAnno(name = "ctOccupied",type = "boolean",desc = "通信车占用")
private boolean ctOccupied;
/**
* 计轴占用-非通信车占用
*/
@ExpConditionMaterialAnno(name = "nctOccupied",type = "boolean",desc = "计轴占用-非通信车占用")
private boolean nctOccupied;
/**
* 占用列车方向
*/
@ExpConditionMaterialAnno(name = "trainRight",type = "boolean",desc = "占用列车方向")
private boolean trainRight;
/**
* 是否切除
*/
@ExpConditionMaterialAnno(name = "cutOff",type = "boolean",desc = "是否切除")
private boolean cutOff;
/**
* 计轴是否被报失效(ARB故障)
*/
@ExpConditionMaterialAnno(name = "invalid",type = "boolean",desc = "计轴是否被报失效(ARB故障)")
private boolean invalid;
/**
* 故障锁闭
*/
@ExpConditionMaterialAnno(name = "faultLock",type = "boolean",desc = "故障锁闭")
private boolean faultLock;
/**
@ -261,6 +278,14 @@ public class Section extends DelayUnlockDevice {
*/
private List<ShuntingType> shuntingTypeList;
/**
* 停稳倒计时
* 0 表示初始状态
* -1 表示准备开始计时
* 非负数表示当前计时
*/
private int stopCountDown;
@Override
public void reset() {
super.reset();
@ -280,13 +305,31 @@ public class Section extends DelayUnlockDevice {
this.closeInit = false;
this.openInit = false;
this.closed = false;
this.badShunt = false;
this.shuntingTypeList = new ArrayList<>();
this.stopCountDown = 0;
}
/**
* 开始停稳倒计时
*/
public void startStopCountDown() {
stopCountDown = 40 * 1000;
}
/**
* 准备开始停稳倒计时
*/
public void readyStartStopCountDown() {
stopCountDown = -1;
}
public int getStopCountDownInSeconds() {
return stopCountDown / 1000;
}
/**
* 区段是否被列车占用
*
* @return
*/
public boolean isOccupied() {
return this.nctOccupied || this.ctOccupied || this.isLogicOccupied();

View File

@ -4,6 +4,8 @@ import club.joylink.rtss.simulation.cbtc.constant.SignalAspect;
import club.joylink.rtss.simulation.cbtc.constant.SignalModel;
import club.joylink.rtss.simulation.cbtc.data.support.SectionPosition;
import club.joylink.rtss.simulation.cbtc.data.vr.VirtualRealitySignal;
import club.joylink.rtss.simulation.cbtc.training2.ecm.anno.ExpConditionMaterialAnno;
import club.joylink.rtss.simulation.cbtc.training2.ecm.anno.ExpConditionMaterialSrcAnno;
import lombok.Getter;
import lombok.Setter;
import org.springframework.util.CollectionUtils;
@ -20,6 +22,7 @@ import java.util.stream.Collectors;
*/
@Getter
@Setter
@ExpConditionMaterialSrcAnno(name = "Signal")
public class Signal extends DelayUnlockDevice {
public static int GUIDE_DELAY = 15 * 1000; //大铁首区段占用的引导进路的延时关闭时长
@ -111,7 +114,9 @@ public class Signal extends DelayUnlockDevice {
*/
private boolean ctc;
/** CTC级别是否办理延续保护 */
/**
* CTC级别是否办理延续保护
*/
private boolean ctcSetOverlap;
/**
@ -176,15 +181,18 @@ public class Signal extends DelayUnlockDevice {
/**
* 是否封锁
*/
@ExpConditionMaterialAnno(name = "blockade", type = "boolean", desc = "是否封锁")
private boolean blockade;
/**
* 是否钮封
* 是否钮封
*/
@ExpConditionMaterialAnno(name = "buttonBlockade", type = "boolean", desc = "是否钮封")
private boolean buttonBlockade;
/**
* 重复封锁*后期去掉*
*/
@ExpConditionMaterialAnno(name = "reblockade", type = "boolean", desc = "重复封锁")
private boolean reblockade;
/**
* 侧防锁闭侧防锁闭后不能排列此信号机为始端的任何进路
@ -199,14 +207,18 @@ public class Signal extends DelayUnlockDevice {
/**
* 当前信号显示
*/
@ExpConditionMaterialAnno(name = "aspect", type = "SignalAspect", desc = "信号显示")
private SignalAspect aspect;
/**
* 是否禁止联锁自动开信号
*/
@ExpConditionMaterialAnno(name = "forbidden", type = "boolean", desc = "是否禁止联锁自动开信号")
private boolean forbidden;
/**
* 引导信号开放剩余时间单位ms
*/
@ExpConditionMaterialAnno(name = "guideRemain", type = "int", desc = "引导信号开放剩余时间单位ms")
private int guideRemain;
/**
@ -222,9 +234,13 @@ public class Signal extends DelayUnlockDevice {
/**
* 是否接近锁闭
*/
@ExpConditionMaterialAnno(name = "approachLock", type = "boolean", desc = "是否接近锁闭")
private boolean approachLock;
/** 延续保护锁闭 */
/**
* 延续保护锁闭
*/
@ExpConditionMaterialAnno(name = "overlapLock", type = "boolean", desc = "延续保护锁闭")
private boolean overlapLock;
/**
@ -244,7 +260,7 @@ public class Signal extends DelayUnlockDevice {
this.lockedRoute = null;
this.level = LEVEL_Close;
this.blockade = false;
this.buttonBlockade=false;
this.buttonBlockade = false;
this.reblockade = false;
this.fpl = false;
this.logicLight = this.isCtc();
@ -267,6 +283,7 @@ public class Signal extends DelayUnlockDevice {
/**
* 切换为CBTC模式
*
* @return
*/
public boolean changeToCbtcMode() {
@ -287,6 +304,7 @@ public class Signal extends DelayUnlockDevice {
/**
* 切换为后备模式
*
* @return
*/
public boolean changeToBackupMode() {
@ -318,7 +336,7 @@ public class Signal extends DelayUnlockDevice {
public boolean isMainAspect() {
if (this.lockedRoute != null) {
return this.aspect.equals(this.lockedRoute.getAspect());
return this.aspect.equals(this.lockedRoute.getSettedAspect());
}
return false;
}
@ -566,6 +584,7 @@ public class Signal extends DelayUnlockDevice {
/**
* 引导信号控制级别
*
* @return
*/
public boolean isGuideLevel() {
@ -574,6 +593,7 @@ public class Signal extends DelayUnlockDevice {
/**
* ATP 移动闭塞信号控制级别
*
* @return
*/
public boolean isAtpLevel() {
@ -582,6 +602,7 @@ public class Signal extends DelayUnlockDevice {
/**
* 主信号控制级别
*
* @return
*/
public boolean isMainLevel() {
@ -736,9 +757,13 @@ public class Signal extends DelayUnlockDevice {
* 出段信号机
*/
OUTBOUND,
/** 接车信号机大铁X/S */
/**
* 接车信号机大铁X/S
*/
RECEIVING,
/** 发车信号机大铁XF/SF */
/**
* 发车信号机大铁XF/SF
*/
DEPARTURE,
}

View File

@ -5,6 +5,8 @@ import club.joylink.rtss.simulation.cbtc.data.vr.VirtualRealityPsl;
import club.joylink.rtss.simulation.cbtc.data.vr.VirtualRealityScreenDoor;
import club.joylink.rtss.simulation.cbtc.exception.SimulationException;
import club.joylink.rtss.simulation.cbtc.exception.SimulationExceptionType;
import club.joylink.rtss.simulation.cbtc.training2.ecm.anno.ExpConditionMaterialAnno;
import club.joylink.rtss.simulation.cbtc.training2.ecm.anno.ExpConditionMaterialSrcAnno;
import lombok.Getter;
import lombok.Setter;
import org.springframework.util.CollectionUtils;
@ -18,6 +20,7 @@ import java.util.concurrent.ConcurrentHashMap;
*/
@Getter
@Setter
@ExpConditionMaterialSrcAnno(name = "Stand")
public class Stand extends MayOutOfOrderDevice {
public Stand(String code, String name) {
@ -62,7 +65,9 @@ public class Stand extends MayOutOfOrderDevice {
private VirtualRealityPsl vrPsl;
/** 默认折返策略 */
/**
* 默认折返策略
*/
private TurnBackType defaultTypeStrategy;
// -------------------------------状态属性---------------------------------
@ -75,12 +80,14 @@ public class Stand extends MayOutOfOrderDevice {
/**
* 列车停站倒计时,单位ms
*/
@ExpConditionMaterialAnno(name = "remainTime", type = "int", desc = "列车停站倒计时,单位ms")
private int remainTime;
/*扣车相关*/
/**
* 车站是否扣车
*/
@ExpConditionMaterialAnno(name = "stationHoldTrain", type = "boolean", desc = "车站是否扣车")
private volatile boolean stationHoldTrain;
/**
@ -88,10 +95,14 @@ public class Stand extends MayOutOfOrderDevice {
*/
private volatile boolean centerHoldTrain;
/**系统扣车*/
/**
* 系统扣车
*/
private volatile boolean sysHoldTrain;
/** IBP盘扣车 */
/**
* IBP盘扣车
*/
private boolean ibpHoldTrain;
/**
@ -103,6 +114,7 @@ public class Stand extends MayOutOfOrderDevice {
/**
* 是否全部跳停
*/
@ExpConditionMaterialAnno(name = "allSkip", type = "boolean", desc = "是否全部跳停")
private volatile boolean allSkip;
/**
@ -113,6 +125,7 @@ public class Stand extends MayOutOfOrderDevice {
/**
* 跳停一直有效
*/
@ExpConditionMaterialAnno(name = "skipAlwaysValid", type = "boolean", desc = "跳停持续有效")
private boolean skipAlwaysValid;
/*运行等级(时间)相关*/
@ -121,7 +134,9 @@ public class Stand extends MayOutOfOrderDevice {
*/
private int runLevelTime;
/** 列车-停站时间map */
/**
* 列车-停站时间map
*/
private final Map<String, Integer> runTimeMap = new ConcurrentHashMap<>();
/**
@ -140,7 +155,9 @@ public class Stand extends MayOutOfOrderDevice {
*/
private int parkingTime;
/** 列车-停站时间map */
/**
* 列车-停站时间map
*/
private final Map<String, Integer> parkingTimeMap = new ConcurrentHashMap<>();
/**
@ -157,7 +174,9 @@ public class Stand extends MayOutOfOrderDevice {
private boolean closed;
/** 最后一辆列车的发车时间 */
/**
* 最后一辆列车的发车时间
*/
private LocalDateTime lastTrainDepartTime;
// ---------------------------- method -------------------------------------
@ -298,7 +317,7 @@ public class Stand extends MayOutOfOrderDevice {
public String debugStr() {
return String.format("%s-%s-%s(%s)", this.station.getName(),
this.isRight()?"右行":"左行", this.getName(), this.getCode());
this.isRight() ? "右行" : "左行", this.getName(), this.getCode());
}
public String showStr() {
@ -407,7 +426,9 @@ public class Stand extends MayOutOfOrderDevice {
}
},
/** 无关闭锁紧信号 */
/**
* 无关闭锁紧信号
*/
NO_CLOSE_AND_LOCK {
@Override
public boolean apply(MayOutOfOrderDevice device) {

View File

@ -10,6 +10,8 @@ import club.joylink.rtss.simulation.cbtc.data.vr.VirtualRealityIbp;
import club.joylink.rtss.simulation.cbtc.exception.SimulationException;
import club.joylink.rtss.simulation.cbtc.exception.SimulationExceptionType;
import club.joylink.rtss.simulation.cbtc.member.SimulationMember;
import club.joylink.rtss.simulation.cbtc.training2.ecm.anno.ExpConditionMaterialAnno;
import club.joylink.rtss.simulation.cbtc.training2.ecm.anno.ExpConditionMaterialSrcAnno;
import lombok.Getter;
import lombok.NonNull;
import lombok.Setter;
@ -22,6 +24,7 @@ import java.util.stream.Collectors;
@Getter
@Setter
@ExpConditionMaterialSrcAnno(name = "Station")
public class Station extends MayOutOfOrderDevice {
public Station(String code, String name) {
super(code, name, DeviceType.STATION);
@ -126,11 +129,13 @@ public class Station extends MayOutOfOrderDevice {
/**
* 是否引导总锁
*/
@ExpConditionMaterialAnno(name = "totalGuideLock", type = "boolean", desc = "是否引导总锁")
private boolean totalGuideLock;
/**
* 控制模式
*/
@ExpConditionMaterialAnno(name = "controlMode", type = "ControlMode", desc = "控制模式")
private ControlMode controlMode;
/**
@ -171,6 +176,7 @@ public class Station extends MayOutOfOrderDevice {
/**
* 是否紧急控制
*/
@ExpConditionMaterialAnno(name = "emergencyController", type = "boolean", desc = "是否紧急控制")
private boolean emergencyController;
/**
@ -188,8 +194,10 @@ public class Station extends MayOutOfOrderDevice {
*/
private Map<DirectionLabelEnum, StationDirection> stationDirectionMap;
@ExpConditionMaterialAnno(name = "sGuideMasterLock", type = "boolean", desc = "S引导总锁")
private boolean sGuideMasterLock;
@ExpConditionMaterialAnno(name = "xGuideMasterLock", type = "boolean", desc = "X引导总锁")
private boolean xGuideMasterLock;
/**
@ -197,8 +205,12 @@ public class Station extends MayOutOfOrderDevice {
*/
private boolean allowAutonomy;
@Override
/**
* 操作计数器
*/
private Map<String, Integer> counter;
@Override
public void reset() {
super.reset();
if (vrIbp != null) {
@ -223,6 +235,7 @@ public class Station extends MayOutOfOrderDevice {
preResetValidDuration = new AtomicInteger(0);
sGuideMasterLock = false;
xGuideMasterLock = false;
counter = null;
}
public List<Stand> getStandOf(boolean right) {
@ -459,6 +472,13 @@ public class Station extends MayOutOfOrderDevice {
return Fault.ATS_ROUTE_TRIGGER_FAULT.equals(getFault());
}
public void count(String countName) {
if (this.counter == null) {
this.counter = new HashMap<>();
}
this.counter.merge(countName, 1, Integer::sum);
}
public enum ControlMode {
/**
* 交出未被接收

View File

@ -2,6 +2,8 @@ package club.joylink.rtss.simulation.cbtc.data.map;
import club.joylink.rtss.simulation.cbtc.constant.SwitchIndication;
import club.joylink.rtss.simulation.cbtc.data.vr.VirtualRealitySwitch;
import club.joylink.rtss.simulation.cbtc.training2.ecm.anno.ExpConditionMaterialAnno;
import club.joylink.rtss.simulation.cbtc.training2.ecm.anno.ExpConditionMaterialSrcAnno;
import lombok.Getter;
import lombok.Setter;
@ -13,6 +15,7 @@ import java.util.stream.Collectors;
*/
@Getter
@Setter
@ExpConditionMaterialSrcAnno(name = "Switch")
public class Switch extends DelayUnlockDevice {
public Switch(String code, String name) {
super(code, name, DeviceType.SWITCH);
@ -53,11 +56,13 @@ public class Switch extends DelayUnlockDevice {
/**
* 是否单锁
*/
@ExpConditionMaterialAnno(name = "singleLock", type = "boolean", desc = "是否单锁")
private boolean singleLock;
/**
* 是否封锁
*/
@ExpConditionMaterialAnno(name = "blockade", type = "boolean", desc = "是否封锁")
private boolean blockade;
/**
@ -71,6 +76,7 @@ public class Switch extends DelayUnlockDevice {
/**
* 是否进路锁闭
*/
@ExpConditionMaterialAnno(name = "routeLock", type = "boolean", desc = "是否进路锁闭")
private boolean routeLock;
/**
@ -81,25 +87,30 @@ public class Switch extends DelayUnlockDevice {
/**
* 是否进路侧防锁闭
*/
@ExpConditionMaterialAnno(name = "fpLock", type = "boolean", desc = "是否进路侧防锁闭")
private boolean fpLock;
/**
* 是否进路延续保护锁闭
*/
@ExpConditionMaterialAnno(name = "overlapLock", type = "boolean", desc = "是否进路延续保护锁闭")
private boolean overlapLock;
/**
* 是否引导总锁
*/
@ExpConditionMaterialAnno(name = "guideMasterLock", type = "boolean", desc = "是否引导总锁")
private boolean guideMasterLock;
/**
* 道岔位置表示
*/
@ExpConditionMaterialAnno(name = "pos", type = "SwitchIndication", desc = "道岔位置表示")
private SwitchIndication pos;
/**
* 预复位
*/
@ExpConditionMaterialAnno(name = "preReset", type = "boolean", desc = "预复位")
private boolean preReset;
/**
@ -404,6 +415,7 @@ public class Switch extends DelayUnlockDevice {
/**
* 联锁征用(进路/延续保护/侧防等)
*
* @param normal
*/
public boolean ciUse(boolean normal) {
@ -423,6 +435,7 @@ public class Switch extends DelayUnlockDevice {
/**
* 是否被征用至相反位置
*
* @param normal
* @return
*/
@ -436,6 +449,7 @@ public class Switch extends DelayUnlockDevice {
/**
* 是否被征用至所需位置
*
* @param normal
* @return
*/

View File

@ -126,6 +126,8 @@ public class SectionStatus extends DeviceStatus {
*/
private boolean badShunt;
private Integer stopCountDown;
public SectionStatus(Section section) {
super(section.getCode(), section.getDeviceType());
this.blockade = section.isBlockade();
@ -147,6 +149,7 @@ public class SectionStatus extends DeviceStatus {
this.fault = section.getFault() == null ? null : section.getFault().toString();
this.shuntingTypeList = section.getShuntingTypeList();
this.badShunt = section.isBadShunt();
this.stopCountDown = section.getStopCountDownInSeconds();
}
@Override
@ -250,6 +253,13 @@ public class SectionStatus extends DeviceStatus {
this.badShunt = section.isBadShunt();
status.setBadShunt(this.badShunt);
}
int stopCountDownInSeconds = section.getStopCountDownInSeconds();
if (!Objects.equals(this.stopCountDown, stopCountDownInSeconds)) {
change = true;
this.stopCountDown = stopCountDownInSeconds;
}
status.setStopCountDown(stopCountDown == 0 ? null : stopCountDown);
return change;
}
@ -272,6 +282,7 @@ public class SectionStatus extends DeviceStatus {
statusVO.setDelayUnlock(delayUnlock);
statusVO.setClosed(closed);
statusVO.setFault(fault);
statusVO.setBadShunt(badShunt);
statusVO.setShuntingTypeList(this.shuntingTypeList);
return statusVO;
}

View File

@ -11,6 +11,8 @@ import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import lombok.Getter;
import java.time.LocalTime;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
/**
@ -90,6 +92,11 @@ public class StationStatus extends DeviceStatus {
*/
private boolean allowAutonomy;
/**
* 计数器
*/
private Map<String, Integer> counter;
public StationStatus(Station station) {
super(station.getCode(), station.getDeviceType());
controlMode = station.getControlMode();
@ -107,6 +114,9 @@ public class StationStatus extends DeviceStatus {
sGuideMasterLock = station.isSGuideMasterLock();
xGuideMasterLock = station.isXGuideMasterLock();
allowAutonomy = station.isAllowAutonomy();
if (station.getCounter() != null) {
counter = new HashMap<>(station.getCounter());
}
}
@Override
@ -190,6 +200,15 @@ public class StationStatus extends DeviceStatus {
allowAutonomy = station.isAllowAutonomy();
status.setAllowAutonomy(allowAutonomy);
}
if (!Objects.equals(counter, station.getCounter())) {
change = true;
if (counter == null) {
counter = new HashMap<>(station.getCounter());
} else {
counter.putAll(station.getCounter());
}
status.setCounter(counter);
}
return change;
}

View File

@ -1,177 +1,191 @@
package club.joylink.rtss.simulation.cbtc.data.storage.device;
import club.joylink.rtss.simulation.cbtc.Simulation;
import club.joylink.rtss.simulation.cbtc.data.SimulationDataRepository;
import club.joylink.rtss.simulation.cbtc.data.map.DelayUnlockDevice;
import club.joylink.rtss.simulation.cbtc.data.map.MapElement;
import club.joylink.rtss.simulation.cbtc.data.map.Route;
import club.joylink.rtss.simulation.cbtc.data.map.Section;
import club.joylink.rtss.util.jsonSerialize.Boolean2NumDeserializer;
import club.joylink.rtss.util.jsonSerialize.Boolean2NumSerializer;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import java.time.LocalDateTime;
import java.util.Objects;
@Getter
@Setter
@NoArgsConstructor
public class StorageRoute extends StorageDevice {
/**
* 是否CBTC模式
*/
@JsonSerialize(using = Boolean2NumSerializer.class)
@JsonDeserialize(using = Boolean2NumDeserializer.class)
private Boolean cbtcMode;
/**
* ats自动控制
*/
@JsonSerialize(using = Boolean2NumSerializer.class)
@JsonDeserialize(using = Boolean2NumDeserializer.class)
private Boolean atsControl;
/**
* 连续通过进路模式(联锁自动进路)开启
*/
@JsonSerialize(using = Boolean2NumSerializer.class)
@JsonDeserialize(using = Boolean2NumDeserializer.class)
private Boolean fleetMode;
/**
* 自动追踪/联锁自动触发模式开启
*/
@JsonSerialize(using = Boolean2NumSerializer.class)
@JsonDeserialize(using = Boolean2NumDeserializer.class)
private Boolean ciControl;
/**
* 进路是否排列中
*/
@JsonSerialize(using = Boolean2NumSerializer.class)
@JsonDeserialize(using = Boolean2NumDeserializer.class)
private Boolean setting;
private LocalDateTime settingStartTime;
/**
* 是否引导进路排列
*/
@JsonSerialize(using = Boolean2NumSerializer.class)
@JsonDeserialize(using = Boolean2NumDeserializer.class)
private Boolean settingGuide;
/**
* 进路是否锁闭
*/
@JsonSerialize(using = Boolean2NumSerializer.class)
@JsonDeserialize(using = Boolean2NumDeserializer.class)
private Boolean lock;
/** 进路延时解锁设备 */
private String delayUnlockDevice;
/**
* 是否正常解锁中
*/
@JsonSerialize(using = Boolean2NumSerializer.class)
@JsonDeserialize(using = Boolean2NumDeserializer.class)
private Boolean normalUnlock;
private String unlockedSection;
// public StorageRoute(Route route) {
// super(route.getCode());
// cbtcMode = route.isCbtcMode();
// turnBackMode = route.isTurnBackMode();
// atsControl = route.isAtsControl();
// fleetMode = route.isFleetMode();
// ciControl = route.isCiControl();
// setting = route.isSetting();
// settingGuide = route.isSettingGuide();
// lock = route.isLock();
// canceling = route.isCanceling();
// normalUnlock = route.isNormalUnlock();
// }
public StorageRoute(String code) {
super(code);
}
public static StorageRoute convert2Storage(Route route) {
StorageRoute storageRoute = new StorageRoute(route.getCode());
if (storageRoute.convert(route)) {
return storageRoute;
}
return null;
}
@Override
public boolean convert(MapElement element) {
boolean change = false;
Route route = (Route) element;
if (!route.isAtsControl()) {
change = true;
this.setAtsControl(route.isAtsControl());
}
if (route.isFleetMode()) {
change = true;
this.setFleetMode(route.isFleetMode());
}
if (route.isCiControl()) {
change = true;
this.setCiControl(route.isCiControl());
}
if (route.isSetting()) {
change = true;
this.setSetting(route.isSetting());
this.setSettingStartTime(route.getSettingStartTime());
}
if (route.isGuideSetting()) {
change = true;
this.setSettingGuide(route.isGuideSetting());
}
if (route.isLock()) {
change = true;
this.setLock(route.isLock());
}
if (route.getDelayUnlockDevice() != null) {
change = true;
this.setDelayUnlockDevice(route.getDelayUnlockDevice().getCode());
}
if (route.isNormalUnlock()) {
change = true;
this.setNormalUnlock(route.isNormalUnlock());
}
if (Objects.nonNull(route.getUnlockedSection())) {
change = true;
this.setUnlockedSection(route.getUnlockedSection().getCode());
}
return change;
}
@Override
public void recover2Simulation(MapElement element, Simulation simulation, SimulationDataRepository repository) {
Route route = (Route) element;
route.setAtsControl(atsControl != null ? atsControl : true);
route.setFleetMode(fleetMode != null ? fleetMode : false);
route.setCiControl(ciControl != null ? ciControl : false);
route.setSetting(setting != null? setting : false);
route.setSettingStartTime(this.settingStartTime);
route.setGuideSetting(settingGuide != null? settingGuide : false);
route.setLock(lock != null ? lock : false);
if (this.delayUnlockDevice != null) {
route.setDelayUnlockDevice((DelayUnlockDevice) repository.getByCode(this.delayUnlockDevice));
}
route.setNormalUnlock(normalUnlock != null ? normalUnlock : false);
if (Objects.nonNull(this.unlockedSection)) {
route.setUnlockedSection(repository.getByCode(this.unlockedSection, Section.class));
}
}
}
package club.joylink.rtss.simulation.cbtc.data.storage.device;
import club.joylink.rtss.simulation.cbtc.Simulation;
import club.joylink.rtss.simulation.cbtc.constant.SignalAspect;
import club.joylink.rtss.simulation.cbtc.data.SimulationDataRepository;
import club.joylink.rtss.simulation.cbtc.data.map.DelayUnlockDevice;
import club.joylink.rtss.simulation.cbtc.data.map.MapElement;
import club.joylink.rtss.simulation.cbtc.data.map.Route;
import club.joylink.rtss.simulation.cbtc.data.map.Section;
import club.joylink.rtss.util.jsonSerialize.Boolean2NumDeserializer;
import club.joylink.rtss.util.jsonSerialize.Boolean2NumSerializer;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import java.time.LocalDateTime;
import java.util.Objects;
@Getter
@Setter
@NoArgsConstructor
public class StorageRoute extends StorageDevice {
/**
* 是否CBTC模式
*/
@JsonSerialize(using = Boolean2NumSerializer.class)
@JsonDeserialize(using = Boolean2NumDeserializer.class)
private Boolean cbtcMode;
/**
* ats自动控制
*/
@JsonSerialize(using = Boolean2NumSerializer.class)
@JsonDeserialize(using = Boolean2NumDeserializer.class)
private Boolean atsControl;
/**
* 连续通过进路模式(联锁自动进路)开启
*/
@JsonSerialize(using = Boolean2NumSerializer.class)
@JsonDeserialize(using = Boolean2NumDeserializer.class)
private Boolean fleetMode;
/**
* 自动追踪/联锁自动触发模式开启
*/
@JsonSerialize(using = Boolean2NumSerializer.class)
@JsonDeserialize(using = Boolean2NumDeserializer.class)
private Boolean ciControl;
/**
* 进路是否排列中
*/
@JsonSerialize(using = Boolean2NumSerializer.class)
@JsonDeserialize(using = Boolean2NumDeserializer.class)
private Boolean setting;
private LocalDateTime settingStartTime;
/**
* 是否引导进路排列
*/
@JsonSerialize(using = Boolean2NumSerializer.class)
@JsonDeserialize(using = Boolean2NumDeserializer.class)
private Boolean settingGuide;
/**
* 进路是否锁闭
*/
@JsonSerialize(using = Boolean2NumSerializer.class)
@JsonDeserialize(using = Boolean2NumDeserializer.class)
private Boolean lock;
/** 进路延时解锁设备 */
private String delayUnlockDevice;
/**
* 是否正常解锁中
*/
@JsonSerialize(using = Boolean2NumSerializer.class)
@JsonDeserialize(using = Boolean2NumDeserializer.class)
private Boolean normalUnlock;
private String unlockedSection;
/**
* 该进路办理成功后要开放的信号
* <p>
* 注意每次开始触发办理进路时设置
*/
private SignalAspect settedAspect;
// public StorageRoute(Route route) {
// super(route.getCode());
// cbtcMode = route.isCbtcMode();
// turnBackMode = route.isTurnBackMode();
// atsControl = route.isAtsControl();
// fleetMode = route.isFleetMode();
// ciControl = route.isCiControl();
// setting = route.isSetting();
// settingGuide = route.isSettingGuide();
// lock = route.isLock();
// canceling = route.isCanceling();
// normalUnlock = route.isNormalUnlock();
// }
public StorageRoute(String code) {
super(code);
}
public static StorageRoute convert2Storage(Route route) {
StorageRoute storageRoute = new StorageRoute(route.getCode());
if (storageRoute.convert(route)) {
return storageRoute;
}
return null;
}
@Override
public boolean convert(MapElement element) {
boolean change = false;
Route route = (Route) element;
if (!route.isAtsControl()) {
change = true;
this.setAtsControl(route.isAtsControl());
}
if (route.isFleetMode()) {
change = true;
this.setFleetMode(route.isFleetMode());
}
if (route.isCiControl()) {
change = true;
this.setCiControl(route.isCiControl());
}
if (route.isSetting()) {
change = true;
this.setSetting(route.isSetting());
this.setSettingStartTime(route.getSettingStartTime());
}
if (route.isGuideSetting()) {
change = true;
this.setSettingGuide(route.isGuideSetting());
}
if (route.isLock()) {
change = true;
this.setLock(route.isLock());
}
if (route.getDelayUnlockDevice() != null) {
change = true;
this.setDelayUnlockDevice(route.getDelayUnlockDevice().getCode());
}
if (route.isNormalUnlock()) {
change = true;
this.setNormalUnlock(route.isNormalUnlock());
}
if (Objects.nonNull(route.getUnlockedSection())) {
change = true;
this.setUnlockedSection(route.getUnlockedSection().getCode());
}
if (Objects.nonNull(route.getSettedAspect())) {
change = true;
this.setSettedAspect(route.getSettedAspect());
}
return change;
}
@Override
public void recover2Simulation(MapElement element, Simulation simulation, SimulationDataRepository repository) {
Route route = (Route) element;
route.setAtsControl(atsControl != null ? atsControl : true);
route.setFleetMode(fleetMode != null ? fleetMode : false);
route.setCiControl(ciControl != null ? ciControl : false);
route.setSetting(setting != null? setting : false);
route.setSettingStartTime(this.settingStartTime);
route.setGuideSetting(settingGuide != null? settingGuide : false);
route.setLock(lock != null ? lock : false);
if (this.delayUnlockDevice != null) {
route.setDelayUnlockDevice((DelayUnlockDevice) repository.getByCode(this.delayUnlockDevice));
}
route.setNormalUnlock(normalUnlock != null ? normalUnlock : false);
if (Objects.nonNull(this.unlockedSection)) {
route.setUnlockedSection(repository.getByCode(this.unlockedSection, Section.class));
}
route.setSettedAspect(settedAspect);
}
}

View File

@ -106,6 +106,11 @@ public class StorageSection extends StorageDelayUnlockDevice {
*/
private Boolean badShunt;
/**
* 停稳倒计时
*/
private Integer stopCountDown;
public StorageSection(Section section) {
super(section);
}
@ -176,6 +181,10 @@ public class StorageSection extends StorageDelayUnlockDevice {
this.shuntingTypeList = section.getShuntingTypeList();
this.badShunt = section.isBadShunt();
}
if (section.getStopCountDown() != 0) {
change = true;
this.stopCountDown = section.getStopCountDown();
}
return change;
}
@ -197,5 +206,6 @@ public class StorageSection extends StorageDelayUnlockDevice {
section.setSpeedLimitBeforeFault(speedLimitBeforeFault);
section.setShuntingTypeList(shuntingTypeList != null ? shuntingTypeList : new ArrayList<>());
section.setBadShunt(badShunt != null ? badShunt : false);
section.setStopCountDown(stopCountDown == null ? 0 : stopCountDown);
}
}

View File

@ -13,6 +13,7 @@ import lombok.NoArgsConstructor;
import lombok.Setter;
import java.time.LocalTime;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicInteger;
@ -65,6 +66,8 @@ public class StorageStation extends StorageStatusDevice {
private Integer preResetValidDuration;
private Map<String, Integer> counter;
public StorageStation(Station station) {
super(station);
}
@ -111,6 +114,7 @@ public class StorageStation extends StorageStatusDevice {
if (station.getPreResetValidDuration() != null && station.getPreResetValidDuration().get() != 0) {
this.setPreResetValidDuration(station.getPreResetValidDuration().get());
}
this.counter = station.getCounter();
return true;
}
@ -133,5 +137,6 @@ public class StorageStation extends StorageStatusDevice {
station.setEmergencyController(emergencyController != null ? emergencyController : false);
station.setControlApplicant(controlApplicant != null ? simulation.getSimulationMemberById(controlApplicant) : null);
station.setPreResetValidDuration(new AtomicInteger(Objects.requireNonNullElse(preResetValidDuration, 0)));
station.setCounter(counter);
}
}

View File

@ -3,11 +3,12 @@ package club.joylink.rtss.simulation.cbtc.data.support;
import club.joylink.rtss.exception.BusinessExceptionAssertEnum;
import club.joylink.rtss.simulation.cbtc.data.map.*;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.CollectionUtils;
import java.util.*;
import java.util.stream.Collectors;
@Slf4j
@Getter
public class RoutePath {
@ -470,6 +471,15 @@ public class RoutePath {
// 取第一个延续保护道岔定位的
for (Route temp : triggerList) {
List<SwitchElement> switchList = temp.getOverlap().getFirstPath().getSwitchList();
if(null==switchList||switchList.isEmpty()){
log.debug("==============================================================================");
log.debug("==>>异常进路code = {} name = {}",temp.getCode(),temp.getName());
log.debug("==>>异常相关所有进路:");
triggerList.forEach(r->{
log.debug("==>>进路code={} name={} , 始端信号机code={} name={}",r.getCode(),r.getName(),r.getStart().getCode(),r.getName());
});
log.debug("==============================================================================");
}
if (switchList.get(0).isNormal()) {
route = temp;
break;

View File

@ -23,12 +23,15 @@ public class ConversationMessageVO {
private String audioPath;
private ConversationMessage.MessageType type;
public ConversationMessageVO(ConversationMessage message) {
this.id = message.getId();
this.memberId = message.getMember().getId();
this.time = message.getTime();
this.content = message.getContent();
this.audioPath = message.getAudioPath();
this.type = message.getType();
}
public static List<ConversationMessageVO> convert2VOList(List<ConversationMessage> list) {

View File

@ -99,6 +99,9 @@ public class SectionStatusVO extends DeviceStatusVO {
private Boolean badShunt;
@JsonInclude
private Integer stopCountDown;
public SectionStatusVO(Section section) {
super(section.getCode(), section.getDeviceType());
}

View File

@ -10,6 +10,7 @@ import lombok.Getter;
import lombok.Setter;
import java.time.LocalTime;
import java.util.Map;
/**
* 车站状态
@ -87,6 +88,8 @@ public class StationStatusVO extends DeviceStatusVO {
private Boolean allowAutonomy;
private Map<String, Integer> counter;
public StationStatusVO(Station station) {
super(station.getCode(), station.getDeviceType());
}

View File

@ -13,6 +13,8 @@ import club.joylink.rtss.simulation.cbtc.data.support.MovementAuthority;
import club.joylink.rtss.simulation.cbtc.data.support.SectionPosition;
import club.joylink.rtss.simulation.cbtc.exception.SimulationException;
import club.joylink.rtss.simulation.cbtc.exception.SimulationExceptionType;
import club.joylink.rtss.simulation.cbtc.training2.ecm.anno.ExpConditionMaterialAnno;
import club.joylink.rtss.simulation.cbtc.training2.ecm.anno.ExpConditionMaterialSrcAnno;
import club.joylink.rtss.vo.client.operation.DriveParamVO;
import lombok.Getter;
import lombok.Setter;
@ -27,6 +29,7 @@ import java.util.*;
@Slf4j
@Getter
@Setter
@ExpConditionMaterialSrcAnno(name = "Train")
public class VirtualRealityTrain extends VirtualRealityDevice {
// -----------列车公共属性-----------
@ -118,15 +121,17 @@ public class VirtualRealityTrain extends VirtualRealityDevice {
/**
* 车载服务通讯是否正常在线
*/
private boolean communication;
private boolean communication;
/**
* 列车运行级别
*/
@ExpConditionMaterialAnno(name = "runLevel", type = "RunLevel", desc = "列车运行级别")
private RunLevel runLevel;
/**
* 驾驶模式
*/
@ExpConditionMaterialAnno(name = "driveMode", type = "DriveMode", desc = "驾驶模式")
private DriveMode driveMode;
/**
@ -260,12 +265,14 @@ public class VirtualRealityTrain extends VirtualRealityDevice {
/**
* 是否紧急停车信号
*/
@ExpConditionMaterialAnno(name = "signalEB", type = "boolean", desc = "是否紧急停车(信号)")
private boolean signalEB;
/**
* 是否紧急停车电路
*/
private boolean circuitEB;
@ExpConditionMaterialAnno(name = "circuitEB", type = "boolean", desc = "是否紧急停车(电路)")
private boolean circuitEB;
/**
* 站台停靠列车动作
@ -275,6 +282,7 @@ public class VirtualRealityTrain extends VirtualRealityDevice {
/**
* 下一计划是否停站
*/
@ExpConditionMaterialAnno(name = "nextParking", type = "boolean", desc = "下一计划是否停站")
private boolean nextParking;
/**
@ -285,6 +293,7 @@ public class VirtualRealityTrain extends VirtualRealityDevice {
/**
* 是否扣车
*/
@ExpConditionMaterialAnno(name = "hold", type = "boolean", desc = "是否扣车")
private boolean hold;
/**
@ -295,11 +304,13 @@ public class VirtualRealityTrain extends VirtualRealityDevice {
/**
* 是否自动折返中
*/
@ExpConditionMaterialAnno(name = "dtro", type = "boolean", desc = "是否自动折返中")
private boolean dtro;
/**
* 是否换端中
*/
@ExpConditionMaterialAnno(name = "changeEnds", type = "boolean", desc = "是否换端中")
private boolean changeEnds;
/**
@ -310,16 +321,19 @@ public class VirtualRealityTrain extends VirtualRealityDevice {
/**
* ATO是否开启
*/
@ExpConditionMaterialAnno(name = "atoOn", type = "boolean", desc = "ATO是否开启")
private boolean atoOn;
/**
* ATP是否可用
*/
@ExpConditionMaterialAnno(name = "atpOn", type = "boolean", desc = "ATP是否可用")
private boolean atpOn;
/**
* 进路优先排列
*/
@ExpConditionMaterialAnno(name = "priorityRouteSet", type = "boolean", desc = "进路优先排列")
private boolean priorityRouteSet;
/**
@ -335,6 +349,7 @@ public class VirtualRealityTrain extends VirtualRealityDevice {
/**
* 门模式
*/
@ExpConditionMaterialAnno(name = "doorMode", type = "DoorMode", desc = "门模式")
private DoorMode doorMode;
/**
@ -409,6 +424,7 @@ public class VirtualRealityTrain extends VirtualRealityDevice {
/**
* 运行类型
*/
@ExpConditionMaterialAnno(name = "runType", type = "RunType", desc = "运行类型")
private RunType runType;
/**
@ -445,6 +461,7 @@ public class VirtualRealityTrain extends VirtualRealityDevice {
/**
* ato可以开启
*/
@ExpConditionMaterialAnno(name = "atoCanOpen", type = "boolean", desc = "ato可以开启")
private boolean atoCanOpen;
private VirtualRealityAudio vrAudio;
@ -507,7 +524,7 @@ public class VirtualRealityTrain extends VirtualRealityDevice {
super(code, groupNumber, DeviceType.TRAIN);
this.groupNumber = groupNumber;
this.gear = Handwheel.ATO;
this.communication = true;
this.communication = true;
this.atpOn = true;
this.door1 = new Door(this, "1");
this.door2 = new Door(this, "2");
@ -523,7 +540,7 @@ public class VirtualRealityTrain extends VirtualRealityDevice {
@Override
public void reset() {
this.noCommunicateDevice = false;
this.communication = true;
this.communication = true;
this.runLevel = null;
this.driveMode = null;
this.tempPreselectionMode = PreselectionMode.AM_C;
@ -653,7 +670,7 @@ public class VirtualRealityTrain extends VirtualRealityDevice {
}
private void init() {
this.communication = true;
this.communication = true;
this.jump = false;
this.hold = false;
this.standParkedTrainActivity = null;
@ -1024,7 +1041,7 @@ public class VirtualRealityTrain extends VirtualRealityDevice {
* 在空挡
*/
public boolean isInNeutralGear() {
return Handwheel.WASH.equals(gear) || Handwheel.DISCONNECT.equals(gear);
return Handwheel.WASH.equals(gear) || Handwheel.DISCONNECT.equals(gear);
}
/**
@ -1078,12 +1095,16 @@ public class VirtualRealityTrain extends VirtualRealityDevice {
return getAtoSpeed() * 3.6 < 20;
}
/** 操纵杆是否在惰行位 */
/**
* 操纵杆是否在惰行位
*/
public boolean isLeverInCoastingGear() {
return leverPosition == 0;
}
/** 是否不在牵引位 */
/**
* 是否不在牵引位
*/
public boolean isLeverNotInTractionGear() {
return leverPosition <= 0;
}
@ -1155,9 +1176,13 @@ public class VirtualRealityTrain extends VirtualRealityDevice {
* 道岔支持的操作
*/
public enum Operation {
/** 开门 */
/**
* 开门
*/
K,
/** 关门 */
/**
* 关门
*/
G,
}
@ -1273,7 +1298,9 @@ public class VirtualRealityTrain extends VirtualRealityDevice {
}
},
/** 驾驶异常 */
/**
* 驾驶异常
*/
DRIVE_FAULT {
@Override
public boolean apply(MapElement device) {
@ -1285,10 +1312,15 @@ public class VirtualRealityTrain extends VirtualRealityDevice {
return false;
}
},
/** 列车脱线 */
/**
* 列车脱线
*/
OFF_LINE {},
/** 突然EB */
SUDDEN_EB{},;
/**
* 突然EB
*/
SUDDEN_EB {},
;
public boolean apply(MapElement device) {
VirtualRealityTrain train = (VirtualRealityTrain) device;
@ -1298,8 +1330,9 @@ public class VirtualRealityTrain extends VirtualRealityDevice {
train.setFault(this);
return true;
}
/**
* 取消故障
* 取消故障
*/
public void fix(MapElement device) {
VirtualRealityTrain train = (VirtualRealityTrain) device;
@ -1416,9 +1449,13 @@ public class VirtualRealityTrain extends VirtualRealityDevice {
}
},
;
/** 所允许的最高驾驶模式 */
/**
* 所允许的最高驾驶模式
*/
private DriveMode driveMode;
/** 所允许的最高运行级别 */
/**
* 所允许的最高运行级别
*/
private RunLevel runLevel;
PreselectionMode(DriveMode driveMode, RunLevel runLevel) {

View File

@ -1,236 +1,236 @@
package club.joylink.rtss.simulation.cbtc.depot;
import club.joylink.rtss.simulation.cbtc.ATS.tools.TrainOutboundLoadTool;
import club.joylink.rtss.simulation.cbtc.CI.device.CiRouteService;
import club.joylink.rtss.simulation.cbtc.GroupSimulationService;
import club.joylink.rtss.simulation.cbtc.Simulation;
import club.joylink.rtss.simulation.cbtc.command.CommandBO;
import club.joylink.rtss.simulation.cbtc.command.CommandInitiateVO;
import club.joylink.rtss.simulation.cbtc.constant.SimulationConstants;
import club.joylink.rtss.simulation.cbtc.constant.SimulationModule;
import club.joylink.rtss.simulation.cbtc.data.map.Route;
import club.joylink.rtss.simulation.cbtc.data.map.Section;
import club.joylink.rtss.simulation.cbtc.data.map.Signal;
import club.joylink.rtss.simulation.cbtc.data.map.Station;
import club.joylink.rtss.simulation.cbtc.data.plan.SchedulingTrainPlan;
import club.joylink.rtss.simulation.cbtc.data.support.RoutePath;
import club.joylink.rtss.simulation.cbtc.data.support.SectionPosition;
import club.joylink.rtss.simulation.cbtc.data.vo.TrainInfo;
import club.joylink.rtss.simulation.cbtc.data.vr.VirtualRealityTrain;
import club.joylink.rtss.simulation.cbtc.member.SimulationMember;
import club.joylink.rtss.simulation.cbtc.onboard.ATP.ATPService;
import lombok.Getter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;
@Component
public class DepotService {
@Autowired
private CiRouteService ciRouteService;
@Autowired
private TrainOutboundLoadTool trainOutboundLoadTool;
@Autowired
private GroupSimulationService groupSimulationService;
@Autowired
private ATPService atpService;
public void loadDepotTrain(Simulation simulation) {
if (!simulation.getRepository().getConfig().isHandleDepot()) {
return;
}
Map<Station, List<Section>> parkingTracksMap = simulation.getRepository().getParkingTracksMap();
simulation.getRepository().getAllVrTrain().stream()
.collect(Collectors.groupingBy(VirtualRealityTrain::getDepotStation))
.forEach((station, trainList) -> {
List<Section> sections = parkingTracksMap.get(station);
// 先加载内侧的停车轨
sections.sort(Comparator.comparing(section ->
Objects.isNull(section.getLeftSection()) || Objects.isNull(section.getRightSection())));
boolean right = sections.get(sections.size() - 1).getLeftSection() == null;
for (int i = 0, trainListSize = trainList.size(); i < trainListSize; i++) {
VirtualRealityTrain train = trainList.get(i);
Section section = sections.get(i);
train.initManualTrain(new SectionPosition(section, section.getStopPointByDirection(right)), right);
train.parkingAt(section);
train.initAsRM();
TrainInfo trainInfo = TrainInfo.constructManualTrain(train);
trainInfo.tracking(train);
simulation.getRepository().addOnlineTrain(train);
simulation.getRepository().addTrainInfo(trainInfo);
}
});
}
public void addJobs(Simulation simulation) {
simulation.addJob(SimulationModule.DEPOT.name(), () -> this.run(simulation), SimulationConstants.DEPOT_LOOP_RATE);
}
private void run(Simulation simulation) {
if (!simulation.isPlanRunning()) {
return;
}
if (!simulation.getRepository().getConfig().isHandleDepot()) {
trainOutboundLoadTool.loadOutboundTrain(simulation);
} else {
timeToDeparture(simulation);
backToParking(simulation);
settingRouteAndMoving(simulation);
arriveDestination(simulation);
}
}
/**
* 根据时间筛选从停车轨自动发车
*/
private void timeToDeparture(Simulation simulation) {
LocalDateTime systemTime = simulation.getSystemTime();
for (SchedulingTrainPlan schedulingTrainPlan : simulation.getRepository().getSchedulingTrainPlanList()) {
if (schedulingTrainPlan.getOutDepotTrip().isDispatched()) {
continue;
}
if (schedulingTrainPlan.getOutDepotTrip().getStartTime().minusMinutes(10).isBefore(systemTime.toLocalTime())) {
schedulingTrainPlan.getOutDepotTrip().dispatched();
// 保存信息
VirtualRealityTrain train = simulation.getRepository().getVRByCode(schedulingTrainPlan.getGroupNumber(), VirtualRealityTrain.class);
Section startSection = train.getHeadPosition().getSection();
Section endSection = schedulingTrainPlan.getOutDepotTrip().getStartSection();
List<RoutePath> routePaths = simulation.getRepository().queryRoutePaths(startSection, endSection);
RoutePath routePath = routePaths.get(0);
DepotRunningInfo depotRunningInfo = new DepotRunningInfo(endSection, train, routePath, false);
simulation.getRepository().getDepotRunningInfoList().add(depotRunningInfo);
}
}
}
/**
* 筛选入库
*/
private void backToParking(Simulation simulation) {
for (TrainInfo trainInfo : simulation.getRepository().getTrainInfoMap().values()) {
if (trainInfo.isInbound() && trainInfo.isParking()) {
VirtualRealityTrain train = simulation.getRepository().getVRByCode(trainInfo.getGroupNumber(), VirtualRealityTrain.class);
if (train.getHeadPosition().getSection().isTransferTrack()
&& train.getTailPosition().getSection().isTransferTrack()) {
if (simulation.getRepository().getDepotRunningInfoList().stream()
.anyMatch(depotRunningInfo -> depotRunningInfo.getTrain().equals(train))) {
continue;
}
train.initAsRM();
Section startSection = train.getHeadPosition().getSection();
Section endSection = null;
for (Section section : simulation.getRepository().getParkingTracksMap().get(startSection.getStation())) {
if (section.isOccupied()) {
continue;
}
if (section.getLeftSection() == null || section.getRightSection() == null) {
endSection = section;
} else if (section.getLeftSection().isParkingTrack() && !section.getLeftSection().isOccupied()) {
endSection = section.getLeftSection();
} else if (section.getRightSection().isParkingTrack() && !section.getRightSection().isOccupied()) {
endSection = section.getRightSection();
} else {
endSection = section;
}
break;
}
// train.setTarget(endSection);
List<RoutePath> routePaths = simulation.getRepository().queryRoutePaths(startSection, endSection);
if (routePaths == null || routePaths.isEmpty()) {
return;
}
RoutePath routePath = routePaths.get(0);
DepotRunningInfo depotRunningInfo = new DepotRunningInfo(endSection, train, routePath, true);
simulation.getRepository().getDepotRunningInfoList().add(depotRunningInfo);
break;
}
}
}
}
/**
* 列车排进路并运行
*/
private void settingRouteAndMoving(Simulation simulation) {
for (DepotRunningInfo depotRunningInfo : simulation.getRepository().getDepotRunningInfoList()) {
Section endSection = depotRunningInfo.getEndSection();
SectionPosition position = new SectionPosition(endSection, endSection.getStopPointByDirection(depotRunningInfo.getRight()));
depotRunningInfo.getTrain().setRobotTargetPosition(position);
if (!depotRunningInfo.getRouteList().isEmpty()) {
Route route = depotRunningInfo.getRouteList().get(0);
if (route.isLock()) {
depotRunningInfo.getRouteList().remove(0);
}
if (!route.isSetting()) {
ciRouteService.setRoute(simulation, route);
}
}
}
}
/**
* 判断运行列车是否到达转换轨并升级
*/
private void arriveDestination(Simulation simulation) {
for (Iterator<DepotRunningInfo> iterator = simulation.getRepository().getDepotRunningInfoList().iterator(); iterator.hasNext(); ) {
DepotRunningInfo depotRunningInfo = iterator.next();
VirtualRealityTrain train = depotRunningInfo.getTrain();
if (depotRunningInfo.isArrival()) {
// 到达
iterator.remove();
if (depotRunningInfo.in) {
atpService.turnDirectionImmediately(train);
} else {
// 升级
SimulationMember member = simulation.getSimulationMember(train, SimulationMember.Type.DRIVER);
Map<String, Object> param = new HashMap<>();
param.put("preselectionMode", "AM_C");
CommandInitiateVO commandInitiateVO = new CommandInitiateVO(CommandBO.CommandType.Change_Preselection_Mode,
member.getId(), param);
groupSimulationService.command(simulation, commandInitiateVO, member);
}
}
}
}
@Getter
public static class DepotRunningInfo {
private final List<Route> routeList = new ArrayList<>();
private final Section endSection;
private final VirtualRealityTrain train;
private final Boolean right;
private final Boolean in;
public DepotRunningInfo(Section endSection, VirtualRealityTrain train, RoutePath routePath, boolean in) {
this.endSection = endSection;
this.train = train;
for (Signal signal : routePath.getSignalList()) {
for (Route route : signal.getRouteList()) {
if (routePath.getRouteList().contains(route)) {
routeList.add(route);
}
}
}
this.right = routePath.isRight();
this.in = in;
}
// 列车是否到达终点
public boolean isArrival() {
return train.getSpeed() == 0 && train.getHeadPosition().getSection().equals(endSection)
&& train.getTailPosition().getSection().equals(endSection);
}
}
}
package club.joylink.rtss.simulation.cbtc.depot;
import club.joylink.rtss.simulation.cbtc.ATS.tools.TrainOutboundLoadTool;
import club.joylink.rtss.simulation.cbtc.CI.device.CiRouteService;
import club.joylink.rtss.simulation.cbtc.GroupSimulationService;
import club.joylink.rtss.simulation.cbtc.Simulation;
import club.joylink.rtss.simulation.cbtc.command.CommandBO;
import club.joylink.rtss.simulation.cbtc.command.CommandInitiateVO;
import club.joylink.rtss.simulation.cbtc.constant.SimulationConstants;
import club.joylink.rtss.simulation.cbtc.constant.SimulationModule;
import club.joylink.rtss.simulation.cbtc.data.map.Route;
import club.joylink.rtss.simulation.cbtc.data.map.Section;
import club.joylink.rtss.simulation.cbtc.data.map.Signal;
import club.joylink.rtss.simulation.cbtc.data.map.Station;
import club.joylink.rtss.simulation.cbtc.data.plan.SchedulingTrainPlan;
import club.joylink.rtss.simulation.cbtc.data.support.RoutePath;
import club.joylink.rtss.simulation.cbtc.data.support.SectionPosition;
import club.joylink.rtss.simulation.cbtc.data.vo.TrainInfo;
import club.joylink.rtss.simulation.cbtc.data.vr.VirtualRealityTrain;
import club.joylink.rtss.simulation.cbtc.member.SimulationMember;
import club.joylink.rtss.simulation.cbtc.onboard.ATP.ATPService;
import lombok.Getter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;
@Component
public class DepotService {
@Autowired
private CiRouteService ciRouteService;
@Autowired
private TrainOutboundLoadTool trainOutboundLoadTool;
@Autowired
private GroupSimulationService groupSimulationService;
@Autowired
private ATPService atpService;
public void loadDepotTrain(Simulation simulation) {
if (!simulation.getRepository().getConfig().isHandleDepot()) {
return;
}
Map<Station, List<Section>> parkingTracksMap = simulation.getRepository().getParkingTracksMap();
simulation.getRepository().getAllVrTrain().stream()
.collect(Collectors.groupingBy(VirtualRealityTrain::getDepotStation))
.forEach((station, trainList) -> {
List<Section> sections = parkingTracksMap.get(station);
// 先加载内侧的停车轨
sections.sort(Comparator.comparing(section ->
Objects.isNull(section.getLeftSection()) || Objects.isNull(section.getRightSection())));
boolean right = sections.get(sections.size() - 1).getLeftSection() == null;
for (int i = 0, trainListSize = trainList.size(); i < trainListSize; i++) {
VirtualRealityTrain train = trainList.get(i);
Section section = sections.get(i);
train.initManualTrain(new SectionPosition(section, section.getStopPointByDirection(right)), right);
train.parkingAt(section);
train.initAsRM();
TrainInfo trainInfo = TrainInfo.constructManualTrain(train);
trainInfo.tracking(train);
simulation.getRepository().addOnlineTrain(train);
simulation.getRepository().addTrainInfo(trainInfo);
}
});
}
public void addJobs(Simulation simulation) {
simulation.addJob(SimulationModule.DEPOT.name(), () -> this.run(simulation), SimulationConstants.DEPOT_LOOP_RATE);
}
private void run(Simulation simulation) {
if (!simulation.isPlanRunning()) {
return;
}
if (!simulation.getRepository().getConfig().isHandleDepot()) {
trainOutboundLoadTool.loadOutboundTrain(simulation);
} else {
timeToDeparture(simulation);
backToParking(simulation);
settingRouteAndMoving(simulation);
arriveDestination(simulation);
}
}
/**
* 根据时间筛选从停车轨自动发车
*/
private void timeToDeparture(Simulation simulation) {
LocalDateTime systemTime = simulation.getSystemTime();
for (SchedulingTrainPlan schedulingTrainPlan : simulation.getRepository().getSchedulingTrainPlanList()) {
if (schedulingTrainPlan.getOutDepotTrip().isDispatched()) {
continue;
}
if (schedulingTrainPlan.getOutDepotTrip().getStartTime().minusMinutes(10).isBefore(systemTime.toLocalTime())) {
schedulingTrainPlan.getOutDepotTrip().dispatched();
// 保存信息
VirtualRealityTrain train = simulation.getRepository().getVRByCode(schedulingTrainPlan.getGroupNumber(), VirtualRealityTrain.class);
Section startSection = train.getHeadPosition().getSection();
Section endSection = schedulingTrainPlan.getOutDepotTrip().getStartSection();
List<RoutePath> routePaths = simulation.getRepository().queryRoutePaths(startSection, endSection);
RoutePath routePath = routePaths.get(0);
DepotRunningInfo depotRunningInfo = new DepotRunningInfo(endSection, train, routePath, false);
simulation.getRepository().getDepotRunningInfoList().add(depotRunningInfo);
}
}
}
/**
* 筛选入库
*/
private void backToParking(Simulation simulation) {
for (TrainInfo trainInfo : simulation.getRepository().getTrainInfoMap().values()) {
if (trainInfo.isInbound() && trainInfo.isParking()) {
VirtualRealityTrain train = simulation.getRepository().getVRByCode(trainInfo.getGroupNumber(), VirtualRealityTrain.class);
if (train.getHeadPosition().getSection().isTransferTrack()
&& train.getTailPosition().getSection().isTransferTrack()) {
if (simulation.getRepository().getDepotRunningInfoList().stream()
.anyMatch(depotRunningInfo -> depotRunningInfo.getTrain().equals(train))) {
continue;
}
train.initAsRM();
Section startSection = train.getHeadPosition().getSection();
Section endSection = null;
for (Section section : simulation.getRepository().getParkingTracksMap().get(startSection.getStation())) {
if (section.isOccupied()) {
continue;
}
if (section.getLeftSection() == null || section.getRightSection() == null) {
endSection = section;
} else if (section.getLeftSection().isParkingTrack() && !section.getLeftSection().isOccupied()) {
endSection = section.getLeftSection();
} else if (section.getRightSection().isParkingTrack() && !section.getRightSection().isOccupied()) {
endSection = section.getRightSection();
} else {
endSection = section;
}
break;
}
// train.setTarget(endSection);
List<RoutePath> routePaths = simulation.getRepository().queryRoutePaths(startSection, endSection);
if (routePaths == null || routePaths.isEmpty()) {
return;
}
RoutePath routePath = routePaths.get(0);
DepotRunningInfo depotRunningInfo = new DepotRunningInfo(endSection, train, routePath, true);
simulation.getRepository().getDepotRunningInfoList().add(depotRunningInfo);
break;
}
}
}
}
/**
* 列车排进路并运行
*/
private void settingRouteAndMoving(Simulation simulation) {
for (DepotRunningInfo depotRunningInfo : simulation.getRepository().getDepotRunningInfoList()) {
Section endSection = depotRunningInfo.getEndSection();
SectionPosition position = new SectionPosition(endSection, endSection.getStopPointByDirection(depotRunningInfo.getRight()));
depotRunningInfo.getTrain().setRobotTargetPosition(position);
if (!depotRunningInfo.getRouteList().isEmpty()) {
Route route = depotRunningInfo.getRouteList().get(0);
if (route.isLock()) {
depotRunningInfo.getRouteList().remove(0);
}
if (!route.isSetting()) {
ciRouteService.setRoute(simulation, route,route.getAspect());
}
}
}
}
/**
* 判断运行列车是否到达转换轨并升级
*/
private void arriveDestination(Simulation simulation) {
for (Iterator<DepotRunningInfo> iterator = simulation.getRepository().getDepotRunningInfoList().iterator(); iterator.hasNext(); ) {
DepotRunningInfo depotRunningInfo = iterator.next();
VirtualRealityTrain train = depotRunningInfo.getTrain();
if (depotRunningInfo.isArrival()) {
// 到达
iterator.remove();
if (depotRunningInfo.in) {
atpService.turnDirectionImmediately(train);
} else {
// 升级
SimulationMember member = simulation.getSimulationMember(train, SimulationMember.Type.DRIVER);
Map<String, Object> param = new HashMap<>();
param.put("preselectionMode", "AM_C");
CommandInitiateVO commandInitiateVO = new CommandInitiateVO(CommandBO.CommandType.Change_Preselection_Mode,
member.getId(), param);
groupSimulationService.command(simulation, commandInitiateVO, member);
}
}
}
}
@Getter
public static class DepotRunningInfo {
private final List<Route> routeList = new ArrayList<>();
private final Section endSection;
private final VirtualRealityTrain train;
private final Boolean right;
private final Boolean in;
public DepotRunningInfo(Section endSection, VirtualRealityTrain train, RoutePath routePath, boolean in) {
this.endSection = endSection;
this.train = train;
for (Signal signal : routePath.getSignalList()) {
for (Route route : signal.getRouteList()) {
if (routePath.getRouteList().contains(route)) {
routeList.add(route);
}
}
}
this.right = routePath.isRight();
this.in = in;
}
// 列车是否到达终点
public boolean isArrival() {
return train.getSpeed() == 0 && train.getHeadPosition().getSection().equals(endSection)
&& train.getTailPosition().getSection().equals(endSection);
}
}
}

View File

@ -106,11 +106,11 @@ public class MemberManager {
this.playRole(simulation, userId, ddList.get(0).getId());
break;
}
case CTC: {
List<SimulationMember> list = simulation.querySimulationMembersOfRole(SimulationMember.Type.RAIL_CTC);
this.playRole(simulation, userId, list.get(0).getId());
break;
}
// case CTC: {
// List<SimulationMember> list = simulation.querySimulationMembersOfRole(SimulationMember.Type.RAIL_CTC);
// this.playRole(simulation, userId, list.get(0).getId());
// break;
// }
}
}
}

Some files were not shown because too many files have changed in this diff Show More