LingxinMeng 2 жил өмнө
parent
commit
6ee039a075

+ 467 - 549
simulation-resource-scheduler/src/main/java/com/css/simulation/resource/scheduler/consumer/ProjectConsumer.java

@@ -35,572 +35,490 @@ import java.util.concurrent.TimeUnit;
 @Component
 @Slf4j
 public class ProjectConsumer {
-    @Value("${scheduler.linux-path.temp}")
-    private String linuxTempPath;
-    @Value("${scheduler.minio-path.project-result}")
-    private String projectResultPathOfMinio;
-    @Value("${minio.bucket-name}")
-    private String bucketName;
-
-    // -------------------------------- Comment --------------------------------
-    @Resource
-    private MinioClient minioClient;
-    @Resource
-    private StringRedisTemplate stringRedisTemplate;
-    @Resource
-    private ManualProjectMapper manualProjectMapper;
-    @Resource
-    private AutoSubProjectMapper autoSubProjectMapper;
-    @Resource
-    private VehicleMapper vehicleMapper;
-    @Resource
-    private SensorCameraMapper sensorCameraMapper;
-    @Resource
-    private SensorOgtMapper sensorOgtMapper;
-    @Resource
-    private AlgorithmMapper algorithmMapper;
-    @Resource
-    private UserMapper userMapper;
-    @Resource
-    private ClusterMapper clusterMapper;
-    @Resource
-    private ProjectService projectService;
-    @Resource
-    private ProjectUtil projectUtil;
-    @Resource
-    private IndexMapper indexMapper;
-    @Resource
-    private TaskMapper taskMapper;
-    @Resource
-    private TaskManager taskManager;
-    @Resource
-    private ProjectManager projectManager;
-    @Resource
-    private KafkaTemplate<String, String> kafkaTemplate;
-    @Resource(name = "myKafkaAdmin")
-    private Admin kafkaAdminClient;
-
-    /**
-     * 接收到运行信息立即复制一份数据作为运行数据
-     *
-     * @param projectRecord 项目启动消息
-     */
-    @KafkaListener(groupId = "simulation-resource-scheduler", topics = "${scheduler.start-topic}")
-    @SneakyThrows
-    public void acceptMessage(ConsumerRecord<String, String> projectRecord) {
-        String initialProjectJson = projectRecord.value();
-        ProjectMessageDTO projectMessageDTO = JsonUtil.jsonToBean(initialProjectJson, ProjectMessageDTO.class);
-        String projectId = projectMessageDTO.getProjectId();        // 手动执行项目 id 或 自动执行子项目 id
-        new Thread(() -> createTaskAndFixData(projectRecord), "fix-" + projectId).start();
+  @Value("${scheduler.linux-path.temp}")
+  private String linuxTempPath;
+  @Value("${scheduler.minio-path.project-result}")
+  private String projectResultPathOfMinio;
+  @Value("${minio.bucket-name}")
+  private String bucketName;
+
+  // -------------------------------- Comment --------------------------------
+  @Resource
+  private MinioClient minioClient;
+  @Resource
+  private StringRedisTemplate stringRedisTemplate;
+  @Resource
+  private ManualProjectMapper manualProjectMapper;
+  @Resource
+  private AutoSubProjectMapper autoSubProjectMapper;
+  @Resource
+  private VehicleMapper vehicleMapper;
+  @Resource
+  private SensorCameraMapper sensorCameraMapper;
+  @Resource
+  private SensorOgtMapper sensorOgtMapper;
+  @Resource
+  private AlgorithmMapper algorithmMapper;
+  @Resource
+  private UserMapper userMapper;
+  @Resource
+  private ClusterMapper clusterMapper;
+  @Resource
+  private ProjectService projectService;
+  @Resource
+  private ProjectUtil projectUtil;
+  @Resource
+  private IndexMapper indexMapper;
+  @Resource
+  private TaskMapper taskMapper;
+  @Resource
+  private TaskManager taskManager;
+  @Resource
+  private ProjectManager projectManager;
+  @Resource
+  private KafkaTemplate<String, String> kafkaTemplate;
+  @Resource(name = "myKafkaAdmin")
+  private Admin kafkaAdminClient;
+
+  /**
+   * 接收到运行信息立即复制一份数据作为运行数据
+   *
+   * @param projectRecord 项目启动消息
+   */
+  @KafkaListener(groupId = "simulation-resource-scheduler", topics = "${scheduler.start-topic}")
+  @SneakyThrows
+  public void acceptMessage(ConsumerRecord<String, String> projectRecord) {
+    final ProjectMessageDTO projectMessageDTO = JsonUtil.jsonToBean(projectRecord.value(), ProjectMessageDTO.class);
+    log.info("接收到项目开始消息为:" + projectMessageDTO);
+    new Thread(() -> createTaskAndFixData(projectMessageDTO), "fix-" + projectMessageDTO.getProjectId()).start();
+  }
+
+
+  @SneakyThrows
+  public void createTaskAndFixData(ProjectMessageDTO projectMessageDTO) {
+    //* -------------------------------- 0 读取消息,创建临时目录 --------------------------------
+    String projectId = projectMessageDTO.getProjectId();                // 手动执行项目 id 或 自动执行子项目 id
+    String modelType = projectMessageDTO.getModelType();                // 模型类型,1 动力学模型 2 carsim模型
+    String packageId = projectMessageDTO.getScenePackageId();           // 场景测试包 id
+    String vehicleConfigId = projectMessageDTO.getVehicleConfigId();    // 模型配置 id
+    String algorithmId = projectMessageDTO.getAlgorithmId();            // 模型配置 id
+    long videoTime = projectMessageDTO.getMaxSimulationTime();          // 结果视频的时长
+    String projectType = projectMessageDTO.getType();                   // 项目类型
+    String userId = "";  // 用户 id
+    if (DictConstants.PROJECT_TYPE_MANUAL.equals(projectType)) {
+      userId = manualProjectMapper.selectCreateUserById(projectId);
+    } else if (DictConstants.PROJECT_TYPE_AUTO_SUB.equals(projectType)) {
+      userId = autoSubProjectMapper.selectCreateUserById(projectId);
     }
-
-
-    @SneakyThrows
-    public void createTaskAndFixData(ConsumerRecord<String, String> projectRecord) {
-        //* -------------------------------- 0 读取消息,创建临时目录 --------------------------------
-        String initialProjectJson = projectRecord.value();
-        log.info("接收到项目开始消息为:" + initialProjectJson);
-        ProjectMessageDTO projectMessageDTO = JsonUtil.jsonToBean(initialProjectJson, ProjectMessageDTO.class);
-        String projectId = projectMessageDTO.getProjectId();                // 手动执行项目 id 或 自动执行子项目 id
-        String modelType = projectMessageDTO.getModelType();                // 模型类型,1 动力学模型 2 carsim模型
-        String packageId = projectMessageDTO.getScenePackageId();           // 场景测试包 id
-        String vehicleConfigId = projectMessageDTO.getVehicleConfigId();    // 模型配置 id
-        String algorithmId = projectMessageDTO.getAlgorithmId();            // 模型配置 id
-        long videoTime = projectMessageDTO.getMaxSimulationTime();          // 结果视频的时长
-        String projectType = projectMessageDTO.getType();                   // 项目类型
-        String userId = "";  // 用户 id
+    String projectPath = linuxTempPath + "project/" + projectId + "/";
+    FileUtil.mkdir(projectPath);
+    //5 将该 project 下所有旧的指标得分删除。
+    taskMapper.deleteByProject(projectId);
+    indexMapper.deleteFirstTargetScoreByProjectId(projectId);
+    indexMapper.deleteLastTargetScoreByProjectId(projectId);
+    // -------------------------------- 1 查询场景 --------------------------------
+    log.info("项目 " + projectId + " 开始查询场景。");
+    //根据场景测试包 packageId,拿到场景集合(包括重复场景),重复场景会在发送消息时根据叶子指标发送多次。
+    List<SceneEntity> sceneEntityList = projectService.getSceneList(projectId, packageId);
+    int taskTotal = sceneEntityList.size();
+    projectMessageDTO.setTaskTotal(taskTotal);
+    projectMessageDTO.setTaskCompleted(0);
+    //去重,之后发送消息的时候会补全指标,如果不去重的话会出现多个场景重复关联多个指标
+    Set<SceneEntity> sceneEntitySet = new HashSet<>(sceneEntityList);
+    log.info("项目 " + projectId + " 场景包括:" + sceneEntitySet);
+    // -------------------------------- 2 算法导入 --------------------------------
+    log.info("项目 " + projectId + " 开始算法导入。");
+    String algorithmDockerImage = projectService.handleAlgorithm(projectId, algorithmId);
+    log.info("项目 " + projectId + " 算法已导入:" + algorithmDockerImage);
+    // -------------------------------- 3 查询模型 --------------------------------
+    if ("1".equals(modelType)) {
+      log.info("项目 " + projectId + " 开始查询模型。");
+      //2-1 根据车辆配置id vehicleConfigId, 获取 模型信息和传感器信息
+      VehicleEntity vehicleEntity = vehicleMapper.selectByVehicleConfigId(vehicleConfigId);   // 车辆
+      List<CameraEntity> cameraEntityList = sensorCameraMapper.selectCameraByVehicleConfigId(vehicleConfigId);    // 摄像头
+      List<OgtEntity> ogtEntityList = sensorOgtMapper.selectOgtByVehicleId(vehicleConfigId); // 完美传感器
+      // -------------------------------- 4 保存任务消息 --------------------------------
+      log.info("项目 " + projectId + " 开始保存任务消息。");
+      List<TaskEntity> taskList = new ArrayList<>();
+      for (SceneEntity sceneEntity : sceneEntitySet) {
+        String sceneId = sceneEntity.getId();
+        //3-1 可能会存在多个指标下有同样的场景,所以会查出多个指标,多个指标的场景需要发送多次
+        List<String> lastTargetIdList = null;
         if (DictConstants.PROJECT_TYPE_MANUAL.equals(projectType)) {
-            userId = manualProjectMapper.selectCreateUserById(projectId);
+          lastTargetIdList = indexMapper.selectLeafIndexIdByManualProjectIdAndSceneId(projectId, "%" + sceneId + "%");
         } else if (DictConstants.PROJECT_TYPE_AUTO_SUB.equals(projectType)) {
-            userId = autoSubProjectMapper.selectCreateUserById(projectId);
+          lastTargetIdList = indexMapper.selectLeafIndexIdByAutoSubProjectIdAndSceneId(projectId, "%" + sceneId + "%");
         }
-        String projectPath = linuxTempPath + "project/" + projectId + "/";
-        FileUtil.mkdir(projectPath);
-        //5 将该 project 下所有旧的指标得分删除。
-        taskMapper.deleteByProject(projectId);
-        indexMapper.deleteFirstTargetScoreByProjectId(projectId);
-        indexMapper.deleteLastTargetScoreByProjectId(projectId);
-        // -------------------------------- 1 查询场景 --------------------------------
-        log.info("项目 " + projectId + " 开始查询场景。");
-        //根据场景测试包 packageId,拿到场景集合(包括重复场景),重复场景会在发送消息时根据叶子指标发送多次。
-        List<SceneEntity> sceneEntityList = projectService.getSceneList(projectId, packageId);
-        int taskTotal = sceneEntityList.size();
-        projectMessageDTO.setTaskTotal(taskTotal);
-        projectMessageDTO.setTaskCompleted(0);
-        //去重,之后发送消息的时候会补全指标,如果不去重的话会出现多个场景重复关联多个指标
-        Set<SceneEntity> sceneEntitySet = new HashSet<>(sceneEntityList);
-        log.info("项目 " + projectId + " 场景包括:" + sceneEntitySet);
-        // -------------------------------- 2 算法导入 --------------------------------
-        log.info("项目 " + projectId + " 开始算法导入。");
-        String algorithmDockerImage = projectService.handleAlgorithm(projectId, algorithmId);
-        log.info("项目 " + projectId + " 算法已导入:" + algorithmDockerImage);
-        // -------------------------------- 3 查询模型 --------------------------------
-        if ("1".equals(modelType)) {
-            log.info("项目 " + projectId + " 开始查询模型。");
-            //2-1 根据车辆配置id vehicleConfigId, 获取 模型信息和传感器信息
-            VehicleEntity vehicleEntity = vehicleMapper.selectByVehicleConfigId(vehicleConfigId);   // 车辆
-            List<CameraEntity> cameraEntityList = sensorCameraMapper.selectCameraByVehicleConfigId(vehicleConfigId);    // 摄像头
-            List<OgtEntity> ogtEntityList = sensorOgtMapper.selectOgtByVehicleId(vehicleConfigId); // 完美传感器
-            // -------------------------------- 4 保存任务消息 --------------------------------
-            log.info("项目 " + projectId + " 开始保存任务消息。");
-            List<TaskEntity> taskList = new ArrayList<>();
-            for (SceneEntity sceneEntity : sceneEntitySet) {
-                String sceneId = sceneEntity.getId();
-                //3-1 可能会存在多个指标下有同样的场景,所以会查出多个指标,多个指标的场景需要发送多次
-                List<String> lastTargetIdList = null;
-                if (DictConstants.PROJECT_TYPE_MANUAL.equals(projectType)) {
-                    lastTargetIdList = indexMapper.selectLeafIndexIdByManualProjectIdAndSceneId(projectId, "%" + sceneId + "%");
-                } else if (DictConstants.PROJECT_TYPE_AUTO_SUB.equals(projectType)) {
-                    lastTargetIdList = indexMapper.selectLeafIndexIdByAutoSubProjectIdAndSceneId(projectId, "%" + sceneId + "%");
-                }
-                if (CollectionUtil.isEmpty(lastTargetIdList)) {
-                    throw new RuntimeException("项目 " + projectId + " 使用的场景测试包 " + sceneId + " 不存在指标。");
-                }
-                for (String lastTargetId : lastTargetIdList) {
-                    String taskId = StringUtil.getRandomUUID();
-                    // 保存任务信息
-                    TaskEntity taskEntity = TaskEntity.builder() // run_start_time 和 run_end_time 不填
-                            .id(taskId)
-                            .pId(projectId)
-                            .sceneId(sceneId)
-                            .lastTargetId(lastTargetId)
-                            .sceneName(sceneEntity.getName())
-                            .sceneType(sceneEntity.getType())
-                            .runState(DictConstants.TASK_PENDING)
-                            .runResultFilePath(projectResultPathOfMinio + projectId + "/" + taskId)
-                            .build();
-                    taskEntity.setCreateTime(TimeUtil.getNowForMysql());
-                    taskEntity.setCreateUserId(userId);
-                    taskEntity.setModifyTime(TimeUtil.getNowForMysql());
-                    taskEntity.setModifyUserId(userId);
-                    taskEntity.setModifyTime(TimeUtil.getNowForMysql());
-                    taskEntity.setIsDeleted("0");
-                    taskList.add(taskEntity);
-                    // 将 xosc、xodr、osgb 全部上传到仿真结果路径
-                    String scenarioOsc = sceneEntity.getScenarioOsc();
-                    String[] splitXosc = scenarioOsc.split("/");
-                    String xoscName = splitXosc[splitXosc.length - 1];
-                    String[] xoscNameSplit = xoscName.split("\\.");
-                    String xoscSuffix = xoscNameSplit[xoscNameSplit.length - 1];
-                    String xoscPathOfLinux = linuxTempPath + "video/" + projectId + "/" + taskId + "/" + xoscName;
-                    String xoscPathOfMinio = projectResultPathOfMinio + projectId + "/" + taskId + "/" + taskId + "." + xoscSuffix;
-                    MinioUtil.downloadToFile(minioClient, bucketName, scenarioOsc, xoscPathOfLinux);
-                    MinioUtil.uploadFromFile(minioClient, xoscPathOfLinux, bucketName, xoscPathOfMinio);
-
-                    String scenarioOdr = sceneEntity.getScenarioOdr();
-                    String[] splitXodr = scenarioOdr.split("/");
-                    String xodrName = splitXodr[splitXodr.length - 1];
-                    String[] xodrNameSplit = xodrName.split("\\.");
-                    String xodrSuffix = xodrNameSplit[xodrNameSplit.length - 1];
-                    String xodrPathOfLinux = linuxTempPath + "video/" + projectId + "/" + taskId + "/" + xodrName;
-                    String xodrPathOfMinio = projectResultPathOfMinio + projectId + "/" + taskId + "/" + taskId + "." + xodrSuffix;
-                    MinioUtil.downloadToFile(minioClient, bucketName, scenarioOdr, xodrPathOfLinux);
-                    MinioUtil.uploadFromFile(minioClient, xodrPathOfLinux, bucketName, xodrPathOfMinio);
-
-                    String scenarioOsgb = sceneEntity.getScenarioOsgb();
-                    String[] splitOsgb = scenarioOsgb.split("/");
-                    String osgbName = splitOsgb[splitOsgb.length - 1];
-                    String[] osgbNameSplit = osgbName.split("\\.");
-                    String osgbSuffix = osgbNameSplit[osgbNameSplit.length - 1];
-                    String osgbPathOfLinux = linuxTempPath + "video/" + projectId + "/" + taskId + "/" + osgbName;
-                    String osgbPathOfMinio = projectResultPathOfMinio + projectId + "/" + taskId + "/" + taskId + "." + osgbSuffix;
-                    MinioUtil.downloadToFile(minioClient, bucketName, scenarioOsgb, osgbPathOfLinux);
-                    MinioUtil.uploadFromFile(minioClient, osgbPathOfLinux, bucketName, osgbPathOfMinio);
-                    log.info("已经将 xosc、xodr、osgb 上传到 minio 的结果文件目录:" + projectResultPathOfMinio);
-
-                    // 组装 task 消息
-                    TaskMessageEntity taskMessageEntity = TaskMessageEntity.builder()
-                            .info(InfoEntity.builder()
-                                    .project_id(taskEntity.getPId())
-                                    .task_id(taskEntity.getId())
-                                    .task_path(taskEntity.getRunResultFilePath())
-                                    .default_time(videoTime)
-                                    .build())
-                            .scenario(ScenarioEntity.builder()
-                                    .scenario_osc(xoscPathOfMinio)
-                                    .scenario_odr(xodrPathOfMinio)
-                                    .scenario_osgb(osgbPathOfMinio)
-                                    .build())
-                            .vehicle(VehicleTO.builder()
-                                    .model(ModelEntity.builder()
-                                            .model_label(vehicleEntity.getModelLabel())
-                                            .build())
-                                    .dynamics(DynamicsTO.builder()
-                                            .dynamics_maxspeed(vehicleEntity.getMaxSpeed())
-                                            .dynamics_enginepower(vehicleEntity.getEnginePower())
-                                            .dynamics_maxdecel(vehicleEntity.getMaxDeceleration())
-                                            .dynamics_maxsteering(vehicleEntity.getMaxSteeringAngle())
-                                            .dynamics_mass(vehicleEntity.getMass())
-                                            .dynamics_frontsurfaceeffective(vehicleEntity.getFrontSurfaceEffective())
-                                            .dynamics_airdragcoefficient(vehicleEntity.getAirDragCoefficient())
-                                            .dynamics_rollingresistance(vehicleEntity.getRollingResistanceCoefficient())
-                                            .dynamics_wheeldiameter(vehicleEntity.getWheelDiameter())
-                                            .dynamics_wheeldrive(vehicleEntity.getWheelDrive())
-                                            .dynamics_overallefficiency(vehicleEntity.getOverallEfficiency())
-                                            .dynamics_distfront(vehicleEntity.getFrontDistance())
-                                            .dynamics_distrear(vehicleEntity.getRearDistance())
-                                            .dynamics_distleft(vehicleEntity.getLeftDistance())
-                                            .dynamics_distright(vehicleEntity.getRightDistance())
-                                            .dynamics_distheight(vehicleEntity.getHeightDistance())
-                                            .dynamics_wheelbase(vehicleEntity.getWheelbase())
-                                            .build())
-                                    .sensors(SensorsEntity.builder()   // 根据 vehicleId 查询绑定的传感器列表
-                                            .camera(cameraEntityList)
-                                            .OGT(ogtEntityList)
-                                            .build())
-                                    .build())
-                            .build();
-                    FileUtil.writeStringToLocalFile(JsonUtil.beanToJson(taskMessageEntity), projectPath + taskId + ".json");
-                    log.info("项目 " + projectId + " 将任务消息转成 json 保存到临时目录等待资源分配后执行:" + taskMessageEntity.getInfo().getTask_id());
-                }
-            }
-            taskManager.batchInsertTask(taskList);
-            log.info("项目 " + projectId + " 共有 " + taskList.size() + " 个任务,已保存到数据库");
-        } else if ("2".equals(modelType)) {
-            log.info("项目 " + projectId + " 开始查询模型。");
-
-            VehicleEntity vehicleEntity = vehicleMapper.selectByVehicleConfigId(vehicleConfigId);   // 车辆
-            List<CameraEntity> cameraEntityList = sensorCameraMapper.selectCameraByVehicleConfigId(vehicleConfigId);    // 摄像头
-            List<OgtEntity> ogtEntityList = sensorOgtMapper.selectOgtByVehicleId(vehicleConfigId); // 完美传感器
-            // -------------------------------- 4 保存任务消息 --------------------------------
-            log.info("项目 " + projectId + " 开始保存任务消息。");
-            List<TaskEntity> taskList = new ArrayList<>();
-            for (SceneEntity sceneEntity : sceneEntitySet) {
-                String sceneId = sceneEntity.getId();
-                //3-1 可能会存在多个指标下有同样的场景,所以会查出多个指标,多个指标的场景需要发送多次
-                List<String> lastTargetIdList = null;
-                if (DictConstants.PROJECT_TYPE_MANUAL.equals(projectType)) {
-                    lastTargetIdList = indexMapper.selectLeafIndexIdByManualProjectIdAndSceneId(projectId, "%" + sceneId + "%");
-                } else if (DictConstants.PROJECT_TYPE_AUTO_SUB.equals(projectType)) {
-                    lastTargetIdList = indexMapper.selectLeafIndexIdByAutoSubProjectIdAndSceneId(projectId, "%" + sceneId + "%");
-                }
-                if (CollectionUtil.isEmpty(lastTargetIdList)) {
-                    throw new RuntimeException("项目 " + projectId + " 使用的场景测试包 " + sceneId + " 不存在指标。");
-                }
-                for (String lastTargetId : lastTargetIdList) {
-                    String taskId = StringUtil.getRandomUUID();
-                    // 保存任务信息
-                    TaskEntity taskEntity = TaskEntity.builder() // run_start_time 和 run_end_time 不填
-                            .id(taskId)
-                            .pId(projectId)
-                            .sceneId(sceneId)
-                            .lastTargetId(lastTargetId)
-                            .sceneName(sceneEntity.getName())
-                            .sceneType(sceneEntity.getType())
-                            .runState(DictConstants.TASK_PENDING)
-                            .runResultFilePath(projectResultPathOfMinio + projectId + "/" + taskId)
-                            .build();
-                    taskEntity.setCreateTime(TimeUtil.getNowForMysql());
-                    taskEntity.setCreateUserId(userId);
-                    taskEntity.setModifyTime(TimeUtil.getNowForMysql());
-                    taskEntity.setModifyUserId(userId);
-                    taskEntity.setModifyTime(TimeUtil.getNowForMysql());
-                    taskEntity.setIsDeleted("0");
-                    taskList.add(taskEntity);
-                    // 将 xosc、xodr、osgb 全部上传到仿真结果路径
-                    String scenarioOsc = sceneEntity.getScenarioOsc();
-                    String[] splitXosc = scenarioOsc.split("/");
-                    String xoscName = splitXosc[splitXosc.length - 1];
-                    String[] xoscNameSplit = xoscName.split("\\.");
-                    String xoscSuffix = xoscNameSplit[xoscNameSplit.length - 1];
-                    String xoscPathOfLinux = linuxTempPath + "video/" + projectId + "/" + taskId + "/" + xoscName;
-                    String xoscPathOfMinio = projectResultPathOfMinio + projectId + "/" + taskId + "/" + taskId + "." + xoscSuffix;
-                    MinioUtil.downloadToFile(minioClient, bucketName, scenarioOsc, xoscPathOfLinux);
-                    MinioUtil.uploadFromFile(minioClient, xoscPathOfLinux, bucketName, xoscPathOfMinio);
-
-                    String scenarioOdr = sceneEntity.getScenarioOdr();
-                    String[] splitXodr = scenarioOdr.split("/");
-                    String xodrName = splitXodr[splitXodr.length - 1];
-                    String[] xodrNameSplit = xodrName.split("\\.");
-                    String xodrSuffix = xodrNameSplit[xodrNameSplit.length - 1];
-                    String xodrPathOfLinux = linuxTempPath + "video/" + projectId + "/" + taskId + "/" + xodrName;
-                    String xodrPathOfMinio = projectResultPathOfMinio + projectId + "/" + taskId + "/" + taskId + "." + xodrSuffix;
-                    MinioUtil.downloadToFile(minioClient, bucketName, scenarioOdr, xodrPathOfLinux);
-                    MinioUtil.uploadFromFile(minioClient, xodrPathOfLinux, bucketName, xodrPathOfMinio);
-
-                    String scenarioOsgb = sceneEntity.getScenarioOsgb();
-                    String[] splitOsgb = scenarioOsgb.split("/");
-                    String osgbName = splitOsgb[splitOsgb.length - 1];
-                    String[] osgbNameSplit = osgbName.split("\\.");
-                    String osgbSuffix = osgbNameSplit[osgbNameSplit.length - 1];
-                    String osgbPathOfLinux = linuxTempPath + "video/" + projectId + "/" + taskId + "/" + osgbName;
-                    String osgbPathOfMinio = projectResultPathOfMinio + projectId + "/" + taskId + "/" + taskId + "." + osgbSuffix;
-                    MinioUtil.downloadToFile(minioClient, bucketName, scenarioOsgb, osgbPathOfLinux);
-                    MinioUtil.uploadFromFile(minioClient, osgbPathOfLinux, bucketName, osgbPathOfMinio);
-                    log.info("已经将 xosc、xodr、osgb 上传到 minio 的结果文件目录:" + projectResultPathOfMinio);
-
-                    // 组装 task 消息
-                    // carsim 不需要查询模型参数
-                    TaskMessageEntity taskMessageEntity = TaskMessageEntity.builder()
-                            .info(InfoEntity.builder()
-                                    .project_id(taskEntity.getPId())
-                                    .task_id(taskEntity.getId())
-                                    .task_path(taskEntity.getRunResultFilePath())
-                                    .default_time(videoTime)
-                                    .build())
-                            .scenario(ScenarioEntity.builder()
-                                    .scenario_osc(xoscPathOfMinio)
-                                    .scenario_odr(xodrPathOfMinio)
-                                    .scenario_osgb(osgbPathOfMinio)
-                                    .build())
-                            .vehicle(VehicleTO.builder()
-                                    .model(ModelEntity.builder()
-                                            .model_label(vehicleEntity.getModelLabel())
-                                            .build())
-                                    .dynamics(null)
-                                    .sensors(SensorsEntity.builder()   // 根据 vehicleId 查询绑定的传感器列表
-                                            .camera(cameraEntityList)
-                                            .OGT(ogtEntityList)
-                                            .build())
-                                    .build())
-                            .build();
-
-                    FileUtil.writeStringToLocalFile(JsonUtil.beanToJson(taskMessageEntity), projectPath + taskId + ".json");
-                    log.info("项目 " + projectId + " 将任务消息转成 json 保存到临时目录等待资源分配后执行:" + taskMessageEntity.getInfo().getTask_id());
-                }
-            }
-            taskManager.batchInsertTask(taskList);
-            log.info("项目 " + projectId + " 共有 " + taskList.size() + " 个任务,已保存到数据库");
+        if (CollectionUtil.isEmpty(lastTargetIdList)) {
+          throw new RuntimeException("项目 " + projectId + " 使用的场景测试包 " + sceneId + " 不存在指标。");
         }
-
-        //* -------------------------------- 4 开始排队 --------------------------------
-        cacheProject(projectRecord);
-
-    }
-
-
-    /**
-     * 任务运行前首先判断用户是否拥有可分配资源
-     *
-     * @param projectRecord 项目启动消息
-     */
-    @SneakyThrows
-    public void cacheProject(ConsumerRecord<String, String> projectRecord) {
-        String initialProjectJson = projectRecord.value();
-        log.info("判断用户是否拥有可分配资源:" + initialProjectJson);
-        //1 读取 kafka 的 project 信息
-        ProjectMessageDTO projectMessageDTO = JsonUtil.jsonToBean(initialProjectJson, ProjectMessageDTO.class);
-        String projectId = projectMessageDTO.getProjectId();    // 手动执行项目 id 或 自动执行子项目 id
-        long parallelism = projectMessageDTO.getParallelism();   // 项目并行度
-        String projectType = projectMessageDTO.getType(); // 项目类型
-        //2 根据 projectId 获取创建用户 id
-        String userId;
+        for (String lastTargetId : lastTargetIdList) {
+          String taskId = StringUtil.getRandomUUID();
+          // 保存任务信息
+          TaskEntity taskEntity = TaskEntity.builder() // run_start_time 和 run_end_time 不填
+              .id(taskId).pId(projectId).sceneId(sceneId).lastTargetId(lastTargetId).sceneName(sceneEntity.getName()).sceneType(sceneEntity.getType()).runState(DictConstants.TASK_PENDING).runResultFilePath(projectResultPathOfMinio + projectId + "/" + taskId).build();
+          taskEntity.setCreateTime(TimeUtil.getNowForMysql());
+          taskEntity.setCreateUserId(userId);
+          taskEntity.setModifyTime(TimeUtil.getNowForMysql());
+          taskEntity.setModifyUserId(userId);
+          taskEntity.setModifyTime(TimeUtil.getNowForMysql());
+          taskEntity.setIsDeleted("0");
+          taskList.add(taskEntity);
+          // 将 xosc、xodr、osgb 全部上传到仿真结果路径
+          String scenarioOsc = sceneEntity.getScenarioOsc();
+          String[] splitXosc = scenarioOsc.split("/");
+          String xoscName = splitXosc[splitXosc.length - 1];
+          String[] xoscNameSplit = xoscName.split("\\.");
+          String xoscSuffix = xoscNameSplit[xoscNameSplit.length - 1];
+          String xoscPathOfLinux = linuxTempPath + "video/" + projectId + "/" + taskId + "/" + xoscName;
+          String xoscPathOfMinio = projectResultPathOfMinio + projectId + "/" + taskId + "/" + taskId + "." + xoscSuffix;
+          MinioUtil.downloadToFile(minioClient, bucketName, scenarioOsc, xoscPathOfLinux);
+          MinioUtil.uploadFromFile(minioClient, xoscPathOfLinux, bucketName, xoscPathOfMinio);
+
+          String scenarioOdr = sceneEntity.getScenarioOdr();
+          String[] splitXodr = scenarioOdr.split("/");
+          String xodrName = splitXodr[splitXodr.length - 1];
+          String[] xodrNameSplit = xodrName.split("\\.");
+          String xodrSuffix = xodrNameSplit[xodrNameSplit.length - 1];
+          String xodrPathOfLinux = linuxTempPath + "video/" + projectId + "/" + taskId + "/" + xodrName;
+          String xodrPathOfMinio = projectResultPathOfMinio + projectId + "/" + taskId + "/" + taskId + "." + xodrSuffix;
+          MinioUtil.downloadToFile(minioClient, bucketName, scenarioOdr, xodrPathOfLinux);
+          MinioUtil.uploadFromFile(minioClient, xodrPathOfLinux, bucketName, xodrPathOfMinio);
+
+          String scenarioOsgb = sceneEntity.getScenarioOsgb();
+          String[] splitOsgb = scenarioOsgb.split("/");
+          String osgbName = splitOsgb[splitOsgb.length - 1];
+          String[] osgbNameSplit = osgbName.split("\\.");
+          String osgbSuffix = osgbNameSplit[osgbNameSplit.length - 1];
+          String osgbPathOfLinux = linuxTempPath + "video/" + projectId + "/" + taskId + "/" + osgbName;
+          String osgbPathOfMinio = projectResultPathOfMinio + projectId + "/" + taskId + "/" + taskId + "." + osgbSuffix;
+          MinioUtil.downloadToFile(minioClient, bucketName, scenarioOsgb, osgbPathOfLinux);
+          MinioUtil.uploadFromFile(minioClient, osgbPathOfLinux, bucketName, osgbPathOfMinio);
+          log.info("已经将 xosc、xodr、osgb 上传到 minio 的结果文件目录:" + projectResultPathOfMinio);
+
+          // 组装 task 消息
+          TaskMessageEntity taskMessageEntity = TaskMessageEntity.builder().info(InfoEntity.builder().project_id(taskEntity.getPId()).task_id(taskEntity.getId()).task_path(taskEntity.getRunResultFilePath()).default_time(videoTime).build()).scenario(ScenarioEntity.builder().scenario_osc(xoscPathOfMinio).scenario_odr(xodrPathOfMinio).scenario_osgb(osgbPathOfMinio).build()).vehicle(VehicleTO.builder().model(ModelEntity.builder().model_label(vehicleEntity.getModelLabel()).build()).dynamics(DynamicsTO.builder().dynamics_maxspeed(vehicleEntity.getMaxSpeed()).dynamics_enginepower(vehicleEntity.getEnginePower()).dynamics_maxdecel(vehicleEntity.getMaxDeceleration()).dynamics_maxsteering(vehicleEntity.getMaxSteeringAngle()).dynamics_mass(vehicleEntity.getMass()).dynamics_frontsurfaceeffective(vehicleEntity.getFrontSurfaceEffective()).dynamics_airdragcoefficient(vehicleEntity.getAirDragCoefficient()).dynamics_rollingresistance(vehicleEntity.getRollingResistanceCoefficient()).dynamics_wheeldiameter(vehicleEntity.getWheelDiameter()).dynamics_wheeldrive(vehicleEntity.getWheelDrive()).dynamics_overallefficiency(vehicleEntity.getOverallEfficiency()).dynamics_distfront(vehicleEntity.getFrontDistance()).dynamics_distrear(vehicleEntity.getRearDistance()).dynamics_distleft(vehicleEntity.getLeftDistance()).dynamics_distright(vehicleEntity.getRightDistance()).dynamics_distheight(vehicleEntity.getHeightDistance()).dynamics_wheelbase(vehicleEntity.getWheelbase()).build()).sensors(SensorsEntity.builder()   // 根据 vehicleId 查询绑定的传感器列表
+              .camera(cameraEntityList).OGT(ogtEntityList).build()).build()).build();
+          FileUtil.writeStringToLocalFile(JsonUtil.beanToJson(taskMessageEntity), projectPath + taskId + ".json");
+          log.info("项目 " + projectId + " 将任务消息转成 json 保存到临时目录等待资源分配后执行:" + taskMessageEntity.getInfo().getTask_id());
+        }
+      }
+      taskManager.batchInsertTask(taskList);
+      log.info("项目 " + projectId + " 共有 " + taskList.size() + " 个任务,已保存到数据库");
+    } else if ("2".equals(modelType)) {
+      log.info("项目 " + projectId + " 开始查询模型。");
+
+      VehicleEntity vehicleEntity = vehicleMapper.selectByVehicleConfigId(vehicleConfigId);   // 车辆
+      List<CameraEntity> cameraEntityList = sensorCameraMapper.selectCameraByVehicleConfigId(vehicleConfigId);    // 摄像头
+      List<OgtEntity> ogtEntityList = sensorOgtMapper.selectOgtByVehicleId(vehicleConfigId); // 完美传感器
+      // -------------------------------- 4 保存任务消息 --------------------------------
+      log.info("项目 " + projectId + " 开始保存任务消息。");
+      List<TaskEntity> taskList = new ArrayList<>();
+      for (SceneEntity sceneEntity : sceneEntitySet) {
+        String sceneId = sceneEntity.getId();
+        //3-1 可能会存在多个指标下有同样的场景,所以会查出多个指标,多个指标的场景需要发送多次
+        List<String> lastTargetIdList = null;
         if (DictConstants.PROJECT_TYPE_MANUAL.equals(projectType)) {
-            userId = manualProjectMapper.selectCreateUserById(projectId);
+          lastTargetIdList = indexMapper.selectLeafIndexIdByManualProjectIdAndSceneId(projectId, "%" + sceneId + "%");
         } else if (DictConstants.PROJECT_TYPE_AUTO_SUB.equals(projectType)) {
-            userId = autoSubProjectMapper.selectCreateUserById(projectId);
-        } else {
-            log.error("项目类型错误:" + initialProjectJson);
-            return;
+          lastTargetIdList = indexMapper.selectLeafIndexIdByAutoSubProjectIdAndSceneId(projectId, "%" + sceneId + "%");
         }
-        if (StringUtil.isEmpty(userId)) {
-            log.error("未查询到项目创建人:" + initialProjectJson);
-            return;
+        if (CollectionUtil.isEmpty(lastTargetIdList)) {
+          throw new RuntimeException("项目 " + projectId + " 使用的场景测试包 " + sceneId + " 不存在指标。");
         }
-        //3 获取用户类型(管理员账户、管理员子账户、普通账户、普通子账户)(独占、共享)
-        UserEntity userEntity = userMapper.selectById(userId);
-        log.info("项目 " + projectId + " 的创建人为:" + userEntity);
-        String roleCode = userEntity.getRoleCode();
-        String useType = userEntity.getUseType();
-        ClusterEntity clusterEntity;
-        if (DictConstants.ROLE_CODE_SYSADMIN.equals(roleCode) || DictConstants.ROLE_CODE_ADMIN.equals(roleCode)) {  //3-1 管理员账户和管理员子账户直接执行
-            log.info("项目 " + projectId + " 的创建人 " + userId + " 为管理员账户或管理员子账户,直接判断服务器能否执行。");
-            PrefixEntity redisPrefix = projectUtil.getRedisPrefixByClusterIdAndProjectId(DictConstants.SYSTEM_CLUSTER_ID, projectId);
-            run(projectMessageDTO, DictConstants.SYSTEM_CLUSTER_ID, redisPrefix.getProjectRunningKey(), redisPrefix.getProjectWaitingKey());
-            return;
-        } else if (DictConstants.ROLE_CODE_UESR.equals(roleCode)) { //3-2 普通账户,不管是独占还是共享,都在自己的集群里排队,根据自己的独占节点排队
-            clusterEntity = clusterMapper.selectByUserId(userId);
-            log.info("项目 " + projectId + " 的创建人 " + userId + " 为普通账户(包括独占或共享都在自己的集群),集群为:" + clusterEntity);
-        } else if (DictConstants.ROLE_CODE_SUBUESR.equals(roleCode)) {
-            if (DictConstants.USER_TYPE_EXCLUSIVE.equals(useType)) {   //3-3 普通子账户,根据自己的独占节点排队
-                clusterEntity = clusterMapper.selectByUserId(userId);
-                log.info("项目 " + projectId + " 的创建人 " + userId + " 为普通独占子账户(自己的集群),集群为:" + clusterEntity);
-            } else {    //3-4 共享子账户,根据父账户的共享节点排队
-                String parentUserId = userEntity.getCreateUserId();
-                clusterEntity = clusterMapper.selectByUserId(parentUserId);
-                log.info("项目 " + projectId + " 的创建人 " + userId + " 为普通共享子账户(父账户的集群),集群为:" + clusterEntity);
-            }
-        } else {
-            log.error("项目 " + projectId + " 的创建人 " + userId + " 为未知账户类型,不予执行!");
-            return;
-        }
-        // 获取拥有的节点数量,即仿真软件证书数量
-        String clusterId = clusterEntity.getId();
-        int simulationLicenseNumber = clusterEntity.getNumSimulationLicense();
-        // 获取该集群中正在运行的项目,如果没有则立即执行
-        PrefixEntity redisPrefix = projectUtil.getRedisPrefixByClusterIdAndProjectId(clusterId, projectId);
-        // 获取正在运行的项目的并行度总和
-        int currentParallelismSum = projectUtil.getCurrentParallelismSum(redisPrefix.getClusterRunningPrefix());
-        // 如果执行后的并行度总和小于最大节点数则执行,否则不执行
-        if (currentParallelismSum + parallelism <= simulationLicenseNumber) {
-            run(projectMessageDTO, clusterId, redisPrefix.getProjectRunningKey(), redisPrefix.getProjectWaitingKey());
-        } else {
-            log.info("项目 " + projectId + " 并行度超出账户允许,加入等待队列,暂不执行。 ");
-            wait(redisPrefix.getProjectWaitingKey(), projectMessageDTO);
+        for (String lastTargetId : lastTargetIdList) {
+          String taskId = StringUtil.getRandomUUID();
+          // 保存任务信息
+          TaskEntity taskEntity = TaskEntity.builder() // run_start_time 和 run_end_time 不填
+              .id(taskId).pId(projectId).sceneId(sceneId).lastTargetId(lastTargetId).sceneName(sceneEntity.getName()).sceneType(sceneEntity.getType()).runState(DictConstants.TASK_PENDING).runResultFilePath(projectResultPathOfMinio + projectId + "/" + taskId).build();
+          taskEntity.setCreateTime(TimeUtil.getNowForMysql());
+          taskEntity.setCreateUserId(userId);
+          taskEntity.setModifyTime(TimeUtil.getNowForMysql());
+          taskEntity.setModifyUserId(userId);
+          taskEntity.setModifyTime(TimeUtil.getNowForMysql());
+          taskEntity.setIsDeleted("0");
+          taskList.add(taskEntity);
+          // 将 xosc、xodr、osgb 全部上传到仿真结果路径
+          String scenarioOsc = sceneEntity.getScenarioOsc();
+          String[] splitXosc = scenarioOsc.split("/");
+          String xoscName = splitXosc[splitXosc.length - 1];
+          String[] xoscNameSplit = xoscName.split("\\.");
+          String xoscSuffix = xoscNameSplit[xoscNameSplit.length - 1];
+          String xoscPathOfLinux = linuxTempPath + "video/" + projectId + "/" + taskId + "/" + xoscName;
+          String xoscPathOfMinio = projectResultPathOfMinio + projectId + "/" + taskId + "/" + taskId + "." + xoscSuffix;
+          MinioUtil.downloadToFile(minioClient, bucketName, scenarioOsc, xoscPathOfLinux);
+          MinioUtil.uploadFromFile(minioClient, xoscPathOfLinux, bucketName, xoscPathOfMinio);
+
+          String scenarioOdr = sceneEntity.getScenarioOdr();
+          String[] splitXodr = scenarioOdr.split("/");
+          String xodrName = splitXodr[splitXodr.length - 1];
+          String[] xodrNameSplit = xodrName.split("\\.");
+          String xodrSuffix = xodrNameSplit[xodrNameSplit.length - 1];
+          String xodrPathOfLinux = linuxTempPath + "video/" + projectId + "/" + taskId + "/" + xodrName;
+          String xodrPathOfMinio = projectResultPathOfMinio + projectId + "/" + taskId + "/" + taskId + "." + xodrSuffix;
+          MinioUtil.downloadToFile(minioClient, bucketName, scenarioOdr, xodrPathOfLinux);
+          MinioUtil.uploadFromFile(minioClient, xodrPathOfLinux, bucketName, xodrPathOfMinio);
+
+          String scenarioOsgb = sceneEntity.getScenarioOsgb();
+          String[] splitOsgb = scenarioOsgb.split("/");
+          String osgbName = splitOsgb[splitOsgb.length - 1];
+          String[] osgbNameSplit = osgbName.split("\\.");
+          String osgbSuffix = osgbNameSplit[osgbNameSplit.length - 1];
+          String osgbPathOfLinux = linuxTempPath + "video/" + projectId + "/" + taskId + "/" + osgbName;
+          String osgbPathOfMinio = projectResultPathOfMinio + projectId + "/" + taskId + "/" + taskId + "." + osgbSuffix;
+          MinioUtil.downloadToFile(minioClient, bucketName, scenarioOsgb, osgbPathOfLinux);
+          MinioUtil.uploadFromFile(minioClient, osgbPathOfLinux, bucketName, osgbPathOfMinio);
+          log.info("已经将 xosc、xodr、osgb 上传到 minio 的结果文件目录:" + projectResultPathOfMinio);
+
+          // 组装 task 消息
+          // carsim 不需要查询模型参数
+          TaskMessageEntity taskMessageEntity = TaskMessageEntity.builder().info(InfoEntity.builder().project_id(taskEntity.getPId()).task_id(taskEntity.getId()).task_path(taskEntity.getRunResultFilePath()).default_time(videoTime).build()).scenario(ScenarioEntity.builder().scenario_osc(xoscPathOfMinio).scenario_odr(xodrPathOfMinio).scenario_osgb(osgbPathOfMinio).build()).vehicle(VehicleTO.builder().model(ModelEntity.builder().model_label(vehicleEntity.getModelLabel()).build()).dynamics(null).sensors(SensorsEntity.builder()   // 根据 vehicleId 查询绑定的传感器列表
+              .camera(cameraEntityList).OGT(ogtEntityList).build()).build()).build();
+
+          FileUtil.writeStringToLocalFile(JsonUtil.beanToJson(taskMessageEntity), projectPath + taskId + ".json");
+          log.info("项目 " + projectId + " 将任务消息转成 json 保存到临时目录等待资源分配后执行:" + taskMessageEntity.getInfo().getTask_id());
         }
+      }
+      taskManager.batchInsertTask(taskList);
+      log.info("项目 " + projectId + " 共有 " + taskList.size() + " 个任务,已保存到数据库");
     }
 
-    //* -------------------------------- 运行 --------------------------------
-
-    /**
-     * @param projectMessageDTO 初始接收到的项目启动信息
-     * @param clusterId         集群 id
-     * @param projectRunningKey projectRunningKey
-     * @param projectWaitingKey projectWaitingKey
-     */
-    public void run(ProjectMessageDTO projectMessageDTO, String clusterId, String projectRunningKey, String projectWaitingKey) {
-
-        String projectId = projectMessageDTO.getProjectId();
-        int parallelism = projectMessageDTO.getParallelism();  // 期望并行度
-        //1 获取集群剩余可用并行度
-        int restParallelism = projectUtil.getRestParallelism();
-        //2 判断剩余可用并行度是否大于项目并行度,否则加入扩充队列
-        if (restParallelism > 0L) {
-            log.info("集群 " + clusterId + " 执行项目 " + projectId);
-            // 设置实际的并行度
-            projectMessageDTO.setCurrentParallelism(Math.min(restParallelism, parallelism));   // 设置实际的并行度
-            parseProject(projectMessageDTO, projectRunningKey);
-        } else {
-            log.info("服务器资源不够,项目 " + projectId + " 暂时加入等待队列。");
-            wait(projectWaitingKey, projectMessageDTO);
-        }
+    //* -------------------------------- 4 开始排队 --------------------------------
+    cacheProject(projectMessageDTO);
+
+  }
+
+
+  /**
+   * 任务运行前首先判断用户是否拥有可分配资源
+   *
+   * @param projectMessageDTO 项目启动消息
+   */
+  @SneakyThrows
+  public void cacheProject(ProjectMessageDTO projectMessageDTO) {
+    log.info("判断用户是否拥有可分配资源:" + projectMessageDTO);
+    //1 读取 kafka 的 project 信息
+    String projectId = projectMessageDTO.getProjectId();    // 手动执行项目 id 或 自动执行子项目 id
+    long parallelism = projectMessageDTO.getParallelism();   // 项目并行度
+    String projectType = projectMessageDTO.getType(); // 项目类型
+    //2 根据 projectId 获取创建用户 id
+    String userId;
+    if (DictConstants.PROJECT_TYPE_MANUAL.equals(projectType)) {
+      userId = manualProjectMapper.selectCreateUserById(projectId);
+    } else if (DictConstants.PROJECT_TYPE_AUTO_SUB.equals(projectType)) {
+      userId = autoSubProjectMapper.selectCreateUserById(projectId);
+    } else {
+      log.error("项目类型错误:" + projectMessageDTO);
+      return;
     }
-
-    /**
-     * @param projectMessageDTO 初始接收到的项目启动信息
-     * @param projectRunningKey projectRunningKey
-     */
-    @SneakyThrows
-    public void parseProject(ProjectMessageDTO projectMessageDTO, String projectRunningKey) {
-        String projectId = projectMessageDTO.getProjectId();    // 项目 id
-        String modelType = projectMessageDTO.getModelType();
-        String vehicleConfigId = projectMessageDTO.getVehicleConfigId();
-        ProjectEntity projectEntity = projectUtil.getProjectByProjectId(projectId);
-        String isChoiceGpu = projectEntity.getIsChoiceGpu();
-        int currentParallelism = projectMessageDTO.getCurrentParallelism();   // 当前并行度
-        String algorithmId = projectMessageDTO.getAlgorithmId();    // 算法 id
-        String projectPath = linuxTempPath + "project/" + projectId + "/";
-        // -------------------------------- 1 获取任务 json 列表 --------------------------------
-        List<String> taskJsonList = FileUtil.listAbsolutePathByTypeAndLength(projectPath, "json", 37);
-        int taskTotal = taskJsonList.size();
-        projectMessageDTO.setTaskTotal(taskTotal);
-        projectMessageDTO.setTaskCompleted(0);
-        // 设置任务数量之后,获取运行节点,并将项目运行信息放入 redis
-        //1 获取剩余并行度和即将使用的各node的并行度
-        Map<String, Integer> nodeMap0 = projectUtil.getNodeMap();
-        Map<String, Integer> nodeMap = projectUtil.getNodeMapToUse(Math.min(currentParallelism, taskTotal));
-        //2 将指定 node 的并行度减少
-        nodeMap.keySet().forEach(nodeName -> projectUtil.decrementParallelismOfGpuNode(nodeName, nodeMap.get(nodeName)));
-        // 重新设置实际使用的并行度并保存到 redis
-        int realCurrentParallelism = nodeMap.values().stream().mapToInt(parallelism -> parallelism).sum();
-        projectMessageDTO.setCurrentParallelism(realCurrentParallelism);
-        log.info("项目 " + projectId + " 运行在:" + nodeMap);
-        stringRedisTemplate.opsForValue().set(projectRunningKey, JsonUtil.beanToJson(projectMessageDTO));
-        //* -------------------------------- 3 根据算法id查询算法名称 --------------------------------
-        String algorithmDockerImage = algorithmMapper.selectDockerImageById(algorithmId);
-        // -------------------------------- 4 发送任务消息 --------------------------------
-        List<NodeEntity> nodeListToCount = projectUtil.getNodeListToCount(nodeMap);
-        int messageNumber = 0;
-        ApacheKafkaUtil.createTopic(kafkaAdminClient, projectId, realCurrentParallelism, (short) 1);   // 创建主题
-        TimeUnit.SECONDS.sleep(7);
-        // 需要即时启动的任务(并行度的大小)
-        CopyOnWriteArrayList<String> yamlToRunRedisKeyList = new CopyOnWriteArrayList<>();
-        for (String taskJsonPath : taskJsonList) {
-            String taskId = FileUtil.getFilenameWithoutSuffix(taskJsonPath);
-            // 保存运行中的任务信息
-            String taskMessageKey = projectRunningKey + ":task:" + taskId + ":message";
-            String taskJson = FileUtil.read(taskJsonPath);
-            stringRedisTemplate.opsForValue().set(taskMessageKey, taskJson);
-
-            //4-5 将 projectId 作为 topic 名称,根据 parallelism 分散发送 task 信息到 kafka
-            SendResult<String, String> stringStringSendResult = kafkaTemplate.send(projectId, messageNumber % currentParallelism, taskId, taskJson).get();
-            RecordMetadata recordMetadata = stringStringSendResult.getRecordMetadata();
-            String topic = recordMetadata.topic();  // 消息发送到的topic
-            int partition = recordMetadata.partition(); // 消息发送到的分区
-            long offset = recordMetadata.offset();  // 消息在分区内的offset
-            log.info("发送消息成功, 主题 topic 为:" + topic + " 分区 partition 为:" + partition + " 偏移量为:" + offset + " 消息体为:" + taskJson);
-            //4-6 发送成功过的同时创建 pod.yaml 文件并把文件地址存到 redis
-            // 选一个 count 最少的 node
-            String currentNodeName = "";
-            NodeEntity currentNodeEntity = null;
-            int currentCount = Integer.MAX_VALUE;
-            log.info("各节点已经预定的任务个数为:" + nodeListToCount);
-            for (NodeEntity nodeEntity : nodeListToCount) {
-                int tempCount = nodeEntity.getCount();
-                String tempNodeName = nodeEntity.getNodeName();
-                if (tempCount < currentCount) {
-                    currentCount = tempCount;
-                    currentNodeName = tempNodeName;
-                    currentNodeEntity = nodeEntity;
-                }
-            }
-            if (currentNodeEntity == null) {
-                String errorMessage = "挑选节点失败。";
-                log.info(errorMessage);
-                throw new RuntimeException(errorMessage);
-            }
-            currentNodeEntity.setCount(currentNodeEntity.getCount() + 1);
-            Integer cpuOrder = null;
-            if (currentCount == 0) {
-                // 根据各节点剩余并行度,倒序获取 cpu 编号
-                cpuOrder = nodeMap0.get(currentNodeName) - 1;
-                nodeMap0.put(currentNodeName, cpuOrder);
-            }
-            // 只有准备启动(即 currentCount == 0)的时候才指定 cpu 编号
-            log.info("创建任务 " + taskId + " 的 yaml:是否使用 gpu (0是1否)" + isChoiceGpu + ",当前节点已创建 yaml 个数为:" + currentCount + ",当前节点名称为:" + currentNodeName + ",当前 cpu 编号为:" + cpuOrder);
-            String yamlRedisKey = projectManager.createTempYaml(projectId, vehicleConfigId, modelType, algorithmDockerImage, currentNodeName, partition, offset, isChoiceGpu, cpuOrder);
-
-            if (currentCount == 0) {
-                String podName = yamlRedisKey.split(":")[yamlRedisKey.split(":").length - 1];
-                log.info("将 pod 加入到启动列表 " + podName);
-                yamlToRunRedisKeyList.add(yamlRedisKey);
-            }
-            messageNumber++;
-        }
-        TimeUnit.SECONDS.sleep(6);
-        log.info("项目 " + projectId + " 共发送了 " + messageNumber + " 条消息,准备首先启动 " + yamlToRunRedisKeyList);
-        for (String redisKey : yamlToRunRedisKeyList) {
-            projectUtil.createPodBegin(projectId, redisKey);
-        }
-        log.info("项目 " + projectId + " 已经启动 " + yamlToRunRedisKeyList);
+    if (StringUtil.isEmpty(userId)) {
+      log.error("未查询到项目创建人:" + projectMessageDTO);
+      return;
     }
-
-
-    //* -------------------------------- 等待 --------------------------------
-
-    /**
-     * @param projectWaitingKey 项目等待 key
-     * @param projectMessageDTO 项目信息
-     */
-    public void wait(String projectWaitingKey, ProjectMessageDTO projectMessageDTO) {
-        stringRedisTemplate.opsForValue().set(projectWaitingKey, JsonUtil.beanToJson(projectMessageDTO));
+    //3 获取用户类型(管理员账户、管理员子账户、普通账户、普通子账户)(独占、共享)
+    UserEntity userEntity = userMapper.selectById(userId);
+    log.info("项目 " + projectId + " 的创建人为:" + userEntity);
+    String roleCode = userEntity.getRoleCode();
+    String useType = userEntity.getUseType();
+    ClusterEntity clusterEntity;
+    if (DictConstants.ROLE_CODE_SYSADMIN.equals(roleCode) || DictConstants.ROLE_CODE_ADMIN.equals(roleCode)) {  //3-1 管理员账户和管理员子账户直接执行
+      log.info("项目 " + projectId + " 的创建人 " + userId + " 为管理员账户或管理员子账户,直接判断服务器能否执行。");
+      PrefixEntity redisPrefix = projectUtil.getRedisPrefixByClusterIdAndProjectId(DictConstants.SYSTEM_CLUSTER_ID, projectId);
+      run(projectMessageDTO, DictConstants.SYSTEM_CLUSTER_ID, redisPrefix.getProjectRunningKey(), redisPrefix.getProjectWaitingKey());
+      return;
+    } else if (DictConstants.ROLE_CODE_UESR.equals(roleCode)) { //3-2 普通账户,不管是独占还是共享,都在自己的集群里排队,根据自己的独占节点排队
+      clusterEntity = clusterMapper.selectByUserId(userId);
+      log.info("项目 " + projectId + " 的创建人 " + userId + " 为普通账户(包括独占或共享都在自己的集群),集群为:" + clusterEntity);
+    } else if (DictConstants.ROLE_CODE_SUBUESR.equals(roleCode)) {
+      if (DictConstants.USER_TYPE_EXCLUSIVE.equals(useType)) {   //3-3 普通子账户,根据自己的独占节点排队
+        clusterEntity = clusterMapper.selectByUserId(userId);
+        log.info("项目 " + projectId + " 的创建人 " + userId + " 为普通独占子账户(自己的集群),集群为:" + clusterEntity);
+      } else {    //3-4 共享子账户,根据父账户的共享节点排队
+        String parentUserId = userEntity.getCreateUserId();
+        clusterEntity = clusterMapper.selectByUserId(parentUserId);
+        log.info("项目 " + projectId + " 的创建人 " + userId + " 为普通共享子账户(父账户的集群),集群为:" + clusterEntity);
+      }
+    } else {
+      log.error("项目 " + projectId + " 的创建人 " + userId + " 为未知账户类型,不予执行!");
+      return;
+    }
+    // 获取拥有的节点数量,即仿真软件证书数量
+    String clusterId = clusterEntity.getId();
+    int simulationLicenseNumber = clusterEntity.getNumSimulationLicense();
+    // 获取该集群中正在运行的项目,如果没有则立即执行
+    PrefixEntity redisPrefix = projectUtil.getRedisPrefixByClusterIdAndProjectId(clusterId, projectId);
+    // 获取正在运行的项目的并行度总和
+    int currentParallelismSum = projectUtil.getCurrentParallelismSum(redisPrefix.getClusterRunningPrefix());
+    // 如果执行后的并行度总和小于最大节点数则执行,否则不执行
+    if (currentParallelismSum + parallelism <= simulationLicenseNumber) {
+      run(projectMessageDTO, clusterId, redisPrefix.getProjectRunningKey(), redisPrefix.getProjectWaitingKey());
+    } else {
+      log.info("项目 " + projectId + " 并行度超出账户允许,加入等待队列,暂不执行。 ");
+      wait(redisPrefix.getProjectWaitingKey(), projectMessageDTO);
+    }
+  }
+
+  //* -------------------------------- 运行 --------------------------------
+
+  /**
+   * @param projectMessageDTO 初始接收到的项目启动信息
+   * @param clusterId         集群 id
+   * @param projectRunningKey projectRunningKey
+   * @param projectWaitingKey projectWaitingKey
+   */
+  public void run(ProjectMessageDTO projectMessageDTO, String clusterId, String projectRunningKey, String projectWaitingKey) {
+
+    String projectId = projectMessageDTO.getProjectId();
+    int parallelism = projectMessageDTO.getParallelism();  // 期望并行度
+    //1 获取集群剩余可用并行度
+    int restParallelism = projectUtil.getRestParallelism();
+    //2 判断剩余可用并行度是否大于项目并行度,否则加入扩充队列
+    if (restParallelism > 0L) {
+      log.info("集群 " + clusterId + " 执行项目 " + projectId);
+      // 设置实际的并行度
+      projectMessageDTO.setCurrentParallelism(Math.min(restParallelism, parallelism));   // 设置实际的并行度
+      parseProject(projectMessageDTO, projectRunningKey);
+    } else {
+      log.info("服务器资源不够,项目 " + projectId + " 暂时加入等待队列。");
+      wait(projectWaitingKey, projectMessageDTO);
     }
-    //* -------------------------------- 结束 --------------------------------
-
-    /**
-     * {
-     * "projectId": "sadfasdfs",	// 项目 id
-     * "type": "1",	// 项目类型
-     * }
-     */
-    @KafkaListener(groupId = "simulation-resource-scheduler", topics = "${scheduler.stop-topic}")
-    @SneakyThrows
-    public void stopProject(ConsumerRecord<String, String> stopRecord) {
-        log.info("接收到的项目终止消息为:" + stopRecord);
-        //1 读取 kafka 的项目停止信息
-        String json = stopRecord.value();
-        ObjectMapper objectMapper = new ObjectMapper();
-        JsonNode jsonNode = objectMapper.readTree(json);
-        // 将项目状态修改为终止中
-        String projectId = jsonNode.path("projectId").asText();
-        String type = jsonNode.path("type").asText();
-        if (DictConstants.PROJECT_TYPE_MANUAL.equals(type)) {
-            manualProjectMapper.updateProjectState(projectId, DictConstants.PROJECT_TERMINATING, TimeUtil.getNowForMysql());
-        } else if (DictConstants.PROJECT_TYPE_AUTO_SUB.equals(type)) {
-            autoSubProjectMapper.updateProjectState(projectId, DictConstants.PROJECT_TERMINATING, TimeUtil.getNowForMysql());
+  }
+
+  /**
+   * @param projectMessageDTO 初始接收到的项目启动信息
+   * @param projectRunningKey projectRunningKey
+   */
+  @SneakyThrows
+  public void parseProject(ProjectMessageDTO projectMessageDTO, String projectRunningKey) {
+    String projectId = projectMessageDTO.getProjectId();    // 项目 id
+    String modelType = projectMessageDTO.getModelType();
+    String vehicleConfigId = projectMessageDTO.getVehicleConfigId();
+    ProjectEntity projectEntity = projectUtil.getProjectByProjectId(projectId);
+    String isChoiceGpu = projectEntity.getIsChoiceGpu();
+    int currentParallelism = projectMessageDTO.getCurrentParallelism();   // 当前并行度
+    String algorithmId = projectMessageDTO.getAlgorithmId();    // 算法 id
+    String projectPath = linuxTempPath + "project/" + projectId + "/";
+    // -------------------------------- 1 获取任务 json 列表 --------------------------------
+    List<String> taskJsonList = FileUtil.listAbsolutePathByTypeAndLength(projectPath, "json", 37);
+    int taskTotal = taskJsonList.size();
+    projectMessageDTO.setTaskTotal(taskTotal);
+    projectMessageDTO.setTaskCompleted(0);
+    // 设置任务数量之后,获取运行节点,并将项目运行信息放入 redis
+    //1 获取剩余并行度和即将使用的各node的并行度
+    Map<String, Integer> nodeMap0 = projectUtil.getNodeMap();
+    Map<String, Integer> nodeMap = projectUtil.getNodeMapToUse(Math.min(currentParallelism, taskTotal));
+    //2 将指定 node 的并行度减少
+    nodeMap.keySet().forEach(nodeName -> projectUtil.decrementParallelismOfGpuNode(nodeName, nodeMap.get(nodeName)));
+    // 重新设置实际使用的并行度并保存到 redis
+    int realCurrentParallelism = nodeMap.values().stream().mapToInt(parallelism -> parallelism).sum();
+    projectMessageDTO.setCurrentParallelism(realCurrentParallelism);
+    log.info("项目 " + projectId + " 运行在:" + nodeMap);
+    stringRedisTemplate.opsForValue().set(projectRunningKey, JsonUtil.beanToJson(projectMessageDTO));
+    //* -------------------------------- 3 根据算法id查询算法名称 --------------------------------
+    String algorithmDockerImage = algorithmMapper.selectDockerImageById(algorithmId);
+    // -------------------------------- 4 发送任务消息 --------------------------------
+    List<NodeEntity> nodeListToCount = projectUtil.getNodeListToCount(nodeMap);
+    int messageNumber = 0;
+    ApacheKafkaUtil.createTopic(kafkaAdminClient, projectId, realCurrentParallelism, (short) 1);   // 创建主题
+    TimeUnit.SECONDS.sleep(7);
+    // 需要即时启动的任务(并行度的大小)
+    CopyOnWriteArrayList<String> yamlToRunRedisKeyList = new CopyOnWriteArrayList<>();
+    for (String taskJsonPath : taskJsonList) {
+      String taskId = FileUtil.getFilenameWithoutSuffix(taskJsonPath);
+      // 保存运行中的任务信息
+      String taskMessageKey = projectRunningKey + ":task:" + taskId + ":message";
+      String taskJson = FileUtil.read(taskJsonPath);
+      stringRedisTemplate.opsForValue().set(taskMessageKey, taskJson);
+
+      //4-5 将 projectId 作为 topic 名称,根据 parallelism 分散发送 task 信息到 kafka
+      SendResult<String, String> stringStringSendResult = kafkaTemplate.send(projectId, messageNumber % currentParallelism, taskId, taskJson).get();
+      RecordMetadata recordMetadata = stringStringSendResult.getRecordMetadata();
+      String topic = recordMetadata.topic();  // 消息发送到的topic
+      int partition = recordMetadata.partition(); // 消息发送到的分区
+      long offset = recordMetadata.offset();  // 消息在分区内的offset
+      log.info("发送消息成功, 主题 topic 为:" + topic + " 分区 partition 为:" + partition + " 偏移量为:" + offset + " 消息体为:" + taskJson);
+      //4-6 发送成功过的同时创建 pod.yaml 文件并把文件地址存到 redis
+      // 选一个 count 最少的 node
+      String currentNodeName = "";
+      NodeEntity currentNodeEntity = null;
+      int currentCount = Integer.MAX_VALUE;
+      log.info("各节点已经预定的任务个数为:" + nodeListToCount);
+      for (NodeEntity nodeEntity : nodeListToCount) {
+        int tempCount = nodeEntity.getCount();
+        String tempNodeName = nodeEntity.getNodeName();
+        if (tempCount < currentCount) {
+          currentCount = tempCount;
+          currentNodeName = tempNodeName;
+          currentNodeEntity = nodeEntity;
         }
-        projectService.stopProject(projectId, type);
+      }
+      if (currentNodeEntity == null) {
+        String errorMessage = "挑选节点失败。";
+        log.info(errorMessage);
+        throw new RuntimeException(errorMessage);
+      }
+      currentNodeEntity.setCount(currentNodeEntity.getCount() + 1);
+      Integer cpuOrder = null;
+      if (currentCount == 0) {
+        // 根据各节点剩余并行度,倒序获取 cpu 编号
+        cpuOrder = nodeMap0.get(currentNodeName) - 1;
+        nodeMap0.put(currentNodeName, cpuOrder);
+      }
+      // 只有准备启动(即 currentCount == 0)的时候才指定 cpu 编号
+      log.info("创建任务 " + taskId + " 的 yaml:是否使用 gpu (0是1否)" + isChoiceGpu + ",当前节点已创建 yaml 个数为:" + currentCount + ",当前节点名称为:" + currentNodeName + ",当前 cpu 编号为:" + cpuOrder);
+      String yamlRedisKey = projectManager.createTempYaml(projectId, vehicleConfigId, modelType, algorithmDockerImage, currentNodeName, partition, offset, isChoiceGpu, cpuOrder);
+
+      if (currentCount == 0) {
+        String podName = yamlRedisKey.split(":")[yamlRedisKey.split(":").length - 1];
+        log.info("将 pod 加入到启动列表 " + podName);
+        yamlToRunRedisKeyList.add(yamlRedisKey);
+      }
+      messageNumber++;
+    }
+    TimeUnit.SECONDS.sleep(6);
+    log.info("项目 " + projectId + " 共发送了 " + messageNumber + " 条消息,准备首先启动 " + yamlToRunRedisKeyList);
+    for (String redisKey : yamlToRunRedisKeyList) {
+      projectUtil.createPodBegin(projectId, redisKey);
+    }
+    log.info("项目 " + projectId + " 已经启动 " + yamlToRunRedisKeyList);
+  }
+
+
+  //* -------------------------------- 等待 --------------------------------
+
+  /**
+   * @param projectWaitingKey 项目等待 key
+   * @param projectMessageDTO 项目信息
+   */
+  public void wait(String projectWaitingKey, ProjectMessageDTO projectMessageDTO) {
+    stringRedisTemplate.opsForValue().set(projectWaitingKey, JsonUtil.beanToJson(projectMessageDTO));
+  }
+  //* -------------------------------- 结束 --------------------------------
+
+  /**
+   * {
+   * "projectId": "sadfasdfs",	// 项目 id
+   * "type": "1",	// 项目类型
+   * }
+   */
+  @KafkaListener(groupId = "simulation-resource-scheduler", topics = "${scheduler.stop-topic}")
+  @SneakyThrows
+  public void stopProject(ConsumerRecord<String, String> stopRecord) {
+    log.info("接收到的项目终止消息为:" + stopRecord);
+    //1 读取 kafka 的项目停止信息
+    String json = stopRecord.value();
+    ObjectMapper objectMapper = new ObjectMapper();
+    JsonNode jsonNode = objectMapper.readTree(json);
+    // 将项目状态修改为终止中
+    String projectId = jsonNode.path("projectId").asText();
+    String type = jsonNode.path("type").asText();
+    if (DictConstants.PROJECT_TYPE_MANUAL.equals(type)) {
+      manualProjectMapper.updateProjectState(projectId, DictConstants.PROJECT_TERMINATING, TimeUtil.getNowForMysql());
+    } else if (DictConstants.PROJECT_TYPE_AUTO_SUB.equals(type)) {
+      autoSubProjectMapper.updateProjectState(projectId, DictConstants.PROJECT_TERMINATING, TimeUtil.getNowForMysql());
     }
+    projectService.stopProject(projectId, type);
+  }
 
 
 }

+ 28 - 30
simulation-resource-scheduler/src/main/java/com/css/simulation/resource/scheduler/controller/TaskController.java

@@ -15,36 +15,34 @@ import javax.annotation.Resource;
 @RequestMapping("/task")
 public class TaskController {
 
-    @Resource
-    private TaskService taskService;
-
-    // -------------------------------- Comment --------------------------------
-
-    /**
-     * 修改任务状态
-     */
-    @GetMapping("/state")
-    public void taskState(@RequestParam("taskId") String taskId,
-                          @RequestParam("state") String state,
-                          @RequestParam("podName") String podName) {
-        taskService.taskState(taskId, state, podName);
-    }
-
-    /**
-     * Pod 的心跳接口
-     */
-    @GetMapping("/tick")
-    public void taskTick(@RequestParam("taskId") String taskId) {
-        taskService.taskTick(taskId);
-    }
-
-    /**
-     * 任务执行前调用该接口,确定该任务没有被终止
-     */
-    @GetMapping("/confirm")
-    public Boolean taskConfirm(@RequestParam("taskId") String taskId) {
-        return taskService.taskConfirm(taskId);
-    }
+  @Resource
+  private TaskService taskService;
+
+  // -------------------------------- Comment --------------------------------
+
+  /**
+   * 修改任务状态
+   */
+  @GetMapping("/state")
+  public void taskState(@RequestParam("taskId") String taskId, @RequestParam("state") String state, @RequestParam("podName") String podName) {
+    taskService.taskState(taskId, state, podName);
+  }
+
+  /**
+   * Pod 的心跳接口
+   */
+  @GetMapping("/tick")
+  public void taskTick(@RequestParam("taskId") String taskId) {
+    taskService.taskTick(taskId);
+  }
+
+  /**
+   * 任务执行前调用该接口,确定该任务没有被终止
+   */
+  @GetMapping("/confirm")
+  public Boolean taskConfirm(@RequestParam("taskId") String taskId) {
+    return taskService.taskConfirm(taskId);
+  }
 
 
 }

+ 376 - 417
simulation-resource-scheduler/src/main/java/com/css/simulation/resource/scheduler/service/TaskManager.java

@@ -35,454 +35,413 @@ import java.util.stream.Collectors;
 @Slf4j
 public class TaskManager {
 
-    @Value("${scheduler.linux-path.pod-yaml-directory}")
-    private String podYamlDirectory;
-    @Value("${minio.bucket-name}")
-    private String bucketName;
-    @Value("${scheduler.linux-path.score-py}")
-    private String pyPath;
-    @Value("${scheduler.linux-path.temp}")
-    private String linuxTempPath;
-    @Value("${simulation-cloud.client-id}")
-    private String clientId;
-    @Value("${simulation-cloud.client-secret}")
-    private String clientSecret;
-    @Value("${simulation-cloud.token-uri}")
-    private String tokenUri;
-    @Value("${simulation-cloud.evaluation-level-uri}")
-    private String evaluationLevelUri;
-    @Value("${scheduler.minio-path.project-result}")
-    private String resultPathMinio;
-    @Resource
-    private StringRedisTemplate stringRedisTemplate;
-    @Resource
-    private TaskMapper taskMapper;
-    @Resource
-    private MinioClient minioClient;
-    @Resource
-    private ManualProjectMapper manualProjectMapper;
-    @Resource
-    private AutoSubProjectMapper autoSubProjectMapper;
-    @Resource
-    private TaskIndexManager taskIndexManager;
-    @Resource
-    private IndexMapper indexMapper;
-    @Resource
-    private ScoringRulesMapper scoringRulesMapper;
-    @Resource
-    private CloseableHttpClient closeableHttpClient;
-    @Resource
-    private RequestConfig requestConfig;
-    @Resource
-    private ProjectUtil projectUtil;
-    @Resource
-    private VideoFeignClient videoFeignClient;
-    @Resource
-    private SqlSessionFactory sqlSessionFactory;
-    @Resource
-    private KubernetesConfiguration kubernetesConfiguration;
-    @Resource
-    private ApiClient apiClient;
-    @Resource(name = "myKafkaAdmin")
-    private Admin admin;
+  @Value("${scheduler.linux-path.pod-yaml-directory}")
+  private String podYamlDirectory;
+  @Value("${minio.bucket-name}")
+  private String bucketName;
+  @Value("${scheduler.linux-path.score-py}")
+  private String pyPath;
+  @Value("${scheduler.linux-path.temp}")
+  private String linuxTempPath;
+  @Value("${simulation-cloud.client-id}")
+  private String clientId;
+  @Value("${simulation-cloud.client-secret}")
+  private String clientSecret;
+  @Value("${simulation-cloud.token-uri}")
+  private String tokenUri;
+  @Value("${simulation-cloud.evaluation-level-uri}")
+  private String evaluationLevelUri;
+  @Value("${scheduler.minio-path.project-result}")
+  private String resultPathMinio;
+  @Resource
+  private StringRedisTemplate stringRedisTemplate;
+  @Resource
+  private TaskMapper taskMapper;
+  @Resource
+  private MinioClient minioClient;
+  @Resource
+  private ManualProjectMapper manualProjectMapper;
+  @Resource
+  private AutoSubProjectMapper autoSubProjectMapper;
+  @Resource
+  private TaskIndexManager taskIndexManager;
+  @Resource
+  private IndexMapper indexMapper;
+  @Resource
+  private ScoringRulesMapper scoringRulesMapper;
+  @Resource
+  private CloseableHttpClient closeableHttpClient;
+  @Resource
+  private RequestConfig requestConfig;
+  @Resource
+  private ProjectUtil projectUtil;
+  @Resource
+  private VideoFeignClient videoFeignClient;
+  @Resource
+  private SqlSessionFactory sqlSessionFactory;
+  @Resource
+  private KubernetesConfiguration kubernetesConfiguration;
+  @Resource
+  private ApiClient apiClient;
+  @Resource(name = "myKafkaAdmin")
+  private Admin admin;
 
-    public void batchInsertTask(List<TaskEntity> taskEntityList) {
-        try (SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH, false)) {
-            TaskMapper taskMapper1 = sqlSession.getMapper(TaskMapper.class);
-            for (TaskEntity taskEntity : taskEntityList) {
-                taskMapper1.insert(taskEntity);
-            }
-            sqlSession.commit();
-        }
+  public void batchInsertTask(List<TaskEntity> taskEntityList) {
+    try (SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH, false)) {
+      TaskMapper taskMapper1 = sqlSession.getMapper(TaskMapper.class);
+      for (TaskEntity taskEntity : taskEntityList) {
+        taskMapper1.insert(taskEntity);
+      }
+      sqlSession.commit();
     }
+  }
 
-    /**
-     * 加事务的话高并发情况下会死锁
-     */
-    @SneakyThrows
-    public boolean isProjectCompleted(PrefixEntity redisPrefix, String projectId, String projectType, String maxSimulationTime, String taskId, String state, String podName) {
-        boolean result;
-        String nodeName = projectUtil.getNodeNameOfPod(projectId, podName);
-        if (DictConstants.TASK_RUNNING.equals(state)) {  // 运行中的 pod 无需删除
-            // 将运行中的任务的 pod 名称放入 redis
-            stringRedisTemplate.opsForValue().set(redisPrefix.getTaskPodKey(), podName);
-            taskTick(taskId); // 刷新一下心跳
-            log.info("修改任务 " + taskId + " 的状态为 " + state + ",pod 名称为:" + podName);
-            taskMapper.updateStateWithStartTime(taskId, state, TimeUtil.getNowForMysql());
-            return false;
-        } else { // 结束的 pod 都直接删除,并判断项目是否完成
-            // -------------------------------- 处理状态 --------------------------------
-            log.info("修改任务 {} 的状态为 {} ,pod 名称为 {} ,并删除 pod。", taskId, state, podName);
-            if (DictConstants.TASK_ABORTED.equals(state)) {
-                String minioPathOfErrorLog = resultPathMinio + projectId + "/" + taskId + "error.log";
-                boolean objectExist = MinioUtil.isObjectExist(minioClient, bucketName, minioPathOfErrorLog);
-                String targetEvaluate;
-                if (objectExist) {
-                    String errorString = MinioUtil.downloadToString(minioClient, bucketName, minioPathOfErrorLog);
-                    String[] lines = errorString.split("\n");
-                    StringBuilder errorMessage = new StringBuilder();
-                    for (String line : lines) {
-                        if (line.startsWith("Original Error")) {
-                            errorMessage.append(line).append("\n");
-                        }
-                        if (line.startsWith("Possible Cause")) {
-                            errorMessage.append(line);
-                            break;
-                        }
-                    }
-                    targetEvaluate = errorMessage.toString();
-                } else {
-                    targetEvaluate = DictConstants.TASK_ERROR_REASON_2;
-                }
-                taskMapper.updateFailStateWithStopTime(taskId, state, TimeUtil.getNowForMysql(), targetEvaluate);
-            } else if (DictConstants.TASK_TERMINATED.equals(state)) {
-                taskMapper.updateFailStateWithStopTime(taskId, state, TimeUtil.getNowForMysql(), DictConstants.TASK_ERROR_REASON_3);
-            } else if (DictConstants.TASK_ANALYSIS.equals(state)) { // 该状态只会获得一次
-                taskMapper.updateSuccessStateWithStopTime(taskId, state, TimeUtil.getNowForMysql());
-                // 查询项目是否使用 gpu 生成视频(0是1否)
-                String isChoiceGpu = projectUtil.getProjectByProjectId(projectId).getIsChoiceGpu();
-                if (DictConstants.VIDEO_GPU.equals(isChoiceGpu)) {
-                    log.info("项目 {} 使用 GPU 生成视频。", projectId);
-                } else if (DictConstants.VIDEO_CPU.equals(isChoiceGpu)) {
-                    log.info("项目 {} 使用 CPU 生成视频。", projectId);
-                    videoFeignClient.generateVideo(projectId, projectType, maxSimulationTime, taskId);
-                } else {
-                    throw new RuntimeException("未设置视频生成。");
-                }
+  /**
+   * 加事务的话高并发情况下会死锁
+   */
+  @SneakyThrows
+  public boolean isProjectCompleted(PrefixEntity redisPrefix, String projectId, String projectType, String maxSimulationTime, String taskId, String state, String podName) {
+    boolean result;
+    String nodeName = projectUtil.getNodeNameOfPod(projectId, podName);
+    if (DictConstants.TASK_RUNNING.equals(state)) {  // 运行中的 pod 无需删除
+      // 将运行中的任务的 pod 名称放入 redis
+      stringRedisTemplate.opsForValue().set(redisPrefix.getTaskPodKey(), podName);
+      taskTick(taskId); // 刷新一下心跳
+      log.info("修改任务 " + taskId + " 的状态为 " + state + ",pod 名称为:" + podName);
+      taskMapper.updateStateWithStartTime(taskId, state, TimeUtil.getNowForMysql());
+      return false;
+    } else { // 结束的 pod 都直接删除,并判断项目是否完成
+      // -------------------------------- 处理状态 --------------------------------
+      log.info("修改任务 {} 的状态为 {} ,pod 名称为 {} ,并删除 pod。", taskId, state, podName);
+      if (DictConstants.TASK_ABORTED.equals(state)) {
+        String minioPathOfErrorLog = resultPathMinio + projectId + "/" + taskId + "error.log";
+        boolean objectExist = MinioUtil.isObjectExist(minioClient, bucketName, minioPathOfErrorLog);
+        String targetEvaluate;
+        if (objectExist) {
+          String errorString = MinioUtil.downloadToString(minioClient, bucketName, minioPathOfErrorLog);
+          String[] lines = errorString.split("\n");
+          StringBuilder errorMessage = new StringBuilder();
+          for (String line : lines) {
+            if (line.startsWith("Original Error")) {
+              errorMessage.append(line).append("\n");
             }
-            // -------------------------------- 判断项目是否结束 --------------------------------
-            result = projectUtil.complete(redisPrefix, projectId);
-            if (!result) {
-                log.info("项目 " + projectId + " 还未运行完成。");
-                projectUtil.createNextPod3(projectId, nodeName, podName);
-            } else {
-                //如果项目已完成先把 pod 删除,并归还并行度
-                KubernetesUtil.deletePod2(apiClient, kubernetesConfiguration.getNamespace(), podName);
-                projectUtil.incrementOneParallelismOfGpuNode(nodeName);
+            if (line.startsWith("Possible Cause")) {
+              errorMessage.append(line);
+              break;
             }
-            RedisUtil.deleteByPrefix(stringRedisTemplate, redisPrefix.getTaskMessageKey());
-            RedisUtil.deleteByPrefix(stringRedisTemplate, redisPrefix.getTaskPodKey());
+          }
+          targetEvaluate = errorMessage.toString();
+        } else {
+          targetEvaluate = DictConstants.TASK_ERROR_REASON_2;
+        }
+        taskMapper.updateFailStateWithStopTime(taskId, state, TimeUtil.getNowForMysql(), targetEvaluate);
+      } else if (DictConstants.TASK_TERMINATED.equals(state)) {
+        taskMapper.updateFailStateWithStopTime(taskId, state, TimeUtil.getNowForMysql(), DictConstants.TASK_ERROR_REASON_3);
+      } else if (DictConstants.TASK_ANALYSIS.equals(state)) { // 该状态只会获得一次
+        taskMapper.updateSuccessStateWithStopTime(taskId, state, TimeUtil.getNowForMysql());
+        // 查询项目是否使用 gpu 生成视频(0是1否)
+        String isChoiceGpu = projectUtil.getProjectByProjectId(projectId).getIsChoiceGpu();
+        if (DictConstants.VIDEO_GPU.equals(isChoiceGpu)) {
+          log.info("项目 {} 使用 GPU 生成视频。", projectId);
+        } else if (DictConstants.VIDEO_CPU.equals(isChoiceGpu)) {
+          log.info("项目 {} 使用 CPU 生成视频。", projectId);
+          videoFeignClient.generateVideo(projectId, projectType, maxSimulationTime, taskId);
+        } else {
+          throw new RuntimeException("未设置视频生成。");
         }
-        return result;
+      }
+      // -------------------------------- 判断项目是否结束 --------------------------------
+      result = projectUtil.complete(redisPrefix, projectId);
+      if (!result) {
+        log.info("项目 " + projectId + " 还未运行完成。");
+        projectUtil.createNextPod(projectId, nodeName, podName);
+      } else {
+        //如果项目已完成先把 pod 删除,并归还并行度
+        KubernetesUtil.deletePod2(apiClient, kubernetesConfiguration.getNamespace(), podName);
+        projectUtil.incrementOneParallelismOfGpuNode(nodeName);
+      }
+      RedisUtil.deleteByPrefix(stringRedisTemplate, redisPrefix.getTaskMessageKey());
+      RedisUtil.deleteByPrefix(stringRedisTemplate, redisPrefix.getTaskPodKey());
     }
+    return result;
+  }
 
 
-    /**
-     * @param userId 项目创建用户的 id
-     */
-    @SneakyThrows
-    public void score(String projectRunningKey, String userId, String projectId, String projectType) {
-        stringRedisTemplate.delete(projectRunningKey);
-        // -------------------------------- 打分 --------------------------------
-        ProjectEntity projectEntity = null;
-        if (DictConstants.PROJECT_TYPE_MANUAL.equals(projectType)) {
-            projectEntity = manualProjectMapper.selectById(projectId);
-        } else if (DictConstants.PROJECT_TYPE_AUTO_SUB.equals(projectType)) {
-            projectEntity = autoSubProjectMapper.selectById(projectId);
-        }
-        if (projectEntity == null) {
-            log.error("不存在项目 {}" + projectId);
-            return;
-        }
-        String packageId = projectEntity.getScenePackageId();  // 场景测试包 id,指标的rootId
-        TimeUnit.SECONDS.sleep(10); // 先等一下数据库更新
-        List<TaskEntity> taskList = taskMapper.selectTaskListByProjectId(projectId);  // 所有任务信息
-        if (CollectionUtil.isEmpty(taskList)) {
-            log.error("项目 {} 下没有查询到任务!", projectId);
-            return;
-        }
-        indexMapper.deleteFirstByProjectId(projectId);
-        indexMapper.deleteLastByProjectId(projectId);
-        //1 查询场景包对应指标
-        String allIndexKey = "project:" + projectId + ":package:" + packageId + ":all";
-        String leafIndexKey = "project:" + projectId + ":package:" + packageId + ":leaf";
-        String allIndexTemplateListJson = stringRedisTemplate.opsForValue().get(allIndexKey);
-        String leafIndexTemplateListJson = stringRedisTemplate.opsForValue().get(leafIndexKey);
-        List<IndexTemplateEntity> allIndexTemplateList = JsonUtil.jsonToList(allIndexTemplateListJson, IndexTemplateEntity.class);
-        List<IndexTemplateEntity> leafIndexTemplateList = JsonUtil.jsonToList(leafIndexTemplateListJson, IndexTemplateEntity.class);
-        log.info("共有 " + leafIndexTemplateList.size() + "个叶子节点:" + leafIndexTemplateListJson);
-        int maxLevel = 1; // 用于计算指标得分
-        List<LeafIndexEntity> leafIndexList = new ArrayList<>();
-        for (int i = 0; i < leafIndexTemplateList.size(); i++) {
-            String scoreExplain = null; // 每个叶子指标下的任务的得分说明一样和叶子指标一致
-            IndexTemplateEntity leafIndexTemplate = leafIndexTemplateList.get(i);
-            String indexId = leafIndexTemplate.getIndexId(); // 叶子指标id
-            String parentId = leafIndexTemplate.getParentId(); // 父 id
-            String rootId = leafIndexTemplate.getRootId(); // 包 id
-            String weight = leafIndexTemplate.getWeight(); // 权重
-            Integer packageLevel = leafIndexTemplate.getPackageLevel(); // 几级指标
-            String ruleName = leafIndexTemplate.getRuleName();    // 打分脚本名称,例如 AEB_1-1
-            String ruleDetails = leafIndexTemplate.getRuleDetails();    // 打分脚本内容
-            if (packageLevel > maxLevel) {
-                maxLevel = packageLevel;
-            }
-            log.info("开始执行对第 " + (i + 1) + " 个叶子节点 " + indexId + " 进行打分!");
-            // 根据叶子指标id查询评分规则创建用户id
-            String createUserIdOfRule = scoringRulesMapper.selectCreateUserIdByIndexId(indexId);
-            //1 判断有没有用户目录,没有则复制
-            String scoreDirectoryOfUser = linuxTempPath + "score/" + createUserIdOfRule + "/";
-            if (!new File(scoreDirectoryOfUser + "main.py").exists()) {
-                // 复制 main.py
-                FileUtil.createDirectory(scoreDirectoryOfUser);
-                FileUtil.cpR(pyPath, scoreDirectoryOfUser);
-            }
-            //2 将打分规则保存到script目录
+  /**
+   * @param userId 项目创建用户的 id
+   */
+  @SneakyThrows
+  public void score(String projectRunningKey, String userId, String projectId, String projectType) {
+    stringRedisTemplate.delete(projectRunningKey);
+    // -------------------------------- 打分 --------------------------------
+    ProjectEntity projectEntity = null;
+    if (DictConstants.PROJECT_TYPE_MANUAL.equals(projectType)) {
+      projectEntity = manualProjectMapper.selectById(projectId);
+    } else if (DictConstants.PROJECT_TYPE_AUTO_SUB.equals(projectType)) {
+      projectEntity = autoSubProjectMapper.selectById(projectId);
+    }
+    if (projectEntity == null) {
+      log.error("不存在项目 {}" + projectId);
+      return;
+    }
+    String packageId = projectEntity.getScenePackageId();  // 场景测试包 id,指标的rootId
+    TimeUnit.SECONDS.sleep(10); // 先等一下数据库更新
+    List<TaskEntity> taskList = taskMapper.selectTaskListByProjectId(projectId);  // 所有任务信息
+    if (CollectionUtil.isEmpty(taskList)) {
+      log.error("项目 {} 下没有查询到任务!", projectId);
+      return;
+    }
+    indexMapper.deleteFirstByProjectId(projectId);
+    indexMapper.deleteLastByProjectId(projectId);
+    //1 查询场景包对应指标
+    String allIndexKey = "project:" + projectId + ":package:" + packageId + ":all";
+    String leafIndexKey = "project:" + projectId + ":package:" + packageId + ":leaf";
+    String allIndexTemplateListJson = stringRedisTemplate.opsForValue().get(allIndexKey);
+    String leafIndexTemplateListJson = stringRedisTemplate.opsForValue().get(leafIndexKey);
+    List<IndexTemplateEntity> allIndexTemplateList = JsonUtil.jsonToList(allIndexTemplateListJson, IndexTemplateEntity.class);
+    List<IndexTemplateEntity> leafIndexTemplateList = JsonUtil.jsonToList(leafIndexTemplateListJson, IndexTemplateEntity.class);
+    log.info("共有 " + leafIndexTemplateList.size() + "个叶子节点:" + leafIndexTemplateListJson);
+    int maxLevel = 1; // 用于计算指标得分
+    List<LeafIndexEntity> leafIndexList = new ArrayList<>();
+    for (int i = 0; i < leafIndexTemplateList.size(); i++) {
+      String scoreExplain = null; // 每个叶子指标下的任务的得分说明一样和叶子指标一致
+      IndexTemplateEntity leafIndexTemplate = leafIndexTemplateList.get(i);
+      String indexId = leafIndexTemplate.getIndexId(); // 叶子指标id
+      String parentId = leafIndexTemplate.getParentId(); // 父 id
+      String rootId = leafIndexTemplate.getRootId(); // 包 id
+      String weight = leafIndexTemplate.getWeight(); // 权重
+      Integer packageLevel = leafIndexTemplate.getPackageLevel(); // 几级指标
+      String ruleName = leafIndexTemplate.getRuleName();    // 打分脚本名称,例如 AEB_1-1
+      String ruleDetails = leafIndexTemplate.getRuleDetails();    // 打分脚本内容
+      if (packageLevel > maxLevel) {
+        maxLevel = packageLevel;
+      }
+      log.info("开始执行对第 " + (i + 1) + " 个叶子节点 " + indexId + " 进行打分!");
+      // 根据叶子指标id查询评分规则创建用户id
+      String createUserIdOfRule = scoringRulesMapper.selectCreateUserIdByIndexId(indexId);
+      //1 判断有没有用户目录,没有则复制
+      String scoreDirectoryOfUser = linuxTempPath + "score/" + createUserIdOfRule + "/";
+      if (!new File(scoreDirectoryOfUser + "main.py").exists()) {
+        // 复制 main.py
+        FileUtil.createDirectory(scoreDirectoryOfUser);
+        FileUtil.cpR(pyPath, scoreDirectoryOfUser);
+      }
+      //2 将打分规则保存到script目录
 
-            String ruleFilePath = scoreDirectoryOfUser + "scripts/" + ruleName.split("_")[0] + "/" + ruleName + ".py";
-            FileUtil.writeInputStreamToLocalFile(IoUtil.stringToInputStream(ruleDetails), ruleFilePath);
-            log.info("将叶子节点 " + indexId + " 对应的打分规则保存到临时目录:" + ruleFilePath);
-            List<TaskEntity> taskListOfLeafIndex = taskList.stream()
-                    .filter(task -> indexId.equals(task.getLastTargetId()))
-                    .collect(Collectors.toList());
-            log.info("叶子节点 " + indexId + " 包括 " + taskListOfLeafIndex.size() + " 个任务:" + taskListOfLeafIndex);
-            // 计算叶子指标的得分
-            // 使用 stream 流会出现无法进入循环的情况
-            for (TaskEntity taskOfLeaf : taskListOfLeafIndex) {
-                String task2Id = taskOfLeaf.getId();
+      String ruleFilePath = scoreDirectoryOfUser + "scripts/" + ruleName.split("_")[0] + "/" + ruleName + ".py";
+      FileUtil.writeInputStreamToLocalFile(IoUtil.stringToInputStream(ruleDetails), ruleFilePath);
+      log.info("将叶子节点 " + indexId + " 对应的打分规则保存到临时目录:" + ruleFilePath);
+      List<TaskEntity> taskListOfLeafIndex = taskList.stream().filter(task -> indexId.equals(task.getLastTargetId())).collect(Collectors.toList());
+      log.info("叶子节点 " + indexId + " 包括 " + taskListOfLeafIndex.size() + " 个任务:" + taskListOfLeafIndex);
+      // 计算叶子指标的得分
+      // 使用 stream 流会出现无法进入循环的情况
+      for (TaskEntity taskOfLeaf : taskListOfLeafIndex) {
+        String task2Id = taskOfLeaf.getId();
 
-                String runState = taskOfLeaf.getRunState();
-                log.info("TaskManager--score 任务 " + task2Id + " 的运行状态为:" + runState);
-                if (DictConstants.TASK_ANALYSIS.equals(runState)) {
-                    taskMapper.updateSuccessStateWithStopTime(task2Id, DictConstants.TASK_ANALYSING, TimeUtil.getNowForMysql());
-                    // 计算每个任务的得分
-                    String result1OfMinio = taskOfLeaf.getRunResultFilePath() + "/Ego.csv";
-                    String result1OfLinux = linuxTempPath + result1OfMinio;
-                    String result2OfMinio = taskOfLeaf.getRunResultFilePath() + "/evaluation.csv";
-                    String result2OfLinux = linuxTempPath + result2OfMinio;
-                    String scoreCommand = "python3 " + scoreDirectoryOfUser + "main.py " + result1OfLinux + " " + result2OfLinux + " " + taskOfLeaf.getSceneType() + " " + ruleName; // 指定打分脚本
-                    String scoreResult;
-                    ScoreEntity score = null;
-                    log.info("下载 minio 上的结果文件 " + result1OfMinio + " 和 " + result2OfMinio + " 到临时目录:" + linuxTempPath);
-                    MinioUtil.downloadToFile(minioClient, bucketName, result1OfMinio, result1OfLinux);  // 也可改成下载到指定ip的服务器上,需要保证和打分脚本在一台机器上。
-                    MinioUtil.downloadToFile(minioClient, bucketName, result2OfMinio, result2OfLinux);  // 也可改成下载到指定ip的服务器上,需要保证和打分脚本在一台机器上。
-                    log.info("开始执行打分命令:" + scoreCommand);
-                    Runtime r = Runtime.getRuntime();
-                    Process p = r.exec(scoreCommand, null, new File(scoreDirectoryOfUser));
-                    BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
-                    StringBuilder sb = new StringBuilder();
-                    String inline;
-                    while (null != (inline = br.readLine())) {
-                        sb.append(inline).append("\n");
-                    }
-                    scoreResult = sb.toString();
-                    log.info("项目" + projectId + " 的任务 " + task2Id + " 打分结束,结果为:" + scoreResult);
-                    String replace = StringUtil.replace(scoreResult, "'", "\"");
-                    try {
-                        score = JsonUtil.jsonToBean(replace, ScoreEntity.class);
-                    } catch (Exception e) { // 打分失败
-                        log.info("项目" + projectId + " 的任务 " + task2Id + " 打分失败:", e);
-                    }
-                    if (score != null) {
-                        taskOfLeaf.setReturnSceneId(score.getUnit_scene_ID());
-                        taskOfLeaf.setTargetEvaluate(score.getEvaluate_item());
-                        taskOfLeaf.setScoreExplain(score.getScore_description());
-                        taskOfLeaf.setModifyUserId(userId);
-                        taskOfLeaf.setModifyTime(TimeUtil.getNowForMysql());
-                        scoreExplain = score.getScore_description();
-                        taskOfLeaf.setRunState(DictConstants.TASK_COMPLETED);
-                        double taskScore = score.getUnit_scene_score();
-                        if (taskScore == -1.0) {
-                            taskOfLeaf.setScore(0.0);
-                            taskOfLeaf.setScored(false);
-                        } else {
-                            taskOfLeaf.setScore(NumberUtil.cut(taskScore, 2));
-                            taskOfLeaf.setScored(true);
-                        }
-                        taskMapper.updateSuccessState(taskOfLeaf, DictConstants.TASK_COMPLETED);
-                    } else {
-                        //1 修改任务状态为 aborted
-                        taskOfLeaf.setRunState(DictConstants.TASK_ABORTED);
-                        taskOfLeaf.setScore(0.0);
-                        taskOfLeaf.setScored(false);
-                        taskMapper.updateFailStateWithStopTime(task2Id, DictConstants.TASK_ABORTED, TimeUtil.getNowForMysql(), DictConstants.TASK_ERROR_REASON_5);
-                    }
-                }
+        String runState = taskOfLeaf.getRunState();
+        log.info("TaskManager--score 任务 " + task2Id + " 的运行状态为:" + runState);
+        if (DictConstants.TASK_ANALYSIS.equals(runState)) {
+          taskMapper.updateSuccessStateWithStopTime(task2Id, DictConstants.TASK_ANALYSING, TimeUtil.getNowForMysql());
+          // 计算每个任务的得分
+          String result1OfMinio = taskOfLeaf.getRunResultFilePath() + "/Ego.csv";
+          String result1OfLinux = linuxTempPath + result1OfMinio;
+          String result2OfMinio = taskOfLeaf.getRunResultFilePath() + "/evaluation.csv";
+          String result2OfLinux = linuxTempPath + result2OfMinio;
+          String scoreCommand = "python3 " + scoreDirectoryOfUser + "main.py " + result1OfLinux + " " + result2OfLinux + " " + taskOfLeaf.getSceneType() + " " + ruleName; // 指定打分脚本
+          String scoreResult;
+          ScoreEntity score = null;
+          log.info("下载 minio 上的结果文件 " + result1OfMinio + " 和 " + result2OfMinio + " 到临时目录:" + linuxTempPath);
+          MinioUtil.downloadToFile(minioClient, bucketName, result1OfMinio, result1OfLinux);  // 也可改成下载到指定ip的服务器上,需要保证和打分脚本在一台机器上。
+          MinioUtil.downloadToFile(minioClient, bucketName, result2OfMinio, result2OfLinux);  // 也可改成下载到指定ip的服务器上,需要保证和打分脚本在一台机器上。
+          log.info("开始执行打分命令:" + scoreCommand);
+          Runtime r = Runtime.getRuntime();
+          Process p = r.exec(scoreCommand, null, new File(scoreDirectoryOfUser));
+          BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
+          StringBuilder sb = new StringBuilder();
+          String inline;
+          while (null != (inline = br.readLine())) {
+            sb.append(inline).append("\n");
+          }
+          scoreResult = sb.toString();
+          log.info("项目" + projectId + " 的任务 " + task2Id + " 打分结束,结果为:" + scoreResult);
+          String replace = StringUtil.replace(scoreResult, "'", "\"");
+          try {
+            score = JsonUtil.jsonToBean(replace, ScoreEntity.class);
+          } catch (Exception e) { // 打分失败
+            log.info("项目" + projectId + " 的任务 " + task2Id + " 打分失败:", e);
+          }
+          if (score != null) {
+            taskOfLeaf.setReturnSceneId(score.getUnit_scene_ID());
+            taskOfLeaf.setTargetEvaluate(score.getEvaluate_item());
+            taskOfLeaf.setScoreExplain(score.getScore_description());
+            taskOfLeaf.setModifyUserId(userId);
+            taskOfLeaf.setModifyTime(TimeUtil.getNowForMysql());
+            scoreExplain = score.getScore_description();
+            taskOfLeaf.setRunState(DictConstants.TASK_COMPLETED);
+            double taskScore = score.getUnit_scene_score();
+            if (taskScore == -1.0) {
+              taskOfLeaf.setScore(0.0);
+              taskOfLeaf.setScored(false);
+            } else {
+              taskOfLeaf.setScore(NumberUtil.cut(taskScore, 2));
+              taskOfLeaf.setScored(true);
             }
+            taskMapper.updateSuccessState(taskOfLeaf, DictConstants.TASK_COMPLETED);
+          } else {
+            //1 修改任务状态为 aborted
+            taskOfLeaf.setRunState(DictConstants.TASK_ABORTED);
+            taskOfLeaf.setScore(0.0);
+            taskOfLeaf.setScored(false);
+            taskMapper.updateFailStateWithStopTime(task2Id, DictConstants.TASK_ABORTED, TimeUtil.getNowForMysql(), DictConstants.TASK_ERROR_REASON_5);
+          }
+        }
+      }
 
-            // 全部参与计算
-            // 计算不合格的任务数(不到100分就是不合格,执行失败的不算)
-            // 计算叶子指标下任务得分总和
-            int errorSceneNumber = 0;   // 仿真失败的任务
-            int notScoredSceneNumber = 0;   // 评分失败的任务
-            int notStandardSceneNumber = 0;
-            int standardSceneNumber = 0;
-            double leafSum = 0.0;
-            for (TaskEntity task : taskListOfLeafIndex) {
-                Double scoreTemp = task.getScore();
-                if (scoreTemp == null) {   // 失败状态的任务是没有分数的,计作 0 分。
-                    errorSceneNumber++;
-                    scoreTemp = 0.0;
-                } else if (task.getScored() == null || !task.getScored()) {  // 如果评分失败,也计作 0 分
-                    notScoredSceneNumber++;
-                    scoreTemp = 0.0;
-                } else if (scoreTemp < 100.0) {
-                    notStandardSceneNumber++;
-                } else if (scoreTemp == 100.0) {
-                    standardSceneNumber++;
-                }
-                // 计算分数总和
-                leafSum += scoreTemp;
-            }
+      // 全部参与计算
+      // 计算不合格的任务数(不到100分就是不合格,执行失败的不算)
+      // 计算叶子指标下任务得分总和
+      int errorSceneNumber = 0;   // 仿真失败的任务
+      int notScoredSceneNumber = 0;   // 评分失败的任务
+      int notStandardSceneNumber = 0;
+      int standardSceneNumber = 0;
+      double leafSum = 0.0;
+      for (TaskEntity task : taskListOfLeafIndex) {
+        Double scoreTemp = task.getScore();
+        if (scoreTemp == null) {   // 失败状态的任务是没有分数的,计作 0 分。
+          errorSceneNumber++;
+          scoreTemp = 0.0;
+        } else if (task.getScored() == null || !task.getScored()) {  // 如果评分失败,也计作 0 分
+          notScoredSceneNumber++;
+          scoreTemp = 0.0;
+        } else if (scoreTemp < 100.0) {
+          notStandardSceneNumber++;
+        } else if (scoreTemp == 100.0) {
+          standardSceneNumber++;
+        }
+        // 计算分数总和
+        leafSum += scoreTemp;
+      }
 
-            // 计算任务的个数
-            long taskNumberToScore = taskListOfLeafIndex.size();
-            log.info("项目 " + projectId + " 的叶子指标 " + indexId
-                    + " 下参与计算的任务总数为 " + taskNumberToScore
-                    + ":仿真异常场景个数 " + errorSceneNumber
-                    + "、未达标场景个数 " + notStandardSceneNumber
-                    + "、达标场景个数 " + standardSceneNumber
-            );
+      // 计算任务的个数
+      long taskNumberToScore = taskListOfLeafIndex.size();
+      log.info("项目 " + projectId + " 的叶子指标 " + indexId + " 下参与计算的任务总数为 " + taskNumberToScore + ":仿真异常场景个数 " + errorSceneNumber + "、未达标场景个数 " + notStandardSceneNumber + "、达标场景个数 " + standardSceneNumber);
 
-            // 计算叶子指标得分(任务得分总和 / 任务数量)
-            double leafIndexScore = NumberUtil.cut(leafSum / taskNumberToScore, 2);
-            // 创建叶子指标对象
-            leafIndexTemplate.setTempScore(leafIndexScore);
+      // 计算叶子指标得分(任务得分总和 / 任务数量)
+      double leafIndexScore = NumberUtil.cut(leafSum / taskNumberToScore, 2);
+      // 创建叶子指标对象
+      leafIndexTemplate.setTempScore(leafIndexScore);
 
-            LeafIndexEntity leafIndex = LeafIndexEntity.builder()
-                    .id(StringUtil.getRandomUUID())
-                    .pId(projectId)
-                    .target(leafIndexTemplate.getIndexId())
-                    .errorSceneNum(errorSceneNumber)
-                    .notScoredSceneNum(notScoredSceneNumber)
-                    .notStandardSceneNum(notStandardSceneNumber)
-                    .standardSceneNum(standardSceneNumber)
-                    .score(leafIndexScore)
-                    .indexId(indexId)
-                    .parentId(parentId)
-                    .rootId(rootId)
-                    .weight(weight)
-                    .scoreExplain(scoreExplain)
-                    .packageLevel(packageLevel)
-                    .build();
-            leafIndex.setCreateUserId(userId);
-            leafIndex.setCreateTime(TimeUtil.getNowForMysql());
-            leafIndex.setModifyUserId(userId);
-            leafIndex.setModifyTime(TimeUtil.getNowForMysql());
-            leafIndex.setIsDeleted("0");
+      LeafIndexEntity leafIndex = LeafIndexEntity.builder().id(StringUtil.getRandomUUID()).pId(projectId).target(leafIndexTemplate.getIndexId()).errorSceneNum(errorSceneNumber).notScoredSceneNum(notScoredSceneNumber).notStandardSceneNum(notStandardSceneNumber).standardSceneNum(standardSceneNumber).score(leafIndexScore).indexId(indexId).parentId(parentId).rootId(rootId).weight(weight).scoreExplain(scoreExplain).packageLevel(packageLevel).build();
+      leafIndex.setCreateUserId(userId);
+      leafIndex.setCreateTime(TimeUtil.getNowForMysql());
+      leafIndex.setModifyUserId(userId);
+      leafIndex.setModifyTime(TimeUtil.getNowForMysql());
+      leafIndex.setIsDeleted("0");
 
-            leafIndexList.add(leafIndex);
-        }
-        // 保存叶子指标得分
-        taskIndexManager.batchInsertLeafIndex(leafIndexList);
-        // 保存一级指标分数
-        log.info("项目 " + projectId + " 的所有任务分数为:" + taskList);
-        computeFirst(leafIndexList, allIndexTemplateList, projectId, maxLevel);
-        log.info("项目 " + projectId + " 打分完成!");
+      leafIndexList.add(leafIndex);
     }
+    // 保存叶子指标得分
+    taskIndexManager.batchInsertLeafIndex(leafIndexList);
+    // 保存一级指标分数
+    log.info("项目 " + projectId + " 的所有任务分数为:" + taskList);
+    computeFirst(leafIndexList, allIndexTemplateList, projectId, maxLevel);
+    log.info("项目 " + projectId + " 打分完成!");
+  }
 
-    public void computeFirst(List<LeafIndexEntity> leafIndexList, List<IndexTemplateEntity> allIndexTemplateList, String projectId, int maxLevel) {
-
-        log.info("计算父指标得分:" + leafIndexList);
-        Iterator<LeafIndexEntity> leafTaskIndexIterator = leafIndexList.iterator();
-        // 把 1 级的指标得分直接保存
-        while (leafTaskIndexIterator.hasNext()) {
-            LeafIndexEntity leafTaskIndex = leafTaskIndexIterator.next();
-            if (leafTaskIndex.getPackageLevel() == 1) {
-                leafTaskIndex.setCreateUserId(leafTaskIndex.getCreateUserId());
-                leafTaskIndex.setCreateTime(TimeUtil.getNowForMysql());
-                leafTaskIndex.setModifyUserId(leafTaskIndex.getModifyUserId());
-                leafTaskIndex.setModifyTime(TimeUtil.getNowForMysql());
-                leafTaskIndex.setIsDeleted("0");
-                indexMapper.insertFirstIndex(leafTaskIndex);
-                leafTaskIndexIterator.remove();
-            }
-        }
-        if (leafIndexList.size() > 0) {
-            List<LeafIndexEntity> nextLevelIndexList = new ArrayList<>();
-            // 找出等级和 maxLevel 不相同的指标暂时不计算
-            leafIndexList.stream()
-                    .filter(po -> maxLevel != po.getPackageLevel())
-                    .forEach(nextLevelIndexList::add);
-            // 找出等级和 maxLevel 相同的指标并根据父指标分组
-            Map<String, List<LeafIndexEntity>> sonTaskIndexMap = leafIndexList.stream()
-                    .filter(po -> maxLevel == po.getPackageLevel())
-                    .collect(Collectors.groupingBy(LeafIndexEntity::getParentId));
-            Set<String> parentIdSet = sonTaskIndexMap.keySet();
-            List<String> parentIdList = CollectionUtil.setToList(parentIdSet);
+  public void computeFirst(List<LeafIndexEntity> leafIndexList, List<IndexTemplateEntity> allIndexTemplateList, String projectId, int maxLevel) {
 
-            List<IndexTemplateEntity> parentIndexTemplateList = allIndexTemplateList.stream()
-                    .filter(indexTemplate -> parentIdList.contains(indexTemplate.getIndexId()))
-                    .collect(Collectors.toList());
-            // 计算父指标得分
-            parentIndexTemplateList.forEach(indexTemplate -> {
-                String weight = indexTemplate.getWeight();
-                List<LeafIndexEntity> sonTaskIndexList = sonTaskIndexMap.get(indexTemplate.getIndexId());
-                double parentScore = NumberUtil.cut(sonTaskIndexList.stream().mapToDouble(taskIndex -> taskIndex
-                        .getScore() * Double.parseDouble(taskIndex.getWeight()) / 100).sum(), 2);
-                LeafIndexEntity parentTaskIndex = LeafIndexEntity.builder()
-                        .id(StringUtil.getRandomUUID())
-                        .pId(projectId)
-                        .target(indexTemplate.getIndexId())
-                        .score(parentScore)
-                        .indexId(indexTemplate.getIndexId())
-                        .parentId(indexTemplate.getParentId())
-                        .rootId(indexTemplate.getRootId())
-                        .weight(weight)
-                        .packageLevel(maxLevel - 1)
-                        .build();
-                nextLevelIndexList.add(parentTaskIndex);
-            });
-            // 将父指标作为叶子指标递归
-            computeFirst(nextLevelIndexList, allIndexTemplateList, projectId, maxLevel - 1);
-        }
+    log.info("计算父指标得分:" + leafIndexList);
+    Iterator<LeafIndexEntity> leafTaskIndexIterator = leafIndexList.iterator();
+    // 把 1 级的指标得分直接保存
+    while (leafTaskIndexIterator.hasNext()) {
+      LeafIndexEntity leafTaskIndex = leafTaskIndexIterator.next();
+      if (leafTaskIndex.getPackageLevel() == 1) {
+        leafTaskIndex.setCreateUserId(leafTaskIndex.getCreateUserId());
+        leafTaskIndex.setCreateTime(TimeUtil.getNowForMysql());
+        leafTaskIndex.setModifyUserId(leafTaskIndex.getModifyUserId());
+        leafTaskIndex.setModifyTime(TimeUtil.getNowForMysql());
+        leafTaskIndex.setIsDeleted("0");
+        indexMapper.insertFirstIndex(leafTaskIndex);
+        leafTaskIndexIterator.remove();
+      }
     }
+    if (leafIndexList.size() > 0) {
+      List<LeafIndexEntity> nextLevelIndexList = new ArrayList<>();
+      // 找出等级和 maxLevel 不相同的指标暂时不计算
+      leafIndexList.stream().filter(po -> maxLevel != po.getPackageLevel()).forEach(nextLevelIndexList::add);
+      // 找出等级和 maxLevel 相同的指标并根据父指标分组
+      Map<String, List<LeafIndexEntity>> sonTaskIndexMap = leafIndexList.stream().filter(po -> maxLevel == po.getPackageLevel()).collect(Collectors.groupingBy(LeafIndexEntity::getParentId));
+      Set<String> parentIdSet = sonTaskIndexMap.keySet();
+      List<String> parentIdList = CollectionUtil.setToList(parentIdSet);
 
-    @SneakyThrows
-    public void evaluationLevel(String projectId) {
-        String tokenUrl = tokenUri + "?grant_type=client_credentials"
-                + "&client_id=" + clientId
-                + "&client_secret=" + clientSecret;
-        log.info("获取仿真云平台 token:" + tokenUrl);
-        String response = HttpUtil.get(closeableHttpClient, requestConfig, tokenUrl);
-        ObjectMapper objectMapper = new ObjectMapper();
-        JsonNode jsonNode = objectMapper.readTree(response);
-        String accessToken = jsonNode.path("access_token").asText();
-        log.info("仿真云平台 token 为:" + accessToken);
-        Map<String, String> headers = new HashMap<>();
-        headers.put("Authorization", "Bearer " + accessToken);
-        Map<String, String> params = new HashMap<>();
-        params.put("id", projectId);
-        String post = HttpUtil.post(closeableHttpClient, requestConfig, evaluationLevelUri, headers, params);
-        log.info("访问仿真云平台评价等级接口:" + evaluationLevelUri + ",请求头为:" + headers + ",请求体为:" + params + "结果为:" + post);
+      List<IndexTemplateEntity> parentIndexTemplateList = allIndexTemplateList.stream().filter(indexTemplate -> parentIdList.contains(indexTemplate.getIndexId())).collect(Collectors.toList());
+      // 计算父指标得分
+      parentIndexTemplateList.forEach(indexTemplate -> {
+        String weight = indexTemplate.getWeight();
+        List<LeafIndexEntity> sonTaskIndexList = sonTaskIndexMap.get(indexTemplate.getIndexId());
+        double parentScore = NumberUtil.cut(sonTaskIndexList.stream().mapToDouble(taskIndex -> taskIndex.getScore() * Double.parseDouble(taskIndex.getWeight()) / 100).sum(), 2);
+        LeafIndexEntity parentTaskIndex = LeafIndexEntity.builder().id(StringUtil.getRandomUUID()).pId(projectId).target(indexTemplate.getIndexId()).score(parentScore).indexId(indexTemplate.getIndexId()).parentId(indexTemplate.getParentId()).rootId(indexTemplate.getRootId()).weight(weight).packageLevel(maxLevel - 1).build();
+        nextLevelIndexList.add(parentTaskIndex);
+      });
+      // 将父指标作为叶子指标递归
+      computeFirst(nextLevelIndexList, allIndexTemplateList, projectId, maxLevel - 1);
     }
+  }
 
+  @SneakyThrows
+  public void evaluationLevel(String projectId) {
+    String tokenUrl = tokenUri + "?grant_type=client_credentials" + "&client_id=" + clientId + "&client_secret=" + clientSecret;
+    log.info("获取仿真云平台 token:" + tokenUrl);
+    String response = HttpUtil.get(closeableHttpClient, requestConfig, tokenUrl);
+    ObjectMapper objectMapper = new ObjectMapper();
+    JsonNode jsonNode = objectMapper.readTree(response);
+    String accessToken = jsonNode.path("access_token").asText();
+    log.info("仿真云平台 token 为:" + accessToken);
+    Map<String, String> headers = new HashMap<>();
+    headers.put("Authorization", "Bearer " + accessToken);
+    Map<String, String> params = new HashMap<>();
+    params.put("id", projectId);
+    String post = HttpUtil.post(closeableHttpClient, requestConfig, evaluationLevelUri, headers, params);
+    log.info("访问仿真云平台评价等级接口:" + evaluationLevelUri + ",请求头为:" + headers + ",请求体为:" + params + "结果为:" + post);
+  }
 
-    public Boolean taskConfirm(String taskId) {
-        // 查询 task 如果不是 pending 则不执行
-        String state = taskMapper.selectStateById(taskId);
-        return DictConstants.TASK_PENDING.equals(state);
-    }
 
-    public void taskTick(String taskId) {
-        log.info("收到任务 " + taskId + " 的心跳。");
-        TaskEntity taskEntity = taskMapper.selectById(taskId);
-        String projectId = taskEntity.getPId();
-        String userId = taskEntity.getCreateUserId();
-        // 刷新 redis 心跳时间
-        PrefixEntity redisPrefix = projectUtil.getRedisPrefixByUserIdAndProjectIdAndTaskId(userId, projectId, taskId);
-        if (RedisUtil.getStringByKey(stringRedisTemplate, redisPrefix.getProjectRunningKey()) != null) {
-            stringRedisTemplate.opsForValue().set(redisPrefix.getTaskTickKey(), TimeUtil.getNowString());
-        }
+  public Boolean taskConfirm(String taskId) {
+    // 查询 task 如果不是 pending 则不执行
+    String state = taskMapper.selectStateById(taskId);
+    return DictConstants.TASK_PENDING.equals(state);
+  }
 
+  public void taskTick(String taskId) {
+    log.info("收到任务 " + taskId + " 的心跳。");
+    TaskEntity taskEntity = taskMapper.selectById(taskId);
+    String projectId = taskEntity.getPId();
+    String userId = taskEntity.getCreateUserId();
+    // 刷新 redis 心跳时间
+    PrefixEntity redisPrefix = projectUtil.getRedisPrefixByUserIdAndProjectIdAndTaskId(userId, projectId, taskId);
+    if (RedisUtil.getStringByKey(stringRedisTemplate, redisPrefix.getProjectRunningKey()) != null) {
+      stringRedisTemplate.opsForValue().set(redisPrefix.getTaskTickKey(), TimeUtil.getNowString());
     }
 
+  }
 
-    @SneakyThrows
-    public void done(PrefixEntity redisPrefix, String projectId, String projectType) {
-        // 更新项目状态为已完成
-        if (DictConstants.PROJECT_TYPE_MANUAL.equals(projectType)) {
-            manualProjectMapper.updateProjectState(projectId, DictConstants.PROJECT_COMPLETED, TimeUtil.getNowForMysql());
-        } else if (DictConstants.PROJECT_TYPE_AUTO_SUB.equals(projectType)) {
-            autoSubProjectMapper.updateProjectState(projectId, DictConstants.PROJECT_COMPLETED, TimeUtil.getNowForMysql());
-        }
-        // 删除 kafka topic
-        ApacheKafkaUtil.deleteTopic(admin, projectId);
-        // 删除 redis 中的 项目运行信息 键值对
-        RedisUtil.deleteByPrefix(stringRedisTemplate, redisPrefix.getProjectRunningKey());
-        RedisUtil.deleteByPrefix(stringRedisTemplate, "project:" + projectId);
-        // 删除剩余 yaml
-        projectUtil.deleteYamlByProjectId(projectId);
+
+  @SneakyThrows
+  public void done(PrefixEntity redisPrefix, String projectId, String projectType) {
+    // 更新项目状态为已完成
+    if (DictConstants.PROJECT_TYPE_MANUAL.equals(projectType)) {
+      manualProjectMapper.updateProjectState(projectId, DictConstants.PROJECT_COMPLETED, TimeUtil.getNowForMysql());
+    } else if (DictConstants.PROJECT_TYPE_AUTO_SUB.equals(projectType)) {
+      autoSubProjectMapper.updateProjectState(projectId, DictConstants.PROJECT_COMPLETED, TimeUtil.getNowForMysql());
     }
+    // 删除 kafka topic
+    ApacheKafkaUtil.deleteTopic(admin, projectId);
+    // 删除 redis 中的 项目运行信息 键值对
+    RedisUtil.deleteByPrefix(stringRedisTemplate, redisPrefix.getProjectRunningKey());
+    RedisUtil.deleteByPrefix(stringRedisTemplate, "project:" + projectId);
+    // 删除剩余 yaml
+    projectUtil.deleteYamlByProjectId(projectId);
+  }
 
 
 }

+ 45 - 45
simulation-resource-scheduler/src/main/java/com/css/simulation/resource/scheduler/service/TaskService.java

@@ -15,58 +15,58 @@ import javax.annotation.Resource;
 @Service
 @Slf4j
 public class TaskService {
-    @Resource
-    private TaskManager taskManager;
-    @Resource
-    private TaskMapper taskMapper;
-    @Resource
-    private ProjectUtil projectUtil;
-    @Resource
-    private CustomRedisClient customRedisClient;
+  @Resource
+  private TaskManager taskManager;
+  @Resource
+  private TaskMapper taskMapper;
+  @Resource
+  private ProjectUtil projectUtil;
+  @Resource
+  private CustomRedisClient customRedisClient;
 
 
-    // -------------------------------- Comment --------------------------------
-
-    @SneakyThrows
-    public void taskState(String taskId, String state, String podName) {
-        String lock1 = "taskId:" + taskId + ":state:" + state + ":pod-name:" + podName;
-        customRedisClient.lock(lock1, 1L, 30 * 60L);
-        try {
-            // 查询相关信息
-            TaskEntity taskEntity = taskMapper.selectById(taskId);
-            String projectId = taskEntity.getPId(); // 项目 id
-            ProjectEntity projectEntity = projectUtil.getProjectByProjectId(projectId);
-            String projectType = projectEntity.getProjectType();  // 项目类型
-            String maxSimulationTime = projectEntity.getMaxSimulationTime();  // 项目类型
-            String userId = taskEntity.getCreateUserId();   // 用户 id
-            PrefixEntity redisPrefix = projectUtil.getRedisPrefixByUserIdAndProjectIdAndTaskId(userId, projectId, taskId);
-            // 判断是否完成
-            boolean projectCompleted = taskManager.isProjectCompleted(redisPrefix, projectId, projectType, maxSimulationTime, taskId, state, podName);
-            if (projectCompleted) {
-                String lock2 = "project:" + projectId + ":completed-lock";
-                customRedisClient.tryLock(lock2, 10 * 60L);
-                log.info("项目 {} 开始打分。", projectId);
-                taskManager.score(redisPrefix.getProjectRunningKey(), userId, projectId, projectType);
-                log.info("项目 {} 计算评价等级。", projectId);
-                taskManager.evaluationLevel(projectId);
-                log.info("项目 {} 开始释放资源。", projectId);
-                taskManager.done(redisPrefix, projectId, projectType);
-                log.info("项目 {} 运行结束。", projectId);
-            }
-        } finally {
-            customRedisClient.unlock(lock1);
-        }
+  // -------------------------------- Comment --------------------------------
 
+  @SneakyThrows
+  public void taskState(String taskId, String state, String podName) {
+    String lock1 = "taskId:" + taskId + ":state:" + state + ":pod-name:" + podName;
+    customRedisClient.lock(lock1, 1L, 30 * 60L);
+    try {
+      // 查询相关信息
+      TaskEntity taskEntity = taskMapper.selectById(taskId);
+      String projectId = taskEntity.getPId(); // 项目 id
+      ProjectEntity projectEntity = projectUtil.getProjectByProjectId(projectId);
+      String projectType = projectEntity.getProjectType();  // 项目类型
+      String maxSimulationTime = projectEntity.getMaxSimulationTime();  // 项目类型
+      String userId = taskEntity.getCreateUserId();   // 用户 id
+      PrefixEntity redisPrefix = projectUtil.getRedisPrefixByUserIdAndProjectIdAndTaskId(userId, projectId, taskId);
+      // 判断是否完成
+      boolean projectCompleted = taskManager.isProjectCompleted(redisPrefix, projectId, projectType, maxSimulationTime, taskId, state, podName);
+      if (projectCompleted) {
+        String lock2 = "project:" + projectId + ":completed-lock";
+        customRedisClient.tryLock(lock2, 10 * 60L);
+        log.info("项目 {} 开始打分。", projectId);
+        taskManager.score(redisPrefix.getProjectRunningKey(), userId, projectId, projectType);
+        log.info("项目 {} 计算评价等级。", projectId);
+        taskManager.evaluationLevel(projectId);
+        log.info("项目 {} 开始释放资源。", projectId);
+        taskManager.done(redisPrefix, projectId, projectType);
+        log.info("项目 {} 运行结束。", projectId);
+      }
+    } finally {
+      customRedisClient.unlock(lock1);
     }
 
+  }
 
-    public Boolean taskConfirm(String taskId) {
-        return taskManager.taskConfirm(taskId);
-    }
 
-    public void taskTick(String taskId) {
-        taskManager.taskTick(taskId);
-    }
+  public Boolean taskConfirm(String taskId) {
+    return taskManager.taskConfirm(taskId);
+  }
+
+  public void taskTick(String taskId) {
+    taskManager.taskTick(taskId);
+  }
 
 
 }

+ 441 - 464
simulation-resource-scheduler/src/main/java/com/css/simulation/resource/scheduler/util/ProjectUtil.java

@@ -33,491 +33,468 @@ import java.util.stream.Collectors;
 @Slf4j
 public class ProjectUtil {
 
-    @Value("${scheduler.linux-path.pod-yaml-directory}")
-    private String podYamlDirectory;
-    @Value("${scheduler.host.hostname}")
-    private String hostname;
-    @Value("${scheduler.host.username}")
-    private String username;
-    @Value("${scheduler.host.password}")
-    private String password;
-
-
-    @Resource
-    private ManualProjectMapper manualProjectMapper;
-    @Resource
-    private AutoSubProjectMapper autoSubProjectMapper;
-    @Resource
-    private UserMapper userMapper;
-    @Resource
-    private ClusterMapper clusterMapper;
-    @Resource
-    private EsminiConfiguration esminiConfiguration;
-    @Resource
-    private KubernetesConfiguration kubernetesConfiguration;
-    @Resource
-    private ApiClient apiClient;
-    @Resource
-    private StringRedisTemplate stringRedisTemplate;
-    @Resource
-    private CustomRedisClient customRedisClient;
-
-
-    @SneakyThrows
-    public void deleteYamlByProjectId(String projectId) {
-        List<String> absolutePathList = FileUtil.listAbsolutePath(podYamlDirectory);
-        for (String absolutePath : absolutePathList) {
-            if (absolutePath.contains(projectId)) {
-                boolean delete = new File(absolutePath).delete();
-            }
-        }
-    }
-
-
-    public List<NodeEntity> getNodeListToCount(Map<String, Integer> nodeMap) {
-        List<NodeEntity> result = new ArrayList<>();
-        nodeMap.forEach((nodeName, parallelism) -> {
-            for (int i = 0; i < parallelism; i++) {
-                result.add(new NodeEntity(nodeName, 0));
-            }
-        });
-        return result;
-    }
-
-    /**
-     * 判断算法是否已经导入
-     *
-     * @return 算法是否已经导入
-     */
-    @SneakyThrows
-    public boolean isImported(String dockerImageWithoutVersion) {
-        String dockerImageListString = LinuxUtil.execute("docker images");
-        return dockerImageListString.contains(dockerImageWithoutVersion);
-    }
-
-    public String getRandomPodName(String projectId) {
-        return "project-" + projectId + "-" + StringUtil.getRandomEightBitUUID();
+  @Value("${scheduler.linux-path.pod-yaml-directory}")
+  private String podYamlDirectory;
+  @Value("${scheduler.host.hostname}")
+  private String hostname;
+  @Value("${scheduler.host.username}")
+  private String username;
+  @Value("${scheduler.host.password}")
+  private String password;
+
+
+  @Resource
+  private ManualProjectMapper manualProjectMapper;
+  @Resource
+  private AutoSubProjectMapper autoSubProjectMapper;
+  @Resource
+  private UserMapper userMapper;
+  @Resource
+  private ClusterMapper clusterMapper;
+  @Resource
+  private EsminiConfiguration esminiConfiguration;
+  @Resource
+  private KubernetesConfiguration kubernetesConfiguration;
+  @Resource
+  private ApiClient apiClient;
+  @Resource
+  private StringRedisTemplate stringRedisTemplate;
+  @Resource
+  private CustomRedisClient customRedisClient;
+
+
+  @SneakyThrows
+  public void deleteYamlByProjectId(String projectId) {
+    List<String> absolutePathList = FileUtil.listAbsolutePath(podYamlDirectory);
+    for (String absolutePath : absolutePathList) {
+      if (absolutePath.contains(projectId)) {
+        boolean delete = new File(absolutePath).delete();
+      }
     }
-
-    public String getPodYamlName(String nodeName, String podName) {
-        return nodeName + "#" + podName + ".yaml";
-    }
-
-
-    public void deletePod(String podName) {
-        try {
-            // 先删除 redis key
-            KubernetesUtil.deletePod(apiClient, kubernetesConfiguration.getNamespace(), podName);
-            log.info("等待 pod " + podName + " 的资源释放完成。");
-            TimeUnit.SECONDS.sleep(7);
-        } catch (ApiException apiException) {
-            log.info("pod " + podName + " 已删除。");
-        } catch (Exception e) {
-            e.printStackTrace();
-            log.error("删除 pod " + podName + " 报错。", e);
-        }
-    }
-
-
-    public String getNodeNameOfPod(String projectId, String podName) {
-        String key = "project:" + projectId + ":pod:" + podName + ":node";
-        final String s = stringRedisTemplate.opsForValue().get(key);
-        if (StringUtil.isEmpty(s)) {
-            throw new RuntimeException("无法获取 pod 运行所在节点:" + key);
-        }
-        return s;
+  }
+
+
+  public List<NodeEntity> getNodeListToCount(Map<String, Integer> nodeMap) {
+    List<NodeEntity> result = new ArrayList<>();
+    nodeMap.forEach((nodeName, parallelism) -> {
+      for (int i = 0; i < parallelism; i++) {
+        result.add(new NodeEntity(nodeName, 0));
+      }
+    });
+    return result;
+  }
+
+  /**
+   * 判断算法是否已经导入
+   *
+   * @return 算法是否已经导入
+   */
+  @SneakyThrows
+  public boolean isImported(String dockerImageWithoutVersion) {
+    String dockerImageListString = LinuxUtil.execute("docker images");
+    return dockerImageListString.contains(dockerImageWithoutVersion);
+  }
+
+  public String getRandomPodName(String projectId) {
+    return "project-" + projectId + "-" + StringUtil.getRandomEightBitUUID();
+  }
+
+  public String getPodYamlName(String nodeName, String podName) {
+    return nodeName + "#" + podName + ".yaml";
+  }
+
+
+  public void deletePod(String podName) {
+    try {
+      // 先删除 redis key
+      KubernetesUtil.deletePod(apiClient, kubernetesConfiguration.getNamespace(), podName);
+      log.info("等待 pod " + podName + " 的资源释放完成。");
+      TimeUnit.SECONDS.sleep(7);
+    } catch (ApiException apiException) {
+      log.info("pod " + podName + " 已删除。");
+    } catch (Exception e) {
+      e.printStackTrace();
+      log.error("删除 pod " + podName + " 报错。", e);
     }
+  }
 
 
-    /**
-     * 更改一个名字继续启动
-     *
-     * @param projectId   项目 id
-     * @param nodeName    运行 pod 的节点名称
-     * @param lastPodName 即将删除的 pod 名称
-     */
-    @SneakyThrows
-    public void createNextPod3(String projectId, String nodeName, String lastPodName) {
-        log.info("删除上一个 pod:projectId={},nodeName={},lastPodName={}", projectId, nodeName, lastPodName);
-        String cpuOrderString = stringRedisTemplate.opsForValue().get("project:" + projectId + ":pod:" + lastPodName + ":cpu");
-        deletePod(lastPodName);
-        RedisUtil.deleteByKey(stringRedisTemplate, "project:" + projectId + ":pod:" + lastPodName + ":cpu");
-        //2 获取新的 yaml 信息
-        final Set<String> yamlPathCacheKeySet = RedisUtil.getKeySetByPrefix(stringRedisTemplate, "project:" + projectId + ":node:" + nodeName + ":yaml");
-        if (CollectionUtil.isEmpty(yamlPathCacheKeySet)) {
-            // 如果当前节点没有下一个yaml,则返回一个并行度。
-            log.info("节点 " + nodeName + " 已经执行完被分配的项目 " + projectId + " 的所有 pod。");
-            incrementOneParallelismOfGpuNode(nodeName);
-        } else {
-            final String yamlPathCacheKey = new ArrayList<>(yamlPathCacheKeySet).get(0);
-            final String absolutePath = stringRedisTemplate.opsForValue().get(yamlPathCacheKey);
-            // 修改 cpu 编号
-
-            Optional.ofNullable(cpuOrderString).orElseThrow(() -> new RuntimeException("createNextPod2() pod " + lastPodName + " 缓存的 cpu 编号为空。"));
-            final String read = FileUtil.read(absolutePath);
-            final String replace = read.replace("cpu-order", "\"" + cpuOrderString + "\"");
-            FileUtil.writeStringToLocalFile(replace, absolutePath);
-            // 创建 pod
-            createPod3(projectId, yamlPathCacheKey, cpuOrderString);
-            log.info("创建项目 " + projectId + " 在节点 " + nodeName + " 的下一个 pod,使用 cpu 编号为 " + cpuOrderString);
-        }
+  public String getNodeNameOfPod(String projectId, String podName) {
+    String key = "project:" + projectId + ":pod:" + podName + ":node";
+    final String s = stringRedisTemplate.opsForValue().get(key);
+    if (StringUtil.isEmpty(s)) {
+      throw new RuntimeException("无法获取 pod 运行所在节点:" + key);
     }
-
-    /**
-     * @param redisKey yaml 地址的缓存 key
-     */
-    public void createPodBegin(String projectId, String redisKey) {
-        final String podYamlPath = stringRedisTemplate.opsForValue().get(redisKey);
-        if (podYamlPath == null) {
-            throw new RuntimeException("根据缓存 key 获取 yaml 地址为 null:" + redisKey);
-        }
-        stringRedisTemplate.delete(redisKey);
-        String nodeName = new File(podYamlPath).getName().split("#")[0];
-        String podName = podYamlPath.split("#")[1].split("\\.")[0];
-        stringRedisTemplate.opsForValue().set("project:" + projectId + ":pod:" + podName + ":node", nodeName);    // 将 pod 运行在哪个 node 上记录到 redis
-        new Thread(() -> KubernetesUtil.applyYaml(hostname, username, password, podYamlPath), "apply-" + podName).start();
+    return s;
+  }
+
+
+  /**
+   * 更改一个名字继续启动
+   *
+   * @param projectId   项目 id
+   * @param nodeName    运行 pod 的节点名称
+   * @param lastPodName 即将删除的 pod 名称
+   */
+  @SneakyThrows
+  public void createNextPod(String projectId, String nodeName, String lastPodName) {
+    log.info("删除上一个 pod:projectId={},nodeName={},lastPodName={}", projectId, nodeName, lastPodName);
+    String cpuOrderString = stringRedisTemplate.opsForValue().get("project:" + projectId + ":pod:" + lastPodName + ":cpu");
+    deletePod(lastPodName);
+    RedisUtil.deleteByKey(stringRedisTemplate, "project:" + projectId + ":pod:" + lastPodName + ":cpu");
+    //2 获取新的 yaml 信息
+    final Set<String> yamlPathCacheKeySet = RedisUtil.getKeySetByPrefix(stringRedisTemplate, "project:" + projectId + ":node:" + nodeName + ":yaml");
+    if (CollectionUtil.isEmpty(yamlPathCacheKeySet)) {
+      // 如果当前节点没有下一个yaml,则返回一个并行度。
+      log.info("节点 " + nodeName + " 已经执行完被分配的项目 " + projectId + " 的所有 pod。");
+      incrementOneParallelismOfGpuNode(nodeName);
+    } else {
+      final String yamlPathCacheKey = new ArrayList<>(yamlPathCacheKeySet).get(0);
+      final String absolutePath = stringRedisTemplate.opsForValue().get(yamlPathCacheKey);
+      // 修改 cpu 编号
+      Optional.ofNullable(cpuOrderString).orElseThrow(() -> new RuntimeException("createNextPod2() pod " + lastPodName + " 缓存的 cpu 编号为空。"));
+      final String read = FileUtil.read(absolutePath);
+      final String replace = read.replace("cpu-order", "\"" + cpuOrderString + "\"");
+      FileUtil.writeStringToLocalFile(replace, absolutePath);
+      // 创建 pod
+      createPod3(projectId, yamlPathCacheKey, cpuOrderString);
+      log.info("创建项目 " + projectId + " 在节点 " + nodeName + " 的下一个 pod,使用 cpu 编号为 " + cpuOrderString);
     }
-
-
-    /**
-     * @param redisKey yaml 地址的缓存 key
-     */
-    public void createPod3(String projectId, String redisKey, String cpuOrderString) {
-        final String podYamlPath = stringRedisTemplate.opsForValue().get(redisKey);
-        if (podYamlPath == null) {
-            throw new RuntimeException("根据缓存 key 获取 yaml 地址为 null:" + redisKey);
-        }
-        stringRedisTemplate.delete(redisKey);
-        String nodeName = new File(podYamlPath).getName().split("#")[0];
-        String podName = podYamlPath.split("#")[1].split("\\.")[0];
-        stringRedisTemplate.opsForValue().set("project:" + projectId + ":pod:" + podName + ":node", nodeName);    // 将 pod 运行在哪个 node 上记录到 redis
-        stringRedisTemplate.opsForValue().set("project:" + projectId + ":pod:" + podName + ":cpu", cpuOrderString);    // 将 pod 运行在哪个 node 上记录到 redis
-        new Thread(() -> KubernetesUtil.applyYaml(hostname, username, password, podYamlPath), "create-" + podName).start();
+  }
+
+  /**
+   * @param redisKey yaml 地址的缓存 key
+   */
+  public void createPodBegin(String projectId, String redisKey) {
+    final String podYamlPath = stringRedisTemplate.opsForValue().get(redisKey);
+    if (podYamlPath == null) {
+      throw new RuntimeException("根据缓存 key 获取 yaml 地址为 null:" + redisKey);
     }
-
-
-    public ProjectEntity getProjectByProjectId(String projectId) {
-        ProjectEntity manualProjectEntity = manualProjectMapper.selectById(projectId);
-        ProjectEntity autoSubProjectEntity = autoSubProjectMapper.selectById(projectId);
-        if (manualProjectEntity != null) {
-            return manualProjectEntity;
-        } else if (autoSubProjectEntity != null) {
-            return autoSubProjectEntity;
-        }
-        throw new RuntimeException("不存在项目:" + projectId);
+    stringRedisTemplate.delete(redisKey);
+    String nodeName = new File(podYamlPath).getName().split("#")[0];
+    String podName = podYamlPath.split("#")[1].split("\\.")[0];
+    stringRedisTemplate.opsForValue().set("project:" + projectId + ":pod:" + podName + ":node", nodeName);    // 将 pod 运行在哪个 node 上记录到 redis
+    new Thread(() -> KubernetesUtil.applyYaml(hostname, username, password, podYamlPath), "apply-" + podName).start();
+  }
+
+
+  /**
+   * @param redisKey yaml 地址的缓存 key
+   */
+  public void createPod3(String projectId, String redisKey, String cpuOrderString) {
+    final String podYamlPath = stringRedisTemplate.opsForValue().get(redisKey);
+    if (podYamlPath == null) {
+      throw new RuntimeException("根据缓存 key 获取 yaml 地址为 null:" + redisKey);
     }
-
-
-    /**
-     * 获取正在运行的项目的并行度总和
-     *
-     * @param clusterRunningPrefix 集群 key 前缀
-     * @return 正在运行的项目的并行度总和
-     */
-    @SneakyThrows
-    public int getCurrentParallelismSum(String clusterRunningPrefix) {
-        int result = 0;
-        Set<String> clusterRunningKeySet = stringRedisTemplate.keys(clusterRunningPrefix + "*");
-        List<String> runningProjectSet; // 运行中的 projectId 列表
-        if (CollectionUtil.isEmpty(clusterRunningKeySet)) {
-            return 0;
-        }
-        runningProjectSet = getRunningProjectList(clusterRunningKeySet);
-        if (CollectionUtil.isEmpty(runningProjectSet)) {
-            return 0;
-        }
-        for (String projectKey : runningProjectSet) {
-            String projectJsonTemp = stringRedisTemplate.opsForValue().get(projectKey);
-            ProjectMessageDTO projectMessageTemp = JsonUtil.jsonToBean(projectJsonTemp, ProjectMessageDTO.class);
-            result += projectMessageTemp.getCurrentParallelism();   // 获取当前正在使用的并行度
-        }
-        return result;
+    stringRedisTemplate.delete(redisKey);
+    String nodeName = new File(podYamlPath).getName().split("#")[0];
+    String podName = podYamlPath.split("#")[1].split("\\.")[0];
+    stringRedisTemplate.opsForValue().set("project:" + projectId + ":pod:" + podName + ":node", nodeName);    // 将 pod 运行在哪个 node 上记录到 redis
+    stringRedisTemplate.opsForValue().set("project:" + projectId + ":pod:" + podName + ":cpu", cpuOrderString);    // 将 pod 运行在哪个 node 上记录到 redis
+    new Thread(() -> KubernetesUtil.applyYaml(hostname, username, password, podYamlPath), "create-" + podName).start();
+  }
+
+
+  public ProjectEntity getProjectByProjectId(String projectId) {
+    ProjectEntity manualProjectEntity = manualProjectMapper.selectById(projectId);
+    ProjectEntity autoSubProjectEntity = autoSubProjectMapper.selectById(projectId);
+    if (manualProjectEntity != null) {
+      return manualProjectEntity;
+    } else if (autoSubProjectEntity != null) {
+      return autoSubProjectEntity;
     }
-
-
-    /**
-     * 节点剩余可用并行度列表
-     *
-     * @return 节点映射(节点名,并行度)
-     */
-    public Map<String, Integer> getNodeMap() {
-        List<GpuNodeEntity> initialNodeList = kubernetesConfiguration.getNodeList(); // 预设并行度的节点列表
-        log.info("预设并行度的节点列表为:" + initialNodeList);
-        Map<String, Integer> resultNodeMap = new HashMap<>();    // 用于执行的节点映射(节点名,并行度)
-        for (GpuNodeEntity kubernetesNodeSource : initialNodeList) {
-            GpuNodeEntity kubernetesNodeCopy = kubernetesNodeSource.clone();
-            String nodeName = kubernetesNodeCopy.getHostname();
-            int maxParallelism = kubernetesNodeCopy.getParallelism();
-            String restParallelismKey = "gpu-node:" + nodeName + ":parallelism";
-            String restParallelismString = stringRedisTemplate.opsForValue().get(restParallelismKey);
-            int restParallelism;
-            if (restParallelismString == null) {    // 如果剩余可用并行度没有值,说明是第一次查询,则重置成最大并行度的预设值
-                restParallelism = maxParallelism;
-                stringRedisTemplate.opsForValue().set(restParallelismKey, restParallelism + "");
-            } else {
-                restParallelism = Integer.parseInt(restParallelismString);
-            }
-            resultNodeMap.put(nodeName, restParallelism);
-        }
-        log.info("剩余并行度的节点列表为:" + resultNodeMap);
-        return resultNodeMap;
+    throw new RuntimeException("不存在项目:" + projectId);
+  }
+
+
+  /**
+   * 获取正在运行的项目的并行度总和
+   *
+   * @param clusterRunningPrefix 集群 key 前缀
+   * @return 正在运行的项目的并行度总和
+   */
+  @SneakyThrows
+  public int getCurrentParallelismSum(String clusterRunningPrefix) {
+    int result = 0;
+    Set<String> clusterRunningKeySet = stringRedisTemplate.keys(clusterRunningPrefix + "*");
+    List<String> runningProjectSet; // 运行中的 projectId 列表
+    if (CollectionUtil.isEmpty(clusterRunningKeySet)) {
+      return 0;
     }
-
-
-    /**
-     * 获取集群剩余并行度
-     *
-     * @return 集群剩余并行度
-     */
-    public int getRestParallelism() {
-        List<GpuNodeEntity> initialNodeList = kubernetesConfiguration.getNodeList(); // 预设并行度的节点列表
-        // 遍历所有节点,获取还有剩余并行度的节点
-        List<GpuNodeEntity> restNodeList = new ArrayList<>();    // 剩余并行度的节点列表
-        for (GpuNodeEntity kubernetesNodeSource : initialNodeList) {
-            GpuNodeEntity kubernetesNodeCopy = kubernetesNodeSource.clone();
-            String nodeName = kubernetesNodeCopy.getHostname();   // 节点名称
-            int maxParallelism = kubernetesNodeCopy.getParallelism();
-            String restParallelismString = stringRedisTemplate.opsForValue().get("gpu-node:" + nodeName + ":parallelism");// 获取节点剩余并行度的 key
-            // -------------------------------- Comment --------------------------------
-            int restParallelism;
-            if (restParallelismString == null || Integer.parseInt(restParallelismString) > maxParallelism) {    // 如果剩余可用并行度没有值,说明是第一次查询,则重置成最大并行度的预设值
-                restParallelism = maxParallelism;
-                stringRedisTemplate.opsForValue().set("gpu-node:" + nodeName + ":parallelism", restParallelism + "");
-            } else {
-                restParallelism = Integer.parseInt(restParallelismString);
-                kubernetesNodeCopy.setParallelism(restParallelism);
-            }
-            if (restParallelism > 0) {
-                restNodeList.add(kubernetesNodeCopy);
-            }
-        }
-        log.info("ProjectUtil--getRestParallelism 集群剩余并行度为:" + restNodeList);
-        return restNodeList.size() == 0 ? 0 : restNodeList.stream().mapToInt(GpuNodeEntity::getParallelism).sum();
+    runningProjectSet = getRunningProjectList(clusterRunningKeySet);
+    if (CollectionUtil.isEmpty(runningProjectSet)) {
+      return 0;
     }
-
-    /**
-     * 根据并行度获取用于执行的节点列表
-     * 根据剩余可用并行度降序排序
-     *
-     * @return 节点映射(节点名,并行度)
-     */
-    public Map<String, Integer> getNodeMapToUse(int parallelism) {
-        List<GpuNodeEntity> initialNodeList = kubernetesConfiguration.getNodeList(); // 预设并行度的节点列表
-        log.info("预设并行度的节点列表为:" + initialNodeList);
-        // 遍历所有节点,获取还有剩余并行度的节点
-        List<GpuNodeEntity> restNodeList = new ArrayList<>();    // 剩余并行度的节点列表
-        for (GpuNodeEntity kubernetesNodeSource : initialNodeList) {
-            GpuNodeEntity kubernetesNodeCopy = kubernetesNodeSource.clone();
-            String nodeName = kubernetesNodeCopy.getHostname();   // 节点名称
-            int maxParallelism = kubernetesNodeCopy.getParallelism();
-            String restParallelismString = stringRedisTemplate.opsForValue().get("gpu-node:" + nodeName + ":parallelism");// 获取节点剩余并行度的 key
-            // -------------------------------- Comment --------------------------------
-            int restParallelism;
-            if (restParallelismString == null || Integer.parseInt(restParallelismString) > maxParallelism) {    // 如果剩余可用并行度没有值,说明是第一次查询,则重置成最大并行度的预设值
-                restParallelism = maxParallelism;
-                stringRedisTemplate.opsForValue().set("gpu-node:" + nodeName + ":parallelism", restParallelism + "");
-            } else {
-                restParallelism = Integer.parseInt(restParallelismString);
-                kubernetesNodeCopy.setParallelism(restParallelism);
-            }
-            if (restParallelism > 0) {
-                restNodeList.add(kubernetesNodeCopy);
-            }
-        }
-        log.info("剩余并行度的节点列表为:" + restNodeList);
-        Map<String, Integer> resultNodeMap = new HashMap<>();    // 用于执行的节点映射(节点名,并行度)
-        if (!CollectionUtil.isEmpty(restNodeList)) {
-            if (restNodeList.size() == 1) {
-                GpuNodeEntity tempNode = restNodeList.get(0);
-                String tempNodeName = tempNode.getHostname();
-                int tempParallelism = tempNode.getParallelism();
-                resultNodeMap.put(tempNodeName, Math.min(tempParallelism, parallelism));
-            }
-            if (restNodeList.size() > 1) {
-                for (int i = 0; i < parallelism; i++) {
-                    // 每次降序排序都取剩余并行度最大的一个。
-                    restNodeList.sort((o1, o2) -> o2.getParallelism() - o1.getParallelism());
-                    GpuNodeEntity tempNode = restNodeList.get(0);
-                    String tempNodeName = tempNode.getHostname();
-                    int tempParallelism = tempNode.getParallelism();
-                    if (tempParallelism > 0) {
-                        tempNode.setParallelism(tempParallelism - 1);
-                        CollectionUtil.addValueToMap(resultNodeMap, 1, tempNodeName);
-                    }
-                }
-            }
-        }
-        log.info("即将使用节点的并行度为:" + resultNodeMap);
-        return resultNodeMap;
+    for (String projectKey : runningProjectSet) {
+      String projectJsonTemp = stringRedisTemplate.opsForValue().get(projectKey);
+      ProjectMessageDTO projectMessageTemp = JsonUtil.jsonToBean(projectJsonTemp, ProjectMessageDTO.class);
+      result += projectMessageTemp.getCurrentParallelism();   // 获取当前正在使用的并行度
     }
-
-
-    public PrefixEntity getRedisPrefixByUserIdAndProjectIdAndTaskId(String userId, String projectId, String taskId) {
-        //3 获取用户类型(管理员账户、管理员子账户、普通账户、普通子账户)(独占、共享)
-        UserEntity userEntity = userMapper.selectById(userId);
-        String roleCode = userEntity.getRoleCode();
-        String useType = userEntity.getUseType();
-        String clusterId;
-        if (DictConstants.ROLE_CODE_SYSADMIN.equals(roleCode) || DictConstants.ROLE_CODE_ADMIN.equals(roleCode)) {  //3-1 管理员账户和管理员子账户直接执行
-            clusterId = DictConstants.SYSTEM_CLUSTER_ID;
-        } else if (DictConstants.ROLE_CODE_UESR.equals(roleCode)) { //3-2 普通账户,不管是独占还是共享,都在自己的集群里排队,根据自己的独占节点排队
-            clusterId = clusterMapper.selectByUserId(userId).getId();
-        } else if (DictConstants.ROLE_CODE_SUBUESR.equals(roleCode)) {
-            if (DictConstants.USER_TYPE_EXCLUSIVE.equals(useType)) {   //3-3 普通子账户,根据自己的独占节点排队
-                clusterId = clusterMapper.selectByUserId(userId).getId();
-            } else {    //3-4 共享子账户,根据父账户的共享节点排队
-                String parentUserId = userEntity.getCreateUserId();
-                clusterId = clusterMapper.selectByUserId(parentUserId).getId();
-            }
-        } else {
-            throw new RuntimeException("未知账户类型,无法获取集群信息。");
-        }
-        String clusterPrefix = "cluster:" + clusterId;
-        String clusterRunningPrefix = clusterPrefix + ":running";
-        String projectRunningKey = clusterRunningPrefix + ":" + projectId;
-        String taskTickKey = projectRunningKey + ":task:" + taskId + ":tick";
-        String taskPodKey = projectRunningKey + ":task:" + taskId + ":pod";
-        String taskRetryKey = projectRunningKey + ":task:" + taskId + ":retry";
-        String taskMessageKey = projectRunningKey + ":task:" + taskId + ":message";
-
-        return PrefixEntity.builder()
-                .clusterPrefix(clusterPrefix)
-                .clusterRunningPrefix(clusterRunningPrefix)
-                .projectRunningKey(projectRunningKey)
-                .taskTickKey(taskTickKey)
-                .taskPodKey(taskPodKey)
-                .taskRetryKey(taskRetryKey)
-                .taskMessageKey(taskMessageKey)
-                .build();
-
+    return result;
+  }
+
+
+  /**
+   * 节点剩余可用并行度列表
+   *
+   * @return 节点映射(节点名,并行度)
+   */
+  public Map<String, Integer> getNodeMap() {
+    List<GpuNodeEntity> initialNodeList = kubernetesConfiguration.getNodeList(); // 预设并行度的节点列表
+    log.info("预设并行度的节点列表为:" + initialNodeList);
+    Map<String, Integer> resultNodeMap = new HashMap<>();    // 用于执行的节点映射(节点名,并行度)
+    for (GpuNodeEntity kubernetesNodeSource : initialNodeList) {
+      GpuNodeEntity kubernetesNodeCopy = kubernetesNodeSource.clone();
+      String nodeName = kubernetesNodeCopy.getHostname();
+      int maxParallelism = kubernetesNodeCopy.getParallelism();
+      String restParallelismKey = "gpu-node:" + nodeName + ":parallelism";
+      String restParallelismString = stringRedisTemplate.opsForValue().get(restParallelismKey);
+      int restParallelism;
+      if (restParallelismString == null) {    // 如果剩余可用并行度没有值,说明是第一次查询,则重置成最大并行度的预设值
+        restParallelism = maxParallelism;
+        stringRedisTemplate.opsForValue().set(restParallelismKey, restParallelism + "");
+      } else {
+        restParallelism = Integer.parseInt(restParallelismString);
+      }
+      resultNodeMap.put(nodeName, restParallelism);
     }
-
-
-    public PrefixEntity getRedisPrefixByClusterIdAndProjectId(String clusterId, String projectId) {
-        String clusterPrefix = "cluster:" + clusterId;
-        String clusterRunningPrefix = clusterPrefix + ":running";
-        String clusterWaitingPrefix = clusterPrefix + ":waiting";
-        String projectRunningKey = clusterRunningPrefix + ":" + projectId;
-        String projectWaitingKey = clusterWaitingPrefix + ":" + projectId;
-        String projectCheckKey = clusterWaitingPrefix + ":" + projectId + ":check";
-
-        return PrefixEntity.builder()
-                .clusterPrefix(clusterPrefix)
-                .clusterRunningPrefix(clusterRunningPrefix)
-                .clusterWaitingPrefix(clusterWaitingPrefix)
-                .projectRunningKey(projectRunningKey)
-                .projectWaitingKey(projectWaitingKey)
-                .projectCheckKey(projectCheckKey)
-                .build();
-
+    log.info("剩余并行度的节点列表为:" + resultNodeMap);
+    return resultNodeMap;
+  }
+
+
+  /**
+   * 获取集群剩余并行度
+   *
+   * @return 集群剩余并行度
+   */
+  public int getRestParallelism() {
+    List<GpuNodeEntity> initialNodeList = kubernetesConfiguration.getNodeList(); // 预设并行度的节点列表
+    // 遍历所有节点,获取还有剩余并行度的节点
+    List<GpuNodeEntity> restNodeList = new ArrayList<>();    // 剩余并行度的节点列表
+    for (GpuNodeEntity kubernetesNodeSource : initialNodeList) {
+      GpuNodeEntity kubernetesNodeCopy = kubernetesNodeSource.clone();
+      String nodeName = kubernetesNodeCopy.getHostname();   // 节点名称
+      int maxParallelism = kubernetesNodeCopy.getParallelism();
+      String restParallelismString = stringRedisTemplate.opsForValue().get("gpu-node:" + nodeName + ":parallelism");// 获取节点剩余并行度的 key
+      // -------------------------------- Comment --------------------------------
+      int restParallelism;
+      if (restParallelismString == null || Integer.parseInt(restParallelismString) > maxParallelism) {    // 如果剩余可用并行度没有值,说明是第一次查询,则重置成最大并行度的预设值
+        restParallelism = maxParallelism;
+        stringRedisTemplate.opsForValue().set("gpu-node:" + nodeName + ":parallelism", restParallelism + "");
+      } else {
+        restParallelism = Integer.parseInt(restParallelismString);
+        kubernetesNodeCopy.setParallelism(restParallelism);
+      }
+      if (restParallelism > 0) {
+        restNodeList.add(kubernetesNodeCopy);
+      }
     }
-
-
-    /**
-     * 获取 projectId 列表
-     *
-     * @param clusterRunningKeySet 集群下的所有键值对(包括运行中的项目和等待中的项目)
-     * @return projectId 列表
-     */
-    public List<String> getRunningProjectList(Set<String> clusterRunningKeySet) {
-        return clusterRunningKeySet.stream().filter(key -> StringUtil.countSubString(key, ":") == 3).collect(Collectors.toList());
+    log.info("ProjectUtil--getRestParallelism 集群剩余并行度为:" + restNodeList);
+    return restNodeList.size() == 0 ? 0 : restNodeList.stream().mapToInt(GpuNodeEntity::getParallelism).sum();
+  }
+
+  /**
+   * 根据并行度获取用于执行的节点列表
+   * 根据剩余可用并行度降序排序
+   *
+   * @return 节点映射(节点名,并行度)
+   */
+  public Map<String, Integer> getNodeMapToUse(int parallelism) {
+    List<GpuNodeEntity> initialNodeList = kubernetesConfiguration.getNodeList(); // 预设并行度的节点列表
+    log.info("预设并行度的节点列表为:" + initialNodeList);
+    // 遍历所有节点,获取还有剩余并行度的节点
+    List<GpuNodeEntity> restNodeList = new ArrayList<>();    // 剩余并行度的节点列表
+    for (GpuNodeEntity kubernetesNodeSource : initialNodeList) {
+      GpuNodeEntity kubernetesNodeCopy = kubernetesNodeSource.clone();
+      String nodeName = kubernetesNodeCopy.getHostname();   // 节点名称
+      int maxParallelism = kubernetesNodeCopy.getParallelism();
+      String restParallelismString = stringRedisTemplate.opsForValue().get("gpu-node:" + nodeName + ":parallelism");// 获取节点剩余并行度的 key
+      // -------------------------------- Comment --------------------------------
+      int restParallelism;
+      if (restParallelismString == null || Integer.parseInt(restParallelismString) > maxParallelism) {    // 如果剩余可用并行度没有值,说明是第一次查询,则重置成最大并行度的预设值
+        restParallelism = maxParallelism;
+        stringRedisTemplate.opsForValue().set("gpu-node:" + nodeName + ":parallelism", restParallelism + "");
+      } else {
+        restParallelism = Integer.parseInt(restParallelismString);
+        kubernetesNodeCopy.setParallelism(restParallelism);
+      }
+      if (restParallelism > 0) {
+        restNodeList.add(kubernetesNodeCopy);
+      }
     }
-
-
-    public PrefixEntity getRedisPrefixByProjectIdAndProjectType(String projectId, String projectType) {
-        String userId;
-        if (DictConstants.PROJECT_TYPE_MANUAL.equals(projectType)) {
-            userId = manualProjectMapper.selectCreateUserById(projectId);
-        } else if (DictConstants.PROJECT_TYPE_AUTO_SUB.equals(projectType)) {
-            userId = autoSubProjectMapper.selectCreateUserById(projectId);
-        } else {
-            throw new RuntimeException("未知的项目类型。");
+    log.info("剩余并行度的节点列表为:" + restNodeList);
+    Map<String, Integer> resultNodeMap = new HashMap<>();    // 用于执行的节点映射(节点名,并行度)
+    if (!CollectionUtil.isEmpty(restNodeList)) {
+      if (restNodeList.size() == 1) {
+        GpuNodeEntity tempNode = restNodeList.get(0);
+        String tempNodeName = tempNode.getHostname();
+        int tempParallelism = tempNode.getParallelism();
+        resultNodeMap.put(tempNodeName, Math.min(tempParallelism, parallelism));
+      }
+      if (restNodeList.size() > 1) {
+        for (int i = 0; i < parallelism; i++) {
+          // 每次降序排序都取剩余并行度最大的一个。
+          restNodeList.sort((o1, o2) -> o2.getParallelism() - o1.getParallelism());
+          GpuNodeEntity tempNode = restNodeList.get(0);
+          String tempNodeName = tempNode.getHostname();
+          int tempParallelism = tempNode.getParallelism();
+          if (tempParallelism > 0) {
+            tempNode.setParallelism(tempParallelism - 1);
+            CollectionUtil.addValueToMap(resultNodeMap, 1, tempNodeName);
+          }
         }
-
-        //3 获取用户类型(管理员账户、管理员子账户、普通账户、普通子账户)(独占、共享)
-        UserEntity userEntity = userMapper.selectById(userId);
-        String roleCode = userEntity.getRoleCode();
-        String useType = userEntity.getUseType();
-        String clusterId;
-        if (DictConstants.ROLE_CODE_SYSADMIN.equals(roleCode) || DictConstants.ROLE_CODE_ADMIN.equals(roleCode)) {  //3-1 管理员账户和管理员子账户直接执行
-            clusterId = DictConstants.SYSTEM_CLUSTER_ID;
-        } else if (DictConstants.ROLE_CODE_UESR.equals(roleCode)) { //3-2 普通账户,不管是独占还是共享,都在自己的集群里排队,根据自己的独占节点排队
-            clusterId = clusterMapper.selectByUserId(userId).getId();
-        } else if (DictConstants.ROLE_CODE_SUBUESR.equals(roleCode)) {
-            if (DictConstants.USER_TYPE_EXCLUSIVE.equals(useType)) {   //3-3 普通子账户,根据自己的独占节点排队
-                clusterId = clusterMapper.selectByUserId(userId).getId();
-            } else {    //3-4 共享子账户,根据父账户的共享节点排队
-                String parentUserId = userEntity.getCreateUserId();
-                clusterId = clusterMapper.selectByUserId(parentUserId).getId();
-            }
-        } else {
-            throw new RuntimeException("未知账户类型,无法获取集群信息!");
-        }
-        String clusterPrefix = "cluster:" + clusterId;
-        String clusterRunningPrefix = clusterPrefix + ":running";
-        String clusterWaitingPrefix = clusterPrefix + ":waiting";
-        String projectRunningKey = clusterRunningPrefix + ":" + projectId;
-        String projectWaitingKey = clusterWaitingPrefix + ":" + projectId;
-        String projectCheckKey = projectRunningKey + ":check";
-
-        return PrefixEntity.builder()
-                .clusterPrefix(clusterPrefix)
-                .clusterRunningPrefix(clusterRunningPrefix)
-                .clusterWaitingPrefix(clusterWaitingPrefix)
-                .projectRunningKey(projectRunningKey)
-                .projectWaitingKey(projectWaitingKey)
-                .projectCheckKey(projectCheckKey)
-                .build();
-    }
-
-
-    public void incrementOneParallelismOfGpuNode(String nodeName) {
-        incrementParallelismOfGpuNode(nodeName, 1L);
+      }
     }
-
-    public void incrementParallelismOfGpuNode(String nodeName, long number) {
-        String key = "gpu-node:" + nodeName + ":parallelism";
-        customRedisClient.increment(key, 1L);
-        log.info("归还节点 {} 的 {} 个 GPU 并行度。", nodeName, number);
+    log.info("即将使用节点的并行度为:" + resultNodeMap);
+    return resultNodeMap;
+  }
+
+
+  public PrefixEntity getRedisPrefixByUserIdAndProjectIdAndTaskId(String userId, String projectId, String taskId) {
+    //3 获取用户类型(管理员账户、管理员子账户、普通账户、普通子账户)(独占、共享)
+    UserEntity userEntity = userMapper.selectById(userId);
+    String roleCode = userEntity.getRoleCode();
+    String useType = userEntity.getUseType();
+    String clusterId;
+    if (DictConstants.ROLE_CODE_SYSADMIN.equals(roleCode) || DictConstants.ROLE_CODE_ADMIN.equals(roleCode)) {  //3-1 管理员账户和管理员子账户直接执行
+      clusterId = DictConstants.SYSTEM_CLUSTER_ID;
+    } else if (DictConstants.ROLE_CODE_UESR.equals(roleCode)) { //3-2 普通账户,不管是独占还是共享,都在自己的集群里排队,根据自己的独占节点排队
+      clusterId = clusterMapper.selectByUserId(userId).getId();
+    } else if (DictConstants.ROLE_CODE_SUBUESR.equals(roleCode)) {
+      if (DictConstants.USER_TYPE_EXCLUSIVE.equals(useType)) {   //3-3 普通子账户,根据自己的独占节点排队
+        clusterId = clusterMapper.selectByUserId(userId).getId();
+      } else {    //3-4 共享子账户,根据父账户的共享节点排队
+        String parentUserId = userEntity.getCreateUserId();
+        clusterId = clusterMapper.selectByUserId(parentUserId).getId();
+      }
+    } else {
+      throw new RuntimeException("未知账户类型,无法获取集群信息。");
     }
-
-    public void decrementParallelismOfGpuNode(String nodeName, long number) {
-        String key = "gpu-node:" + nodeName + ":parallelism";
-        customRedisClient.decrement(key, number);
-        log.info("获取节点 {} 的 {} 个 GPU 并行度。", nodeName, number);
+    String clusterPrefix = "cluster:" + clusterId;
+    String clusterRunningPrefix = clusterPrefix + ":running";
+    String projectRunningKey = clusterRunningPrefix + ":" + projectId;
+    String taskTickKey = projectRunningKey + ":task:" + taskId + ":tick";
+    String taskPodKey = projectRunningKey + ":task:" + taskId + ":pod";
+    String taskRetryKey = projectRunningKey + ":task:" + taskId + ":retry";
+    String taskMessageKey = projectRunningKey + ":task:" + taskId + ":message";
+
+    return PrefixEntity.builder().clusterPrefix(clusterPrefix).clusterRunningPrefix(clusterRunningPrefix).projectRunningKey(projectRunningKey).taskTickKey(taskTickKey).taskPodKey(taskPodKey).taskRetryKey(taskRetryKey).taskMessageKey(taskMessageKey).build();
+
+  }
+
+
+  public PrefixEntity getRedisPrefixByClusterIdAndProjectId(String clusterId, String projectId) {
+    String clusterPrefix = "cluster:" + clusterId;
+    String clusterRunningPrefix = clusterPrefix + ":running";
+    String clusterWaitingPrefix = clusterPrefix + ":waiting";
+    String projectRunningKey = clusterRunningPrefix + ":" + projectId;
+    String projectWaitingKey = clusterWaitingPrefix + ":" + projectId;
+    String projectCheckKey = clusterWaitingPrefix + ":" + projectId + ":check";
+
+    return PrefixEntity.builder().clusterPrefix(clusterPrefix).clusterRunningPrefix(clusterRunningPrefix).clusterWaitingPrefix(clusterWaitingPrefix).projectRunningKey(projectRunningKey).projectWaitingKey(projectWaitingKey).projectCheckKey(projectCheckKey).build();
+
+  }
+
+
+  /**
+   * 获取 projectId 列表
+   *
+   * @param clusterRunningKeySet 集群下的所有键值对(包括运行中的项目和等待中的项目)
+   * @return projectId 列表
+   */
+  public List<String> getRunningProjectList(Set<String> clusterRunningKeySet) {
+    return clusterRunningKeySet.stream().filter(key -> StringUtil.countSubString(key, ":") == 3).collect(Collectors.toList());
+  }
+
+
+  public PrefixEntity getRedisPrefixByProjectIdAndProjectType(String projectId, String projectType) {
+    String userId;
+    if (DictConstants.PROJECT_TYPE_MANUAL.equals(projectType)) {
+      userId = manualProjectMapper.selectCreateUserById(projectId);
+    } else if (DictConstants.PROJECT_TYPE_AUTO_SUB.equals(projectType)) {
+      userId = autoSubProjectMapper.selectCreateUserById(projectId);
+    } else {
+      throw new RuntimeException("未知的项目类型。");
     }
 
-
-    public List<String> getWaitingProjectMessageKeys() {
-        final Set<String> keys = stringRedisTemplate.keys("*");
-        if (CollectionUtil.isEmpty(keys)) {
-            return new ArrayList<>();
-        } else {
-            return keys.stream().filter(key -> key.contains("waiting") && key.contains("message")).collect(Collectors.toList());
-        }
+    //3 获取用户类型(管理员账户、管理员子账户、普通账户、普通子账户)(独占、共享)
+    UserEntity userEntity = userMapper.selectById(userId);
+    String roleCode = userEntity.getRoleCode();
+    String useType = userEntity.getUseType();
+    String clusterId;
+    if (DictConstants.ROLE_CODE_SYSADMIN.equals(roleCode) || DictConstants.ROLE_CODE_ADMIN.equals(roleCode)) {  //3-1 管理员账户和管理员子账户直接执行
+      clusterId = DictConstants.SYSTEM_CLUSTER_ID;
+    } else if (DictConstants.ROLE_CODE_UESR.equals(roleCode)) { //3-2 普通账户,不管是独占还是共享,都在自己的集群里排队,根据自己的独占节点排队
+      clusterId = clusterMapper.selectByUserId(userId).getId();
+    } else if (DictConstants.ROLE_CODE_SUBUESR.equals(roleCode)) {
+      if (DictConstants.USER_TYPE_EXCLUSIVE.equals(useType)) {   //3-3 普通子账户,根据自己的独占节点排队
+        clusterId = clusterMapper.selectByUserId(userId).getId();
+      } else {    //3-4 共享子账户,根据父账户的共享节点排队
+        String parentUserId = userEntity.getCreateUserId();
+        clusterId = clusterMapper.selectByUserId(parentUserId).getId();
+      }
+    } else {
+      throw new RuntimeException("未知账户类型,无法获取集群信息!");
     }
-
-    public void resetNodeParallelism() {
-        kubernetesConfiguration.getNodeList().forEach((node) -> customRedisClient.set("gpu-node:" + node.getHostname() + ":parallelism", node.getParallelism() + ""));
-        esminiConfiguration.getNodeList().forEach((node) -> customRedisClient.set("cpu-node:" + node.getHostname() + ":parallelism", node.getParallelism() + ""));
+    String clusterPrefix = "cluster:" + clusterId;
+    String clusterRunningPrefix = clusterPrefix + ":running";
+    String clusterWaitingPrefix = clusterPrefix + ":waiting";
+    String projectRunningKey = clusterRunningPrefix + ":" + projectId;
+    String projectWaitingKey = clusterWaitingPrefix + ":" + projectId;
+    String projectCheckKey = projectRunningKey + ":check";
+
+    return PrefixEntity.builder().clusterPrefix(clusterPrefix).clusterRunningPrefix(clusterRunningPrefix).clusterWaitingPrefix(clusterWaitingPrefix).projectRunningKey(projectRunningKey).projectWaitingKey(projectWaitingKey).projectCheckKey(projectCheckKey).build();
+  }
+
+
+  public void incrementOneParallelismOfGpuNode(String nodeName) {
+    incrementParallelismOfGpuNode(nodeName, 1L);
+  }
+
+  public void incrementParallelismOfGpuNode(String nodeName, long number) {
+    String key = "gpu-node:" + nodeName + ":parallelism";
+    customRedisClient.increment(key, 1L);
+    log.info("归还节点 {} 的 {} 个 GPU 并行度。", nodeName, number);
+  }
+
+  public void decrementParallelismOfGpuNode(String nodeName, long number) {
+    String key = "gpu-node:" + nodeName + ":parallelism";
+    customRedisClient.decrement(key, number);
+    log.info("获取节点 {} 的 {} 个 GPU 并行度。", nodeName, number);
+  }
+
+
+  public List<String> getWaitingProjectMessageKeys() {
+    final Set<String> keys = stringRedisTemplate.keys("*");
+    if (CollectionUtil.isEmpty(keys)) {
+      return new ArrayList<>();
+    } else {
+      return keys.stream().filter(key -> key.contains("waiting") && key.contains("message")).collect(Collectors.toList());
     }
-
-    /**
-     * 判断项目完成度
-     */
-    @Synchronized
-    public boolean complete(PrefixEntity redisPrefix, String projectId) {
-        boolean result = false;
-        ProjectMessageDTO projectMessageDTO = JsonUtil.jsonToBean(customRedisClient.get(redisPrefix.getProjectRunningKey()), ProjectMessageDTO.class);
-        int taskTotal = projectMessageDTO.getTaskTotal();
-        int taskCompleted = projectMessageDTO.getTaskCompleted();
-        log.info("complete() 项目 " + projectId + " 完成进度为:" + (taskCompleted + 1) + "/" + taskTotal);
-        if (taskCompleted + 1 == taskTotal) {
-            result = true;
-        } else {    // 项目没有完成
-            projectMessageDTO.setTaskCompleted(taskCompleted + 1);  // 增加已完成任务数
-            stringRedisTemplate.opsForValue().set(redisPrefix.getProjectRunningKey(), JsonUtil.beanToJson(projectMessageDTO));
-        }
-        return result;
+  }
+
+  public void resetNodeParallelism() {
+    kubernetesConfiguration.getNodeList().forEach((node) -> customRedisClient.set("gpu-node:" + node.getHostname() + ":parallelism", node.getParallelism() + ""));
+    esminiConfiguration.getNodeList().forEach((node) -> customRedisClient.set("cpu-node:" + node.getHostname() + ":parallelism", node.getParallelism() + ""));
+  }
+
+  /**
+   * 判断项目完成度
+   */
+  @Synchronized
+  public boolean complete(PrefixEntity redisPrefix, String projectId) {
+    boolean result = false;
+    ProjectMessageDTO projectMessageDTO = JsonUtil.jsonToBean(customRedisClient.get(redisPrefix.getProjectRunningKey()), ProjectMessageDTO.class);
+    int taskTotal = projectMessageDTO.getTaskTotal();
+    int taskCompleted = projectMessageDTO.getTaskCompleted();
+    log.info("complete() 项目 " + projectId + " 完成进度为:" + (taskCompleted + 1) + "/" + taskTotal);
+    if (taskCompleted + 1 == taskTotal) {
+      result = true;
+    } else {    // 项目没有完成
+      projectMessageDTO.setTaskCompleted(taskCompleted + 1);  // 增加已完成任务数
+      stringRedisTemplate.opsForValue().set(redisPrefix.getProjectRunningKey(), JsonUtil.beanToJson(projectMessageDTO));
     }
+    return result;
+  }
 }

+ 273 - 273
simulation-resource-server/src/main/java/com/css/simulation/resource/project/controller/SimulationProjectController.java

@@ -24,280 +24,280 @@ import java.util.List;
 @RequestMapping("/simulationProject")
 public class SimulationProjectController {
 
-    @Resource
-    private SimulationProjectService service;
-    @Resource
-    private ClusterService clusterService;
-
-    //* -------------------------------- 项目运行 --------------------------------
-
-    /**
-     * 1. 手动项目:第一次运行项目
-     * 2. 手动项目:重新运行项目
-     */
-    @RequestMapping("updateProjectNowRunState")
-    public ResponseBodyVO<String> updateProjectNowRunState(@RequestBody SimulationManualProjectParam param) {
-        return service.updateProjectNowRunState(param);
-    }
-
-    /**
-     * 修改自动运行状态
-     */
-    @RequestMapping("updateAutomaticRunState")
-    public ResponseBodyVO<String> updateAutomaticRunState(@RequestBody SimulationManualProjectParam param) {
-        return service.updateAutomaticRunState(param);
-    }
-
-    /**
-     * 手动运行自动项目
-     */
-    @RequestMapping("createAutomaticSubProject")
-    public ResponseBodyVO<String> createAutomaticSubProject(@RequestBody SimulationManualProjectParam param) {
-        return service.createAutomaticSubProject(param);
-    }
-
-    //* -------------------------------- Comment --------------------------------
-
-
-    /**
-     * 导出测试报告
-     */
-    @RequestMapping("exportProjectReportById")
-    public void exportProjectReportById(@RequestBody SimulationManualProjectParam param) {
-        service.exportProjectReport(param);
-    }
-
-    //* -------------------------------- Comment --------------------------------
-
-    /**
-     * 创建/修改工作
-     */
-    @RequestMapping("addOrUpdateProject")
-    public ResponseBodyVO<String> addOrUpdateProject(@RequestBody SimulationManualProjectParam param) {
-        return service.addOrUpdateProject(param);
-    }
-
-    /**
-     * 查询项目列表
-     */
-    @RequestMapping("selectProject")
-    public ResponseBodyVO<PageInfo<SimulationManualProjectVo>> selectProject(@RequestBody SimulationManualProjectParam param) {
-        return service.selectProject(param);
-    }
-
-    /**
-     * 根据id查询
-     */
-    @RequestMapping("selectProjectById")
-    public ResponseBodyVO<SimulationManualProjectSingleVo> selectProjectById(@RequestBody SimulationManualProjectParam param) {
-        return service.selectProjectById(param);
-    }
-
-    /**
-     * 删除工作(支持批量删除)
-     */
-    @RequestMapping("deleteProjectByids")
-    public ResponseBodyVO<String> deleteProjectByids(@RequestBody SimulationManualProjectParam param) {
-        return service.deleteProjectByids(param);
-    }
-
-
-    /**
-     * 获取工作详情
-     */
-    @RequestMapping("selectProjectDetailsById")
-    public ResponseBodyVO<ProjectDetailsVo> selectProjectDetailsById(@RequestBody SimulationManualProjectParam param) {
-        return service.selectProjectDetailsById(param);
-    }
-
-    /**
-     * 获取测试报告详情
-     */
-    @RequestMapping("selectProjectReportById")
-    public ResponseBodyVO<ProjectReportVo> selectProjectReportById(@RequestBody SimulationManualProjectParam param) {
-        return service.selectProjectReportById(param);
-    }
-
-    /**
-     * 获取任务详情信息
-     */
-    @RequestMapping("selectProjectTaskById")
-    public ResponseBodyVO<ProjectTaskDetailsVo> selectProjectTaskById(@RequestBody SimulationManualProjectParam param) {
-        return service.selectProjectTaskById(param);
-    }
-
-    /**
-     * 获取添加工作时需要的下拉选项
-     * 0. 算法列表
-     * 1. 车辆列表
-     * 2. 场景列表
-     */
-    @RequestMapping("selectDropDownByType")
-    public ResponseBodyVO<List<DropDownTypeVo>> selectDropDownByType(@RequestBody SimulationManualProjectParam param) {
-        return service.selectDropDownByType(param);
-    }
-
-    /**
-     * 获取添加工作时需要的下拉选项
-     * 0. 算法列表
-     * 1. 车辆列表
-     * 2. 场景列表
-     */
-    @RequestMapping("selectDropDownByTypeNew")
-    public ResponseBodyVO<List<DropDownTypeNewVo>> selectDropDownByTypeNew(@RequestBody SimulationManualProjectParam param) {
-        return service.selectDropDownByTypeNew(param);
-    }
-
-
-    /**
-     * @return 人员可用最大并行度
-     */
-    @RequestMapping("selectMaxParallelism")
-    public ResponseBodyVO<String> selectMaxParallelism() {
-        Integer licenseNum = clusterService.getLicenseNum();
-        return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS, null, licenseNum + "");
-    }
-
-    /**
-     * 根据字典类型和
-     *
-     * @param param 参数
-     */
-    @PostMapping("getDictName")
-    public ResponseBodyVO<String> getDictName(@RequestBody DictParam param) {
-        String dictName = service.getDictName(param.getType(), param.getCode());
-        return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS, null, dictName);
-
-    }
-
-
-    /**
-     * 解析车辆坐标文件
-     */
-    @RequestMapping("analysisVehicleCoord")
-    public ResponseBodyVO<String> analysisVehicleCoord(){
-        return service.analysisVehicleCoord();
-    }
-
-
-    /**
-     * 查询工作任务列表
-     */
-    @RequestMapping("selectProjectTaskList")
-    public ResponseBodyVO<PageInfo<ManualProjectTaskVo>> selectProjectTaskList(@RequestBody SimulationManualProjectParam param) {
-        return service.selectProjectTaskList(param);
-    }
-
-
-    /**
-     * 生成保存评测等级(任务结果返回时调用)
-     *
-     * @return 响应对象
-     */
-    @RequestMapping("saveEvaluationLevel")
-    public ResponseBodyVO<String> saveEvaluationLevel(@RequestBody SimulationManualProjectParam simulationManualProjectParam) {
-        String id = simulationManualProjectParam.getId();
-        if (StringUtil.isEmpty(id)) {
-            return new ResponseBodyVO<>(ResponseBodyVO.Response.CLIENT_FAILURE, "id 不能为空", "");
-        } else {
-            return service.saveEvaluationLevel(id);
-        }
-    }
-
-    /**
-     * 保存仿真结果到数据库(任务结果返回时调用)
-     */
-    @RequestMapping("saveTaskResult")
-    public ResponseBodyVO saveTaskResult(@RequestBody SimulationManualProjectParam param) {
-        return service.saveTaskResult(param);
-    }
-
-    /**
-     * 导出工作任务文件包
-     */
-    @RequestMapping("exportProjectTaskFileById")
-    public void exportProjectTaskFileById(@RequestBody SimulationManualProjectParam param) {
-        service.exportProjectTaskFileById(param);
-    }
-
-    /**
-     * 同时导出工作报告和任务包
-     */
-    @RequestMapping("exportProjectReportAndTaskFileById")
-    public void exportProjectReportAndTaskFileById(@RequestBody SimulationManualProjectParam param) {
-        service.exportProjectReportAndTaskFileById(param);
-    }
-
-    /**
-     * 添加编辑自动项目
-     */
-    @RequestMapping("addOrUpdateAutomaticProject")
-    public ResponseBodyVO addOrUpdateAutomaticProject(@RequestBody SimulationManualProjectParam param) {
-        return service.addOrUpdateAutomaticProject(param);
-    }
-
-
-    /**
-     * 删除自动运行工作(支持批量删除)
-     */
-    @RequestMapping("deleteAutomaticProjectByids")
-    public ResponseBodyVO<String> deleteAutomaticProjectByids(@RequestBody SimulationManualProjectParam param) {
-        return service.deleteAutomaticProjectByids(param);
-    }
-
-
-    ;
-
-    /**
-     * 查询自动运行项目列表
-     */
-    @RequestMapping("selectAutomaticProject")
-    public ResponseBodyVO<PageInfo<SimulationManualProjectVo>> selectAutomaticProject(@RequestBody SimulationManualProjectParam param) {
-        return service.selectAutomaticProject(param);
-    }
-
-
-    /**
-     * 删除自动运行子项目(支持批量删除)
-     */
-    @RequestMapping("deleteAutomaticSubProjectByIds")
-    public ResponseBodyVO deleteAutomaticSubProjectByIds(@RequestBody SimulationManualProjectParam param) {
-
-        return service.deleteAutomaticSubProjectByIds(param);
-    }
-
-    /**
-     * 查询自动运行子工作信息
-     */
-    @RequestMapping("selectSubProjectInfo")
-    public ResponseBodyVO<AutomaticProjectVo> selectSubProjectInfo(@RequestBody SimulationManualProjectParam param) {
-        return service.selectSubProjectInfo(param);
-    }
-
-
-    /**
-     * 查询自动运行子工作列表
-     */
-    @RequestMapping("selectSubProjectList")
-    public ResponseBodyVO<PageInfo<SimulationManualProjectVo>> selectSubProjectList(@RequestBody SimulationManualProjectParam param) {
-        return service.selectSubProjectList(param);
-    }
-
-    /**
-     * 根据id查询自动运行项目信息
-     */
-    @RequestMapping("selectAutomaticProjectById")
-    public ResponseBodyVO<SimulationManualProjectSingleVo> selectAutomaticProjectById(@RequestBody SimulationManualProjectParam param) {
-        return service.selectAutomaticProjectById(param);
-    }
-
-    /**
-     * 修改自动运行子工作运行状态
-     */
-    @RequestMapping("updateAutoProjectNowRunState")
-    public ResponseBodyVO<String> updateAutoProjectNowRunState(@RequestBody SimulationManualProjectParam param) {
-        return service.updateAutoProjectNowRunState(param);
+  @Resource
+  private SimulationProjectService service;
+  @Resource
+  private ClusterService clusterService;
+
+  //* -------------------------------- 项目运行 --------------------------------
+
+  /**
+   * 1. 手动项目:第一次运行项目
+   * 2. 手动项目:重新运行项目
+   */
+  @RequestMapping("updateProjectNowRunState")
+  public ResponseBodyVO<String> updateProjectNowRunState(@RequestBody SimulationManualProjectParam param) {
+    return service.updateProjectNowRunState(param);
+  }
+
+  /**
+   * 修改自动运行状态
+   */
+  @RequestMapping("updateAutomaticRunState")
+  public ResponseBodyVO<String> updateAutomaticRunState(@RequestBody SimulationManualProjectParam param) {
+    return service.updateAutomaticRunState(param);
+  }
+
+  /**
+   * 手动运行自动项目
+   */
+  @RequestMapping("createAutomaticSubProject")
+  public ResponseBodyVO<String> createAutomaticSubProject(@RequestBody SimulationManualProjectParam param) {
+    return service.createAutomaticSubProject(param);
+  }
+
+  //* -------------------------------- Comment --------------------------------
+
+
+  /**
+   * 导出测试报告
+   */
+  @RequestMapping("exportProjectReportById")
+  public void exportProjectReportById(@RequestBody SimulationManualProjectParam param) {
+    service.exportProjectReport(param);
+  }
+
+  //* -------------------------------- Comment --------------------------------
+
+  /**
+   * 创建/修改工作
+   */
+  @RequestMapping("addOrUpdateProject")
+  public ResponseBodyVO<String> addOrUpdateProject(@RequestBody SimulationManualProjectParam param) {
+    return service.addOrUpdateProject(param);
+  }
+
+  /**
+   * 查询项目列表
+   */
+  @RequestMapping("selectProject")
+  public ResponseBodyVO<PageInfo<SimulationManualProjectVo>> selectProject(@RequestBody SimulationManualProjectParam param) {
+    return service.selectProject(param);
+  }
+
+  /**
+   * 根据id查询
+   */
+  @RequestMapping("selectProjectById")
+  public ResponseBodyVO<SimulationManualProjectSingleVo> selectProjectById(@RequestBody SimulationManualProjectParam param) {
+    return service.selectProjectById(param);
+  }
+
+  /**
+   * 删除工作(支持批量删除)
+   */
+  @RequestMapping("deleteProjectByids")
+  public ResponseBodyVO<String> deleteProjectByids(@RequestBody SimulationManualProjectParam param) {
+    return service.deleteProjectByids(param);
+  }
+
+
+  /**
+   * 获取工作详情
+   */
+  @RequestMapping("selectProjectDetailsById")
+  public ResponseBodyVO<ProjectDetailsVo> selectProjectDetailsById(@RequestBody SimulationManualProjectParam param) {
+    return service.selectProjectDetailsById(param);
+  }
+
+  /**
+   * 获取测试报告详情
+   */
+  @RequestMapping("selectProjectReportById")
+  public ResponseBodyVO<ProjectReportVo> selectProjectReportById(@RequestBody SimulationManualProjectParam param) {
+    return service.selectProjectReportById(param);
+  }
+
+  /**
+   * 获取任务详情信息
+   */
+  @RequestMapping("selectProjectTaskById")
+  public ResponseBodyVO<ProjectTaskDetailsVo> selectProjectTaskById(@RequestBody SimulationManualProjectParam param) {
+    return service.selectProjectTaskById(param);
+  }
+
+  /**
+   * 获取添加工作时需要的下拉选项
+   * 0. 算法列表
+   * 1. 车辆列表
+   * 2. 场景列表
+   */
+  @RequestMapping("selectDropDownByType")
+  public ResponseBodyVO<List<DropDownTypeVo>> selectDropDownByType(@RequestBody SimulationManualProjectParam param) {
+    return service.selectDropDownByType(param);
+  }
+
+  /**
+   * 获取添加工作时需要的下拉选项
+   * 0. 算法列表
+   * 1. 车辆列表
+   * 2. 场景列表
+   */
+  @RequestMapping("selectDropDownByTypeNew")
+  public ResponseBodyVO<List<DropDownTypeNewVo>> selectDropDownByTypeNew(@RequestBody SimulationManualProjectParam param) {
+    return service.selectDropDownByTypeNew(param);
+  }
+
+
+  /**
+   * @return 人员可用最大并行度
+   */
+  @RequestMapping("selectMaxParallelism")
+  public ResponseBodyVO<String> selectMaxParallelism() {
+    Integer licenseNum = clusterService.getLicenseNum();
+    return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS, null, licenseNum + "");
+  }
+
+  /**
+   * 根据字典类型和
+   *
+   * @param param 参数
+   */
+  @PostMapping("getDictName")
+  public ResponseBodyVO<String> getDictName(@RequestBody DictParam param) {
+    String dictName = service.getDictName(param.getType(), param.getCode());
+    return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS, null, dictName);
+
+  }
+
+
+  /**
+   * 解析车辆坐标文件
+   */
+  @RequestMapping("analysisVehicleCoord")
+  public ResponseBodyVO<String> analysisVehicleCoord() {
+    return service.analysisVehicleCoord();
+  }
+
+
+  /**
+   * 查询工作任务列表
+   */
+  @RequestMapping("selectProjectTaskList")
+  public ResponseBodyVO<PageInfo<ManualProjectTaskVo>> selectProjectTaskList(@RequestBody SimulationManualProjectParam param) {
+    return service.selectProjectTaskList(param);
+  }
+
+
+  /**
+   * 生成保存评测等级(任务结果返回时调用)
+   *
+   * @return 响应对象
+   */
+  @RequestMapping("saveEvaluationLevel")
+  public ResponseBodyVO<String> saveEvaluationLevel(@RequestBody SimulationManualProjectParam simulationManualProjectParam) {
+    String id = simulationManualProjectParam.getId();
+    if (StringUtil.isEmpty(id)) {
+      return new ResponseBodyVO<>(ResponseBodyVO.Response.CLIENT_FAILURE, "id 不能为空", "");
+    } else {
+      return service.saveEvaluationLevel(id);
     }
+  }
+
+  /**
+   * 保存仿真结果到数据库(任务结果返回时调用)
+   */
+  @RequestMapping("saveTaskResult")
+  public ResponseBodyVO saveTaskResult(@RequestBody SimulationManualProjectParam param) {
+    return service.saveTaskResult(param);
+  }
+
+  /**
+   * 导出工作任务文件包
+   */
+  @RequestMapping("exportProjectTaskFileById")
+  public void exportProjectTaskFileById(@RequestBody SimulationManualProjectParam param) {
+    service.exportProjectTaskFileById(param);
+  }
+
+  /**
+   * 同时导出工作报告和任务包
+   */
+  @RequestMapping("exportProjectReportAndTaskFileById")
+  public void exportProjectReportAndTaskFileById(@RequestBody SimulationManualProjectParam param) {
+    service.exportProjectReportAndTaskFileById(param);
+  }
+
+  /**
+   * 添加编辑自动项目
+   */
+  @RequestMapping("addOrUpdateAutomaticProject")
+  public ResponseBodyVO addOrUpdateAutomaticProject(@RequestBody SimulationManualProjectParam param) {
+    return service.addOrUpdateAutomaticProject(param);
+  }
+
+
+  /**
+   * 删除自动运行工作(支持批量删除)
+   */
+  @RequestMapping("deleteAutomaticProjectByids")
+  public ResponseBodyVO<String> deleteAutomaticProjectByids(@RequestBody SimulationManualProjectParam param) {
+    return service.deleteAutomaticProjectByids(param);
+  }
+
+
+  ;
+
+  /**
+   * 查询自动运行项目列表
+   */
+  @RequestMapping("selectAutomaticProject")
+  public ResponseBodyVO<PageInfo<SimulationManualProjectVo>> selectAutomaticProject(@RequestBody SimulationManualProjectParam param) {
+    return service.selectAutomaticProject(param);
+  }
+
+
+  /**
+   * 删除自动运行子项目(支持批量删除)
+   */
+  @RequestMapping("deleteAutomaticSubProjectByIds")
+  public ResponseBodyVO deleteAutomaticSubProjectByIds(@RequestBody SimulationManualProjectParam param) {
+
+    return service.deleteAutomaticSubProjectByIds(param);
+  }
+
+  /**
+   * 查询自动运行子工作信息
+   */
+  @RequestMapping("selectSubProjectInfo")
+  public ResponseBodyVO<AutomaticProjectVo> selectSubProjectInfo(@RequestBody SimulationManualProjectParam param) {
+    return service.selectSubProjectInfo(param);
+  }
+
+
+  /**
+   * 查询自动运行子工作列表
+   */
+  @RequestMapping("selectSubProjectList")
+  public ResponseBodyVO<PageInfo<SimulationManualProjectVo>> selectSubProjectList(@RequestBody SimulationManualProjectParam param) {
+    return service.selectSubProjectList(param);
+  }
+
+  /**
+   * 根据id查询自动运行项目信息
+   */
+  @RequestMapping("selectAutomaticProjectById")
+  public ResponseBodyVO<SimulationManualProjectSingleVo> selectAutomaticProjectById(@RequestBody SimulationManualProjectParam param) {
+    return service.selectAutomaticProjectById(param);
+  }
+
+  /**
+   * 修改自动运行子工作运行状态
+   */
+  @RequestMapping("updateAutoProjectNowRunState")
+  public ResponseBodyVO<String> updateAutoProjectNowRunState(@RequestBody SimulationManualProjectParam param) {
+    return service.updateAutoProjectNowRunState(param);
+  }
 
 
 }

+ 32 - 32
simulation-resource-server/src/main/java/com/css/simulation/resource/project/service/SimulationProjectService.java

@@ -11,67 +11,67 @@ import java.util.Map;
 
 public interface SimulationProjectService {
 
-    ResponseBodyVO<String> addOrUpdateProject(SimulationManualProjectParam param);
+  ResponseBodyVO<String> addOrUpdateProject(SimulationManualProjectParam param);
 
-    ResponseBodyVO<PageInfo<SimulationManualProjectVo>> selectProject(SimulationManualProjectParam param);
+  ResponseBodyVO<PageInfo<SimulationManualProjectVo>> selectProject(SimulationManualProjectParam param);
 
-    ResponseBodyVO<SimulationManualProjectSingleVo> selectProjectById(SimulationManualProjectParam param);
+  ResponseBodyVO<SimulationManualProjectSingleVo> selectProjectById(SimulationManualProjectParam param);
 
-    ResponseBodyVO<String> deleteProjectByids(SimulationManualProjectParam param);
+  ResponseBodyVO<String> deleteProjectByids(SimulationManualProjectParam param);
 
-    ResponseBodyVO<String> updateProjectNowRunState(SimulationManualProjectParam param);
+  ResponseBodyVO<String> updateProjectNowRunState(SimulationManualProjectParam param);
 
-    ResponseBodyVO<ProjectDetailsVo> selectProjectDetailsById(SimulationManualProjectParam param);
+  ResponseBodyVO<ProjectDetailsVo> selectProjectDetailsById(SimulationManualProjectParam param);
 
-    ResponseBodyVO<ProjectReportVo> selectProjectReportById(SimulationManualProjectParam param);
+  ResponseBodyVO<ProjectReportVo> selectProjectReportById(SimulationManualProjectParam param);
 
-    ResponseBodyVO<List<DropDownTypeVo>> selectDropDownByType(SimulationManualProjectParam param);
+  ResponseBodyVO<List<DropDownTypeVo>> selectDropDownByType(SimulationManualProjectParam param);
 
-    ResponseBodyVO<List<DropDownTypeNewVo>> selectDropDownByTypeNew(SimulationManualProjectParam param);
+  ResponseBodyVO<List<DropDownTypeNewVo>> selectDropDownByTypeNew(SimulationManualProjectParam param);
 
-    ResponseBodyVO<ProjectTaskDetailsVo> selectProjectTaskById(SimulationManualProjectParam param);
+  ResponseBodyVO<ProjectTaskDetailsVo> selectProjectTaskById(SimulationManualProjectParam param);
 
-    String getDictName(String type, String code);
+  String getDictName(String type, String code);
 
-    ResponseBodyVO<String> analysisVehicleCoord();
+  ResponseBodyVO<String> analysisVehicleCoord();
 
-    ResponseBodyVO<PageInfo<ManualProjectTaskVo>> selectProjectTaskList(SimulationManualProjectParam param);
+  ResponseBodyVO<PageInfo<ManualProjectTaskVo>> selectProjectTaskList(SimulationManualProjectParam param);
 
-    ResponseBodyVO<List<Map<String, Object>>> selectRunTaskByState();
+  ResponseBodyVO<List<Map<String, Object>>> selectRunTaskByState();
 
-    ResponseBodyVO<List<Map<String, Object>>> selectRunProjectByState();
+  ResponseBodyVO<List<Map<String, Object>>> selectRunProjectByState();
 
-    ResponseBodyVO<List<Map<String, Object>>> selectEvaluationLevel();
+  ResponseBodyVO<List<Map<String, Object>>> selectEvaluationLevel();
 
-    void exportProjectReport(SimulationManualProjectParam param);
+  void exportProjectReport(SimulationManualProjectParam param);
 
-    String selectProjectReportIdByAlgorithmId(String algorithmId);
+  String selectProjectReportIdByAlgorithmId(String algorithmId);
 
-    ResponseBodyVO<String> saveEvaluationLevel(String id);
+  ResponseBodyVO<String> saveEvaluationLevel(String id);
 
-    ResponseBodyVO saveTaskResult(SimulationManualProjectParam param);
+  ResponseBodyVO saveTaskResult(SimulationManualProjectParam param);
 
-    void exportProjectTaskFileById(SimulationManualProjectParam param);
+  void exportProjectTaskFileById(SimulationManualProjectParam param);
 
-    void exportProjectReportAndTaskFileById(SimulationManualProjectParam param);
+  void exportProjectReportAndTaskFileById(SimulationManualProjectParam param);
 
-    ResponseBodyVO addOrUpdateAutomaticProject(SimulationManualProjectParam param);
+  ResponseBodyVO addOrUpdateAutomaticProject(SimulationManualProjectParam param);
 
-    ResponseBodyVO<String> deleteAutomaticProjectByids(SimulationManualProjectParam param);
+  ResponseBodyVO<String> deleteAutomaticProjectByids(SimulationManualProjectParam param);
 
-    ResponseBodyVO<String> updateAutomaticRunState(SimulationManualProjectParam param);
+  ResponseBodyVO<String> updateAutomaticRunState(SimulationManualProjectParam param);
 
-    ResponseBodyVO<PageInfo<SimulationManualProjectVo>> selectAutomaticProject(SimulationManualProjectParam param);
+  ResponseBodyVO<PageInfo<SimulationManualProjectVo>> selectAutomaticProject(SimulationManualProjectParam param);
 
-    ResponseBodyVO<String> createAutomaticSubProject(SimulationManualProjectParam param);
+  ResponseBodyVO<String> createAutomaticSubProject(SimulationManualProjectParam param);
 
-    ResponseBodyVO<String> deleteAutomaticSubProjectByIds(SimulationManualProjectParam param);
+  ResponseBodyVO<String> deleteAutomaticSubProjectByIds(SimulationManualProjectParam param);
 
-    ResponseBodyVO<AutomaticProjectVo> selectSubProjectInfo(SimulationManualProjectParam param);
+  ResponseBodyVO<AutomaticProjectVo> selectSubProjectInfo(SimulationManualProjectParam param);
 
-    ResponseBodyVO<PageInfo<SimulationManualProjectVo>> selectSubProjectList(SimulationManualProjectParam param);
+  ResponseBodyVO<PageInfo<SimulationManualProjectVo>> selectSubProjectList(SimulationManualProjectParam param);
 
-    ResponseBodyVO<SimulationManualProjectSingleVo> selectAutomaticProjectById(SimulationManualProjectParam param);
+  ResponseBodyVO<SimulationManualProjectSingleVo> selectAutomaticProjectById(SimulationManualProjectParam param);
 
-    ResponseBodyVO<String> updateAutoProjectNowRunState(SimulationManualProjectParam param);
+  ResponseBodyVO<String> updateAutoProjectNowRunState(SimulationManualProjectParam param);
 }

+ 4987 - 5097
simulation-resource-server/src/main/java/com/css/simulation/resource/project/service/impl/SimulationProjectServiceImpl.java

@@ -73,5431 +73,5321 @@ import java.util.zip.ZipOutputStream;
 @Slf4j
 public class SimulationProjectServiceImpl implements SimulationProjectService {
 
-    @Resource
-    private SimulationProjectMapper simulationProjectMapper;
-    @Resource
-    private ManualProjectMapper manualProjectMapper;
-    @Resource
-    private AutoSubProjectMapper autoSubProjectMapper;
-    @Resource
-    private SimulationAutomaticProjectMapper simulationAutomaticProjectMapper;
-    @Resource
-    private SimulationProjectTaskMapper simulationProjectTaskMapper;
-    @Resource
-    private SimulationAutomaticSubProjectMapper simulationAutomaticSubProjectMapper;
-    @Resource
-    private SimulationMptFirstTargetScoreMapper simulationMptFirstTargetScoreMapper;
-    @Resource
-    private SimulationMptLastTargetScoreMapper simulationMptLastTargetScoreMapper;
-    @Resource
-    private AlgorithmMapper algorithmMapper;
-    @Resource
-    private KafkaTemplate<String, String> kafkaTemplate;
-    @Resource
-    private DictService dictService;
-    @Resource
-    private AlgoPlatformService algoPlatformService;
-    @Resource
-    private FileDownService fileDownService;
-    @Resource
-    private AlgorithmService algorithmService;
-    @Resource
-    private MonitorService monitorService;
-    @Resource
-    private ProjectUtil projectUtil;
-    @Resource
-    private VehicleMapper vehicleMapper;
-
-    // * -------------------------------- Comment --------------------------------
-
-    private final String[] dateFmtArr = new String[] { "yyyyMMdd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd" };
-
-    @Override
-    public ResponseBodyVO<String> addOrUpdateProject(SimulationManualProjectParam param) {
-
-        if (isEmpty(param.getProjectName())) {
-            return new ResponseBodyVO<>(ResponseBodyVO.Response.CLIENT_FAILURE, "工作名称不能为空。");
-        }
-        SimulationManualProjectPo po = convertParamToPo(param);
-
-        if (isEmpty(param.getId())) {
-            // 工作名称一样的的不能创建
-            List<SimulationManualProjectPo> simulationManualProjectPos = simulationProjectMapper
-                    .selectProjectByName(param);
-            if (!isEmpty(simulationManualProjectPos)) {
-                return new ResponseBodyVO<>(ResponseBodyVO.Response.CLIENT_FAILURE, "工作名称已经存在,请修改后再保存。");
-            }
-            po.createPo(AuthUtil.getCurrentUserId());
-            // 生成id
-            createProjectId(po);
-            int add = simulationProjectMapper.add(po);
-            if (add > 0) {
-                return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS,
-                        ResponseBodyVO.Response.SUCCESS.getMessage(), po.getId());
-            }
-            return new ResponseBodyVO<>(ResponseBodyVO.Response.SERVER_FAILURE, "添加失败");
-        } else {
-            // 取工作状态,仅未开始的才可以修改信息
-            SimulationManualProjectPo simulationManualProjectPo = simulationProjectMapper.selectProjectById(param);
-            if (!ProjectRunStateEnum.NOT_START.getCode().equals(simulationManualProjectPo.getNowRunState())) {
-                return new ResponseBodyVO<>(ResponseBodyVO.Response.SERVER_FAILURE, "当前状态不支持修改。");
-            }
-            po.updatePo(AuthUtil.getCurrentUserId());
-            int update = simulationProjectMapper.update(po);
-            if (update > 0) {
-                return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS,
-                        ResponseBodyVO.Response.SUCCESS.getMessage(), po.getId());
-            }
-            return new ResponseBodyVO<>(ResponseBodyVO.Response.SERVER_FAILURE, "修改失败。");
-        }
-
+  @Resource
+  private SimulationProjectMapper simulationProjectMapper;
+  @Resource
+  private ManualProjectMapper manualProjectMapper;
+  @Resource
+  private AutoSubProjectMapper autoSubProjectMapper;
+  @Resource
+  private SimulationAutomaticProjectMapper simulationAutomaticProjectMapper;
+  @Resource
+  private SimulationProjectTaskMapper simulationProjectTaskMapper;
+  @Resource
+  private SimulationAutomaticSubProjectMapper simulationAutomaticSubProjectMapper;
+  @Resource
+  private SimulationMptFirstTargetScoreMapper simulationMptFirstTargetScoreMapper;
+  @Resource
+  private SimulationMptLastTargetScoreMapper simulationMptLastTargetScoreMapper;
+  @Resource
+  private AlgorithmMapper algorithmMapper;
+  @Resource
+  private KafkaTemplate<String, String> kafkaTemplate;
+  @Resource
+  private DictService dictService;
+  @Resource
+  private AlgoPlatformService algoPlatformService;
+  @Resource
+  private FileDownService fileDownService;
+  @Resource
+  private AlgorithmService algorithmService;
+  @Resource
+  private MonitorService monitorService;
+  @Resource
+  private ProjectUtil projectUtil;
+  @Resource
+  private VehicleMapper vehicleMapper;
+
+  // * -------------------------------- Comment --------------------------------
+
+  private final String[] dateFmtArr = new String[]{"yyyyMMdd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd"};
+
+  @Override
+  public ResponseBodyVO<String> addOrUpdateProject(SimulationManualProjectParam param) {
+
+    if (isEmpty(param.getProjectName())) {
+      return new ResponseBodyVO<>(ResponseBodyVO.Response.CLIENT_FAILURE, "工作名称不能为空。");
     }
-
-    @Override
-    public ResponseBodyVO<PageInfo<SimulationManualProjectVo>> selectProject(SimulationManualProjectParam param) {
-
-        // 设置当前用户id
-        param.setCreateUserId(AuthUtil.getCurrentUserId());
-        if (!isEmpty(param.getCreateStartDate())) {
-            String createStartDate = param.getCreateStartDate();
-            Date startDate = getDate(createStartDate + " 00:00:00", 1);
-            if (startDate == null) {
-                return new ResponseBodyVO<>(ResponseBodyVO.Response.CLIENT_FAILURE);
-            }
-            param.setCreateTimeStart(startDate);
-        }
-        if (!isEmpty(param.getCreateEndDate())) {
-            String createEndDate = param.getCreateEndDate();
-            Date endDate = getDate(createEndDate + " 23:59:59", 1);
-            if (endDate == null) {
-                return new ResponseBodyVO<>(ResponseBodyVO.Response.CLIENT_FAILURE);
-            }
-            param.setCreateTimeEnd(endDate);
-        }
-
-        if (!isEmpty(param.getFinishDateStart())) {
-            String finishDateStart = param.getFinishDateStart();
-            Date startDate = getDate(finishDateStart + " 00:00:00", 1);
-            if (startDate == null) {
-                return new ResponseBodyVO<>(ResponseBodyVO.Response.CLIENT_FAILURE);
-            }
-            param.setFinishTimeStart(startDate);
-
-        }
-        if (!isEmpty(param.getFinishDateEnd())) {
-            String finishDateEnd = param.getFinishDateEnd();
-            Date endDate = getDate(finishDateEnd + " 23:59:59", 1);
-            if (endDate == null) {
-                return new ResponseBodyVO<>(ResponseBodyVO.Response.CLIENT_FAILURE);
-            }
-            param.setFinishTimeEnd(endDate);
-        }
-
-        // 查询有效数据
-        param.setIsDeleted("0");
-        setPage(param.getCurrentPage() == null ? 1 : param.getCurrentPage(),
-                param.getPageSize() == null ? 10 : param.getPageSize());
-        List<SimulationManualProjectVo> vos = simulationProjectMapper.selectProjectList(param); // 查出来的 algorithm
-                                                                                                // 字段内容是算法 id
-        PageInfo<SimulationManualProjectVo> pageInfo = new PageInfo<>(vos);
-
-        for (SimulationManualProjectVo simulationManualProjectVo : pageInfo.getList()) {
-            convertPoToVo(simulationManualProjectVo, false); // 同时将算法 id 转换成算法名称
-        }
-
-        return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS, pageInfo);
+    SimulationManualProjectPo po = convertParamToPo(param);
+
+    if (isEmpty(param.getId())) {
+      // 工作名称一样的的不能创建
+      List<SimulationManualProjectPo> simulationManualProjectPos = simulationProjectMapper.selectProjectByName(param);
+      if (!isEmpty(simulationManualProjectPos)) {
+        return new ResponseBodyVO<>(ResponseBodyVO.Response.CLIENT_FAILURE, "工作名称已经存在,请修改后再保存。");
+      }
+      po.createPo(AuthUtil.getCurrentUserId());
+      // 生成id
+      createProjectId(po);
+      int add = simulationProjectMapper.add(po);
+      if (add > 0) {
+        return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS, ResponseBodyVO.Response.SUCCESS.getMessage(), po.getId());
+      }
+      return new ResponseBodyVO<>(ResponseBodyVO.Response.SERVER_FAILURE, "添加失败");
+    } else {
+      // 取工作状态,仅未开始的才可以修改信息
+      SimulationManualProjectPo simulationManualProjectPo = simulationProjectMapper.selectProjectById(param);
+      if (!ProjectRunStateEnum.NOT_START.getCode().equals(simulationManualProjectPo.getNowRunState())) {
+        return new ResponseBodyVO<>(ResponseBodyVO.Response.SERVER_FAILURE, "当前状态不支持修改。");
+      }
+      po.updatePo(AuthUtil.getCurrentUserId());
+      int update = simulationProjectMapper.update(po);
+      if (update > 0) {
+        return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS, ResponseBodyVO.Response.SUCCESS.getMessage(), po.getId());
+      }
+      return new ResponseBodyVO<>(ResponseBodyVO.Response.SERVER_FAILURE, "修改失败。");
     }
 
-    @Override
-    public ResponseBodyVO<SimulationManualProjectSingleVo> selectProjectById(SimulationManualProjectParam param) {
-        if (isEmpty(param.getId())) {
-            return new ResponseBodyVO<>(ResponseBodyVO.Response.CLIENT_FAILURE);
-        }
-        SimulationManualProjectPo po = simulationProjectMapper.selectProjectById(param);
-        if (po == null) {
-            return new ResponseBodyVO<>(ResponseBodyVO.Response.SERVER_FAILURE, "没有获取到数据。");
-        }
+  }
 
-        SimulationManualProjectSingleVo vo = new SimulationManualProjectSingleVo();
-        convertPoToVo(po, vo);
-        if (ObjectUtil.isNotNull(po.getAlgorithmArray())) {
-            vo.setAlgorithmArrayS(po.getAlgorithmArray().split(","));
-        }
-        if (ObjectUtil.isNotNull(po.getVehicleArray())) {
-            vo.setVehicleArrayS(po.getVehicleArray().split(","));
-        }
-        if (ObjectUtil.isNotNull(po.getSceneArray())) {
-            vo.setSceneArrayS(po.getSceneArray().split(","));
-        }
-        return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS, vo);
+  @Override
+  public ResponseBodyVO<PageInfo<SimulationManualProjectVo>> selectProject(SimulationManualProjectParam param) {
 
+    // 设置当前用户id
+    param.setCreateUserId(AuthUtil.getCurrentUserId());
+    if (!isEmpty(param.getCreateStartDate())) {
+      String createStartDate = param.getCreateStartDate();
+      Date startDate = getDate(createStartDate + " 00:00:00", 1);
+      if (startDate == null) {
+        return new ResponseBodyVO<>(ResponseBodyVO.Response.CLIENT_FAILURE);
+      }
+      param.setCreateTimeStart(startDate);
+    }
+    if (!isEmpty(param.getCreateEndDate())) {
+      String createEndDate = param.getCreateEndDate();
+      Date endDate = getDate(createEndDate + " 23:59:59", 1);
+      if (endDate == null) {
+        return new ResponseBodyVO<>(ResponseBodyVO.Response.CLIENT_FAILURE);
+      }
+      param.setCreateTimeEnd(endDate);
     }
 
-    @Override
-    public ResponseBodyVO<String> deleteProjectByids(SimulationManualProjectParam param) {
-
-        String ids = param.getIds();
-        if (isEmpty(ids)) {
-            return new ResponseBodyVO<>(ResponseBodyVO.Response.CLIENT_FAILURE);
-        }
-
-        String[] idArr = ids.split(",");
-
-        // 仅有执行中的不能删除
-        List<SimulationManualProjectPo> pos = simulationProjectMapper.selectProjectNowRunState(idArr);
-        for (SimulationManualProjectPo p : pos) {
-            if (ProjectRunStateEnum.EXECUTION.getCode().equals(p.getNowRunState())) {
-                return new ResponseBodyVO<>(ResponseBodyVO.Response.SERVER_FAILURE, "数据不支持删除。");
-            }
-        }
+    if (!isEmpty(param.getFinishDateStart())) {
+      String finishDateStart = param.getFinishDateStart();
+      Date startDate = getDate(finishDateStart + " 00:00:00", 1);
+      if (startDate == null) {
+        return new ResponseBodyVO<>(ResponseBodyVO.Response.CLIENT_FAILURE);
+      }
+      param.setFinishTimeStart(startDate);
 
-        int i = simulationProjectMapper.deleteProject(idArr);
-        if (i > 0) {
-            return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS);
-        }
-        return new ResponseBodyVO<>(ResponseBodyVO.Response.SERVER_FAILURE, "删除失败。");
     }
-
-    /**
-     * 修改手动运行项目状态
-     */
-    @SneakyThrows
-    @Override
-    public ResponseBodyVO<String> updateProjectNowRunState(SimulationManualProjectParam param) {
-
-        // 1 查询项目详细信息
-        SimulationManualProjectPo po = projectUtil.getProjectInfo(param);
-        // 2 项目终止信息直接推送
-        if (DictConstants.PROJECT_TERMINATED.equals(param.getNowRunState())) {
-            projectStopToKafka(po);
-            simulationProjectMapper.updateProjectNowRunState(param);
-        } else {
-            // 3 校验项目的信息是否可用
-            projectUtil.checkProject(po.getAlgorithm(), po.getVehicle(), po.getScene());
-            // 已经完成的项目再次运行
-            if (DictConstants.PROJECT_COMPLETED.equals(po.getNowRunState())) {
-                po.createPo(AuthUtil.getCurrentUserId());
-                // 生成id
-                createProjectId(po);
-                // 初始化数据
-                po.setNowRunState(param.getNowRunState());
-                po.setEvaluationLevel("");
-                po.setStartTime(new Date());
-                po.setFinishTime(null);
-                int add = simulationProjectMapper.add(po);
-                if (add <= 0) {
-                    return new ResponseBodyVO<>(ResponseBodyVO.Response.SERVER_FAILURE, "生成新工作失败。");
-                }
-                // 查询项目详情信息并保存,固定项目最原始的运行数据
-                String projectId = po.getId();
-                ProjectDetailsVo info = selectProjectDetailsByIdBackUp(SimulationManualProjectParam.builder()
-                        .id(projectId).projectType(DictConstants.PROJECT_TYPE_MANUAL).build()).getInfo();
-                String infoJson = JsonUtil.beanToJson(info);
-                // 保存項目詳情信息
-                simulationProjectMapper.updateDetailsById(projectId, infoJson);
-                // Kafka推送消息
-                projectRunToKafka(po);
-            } else { // 创建新的项目或者重新运行被终止的项目
-                // 查询项目详情信息并保存
-                String projectId = param.getId();
-                ProjectDetailsVo info = selectProjectDetailsByIdBackUp(SimulationManualProjectParam.builder()
-                        .id(projectId).projectType(DictConstants.PROJECT_TYPE_MANUAL).build()).getInfo();
-                String infoJson = JsonUtil.beanToJson(info);
-                log.info("项目 " + projectId + " 的详情信息为:" + infoJson);
-                // 保存項目詳情信息
-                simulationProjectMapper.updateDetailsById(projectId, infoJson);
-                if ("20".equals(param.getNowRunState())) {
-                    // 设置开始时间
-                    param.setStartTime(new Date());
-                    // Kafka推送消息
-                    projectRunToKafka(po);
-                } else if ("30".equals(param.getNowRunState())) {
-                    // 设置完成时间
-                    param.setFinishTime(new Date());
-                }
-                simulationProjectMapper.updateProjectNowRunState(param);
-            }
-        }
-        return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS);
+    if (!isEmpty(param.getFinishDateEnd())) {
+      String finishDateEnd = param.getFinishDateEnd();
+      Date endDate = getDate(finishDateEnd + " 23:59:59", 1);
+      if (endDate == null) {
+        return new ResponseBodyVO<>(ResponseBodyVO.Response.CLIENT_FAILURE);
+      }
+      param.setFinishTimeEnd(endDate);
     }
 
-    private void projectRunToKafka(SimulationManualProjectPo po) {
-        try {
-            log.info("准备发送项目消息:" + po);
-            SimulationManualProjectKafkaParam kafkaParam = new SimulationManualProjectKafkaParam();
-            kafkaParam.setProjectId(po.getId());
-            kafkaParam.setAlgorithmId(po.getAlgorithm());
-            kafkaParam.setVehicleConfigId(po.getVehicle());
-            kafkaParam.setScenePackageId(po.getScene());
-            kafkaParam.setMaxSimulationTime(po.getMaxSimulationTime());
-            kafkaParam.setParallelism(Integer.valueOf(po.getParallelism()));
-            kafkaParam.setType(DictConstants.PROJECT_TYPE_MANUAL);
-            kafkaParam.setModelType(vehicleMapper.selectParameterTypeById(po.getVehicle()));
-            KafkaParameter kafkaParameter = new KafkaParameter();
-            kafkaParameter.setTopic(ProjectConstants.RUN_TASK_TOPIC);
-            String data = JsonUtil.beanToJson(kafkaParam);
-            kafkaParameter.setData(data);
-            log.info("推送项目运行消息到kafka:" + data);
-            kafkaTemplate.send(kafkaParameter.getTopic(), kafkaParameter.getData()).addCallback(success -> {
-                // 消息发送到的topic
-                String topic = success.getRecordMetadata().topic();
-                // 消息发送到的分区
-                int partition = success.getRecordMetadata().partition();
-                // 消息在分区内的offset
-                long offset = success.getRecordMetadata().offset();
-                log.info("发送消息成功,主题 topic 为:" + topic + ",分区 partition 为:" + partition + ",偏移量为:" + offset + ",消息体为:"
-                        + kafkaParameter.getData());
-            }, failure -> log.error("发送消息失败:" + failure.getMessage()));
-        } catch (NumberFormatException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    private void projectStopToKafka(SimulationManualProjectPo po) {
-        SimulationManualProjectKafkaParam kafkaParam = new SimulationManualProjectKafkaParam();
-        kafkaParam.setProjectId(po.getId());
-        kafkaParam.setType(DictConstants.PROJECT_TYPE_MANUAL);
-        KafkaParameter kafkaParameter = new KafkaParameter();
-        kafkaParameter.setTopic(ProjectConstants.STOP_TASK_TOPIC);
-        String data = JsonUtil.beanToJson(kafkaParam);
-        kafkaParameter.setData(data);
-        log.info("推送项目中止消息到kafka:" + data);
-        kafkaTemplate.send(kafkaParameter.getTopic(), kafkaParameter.getData()).addCallback(success -> {
-            // 消息发送到的topic
-            String topic = success.getRecordMetadata().topic();
-            // 消息发送到的分区
-            int partition = success.getRecordMetadata().partition();
-            // 消息在分区内的offset
-            long offset = success.getRecordMetadata().offset();
-            log.info("------- 发送消息成功:主题 topic 为:" + topic + "分区 partition 为:" + partition + "偏移量为:"
-                    + offset + "消息体为:" + kafkaParameter.getData());
-        }, failure -> log.error("发送消息失败:" + failure.getMessage()));
-    }
-
-    private void autoProjectStopToKafka(SimulationAutomaticSubProjectPo po) {
-        SimulationManualProjectKafkaParam kafkaParam = new SimulationManualProjectKafkaParam();
-        kafkaParam.setProjectId(po.getId());
-        kafkaParam.setType(DictConstants.PROJECT_TYPE_AUTO_SUB);
-        KafkaParameter kafkaParameter = new KafkaParameter();
-        kafkaParameter.setTopic(ProjectConstants.STOP_TASK_TOPIC);
-        String data = JsonUtil.beanToJson(kafkaParam);
-        kafkaParameter.setData(data);
-        log.info("推送自动项目中止消息到kafka:" + data);
-        // kafkaService.send(kafkaParameter);
-        kafkaTemplate.send(kafkaParameter.getTopic(), kafkaParameter.getData()).addCallback(success -> {
-            // 消息发送到的topic
-            String topic = success.getRecordMetadata().topic();
-            // 消息发送到的分区
-            int partition = success.getRecordMetadata().partition();
-            // 消息在分区内的offset
-            long offset = success.getRecordMetadata().offset();
-            log.info("------- 发送消息成功:\n"
-                    + "主题 topic 为:" + topic + "\n"
-                    + "分区 partition 为:" + partition + "\n"
-                    + "偏移量为:" + offset + "\n"
-                    + "消息体为:" + kafkaParameter.getData());
-        }, failure -> log.error("发送消息失败:" + failure.getMessage()));
-    }
-
-    @Override
-    @SneakyThrows
-    public ResponseBodyVO<ProjectDetailsVo> selectProjectDetailsById(SimulationManualProjectParam param) {
-
-        ProjectDetailsVo projectDetailsVo = null;
-        if (DictConstants.PROJECT_TYPE_MANUAL.equals(param.getProjectType())) { // 手动运行任务
-            SimulationManualProjectPo po = simulationProjectMapper.selectProjectById(param);
-            projectDetailsVo = JsonUtil.jsonToBean(po.getDetails(), ProjectDetailsVo.class);
-            projectDetailsVo.setEvaluationLevel(getDictName(DictConstants.EVALUATION_LEVEL, po.getEvaluationLevel()));
-            projectDetailsVo.setStartTime(getRqStr(po.getStartTime(), 1));
-            projectDetailsVo.setFinishTime(getRqStr(po.getFinishTime(), 1));
-            projectDetailsVo.setNowRunState(po.getNowRunState());
-            projectDetailsVo.setNowRunStateName(getDictName(DictConstants.PROJECT_RUN_STATE, po.getNowRunState()));
-        } else if (DictConstants.PROJECT_TYPE_AUTO_SUB.equals(param.getProjectType())) {
-            SimulationManualProjectVo po = simulationAutomaticSubProjectMapper.selectProjectInfo(param);
-            projectDetailsVo = JsonUtil.jsonToBean(po.getDetails(), ProjectDetailsVo.class);
-            projectDetailsVo.setEvaluationLevel(getDictName(DictConstants.EVALUATION_LEVEL, po.getEvaluationLevel()));
-            projectDetailsVo.setStartTime(getRqStr(po.getStartTime(), 1));
-            projectDetailsVo.setFinishTime(getRqStr(po.getFinishTime(), 1));
-            projectDetailsVo.setNowRunState(po.getNowRunState());
-            projectDetailsVo.setNowRunStateName(getDictName(DictConstants.PROJECT_RUN_STATE, po.getNowRunState()));
-
-        }
-        // 获取测试得分列表
-        List<AlgorithmScoreVo> firstTargetScore = getFirstTargetScore(param.getId());
-        projectDetailsVo.setAlgorithmScoreList(firstTargetScore);
-        // 任务运行状态统计
-        List<ProjectRunStateNumVo> states = null;
-
-        // 任务运行结果统计
-        List<ProjectRunResultRatioNumVo> resultScoreList = null;
-
-        // 任务信息
-        ProjectTaskParam projectTaskParam = new ProjectTaskParam();
-        projectTaskParam.setPId(param.getId());
-        List<ProjectRunResultRatioNumVo> projectRunResultRatioNumVos = null;
-        Integer size = simulationProjectTaskMapper.selectProjectTaskNumByProjectId(projectTaskParam);
-        if (size > 0) {
-            states = simulationProjectTaskMapper.selectRunStateCount(param.getId());
-            taskRunState(states, size);
-            projectRunResultRatioNumVos = simulationProjectTaskMapper.selectRunResultCount(param.getId());
-            taskResultState(projectRunResultRatioNumVos, size);
-
-            resultScoreList = simulationProjectTaskMapper.selectScoreCount(param.getId());
-
-            // 未完成得分为”“的改为0
-            if (!isEmpty(resultScoreList) && resultScoreList.size() == 1
-                    && isEmpty(resultScoreList.get(0).getResultName())) {
-                ProjectRunResultRatioNumVo projectRunResultRatioNumVo = resultScoreList.get(0);
-                projectRunResultRatioNumVo.setResultName("0");
-            }
-            taskScore(resultScoreList, size);
-        }
-        projectDetailsVo.setResultList(projectRunResultRatioNumVos);
-        projectDetailsVo.setResultScoreList(resultScoreList);
-        // 汉化
-        if (CollectionUtil.isNotEmpty(states)) {
-            states.forEach(state -> {
-                if (StateConstant.Aborted.getEnglish().equals(state.getStateName())) {
-                    state.setStateName(StateConstant.Aborted.getChinese());
-                }
-                if (StateConstant.PendingAnalysis.getEnglish().equals(state.getStateName())) {
-                    state.setStateName(StateConstant.PendingAnalysis.getChinese());
-                }
-                if (StateConstant.Running.getEnglish().equals(state.getStateName())) {
-                    state.setStateName(StateConstant.Running.getChinese());
-                }
-                if (StateConstant.Analysing.getEnglish().equals(state.getStateName())) {
-                    state.setStateName(StateConstant.Analysing.getChinese());
-                }
-                if (StateConstant.Completed.getEnglish().equals(state.getStateName())) {
-                    state.setStateName(StateConstant.Completed.getChinese());
-                }
-                if (StateConstant.Terminated.getEnglish().equals(state.getStateName())) {
-                    state.setStateName(StateConstant.Terminated.getChinese());
-                }
-                if (StateConstant.Terminating.getEnglish().equals(state.getStateName())) {
-                    state.setStateName(StateConstant.Terminating.getChinese());
-                }
-                if (StateConstant.Pending.getEnglish().equals(state.getStateName())) {
-                    state.setStateName(StateConstant.Pending.getChinese());
-                }
-            });
-        }
-        projectDetailsVo.setStateList(states);
-
-        return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS, projectDetailsVo);
-    }
-
-    private ResponseBodyVO<ProjectDetailsVo> selectProjectDetailsByIdBackUp(SimulationManualProjectParam param) {
-
-        if (isEmpty(param.getId())) {
-            return new ResponseBodyVO<>(ResponseBodyVO.Response.CLIENT_FAILURE);
-        }
-
-        if (isEmpty(param.getProjectType())) {
-            param.setProjectType("1");// 默认
-        }
-
-        ProjectDetailsVo projectDetailsVo = new ProjectDetailsVo();
-
-        // 封装要使用到的数据
-        SimulationManualProjectPo poParam = new SimulationManualProjectPo();
-
-        if ("1".equals(param.getProjectType())) { // 手动运行任务
-            // 项目基本信息
-            SimulationManualProjectPo po = simulationProjectMapper.selectProjectById(param);
-            if (po == null) {
-                return new ResponseBodyVO<>(ResponseBodyVO.Response.SERVER_FAILURE, "没有获取到数据");
-            }
-            poParam = po;
-        } else if ("2".equals(param.getProjectType())) {
-            SimulationManualProjectVo po = simulationAutomaticSubProjectMapper.selectProjectInfo(param);
-            if (po == null) {
-                return new ResponseBodyVO<>(ResponseBodyVO.Response.SERVER_FAILURE, "没有获取到数据");
-            }
-            BeanUtils.copyProperties(po, poParam);
-
-        }
-
-        // 获取场景包信息
-        ScenePackagePO scenePackagePO = simulationProjectMapper.selectScenePackageInfoById(poParam.getScene());
-
-        projectDetailsVo.setPackageName(scenePackagePO.getPackageName());
-
-        // 算法配置
-        AlgorithmPO algorithmBaseInfoVo = getAlgorithmInfo(poParam);
-        // 获取测试得分列表
-        List<AlgorithmScoreVo> firstTargetScore = getFirstTargetScore(param.getId());
-        projectDetailsVo.setAlgorithmScoreList(firstTargetScore);
-
-        // 车辆配置
-        VehiclePO vehicleBaseInfoVo = null;
-        String vehicleConfigId = poParam.getVehicle();
-
-        ConfigPO configPO = new ConfigPO();
-        configPO.setId(vehicleConfigId);
-        List<ConfigPO> configVehicleVOS = simulationProjectMapper.selectConfigVehicle(configPO);
-        if (!isEmpty(configVehicleVOS)) {
-            ConfigPO configVehicleVO = configVehicleVOS.get(0);
-            List<VehiclePO> vehiclePOS = simulationProjectMapper
-                    .selectVehicleBaseInfoById(configVehicleVO.getVehicleId());
-            if (!isEmpty(vehiclePOS)) {
-                vehicleBaseInfoVo = vehiclePOS.get(0);
-            }
-
-        }
-        /*
-         * String vehicleImage = vehicleBaseInfoVo.getVehicleImage();
-         * if(!isEmpty(vehicleImage)){
-         * vehicleBaseInfoVo.setVehicleImage(vehicleImage.replaceFirst("Front side"
-         * ,"Top"));
-         * }
-         */
-
-        List<ConfigSensorPO> vehicleSensorVos = simulationProjectMapper.selectVehicleSensor(vehicleConfigId);
-
-        List<SensorBaseInfoVo> sensorCameraList = new ArrayList<>();
-        List<SensorBaseInfoVo> sensorOgtList = new ArrayList<>();
-        List<SensorBaseInfoVo> sensorLidarList = new ArrayList<>();
-        List<SensorBaseInfoVo> sensorRadarList = new ArrayList<>();
-        List<SensorBaseInfoVo> sensorGpsList = new ArrayList<>();
-        for (ConfigSensorPO vs : vehicleSensorVos) {
-            String sensorType = vs.getSensorType();
-            String sensorId = vs.getSensorId();
-            if (DictConstants.SENSOR_CAMERA.equals(sensorType)) {
-                // 摄像头
-                SensorBaseInfoVo sensorBaseInfoVo = simulationProjectMapper.selectSensorCamera(sensorId);
-                if(ObjectUtil.isNotNull(sensorBaseInfoVo)&&sensorBaseInfoVo.getShare().equals("0")){
-                    sensorBaseInfoVo.setSensorName("私有/"+sensorBaseInfoVo.getSensorName());
-                }else if(ObjectUtil.isNotNull(sensorBaseInfoVo)&&sensorBaseInfoVo.getShare().equals("1")){
-                    sensorBaseInfoVo.setSensorName("公有/"+sensorBaseInfoVo.getSensorName());
-                }
-                setVehicleConfig(sensorBaseInfoVo, vs);
-                sensorCameraList.add(sensorBaseInfoVo);
-            } else if (DictConstants.SENSOR_OGT.equals(sensorType)) {
-                // 完美传感器
-                SensorBaseInfoVo sensorBaseInfoVo = simulationProjectMapper.selectSensorOgt(sensorId);
-                if(ObjectUtil.isNotNull(sensorBaseInfoVo)&&sensorBaseInfoVo.getShare().equals("0")){
-                    sensorBaseInfoVo.setSensorName("私有/"+sensorBaseInfoVo.getSensorName());
-                }else if(ObjectUtil.isNotNull(sensorBaseInfoVo)&&sensorBaseInfoVo.getShare().equals("1")){
-                    sensorBaseInfoVo.setSensorName("公有/"+sensorBaseInfoVo.getSensorName());
-                }
-                setVehicleConfig(sensorBaseInfoVo, vs);
-                sensorOgtList.add(sensorBaseInfoVo);
-            } else if (DictConstants.SENSOR_LIDAR.equals(sensorType)) {
-                // 激光雷达
-                SensorBaseInfoVo sensorBaseInfoVo = simulationProjectMapper.selectSensorLidar(sensorId);
-                if(ObjectUtil.isNotNull(sensorBaseInfoVo)&&sensorBaseInfoVo.getShare().equals("0")){
-                    sensorBaseInfoVo.setSensorName("私有/"+sensorBaseInfoVo.getSensorName());
-                }else if(ObjectUtil.isNotNull(sensorBaseInfoVo)&&sensorBaseInfoVo.getShare().equals("1")){
-                    sensorBaseInfoVo.setSensorName("公有/"+sensorBaseInfoVo.getSensorName());
-                }
-                setVehicleConfig(sensorBaseInfoVo, vs);
-                sensorLidarList.add(sensorBaseInfoVo);
-            } else if (DictConstants.SENSOR_RADAR.equals(sensorType)) {
-                // 毫米波雷达
-                SensorBaseInfoVo sensorBaseInfoVo = simulationProjectMapper.selectSensorRadar(sensorId);
-                if(ObjectUtil.isNotNull(sensorBaseInfoVo)&&sensorBaseInfoVo.getShare().equals("0")){
-                    sensorBaseInfoVo.setSensorName("私有/"+sensorBaseInfoVo.getSensorName());
-                }else if(ObjectUtil.isNotNull(sensorBaseInfoVo)&&sensorBaseInfoVo.getShare().equals("1")){
-                    sensorBaseInfoVo.setSensorName("公有/"+sensorBaseInfoVo.getSensorName());
-                }
-                setVehicleConfig(sensorBaseInfoVo, vs);
-                sensorRadarList.add(sensorBaseInfoVo);
-            } else if (DictConstants.SENSOR_GPS.equals(sensorType)) {
-                // gps
-                SensorBaseInfoVo sensorBaseInfoVo = simulationProjectMapper.selectSensorGps(sensorId);
-                setVehicleConfig(sensorBaseInfoVo, vs);
-                sensorGpsList.add(sensorBaseInfoVo);
-            }
-        }
-
-        // 任务信息
-        ProjectTaskParam projectTaskParam = new ProjectTaskParam();
-        projectTaskParam.setPId(poParam.getId());
-        List<ProjectRunResultRatioNumVo> projectRunResultRatioNumVos = null;
+    // 查询有效数据
+    param.setIsDeleted("0");
+    setPage(param.getCurrentPage() == null ? 1 : param.getCurrentPage(), param.getPageSize() == null ? 10 : param.getPageSize());
+    List<SimulationManualProjectVo> vos = simulationProjectMapper.selectProjectList(param); // 查出来的 algorithm
+    // 字段内容是算法 id
+    PageInfo<SimulationManualProjectVo> pageInfo = new PageInfo<>(vos);
 
-        // 任务运行状态统计
-        List<ProjectRunStateNumVo> projectRunStateNumVos = null;
+    for (SimulationManualProjectVo simulationManualProjectVo : pageInfo.getList()) {
+      convertPoToVo(simulationManualProjectVo, false); // 同时将算法 id 转换成算法名称
+    }
 
-        // 任务运行结果统计
-        List<ProjectRunResultRatioNumVo> resultScoreList = null;
+    return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS, pageInfo);
+  }
 
-        Integer size = simulationProjectTaskMapper.selectProjectTaskNumByProjectId(projectTaskParam);
-        if (size > 0) {
-            projectRunStateNumVos = simulationProjectTaskMapper.selectRunStateCount(poParam.getId());
-            taskRunState(projectRunStateNumVos, size);
+  @Override
+  public ResponseBodyVO<SimulationManualProjectSingleVo> selectProjectById(SimulationManualProjectParam param) {
+    if (isEmpty(param.getId())) {
+      return new ResponseBodyVO<>(ResponseBodyVO.Response.CLIENT_FAILURE);
+    }
+    SimulationManualProjectPo po = simulationProjectMapper.selectProjectById(param);
+    if (po == null) {
+      return new ResponseBodyVO<>(ResponseBodyVO.Response.SERVER_FAILURE, "没有获取到数据。");
+    }
 
-            projectRunResultRatioNumVos = simulationProjectTaskMapper.selectRunResultCount(poParam.getId());
-            taskResultState(projectRunResultRatioNumVos, size);
+    SimulationManualProjectSingleVo vo = new SimulationManualProjectSingleVo();
+    convertPoToVo(po, vo);
+    if (ObjectUtil.isNotNull(po.getAlgorithmArray())) {
+      vo.setAlgorithmArrayS(po.getAlgorithmArray().split(","));
+    }
+    if (ObjectUtil.isNotNull(po.getVehicleArray())) {
+      vo.setVehicleArrayS(po.getVehicleArray().split(","));
+    }
+    if (ObjectUtil.isNotNull(po.getSceneArray())) {
+      vo.setSceneArrayS(po.getSceneArray().split(","));
+    }
+    return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS, vo);
 
-            resultScoreList = simulationProjectTaskMapper.selectScoreCount(poParam.getId());
+  }
 
-            // 未完成得分为”“的改为0
-            if (!isEmpty(resultScoreList) && resultScoreList.size() == 1
-                    && isEmpty(resultScoreList.get(0).getResultName())) {
-                ProjectRunResultRatioNumVo projectRunResultRatioNumVo = resultScoreList.get(0);
-                projectRunResultRatioNumVo.setResultName("0");
-            }
-            taskScore(resultScoreList, size);
-
-        }
-
-        projectDetailsVo.setProjectId(poParam.getProjectId());
-        projectDetailsVo.setProjectName(poParam.getProjectName());
-        projectDetailsVo.setProjectDescribe(poParam.getProjectDescribe());
-        projectDetailsVo.setStartTime(getRqStr(poParam.getStartTime(), 1));
-        projectDetailsVo.setFinishTime(getRqStr(poParam.getFinishTime(), 1));
-        projectDetailsVo.setNowRunState(poParam.getNowRunState());
-        projectDetailsVo.setNowRunStateName(getDictName(DictConstants.PROJECT_RUN_STATE, poParam.getNowRunState()));
-        projectDetailsVo.setEvaluationLevel(getDictName(DictConstants.EVALUATION_LEVEL, poParam.getEvaluationLevel()));
-        // projectDetailsVo.setEvaluationLevel(s);
-        if (algorithmBaseInfoVo != null) {
-            projectDetailsVo.setAlgorithmName(algorithmBaseInfoVo.getAlgorithmName());
-            projectDetailsVo.setAlgorithmDescribe(algorithmBaseInfoVo.getDescription());
-        }
-        if (vehicleBaseInfoVo != null) {
-            projectDetailsVo.setVehicleName(vehicleBaseInfoVo.getVehicleName());
-            projectDetailsVo.setVehicleDescribe(vehicleBaseInfoVo.getDescription());
-            projectDetailsVo.setVehicleTopView(vehicleBaseInfoVo.getVehicleFrontView());
-
-        }
-        projectDetailsVo.setSensorCameraList(sensorCameraList);
-        projectDetailsVo.setSensorOgtList(sensorOgtList);
-        projectDetailsVo.setSensorLidarList(sensorLidarList);
-        projectDetailsVo.setSensorRadarList(sensorRadarList);
-        projectDetailsVo.setSensorGpsList(sensorGpsList);
-        projectDetailsVo.setStateList(projectRunStateNumVos);
-        projectDetailsVo.setResultList(projectRunResultRatioNumVos);
-        projectDetailsVo.setResultScoreList(resultScoreList);
-
-        projectDetailsVo.setParallelism(poParam.getParallelism());
-        projectDetailsVo.setMaxSimulationTime(poParam.getMaxSimulationTime());
-        String isChoiceGpu = poParam.getIsChoiceGpu();
-        String g = "";
-        if ("0".equals(isChoiceGpu)) {
-            g = "是";
-        } else if ("1".equals(isChoiceGpu)) {
-            g = "否";
-        }
-        projectDetailsVo.setIsChoiceGpu(g);
+  @Override
+  public ResponseBodyVO<String> deleteProjectByids(SimulationManualProjectParam param) {
 
-        /*
-         * //是否生成报告
-         * boolean isCreateReport = true;
-         * String nowRunState = projectDetailsVo.getNowRunState();
-         * if(!ProjectRunStateEnum.FINISH.getCode().equals(nowRunState)){
-         * isCreateReport = false;
-         * }else{
-         * //查询任务是否存在aborted
-         * SimulationMptSceneScorePo sPo = new SimulationMptSceneScorePo();
-         * sPo.setPId(param.getId());
-         * SceneScoreVo sceneScoreVo =
-         * simulationProjectTaskMapper.selectRunStateByAborted(sPo);
-         * if(sceneScoreVo != null && sceneScoreVo.getNum() > 0){
-         * isCreateReport = false;
-         * }
-         * }
-         * 
-         * projectDetailsVo.setCreateReport(isCreateReport);
-         */
+    String ids = param.getIds();
+    if (isEmpty(ids)) {
+      return new ResponseBodyVO<>(ResponseBodyVO.Response.CLIENT_FAILURE);
+    }
 
-        return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS, projectDetailsVo);
-    }
-
-    // 运行状态统计
-    private void taskRunState(List<ProjectRunStateNumVo> vos, Integer size) {
-        for (ProjectRunStateNumVo pv : vos) {
-            Integer num = pv.getNum();
-            Double d = (double) num / size;
-            d = saveTwoDecimalPlaces(d);
-            pv.setRatio(d);
-        }
-        // 补全没有的
-        Map<String, String> dict = getDictByType(ProjectConstants.TASK_RUN_STATE);
-        for (String key : dict.keySet()) {
-            boolean b = false;
-            for (ProjectRunStateNumVo pv : vos) {
-                if (pv.getStateName().equals(dict.get(key))) {
-                    b = true;
-                }
-            }
-            if (!b) {
-                ProjectRunStateNumVo vo = new ProjectRunStateNumVo();
-                vo.setStateName(dict.get(key));
-                vo.setNum(0);
-                vo.setRatio(0D);
-                vos.add(vo);
-            }
+    String[] idArr = ids.split(",");
 
-        }
+    // 仅有执行中的不能删除
+    List<SimulationManualProjectPo> pos = simulationProjectMapper.selectProjectNowRunState(idArr);
+    for (SimulationManualProjectPo p : pos) {
+      if (ProjectRunStateEnum.EXECUTION.getCode().equals(p.getNowRunState())) {
+        return new ResponseBodyVO<>(ResponseBodyVO.Response.SERVER_FAILURE, "数据不支持删除。");
+      }
     }
 
-    // 运行结果统计
-    private void taskResultState(List<ProjectRunResultRatioNumVo> vos, Integer size) {
-        // 结果状态统计
-        for (ProjectRunResultRatioNumVo rv : vos) {
-            Integer num = rv.getNum();
-            Double d = (double) num / size;
-            d = saveTwoDecimalPlaces(d);
-            rv.setRatio(d);
-        }
-        // 补全没有的
-        Map<String, String> dict = getDictByType(ProjectConstants.TASK_RESULT_STATE);
-        for (String key : dict.keySet()) {
-            boolean b = false;
-            for (ProjectRunResultRatioNumVo pv : vos) {
-                if (dict.get(key).equals(pv.getResultName())) {
-                    b = true;
-                }
-            }
-            if (!b) {
-                ProjectRunResultRatioNumVo vo = new ProjectRunResultRatioNumVo();
-                vo.setResultName(dict.get(key));
-                vo.setNum(0);
-                vo.setRatio(0D);
-                vos.add(vo);
-            }
-        }
+    int i = simulationProjectMapper.deleteProject(idArr);
+    if (i > 0) {
+      return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS);
     }
-
-    /**
-     * 得分统计
-     */
-    private void taskScore(List<ProjectRunResultRatioNumVo> vos, Integer size) {
-        for (ProjectRunResultRatioNumVo rv : vos) {
-            Integer num = rv.getNum();
-            Double d = (double) num / size;
-            d = saveTwoDecimalPlaces(d);
-            rv.setRatio(d);
-        }
+    return new ResponseBodyVO<>(ResponseBodyVO.Response.SERVER_FAILURE, "删除失败。");
+  }
+
+  /**
+   * 修改手动运行项目状态
+   */
+  @SneakyThrows
+  @Override
+  public ResponseBodyVO<String> updateProjectNowRunState(SimulationManualProjectParam param) {
+
+    // 1 查询项目详细信息
+    SimulationManualProjectPo po = projectUtil.getProjectInfo(param);
+    // 2 项目终止信息直接推送
+    if (DictConstants.PROJECT_TERMINATED.equals(param.getNowRunState())) {
+      projectStopToKafka(po);
+      simulationProjectMapper.updateProjectNowRunState(param);
+    } else {
+      // 3 校验项目的信息是否可用
+      projectUtil.checkProject(po.getAlgorithm(), po.getVehicle(), po.getScene());
+      // 已经完成的项目再次运行
+      if (DictConstants.PROJECT_COMPLETED.equals(po.getNowRunState())) {
+        po.createPo(AuthUtil.getCurrentUserId());
+        // 生成id
+        createProjectId(po);
+        // 初始化数据
+        po.setNowRunState(param.getNowRunState());
+        po.setEvaluationLevel("");
+        po.setStartTime(new Date());
+        po.setFinishTime(null);
+        int add = simulationProjectMapper.add(po);
+        if (add <= 0) {
+          return new ResponseBodyVO<>(ResponseBodyVO.Response.SERVER_FAILURE, "生成新工作失败。");
+        }
+        // 查询项目详情信息并保存,固定项目最原始的运行数据
+        String projectId = po.getId();
+        ProjectDetailsVo info = selectProjectDetailsByIdBackUp(SimulationManualProjectParam.builder().id(projectId).projectType(DictConstants.PROJECT_TYPE_MANUAL).build()).getInfo();
+        String infoJson = JsonUtil.beanToJson(info);
+        // 保存項目詳情信息
+        simulationProjectMapper.updateDetailsById(projectId, infoJson);
+        // Kafka推送消息
+        projectRunToKafka(po);
+      } else { // 创建新的项目或者重新运行被终止的项目
+        // 查询项目详情信息并保存
+        String projectId = param.getId();
+        ProjectDetailsVo info = selectProjectDetailsByIdBackUp(SimulationManualProjectParam.builder().id(projectId).projectType(DictConstants.PROJECT_TYPE_MANUAL).build()).getInfo();
+        String infoJson = JsonUtil.beanToJson(info);
+        log.info("项目 " + projectId + " 的详情信息为:" + infoJson);
+        // 保存項目詳情信息
+        simulationProjectMapper.updateDetailsById(projectId, infoJson);
+        if ("20".equals(param.getNowRunState())) {
+          // 设置开始时间
+          param.setStartTime(new Date());
+          // Kafka推送消息
+          projectRunToKafka(po);
+        } else if ("30".equals(param.getNowRunState())) {
+          // 设置完成时间
+          param.setFinishTime(new Date());
+        }
+        simulationProjectMapper.updateProjectNowRunState(param);
+      }
     }
+    return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS);
+  }
+
+  private void projectRunToKafka(SimulationManualProjectPo po) {
+    try {
+      log.info("准备发送项目消息:" + po);
+      SimulationManualProjectKafkaParam kafkaParam = new SimulationManualProjectKafkaParam();
+      kafkaParam.setProjectId(po.getId());
+      kafkaParam.setAlgorithmId(po.getAlgorithm());
+      kafkaParam.setVehicleConfigId(po.getVehicle());
+      kafkaParam.setScenePackageId(po.getScene());
+      kafkaParam.setMaxSimulationTime(po.getMaxSimulationTime());
+      kafkaParam.setParallelism(Integer.valueOf(po.getParallelism()));
+      kafkaParam.setType(DictConstants.PROJECT_TYPE_MANUAL);
+      kafkaParam.setModelType(vehicleMapper.selectParameterTypeById(po.getVehicle()));
+      KafkaParameter kafkaParameter = new KafkaParameter();
+      kafkaParameter.setTopic(ProjectConstants.RUN_TASK_TOPIC);
+      String data = JsonUtil.beanToJson(kafkaParam);
+      kafkaParameter.setData(data);
+      log.info("推送项目运行消息到kafka:" + data);
+      kafkaTemplate.send(kafkaParameter.getTopic(), kafkaParameter.getData()).addCallback(success -> {
+        // 消息发送到的topic
+        String topic = success.getRecordMetadata().topic();
+        // 消息发送到的分区
+        int partition = success.getRecordMetadata().partition();
+        // 消息在分区内的offset
+        long offset = success.getRecordMetadata().offset();
+        log.info("发送消息成功,主题 topic 为:" + topic + ",分区 partition 为:" + partition + ",偏移量为:" + offset + ",消息体为:" + kafkaParameter.getData());
+      }, failure -> log.error("发送消息失败:" + failure.getMessage()));
+    } catch (NumberFormatException e) {
+      throw new RuntimeException(e);
+    }
+  }
+
+  private void projectStopToKafka(SimulationManualProjectPo po) {
+    SimulationManualProjectKafkaParam kafkaParam = new SimulationManualProjectKafkaParam();
+    kafkaParam.setProjectId(po.getId());
+    kafkaParam.setType(DictConstants.PROJECT_TYPE_MANUAL);
+    KafkaParameter kafkaParameter = new KafkaParameter();
+    kafkaParameter.setTopic(ProjectConstants.STOP_TASK_TOPIC);
+    String data = JsonUtil.beanToJson(kafkaParam);
+    kafkaParameter.setData(data);
+    log.info("推送项目中止消息到kafka:" + data);
+    kafkaTemplate.send(kafkaParameter.getTopic(), kafkaParameter.getData()).addCallback(success -> {
+      // 消息发送到的topic
+      String topic = success.getRecordMetadata().topic();
+      // 消息发送到的分区
+      int partition = success.getRecordMetadata().partition();
+      // 消息在分区内的offset
+      long offset = success.getRecordMetadata().offset();
+      log.info("------- 发送消息成功:主题 topic 为:" + topic + "分区 partition 为:" + partition + "偏移量为:" + offset + "消息体为:" + kafkaParameter.getData());
+    }, failure -> log.error("发送消息失败:" + failure.getMessage()));
+  }
+
+  private void autoProjectStopToKafka(SimulationAutomaticSubProjectPo po) {
+    SimulationManualProjectKafkaParam kafkaParam = new SimulationManualProjectKafkaParam();
+    kafkaParam.setProjectId(po.getId());
+    kafkaParam.setType(DictConstants.PROJECT_TYPE_AUTO_SUB);
+    KafkaParameter kafkaParameter = new KafkaParameter();
+    kafkaParameter.setTopic(ProjectConstants.STOP_TASK_TOPIC);
+    String data = JsonUtil.beanToJson(kafkaParam);
+    kafkaParameter.setData(data);
+    log.info("推送自动项目中止消息到kafka:" + data);
+    // kafkaService.send(kafkaParameter);
+    kafkaTemplate.send(kafkaParameter.getTopic(), kafkaParameter.getData()).addCallback(success -> {
+      // 消息发送到的topic
+      String topic = success.getRecordMetadata().topic();
+      // 消息发送到的分区
+      int partition = success.getRecordMetadata().partition();
+      // 消息在分区内的offset
+      long offset = success.getRecordMetadata().offset();
+      log.info("------- 发送消息成功:\n" + "主题 topic 为:" + topic + "\n" + "分区 partition 为:" + partition + "\n" + "偏移量为:" + offset + "\n" + "消息体为:" + kafkaParameter.getData());
+    }, failure -> log.error("发送消息失败:" + failure.getMessage()));
+  }
+
+  @Override
+  @SneakyThrows
+  public ResponseBodyVO<ProjectDetailsVo> selectProjectDetailsById(SimulationManualProjectParam param) {
+
+    ProjectDetailsVo projectDetailsVo = null;
+    if (DictConstants.PROJECT_TYPE_MANUAL.equals(param.getProjectType())) { // 手动运行任务
+      SimulationManualProjectPo po = simulationProjectMapper.selectProjectById(param);
+      projectDetailsVo = JsonUtil.jsonToBean(po.getDetails(), ProjectDetailsVo.class);
+      projectDetailsVo.setEvaluationLevel(getDictName(DictConstants.EVALUATION_LEVEL, po.getEvaluationLevel()));
+      projectDetailsVo.setStartTime(getRqStr(po.getStartTime(), 1));
+      projectDetailsVo.setFinishTime(getRqStr(po.getFinishTime(), 1));
+      projectDetailsVo.setNowRunState(po.getNowRunState());
+      projectDetailsVo.setNowRunStateName(getDictName(DictConstants.PROJECT_RUN_STATE, po.getNowRunState()));
+    } else if (DictConstants.PROJECT_TYPE_AUTO_SUB.equals(param.getProjectType())) {
+      SimulationManualProjectVo po = simulationAutomaticSubProjectMapper.selectProjectInfo(param);
+      projectDetailsVo = JsonUtil.jsonToBean(po.getDetails(), ProjectDetailsVo.class);
+      projectDetailsVo.setEvaluationLevel(getDictName(DictConstants.EVALUATION_LEVEL, po.getEvaluationLevel()));
+      projectDetailsVo.setStartTime(getRqStr(po.getStartTime(), 1));
+      projectDetailsVo.setFinishTime(getRqStr(po.getFinishTime(), 1));
+      projectDetailsVo.setNowRunState(po.getNowRunState());
+      projectDetailsVo.setNowRunStateName(getDictName(DictConstants.PROJECT_RUN_STATE, po.getNowRunState()));
 
-    private void setVehicleConfig(SensorBaseInfoVo vo, ConfigSensorPO vs) {
-        vo.setConfigId(vs.getConfigId());
-        vo.setSensorId(vs.getSensorId());
-        vo.setSensorType(vs.getSensorType());
-        if (StringUtil.isNotEmpty(vs.getSensorX())) {
-            vo.setSensorX(saveTwoDecimalPlaces(vs.getSensorX().doubleValue()));
+    }
+    // 获取测试得分列表
+    List<AlgorithmScoreVo> firstTargetScore = getFirstTargetScore(param.getId());
+    projectDetailsVo.setAlgorithmScoreList(firstTargetScore);
+    // 任务运行状态统计
+    List<ProjectRunStateNumVo> states = null;
+
+    // 任务运行结果统计
+    List<ProjectRunResultRatioNumVo> resultScoreList = null;
+
+    // 任务信息
+    ProjectTaskParam projectTaskParam = new ProjectTaskParam();
+    projectTaskParam.setPId(param.getId());
+    List<ProjectRunResultRatioNumVo> projectRunResultRatioNumVos = null;
+    Integer size = simulationProjectTaskMapper.selectProjectTaskNumByProjectId(projectTaskParam);
+    if (size > 0) {
+      states = simulationProjectTaskMapper.selectRunStateCount(param.getId());
+      taskRunState(states, size);
+      projectRunResultRatioNumVos = simulationProjectTaskMapper.selectRunResultCount(param.getId());
+      taskResultState(projectRunResultRatioNumVos, size);
+
+      resultScoreList = simulationProjectTaskMapper.selectScoreCount(param.getId());
+
+      // 未完成得分为”“的改为0
+      if (!isEmpty(resultScoreList) && resultScoreList.size() == 1 && isEmpty(resultScoreList.get(0).getResultName())) {
+        ProjectRunResultRatioNumVo projectRunResultRatioNumVo = resultScoreList.get(0);
+        projectRunResultRatioNumVo.setResultName("0");
+      }
+      taskScore(resultScoreList, size);
+    }
+    projectDetailsVo.setResultList(projectRunResultRatioNumVos);
+    projectDetailsVo.setResultScoreList(resultScoreList);
+    // 汉化
+    if (CollectionUtil.isNotEmpty(states)) {
+      states.forEach(state -> {
+        if (StateConstant.Aborted.getEnglish().equals(state.getStateName())) {
+          state.setStateName(StateConstant.Aborted.getChinese());
         }
-        if (StringUtil.isNotEmpty(vs.getSensorY())) {
-            vo.setSensorY(saveTwoDecimalPlaces(vs.getSensorY().doubleValue()));
+        if (StateConstant.PendingAnalysis.getEnglish().equals(state.getStateName())) {
+          state.setStateName(StateConstant.PendingAnalysis.getChinese());
         }
-        if (StringUtil.isNotEmpty(vs.getSensorZ())) {
-            vo.setSensorZ(saveTwoDecimalPlaces(vs.getSensorZ().doubleValue()));
+        if (StateConstant.Running.getEnglish().equals(state.getStateName())) {
+          state.setStateName(StateConstant.Running.getChinese());
         }
-        if (StringUtil.isNotEmpty(vs.getSensorH())) {
-            vo.setSensorH(saveTwoDecimalPlaces(vs.getSensorH().doubleValue()));
+        if (StateConstant.Analysing.getEnglish().equals(state.getStateName())) {
+          state.setStateName(StateConstant.Analysing.getChinese());
         }
-        if (StringUtil.isNotEmpty(vs.getSensorP())) {
-            vo.setSensorP(saveTwoDecimalPlaces(vs.getSensorP().doubleValue()));
+        if (StateConstant.Completed.getEnglish().equals(state.getStateName())) {
+          state.setStateName(StateConstant.Completed.getChinese());
         }
-        if (StringUtil.isNotEmpty(vs.getSensorR())) {
-            vo.setSensorR(saveTwoDecimalPlaces(vs.getSensorR().doubleValue()));
+        if (StateConstant.Terminated.getEnglish().equals(state.getStateName())) {
+          state.setStateName(StateConstant.Terminated.getChinese());
         }
-        if (StringUtil.isNotEmpty(vs.getSensorPort())) {
-            vo.setSensorPort(vs.getSensorPort());
+        if (StateConstant.Terminating.getEnglish().equals(state.getStateName())) {
+          state.setStateName(StateConstant.Terminating.getChinese());
         }
-
-    }
-
-    @Override
-    public ResponseBodyVO<ProjectReportVo> selectProjectReportById(SimulationManualProjectParam param) {
-        String projectType = param.getProjectType();
-        // 封装要使用到的数据
-        SimulationManualProjectPo poParam = new SimulationManualProjectPo();
-
-        if (DictConstants.PROJECT_TYPE_MANUAL.equals(projectType)) {
-            // 项目基本信息
-            poParam = simulationProjectMapper.selectProjectBaseById(param);
-        } else if (DictConstants.PROJECT_TYPE_AUTO_SUB.equals(projectType)) {
-            SimulationManualProjectVo po = simulationAutomaticSubProjectMapper.selectProjectInfo(param);
-            BeanUtils.copyProperties(po, poParam);
+        if (StateConstant.Pending.getEnglish().equals(state.getStateName())) {
+          state.setStateName(StateConstant.Pending.getChinese());
         }
+      });
+    }
+    projectDetailsVo.setStateList(states);
 
-        // 算法配置
-        AlgorithmPO algorithmBaseInfoVo = getAlgorithmInfo(poParam);
-        ProjectReportVo projectReportVo = new ProjectReportVo();
-        projectReportVo.setProjectId(poParam.getProjectId());
-        projectReportVo.setProjectName(poParam.getProjectName());
-        projectReportVo.setAlgorithmName(algorithmBaseInfoVo.getAlgorithmName());
-        projectReportVo.setAlgorithmDescribe(algorithmBaseInfoVo.getDescription());
-
-        // 添加开始时间
-        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
-        if (poParam.getStartTime() != null) {
-            projectReportVo.setStartTime(dateFormat.format(poParam.getStartTime()));
-        }
+    return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS, projectDetailsVo);
+  }
 
-        String sceneNames;
+  private ResponseBodyVO<ProjectDetailsVo> selectProjectDetailsByIdBackUp(SimulationManualProjectParam param) {
 
-        // 算法测试得分表
-        /*
-         * 汇总测试得分计算方法:(每一项一级指标的测试得分*测试权重)累加
-         * 得分率计算方法:每一项一级指标的所有场景得分不为0的数量/每一项一级指标的场景数量
-         * 汇总得分率计算方法:(每一项一级指标的所有场景得分不为0的数量_累加/每一项一级指标的场景数量_累加)换成(得分累加取平均值)
-         */
-
-        // 获取得分表一级指标信息
-        SimulationMptFirstTargetScorePo par = new SimulationMptFirstTargetScorePo();
-        par.setPId(poParam.getId());
-        List<SimulationMptFirstTargetScorePo> pos = simulationMptFirstTargetScoreMapper.selectFirstTargetByPid(par);
-
-        List<AlgorithmScoreVo> algorithmScoreVoList = new ArrayList<>();
-        String evaluationLevelReport;
+    if (isEmpty(param.getId())) {
+      return new ResponseBodyVO<>(ResponseBodyVO.Response.CLIENT_FAILURE);
+    }
 
-        StringBuilder stringBuilder = new StringBuilder();
+    if (isEmpty(param.getProjectType())) {
+      param.setProjectType("1");// 默认
+    }
 
-        // 汇总数据初始化
-        int totalSceneNum = 0;
-        double totalScore = 0D;
-        double totalScoreRatio = 0D;
-        int totalSceneScoreNum = 0;
-
-        // 根据一级指标表结果获取平分细则
-        for (SimulationMptFirstTargetScorePo firstTargetScorePo : pos) {
-            // 获取指标信息
-            int sceneNum = firstTargetScorePo.getSceneNum(); // 一级指标包含场景数量
-            String weight = firstTargetScorePo.getWeight(); // 一级指标权重
-            double weightDouble = Double.parseDouble(weight);
-            // 单个二级指标得分
-            Double score = firstTargetScorePo.getScore();
-            totalScore += BigDecimal.valueOf(score)
-                    .multiply(BigDecimal.valueOf(weightDouble).divide(BigDecimal.valueOf(100))).doubleValue();
-            // 获取得分不为 0 的场景数量
-            Integer scoreNum = getSetScoreNum(firstTargetScorePo.getSublistId(), poParam.getId());
-            totalSceneScoreNum += scoreNum;
-
-            totalScoreRatio += Double.valueOf(scoreNum) / Double.valueOf(sceneNum) * 100;
-
-            AlgorithmScoreVo algorithmScoreVo = new AlgorithmScoreVo();
-            algorithmScoreVo.setProjectName(firstTargetScorePo.getSublistName());
-            algorithmScoreVo.setSceneNum(sceneNum);
-            algorithmScoreVo.setWeight(weight);
-            algorithmScoreVo.setScore(saveTwoDecimalPlaces(score));
-            algorithmScoreVo
-                    .setScoreRatio(saveTwoDecimalPlaces(Double.valueOf(scoreNum) / Double.valueOf(sceneNum) * 100));
-
-            algorithmScoreVoList.add(algorithmScoreVo);
-
-            // 其他操作
-            stringBuilder.append(firstTargetScorePo.getSublistName()).append("、");
-            totalSceneNum += sceneNum;
-        }
-        // 汇总
-        AlgorithmScoreVo algorithmScoreVo = new AlgorithmScoreVo();
-        algorithmScoreVo.setProjectName("汇总");
-        algorithmScoreVo.setSceneNum(totalSceneNum);
-        // 指标权重总和默认是100%
-        algorithmScoreVo.setWeight("100");
-        algorithmScoreVo.setScore(saveTwoDecimalPlaces(totalScore));
-
-        totalScoreRatio = Double.valueOf(totalSceneScoreNum) / Double.valueOf(totalSceneNum) * 100;
-        // 汇总得分率计算方式修改
-        // algorithmScoreVo.setScoreRatio(saveTwoDecimalPlaces(totalScoreRatio));
-        algorithmScoreVo.setScoreRatio(NumberUtil.cut(totalScoreRatio, 2));
-        algorithmScoreVoList.add(algorithmScoreVo);
-        projectReportVo.setScoreRatio(saveTwoDecimalPlaces(totalScoreRatio));
-        projectReportVo.setAlgorithmScore(saveTwoDecimalPlaces(totalScore));
-        evaluationLevelReport = poParam.getEvaluationLevel();
-        if (DictConstants.EVALUATION_LEVEL_G.equals(evaluationLevelReport)) {
-            projectReportVo.setEvaluationLevel(DictConstants.EVALUATION_LEVEL_G_DESCRIPTION);
-            projectReportVo.setEvaluationGrade(DictConstants.EVALUATION_LEVEL_G_DESCRIPTION);
-        } else if (DictConstants.EVALUATION_LEVEL_A.equals(evaluationLevelReport)) {
-            projectReportVo.setEvaluationLevel(DictConstants.EVALUATION_LEVEL_A_DESCRIPTION);
-            projectReportVo.setEvaluationGrade(DictConstants.EVALUATION_LEVEL_A_DESCRIPTION);
-        } else if (DictConstants.EVALUATION_LEVEL_M.equals(evaluationLevelReport)) {
-            projectReportVo.setEvaluationLevel(DictConstants.EVALUATION_LEVEL_M_DESCRIPTION);
-            projectReportVo.setEvaluationGrade(DictConstants.EVALUATION_LEVEL_M_DESCRIPTION);
-        } else if (DictConstants.EVALUATION_LEVEL_P.equals(evaluationLevelReport)) {
-            projectReportVo.setEvaluationLevel(DictConstants.EVALUATION_LEVEL_P_DESCRIPTION);
-            projectReportVo.setEvaluationGrade(DictConstants.EVALUATION_LEVEL_P_DESCRIPTION);
-        }
-
-        sceneNames = stringBuilder.substring(0, stringBuilder.lastIndexOf("、"));
-        projectReportVo.setAlgorithmEvaluation(
-                algorithmBaseInfoVo.getAlgorithmName() + "经测试获得" + projectReportVo.getEvaluationLevel() + "级评价," + "("
-                        + sceneNames + ")得分率达到了" + projectReportVo.getScoreRatio() + "%。");
-        projectReportVo.setAlgorithmScoreList(algorithmScoreVoList);
-        // 指标得分列表
-        Map<String, Object> stringObjectMap = selectScenePackageSubListAndSetScore(poParam.getScene(), poParam.getId());
-        projectReportVo.setSubListScoreLiTitle((List<Map>) stringObjectMap.get("headerList"));
-        projectReportVo.setSubListScoreLi((List<SubScListVo>) stringObjectMap.get("result"));
-
-        // 场景得分列表
-        Map<String, Object> maps = selectSceneScore2(poParam.getScene(), poParam.getId(), null, projectReportVo);
-        projectReportVo.setSceneScoreLiTitle((List<Map>) maps.get("headerList"));
-        projectReportVo.setSceneScoreLi((List<SceneScListVo>) maps.get("result"));
-
-        return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS, projectReportVo);
-    }
-
-    private AlgorithmPO getAlgorithmInfo(SimulationManualProjectPo po) {
-        AlgorithmPO algorithmBaseInfoVo = null;
-        String algorithmId = po.getAlgorithm();
-        String algorithmType = po.getAlgorithmType();
-        // 第三方算法平台
-        if ("3".equals(algorithmType)) {
-            String sort = "algorithmId-desc";
-            int page = 1;
-            int size = 1;// 全部
-
-            String urlParam = "&algorithmId" + algorithmId + "&page=" + page + "&size=" + size + "&sort=" + sort;
-            List<DropDownVo> otherAlgorithmInfo = getOtherAlgorithmInfo(urlParam);
-            if (StringUtil.isNotEmpty(otherAlgorithmInfo)) {
-                DropDownVo dropDownVo = otherAlgorithmInfo.get(0);
-                algorithmBaseInfoVo = new AlgorithmPO();
-                algorithmBaseInfoVo.setAlgorithmName(dropDownVo.getName());
-                algorithmBaseInfoVo.setDescription(dropDownVo.getDescription());
-            }
+    ProjectDetailsVo projectDetailsVo = new ProjectDetailsVo();
+
+    // 封装要使用到的数据
+    SimulationManualProjectPo poParam = new SimulationManualProjectPo();
+
+    if ("1".equals(param.getProjectType())) { // 手动运行任务
+      // 项目基本信息
+      SimulationManualProjectPo po = simulationProjectMapper.selectProjectById(param);
+      if (po == null) {
+        return new ResponseBodyVO<>(ResponseBodyVO.Response.SERVER_FAILURE, "没有获取到数据");
+      }
+      poParam = po;
+    } else if ("2".equals(param.getProjectType())) {
+      SimulationManualProjectVo po = simulationAutomaticSubProjectMapper.selectProjectInfo(param);
+      if (po == null) {
+        return new ResponseBodyVO<>(ResponseBodyVO.Response.SERVER_FAILURE, "没有获取到数据");
+      }
+      BeanUtils.copyProperties(po, poParam);
 
-        } else {
-            algorithmBaseInfoVo = simulationProjectMapper.selectAlgorithmById(algorithmId);
-        }
-        return algorithmBaseInfoVo;
     }
 
-    /**
-     * 获取添加工作时需要的下拉选项
-     * 0. 算法列表
-     * 1. 车辆列表
-     * 2. 场景列表
-     */
-    @Override
-    public ResponseBodyVO<List<DropDownTypeVo>> selectDropDownByType(SimulationManualProjectParam param) {
-        List<DropDownTypeVo> result = new ArrayList<>();
-        if (isEmpty(param.getDropDownType())) {
-            // 获取全部(算法,车辆,场景)
-            setAlgorithmDropDown(result, param.getAlgorithmType());
-            setVehicleDropDown(result, null);
-            setScenePackageDropDown(result);
-        } else if ("1".equals(param.getDropDownType())) {
-            setAlgorithmDropDown(result, param.getAlgorithmType());
-        } else if ("2".equals(param.getDropDownType())) {
-            setVehicleDropDown(result, null);
-        } else if ("3".equals(param.getDropDownType())) {
-            setScenePackageDropDown(result);
-        }
-        return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS, result);
-    }
-
-    /**
-     * 获取添加工作时需要的下拉选项
-     * 0. 算法列表
-     * 1. 车辆列表
-     * 2. 场景列表
-     */
-    @Override
-    public ResponseBodyVO<List<DropDownTypeNewVo>> selectDropDownByTypeNew(SimulationManualProjectParam param) {
-        List<DropDownTypeNewVo> result = new ArrayList<>();
-        if (isEmpty(param.getDropDownType())) {
-            // 获取全部(算法,车辆,场景)
-            setAlgorithmDropDownNew(result, param.getAlgorithmType());
-            setVehicleDropDownNew(result);
-            setScenePackageDropDownNew(result);
-        } else if ("1".equals(param.getDropDownType())) {
-            setAlgorithmDropDownNew(result, param.getAlgorithmType());
-        } else if ("2".equals(param.getDropDownType())) {
-            setVehicleDropDownNew(result);
-        } else if ("3".equals(param.getDropDownType())) {
-            setScenePackageDropDownNew(result);
-        }
-        return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS, result);
-    }
-
-    @Override
-    public ResponseBodyVO<ProjectTaskDetailsVo> selectProjectTaskById(SimulationManualProjectParam param) {
-        ProjectTaskDetailsVo resultVo = new ProjectTaskDetailsVo();
-        // 1 获取参数
-        Optional.ofNullable(param).orElseThrow(() -> new RuntimeException("参数不能为空。"));
-        Optional.ofNullable(param.getId()).orElseThrow(() -> new RuntimeException("项目 id 不能为空。"));
-        Optional.ofNullable(param.getTaskId()).orElseThrow(() -> new RuntimeException("任务 id 不能为空。"));
-        Optional.ofNullable(param.getProjectType()).orElseThrow(() -> new RuntimeException("项目类型不能为空。"));
-        String id = param.getId();
-        String taskId = param.getTaskId();
-        String projectType = param.getProjectType(); // 2
-        // 2 查询任务信息,手动项目和自动项目共用一个任务表
-        ProjectTaskParam projectTaskParam = new ProjectTaskParam();
-        projectTaskParam.setPId(id);
-        projectTaskParam.setId(taskId);
-        List<ManualProjectTaskPo> pos = simulationProjectTaskMapper.selectProjectTask(projectTaskParam);
-        if (CollectionUtil.isEmpty(pos)) {
-            return new ResponseBodyVO<>(ResponseBodyVO.Response.SERVER_FAILURE, "没有获取到任务信息。");
-        }
-        ManualProjectTaskPo po = pos.get(0);
-        resultVo.setTaskId(po.getId());
-        String sceneId = po.getSceneId();
-        String sceneType = po.getSceneType(); // 4
-        SceneBaseInfoVo sceneBaseInfoVo = getSceneNameAndOther(sceneId, sceneType); // ACC_2-5-1
-        resultVo.setSceneName(sceneBaseInfoVo.getCommonSceneName()); // ACC_2-5-1
-        resultVo.setRunStartTime(getRqStr(po.getRunStartTime(), 1)); // 2022-07-27 09:52:04
-        resultVo.setRunEndTime(getRqStr(po.getRunEndTime(), 1)); // 2022-07-27 09:53:14
-        resultVo.setRunState(po.getRunState()); // Completed
-        resultVo.setFinishState(po.getRunResult()); // Completed
-        resultVo.setSceneDescribe(""); // 场景描述设置为空
-        // -------------------------------- 获取任务得分详情 --------------------------------
-        SimulationManualProjectPo poParam = new SimulationManualProjectPo();
-        if (DictConstants.PROJECT_TYPE_MANUAL.equals(projectType)) {
-            SimulationManualProjectPo spo = simulationProjectMapper.selectProjectBaseById(param);
-            Optional.ofNullable(spo).orElseThrow(() -> new RuntimeException("没有获取到数据。"));
-            poParam = spo;
-        } else if (DictConstants.PROJECT_TYPE_AUTO_SUB.equals(projectType)) {
-            SimulationManualProjectVo spo = simulationAutomaticSubProjectMapper.selectProjectInfo(param);
-            Optional.ofNullable(spo).orElseThrow(() -> new RuntimeException("没有获取到数据。"));
-            BeanUtils.copyProperties(spo, poParam);
-        }
-        Map<String, Object> stringObjectMap = selectSceneScore(poParam.getScene(), poParam.getId(), taskId);
-        resultVo.setSceneScoreLiTitle((List<Map>) stringObjectMap.get("headerList"));
-        resultVo.setSceneScoreLi((List<SceneScListVo>) stringObjectMap.get("result"));
-        // 1.获取仿真结果文件
-        InputStream fileInputStream = null;
-        InputStreamReader inputStreamReader = null;
-        BufferedReader bufferedReader = null;
-        try {
-            // 2.解析仿真文件
-            // time
-            List<Double> time_list = new ArrayList<>();
-            // velocity
-            List<Double> velocity_list = new ArrayList<>();
-            List<Double> lateral_velocity_list = new ArrayList<>();// 横 时间
-            List<Double> longitudinal_velocity_list = new ArrayList<>();// 纵 速度
-            // acceleration
-            // List<Double> acceleration_list = new ArrayList<>();
-            // List<Double> acceleration_list_longitudinal = new ArrayList<>();
-            List<Double> lateral_acceleration_list = new ArrayList<>(); // 横向加速度
-            List<Double> longitudinal_acceleration_list = new ArrayList<>(); // 纵向加速度
-            // lane_offset
-            List<Double> lane_offset_list = new ArrayList<>();
-            /// TODO brake
-            List<Double> brake_list = new ArrayList<>();
-            // steeting_wheel
-            List<Double> steeting_wheel_list = new ArrayList<>();
-            /// TODO throttle
-            List<Double> throttle_list = new ArrayList<>();
-
-            List<Double> yawrate_list = new ArrayList<>();// 摆角速度
-
-            /*
-             * File file = new File("E:\\仿真云平台\\任务详情界面数据\\Ego(1).csv");
-             * fileInputStream = new FileInputStream(file);
-             * inputStreamReader = new InputStreamReader(fileInputStream,"utf-8");
-             */
-
-            MinioParameter minioParameter = new MinioParameter();
-            minioParameter.setObjectName(po.getRunResultFilePath() + "/Ego.csv");
-            // minioParameter.setObjectName("test/ego.csv");
-            Response download = fileDownService.download(minioParameter);
-            Response.Body body = download.body();
-            fileInputStream = body.asInputStream();
-
-            /*
-             * String path = "/temp" + StringUtil.getRandomCode();
-             * FileUtil.writeInputStreamToLocalFile(body.asInputStream(),path);
-             * file = new File(path);
-             * fileInputStream = new FileInputStream(file);
-             */
-
-            inputStreamReader = new InputStreamReader(fileInputStream, StandardCharsets.UTF_8);
-
-            bufferedReader = new BufferedReader(inputStreamReader);
-            String line;
-            int lineIndex = 0;
-            while ((line = bufferedReader.readLine()) != null) {
-                lineIndex++;
-                if (lineIndex == 1) {
-                    continue;
-                }
-                String[] split = line.split(",");
-
-                //// 添加异常捕获,非正常数据默认为0
-                // 1时间 6横向速度 7纵向速度 8横向加速度 9纵向加速度 12steering_angle 13yawrate 27lane_center_offset
-                // 时间
-                try {
-                    double aDouble = Double.parseDouble(split[1]);
-                    if (Double.isNaN(aDouble)) {
-                        time_list.add(0D);
-                    } else {
-                        time_list.add(Double.valueOf(split[1]));
-                    }
-                } catch (NumberFormatException e) {
-                    time_list.add(0D);
-                }
-
-                // 横向速度
-                try {
-                    double aDouble = Double.parseDouble(split[6]);
-                    if (Double.isNaN(aDouble)) {
-                        lateral_velocity_list.add(0D);
-                    } else {
-                        lateral_velocity_list.add(Double.valueOf(split[6]));
-                    }
-                } catch (NumberFormatException e) {
-                    lateral_velocity_list.add(0D);
-                }
-
-                // 纵向速度
-                try {
-                    double aDouble = Double.parseDouble(split[7]);
-                    if (Double.isNaN(aDouble)) {
-                        longitudinal_velocity_list.add(0D);
-                    } else {
-                        longitudinal_velocity_list.add(Double.valueOf(split[7]));
-                    }
-                } catch (NumberFormatException e) {
-                    longitudinal_velocity_list.add(0D);
-                }
-
-                // 横向加速度
-                try {
-                    double aDouble = Double.parseDouble(split[8]);
-                    if (Double.isNaN(aDouble)) {
-                        lateral_acceleration_list.add(0D);
-                    } else {
-                        lateral_acceleration_list.add(Double.valueOf(split[8]));
-                    }
-                } catch (NumberFormatException e) {
-                    lateral_acceleration_list.add(0D);
-                }
-
-                // 纵向加速度
-                try {
-                    double aDouble = Double.parseDouble(split[9]);
-                    if (Double.isNaN(aDouble)) {
-                        longitudinal_acceleration_list.add(0D);
-                    } else {
-                        longitudinal_acceleration_list.add(Double.valueOf(split[9]));
-                    }
-                } catch (NumberFormatException e) {
-                    longitudinal_acceleration_list.add(0D);
-                }
-
-                // steering_angle
-                try {
-                    double aDouble = Double.parseDouble(split[12]);
-                    if (Double.isNaN(aDouble)) {
-                        steeting_wheel_list.add(0D);
-                    } else {
-                        steeting_wheel_list.add(Double.valueOf(split[12]));// steering_angle
-                    }
-                } catch (NumberFormatException e) {
-                    steeting_wheel_list.add(0D);
-                }
-
-                try {
-                    double aDouble = Double.parseDouble(split[13]);
-                    if (Double.isNaN(aDouble)) {
-                        yawrate_list.add(0D);
-                    } else {
-                        yawrate_list.add(Double.valueOf(split[13]));
-                    }
-                } catch (NumberFormatException e) {
-                    yawrate_list.add(0D);
-                }
-
-                try {
-                    double aDouble = Double.parseDouble(split[27]);
-                    if (Double.isNaN(aDouble)) {
-                        lane_offset_list.add(0D);
-                    } else {
-                        lane_offset_list.add(Double.valueOf(split[27]));// lane_center_offset
-                    }
-                } catch (NumberFormatException e) {
-                    lane_offset_list.add(0D);
-                }
-
-                // brake_list.add(Double.valueOf(split[])); ///TODO 没有
-                // throttle_list.add(Double.valueOf(split[]));///TODO 没有
+    // 获取场景包信息
+    ScenePackagePO scenePackagePO = simulationProjectMapper.selectScenePackageInfoById(poParam.getScene());
 
-            }
-            // 里程
-            double lc = 0.0;
-            for (int i = 0; i < time_list.size(); i++) {
-                if (i == 0) {
-                    continue;
-                }
-                lc += (time_list.get(i) - time_list.get(i - 1)) * longitudinal_velocity_list.get(i - 1);
+    projectDetailsVo.setPackageName(scenePackagePO.getPackageName());
 
-            }
-
-            // 平均速度
-            Double pjsd = lc / time_list.get(time_list.size() - 1);
-            pjsd = saveTwoDecimalPlaces(pjsd, 4);
-
-            Double zdsd = Collections.max(longitudinal_velocity_list); // 最大速度
-            Double zxsd = Collections.min(longitudinal_velocity_list); // 最小速度
-            Double maxLateralAcceleration = Collections.max(lateral_acceleration_list); // 最大横向加速度
-            Double minLateralAcceleration = Collections.min(lateral_acceleration_list); // 最小横向加速度(最大横向减速度)
-            Double maxLongitudinalAcceleration = Collections.max(longitudinal_acceleration_list); // 最大纵向加速度
-            Double minLongitudinalAcceleration = Collections.min(longitudinal_acceleration_list); // 最小纵向加速度
-            Double zdbjsd = Collections.max(yawrate_list); // 最大摆角速度
-
-            // 自车速度方差
-            Double zcsdfc = 0D;
-            for (Double d : longitudinal_velocity_list) {
-                zcsdfc += Math.pow(d - pjsd, 2);
-            }
-            zcsdfc = zcsdfc / longitudinal_velocity_list.size();
-            zcsdfc = saveTwoDecimalPlaces(zcsdfc, 4);
-
-            // 自车横摆角速度均方根
-            Double zchbjsdjfg = 0D;
-            for (Double d : yawrate_list) {
-                // zchbjsdjfg += Math.pow(d-pjsd,2);
-                zchbjsdjfg += Math.pow(d, 2);
-            }
-            zchbjsdjfg = Math.sqrt(zchbjsdjfg / yawrate_list.size());
-            zchbjsdjfg = saveTwoDecimalPlaces(zchbjsdjfg, 4);
-
-            // for (int i = 0; i < lateral_acceleration.size(); i++) {
-            // Double aDouble = lateral_acceleration.get(i);
-            // Double aDouble1 = longitudinal_acceleration_list.get(i);
-            // double d = Math.pow(aDouble, 2) + Math.pow(aDouble1, 2);
-            // acceleration_list.add(Math.sqrt(d));
-            // }
-
-            for (int i = 0; i < lateral_velocity_list.size(); i++) {
-                Double aDouble = lateral_velocity_list.get(i);
-                Double aDouble1 = longitudinal_velocity_list.get(i);
-                double d = Math.pow(aDouble, 2) + Math.pow(aDouble1, 2);
-                velocity_list.add(Math.sqrt(d) * 3.6);
-            }
+    // 算法配置
+    AlgorithmPO algorithmBaseInfoVo = getAlgorithmInfo(poParam);
+    // 获取测试得分列表
+    List<AlgorithmScoreVo> firstTargetScore = getFirstTargetScore(param.getId());
+    projectDetailsVo.setAlgorithmScoreList(firstTargetScore);
 
-            // 获取视频预览路径
-            List<String> list1 = new ArrayList<>();
-            String runResultFilePath = po.getRunResultFilePath();
-            MinioParameter minioParameter1 = new MinioParameter();
-            minioParameter1.setObjectName(runResultFilePath);
-            ResponseBodyVO<List<String>> list = fileDownService.list(minioParameter1);
-            List<String> info = list.getInfo();
-            for (String s : info) {
-                String substring = s.substring(s.lastIndexOf(".") + 1);
-                if ("mp4".equals(substring)) {
-                    // mp4视频文件
-                    minioParameter1.setObjectName(s);
-                    ResponseBodyVO<String> preview = fileDownService.getPreviewUrl(minioParameter1);
-                    list1.add(preview.getInfo());
-                }
+    // 车辆配置
+    VehiclePO vehicleBaseInfoVo = null;
+    String vehicleConfigId = poParam.getVehicle();
 
-            }
+    ConfigPO configPO = new ConfigPO();
+    configPO.setId(vehicleConfigId);
+    List<ConfigPO> configVehicleVOS = simulationProjectMapper.selectConfigVehicle(configPO);
+    if (!isEmpty(configVehicleVOS)) {
+      ConfigPO configVehicleVO = configVehicleVOS.get(0);
+      List<VehiclePO> vehiclePOS = simulationProjectMapper.selectVehicleBaseInfoById(configVehicleVO.getVehicleId());
+      if (!isEmpty(vehiclePOS)) {
+        vehicleBaseInfoVo = vehiclePOS.get(0);
+      }
 
-            // 任务详情信息
-            resultVo.setMileage(Double.toString(lc));
-            resultVo.setAverageVelocity(saveTwoDecimalPlaces(pjsd * 3.6, 4).toString());
-            resultVo.setMaximunSpeed(zdsd.toString()); // 最大速度
-            resultVo.setMinimunVelocity(zxsd.toString()); // 最小速度
-            resultVo.setMaximumAcceleration(maxLateralAcceleration.toString()); // 最大横向加速度
-            resultVo.setMaximumDeceleration(minLateralAcceleration.toString()); // 最大横向减速度
-            resultVo.setMaxLongitudinalAcceleration(maxLongitudinalAcceleration.toString()); // 最大纵向加速度
-            resultVo.setMinLongitudinalAcceleration(minLongitudinalAcceleration.toString()); // 最小纵向加速度
-            resultVo.setMaximumSwingSpeed(zdbjsd.toString());
-            resultVo.setSpeedVariance(zcsdfc);
-            // resultVo.setSpeedComfortLevel(po.getSpeedComfortLevel());
-
-            resultVo.setSwingSpeedMeanSquareRoot(zchbjsdjfg);
-            // resultVo.setSwingComfortLevel(po.getSwingComfortLevel());
-            resultVo.setVideoUrl(list1);
-
-            HashMap<String, List<Double>> CurveData = new HashMap<>();
-            CurveData.put("time", time_list);
-            CurveData.put("acceleration", lateral_acceleration_list);
-            CurveData.put("acceleration_longitudinal", longitudinal_acceleration_list);
-            CurveData.put("lane_offset", lane_offset_list);
-            CurveData.put("brake", brake_list);
-            CurveData.put("steeting", steeting_wheel_list);
-            CurveData.put("throttle", throttle_list);
-            CurveData.put("yaw_rate", yawrate_list);
-            CurveData.put("velocity", velocity_list); // 速度变化曲线
-            resultVo.setCurveData(CurveData);
-
-        } catch (Exception e) {
-            e.printStackTrace();
-
-        } finally {
-            try {
-                if (fileInputStream != null) {
-                    fileInputStream.close();
-                }
-                if (inputStreamReader != null) {
-                    inputStreamReader.close();
-                }
-                if (bufferedReader != null) {
-                    bufferedReader.close();
-                }
-            } catch (IOException e) {
-                e.printStackTrace();
-            }
-        }
-        return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS, resultVo);
     }
+    /*
+     * String vehicleImage = vehicleBaseInfoVo.getVehicleImage();
+     * if(!isEmpty(vehicleImage)){
+     * vehicleBaseInfoVo.setVehicleImage(vehicleImage.replaceFirst("Front side"
+     * ,"Top"));
+     * }
+     */
 
-    @Override
-    public String getDictName(String type, String code) {
-        Map<String, String> stringStringMap = getDictByType(type);
-        if (stringStringMap != null && stringStringMap.size() > 0) {
-            return stringStringMap.get(code);
-        }
-        return "";
+    List<ConfigSensorPO> vehicleSensorVos = simulationProjectMapper.selectVehicleSensor(vehicleConfigId);
+
+    List<SensorBaseInfoVo> sensorCameraList = new ArrayList<>();
+    List<SensorBaseInfoVo> sensorOgtList = new ArrayList<>();
+    List<SensorBaseInfoVo> sensorLidarList = new ArrayList<>();
+    List<SensorBaseInfoVo> sensorRadarList = new ArrayList<>();
+    List<SensorBaseInfoVo> sensorGpsList = new ArrayList<>();
+    for (ConfigSensorPO vs : vehicleSensorVos) {
+      String sensorType = vs.getSensorType();
+      String sensorId = vs.getSensorId();
+      if (DictConstants.SENSOR_CAMERA.equals(sensorType)) {
+        // 摄像头
+        SensorBaseInfoVo sensorBaseInfoVo = simulationProjectMapper.selectSensorCamera(sensorId);
+        if (ObjectUtil.isNotNull(sensorBaseInfoVo) && sensorBaseInfoVo.getShare().equals("0")) {
+          sensorBaseInfoVo.setSensorName("私有/" + sensorBaseInfoVo.getSensorName());
+        } else if (ObjectUtil.isNotNull(sensorBaseInfoVo) && sensorBaseInfoVo.getShare().equals("1")) {
+          sensorBaseInfoVo.setSensorName("公有/" + sensorBaseInfoVo.getSensorName());
+        }
+        setVehicleConfig(sensorBaseInfoVo, vs);
+        sensorCameraList.add(sensorBaseInfoVo);
+      } else if (DictConstants.SENSOR_OGT.equals(sensorType)) {
+        // 完美传感器
+        SensorBaseInfoVo sensorBaseInfoVo = simulationProjectMapper.selectSensorOgt(sensorId);
+        if (ObjectUtil.isNotNull(sensorBaseInfoVo) && sensorBaseInfoVo.getShare().equals("0")) {
+          sensorBaseInfoVo.setSensorName("私有/" + sensorBaseInfoVo.getSensorName());
+        } else if (ObjectUtil.isNotNull(sensorBaseInfoVo) && sensorBaseInfoVo.getShare().equals("1")) {
+          sensorBaseInfoVo.setSensorName("公有/" + sensorBaseInfoVo.getSensorName());
+        }
+        setVehicleConfig(sensorBaseInfoVo, vs);
+        sensorOgtList.add(sensorBaseInfoVo);
+      } else if (DictConstants.SENSOR_LIDAR.equals(sensorType)) {
+        // 激光雷达
+        SensorBaseInfoVo sensorBaseInfoVo = simulationProjectMapper.selectSensorLidar(sensorId);
+        if (ObjectUtil.isNotNull(sensorBaseInfoVo) && sensorBaseInfoVo.getShare().equals("0")) {
+          sensorBaseInfoVo.setSensorName("私有/" + sensorBaseInfoVo.getSensorName());
+        } else if (ObjectUtil.isNotNull(sensorBaseInfoVo) && sensorBaseInfoVo.getShare().equals("1")) {
+          sensorBaseInfoVo.setSensorName("公有/" + sensorBaseInfoVo.getSensorName());
+        }
+        setVehicleConfig(sensorBaseInfoVo, vs);
+        sensorLidarList.add(sensorBaseInfoVo);
+      } else if (DictConstants.SENSOR_RADAR.equals(sensorType)) {
+        // 毫米波雷达
+        SensorBaseInfoVo sensorBaseInfoVo = simulationProjectMapper.selectSensorRadar(sensorId);
+        if (ObjectUtil.isNotNull(sensorBaseInfoVo) && sensorBaseInfoVo.getShare().equals("0")) {
+          sensorBaseInfoVo.setSensorName("私有/" + sensorBaseInfoVo.getSensorName());
+        } else if (ObjectUtil.isNotNull(sensorBaseInfoVo) && sensorBaseInfoVo.getShare().equals("1")) {
+          sensorBaseInfoVo.setSensorName("公有/" + sensorBaseInfoVo.getSensorName());
+        }
+        setVehicleConfig(sensorBaseInfoVo, vs);
+        sensorRadarList.add(sensorBaseInfoVo);
+      } else if (DictConstants.SENSOR_GPS.equals(sensorType)) {
+        // gps
+        SensorBaseInfoVo sensorBaseInfoVo = simulationProjectMapper.selectSensorGps(sensorId);
+        setVehicleConfig(sensorBaseInfoVo, vs);
+        sensorGpsList.add(sensorBaseInfoVo);
+      }
     }
 
-    private Map<String, String> getDictByType(String type) {
-        DictParam dictParam = new DictParam();
-        dictParam.setDictTypes(type);
-        Map<String, Map<String, String>> dictMapsByTypes = dictService.getDictMapsByTypes(dictParam);
-        Map<String, String> stringStringMap = dictMapsByTypes.get(type);
-        if (stringStringMap != null && stringStringMap.size() > 0) {
-            return stringStringMap;
-        }
-        return null;
+    // 任务信息
+    ProjectTaskParam projectTaskParam = new ProjectTaskParam();
+    projectTaskParam.setPId(poParam.getId());
+    List<ProjectRunResultRatioNumVo> projectRunResultRatioNumVos = null;
 
-    }
+    // 任务运行状态统计
+    List<ProjectRunStateNumVo> projectRunStateNumVos = null;
 
-    @Override
-    @SneakyThrows
-    public ResponseBodyVO<String> analysisVehicleCoord() {
-        analysisCsvFile("E:\\仿真云平台\\三维还原视频说明\\360ogt.csv", new int[] { 6, 7, 9 });
-        return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS);
+    // 任务运行结果统计
+    List<ProjectRunResultRatioNumVo> resultScoreList = null;
 
-    }
+    Integer size = simulationProjectTaskMapper.selectProjectTaskNumByProjectId(projectTaskParam);
+    if (size > 0) {
+      projectRunStateNumVos = simulationProjectTaskMapper.selectRunStateCount(poParam.getId());
+      taskRunState(projectRunStateNumVos, size);
 
-    @Override
-    public ResponseBodyVO<PageInfo<ManualProjectTaskVo>> selectProjectTaskList(SimulationManualProjectParam param) {
-        // 查询任务信息
-        ProjectTaskParam projectTaskParam = new ProjectTaskParam();
-        projectTaskParam.setPId(param.getId());
-        setPage(param.getCurrentPage() == null ? 1 : param.getCurrentPage(),
-                param.getPageSize() == null ? 10 : param.getPageSize());
-        List<ManualProjectTaskVo> tasks = simulationProjectTaskMapper.selectProjectTaskByProjectId(projectTaskParam);
-        tasks.forEach(task -> {
-            if (StateConstant.Aborted.getEnglish().equals(task.getRunState())) {
-                task.setRunState(StateConstant.Aborted.getChinese());
-            }
-            if (StateConstant.PendingAnalysis.getEnglish().equals(task.getRunState())) {
-                task.setRunState(StateConstant.PendingAnalysis.getChinese());
-            }
-            if (StateConstant.Running.getEnglish().equals(task.getRunState())) {
-                task.setRunState(StateConstant.Running.getChinese());
-            }
-            if (StateConstant.Analysing.getEnglish().equals(task.getRunState())) {
-                task.setRunState(StateConstant.Analysing.getChinese());
-            }
-            if (StateConstant.Completed.getEnglish().equals(task.getRunState())) {
-                task.setRunState(StateConstant.Completed.getChinese());
-            }
-            if (StateConstant.Terminated.getEnglish().equals(task.getRunState())) {
-                task.setRunState(StateConstant.Terminated.getChinese());
-            }
-            if (StateConstant.Terminating.getEnglish().equals(task.getRunState())) {
-                task.setRunState(StateConstant.Terminating.getChinese());
-            }
-            if (StateConstant.Pending.getEnglish().equals(task.getRunState())) {
-                task.setRunState(StateConstant.Pending.getChinese());
-            }
-            if (StateConstant.Success.getEnglish().equals(task.getRunResult())) {
-                task.setRunResult(StateConstant.Success.getChinese());
-            }
-            if (StateConstant.Failed.getEnglish().equals(task.getRunResult())) {
-                task.setRunResult(StateConstant.Failed.getChinese());
-            }
-        });
+      projectRunResultRatioNumVos = simulationProjectTaskMapper.selectRunResultCount(poParam.getId());
+      taskResultState(projectRunResultRatioNumVos, size);
 
-        PageInfo<ManualProjectTaskVo> pageInfo = new PageInfo<>(tasks);
+      resultScoreList = simulationProjectTaskMapper.selectScoreCount(poParam.getId());
 
-        if (pageInfo.getList() != null) {
-            for (ManualProjectTaskVo task : pageInfo.getList()) {
-                task.setRunStartTimeFmt(getRqStr(task.getRunStartTime(), 1));
-                task.setRunEndTimeFmt(getRqStr(task.getRunEndTime(), 1));
-                setUpSceneInfo(task);
+      // 未完成得分为”“的改为0
+      if (!isEmpty(resultScoreList) && resultScoreList.size() == 1 && isEmpty(resultScoreList.get(0).getResultName())) {
+        ProjectRunResultRatioNumVo projectRunResultRatioNumVo = resultScoreList.get(0);
+        projectRunResultRatioNumVo.setResultName("0");
+      }
+      taskScore(resultScoreList, size);
 
-            }
-        }
-        return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS, pageInfo);
     }
 
-    private void analysisCsvFile(String filePath, int[] analysisFields) throws Exception {
-
-        File file = new File(filePath);
-        InputStream fileInputStream = Files.newInputStream(file.toPath());
-        InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream, "utf-8");
-        BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
-        String line;
-        while ((line = bufferedReader.readLine()) != null) {
-            String[] split = line.split(",");
-            for (int fs : analysisFields) {
-                System.out.println(split[fs]);
-            }
-
-        }
+    projectDetailsVo.setProjectId(poParam.getProjectId());
+    projectDetailsVo.setProjectName(poParam.getProjectName());
+    projectDetailsVo.setProjectDescribe(poParam.getProjectDescribe());
+    projectDetailsVo.setStartTime(getRqStr(poParam.getStartTime(), 1));
+    projectDetailsVo.setFinishTime(getRqStr(poParam.getFinishTime(), 1));
+    projectDetailsVo.setNowRunState(poParam.getNowRunState());
+    projectDetailsVo.setNowRunStateName(getDictName(DictConstants.PROJECT_RUN_STATE, poParam.getNowRunState()));
+    projectDetailsVo.setEvaluationLevel(getDictName(DictConstants.EVALUATION_LEVEL, poParam.getEvaluationLevel()));
+    // projectDetailsVo.setEvaluationLevel(s);
+    if (algorithmBaseInfoVo != null) {
+      projectDetailsVo.setAlgorithmName(algorithmBaseInfoVo.getAlgorithmName());
+      projectDetailsVo.setAlgorithmDescribe(algorithmBaseInfoVo.getDescription());
     }
+    if (vehicleBaseInfoVo != null) {
+      projectDetailsVo.setVehicleName(vehicleBaseInfoVo.getVehicleName());
+      projectDetailsVo.setVehicleDescribe(vehicleBaseInfoVo.getDescription());
+      projectDetailsVo.setVehicleTopView(vehicleBaseInfoVo.getVehicleFrontView());
 
-    /**
-     * 根据场景id和场景类型获取场景名
-     *
-     * @return 场景名称
-     */
-    private SceneBaseInfoVo getSceneNameAndOther(String sceneId, String sceneType) {
-        SceneBaseInfoVo resultVo = new SceneBaseInfoVo();
-        if (DictConstants.SCENE_NATURAL.equals(sceneType)) {
-            SceneBaseInfoVo sceneBaseInfoVo = simulationProjectMapper.selectSceneNatural(sceneId);
-            if (sceneBaseInfoVo != null) {
-                resultVo.setCommonSceneName(sceneBaseInfoVo.getNaturalName());
-            }
-        } else if (DictConstants.SCENE_STANDARD.equals(sceneType)) {
-            SceneBaseInfoVo sceneBaseInfoVo = simulationProjectMapper.selectSceneStandardsRegulations(sceneId);
-            if (sceneBaseInfoVo != null) {
-                resultVo.setCommonSceneName(sceneBaseInfoVo.getSceneName());
-            }
-        } else if (DictConstants.SCENE_ACCIDENT.equals(sceneType)) {
-            SceneBaseInfoVo sceneBaseInfoVo = simulationProjectMapper.selectSceneAccidentById(sceneId);
-            if (sceneBaseInfoVo != null) {
-                resultVo.setCommonSceneName(sceneBaseInfoVo.getSceneName());
-            }
-        } else if (DictConstants.SCENE_GENERAL.equals(sceneType)) {
-            SceneBaseInfoVo sceneBaseInfoVo = simulationProjectMapper.selectSceneGeneralDataById(sceneId);
-            if (sceneBaseInfoVo != null) {
-                resultVo.setCommonSceneName(sceneBaseInfoVo.getSceneName());
-            }
-        }
-        return resultVo;
     }
+    projectDetailsVo.setSensorCameraList(sensorCameraList);
+    projectDetailsVo.setSensorOgtList(sensorOgtList);
+    projectDetailsVo.setSensorLidarList(sensorLidarList);
+    projectDetailsVo.setSensorRadarList(sensorRadarList);
+    projectDetailsVo.setSensorGpsList(sensorGpsList);
+    projectDetailsVo.setStateList(projectRunStateNumVos);
+    projectDetailsVo.setResultList(projectRunResultRatioNumVos);
+    projectDetailsVo.setResultScoreList(resultScoreList);
+
+    projectDetailsVo.setParallelism(poParam.getParallelism());
+    projectDetailsVo.setMaxSimulationTime(poParam.getMaxSimulationTime());
+    String isChoiceGpu = poParam.getIsChoiceGpu();
+    String g = "";
+    if ("0".equals(isChoiceGpu)) {
+      g = "是";
+    } else if ("1".equals(isChoiceGpu)) {
+      g = "否";
+    }
+    projectDetailsVo.setIsChoiceGpu(g);
 
-    /**
-     * 查询算法下拉列表
+    /*
+     * //是否生成报告
+     * boolean isCreateReport = true;
+     * String nowRunState = projectDetailsVo.getNowRunState();
+     * if(!ProjectRunStateEnum.FINISH.getCode().equals(nowRunState)){
+     * isCreateReport = false;
+     * }else{
+     * //查询任务是否存在aborted
+     * SimulationMptSceneScorePo sPo = new SimulationMptSceneScorePo();
+     * sPo.setPId(param.getId());
+     * SceneScoreVo sceneScoreVo =
+     * simulationProjectTaskMapper.selectRunStateByAborted(sPo);
+     * if(sceneScoreVo != null && sceneScoreVo.getNum() > 0){
+     * isCreateReport = false;
+     * }
+     * }
      *
-     * @param result
-     * @param algorithmType 算法类型
+     * projectDetailsVo.setCreateReport(isCreateReport);
      */
-    private void setAlgorithmDropDown(List<DropDownTypeVo> result, String algorithmType) {
-        List<DropDownVo> algorithmList = new ArrayList<>();
-        if (DictConstants.FILE.equals(algorithmType) || DictConstants.GIT.equals(algorithmType)) {
-            AlgorithmPO algorithmPO = new AlgorithmPO();
-            algorithmPO.setCreateUserId(AuthUtil.getCurrentUserId()); // 获取当前用户 id
-            if (StringUtil.isEmpty(algorithmType)) {
-                algorithmPO.setUploadMode("1");
-            } else {
-                algorithmPO.setUploadMode(algorithmType);
-            }
-            List<AlgorithmPO> algorithmBaseInfoVo = simulationProjectMapper.selectAlgorithmBaseInfoById(algorithmPO);
-
-            for (AlgorithmPO v : algorithmBaseInfoVo) {
-                DropDownVo dropDownVo = new DropDownVo();
-                dropDownVo.setId(v.getId());
-                dropDownVo.setName(v.getAlgorithmName());
-                dropDownVo.setDescription(v.getDescription());
-                dropDownVo.setShare(v.getShare());
-                algorithmList.add(dropDownVo);
-            }
-
-        } else if (DictConstants.PLATFORM.equals(algorithmType)) {
-            // 第三方算法平台获取(索为)
-            String sort = "algorithmId-desc";
-            int page = 1;
-            int size = 999;// 全部
-            String urlParam = "&page=" + page + "&size=" + size + "&sort=" + sort;
-            algorithmList = getOtherAlgorithmInfo(urlParam);
 
-        }
-        DropDownTypeVo algorithmDropDown = new DropDownTypeVo();
-        algorithmDropDown.setDropDownList(algorithmList);
-        algorithmDropDown.setType("1");
-        result.add(algorithmDropDown);
+    return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS, projectDetailsVo);
+  }
 
+  // 运行状态统计
+  private void taskRunState(List<ProjectRunStateNumVo> vos, Integer size) {
+    for (ProjectRunStateNumVo pv : vos) {
+      Integer num = pv.getNum();
+      Double d = (double) num / size;
+      d = saveTwoDecimalPlaces(d);
+      pv.setRatio(d);
     }
+    // 补全没有的
+    Map<String, String> dict = getDictByType(ProjectConstants.TASK_RUN_STATE);
+    for (String key : dict.keySet()) {
+      boolean b = false;
+      for (ProjectRunStateNumVo pv : vos) {
+        if (pv.getStateName().equals(dict.get(key))) {
+          b = true;
+        }
+      }
+      if (!b) {
+        ProjectRunStateNumVo vo = new ProjectRunStateNumVo();
+        vo.setStateName(dict.get(key));
+        vo.setNum(0);
+        vo.setRatio(0D);
+        vos.add(vo);
+      }
 
-    /**
-     * 获取第三方算法平台的算法信息
-     *
-     * @return 第三方算法平台的算法信息
-     */
-    private List<DropDownVo> getOtherAlgorithmInfo(String query) {
-
-        List<DropDownVo> algorithmList = new ArrayList<>();
-
-        ResponseBodyVO algorithmBody = algoPlatformService.getAlgorithmList(query);
-
-        // 解析数据
-        Map jsonMap = JsonUtil.jsonToMap((String) algorithmBody.getInfo());
-        Map<String, Object> dataMap = (Map<String, Object>) jsonMap.get("data");
-        List<Map<String, String>> contentList = (List<Map<String, String>>) dataMap.get("content");
-        Integer totalElements = (Integer) dataMap.get("totalElements");
-        if (totalElements > 0) {
-            for (Map<String, String> content : contentList) {
-                DropDownVo dropDownVo = new DropDownVo();
-                dropDownVo.setId(content.get("algorithmId"));
-                dropDownVo.setName(content.get("algorithmName"));
-                dropDownVo.setDescription(content.get("description"));
-                algorithmList.add(dropDownVo);
-            }
-        }
-        return algorithmList;
-
-    }
-
-    private void setVehicleDropDown(List<DropDownTypeVo> result, String ConfigId) {
-        ConfigPO configPO = new ConfigPO();
-        if (StringUtil.isNotEmpty(ConfigId)) {
-            configPO.setId(ConfigId);
-        }
-        configPO.setCreateUserId(AuthUtil.getCurrentUserId());
-        List<ConfigPO> vehicleBaseInfoVo = simulationProjectMapper.selectConfigVehicle2(configPO);
-        List<DropDownVo> vehicleList = new ArrayList<>();
-        for (ConfigPO v : vehicleBaseInfoVo) {
-            DropDownVo dropDownVo = new DropDownVo();
-            dropDownVo.setId(v.getId());
-            dropDownVo.setName(v.getConfigName());
-            dropDownVo.setDescription(v.getDescription());
-            dropDownVo.setShare(v.getShare());
-            // 获取传感器信息
-            List<ConfigSensorPO> configSensorVos = simulationProjectMapper.selectConfigSensor(v.getId());
-            String sensor = "";
-            if (!isEmpty(configSensorVos) && configSensorVos.get(0) != null) {
-                StringBuilder stringBuilder = new StringBuilder();
-                for (ConfigSensorPO cv : configSensorVos) {
-                    stringBuilder.append(cv.getSensorType()).append(",");
-                }
-                sensor = stringBuilder.substring(0, stringBuilder.lastIndexOf(","));
+    }
+  }
+
+  // 运行结果统计
+  private void taskResultState(List<ProjectRunResultRatioNumVo> vos, Integer size) {
+    // 结果状态统计
+    for (ProjectRunResultRatioNumVo rv : vos) {
+      Integer num = rv.getNum();
+      Double d = (double) num / size;
+      d = saveTwoDecimalPlaces(d);
+      rv.setRatio(d);
+    }
+    // 补全没有的
+    Map<String, String> dict = getDictByType(ProjectConstants.TASK_RESULT_STATE);
+    for (String key : dict.keySet()) {
+      boolean b = false;
+      for (ProjectRunResultRatioNumVo pv : vos) {
+        if (dict.get(key).equals(pv.getResultName())) {
+          b = true;
+        }
+      }
+      if (!b) {
+        ProjectRunResultRatioNumVo vo = new ProjectRunResultRatioNumVo();
+        vo.setResultName(dict.get(key));
+        vo.setNum(0);
+        vo.setRatio(0D);
+        vos.add(vo);
+      }
+    }
+  }
+
+  /**
+   * 得分统计
+   */
+  private void taskScore(List<ProjectRunResultRatioNumVo> vos, Integer size) {
+    for (ProjectRunResultRatioNumVo rv : vos) {
+      Integer num = rv.getNum();
+      Double d = (double) num / size;
+      d = saveTwoDecimalPlaces(d);
+      rv.setRatio(d);
+    }
+  }
+
+  private void setVehicleConfig(SensorBaseInfoVo vo, ConfigSensorPO vs) {
+    vo.setConfigId(vs.getConfigId());
+    vo.setSensorId(vs.getSensorId());
+    vo.setSensorType(vs.getSensorType());
+    if (StringUtil.isNotEmpty(vs.getSensorX())) {
+      vo.setSensorX(saveTwoDecimalPlaces(vs.getSensorX().doubleValue()));
+    }
+    if (StringUtil.isNotEmpty(vs.getSensorY())) {
+      vo.setSensorY(saveTwoDecimalPlaces(vs.getSensorY().doubleValue()));
+    }
+    if (StringUtil.isNotEmpty(vs.getSensorZ())) {
+      vo.setSensorZ(saveTwoDecimalPlaces(vs.getSensorZ().doubleValue()));
+    }
+    if (StringUtil.isNotEmpty(vs.getSensorH())) {
+      vo.setSensorH(saveTwoDecimalPlaces(vs.getSensorH().doubleValue()));
+    }
+    if (StringUtil.isNotEmpty(vs.getSensorP())) {
+      vo.setSensorP(saveTwoDecimalPlaces(vs.getSensorP().doubleValue()));
+    }
+    if (StringUtil.isNotEmpty(vs.getSensorR())) {
+      vo.setSensorR(saveTwoDecimalPlaces(vs.getSensorR().doubleValue()));
+    }
+    if (StringUtil.isNotEmpty(vs.getSensorPort())) {
+      vo.setSensorPort(vs.getSensorPort());
+    }
 
-            }
-            dropDownVo.setSensor(sensor);
-
-            vehicleList.add(dropDownVo);
-        }
-
-        DropDownTypeVo vehicleDropDown = new DropDownTypeVo();
-        vehicleDropDown.setDropDownList(vehicleList);
-        vehicleDropDown.setType("2");
-        result.add(vehicleDropDown);
-    }
-
-    private void setScenePackageDropDown(List<DropDownTypeVo> result) {
-        ScenePackagePO scenePackagePO = new ScenePackagePO();
-        scenePackagePO.setCreateUserId(AuthUtil.getCurrentUserId());
-        List<ScenePackagePO> scenePackageBaseVo = simulationProjectMapper.selectScenePackageBaseById(scenePackagePO);
-        List<DropDownVo> scenePackageList = new ArrayList<>();
-        for (ScenePackagePO v : scenePackageBaseVo) {
-            DropDownVo dropDownVo = new DropDownVo();
-            dropDownVo.setId(v.getPackageId());
-            dropDownVo.setName(v.getPackageName());
-            dropDownVo.setSceneNum(String.valueOf(v.getSceneNum()));
-            dropDownVo.setShare(v.getShare());
-            scenePackageList.add(dropDownVo);
-        }
-        DropDownTypeVo scenePackageDropDown = new DropDownTypeVo();
-        scenePackageDropDown.setDropDownList(scenePackageList);
-        scenePackageDropDown.setType("3");
-        result.add(scenePackageDropDown);
-    }
-
-    private SimulationManualProjectPo convertParamToPo(SimulationManualProjectParam param) {
-        SimulationManualProjectPo po = new SimulationManualProjectPo();
-        po.setId(param.getId());
-        po.setProjectName(param.getProjectName());
-        po.setProjectDescribe(param.getProjectDescribe());
-        po.setAlgorithm(param.getAlgorithm());
-        po.setVehicle(param.getVehicle());
-        po.setScene(param.getScene());
-        // po.setOperationCycle(param.getOperationCycle());
-        po.setMaxSimulationTime(param.getMaxSimulationTime());
-        po.setParallelism(param.getParallelism());
-        // po.setRuleView(param.getRuleView());
-        po.setIsChoiceGpu(param.getIsChoiceGpu());
-        po.setNowRunState(param.getNowRunState());
-        po.setAlgorithmType(param.getAlgorithmType());
+  }
 
-        if (ObjectUtil.isNotNull(param.getVehicleArrayS())) {
-            po.setVehicleArray(StringUtils.join(Arrays.asList(param.getVehicleArrayS()), ','));
-        }
-        if (ObjectUtil.isNotNull(param.getAlgorithmArrayS())) {
-            po.setAlgorithmArray(StringUtils.join(Arrays.asList(param.getAlgorithmArrayS()), ','));
-        }
-        if (ObjectUtil.isNotNull(param.getSceneArrayS())) {
-            po.setSceneArray(StringUtils.join(Arrays.asList(param.getSceneArrayS()), ','));
-        }
-        return po;
+  @Override
+  public ResponseBodyVO<ProjectReportVo> selectProjectReportById(SimulationManualProjectParam param) {
+    String projectType = param.getProjectType();
+    // 封装要使用到的数据
+    SimulationManualProjectPo poParam = new SimulationManualProjectPo();
 
+    if (DictConstants.PROJECT_TYPE_MANUAL.equals(projectType)) {
+      // 项目基本信息
+      poParam = simulationProjectMapper.selectProjectBaseById(param);
+    } else if (DictConstants.PROJECT_TYPE_AUTO_SUB.equals(projectType)) {
+      SimulationManualProjectVo po = simulationAutomaticSubProjectMapper.selectProjectInfo(param);
+      BeanUtils.copyProperties(po, poParam);
     }
 
-    private void convertPoToVo(SimulationManualProjectVo simulationManualProjectVo, boolean isAuto) {
-        // 1 查询算法名称
-        String algorithmId = simulationManualProjectVo.getAlgorithm();
-        String algorithmType = simulationManualProjectVo.getAlgorithmType();
-        String algorithmName;
-        if (DictConstants.ALGORITHM_UPLOAD_MODE_PLATFORM.equals(algorithmType)) {
-            // 1 获取 token
-            algorithmName = algoPlatformService.selectAlgorithmNameByAlgorithmId(algorithmId).getInfo();
-            if (StringUtil.isEmpty(algorithmName)) {
-                algorithmName = "算法平台已删除该算法";
-            }
-        } else {
-            AlgorithmPO algorithmPO = simulationProjectMapper.selectAlgorithmById(algorithmId);
-            if (algorithmPO != null && StringUtil.isNotEmpty(algorithmPO.getAlgorithmName())) {
-                algorithmName = algorithmPO.getAlgorithmName();
-            } else {
-                algorithmName = "仿真平台不存在该算法";
-            }
-        }
-
-        simulationManualProjectVo.setAlgorithm(algorithmName);
-        // 2 是否是自动项目
-        if (!isAuto) {
-            simulationManualProjectVo.setNowRunStateDict(
-                    getDictName(DictConstants.PROJECT_RUN_STATE, simulationManualProjectVo.getNowRunState()));
-            simulationManualProjectVo.setEvaluationLevelDict(
-                    getDictName(DictConstants.EVALUATION_LEVEL, simulationManualProjectVo.getEvaluationLevel()));
-        } else {
-            simulationManualProjectVo.setLastRunTimeFmt(getRqStr(simulationManualProjectVo.getLastRunTime(), 1));
-        }
-        // 3 格式化创建时间字符串
-        simulationManualProjectVo.setCreateTimeFmt(getRqStr(simulationManualProjectVo.getCreateTime(), 1));
+    // 算法配置
+    AlgorithmPO algorithmBaseInfoVo = getAlgorithmInfo(poParam);
+    ProjectReportVo projectReportVo = new ProjectReportVo();
+    projectReportVo.setProjectId(poParam.getProjectId());
+    projectReportVo.setProjectName(poParam.getProjectName());
+    projectReportVo.setAlgorithmName(algorithmBaseInfoVo.getAlgorithmName());
+    projectReportVo.setAlgorithmDescribe(algorithmBaseInfoVo.getDescription());
+
+    // 添加开始时间
+    SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+    if (poParam.getStartTime() != null) {
+      projectReportVo.setStartTime(dateFormat.format(poParam.getStartTime()));
     }
 
-    private void convertPoToVo(SimulationManualProjectPo po, SimulationManualProjectSingleVo vo) {
-        vo.setId(po.getId());
-        vo.setProjectName(po.getProjectName());
-        vo.setProjectDescribe(po.getProjectDescribe());
-        vo.setAlgorithm(po.getAlgorithm());
-        vo.setAlgorithmType(po.getAlgorithmType());
-        vo.setVehicle(po.getVehicle());
-        vo.setScene(po.getScene());
-        vo.setMaxSimulationTime(po.getMaxSimulationTime());
-        vo.setParallelism(po.getParallelism());
-        vo.setIsChoiceGpu(po.getIsChoiceGpu());
-
-    }
+    String sceneNames;
 
-    private void createProjectId(SimulationManualProjectPo po) {
-        Integer nowRq = getRq(null, 0);
-        po.setProjectDate(nowRq);
-        SimulationManualProjectPo po1 = simulationProjectMapper.selectLastProjectId(nowRq);
-        if (po1 == null) {
-            // 生成新id
-            po.setProjectNum(1);
-        } else {
-            po.setProjectNum(po1.getProjectNum() + 1);
-        }
-        po.setProjectId(po.getProjectDate() + "-" + po.getProjectNum());
+    // 算法测试得分表
+    /*
+     * 汇总测试得分计算方法:(每一项一级指标的测试得分*测试权重)累加
+     * 得分率计算方法:每一项一级指标的所有场景得分不为0的数量/每一项一级指标的场景数量
+     * 汇总得分率计算方法:(每一项一级指标的所有场景得分不为0的数量_累加/每一项一级指标的场景数量_累加)换成(得分累加取平均值)
+     */
 
+    // 获取得分表一级指标信息
+    SimulationMptFirstTargetScorePo par = new SimulationMptFirstTargetScorePo();
+    par.setPId(poParam.getId());
+    List<SimulationMptFirstTargetScorePo> pos = simulationMptFirstTargetScoreMapper.selectFirstTargetByPid(par);
+
+    List<AlgorithmScoreVo> algorithmScoreVoList = new ArrayList<>();
+    String evaluationLevelReport;
+
+    StringBuilder stringBuilder = new StringBuilder();
+
+    // 汇总数据初始化
+    int totalSceneNum = 0;
+    double totalScore = 0D;
+    double totalScoreRatio = 0D;
+    int totalSceneScoreNum = 0;
+
+    // 根据一级指标表结果获取平分细则
+    for (SimulationMptFirstTargetScorePo firstTargetScorePo : pos) {
+      // 获取指标信息
+      int sceneNum = firstTargetScorePo.getSceneNum(); // 一级指标包含场景数量
+      String weight = firstTargetScorePo.getWeight(); // 一级指标权重
+      double weightDouble = Double.parseDouble(weight);
+      // 单个二级指标得分
+      Double score = firstTargetScorePo.getScore();
+      totalScore += BigDecimal.valueOf(score).multiply(BigDecimal.valueOf(weightDouble).divide(BigDecimal.valueOf(100))).doubleValue();
+      // 获取得分不为 0 的场景数量
+      Integer scoreNum = getSetScoreNum(firstTargetScorePo.getSublistId(), poParam.getId());
+      totalSceneScoreNum += scoreNum;
+
+      totalScoreRatio += Double.valueOf(scoreNum) / Double.valueOf(sceneNum) * 100;
+
+      AlgorithmScoreVo algorithmScoreVo = new AlgorithmScoreVo();
+      algorithmScoreVo.setProjectName(firstTargetScorePo.getSublistName());
+      algorithmScoreVo.setSceneNum(sceneNum);
+      algorithmScoreVo.setWeight(weight);
+      algorithmScoreVo.setScore(saveTwoDecimalPlaces(score));
+      algorithmScoreVo.setScoreRatio(saveTwoDecimalPlaces(Double.valueOf(scoreNum) / Double.valueOf(sceneNum) * 100));
+
+      algorithmScoreVoList.add(algorithmScoreVo);
+
+      // 其他操作
+      stringBuilder.append(firstTargetScorePo.getSublistName()).append("、");
+      totalSceneNum += sceneNum;
     }
-
-    private void createProjectId(SimulationAutomaticProjectPo po) {
-        Integer nowRq = getRq(null, 0);
-        po.setProjectDate(nowRq);
-        SimulationAutomaticProjectPo po1 = simulationAutomaticProjectMapper.selectLastProjectId(nowRq);
-        if (po1 == null) {
-            // 生成新id
-            po.setProjectNum(1);
-        } else {
-            po.setProjectNum(po1.getProjectNum() + 1);
-        }
-        po.setProjectId(po.getProjectDate() + "-" + po.getProjectNum());
-
+    // 汇总
+    AlgorithmScoreVo algorithmScoreVo = new AlgorithmScoreVo();
+    algorithmScoreVo.setProjectName("汇总");
+    algorithmScoreVo.setSceneNum(totalSceneNum);
+    // 指标权重总和默认是100%
+    algorithmScoreVo.setWeight("100");
+    algorithmScoreVo.setScore(saveTwoDecimalPlaces(totalScore));
+
+    totalScoreRatio = Double.valueOf(totalSceneScoreNum) / Double.valueOf(totalSceneNum) * 100;
+    // 汇总得分率计算方式修改
+    // algorithmScoreVo.setScoreRatio(saveTwoDecimalPlaces(totalScoreRatio));
+    algorithmScoreVo.setScoreRatio(NumberUtil.cut(totalScoreRatio, 2));
+    algorithmScoreVoList.add(algorithmScoreVo);
+    projectReportVo.setScoreRatio(saveTwoDecimalPlaces(totalScoreRatio));
+    projectReportVo.setAlgorithmScore(saveTwoDecimalPlaces(totalScore));
+    evaluationLevelReport = poParam.getEvaluationLevel();
+    if (DictConstants.EVALUATION_LEVEL_G.equals(evaluationLevelReport)) {
+      projectReportVo.setEvaluationLevel(DictConstants.EVALUATION_LEVEL_G_DESCRIPTION);
+      projectReportVo.setEvaluationGrade(DictConstants.EVALUATION_LEVEL_G_DESCRIPTION);
+    } else if (DictConstants.EVALUATION_LEVEL_A.equals(evaluationLevelReport)) {
+      projectReportVo.setEvaluationLevel(DictConstants.EVALUATION_LEVEL_A_DESCRIPTION);
+      projectReportVo.setEvaluationGrade(DictConstants.EVALUATION_LEVEL_A_DESCRIPTION);
+    } else if (DictConstants.EVALUATION_LEVEL_M.equals(evaluationLevelReport)) {
+      projectReportVo.setEvaluationLevel(DictConstants.EVALUATION_LEVEL_M_DESCRIPTION);
+      projectReportVo.setEvaluationGrade(DictConstants.EVALUATION_LEVEL_M_DESCRIPTION);
+    } else if (DictConstants.EVALUATION_LEVEL_P.equals(evaluationLevelReport)) {
+      projectReportVo.setEvaluationLevel(DictConstants.EVALUATION_LEVEL_P_DESCRIPTION);
+      projectReportVo.setEvaluationGrade(DictConstants.EVALUATION_LEVEL_P_DESCRIPTION);
     }
 
-    private Integer getRq(Date date, int index) {
-        return TimeUtil.getRq(date, index);
+    sceneNames = stringBuilder.substring(0, stringBuilder.lastIndexOf("、"));
+    projectReportVo.setAlgorithmEvaluation(algorithmBaseInfoVo.getAlgorithmName() + "经测试获得" + projectReportVo.getEvaluationLevel() + "级评价," + "(" + sceneNames + ")得分率达到了" + projectReportVo.getScoreRatio() + "%。");
+    projectReportVo.setAlgorithmScoreList(algorithmScoreVoList);
+    // 指标得分列表
+    Map<String, Object> stringObjectMap = selectScenePackageSubListAndSetScore(poParam.getScene(), poParam.getId());
+    projectReportVo.setSubListScoreLiTitle((List<Map>) stringObjectMap.get("headerList"));
+    projectReportVo.setSubListScoreLi((List<SubScListVo>) stringObjectMap.get("result"));
+
+    // 场景得分列表
+    Map<String, Object> maps = selectSceneScore2(poParam.getScene(), poParam.getId(), null, projectReportVo);
+    projectReportVo.setSceneScoreLiTitle((List<Map>) maps.get("headerList"));
+    projectReportVo.setSceneScoreLi((List<SceneScListVo>) maps.get("result"));
+
+    return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS, projectReportVo);
+  }
+
+  private AlgorithmPO getAlgorithmInfo(SimulationManualProjectPo po) {
+    AlgorithmPO algorithmBaseInfoVo = null;
+    String algorithmId = po.getAlgorithm();
+    String algorithmType = po.getAlgorithmType();
+    // 第三方算法平台
+    if ("3".equals(algorithmType)) {
+      String sort = "algorithmId-desc";
+      int page = 1;
+      int size = 1;// 全部
+
+      String urlParam = "&algorithmId" + algorithmId + "&page=" + page + "&size=" + size + "&sort=" + sort;
+      List<DropDownVo> otherAlgorithmInfo = getOtherAlgorithmInfo(urlParam);
+      if (StringUtil.isNotEmpty(otherAlgorithmInfo)) {
+        DropDownVo dropDownVo = otherAlgorithmInfo.get(0);
+        algorithmBaseInfoVo = new AlgorithmPO();
+        algorithmBaseInfoVo.setAlgorithmName(dropDownVo.getName());
+        algorithmBaseInfoVo.setDescription(dropDownVo.getDescription());
+      }
+
+    } else {
+      algorithmBaseInfoVo = simulationProjectMapper.selectAlgorithmById(algorithmId);
     }
+    return algorithmBaseInfoVo;
+  }
+
+  /**
+   * 获取添加工作时需要的下拉选项
+   * 0. 算法列表
+   * 1. 车辆列表
+   * 2. 场景列表
+   */
+  @Override
+  public ResponseBodyVO<List<DropDownTypeVo>> selectDropDownByType(SimulationManualProjectParam param) {
+    List<DropDownTypeVo> result = new ArrayList<>();
+    if (isEmpty(param.getDropDownType())) {
+      // 获取全部(算法,车辆,场景)
+      setAlgorithmDropDown(result, param.getAlgorithmType());
+      setVehicleDropDown(result, null);
+      setScenePackageDropDown(result);
+    } else if ("1".equals(param.getDropDownType())) {
+      setAlgorithmDropDown(result, param.getAlgorithmType());
+    } else if ("2".equals(param.getDropDownType())) {
+      setVehicleDropDown(result, null);
+    } else if ("3".equals(param.getDropDownType())) {
+      setScenePackageDropDown(result);
+    }
+    return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS, result);
+  }
+
+  /**
+   * 获取添加工作时需要的下拉选项
+   * 0. 算法列表
+   * 1. 车辆列表
+   * 2. 场景列表
+   */
+  @Override
+  public ResponseBodyVO<List<DropDownTypeNewVo>> selectDropDownByTypeNew(SimulationManualProjectParam param) {
+    List<DropDownTypeNewVo> result = new ArrayList<>();
+    if (isEmpty(param.getDropDownType())) {
+      // 获取全部(算法,车辆,场景)
+      setAlgorithmDropDownNew(result, param.getAlgorithmType());
+      setVehicleDropDownNew(result);
+      setScenePackageDropDownNew(result);
+    } else if ("1".equals(param.getDropDownType())) {
+      setAlgorithmDropDownNew(result, param.getAlgorithmType());
+    } else if ("2".equals(param.getDropDownType())) {
+      setVehicleDropDownNew(result);
+    } else if ("3".equals(param.getDropDownType())) {
+      setScenePackageDropDownNew(result);
+    }
+    return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS, result);
+  }
+
+  @Override
+  public ResponseBodyVO<ProjectTaskDetailsVo> selectProjectTaskById(SimulationManualProjectParam param) {
+    ProjectTaskDetailsVo resultVo = new ProjectTaskDetailsVo();
+    // 1 获取参数
+    Optional.ofNullable(param).orElseThrow(() -> new RuntimeException("参数不能为空。"));
+    Optional.ofNullable(param.getId()).orElseThrow(() -> new RuntimeException("项目 id 不能为空。"));
+    Optional.ofNullable(param.getTaskId()).orElseThrow(() -> new RuntimeException("任务 id 不能为空。"));
+    Optional.ofNullable(param.getProjectType()).orElseThrow(() -> new RuntimeException("项目类型不能为空。"));
+    String id = param.getId();
+    String taskId = param.getTaskId();
+    String projectType = param.getProjectType(); // 2
+    // 2 查询任务信息,手动项目和自动项目共用一个任务表
+    ProjectTaskParam projectTaskParam = new ProjectTaskParam();
+    projectTaskParam.setPId(id);
+    projectTaskParam.setId(taskId);
+    List<ManualProjectTaskPo> pos = simulationProjectTaskMapper.selectProjectTask(projectTaskParam);
+    if (CollectionUtil.isEmpty(pos)) {
+      return new ResponseBodyVO<>(ResponseBodyVO.Response.SERVER_FAILURE, "没有获取到任务信息。");
+    }
+    ManualProjectTaskPo po = pos.get(0);
+    resultVo.setTaskId(po.getId());
+    String sceneId = po.getSceneId();
+    String sceneType = po.getSceneType(); // 4
+    SceneBaseInfoVo sceneBaseInfoVo = getSceneNameAndOther(sceneId, sceneType); // ACC_2-5-1
+    resultVo.setSceneName(sceneBaseInfoVo.getCommonSceneName()); // ACC_2-5-1
+    resultVo.setRunStartTime(getRqStr(po.getRunStartTime(), 1)); // 2022-07-27 09:52:04
+    resultVo.setRunEndTime(getRqStr(po.getRunEndTime(), 1)); // 2022-07-27 09:53:14
+    resultVo.setRunState(po.getRunState()); // Completed
+    resultVo.setFinishState(po.getRunResult()); // Completed
+    resultVo.setSceneDescribe(""); // 场景描述设置为空
+    // -------------------------------- 获取任务得分详情 --------------------------------
+    SimulationManualProjectPo poParam = new SimulationManualProjectPo();
+    if (DictConstants.PROJECT_TYPE_MANUAL.equals(projectType)) {
+      SimulationManualProjectPo spo = simulationProjectMapper.selectProjectBaseById(param);
+      Optional.ofNullable(spo).orElseThrow(() -> new RuntimeException("没有获取到数据。"));
+      poParam = spo;
+    } else if (DictConstants.PROJECT_TYPE_AUTO_SUB.equals(projectType)) {
+      SimulationManualProjectVo spo = simulationAutomaticSubProjectMapper.selectProjectInfo(param);
+      Optional.ofNullable(spo).orElseThrow(() -> new RuntimeException("没有获取到数据。"));
+      BeanUtils.copyProperties(spo, poParam);
+    }
+    Map<String, Object> stringObjectMap = selectSceneScore(poParam.getScene(), poParam.getId(), taskId);
+    resultVo.setSceneScoreLiTitle((List<Map>) stringObjectMap.get("headerList"));
+    resultVo.setSceneScoreLi((List<SceneScListVo>) stringObjectMap.get("result"));
+    // 1.获取仿真结果文件
+    InputStream fileInputStream = null;
+    InputStreamReader inputStreamReader = null;
+    BufferedReader bufferedReader = null;
+    try {
+      // 2.解析仿真文件
+      // time
+      List<Double> time_list = new ArrayList<>();
+      // velocity
+      List<Double> velocity_list = new ArrayList<>();
+      List<Double> lateral_velocity_list = new ArrayList<>();// 横 时间
+      List<Double> longitudinal_velocity_list = new ArrayList<>();// 纵 速度
+      // acceleration
+      // List<Double> acceleration_list = new ArrayList<>();
+      // List<Double> acceleration_list_longitudinal = new ArrayList<>();
+      List<Double> lateral_acceleration_list = new ArrayList<>(); // 横向加速度
+      List<Double> longitudinal_acceleration_list = new ArrayList<>(); // 纵向加速度
+      // lane_offset
+      List<Double> lane_offset_list = new ArrayList<>();
+      /// TODO brake
+      List<Double> brake_list = new ArrayList<>();
+      // steeting_wheel
+      List<Double> steeting_wheel_list = new ArrayList<>();
+      /// TODO throttle
+      List<Double> throttle_list = new ArrayList<>();
+
+      List<Double> yawrate_list = new ArrayList<>();// 摆角速度
+
+      /*
+       * File file = new File("E:\\仿真云平台\\任务详情界面数据\\Ego(1).csv");
+       * fileInputStream = new FileInputStream(file);
+       * inputStreamReader = new InputStreamReader(fileInputStream,"utf-8");
+       */
+
+      MinioParameter minioParameter = new MinioParameter();
+      minioParameter.setObjectName(po.getRunResultFilePath() + "/Ego.csv");
+      // minioParameter.setObjectName("test/ego.csv");
+      Response download = fileDownService.download(minioParameter);
+      Response.Body body = download.body();
+      fileInputStream = body.asInputStream();
+
+      /*
+       * String path = "/temp" + StringUtil.getRandomCode();
+       * FileUtil.writeInputStreamToLocalFile(body.asInputStream(),path);
+       * file = new File(path);
+       * fileInputStream = new FileInputStream(file);
+       */
+
+      inputStreamReader = new InputStreamReader(fileInputStream, StandardCharsets.UTF_8);
+
+      bufferedReader = new BufferedReader(inputStreamReader);
+      String line;
+      int lineIndex = 0;
+      while ((line = bufferedReader.readLine()) != null) {
+        lineIndex++;
+        if (lineIndex == 1) {
+          continue;
+        }
+        String[] split = line.split(",");
+
+        //// 添加异常捕获,非正常数据默认为0
+        // 1时间 6横向速度 7纵向速度 8横向加速度 9纵向加速度 12steering_angle 13yawrate 27lane_center_offset
+        // 时间
+        try {
+          double aDouble = Double.parseDouble(split[1]);
+          if (Double.isNaN(aDouble)) {
+            time_list.add(0D);
+          } else {
+            time_list.add(Double.valueOf(split[1]));
+          }
+        } catch (NumberFormatException e) {
+          time_list.add(0D);
+        }
 
-    private String getRqStr(Date date, int index) {
-        SimpleDateFormat sdf = new SimpleDateFormat(dateFmtArr[index]);
-        if (date == null) {
-            return "";
+        // 横向速度
+        try {
+          double aDouble = Double.parseDouble(split[6]);
+          if (Double.isNaN(aDouble)) {
+            lateral_velocity_list.add(0D);
+          } else {
+            lateral_velocity_list.add(Double.valueOf(split[6]));
+          }
+        } catch (NumberFormatException e) {
+          lateral_velocity_list.add(0D);
         }
-        return sdf.format(date);
 
-    }
+        // 纵向速度
+        try {
+          double aDouble = Double.parseDouble(split[7]);
+          if (Double.isNaN(aDouble)) {
+            longitudinal_velocity_list.add(0D);
+          } else {
+            longitudinal_velocity_list.add(Double.valueOf(split[7]));
+          }
+        } catch (NumberFormatException e) {
+          longitudinal_velocity_list.add(0D);
+        }
 
-    private Date getDate(String dateFmt, int index) {
-        SimpleDateFormat sdf = new SimpleDateFormat(dateFmtArr[index]);
+        // 横向加速度
         try {
-            return sdf.parse(dateFmt);
-        } catch (ParseException e) {
-            return null;
+          double aDouble = Double.parseDouble(split[8]);
+          if (Double.isNaN(aDouble)) {
+            lateral_acceleration_list.add(0D);
+          } else {
+            lateral_acceleration_list.add(Double.valueOf(split[8]));
+          }
+        } catch (NumberFormatException e) {
+          lateral_acceleration_list.add(0D);
         }
-    }
 
-    private boolean isEmpty(String value) {
-        if (value == null) {
-            return true;
+        // 纵向加速度
+        try {
+          double aDouble = Double.parseDouble(split[9]);
+          if (Double.isNaN(aDouble)) {
+            longitudinal_acceleration_list.add(0D);
+          } else {
+            longitudinal_acceleration_list.add(Double.valueOf(split[9]));
+          }
+        } catch (NumberFormatException e) {
+          longitudinal_acceleration_list.add(0D);
         }
-        value = value.trim();
-        if (value.length() == 0) {
-            return true;
+
+        // steering_angle
+        try {
+          double aDouble = Double.parseDouble(split[12]);
+          if (Double.isNaN(aDouble)) {
+            steeting_wheel_list.add(0D);
+          } else {
+            steeting_wheel_list.add(Double.valueOf(split[12]));// steering_angle
+          }
+        } catch (NumberFormatException e) {
+          steeting_wheel_list.add(0D);
         }
-        return false;
-    }
 
-    private boolean isEmpty(List list) {
-        if (list == null || list.size() <= 0) {
-            return true;
+        try {
+          double aDouble = Double.parseDouble(split[13]);
+          if (Double.isNaN(aDouble)) {
+            yawrate_list.add(0D);
+          } else {
+            yawrate_list.add(Double.valueOf(split[13]));
+          }
+        } catch (NumberFormatException e) {
+          yawrate_list.add(0D);
         }
-        return false;
-    }
 
-    private void setPage(Integer pageNum, Integer pageSize) {
-        PageVO pageVO = new PageVO();
-        pageVO.setCurrentPage(pageNum);
-        pageVO.setPageSize(pageSize);
-        PageUtil.setPageInfo(pageVO);
+        try {
+          double aDouble = Double.parseDouble(split[27]);
+          if (Double.isNaN(aDouble)) {
+            lane_offset_list.add(0D);
+          } else {
+            lane_offset_list.add(Double.valueOf(split[27]));// lane_center_offset
+          }
+        } catch (NumberFormatException e) {
+          lane_offset_list.add(0D);
+        }
+
+        // brake_list.add(Double.valueOf(split[])); ///TODO 没有
+        // throttle_list.add(Double.valueOf(split[]));///TODO 没有
+
+      }
+      // 里程
+      double lc = 0.0;
+      for (int i = 0; i < time_list.size(); i++) {
+        if (i == 0) {
+          continue;
+        }
+        lc += (time_list.get(i) - time_list.get(i - 1)) * longitudinal_velocity_list.get(i - 1);
+
+      }
+
+      // 平均速度
+      Double pjsd = lc / time_list.get(time_list.size() - 1);
+      pjsd = saveTwoDecimalPlaces(pjsd, 4);
+
+      Double zdsd = Collections.max(longitudinal_velocity_list); // 最大速度
+      Double zxsd = Collections.min(longitudinal_velocity_list); // 最小速度
+      Double maxLateralAcceleration = Collections.max(lateral_acceleration_list); // 最大横向加速度
+      Double minLateralAcceleration = Collections.min(lateral_acceleration_list); // 最小横向加速度(最大横向减速度)
+      Double maxLongitudinalAcceleration = Collections.max(longitudinal_acceleration_list); // 最大纵向加速度
+      Double minLongitudinalAcceleration = Collections.min(longitudinal_acceleration_list); // 最小纵向加速度
+      Double zdbjsd = Collections.max(yawrate_list); // 最大摆角速度
+
+      // 自车速度方差
+      Double zcsdfc = 0D;
+      for (Double d : longitudinal_velocity_list) {
+        zcsdfc += Math.pow(d - pjsd, 2);
+      }
+      zcsdfc = zcsdfc / longitudinal_velocity_list.size();
+      zcsdfc = saveTwoDecimalPlaces(zcsdfc, 4);
+
+      // 自车横摆角速度均方根
+      Double zchbjsdjfg = 0D;
+      for (Double d : yawrate_list) {
+        // zchbjsdjfg += Math.pow(d-pjsd,2);
+        zchbjsdjfg += Math.pow(d, 2);
+      }
+      zchbjsdjfg = Math.sqrt(zchbjsdjfg / yawrate_list.size());
+      zchbjsdjfg = saveTwoDecimalPlaces(zchbjsdjfg, 4);
+
+      // for (int i = 0; i < lateral_acceleration.size(); i++) {
+      // Double aDouble = lateral_acceleration.get(i);
+      // Double aDouble1 = longitudinal_acceleration_list.get(i);
+      // double d = Math.pow(aDouble, 2) + Math.pow(aDouble1, 2);
+      // acceleration_list.add(Math.sqrt(d));
+      // }
+
+      for (int i = 0; i < lateral_velocity_list.size(); i++) {
+        Double aDouble = lateral_velocity_list.get(i);
+        Double aDouble1 = longitudinal_velocity_list.get(i);
+        double d = Math.pow(aDouble, 2) + Math.pow(aDouble1, 2);
+        velocity_list.add(Math.sqrt(d) * 3.6);
+      }
+
+      // 获取视频预览路径
+      List<String> list1 = new ArrayList<>();
+      String runResultFilePath = po.getRunResultFilePath();
+      MinioParameter minioParameter1 = new MinioParameter();
+      minioParameter1.setObjectName(runResultFilePath);
+      ResponseBodyVO<List<String>> list = fileDownService.list(minioParameter1);
+      List<String> info = list.getInfo();
+      for (String s : info) {
+        String substring = s.substring(s.lastIndexOf(".") + 1);
+        if ("mp4".equals(substring)) {
+          // mp4视频文件
+          minioParameter1.setObjectName(s);
+          ResponseBodyVO<String> preview = fileDownService.getPreviewUrl(minioParameter1);
+          list1.add(preview.getInfo());
+        }
+
+      }
+
+      // 任务详情信息
+      resultVo.setMileage(Double.toString(lc));
+      resultVo.setAverageVelocity(saveTwoDecimalPlaces(pjsd * 3.6, 4).toString());
+      resultVo.setMaximunSpeed(zdsd.toString()); // 最大速度
+      resultVo.setMinimunVelocity(zxsd.toString()); // 最小速度
+      resultVo.setMaximumAcceleration(maxLateralAcceleration.toString()); // 最大横向加速度
+      resultVo.setMaximumDeceleration(minLateralAcceleration.toString()); // 最大横向减速度
+      resultVo.setMaxLongitudinalAcceleration(maxLongitudinalAcceleration.toString()); // 最大纵向加速度
+      resultVo.setMinLongitudinalAcceleration(minLongitudinalAcceleration.toString()); // 最小纵向加速度
+      resultVo.setMaximumSwingSpeed(zdbjsd.toString());
+      resultVo.setSpeedVariance(zcsdfc);
+      // resultVo.setSpeedComfortLevel(po.getSpeedComfortLevel());
+
+      resultVo.setSwingSpeedMeanSquareRoot(zchbjsdjfg);
+      // resultVo.setSwingComfortLevel(po.getSwingComfortLevel());
+      resultVo.setVideoUrl(list1);
+
+      HashMap<String, List<Double>> CurveData = new HashMap<>();
+      CurveData.put("time", time_list);
+      CurveData.put("acceleration", lateral_acceleration_list);
+      CurveData.put("acceleration_longitudinal", longitudinal_acceleration_list);
+      CurveData.put("lane_offset", lane_offset_list);
+      CurveData.put("brake", brake_list);
+      CurveData.put("steeting", steeting_wheel_list);
+      CurveData.put("throttle", throttle_list);
+      CurveData.put("yaw_rate", yawrate_list);
+      CurveData.put("velocity", velocity_list); // 速度变化曲线
+      resultVo.setCurveData(CurveData);
+
+    } catch (Exception e) {
+      e.printStackTrace();
+
+    } finally {
+      try {
+        if (fileInputStream != null) {
+          fileInputStream.close();
+        }
+        if (inputStreamReader != null) {
+          inputStreamReader.close();
+        }
+        if (bufferedReader != null) {
+          bufferedReader.close();
+        }
+      } catch (IOException e) {
+        e.printStackTrace();
+      }
     }
-
-    private Double saveTwoDecimalPlaces(Double d) {
-        if (d == null) {
-            return null;
-        }
-        return new BigDecimal(d.toString()).setScale(2, RoundingMode.HALF_UP).doubleValue();
+    return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS, resultVo);
+  }
+
+  @Override
+  public String getDictName(String type, String code) {
+    Map<String, String> stringStringMap = getDictByType(type);
+    if (stringStringMap != null && stringStringMap.size() > 0) {
+      return stringStringMap.get(code);
     }
-
-    private Double saveTwoDecimalPlaces(Double d, int num) {
-        if (d == null) {
-            return null;
-        }
-        return new BigDecimal(d.toString()).setScale(num, RoundingMode.HALF_UP).doubleValue();
+    return "";
+  }
+
+  private Map<String, String> getDictByType(String type) {
+    DictParam dictParam = new DictParam();
+    dictParam.setDictTypes(type);
+    Map<String, Map<String, String>> dictMapsByTypes = dictService.getDictMapsByTypes(dictParam);
+    Map<String, String> stringStringMap = dictMapsByTypes.get(type);
+    if (stringStringMap != null && stringStringMap.size() > 0) {
+      return stringStringMap;
     }
-
-    /**
-     * 设置场景基本字段
-     */
-    private void setUpSceneInfo(ManualProjectTaskVo vo) {
-        String sceneType = vo.getSceneType();
-        String sceneId = vo.getSceneId();
-        SceneBaseInfoVo sceneBaseInfoVo;
-        if (DictConstants.SCENE_NATURAL.equals(sceneType)) {
-            // 自然驾驶
-            sceneBaseInfoVo = simulationProjectMapper.selectSceneNatural(sceneId);
-            if (sceneBaseInfoVo != null) {
-                vo.setSceneName(sceneBaseInfoVo.getNaturalName());
-            }
-        } else if (DictConstants.SCENE_STANDARD.equals(sceneType)) {
-            // 标准法规
-            sceneBaseInfoVo = simulationProjectMapper.selectSceneStandardsRegulations(sceneId);
-            if (sceneBaseInfoVo != null) {
-                vo.setSceneName(sceneBaseInfoVo.getSceneName());
-            }
-        } else if (DictConstants.SCENE_ACCIDENT.equals(sceneType)) {
-            // 交通事故
-            sceneBaseInfoVo = simulationProjectMapper.selectSceneAccidentById(sceneId);
-            if (sceneBaseInfoVo != null) {
-                vo.setSceneName(sceneBaseInfoVo.getSceneName());
-            }
-        } else if (DictConstants.SCENE_GENERAL.equals(sceneType)) {
-            /// TODO 泛化场景暂不支持
-            sceneBaseInfoVo = simulationProjectMapper.selectSceneGeneralDataById(sceneId);
-            if (sceneBaseInfoVo != null) {
-                vo.setSceneName(sceneBaseInfoVo.getSceneName());
-            }
-
-        }
+    return null;
+
+  }
+
+  @Override
+  @SneakyThrows
+  public ResponseBodyVO<String> analysisVehicleCoord() {
+    analysisCsvFile("E:\\仿真云平台\\三维还原视频说明\\360ogt.csv", new int[]{6, 7, 9});
+    return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS);
+
+  }
+
+  @Override
+  public ResponseBodyVO<PageInfo<ManualProjectTaskVo>> selectProjectTaskList(SimulationManualProjectParam param) {
+    // 查询任务信息
+    ProjectTaskParam projectTaskParam = new ProjectTaskParam();
+    projectTaskParam.setPId(param.getId());
+    setPage(param.getCurrentPage() == null ? 1 : param.getCurrentPage(), param.getPageSize() == null ? 10 : param.getPageSize());
+    List<ManualProjectTaskVo> tasks = simulationProjectTaskMapper.selectProjectTaskByProjectId(projectTaskParam);
+    tasks.forEach(task -> {
+      if (StateConstant.Aborted.getEnglish().equals(task.getRunState())) {
+        task.setRunState(StateConstant.Aborted.getChinese());
+      }
+      if (StateConstant.PendingAnalysis.getEnglish().equals(task.getRunState())) {
+        task.setRunState(StateConstant.PendingAnalysis.getChinese());
+      }
+      if (StateConstant.Running.getEnglish().equals(task.getRunState())) {
+        task.setRunState(StateConstant.Running.getChinese());
+      }
+      if (StateConstant.Analysing.getEnglish().equals(task.getRunState())) {
+        task.setRunState(StateConstant.Analysing.getChinese());
+      }
+      if (StateConstant.Completed.getEnglish().equals(task.getRunState())) {
+        task.setRunState(StateConstant.Completed.getChinese());
+      }
+      if (StateConstant.Terminated.getEnglish().equals(task.getRunState())) {
+        task.setRunState(StateConstant.Terminated.getChinese());
+      }
+      if (StateConstant.Terminating.getEnglish().equals(task.getRunState())) {
+        task.setRunState(StateConstant.Terminating.getChinese());
+      }
+      if (StateConstant.Pending.getEnglish().equals(task.getRunState())) {
+        task.setRunState(StateConstant.Pending.getChinese());
+      }
+      if (StateConstant.Success.getEnglish().equals(task.getRunResult())) {
+        task.setRunResult(StateConstant.Success.getChinese());
+      }
+      if (StateConstant.Failed.getEnglish().equals(task.getRunResult())) {
+        task.setRunResult(StateConstant.Failed.getChinese());
+      }
+    });
+
+    PageInfo<ManualProjectTaskVo> pageInfo = new PageInfo<>(tasks);
+
+    if (pageInfo.getList() != null) {
+      for (ManualProjectTaskVo task : pageInfo.getList()) {
+        task.setRunStartTimeFmt(getRqStr(task.getRunStartTime(), 1));
+        task.setRunEndTimeFmt(getRqStr(task.getRunEndTime(), 1));
+        setUpSceneInfo(task);
+
+      }
     }
+    return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS, pageInfo);
+  }
+
+  private void analysisCsvFile(String filePath, int[] analysisFields) throws Exception {
+
+    File file = new File(filePath);
+    InputStream fileInputStream = Files.newInputStream(file.toPath());
+    InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream, "utf-8");
+    BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
+    String line;
+    while ((line = bufferedReader.readLine()) != null) {
+      String[] split = line.split(",");
+      for (int fs : analysisFields) {
+        System.out.println(split[fs]);
+      }
 
-    private ManualProjectTaskVo convertManualProjectTaskPoToVo(ManualProjectTaskPo po) {
-        ManualProjectTaskVo manualProjectTaskVo = new ManualProjectTaskVo();
-        manualProjectTaskVo.setId(po.getId());
-        manualProjectTaskVo.setPId(po.getPId());
-        manualProjectTaskVo.setSceneId(po.getSceneId());
-        // manualProjectTaskVo.setSceneName(po.getSceneName());
-        manualProjectTaskVo.setSceneType(po.getSceneType());
-        manualProjectTaskVo.setRunStartTimeFmt(getRqStr(po.getRunStartTime(), 2));
-        manualProjectTaskVo.setRunEndTimeFmt(getRqStr(po.getRunEndTime(), 2));
-        manualProjectTaskVo.setRunState(po.getRunState());
-        manualProjectTaskVo.setRunResult(po.getRunResult());
-        return manualProjectTaskVo;
     }
+  }
+
+  /**
+   * 根据场景id和场景类型获取场景名
+   *
+   * @return 场景名称
+   */
+  private SceneBaseInfoVo getSceneNameAndOther(String sceneId, String sceneType) {
+    SceneBaseInfoVo resultVo = new SceneBaseInfoVo();
+    if (DictConstants.SCENE_NATURAL.equals(sceneType)) {
+      SceneBaseInfoVo sceneBaseInfoVo = simulationProjectMapper.selectSceneNatural(sceneId);
+      if (sceneBaseInfoVo != null) {
+        resultVo.setCommonSceneName(sceneBaseInfoVo.getNaturalName());
+      }
+    } else if (DictConstants.SCENE_STANDARD.equals(sceneType)) {
+      SceneBaseInfoVo sceneBaseInfoVo = simulationProjectMapper.selectSceneStandardsRegulations(sceneId);
+      if (sceneBaseInfoVo != null) {
+        resultVo.setCommonSceneName(sceneBaseInfoVo.getSceneName());
+      }
+    } else if (DictConstants.SCENE_ACCIDENT.equals(sceneType)) {
+      SceneBaseInfoVo sceneBaseInfoVo = simulationProjectMapper.selectSceneAccidentById(sceneId);
+      if (sceneBaseInfoVo != null) {
+        resultVo.setCommonSceneName(sceneBaseInfoVo.getSceneName());
+      }
+    } else if (DictConstants.SCENE_GENERAL.equals(sceneType)) {
+      SceneBaseInfoVo sceneBaseInfoVo = simulationProjectMapper.selectSceneGeneralDataById(sceneId);
+      if (sceneBaseInfoVo != null) {
+        resultVo.setCommonSceneName(sceneBaseInfoVo.getSceneName());
+      }
+    }
+    return resultVo;
+  }
+
+  /**
+   * 查询算法下拉列表
+   *
+   * @param result
+   * @param algorithmType 算法类型
+   */
+  private void setAlgorithmDropDown(List<DropDownTypeVo> result, String algorithmType) {
+    List<DropDownVo> algorithmList = new ArrayList<>();
+    if (DictConstants.FILE.equals(algorithmType) || DictConstants.GIT.equals(algorithmType)) {
+      AlgorithmPO algorithmPO = new AlgorithmPO();
+      algorithmPO.setCreateUserId(AuthUtil.getCurrentUserId()); // 获取当前用户 id
+      if (StringUtil.isEmpty(algorithmType)) {
+        algorithmPO.setUploadMode("1");
+      } else {
+        algorithmPO.setUploadMode(algorithmType);
+      }
+      List<AlgorithmPO> algorithmBaseInfoVo = simulationProjectMapper.selectAlgorithmBaseInfoById(algorithmPO);
+
+      for (AlgorithmPO v : algorithmBaseInfoVo) {
+        DropDownVo dropDownVo = new DropDownVo();
+        dropDownVo.setId(v.getId());
+        dropDownVo.setName(v.getAlgorithmName());
+        dropDownVo.setDescription(v.getDescription());
+        dropDownVo.setShare(v.getShare());
+        algorithmList.add(dropDownVo);
+      }
+
+    } else if (DictConstants.PLATFORM.equals(algorithmType)) {
+      // 第三方算法平台获取(索为)
+      String sort = "algorithmId-desc";
+      int page = 1;
+      int size = 999;// 全部
+      String urlParam = "&page=" + page + "&size=" + size + "&sort=" + sort;
+      algorithmList = getOtherAlgorithmInfo(urlParam);
 
-    /**
-     * 级联获取场景指标得分数据
-     *
-     * @param parentVoList   首次传null
-     * @param isRoot         首次传true
-     * @param scenePackageId 场景包id
-     * @param pId            项目表id,用于统计得分使用
-     * @param level          指标级别
-     * @return
-     */
-    private List<ScenePackageSubListVO> selectScenePackageSubListTreeAndSetScore(
-            List<ScenePackageSubListVO> parentVoList,
-            boolean isRoot, String scenePackageId, String pId, Integer level) {
-
-        if (isRoot) {
-            // 查找一级节点
-            parentVoList = simulationProjectMapper.selectSubSceneByPid(scenePackageId);
-            if (!isEmpty(parentVoList)) {
-                selectScenePackageSubListTreeAndSetScore(parentVoList, false, null, pId, level);
-            }
-
-        } else {
-
-            // 获取子节点集合
-            for (ScenePackageSubListVO pvo : parentVoList) {
-
-                pvo.setLevel(level);
-
-                // 二级指标获取总分
-                if (level == 2) {
-                    setFirstTargetScore(pvo, pId);
-                }
-
-                List<ScenePackageSubListVO> cvoList = simulationProjectMapper.selectSubSceneByPid(pvo.getSublistId());
-                if (!isEmpty(cvoList)) {
-                    // 存入父节点集合中
-                    pvo.setChildScenePackageSubListVOList(cvoList);
-                    // 继续查找下一节点
-                    selectScenePackageSubListTreeAndSetScore(cvoList, false, null, pId, level + 1);
-                } else {
-
-                    // 没有子节点;最后一级,获取指标得分,指标得分说明,和指标下场景得分
-                    setScore(pvo, pId);
-                }
-
-            }
-        }
+    }
+    DropDownTypeVo algorithmDropDown = new DropDownTypeVo();
+    algorithmDropDown.setDropDownList(algorithmList);
+    algorithmDropDown.setType("1");
+    result.add(algorithmDropDown);
+
+  }
+
+  /**
+   * 获取第三方算法平台的算法信息
+   *
+   * @return 第三方算法平台的算法信息
+   */
+  private List<DropDownVo> getOtherAlgorithmInfo(String query) {
+
+    List<DropDownVo> algorithmList = new ArrayList<>();
+
+    ResponseBodyVO algorithmBody = algoPlatformService.getAlgorithmList(query);
+
+    // 解析数据
+    Map jsonMap = JsonUtil.jsonToMap((String) algorithmBody.getInfo());
+    Map<String, Object> dataMap = (Map<String, Object>) jsonMap.get("data");
+    List<Map<String, String>> contentList = (List<Map<String, String>>) dataMap.get("content");
+    Integer totalElements = (Integer) dataMap.get("totalElements");
+    if (totalElements > 0) {
+      for (Map<String, String> content : contentList) {
+        DropDownVo dropDownVo = new DropDownVo();
+        dropDownVo.setId(content.get("algorithmId"));
+        dropDownVo.setName(content.get("algorithmName"));
+        dropDownVo.setDescription(content.get("description"));
+        algorithmList.add(dropDownVo);
+      }
+    }
+    return algorithmList;
 
-        return parentVoList;
-    }
-
-    private Map<String, Object> selectSceneScore(String scenePackageId, String projectId, String taskId) {
-
-        // 1 查询指定项目的所有指标得分结果
-        SimulationManualProjectParam query = new SimulationManualProjectParam();
-        query.setId(projectId);
-        query.setPackageId(scenePackageId);
-        List<SublistScoreVo> pos = simulationProjectMapper.selectSubScore2(query);
-        // 2 查询指定项目的所有任务得分结果
-        ProjectTaskParam param = new ProjectTaskParam();
-        param.setPId(projectId);
-        if (!isEmpty(taskId)) {
-            param.setTaskId(taskId);
-        }
-        List<ManualProjectTaskVo> taskList = simulationProjectTaskMapper.selectProjectTaskByProjectId(param); // 手动运行项目和自动运行项目使用同一个任务表
-
-        // 2 拼接场景得分信息
-        List<SublistScoreVo> lastSubList = new ArrayList<>();
-        for (SublistScoreVo po : pos) {
-            if (ObjectUtil.isNotNull(po.getPackageAndRules())) {
-                // 获取场景得分信息
-                for (ManualProjectTaskVo task : taskList)
-                    if (task.getLastTargerId().equals(po.getId())) {
-                        SublistScoreVo sublistScoreVo = new SublistScoreVo();
-                        BeanUtils.copyProperties(po, sublistScoreVo);
-                        sublistScoreVo.setRunResult(task.getRunResult());
-                        sublistScoreVo.setSceneScore(saveTwoDecimalPlaces(task.getScore())); // 得分
-                        sublistScoreVo.setTargetEvaluate(task.getTargetEvaluate());// 指标评价
-                        String sceneType = task.getSceneType();
-                        String sceneId = task.getSceneId();
-                        String sceneName = "";
-                        if (DictConstants.SCENE_NATURAL.equals(sceneType)) {
-                            sublistScoreVo.setSceneType("自然驾驶");
-                            SceneBaseInfoVo sceneBaseInfoVo = simulationProjectMapper.selectSceneNatural(sceneId);
-                            sceneName = sceneBaseInfoVo.getNaturalName();
-                        } else if (DictConstants.SCENE_STANDARD.equals(sceneType)) {
-                            sublistScoreVo.setSceneType("标准法规");
-                            SceneBaseInfoVo sceneBaseInfoVo = simulationProjectMapper
-                                    .selectSceneStandardsRegulations(sceneId);
-                            sceneName = sceneBaseInfoVo.getSceneName();
-                        } else if (DictConstants.SCENE_ACCIDENT.equals(sceneType)) {
-                            sublistScoreVo.setSceneType("交通事故");
-                            SceneBaseInfoVo sceneBaseInfoVo = simulationProjectMapper.selectSceneAccidentById(sceneId);
-                            sceneName = sceneBaseInfoVo.getSceneName();
-                        } else if (DictConstants.SCENE_GENERAL.equals(sceneType)) {
-                            sublistScoreVo.setSceneType("泛化");
-                            SceneBaseInfoVo sceneBaseInfoVo = simulationProjectMapper
-                                    .selectSceneGeneralDataById(sceneId);
-                            sceneName = sceneBaseInfoVo.getSceneName();
-                        }
-                        sublistScoreVo.setReturnSceneId(sceneName); // 显示场景名称
-                        lastSubList.add(sublistScoreVo);
-                    }
-            }
-        }
-        int size = 0;
-        List<List<String>> result = new ArrayList<>();
-        // 新增返回状态
-        ArrayList<String> runStateList = new ArrayList<>();
-        // 末级指标
-        for (SublistScoreVo sp : lastSubList) {
-            setParentSub(sp, null, pos);
-            String sublistName = sp.getSublistName();
-            // 失败的任务没有数据,需要校验
-            Double sceneScore = sp.getSceneScore();
-            if (sceneScore == null) {
-                sceneScore = 0D;
-            }
-            String targetEvaluate = sp.getTargetEvaluate();
-            if (targetEvaluate == null) {
-                targetEvaluate = "";
-            }
-            /*
-             * sublistName +=
-             * ProjectConstants.SEPARATOR+sp.getReturnSceneId()+ProjectConstants.SEPARATOR+
-             * sp.getSceneType()+ProjectConstants.SEPARATOR+
-             * sp.getSceneScore()+ProjectConstants.SEPARATOR+sp.getTargetEvaluate()+
-             * ProjectConstants.SEPARATOR+sp.getScoreExplain();
-             */
-            // 测试得分,指标评价,得分说明 --处理
-            if (isEmpty(targetEvaluate) || isEmpty(sp.getScoreExplain())) {
-                sublistName += ProjectConstants.SEPARATOR
-                        + sp.getReturnSceneId() + ProjectConstants.SEPARATOR
-                        + sp.getSceneType() + ProjectConstants.SEPARATOR
-                        + "--" + ProjectConstants.SEPARATOR
-                        + "--" + ProjectConstants.SEPARATOR
-                        + "--";
-            } else {
-                sublistName += ProjectConstants.SEPARATOR
-                        + sp.getReturnSceneId() + ProjectConstants.SEPARATOR
-                        + sp.getSceneType() + ProjectConstants.SEPARATOR
-                        + sceneScore + ProjectConstants.SEPARATOR
-                        + targetEvaluate + ProjectConstants.SEPARATOR
-                        + sp.getScoreExplain();
-            }
-            String[] split = sublistName.split(ProjectConstants.SEPARATOR);
-            List<String> strings = new LinkedList<>(Arrays.asList(split));
-            if (size < strings.size()) {
-                size = strings.size();
-            }
-            result.add(strings);
-            runStateList.add(sp.getRunResult());
-        }
-        List<SceneScListVo> objects = new ArrayList<>();
-        // 结果补全
-        int r = 0;
-        for (List<String> list : result) {
-            int start = list.size() - 5;
-            SceneScListVo sceneScListVo = new SceneScListVo();
-            for (int i = 0; i < start; i++) {
-                if (0 == i) {
-                    sceneScListVo.setSublistName1(list.get(i));
-                } else if (1 == i) {
-                    sceneScListVo.setSublistName2(list.get(i));
-                } else if (2 == i) {
-                    sceneScListVo.setSublistName3(list.get(i));
-                } else if (3 == i) {
-                    sceneScListVo.setSublistName4(list.get(i));
-                } else if (4 == i) {
-                    sceneScListVo.setSublistName5(list.get(i));
-                } else if (5 == i) {
-                    sceneScListVo.setSublistName6(list.get(i));
-                }
-            }
-            sceneScListVo.setSceneId(list.get(start));
-            sceneScListVo.setSceneIdType(list.get(start + 1));
-            sceneScListVo.setSceneScore(list.get(start + 2));
-            sceneScListVo.setTargetEvaluate(list.get(start + 3));
-            sceneScListVo.setScoreExplain(list.get(start + 4));
-            sceneScListVo.setRunState(runStateList.get(r));
-            objects.add(sceneScListVo);
-            r++;
-        }
-        List<Map<Object, Object>> headerList = new ArrayList<>();
-        int maxIndex = size - 5;
-        for (int i = 0; i < maxIndex; i++) {
-            addHeaders(i, headerList);
-        }
-        headerList.add(ImmutableMap.builder().put("label", "场景名称").put("prop", "sceneId").build());
-        headerList.add(ImmutableMap.builder().put("label", "场景类型").put("prop", "sceneIdType").build());
-        headerList.add(ImmutableMap.builder().put("label", "测试得分").put("prop", "sceneScore").build());
-        headerList.add(ImmutableMap.builder().put("label", "指标评价").put("prop", "targetEvaluate").build());
-        headerList.add(ImmutableMap.builder().put("label", "得分说明").put("prop", "scoreExplain").build());
-        HashMap<String, Object> hashMap = new HashMap<>();
-        hashMap.put("headerList", headerList);
-        hashMap.put("result", objects);
-        return hashMap;
-    }
-
-    private Map<String, Object> selectSceneScore2(String scenePackageId, String projectId, String taskId,
-            ProjectReportVo projectReportVo) {
-
-        // 1 查询指定项目的所有指标得分结果
-        SimulationManualProjectParam query = new SimulationManualProjectParam();
-        query.setId(projectId);
-        query.setPackageId(scenePackageId);
-        List<SublistScoreVo> pos = simulationProjectMapper.selectSubScore2(query);
-        // 2 查询指定项目的所有任务得分结果
-        ProjectTaskParam param = new ProjectTaskParam();
-        param.setPId(projectId);
-        if (!isEmpty(taskId)) {
-            param.setTaskId(taskId);
-        }
-        List<ManualProjectTaskVo> taskList = simulationProjectTaskMapper.selectProjectTaskByProjectId(param); // 手动运行项目和自动运行项目使用同一个任务表
-
-        // 2 拼接场景得分信息
-        List<SublistScoreVo> lastSubList = new ArrayList<>();
-        for (SublistScoreVo po : pos) {
-            if (ObjectUtil.isNotNull(po.getPackageAndRules())) {
-                // 获取场景得分信息
-                for (ManualProjectTaskVo task : taskList)
-                    if (task.getLastTargerId().equals(po.getId())) {
-                        SublistScoreVo sublistScoreVo = new SublistScoreVo();
-                        BeanUtils.copyProperties(po, sublistScoreVo);
-                        sublistScoreVo.setRunResult(task.getRunResult());
-                        sublistScoreVo.setSceneScore(saveTwoDecimalPlaces(task.getScore())); // 得分
-                        sublistScoreVo.setTargetEvaluate(task.getTargetEvaluate());// 指标评价
-                        String sceneType = task.getSceneType();
-                        String sceneId = task.getSceneId();
-                        String sceneName = "";
-                        if (DictConstants.SCENE_NATURAL.equals(sceneType)) {
-                            sublistScoreVo.setSceneType("自然驾驶");
-                            SceneBaseInfoVo sceneBaseInfoVo = simulationProjectMapper.selectSceneNatural(sceneId);
-                            sceneName = sceneBaseInfoVo.getNaturalName();
-                        } else if (DictConstants.SCENE_STANDARD.equals(sceneType)) {
-                            sublistScoreVo.setSceneType("标准法规");
-                            SceneBaseInfoVo sceneBaseInfoVo = simulationProjectMapper
-                                    .selectSceneStandardsRegulations(sceneId);
-                            sceneName = sceneBaseInfoVo.getSceneName();
-                        } else if (DictConstants.SCENE_ACCIDENT.equals(sceneType)) {
-                            sublistScoreVo.setSceneType("交通事故");
-                            SceneBaseInfoVo sceneBaseInfoVo = simulationProjectMapper.selectSceneAccidentById(sceneId);
-                            sceneName = sceneBaseInfoVo.getSceneName();
-                        } else if (DictConstants.SCENE_GENERAL.equals(sceneType)) {
-                            sublistScoreVo.setSceneType("泛化");
-                            SceneBaseInfoVo sceneBaseInfoVo = simulationProjectMapper
-                                    .selectSceneGeneralDataById(sceneId);
-                            sceneName = sceneBaseInfoVo.getSceneName();
-                        }
-                        sublistScoreVo.setReturnSceneId(sceneName); // 显示场景名称
-                        lastSubList.add(sublistScoreVo);
-                    }
-            }
-        }
-        int size = 0;
-        List<List<String>> result = new ArrayList<>();
-        // 新增返回状态
-        ArrayList<String> runStateList = new ArrayList<>();
-        // 末级指标
-        for (SublistScoreVo sp : lastSubList) {
-            setParentSub(sp, null, pos);
-            String sublistName = sp.getSublistName();
-            // 失败的任务没有数据,需要校验
-            Double sceneScore = sp.getSceneScore();
-            if (sceneScore == null) {
-                sceneScore = 0D;
-            }
-            String targetEvaluate = sp.getTargetEvaluate();
-            if (targetEvaluate == null) {
-                targetEvaluate = "";
-            }
-            /*
-             * sublistName +=
-             * ProjectConstants.SEPARATOR+sp.getReturnSceneId()+ProjectConstants.SEPARATOR+
-             * sp.getSceneType()+ProjectConstants.SEPARATOR+
-             * sp.getSceneScore()+ProjectConstants.SEPARATOR+sp.getTargetEvaluate()+
-             * ProjectConstants.SEPARATOR+sp.getScoreExplain();
-             */
-            // 测试得分,指标评价,得分说明 --处理
-            if (isEmpty(targetEvaluate) || isEmpty(sp.getScoreExplain())) {
-                sublistName += ProjectConstants.SEPARATOR
-                        + sp.getReturnSceneId() + ProjectConstants.SEPARATOR
-                        + sp.getSceneType() + ProjectConstants.SEPARATOR
-                        + "--" + ProjectConstants.SEPARATOR
-                        + "--" + ProjectConstants.SEPARATOR
-                        + "--";
-            } else {
-                sublistName += ProjectConstants.SEPARATOR
-                        + sp.getReturnSceneId() + ProjectConstants.SEPARATOR
-                        + sp.getSceneType() + ProjectConstants.SEPARATOR
-                        + sceneScore + ProjectConstants.SEPARATOR
-                        + targetEvaluate + ProjectConstants.SEPARATOR
-                        + sp.getScoreExplain();
-            }
-            String[] split = sublistName.split(ProjectConstants.SEPARATOR);
-            List<String> strings = new LinkedList<>(Arrays.asList(split));
-            if (size < strings.size()) {
-                size = strings.size();
-            }
-            result.add(strings);
-            runStateList.add(sp.getRunResult());
-        }
-        List<SceneScListVo> objects = new ArrayList<>();
-        // 结果补全
-        int r = 0;
-        for (List<String> list : result) {
-            int start = list.size() - 5;
-            SceneScListVo sceneScListVo = new SceneScListVo();
-            for (int i = 0; i < start; i++) {
-                if (0 == i) {
-                    String s0 = list.get(i);
-                    if (StringUtil.isNotEmpty(s0)) {
-                        sceneScListVo.setEachMaxIndex((i + 1) + "");
-                    }
-                    sceneScListVo.setSublistName1(s0);
-                } else if (1 == i) {
-                    String s1 = list.get(i);
-                    if (StringUtil.isNotEmpty(s1)) {
-                        sceneScListVo.setEachMaxIndex((i + 1) + "");
-                    }
-                    sceneScListVo.setSublistName2(list.get(i));
-                } else if (2 == i) {
-                    String s2 = list.get(i);
-                    if (StringUtil.isNotEmpty(s2)) {
-                        sceneScListVo.setEachMaxIndex((i + 1) + "");
-                    }
-                    sceneScListVo.setSublistName3(list.get(i));
-                } else if (3 == i) {
-                    String s3 = list.get(i);
-                    if (StringUtil.isNotEmpty(s3)) {
-                        sceneScListVo.setEachMaxIndex((i + 1) + "");
-                    }
-                    sceneScListVo.setSublistName4(list.get(i));
-                } else if (4 == i) {
-                    String s4 = list.get(i);
-                    if (StringUtil.isNotEmpty(s4)) {
-                        sceneScListVo.setEachMaxIndex((i + 1) + "");
-                    }
-                    sceneScListVo.setSublistName5(list.get(i));
-                } else if (5 == i) {
-                    String s5 = list.get(i);
-                    if (StringUtil.isNotEmpty(s5)) {
-                        sceneScListVo.setEachMaxIndex((i + 1) + "");
-                    }
-                    sceneScListVo.setSublistName6(list.get(i));
-                }
-            }
-            sceneScListVo.setSceneId(list.get(start));
-            sceneScListVo.setSceneIdType(list.get(start + 1));
-            sceneScListVo.setSceneScore(list.get(start + 2));
-            sceneScListVo.setTargetEvaluate(list.get(start + 3));
-            sceneScListVo.setScoreExplain(list.get(start + 4));
-            sceneScListVo.setRunState(runStateList.get(r));
-            objects.add(sceneScListVo);
-            r++;
-        }
-        List<Map<Object, Object>> headerList = new ArrayList<>();
-        int maxIndex = size - 5;
-        projectReportVo.setMaxIndex(maxIndex);
-        for (int i = 0; i < maxIndex; i++) {
-            addHeaders(i, headerList);
-        }
-        headerList.add(ImmutableMap.builder().put("label", "场景名称").put("prop", "sceneId").build());
-        headerList.add(ImmutableMap.builder().put("label", "场景类型").put("prop", "sceneIdType").build());
-        headerList.add(ImmutableMap.builder().put("label", "测试得分").put("prop", "sceneScore").build());
-        headerList.add(ImmutableMap.builder().put("label", "指标评价").put("prop", "targetEvaluate").build());
-        headerList.add(ImmutableMap.builder().put("label", "得分说明").put("prop", "scoreExplain").build());
-        HashMap<String, Object> hashMap = new HashMap<>();
-        hashMap.put("headerList", headerList);
-        hashMap.put("result", objects);
-        return hashMap;
-    }
-
-    /**
-     * @param po       末级指标
-     * @param parentPo 上级指标
-     * @param pos      所有指标
-     */
-    private void setParentSub(SublistScoreVo po, SublistScoreVo parentPo, List<SublistScoreVo> pos) {
-        if (parentPo == null) {
-            for (SublistScoreVo p : pos) {
-                setSc(po, p, po, pos);
-            }
+  }
 
-        } else {
-            for (SublistScoreVo p : pos) {
-                setSc(parentPo, p, po, pos);
-            }
-        }
+  private void setVehicleDropDown(List<DropDownTypeVo> result, String ConfigId) {
+    ConfigPO configPO = new ConfigPO();
+    if (StringUtil.isNotEmpty(ConfigId)) {
+      configPO.setId(ConfigId);
     }
-
-    /**
-     * @param p1  上级指标
-     * @param p2  比对指标
-     * @param p3  末级指标
-     * @param pos 所有指标
-     */
-    private void setSc(SublistScoreVo p1, SublistScoreVo p2, SublistScoreVo p3, List<SublistScoreVo> pos) {
-        // 上级指标
-        if (p1.getParentId().equals(p2.getId())) {
-
-            // 末级指标拼接指标名
-            p3.setSublistName(p2.getSublistName() + ProjectConstants.SEPARATOR + p3.getSublistName());
-            // 查找上级指标,继续拼接
-            setParentSub(p3, p2, pos);
-        }
-
-    }
-
-    private Map<String, Object> selectScenePackageSubListAndSetScore(String scenePackageId, String projectId) {
-
-        // 查询场景包所有数据
-        SimulationManualProjectParam query = new SimulationManualProjectParam();
-        query.setId(projectId);
-        query.setPackageId(scenePackageId);
-        List<SublistScoreVo> sublistScoreVoList = simulationProjectMapper.selectSubScore2(query);
-        HashMap<String, Object> hashMap = new HashMap<>();
-        int maxHeaderNumber = 0;
-        List<List<String>> result = new ArrayList<>();
-        // 递归指标名称得分
-        for (SublistScoreVo sublistScoreVo : sublistScoreVoList) {
-            if (ObjectUtil.isNotNull(sublistScoreVo.getPackageAndRules())
-                    && (sublistScoreVo.getFirTarget() != null || sublistScoreVo.getLasTarget() != null)) {
-                // 末级指标
-                setParent(sublistScoreVo, null, sublistScoreVoList, scenePackageId);
-                String sublistName = sublistScoreVo.getSublistName();
-                Double firScore = sublistScoreVo.getFirScore();
-                String firstScore = ""; // first得分
-                if (firScore != null) {
-                    firstScore = saveTwoDecimalPlaces(firScore, 1).toString();
-                }
-                Double lasScore = sublistScoreVo.getLasScore();
-                String LastScore = ""; // last得分
-                if (lasScore != null) {
-                    LastScore = saveTwoDecimalPlaces(lasScore, 1).toString();
-                }
-                String sceneNum = sublistScoreVo.getSceneNum(); // 场景数量
-                String errorSceneNum = sublistScoreVo.getErrorSceneNum(); // 仿真异常场景个数
-                String notScoredSceneNum = sublistScoreVo.getNotScoredSceneNum(); // 未参与评分数量
-                String notStandardSceneNum = sublistScoreVo.getNotStandardSceneNum(); // 未达标场景数量
-                String standardSceneNum = sublistScoreVo.getStandardSceneNum(); // 达标场景数量
-
-                if (ObjectUtil.isNotNull(sublistName)) {
-                    sublistName += ProjectConstants.SEPARATOR
-                            + sceneNum + ProjectConstants.SEPARATOR
-                            + errorSceneNum + ProjectConstants.SEPARATOR
-                            + notScoredSceneNum + ProjectConstants.SEPARATOR
-                            + notStandardSceneNum + ProjectConstants.SEPARATOR
-                            + standardSceneNum + ProjectConstants.SEPARATOR
-                            + LastScore + ProjectConstants.SEPARATOR
-                            + firstScore;
-                    String[] split = sublistName.split(ProjectConstants.SEPARATOR);
-                    maxHeaderNumber = Math.max(maxHeaderNumber, split.length); // 求最大表头数量
-                    result.add(Arrays.asList(split));
-                }
-            }
-        }
-        // 结果补全
-        List<SubScListVo> values = new ArrayList<>();
-        int fieldNumber = 7;
-        for (List<String> list : result) {
-            int start = list.size() - fieldNumber;
-            SubScListVo subScListVo = new SubScListVo();
-            subScListVo.setSceneNum(list.get(start));
-            subScListVo.setErrorSceneNum(list.get(start + 1));
-            subScListVo.setNotScoredSceneNum(list.get(start + 2));
-            subScListVo.setNotStandardSceneNum(list.get(start + 3));
-            subScListVo.setStandardSceneNum(list.get(start + 4));
-            subScListVo.setLastScore(list.get(start + 5));
-            subScListVo.setFirstScore(list.get(start + 6));
-            for (int i = 0; i < start; i++) {
-                if (0 == i) {
-                    subScListVo.setSublistName1(list.get(i));
-                } else if (1 == i) {
-                    subScListVo.setSublistName2(list.get(i));
-                } else if (2 == i) {
-                    subScListVo.setSublistName3(list.get(i));
-                } else if (3 == i) {
-                    subScListVo.setSublistName4(list.get(i));
-                } else if (4 == i) {
-                    subScListVo.setSublistName5(list.get(i));
-                } else if (5 == i) {
-                    subScListVo.setSublistName6(list.get(i));
-                }
-            }
-            values.add(subScListVo);
-        }
-        List<Map<Object, Object>> headerList = new ArrayList<>();
-        for (int i = 0; i < maxHeaderNumber - fieldNumber; i++) {
-            addHeaders(i, headerList);
+    configPO.setCreateUserId(AuthUtil.getCurrentUserId());
+    List<ConfigPO> vehicleBaseInfoVo = simulationProjectMapper.selectConfigVehicle2(configPO);
+    List<DropDownVo> vehicleList = new ArrayList<>();
+    for (ConfigPO v : vehicleBaseInfoVo) {
+      DropDownVo dropDownVo = new DropDownVo();
+      dropDownVo.setId(v.getId());
+      dropDownVo.setName(v.getConfigName());
+      dropDownVo.setDescription(v.getDescription());
+      dropDownVo.setShare(v.getShare());
+      // 获取传感器信息
+      List<ConfigSensorPO> configSensorVos = simulationProjectMapper.selectConfigSensor(v.getId());
+      String sensor = "";
+      if (!isEmpty(configSensorVos) && configSensorVos.get(0) != null) {
+        StringBuilder stringBuilder = new StringBuilder();
+        for (ConfigSensorPO cv : configSensorVos) {
+          stringBuilder.append(cv.getSensorType()).append(",");
         }
-        headerList.add(ImmutableMap.builder().put("label", "场景个数").put("prop", "sceneNum").build());
-        headerList.add(ImmutableMap.builder().put("label", "仿真异常场景个数").put("prop", "errorSceneNum").build());
-        headerList.add(ImmutableMap.builder().put("label", "评分失败场景个数").put("prop", "notScoredSceneNum").build());
-        headerList.add(ImmutableMap.builder().put("label", "未达标场景个数").put("prop", "notStandardSceneNum").build());
-        headerList.add(ImmutableMap.builder().put("label", "达标场景个数").put("prop", "standardSceneNum").build());
-        headerList.add(ImmutableMap.builder().put("label", "得分").put("prop", "lastScore").build());
-        headerList.add(ImmutableMap.builder().put("label", "总分").put("prop", "firstScore").build());
-        hashMap.put("headerList", headerList);
-        hashMap.put("result", values);
+        sensor = stringBuilder.substring(0, stringBuilder.lastIndexOf(","));
 
-        return hashMap;
+      }
+      dropDownVo.setSensor(sensor);
 
+      vehicleList.add(dropDownVo);
     }
 
-    /**
-     * @param po     末级指标
-     * @param pos    场景包下所有指标
-     * @param rootId 场景包id,用于判断是否根指标
-     */
-    private void setParent(SublistScoreVo po, List<SublistScoreVo> pos, String rootId) {
-        for (SublistScoreVo p : pos) {
-
-            if (po.getParentId().equals(p.getId())) {
-                // 给一级指标添加末级指标得分,给末级指标添加一级指标得分
-                if (p.getParentId().equals(rootId)) {
-                    p.setLasScore(po.getLasScore());
-                    po.setFirScore(p.getFirScore());
-                }
-                po.setSublistName(p.getSublistName() + "," + po.getSublistName());
-                setParent(p, pos, rootId);
-            }
-
-        }
+    DropDownTypeVo vehicleDropDown = new DropDownTypeVo();
+    vehicleDropDown.setDropDownList(vehicleList);
+    vehicleDropDown.setType("2");
+    result.add(vehicleDropDown);
+  }
+
+  private void setScenePackageDropDown(List<DropDownTypeVo> result) {
+    ScenePackagePO scenePackagePO = new ScenePackagePO();
+    scenePackagePO.setCreateUserId(AuthUtil.getCurrentUserId());
+    List<ScenePackagePO> scenePackageBaseVo = simulationProjectMapper.selectScenePackageBaseById(scenePackagePO);
+    List<DropDownVo> scenePackageList = new ArrayList<>();
+    for (ScenePackagePO v : scenePackageBaseVo) {
+      DropDownVo dropDownVo = new DropDownVo();
+      dropDownVo.setId(v.getPackageId());
+      dropDownVo.setName(v.getPackageName());
+      dropDownVo.setSceneNum(String.valueOf(v.getSceneNum()));
+      dropDownVo.setShare(v.getShare());
+      scenePackageList.add(dropDownVo);
+    }
+    DropDownTypeVo scenePackageDropDown = new DropDownTypeVo();
+    scenePackageDropDown.setDropDownList(scenePackageList);
+    scenePackageDropDown.setType("3");
+    result.add(scenePackageDropDown);
+  }
+
+  private SimulationManualProjectPo convertParamToPo(SimulationManualProjectParam param) {
+    SimulationManualProjectPo po = new SimulationManualProjectPo();
+    po.setId(param.getId());
+    po.setProjectName(param.getProjectName());
+    po.setProjectDescribe(param.getProjectDescribe());
+    po.setAlgorithm(param.getAlgorithm());
+    po.setVehicle(param.getVehicle());
+    po.setScene(param.getScene());
+    // po.setOperationCycle(param.getOperationCycle());
+    po.setMaxSimulationTime(param.getMaxSimulationTime());
+    po.setParallelism(param.getParallelism());
+    // po.setRuleView(param.getRuleView());
+    po.setIsChoiceGpu(param.getIsChoiceGpu());
+    po.setNowRunState(param.getNowRunState());
+    po.setAlgorithmType(param.getAlgorithmType());
+
+    if (ObjectUtil.isNotNull(param.getVehicleArrayS())) {
+      po.setVehicleArray(StringUtils.join(Arrays.asList(param.getVehicleArrayS()), ','));
+    }
+    if (ObjectUtil.isNotNull(param.getAlgorithmArrayS())) {
+      po.setAlgorithmArray(StringUtils.join(Arrays.asList(param.getAlgorithmArrayS()), ','));
+    }
+    if (ObjectUtil.isNotNull(param.getSceneArrayS())) {
+      po.setSceneArray(StringUtils.join(Arrays.asList(param.getSceneArrayS()), ','));
+    }
+    return po;
+
+  }
+
+  private void convertPoToVo(SimulationManualProjectVo simulationManualProjectVo, boolean isAuto) {
+    // 1 查询算法名称
+    String algorithmId = simulationManualProjectVo.getAlgorithm();
+    String algorithmType = simulationManualProjectVo.getAlgorithmType();
+    String algorithmName;
+    if (DictConstants.ALGORITHM_UPLOAD_MODE_PLATFORM.equals(algorithmType)) {
+      // 1 获取 token
+      algorithmName = algoPlatformService.selectAlgorithmNameByAlgorithmId(algorithmId).getInfo();
+      if (StringUtil.isEmpty(algorithmName)) {
+        algorithmName = "算法平台已删除该算法";
+      }
+    } else {
+      AlgorithmPO algorithmPO = simulationProjectMapper.selectAlgorithmById(algorithmId);
+      if (algorithmPO != null && StringUtil.isNotEmpty(algorithmPO.getAlgorithmName())) {
+        algorithmName = algorithmPO.getAlgorithmName();
+      } else {
+        algorithmName = "仿真平台不存在该算法";
+      }
     }
 
-    /**
-     * @param po     末级指标
-     * @param pos    场景包下所有指标
-     * @param rootId 场景包id,用于判断是否一级指标
-     */
-    private void setParent(SublistScoreVo po, SublistScoreVo parentPo, List<SublistScoreVo> pos, String rootId) {
-        // 第一次查找
-        if (parentPo == null) {
-            for (SublistScoreVo p : pos) {
-
-                setSubSc(po, p, po, pos, rootId);
-                /*
-                 * if(po.getParentId().equals(p.getId())){
-                 * //根指标给一级指标添加末级指标得分,给末级指标添加一级指标得分
-                 * if(p.getParentId().equals(rootId)){
-                 * p.setLasScore(po.getLasScore());
-                 * po.setFirScore(p.getFirScore());
-                 * }
-                 * //末级指标拼接指标名
-                 * po.setSublistName(p.getSublistName()+","+po.getSublistName());
-                 * //查找上级指标,继续拼接
-                 * setParent(po,p, pos, rootId);
-                 * 
-                 * }
-                 */
-            }
+    simulationManualProjectVo.setAlgorithm(algorithmName);
+    // 2 是否是自动项目
+    if (!isAuto) {
+      simulationManualProjectVo.setNowRunStateDict(getDictName(DictConstants.PROJECT_RUN_STATE, simulationManualProjectVo.getNowRunState()));
+      simulationManualProjectVo.setEvaluationLevelDict(getDictName(DictConstants.EVALUATION_LEVEL, simulationManualProjectVo.getEvaluationLevel()));
+    } else {
+      simulationManualProjectVo.setLastRunTimeFmt(getRqStr(simulationManualProjectVo.getLastRunTime(), 1));
+    }
+    // 3 格式化创建时间字符串
+    simulationManualProjectVo.setCreateTimeFmt(getRqStr(simulationManualProjectVo.getCreateTime(), 1));
+  }
+
+  private void convertPoToVo(SimulationManualProjectPo po, SimulationManualProjectSingleVo vo) {
+    vo.setId(po.getId());
+    vo.setProjectName(po.getProjectName());
+    vo.setProjectDescribe(po.getProjectDescribe());
+    vo.setAlgorithm(po.getAlgorithm());
+    vo.setAlgorithmType(po.getAlgorithmType());
+    vo.setVehicle(po.getVehicle());
+    vo.setScene(po.getScene());
+    vo.setMaxSimulationTime(po.getMaxSimulationTime());
+    vo.setParallelism(po.getParallelism());
+    vo.setIsChoiceGpu(po.getIsChoiceGpu());
+
+  }
+
+  private void createProjectId(SimulationManualProjectPo po) {
+    Integer nowRq = getRq(null, 0);
+    po.setProjectDate(nowRq);
+    SimulationManualProjectPo po1 = simulationProjectMapper.selectLastProjectId(nowRq);
+    if (po1 == null) {
+      // 生成新id
+      po.setProjectNum(1);
+    } else {
+      po.setProjectNum(po1.getProjectNum() + 1);
+    }
+    po.setProjectId(po.getProjectDate() + "-" + po.getProjectNum());
+
+  }
+
+  private void createProjectId(SimulationAutomaticProjectPo po) {
+    Integer nowRq = getRq(null, 0);
+    po.setProjectDate(nowRq);
+    SimulationAutomaticProjectPo po1 = simulationAutomaticProjectMapper.selectLastProjectId(nowRq);
+    if (po1 == null) {
+      // 生成新id
+      po.setProjectNum(1);
+    } else {
+      po.setProjectNum(po1.getProjectNum() + 1);
+    }
+    po.setProjectId(po.getProjectDate() + "-" + po.getProjectNum());
 
-        } else {
-            for (SublistScoreVo p : pos) {
-
-                setSubSc(parentPo, p, po, pos, rootId);
-
-                /*
-                 * //上级指标
-                 * if(parentPo.getParentId().equals(p.getId())){
-                 * //根指标给一级指标添加末级指标得分,给末级指标添加一级指标得分
-                 * if(p.getParentId().equals(rootId)){
-                 * p.setLasScore(po.getLasScore());
-                 * po.setFirScore(p.getFirScore());
-                 * }
-                 * //末级指标拼接指标名
-                 * po.setSublistName(p.getSublistName()+","+po.getSublistName());
-                 * //查找上级指标,继续拼接
-                 * setParent(po,p, pos, rootId);
-                 * }
-                 */
+  }
 
-            }
-        }
+  private Integer getRq(Date date, int index) {
+    return TimeUtil.getRq(date, index);
+  }
 
+  private String getRqStr(Date date, int index) {
+    SimpleDateFormat sdf = new SimpleDateFormat(dateFmtArr[index]);
+    if (date == null) {
+      return "";
     }
+    return sdf.format(date);
 
-    /**
-     * @param p1     上级指标
-     * @param p2     比对指标
-     * @param p3     末级指标
-     * @param pos    所有指标
-     * @param rootId 场景包id
-     */
-    private void setSubSc(SublistScoreVo p1, SublistScoreVo p2, SublistScoreVo p3, List<SublistScoreVo> pos,
-            String rootId) {
-        // 上级指标
-        if (p1.getParentId().equals(p2.getId())) {
-            // 根指标给一级指标添加末级指标得分,给末级指标添加一级指标得分
-            if (p2.getParentId().equals(rootId)) {
-                p2.setLasScore(p3.getLasScore());
-                p3.setFirScore(p2.getFirScore());
-            }
-            // 末级指标拼接指标名
-            p3.setSublistName(p2.getSublistName() + ProjectConstants.SEPARATOR + p3.getSublistName());
-            // 查找上级指标,继续拼接
-            setParent(p3, p2, pos, rootId);
-        }
+  }
 
+  private Date getDate(String dateFmt, int index) {
+    SimpleDateFormat sdf = new SimpleDateFormat(dateFmtArr[index]);
+    try {
+      return sdf.parse(dateFmt);
+    } catch (ParseException e) {
+      return null;
     }
+  }
 
-    /*
-     */
+  private boolean isEmpty(String value) {
+    if (value == null) {
+      return true;
+    }
+    value = value.trim();
+    if (value.length() == 0) {
+      return true;
+    }
+    return false;
+  }
 
-    /**
-     * 查询所有指标和得分
-     *
-     * @param
-     *//*
-        * private void selectScenePackageSubListAndSetScore(String pId, String
-        * scenePackageId, List<List<String>> resultArr, List<ScenePackageSubListVO>
-        * single){
-        * 
-        * //首次,初始化数据以及赋值
-        * if(isEmpty(single)){
-        * //单个级联,按最后一级到第一级指标顺序添加
-        * single= new ArrayList<>();
-        * //查询所有指标最后一级
-        * List<ScenePackageSubListVO> vos =
-        * simulationProjectMapper.selectSubListByPid(scenePackageId);
-        * for(ScenePackageSubListVO vo : vos){
-        * selectSceneSubList(vo, pId, single, resultArr);
-        * }
-        * }
-        * //继续添加数据
-        * else{
-        * //查询父级节点,只有一个
-        * ScenePackageSubListVO vo =
-        * simulationProjectMapper.selectsublistBySublistId(scenePackageId);
-        * //如果是根节点,不再查询,组装返回数据
-        * if(vo.getSublistId().equals(scenePackageId)){
-        * if(isEmpty(resultArr)){
-        * //初始化返回数据
-        * resultArr = new ArrayList<>();
-        * List<String> singleList = new ArrayList<>();
-        * //反转list,正序添加(从一级开始)
-        * Collections.reverse(single);
-        * 
-        * for(int i=0;i<single.size();i--){
-        * if(i == single.size()-1){
-        * singleList.add(String.valueOf(single.get(i).getSceneNum()));
-        * singleList.add(String.valueOf(single.get(i).getNotStandardSceneNum()));
-        * singleList.add(String.valueOf(single.get(i).getScore()));
-        * 
-        * singleList.add(String.valueOf(single.get(i).getScore()));
-        * 
-        * }
-        * singleList.add(single.get(i).getSublistName());
-        * }
-        * 
-        * 
-        * 
-        * 
-        * 
-        * 
-        * }
-        * 
-        * }else{
-        * selectSceneSubList(vo, pId, single, resultArr);
-        * }
-        * }
-        * 
-        * };
-        */
+  private boolean isEmpty(List list) {
+    if (list == null || list.size() <= 0) {
+      return true;
+    }
+    return false;
+  }
+
+  private void setPage(Integer pageNum, Integer pageSize) {
+    PageVO pageVO = new PageVO();
+    pageVO.setCurrentPage(pageNum);
+    pageVO.setPageSize(pageSize);
+    PageUtil.setPageInfo(pageVO);
+  }
+
+  private Double saveTwoDecimalPlaces(Double d) {
+    if (d == null) {
+      return null;
+    }
+    return new BigDecimal(d.toString()).setScale(2, RoundingMode.HALF_UP).doubleValue();
+  }
 
-    /*
-     * private void selectSceneSubList(ScenePackageSubListVO vo, String pId,
-     * List<ScenePackageSubListVO> single, List<List<String>> resultArr){
-     * //获取未达标个数,得分,总分
-     * setScore(vo,pId);
-     * //放入集合
-     * single.add(vo);
-     * //递归查询上级指标
-     * selectScenePackageSubListAndSetScore(pId, vo.getParentId(), resultArr,
-     * single);
-     * }
-     */
-    private void setScore(ScenePackageSubListVO vo, String pId) {
-        setLastTargetScore(vo, pId);
-        setSceneScore(vo, pId);
+  private Double saveTwoDecimalPlaces(Double d, int num) {
+    if (d == null) {
+      return null;
     }
+    return new BigDecimal(d.toString()).setScale(num, RoundingMode.HALF_UP).doubleValue();
+  }
+
+  /**
+   * 设置场景基本字段
+   */
+  private void setUpSceneInfo(ManualProjectTaskVo vo) {
+    String sceneType = vo.getSceneType();
+    String sceneId = vo.getSceneId();
+    SceneBaseInfoVo sceneBaseInfoVo;
+    if (DictConstants.SCENE_NATURAL.equals(sceneType)) {
+      // 自然驾驶
+      sceneBaseInfoVo = simulationProjectMapper.selectSceneNatural(sceneId);
+      if (sceneBaseInfoVo != null) {
+        vo.setSceneName(sceneBaseInfoVo.getNaturalName());
+      }
+    } else if (DictConstants.SCENE_STANDARD.equals(sceneType)) {
+      // 标准法规
+      sceneBaseInfoVo = simulationProjectMapper.selectSceneStandardsRegulations(sceneId);
+      if (sceneBaseInfoVo != null) {
+        vo.setSceneName(sceneBaseInfoVo.getSceneName());
+      }
+    } else if (DictConstants.SCENE_ACCIDENT.equals(sceneType)) {
+      // 交通事故
+      sceneBaseInfoVo = simulationProjectMapper.selectSceneAccidentById(sceneId);
+      if (sceneBaseInfoVo != null) {
+        vo.setSceneName(sceneBaseInfoVo.getSceneName());
+      }
+    } else if (DictConstants.SCENE_GENERAL.equals(sceneType)) {
+      /// TODO 泛化场景暂不支持
+      sceneBaseInfoVo = simulationProjectMapper.selectSceneGeneralDataById(sceneId);
+      if (sceneBaseInfoVo != null) {
+        vo.setSceneName(sceneBaseInfoVo.getSceneName());
+      }
 
-    private void setSceneScore(ScenePackageSubListVO vo, String pId) {
-        String sceneNaturalIds = vo.getSceneNaturalIds();
-        String sceneTrafficIds = vo.getSceneTrafficIds();
-        String sceneStatueIds = vo.getSceneStatueIds();
-        List<SceneScoreVo> sceneScoreVos = new ArrayList<>();
-        List<SceneScoreVo> NaturalSceneScoreVos = setSceneScore(vo, sceneNaturalIds, DictConstants.SCENE_NATURAL, pId);
-        List<SceneScoreVo> StatueSceneScoreVos = setSceneScore(vo, sceneStatueIds, DictConstants.SCENE_STANDARD, pId);
-        List<SceneScoreVo> TrafficSceneScoreVos = setSceneScore(vo, sceneTrafficIds, DictConstants.SCENE_ACCIDENT, pId);
-        /// TODO 暂不支持泛化场景
-        List<SceneScoreVo> FhSceneScoreVos = setSceneScore(vo, sceneTrafficIds, DictConstants.SCENE_GENERAL, pId);
+    }
+  }
+
+  private ManualProjectTaskVo convertManualProjectTaskPoToVo(ManualProjectTaskPo po) {
+    ManualProjectTaskVo manualProjectTaskVo = new ManualProjectTaskVo();
+    manualProjectTaskVo.setId(po.getId());
+    manualProjectTaskVo.setPId(po.getPId());
+    manualProjectTaskVo.setSceneId(po.getSceneId());
+    // manualProjectTaskVo.setSceneName(po.getSceneName());
+    manualProjectTaskVo.setSceneType(po.getSceneType());
+    manualProjectTaskVo.setRunStartTimeFmt(getRqStr(po.getRunStartTime(), 2));
+    manualProjectTaskVo.setRunEndTimeFmt(getRqStr(po.getRunEndTime(), 2));
+    manualProjectTaskVo.setRunState(po.getRunState());
+    manualProjectTaskVo.setRunResult(po.getRunResult());
+    return manualProjectTaskVo;
+  }
+
+  /**
+   * 级联获取场景指标得分数据
+   *
+   * @param parentVoList   首次传null
+   * @param isRoot         首次传true
+   * @param scenePackageId 场景包id
+   * @param pId            项目表id,用于统计得分使用
+   * @param level          指标级别
+   * @return
+   */
+  private List<ScenePackageSubListVO> selectScenePackageSubListTreeAndSetScore(List<ScenePackageSubListVO> parentVoList, boolean isRoot, String scenePackageId, String pId, Integer level) {
+
+    if (isRoot) {
+      // 查找一级节点
+      parentVoList = simulationProjectMapper.selectSubSceneByPid(scenePackageId);
+      if (!isEmpty(parentVoList)) {
+        selectScenePackageSubListTreeAndSetScore(parentVoList, false, null, pId, level);
+      }
+
+    } else {
+
+      // 获取子节点集合
+      for (ScenePackageSubListVO pvo : parentVoList) {
+
+        pvo.setLevel(level);
+
+        // 二级指标获取总分
+        if (level == 2) {
+          setFirstTargetScore(pvo, pId);
+        }
+
+        List<ScenePackageSubListVO> cvoList = simulationProjectMapper.selectSubSceneByPid(pvo.getSublistId());
+        if (!isEmpty(cvoList)) {
+          // 存入父节点集合中
+          pvo.setChildScenePackageSubListVOList(cvoList);
+          // 继续查找下一节点
+          selectScenePackageSubListTreeAndSetScore(cvoList, false, null, pId, level + 1);
+        } else {
 
-        // 合成一个list
-        if (!isEmpty(NaturalSceneScoreVos)) {
-            sceneScoreVos.addAll(NaturalSceneScoreVos);
-        }
-        if (!isEmpty(StatueSceneScoreVos)) {
-            sceneScoreVos.addAll(StatueSceneScoreVos);
-        }
-        if (!isEmpty(TrafficSceneScoreVos)) {
-            sceneScoreVos.addAll(TrafficSceneScoreVos);
+          // 没有子节点;最后一级,获取指标得分,指标得分说明,和指标下场景得分
+          setScore(pvo, pId);
         }
 
-        if (!isEmpty(FhSceneScoreVos)) {
-            sceneScoreVos.addAll(FhSceneScoreVos);
-        }
-        vo.setSceneScoreList(sceneScoreVos);
+      }
     }
 
-    private void setLastTargetScore(ScenePackageSubListVO vo, String pId) {
-        SimulationMptLastTargetScorePo poParam = new SimulationMptLastTargetScorePo();
-        poParam.setPId(pId);
-        poParam.setTarget(vo.getSublistId());
-        SimulationMptLastTargetScorePo po = simulationMptLastTargetScoreMapper.selectLastTargetScore(poParam);
-        if (po != null) {
-            vo.setNotStandardSceneNum(po.getNotStandardSceneNum());
-            vo.setScore(po.getScore());
-            vo.setScoreExplain(po.getScoreExplain());
-        }
-
+    return parentVoList;
+  }
+
+  private Map<String, Object> selectSceneScore(String scenePackageId, String projectId, String taskId) {
+
+    // 1 查询指定项目的所有指标得分结果
+    SimulationManualProjectParam query = new SimulationManualProjectParam();
+    query.setId(projectId);
+    query.setPackageId(scenePackageId);
+    List<SublistScoreVo> pos = simulationProjectMapper.selectSubScore2(query);
+    // 2 查询指定项目的所有任务得分结果
+    ProjectTaskParam param = new ProjectTaskParam();
+    param.setPId(projectId);
+    if (!isEmpty(taskId)) {
+      param.setTaskId(taskId);
+    }
+    List<ManualProjectTaskVo> taskList = simulationProjectTaskMapper.selectProjectTaskByProjectId(param); // 手动运行项目和自动运行项目使用同一个任务表
+
+    // 2 拼接场景得分信息
+    List<SublistScoreVo> lastSubList = new ArrayList<>();
+    for (SublistScoreVo po : pos) {
+      if (ObjectUtil.isNotNull(po.getPackageAndRules())) {
+        // 获取场景得分信息
+        for (ManualProjectTaskVo task : taskList)
+          if (task.getLastTargerId().equals(po.getId())) {
+            SublistScoreVo sublistScoreVo = new SublistScoreVo();
+            BeanUtils.copyProperties(po, sublistScoreVo);
+            sublistScoreVo.setRunResult(task.getRunResult());
+            sublistScoreVo.setSceneScore(saveTwoDecimalPlaces(task.getScore())); // 得分
+            sublistScoreVo.setTargetEvaluate(task.getTargetEvaluate());// 指标评价
+            String sceneType = task.getSceneType();
+            String sceneId = task.getSceneId();
+            String sceneName = "";
+            if (DictConstants.SCENE_NATURAL.equals(sceneType)) {
+              sublistScoreVo.setSceneType("自然驾驶");
+              SceneBaseInfoVo sceneBaseInfoVo = simulationProjectMapper.selectSceneNatural(sceneId);
+              sceneName = sceneBaseInfoVo.getNaturalName();
+            } else if (DictConstants.SCENE_STANDARD.equals(sceneType)) {
+              sublistScoreVo.setSceneType("标准法规");
+              SceneBaseInfoVo sceneBaseInfoVo = simulationProjectMapper.selectSceneStandardsRegulations(sceneId);
+              sceneName = sceneBaseInfoVo.getSceneName();
+            } else if (DictConstants.SCENE_ACCIDENT.equals(sceneType)) {
+              sublistScoreVo.setSceneType("交通事故");
+              SceneBaseInfoVo sceneBaseInfoVo = simulationProjectMapper.selectSceneAccidentById(sceneId);
+              sceneName = sceneBaseInfoVo.getSceneName();
+            } else if (DictConstants.SCENE_GENERAL.equals(sceneType)) {
+              sublistScoreVo.setSceneType("泛化");
+              SceneBaseInfoVo sceneBaseInfoVo = simulationProjectMapper.selectSceneGeneralDataById(sceneId);
+              sceneName = sceneBaseInfoVo.getSceneName();
+            }
+            sublistScoreVo.setReturnSceneId(sceneName); // 显示场景名称
+            lastSubList.add(sublistScoreVo);
+          }
+      }
+    }
+    int size = 0;
+    List<List<String>> result = new ArrayList<>();
+    // 新增返回状态
+    ArrayList<String> runStateList = new ArrayList<>();
+    // 末级指标
+    for (SublistScoreVo sp : lastSubList) {
+      setParentSub(sp, null, pos);
+      String sublistName = sp.getSublistName();
+      // 失败的任务没有数据,需要校验
+      Double sceneScore = sp.getSceneScore();
+      if (sceneScore == null) {
+        sceneScore = 0D;
+      }
+      String targetEvaluate = sp.getTargetEvaluate();
+      if (targetEvaluate == null) {
+        targetEvaluate = "";
+      }
+      /*
+       * sublistName +=
+       * ProjectConstants.SEPARATOR+sp.getReturnSceneId()+ProjectConstants.SEPARATOR+
+       * sp.getSceneType()+ProjectConstants.SEPARATOR+
+       * sp.getSceneScore()+ProjectConstants.SEPARATOR+sp.getTargetEvaluate()+
+       * ProjectConstants.SEPARATOR+sp.getScoreExplain();
+       */
+      // 测试得分,指标评价,得分说明 --处理
+      if (isEmpty(targetEvaluate) || isEmpty(sp.getScoreExplain())) {
+        sublistName += ProjectConstants.SEPARATOR + sp.getReturnSceneId() + ProjectConstants.SEPARATOR + sp.getSceneType() + ProjectConstants.SEPARATOR + "--" + ProjectConstants.SEPARATOR + "--" + ProjectConstants.SEPARATOR + "--";
+      } else {
+        sublistName += ProjectConstants.SEPARATOR + sp.getReturnSceneId() + ProjectConstants.SEPARATOR + sp.getSceneType() + ProjectConstants.SEPARATOR + sceneScore + ProjectConstants.SEPARATOR + targetEvaluate + ProjectConstants.SEPARATOR + sp.getScoreExplain();
+      }
+      String[] split = sublistName.split(ProjectConstants.SEPARATOR);
+      List<String> strings = new LinkedList<>(Arrays.asList(split));
+      if (size < strings.size()) {
+        size = strings.size();
+      }
+      result.add(strings);
+      runStateList.add(sp.getRunResult());
+    }
+    List<SceneScListVo> objects = new ArrayList<>();
+    // 结果补全
+    int r = 0;
+    for (List<String> list : result) {
+      int start = list.size() - 5;
+      SceneScListVo sceneScListVo = new SceneScListVo();
+      for (int i = 0; i < start; i++) {
+        if (0 == i) {
+          sceneScListVo.setSublistName1(list.get(i));
+        } else if (1 == i) {
+          sceneScListVo.setSublistName2(list.get(i));
+        } else if (2 == i) {
+          sceneScListVo.setSublistName3(list.get(i));
+        } else if (3 == i) {
+          sceneScListVo.setSublistName4(list.get(i));
+        } else if (4 == i) {
+          sceneScListVo.setSublistName5(list.get(i));
+        } else if (5 == i) {
+          sceneScListVo.setSublistName6(list.get(i));
+        }
+      }
+      sceneScListVo.setSceneId(list.get(start));
+      sceneScListVo.setSceneIdType(list.get(start + 1));
+      sceneScListVo.setSceneScore(list.get(start + 2));
+      sceneScListVo.setTargetEvaluate(list.get(start + 3));
+      sceneScListVo.setScoreExplain(list.get(start + 4));
+      sceneScListVo.setRunState(runStateList.get(r));
+      objects.add(sceneScListVo);
+      r++;
+    }
+    List<Map<Object, Object>> headerList = new ArrayList<>();
+    int maxIndex = size - 5;
+    for (int i = 0; i < maxIndex; i++) {
+      addHeaders(i, headerList);
+    }
+    headerList.add(ImmutableMap.builder().put("label", "场景名称").put("prop", "sceneId").build());
+    headerList.add(ImmutableMap.builder().put("label", "场景类型").put("prop", "sceneIdType").build());
+    headerList.add(ImmutableMap.builder().put("label", "测试得分").put("prop", "sceneScore").build());
+    headerList.add(ImmutableMap.builder().put("label", "指标评价").put("prop", "targetEvaluate").build());
+    headerList.add(ImmutableMap.builder().put("label", "得分说明").put("prop", "scoreExplain").build());
+    HashMap<String, Object> hashMap = new HashMap<>();
+    hashMap.put("headerList", headerList);
+    hashMap.put("result", objects);
+    return hashMap;
+  }
+
+  private Map<String, Object> selectSceneScore2(String scenePackageId, String projectId, String taskId, ProjectReportVo projectReportVo) {
+
+    // 1 查询指定项目的所有指标得分结果
+    SimulationManualProjectParam query = new SimulationManualProjectParam();
+    query.setId(projectId);
+    query.setPackageId(scenePackageId);
+    List<SublistScoreVo> pos = simulationProjectMapper.selectSubScore2(query);
+    // 2 查询指定项目的所有任务得分结果
+    ProjectTaskParam param = new ProjectTaskParam();
+    param.setPId(projectId);
+    if (!isEmpty(taskId)) {
+      param.setTaskId(taskId);
+    }
+    List<ManualProjectTaskVo> taskList = simulationProjectTaskMapper.selectProjectTaskByProjectId(param); // 手动运行项目和自动运行项目使用同一个任务表
+
+    // 2 拼接场景得分信息
+    List<SublistScoreVo> lastSubList = new ArrayList<>();
+    for (SublistScoreVo po : pos) {
+      if (ObjectUtil.isNotNull(po.getPackageAndRules())) {
+        // 获取场景得分信息
+        for (ManualProjectTaskVo task : taskList)
+          if (task.getLastTargerId().equals(po.getId())) {
+            SublistScoreVo sublistScoreVo = new SublistScoreVo();
+            BeanUtils.copyProperties(po, sublistScoreVo);
+            sublistScoreVo.setRunResult(task.getRunResult());
+            sublistScoreVo.setSceneScore(saveTwoDecimalPlaces(task.getScore())); // 得分
+            sublistScoreVo.setTargetEvaluate(task.getTargetEvaluate());// 指标评价
+            String sceneType = task.getSceneType();
+            String sceneId = task.getSceneId();
+            String sceneName = "";
+            if (DictConstants.SCENE_NATURAL.equals(sceneType)) {
+              sublistScoreVo.setSceneType("自然驾驶");
+              SceneBaseInfoVo sceneBaseInfoVo = simulationProjectMapper.selectSceneNatural(sceneId);
+              sceneName = sceneBaseInfoVo.getNaturalName();
+            } else if (DictConstants.SCENE_STANDARD.equals(sceneType)) {
+              sublistScoreVo.setSceneType("标准法规");
+              SceneBaseInfoVo sceneBaseInfoVo = simulationProjectMapper.selectSceneStandardsRegulations(sceneId);
+              sceneName = sceneBaseInfoVo.getSceneName();
+            } else if (DictConstants.SCENE_ACCIDENT.equals(sceneType)) {
+              sublistScoreVo.setSceneType("交通事故");
+              SceneBaseInfoVo sceneBaseInfoVo = simulationProjectMapper.selectSceneAccidentById(sceneId);
+              sceneName = sceneBaseInfoVo.getSceneName();
+            } else if (DictConstants.SCENE_GENERAL.equals(sceneType)) {
+              sublistScoreVo.setSceneType("泛化");
+              SceneBaseInfoVo sceneBaseInfoVo = simulationProjectMapper.selectSceneGeneralDataById(sceneId);
+              sceneName = sceneBaseInfoVo.getSceneName();
+            }
+            sublistScoreVo.setReturnSceneId(sceneName); // 显示场景名称
+            lastSubList.add(sublistScoreVo);
+          }
+      }
+    }
+    int size = 0;
+    List<List<String>> result = new ArrayList<>();
+    // 新增返回状态
+    ArrayList<String> runStateList = new ArrayList<>();
+    // 末级指标
+    for (SublistScoreVo sp : lastSubList) {
+      setParentSub(sp, null, pos);
+      String sublistName = sp.getSublistName();
+      // 失败的任务没有数据,需要校验
+      Double sceneScore = sp.getSceneScore();
+      if (sceneScore == null) {
+        sceneScore = 0D;
+      }
+      String targetEvaluate = sp.getTargetEvaluate();
+      if (targetEvaluate == null) {
+        targetEvaluate = "";
+      }
+      /*
+       * sublistName +=
+       * ProjectConstants.SEPARATOR+sp.getReturnSceneId()+ProjectConstants.SEPARATOR+
+       * sp.getSceneType()+ProjectConstants.SEPARATOR+
+       * sp.getSceneScore()+ProjectConstants.SEPARATOR+sp.getTargetEvaluate()+
+       * ProjectConstants.SEPARATOR+sp.getScoreExplain();
+       */
+      // 测试得分,指标评价,得分说明 --处理
+      if (isEmpty(targetEvaluate) || isEmpty(sp.getScoreExplain())) {
+        sublistName += ProjectConstants.SEPARATOR + sp.getReturnSceneId() + ProjectConstants.SEPARATOR + sp.getSceneType() + ProjectConstants.SEPARATOR + "--" + ProjectConstants.SEPARATOR + "--" + ProjectConstants.SEPARATOR + "--";
+      } else {
+        sublistName += ProjectConstants.SEPARATOR + sp.getReturnSceneId() + ProjectConstants.SEPARATOR + sp.getSceneType() + ProjectConstants.SEPARATOR + sceneScore + ProjectConstants.SEPARATOR + targetEvaluate + ProjectConstants.SEPARATOR + sp.getScoreExplain();
+      }
+      String[] split = sublistName.split(ProjectConstants.SEPARATOR);
+      List<String> strings = new LinkedList<>(Arrays.asList(split));
+      if (size < strings.size()) {
+        size = strings.size();
+      }
+      result.add(strings);
+      runStateList.add(sp.getRunResult());
+    }
+    List<SceneScListVo> objects = new ArrayList<>();
+    // 结果补全
+    int r = 0;
+    for (List<String> list : result) {
+      int start = list.size() - 5;
+      SceneScListVo sceneScListVo = new SceneScListVo();
+      for (int i = 0; i < start; i++) {
+        if (0 == i) {
+          String s0 = list.get(i);
+          if (StringUtil.isNotEmpty(s0)) {
+            sceneScListVo.setEachMaxIndex((i + 1) + "");
+          }
+          sceneScListVo.setSublistName1(s0);
+        } else if (1 == i) {
+          String s1 = list.get(i);
+          if (StringUtil.isNotEmpty(s1)) {
+            sceneScListVo.setEachMaxIndex((i + 1) + "");
+          }
+          sceneScListVo.setSublistName2(list.get(i));
+        } else if (2 == i) {
+          String s2 = list.get(i);
+          if (StringUtil.isNotEmpty(s2)) {
+            sceneScListVo.setEachMaxIndex((i + 1) + "");
+          }
+          sceneScListVo.setSublistName3(list.get(i));
+        } else if (3 == i) {
+          String s3 = list.get(i);
+          if (StringUtil.isNotEmpty(s3)) {
+            sceneScListVo.setEachMaxIndex((i + 1) + "");
+          }
+          sceneScListVo.setSublistName4(list.get(i));
+        } else if (4 == i) {
+          String s4 = list.get(i);
+          if (StringUtil.isNotEmpty(s4)) {
+            sceneScListVo.setEachMaxIndex((i + 1) + "");
+          }
+          sceneScListVo.setSublistName5(list.get(i));
+        } else if (5 == i) {
+          String s5 = list.get(i);
+          if (StringUtil.isNotEmpty(s5)) {
+            sceneScListVo.setEachMaxIndex((i + 1) + "");
+          }
+          sceneScListVo.setSublistName6(list.get(i));
+        }
+      }
+      sceneScListVo.setSceneId(list.get(start));
+      sceneScListVo.setSceneIdType(list.get(start + 1));
+      sceneScListVo.setSceneScore(list.get(start + 2));
+      sceneScListVo.setTargetEvaluate(list.get(start + 3));
+      sceneScListVo.setScoreExplain(list.get(start + 4));
+      sceneScListVo.setRunState(runStateList.get(r));
+      objects.add(sceneScListVo);
+      r++;
+    }
+    List<Map<Object, Object>> headerList = new ArrayList<>();
+    int maxIndex = size - 5;
+    projectReportVo.setMaxIndex(maxIndex);
+    for (int i = 0; i < maxIndex; i++) {
+      addHeaders(i, headerList);
+    }
+    headerList.add(ImmutableMap.builder().put("label", "场景名称").put("prop", "sceneId").build());
+    headerList.add(ImmutableMap.builder().put("label", "场景类型").put("prop", "sceneIdType").build());
+    headerList.add(ImmutableMap.builder().put("label", "测试得分").put("prop", "sceneScore").build());
+    headerList.add(ImmutableMap.builder().put("label", "指标评价").put("prop", "targetEvaluate").build());
+    headerList.add(ImmutableMap.builder().put("label", "得分说明").put("prop", "scoreExplain").build());
+    HashMap<String, Object> hashMap = new HashMap<>();
+    hashMap.put("headerList", headerList);
+    hashMap.put("result", objects);
+    return hashMap;
+  }
+
+  /**
+   * @param po       末级指标
+   * @param parentPo 上级指标
+   * @param pos      所有指标
+   */
+  private void setParentSub(SublistScoreVo po, SublistScoreVo parentPo, List<SublistScoreVo> pos) {
+    if (parentPo == null) {
+      for (SublistScoreVo p : pos) {
+        setSc(po, p, po, pos);
+      }
+
+    } else {
+      for (SublistScoreVo p : pos) {
+        setSc(parentPo, p, po, pos);
+      }
+    }
+  }
+
+  /**
+   * @param p1  上级指标
+   * @param p2  比对指标
+   * @param p3  末级指标
+   * @param pos 所有指标
+   */
+  private void setSc(SublistScoreVo p1, SublistScoreVo p2, SublistScoreVo p3, List<SublistScoreVo> pos) {
+    // 上级指标
+    if (p1.getParentId().equals(p2.getId())) {
+
+      // 末级指标拼接指标名
+      p3.setSublistName(p2.getSublistName() + ProjectConstants.SEPARATOR + p3.getSublistName());
+      // 查找上级指标,继续拼接
+      setParentSub(p3, p2, pos);
     }
 
-    private void setFirstTargetScore(ScenePackageSubListVO vo, String pId) {
-        SimulationMptFirstTargetScorePo poParam = new SimulationMptFirstTargetScorePo();
-        poParam.setPId(pId);
-        poParam.setTarget(vo.getSublistId());
-        SimulationMptFirstTargetScorePo po = simulationMptFirstTargetScoreMapper.selectFirstTargetScore(poParam);
-        if (po != null) {
-            vo.setScore(po.getScore());
+  }
+
+  private Map<String, Object> selectScenePackageSubListAndSetScore(String scenePackageId, String projectId) {
+
+    // 查询场景包所有数据
+    SimulationManualProjectParam query = new SimulationManualProjectParam();
+    query.setId(projectId);
+    query.setPackageId(scenePackageId);
+    List<SublistScoreVo> sublistScoreVoList = simulationProjectMapper.selectSubScore2(query);
+    HashMap<String, Object> hashMap = new HashMap<>();
+    int maxHeaderNumber = 0;
+    List<List<String>> result = new ArrayList<>();
+    // 递归指标名称得分
+    for (SublistScoreVo sublistScoreVo : sublistScoreVoList) {
+      if (ObjectUtil.isNotNull(sublistScoreVo.getPackageAndRules()) && (sublistScoreVo.getFirTarget() != null || sublistScoreVo.getLasTarget() != null)) {
+        // 末级指标
+        setParent(sublistScoreVo, null, sublistScoreVoList, scenePackageId);
+        String sublistName = sublistScoreVo.getSublistName();
+        Double firScore = sublistScoreVo.getFirScore();
+        String firstScore = ""; // first得分
+        if (firScore != null) {
+          firstScore = saveTwoDecimalPlaces(firScore, 1).toString();
+        }
+        Double lasScore = sublistScoreVo.getLasScore();
+        String LastScore = ""; // last得分
+        if (lasScore != null) {
+          LastScore = saveTwoDecimalPlaces(lasScore, 1).toString();
+        }
+        String sceneNum = sublistScoreVo.getSceneNum(); // 场景数量
+        String errorSceneNum = sublistScoreVo.getErrorSceneNum(); // 仿真异常场景个数
+        String notScoredSceneNum = sublistScoreVo.getNotScoredSceneNum(); // 未参与评分数量
+        String notStandardSceneNum = sublistScoreVo.getNotStandardSceneNum(); // 未达标场景数量
+        String standardSceneNum = sublistScoreVo.getStandardSceneNum(); // 达标场景数量
+
+        if (ObjectUtil.isNotNull(sublistName)) {
+          sublistName += ProjectConstants.SEPARATOR + sceneNum + ProjectConstants.SEPARATOR + errorSceneNum + ProjectConstants.SEPARATOR + notScoredSceneNum + ProjectConstants.SEPARATOR + notStandardSceneNum + ProjectConstants.SEPARATOR + standardSceneNum + ProjectConstants.SEPARATOR + LastScore + ProjectConstants.SEPARATOR + firstScore;
+          String[] split = sublistName.split(ProjectConstants.SEPARATOR);
+          maxHeaderNumber = Math.max(maxHeaderNumber, split.length); // 求最大表头数量
+          result.add(Arrays.asList(split));
+        }
+      }
+    }
+    // 结果补全
+    List<SubScListVo> values = new ArrayList<>();
+    int fieldNumber = 7;
+    for (List<String> list : result) {
+      int start = list.size() - fieldNumber;
+      SubScListVo subScListVo = new SubScListVo();
+      subScListVo.setSceneNum(list.get(start));
+      subScListVo.setErrorSceneNum(list.get(start + 1));
+      subScListVo.setNotScoredSceneNum(list.get(start + 2));
+      subScListVo.setNotStandardSceneNum(list.get(start + 3));
+      subScListVo.setStandardSceneNum(list.get(start + 4));
+      subScListVo.setLastScore(list.get(start + 5));
+      subScListVo.setFirstScore(list.get(start + 6));
+      for (int i = 0; i < start; i++) {
+        if (0 == i) {
+          subScListVo.setSublistName1(list.get(i));
+        } else if (1 == i) {
+          subScListVo.setSublistName2(list.get(i));
+        } else if (2 == i) {
+          subScListVo.setSublistName3(list.get(i));
+        } else if (3 == i) {
+          subScListVo.setSublistName4(list.get(i));
+        } else if (4 == i) {
+          subScListVo.setSublistName5(list.get(i));
+        } else if (5 == i) {
+          subScListVo.setSublistName6(list.get(i));
         }
+      }
+      values.add(subScListVo);
+    }
+    List<Map<Object, Object>> headerList = new ArrayList<>();
+    for (int i = 0; i < maxHeaderNumber - fieldNumber; i++) {
+      addHeaders(i, headerList);
+    }
+    headerList.add(ImmutableMap.builder().put("label", "场景个数").put("prop", "sceneNum").build());
+    headerList.add(ImmutableMap.builder().put("label", "仿真异常场景个数").put("prop", "errorSceneNum").build());
+    headerList.add(ImmutableMap.builder().put("label", "评分失败场景个数").put("prop", "notScoredSceneNum").build());
+    headerList.add(ImmutableMap.builder().put("label", "未达标场景个数").put("prop", "notStandardSceneNum").build());
+    headerList.add(ImmutableMap.builder().put("label", "达标场景个数").put("prop", "standardSceneNum").build());
+    headerList.add(ImmutableMap.builder().put("label", "得分").put("prop", "lastScore").build());
+    headerList.add(ImmutableMap.builder().put("label", "总分").put("prop", "firstScore").build());
+    hashMap.put("headerList", headerList);
+    hashMap.put("result", values);
+
+    return hashMap;
+
+  }
+
+  /**
+   * @param po     末级指标
+   * @param pos    场景包下所有指标
+   * @param rootId 场景包id,用于判断是否根指标
+   */
+  private void setParent(SublistScoreVo po, List<SublistScoreVo> pos, String rootId) {
+    for (SublistScoreVo p : pos) {
+
+      if (po.getParentId().equals(p.getId())) {
+        // 给一级指标添加末级指标得分,给末级指标添加一级指标得分
+        if (p.getParentId().equals(rootId)) {
+          p.setLasScore(po.getLasScore());
+          po.setFirScore(p.getFirScore());
+        }
+        po.setSublistName(p.getSublistName() + "," + po.getSublistName());
+        setParent(p, pos, rootId);
+      }
 
     }
+  }
+
+  /**
+   * @param po     末级指标
+   * @param pos    场景包下所有指标
+   * @param rootId 场景包id,用于判断是否一级指标
+   */
+  private void setParent(SublistScoreVo po, SublistScoreVo parentPo, List<SublistScoreVo> pos, String rootId) {
+    // 第一次查找
+    if (parentPo == null) {
+      for (SublistScoreVo p : pos) {
+
+        setSubSc(po, p, po, pos, rootId);
+        /*
+         * if(po.getParentId().equals(p.getId())){
+         * //根指标给一级指标添加末级指标得分,给末级指标添加一级指标得分
+         * if(p.getParentId().equals(rootId)){
+         * p.setLasScore(po.getLasScore());
+         * po.setFirScore(p.getFirScore());
+         * }
+         * //末级指标拼接指标名
+         * po.setSublistName(p.getSublistName()+","+po.getSublistName());
+         * //查找上级指标,继续拼接
+         * setParent(po,p, pos, rootId);
+         *
+         * }
+         */
+      }
 
-    private List<SceneScoreVo> setSceneScore(ScenePackageSubListVO vo, String sceneIds, String sceneType, String pId) {
-        if (isEmpty(sceneIds)) {
-            return null;
-        }
-        String[] sceneIdArr = sceneIds.split(",");
-        SceneScoreParam sceneScoreParam = new SceneScoreParam();
-        sceneScoreParam.setPId(pId);
-        sceneScoreParam.setLastTargerId(vo.getSublistId());
-        sceneScoreParam.setSceneType(sceneType);
-        sceneScoreParam.setSceneIds(Arrays.asList(sceneIdArr));
-        List<SceneScoreVo> sceneScoreVos = simulationProjectTaskMapper.selectSceneScoreByIds(sceneScoreParam);
+    } else {
+      for (SublistScoreVo p : pos) {
 
-        for (SceneScoreVo s : sceneScoreVos) {
-            /*
-             * if(SceneTypeEnum.SCENE_NATURAL.getCode().equals(sceneType)){
-             * SceneBaseInfoVo sceneBaseInfoVo =
-             * simulationProjectMapper.selectSceneNatural(s.getSceneId());
-             * if(sceneBaseInfoVo != null){
-             * s.setSceneName(sceneBaseInfoVo.getNaturalName());
-             * }
-             * }else if(SceneTypeEnum.SCENE_STANDARD.getCode().equals(sceneType)){
-             * SceneBaseInfoVo sceneBaseInfoVo =
-             * simulationProjectMapper.selectSceneStandardsRegulations(s.getSceneId());
-             * if(sceneBaseInfoVo != null){
-             * s.setSceneName(sceneBaseInfoVo.getSceneName());
-             * }
-             * }else if(SceneTypeEnum.SCENE_ACCIDENT.getCode().equals(sceneType)){
-             * SceneBaseInfoVo sceneBaseInfoVo =
-             * simulationProjectMapper.selectSceneAccidentById(s.getSceneId());
-             * if(sceneBaseInfoVo != null){
-             * s.setSceneName(sceneBaseInfoVo.getSceneName());
-             * }
-             * }else if(SceneTypeEnum.SCENE_GENERAL.getCode().equals(sceneType)){
-             * ///TODO 泛化场景暂不支持
-             * 
-             * }
-             */
-            s.setSceneType(SceneTypeEnum.getState(sceneType));
-        }
+        setSubSc(parentPo, p, po, pos, rootId);
 
-        return sceneScoreVos;
+        /*
+         * //上级指标
+         * if(parentPo.getParentId().equals(p.getId())){
+         * //根指标给一级指标添加末级指标得分,给末级指标添加一级指标得分
+         * if(p.getParentId().equals(rootId)){
+         * p.setLasScore(po.getLasScore());
+         * po.setFirScore(p.getFirScore());
+         * }
+         * //末级指标拼接指标名
+         * po.setSublistName(p.getSublistName()+","+po.getSublistName());
+         * //查找上级指标,继续拼接
+         * setParent(po,p, pos, rootId);
+         * }
+         */
 
+      }
     }
 
-    /**
-     * 获取二级场景下所有得分不为 0 的场景数量
-     *
-     * @param sublistId
-     * @param pId
-     * @return
-     */
-    private Integer getSetScoreNum(String sublistId, String pId) {
-        SceneScoreVo vo = selectScoreNum(null, null, true, pId, sublistId);
-        return vo.getNum();
+  }
+
+  /**
+   * @param p1     上级指标
+   * @param p2     比对指标
+   * @param p3     末级指标
+   * @param pos    所有指标
+   * @param rootId 场景包id
+   */
+  private void setSubSc(SublistScoreVo p1, SublistScoreVo p2, SublistScoreVo p3, List<SublistScoreVo> pos, String rootId) {
+    // 上级指标
+    if (p1.getParentId().equals(p2.getId())) {
+      // 根指标给一级指标添加末级指标得分,给末级指标添加一级指标得分
+      if (p2.getParentId().equals(rootId)) {
+        p2.setLasScore(p3.getLasScore());
+        p3.setFirScore(p2.getFirScore());
+      }
+      // 末级指标拼接指标名
+      p3.setSublistName(p2.getSublistName() + ProjectConstants.SEPARATOR + p3.getSublistName());
+      // 查找上级指标,继续拼接
+      setParent(p3, p2, pos, rootId);
     }
 
-    /**
-     * 获取一级指标下所有得分不为 0 的场景总数
-     *
-     * @param resultVo     返回值,返回统计数量,首次传null
-     * @param parentVoList 首次传null
-     * @param isRoot       首次传true
-     * @param pId          项目表id,用于统计得分使用
-     * @param sublistId    指标id(用户查询指标下的所有场景)
-     * @return
-     */
-    private SceneScoreVo selectScoreNum(SceneScoreVo resultVo, List<ScenePackageSubListVO> parentVoList, boolean isRoot,
-            String pId, String sublistId) {
-        if (isRoot) {
-            // 初始化返回值
-            resultVo = new SceneScoreVo();
-            resultVo.setNum(0);
-
-            // 查找下一级指标
-            parentVoList = simulationProjectMapper.selectSubSceneByPid(sublistId);
-            if (!isEmpty(parentVoList)) {
-                selectScoreNum(resultVo, parentVoList, false, pId, null);
-            } else {
-                // 当前指标为最后一级指标,获取当前指标,统计得分场景数
-                setScoreNum(sublistId, pId, resultVo);
-            }
-
-        } else {
+  }
+
+  /*
+   */
+
+  /**
+   * 查询所有指标和得分
+   *
+   * @param
+   *//*
+   * private void selectScenePackageSubListAndSetScore(String pId, String
+   * scenePackageId, List<List<String>> resultArr, List<ScenePackageSubListVO>
+   * single){
+   *
+   * //首次,初始化数据以及赋值
+   * if(isEmpty(single)){
+   * //单个级联,按最后一级到第一级指标顺序添加
+   * single= new ArrayList<>();
+   * //查询所有指标最后一级
+   * List<ScenePackageSubListVO> vos =
+   * simulationProjectMapper.selectSubListByPid(scenePackageId);
+   * for(ScenePackageSubListVO vo : vos){
+   * selectSceneSubList(vo, pId, single, resultArr);
+   * }
+   * }
+   * //继续添加数据
+   * else{
+   * //查询父级节点,只有一个
+   * ScenePackageSubListVO vo =
+   * simulationProjectMapper.selectsublistBySublistId(scenePackageId);
+   * //如果是根节点,不再查询,组装返回数据
+   * if(vo.getSublistId().equals(scenePackageId)){
+   * if(isEmpty(resultArr)){
+   * //初始化返回数据
+   * resultArr = new ArrayList<>();
+   * List<String> singleList = new ArrayList<>();
+   * //反转list,正序添加(从一级开始)
+   * Collections.reverse(single);
+   *
+   * for(int i=0;i<single.size();i--){
+   * if(i == single.size()-1){
+   * singleList.add(String.valueOf(single.get(i).getSceneNum()));
+   * singleList.add(String.valueOf(single.get(i).getNotStandardSceneNum()));
+   * singleList.add(String.valueOf(single.get(i).getScore()));
+   *
+   * singleList.add(String.valueOf(single.get(i).getScore()));
+   *
+   * }
+   * singleList.add(single.get(i).getSublistName());
+   * }
+   *
+   *
+   *
+   *
+   *
+   *
+   * }
+   *
+   * }else{
+   * selectSceneSubList(vo, pId, single, resultArr);
+   * }
+   * }
+   *
+   * };
+   */
+
+  /*
+   * private void selectSceneSubList(ScenePackageSubListVO vo, String pId,
+   * List<ScenePackageSubListVO> single, List<List<String>> resultArr){
+   * //获取未达标个数,得分,总分
+   * setScore(vo,pId);
+   * //放入集合
+   * single.add(vo);
+   * //递归查询上级指标
+   * selectScenePackageSubListAndSetScore(pId, vo.getParentId(), resultArr,
+   * single);
+   * }
+   */
+  private void setScore(ScenePackageSubListVO vo, String pId) {
+    setLastTargetScore(vo, pId);
+    setSceneScore(vo, pId);
+  }
+
+  private void setSceneScore(ScenePackageSubListVO vo, String pId) {
+    String sceneNaturalIds = vo.getSceneNaturalIds();
+    String sceneTrafficIds = vo.getSceneTrafficIds();
+    String sceneStatueIds = vo.getSceneStatueIds();
+    List<SceneScoreVo> sceneScoreVos = new ArrayList<>();
+    List<SceneScoreVo> NaturalSceneScoreVos = setSceneScore(vo, sceneNaturalIds, DictConstants.SCENE_NATURAL, pId);
+    List<SceneScoreVo> StatueSceneScoreVos = setSceneScore(vo, sceneStatueIds, DictConstants.SCENE_STANDARD, pId);
+    List<SceneScoreVo> TrafficSceneScoreVos = setSceneScore(vo, sceneTrafficIds, DictConstants.SCENE_ACCIDENT, pId);
+    /// TODO 暂不支持泛化场景
+    List<SceneScoreVo> FhSceneScoreVos = setSceneScore(vo, sceneTrafficIds, DictConstants.SCENE_GENERAL, pId);
+
+    // 合成一个list
+    if (!isEmpty(NaturalSceneScoreVos)) {
+      sceneScoreVos.addAll(NaturalSceneScoreVos);
+    }
+    if (!isEmpty(StatueSceneScoreVos)) {
+      sceneScoreVos.addAll(StatueSceneScoreVos);
+    }
+    if (!isEmpty(TrafficSceneScoreVos)) {
+      sceneScoreVos.addAll(TrafficSceneScoreVos);
+    }
 
-            // 获取子节点集合
-            for (ScenePackageSubListVO pvo : parentVoList) {
+    if (!isEmpty(FhSceneScoreVos)) {
+      sceneScoreVos.addAll(FhSceneScoreVos);
+    }
+    vo.setSceneScoreList(sceneScoreVos);
+  }
+
+  private void setLastTargetScore(ScenePackageSubListVO vo, String pId) {
+    SimulationMptLastTargetScorePo poParam = new SimulationMptLastTargetScorePo();
+    poParam.setPId(pId);
+    poParam.setTarget(vo.getSublistId());
+    SimulationMptLastTargetScorePo po = simulationMptLastTargetScoreMapper.selectLastTargetScore(poParam);
+    if (po != null) {
+      vo.setNotStandardSceneNum(po.getNotStandardSceneNum());
+      vo.setScore(po.getScore());
+      vo.setScoreExplain(po.getScoreExplain());
+    }
 
-                List<ScenePackageSubListVO> cvoList = simulationProjectMapper.selectSubSceneByPid(pvo.getSublistId());
-                if (!isEmpty(cvoList)) {
-                    // 存入父节点集合中
-                    pvo.setChildScenePackageSubListVOList(cvoList);
-                    // 继续查找下一节点
-                    selectScoreNum(resultVo, cvoList, false, pId, null);
-                } else {
-                    // 没有子节点;获取最后一级的得分场景数量
-                    setScoreNum(pvo.getSublistId(), pId, resultVo);
+  }
 
-                }
+  private void setFirstTargetScore(ScenePackageSubListVO vo, String pId) {
+    SimulationMptFirstTargetScorePo poParam = new SimulationMptFirstTargetScorePo();
+    poParam.setPId(pId);
+    poParam.setTarget(vo.getSublistId());
+    SimulationMptFirstTargetScorePo po = simulationMptFirstTargetScoreMapper.selectFirstTargetScore(poParam);
+    if (po != null) {
+      vo.setScore(po.getScore());
+    }
 
-            }
-        }
+  }
 
-        return resultVo;
+  private List<SceneScoreVo> setSceneScore(ScenePackageSubListVO vo, String sceneIds, String sceneType, String pId) {
+    if (isEmpty(sceneIds)) {
+      return null;
     }
-
-    private void setScoreNum(String sublistId, String pId, SceneScoreVo resultVo) {
-        SimulationMptSceneScorePo po = new SimulationMptSceneScorePo();
-        po.setPId(pId);
-        po.setLastTargerId(sublistId);
-        SceneScoreVo sceneScoreVo = simulationProjectTaskMapper.selectSceneScoreNumQuery(po);
-        resultVo.setNum(resultVo.getNum() + sceneScoreVo.getNum());
+    String[] sceneIdArr = sceneIds.split(",");
+    SceneScoreParam sceneScoreParam = new SceneScoreParam();
+    sceneScoreParam.setPId(pId);
+    sceneScoreParam.setLastTargerId(vo.getSublistId());
+    sceneScoreParam.setSceneType(sceneType);
+    sceneScoreParam.setSceneIds(Arrays.asList(sceneIdArr));
+    List<SceneScoreVo> sceneScoreVos = simulationProjectTaskMapper.selectSceneScoreByIds(sceneScoreParam);
+
+    for (SceneScoreVo s : sceneScoreVos) {
+      /*
+       * if(SceneTypeEnum.SCENE_NATURAL.getCode().equals(sceneType)){
+       * SceneBaseInfoVo sceneBaseInfoVo =
+       * simulationProjectMapper.selectSceneNatural(s.getSceneId());
+       * if(sceneBaseInfoVo != null){
+       * s.setSceneName(sceneBaseInfoVo.getNaturalName());
+       * }
+       * }else if(SceneTypeEnum.SCENE_STANDARD.getCode().equals(sceneType)){
+       * SceneBaseInfoVo sceneBaseInfoVo =
+       * simulationProjectMapper.selectSceneStandardsRegulations(s.getSceneId());
+       * if(sceneBaseInfoVo != null){
+       * s.setSceneName(sceneBaseInfoVo.getSceneName());
+       * }
+       * }else if(SceneTypeEnum.SCENE_ACCIDENT.getCode().equals(sceneType)){
+       * SceneBaseInfoVo sceneBaseInfoVo =
+       * simulationProjectMapper.selectSceneAccidentById(s.getSceneId());
+       * if(sceneBaseInfoVo != null){
+       * s.setSceneName(sceneBaseInfoVo.getSceneName());
+       * }
+       * }else if(SceneTypeEnum.SCENE_GENERAL.getCode().equals(sceneType)){
+       * ///TODO 泛化场景暂不支持
+       *
+       * }
+       */
+      s.setSceneType(SceneTypeEnum.getState(sceneType));
     }
 
-    /**
-     * 计算评测等级
-     *
-     * @return
-     */
-    private String getEvaluationLevel(SimulationManualProjectPo po) {
-        /*
-         * 汇总测试得分(计算评级)计算方法:(每一项一级指标的测试得分*测试权重)累加
-         */
-        List<ScenePackageSubListVO> scenePackageSubListVOS = simulationProjectMapper.selectSubSceneByPid(po.getScene());
-
-        String evaluationLevelReport = "";
-        if (!isEmpty(scenePackageSubListVOS)) {
-            // 汇总数据初始化
-            double totalScore = 0.0;
-            for (ScenePackageSubListVO scenePackageSubListVO : scenePackageSubListVOS) {
-                double weightDouble = Double.parseDouble(scenePackageSubListVO.getWeight());
-                SimulationMptFirstTargetScorePo simulationMptFirstTargetScorePo = new SimulationMptFirstTargetScorePo();
-                simulationMptFirstTargetScorePo.setPId(po.getId());
-                simulationMptFirstTargetScorePo.setTarget(scenePackageSubListVO.getSublistId());
-                // 单个二级指标得分
-                SimulationMptFirstTargetScorePo simulationMptFirstTargetScorePo1 = simulationMptFirstTargetScoreMapper
-                        .selectFirstTargetScore(simulationMptFirstTargetScorePo);
-                if (simulationMptFirstTargetScorePo1 == null) {
-                    return evaluationLevelReport;
-                }
-                double score = simulationMptFirstTargetScorePo1.getScore();
-                totalScore += score * (weightDouble / 100);
-            }
+    return sceneScoreVos;
+
+  }
+
+  /**
+   * 获取二级场景下所有得分不为 0 的场景数量
+   *
+   * @param sublistId
+   * @param pId
+   * @return
+   */
+  private Integer getSetScoreNum(String sublistId, String pId) {
+    SceneScoreVo vo = selectScoreNum(null, null, true, pId, sublistId);
+    return vo.getNum();
+  }
+
+  /**
+   * 获取一级指标下所有得分不为 0 的场景总数
+   *
+   * @param resultVo     返回值,返回统计数量,首次传null
+   * @param parentVoList 首次传null
+   * @param isRoot       首次传true
+   * @param pId          项目表id,用于统计得分使用
+   * @param sublistId    指标id(用户查询指标下的所有场景)
+   * @return
+   */
+  private SceneScoreVo selectScoreNum(SceneScoreVo resultVo, List<ScenePackageSubListVO> parentVoList, boolean isRoot, String pId, String sublistId) {
+    if (isRoot) {
+      // 初始化返回值
+      resultVo = new SceneScoreVo();
+      resultVo.setNum(0);
+
+      // 查找下一级指标
+      parentVoList = simulationProjectMapper.selectSubSceneByPid(sublistId);
+      if (!isEmpty(parentVoList)) {
+        selectScoreNum(resultVo, parentVoList, false, pId, null);
+      } else {
+        // 当前指标为最后一级指标,获取当前指标,统计得分场景数
+        setScoreNum(sublistId, pId, resultVo);
+      }
+
+    } else {
+
+      // 获取子节点集合
+      for (ScenePackageSubListVO pvo : parentVoList) {
+
+        List<ScenePackageSubListVO> cvoList = simulationProjectMapper.selectSubSceneByPid(pvo.getSublistId());
+        if (!isEmpty(cvoList)) {
+          // 存入父节点集合中
+          pvo.setChildScenePackageSubListVOList(cvoList);
+          // 继续查找下一节点
+          selectScoreNum(resultVo, cvoList, false, pId, null);
+        } else {
+          // 没有子节点;获取最后一级的得分场景数量
+          setScoreNum(pvo.getSublistId(), pId, resultVo);
 
-            evaluationLevelReport = ProjectUtil.getEvaluationLevelReport(saveTwoDecimalPlaces(totalScore));
-            return evaluationLevelReport;
         }
 
-        return evaluationLevelReport;
+      }
+    }
 
+    return resultVo;
+  }
+
+  private void setScoreNum(String sublistId, String pId, SceneScoreVo resultVo) {
+    SimulationMptSceneScorePo po = new SimulationMptSceneScorePo();
+    po.setPId(pId);
+    po.setLastTargerId(sublistId);
+    SceneScoreVo sceneScoreVo = simulationProjectTaskMapper.selectSceneScoreNumQuery(po);
+    resultVo.setNum(resultVo.getNum() + sceneScoreVo.getNum());
+  }
+
+  /**
+   * 计算评测等级
+   *
+   * @return
+   */
+  private String getEvaluationLevel(SimulationManualProjectPo po) {
+    /*
+     * 汇总测试得分(计算评级)计算方法:(每一项一级指标的测试得分*测试权重)累加
+     */
+    List<ScenePackageSubListVO> scenePackageSubListVOS = simulationProjectMapper.selectSubSceneByPid(po.getScene());
+
+    String evaluationLevelReport = "";
+    if (!isEmpty(scenePackageSubListVOS)) {
+      // 汇总数据初始化
+      double totalScore = 0.0;
+      for (ScenePackageSubListVO scenePackageSubListVO : scenePackageSubListVOS) {
+        double weightDouble = Double.parseDouble(scenePackageSubListVO.getWeight());
+        SimulationMptFirstTargetScorePo simulationMptFirstTargetScorePo = new SimulationMptFirstTargetScorePo();
+        simulationMptFirstTargetScorePo.setPId(po.getId());
+        simulationMptFirstTargetScorePo.setTarget(scenePackageSubListVO.getSublistId());
+        // 单个二级指标得分
+        SimulationMptFirstTargetScorePo simulationMptFirstTargetScorePo1 = simulationMptFirstTargetScoreMapper.selectFirstTargetScore(simulationMptFirstTargetScorePo);
+        if (simulationMptFirstTargetScorePo1 == null) {
+          return evaluationLevelReport;
+        }
+        double score = simulationMptFirstTargetScorePo1.getScore();
+        totalScore += score * (weightDouble / 100);
+      }
+
+      evaluationLevelReport = ProjectUtil.getEvaluationLevelReport(saveTwoDecimalPlaces(totalScore));
+      return evaluationLevelReport;
     }
 
-    private void addHeaders(Integer i, List<Map<Object, Object>> header) {
-        if (0 == i) {
-            header.add(ImmutableMap.builder().put("label", "一级指标").put("prop", "sublistName1").build());
-        } else if (1 == i) {
-            header.add(ImmutableMap.builder().put("label", "二级指标").put("prop", "sublistName2").build());
-        } else if (2 == i) {
-            header.add(ImmutableMap.builder().put("label", "三级指标").put("prop", "sublistName3").build());
-        } else if (3 == i) {
-            header.add(ImmutableMap.builder().put("label", "四级指标").put("prop", "sublistName4").build());
-        } else if (4 == i) {
-            header.add(ImmutableMap.builder().put("label", "五级指标").put("prop", "sublistName5").build());
-        } else if (5 == i) {
-            header.add(ImmutableMap.builder().put("label", "六级指标").put("prop", "sublistName6").build());
-        }
-    }
-
-    // 任务运行状态统计-饼图
-    @Override
-    public ResponseBodyVO<List<Map<String, Object>>> selectRunTaskByState() {
-        String key1 = "num";
-        String key2 = "runState";
-        Map<String, Object> params = new HashMap<>();
-        params.put("createUserId", AuthUtil.getCurrentUserId());
-        List<Map<String, Object>> list = simulationProjectTaskMapper.selectRunTaskByState(params);
-        // 汉化
-        if (CollectionUtil.isNotEmpty(list)) {
-            list.forEach(map -> {
-                if (StateConstant.Aborted.getEnglish().equals(map.get(key2))) {
-                    map.put(key2, StateConstant.Aborted.getChinese());
-                }
-                if (StateConstant.PendingAnalysis.getEnglish().equals(map.get(key2))) {
-                    map.put(key2, StateConstant.PendingAnalysis.getChinese());
-                }
-                if (StateConstant.Running.getEnglish().equals(map.get(key2))) {
-                    map.put(key2, StateConstant.Running.getChinese());
-                }
-                if (StateConstant.Analysing.getEnglish().equals(map.get(key2))) {
-                    map.put(key2, StateConstant.Analysing.getChinese());
-                }
-                if (StateConstant.Completed.getEnglish().equals(map.get(key2))) {
-                    map.put(key2, StateConstant.Completed.getChinese());
-                }
-                if (StateConstant.Terminated.getEnglish().equals(map.get(key2))) {
-                    map.put(key2, StateConstant.Terminated.getChinese());
-                }
-                if (StateConstant.Terminating.getEnglish().equals(map.get(key2))) {
-                    map.put(key2, StateConstant.Terminating.getChinese());
-                }
-                if (StateConstant.Pending.getEnglish().equals(map.get(key2))) {
-                    map.put(key2, StateConstant.Pending.getChinese());
-                }
-            });
-            // 合并手动终止
-            Map<String, Object> newMap = new HashMap<>();
-            int numSum = 0;
-            final Iterator<Map<String, Object>> iterator = list.iterator();
-            while (iterator.hasNext()) {
-                final Map<String, Object> map = iterator.next();
-                if (StateConstant.Terminated.getChinese().equals(map.get(key2))) {
-                    numSum += Integer.parseInt(map.get(key1) + "");
-                    iterator.remove();
-                }
-            }
-            newMap.put(key1, numSum + "");
-            newMap.put(key2, StateConstant.Terminated.getChinese());
-            list.add(newMap);
-        }
-        return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS, list);
-    }
-
-    // 项目运行状态统计-饼图
-    @Override
-    public ResponseBodyVO<List<Map<String, Object>>> selectRunProjectByState() {
-        Map<String, Object> params = new HashMap<>();
-        params.put("createUserId", AuthUtil.getCurrentUserId());
-        // 10:未执行,20:执行中,30:执行完成,40:已中止
-        List<Map<String, Object>> list = simulationProjectMapper.selectRunProjectByState(params);
-        if (list != null && list.size() > 0) {
-            for (Map<String, Object> map : list) {
-                String nowRunState = map.get("nowRunState").toString();
-                map.put("nowRunState", getDictName(DictConstants.PROJECT_RUN_STATE, nowRunState));
-            }
-        }
-        return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS, list);
-    }
-
-    // 评测等级分布-饼图
-    @Override
-    public ResponseBodyVO<List<Map<String, Object>>> selectEvaluationLevel() {
-        String key2 = "evaluationLevel";
-        Map<String, Object> params = new HashMap<>();
-        params.put("createUserId", AuthUtil.getCurrentUserId());
-        final List<Map<String, Object>> maps = simulationProjectMapper.selectEvaluationLevel(params);
-        final Iterator<Map<String, Object>> iterator = maps.iterator();
-        while (iterator.hasNext()) {
-            final Map<String, Object> map = iterator.next();
-            if (StateConstant.G.getEnglish().equals(map.get(key2))) {
-                map.put(key2, StateConstant.G.getChinese());
-            } else if (StateConstant.A.getEnglish().equals(map.get(key2))) {
-                map.put(key2, StateConstant.A.getChinese());
-            } else if (StateConstant.M.getEnglish().equals(map.get(key2))) {
-                map.put(key2, StateConstant.M.getChinese());
-            } else if (StateConstant.P.getEnglish().equals(map.get(key2))) {
-                map.put(key2, StateConstant.P.getChinese());
-            } else {
-                iterator.remove();
-            }
-        }
-        return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS, maps);
+    return evaluationLevelReport;
+
+  }
+
+  private void addHeaders(Integer i, List<Map<Object, Object>> header) {
+    if (0 == i) {
+      header.add(ImmutableMap.builder().put("label", "一级指标").put("prop", "sublistName1").build());
+    } else if (1 == i) {
+      header.add(ImmutableMap.builder().put("label", "二级指标").put("prop", "sublistName2").build());
+    } else if (2 == i) {
+      header.add(ImmutableMap.builder().put("label", "三级指标").put("prop", "sublistName3").build());
+    } else if (3 == i) {
+      header.add(ImmutableMap.builder().put("label", "四级指标").put("prop", "sublistName4").build());
+    } else if (4 == i) {
+      header.add(ImmutableMap.builder().put("label", "五级指标").put("prop", "sublistName5").build());
+    } else if (5 == i) {
+      header.add(ImmutableMap.builder().put("label", "六级指标").put("prop", "sublistName6").build());
     }
+  }
+
+  // 任务运行状态统计-饼图
+  @Override
+  public ResponseBodyVO<List<Map<String, Object>>> selectRunTaskByState() {
+    String key1 = "num";
+    String key2 = "runState";
+    Map<String, Object> params = new HashMap<>();
+    params.put("createUserId", AuthUtil.getCurrentUserId());
+    List<Map<String, Object>> list = simulationProjectTaskMapper.selectRunTaskByState(params);
+    // 汉化
+    if (CollectionUtil.isNotEmpty(list)) {
+      list.forEach(map -> {
+        if (StateConstant.Aborted.getEnglish().equals(map.get(key2))) {
+          map.put(key2, StateConstant.Aborted.getChinese());
+        }
+        if (StateConstant.PendingAnalysis.getEnglish().equals(map.get(key2))) {
+          map.put(key2, StateConstant.PendingAnalysis.getChinese());
+        }
+        if (StateConstant.Running.getEnglish().equals(map.get(key2))) {
+          map.put(key2, StateConstant.Running.getChinese());
+        }
+        if (StateConstant.Analysing.getEnglish().equals(map.get(key2))) {
+          map.put(key2, StateConstant.Analysing.getChinese());
+        }
+        if (StateConstant.Completed.getEnglish().equals(map.get(key2))) {
+          map.put(key2, StateConstant.Completed.getChinese());
+        }
+        if (StateConstant.Terminated.getEnglish().equals(map.get(key2))) {
+          map.put(key2, StateConstant.Terminated.getChinese());
+        }
+        if (StateConstant.Terminating.getEnglish().equals(map.get(key2))) {
+          map.put(key2, StateConstant.Terminating.getChinese());
+        }
+        if (StateConstant.Pending.getEnglish().equals(map.get(key2))) {
+          map.put(key2, StateConstant.Pending.getChinese());
+        }
+      });
+      // 合并手动终止
+      Map<String, Object> newMap = new HashMap<>();
+      int numSum = 0;
+      final Iterator<Map<String, Object>> iterator = list.iterator();
+      while (iterator.hasNext()) {
+        final Map<String, Object> map = iterator.next();
+        if (StateConstant.Terminated.getChinese().equals(map.get(key2))) {
+          numSum += Integer.parseInt(map.get(key1) + "");
+          iterator.remove();
+        }
+      }
+      newMap.put(key1, numSum + "");
+      newMap.put(key2, StateConstant.Terminated.getChinese());
+      list.add(newMap);
+    }
+    return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS, list);
+  }
+
+  // 项目运行状态统计-饼图
+  @Override
+  public ResponseBodyVO<List<Map<String, Object>>> selectRunProjectByState() {
+    Map<String, Object> params = new HashMap<>();
+    params.put("createUserId", AuthUtil.getCurrentUserId());
+    // 10:未执行,20:执行中,30:执行完成,40:已中止
+    List<Map<String, Object>> list = simulationProjectMapper.selectRunProjectByState(params);
+    if (list != null && list.size() > 0) {
+      for (Map<String, Object> map : list) {
+        String nowRunState = map.get("nowRunState").toString();
+        map.put("nowRunState", getDictName(DictConstants.PROJECT_RUN_STATE, nowRunState));
+      }
+    }
+    return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS, list);
+  }
+
+  // 评测等级分布-饼图
+  @Override
+  public ResponseBodyVO<List<Map<String, Object>>> selectEvaluationLevel() {
+    String key2 = "evaluationLevel";
+    Map<String, Object> params = new HashMap<>();
+    params.put("createUserId", AuthUtil.getCurrentUserId());
+    final List<Map<String, Object>> maps = simulationProjectMapper.selectEvaluationLevel(params);
+    final Iterator<Map<String, Object>> iterator = maps.iterator();
+    while (iterator.hasNext()) {
+      final Map<String, Object> map = iterator.next();
+      if (StateConstant.G.getEnglish().equals(map.get(key2))) {
+        map.put(key2, StateConstant.G.getChinese());
+      } else if (StateConstant.A.getEnglish().equals(map.get(key2))) {
+        map.put(key2, StateConstant.A.getChinese());
+      } else if (StateConstant.M.getEnglish().equals(map.get(key2))) {
+        map.put(key2, StateConstant.M.getChinese());
+      } else if (StateConstant.P.getEnglish().equals(map.get(key2))) {
+        map.put(key2, StateConstant.P.getChinese());
+      } else {
+        iterator.remove();
+      }
+    }
+    return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS, maps);
+  }
+
+  @Override
+  @SneakyThrows
+  public void exportProjectReport(SimulationManualProjectParam param) {
+    Document document = new Document(PageSize.A4);
+    OutputStream os = null;
+    try {
+      HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
+
+      // 获取要生成的数据
+      ResponseBodyVO<ProjectReportVo> bodyVO = selectProjectReportById(param);
+      ProjectReportVo vo = bodyVO.getInfo();
+
+      // 下载 or 保存本地
+      if (param.getIsCreateLocalPdfFile() != null && param.getIsCreateLocalPdfFile()) {
+        File file = new File(param.getLocalPdfFilePath());
+        os = new BufferedOutputStream(Files.newOutputStream(file.toPath()));
+      } else {
+        // String fileName = vo.getProjectId() + "_" + vo.getProjectName();
+        String fileName = vo.getAlgorithmName() + "评价报告";
+        response.setContentType("application/x-download");
+        response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8") + ".pdf");
+        os = new BufferedOutputStream(response.getOutputStream());
+      }
+
+      // 监听生成pdf数据
+      PdfWriter instance = PdfWriter.getInstance(document, os);
+
+      // 设置监听,添加页眉以及设置页面顶部间隔
+      PdfBuilder pdfBuilder = new PdfBuilder();
+      instance.setPageEvent(pdfBuilder);
+
+      // 以下生成PDF
+      BaseFont font = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
+      document.open();
+
+      lineFeed(document, 1, 2);
+      lineFeed(document, 4, 1);
+
+      // 添加首页
+      BaseFont bf = BaseFont.createFont("fonts/simsun.ttc,1", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
+      Font f1 = new Font(bf, 48, Font.BOLD);
+      Paragraph elm1 = new Paragraph("ICV仿真云平台", f1);
+      elm1.setAlignment(Element.ALIGN_CENTER);
+      document.add(elm1);
+
+      lineFeed(document, 1, 1);
+      Font f2 = new Font(bf, 72, Font.BOLD);
+      Paragraph elm2 = new Paragraph("算法评价报告", f2);
+      elm2.setAlignment(Element.ALIGN_CENTER);
+      document.add(elm2);
+
+      // 测试时间(开始时间)
+      lineFeed(document, 16, 2);
+      Font f3 = new Font(bf, 18);
+      Paragraph elm3 = new Paragraph(vo.getStartTime(), f3);
+      elm3.setAlignment(Element.ALIGN_CENTER);
+      document.add(elm3);
+
+      // 下一页(横板)
+      document.setPageSize(PageSize.A4.rotate());
+      document.newPage();
+
+      // lineFeed(document, 2, 2);
+
+      BaseFont bf3 = BaseFont.createFont("fonts/simsun.ttc,1", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
+      addElement(document, "算法名称:", vo.getAlgorithmName(), bf3, 15, true, 0, false);
+      addElement(document, "算法得分:", vo.getAlgorithmScore().toString(), bf3, 15, true, 30, false);
+      addElement(document, "测试等级:", vo.getEvaluationLevel(), bf3, 15, true, 30, false);
+
+      BaseFont bf4 = BaseFont.createFont("fonts/simhei.ttf", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
+
+      addElement(document, "1. 算法描述与简评", null, bf4, 16, false, 40, false);
+      addElement(document, "1. 1  算法描述:", null, bf3, 15, false, 30, false);
+      addElement(document, "       " + vo.getAlgorithmDescribe(), null, bf3, 15, false, 30, false);
+      addElement(document, "1. 2  算法简评:", null, bf3, 15, false, 30, false);
+
+      // 此处为了方便直接截取 ”算法简评“ 字段后半段,不再重新获取数据
+      String algorithmEvaluation = vo.getAlgorithmEvaluation();
+      String s = algorithmEvaluation.substring(algorithmEvaluation.lastIndexOf("级评价,") + 4);
+      s = s.replace("(", "");
+      s = s.replace(")", "");
+
+      addElement(document, "       " + vo.getAlgorithmName() + "测试得分为" + vo.getAlgorithmScore() + ",依据图1-1的标准,该算法获得" + vo.getEvaluationLevel() + "级评价," + s, null, bf3, 15, false, 30, false);
+
+      Image image = Image.getInstance("classpath:icon/pjdj_new.png");
+      image.scaleAbsolute(500, 150);
+      image.setAlignment(Element.ALIGN_CENTER);
+      document.add(image);
+
+      addElement(document, "图1-1 评价标准", null, bf3, 15, false, 30, true);
+
+      addElement(document, "2. 测试得分说明", null, bf4, 16, false, 40, false);
+
+      List<AlgorithmScoreVo> algorithmScoreList = vo.getAlgorithmScoreList();
+
+      StringBuilder stringBuilder = new StringBuilder("       " + vo.getAlgorithmName() + "在");
+      for (AlgorithmScoreVo v : algorithmScoreList) {
+        if ("汇总".equals(v.getProjectName())) {
+          continue;
+        }
+        stringBuilder.append(v.getProjectName()).append("项目的").append(v.getSceneNum()).append("个场景中,测试得分为").append(v.getScore()).append(",得分率为").append(v.getScoreRatio()).append("%;");
+      }
+      String substring = stringBuilder.substring(0, stringBuilder.lastIndexOf(";"));
 
-    @Override
-    @SneakyThrows
-    public void exportProjectReport(SimulationManualProjectParam param) {
-        Document document = new Document(PageSize.A4);
-        OutputStream os = null;
-        try {
-            HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
-                    .getResponse();
+      addElement(document, substring + ",详见表2-1。", null, bf3, 15, false, 30, false);
+      addElement(document, "表2-1 测试得分表", null, bf3, 15, false, 30, true);
 
-            // 获取要生成的数据
-            ResponseBodyVO<ProjectReportVo> bodyVO = selectProjectReportById(param);
-            ProjectReportVo vo = bodyVO.getInfo();
+      // 表2-1 测试得分表
+      setBlankLineSpacing(20, font, document);
+      PdfPTable pdfPTable = new PdfPTable(5);
+      pdfPTable.setHeaderRows(1); // 换页每页显示表头
+      addTitleList(pdfPTable, font, new String[]{"测试项目", "场景数量", "测试权重(%)", "测试得分", "得分率(%)"}, true, 30);
 
-            // 下载 or 保存本地
-            if (param.getIsCreateLocalPdfFile() != null && param.getIsCreateLocalPdfFile()) {
-                File file = new File(param.getLocalPdfFilePath());
-                os = new BufferedOutputStream(Files.newOutputStream(file.toPath()));
-            } else {
-                // String fileName = vo.getProjectId() + "_" + vo.getProjectName();
-                String fileName = vo.getAlgorithmName() + "评价报告";
-                response.setContentType("application/x-download");
-                response.addHeader("Content-Disposition",
-                        "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8") + ".pdf");
-                os = new BufferedOutputStream(response.getOutputStream());
-            }
+      // 数据
+      for (AlgorithmScoreVo asv : algorithmScoreList) {
+        String[] data = new String[]{asv.getProjectName(), String.valueOf(asv.getSceneNum()), asv.getWeight(), String.valueOf(asv.getScore()), String.valueOf(asv.getScoreRatio())};
 
-            // 监听生成pdf数据
-            PdfWriter instance = PdfWriter.getInstance(document, os);
-
-            // 设置监听,添加页眉以及设置页面顶部间隔
-            PdfBuilder pdfBuilder = new PdfBuilder();
-            instance.setPageEvent(pdfBuilder);
-
-            // 以下生成PDF
-            BaseFont font = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
-            document.open();
-
-            lineFeed(document, 1, 2);
-            lineFeed(document, 4, 1);
-
-            // 添加首页
-            BaseFont bf = BaseFont.createFont("fonts/simsun.ttc,1", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
-            Font f1 = new Font(bf, 48, Font.BOLD);
-            Paragraph elm1 = new Paragraph("ICV仿真云平台", f1);
-            elm1.setAlignment(Element.ALIGN_CENTER);
-            document.add(elm1);
-
-            lineFeed(document, 1, 1);
-            Font f2 = new Font(bf, 72, Font.BOLD);
-            Paragraph elm2 = new Paragraph("算法评价报告", f2);
-            elm2.setAlignment(Element.ALIGN_CENTER);
-            document.add(elm2);
-
-            // 测试时间(开始时间)
-            lineFeed(document, 16, 2);
-            Font f3 = new Font(bf, 18);
-            Paragraph elm3 = new Paragraph(vo.getStartTime(), f3);
-            elm3.setAlignment(Element.ALIGN_CENTER);
-            document.add(elm3);
-
-            // 下一页(横板)
-            document.setPageSize(PageSize.A4.rotate());
-            document.newPage();
-
-            // lineFeed(document, 2, 2);
-
-            BaseFont bf3 = BaseFont.createFont("fonts/simsun.ttc,1", BaseFont.IDENTITY_H,
-                    BaseFont.NOT_EMBEDDED);
-            addElement(document, "算法名称:", vo.getAlgorithmName(), bf3, 15, true, 0, false);
-            addElement(document, "算法得分:", vo.getAlgorithmScore().toString(), bf3, 15, true, 30, false);
-            addElement(document, "测试等级:", vo.getEvaluationLevel(), bf3, 15, true, 30, false);
-
-            BaseFont bf4 = BaseFont.createFont("fonts/simhei.ttf", BaseFont.IDENTITY_H,
-                    BaseFont.NOT_EMBEDDED);
-
-            addElement(document, "1. 算法描述与简评", null, bf4, 16, false, 40, false);
-            addElement(document, "1. 1  算法描述:", null, bf3, 15, false, 30, false);
-            addElement(document, "       " + vo.getAlgorithmDescribe(), null, bf3, 15, false, 30, false);
-            addElement(document, "1. 2  算法简评:", null, bf3, 15, false, 30, false);
-
-            // 此处为了方便直接截取 ”算法简评“ 字段后半段,不再重新获取数据
-            String algorithmEvaluation = vo.getAlgorithmEvaluation();
-            String s = algorithmEvaluation.substring(algorithmEvaluation.lastIndexOf("级评价,") + 4);
-            s = s.replace("(", "");
-            s = s.replace(")", "");
-
-            addElement(document, "       " + vo.getAlgorithmName() + "测试得分为" + vo.getAlgorithmScore() +
-                    ",依据图1-1的标准,该算法获得" + vo.getEvaluationLevel() + "级评价," + s, null, bf3,
-                    15, false, 30, false);
-
-            Image image = Image.getInstance("classpath:icon/pjdj_new.png");
-            image.scaleAbsolute(500, 150);
-            image.setAlignment(Element.ALIGN_CENTER);
-            document.add(image);
-
-            addElement(document, "图1-1 评价标准", null, bf3, 15, false, 30, true);
-
-            addElement(document, "2. 测试得分说明", null, bf4, 16, false, 40, false);
-
-            List<AlgorithmScoreVo> algorithmScoreList = vo.getAlgorithmScoreList();
-
-            StringBuilder stringBuilder = new StringBuilder("       " + vo.getAlgorithmName() + "在");
-            for (AlgorithmScoreVo v : algorithmScoreList) {
-                if ("汇总".equals(v.getProjectName())) {
-                    continue;
-                }
-                stringBuilder.append(v.getProjectName()).append("项目的").append(v.getSceneNum()).append("个场景中,测试得分为")
-                        .append(v.getScore()).append(",得分率为").append(v.getScoreRatio()).append("%;");
-            }
-            String substring = stringBuilder.substring(0, stringBuilder.lastIndexOf(";"));
-
-            addElement(document, substring + ",详见表2-1。", null, bf3, 15, false, 30, false);
-            addElement(document, "表2-1 测试得分表", null, bf3, 15, false, 30, true);
-
-            // 表2-1 测试得分表
-            setBlankLineSpacing(20, font, document);
-            PdfPTable pdfPTable = new PdfPTable(5);
-            pdfPTable.setHeaderRows(1); // 换页每页显示表头
-            addTitleList(pdfPTable, font,
-                    new String[] { "测试项目", "场景数量", "测试权重(%)", "测试得分", "得分率(%)" }, true, 30);
-
-            // 数据
-            for (AlgorithmScoreVo asv : algorithmScoreList) {
-                String[] data = new String[] {
-                        asv.getProjectName(),
-                        String.valueOf(asv.getSceneNum()),
-                        asv.getWeight(),
-                        String.valueOf(asv.getScore()),
-                        String.valueOf(asv.getScoreRatio())
-                };
-
-                addDataList(pdfPTable, font, data, true, 20);
-            }
-            document.add(pdfPTable);
-
-            addElement(document, "3. 算法测试评分情况", null, bf4, 16, false, 40, false);
-            addElement(document, "       为排除其他因素的干扰,科学评价算法效果,本报告将测试场景分为仿真异常场景、未参与评分场景、未达标场景和达标场景4类:", null, bf3, 15,
-                    false, 30, false);
-            addElement(document, "       1. 仿真异常场景指的是在仿真过程中报自动终止错误的场景,参与得分权重,测试结果均赋0分;", null, bf3, 15, false, 30,
-                    false);
-            addElement(document, "       2. 评分失败场景是指因为场景与评分规则不匹配导致程序报错无法对仿真结果进行打分的场景,参与得分权重,测试结果均赋0分;", null, bf3, 15,
-                    false, 30, false);
-            addElement(document, "       3. 未达标场景是指仿真测试未得到满分的场景;", null, bf3, 15, false, 30, false);
-            addElement(document, "       4. 达标场景是指仿真测试得到满分的场景。", null, bf3, 15, false, 30, false);
-            addElement(document, "       算法在本次场景测试包中的表现见表3-1.", null, bf3, 15, false, 30, false);
-            addElement(document, "表3-1 算法测试评分细则", null, bf3, 15, false, 30, true);
-
-            // * -------------------------------- 算法评分细则 --------------------------------
-
-            setBlankLineSpacing(20, font, document);
-
-            List<Map> subListScoreLiTitle = vo.getSubListScoreLiTitle();
-            int size = subListScoreLiTitle.size();
-            // 表3-1 算法评分细则
-            PdfPTable pdfPTable2 = new PdfPTable(size);
-            pdfPTable2.setHeaderRows(1);
-            String[] slt = new String[size];
-            for (int i = 0; i < size; i++) {
-                slt[i] = subListScoreLiTitle.get(i).get("label").toString();
-            }
-            addTitleList(pdfPTable2, font, slt, true, 40);
-
-            List<SubScListVo> subListScoreLi = vo.getSubListScoreLi();
-
-            List<String[]> list = new ArrayList<>();
-            for (SubScListVo slv : subListScoreLi) {
-                String[] slsi = new String[size];
-                for (int i = 0; i < size; i++) {
-                    slsi[i] = "";
-                }
-                // 目前最多支持到6级指标
-                for (int i = 0; i < size - 4; i++) {
-                    if (i == 0) {
-                        if (slv.getSublistName1() != null) {
-                            slsi[i] = slv.getSublistName1();
-                        }
-
-                    } else if (i == 1) {
-                        if (slv.getSublistName2() != null) {
-                            slsi[i] = slv.getSublistName2();
-                        }
-
-                    } else if (i == 2) {
-                        if (slv.getSublistName3() != null) {
-                            slsi[i] = slv.getSublistName3();
-                        }
-
-                    } else if (i == 3) {
-                        if (slv.getSublistName4() != null) {
-                            slsi[i] = slv.getSublistName4();
-                        }
-
-                    } else if (i == 4) {
-                        if (slv.getSublistName5() != null) {
-                            slsi[i] = slv.getSublistName5();
-                        }
-
-                    } else if (i == 5) {
-                        if (slv.getSublistName6() != null) {
-                            slsi[i] = slv.getSublistName6();
-                        }
-
-                    }
-                }
-                slsi[size - 7] = slv.getSceneNum();
-                slsi[size - 6] = slv.getErrorSceneNum();
-                slsi[size - 5] = slv.getNotScoredSceneNum();
-                slsi[size - 4] = slv.getNotStandardSceneNum();
-                slsi[size - 3] = slv.getStandardSceneNum();
-                slsi[size - 2] = slv.getLastScore();
-                slsi[size - 1] = slv.getFirstScore();
-
-                list.add(slsi);
-
-                // addDataList(pdfPTable2, font, slsi);
-            }
+        addDataList(pdfPTable, font, data, true, 20);
+      }
+      document.add(pdfPTable);
 
-            Map map = getSubScListCombineCoord(subListScoreLi, size);
-
-            Map<String, Integer> combineCoordList = (Map<String, Integer>) map.get("combineCoordList");
-            List<String> skipCoordList = (List<String>) map.get("skipCoordList");
-
-            for (int i = 0; i < list.size(); i++) {
-                String[] strings = list.get(i);
-                for (int j = 0; j < strings.length; j++) {
-                    String coord = i + "," + j;
-
-                    // 是否要跳过
-                    boolean contains = skipCoordList.contains(coord);
-                    if (contains) {
-                        continue;
-                    }
-                    PdfPCell pdfPCell = new PdfPCell(new Paragraph(strings[j], defaultFont(font)));
-
-                    // 是否要合并
-                    Integer n = combineCoordList.get(coord);
-                    if (n != null) {
-                        pdfPCell.setRowspan(n);
-                    } else {
-                        pdfPCell.setFixedHeight(20);
-                    }
-                    addCell(pdfPTable2, pdfPCell, true);
-                }
-            }
-            document.add(pdfPTable2);
-
-            // ------- 4.详细得分说明 -------
-
-            /*
-             * //新的一页,横向显示
-             * document.setPageSize(PageSize.A4.rotate());
-             * document.newPage();
-             */
-            // lineFeed(document, 2, 2);
-            List<Map> scoreLiTitle = vo.getSceneScoreLiTitle();
-            List<SceneScListVo> sceneScoreLi = vo.getSceneScoreLi();
-            addElement(document, "4. 详细场景得分说明", null, bf4, 16, false, 40, false);
-            StringBuffer s1 = new StringBuffer("       " + vo.getAlgorithmName());
-            /*
-             * boolean b = true;
-             * for (int i = 0; i < size1; i++) {
-             * AlgorithmScoreVo v = algorithmScoreList.get(i);
-             * Double score = v.getScore();
-             * if (100 > score) {
-             * b = false;
-             * break;
-             * }
-             * }
-             */
-            String substring1 = "";
-            // StringBuffer stringBuffer2 = new StringBuffer(" ");
-            // 末级指标
-            // 先对末级指标进行分组
-            LinkedHashMap<String, List<SceneScListVo>> map1 = new LinkedHashMap<>();
-            for (SceneScListVo sc : sceneScoreLi) {
-                String lastZbName = "";
-                // 最多支持到6级指标
-                lastZbName = sc.getSublistName1();
-                if (StringUtil.isNotEmpty(sc.getSublistName2())) {
-                    lastZbName = sc.getSublistName2();
-                }
-                if (StringUtil.isNotEmpty(sc.getSublistName3())) {
-                    lastZbName = sc.getSublistName3();
-                }
-                if (StringUtil.isNotEmpty(sc.getSublistName4())) {
-                    lastZbName = sc.getSublistName4();
-                }
-                if (StringUtil.isNotEmpty(sc.getSublistName5())) {
-                    lastZbName = sc.getSublistName5();
-                }
-                if (StringUtil.isNotEmpty(sc.getSublistName6())) {
-                    lastZbName = sc.getSublistName6();
-                }
-
-                List<SceneScListVo> listVos = map1.get(lastZbName);
-                if (listVos == null) {
-                    listVos = new ArrayList<>();
-                    listVos.add(sc);
-                    map1.put(lastZbName, listVos);
-                } else {
-                    listVos.add(sc);
-                }
-            }
-            StringBuffer deFenShuoMing = new StringBuffer("       " + vo.getAlgorithmName());
-            for (String m : map1.keySet()) {
-                List<SceneScListVo> sceneScListVos = map1.get(m);
-                int size2 = sceneScListVos.size();
-                int xy100b = 0;
-                for (SceneScListVo sc1 : sceneScListVos) {
-                    String sceneScore = sc1.getSceneScore();
-                    BigDecimal score = new BigDecimal("0");
-                    if (sceneScore != null && !"".equals(sceneScore)) {
-                        try {
-                            score = new BigDecimal(sceneScore);
-                        } catch (Exception e) {
-                            score = new BigDecimal("0");
-                        }
-
-                    }
-                    int r = score.compareTo(new BigDecimal("100"));
-                    // 小于100
-                    if (r < 0) {
-                        xy100b++;
-                        deFenShuoMing.append("在" + m + "指标中的" + sc1.getSceneId() + "中,测试得分为" + sceneScore + ";");
-                    }
-
-                }
-                if (xy100b == 0) {
-                    deFenShuoMing.append("在" + m + "指标中的" + sceneScListVos.size() + "个场景均表现优秀,测试得分100分。");
-                } else {
-                    int num = size2 - xy100b;
-                    if (num != 0) {
-                        deFenShuoMing.append("其他" + num + "个场景表现优秀,测试得分100分。");
-                    } else {
-                        deFenShuoMing = new StringBuffer(
-                                deFenShuoMing.substring(0, deFenShuoMing.lastIndexOf(";")) + "。");
-                    }
-                }
-            }
-            substring1 = deFenShuoMing.append("详见表4-1。").toString();
-
-            /*
-             * if (b) {
-             * //得分都为100,取末级指标
-             * for (int i = 0; i < size1; i++) {
-             * AlgorithmScoreVo v = algorithmScoreList.get(i);
-             * if ("汇总".equals(v.getProjectName())) {
-             * continue;
-             * }
-             * stringBuffer2.append(vo.getAlgorithmName() + "在指标中的" + v.getSceneNum() +
-             * "个场景均表现良好,测试得分为" + v.getScore() +
-             * ";");
-             * }
-             * substring1 = stringBuffer2.substring(0, stringBuffer2.lastIndexOf(";"));
-             * substring1 += "。详见表4-1。";
-             * 
-             * } else {
-             * //得分有小于100的,取末级指标
-             * for (int i = 0; i < size1; i++) {
-             * AlgorithmScoreVo v = algorithmScoreList.get(i);
-             * if ("汇总".equals(v.getProjectName())) {
-             * continue;
-             * }
-             * Integer sceneNum = v.getSceneNum();
-             * String projectName = v.getProjectName();
-             * 
-             * for (SceneScListVo v1 : sceneScoreLi) {
-             * if (projectName.equals(v1.getSublistName1())) {
-             * String sceneScore = v1.getSceneScore();
-             * BigDecimal score = new BigDecimal("0");
-             * if (sceneScore != null && !"".equals(sceneScore)) {
-             * try {
-             * score = new BigDecimal(sceneScore);
-             * } catch (Exception e) {
-             * score = new BigDecimal("0");
-             * }
-             * 
-             * }
-             * int r = score.compareTo(new BigDecimal("100"));
-             * if (r == -1) {
-             * stringBuffer2.append(vo.getAlgorithmName() + "在" + v1.getSublistName1() +
-             * "指标中的" + v1.getSceneId() + "中," + "测试得分为" + v1.getSceneScore() + ";");
-             * sceneNum--;
-             * }
-             * }
-             * }
-             * substring1 = stringBuffer2.substring(0, stringBuffer2.lastIndexOf(";"));
-             * if (sceneNum > 0) {
-             * substring1 += ",在其他" + sceneNum + "个场景表现良好,测试得分100分";
-             * } else {
-             * substring1 += "。详见表4-1。";
-             * }
-             * 
-             * 
-             * }
-             * 
-             * }
-             */
-
-            addElement(document, substring1, null, bf3, 15, false, 30, false);
-            addElement(document, "表4-1 详细得分情况", null, bf3, 15, false, 30, true);
-
-            /*
-             * 详细得分情况
-             */
-            /*
-             * Paragraph sceneScoreElements = new Paragraph(
-             * 50,
-             * "详细得分情况",
-             * defaultFont(font));
-             * sceneScoreElements.setAlignment(Element.ALIGN_CENTER); //居中
-             * document.add(sceneScoreElements);
-             */
-
-            setBlankLineSpacing(20, font, document);
-
-            // List<Map> scoreLiTitle = vo.getSceneScoreLiTitle();
-            int size2 = scoreLiTitle.size();
-            PdfPTable pdfPTable3 = new PdfPTable(size2);
-            pdfPTable3.setSplitLate(false);
-            pdfPTable3.setHeaderRows(1);
-            String[] slt2 = new String[size2];
-            for (int i = 0; i < size2; i++) {
-                slt2[i] = scoreLiTitle.get(i).get("label").toString();
-            }
-            addTitleList(pdfPTable3, font, slt2, true, 30);
-
-            List<String[]> list2 = new ArrayList<>();
-
-            for (SceneScListVo sslv : sceneScoreLi) {
-                String[] ssli = new String[size2];
-                for (int i = 0; i < size2; i++) {
-                    ssli[i] = "";
-                }
-                // 目前最多支持到6级指标
-                for (int i = 0; i < size2 - 5; i++) {
-                    if (i == 0) {
-                        if (sslv.getSublistName1() != null) {
-                            ssli[i] = sslv.getSublistName1();
-                        }
-
-                    } else if (i == 1) {
-                        if (sslv.getSublistName2() != null) {
-                            ssli[i] = sslv.getSublistName2();
-                        }
-
-                    } else if (i == 2) {
-                        if (sslv.getSublistName3() != null) {
-                            ssli[i] = sslv.getSublistName3();
-                        }
-
-                    } else if (i == 3) {
-                        if (sslv.getSublistName4() != null) {
-                            ssli[i] = sslv.getSublistName4();
-                        }
-
-                    } else if (i == 4) {
-                        if (sslv.getSublistName5() != null) {
-                            ssli[i] = sslv.getSublistName5();
-                        }
-
-                    } else if (i == 5) {
-                        if (sslv.getSublistName6() != null) {
-                            ssli[i] = sslv.getSublistName6();
-                        }
-
-                    }
-                }
-                ssli[size2 - 5] = sslv.getSceneId();
-                ssli[size2 - 4] = sslv.getSceneIdType();
-                ssli[size2 - 3] = sslv.getSceneScore();
-                ssli[size2 - 2] = sslv.getTargetEvaluate();
-                ssli[size2 - 1] = sslv.getScoreExplain();
-
-                list2.add(ssli);
-
-                // addDataList(pdfPTable3, font, ssli);
-            }
+      addElement(document, "3. 算法测试评分情况", null, bf4, 16, false, 40, false);
+      addElement(document, "       为排除其他因素的干扰,科学评价算法效果,本报告将测试场景分为仿真异常场景、未参与评分场景、未达标场景和达标场景4类:", null, bf3, 15, false, 30, false);
+      addElement(document, "       1. 仿真异常场景指的是在仿真过程中报自动终止错误的场景,参与得分权重,测试结果均赋0分;", null, bf3, 15, false, 30, false);
+      addElement(document, "       2. 评分失败场景是指因为场景与评分规则不匹配导致程序报错无法对仿真结果进行打分的场景,参与得分权重,测试结果均赋0分;", null, bf3, 15, false, 30, false);
+      addElement(document, "       3. 未达标场景是指仿真测试未得到满分的场景;", null, bf3, 15, false, 30, false);
+      addElement(document, "       4. 达标场景是指仿真测试得到满分的场景。", null, bf3, 15, false, 30, false);
+      addElement(document, "       算法在本次场景测试包中的表现见表3-1.", null, bf3, 15, false, 30, false);
+      addElement(document, "表3-1 算法测试评分细则", null, bf3, 15, false, 30, true);
 
-            Map map2 = getSceneScListCombineCoord(sceneScoreLi, size2);
-
-            Map<String, Integer> combineCoordList2 = (Map<String, Integer>) map2.get("combineCoordList");
-            List<String> skipCoordList2 = (List<String>) map2.get("skipCoordList");
-
-            boolean b2 = false;
-            int num2 = 0;
-            for (int i = 0; i < list2.size(); i++) {
-                String[] strings = list2.get(i);
-                for (int j = 0; j < strings.length; j++) {
-                    String coord = i + "," + j;
-
-                    // 是否要跳过
-                    boolean contains = skipCoordList2.contains(coord);
-                    if (contains) {
-                        continue;
-                    }
-                    PdfPCell pdfPCell = new PdfPCell(new Paragraph(strings[j], defaultFont(font)));
-                    // 是否要合并
-                    Integer n = combineCoordList2.get(coord);
-                    if (n != null) {
-                        pdfPCell.setRowspan(n);
-                    }
-                    addCell(pdfPTable3, pdfPCell, true);
-                }
-            }
+      // * -------------------------------- 算法评分细则 --------------------------------
 
-            document.add(pdfPTable3);
-
-            /*
-             * //标题
-             * Font titleFont = new Font(font, 20); //字体
-             * Paragraph titleElements = new Paragraph("评价报告",titleFont);
-             * titleElements.setAlignment(Element.ALIGN_CENTER); //居中
-             * document.add(titleElements);
-             * 
-             * 
-             * //算法名称、算法得分、测试等级
-             * Paragraph algorithmNanmeElements = new Paragraph(
-             * 50,
-             * "          算法名称:"+vo.getAlgorithmName()
-             * +"         算法得分:"+vo.getAlgorithmScore()
-             * +"         测试等级:"+vo.getEvaluationLevel(),
-             * defaultFont(font));
-             * algorithmNanmeElements.setAlignment(Element.ALIGN_LEFT); //靠左
-             * document.add(algorithmNanmeElements);
-             * 
-             * 
-             * //算法描述
-             * Paragraph algorithmDescribeFontElements = new Paragraph(
-             * 30,
-             * "          算法描述:"+vo.getAlgorithmDescribe(),
-             * defaultFont(font));
-             * algorithmDescribeFontElements.setAlignment(Element.ALIGN_LEFT); //居中
-             * document.add(algorithmDescribeFontElements);
-             * 
-             * //算法简评
-             * Font algorithmEvaluateFont = new Font(font, 14); //字体
-             * Paragraph algorithmEvaluateElements = new Paragraph(
-             * 30,
-             * "          算法简评:"+vo.getAlgorithmEvaluation(),
-             * algorithmEvaluateFont);
-             * algorithmEvaluateElements.setAlignment(Element.ALIGN_LEFT); //居中
-             * document.add(algorithmEvaluateElements);
-             */
-
-            /*
-             * 测试得分表
-             *//*
-                * Paragraph scoreTableElements = new Paragraph(
-                * 50,
-                * "测试得分表",
-                * defaultFont(font));
-                * scoreTableElements.setAlignment(Element.ALIGN_CENTER); //居中
-                * document.add(scoreTableElements);
-                * 
-                * setBlankLineSpacing(20,font,document);
-                * 
-                * //表头
-                * PdfPTable pdfPTable = new PdfPTable(5);
-                * pdfPTable.setHeaderRows(1);//换页每页显示表头
-                * addTitleList(pdfPTable, font, new
-                * String[]{"测试项目","场景数量","测试权重(%)","测试得分","得分率(%)"});
-                * 
-                * //数据
-                * // List<AlgorithmScoreVo> algorithmScoreList = vo.getAlgorithmScoreList();
-                * for(AlgorithmScoreVo asv : algorithmScoreList){
-                * String[] data = new String[]{
-                * asv.getProjectName(), String.valueOf(asv.getSceneNum()), asv.getWeight(),
-                * String.valueOf(asv.getScore()), String.valueOf(asv.getScoreRatio())
-                * };
-                * 
-                * addDataList(pdfPTable, font, data);
-                * }
-                * document.add(pdfPTable);
-                */
-
-            /*
-             * 评价等级
-             */
-            /*
-             * Paragraph levelTableElements = new Paragraph(
-             * 50,
-             * "评价等级",
-             * defaultFont(font));
-             * levelTableElements.setAlignment(Element.ALIGN_CENTER); //居中
-             * document.add(levelTableElements);
-             * 
-             * setBlankLineSpacing(20,font,document);
-             * 
-             * PdfPTable pdfPTable1 = new PdfPTable(5);
-             * addTitleList(pdfPTable1, font, new
-             * String[]{"测试项目","90<总分<100","80<总分<90","70<总分<80","0<总分<70"});
-             * addDataList(pdfPTable1, font, new
-             * String[]{"评价等级","优秀(G)","良好(A)","一般(M)","较差(P)",
-             * "评价等级","++++++","+++++","++++","+++",});
-             * document.add(pdfPTable1);
-             */
-
-            /*
-             * //新的一页,横向显示
-             * document.setPageSize(PageSize.A4.rotate());
-             * document.newPage();
-             */
-
-            // 指标得分列表
-            /*
-             * Paragraph subListScoreElements = new Paragraph(
-             * 50,
-             * "算法测试评分细则",
-             * defaultFont(font));
-             * subListScoreElements.setAlignment(Element.ALIGN_CENTER); //居中
-             * document.add(subListScoreElements);
-             * 
-             * setBlankLineSpacing(20,font,document);
-             * 
-             * List<Map> subListScoreLiTitle = vo.getSubListScoreLiTitle();
-             * int size = subListScoreLiTitle.size();
-             * PdfPTable pdfPTable2 = new PdfPTable(size);
-             * pdfPTable2.setHeaderRows(1);
-             * String[] slt = new String[size];
-             * for(int i=0; i<size; i++){
-             * slt[i] = subListScoreLiTitle.get(i).get("label").toString();
-             * }
-             * addTitleList(pdfPTable2, font, slt);
-             * 
-             * List<SubScListVo> subListScoreLi = vo.getSubListScoreLi();
-             * 
-             * List<String[]> list = new ArrayList<>();
-             * for(SubScListVo slv : subListScoreLi){
-             * String[] slsi = new String[size];
-             * for(int i=0;i<size;i++){
-             * slsi[i] = "";
-             * }
-             * //目前最多支持到6级指标
-             * for(int i=0; i<size-4; i++){
-             * if(i==0){
-             * if(slv.getSublistName1() != null){
-             * slsi[i] = slv.getSublistName1();
-             * }
-             * 
-             * }else if(i==1){
-             * if(slv.getSublistName2() != null){
-             * slsi[i] = slv.getSublistName2();
-             * }
-             * 
-             * }else if(i==2){
-             * if(slv.getSublistName3() != null){
-             * slsi[i] = slv.getSublistName3();
-             * }
-             * 
-             * }else if(i==3){
-             * if(slv.getSublistName4() != null){
-             * slsi[i] = slv.getSublistName4();
-             * }
-             * 
-             * }else if(i==4){
-             * if(slv.getSublistName5() != null){
-             * slsi[i] = slv.getSublistName5();
-             * }
-             * 
-             * }else if(i==5){
-             * if(slv.getSublistName6() != null){
-             * slsi[i] = slv.getSublistName6();
-             * }
-             * 
-             * }
-             * }
-             * slsi[size-4] = slv.getSceneNum();
-             * slsi[size-3] = slv.getNotStandardSceneNum();
-             * slsi[size-2] = slv.getLastScore();
-             * slsi[size-1] = slv.getFirstScore();
-             * 
-             * list.add(slsi);
-             * 
-             * // addDataList(pdfPTable2, font, slsi);
-             * }
-             * 
-             * 
-             * Map map = getSubScListCombineCoord(subListScoreLi, size);
-             * 
-             * Map<String, Integer> combineCoordList = (Map<String, Integer>)
-             * map.get("combineCoordList");
-             * List<String> skipCoordList = (List<String>) map.get("skipCoordList");
-             * 
-             * for(int i=0; i<list.size();i++){
-             * String[] strings = list.get(i);
-             * for(int j=0; j<strings.length; j++){
-             * String coord = i+","+j;
-             * 
-             * //是否要跳过
-             * boolean contains = skipCoordList.contains(coord);
-             * if(contains){
-             * continue;
-             * }
-             * PdfPCell pdfPCell = new PdfPCell(new
-             * Paragraph(strings[j],defaultFont(font)));
-             * 
-             * //是否要合并
-             * Integer n = combineCoordList.get(coord);
-             * if(n != null){
-             * pdfPCell.setRowspan(n);
-             * }
-             * 
-             * pdfPTable2.addCell(pdfPCell);
-             * 
-             * 
-             * }
-             * }
-             * 
-             * document.add(pdfPTable2);
-             */
-
-            /*
-             * 场景得分列表
-             */
-            /*
-             * Paragraph sceneScoreElements = new Paragraph(
-             * 50,
-             * "详细得分情况",
-             * defaultFont(font));
-             * sceneScoreElements.setAlignment(Element.ALIGN_CENTER); //居中
-             * document.add(sceneScoreElements);
-             * 
-             * setBlankLineSpacing(20,font,document);
-             * 
-             * List<Map> scoreLiTitle = vo.getSceneScoreLiTitle();
-             * int size2 = scoreLiTitle.size();
-             * PdfPTable pdfPTable3 = new PdfPTable(size2);
-             * pdfPTable3.setHeaderRows(1);
-             * String[] slt2 = new String[size2];
-             * for(int i=0; i<size2; i++){
-             * slt2[i] = scoreLiTitle.get(i).get("label").toString();
-             * }
-             * addTitleList(pdfPTable3, font, slt2);
-             * List<SceneScListVo> sceneScoreLi = vo.getSceneScoreLi();
-             * 
-             * List<String[]> list2 = new ArrayList<>();
-             * 
-             * for(SceneScListVo sslv : sceneScoreLi){
-             * String[] ssli = new String[size2];
-             * for(int i=0;i<size2;i++){
-             * ssli[i] = "";
-             * }
-             * //目前最多支持到6级指标
-             * for(int i=0; i<size2-5; i++){
-             * if(i==0){
-             * if(sslv.getSublistName1() != null){
-             * ssli[i] = sslv.getSublistName1();
-             * }
-             * 
-             * }else if(i==1){
-             * if(sslv.getSublistName2() != null){
-             * ssli[i] = sslv.getSublistName2();
-             * }
-             * 
-             * }else if(i==2){
-             * if(sslv.getSublistName3() != null){
-             * ssli[i] = sslv.getSublistName3();
-             * }
-             * 
-             * }else if(i==3){
-             * if(sslv.getSublistName4() != null){
-             * ssli[i] = sslv.getSublistName4();
-             * }
-             * 
-             * }else if(i==4){
-             * if(sslv.getSublistName5() != null){
-             * ssli[i] = sslv.getSublistName5();
-             * }
-             * 
-             * }else if(i==5){
-             * if(sslv.getSublistName6() != null){
-             * ssli[i] = sslv.getSublistName6();
-             * }
-             * 
-             * }
-             * }
-             * ssli[size2-5] = sslv.getSceneId();
-             * ssli[size2-4] = sslv.getSceneIdType();
-             * ssli[size2-3] = sslv.getSceneScore();
-             * ssli[size2-2] = sslv.getTargetEvaluate();
-             * ssli[size2-1] = sslv.getScoreExplain();
-             * 
-             * list2.add(ssli);
-             * 
-             * // addDataList(pdfPTable3, font, ssli);
-             * }
-             * 
-             * Map map2 = getSceneScListCombineCoord(sceneScoreLi, size2);
-             * 
-             * Map<String, Integer> combineCoordList2 = (Map<String, Integer>)
-             * map2.get("combineCoordList");
-             * List<String> skipCoordList2 = (List<String>) map2.get("skipCoordList");
-             * 
-             * boolean b2 = false;
-             * int num2 = 0;
-             * for(int i=0; i<list2.size();i++){
-             * String[] strings = list2.get(i);
-             * for(int j=0; j<strings.length; j++){
-             * String coord = i+","+j;
-             * 
-             * //是否要跳过
-             * boolean contains = skipCoordList2.contains(coord);
-             * if(contains){
-             * continue;
-             * }
-             * PdfPCell pdfPCell = new PdfPCell(new
-             * Paragraph(strings[j],defaultFont(font)));
-             * //是否要合并
-             * Integer n = combineCoordList2.get(coord);
-             * if(n != null){
-             * pdfPCell.setRowspan(n);
-             * }
-             * 
-             * pdfPTable3.addCell(pdfPCell);
-             * 
-             * 
-             * }
-             * }
-             * 
-             * document.add(pdfPTable3);
-             */
-
-        } catch (Exception e) {
-            e.printStackTrace();
-
-        } finally {
-            document.close();
+      setBlankLineSpacing(20, font, document);
+
+      List<Map> subListScoreLiTitle = vo.getSubListScoreLiTitle();
+      int size = subListScoreLiTitle.size();
+      // 表3-1 算法评分细则
+      PdfPTable pdfPTable2 = new PdfPTable(size);
+      pdfPTable2.setHeaderRows(1);
+      String[] slt = new String[size];
+      for (int i = 0; i < size; i++) {
+        slt[i] = subListScoreLiTitle.get(i).get("label").toString();
+      }
+      addTitleList(pdfPTable2, font, slt, true, 40);
+
+      List<SubScListVo> subListScoreLi = vo.getSubListScoreLi();
+
+      List<String[]> list = new ArrayList<>();
+      for (SubScListVo slv : subListScoreLi) {
+        String[] slsi = new String[size];
+        for (int i = 0; i < size; i++) {
+          slsi[i] = "";
+        }
+        // 目前最多支持到6级指标
+        for (int i = 0; i < size - 4; i++) {
+          if (i == 0) {
+            if (slv.getSublistName1() != null) {
+              slsi[i] = slv.getSublistName1();
+            }
+
+          } else if (i == 1) {
+            if (slv.getSublistName2() != null) {
+              slsi[i] = slv.getSublistName2();
+            }
+
+          } else if (i == 2) {
+            if (slv.getSublistName3() != null) {
+              slsi[i] = slv.getSublistName3();
+            }
+
+          } else if (i == 3) {
+            if (slv.getSublistName4() != null) {
+              slsi[i] = slv.getSublistName4();
+            }
+
+          } else if (i == 4) {
+            if (slv.getSublistName5() != null) {
+              slsi[i] = slv.getSublistName5();
+            }
+
+          } else if (i == 5) {
+            if (slv.getSublistName6() != null) {
+              slsi[i] = slv.getSublistName6();
+            }
+
+          }
+        }
+        slsi[size - 7] = slv.getSceneNum();
+        slsi[size - 6] = slv.getErrorSceneNum();
+        slsi[size - 5] = slv.getNotScoredSceneNum();
+        slsi[size - 4] = slv.getNotStandardSceneNum();
+        slsi[size - 3] = slv.getStandardSceneNum();
+        slsi[size - 2] = slv.getLastScore();
+        slsi[size - 1] = slv.getFirstScore();
+
+        list.add(slsi);
+
+        // addDataList(pdfPTable2, font, slsi);
+      }
+
+      Map map = getSubScListCombineCoord(subListScoreLi, size);
+
+      Map<String, Integer> combineCoordList = (Map<String, Integer>) map.get("combineCoordList");
+      List<String> skipCoordList = (List<String>) map.get("skipCoordList");
+
+      for (int i = 0; i < list.size(); i++) {
+        String[] strings = list.get(i);
+        for (int j = 0; j < strings.length; j++) {
+          String coord = i + "," + j;
+
+          // 是否要跳过
+          boolean contains = skipCoordList.contains(coord);
+          if (contains) {
+            continue;
+          }
+          PdfPCell pdfPCell = new PdfPCell(new Paragraph(strings[j], defaultFont(font)));
+
+          // 是否要合并
+          Integer n = combineCoordList.get(coord);
+          if (n != null) {
+            pdfPCell.setRowspan(n);
+          } else {
+            pdfPCell.setFixedHeight(20);
+          }
+          addCell(pdfPTable2, pdfPCell, true);
+        }
+      }
+      document.add(pdfPTable2);
+
+      // ------- 4.详细得分说明 -------
+
+      /*
+       * //新的一页,横向显示
+       * document.setPageSize(PageSize.A4.rotate());
+       * document.newPage();
+       */
+      // lineFeed(document, 2, 2);
+      List<Map> scoreLiTitle = vo.getSceneScoreLiTitle();
+      List<SceneScListVo> sceneScoreLi = vo.getSceneScoreLi();
+      addElement(document, "4. 详细场景得分说明", null, bf4, 16, false, 40, false);
+      StringBuffer s1 = new StringBuffer("       " + vo.getAlgorithmName());
+      /*
+       * boolean b = true;
+       * for (int i = 0; i < size1; i++) {
+       * AlgorithmScoreVo v = algorithmScoreList.get(i);
+       * Double score = v.getScore();
+       * if (100 > score) {
+       * b = false;
+       * break;
+       * }
+       * }
+       */
+      String substring1 = "";
+      // StringBuffer stringBuffer2 = new StringBuffer(" ");
+      // 末级指标
+      // 先对末级指标进行分组
+      LinkedHashMap<String, List<SceneScListVo>> map1 = new LinkedHashMap<>();
+      for (SceneScListVo sc : sceneScoreLi) {
+        String lastZbName = "";
+        // 最多支持到6级指标
+        lastZbName = sc.getSublistName1();
+        if (StringUtil.isNotEmpty(sc.getSublistName2())) {
+          lastZbName = sc.getSublistName2();
+        }
+        if (StringUtil.isNotEmpty(sc.getSublistName3())) {
+          lastZbName = sc.getSublistName3();
+        }
+        if (StringUtil.isNotEmpty(sc.getSublistName4())) {
+          lastZbName = sc.getSublistName4();
+        }
+        if (StringUtil.isNotEmpty(sc.getSublistName5())) {
+          lastZbName = sc.getSublistName5();
+        }
+        if (StringUtil.isNotEmpty(sc.getSublistName6())) {
+          lastZbName = sc.getSublistName6();
+        }
+
+        List<SceneScListVo> listVos = map1.get(lastZbName);
+        if (listVos == null) {
+          listVos = new ArrayList<>();
+          listVos.add(sc);
+          map1.put(lastZbName, listVos);
+        } else {
+          listVos.add(sc);
+        }
+      }
+      StringBuffer deFenShuoMing = new StringBuffer("       " + vo.getAlgorithmName());
+      for (String m : map1.keySet()) {
+        List<SceneScListVo> sceneScListVos = map1.get(m);
+        int size2 = sceneScListVos.size();
+        int xy100b = 0;
+        for (SceneScListVo sc1 : sceneScListVos) {
+          String sceneScore = sc1.getSceneScore();
+          BigDecimal score = new BigDecimal("0");
+          if (sceneScore != null && !"".equals(sceneScore)) {
             try {
-                os.close();
-            } catch (IOException e) {
-                e.printStackTrace();
+              score = new BigDecimal(sceneScore);
+            } catch (Exception e) {
+              score = new BigDecimal("0");
             }
-        }
 
-    }
+          }
+          int r = score.compareTo(new BigDecimal("100"));
+          // 小于100
+          if (r < 0) {
+            xy100b++;
+            deFenShuoMing.append("在" + m + "指标中的" + sc1.getSceneId() + "中,测试得分为" + sceneScore + ";");
+          }
 
-    public void lineFeed(Document document, int length, int type) throws DocumentException {
-        if (type == 1) {
-            for (int i = 0; i < length; i++) {
-                document.add(Chunk.NEWLINE);
-            }
-        } else if (type == 2) {
-            for (int i = 0; i < length; i++) {
-                document.add(new Phrase("\n"));
-            }
         }
+        if (xy100b == 0) {
+          deFenShuoMing.append("在" + m + "指标中的" + sceneScListVos.size() + "个场景均表现优秀,测试得分100分。");
+        } else {
+          int num = size2 - xy100b;
+          if (num != 0) {
+            deFenShuoMing.append("其他" + num + "个场景表现优秀,测试得分100分。");
+          } else {
+            deFenShuoMing = new StringBuffer(deFenShuoMing.substring(0, deFenShuoMing.lastIndexOf(";")) + "。");
+          }
+        }
+      }
+      substring1 = deFenShuoMing.append("详见表4-1。").toString();
+
+      /*
+       * if (b) {
+       * //得分都为100,取末级指标
+       * for (int i = 0; i < size1; i++) {
+       * AlgorithmScoreVo v = algorithmScoreList.get(i);
+       * if ("汇总".equals(v.getProjectName())) {
+       * continue;
+       * }
+       * stringBuffer2.append(vo.getAlgorithmName() + "在指标中的" + v.getSceneNum() +
+       * "个场景均表现良好,测试得分为" + v.getScore() +
+       * ";");
+       * }
+       * substring1 = stringBuffer2.substring(0, stringBuffer2.lastIndexOf(";"));
+       * substring1 += "。详见表4-1。";
+       *
+       * } else {
+       * //得分有小于100的,取末级指标
+       * for (int i = 0; i < size1; i++) {
+       * AlgorithmScoreVo v = algorithmScoreList.get(i);
+       * if ("汇总".equals(v.getProjectName())) {
+       * continue;
+       * }
+       * Integer sceneNum = v.getSceneNum();
+       * String projectName = v.getProjectName();
+       *
+       * for (SceneScListVo v1 : sceneScoreLi) {
+       * if (projectName.equals(v1.getSublistName1())) {
+       * String sceneScore = v1.getSceneScore();
+       * BigDecimal score = new BigDecimal("0");
+       * if (sceneScore != null && !"".equals(sceneScore)) {
+       * try {
+       * score = new BigDecimal(sceneScore);
+       * } catch (Exception e) {
+       * score = new BigDecimal("0");
+       * }
+       *
+       * }
+       * int r = score.compareTo(new BigDecimal("100"));
+       * if (r == -1) {
+       * stringBuffer2.append(vo.getAlgorithmName() + "在" + v1.getSublistName1() +
+       * "指标中的" + v1.getSceneId() + "中," + "测试得分为" + v1.getSceneScore() + ";");
+       * sceneNum--;
+       * }
+       * }
+       * }
+       * substring1 = stringBuffer2.substring(0, stringBuffer2.lastIndexOf(";"));
+       * if (sceneNum > 0) {
+       * substring1 += ",在其他" + sceneNum + "个场景表现良好,测试得分100分";
+       * } else {
+       * substring1 += "。详见表4-1。";
+       * }
+       *
+       *
+       * }
+       *
+       * }
+       */
+
+      addElement(document, substring1, null, bf3, 15, false, 30, false);
+      addElement(document, "表4-1 详细得分情况", null, bf3, 15, false, 30, true);
+
+      /*
+       * 详细得分情况
+       */
+      /*
+       * Paragraph sceneScoreElements = new Paragraph(
+       * 50,
+       * "详细得分情况",
+       * defaultFont(font));
+       * sceneScoreElements.setAlignment(Element.ALIGN_CENTER); //居中
+       * document.add(sceneScoreElements);
+       */
+
+      setBlankLineSpacing(20, font, document);
+
+      // List<Map> scoreLiTitle = vo.getSceneScoreLiTitle();
+      int size2 = scoreLiTitle.size();
+      PdfPTable pdfPTable3 = new PdfPTable(size2);
+      pdfPTable3.setSplitLate(false);
+      pdfPTable3.setHeaderRows(1);
+      String[] slt2 = new String[size2];
+      for (int i = 0; i < size2; i++) {
+        slt2[i] = scoreLiTitle.get(i).get("label").toString();
+      }
+      addTitleList(pdfPTable3, font, slt2, true, 30);
+
+      List<String[]> list2 = new ArrayList<>();
+
+      for (SceneScListVo sslv : sceneScoreLi) {
+        String[] ssli = new String[size2];
+        for (int i = 0; i < size2; i++) {
+          ssli[i] = "";
+        }
+        // 目前最多支持到6级指标
+        for (int i = 0; i < size2 - 5; i++) {
+          if (i == 0) {
+            if (sslv.getSublistName1() != null) {
+              ssli[i] = sslv.getSublistName1();
+            }
+
+          } else if (i == 1) {
+            if (sslv.getSublistName2() != null) {
+              ssli[i] = sslv.getSublistName2();
+            }
+
+          } else if (i == 2) {
+            if (sslv.getSublistName3() != null) {
+              ssli[i] = sslv.getSublistName3();
+            }
+
+          } else if (i == 3) {
+            if (sslv.getSublistName4() != null) {
+              ssli[i] = sslv.getSublistName4();
+            }
+
+          } else if (i == 4) {
+            if (sslv.getSublistName5() != null) {
+              ssli[i] = sslv.getSublistName5();
+            }
+
+          } else if (i == 5) {
+            if (sslv.getSublistName6() != null) {
+              ssli[i] = sslv.getSublistName6();
+            }
+
+          }
+        }
+        ssli[size2 - 5] = sslv.getSceneId();
+        ssli[size2 - 4] = sslv.getSceneIdType();
+        ssli[size2 - 3] = sslv.getSceneScore();
+        ssli[size2 - 2] = sslv.getTargetEvaluate();
+        ssli[size2 - 1] = sslv.getScoreExplain();
+
+        list2.add(ssli);
+
+        // addDataList(pdfPTable3, font, ssli);
+      }
+
+      Map map2 = getSceneScListCombineCoord(sceneScoreLi, size2);
+
+      Map<String, Integer> combineCoordList2 = (Map<String, Integer>) map2.get("combineCoordList");
+      List<String> skipCoordList2 = (List<String>) map2.get("skipCoordList");
+
+      boolean b2 = false;
+      int num2 = 0;
+      for (int i = 0; i < list2.size(); i++) {
+        String[] strings = list2.get(i);
+        for (int j = 0; j < strings.length; j++) {
+          String coord = i + "," + j;
+
+          // 是否要跳过
+          boolean contains = skipCoordList2.contains(coord);
+          if (contains) {
+            continue;
+          }
+          PdfPCell pdfPCell = new PdfPCell(new Paragraph(strings[j], defaultFont(font)));
+          // 是否要合并
+          Integer n = combineCoordList2.get(coord);
+          if (n != null) {
+            pdfPCell.setRowspan(n);
+          }
+          addCell(pdfPTable3, pdfPCell, true);
+        }
+      }
+
+      document.add(pdfPTable3);
+
+      /*
+       * //标题
+       * Font titleFont = new Font(font, 20); //字体
+       * Paragraph titleElements = new Paragraph("评价报告",titleFont);
+       * titleElements.setAlignment(Element.ALIGN_CENTER); //居中
+       * document.add(titleElements);
+       *
+       *
+       * //算法名称、算法得分、测试等级
+       * Paragraph algorithmNanmeElements = new Paragraph(
+       * 50,
+       * "          算法名称:"+vo.getAlgorithmName()
+       * +"         算法得分:"+vo.getAlgorithmScore()
+       * +"         测试等级:"+vo.getEvaluationLevel(),
+       * defaultFont(font));
+       * algorithmNanmeElements.setAlignment(Element.ALIGN_LEFT); //靠左
+       * document.add(algorithmNanmeElements);
+       *
+       *
+       * //算法描述
+       * Paragraph algorithmDescribeFontElements = new Paragraph(
+       * 30,
+       * "          算法描述:"+vo.getAlgorithmDescribe(),
+       * defaultFont(font));
+       * algorithmDescribeFontElements.setAlignment(Element.ALIGN_LEFT); //居中
+       * document.add(algorithmDescribeFontElements);
+       *
+       * //算法简评
+       * Font algorithmEvaluateFont = new Font(font, 14); //字体
+       * Paragraph algorithmEvaluateElements = new Paragraph(
+       * 30,
+       * "          算法简评:"+vo.getAlgorithmEvaluation(),
+       * algorithmEvaluateFont);
+       * algorithmEvaluateElements.setAlignment(Element.ALIGN_LEFT); //居中
+       * document.add(algorithmEvaluateElements);
+       */
+
+      /*
+       * 测试得分表
+       *//*
+       * Paragraph scoreTableElements = new Paragraph(
+       * 50,
+       * "测试得分表",
+       * defaultFont(font));
+       * scoreTableElements.setAlignment(Element.ALIGN_CENTER); //居中
+       * document.add(scoreTableElements);
+       *
+       * setBlankLineSpacing(20,font,document);
+       *
+       * //表头
+       * PdfPTable pdfPTable = new PdfPTable(5);
+       * pdfPTable.setHeaderRows(1);//换页每页显示表头
+       * addTitleList(pdfPTable, font, new
+       * String[]{"测试项目","场景数量","测试权重(%)","测试得分","得分率(%)"});
+       *
+       * //数据
+       * // List<AlgorithmScoreVo> algorithmScoreList = vo.getAlgorithmScoreList();
+       * for(AlgorithmScoreVo asv : algorithmScoreList){
+       * String[] data = new String[]{
+       * asv.getProjectName(), String.valueOf(asv.getSceneNum()), asv.getWeight(),
+       * String.valueOf(asv.getScore()), String.valueOf(asv.getScoreRatio())
+       * };
+       *
+       * addDataList(pdfPTable, font, data);
+       * }
+       * document.add(pdfPTable);
+       */
+
+      /*
+       * 评价等级
+       */
+      /*
+       * Paragraph levelTableElements = new Paragraph(
+       * 50,
+       * "评价等级",
+       * defaultFont(font));
+       * levelTableElements.setAlignment(Element.ALIGN_CENTER); //居中
+       * document.add(levelTableElements);
+       *
+       * setBlankLineSpacing(20,font,document);
+       *
+       * PdfPTable pdfPTable1 = new PdfPTable(5);
+       * addTitleList(pdfPTable1, font, new
+       * String[]{"测试项目","90<总分<100","80<总分<90","70<总分<80","0<总分<70"});
+       * addDataList(pdfPTable1, font, new
+       * String[]{"评价等级","优秀(G)","良好(A)","一般(M)","较差(P)",
+       * "评价等级","++++++","+++++","++++","+++",});
+       * document.add(pdfPTable1);
+       */
+
+      /*
+       * //新的一页,横向显示
+       * document.setPageSize(PageSize.A4.rotate());
+       * document.newPage();
+       */
+
+      // 指标得分列表
+      /*
+       * Paragraph subListScoreElements = new Paragraph(
+       * 50,
+       * "算法测试评分细则",
+       * defaultFont(font));
+       * subListScoreElements.setAlignment(Element.ALIGN_CENTER); //居中
+       * document.add(subListScoreElements);
+       *
+       * setBlankLineSpacing(20,font,document);
+       *
+       * List<Map> subListScoreLiTitle = vo.getSubListScoreLiTitle();
+       * int size = subListScoreLiTitle.size();
+       * PdfPTable pdfPTable2 = new PdfPTable(size);
+       * pdfPTable2.setHeaderRows(1);
+       * String[] slt = new String[size];
+       * for(int i=0; i<size; i++){
+       * slt[i] = subListScoreLiTitle.get(i).get("label").toString();
+       * }
+       * addTitleList(pdfPTable2, font, slt);
+       *
+       * List<SubScListVo> subListScoreLi = vo.getSubListScoreLi();
+       *
+       * List<String[]> list = new ArrayList<>();
+       * for(SubScListVo slv : subListScoreLi){
+       * String[] slsi = new String[size];
+       * for(int i=0;i<size;i++){
+       * slsi[i] = "";
+       * }
+       * //目前最多支持到6级指标
+       * for(int i=0; i<size-4; i++){
+       * if(i==0){
+       * if(slv.getSublistName1() != null){
+       * slsi[i] = slv.getSublistName1();
+       * }
+       *
+       * }else if(i==1){
+       * if(slv.getSublistName2() != null){
+       * slsi[i] = slv.getSublistName2();
+       * }
+       *
+       * }else if(i==2){
+       * if(slv.getSublistName3() != null){
+       * slsi[i] = slv.getSublistName3();
+       * }
+       *
+       * }else if(i==3){
+       * if(slv.getSublistName4() != null){
+       * slsi[i] = slv.getSublistName4();
+       * }
+       *
+       * }else if(i==4){
+       * if(slv.getSublistName5() != null){
+       * slsi[i] = slv.getSublistName5();
+       * }
+       *
+       * }else if(i==5){
+       * if(slv.getSublistName6() != null){
+       * slsi[i] = slv.getSublistName6();
+       * }
+       *
+       * }
+       * }
+       * slsi[size-4] = slv.getSceneNum();
+       * slsi[size-3] = slv.getNotStandardSceneNum();
+       * slsi[size-2] = slv.getLastScore();
+       * slsi[size-1] = slv.getFirstScore();
+       *
+       * list.add(slsi);
+       *
+       * // addDataList(pdfPTable2, font, slsi);
+       * }
+       *
+       *
+       * Map map = getSubScListCombineCoord(subListScoreLi, size);
+       *
+       * Map<String, Integer> combineCoordList = (Map<String, Integer>)
+       * map.get("combineCoordList");
+       * List<String> skipCoordList = (List<String>) map.get("skipCoordList");
+       *
+       * for(int i=0; i<list.size();i++){
+       * String[] strings = list.get(i);
+       * for(int j=0; j<strings.length; j++){
+       * String coord = i+","+j;
+       *
+       * //是否要跳过
+       * boolean contains = skipCoordList.contains(coord);
+       * if(contains){
+       * continue;
+       * }
+       * PdfPCell pdfPCell = new PdfPCell(new
+       * Paragraph(strings[j],defaultFont(font)));
+       *
+       * //是否要合并
+       * Integer n = combineCoordList.get(coord);
+       * if(n != null){
+       * pdfPCell.setRowspan(n);
+       * }
+       *
+       * pdfPTable2.addCell(pdfPCell);
+       *
+       *
+       * }
+       * }
+       *
+       * document.add(pdfPTable2);
+       */
+
+      /*
+       * 场景得分列表
+       */
+      /*
+       * Paragraph sceneScoreElements = new Paragraph(
+       * 50,
+       * "详细得分情况",
+       * defaultFont(font));
+       * sceneScoreElements.setAlignment(Element.ALIGN_CENTER); //居中
+       * document.add(sceneScoreElements);
+       *
+       * setBlankLineSpacing(20,font,document);
+       *
+       * List<Map> scoreLiTitle = vo.getSceneScoreLiTitle();
+       * int size2 = scoreLiTitle.size();
+       * PdfPTable pdfPTable3 = new PdfPTable(size2);
+       * pdfPTable3.setHeaderRows(1);
+       * String[] slt2 = new String[size2];
+       * for(int i=0; i<size2; i++){
+       * slt2[i] = scoreLiTitle.get(i).get("label").toString();
+       * }
+       * addTitleList(pdfPTable3, font, slt2);
+       * List<SceneScListVo> sceneScoreLi = vo.getSceneScoreLi();
+       *
+       * List<String[]> list2 = new ArrayList<>();
+       *
+       * for(SceneScListVo sslv : sceneScoreLi){
+       * String[] ssli = new String[size2];
+       * for(int i=0;i<size2;i++){
+       * ssli[i] = "";
+       * }
+       * //目前最多支持到6级指标
+       * for(int i=0; i<size2-5; i++){
+       * if(i==0){
+       * if(sslv.getSublistName1() != null){
+       * ssli[i] = sslv.getSublistName1();
+       * }
+       *
+       * }else if(i==1){
+       * if(sslv.getSublistName2() != null){
+       * ssli[i] = sslv.getSublistName2();
+       * }
+       *
+       * }else if(i==2){
+       * if(sslv.getSublistName3() != null){
+       * ssli[i] = sslv.getSublistName3();
+       * }
+       *
+       * }else if(i==3){
+       * if(sslv.getSublistName4() != null){
+       * ssli[i] = sslv.getSublistName4();
+       * }
+       *
+       * }else if(i==4){
+       * if(sslv.getSublistName5() != null){
+       * ssli[i] = sslv.getSublistName5();
+       * }
+       *
+       * }else if(i==5){
+       * if(sslv.getSublistName6() != null){
+       * ssli[i] = sslv.getSublistName6();
+       * }
+       *
+       * }
+       * }
+       * ssli[size2-5] = sslv.getSceneId();
+       * ssli[size2-4] = sslv.getSceneIdType();
+       * ssli[size2-3] = sslv.getSceneScore();
+       * ssli[size2-2] = sslv.getTargetEvaluate();
+       * ssli[size2-1] = sslv.getScoreExplain();
+       *
+       * list2.add(ssli);
+       *
+       * // addDataList(pdfPTable3, font, ssli);
+       * }
+       *
+       * Map map2 = getSceneScListCombineCoord(sceneScoreLi, size2);
+       *
+       * Map<String, Integer> combineCoordList2 = (Map<String, Integer>)
+       * map2.get("combineCoordList");
+       * List<String> skipCoordList2 = (List<String>) map2.get("skipCoordList");
+       *
+       * boolean b2 = false;
+       * int num2 = 0;
+       * for(int i=0; i<list2.size();i++){
+       * String[] strings = list2.get(i);
+       * for(int j=0; j<strings.length; j++){
+       * String coord = i+","+j;
+       *
+       * //是否要跳过
+       * boolean contains = skipCoordList2.contains(coord);
+       * if(contains){
+       * continue;
+       * }
+       * PdfPCell pdfPCell = new PdfPCell(new
+       * Paragraph(strings[j],defaultFont(font)));
+       * //是否要合并
+       * Integer n = combineCoordList2.get(coord);
+       * if(n != null){
+       * pdfPCell.setRowspan(n);
+       * }
+       *
+       * pdfPTable3.addCell(pdfPCell);
+       *
+       *
+       * }
+       * }
+       *
+       * document.add(pdfPTable3);
+       */
+
+    } catch (Exception e) {
+      e.printStackTrace();
+
+    } finally {
+      document.close();
+      try {
+        os.close();
+      } catch (IOException e) {
+        e.printStackTrace();
+      }
     }
 
-    private void addElement(Document document, String val1, String val2, BaseFont f, int fontSize, boolean isBold,
-            int leading, boolean isCenter) throws DocumentException {
-        Font ft;
-        Paragraph elm;
-        if (isBold) {
-            ft = new Font(f, fontSize, Font.BOLD);
-        } else {
-            ft = new Font(f, fontSize);
-        }
-        if (val2 != null && !"".equals(val2)) {
-            elm = new Paragraph(leading, val1 + val2, ft);
-        } else {
-            elm = new Paragraph(leading, val1, ft);
-        }
-        if (isCenter) {
-            elm.setAlignment(Element.ALIGN_CENTER);
-        }
-        document.add(elm);
+  }
+
+  public void lineFeed(Document document, int length, int type) throws DocumentException {
+    if (type == 1) {
+      for (int i = 0; i < length; i++) {
+        document.add(Chunk.NEWLINE);
+      }
+    } else if (type == 2) {
+      for (int i = 0; i < length; i++) {
+        document.add(new Phrase("\n"));
+      }
+    }
+  }
+
+  private void addElement(Document document, String val1, String val2, BaseFont f, int fontSize, boolean isBold, int leading, boolean isCenter) throws DocumentException {
+    Font ft;
+    Paragraph elm;
+    if (isBold) {
+      ft = new Font(f, fontSize, Font.BOLD);
+    } else {
+      ft = new Font(f, fontSize);
     }
+    if (val2 != null && !"".equals(val2)) {
+      elm = new Paragraph(leading, val1 + val2, ft);
+    } else {
+      elm = new Paragraph(leading, val1, ft);
+    }
+    if (isCenter) {
+      elm.setAlignment(Element.ALIGN_CENTER);
+    }
+    document.add(elm);
+  }
 
-    /**
-     * 获取所有要合并的下标、每个下标索要合并的行数、要跳过创建表格的下标
-     */
-    private Map getSubScListCombineCoord(List<SubScListVo> voList, int size) {
-        int sublistNameSize = size - 4;// 指标最大级数
-        HashMap<String, Object> resultMap = new HashMap<>();
-        Map<String, CombineCoordVo> map = new HashMap<>();
-        Map<String, Integer> combineCoordMap = new HashMap<>(); // 要合并的格子下标
-        List<String> skipCoordList = new ArrayList<>(); // 要跳过的格子下标
-
-        for (int i = 0; i < voList.size(); i++) {
-            SubScListVo vo = voList.get(i);
-            if (sublistNameSize == 1) {
-                // 一级
-                String sublistName1 = vo.getSublistName1();
-                if (!isEmpty(sublistName1)) {
-                    setCoord(map, sublistName1, i + ",0", skipCoordList);
-                    setCoord(map, sublistName1 + "firstScore", i + "," + (size - 1), skipCoordList);
-                }
-
-            } else if (sublistNameSize == 2) {
-                // 二级
-                String sublistName1 = vo.getSublistName1();
-                String sublistName2 = vo.getSublistName2();
-
-                if (!isEmpty(sublistName1)) {
-                    setCoord(map, sublistName1, i + ",0", skipCoordList);
-                    setCoord(map, sublistName1 + "firstScore", i + "," + (size - 1), skipCoordList);
-                }
-                if (!isEmpty(sublistName2)) {
-                    setCoord(map, sublistName2, i + ",1", skipCoordList);
-                }
-
-            } else if (sublistNameSize == 3) {
-                // 三级
-                String sublistName1 = vo.getSublistName1();
-                String sublistName2 = vo.getSublistName2();
-                String sublistName3 = vo.getSublistName3();
-
-                if (!isEmpty(sublistName1)) {
-                    setCoord(map, sublistName1, i + ",0", skipCoordList);
-                    setCoord(map, sublistName1 + "firstScore", i + "," + (size - 1), skipCoordList);
-                }
-                if (!isEmpty(sublistName2)) {
-                    setCoord(map, sublistName2, i + ",1", skipCoordList);
-                }
-                if (!isEmpty(sublistName3)) {
-                    setCoord(map, sublistName3, i + ",2", skipCoordList);
-                }
-            } else if (sublistNameSize == 4) {
-                // 四级
-                String sublistName1 = vo.getSublistName1();
-                String sublistName2 = vo.getSublistName2();
-                String sublistName3 = vo.getSublistName3();
-                String sublistName4 = vo.getSublistName4();
-
-                if (!isEmpty(sublistName1)) {
-                    setCoord(map, sublistName1, i + ",0", skipCoordList);
-                    setCoord(map, sublistName1 + "firstScore", i + "," + (size - 1), skipCoordList);
-                }
-                if (!isEmpty(sublistName2)) {
-                    setCoord(map, sublistName2, i + ",1", skipCoordList);
-                }
-                if (!isEmpty(sublistName3)) {
-                    setCoord(map, sublistName3, i + ",2", skipCoordList);
-                }
-                if (!isEmpty(sublistName4)) {
-                    setCoord(map, sublistName4, i + ",3", skipCoordList);
-                }
-
-            } else if (sublistNameSize == 5) {
-                // 五级
-                String sublistName1 = vo.getSublistName1();
-                String sublistName2 = vo.getSublistName2();
-                String sublistName3 = vo.getSublistName3();
-                String sublistName4 = vo.getSublistName4();
-                String sublistName5 = vo.getSublistName5();
-
-                if (!isEmpty(sublistName1)) {
-                    setCoord(map, sublistName1, i + ",0", skipCoordList);
-                    setCoord(map, sublistName1 + "firstScore", i + "," + (size - 1), skipCoordList);
-                }
-                if (!isEmpty(sublistName2)) {
-                    setCoord(map, sublistName2, i + ",1", skipCoordList);
-                }
-                if (!isEmpty(sublistName3)) {
-                    setCoord(map, sublistName3, i + ",2", skipCoordList);
-                }
-                if (!isEmpty(sublistName4)) {
-                    setCoord(map, sublistName4, i + ",3", skipCoordList);
-                }
-                if (!isEmpty(sublistName5)) {
-                    setCoord(map, sublistName5, i + ",4", skipCoordList);
-                }
-
-            } else if (sublistNameSize == 6) {
-                // 六级
-                String sublistName1 = vo.getSublistName1();
-                String sublistName2 = vo.getSublistName2();
-                String sublistName3 = vo.getSublistName3();
-                String sublistName4 = vo.getSublistName4();
-                String sublistName5 = vo.getSublistName5();
-                String sublistName6 = vo.getSublistName6();
-
-                if (!isEmpty(sublistName1)) {
-                    setCoord(map, sublistName1, i + ",0", skipCoordList);
-                    setCoord(map, sublistName1 + "firstScore", i + "," + (size - 1), skipCoordList);
-                }
-                if (!isEmpty(sublistName2)) {
-                    setCoord(map, sublistName2, i + ",1", skipCoordList);
-                }
-                if (!isEmpty(sublistName3)) {
-                    setCoord(map, sublistName3, i + ",2", skipCoordList);
-                }
-                if (!isEmpty(sublistName4)) {
-                    setCoord(map, sublistName4, i + ",3", skipCoordList);
-                }
-                if (!isEmpty(sublistName5)) {
-                    setCoord(map, sublistName5, i + ",4", skipCoordList);
-                }
-                if (!isEmpty(sublistName6)) {
-                    setCoord(map, sublistName6, i + ",5", skipCoordList);
-                }
+  /**
+   * 获取所有要合并的下标、每个下标索要合并的行数、要跳过创建表格的下标
+   */
+  private Map getSubScListCombineCoord(List<SubScListVo> voList, int size) {
+    int sublistNameSize = size - 4;// 指标最大级数
+    HashMap<String, Object> resultMap = new HashMap<>();
+    Map<String, CombineCoordVo> map = new HashMap<>();
+    Map<String, Integer> combineCoordMap = new HashMap<>(); // 要合并的格子下标
+    List<String> skipCoordList = new ArrayList<>(); // 要跳过的格子下标
+
+    for (int i = 0; i < voList.size(); i++) {
+      SubScListVo vo = voList.get(i);
+      if (sublistNameSize == 1) {
+        // 一级
+        String sublistName1 = vo.getSublistName1();
+        if (!isEmpty(sublistName1)) {
+          setCoord(map, sublistName1, i + ",0", skipCoordList);
+          setCoord(map, sublistName1 + "firstScore", i + "," + (size - 1), skipCoordList);
+        }
 
-            }
+      } else if (sublistNameSize == 2) {
+        // 二级
+        String sublistName1 = vo.getSublistName1();
+        String sublistName2 = vo.getSublistName2();
 
+        if (!isEmpty(sublistName1)) {
+          setCoord(map, sublistName1, i + ",0", skipCoordList);
+          setCoord(map, sublistName1 + "firstScore", i + "," + (size - 1), skipCoordList);
         }
-
-        for (String k : map.keySet()) {
-            CombineCoordVo combineCoordVo = map.get(k);
-            combineCoordMap.put(combineCoordVo.getCoord(), combineCoordVo.getRepetitionNum());
+        if (!isEmpty(sublistName2)) {
+          setCoord(map, sublistName2, i + ",1", skipCoordList);
         }
 
-        resultMap.put("combineCoordList", combineCoordMap);
-        resultMap.put("skipCoordList", skipCoordList);
+      } else if (sublistNameSize == 3) {
+        // 三级
+        String sublistName1 = vo.getSublistName1();
+        String sublistName2 = vo.getSublistName2();
+        String sublistName3 = vo.getSublistName3();
 
-        return resultMap;
-
-    }
+        if (!isEmpty(sublistName1)) {
+          setCoord(map, sublistName1, i + ",0", skipCoordList);
+          setCoord(map, sublistName1 + "firstScore", i + "," + (size - 1), skipCoordList);
+        }
+        if (!isEmpty(sublistName2)) {
+          setCoord(map, sublistName2, i + ",1", skipCoordList);
+        }
+        if (!isEmpty(sublistName3)) {
+          setCoord(map, sublistName3, i + ",2", skipCoordList);
+        }
+      } else if (sublistNameSize == 4) {
+        // 四级
+        String sublistName1 = vo.getSublistName1();
+        String sublistName2 = vo.getSublistName2();
+        String sublistName3 = vo.getSublistName3();
+        String sublistName4 = vo.getSublistName4();
 
-    /**
-     * 获取所有要合并的下标、每个下标索要合并的行数、要跳过创建表格的下标
-     */
-    private Map getSceneScListCombineCoord(List<SceneScListVo> voList, int size) {
-        int sublistNameSize = size - 5;// 指标最大级数
-        HashMap<String, Object> resultMap = new HashMap<>();
-        Map<String, CombineCoordVo> map = new HashMap<>();
-        Map<String, Integer> combineCoordMap = new HashMap<>(); // 要合并的格子下标
-        List<String> skipCoordList = new ArrayList<>(); // 要跳过的格子下标
-
-        for (int i = 0; i < voList.size(); i++) {
-            SceneScListVo vo = voList.get(i);
-            if (sublistNameSize == 1) {
-                // 一级
-                String sublistName1 = vo.getSublistName1();
-                if (!isEmpty(sublistName1)) {
-                    setCoord(map, sublistName1, i + ",0", skipCoordList);
-                    setCoord(map, sublistName1 + "scoreExplain", i + "," + (size - 1), skipCoordList);
-                }
-
-            } else if (sublistNameSize == 2) {
-                // 二级
-                String sublistName1 = vo.getSublistName1();
-                String sublistName2 = vo.getSublistName2();
-
-                if (!isEmpty(sublistName1)) {
-                    setCoord(map, sublistName1, i + ",0", skipCoordList);
-                }
-                if (!isEmpty(sublistName2)) {
-                    setCoord(map, sublistName2, i + ",1", skipCoordList);
-
-                }
-                if (!isEmpty(sublistName2)) {
-                    setCoord(map, sublistName2 + "scoreExplain", i + "," + (size - 1), skipCoordList);
-                } else {
-                    setCoord(map, sublistName1 + "scoreExplain", i + "," + (size - 1), skipCoordList);
-                }
-
-            } else if (sublistNameSize == 3) {
-                // 三级
-                String sublistName1 = vo.getSublistName1();
-                String sublistName2 = vo.getSublistName2();
-                String sublistName3 = vo.getSublistName3();
-
-                if (!isEmpty(sublistName1)) {
-                    setCoord(map, sublistName1, i + ",0", skipCoordList);
-                }
-                if (!isEmpty(sublistName2)) {
-                    setCoord(map, sublistName2, i + ",1", skipCoordList);
-                }
-                if (!isEmpty(sublistName3)) {
-                    setCoord(map, sublistName3, i + ",2", skipCoordList);
-
-                }
-                if (!isEmpty(sublistName3)) {
-                    setCoord(map, sublistName3 + "scoreExplain", i + "," + (size - 1), skipCoordList);
-                } else if (!isEmpty(sublistName2)) {
-                    setCoord(map, sublistName2 + "scoreExplain", i + "," + (size - 1), skipCoordList);
-                } else {
-                    setCoord(map, sublistName1 + "scoreExplain", i + "," + (size - 1), skipCoordList);
-                }
-            } else if (sublistNameSize == 4) {
-                // 四级
-                String sublistName1 = vo.getSublistName1();
-                String sublistName2 = vo.getSublistName2();
-                String sublistName3 = vo.getSublistName3();
-                String sublistName4 = vo.getSublistName4();
-
-                if (!isEmpty(sublistName1)) {
-                    setCoord(map, sublistName1, i + ",0", skipCoordList);
-                }
-                if (!isEmpty(sublistName2)) {
-                    setCoord(map, sublistName2, i + ",1", skipCoordList);
-                }
-                if (!isEmpty(sublistName3)) {
-                    setCoord(map, sublistName3, i + ",2", skipCoordList);
-                }
-                if (!isEmpty(sublistName4)) {
-                    setCoord(map, sublistName4, i + ",3", skipCoordList);
-                }
-
-                if (!isEmpty(sublistName4)) {
-                    setCoord(map, sublistName4 + "scoreExplain", i + "," + (size - 1), skipCoordList);
-                } else if (!isEmpty(sublistName3)) {
-                    setCoord(map, sublistName3 + "scoreExplain", i + "," + (size - 1), skipCoordList);
-                } else if (!isEmpty(sublistName2)) {
-                    setCoord(map, sublistName2 + "scoreExplain", i + "," + (size - 1), skipCoordList);
-                } else {
-                    setCoord(map, sublistName1 + "scoreExplain", i + "," + (size - 1), skipCoordList);
-                }
-
-            } else if (sublistNameSize == 5) {
-                // 五级
-                String sublistName1 = vo.getSublistName1();
-                String sublistName2 = vo.getSublistName2();
-                String sublistName3 = vo.getSublistName3();
-                String sublistName4 = vo.getSublistName4();
-                String sublistName5 = vo.getSublistName5();
-
-                if (!isEmpty(sublistName1)) {
-                    setCoord(map, sublistName1, i + ",0", skipCoordList);
-                }
-                if (!isEmpty(sublistName2)) {
-                    setCoord(map, sublistName2, i + ",1", skipCoordList);
-                }
-                if (!isEmpty(sublistName3)) {
-                    setCoord(map, sublistName3, i + ",2", skipCoordList);
-                }
-                if (!isEmpty(sublistName4)) {
-                    setCoord(map, sublistName4, i + ",3", skipCoordList);
-                }
-                if (!isEmpty(sublistName5)) {
-                    setCoord(map, sublistName5, i + ",4", skipCoordList);
-                }
-
-                if (!isEmpty(sublistName5)) {
-                    setCoord(map, sublistName5 + "scoreExplain", i + "," + (size - 1), skipCoordList);
-                } else if (!isEmpty(sublistName4)) {
-                    setCoord(map, sublistName4 + "scoreExplain", i + "," + (size - 1), skipCoordList);
-                } else if (!isEmpty(sublistName3)) {
-                    setCoord(map, sublistName3 + "scoreExplain", i + "," + (size - 1), skipCoordList);
-                } else if (!isEmpty(sublistName2)) {
-                    setCoord(map, sublistName2 + "scoreExplain", i + "," + (size - 1), skipCoordList);
-                } else {
-                    setCoord(map, sublistName1 + "scoreExplain", i + "," + (size - 1), skipCoordList);
-                }
-
-            } else if (sublistNameSize == 6) {
-                // 六级
-                String sublistName1 = vo.getSublistName1();
-                String sublistName2 = vo.getSublistName2();
-                String sublistName3 = vo.getSublistName3();
-                String sublistName4 = vo.getSublistName4();
-                String sublistName5 = vo.getSublistName5();
-                String sublistName6 = vo.getSublistName6();
-
-                if (!isEmpty(sublistName1)) {
-                    setCoord(map, sublistName1, i + ",0", skipCoordList);
-                }
-                if (!isEmpty(sublistName2)) {
-                    setCoord(map, sublistName2, i + ",1", skipCoordList);
-                }
-                if (!isEmpty(sublistName3)) {
-                    setCoord(map, sublistName3, i + ",2", skipCoordList);
-                }
-                if (!isEmpty(sublistName4)) {
-                    setCoord(map, sublistName4, i + ",3", skipCoordList);
-                }
-                if (!isEmpty(sublistName5)) {
-                    setCoord(map, sublistName5, i + ",4", skipCoordList);
-                }
-                if (!isEmpty(sublistName6)) {
-                    setCoord(map, sublistName6, i + ",5", skipCoordList);
-                    setCoord(map, sublistName1 + "scoreExplain", i + "," + (size - 1), skipCoordList);
-                }
-
-                if (!isEmpty(sublistName6)) {
-                    setCoord(map, sublistName6 + "scoreExplain", i + "," + (size - 1), skipCoordList);
-                } else if (!isEmpty(sublistName5)) {
-                    setCoord(map, sublistName5 + "scoreExplain", i + "," + (size - 1), skipCoordList);
-                } else if (!isEmpty(sublistName4)) {
-                    setCoord(map, sublistName4 + "scoreExplain", i + "," + (size - 1), skipCoordList);
-                } else if (!isEmpty(sublistName3)) {
-                    setCoord(map, sublistName3 + "scoreExplain", i + "," + (size - 1), skipCoordList);
-                } else if (!isEmpty(sublistName2)) {
-                    setCoord(map, sublistName2 + "scoreExplain", i + "," + (size - 1), skipCoordList);
-                } else {
-                    setCoord(map, sublistName1 + "scoreExplain", i + "," + (size - 1), skipCoordList);
-                }
+        if (!isEmpty(sublistName1)) {
+          setCoord(map, sublistName1, i + ",0", skipCoordList);
+          setCoord(map, sublistName1 + "firstScore", i + "," + (size - 1), skipCoordList);
+        }
+        if (!isEmpty(sublistName2)) {
+          setCoord(map, sublistName2, i + ",1", skipCoordList);
+        }
+        if (!isEmpty(sublistName3)) {
+          setCoord(map, sublistName3, i + ",2", skipCoordList);
+        }
+        if (!isEmpty(sublistName4)) {
+          setCoord(map, sublistName4, i + ",3", skipCoordList);
+        }
 
-            }
+      } else if (sublistNameSize == 5) {
+        // 五级
+        String sublistName1 = vo.getSublistName1();
+        String sublistName2 = vo.getSublistName2();
+        String sublistName3 = vo.getSublistName3();
+        String sublistName4 = vo.getSublistName4();
+        String sublistName5 = vo.getSublistName5();
 
+        if (!isEmpty(sublistName1)) {
+          setCoord(map, sublistName1, i + ",0", skipCoordList);
+          setCoord(map, sublistName1 + "firstScore", i + "," + (size - 1), skipCoordList);
+        }
+        if (!isEmpty(sublistName2)) {
+          setCoord(map, sublistName2, i + ",1", skipCoordList);
+        }
+        if (!isEmpty(sublistName3)) {
+          setCoord(map, sublistName3, i + ",2", skipCoordList);
+        }
+        if (!isEmpty(sublistName4)) {
+          setCoord(map, sublistName4, i + ",3", skipCoordList);
+        }
+        if (!isEmpty(sublistName5)) {
+          setCoord(map, sublistName5, i + ",4", skipCoordList);
         }
 
-        /*
-         * List<CombineCoordVo> combineCoordVoList = new ArrayList<>();
-         * 
-         * for(String k : map.keySet()){
-         * combineCoordVoList.add(map.get(k));
-         * }
-         */
+      } else if (sublistNameSize == 6) {
+        // 六级
+        String sublistName1 = vo.getSublistName1();
+        String sublistName2 = vo.getSublistName2();
+        String sublistName3 = vo.getSublistName3();
+        String sublistName4 = vo.getSublistName4();
+        String sublistName5 = vo.getSublistName5();
+        String sublistName6 = vo.getSublistName6();
 
-        for (String k : map.keySet()) {
-            CombineCoordVo combineCoordVo = map.get(k);
-            combineCoordMap.put(combineCoordVo.getCoord(), combineCoordVo.getRepetitionNum());
+        if (!isEmpty(sublistName1)) {
+          setCoord(map, sublistName1, i + ",0", skipCoordList);
+          setCoord(map, sublistName1 + "firstScore", i + "," + (size - 1), skipCoordList);
+        }
+        if (!isEmpty(sublistName2)) {
+          setCoord(map, sublistName2, i + ",1", skipCoordList);
+        }
+        if (!isEmpty(sublistName3)) {
+          setCoord(map, sublistName3, i + ",2", skipCoordList);
+        }
+        if (!isEmpty(sublistName4)) {
+          setCoord(map, sublistName4, i + ",3", skipCoordList);
+        }
+        if (!isEmpty(sublistName5)) {
+          setCoord(map, sublistName5, i + ",4", skipCoordList);
+        }
+        if (!isEmpty(sublistName6)) {
+          setCoord(map, sublistName6, i + ",5", skipCoordList);
         }
 
-        resultMap.put("combineCoordList", combineCoordMap);
-        resultMap.put("skipCoordList", skipCoordList);
-
-        return resultMap;
+      }
 
     }
 
-    private void setCoord(Map<String, CombineCoordVo> map, String key, String coord, List<String> skipCoordList) {
-        CombineCoordVo value = map.get(key);
-        if (value != null) {
-            // 坐标不变,合并行数+1
-            value.setRepetitionNum(value.getRepetitionNum() + 1);
-            skipCoordList.add(coord);
-        } else {
-            // 新增
-            CombineCoordVo combineCoordVo = new CombineCoordVo();
-            combineCoordVo.setCoord(coord);
-            combineCoordVo.setRepetitionNum(1);
-            map.put(key, combineCoordVo);
-
-        }
+    for (String k : map.keySet()) {
+      CombineCoordVo combineCoordVo = map.get(k);
+      combineCoordMap.put(combineCoordVo.getCoord(), combineCoordVo.getRepetitionNum());
     }
 
-    @Override
-    public String selectProjectReportIdByAlgorithmId(String algorithmId) {
-        SimulationManualProjectPo po = simulationProjectMapper.selectProjectReportIdByAlgorithmId(algorithmId);
-        if (StringUtil.isNotEmpty(po)) {
-            return po.getId();
-        }
-        return null;
-    }
+    resultMap.put("combineCoordList", combineCoordMap);
+    resultMap.put("skipCoordList", skipCoordList);
 
-    @Override
-    public ResponseBodyVO<String> saveEvaluationLevel(String projectId) {
+    return resultMap;
 
-        // 1 根据 projectId 查询一级指标
-        double scoreOfProject = simulationMptFirstTargetScoreMapper.selectScoreOfProject(projectId);
-        String evaluationLevel = ProjectUtil.getEvaluationLevelReport(scoreOfProject);
-        // -------------------------------- 保存结果 --------------------------------
-        // 1 根据 projectId 获取类型 projectType
-        String projectType = projectUtil.getProjectTypeByProjectId(projectId);
-        log.info("SimulationProjectServiceImpl--saveEvaluationLevel 项目 " + projectId + " 类型为 " + projectType);
-        if (DictConstants.PROJECT_TYPE_MANUAL.equals(projectType)) {
-            manualProjectMapper.updateEvaluationLevel(projectId, evaluationLevel);
-        } else if (DictConstants.PROJECT_TYPE_AUTO_SUB.equals(projectType)) {
-            autoSubProjectMapper.updateEvaluationLevel(projectId, evaluationLevel);
-        } else {
-            ;
-        }
-        log.info("SimulationProjectServiceImpl--saveEvaluationLevel 项目 " + projectId + " 的总分为: " + scoreOfProject
-                + ",评价等级为:" + evaluationLevel);
-
-        return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS, "评价等级为" + evaluationLevel, "");
-    }
-
-    // @Override
-    // public ResponseBodyVO<String> saveEvaluationLevel(String projectId) {
-    //
-    // //1 根据 projectId 获取类型 projectType
-    // String projectType = projectUtil.getProjectTypeByProjectId(projectId);
-    // log.info("SimulationProjectServiceImpl--saveEvaluationLevel 项目 " + projectId
-    // + " 类型为 " + projectType);
-    //
-    // //2 查询场景包 id
-    // String scene = null;
-    // if (DictConstants.PROJECT_TYPE_MANUAL.equals(projectType)) { // 手动运行
-    // scene = simulationProjectMapper.selectSceneById(projectId);
-    // } else if (DictConstants.PROJECT_TYPE_AUTO_SUB.equals(projectType)) {// 自动运行
-    // scene = simulationAutomaticSubProjectMapper.selectSceneById(projectId);
-    // }
-    // if (StringUtil.isEmpty(scene)) {
-    // return new ResponseBodyVO<>(ResponseBodyVO.Response.SERVER_FAILURE,
-    // "未查询到项目使用的场景测试包。");
-    // }
-    // log.info("SimulationProjectServiceImpl--saveEvaluationLevel 项目 " + projectId
-    // + " 使用的场景包为 " + scene);
-    //
-    // // -------------------------------- 计算评价等级 --------------------------------
-    // //TODO 该段代码可优化,有时间再优化
-    // //1 查询场景报告关联的指标
-    // List<ScenePackageSubListVO> scenePackageSubListVOS =
-    // simulationProjectMapper.selectSubSceneByPid(scene);
-    // String evaluationLevelReport = "";
-    // if (!isEmpty(scenePackageSubListVOS)) {
-    // double totalScore = 0.0;
-    // for (ScenePackageSubListVO v : scenePackageSubListVOS) {
-    // double weightDouble = Double.parseDouble(v.getWeight());
-    // // 根据一级指标计算总得分
-    // SimulationMptFirstTargetScorePo simulationMptFirstTargetScorePo = new
-    // SimulationMptFirstTargetScorePo();
-    // simulationMptFirstTargetScorePo.setPId(projectId); //直接(子)任务表id
-    // simulationMptFirstTargetScorePo.setTarget(v.getSublistId());
-    // SimulationMptFirstTargetScorePo simulationMptFirstTargetScorePo1 =
-    // simulationMptFirstTargetScoreMapper.selectFirstTargetScore(simulationMptFirstTargetScorePo);
-    // if (simulationMptFirstTargetScorePo1 == null) {
-    // continue;
-    // }
-    // Double score = simulationMptFirstTargetScorePo1.getScore();
-    // totalScore += score * (weightDouble / 100);
-    // }
-    // evaluationLevelReport = ProjectUtil.getEvaluationLevelReport(totalScore);
-    // log.info("SimulationProjectServiceImpl--saveEvaluationLevel 项目 " + projectId
-    // + " 的总分为: " + totalScore + ",评价等级为:" + evaluationLevelReport);
-    // }
-    // // -------------------------------- 保存结果 --------------------------------
-    // if (DictConstants.PROJECT_TYPE_MANUAL.equals(projectType)) {
-    // manualProjectMapper.updateEvaluationLevel(projectId, evaluationLevelReport);
-    // } else if (DictConstants.PROJECT_TYPE_AUTO_SUB.equals(projectType)) {
-    // autoSubProjectMapper.updateEvaluationLevel(projectId, evaluationLevelReport);
-    // } else {
-    // ;
-    // }
-    //
-    // return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS);
-    // }
+  }
+
+  /**
+   * 获取所有要合并的下标、每个下标索要合并的行数、要跳过创建表格的下标
+   */
+  private Map getSceneScListCombineCoord(List<SceneScListVo> voList, int size) {
+    int sublistNameSize = size - 5;// 指标最大级数
+    HashMap<String, Object> resultMap = new HashMap<>();
+    Map<String, CombineCoordVo> map = new HashMap<>();
+    Map<String, Integer> combineCoordMap = new HashMap<>(); // 要合并的格子下标
+    List<String> skipCoordList = new ArrayList<>(); // 要跳过的格子下标
 
-    @Override
-    public ResponseBodyVO saveTaskResult(SimulationManualProjectParam param) {
+    for (int i = 0; i < voList.size(); i++) {
+      SceneScListVo vo = voList.get(i);
+      if (sublistNameSize == 1) {
+        // 一级
+        String sublistName1 = vo.getSublistName1();
+        if (!isEmpty(sublistName1)) {
+          setCoord(map, sublistName1, i + ",0", skipCoordList);
+          setCoord(map, sublistName1 + "scoreExplain", i + "," + (size - 1), skipCoordList);
+        }
 
-        String projectId = param.getProjectId();
-        String taskId = param.getTaskId();
-        String runResultFilePath = param.getRunResultFilePath();
+      } else if (sublistNameSize == 2) {
+        // 二级
+        String sublistName1 = vo.getSublistName1();
+        String sublistName2 = vo.getSublistName2();
 
-        if (StringUtil.isEmpty(projectId)) {
-            return new ResponseBodyVO(ResponseBodyVO.Response.CLIENT_FAILURE, "工作id不能为空");
+        if (!isEmpty(sublistName1)) {
+          setCoord(map, sublistName1, i + ",0", skipCoordList);
         }
-        if (StringUtil.isEmpty(taskId)) {
-            return new ResponseBodyVO(ResponseBodyVO.Response.CLIENT_FAILURE, "任务id不能为空");
+        if (!isEmpty(sublistName2)) {
+          setCoord(map, sublistName2, i + ",1", skipCoordList);
+
         }
-        if (StringUtil.isEmpty(runResultFilePath)) {
-            return new ResponseBodyVO(ResponseBodyVO.Response.CLIENT_FAILURE, "地址不能为空");
+        if (!isEmpty(sublistName2)) {
+          setCoord(map, sublistName2 + "scoreExplain", i + "," + (size - 1), skipCoordList);
+        } else {
+          setCoord(map, sublistName1 + "scoreExplain", i + "," + (size - 1), skipCoordList);
         }
 
-        InputStream fileInputStream = null;
-        InputStreamReader inputStreamReader = null;
-        BufferedReader bufferedReader = null;
-        File file = null;
-        try {
-            // time
-            List<Double> time_list = new ArrayList<>();
-            // velocity
-            List<String> velocity_list = new ArrayList<>();
-            List<Double> lateral_velocity_list = new ArrayList<>();
-            List<Double> longitudinal_velocity_list = new ArrayList<>();
-            // acceleration
-            List<String> acceleration_list = new ArrayList<>();
-            List<Double> lateral_acceleration = new ArrayList<>();
-            List<Double> longitudinal_acceleration_list = new ArrayList<>();
-            // lane_offset
-            List<String> lane_offset_list = new ArrayList<>();
-            /// TODO brake 暂无
-            List<String> brake_list = new ArrayList<>();
-            // steeting_wheel
-            List<String> steeting_wheel_list = new ArrayList<>();
-            /// TODO throttle 暂无
-            List<String> throttle_list = new ArrayList<>();
-            // 摆角速度
-            List<Double> yawrate_list = new ArrayList<>();
-
-            MinioParameter minioParameter = new MinioParameter();
-            minioParameter.setObjectName(runResultFilePath + "/Ego.csv");
-            Response download = fileDownService.download(minioParameter);
-            Response.Body body = download.body();
-            fileInputStream = body.asInputStream();
-
-            /*
-             * file = new File("E:\\仿真云平台\\任务详情界面数据\\Ego(1).csv");
-             * fileInputStream = new FileInputStream(file);
-             * inputStreamReader = new InputStreamReader(fileInputStream,"utf-8");
-             */
-
-            inputStreamReader = new InputStreamReader(fileInputStream, "utf-8");
-            bufferedReader = new BufferedReader(inputStreamReader);
-            String line;
-            int lineIndex = 0;
-
-            while ((line = bufferedReader.readLine()) != null) {
-                lineIndex++;
-                if (lineIndex == 1) {
-                    continue;
-                }
-                String[] split = line.split(",");
-
-                // 添加异常捕获,非正常数据默认为0
-                try {
-                    Double aDouble = Double.valueOf(split[1]);
-                    if (aDouble.isNaN()) {
-                        time_list.add(0D);
-                    } else {
-                        time_list.add(aDouble);
-                    }
-                } catch (NumberFormatException e) {
-                    time_list.add(0D);
-                }
-
-                try {
-                    Double aDouble = Double.valueOf(split[6]);
-                    if (aDouble.isNaN()) {
-                        lateral_velocity_list.add(0D);
-                    } else {
-                        lateral_velocity_list.add(aDouble);
-                    }
-
-                } catch (NumberFormatException e) {
-                    lateral_velocity_list.add(0D);
-                }
-
-                try {
-                    Double aDouble = Double.valueOf(split[7]);
-                    if (aDouble.isNaN()) {
-                        longitudinal_velocity_list.add(0D);
-                    } else {
-                        longitudinal_velocity_list.add(aDouble);
-                    }
-
-                } catch (NumberFormatException e) {
-                    longitudinal_velocity_list.add(0D);
-                }
-
-                try {
-                    Double aDouble = Double.valueOf(split[8]);
-                    if (aDouble.isNaN()) {
-                        lateral_acceleration.add(0D);
-                    } else {
-                        lateral_acceleration.add(aDouble);
-                    }
-
-                } catch (NumberFormatException e) {
-                    lateral_acceleration.add(0D);
-                }
-
-                try {
-                    Double aDouble = Double.valueOf(split[9]);
-                    if (aDouble.isNaN()) {
-                        longitudinal_acceleration_list.add(0D);
-                    } else {
-                        longitudinal_acceleration_list.add(aDouble);
-                    }
-
-                } catch (NumberFormatException e) {
-                    longitudinal_acceleration_list.add(0D);
-                }
-
-                try {
-                    Double aDouble = Double.valueOf(split[12]);
-                    if (aDouble.isNaN()) {
-                        steeting_wheel_list.add("0");
-                    } else {
-                        steeting_wheel_list.add(String.valueOf(aDouble));// steering_angle
-                    }
-                } catch (NumberFormatException e) {
-                    steeting_wheel_list.add("0");
-                }
-
-                try {
-                    Double aDouble = Double.valueOf(split[13]);
-                    if (aDouble.isNaN()) {
-                        yawrate_list.add(0D);
-                    } else {
-                        yawrate_list.add(aDouble);
-                    }
-                } catch (NumberFormatException e) {
-                    yawrate_list.add(0D);
-                }
-
-                try {
-                    Double aDouble = Double.valueOf(split[27]);
-                    if (aDouble.isNaN()) {
-                        lane_offset_list.add("0");
-                    } else {
-                        lane_offset_list.add(String.valueOf(aDouble));// lane_center_offset
-                    }
-                } catch (NumberFormatException e) {
-                    lane_offset_list.add("0");
-                }
+      } else if (sublistNameSize == 3) {
+        // 三级
+        String sublistName1 = vo.getSublistName1();
+        String sublistName2 = vo.getSublistName2();
+        String sublistName3 = vo.getSublistName3();
 
-            }
+        if (!isEmpty(sublistName1)) {
+          setCoord(map, sublistName1, i + ",0", skipCoordList);
+        }
+        if (!isEmpty(sublistName2)) {
+          setCoord(map, sublistName2, i + ",1", skipCoordList);
+        }
+        if (!isEmpty(sublistName3)) {
+          setCoord(map, sublistName3, i + ",2", skipCoordList);
 
-            // 里程
-            Double lc = 0D;
-            for (int i = 0; i < time_list.size(); i++) {
-                if (i == 0) {
-                    continue;
-                }
-                lc += (time_list.get(i) - time_list.get(i - 1)) * longitudinal_velocity_list.get(i - 1);
+        }
+        if (!isEmpty(sublistName3)) {
+          setCoord(map, sublistName3 + "scoreExplain", i + "," + (size - 1), skipCoordList);
+        } else if (!isEmpty(sublistName2)) {
+          setCoord(map, sublistName2 + "scoreExplain", i + "," + (size - 1), skipCoordList);
+        } else {
+          setCoord(map, sublistName1 + "scoreExplain", i + "," + (size - 1), skipCoordList);
+        }
+      } else if (sublistNameSize == 4) {
+        // 四级
+        String sublistName1 = vo.getSublistName1();
+        String sublistName2 = vo.getSublistName2();
+        String sublistName3 = vo.getSublistName3();
+        String sublistName4 = vo.getSublistName4();
 
-            }
+        if (!isEmpty(sublistName1)) {
+          setCoord(map, sublistName1, i + ",0", skipCoordList);
+        }
+        if (!isEmpty(sublistName2)) {
+          setCoord(map, sublistName2, i + ",1", skipCoordList);
+        }
+        if (!isEmpty(sublistName3)) {
+          setCoord(map, sublistName3, i + ",2", skipCoordList);
+        }
+        if (!isEmpty(sublistName4)) {
+          setCoord(map, sublistName4, i + ",3", skipCoordList);
+        }
 
-            // 平均速度
-            Double pjsd = lc / time_list.get(time_list.size() - 1);
+        if (!isEmpty(sublistName4)) {
+          setCoord(map, sublistName4 + "scoreExplain", i + "," + (size - 1), skipCoordList);
+        } else if (!isEmpty(sublistName3)) {
+          setCoord(map, sublistName3 + "scoreExplain", i + "," + (size - 1), skipCoordList);
+        } else if (!isEmpty(sublistName2)) {
+          setCoord(map, sublistName2 + "scoreExplain", i + "," + (size - 1), skipCoordList);
+        } else {
+          setCoord(map, sublistName1 + "scoreExplain", i + "," + (size - 1), skipCoordList);
+        }
 
-            // 最大速度
-            Double zdsd = Collections.max(longitudinal_velocity_list);
+      } else if (sublistNameSize == 5) {
+        // 五级
+        String sublistName1 = vo.getSublistName1();
+        String sublistName2 = vo.getSublistName2();
+        String sublistName3 = vo.getSublistName3();
+        String sublistName4 = vo.getSublistName4();
+        String sublistName5 = vo.getSublistName5();
 
-            // 最小速度
-            Double zxsd = Collections.min(longitudinal_velocity_list);
+        if (!isEmpty(sublistName1)) {
+          setCoord(map, sublistName1, i + ",0", skipCoordList);
+        }
+        if (!isEmpty(sublistName2)) {
+          setCoord(map, sublistName2, i + ",1", skipCoordList);
+        }
+        if (!isEmpty(sublistName3)) {
+          setCoord(map, sublistName3, i + ",2", skipCoordList);
+        }
+        if (!isEmpty(sublistName4)) {
+          setCoord(map, sublistName4, i + ",3", skipCoordList);
+        }
+        if (!isEmpty(sublistName5)) {
+          setCoord(map, sublistName5, i + ",4", skipCoordList);
+        }
 
-            // 最大加速度
-            Double zdjiasd = Collections.max(longitudinal_acceleration_list);
+        if (!isEmpty(sublistName5)) {
+          setCoord(map, sublistName5 + "scoreExplain", i + "," + (size - 1), skipCoordList);
+        } else if (!isEmpty(sublistName4)) {
+          setCoord(map, sublistName4 + "scoreExplain", i + "," + (size - 1), skipCoordList);
+        } else if (!isEmpty(sublistName3)) {
+          setCoord(map, sublistName3 + "scoreExplain", i + "," + (size - 1), skipCoordList);
+        } else if (!isEmpty(sublistName2)) {
+          setCoord(map, sublistName2 + "scoreExplain", i + "," + (size - 1), skipCoordList);
+        } else {
+          setCoord(map, sublistName1 + "scoreExplain", i + "," + (size - 1), skipCoordList);
+        }
 
-            // 最大减速度
-            Double zdjiansd = Collections.min(longitudinal_acceleration_list);
+      } else if (sublistNameSize == 6) {
+        // 六级
+        String sublistName1 = vo.getSublistName1();
+        String sublistName2 = vo.getSublistName2();
+        String sublistName3 = vo.getSublistName3();
+        String sublistName4 = vo.getSublistName4();
+        String sublistName5 = vo.getSublistName5();
+        String sublistName6 = vo.getSublistName6();
 
-            // 最大摆角速度
-            Double zdbjsd = Collections.max(yawrate_list);
+        if (!isEmpty(sublistName1)) {
+          setCoord(map, sublistName1, i + ",0", skipCoordList);
+        }
+        if (!isEmpty(sublistName2)) {
+          setCoord(map, sublistName2, i + ",1", skipCoordList);
+        }
+        if (!isEmpty(sublistName3)) {
+          setCoord(map, sublistName3, i + ",2", skipCoordList);
+        }
+        if (!isEmpty(sublistName4)) {
+          setCoord(map, sublistName4, i + ",3", skipCoordList);
+        }
+        if (!isEmpty(sublistName5)) {
+          setCoord(map, sublistName5, i + ",4", skipCoordList);
+        }
+        if (!isEmpty(sublistName6)) {
+          setCoord(map, sublistName6, i + ",5", skipCoordList);
+          setCoord(map, sublistName1 + "scoreExplain", i + "," + (size - 1), skipCoordList);
+        }
 
-            // 自车速度方差
-            Double zcsdfc = 0D;
-            for (Double d : longitudinal_velocity_list) {
-                zcsdfc += Math.pow(d - pjsd, 2);
-            }
-            zcsdfc = zcsdfc / longitudinal_velocity_list.size();
+        if (!isEmpty(sublistName6)) {
+          setCoord(map, sublistName6 + "scoreExplain", i + "," + (size - 1), skipCoordList);
+        } else if (!isEmpty(sublistName5)) {
+          setCoord(map, sublistName5 + "scoreExplain", i + "," + (size - 1), skipCoordList);
+        } else if (!isEmpty(sublistName4)) {
+          setCoord(map, sublistName4 + "scoreExplain", i + "," + (size - 1), skipCoordList);
+        } else if (!isEmpty(sublistName3)) {
+          setCoord(map, sublistName3 + "scoreExplain", i + "," + (size - 1), skipCoordList);
+        } else if (!isEmpty(sublistName2)) {
+          setCoord(map, sublistName2 + "scoreExplain", i + "," + (size - 1), skipCoordList);
+        } else {
+          setCoord(map, sublistName1 + "scoreExplain", i + "," + (size - 1), skipCoordList);
+        }
 
-            // 自车横摆角速度均方根
-            Double zchbjsdjfg = 0D;
-            for (Double d : yawrate_list) {
-                zchbjsdjfg += Math.pow(d - pjsd, 2);
-            }
-            zchbjsdjfg = Math.sqrt(zchbjsdjfg / yawrate_list.size());
+      }
 
-            for (int i = 0; i < lateral_acceleration.size(); i++) {
-                Double aDouble = lateral_acceleration.get(i);
-                Double aDouble1 = longitudinal_acceleration_list.get(i);
-                Double d = Math.pow(aDouble, 2) + Math.pow(aDouble1, 2);
-                acceleration_list.add(String.valueOf(Math.sqrt(d)));
-            }
+    }
 
-            for (int i = 0; i < lateral_velocity_list.size(); i++) {
-                Double aDouble = lateral_velocity_list.get(i);
-                Double aDouble1 = longitudinal_velocity_list.get(i);
-                Double d = Math.pow(aDouble, 2) + Math.pow(aDouble1, 2);
-                velocity_list.add(String.valueOf(d));
-            }
+    /*
+     * List<CombineCoordVo> combineCoordVoList = new ArrayList<>();
+     *
+     * for(String k : map.keySet()){
+     * combineCoordVoList.add(map.get(k));
+     * }
+     */
 
-            // 将数据保存到库
-            ManualProjectTaskPo manualProjectTaskPo = new ManualProjectTaskPo();
-            manualProjectTaskPo.setId(taskId);
-            manualProjectTaskPo.setPId(projectId);
-            manualProjectTaskPo.setMileage(lc.toString());
-            manualProjectTaskPo.setAverageVelocity(pjsd.toString());
-            manualProjectTaskPo.setMaximunSpeed(zdsd.toString());
-            manualProjectTaskPo.setMinimunVelocity(zxsd.toString());
-            manualProjectTaskPo.setMaximumAcceleration(zdjiasd.toString());
-            manualProjectTaskPo.setMaximumDeceleration(zdjiansd.toString());
-            manualProjectTaskPo.setMaximumSwingSpeed(zdbjsd.toString());
-            manualProjectTaskPo.setSpeedVariance(String.valueOf(zcsdfc));
-            manualProjectTaskPo.setSwingSpeedMeanSquareRoot(String.valueOf(zchbjsdjfg));
-            manualProjectTaskPo.setAcceleration(String.join(",", acceleration_list));
-            manualProjectTaskPo.setLaneOffset(String.join(",", lane_offset_list));
-            manualProjectTaskPo.setBrake(String.join(",", brake_list));
-            manualProjectTaskPo.setSteetingWheel(String.join(",", steeting_wheel_list));
-            manualProjectTaskPo.setThrottle(String.join(",", throttle_list));
-            if (!isEmpty(yawrate_list)) {
-                StringBuffer sb = new StringBuffer();
-                for (Double d : yawrate_list) {
-                    sb.append(d + ",");
-                }
-                String s = sb.substring(0, sb.lastIndexOf(","));
-                manualProjectTaskPo.setYawRate(s);
-            }
-            manualProjectTaskPo.setVelocity(String.join(",", velocity_list));
-            manualProjectTaskPo.setOtherCurve("");/// TODO 其他暂无
-
-            if (!isEmpty(time_list)) {
-                StringBuffer sb = new StringBuffer();
-                for (Double d : time_list) {
-                    sb.append(d + ",");
-                }
-                String s = sb.substring(0, sb.lastIndexOf(","));
-                manualProjectTaskPo.setTimerShaft(s);
-            }
+    for (String k : map.keySet()) {
+      CombineCoordVo combineCoordVo = map.get(k);
+      combineCoordMap.put(combineCoordVo.getCoord(), combineCoordVo.getRepetitionNum());
+    }
 
-            simulationProjectTaskMapper.updateTaksResult(manualProjectTaskPo);
+    resultMap.put("combineCoordList", combineCoordMap);
+    resultMap.put("skipCoordList", skipCoordList);
 
-        } catch (Exception e) {
-            e.printStackTrace();
-        } finally {
-            try {
-                if (fileInputStream != null) {
-                    fileInputStream.close();
-                }
-                if (inputStreamReader != null) {
-                    inputStreamReader.close();
-                }
-                if (bufferedReader != null) {
-                    bufferedReader.close();
-                }
-                /*
-                 * if(file != null ){
-                 * file.delete();
-                 * }
-                 */
-            } catch (IOException e) {
-                e.printStackTrace();
+    return resultMap;
 
-            }
-        }
+  }
 
-        return new ResponseBodyVO(ResponseBodyVO.Response.SUCCESS);
+  private void setCoord(Map<String, CombineCoordVo> map, String key, String coord, List<String> skipCoordList) {
+    CombineCoordVo value = map.get(key);
+    if (value != null) {
+      // 坐标不变,合并行数+1
+      value.setRepetitionNum(value.getRepetitionNum() + 1);
+      skipCoordList.add(coord);
+    } else {
+      // 新增
+      CombineCoordVo combineCoordVo = new CombineCoordVo();
+      combineCoordVo.setCoord(coord);
+      combineCoordVo.setRepetitionNum(1);
+      map.put(key, combineCoordVo);
 
     }
+  }
 
-    @Override
-    public void exportProjectTaskFileById(SimulationManualProjectParam param) {
-        String id = param.getId();
+  @Override
+  public String selectProjectReportIdByAlgorithmId(String algorithmId) {
+    SimulationManualProjectPo po = simulationProjectMapper.selectProjectReportIdByAlgorithmId(algorithmId);
+    if (StringUtil.isNotEmpty(po)) {
+      return po.getId();
+    }
+    return null;
+  }
+
+  @Override
+  public ResponseBodyVO<String> saveEvaluationLevel(String projectId) {
+
+    // 1 根据 projectId 查询一级指标
+    double scoreOfProject = simulationMptFirstTargetScoreMapper.selectScoreOfProject(projectId);
+    String evaluationLevel = ProjectUtil.getEvaluationLevelReport(scoreOfProject);
+    // -------------------------------- 保存结果 --------------------------------
+    // 1 根据 projectId 获取类型 projectType
+    String projectType = projectUtil.getProjectTypeByProjectId(projectId);
+    log.info("SimulationProjectServiceImpl--saveEvaluationLevel 项目 " + projectId + " 类型为 " + projectType);
+    if (DictConstants.PROJECT_TYPE_MANUAL.equals(projectType)) {
+      manualProjectMapper.updateEvaluationLevel(projectId, evaluationLevel);
+    } else if (DictConstants.PROJECT_TYPE_AUTO_SUB.equals(projectType)) {
+      autoSubProjectMapper.updateEvaluationLevel(projectId, evaluationLevel);
+    } else {
+      ;
+    }
+    log.info("SimulationProjectServiceImpl--saveEvaluationLevel 项目 " + projectId + " 的总分为: " + scoreOfProject + ",评价等级为:" + evaluationLevel);
+
+    return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS, "评价等级为" + evaluationLevel, "");
+  }
+
+  // @Override
+  // public ResponseBodyVO<String> saveEvaluationLevel(String projectId) {
+  //
+  // //1 根据 projectId 获取类型 projectType
+  // String projectType = projectUtil.getProjectTypeByProjectId(projectId);
+  // log.info("SimulationProjectServiceImpl--saveEvaluationLevel 项目 " + projectId
+  // + " 类型为 " + projectType);
+  //
+  // //2 查询场景包 id
+  // String scene = null;
+  // if (DictConstants.PROJECT_TYPE_MANUAL.equals(projectType)) { // 手动运行
+  // scene = simulationProjectMapper.selectSceneById(projectId);
+  // } else if (DictConstants.PROJECT_TYPE_AUTO_SUB.equals(projectType)) {// 自动运行
+  // scene = simulationAutomaticSubProjectMapper.selectSceneById(projectId);
+  // }
+  // if (StringUtil.isEmpty(scene)) {
+  // return new ResponseBodyVO<>(ResponseBodyVO.Response.SERVER_FAILURE,
+  // "未查询到项目使用的场景测试包。");
+  // }
+  // log.info("SimulationProjectServiceImpl--saveEvaluationLevel 项目 " + projectId
+  // + " 使用的场景包为 " + scene);
+  //
+  // // -------------------------------- 计算评价等级 --------------------------------
+  // //TODO 该段代码可优化,有时间再优化
+  // //1 查询场景报告关联的指标
+  // List<ScenePackageSubListVO> scenePackageSubListVOS =
+  // simulationProjectMapper.selectSubSceneByPid(scene);
+  // String evaluationLevelReport = "";
+  // if (!isEmpty(scenePackageSubListVOS)) {
+  // double totalScore = 0.0;
+  // for (ScenePackageSubListVO v : scenePackageSubListVOS) {
+  // double weightDouble = Double.parseDouble(v.getWeight());
+  // // 根据一级指标计算总得分
+  // SimulationMptFirstTargetScorePo simulationMptFirstTargetScorePo = new
+  // SimulationMptFirstTargetScorePo();
+  // simulationMptFirstTargetScorePo.setPId(projectId); //直接(子)任务表id
+  // simulationMptFirstTargetScorePo.setTarget(v.getSublistId());
+  // SimulationMptFirstTargetScorePo simulationMptFirstTargetScorePo1 =
+  // simulationMptFirstTargetScoreMapper.selectFirstTargetScore(simulationMptFirstTargetScorePo);
+  // if (simulationMptFirstTargetScorePo1 == null) {
+  // continue;
+  // }
+  // Double score = simulationMptFirstTargetScorePo1.getScore();
+  // totalScore += score * (weightDouble / 100);
+  // }
+  // evaluationLevelReport = ProjectUtil.getEvaluationLevelReport(totalScore);
+  // log.info("SimulationProjectServiceImpl--saveEvaluationLevel 项目 " + projectId
+  // + " 的总分为: " + totalScore + ",评价等级为:" + evaluationLevelReport);
+  // }
+  // // -------------------------------- 保存结果 --------------------------------
+  // if (DictConstants.PROJECT_TYPE_MANUAL.equals(projectType)) {
+  // manualProjectMapper.updateEvaluationLevel(projectId, evaluationLevelReport);
+  // } else if (DictConstants.PROJECT_TYPE_AUTO_SUB.equals(projectType)) {
+  // autoSubProjectMapper.updateEvaluationLevel(projectId, evaluationLevelReport);
+  // } else {
+  // ;
+  // }
+  //
+  // return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS);
+  // }
+
+  @Override
+  public ResponseBodyVO saveTaskResult(SimulationManualProjectParam param) {
+
+    String projectId = param.getProjectId();
+    String taskId = param.getTaskId();
+    String runResultFilePath = param.getRunResultFilePath();
+
+    if (StringUtil.isEmpty(projectId)) {
+      return new ResponseBodyVO(ResponseBodyVO.Response.CLIENT_FAILURE, "工作id不能为空");
+    }
+    if (StringUtil.isEmpty(taskId)) {
+      return new ResponseBodyVO(ResponseBodyVO.Response.CLIENT_FAILURE, "任务id不能为空");
+    }
+    if (StringUtil.isEmpty(runResultFilePath)) {
+      return new ResponseBodyVO(ResponseBodyVO.Response.CLIENT_FAILURE, "地址不能为空");
+    }
 
-        // 获取任务包信息
-        ProjectTaskParam projectTaskParam = new ProjectTaskParam();
-        projectTaskParam.setPId(id);
-        List<ManualProjectTaskVo> manualProjectTaskVos = simulationProjectTaskMapper
-                .selectProjectTaskByProjectId(projectTaskParam);
-        if (isEmpty(manualProjectTaskVos)) {
-            throw new RuntimeException("没有获取到任务信息。");
+    InputStream fileInputStream = null;
+    InputStreamReader inputStreamReader = null;
+    BufferedReader bufferedReader = null;
+    File file = null;
+    try {
+      // time
+      List<Double> time_list = new ArrayList<>();
+      // velocity
+      List<String> velocity_list = new ArrayList<>();
+      List<Double> lateral_velocity_list = new ArrayList<>();
+      List<Double> longitudinal_velocity_list = new ArrayList<>();
+      // acceleration
+      List<String> acceleration_list = new ArrayList<>();
+      List<Double> lateral_acceleration = new ArrayList<>();
+      List<Double> longitudinal_acceleration_list = new ArrayList<>();
+      // lane_offset
+      List<String> lane_offset_list = new ArrayList<>();
+      /// TODO brake 暂无
+      List<String> brake_list = new ArrayList<>();
+      // steeting_wheel
+      List<String> steeting_wheel_list = new ArrayList<>();
+      /// TODO throttle 暂无
+      List<String> throttle_list = new ArrayList<>();
+      // 摆角速度
+      List<Double> yawrate_list = new ArrayList<>();
+
+      MinioParameter minioParameter = new MinioParameter();
+      minioParameter.setObjectName(runResultFilePath + "/Ego.csv");
+      Response download = fileDownService.download(minioParameter);
+      Response.Body body = download.body();
+      fileInputStream = body.asInputStream();
+
+      /*
+       * file = new File("E:\\仿真云平台\\任务详情界面数据\\Ego(1).csv");
+       * fileInputStream = new FileInputStream(file);
+       * inputStreamReader = new InputStreamReader(fileInputStream,"utf-8");
+       */
+
+      inputStreamReader = new InputStreamReader(fileInputStream, "utf-8");
+      bufferedReader = new BufferedReader(inputStreamReader);
+      String line;
+      int lineIndex = 0;
+
+      while ((line = bufferedReader.readLine()) != null) {
+        lineIndex++;
+        if (lineIndex == 1) {
+          continue;
+        }
+        String[] split = line.split(",");
+
+        // 添加异常捕获,非正常数据默认为0
+        try {
+          Double aDouble = Double.valueOf(split[1]);
+          if (aDouble.isNaN()) {
+            time_list.add(0D);
+          } else {
+            time_list.add(aDouble);
+          }
+        } catch (NumberFormatException e) {
+          time_list.add(0D);
         }
 
-        // 压缩包根路径
-        SimulationManualProjectParam sp = new SimulationManualProjectParam();
-        sp.setId(id);
-        SimulationManualProjectPo spo = simulationProjectMapper.selectProjectBaseById(sp);
-        String rootPath = spo.getProjectName();
-        // FileUtil.createDirectory(rootPath);
-
-        int len;
-        byte[] buffer = new byte[1024];
-        // BufferedInputStream in = null;
-        ZipOutputStream zos = null;
-        // InputStream inputStream = null;
-        File pdfFile = null;
         try {
-            HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
-                    .getResponse();
-            response.setContentType("multipart/form-data");
-            response.setHeader("Content-Disposition", "attachment;fileName=" + URLEncoder.encode("运行任务包.zip", "UTF-8"));
-            zos = new ZipOutputStream(response.getOutputStream());
-            int i = 1;
-            // ArrayList<String> fileList = CollectionUtil.createArrayList("Ego.csv",
-            // "evaluation.csv");
-            for (ManualProjectTaskVo task : manualProjectTaskVos) {
-                String taskId = task.getId();
-                String runResultFilePath = task.getRunResultFilePath();
-                if (!isEmpty(runResultFilePath)) {
-
-                    // 获取场景名
-                    SceneBaseInfoVo sceneBaseInfoVo = getSceneNameAndOther(task.getSceneId(), task.getSceneType());
-                    String sceneName = sceneBaseInfoVo.getCommonSceneName();
-
-                    // 任务包路径
-                    // String taskPagePath = rootPath + File.separator + sceneName + "(" + i + ")";
-                    String taskPagePath = rootPath + File.separator + sceneName + "- " + taskId.substring(0, 8);
-
-                    // 视频文件路径
-                    MinioParameter minioParameter1 = new MinioParameter();
-                    minioParameter1.setObjectName(runResultFilePath);
-                    ResponseBodyVO<List<String>> list = fileDownService.list(minioParameter1);
-                    List<String> info = list.getInfo();
-                    for (String s : info) {
-                        String fileName;
-                        String zipPath;
-                        // 获取文件名
-                        if (s.contains("/")) {
-                            fileName = s.substring(s.lastIndexOf("/") + 1);
-                        } else {
-                            fileName = s.substring(s.lastIndexOf("\\") + 1);
-                        }
-                        zipPath = taskPagePath + File.separator + fileName;
-                        // 文件后缀
-                        String substring = s.substring(s.lastIndexOf(".") + 1);
-                        if ("mp4".equals(substring)) {
-                            // mp4视频文件导出
-                            MinioParameter minioParameter2 = new MinioParameter();
-                            minioParameter2.setObjectName(s);
-                            Response download2 = fileDownService.download(minioParameter2);
-                            Response.Body body2 = download2.body();
-                            ZipEntry entry2 = new ZipEntry(zipPath);
-                            zos.putNextEntry(entry2);
-                            BufferedInputStream in = new BufferedInputStream(body2.asInputStream());
-                            while ((len = in.read(buffer)) != -1) {
-                                zos.write(buffer, 0, len);
-                            }
-                            in.close();
-                        } else if ("Ego.csv".equals(fileName) || "evaluation.csv".equals(fileName)) {
-
-                            MinioParameter minioParameter = new MinioParameter();
-                            if (s.contains("/")) {
-                                minioParameter.setObjectName(runResultFilePath + "/" + fileName);
-                            } else {
-                                minioParameter.setObjectName(runResultFilePath + "\\" + fileName);
-                            }
-
-                            Response download = fileDownService.download(minioParameter);
-                            Response.Body body = download.body();
-
-                            // 任务文件路径
-                            String taskFilePath = taskPagePath + File.separator + fileName;
-
-                            ZipEntry entry = new ZipEntry(taskFilePath);
-                            zos.putNextEntry(entry);
-                            BufferedInputStream in = new BufferedInputStream(body.asInputStream());
-                            while ((len = in.read(buffer)) != -1) {
-                                zos.write(buffer, 0, len);
-                            }
-                            in.close();
-                        }
-                    }
-                    i++;
-                }
-            }
+          Double aDouble = Double.valueOf(split[6]);
+          if (aDouble.isNaN()) {
+            lateral_velocity_list.add(0D);
+          } else {
+            lateral_velocity_list.add(aDouble);
+          }
 
-            // 打包pdf
-            if (param.getIsPagePdf() != null && param.getIsPagePdf()) {
-                // 获取工作信息
-                SimulationManualProjectPo p = simulationProjectMapper.selectProjectBaseById(param);
-                final String algorithmName = algorithmMapper.selectAlgorithmNameByAlgorithmId(param.getAlgorithm());
-
-                pdfFile = new File(param.getLocalPdfFilePath());
-                FileInputStream fileInputStream = new FileInputStream(pdfFile);
-                BufferedInputStream in = new BufferedInputStream(fileInputStream);
-                ZipEntry entry = new ZipEntry(rootPath + File.separator + algorithmName + "评价报告.pdf");
-                zos.putNextEntry(entry);
-                while ((len = in.read(buffer)) != -1) {
-                    zos.write(buffer, 0, len);
-                }
-                in.close();
-            }
+        } catch (NumberFormatException e) {
+          lateral_velocity_list.add(0D);
+        }
 
-        } catch (Exception e) {
-            e.printStackTrace();
-        } finally {
-            try {
-                if (zos != null) {
-                    zos.close();
-                }
-                if (pdfFile != null) {
-                    pdfFile.delete();
-                }
-            } catch (IOException e) {
-                e.printStackTrace();
-            }
+        try {
+          Double aDouble = Double.valueOf(split[7]);
+          if (aDouble.isNaN()) {
+            longitudinal_velocity_list.add(0D);
+          } else {
+            longitudinal_velocity_list.add(aDouble);
+          }
 
+        } catch (NumberFormatException e) {
+          longitudinal_velocity_list.add(0D);
         }
 
-    }
+        try {
+          Double aDouble = Double.valueOf(split[8]);
+          if (aDouble.isNaN()) {
+            lateral_acceleration.add(0D);
+          } else {
+            lateral_acceleration.add(aDouble);
+          }
 
-    @Override
-    public void exportProjectReportAndTaskFileById(SimulationManualProjectParam param) {
-        // 生成本地pdf
-        param.setIsCreateLocalPdfFile(true);
-        param.setLocalPdfFilePath(StringUtil.getRandomUUID() + ".pdf");
-        param.setIsPagePdf(true);
-        // 下载报告和任务包
-        exportProjectReport(param);
-        exportProjectTaskFileById(param);
-    }
+        } catch (NumberFormatException e) {
+          lateral_acceleration.add(0D);
+        }
 
-    @Override
-    public ResponseBodyVO addOrUpdateAutomaticProject(SimulationManualProjectParam param) {
+        try {
+          Double aDouble = Double.valueOf(split[9]);
+          if (aDouble.isNaN()) {
+            longitudinal_acceleration_list.add(0D);
+          } else {
+            longitudinal_acceleration_list.add(aDouble);
+          }
 
-        if (isEmpty(param.getProjectName())) {
-            return new ResponseBodyVO(ResponseBodyVO.Response.CLIENT_FAILURE, "工作名称不能为空");
+        } catch (NumberFormatException e) {
+          longitudinal_acceleration_list.add(0D);
         }
-        // 校验cron表达式(运行周期)
-        String operationCycle = param.getOperationCycle();
-        if (isEmpty(operationCycle)) {
-            return new ResponseBodyVO(ResponseBodyVO.Response.CLIENT_FAILURE, "运行周期为必填项");
+
+        try {
+          Double aDouble = Double.valueOf(split[12]);
+          if (aDouble.isNaN()) {
+            steeting_wheel_list.add("0");
+          } else {
+            steeting_wheel_list.add(String.valueOf(aDouble));// steering_angle
+          }
+        } catch (NumberFormatException e) {
+          steeting_wheel_list.add("0");
         }
+
         try {
-            CronExpression.parse(operationCycle);
-        } catch (Exception e) {
-            return new ResponseBodyVO(ResponseBodyVO.Response.CLIENT_FAILURE, "运行周期格式不对");
+          Double aDouble = Double.valueOf(split[13]);
+          if (aDouble.isNaN()) {
+            yawrate_list.add(0D);
+          } else {
+            yawrate_list.add(aDouble);
+          }
+        } catch (NumberFormatException e) {
+          yawrate_list.add(0D);
         }
 
-        // 创建自动运行任务时自动运行状态默认为关闭(1)
-        param.setAutomaticRunState("1");
+        try {
+          Double aDouble = Double.valueOf(split[27]);
+          if (aDouble.isNaN()) {
+            lane_offset_list.add("0");
+          } else {
+            lane_offset_list.add(String.valueOf(aDouble));// lane_center_offset
+          }
+        } catch (NumberFormatException e) {
+          lane_offset_list.add("0");
+        }
+
+      }
+
+      // 里程
+      Double lc = 0D;
+      for (int i = 0; i < time_list.size(); i++) {
+        if (i == 0) {
+          continue;
+        }
+        lc += (time_list.get(i) - time_list.get(i - 1)) * longitudinal_velocity_list.get(i - 1);
+
+      }
+
+      // 平均速度
+      Double pjsd = lc / time_list.get(time_list.size() - 1);
+
+      // 最大速度
+      Double zdsd = Collections.max(longitudinal_velocity_list);
+
+      // 最小速度
+      Double zxsd = Collections.min(longitudinal_velocity_list);
+
+      // 最大加速度
+      Double zdjiasd = Collections.max(longitudinal_acceleration_list);
+
+      // 最大减速度
+      Double zdjiansd = Collections.min(longitudinal_acceleration_list);
+
+      // 最大摆角速度
+      Double zdbjsd = Collections.max(yawrate_list);
+
+      // 自车速度方差
+      Double zcsdfc = 0D;
+      for (Double d : longitudinal_velocity_list) {
+        zcsdfc += Math.pow(d - pjsd, 2);
+      }
+      zcsdfc = zcsdfc / longitudinal_velocity_list.size();
+
+      // 自车横摆角速度均方根
+      Double zchbjsdjfg = 0D;
+      for (Double d : yawrate_list) {
+        zchbjsdjfg += Math.pow(d - pjsd, 2);
+      }
+      zchbjsdjfg = Math.sqrt(zchbjsdjfg / yawrate_list.size());
+
+      for (int i = 0; i < lateral_acceleration.size(); i++) {
+        Double aDouble = lateral_acceleration.get(i);
+        Double aDouble1 = longitudinal_acceleration_list.get(i);
+        Double d = Math.pow(aDouble, 2) + Math.pow(aDouble1, 2);
+        acceleration_list.add(String.valueOf(Math.sqrt(d)));
+      }
+
+      for (int i = 0; i < lateral_velocity_list.size(); i++) {
+        Double aDouble = lateral_velocity_list.get(i);
+        Double aDouble1 = longitudinal_velocity_list.get(i);
+        Double d = Math.pow(aDouble, 2) + Math.pow(aDouble1, 2);
+        velocity_list.add(String.valueOf(d));
+      }
+
+      // 将数据保存到库
+      ManualProjectTaskPo manualProjectTaskPo = new ManualProjectTaskPo();
+      manualProjectTaskPo.setId(taskId);
+      manualProjectTaskPo.setPId(projectId);
+      manualProjectTaskPo.setMileage(lc.toString());
+      manualProjectTaskPo.setAverageVelocity(pjsd.toString());
+      manualProjectTaskPo.setMaximunSpeed(zdsd.toString());
+      manualProjectTaskPo.setMinimunVelocity(zxsd.toString());
+      manualProjectTaskPo.setMaximumAcceleration(zdjiasd.toString());
+      manualProjectTaskPo.setMaximumDeceleration(zdjiansd.toString());
+      manualProjectTaskPo.setMaximumSwingSpeed(zdbjsd.toString());
+      manualProjectTaskPo.setSpeedVariance(String.valueOf(zcsdfc));
+      manualProjectTaskPo.setSwingSpeedMeanSquareRoot(String.valueOf(zchbjsdjfg));
+      manualProjectTaskPo.setAcceleration(String.join(",", acceleration_list));
+      manualProjectTaskPo.setLaneOffset(String.join(",", lane_offset_list));
+      manualProjectTaskPo.setBrake(String.join(",", brake_list));
+      manualProjectTaskPo.setSteetingWheel(String.join(",", steeting_wheel_list));
+      manualProjectTaskPo.setThrottle(String.join(",", throttle_list));
+      if (!isEmpty(yawrate_list)) {
+        StringBuffer sb = new StringBuffer();
+        for (Double d : yawrate_list) {
+          sb.append(d + ",");
+        }
+        String s = sb.substring(0, sb.lastIndexOf(","));
+        manualProjectTaskPo.setYawRate(s);
+      }
+      manualProjectTaskPo.setVelocity(String.join(",", velocity_list));
+      manualProjectTaskPo.setOtherCurve("");/// TODO 其他暂无
+
+      if (!isEmpty(time_list)) {
+        StringBuffer sb = new StringBuffer();
+        for (Double d : time_list) {
+          sb.append(d + ",");
+        }
+        String s = sb.substring(0, sb.lastIndexOf(","));
+        manualProjectTaskPo.setTimerShaft(s);
+      }
+
+      simulationProjectTaskMapper.updateTaksResult(manualProjectTaskPo);
+
+    } catch (Exception e) {
+      e.printStackTrace();
+    } finally {
+      try {
+        if (fileInputStream != null) {
+          fileInputStream.close();
+        }
+        if (inputStreamReader != null) {
+          inputStreamReader.close();
+        }
+        if (bufferedReader != null) {
+          bufferedReader.close();
+        }
+        /*
+         * if(file != null ){
+         * file.delete();
+         * }
+         */
+      } catch (IOException e) {
+        e.printStackTrace();
 
-        SimulationAutomaticProjectPo po = convertToSimulationAutomaticProjectPo(param);
+      }
+    }
 
-        if (isEmpty(param.getId())) {
-            // 工作名称一样的的不能创建
-            List<SimulationAutomaticProjectPo> simulationManualProjectPos = simulationAutomaticProjectMapper
-                    .selectAutomaticProjectByQuery(param);
-            if (!isEmpty(simulationManualProjectPos)) {
-                return new ResponseBodyVO(ResponseBodyVO.Response.CLIENT_FAILURE, "工作名称已经存在,请修改后再保存");
-            }
-            po.createPo(AuthUtil.getCurrentUserId());
-            // 生成id
-            createProjectId(po);
-            int add = simulationAutomaticProjectMapper.add(po);
-            if (add > 0) {
-                return new ResponseBodyVO(ResponseBodyVO.Response.SUCCESS, ResponseBodyVO.Response.SUCCESS.getMessage(),
-                        po.getId());
-            }
-            return new ResponseBodyVO(ResponseBodyVO.Response.SERVER_FAILURE, "添加失败");
-        } else {
+    return new ResponseBodyVO(ResponseBodyVO.Response.SUCCESS);
 
-            SimulationAutomaticProjectPo saPo = simulationAutomaticProjectMapper.selectById(param.getId());
+  }
 
-            // 自动运行状态为关闭的才可以修改
-            if ("0".equals(saPo.getAutomaticRunState())) {
-                return new ResponseBodyVO(ResponseBodyVO.Response.SERVER_FAILURE, "自动任务开启状态不支持修改");
-            }
+  @Override
+  public void exportProjectTaskFileById(SimulationManualProjectParam param) {
+    String id = param.getId();
 
-            po.updatePo(AuthUtil.getCurrentUserId());
-            int update = simulationAutomaticProjectMapper.updateById(po);
-            if (update > 0) {
-                return new ResponseBodyVO(ResponseBodyVO.Response.SUCCESS, ResponseBodyVO.Response.SUCCESS.getMessage(),
-                        po.getId());
-            }
+    // 获取任务包信息
+    ProjectTaskParam projectTaskParam = new ProjectTaskParam();
+    projectTaskParam.setPId(id);
+    List<ManualProjectTaskVo> manualProjectTaskVos = simulationProjectTaskMapper.selectProjectTaskByProjectId(projectTaskParam);
+    if (isEmpty(manualProjectTaskVos)) {
+      throw new RuntimeException("没有获取到任务信息。");
+    }
 
-            return new ResponseBodyVO(ResponseBodyVO.Response.SERVER_FAILURE, "修改失败");
-        }
+    // 压缩包根路径
+    SimulationManualProjectParam sp = new SimulationManualProjectParam();
+    sp.setId(id);
+    SimulationManualProjectPo spo = simulationProjectMapper.selectProjectBaseById(sp);
+    String rootPath = spo.getProjectName();
+    // FileUtil.createDirectory(rootPath);
+
+    int len;
+    byte[] buffer = new byte[1024];
+    // BufferedInputStream in = null;
+    ZipOutputStream zos = null;
+    // InputStream inputStream = null;
+    File pdfFile = null;
+    try {
+      HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
+      response.setContentType("multipart/form-data");
+      response.setHeader("Content-Disposition", "attachment;fileName=" + URLEncoder.encode("运行任务包.zip", "UTF-8"));
+      zos = new ZipOutputStream(response.getOutputStream());
+      int i = 1;
+      // ArrayList<String> fileList = CollectionUtil.createArrayList("Ego.csv",
+      // "evaluation.csv");
+      for (ManualProjectTaskVo task : manualProjectTaskVos) {
+        String taskId = task.getId();
+        String runResultFilePath = task.getRunResultFilePath();
+        if (!isEmpty(runResultFilePath)) {
+
+          // 获取场景名
+          SceneBaseInfoVo sceneBaseInfoVo = getSceneNameAndOther(task.getSceneId(), task.getSceneType());
+          String sceneName = sceneBaseInfoVo.getCommonSceneName();
+
+          // 任务包路径
+          // String taskPagePath = rootPath + File.separator + sceneName + "(" + i + ")";
+          String taskPagePath = rootPath + File.separator + sceneName + "- " + taskId.substring(0, 8);
+
+          // 视频文件路径
+          MinioParameter minioParameter1 = new MinioParameter();
+          minioParameter1.setObjectName(runResultFilePath);
+          ResponseBodyVO<List<String>> list = fileDownService.list(minioParameter1);
+          List<String> info = list.getInfo();
+          for (String s : info) {
+            String fileName;
+            String zipPath;
+            // 获取文件名
+            if (s.contains("/")) {
+              fileName = s.substring(s.lastIndexOf("/") + 1);
+            } else {
+              fileName = s.substring(s.lastIndexOf("\\") + 1);
+            }
+            zipPath = taskPagePath + File.separator + fileName;
+            // 文件后缀
+            String substring = s.substring(s.lastIndexOf(".") + 1);
+            if ("mp4".equals(substring)) {
+              // mp4视频文件导出
+              MinioParameter minioParameter2 = new MinioParameter();
+              minioParameter2.setObjectName(s);
+              Response download2 = fileDownService.download(minioParameter2);
+              Response.Body body2 = download2.body();
+              ZipEntry entry2 = new ZipEntry(zipPath);
+              zos.putNextEntry(entry2);
+              BufferedInputStream in = new BufferedInputStream(body2.asInputStream());
+              while ((len = in.read(buffer)) != -1) {
+                zos.write(buffer, 0, len);
+              }
+              in.close();
+            } else if ("Ego.csv".equals(fileName) || "evaluation.csv".equals(fileName)) {
+
+              MinioParameter minioParameter = new MinioParameter();
+              if (s.contains("/")) {
+                minioParameter.setObjectName(runResultFilePath + "/" + fileName);
+              } else {
+                minioParameter.setObjectName(runResultFilePath + "\\" + fileName);
+              }
+
+              Response download = fileDownService.download(minioParameter);
+              Response.Body body = download.body();
+
+              // 任务文件路径
+              String taskFilePath = taskPagePath + File.separator + fileName;
+
+              ZipEntry entry = new ZipEntry(taskFilePath);
+              zos.putNextEntry(entry);
+              BufferedInputStream in = new BufferedInputStream(body.asInputStream());
+              while ((len = in.read(buffer)) != -1) {
+                zos.write(buffer, 0, len);
+              }
+              in.close();
+            }
+          }
+          i++;
+        }
+      }
+
+      // 打包pdf
+      if (param.getIsPagePdf() != null && param.getIsPagePdf()) {
+        // 获取工作信息
+        SimulationManualProjectPo p = simulationProjectMapper.selectProjectBaseById(param);
+        final String algorithmName = algorithmMapper.selectAlgorithmNameByAlgorithmId(param.getAlgorithm());
+
+        pdfFile = new File(param.getLocalPdfFilePath());
+        FileInputStream fileInputStream = new FileInputStream(pdfFile);
+        BufferedInputStream in = new BufferedInputStream(fileInputStream);
+        ZipEntry entry = new ZipEntry(rootPath + File.separator + algorithmName + "评价报告.pdf");
+        zos.putNextEntry(entry);
+        while ((len = in.read(buffer)) != -1) {
+          zos.write(buffer, 0, len);
+        }
+        in.close();
+      }
+
+    } catch (Exception e) {
+      e.printStackTrace();
+    } finally {
+      try {
+        if (zos != null) {
+          zos.close();
+        }
+        if (pdfFile != null) {
+          pdfFile.delete();
+        }
+      } catch (IOException e) {
+        e.printStackTrace();
+      }
 
     }
 
-    @Override
-    public ResponseBodyVO<String> deleteAutomaticProjectByids(SimulationManualProjectParam param) {
-        String ids = param.getIds();
-        String[] idArr = ids.split(",");
+  }
 
-        List<SimulationAutomaticProjectPo> pos = simulationAutomaticProjectMapper.selectProjectNowRunState(idArr);
-
-        // 已经启动定时任务的项目不可以删除
-        for (SimulationAutomaticProjectPo p : pos) {
-            if ("0".equals(p.getAutomaticRunState())) {
-                return new ResponseBodyVO<>(ResponseBodyVO.Response.SERVER_FAILURE, "自动任务开启状态不支持删除");
-            }
-        }
+  @Override
+  public void exportProjectReportAndTaskFileById(SimulationManualProjectParam param) {
+    // 生成本地pdf
+    param.setIsCreateLocalPdfFile(true);
+    param.setLocalPdfFilePath(StringUtil.getRandomUUID() + ".pdf");
+    param.setIsPagePdf(true);
+    // 下载报告和任务包
+    exportProjectReport(param);
+    exportProjectTaskFileById(param);
+  }
 
-        int i = simulationAutomaticProjectMapper.deleteProject(idArr);
-        if (i > 0) {
-            return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS);
-        }
+  @Override
+  public ResponseBodyVO addOrUpdateAutomaticProject(SimulationManualProjectParam param) {
 
-        return new ResponseBodyVO<>(ResponseBodyVO.Response.SERVER_FAILURE, "删除失败");
+    if (isEmpty(param.getProjectName())) {
+      return new ResponseBodyVO(ResponseBodyVO.Response.CLIENT_FAILURE, "工作名称不能为空");
     }
-
-    @Override
-    public ResponseBodyVO<String> updateAutomaticRunState(SimulationManualProjectParam param) {
-        String id = param.getId();
-        String automaticRunState = param.getAutomaticRunState();
-        Optional.ofNullable(id).orElseThrow(() -> new RuntimeException("id 不能为空。"));
-        Optional.ofNullable(automaticRunState).orElseThrow(() -> new RuntimeException("自动运行状态不能为空。"));
-
-        // 1 修改父项目停用状态
-        SimulationAutomaticProjectPo po = simulationAutomaticProjectMapper.selectById(id); // 查询父项目信息
-        if ("0".equals(param.getAutomaticRunState())) { // 启动
-            // 1 判断算法是否已经被删除
-            projectUtil.checkProject(po.getAlgorithm(), po.getVehicle(), po.getScene());
-            String currentGitVersion = algorithmService.getGitVersion(po.getAlgorithm());
-            simulationAutomaticProjectMapper.updateAutomaticRunState(param);
-            AlgorithmParameter algorithmParam = new AlgorithmParameter();
-            algorithmParam.setId(po.getAlgorithm());
-            algorithmParam.setGitVersion(currentGitVersion);
-            runProject(algorithmParam, param, po);
-        } else if ("1".equals(param.getAutomaticRunState())) { // 停止
-            simulationAutomaticProjectMapper.updateAutomaticRunState(param);
-            // 推送定时请求
-            projectTaskStop(po);
-        }
-        return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS);
+    // 校验cron表达式(运行周期)
+    String operationCycle = param.getOperationCycle();
+    if (isEmpty(operationCycle)) {
+      return new ResponseBodyVO(ResponseBodyVO.Response.CLIENT_FAILURE, "运行周期为必填项");
+    }
+    try {
+      CronExpression.parse(operationCycle);
+    } catch (Exception e) {
+      return new ResponseBodyVO(ResponseBodyVO.Response.CLIENT_FAILURE, "运行周期格式不对");
     }
 
-    private void runProject(AlgorithmParameter algorithmParam,
-            SimulationManualProjectParam simulationManualProjectParam,
-            SimulationAutomaticProjectPo simulationAutomaticProjectPo) {
+    // 创建自动运行任务时自动运行状态默认为关闭(1)
+    param.setAutomaticRunState("1");
+
+    SimulationAutomaticProjectPo po = convertToSimulationAutomaticProjectPo(param);
+
+    if (isEmpty(param.getId())) {
+      // 工作名称一样的的不能创建
+      List<SimulationAutomaticProjectPo> simulationManualProjectPos = simulationAutomaticProjectMapper.selectAutomaticProjectByQuery(param);
+      if (!isEmpty(simulationManualProjectPos)) {
+        return new ResponseBodyVO(ResponseBodyVO.Response.CLIENT_FAILURE, "工作名称已经存在,请修改后再保存");
+      }
+      po.createPo(AuthUtil.getCurrentUserId());
+      // 生成id
+      createProjectId(po);
+      int add = simulationAutomaticProjectMapper.add(po);
+      if (add > 0) {
+        return new ResponseBodyVO(ResponseBodyVO.Response.SUCCESS, ResponseBodyVO.Response.SUCCESS.getMessage(), po.getId());
+      }
+      return new ResponseBodyVO(ResponseBodyVO.Response.SERVER_FAILURE, "添加失败");
+    } else {
+
+      SimulationAutomaticProjectPo saPo = simulationAutomaticProjectMapper.selectById(param.getId());
+
+      // 自动运行状态为关闭的才可以修改
+      if ("0".equals(saPo.getAutomaticRunState())) {
+        return new ResponseBodyVO(ResponseBodyVO.Response.SERVER_FAILURE, "自动任务开启状态不支持修改");
+      }
+
+      po.updatePo(AuthUtil.getCurrentUserId());
+      int update = simulationAutomaticProjectMapper.updateById(po);
+      if (update > 0) {
+        return new ResponseBodyVO(ResponseBodyVO.Response.SUCCESS, ResponseBodyVO.Response.SUCCESS.getMessage(), po.getId());
+      }
+
+      return new ResponseBodyVO(ResponseBodyVO.Response.SERVER_FAILURE, "修改失败");
+    }
 
-        // 更新算法版本
-        simulationAutomaticProjectMapper.updateAlgorithmGitVersion(algorithmParam);
+  }
 
-        // 添加一条子工作信息并推送消息到kafka ,执行项目
-        createAutomaticSubProject(simulationManualProjectParam);
+  @Override
+  public ResponseBodyVO<String> deleteAutomaticProjectByids(SimulationManualProjectParam param) {
+    String ids = param.getIds();
+    String[] idArr = ids.split(",");
 
-        // 推送定时请求,启动运行周期
-        projectTaskStart(simulationAutomaticProjectPo);
+    List<SimulationAutomaticProjectPo> pos = simulationAutomaticProjectMapper.selectProjectNowRunState(idArr);
 
+    // 已经启动定时任务的项目不可以删除
+    for (SimulationAutomaticProjectPo p : pos) {
+      if ("0".equals(p.getAutomaticRunState())) {
+        return new ResponseBodyVO<>(ResponseBodyVO.Response.SERVER_FAILURE, "自动任务开启状态不支持删除");
+      }
     }
 
-    @Override
-    public ResponseBodyVO<PageInfo<SimulationManualProjectVo>> selectAutomaticProject(
-            SimulationManualProjectParam param) {
+    int i = simulationAutomaticProjectMapper.deleteProject(idArr);
+    if (i > 0) {
+      return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS);
+    }
 
-        // 1 获取当前用户id
-        param.setCreateUserId(AuthUtil.getCurrentUserId());
+    return new ResponseBodyVO<>(ResponseBodyVO.Response.SERVER_FAILURE, "删除失败");
+  }
+
+  @Override
+  public ResponseBodyVO<String> updateAutomaticRunState(SimulationManualProjectParam param) {
+    String id = param.getId();
+    String automaticRunState = param.getAutomaticRunState();
+    Optional.ofNullable(id).orElseThrow(() -> new RuntimeException("id 不能为空。"));
+    Optional.ofNullable(automaticRunState).orElseThrow(() -> new RuntimeException("自动运行状态不能为空。"));
+
+    // 1 修改父项目停用状态
+    SimulationAutomaticProjectPo po = simulationAutomaticProjectMapper.selectById(id); // 查询父项目信息
+    if ("0".equals(param.getAutomaticRunState())) { // 启动
+      // 1 判断算法是否已经被删除
+      projectUtil.checkProject(po.getAlgorithm(), po.getVehicle(), po.getScene());
+      String currentGitVersion = algorithmService.getGitVersion(po.getAlgorithm());
+      simulationAutomaticProjectMapper.updateAutomaticRunState(param);
+      AlgorithmParameter algorithmParam = new AlgorithmParameter();
+      algorithmParam.setId(po.getAlgorithm());
+      algorithmParam.setGitVersion(currentGitVersion);
+      runProject(algorithmParam, param, po);
+    } else if ("1".equals(param.getAutomaticRunState())) { // 停止
+      simulationAutomaticProjectMapper.updateAutomaticRunState(param);
+      // 推送定时请求
+      projectTaskStop(po);
+    }
+    return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS);
+  }
 
-        // 2 获取创建时间和开始时间
-        if (!isEmpty(param.getCreateStartDate())) {
-            String createStartDate = param.getCreateStartDate();
-            Date startDate = getDate(createStartDate + " 00:00:00", 1);
-            if (startDate == null) {
-                return new ResponseBodyVO<>(ResponseBodyVO.Response.CLIENT_FAILURE);
-            }
-            param.setCreateTimeStart(startDate);
-        }
-        if (!isEmpty(param.getCreateEndDate())) {
-            String createEndDate = param.getCreateEndDate();
-            Date endDate = getDate(createEndDate + " 23:59:59", 1);
-            if (endDate == null) {
-                return new ResponseBodyVO<>(ResponseBodyVO.Response.CLIENT_FAILURE);
-            }
-            param.setCreateTimeEnd(endDate);
-        }
+  private void runProject(AlgorithmParameter algorithmParam, SimulationManualProjectParam simulationManualProjectParam, SimulationAutomaticProjectPo simulationAutomaticProjectPo) {
 
-        setPage(param.getCurrentPage() == null ? 1 : param.getCurrentPage(),
-                param.getPageSize() == null ? 10 : param.getPageSize());
-        List<SimulationManualProjectVo> simulationManualProjectVoList = simulationAutomaticProjectMapper
-                .selectAutomaticProjectList(param);
-        PageInfo<SimulationManualProjectVo> pageInfo = new PageInfo<>(simulationManualProjectVoList);
+    // 更新算法版本
+    simulationAutomaticProjectMapper.updateAlgorithmGitVersion(algorithmParam);
 
-        for (SimulationManualProjectVo simulationManualProjectVo : pageInfo.getList()) {
-            convertPoToVo(simulationManualProjectVo, true);
-        }
+    // 添加一条子工作信息并推送消息到kafka ,执行项目
+    createAutomaticSubProject(simulationManualProjectParam);
 
-        return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS, pageInfo);
+    // 推送定时请求,启动运行周期
+    projectTaskStart(simulationAutomaticProjectPo);
 
-    }
+  }
 
-    @Override
-    @SneakyThrows
-    public ResponseBodyVO<String> createAutomaticSubProject(SimulationManualProjectParam param) {
-        if (StringUtil.isEmpty(param.getId())) {
-            throw new RuntimeException("id 不能为空。");
-        }
-        SimulationAutomaticProjectPo po = simulationAutomaticProjectMapper.selectById(param.getId());
-        // 校验项目信息
-        projectUtil.checkProject(po.getAlgorithm(), po.getVehicle(), po.getScene());
-        // 组装数据
-        String projectName = po.getProjectName();
-        SimulationAutomaticSubProjectPo subprojectPo = new SimulationAutomaticSubProjectPo();
-        subprojectPo.createPo(po.getCreateUserId());
-        subprojectPo.setParentId(po.getId());
-        subprojectPo.setParentProjectId(po.getProjectId());
-        subprojectPo.setProjectName(projectName);
-        subprojectPo.setStartTime(new Date());
-        subprojectPo.setNowRunState(ProjectRunStateEnum.EXECUTION.getCode());// 执行中
-        SimulationAutomaticSubProjectPo sPo = simulationAutomaticSubProjectMapper.selectLastProjectId(param.getId());
-        if (StringUtil.isEmpty(sPo)) {
-            subprojectPo.setProjectNum(1);
-            subprojectPo.setProjectId(po.getProjectId() + "-1");
-        } else {
-            Integer projectNum = sPo.getProjectNum() + 1;
-            subprojectPo.setProjectNum(projectNum);
-            subprojectPo.setProjectId(po.getProjectId() + "-" + projectNum);
-        }
-        // 修改自动运行次数
-        Long automaticRunTimes = po.getAutomaticRunTimes();
-        if (automaticRunTimes == null) {
-            po.setAutomaticRunTimes(1L);
-        } else {
-            po.setAutomaticRunTimes(automaticRunTimes + 1);
-        }
-        simulationAutomaticProjectMapper.updateAutomaticRunTimes(po);
-        int i = simulationAutomaticSubProjectMapper.addAutomaticSubProject(subprojectPo);
-        // 查询详情信息并保存
-        String projectId = subprojectPo.getId();
-        ProjectDetailsVo info = selectProjectDetailsByIdBackUp(SimulationManualProjectParam.builder().id(projectId)
-                .projectType(DictConstants.PROJECT_TYPE_AUTO_SUB).build()).getInfo();
-        String infoJson = JsonUtil.beanToJson(info);
-        log.info("项目 " + projectId + " 的详情信息为:" + infoJson);
-        autoSubProjectMapper.updateDetailsById(projectId, infoJson);
-        if (i <= 0) {
-            return new ResponseBodyVO<>(ResponseBodyVO.Response.SERVER_FAILURE, "执行失败");
-        }
-        // 推送消息到 kafka
-        autoProjectRunToKafka(po, subprojectPo.getId());
-        return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS, null);
-    }
-
-    private void autoProjectRunToKafka(SimulationAutomaticProjectPo po, String subId) {
-        SimulationManualProjectKafkaParam kafkaParam = new SimulationManualProjectKafkaParam();
-        kafkaParam.setProjectId(subId); // 子任务id
-        kafkaParam.setAlgorithmId(po.getAlgorithm());
-        kafkaParam.setVehicleConfigId(po.getVehicle());
-        kafkaParam.setScenePackageId(po.getScene());
-        kafkaParam.setMaxSimulationTime(po.getMaxSimulationTime());
-        kafkaParam.setParallelism(Integer.valueOf(po.getParallelism()));
-        kafkaParam.setType(DictConstants.PROJECT_TYPE_AUTO_SUB);
-        KafkaParameter kafkaParameter = new KafkaParameter();
-        kafkaParameter.setTopic(ProjectConstants.RUN_TASK_TOPIC);
-        kafkaParam.setModelType(vehicleMapper.selectParameterTypeById(po.getVehicle()));
-        String data = JsonUtil.beanToJson(kafkaParam);
-        kafkaParameter.setData(data);
-        log.info("自动运行项目推送消息到 kafka:" + data);
-        kafkaTemplate.send(kafkaParameter.getTopic(), kafkaParameter.getData()).addCallback(success -> {
-            // 消息发送到的topic
-            String topic = success.getRecordMetadata().topic();
-            // 消息发送到的分区
-            int partition = success.getRecordMetadata().partition();
-            // 消息在分区内的offset
-            long offset = success.getRecordMetadata().offset();
-            log.info("------- 发送消息成功:\n"
-                    + "主题 topic 为:" + topic + "\n"
-                    + "分区 partition 为:" + partition + "\n"
-                    + "偏移量为:" + offset + "\n"
-                    + "消息体为:" + kafkaParameter.getData());
-        }, failure -> {
-            log.error("发送消息失败:" + failure.getMessage());
-        });
-    }
-
-    @Override
-    public ResponseBodyVO<String> deleteAutomaticSubProjectByIds(SimulationManualProjectParam param) {
-
-        String ids = param.getIds();
-        if (isEmpty(ids)) {
-            return new ResponseBodyVO<>(ResponseBodyVO.Response.CLIENT_FAILURE);
-        }
-        String[] idArr = ids.split(",");
-        // 仅有执行中的不能删除
-        List<SimulationAutomaticSubProjectPo> pos = simulationAutomaticSubProjectMapper.selectProjectNowRunState(idArr);
-        for (SimulationAutomaticSubProjectPo p : pos) {
-            if (ProjectRunStateEnum.EXECUTION.getCode().equals(p.getNowRunState())) {
-                return new ResponseBodyVO<>(ResponseBodyVO.Response.SERVER_FAILURE, "数据不支持删除");
-            }
-        }
+  @Override
+  public ResponseBodyVO<PageInfo<SimulationManualProjectVo>> selectAutomaticProject(SimulationManualProjectParam param) {
 
-        int i = simulationAutomaticSubProjectMapper.deleteProject(idArr);
-        if (i > 0) {
-            return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS);
+    // 1 获取当前用户id
+    param.setCreateUserId(AuthUtil.getCurrentUserId());
 
-        }
-        return new ResponseBodyVO<>(ResponseBodyVO.Response.SERVER_FAILURE, "删除失败");
+    // 2 获取创建时间和开始时间
+    if (!isEmpty(param.getCreateStartDate())) {
+      String createStartDate = param.getCreateStartDate();
+      Date startDate = getDate(createStartDate + " 00:00:00", 1);
+      if (startDate == null) {
+        return new ResponseBodyVO<>(ResponseBodyVO.Response.CLIENT_FAILURE);
+      }
+      param.setCreateTimeStart(startDate);
+    }
+    if (!isEmpty(param.getCreateEndDate())) {
+      String createEndDate = param.getCreateEndDate();
+      Date endDate = getDate(createEndDate + " 23:59:59", 1);
+      if (endDate == null) {
+        return new ResponseBodyVO<>(ResponseBodyVO.Response.CLIENT_FAILURE);
+      }
+      param.setCreateTimeEnd(endDate);
     }
 
-    /**
-     * 自动项目父项目信息
-     */
-    @Override
-    public ResponseBodyVO<AutomaticProjectVo> selectSubProjectInfo(SimulationManualProjectParam param) {
-        /*
-         * 项目名称、项目描述、算法名称、车辆、传感器、场景、运行周期、并行度、是否选择GPU、最大运行时间
-         */
-        String id = param.getId();
-        if (StringUtil.isEmpty(id)) {
-            return new ResponseBodyVO<>(ResponseBodyVO.Response.CLIENT_FAILURE, "id不能为空");
-        }
-        AutomaticProjectVo automaticProjectVo = simulationAutomaticProjectMapper.selectAutomaticProjectInfoById(id);
-        if (StringUtil.isEmpty(automaticProjectVo)) {
-            return new ResponseBodyVO<>(ResponseBodyVO.Response.SERVER_FAILURE, "没有查询到数据");
-        }
-        List<DropDownTypeVo> result = new ArrayList<>();
-        setVehicleDropDown(result, automaticProjectVo.getVehicle());
-        DropDownTypeVo dropDownTypeVo = result.get(0);
-        DropDownVo dropDownVo = dropDownTypeVo.getDropDownList().get(0);
-        automaticProjectVo.setVehicle(dropDownVo.getName());
-        automaticProjectVo.setSensor(dropDownVo.getSensor());
-        String isChoiceGpu = automaticProjectVo.getIsChoiceGpu();
-        if ("0".equals(isChoiceGpu)) {
-            isChoiceGpu = "是";
-        } else if ("1".equals(isChoiceGpu)) {
-            isChoiceGpu = "否";
-        } else {
-            isChoiceGpu = "未知";
-        }
-        automaticProjectVo.setIsChoiceGpu(isChoiceGpu);
-
-        if (ObjectUtil.isNotNull(automaticProjectVo.getAlgorithmArray())) {
-            automaticProjectVo.setAlgorithmArrayS(automaticProjectVo.getAlgorithmArray().split(","));
-        }
-        if (ObjectUtil.isNotNull(automaticProjectVo.getVehicleArray())) {
-            automaticProjectVo.setVehicleArrayS(automaticProjectVo.getVehicleArray().split(","));
-        }
-        if (ObjectUtil.isNotNull(automaticProjectVo.getSceneArray())) {
-            automaticProjectVo.setSceneArrayS(automaticProjectVo.getSceneArray().split(","));
-        }
-        return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS, automaticProjectVo);
+    setPage(param.getCurrentPage() == null ? 1 : param.getCurrentPage(), param.getPageSize() == null ? 10 : param.getPageSize());
+    List<SimulationManualProjectVo> simulationManualProjectVoList = simulationAutomaticProjectMapper.selectAutomaticProjectList(param);
+    PageInfo<SimulationManualProjectVo> pageInfo = new PageInfo<>(simulationManualProjectVoList);
 
+    for (SimulationManualProjectVo simulationManualProjectVo : pageInfo.getList()) {
+      convertPoToVo(simulationManualProjectVo, true);
     }
 
-    @Override
-    public ResponseBodyVO<PageInfo<SimulationManualProjectVo>> selectSubProjectList(
-            SimulationManualProjectParam param) {
+    return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS, pageInfo);
 
-        String id = param.getParentId();
+  }
 
-        if (isEmpty(id)) {
-            return new ResponseBodyVO<>(ResponseBodyVO.Response.CLIENT_FAILURE, "id不能为空");
-        }
+  @Override
+  @SneakyThrows
+  public ResponseBodyVO<String> createAutomaticSubProject(SimulationManualProjectParam param) {
+    if (StringUtil.isEmpty(param.getId())) {
+      throw new RuntimeException("id 不能为空。");
+    }
+    SimulationAutomaticProjectPo po = simulationAutomaticProjectMapper.selectById(param.getId());
+    // 校验项目信息
+    projectUtil.checkProject(po.getAlgorithm(), po.getVehicle(), po.getScene());
+    // 组装数据
+    String projectName = po.getProjectName();
+    SimulationAutomaticSubProjectPo subprojectPo = new SimulationAutomaticSubProjectPo();
+    subprojectPo.createPo(po.getCreateUserId());
+    subprojectPo.setParentId(po.getId());
+    subprojectPo.setParentProjectId(po.getProjectId());
+    subprojectPo.setProjectName(projectName);
+    subprojectPo.setStartTime(new Date());
+    subprojectPo.setNowRunState(ProjectRunStateEnum.EXECUTION.getCode());// 执行中
+    SimulationAutomaticSubProjectPo sPo = simulationAutomaticSubProjectMapper.selectLastProjectId(param.getId());
+    if (StringUtil.isEmpty(sPo)) {
+      subprojectPo.setProjectNum(1);
+      subprojectPo.setProjectId(po.getProjectId() + "-1");
+    } else {
+      Integer projectNum = sPo.getProjectNum() + 1;
+      subprojectPo.setProjectNum(projectNum);
+      subprojectPo.setProjectId(po.getProjectId() + "-" + projectNum);
+    }
+    // 修改自动运行次数
+    Long automaticRunTimes = po.getAutomaticRunTimes();
+    if (automaticRunTimes == null) {
+      po.setAutomaticRunTimes(1L);
+    } else {
+      po.setAutomaticRunTimes(automaticRunTimes + 1);
+    }
+    simulationAutomaticProjectMapper.updateAutomaticRunTimes(po);
+    int i = simulationAutomaticSubProjectMapper.addAutomaticSubProject(subprojectPo);
+    // 查询详情信息并保存
+    String projectId = subprojectPo.getId();
+    ProjectDetailsVo info = selectProjectDetailsByIdBackUp(SimulationManualProjectParam.builder().id(projectId).projectType(DictConstants.PROJECT_TYPE_AUTO_SUB).build()).getInfo();
+    String infoJson = JsonUtil.beanToJson(info);
+    log.info("项目 " + projectId + " 的详情信息为:" + infoJson);
+    autoSubProjectMapper.updateDetailsById(projectId, infoJson);
+    if (i <= 0) {
+      return new ResponseBodyVO<>(ResponseBodyVO.Response.SERVER_FAILURE, "执行失败");
+    }
+    // 推送消息到 kafka
+    autoProjectRunToKafka(po, subprojectPo.getId());
+    return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS, null);
+  }
+
+  private void autoProjectRunToKafka(SimulationAutomaticProjectPo po, String subId) {
+    SimulationManualProjectKafkaParam kafkaParam = new SimulationManualProjectKafkaParam();
+    kafkaParam.setProjectId(subId); // 子任务id
+    kafkaParam.setAlgorithmId(po.getAlgorithm());
+    kafkaParam.setVehicleConfigId(po.getVehicle());
+    kafkaParam.setScenePackageId(po.getScene());
+    kafkaParam.setMaxSimulationTime(po.getMaxSimulationTime());
+    kafkaParam.setParallelism(Integer.valueOf(po.getParallelism()));
+    kafkaParam.setType(DictConstants.PROJECT_TYPE_AUTO_SUB);
+    KafkaParameter kafkaParameter = new KafkaParameter();
+    kafkaParameter.setTopic(ProjectConstants.RUN_TASK_TOPIC);
+    kafkaParam.setModelType(vehicleMapper.selectParameterTypeById(po.getVehicle()));
+    String data = JsonUtil.beanToJson(kafkaParam);
+    kafkaParameter.setData(data);
+    log.info("自动运行项目推送消息到 kafka:" + data);
+    kafkaTemplate.send(kafkaParameter.getTopic(), kafkaParameter.getData()).addCallback(success -> {
+      // 消息发送到的topic
+      String topic = success.getRecordMetadata().topic();
+      // 消息发送到的分区
+      int partition = success.getRecordMetadata().partition();
+      // 消息在分区内的offset
+      long offset = success.getRecordMetadata().offset();
+      log.info("------- 发送消息成功:\n" + "主题 topic 为:" + topic + "\n" + "分区 partition 为:" + partition + "\n" + "偏移量为:" + offset + "\n" + "消息体为:" + kafkaParameter.getData());
+    }, failure -> {
+      log.error("发送消息失败:" + failure.getMessage());
+    });
+  }
+
+  @Override
+  public ResponseBodyVO<String> deleteAutomaticSubProjectByIds(SimulationManualProjectParam param) {
+
+    String ids = param.getIds();
+    if (isEmpty(ids)) {
+      return new ResponseBodyVO<>(ResponseBodyVO.Response.CLIENT_FAILURE);
+    }
+    String[] idArr = ids.split(",");
+    // 仅有执行中的不能删除
+    List<SimulationAutomaticSubProjectPo> pos = simulationAutomaticSubProjectMapper.selectProjectNowRunState(idArr);
+    for (SimulationAutomaticSubProjectPo p : pos) {
+      if (ProjectRunStateEnum.EXECUTION.getCode().equals(p.getNowRunState())) {
+        return new ResponseBodyVO<>(ResponseBodyVO.Response.SERVER_FAILURE, "数据不支持删除");
+      }
+    }
 
-        setPage(param.getCurrentPage() == null ? 1 : param.getCurrentPage(),
-                param.getPageSize() == null ? 10 : param.getPageSize());
+    int i = simulationAutomaticSubProjectMapper.deleteProject(idArr);
+    if (i > 0) {
+      return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS);
 
-        List<SimulationManualProjectVo> simulationManualProjectVoList = simulationAutomaticSubProjectMapper
-                .selectList(param);
-        simulationManualProjectVoList.forEach(simulationManualProjectVo -> {
-            simulationManualProjectVo.setNowRunStateDict(
-                    getDictName(DictConstants.PROJECT_RUN_STATE, simulationManualProjectVo.getNowRunState()));
-            simulationManualProjectVo.setEvaluationLevelDict(
-                    getDictName(DictConstants.EVALUATION_LEVEL, simulationManualProjectVo.getEvaluationLevel()));
-        });
-        return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS, new PageInfo<>(simulationManualProjectVoList));
     }
+    return new ResponseBodyVO<>(ResponseBodyVO.Response.SERVER_FAILURE, "删除失败");
+  }
+
+  /**
+   * 自动项目父项目信息
+   */
+  @Override
+  public ResponseBodyVO<AutomaticProjectVo> selectSubProjectInfo(SimulationManualProjectParam param) {
+    /*
+     * 项目名称、项目描述、算法名称、车辆、传感器、场景、运行周期、并行度、是否选择GPU、最大运行时间
+     */
+    String id = param.getId();
+    if (StringUtil.isEmpty(id)) {
+      return new ResponseBodyVO<>(ResponseBodyVO.Response.CLIENT_FAILURE, "id不能为空");
+    }
+    AutomaticProjectVo automaticProjectVo = simulationAutomaticProjectMapper.selectAutomaticProjectInfoById(id);
+    if (StringUtil.isEmpty(automaticProjectVo)) {
+      return new ResponseBodyVO<>(ResponseBodyVO.Response.SERVER_FAILURE, "没有查询到数据");
+    }
+    List<DropDownTypeVo> result = new ArrayList<>();
+    setVehicleDropDown(result, automaticProjectVo.getVehicle());
+    DropDownTypeVo dropDownTypeVo = result.get(0);
+    DropDownVo dropDownVo = dropDownTypeVo.getDropDownList().get(0);
+    automaticProjectVo.setVehicle(dropDownVo.getName());
+    automaticProjectVo.setSensor(dropDownVo.getSensor());
+    String isChoiceGpu = automaticProjectVo.getIsChoiceGpu();
+    if ("0".equals(isChoiceGpu)) {
+      isChoiceGpu = "是";
+    } else if ("1".equals(isChoiceGpu)) {
+      isChoiceGpu = "否";
+    } else {
+      isChoiceGpu = "未知";
+    }
+    automaticProjectVo.setIsChoiceGpu(isChoiceGpu);
 
-    @Override
-    public ResponseBodyVO<SimulationManualProjectSingleVo> selectAutomaticProjectById(
-            SimulationManualProjectParam param) {
+    if (ObjectUtil.isNotNull(automaticProjectVo.getAlgorithmArray())) {
+      automaticProjectVo.setAlgorithmArrayS(automaticProjectVo.getAlgorithmArray().split(","));
+    }
+    if (ObjectUtil.isNotNull(automaticProjectVo.getVehicleArray())) {
+      automaticProjectVo.setVehicleArrayS(automaticProjectVo.getVehicleArray().split(","));
+    }
+    if (ObjectUtil.isNotNull(automaticProjectVo.getSceneArray())) {
+      automaticProjectVo.setSceneArrayS(automaticProjectVo.getSceneArray().split(","));
+    }
+    return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS, automaticProjectVo);
 
-        if (isEmpty(param.getId())) {
-            return new ResponseBodyVO<>(ResponseBodyVO.Response.CLIENT_FAILURE, "id不能为空");
-        }
-        SimulationAutomaticProjectPo po = simulationAutomaticProjectMapper.selectById(param.getId());
-        if (po == null) {
-            return new ResponseBodyVO<>(ResponseBodyVO.Response.SERVER_FAILURE, "没有获取到数据");
-        }
-        String deletedName = algorithmMapper.selectDeletedById(po.getAlgorithm());
-        if (StringUtil.isNotEmpty(deletedName)) {
-            po.setAlgorithm(deletedName + "(已删除)");
-        }
-        SimulationManualProjectSingleVo vo = new SimulationManualProjectSingleVo();
-        convertPoToVo(po, vo);
+  }
 
-        if (ObjectUtil.isNotNull(po.getAlgorithmArray())) {
-            vo.setAlgorithmArrayS(po.getAlgorithmArray().split(","));
-        }
-        if (ObjectUtil.isNotNull(po.getVehicleArray())) {
-            vo.setVehicleArrayS(po.getVehicleArray().split(","));
-        }
-        if (ObjectUtil.isNotNull(po.getSceneArray())) {
-            vo.setSceneArrayS(po.getSceneArray().split(","));
-        }
+  @Override
+  public ResponseBodyVO<PageInfo<SimulationManualProjectVo>> selectSubProjectList(SimulationManualProjectParam param) {
 
-        return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS, vo);
+    String id = param.getParentId();
 
+    if (isEmpty(id)) {
+      return new ResponseBodyVO<>(ResponseBodyVO.Response.CLIENT_FAILURE, "id不能为空");
     }
 
-    @SneakyThrows
-    @Override
-    public ResponseBodyVO<String> updateAutoProjectNowRunState(SimulationManualProjectParam param) {
+    setPage(param.getCurrentPage() == null ? 1 : param.getCurrentPage(), param.getPageSize() == null ? 10 : param.getPageSize());
 
-        if (isEmpty(param.getId()) || isEmpty(param.getNowRunState())) {
-            return new ResponseBodyVO<>(ResponseBodyVO.Response.CLIENT_FAILURE, "id或状态值不能为空");
-        }
+    List<SimulationManualProjectVo> simulationManualProjectVoList = simulationAutomaticSubProjectMapper.selectList(param);
+    simulationManualProjectVoList.forEach(simulationManualProjectVo -> {
+      simulationManualProjectVo.setNowRunStateDict(getDictName(DictConstants.PROJECT_RUN_STATE, simulationManualProjectVo.getNowRunState()));
+      simulationManualProjectVo.setEvaluationLevelDict(getDictName(DictConstants.EVALUATION_LEVEL, simulationManualProjectVo.getEvaluationLevel()));
+    });
+    return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS, new PageInfo<>(simulationManualProjectVoList));
+  }
 
-        SimulationAutomaticSubProjectPo po = simulationAutomaticSubProjectMapper.selectById(param);
+  @Override
+  public ResponseBodyVO<SimulationManualProjectSingleVo> selectAutomaticProjectById(SimulationManualProjectParam param) {
 
-        if (po == null) {
-            return new ResponseBodyVO<>(ResponseBodyVO.Response.SERVER_FAILURE, "数据没有找到");
-        }
+    if (isEmpty(param.getId())) {
+      return new ResponseBodyVO<>(ResponseBodyVO.Response.CLIENT_FAILURE, "id不能为空");
+    }
+    SimulationAutomaticProjectPo po = simulationAutomaticProjectMapper.selectById(param.getId());
+    if (po == null) {
+      return new ResponseBodyVO<>(ResponseBodyVO.Response.SERVER_FAILURE, "没有获取到数据");
+    }
+    String deletedName = algorithmMapper.selectDeletedById(po.getAlgorithm());
+    if (StringUtil.isNotEmpty(deletedName)) {
+      po.setAlgorithm(deletedName + "(已删除)");
+    }
+    SimulationManualProjectSingleVo vo = new SimulationManualProjectSingleVo();
+    convertPoToVo(po, vo);
 
-        // 自动运行子项目只能终止
-        if (ProjectRunStateEnum.DISCONTINUE.getCode().equals(param.getNowRunState())) {
-            int i = simulationAutomaticSubProjectMapper.updateNowRunState(param);
-            if (i > 0) {
-                // 项目终止,推送到kafka
-                autoProjectStopToKafka(po);
-                return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS);
-            }
+    if (ObjectUtil.isNotNull(po.getAlgorithmArray())) {
+      vo.setAlgorithmArrayS(po.getAlgorithmArray().split(","));
+    }
+    if (ObjectUtil.isNotNull(po.getVehicleArray())) {
+      vo.setVehicleArrayS(po.getVehicleArray().split(","));
+    }
+    if (ObjectUtil.isNotNull(po.getSceneArray())) {
+      vo.setSceneArrayS(po.getSceneArray().split(","));
+    }
 
-        }
+    return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS, vo);
 
-        return new ResponseBodyVO<>(ResponseBodyVO.Response.SERVER_FAILURE, "操作失败");
-    }
+  }
 
-    private void convertPoToVo(SimulationAutomaticProjectPo po, SimulationManualProjectSingleVo vo) {
-        vo.setId(po.getId());
-        vo.setProjectName(po.getProjectName());
-        vo.setProjectDescribe(po.getProjectDescribe());
-        vo.setAlgorithm(po.getAlgorithm());
-        vo.setAlgorithmType(po.getAlgorithmType());
-        vo.setVehicle(po.getVehicle());
-        vo.setScene(po.getScene());
-        vo.setOperationCycle(po.getOperationCycle());
-        vo.setParallelism(po.getParallelism());
-        vo.setRuleView(po.getRuleView());
-        vo.setIsChoiceGpu(po.getIsChoiceGpu());
-        vo.setMaxSimulationTime(po.getMaxSimulationTime());
+  @SneakyThrows
+  @Override
+  public ResponseBodyVO<String> updateAutoProjectNowRunState(SimulationManualProjectParam param) {
+
+    if (isEmpty(param.getId()) || isEmpty(param.getNowRunState())) {
+      return new ResponseBodyVO<>(ResponseBodyVO.Response.CLIENT_FAILURE, "id或状态值不能为空");
     }
 
-    private SimulationAutomaticProjectPo convertToSimulationAutomaticProjectPo(SimulationManualProjectParam param) {
-        SimulationAutomaticProjectPo po = new SimulationAutomaticProjectPo();
-        po.setId(param.getId());
-        po.setProjectName(param.getProjectName());
-        po.setProjectDescribe(param.getProjectDescribe());
-        po.setAlgorithm(param.getAlgorithm());
-        po.setVehicle(param.getVehicle());
-        po.setScene(param.getScene());
-        po.setOperationCycle(param.getOperationCycle());
-        po.setMaxSimulationTime(param.getMaxSimulationTime());
-        po.setParallelism(param.getParallelism());
-        po.setRuleView(param.getRuleView());
-        po.setIsChoiceGpu(param.getIsChoiceGpu());
-        // po.setNowRunState(param.getNowRunState());
-        po.setAutomaticRunState(param.getAutomaticRunState());
-        po.setAlgorithmType(param.getAlgorithmType());
+    SimulationAutomaticSubProjectPo po = simulationAutomaticSubProjectMapper.selectById(param);
 
-        if (ObjectUtil.isNotNull(param.getVehicleArrayS())) {
-            po.setVehicleArray(StringUtils.join(Arrays.asList(param.getVehicleArrayS()), ','));
-        }
-        if (ObjectUtil.isNotNull(param.getAlgorithmArrayS())) {
-            po.setAlgorithmArray(StringUtils.join(Arrays.asList(param.getAlgorithmArrayS()), ','));
-        }
-        if (ObjectUtil.isNotNull(param.getSceneArrayS())) {
-            po.setSceneArray(StringUtils.join(Arrays.asList(param.getSceneArrayS()), ','));
-        }
-        return po;
+    if (po == null) {
+      return new ResponseBodyVO<>(ResponseBodyVO.Response.SERVER_FAILURE, "数据没有找到");
     }
 
-    /**
-     * 换行
-     *
-     * @param lineNum  换行数量
-     * @param document
-     */
-    private void lineFeed(int lineNum, Document document) throws DocumentException {
-        for (int i = 0; i < lineNum; i++) {
-            document.add(Chunk.NEWLINE);
-        }
-    }
+    // 自动运行子项目只能终止
+    if (ProjectRunStateEnum.DISCONTINUE.getCode().equals(param.getNowRunState())) {
+      int i = simulationAutomaticSubProjectMapper.updateNowRunState(param);
+      if (i > 0) {
+        // 项目终止,推送到kafka
+        autoProjectStopToKafka(po);
+        return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS);
+      }
 
-    private void setBlankLineSpacing(int lineSpacingIndex, BaseFont font, Document document) throws DocumentException {
-        Paragraph elements2 = new Paragraph(
-                lineSpacingIndex,
-                " ",
-                defaultFont(font));
-        document.add(elements2);
     }
 
-    /**
-     * 默认字体
-     */
-    private Font defaultFont(BaseFont font) {
-        return new Font(font, 14);
+    return new ResponseBodyVO<>(ResponseBodyVO.Response.SERVER_FAILURE, "操作失败");
+  }
+
+  private void convertPoToVo(SimulationAutomaticProjectPo po, SimulationManualProjectSingleVo vo) {
+    vo.setId(po.getId());
+    vo.setProjectName(po.getProjectName());
+    vo.setProjectDescribe(po.getProjectDescribe());
+    vo.setAlgorithm(po.getAlgorithm());
+    vo.setAlgorithmType(po.getAlgorithmType());
+    vo.setVehicle(po.getVehicle());
+    vo.setScene(po.getScene());
+    vo.setOperationCycle(po.getOperationCycle());
+    vo.setParallelism(po.getParallelism());
+    vo.setRuleView(po.getRuleView());
+    vo.setIsChoiceGpu(po.getIsChoiceGpu());
+    vo.setMaxSimulationTime(po.getMaxSimulationTime());
+  }
+
+  private SimulationAutomaticProjectPo convertToSimulationAutomaticProjectPo(SimulationManualProjectParam param) {
+    SimulationAutomaticProjectPo po = new SimulationAutomaticProjectPo();
+    po.setId(param.getId());
+    po.setProjectName(param.getProjectName());
+    po.setProjectDescribe(param.getProjectDescribe());
+    po.setAlgorithm(param.getAlgorithm());
+    po.setVehicle(param.getVehicle());
+    po.setScene(param.getScene());
+    po.setOperationCycle(param.getOperationCycle());
+    po.setMaxSimulationTime(param.getMaxSimulationTime());
+    po.setParallelism(param.getParallelism());
+    po.setRuleView(param.getRuleView());
+    po.setIsChoiceGpu(param.getIsChoiceGpu());
+    // po.setNowRunState(param.getNowRunState());
+    po.setAutomaticRunState(param.getAutomaticRunState());
+    po.setAlgorithmType(param.getAlgorithmType());
+
+    if (ObjectUtil.isNotNull(param.getVehicleArrayS())) {
+      po.setVehicleArray(StringUtils.join(Arrays.asList(param.getVehicleArrayS()), ','));
     }
-
-    /**
-     * 添加表头
-     */
-    private void addTitleList(PdfPTable pdfPTable, BaseFont font, String[] titleList) {
-        for (String title : titleList) {
-            PdfPCell pdfPCell = new PdfPCell(new Paragraph(title, defaultFont(font)));
-            pdfPCell.setBackgroundColor(BaseColor.LIGHT_GRAY);
-            pdfPCell.setHorizontalAlignment(1);
-            pdfPTable.addCell(pdfPCell);
-        }
+    if (ObjectUtil.isNotNull(param.getAlgorithmArrayS())) {
+      po.setAlgorithmArray(StringUtils.join(Arrays.asList(param.getAlgorithmArrayS()), ','));
     }
-
-    /**
-     * 水平垂直居中添加表头
-     */
-    private void addTitleList(PdfPTable table, BaseFont font, String[] titleList, boolean center) {
-        if (center) {
-            for (String title : titleList) {
-                PdfPCell cell = new PdfPCell(new Paragraph(title, defaultFont(font)));
-                cell.setFixedHeight(30);
-                cell.setUseAscender(true);
-                cell.setBackgroundColor(BaseColor.LIGHT_GRAY); // 单元格底色
-                cell.setHorizontalAlignment(Element.ALIGN_CENTER); // 水平居中
-                cell.setVerticalAlignment(Element.ALIGN_MIDDLE); // 垂直居中
-                table.addCell(cell);
-            }
-        } else {
-            for (String title : titleList) {
-                PdfPCell cell = new PdfPCell(new Paragraph(title, defaultFont(font)));
-                cell.setBackgroundColor(BaseColor.LIGHT_GRAY);
-                cell.setHorizontalAlignment(1);
-                table.addCell(cell);
-            }
-        }
+    if (ObjectUtil.isNotNull(param.getSceneArrayS())) {
+      po.setSceneArray(StringUtils.join(Arrays.asList(param.getSceneArrayS()), ','));
     }
-
-    /**
-     * 水平垂直居中添加表头
-     */
-    private void addTitleList(PdfPTable table, BaseFont font, String[] titleList, boolean center, int height) {
-        if (center) {
-            for (String title : titleList) {
-                PdfPCell cell = new PdfPCell(new Paragraph(title, defaultFont(font)));
-                cell.setFixedHeight(height);
-                cell.setUseAscender(true);
-                cell.setBackgroundColor(BaseColor.LIGHT_GRAY); // 单元格底色
-                cell.setHorizontalAlignment(Element.ALIGN_CENTER); // 水平居中
-                cell.setVerticalAlignment(Element.ALIGN_MIDDLE); // 垂直居中
-                table.addCell(cell);
-            }
-        } else {
-            for (String title : titleList) {
-                PdfPCell cell = new PdfPCell(new Paragraph(title, defaultFont(font)));
-                cell.setBackgroundColor(BaseColor.LIGHT_GRAY);
-                cell.setHorizontalAlignment(1);
-                table.addCell(cell);
-            }
-        }
+    return po;
+  }
+
+  /**
+   * 换行
+   *
+   * @param lineNum  换行数量
+   * @param document
+   */
+  private void lineFeed(int lineNum, Document document) throws DocumentException {
+    for (int i = 0; i < lineNum; i++) {
+      document.add(Chunk.NEWLINE);
     }
-
-    /**
-     * 添加数据
-     *
-     * @param pdfPTable
-     * @param font
-     * @param dataList
-     */
-    private void addDataList(PdfPTable table, BaseFont font, String[] dataList) {
-        for (String data : dataList) {
-            PdfPCell cell = new PdfPCell(new Paragraph(data, defaultFont(font)));
-            table.addCell(cell);
-        }
+  }
+
+  private void setBlankLineSpacing(int lineSpacingIndex, BaseFont font, Document document) throws DocumentException {
+    Paragraph elements2 = new Paragraph(lineSpacingIndex, " ", defaultFont(font));
+    document.add(elements2);
+  }
+
+  /**
+   * 默认字体
+   */
+  private Font defaultFont(BaseFont font) {
+    return new Font(font, 14);
+  }
+
+  /**
+   * 添加表头
+   */
+  private void addTitleList(PdfPTable pdfPTable, BaseFont font, String[] titleList) {
+    for (String title : titleList) {
+      PdfPCell pdfPCell = new PdfPCell(new Paragraph(title, defaultFont(font)));
+      pdfPCell.setBackgroundColor(BaseColor.LIGHT_GRAY);
+      pdfPCell.setHorizontalAlignment(1);
+      pdfPTable.addCell(pdfPCell);
     }
-
-    /**
-     * 添加数据
-     *
-     * @param pdfPTable
-     * @param font
-     * @param dataList
-     */
-    private void addDataList(PdfPTable table, BaseFont font, String[] dataList, boolean center) {
-        if (center) {
-            for (String data : dataList) {
-                PdfPCell cell = new PdfPCell(new Paragraph(data, defaultFont(font)));
-                cell.setUseAscender(true);
-                cell.setHorizontalAlignment(Element.ALIGN_CENTER); // 水平居中
-                cell.setVerticalAlignment(Element.ALIGN_MIDDLE); // 垂直居中
-                table.addCell(cell);
-            }
-        } else {
-            addDataList(table, font, dataList);
-        }
+  }
+
+  /**
+   * 水平垂直居中添加表头
+   */
+  private void addTitleList(PdfPTable table, BaseFont font, String[] titleList, boolean center) {
+    if (center) {
+      for (String title : titleList) {
+        PdfPCell cell = new PdfPCell(new Paragraph(title, defaultFont(font)));
+        cell.setFixedHeight(30);
+        cell.setUseAscender(true);
+        cell.setBackgroundColor(BaseColor.LIGHT_GRAY); // 单元格底色
+        cell.setHorizontalAlignment(Element.ALIGN_CENTER); // 水平居中
+        cell.setVerticalAlignment(Element.ALIGN_MIDDLE); // 垂直居中
+        table.addCell(cell);
+      }
+    } else {
+      for (String title : titleList) {
+        PdfPCell cell = new PdfPCell(new Paragraph(title, defaultFont(font)));
+        cell.setBackgroundColor(BaseColor.LIGHT_GRAY);
+        cell.setHorizontalAlignment(1);
+        table.addCell(cell);
+      }
     }
-
-    /**
-     * 添加数据
-     *
-     * @param pdfPTable
-     * @param font
-     * @param dataList
-     */
-    private void addDataList(PdfPTable table, BaseFont font, String[] dataList, boolean center, int height) {
-        if (center) {
-            for (String data : dataList) {
-                PdfPCell cell = new PdfPCell(new Paragraph(data, defaultFont(font)));
-                cell.setFixedHeight(height);
-                cell.setUseAscender(true);
-                cell.setHorizontalAlignment(Element.ALIGN_CENTER); // 水平居中
-                cell.setVerticalAlignment(Element.ALIGN_MIDDLE); // 垂直居中
-                table.addCell(cell);
-            }
-        } else {
-            addDataList(table, font, dataList);
-        }
+  }
+
+  /**
+   * 水平垂直居中添加表头
+   */
+  private void addTitleList(PdfPTable table, BaseFont font, String[] titleList, boolean center, int height) {
+    if (center) {
+      for (String title : titleList) {
+        PdfPCell cell = new PdfPCell(new Paragraph(title, defaultFont(font)));
+        cell.setFixedHeight(height);
+        cell.setUseAscender(true);
+        cell.setBackgroundColor(BaseColor.LIGHT_GRAY); // 单元格底色
+        cell.setHorizontalAlignment(Element.ALIGN_CENTER); // 水平居中
+        cell.setVerticalAlignment(Element.ALIGN_MIDDLE); // 垂直居中
+        table.addCell(cell);
+      }
+    } else {
+      for (String title : titleList) {
+        PdfPCell cell = new PdfPCell(new Paragraph(title, defaultFont(font)));
+        cell.setBackgroundColor(BaseColor.LIGHT_GRAY);
+        cell.setHorizontalAlignment(1);
+        table.addCell(cell);
+      }
     }
-
-    private void addCell(PdfPTable table, PdfPCell cell, boolean center) {
+  }
+
+  /**
+   * 添加数据
+   *
+   * @param pdfPTable
+   * @param font
+   * @param dataList
+   */
+  private void addDataList(PdfPTable table, BaseFont font, String[] dataList) {
+    for (String data : dataList) {
+      PdfPCell cell = new PdfPCell(new Paragraph(data, defaultFont(font)));
+      table.addCell(cell);
+    }
+  }
+
+  /**
+   * 添加数据
+   *
+   * @param pdfPTable
+   * @param font
+   * @param dataList
+   */
+  private void addDataList(PdfPTable table, BaseFont font, String[] dataList, boolean center) {
+    if (center) {
+      for (String data : dataList) {
+        PdfPCell cell = new PdfPCell(new Paragraph(data, defaultFont(font)));
         cell.setUseAscender(true);
         cell.setHorizontalAlignment(Element.ALIGN_CENTER); // 水平居中
         cell.setVerticalAlignment(Element.ALIGN_MIDDLE); // 垂直居中
         table.addCell(cell);
+      }
+    } else {
+      addDataList(table, font, dataList);
     }
-
-    private void insertOtherAlgorithm(SimulationManualProjectParam param) {
-        if (DictConstants.PLATFORM.equals(param.getAlgorithmType())) {
-            AlgorithmPO po = new AlgorithmPO();
-            po.setId(param.getAlgorithm());
-            po.setAlgorithmName(param.getAlgorithmName());
-            po.setUploadMode(DictConstants.PLATFORM);
-            po.setIsDeleted("0");
-            AlgorithmPO po1 = simulationProjectMapper.selectalgorithmByQuery(po);
-            if (po1 == null) {
-                simulationProjectMapper.insertOtherAlgorithm(po);
-            } else {
-                if (!po1.getAlgorithmName().equals(param.getAlgorithmName())) {
-                    simulationProjectMapper.updateOtherAlgorithm(po);
-                }
-            }
-
-        }
+  }
+
+  /**
+   * 添加数据
+   *
+   * @param pdfPTable
+   * @param font
+   * @param dataList
+   */
+  private void addDataList(PdfPTable table, BaseFont font, String[] dataList, boolean center, int height) {
+    if (center) {
+      for (String data : dataList) {
+        PdfPCell cell = new PdfPCell(new Paragraph(data, defaultFont(font)));
+        cell.setFixedHeight(height);
+        cell.setUseAscender(true);
+        cell.setHorizontalAlignment(Element.ALIGN_CENTER); // 水平居中
+        cell.setVerticalAlignment(Element.ALIGN_MIDDLE); // 垂直居中
+        table.addCell(cell);
+      }
+    } else {
+      addDataList(table, font, dataList);
+    }
+  }
+
+  private void addCell(PdfPTable table, PdfPCell cell, boolean center) {
+    cell.setUseAscender(true);
+    cell.setHorizontalAlignment(Element.ALIGN_CENTER); // 水平居中
+    cell.setVerticalAlignment(Element.ALIGN_MIDDLE); // 垂直居中
+    table.addCell(cell);
+  }
+
+  private void insertOtherAlgorithm(SimulationManualProjectParam param) {
+    if (DictConstants.PLATFORM.equals(param.getAlgorithmType())) {
+      AlgorithmPO po = new AlgorithmPO();
+      po.setId(param.getAlgorithm());
+      po.setAlgorithmName(param.getAlgorithmName());
+      po.setUploadMode(DictConstants.PLATFORM);
+      po.setIsDeleted("0");
+      AlgorithmPO po1 = simulationProjectMapper.selectalgorithmByQuery(po);
+      if (po1 == null) {
+        simulationProjectMapper.insertOtherAlgorithm(po);
+      } else {
+        if (!po1.getAlgorithmName().equals(param.getAlgorithmName())) {
+          simulationProjectMapper.updateOtherAlgorithm(po);
+        }
+      }
 
     }
 
-    private void projectTaskStart(SimulationAutomaticProjectPo po) {
-        SimulationManualProjectParam p = new SimulationManualProjectParam();
-        p.setProjectId(po.getId());
-        p.setCron(po.getOperationCycle());
-        ResponseBodyVO<String> start = monitorService.start(p);
-        boolean status = start.isStatus();
-        if (!status) {
-            // 定时任务启动失败,抛出异常
-            log.info("自动运行项目启动失败:" + po.getId());
-            throw new RuntimeException("自动运行项目启动失败:" + po.getId());
-        }
+  }
+
+  private void projectTaskStart(SimulationAutomaticProjectPo po) {
+    SimulationManualProjectParam p = new SimulationManualProjectParam();
+    p.setProjectId(po.getId());
+    p.setCron(po.getOperationCycle());
+    ResponseBodyVO<String> start = monitorService.start(p);
+    boolean status = start.isStatus();
+    if (!status) {
+      // 定时任务启动失败,抛出异常
+      log.info("自动运行项目启动失败:" + po.getId());
+      throw new RuntimeException("自动运行项目启动失败:" + po.getId());
+    }
+  }
+
+  private void projectTaskStop(SimulationAutomaticProjectPo po) {
+
+    SimulationManualProjectParam p = new SimulationManualProjectParam();
+    p.setProjectId(po.getId());
+    // 停止任务
+    ResponseBodyVO stop = monitorService.stop(p);
+    // boolean status = stop.isStatus();
+    // if (!status) {
+    // //定时任务关闭失败,抛出异常
+    // log.info("自动运行项目停止失败:" + po.getId());
+    // throw new RuntimeException("自动运行项目停止失败:" + po.getId());
+    // }
+  }
+
+  /**
+   * 获取一级指标得分列表
+   *
+   * @return
+   */
+  private List<AlgorithmScoreVo> getFirstTargetScore(String id) {
+    // 算法测试得分表
+    /*
+     * 汇总测试得分计算方法:(每一项一级指标的测试得分*测试权重)累加
+     * 得分率计算方法:每一项一级指标的所有场景得分不为0的数量/每一项一级指标的场景数量
+     * 汇总得分率计算方法:(每一项一级指标的所有场景得分不为0的数量_累加/每一项一级指标的场景数量_累加)换成(得分累加取平均值)
+     */
+    // 获取得分表一级指标信息
+    SimulationMptFirstTargetScorePo simulationMptFirstTargetScorePo = new SimulationMptFirstTargetScorePo();
+    simulationMptFirstTargetScorePo.setPId(id);
+    List<SimulationMptFirstTargetScorePo> pos = simulationMptFirstTargetScoreMapper.selectFirstTargetByPid(simulationMptFirstTargetScorePo);
+    List<AlgorithmScoreVo> algorithmScoreVoList = new ArrayList<>();
+    if (!isEmpty(pos)) {
+      // StringBuilder stringBuilder = new StringBuilder();
+      // 汇总数据初始化
+      Integer totalSceneNum = 0;
+      double totalScore = 0D;
+      double totalScoreRatio = 0D;
+      Integer totalSceneScoreNum = 0;
+      for (SimulationMptFirstTargetScorePo v : pos) {
+        // stringBuilder.append(v.getSublistName()).append("、");
+        AlgorithmScoreVo algorithmScoreVo = new AlgorithmScoreVo();
+        algorithmScoreVo.setProjectName(v.getSublistName());
+        Integer sceneNum = v.getSceneNum();
+        totalSceneNum += sceneNum;
+        algorithmScoreVo.setSceneNum(sceneNum);
+        String weight = v.getWeight();
+        double weightDouble = Double.parseDouble(weight);
+        algorithmScoreVo.setWeight(weight);
+        // 单个二级指标得分
+        Double score = v.getScore();
+        totalScore += BigDecimal.valueOf(score).multiply(BigDecimal.valueOf(weightDouble).divide(BigDecimal.valueOf(100))).doubleValue();
+        algorithmScoreVo.setScore(saveTwoDecimalPlaces(score));
+        // 获取得分不为 0 的场景数量
+        Integer scoreNum = getSetScoreNum(v.getSublistId(), id);
+        totalSceneScoreNum += scoreNum;
+        double tempScoreRatio = Double.valueOf(scoreNum) / Double.valueOf(sceneNum) * 100;
+        algorithmScoreVo.setScoreRatio(saveTwoDecimalPlaces(tempScoreRatio));
+        algorithmScoreVoList.add(algorithmScoreVo);
+        totalScoreRatio += tempScoreRatio;
+      }
+      // 汇总
+      AlgorithmScoreVo algorithmScoreVo = new AlgorithmScoreVo();
+      algorithmScoreVo.setProjectName("汇总");
+      algorithmScoreVo.setSceneNum(totalSceneNum);
+      // 指标权重总和默认是100%
+      algorithmScoreVo.setWeight("100");
+      algorithmScoreVo.setScore(saveTwoDecimalPlaces(totalScore));
+      totalScoreRatio = Double.valueOf(totalSceneScoreNum) / Double.valueOf(totalSceneNum) * 100;
+      algorithmScoreVo.setScoreRatio(saveTwoDecimalPlaces(totalScoreRatio));
+      algorithmScoreVoList.add(algorithmScoreVo);
     }
 
-    private void projectTaskStop(SimulationAutomaticProjectPo po) {
+    return algorithmScoreVoList;
+
+  }
+
+  /**
+   * 查询算法下拉列表
+   *
+   * @param result
+   * @param algorithmType 算法类型
+   */
+  private void setAlgorithmDropDownNew(List<DropDownTypeNewVo> result, String algorithmType) {
+    List<Map> treeList = new ArrayList<>();
+    List<DropDownVo> algorithmListSy = new ArrayList<>();
+    List<DropDownVo> algorithmListGy = new ArrayList<>();
+    if (DictConstants.FILE.equals(algorithmType) || DictConstants.GIT.equals(algorithmType)) {
+      AlgorithmPO algorithmPO = new AlgorithmPO();
+      algorithmPO.setCreateUserId(AuthUtil.getCurrentUserId()); // 获取当前用户 id
+      if (StringUtil.isEmpty(algorithmType)) {
+        algorithmPO.setUploadMode("1");
+      } else {
+        algorithmPO.setUploadMode(algorithmType);
+      }
+      List<AlgorithmPO> algorithmBaseInfoSyVo = simulationProjectMapper.selectAlgorithmBaseInfoByIdSy(algorithmPO);
+
+      for (AlgorithmPO v : algorithmBaseInfoSyVo) {
+        DropDownVo dropDownVo = new DropDownVo();
+        dropDownVo.setId(v.getId());
+        dropDownVo.setName(v.getAlgorithmName());
+        dropDownVo.setDescription(v.getDescription());
+        dropDownVo.setShare(v.getShare());
+        algorithmListSy.add(dropDownVo);
+      }
+      List<AlgorithmPO> algorithmBaseInfoGyVo = simulationProjectMapper.selectAlgorithmBaseInfoByIdGy(algorithmPO);
+
+      for (AlgorithmPO v : algorithmBaseInfoGyVo) {
+        DropDownVo dropDownVo = new DropDownVo();
+        dropDownVo.setId(v.getId());
+        dropDownVo.setName(v.getAlgorithmName());
+        dropDownVo.setDescription(v.getDescription());
+        dropDownVo.setShare(v.getShare());
+        algorithmListGy.add(dropDownVo);
+      }
+
+    } else if (DictConstants.PLATFORM.equals(algorithmType)) {
+      // 第三方算法平台获取(索为)
+      String sort = "algorithmId-desc";
+      int page = 1;
+      int size = 999;// 全部
+      String urlParam = "&page=" + page + "&size=" + size + "&sort=" + sort;
+      algorithmListSy = getOtherAlgorithmInfo(urlParam);
 
-        SimulationManualProjectParam p = new SimulationManualProjectParam();
-        p.setProjectId(po.getId());
-        // 停止任务
-        ResponseBodyVO stop = monitorService.stop(p);
-        // boolean status = stop.isStatus();
-        // if (!status) {
-        // //定时任务关闭失败,抛出异常
-        // log.info("自动运行项目停止失败:" + po.getId());
-        // throw new RuntimeException("自动运行项目停止失败:" + po.getId());
-        // }
     }
 
-    /**
-     * 获取一级指标得分列表
-     *
-     * @return
+    Map typeMap = new HashMap();
+    typeMap.put("code", "公有");
+    typeMap.put("name", "公有");
+    List<Map> colourList = new LinkedList();
+    algorithmListGy.forEach(vo -> {
+      Map colourMap = new HashMap();
+      colourMap.put("code", vo.getId());
+      colourMap.put("name", vo.getName());
+      colourMap.put("vo", vo);
+      colourList.add(colourMap);
+    });
+    typeMap.put("children", colourList);
+    Map typeMap1 = new HashMap();
+    typeMap1.put("code", "私有");
+    typeMap1.put("name", "私有");
+    List<Map> colourList1 = new LinkedList();
+    algorithmListSy.forEach(vo -> {
+      Map colourMap = new HashMap();
+      colourMap.put("code", vo.getId());
+      colourMap.put("name", vo.getName());
+      colourMap.put("vo", vo);
+      colourList1.add(colourMap);
+    });
+    typeMap1.put("children", colourList1);
+    treeList.add(typeMap);
+    treeList.add(typeMap1);
+    /*
+     * List<DropDownNewVo> listGSy = new ArrayList<>();
+     * DropDownNewVo dropDownNewSyVo = new DropDownNewVo();
+     * dropDownNewSyVo.setLabel("私有");
+     * dropDownNewSyVo.setOptions(algorithmListSy);
+     * listGSy.add(dropDownNewSyVo);
+     * DropDownNewVo dropDownNewGyVo = new DropDownNewVo();
+     * dropDownNewGyVo.setLabel("公有");
+     * dropDownNewGyVo.setOptions(algorithmListGy);
+     * listGSy.add(dropDownNewGyVo);
      */
-    private List<AlgorithmScoreVo> getFirstTargetScore(String id) {
-        // 算法测试得分表
-        /*
-         * 汇总测试得分计算方法:(每一项一级指标的测试得分*测试权重)累加
-         * 得分率计算方法:每一项一级指标的所有场景得分不为0的数量/每一项一级指标的场景数量
-         * 汇总得分率计算方法:(每一项一级指标的所有场景得分不为0的数量_累加/每一项一级指标的场景数量_累加)换成(得分累加取平均值)
-         */
-        // 获取得分表一级指标信息
-        SimulationMptFirstTargetScorePo simulationMptFirstTargetScorePo = new SimulationMptFirstTargetScorePo();
-        simulationMptFirstTargetScorePo.setPId(id);
-        List<SimulationMptFirstTargetScorePo> pos = simulationMptFirstTargetScoreMapper
-                .selectFirstTargetByPid(simulationMptFirstTargetScorePo);
-        List<AlgorithmScoreVo> algorithmScoreVoList = new ArrayList<>();
-        if (!isEmpty(pos)) {
-            // StringBuilder stringBuilder = new StringBuilder();
-            // 汇总数据初始化
-            Integer totalSceneNum = 0;
-            double totalScore = 0D;
-            double totalScoreRatio = 0D;
-            Integer totalSceneScoreNum = 0;
-            for (SimulationMptFirstTargetScorePo v : pos) {
-                // stringBuilder.append(v.getSublistName()).append("、");
-                AlgorithmScoreVo algorithmScoreVo = new AlgorithmScoreVo();
-                algorithmScoreVo.setProjectName(v.getSublistName());
-                Integer sceneNum = v.getSceneNum();
-                totalSceneNum += sceneNum;
-                algorithmScoreVo.setSceneNum(sceneNum);
-                String weight = v.getWeight();
-                double weightDouble = Double.parseDouble(weight);
-                algorithmScoreVo.setWeight(weight);
-                // 单个二级指标得分
-                Double score = v.getScore();
-                totalScore += BigDecimal.valueOf(score)
-                        .multiply(BigDecimal.valueOf(weightDouble).divide(BigDecimal.valueOf(100))).doubleValue();
-                algorithmScoreVo.setScore(saveTwoDecimalPlaces(score));
-                // 获取得分不为 0 的场景数量
-                Integer scoreNum = getSetScoreNum(v.getSublistId(), id);
-                totalSceneScoreNum += scoreNum;
-                double tempScoreRatio = Double.valueOf(scoreNum) / Double.valueOf(sceneNum) * 100;
-                algorithmScoreVo.setScoreRatio(saveTwoDecimalPlaces(tempScoreRatio));
-                algorithmScoreVoList.add(algorithmScoreVo);
-                totalScoreRatio += tempScoreRatio;
-            }
-            // 汇总
-            AlgorithmScoreVo algorithmScoreVo = new AlgorithmScoreVo();
-            algorithmScoreVo.setProjectName("汇总");
-            algorithmScoreVo.setSceneNum(totalSceneNum);
-            // 指标权重总和默认是100%
-            algorithmScoreVo.setWeight("100");
-            algorithmScoreVo.setScore(saveTwoDecimalPlaces(totalScore));
-            totalScoreRatio = Double.valueOf(totalSceneScoreNum) / Double.valueOf(totalSceneNum) * 100;
-            algorithmScoreVo.setScoreRatio(saveTwoDecimalPlaces(totalScoreRatio));
-            algorithmScoreVoList.add(algorithmScoreVo);
+    DropDownTypeNewVo dropDownTypeNewVo = new DropDownTypeNewVo();
+    dropDownTypeNewVo.setDropDownList(treeList);
+    dropDownTypeNewVo.setType("1");
+    result.add(dropDownTypeNewVo);
+
+  }
+
+  private void setVehicleDropDownNew(List<DropDownTypeNewVo> result) {
+    List<Map> treeList = new ArrayList<>();
+    ConfigPO configPO = new ConfigPO();
+    configPO.setCreateUserId(AuthUtil.getCurrentUserId());
+    List<ConfigPO> vehicleBaseInfoSyVo = simulationProjectMapper.selectConfigVehicleSy(configPO);
+    List<DropDownVo> vehicleSyList = new ArrayList<>();
+    for (ConfigPO v : vehicleBaseInfoSyVo) {
+      DropDownVo dropDownVo = new DropDownVo();
+      dropDownVo.setId(v.getId());
+      dropDownVo.setName(v.getConfigName());
+      dropDownVo.setDescription(v.getDescription());
+      dropDownVo.setShare(v.getShare());
+      // 获取传感器信息
+      List<ConfigSensorPO> configSensorVos = simulationProjectMapper.selectConfigSensor(v.getId());
+      String sensor = "";
+      if (!isEmpty(configSensorVos) && configSensorVos.get(0) != null) {
+        StringBuilder stringBuilder = new StringBuilder();
+        for (ConfigSensorPO cv : configSensorVos) {
+          stringBuilder.append(cv.getSensorType()).append(",");
         }
+        sensor = stringBuilder.substring(0, stringBuilder.lastIndexOf(","));
 
-        return algorithmScoreVoList;
+      }
+      dropDownVo.setSensor(sensor);
 
+      vehicleSyList.add(dropDownVo);
     }
 
-    /**
-     * 查询算法下拉列表
-     *
-     * @param result
-     * @param algorithmType 算法类型
-     */
-    private void setAlgorithmDropDownNew(List<DropDownTypeNewVo> result, String algorithmType) {
-        List<Map> treeList = new ArrayList<>();
-        List<DropDownVo> algorithmListSy = new ArrayList<>();
-        List<DropDownVo> algorithmListGy = new ArrayList<>();
-        if (DictConstants.FILE.equals(algorithmType) || DictConstants.GIT.equals(algorithmType)) {
-            AlgorithmPO algorithmPO = new AlgorithmPO();
-            algorithmPO.setCreateUserId(AuthUtil.getCurrentUserId()); // 获取当前用户 id
-            if (StringUtil.isEmpty(algorithmType)) {
-                algorithmPO.setUploadMode("1");
-            } else {
-                algorithmPO.setUploadMode(algorithmType);
-            }
-            List<AlgorithmPO> algorithmBaseInfoSyVo = simulationProjectMapper
-                    .selectAlgorithmBaseInfoByIdSy(algorithmPO);
-
-            for (AlgorithmPO v : algorithmBaseInfoSyVo) {
-                DropDownVo dropDownVo = new DropDownVo();
-                dropDownVo.setId(v.getId());
-                dropDownVo.setName(v.getAlgorithmName());
-                dropDownVo.setDescription(v.getDescription());
-                dropDownVo.setShare(v.getShare());
-                algorithmListSy.add(dropDownVo);
-            }
-            List<AlgorithmPO> algorithmBaseInfoGyVo = simulationProjectMapper
-                    .selectAlgorithmBaseInfoByIdGy(algorithmPO);
-
-            for (AlgorithmPO v : algorithmBaseInfoGyVo) {
-                DropDownVo dropDownVo = new DropDownVo();
-                dropDownVo.setId(v.getId());
-                dropDownVo.setName(v.getAlgorithmName());
-                dropDownVo.setDescription(v.getDescription());
-                dropDownVo.setShare(v.getShare());
-                algorithmListGy.add(dropDownVo);
-            }
-
-        } else if (DictConstants.PLATFORM.equals(algorithmType)) {
-            // 第三方算法平台获取(索为)
-            String sort = "algorithmId-desc";
-            int page = 1;
-            int size = 999;// 全部
-            String urlParam = "&page=" + page + "&size=" + size + "&sort=" + sort;
-            algorithmListSy = getOtherAlgorithmInfo(urlParam);
-
-        }
-
-        Map typeMap = new HashMap();
-        typeMap.put("code", "公有");
-        typeMap.put("name", "公有");
-        List<Map> colourList = new LinkedList();
-        algorithmListGy.forEach(vo -> {
-            Map colourMap = new HashMap();
-            colourMap.put("code", vo.getId());
-            colourMap.put("name", vo.getName());
-            colourMap.put("vo", vo);
-            colourList.add(colourMap);
-        });
-        typeMap.put("children", colourList);
-        Map typeMap1 = new HashMap();
-        typeMap1.put("code", "私有");
-        typeMap1.put("name", "私有");
-        List<Map> colourList1 = new LinkedList();
-        algorithmListSy.forEach(vo -> {
-            Map colourMap = new HashMap();
-            colourMap.put("code", vo.getId());
-            colourMap.put("name", vo.getName());
-            colourMap.put("vo", vo);
-            colourList1.add(colourMap);
-        });
-        typeMap1.put("children", colourList1);
-        treeList.add(typeMap);
-        treeList.add(typeMap1);
-        /*
-         * List<DropDownNewVo> listGSy = new ArrayList<>();
-         * DropDownNewVo dropDownNewSyVo = new DropDownNewVo();
-         * dropDownNewSyVo.setLabel("私有");
-         * dropDownNewSyVo.setOptions(algorithmListSy);
-         * listGSy.add(dropDownNewSyVo);
-         * DropDownNewVo dropDownNewGyVo = new DropDownNewVo();
-         * dropDownNewGyVo.setLabel("公有");
-         * dropDownNewGyVo.setOptions(algorithmListGy);
-         * listGSy.add(dropDownNewGyVo);
-         */
-        DropDownTypeNewVo dropDownTypeNewVo = new DropDownTypeNewVo();
-        dropDownTypeNewVo.setDropDownList(treeList);
-        dropDownTypeNewVo.setType("1");
-        result.add(dropDownTypeNewVo);
-
-    }
-
-    private void setVehicleDropDownNew(List<DropDownTypeNewVo> result) {
-        List<Map> treeList = new ArrayList<>();
-        ConfigPO configPO = new ConfigPO();
-        configPO.setCreateUserId(AuthUtil.getCurrentUserId());
-        List<ConfigPO> vehicleBaseInfoSyVo = simulationProjectMapper.selectConfigVehicleSy(configPO);
-        List<DropDownVo> vehicleSyList = new ArrayList<>();
-        for (ConfigPO v : vehicleBaseInfoSyVo) {
-            DropDownVo dropDownVo = new DropDownVo();
-            dropDownVo.setId(v.getId());
-            dropDownVo.setName(v.getConfigName());
-            dropDownVo.setDescription(v.getDescription());
-            dropDownVo.setShare(v.getShare());
-            // 获取传感器信息
-            List<ConfigSensorPO> configSensorVos = simulationProjectMapper.selectConfigSensor(v.getId());
-            String sensor = "";
-            if (!isEmpty(configSensorVos) && configSensorVos.get(0) != null) {
-                StringBuilder stringBuilder = new StringBuilder();
-                for (ConfigSensorPO cv : configSensorVos) {
-                    stringBuilder.append(cv.getSensorType()).append(",");
-                }
-                sensor = stringBuilder.substring(0, stringBuilder.lastIndexOf(","));
-
-            }
-            dropDownVo.setSensor(sensor);
-
-            vehicleSyList.add(dropDownVo);
-        }
-
-        List<ConfigPO> vehicleBaseInfoGyVo = simulationProjectMapper.selectConfigVehicleGy(configPO);
-        List<DropDownVo> vehicleGyList = new ArrayList<>();
-        for (ConfigPO v : vehicleBaseInfoGyVo) {
-            DropDownVo dropDownVo = new DropDownVo();
-            dropDownVo.setId(v.getId());
-            dropDownVo.setName(v.getConfigName());
-            dropDownVo.setDescription(v.getDescription());
-            dropDownVo.setShare(v.getShare());
-            // 获取传感器信息
-            List<ConfigSensorPO> configSensorVos = simulationProjectMapper.selectConfigSensor(v.getId());
-            String sensor = "";
-            if (!isEmpty(configSensorVos) && configSensorVos.get(0) != null) {
-                StringBuilder stringBuilder = new StringBuilder();
-                for (ConfigSensorPO cv : configSensorVos) {
-                    stringBuilder.append(cv.getSensorType()).append(",");
-                }
-                sensor = stringBuilder.substring(0, stringBuilder.lastIndexOf(","));
+    List<ConfigPO> vehicleBaseInfoGyVo = simulationProjectMapper.selectConfigVehicleGy(configPO);
+    List<DropDownVo> vehicleGyList = new ArrayList<>();
+    for (ConfigPO v : vehicleBaseInfoGyVo) {
+      DropDownVo dropDownVo = new DropDownVo();
+      dropDownVo.setId(v.getId());
+      dropDownVo.setName(v.getConfigName());
+      dropDownVo.setDescription(v.getDescription());
+      dropDownVo.setShare(v.getShare());
+      // 获取传感器信息
+      List<ConfigSensorPO> configSensorVos = simulationProjectMapper.selectConfigSensor(v.getId());
+      String sensor = "";
+      if (!isEmpty(configSensorVos) && configSensorVos.get(0) != null) {
+        StringBuilder stringBuilder = new StringBuilder();
+        for (ConfigSensorPO cv : configSensorVos) {
+          stringBuilder.append(cv.getSensorType()).append(",");
+        }
+        sensor = stringBuilder.substring(0, stringBuilder.lastIndexOf(","));
 
-            }
-            dropDownVo.setSensor(sensor);
+      }
+      dropDownVo.setSensor(sensor);
 
-            vehicleGyList.add(dropDownVo);
-        }
-        /*
-         * List<DropDownNewVo> listGSy = new ArrayList<>();
-         * DropDownNewVo dropDownNewSyVo = new DropDownNewVo();
-         * dropDownNewSyVo.setLabel("私有");
-         * dropDownNewSyVo.setOptions(vehicleSyList);
-         * listGSy.add(dropDownNewSyVo);
-         * DropDownNewVo dropDownNewGyVo = new DropDownNewVo();
-         * dropDownNewGyVo.setLabel("公有");
-         * dropDownNewGyVo.setOptions(vehicleGyList);
-         * listGSy.add(dropDownNewGyVo);
-         */
-        Map typeMap = new HashMap();
-        typeMap.put("code", "公有");
-        typeMap.put("name", "公有");
-        List<Map> colourList = new LinkedList();
-        vehicleGyList.forEach(vo -> {
-            Map colourMap = new HashMap();
-            colourMap.put("code", vo.getId());
-            colourMap.put("name", vo.getName());
-            colourMap.put("vo", vo);
-            colourList.add(colourMap);
-        });
-        typeMap.put("children", colourList);
-        Map typeMap1 = new HashMap();
-        typeMap1.put("code", "私有");
-        typeMap1.put("name", "私有");
-        List<Map> colourList1 = new LinkedList();
-        vehicleSyList.forEach(vo -> {
-            Map colourMap = new HashMap();
-            colourMap.put("code", vo.getId());
-            colourMap.put("name", vo.getName());
-            colourMap.put("vo", vo);
-            colourList1.add(colourMap);
-        });
-        typeMap1.put("children", colourList1);
-        treeList.add(typeMap);
-        treeList.add(typeMap1);
-
-        DropDownTypeNewVo dropDownTypeNewVo = new DropDownTypeNewVo();
-        dropDownTypeNewVo.setDropDownList(treeList);
-        dropDownTypeNewVo.setType("2");
-        result.add(dropDownTypeNewVo);
-    }
-
-    private void setScenePackageDropDownNew(List<DropDownTypeNewVo> result) {
-        List<Map> treeList = new ArrayList<>();
-        ScenePackagePO scenePackagePO = new ScenePackagePO();
-        scenePackagePO.setCreateUserId(AuthUtil.getCurrentUserId());
-        List<ScenePackagePO> scenePackageBaseSyVo = simulationProjectMapper
-                .selectScenePackageBaseByIdSy(scenePackagePO);
-        List<DropDownVo> scenePackageSyList = new ArrayList<>();
-        for (ScenePackagePO v : scenePackageBaseSyVo) {
-            DropDownVo dropDownVo = new DropDownVo();
-            dropDownVo.setId(v.getPackageId());
-            dropDownVo.setName(v.getPackageName());
-            dropDownVo.setSceneNum(String.valueOf(v.getSceneNum()));
-            dropDownVo.setShare(v.getShare());
-            scenePackageSyList.add(dropDownVo);
-        }
-        List<ScenePackagePO> scenePackageBaseGyVo = simulationProjectMapper
-                .selectScenePackageBaseByIdGy(scenePackagePO);
-        List<DropDownVo> scenePackageGyList = new ArrayList<>();
-        for (ScenePackagePO v : scenePackageBaseGyVo) {
-            DropDownVo dropDownVo = new DropDownVo();
-            dropDownVo.setId(v.getPackageId());
-            dropDownVo.setName(v.getPackageName());
-            dropDownVo.setSceneNum(String.valueOf(v.getSceneNum()));
-            dropDownVo.setShare(v.getShare());
-            scenePackageGyList.add(dropDownVo);
-        }
-        Map typeMap = new HashMap();
-        typeMap.put("code", "公有");
-        typeMap.put("name", "公有");
-        List<Map> colourList = new LinkedList();
-        scenePackageGyList.forEach(vo -> {
-            Map colourMap = new HashMap();
-            colourMap.put("code", vo.getId());
-            colourMap.put("name", vo.getName());
-            colourMap.put("vo", vo);
-            colourList.add(colourMap);
-        });
-        typeMap.put("children", colourList);
-        Map typeMap1 = new HashMap();
-        typeMap1.put("code", "私有");
-        typeMap1.put("name", "私有");
-        List<Map> colourList1 = new LinkedList();
-        scenePackageSyList.forEach(vo -> {
-            Map colourMap = new HashMap();
-            colourMap.put("code", vo.getId());
-            colourMap.put("name", vo.getName());
-            colourMap.put("vo", vo);
-            colourList1.add(colourMap);
-        });
-        typeMap1.put("children", colourList1);
-        treeList.add(typeMap);
-        treeList.add(typeMap1);
-        DropDownTypeNewVo dropDownTypeNewVo = new DropDownTypeNewVo();
-        dropDownTypeNewVo.setDropDownList(treeList);
-        dropDownTypeNewVo.setType("3");
-        result.add(dropDownTypeNewVo);
+      vehicleGyList.add(dropDownVo);
+    }
+    /*
+     * List<DropDownNewVo> listGSy = new ArrayList<>();
+     * DropDownNewVo dropDownNewSyVo = new DropDownNewVo();
+     * dropDownNewSyVo.setLabel("私有");
+     * dropDownNewSyVo.setOptions(vehicleSyList);
+     * listGSy.add(dropDownNewSyVo);
+     * DropDownNewVo dropDownNewGyVo = new DropDownNewVo();
+     * dropDownNewGyVo.setLabel("公有");
+     * dropDownNewGyVo.setOptions(vehicleGyList);
+     * listGSy.add(dropDownNewGyVo);
+     */
+    Map typeMap = new HashMap();
+    typeMap.put("code", "公有");
+    typeMap.put("name", "公有");
+    List<Map> colourList = new LinkedList();
+    vehicleGyList.forEach(vo -> {
+      Map colourMap = new HashMap();
+      colourMap.put("code", vo.getId());
+      colourMap.put("name", vo.getName());
+      colourMap.put("vo", vo);
+      colourList.add(colourMap);
+    });
+    typeMap.put("children", colourList);
+    Map typeMap1 = new HashMap();
+    typeMap1.put("code", "私有");
+    typeMap1.put("name", "私有");
+    List<Map> colourList1 = new LinkedList();
+    vehicleSyList.forEach(vo -> {
+      Map colourMap = new HashMap();
+      colourMap.put("code", vo.getId());
+      colourMap.put("name", vo.getName());
+      colourMap.put("vo", vo);
+      colourList1.add(colourMap);
+    });
+    typeMap1.put("children", colourList1);
+    treeList.add(typeMap);
+    treeList.add(typeMap1);
+
+    DropDownTypeNewVo dropDownTypeNewVo = new DropDownTypeNewVo();
+    dropDownTypeNewVo.setDropDownList(treeList);
+    dropDownTypeNewVo.setType("2");
+    result.add(dropDownTypeNewVo);
+  }
+
+  private void setScenePackageDropDownNew(List<DropDownTypeNewVo> result) {
+    List<Map> treeList = new ArrayList<>();
+    ScenePackagePO scenePackagePO = new ScenePackagePO();
+    scenePackagePO.setCreateUserId(AuthUtil.getCurrentUserId());
+    List<ScenePackagePO> scenePackageBaseSyVo = simulationProjectMapper.selectScenePackageBaseByIdSy(scenePackagePO);
+    List<DropDownVo> scenePackageSyList = new ArrayList<>();
+    for (ScenePackagePO v : scenePackageBaseSyVo) {
+      DropDownVo dropDownVo = new DropDownVo();
+      dropDownVo.setId(v.getPackageId());
+      dropDownVo.setName(v.getPackageName());
+      dropDownVo.setSceneNum(String.valueOf(v.getSceneNum()));
+      dropDownVo.setShare(v.getShare());
+      scenePackageSyList.add(dropDownVo);
+    }
+    List<ScenePackagePO> scenePackageBaseGyVo = simulationProjectMapper.selectScenePackageBaseByIdGy(scenePackagePO);
+    List<DropDownVo> scenePackageGyList = new ArrayList<>();
+    for (ScenePackagePO v : scenePackageBaseGyVo) {
+      DropDownVo dropDownVo = new DropDownVo();
+      dropDownVo.setId(v.getPackageId());
+      dropDownVo.setName(v.getPackageName());
+      dropDownVo.setSceneNum(String.valueOf(v.getSceneNum()));
+      dropDownVo.setShare(v.getShare());
+      scenePackageGyList.add(dropDownVo);
     }
+    Map typeMap = new HashMap();
+    typeMap.put("code", "公有");
+    typeMap.put("name", "公有");
+    List<Map> colourList = new LinkedList();
+    scenePackageGyList.forEach(vo -> {
+      Map colourMap = new HashMap();
+      colourMap.put("code", vo.getId());
+      colourMap.put("name", vo.getName());
+      colourMap.put("vo", vo);
+      colourList.add(colourMap);
+    });
+    typeMap.put("children", colourList);
+    Map typeMap1 = new HashMap();
+    typeMap1.put("code", "私有");
+    typeMap1.put("name", "私有");
+    List<Map> colourList1 = new LinkedList();
+    scenePackageSyList.forEach(vo -> {
+      Map colourMap = new HashMap();
+      colourMap.put("code", vo.getId());
+      colourMap.put("name", vo.getName());
+      colourMap.put("vo", vo);
+      colourList1.add(colourMap);
+    });
+    typeMap1.put("children", colourList1);
+    treeList.add(typeMap);
+    treeList.add(typeMap1);
+    DropDownTypeNewVo dropDownTypeNewVo = new DropDownTypeNewVo();
+    dropDownTypeNewVo.setDropDownList(treeList);
+    dropDownTypeNewVo.setType("3");
+    result.add(dropDownTypeNewVo);
+  }
 
 }