package cn.teammodel.controller.admin.service.impl;

import cn.teammodel.common.ErrorCode;
import cn.teammodel.common.PK;
import cn.teammodel.config.exception.ServiceException;
import cn.teammodel.controller.admin.service.CommonService;
import cn.teammodel.controller.admin.service.MoralEducationService;
import cn.teammodel.model.dto.admin.Moral.MoralDto;
import cn.teammodel.model.dto.admin.common.GCDto;
import cn.teammodel.model.dto.admin.common.GroupDto;
import cn.teammodel.model.dto.admin.common.RGroupList;
import cn.teammodel.model.dto.admin.common.RMember;
import cn.teammodel.model.dto.admin.labor.FindDto;
import cn.teammodel.model.dto.admin.labor.LaborDto;
import cn.teammodel.model.entity.appraise.Appraise;
import cn.teammodel.model.entity.appraise.AppraiseTreeNode;
import cn.teammodel.model.entity.common.Exam;
import cn.teammodel.model.entity.common.ExamClassResult;
import cn.teammodel.model.entity.school.ClassInfo;
import cn.teammodel.model.entity.school.LessonRecord;
import cn.teammodel.model.entity.school.School;
import cn.teammodel.model.vo.Common.ExamVo;
import cn.teammodel.model.vo.admin.GradeAndClassVo;
import cn.teammodel.model.vo.appraise.RecordVo;
import cn.teammodel.repository.*;
import cn.teammodel.security.utils.SecurityUtil;
import cn.teammodel.service.impl.EvaluationServiceImpl;
import cn.teammodel.test.LessonRecordQueryService;
import cn.teammodel.utils.GroupUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import lombok.AllArgsConstructor;
import lombok.Data;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;
import java.util.concurrent.ExecutionException;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

@Service
public class MoralEducationServiceImpl implements MoralEducationService {

    @Resource
    private LessonRecordRepository lessonRecordRepository;
    @Resource
    private ClassRepository classRepository;
    @Resource
    private AppraiseRecordRepository appraiseRecordRepository;
    @Resource
    private ExamRepository examRepository;
    @Resource
    private ExamClassResultRepository examClassResultRepository;
    @Resource
    private AppraiseRepository appraiseRepository;
    @Resource
    private EvaluationServiceImpl evaluationService;
    @Resource
    private SchoolRepository schoolRepository;
    @Resource
    private CommonService commonService;

    private static Environment environment; // 静态字段
    @Autowired
    private Environment env; // 非静态字段

    @PostConstruct
    public void init() {
        MoralEducationServiceImpl.environment = env; // 在初始化时将非静态字段赋值给静态字段
    }
    @Override
    public Map<String, Object> getAnalysis(MoralDto moralDto, HttpServletRequest request) {

        //根据具体参数查询相关课列内容
        List<LessonRecord> records;
        LessonRecordQueryService queryService = new LessonRecordQueryService(lessonRecordRepository);
        String schoolId = SecurityUtil.getLoginUser().getSchoolId();
        String lessonRecordKey = String.format(PK.PK_LESSON_RECORD, moralDto.getCode());
        Long startTime = moralDto.getStartTime();
        Long endTime = moralDto.getEndTime();
        String subjectId = moralDto.getSubjectId();
        //String tmdId = moralDto.getTmdId();
        String grade = moralDto.getGrade();
        String periodId = moralDto.getPeriodId();
        String academicYearId = moralDto.getAcademicYearId();
        try {

            records = queryService.queryLessonsInParallel(
                    lessonRecordKey, startTime, endTime, subjectId, null, grade, periodId
            );
            // 获取当前月份的起始时间和结束时间
            Calendar calendar = Calendar.getInstance();
            calendar.set(Calendar.DAY_OF_MONTH, 1);
            calendar.set(Calendar.HOUR_OF_DAY, 0);
            calendar.set(Calendar.MINUTE, 0);
            calendar.set(Calendar.SECOND, 0);
            calendar.set(Calendar.MILLISECOND, 0);
            long startOfMonth = calendar.getTimeInMillis();

            calendar.add(Calendar.MONTH, 1);
            calendar.add(Calendar.MILLISECOND, -1);
            long endOfMonth = calendar.getTimeInMillis();

            // 筛选出本月的数据量
            int currentRecordsCount = records.stream()
                    .filter(record -> record.getStartTime() >= startOfMonth && record.getStartTime() <= endOfMonth)
                    .mapToInt(record -> 1)
                    .sum();

        } catch (InterruptedException | ExecutionException e) {
            throw new ServiceException(ErrorCode.SYSTEM_ERROR.getCode(), "数据查询异常");
        } finally {
            queryService.shutdown();
        }
        //总评价数
        List<ClassInfo> classes = classRepository.findClassBySchoolIdAndPeriodId(moralDto.getPeriodId(), String.format(PK.CLASS, schoolId));
        if (classes.isEmpty()) {
            throw new ServiceException(ErrorCode.SYSTEM_ERROR.getCode(), "暂无班级");
        }
        List<String> classIds = classes.stream().map(ClassInfo::getId).collect(Collectors.toList());
        List<RecordVo> res = appraiseRecordRepository.latestRecords(
                String.format(PK.PK_APPRAISE_RECORD, schoolId),
                academicYearId,
                startTime,
                endTime,
                "劳育",
                classIds
        );
        //表扬的次数
        int rightCount = (int) res.stream().filter(RecordVo::isPraise).count();
        //批评的次数
        int wrongCount = (int) res.stream().filter(record -> !record.isPraise()).count();
        //已经评价的学生人数
        long uniqueTargetIdCount = res.stream()
                .map(RecordVo::getTargetId)
                .filter(Objects::nonNull) // 过滤掉 null 值
                .distinct()
                .count();

        List<String> recordIds = new ArrayList<>();
        for (LessonRecord record : records) {
            recordIds.add(record.getId());
        }
        //examIds.add("c26e5766-597f-45b3-91ad-19e76426323b");
        //获取所有课程下的课中活动
        List<ExamVo> exams = new ArrayList<>();
        if (!recordIds.isEmpty()) {
            exams = examRepository.findExamsByIds(moralDto.getSource(),recordIds);
            exams = exams.stream()
                    .filter(exam -> !exam.getClasses().isEmpty())
                    .collect(Collectors.toList());
        }
        Map<String, List<List<String>>> knowledgeMap = new HashMap<>();
        Map<String, List<Double>> point = new HashMap<>();
        List<String> examIds = new ArrayList<>();
        for (ExamVo exam : exams) {
            examIds.add(exam.getId());
            String lessonRecordId = exam.getLessonRecordId(); // 获取 lessonRecordId
            Optional<LessonRecord> recordOptional = records.stream()
                    .filter(record -> record.getId().equals(lessonRecordId))
                    .findFirst();
            if (recordOptional.isPresent()) {
                LessonRecord record = recordOptional.get();
                exam.setRecordName(record.getName()); // 设置 recordName
            }
            if (exam.getPapers() != null) {
                if (exam.getPapers().get(0).getKnowledge() != null)
                {
                    knowledgeMap.put(exam.getId(), exam.getPapers().get(0).getKnowledge());
                    point.put(exam.getId(), exam.getPapers().get(0).getPoint());
                }
            }
        }
        List<ExamClassResult> examResults = new ArrayList<>();
        if (!examIds.isEmpty()) {
            examResults = examClassResultRepository.findAll(String.format(PK.CLASS_RESULT, moralDto.getCode()),examIds);
        }
        //获取学校基础信息
        List<School.Period> period = schoolRepository.findPeriodById(schoolId,periodId);

        List<GradeAndClassVo> gradeAndClassVos = commonService.getGradeAndClass(new GCDto(schoolId, periodId));
        Map<String, Object> resMap = new HashMap<>();
        //处理劳育知识块和知识点的关联关系
        resMap.put("exams",exams);//评测明细
        resMap.put("subjectiveCount", res.size()); //主观评价数
        resMap.put("examCount", exams.size());//评测数量
        resMap.put("lessonCount", records.size());//班会课数量
        resMap.put("rightCount", rightCount);//表扬评价数
        resMap.put("wrongCount", wrongCount);//待改进评价数
        resMap.put("uniqueTargetIdCount", uniqueTargetIdCount);//评价学生数
        Appraise appraise = appraiseRepository.findAppraiseBySchoolIdAndPeriodIdAndCode(schoolId, periodId, PK.PK_APPRAISE);
        if (appraise != null) {
            appraise = evaluationService.buildTree(appraise);
            Map<String, List<String>> knowledgeBlockToPointsMap = getKnowledgeBlockToPointsMap(appraise);
            Map<String, Object> classScoreRate = new HashMap<>();
            Map<String, Object> gradeScoreRate = new HashMap<>();
            if (moralDto.getClassId() != null) {
                classScoreRate =  calculateKnowledgeScoreRateForClass(moralDto.getClassId(), examResults, knowledgeMap, appraise, point,res,request);
            }
            if (moralDto.getGrade() != null) {
                gradeScoreRate = calculateKnowledgeScoreForGrade(moralDto.getGrade(), examResults, knowledgeMap,appraise, point,res,gradeAndClassVos,request);
            }
            Map<String,Object> schoolScoreRate = calculateKnowledgeScoreForSchool(examResults, knowledgeMap,appraise, point,res,period,gradeAndClassVos,request);
            resMap.put("gradeScoreRate", gradeScoreRate);
            resMap.put("classScoreRate", classScoreRate);
            resMap.put("schoolScoreRate", schoolScoreRate);
            List<Map<String, Object>>  scores = calculateScoresWithDetails(res, appraise, request);
            List<Map<String, Object>> students = combineScoresWithExamResults(scores,examResults,knowledgeMap,point,knowledgeBlockToPointsMap);
            resMap.put("scores", students);
        }
        //处理主观评价内容
        return resMap;

    }

    @Override
    public Map<String, Object> getDetails(FindDto findDto, HttpServletRequest request) {
        Map<String, Object> resMap = new HashMap<>();
        List<Exam> exams;
        List<RecordVo> res;
        try {
            exams = examRepository.findExamByClassId(String.format(PK.EXAM, findDto.getTmdId()), findDto.getClassId(), findDto.getPeriodId(), findDto.getSubjectId());
            res= appraiseRecordRepository.getRecords(String.format(PK.PK_APPRAISE_RECORD, findDto.getCode()),findDto.getAcademicYearId(), findDto.getClassId(), findDto.getStudentId(),"劳育");
            resMap.put("exams",exams);
            resMap.put("res", res);
        }catch (Exception e){
            throw new ServiceException(ErrorCode.SYSTEM_ERROR.getCode(), "数据查询异常");
        }
        return resMap;
    }
    @Override
    public Map<String, Object> getExamDetails(MoralDto moralDto, HttpServletRequest request) {
        Map<String, Object> resMap = new HashMap<>();
        try {
            List<ExamClassResult> examResults = new ArrayList<>();
            if (!moralDto.getExamId().isEmpty()) {
                Map<String, List<List<String>>> knowledgeMap = new HashMap<>();
                Map<String, List<Double>> points = new HashMap<>();

                // 1. 查询考试信息
                Exam exam = examRepository.findExamById(String.format(PK.EXAM, moralDto.getTmdId()), moralDto.getExamId()).get(0);
                if (exam.getPapers() != null && !exam.getPapers().isEmpty()) {
                    knowledgeMap.put(exam.getId(), exam.getPapers().get(0).getKnowledge());
                    points.put(exam.getId(), exam.getPapers().get(0).getPoint());
                }

                // 2. 查询考试结果
                examResults = examClassResultRepository.findById(
                        String.format(PK.CLASS_RESULT, moralDto.getCode()),
                        moralDto.getClassId(),
                        moralDto.getExamId()
                );

                // 3. 查询知识块-知识点映射关系
                Appraise appraise = appraiseRepository.findAppraiseBySchoolIdAndPeriodIdAndCode(
                        moralDto.getCode(),
                        moralDto.getPeriodId(),
                        PK.PK_APPRAISE
                );
                appraise = evaluationService.buildTree(appraise);
                Map<String, List<String>> knowledgeBlockToPointsMap = getKnowledgeBlockToPointsMap(appraise);

                // 4. 计算每个知识点的得分（调用 calculateStudentScoreRates）
                Map<String, Double> knowledgeTotalScore = new HashMap<>();
                if (!examResults.isEmpty()) {
                    // 假设计算所有学生的平均分（或指定某个学生）
                    String studentId = moralDto.getStudentId(); // 如果传入了学生ID
                    calculateStudentScoreRates(studentId, examResults, knowledgeMap, points, knowledgeTotalScore);
                } else {
                    // 如果没有考试数据，默认所有知识点60分
                    knowledgeMap.values().stream()
                            .flatMap(List::stream)
                            .flatMap(List::stream)
                            .forEach(knowledge -> knowledgeTotalScore.put(knowledge, 60.0));
                }

                // 5. 按知识块分组，计算每个知识块下知识点的得分
                List<Map<String, Object>> knowledgeBlockScores = new ArrayList<>();
                for (Map.Entry<String, List<String>> entry : knowledgeBlockToPointsMap.entrySet()) {
                    String blockName = entry.getKey();
                    List<String> knowledgePoints = entry.getValue();

                    List<Map<String, Object>> pointScores = new ArrayList<>();
                    for (String point : knowledgePoints) {
                        double score = knowledgeTotalScore.getOrDefault(point, 60.0); // 默认60分
                        pointScores.add(new HashMap<String, Object>() {{
                            put("name", point);
                            put("score", score);
                        }});
                    }
                    knowledgeBlockScores.add(new HashMap<String, Object>() {{
                        put("name", blockName);
                        put("children", pointScores);
                    }});
                }

                resMap.put("data", knowledgeBlockScores);
            }
        } catch (Exception e) {
            throw new ServiceException(ErrorCode.SYSTEM_ERROR.getCode(), "数据查询异常");
        }
        return resMap;
    }

