package com.xhkjedu.smarking.service.report.generate;

import com.alibaba.fastjson.JSON;
import com.xhkjedu.smarking.mapper.report.reportclass.*;
import com.xhkjedu.smarking.model.report.reportclass.*;
import com.xhkjedu.smarking.model.report.reportother.MsrReportparam;
import com.xhkjedu.smarking.model.report.reportstu.MsrStudent;
import com.xhkjedu.smarking.service.report.reportother.MsrReportparamService;
import com.xhkjedu.smarking.utils.MarkingUtil;
import com.xhkjedu.smarking.vo.report.reportclass.ClassTopVo;
import com.xhkjedu.smarking.vo.report.reportclass.RankRateGroupVo;
import com.xhkjedu.smarking.vo.report.reportother.RankGroupVo;
import com.xhkjedu.smarking.vo.report.reportother.SzJsonVo;
import com.xhkjedu.utils.N_Utils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 *@Description : 班级生成报告服务
 *@Author ywx
 *Date 2025/1/3 11:07
 **/
@Service
public class ReportGenerateClassService {
    @Resource
    private MsrReportparamService msrReportparamService;
    @Resource
    private MsrClassSubjectMapper msrClassSubjectMapper;
    @Resource
    private MsrClassTopMapper msrClassTopMapper;
    @Resource
    private MsrClassSubjectGradeMapper msrClassSubjectGradeMapper;
    @Resource
    private MsrClassRankgroupMapper msrClassRankgroupMapper;
    @Resource
    private MsrClassRankrateMapper msrClassRankrateMapper;
    @Resource
    private MsrClassSectionMapper msrClassSectionMapper;
    @Resource
    private MsrClassNearlineMapper msrClassNearlineMapper;
    @Resource
    private MsrClassGoodbadMapper msrClassGoodbadMapper;

    //班级学科前60分析
    public void saveClassTop(Integer examid, List<MsrStudent> msrStudents,Integer raid) {
        List<MsrClassTop> msrClassTops = new ArrayList<>();//班级学科前60分析
        Map<String, ClassTopVo> lsMap = new HashMap<>();//处于年级60%得分map
        Map<String, List<MsrStudent>> collect = MarkingUtil.getSubjectCollect(msrStudents);
        for (Map.Entry<String, List<MsrStudent>> entry : collect.entrySet()) {
            MarkingUtil.studentsDistinct(entry, null);
            String subjectid = entry.getKey().split("_")[1];
            List<Double> scores = entry.getValue().stream().map(MsrStudent::getStuscore).sorted().collect(Collectors.toList());
            Double lsscore = MarkingUtil.cynjdf(scores, 0.6);
            List<MsrStudent> lsstudents = entry.getValue().stream().filter(s -> s.getStuscore().compareTo(lsscore) >= 0).collect(Collectors.toList());
            ClassTopVo classTopVo = new ClassTopVo();
            classTopVo.setSubjectid(subjectid);
            classTopVo.setLsscore(lsscore);
            classTopVo.setXtnum(lsstudents.size());
            double average = lsstudents.stream().mapToDouble(MsrStudent::getStuscore).summaryStatistics().getAverage();
            classTopVo.setXtavgscore(N_Utils.formatDouble(average, 2));
            String xtstuids = lsstudents.stream().map(s -> s.getStudentid().toString()).collect(Collectors.joining(","));
            classTopVo.setXtstuids(xtstuids);
            lsMap.put(subjectid, classTopVo);
        }
        setClassTop(examid, collect, lsMap, msrClassTops,raid);
        Map<String, List<MsrStudent>> scCollect = msrStudents.stream().collect(Collectors.groupingBy(s -> s.getClassid() + "_" + s.getSubjectid()));
        setClassTop(examid, scCollect, lsMap, msrClassTops,raid);
        msrClassTopMapper.insertList(msrClassTops);
    }

    //班级学科前60计算
    private void setClassTop(Integer examid, Map<String, List<MsrStudent>> scCollect, Map<String, ClassTopVo> lsMap
            , List<MsrClassTop> msrClassTops,Integer raid) {
        Integer totalnum;
        String subjectid;
        for (Map.Entry<String, List<MsrStudent>> entry : scCollect.entrySet()) {
            String key = entry.getKey();
            Integer classid = N_Utils.obj2Int(key.split("_")[0]);
            subjectid = key.split("_")[1];
            List<MsrStudent> studentList = entry.getValue();
            totalnum = studentList.size();//区间总人数

            MsrClassTop msrClassTop = new MsrClassTop();
            msrClassTop.setRaid(raid);
            msrClassTop.setExamid(examid);
            msrClassTop.setClassid(classid);
            msrClassTop.setSubjectid(subjectid);
            msrClassTop.setStunum(totalnum);
            ClassTopVo classTopVo = lsMap.get(subjectid);//处于年级60%得分
            Double lsscore = classTopVo.getLsscore();
            List<MsrStudent> lsstudents = studentList.stream().filter(s -> s.getStuscore().compareTo(lsscore) >= 0).collect(Collectors.toList());
            msrClassTop.setBtnum(lsstudents.size());
            msrClassTop.setBtrate(N_Utils.getIntegerDivideAndMulitiply(msrClassTop.getBtnum(), totalnum));
            double average = lsstudents.stream().mapToDouble(MsrStudent::getStuscore).summaryStatistics().getAverage();
            msrClassTop.setBtavgscore(N_Utils.formatDouble(average, 2));
            String btstuids = lsstudents.stream().map(s -> s.getStudentid().toString()).collect(Collectors.joining(","));
            msrClassTop.setBtstuids(btstuids);
            msrClassTop.setXtnum(classTopVo.getXtnum());
            msrClassTop.setXtavgscore(classTopVo.getXtavgscore());
            msrClassTop.setXtstuids(classTopVo.getXtstuids());
            msrClassTops.add(msrClassTop);
        }
    }

    //班级学科四率等级分析
    public void saveClassSubjectGrade(Integer examid, String reportcode, List<MsrStudent> msrStudents,Integer raid) {
        Map<String, List<SzJsonVo>> qjMap = formatSzJson(msrReportparamService.getMsrReportParams(examid, "scorerate", reportcode));
        List<MsrClassSubjectGrade> msrClassSubjectGrades = new ArrayList<>();//班级学科分析
        Map<String, List<MsrStudent>> collect = MarkingUtil.getSubjectCollect(msrStudents);
        Map<String, Integer> rsMap = new HashMap<>();//学科人数map
        for (Map.Entry<String, List<MsrStudent>> entry : collect.entrySet()) {
            MarkingUtil.studentsDistinct(entry, rsMap);
        }
        setClassSubjectGrade(examid, reportcode, collect, qjMap, msrClassSubjectGrades, rsMap,raid);
        Map<String, List<MsrStudent>> scCollect = msrStudents.stream().collect(Collectors.groupingBy(s -> s.getClassid() + "_" + s.getSubjectid()));
        setClassSubjectGrade(examid, reportcode, scCollect, qjMap, msrClassSubjectGrades, rsMap,raid);
        msrClassSubjectGradeMapper.insertList(msrClassSubjectGrades);
    }

    //格式化报告参数
    private Map<String, List<SzJsonVo>> formatSzJson(List<MsrReportparam> list) {
        Map<String, List<SzJsonVo>> qjMap = new HashMap<>();
        for (MsrReportparam param : list) {
            qjMap.put(param.getSubjectid(), JSON.parseArray(param.getSzjson(), SzJsonVo.class));
        }
        return qjMap;
    }

