package com.xhkjedu.sstudy.service.paper;

import com.alibaba.fastjson.JSON;
import com.xhkjedu.constant.PlatformConstant;
import com.xhkjedu.exception.MissingParametersException;
import com.xhkjedu.sstudy.mapper.gradeclass.ClassMapper;
import com.xhkjedu.sstudy.mapper.paper.*;
import com.xhkjedu.sstudy.mapper.paperstudent.PaperClassMapper;
import com.xhkjedu.sstudy.mapper.paperstudent.PaperStudentMapper;
import com.xhkjedu.sstudy.mapper.subjectbook.TeacherSubjectbookMapper;
import com.xhkjedu.sstudy.mapper.system.SchoolMapper;
import com.xhkjedu.sstudy.model.paper.*;
import com.xhkjedu.sstudy.model.paperstudent.TPaperClass;
import com.xhkjedu.sstudy.model.paperstudent.TPaperStudent;
import com.xhkjedu.sstudy.utils.StudyUtil;
import com.xhkjedu.sstudy.vo.paper.*;
import com.xhkjedu.sstudy.vo.paperstudent.PaperSearchVo;
import com.xhkjedu.sstudy.vo.question.QuestionVo;
import com.xhkjedu.sstudy.vo.subjectbook.PointVo;
import com.xhkjedu.utils.N_Utils;
import com.xhkjedu.vo.ResultVo;
import com.xhkjedu.vo.paper.PaperListVo;
import com.xhkjedu.vo.system.UserVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @ClassName PaperService
 * Description 作业
 * Author WN
 * Date 2020/6/8 16:14
 **/
@Slf4j
@Service
public class PaperService {
    @Resource
    private PaperMapper paperMapper;
    @Resource
    private PaperFileService paperFileService;
    @Resource
    private PaperScantronQtypeMapper paperScantronQtypeMapper;
    @Resource
    private PaperScantronMapper paperScantronMapper;
    @Resource
    private PaperQtypeMapper paperQtypeMapper;
    @Resource
    private PaperQtypeQuestionMapper paperQtypeQuestionMapper;
    @Resource
    private PaperAnalyzeMapper paperAnalyzeMapper;
    @Resource
    private PaperStudentMapper paperStudentMapper;
    @Resource
    private ClassMapper classMapper;
    @Resource
    private PaperClassMapper paperClassMapper;
    @Resource
    private HttpServletRequest request;

    @Resource
    private TeacherSubjectbookMapper teacherSubjectbookMapper;
    @Resource
    private SchoolMapper schoolMapper;

    /**
     * 功能描述  答题卡作业--保存
     *
     * @param *      @param paper
     * @param qtypes
     * @return boolean
     * @author WN
     * @date 2020/6/9
     */
    @Transactional(rollbackFor = Exception.class)
    public Integer saveScantronPaper(TPaper paper, List<TPaperScantronQtype> qtypes) throws Exception {
        Integer paperid = 0;
        try {

            //根据用户id获取用户权限科目，如果上传科目和权限科目不一致，不允许保存
            String subjectid = teacherSubjectbookMapper.listSubjectidByTeacherid(paper.getCreateid());
            if(!subjectid.equals(paper.getSubjectid())){
                throw new Exception("保存失败");
            }

            paper.setPapertype(2); //作业类型1结构性试题2自定义答题卡

            //答题卡中试题
            List<TPaperScantron> scanlist = new ArrayList<>();
            qtypes.forEach(t->{
                scanlist.addAll(t.getScantrons());
            });

            if(N_Utils.isListNotEmpty(scanlist)){
                paper.setPapernum(scanlist.size());
                Double paperscore = scanlist.stream().collect(Collectors.summingDouble(TPaperScantron::getPsscore));
                paper.setPaperscore(paperscore);
                List<TPaperFile> lst = paper.getPfiles();
                if(N_Utils.isListNotEmpty(lst)){
                    paper.setHasfile(1);
                }else{
                    paper.setHasfile(0);
                }

                paperid = savePaper(paper);//保存作业
                paper.setPaperid(paperid);

                //保存作业关联信息
                if(N_Utils.isListNotEmpty(lst)){
                    //保存作业附件
                    savePaperScantronFile(paper);
                }
                //保存答题卡信息
                savePaperScantronQtype(paper,qtypes);
                //保存分析
                savePaperScantronAnalyze(paper,qtypes,scanlist);
            } else {
                throw new Exception("试题不能为空");
            }
        }catch (Exception e){
            log.error("保存答题卡作业失败：" + e.getMessage());
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            throw new MissingParametersException("保存答题卡作业失败");
        }

        return paperid;
    }

    /**
     *功能描述  答题卡作业--修改
     * @author WN
     * @date 2020/6/11
     * @param  * @param paper
     * @param qtypes
     * @return boolean
     */
    @Transactional(rollbackFor = Exception.class)
    public boolean updateScantronPaper(TPaper paper, List<TPaperScantronQtype> qtypes) throws Exception {
        boolean rtn = false;
        try {
            //答题卡中试题
            List<TPaperScantron> scanlist = new ArrayList<>();
            qtypes.forEach(t->{
                scanlist.addAll(t.getScantrons());
            });

            if(N_Utils.isListNotEmpty(scanlist)){
                paper.setPapernum(scanlist.size());
                Double paperscore = scanlist.stream().collect(Collectors.summingDouble(TPaperScantron::getPsscore));
                paper.setPaperscore(paperscore);
                List<TPaperFile> lst = paper.getPfiles();
                if(N_Utils.isListNotEmpty(lst)){
                    paper.setHasfile(1);
                }else{
                    paper.setHasfile(0);
                }
                paper.setPapertype(2);

                //修改作业基本信息
                paperMapper.updatePaper(paper);

                //保存作业关联信息
                if(N_Utils.isListNotEmpty(lst)){
                    //删除作业附件后重新保存
                    paperFileService.deleteByPaperid(paper.getPaperid());
                    savePaperScantronFile(paper);    //保存作业附件
                }

                //删除作业答题卡信息
                paperScantronQtypeMapper.deleteByPaperid(paper.getPaperid());   //保存答题卡信息
                savePaperScantronQtype(paper, qtypes);
                //删除分析信息
                savePaperScantronAnalyze(paper,qtypes,scanlist);  //保存分析

                rtn = true;
            } else {
                throw new Exception("试题不能为空");
            }

        }catch (Exception e){
            log.error("修改答题卡作业失败：" + e.getMessage());
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            throw new MissingParametersException("修改答题卡作业失败");
        }
        return rtn;
    }

    /**
     * 保存作业
     * @Param [paper]
     * @Author ywx
     * @Date 2020/6/10 10:29
     * @return void
     **/
    private Integer savePaper(TPaper paper) {
        paper.setPaperstate(21);//作业状态：21未布置 22 已布置
        paper.setCreatetime(N_Utils.getSecondTimestamp());
        paper.setChecktype(0);
        paper.setHasreport(0);
        paper.setTimetype(1);
        paper.setDeleted(0);
        String directorid = paper.getDirectorid();
        if (directorid != null && (directorid.equals("0") || directorid.equals(""))) {
            paper.setDirectorid(null);
        }
        int year = schoolMapper.getYearByUserId(paper.getCreateid());
        paper.setYear(year);
        paperMapper.insertUseGeneratedKeys(paper);
        return paper.getId();
    }

    //答题卡--保存作业附件信息
    private void savePaperScantronFile(TPaper paper){
        int fileorder = 1;
        List<TPaperFile> lst = paper.getPfiles();
        for(TPaperFile pf : lst){
            pf.setCreateid(paper.getCreateid());
            pf.setCreatetime(N_Utils.getSecondTimestamp());
            pf.setSchoolid(paper.getSchoolid());
            pf.setFileorder(fileorder);
            pf.setPaperid(paper.getPaperid());
            fileorder++;
        }
        paperFileService.addBatch(lst);
    }

