package cn.com.qmth.examcloud.core.questions.service;

import java.io.File;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
import org.springframework.stereotype.Service;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;

import cn.com.qmth.examcloud.api.commons.security.bean.User;
import cn.com.qmth.examcloud.core.questions.base.CommonUtils;
import cn.com.qmth.examcloud.core.questions.base.converter.utils.FileUtil;
import cn.com.qmth.examcloud.core.questions.base.enums.PaperStatus;
import cn.com.qmth.examcloud.core.questions.base.enums.PaperType;
import cn.com.qmth.examcloud.core.questions.base.enums.QuesUnit;
import cn.com.qmth.examcloud.core.questions.base.exception.PaperException;
import cn.com.qmth.examcloud.core.questions.base.json.JsonImportUtil;
import cn.com.qmth.examcloud.core.questions.base.json.SectionElement;
import cn.com.qmth.examcloud.core.questions.base.question.enums.QuesStructType;
import cn.com.qmth.examcloud.core.questions.dao.CoursePropertyRepo;
import cn.com.qmth.examcloud.core.questions.dao.PaperDetailRepo;
import cn.com.qmth.examcloud.core.questions.dao.PaperDetailUnitRepo;
import cn.com.qmth.examcloud.core.questions.dao.PaperRepo;
import cn.com.qmth.examcloud.core.questions.dao.PropertyRepo;
import cn.com.qmth.examcloud.core.questions.dao.QuesRepo;
import cn.com.qmth.examcloud.core.questions.dao.entity.Course;
import cn.com.qmth.examcloud.core.questions.dao.entity.CourseProperty;
import cn.com.qmth.examcloud.core.questions.dao.entity.ImportPaperCheck;
import cn.com.qmth.examcloud.core.questions.dao.entity.ImportPaperMsg;
import cn.com.qmth.examcloud.core.questions.dao.entity.Paper;
import cn.com.qmth.examcloud.core.questions.dao.entity.PaperDetail;
import cn.com.qmth.examcloud.core.questions.dao.entity.PaperDetailUnit;
import cn.com.qmth.examcloud.core.questions.dao.entity.Property;
import cn.com.qmth.examcloud.core.questions.dao.entity.QuesOption;
import cn.com.qmth.examcloud.core.questions.dao.entity.QuesProperty;
import cn.com.qmth.examcloud.core.questions.dao.entity.Question;
import cn.com.qmth.examcloud.core.questions.service.impl.CourseService;

@Service
public class ImportPaperFromJsonService {


    @Autowired
    private PaperRepo paperRepo;

    @Autowired
    private PaperDetailRepo paperDetailRepo;

    @Autowired
    private PaperDetailUnitRepo paperDetailUnitRepo;

    @Autowired
    private QuesRepo quesRepo;

    @Autowired
    private PaperService paperService;

    @Autowired
    private CourseService courseService;

    @Autowired
    private QuesTypeNameService quesTypeNameService;

    @Autowired
    private CoursePropertyRepo coursePropertyRepo;

    @Autowired
    private PropertyRepo propertyRepo;

    /**
     * 保存导入试卷信息
     *
     * @param paper
     * @param paperDetails
     * @param paperDetailUnits
     * @param importPaperCheck
     * @throws PaperException
     */
    private Paper savePaper(Paper paper, List<PaperDetail> paperDetails, List<PaperDetailUnit> paperDetailUnits,
            List<Question> questions, ImportPaperCheck importPaperCheck) throws Exception {
        Paper tempPaper = null;
        if (!StringUtils.isEmpty(importPaperCheck.getErrorInfo()))
            return null;
        if (paper != null) {
            // 总分校验
            checkTotalScore(paper, paperDetailUnits, importPaperCheck);
            // 大题下小题数量校验
            checkUnitNum(paperDetailUnits, importPaperCheck);
            // 校验答案是否不全
            checkAnswerISfull(paperDetailUnits, importPaperCheck);
            // 如果合并相同的大题
            if (paper.getSameName().equals("1")) {
                paperDetails = mergePaperDetails(paperDetails, paperDetailUnits);
            }
            tempPaper = paperRepo.save(paper);
        }
        if (paperDetails != null && paperDetails.size() > 0) {
            paperDetailRepo.saveAll(paperDetails);
        }
        if (questions != null && questions.size() > 0) {
            for (Question question : questions) {
                String now = CommonUtils.getCurDateTime();
                question.setCreateTime(now);
            }
            quesRepo.saveAll(questions);
        }
        if (paperDetailUnits.size() > 0) {
            paperDetailUnitRepo.saveAll(paperDetailUnits);
            quesTypeNameService.saveQuesTypeName(paperDetailUnits);
        }
        paperService.formatPaper(tempPaper, null);
        return tempPaper;
    }

    /**
     * 合并相同大题
     *
     * @param paperDetails
     * @param paperDetailUnits
     * @return
     */
    private List<PaperDetail> mergePaperDetails(List<PaperDetail> paperDetails,
            List<PaperDetailUnit> paperDetailUnits) {
        List<PaperDetail> mergePaperDetails = new ArrayList<>();
        Set<String> set = new HashSet<>();
        for (PaperDetail paperDetail : paperDetails) {
            if (set.add(paperDetail.getName())) {
                mergePaperDetails.add(paperDetail);
            }
        }
        for (PaperDetail mergePaperDetail : mergePaperDetails) {
            for (PaperDetailUnit mergePaperDetailUnit : paperDetailUnits) {
                if (mergePaperDetailUnit.getPaperDetail().getName().equals(mergePaperDetail.getName())) {
                    mergePaperDetailUnit.setPaperDetail(mergePaperDetail);
                }
            }
        }
        return mergePaperDetails;
    }

    /**
     * 清空试卷对象,加速回收
     */
    private void clearPaper(List<PaperDetail> paperDetails, List<PaperDetailUnit> paperDetailUnits,
            List<Question> questions) {
        paperDetails.clear();
        paperDetailUnits.clear();
        questions.clear();
    }

    /**
     * 处理导入试卷
     *
     * @param paper
     * @param user
     * @param file
     * @return
     * @throws Exception
     */

    public Paper processImportPaper(Paper paper, User user, File file) throws Exception {
        try {
            String fileContent = FileUtil.readFileContent(file);
            if (StringUtils.isEmpty(fileContent)) {
                throw new PaperException("文件内容为空");
            }
            Gson gson = new Gson();
            List<List<SectionElement>> pList = gson.fromJson(fileContent, new TypeToken<List<List<SectionElement>>>() {
            }.getType());
            // 得到前台的课程代码
            String courseNo = paper.getCourseNo();
            ImportPaperCheck importPaperCheck = new ImportPaperCheck();
            // 设置试卷
            initPaper(paper, paper.getName(), user);
            // 创建空大题类
            PaperDetail paperDetail = null;
            // 创建大题集合
            List<PaperDetail> paperDetails = new ArrayList<>();
            // 创建小题集合
            List<PaperDetailUnit> paperDetailUnits = new ArrayList<>();
            // 创建试题集合
            List<Question> questions = new ArrayList<>();
            // 大题号
            int mainQuesNum = 0;
            // 小题号
            int subQuesNum = 0;
            // 大题下的小题序号
            int errorQuesNum = 0;
            for (int i = 0; i < pList.size(); i++) {
                List<SectionElement> p = pList.get(i);
                String pText = JsonImportUtil.getPText(p);
                if (StringUtils.isEmpty(pText)) {
                    // 跳过空白段落
                    continue;
                } else if (isMainQuesHeader(pText)) {
                    // 处理大题头信息
                    processMainQuesHeader(pList, importPaperCheck.getIndex(), importPaperCheck, courseNo);
                    // 校验大题头信息
                    if (!checkQuesHeader(importPaperCheck)) {
                        throw new PaperException(importPaperCheck.getErrorInfo());
                    }
                    // 创建大题类
                    paperDetail = new PaperDetail();
                    // 设置大题类
                    initQuesHeader(paper, paperDetail, paperDetails, ++mainQuesNum, importPaperCheck);
                    // 设置当前索引,防止多余循环
                    i = importPaperCheck.getIndex() - 1;
                    errorQuesNum = 0;
                } else if ((pText.matches("^\\d{1,}\\.[\\s\\S]*") && !pText.startsWith(ImportPaperMsg.left_bracket))
                        || (isNested(importPaperCheck) && pText.startsWith(ImportPaperMsg.nestedQuestion_start))) {
                    if (paperDetail == null) {
                        throw new PaperException("导入文件格式有误,必须有大题头信息,且以 [ 开头!");
                    }
                    ++errorQuesNum;
                    ++subQuesNum;
                    // 处理试题
                    // 创建小题类和试题类
                    PaperDetailUnit paperDetailUnit = new PaperDetailUnit();
                    Question question = new Question();
                    // 初始化小题类和试题类
                    initPaperDetail(paper, paperDetail, paperDetailUnit, question, subQuesNum, importPaperCheck);
                    // 处理客观题
                    if (importPaperCheck.getQuesType().equals(ImportPaperMsg.singleSelection)
                            || importPaperCheck.getQuesType().equals(ImportPaperMsg.multipleSelection)) {
                        // 处理题干
                        processQuesBody(pList, importPaperCheck.getIndex(), subQuesNum, question, importPaperCheck,
                                errorQuesNum);
                        // 处理选项
                        processQuesOption(pList, importPaperCheck.getIndex(), subQuesNum, question, importPaperCheck,
                                errorQuesNum);
                        // 处理尾信息
                        processQuesTail(pList, importPaperCheck.getIndex(), subQuesNum, question, paperDetailUnit,
                                importPaperCheck, false, paper, errorQuesNum);
                        // 处理选择题的option
                        processSelectOption(question);
                    } else if (importPaperCheck.getQuesType().equals(ImportPaperMsg.nestedQuestion_word)) {
                        // 处理套题
                        processNestedQues(pList, importPaperCheck.getIndex(), question, paperDetailUnit,
                                importPaperCheck, paper);
                    } else {
                        // 处理其他题型
                        processQuesBody(pList, importPaperCheck.getIndex(), subQuesNum, question, importPaperCheck,
                                errorQuesNum);
                        processQuesTail(pList, importPaperCheck.getIndex(), subQuesNum, question, paperDetailUnit,
                                importPaperCheck, false, paper, errorQuesNum);
                        // 填空题空格校验
                        if (question.getQuestionType().getName().equals(QuesStructType.FILL_BLANK_QUESTION.getName())) {
                            if (!StringUtils.isBlank(question.getQuesAnswer())) {
                                processFill(question, paperDetailUnit, importPaperCheck, subQuesNum, errorQuesNum);
                            }
                        }
                    }
                    question.setQuesPkgPathId(null);
                    // 设置question与Unit集合数据
                    question.setCourse(paper.getCourse());
                    question.setOrgId(user.getRootOrgId().toString());
                    questions.add(question);
                    paperDetailUnits.add(paperDetailUnit);
                    // 设置当前索引,防止多余循环
                    i = importPaperCheck.getIndex() - 1;
                } else if (paperDetail == null) {
                    throw new PaperException("导入文件格式有误,必须有大题头信息,且以[试题分类]开头!");
                } else {
                    String errorMsg = pText.length() > 10 ? pText.substring(0, 10) : pText;
                    if (pText.startsWith(ImportPaperMsg.left_bracket)) {
                        throw new PaperException(
                                errorMsg + "，标签格式不正确！正确标签格式：[套题]、[套题数量]、[小题分数]、[答案]、[难度]、[一级属性]、[二级属性]、[公开度]、[小题型]");
                    }
                    throw new PaperException(
                            importPaperCheck.getQuesName() + "：“" + errorMsg + "”" + ImportPaperMsg.errMsg_12);
                }
                if (!StringUtils.isEmpty(importPaperCheck.getErrorInfo())) {
                    throw new PaperException(importPaperCheck.getErrorInfo());
                }
            }
            if (paperDetails.size() == 0 || paperDetailUnits.size() == 0) {
                throw new PaperException("导入文件格式有误!");
            }
            paper.setPaperDetailCount(mainQuesNum);
            // 保存导入试卷信息
            paper = savePaper(paper, paperDetails, paperDetailUnits, questions, importPaperCheck);
            clearPaper(paperDetails, paperDetailUnits, questions);
        } finally {
            FileUtils.deleteQuietly(file);
        }
        return paper;
    }

