package com.xhkjedu.sexam.service.paperstudent;

import com.alibaba.fastjson.JSON;
import com.xhkjedu.config.MissingParametersException;
import com.xhkjedu.sexam.mapper.paper.EPaperFileMapper;
import com.xhkjedu.sexam.mapper.paper.EPaperQtypeQuestionMapper;
import com.xhkjedu.sexam.mapper.paperstudent.EPaperStudentMapper;
import com.xhkjedu.sexam.mapper.paperstudent.EPaperStudentQuestionMapper;
import com.xhkjedu.sexam.mapper.paperstudent.EScanbatchMapper;
import com.xhkjedu.sexam.mapper.paperstudent.EScanerrorMapper;
import com.xhkjedu.sexam.mapper.system.UserMapper;
import com.xhkjedu.sexam.model.paper.EPaperQtype;
import com.xhkjedu.sexam.model.paper.EPaperQtypeQuestion;
import com.xhkjedu.sexam.model.paperstudent.EPaperStudent;
import com.xhkjedu.sexam.model.paperstudent.EPaperStudentQuestion;
import com.xhkjedu.sexam.model.paperstudent.EScanerror;
import com.xhkjedu.sexam.utils.ConvertUtil;
import com.xhkjedu.sexam.utils.ExamUtil;
import com.xhkjedu.sexam.vo.paperstudent.EPaperStudentVo;
import com.xhkjedu.sexam.vo.paperstudent.PaperStudentWebVo;
import com.xhkjedu.sexam.vo.paperstudent.PsqAnswerVo;
import com.xhkjedu.utils.N_Utils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @Description 学生试卷信息
 * @Author WN
 * Date 2022/7/26 14:00
 **/
@Service
@Slf4j
public class EPaperStudentService {
    @Resource
    private EPaperStudentMapper ePaperStudentMapper;
    @Resource
    private EPaperQtypeQuestionMapper ePaperQtypeQuestionMapper;
    @Resource
    private EPaperStudentQuestionMapper ePaperStudentQuestionMapper;
    @Resource
    private UserMapper userMapper;
    @Resource
    private EPaperFileMapper ePaperFileMapper;
    @Resource
    private EScanbatchMapper eScanbatchMapper;
    @Resource
    private EScanerrorMapper eScanerrorMapper;
    @Autowired
    private ConvertUtil convertUtil;

    /**
     * @Description 学生进行中考试列表
     * @Param [eps]
     * @Return java.util.List<java.util.Map>
     * @Author wn
     * @Date 2022/7/27 10:35
     **/
    public List<Map> listExamPapersForStudent(EPaperStudent eps) {
        return ePaperStudentMapper.listExamPapersForStudent(eps.getStudentid());
    }

    public Map getExamSubjectPaperByEpsid(Integer epsid) {
        Map map = ePaperStudentMapper.getExamSubjectPaperByEpsid(epsid);
        Long times = null;
        if (map.get("sdate") != null && map.get("begintime") != null && map.get("endtime") != null) {
            long bg = ExamUtil.strToTimestamp(map.get("sdate").toString() + " " + map.get("begintime").toString() + ":00");
            long ed = ExamUtil.strToTimestamp(map.get("sdate").toString() + " " + map.get("endtime").toString() + ":00");
            times = ExamUtil.subtract(ed, bg);
        }
        map.put("times", times);
        return map;
    }

    /**
     * 学生已结束考试列表
     *
     * @Description
     * @Param [eps]
     * @Return java.util.List<java.util.Map>
     * @Author wn
     * @Date 2022/7/27 11:34
     **/
    public List<Map> listExamsEndForStudent(EPaperStudent eps) {
        return ePaperStudentMapper.listExamsEndForStudent(eps.getStudentid());
    }

    /**
     * @Description 开始考试(andorid)
     * @Param [eps]
     * @Return java.util.Map
     * @Author wn
     * @Date 2022/7/27 11:48
     **/
    public Map startPaperForAndroid(EPaperStudent eps) {
        Integer epsid = eps.getEpsid();
        Integer examstate = ePaperStudentMapper.getExamStateByEpsId(epsid);
        if (2 == examstate) throw new MissingParametersException("考试已结束禁止操作");
        Map map = new HashMap();
        //获取试卷基本信息
        EPaperStudentVo psvo = ePaperStudentMapper.getExamSubjectByEpsid(epsid);
        Integer ptype = psvo.getPtype();

        List<Map> questions = null;
        if (ptype == 1) {
            //题库试卷试题
            questions = ePaperStudentMapper.listStuPaperQuestionsForAndroid(epsid);
        } else {
            questions = ePaperStudentMapper.listStuPaperFjQuestionsForAndroid(epsid);
        }
        if (ptype == 2) {
            List<Map> files = ePaperFileMapper.listPaperFiles(psvo.getEpid());
            map.put("files", files);
        }

        ePaperStudentMapper.updateStuStartime(epsid, N_Utils.getSecondTimestamp());
        map.put("paper", psvo);
        map.put("questions", questions);
        return map;
    }