    //班级学科四率等级计算
    private void setClassSubjectGrade(Integer examid, String reportcode, Map<String, List<MsrStudent>> scCollect
            , Map<String, List<SzJsonVo>> qjMap, List<MsrClassSubjectGrade> msrClassSubjectGrades
            , Map<String, Integer> rsMap,Integer raid) {
        int totalnum;
        String subjectid;
        for (Map.Entry<String, List<MsrStudent>> entry : scCollect.entrySet()) {
            String key = entry.getKey();
            Integer classid = N_Utils.obj2Int(key.split("_")[0]);
            subjectid = key.split("_")[1];
            List<SzJsonVo> list = qjMap.get(subjectid);
            List<MsrStudent> studentList = entry.getValue();
            totalnum = rsMap.get(subjectid);//科目总人数
            Double fullscore1 = studentList.get(0).getFullscore();
            for (SzJsonVo rg : list) {
                String qjname = rg.getDjkey();
                double min = MarkingUtil.mul(rg.getMinvalue(), fullscore1);
                double max = MarkingUtil.mul(rg.getMaxvalue(), fullscore1);
                List<MsrStudent> qjstudents;
                if (fullscore1.compareTo(max) == 0) {
                    qjstudents = studentList.stream().filter(s -> s.getStuscore().compareTo(min) >= 0).collect(Collectors.toList());
                } else {
                    qjstudents = studentList.stream().filter(s -> s.getStuscore().compareTo(min) >= 0 && s.getStuscore().compareTo(max) < 0).collect(Collectors.toList());
                }
                int qjnum = qjstudents.size();
                MsrClassSubjectGrade classSubjectGrade = new MsrClassSubjectGrade();
                classSubjectGrade.setRaid(raid);
                classSubjectGrade.setExamid(examid);
                classSubjectGrade.setSubjectid(subjectid);
                classSubjectGrade.setClassid(classid);
                classSubjectGrade.setReportcode(reportcode);
                classSubjectGrade.setRangename(qjname);
                classSubjectGrade.setRangenum(qjnum);
                classSubjectGrade.setRangerate(N_Utils.getIntegerDivideAndMulitiply(qjnum, totalnum));
                double qjavg = qjstudents.stream().mapToDouble(MsrStudent::getStuscore).summaryStatistics().getAverage();
                classSubjectGrade.setDjscore(N_Utils.formatDouble(qjavg, 2));
                classSubjectGrade.setDjrate(N_Utils.getDoubleDivideAndMulitiply(qjavg, fullscore1));
                String stuids = qjstudents.stream().map(s -> s.getStudentid().toString()).collect(Collectors.joining(","));
                classSubjectGrade.setStuids(stuids);
                msrClassSubjectGrades.add(classSubjectGrade);
            }
        }
        Map<String, List<MsrClassSubjectGrade>> collect = msrClassSubjectGrades.stream().collect(Collectors.groupingBy(g -> g.getSubjectid() + "_" + g.getRangename()));
        for (Map.Entry<String, List<MsrClassSubjectGrade>> entry : collect.entrySet()) {
            List<MsrClassSubjectGrade> nearlineList = entry.getValue();
            List<Integer> nums = new ArrayList<>();
            for (MsrClassSubjectGrade classSubjectGrade : nearlineList) {
                nums.add(classSubjectGrade.getRangenum());
            }
            Map<Integer, Integer> rspm = MarkingUtil.rspm(nums);//人数排名
            for (MsrClassSubjectGrade classSubjectGrade : nearlineList) {
                classSubjectGrade.setRangenumrank(rspm.get(classSubjectGrade.getRangenum()));
            }
        }
    }

