package com.xhkjedu.sexam.service.report;

import com.alibaba.fastjson.JSON;
import com.xhkjedu.sexam.mapper.exam.EClassMapper;
import com.xhkjedu.sexam.mapper.paper.EPaperAnalyzeMapper;
import com.xhkjedu.sexam.mapper.paper.EPaperQtypeMapper;
import com.xhkjedu.sexam.mapper.paperstudent.EPaperStudentMapper;
import com.xhkjedu.sexam.mapper.paperstudent.EPaperStudentQuestionMapper;
import com.xhkjedu.sexam.mapper.report.ERbaseMapper;
import com.xhkjedu.sexam.mapper.report.EReportGenerateMapper;
import com.xhkjedu.sexam.mapper.report.ERrankMapper;
import com.xhkjedu.sexam.mapper.report.ERsubjectMapper;
import com.xhkjedu.sexam.mapper.reportclass.*;
import com.xhkjedu.sexam.mapper.reportstu.*;
import com.xhkjedu.sexam.mapper.system.UserMapper;
import com.xhkjedu.sexam.model.paperstudent.EPaperStudentQuestion;
import com.xhkjedu.sexam.model.report.ERbase;
import com.xhkjedu.sexam.model.report.ERrank;
import com.xhkjedu.sexam.model.report.ERsubject;
import com.xhkjedu.sexam.model.reportclass.*;
import com.xhkjedu.sexam.model.reportstu.*;
import com.xhkjedu.sexam.utils.ExamUtil;
import com.xhkjedu.sexam.vo.paper.QuestionPointVo;
import com.xhkjedu.sexam.vo.report.ERClassScoreVo;
import com.xhkjedu.sexam.vo.report.ERPaperVo;
import com.xhkjedu.sexam.vo.report.ERPointStuScoreVo;
import com.xhkjedu.sexam.vo.report.ExamPaperClassVo;
import com.xhkjedu.sexam.vo.system.UserVo;
import com.xhkjedu.utils.N_Utils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

/**
 * @author ywx
 * @classname EReportGenerateService
 * @description 考试报告生成
 * 人数： 指定范围下考生人数
 * 占比： 指定范围下考生人数/全部学生*100%
 * @date 2022/8/8 10:04
 **/
@Service
public class EReportGenerateService {
    @Resource
    private EReportGenerateMapper eReportGenerateMapper;
    @Resource
    private EClassMapper eClassMapper;
    @Resource
    private EPaperStudentMapper ePaperStudentMapper;
    @Resource
    private EPaperQtypeMapper ePaperQtypeMapper;
    @Resource
    private EPaperStudentQuestionMapper ePaperStudentQuestionMapper;
    @Resource
    private EPaperAnalyzeMapper ePaperAnalyzeMapper;

    @Resource
    private ERbaseMapper eRbaseMapper;
    @Resource
    private ERstudentMapper eRstudentMapper;
    @Resource
    private ERsubjectMapper eRsubjectMapper;
    @Resource
    private ERclassMapper eRclassMapper;
    @Resource
    private ERclassQtypeMapper eRclassQtypeMapper;
    @Resource
    private ERclassQuestionMapper eRclassQuestionMapper;
    @Resource
    private ERclassPointMapper eRclassPointMapper;
    @Resource
    private ERstudentPointMapper eRstudentPointMapper;
    @Resource
    private ERstudentQtypeMapper eRstudentQtypeMapper;
    @Resource
    private ERclassComplexityMapper eRclassComplexityMapper;
    @Resource
    private ERStudentComplexityMapper erStudentComplexityMapper;
    @Resource
    private UserMapper userMapper;
    @Resource
    private ERrankMapper eRrankMapper;
    @Resource
    private ERclassRankMapper eRclassRankMapper;
    @Resource
    private ERclassActionMapper eRclassActionMapper;
    @Resource
    private ERstudentActionMapper eRstudentActionMapper;

    //生成考试报告
    @Transactional(rollbackFor = Exception.class)
    public void generateExamReport(Integer examid, Integer createid) throws Exception {
        //生成前先删除以前的考试报告
        eReportGenerateMapper.deleteExamReport(examid);
        //学生上次考试排名及目标
        List<ERstudent> stuRankGoals = eReportGenerateMapper.listStuRankAndGoal(examid);

        List<Map> classes = eClassMapper.listByExamId(examid);
        Integer exammode = eReportGenerateMapper.getExamModeById(examid);
        List<Map> subjects = eReportGenerateMapper.listSubject(examid, exammode);
        List<ERPaperVo> papers = new ArrayList<>();
        Map<String, String> subjectMap = new HashMap<>();
        Map<String, ERPaperVo> paperMap = new HashMap<>();
        List<Integer> epids = new ArrayList<>();
        for (Map subject : subjects) {
            String subjectid = subject.get("subjectid").toString();
            String subjectname = subject.get("subjectname").toString();
            ERPaperVo p = new ERPaperVo();
            p.setSubjectid(subjectid);
            p.setPscore((Double) subject.get("pscore"));
            papers.add(p);
            subjectMap.put(subjectid, subjectname);
            paperMap.put(subjectid, p);
            epids.add((Integer) subject.get("epid"));
        }
        int classnum = classes.size();
        int stunum = classes.stream().mapToInt(m -> (int) m.get("classnum")).sum();
        int subjectnum = subjects.size();

        String subjectid;
        String subjectname;

        List<ERstudent> schoolStudents = new ArrayList<>();//学校学生成绩
        List<ERstudent> schoolSubjectStudents = new ArrayList<>();//学校科目学生成绩
        List<ERstudent> classStudents = new ArrayList<>();//班级学生成绩
        List<ERstudent> classSubjectStudents = new ArrayList<>();//班级科目学生成绩
        Map<String, Integer> schoolStuRank = new HashMap<>();//学校学生分数排名
        Map<String, Integer> schoolSubStuRank = new HashMap<>();//学校科目学生分数排名
        Map<String, Integer> classStuRank = new HashMap<>();//班级学生分数排名
        Map<String, Integer> classSubStuRank = new HashMap<>();//班级科目学生分数排名
        List<ERstudent> students = ePaperStudentMapper.listByExamId(examid, epids);
        Map<Integer, List<ERstudent>> schoolCollect = students.stream().collect(Collectors.groupingBy(s -> s.getStudentid()));
        for (Map.Entry<Integer, List<ERstudent>> entry : schoolCollect.entrySet()) {
            Integer studentid = entry.getKey();
            ERstudent cs = new ERstudent();
            List<ERstudent> list = entry.getValue();
            cs.setClassid(list.get(0).getClassid());
            cs.setStudentid(studentid);
            cs.setScore(list.stream().mapToDouble(s -> s.getScore()).sum());
            cs.setSstate(list.stream().max(Comparator.comparing(ERstudent::getSstate)).get().getSstate());
            schoolStudents.add(cs);
        }
        Map<Integer, List<ERstudent>> cCollect = students.stream().collect(Collectors.groupingBy(s -> s.getClassid()));
        for (Map.Entry<Integer, List<ERstudent>> entry : cCollect.entrySet()) {
            Integer classid = entry.getKey();
            subjectid = "zf";
            subjectname = "总分";
            List<ERstudent> studentList = entry.getValue();

            Map<Integer, List<ERstudent>> sCollect = studentList.stream().collect(Collectors.groupingBy(s -> s.getStudentid()));
            List<ERstudent> rstudents = new ArrayList<>();
            for (Map.Entry<Integer, List<ERstudent>> csEntry : sCollect.entrySet()) {
                ERstudent cs = new ERstudent();
                cs.setExamid(examid);
                cs.setClassid(classid);
                cs.setStudentid(csEntry.getKey());
                cs.setSubjectid(subjectid);
                cs.setSubjectname(subjectname);
                cs.setScore(csEntry.getValue().stream().mapToDouble(s -> s.getScore()).sum());
                rstudents.add(cs);
            }
            setRank(rstudents, classStuRank, 3);//班级学生分数排名
            classStudents.addAll(rstudents);
            Map<String, List<ERstudent>> subCollect = studentList.stream().collect(Collectors.groupingBy(s -> s.getSubjectid()));
            for (Map.Entry<String, List<ERstudent>> ssEntry : subCollect.entrySet()) {
                subjectid = ssEntry.getKey();
                subjectname = subjectMap.get(subjectid);
                studentList = ssEntry.getValue();
                rstudents = new ArrayList<>();
                for (ERstudent cs : studentList) {
                    cs.setSubjectname(subjectname);
                    rstudents.add(cs);
                }
                setRank(rstudents, classSubStuRank, 4);//班级科目学生分数排名
                classSubjectStudents.addAll(rstudents);
            }
        }

        DoubleSummaryStatistics schoolStatistics = schoolStudents.stream().mapToDouble(s -> s.getScore()).summaryStatistics();
        DoubleSummaryStatistics classStatistics = classStudents.stream().mapToDouble(s -> s.getScore()).summaryStatistics();
        DoubleSummaryStatistics cSStatistics = classSubjectStudents.stream().mapToDouble(s -> s.getScore()).summaryStatistics();
        double schoolStatisticsMax = schoolStatistics.getMax();
        double schoolStatisticsAverage = N_Utils.formatDouble(schoolStatistics.getAverage(), 2);
        double schoolStatisticsMin = schoolStatistics.getMin();
        if (N_Utils.isListEmpty(students)) {
            schoolStatisticsMax = 0;
            schoolStatisticsMin = 0;
        }

        ERbase rbase = new ERbase();
        rbase.setExamid(examid);
        rbase.setClassnum(classnum);
        rbase.setStunum(stunum);
        rbase.setMissnum(students.stream().filter(l -> l.getSstate() == 3)
                .map(l -> l.getStudentid()).distinct().collect(Collectors.toList()).size());
        rbase.setSubjectnum(subjectnum);
        rbase.setMaxscore(schoolStatisticsMax);
        rbase.setAvgscore(schoolStatisticsAverage);
        rbase.setMixscore(schoolStatisticsMin);
        eRbaseMapper.insertSelective(rbase);

        Map<String, List<ERstudent>> subCollect = students.stream().collect(Collectors.groupingBy(s -> s.getSubjectid()));
        List<ERsubject> subjectList = new ArrayList<>();//考试报告科目情况
        List<ERclass> classList = new ArrayList<>();//考试报告班级情况
        setSubject(examid, stunum, "zf", "总分", subjectList, classList, schoolStudents
                , papers.stream().mapToDouble(p -> p.getPscore()).sum());
        for (Map.Entry<String, List<ERstudent>> ssEntry : subCollect.entrySet()) {
            subjectid = ssEntry.getKey();
            subjectname = subjectMap.get(subjectid);
            List<ERstudent> list = ssEntry.getValue();
            Map<Integer, List<ERstudent>> sCollect = list.stream().collect(Collectors.groupingBy(s -> s.getStudentid()));
            List<ERstudent> rstudents = new ArrayList<>();
            for (Map.Entry<Integer, List<ERstudent>> csEntry : sCollect.entrySet()) {
                ERstudent cs = new ERstudent();
                cs.setClassid(0);
                cs.setStudentid(csEntry.getKey());
                cs.setSubjectid(subjectid);
                cs.setSubjectname(subjectname);
                cs.setScore(csEntry.getValue().stream().mapToDouble(s -> s.getScore()).sum());
                cs.setSstate(csEntry.getValue().get(0).getSstate());
                rstudents.add(cs);
            }
            setRank(rstudents, schoolSubStuRank, 2);//学校科目学生分数排名
            schoolSubjectStudents.addAll(rstudents);
            ERPaperVo rp = paperMap.get(subjectid);
            Double allscore = rp.getPscore();//满分
            setSubject(examid, stunum, subjectid, subjectname, subjectList, classList, list, allscore);
        }

        setClassAvgRank(classList);//班级科目平均分排名
        if (N_Utils.isListNotEmpty(classList)) eRclassMapper.insertList(classList);
        if (N_Utils.isListNotEmpty(subjectList)) eRsubjectMapper.insertList(subjectList);

        setRank(schoolStudents, schoolStuRank, 1);//学校学生分数排名

        Map<String, Double> bzcMap = subjectList.stream().collect(Collectors.toMap(ERsubject::getSubjectid, ERsubject::getBzc));
        for (ERstudent cs : classStudents) {
            Integer studentid = cs.getStudentid();
            cs.setClassrank(classStuRank.get(cs.getClassid() + "_" + studentid));
            cs.setClassmaxscore(classStatistics.getMax());
            cs.setClassavgscore(N_Utils.formatDouble(classStatistics.getAverage(), 2));
            Integer schoolrank = schoolStuRank.get(studentid.toString());
            cs.setSchoolrank(schoolrank);
            cs.setSchoolmaxscore(schoolStatisticsMax);
            cs.setSchoolavgscore(schoolStatisticsAverage);
            setStuGoal(stuRankGoals, cs, schoolrank);//设置学生目标
            Double bzc = bzcMap.get(cs.getSubjectid());
            cs.setBzscore(ExamUtil.standardScore(cs.getScore(), cs.getSchoolavgscore(), bzc));//学生标准分
        }
        if (N_Utils.isListNotEmpty(classStudents)) eRstudentMapper.insertList(classStudents);

        DoubleSummaryStatistics sSStatistics = schoolSubjectStudents.stream().mapToDouble(s -> s.getScore()).summaryStatistics();
        for (ERstudent cs : classSubjectStudents) {
            Integer studentid = cs.getStudentid();
            Integer classid = cs.getClassid();
            subjectid = cs.getSubjectid();
            cs.setClassrank(classSubStuRank.get(classid + "_" + subjectid + "_" + studentid));
            cs.setClassmaxscore(cSStatistics.getMax());
            cs.setClassavgscore(N_Utils.formatDouble(cSStatistics.getAverage(), 2));
            Integer schoolrank = schoolSubStuRank.get(subjectid + "_" + studentid);
            cs.setSchoolrank(schoolrank);
            cs.setZfSchoolRank(schoolStuRank.get(studentid.toString()));
            cs.setSchoolmaxscore(sSStatistics.getMax());
            cs.setSchoolavgscore(N_Utils.formatDouble(sSStatistics.getAverage(), 2));
            setStuGoal(stuRankGoals, cs, schoolrank);//设置学生目标
            Double bzc = bzcMap.get(subjectid);
            cs.setBzscore(ExamUtil.standardScore(cs.getScore(), cs.getSchoolavgscore(), bzc));//学生标准分
        }
        if (N_Utils.isListNotEmpty(classSubjectStudents)) eRstudentMapper.insertList(classSubjectStudents);

        setClassQuestion(examid, subjects, classes);//题型试题
        Map<Integer, String> userMap = new HashMap<>();
        if (N_Utils.isListNotEmpty(students)) {
            List<Integer> userids = students.stream().map(ERstudent::getStudentid).distinct().collect(Collectors.toList());
            List<UserVo> users = userMapper.listNameByUserIds(userids);
            userMap = users.stream().collect(Collectors.toMap(UserVo::getUserid, UserVo::getUsername));
        }
        setClassGradeRankAll(examid, stunum, papers, classSubjectStudents, createid, userMap);//班级等级分布
        setAction(examid, userMap);//行为分析
    }