    private boolean isMainQuesHeader(String pText) {
        /*
         * return pText.startsWith(ImportPaperMsg.left_bracket) &&
         * !pText.startsWith(ImportPaperMsg.answer_word) &&
         * !pText.startsWith(ImportPaperMsg.score_word) &&
         * !pText.startsWith(ImportPaperMsg.subQuestionType_word) &&
         * !pText.startsWith(ImportPaperMsg.nestedQuestion_start) &&
         * !pText.startsWith(ImportPaperMsg.nestedQuestion_number);
         */
        return pText.startsWith(ImportPaperMsg.questionClassify_word)
                || pText.startsWith(ImportPaperMsg.questionType_word)
                || pText.startsWith(ImportPaperMsg.questionName_word)
                || pText.startsWith(ImportPaperMsg.questionNum_word) || pText.startsWith(ImportPaperMsg.score_word);
    }

    private boolean isHeader(String pText) {
        return pText.startsWith(ImportPaperMsg.questionClassify_word)
                || pText.startsWith(ImportPaperMsg.questionType_word)
                || pText.startsWith(ImportPaperMsg.questionName_word)
                || pText.startsWith(ImportPaperMsg.questionNum_word) || pText.startsWith(ImportPaperMsg.score_word)
                || pText.startsWith(ImportPaperMsg.answer_word) || pText.startsWith(ImportPaperMsg.subQuestionType_word)
                || pText.startsWith(ImportPaperMsg.subQuesScore_word)
                || pText.startsWith(ImportPaperMsg.nestedQuestion_start)
                || pText.startsWith(ImportPaperMsg.nestedQuestion_number)
                || pText.startsWith(ImportPaperMsg.left_bracket);
    }

    /**
     * 初始化试卷信息
     *
     * @param paper
     * @param paperName
     * @param user
     */
    private void initPaper(Paper paper, String paperName, User user) {
        paper.setName(paperName);
        paper.setTitle(paperName);
        paper.setPaperType(PaperType.IMPORT);
        paper.setPaperStatus(PaperStatus.DRAFT);
        paper.setOrgId(user.getRootOrgId().toString());
        paper.setCreator(user.getDisplayName());
        Course course = courseService.getCourse(user.getRootOrgId(), paper.getCourseNo());
        paper.setCourse(course);
        paper.setCourseName(course.getName());
        paper.setCreateTime(CommonUtils.getCurDateTime());
    }

    /**
     * 初始化大题头信息
     *
     * @param paper
     * @param paperDetail
     * @param paperDetails
     * @param mainQuesNum
     * @param importPaperCheck
     */
    private void initQuesHeader(Paper paper, PaperDetail paperDetail, List<PaperDetail> paperDetails, int mainQuesNum,
            ImportPaperCheck importPaperCheck) {

        paperDetail.setPaper(paper);
        // 设置大题信息
        paperDetail.setName(importPaperCheck.getQuesName());
        paperDetail.setUnitCount(Integer.parseInt(importPaperCheck.getQuesCount()));
        paperDetail.setNumber(mainQuesNum);
        paperDetail.setCreator(paper.getCreator());
        paperDetails.add(paperDetail);

    }

    /**
     * 初始化试卷明细和试题
     *
     * @param paperDetail
     * @param paperDetailUnit
     * @param question
     * @param subQuesNum
     * @param importPaperCheck
     */
    private void initPaperDetail(Paper paper, PaperDetail paperDetail, PaperDetailUnit paperDetailUnit,
            Question question, int subQuesNum, ImportPaperCheck importPaperCheck) {

        // 重置importPaperCheck
        importPaperCheck.setNestedHeadNumber(0);
        question.setQuestionType(getQuesStructType(importPaperCheck.getQuesType()));
        question.setScore(Double.parseDouble(importPaperCheck.getQuesScore()));
        paperDetailUnit.setNumber(subQuesNum);
        paperDetailUnit.setQuestion(question);
        paperDetailUnit.setPaperDetail(paperDetail);
        paperDetailUnit.setQuestionType(getQuesStructType(importPaperCheck.getQuesType()));
        paperDetailUnit.setScore(Double.parseDouble(importPaperCheck.getQuesScore()));
        paperDetailUnit.setCreator(paper.getCreator());
        paperDetailUnit.setPaper(paper);
        paperDetailUnit.setPaperType(PaperType.IMPORT);
    }

    /**
     * 校验试题头标识
     *
     * @param importPaperCheck
     * @return
     */
    private boolean checkQuesHeader(ImportPaperCheck importPaperCheck) {

        String tmpErrorInfo = "";
        if (StringUtils.isEmpty(importPaperCheck.getQuesGroup())) {
            tmpErrorInfo += ImportPaperMsg.errMsg_04;

        }
        if (StringUtils.isEmpty(importPaperCheck.getQuesType())) {
            tmpErrorInfo += ImportPaperMsg.errMsg_05;

        }
        if (StringUtils.isEmpty(importPaperCheck.getQuesName())) {
            tmpErrorInfo += ImportPaperMsg.errMsg_06;

        }
        if (StringUtils.isEmpty(importPaperCheck.getQuesCount())) {
            tmpErrorInfo += ImportPaperMsg.errMsg_07;

        }
        if (StringUtils.isEmpty(importPaperCheck.getQuesScore())) {
            tmpErrorInfo += ImportPaperMsg.errMsg_08;
        }
        if (!StringUtils.isEmpty(importPaperCheck.getQuesType())
                && !CommonUtils.checkQuesType(importPaperCheck.getQuesType())) {
            tmpErrorInfo += ImportPaperMsg.errMsg_09;
        }
        if (StringUtils.isEmpty(tmpErrorInfo)) {
            return true;
        } else {
            importPaperCheck.setErrorInfo(tmpErrorInfo);
            return false;
        }
    }