    //保存学生试卷关联信息
    private void savePaperStudentQuestion(EPaperStudentVo psvo) {
        //生成学生试卷
        List<EPaperQtypeQuestion> pqlist = ePaperQtypeQuestionMapper.listQuestionsByEpid(psvo.getEpid());

        List<EPaperStudentQuestion> psqlist = new ArrayList<>();
        for (EPaperQtypeQuestion q : pqlist) {
            EPaperStudentQuestion sq = new EPaperStudentQuestion();
            sq.setClassid(psvo.getClassid());
            sq.setStudentid(psvo.getStudentid());
            sq.setExamid(psvo.getExamid());
            sq.setSubjectid(psvo.getSubjectid());
            sq.setEpid(psvo.getEpid());
            sq.setEpsid(psvo.getEpsid());
            sq.setEptqid(q.getEptqid());
            sq.setCtype(q.getCtype());
            sq.setQuestionid(q.getQuestionid());
            sq.setQn(q.getQn());
            sq.setQorder(q.getQorder());
            sq.setQscore(q.getScore());
            sq.setAnswered(0);
            sq.setConverted(0);
            sq.setChecked(0);
            sq.setStuscore(0.0);
            sq.setCosttime(0);
            sq.setGood(0);
            sq.setBad(0);
            psqlist.add(sq);
        }
        ePaperStudentQuestionMapper.insertList(psqlist);//保存试卷
    }

    /**
     * @Description 开始考试（web）
     * @Param [eps]
     * @Return java.util.List<java.util.Map>
     * @Author wn
     * @Date 2022/7/27 15:36
     **/
    public EPaperStudentVo startPaperForWeb(EPaperStudent eps) {
        Integer epsid = eps.getEpsid();
        Integer examstate = ePaperStudentMapper.getExamStateByEpsId(epsid);
        if (2 == examstate) throw new MissingParametersException("考试已结束禁止操作");
        //获取试卷基本信息
        EPaperStudentVo psvo = ePaperStudentMapper.getExamSubjectByEpsid(epsid);
        Integer ptype = psvo.getPtype();

        List<EPaperQtype> questions = null;
        if (ptype == 1) {
            //题库试卷试题
            questions = ePaperStudentMapper.listStuPaperQuestionsForWeb(epsid);
        } else {
            questions = ePaperStudentMapper.listStuPaperFjQuestionsForWeb(epsid);
        }

        if (ptype == 2) {
            List<Map> files = ePaperFileMapper.listPaperFiles(psvo.getEpid());
            psvo.setFiles(files);
        }
        psvo.setQtypelist(questions);
        ePaperStudentMapper.updateStuStartime(epsid, N_Utils.getSecondTimestamp());
        return psvo;
    }

    /**
     * @Description 提交单题
     * @Param [psq]
     * @Return void
     * @Author wn
     * @Date 2022/7/28 13:47
     **/
    public void saveCommitQuestion(EPaperStudentQuestion psq) throws Exception {
        try {
            //学生作答提交时先判断试卷是否设置的正确答案
            PsqAnswerVo answerVo = ePaperStudentQuestionMapper.getPaperQuestionAnswer(psq.getEpsqid());
            Integer examstate = ePaperStudentMapper.getExamStateByEpsId(answerVo.getEpsid());
            if (2 == examstate) throw new MissingParametersException("考试已结束禁止操作");
            setCommitQuestion(psq, answerVo);
            ePaperStudentQuestionMapper.updateStuAnswer(psq);
        } catch (Exception e) {
            log.error("提交试题失败：" + e.getMessage());
            throw new Exception("提交试题失败");
        }

    }