    //科目统计
    private void setSubject(Integer examid, int stunum, String subjectid, String subjectname, List<ERsubject> subjectList,
                            List<ERclass> classList, List<ERstudent> list, Double allscore) {
        double yxscore = ExamUtil.mul(allscore, 0.85);//优秀分
        double lhscore = ExamUtil.mul(allscore, 0.7);//良好分
        double jgscore = ExamUtil.mul(allscore, 0.6);//及格分
        double dfscore = ExamUtil.mul(allscore, 0.4);//低分

        DoubleSummaryStatistics statistics = list.stream().mapToDouble(s -> s.getScore()).summaryStatistics();
        double maxscore = statistics.getMax();
        double minscore = statistics.getMin();
        if (N_Utils.isListEmpty(list)) {
            maxscore = 0;
            minscore = 0;
        }
        ERsubject rs = new ERsubject();
        rs.setExamid(examid);
        rs.setSubjectid(subjectid);
        rs.setSubjectname(subjectname);
        rs.setScore(allscore);
        rs.setMaxscore(maxscore);
        rs.setMinscore(minscore);
        rs.setAvgscore(N_Utils.formatDouble(statistics.getAverage(), 2));
        int yxnum = list.stream().filter(l -> l.getScore().compareTo(yxscore) != -1)
                .collect(Collectors.toList()).size();
        int lhnum = list.stream().filter(l -> l.getScore().compareTo(lhscore) != -1)
                .collect(Collectors.toList()).size();
        int jgnum = list.stream().filter(l -> l.getScore().compareTo(jgscore) != -1)
                .collect(Collectors.toList()).size();
        int dfnum = list.stream().filter(l -> l.getScore().compareTo(dfscore) != 1)
                .collect(Collectors.toList()).size();
        List<Double> scores = list.stream().map(l -> l.getScore()).collect(Collectors.toList());
        rs.setYxrate(N_Utils.getIntegerDivideAndMulitiply(yxnum, stunum));
        rs.setLhrate(N_Utils.getIntegerDivideAndMulitiply(lhnum, stunum));
        rs.setJgrate(N_Utils.getIntegerDivideAndMulitiply(jgnum, stunum));
        rs.setDfrate(N_Utils.getIntegerDivideAndMulitiply(dfnum, stunum));
        double qkbzc = ExamUtil.standardDiviation(scores);
        rs.setBzc(qkbzc);
        int sknum = list.stream().filter(l -> l.getSstate() == 2)
                .map(l -> l.getStudentid()).distinct().collect(Collectors.toList()).size();
        rs.setStunum(sknum);//实考人数
        rs.setMissnum(stunum - sknum);//缺考人数=计划人数-实考人数
        subjectList.add(rs);

        Map<Integer, List<ERstudent>> claCollect = list.stream().collect(Collectors.groupingBy(s -> s.getClassid()));
        for (Map.Entry<Integer, List<ERstudent>> entry : claCollect.entrySet()) {
            Integer classid = entry.getKey();
            List<ERstudent> rstudentList = entry.getValue();
            DoubleSummaryStatistics claStatistics = rstudentList.stream().mapToDouble(s -> s.getScore()).summaryStatistics();
            ERclass rc = new ERclass();
            rc.setQkbzc(qkbzc);
            rc.setExamid(examid);
            rc.setClassid(classid);
            rc.setSubjectid(subjectid);
            rc.setSubjectname(subjectname);
            rc.setAllscore(allscore);
            rc.setClassmaxscore(claStatistics.getMax());
            rc.setClassminscore(claStatistics.getMin());
            rc.setClassavgscore(N_Utils.formatDouble(claStatistics.getAverage(), 2));
            rc.setSchoolmaxscore(maxscore);
            rc.setSchoolavgscore(N_Utils.formatDouble(statistics.getAverage(), 2));
            sknum = rstudentList.stream().filter(l -> l.getSstate() == 2)
                    .map(l -> l.getStudentid()).distinct().collect(Collectors.toList()).size();
            rc.setStunum(sknum);//实考人数
            rc.setMissnum(stunum - sknum);//缺考人数=计划人数-实考人数
            yxnum = rstudentList.stream().filter(l -> l.getScore().compareTo(yxscore) != -1)
                    .collect(Collectors.toList()).size();
            lhnum = rstudentList.stream().filter(l -> l.getScore().compareTo(lhscore) != -1)
                    .collect(Collectors.toList()).size();
            jgnum = rstudentList.stream().filter(l -> l.getScore().compareTo(jgscore) != -1)
                    .collect(Collectors.toList()).size();
            dfnum = rstudentList.stream().filter(l -> l.getScore().compareTo(dfscore) != 1)
                    .collect(Collectors.toList()).size();
            scores = rstudentList.stream().map(l -> l.getScore()).collect(Collectors.toList());
            rc.setYxrate(N_Utils.getIntegerDivideAndMulitiply(yxnum, stunum));
            rc.setLhrate(N_Utils.getIntegerDivideAndMulitiply(lhnum, stunum));
            rc.setJgrate(N_Utils.getIntegerDivideAndMulitiply(jgnum, stunum));
            rc.setDfrate(N_Utils.getIntegerDivideAndMulitiply(dfnum, stunum));
            rc.setBzc(ExamUtil.standardDiviation(scores));
            classList.add(rc);
        }
    }

    //班级科目平均分排名
    private void setClassAvgRank(List<ERclass> classList) {
        Map<String, Integer> classSubRank = new HashMap<>();
        Map<String, List<ERclass>> collect = classList.stream().collect(Collectors.groupingBy(c -> c.getSubjectid()));
        for (Map.Entry<String, List<ERclass>> centry : collect.entrySet()) {
            List<Map.Entry<Double, List<ERclass>>> gslist2 = centry.getValue().stream()
                    .collect(Collectors.groupingBy(ERclass::getClassavgscore)).entrySet()
                    .stream().sorted((s1, s2) -> -Double.compare(s1.getKey(), s2.getKey())).collect(Collectors.toList());
            Integer index = 1;
            for (Map.Entry<Double, List<ERclass>> entry : gslist2) {
                for (ERclass rc : entry.getValue()) {
                    classSubRank.put(rc.getClassid() + "_" + rc.getSubjectid(), index);
                }
                index = index + entry.getValue().size();
            }
        }
        for (ERclass rc : classList) {
            rc.setClassavgscorerank(classSubRank.get(rc.getClassid() + "_" + rc.getSubjectid()));
        }
    }

    //行为分析
    private void setAction(Integer examid, Map<Integer, String> userMap) {
        List<ERstudentAction> studentActions = new ArrayList<>();
        List<ERclassAction> classActions = new ArrayList<>();
        //违纪行为
        List<Map> bads = eReportGenerateMapper.listBadActionByExamId(examid);
        Integer actiontype = 1;
        setActions(examid, studentActions, classActions, bads, actiontype, userMap);
        List<Map> goods = eReportGenerateMapper.listGoodActionByExamId(examid);
        actiontype = 2;
        setActions(examid, studentActions, classActions, goods, actiontype, userMap);
        if (N_Utils.isListEmpty(studentActions)) return;

        if (N_Utils.isListNotEmpty(studentActions)) eRstudentActionMapper.insertList(studentActions);
        if (N_Utils.isListNotEmpty(classActions)) eRclassActionMapper.insertList(classActions);
    }

    //处理行为数据
    private void setActions(Integer examid
            , List<ERstudentAction> studentActions, List<ERclassAction> classActions
            , List<Map> actions, Integer actiontype, Map<Integer, String> userMap) {
        if (N_Utils.isListNotEmpty(actions)) {
            //班级行为分析
            Map<Integer, List<Map>> ccollect = actions.stream().collect(Collectors.groupingBy(s -> (Integer) s.get("classid")));
            for (Map.Entry<Integer, List<Map>> entry : ccollect.entrySet()) {
                List<Map> subjects = new ArrayList<>();
                Map<String, List<Map>> scollect = entry.getValue().stream().collect(Collectors.groupingBy(s -> s.get("subjectid").toString()));
                for (Map.Entry<String, List<Map>> sentry : scollect.entrySet()) {
                    String subjectid = sentry.getKey();
                    int znum = actions.stream().filter(s -> s.get("subjectid").equals(subjectid))
                            .collect(Collectors.toList()).size();//总人数
                    List<Map> list = sentry.getValue();
                    Map subject = new HashMap();
                    subject.put("subjectid", subjectid);
                    subject.put("subjectname", list.get(0).get("subjectname"));
                    int num = list.size();
                    subject.put("num", num);
                    subject.put("nrate", N_Utils.getIntegerDivideAndMulitiply(num, znum));
                    List<Map> students = new ArrayList<>();
                    for (Map s : list) {
                        Map stu = new HashMap();
                        Integer studentid = (Integer) s.get("studentid");
                        stu.put("studentid", studentid);
                        stu.put("num", s.get("num"));
                        stu.put("studentname", userMap.get(studentid));
                        students.add(stu);
                    }
                    subject.put("students", students);
                    subjects.add(subject);
                }
                ERclassAction ca = new ERclassAction();
                ca.setClassid(entry.getKey());
                ca.setExamid(examid);
                ca.setActiontype(actiontype);
                String subjectjson = JSON.toJSONString(subjects);
                ca.setSubjectjson(subjectjson);
                classActions.add(ca);
            }

            //学生行为分析
            Map<Integer, List<Map>> collect = actions.stream().collect(Collectors.groupingBy(s -> (Integer) s.get("studentid")));
            for (Map.Entry<Integer, List<Map>> entry : collect.entrySet()) {
                List<Map> list = entry.getValue();
                Map sq = list.get(0);
                ERstudentAction sa = new ERstudentAction();
                sa.setClassid((Integer) sq.get("classid"));
                sa.setStudentid(entry.getKey());
                sa.setExamid(examid);
                sa.setActiontype(actiontype);
                for (Map s : list) {
                    s.remove("classid");
                    s.remove("studentid");
                }
                String subjectjson = JSON.toJSONString(list);
                sa.setSubjectjson(subjectjson);
                studentActions.add(sa);
            }
        }
    }

    //班级等级分布
    private void setClassGradeRankAll(Integer examid, Integer stunum, List<ERPaperVo> papers, List<ERstudent> students
            , Integer createid, Map<Integer, String> userMap) {
        setClassGradeRank(examid, stunum, papers, students, setRrank(1), createid, userMap);//班级等级分布--等级
        setClassGradeRank(examid, stunum, papers, students, setRrank(2), createid, userMap);//班级等级分布--分数段
        setClassGradeRank(examid, stunum, papers, students, setRrank(3), createid, userMap);//班级等级分布--临界分
        setClassGradeRank(examid, stunum, papers, students, setRrank(4), createid, userMap);//班级等级分布--临界名次
        setClassGradeRank(examid, stunum, papers, students, setRrank(5), createid, userMap);//班级等级分布--优困生
    }

    //等级初始值设置
    private List<ERrank> setRrank(Integer ranktype) {
        List<ERrank> rranks = new ArrayList<>();
        ERrank rrank;
        if (ranktype == 1) {//等级（A[85%~100%],B[70%~85%),C[60%~70%),D[40%~60%),E[0%~40%)）
            rrank = new ERrank();
            rrank.setRanktype(ranktype);
            rrank.setRankname("A");
            rrank.setMaxscore(1.0);
            rrank.setMinscore(0.85);
            rranks.add(rrank);

            rrank = new ERrank();
            rrank.setRanktype(ranktype);
            rrank.setRankname("B");
            rrank.setMaxscore(0.85);
            rrank.setMinscore(0.7);
            rranks.add(rrank);

            rrank = new ERrank();
            rrank.setRanktype(ranktype);
            rrank.setRankname("C");
            rrank.setMaxscore(0.7);
            rrank.setMinscore(0.6);
            rranks.add(rrank);

            rrank = new ERrank();
            rrank.setRanktype(ranktype);
            rrank.setRankname("D");
            rrank.setMaxscore(0.6);
            rrank.setMinscore(0.4);
            rranks.add(rrank);

            rrank = new ERrank();
            rrank.setRanktype(ranktype);
            rrank.setRankname("E");
            rrank.setMaxscore(0.4);
            rrank.setMinscore(0.0);
            rranks.add(rrank);
        } else if (ranktype == 2) {//分数段（10分/段）
            rrank = new ERrank();
            rrank.setRanktype(ranktype);
            rrank.setLinescore(10);
            rranks.add(rrank);
        } else if (ranktype == 3) {//临界分（临界分：总分*80%，浮动分：5分）
            rrank = new ERrank();
            rrank.setRanktype(ranktype);
            rrank.setFloatscore(5);
            rranks.add(rrank);
        } else if (ranktype == 4) {//临界名次（临界名次10，浮动名次5）
            rrank = new ERrank();
            rrank.setRanktype(ranktype);
            rrank.setLinescore(10);
            rrank.setFloatscore(5);
            rranks.add(rrank);
        } else if (ranktype == 5) {//优困生年级前/后（10名）
            rrank = new ERrank();
            rrank.setRanktype(ranktype);
            rrank.setLinescore(10);
            rrank.setFloatscore(10);
            rranks.add(rrank);
        }
        return rranks;
    }