    /**
     * 处理大题头信息
     *
     * @param pList
     * @param index
     * @param importPaperCheck
     * @throws PaperException
     */
    private void processMainQuesHeader(List<List<SectionElement>> pList, int index, ImportPaperCheck importPaperCheck,
            String courseNo) throws PaperException {
        int i = 0;
        for (i = index; i < pList.size(); i++) {
            List<SectionElement> pFirst = pList.get(i);
            String tmpTextFirst = JsonImportUtil.getPText(pFirst);
            if (StringUtils.isBlank(tmpTextFirst)) {
                continue;
            }
            if (!tmpTextFirst.startsWith(ImportPaperMsg.questionClassify_word)) {
                throw new PaperException("导入文件格式有误,必须有大题头信息,且以[试题分类]开头!");
            }
            break;
        }
        for (i = index; i < pList.size(); i++) {
            List<SectionElement> pHeader = pList.get(i);
            List<SectionElement> pNextHeader = pList.get(i + 1);
            String tmpText = JsonImportUtil.getPText(pHeader);
            String nextTmpText = JsonImportUtil.getPText(pNextHeader);
            if (tmpText.startsWith(ImportPaperMsg.questionClassify_word)) {
                if (!nextTmpText.startsWith(ImportPaperMsg.questionType_word)) {
                    importPaperCheck.setErrorInfo("[试题分类]的下一题头应该是[题型],当前读到的信息为:“" + nextTmpText + "”,请检查word中格式问题");
                    throw new PaperException(importPaperCheck.getErrorInfo());
                }
                List<String> paperList = Stream.of(tmpText.split("_")).collect(Collectors.toList());
                // 获取[试题分类]中的课程代码
                if (paperList.size() != 2) {
                    importPaperCheck.setErrorInfo("[试题分类]的格式不正确或者是内容为空");
                    throw new PaperException(importPaperCheck.getErrorInfo());
                }
                String impCourseCode = paperList.get(1);
                if (!courseNo.equals(impCourseCode)) {
                    importPaperCheck.setErrorInfo("[试题分类]中的课程代码与指定的课程代码不一样，当前读到的信息为:“" + tmpText + "”,请检查word中格式问题");
                    throw new PaperException(importPaperCheck.getErrorInfo());
                }
                importPaperCheck.setQuesGroup(getContent(tmpText, ImportPaperMsg.questionClassify_word));
            } else if (tmpText.startsWith(ImportPaperMsg.questionType_word)) {
                if (!nextTmpText.startsWith(ImportPaperMsg.questionName_word)) {
                    importPaperCheck.setErrorInfo("[题型]的下一题头应该是[大题名称],当前读到的信息为:“" + nextTmpText + "”,请检查word中格式问题");
                    throw new PaperException(importPaperCheck.getErrorInfo());
                }
                importPaperCheck.setQuesType(getContent(tmpText, ImportPaperMsg.questionType_word));
            } else if (tmpText.startsWith(ImportPaperMsg.questionName_word)) {
                if (!nextTmpText.startsWith(ImportPaperMsg.questionNum_word)) {
                    importPaperCheck.setErrorInfo("[大题名称]的下一题头应该是[题目数量],当前读到的信息为:“" + nextTmpText + "”,请检查word中格式问题");
                    throw new PaperException(importPaperCheck.getErrorInfo());
                }
                importPaperCheck.setQuesName(getContent(tmpText, ImportPaperMsg.questionName_word));
            } else if (tmpText.startsWith(ImportPaperMsg.questionNum_word)) {
                if (!CommonUtils.isInteger(getContent(tmpText, ImportPaperMsg.questionNum_word))) {
                    importPaperCheck.setErrorInfo("[题目数量]的格式不正确");
                    throw new PaperException(importPaperCheck.getErrorInfo());
                }
                if (!nextTmpText.startsWith(ImportPaperMsg.score_word)) {
                    importPaperCheck.setErrorInfo("[题目数量]的下一题头应该是[分数],当前读到的信息为:“" + nextTmpText + "”,请检查word中格式问题");
                    throw new PaperException(importPaperCheck.getErrorInfo());
                }
                importPaperCheck.setQuesCount(getContent(tmpText, ImportPaperMsg.questionNum_word));
            } else if (tmpText.startsWith(ImportPaperMsg.score_word)) {
                if (!CommonUtils.isInteger(getContent(tmpText, ImportPaperMsg.score_word))) {
                    importPaperCheck.setErrorInfo("[分数]的格式不正确");
                    throw new PaperException(importPaperCheck.getErrorInfo());
                }
                importPaperCheck.setQuesScore(getContent(tmpText, ImportPaperMsg.score_word));
            } else if (StringUtils.isEmpty(tmpText)) {
                continue;
            } else {
                break;
            }
        }
        importPaperCheck.setIndex(i);
    }

    /**
     * 处理套题的头信息
     *
     * @param pList
     * @param index
     * @param subQuesNum
     * @param question
     * @param importPaperCheck
     * @throws Exception
     */
    private void processNestedQuestionHead(List<List<SectionElement>> pList, int index, int subQuesNum,
            Question question, ImportPaperCheck importPaperCheck, PaperDetailUnit paperDetailUnit) throws Exception {
        int i = 0;
        for (i = index; i < pList.size(); i++) {
            List<SectionElement> pHeader = pList.get(i);
            List<SectionElement> pNextHeader = pList.get(i + 1);
            String tmpText = JsonImportUtil.getPText(pHeader);
            String nextTmpText = JsonImportUtil.getPText(pNextHeader);
            if (StringUtils.isEmpty(tmpText)) {
                // 跳过空白段落
                continue;
            } else if (tmpText.startsWith(ImportPaperMsg.nestedQuestion_start)) {
                // 判断【套题】后面的值
                if (StringUtils.isBlank(getContent(tmpText, ImportPaperMsg.nestedQuestion_start))) {
                    importPaperCheck.setErrorInfo(paperDetailUnit.getPaperDetail().getName()
                            + "中“[套题]：”的后面没有值,当前读到的信息为:“" + tmpText + "”,请检查word中格式问题");
                    throw new PaperException(importPaperCheck.getErrorInfo());
                }
                Pattern pattern = Pattern.compile("[0-9]*");
                boolean isHeadNumber = pattern.matcher(getContent(tmpText, ImportPaperMsg.nestedQuestion_start))
                        .matches();
                if (!isHeadNumber) {
                    importPaperCheck.setErrorInfo("[套题]后面应该为整数,当前读到的信息为:“" + tmpText + "”,请检查word中格式问题");
                    throw new PaperException(importPaperCheck.getErrorInfo());
                }
                // 判断是否含有【套题数量】标签
                if (!nextTmpText.startsWith(ImportPaperMsg.nestedQuestion_number)) {
                    // 如果读取的错误信息太长，截取前50个字符。
                    if (nextTmpText.length() > 50) {
                        nextTmpText = nextTmpText.substring(0, 50) + "...";
                    }
                    importPaperCheck.setErrorInfo("[大题名称]：" + paperDetailUnit.getPaperDetail().getName() + "," + tmpText
                            + "的下一题头应该是[套题数量],当前读到的信息为:“" + nextTmpText + "”,请检查word中格式问题");
                    throw new PaperException(importPaperCheck.getErrorInfo());
                }
                // 判断【套题数量】后面的值
                if (StringUtils.isBlank(getContent(nextTmpText, ImportPaperMsg.nestedQuestion_number))) {
                    importPaperCheck.setErrorInfo("[套题数量]的后面没有值,当前读到的信息为:“" + nextTmpText + "”,请检查word中格式问题");
                    throw new PaperException(importPaperCheck.getErrorInfo());
                }
                boolean isNumber = pattern.matcher(getContent(nextTmpText, ImportPaperMsg.nestedQuestion_number))
                        .matches();

                if (!isNumber) {
                    importPaperCheck.setErrorInfo("[套题数量]应该为整数,当前读到的信息为:“" + nextTmpText + "”,请检查word中格式问题");
                    throw new PaperException(importPaperCheck.getErrorInfo());
                }
                importPaperCheck.setNestedHeadNumber(
                        Integer.parseInt(getContent(tmpText, ImportPaperMsg.nestedQuestion_start)));
                importPaperCheck.setNestedQuesNumber(
                        Integer.parseInt(getContent(nextTmpText, ImportPaperMsg.nestedQuestion_number)));
            } else {
                importPaperCheck.setIndex(i + 1);
                break;
            }
        }
    }

    /**
     * 处理题干信息
     *
     * @param pList
     * @param index
     * @param question
     * @param importPaperCheck
     * @throws Exception
     */
    private void processQuesBody(List<List<SectionElement>> pList, int index, int subQuesNum, Question question,
            ImportPaperCheck importPaperCheck, int errorQuesNum) throws Exception {
        // 定义题干json和html
        StringBuilder quesBodyHtml = new StringBuilder();
        int i = 0;
        for (i = index; i < pList.size(); i++) {
            List<SectionElement> pBody = pList.get(i);
            String tmpText = JsonImportUtil.getPText(pBody);
            if (StringUtils.isEmpty(tmpText) && JsonImportUtil.isText(pBody)) {
                // 跳过空白段落
                continue;
            } else if (tmpText.matches("^\\d{1,}\\.[\\s\\S]*")) {
                // 题干第一段
                // 过滤题干标题
                pBody = JsonImportUtil.formatP(pBody, QuesUnit.QUES_BODY);
                quesBodyHtml.append(JsonImportUtil.questionJson2Html(pBody));
            } else if (tmpText.matches("^[a-zA-Z]\\.[\\s\\S]*") || isHeader(tmpText)) {
                // 检测到选项或其他特殊段落直接退出
                break;
            } else {
                // 题干普通段落
                quesBodyHtml.append(JsonImportUtil.questionJson2Html(pBody));
            }
        }
        if (StringUtils.isEmpty(quesBodyHtml)) {
            if (subQuesNum == 0) {
                if (importPaperCheck.getNestedHeadNumber() != 0) {
                    importPaperCheck.setErrorInfo(importPaperCheck.getQuesName() + "第"
                            + importPaperCheck.getNestedHeadNumber() + "个题" + ImportPaperMsg.errMsg_01);
                } else {
                    importPaperCheck.setErrorInfo(
                            getQuesNumInfo(importPaperCheck.getQuesName(), errorQuesNum) + ImportPaperMsg.errMsg_01);
                }
            } else {
                if (importPaperCheck.getNestedHeadNumber() != 0) {
                    importPaperCheck.setErrorInfo(importPaperCheck.getQuesName() + "第"
                            + importPaperCheck.getNestedHeadNumber() + "个题" + errorQuesNum + ImportPaperMsg.errMsg_01);
                } else {
                    importPaperCheck.setErrorInfo(
                            getQuesNumInfo(importPaperCheck.getQuesName(), errorQuesNum) + ImportPaperMsg.errMsg_01);
                }
            }
            throw new PaperException(importPaperCheck.getErrorInfo());
        }
        importPaperCheck.setIndex(i);
        question.setQuesBody(quesBodyHtml.toString());
    }