    //判断单道题情况
    private void setCommitQuestion(EPaperStudentQuestion psq, PsqAnswerVo answerVo) {
        int timestamp = N_Utils.getSecondTimestamp();
        psq.setAnswertime(timestamp);
        int coverted = 1;//是否转换0未转换1已转换2转换失败
        String stuanswer = psq.getStuanswer();
        Double stuscore = 0D;
        if (N_Utils.isEmpty(stuanswer) && N_Utils.isEmpty(psq.getStuanswertxt())
                && N_Utils.isListEmpty(JSON.parseArray(stuanswer, String.class))
                && N_Utils.isListEmpty(JSON.parseArray(psq.getStuanswertxt(), String.class))) {
            psq.setStuscore(stuscore);
            psq.setChecked(2);
            psq.setChecktime(timestamp);
            psq.setAnswered(0);
        } else {
            List<String> stuanswers = JSON.parseArray(stuanswer, String.class);
            //试卷已经设置了正确答案
            if (answerVo.getAnswered() == 1) {
                String qanswer = answerVo.getAnswer();
                List<String> qanswers = JSON.parseArray(qanswer, String.class);
                int ctype = answerVo.getCtype();
                if (psq.getAnswertype() == 1) {
                    if (N_Utils.isObjectiveQuestion(ctype)) {
                        //客观题进行批阅
                        if (ctype == 1 || ctype == 4 || ctype == 5 || ctype == 6) {
                            //单选、判断
                            if (stuanswer.equalsIgnoreCase(qanswer)) {
                                stuscore = answerVo.getScore();
                            }
                        } else if (ctype == 2) {//多选
                            //多选、选错不得分
                            if (stuanswers.get(0).length() <= qanswer.length()) {
                                String[] qanswerList = qanswers.get(0).split("");
                                String[] stuanswerList = stuanswers.get(0).split("");
                                int rightNum = 0;//选对个数
                                for (String sa : stuanswerList) {
                                    int right = 0;
                                    for (String qa : qanswerList) {
                                        if (qa.equals(sa)) {
                                            right = 1;
                                            rightNum++;
                                        }
                                    }
                                    if (right == 0) {//说明选错
                                        rightNum = 0;
                                        break;
                                    }
                                }
                                if (rightNum > 0) {
                                    if (qanswerList.length == rightNum) {
                                        //全选对
                                        stuscore = answerVo.getScore();
                                    } else if (qanswerList.length > rightNum) {
                                        //少选得半分
                                        stuscore = ExamUtil.div(answerVo.getScore(), 2, 1);
                                    }
                                }
                            }
                        }

                        psq.setChecked(2);
                        psq.setChecktime(timestamp);
                    } else {
                        if (stuanswers.size() > 1) {
                            coverted = 0;//上传的多张图片设为0未转换
                        }
                        psq.setChecked(0);
                    }
                } else {
                    psq.setChecked(0);
                }
            } else {
                psq.setChecked(0);
            }
            psq.setStuscore(stuscore);
        }

        Integer costtime = answerVo.getCosttime();
        if (costtime == null) {
            costtime = 0;
        }
        if (psq.getCosttime() == null) {
            psq.setCosttime(costtime);
        } else {
            psq.setCosttime(psq.getCosttime());
        }

        psq.setConverted(coverted);
    }

    /**
     * @Description 提交试卷
     * @Param [epsid]
     * @Return int
     * @Author wn
     * @Date 2022/7/28 16:59
     **/
    @Transactional(rollbackFor = Exception.class)
    public void saveCommitPaper(Integer epsid) {
        Integer examstate = ePaperStudentMapper.getExamStateByEpsId(epsid);
        if (2 == examstate) throw new MissingParametersException("考试已结束禁止操作");
        EPaperStudent ps = ePaperStudentMapper.selectByPrimaryKey(epsid);
        if (ps == null || ps.getSstate() == 2) {
            return;
        }
        EPaperStudent paperStudent = new EPaperStudent();
        paperStudent.setEpsid(epsid);
        paperStudent.setSstate(2);
        paperStudent.setEndtime(N_Utils.getSecondTimestamp());

        //更改试卷中学生未提交的试题设置为0分，标记为已批改
        ePaperStudentQuestionMapper.updateStuQuesitonNoCommit(epsid);
        //获取试卷中未批阅试题数量
        int noCheckNum = ePaperStudentQuestionMapper.getStuQuestionNoCheckNum(epsid);
        int checked = 0;
        if (noCheckNum == 0) {
            checked = 2;//试卷中所有试题都批完后标识试卷已批改
        }
        paperStudent.setChecked(checked);
        ePaperStudentMapper.updateStudentPaper(paperStudent);//修改试卷信息
        chandleStudentQuestionNoconvertedPic(epsid, 1);//处理试卷中多张图片未合并情况
    }

