package com.xhkjedu.sexam.service.paperstudent;

import com.alibaba.fastjson.JSON;
import com.xhkjedu.exception.MissingParametersException;
import com.xhkjedu.sexam.config.ConfigKey;
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.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 com.xhkjedu.vo.ResultVo;
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) {
        int timestamp = N_Utils.getSecondTimestamp();
        String nowtime = N_Utils.getStrtimeTimestamp(timestamp, "yyyy-MM-dd HH:mm");
        return ePaperStudentMapper.listExamPapersForStudent(eps.getStudentid(),nowtime);
    }

    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 学生开始考试
     * @Param [epsid]
     * @Return void
     * @Author wn
     * @Date 2022/11/17 17:43
     **/
    public Integer updatePaperStudentState(Integer epsid){
        Map ssmap = ePaperStudentMapper.getSubjectStateAndSstageByEpsid(epsid);
        Integer pstate = Integer.parseInt(ssmap.get("pstate").toString());
        if(pstate == 2) throw new MissingParametersException("考试已结束禁止操作");

        Integer sstate = Integer.parseInt(ssmap.get("sstate").toString());
        if(sstate >= 2) throw new MissingParametersException("试卷已提交");

        ePaperStudentMapper.updateStuStartime(epsid, N_Utils.getSecondTimestamp());
        Integer esid= (Integer) ssmap.get("esid");
        Integer studentid= (Integer) ssmap.get("studentid");
        Integer endTime = getEndTime(esid, studentid);
        return endTime;
    }

    /**
     * @Description 学生开始考试获取试卷
     * @Param [eps]
     * @Return java.util.Map
     * @Author wn
     * @Date 2022/11/18 19:24
     **/
    public Map startPaperForAndroidNew(EPaperStudent eps) throws Exception {
        Integer epsid = eps.getEpsid();

        Map ssmap = ePaperStudentMapper.getSubjectStateAndSstageByEpsid(epsid);
        Integer pstate = Integer.parseInt(ssmap.get("pstate").toString());
        if(pstate == 2) throw new MissingParametersException("考试已结束禁止操作");

        Integer sstate = Integer.parseInt(ssmap.get("sstate").toString());
        if(sstate >= 2) throw new MissingParametersException("试卷已提交");

        Map rtnmap = new HashMap();
        //获取试卷基本信息
        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);

        Integer ptype = Integer.parseInt(map.get("ptype").toString());
        Integer epid = Integer.parseInt(map.get("epid").toString());
        Integer classid = Integer.parseInt(map.get("classid").toString());

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

        rtnmap.put("paper", map);
        rtnmap.put("questions", questions);
        rtnmap.put("classid",classid);
        return rtnmap;
    }


    /**
     * @Description 开始考试(andorid)
     * @Param [eps]
     * @Return java.util.Map
     * @Author wn
     * @Date 2022/7/27 11:48
     **/
    public Map startPaperForAndroid(EPaperStudent eps) throws Exception {
        Integer epsid = eps.getEpsid();

        Map ssmap = ePaperStudentMapper.getSubjectStateAndSstageByEpsid(epsid);
        Integer pstate = Integer.parseInt(ssmap.get("pstate").toString());
        if(pstate == 2) throw new MissingParametersException("考试已结束禁止操作");

        Integer sstate = Integer.parseInt(ssmap.get("sstate").toString());
        if(sstate >= 2) throw new MissingParametersException("试卷已提交");

        String sdate = ssmap.get("sdate").toString();
        String sbegintime = ssmap.get("begintime").toString();
        int nowstamp = N_Utils.getSecondTimestamp();
        long beginstamp = ExamUtil.getTimestrToTimetamp(sdate + " " + sbegintime + " 00");
        if(nowstamp < beginstamp){
            long diff = (beginstamp - nowstamp)/60;
            if(diff > 5){
                throw new MissingParametersException("未到考试时间，请耐心等待");
            }
        }

        Map rtnmap = new HashMap();
        //获取试卷基本信息
        EPaperStudentVo psvo = ePaperStudentMapper.getExamSubjectByEpsid(epsid);

        Integer ptype = psvo.getPtype();
        Integer epid = psvo.getEpid();
        Integer classid = psvo.getClassid();

        List<Map> questions = null;
        if (ptype == 1) {
            //题库试卷试题
            questions = ePaperStudentMapper.listStuPaperQuestionsForAndroid(epsid);
        } else {
            questions = ePaperStudentMapper.listStuPaperFjQuestionsForAndroid(epsid);
        }
        if (ptype == 2) {
            List<Map> files = ePaperFileMapper.listPaperStemFile(epid);
            psvo.setFiles(files);
        }
        ePaperStudentMapper.updateStuStartime(epsid, N_Utils.getSecondTimestamp());

        rtnmap.put("paper", psvo);
        rtnmap.put("questions", questions);
        rtnmap.put("classid",classid);
        return rtnmap;
    }

    /**
     * @Description 获取考试状态
     * @Param [epsid]
     * @Return java.lang.Integer
     * @Author wn
     **/
    public Integer getExamstateSubjectState(Integer epsid){
        Integer rtnresult = 1;
        Map mapstate = ePaperStudentMapper.getExamStateSubjectStateByEpsid(epsid);
        Integer pstate = Integer.parseInt(mapstate.get("pstate").toString());
        String begintime = mapstate.get("begintime").toString();
        String sdate = mapstate.get("sdate").toString();
        if(pstate == 2){
            rtnresult = 2;//考试已结束
        }else{
            String beginstr = sdate + " " + begintime + ":00";
            long beginstamp = ExamUtil.getTimestrToTimetamp(beginstr);//考试开始时间
            Integer timestamp = N_Utils.getSecondTimestamp();//当前时间
            if(timestamp < beginstamp){
                long diff=(beginstamp - timestamp)/60;
                if(diff>5){
                    //可以提前5分钟进场
                    rtnresult = 3;//还未到时间
                }
            }else{
                long diff=(timestamp-beginstamp)/60;
                if(diff > 15){
                    rtnresult = 4;//超过15分钟禁止进入
                }
            }
        }

        return rtnresult;
    }

    /**
     * @Description 开始考试（web）
     * @Param [eps]
     * @Return java.util.List<java.util.Map>
     * @Author wn
     * @Date 2022/7/27 15:36
     **/
    public Map startPaperForWeb(EPaperStudent eps) throws Exception {
        Integer epsid = eps.getEpsid();
        Map ssmap = ePaperStudentMapper.getSubjectStateAndSstageByEpsid(epsid);
        Integer pstate = Integer.parseInt(ssmap.get("pstate").toString());
        if(pstate == 2) throw new MissingParametersException("考试已结束禁止操作");

        Integer sstate = Integer.parseInt(ssmap.get("sstate").toString());
        if(sstate >= 2) throw new MissingParametersException("试卷已提交");

        String sdate = ssmap.get("sdate").toString();
        String sbegintime = ssmap.get("begintime").toString();
        int nowstamp = N_Utils.getSecondTimestamp();
        long beginstamp = ExamUtil.getTimestrToTimetamp(sdate + " " + sbegintime + ":00");
        if(nowstamp < beginstamp){
            long diff = beginstamp - nowstamp;
            if(diff > 300){
                throw new MissingParametersException("未到考试时间，请耐心等待");
            }
        }

        //获取试卷基本信息
//        EPaperStudentVo psvo = ePaperStudentMapper.getExamSubjectByEpsid(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);

        Integer ptype = Integer.parseInt(map.get("ptype").toString());
        Integer epid = Integer.parseInt(map.get("epid").toString());

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

        if (ptype == 2) {
            List<Map> files = ePaperFileMapper.listPaperStemFile(epid);
            map.put("files",files);
        }
        map.put("qtypelist",questions);
        return map;
    }

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

            /*//2022年10月27日提交单题不再进行判断
            Map mapstate = ePaperStudentMapper.getExamStateSubjectStateByEpsid(answerVo.getEpsid());
            Integer examstate = Integer.parseInt(mapstate.get("examstate").toString());
            Integer pstate = Integer.parseInt(mapstate.get("pstate").toString());
            if(examstate >= 2 || pstate == 2) throw new MissingParametersException("考试已结束禁止操作");*/
        setCommitQuestion(psq, answerVo);
        if(N_Utils.isTrueInteger(psq.getAnswered())){
            ePaperStudentQuestionMapper.updateStuAnswer(psq);
        }
    }

    //判断单道题情况
    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();
        String stuanswertxt = psq.getStuanswertxt();
        Double stuscore = 0D;
        if (N_Utils.isEmpty(stuanswer) && N_Utils.isEmpty(stuanswertxt)
                && N_Utils.isListEmpty(JSON.parseArray(stuanswer, String.class))
                && N_Utils.isListEmpty(JSON.parseArray(stuanswertxt, String.class))) {
            psq.setAnswered(0);
            psq.setStuanswer(null);
            psq.setStuanswertxt(null);
            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 {
                    if(N_Utils.isNotEmpty(stuanswertxt)){
                        List<String> stuanswertxt_list = JSON.parseArray(stuanswertxt,String.class);
                        String stuanswertxt_txt = stuanswertxt_list.get(0);
                        if(N_Utils.isNotEmpty(stuanswertxt_txt)){
                            stuanswertxt_txt = N_Utils.strTrim(stuanswertxt_txt);
                            if(N_Utils.isNotEmpty(stuanswertxt_txt)){
                                psq.setChecked(0);
                                List<String> stuanswertxt_list_new = new ArrayList<>();
                                stuanswertxt_list_new.add(stuanswertxt_txt);
                                psq.setStuanswertxt(JSON.toJSONString(stuanswertxt_list_new));
                            }else{
                                psq.setChecked(2);
                                psq.setStuanswertxt("[\"\"]");
                            }
                        }else{
                            psq.setChecked(2);
                            psq.setStuanswertxt("[\"\"]");
                        }
                    }else{
                        psq.setChecked(2);
                    }
                }
            } 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 ResultVo saveCommitPaper(EPaperStudent paperStudent){
       /* Integer examstate = ePaperStudentMapper.getExamStateByEpsId(epsid);
        if (2 <= examstate) throw new MissingParametersException("考试已结束禁止操作");*/
        Integer epsid = paperStudent.getEpsid();
        Integer pstate = ePaperStudentMapper.getSubjectStateByEpsid(epsid);
        if(pstate == 2){
            return new ResultVo(0,"考试已结束");
        }
        /*EPaperStudent ps = ePaperStudentMapper.selectByPrimaryKey(epsid);
        if (ps == null || ps.getSstate() == 2) {
            return new ResultVo(0,"试卷已提交");
        }*/
        paperStudent.setSstate(2);
        int timestamp = N_Utils.getSecondTimestamp();
        paperStudent.setEndtime(timestamp);

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

    //处理试卷中未已提交需要合并的图片,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);
                }
            }
        }
    }

    /*
     * 合并学生答案
     * @Param []
     * @Author ywx
     * @Date 2022/11/12 17:34
     * @return void
     **/
    public void paperStuQuestionAnswerMerge() {
        //获取试卷中未合并图片
        List<EPaperStudentQuestion> list = ePaperStudentQuestionMapper.listNoMergeUserAnswer();
        if (N_Utils.isListEmpty(list)) return;
        List<Integer> examids = list.stream().map(s -> s.getExamid()).distinct().collect(Collectors.toList());
        List<Map> exams = ePaperStudentQuestionMapper.listExamByIds(examids);//获取未合并图片考试模式列表
        Map<Integer, Integer> emap = exams.stream().collect(Collectors.toMap(e -> (Integer) e.get("examid")
                , e -> (Integer) e.get("exammode")));
        if (N_Utils.isListNotEmpty(list)) {
            for (EPaperStudentQuestion sq : list) {
                List<String> stuanswer = JSON.parseArray(sq.getStuanswer(), String.class);
                if (N_Utils.isListNotEmpty(stuanswer) && stuanswer.size() > 1) {
                    convertUtil.imgMerge(sq.getEpsqid(), stuanswer, emap.get(sq.getExamid()));
                }
            }
        }
    }

    /**
     * @Description 网页端提交试题
     * @Param [pswvo]
     * @Return com.xhkjedu.vo.ResultVo
     * @Author wn
     * @Date 2022/11/23 14:43
     **/
    public ResultVo saveCommitQuestionForWeb(PaperStudentWebVo pswvo) {
        List<EPaperStudentQuestion> sqlist = pswvo.getQuestions();//学生提交试卷中试题
        //获取试卷中所有试题答案及分值
        List<PsqAnswerVo> anvolist = ePaperStudentQuestionMapper.listPaperQuestionsAnswer(pswvo.getEpsid());
        Integer checknum = 0;//记录试卷中试题批阅数量
        Double paperscore = 0D;//学生试卷得分
        List<EPaperStudentQuestion> saveQlist = new ArrayList<>();//提交有值试题
        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());

            if(N_Utils.isTrueInteger(q.getAnswered())){
                saveQlist.add(q);
            }
        }
        EPaperStudent paperStudent = new EPaperStudent();
        paperStudent.setEpsid(pswvo.getEpsid());
        int timestamp = N_Utils.getSecondTimestamp();
        paperStudent.setEndtime(timestamp);
        paperStudent.setSstate(2);
        paperStudent.setStuscore(paperscore);
        paperStudent.setDevice(pswvo.getDevice());
        paperStudent.setSubmittype(pswvo.getSubmittype());
        if(N_Utils.isTrueInteger(pswvo.getCosttime())){
            paperStudent.setCosttime(pswvo.getCosttime());
        }else{
            paperStudent.setCosttime(0);
        }

        int checked = 0;
        if (checknum == saveQlist.size()) {
            checked = 2;
        }
        paperStudent.setChecked(checked);
        if(N_Utils.isListNotEmpty(saveQlist)){
            ePaperStudentQuestionMapper.updateBatchStuQuestion(saveQlist);
        }
        return new ResultVo(0,"提交成功");
    }

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

            if(N_Utils.isTrueInteger(q.getAnswered())){
                saveQlist.add(q);
            }else{
                saveCheckedlist.add(q);
            }
        }
        EPaperStudent paperStudent = new EPaperStudent();
        paperStudent.setEpsid(pswvo.getEpsid());
        int timestamp = N_Utils.getSecondTimestamp();
        paperStudent.setEndtime(timestamp);
        paperStudent.setSstate(2);
        paperStudent.setStuscore(paperscore);
        paperStudent.setDevice(pswvo.getDevice());
        paperStudent.setSubmittype(pswvo.getSubmittype());
        if(N_Utils.isTrueInteger(pswvo.getCosttime())){
            paperStudent.setCosttime(pswvo.getCosttime());
        }else{
            paperStudent.setCosttime(0);
        }

        int checked = 0;
        if (checknum == saveQlist.size()) {
            checked = 2;
        }
        paperStudent.setChecked(checked);
        if(N_Utils.isListNotEmpty(saveQlist)){
            ePaperStudentQuestionMapper.updateBatchStuQuestion(saveQlist);
        }
        if(N_Utils.isListNotEmpty(saveCheckedlist)){
            //改未提交试题的批改状态
            ePaperStudentQuestionMapper.updateStuQuesitonNoCommit(pswvo.getEpsid(), timestamp);
        }

        ePaperStudentMapper.updateStudentPaper(paperStudent);

        //获取试卷中需要合并图片的试题
        chandleStudentQuestionNoconvertedPic(pswvo.getEpsid(), 1);
        return new ResultVo(0,"提交成功");
    }

    /**
     * @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(answerednum == -1){
            //扫描的试题数量和实际的试题数量不相等
            updateScanErrorInfo(1, 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("考试已结束禁止操作");*/
        Integer pstate = ePaperStudentMapper.getSubjectStateByEpsid(epsid);
        if(pstate == 2) 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());
        int rtnanswernum = 0;
        if(sqlist.size() != anvolist.size()){
            return -1;
        }

        Integer checknum = 0;//记录试卷中试题批阅数量
        Double paperscore = 0D;//学生试卷得分
        List<EPaperStudentQuestion> saveQlist = new ArrayList<>();//提交有值试题
        List<EPaperStudentQuestion> saveCheckedlist = new ArrayList<>();//提交无值需要自动批改试题

        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++;
            }

            if(N_Utils.isTrueInteger(q.getAnswered())){
                saveQlist.add(q);
            }else{
                saveCheckedlist.add(q);
            }
        }
        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());

        if(N_Utils.isListNotEmpty(saveQlist)){
            ePaperStudentQuestionMapper.updateBatchStuQuestion(saveQlist);
        }
        if(N_Utils.isListNotEmpty(saveCheckedlist)){
            int timestamp = N_Utils.getSecondTimestamp();
            //改未提交试题的批改状态
            ePaperStudentQuestionMapper.updateStuQuesitonNoCommit(pswvo.getEpsid(), timestamp);
        }

        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);//更改异常已处理数量
    }

    /*
     * 定时更新学生考试状态
     * @Param [esids(考试科目ids), cs(执行的次数), stime(隔几毫秒执行一次)]
     * @Author ywx
     * @Date 2022/11/9 19:02
     * @return java.lang.Integer
     **/
    public Integer update(String esids, Integer cs, Integer stime) {
        Integer num = 0;
        try {
            if (N_Utils.isEmpty(esids)) {
                int timestamp = N_Utils.getSecondTimestamp();
                String strtime = N_Utils.getStrtimeTimestamp(timestamp, "yyyy-MM-dd");
                List<Map> list = ePaperStudentMapper.listExam(strtime);
                esids = list.stream().map(s -> s.get("esid").toString()).collect(Collectors.joining(","));
                log.info(JSON.toJSONString(list));
            }
            if (N_Utils.isEmpty(esids)) return 0;
            for (int i = 0; i < cs; i++) {
                Integer unum = ePaperStudentMapper.updateSstateByEsIds(esids);
                num += unum;
                log.error("本次更新:【" + unum + "】条");
                Thread.sleep(stime);
            }
            log.error("共更新:【" + num + "】条");
        } catch (InterruptedException e) {
            log.error("定时更新学生考试状态出错", e.getMessage());
        }
        return num;
    }

    //获取考试剩余时间（秒）
    public Integer getEndTime(Integer esid, Integer studentid) {
        EPaperStudent ps = ePaperStudentMapper.getEndTime(esid, studentid);
        if (ps == null) throw new MissingParametersException("考试不存在");
        double mul = ExamUtil.mul(ConfigKey.endtime, ps.getScore());
        long endtime = ExamUtil.strToTimestamp(ps.getDevice());
        Double timestamp = Math.floor(ExamUtil.add(endtime, mul));
        Double sub = ExamUtil.sub(timestamp, N_Utils.getSecondTimestamp());//结束时间戳-当前时间戳
        int subtime = sub.intValue();
        if (subtime < 0) subtime = 0;
        return subtime;
    }
}