    /**
     * 处理题目选项
     *
     * @param pList
     * @param index
     * @param subQuesNum
     * @param question
     * @param importPaperCheck
     * @param wordMLPackage
     * @return
     * @throws Exception
     */
    private String processQuesOption(List<List<SectionElement>> pList, int index, int subQuesNum, Question question,
            ImportPaperCheck importPaperCheck, int errorQuesNum) throws Exception {

        // 定义选项集合
        List<QuesOption> quesOptions = new ArrayList<>();
        // 定义选项数量
        int optionCount = 0;
        // 当前所处的选项
        QuesOption current = null;
        int i = 0;
        int number = 0;
        for (i = index; i < pList.size(); i++) {
            List<SectionElement> pOption = pList.get(i);
            String tmpText = JsonImportUtil.getPText(pOption);
            if (StringUtils.isEmpty(tmpText) && JsonImportUtil.isText(pOption)) {
                // 跳过空白段落
                continue;
            } else if (tmpText.matches("^[a-zA-Z]\\.[\\s\\S]*")) {
                // 检测到选项开始段落
                // 创建试题选项
                number++;
                current = new QuesOption();
                int optionNumber = JsonImportUtil.getOptionNum(tmpText);
                if (optionNumber != number || "abcdefghijklmnopqrstuvwxyz".indexOf(tmpText.substring(0, 1)) > -1) {
                    String errorMsg = tmpText.length() > 10 ? tmpText.substring(0, 10) : tmpText;
                    if (importPaperCheck.getNestedHeadNumber() != 0) {
                        importPaperCheck.setErrorInfo(
                                importPaperCheck.getQuesName() + "第" + importPaperCheck.getNestedHeadNumber() + "个题"
                                        + errorQuesNum + ":“" + errorMsg + "”" + ImportPaperMsg.errMsg_13);
                    } else {
                        importPaperCheck.setErrorInfo(getQuesNumInfo(importPaperCheck.getQuesName(), errorQuesNum)
                                + ":“" + errorMsg + "”" + ImportPaperMsg.errMsg_13);
                    }
                    throw new PaperException(importPaperCheck.getErrorInfo());
                }
                current.setNumber(String.valueOf(optionNumber));
                current.setOptionBody("");
                quesOptions.add(current);
                optionCount++;
                // 过滤选项标题
                pOption = JsonImportUtil.formatP(pOption, QuesUnit.QUES_OPTION);
                current.setOptionBody(current.getOptionBody() + JsonImportUtil.questionJson2Html(pOption));
            } else if (isHeader(tmpText)) {
                // 非选项的其他内容直接退出
                break;
            } else if (current != null) {
                // 选项的其他段落
                current.setOptionBody(current.getOptionBody() + JsonImportUtil.questionJson2Html(pOption));
            } else {
                break;
            }
        }
        importPaperCheck.setIndex(i);
        if (optionCount < 2) {
            if (importPaperCheck.getNestedHeadNumber() != 0) {
                importPaperCheck.setErrorInfo(importPaperCheck.getQuesName() + "第"
                        + importPaperCheck.getNestedHeadNumber() + "个题" + errorQuesNum + "中选项格式不正确或有缺失\n");
            } else {
                importPaperCheck
                        .setErrorInfo(getQuesNumInfo(importPaperCheck.getQuesName(), errorQuesNum) + "中选项格式不正确或有缺失\n");
            }
            throw new PaperException(importPaperCheck.getErrorInfo());
        } else {
            question.setQuesOptions(quesOptions);
        }
        return importPaperCheck.getErrorInfo();
    }

    /**
     * 处理小题尾信息
     *
     * @param pList
     * @param index
     * @param subQuesNum
     * @param question
     * @param paperDetailUnit
     * @param importPaperCheck
     */
    private void processQuesTail(List<List<SectionElement>> pList, int index, int subQuesNum, Question question,
            PaperDetailUnit paperDetailUnit, ImportPaperCheck importPaperCheck, boolean isNested, Paper paper,
            int errorQuesNum) throws Exception {

        StringBuilder answerHTML = new StringBuilder("");
        String quesScore = null;
        // 定义一级属性
        String firstProperty = null;
        // 定义二级级属性
        String secondProperty = null;
        // 定义难度
        Double difficulty = null;
        // 定义公开度
        Boolean publicity = null;
        // 定义试题属性集合
        List<QuesProperty> quesProperties = new ArrayList<>();
        // Map<String, String> quesParams = new HashMap<>();
        int i = 0;
        // 是否刚刚检测到答案内容
        boolean answerStart = false;
        boolean hasAnswer = false;

        for (i = index; i < pList.size(); i++) {
            List<SectionElement> pAnswer = pList.get(i);
            String tmpText = JsonImportUtil.getPText(pAnswer);
            if (StringUtils.isEmpty(tmpText) && JsonImportUtil.isText(pAnswer)) {
                // 跳过空白段落
                continue;
            } else if (tmpText.startsWith(ImportPaperMsg.answer_word)) {
                // 检测到答案开始段落
                pAnswer = JsonImportUtil.formatP(pAnswer, QuesUnit.QUES_ANSWER);
                if (question.getQuestionType() == QuesStructType.SINGLE_ANSWER_QUESTION
                        || question.getQuestionType() == QuesStructType.MULTIPLE_ANSWER_QUESTION) {
                    // 校验单选多选答案
                    String answerText = getContent(tmpText, ImportPaperMsg.answer_word);
                    checkSelectAnswer(question, answerText, importPaperCheck, errorQuesNum);
                    answerHTML.append(getContent(tmpText, ImportPaperMsg.answer_word));
                } else if (question.getQuestionType() == QuesStructType.BOOL_ANSWER_QUESTION) {
                    // 校验判断题答案
                    String answerText = getContent(tmpText, ImportPaperMsg.answer_word);
                    checkBoolAnswer(answerText, importPaperCheck, errorQuesNum);
                    answerHTML.append(answerText);
                } else {
                    answerHTML.append(JsonImportUtil.questionJson2Html(pAnswer));
                }
                hasAnswer = true;
                answerStart = true;
            } else if (tmpText.startsWith(ImportPaperMsg.subQuesScore_word)) {
                // 检测到分数开始段落
                quesScore = getContent(tmpText, ImportPaperMsg.subQuesScore_word);
                if (!CommonUtils.isInteger(quesScore)) {
                    if (importPaperCheck.getNestedHeadNumber() == 0) {
                        importPaperCheck.setErrorInfo(
                                "[大题名称]：" + importPaperCheck.getQuesName() + "第" + errorQuesNum + "题中[小题分数]格式不对或没有值");
                    } else {
                        importPaperCheck.setErrorInfo("[大题名称]：" + importPaperCheck.getQuesName() + "第"
                                + importPaperCheck.getNestedHeadNumber() + "个套题中,第" + errorQuesNum
                                + "题中[小题分数]格式不对或没有值");
                    }
                    throw new PaperException(importPaperCheck.getErrorInfo());
                }
                answerStart = false;
            } else if (tmpText.startsWith(ImportPaperMsg.first_property)) {
                // 检测到一级属性开始段落
                firstProperty = getContent(tmpText, ImportPaperMsg.first_property);
                if (StringUtils.isBlank(firstProperty)) {
                    firstProperty = "";
                }
                answerStart = false;
            } else if (tmpText.startsWith(ImportPaperMsg.second_property)) {
                // 检测到二级属性开始段落
                secondProperty = getContent(tmpText, ImportPaperMsg.second_property);
                if (StringUtils.isBlank(secondProperty)) {
                    secondProperty = "";
                }
                answerStart = false;
            } else if (tmpText.startsWith(ImportPaperMsg.difficulty)) {
                // 检测到难度开始段落 difficultyDegree
                String dif = getContent(tmpText, ImportPaperMsg.difficulty);

                difficulty = checkDifficulty(dif, importPaperCheck, errorQuesNum, question);
                question.setDifficultyDegree(difficulty);
                answerStart = false;
            } else if (tmpText.startsWith(ImportPaperMsg.publicity)) {
                // 检测到公安度开始段落
                String pub = getContent(tmpText, ImportPaperMsg.publicity);

                publicity = checkPublicity(pub, importPaperCheck, errorQuesNum);
                question.setPublicity(publicity);
                answerStart = false;
            } else if (isHeader(tmpText) || tmpText.matches("^\\d{1,}\\.[\\s\\S]*")) {
                // 检测到其他特殊段落或下一题直接退出
                break;
            } else if (answerStart) {
                answerHTML.append(JsonImportUtil.questionJson2Html(pAnswer));
                if (question.getQuestionType() == QuesStructType.SINGLE_ANSWER_QUESTION
                        || question.getQuestionType() == QuesStructType.MULTIPLE_ANSWER_QUESTION) {
                    importPaperCheck.setErrorInfo(
                            getQuesNumInfo(importPaperCheck.getQuesName(), subQuesNum) + "中,答案格式不正确,答案为:" + pList.get(i).toString());
                    throw new PaperException(importPaperCheck.getErrorInfo());
                }else if(question.getQuestionType() == QuesStructType.BOOL_ANSWER_QUESTION){
                    importPaperCheck.setErrorInfo(
                            getQuesNumInfo(importPaperCheck.getQuesName(), subQuesNum) + "中,答案格式不正确,应为:正确或错误");
                }
            } else {
                break;
            }
        }
        importPaperCheck.setIndex(i);
        // 如果没有答案字段，抛出异常
        if (!hasAnswer) {
            if (paperDetailUnit.getQuestionType() == QuesStructType.NESTED_ANSWER_QUESTION) {
                importPaperCheck.setErrorInfo(paperDetailUnit.getPaperDetail().getName() + "中，第"
                        + paperDetailUnit.getNumber() + "个套题的" + errorQuesNum + "小题中,缺失“[答案]”");
            } else {
                importPaperCheck
                        .setErrorInfo(getQuesNumInfo(importPaperCheck.getQuesName(), errorQuesNum) + "中,缺失“[答案]”");
            }
            throw new PaperException(importPaperCheck.getErrorInfo());
        }
        // 设置答案
        if (StringUtils.isNotEmpty(answerHTML)) {
            if (question.getQuestionType() == QuesStructType.SINGLE_ANSWER_QUESTION
                    || question.getQuestionType() == QuesStructType.MULTIPLE_ANSWER_QUESTION
                    ||question.getQuestionType() == QuesStructType.BOOL_ANSWER_QUESTION) {
                question.setQuesAnswer(answerHTML.toString().replaceAll(" ", ""));
            }else {
                question.setQuesAnswer(answerHTML.toString());
            }
        } else {
            if (question.getQuestionType() == QuesStructType.SINGLE_ANSWER_QUESTION
                    || question.getQuestionType() == QuesStructType.MULTIPLE_ANSWER_QUESTION
                    ||question.getQuestionType() == QuesStructType.BOOL_ANSWER_QUESTION) {
                question.setQuesAnswer("");
            }else {
                question.setQuesAnswer("<p></p>");
            }
        }

        if (quesScore != null) {
            question.setScore(Double.parseDouble(quesScore));
        }
        // 一般大题明细需要设置分数
        if (!isNested && quesScore != null) {
            paperDetailUnit.setScore(Double.parseDouble(quesScore));
        }
        // 校验小题尾信息是否含有"一节属性"，"二级属性","难度","公开"
        checkAttributeIsFull(firstProperty, secondProperty, difficulty, publicity, importPaperCheck, errorQuesNum);
        // 试题一级属性与二级属性校验
        checkProperty(firstProperty, secondProperty, importPaperCheck, errorQuesNum, paper, quesProperties);
        question.setQuesProperties(quesProperties);
    }

