package com.css.simulation.resource.server.app.impl;

import api.common.pojo.common.PageVO;
import api.common.pojo.common.ResponseBodyVO;
import api.common.pojo.constants.DictConstants;
import api.common.pojo.constants.ProjectConstants;
import api.common.pojo.constants.StateConstant;
import api.common.pojo.enums.SceneEvaluationEnum;
import api.common.pojo.param.KafkaParameter;
import api.common.pojo.param.MinioParameter;
import api.common.pojo.param.algorithm.AlgorithmParameter;
import api.common.pojo.param.project.ProjectTaskParam;
import api.common.pojo.param.project.SceneScoreParam;
import api.common.pojo.param.project.SimulationManualProjectKafkaParam;
import api.common.pojo.param.project.SimulationManualProjectParam;
import api.common.pojo.param.system.DictParam;
import api.common.pojo.po.algorithm.AlgorithmPO;
import api.common.pojo.po.model.ConfigPO;
import api.common.pojo.po.model.ConfigSensorPO;
import api.common.pojo.po.model.VehiclePO;
import api.common.pojo.po.project.*;
import api.common.pojo.po.scene.SceneComplexityPO;
import api.common.pojo.po.scene.ScenePackagePO;
import api.common.pojo.po.scene.SceneRiskPO;
import api.common.pojo.vo.algorithm.AlgorithmVO;
import api.common.pojo.vo.project.*;
import api.common.util.*;
import com.css.simulation.resource.server.domain.service.UserDomainService;
import com.css.simulation.resource.server.infra.db.mysql.mapper.*;
import com.css.simulation.resource.server.app.service.AlgorithmService;
import com.css.simulation.resource.server.infra.util.*;
import com.css.simulation.resource.server.infra.feign.service.AlgoPlatformService;
import com.css.simulation.resource.server.infra.feign.service.FileDownService;
import com.css.simulation.resource.server.infra.feign.service.MonitorService;
import com.css.simulation.resource.server.app.constant.ProjectRunStateEnum;
import com.css.simulation.resource.server.app.constant.SceneTypeEnum;
import com.css.simulation.resource.server.app.service.job_manage.SimulationProjectService;
import com.css.simulation.resource.server.app.service.DictService;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.ImmutableMap;
import com.itextpdf.text.*;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfWriter;
import feign.Response;
import lombok.SneakyThrows;
import lombok.Synchronized;
import lombok.extern.slf4j.Slf4j;
import org.apache.tomcat.util.buf.StringUtils;
import org.jfree.chart.ChartUtils;
import org.jfree.data.category.DefaultCategoryDataset;
import org.jfree.data.general.DefaultPieDataset;
import org.springframework.beans.BeanUtils;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.scheduling.support.CronExpression;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.List;
import java.util.*;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

@Service
@Slf4j
public class SimulationProjectServiceImpl implements SimulationProjectService {

    //    @Resource
//    private StringRedisTemplate stringRedisTemplate;
    @Resource
    private SimulationManualProjectMapper simulationManualProjectMapper;
    @Resource
    private ManualProjectMapper manualProjectMapper;
    @Resource
    private AutoSubProjectMapper autoSubProjectMapper;
    @Resource
    private SimulationAutomaticProjectMapper simulationAutomaticProjectMapper;
    @Resource
    private SimulationManualProjectTaskMapper simulationManualProjectTaskMapper;
    @Resource
    private SimulationAutomaticSubprojectMapper simulationAutomaticSubProjectMapper;
    @Resource
    private SimulationMptFirstTargetScoreMapper simulationMptFirstTargetScoreMapper;
    @Resource
    private SimulationMptLastTargetScoreMapper simulationMptLastTargetScoreMapper;
    @Resource
    private AlgorithmMapper algorithmMapper;
    @Resource
    private AlgorithmExpandMapper algorithmExpandMapper;
    @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;
    @Resource
    private UserDomainService userDomainService;
    @Resource
    private SceneComplexityMapper sceneComplexityMapper;
    @Resource
    private SceneRiskMapper sceneRiskMapper;
    @Resource
    private SceneEvaluationRuleMapper sceneEvaluationRuleMapper;