    //班级学科分析
    public void saveClassSubject(Integer examid, List<MsrStudent> msrStudents,Integer raid) {
        List<MsrClassSubject> msrClassSubjects = new ArrayList<>();//班级学科分析
        Map<String, List<MsrStudent>> collect = MarkingUtil.getSubjectCollect(msrStudents);
        List<MsrReportparam> scorerate = msrReportparamService.getMsrReportParams(examid, "scorerate", "zh");
        Map<String, SzJsonVo> tsMap = new HashMap<>();//得分率头部学生比例map
        int subjectnum = 0;
        for (MsrReportparam reportparam : scorerate) {
            SzJsonVo sz = new SzJsonVo();
            String szjson = reportparam.getSzjson();
            Integer rptype = reportparam.getRptype();
            if (rptype.equals(2)) {
                Map<String, Object> map = JSON.parseObject(szjson, Map.class);
                sz.setAlltop(N_Utils.obj2Int(map.get("alltop")));
                sz.setAllbottom(N_Utils.obj2Int(map.get("allbottom")));
            }
            String subjectid = reportparam.getSubjectid();
            tsMap.put(subjectid, sz);
            if (!"zf".equals(subjectid)) {
                subjectnum++;
            }
        }
        Map<String, Integer> rsMap = new HashMap<>();//学科人数map
        Map<String, List<Integer>> qkMap = new LinkedHashMap<>();//全科及格率学生map
        for (Map.Entry<String, List<MsrStudent>> entry : collect.entrySet()) {
            MarkingUtil.studentsDistinct(entry, rsMap);
            String key = entry.getKey();
            String subjectid = key.split("_")[1];
            SzJsonVo sz = tsMap.get(subjectid);
            if (N_Utils.isTrueInteger(sz.getAlltop())) {
                List<MsrStudent> studentList = entry.getValue();
                List<Double> scores = studentList.stream().map(MsrStudent::getStuscore).sorted().collect(Collectors.toList());
                int totalnum = scores.size();
                int index = (int) Math.ceil(MarkingUtil.div(MarkingUtil.mul(sz.getAlltop(), totalnum), 100));
                if (index > totalnum) index = totalnum;
                int goodvalue = studentList.subList(totalnum - index, totalnum).stream().mapToInt(MsrStudent::getSchoolrank).summaryStatistics().getMax();
                int index2 = (int) Math.ceil(MarkingUtil.div(MarkingUtil.mul(sz.getAllbottom(), totalnum), 100));
                if (index2 > totalnum) index2 = totalnum;
                int badvalue = studentList.subList(0, index2).stream().mapToInt(MsrStudent::getSchoolrank).summaryStatistics().getMin();
                sz.setGoodvalue(goodvalue);
                sz.setBadvalue(badvalue);
            }
            //全科及格率
            if (subjectid.equals("zf")) {
                List<MsrClassSubjectGrade> grades = msrClassSubjectGradeMapper.listSubjectGradeForQk(examid, "zh");
                if (N_Utils.isListNotEmpty(grades)) {
                    Map<String, List<MsrClassSubjectGrade>> rcollect = grades.stream().collect(Collectors.groupingBy(MsrClassSubjectGrade::getRangename, LinkedHashMap::new, Collectors.toList()));
                    for (Map.Entry<String, List<MsrClassSubjectGrade>> rentry : rcollect.entrySet()) {
                        String rkey = rentry.getKey();
                        List<MsrClassSubjectGrade> gradeList = rentry.getValue();
                        String stuids = gradeList.get(0).getStuids();
                        List<Integer> ids = new ArrayList<>();
                        for (String id : stuids.split(",")) {
                            ids.add(N_Utils.obj2Int(id));
                        }
                        if (subjectnum == 1) {
                            qkMap.put(rkey, ids);
                        } else if (N_Utils.isListNotEmpty(ids)) {
                            for (int i = 1; i < gradeList.size(); i++) {
                                MsrClassSubjectGrade grade = gradeList.get(i);
                                String stuids2 = grade.getStuids();
                                List<Integer> ids2 = new ArrayList<>();
                                for (String id2 : stuids2.split(",")) {
                                    ids2.add(N_Utils.obj2Int(id2));
                                }
                                //交集
                                if (N_Utils.isListEmpty(ids2)) {
                                    ids = new ArrayList<>();
                                    break;
                                }
                                ids = ids.stream().filter(ids2::contains).collect(Collectors.toList());
                                if (N_Utils.isListEmpty(ids)) {
                                    ids = new ArrayList<>();
                                    break;
                                }

                            }
                        }
                        qkMap.put(rkey, ids);
                    }
                }
            }
        }
        List<MsrReportparam> params = msrReportparamService.getMsrReportParams(examid, "allrate", "all");
        SzJsonVo vo = JSON.parseObject(params.get(0).getSzjson(), SzJsonVo.class);
        String calformula = vo.getCalformula();
        Map<String, MsrClassSubject> csMap = new HashMap<>();//班级学科map
        setClassSubject(examid, collect, msrClassSubjects, csMap, calformula, tsMap, qkMap,raid);
        Map<String, List<MsrStudent>> scCollect = msrStudents.stream().collect(Collectors.groupingBy(s -> s.getClassid() + "_" + s.getSubjectid()));
        setClassSubject(examid, scCollect, msrClassSubjects, csMap, calformula, tsMap, qkMap,raid);

        Map<String, List<MsrClassSubject>> scollect = msrClassSubjects.stream().collect(Collectors.groupingBy(MsrClassSubject::getSubjectid));
        for (Map.Entry<String, List<MsrClassSubject>> entry : scollect.entrySet()) {
            List<MsrClassSubject> nearlineList = entry.getValue();
            if (entry.getKey().equals("zf")) {
                Map<String, List<Integer>> qknum = new LinkedHashMap<>();
                for (MsrClassSubject cs : nearlineList) {
                    List<MsrClassSubjectGrade> grades = cs.getGrades();
                    for (MsrClassSubjectGrade grade : grades) {
                        String rangename = grade.getRangename();
                        Integer rangenum = grade.getRangenum();
                        if (qknum.containsKey(rangename)) {
                            qknum.get(rangename).add(rangenum);
                        } else {
                            qknum.put(rangename, new ArrayList<>(Collections.singletonList(rangenum)));
                        }
                    }
                }
                Map<String, Map<Integer, Integer>> qkpm = new LinkedHashMap<>();
                for (Map.Entry<String, List<Integer>> entry2 : qknum.entrySet()) {
                    Map<Integer, Integer> rspm = MarkingUtil.rspm(entry2.getValue());
                    qkpm.put(entry2.getKey(), rspm);
                }

                for (MsrClassSubject cs : nearlineList) {
                    List<MsrClassSubjectGrade> grades = cs.getGrades();
                    for (MsrClassSubjectGrade grade : grades) {
                        String rangename = grade.getRangename();
                        Integer rangenum = grade.getRangenum();
                        Integer rank = qkpm.get(rangename).get(rangenum);
                        grade.setRangenumrank(rank);
                    }
                    cs.setQkjgl(JSON.toJSONString(grades));
                }
            }
            List<Double> classavgscore = new ArrayList<>();//班级平均分列表
            List<Double> bzf = new ArrayList<>();//标准分列表
            List<Double> cjl = new ArrayList<>();//超均率列表
            List<Double> bjl = new ArrayList<>();//比均率列表
            List<Double> zws = new ArrayList<>();//中位数列表
            List<Double> ljc = new ArrayList<>();//离均差列表
            List<Double> zs = new ArrayList<>();//众数列表
            for (MsrClassSubject cs : nearlineList) {
                classavgscore.add(cs.getClassavgscore());
                bzf.add(cs.getBzf());
                cjl.add(cs.getCjl());
                bjl.add(cs.getBjl());
                zws.add(cs.getZws());
                ljc.add(cs.getLjc());
                zs.add(cs.getZsmax());
            }
            Map<Double, Integer> pjfpm = MarkingUtil.fspm(classavgscore);//班级平均分排名
            Map<Double, Integer> bzfpm = MarkingUtil.fspm(bzf);//标准分排名
            Map<Double, Integer> cjlpm = MarkingUtil.fspm(cjl);//超均率排名
            Map<Double, Integer> bjlpm = MarkingUtil.fspm(bjl);//比均率排名
            Map<Double, Integer> zwspm = MarkingUtil.fspm(zws);//中位数排名
            Map<Double, Integer> ljcpm = MarkingUtil.fspm(ljc);//离均差排名
            Map<Double, Integer> zspm = MarkingUtil.fspm(zs);//众数排名
            for (MsrClassSubject cs : nearlineList) {
                cs.setClassavgrank(pjfpm.get(cs.getClassavgscore()));
                cs.setBzfrank(bzfpm.get(cs.getBzf()));
                cs.setCjlrank(cjlpm.get(cs.getCjl()));
                cs.setBjlrank(bjlpm.get(cs.getBjl()));
                cs.setZwsrank(zwspm.get(cs.getZws()));
                cs.setLjcrank(ljcpm.get(cs.getLjc()));
                cs.setZsrank(zspm.get(cs.getZsmax()));
            }
        }
        msrClassSubjectMapper.insertList(msrClassSubjects);
    }