    //答题卡--保存答题卡-题型-知识点
    private void savePaperScantronQtype(TPaper paper, List<TPaperScantronQtype> qtypes) {
        int sorder = 1;//答题卡试题序号
        int qtypeorder = 1;//答题卡题型序号
        //处理答题卡--题型--试题
        List<TPaperScantron> savescan = new ArrayList<>();
        for (TPaperScantronQtype qtype : qtypes) {
            List<TPaperScantron> scanlst = qtype.getScantrons();//题型下试题
            qtype.setCreateid(paper.getCreateid());
            qtype.setCreatetime(N_Utils.getSecondTimestamp());
            qtype.setSchoolid(paper.getSchoolid());
            qtype.setPstnum(scanlst.size());
            Double qtypescore = scanlst.stream().collect(Collectors.summingDouble(TPaperScantron::getPsscore));
            qtype.setPstscore(qtypescore);
            qtype.setPaperid(paper.getPaperid());
        }

        paperScantronQtypeMapper.insertList(qtypes);//批量保存答题卡题型
        for (TPaperScantronQtype qtype : qtypes) {
            for (TPaperScantron sc : qtype.getScantrons()) {
                sc.setCreateid(paper.getCreateid());
                sc.setCreatetime(N_Utils.getSecondTimestamp());
                sc.setSchoolid(paper.getSchoolid());
                sc.setPaperid(paper.getPaperid());
                sc.setPsqtypeid(qtype.getId());
                savescan.add(sc);
            }
        }
        paperScantronMapper.insertList(savescan);//批量保存答题卡
    }

    //保存答题卡分析
    private Integer savePaperScantronAnalyze(TPaper paper,List<TPaperScantronQtype> qtypes,List<TPaperScantron> scanlist){
        int znum = 0;
        double zscore = 0;
        int knum = 0;
        double kscore = 0;
        for(TPaperScantron q : scanlist){
            if(N_Utils.isObjectiveQuestion(q.getCtype())){
                knum ++;
                kscore = kscore + q.getPsscore();
            }else{
                znum ++;
                zscore = zscore + q.getPsscore();
            }
        }

        double znumrate = N_Utils.getIntegerDivideAndMulitiply(znum, paper.getPapernum());
        double knumrate = N_Utils.getDoubleReduce(100.0, znumrate);

        double zscorerate = N_Utils.getDoubleDivideAndMulitiply(zscore, paper.getPaperscore());
        double kscorerate = N_Utils.getDoubleReduce(100.0,zscorerate);

        List<Map> ranglist = new ArrayList<>();
        Map zgmap = new TreeMap();
        zgmap.put("qtname","主观题");
        zgmap.put("score",zscore);
        zgmap.put("num",znum);
        zgmap.put("srate",zscorerate);
        zgmap.put("nrate",znumrate);
        ranglist.add(zgmap);
        Map kgmap = new TreeMap();
        kgmap.put("qtname","客观题");
        kgmap.put("score",kscore);
        kgmap.put("num",knum);
        kgmap.put("srate",kscorerate);
        kgmap.put("nrate",knumrate);
        ranglist.add(kgmap);

        Map ztmap = new TreeMap<>();
        ztmap.put("pnum", paper.getPapernum());
        ztmap.put("pscore",paper.getPaperscore());
        ztmap.put("ranglist",ranglist);

        //题型分布(按照名称进行分组)
        qtypes.stream().sorted(Comparator.comparing(TPaperScantronQtype::getPstorder)).collect(Collectors.toList());
        Map<String,List<TPaperScantronQtype>> qtypemap =  qtypes.stream().collect(Collectors.groupingBy(TPaperScantronQtype:: getQtypename, Collectors.toList()));
        List<Map> qtlist = new ArrayList<>();
        for(Map.Entry<String, List<TPaperScantronQtype>> entry : qtypemap.entrySet()){
            List<TPaperScantronQtype> aq = entry.getValue();
            int num = aq.stream().mapToInt(TPaperScantronQtype::getPstnum).sum();
            double tscore = aq.stream().collect(Collectors.summingDouble(TPaperScantronQtype:: getPstscore));
            tscore = N_Utils.formatDouble(tscore,1);
            double storerate = N_Utils.getDoubleDivideAndMulitiply(tscore, paper.getPaperscore());
            //获取小题题号
            List<Integer> orderlist = new ArrayList<>();
            List<Integer> eptqidlist = new ArrayList<>();
            List<Double> scorelist = new ArrayList<>();
            List<String> qnamelist = new ArrayList<>();
            List<String> qnlist = new ArrayList<>();
            for(TPaperScantronQtype t : aq){
                List<TPaperScantron> qlist = t.getScantrons();
                for(TPaperScantron q : qlist){
                    orderlist.add(q.getPsorder());
                    eptqidlist.add(q.getPscaid());
                    qnlist.add(q.getQn());
                    scorelist.add(q.getPsscore());
                    qnamelist.add(q.getQtypename());
                }
            }

            Map anmap = new TreeMap();//题型对应试题的id和基础信息
            anmap.put("orders",orderlist);
            anmap.put("eptqids",eptqidlist);
            anmap.put("qns",qnlist);
            anmap.put("scores",scorelist);
            anmap.put("qtypenames",qnamelist);

            Map tmap = new TreeMap();
            tmap.put("qtname",entry.getKey());
            tmap.put("qtid",aq.get(0).getPsqtypeid());
            tmap.put("num",num);
            tmap.put("score",tscore);
            tmap.put("srate",storerate);
            tmap.put("ques",anmap);
            qtlist.add(tmap);
        }

        TPaperAnalyze paperAnalyze = new TPaperAnalyze();
        paperAnalyze.setPaperid(paper.getPaperid());
        paperAnalyze.setQtypejson(JSON.toJSONString(qtlist));
        paperAnalyze.setAlljson(JSON.toJSONString(ztmap));

        paperAnalyzeMapper.deleteByPaperid(paper.getPaperid());//先删除原分析
        paperAnalyzeMapper.insertUseGeneratedKeys(paperAnalyze);
        return paperAnalyze.getId();
    }

    /**
     *功能描述  删除作业
     * @author WN
     * @date 2020/6/9
     * @param  * @param paper
     * @return void
     */
    public Integer delPaper(TPaper paper){

        // int result =  paperMapper.delPaper(paper.getPaperid());
        //2023-06-08新增作业复制功能，因为文件仅复制地址，之前删除文件取消
       /* List<TPaperFile> pfilelist = paperFileService.listObjsByPaperid(paper.getPaperid());//获取作业文件夹

        if (N_Utils.isListNotEmpty(pfilelist)) {
            List<String> resourceUrls = new ArrayList<>();
            for (int i = 0; i < pfilelist.size(); i++) {
                TPaperFile pf = pfilelist.get(i);
                resourceUrls.add(pf.getFilepath());

                if(!resourceUrls.contains(pf.getSourcepath())){
                    resourceUrls.add(pf.getSourcepath());
                }
            }
            messageSender.resourceDel(resourceUrls);//给文件服务器发送mq删除文件
        }*/
        //2023-11-22作业删除改为逻辑删除
        return paperMapper.updatePaperDeleted(paper.getPaperid(),1);
    }

    /**
     * 结构性试题作业--保存
     * @Param [paper, qtypes]
     * @Author ywx
     * @Date 2020/6/10 8:11
     * @return boolean
     **/
    @Transactional(rollbackFor = Exception.class)
    public Integer saveQuestionPaper(TPaper paper, List<TPaperQtype> qtypes) throws Exception {
        Integer paperid = 0;
        try {

            //根据用户id获取用户权限科目，如果上传科目和权限科目不一致，不允许保存
            String subjectid = teacherSubjectbookMapper.listSubjectidByTeacherid(paper.getCreateid());
            if(!subjectid.equals(paper.getSubjectid())){
                throw new Exception("保存失败");
            }

            setPaperScoreAndNum(paper, qtypes);//设置作业分值和试题数量
            paperid = savePaper(paper);//保存作业
            paper.setPaperid(paperid);
            savePaperQtype(paper, qtypes);//保存作业题型信息
            generatePaperAnalyze(paper);//生成作业分析
        }catch (Exception e){
            log.error("保存结构性试题作业失败：" + e.getMessage());
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            throw new RuntimeException("保存结构性试题作业失败");
       }
        return paperid;
    }