    /**
     * 校验一级属性与二级属性，并保存到试题中
     *
     * @param firstProperty
     * @param secondProperty
     * @param importPaperCheck
     * @param subQuesNum
     * @param paper
     * @param quesProperties
     * @throws Exception
     */
    private void checkProperty(String firstProperty, String secondProperty, ImportPaperCheck importPaperCheck,
            int subQuesNum, Paper paper, List<QuesProperty> quesProperties) throws Exception {
        // 一级属性为空，二级属性有值
        if (StringUtils.isBlank(firstProperty) && StringUtils.isNotBlank(secondProperty)) {
            if (importPaperCheck.getNestedHeadNumber() != 0) {
                importPaperCheck.setErrorInfo(importPaperCheck.getQuesName() + "第"
                        + importPaperCheck.getNestedHeadNumber() + "个题" + subQuesNum + "中,小题一级属性值为空,请检查");
            } else {
                importPaperCheck
                        .setErrorInfo(getQuesNumInfo(importPaperCheck.getQuesName(), subQuesNum) + "中,小题一级属性值为空,请检查");
            }
            throw new PaperException(importPaperCheck.getErrorInfo());
        }
        // 一级属性，二级属性都有值
        else if (StringUtils.isNotBlank(firstProperty) && StringUtils.isNotBlank(secondProperty)) {
            boolean isFirstEmpty = true;
            boolean isSecondEmpty = true;
            // 根据课程查询所有课程属性树
            List<CourseProperty> courseProperties = coursePropertyRepo
                    .findByCourseCodeAndEnable(paper.getCourse().getCode(), true);
            if (courseProperties == null || courseProperties.size() < 1) {
                if (importPaperCheck.getNestedHeadNumber() != 0) {
                    importPaperCheck.setErrorInfo(importPaperCheck.getQuesName() + "第"
                            + importPaperCheck.getNestedHeadNumber() + "个题" + subQuesNum + "中,没有设置课程属性结构，请先设置课程属性结构");
                } else {
                    importPaperCheck.setErrorInfo(
                            getQuesNumInfo(importPaperCheck.getQuesName(), subQuesNum) + "中,没有设置课程属性结构，请先设置课程属性结构");
                }
                throw new PaperException(importPaperCheck.getErrorInfo());
            }

            for (CourseProperty courseProperty : courseProperties) {
                Property propertyParent = new Property();
                propertyParent.setCoursePropertyId(courseProperty.getId());
                propertyParent.setParentId(Property.ROOT_PARENT_ID);
                propertyParent.setName(firstProperty);

                // 查询一级属性是否存在
                List<Property> parentProperties = propertyRepo.findAll(Example.of(propertyParent));

                // 存在一级属性
                if (parentProperties != null && parentProperties.size() > 0) {
                    isFirstEmpty = false;
                    for (Property proParent : parentProperties) {
                        Property propertySon = new Property();
                        propertySon.setCoursePropertyId(courseProperty.getId());
                        propertySon.setParentId(proParent.getId());
                        propertySon.setName(secondProperty);

                        // 查询二级属性
                        List<Property> sonProperties = propertyRepo.findAll(Example.of(propertySon));

                        // 存在二级属性
                        if (sonProperties != null && sonProperties.size() > 0) {
                            isSecondEmpty = false;
                            for (Property proSon : sonProperties) {
                                // 保存一级和二级属性
                                QuesProperty quesProperty = new QuesProperty(proParent, proSon, courseProperty);
                                String idNumber = quesProperty.getCoursePropertyName() + "-"
                                        + quesProperty.getFirstProperty().getId() + "-"
                                        + quesProperty.getSecondProperty().getId();
                                quesProperty.setId(idNumber);
                                quesProperties.add(quesProperty);
                            }
                        }
                    }
                }
            }

            if (isFirstEmpty) {
                if (importPaperCheck.getNestedHeadNumber() != 0) {
                    importPaperCheck
                            .setErrorInfo(importPaperCheck.getQuesName() + "第" + importPaperCheck.getNestedHeadNumber()
                                    + "个题" + subQuesNum + "中,小题一级属性值与课程属性中一级属性不匹配,请检查");
                } else {
                    importPaperCheck.setErrorInfo(
                            getQuesNumInfo(importPaperCheck.getQuesName(), subQuesNum) + "中,小题一级属性值与课程属性中一级属性不匹配,请检查");
                }
                throw new PaperException(importPaperCheck.getErrorInfo());
            }

            if (isSecondEmpty) {
                if (importPaperCheck.getNestedHeadNumber() != 0) {
                    importPaperCheck
                            .setErrorInfo(importPaperCheck.getQuesName() + "第" + importPaperCheck.getNestedHeadNumber()
                                    + "个题" + subQuesNum + "中,小题二级属性值与课程属性中二级属性不匹配,请检查");
                } else {
                    importPaperCheck.setErrorInfo(
                            getQuesNumInfo(importPaperCheck.getQuesName(), subQuesNum) + "中,小题二级属性值与课程属性中二级属性不匹配,请检查");
                }
                throw new PaperException(importPaperCheck.getErrorInfo());
            }
        } else if (StringUtils.isNotBlank(firstProperty) && StringUtils.isBlank(secondProperty)) {
            // 一级属性有值，二级属性为空

            boolean isFirstEmpty = true;
            boolean isSecondEmpty = true;

            // 根据课程查询所有课程属性树
            List<CourseProperty> courseProperties = coursePropertyRepo
                    .findByCourseCodeAndEnable(paper.getCourse().getCode(), true);
            if (courseProperties == null || courseProperties.size() < 1) {
                if (importPaperCheck.getNestedHeadNumber() != 0) {
                    importPaperCheck.setErrorInfo(importPaperCheck.getQuesName() + "第"
                            + importPaperCheck.getNestedHeadNumber() + "个题" + subQuesNum + "中,没有设置课程属性结构，请先设置课程属性结构");
                } else {
                    importPaperCheck.setErrorInfo(
                            getQuesNumInfo(importPaperCheck.getQuesName(), subQuesNum) + "中,没有设置课程属性结构，请先设置课程属性结构");
                }
                throw new PaperException(importPaperCheck.getErrorInfo());
            }

            for (CourseProperty courseProperty : courseProperties) {
                // 查询一级属性
                Property propertyParent = new Property();
                propertyParent.setCoursePropertyId(courseProperty.getId());
                propertyParent.setParentId(Property.ROOT_PARENT_ID);
                propertyParent.setName(firstProperty);

                List<Property> parentProperties = propertyRepo.findAll(Example.of(propertyParent));

                // 存在一级属性
                if (parentProperties != null && parentProperties.size() > 0) {
                    isFirstEmpty = false;
                    for (Property proParent : parentProperties) {
                        // 根据一级属性查询二级属性
                        List<Property> sonProperties = propertyRepo.findByParentIdOrderByNumber(proParent.getId());

                        // 存在二级属性，跳过
                        if (sonProperties != null && sonProperties.size() > 0) {
                            continue;
                        } else {
                            isSecondEmpty = false;
                            // 保存试题属性
                            QuesProperty quesProperty = new QuesProperty(proParent, null, courseProperty);
                            String idNumber = quesProperty.getCoursePropertyName() + "-"
                                    + quesProperty.getFirstProperty().getId();
                            quesProperty.setId(idNumber);
                            quesProperties.add(quesProperty);
                        }
                    }
                }
            }
            if (isFirstEmpty) {
                if (importPaperCheck.getNestedHeadNumber() != 0) {
                    importPaperCheck
                            .setErrorInfo(importPaperCheck.getQuesName() + "第" + importPaperCheck.getNestedHeadNumber()
                                    + "个题" + subQuesNum + "中,小题一级属性值与课程属性中一级属性不匹配,请检查");
                } else {
                    importPaperCheck.setErrorInfo(
                            getQuesNumInfo(importPaperCheck.getQuesName(), subQuesNum) + "中,小题一级属性值与课程属性中一级属性不匹配,请检查");
                }
                throw new PaperException(importPaperCheck.getErrorInfo());
            }

            if (isSecondEmpty) {
                if (importPaperCheck.getNestedHeadNumber() != 0) {
                    importPaperCheck
                            .setErrorInfo(importPaperCheck.getQuesName() + "第" + importPaperCheck.getNestedHeadNumber()
                                    + "个题" + subQuesNum + "中,小题二级属性值与课程属性中二级属性不匹配,请检查");
                } else {
                    importPaperCheck.setErrorInfo(
                            getQuesNumInfo(importPaperCheck.getQuesName(), subQuesNum) + "中,小题二级属性值与课程属性中二级属性不匹配,请检查");
                }
                throw new PaperException(importPaperCheck.getErrorInfo());
            }
        } else {
            // 一级，二级都为空
        }
    }