    //班级学科计算
    private void setClassSubject(Integer examid, Map<String, List<MsrStudent>> scCollect
            , List<MsrClassSubject> msrClassSubjects, Map<String, MsrClassSubject> csMap, String calformula
            , Map<String, SzJsonVo> tsMap, Map<String, List<Integer>> qkMap,Integer raid) {
        String subjectid;
        MsrClassSubject zf = csMap.get("zf");
        for (Map.Entry<String, List<MsrStudent>> entry : scCollect.entrySet()) {
            String key = entry.getKey();
            Integer classid = N_Utils.obj2Int(key.split("_")[0]);
            subjectid = key.split("_")[1];
            SzJsonVo ts = tsMap.get(subjectid);
            MsrClassSubject gs = csMap.get(subjectid);
            List<MsrStudent> studentList = entry.getValue();
            studentList.sort(Comparator.comparing(MsrStudent::getStuscore));
            MsrStudent minStudent = studentList.get(0);
            int stunum = studentList.size();
            MsrStudent maxStudent = studentList.get(stunum - 1);
            Double fullscore = minStudent.getFullscore();
            MsrClassSubject msrClassSubject = new MsrClassSubject();
            if ("zf".equals(subjectid)) {
                List<Integer> studentids = studentList.stream().map(MsrStudent::getStudentid).collect(Collectors.toList());
                List<MsrClassSubjectGrade> grades = new ArrayList<>();
                for (Map.Entry<String, List<Integer>> entry2 : qkMap.entrySet()) {
                    String key2 = entry2.getKey();
                    List<Integer> ids = entry2.getValue();
                    //ids与studentList的studentid交集
                    List<Integer> ids2 = ids.stream().filter(studentids::contains).collect(Collectors.toList());
                    MsrClassSubjectGrade grade = new MsrClassSubjectGrade();
                    grade.setRangename(key2);
                    int rangenum = ids2.size();
                    grade.setRangenum(rangenum);
                    grade.setRangerate(N_Utils.getIntegerDivideAndMulitiply(rangenum, stunum));
                    grade.setStuids(ids2.stream().map(Object::toString).collect(Collectors.joining(",")));
                    grades.add(grade);
                }
                msrClassSubject.setGrades(grades);
            }
            msrClassSubject.setStunum(stunum);
            msrClassSubject.setExamid(examid);
            msrClassSubject.setRaid(raid);
            msrClassSubject.setSubjectid(subjectid);
            msrClassSubject.setClassid(classid);
            msrClassSubject.setFullscore(fullscore);
            msrClassSubject.setClassmaxscore(maxStudent.getStuscore());
            msrClassSubject.setClassmaxrank(maxStudent.getSchoolrank());
            msrClassSubject.setClassminscore(minStudent.getStuscore());
            msrClassSubject.setClassminrank(minStudent.getSchoolrank());
            List<Double> scores = studentList.stream().map(MsrStudent::getStuscore).collect(Collectors.toList());
            double classavgscore = N_Utils.formatDouble(scores.stream().mapToDouble(Double::doubleValue).summaryStatistics().getAverage(), 2);
            msrClassSubject.setClassavgscore(classavgscore);
            double classavgrate = N_Utils.getDoubleDivideAndMulitiply(classavgscore, fullscore);
            msrClassSubject.setClassavgrate(classavgrate);
            msrClassSubject.setBzc(MarkingUtil.bzc(scores));
            if (classid.equals(0)) {
                msrClassSubject.setSchoolmaxscore(msrClassSubject.getClassmaxscore());
                msrClassSubject.setSchoolminscore(msrClassSubject.getClassminscore());
                msrClassSubject.setSchoolavgscore(msrClassSubject.getClassavgscore());
                msrClassSubject.setSchoolavgrate(msrClassSubject.getClassavgrate());
                msrClassSubject.setBzf(0.0);
                msrClassSubject.setCjl(0.0);
                msrClassSubject.setLjc(0.0);
                msrClassSubject.setBjl(1.0);
                msrClassSubject.setDfgxzs(0.0);
                msrClassSubject.setPjfgxzs(0.0);
            } else {
                Double schoolavgscore = gs.getClassavgscore();
                msrClassSubject.setSchoolmaxscore(gs.getClassmaxscore());
                msrClassSubject.setSchoolminscore(gs.getClassminscore());
                msrClassSubject.setSchoolavgscore(schoolavgscore);
                msrClassSubject.setSchoolavgrate(gs.getClassavgrate());
                msrClassSubject.setBzf(MarkingUtil.bzf(classavgscore, schoolavgscore, gs.getBzc()));
                msrClassSubject.setCjl(MarkingUtil.cjl(classavgscore, schoolavgscore));
                msrClassSubject.setLjc(MarkingUtil.sub(classavgscore, schoolavgscore));
                msrClassSubject.setBjl(1.0);
                msrClassSubject.setDfgxzs(MarkingUtil.sub(classavgrate, zf.getClassavgrate()));
                msrClassSubject.setPjfgxzs(MarkingUtil.sub(classavgscore, zf.getClassavgscore()));
            }
            msrClassSubject.setZws(MarkingUtil.zws(scores));
            List<Double> zs = MarkingUtil.zs(scores);
            msrClassSubject.setZs(JSON.toJSONString(zs));
            msrClassSubject.setZsmax(zs.stream().max(Double::compareTo).orElse(0.0));
            if (N_Utils.isNotEmpty(calformula)) {
                calformula = calformula.replaceAll("平均分", msrClassSubject.getClassavgscore() + "");
                calformula = calformula.replaceAll("标准差", msrClassSubject.getBzc() + "");
                calformula = calformula.replaceAll("最高分", msrClassSubject.getClassmaxscore() + "");
                calformula = calformula.replaceAll("最低分", msrClassSubject.getClassminscore() + "");
                calformula = calformula.replaceAll("超均率", msrClassSubject.getCjl() + "");
                calformula = calformula.replaceAll("标准分", msrClassSubject.getBzf() + "");
                calformula = calformula.replaceAll("中位数", msrClassSubject.getZws() + "");
                calformula = calformula.replaceAll("离均差", msrClassSubject.getLjc() + "");
                calformula = calformula.replaceAll("比均率", msrClassSubject.getBjl() + "");
                calformula = calformula.replaceAll("众数", msrClassSubject.getZsmax() + "");
                msrClassSubject.setZhl(MarkingUtil.evaluate(calformula));
            }

            if (N_Utils.isTrueInteger(ts.getAlltop())) {
                Double goodAvgScore = N_Utils.formatDouble(studentList.stream().filter(s -> s.getSchoolrank().compareTo(ts.getGoodvalue()) <= 0)
                                                                      .mapToDouble(MsrStudent::getStuscore).summaryStatistics().getAverage(), 2);
                Double badAvgScore = N_Utils.formatDouble(studentList.stream().filter(s -> s.getSchoolrank().compareTo(ts.getBadvalue()) >= 0)
                                                                     .mapToDouble(MsrStudent::getStuscore).summaryStatistics().getAverage(), 2);
                msrClassSubject.setJhl(MarkingUtil.div(badAvgScore, goodAvgScore));
            }

            if (classid.equals(0)) {
                csMap.put(subjectid, msrClassSubject);
            }
            msrClassSubjects.add(msrClassSubject);
        }
    }

    //学科报告-班级学科名次分组分析
    public void saveClassRankGroup(Integer examid, List<MsrStudent> msrStudents,Integer raid) {
        List<MsrClassRankgroup> classRankGroups = new ArrayList<>();
        Map<String, List<MsrStudent>> collect = MarkingUtil.getSubjectCollect(msrStudents);
        Map<String, List<RankGroupVo>> groupsMap = new HashMap<>();
        Map<String, Integer> rsMap = new HashMap<>();//学科人数map
        for (Map.Entry<String, List<MsrStudent>> entry : collect.entrySet()) {
            MarkingUtil.studentsDistinct(entry, rsMap);
            List<MsrStudent> studentList = entry.getValue();
            int maxRank = studentList.stream().mapToInt(MsrStudent::getSchoolrank).summaryStatistics().getMax();
            List<RankGroupVo> groups = MarkingUtil.rankGroup(maxRank, 10);
            groupsMap.put(studentList.get(0).getSubjectid(), groups);
        }
        setClassRankGroup(examid, collect, classRankGroups, groupsMap,raid);
        Map<String, List<MsrStudent>> scCollect = msrStudents.stream().collect(Collectors.groupingBy(s -> s.getClassid() + "_" + s.getSubjectid()));
        setClassRankGroup(examid, scCollect, classRankGroups, groupsMap,raid);
        msrClassRankgroupMapper.insertList(classRankGroups);
    }

    //学科报告-班级学科名次分组计算
    private void setClassRankGroup(Integer examid, Map<String, List<MsrStudent>> scCollect
            , List<MsrClassRankgroup> classRankGroups, Map<String, List<RankGroupVo>> groupsMap,Integer raid) {
        String subjectid;
        for (Map.Entry<String, List<MsrStudent>> entry : scCollect.entrySet()) {
            String key = entry.getKey();
            Integer classid = N_Utils.obj2Int(key.split("_")[0]);
            subjectid = key.split("_")[1];
            List<MsrStudent> studentList = entry.getValue();
            List<RankGroupVo> groups = groupsMap.get(subjectid);
            for (RankGroupVo group : groups) {
                int maxvalue = group.getMaxvalue();
                int minvalue = group.getMinvalue();
                List<MsrStudent> qjstudents = studentList.stream().filter(s -> s.getSchoolrank().compareTo(minvalue) >= 0 && s.getSchoolrank().compareTo(maxvalue) <= 0).collect(Collectors.toList());
                MsrClassRankgroup cg = new MsrClassRankgroup();
                cg.setRaid(raid);
                cg.setExamid(examid);
                cg.setClassid(classid);
                cg.setSubjectid(subjectid);
                cg.setRname(group.getGroupname());
                cg.setRnum(qjstudents.size());
                String stuids = qjstudents.stream().map(s -> s.getStudentid().toString()).collect(Collectors.joining(","));
                cg.setStuids(stuids);
                classRankGroups.add(cg);
            }
        }
    }