    public List<Map<String, Object>> combineScoresWithExamResults(
            List<Map<String, Object>> scores,
            List<ExamClassResult> examResults,
            Map<String, List<List<String>>> knowledgeMap,
            Map<String, List<Double>> points,
            Map<String, List<String>> knowledgeBlockToPointsMap) {

        // 1. 计算每个学生的知识点得分
        Map<String, Map<String, Double>> studentKnowledgePointScores = new HashMap<>();
        for (Map<String, Object> studentResult : scores) {
            String studentId = (String) studentResult.get("studentId");

            // 初始化知识点总分
            Map<String, Double> knowledgeTotalScore = new HashMap<>();

            // 计算当前学生的知识点得分
            calculateStudentScoreRates(studentId, examResults, knowledgeMap, points, knowledgeTotalScore);

            // 将知识点得分存储到 studentKnowledgePointScores 中
            studentKnowledgePointScores.put(studentId, knowledgeTotalScore);
        }

        // 2. 将知识点得分汇总到知识块级别
        Map<String, Map<String, Double>> studentKnowledgeBlockScores = getStringMapMap(knowledgeBlockToPointsMap, studentKnowledgePointScores);

        // 3. 更新现有的 scores 返回数据
        for (Map<String, Object> studentResult : scores) {
            String studentId = (String) studentResult.get("studentId");
            Map<String, Integer> subjectiveScores = (Map<String, Integer>) studentResult.get("scores");

            // 查找该学生的知识块客观成绩
            Map<String, Double> knowledgeBlockScores = studentKnowledgeBlockScores.get(studentId);

            // 初始化主观总分和客观总分
            double subjectiveTotal = 0.0;
            double objectiveTotal = 0.0;
            int knowledgeBlockCount = knowledgeBlockScores.size();

            // 更新主观成绩，计算主观总分和客观总分
            Map<String, Object> combinedScores = new HashMap<>();
            for (Map.Entry<String, Integer> entry : subjectiveScores.entrySet()) {
                double score = 0;
                String knowledgeBlock = entry.getKey();
                int count = entry.getValue(); // 次数
                // 确保 count 不小于0
                if (count < 0) {
                    count = 0;
                }
                double maxCount = 50.0; // 调整此参数控制分数增长速率

                // 使用反比例函数计算加分
                double additionalScore = 40.0 * ((double) count / (count + maxCount));
                double convertedScore = 60.0 + additionalScore;

                // 保留两位小数
                convertedScore = Double.parseDouble(String.format("%.2f", convertedScore));
                subjectiveTotal += convertedScore;

                // 获取对应知识块的客观成绩，并转换为基于60分加分的分数
                double objectiveScore = knowledgeBlockScores.get(knowledgeBlock);
                // 确保不超过100分
                objectiveScore = Math.min(100.0, objectiveScore);
                // 保留两位小数
                objectiveScore = Double.parseDouble(String.format("%.2f", objectiveScore));
                objectiveTotal += objectiveScore;

                // 计算综合得分（主观占60%，客观占40%）
                score = convertedScore * 0.6 + objectiveScore * 0.4;
                score = Double.parseDouble(String.format("%.2f", score));

                // 存储结果
                double finalConvertedScore = convertedScore;
                double finalObjectiveScore = objectiveScore;
                double finalScore = score;
                combinedScores.put(knowledgeBlock, new HashMap<String, Object>() {{
                    put("count", finalConvertedScore);
                    put("objectiveScore", finalObjectiveScore);
                    put("compositeScore", finalScore);
                }});
            }

            // 计算客观平均分
            double objectiveAverage = (knowledgeBlockCount > 0) ? objectiveTotal / knowledgeBlockCount : 0.0;
            objectiveAverage = Double.parseDouble(String.format("%.2f", objectiveAverage));

            // 计算主观平均分
            double subjectiveAverage = (subjectiveTotal > 0) ? subjectiveTotal / knowledgeBlockCount : 0.0;
            subjectiveAverage = Double.parseDouble(String.format("%.2f", subjectiveAverage));

            // 计算综合得分（主观占60%，客观占40%）
            double compositeScore = (subjectiveAverage * 0.6) + (objectiveAverage * 0.4);
            compositeScore = Double.parseDouble(String.format("%.2f", compositeScore));

            // 更新返回数据
            studentResult.put("scores", combinedScores);
            studentResult.put("subjectiveTotal", subjectiveAverage);
            studentResult.put("objectiveTotal", objectiveAverage);
            studentResult.put("compositeScore", compositeScore);
        }

        return scores;
    }

    private static Map<String, Map<String, Double>> getStringMapMap(
            Map<String, List<String>> knowledgeBlockToPointsMap,
            Map<String, Map<String, Double>> studentKnowledgePointScores) {

        Map<String, Map<String, Double>> studentKnowledgeBlockScores = new HashMap<>();
        for (Map.Entry<String, Map<String, Double>> entry : studentKnowledgePointScores.entrySet()) {
            String studentId = entry.getKey();
            Map<String, Double> pointScores = entry.getValue();
            Map<String, Double> blockScores = studentKnowledgeBlockScores.computeIfAbsent(studentId, k -> new HashMap<>());

            for (Map.Entry<String, List<String>> blockEntry : knowledgeBlockToPointsMap.entrySet()) {
                String knowledgeBlock = blockEntry.getKey();
                List<String> knowledgePoints = blockEntry.getValue();

                double totalScore = 0.0;
                int validPointCount = 0;
                for (String knowledgePoint : knowledgePoints) {
                    if (pointScores.containsKey(knowledgePoint)) {
                        totalScore += pointScores.get(knowledgePoint);
                        validPointCount++;
                    }
                }

                // 关键修改：统一分数转换逻辑
                double averageScore = (validPointCount > 0) ? totalScore / validPointCount : 0.0; // 原始正确率
                double correctRate = averageScore / 100.0;
                double convertedScore = 60.0 + (correctRate * 40.0);
                convertedScore = Math.min(100.0, convertedScore);
                convertedScore = Double.parseDouble(String.format("%.2f", convertedScore));

                blockScores.put(knowledgeBlock, convertedScore);
            }
        }
        return studentKnowledgeBlockScores;
    }


    public static List<Map<String, Object>> calculateScoresWithDetails(List<RecordVo> res, Appraise appraise,HttpServletRequest request) {
        // 1. 构建知识点到知识块的映射 (一个知识块对应多个知识点)
        Map<String, List<String>> knowledgeBlockToPointsMap = getKnowledgeBlockToPointsMap(appraise);

        // 2. 构建所有二级知识块名称列表
        Set<String> knowledgeBlocks = new HashSet<>();
        for (AppraiseTreeNode node : appraise.getNodes()) {
            if ("劳育".equals(node.getName())) {
                for (AppraiseTreeNode secondLevelNode : node.getChildren()) {
                    knowledgeBlocks.add(secondLevelNode.getName());
                }
            }
        }

        // 3. 构建知识点到知识块的映射 (一个知识点对应一个知识块)
        Map<String, String> knowledgePointToBlockMap = new HashMap<>();
        for (Map.Entry<String, List<String>> entry : knowledgeBlockToPointsMap.entrySet()) {
            String knowledgeBlock = entry.getKey();
            for (String knowledgePoint : entry.getValue()) {
                knowledgePointToBlockMap.put(knowledgePoint, knowledgeBlock);
            }
        }

        // 4. 遍历评价记录并统计得分
        Map<String, Map<String, Integer>> studentScores = new HashMap<>();
        Map<String, List<Map<String, Object>>> studentAppraises = new HashMap<>(); // 存储每个学生的评价记录

        // 将 classId 转换为 List<String>
        //获取res中的classId集合
        List<String> classIds = res.stream()
                .map(RecordVo::getClassId)
                .distinct()
                .collect(Collectors.toList());
        //List<String> classIds = Collections.singletonList(classId);
        GroupDto groupDto = new GroupDto();
        groupDto.setIds(classIds);
        groupDto.setSchoolId(appraise.getSchoolId());
        String url = environment.getProperty("ies.server-url-group");
        Map<String, Object> groupId = GroupUtil.getGroupId(groupDto, new GroupUtil(environment), request, url);
        List<RGroupList> rGroupList = new ArrayList<>();
        List<RMember> rMembers = new ArrayList<>();
        for (Map.Entry<String, Object> entry : groupId.entrySet()) {
            String key = entry.getKey();
            Object value = entry.getValue();
            if (key.equals("groups")) {
                String jsonGroups = JSON.toJSONString(value);
                rGroupList = JSON.parseObject(jsonGroups, new TypeReference<List<RGroupList>>() {});
            }
            if (key.equals("members")) {
                String jsonGroups = JSON.toJSONString(value);
                rMembers = JSON.parseObject(jsonGroups, new TypeReference<List<RMember>>() {});
            }
        }

        for (RecordVo record : res) {
            String studentId = record.getTargetId(); // 学生 ID
            String studentName = record.getTargetName(); // 学生名称
            String className = "";
            if (record.getClassName() == null) {
                className = rGroupList.stream()
                        .filter(rGroupList1 -> rGroupList1.getId().equals(record.getClassId()))
                        .findFirst()
                        .map(RGroupList::getName)
                        .orElse("未知班级"); // 如果未找到则返回默认值 "未知班级"
            }else {
                className = record.getClassName();
            }

            String appraiseName = record.getAppraiseName(); // 评价内容
            boolean isPraise = record.isPraise(); // 是否为优点

            // 获取评价内容对应的第二级节点（知识块）
            String knowledgeBlock = knowledgePointToBlockMap.get(appraiseName);
            if (knowledgeBlock == null) {
                continue; // 如果不在劳育知识块中，跳过
            }

            // 初始化学生得分记录
            String studentKey = studentId + "|" + studentName + "|" + className; // 组合学生唯一标识
            studentScores.putIfAbsent(studentKey, new HashMap<>());
            Map<String, Integer> studentScoreMap = studentScores.get(studentKey);

            // 计分
            int score = isPraise ? 1 : -1;
            int currentScore = studentScoreMap.getOrDefault(knowledgeBlock, 0) + score;
            if (currentScore < 0) {
                currentScore = 0; // 或者你可以设置为其他最小允许的分数
            }
            studentScoreMap.put(knowledgeBlock, currentScore);

            // 存储每个学生的评价记录
            studentAppraises.putIfAbsent(studentKey, new ArrayList<>());
            Map<String, Object> appraiseRecord = new HashMap<>();
            appraiseRecord.put("appraiseName", appraiseName);
            appraiseRecord.put("isPraise", isPraise);
            studentAppraises.get(studentKey).add(appraiseRecord);
        }

        // 5. 初始化缺失的二级知识块分数
        for (Map.Entry<String, Map<String, Integer>> entry : studentScores.entrySet()) {
            Map<String, Integer> studentScoreMap = entry.getValue();
            for (String block : knowledgeBlocks) {
                studentScoreMap.putIfAbsent(block, 0);
            }
        }

        // 6. 整理并返回结果
        return getMaps(studentScores, studentAppraises);
    }

    // 整理并返回结果
    private static List<Map<String, Object>> getMaps(Map<String, Map<String, Integer>> studentScores, Map<String, List<Map<String, Object>>> studentAppraises) {
        List<Map<String, Object>> result = new ArrayList<>();

        for (Map.Entry<String, Map<String, Integer>> entry : studentScores.entrySet()) {
            String studentKey = entry.getKey();
            Map<String, Integer> scoreMap = entry.getValue();
            List<Map<String, Object>> appraiseList = studentAppraises.get(studentKey); // 获取学生的评价记录

            // 解析学生唯一标识
            String[] studentInfo = studentKey.split("\\|");
            String studentId = studentInfo[0];
            String studentName = studentInfo[1];
            String className = studentInfo[2];

            // 构建返回结果
            Map<String, Object> studentResult = new HashMap<>();
            studentResult.put("studentId", studentId);
            studentResult.put("studentName", studentName);
            studentResult.put("className", className);
            studentResult.put("scores", scoreMap);
            studentResult.put("appraises", appraiseList); // 添加评价记录

            result.add(studentResult);
        }

        return result;
    }

    // 构建知识块到知识点的映射 (一个知识块对应多个知识点)
    private static Map<String, List<String>> getKnowledgeBlockToPointsMap(Appraise appraise) {
        Map<String, List<String>> knowledgeBlockToPointsMap = new HashMap<>();

        for (AppraiseTreeNode node : appraise.getNodes()) {
            if ("劳育".equals(node.getName())) {
                for (AppraiseTreeNode secondLevelNode : node.getChildren()) {
                    String knowledgeBlock = secondLevelNode.getName();
                    List<String> knowledgePoints = new ArrayList<>();

                    // 假设知识点的信息存储在 secondLevelNode.getChildren() 中
                    for (AppraiseTreeNode pointNode : secondLevelNode.getChildren()) {
                        knowledgePoints.add(pointNode.getName());
                    }

                    knowledgeBlockToPointsMap.put(knowledgeBlock, knowledgePoints);
                }
            }
        }

        return knowledgeBlockToPointsMap;
    }