    // * -------------------------------- 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 = simulationManualProjectMapper.selectProjectByName(param);
//            if (!isEmpty(simulationManualProjectPOS)) {
//                return new ResponseBodyVO<>(ResponseBodyVO.Response.CLIENT_FAILURE, "工作名称已经存在，请修改后再保存。");
//            }
            po.createPo(AuthUtil.getCurrentUserId());
            // 生成id
            createProjectIdAndAdd(po);
            return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS, ResponseBodyVO.Response.SUCCESS.getMessage(), po.getId());
        } else {
            // 取工作状态，仅未开始的才可以修改信息
            SimulationManualProjectPO simulationManualProjectPo = simulationManualProjectMapper.selectProjectById(param);
            if (!ProjectRunStateEnum.NOT_START.getCode().equals(simulationManualProjectPo.getNowRunState())) {
                return new ResponseBodyVO<>(ResponseBodyVO.Response.SERVER_FAILURE, "当前状态不支持修改。");
            }
            po.updatePo(AuthUtil.getCurrentUserId());
            int update = simulationManualProjectMapper.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<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 = simulationManualProjectMapper.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);
    }

    @Override
    public ResponseBodyVO<SimulationManualProjectSingleVo> selectProjectById(SimulationManualProjectParam param) {
        if (isEmpty(param.getId())) {
            return new ResponseBodyVO<>(ResponseBodyVO.Response.CLIENT_FAILURE);
        }
        SimulationManualProjectPO po = simulationManualProjectMapper.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<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 = simulationManualProjectMapper.selectProjectNowRunState(idArr);
        for (SimulationManualProjectPO p : pos) {
            if (ProjectRunStateEnum.EXECUTION.getCode().equals(p.getNowRunState())) {
                return new ResponseBodyVO<>(ResponseBodyVO.Response.SERVER_FAILURE, "数据不支持删除。");
            }
        }

        int i = simulationManualProjectMapper.deleteProject(idArr);
        if (i > 0) {
            return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS);
        }
        return new ResponseBodyVO<>(ResponseBodyVO.Response.SERVER_FAILURE, "删除失败。");
    }

    /**
     * 1. 手动项目：第一次运行项目 10 -> 20
     * 2. 手动项目：已完成的项目再次运行 20
     * 2. 手动项目：终止项目 20 -> 40
     * 3. 手动项目：重新运行项目 40 -> 20
     */
    @Override
    public ResponseBodyVO<String> updateProjectNowRunState(SimulationManualProjectParam oldProjectParam) {
        //1 查询项目详细信息，即使是新创建的任务也是保存了信息后再执行
        SimulationManualProjectPO oldProjectPO = projectUtil.getProjectInfo(oldProjectParam);
        final String oldState = oldProjectPO.getNowRunState();
        final String newState = oldProjectParam.getNowRunState();
        final String oldProjectId = oldProjectParam.getId();
        final int parallelism = Integer.parseInt(oldProjectPO.getParallelism());
        //2 查询项目详情信息，固定项目最原始的运行数据
        ProjectDetailsVO projectDetailsVO = selectProjectDetailsByIdBeforeRunning(SimulationManualProjectParam.builder().id(oldProjectId).projectType(DictConstants.PROJECT_TYPE_MANUAL).build()).getInfo();
        projectDetailsVO.setFinishTime("");
        projectDetailsVO.setAlgorithmScoreList(new ArrayList<>());
        log.info("项目 " + oldProjectId + " 的详情信息为：" + projectDetailsVO);

        if (DictConstants.PROJECT_TERMINATED.equals(newState)) {
            projectDetailsVO.setNowRunState(DictConstants.PROJECT_TERMINATED);
            projectDetailsVO.setNowRunStateName(DictConstants.PROJECT_TERMINATED_NAME);
            String projectDetailsVOJson = JsonUtil.beanToJson(projectDetailsVO);
            oldProjectPO.setDetails(projectDetailsVOJson);
            simulationManualProjectMapper.updateDetailsAndNowRunStateById(oldProjectId, projectDetailsVOJson, DictConstants.PROJECT_TERMINATED);
            projectStopToKafka(oldProjectPO);
        } else if (DictConstants.PROJECT_RUNNING.equals(newState)) {
            projectDetailsVO.setNowRunState(DictConstants.PROJECT_RUNNING);
            projectDetailsVO.setNowRunStateName(DictConstants.PROJECT_RUNNING_NAME);
            //1 校验项目的信息是否可用
            projectUtil.checkProject(oldProjectPO.getAlgorithm(), oldProjectPO.getVehicle(), oldProjectPO.getScene(), parallelism);
            if (DictConstants.PROJECT_COMPLETED.equals(oldState)) {  // 根据已完成的项目创建新项目
                SimulationManualProjectPO newProjectPO = new SimulationManualProjectPO();
                BeanUtils.copyProperties(oldProjectPO, newProjectPO);
                projectDetailsVO.setStartTime(TimeUtil.dateToString(new Date()));
                //1 初始化数据
                newProjectPO.createPo(AuthUtil.getCurrentUserId()); // 创建新ID
                synchronized (newProjectPO) {
                    newProjectPO.setNowRunState(DictConstants.PROJECT_RUNNING);
                    newProjectPO.setEvaluationLevel("");
                    newProjectPO.setStartTime(new Date());
                    newProjectPO.setFinishTime(null);
                    projectDetailsVO.setProjectId(newProjectPO.getProjectId());
                    String projectDetailsVOJson = JsonUtil.beanToJson(projectDetailsVO);
                    newProjectPO.setDetails(projectDetailsVOJson);
                    createProjectIdAndAdd(newProjectPO);

                }
                projectRunToKafka(newProjectPO);
            } else if (DictConstants.PROJECT_TERMINATED.equals(oldState)) { //重新运行被终止的项目需要修改新的ID
                // 如果是重新运行的项目，修改项目ID
                String newProjectId = StringUtil.getRandomUUID();
                oldProjectPO.setId(newProjectId);
                String projectDetailsVOJson = JsonUtil.beanToJson(projectDetailsVO);
                simulationManualProjectMapper.updateIdAndDetailsAndNowRunStateById(oldProjectId, newProjectId, projectDetailsVOJson, DictConstants.PROJECT_RUNNING);
                projectRunToKafka(oldProjectPO);
            } else if (DictConstants.PROJECT_WAITING.equals(oldState)) { // 启动已保存的新项目
                String projectDetailsVOJson = JsonUtil.beanToJson(projectDetailsVO);
                simulationManualProjectMapper.updateDetailsAndNowRunStateById(oldProjectId, projectDetailsVOJson, DictConstants.PROJECT_RUNNING);
                projectRunToKafka(oldProjectPO);
            } else {
                throw new RuntimeException("未知项目状态:" + oldState);
            }

        }
        return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS);
    }

    @SneakyThrows
    private void projectRunToKafka(SimulationManualProjectPO po) {
        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()));
    }

    @SneakyThrows
    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;
        final String projectType = param.getProjectType();
        String details;
        String algorithmType;
        String algorithmId;
        String projectId;
        String createTime;
        if (DictConstants.PROJECT_TYPE_MANUAL.equals(projectType)) { // 手动运行任务
            SimulationManualProjectPO simulationManualProjectPO = simulationManualProjectMapper.selectProjectById(param);
            details = simulationManualProjectPO.getDetails();
            algorithmType = simulationManualProjectPO.getAlgorithmType();
            algorithmId = simulationManualProjectPO.getAlgorithm();
            projectId = simulationManualProjectPO.getProjectId();
            createTime = String.valueOf(simulationManualProjectPO.getCreateTime());
        } else if (DictConstants.PROJECT_TYPE_AUTO_SUB.equals(projectType)) {
            SimulationManualProjectVO simulationManualProjectVO = simulationAutomaticSubProjectMapper.selectProjectInfo(param);
            details = simulationManualProjectVO.getDetails();
            algorithmType = simulationManualProjectVO.getAlgorithmType();
            algorithmId = simulationManualProjectVO.getAlgorithm();
            projectId = simulationManualProjectVO.getProjectId();
            createTime = String.valueOf(simulationManualProjectVO.getCreateTime());
        } else {
            throw new RuntimeException("未知项目类型：" + projectType);
        }
        projectDetailsVO = JsonUtil.jsonToBean(details, ProjectDetailsVO.class);

        // 修正项目ID、创建时间
        {
            projectDetailsVO.setProjectId(projectId);
            if (StringUtil.isEmpty(projectDetailsVO.getStartTime())) {
                projectDetailsVO.setStartTime(createTime);
            }
        }
        //修正算法名称
        {
            String algorithmName = null;
            String algorithmDescription = null;
            {
                if (DictConstants.ALGORITHM_UPLOAD_MODE_PLATFORM.equals(algorithmType)) {
                    List<AlgorithmVO> select = algorithmExpandMapper.select(AlgorithmParameter.builder().algorithmId(algorithmId).build());
                    AlgorithmVO algorithmVO = select.get(0);
                    algorithmName = algorithmVO.getAlgorithmName() + "-" + algorithmVO.getAlgorithmVersion();
                    algorithmDescription = select.get(0).getDescription();
                }
                // 暂时不处理非算法平台的算法
                projectDetailsVO.setAlgorithmName(algorithmName);
                projectDetailsVO.setAlgorithmDescribe(algorithmDescription);
            }
        }

        //* -------------------------------- 任务 --------------------------------
        List<ProjectRunStateNumVo> states = null;
        List<ProjectRunResultRatioNumVo> resultScoreList = null;
        ProjectTaskParam projectTaskParam = new ProjectTaskParam();
        projectTaskParam.setPId(param.getId());
        List<ProjectRunResultRatioNumVo> projectRunResultRatioNumVos = null;
        Integer size = simulationManualProjectTaskMapper.selectProjectTaskNumByProjectId(projectTaskParam);
        if (size > 0) {
            states = simulationManualProjectTaskMapper.selectRunStateCount(param.getId());
            taskRunState(states, size);
            projectRunResultRatioNumVos = simulationManualProjectTaskMapper.selectRunResultCount(param.getId());
            taskResultState(projectRunResultRatioNumVos, size);

            resultScoreList = simulationManualProjectTaskMapper.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);
    }

    /**
     * 查询项目详情，不使用详情字段中的某些字段，例如项目运行状态，并查询任务列表
     */
    @Override
    @SneakyThrows
    public ResponseBodyVO<ProjectDetailsVO> selectProjectDetailsByIdForScheduler(SimulationManualProjectParam param) {

        ProjectDetailsVO projectDetailsVO = null;
        String algorithmType = null;
        String algorithmId = null;
        if (DictConstants.PROJECT_TYPE_MANUAL.equals(param.getProjectType())) { // 手动运行任务
            SimulationManualProjectPO po = simulationManualProjectMapper.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()));
            algorithmType = po.getAlgorithmType();
            algorithmId = po.getAlgorithm();
        } 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()));
            algorithmType = po.getAlgorithmType();
            algorithmId = po.getAlgorithm();
        }
        // 获取测试得分列表
        List<AlgorithmScoreVO> firstTargetScore = getFirstTargetScore(param.getId());
        projectDetailsVO.setAlgorithmScoreList(firstTargetScore);

        // 修改算法名称和算法描述
        String algorithmName = null;
        String algorithmDescription = null;
        {
            if (DictConstants.ALGORITHM_UPLOAD_MODE_PLATFORM.equals(algorithmType)) {
                List<AlgorithmVO> select = algorithmExpandMapper.select(AlgorithmParameter.builder().algorithmId(algorithmId).build());
                AlgorithmVO algorithmVO = select.get(0);
                algorithmName = algorithmVO.getAlgorithmName() + "-" + algorithmVO.getAlgorithmVersion();
                algorithmDescription = select.get(0).getDescription();
            }
            //TODO 暂时不处理非算法平台的算法
            projectDetailsVO.setAlgorithmName(algorithmName);
            projectDetailsVO.setAlgorithmDescribe(algorithmDescription);
        }


        //* -------------------------------- 任务 --------------------------------
        List<ProjectRunStateNumVo> states = null;
        List<ProjectRunResultRatioNumVo> resultScoreList = null;
        ProjectTaskParam projectTaskParam = new ProjectTaskParam();
        projectTaskParam.setPId(param.getId());
        List<ProjectRunResultRatioNumVo> projectRunResultRatioNumVos = null;
        Integer size = simulationManualProjectTaskMapper.selectProjectTaskNumByProjectId(projectTaskParam);
        if (size > 0) {
            states = simulationManualProjectTaskMapper.selectRunStateCount(param.getId());
            taskRunState(states, size);
            projectRunResultRatioNumVos = simulationManualProjectTaskMapper.selectRunResultCount(param.getId());
            taskResultState(projectRunResultRatioNumVos, size);

            resultScoreList = simulationManualProjectTaskMapper.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);
    }


    @SneakyThrows
    private ResponseBodyVO<ProjectDetailsVO> selectProjectDetailsByIdBeforeRunning(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 projectPO = new SimulationManualProjectPO();

        if (DictConstants.PROJECT_TYPE_MANUAL.equals(param.getProjectType())) { // 手动运行任务
            // 项目基本信息
            SimulationManualProjectPO po = simulationManualProjectMapper.selectProjectById(param);
            if (po == null) {
                return new ResponseBodyVO<>(ResponseBodyVO.Response.SERVER_FAILURE, "没有获取到数据");
            }
            projectPO = po;
        } else if (DictConstants.PROJECT_TYPE_AUTO_SUB.equals(param.getProjectType())) {
            SimulationManualProjectVO po = simulationAutomaticSubProjectMapper.selectProjectInfo(param);
            if (po == null) {
                return new ResponseBodyVO<>(ResponseBodyVO.Response.SERVER_FAILURE, "没有获取到数据");
            }
            BeanUtils.copyProperties(po, projectPO);

        }

        // 获取场景包信息
        ScenePackagePO scenePackagePO = simulationManualProjectMapper.selectScenePackageInfoById(projectPO.getScene());

        projectDetailsVO.setPackageName(scenePackagePO.getPackageName());

        // 算法配置
        AlgorithmPO algorithmBaseInfoVo = getAlgorithmInfo(projectPO);
        // 获取测试得分列表
        List<AlgorithmScoreVO> firstTargetScore = getFirstTargetScore(param.getId());
        projectDetailsVO.setAlgorithmScoreList(firstTargetScore);

        // 车辆配置
        VehiclePO vehicleBaseInfoVo = null;
        String vehicleConfigId = projectPO.getVehicle();

        ConfigPO configPO = new ConfigPO();
        configPO.setId(vehicleConfigId);
        List<ConfigPO> configVehicleVOS = simulationManualProjectMapper.selectConfigVehicle(configPO);
        if (!isEmpty(configVehicleVOS)) {
            ConfigPO configVehicleVO = configVehicleVOS.get(0);
            List<VehiclePO> vehiclePOS = simulationManualProjectMapper.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 = simulationManualProjectMapper.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 = simulationManualProjectMapper.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 = simulationManualProjectMapper.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 = simulationManualProjectMapper.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 = simulationManualProjectMapper.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 = simulationManualProjectMapper.selectSensorGps(sensorId);
                setVehicleConfig(sensorBaseInfoVo, vs);
                sensorGpsList.add(sensorBaseInfoVo);
            }
        }

        projectDetailsVO.setProjectId(projectPO.getProjectId());
        projectDetailsVO.setProjectName(projectPO.getProjectName());
        projectDetailsVO.setProjectDescribe(projectPO.getProjectDescribe());
        projectDetailsVO.setStartTime(getRqStr(projectPO.getStartTime(), 1));
        projectDetailsVO.setFinishTime(getRqStr(projectPO.getFinishTime(), 1));
        projectDetailsVO.setNowRunState(projectPO.getNowRunState());
        projectDetailsVO.setNowRunStateName(getDictName(DictConstants.PROJECT_RUN_STATE, projectPO.getNowRunState()));
        projectDetailsVO.setEvaluationLevel(getDictName(DictConstants.EVALUATION_LEVEL, projectPO.getEvaluationLevel()));
        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(projectPO.getParallelism());
        projectDetailsVO.setMaxSimulationTime(projectPO.getMaxSimulationTime());
        String isChoiceGpu = projectPO.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;
         * }
         * }
         *
         * projectDetailsVO.setCreateReport(isCreateReport);
         */

        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);
            }

        }
    }

    // 运行结果统计
    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());
        }

    }

    @Override
    public ResponseBodyVO<ProjectReportVO> selectProjectReportById(SimulationManualProjectParam param) {
        final String projectType = param.getProjectType();
        final String id = param.getId();
        ProjectReportVO projectReportVO;
        if (DictConstants.PROJECT_TYPE_MANUAL.equals(projectType)) {
            final String projectReportVOJson = simulationManualProjectMapper.selectReportById(id);
            projectReportVO = JsonUtil.jsonToBean(projectReportVOJson, ProjectReportVO.class);
        } else if (DictConstants.PROJECT_TYPE_AUTO_SUB.equals(projectType)) {
            final String projectReportVOJson = simulationAutomaticSubProjectMapper.selectReportById(id);
            projectReportVO = JsonUtil.jsonToBean(projectReportVOJson, ProjectReportVO.class);
        } else {
            throw new RuntimeException("未知项目类型：" + projectType);
        }
        return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS, projectReportVO);
    }

    @Override
    public ResponseBodyVO<ProjectReportVO> selectProjectReportByIdForScheduler(SimulationManualProjectParam param) {
        String projectType = param.getProjectType();
        // 封装要使用到的数据
        SimulationManualProjectPO projectPO = new SimulationManualProjectPO();

        if (DictConstants.PROJECT_TYPE_MANUAL.equals(projectType)) {
            // 项目基本信息
            projectPO = simulationManualProjectMapper.selectProjectBaseById(param);
        } else if (DictConstants.PROJECT_TYPE_AUTO_SUB.equals(projectType)) {
            SimulationManualProjectVO po = simulationAutomaticSubProjectMapper.selectProjectInfo(param);
            BeanUtils.copyProperties(po, projectPO);
        }

        // 算法配置
        AlgorithmPO algorithmBaseInfoVo = getAlgorithmInfo(projectPO);
        ProjectReportVO projectReportVO = new ProjectReportVO();
        projectReportVO.setProjectId(projectPO.getProjectId());
        projectReportVO.setProjectName(projectPO.getProjectName());
        projectReportVO.setAlgorithmName(algorithmBaseInfoVo.getAlgorithmName());
        projectReportVO.setAlgorithmDescribe(algorithmBaseInfoVo.getDescription());

        // 添加开始时间
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        if (projectPO.getStartTime() != null) {
            projectReportVO.setStartTime(dateFormat.format(projectPO.getStartTime()));
        }

        String sceneNames;

        // 算法测试得分表
        /*
         * 汇总测试得分计算方法：（每一项一级指标的测试得分*测试权重）累加
         * 得分率计算方法：每一项一级指标的所有场景得分不为0的数量/每一项一级指标的场景数量
         * 汇总得分率计算方法：（每一项一级指标的所有场景得分不为0的数量_累加/每一项一级指标的场景数量_累加）换成（得分累加取平均值）
         */

        // 获取得分表一级指标信息
        SimulationMptFirstTargetScorePO par = new SimulationMptFirstTargetScorePO();
        par.setPId(projectPO.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(), projectPO.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 = projectPO.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(projectPO.getScene(), projectPO.getId());
        projectReportVO.setSubListScoreLiTitle((List<Map>) stringObjectMap.get("headerList"));
        projectReportVO.setSubListScoreLi((List<SubScListVo>) stringObjectMap.get("result"));

        // 场景得分列表
        Map<String, Object> maps = selectSceneScore2(projectPO.getScene(), projectPO.getId(), 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 = 0;
            int size = 99999;// 全部

            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 = simulationManualProjectMapper.selectAlgorithmInfoById(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 = simulationManualProjectTaskMapper.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 projectPO = new SimulationManualProjectPO();
        if (DictConstants.PROJECT_TYPE_MANUAL.equals(projectType)) {
            SimulationManualProjectPO spo = simulationManualProjectMapper.selectProjectBaseById(param);
            Optional.ofNullable(spo).orElseThrow(() -> new RuntimeException("没有获取到数据。"));
            projectPO = spo;
        } else if (DictConstants.PROJECT_TYPE_AUTO_SUB.equals(projectType)) {
            SimulationManualProjectVO spo = simulationAutomaticSubProjectMapper.selectProjectInfo(param);
            Optional.ofNullable(spo).orElseThrow(() -> new RuntimeException("没有获取到数据。"));
            BeanUtils.copyProperties(spo, projectPO);
        }
        Map<String, Object> stringObjectMap = selectSceneScore(projectPO.getScene(), projectPO.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 没有

            }
            // 计算总里程
            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) * 3.6; // 最大速度
            double zxsd = Collections.min(longitudinal_velocity_list) * 3.6; // 最小速度
            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(Double.toString(zdsd)); // 最大速度
            resultVo.setMinimunVelocity(Double.toString(zxsd)); // 最小速度
            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);
    }

    @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 "";
    }

    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;

    }

    @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 = simulationManualProjectTaskMapper.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]);
            }

        }
    }

    /**
     * 根据场景id和场景类型获取场景名
     *
     * @return 场景名称
     */
    private SceneBaseInfoVo getSceneNameAndOther(String sceneId, String sceneType) {
        SceneBaseInfoVo resultVo = new SceneBaseInfoVo();
        if (DictConstants.SCENE_NATURAL.equals(sceneType)) {
            SceneBaseInfoVo sceneBaseInfoVo = simulationManualProjectMapper.selectSceneNatural(sceneId);
            if (sceneBaseInfoVo != null) {
                resultVo.setCommonSceneName(sceneBaseInfoVo.getNaturalName());
            }
        } else if (DictConstants.SCENE_STANDARD.equals(sceneType)) {
            SceneBaseInfoVo sceneBaseInfoVo = simulationManualProjectMapper.selectSceneStandardsRegulations(sceneId);
            if (sceneBaseInfoVo != null) {
                resultVo.setCommonSceneName(sceneBaseInfoVo.getSceneName());
            }
        } else if (DictConstants.SCENE_ACCIDENT.equals(sceneType)) {
            SceneBaseInfoVo sceneBaseInfoVo = simulationManualProjectMapper.selectSceneAccidentById(sceneId);
            if (sceneBaseInfoVo != null) {
                resultVo.setCommonSceneName(sceneBaseInfoVo.getSceneName());
            }
        } else if (DictConstants.SCENE_GENERAL.equals(sceneType)) {
            SceneBaseInfoVo sceneBaseInfoVo = simulationManualProjectMapper.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 = simulationManualProjectMapper.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 = 0;
            int size = 99999;// 全部
            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 第三方算法平台的算法信息
     */
    private List<DropDownVo> getOtherAlgorithmInfo(String query) {

        try {
            //1 判断用户是否是管理员
            final boolean admin = userDomainService.isAdmin(AuthUtil.getCurrentUserId(), AuthUtil.getCurrentUserRoleCode());

            List<DropDownVo> algorithmList = new ArrayList<>();

            ResponseBodyVO<String> algorithmBody = algoPlatformService.getAlgorithmList(query);

            // 解析数据
            Map jsonMap = JsonUtil.jsonToMap(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) {
                    final String teamName = content.get("teamName");
                    final String algorithmId = content.get("algorithmId");
                    final String algorithmName = content.get("algorithmName");
                    final String evaluationName = content.get("evaluationName");    // 算法版本号
                    final String description = content.get("description");
                    if (StringUtil.isNotEmpty(teamName)) {
                        if (admin) {
                            DropDownVo dropDownVo = new DropDownVo();
                            dropDownVo.setId(algorithmId);
                            dropDownVo.setName(algorithmName + "-" + evaluationName);
                            dropDownVo.setDescription(description);
                            algorithmList.add(dropDownVo);
                        }
                    } else {
                        DropDownVo dropDownVo = new DropDownVo();
                        dropDownVo.setId(algorithmId);
                        dropDownVo.setName(algorithmName);
                        dropDownVo.setDescription(description);
                        algorithmList.add(dropDownVo);
                    }
                }
            }
            return algorithmList;
        } catch (Exception e) {
            throw new RuntimeException("获取第三方算法平台的算法信息失败。", e);
        }

    }

    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 = simulationManualProjectMapper.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 = simulationManualProjectMapper.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);

            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 = simulationManualProjectMapper.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());
        po.setComplexityEvaluationRuleId(param.getComplexityEvaluationRuleId());
        po.setRiskEvaluationRuleId(param.getRiskEvaluationRuleId());
        po.setExposureRateEvaluationRuleId(param.getExposureRateEvaluationRuleId());
        po.setCoverageRateEvaluationRuleId(param.getCoverageRateEvaluationRuleId());

        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 = simulationManualProjectMapper.selectAlgorithmInfoById(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));
    }

    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());
        vo.setComplexityEvaluationRuleId(po.getComplexityEvaluationRuleId());
        vo.setRiskEvaluationRuleId(po.getRiskEvaluationRuleId());
        vo.setCoverageRateEvaluationRuleId(po.getCoverageRateEvaluationRuleId());
        vo.setExposureRateEvaluationRuleId(po.getExposureRateEvaluationRuleId());

    }

    @Synchronized
    private void createProjectIdAndAdd(SimulationManualProjectPO po) {
        String nowDateString = TimeUtil.dateToString(new Date(), "yyyyMMdd");
        po.setProjectDate(Integer.valueOf(nowDateString));

//        SimulationManualProjectPO po1 = simulationManualProjectMapper.selectLastProjectId(Integer.valueOf(nowDateString), AuthUtil.getCreateUserId());
        SimulationManualProjectPO po1 = simulationManualProjectMapper.selectLastProjectId(Integer.valueOf(nowDateString));
        if (po1 == null) {
            // 生成新id
            po.setProjectNum(1);
        } else {
            po.setProjectNum(po1.getProjectNum() + 1);
        }
        po.setProjectId(po.getProjectDate() + "-" + po.getProjectNum());
        simulationManualProjectMapper.add(po);
    }

    @Synchronized
    private void createProjectIdAndAdd(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());
        simulationAutomaticProjectMapper.add(po);
    }

    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);

    }

    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;
    }

    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 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 = simulationManualProjectMapper.selectSceneNatural(sceneId);
            if (sceneBaseInfoVo != null) {
                vo.setSceneName(sceneBaseInfoVo.getNaturalName());
            }
        } else if (DictConstants.SCENE_STANDARD.equals(sceneType)) {
            // 标准法规
            sceneBaseInfoVo = simulationManualProjectMapper.selectSceneStandardsRegulations(sceneId);
            if (sceneBaseInfoVo != null) {
                vo.setSceneName(sceneBaseInfoVo.getSceneName());
            }
        } else if (DictConstants.SCENE_ACCIDENT.equals(sceneType)) {
            // 交通事故
            sceneBaseInfoVo = simulationManualProjectMapper.selectSceneAccidentById(sceneId);
            if (sceneBaseInfoVo != null) {
                vo.setSceneName(sceneBaseInfoVo.getSceneName());
            }
        } else if (DictConstants.SCENE_GENERAL.equals(sceneType)) {
            /// TODO 泛化场景暂不支持
            sceneBaseInfoVo = simulationManualProjectMapper.selectSceneGeneralDataById(sceneId);
            if (sceneBaseInfoVo != null) {
                vo.setSceneName(sceneBaseInfoVo.getSceneName());
            }

        }
    }

    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 = simulationManualProjectMapper.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 = simulationManualProjectMapper.selectSubSceneByPid(pvo.getSublistId());
                if (!isEmpty(cvoList)) {
                    // 存入父节点集合中
                    pvo.setChildScenePackageSubListVOList(cvoList);
                    // 继续查找下一节点
                    selectScenePackageSubListTreeAndSetScore(cvoList, false, null, pId, level + 1);
                } else {

                    // 没有子节点；最后一级，获取指标得分,指标得分说明,和指标下场景得分
                    setScore(pvo, pId);
                }

            }
        }

        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 = simulationManualProjectMapper.selectSubScore2(query);
        // 2 查询指定项目的所有任务得分结果
        ProjectTaskParam param = new ProjectTaskParam();
        param.setPId(projectId);
        if (!isEmpty(taskId)) {
            param.setTaskId(taskId);
        }
        List<ManualProjectTaskVo> taskList = simulationManualProjectTaskMapper.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 = simulationManualProjectMapper.selectSceneNatural(sceneId);
                            sceneName = sceneBaseInfoVo.getNaturalName();
                        } else if (DictConstants.SCENE_STANDARD.equals(sceneType)) {
                            sublistScoreVo.setSceneType("标准法规");
                            SceneBaseInfoVo sceneBaseInfoVo = simulationManualProjectMapper.selectSceneStandardsRegulations(sceneId);
                            sceneName = sceneBaseInfoVo.getSceneName();
                        } else if (DictConstants.SCENE_ACCIDENT.equals(sceneType)) {
                            sublistScoreVo.setSceneType("交通事故");
                            SceneBaseInfoVo sceneBaseInfoVo = simulationManualProjectMapper.selectSceneAccidentById(sceneId);
                            sceneName = sceneBaseInfoVo.getSceneName();
                        } else if (DictConstants.SCENE_GENERAL.equals(sceneType)) {
                            sublistScoreVo.setSceneType("泛化");
                            SceneBaseInfoVo sceneBaseInfoVo = simulationManualProjectMapper.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, ProjectReportVO projectReportVO) {

        // 1 查询指定项目的所有指标得分结果
        SimulationManualProjectParam query = new SimulationManualProjectParam();
        query.setId(projectId);
        query.setPackageId(scenePackageId);
        List<SublistScoreVo> pos = simulationManualProjectMapper.selectSubScore2(query);
        // 2 查询指定项目的所有任务得分结果
        ProjectTaskParam param = new ProjectTaskParam();
        param.setPId(projectId);
        List<ManualProjectTaskVo> taskList = simulationManualProjectTaskMapper.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());// 指标评价
                        sublistScoreVo.setTimeActual(task.getTimeActual());
                        sublistScoreVo.setTimeCorrection(task.getTimeCorrection());
                        String sceneType = task.getSceneType();
                        String sceneId = task.getSceneId();
                        String sceneName = "";
                        if (DictConstants.SCENE_NATURAL.equals(sceneType)) {
                            sublistScoreVo.setSceneType("自然驾驶");
                            SceneBaseInfoVo sceneBaseInfoVo = simulationManualProjectMapper.selectSceneNatural(sceneId);
                            sceneName = sceneBaseInfoVo.getNaturalName();
                        } else if (DictConstants.SCENE_STANDARD.equals(sceneType)) {
                            sublistScoreVo.setSceneType("标准法规");
                            SceneBaseInfoVo sceneBaseInfoVo = simulationManualProjectMapper.selectSceneStandardsRegulations(sceneId);
                            sceneName = sceneBaseInfoVo.getSceneName();
                        } else if (DictConstants.SCENE_ACCIDENT.equals(sceneType)) {
                            sublistScoreVo.setSceneType("交通事故");
                            SceneBaseInfoVo sceneBaseInfoVo = simulationManualProjectMapper.selectSceneAccidentById(sceneId);
                            sceneName = sceneBaseInfoVo.getSceneName();
                        } else if (DictConstants.SCENE_GENERAL.equals(sceneType)) {
                            sublistScoreVo.setSceneType("泛化");
                            SceneBaseInfoVo sceneBaseInfoVo = simulationManualProjectMapper.selectSceneGeneralDataById(sceneId);
                            sceneName = sceneBaseInfoVo.getSceneName();
                        } else if (DictConstants.SCENE_REFERENCE_LIB.equals(sceneType)) {
                            sublistScoreVo.setSceneType("基准场景库");
                            SceneBaseInfoVo sceneBaseInfoVo = simulationManualProjectMapper.selectSceneReferenceLibDataById(sceneId);
                            sceneName = sceneBaseInfoVo.getSceneName();
                        }
                        sublistScoreVo.setReturnSceneId(sceneName); // 显示场景名称
                        lastSubList.add(sublistScoreVo);
                    }
            }
        }
        int size = 0;
        int attributeNum = 7;
        // 所有末级指标的列表
        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 + "--"
                        + ProjectConstants.SEPARATOR + "--"
                        + ProjectConstants.SEPARATOR + "--";
            } else {
                // 最后两个字段暂时不需要，用 -- 替代了
                String timeActual = "0";
                String timeCorrection = "0";

                if (StringUtil.isNotEmpty(sp.getTimeActual())) {
                    timeActual = sp.getTimeActual();
                }
                if (StringUtil.isNotEmpty(sp.getTimeCorrection())) {
                    timeCorrection = sp.getTimeCorrection();
                }

                sublistName += ProjectConstants.SEPARATOR + sp.getReturnSceneId()
                        + ProjectConstants.SEPARATOR + sp.getSceneType()
                        + ProjectConstants.SEPARATOR + sceneScore
                        + ProjectConstants.SEPARATOR + targetEvaluate
                        + ProjectConstants.SEPARATOR + sp.getScoreExplain()
                        + ProjectConstants.SEPARATOR + timeActual
                        + ProjectConstants.SEPARATOR + timeCorrection;
            }
            // 将字符穿序列分割
            List<String> strings = CollectionUtil.createArrayList(sublistName.split(ProjectConstants.SEPARATOR));
            if (size < strings.size()) {
                size = strings.size();
            }
            result.add(strings);
            runStateList.add(sp.getRunResult());
        }
        List<SceneScListVo> objects = new ArrayList<>();
        // 结果补全
        int r = 0;
        log.info("结果为：" + result);
        for (List<String> list : result) {
            int sublistStartIndex = 0; // 指标字段开始
            int sublistStopIndex = list.size() - 1 - attributeNum + 1;    // 指标字段末尾
            SceneScListVo sceneScListVo = new SceneScListVo();
            // 填充指标
            for (int i = sublistStartIndex; i < sublistStopIndex; i++) {
                if (0 == i) {
                    String s0 = list.get(i);
                    if (StringUtil.isNotEmpty(s0)) {
                        sceneScListVo.setEachMaxIndex(String.valueOf(i + 1));
                    }
                    sceneScListVo.setSublistName1(s0);
                } else if (1 == i) {
                    String s1 = list.get(i);
                    if (StringUtil.isNotEmpty(s1)) {
                        sceneScListVo.setEachMaxIndex(String.valueOf(i + 1));
                    }
                    sceneScListVo.setSublistName2(list.get(i));
                } else if (2 == i) {
                    String s2 = list.get(i);
                    if (StringUtil.isNotEmpty(s2)) {
                        sceneScListVo.setEachMaxIndex(String.valueOf(i + 1));
                    }

                    sceneScListVo.setSublistName3(list.get(i));
                } else if (3 == i) {
                    String s3 = list.get(i);
                    if (StringUtil.isNotEmpty(s3)) {
                        sceneScListVo.setEachMaxIndex(String.valueOf(i + 1));
                    }
                    sceneScListVo.setSublistName4(list.get(i));
                } else if (4 == i) {
                    String s4 = list.get(i);
                    if (StringUtil.isNotEmpty(s4)) {
                        sceneScListVo.setEachMaxIndex(String.valueOf(i + 1));
                    }
                    sceneScListVo.setSublistName5(list.get(i));
                } else if (5 == i) {
                    String s5 = list.get(i);
                    if (StringUtil.isNotEmpty(s5)) {
                        sceneScListVo.setEachMaxIndex(String.valueOf(i + 1));
                    }
                    sceneScListVo.setSublistName6(list.get(i));
                }
            }
            sceneScListVo.setSceneId(list.get(sublistStopIndex));
            sceneScListVo.setSceneIdType(list.get(sublistStopIndex + 1));
            sceneScListVo.setSceneScore(list.get(sublistStopIndex + 2));
            sceneScListVo.setTargetEvaluate(list.get(sublistStopIndex + 3));
            sceneScListVo.setScoreExplain(list.get(sublistStopIndex + 4));
            sceneScListVo.setTimeActual(list.get(sublistStopIndex + 5));
            sceneScListVo.setTimeCorrection(list.get(sublistStopIndex + 6));
            sceneScListVo.setRunState(runStateList.get(r));
            objects.add(sceneScListVo);
            r++;
        }
        List<Map<Object, Object>> headerList = new ArrayList<>();
        int maxIndex = size - attributeNum;
        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 Map<String, Object> selectScenePackageSubListAndSetScore(String scenePackageId, String projectId) {

        // 查询场景包所有数据
        SimulationManualProjectParam query = new SimulationManualProjectParam();
        query.setId(projectId);
        query.setPackageId(scenePackageId);
        List<SublistScoreVo> sublistScoreVoList = simulationManualProjectMapper.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);
                 *
                 * }
                 */
            }

        } 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);
                 * }
                 */

            }
        }

    }

    /**
     * @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);
        }

    }

    /*
     */

    /**
     * 查询所有指标和得分
     *
     * @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);
        }

        if (!isEmpty(FhSceneScoreVos)) {
            sceneScoreVos.addAll(FhSceneScoreVos);
        }
        vo.setSceneScoreList(sceneScoreVos);
    }

    private void setLastTargetScore(ScenePackageSubListVO vo, String pId) {
        SimulationMptLastTargetScorePO projectPO = new SimulationMptLastTargetScorePO();
        projectPO.setPId(pId);
        projectPO.setTarget(vo.getSublistId());
        SimulationMptLastTargetScorePO po = simulationMptLastTargetScoreMapper.selectLastTargetScore(projectPO);
        if (po != null) {
            vo.setNotStandardSceneNum(po.getNotStandardSceneNum());
            vo.setScore(po.getScore());
            vo.setScoreExplain(po.getScoreExplain());
        }

    }

    private void setFirstTargetScore(ScenePackageSubListVO vo, String pId) {
        SimulationMptFirstTargetScorePO projectPO = new SimulationMptFirstTargetScorePO();
        projectPO.setPId(pId);
        projectPO.setTarget(vo.getSublistId());
        SimulationMptFirstTargetScorePO po = simulationMptFirstTargetScoreMapper.selectFirstTargetScore(projectPO);
        if (po != null) {
            vo.setScore(po.getScore());
        }

    }

    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 = simulationManualProjectTaskMapper.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 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 = simulationManualProjectMapper.selectSubSceneByPid(sublistId);
            if (!isEmpty(parentVoList)) {
                selectScoreNum(resultVo, parentVoList, false, pId, null);
            } else {
                // 当前指标为最后一级指标，获取当前指标，统计得分场景数
                setScoreNum(sublistId, pId, resultVo);
            }

        } else {

            // 获取子节点集合
            for (ScenePackageSubListVO pvo : parentVoList) {

                List<ScenePackageSubListVO> cvoList = simulationManualProjectMapper.selectSubSceneByPid(pvo.getSublistId());
                if (!isEmpty(cvoList)) {
                    // 存入父节点集合中
                    pvo.setChildScenePackageSubListVOList(cvoList);
                    // 继续查找下一节点
                    selectScoreNum(resultVo, cvoList, false, pId, null);
                } else {
                    // 没有子节点；获取最后一级的得分场景数量
                    setScoreNum(pvo.getSublistId(), pId, resultVo);

                }

            }
        }

        return resultVo;
    }

    private void setScoreNum(String sublistId, String pId, SceneScoreVo resultVo) {
        SimulationMptSceneScorePO po = new SimulationMptSceneScorePO();
        po.setPId(pId);
        po.setLastTargerId(sublistId);
        SceneScoreVo sceneScoreVo = simulationManualProjectTaskMapper.selectSceneScoreNumQuery(po);
        resultVo.setNum(resultVo.getNum() + sceneScoreVo.getNum());
    }

    /**
     * 计算评测等级
     *
     * @return
     */
    private String getEvaluationLevel(SimulationManualProjectPO po) {
        /*
         * 汇总测试得分(计算评级)计算方法：（每一项一级指标的测试得分*测试权重）累加
         */
        List<ScenePackageSubListVO> scenePackageSubListVOS = simulationManualProjectMapper.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;
        }

        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 = simulationManualProjectTaskMapper.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() {
        // 10：未执行，20：执行中，30：执行完成，40：已中止
        List<Map<String, Object>> list = simulationManualProjectMapper.selectRunProjectByState(AuthUtil.getCurrentUserId());
        if (CollectionUtil.isNotEmpty(list)) {
            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 = simulationManualProjectMapper.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() + "在");
            int totalSceneNum = vo.getSceneScoreLi().size();
            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);
            }

            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);
            List<SceneScListVo> sceneScoreLi = vo.getSceneScoreLi();

            if ("1".equals(param.getProjectType())) {
                // 场景评价
                List<String> sceneIds = sceneScoreLi.stream().map(SceneScListVo::getSceneId).collect(Collectors.toList());
                // 查询复杂度和危险度
                List<SceneComplexityPO> sceneComplexityPOS = sceneComplexityMapper.selectSceneComplexityEvaluationForExport(param.getProjectId(), sceneIds);
                sceneComplexityPOS.forEach(sceneComplexityPO -> sceneComplexityPO.setComplexityLevel(SceneEvaluationEnum.matchLevelEnumByLevelValue(sceneComplexityPO.getComplexityLevel())));
                List<SceneRiskPO> sceneRiskPOS = sceneRiskMapper.selectSceneRiskEvaluationForExport(param.getProjectId(), sceneIds);
                sceneRiskPOS.forEach(sceneRiskPO -> sceneRiskPO.setRiskLevel(SceneEvaluationEnum.matchLevelEnumByLevelValue(sceneRiskPO.getRiskLevel())));
                if (CollectionUtil.isNotEmpty(sceneComplexityPOS) || CollectionUtil.isNotEmpty(sceneRiskPOS)) {
                    addElement(document, "场景评价", null, bf3, 15, false, 30, true);
                    addElement(document, "       场景测试包共包含" + totalSceneNum + "个场景.", null, bf3, 15, false, 30, false);
                    createBarAndPieImg(document, sceneComplexityPOS, sceneRiskPOS);
                }
            }

            // ------- 4.详细得分说明 -------

            /*
             * //新的一页，横向显示
             * document.setPageSize(PageSize.A4.rotate());
             * document.newPage();
             */
            // lineFeed(document, 2, 2);
            List<Map> scoreLiTitle = vo.getSceneScoreLiTitle();
            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);
            }

            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();
            }
        }

    }

    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 void createBarAndPieImg(Document document, List<SceneComplexityPO> sceneComplexityPOS, List<SceneRiskPO> sceneRiskPOS) {
        try {
            // 饼图
            DefaultPieDataset complexityDataSet = new DefaultPieDataset();
            DefaultCategoryDataset complexityData = getBarDataSet();
            DefaultCategoryDataset riskData = getBarDataSet();
            if (CollectionUtil.isNotEmpty(sceneComplexityPOS)) {
                sceneComplexityPOS.forEach(sceneComplexityPO -> {
                    if (complexityDataSet.getValue(sceneComplexityPO.getComplexityLevel()) == null) {
                        complexityDataSet.setValue(sceneComplexityPO.getComplexityLevel(), 1);
                    } else {
                        int num = complexityDataSet.getValue(sceneComplexityPO.getComplexityLevel()).intValue();
                        complexityDataSet.setValue(sceneComplexityPO.getComplexityLevel(), ++num);
                    }
                    checkAndSetDataSetValue(complexityData, sceneComplexityPO.getComplexity());

                });
            }
            ByteArrayOutputStream pieBos = new ByteArrayOutputStream();
            ChartUtils.writeChartAsJPEG(pieBos, ChartUtil.pieChart("复杂度等级分布图", complexityDataSet), 300, 188);
            Image pieImage = Image.getInstance(pieBos.toByteArray());
            pieImage.setAlignment(Element.ALIGN_CENTER);
            pieBos.close();

            // 饼图
            DefaultPieDataset riskDataSet = new DefaultPieDataset();
            if (CollectionUtil.isNotEmpty(sceneRiskPOS)) {
                sceneRiskPOS.forEach(sceneRiskPO -> {
                    if (riskDataSet.getValue(sceneRiskPO.getRiskLevel()) == null) {
                        riskDataSet.setValue(sceneRiskPO.getRiskLevel(), 1);
                    } else {
                        int num = riskDataSet.getValue(sceneRiskPO.getRiskLevel()).intValue();
                        riskDataSet.setValue(sceneRiskPO.getRiskLevel(), ++num);
                    }
                    checkAndSetDataSetValue(riskData, sceneRiskPO.getRisk());
                });
            }
            ByteArrayOutputStream riskBos = new ByteArrayOutputStream();
            ChartUtils.writeChartAsJPEG(riskBos, ChartUtil.pieChart("危险度等级分布图", riskDataSet), 300, 188);
            Image riskLevelImage = Image.getInstance(riskBos.toByteArray());
            riskLevelImage.setAlignment(Element.ALIGN_CENTER);
            riskBos.close();
            if (CollectionUtil.isNotEmpty(sceneComplexityPOS) && CollectionUtil.isNotEmpty(sceneRiskPOS)) {
                float[] floats = new float[2];
                Arrays.fill(floats, 60);
                PdfPTable table = new PdfPTable(floats);
                table.setTotalWidth(600);
                table.setLockedWidth(true);
                table.setHorizontalAlignment(Element.ALIGN_CENTER);
                table.getDefaultCell().setBorder(1);
                PdfPCell complexityCell = new PdfPCell(pieImage);
                pieImage.scaleAbsolute(300, 188);
                complexityCell.setHorizontalAlignment(Element.ALIGN_CENTER);
                complexityCell.setBorder(com.itextpdf.text.Rectangle.NO_BORDER);
                table.addCell(complexityCell);

                PdfPCell riskCell = new PdfPCell(riskLevelImage);
                riskLevelImage.scaleAbsolute(300, 188);
                riskCell.setHorizontalAlignment(Element.ALIGN_CENTER);
                riskCell.setBorder(com.itextpdf.text.Rectangle.NO_BORDER);
                table.addCell(riskCell);
                document.add(table);
                BaseFont font = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
                Paragraph elements = new Paragraph(40, " ", new com.itextpdf.text.Font(font, 14));
                document.add(elements);
            } else if (CollectionUtil.isNotEmpty(sceneComplexityPOS)) {
                document.add(pieImage);
            } else if (CollectionUtil.isNotEmpty(sceneRiskPOS)) {
                document.add(riskLevelImage);
            }
            if (CollectionUtil.isNotEmpty(sceneComplexityPOS)) {
                ByteArrayOutputStream pieBos2 = new ByteArrayOutputStream();
                ChartUtils.writeChartAsJPEG(pieBos2, ChartUtil.barChart("复杂度分布图", null, "复杂度", complexityData), 620, 200);
                Image pieImage3 = Image.getInstance(pieBos2.toByteArray());
                pieImage3.setAlignment(Element.ALIGN_CENTER);
                document.add(pieImage3);
            }
            if (CollectionUtil.isNotEmpty(sceneRiskPOS)) {
                ByteArrayOutputStream pieBos3 = new ByteArrayOutputStream();
                ChartUtils.writeChartAsJPEG(pieBos3, ChartUtil.barChart("危险度分布图", null, "危险度", riskData), 620, 200);
                Image pieImage4 = Image.getInstance(pieBos3.toByteArray());
                pieImage4.setAlignment(Element.ALIGN_CENTER);
                document.add(pieImage4);
            }
        } catch (Exception e) {
            log.error("创建饼图和柱状图失败. ", e);
        }
    }

    private DefaultCategoryDataset getBarDataSet() {
        DefaultCategoryDataset dataset = new DefaultCategoryDataset();
        dataset.addValue(0, "场景名称", "[0,10]");
        dataset.addValue(0, "场景名称", "(10,20]");
        dataset.addValue(0, "场景名称", "(20,30]");
        dataset.addValue(0, "场景名称", "(30,40]");
        dataset.addValue(0, "场景名称", "(40,50]");
        dataset.addValue(0, "场景名称", "(50,60]");
        dataset.addValue(0, "场景名称", "(60,70]");
        dataset.addValue(0, "场景名称", "(70,80]");
        dataset.addValue(0, "场景名称", "(80,90]");
        dataset.addValue(0, "场景名称", "(90,100]");
        return dataset;
    }

    private void checkAndSetDataSetValue(DefaultCategoryDataset dataset, String value) {
        int valInt = Integer.parseInt(value);
        if (valInt >= 0 && valInt <= 10) {
            int num = dataset.getValue("场景名称", "[0,10]").intValue();
            dataset.setValue(++num, "场景名称", "[0,10]");
        } else if (valInt > 10 && valInt <= 20) {
            int num = dataset.getValue("场景名称", "(10,20]").intValue();
            dataset.setValue(++num, "场景名称", "(10,20]");
        } else if (valInt > 20 && valInt <= 30) {
            int num = dataset.getValue("场景名称", "(20,30]").intValue();
            dataset.setValue(++num, "场景名称", "(20,30]");
        } else if (valInt > 30 && valInt <= 40) {
            int num = dataset.getValue("场景名称", "(30,40]").intValue();
            dataset.setValue(++num, "场景名称", "(30,40]");
        } else if (valInt > 40 && valInt <= 50) {
            int num = dataset.getValue("场景名称", "(40,50]").intValue();
            dataset.setValue(++num, "场景名称", "(40,50]");
        } else if (valInt > 50 && valInt <= 60) {
            int num = dataset.getValue("场景名称", "(50,60]").intValue();
            dataset.setValue(++num, "场景名称", "(50,60]");
        } else if (valInt > 60 && valInt <= 70) {
            int num = dataset.getValue("场景名称", "(60,70]").intValue();
            dataset.setValue(++num, "场景名称", "(60,70]");
        } else if (valInt > 70 && valInt <= 80) {
            int num = dataset.getValue("场景名称", "(70,80]").intValue();
            dataset.setValue(++num, "场景名称", "(70,80]");
        } else if (valInt > 80 && valInt <= 90) {
            int num = dataset.getValue("场景名称", "(80,90]").intValue();
            dataset.setValue(++num, "场景名称", "(80,90]");
        } else if (valInt > 90 && valInt <= 100) {
            int num = dataset.getValue("场景名称", "(90,100]").intValue();
            dataset.setValue(++num, "场景名称", "(90,100]");
        }

    }

    /**
     * 获取所有要合并的下标、每个下标索要合并的行数、要跳过创建表格的下标
     */
    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);
                }

            }

        }

        for (String k : map.keySet()) {
            CombineCoordVo combineCoordVo = map.get(k);
            combineCoordMap.put(combineCoordVo.getCoord(), combineCoordVo.getRepetitionNum());
        }

        resultMap.put("combineCoordList", combineCoordMap);
        resultMap.put("skipCoordList", skipCoordList);

        return resultMap;

    }

    /**
     * 获取所有要合并的下标、每个下标索要合并的行数、要跳过创建表格的下标
     */
    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);
                }

            }

        }

        /*
         * List<CombineCoordVo> combineCoordVoList = new ArrayList<>();
         *
         * for(String k : map.keySet()){
         * combineCoordVoList.add(map.get(k));
         * }
         */

        for (String k : map.keySet()) {
            CombineCoordVo combineCoordVo = map.get(k);
            combineCoordMap.put(combineCoordVo.getCoord(), combineCoordVo.getRepetitionNum());
        }

        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);

        }
    }

    @Override
    public String selectLastProjectIdByAlgorithmId(String algorithmId) {
        return simulationManualProjectMapper.selectLastProjectIdByAlgorithmId(algorithmId);
    }

    @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("项目 " + 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<Object> 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, "地址不能为空");
        }

        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");
                }

            }

            // 里程
            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);
            }

            simulationManualProjectTaskMapper.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();

            }
        }

        return new ResponseBodyVO(ResponseBodyVO.Response.SUCCESS);

    }

    @Override
    public void exportProjectTaskFileById(SimulationManualProjectParam param) {
        String id = param.getId();

        // 获取任务包信息
        ProjectTaskParam projectTaskParam = new ProjectTaskParam();
        projectTaskParam.setPId(id);
        List<ManualProjectTaskVo> manualProjectTaskVos = simulationManualProjectTaskMapper.selectProjectTaskByProjectId(projectTaskParam);
        if (isEmpty(manualProjectTaskVos)) {
            throw new RuntimeException("没有获取到任务信息。");
        }

        // 压缩包根路径
        SimulationManualProjectParam sp = new SimulationManualProjectParam();
        sp.setId(id);
        SimulationManualProjectPO spo = simulationManualProjectMapper.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 = simulationManualProjectMapper.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 void exportProjectReportAndTaskFileById(SimulationManualProjectParam param) {
        // 生成本地pdf
        param.setIsCreateLocalPdfFile(true);
        param.setLocalPdfFilePath(StringUtil.getRandomUUID() + ".pdf");
        param.setIsPagePdf(true);
        // 下载报告和任务包
        exportProjectReport(param);
        exportProjectTaskFileById(param);
    }

    @Override
    public ResponseBodyVO addOrUpdateAutomaticProject(SimulationManualProjectParam param) {

        if (isEmpty(param.getProjectName())) {
            return new ResponseBodyVO(ResponseBodyVO.Response.CLIENT_FAILURE, "工作名称不能为空");
        }
        // 校验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, "运行周期格式不对");
        }

        // 创建自动运行任务时自动运行状态默认为关闭（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
            createProjectIdAndAdd(po);
            return new ResponseBodyVO(ResponseBodyVO.Response.SUCCESS, ResponseBodyVO.Response.SUCCESS.getMessage(), po.getId());
        } 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, "修改失败");
        }

    }

    @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, "自动任务开启状态不支持删除");
            }
        }

        int i = simulationAutomaticProjectMapper.deleteProject(idArr);
        if (i > 0) {
            return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS);
        }

        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); // 查询父项目信息
        final int parallelism = Integer.parseInt(po.getParallelism());
        if ("0".equals(param.getAutomaticRunState())) { // 启动
            // 1 判断算法是否已经被删除
            projectUtil.checkProject(po.getAlgorithm(), po.getVehicle(), po.getScene(), parallelism);
            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);
    }

    private void runProject(AlgorithmParameter algorithmParam, SimulationManualProjectParam simulationManualProjectParam, SimulationAutomaticProjectPO simulationAutomaticProjectPo) {

        // 更新算法版本
        simulationAutomaticProjectMapper.updateAlgorithmGitVersion(algorithmParam);

        // 添加一条子工作信息并推送消息到kafka ，执行项目
        createAutomaticSubProject(simulationManualProjectParam);

        // 推送定时请求，启动运行周期
        projectTaskStart(simulationAutomaticProjectPo);

    }

    @Override
    public ResponseBodyVO<PageInfo<SimulationManualProjectVO>> selectAutomaticProject(SimulationManualProjectParam param) {

        // 1 获取当前用户id
        param.setCreateUserId(AuthUtil.getCurrentUserId());

        // 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);
        }

        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);
        }

        return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS, pageInfo);

    }

    @Override
    @SneakyThrows
    public ResponseBodyVO<String> createAutomaticSubProject(SimulationManualProjectParam param) {
        if (StringUtil.isEmpty(param.getId())) {
            throw new RuntimeException("id 不能为空。");
        }
        SimulationAutomaticProjectPO po = simulationAutomaticProjectMapper.selectById(param.getId());
        // 校验项目信息
        int parallelism = Integer.parseInt(po.getParallelism());
        projectUtil.checkProject(po.getAlgorithm(), po.getVehicle(), po.getScene(), parallelism);
        // 组装数据
        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 = selectProjectDetailsByIdBeforeRunning(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, "数据不支持删除");
            }
        }

        int i = simulationAutomaticSubProjectMapper.deleteProject(idArr);
        if (i > 0) {
            return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS);

        }
        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);

        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);

    }

    @Override
    public ResponseBodyVO<PageInfo<SimulationManualProjectVO>> selectSubProjectList(SimulationManualProjectParam param) {

        String id = param.getParentId();

        if (isEmpty(id)) {
            return new ResponseBodyVO<>(ResponseBodyVO.Response.CLIENT_FAILURE, "id不能为空");
        }

        setPage(param.getCurrentPage() == null ? 1 : param.getCurrentPage(), param.getPageSize() == null ? 10 : param.getPageSize());

        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));
    }

    @Override
    public ResponseBodyVO<SimulationManualProjectSingleVo> selectAutomaticProjectById(SimulationManualProjectParam param) {

        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(","));
        }

        return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS, vo);

    }

    @SneakyThrows
    @Override
    public ResponseBodyVO<String> updateAutoProjectNowRunState(SimulationManualProjectParam param) {

        if (isEmpty(param.getId()) || isEmpty(param.getNowRunState())) {
            return new ResponseBodyVO<>(ResponseBodyVO.Response.CLIENT_FAILURE, "id或状态值不能为空");
        }

        SimulationAutomaticSubProjectPO po = simulationAutomaticSubProjectMapper.selectById(param);

        if (po == null) {
            return new ResponseBodyVO<>(ResponseBodyVO.Response.SERVER_FAILURE, "数据没有找到");
        }

        // 自动运行子项目只能终止
        if (ProjectRunStateEnum.DISCONTINUE.getCode().equals(param.getNowRunState())) {
            int i = simulationAutomaticSubProjectMapper.updateNowRunState(param);
            if (i > 0) {
                // 项目终止，推送到kafka
                autoProjectStopToKafka(po);
                return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS);
            }

        }

        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()), ','));
        }
        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;
    }

    /**
     * 换行
     *
     * @param lineNum  换行数量
     * @param document
     */
    private void lineFeed(int lineNum, Document document) throws DocumentException {
        for (int i = 0; i < lineNum; i++) {
            document.add(Chunk.NEWLINE);
        }
    }

    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);
        }
    }

    /**
     * 水平垂直居中添加表头
     */
    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);
            }
        }
    }

    /**
     * 水平垂直居中添加表头
     */
    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);
            }
        }
    }

    /**
     * 添加数据
     *
     * @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 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);
        }
    }

    /**
     * 添加数据
     *
     * @param table
     * @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 = simulationManualProjectMapper.selectAlgorithmByQuery(po);
            if (po1 == null) {
                simulationManualProjectMapper.insertOtherAlgorithm(po);
            } else {
                if (!po1.getAlgorithmName().equals(param.getAlgorithmName())) {
                    simulationManualProjectMapper.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 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);
        }

        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 = simulationManualProjectMapper.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 = simulationManualProjectMapper.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 = 0;
            int size = 99999;// 全部
            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 = simulationManualProjectMapper.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 = simulationManualProjectMapper.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 = simulationManualProjectMapper.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 = simulationManualProjectMapper.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);

            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 = simulationManualProjectMapper.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 = simulationManualProjectMapper.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);
    }

}