    //综合报表-名次和比例分析
    public void saveClassRankRate(Integer examid, List<MsrStudent> msrStudents,Integer raid) {
        List<MsrReportparam> params = msrReportparamService.getMsrReportParams(examid, "rankrate", "zh");
        Map<String, List<SzJsonVo>> qjMap = new HashMap<>();
        Map<String, Integer> tMap = new HashMap<>();
        for (MsrReportparam param : params) {
            String subjectid = param.getSubjectid();
            qjMap.put(subjectid, JSON.parseArray(param.getSzjson(), SzJsonVo.class));
            tMap.put(subjectid, param.getRptype());
        }
        List<MsrClassRankrate> classRankrates = new ArrayList<>();
        Map<String, List<MsrStudent>> collect = MarkingUtil.getSubjectCollect(msrStudents);
        Map<String, List<RankRateGroupVo>> sgMap = new HashMap<>();//学科名次分组map
        Map<String, Integer> rsMap = new HashMap<>();//学科人数map
        for (Map.Entry<String, List<MsrStudent>> entry : collect.entrySet()) {
            MarkingUtil.studentsDistinct(entry, rsMap);
            List<RankRateGroupVo> subjectGroupList = new ArrayList<>();//学科名次分组列表
            String subjectid = entry.getKey().split("_")[1];
            List<SzJsonVo> list = qjMap.get(subjectid);
            Integer rptype = tMap.get(subjectid);
            List<MsrStudent> studentList = entry.getValue();
            if (rptype.equals(3)) {
                studentList = studentList.stream().sorted(Comparator.comparing(MsrStudent::getStuscore).reversed()).collect(Collectors.toList());
            }
            int totalnum = studentList.size();//总人数
            Double max = null;
            Integer minRank = null;
            int minIndex = 0;
            Object minRate = null;
            for (SzJsonVo rg : list) {
                Object djvalue = rg.getDjvalue();
                RankRateGroupVo group = new RankRateGroupVo();
                List<MsrStudent> qjstudents;
                String ztname;
                String ctname;
                if (rptype.equals(1)) {//按名次
                    ztname = "前" + djvalue + "名";
                    Integer rank = N_Utils.obj2Int(djvalue);
                    if (minRank == null) {
                        qjstudents = studentList.stream().filter(s -> s.getSchoolrank().compareTo(rank) <= 0).collect(Collectors.toList());
                    } else {
                        Integer finalMinRank = minRank;
                        qjstudents = studentList.stream().filter(s -> s.getSchoolrank().compareTo(finalMinRank) > 0 && s.getSchoolrank().compareTo(rank) <= 0).collect(Collectors.toList());
                        group.setMinrank(minRank);
                    }
                    group.setMaxrank(rank);
                    minRank = rank;
                    double minScore = N_Utils.handleInfinity(qjstudents.stream().mapToDouble(MsrStudent::getStuscore).summaryStatistics().getMin());
                    ctname = ">=" + minScore + "分";
                } else if (rptype.equals(2)) {//按分数
                    ztname = ">=" + djvalue + "分";
                    Double score = MarkingUtil.objToDouble(djvalue);
                    double minScore = score;
                    if (max == null) {
                        qjstudents = studentList.stream().filter(s -> s.getStuscore().compareTo(score) >= 0).collect(Collectors.toList());
                    } else {
                        Double finalMax = max;
                        qjstudents = studentList.stream().filter(s -> s.getStuscore().compareTo(score) >= 0 && s.getStuscore().compareTo(finalMax) < 0).collect(Collectors.toList());
                        group.setMaxscore(max);
                    }
                    group.setMinscore(minScore);
                    max = score;
                    minRank = qjstudents.stream().mapToInt(MsrStudent::getSchoolrank).summaryStatistics().getMin();
                    ctname = "前" + minRank + "名";
                } else {//按比例
                    if (minIndex == 0) {
                        ztname = "前" + djvalue + "%";
                    } else {
                        ztname = "前" + minRate + "%-" + djvalue + "%";
                    }
                    int index = (int) Math.ceil(MarkingUtil.div(totalnum * 100, djvalue));
                    if (index > totalnum) index = totalnum;
                    qjstudents = studentList.subList(minIndex, index);
                    minIndex = index;
                    minRate = djvalue;
                    DoubleSummaryStatistics statistics = qjstudents.stream().mapToDouble(MsrStudent::getStuscore).summaryStatistics();
                    double minScore = N_Utils.handleInfinity(statistics.getMin());
                    double maxScore = N_Utils.handleInfinity(statistics.getMax());
                    ctname = "[" + minScore + "-" + maxScore + "]";
                    group.setMaxscore(maxScore);
                    group.setMinscore(minScore);
                }
                group.setRtype(rptype);
                group.setZtname(ztname);
                group.setCtname(ctname);
                subjectGroupList.add(group);
            }
            sgMap.put(subjectid, subjectGroupList);
        }
        setClassRankRate(examid, collect, classRankrates, sgMap, rsMap,raid);
        Map<String, List<MsrStudent>> scCollect = msrStudents.stream().collect(Collectors.groupingBy(s -> s.getClassid() + "_" + s.getSubjectid()));
        setClassRankRate(examid, scCollect, classRankrates, sgMap, rsMap,raid);
        msrClassRankrateMapper.insertList(classRankrates);
    }

    //综合报表-名次和比例计算
    private void setClassRankRate(Integer examid, Map<String, List<MsrStudent>> scCollect
            , List<MsrClassRankrate> classRankrates, Map<String, List<RankRateGroupVo>> sgMap
            , Map<String, Integer> rsMap,Integer raid) {
        int totalnum;
        String subjectid;
        for (Map.Entry<String, List<MsrStudent>> entry : scCollect.entrySet()) {
            String key = entry.getKey();
            Integer classid = N_Utils.obj2Int(key.split("_")[0]);
            subjectid = key.split("_")[1];
            totalnum = rsMap.get(subjectid);
            List<RankRateGroupVo> list = sgMap.get(subjectid);
            Integer rptype = list.get(0).getRtype();
            List<MsrStudent> studentList = entry.getValue();
            if (rptype.equals(3)) {
                studentList = studentList.stream().sorted(Comparator.comparing(MsrStudent::getStuscore).reversed()).collect(Collectors.toList());
            }
            int stunum = studentList.size();//参考人数
            for (int i = 0; i < list.size(); i++) {
                RankRateGroupVo rg = list.get(i);
                List<MsrStudent> qjstudents;
                if (rptype.equals(1)) {//按名次
                    if (i == 0) {
                        qjstudents = studentList.stream().filter(s -> s.getSchoolrank().compareTo(rg.getMaxrank()) >= 0).collect(Collectors.toList());
                    } else {
                        qjstudents = studentList.stream().filter(s -> s.getSchoolrank().compareTo(rg.getMaxrank()) >= 0 && s.getSchoolrank().compareTo(rg.getMinrank()) < 0).collect(Collectors.toList());
                    }
                } else {//按分数
                    if (i == 0) {
                        qjstudents = studentList.stream().filter(s -> s.getStuscore().compareTo(rg.getMinscore()) >= 0).collect(Collectors.toList());
                    } else {
                        qjstudents = studentList.stream().filter(s -> s.getStuscore().compareTo(rg.getMinscore()) >= 0 && s.getStuscore().compareTo(rg.getMaxscore()) < 0).collect(Collectors.toList());
                    }
                }
                int qjnum = qjstudents.size();
                MsrClassRankrate rankrate = new MsrClassRankrate();
                rankrate.setRaid(raid);
                rankrate.setExamid(examid);
                rankrate.setSubjectid(subjectid);
                rankrate.setClassid(classid);
                rankrate.setStunum(stunum);
                rankrate.setRtype(rptype);
                rankrate.setZtname(rg.getZtname());
                rankrate.setCtname(rg.getCtname());
                rankrate.setRnum(qjnum);
                rankrate.setRrate(N_Utils.getIntegerDivideAndMulitiply(qjnum, totalnum));
                String stuids = qjstudents.stream().map(s -> s.getStudentid().toString()).collect(Collectors.joining(","));
                rankrate.setStuids(stuids);
                classRankrates.add(rankrate);
            }
        }
    }