    /**
     * 校验小题尾信息是否含有"一节属性"，"二级属性","难度","公开"
     *
     * @param firstProperty
     * @param secondProperty
     * @param difficulty
     * @param publicity
     */
    private void checkAttributeIsFull(String firstProperty, String secondProperty, Double difficulty, Boolean publicity,
            ImportPaperCheck importPaperCheck, int subQuesNum) throws Exception {
        if (firstProperty == null) {
            if (importPaperCheck.getNestedHeadNumber() != 0) {
                importPaperCheck.setErrorInfo(importPaperCheck.getQuesName() + "第"
                        + importPaperCheck.getNestedHeadNumber() + "个题" + subQuesNum + "中,小题一级属性缺失,请检查");
            } else {
                importPaperCheck
                        .setErrorInfo(getQuesNumInfo(importPaperCheck.getQuesName(), subQuesNum) + "中,小题一级属性缺失,请检查");
            }
            throw new PaperException(importPaperCheck.getErrorInfo());
        }

        if (secondProperty == null) {
            if (importPaperCheck.getNestedHeadNumber() != 0) {
                importPaperCheck.setErrorInfo(importPaperCheck.getQuesName() + "第"
                        + importPaperCheck.getNestedHeadNumber() + "个题" + subQuesNum + "中,小题二级属性缺失,请检查");
            } else {
                importPaperCheck
                        .setErrorInfo(getQuesNumInfo(importPaperCheck.getQuesName(), subQuesNum) + "中,小题二级属性缺失,请检查");
            }
            throw new PaperException(importPaperCheck.getErrorInfo());
        }

        if (difficulty == null) {
            if (importPaperCheck.getNestedHeadNumber() != 0) {
                importPaperCheck.setErrorInfo(importPaperCheck.getQuesName() + "第"
                        + importPaperCheck.getNestedHeadNumber() + "个题" + subQuesNum + "中,小题难度缺失,请检查");
            } else {
                importPaperCheck
                        .setErrorInfo(getQuesNumInfo(importPaperCheck.getQuesName(), subQuesNum) + "中,小题难度缺失,请检查");
            }
            throw new PaperException(importPaperCheck.getErrorInfo());
        }

        if (publicity == null) {
            if (importPaperCheck.getNestedHeadNumber() != 0) {
                importPaperCheck.setErrorInfo(importPaperCheck.getQuesName() + "第"
                        + importPaperCheck.getNestedHeadNumber() + "个题" + subQuesNum + "中,小题公开性缺失,请检查");
            } else {
                importPaperCheck
                        .setErrorInfo(getQuesNumInfo(importPaperCheck.getQuesName(), subQuesNum) + "中,小题公开性缺失,请检查");
            }
            throw new PaperException(importPaperCheck.getErrorInfo());
        }
    }

    /**
     * 处理选择题option信息
     *
     * @param question
     */
    private void processSelectOption(Question question) {
        String answer = question.getQuesAnswer();
        if (StringUtils.isNotBlank(answer)) {
            String[] answerArray = answer.split(",");
            for (int i = 0; i < question.getQuesOptions().size(); i++) {
                QuesOption quesOption = question.getQuesOptions().get(i);
                char number = (char) (Integer.parseInt(quesOption.getNumber()) + 64);
                if (ArrayUtils.contains(answerArray, String.valueOf(number))) {
                    quesOption.setIsCorrect((short) 1);
                } else {
                    quesOption.setIsCorrect((short) 0);
                }
            }
        }
    }

    /**
     * 处理套题
     *
     * @param pList
     * @param index
     * @param question
     * @param paperDetailUnit
     * @param importPaperCheck
     * @throws Exception
     */
    private void processNestedQues(List<List<SectionElement>> pList, int index, Question question,
            PaperDetailUnit paperDetailUnit, ImportPaperCheck importPaperCheck, Paper paper) throws Exception {
        // 题型
        String nestedQuesType = "";
        // 处理套题的头信息
        processNestedQuestionHead(pList, index, 0, question, importPaperCheck, paperDetailUnit);
        // 设置套题题干
        processQuesBody(pList, importPaperCheck.getIndex(), 0, question, importPaperCheck, 0);
        // 创建小题集合
        List<Question> subQuesList = new ArrayList<>();
        Question subQues = null;
        int beginNum = importPaperCheck.getIndex();
        int quesTypeNum = 0;
        int subQuesNum = 0;
        boolean hasQuesType = false;
        for (int i = beginNum; i < pList.size(); i++) {
            List<SectionElement> pSubQues = pList.get(i);
            String tmpText = JsonImportUtil.getPText(pSubQues);
            if (StringUtils.isEmpty(tmpText)) {
                continue;
            }
            if (tmpText.startsWith(ImportPaperMsg.subQuestionType_word)) {
                nestedQuesType = getContent(tmpText, ImportPaperMsg.subQuestionType_word);
                importPaperCheck.setIndex(importPaperCheck.getIndex() + 1);
                quesTypeNum++;
                hasQuesType = true;
            } else if (tmpText.matches("^\\d{1,}\\.[\\s\\S]*")) {
                ++subQuesNum;
                if (!hasQuesType) {
                    if (importPaperCheck.getNestedHeadNumber() == 0) {
                        importPaperCheck.setErrorInfo(
                                "[大题名称]：" + importPaperCheck.getQuesName() + "第" + subQuesNum + "题中,缺失[小题型]，请检查套题");
                    } else {
                        importPaperCheck.setErrorInfo("[大题名称]：" + importPaperCheck.getQuesName() + "第"
                                + importPaperCheck.getNestedHeadNumber() + "个套题中,第" + subQuesNum + "题缺失[小题型]，请检查套题");
                    }
                    throw new PaperException(importPaperCheck.getErrorInfo());
                }
                if (StringUtils.isBlank(nestedQuesType) || getQuesStructType(nestedQuesType) == null) {
                    importPaperCheck.setErrorInfo(importPaperCheck.getQuesName() + "第"
                            + importPaperCheck.getNestedHeadNumber() + "个题" + subQuesNum + "中,"
                            + ImportPaperMsg.errMsg_02 + "(" + ImportPaperMsg.errMsg_09 + ")");
                    throw new PaperException(importPaperCheck.getErrorInfo());
                }
                subQues = new Question();
                subQues.setId(new ObjectId().toString());
                subQues.setQuestionType(getQuesStructType(nestedQuesType));
                if (StringUtils.isNumeric(importPaperCheck.getQuesScore())) {
                    subQues.setScore(Double.parseDouble(importPaperCheck.getQuesScore()));
                }
                // 处理客观题
                if (nestedQuesType.equals(ImportPaperMsg.singleSelection)
                        || nestedQuesType.equals(ImportPaperMsg.multipleSelection)) {
                    // 处理题干
                    processQuesBody(pList, importPaperCheck.getIndex(), subQuesNum, subQues, importPaperCheck,
                            subQuesNum);
                    // 处理选项
                    processQuesOption(pList, importPaperCheck.getIndex(), subQuesNum, subQues, importPaperCheck,
                            subQuesNum);
                    // 处理尾信息
                    processQuesTail(pList, importPaperCheck.getIndex(), subQuesNum, subQues, paperDetailUnit,
                            importPaperCheck, true, paper, subQuesNum);
                    // 处理选择题的option
                    processSelectOption(subQues);
                } else {
                    // 处理其他题型
                    processQuesBody(pList, importPaperCheck.getIndex(), subQuesNum, subQues, importPaperCheck,
                            subQuesNum);
                    processQuesTail(pList, importPaperCheck.getIndex(), subQuesNum, subQues, paperDetailUnit,
                            importPaperCheck, true, paper, subQuesNum);
                    // 填空题空格校验
                    if (QuesStructType.FILL_BLANK_QUESTION.getName().equals(subQues.getQuestionType().getName())) {
                        processFill(subQues, paperDetailUnit, importPaperCheck, subQuesNum, subQuesNum);
                    }
                }
                subQuesList.add(subQues);
                i = importPaperCheck.getIndex() - 1;
                nestedQuesType = "";
                hasQuesType = false;
            } else if (subQuesNum != quesTypeNum) {
                if (StringUtils.isEmpty(nestedQuesType)) {
                    importPaperCheck.setErrorInfo(
                            getQuesNumInfo(importPaperCheck.getQuesName(), quesTypeNum) + ImportPaperMsg.errMsg_02);
                } else {
                    importPaperCheck.setErrorInfo(
                            getQuesNumInfo(importPaperCheck.getQuesName(), quesTypeNum) + ImportPaperMsg.errMsg_03);
                }
                throw new PaperException(importPaperCheck.getErrorInfo());
            } else if (isHeader(tmpText)) {
                break;
            }
            if (!StringUtils.isEmpty(importPaperCheck.getErrorInfo())) {
                return;
            }
        }
        // 判断标签是否丢失
        if (importPaperCheck.getNestedQuesNumber() == 0 || importPaperCheck.getNestedHeadNumber() == 0) {
            importPaperCheck.setErrorInfo(importPaperCheck.getQuesName() + "中,套题可能缺失【套题】和【套题数量】标签，请检查套题");
            throw new PaperException(importPaperCheck.getErrorInfo());
        }
        // 判断子题数量是否一样
        if (importPaperCheck.getNestedQuesNumber() != subQuesList.size()) {
            importPaperCheck.setErrorInfo(importPaperCheck.getQuesName() + "第" + importPaperCheck.getNestedHeadNumber()
                    + "个套题" + "中,套题数量与子题数量不一样，请检查套题");
            throw new PaperException(importPaperCheck.getErrorInfo());
        }
        question.setSubQuestions(subQuesList);
        // 设置套题主题干的 难度，公开度，一级属性，二级属性
        setAttributes(question, subQuesList);
        // 计算套题总分
        double totalScore = 0;
        List<Double> scoreList = new ArrayList<>();
        for (Question child : subQuesList) {
            Double score = child.getScore();
            if (score != null) {
                totalScore += score;
                scoreList.add(score);
            } else {
                scoreList.add(0d);
            }
        }
        question.setScore(totalScore);
        paperDetailUnit.setSubScoreList(scoreList);
    }