    //班级等级分布
    public void setClassGradeRank(Integer examid, Integer fbstunum, List<ERPaperVo> papers, List<ERstudent> students
            , List<ERrank> rranks, Integer createid, Map<Integer, String> userMap) {
        Map<String, Double> scoreMap = papers.stream().collect(Collectors.toMap(p -> p.getSubjectid(), p -> p.getPscore()));//考试总分
        Double pscore;//试卷总分
        Double zfscore = papers.stream().mapToDouble(p -> p.getPscore()).sum();//考试总分
        List<ERstudent> cstudents = new ArrayList<>();//班级学生
        Map<String, List<ERstudent>> cscollect = students.stream().collect(
                Collectors.groupingBy(s -> s.getClassid() + "_" + s.getStudentid()));
        setStuScore(cscollect, cstudents);
        //总分统计
        Map<Integer, List<ERstudent>> zfcollect = cstudents.stream().collect(
                Collectors.groupingBy(s -> s.getClassid()));
        //全部班级统计
        Map<String, List<ERstudent>> qbbjcollect = students.stream().collect(
                Collectors.groupingBy(s -> s.getSubjectid()));

        List<ERrank> rrankList = new ArrayList<>();//考试报告等级
        List<ERclassRank> rclassRankList = new ArrayList<>();//考试报告班级统计
        ERrank eRrank = rranks.get(0);
        Integer ranktype = eRrank.getRanktype();
        if (ranktype == 1) {//等级（A[85%~100%],B[70%~85%),C[60%~70%),D[40%~60%),E[0%~40%)）
            for (ERrank rank : rranks) {
                Double maxrate = rank.getMaxscore();
                Double minrate = rank.getMinscore();
                //总分统计
                double zfmaxscore = ExamUtil.mul(maxrate, zfscore);
                double zfminscore = ExamUtil.mul(minrate, zfscore);
                ERrank rr = new ERrank();
                String rankname = rank.getRankname();
                rr.setRanktype(ranktype);
                rr.setRankname(rankname);
                rr.setMaxscore(zfmaxscore);
                rr.setMinscore(zfminscore);
                rr.setSubjectid("zf");
                String zfrankrange = getRankRange(zfmaxscore, zfminscore);
                List<ERstudent> collect;
                if (rr.getRankname().equals("A")) {
                    zfrankrange = zfrankrange + "]";
                    collect = cstudents.stream().filter(
                            s -> s.getScore().compareTo(zfminscore) != -1
                    ).collect(Collectors.toList());
                } else {
                    zfrankrange = zfrankrange + ")";
                    collect = cstudents.stream().filter(
                            s -> s.getScore().compareTo(zfminscore) != -1 && s.getScore().compareTo(zfmaxscore) == -1
                    ).collect(Collectors.toList());
                }
                setDjTj(examid, fbstunum, userMap, rclassRankList, rr, zfrankrange, "zf", 0, cstudents);
                for (Map.Entry<Integer, List<ERstudent>> entry : zfcollect.entrySet()) {
                    Integer classid = entry.getKey();
                    String subjectid = "zf";
                    List<ERstudent> list = entry.getValue();
                    setDjTj(examid, fbstunum, userMap, rclassRankList, rr, zfrankrange, subjectid, classid, list);
                }
                Integer maxrank = null;
                Integer minrank = null;
                if (N_Utils.isListNotEmpty(collect)) {
                    maxrank = collect.stream().max(Comparator.comparing(ERstudent::getZfSchoolRank)).get().getSchoolrank();
                    minrank = collect.stream().min(Comparator.comparing(ERstudent::getZfSchoolRank)).get().getSchoolrank();
                }
                rr.setLinescore(maxrank);
                rr.setFloatscore(minrank);
                rrankList.add(rr);

                //分科统计
                for (ERPaperVo paper : papers) {
                    String subjectid = paper.getSubjectid();
                    ERrank rrank = new ERrank();
                    rrank.setRanktype(ranktype);
                    rrank.setRankname(rankname);
                    rrank.setSubjectid(subjectid);
                    pscore = scoreMap.get(subjectid);
                    double maxscore = ExamUtil.mul(maxrate, pscore);
                    double minscore = ExamUtil.mul(minrate, pscore);
                    rrank.setMaxscore(maxscore);
                    rrank.setMinscore(minscore);
                    String rankrange = getRankRange(maxscore, minscore);
                    List<ERstudent> list = listStudentBySubjectId(subjectid, qbbjcollect);
                    if (rankname.equals("A")) {
                        rankrange = rankrange + "]";
                        collect = list.stream().filter(
                                s -> s.getScore().compareTo(minscore) != -1
                        ).collect(Collectors.toList());
                    } else {
                        rankrange = rankrange + ")";
                        collect = list.stream().filter(
                                s -> s.getScore().compareTo(minscore) != -1 && s.getScore().compareTo(maxscore) == -1
                        ).collect(Collectors.toList());
                    }

                    //全部班级统计
                    Integer classid = 0;
                    setDjTj(examid, fbstunum, userMap, rclassRankList, rrank, rankrange, subjectid, classid, list);
                    maxrank = null;
                    minrank = null;
                    if (N_Utils.isListNotEmpty(collect)) {
                        maxrank = collect.stream().max(Comparator.comparing(ERstudent::getSchoolrank)).get().getSchoolrank();
                        minrank = collect.stream().min(Comparator.comparing(ERstudent::getSchoolrank)).get().getSchoolrank();
                    }
                    rrank.setLinescore(maxrank);
                    rrank.setFloatscore(minrank);
                    rrankList.add(rrank);

                    //班级科目统计
                    Map<Integer, List<ERstudent>> ccollect = students.stream().filter(s -> s.getSubjectid().equals(subjectid))
                            .collect(Collectors.groupingBy(s -> s.getClassid()));
                    for (Map.Entry<Integer, List<ERstudent>> entry : ccollect.entrySet()) {
                        classid = entry.getKey();
                        list = entry.getValue();
                        setDjTj(examid, fbstunum, userMap, rclassRankList, rrank, rankrange, subjectid, classid, list);
                    }
                }
            }
        } else if (ranktype == 2) {//分数段（10分/段）
            Integer linescore = eRrank.getLinescore();
            //总分统计
            Integer gnum = ExamUtil.divUp(zfscore, linescore);
            for (Integer i = 1; i <= gnum; i++) {
                ERrank rrank = new ERrank();
                rrank.setRanktype(ranktype);
                double maxscore = ExamUtil.mul(i, linescore);
                double minscore = ExamUtil.mul(i - 1, linescore);
                if (maxscore > zfscore) {
                    maxscore = zfscore;
                }
                rrank.setMaxscore(maxscore);
                rrank.setMinscore(minscore);
                String rankrange = getRankRange(maxscore, minscore);
                if (i == gnum) {
                    rankrange = rankrange + "]";
                } else {
                    rankrange = rankrange + ")";
                }
                rrank.setRankname(rankrange);
                rrank.setSubjectid("zf");
                rrankList.add(rrank);

                setFdTj(examid, fbstunum, userMap, rclassRankList, gnum, i, rrank, rankrange, 0, cstudents);
                for (Map.Entry<Integer, List<ERstudent>> entry : zfcollect.entrySet()) {
                    Integer classid = entry.getKey();
                    String subjectid = "zf";
                    List<ERstudent> list = entry.getValue();
                    setFdTj(examid, fbstunum, userMap, rclassRankList, gnum, i, rrank, rankrange, classid, list);
                }
            }

            //分科统计
            for (ERPaperVo paper : papers) {
                String subjectid = paper.getSubjectid();
                pscore = scoreMap.get(subjectid);
                Integer cnum = ExamUtil.divUp(pscore, linescore);
                for (Integer i = 1; i <= cnum; i++) {
                    ERrank rrank = new ERrank();
                    rrank.setSubjectid(subjectid);
                    rrank.setRanktype(ranktype);
                    rrank.setSubjectid(subjectid);
                    double maxscore = ExamUtil.mul(i, linescore);
                    double minscore = ExamUtil.mul(i - 1, linescore);
                    if (maxscore > pscore) {
                        maxscore = pscore;
                    }
                    rrank.setMaxscore(maxscore);
                    rrank.setMinscore(minscore);
                    String rankrange = getRankRange(maxscore, minscore);
                    if (i == cnum) {
                        rankrange = rankrange + "]";
                    } else {
                        rankrange = rankrange + ")";
                    }
                    rrank.setRankname(rankrange);
                    rrankList.add(rrank);

                    //全部班级统计
                    Integer classid = 0;
                    List<ERstudent> list = listStudentBySubjectId(subjectid, qbbjcollect);
                    setFdTj(examid, fbstunum, userMap, rclassRankList, cnum, i, rrank, rankrange, classid, list);

                    //班级科目统计
                    Map<Integer, List<ERstudent>> ccollect = students.stream().filter(s -> s.getSubjectid().equals(subjectid))
                            .collect(Collectors.groupingBy(s -> s.getClassid()));
                    for (Map.Entry<Integer, List<ERstudent>> entry : ccollect.entrySet()) {
                        classid = entry.getKey();
                        list = entry.getValue();
                        setFdTj(examid, fbstunum, userMap, rclassRankList, cnum, i, rrank, rankrange, classid, list);
                    }
                }
            }
        } else {
            Integer lscore = eRrank.getLinescore();
            if (ranktype == 3) {//临界分（临界分：总分*80%，浮动分：5分）
                Integer linescore = lscore;
                Integer floatscore = eRrank.getFloatscore();
                ERrank rr = new ERrank();
                rr.setRanktype(ranktype);
                //总分统计
                if (N_Utils.isEmptyInteger(linescore)) linescore = (int) (ExamUtil.mul(zfscore, 0.8));
                double zfmaxscore = ExamUtil.add(linescore, floatscore);
                double zfminscore = ExamUtil.sub(linescore, floatscore);
                if (zfmaxscore > zfscore) zfmaxscore = zfscore;
                if (zfminscore < 0) zfminscore = 0;
                rr.setMaxscore(zfmaxscore);
                rr.setMinscore(zfminscore);
                rr.setLinescore(linescore);
                rr.setFloatscore(floatscore);
                String zfrankrange = getRankRange(zfmaxscore, zfminscore) + "]";
                rr.setRankname(zfrankrange);
                rr.setSubjectid("zf");
                rrankList.add(rr);

                setLjfTj(examid, fbstunum, userMap, rclassRankList, rr, zfrankrange, 0, "zf", cstudents);
                for (Map.Entry<Integer, List<ERstudent>> entry : zfcollect.entrySet()) {
                    Integer classid = entry.getKey();
                    String subjectid = "zf";
                    List<ERstudent> list = entry.getValue();
                    setLjfTj(examid, fbstunum, userMap, rclassRankList, rr, zfrankrange, classid, subjectid, list);
                }

                //分科统计
                for (ERPaperVo paper : papers) {
                    String subjectid = paper.getSubjectid();
                    ERrank rrank = new ERrank();
                    rrank.setRanktype(ranktype);
                    rrank.setSubjectid(subjectid);
                    pscore = scoreMap.get(subjectid);
                    linescore = lscore;
                    if (N_Utils.isEmptyInteger(linescore)) linescore = (int) (ExamUtil.mul(pscore, 0.8));
                    double maxscore = ExamUtil.add(linescore, floatscore);
                    double minscore = ExamUtil.sub(linescore, floatscore);
                    if (maxscore > pscore) maxscore = pscore;
                    if (minscore < 0) minscore = 0;
                    rrank.setMaxscore(maxscore);
                    rrank.setMinscore(minscore);
                    rrank.setLinescore(linescore);
                    rrank.setFloatscore(floatscore);
                    String rankrange = getRankRange(maxscore, minscore) + "]";
                    rrank.setRankname(rankrange);
                    rrankList.add(rrank);

                    //全部班级统计
                    Integer classid = 0;
                    List<ERstudent> list = listStudentBySubjectId(subjectid, qbbjcollect);
                    setLjfTj(examid, fbstunum, userMap, rclassRankList, rrank, rankrange, classid, subjectid, list);

                    //班级科目统计
                    Map<Integer, List<ERstudent>> ccollect = students.stream().filter(s -> s.getSubjectid().equals(subjectid))
                            .collect(Collectors.groupingBy(s -> s.getClassid()));
                    for (Map.Entry<Integer, List<ERstudent>> entry : ccollect.entrySet()) {
                        classid = entry.getKey();
                        list = entry.getValue();
                        setLjfTj(examid, fbstunum, userMap, rclassRankList, rrank, rankrange, classid, subjectid, list);
                    }
                }
            } else if (ranktype == 4) {//临界名次（临界名次10，浮动名次5）
                Integer linescore = lscore;
                Integer floatscore = eRrank.getFloatscore();
                ERrank rr = new ERrank();
                rr.setRanktype(ranktype);
                //总分统计
                double zfmaxscore = ExamUtil.sub(linescore, floatscore);//最高名次
                double zfminscore = ExamUtil.add(linescore, floatscore);//最低名次
                if (zfmaxscore < 1) zfmaxscore = 1;//最高名次为1
                int zfstunum = (int) students.stream().map(s -> s.getStudentid()).distinct().count();//学生数量
                if (zfminscore > zfstunum) zfminscore = zfstunum;//最低名次=学生数量
                rr.setMaxscore(zfmaxscore);
                rr.setMinscore(zfminscore);
                rr.setLinescore(linescore);
                rr.setFloatscore(floatscore);
                String zfrankrange = getRankRange(zfmaxscore, zfminscore) + "]";
                rr.setRankname(zfrankrange);
                rr.setSubjectid("zf");
                rrankList.add(rr);

                setLjmcTj(examid, fbstunum, userMap, rclassRankList, rr, zfrankrange, 0, "zf", cstudents);
                for (Map.Entry<Integer, List<ERstudent>> entry : zfcollect.entrySet()) {
                    Integer classid = entry.getKey();
                    String subjectid = "zf";
                    List<ERstudent> list = entry.getValue();
                    setLjmcTj(examid, fbstunum, userMap, rclassRankList, rr, zfrankrange, classid, subjectid, list);
                }

                //分科统计
                for (ERPaperVo paper : papers) {
                    String subjectid = paper.getSubjectid();
                    double maxscore = ExamUtil.sub(linescore, floatscore);//最高名次
                    double minscore = ExamUtil.add(linescore, floatscore);//最低名次
                    if (maxscore < 1) maxscore = 1;//最高名次为1
                    Integer stunum = students.size();//学生数量
                    if (minscore > stunum) minscore = stunum;//最低名次=学生数量
                    ERrank rrank = new ERrank();
                    rrank.setRanktype(ranktype);
                    rrank.setSubjectid(subjectid);
                    rrank.setMaxscore(maxscore);
                    rrank.setMinscore(minscore);
                    rrank.setLinescore(linescore);
                    rrank.setFloatscore(floatscore);
                    String rankrange = getRankRange(maxscore, minscore) + "]";
                    rrank.setRankname(rankrange);
                    rrankList.add(rrank);

                    //全部班级统计
                    Integer classid = 0;
                    List<ERstudent> list = listStudentBySubjectId(subjectid, qbbjcollect);
                    setLjmcTj(examid, fbstunum, userMap, rclassRankList, rrank, rankrange, classid, subjectid, list);

                    //班级科目统计
                    Map<Integer, List<ERstudent>> ccollect = students.stream().filter(s -> s.getSubjectid().equals(subjectid))
                            .collect(Collectors.groupingBy(s -> s.getClassid()));
                    for (Map.Entry<Integer, List<ERstudent>> entry : ccollect.entrySet()) {
                        classid = entry.getKey();
                        list = entry.getValue();
                        setLjmcTj(examid, fbstunum, userMap, rclassRankList, rrank, rankrange, classid, subjectid, list);
                    }
                }
            } else if (ranktype == 5) {//优困生
                Integer linescore = lscore;
                Integer floatscore = eRrank.getFloatscore();
                ERrank rr = new ERrank();
                rr.setRanktype(ranktype);
                rr.setLinescore(linescore);
                rr.setFloatscore(floatscore);
                String rankrange = getRankRange(floatscore, linescore) + "]";
                String rankname = "优困生";
                rr.setRankname(rankname);
                //总分统计
                rr.setSubjectid("zf");
                rrankList.add(rr);
                rr.setMaxscore(getMaxScore(cstudents, floatscore));
                setYksTj(examid, fbstunum, rclassRankList, rr, rankrange, 0, "zf", cstudents);
                for (Map.Entry<Integer, List<ERstudent>> entry : zfcollect.entrySet()) {
                    Integer classid = entry.getKey();
                    String subjectid = "zf";
                    List<ERstudent> list = entry.getValue();
                    rr.setMaxscore(getMaxScore(list, floatscore));
                    setYksTj(examid, fbstunum, rclassRankList, rr, rankrange, classid, subjectid, list);
                }
                rr.setMaxscore(null);

                //分科统计
                for (ERPaperVo paper : papers) {
                    String subjectid = paper.getSubjectid();
                    ERrank rrank = new ERrank();
                    rrank.setRanktype(ranktype);
                    rrank.setRankname(rankname);
                    rrank.setLinescore(linescore);
                    rrank.setFloatscore(floatscore);
                    rrank.setSubjectid(subjectid);
                    rrankList.add(rrank);
                    //全部班级统计
                    Integer classid = 0;
                    List<ERstudent> list = listStudentBySubjectId(subjectid, qbbjcollect);
                    rrank.setMaxscore(getMaxScore(list, floatscore));
                    setYksTj(examid, fbstunum, rclassRankList, rrank, rankrange, classid, subjectid, list);

                    //班级科目统计
                    Map<Integer, List<ERstudent>> ccollect = students.stream().filter(s -> s.getSubjectid().equals(subjectid))
                            .collect(Collectors.groupingBy(s -> s.getClassid()));
                    for (Map.Entry<Integer, List<ERstudent>> entry : ccollect.entrySet()) {
                        classid = entry.getKey();
                        list = entry.getValue();
                        setYksTj(examid, fbstunum, rclassRankList, rrank, rankrange, classid, subjectid, list);
                    }
                    rrank.setMaxscore(null);
                }
            }
        }

        int timestamp = N_Utils.getSecondTimestamp();
        rrankList.forEach(r -> {
            r.setExamid(examid);
            r.setCreateid(createid);
            r.setCreatetime(timestamp);
        });
        if (N_Utils.isListNotEmpty(rrankList)) eRrankMapper.insertList(rrankList);
        saveClassRank(rclassRankList, ranktype);//保存考试报告班级等级分布
    }