    // 知识点得分率结果类
    @Data
    @AllArgsConstructor
    public static class KnowledgeScoreRate {
        public String knowledge; // 知识点
        public double scoreRate; // 得分率
    }

    /**
     * 计算某个学生在多次考试中的知识点得分率，并返回其所属节点的父节点得分率
     *
     * @param studentId       学生 ID
     * @param examResults     学生作答结果集
     * @param knowledgeMap    知识点映射（试卷 ID -> 知识点列表）
     * @param appraise        评价对象
     * @return 父节点得分率
     */
    public static Map<String, Double> calculateKnowledgeScoreRateForStudent(
            String studentId, List<ExamClassResult> examResults,
            Map<String, List<List<String>>> knowledgeMap, Appraise appraise, Map<String, List<Double>> points) {
        Map<String, Double> knowledgeTotalScore = new HashMap<>();

        // 计算学生的知识点得分率
        List<MoralEducationServiceImpl.KnowledgeScoreRate> studentScoreRates = calculateStudentScoreRates(studentId, examResults, knowledgeMap, points, knowledgeTotalScore);

        // 查找知识点对应的节点及其父节点
        Map<String, Double> parentNodeScoreRates = new HashMap<>();
        Map<String, Integer> parentNodeScoreCount = new HashMap<>(); // 记录每个父节点的知识点数量

        for (MoralEducationServiceImpl.KnowledgeScoreRate scoreRate : studentScoreRates) {
            String knowledge = scoreRate.getKnowledge();
            AppraiseTreeNode node = findKnowledgeNode(appraise.getNodes(), knowledge);

            // 1. 查找知识点所属的知识块（假设通过knowledgeMap映射）
            String block = findKnowledgeBlock(knowledgeMap, knowledge); // 自定义方法：从knowledgeMap中获取知识点所属的知识块

            // 2. 查找知识块对应的父节点
            AppraiseTreeNode parentNode = null;
            if (block != null) {
                parentNode = findParentNodeByBlockName(appraise.getNodes(), block); // 自定义方法：按知识块名称查找父节点
            }

            // 3. 处理匹配到节点的情况
            if (node != null) {
                parentNode = findParentNode(appraise.getNodes(), node.getId());
            } else {
                // 未匹配知识点：默认60分，归入其所属知识块的父节点
                double defaultScore = 60.0;
                if (parentNode == null) {
                    // 若知识块无对应父节点，归入全局默认块
                    parentNodeScoreRates.merge("默认块", defaultScore, Double::sum);
                    parentNodeScoreCount.merge("默认块", 1, Integer::sum);
                } else {
                    // 归入知识块对应的父节点
                    parentNodeScoreRates.merge(parentNode.getName(), defaultScore, Double::sum);
                    parentNodeScoreCount.merge(parentNode.getName(), 1, Integer::sum);
                }
                continue; // 跳过后续匹配逻辑
            }

            // 4. 累加得分到父节点（原有逻辑）
            if (parentNode != null) {
                parentNodeScoreRates.merge(parentNode.getName(), scoreRate.getScoreRate(), Double::sum);
                parentNodeScoreCount.merge(parentNode.getName(), 1, Integer::sum);
            } else {
                parentNodeScoreRates.put(node.getName(), scoreRate.getScoreRate());
                parentNodeScoreCount.put(node.getName(), 1);
            }
        }

        // 计算父节点的平均得分（原始正确率）后，转换为基于60分的加分制
        parentNodeScoreRates.replaceAll((parentNodeName, totalScore) -> {
            int count = parentNodeScoreCount.getOrDefault(parentNodeName, 1);
            double averageScore = totalScore / count; // 原始正确率（0-100的百分比）

            // 将原始正确率转换为以60分为基础的加分制（正确率 × 40%）
            double correctRate = averageScore / 100.0;       // 转为0-1的小数
            double convertedScore = 60.0 + (correctRate * 40.0); // 最低60分，最高100分

            // 确保不超过100分，并保留两位小数
            convertedScore = Math.min(100.0, convertedScore);
            return Double.parseDouble(String.format("%.2f", convertedScore));
        });

        // 初始化所有同层的父节点
        for (AppraiseTreeNode node : appraise.getNodes()) {
            if (node.getName().equals("劳育")) {
                for (AppraiseTreeNode child : node.getChildren()) {
                    if (!parentNodeScoreRates.containsKey(child.getName())) {
                        parentNodeScoreRates.put(child.getName(), 60.0); // 默认60分
                    }
                }
            }
        }

        return parentNodeScoreRates;
    }

    // 从knowledgeMap中查找知识点所属的知识块
    private  static String findKnowledgeBlock(Map<String, List<List<String>>> knowledgeMap, String knowledge) {
        for (Map.Entry<String, List<List<String>>> entry : knowledgeMap.entrySet()) {
            for (List<String> subList : entry.getValue()) {
                if (subList.contains(knowledge)) {
                    return entry.getKey();
                }
            }
        }
        return null;
    }

    // 按知识块名称查找父节点
    private  static AppraiseTreeNode findParentNodeByBlockName(List<AppraiseTreeNode> nodes, String blockName) {
        for (AppraiseTreeNode node : nodes) {
            if (node.getName().equals(blockName)) {
                return node;
            }
            AppraiseTreeNode found = findParentNodeByBlockName(node.getChildren(), blockName);
            if (found != null) return found;
        }
        return null;
    }


    /**
     * 计算班级每个学生知识点得分率，并返回每个学生所属节点的父节点得分率
     *
     * @param classId         班级 ID
     * @param examResults     学生作答结果集
     * @param knowledgeMap    知识点映射（试卷 ID -> 知识点列表）
     * @param appraise        评价对象
     * @return 学生 ID -> 父节点得分率映射
     */
    public static Map<String, Object> calculateKnowledgeScoreRateForClass(
            String classId,
            List<ExamClassResult> examResults,
            Map<String, List<List<String>>> knowledgeMap,
            Appraise appraise,
            Map<String, List<Double>> points,
            List<RecordVo> res,
            HttpServletRequest request) {

        // 将 classId 转换为 List<String>
        List<String> classIds = Collections.singletonList(classId);
        GroupDto groupDto = new GroupDto();
        groupDto.setIds(classIds);
        groupDto.setSchoolId(appraise.getSchoolId());
        String url = environment.getProperty("ies.server-url-group");
        Map<String, Object> groupId = GroupUtil.getGroupId(groupDto, new GroupUtil(environment), request, url);
        List<RGroupList> rGroupList = new ArrayList<>();
        List<RMember> rMembers = new ArrayList<>();
        for (Map.Entry<String, Object> entry : groupId.entrySet()) {
            String key = entry.getKey();
            Object value = entry.getValue();
            if (key.equals("groups")) {
                String jsonGroups = JSON.toJSONString(value);
                rGroupList = JSON.parseObject(jsonGroups, new TypeReference<List<RGroupList>>() {});
            }
            if (key.equals("members")) {
                String jsonGroups = JSON.toJSONString(value);
                rMembers = JSON.parseObject(jsonGroups, new TypeReference<List<RMember>>() {});
            }
        }
        String className = rGroupList.stream()
                .filter(rGroupList1 -> rGroupList1.getId().equals(classId))
                .findFirst()
                .map(RGroupList::getName)
                .orElse("未知班级"); // 如果未找到则返回默认值 "未知班级"

        // 1. 获取班级所有学生的客观分数
        Map<String, Map<String, Double>> studentScoreRates = new HashMap<>();
        Map<String, Double> classScoreRates = new HashMap<>();

        // 获取班级所有学生的名单（来自 rMembers）
        Map<String, String> studentIdToName = new HashMap<>();
        RGroupList groupList =  rGroupList.stream().filter(rGroupList1 -> rGroupList1.getId().equals(classId)).findFirst().orElse(null);
        if (groupList != null) {
            for (RMember member : groupList.members) {
                studentIdToName.put(member.getId(), member.getName());
            }
        }

        // 初始化知识块列表（从 appraise 配置中提取）
        Set<String> knowledgeBlocks = new HashSet<>();
        for (AppraiseTreeNode node : appraise.getNodes()) {
            if (node.getName().equals("劳育")) {
                for (AppraiseTreeNode child : node.getChildren()) {
                    knowledgeBlocks.add(child.getName());
                }
            }
        }

        if (examResults != null && !examResults.isEmpty()) {
            // 遍历班级中的每个学生
            for (ExamClassResult examResult : examResults) {
                if (!examResult.getInfo().getId().equals(classId)){
                    // 无考试数据时，初始化所有学生的默认分数为60
                    if (groupList != null) {
                        for (RMember member : groupList.members) {
                            String studentId = member.getId();
                            String studentName = studentIdToName.getOrDefault(studentId, "未知学生");
                            Map<String, Double> defaultScores = new HashMap<>();
                            for (String block : knowledgeBlocks) {
                                defaultScores.put(block, 84.0); // 初始化为60分
                            }
                            studentScoreRates.put(studentName, defaultScores);
                        }
                    }
                }else{
                    List<Integer> statuses = examResult.getStatus();
                    for (int i = 0; i < examResult.getStudentIds().size(); i++) {
                        String studentId = examResult.getStudentIds().get(i);
                        String name = rMembers.stream()
                                .filter(member -> member.getId().equals(studentId))
                                .findFirst()
                                .map(RMember::getName)
                                .orElse("未知");
                        int status = statuses.get(i);
                        if (status == 1) continue;

                        // 正确获取已转换的客观分数（无需二次截断）
                        Map<String, Double> scoreRates = calculateKnowledgeScoreRateForStudent(
                                studentId, examResults, knowledgeMap, appraise, points
                        );
                        studentScoreRates.put(name, scoreRates);

                        // 累加班级整体得分率
                        for (Map.Entry<String, Double> entry : scoreRates.entrySet()) {
                            classScoreRates.put(entry.getKey(), classScoreRates.getOrDefault(entry.getKey(), 0.0) + entry.getValue());
                        }
                    }
                }

            }
        }else {
            // 无考试数据时，初始化所有学生的默认分数为60
            if (groupList != null) {
                for (RMember member : groupList.members) {
                    String studentId = member.getId();
                    String studentName = studentIdToName.getOrDefault(studentId, "未知学生");
                    Map<String, Double> defaultScores = new HashMap<>();
                    for (String block : knowledgeBlocks) {
                        defaultScores.put(block, 84.0); // 初始化为60分
                    }
                    studentScoreRates.put(studentName, defaultScores);
                }
            }
        }

        // 2. 获取班级所有学生的主观分数（次数）
        List<Map<String, Object>> subjectiveScoresList = calculateScoresWithDetails(res, appraise,request);

        // 3. 将主观次数转换为0-100分数
        Map<String, Map<String, Double>> subjectiveScores = new HashMap<>();
        for (Map<String, Object> studentScore : subjectiveScoresList) {
            String studentId = (String) studentScore.get("studentId");
            @SuppressWarnings("unchecked")
            Map<String, Integer> scores = (Map<String, Integer>) studentScore.get("scores");
            Map<String, Double> convertedScores = new HashMap<>();

            for (Map.Entry<String, Integer> entry : scores.entrySet()) {
                String block = entry.getKey();
                int count = entry.getValue();
                // 确保 count 不小于0
                if (count < 0) {
                    count = 0;
                }
                double maxCount = 50.0; // 调整此参数控制分数增长速率

                // 使用反比例函数计算加分
                double additionalScore = 40.0 * ((double) count / (count + maxCount));
                double convertedScore = 60.0 + additionalScore;

                // 保留两位小数
                convertedScore = Double.parseDouble(String.format("%.2f", convertedScore));
                convertedScores.put(block, convertedScore);
            }

            subjectiveScores.put(studentId, convertedScores);
        }

        // 4. 融合主观和客观分数
        Map<String, Map<String, Double>> compositeStudentScores = new HashMap<>();
        for (String studentId : studentIdToName.keySet()) {
            String studentName = studentIdToName.get(studentId);
            // 获取客观分数（已确保60-100分）
            Map<String, Double> objective = studentScoreRates.getOrDefault(studentName, new HashMap<>());
            // 获取主观分数（确保60-100分）
            Map<String, Double> subjective = subjectiveScores.getOrDefault(studentId, new HashMap<>());

            Map<String, Double> compositeScores = new HashMap<>();
            for (String block : knowledgeBlocks) {
                // 客观分数兜底逻辑（确保60分）
                double objectiveScore = objective.getOrDefault(block, 60.0);
                // 主观分数兜底逻辑（确保60分）
                double subjectiveScore = subjective.getOrDefault(block, 60.0);

                // 计算综合得分（主观60% + 客观40%）
                double compositeScore = (subjectiveScore * 0.6) + (objectiveScore * 0.4);
                compositeScore = Math.min(100.0, compositeScore);  // 确保不超过100分
                compositeScore = Double.parseDouble(String.format("%.2f", compositeScore));

                compositeScores.put(block, compositeScore);
            }
            compositeStudentScores.put(studentName, compositeScores);
        }

        // 5. 计算班级整体得分率
        int studentCount = compositeStudentScores.size();
        Map<String, Double> compositeClassScoreRates = new HashMap<>();
        if (studentCount > 0) {
            for (Map<String, Double> studentScores : compositeStudentScores.values()) {
                for (String block : knowledgeBlocks) {
                    double score = studentScores.getOrDefault(block, 0.0);
                    compositeClassScoreRates.put(block, compositeClassScoreRates.getOrDefault(block, 0.0) + score);
                }
            }
            compositeClassScoreRates.replaceAll((k, v) -> Double.parseDouble(String.format("%.2f", v / studentCount)));
        } else {
            // 无学生时初始化空值
            for (String block : knowledgeBlocks) {
                compositeClassScoreRates.put(block, 0.0);
            }
        }

        // 6. 初始化所有同层的父节点
        for (AppraiseTreeNode node : appraise.getNodes()) {
            if (node.getName().equals("劳育")) {
                for (AppraiseTreeNode child : node.getChildren()) {
                    if (!compositeClassScoreRates.containsKey(child.getName())) {
                        compositeClassScoreRates.put(child.getName(), 0.0);
                    }
                }
            }
        }

        // 7. 转换 classScoreRates 和 studentScoreRates 为新的数据结构
        return getResult(className, compositeClassScoreRates, compositeStudentScores);
    }