    //分段统计
    public void saveClassSection(Integer examid, Integer type, String reportcode, List<MsrStudent> msrStudents,Integer raid) {
        List<MsrReportparam> params = msrReportparamService.getMsrReportParams(examid, "scoresection", reportcode);
        Integer rptype = params.get(0).getRptype();
        Map<String, List<RankGroupVo>> fdMap = new HashMap<>();
        if (rptype.equals(0)) {//固定步长
            for (MsrReportparam param : params) {
                SzJsonVo vo = JSON.parseObject(param.getSzjson(), SzJsonVo.class);
                List<RankGroupVo> groups = MarkingUtil.fdScore(N_Utils.obj2Int(vo.getMaxvalue()), N_Utils.obj2Int(vo.getMinvalue()), N_Utils.obj2Int(vo.getDjvalue()), type);
                fdMap.put(param.getSubjectid(), groups);
            }
        } else {//不定步长
            for (MsrReportparam param : params) {
                List<SzJsonVo> vos = JSON.parseArray(param.getSzjson(), SzJsonVo.class);
                List<RankGroupVo> groups = MarkingUtil.fdScore(vos, type);
                fdMap.put(param.getSubjectid(), groups);
            }
        }

        List<MsrClassSection> classSections = new ArrayList<>();
        Map<String, List<MsrStudent>> collect = MarkingUtil.getSubjectCollect(msrStudents);
        for (Map.Entry<String, List<MsrStudent>> entry : collect.entrySet()) {
            MarkingUtil.studentsDistinct(entry, null);
        }
        setClassSection(examid, type, reportcode, collect, fdMap, classSections, raid);
        Map<String, List<MsrStudent>> scCollect = msrStudents.stream().collect(Collectors.groupingBy(s -> s.getClassid() + "_" + s.getSubjectid()));
        setClassSection(examid, type, reportcode, scCollect, fdMap, classSections, raid);
        msrClassSectionMapper.insertList(classSections);
    }

    //分段统计-计算
    private void setClassSection(Integer examid, Integer type, String reportcode, Map<String, List<MsrStudent>> scCollect
            , Map<String, List<RankGroupVo>> fdMap, List<MsrClassSection> classSections, Integer raid) {
        String subjectid;
        for (Map.Entry<String, List<MsrStudent>> entry : scCollect.entrySet()) {
            String key = entry.getKey();
            Integer classid = N_Utils.obj2Int(key.split("_")[0]);
            subjectid = key.split("_")[1];
            List<MsrStudent> studentList = entry.getValue();
            Integer stunum = studentList.size();
            List<RankGroupVo> groups = fdMap.get(subjectid);
            for (int i = 0; i < groups.size(); i++) {
                RankGroupVo group = groups.get(i);
                int maxvalue = group.getMaxvalue();
                int minvalue = group.getMinvalue();
                List<MsrStudent> qjstudents;
                if (type.equals(1)) {
                    if (i == 0) {
                        qjstudents = studentList.stream().filter(s -> MarkingUtil.sub(s.getStuscore(), minvalue) >= 0 && MarkingUtil.sub(s.getStuscore(), maxvalue) <= 0).collect(Collectors.toList());
                    } else {
                        qjstudents = studentList.stream().filter(s -> MarkingUtil.sub(s.getStuscore(), minvalue) >= 0 && MarkingUtil.sub(s.getStuscore(), maxvalue) < 0).collect(Collectors.toList());
                    }
                } else {
                    qjstudents = studentList.stream().filter(s -> MarkingUtil.sub(s.getStuscore(), maxvalue) >= 0).collect(Collectors.toList());
                }
                MsrClassSection classSection = new MsrClassSection();
                classSection.setRaid(raid);
                classSection.setExamid(examid);
                classSection.setClassid(classid);
                classSection.setSubjectid(subjectid);
                classSection.setStunum(stunum);
                classSection.setType(type);
                classSection.setReportcode(reportcode);
                classSection.setFzfw(group.getGroupname());
                int qjnum = qjstudents.size();
                classSection.setFzfwnum(qjnum);
                classSection.setFzfwrate(N_Utils.getIntegerDivideAndMulitiply(qjnum, stunum));
                String stuids = qjstudents.stream().map(s -> s.getStudentid().toString()).collect(Collectors.joining(","));
                classSection.setStuids(stuids);
                classSections.add(classSection);
            }
        }
    }

    //分档上线分析
    public void saveClassNearLine(Integer examid, List<MsrStudent> msrStudents, Integer raid) {
        List<MsrReportparam> params = msrReportparamService.getMsrReportParams(examid, "gradescore", "all");
        Map<String, List<SzJsonVo>> qjMap = new HashMap<>();
        Map<String, Integer> tMap = new HashMap<>();
        for (MsrReportparam param : params) {
            String subjectid = param.getSubjectid();
            qjMap.put(subjectid, JSON.parseArray(param.getSzjson(), SzJsonVo.class));
            tMap.put(subjectid, param.getRptype());
        }
        params = msrReportparamService.getMsrReportParams(examid, "nearline", "all");
        List<SzJsonVo> vos = JSON.parseArray(params.get(0).getSzjson(), SzJsonVo.class);
        Map<Integer, List<Integer>> zfSx = null;//学生总分是否上线
        List<MsrClassNearline> classNearlines = new ArrayList<>();
        Map<String, List<MsrStudent>> collect0 = MarkingUtil.getSubjectCollect(msrStudents);
        Map<String, Integer> rsMap = new HashMap<>();//学科人数map
        for (Map.Entry<String, List<MsrStudent>> entry : collect0.entrySet()) {
            MarkingUtil.studentsDistinct(entry, rsMap);
            if (entry.getKey().endsWith("zf")) {
                zfSx = setZfsxMap(entry.getValue(), qjMap, tMap);
            }
            setClassNearLine(examid, entry, qjMap, tMap, vos, zfSx, classNearlines, rsMap, raid);
        }
        Map<String, List<MsrStudent>> scCollect = msrStudents.stream().collect(Collectors.groupingBy(s -> s.getClassid() + "_" + s.getSubjectid()));
        for (Map.Entry<String, List<MsrStudent>> entry : scCollect.entrySet()) {
            setClassNearLine(examid, entry, qjMap, tMap, vos, zfSx, classNearlines, rsMap, raid);
        }
        Map<String, List<MsrClassNearline>> collect = classNearlines.stream().collect(Collectors.groupingBy(l -> l.getSubjectid() + "_" + l.getDworder()));
        for (Map.Entry<String, List<MsrClassNearline>> entry : collect.entrySet()) {
            List<MsrClassNearline> nearlineList = entry.getValue();
            List<Integer> nums = new ArrayList<>();
            for (MsrClassNearline nearline : nearlineList) {
                nums.add(nearline.getSxnum());
            }
            Map<Integer, Integer> rspm = MarkingUtil.rspm(nums);//人数排名
            for (MsrClassNearline nearline : nearlineList) {
                nearline.setSxrank(rspm.get(nearline.getSxnum()));
            }
        }
        msrClassNearlineMapper.insertList(classNearlines);
    }