    //处理试卷中未已提交需要合并的图片,type1代表线上2代表扫码答题卡图片
    private void chandleStudentQuestionNoconvertedPic(Integer epsid, Integer type) {
        List<EPaperStudentQuestion> psqlist = ePaperStudentQuestionMapper.listStuQuesitonStuAnswerPic(epsid);
        if (N_Utils.isListNotEmpty(psqlist)) {
            for (EPaperStudentQuestion sq : psqlist) {
                List<String> stuanswer = JSON.parseArray(sq.getStuanswer(), String.class);
                if (N_Utils.isListNotEmpty(stuanswer) && stuanswer.size() > 1) {
                    convertUtil.imgMerge(sq.getEpsqid(), stuanswer, type);
                }
            }
        }
    }

    /**
     * @Description 提交试卷、试题（网页端）
     * @Param [pswvo]
     * @Return void
     * @Author wn
     * @Date 2022/7/28 19:18
     **/
    public void saveCommitPaperForWeb(PaperStudentWebVo pswvo) {
        Integer examstate = ePaperStudentMapper.getExamStateByEpsId(pswvo.getEpsid());
        if (2 == examstate) throw new MissingParametersException("考试已结束禁止操作");
        List<EPaperStudentQuestion> sqlist = pswvo.getQuestions();//学生提交试卷中试题
        EPaperStudent ps = ePaperStudentMapper.selectByPrimaryKey(pswvo.getEpsid());
        //试卷不存在或者已提交
        if (ps == null || ps.getSstate() == 2) {
            return;
        }
        //获取试卷中所有试题答案及分值
        List<PsqAnswerVo> anvolist = ePaperStudentQuestionMapper.listPaperQuestionsAnswer(pswvo.getEpsid());
        Integer checknum = 0;//记录试卷中试题批阅数量
        Double paperscore = 0D;//学生试卷得分
        for (EPaperStudentQuestion q : sqlist) {

            //获取该试题正确答案
            PsqAnswerVo anvo = anvolist.stream().filter(a -> a.getEpsqid().equals(q.getEpsqid())).findFirst().orElse(null);

            setCommitQuestion(q, anvo);
            if (q.getChecked() == 2) {
                checknum++;
            }
            paperscore = ExamUtil.add(paperscore, q.getStuscore());
        }
        EPaperStudent paperStudent = new EPaperStudent();
        paperStudent.setEpsid(pswvo.getEpsid());
        paperStudent.setEndtime(N_Utils.getSecondTimestamp());
        paperStudent.setSstate(2);
        paperStudent.setStuscore(paperscore);
        int checked = 0;
        if (checknum == sqlist.size()) {
            checked = 2;
        }
        paperStudent.setChecked(checked);

        ePaperStudentQuestionMapper.updateBatchStuQuestion(sqlist);
        ePaperStudentMapper.updateStudentPaper(paperStudent);

        //获取试卷中需要合并图片的试题
        chandleStudentQuestionNoconvertedPic(pswvo.getEpsid(), 1);
    }

    /**
     * @Description 答题卡扫描时保存
     * @Param [pswvo]
     * @Return void
     * @Author wn
     * @Date 2022/8/3 9:17
     **/
    @Transactional(rollbackFor = Exception.class)
    public void saveCommitPaperForScantron(PaperStudentWebVo pswvo) throws Exception {
        //扫描一次扫描数量+1
        eScanbatchMapper.updateScannum(pswvo.getBatchid());

        if (N_Utils.isEmpty(pswvo.getExamno())) {
            updateScanErrorInfo(2, pswvo);
            return;
        }

        //根据学生姓名和准考证号找到对应学生
        Integer userid = userMapper.getUseridByExamno(pswvo.getExamno());
        if (!N_Utils.isTrueInteger(userid)) {
            updateScanErrorInfo(2, pswvo);
            return;
        }
        //获取学生试卷
        EPaperStudent ps = ePaperStudentMapper.getPaperStudentByStuidAndEpid(pswvo.getEpid(), userid);
        //试卷不存在
        if (ps == null) {
            updateScanErrorInfo(1, pswvo);
            return;
        }

        pswvo.setEpsid(ps.getEpsid());
        String stupic = ps.getStupic();
        //考号重复1（已保存试卷）
        if (N_Utils.isNotEmpty(stupic)) {//已经有扫描的信息
            updateScanErrorInfo(3, pswvo);//标记本次扫描为考号重复
            updateScanErrorToDuplicate(pswvo, ps);//标记上次扫描结果为考号重复
            return;
        }
        //考号重复2（未保存试卷）
        //获取考号对应的出错信息，只要有出错信息直接保存进入错误
        Integer errornum = eScanerrorMapper.getErrorNumByExamno(pswvo.getEpid(),pswvo.getExamno());
        if(errornum > 0){
            updateScanErrorInfo(3, pswvo);//标记本次扫描为考号重复
            return;
        }

        int answerednum = saveScanQuestion(pswvo);//保存扫描试题
        if (pswvo.getSstate() == 3 && answerednum > 0) {//缺考 说明标记缺考但是客观题有作答
            updateScanErrorInfo(4, pswvo);
        }
    }