    //保存考试报告班级等级分布
    private void saveClassRank(List<ERclassRank> rclassRankList, Integer ranktype) {
        if (N_Utils.isListEmpty(rclassRankList)) return;
        if (ranktype == 3 || ranktype == 4) {
            Map<String, List<ERclassRank>> collect = rclassRankList.stream().collect(
                    Collectors.groupingBy(r -> r.getSubjectid(), LinkedHashMap::new, Collectors.toList()));
            for (Map.Entry<String, List<ERclassRank>> entry : collect.entrySet()) {
                Integer znum = 0;//范围内总人数
                List<ERclassRank> rankList = entry.getValue();
                for (int i = 0; i < rankList.size(); i++) {
                    ERclassRank r = rankList.get(i);
                    if (i == 0) {
                        r.setSturate(100.0);
                        znum = r.getStunum();
                    } else {
                        r.setSturate(N_Utils.getIntegerDivideAndMulitiply(r.getStunum(), znum));
                    }
                }
            }
        } else if (ranktype == 5) {
            Map<String, List<ERclassRank>> collect = rclassRankList.stream().collect(
                    Collectors.groupingBy(r -> r.getSubjectid(), LinkedHashMap::new, Collectors.toList()));
            for (Map.Entry<String, List<ERclassRank>> entry : collect.entrySet()) {
                Integer qznum = 0;//前X名总人数
                Integer hznum = 0;//后X名总人数
                List<ERclassRank> rankList = entry.getValue();
                for (int i = 0; i < rankList.size(); i++) {
                    ERclassRank r = rankList.get(i);
                    List<Map> list = JSON.parseArray(r.getStujson(), Map.class);
                    Map q = new HashMap();
                    Map h = new HashMap();
                    if (N_Utils.isListNotEmpty(list)) {
                        q = list.get(0);
                        h = list.get(1);
                    }
                    if (i == 0) {
                        if (N_Utils.isListEmpty(list)) continue;
                        qznum = (Integer) q.get("stunum");
                        hznum = (Integer) h.get("stunum");
                        q.put("sturate", 100);
                        h.put("sturate", 100);
                    } else {
                        q.put("sturate", N_Utils.getIntegerDivideAndMulitiply((Integer) q.get("stunum"), qznum));
                        h.put("sturate", N_Utils.getIntegerDivideAndMulitiply((Integer) h.get("stunum"), hznum));
                    }
                    r.setStujson(JSON.toJSONString(list));
                }
            }
        }
        eRclassRankMapper.insertList(rclassRankList);
    }

    //单科校次
    private void setSchoolRank(List<ERstudent> students, Map<Integer, Integer> rank) {
        List<Map.Entry<Double, List<ERstudent>>> gslist2 = students.stream()
                .collect(Collectors.groupingBy(ERstudent::getScore)).entrySet()
                .stream().sorted((s1, s2) -> -Double.compare(s1.getKey(), s2.getKey())).collect(Collectors.toList());
        Integer index = 1;
        for (Map.Entry<Double, List<ERstudent>> entry : gslist2) {
            for (ERstudent cgs : entry.getValue()) {
                Integer studentid = cgs.getStudentid();
                rank.put(studentid, index);
                cgs.setSchoolrank(index);
                cgs.setZfSchoolRank(index);
                cgs.setClassrank(index);
            }
            index = index + entry.getValue().size();
        }
    }

    //单科等级分布
    public void setSubjectRank(Integer examid, String subjectid, Integer createid, List<ERrank> rranks, Integer ranktype) {
        Integer fbstunum = eReportGenerateMapper.getStuNumByExamId(examid);//获取考试发布学生数量
        Double pscore = eReportGenerateMapper.getScoreByExamAndSubjectId(examid, subjectid);//获取试卷分数
        List<ERstudent> students = ePaperStudentMapper.listByExamAndSubjectId(examid, subjectid);//考试试卷学生
        List<Integer> userids = students.stream().map(ERstudent::getStudentid).distinct().collect(Collectors.toList());
        List<UserVo> users = userMapper.listNameByUserIds(userids);
        Map<Integer, String> userMap = users.stream().collect(Collectors.toMap(UserVo::getUserid, UserVo::getUsername));
        List<ERstudent> cstudents = new ArrayList<>();//班级学生
        Map<String, List<ERstudent>> cscollect = students.stream().collect(
                Collectors.groupingBy(s -> s.getClassid() + "_" + s.getStudentid()));
        setStuScore(cscollect, cstudents);
        //总分统计
        Map<Integer, List<ERstudent>> zfcollect = cstudents.stream().collect(
                Collectors.groupingBy(s -> s.getClassid()));

        //排名
        Map<Integer, Integer> schoolStuRank = new HashMap<>();//学校学生分数排名
        setSchoolRank(cstudents, schoolStuRank);//学校学生分数排名
        for (ERstudent cs : students) {
            Integer studentid = cs.getStudentid();
            Integer schoolrank = schoolStuRank.get(studentid);
            cs.setSchoolrank(schoolrank);
            cs.setZfSchoolRank(schoolrank);
            cs.setClassrank(schoolrank);
        }

        //全部班级统计
        Map<String, List<ERstudent>> qbbjcollect = students.stream().collect(
                Collectors.groupingBy(s -> s.getSubjectid()));

        List<ERrank> rrankList = new ArrayList<>();//考试报告等级
        List<ERclassRank> rclassRankList = new ArrayList<>();//考试报告班级统计
        ERrank eRrank = rranks.get(0);
        if (ranktype == 1) {//等级（A[85%~100%],B[70%~85%),C[60%~70%),D[40%~60%),E[0%~40%)）
            for (ERrank rank : rranks) {
                Double maxscore = rank.getMaxscore();
                Double minscore = rank.getMinscore();
                String rankname = rank.getRankname();
                if ("zf".equals(subjectid)) {
                    //总分统计
                    ERrank rr = new ERrank();
                    rr.setRanktype(ranktype);
                    rr.setRankname(rankname);
                    rr.setMaxscore(maxscore);
                    rr.setMinscore(minscore);
                    rr.setSubjectid("zf");
                    String zfrankrange = getRankRange(maxscore, minscore);
                    List<ERstudent> collect;
                    if (rr.getRankname().equals("A")) {
                        zfrankrange = zfrankrange + "]";
                        collect = cstudents.stream().filter(
                                s -> s.getScore().compareTo(minscore) != -1
                        ).collect(Collectors.toList());
                    } else {
                        zfrankrange = zfrankrange + ")";
                        collect = cstudents.stream().filter(
                                s -> s.getScore().compareTo(minscore) != -1 && s.getScore().compareTo(maxscore) == -1
                        ).collect(Collectors.toList());
                    }
                    setDjTj(examid, fbstunum, userMap, rclassRankList, rr, zfrankrange, subjectid, 0, cstudents);
                    for (Map.Entry<Integer, List<ERstudent>> entry : zfcollect.entrySet()) {
                        Integer classid = entry.getKey();
                        List<ERstudent> list = entry.getValue();
                        setDjTj(examid, fbstunum, userMap, rclassRankList, rr, zfrankrange, subjectid, classid, list);
                    }
                    Integer maxrank = null;
                    Integer minrank = null;
                    if (N_Utils.isListNotEmpty(collect)) {
                        maxrank = collect.stream().max(Comparator.comparing(ERstudent::getSchoolrank)).get().getSchoolrank();
                        minrank = collect.stream().min(Comparator.comparing(ERstudent::getSchoolrank)).get().getSchoolrank();
                    }
                    rr.setLinescore(maxrank);
                    rr.setFloatscore(minrank);
                    rrankList.add(rr);
                } else {
                    //分科统计
                    ERrank rrank = new ERrank();
                    rrank.setRanktype(ranktype);
                    rrank.setRankname(rankname);
                    rrank.setSubjectid(subjectid);
                    rrank.setMaxscore(maxscore);
                    rrank.setMinscore(minscore);
                    String rankrange = getRankRange(maxscore, minscore);
                    List<ERstudent> list = listStudentBySubjectId(subjectid, qbbjcollect);
                    List<ERstudent> collect;
                    if (rankname.equals("A")) {
                        rankrange = rankrange + "]";
                        collect = list.stream().filter(
                                s -> s.getScore().compareTo(minscore) != -1
                        ).collect(Collectors.toList());
                    } else {
                        rankrange = rankrange + ")";
                        collect = list.stream().filter(
                                s -> s.getScore().compareTo(minscore) != -1 && s.getScore().compareTo(maxscore) == -1
                        ).collect(Collectors.toList());
                    }

                    //全部班级统计
                    Integer classid = 0;
                    setDjTj(examid, fbstunum, userMap, rclassRankList, rrank, rankrange, subjectid, classid, list);
                    Integer maxrank = null;
                    Integer minrank = null;
                    if (N_Utils.isListNotEmpty(collect)) {
                        maxrank = collect.stream().max(Comparator.comparing(ERstudent::getSchoolrank)).get().getSchoolrank();
                        minrank = collect.stream().min(Comparator.comparing(ERstudent::getSchoolrank)).get().getSchoolrank();
                    }
                    rrank.setLinescore(maxrank);
                    rrank.setFloatscore(minrank);
                    rrankList.add(rrank);

                    //班级科目统计
                    Map<Integer, List<ERstudent>> ccollect = students.stream().filter(s -> s.getSubjectid().equals(subjectid))
                            .collect(Collectors.groupingBy(s -> s.getClassid()));
                    for (Map.Entry<Integer, List<ERstudent>> entry : ccollect.entrySet()) {
                        classid = entry.getKey();
                        list = entry.getValue();
                        setDjTj(examid, fbstunum, userMap, rclassRankList, rrank, rankrange, subjectid, classid, list);
                    }
                }
            }
        } else if (ranktype == 2) {//分数段（10分/段）
            Integer linescore = eRrank.getLinescore();
            if ("zf".equals(subjectid)) {
                //总分统计
                Integer gnum = ExamUtil.divUp(pscore, linescore);
                for (Integer i = 1; i <= gnum; i++) {
                    ERrank rrank = new ERrank();
                    rrank.setRanktype(ranktype);
                    double maxscore = ExamUtil.mul(i, linescore);
                    double minscore = ExamUtil.mul(i - 1, linescore);
                    if (maxscore > pscore) {
                        maxscore = pscore;
                    }
                    rrank.setMaxscore(maxscore);
                    rrank.setMinscore(minscore);
                    String rankrange = getRankRange(maxscore, minscore);
                    if (i == gnum) {
                        rankrange = rankrange + "]";
                    } else {
                        rankrange = rankrange + ")";
                    }
                    rrank.setRankname(rankrange);
                    rrank.setSubjectid("zf");
                    rrankList.add(rrank);

                    setFdTj(examid, fbstunum, userMap, rclassRankList, gnum, i, rrank, rankrange, 0, cstudents);
                    for (Map.Entry<Integer, List<ERstudent>> entry : zfcollect.entrySet()) {
                        Integer classid = entry.getKey();
                        List<ERstudent> list = entry.getValue();
                        setFdTj(examid, fbstunum, userMap, rclassRankList, gnum, i, rrank, rankrange, classid, list);
                    }
                }
            } else {
                //分科统计
                Integer cnum = ExamUtil.divUp(pscore, linescore);
                for (Integer i = 1; i <= cnum; i++) {
                    ERrank rrank = new ERrank();
                    rrank.setSubjectid(subjectid);
                    rrank.setRanktype(ranktype);
                    rrank.setSubjectid(subjectid);
                    double maxscore = ExamUtil.mul(i, linescore);
                    double minscore = ExamUtil.mul(i - 1, linescore);
                    if (maxscore > pscore) {
                        maxscore = pscore;
                    }
                    rrank.setMaxscore(maxscore);
                    rrank.setMinscore(minscore);
                    String rankrange = getRankRange(maxscore, minscore);
                    if (i == cnum) {
                        rankrange = rankrange + "]";
                    } else {
                        rankrange = rankrange + ")";
                    }
                    rrank.setRankname(rankrange);
                    rrankList.add(rrank);

                    //全部班级统计
                    Integer classid = 0;
                    List<ERstudent> list = listStudentBySubjectId(subjectid, qbbjcollect);
                    setFdTj(examid, fbstunum, userMap, rclassRankList, cnum, i, rrank, rankrange, classid, list);

                    //班级科目统计
                    Map<Integer, List<ERstudent>> ccollect = students.stream().filter(s -> s.getSubjectid().equals(subjectid))
                            .collect(Collectors.groupingBy(s -> s.getClassid()));
                    for (Map.Entry<Integer, List<ERstudent>> entry : ccollect.entrySet()) {
                        classid = entry.getKey();
                        list = entry.getValue();
                        setFdTj(examid, fbstunum, userMap, rclassRankList, cnum, i, rrank, rankrange, classid, list);
                    }
                }
            }
        } else {
            Integer lscore = eRrank.getLinescore();
            if (ranktype == 3) {//临界分（临界分：总分*80%，浮动分：5分）
                Integer linescore = lscore;
                Integer floatscore = eRrank.getFloatscore();
                ERrank rr = new ERrank();
                rr.setRanktype(ranktype);
                if ("zf".equals(subjectid)) {
                    //总分统计
                    if (N_Utils.isEmptyInteger(linescore)) linescore = (int) (ExamUtil.mul(pscore, 0.8));
                    double zfmaxscore = ExamUtil.add(linescore, floatscore);
                    double zfminscore = ExamUtil.sub(linescore, floatscore);
                    if (zfmaxscore > pscore) zfmaxscore = pscore;
                    if (zfminscore < 0) zfminscore = 0;
                    rr.setMaxscore(zfmaxscore);
                    rr.setMinscore(zfminscore);
                    rr.setLinescore(linescore);
                    rr.setFloatscore(floatscore);
                    String zfrankrange = getRankRange(zfmaxscore, zfminscore) + "]";
                    rr.setRankname(zfrankrange);
                    rr.setSubjectid("zf");
                    rrankList.add(rr);

                    setLjfTj(examid, fbstunum, userMap, rclassRankList, rr, zfrankrange, 0, subjectid, cstudents);
                    for (Map.Entry<Integer, List<ERstudent>> entry : zfcollect.entrySet()) {
                        Integer classid = entry.getKey();
                        List<ERstudent> list = entry.getValue();
                        setLjfTj(examid, fbstunum, userMap, rclassRankList, rr, zfrankrange, classid, subjectid, list);
                    }
                } else {
                    //分科统计
                    ERrank rrank = new ERrank();
                    rrank.setRanktype(ranktype);
                    rrank.setSubjectid(subjectid);
                    linescore = lscore;
                    if (N_Utils.isEmptyInteger(linescore)) linescore = (int) (ExamUtil.mul(pscore, 0.8));
                    double maxscore = ExamUtil.add(linescore, floatscore);
                    double minscore = ExamUtil.sub(linescore, floatscore);
                    if (maxscore > pscore) maxscore = pscore;
                    if (minscore < 0) minscore = 0;
                    rrank.setMaxscore(maxscore);
                    rrank.setMinscore(minscore);
                    rrank.setLinescore(linescore);
                    rrank.setFloatscore(floatscore);
                    String rankrange = getRankRange(maxscore, minscore) + "]";
                    rrank.setRankname(rankrange);
                    rrankList.add(rrank);

                    //全部班级统计
                    Integer classid = 0;
                    List<ERstudent> list = listStudentBySubjectId(subjectid, qbbjcollect);
                    setLjfTj(examid, fbstunum, userMap, rclassRankList, rrank, rankrange, classid, subjectid, list);

                    //班级科目统计
                    Map<Integer, List<ERstudent>> ccollect = students.stream().filter(s -> s.getSubjectid().equals(subjectid))
                            .collect(Collectors.groupingBy(s -> s.getClassid()));
                    for (Map.Entry<Integer, List<ERstudent>> entry : ccollect.entrySet()) {
                        classid = entry.getKey();
                        list = entry.getValue();
                        setLjfTj(examid, fbstunum, userMap, rclassRankList, rrank, rankrange, classid, subjectid, list);
                    }
                }

            } else if (ranktype == 4) {//临界名次（临界名次10，浮动名次5）
                Integer linescore = lscore;
                Integer floatscore = eRrank.getFloatscore();
                ERrank rr = new ERrank();
                rr.setRanktype(ranktype);
                if ("zf".equals(subjectid)) {
                    //总分统计
                    double zfmaxscore = ExamUtil.sub(linescore, floatscore);//最高名次
                    double zfminscore = ExamUtil.add(linescore, floatscore);//最低名次
                    if (zfmaxscore < 1) zfmaxscore = 1;//最高名次为1
                    int zfstunum = (int) students.stream().map(s -> s.getStudentid()).distinct().count();//学生数量
                    if (zfminscore > zfstunum) zfminscore = zfstunum;//最低名次=学生数量
                    rr.setMaxscore(zfmaxscore);
                    rr.setMinscore(zfminscore);
                    rr.setLinescore(linescore);
                    rr.setFloatscore(floatscore);
                    String zfrankrange = getRankRange(zfmaxscore, zfminscore) + "]";
                    rr.setRankname(zfrankrange);
                    rr.setSubjectid("zf");
                    rrankList.add(rr);

                    setLjmcTj(examid, fbstunum, userMap, rclassRankList, rr, zfrankrange, 0, subjectid, cstudents);
                    for (Map.Entry<Integer, List<ERstudent>> entry : zfcollect.entrySet()) {
                        Integer classid = entry.getKey();
                        List<ERstudent> list = entry.getValue();
                        setLjmcTj(examid, fbstunum, userMap, rclassRankList, rr, zfrankrange, classid, subjectid, list);
                    }
                } else {
                    //分科统计
                    double maxscore = ExamUtil.sub(linescore, floatscore);//最高名次
                    double minscore = ExamUtil.add(linescore, floatscore);//最低名次
                    if (maxscore < 1) maxscore = 1;//最高名次为1
                    Integer stunum = students.size();//学生数量
                    if (minscore > stunum) minscore = stunum;//最低名次=学生数量
                    ERrank rrank = new ERrank();
                    rrank.setRanktype(ranktype);
                    rrank.setSubjectid(subjectid);
                    rrank.setMaxscore(maxscore);
                    rrank.setMinscore(minscore);
                    rrank.setLinescore(linescore);
                    rrank.setFloatscore(floatscore);
                    String rankrange = getRankRange(maxscore, minscore) + "]";
                    rrank.setRankname(rankrange);
                    rrankList.add(rrank);

                    //全部班级统计
                    Integer classid = 0;
                    List<ERstudent> list = listStudentBySubjectId(subjectid, qbbjcollect);
                    setLjmcTj(examid, fbstunum, userMap, rclassRankList, rrank, rankrange, classid, subjectid, list);

                    //班级科目统计
                    Map<Integer, List<ERstudent>> ccollect = students.stream().filter(s -> s.getSubjectid().equals(subjectid))
                            .collect(Collectors.groupingBy(s -> s.getClassid()));
                    for (Map.Entry<Integer, List<ERstudent>> entry : ccollect.entrySet()) {
                        classid = entry.getKey();
                        list = entry.getValue();
                        setLjmcTj(examid, fbstunum, userMap, rclassRankList, rrank, rankrange, classid, subjectid, list);
                    }
                }

            } else if (ranktype == 5) {//优困生
                Integer linescore = lscore;
                Integer floatscore = eRrank.getFloatscore();
                ERrank rr = new ERrank();
                rr.setRanktype(ranktype);
                rr.setLinescore(linescore);
                rr.setFloatscore(floatscore);
                String rankrange = getRankRange(floatscore, linescore) + "]";
                String rankname = "优困生";
                rr.setRankname(rankname);
                if ("zf".equals(subjectid)) {
                    //总分统计
                    rr.setSubjectid("zf");
                    rrankList.add(rr);
                    rr.setMaxscore(getMaxScore(cstudents, floatscore));
                    setYksTj(examid, fbstunum, rclassRankList, rr, rankrange, 0, subjectid, cstudents);
                    for (Map.Entry<Integer, List<ERstudent>> entry : zfcollect.entrySet()) {
                        Integer classid = entry.getKey();
                        List<ERstudent> list = entry.getValue();
                        //rr.setMaxscore(getMaxScore(list, floatscore));
                        setYksTj(examid, fbstunum, rclassRankList, rr, rankrange, classid, subjectid, list);
                    }
                    rr.setMaxscore(null);
                } else {
                    //分科统计
                    ERrank rrank = new ERrank();
                    rrank.setRanktype(ranktype);
                    rrank.setRankname(rankname);
                    rrank.setLinescore(linescore);
                    rrank.setFloatscore(floatscore);
                    rrank.setSubjectid(subjectid);
                    rrankList.add(rrank);
                    //全部班级统计
                    Integer classid = 0;
                    List<ERstudent> list = listStudentBySubjectId(subjectid, qbbjcollect);
                    rrank.setMaxscore(getMaxScore(list, floatscore));
                    setYksTj(examid, fbstunum, rclassRankList, rrank, rankrange, classid, subjectid, list);

                    //班级科目统计
                    Map<Integer, List<ERstudent>> ccollect = students.stream().filter(s -> s.getSubjectid().equals(subjectid))
                            .collect(Collectors.groupingBy(s -> s.getClassid()));
                    for (Map.Entry<Integer, List<ERstudent>> entry : ccollect.entrySet()) {
                        classid = entry.getKey();
                        list = entry.getValue();
                        setYksTj(examid, fbstunum, rclassRankList, rrank, rankrange, classid, subjectid, list);
                    }
                    rrank.setMaxscore(null);
                }
            }
        }

        int timestamp = N_Utils.getSecondTimestamp();
        rrankList.forEach(r -> {
            r.setExamid(examid);
            r.setCreateid(createid);
            r.setCreatetime(timestamp);
        });
        if (N_Utils.isListNotEmpty(rrankList)) eRrankMapper.insertList(rrankList);
        saveClassRank(rclassRankList, ranktype);//保存考试报告班级等级分布
    }