    /**
     * 设置作业分值和试题数量
     * @Param [paper, qtypes]
     * @Author ywx
     * @Date 2020/6/28 18:05
     * @return void
     **/
    private void setPaperScoreAndNum(TPaper paper, List<TPaperQtype> qtypes) throws Exception {
        List<QuestionVo> questionList = new ArrayList<>();
        qtypes.forEach(t -> {
            questionList.addAll(t.getQuestions());
        });
        if(N_Utils.isListEmpty(questionList)) throw new Exception("试题不能为空");
        Double paperscore = questionList.stream().collect(Collectors.summingDouble(QuestionVo::getScore));
        paper.setPaperscore(paperscore);
        paper.setPapernum(questionList.size());
    }

    @Transactional(rollbackFor = Exception.class)
    public boolean updateQuestionPaper(TPaper paper, List<TPaperQtype> qtypes) throws Exception {
        boolean rtn = false;
        try {

            setPaperScoreAndNum(paper, qtypes);//设置作业分值和试题数量
            //修改作业基本信息
            paperMapper.updatePaper(paper);
            paperQtypeMapper.deleteByPaperid(paper.getPaperid());//删除作业题型信息
            savePaperQtype(paper, qtypes);//保存作业题型信息
            generatePaperAnalyze(paper);//生成作业分析
            rtn = true;
        }catch (Exception e){
            log.error("保存结构性试题作业失败：" + e.getMessage());
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            throw new RuntimeException("保存结构性试题作业失败");
        }
        return rtn;
    }

    /**
     * 保存作业题型信息
     * @Param [paper, qtypes]
     * @Author ywx
     * @Date 2020/6/28 17:58
     * @return void
     **/
    private void savePaperQtype(TPaper paper, List<TPaperQtype> qtypes) {
        Integer paperid = paper.getPaperid();
        Integer createid = paper.getCreateid();
        Integer schoolid = paper.getSchoolid();

        int qorder = 1;//试题序号
        int ptorder = 1;//题型序号
        //处理答题卡--题型--试题
        List<TPaperQtypeQuestion> ptqs = new ArrayList<>();
        for (TPaperQtype qtype : qtypes) {
            if("tlt".equals(qtype.getQtypeid())){
                qtype.setQtypeid(null);
            }
            List<QuestionVo> questions = qtype.getQuestions();//题型下试题
            qtype.setCreateid(createid);
            qtype.setCreatetime(N_Utils.getSecondTimestamp());
            qtype.setSchoolid(schoolid);
            qtype.setPtnum(questions.size());
            Double ptscore = questions.stream().collect(Collectors.summingDouble(QuestionVo::getScore));
            qtype.setPtscore(ptscore);
            qtype.setPtorder(ptorder);
            qtype.setPaperid(paperid);
            ptorder++;
        }
        paperQtypeMapper.insertList(qtypes);//批量保存答题卡题型
        for (TPaperQtype qtype : qtypes) {
            for (QuestionVo q : qtype.getQuestions()) {
                List<Map> sonqlist = q.getSonqlist();
                if (N_Utils.isListEmpty(sonqlist)) {
                    TPaperQtypeQuestion ptq = new TPaperQtypeQuestion();
                    ptq.setPtid(qtype.getId());
                    ptq.setPaperid(paperid);
                    ptq.setQuestionid(q.getQuestionid());
                    ptq.setPtqscore(q.getScore());
                    ptq.setPtqorder(qorder);
                    ptq.setCreateid(createid);
                    ptq.setCreatetime(N_Utils.getSecondTimestamp());
                    ptq.setSchoolid(schoolid);
                    ptq.setQn(ptq.getPtqorder().toString());
                    ptq.setQuestionpid(q.getQuestionid());
                    ptq.setMscore(q.getScore());
                    ptq.setMqtypeid(q.getQtypeid());
                    ptq.setMqtypename(q.getQtypename());
                    ptq.setCtype(q.getCtype());
                    ptqs.add(ptq);
                } else {
                    Integer sorder = 1;
                    for (Map sq : sonqlist) {
                        TPaperQtypeQuestion ptq = new TPaperQtypeQuestion();
                        ptq.setPtid(qtype.getId());
                        ptq.setPaperid(paperid);
                        ptq.setQuestionid(sq.get("questionid").toString());
                        ptq.setPtqscore(Double.valueOf(sq.get("score").toString()));
                        ptq.setPtqorder(qorder);
                        ptq.setCreateid(createid);
                        ptq.setCreatetime(N_Utils.getSecondTimestamp());
                        ptq.setSchoolid(schoolid);
                        ptq.setQn(qorder+"."+sorder);
                        ptq.setQuestionpid(q.getQuestionid());
                        ptq.setMscore(q.getScore());
                        ptq.setMqtypeid(q.getQtypeid());
                        ptq.setMqtypename(q.getQtypename());
                        ptq.setCtype((Integer) sq.get("ctype"));
                        sorder++;
                        ptqs.add(ptq);
                    }
                }
                qorder++;
            }
        }
        paperQtypeQuestionMapper.insertList(ptqs);//批量保存答题卡
    }