    // 设置套题主题干的 难度，公开度，一级属性，二级属性
    private void setAttributes(Question question, List<Question> subQuesList) {
        if (subQuesList != null && subQuesList.size() > 0) {
            Double totalDouble = 0d;
            Double sum = 0.0;
            Boolean publicity = false;
            List<QuesProperty> subQuesProperties = new ArrayList<>();
            for (Question subQuestion : subQuesList) {
                // 设置一级属性，二级属性
                List<QuesProperty> quesProperties = subQuestion.getQuesProperties();
                if (quesProperties != null && quesProperties.size() > 0) {
                    for (QuesProperty quesProperty : quesProperties) {
                        subQuesProperties.add(quesProperty);
                    }
                }
                // 设置公开度
                if (subQuestion.getPublicity()) {
                    publicity = true;
                }
                sum = subQuestion.getDifficultyDegree() * subQuestion.getScore() + sum;
                totalDouble = subQuestion.getScore() + totalDouble;
            }

            BigDecimal b = BigDecimal.valueOf(sum / totalDouble);
            Double difficulty = b.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
            // 给属性去重
            Set<QuesProperty> ts = new HashSet<>();
            ts.addAll(subQuesProperties);
            subQuesProperties.clear();
            subQuesProperties.addAll(ts);
            question.setDifficultyDegree(difficulty);
            question.setPublicity(publicity);
            question.setQuesProperties(subQuesProperties);
            question.setDifficulty(setDiff(difficulty));
        }
    }

    /**
     * 获取试题结构类型
     *
     * @param quesType
     * @return
     */
    private static QuesStructType getQuesStructType(String quesType) {
        return CommonUtils.getEnum(QuesStructType.class, quesType);
    }

    /**
     * 获取当前试题大题小题号
     *
     * @param quesType
     * @param subQuesNum
     * @return
     */
    private static String getQuesNumInfo(String quesType, int subQuesNum) {
        return quesType + "第" + subQuesNum + "小题";
    }