    //等级分类范围
    private String getRankRange(double maxscore, double minscore) {
        return "[" + ExamUtil.doubleToStr(minscore) + "," + ExamUtil.doubleToStr(maxscore);
    }

    //获取科目学生
    private List<ERstudent> listStudentBySubjectId(String subjectid, Map<String, List<ERstudent>> qbbjcollect) {
        List<ERstudent> list = qbbjcollect.get(subjectid);
        if (list == null) list = new ArrayList<>();
        return list;
    }

    //获取最高分
    private Double getMaxScore(List<ERstudent> cstudents, Integer linescore) {
        List<Double> cScore = cstudents.stream().map(s -> s.getScore()).distinct().sorted().collect(Collectors.toList());
        int rnum = cScore.size();//排名数量
        if (linescore > rnum) linescore = rnum;
        Double maxscore = cScore.get(linescore - 1);
        return maxscore;
    }

    //考试报告--优困生统计
    private void setYksTj(Integer examid, Integer gstunum, List<ERclassRank> rclassRankList, ERrank rrank,
                          String rankrange, Integer classid, String subjectid, List<ERstudent> list) {
        ERclassRank cr = new ERclassRank();
        cr.setExamid(examid);
        cr.setClassid(classid);
        cr.setSubjectid(subjectid);
        cr.setRanktype(rrank.getRanktype());
        cr.setRankname(rrank.getRankname());

        Integer rank = rrank.getLinescore();//年级前rank名
        Double maxscore = rrank.getMaxscore();//年级后rank名最高分

        List<ERstudent> list2 = list.stream().filter(s -> s.getSchoolrank().compareTo(rank) != 1).collect(Collectors.toList());
        List<ERstudent> list3 = list.stream().filter(s -> s.getScore().compareTo(maxscore) != 1).collect(Collectors.toList());

        cr.setRankrange(rankrange);
        int stuqnum = list2.size();
        int stuhnum = list3.size();
        //int stunum = stuqnum + stuhnum;

        //cr.setStunum(stunum);
        //cr.setSturate(N_Utils.getIntegerDivideAndMulitiply(stunum, gstunum));
        List<Map> students = new ArrayList<>();
        Map q = new HashMap();
        q.put("stunum", stuqnum);
        //q.put("sturate", N_Utils.getIntegerDivideAndMulitiply(stuqnum, gstunum));
        students.add(q);
        Map h = new HashMap();
        h.put("stunum", stuhnum);
        //h.put("sturate", N_Utils.getIntegerDivideAndMulitiply(stuhnum, gstunum));
        students.add(h);
        String stujson = JSON.toJSONString(students);
        cr.setStujson(stujson);
        rclassRankList.add(cr);
    }

    //考试报告--临界名次统计
    private void setLjmcTj(Integer examid, Integer gstunum, Map<Integer, String> userMap,
                           List<ERclassRank> rclassRankList, ERrank rrank,
                           String rankrange, Integer classid, String subjectid, List<ERstudent> list) {
        ERclassRank cr = new ERclassRank();
        cr.setExamid(examid);
        cr.setClassid(classid);
        cr.setSubjectid(subjectid);
        cr.setRanktype(rrank.getRanktype());
        cr.setRankname(rrank.getRankname());
        List<ERstudent> list2;

        Integer finalMinscore = rrank.getMinscore().intValue();
        Integer finalMaxscore = rrank.getMaxscore().intValue();
        if (subjectid.equals("zf")) {//总分统计
            list2 = list.stream().filter(s -> s.getZfSchoolRank().compareTo(finalMinscore) != 1
                    && s.getZfSchoolRank().compareTo(finalMaxscore) != -1).collect(Collectors.toList());
        } else if (classid == 0) {//全部班级统计
            list2 = list.stream().filter(s -> s.getSchoolrank().compareTo(finalMinscore) != 1
                    && s.getSchoolrank().compareTo(finalMaxscore) != -1).collect(Collectors.toList());
        } else {//班级科目统计
            list2 = list.stream().filter(s -> s.getClassrank().compareTo(finalMinscore) != 1
                    && s.getClassrank().compareTo(finalMaxscore) != -1).collect(Collectors.toList());
        }

        cr.setRankrange(rankrange);
        int stunum = list2.size();
        cr.setStunum(stunum);
        //cr.setSturate(N_Utils.getIntegerDivideAndMulitiply(stunum, gstunum));
        setStudentName(list2, userMap);
        String stujson = stuJson(list2);
        cr.setStujson(stujson);
        rclassRankList.add(cr);
    }

    //考试报告--临界分统计
    private void setLjfTj(Integer examid, Integer gstunum, Map<Integer, String> userMap,
                          List<ERclassRank> rclassRankList, ERrank rrank,
                          String rankrange, Integer classid, String subjectid, List<ERstudent> list) {
        ERclassRank cr = new ERclassRank();
        cr.setExamid(examid);
        cr.setClassid(classid);
        cr.setSubjectid(subjectid);
        cr.setRanktype(rrank.getRanktype());
        cr.setRankname(rrank.getRankname());
        List<ERstudent> list2;

        double finalMinscore = rrank.getMinscore();
        double finalMaxscore = rrank.getMaxscore();
        list2 = list.stream().filter(s -> s.getScore().compareTo(finalMinscore) != -1
                && s.getScore().compareTo(finalMaxscore) != 1).collect(Collectors.toList());
        cr.setRankrange(rankrange);
        int stunum = list2.size();
        cr.setStunum(stunum);
        //cr.setSturate(N_Utils.getIntegerDivideAndMulitiply(stunum, gstunum));
        setStudentName(list2, userMap);
        String stujson = stuJson(list2);
        cr.setStujson(stujson);
        rclassRankList.add(cr);
    }

    //考试报告--分段统计
    private void setFdTj(Integer examid, Integer gstunum, Map<Integer, String> userMap,
                         List<ERclassRank> rclassRankList, Integer gnum,
                         Integer i, ERrank rrank, String rankrange, Integer classid, List<ERstudent> list) {
        ERclassRank gr = new ERclassRank();
        gr.setExamid(examid);
        gr.setClassid(classid);
        gr.setSubjectid(rrank.getSubjectid());
        gr.setRanktype(rrank.getRanktype());
        gr.setRankname(rrank.getRankname());
        List<ERstudent> list2;

        double finalMinscore = rrank.getMinscore();
        double finalMaxscore = rrank.getMaxscore();
        if (i == gnum) {
            list2 = list.stream().filter(s -> s.getScore().compareTo(finalMinscore) != -1).collect(Collectors.toList());
        } else {
            list2 = list.stream().filter(s -> s.getScore().compareTo(finalMinscore) != -1
                    && s.getScore().compareTo(finalMaxscore) == -1).collect(Collectors.toList());
        }
        gr.setRankrange(rankrange);
        int stunum = list2.size();
        gr.setStunum(stunum);
        gr.setSturate(N_Utils.getIntegerDivideAndMulitiply(stunum, gstunum));
        setStudentName(list2, userMap);
        String stujson = stuJson(list2);
        gr.setStujson(stujson);
        rclassRankList.add(gr);
    }

    //考试报告--等级统计
    private void setDjTj(Integer examid, Integer gstunum, Map<Integer, String> userMap,
                         List<ERclassRank> rclassRankList, ERrank rrank,
                         String rankrange, String subjectid, Integer classid, List<ERstudent> list) {
        String rankname = rrank.getRankname();
        ERclassRank cr = new ERclassRank();
        cr.setExamid(examid);
        cr.setClassid(classid);
        cr.setSubjectid(subjectid);
        cr.setRanktype(rrank.getRanktype());
        cr.setRankname(rankname);
        List<ERstudent> list2;
        double finalMinscore = rrank.getMinscore();
        double finalMaxscore = rrank.getMaxscore();
        if (rankname.equals("A")) {
            list2 = list.stream().filter(s -> s.getScore().compareTo(finalMinscore) != -1).collect(Collectors.toList());
        } else {
            list2 = list.stream().filter(s -> s.getScore().compareTo(finalMinscore) != -1
                    && s.getScore().compareTo(finalMaxscore) == -1).collect(Collectors.toList());
        }
        cr.setRankrange(rankrange);
        int stunum = list2.size();
        cr.setStunum(stunum);
        cr.setSturate(N_Utils.getIntegerDivideAndMulitiply(stunum, gstunum));
        setStudentName(list2, userMap);
        String stujson = stuJson(list2);
        cr.setStujson(stujson);
        rclassRankList.add(cr);
    }

    //学生名单
    private String stuJson(List<ERstudent> list2) {
        List<Map> students = new ArrayList<>();
        for (ERstudent rstudent : list2) {
            Map s = new HashMap();
            s.put("studentname", rstudent.getStudentname());
            s.put("schoolrank", rstudent.getSchoolrank());
            s.put("score", rstudent.getScore());
            students.add(s);
        }
        return JSON.toJSONString(students);
    }

    //学生姓名处理
    private void setStudentName(List<ERstudent> list, Map<Integer, String> userMap) {
        list.forEach(s -> s.setStudentname(userMap.get(s.getStudentid())));
    }