    private static @NotNull Map<String, Object> getResult(String className, Map<String, Double> compositeClassScoreRates, Map<String, Map<String, Double>> compositeStudentScores) {
        List<Map<String, Object>> adjustedClassScoreRates = new ArrayList<>();
        Map<String, Object> classScore = new HashMap<>();
        classScore.put("className", className); // 设置班级名称

        List<Map<String, Object>> classBlocks = new ArrayList<>();
        for (Map.Entry<String, Double> entry : compositeClassScoreRates.entrySet()) {
            Map<String, Object> block = new HashMap<>();
            block.put("name", entry.getKey());
            block.put("score", entry.getValue());
            classBlocks.add(block);
        }
        classScore.put("blocks", classBlocks);
        adjustedClassScoreRates.add(classScore);

        List<Map<String, Object>> adjustedStudentScoreRates = new ArrayList<>();
        for (Map.Entry<String, Map<String, Double>> entry : compositeStudentScores.entrySet()) {
            String studentId = entry.getKey();
            Map<String, Double> scores = entry.getValue();

            Map<String, Object> studentScore = new HashMap<>();
            studentScore.put("studentName", studentId); // 设置学生名称

            List<Map<String, Object>> studentBlocks = new ArrayList<>();
            for (Map.Entry<String, Double> scoreEntry : scores.entrySet()) {
                Map<String, Object> block = new HashMap<>();
                block.put("name", scoreEntry.getKey());
                block.put("score", scoreEntry.getValue());
                studentBlocks.add(block);
            }
            studentScore.put("blocks", studentBlocks);
            adjustedStudentScoreRates.add(studentScore);
        }

        // 8. 返回结果
        Map<String, Object> result = new HashMap<>();
        result.put("classScoreRates", adjustedClassScoreRates); // 班级整体得分率
        result.put("studentScoreRates", adjustedStudentScoreRates); // 每个学生的综合得分率
        return result;
    }


    private static List<MoralEducationServiceImpl.KnowledgeScoreRate> calculateStudentScoreRates(
            String studentId,
            List<ExamClassResult> examResults,
            Map<String, List<List<String>>> knowledgeMap,
            Map<String, List<Double>> points,
            Map<String, Double> knowledgeTotalScore) {
        Map<String, Double> knowledgeTotalAverage = new HashMap<>();
        Map<String, Integer> knowledgeExamCount = new HashMap<>();

        // 如果没有考试数据，初始化所有知识点分数为60分
        if (examResults == null || examResults.isEmpty()) {
            for (String knowledge : knowledgeMap.values().stream()
                    .flatMap(List::stream)
                    .flatMap(List::stream)
                    .collect(Collectors.toSet())) {
                knowledgeTotalScore.put(knowledge, 60.0); // 默认60分
            }
            return knowledgeTotalScore.entrySet().stream()
                    .map(entry -> new MoralEducationServiceImpl.KnowledgeScoreRate(entry.getKey(), entry.getValue()))
                    .collect(Collectors.toList());
        }

        // 正常处理考试数据
        for (ExamClassResult examResult : examResults) {
            int studentIndex = examResult.getStudentIds().indexOf(studentId);
            if (studentIndex == -1) continue;
            int status = examResult.getStatus().get(studentIndex);
            if (status == 1) continue;

            List<List<String>> knowledgeList = knowledgeMap.get(examResult.getExamId());
            List<Double> pointList = points.get(examResult.getExamId());
            if (knowledgeList == null || pointList == null) continue;

            List<List<Double>> studentScores = examResult.getStudentScores();
            if (studentIndex >= studentScores.size() || studentScores.get(studentIndex) == null) continue;
            List<Double> studentScoreList = studentScores.get(studentIndex);

            if (knowledgeList.size() != studentScoreList.size()) continue;

            Map<String, Double> currentExamKnowledgeTotal = new HashMap<>();
            Map<String, Integer> currentExamKnowledgeCount = new HashMap<>();

            // 遍历每道题
            for (int i = 0; i < studentScoreList.size(); i++) {
                List<String> knowledgePoints = knowledgeList.get(i); // 题目对应的知识点列表
                double score = studentScoreList.get(i);

                // 如果题目没有知识点或得分为空，跳过
                if (knowledgePoints.isEmpty() || score < 0) continue;

                // 将题目得分分摊到每个知识点
                double scorePerKnowledge = score / knowledgePoints.size();

                // 遍历该题的所有知识点
                for (String knowledge : knowledgePoints) {
                    // 累加当前考试中该知识点的总得分和题目数量
                    currentExamKnowledgeTotal.merge(knowledge, scorePerKnowledge, Double::sum);
                    currentExamKnowledgeCount.merge(knowledge, 1, Integer::sum);
                }
            }

            // 计算当前考试中每个知识点的平均分（总得分/题目数量）
            for (String knowledge : currentExamKnowledgeTotal.keySet()) {
                double total = currentExamKnowledgeTotal.get(knowledge);
                int count = currentExamKnowledgeCount.get(knowledge);
                double average = total / count;

                // 累加跨考试的总平均分和考试次数
                knowledgeTotalAverage.merge(knowledge, average, Double::sum);
                knowledgeExamCount.merge(knowledge, 1, Integer::sum);
            }
        }

        // 计算最终平均分（所有考试平均分的平均），并限制在60-100分之间
        for (String knowledge : knowledgeTotalAverage.keySet()) {
            double totalAverage = knowledgeTotalAverage.get(knowledge);
            int examCount = knowledgeExamCount.get(knowledge);
            double finalAverage = totalAverage / examCount;

            // 在基础分60分上累加实际考试得分（最多加40分）
            double additionalScore = Math.min(finalAverage, 40.0); // 实际考试得分最多加40分
            finalAverage = 60.0 + additionalScore; // 基础分60 + 实际考试得分
            finalAverage = Math.min(finalAverage, 100.0); // 总分不超过100分

            finalAverage = Double.parseDouble(String.format("%.2f", finalAverage));
            knowledgeTotalScore.put(knowledge, finalAverage);
        }

        // 如果没有考试数据，确保所有知识点都有默认60分
        if (knowledgeTotalScore.isEmpty()) {
            for (String knowledge : knowledgeMap.values().stream()
                    .flatMap(List::stream)
                    .flatMap(List::stream)
                    .collect(Collectors.toSet())) {
                knowledgeTotalScore.put(knowledge, 60.0); // 默认60分
            }
        }

        return knowledgeTotalScore.entrySet().stream()
                .map(entry -> new MoralEducationServiceImpl.KnowledgeScoreRate(entry.getKey(), entry.getValue()))
                .collect(Collectors.toList());
    }


    public static double calculateNodeScoreRate(AppraiseTreeNode node, Map<String, Double> knowledgeTotalScore) {
        // 获取当前节点的得分
        double totalScore = knowledgeTotalScore.getOrDefault(node.getName(), 0.0);

        // 递归计算子节点的得分并累加
        for (AppraiseTreeNode child : node.getChildren()) {
            totalScore += calculateNodeScoreRate(child, knowledgeTotalScore);
        }

        return totalScore;
    }

    /**
     * 计算年级整体得分率，并返回其所属节点的父节点得分率
     *
     * @param gradeId         年级 ID
     * @param examResults     学生作答结果集
     * @param knowledgeMap    知识点映射（试卷 ID -> 知识点列表）
     * @param appraise        评价对象
     *  @param points         试卷配分
     * @return 年级所属节点的父节点得分率
     */
    public static Map<String, Object> calculateKnowledgeScoreForGrade(
            String gradeId,
            List<ExamClassResult> examResults,
            Map<String, List<List<String>>> knowledgeMap,
            Appraise appraise,
            Map<String, List<Double>> points,
            List<RecordVo> res,
            List<GradeAndClassVo> gradeAndClassVos,
            HttpServletRequest request) {

        // 1. 获取年级所有班级的客观分数
        Map<String, Map<String, Double>> classScores = new HashMap<>();
        Map<String, Double> gradeScores = new HashMap<>();

        // 根据 gradeId 匹配并取出 classId 集合
        List<GradeAndClassVo.CI> classInfos = gradeAndClassVos.stream()
                .filter(gradeAndClassVo -> String.valueOf(gradeAndClassVo.getGradeId()).equals(gradeId))
                .flatMap(gradeAndClassVo -> gradeAndClassVo.getClasses().stream())
                .collect(Collectors.toList());
        String gradeName = gradeAndClassVos.stream()
                .filter(gradeAndClassVo -> String.valueOf(gradeAndClassVo.getGradeId()).equals(gradeId))
                .findFirst()
                .map(GradeAndClassVo::getGradeName)
                .orElse("");

        // 过滤出该年级的考试结果
        List<ExamClassResult> gradeExamResults = examResults.stream()
                .filter(examResult -> examResult.getGradeId().equals(gradeId))
                .collect(Collectors.toList());

        // 2. 获取年级所有学生的主观分数（次数）
        List<Map<String, Object>> subjectiveScoresList = calculateScoresWithDetails(res, appraise,request);

        // 3. 将主观次数转换为0-100分数，并收集学生班级信息
        Map<String, Map<String, Double>> subjectiveScores = new HashMap<>();
        Map<String, String> studentClassMap = new HashMap<>(); // 学生ID到班级ID的映射
        for (RecordVo record : res) {
            // 假设RecordVo中有getStudentId()和getClassId()方法
            studentClassMap.put(record.getTargetId(), record.getClassId());
        }
        for (Map<String, Object> studentScore : subjectiveScoresList) {
            String studentId = (String) studentScore.get("studentId");
            @SuppressWarnings("unchecked")
            Map<String, Integer> scores = (Map<String, Integer>) studentScore.get("scores");
            Map<String, Double> convertedScores = new HashMap<>();

            for (Map.Entry<String, Integer> entry : scores.entrySet()) {
                String block = entry.getKey();
                int count = entry.getValue();
                // 确保 count 不小于0
                if (count < 0) {
                    count = 0;
                }
                double maxCount = 50.0; // 调整此参数控制分数增长速率

                // 使用反比例函数计算加分
                double additionalScore = 40.0 * ((double) count / (count + maxCount));
                double convertedScore = 60.0 + additionalScore;

                // 保留两位小数
                convertedScore = Double.parseDouble(String.format("%.2f", convertedScore));
                convertedScores.put(block, convertedScore);
            }
            subjectiveScores.put(studentId, convertedScores);
        }

        // 4. 遍历年级下的所有班级
        for (GradeAndClassVo.CI info : classInfos) {
            String classId = info.getClassId();
            String className = info.getClassName();
            Map<String, Double> classScoresInner = new HashMap<>();

            // 获取该班级的所有学生ID（来自res记录）
            List<String> studentIdsInClass = studentClassMap.entrySet().stream()
                    .filter(entry -> entry.getValue().equals(classId))
                    .map(Map.Entry::getKey)
                    .collect(Collectors.toList());

            Map<String, Double> classScoreSum = new HashMap<>();
            Map<String, Integer> classScoreCount = new HashMap<>();

            for (String studentId : studentIdsInClass) {
                // 获取学生状态（从考试结果中查找，默认为有效）
                int status = 0;
                for (ExamClassResult examResult : gradeExamResults) {
                    int index = examResult.getStudentIds().indexOf(studentId);
                    if (index != -1) {
                        status = examResult.getStatus().get(index);
                        break;
                    }
                }
                if (status == 1) continue;

                // 计算学生的知识点得分（客观分数）
                Map<String, Double> studentObjectiveScores = calculateKnowledgeScoreRateForStudent(
                        studentId, examResults, knowledgeMap, appraise, points
                );

                // 确保客观分数最低为60分
                for (Map.Entry<String, Double> entry : studentObjectiveScores.entrySet()) {
                    String block = entry.getKey();
                    double score = entry.getValue();
                    score = Math.max(60.0, Math.min(100.0, score)); // 确保60-100分
                    studentObjectiveScores.put(block, score);
                }

                // 获取学生的主观分数
                Map<String, Double> studentSubjectiveScores = subjectiveScores.getOrDefault(studentId, new HashMap<>());

                // 确定所有需要处理的评分块（合并主客观的块）
                Set<String> allBlocks = new HashSet<>();
                allBlocks.addAll(studentObjectiveScores.keySet());
                allBlocks.addAll(studentSubjectiveScores.keySet());

                // 计算综合得分（主观60%，客观40%）
                for (String block : allBlocks) {
                    double objectiveScore = studentObjectiveScores.getOrDefault(block, 60.0); // 默认60分
                    double subjectiveScore = studentSubjectiveScores.getOrDefault(block, 0.0);
                    double compositeScore = (subjectiveScore * 0.6) + (objectiveScore * 0.4);
                    compositeScore = Math.max(60.0, Math.min(100.0, compositeScore)); // 确保60-100分
                    compositeScore = Double.parseDouble(String.format("%.2f", compositeScore));

                    // 累加班级得分
                    classScoreSum.put(block, classScoreSum.getOrDefault(block, 0.0) + compositeScore);
                    classScoreCount.put(block, classScoreCount.getOrDefault(block, 0) + 1);
                }
            }

            // 计算班级平均得分
            for (String block : classScoreSum.keySet()) {
                double total = classScoreSum.get(block);
                int count = classScoreCount.getOrDefault(block, 1);
                classScoresInner.put(block, Double.parseDouble(String.format("%.2f", total / count)));
            }

            // 初始化所有同层的父节点（确保结构完整）
            for (AppraiseTreeNode node : appraise.getNodes()) {
                if ("劳育".equals(node.getName())) {
                    node.getChildren().forEach(child ->
                            classScoresInner.putIfAbsent(child.getName(), 60.0)); // 默认60分
                }
            }

            classScores.put(className, classScoresInner);
        }

        // 5. 计算年级的平均得分
        Map<String, Double> gradeScoreSum = new HashMap<>();
        Map<String, Integer> gradeScoreCount = new HashMap<>();
        classScores.values().forEach(classScore ->
                classScore.forEach((block, score) -> {
                    gradeScoreSum.put(block, gradeScoreSum.getOrDefault(block, 0.0) + score);
                    gradeScoreCount.put(block, gradeScoreCount.getOrDefault(block, 0) + 1);
                }));

        gradeScoreSum.forEach((block, total) -> {
            int count = gradeScoreCount.getOrDefault(block, 1);
            gradeScores.put(block, Double.parseDouble(String.format("%.2f", total / count)));
        });

        // 初始化年级层级的父节点
        for (AppraiseTreeNode node : appraise.getNodes()) {
            if ("劳育".equals(node.getName())) {
                node.getChildren().forEach(child ->
                        gradeScores.putIfAbsent(child.getName(), 60.0)); // 默认60分
            }
        }

        // 6. 转换数据结构并返回
        return getStringObjectMap(gradeName, gradeScores, classScores);
    }