    /**
     * 生成作业分析
     * @Param [paperid, schoolid]
     * @Author ywx
     * @Date 2020/6/10 9:57
     * @return java.lang.Integer
     **/
    private Integer generatePaperAnalyze(TPaper paper) {
        //获取是试卷试题
        List<PaperQtypeVo> qtypelist = paperQtypeMapper.listPaperQtypeQuestions(paper.getPaperid());
        List<QuestionOrderVo> pointqlist = new ArrayList<>();//用于存放知识点，以及知识点下得分
        List<PaperQtypeQuesVo> mquestions = new ArrayList<>();//存放单题和母题
        List<QuestionOrderVo> complexitylist = new ArrayList<>();//试题难易度存放试题
        List<QuestionPointVo> quesplist = new ArrayList<>();//单题、母题对应知识点

        //处理出试卷中所有试题、知识点
        List<Map> typelist = new ArrayList<>();//题型分析
        for(PaperQtypeVo qt : qtypelist){
            List<Integer> qorderlist = new ArrayList<>();
            List<QuestionOrderVo> qtypeqlist = new ArrayList<>();
            List<PaperQtypeQuesVo> tqlist = qt.getQuelist();
            int hasmt = 0;
            for(PaperQtypeQuesVo q : tqlist){
                int ctype = q.getCtype();
                //单题的pid设置为默认值，方便后续进行单题和母题处理
                if(q.getQlevel()==1){
                    q.setQuestionpid("000");
                    //判断试题是否是客观题
                    if(N_Utils.isObjectiveQuestion(ctype)){
                        //判断试题是否是客观题,暂时用mctype进行标识
                        q.setMctype(111);
                    }else{
                        q.setMctype(112);
                    }
                    //设置知识点
                    mquestions.add(q);
                    //获取试题知识点
                    List<Map> qpoints = q.getPoints();
                    //处理试题知识点占分
                    setPaperQuestionPointScore(pointqlist,quesplist,qpoints,q,null,null);
                    setPaperQuestionQtypeScore(qtypeqlist,q,null,null);//处理试题题型
                    setPaperQuestionComplexityScore(complexitylist,q,null,null);//处理试题难易度
                }
                if(q.getQlevel() == 3){
                    hasmt ++;
                }
                if(!qorderlist.contains(q.getPtqorder())){
                    qorderlist.add(q.getPtqorder());
                }
            }

            if(hasmt > 0){
                //说明该题型下有复合题,复合体进行知识点、题型下试题题号及id进行操作
                LinkedHashMap<String,List<PaperQtypeQuesVo>> quesMap = tqlist.stream().collect(Collectors.groupingBy(PaperQtypeQuesVo:: getQuestionpid,LinkedHashMap::new, Collectors.toList()));
                for(Map.Entry<String, List<PaperQtypeQuesVo>> entry : quesMap.entrySet()){
                    if(!entry.getKey().equals("000")){
                        //说明该题为母题，
                        PaperQtypeQuesVo mq = new PaperQtypeQuesVo();
                        List<PaperQtypeQuesVo> sonques = entry.getValue();
                        int k = 0;//如果k大于1说明有小题是主观题，则母题为主观题
                        double score = 0;
                        for(PaperQtypeQuesVo sq : sonques){
                            if(!N_Utils.isObjectiveQuestion(sq.getCtype())){
                                k++;
                            }
                            score = N_Utils.getDoubleSum(score,sq.getPtqscore());
                        }

                        PaperQtypeQuesVo qobj = sonques.get(0);
                        mq.setQuestionid(qobj.getQuestionpid());
                        mq.setComplexity(qobj.getMcomplexity());
                        mq.setPtqorder(qobj.getPtqorder());
                        mq.setPtqscore(score);
                        mq.setQtypename(qobj.getMqtypename());
                        if(k == 0){
                            mq.setMctype(111);
                        }else{
                            mq.setMctype(112);
                        }
                        mq.setQlevel(qobj.getMqlevel());
                        mq.setSonques(sonques);
                        //获取所有子题的试题题号
                        List<String> qns = sonques.stream().map(PaperQtypeQuesVo::getQn).collect(Collectors.toList());
                        String[] qnstr = qns.stream().toArray(String[]::new);
                        //所有子题的试题eptqid
                        List<Integer> eptqids = sonques.stream().map(PaperQtypeQuesVo::getPtqid).collect(Collectors.toList());
                        Integer[] eptqidstr = eptqids.stream().toArray(Integer[]::new);

                        //获取知识点
                        List<Map> qpoints = sonques.get(0).getPoints();
                        mq.setPoints(qpoints);
                        mquestions.add(mq);
                        setPaperQuestionPointScore(pointqlist,quesplist,qpoints,mq,qnstr,eptqids);
                        setPaperQuestionQtypeScore(qtypeqlist,mq,qnstr,eptqidstr);//处理试题题型
                        setPaperQuestionComplexityScore(complexitylist,mq,qnstr,eptqidstr);//处理试题难易度
                    }
                }
            }

            //试题题型分析数据
            double storerate = N_Utils.getDoubleDivideAndMulitiply(qt.getPtscore(), paper.getPaperscore());
            Map tmap = new TreeMap();
            tmap.put("qtid",qt.getPtid());
            tmap.put("qtname",qt.getQtypename());
            tmap.put("num",qt.getPtnum());
            tmap.put("score",qt.getPtscore());
            tmap.put("srate",storerate);
            qtypeqlist = qtypeqlist.stream().sorted(Comparator.comparing(QuestionOrderVo::getOrder)).collect(Collectors.toList());
            tmap.put("ques",qtypeqlist);
            typelist.add(tmap);
        }

        //试题总体分布进行分析
        //客观题集合
        List<PaperQtypeQuesVo> ktlst = mquestions.stream().filter(q->q.getMctype() == 111).collect(Collectors.toList());
        int ktnum = ktlst.size();
        double ktscore = ktlst.stream().collect(Collectors.summingDouble(PaperQtypeQuesVo:: getPtqscore));
        ktscore = N_Utils.formatDouble(ktscore,1);
        double ktnrate = N_Utils.getIntegerDivideAndMulitiply(ktnum, paper.getPapernum());
        double ktsrate = N_Utils.getDoubleDivideAndMulitiply(ktscore, paper.getPaperscore());
        List<PaperQsVo> ranglist = new ArrayList<>();
        ranglist.add(new PaperQsVo("客观题", ktscore, ktnum, ktsrate, ktnrate));
        PaperQsVo zgq = new PaperQsVo();
        zgq.setQtname("主观题");
        zgq.setNum(paper.getPapernum() - ktnum);
        zgq.setNrate(N_Utils.getDoubleReduce(100.0,ktnrate));
        zgq.setScore(N_Utils.getDoubleReduce(paper.getPaperscore(),ktscore));
        zgq.setSrate(N_Utils.getDoubleReduce(100.0,ktsrate));
        ranglist.add(zgq);
        Map ztmap = new TreeMap<>();
        ztmap.put("pnum", paper.getPapernum());
        ztmap.put("pscore",paper.getPaperscore());
        ztmap.put("ranglist",ranglist);

        //难易度
        List<Map> clist = new ArrayList<>();
        if(N_Utils.isListNotEmpty(complexitylist)){
            Map<String,List<QuestionOrderVo>> complxmap =  complexitylist.stream().collect(Collectors.groupingBy(QuestionOrderVo:: getId, Collectors.toList()));
            for(Map.Entry<String, List<QuestionOrderVo>> entry : complxmap.entrySet()){
                List<QuestionOrderVo> pgblist = entry.getValue();
                Double score = pgblist.stream().mapToDouble(s -> s.getScore()).sum();
                score = N_Utils.formatDouble(score,1);
                Double srate = N_Utils.getDoubleDivideAndMulitiply(score,paper.getPaperscore());
                Map prate = new TreeMap();
                prate.put("level",Integer.parseInt(entry.getKey()));
                prate.put("score",score);
                prate.put("srate",srate);
                prate.put("ques",pgblist.stream().sorted(Comparator.comparing(QuestionOrderVo::getOrder)).collect(Collectors.toList()));
                clist.add(prate);
            }
        }

        //知识点分析
        List<Map> pointlist = new ArrayList<>();
        if(N_Utils.isListNotEmpty(pointqlist)){
            LinkedHashMap<String,List<QuestionOrderVo>> pointmap = pointqlist.stream().collect(Collectors.groupingBy(QuestionOrderVo::getId,LinkedHashMap::new,Collectors.toList()));
            //根据指示进行分组，
            for(Map.Entry<String, List<QuestionOrderVo>> entry : pointmap.entrySet()){
                List<QuestionOrderVo> pgblist = entry.getValue();
                //获取知识点的总分
                Double score = pgblist.stream().mapToDouble(s -> s.getScore()).sum();
                score = N_Utils.formatDouble(score,1);
                Double srate = N_Utils.getDoubleDivideAndMulitiply(score,paper.getPaperscore());
                Map prate = new TreeMap();
                prate.put("pointid",entry.getKey());
                prate.put("pointname",pgblist.get(0).getName());
                prate.put("score",score);
                prate.put("srate",srate);
                prate.put("ques",pgblist.stream().sorted(Comparator.comparing(QuestionOrderVo::getOrder)).collect(Collectors.toList()));
                pointlist.add(prate);
            }
        }

        TPaperAnalyze paperAnalyze = new TPaperAnalyze();
        paperAnalyze.setPaperid(paper.getPaperid());
        paperAnalyze.setAlljson(JSON.toJSONString(ztmap));//总体分析
        paperAnalyze.setQtypejson(JSON.toJSONString(typelist));//试题栏题型分析
        paperAnalyze.setComplexityjson(JSON.toJSONString(clist));//难易度分析
        paperAnalyze.setPointjson(JSON.toJSONString(pointlist));//知识点分析
        paperAnalyze.setQuespointjson(JSON.toJSONString(quesplist));

        paperAnalyzeMapper.deleteByPaperid(paper.getPaperid());
        paperAnalyzeMapper.insertUseGeneratedKeys(paperAnalyze);
        return paperAnalyze.getId();
    }