    //更新扫描出错信息
    private void updateScanErrorInfo(Integer errortype, PaperStudentWebVo pswvo) {
        //识别出错
        EScanerror er = new EScanerror();
        er.setBatchid(pswvo.getBatchid());
        er.setErrortype(errortype);
        er.setPagenum(pswvo.getPagenum());
        er.setErrorjson(JSON.toJSONString(pswvo));
        er.setCreatetime(N_Utils.getSecondTimestamp());
        er.setStupic(pswvo.getStupic());
        er.setExamno(pswvo.getExamno());
        er.setErrorstate(0);
        er.setQkjg(0);
        eScanerrorMapper.insertUseGeneratedKeys(er);
        eScanbatchMapper.updateErrornum(pswvo.getBatchid());//更改出错数量

        //错误日志中stupic中bae64转为图片
        if(N_Utils.isNotEmpty(pswvo.getStupic())){
            List<String> imgs = JSON.parseArray(pswvo.getStupic(),String.class);
            if(N_Utils.isListNotEmpty(imgs)){
                Map map = eScanbatchMapper.getScanBatchSchool(pswvo.getBatchid());
                Integer examid = Integer.parseInt(map.get("examid").toString());
                Integer schoolid = Integer.parseInt(map.get("schoolid").toString());
                String cloudcode =  map.get("cloudcode").toString();
                String path = cloudcode + File.separator + schoolid + File.separator + "exam";
                convertUtil.baseToScanImg(er.getId(),examid,imgs,path);
            }
        }
    }

    /**
     * @description 保存扫描出错信息
     * @param: [eScanerror]
     * @return: void
     * @author: wn
     * @date:
     **/
    @Transactional(rollbackFor = Exception.class)
    public void saveScanPaperError(EScanerror eScanerror) {
        eScanerror.setErrortype(1);
        eScanerror.setErrorstate(0);
        eScanerror.setQkjg(0);
        eScanerror.setCreatetime(N_Utils.getSecondTimestamp());
        eScanerrorMapper.insertUseGeneratedKeys(eScanerror);
        eScanbatchMapper.updateScanAndErrorNum(eScanerror.getBatchid());//更改扫描和出错数量

        //错误日志中stupic中bae64转为图片
        if(N_Utils.isNotEmpty(eScanerror.getStupic())){
            List<String> imgs = JSON.parseArray(eScanerror.getStupic(),String.class);
            if(N_Utils.isListNotEmpty(imgs)){
                Map map = eScanbatchMapper.getScanBatchSchool(eScanerror.getBatchid());
                Integer examid = Integer.parseInt(map.get("examid").toString());
                Integer schoolid = Integer.parseInt(map.get("schoolid").toString());
                String cloudcode =  map.get("cloudcode").toString();
                String path = cloudcode + File.separator + schoolid + File.separator + "exam";
                convertUtil.baseToScanImg(eScanerror.getId(),examid,imgs,path);
            }
        }
    }

    /**
     * @Description 学生试卷作答得分
     * @Param [studentid, epid]
     * @Return java.util.Map
     * @Author wn
     * @Date 2022/8/12 10:45
     **/
    public Map getStudentPaperScore(Integer epsid) {
        Map paper = ePaperStudentMapper.getStudentPaperScore(epsid);
        Integer ptype = Integer.parseInt(paper.get("ptype").toString());
        Integer epid = Integer.parseInt(paper.get("epid").toString());
        List<Map> qtypeques = null;
        if (ptype == 1) {
            qtypeques = ePaperStudentQuestionMapper.listQStuQuestionScore(epsid);
            setQuestionsForPaper(qtypeques);
        } else {
            qtypeques = ePaperStudentQuestionMapper.listFjStuQuestionScore(epsid);
            List<Map> files = ePaperFileMapper.listPaperFiles(epid);
            paper.put("files", files);
        }
        paper.put("qtypes", qtypeques);
        return paper;
    }