    //计算学生分值
    private void setStuScore(Map<String, List<ERstudent>> gcollect, List<ERstudent> cstudents) {
        for (Map.Entry<String, List<ERstudent>> entry : gcollect.entrySet()) {
            List<ERstudent> list = entry.getValue();
            ERstudent rstudent = list.get(0);
            ERstudent rs = new ERstudent();
            rs.setClassid(rstudent.getClassid());
            rs.setSubjectid(rstudent.getSubjectid());
            rs.setStudentid(rstudent.getStudentid());
            rs.setClassrank(rstudent.getClassrank());
            rs.setSchoolrank(rstudent.getSchoolrank());
            rs.setZfSchoolRank(rstudent.getZfSchoolRank());
            rs.setScore(list.stream().mapToDouble(s -> s.getScore()).sum());
            cstudents.add(rs);
        }
    }

    //设置学生目标
    private void setStuGoal(List<ERstudent> stuRankGoals, ERstudent cs, Integer schoolrank) {
        String goalparam = "0.2";
        ERstudent rg = stuRankGoals.stream().filter(s -> s.getStudentid().equals(cs.getStudentid())
                && s.getSubjectid().equals(cs.getSubjectid())).findFirst().orElse(null);
        Integer goal = cs.getSchoolrank();
        Integer nextgoal = ExamUtil.getUserGroupGoalByParam(schoolrank, goalparam);
        Integer classrankpre = 0;
        if (rg != null) {
            goal = rg.getNextgoal();
            classrankpre = cs.getClassrank() - rg.getClassrank();
        }
        cs.setClassrankpre(classrankpre);
        cs.setGoal(goal);
        cs.setNextgoal(nextgoal);
    }

    //分数排名
    private void setRank(List<ERstudent> students, Map<String, Integer> rank, Integer code) {
        List<Map.Entry<Double, List<ERstudent>>> gslist2 = students.stream()
                                                                   .collect(Collectors.groupingBy(ERstudent::getScore)).entrySet()
                                                                   .stream().sorted((s1, s2) -> -Double.compare(s1.getKey(), s2.getKey())).collect(Collectors.toList());
        Integer index = 1;
        String key;
        for (Map.Entry<Double, List<ERstudent>> entry : gslist2) {
            for (ERstudent cgs : entry.getValue()) {
                Integer studentid = cgs.getStudentid();
                Integer classid = cgs.getClassid();
                String subjectid = cgs.getSubjectid();
                if (code == 1) {//学校学生
                    key = studentid.toString();
                } else if (code == 2) {//学校科目学生
                    key = subjectid + "_" + studentid;
                } else if (code == 3) {//班级学生
                    key = classid + "_" + studentid;
                } else {//班级科目学生
                    key = classid + "_" + subjectid + "_" + studentid;
                }
                rank.put(key, index);
            }
            index = index + entry.getValue().size();
        }
    }

    @Transactional(rollbackFor = Exception.class)
    public void saveClassQuestions(Integer examid) {
        List<Map> classes = eClassMapper.listByExamId(examid);
        Integer exammode = eReportGenerateMapper.getExamModeById(examid);
        List<Map> subjects = eReportGenerateMapper.listSubject(examid, exammode);
        setClassQuestion(examid, subjects, classes);

    }

    //题型、试题、知识点
    private void setClassQuestion(Integer examid, List<Map> subjects, List<Map> classes) {
        //考试所有学生提交试卷作答情况
        List<EPaperStudentQuestion> stulist = ePaperStudentQuestionMapper.listExamStudentsAnswer(examid);
        if(N_Utils.isListNotEmpty(stulist)){
            List<ERclassQtype> rtypelist = new ArrayList<>();//班级题型
            List<ERStudentQtype> stutypelist = new ArrayList<>();//学生题型
            List<ERclassQuestion> rqueslist = new ArrayList<>();//班级试题
            List<ERclassPoint> rpointlist = new ArrayList<>();//班级知识点
            List<ERstudentPoint> stupointlist = new ArrayList<>();//学生知识点
            List<ERclassComplexity> complist = new ArrayList<>();//班级难易度
            List<ERStudentComplexity> stucomplist = new ArrayList<>();//学生难易度

            for (Map map : subjects) {
                String subjectid = map.get("subjectid").toString();
                Integer epid = Integer.parseInt(map.get("epid").toString());//获取试卷id
                Integer ptype = Integer.parseInt(map.get("ptype").toString());//试卷类型1题库2附件
                ExamPaperClassVo examPaperClassVo = new ExamPaperClassVo();
                examPaperClassVo.setExamid(examid);
                examPaperClassVo.setEpid(epid);
                examPaperClassVo.setSubjectid(subjectid);
                examPaperClassVo.setClasses(classes);

                //获取试卷本身的分析
                Map panalyze = ePaperAnalyzeMapper.getPaperAnalzyeByEpid(epid);
                //获取指定试卷学生作答情况
                List<EPaperStudentQuestion> paperstulist = stulist.stream().filter(s -> s.getEpid().equals(epid)).collect(Collectors.toList());
                if(N_Utils.isListNotEmpty(paperstulist)){
                    if (ptype == 1) {
                        //处理题型下试题：题库显示题号时为母题的题号即order（qn是英语为顺延题号其他学科为母题号和子题排序拼接）
                        String qtypejson = panalyze.get("qnumjson").toString();//原试卷题型分析
                        List<Map> qtypelist = JSON.parseArray(qtypejson, Map.class);
                        setPaperQuestionTkQtypes(qtypelist, paperstulist, rtypelist, rqueslist, stutypelist, examPaperClassVo);

                        //处理知识点
                        setEPaperQuestionPoints(panalyze, paperstulist, rpointlist, stupointlist, examPaperClassVo);

                        //处理难易度
                        String complexityjson = panalyze.get("complexityjson").toString();
                        List<Map> complexitylist = JSON.parseArray(complexityjson, Map.class);
                        setEPaperQuestionComplexitys(complexitylist, paperstulist, complist, stucomplist, examPaperClassVo);

                    } else {
                        //处理题型及题型下试题：附件显示题号为qn（order）作为排序使用
                        String qtypejson = panalyze.get("qnumjson").toString();//原试卷题型分析
                        List<Map> qtypelist = JSON.parseArray(qtypejson, Map.class);
                        setPaperQuestionFjQtypes(qtypelist, paperstulist, rtypelist, rqueslist, stutypelist, examPaperClassVo);
                    }
                }
            }

            eRclassQtypeMapper.insertList(rtypelist);
            eRstudentQtypeMapper.insertList(stutypelist);
            eRclassQuestionMapper.insertList(rqueslist);
            if (N_Utils.isListNotEmpty(complist)) eRclassComplexityMapper.insertList(complist);
            if (N_Utils.isListNotEmpty(stucomplist)) erStudentComplexityMapper.insertList(stucomplist);
            if (N_Utils.isListNotEmpty(rpointlist)) eRclassPointMapper.insertList(rpointlist);
            if (N_Utils.isListNotEmpty(stupointlist)) eRstudentPointMapper.insertList(stupointlist);
        }
    }

    //题型、试题、知识点、难易度--处理学生选项情况和得分情况
    private Map setPaperQuestionsForStuAnswer(List<EPaperStudentQuestion> classStu) {
        EPaperStudentQuestion q = classStu.get(0);//取第一条数据

        Map<String, List<Map>> answermap = null;
        List<Map> goodlist = new ArrayList<>();
        List<Map> badlist = new ArrayList<>();

        Double score8 = 0.0;
        Double score5 = 0.0;
        String key1 = "";
        String key2 = "";
        String key3 = "";

        for (int i = 0; i < classStu.size(); i++) {
            EPaperStudentQuestion sq = classStu.get(i);
            String stuanswer = sq.getStuanswer();
            if (q.getCtype() == 1 || q.getCtype() == 2 || q.getCtype() == 4 || q.getCtype() == 5 || q.getCtype() == 6) {
                String answeroption = "未作答";
                if (N_Utils.isNotEmpty(stuanswer)) {
                    List<String> stuanswers = JSON.parseArray(stuanswer, String.class);
                    if (N_Utils.isListNotEmpty(stuanswers)) {
                        String stuansopt = stuanswers.get(0);
                        if(N_Utils.isNotEmpty(stuansopt)){
                            answeroption = stuansopt;
                        }
                    }
                }

                if(i == 0){
                    answermap = new TreeMap<>();
                }

                Map stumap = new HashMap();
                stumap.put("studentid", sq.getStudentid());
                stumap.put("stuname", sq.getStuname());
                if (answermap.containsKey(answeroption)) {
                    List<Map> stulist = answermap.get(answeroption);
                    stulist.add(stumap);
                } else {
                    List<Map> stulist = new ArrayList<>();
                    stulist.add(stumap);
                    answermap.put(answeroption, stulist);
                }
            } else {
                //主观题
                if (i == 0) {
                    answermap = new LinkedHashMap<>();
                    //处理分数分段对应,用于分数段[0，50%）   [50%，80%）,  [80%，100%]
                    score8 = ExamUtil.getScoreRateScore(q.getQscore(), 0.8);
                    score5 = ExamUtil.getScoreRateScore(q.getQscore(), 0.5);
                    String str10 = N_Utils.formatDouble(q.getQscore());
                    String str8 = N_Utils.formatDouble(score8);
                    String str5 = N_Utils.formatDouble(score5);
                    key1 = str8 + "-" + str10;
                    key2 = str5 + "-" + str8;
                    key3 = 0 + "-" + str5;
                    answermap.put(key1, new ArrayList<>());
                    answermap.put(key2, new ArrayList<>());
                    answermap.put(key3, new ArrayList<>());
                }

                List<Map> stulist = null;
                if (sq.getStuscore() >= score8) {
                    stulist = answermap.get(key1);
                } else if (sq.getStuscore() >= score5 && sq.getStuscore() < score8) {
                    stulist = answermap.get(key2);
                } else {
                    stulist = answermap.get(key3);
                }

                Map stumap = new HashMap();
                stumap.put("studentid", sq.getStudentid());
                stumap.put("stuname", sq.getStuname());
                stulist.add(stumap);
            }

            if (!N_Utils.isEmptyInteger(sq.getGood()) && sq.getGood() == 1) {
                Map goodmap = new HashMap();
                goodmap.put("studentid", sq.getStudentid());
                goodmap.put("stuname", sq.getStuname());
                goodlist.add(goodmap);
            }
            if (!N_Utils.isEmptyInteger(sq.getBad()) && sq.getBad() == 1) {
                Map badmap = new HashMap();
                badmap.put("studentid", sq.getStudentid());
                badmap.put("stuname", sq.getStuname());
                badlist.add(badmap);
            }
        }

        String erroroption = "";//高频错误项
        if (q.getCtype() == 1 || q.getCtype() == 2 || q.getCtype() == 4 || q.getCtype() == 5 || q.getCtype() == 6) {
            String answer = q.getAnswer();//试题正确答案
            List<String> answerlist = JSON.parseArray(answer, String.class);
            int num = 0;
            for (Map.Entry<String, List<Map>> entry : answermap.entrySet()) {
                if (!entry.getKey().equalsIgnoreCase(answerlist.get(0))) {
                    //当前选项不是正确答案时,数量大的为高频错误选项
                    if (num < entry.getValue().size()) {
                        num = entry.getValue().size();
                        erroroption = entry.getKey();
                    }
                }
            }
        }

        Map rtnmap = new HashMap();
        rtnmap.put("answerlist", JSON.toJSONString(answermap));
        rtnmap.put("goodlist", JSON.toJSONString(goodlist));
        rtnmap.put("badlist", JSON.toJSONString(badlist));
        rtnmap.put("erroroption",erroroption);
        return rtnmap;
    }