    //设置知识点
    private void setPaperQuestionPointScore(List<QuestionOrderVo> pointqlist,List<QuestionPointVo> quesplist,List<Map> qpoints,PaperQtypeQuesVo dq,String[] qnstr,List<Integer> eptqids){
        if(N_Utils.isListNotEmpty(qpoints)){
            if(qpoints.size() == 1){
                //试题只有一个知识点
                Map pointmap = qpoints.get(0);
                QuestionOrderVo qpoint = new QuestionOrderVo();
                qpoint.setId(pointmap.get("pointid").toString());
                qpoint.setName(pointmap.get("pointname").toString());
                qpoint.setOrder(dq.getPtqorder());
                qpoint.setScore(dq.getPtqscore());
                qpoint.setQlevel(dq.getQlevel());
                qpoint.setQuestionid(dq.getQuestionid());
                if(qnstr == null){
                    qpoint.setQns(new String[]{dq.getQn()});
                }else{
                    qpoint.setQns(qnstr);
                }

                if(N_Utils.isListEmpty(eptqids)){
                    qpoint.setPtqids(new Integer[]{dq.getPtqid()});
                }else{
                    Integer[] eptqidstr = eptqids.stream().toArray(Integer[]::new);
                    qpoint.setPtqids(eptqidstr);
                }
                pointqlist.add(qpoint);

                //试题对应知识点
                QuestionPointVo questionPointVo = new QuestionPointVo();
                questionPointVo.setOrder(dq.getPtqorder());
                questionPointVo.setScore(dq.getPtqscore());
                questionPointVo.setQlevel(dq.getQlevel());
                questionPointVo.setQuestionid(dq.getQuestionid());
                List<Map> pointids = new ArrayList<>();
                Map map = new HashMap();
                map.put("pointid",pointmap.get("pointid").toString());
                map.put("score",dq.getPtqscore());
                pointids.add(map);
                questionPointVo.setPointids(pointids);

                if(N_Utils.isListEmpty(eptqids)){
                    List<Integer> saveids = new ArrayList<>();
                    saveids.add(dq.getPtqid());
                    questionPointVo.setPtqids(saveids);
                    questionPointVo.setPtqid(dq.getPtqid());
                }else{
                    questionPointVo.setPtqids(eptqids);
                    questionPointVo.setPtqid(0);
                }
                quesplist.add(questionPointVo);
            }else{

                //试题有多个知识点
                //计算每个知识点所占分值（平均分配）
                Double[] avgps = N_Utils.getPointAvgScore(qpoints.size(), dq.getPtqscore());
                List<Map> pointids = new ArrayList<>();
                for(int m = 0; m<qpoints.size();m++){
                    Map pointmap = qpoints.get(m);
                    QuestionOrderVo qpoint = new QuestionOrderVo();
                    qpoint.setId(pointmap.get("pointid").toString());
                    qpoint.setName(pointmap.get("pointname").toString());
                    qpoint.setOrder(dq.getPtqorder());
                    qpoint.setQlevel(dq.getQlevel());
                    qpoint.setQuestionid(dq.getQuestionid());


                    Map quesmap = new HashMap();//试题对应知识点
                    quesmap.put("pointid",pointmap.get("pointid").toString());

                    if(avgps.length == 2 && (m+1) == qpoints.size()){
                        //不能整除分，并且是最后一个知识点
                        qpoint.setScore(avgps[1]);
                        quesmap.put("score",avgps[1]);
                    }else{
                        qpoint.setScore(avgps[0]);
                        quesmap.put("score",avgps[0]);
                    }
                    pointids.add(quesmap);

                    //题号集合
                    if(qnstr == null){
                        qpoint.setQns(new String[]{dq.getQn()});
                    }else{
                        qpoint.setQns(qnstr);
                    }
                    //试卷中试题id集合
                    if(N_Utils.isListEmpty(eptqids)){
                        qpoint.setPtqids(new Integer[]{dq.getPtqid()});
                    }else{
                        Integer[] eptqidstr = eptqids.stream().toArray(Integer[]::new);
                        qpoint.setPtqids(eptqidstr);
                    }
                    pointqlist.add(qpoint);
                }

                //试题对应知识点
                QuestionPointVo questionPointVo = new QuestionPointVo();
                questionPointVo.setOrder(dq.getPtqorder());
                questionPointVo.setScore(dq.getPtqscore());
                questionPointVo.setQlevel(dq.getQlevel());
                questionPointVo.setQuestionid(dq.getQuestionid());
                questionPointVo.setPointids(pointids);
                if(N_Utils.isListEmpty(eptqids)){
                    List<Integer> saveids = new ArrayList<>();
                    saveids.add(dq.getPtqid());
                    questionPointVo.setPtqids(saveids);
                    questionPointVo.setPtqid(dq.getPtqid());

                }else{
                    questionPointVo.setPtqids(eptqids);
                    questionPointVo.setPtqid(0);
                }
                quesplist.add(questionPointVo);

            }
        } else{
            QuestionPointVo questionPointVo = new QuestionPointVo();
            questionPointVo.setOrder(dq.getPtqorder());
            questionPointVo.setScore(dq.getPtqscore());
            questionPointVo.setQlevel(dq.getQlevel());
            questionPointVo.setQuestionid(dq.getQuestionid());
            questionPointVo.setPointids(null);
            if(N_Utils.isListEmpty(eptqids)){
                List<Integer> saveids = new ArrayList<>();
                saveids.add(dq.getPtqid());
                questionPointVo.setPtqids(saveids);
                questionPointVo.setPtqid(dq.getPtqid());
            }else{
                questionPointVo.setPtqids(eptqids);
                questionPointVo.setPtqid(0);
            }

            quesplist.add(questionPointVo);
        }
    }

    //设置题型下试题题号及分值
    private void setPaperQuestionQtypeScore(List<QuestionOrderVo> qtypelist,PaperQtypeQuesVo dq,String[] qnstr,Integer[] eptqidstr){
        QuestionOrderVo qtype = new QuestionOrderVo();
        qtype.setId(dq.getQtypeid());
        qtype.setName(dq.getQtypename());
        qtype.setComplexity(dq.getComplexity());
        qtype.setOrder(dq.getPtqorder());
        qtype.setScore(dq.getPtqscore());
        qtype.setQlevel(dq.getQlevel());
        qtype.setQuestionid(dq.getQuestionid());
        if(qnstr == null){
            qtype.setQns(new String[]{dq.getQn()});
        }else{
            qtype.setQns(qnstr);
        }
        if(eptqidstr == null){
            qtype.setPtqids(new Integer[]{dq.getPtqid()});
        }else{
            qtype.setPtqids(eptqidstr);
        }

        qtypelist.add(qtype);
    }

    //设置试题难易度
    private void setPaperQuestionComplexityScore(List<QuestionOrderVo> complexityList,PaperQtypeQuesVo dq,String[] qnstr,Integer[] eptqidstr){
        QuestionOrderVo qtype = new QuestionOrderVo();
        qtype.setId(dq.getComplexity().toString());//存放试题难易度
        qtype.setOrder(dq.getPtqorder());
        qtype.setScore(dq.getPtqscore());
        qtype.setQlevel(dq.getQlevel());
        qtype.setQuestionid(dq.getQuestionid());
        if(qnstr == null){
            qtype.setQns(new String[]{dq.getQn()});
        }else{
            qtype.setQns(qnstr);
        }
        if(eptqidstr == null){
            qtype.setPtqids(new Integer[]{dq.getPtqid()});
        }else{
            qtype.setPtqids(eptqidstr);
        }

        complexityList.add(qtype);
    }