    //这只试卷中母子题
    private void setQuestionsForPaper(List<Map> qtypes) {
        for (Map mt : qtypes) {
            List<Map> questions = (List<Map>) mt.get("questions");
            List<Map> mqlist = new ArrayList<>();//存放母子题结构试题
            List<String> mtquestionids = new ArrayList<>();//存放母题的id
            for (Map qmap : questions) {
                Integer qlevel = Integer.parseInt(qmap.get("qlevel").toString());
                if (qlevel == 1) {
                    //单题
                    qmap.remove("mqstem");
                    qmap.remove("mqoption");
                    qmap.remove("msum");
                    qmap.remove("mqtypeid");
                    qmap.remove("mqtypename");
                    qmap.remove("mhashear");
                    qmap.remove("mhearfile");
                    qmap.remove("mquestionid");
                    qmap.remove("mctype");
                    qmap.remove("questionpid");
                    qmap.remove("mqanalyze");
                    qmap.remove("mqanswer");
                    qmap.remove("mqlevel");

                    mqlist.add(qmap);
                } else {
                    //子题
                    String questionpid = qmap.get("questionpid").toString();
                    if (!mtquestionids.contains(questionpid)) {
                        mtquestionids.add(questionpid);
                        List<Map> sonqueslist =
                                questions.stream().filter(s -> qlevel.equals(Integer.parseInt(s.get("qlevel").toString())) && questionpid.equals(s.get("questionpid").toString())).collect(Collectors.toList());

                        Double sontotalsocre = sonqueslist.stream().mapToDouble(o -> Double.parseDouble(o.get("score").toString())).sum();
                        Double stuscore = sonqueslist.stream().mapToDouble(o -> Double.parseDouble(o.get("stuscore").toString())).sum();
                        Map sque = sonqueslist.get(0);
                        Map mque = new HashMap();
                        mque.put("questionid", sque.get("mquestionid").toString());
                        mque.put("qlevel", 2);
                        mque.put("qstem", sque.get("mqstem").toString());
                        mque.put("ctype", Integer.parseInt(sque.get("mctype").toString()));
                        mque.put("qtypeid", sque.get("mqtypeid").toString());
                        mque.put("qtypename", sque.get("mqtypename").toString());
                        mque.put("qorder", sque.get("qorder").toString());
                        mque.put("qn", sque.get("qn").toString());
                        mque.put("snum", Integer.parseInt(sque.get("snum").toString()));
                        Integer hashear = Integer.parseInt(sque.get("mhashear").toString());
                        mque.put("hashear", hashear);
                        if (hashear == 1) {
                            mque.put("hearfile", sque.get("mhearfile").toString());
                        } else {
                            mque.put("hearfile", "");
                        }
                        mque.put("score", sontotalsocre);
                        mque.put("stuscore", stuscore);
                        if (N_Utils.isNotEmpty(sque.get("mqanalyze"))) {
                            mque.put("qanalyze", sque.get("mqanalyze").toString());
                        } else {
                            mque.put("qanalyze", "");
                        }
                        if (N_Utils.isNotEmpty(sque.get("mqanswer"))) {
                            mque.put("qanswer", sque.get("mqanswer").toString());
                        } else {
                            mque.put("qanswer", "");
                        }

                        for (Map sonquem : sonqueslist) {
                            sonquem.remove("mqstem");
                            sonquem.remove("mqoption");
                            sonquem.remove("msnum");
                            sonquem.remove("mqanalyze");
                            sonquem.remove("mqanswer");
                            sonquem.remove("mqlevel");
                            sonquem.remove("mqtypeid");
                            sonquem.remove("mqtypename");
                            sonquem.remove("mhashear");
                            sonquem.remove("mhearfile");
                            sonquem.remove("mquestionid");
                            sonquem.remove("mctype");
                            sonquem.remove("hashear");
                            sonquem.remove("hearfile");
                        }
                        mque.put("sonques", sonqueslist);
                        mqlist.add(mque);
                    }
                }
            }
            mt.put("questions", mqlist);
        }
    }

    //搜索考试学生获取学生试卷id
    public List<Map> getStuSubjectPaperByname(EPaperStudent ps) {
        return ePaperStudentMapper.getStuSubjectPaperByname(ps);
    }