    private static @NotNull Map<String, Object> getStringObjectMap(String gradeName, Map<String, Double> gradeScores, Map<String, Map<String, Double>> classScores) {
        List<Map<String, Object>> adjustedGradeScores = new ArrayList<>();
        Map<String, Object> gradeScore = new HashMap<>();
        gradeScore.put("gradeName", gradeName); // 设置年级名称

        List<Map<String, Object>> gradeBlocks = new ArrayList<>();
        for (Map.Entry<String, Double> entry : gradeScores.entrySet()) {
            Map<String, Object> block = new HashMap<>();
            block.put("name", entry.getKey());
            block.put("score", entry.getValue());
            gradeBlocks.add(block);
        }
        gradeScore.put("blocks", gradeBlocks);
        adjustedGradeScores.add(gradeScore);

        List<Map<String, Object>> adjustedClassScores = new ArrayList<>();
        for (Map.Entry<String, Map<String, Double>> entry : classScores.entrySet()) {
            String className = entry.getKey();
            Map<String, Double> scores = entry.getValue();

            Map<String, Object> classScore = new HashMap<>();
            classScore.put("className", className); // 设置班级名称

            List<Map<String, Object>> classBlocks = new ArrayList<>();
            for (Map.Entry<String, Double> scoreEntry : scores.entrySet()) {
                Map<String, Object> block = new HashMap<>();
                block.put("name", scoreEntry.getKey());
                block.put("score", scoreEntry.getValue());
                classBlocks.add(block);
            }
            classScore.put("blocks", classBlocks);
            adjustedClassScores.add(classScore);
        }

        // 7. 返回结果
        Map<String, Object> result = new HashMap<>();
        result.put("gradeScores", adjustedGradeScores); // 年级平均得分
        result.put("classScores", adjustedClassScores); // 每个班级的平均得分
        return result;
    }


    public static Map<String, Object> calculateKnowledgeScoreForSchool(
            List<ExamClassResult> examResults,
            Map<String, List<List<String>>> knowledgeMap,
            Appraise appraise,
            Map<String, List<Double>> points,
            List<RecordVo> res,
            List<School.Period> period,
            List<GradeAndClassVo> gradeAndClassVos,HttpServletRequest request) {

        // 1. 初始化数据结构
        Map<String, Map<String, Double>> gradeScores = new HashMap<>();
        Map<String, Double> schoolScores = new HashMap<>();
        List<String> gradeIds = period.stream()
                .flatMap(period1 -> period1.getGrades().stream())
                .collect(Collectors.toList());
        int totalClassCount = 0; // 新增：全校总班级数统计

        // 2. 遍历所有年级
        int index = 0;
        for (String gradeId : gradeIds) {
            Map<String, Object> gradeResult = calculateKnowledgeScoreForGrade(
                    String.valueOf(index), examResults, knowledgeMap, appraise, points, res, gradeAndClassVos,request
            );

            // 2.1 提取年级平均分
            List<Map<String, Object>> adjustedGradeScores = (List<Map<String, Object>>) gradeResult.get("gradeScores");
            Map<String, Double> gradeScoresInner = new HashMap<>();
            for (Map<String, Object> gradeScoreEntry : adjustedGradeScores) {
                List<Map<String, Object>> blocks = (List<Map<String, Object>>) gradeScoreEntry.get("blocks");
                for (Map<String, Object> block : blocks) {
                    String nodeName = (String) block.get("name");
                    Double score = (Double) block.get("score");
                    gradeScoresInner.put(nodeName, score);
                }
            }
            gradeScores.put(gradeId, gradeScoresInner);

            // 2.2 累加全校总分并统计班级数
            List<Map<String, Object>> adjustedClassScores = (List<Map<String, Object>>) gradeResult.get("classScores");
            totalClassCount += adjustedClassScores.size(); // 累加班级数
            for (Map<String, Object> classScoreEntry : adjustedClassScores) {
                List<Map<String, Object>> classBlocks = (List<Map<String, Object>>) classScoreEntry.get("blocks");
                for (Map<String, Object> block : classBlocks) {
                    String nodeName = (String) block.get("name");
                    Double score = (Double) block.get("score");
                    schoolScores.put(nodeName, schoolScores.getOrDefault(nodeName, 0.0) + score);
                }
            }
            index++;
        }

        // 3. 计算全校平均分
        if (gradeIds.size() == 1) {
            schoolScores.putAll(gradeScores.get(gradeIds.iterator().next()));
        } else {
            for (Map.Entry<String, Double> entry : schoolScores.entrySet()) {
                String nodeName = entry.getKey();
                double totalScore = entry.getValue();
                if (totalClassCount == 0) {
                    schoolScores.put(nodeName, 0.0);
                } else {
                    double average = totalScore / totalClassCount;
                    average = Double.parseDouble(String.format("%.2f", average));
                    schoolScores.put(nodeName, average);
                }
            }
        }

        // 4. 初始化未参与计算的父节点（保持默认0分）
        for (AppraiseTreeNode node : appraise.getNodes()) {
            if (node.getName().equals("劳育")) {
                for (AppraiseTreeNode child : node.getChildren()) {
                    if (!schoolScores.containsKey(child.getName())) {
                        schoolScores.put(child.getName(), 0.0);
                    }
                }
            }
        }

        // 5. 转换数据结构并返回
        return getResult(gradeScores, schoolScores);
    }

    private static @NotNull Map<String, Object> getResult(Map<String, Map<String, Double>> gradeScores, Map<String, Double> schoolScores) {
        List<Map<String, Object>> adjustedGradeScores = new ArrayList<>();
        for (Map.Entry<String, Map<String, Double>> entry : gradeScores.entrySet()) {
            String gradeName = entry.getKey();
            Map<String, Double> scores = entry.getValue();

            List<Map<String, Object>> blocks = new ArrayList<>();
            for (Map.Entry<String, Double> scoreEntry : scores.entrySet()) {
                Map<String, Object> block = new HashMap<>();
                block.put("name", scoreEntry.getKey());
                block.put("score", scoreEntry.getValue());
                blocks.add(block);
            }

            Map<String, Object> gradeScore = new HashMap<>();
            gradeScore.put("gradeName", gradeName);
            gradeScore.put("blocks", blocks);
            adjustedGradeScores.add(gradeScore);
        }

        // 8. 转换 schoolScores 为新的数据结构
        List<Map<String, Object>> adjustedSchoolScores = new ArrayList<>();
        Map<String, Object> schoolScore = new HashMap<>();
        schoolScore.put("gradeName", "全校"); // 全校的 gradeName 设置为 "全校"

        List<Map<String, Object>> schoolBlocks = new ArrayList<>();
        for (Map.Entry<String, Double> entry : schoolScores.entrySet()) {
            Map<String, Object> block = new HashMap<>();
            block.put("name", entry.getKey());
            block.put("score", entry.getValue());
            schoolBlocks.add(block);
        }
        schoolScore.put("blocks", schoolBlocks);
        adjustedSchoolScores.add(schoolScore);

        // 9. 返回结果
        Map<String, Object> result = new HashMap<>();
        result.put("schoolScores", adjustedSchoolScores); // 全校平均得分
        result.put("gradeScores", adjustedGradeScores); // 每个年级的平均得分
        return result;
    }


    /**
     * 查找知识点对应的节点
     *
     * @param nodes             节点列表
     * @param knowledge 学生知识点得分率列表
     * @return 知识点对应的节点
     */
    private static AppraiseTreeNode findKnowledgeNode(List<AppraiseTreeNode> nodes, String knowledge) {
        for (AppraiseTreeNode node : nodes) {
            if (node.getName().equals("劳育")) {
                for (AppraiseTreeNode child : node.getChildren()) {
                    for (AppraiseTreeNode grandchild : child.getChildren()) {
                        if (grandchild.getName().equals(knowledge)) {
                            return grandchild; // 返回知识点对应的节点
                        }
                    }
                }
            }
        }
        return null; // 未找到匹配的节点
    }

    private static AppraiseTreeNode findParentNode(List<AppraiseTreeNode> nodes, String nodeId) {
        for (AppraiseTreeNode node : nodes) {
            for (AppraiseTreeNode child : node.getChildren()) {
                for (AppraiseTreeNode grandchild : child.getChildren()) {
                    if (grandchild.getId().equals(nodeId)) {
                        return child; // 返回父节点
                    }
                }
            }
        }
        return null; // 未找到父节点
    }