    /**
     *功能描述  详情--答题卡
     * @author WN
     * @date 2020/6/11
     * @param  * @param paperid
     * @return com.xhkjedu.vo.paper.PaperScantronVo
     */
    public Map getPaperScantronDetial(Integer paperid){
        Map paper = paperMapper.findById(paperid);

        Integer paperstate = Integer.parseInt(paper.get("paperstate").toString());
        if(paperstate == 22){
            Integer timetype = Integer.parseInt(paper.get("timetype").toString());
            if(timetype == 1){
                //统一布置，获取班级发布时间
                TPaperClass paperClass = paperClassMapper.getPaperClassTimes(paperid);
                paper.put("starttime",paperClass.getStarttime());
                paper.put("stoptime",paperClass.getStoptime());
            }
        }

        List<TPaperFile> fils = paperFileService.listObjsByPaperid(paperid);
        paper.put("pfiles",fils);
        //获取题型下试题
        List<PaperScantronQtypeVo> lst = paperScantronQtypeMapper.listQtypeScans(paperid);
        paper.put("qtypes",lst);

        return paper;

    }

    /**
     * 作业详情--结构性试题
     * @Param [paperid]
     * @Author ywx
     * @Date 2020/6/10 14:33
     * @return com.xhkjedu.vo.paper.PaperVo
     **/
    public Map findById(Integer paperid, Integer schoolid) {
        Map paper = paperMapper.findById(paperid);
        Integer papertype = Integer.parseInt(paper.get("papertype").toString());
        Integer paperstate = Integer.parseInt(paper.get("paperstate").toString());


        if(paperstate == 22){
            Integer timetype = Integer.parseInt(paper.get("timetype").toString());
            if(timetype == 1){
                //统一布置，获取班级发布时间
                TPaperClass paperClass = paperClassMapper.getPaperClassTimes(paperid);
                paper.put("starttime",paperClass.getStarttime());
                paper.put("stoptime",paperClass.getStoptime());
            }
        }

        List<PaperQtypeVo> types = paperMapper.listPaperType(paperid);//获取作业题型列表
        List<QuestionVo> qlist = new ArrayList<>();
        types.forEach(t -> {
            qlist.addAll(t.getQuestions());
        });
        List<String> questionids = qlist.stream().map(q -> q.getQuestionpid()).distinct().collect(Collectors.toList());
        List<Map> pointList = paperMapper.listQuestionPoints(questionids);
        List<String> questionpids = qlist.stream().filter(q -> q.getQlevel() == 3)
                .map(q -> q.getQuestionpid()).distinct().collect(Collectors.toList());
        List<QuestionVo> mquestions = new ArrayList<>();
        if (N_Utils.isListNotEmpty(questionpids)) {
            mquestions = paperMapper.listQuestionByQuestionIds(questionpids);
        }
        boolean bxzyfb = false;//靶向作业发布
        List<Map> students = null;
        List<Map> classList = null;
        if (papertype == 3 && paperstate == 22) {//靶向作业获取试题发布对象
            bxzyfb = true;
            students = paperStudentMapper.listStudent(paperid);
            List<Integer> classids = students.stream().map(m -> (Integer) m.get("classid")).distinct().collect(Collectors.toList());
            classList = classMapper.listByClassIds(classids, paperid);//获取班级基本信息列表
            Integer checkid = request.getIntHeader(PlatformConstant.XH_USER_ID);
            if(N_Utils.isTrueInteger(checkid)) {
                long checknum = 0;//可批阅人数
                if (N_Utils.str2Int(paper.get("createid").toString()).equals(checkid)) {
                    checknum = students.stream().filter(s -> StudyUtil.tjlist.contains(s.get("psstate"))).count();
                } else {
                    for (Map map : classList) {
                        Object classid = map.get("classid");
                        Object checkId = map.get("checkid");
                        if (checkid.equals(checkId)) {
                            checknum += students.stream().filter(s -> StudyUtil.tjlist.contains(s.get("psstate")) && classid.equals(s.get("classid"))).count();
                        }
                    }
                }
                paper.put("checknum", checknum);
            }
        }
        for (PaperQtypeVo type : types) {
            List<QuestionVo> questions = type.getQuestions();
            Map<String, List<QuestionVo>> fq = questions.stream().collect(Collectors.groupingBy(q -> q.getQuestionpid(),
                    LinkedHashMap::new, Collectors.toList()));
            List<QuestionVo> questionList = new ArrayList<>();
            for (Map.Entry<String, List<QuestionVo>> entry : fq.entrySet()) {
                List<QuestionVo> list = entry.getValue();
                QuestionVo tq = list.get(0);
                QuestionVo q;
                if (tq.getQlevel() == 3) {//复合题
                    String questionpid = tq.getQuestionpid();
                    q = mquestions.stream().filter(mq -> mq.getQuestionid().equals(questionpid)).findFirst().orElse(null);
                    double score = list.stream().mapToDouble(QuestionVo::getScore).sum();
                    q.setScore(score);
                    q.setPtqorder(tq.getPtqorder());
                    q.setSonqlist(JSON.parseArray(JSON.toJSONString(list), Map.class));
                    q.setQtypename(type.getQtypename());
                    q.setQtypeid(type.getQtypeid());
                    q.setComplexity(tq.getComplexity());
                } else {
                    q = tq;
                }
                String questionid = q.getQuestionid();
                List<Map> points = pointList.stream().filter(qp -> qp.get("questionid").toString().equals(questionid))
                        .collect(Collectors.toList());
                q.setPoints(JSON.parseArray(JSON.toJSONString(points), PointVo.class));
                if (bxzyfb) {
                    List<Map> qsList = students.stream().filter(s -> s.get("questionids").toString().contains(questionid))
                                               .collect(Collectors.toList());
                    Map<Integer, List<Map>> classCollect = qsList.stream().collect(Collectors.groupingBy(m -> (Integer) m.get("classid")
                            , LinkedHashMap::new, Collectors.toList()));
                    List<Map> schools = new ArrayList<>();
                    Map<Object, List<Map>> scollect = classList.stream().collect(Collectors.groupingBy(c -> c.get("schoolid")
                            , LinkedHashMap::new, Collectors.toList()));
                    for (Map.Entry<Object, List<Map>> sentry : scollect.entrySet()) {
                        List<Map> classes = new ArrayList<>();
                        List<Map> clist = sentry.getValue();
                        Map school = new HashMap();
                        school.put("schoolid", sentry.getKey());
                        school.put("schoolname", clist.get(0).get("schoolname"));
                        for (Map map : clist) {
                            Map cmap = new HashMap();
                            Integer classid = (Integer) map.get("classid");
                            cmap.put("classid", classid);
                            cmap.put("classname", map.get("classname"));
                            cmap.put("gradeid", map.get("gradeid"));
                            cmap.put("starttime", map.get("starttime"));
                            cmap.put("stoptime", map.get("stoptime"));
                            List<String> studentNames = classCollect.get(classid).stream().map(m -> m.get("username").toString()).collect(Collectors.toList());
                            cmap.put("students", studentNames);
                            classes.add(cmap);
                        }
                        school.put("classes", classes);
                        schools.add(school);
                    }
                    if (!N_Utils.isEmptyInteger(schoolid) && schools.size() > 1) {
                        //把本校放在第一个位置
                        for (int i = 0; i < schools.size(); i++) {
                            Map rtnMap = schools.get(i);
                            Integer schoolid2 = Integer.parseInt(rtnMap.get("schoolid").toString());
                            if (schoolid.equals(schoolid2)) {
                                Collections.swap(schools, i, 0);
                                break;
                            }
                        }
                    }
                    q.setSchools(schools);
                }
                questionList.add(q);
            }
            type.setQuestions(questionList);
        }

        paper.put("types",types);

        //获取作业对应的教材版本章节信息

        return paper;
    }