    /**
     * 判断是否为套题
     *
     * @param importPaperCheck
     * @return
     */
    private static boolean isNested(ImportPaperCheck importPaperCheck) {
        if (importPaperCheck.getQuesType().equals(ImportPaperMsg.nestedQuestion_word)) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 校验试卷总分是否与设定一致
     *
     * @param paper
     * @param paperDetailUnits
     * @param importPaperCheck
     * @throws PaperException
     */
    private void checkTotalScore(Paper paper, List<PaperDetailUnit> paperDetailUnits, ImportPaperCheck importPaperCheck)
            throws PaperException {
        double totalScore = 0;
        for (PaperDetailUnit unit : paperDetailUnits) {
            if (unit.getScore() != null) {
                totalScore += unit.getScore();
            }
        }
        if (paper.getTotalScore() != null && paper.getTotalScore() != totalScore) {
            importPaperCheck.setErrorInfo("试卷总分(" + totalScore + ")与设置总分(" + paper.getTotalScore() + ")不符");
            throw new PaperException(importPaperCheck.getErrorInfo());
        }
    }

    /**
     * 校验大题下小题数量是否与标识数量一致
     *
     * @throws PaperException
     */
    private void checkUnitNum(List<PaperDetailUnit> paperDetailUnits, ImportPaperCheck importPaperCheck)
            throws PaperException {
        Map<PaperDetail, Integer> unitNumMap = new HashMap<>();
        Collections.sort(paperDetailUnits);

        for (PaperDetailUnit paperDetailUnit : paperDetailUnits) {
            PaperDetail key = paperDetailUnit.getPaperDetail();
            if (unitNumMap.containsKey(key)) {
                int value = unitNumMap.get(key);
                /*
                 * if (paperDetailUnit.getQuestionType() ==
                 * QuesStructType.NESTED_ANSWER_QUESTION) { unitNumMap.put(key,
                 * value + 1); } else { unitNumMap.put(key, value + 1); }
                 */
                unitNumMap.put(key, value + 1);
            } else {
                /*
                 * if (paperDetailUnit.getQuestionType() ==
                 * QuesStructType.NESTED_ANSWER_QUESTION) { unitNumMap.put(key,
                 * 1); } else { unitNumMap.put(key, 1); }
                 */
                unitNumMap.put(key, 1);
            }
        }

        for (Map.Entry<PaperDetail, Integer> entry : unitNumMap.entrySet()) {
            PaperDetail paperDetail = entry.getKey();
            if (paperDetail.getUnitCount().intValue() != entry.getValue().intValue()) {
                importPaperCheck.setErrorInfo("大题:" + paperDetail.getName() + "标识小题数量(" + paperDetail.getUnitCount()
                        + ")与实际小题数量(" + entry.getValue() + ")不符。" + "(注:若检查小题数量无问题,请检查word中题目的格式是否正确)");
                throw new PaperException(importPaperCheck.getErrorInfo());
            }
        }
    }

    /**
     * 校验选择题答案 1.判断答案格式，选择题答案必须以","分隔,且都为字母 2.判断答案在选项中是否不存在,例如选项为A,B,C,D，答案为E
     *
     * @param question
     * @param answerWord
     * @param importPaperCheck
     * @throws PaperException
     */
    private void checkSelectAnswer(Question question, String answerWord, ImportPaperCheck importPaperCheck,
            int subQuesNum) throws PaperException {
        if (!StringUtils.isBlank(answerWord)) {
            if (question.getQuestionType() == QuesStructType.SINGLE_ANSWER_QUESTION&&answerWord.contains(",")) {
                importPaperCheck.setErrorInfo(
                        getQuesNumInfo(importPaperCheck.getQuesName(), subQuesNum) + "中,答案格式不正确,答案为:" + answerWord);
                throw new PaperException(importPaperCheck.getErrorInfo());
            }
            String[] pAnswerArray = answerWord.split(",");
            List<QuesOption> options = question.getQuesOptions();
            List<String> optionNumList = new ArrayList<>();
            for (QuesOption quesOption : options) {
                Integer numInteger = Integer.parseInt(quesOption.getNumber());
                char word = (char) (numInteger + 64);
                optionNumList.add(word + "");
            }
            for (String answer : pAnswerArray) {
                answer = answer.trim();
                String pattern = "[A-Z]|[a-z]";
                if (!Pattern.matches(pattern, answer)) {
                    importPaperCheck.setErrorInfo(
                            getQuesNumInfo(importPaperCheck.getQuesName(), subQuesNum) + "中,答案格式不正确,答案为:" + answerWord);
                    throw new PaperException(importPaperCheck.getErrorInfo());
                }
                if (!optionNumList.contains(answer)) {
                    importPaperCheck.setErrorInfo(getQuesNumInfo(importPaperCheck.getQuesName(), subQuesNum) + "中,选项为:"
                            + optionNumList.toString() + ",答案为:" + answerWord + "。(注:若检查选项无问题,请检查word中题目的格式是否正确)");
                    throw new PaperException(importPaperCheck.getErrorInfo());
                }
            }
        }
    }

    /**
     * 校验判断题答案
     *
     * @param tmpText
     * @param importPaperCheck
     * @param subQuesNum
     * @throws Exception
     */
    private void checkBoolAnswer(String tmpText, ImportPaperCheck importPaperCheck, int subQuesNum) throws Exception {
        if (!StringUtils.isBlank(tmpText)) {
            tmpText = tmpText.trim();
            if (tmpText.equals("正确") || tmpText.equals("错误")) {
                return;
            } else {
                importPaperCheck.setErrorInfo(
                        getQuesNumInfo(importPaperCheck.getQuesName(), subQuesNum) + "中,答案格式不正确,应为:正确或错误");
                throw new PaperException(importPaperCheck.getErrorInfo());
            }
        }
    }

    /**
     * 校验试题难度
     */
    private Double checkDifficulty(String tmpText, ImportPaperCheck importPaperCheck, int subQuesNum, Question question)
            throws Exception {
        Double tempDifficulty;
        if (StringUtils.isBlank(tmpText)) {
            // 如果为空，默认难度0.5
            tempDifficulty = 0.5;
            question.setDifficulty("中");
        } else if (!isInteger(tmpText) || (Double.parseDouble(tmpText) < 1) || (Double.parseDouble(tmpText) > 10)) {
            // 如果不是整数，或者在1到10之间，就报错
            importPaperCheck
                    .setErrorInfo(getQuesNumInfo(importPaperCheck.getQuesName(), subQuesNum) + "中,试题难度只能是1到10之间整数");
            throw new PaperException(importPaperCheck.getErrorInfo());
        } else {
            tempDifficulty = Double.parseDouble(tmpText) / 10;
            question.setDifficulty(setDiff(tempDifficulty));
        }

        return tempDifficulty;
    }

    private String setDiff(Double difficulty) {
        if (difficulty > 0 && difficulty < 0.4) {
            return "难";
        } else if (difficulty > 0.3 && difficulty < 0.8) {
            return "中";
        } else {
            return "易";
        }
    }

    /**
     * 校验试题公开度
     */
    private Boolean checkPublicity(String tmpText, ImportPaperCheck importPaperCheck, int subQuesNum) throws Exception {
        Boolean publicity;
        if (StringUtils.isBlank(tmpText)) {
            // 如果为空，默认是公开
            publicity = true;
        } else if (!tmpText.equals("公开") && !tmpText.equals("非公开")) {
            // 如果不是公开和非公开，就报错
            importPaperCheck
                    .setErrorInfo(getQuesNumInfo(importPaperCheck.getQuesName(), subQuesNum) + "中,试题公开度只能是公开和非公开");
            throw new PaperException(importPaperCheck.getErrorInfo());
        } else {
            if (tmpText.equals("非公开")) {
                publicity = false;
            } else {
                publicity = true;
            }
        }
        return publicity;
    }

    /**
     * 校验客观题答案完整性 客观题答案要么全有，要么全没有
     *
     * @throws PaperException
     */
    private void checkAnswerISfull(List<PaperDetailUnit> paperDetailUnits, ImportPaperCheck importPaperCheck)
            throws PaperException {
        Map<Question, PaperDetailUnit> map = new HashMap<>();
        for (PaperDetailUnit paperDetailUnit : paperDetailUnits) {
            Question question = paperDetailUnit.getQuestion();
            if (question.getQuestionType() == QuesStructType.SINGLE_ANSWER_QUESTION
                    || question.getQuestionType() == QuesStructType.MULTIPLE_ANSWER_QUESTION
                    || question.getQuestionType() == QuesStructType.BOOL_ANSWER_QUESTION) {
                map.put(question, paperDetailUnit);
            }
            if (question.getQuestionType() == QuesStructType.NESTED_ANSWER_QUESTION) {
                List<Question> subQuestions = question.getSubQuestions();
                for (Question subQuestion : subQuestions) {
                    if (subQuestion.getQuestionType() == QuesStructType.SINGLE_ANSWER_QUESTION
                            || subQuestion.getQuestionType() == QuesStructType.MULTIPLE_ANSWER_QUESTION
                            || subQuestion.getQuestionType() == QuesStructType.BOOL_ANSWER_QUESTION) {
                        map.put(subQuestion, paperDetailUnit);
                    }
                }
            }
        }
        boolean isNull = false;
        boolean isNotNull = false;
        PaperDetailUnit paperDetailUnit = new PaperDetailUnit();
        Question subQuestion = new Question();
        for (Question question : map.keySet()) {
            PaperDetailUnit pdu = map.get(question);
            if (StringUtils.isBlank(question.getQuesAnswer())) {
                isNull = true;
                if (pdu.getQuestion().getQuestionType() == QuesStructType.NESTED_ANSWER_QUESTION) {
                    subQuestion = question;
                }
                paperDetailUnit = pdu;
                break;
            }
        }
        for (Question question : map.keySet()) {
            // PaperDetailUnit pdu = map.get(question);
            if (StringUtils.isNotBlank(question.getQuesAnswer())) {
                isNotNull = true;
                break;
            }
        }
        // 不满足(客观题答案要么全有，要么全没有)条件
        if (isNull && isNotNull) {
            if (paperDetailUnit.getQuestion().getQuestionType() == QuesStructType.NESTED_ANSWER_QUESTION) {
                int number = 0;
                for (int i = 0; i < paperDetailUnit.getQuestion().getSubQuestions().size(); i++) {
                    if (paperDetailUnit.getQuestion().getSubQuestions().get(i).getId().equals(subQuestion.getId())) {
                        number = i + 1;
                    }
                }
                importPaperCheck.setErrorInfo("第" + paperDetailUnit.getNumber() + "大题套题中" + number + "小题答案缺失,请检查");
                throw new PaperException(importPaperCheck.getErrorInfo());
            }
            importPaperCheck.setErrorInfo("第" + paperDetailUnit.getNumber() + "小题答案缺失,请检查");
            throw new PaperException(importPaperCheck.getErrorInfo());
        }
    }

    /**
     * 替换字符串中的属性头得到属性值
     *
     * @param pText
     * @param replaceContent
     * @return
     */
    private static String getContent(String pText, String replaceContent) {
        String word = replaceContent.replace("[", "").replace("]", "");
        return pText.replaceAll("\\[" + word + "\\]", "").replaceAll("[:|：]", "").trim();
    }

    private static boolean isInteger(String str) {
        Pattern pattern = Pattern.compile("^[-\\+]?[\\d]*$");
        return pattern.matcher(str).matches();
    }

    /**
     * 判断填空题题干和答案空格数量是否一致
     *
     * @throws PaperException
     */
    private void processFill(Question question, PaperDetailUnit paperDetailUnit, ImportPaperCheck importPaperCheck,
            int subQuesNum, int errorQuesNum) throws PaperException {
    	if(!question.getQuesBody().contains("###")) {
    		if (importPaperCheck.getNestedHeadNumber() == 0) {
                importPaperCheck.setErrorInfo(
                        "[大题名称]：" + importPaperCheck.getQuesName() + "第" + errorQuesNum + "题中,题干中没有空格");
            } else {
                importPaperCheck.setErrorInfo("[大题名称]：" + importPaperCheck.getQuesName() + "第"
                        + importPaperCheck.getNestedHeadNumber() + "个套题中,第" + errorQuesNum
                        + "题中,题干中没有空格");
            }
            throw new PaperException(importPaperCheck.getErrorInfo());
    	}
        // 按3个#号截取题干
        String[] quesBody = question.getQuesBody().split("###");
        String[] quesAnwser = question.getQuesAnswer().split("##");
        // 如果有答案，进行判断
        if (quesAnwser.length > 0) {
            String str = quesAnwser[0].replaceAll("<p>", "").replaceAll("</p>", "").replaceAll("<span>", "")
                    .replaceAll("</span>", "").replace("&nbsp;", "");
            if (quesAnwser.length == 1 && !StringUtils.isBlank(str) || quesAnwser.length > 1) {
                // 判断题干空格和答案空格是否相等
                if ((quesBody.length - 1) != quesAnwser.length) {
                    if (importPaperCheck.getNestedHeadNumber() == 0) {
                        importPaperCheck.setErrorInfo(
                                "[大题名称]：" + importPaperCheck.getQuesName() + "第" + errorQuesNum + "题中,题干与答案的空格数量不一样");
                    } else {
                        importPaperCheck.setErrorInfo("[大题名称]：" + importPaperCheck.getQuesName() + "第"
                                + importPaperCheck.getNestedHeadNumber() + "个套题中,第" + errorQuesNum
                                + "题中,题干与答案的空格数量不一样");
                    }
                    throw new PaperException(importPaperCheck.getErrorInfo());
                }
            }
        }
    }
}