    //获取每月各个知识库综合得分以及整体得分内容
    public Map<String,List<Map<String, Object>>> getStudentMonthlyScores(MoralDto moralDto,HttpServletRequest request) {
        // 1. 获取基础信息
        String schoolId = SecurityUtil.getLoginUser().getSchoolId();
        String studentId = moralDto.getStudentId();
        List<String> classStudentIds = Collections.emptyList();
        // 2. 获取相关开课记录
        List<LessonRecord> records = getLessonRecords(moralDto, schoolId);
        List<RecordVo> res;
        int rightCount = 0;
        int wrongCount = 0;
        if (moralDto.getClassId() == null) {
            res = appraiseRecordRepository.getStudentRecords(
                    String.format(PK.PK_APPRAISE_RECORD, schoolId),
                    moralDto.getAcademicYearId(),
                    moralDto.getStudentId(),
                    moralDto.getStartTime(),
                    moralDto.getEndTime(),
                    "劳育"
            );
            //表扬的次数
            rightCount = (int) res.stream().filter(RecordVo::isPraise).count();
            //批评的次数
            wrongCount = (int) res.stream().filter(record -> !record.isPraise()).count();
        }else {
            //当班级ID 存在时 获取该班级下所有名单即学生Id
            List<String> classIds = Collections.singletonList(moralDto.getClassId());
            GroupDto groupDto = new GroupDto();
            groupDto.setIds(classIds);
            groupDto.setSchoolId(moralDto.getCode());
            String url = environment.getProperty("ies.server-url-group");
            Map<String, Object> groupId = GroupUtil.getGroupId(groupDto, new GroupUtil(environment), request, url);
            List<RGroupList> rGroupList = new ArrayList<>();
            List<RMember> rMembers = new ArrayList<>();
            for (Map.Entry<String, Object> entry : groupId.entrySet()) {
                String key = entry.getKey();
                Object value = entry.getValue();
                if (key.equals("groups")) {
                    String jsonGroups = JSON.toJSONString(value);
                    rGroupList = JSON.parseObject(jsonGroups, new TypeReference<List<RGroupList>>() {});
                }
            }
            rMembers = rGroupList.stream()
                    .flatMap(rGroupList1 -> rGroupList1.getMembers().stream())
                    .filter(rMember -> rMember.getClassId().equals(moralDto.getClassId()))
                    .collect(Collectors.toList());
            classStudentIds = rMembers.stream().map(RMember::getId).collect(Collectors.toList());
        /*String className = rGroupList.stream()
                .filter(rGroupList1 -> rGroupList1.getId().equals(classId))
                .findFirst()
                .map(RGroupList::getName)
                .orElse("未知班级"); // 如果未找到则返回默认值 "未知班级"*/
            res = appraiseRecordRepository.getRecords(
                    String.format(PK.PK_APPRAISE_RECORD, schoolId),
                    moralDto.getAcademicYearId(),
                    moralDto.getClassId(),
                    moralDto.getStudentId(),
                    "劳育"
            );
            //表扬的次数
            rightCount = (int) res.stream().filter(RecordVo::isPraise).count();
            //批评的次数
            wrongCount = (int) res.stream().filter(record -> !record.isPraise()).count();
        }

        // 3. 获取考试及知识点映射
        Map<String, List<List<String>>> examKnowledgeMap = new HashMap<>();
        Map<String, List<Double>> points = new HashMap<>();
        List<ExamVo> exams = getExamsWithKnowledge(moralDto, records, examKnowledgeMap, points);

        // 4. 获取考试结果并按月份分组
        List<String> targetStudents = moralDto.getClassId() != null ?
                classStudentIds : Collections.singletonList(studentId);

        Map<Integer, List<ExamResultWrapper>> monthlyResults = getMonthlyExamResults(
                schoolId, moralDto.getClassId(), exams, records,
                examKnowledgeMap, points, targetStudents // 传入目标学生列表
        );

        // 5. 获取知识块配置
        Appraise appraise = appraiseRepository.findAppraiseBySchoolIdAndPeriodIdAndCode(
                schoolId, moralDto.getPeriodId(), PK.PK_APPRAISE
        );
        appraise = evaluationService.buildTree(appraise);
        Map<String, List<String>> knowledgeBlockMap = getKnowledgeBlockToPointsMap(appraise);


        // 在获取知识块配置后添加
        Map<String, String> pointToBlockMap = new HashMap<>();
        knowledgeBlockMap.forEach((block, ps) -> {
            ps.forEach(point -> pointToBlockMap.put(point, block));
        });
        // 处理主观评价数据，统计每个月的次数
        Map<String, Map<Integer, Integer>> blockMonthlyCounts = new HashMap<>();

        Map<String, Map<Integer, Integer>> finalBlockMonthlyCounts = blockMonthlyCounts;
        res.stream()
                .filter(vo -> moralDto.getClassId() != null ?
                        targetStudents.contains(vo.getTargetId()) :
                        studentId.equals(vo.getTargetId()))
                .forEach(vo -> {
                    // 获取知识点对应的知识块
                    String originalPoint = vo.getAppraiseName();
                    String block = pointToBlockMap.getOrDefault(originalPoint, "其他");

                    // 计算月份
                    int month = getMonthFromTimestamp(vo.getCreateTime());

                    // 更新计数器
                    Map<Integer, Integer> monthCounts = finalBlockMonthlyCounts.computeIfAbsent(block, k -> new HashMap<>());
                    int current = monthCounts.getOrDefault(month, 0);
                    monthCounts.put(month, current + (vo.isPraise() ? 1 : -1));
                });

        // 处理负数和非分类数据
        blockMonthlyCounts = blockMonthlyCounts.entrySet().stream()
                .filter(entry -> !"未分类".equals(entry.getKey())) // 过滤掉未映射的评价
                .collect(Collectors.toMap(
                        Map.Entry::getKey,
                        entry -> entry.getValue().entrySet().stream()
                                .collect(Collectors.toMap(
                                                Map.Entry::getKey,
                                                e -> Math.max(e.getValue(), 0)
                                        )
                                )));

        // 6. 处理每月数据，传入主观评价统计结果

        return processMonthlyData(records,res,rightCount,wrongCount,
                targetStudents,
                monthlyResults,
                knowledgeBlockMap,
                getMonthsBetween(moralDto.getStartTime(), moralDto.getEndTime()),
                blockMonthlyCounts
        );
    }


    // 新增方法：添加综合得分
    private List<Map<String, Object>> addOverallScore(
            List<Map<String, Object>> monthlyData,
            Set<String> knowledgeBlocks
    ) {
        // 创建综合得分容器
        Map<String, Double> totalScores = new HashMap<>();
        Map<String, Integer> scoreCounts = new HashMap<>();

        // 累加所有月份得分
        for (Map<String, Object> monthData : monthlyData) {
            for (String block : knowledgeBlocks) {
                Double score = (Double) monthData.get(block);
                if (score != null) {
                    totalScores.put(block, totalScores.getOrDefault(block, 0.0) + score);
                    scoreCounts.put(block, scoreCounts.getOrDefault(block, 0) + 1);
                }
            }
        }

        // 计算平均分
        Map<String, Object> overall = new LinkedHashMap<>();
        overall.put("type", "overall");
        for (String block : knowledgeBlocks) {
            int count = scoreCounts.getOrDefault(block, 1);
            double avg = totalScores.getOrDefault(block, 0.0) / count;
            overall.put(block, Double.parseDouble(String.format("%.2f", avg)));
        }

        // 创建新的结果列表（保持原数据不变）
        List<Map<String, Object>> result = new ArrayList<>(monthlyData);
        result.add(overall);

        return result;
    }

    private List<LessonRecord> getLessonRecords(MoralDto moralDto, String schoolId) {
        LessonRecordQueryService queryService = new LessonRecordQueryService(lessonRecordRepository);
        try {
            return queryService.queryLessonsInParallel(
                    String.format(PK.PK_LESSON_RECORD, schoolId),
                    moralDto.getStartTime(),
                    moralDto.getEndTime(),
                    moralDto.getSubjectId(),
                    null,
                    null,
                    moralDto.getPeriodId()
            );
        } catch (InterruptedException | ExecutionException e) {
            throw new ServiceException(ErrorCode.SYSTEM_ERROR.getCode(), "课程查询异常");
        } finally {
            queryService.shutdown();
        }
    }

    private List<ExamVo> getExamsWithKnowledge(MoralDto moralDto, List<LessonRecord> records,
                                               Map<String, List<List<String>>> examKnowledgeMap,
                                               Map<String, List<Double>> points) {
        if (records == null || records.isEmpty()) {
            return Collections.emptyList();
        }

        List<String> lessonRecordIds = records.stream()
                .map(LessonRecord::getId)
                .filter(id -> id != null && !id.isEmpty())
                .distinct()
                .collect(Collectors.toList());

        if (lessonRecordIds.isEmpty()) {
            return Collections.emptyList();
        }

        List<ExamVo> exams = examRepository.findExamsByIds(moralDto.getSource(), lessonRecordIds);

        exams.forEach(exam -> {
            if (!exam.getPapers().isEmpty() && exam.getPapers().get(0).getKnowledge() != null) {
                examKnowledgeMap.put(exam.getId(), exam.getPapers().get(0).getKnowledge());
                points.put(exam.getId(), exam.getPapers().get(0).getPoint());
            }
        });

        return exams.stream()
                .filter(exam -> !exam.getClasses().isEmpty())
                .collect(Collectors.toList());
    }

    private Map<Integer, List<ExamResultWrapper>> getMonthlyExamResults(
            String schoolId, String classId, List<ExamVo> exams,
            List<LessonRecord> records, Map<String, List<List<String>>> examKnowledgeMap,
            Map<String, List<Double>> points, List<String> studentIds) { // 新增studentIds参数

        Map<Integer, List<ExamResultWrapper>> monthlyResults = new HashMap<>();

        if (classId == null) {
            exams.forEach(exam -> {
                List<ExamClassResult> results = examClassResultRepository.findByStudentId(
                        String.format(PK.CLASS_RESULT, schoolId), studentIds.get(0), exam.getId()
                );

                results.forEach(result -> {
                    records.stream()
                            .filter(r -> r.getId().equals(exam.getLessonRecordId()))
                            .findFirst()
                            .ifPresent(record -> {
                                int month = getMonthFromTimestamp(record.getStartTime());
                                List<List<String>> knowledge = examKnowledgeMap.get(exam.getId());
                                List<Double> point = points.get(exam.getId());

                                // 处理所有相关学生
                                result.getStudentIds().stream()
                                        .filter(studentIds::contains) // 仅处理班级学生
                                        .forEach(studentId -> {
                                            monthlyResults.computeIfAbsent(month, k -> new ArrayList<>())
                                                    .add(new ExamResultWrapper(
                                                            exam.getId(),
                                                            result,
                                                            knowledge,
                                                            point,
                                                            studentId // 新增学生ID字段
                                                    ));
                                        });
                            });
                });
            });
        }else {
            exams.forEach(exam -> {
                List<ExamClassResult> results = examClassResultRepository.findById(
                        String.format(PK.CLASS_RESULT, schoolId), classId, exam.getId()
                );

                results.forEach(result -> {
                    records.stream()
                            .filter(r -> r.getId().equals(exam.getLessonRecordId()))
                            .findFirst()
                            .ifPresent(record -> {
                                int month = getMonthFromTimestamp(record.getStartTime());
                                List<List<String>> knowledge = examKnowledgeMap.get(exam.getId());
                                List<Double> point = points.get(exam.getId());

                                // 处理所有相关学生
                                result.getStudentIds().stream()
                                        .filter(studentIds::contains) // 仅处理班级学生
                                        .forEach(studentId -> {
                                            monthlyResults.computeIfAbsent(month, k -> new ArrayList<>())
                                                    .add(new ExamResultWrapper(
                                                            exam.getId(),
                                                            result,
                                                            knowledge,
                                                            point,
                                                            studentId // 新增学生ID字段
                                                    ));
                                        });
                            });
                });
            });

        }

        return monthlyResults;
    }

    private Map<String,List<Map<String, Object>>> processMonthlyData(
            List<LessonRecord> records,List<RecordVo> res,int rightCount,int wrongCount,
            List<String> targetStudentIds,
            Map<Integer, List<ExamResultWrapper>> monthlyResults,
            Map<String, List<String>> knowledgeBlockMap,
            Set<Integer> months,
            Map<String, Map<Integer, Integer>> blockMonthlyCounts) {

        Map<String,List<Map<String, Object>>> detailList = new HashMap<>();
        List<Map<String, Object>> details = new ArrayList<>();
        Map<String, Object> detail = new HashMap<>();
        detail.put("rightCount", rightCount);
        detail.put("wrongCount", wrongCount);
        detail.put("recordCount", records.size());
        detail.put("resCount", res.size());
        details.add(detail);
        detailList.put("detail",details);
        List<Map<String, Object>> collect = months.stream().map(month -> {
                    Map<String, Object> monthEntry = new LinkedHashMap<>();
                    monthEntry.put("month", month);
                    List<Map<String, Object>> scoreList = new ArrayList<>();

                    // 按学生分组考试结果
                    Map<String, List<ExamResultWrapper>> studentResults = monthlyResults
                            .getOrDefault(month, Collections.emptyList())
                            .stream()
                            .filter(wrapper -> targetStudentIds.contains(wrapper.getStudentId()))
                            .collect(Collectors.groupingBy(ExamResultWrapper::getStudentId));

                    // 初始化知识块总分计数器
                    Map<String, Double> blockTotalScores = new HashMap<>();
                    knowledgeBlockMap.keySet().forEach(block -> blockTotalScores.put(block, 0.0));

                    // 遍历所有目标学生
                    targetStudentIds.forEach(studentId -> {
                        List<ExamResultWrapper> wrappers = studentResults.getOrDefault(studentId, Collections.emptyList());
                        List<ExamClassResult> examResults = wrappers.stream()
                                .map(ExamResultWrapper::getResult)
                                .collect(Collectors.toList());

                        // 1. 计算知识点得分（保留原始逻辑）
                        Map<String, Double> knowledgeScores = calculateMonthlyKnowledgeScores(
                                studentId,
                                examResults,
                                wrappers.stream().collect(Collectors.toMap(
                                        ExamResultWrapper::getExamId,
                                        ExamResultWrapper::getKnowledge)),
                                wrappers.stream().collect(Collectors.toMap(
                                        ExamResultWrapper::getExamId,
                                        ExamResultWrapper::getPoints))
                        );

                        // 2. 计算每个知识块的客观得分（新增关键逻辑）
                        Map<String, Double> objectiveScores = new HashMap<>();
                        knowledgeBlockMap.forEach((block, knowledges) -> {
                            // 获取该学生当前月份被测试的知识点
                            Set<String> monthlyTestedKnowledges = knowledgeScores.keySet();
                            List<String> testedKnowledges = knowledges.stream()
                                    .filter(monthlyTestedKnowledges::contains)
                                    .collect(Collectors.toList());

                            // 计算客观得分（原始逻辑）
                            double finalScore;
                            if (testedKnowledges.isEmpty()) {
                                finalScore = 60.0;
                            } else {
                                double averageCorrectRate = testedKnowledges.stream()
                                        .mapToDouble(k -> knowledgeScores.get(k))
                                        .average()
                                        .orElse(60.0);
                                finalScore = 60.0 + (averageCorrectRate * 0.4);
                                finalScore = Math.min(finalScore, 100.0);
                            }
                            finalScore = Double.parseDouble(String.format("%.2f", finalScore));
                            objectiveScores.put(block, finalScore);
                        });

                        // 3. 处理主观评价得分
                        Map<String, Double> subjectiveScores = calculateSubjectiveScores(
                                knowledgeBlockMap,
                                blockMonthlyCounts,
                                month,
                                studentId
                        );

                        // 4. 合并主客观得分（调整权重）
                        knowledgeBlockMap.keySet().forEach(block -> {
                            double objectiveScore = objectiveScores.getOrDefault(block, 60.0);
                            double subjectiveScore = subjectiveScores.getOrDefault(block, 60.0);
                            double combinedScore = (subjectiveScore * 0.6) + (objectiveScore * 0.4);
                            blockTotalScores.merge(block, combinedScore, Double::sum);
                        });
                    });

                    // 计算班级平均分
                    int studentCount = targetStudentIds.size();
                    knowledgeBlockMap.keySet().forEach(block -> {
                        double avg = studentCount > 0 ?
                                blockTotalScores.get(block) / studentCount : 0.0;
                        Map<String, Object> scoreEntry = new LinkedHashMap<>();
                        scoreEntry.put("name", block);
                        scoreEntry.put("score", Double.parseDouble(String.format("%.2f", avg)));
                        scoreList.add(scoreEntry);
                    });

                    // 按知识块名称排序（可选）
                    scoreList.sort(Comparator.comparing(m -> (String) m.get("name")));

                    monthEntry.put("types", scoreList);
                    return monthEntry;
                }).sorted(Comparator.comparingInt(m -> (Integer) m.get("month")))
                .collect(Collectors.toList());
        detailList.put("collect", collect);
        return detailList;
    }