    //题型、试题、知识点、难易度--附件题型
    private void setPaperQuestionFjQtypes(List<Map> qtypelist, List<EPaperStudentQuestion> paperstulist, List<ERclassQtype> rtypelist, List<ERclassQuestion> rqueslist,
                                          List<ERStudentQtype> stutypelist, ExamPaperClassVo examPaperClassVo) {
        List<Map> classes = examPaperClassVo.getClasses();
        for (int k = 0; k < qtypelist.size(); k++) {
            Map qtypemap = qtypelist.get(k);
            String qtypename = qtypemap.get("qtname").toString();
            String qtypeid = qtypemap.get("qtid").toString();
            Double score = Double.parseDouble(qtypemap.get("score").toString());//题型下试题总分值
            Double srate = Double.parseDouble(qtypemap.get("srate").toString());//题型下试题分值占比
            Integer num = Integer.parseInt(qtypemap.get("num").toString());//题型下试题数量
            Map ques = (Map) qtypemap.get("ques");//试题相关对象
            List<Integer> eptqids = (List<Integer>) ques.get("eptqids");//试卷中题型下试题id
            List<String> qns = (List<String>) ques.get("qns");//试卷中试题题号
            List<Integer> orders = (List<Integer>) ques.get("orders");//试卷中试题题号
            List<String> qtypenames = (List<String>) ques.get("qtypenames");
            List<Object> scoresObj = (List<Object>) ques.get("scores");
            List<Double> scores  = scoresObj.stream().map((d) -> {
                return Double.valueOf(d + "");
            }).collect(Collectors.toList());

            Double tgstuscore = 0.0;//题型下学生得分
            Double tgscore = 0.0;//题型下试题总分
            int gstunum = 0;//题型下学生数量
            Map<Integer, ERClassScoreVo> tclassmap = new HashMap<>();
            Map<Integer, ERStudentQtype> tstumap = new HashMap<>();

            for (int q = 0; q < eptqids.size(); q++) {
                Integer eptqid = eptqids.get(q);
                //获取改题所有学生作答情况
                List<EPaperStudentQuestion> qgstulist = paperstulist.stream().filter(s -> s.getEptqid().equals(eptqid)).collect(Collectors.toList());
                gstunum = qgstulist.size();
                EPaperStudentQuestion qgmaxstu = qgstulist.stream().max(Comparator.comparing(EPaperStudentQuestion::getStuscore)).get();
                Double qgscore = qgstulist.stream().mapToDouble(EPaperStudentQuestion::getQscore).sum();
                Double qgstuscore = qgstulist.stream().mapToDouble(EPaperStudentQuestion::getStuscore).sum();
                Double qgavgscore = N_Utils.getDoubleDivideForAvg(qgstuscore, gstunum);//年级平均分
                Double qgsrate = N_Utils.getDoubleDivideAndMulitiply(qgstuscore, qgscore);
                tgscore = ExamUtil.add(tgscore, qgscore);
                tgstuscore = ExamUtil.add(tgstuscore, qgstuscore);

                //处理试题班级学生作答
                for (Map classm : classes) {
                    Integer classid = Integer.parseInt(classm.get("classid").toString());
                    List<EPaperStudentQuestion> qcstulist = qgstulist.stream().filter(s -> s.getClassid().equals(classid)).collect(Collectors.toList());
                    if(N_Utils.isListNotEmpty(qcstulist)){
                        int cstunum = qcstulist.size();//班级下试题作答学生数量
                        EPaperStudentQuestion qcmaxstu = qcstulist.stream().max(Comparator.comparing(EPaperStudentQuestion::getStuscore)).get();
                        Double qcscore = qcstulist.stream().mapToDouble(EPaperStudentQuestion::getQscore).sum();
                        Double qcstuscore = qcstulist.stream().mapToDouble(EPaperStudentQuestion::getStuscore).sum();
                        Double qcavgscore = N_Utils.getDoubleDivideForAvg(qcstuscore, cstunum);
                        Double qcsrate = N_Utils.getDoubleDivideAndMulitiply(qcstuscore, qcscore);

                        //班级单题情况
                        ERclassQuestion ercq = new ERclassQuestion();
                        ercq.setExamid(examPaperClassVo.getExamid());
                        ercq.setClassid(classid);
                        ercq.setSubjectid(examPaperClassVo.getSubjectid());
                        ercq.setEpid(examPaperClassVo.getEpid());
                        ercq.setEptqid(eptqid);
                        ercq.setQn(qns.get(q));
                        ercq.setQorder(orders.get(q));
                        ercq.setScore(scores.get(q));
                        ercq.setQtypename(qtypenames.get(q));
                        ercq.setClassscore(qcstuscore);
                        ercq.setClassmaxscore(qcmaxstu.getStuscore());
                        ercq.setClassavgscore(qcavgscore);
                        ercq.setClasssrate(qcsrate);
                        ercq.setClassratetype(ExamUtil.getScoreRateType(qcsrate));
                        ercq.setGradescore(qgstuscore);
                        ercq.setGrademaxscore(qgmaxstu.getStuscore());
                        ercq.setGradeavgscore(qgavgscore);
                        ercq.setGradesrate(qgsrate);
                        //处理单选题选项情况
                        Map stuansmap = setPaperQuestionsForStuAnswer(qcstulist);
                        ercq.setAnswerjson(stuansmap.get("answerlist").toString());
                        if(N_Utils.isNotEmpty(stuansmap.get("goodlist"))){
                            ercq.setGoodstujson(stuansmap.get("goodlist").toString());
                        }
                        if(N_Utils.isNotEmpty(stuansmap.get("badlist"))){
                            ercq.setBadstujson(stuansmap.get("badlist").toString());
                        }

                        ercq.setErroroption(stuansmap.get("erroroption").toString());
                        rqueslist.add(ercq);//单个试题统计

                        if (tclassmap.containsKey(classid)) {
                            ERClassScoreVo erClassScoreVo = tclassmap.get(classid);
                            erClassScoreVo.setStuscore(ExamUtil.add(erClassScoreVo.getStuscore(), qcstuscore));
                            erClassScoreVo.setCscore(ExamUtil.add(erClassScoreVo.getCscore(), qcscore));
                        } else {
                            ERClassScoreVo erClassScoreVo = new ERClassScoreVo();
                            erClassScoreVo.setStunum(cstunum);
                            erClassScoreVo.setStuscore(qcstuscore);
                            erClassScoreVo.setCscore(qcscore);
                            tclassmap.put(classid, erClassScoreVo);
                        }

                        for (EPaperStudentQuestion psq : qcstulist) {
                            if (tstumap.containsKey(psq.getStudentid())) {
                                ERStudentQtype sq = tstumap.get(psq.getStudentid());
                                sq.setStuscore(ExamUtil.add(sq.getStuscore(), psq.getStuscore()));
                            } else {
                                ERStudentQtype sq = new ERStudentQtype();
                                sq.setClassid(psq.getClassid());
                                sq.setStudentid(psq.getStudentid());
                                sq.setStuscore(psq.getStuscore());
                                tstumap.put(psq.getStudentid(), sq);
                            }
                        }
                    }
                }
            }

            Double tgavgscore = N_Utils.getDoubleDivideForAvg(tgstuscore, gstunum);//题型下年级平均分
            Double tgsrate = N_Utils.getDoubleDivideAndMulitiply(tgstuscore, tgscore);//年级得分率

            //题型--班级得分
            for (Map.Entry<Integer, ERClassScoreVo> entry : tclassmap.entrySet()) {
                ERClassScoreVo erClassScoreVo = entry.getValue();
                ERclassQtype eRclassQtype = new ERclassQtype();
                eRclassQtype.setExamid(examPaperClassVo.getExamid());
                eRclassQtype.setSubjectid(examPaperClassVo.getSubjectid());
                eRclassQtype.setEpid(examPaperClassVo.getEpid());
                eRclassQtype.setClassid(entry.getKey());
                eRclassQtype.setQtypename(qtypename);
                eRclassQtype.setQtypeid(qtypeid);
                eRclassQtype.setScore(score);
                eRclassQtype.setNum(num);
                eRclassQtype.setSrate(srate);
                eRclassQtype.setGradescore(tgstuscore);
                eRclassQtype.setGradeavgscore(tgavgscore);
                eRclassQtype.setGradesrate(tgsrate);
                eRclassQtype.setClassscore(erClassScoreVo.getStuscore());
                eRclassQtype.setClassavgscore(N_Utils.getDoubleDivideForAvg(erClassScoreVo.getStuscore(), erClassScoreVo.getStunum()));
                eRclassQtype.setClasssrate(N_Utils.getDoubleDivideAndMulitiply(erClassScoreVo.getStuscore(), erClassScoreVo.getCscore()));
                eRclassQtype.setQns(qns.stream().map(String::valueOf).collect(Collectors.joining(",")));
                rtypelist.add(eRclassQtype);
            }

            //题型--学生得分
            for (Map.Entry<Integer, ERStudentQtype> entry : tstumap.entrySet()) {
                ERStudentQtype erStudentQtype = entry.getValue();
                erStudentQtype.setExamid(examPaperClassVo.getExamid());
                erStudentQtype.setSubjectid(examPaperClassVo.getSubjectid());
                erStudentQtype.setEpid(examPaperClassVo.getEpid());
                erStudentQtype.setQtypename(qtypename);
                erStudentQtype.setQtypeid(qtypeid);
                erStudentQtype.setStusrate(N_Utils.getDoubleDivideAndMulitiply(erStudentQtype.getStuscore(), score));
                stutypelist.add(erStudentQtype);
            }
        }
    }

    //题型、试题、知识点、难易度--题库题型
    private void setPaperQuestionTkQtypes(List<Map> qtypelist, List<EPaperStudentQuestion> paperstulist, List<ERclassQtype> rtypelist, List<ERclassQuestion> rqueslist,
                                          List<ERStudentQtype> stutypelist, ExamPaperClassVo examPaperClassVo) {
        List<Map> classes = examPaperClassVo.getClasses();
        for (int k = 0; k < qtypelist.size(); k++) {
            Map qtypemap = qtypelist.get(k);
            String qtypename = qtypemap.get("qtname").toString();
            String qtypeid = qtypemap.get("qtid").toString();
            Double score = Double.parseDouble(qtypemap.get("score").toString());//题型下试题总分值
            Double srate = Double.parseDouble(qtypemap.get("srate").toString());//题型下试题分值占比
            Integer num = Integer.parseInt(qtypemap.get("num").toString());//题型下试题数量
            List<Map> queslist = (List<Map>) qtypemap.get("ques");//试题相关对象（数量为几个代表几个母题）
            String qns = "";

            Double tgstuscore = 0.0;//题型下学生得分
            Double tgscore = 0.0;//题型下试题总分
            int gstunum = 0;//题型下学生数量

            Map<Integer, ERClassScoreVo> tclassmap = new HashMap<>();
            Map<Integer, ERStudentQtype> tstumap = new HashMap<>();

            for (Map quesmap : queslist) {
                List<Integer> eptqids = (List<Integer>) quesmap.get("eptqids");
                Integer qlevel = Integer.parseInt(quesmap.get("qlevel").toString());
                String order = quesmap.get("order").toString();//试题母题题号
                String questionid = quesmap.get("questionid").toString();
                List<String> qnslist = (List<String>) quesmap.get("qns");
                String quesname = quesmap.get("name").toString();
                Integer complexity = Integer.parseInt(quesmap.get("complexity").toString());
                Double quesscore = Double.parseDouble(quesmap.get("score").toString());
                qns = qns + order + ",";

                //获取集合中对应子题集合的数据
                List<EPaperStudentQuestion> qgstulist = null;
                Integer eptqid = null;
                if (qlevel == 1) {
                    //单题时直接为试题id
                    eptqid = eptqids.get(0);
                    Integer teptqid = eptqid;
                    qgstulist = paperstulist.stream().filter(s -> teptqid.equals(s.getEptqid())).collect(Collectors.toList());
                } else {
                    qgstulist = new ArrayList<>();
                    List<EPaperStudentQuestion> stuqlist = paperstulist.stream().filter(s -> eptqids.contains(s.getEptqid())).collect(Collectors.toList());
                    //母子题情况，计算所有子题的和即为母题。把试题按照学生分组，分组为一组的即为
                    Map<Integer, List<EPaperStudentQuestion>> stuQuesMap = stuqlist.stream().collect(Collectors.groupingBy(EPaperStudentQuestion::getStudentid));
                    for (Map.Entry<Integer, List<EPaperStudentQuestion>> entry : stuQuesMap.entrySet()) {
                        List<EPaperStudentQuestion> stuqueslist = entry.getValue();
                        EPaperStudentQuestion pfist = stuqueslist.get(0);
                        EPaperStudentQuestion pstq = new EPaperStudentQuestion();
                        pstq.setClassid(pfist.getClassid());
                        pstq.setStudentid(entry.getKey());

                        Double qstuscore = stuqueslist.stream().mapToDouble(EPaperStudentQuestion::getStuscore).sum();
                        Double qscore = stuqueslist.stream().mapToDouble(EPaperStudentQuestion::getQscore).sum();
                        pstq.setQscore(qscore);
                        pstq.setStuscore(qstuscore);
                        pstq.setCtype(11);//母子题关系的均设置为复合题，不再进行选项区分
                        int bad = 0;
                        int good = 0;
                        for (EPaperStudentQuestion sq : stuqueslist) {
                            if (sq.getBad() == 1) {
                                bad++;
                            }
                            if (sq.getGood() == 1) {
                                good++;
                            }
                        }
                        if (bad > 0) {
                            pstq.setBad(1);
                        }
                        if (good > 0) {
                            pstq.setGood(1);
                        }
                        qgstulist.add(pstq);
                    }
                }

                gstunum = qgstulist.size();
                Double qgscore = qgstulist.stream().mapToDouble(EPaperStudentQuestion::getQscore).sum();
                Double qgstuscore = qgstulist.stream().mapToDouble(EPaperStudentQuestion::getStuscore).sum();
                EPaperStudentQuestion qgmaxscore = qgstulist.stream().max(Comparator.comparing(EPaperStudentQuestion::getStuscore)).get();
                tgscore = ExamUtil.add(tgscore, qgscore);
                tgstuscore = ExamUtil.add(tgstuscore, qgstuscore);

                for (Map classm : classes) {
                    Integer classid = Integer.parseInt(classm.get("classid").toString());
                    List<EPaperStudentQuestion> qcstulist = qgstulist.stream().filter(s -> s.getClassid().equals(classid)).collect(Collectors.toList());
                    if(N_Utils.isListNotEmpty(qcstulist)){
                        int cstunum = qcstulist.size();//班级下试题作答学生数量
                        Double qcscore = qcstulist.stream().mapToDouble(EPaperStudentQuestion::getQscore).sum();
                        Double qcstuscore = qcstulist.stream().mapToDouble(EPaperStudentQuestion::getStuscore).sum();
                        Double qcavgscore = N_Utils.getDoubleDivideForAvg(qcstuscore,cstunum);
                        EPaperStudentQuestion maxscore = qcstulist.stream().max(Comparator.comparing(EPaperStudentQuestion::getStuscore)).get();

                        if (tclassmap.containsKey(classid)) {
                            ERClassScoreVo erClassScoreVo = tclassmap.get(classid);
                            erClassScoreVo.setStuscore(ExamUtil.add(erClassScoreVo.getStuscore(), qcstuscore));
                            erClassScoreVo.setCscore(ExamUtil.add(erClassScoreVo.getCscore(), qcscore));
                        } else {
                            ERClassScoreVo erClassScoreVo = new ERClassScoreVo();
                            erClassScoreVo.setStunum(cstunum);
                            erClassScoreVo.setStuscore(qcstuscore);
                            erClassScoreVo.setCscore(qcscore);
                            tclassmap.put(classid, erClassScoreVo);
                        }
                        for (EPaperStudentQuestion psq : qcstulist) {
                            if (tstumap.containsKey(psq.getStudentid())) {
                                ERStudentQtype sq = tstumap.get(psq.getStudentid());
                                sq.setStuscore(ExamUtil.add(sq.getStuscore(), psq.getStuscore()));
                            } else {
                                ERStudentQtype sq = new ERStudentQtype();
                                sq.setClassid(psq.getClassid());
                                sq.setStudentid(psq.getStudentid());
                                sq.setStuscore(psq.getStuscore());
                                tstumap.put(psq.getStudentid(), sq);
                            }
                        }

                        //班级单题情况
                        ERclassQuestion ercq = new ERclassQuestion();
                        ercq.setExamid(examPaperClassVo.getExamid());
                        ercq.setClassid(classid);
                        ercq.setSubjectid(examPaperClassVo.getSubjectid());
                        ercq.setEpid(examPaperClassVo.getEpid());
                        ercq.setEptqid(eptqid);
                        ercq.setQuestionid(questionid);
                        ercq.setQtypename(quesname);
                        ercq.setComplexity(complexity);
                        ercq.setScore(quesscore);
                        ercq.setQn(String.join(",", qnslist));
                        ercq.setQorder(Integer.parseInt(order));
                        ercq.setClassscore(qcstuscore);
                        ercq.setClassmaxscore(maxscore.getStuscore());
                        ercq.setClassavgscore(qcavgscore);
                        Double qcsrate = N_Utils.getDoubleDivideAndMulitiply(qcstuscore,qcscore);
                        ercq.setClasssrate(qcsrate);
                        ercq.setClassratetype(ExamUtil.getScoreRateType(qcsrate));
                        ercq.setGrademaxscore(qgmaxscore.getStuscore());
                        ercq.setGradescore(qgstuscore);
                        ercq.setGradeavgscore(N_Utils.getDoubleDivideForAvg(qgstuscore,gstunum));
                        ercq.setGradesrate(N_Utils.getDoubleDivideAndMulitiply(qgstuscore,qgscore));
                        //处理单选题选项情况
                        Map stuansmap = setPaperQuestionsForStuAnswer(qcstulist);
                        ercq.setAnswerjson(stuansmap.get("answerlist").toString());
                        if(N_Utils.isNotEmpty(stuansmap.get("goodlist"))){
                            ercq.setGoodstujson(stuansmap.get("goodlist").toString());
                        }
                        if(N_Utils.isNotEmpty(stuansmap.get("badlist"))){
                            ercq.setBadstujson(stuansmap.get("badlist").toString());
                        }
                        ercq.setErroroption(stuansmap.get("erroroption").toString());
                        rqueslist.add(ercq);//单个试题统计
                    }
                }
            }

            Double tgavgscore = N_Utils.getDoubleDivideForAvg(tgstuscore, gstunum);//题型下年级平均分
            Double tgsrate = N_Utils.getDoubleDivideAndMulitiply(tgstuscore, tgscore);//年级得分率

            //题型--班级得分
            for (Map.Entry<Integer, ERClassScoreVo> entry : tclassmap.entrySet()) {
                ERClassScoreVo erClassScoreVo = entry.getValue();
                ERclassQtype eRclassQtype = new ERclassQtype();
                eRclassQtype.setExamid(examPaperClassVo.getExamid());
                eRclassQtype.setSubjectid(examPaperClassVo.getSubjectid());
                eRclassQtype.setEpid(examPaperClassVo.getEpid());
                eRclassQtype.setClassid(entry.getKey());
                eRclassQtype.setQtypename(qtypename);
                eRclassQtype.setQtypeid(qtypeid);
                eRclassQtype.setScore(score);
                eRclassQtype.setNum(num);
                eRclassQtype.setSrate(srate);
                eRclassQtype.setGradescore(tgstuscore);
                eRclassQtype.setGradeavgscore(tgavgscore);
                eRclassQtype.setGradesrate(tgsrate);
                eRclassQtype.setClassscore(erClassScoreVo.getStuscore());
                eRclassQtype.setClassavgscore(N_Utils.getDoubleDivideForAvg(erClassScoreVo.getStuscore(), erClassScoreVo.getStunum()));
                eRclassQtype.setClasssrate(N_Utils.getDoubleDivideAndMulitiply(erClassScoreVo.getStuscore(), erClassScoreVo.getCscore()));
                eRclassQtype.setQns(qns.substring(0, qns.lastIndexOf(",")));
                rtypelist.add(eRclassQtype);
            }

            //题型--学生得分
            for (Map.Entry<Integer, ERStudentQtype> entry : tstumap.entrySet()) {
                ERStudentQtype erStudentQtype = entry.getValue();
                erStudentQtype.setExamid(examPaperClassVo.getExamid());
                erStudentQtype.setSubjectid(examPaperClassVo.getSubjectid());
                erStudentQtype.setEpid(examPaperClassVo.getEpid());
                erStudentQtype.setQtypename(qtypename);
                erStudentQtype.setQtypeid(qtypeid);
                erStudentQtype.setStusrate(N_Utils.getDoubleDivideAndMulitiply(erStudentQtype.getStuscore(), score));
                stutypelist.add(erStudentQtype);
            }
        }
    }

