package com.qmth.teachcloud.report.business.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.qmth.teachcloud.common.contant.SpringContextHolder;
import com.qmth.teachcloud.common.contant.SystemConstant;
import com.qmth.teachcloud.common.entity.SysOrg;
import com.qmth.teachcloud.common.enums.AssignEnum;
import com.qmth.teachcloud.common.enums.ExceptionResultEnum;
import com.qmth.teachcloud.common.service.BasicCourseService;
import com.qmth.teachcloud.common.service.SysOrgService;
import com.qmth.teachcloud.common.service.SysUserService;
import com.qmth.teachcloud.report.business.bean.dto.AnswerDetailBean;
import com.qmth.teachcloud.report.business.bean.dto.query.BasicAnswerDto;
import com.qmth.teachcloud.report.business.bean.dto.query.BasicExamRecordDto;
import com.qmth.teachcloud.report.business.bean.dto.query.ValidAnswerDetailDto;
import com.qmth.teachcloud.report.business.entity.*;
import com.qmth.teachcloud.report.business.enums.*;
import com.qmth.teachcloud.report.business.service.*;
import com.qmth.teachcloud.report.business.utils.AnalyzeScopeUtil;
import com.qmth.teachcloud.report.business.utils.ConversionUtils;
import com.qmth.teachcloud.report.business.utils.MathUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description: 学生看板数据计算
 * @Author: CaoZixuan
 * @Date: 2021-06-06
 */
@Service
public class AnalyzeForReportServiceImpl implements AnalyzeForReportService {
    @Resource
    private TAExamCourseRecordService taExamCourseRecordService;
    @Resource
    private TBExamCourseService tbExamCourseService;
    @Resource
    private TBCommonLevelConfigService tbCommonLevelConfigService;
    @Resource
    private TBCommonRankLevelConfigService tbCommonRankLevelConfigService;
    @Resource
    private BasicCourseService basicCourseService;
    @Resource
    private TAExamCourseCollegeInspectService taExamCourseCollegeInspectService;
    @Resource
    private TBPaperService tbPaperService;
    @Resource
    private TBExamStudentService tbExamStudentService;
    @Resource
    private SysOrgService sysOrgService;
    @Resource
    private TBExamService tbExamService;
    @Resource
    private TAExamCourseService taExamCourseService;
    @Resource
    private TAExamCourseClazzService taExamCourseClazzService;
    @Resource
    private TBDimensionService tbDimensionService;
    @Resource
    private TAExamCourseDioService taExamCourseDioService;
    @Resource
    private TAExamCourseRecordDioService taExamCourseRecordDioService;
    @Resource
    private TAExamCourseRecordModService taExamCourseRecordModService;
    @Resource
    private TBPaperStructService tbPaperStructService;
    @Resource
    private TBAnswerService tbAnswerService;
    @Resource
    private TBModuleConfigService tbModuleConfigService;
    @Resource
    private TBModuleProficiencyService tbModuleProficiencyService;
    @Resource
    private TAExamCourseCollegeInspectDioService taExamCourseCollegeInspectDioService;
    @Resource
    private TAPaperStructService taPaperStructService;
    @Resource
    private TAExamTotalService taExamTotalService;
    @Resource
    private TAExamCourseCollegeTeacherService taExamCourseCollegeTeacherService;
    @Resource
    private TAExamCourseTeacherService taExamCourseTeacherService;
    @Resource
    private SysUserService sysUserService;
    @Resource
    private TAExamCourseDifficultService taExamCourseDifficultService;
    @Resource
    private TAExamCourseTeacherDifficultService taExamCourseTeacherDifficultService;
    @Resource
    private TAExamCourseTeacherDioService taExamCourseTeacherDioService;
    @Resource
    private TBExamRecordService tbExamRecordService;
    @Resource
    private TAExamCourseTeacherCollegeDioService taExamCourseTeacherCollegeDioService;
    @Resource
    private TAExamCourseTeacherCollegeDifficultService taExamCourseTeacherCollegeDifficultService;
    @Resource
    private TAExamCourseCollegePaperStructService taExamCourseCollegePaperStructService;
    @Resource
    private TAExamCourseTeacherPaperStructService taExamCourseTeacherPaperStructService;
    @Resource
    private TAExamCourseTeacherCollegePaperStructService taExamCourseTeacherCollegePaperStructService;