    //修改学生试卷状态
    public void updateSstate(Integer epsid, Integer sstate) {
        Integer examstate = ePaperStudentMapper.getExamStateByEpsId(epsid);
        if (2 == examstate) throw new MissingParametersException("考试已结束禁止操作");
        ePaperStudentMapper.updateSstate(epsid, sstate);
    }

    //试卷、考号确认
    @Transactional(rollbackFor = Exception.class)
    public void sjKhConfirm(PaperStudentWebVo ps) throws Exception {
        saveCommitPaperForConfirm(ps);//保存试卷、考号确认扫描结果
        eScanerrorMapper.updateErrorStateExamno(ps.getSerrorid(), 1, ps.getExamno());//更新扫描出错记录为已处理
        eScanbatchMapper.updateErrornum(ps.getBatchid());//更改未处理出错数量

    }

    //保存试卷、考号确认扫描结果
    public void saveCommitPaperForConfirm(PaperStudentWebVo pswvo) throws Exception {
        //根据出错id获取errorjson中数据
        EScanerror scanerror = eScanerrorMapper.getErrorJsonById(pswvo.getSerrorid());
        if(N_Utils.isNotEmpty(scanerror.getErrorjson())){
            //出错时扫码的信息，用于保存
            PaperStudentWebVo errorObj = JSON.parseObject(scanerror.getErrorjson(),PaperStudentWebVo.class);
            errorObj.setExamno(pswvo.getExamno());
            errorObj.setSerrorid(pswvo.getSerrorid());
            errorObj.setEpid(pswvo.getEpid());

            //根据学生姓名和准考证号找到对应学生
            Integer userid = userMapper.getUseridByExamno(pswvo.getExamno());
            if (!N_Utils.isTrueInteger(userid)) {
                throw new Exception("考号对应学生不存在");
            }
            //获取学生试卷
            EPaperStudent ps = ePaperStudentMapper.getPaperStudentByStuidAndEpid(pswvo.getEpid(), userid);

            pswvo.setEpsid(ps.getEpsid());
            errorObj.setEpsid(ps.getEpsid());
            String stupic = ps.getStupic();
            if (N_Utils.isNotEmpty(stupic)) {//已经有扫描的信息
                updateScanErrorInfo(3,errorObj);
                updateScanErrorToDuplicate(pswvo, ps);//标记上次扫描结果为考号重复
                return;
            }

            int answerednum = saveScanQuestion(errorObj);//保存扫描试题
            if (!N_Utils.isEmptyInteger(errorObj.getSstate()) && errorObj.getSstate() == 3 && answerednum>0) {//缺考
                updateScanErrorInfo(4, errorObj);
                return;
            }
        }
    }

    //标记上次扫描结果为考号重复
    private void updateScanErrorToDuplicate(PaperStudentWebVo pswvo, EPaperStudent ps) {
        pswvo.setBatchid(ps.getBatchid());
        pswvo.setHasbad(ps.getHasbad());
        pswvo.setPagenum(ps.getPagenum());
        pswvo.setStupic(ps.getStupic());
        List<EPaperStudentQuestion> questions = ePaperStudentMapper.listStuPaperQuestionsForSca(ps.getEpsid());
        pswvo.setQuestions(questions);
        updateScanErrorInfo(3, pswvo);

        //学生试卷重置为未提交
        for (EPaperStudentQuestion question : questions) {
            question.setAnswered(0);
            question.setAnswertype(0);
            question.setStuanswer(null);
            question.setConverted(0);
            question.setAnswertime(null);
            question.setStuscore(0.0);
            question.setChecked(0);
            question.setChecktime(0);
        }
        ePaperStudentQuestionMapper.updateBatchStuQuestion(questions);

        //更新学生试卷扫描信息
        EPaperStudent paperStudent = new EPaperStudent();
        paperStudent.setEpsid(pswvo.getEpsid());
        paperStudent.setStupic(null);
        paperStudent.setSstate(0);
        paperStudent.setStuscore(0.0);
        paperStudent.setBatchid(null);
        paperStudent.setHasbad(0);
        paperStudent.setChecked(0);
        paperStudent.setPagenum(0);
        ePaperStudentMapper.updateScaStudentPaper(paperStudent);
    }