    //题型、试题、知识点、难易度--知识点
    private void setEPaperQuestionPoints(Map panalyze, List<EPaperStudentQuestion> paperstulist, List<ERclassPoint> cpointlist, List<ERstudentPoint> stupointlist,
                                         ExamPaperClassVo examPaperClassVo) {
        //原试卷知识点分析
        String pointjson = panalyze.get("pointjson").toString();
        List<Map> pointlist = JSON.parseArray(pointjson, Map.class);

        //试题对应知识点关系
        String quespointjson = panalyze.get("quespointjson").toString();
        List<QuestionPointVo> quepointlist = JSON.parseArray(quespointjson, QuestionPointVo.class);

        List<ERPointStuScoreVo> gradestulist = new ArrayList<>();//每个知识点每个学生的得分
        for (int i = 0; i < quepointlist.size(); i++) {
            QuestionPointVo qpoint = quepointlist.get(i);
            List<Map> points = qpoint.getPointids();
            if (N_Utils.isListNotEmpty(points)) {
                if (qpoint.getQlevel() == 1 || !N_Utils.isEmptyInteger(qpoint.getEptqid())) {
                    //说明本题为单题,获取该题下所有学生的得分情况
                    List<EPaperStudentQuestion> stuqueslist = paperstulist.stream().filter(s -> s.getEptqid().equals(qpoint.getEptqid())).collect(Collectors.toList());
                    for (EPaperStudentQuestion sq : stuqueslist) {
                        setEPaperQuestionPointsForStuQues(gradestulist, sq, points, qpoint.getEptqid().toString());
                    }
                } else {
                    //说明该题为复合题，获取所有子题
                    List<Integer> eptqids = qpoint.getEptqids();
                    String eptqidsStr = eptqids.stream().map(String::valueOf).collect(Collectors.joining(","));
                    List<EPaperStudentQuestion> stuqueslist = paperstulist.stream().filter(s -> eptqids.contains(s.getEptqid())).collect(Collectors.toList());
                    //根据每个学生分组获取每个学生该题分值
                    Map<Integer, List<EPaperStudentQuestion>> stuquesmap = stuqueslist.stream().collect(Collectors.groupingBy(EPaperStudentQuestion::getStudentid));
                    for (Map.Entry<Integer, List<EPaperStudentQuestion>> entry : stuquesmap.entrySet()) {
                        List<EPaperStudentQuestion> stuques = entry.getValue();
                        Double stuscore = stuques.stream().mapToDouble(EPaperStudentQuestion::getStuscore).sum();
                        EPaperStudentQuestion sqfirst = stuques.get(0);
                        EPaperStudentQuestion sq = new EPaperStudentQuestion();
                        sq.setStudentid(entry.getKey());
                        sq.setClassid(sqfirst.getClassid());
                        sq.setStuscore(stuscore);
                        setEPaperQuestionPointsForStuQues(gradestulist, sq, points, eptqidsStr);
                    }
                }
            }
        }
        List<Map> classes = examPaperClassVo.getClasses();
        //根据试卷知识点分析进行生成学生、班级、年级知识点分析
        for (Map map : pointlist) {
            String pointid = map.get("pointid").toString();
            String pointname = map.get("pointname").toString();
            Double pointscore = Double.parseDouble(map.get("score").toString());
            Double pointrate = Double.parseDouble(map.get("srate").toString());
            List<Map> qorders = (List<Map>) map.get("ques");
            List<Integer> orders = qorders.stream().map(s -> Integer.parseInt(s.get("order").toString())).collect(Collectors.toList());
            String orderstr = orders.stream().map(String::valueOf).collect(Collectors.joining(","));//试题
            //单个知识点学生得分情况:一个知识对应一个或多个试题，
            List<ERPointStuScoreVo> gradepointstulist = gradestulist.stream().filter(s -> s.getPointid().equals(pointid)).collect(Collectors.toList());

            List<ERPointStuScoreVo> pointstuscorelist = new ArrayList<>(); //知识点下多个试题，处理成单个学生总分值情况
            Map<Integer, List<ERPointStuScoreVo>> pointstuscoremap = gradepointstulist.stream().collect(Collectors.groupingBy(ERPointStuScoreVo::getStudentid));
            for (Map.Entry<Integer, List<ERPointStuScoreVo>> entry : pointstuscoremap.entrySet()) {
                List<ERPointStuScoreVo> stuscorelist = entry.getValue();
                Double stuscore = stuscorelist.stream().mapToDouble(ERPointStuScoreVo::getStuscore).sum();
                ERPointStuScoreVo sscorevofirst = stuscorelist.get(0);
                ERPointStuScoreVo sscorevo = new ERPointStuScoreVo();
                sscorevo.setStudentid(sscorevofirst.getStudentid());
                sscorevo.setClassid(sscorevofirst.getClassid());
                sscorevo.setStuscore(stuscore);
                pointstuscorelist.add(sscorevo);
            }

            Double gstuscore = pointstuscorelist.stream().mapToDouble(ERPointStuScoreVo::getStuscore).sum();
            Double gavgscore = N_Utils.getDoubleDivideForAvg(gstuscore, pointstuscorelist.size());
            Double gsrate = N_Utils.getDoubleDivideAndMulitiply(gstuscore, pointscore * pointstuscorelist.size());

            for (Map classm : classes) {
                Integer classid = Integer.parseInt(classm.get("classid").toString());
                List<ERPointStuScoreVo> classpointstulist = pointstuscorelist.stream().filter(s -> s.getClassid().equals(classid)).collect(Collectors.toList());
                if(N_Utils.isListNotEmpty(classpointstulist)){
                    Double cstuscore = classpointstulist.stream().mapToDouble(ERPointStuScoreVo::getStuscore).sum();
//                Double cscore = classpointstulist.stream().mapToDouble(ERPointStuScoreVo::getScore).sum();
                    Double cavgscore = N_Utils.getDoubleDivideForAvg(cstuscore, classpointstulist.size());
                    Double csrate = N_Utils.getDoubleDivideAndMulitiply(cstuscore, pointscore * classpointstulist.size());

                    ERclassPoint eRclassPoint = new ERclassPoint();
                    eRclassPoint.setExamid(examPaperClassVo.getExamid());
                    eRclassPoint.setClassid(classid);
                    eRclassPoint.setEpid(examPaperClassVo.getEpid());
                    eRclassPoint.setSubjectid(examPaperClassVo.getSubjectid());
                    eRclassPoint.setPointid(pointid);
                    eRclassPoint.setPointname(pointname);
                    eRclassPoint.setScore(pointscore);
                    eRclassPoint.setSrate(pointrate);
                    eRclassPoint.setGradescore(gstuscore);
                    eRclassPoint.setGradeavgscore(gavgscore);
                    eRclassPoint.setGradesrate(gsrate);
                    eRclassPoint.setClassscore(cstuscore);
                    eRclassPoint.setClassavgscore(cavgscore);
                    eRclassPoint.setClasssrate(csrate);
                    eRclassPoint.setQns(orderstr);
                    cpointlist.add(eRclassPoint);

                    //遍历单个学生
                    for (ERPointStuScoreVo stu : classpointstulist) {
                        ERstudentPoint erstupoint = new ERstudentPoint();
                        erstupoint.setExamid(examPaperClassVo.getExamid());
                        erstupoint.setSubjectid(examPaperClassVo.getSubjectid());
                        erstupoint.setEpid(examPaperClassVo.getEpid());
                        erstupoint.setStudentid(stu.getStudentid());
                        erstupoint.setClassid(classid);
                        erstupoint.setPointid(pointid);
                        erstupoint.setPointname(pointname);
                        erstupoint.setStuscore(stu.getStuscore());
                        erstupoint.setStusrate(N_Utils.getDoubleDivideAndMulitiply(stu.getStuscore(), pointscore));
                        stupointlist.add(erstupoint);
                    }
                }
            }
        }
    }

    //题型、试题、知识点、难易度--知识点:设置每个学生每个试题知识点得分
    private void setEPaperQuestionPointsForStuQues(List<ERPointStuScoreVo> gradestulist, EPaperStudentQuestion sq, List<Map> points, String eptqids) {
        if (points.size() == 1) {
            Map pointmap = points.get(0);
            //说明该试题仅有一个知识点得分直接为改知识点分值
            ERPointStuScoreVo pscvo = new ERPointStuScoreVo();
            pscvo.setClassid(sq.getClassid());
            pscvo.setStudentid(sq.getStudentid());
            pscvo.setStuscore(sq.getStuscore());
            String pointid = pointmap.get("pointid").toString();
            pscvo.setPointid(pointid);
            pscvo.setEptqids(eptqids);
            gradestulist.add(pscvo);
        } else {
            //计算每个知识点所占分值（平均分配）
            Double[] avgps = ExamUtil.getPointAvgScore(points.size(), sq.getStuscore());
            for (int j = 0; j < points.size(); j++) {
                Map pointmap = points.get(j);
                ERPointStuScoreVo pscvo = new ERPointStuScoreVo();
                pscvo.setClassid(sq.getClassid());
                pscvo.setStudentid(sq.getStudentid());
                String pointid = pointmap.get("pointid").toString();
                pscvo.setPointid(pointid);
                pscvo.setEptqids(eptqids);
                if (avgps.length == 2 && (j + 1) == points.size()) {
                    pscvo.setStuscore(avgps[1]);
                } else {
                    pscvo.setStuscore(avgps[0]);
                }

                gradestulist.add(pscvo);
            }
        }
    }

    //题型、试题、知识点、难易度--难易度
    private void setEPaperQuestionComplexitys(List<Map> complexitylist, List<EPaperStudentQuestion> paperstulist, List<ERclassComplexity> complist,
                                              List<ERStudentComplexity> stucomplist, ExamPaperClassVo examPaperClassVo) {
        List<Map> classes = examPaperClassVo.getClasses();
        for (Map compmap : complexitylist) {
            Integer complexity = Integer.parseInt(compmap.get("level").toString());
            Double score = Double.parseDouble(compmap.get("score").toString());//难易度下试题总分值
            Double srate = Double.parseDouble(compmap.get("srate").toString());//难易度下试题分值占比
            List<Map> queslist = (List<Map>) compmap.get("ques");//试题相关对象（数量为几个代表几个母题）

            String qns = "";
            List<Integer> leveleptqids = new ArrayList<>();//所有试题id
            for (Map quesmap : queslist) {
                List<Integer> eptqids = (List<Integer>) quesmap.get("eptqids");
                String order = quesmap.get("order").toString();//试题母题题号
                qns = qns + order + ",";
                leveleptqids.addAll(eptqids);
            }

            List<EPaperStudentQuestion> levelstuquelist = new ArrayList<>();//难易度下所有试题
            for (Integer eptqid : leveleptqids) {
                List<EPaperStudentQuestion> petqqueslit = paperstulist.stream().filter(s -> eptqid.equals(s.getEptqid())).collect(Collectors.toList());
                levelstuquelist.addAll(petqqueslit);
            }

            List<EPaperStudentQuestion> qgstulist = new ArrayList<>();//每个学生难易度下得分
            Map<Integer, List<EPaperStudentQuestion>> stuQuesMap = levelstuquelist.stream().collect(Collectors.groupingBy(EPaperStudentQuestion::getStudentid));
            for (Map.Entry<Integer, List<EPaperStudentQuestion>> entry : stuQuesMap.entrySet()) {
                List<EPaperStudentQuestion> stuqueslist = entry.getValue();
                EPaperStudentQuestion pfirst = stuqueslist.get(0);
                EPaperStudentQuestion pstq = new EPaperStudentQuestion();
                pstq.setStudentid(entry.getKey());
                pstq.setClassid(pfirst.getClassid());
                Double qstuscore = stuqueslist.stream().mapToDouble(EPaperStudentQuestion::getStuscore).sum();
                Double qscore = stuqueslist.stream().mapToDouble(EPaperStudentQuestion::getQscore).sum();
                pstq.setQscore(qscore);
                pstq.setStuscore(qstuscore);
                qgstulist.add(pstq);

                ERStudentComplexity stucomp = new ERStudentComplexity();
                stucomp.setStudentid(entry.getKey());
                stucomp.setClassid(pstq.getClassid());
                stucomp.setExamid(examPaperClassVo.getExamid());
                stucomp.setSubjectid(examPaperClassVo.getSubjectid());
                stucomp.setEpid(examPaperClassVo.getEpid());
                stucomp.setComplexity(complexity);
                stucomp.setStuscore(qstuscore);
                stucomp.setStusrate(N_Utils.getDoubleDivideAndMulitiply(qstuscore, qscore));
                stucomplist.add(stucomp);
            }

            Double tgstuscore = qgstulist.stream().mapToDouble(EPaperStudentQuestion::getStuscore).sum();//难易度下学生得分
            Double tgscore = qgstulist.stream().mapToDouble(EPaperStudentQuestion::getQscore).sum();//难易度下试题总分
            Double tgsrate = N_Utils.getDoubleDivideAndMulitiply(tgstuscore, tgscore);//年级得分率
            Double tgavgscore = N_Utils.getDoubleDivideForAvg(tgstuscore,qgstulist.size());


            for (Map classm : classes) {
                Integer classid = Integer.parseInt(classm.get("classid").toString());
                List<EPaperStudentQuestion> qcstulist = qgstulist.stream().filter(s -> s.getClassid().equals(classid)).collect(Collectors.toList());
                if(N_Utils.isListNotEmpty(qcstulist)){
                    Double qcscore = qcstulist.stream().mapToDouble(EPaperStudentQuestion::getQscore).sum();
                    Double qcstuscore = qcstulist.stream().mapToDouble(EPaperStudentQuestion::getStuscore).sum();
                    Double qcavgscore = N_Utils.getDoubleDivideForAvg(qcstuscore,qcstulist.size());

                    ERclassComplexity erc = new ERclassComplexity();
                    erc.setExamid(examPaperClassVo.getExamid());
                    erc.setSubjectid(examPaperClassVo.getSubjectid());
                    erc.setEpid(examPaperClassVo.getEpid());
                    erc.setClassid(classid);
                    erc.setComplexity(complexity);
                    erc.setScore(score);
                    erc.setSrate(srate);
                    erc.setGradescore(tgstuscore);
                    erc.setGradeavgscore(tgavgscore);
                    erc.setGradesrate(tgsrate);
                    erc.setClassscore(qcstuscore);
                    erc.setClasssrate(N_Utils.getDoubleDivideAndMulitiply(qcstuscore, qcscore));
                    erc.setClassavgscore(qcavgscore);
                    erc.setQns(qns.substring(0, qns.lastIndexOf(",")));
                    complist.add(erc);
                }
            }
        }
    }
}