    //分档上线计算
    private void setClassNearLine(Integer examid, Map.Entry<String, List<MsrStudent>> entry, Map<String, List<SzJsonVo>> qjMap
            , Map<String, Integer> tMap, List<SzJsonVo> vos, Map<Integer, List<Integer>> zfSx
            , List<MsrClassNearline> classNearlines, Map<String, Integer> rsMap, Integer raid) {
        String key = entry.getKey();
        Integer classid = N_Utils.obj2Int(key.split("_")[0]);
        String subjectid = key.split("_")[1];
        int totalnum = rsMap.get(subjectid);
        List<SzJsonVo> list = qjMap.get(subjectid);
        Integer rptype = tMap.get(subjectid);
        List<MsrStudent> studentList = entry.getValue();
        if (rptype.equals(3)) {
            studentList = studentList.stream().sorted(Comparator.comparing(MsrStudent::getStuscore).reversed()).collect(Collectors.toList());
        }
        Double max = null;
        Integer minRank = null;
        int minIndex = 0;
        for (int i = 0; i < list.size(); i++) {
            SzJsonVo fd = vos.get(i);
            Double fdMaxScore = fd.getMaxvalue();//档位浮动分数
            if (fdMaxScore == null) fdMaxScore = MarkingUtil.objToDouble(fd.getDjvalue());
            Double fdMinScore = fd.getMinvalue();//档位浮动分数
            if (fdMinScore == null) {
                fdMinScore = fdMaxScore;
            }
            SzJsonVo rg = list.get(i);
            Object djvalue = rg.getDjvalue();
            double dwscore;
            List<MsrStudent> qjstudents;//上线学生列表
            List<MsrStudent> ljstudents;//累计上线学生列表
            if (rptype.equals(1)) {//按名次
                Integer rank = N_Utils.obj2Int(djvalue);
                ljstudents = studentList.stream().filter(s -> s.getSchoolrank().compareTo(rank) <= 0).collect(Collectors.toList());
                if (minRank == null) {
                    qjstudents = studentList.stream().filter(s -> s.getSchoolrank().compareTo(rank) <= 0).collect(Collectors.toList());
                } else {
                    Integer finalMinRank = minRank;
                    qjstudents = studentList.stream().filter(s -> s.getSchoolrank().compareTo(finalMinRank) >= 0 && s.getSchoolrank().compareTo(rank) < 0).collect(Collectors.toList());
                }
                minRank = rank;
                dwscore = N_Utils.handleInfinity(qjstudents.stream().mapToDouble(MsrStudent::getStuscore).summaryStatistics().getMin());
            } else if (rptype.equals(2)) {//按分数
                Double score = MarkingUtil.objToDouble(djvalue);
                ljstudents = studentList.stream().filter(s -> s.getStuscore().compareTo(score) >= 0).collect(Collectors.toList());
                if (max == null) {
                    qjstudents = studentList.stream().filter(s -> s.getStuscore().compareTo(score) >= 0).collect(Collectors.toList());
                } else {
                    Double finalMax = max;
                    qjstudents = studentList.stream().filter(s -> s.getStuscore().compareTo(score) >= 0 && s.getStuscore().compareTo(finalMax) < 0).collect(Collectors.toList());
                }
                dwscore = MarkingUtil.objToDouble(djvalue);
                max = score;
                minRank = qjstudents.stream().mapToInt(MsrStudent::getSchoolrank).summaryStatistics().getMin();
            } else {//按比例
                int index = (int) Math.ceil(MarkingUtil.div(totalnum * 100, djvalue));
                if (index > totalnum) index = totalnum;
                qjstudents = studentList.subList(minIndex, index);
                minIndex = index;
                DoubleSummaryStatistics statistics = qjstudents.stream().mapToDouble(MsrStudent::getStuscore).summaryStatistics();
                dwscore = N_Utils.handleInfinity(statistics.getMin());
                ljstudents = studentList.stream().filter(s -> s.getStuscore().compareTo(dwscore) >= 0).collect(Collectors.toList());
            }
            int qjnum = qjstudents.size();
            MsrClassNearline nearline = new MsrClassNearline();
            nearline.setRaid(raid);
            nearline.setExamid(examid);
            nearline.setSubjectid(subjectid);
            nearline.setClassid(classid);
            Integer dworder = i + 1;
            String dwname = N_Utils.NumberToChn(dworder) + "档";
            nearline.setDwname(dwname);
            nearline.setDworder(dworder);
            nearline.setDwscore(dwscore);
            nearline.setSxnum(qjnum);
            nearline.setSxrate(N_Utils.getIntegerDivideAndMulitiply(qjnum, totalnum));
            int ljsxnum = ljstudents.size();
            nearline.setLjsxnum(ljsxnum);
            nearline.setLjsxrate(N_Utils.getIntegerDivideAndMulitiply(ljsxnum, totalnum));
            if (!"zf".equals(subjectid)) {
                List<Integer> zfsxIds = zfSx.get(dworder);//总分上线学生id列表
                int zfsxnum = zfsxIds.size();
                List<MsrStudent> ssxIds = qjstudents.stream().filter(s -> zfsxIds.contains(s.getStudentid())).collect(Collectors.toList());
                Integer ssxnum = ssxIds.size();//双上线人数
                nearline.setSsxnum(ssxnum);
                nearline.setStuids2(ssxIds.stream().map(s -> s.getStudentid().toString()).collect(Collectors.joining(",")));
                //总分上线学科未上线人数
                List<Integer> dksxIds = qjstudents.stream().map(MsrStudent::getStudentid).collect(Collectors.toList());
                List<Integer> zfsxxkwsxIds = new ArrayList<>(zfsxIds);
                zfsxxkwsxIds.removeAll(dksxIds);
                int zfsxxkwsxnum = zfsxxkwsxIds.size();
                nearline.setZfsxxkwsxnum(zfsxxkwsxnum);
                nearline.setStuids5(zfsxxkwsxIds.stream().map(Object::toString).collect(Collectors.joining(",")));
                nearline.setGxrate(N_Utils.getIntegerDivideAndMulitiply(qjnum, zfsxnum));
                nearline.setMzxrate(N_Utils.getIntegerDivideAndMulitiply(ssxnum, qjnum));
            }
            nearline.setSxrate(N_Utils.getIntegerDivideAndMulitiply(qjnum, totalnum));
            double ljMax = MarkingUtil.add(dwscore, fdMaxScore);
            double ljMin = MarkingUtil.sub(dwscore, fdMinScore);
            List<MsrStudent> ljStudents = studentList.stream().filter(s -> s.getStuscore().compareTo(ljMax) <= 0 && s.getStuscore().compareTo(ljMin) >= 0).collect(Collectors.toList());
            nearline.setLjsnum(ljStudents.size());
            nearline.setLjsavgscore(N_Utils.formatDouble(ljStudents.stream().mapToDouble(MsrStudent::getStuscore).summaryStatistics().getAverage(), 2));
            nearline.setStuids3(ljStudents.stream().map(s -> s.getStudentid().toString()).collect(Collectors.joining(",")));
            nearline.setStuids4(ljstudents.stream().map(s -> s.getStudentid().toString()).collect(Collectors.joining(",")));
            String stuids = qjstudents.stream().map(s -> s.getStudentid().toString()).collect(Collectors.joining(","));
            nearline.setStuids(stuids);
            classNearlines.add(nearline);
        }
    }