    //保存扫描试题
    private int saveScanQuestion(PaperStudentWebVo pswvo) {
        List<EPaperStudentQuestion> sqlist = pswvo.getQuestions();//学生提交试卷中试题

        //获取试卷中所有试题答案及分值
        List<PsqAnswerVo> anvolist = ePaperStudentQuestionMapper.listPaperQuestionsAnswer(pswvo.getEpsid());
        Integer checknum = 0;//记录试卷中试题批阅数量
        Double paperscore = 0D;//学生试卷得分
        int rtnanswernum = 0;
        for (EPaperStudentQuestion q : sqlist) {
            q.setAnswertype(1);

            //获取该试题正确答案(根据题号区分)
            PsqAnswerVo anvo = anvolist.stream().filter(a -> a.getEptqid().equals(q.getEptqid())).findFirst().orElse(null);

            setCommitQuestion(q, anvo);
            if (q.getChecked() == 2) {
                checknum++;
            }
            q.setEpsqid(anvo.getEpsqid());
            paperscore = ExamUtil.add(paperscore, q.getStuscore());
            if (N_Utils.isObjectiveQuestion(anvo.getCtype()) && q.getAnswered() != null && q.getAnswered() == 1) {
                rtnanswernum++;
            }
        }
        EPaperStudent paperStudent = new EPaperStudent();
        paperStudent.setEpsid(pswvo.getEpsid());
        paperStudent.setStupic(pswvo.getStupic());
        if(!N_Utils.isEmptyInteger(pswvo.getSstate()) && pswvo.getSstate() == 3){
            paperStudent.setSstate(3);
        }else{
            paperStudent.setSstate(2);
        }

        paperStudent.setStuscore(paperscore);
        paperStudent.setBatchid(pswvo.getBatchid());
        if (N_Utils.isEmptyInteger(pswvo.getHasbad())) {
            paperStudent.setHasbad(0);
        } else {
            paperStudent.setHasbad(1);

        }

        int checked = 0;
        if (checknum == sqlist.size()) {
            checked = 2;
        }
        paperStudent.setChecked(checked);
        paperStudent.setPagenum(pswvo.getPagenum());

        ePaperStudentQuestionMapper.updateBatchStuQuestion(sqlist);
        ePaperStudentMapper.updateScaStudentPaper(paperStudent);//更新学生试卷扫描信息
        if(paperStudent.getSstate() == 3){
            eScanbatchMapper.updateQknum(pswvo.getBatchid());//更改缺考数量
        }
        if(paperStudent.getHasbad() == 1){
            eScanbatchMapper.updateWgnum(pswvo.getBatchid());//更改违规数量
        }

        return rtnanswernum;
    }

    //考号重复确认
    @Transactional(rollbackFor = Exception.class)
    public void khcfConfirm(PaperStudentWebVo ps) throws Exception {
        saveCommitPaperForConfirm(ps);//保存试卷、考号确认扫描结果
        eScanerrorMapper.updateErrorState(ps.getSerrorid(), 1);
        eScanbatchMapper.updateErrornum(ps.getBatchid());//更改未处理出错数量
    }

    //缺考确认
    @Transactional(rollbackFor = Exception.class)
    public void qkConfirm(List<PaperStudentWebVo> list) throws Exception {
        List<EPaperStudent> pslist = new ArrayList<>();
        List<Integer> serrorids = list.stream().map(l -> l.getSerrorid()).collect(Collectors.toList());
        List<Integer> batchids = list.stream().map(l -> l.getBatchid()).collect(Collectors.toList());
        //获取扫描错误里面的数据
        List<EScanerror> errorjsonlist = eScanerrorMapper.listErrorObjByIds(serrorids);
        List<EScanerror> updateQklist = new ArrayList<>();
        for (PaperStudentWebVo objvo : list) {
            EScanerror scanerror = errorjsonlist.stream().filter(s -> s.getSerrorid().equals(objvo.getSerrorid())).findFirst().orElse(null);
            if(scanerror!=null){
                PaperStudentWebVo psobj = JSON.parseObject(scanerror.getErrorjson(),PaperStudentWebVo.class);
                EPaperStudent ps = new EPaperStudent();
                ps.setEpsid(psobj.getEpsid());
                ps.setSstate(objvo.getSstate());
                pslist.add(ps);

                EScanerror s = new EScanerror();
                s.setSerrorid(objvo.getSerrorid());
                s.setErrorstate(1);
                s.setQkjg(objvo.getSstate());
                updateQklist.add(s);
            }
        }
        ePaperStudentMapper.batchUpdatePStuState(pslist);
        eScanerrorMapper.batchHandleQkError(updateQklist);//更新缺考记录为已处理
        batchids = batchids.stream().distinct().collect(Collectors.toList());
        eScanbatchMapper.updateBatchErrornum(batchids);//更改异常已处理数量
    }
}