    /**
     * 作业列表
     * @Param [paper]
     * @Author ywx
     * @Date 2020/6/11 16:30
     * @return java.util.List<com.xhkjedu.vo.paper.PaperListVo>
     **/
    public List<PaperListVo> findAll(PaperSearchVo paper, UserVo userVo) {
        if(paper.getPsstate()!=null && paper.getPsstate() == 21){
            //未布置作业
            return paperMapper.listWfbPapers(paper, userVo);
        }else{
            //全部作业
            List<PaperListVo>  list = paperMapper.listAll(paper, userVo);
            return StudyUtil.getPaperListVo(list);
        }
    }

    /*
     * @Description 作业列表-我的
     * @Date 2024/3/12 10:09:33
     * @Author WN
     * @Param [paper, userVo]
     * @Return java.util.List<com.xhkjedu.sstudy.vo.paper.PaperListVo>
     **/
    public List<PaperListVo> findAllMy(PaperSearchVo paper, UserVo userVo) {
        if(paper.getPsstate()!=null && paper.getPsstate() == 21){
            //未布置作业
            return paperMapper.listWfbPapers(paper, userVo);
        }else{
            //全部作业
            List<PaperListVo>  list = paperMapper.listAllMy(paper);
            return StudyUtil.getPaperListVo(list);
        }
    }

    /**
     * 设置批改方式
     * @Param [param]
     * @Author ywx
     * @Date 2020/6/12 7:57
     * @return void
     **/
    @Transactional(rollbackFor = Exception.class)
    public ResultVo setCheckType(PaperParam param) {
        Integer checktype = param.getChecktype();//批改方式1教师批改2学生互改3指定学生批改
        Integer paperid = param.getPaperid();//试卷ID

        try {
            paperMapper.updateCheckType(paperid, checktype);//设置批改方式
            if (checktype == 1){//教师批阅
                if (N_Utils.isEmptyInteger(param.getTeacherid())) {//不同班级分别指定教师
                    List<PaperCheckParam> checkParams = JSON.parseArray(param.getClassids(), PaperCheckParam.class);
                    long count = checkParams.stream().filter(c -> N_Utils.isEmptyInteger(c.getCheckid())).count();
                    if (count != 0) return new ResultVo(1, "有班级未指定批阅人");
                    paperStudentMapper.updateCheckId2(paperid, checkParams);
                } else {//不同班级指定同一个教师
                    paperStudentMapper.updateCheckId(paperid,param.getTeacherid());//设置批改人
                }
            } else {
                List<PaperCheckParam> checkParams = JSON.parseArray(param.getClassids(), PaperCheckParam.class);
                List<PaperCheckParam> classStudents = paperStudentMapper.listStudentIdByPaperIdClassId(paperid, checkParams);
                Integer[] classids_ = new Integer[checkParams.size()];
                Map<Integer, Integer> map = new HashMap<>();
                for (int i = 0; i < checkParams.size(); i++) {
                    PaperCheckParam gs = checkParams.get(i);
                    List<Integer> studentids = classStudents.stream().filter(cs -> cs.getClassid().equals(gs.getClassid()))
                            .map(PaperCheckParam::getCheckid).collect(Collectors.toList());
                    gs.setStudentids(studentids);
                    if (checktype == 2) {
                        //学生互改
                        if (gs.getStudentids().size() == 1) {
                            gs.setCheckids(gs.getStudentids());
                        } else {
                            List<Integer> stuids = new ArrayList<>();
                            List<Integer> stuids_ = gs.getStudentids();
                            stuids.addAll(gs.getStudentids());
                            gs.setStudentids(stuids);

                            //互相批改作业,则把用户集合打散重新组成新的集合
                            Collections.shuffle(stuids_);
                            while (N_Utils.listNeworder(stuids, stuids_)) {
                                Collections.shuffle(stuids_);
                            }

                            gs.setCheckids(stuids_);
                        }
                        checkParams.set(i, gs);
                    } else if (checktype == 3) {
                        //如果选择的批改人只有一个人,则要自己批改自己的作业
                        if (gs.getCheckids().size() > 1) {
                            //设置批改人
                            Map<Integer, Integer> checkMap = this.setStudentIdCheckerId(gs);
                            map.putAll(checkMap);
                        }
                    }

                    classids_[i] = gs.getClassid();

                }
                List<TPaperStudent> list = setStudentCheckId(paperid, checkParams, checktype, map);//设置学生批改人对应关系
                paperStudentMapper.batchUpdateCheckId(list);//设置批改人
            }
        } catch (Exception e) {
            log.error("设置批改方式失败："+e.getMessage());
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return new ResultVo(1, "设置失败");
        }
        return new ResultVo(0,"设置成功");
    }

    /**
     * 设置学生批改人对应关系
     * @Param [paperid, checkParams, checktype, map]
     * @Author ywx
     * @Date 2020/6/12 9:05
     * @return java.util.List<com.xhkjedu.model.paperstudent.TPaperStudent>
     **/
    private List<TPaperStudent> setStudentCheckId(Integer paperid, List<PaperCheckParam> checkParams, Integer checktype, Map<Integer, Integer> map) {
        List<TPaperStudent> list = new ArrayList<>();
        for(int i=0;i<checkParams.size();i++){
            PaperCheckParam cp = checkParams.get(i);
            for(int j=0;j<cp.getStudentids().size();j++){
                TPaperStudent ps = new TPaperStudent();
                ps.setPaperid(paperid);
                ps.setClassid(cp.getClassid());
                Integer studentid = cp.getStudentids().get(j);
                ps.setStudentid(studentid);
                Integer checkid;
                if(checktype==1){
                    checkid = cp.getCheckids().get(0);
                } else if(checktype==2){
                    checkid = cp.getCheckids().get(j);
                }else{
                    //第一种只有一个批改人的
                    if(cp.getCheckids().size()==1){
                        checkid = cp.getCheckids().get(0);
                    }else{
                        checkid = map.get(studentid);
                    }
                }
                ps.setCheckid(checkid);
                list.add(ps);
            }
        }
        return list;
    }

    //设置作业批改人（选择指定学生）
    private Map<Integer,Integer> setStudentIdCheckerId(PaperCheckParam gs){
        Map<Integer,Integer> map = new HashMap<>();
        //选择学生批改
        List<Integer> allstudents = new ArrayList<>();//所有有作业的学生
        allstudents.addAll(gs.getStudentids());
        //去除选中的是批改人的作业
        for(int k=0;k<gs.getCheckids().size();k++){
            allstudents.remove(gs.getCheckids().get(k));//把批改人的作业去除
        }

        List<List<Integer>> result = N_Utils.averageAssignList(allstudents, gs.getCheckids().size());
        Collections.shuffle(gs.getCheckids());//重置批改作业人顺序

        for(int l=0;l<result.size();l++){
            List<Integer> groupstu = new ArrayList<>();
            groupstu.addAll(result.get(l));

            if(l==0){
                //把最有一个用户的作业插入这个集合中（避免数据自己批改自己的作业）
                groupstu.add(gs.getCheckids().get(result.size()-1));
            }else{
                //否则把上一个加入到作业集合中（避免数据自己批改自己的作业）
                int n = l-1;
                groupstu.add(gs.getCheckids().get(n));
            }
            for(int m=0;m<groupstu.size();m++){
                map.put(groupstu.get(m), gs.getCheckids().get(l));//设置批改人
            }
        }
        return map;
    }

    /**
     *获取批改学生列表
     * @Param [paperid, checkid, classid]
     * @Author ywx
     * @Date 2020/6/12 11:00
     * @return com.xhkjedu.vo.paper.CheckClassVo
     **/
    public CheckClassVo listStudentsByPaperIdCheckId(Integer paperid, Integer checkid, Integer classid) {
        CheckClassVo checkVo = paperMapper.listStudentsByPaperIdCheckId(paperid, checkid, classid);
        Integer ytjnum = checkVo.getYtjnum();
        checkVo.setWtjnum(checkVo.getClassnum()-ytjnum);
        if (!N_Utils.isEmptyInteger(ytjnum)){
            double scale = N_Utils.getIntegerDivideAndMulitiply(checkVo.getYpynum(),ytjnum);
            checkVo.setScale(scale);
        } else {
            checkVo.setScale(0);
        }
        if(checkVo.getYpynum() == null){
            checkVo.setYpynum(0);
        }
        return checkVo;
    }