    // 新增方法：计算主观评分转换后的得分
    private Map<String, Double> calculateSubjectiveScores(
            Map<String, List<String>> knowledgeBlockMap,
            Map<String, Map<Integer, Integer>> blockMonthlyCounts,
            int month,
            String studentId) {

        Map<String, Double> subjectiveScores = new HashMap<>();
        knowledgeBlockMap.keySet().forEach(block -> {
            // 获取该学生本月的评价次数
            int praiseCount = blockMonthlyCounts.getOrDefault(block, new HashMap<>())
                    .getOrDefault(month, 0);

            // 次数转分数公式
            final double K = 50.0;
            double convertedScore = (praiseCount * 40.0) / (praiseCount + K);
            convertedScore = Math.min(convertedScore, 40.0);

            // 主观总分 = 基础60 + 转换分
            double totalScore = 60.0 + convertedScore;
            subjectiveScores.put(block, Double.parseDouble(String.format("%.2f", totalScore)));
        });

        return subjectiveScores;
    }

    private Map<String, Double> calculateMonthlyKnowledgeScores(String studentId,
                                                                List<ExamClassResult> examResults,
                                                                Map<String, List<List<String>>> knowledgeMap,
                                                                Map<String, List<Double>> points) {
        Map<String, Double> knowledgeTotalScore = new HashMap<>();
        Map<String, Double> knowledgeTotalAverage = new HashMap<>();
        Map<String, Integer> knowledgeExamCount = new HashMap<>();

        // 处理无考试数据的情况，初始化为60分
        if (examResults.isEmpty()) {
            knowledgeMap.values().stream()
                    .flatMap(List::stream)
                    .flatMap(List::stream)
                    .distinct()
                    .forEach(knowledge -> knowledgeTotalScore.put(knowledge, 60.0));
            return knowledgeTotalScore;
        }

        // 遍历每个考试结果
        for (ExamClassResult examResult : examResults) {
            int studentIndex = examResult.getStudentIds().indexOf(studentId);
            if (studentIndex == -1) continue;
            if (examResult.getStatus().get(studentIndex) == 1) continue; // 跳过无效状态

            List<List<String>> knowledgeList = knowledgeMap.get(examResult.getExamId());
            List<Double> pointList = points.get(examResult.getExamId());
            if (knowledgeList == null || pointList == null) continue;

            List<Double> studentScores = examResult.getStudentScores().get(studentIndex);
            if (studentScores == null || knowledgeList.size() != studentScores.size()) continue;

            // 计算当前考试的知识点得分
            Map<String, Double> currentExamScores = new HashMap<>();
            Map<String, Integer> currentExamCounts = new HashMap<>();

            for (int i = 0; i < studentScores.size(); i++) {
                List<String> knowledges = knowledgeList.get(i);
                double score = studentScores.get(i);
                if (knowledges.isEmpty() || score < 0) continue;

                double perKnowledgeScore = score / knowledges.size();
                knowledges.forEach(knowledge -> {
                    currentExamScores.merge(knowledge, perKnowledgeScore, Double::sum);
                    currentExamCounts.merge(knowledge, 1, Integer::sum);
                });
            }

            // 更新累计数据
            currentExamScores.forEach((knowledge, total) -> {
                double average = total / currentExamCounts.get(knowledge);
                knowledgeTotalAverage.merge(knowledge, average, Double::sum);
                knowledgeExamCount.merge(knowledge, 1, Integer::sum);
            });
        }

        // 计算最终得分（基础60 + 实际得分，限制范围）
        knowledgeTotalAverage.forEach((knowledge, total) -> {
            int count = knowledgeExamCount.get(knowledge);
            double finalScore = 60.0 + Math.min(total / count, 40.0);
            knowledgeTotalScore.put(knowledge, Math.min(finalScore, 100.0));
        });

        // 确保所有知识点都有值（处理部分知识点未出现在考试中的情况）
        knowledgeMap.values().stream()
                .flatMap(List::stream)
                .flatMap(List::stream)
                .distinct()
                .forEach(knowledge -> knowledgeTotalScore.putIfAbsent(knowledge, 60.0));

        // 保留两位小数
        knowledgeTotalScore.replaceAll((k, v) -> Double.parseDouble(String.format("%.2f", v)));
        return knowledgeTotalScore;
    }


    // 辅助类封装考试结果和知识点
    @Data
    @AllArgsConstructor
    private static class ExamResultWrapper {
        private String examId;
        private ExamClassResult result;
        private List<List<String>> knowledge; // 每个题目对应的知识点列表
        private List<Double> points;
        private String studentId; // 新增字段
    }

    // 时间处理工具方法
    private int getMonthFromTimestamp(Long timestamp) {
        return LocalDateTime.ofInstant(Instant.ofEpochMilli(timestamp), ZoneId.systemDefault())
                .getMonthValue();
    }

    private Set<Integer> getMonthsBetween(Long start, Long end) {
        Set<Integer> months = new TreeSet<>();
        LocalDateTime startDate = Instant.ofEpochMilli(start).atZone(ZoneId.systemDefault()).toLocalDateTime();
        LocalDateTime endDate = Instant.ofEpochMilli(end).atZone(ZoneId.systemDefault()).toLocalDateTime();

        while (!startDate.isAfter(endDate)) {
            months.add(startDate.getMonthValue());
            startDate = startDate.plusMonths(1);
        }
        return months;
    }

    // 学期配置实体（对应JSON结构）
    @Data
    @AllArgsConstructor
    public static class SemesterConfig {
        private String name;
        private int start;  // 1表示学年开始学期
        private int month;  // 月份（1-12）
        private int day;    // 日期（1-31）
        private String id;
    }

    // 学期时间范围实体
    @Data
    @AllArgsConstructor
    public static class SemesterPeriod {
        private String name;
        private LocalDate startDate;
        private LocalDate endDate;

        // 转换为时间戳（用于查询）
        public Long getStartTimestamp() {
            return startDate.atStartOfDay(ZoneId.systemDefault())
                    .toInstant().toEpochMilli();
        }

        public Long getEndTimestamp() {
            return endDate.atTime(23, 59, 59)
                    .atZone(ZoneId.systemDefault())
                    .toInstant().toEpochMilli();
        }
    }

    // 分学期比对，分析 学期数据
    public Map<String, Object> getStudentSemesterScores(MoralDto moralDto,HttpServletRequest request) {
        // 1. 获取学期配置
        List<School.Semester> semesters = schoolRepository.findSemestersById(moralDto.getCode(), moralDto.getPeriodId());
        List<SemesterConfig> configs = new ArrayList<>();
        for (School.Semester semester : semesters) {
            configs.add(new SemesterConfig(semester.getName(), semester.getStart(), semester.getMonth(), semester.getDay(), semester.getId()));
        }
        // 2. 计算学期时间范围
        Map<String, SemesterPeriod> periods = calculateSemesters(configs);
        SemesterPeriod current = periods.get("current");
        SemesterPeriod last = periods.get("last");

        // 学生数据处理
        Map<String, Object> studentResult = Collections.emptyMap();
        if (StringUtils.isNotBlank(moralDto.getStudentId())) {
            studentResult = processIndividual(moralDto, current, last, request);
        }
        // 班级数据处理
        Map<String, Object> classResult = Collections.emptyMap();
        if (StringUtils.isNotBlank(moralDto.getClassId())) {
            classResult = processClass(moralDto, current, last, request);
        }

        // 组合最终结果
        return combineAllResults(moralDto, studentResult, classResult);
    }

    private Map<String, Object> combineAllResults(MoralDto dto,
                                                  Map<String, Object> studentResult,
                                                  Map<String, Object> classResult) {
        Map<String, Object> finalResult = new LinkedHashMap<>();

        // 学生维度数据
        finalResult.put("student", studentResult);

        // 班级维度数据
        if (!classResult.isEmpty()) {
            finalResult.put("class", classResult);
        }

        return finalResult;
    }

    private Map<String, Object> processIndividual(MoralDto dto,
                                                  SemesterPeriod current,
                                                  SemesterPeriod last,
                                                  HttpServletRequest request) {
        // 原有学生处理逻辑
        Map<String, Object> currentData = processSemesterData(dto, current, request, true, false);
        Map<String, Object> lastData = processSemesterData(dto, last, request, false,false);
        return combineResults(dto, currentData, lastData);
    }

    private Map<String, Object> processClass(MoralDto dto,
                                             SemesterPeriod current,
                                             SemesterPeriod last,
                                             HttpServletRequest request) {
        // 克隆DTO并清除学生ID
        MoralDto classDto = new MoralDto();
        classDto.setCode(dto.getCode());
        classDto.setPeriodId(dto.getPeriodId());
        classDto.setClassId(dto.getClassId());
        classDto.setSubjectId(dto.getSubjectId());
        classDto.setSemesterId(dto.getSemesterId());
        classDto.setStartTime(dto.getStartTime());
        classDto.setEndTime(dto.getEndTime());
        classDto.setAcademicYearId(dto.getAcademicYearId());
        classDto.setTargetType(dto.getTargetType());
        classDto.setYear(dto.getYear());
        classDto.setGrade(dto.getGrade());
        classDto.setGradeName(dto.getGradeName());
        classDto.setSource(dto.getSource());
        classDto.setTmdId(dto.getTmdId());
        classDto.setStudentId(null);

        Map<String, Object> currentData = processSemesterData(classDto, current, request, true,true);
        Map<String, Object> lastData = processSemesterData(classDto, last, request, false,true);
        return combineClassResults(classDto, currentData, lastData);
    }

    private Map<String, Object> combineClassResults(MoralDto dto,
                                                    Map<String, Object> current,
                                                    Map<String, Object> last) {
        Map<String, Object> result = new LinkedHashMap<>();
        result.put("classId", dto.getClassId());

        // 构建班级数据结构（类似学生结构）
        List<Map<String, Object>> scores = buildClassScoreBlocks(dto, current, last);
        result.put("scores", scores);

        return result;
    }

    private List<Map<String, Object>> buildClassScoreBlocks(MoralDto dto,
                                                            Map<String, Object> current,
                                                            Map<String, Object> last) {

        Map<String, Object> result = new LinkedHashMap<>();
        result.put("classId", dto.getClassId());


        Appraise appraise = appraiseRepository.findAppraiseBySchoolIdAndPeriodIdAndCode(dto.getCode(), dto.getPeriodId(), PK.PK_APPRAISE);
        // 获取知识块配置
        appraise = evaluationService.buildTree(appraise);
        Set<String> knowledgeBlocks = loadKnowledgeBlocks(appraise);

        // 类似学生数据结构，但含班级统计信息
        Appraise finalAppraise = appraise;
        return knowledgeBlocks.stream().map(block -> {
            Map<String, Object> blockData = new LinkedHashMap<>();
            blockData.put("name", block);

            // 处理当前学期班级平均分（空值安全+格式化）
            double currentScore = Optional.ofNullable(current)
                    .map(c -> (Map<String, Double>) c.get("blockScores"))
                    .map(scores -> scores.getOrDefault(block, 0.0))
                    .orElse(0.0);
            currentScore = new BigDecimal(currentScore).setScale(2, RoundingMode.HALF_UP).doubleValue();
            blockData.put("classCurrentScore", currentScore);

            // 处理上学期班级平均分（空值安全+格式化）
            double lastScore = Optional.ofNullable(last)
                    .map(l -> (Map<String, Double>) l.get("blockScores"))
                    .map(scores -> scores.getOrDefault(block, 0.0))
                    .orElse(0.0);
            lastScore = new BigDecimal(lastScore).setScale(2, RoundingMode.HALF_UP).doubleValue();
            blockData.put("classLastScore", lastScore);

            // 获取当前知识块下的所有知识点
            Set<String> blockKnowledgePoints = getKnowledgePointsForBlock(block, finalAppraise);
            // 获取次数统计（空值安全）
            Map<String, Integer> counts = current != null && current.containsKey("knowledgeCounts")
                    ? (Map<String, Integer>) current.get("knowledgeCounts")
                    : Collections.emptyMap();

           /* // 知识点出现总次数（兼容旧逻辑）
            blockKnowledgePoints.forEach(point ->
                    blockData.put(point, counts.getOrDefault(point, 0))
            );*/

            // 构建知识点明细列表
            List<Map<String, Object>> knowledgePoints = new ArrayList<>();
            blockKnowledgePoints.forEach(point -> {
                Map<String, Object> pointData = new HashMap<>();
                pointData.put("name", point);
                pointData.put("count", counts.getOrDefault(point, 0));
                knowledgePoints.add(pointData);
            });
            blockData.put("knowledgePoints", knowledgePoints);

            return blockData;
        }).collect(Collectors.toList());
    }