    @Transactional(rollbackFor = Exception.class)
    @Override
    public String buildAnalyzeExamCourse(Long examId, String courseCode) {
        Long schoolId = tbExamService.findSchoolIdByExamId(examId);
        List<String> effectiveCourseCodeList = tbExamCourseService.findEffectiveByExamId(examId, courseCode);
        // 考试下考生作答数据源
        List<TAExamCourseRecord> dataSource = taExamCourseRecordService.list(new QueryWrapper<TAExamCourseRecord>().lambda()
                .eq(TAExamCourseRecord::getExamId, examId));
        List<TAExamCourse> taExamCourseList = new ArrayList<>();
        // 有效的课程
        for (String effectiveCourseCode : effectiveCourseCodeList) {
            // 原数据删除
            taExamCourseService.remove(new QueryWrapper<TAExamCourse>().lambda()
                    .eq(TAExamCourse::getExamId, examId)
                    .eq(TAExamCourse::getCourseCode, effectiveCourseCode));

            List<TBPaper> tbPaperList = tbPaperService.list(new QueryWrapper<TBPaper>().lambda()
                    .eq(TBPaper::getExamId, examId).eq(TBPaper::getCourseCode, effectiveCourseCode));
            if (tbPaperList.size() < 1) {
                throw ExceptionResultEnum.ERROR.exception("未找到试卷基础信息");
            }
            TBPaper tbPaper = tbPaperList.get(0);
            // 通过分
            BigDecimal passScore = tbPaper.getPassScore();
            // 满分
            BigDecimal totalScore = tbPaper.getTotalScore();
            // 赋分系数
            String coefficient;
            BigDecimal paperCoefficient = tbPaper.getCoefficient();
            paperCoefficient = paperCoefficient.stripTrailingZeros();
            AssignEnum assignEnum = tbPaper.getScoreType();
            if (AssignEnum.SPECIAL_ASSIGN_SCORE.equals(assignEnum)) {
                coefficient = SystemConstant.DEFAULT_SIGN;
            } else {
                coefficient = paperCoefficient.toPlainString();
            }

            /*
                该课程总体学生成绩分析
             */
            // 该课程考生数据
            List<TAExamCourseRecord> totalDatasource = dataSource.stream()
                    .filter(e -> effectiveCourseCode.equals(e.getCourseCode())).collect(Collectors.toList());
            int totalCount = totalDatasource.size();
            long realityCount = totalDatasource.stream().filter(e -> !e.getAbsent()).count();
            long absentCount = totalDatasource.stream().filter(TAExamCourseRecord::getAbsent).count();
            if (totalCount != realityCount + absentCount) {
                throw ExceptionResultEnum.ERROR.exception("考试人数数据异常");
            }
            // 赋分数据集合
            // -------------------赋分------------------------
            List<Double> totalScoreList = totalDatasource.stream().filter(e -> !e.getAbsent()).map(e -> e.getAssignedScore().doubleValue()).collect(Collectors.toList());
            DoubleSummaryStatistics totalStatistics = totalScoreList.stream().collect(Collectors.summarizingDouble(e -> e));
            double avgScore = totalStatistics.getAverage();
            long passCount = totalScoreList.stream().filter(e -> e >= passScore.doubleValue()).count();
            BigDecimal passRate = BigDecimal.valueOf(passCount).divide(BigDecimal.valueOf(realityCount), 4, RoundingMode.HALF_UP);

            // -------------------卷面分------------------------
            List<Double> paperTotalScoreList = totalDatasource.stream().filter(e -> !e.getAbsent()).map(e -> e.getTotalScore().doubleValue()).collect(Collectors.toList());
            DoubleSummaryStatistics paperTotalStatistics = paperTotalScoreList.stream().collect(Collectors.summarizingDouble(e -> e));
            double paperAvgScore = paperTotalStatistics.getAverage();
            long paperPassCount = paperTotalScoreList.stream().filter(e -> e >= passScore.doubleValue()).count();
            BigDecimal paperPassRate = BigDecimal.valueOf(paperPassCount).divide(BigDecimal.valueOf(realityCount), 4, RoundingMode.HALF_UP);



            /*
                该课程往届生成绩分析
             */
            // 该课程往届数据
            List<TAExamCourseRecord> pastDatasource = totalDatasource.stream()
                    .filter(e -> !e.getStudentCurrent()).collect(Collectors.toList());
            int pastTotalCount = pastDatasource.size();
            long pastRealityCount = pastDatasource.stream().filter(e -> !e.getAbsent()).count();
            long pastAbsentCount = pastDatasource.stream().filter(TAExamCourseRecord::getAbsent).count();
            if (pastTotalCount != pastRealityCount + pastAbsentCount) {
                throw ExceptionResultEnum.ERROR.exception("考试往届生人数数据异常");
            }
            BigDecimal pastRealityRate = BigDecimal.valueOf(pastRealityCount).divide(BigDecimal.valueOf(realityCount), 4, RoundingMode.HALF_UP);

            /*
                该课程应届生成绩分析
             */
            // 该课程下应届数据
            List<TAExamCourseRecord> currentDatasource = totalDatasource.stream()
                    .filter(TAExamCourseRecord::getStudentCurrent).collect(Collectors.toList());
            // 人数统计
            int currentTotalCount = currentDatasource.size();
            long currentRealityCount = currentDatasource.stream().filter(e -> !e.getAbsent()).count();
            long currentAbsentCount = currentDatasource.stream().filter(TAExamCourseRecord::getAbsent).count();
            if (currentTotalCount != currentRealityCount + currentAbsentCount) {
                throw ExceptionResultEnum.ERROR.exception("考试应届生人数数据异常");
            }
            BigDecimal currentRealityRate = BigDecimal.valueOf(currentRealityCount).divide(BigDecimal.valueOf(realityCount), 4, RoundingMode.HALF_UP);

            // 通过率统计
            List<Double> currentScoreList = currentDatasource.stream().filter(e -> !e.getAbsent()).map(e -> e.getAssignedScore().doubleValue()).collect(Collectors.toList());
            DoubleSummaryStatistics currentStatistics = currentScoreList.stream().collect(Collectors.summarizingDouble(e -> e));
            long currentPassCount = currentScoreList.stream().filter(e -> e >= passScore.doubleValue()).count();
            BigDecimal currentPassRate = BigDecimal.valueOf(currentPassCount).divide(BigDecimal.valueOf(currentRealityCount), 4, RoundingMode.HALF_UP);

            // 描述统计
            double currentMinScore = currentStatistics.getMin();
            double currentMaxScore = currentStatistics.getMax();
            double currentAvgScore = currentStatistics.getAverage();

            // 计算众数
            String currentMode = MathUtil.calculateMode(currentScoreList);
            // 计算上四分位数
            double currentUpperQuartile = MathUtil.calculateQuantile(currentScoreList, QuantileEnum.UPPER_QUARTILE.getValue());
            // 计算中位数
            double currentMedian = MathUtil.calculateQuantile(currentScoreList, QuantileEnum.MEDIAN.getValue());
            // 计算下四分位数
            double currentLowerQuartile = MathUtil.calculateQuantile(currentScoreList, QuantileEnum.LOWER_QUARTILE.getValue());

            // 极端情况下分位数值处理
            if (currentUpperQuartile == 0) {
                currentUpperQuartile = currentMedian;
            }
            if (currentLowerQuartile == 0) {
                currentLowerQuartile = currentMedian;
            }
            // 计算标准差
            double currentStandardDeviation = MathUtil.calculateStandardDeviation(currentScoreList);

            BigDecimal scoreRate;
            double standardAvgScore = currentDatasource.stream().collect(Collectors.summarizingDouble(e -> e.getTotalScore().doubleValue())).getAverage();
            if (standardAvgScore != 0 && totalScore.compareTo(BigDecimal.ZERO) > 0) {
                scoreRate = BigDecimal.valueOf(standardAvgScore).divide(totalScore, 4, RoundingMode.HALF_UP);
            } else {
                scoreRate = BigDecimal.ZERO;
            }
            // 难度系数保留1位数
            scoreRate = scoreRate.setScale(1, RoundingMode.HALF_UP); // 难度系数保留1位有效数字
            String difficulty = this.handleLevel(examId, effectiveCourseCode, "难度等级", scoreRate.doubleValue());
            //--------------------------应届-卷面成绩-----------------------
            List<Double> paperCurrentScoreList = currentDatasource.stream().filter(e -> !e.getAbsent()).map(e -> e.getTotalScore().doubleValue()).collect(Collectors.toList());
            DoubleSummaryStatistics paperCurrentStatistics = paperCurrentScoreList.stream().collect(Collectors.summarizingDouble(e -> e));
            double paperCurrentAvgScore = paperCurrentStatistics.getAverage();
            long paperCurrentPassCount = paperCurrentScoreList.stream().filter(e -> e >= passScore.doubleValue()).count();
            BigDecimal paperCurrentPassRate = BigDecimal.valueOf(paperCurrentPassCount).divide(BigDecimal.valueOf(currentRealityCount), 4, RoundingMode.HALF_UP);

            /*
                学院信息
             */
            List<TBExamStudent> tbExamStudentList = tbExamStudentService.list(new QueryWrapper<TBExamStudent>().lambda()
                    .eq(TBExamStudent::getExamId, examId).eq(TBExamStudent::getCourseCode, effectiveCourseCode));

            List<Long> teachCollegeIdList = tbExamStudentList.stream().map(TBExamStudent::getTeachCollegeId).distinct().collect(Collectors.toList());
            List<Long> inspectCollegeIdList = tbExamStudentList.stream().map(TBExamStudent::getInspectCollegeId).distinct().collect(Collectors.toList());
            if (teachCollegeIdList.size() != 1) {
                throw ExceptionResultEnum.ERROR.exception("该课程有多个开课学院异常");
            }
            Long teachCollegeId = teachCollegeIdList.get(0);
            SysOrg tbSchoolCollege = sysOrgService.getById(teachCollegeId);
            String teachCollegeName;
            if (Objects.isNull(tbSchoolCollege)) {
                teachCollegeName = SystemConstant.DEFAULT_SIGN;
            } else {
                teachCollegeName = tbSchoolCollege.getName();
            }
            int inspectCollegeCount = inspectCollegeIdList.size();
            if (inspectCollegeIdList.size() == 0) {
                throw ExceptionResultEnum.ERROR.exception("没有考察学院");
            }
            List<SysOrg> sysOrgList = sysOrgService.listByIds(inspectCollegeIdList);
            String inspectCollegeNames = StringUtils.join(sysOrgList.stream().map(SysOrg::getName).collect(Collectors.toList()), '、');


            /*
                组装
             */
            TBExam tbExam = tbExamService.getById(examId);
            TAExamCourse taExamCourse = new TAExamCourse();
            taExamCourse.setId(SystemConstant.getDbUuid());
            taExamCourse.setExamId(examId);
            taExamCourse.setExamName(tbExam.getExamName());
            taExamCourse.setCourseCode(effectiveCourseCode);
            taExamCourse.setCourseName(basicCourseService.findByCourseCode(effectiveCourseCode,schoolId).getName());
            taExamCourse.setSchoolId(tbExam.getSchoolId());
            taExamCourse.setTeachCollegeId(teachCollegeId);
            taExamCourse.setTeachCollegeName(teachCollegeName);
            taExamCourse.setInspectCollegeCount(inspectCollegeCount);
            taExamCourse.setInspectCollegeNames(inspectCollegeNames);
            taExamCourse.setAvgScore(BigDecimal.valueOf(avgScore));
            taExamCourse.setPassCount((int) passCount);
            taExamCourse.setPassRate(passRate);
            taExamCourse.setCurrentPassCount((int) currentPassCount);
            taExamCourse.setCurrentPassRate(currentPassRate);
            taExamCourse.setTotalScore(totalScore);
            taExamCourse.setRealityCount((int) realityCount);
            taExamCourse.setAbsentCount((int) absentCount);
            taExamCourse.setTotalCount(totalCount);
            taExamCourse.setCurrentMinScore(BigDecimal.valueOf(currentMinScore));
            taExamCourse.setCurrentMaxScore(BigDecimal.valueOf(currentMaxScore));
            taExamCourse.setCurrentAvgScore(BigDecimal.valueOf(currentAvgScore));
            taExamCourse.setCurrentScoreRate(scoreRate);
            taExamCourse.setCurrentRealityCount((int) currentRealityCount);
            taExamCourse.setCurrentAbsentCount((int) currentAbsentCount);
            taExamCourse.setCurrentTotalCount(currentTotalCount);
            taExamCourse.setCurrentRealityRate(currentRealityRate);
            taExamCourse.setPastRealityCount((int) pastRealityCount);
            taExamCourse.setPastAbsentCount((int) pastAbsentCount);
            taExamCourse.setPastTotalCount(pastTotalCount);
            taExamCourse.setPastRealityRate(pastRealityRate);
            taExamCourse.setCurrentUpperQuartile(BigDecimal.valueOf(currentUpperQuartile));
            taExamCourse.setCurrentMedian(BigDecimal.valueOf(currentMedian));
            taExamCourse.setCurrentLowerQuartile(BigDecimal.valueOf(currentLowerQuartile));
            taExamCourse.setCurrentMode(currentMode);
            taExamCourse.setCurrentStandardDeviation(BigDecimal.valueOf(currentStandardDeviation));
            taExamCourse.setDifficulty(difficulty);
            taExamCourse.setPaperAvgScore(BigDecimal.valueOf(paperAvgScore));
            taExamCourse.setPaperPassRate(paperPassRate);
            taExamCourse.setPaperPassCount((int) paperPassCount);
            taExamCourse.setPaperCurrentAvgScore(BigDecimal.valueOf(paperCurrentAvgScore));
            taExamCourse.setPaperCurrentPassRate(paperCurrentPassRate);
            taExamCourse.setPaperCurrentPassCount((int) paperCurrentPassCount);
            taExamCourse.setCoefficient(coefficient);
            taExamCourseList.add(taExamCourse);
        }
        taExamCourseService.saveBatch(taExamCourseList);
        return " 't_a_exam_course' 表构建完毕 ";
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public String buildAnalyzeExamCourseRecord(Long examId, String courseCode) {
        // 获取本次考试所有考试记录数据源
        List<TAExamCourseRecord> taExamCourseRecordDatasource = taExamCourseRecordService.list(new QueryWrapper<TAExamCourseRecord>().lambda()
                .eq(TAExamCourseRecord::getExamId, examId)
                .eq(TAExamCourseRecord::getAbsent, false)
                .eq(TAExamCourseRecord::getStudentCurrent, true));

        List<String> effectiveCourseCodeList = tbExamCourseService.findEffectiveByExamId(examId, courseCode);

        for (String effectiveCourseCode : effectiveCourseCodeList) {
            List<TAExamCourse> taExamCourseList = taExamCourseService.list(new QueryWrapper<TAExamCourse>().lambda()
                    .eq(TAExamCourse::getExamId, examId)
                    .eq(TAExamCourse::getCourseCode, effectiveCourseCode));
            if (taExamCourseList.size() != 1) {
                throw ExceptionResultEnum.ERROR.exception("考试课程分析数据获取失败");
            }
            TAExamCourse taExamCourse = taExamCourseList.get(0);
            BigDecimal avgScore = taExamCourse.getAvgScore();
            BigDecimal standardDeviation = taExamCourse.getCurrentStandardDeviation();

            List<TAExamCourseRecord> dataSource = taExamCourseRecordDatasource.stream().filter(e -> effectiveCourseCode.equals(e.getCourseCode())).collect(Collectors.toList());
            for (TAExamCourseRecord taExamCourseRecord : dataSource) {
                BigDecimal totalScore = taExamCourseRecord.getTotalScore(); // 标准分
                long lowCount = dataSource.stream().filter(e -> e.getTotalScore().compareTo(totalScore) < 0).count(); // 低于我的人数
                long sameCount = dataSource.stream().filter(e -> e.getTotalScore().compareTo(totalScore) == 0).count(); // 和我相同的人数
                int totalCount = dataSource.size(); //总人数
                // 标准回归系数
                if (standardDeviation.compareTo(BigDecimal.ZERO) == 0) {
                    standardDeviation = BigDecimal.valueOf(0.001);
                }
                BigDecimal standardizedCoefficients = (taExamCourseRecord.getAssignedScore().subtract(avgScore)).divide(standardDeviation, 4, RoundingMode.HALF_UP);

                int percentGrade = this.handlePercentGrade(BigDecimal.valueOf(lowCount), BigDecimal.valueOf(sameCount), BigDecimal.valueOf(totalCount));
                taExamCourseRecord.setPercentGrade(percentGrade);

                String scoreLevel = this.handleLevel(examId, effectiveCourseCode, "百分等级", percentGrade);
                taExamCourseRecord.setScoreLevel(scoreLevel);
                taExamCourseRecord.setStandardizedCoefficients(standardizedCoefficients);
                this.buildColData(taExamCourseRecord, dataSource); // 总成绩在学院的排名、排名等级档位、超过学院百分比
            }
            taExamCourseRecordService.saveOrUpdateBatch(dataSource);
        }
        return " 't_a_exam_course_record' 表更新完成";
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public String buildAnalyzeExamCourseCollegeInspect(Long examId, String courseCode) {
        Long schoolId = tbExamService.findSchoolIdByExamId(examId);
        List<TAExamCourseRecord> recordDatasource = taExamCourseRecordService.list(new QueryWrapper<TAExamCourseRecord>().lambda()
                .eq(TAExamCourseRecord::getExamId, examId));
        // 可分析有效课程信息
        List<String> effectiveCourseCodeList = tbExamCourseService.findEffectiveByExamId(examId, courseCode);
        List<TAExamCourseCollegeInspect> inspectCollegeList = new ArrayList<>();

        for (String effectiveCourseCode : effectiveCourseCodeList) {
            // 删除原有数据
            taExamCourseCollegeInspectService.remove(new QueryWrapper<TAExamCourseCollegeInspect>().lambda()
                    .eq(TAExamCourseCollegeInspect::getExamId, examId).eq(TAExamCourseCollegeInspect::getCourseCode, effectiveCourseCode));

            // 本课程下所有应届考生考生记录
            List<TAExamCourseRecord> recordCourseCurrentDatasource = recordDatasource.stream()
                    .filter(e -> effectiveCourseCode.equals(e.getCourseCode()) && e.getStudentCurrent()).collect(Collectors.toList());

            List<Long> inspectCollegeIdList = recordCourseCurrentDatasource.stream().filter(e -> !e.getAbsent()).map(TAExamCourseRecord::getInspectCollegeId).distinct().collect(Collectors.toList());
            for (Long collegeId : inspectCollegeIdList) {
                List<TAExamCourseRecord> collegeEffectiveRecordDatasource = recordCourseCurrentDatasource.stream()
                        .filter(e -> collegeId.equals(e.getInspectCollegeId())).collect(Collectors.toList());
                // 课程-学院 总应届人数
                int totalCount = collegeEffectiveRecordDatasource.size();
                // 有效分析数据源
                List<TAExamCourseRecord> effectiveList = collegeEffectiveRecordDatasource.stream().filter(e -> !e.getAbsent()).collect(Collectors.toList());
                // 课程-学院 总应届实考人数
                int realityCount = effectiveList.size();
                // 课程-学院 总缺考应届人数
                int absentCount = totalCount - realityCount;

                List<Double> assignedScoreList = effectiveList.stream().map(e -> e.getAssignedScore().doubleValue()).collect(Collectors.toList());
                DoubleSummaryStatistics doubleSummaryStatistics = assignedScoreList.stream().collect(Collectors.summarizingDouble(e -> e));
                double minScore = doubleSummaryStatistics.getMin();
                double maxScore = doubleSummaryStatistics.getMax();
                double avgScore = doubleSummaryStatistics.getAverage();
                String mode = MathUtil.calculateMode(assignedScoreList);
                double upperQuartile = MathUtil.calculateQuantile(assignedScoreList, QuantileEnum.UPPER_QUARTILE.getValue());
                double median = MathUtil.calculateQuantile(assignedScoreList, QuantileEnum.MEDIAN.getValue());
                double lowerQuartile = MathUtil.calculateQuantile(assignedScoreList, QuantileEnum.LOWER_QUARTILE.getValue());

                if (effectiveList.size() == 0) {
                    minScore = 0;
                    maxScore = 0;
                    avgScore = 0;
                    mode = "";
                    upperQuartile = 0;
                    median = 0;
                    lowerQuartile = 0;
                }

                // 极端情况下分位数值处理
                if (upperQuartile == 0) {
                    upperQuartile = median;
                }
                if (lowerQuartile == 0) {
                    lowerQuartile = median;
                }
                double standardDeviation = MathUtil.calculateStandardDeviation(assignedScoreList);
                // 相对位置
                double relativePosition = effectiveList.stream().collect(Collectors.summarizingDouble(e -> e.getStandardizedCoefficients().doubleValue())).getAverage();

                TAExamCourseCollegeInspect taExamCourseCollegeInspect = new TAExamCourseCollegeInspect();
                taExamCourseCollegeInspect.setId(SystemConstant.getDbUuid());
                taExamCourseCollegeInspect.setExamId(examId);
                taExamCourseCollegeInspect.setSchoolId(tbExamService.getById(examId).getSchoolId());
                taExamCourseCollegeInspect.setCourseCode(effectiveCourseCode);
                taExamCourseCollegeInspect.setCourseName(basicCourseService.findByCourseCode(effectiveCourseCode,schoolId).getName());
                taExamCourseCollegeInspect.setCollegeId(collegeId);
                taExamCourseCollegeInspect.setMaxScore(BigDecimal.valueOf(maxScore));
                taExamCourseCollegeInspect.setMinScore(BigDecimal.valueOf(minScore));
                taExamCourseCollegeInspect.setAvgScore(BigDecimal.valueOf(avgScore));
                taExamCourseCollegeInspect.setRealityCount(realityCount);
                taExamCourseCollegeInspect.setAbsentCount(absentCount);
                taExamCourseCollegeInspect.setTotalCount(totalCount);
                taExamCourseCollegeInspect.setUpperQuartile(BigDecimal.valueOf(upperQuartile));
                taExamCourseCollegeInspect.setMedian(BigDecimal.valueOf(median));
                taExamCourseCollegeInspect.setLowerQuartile(BigDecimal.valueOf(lowerQuartile));
                taExamCourseCollegeInspect.setMode(mode);
                taExamCourseCollegeInspect.setStandardDeviation(BigDecimal.valueOf(standardDeviation));
                taExamCourseCollegeInspect.setRelativePosition(BigDecimal.valueOf(relativePosition));
                inspectCollegeList.add(taExamCourseCollegeInspect);
            }
        }
        taExamCourseCollegeInspectService.saveBatch(inspectCollegeList);
        return "t_a_exam_course_college_inspect";
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public String buildAnalyzeExamCourseClazz(Long examId, String courseCode) {
        Long schoolId = tbExamService.findSchoolIdByExamId(examId);

        List<TAExamCourseRecord> recordDatasource = taExamCourseRecordService.list(new QueryWrapper<TAExamCourseRecord>().lambda()
                .eq(TAExamCourseRecord::getExamId, examId));
        // 可分析有效课程信息
        List<String> effectiveCourseCodeList = tbExamCourseService.findEffectiveByExamId(examId, courseCode);

        List<TAExamCourseClazz> taExamCourseClazzList = new ArrayList<>();
        for (String effectiveCourseCode : effectiveCourseCodeList) {
            // 删除原有数据
            taExamCourseClazzService.remove(new QueryWrapper<TAExamCourseClazz>().lambda()
                    .eq(TAExamCourseClazz::getExamId, examId)
                    .eq(TAExamCourseClazz::getCourseCode, effectiveCourseCode));

            List<TAExamCourseRecord> recordCourseCurrentDatasource = recordDatasource.stream()
                    .filter(e -> effectiveCourseCode.equals(e.getCourseCode()) && e.getStudentCurrent()).collect(Collectors.toList());
            List<Long> clazzIdList = recordCourseCurrentDatasource.stream().filter(e -> !e.getAbsent()).map(TAExamCourseRecord::getClazzId).distinct().collect(Collectors.toList());
            for (Long clazzId : clazzIdList) {
                List<TAExamCourseRecord> clazzEffectiveRecordDatasource = recordCourseCurrentDatasource.stream()
                        .filter(e -> clazzId.equals(e.getClazzId())).collect(Collectors.toList());

                // 课程-班级 总应届人数
                int totalCount = clazzEffectiveRecordDatasource.size();
                // 有效分析数据源
                List<TAExamCourseRecord> effectiveList = clazzEffectiveRecordDatasource.stream().filter(e -> !e.getAbsent()).collect(Collectors.toList());
                // 课程-班级 总应届实考人数
                int realityCount = effectiveList.size();
                // 课程-班级 总缺考应届人数
                int absentCount = totalCount - realityCount;
                List<Double> assignedScoreList = effectiveList.stream().map(e -> e.getAssignedScore().doubleValue()).collect(Collectors.toList());

                DoubleSummaryStatistics doubleSummaryStatistics = assignedScoreList.stream().collect(Collectors.summarizingDouble(e -> e));
                double minScore = doubleSummaryStatistics.getMin();
                double maxScore = doubleSummaryStatistics.getMax();
                double avgScore = doubleSummaryStatistics.getAverage();

                List<TBExamStudent> tbExamStudentList = tbExamStudentService.list(new QueryWrapper<TBExamStudent>().lambda()
                        .eq(TBExamStudent::getExamId, examId)
                        .eq(TBExamStudent::getCourseCode, effectiveCourseCode)
                        .eq(TBExamStudent::getClazzId, clazzId));
                List<Long> teachCollegeIdList = tbExamStudentList.stream().map(TBExamStudent::getTeachCollegeId).distinct().collect(Collectors.toList());
                StringBuilder collegeName = new StringBuilder();
                for (Long collegeId : teachCollegeIdList) {
                    SysOrg tbSchoolCollege = sysOrgService.getById(collegeId);
                    if (Objects.isNull(tbSchoolCollege)) {
                        collegeName.append(SystemConstant.DEFAULT_SIGN).append(",");
                    } else {
                        collegeName.append(tbSchoolCollege.getName()).append(",");
                    }
                }
                collegeName = new StringBuilder(collegeName.substring(0, collegeName.length() - 1));

                TAExamCourseClazz taExamCourseClazz = new TAExamCourseClazz();
                taExamCourseClazz.setId(SystemConstant.getDbUuid());
                taExamCourseClazz.setExamId(examId);
                taExamCourseClazz.setSchoolId(tbExamService.getById(examId).getSchoolId());
                taExamCourseClazz.setCourseCode(effectiveCourseCode);
                taExamCourseClazz.setCourseName(basicCourseService.findByCourseCode(effectiveCourseCode,schoolId).getName());
                taExamCourseClazz.setClazzId(clazzId);
                taExamCourseClazz.setMaxScore(BigDecimal.valueOf(maxScore));
                taExamCourseClazz.setMinScore(BigDecimal.valueOf(minScore));
                taExamCourseClazz.setAvgScore(BigDecimal.valueOf(avgScore));
                taExamCourseClazz.setRealityCount(realityCount);
                taExamCourseClazz.setAbsentCount(absentCount);
                taExamCourseClazz.setTotalCount(totalCount);
                taExamCourseClazz.setCollegeName(collegeName.toString());
                taExamCourseClazzList.add(taExamCourseClazz);
            }
        }
        taExamCourseClazzService.saveBatch(taExamCourseClazzList);
        return " 't_a_exam_course_clazz'表构建成功 ";
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public String buildAnalyzePointScoreRate(Long examId, String courseCode) throws Exception {
        Long schoolId = tbExamService.findSchoolIdByExamId(examId);
        // 可分析有效课程信息
        List<String> effectiveCourseCodeList = tbExamCourseService.findEffectiveByExamId(examId, courseCode);

        List<TAExamCourseRecord> dataSource = taExamCourseRecordService.list(new QueryWrapper<TAExamCourseRecord>().lambda()
                .eq(TAExamCourseRecord::getExamId, examId));

        // 循环进入每次考试课程下
        for (String effectiveCourseCode : effectiveCourseCodeList) {
            // 有效考生作答数据源
            List<TAExamCourseRecord> effectiveDatasource = dataSource.stream()
                    .filter(e -> effectiveCourseCode.equals(e.getCourseCode()) && !e.getAbsent() && e.getStudentCurrent()).collect(Collectors.toList());

            // 考查点数据源
            List<TBDimension> dimensionDatasource = tbDimensionService.list(new QueryWrapper<TBDimension>().lambda()
                    .eq(TBDimension::getExamId, examId)
                    .eq(TBDimension::getCourseCode, effectiveCourseCode));

            if (dimensionDatasource.size() < 1) {
                continue;
            }

            // 删除原数据
            taExamCourseDioService.remove(new QueryWrapper<TAExamCourseDio>().lambda()
                    .eq(TAExamCourseDio::getExamId, examId)
                    .eq(TAExamCourseDio::getCourseCode, effectiveCourseCode));

            taExamCourseRecordDioService.remove(new QueryWrapper<TAExamCourseRecordDio>().lambda()
                    .eq(TAExamCourseRecordDio::getExamId, examId)
                    .eq(TAExamCourseRecordDio::getCourseCode, effectiveCourseCode));

            taExamCourseRecordModService.remove(new QueryWrapper<TAExamCourseRecordMod>().lambda()
                    .eq(TAExamCourseRecordMod::getExamId, examId)
                    .eq(TAExamCourseRecordMod::getCourseCode, effectiveCourseCode));

            List<TBPaper> tbPaperList = tbPaperService.list(new QueryWrapper<TBPaper>().lambda()
                    .eq(TBPaper::getExamId, examId)
                    .eq(TBPaper::getCourseCode, effectiveCourseCode));

            if (tbPaperList.size() == 0) {
                throw ExceptionResultEnum.ERROR.exception("试卷基础数据查找失败");
            }
            for (TBPaper tbPaper : tbPaperList) {
                Long paperId = tbPaper.getId();
                // 试卷结构数据源
                List<TBPaperStruct> tbPaperStructList = tbPaperStructService.list(new QueryWrapper<TBPaperStruct>().lambda()
                        .eq(TBPaperStruct::getPaperId, paperId));
                if (tbPaperStructList.size() == 0) {
                    throw ExceptionResultEnum.ERROR.exception("试卷结构数据查找失败");
                }
                // 该试卷下所有考生作答数据
                List<BasicAnswerDto> answerDtoList = tbAnswerService.findByPaperId(paperId);
                if (answerDtoList.size() == 0) {
                    throw ExceptionResultEnum.ERROR.exception("试卷id为[" + paperId + "]的考生作答详细记录不存在");
                }

                // 5.计算每个考查点所对应的题目集合
                Map<String, List<TBPaperStruct>> pointToPaper = this.handlePointToPaper(dimensionDatasource, tbPaperStructList, examId, effectiveCourseCode);

                // 计算每个模块对应的题目集合
                Map<String, List<TBPaperStruct>> moduleToPaper = this.handleModuleToPaper(dimensionDatasource, tbPaperStructList, examId, effectiveCourseCode);

                // 6.计算每个考查点在此次考试所占分数
                Map<String, Object> everyPointTotalScore = this.handleEveryPointTotalScore(pointToPaper);

                // 计算每个模块在此次考试中所占分数
                Map<String, Object> everyModuleTotalScore = this.handleEveryPointTotalScore(moduleToPaper);

                // 7.计算每个考生各个考查点和考查模块得分率并更新't_a_exam_course_record_dio'表和't_a_exam_course_record_mod'表
                List<TAExamCourseRecordDio> taExamCourseRecordDioList = new ArrayList<>();
                List<TAExamCourseRecordMod> taExamCourseRecordModList = new ArrayList<>();
                for (TAExamCourseRecord taExamCourseRecord : effectiveDatasource) {
                    Long inspectCollegeId = taExamCourseRecord.getInspectCollegeId();
                    String inspectCollegeName = sysOrgService.getById(inspectCollegeId).getName();
                    Long teacherId = taExamCourseRecord.getTeacherId();
                    String teacherName = sysUserService.getById(teacherId).getRealName();
                    List<BasicAnswerDto> oneStudentAnswerDetailDataSource = answerDtoList.stream()
                            .filter(e -> taExamCourseRecord.getExamRecordId().equals(e.getExamRecordId()))
                            .collect(Collectors.toList());
                    if (oneStudentAnswerDetailDataSource.size() == 0) {
                        continue; // 当AB卷时，examPaperTikDataSource还是整体数据，所以会匹配不到，匹配不到的说明不是本套试卷，因此匹配不到的不能处理。
                    }
                    // 考查点得分率
                    for (String s : pointToPaper.keySet()) { // 遍历考查知识点所对应的题目集合键值对
                        List<TBPaperStruct> paperStructList = pointToPaper.get(s);

                        final String split = SystemConstant.HYPHEN;
                        Set<String> questionIndex = paperStructList
                                .stream()
                                .map(e -> e.getNumberType() + split + e.getBigQuestionNumber() + split + e.getSmallQuestionNumber())
                                .collect(Collectors.toSet()); // 该考查点考查到的所有试题在试卷结构（paper）中'题号类型-大题号-小题号'组成的索引集合


                        // 获取学生在该知识点的总得分
                        double studentScore = oneStudentAnswerDetailDataSource.stream()
                                .filter(e -> questionIndex.contains(e.getNumberType() + split + e.getMainNumber() + split + e.getSubNumber()))
                                .collect(Collectors.summarizingDouble(e -> e.getScore().doubleValue()))
                                .getSum();  // 查找该考查点所考查的所有试题在试卷结构（paper）中的索引（'题号类型-大题号-小题号'）包含该学生每题答题记录的索引的答题记录信息，计算描述统计

                        // 获取该知识点在试卷中的总得分
                        double totalScore = (double) everyPointTotalScore.get(s);

                        // 获取该知识点该学生的得分率
                        double rate;
                        if (totalScore != 0 && studentScore != 0) {
                            rate = studentScore / totalScore;
                        } else {
                            rate = 0;
                        }

                        //组装taExamCourseRecordDio数据
                        TAExamCourseRecordDio taExamCourseRecordDio = new TAExamCourseRecordDio();
                        taExamCourseRecordDio.setId(SystemConstant.getDbUuid());
                        taExamCourseRecordDio.setSchoolId(tbExamService.getById(examId).getSchoolId());
                        taExamCourseRecordDio.setExamRecordId(taExamCourseRecord.getExamRecordId());
                        taExamCourseRecordDio.setPaperId(taExamCourseRecord.getPaperId());
                        taExamCourseRecordDio.setExamId(taExamCourseRecord.getExamId());
                        taExamCourseRecordDio.setStudentId(taExamCourseRecord.getStudentId());
                        taExamCourseRecordDio.setStudentCode(taExamCourseRecord.getStudentCode());
                        taExamCourseRecordDio.setCourseCode(effectiveCourseCode);
                        taExamCourseRecordDio.setCourseName(basicCourseService.findByCourseCode(effectiveCourseCode,schoolId).getName());
                        String[] dimCodeArr = s.split("-");
                        if (dimCodeArr.length != 2) {
                            throw ExceptionResultEnum.ERROR.exception("获得的考查点标识不符合标准,标准为 type-dimensionCode,结果为:  " + s);
                        }
                        String dimensionType = dimCodeArr[0];
                        String dimensionCode = dimCodeArr[1];
                        taExamCourseRecordDio.setDimensionType(dimensionType);
                        taExamCourseRecordDio.setDimensionCode(dimensionCode);
                        taExamCourseRecordDio.setStudentScore(BigDecimal.valueOf(studentScore));
                        taExamCourseRecordDio.setScoreRate(BigDecimal.valueOf(rate));
                        taExamCourseRecordDio.setProficiency(this.handleModuleProficiency(examId, effectiveCourseCode, dimensionType, rate));
                        taExamCourseRecordDio.setInspectCollegeId(inspectCollegeId);
                        taExamCourseRecordDio.setInspectCollegeName(inspectCollegeName);
                        taExamCourseRecordDio.setTeacherId(teacherId);
                        taExamCourseRecordDio.setTeacherName(teacherName);
                        taExamCourseRecordDioList.add(taExamCourseRecordDio);
                    }
                    // 考查模块得分率
                    for (String s : moduleToPaper.keySet()) { // 遍历考查模块对应的题目集合键值对
                        List<TBPaperStruct> paperStructList = moduleToPaper.get(s);

                        final String split = SystemConstant.HYPHEN;

                        Set<String> questionIndex = paperStructList
                                .stream()
                                .map(e -> e.getNumberType() + split + e.getBigQuestionNumber() + split + e.getSmallQuestionNumber())
                                .collect(Collectors.toSet()); // 该考查点考查到的所有试题在试卷结构（paper）中'题号类型-大题号-小题号'组成的索引集合

                        // 获取学生在该知识点的总得分
                        double studentScore = oneStudentAnswerDetailDataSource.stream()
                                .filter(e -> questionIndex.contains(e.getNumberType() + split + e.getMainNumber() + split + e.getSubNumber()))
                                .collect(Collectors.summarizingDouble(e -> e.getScore().doubleValue()))
                                .getSum();  // 查找该考查点所考查的所有试题在试卷结构（paper）中的索引（'题号类型-大题号-小题号'）包含该学生每题答题记录的索引的答题记录信息，计算描述统计


                        // 获取该知识点在试卷中的总得分
                        double totalScore = (double) everyModuleTotalScore.get(s);

                        // 获取该知识点该学生的得分率
                        double rate;
                        if (totalScore != 0 && studentScore != 0) {
                            rate = studentScore / totalScore;
                        } else {
                            rate = 0;
                        }
                        TAExamCourseRecordMod taExamCourseRecordMod = new TAExamCourseRecordMod();
                        taExamCourseRecordMod.setId(SystemConstant.getDbUuid());
                        taExamCourseRecordMod.setExamRecordId(taExamCourseRecord.getExamRecordId());
                        taExamCourseRecordMod.setPaperId(taExamCourseRecord.getPaperId());
                        taExamCourseRecordMod.setExamId(taExamCourseRecord.getExamId());
                        taExamCourseRecordMod.setSchoolId(tbExamService.getById(examId).getSchoolId());
                        taExamCourseRecordMod.setCourseCode(effectiveCourseCode);
                        taExamCourseRecordMod.setCourseName(basicCourseService.findByCourseCode(effectiveCourseCode,schoolId).getName());
                        taExamCourseRecordMod.setModuleType(s);
                        taExamCourseRecordMod.setTotalScore(BigDecimal.valueOf(studentScore));
                        taExamCourseRecordMod.setScoreRate(BigDecimal.valueOf(rate));
                        taExamCourseRecordMod.setFullScore(BigDecimal.valueOf(totalScore));
                        taExamCourseRecordMod.setProficiency(this.handleModuleProficiency(examId, effectiveCourseCode, s, rate));
                        taExamCourseRecordMod.setInspectCollegeId(inspectCollegeId);
                        taExamCourseRecordMod.setInspectCollegeName(inspectCollegeName);
                        taExamCourseRecordMod.setStudentId(taExamCourseRecord.getStudentId());
                        taExamCourseRecordMod.setStudentCode(taExamCourseRecord.getStudentCode());
                        taExamCourseRecordModList.add(taExamCourseRecordMod);
                    }
                }
                taExamCourseRecordDioService.saveBatch(taExamCourseRecordDioList);
                taExamCourseRecordModService.saveBatch(taExamCourseRecordModList);

                // 8.计算此次考试各个考查点得分率并插入't_a_exam_course_dio'表
                List<TAExamCourseDio> taExamCourseDioList = new ArrayList<>();
                for (String s : everyPointTotalScore.keySet()) {
                    String[] dimCodeArr = s.split("-");
                    if (dimCodeArr.length != 2) {
                        throw ExceptionResultEnum.ERROR.exception("获得的考查点标识不符合标准,标准为 type-dimensionCode,结果为:  " + s);
                    }
                    String dimensionType = dimCodeArr[0];
                    String dimensionCode = dimCodeArr[1];
                    double totalScore = (double) everyPointTotalScore.get(s);
                    double avgScore = taExamCourseRecordDioList.stream()
                            .filter(e -> dimensionType.equals(e.getDimensionType()) && dimensionCode.equals(e.getDimensionCode()))
                            .collect(Collectors.summarizingDouble(e -> e.getStudentScore().doubleValue()))
                            .getAverage();
                    double rate;
                    if (totalScore != 0 && avgScore != 0) {
                        rate = avgScore / totalScore;
                    } else {
                        rate = 0;
                    }
                    double totalCount = pointToPaper.get(s).size();

                    //组装't_a_exam_course_dio'数据
                    TAExamCourseDio taExamCourseDio = new TAExamCourseDio();
                    taExamCourseDio.setId(SystemConstant.getDbUuid());
                    taExamCourseDio.setExamId(examId);
                    taExamCourseDio.setSchoolId(tbExamService.getById(examId).getSchoolId());
                    taExamCourseDio.setCourseCode(effectiveCourseCode);
                    taExamCourseDio.setCourseName(basicCourseService.findByCourseCode(effectiveCourseCode,schoolId).getName());
                    taExamCourseDio.setPaperId(paperId);
                    taExamCourseDio.setDimensionType(dimensionType);
                    taExamCourseDio.setDimensionCode(dimensionCode);
                    taExamCourseDio.setScoreRate(BigDecimal.valueOf(rate));
                    taExamCourseDio.setTotalScore(BigDecimal.valueOf(totalScore));
                    taExamCourseDio.setTotalCount(BigDecimal.valueOf(totalCount));

                    taExamCourseDioList.add(taExamCourseDio);
                }
                taExamCourseDioService.saveBatch(taExamCourseDioList);
            }

            List<TAExamCourseRecordMod> examCourseRecordModList = taExamCourseRecordModService.list(new QueryWrapper<TAExamCourseRecordMod>().lambda()
                    .eq(TAExamCourseRecordMod::getExamId, examId)
                    .eq(TAExamCourseRecordMod::getCourseCode, effectiveCourseCode));

            // 计算该考生在该模块得分率在该学院排名
            List<TBModuleConfig> tbModuleConfigList = tbModuleConfigService.findDistinctModuleInfoByExamIdAndCourseCode(examId, effectiveCourseCode);
            for (TAExamCourseRecordMod taExamCourseRecordMod : examCourseRecordModList) {
                String moduleType = taExamCourseRecordMod.getModuleType();
                Long myCollegeId = taExamCourseRecordMod.getInspectCollegeId();
                List<TAExamCourseRecordMod> sameColModuleList = examCourseRecordModList.stream().filter(e -> e.getInspectCollegeId().equals(myCollegeId) && moduleType.equals(e.getModuleType())).collect(Collectors.toList()); // 同学院下学生该模块数据

                // 计算模块得分率在学院的排名和排名等级
                double size = sameColModuleList.size();


                BigDecimal myScoreRate = taExamCourseRecordMod.getScoreRate();
                double myNumber = sameColModuleList.stream().filter(e -> e.getScoreRate().compareTo(myScoreRate) > 0).count() + 1; //我在学院的排名
                taExamCourseRecordMod.setColRank((int) myNumber);


                // 计算模块得分率在学院的百分等级
                double lowCount = sameColModuleList.stream().filter(e -> e.getScoreRate().compareTo(myScoreRate) < 0).count(); // 在学院该模块得分低于我的人数
                double sameCount = sameColModuleList.stream().filter(e -> e.getScoreRate().compareTo(myScoreRate) == 0).count(); // 在学院该模块得分等于我的人数
                double totalCount = sameColModuleList.size(); // 该学院总人数
                int percentGrade = this.handlePercentGrade(BigDecimal.valueOf(lowCount), BigDecimal.valueOf(sameCount), BigDecimal.valueOf(totalCount)); // 该学生该模块成绩在该学院的百分等级
                taExamCourseRecordMod.setPercentGrade(percentGrade);

                // 计算模块等级
                List<TBModuleConfig> formulaList = tbModuleConfigList.stream().filter(e -> e.getModuleType().equals(moduleType)).collect(Collectors.toList());
                if (formulaList.size() != 1) {
                    throw ExceptionResultEnum.ERROR.exception("数据异常");
                }
                String formula = formulaList.get(0).getFormula();
                LevelRuleEnum[] levelRuleEnumArr = LevelRuleEnum.values();
                for (LevelRuleEnum levelRuleEnum : levelRuleEnumArr) {
                    if (formula.equals(levelRuleEnum.getValue())) {
                        Field field = taExamCourseRecordMod.getClass().getDeclaredField(levelRuleEnum.getAttribute()); //对应属性
                        Method getMethod = taExamCourseRecordMod.getClass().getDeclaredMethod("get" + ConversionUtils.initCap(field.getName())); // 找到该属性的方法

                        double value = Double.parseDouble(String.valueOf(getMethod.invoke(taExamCourseRecordMod)));
                        if (!formula.equals(LevelRuleEnum.COLLEGE_RANK.getValue())) {  // 当计算规则不为学院排名时，为了方便计算，将minNumber设置为1 使其无效
                            size = -1;
                        }
                        taExamCourseRecordMod.setLevel(this.handleModuleRankLevel(examId, effectiveCourseCode, moduleType, value, size));
                    }
                }
            }
            taExamCourseRecordModService.updateBatchById(examCourseRecordModList);

        }
        return "维度表构建完毕";
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public String buildAnalyzeExamCourseCollegeInspectDio(Long examId, String courseCode) {
        // 可分析有效课程信息
        List<String> effectiveCourseCodeList = tbExamCourseService.findEffectiveByExamId(examId, courseCode);
        for (String effectiveCourseCode : effectiveCourseCodeList) {
            // 删除原有数据
            taExamCourseCollegeInspectDioService.remove(new QueryWrapper<TAExamCourseCollegeInspectDio>().lambda()
                    .eq(TAExamCourseCollegeInspectDio::getExamId, examId)
                    .eq(TAExamCourseCollegeInspectDio::getCourseCode, effectiveCourseCode));

            taExamCourseCollegeInspectDioService.insertByTAExamCourseRecordDio(examId, effectiveCourseCode);
        }
        return "'t_a_exam_course_college_inspect_dio'表构建完成 ";
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public String buildAnalyzeExamCourseTeacherDio(Long examId, String courseCode) {
        // 可分析有效课程信息
        List<String> effectiveCourseCodeList = tbExamCourseService.findEffectiveByExamId(examId, courseCode);
        for (String effectiveCourseCode : effectiveCourseCodeList) {
            // 删除原有数据
            taExamCourseTeacherDioService.remove(new QueryWrapper<TAExamCourseTeacherDio>().lambda()
                    .eq(TAExamCourseTeacherDio::getExamId, examId)
                    .eq(TAExamCourseTeacherDio::getCourseCode, effectiveCourseCode));

            taExamCourseTeacherDioService.insertByTAExamCourseRecordDio(examId, effectiveCourseCode);
        }
        return "'t_a_exam_course_teacher_dio'表构建完成 ";
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public String buildAnalyzeExamCourseTeacherCollegeDio(Long examId, String courseCode) {
        // 可分析有效课程信息
        List<String> effectiveCourseCodeList = tbExamCourseService.findEffectiveByExamId(examId, courseCode);
        for (String effectiveCourseCode : effectiveCourseCodeList) {
            // 删除原有数据
            taExamCourseTeacherCollegeDioService.remove(new QueryWrapper<TAExamCourseTeacherCollegeDio>().lambda()
                    .eq(TAExamCourseTeacherCollegeDio::getExamId, examId)
                    .eq(TAExamCourseTeacherCollegeDio::getCourseCode, effectiveCourseCode));

            taExamCourseTeacherCollegeDioService.insertByTAExamCourseRecordDio(examId, effectiveCourseCode);
        }
        return "'t_a_exam_course_teacher_college_dio'表构建完成 ";
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public String buildAnalyzePaperStruct(Long examId, String courseCode) {
        Long schoolId = tbExamService.findSchoolIdByExamId(examId);
        // 可分析有效课程信息
        List<String> effectiveCourseCodeList = tbExamCourseService.findEffectiveByExamId(examId, courseCode);
        for (String effectiveCourseCode : effectiveCourseCodeList) {
            List<TBPaper> tbPaperList = tbPaperService.list(new QueryWrapper<TBPaper>().lambda()
                    .eq(TBPaper::getExamId, examId).eq(TBPaper::getCourseCode, effectiveCourseCode));
            if (tbPaperList.size() == 0) {
                throw ExceptionResultEnum.ERROR.exception("基础试卷信息异常");
            }
            // 删除原有数据
            taPaperStructService.remove(new QueryWrapper<TAPaperStruct>().lambda()
                    .eq(TAPaperStruct::getExamId, examId)
                    .eq(TAPaperStruct::getCourseCode, effectiveCourseCode));
            List<TAPaperStruct> taPaperStructList = new ArrayList<>();
            // 该课程有效试卷结构数据
            List<ValidAnswerDetailDto> answerDetailDtoList = tbAnswerService.findValid(examId, effectiveCourseCode);
            for (TBPaper tbPaper : tbPaperList) {
                Long paperId = tbPaper.getId();
                String paperType = tbPaper.getPaperType();
                List<TBPaperStruct> tbPaperStructList = tbPaperStructService.list(new QueryWrapper<TBPaperStruct>().lambda()
                        .eq(TBPaperStruct::getPaperId, paperId));
                if (tbPaperStructList.size() == 0) {
                    throw ExceptionResultEnum.ERROR.exception("试卷结构数据异常");
                }
                for (TBPaperStruct paperStruct : tbPaperStructList) {
                    String numberType = paperStruct.getNumberType();
                    String mainNumber = paperStruct.getBigQuestionNumber();
                    String subNumber = paperStruct.getSmallQuestionNumber();

                    List<ValidAnswerDetailDto> oneQuestionAnswerDetailList = answerDetailDtoList
                            .stream().filter(e -> paperType.equals(e.getPaperType()) &&
                                    numberType.equals(e.getNumberType()) &&
                                    mainNumber.equals(e.getMainNumber()) &&
                                    subNumber.equals(e.getSubNumber())).collect(Collectors.toList()); //某道小题的所有参考学生作答信息（并且按照该科目的参考学生百分等级从高到低排序了）
                    if (oneQuestionAnswerDetailList.size() == 0) {
                        System.out.println("异常");
                    }
                    BigDecimal fullScore = paperStruct.getFullScore();
                    PaperStructJudgeEnum paperStructJudgeEnum;
                    if (oneQuestionAnswerDetailList.stream().anyMatch(e -> fullScore.compareTo(e.getScore()) != 0)) {
                        paperStructJudgeEnum = PaperStructJudgeEnum.NOT_QUITE_RIGHT;
                    } else {
                        paperStructJudgeEnum = PaperStructJudgeEnum.ALL_CORRECT;
                    }

                    DoubleSummaryStatistics descriptiveStatistics = oneQuestionAnswerDetailList.stream()
                            .collect(Collectors.summarizingDouble(e -> e.getScore().doubleValue()));

                    double scoreAvg = descriptiveStatistics.getAverage();
                    BigDecimal standardScoreRate = BigDecimal.valueOf(scoreAvg).divide(fullScore, 4, RoundingMode.HALF_UP);
                    BigDecimal scoreRate = standardScoreRate.setScale(1, RoundingMode.HALF_UP);
                    String difficult = this.analyzeDifficult(examId, effectiveCourseCode, scoreRate.doubleValue());

                    double validity = this.calculateValidity(oneQuestionAnswerDetailList, fullScore.doubleValue());

                    TAPaperStruct taPaperStruct = new TAPaperStruct();
                    taPaperStruct.setId(SystemConstant.getDbUuid());
                    taPaperStruct.setPaperStructId(paperStruct.getId());
                    taPaperStruct.setExamId(examId);
                    taPaperStruct.setSchoolId(tbExamService.getById(examId).getSchoolId());
                    taPaperStruct.setCourseCode(effectiveCourseCode);
                    taPaperStruct.setCourseName(basicCourseService.findByCourseCode(effectiveCourseCode,schoolId).getName());
                    taPaperStruct.setPaperId(paperId);
                    taPaperStruct.setPaperType(paperType);
                    taPaperStruct.setQuestionName(paperStruct.getQuestionName());
                    taPaperStruct.setNumberType(paperStruct.getNumberType());
                    taPaperStruct.setBigQuestionNumber(paperStruct.getBigQuestionNumber());
                    taPaperStruct.setSmallQuestionNumber(paperStruct.getSmallQuestionNumber());
                    taPaperStruct.setQuestionType(paperStruct.getQuestionType());
                    taPaperStruct.setFullScore(paperStruct.getFullScore());
                    taPaperStruct.setScoreRules(paperStruct.getScoreRules());
                    taPaperStruct.setRulesDesc(paperStruct.getRulesDesc());
                    taPaperStruct.setKnowledgeDimension(paperStruct.getKnowledgeDimension());
                    taPaperStruct.setAbilityDimension(paperStruct.getAbilityDimension());
                    taPaperStruct.setLiteracyDimension(paperStruct.getLiteracyDimension());
                    taPaperStruct.setStandardScoreRate(standardScoreRate);
                    taPaperStruct.setScoreRate(scoreRate);
                    taPaperStruct.setDifficult(difficult);
                    taPaperStruct.setValidity(BigDecimal.valueOf(validity));
                    taPaperStruct.setPaperStructJudge(paperStructJudgeEnum);
                    taPaperStructList.add(taPaperStruct);
                }
            }
            taPaperStructService.saveBatch(taPaperStructList);
        }
        return " 't_a_paper_struct'表构建成功 ";
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public String buildAnalyzeCollegePaperStruct(Long examId, String courseCode) {
        Long schoolId = tbExamService.findSchoolIdByExamId(examId);
        // 可分析有效课程信息
        List<String> effectiveCourseCodeList = tbExamCourseService.findEffectiveByExamId(examId, courseCode);
        for (String effectiveCourseCode : effectiveCourseCodeList) {
            List<TBPaper> tbPaperList = tbPaperService.list(new QueryWrapper<TBPaper>().lambda()
                    .eq(TBPaper::getExamId, examId).eq(TBPaper::getCourseCode, effectiveCourseCode));
            if (tbPaperList.size() == 0) {
                throw ExceptionResultEnum.ERROR.exception("基础试卷信息异常");
            }
            // 删除原有数据
            taExamCourseCollegePaperStructService.remove(new QueryWrapper<TAExamCourseCollegePaperStruct>().lambda()
                    .eq(TAExamCourseCollegePaperStruct::getExamId, examId)
                    .eq(TAExamCourseCollegePaperStruct::getCourseCode, effectiveCourseCode));
            List<TAExamCourseCollegePaperStruct> taExamCourseCollegePaperStructList = new ArrayList<>();
            // 该课程有效试卷结构数据
            List<ValidAnswerDetailDto> answerDetailDtoList = tbAnswerService.findValid(examId, effectiveCourseCode);
            for (TBPaper tbPaper : tbPaperList) {
                Long paperId = tbPaper.getId();
                String paperType = tbPaper.getPaperType();

                // 参考该试卷的考察学院id集合
                Set<Long> inspectCollegeIdSet = answerDetailDtoList.stream()
                        .filter(e -> paperId.equals(e.getPaperId()))
                        .map(ValidAnswerDetailDto::getInspectCollegeId)
                        .collect(Collectors.toSet());

                List<TBPaperStruct> tbPaperStructList = tbPaperStructService.list(new QueryWrapper<TBPaperStruct>().lambda()
                        .eq(TBPaperStruct::getPaperId, paperId));
                if (tbPaperStructList.size() == 0) {
                    throw ExceptionResultEnum.ERROR.exception("试卷结构数据异常");
                }
                for (Long inspectCollegeId : inspectCollegeIdSet) {
                    String inspectCollegeName = sysOrgService.getById(inspectCollegeId).getName();
                    for (TBPaperStruct paperStruct : tbPaperStructList) {
                        String numberType = paperStruct.getNumberType();
                        String mainNumber = paperStruct.getBigQuestionNumber();
                        String subNumber = paperStruct.getSmallQuestionNumber();

                        List<ValidAnswerDetailDto> oneQuestionAnswerDetailList = answerDetailDtoList
                                .stream().filter(e -> paperType.equals(e.getPaperType()) &&
                                        inspectCollegeId.equals(e.getInspectCollegeId()) &&
                                        numberType.equals(e.getNumberType()) &&
                                        mainNumber.equals(e.getMainNumber()) &&
                                        subNumber.equals(e.getSubNumber())).collect(Collectors.toList()); //某学院某道小题的所有参考学生作答信息（并且按照该科目的参考学生百分等级从高到低排序了）
                        if (oneQuestionAnswerDetailList.size() == 0) {
                            System.out.println("异常");
                        }
                        BigDecimal fullScore = paperStruct.getFullScore();
                        PaperStructJudgeEnum paperStructJudgeEnum;
                        if (oneQuestionAnswerDetailList.stream().anyMatch(e -> fullScore.compareTo(e.getScore()) != 0)) {
                            paperStructJudgeEnum = PaperStructJudgeEnum.NOT_QUITE_RIGHT;
                        } else {
                            paperStructJudgeEnum = PaperStructJudgeEnum.ALL_CORRECT;
                        }

                        DoubleSummaryStatistics descriptiveStatistics = oneQuestionAnswerDetailList.stream()
                                .collect(Collectors.summarizingDouble(e -> e.getScore().doubleValue()));

                        double scoreAvg = descriptiveStatistics.getAverage();
                        BigDecimal standardScoreRate = BigDecimal.valueOf(scoreAvg).divide(fullScore, 4, RoundingMode.HALF_UP);
                        BigDecimal scoreRate = standardScoreRate.setScale(1, RoundingMode.HALF_UP);
                        String difficult = this.analyzeDifficult(examId, effectiveCourseCode, scoreRate.doubleValue());

                        TAExamCourseCollegePaperStruct taExamCourseCollegePaperStruct = new TAExamCourseCollegePaperStruct();
                        taExamCourseCollegePaperStruct.setId(SystemConstant.getDbUuid());
                        taExamCourseCollegePaperStruct.setPaperStructId(paperStruct.getId());
                        taExamCourseCollegePaperStruct.setExamId(examId);
                        taExamCourseCollegePaperStruct.setSchoolId(tbExamService.getById(examId).getSchoolId());
                        taExamCourseCollegePaperStruct.setCourseCode(effectiveCourseCode);
                        taExamCourseCollegePaperStruct.setCourseName(basicCourseService.findByCourseCode(effectiveCourseCode,schoolId).getName());
                        taExamCourseCollegePaperStruct.setPaperId(paperId);
                        taExamCourseCollegePaperStruct.setInspectCollegeId(inspectCollegeId);
                        taExamCourseCollegePaperStruct.setInspectCollegeName(inspectCollegeName);
                        taExamCourseCollegePaperStruct.setPaperType(paperType);
                        taExamCourseCollegePaperStruct.setQuestionName(paperStruct.getQuestionName());
                        taExamCourseCollegePaperStruct.setNumberType(paperStruct.getNumberType());
                        taExamCourseCollegePaperStruct.setBigQuestionNumber(paperStruct.getBigQuestionNumber());
                        taExamCourseCollegePaperStruct.setSmallQuestionNumber(paperStruct.getSmallQuestionNumber());
                        taExamCourseCollegePaperStruct.setQuestionType(paperStruct.getQuestionType());
                        taExamCourseCollegePaperStruct.setFullScore(paperStruct.getFullScore());
                        taExamCourseCollegePaperStruct.setScoreRules(paperStruct.getScoreRules());
                        taExamCourseCollegePaperStruct.setRulesDesc(paperStruct.getRulesDesc());
                        taExamCourseCollegePaperStruct.setKnowledgeDimension(paperStruct.getKnowledgeDimension());
                        taExamCourseCollegePaperStruct.setAbilityDimension(paperStruct.getAbilityDimension());
                        taExamCourseCollegePaperStruct.setLiteracyDimension(paperStruct.getLiteracyDimension());
                        taExamCourseCollegePaperStruct.setStandardScoreRate(standardScoreRate);
                        taExamCourseCollegePaperStruct.setScoreRate(scoreRate);
                        taExamCourseCollegePaperStruct.setDifficult(difficult);
                        taExamCourseCollegePaperStruct.setPaperStructJudge(paperStructJudgeEnum);
                        taExamCourseCollegePaperStructList.add(taExamCourseCollegePaperStruct);
                    }
                }

            }
            taExamCourseCollegePaperStructService.saveBatch(taExamCourseCollegePaperStructList);
        }
        return "'t_a_exam_course_college_paper_struct'表构建成功 ";
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public String buildAnalyzeTeacherPaperStruct(Long examId, String courseCode) {
        Long schoolId = tbExamService.findSchoolIdByExamId(examId);
        // 可分析有效课程信息
        List<String> effectiveCourseCodeList = tbExamCourseService.findEffectiveByExamId(examId, courseCode);
        for (String effectiveCourseCode : effectiveCourseCodeList) {
            List<TBPaper> tbPaperList = tbPaperService.list(new QueryWrapper<TBPaper>().lambda()
                    .eq(TBPaper::getExamId, examId).eq(TBPaper::getCourseCode, effectiveCourseCode));
            if (tbPaperList.size() == 0) {
                throw ExceptionResultEnum.ERROR.exception("基础试卷信息异常");
            }
            // 删除原有数据
            taExamCourseTeacherPaperStructService.remove(new QueryWrapper<TAExamCourseTeacherPaperStruct>().lambda()
                    .eq(TAExamCourseTeacherPaperStruct::getExamId, examId)
                    .eq(TAExamCourseTeacherPaperStruct::getCourseCode, effectiveCourseCode));
            List<TAExamCourseTeacherPaperStruct> taExamCourseTeacherPaperStructList = new ArrayList<>();
            // 该课程有效试卷结构数据
            List<ValidAnswerDetailDto> answerDetailDtoList = tbAnswerService.findValid(examId, effectiveCourseCode);
            for (TBPaper tbPaper : tbPaperList) {
                Long paperId = tbPaper.getId();
                String paperType = tbPaper.getPaperType();

                // 参考该试卷的考察学院id集合
                Set<Long> teacherIdSet = answerDetailDtoList.stream()
                        .filter(e -> paperId.equals(e.getPaperId()))
                        .map(ValidAnswerDetailDto::getTeacherId)
                        .collect(Collectors.toSet());

                List<TBPaperStruct> tbPaperStructList = tbPaperStructService.list(new QueryWrapper<TBPaperStruct>().lambda()
                        .eq(TBPaperStruct::getPaperId, paperId));
                if (tbPaperStructList.size() == 0) {
                    throw ExceptionResultEnum.ERROR.exception("试卷结构数据异常");
                }
                for (Long teacherId : teacherIdSet) {
                    String teacherName = sysUserService.getById(teacherId).getRealName();
                    for (TBPaperStruct paperStruct : tbPaperStructList) {
                        String numberType = paperStruct.getNumberType();
                        String mainNumber = paperStruct.getBigQuestionNumber();
                        String subNumber = paperStruct.getSmallQuestionNumber();

                        List<ValidAnswerDetailDto> oneQuestionAnswerDetailList = answerDetailDtoList
                                .stream().filter(e -> paperType.equals(e.getPaperType()) &&
                                        teacherId.equals(e.getTeacherId()) &&
                                        numberType.equals(e.getNumberType()) &&
                                        mainNumber.equals(e.getMainNumber()) &&
                                        subNumber.equals(e.getSubNumber())).collect(Collectors.toList()); //某教师某道小题的所有参考学生作答信息（并且按照该科目的参考学生百分等级从高到低排序了）
                        if (oneQuestionAnswerDetailList.size() == 0) {
                            System.out.println("异常");
                        }
                        BigDecimal fullScore = paperStruct.getFullScore();
                        PaperStructJudgeEnum paperStructJudgeEnum;
                        if (oneQuestionAnswerDetailList.stream().anyMatch(e -> fullScore.compareTo(e.getScore()) != 0)) {
                            paperStructJudgeEnum = PaperStructJudgeEnum.NOT_QUITE_RIGHT;
                        } else {
                            paperStructJudgeEnum = PaperStructJudgeEnum.ALL_CORRECT;
                        }

                        DoubleSummaryStatistics descriptiveStatistics = oneQuestionAnswerDetailList.stream()
                                .collect(Collectors.summarizingDouble(e -> e.getScore().doubleValue()));

                        double scoreAvg = descriptiveStatistics.getAverage();
                        BigDecimal standardScoreRate = BigDecimal.valueOf(scoreAvg).divide(fullScore, 4, RoundingMode.HALF_UP);
                        BigDecimal scoreRate = standardScoreRate.setScale(1, RoundingMode.HALF_UP);
                        String difficult = this.analyzeDifficult(examId, effectiveCourseCode, scoreRate.doubleValue());

                        TAExamCourseTeacherPaperStruct taExamCourseTeacherPaperStruct = new TAExamCourseTeacherPaperStruct();
                        taExamCourseTeacherPaperStruct.setId(SystemConstant.getDbUuid());
                        taExamCourseTeacherPaperStruct.setPaperStructId(paperStruct.getId());
                        taExamCourseTeacherPaperStruct.setExamId(examId);
                        taExamCourseTeacherPaperStruct.setSchoolId(tbExamService.getById(examId).getSchoolId());
                        taExamCourseTeacherPaperStruct.setCourseCode(effectiveCourseCode);
                        taExamCourseTeacherPaperStruct.setCourseName(basicCourseService.findByCourseCode(effectiveCourseCode,schoolId).getName());
                        taExamCourseTeacherPaperStruct.setPaperId(paperId);
                        taExamCourseTeacherPaperStruct.setTeacherId(teacherId);
                        taExamCourseTeacherPaperStruct.setTeacherName(teacherName);
                        taExamCourseTeacherPaperStruct.setPaperType(paperType);
                        taExamCourseTeacherPaperStruct.setQuestionName(paperStruct.getQuestionName());
                        taExamCourseTeacherPaperStruct.setNumberType(paperStruct.getNumberType());
                        taExamCourseTeacherPaperStruct.setBigQuestionNumber(paperStruct.getBigQuestionNumber());
                        taExamCourseTeacherPaperStruct.setSmallQuestionNumber(paperStruct.getSmallQuestionNumber());
                        taExamCourseTeacherPaperStruct.setQuestionType(paperStruct.getQuestionType());
                        taExamCourseTeacherPaperStruct.setFullScore(paperStruct.getFullScore());
                        taExamCourseTeacherPaperStruct.setScoreRules(paperStruct.getScoreRules());
                        taExamCourseTeacherPaperStruct.setRulesDesc(paperStruct.getRulesDesc());
                        taExamCourseTeacherPaperStruct.setKnowledgeDimension(paperStruct.getKnowledgeDimension());
                        taExamCourseTeacherPaperStruct.setAbilityDimension(paperStruct.getAbilityDimension());
                        taExamCourseTeacherPaperStruct.setLiteracyDimension(paperStruct.getLiteracyDimension());
                        taExamCourseTeacherPaperStruct.setStandardScoreRate(standardScoreRate);
                        taExamCourseTeacherPaperStruct.setScoreRate(scoreRate);
                        taExamCourseTeacherPaperStruct.setDifficult(difficult);
                        taExamCourseTeacherPaperStruct.setPaperStructJudge(paperStructJudgeEnum);
                        taExamCourseTeacherPaperStructList.add(taExamCourseTeacherPaperStruct);
                    }
                }

            }
            taExamCourseTeacherPaperStructService.saveBatch(taExamCourseTeacherPaperStructList);
        }
        return "'t_a_exam_course_teacher_paper_struct'表构建成功 ";
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public String buildAnalyzeTeacherCollegePaperStruct(Long examId, String courseCode) {
        Long schoolId = tbExamService.findSchoolIdByExamId(examId);
        // 可分析有效课程信息
        List<String> effectiveCourseCodeList = tbExamCourseService.findEffectiveByExamId(examId, courseCode);
        for (String effectiveCourseCode : effectiveCourseCodeList) {
            List<TBPaper> tbPaperList = tbPaperService.list(new QueryWrapper<TBPaper>().lambda()
                    .eq(TBPaper::getExamId, examId).eq(TBPaper::getCourseCode, effectiveCourseCode));
            if (tbPaperList.size() == 0) {
                throw ExceptionResultEnum.ERROR.exception("基础试卷信息异常");
            }
            // 删除原有数据
            taExamCourseTeacherCollegePaperStructService.remove(new QueryWrapper<TAExamCourseTeacherCollegePaperStruct>().lambda()
                    .eq(TAExamCourseTeacherCollegePaperStruct::getExamId, examId)
                    .eq(TAExamCourseTeacherCollegePaperStruct::getCourseCode, effectiveCourseCode));
            List<TAExamCourseTeacherCollegePaperStruct> tAExamCourseTeacherCollegePaperStructList = new ArrayList<>();
            // 该课程有效试卷结构数据
            List<ValidAnswerDetailDto> answerDetailDtoList = tbAnswerService.findValid(examId, effectiveCourseCode);
            for (TBPaper tbPaper : tbPaperList) {
                Long paperId = tbPaper.getId();
                String paperType = tbPaper.getPaperType();

                // 参考该试卷的考察学院id集合
                Set<Long> teacherIdSet = answerDetailDtoList.stream()
                        .filter(e -> paperId.equals(e.getPaperId()))
                        .map(ValidAnswerDetailDto::getTeacherId)
                        .collect(Collectors.toSet());

                List<TBPaperStruct> tbPaperStructList = tbPaperStructService.list(new QueryWrapper<TBPaperStruct>().lambda()
                        .eq(TBPaperStruct::getPaperId, paperId));
                if (tbPaperStructList.size() == 0) {
                    throw ExceptionResultEnum.ERROR.exception("试卷结构数据异常");
                }
                // 试卷下
                for (Long teacherId : teacherIdSet) {
                    // 教师下
                    String teacherName = sysUserService.getById(teacherId).getRealName();

                    // 参考该试卷的考察学院id集合
                    Set<Long> inspectCollegeIdSet = answerDetailDtoList.stream()
                            .filter(e -> paperId.equals(e.getPaperId()))
                            .filter(e -> teacherId.equals(e.getTeacherId()))
                            .map(ValidAnswerDetailDto::getInspectCollegeId)
                            .collect(Collectors.toSet());

                    for (Long inspectCollegeId : inspectCollegeIdSet) {
                        // 学院下
                        String inspectCollegeName = sysOrgService.getById(inspectCollegeId).getName();

                        for (TBPaperStruct paperStruct : tbPaperStructList) {
                            // 试题下
                            String numberType = paperStruct.getNumberType();
                            String mainNumber = paperStruct.getBigQuestionNumber();
                            String subNumber = paperStruct.getSmallQuestionNumber();

                            List<ValidAnswerDetailDto> oneQuestionAnswerDetailList = answerDetailDtoList
                                    .stream().filter(e -> paperType.equals(e.getPaperType()) &&
                                            teacherId.equals(e.getTeacherId()) &&
                                            inspectCollegeId.equals(e.getInspectCollegeId()) &&
                                            numberType.equals(e.getNumberType()) &&
                                            mainNumber.equals(e.getMainNumber()) &&
                                            subNumber.equals(e.getSubNumber())).collect(Collectors.toList()); //某教师某道小题的所有参考学生作答信息（并且按照该科目的参考学生百分等级从高到低排序了）
                            if (oneQuestionAnswerDetailList.size() == 0) {
                                System.out.println("异常");
                            }
                            BigDecimal fullScore = paperStruct.getFullScore();
                            PaperStructJudgeEnum paperStructJudgeEnum;
                            if (oneQuestionAnswerDetailList.stream().anyMatch(e -> fullScore.compareTo(e.getScore()) != 0)) {
                                paperStructJudgeEnum = PaperStructJudgeEnum.NOT_QUITE_RIGHT;
                            } else {
                                paperStructJudgeEnum = PaperStructJudgeEnum.ALL_CORRECT;
                            }

                            DoubleSummaryStatistics descriptiveStatistics = oneQuestionAnswerDetailList.stream()
                                    .collect(Collectors.summarizingDouble(e -> e.getScore().doubleValue()));

                            double scoreAvg = descriptiveStatistics.getAverage();
                            BigDecimal standardScoreRate = BigDecimal.valueOf(scoreAvg).divide(fullScore, 4, RoundingMode.HALF_UP);
                            BigDecimal scoreRate = standardScoreRate.setScale(1, RoundingMode.HALF_UP);
                            String difficult = this.analyzeDifficult(examId, effectiveCourseCode, scoreRate.doubleValue());

                            TAExamCourseTeacherCollegePaperStruct taExamCourseTeacherCollegePaperStruct = new TAExamCourseTeacherCollegePaperStruct();
                            taExamCourseTeacherCollegePaperStruct.setId(SystemConstant.getDbUuid());
                            taExamCourseTeacherCollegePaperStruct.setPaperStructId(paperStruct.getId());
                            taExamCourseTeacherCollegePaperStruct.setExamId(examId);
                            taExamCourseTeacherCollegePaperStruct.setSchoolId(tbExamService.getById(examId).getSchoolId());
                            taExamCourseTeacherCollegePaperStruct.setCourseCode(effectiveCourseCode);
                            taExamCourseTeacherCollegePaperStruct.setCourseName(basicCourseService.findByCourseCode(effectiveCourseCode,schoolId).getName());
                            taExamCourseTeacherCollegePaperStruct.setPaperId(paperId);
                            taExamCourseTeacherCollegePaperStruct.setTeacherId(teacherId);
                            taExamCourseTeacherCollegePaperStruct.setTeacherName(teacherName);
                            taExamCourseTeacherCollegePaperStruct.setInspectCollegeId(inspectCollegeId);
                            taExamCourseTeacherCollegePaperStruct.setInspectCollegeName(inspectCollegeName);
                            taExamCourseTeacherCollegePaperStruct.setPaperType(paperType);
                            taExamCourseTeacherCollegePaperStruct.setQuestionName(paperStruct.getQuestionName());
                            taExamCourseTeacherCollegePaperStruct.setNumberType(paperStruct.getNumberType());
                            taExamCourseTeacherCollegePaperStruct.setBigQuestionNumber(paperStruct.getBigQuestionNumber());
                            taExamCourseTeacherCollegePaperStruct.setSmallQuestionNumber(paperStruct.getSmallQuestionNumber());
                            taExamCourseTeacherCollegePaperStruct.setQuestionType(paperStruct.getQuestionType());
                            taExamCourseTeacherCollegePaperStruct.setFullScore(paperStruct.getFullScore());
                            taExamCourseTeacherCollegePaperStruct.setScoreRules(paperStruct.getScoreRules());
                            taExamCourseTeacherCollegePaperStruct.setRulesDesc(paperStruct.getRulesDesc());
                            taExamCourseTeacherCollegePaperStruct.setKnowledgeDimension(paperStruct.getKnowledgeDimension());
                            taExamCourseTeacherCollegePaperStruct.setAbilityDimension(paperStruct.getAbilityDimension());
                            taExamCourseTeacherCollegePaperStruct.setLiteracyDimension(paperStruct.getLiteracyDimension());
                            taExamCourseTeacherCollegePaperStruct.setStandardScoreRate(standardScoreRate);
                            taExamCourseTeacherCollegePaperStruct.setScoreRate(scoreRate);
                            taExamCourseTeacherCollegePaperStruct.setDifficult(difficult);
                            taExamCourseTeacherCollegePaperStruct.setPaperStructJudge(paperStructJudgeEnum);
                            tAExamCourseTeacherCollegePaperStructList.add(taExamCourseTeacherCollegePaperStruct);
                        }

                    }
                }

            }
            taExamCourseTeacherCollegePaperStructService.saveBatch(tAExamCourseTeacherCollegePaperStructList);
        }
        return "'t_a_exam_course_teacher_college_paper_struct'表构建成功 ";
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public String buildExamPaperDifficult(Long examId, String courseCode) {
        Long schoolId = tbExamService.findSchoolIdByExamId(examId);
        // 可分析有效课程信息
        List<String> effectiveCourseCodeList = tbExamCourseService.findEffectiveByExamId(examId, courseCode);

        for (String effectiveCourseCode : effectiveCourseCodeList) {
            taExamCourseDifficultService.remove(new QueryWrapper<TAExamCourseDifficult>().lambda()
                    .eq(TAExamCourseDifficult::getExamId, examId)
                    .eq(TAExamCourseDifficult::getCourseCode, effectiveCourseCode));

            List<TAExamCourseDifficult> taExamCourseDifficultList = new ArrayList<>();

            List<TBCommonLevelConfig> configLevelDatasource = tbCommonLevelConfigService.list(new QueryWrapper<TBCommonLevelConfig>().lambda()
                    .eq(TBCommonLevelConfig::getExamId, examId)
                    .eq(TBCommonLevelConfig::getCourseCode, effectiveCourseCode)
                    .eq(TBCommonLevelConfig::getLevelType, "难度等级"));// 该科目试题难度情况数据源

            List<TAPaperStruct> questionDatasource = taPaperStructService.list(new QueryWrapper<TAPaperStruct>().lambda()
                    .eq(TAPaperStruct::getExamId, examId).eq(TAPaperStruct::getCourseCode, effectiveCourseCode));// 该科目试题情况数据源

            LinkedList<AnswerDetailBean> answerDetailDatasource = tbAnswerService.findValidAnswerDetailWithPap(examId, effectiveCourseCode);
            Set<Long> paperTypeList = questionDatasource.stream().map(TAPaperStruct::getPaperId).collect(Collectors.toSet());

            for (Long paperId : paperTypeList) {
                for (TBCommonLevelConfig levelTemp : configLevelDatasource) {
                    String interpret = levelTemp.getInterpret();
                    String scope = levelTemp.getScope();

                    List<TAPaperStruct> questionList = questionDatasource.stream()
                            .filter(e -> paperId.equals(e.getPaperId()) && interpret.equals(e.getDifficult()))
                            .collect(Collectors.toList()); // 题目信息

                    List<AnswerDetailBean> answerDetailForSch = answerDetailDatasource.stream()
                            .filter(e -> paperId.equals(e.getPaperId()) && interpret.equals(e.getDifficult()))
                            .collect(Collectors.toList());

                    double schAvgScoreRate = 0;
                    if (answerDetailForSch.size() > 0) {
                        schAvgScoreRate = answerDetailForSch.stream().collect(Collectors.summarizingDouble(e -> e.getAnswerScore().doubleValue())).getSum() / answerDetailForSch.stream().collect(Collectors.summarizingDouble(e -> e.getFullScore().doubleValue())).getSum();
                    }

                    // 学院id集合
                    List<Long> collegeIdList = taExamCourseRecordService.list(new QueryWrapper<TAExamCourseRecord>().lambda()
                                    .eq(TAExamCourseRecord::getExamId, examId)
                                    .eq(TAExamCourseRecord::getCourseCode, effectiveCourseCode)
                                    .eq(TAExamCourseRecord::getPaperId, paperId)
                                    .eq(TAExamCourseRecord::getAbsent, false)
                                    .eq(TAExamCourseRecord::getStudentCurrent, true))
                            .stream()
                            .map(TAExamCourseRecord::getInspectCollegeId).distinct()
                            .collect(Collectors.toList());

                    for (Long collegeId : collegeIdList) {
                        List<AnswerDetailBean> answerDetailForCol = answerDetailForSch.stream()
                                .filter(e -> collegeId.equals(e.getCollegeId())).collect(Collectors.toList());

                        double colAvgScoreRate = 0;
                        if (answerDetailForCol.size() > 0) {
                            colAvgScoreRate = answerDetailForCol.stream().collect(Collectors.summarizingDouble(e -> e.getAnswerScore().doubleValue())).getSum() / answerDetailForCol.stream().collect(Collectors.summarizingDouble(e -> e.getFullScore().doubleValue())).getSum();
                        }
                        // 得分率保留2位小数处理
                        Integer count = questionList.size();

                        TAExamCourseDifficult taExamCourseDifficult = new TAExamCourseDifficult();
                        taExamCourseDifficult.setId(SystemConstant.getDbUuid());
                        taExamCourseDifficult.setExamId(examId);
                        taExamCourseDifficult.setCourseCode(effectiveCourseCode);
                        taExamCourseDifficult.setCourseName(basicCourseService.findByCourseCode(effectiveCourseCode,schoolId).getName());
                        taExamCourseDifficult.setPaperId(paperId);
                        taExamCourseDifficult.setPaperType(tbPaperService.getById(paperId).getPaperType());
                        taExamCourseDifficult.setCollegeId(collegeId);
                        taExamCourseDifficult.setSchoolId(tbExamService.getById(examId).getSchoolId());
                        taExamCourseDifficult.setInterpret(interpret);
                        taExamCourseDifficult.setCount(count);
                        taExamCourseDifficult.setScope(scope);
                        taExamCourseDifficult.setSchAvgScoreRate(BigDecimal.valueOf(schAvgScoreRate));
                        taExamCourseDifficult.setColAvgScoreRate(BigDecimal.valueOf(colAvgScoreRate));

                        taExamCourseDifficultList.add(taExamCourseDifficult);
                    }
                }
            }

            taExamCourseDifficultService.saveBatch(taExamCourseDifficultList);
        }

        return "'t_a_exam_course_difficult' 表构建完成";
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public String buildExamPaperTeacherDifficult(Long examId, String courseCode) {
        Long schoolId = tbExamService.findSchoolIdByExamId(examId);
        // 可分析有效课程信息
        List<String> effectiveCourseCodeList = tbExamCourseService.findEffectiveByExamId(examId, courseCode);

        for (String effectiveCourseCode : effectiveCourseCodeList) {
            taExamCourseTeacherDifficultService.remove(new QueryWrapper<TAExamCourseTeacherDifficult>().lambda()
                    .eq(TAExamCourseTeacherDifficult::getExamId, examId)
                    .eq(TAExamCourseTeacherDifficult::getCourseCode, effectiveCourseCode));

            List<TAExamCourseTeacherDifficult> taExamCourseTeacherDifficultList = new ArrayList<>();

            List<TBCommonLevelConfig> configLevelDatasource = tbCommonLevelConfigService.list(new QueryWrapper<TBCommonLevelConfig>().lambda()
                    .eq(TBCommonLevelConfig::getExamId, examId)
                    .eq(TBCommonLevelConfig::getCourseCode, effectiveCourseCode)
                    .eq(TBCommonLevelConfig::getLevelType, "难度等级"));// 该科目试题难度情况数据源

            List<TAPaperStruct> questionDatasource = taPaperStructService.list(new QueryWrapper<TAPaperStruct>().lambda()
                    .eq(TAPaperStruct::getExamId, examId).eq(TAPaperStruct::getCourseCode, effectiveCourseCode));// 该科目试题情况数据源

            LinkedList<AnswerDetailBean> answerDetailDatasource = tbAnswerService.findValidAnswerDetailWithPap(examId, effectiveCourseCode);
            Set<Long> paperTypeList = questionDatasource.stream().map(TAPaperStruct::getPaperId).collect(Collectors.toSet());

            for (Long paperId : paperTypeList) {
                for (TBCommonLevelConfig levelTemp : configLevelDatasource) {
                    String interpret = levelTemp.getInterpret();
                    String scope = levelTemp.getScope();

                    List<TAPaperStruct> questionList = questionDatasource.stream()
                            .filter(e -> paperId.equals(e.getPaperId()) && interpret.equals(e.getDifficult()))
                            .collect(Collectors.toList()); // 题目信息

                    List<AnswerDetailBean> answerDetailForSch = answerDetailDatasource.stream()
                            .filter(e -> paperId.equals(e.getPaperId()) && interpret.equals(e.getDifficult()))
                            .collect(Collectors.toList());

                    double schAvgScoreRate = 0;
                    if (answerDetailForSch.size() > 0) {
                        schAvgScoreRate = answerDetailForSch.stream().collect(Collectors.summarizingDouble(e -> e.getAnswerScore().doubleValue())).getSum() / answerDetailForSch.stream().collect(Collectors.summarizingDouble(e -> e.getFullScore().doubleValue())).getSum();
                    }

                    // 教师id集合
                    List<Long> teacherIdList = taExamCourseRecordService.list(new QueryWrapper<TAExamCourseRecord>().lambda()
                                    .eq(TAExamCourseRecord::getExamId, examId)
                                    .eq(TAExamCourseRecord::getCourseCode, effectiveCourseCode)
                                    .eq(TAExamCourseRecord::getPaperId, paperId)
                                    .eq(TAExamCourseRecord::getAbsent, false)
                                    .eq(TAExamCourseRecord::getStudentCurrent, true))
                            .stream()
                            .map(TAExamCourseRecord::getTeacherId).distinct()
                            .collect(Collectors.toList());

                    for (Long teacherId : teacherIdList) {
                        List<AnswerDetailBean> answerDetailForTea = answerDetailForSch.stream()
                                .filter(e -> teacherId.equals(e.getTeacherId())).collect(Collectors.toList());

                        double teaAvgScoreRate = 0;
                        if (answerDetailForTea.size() > 0) {
                            teaAvgScoreRate = answerDetailForTea.stream().collect(Collectors.summarizingDouble(e -> e.getAnswerScore().doubleValue())).getSum() / answerDetailForTea.stream().collect(Collectors.summarizingDouble(e -> e.getFullScore().doubleValue())).getSum();
                        }

                        // 得分率保留2位小数处理
                        Integer count = questionList.size();
                        TAExamCourseTeacherDifficult taExamCourseTeacherDifficult = new TAExamCourseTeacherDifficult();
                        taExamCourseTeacherDifficult.setId(SystemConstant.getDbUuid());
                        taExamCourseTeacherDifficult.setExamId(examId);
                        taExamCourseTeacherDifficult.setPaperId(paperId);
                        taExamCourseTeacherDifficult.setPaperType(tbPaperService.getById(paperId).getPaperType());
                        taExamCourseTeacherDifficult.setCourseCode(effectiveCourseCode);
                        taExamCourseTeacherDifficult.setCourseName(basicCourseService.findByCourseCode(effectiveCourseCode,schoolId).getName());
                        taExamCourseTeacherDifficult.setTeacherId(teacherId);
                        taExamCourseTeacherDifficult.setTeacherName(sysUserService.getById(teacherId).getRealName());
                        taExamCourseTeacherDifficult.setSchoolId(tbExamService.getById(examId).getSchoolId());
                        taExamCourseTeacherDifficult.setInterpret(interpret);
                        taExamCourseTeacherDifficult.setCount(count);
                        taExamCourseTeacherDifficult.setScope(scope);
                        taExamCourseTeacherDifficult.setSchAvgScoreRate(BigDecimal.valueOf(schAvgScoreRate));
                        taExamCourseTeacherDifficult.setTeaAvgScoreRate(BigDecimal.valueOf(teaAvgScoreRate));

                        taExamCourseTeacherDifficultList.add(taExamCourseTeacherDifficult);
                    }
                }
            }

            taExamCourseTeacherDifficultService.saveBatch(taExamCourseTeacherDifficultList);
        }

        return "'t_a_exam_course_teacher_difficult' 表构建完成";
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public String buildAnalyzeExamCourseTeacherCollegeDifficult(Long examId, String courseCode) {
        Long schoolId = tbExamService.findSchoolIdByExamId(examId);
        // 可分析有效课程信息
        List<String> effectiveCourseCodeList = tbExamCourseService.findEffectiveByExamId(examId, courseCode);

        for (String effectiveCourseCode : effectiveCourseCodeList) {
            taExamCourseTeacherCollegeDifficultService.remove(new QueryWrapper<TAExamCourseTeacherCollegeDifficult>().lambda()
                    .eq(TAExamCourseTeacherCollegeDifficult::getExamId, examId)
                    .eq(TAExamCourseTeacherCollegeDifficult::getCourseCode, effectiveCourseCode));

            List<TAExamCourseTeacherCollegeDifficult> taExamCourseTeacherCollegeDifficultList = new ArrayList<>();

            List<TBCommonLevelConfig> configLevelDatasource = tbCommonLevelConfigService.list(new QueryWrapper<TBCommonLevelConfig>().lambda()
                    .eq(TBCommonLevelConfig::getExamId, examId)
                    .eq(TBCommonLevelConfig::getCourseCode, effectiveCourseCode)
                    .eq(TBCommonLevelConfig::getLevelType, "难度等级"));// 该科目试题难度情况数据源

            List<TAPaperStruct> questionDatasource = taPaperStructService.list(new QueryWrapper<TAPaperStruct>().lambda()
                    .eq(TAPaperStruct::getExamId, examId).eq(TAPaperStruct::getCourseCode, effectiveCourseCode));// 该科目试题情况数据源

            LinkedList<AnswerDetailBean> answerDetailDatasource = tbAnswerService.findValidAnswerDetailWithPap(examId, effectiveCourseCode);
            Set<Long> paperTypeList = questionDatasource.stream().map(TAPaperStruct::getPaperId).collect(Collectors.toSet());

            for (Long paperId : paperTypeList) {
                for (TBCommonLevelConfig levelTemp : configLevelDatasource) {
                    String interpret = levelTemp.getInterpret();
                    String scope = levelTemp.getScope();

                    List<TAPaperStruct> questionList = questionDatasource.stream()
                            .filter(e -> paperId.equals(e.getPaperId()) && interpret.equals(e.getDifficult()))
                            .collect(Collectors.toList()); // 题目信息

                    // 学院id集合
                    List<Long> collegeIdList = taExamCourseRecordService.list(new QueryWrapper<TAExamCourseRecord>().lambda()
                                    .eq(TAExamCourseRecord::getExamId, examId)
                                    .eq(TAExamCourseRecord::getCourseCode, effectiveCourseCode)
                                    .eq(TAExamCourseRecord::getPaperId, paperId)
                                    .eq(TAExamCourseRecord::getAbsent, false)
                                    .eq(TAExamCourseRecord::getStudentCurrent, true))
                            .stream()
                            .map(TAExamCourseRecord::getInspectCollegeId).distinct()
                            .collect(Collectors.toList());

                    // 学校作答集合
                    List<AnswerDetailBean> answerDetailForSch = answerDetailDatasource.stream()
                            .filter(e -> paperId.equals(e.getPaperId()) && interpret.equals(e.getDifficult()))
                            .collect(Collectors.toList());

                    double schAvgScoreRate = 0;
                    if (answerDetailForSch.size() > 0) {
                        schAvgScoreRate = answerDetailForSch.stream().collect(Collectors.summarizingDouble(e -> e.getAnswerScore().doubleValue())).getSum() / answerDetailForSch.stream().collect(Collectors.summarizingDouble(e -> e.getFullScore().doubleValue())).getSum();
                    }

                    for (Long collegeId : collegeIdList) {
                        String collegeName = sysOrgService.getById(collegeId).getName();
                        // 考察学院作答集合
                        List<AnswerDetailBean> answerDetailForCol = answerDetailForSch.stream()
                                .filter(e -> collegeId.equals(e.getCollegeId())).collect(Collectors.toList());

                        double colAvgScoreRate = 0;
                        if (answerDetailForCol.size() > 0) {
                            colAvgScoreRate = answerDetailForCol.stream().collect(Collectors.summarizingDouble(e -> e.getAnswerScore().doubleValue())).getSum() / answerDetailForCol.stream().collect(Collectors.summarizingDouble(e -> e.getFullScore().doubleValue())).getSum();
                        }

                        // 教师id集合
                        List<Long> teacherIdList = taExamCourseRecordService.list(new QueryWrapper<TAExamCourseRecord>().lambda()
                                        .eq(TAExamCourseRecord::getExamId, examId)
                                        .eq(TAExamCourseRecord::getCourseCode, effectiveCourseCode)
                                        .eq(TAExamCourseRecord::getPaperId, paperId)
                                        .eq(TAExamCourseRecord::getInspectCollegeId, collegeId)
                                        .eq(TAExamCourseRecord::getAbsent, false)
                                        .eq(TAExamCourseRecord::getStudentCurrent, true))
                                .stream()
                                .map(TAExamCourseRecord::getTeacherId).distinct()
                                .collect(Collectors.toList());

                        for (Long teacherId : teacherIdList) {
                            List<AnswerDetailBean> answerDetailForColTea = answerDetailForCol.stream()
                                    .filter(e -> teacherId.equals(e.getTeacherId())).collect(Collectors.toList());

                            double teaColAvgScoreRate = 0;
                            if (answerDetailForColTea.size() > 0) {
                                teaColAvgScoreRate = answerDetailForColTea.stream().collect(Collectors.summarizingDouble(e -> e.getAnswerScore().doubleValue())).getSum() / answerDetailForColTea.stream().collect(Collectors.summarizingDouble(e -> e.getFullScore().doubleValue())).getSum();
                            }

                            // 得分率保留2位小数处理
                            Integer count = questionList.size();
                            TAExamCourseTeacherCollegeDifficult taExamCourseTeacherCollegeDifficult = new TAExamCourseTeacherCollegeDifficult();
                            taExamCourseTeacherCollegeDifficult.setId(SystemConstant.getDbUuid());
                            taExamCourseTeacherCollegeDifficult.setExamId(examId);
                            taExamCourseTeacherCollegeDifficult.setPaperId(paperId);
                            taExamCourseTeacherCollegeDifficult.setPaperType(tbPaperService.getById(paperId).getPaperType());
                            taExamCourseTeacherCollegeDifficult.setCourseCode(effectiveCourseCode);
                            taExamCourseTeacherCollegeDifficult.setCourseName(basicCourseService.findByCourseCode(effectiveCourseCode,schoolId).getName());
                            taExamCourseTeacherCollegeDifficult.setTeacherId(teacherId);
                            taExamCourseTeacherCollegeDifficult.setTeacherName(sysUserService.getById(teacherId).getRealName());
                            taExamCourseTeacherCollegeDifficult.setInspectCollegeId(collegeId);
                            taExamCourseTeacherCollegeDifficult.setInspectCollegeName(collegeName);
                            taExamCourseTeacherCollegeDifficult.setSchoolId(tbExamService.getById(examId).getSchoolId());
                            taExamCourseTeacherCollegeDifficult.setInterpret(interpret);
                            taExamCourseTeacherCollegeDifficult.setCount(count);
                            taExamCourseTeacherCollegeDifficult.setScope(scope);
                            taExamCourseTeacherCollegeDifficult.setColAvgScoreRate(BigDecimal.valueOf(colAvgScoreRate));
                            taExamCourseTeacherCollegeDifficult.setTeaColAvgScoreRate(BigDecimal.valueOf(teaColAvgScoreRate));

                            taExamCourseTeacherCollegeDifficultList.add(taExamCourseTeacherCollegeDifficult);
                        }
                    }


                }
            }

            taExamCourseTeacherCollegeDifficultService.saveBatch(taExamCourseTeacherCollegeDifficultList);
        }

        return "'t_a_exam_course_teacher_college_difficult' 表构建完成";
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public String buildAnalyzeExamTotal(Long examId,String courseCode) {
        // 删除原数据
        taExamTotalService.remove(new QueryWrapper<TAExamTotal>().lambda()
                .eq(TAExamTotal::getExamId, examId));

        // 数据源
        List<TAExamCourseRecord> taExamCourseRecordList = taExamCourseRecordService.list(new QueryWrapper<TAExamCourseRecord>().lambda()
                .eq(TAExamCourseRecord::getExamId, examId));

        //考查学院
        List<Long> inspectCollegeInfo = taExamCourseRecordList.stream()
                .map(TAExamCourseRecord::getInspectCollegeId).distinct().collect(Collectors.toList());
        // 考查学院数量
        int collegeCount = inspectCollegeInfo.size();
        StringBuilder inspectCollegeNames = new StringBuilder();
        if (collegeCount > 0) {
            for (Long inspectCollegeId : inspectCollegeInfo) {
                SysOrg college = sysOrgService.getById(inspectCollegeId);
                inspectCollegeNames.append(college.getName()).append("、");
            }
            // 考查学院名称
            inspectCollegeNames = new StringBuilder(inspectCollegeNames.substring(0, inspectCollegeNames.length() - 1));
        }

        // 课程
        List<String> courseInfo = taExamCourseRecordList.stream()
                .map(TAExamCourseRecord::getCourseCode).distinct().collect(Collectors.toList());
        int courseCount = courseInfo.size();

        // 总人数
        List<Long> studentInfo = taExamCourseRecordList.stream()
                .map(TAExamCourseRecord::getStudentId).distinct().collect(Collectors.toList());
        int totalCount = studentInfo.size();

        // ------只要有一门考试了就不算缺考
        List<Long> studentRealityInfo = taExamCourseRecordList.stream()
                .filter(e -> !e.getAbsent())
                .map(TAExamCourseRecord::getStudentId).distinct().collect(Collectors.toList());
        int realityCount = studentRealityInfo.size();
        int absentCount = totalCount - realityCount;

        // 课次
        int totalCourseTimes = taExamCourseRecordList.size();
        int realityCourseTimes = (int) taExamCourseRecordList.stream().filter(e -> !e.getAbsent()).count();
        int absentCourseTimes = (int) taExamCourseRecordList.stream().filter(TAExamCourseRecord::getAbsent).count();

        // 考试时间
        TBExam tbExam = tbExamService.getById(examId);
        Long examTime = tbExam.getExamTime();

        TAExamTotal taExamTotal = new TAExamTotal();
        taExamTotal.setId(SystemConstant.getDbUuid());
        taExamTotal.setExamId(examId);
        taExamTotal.setSchoolId(tbExamService.getById(examId).getSchoolId());
        taExamTotal.setCollegeCount(collegeCount);
        taExamTotal.setCollegeNames(inspectCollegeNames.toString());
        taExamTotal.setCourseCount(courseCount);
        taExamTotal.setPublicCourseCount(courseCount);
        taExamTotal.setMajorCourseCount(0);
        taExamTotal.setTotalCount(totalCount);
        taExamTotal.setRealityCount(realityCount);
        taExamTotal.setAbsentCount(absentCount);
        taExamTotal.setTotalCourseTimes(totalCourseTimes);
        taExamTotal.setRealityCourseTimes(realityCourseTimes);
        taExamTotal.setAbsentCourseTimes(absentCourseTimes);
        taExamTotal.setExamTime(examTime);

        taExamTotalService.save(taExamTotal);
        return " 't_a_exam_total'表构建完毕 ";
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public String buildAnalyzeExamCourseCollegeTeacher(Long examId, String courseCode) {
        Long schoolId = tbExamService.findSchoolIdByExamId(examId);
        // 可分析有效课程信息
        List<String> effectiveCourseCodeList = tbExamCourseService.findEffectiveByExamId(examId, courseCode);
        for (String effectiveCourseCode : effectiveCourseCodeList) {
            // 删除该课程原有分析
            taExamCourseCollegeTeacherService.remove(new QueryWrapper<TAExamCourseCollegeTeacher>().lambda()
                    .eq(TAExamCourseCollegeTeacher::getExamId, examId)
                    .eq(TAExamCourseCollegeTeacher::getCourseCode, effectiveCourseCode));

            List<TAExamCourseCollegeTeacher> taExamCourseCollegeTeacherList = new ArrayList<>();
            // 整体该课程下数据源
            List<TAExamCourseRecord> dataSource = taExamCourseRecordService.list(new QueryWrapper<TAExamCourseRecord>().lambda()
                    .eq(TAExamCourseRecord::getExamId, examId)
                    .eq(TAExamCourseRecord::getCourseCode, effectiveCourseCode));

            // 考查学院
            Set<Long> inspectCollegeIdSet = dataSource.stream().map(TAExamCourseRecord::getInspectCollegeId).collect(Collectors.toSet());


            for (Long inspectCollegeId : inspectCollegeIdSet) {
                // 算教师排名用
                List<TAExamCourseCollegeTeacher> rankTempList = new ArrayList<>();
                // 该考查学院维度下授课教师
                Set<Long> teacherIdSet = dataSource.stream()
                        .filter(e -> inspectCollegeId.equals(e.getInspectCollegeId()) && e.getStudentCurrent() && !e.getAbsent())
                        .map(TAExamCourseRecord::getTeacherId)
                        .collect(Collectors.toSet());

                // 教师人数
                int teacherCount = teacherIdSet.size();
                for (Long teacherId : teacherIdSet) {
                    // 该教师数据
                    // ----- 教师在本院学生数据 ------
                    List<TAExamCourseRecord> teacherRecordList = dataSource.stream()
                            .filter(e -> inspectCollegeId.equals(e.getInspectCollegeId()) && teacherId.equals(e.getTeacherId()) && e.getStudentCurrent())
                            .collect(Collectors.toList());

                    // 学生人数
                    int totalCount = teacherRecordList.size();
                    List<TAExamCourseRecord> teacherEffectiveList = teacherRecordList.stream().filter(e -> !e.getAbsent()).collect(Collectors.toList());
                    int realityCount = teacherEffectiveList.size();
                    if (realityCount == 0) {
                        continue;
                    }
                    int absentCount = totalCount - realityCount;

                    // 成绩统计
                    DoubleSummaryStatistics describeStatistic = teacherEffectiveList.stream()
                            .collect(Collectors.summarizingDouble(e -> e.getAssignedScore().doubleValue())); // 学生赋分的描述统计
                    double minScoreAssign = describeStatistic.getMin();
                    double maxScoreAssign = describeStatistic.getMax();
                    double avgScoreAssign = describeStatistic.getAverage();
                    double avgScore = teacherEffectiveList.stream()
                            .collect(Collectors.summarizingDouble(e -> e.getTotalScore().doubleValue())).getAverage();
                    List<Double> assignedScore = teacherEffectiveList.stream().map(e -> e.getAssignedScore().doubleValue()).collect(Collectors.toList());
                    // 计算上四分位数
                    double upperQuartile = MathUtil.calculateQuantile(assignedScore, QuantileEnum.UPPER_QUARTILE.getValue());

                    // 计算中位数
                    double median = MathUtil.calculateQuantile(assignedScore, QuantileEnum.MEDIAN.getValue());

                    // 计算下四分位数
                    double lowerQuartile = MathUtil.calculateQuantile(assignedScore, QuantileEnum.LOWER_QUARTILE.getValue());

                    // 极端情况下分位数值处理
                    if (upperQuartile == 0) {
                        upperQuartile = median;
                    }
                    if (lowerQuartile == 0) {
                        lowerQuartile = median;
                    }

                    String mode = MathUtil.calculateMode(assignedScore); // 众数
                    double standardDeviation = MathUtil.calculateStandardDeviation(assignedScore); // 标准差

                    double relativePosition = teacherEffectiveList.stream()
                            .collect(Collectors.summarizingDouble(e -> e.getStandardizedCoefficients().doubleValue())).getAverage(); // 相对位置


                    // ----- 教师在其他学院学生数据 -----
                    List<TAExamCourseRecord> teacherRecordOtherCollegeList = dataSource.stream()
                            .filter(e -> !inspectCollegeId.equals(e.getInspectCollegeId()) && teacherId.equals(e.getTeacherId()) && e.getStudentCurrent())
                            .collect(Collectors.toList());

                    // 学生人数
                    int otherCollegeTotalCount = teacherRecordOtherCollegeList.size();
                    List<TAExamCourseRecord> teacherEffectiveOtherCollegeList = teacherRecordOtherCollegeList.stream().filter(e -> !e.getAbsent()).collect(Collectors.toList());
                    int otherCollegeRealityCount = teacherEffectiveOtherCollegeList.size();
                    int otherCollegeAbsentCount = otherCollegeTotalCount - otherCollegeRealityCount;

                    // 成绩统计
                    DoubleSummaryStatistics otherCollegeDescribeStatistic = teacherEffectiveOtherCollegeList.stream()
                            .collect(Collectors.summarizingDouble(e -> e.getAssignedScore().doubleValue())); // 学生赋分的描述统计
                    double otherCollegeMinScoreAssign = otherCollegeDescribeStatistic.getMin();
                    double otherCollegeMaxScoreAssign = otherCollegeDescribeStatistic.getMax();
                    if (otherCollegeRealityCount == 0) {
                        otherCollegeMinScoreAssign = 0;
                        otherCollegeMaxScoreAssign = 0;
                    }
                    double otherCollegeAvgScoreAssign = otherCollegeDescribeStatistic.getAverage();
                    double otherCollegeAvgScore = teacherEffectiveOtherCollegeList.stream()
                            .collect(Collectors.summarizingDouble(e -> e.getTotalScore().doubleValue())).getAverage();
                    List<Double> otherCollegeAssignedScore = teacherEffectiveOtherCollegeList.stream().map(e -> e.getAssignedScore().doubleValue()).collect(Collectors.toList());
                    // 计算上四分位数
                    double otherCollegeUpperQuartile = MathUtil.calculateQuantile(otherCollegeAssignedScore, QuantileEnum.UPPER_QUARTILE.getValue());

                    // 计算中位数
                    double otherCollegeMedian = MathUtil.calculateQuantile(otherCollegeAssignedScore, QuantileEnum.MEDIAN.getValue());

                    // 计算下四分位数
                    double otherCollegeLowerQuartile = MathUtil.calculateQuantile(otherCollegeAssignedScore, QuantileEnum.LOWER_QUARTILE.getValue());

                    // 极端情况下分位数值处理
                    if (otherCollegeUpperQuartile == 0) {
                        otherCollegeUpperQuartile = otherCollegeMedian;
                    }
                    if (otherCollegeLowerQuartile == 0) {
                        otherCollegeLowerQuartile = otherCollegeMedian;
                    }

                    String otherCollegeMode = MathUtil.calculateMode(otherCollegeAssignedScore); // 众数


                    // 开课学院数据
                    List<Long> teachCollegeIdList = teacherEffectiveList.stream().map(TAExamCourseRecord::getTeachCollegeId).distinct().collect(Collectors.toList());
                    if (teachCollegeIdList.size() > 1) {
                        throw ExceptionResultEnum.ERROR.exception("有多个开课学院");
                    }
                    Long teachCollegeId = teachCollegeIdList.get(0);
                    String teachCollegeName = SystemConstant.DEFAULT_SIGN;
                    if (teachCollegeId > 0) {
                        teachCollegeName = sysOrgService.getById(teachCollegeId).getName();
                    }

                    TAExamCourseCollegeTeacher taExamCourseCollegeTeacher = new TAExamCourseCollegeTeacher();
                    taExamCourseCollegeTeacher.setId(SystemConstant.getDbUuid());
                    taExamCourseCollegeTeacher.setExamId(examId);
                    taExamCourseCollegeTeacher.setSchoolId(tbExamService.getById(examId).getSchoolId());
                    taExamCourseCollegeTeacher.setCourseCode(effectiveCourseCode);
                    taExamCourseCollegeTeacher.setCourseName(basicCourseService.findByCourseCode(effectiveCourseCode,schoolId).getName());
                    taExamCourseCollegeTeacher.setTeacherId(teacherId);
                    taExamCourseCollegeTeacher.setTeacherName(sysUserService.getById(teacherId).getRealName());
                    taExamCourseCollegeTeacher.setMinScoreAssign(BigDecimal.valueOf(minScoreAssign));
                    taExamCourseCollegeTeacher.setMaxScoreAssign(BigDecimal.valueOf(maxScoreAssign));
                    taExamCourseCollegeTeacher.setAvgScoreAssign(BigDecimal.valueOf(avgScoreAssign));
                    taExamCourseCollegeTeacher.setAvgScore(BigDecimal.valueOf(avgScore));
                    taExamCourseCollegeTeacher.setUpperQuartile(BigDecimal.valueOf(upperQuartile));
                    taExamCourseCollegeTeacher.setMedian(BigDecimal.valueOf(median));
                    taExamCourseCollegeTeacher.setLowerQuartile(BigDecimal.valueOf(lowerQuartile));
                    taExamCourseCollegeTeacher.setMode(mode);
                    taExamCourseCollegeTeacher.setStandardDeviation(BigDecimal.valueOf(standardDeviation));
                    taExamCourseCollegeTeacher.setRelativePosition(BigDecimal.valueOf(relativePosition));
                    taExamCourseCollegeTeacher.setRealityCount(realityCount);
                    taExamCourseCollegeTeacher.setTotalCount(totalCount);
                    taExamCourseCollegeTeacher.setAbsentCount(absentCount);
                    taExamCourseCollegeTeacher.setInspectCollegeId(inspectCollegeId);
                    taExamCourseCollegeTeacher.setInspectCollegeName(sysOrgService.getById(inspectCollegeId).getName());
                    taExamCourseCollegeTeacher.setTeacherCount(teacherCount);
                    taExamCourseCollegeTeacher.setTeachCollegeId(teachCollegeId);
                    taExamCourseCollegeTeacher.setTeachCollegeName(teachCollegeName);
                    taExamCourseCollegeTeacher.setOtherCollegeMinScoreAssign(BigDecimal.valueOf(otherCollegeMinScoreAssign));
                    taExamCourseCollegeTeacher.setOtherCollegeMaxScoreAssign(BigDecimal.valueOf(otherCollegeMaxScoreAssign));
                    taExamCourseCollegeTeacher.setOtherCollegeAvgScoreAssign(BigDecimal.valueOf(otherCollegeAvgScoreAssign));
                    taExamCourseCollegeTeacher.setOtherCollegeUpperQuartile(BigDecimal.valueOf(otherCollegeUpperQuartile));
                    taExamCourseCollegeTeacher.setOtherCollegeMedian(BigDecimal.valueOf(otherCollegeMedian));
                    taExamCourseCollegeTeacher.setOtherCollegeLowerQuartile(BigDecimal.valueOf(otherCollegeLowerQuartile));
                    taExamCourseCollegeTeacher.setOtherCollegeMode(otherCollegeMode);
                    taExamCourseCollegeTeacher.setOtherCollegeRealityCount(otherCollegeRealityCount);
                    taExamCourseCollegeTeacher.setOtherCollegeAbsentCount(otherCollegeAbsentCount);
                    taExamCourseCollegeTeacher.setOtherCollegeTotalCount(otherCollegeTotalCount);


                    rankTempList.add(taExamCourseCollegeTeacher);
                }
                // 计算教师排名
                for (TAExamCourseCollegeTeacher taExamCourseCollegeTeacher : rankTempList) {
                    BigDecimal thisAvgScoreAssign = taExamCourseCollegeTeacher.getAvgScoreAssign();
                    int rank = (int) (rankTempList.stream().filter(e -> (e.getAvgScoreAssign().setScale(SystemConstant.FINAL_SCALE, RoundingMode.HALF_UP)).compareTo(thisAvgScoreAssign.setScale(SystemConstant.FINAL_SCALE, RoundingMode.HALF_UP)) > 0).count() + 1);
                    taExamCourseCollegeTeacher.setTeacherRank(rank);
                    taExamCourseCollegeTeacherList.add(taExamCourseCollegeTeacher);
                }
            }
            taExamCourseCollegeTeacherService.saveBatch(taExamCourseCollegeTeacherList);

        }
        return " 't_a_exam_course_college_teacher' 表构建我那成";
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public String buildAnalyzeExamCourseTeacher(Long examId, String courseCode) {
        Long schoolId = tbExamService.findSchoolIdByExamId(examId);
        // 可分析有效课程信息
        List<String> effectiveCourseCodeList = tbExamCourseService.findEffectiveByExamId(examId, courseCode);
        for (String effectiveCourseCode : effectiveCourseCodeList) {
            taExamCourseTeacherService.remove(new QueryWrapper<TAExamCourseTeacher>().lambda()
                    .eq(TAExamCourseTeacher::getExamId, examId)
                    .eq(TAExamCourseTeacher::getCourseCode, effectiveCourseCode));

            List<TAExamCourseTeacher> taExamCourseTeacherList = new ArrayList<>();
            List<TAExamCourseRecord> dataSource = taExamCourseRecordService.list(new QueryWrapper<TAExamCourseRecord>().lambda()
                    .eq(TAExamCourseRecord::getExamId, examId).eq(TAExamCourseRecord::getCourseCode, effectiveCourseCode));
            List<TAExamCourseRecord> currentSource = dataSource.stream().filter(TAExamCourseRecord::getStudentCurrent).collect(Collectors.toList());

            Set<Long> teacherIdList = currentSource.stream().map(TAExamCourseRecord::getTeacherId).collect(Collectors.toSet());
            for (Long teacherId : teacherIdList) {
                List<TAExamCourseRecord> teacherRecordList = currentSource.stream()
                        .filter(e -> teacherId.equals(e.getTeacherId())).collect(Collectors.toList());
                int totalCount = teacherRecordList.size();
                List<TAExamCourseRecord> effectiveList = teacherRecordList.stream().filter(e -> !e.getAbsent()).collect(Collectors.toList());
                if (effectiveList.size() == 0) {
                    continue;
                }
                int realityCount = effectiveList.size();
                int absentCount = totalCount - realityCount;

                DoubleSummaryStatistics describeStatistic = effectiveList.stream()
                        .collect(Collectors.summarizingDouble(e -> e.getAssignedScore().doubleValue())); // 学生赋分的描述统计
                double minScore = describeStatistic.getMin();
                double maxScore = describeStatistic.getMax();
                double avgScore = describeStatistic.getAverage();

                List<Double> assignedScore = effectiveList.stream().map(e -> e.getAssignedScore().doubleValue()).collect(Collectors.toList());
                // 计算上四分位数
                double upperQuartile = MathUtil.calculateQuantile(assignedScore, QuantileEnum.UPPER_QUARTILE.getValue());

                // 计算中位数
                double median = MathUtil.calculateQuantile(assignedScore, QuantileEnum.MEDIAN.getValue());

                // 计算下四分位数
                double lowerQuartile = MathUtil.calculateQuantile(assignedScore, QuantileEnum.LOWER_QUARTILE.getValue());

                // 极端情况下分位数值处理
                if (upperQuartile == 0) {
                    upperQuartile = median;
                }
                if (lowerQuartile == 0) {
                    lowerQuartile = median;
                }
                String mode = MathUtil.calculateMode(assignedScore); // 众数
                double standardDeviation = MathUtil.calculateStandardDeviation(assignedScore); // 标准差

                // 相对位置
                double relativePosition = effectiveList.stream()
                        .collect(Collectors.summarizingDouble(e -> e.getStandardizedCoefficients().doubleValue())).getAverage();


                TAExamCourseTeacher taExamCourseTeacher = new TAExamCourseTeacher();
                taExamCourseTeacher.setId(SystemConstant.getDbUuid());
                taExamCourseTeacher.setExamId(examId);
                taExamCourseTeacher.setSchoolId(tbExamService.getById(examId).getSchoolId());
                taExamCourseTeacher.setCourseCode(effectiveCourseCode);
                taExamCourseTeacher.setCourseName(basicCourseService.findByCourseCode(effectiveCourseCode,schoolId).getName());
                taExamCourseTeacher.setTeacherId(teacherId);
                taExamCourseTeacher.setTeacherName(sysUserService.getById(teacherId).getRealName());
                taExamCourseTeacher.setMinScore(BigDecimal.valueOf(minScore));
                taExamCourseTeacher.setMaxScore(BigDecimal.valueOf(maxScore));
                taExamCourseTeacher.setAvgScore(BigDecimal.valueOf(avgScore));
                taExamCourseTeacher.setUpperQuartile(BigDecimal.valueOf(upperQuartile));
                taExamCourseTeacher.setMedian(BigDecimal.valueOf(median));
                taExamCourseTeacher.setLowerQuartile(BigDecimal.valueOf(lowerQuartile));
                taExamCourseTeacher.setMode(mode);
                taExamCourseTeacher.setStandardDeviation(BigDecimal.valueOf(standardDeviation));
                taExamCourseTeacher.setRelativePosition(BigDecimal.valueOf(relativePosition));
                taExamCourseTeacher.setTotalCount(totalCount);
                taExamCourseTeacher.setRealityCount(realityCount);
                taExamCourseTeacher.setAbsentCount(absentCount);
                taExamCourseTeacherList.add(taExamCourseTeacher);
            }
            taExamCourseTeacherService.saveBatch(taExamCourseTeacherList);
        }
        return " 't_a_exam_course_teacher'表构建完毕 ";
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public String updateCoursePublishStatus(Long examId, String courseCode, PublishStatusEnum publishStatusEnum) {
        // 可分析有效课程信息
        List<String> effectiveCourseCodeList = tbExamCourseService.findEffectiveByExamId(examId, courseCode);
        List<TBExamCourse> tbExamCourseList = new ArrayList<>();
        for (String effectiveCourseCode : effectiveCourseCodeList) {
            TBExamCourse tbExamCourse = tbExamCourseService.getOne(new QueryWrapper<TBExamCourse>().lambda()
                    .eq(TBExamCourse::getExamId, examId)
                    .eq(TBExamCourse::getCourseCode, effectiveCourseCode));
            tbExamCourse.setPublishStatus(publishStatusEnum);
            tbExamCourseList.add(tbExamCourse);
        }
        tbExamCourseService.updateBatchById(tbExamCourseList);
        return " 't_b_exam_course' 表状态更新完成";
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void dataCalculate(Long examId, String courseCode) throws Exception {
        AnalyzeForReportService analyzeForReportService = SpringContextHolder.getBean(AnalyzeForReportService.class);
        analyzeForReportService.buildAnalyzeExamCourse(examId, courseCode);
        analyzeForReportService.buildAnalyzeExamCourseRecord(examId, courseCode);
        analyzeForReportService.buildAnalyzeExamCourseCollegeInspect(examId, courseCode);
        analyzeForReportService.buildAnalyzeExamCourseClazz(examId, courseCode);
        analyzeForReportService.buildAnalyzePointScoreRate(examId, courseCode);
        analyzeForReportService.buildAnalyzeExamCourseCollegeInspectDio(examId, courseCode);
        analyzeForReportService.buildAnalyzeExamCourseTeacherDio(examId, courseCode);
        analyzeForReportService.buildAnalyzePaperStruct(examId, courseCode);
        analyzeForReportService.buildExamPaperDifficult(examId, courseCode);
        analyzeForReportService.buildExamPaperTeacherDifficult(examId, courseCode);
        analyzeForReportService.buildAnalyzeExamTotal(examId,courseCode);
        analyzeForReportService.buildAnalyzeExamCourseCollegeTeacher(examId, courseCode);
        analyzeForReportService.buildAnalyzeExamCourseTeacher(examId, courseCode);
        analyzeForReportService.buildAnalyzeExamCourseTeacherCollegeDio(examId, courseCode);
        analyzeForReportService.buildAnalyzeExamCourseTeacherCollegeDifficult(examId, courseCode);
        analyzeForReportService.buildAnalyzeCollegePaperStruct(examId, courseCode);
        analyzeForReportService.buildAnalyzeTeacherPaperStruct(examId, courseCode);
        analyzeForReportService.buildAnalyzeTeacherCollegePaperStruct(examId, courseCode);
    }

    @Override
    public void realityForCalculate(Long examId, String courseCode) {
        this.verifyComputing(examId, courseCode);
        this.updateCoursePublishStatus(examId, courseCode, PublishStatusEnum.COMPUTING);
    }

    @Override
    public void publishReport(Long examId, String courseCode, PublishStatusEnum publishStatusEnum) {
        TBExamCourse tbExamCourse = tbExamCourseService.getOne(new QueryWrapper<TBExamCourse>().lambda()
                .eq(TBExamCourse::getExamId, examId)
                .eq(TBExamCourse::getCourseCode, courseCode));
        PublishStatusEnum status = tbExamCourse.getPublishStatus();
        if (publishStatusEnum.equals(PublishStatusEnum.PUBLISH) && status.equals(PublishStatusEnum.UN_PUBLISH)) {
            // 待发布状态 -》 发布
            tbExamCourse.setPublishStatus(publishStatusEnum);
        } else if (publishStatusEnum.equals(PublishStatusEnum.UN_PUBLISH) && status.equals(PublishStatusEnum.PUBLISH)) {
            // 发布状态 -》 撤回
            tbExamCourse.setPublishStatus(publishStatusEnum);
        } else {
            String statusDesc = "未明确的操作";
            if (publishStatusEnum.equals(PublishStatusEnum.PUBLISH)) {
                statusDesc = "发布";
            } else if (publishStatusEnum.equals(PublishStatusEnum.UN_PUBLISH)) {
                statusDesc = "撤回";
            }
            throw ExceptionResultEnum.ERROR.exception("【" + status + "】状态的课程无法进行" + "【" + statusDesc + "】");
        }
        tbExamCourseService.updateById(tbExamCourse);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void normalAssignScore(Long examId, Long schoolId, String courseCode) {
        List<String> courseCodeList = new ArrayList<>();
        courseCodeList.add(courseCode);

        // 数据同步操作
        // 获取当前课程下所有学生考试成绩记录
        List<BasicExamRecordDto> basicExamRecordDtoDatasource = tbExamRecordService.findByExamIdAndCourseCodeS(examId, courseCodeList);
        for (String s : courseCodeList) {
            if (tbExamCourseService.verifyExamCourseCantRun(examId, schoolId, s, basicCourseService.findByCourseCode(s,schoolId).getName())) {
                throw ExceptionResultEnum.ERROR.exception("课程编号[" + s + "]的课程分析数据已测试或发布，不能变更基础数据");
            }
            List<BasicExamRecordDto> basicExamRecordDtoList = basicExamRecordDtoDatasource.stream()
                    .filter(e -> s.equals(e.getCourseCode())).collect(Collectors.toList());
            if (basicExamRecordDtoList.size() > 0) {
                // 删除源数据
                taExamCourseRecordService.remove(new QueryWrapper<TAExamCourseRecord>()
                        .lambda().eq(TAExamCourseRecord::getExamId, examId).eq(TAExamCourseRecord::getCourseCode, s));
                // 迁移数据至't_a_exam_course_record'
                List<TAExamCourseRecord> taExamCourseRecordList = new ArrayList<>();
                for (BasicExamRecordDto basicExamRecordDto : basicExamRecordDtoList) {
                    boolean absent = basicExamRecordDto.getAbsent();
                    // 正常公式赋分操作
                    Long paperId = basicExamRecordDto.getPaperId();
                    TBPaper tbPaper = tbPaperService.getById(paperId);
                    if (Objects.isNull(tbPaper)) {
                        throw ExceptionResultEnum.ERROR.exception("试卷信息数据异常");
                    }
                    BigDecimal fullScore = tbPaper.getTotalScore();
                    BigDecimal myScore = basicExamRecordDto.getTotalScore();
                    BigDecimal coefficient = tbPaper.getCoefficient();
                    BigDecimal assignScore;
                    // 当该试卷的赋分系数不为0时赋分
                    if (coefficient != null && coefficient.compareTo(BigDecimal.ZERO) > 0 && !absent) {
                        assignScore = myScore.add((fullScore.subtract(myScore)).divide(coefficient, 4, RoundingMode.HALF_UP)).setScale(0, RoundingMode.HALF_UP);
                    } else {
                        assignScore = myScore;
                    }
                    TAExamCourseRecord taExamCourseRecord = new TAExamCourseRecord();
                    taExamCourseRecord.setId(SystemConstant.getDbUuid());
                    taExamCourseRecord.setExamRecordId(basicExamRecordDto.getTbExamRecordId());
                    // 数据同步默认赋分成绩为卷面成绩
                    taExamCourseRecord.setSchoolId(tbExamService.getById(examId).getSchoolId());
                    taExamCourseRecord.setAssignedScore(assignScore);
                    taExamCourseRecord.setExamId(examId);
                    taExamCourseRecord.setCourseCode(basicExamRecordDto.getCourseCode());
                    taExamCourseRecord.setPaperId(basicExamRecordDto.getPaperId());
                    taExamCourseRecord.setPaperType(basicExamRecordDto.getPaperType());
                    taExamCourseRecord.setStudentId(basicExamRecordDto.getStudentId());
                    taExamCourseRecord.setStudentCode(basicExamRecordDto.getStudentCode());
                    taExamCourseRecord.setTeacherId(basicExamRecordDto.getTeacherId());
                    taExamCourseRecord.setClazzId(basicExamRecordDto.getClazzId());
                    taExamCourseRecord.setTeachCollegeId(basicExamRecordDto.getTeachCollegeId());
                    taExamCourseRecord.setInspectCollegeId(basicExamRecordDto.getInspectCollegeId());
                    taExamCourseRecord.setMajorId(basicExamRecordDto.getMajorId());
                    taExamCourseRecord.setTotalScore(myScore);
                    taExamCourseRecord.setAbsent(absent);
                    taExamCourseRecord.setStudentCurrent(basicExamRecordDto.getStudentCurrent());
                    taExamCourseRecordList.add(taExamCourseRecord);
                }
                taExamCourseRecordService.saveBatch(taExamCourseRecordList);
            }
        }
    }


    private void verifyComputing(Long examId, String courseCode) {
        List<String> effectiveCourseCodeList = tbExamCourseService.findEffectiveByExamId(examId, courseCode);
        for (String effectiveCourseCode : effectiveCourseCodeList) {
            TBExamCourse tbExamCourse = tbExamCourseService.getOne(new QueryWrapper<TBExamCourse>().lambda()
                    .eq(TBExamCourse::getExamId, examId)
                    .eq(TBExamCourse::getCourseCode, effectiveCourseCode));
            PublishStatusEnum publishStatusEnum = tbExamCourse.getPublishStatus();
            if (publishStatusEnum.equals(PublishStatusEnum.COMPUTING)) {
                throw ExceptionResultEnum.ERROR.exception("计算中的课程无法再计算 课程【" + tbExamCourse.getCourseName() + "】");
            }
        }
    }

    /**
     * 计算百分位等级
     *
     * @param lowCount   低于我的成绩的人数
     * @param sameCount  和我成绩相同的人数
     * @param totalCount 总人数
     * @return 百分位等级
     */
    private int handlePercentGrade(BigDecimal lowCount, BigDecimal sameCount, BigDecimal totalCount) {
        // ((lowCount + sameCount * 0.5) / totalCount) * 100
        BigDecimal percentGrade = (lowCount.add(sameCount.multiply(new BigDecimal("0.5"))))
                .divide(totalCount, 4, RoundingMode.HALF_UP).multiply(new BigDecimal("100"));
        int result = percentGrade.setScale(0, RoundingMode.HALF_UP).intValue();
        if (result == 100) {
            result = 99;
        }
        if (result == 0) {
            result = 1;
        }
        return result;
    }

    /**
     * 处理计算百分等级和难度等级档位
     *
     * @param type  档位类型（百分等级、难度系数）
     * @param value 值
     * @return 档位
     */
    private String handleLevel(Long examId, String courseCode, String type, double value) {
        List<TBCommonLevelConfig> levelList = tbCommonLevelConfigService.list(new QueryWrapper<TBCommonLevelConfig>().lambda()
                .eq(TBCommonLevelConfig::getExamId, examId)
                .eq(TBCommonLevelConfig::getCourseCode, courseCode)
                .eq(TBCommonLevelConfig::getLevelType, type));
        String level = "";
        if ("百分等级".equals(type) || "难度等级".equals(type)) {
            for (TBCommonLevelConfig levelTemp : levelList) {
                Map<String, Object> scopeMap = AnalyzeScopeUtil.analyzeScope(levelTemp.getScope());
                if ("(".equals(scopeMap.get("minSign")) && ")".equals(scopeMap.get("maxSign"))) {
                    if (Double.parseDouble(String.valueOf(scopeMap.get("minValue"))) < value && value < Double.parseDouble(String.valueOf(scopeMap.get("maxValue")))) {
                        level = levelTemp.getInterpret();
                    }
                } else if ("(".equals(scopeMap.get("minSign")) && "]".equals(scopeMap.get("maxSign"))) {
                    if (Double.parseDouble(String.valueOf(scopeMap.get("minValue"))) < value && value <= Double.parseDouble(String.valueOf(scopeMap.get("maxValue")))) {
                        level = levelTemp.getInterpret();
                    }
                } else if ("[".equals(scopeMap.get("minSign")) && ")".equals(scopeMap.get("maxSign"))) {
                    if (Double.parseDouble(String.valueOf(scopeMap.get("minValue"))) <= value && value < Double.parseDouble(String.valueOf(scopeMap.get("maxValue")))) {
                        level = levelTemp.getInterpret();
                    }
                } else if ("[".equals(scopeMap.get("minSign")) && "]".equals(scopeMap.get("maxSign"))) {
                    if (Double.parseDouble(String.valueOf(scopeMap.get("minValue"))) <= value && value <= Double.parseDouble(String.valueOf(scopeMap.get("maxValue")))) {
                        level = levelTemp.getInterpret();
                    }
                }
            }
            if (level == null || level.length() == 0) {
                throw ExceptionResultEnum.ERROR.exception("范围解析异常");
            }
        } else {
            throw ExceptionResultEnum.ERROR.exception("没有进行计算的等级类型 ： " + type);
        }
        return level;
    }

    /**
     * 构建和学院比较的有关信息（超过学院百分比、排名、排名等级）
     *
     * @param taExamCourseRecord     该学生数据
     * @param taExamCourseRecordList 该课程下学生数据
     */
    private void buildColData(TAExamCourseRecord taExamCourseRecord, List<TAExamCourseRecord> taExamCourseRecordList) {

        //查询出该学生所在学院的全体学生在该科目的考试情况
        List<TAExamCourseRecord> examRecordSameCol = taExamCourseRecordList.stream()
                .filter(e -> taExamCourseRecord.getInspectCollegeId().equals(e.getInspectCollegeId())).collect(Collectors.toList()); // 同考查学院考生数据

        //计算超过学院百分比
        double lowCount = examRecordSameCol.stream().filter(e -> e.getAssignedScore().compareTo(taExamCourseRecord.getAssignedScore()) < 0).count();
        BigDecimal overCollegeRate;
        if (examRecordSameCol.size() > 1) {
            overCollegeRate = BigDecimal.valueOf(lowCount).divide(BigDecimal.valueOf(examRecordSameCol.size() - 1), 4, RoundingMode.HALF_UP);
        } else {
            overCollegeRate = BigDecimal.ONE;
        }
        taExamCourseRecord.setOverCollegeRate(overCollegeRate);

        //计算在学院的排名
        double overCount = examRecordSameCol.stream().filter(e -> e.getAssignedScore().compareTo(taExamCourseRecord.getAssignedScore()) > 0).count();
        double myNumber = overCount + 1;
        taExamCourseRecord.setColRank((int) myNumber);

        //计算在学院排名的档次
        double size = examRecordSameCol.size();
        List<TBCommonRankLevelConfig> tbCommonRankLevelConfigList = tbCommonRankLevelConfigService.list(new QueryWrapper<TBCommonRankLevelConfig>().lambda()
                .eq(TBCommonRankLevelConfig::getExamId, taExamCourseRecord.getExamId())
                .eq(TBCommonRankLevelConfig::getCourseCode, taExamCourseRecord.getCourseCode()));


        if (tbCommonRankLevelConfigList.size() < 1) {
            throw ExceptionResultEnum.ERROR.exception("试卷基础信息不匹配");
        }
        String myLevel = "";
        if (size < tbCommonRankLevelConfigList.size()) {
            myLevel = String.valueOf(tbCommonRankLevelConfigList.get((int) (myNumber - 1)).getLevel());
        } else {
            for (TBCommonRankLevelConfig temp : tbCommonRankLevelConfigList) {

                Map<String, Object> scopeMap = AnalyzeScopeUtil.analyzeScope(temp.getScope());
                if ("(".equals(scopeMap.get("minSign")) && ")".equals(scopeMap.get("maxSign"))) {
                    if (Double.parseDouble(String.valueOf(scopeMap.get("minValue"))) * size < myNumber && myNumber < Double.parseDouble(String.valueOf(scopeMap.get("maxValue"))) * size) {
                        myLevel = temp.getLevel();
                    }
                } else if ("(".equals(scopeMap.get("minSign")) && "]".equals(scopeMap.get("maxSign"))) {
                    if (Double.parseDouble(String.valueOf(scopeMap.get("minValue"))) * size < myNumber && myNumber <= Double.parseDouble(String.valueOf(scopeMap.get("maxValue"))) * size) {
                        myLevel = temp.getLevel();
                    }
                } else if ("[".equals(scopeMap.get("minSign")) && ")".equals(scopeMap.get("maxSign"))) {
                    if (Double.parseDouble(String.valueOf(scopeMap.get("minValue"))) * size <= myNumber && myNumber < Double.parseDouble(String.valueOf(scopeMap.get("maxValue"))) * size) {
                        myLevel = temp.getLevel();
                    }
                } else if ("[".equals(scopeMap.get("minSign")) && "]".equals(scopeMap.get("maxSign"))) {
                    if (Double.parseDouble(String.valueOf(scopeMap.get("minValue"))) * size <= myNumber && myNumber <= Double.parseDouble(String.valueOf(scopeMap.get("maxValue"))) * size) {
                        myLevel = temp.getLevel();
                    }
                }
            }
        }
        if (myLevel == null || myLevel.length() == 0) {
            throw ExceptionResultEnum.ERROR.exception("范围解析异常");
        }
        taExamCourseRecord.setRankLevel(myLevel);
    }

    /**
     * 计算每个考查点所对应的该考试所有题目信息集合（如果要仅记录本次考试匹配到的考查点，那么要判断只有当paperList.size() > 0的结果才put进Map键值对）
     * 通过模块枚举类进行匹配，可以在枚举类横向扩展维度但要和paper表结构对应
     *
     * @param dimensionDatasource 知识点数据源
     * @param tbPaperStructList   试卷结构数据源
     * @param examId              考试id
     * @param courseCode          课程编号
     * @return 键值对 （类型-考查点 -> 考查此考查点的题目信息集合） 例如 ：”知识模块-A“，List<>
     */
    private Map<String, List<TBPaperStruct>> handlePointToPaper(List<TBDimension> dimensionDatasource, List<TBPaperStruct> tbPaperStructList, Long examId, String courseCode) throws NoSuchFieldException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        Map<String, List<TBPaperStruct>> pointToPaper = new HashMap<>();

        // 模块配置信息
        List<TBModuleConfig> tbModuleConfigList = tbModuleConfigService.findDistinctModuleInfoByExamIdAndCourseCode(examId, courseCode);
        if (tbModuleConfigList.size() < 1) {
            throw ExceptionResultEnum.ERROR.exception("基础模块信息异常");
        }

        for (TBModuleConfig value : tbModuleConfigList) {

            //每个考查点所对应的题目集合
            List<TBDimension> pointList = dimensionDatasource
                    .stream().filter(e -> value.getModuleType().equals(e.getDimensionType())).collect(Collectors.toList());  //对应某个模块的考查点集合

            Set<String> keysOne = pointList.stream().map(TBDimension::getCodePrimary).collect(Collectors.toSet());   //考查点一级维度不重复的code集合
            Set<String> keysTwo = pointList.stream().map(TBDimension::getCodeSecond).collect(Collectors.toSet());   //考查点二级维度不重复的code集合

            for (String tmpOne : keysOne) {
                List<TBPaperStruct> paperStructList = new ArrayList<>();
                for (TBPaperStruct paperStruct : tbPaperStructList) {
                    Field field = paperStruct.getClass().getDeclaredField(value.getAttribute()); //获取该模块对应试卷结构中的属性
                    Method getMethod = paperStruct.getClass().getDeclaredMethod("get" + ConversionUtils.initCap(field.getName())); //获取该属性的get方法
                    String dimensions = (String) getMethod.invoke(paperStruct); //调用该属性的get方法获取改题目的考查点
                    if (dimensions != null && dimensions.length() > 0) {
                        if (dimensions.contains(tmpOne)) {
                            paperStructList.add(paperStruct);  //如果该题目包含考查点，则记录该题目
                        }
                    }
                }
                if (paperStructList.size() > 0) {
                    // 只记录试卷结构中出现的考查点包含的题目
                    pointToPaper.put(value.getModuleType() + "-" + tmpOne, paperStructList);
                }
            }

            for (String tmpTwo : keysTwo) {
                List<TBPaperStruct> paperStructList = new ArrayList<>();
                for (TBPaperStruct paperStruct : tbPaperStructList) {
                    Field field = paperStruct.getClass().getDeclaredField(value.getAttribute());
                    Method getMethod = paperStruct.getClass().getDeclaredMethod("get" + ConversionUtils.initCap(field.getName()));
                    String dimensions = (String) getMethod.invoke(paperStruct);
                    if (dimensions != null && dimensions.length() > 0) {
                        if (Arrays.asList(dimensions.split(",")).contains(tmpTwo)) {
                            paperStructList.add(paperStruct);
                        }
                    }
                }
                if (paperStructList.size() > 0) {
                    // 只记录试卷结构中出现的考查点包含的题目
                    pointToPaper.put(value.getModuleType() + "-" + tmpTwo, paperStructList);
                }
            }
        }
        return pointToPaper;
    }

    /**
     * 计算每个考查模块对应的题目集合
     *
     * @param dimensionDatasource 知识点数据源
     * @param tbPaperStructList   试卷结构数据源
     * @param examId              考试id
     * @param courseCode          课程编号
     * @return 键值对 （考查模块 -> 考查此考模块的题目信息集合） 例如 ：”知识模块“，List<>
     * @throws Exception 反射异常
     */
    private Map<String, List<TBPaperStruct>> handleModuleToPaper(List<TBDimension> dimensionDatasource, List<TBPaperStruct> tbPaperStructList, Long examId, String courseCode) throws Exception {
        Map<String, List<TBPaperStruct>> result = new HashMap<>();

        // 模块配置信息
        List<TBModuleConfig> tbModuleConfigList = tbModuleConfigService.findDistinctModuleInfoByExamIdAndCourseCode(examId, courseCode);
        if (tbModuleConfigList.size() < 1) {
            throw ExceptionResultEnum.ERROR.exception("基础模块信息异常");
        }

        List<String> realityTypes = dimensionDatasource.stream().map(TBDimension::getDimensionType).collect(Collectors.toList()); // 以知识点表中的模块类型为准
//        int tmp = 0;
        for (TBModuleConfig module : tbModuleConfigList) {
            String moduleType = module.getModuleType(); // 模块名称
            if (realityTypes.contains(moduleType)) {
//                tmp++;
                String attribute = module.getAttribute(); // 对应paper表列名称
                List<TBPaperStruct> paperStructList = new ArrayList<>();

                for (TBPaperStruct paperStruct : tbPaperStructList) {
                    Field field = paperStruct.getClass().getDeclaredField(attribute);
                    Method getMethod = paperStruct.getClass().getDeclaredMethod("get" + ConversionUtils.initCap(field.getName()));
                    String value = (String) getMethod.invoke(paperStruct);
                    if (value != null && value.length() != 0) {
                        paperStructList.add(paperStruct);
                    }
                }
                result.put(moduleType, paperStructList);
            }
        }
        return result;
    }

    /**
     * 计算每个模块或考查点在该考试中的分数
     * （其实就是计算试题集合总分）
     *
     * @param questionMap 考查点或模块对应的题目信息集合
     * @return 键值对 （考查点 -> 该考查点在此次考试所占分数） 例如 ：”知识模块-A“，46.0000、（模块 -> 该考查点在此次考试所占分数） 例如 ：”能力模块“，75.0000
     */
    private Map<String, Object> handleEveryPointTotalScore(Map<String, List<TBPaperStruct>> questionMap) {
        Map<String, Object> result = new HashMap<>();
        for (String s : questionMap.keySet()) {
            List<TBPaperStruct> paperList = questionMap.get(s);
            double totalScore = paperList.stream().collect(Collectors.summarizingDouble(e -> e.getFullScore().doubleValue())).getSum();
            result.put(s, totalScore);
        }
        return result;
    }

    /**
     * 根据考查点得分率计算该考查点的熟练度
     *
     * @param examId        考试id
     * @param courseCode    课程编号
     * @param dimensionType 考查点类型
     * @param value         得分率
     * @return 熟练度等级
     */
    private String handleModuleProficiency(Long examId, String courseCode, String dimensionType, double value) {
        List<TBModuleProficiency> tbModuleProficiencyList = tbModuleProficiencyService.list(new QueryWrapper<TBModuleProficiency>().lambda()
                .eq(TBModuleProficiency::getExamId, examId)
                .eq(TBModuleProficiency::getCourseCode, courseCode)
                .eq(TBModuleProficiency::getModuleType, dimensionType));

        if (tbModuleProficiencyList.size() < 1) {
            throw ExceptionResultEnum.ERROR.exception("模块二级维度熟练度配置信息不存在");
        }
        String level = "";
        for (TBModuleProficiency tbModuleProficiency : tbModuleProficiencyList) {
            if (tbModuleProficiency.getScope() == null) {
                continue;
            }
            Map<String, Object> scopeMap = AnalyzeScopeUtil.analyzeScope(tbModuleProficiency.getScope());
            if ("(".equals(scopeMap.get("minSign")) && ")".equals(scopeMap.get("maxSign"))) {
                if (Double.parseDouble(String.valueOf(scopeMap.get("minValue"))) < value && value < Double.parseDouble(String.valueOf(scopeMap.get("maxValue")))) {
                    level = tbModuleProficiency.getLevel();
                }
            } else if ("(".equals(scopeMap.get("minSign")) && "]".equals(scopeMap.get("maxSign"))) {
                if (Double.parseDouble(String.valueOf(scopeMap.get("minValue"))) < value && value <= Double.parseDouble(String.valueOf(scopeMap.get("maxValue")))) {
                    level = tbModuleProficiency.getLevel();
                }
            } else if ("[".equals(scopeMap.get("minSign")) && ")".equals(scopeMap.get("maxSign"))) {
                if (Double.parseDouble(String.valueOf(scopeMap.get("minValue"))) <= value && value < Double.parseDouble(String.valueOf(scopeMap.get("maxValue")))) {
                    level = tbModuleProficiency.getLevel();
                }
            } else if ("[".equals(scopeMap.get("minSign")) && "]".equals(scopeMap.get("maxSign"))) {
                if (Double.parseDouble(String.valueOf(scopeMap.get("minValue"))) <= value && value <= Double.parseDouble(String.valueOf(scopeMap.get("maxValue")))) {
                    level = tbModuleProficiency.getLevel();
                }
            }
        }
        return level;
    }

    /**
     * 处理学生在该模块成绩在该学院的排名等级
     *
     * @param examId     考试id
     * @param courseCode 考试编号
     * @param module     模块类型
     * @param value      值（排名、得分率、百分等级）
     * @param size       该学院最低分排名（当其不为排名时，赋值-1）
     * @return 排名等级编号
     */
    private String handleModuleRankLevel(Long examId, String courseCode, String module, double value, double size) {
        List<TBModuleConfig> tbModuleConfigList = tbModuleConfigService.list(new QueryWrapper<TBModuleConfig>().lambda()
                .eq(TBModuleConfig::getExamId, examId)
                .eq(TBModuleConfig::getCourseCode, courseCode)
                .eq(TBModuleConfig::getModuleType, module));

        String result = null;
        if (size < tbModuleConfigList.size() && size > 0) {
            tbModuleConfigList = tbModuleConfigList.stream()
                    .sorted((o1, o2) -> o1.getLevelCode().compareToIgnoreCase(o2.getLevelCode()))
                    .collect(Collectors.toList());
            result = tbModuleConfigList.get((int) (size - 1)).getLevelCode();
        } else {
            if (size < 0) {
                size = -size;
            }
            for (TBModuleConfig tbModuleConfig : tbModuleConfigList) {
                Map<String, Object> scopeMap = AnalyzeScopeUtil.analyzeScope(tbModuleConfig.getScope());
                if ("(".equals(scopeMap.get("minSign")) && ")".equals(scopeMap.get("maxSign"))) {
                    if (Double.parseDouble(String.valueOf(scopeMap.get("minValue"))) * size < value && value < Double.parseDouble(String.valueOf(scopeMap.get("maxValue"))) * size) {
                        result = tbModuleConfig.getLevelCode();
                    }
                } else if ("(".equals(scopeMap.get("minSign")) && "]".equals(scopeMap.get("maxSign"))) {
                    if (Double.parseDouble(String.valueOf(scopeMap.get("minValue"))) * size < value && value <= Double.parseDouble(String.valueOf(scopeMap.get("maxValue"))) * size) {
                        result = tbModuleConfig.getLevelCode();
                    }
                } else if ("[".equals(scopeMap.get("minSign")) && ")".equals(scopeMap.get("maxSign"))) {
                    if (Double.parseDouble(String.valueOf(scopeMap.get("minValue"))) * size <= value && value < Double.parseDouble(String.valueOf(scopeMap.get("maxValue"))) * size) {
                        result = tbModuleConfig.getLevelCode();
                    }
                } else if ("[".equals(scopeMap.get("minSign")) && "]".equals(scopeMap.get("maxSign"))) {
                    if (Double.parseDouble(String.valueOf(scopeMap.get("minValue"))) * size <= value && value <= Double.parseDouble(String.valueOf(scopeMap.get("maxValue"))) * size) {
                        result = tbModuleConfig.getLevelCode();
                    }
                }
            }
        }
        if (result == null || result.length() == 0) {
            throw ExceptionResultEnum.ERROR.exception("范围解析异常");
        }
        return result;
    }

    /**
     * 根据得分率计算每道题目的难度
     *
     * @param examId     考试id
     * @param courseCode 课程编号
     * @param scoreRate  题目得分率
     * @return 难度
     */
    private String analyzeDifficult(Long examId, String courseCode, double scoreRate) {
        List<TBCommonLevelConfig> levelConfigList = tbCommonLevelConfigService.list(new QueryWrapper<TBCommonLevelConfig>().lambda()
                .eq(TBCommonLevelConfig::getExamId, examId)
                .eq(TBCommonLevelConfig::getCourseCode, courseCode)
                .eq(TBCommonLevelConfig::getLevelType, "难度等级"));
        String difficult = "";
        for (TBCommonLevelConfig levelConfig : levelConfigList) {
            Map<String, Object> scopeMap = AnalyzeScopeUtil.analyzeScope(levelConfig.getScope());
            String minSign = String.valueOf(scopeMap.get("minSign"));
            String maxSign = String.valueOf(scopeMap.get("maxSign"));
            double minValue = Double.parseDouble(String.valueOf(scopeMap.get("minValue")));
            double maxValue = Double.parseDouble(String.valueOf(scopeMap.get("maxValue")));
            if ("(".equals(minSign) && ")".equals(maxSign)) {
                if (minValue < scoreRate && scoreRate < maxValue) {
                    difficult = levelConfig.getInterpret();
                }
            } else if ("(".equals(minSign) && "]".equals(maxSign)) {
                if (minValue < scoreRate && scoreRate <= maxValue) {
                    difficult = levelConfig.getInterpret();
                }
            } else if ("[".equals(minSign) && ")".equals(maxSign)) {
                if (minValue <= scoreRate && scoreRate < maxValue) {
                    difficult = levelConfig.getInterpret();
                }
            } else if ("[".equals(minSign) && "]".equals(maxSign)) {
                if (minValue <= scoreRate && scoreRate <= maxValue) {
                    difficult = levelConfig.getInterpret();
                }
            }
        }
        if (difficult == null || difficult.length() < 1) {
            difficult = "容易";
        }
        return difficult;
    }

    /**
     * 计算某个小题的题目鉴别度
     *
     * @param oneQuestionAnswerDetailList 某个小题的所有参考学生作答情况列表（且按照参考学生百分等级降序排列）
     * @param fullScore                   该小题总分
     * @return 鉴别度
     */
    private double calculateValidity(List<ValidAnswerDetailDto> oneQuestionAnswerDetailList, double fullScore) {
        List<ValidAnswerDetailDto> sortList = oneQuestionAnswerDetailList.stream().sorted(((o1, o2) -> {
            double compare1 = o1.getPercentGrade();
            double compare2 = o2.getPercentGrade();
            return Double.compare(compare2, compare1);
        })).collect(Collectors.toList());

        int rank = 0;
        int number = 0;
        double value = 10000;
        for (ValidAnswerDetailDto temp : sortList) {
            double compareValue = temp.getPercentGrade();
            number++;
            if (compareValue < value) {
                rank = number;
                value = compareValue;
            }
            temp.setRank(rank);
        }
        if (sortList.size() == 0) {
            System.out.println("异常");
        }
        double endRank = sortList.get(sortList.size() - 1).getRank();
        double topRank = ValidityEnum.VALIDITY_FOR_RANK.getTopLimitPercent() * endRank;
        double lowRank = ValidityEnum.VALIDITY_FOR_RANK.getLowLimitPercent() * endRank;

        // 计算题目效度
        double topScopeAvgScoreRate = sortList.stream()
                .filter(e -> topRank >= e.getRank())
                .collect(Collectors.summarizingDouble(e -> e.getScore().doubleValue()))
                .getAverage() / fullScore; // 优秀部分统计有效区间平均得分率

        double lowScopeAvgScoreRate = sortList.stream()
                .filter(e -> lowRank <= e.getRank())
                .collect(Collectors.summarizingDouble(e -> e.getScore().doubleValue()))
                .getAverage() / fullScore; // 较差部分统计有效区间平均得分率

        return topScopeAvgScoreRate - lowScopeAvgScoreRate;
    }
}