    /**
     * 教师批阅列表
     * @Param [checkid]
     * @Author ywx
     * @Date 2020/6/18 14:55
     * @return java.util.List<com.xhkjedu.vo.paper.PaperListVo>
     **/
    public List<PaperListVo> correctList(Integer checkid, Integer schoolid) {
        List<PaperListVo> list = paperMapper.correctList(checkid, schoolid);
        return StudyUtil.getPaperListVo(list);
    }

    /**
     * 作业附件列表
     * @Param [paperid]
     * @Author ywx
     * @Date 2020/6/23 21:53
     * @return java.util.List<com.xhkjedu.model.paper.TPaperFile>
     **/
    public List<TPaperFile> listPaperFile(Integer paperid, Integer fileclass) {
        return paperMapper.listPaperFile(paperid, fileclass);
    }

    //获取作业原文件保存地址列表
    public List<String> listSourcePath(Integer paperid) {
        return paperMapper.listSourcePath(paperid);
    }

    //获取今天布置作业数量
    public String getPaperNum(String subjectid, Integer createid, Integer createtime) {
        Integer num = paperMapper.getPaperNum(subjectid, createid, createtime);
        String paperNum = "("+ N_Utils.NumberToChn(num)+")";
        return paperNum;
    }

    //获取作业状态
    public Integer getPaperState(Integer paperid) {
        return paperMapper.getPaperState(paperid);
    }

    //获取批阅班级
    public List<Map> listPaperClass(Integer paperid, Integer checkid, Integer schoolid) {
        return paperMapper.listPaperClass(paperid, checkid, schoolid);
    }

    //处理作业分析
    public void listPapersForAnalyze(Integer paperid){
        List<TPaper> papers = paperMapper.listPapersForAnalyze(paperid);
        for(TPaper p : papers){
            if(p.getPapertype() == 1 || p.getPapertype() == 3){
                //题库
                this.generatePaperAnalyze(p);
            }else{
                List<TPaperScantronQtype> qtypes = paperScantronQtypeMapper.listQtypeScansForAnalyze(p.getPaperid());
                List<TPaperScantron> scanlist = new ArrayList<>();
                qtypes.forEach(t->{
                    scanlist.addAll(t.getScantrons());
                });
                //附件作业
                this.savePaperScantronAnalyze(p,qtypes,scanlist);
            }
        }
    }
    public void listPapersForAnalyze2(Integer paperid){
        List<TPaper> papers = paperMapper.listPapersForAnalyze2(paperid);
        for(TPaper p : papers){
            //题库
            this.generatePaperAnalyze(p);
        }
    }

    //获取作业听力文件地址
    public String getHearfileByPaperid(Integer paperid){
        return paperMapper.getHearfileByPaperid(paperid);
    }

    /*
    * @Description 设置批阅界面内
    * @Author WN
    * @Date 2023/4/14 11:23
    */
    public Map getPaperCheckClassStu(PaperParam param){
        Map rtn = new LinkedHashMap();
        rtn.put("teachers",listSchoolTeacherByPaperid(param));
        rtn.put("stus",listPaperStudentsByPaperid(param));
        return rtn;
    }

    /*
    * @Description 设置批阅--教师
    * @Author WN
    * @Date 2023/4/14 11:13
    */
    public Map listSchoolTeacherByPaperid(PaperParam param){
        List<Map> bxList = new ArrayList<>();
        List<Map> hbList = new ArrayList<>();

        List<Map> rtnList = new ArrayList<>();
        //获取作业发布班级和学校
        List<Map> schoolClassList = paperMapper.listSchoolClassByPaperid(param.getPaperid(), param.getSchoolid());
        if(N_Utils.isListNotEmpty(schoolClassList)){
            Map schoolClass = schoolClassList.get(0);
            param.setSubjectid(schoolClass.get("subjectid").toString());
            param.setGradeid(Integer.parseInt(schoolClass.get("gradeid").toString()));
            param.setYear(Integer.parseInt(schoolClass.get("year").toString()));

            //获取学校对应班级
            Map<Object,List<Map>> schoolMap = schoolClassList.stream().collect(Collectors.groupingBy(m -> m.get("schoolid")
                    , LinkedHashMap::new, Collectors.toList()));//学校下班级集合

            for(Map.Entry<Object,List<Map>> entry : schoolMap.entrySet()){
                Map<String,Object> saveschoolMap = new LinkedHashMap();
                Map schoolClassOne = entry.getValue().get(0);
                saveschoolMap.put("schoolid",schoolClassOne.get("schoolid").toString());
                saveschoolMap.put("schoolname",schoolClassOne.get("schoolname").toString());
                saveschoolMap.put("classlist",entry.getValue());
                rtnList.add(saveschoolMap);
            }

            //获取作业发布班级对应科目的所有教师
            List<Map> classTeacherList = paperMapper.listTeacherClassByPaperid(param);
            if(N_Utils.isListNotEmpty(classTeacherList)){
                Map<Integer, List<Map>> schoolGroupMap = classTeacherList.stream().collect(Collectors.groupingBy(m -> Integer.parseInt(m.get("schoolid").toString())
                        , LinkedHashMap::new, Collectors.toList()));//学校下班级集合

                for(Map school : rtnList){
                    Integer schoolid = Integer.parseInt(school.get("schoolid").toString());
                    List<Map> teacherList = schoolGroupMap.get(schoolid);//学校下教师集合
                    school.put("teacherlist",teacherList);
                    if(schoolid.equals(param.getSchoolid())){
                        bxList.add(school);
                    }else{
                        hbList.add(school);
                    }
                }
            }
        }

        Map rtnMap = new LinkedHashMap();
        rtnMap.put("bx",bxList);
        rtnMap.put("hb",hbList);
        return rtnMap;
    }

    /*
    * @Description 批阅设置--作业关联学生
    * @Author WN
    * @Date 2023/4/14 11:21
    */
    public Map listPaperStudentsByPaperid(PaperParam param){
        List<Map> stulist = paperMapper.listPaperStudentsByPaperid(param.getPaperid(), param.getSchoolid());
        List<Map> bxList = new ArrayList<>();
        List<Map> hbList = new ArrayList<>();

        //把集团校班级放第一位
        for(int i=0;i<stulist.size();i++){
            Map stuClassMap= stulist.get(i);
            Integer schoolid = Integer.parseInt(stuClassMap.get("schoolid").toString());
            if(schoolid.equals(param.getSchoolid())){
                bxList.add(stuClassMap);
            }else{
                hbList.add(stuClassMap);
            }
        }
        Map rtnMap = new LinkedHashMap();
        rtnMap.put("bx",bxList);
        rtnMap.put("hb",hbList);
        return rtnMap;
    }

    /**
     * @Description 修改补交状态
     * @Date 2024/4/1 12:45
     * @Author YWX
     * @Param [paper]
     * @Return void
     **/
    public void updateAfterCommit(TPaper paper) {
        int stoptime = N_Utils.getSecondTimestamp();
        //获取已过截止时间作业班级数量
        int num = paperMapper.countEndPaperClassById(paper.getPaperid(), stoptime);
        if (num != 0) throw new MissingParametersException("已过截止时间，禁止修改！");
        paperMapper.updateAfterCommit(paper);
    }

    /**
     * @Description 获取批阅班级数量
     * @Date 2024/9/23 10:28
     * @Author YWX
     * @Param [paperid, createid]
     * @Return java.lang.Integer
     **/
    public Integer getCheckClassNum(Integer paperid, Integer createid) {
        return paperMapper.getCheckClassNum(paperid, createid);
    }
}