    // 核心学期计算逻辑
    private Map<String, SemesterPeriod> calculateSemesters(List<SemesterConfig> semesters) {
        LocalDate now = LocalDate.now();
        int currentYear = now.getYear();

        // 1. 确定学年起始学期
        SemesterConfig startSemester = semesters.stream()
                .filter(s -> s.start == 1)
                .findFirst()
                .orElseThrow(() -> new IllegalArgumentException("未配置起始学期"));


        // 2. 计算当前所属学年
        int academicYear = calculateAcademicYear(startSemester, LocalDate.now());

        // 3. 生成当前学年学期
        List<SemesterPeriod> currentYearSemesters = generateYearSemesters(
                semesters, academicYear, startSemester);

        // 4. 确定当前学期
        SemesterPeriod current = currentYearSemesters.stream()
                .filter(sp -> !now.isBefore(sp.startDate) && !now.isAfter(sp.endDate))
                .findFirst()
                .orElse(null);

        // 5. 确定上学期
        SemesterPeriod last = findLastSemester(current, semesters, academicYear, startSemester);

        return new HashMap<String, SemesterPeriod>() {{
            put("current", current);
            put("last", last);
        }};
    }

    // 增强学术年度计算方法
    private int calculateAcademicYear(SemesterConfig startSemester, LocalDate currentDate) {
        int currentYear = currentDate.getYear();
        int currentMonth = currentDate.getMonthValue();

        return (currentMonth < startSemester.month) ? currentYear -1 : currentYear;
    }
    // 生成学年学期时间范围
    private List<SemesterPeriod> generateYearSemesters(List<SemesterConfig> semesters,
                                                       int academicYear,
                                                       SemesterConfig startSemester) {
        List<SemesterPeriod> periods = new ArrayList<>();

        // 1. 生成各学期开始日期
        for (SemesterConfig sc : semesters) {
            int year = academicYear;
            if (sc.month < startSemester.month) {
                year += 1; // 跨年学期（如 2024 学年下学期是 2025 年 2 月）
            }
            LocalDate startDate = LocalDate.of(year, sc.month, sc.day);
            periods.add(new SemesterPeriod(sc.name, startDate, null));
        }

        periods.sort(Comparator.comparing(SemesterPeriod::getStartDate));
        // 2. 计算结束日期
        for (int i = 0; i < periods.size(); i++) {
            SemesterPeriod curr = periods.get(i);

            if (i < periods.size() - 1) {
                // 非最后学期：下一学期开始前 1 天
                curr.setEndDate(periods.get(i + 1).getStartDate().minusDays(1));
            } else {
                // 最后学期：学年结束年份的 7 月 31 日（2025-07-31）
                int endYear = academicYear + 1; // 关键修改：统一用学年结束年份
                curr.setEndDate(LocalDate.of(endYear, 7, 31));
            }

            // 3. 校验时间顺序
            if (curr.getStartDate().isAfter(curr.getEndDate())) {
                throw new IllegalStateException("学期日期无效: " + curr.getName()
                        + " 开始日期(" + curr.getStartDate()
                        + ") 不能晚于结束日期(" + curr.getEndDate() + ")");
            }
        }

        return periods;
    }

    // 查找上学期（含跨学年处理）
    private SemesterPeriod findLastSemester(SemesterPeriod current,
                                            List<SemesterConfig> semesters,
                                            int academicYear,
                                            SemesterConfig startSemester) {
        if (current == null) return null;

        List<SemesterPeriod> currentYearSemesters = generateYearSemesters(
                semesters, academicYear, startSemester);

        int index = currentYearSemesters.indexOf(current);
        if (index > 0) {
            return currentYearSemesters.get(index-1);
        } else {
            // 获取去年最后一个学期
            List<SemesterPeriod> lastYear = generateYearSemesters(
                    semesters, academicYear-1, startSemester);
            return lastYear.isEmpty() ? null : lastYear.get(lastYear.size()-1);
        }
    }

    // 处理学期数据
    private Map<String, Object> processSemesterData(MoralDto moralDto,
                                                    SemesterPeriod semester,
                                                    HttpServletRequest request,
                                                    boolean isCurrent,
                                                    boolean isClassMod) {
        Map<String, Object> result = new HashMap<>();

        // 1. 设置时间范围查询条件
        moralDto.setStartTime(convertToTimestamp(semester.startDate));
        moralDto.setEndTime(convertToTimestamp(semester.endDate));

        // 2. 获取原始分析数据
        Map<String, Object> analysisData = getAnalysis(moralDto, request);

        if (isClassMod) {
            // 班级知识点统计
            List<Map<String, Object>> scores = (List<Map<String, Object>>) analysisData.get("scores");
            Map<String, Integer> knowledgeCounts = scores.stream()
                    .map(s -> (List<Map<String, Object>>) s.get("appraises"))
                    .flatMap(List::stream)
                    .collect(Collectors.toMap(
                            a -> (String) a.get("appraiseName"),
                            a -> 1,
                            Integer::sum
                    ));
            result.put("knowledgeCounts", knowledgeCounts);
            // 班级版块平均分
            Map<String, Double> classBlockAverages = calculateClassAverages(analysisData);
            result.put("blockScores", classBlockAverages);
        } else {
            // 3. 提取知识点次数（仅当前学期）
            if (isCurrent) {
                List<Map<String, Object>> scores = (List<Map<String, Object>>) analysisData.get("scores");
                Map<String, Integer> knowledgeCounts = scores.stream()
                        .filter(s -> moralDto.getStudentId().equals(s.get("studentId")))
                        .findFirst()
                        .map(s -> (List<Map<String, Object>>) s.get("appraises"))
                        .map(appraises -> appraises.stream()
                                .collect(Collectors.toMap(
                                        a -> (String) a.get("appraiseName"),
                                        a -> 1,
                                        Integer::sum
                                )))
                        .orElse(new HashMap<>());
                result.put("knowledgeCounts", knowledgeCounts);
            }

            // 4. 提取综合得分
            Map<String, Double> blockScores = extractBlockScores(analysisData, moralDto.getStudentId());
            result.put("blockScores", blockScores);

            // 5. 提取班级均分
            Map<String, List<Map<String, Object>>> classScoreRate = (Map<String, List<Map<String, Object>>>) analysisData.get("classScoreRate");
            List<Map<String, Object>> classScoreList = classScoreRate.get("classScoreRates");
            Map<String, Double> classAverages = classScoreList.stream()
                    .findFirst()
                    .map(c -> (List<Map<String, Object>>) c.get("blocks"))
                    .map(blocks -> blocks.stream()
                            .collect(Collectors.toMap(
                                    b -> (String) b.get("name"),
                                    b -> (Double) b.get("score")
                            )))
                    .orElse(new HashMap<>());
            result.put("classAverage", classAverages);
        }
        return result;
    }

    private Map<String, Double> calculateClassAverages(Map<String, Object> analysisData) {
        return ((List<Map<String, Object>>) analysisData.get("scores")).stream()
                .map(s -> (Map<String, Map<String, Object>>) s.get("scores"))
                .flatMap(m -> m.entrySet().stream())
                .collect(Collectors.groupingBy(
                        Map.Entry::getKey,
                        Collectors.averagingDouble(e -> (Double)e.getValue().get("compositeScore"))
                ));
    }

    private Map<String, Double> extractBlockScores(Map<String, Object> data, String studentId) {
        return ((List<Map<String, Object>>) data.get("scores")).stream()
                .filter(s -> studentId.equals(s.get("studentId")))
                .findFirst()
                .map(scoreMap -> (Map<String, Map<String, Object>>) scoreMap.get("scores")) // 获取知识块得分对象
                .map(scoresMap -> scoresMap.entrySet().stream()
                        .collect(Collectors.toMap(
                                Map.Entry::getKey, // 知识块名称（如"道德修养"）
                                entry -> (Double) entry.getValue().get("compositeScore") // 提取复合分数
                        ))
                )
                .orElse(new HashMap<>());
    }


    // 辅助方法：转换LocalDate为时间戳
    private long convertToTimestamp(LocalDate date) {
        return date.atStartOfDay(ZoneId.systemDefault())
                .toInstant()
                .toEpochMilli();
    }

    // 结果合并方法
    private Map<String, Object> combineResults(MoralDto moralDto,
                                               Map<String, Object> currentData,
                                               Map<String, Object> lastData) {
        Map<String, Object> result = new LinkedHashMap<>();
        result.put("studentId", moralDto.getStudentId());


        Appraise appraise = appraiseRepository.findAppraiseBySchoolIdAndPeriodIdAndCode(moralDto.getCode(), moralDto.getPeriodId(), PK.PK_APPRAISE);
        // 获取知识块配置
        appraise = evaluationService.buildTree(appraise);
        Set<String> knowledgeBlocks = loadKnowledgeBlocks(appraise);

        List<Map<String, Object>> scores = new ArrayList<>();

        for (String block : knowledgeBlocks) {
            Map<String, Object> blockData = new LinkedHashMap<>();
            blockData.put("name", block);

            Map<String, Double> currentBlockScores = (Map<String, Double>) currentData.get("blockScores");
            double moralScore = currentBlockScores.getOrDefault(block, 0.0); // 精确获取目标知识块
            blockData.put("TScore", moralScore);

            Map<String, Double> lastBlockScores = (Map<String, Double>) lastData.get("blockScores");
            double lastScore = lastBlockScores.getOrDefault(block, 0.0);
            blockData.put("LScore", lastScore);

            // 班级均分
            Map<String, Double> classAvg = (Map<String, Double>) currentData.get("classAverage");
            blockData.put("classScore", classAvg.getOrDefault(block, 0.0));

            // 处理知识点次数
            List<Map<String, Object>> knowledgePoints = new ArrayList<>();
            // 获取当前知识块下的所有知识点
            Set<String> blockKnowledgePoints = getKnowledgePointsForBlock(block, appraise);
            // 获取次数统计，若不存在则使用空Map
            Map<String, Integer> counts = currentData.containsKey("knowledgeCounts")
                    ? (Map<String, Integer>) currentData.get("knowledgeCounts")
                    : Collections.emptyMap();

            // 遍历所有知识点，设置次数
            for (String pointName : blockKnowledgePoints) {
                Map<String, Object> point = new HashMap<>();
                point.put("name", pointName);
                point.put("count", counts.getOrDefault(pointName, 0));
                knowledgePoints.add(point);
            }
            blockData.put("knowledgePoints", knowledgePoints);

            scores.add(blockData);
        }

        result.put("scores", scores);
        return result;
    }

    // 新增方法：根据知识块名称获取所有知识点
    private Set<String> getKnowledgePointsForBlock(String block, Appraise appraise) {
        Set<String> points = new LinkedHashSet<>();
        // 遍历appraise的子节点（知识块），找到匹配的块后收集其子节点（知识点）
        for (AppraiseTreeNode child : appraise.getNodes()) {
            if ("劳育".equals(child.getName())) {
                for (AppraiseTreeNode pointOne : child.getChildren()) {
                    if (block.equals(pointOne.getName())) {
                        for (AppraiseTreeNode pointTwo : pointOne.getChildren()) {
                            points.add(pointTwo.getName());
                        }
                        break;
                    }
                }

            }
        }
        return points;
    }


    private Set<String> loadKnowledgeBlocks(Appraise appraise) {
        // 从appraise配置获取所有劳育知识块
        Set<String> knowledgePoints = new HashSet<>();
        for (AppraiseTreeNode node : appraise.getNodes()) {
            if ("劳育".equals(node.getName())) {
                for (AppraiseTreeNode secondLevelNode : node.getChildren()) {
                    knowledgePoints.add(secondLevelNode.getName());
                }
            }
        }
        return knowledgePoints;
    }

    private boolean isBelongToBlock(String knowledge, String block,Appraise appraise) {
        // 实现知识点归属判断逻辑
        Map<String, List<String>> knowledgeBlockToPointsMap = getKnowledgeBlockToPointsMap(appraise);
        return knowledgeBlockToPointsMap.getOrDefault(block, Collections.emptyList())
                .contains(knowledge);
    }

}