    //总分上线分析
    private Map<Integer, List<Integer>> setZfsxMap(List<MsrStudent> studentList, Map<String, List<SzJsonVo>> qjMap
            , Map<String, Integer> tMap) {
        Map<Integer, List<Integer>> zfSx = new HashMap<>();
        String subjectid = "zf";
        int totalnum;
        List<SzJsonVo> list = qjMap.get(subjectid);
        Integer rptype = tMap.get(subjectid);
        if (rptype.equals(3)) {
            studentList = studentList.stream().sorted(Comparator.comparing(MsrStudent::getStuscore).reversed()).collect(Collectors.toList());
        }
        totalnum = studentList.size();//总人数
        Double max = null;
        Integer minRank = null;
        int minIndex = 0;
        for (int i = 0; i < list.size(); i++) {
            SzJsonVo rg = list.get(i);
            Object djvalue = rg.getDjvalue();
            List<MsrStudent> qjstudents;//上线学生列表
            if (rptype.equals(1)) {//按名次
                Integer rank = N_Utils.obj2Int(djvalue);
                if (minRank == null) {
                    qjstudents = studentList.stream().filter(s -> s.getSchoolrank().compareTo(rank) <= 0).collect(Collectors.toList());
                } else {
                    Integer finalMinRank = minRank;
                    qjstudents = studentList.stream().filter(s -> s.getSchoolrank().compareTo(finalMinRank) >= 0 && s.getSchoolrank().compareTo(rank) < 0).collect(Collectors.toList());
                }
                minRank = rank;
            } else if (rptype.equals(2)) {//按分数
                Double score = MarkingUtil.objToDouble(djvalue);
                if (max == null) {
                    qjstudents = studentList.stream().filter(s -> s.getStuscore().compareTo(score) >= 0).collect(Collectors.toList());
                } else {
                    Double finalMax = max;
                    qjstudents = studentList.stream().filter(s -> s.getStuscore().compareTo(score) >= 0 && s.getStuscore().compareTo(finalMax) < 0).collect(Collectors.toList());
                }
                max = score;
                minRank = qjstudents.stream().mapToInt(MsrStudent::getSchoolrank).summaryStatistics().getMin();
            } else {//按比例
                int index = (int) Math.ceil(MarkingUtil.div(totalnum * 100, djvalue));
                if (index > totalnum) index = totalnum;
                qjstudents = studentList.subList(minIndex, index);
                minIndex = index;
            }

            Integer dworder = i + 1;
            List<Integer> ids = qjstudents.stream().map(MsrStudent::getStudentid).collect(Collectors.toList());
            zfSx.put(dworder, ids);
        }
        return zfSx;
    }

    //重点学生-优劣名次统计
    public void saveClassGoodBad(Integer examid, String all, List<MsrStudent> msrStudents, Integer raid) {
        List<MsrReportparam> params = msrReportparamService.getMsrReportParams(examid, "keystu", all);
        SzJsonVo fd = JSON.parseObject(params.get(0).getSzjson(), SzJsonVo.class);
        List<MsrClassGoodbad> classGoodbads = new ArrayList<>();
        Map<String, List<MsrStudent>> collect = MarkingUtil.getSubjectCollect(msrStudents);
        Map<String, Integer> rsMap = new HashMap<>();//学科人数map
        for (Map.Entry<String, List<MsrStudent>> entry : collect.entrySet()) {
            MarkingUtil.studentsDistinct(entry, rsMap);
            setClassGoodBag(examid, entry, fd, classGoodbads, rsMap, raid);
        }
        Map<String, List<MsrStudent>> scCollect = msrStudents.stream().collect(Collectors.groupingBy(s -> s.getClassid() + "_" + s.getSubjectid()));
        for (Map.Entry<String, List<MsrStudent>> entry : scCollect.entrySet()) {
            setClassGoodBag(examid, entry, fd, classGoodbads, rsMap, raid);
        }
        msrClassGoodbadMapper.insertList(classGoodbads);
    }

    //重点学生-优劣名次计算
    private void setClassGoodBag(Integer examid, Map.Entry<String, List<MsrStudent>> entry, SzJsonVo fd
            , List<MsrClassGoodbad> classGoodbads, Map<String, Integer> rsMap, Integer raid) {
        String key = entry.getKey();
        Integer classid = N_Utils.obj2Int(key.split("_")[0]);
        String subjectid = key.split("_")[1];
        int totalnum;
        Integer goodtype = fd.getGoodtype();
        Integer badtype = fd.getBadtype();
        List<MsrStudent> studentList = entry.getValue().stream().sorted(Comparator.comparing(MsrStudent::getSchoolrank)).collect(Collectors.toList());
        Double avgScore = N_Utils.formatDouble(studentList.stream().mapToDouble(MsrStudent::getStuscore).summaryStatistics().getAverage(), 2);
        totalnum = rsMap.get(subjectid);//科目总人数
        Integer goodvalue = fd.getGoodvalue();
        Integer badvalue = fd.getBadvalue();
        List<MsrStudent> yxStudents;//优秀学生列表
        List<MsrStudent> dtgStudents;//待提高学生列表
        List<MsrStudent> dbStudents;//学科短板学生列表
        if (goodtype.equals(1)) {//按名次
            yxStudents = studentList.stream().filter(s -> s.getSchoolrank().compareTo(goodvalue) <= 0).collect(Collectors.toList());
        } else {//按比例
            int index = (int) Math.ceil(MarkingUtil.div(totalnum * 100, goodvalue));
            if (index > totalnum) index = totalnum;
            yxStudents = studentList.subList(0, index);
        }
        if (badtype.equals(1)) {//按名次
            dtgStudents = studentList.stream().filter(s -> s.getSchoolrank().compareTo(badvalue) <= 0).collect(Collectors.toList());
        } else {//按比例
            int index = (int) Math.ceil(MarkingUtil.div(totalnum * 100, badvalue));
            if (index > totalnum) index = totalnum;
            //取后index个
            dtgStudents = studentList.subList(totalnum - index, totalnum);
        }
        dbStudents = studentList.stream().filter(s -> s.getStuscore().compareTo(avgScore) <= 0).collect(Collectors.toList());
        int yxnum = yxStudents.size();
        MsrClassGoodbad goodbad = new MsrClassGoodbad();
        goodbad.setRaid(raid);
        goodbad.setExamid(examid);
        goodbad.setSubjectid(subjectid);
        goodbad.setClassid(classid);
        goodbad.setYxnum(yxnum);
        goodbad.setYxrate(N_Utils.getIntegerDivideAndMulitiply(yxnum, totalnum));
        goodbad.setYxavgscore(N_Utils.formatDouble(yxStudents.stream().mapToDouble(MsrStudent::getStuscore).summaryStatistics().getAverage(), 2));
        int dtgnum = dtgStudents.size();
        goodbad.setDtgnum(dtgnum);
        goodbad.setDtgrate(N_Utils.getIntegerDivideAndMulitiply(dtgnum, totalnum));
        goodbad.setDtgavgscore(N_Utils.formatDouble(dtgStudents.stream().mapToDouble(MsrStudent::getStuscore).summaryStatistics().getAverage(), 2));
        goodbad.setDbnum(dbStudents.size());
        goodbad.setStuids(yxStudents.stream().map(s -> s.getStudentid().toString()).collect(Collectors.joining(",")));
        goodbad.setStuids2(dtgStudents.stream().map(s -> s.getStudentid().toString()).collect(Collectors.joining(",")));
        goodbad.setStuids3(dbStudents.stream().map(s -> s.getStudentid().toString()).collect(Collectors.joining(",")));
        classGoodbads.add(goodbad);
    }

}
