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

import cn.com.qmth.examcloud.commons.exception.StatusException;
import cn.com.qmth.examcloud.commons.logging.ExamCloudLog;
import cn.com.qmth.examcloud.commons.logging.ExamCloudLogFactory;
import cn.com.qmth.examcloud.core.questions.base.CommonUtils;
import cn.com.qmth.examcloud.core.questions.base.Model;
import cn.com.qmth.examcloud.core.questions.base.question.enums.QuesStructType;
import cn.com.qmth.examcloud.core.questions.dao.*;
import cn.com.qmth.examcloud.core.questions.dao.entity.*;
import cn.com.qmth.examcloud.core.questions.service.*;
import cn.com.qmth.examcloud.core.questions.service.bean.extract.ExtractConfigPaper;
import cn.com.qmth.examcloud.core.questions.service.config.UpYunProperty;
import cn.com.qmth.examcloud.question.commons.core.paper.DefaultPaper;
import cn.com.qmth.examcloud.question.commons.core.paper.DefaultQuestionGroup;
import cn.com.qmth.examcloud.question.commons.core.paper.DefaultQuestionStructureWrapper;
import cn.com.qmth.examcloud.question.commons.core.paper.DefaultQuestionUnitWrapper;
import cn.com.qmth.examcloud.question.commons.core.question.QuestionType;
import cn.com.qmth.examcloud.question.commons.core.question.*;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * @author weiwenhai
 * @date 2018.8.15
 * @company qmth
 * @describle provider中的service方法
 * @code 020
 */
@Service("extractConfigCloudService")
public class ExtractConfigProviderServiceImpl implements ExtractConfigProviderService {

    protected ExamCloudLog log = ExamCloudLogFactory.getLog(this.getClass());

    @Autowired
    private ExtractConfigService extractConfigService;

    @Autowired
    private PaperRepo paperRepo;

    @Autowired
    private PaperDetailRepo paperDetailRepo;

    @Autowired
    private PaperDetailUnitRepo paperDetailUnitRepo;

    @Autowired
    private QuesRepo quesRepo;

    @Autowired
    private AudioTimeConfigRepo audioTimeConfigRepo;

    @Autowired
    private QuestionAudioService questionAudioService;

    @Autowired
    private QuesService quesService;

    @Autowired
    private PaperService paperService;

    @Autowired
    private UpYunProperty upYunProperty;

    @Override
    public ExtractConfigPaper getDefaultPaper(Long examId, String courseCode, String groupCode) {
        log.debug("调卷开始...");

        log.debug("开始根据examId:" + examId + "和courseCode:" + courseCode + "获取调卷规则");
        ExtractConfig extractConfig = extractConfigService.findConfig(new ExtractConfig(examId, courseCode));
        if (extractConfig == null) {
            log.error("该课程调卷规则未制定，请联系学校");
            throw new StatusException("Q-020101", "该课程调卷规则未制定，请联系学校");
        }


        log.debug("根据调卷规则中设置的概率获取类型为" + groupCode + "的试卷");
        Map<String, Paper> paperMap = this.getExamPaperByProbability(extractConfig.getExamPaperList());
        if (paperMap.isEmpty()) {
            log.error("该考试和课程下调卷规则中试卷不存在,请检查调卷规则,调卷程序退出");
            throw new StatusException("Q-020109", "该考试和课程下调卷规则中试卷不存在,请重新制定调卷规则");
        }

        Paper basePaper = paperMap.get(groupCode);
        if (basePaper == null) {
            log.error("该考试和课程下调卷规则中该类型试卷不存在,请检查调卷规则,调卷程序退出");
            throw new StatusException("Q-020116", "该考试和课程下调卷规则中试卷不存在,请重新制定调卷规则");
        }

        log.debug("将原始试卷:" + basePaper.getId() + "根据规则构建试卷结构");
        DefaultPaper defaultPaper = this.buildDefaultByBasePaper(basePaper, String.valueOf(examId), courseCode, groupCode);

        Short questionOrder = extractConfig.getScrambling_the_question_order();
        Short optionOrder = extractConfig.getScrambling_the_option_order();

        ExtractConfigPaper result = new ExtractConfigPaper();
        result.setPaperId(basePaper.getId());
        result.setSortQuestionOrder(questionOrder == 0 ? false : true);
        result.setSortOptionOrder(optionOrder == 0 ? false : true);
        result.setDefaultPaper(defaultPaper);
        return result;
    }

    /**
     * 每个试卷类型取出一套试卷
     * {
     * A:Paper,
     * B:Paper
     * }
     * A是试卷类型   Paper是A类型下选定的试卷
     *
     * @param examPaperList
     * @return
     */
    private Map<String, Paper> getExamPaperByProbability(List<ExamPaper> examPaperList) {
        Map<String, Paper> paperByTypeMap = new HashMap<>();
        if (examPaperList == null || examPaperList.size() == 0) {
            throw new StatusException("Q-020114", "可供抽取的试卷集合为空,无法抽取试卷");
        }

        Map<String, List<ExamPaper>> examPaperMap = new HashMap<>();
        for (int i = 0; i < examPaperList.size(); i++) {
            ExamPaper examPaper = examPaperList.get(i);
            if (!examPaperMap.containsKey(examPaper.getGroupCode())) {
                if (examPaper.getPaper() != null) {
                    List<ExamPaper> epList = new ArrayList<>();
                    epList.add(examPaper);
                    examPaperMap.put(examPaper.getGroupCode(), epList);
                }
            } else {
                if (examPaper.getPaper() != null) {
                    List<ExamPaper> epList = examPaperMap.get(examPaper.getGroupCode());
                    epList.add(examPaper);
                }
            }
        }

        if (examPaperMap != null) {
            Set<String> keys = examPaperMap.keySet();
            Iterator<String> it = keys.iterator();
            while (it.hasNext()) {
                String key = it.next();
                Paper paper = this.getPaperByProbability(examPaperMap.get(key));
                //不能用原来的paper对象，否则examPaperList中的paper对象会被覆盖
                Paper newPaper = Model.of(paperRepo.findById(paper.getId()));
                paperByTypeMap.put(key, newPaper);
            }
        }
        return paperByTypeMap;
    }

    /**
     * 根据设定几率取出一套试卷
     *
     * @param examPaperList
     * @return
     */
    private Paper getPaperByProbability(List<ExamPaper> examPaperList) {
        int sum = 0;
        for (int i = 0; i < examPaperList.size(); i++) {
            sum += examPaperList.get(i).getWeight();
        }

        // 从1开始  
        Integer rand = new Random().nextInt(sum) + 1;
        for (int i = 0; i < examPaperList.size(); i++) {
            rand -= examPaperList.get(i).getWeight();
            // 选中
            if (rand <= 0) {
                return examPaperList.get(i).getPaper();
            }
        }

        return null;
    }

    /**
     * 根据paper对象构建DefaultPaper对象
     *
     * @param basePaper
     * @return
     */
    public DefaultPaper buildDefaultByBasePaper(Paper basePaper, String examId, String courseCode, String groupCode) {
        log.debug("开始包装网考需要的试卷结构...");
        long beginTime = System.currentTimeMillis();

        //获取大题
        List<PaperDetail> paperDetails = paperDetailRepo.findByPaper(basePaper);
        log.debug("数据库取大题耗时:" + (System.currentTimeMillis() - beginTime) + "ms");

        //排序大题
        Collections.sort(paperDetails);

        //将小题全部取出来,只取一次,减少对数据库的查询
        beginTime = System.currentTimeMillis();
        List<PaperDetailUnit> allPaperDetailUnits = paperDetailUnitRepo.findByPaper(basePaper);
        boolean fullyObjective = checkIsAllQbjectiveQuestion(allPaperDetailUnits);
        log.debug("数据库取所有小题耗时:" + (System.currentTimeMillis() - beginTime) + "ms");

        //根据大题id将小题归类
        beginTime = System.currentTimeMillis();
        Map<String, List<PaperDetailUnit>> pduMap = allPaperDetailUnits.stream().collect(Collectors.groupingBy(PaperDetailUnit::getDetailId));
        log.debug("获取大题与小题对应关系耗时:" + (System.currentTimeMillis() - beginTime) + "ms");

        log.debug("循环大题，开始组装对象...");
        //生成新的分组集合
        List<DefaultQuestionGroup> questionGroupList = new ArrayList<>();
        for (int i = 0; i < paperDetails.size(); i++) {
            PaperDetail paperDetail = paperDetails.get(i);
            DefaultQuestionGroup defaultQuestionGroup = new DefaultQuestionGroup();
            defaultQuestionGroup.setGroupName(paperDetail.getName());
            defaultQuestionGroup.setGroupScore(paperDetail.getScore());

            //获取原小题的集合
            List<PaperDetailUnit> paperDetailUnits = pduMap.get(paperDetail.getId());
            if (paperDetailUnits == null || paperDetailUnits.size() < 1) {
                log.error("试卷大题下面，没有小题");
                throw new StatusException("Q-020241", "考试试卷有误，请联系老师");
            }

            //按题号顺序排序
            Collections.sort(paperDetailUnits);

            //生成新的题包装器集合
            List<DefaultQuestionStructureWrapper> questionWrapperList = new ArrayList<>();
            for (int j = 0; j < paperDetailUnits.size(); j++) {
                PaperDetailUnit paperDetailUnit = paperDetailUnits.get(j);
                DefaultQuestionStructureWrapper defaultQuestionStructureWrapper = new DefaultQuestionStructureWrapper();
                defaultQuestionStructureWrapper.setQuestionId(paperDetailUnit.getQuestion().getId());
                defaultQuestionStructureWrapper.setVersion(CommonUtils.QUESTION_VERSION);
                defaultQuestionStructureWrapper.setQuestionScore(paperDetailUnit.getScore());
                defaultQuestionStructureWrapper.setTimeLimit(paperDetailUnit.getTimeLimit());

                if (examId != null) {
                    //设置音频播放次数
                    if (paperDetailUnit.getQuestion().getHasAudio() != null && paperDetailUnit.getQuestion().getHasAudio() == true) {
                        AudioTimeConfig audioTimeConfig = Model.of(audioTimeConfigRepo.findOne(Example.of(new AudioTimeConfig(examId, courseCode, groupCode, paperDetailUnit.getQuestion().getId()))));
                        if (audioTimeConfig != null) {
                            defaultQuestionStructureWrapper.setLimitedPlayTimes(audioTimeConfig.getPlayTime());
                        }
                    }
                }

                //生成新的题单元包装器
                List<DefaultQuestionUnitWrapper> defaultQuestionUnitWrappers = new ArrayList<>();
                if (paperDetailUnit.getQuestion().getQuestionType() == QuesStructType.NESTED_ANSWER_QUESTION) {
                    List<Question> subQuesList = paperDetailUnit.getQuestion().getSubQuestions();
                    List<Double> scoreList = paperDetailUnit.getSubScoreList();
                    if (subQuesList != null && subQuesList.size() > 0) {
                        for (int k = 0; k < subQuesList.size(); k++) {
                            DefaultQuestionUnitWrapper defaultQuestionUnitWrapper = buildQuesUnitWrapper(subQuesList.get(k), scoreList.get(k));
                            defaultQuestionUnitWrappers.add(defaultQuestionUnitWrapper);
                        }
                    }
                } else {
                    DefaultQuestionUnitWrapper defaultQuestionUnitWrapper = buildQuesUnitWrapper(paperDetailUnit.getQuestion(), paperDetailUnit.getScore());
                    defaultQuestionUnitWrappers.add(defaultQuestionUnitWrapper);
                }

                defaultQuestionStructureWrapper.setQuestionUnitWrapperList(defaultQuestionUnitWrappers);
                questionWrapperList.add(defaultQuestionStructureWrapper);
            }

            defaultQuestionGroup.setQuestionWrapperList(questionWrapperList);
            questionGroupList.add(defaultQuestionGroup);
        }

        DefaultPaper defaultPaper = new DefaultPaper();
        defaultPaper.setName(basePaper.getName());
        defaultPaper.setQuestionGroupList(questionGroupList);
        defaultPaper.setFullyObjective(fullyObjective);
        return defaultPaper;
    }

    /**
     * 根据question生成题单元包装器
     *
     * @param question
     * @param score
     * @return
     */
    private DefaultQuestionUnitWrapper buildQuesUnitWrapper(Question question, Double score) {
        Integer[] optionPermutation = null;
        if (question.getQuestionType() == QuesStructType.SINGLE_ANSWER_QUESTION || question.getQuestionType() == QuesStructType.MULTIPLE_ANSWER_QUESTION) {
            int length = question.getQuesOptions().size();
            optionPermutation = new Integer[length];

            for (int i = 0; i < length; i++) {
                optionPermutation[i] = i;
            }
        }

        DefaultQuestionUnitWrapper defaultQuestionUnitWrapper = new DefaultQuestionUnitWrapper();
        defaultQuestionUnitWrapper.setOptionPermutation(optionPermutation);
        defaultQuestionUnitWrapper.setQuestionScore(score);
        defaultQuestionUnitWrapper.setQuestionType(getByOldType(question.getQuestionType()));
        defaultQuestionUnitWrapper.setAnswerType(question.getAnswerType());//作答类型
        return defaultQuestionUnitWrapper;
    }

    /**
     * 题型转换方法
     *
     * @param quesStructType
     * @return
     */
    private QuestionType getByOldType(QuesStructType quesStructType) {
        if (quesStructType == QuesStructType.BOOL_ANSWER_QUESTION) {
            return QuestionType.TRUE_OR_FALSE;
        }
        if (quesStructType == QuesStructType.FILL_BLANK_QUESTION) {
            return QuestionType.FILL_UP;
        }
        if (quesStructType == QuesStructType.MULTIPLE_ANSWER_QUESTION) {
            return QuestionType.MULTIPLE_CHOICE;
        }
        if (quesStructType == QuesStructType.SINGLE_ANSWER_QUESTION) {
            return QuestionType.SINGLE_CHOICE;
        }
        if (quesStructType == QuesStructType.TEXT_ANSWER_QUESTION) {
            return QuestionType.ESSAY;
        }
        return null;
    }

    @Override
    public DefaultQuestion getDefaultQuestion(Long examId, String courseCode, String groupCode, String questionId) {
        log.debug("网考根据调卷规则中试题id：" + questionId + "获取单个试题...");
        long beginTime = System.currentTimeMillis();

        Question question = Model.of(quesRepo.findById(questionId));
        if (question == null) {
            throw new StatusException("Q-020330", "question is null");
        }
        quesService.formatQues(question);
        log.debug("查询单个试题耗时：" + (System.currentTimeMillis() - beginTime) + "ms");

        //封装成新的题单元集合
        beginTime = System.currentTimeMillis();
        DefaultQuestionStructure defaultQuestionStructure = new DefaultQuestionStructure();
        if (question.getHasAudio() == null || false == question.getHasAudio()) {
            defaultQuestionStructure.setHasAudios(false);
        } else {
            defaultQuestionStructure.setHasAudios(true);
        }
        defaultQuestionStructure.setVersion(CommonUtils.QUESTION_VERSION);

        List<DefaultQuestionUnit> questionUnitList = new ArrayList<>();
        if (question.getQuestionType() == QuesStructType.NESTED_ANSWER_QUESTION) {
            defaultQuestionStructure.setBody(question.getQuesBody());

            //获取套题下面所有子题
            List<Question> subQuesList = question.getSubQuestions();
            if (CollectionUtils.isNotEmpty(subQuesList)) {
                for (int i = 0; i < subQuesList.size(); i++) {
                    Question subQuestion = subQuesList.get(i);
                    DefaultQuestionUnit defaultQuestionUnit = buildQuestionUnit(subQuestion);
                    questionUnitList.add(defaultQuestionUnit);
                }
            }
        } else {
            DefaultQuestionUnit defaultQuestionUnit = buildQuestionUnit(question);
            questionUnitList.add(defaultQuestionUnit);
        }

        defaultQuestionStructure.setQuestionUnitList(questionUnitList);
        DefaultQuestion defaultQuestion = new DefaultQuestion();
        defaultQuestion.setId(questionId);
        defaultQuestion.setMasterVersion(defaultQuestionStructure);

        if (examId != null) {
            log.debug("替换试题单元中的音频路径...");
            appendAudioFlag(defaultQuestion, String.valueOf(examId), courseCode, groupCode, question);
        }

        log.debug("封装成新的题单元集合耗时：" + (System.currentTimeMillis() - beginTime) + "ms");
        return defaultQuestion;
    }

    /**
     * 构建试题单元
     *
     * @param question
     * @return
     */
    private DefaultQuestionUnit buildQuestionUnit(Question question) {
        DefaultQuestionUnit defaultQuestionUnit = new DefaultQuestionUnit();
        defaultQuestionUnit.setAnswerType(question.getAnswerType());//作答类型
        defaultQuestionUnit.setBody(question.getQuesBody());
        defaultQuestionUnit.setQuestionType(getByOldType(question.getQuestionType()));

        //如果是单选或者多选，添加选项和答案转换
        if (question.getQuestionType() == QuesStructType.SINGLE_ANSWER_QUESTION
                || question.getQuestionType() == QuesStructType.MULTIPLE_ANSWER_QUESTION) {
            List<DefaultQuestionOption> defaultQuestionOptions = new ArrayList<>();
            List<QuesOption> quesOptions = question.getQuesOptions();

            if (quesOptions != null && quesOptions.size() > 0) {
                for (int i = 0; i < quesOptions.size(); i++) {
                    QuesOption quesOption = quesOptions.get(i);
                    DefaultQuestionOption defaultQuestionOption = new DefaultQuestionOption();
                    defaultQuestionOption.setBody(quesOption.getOptionBody());
                    defaultQuestionOptions.add(defaultQuestionOption);
                }
            }
            defaultQuestionUnit.setQuestionOptionList(defaultQuestionOptions);
            defaultQuestionUnit.setRightAnswer(getSelectQuestionAnswer(quesOptions));
        } else {
            defaultQuestionUnit.setRightAnswer(getAnswer(question));
        }

        return defaultQuestionUnit;
    }

    /**
     * 设置单选题和多选题 答案
     *
     * @param quesOptions
     * @return
     */
    private String[] getSelectQuestionAnswer(List<QuesOption> quesOptions) {
        String[] rightAnswer = null;
        List<String> list = new ArrayList<>();

        if (quesOptions != null && quesOptions.size() > 0) {
            for (int i = 0; i < quesOptions.size(); i++) {
                QuesOption quesOption = quesOptions.get(i);
                if (quesOption.getIsCorrect() == 1) {
                    list.add(String.valueOf(i));
                }
            }
            rightAnswer = list.toArray(new String[list.size()]);
            return rightAnswer;
        }

        return rightAnswer;
    }

    /**
     * 设置试题答案
     *
     * @param question
     * @return
     */
    private String[] getAnswer(Question question) {
        String[] rightAnswer = null;
        //判断题答案
        if (question.getQuestionType() == QuesStructType.BOOL_ANSWER_QUESTION) {
            if (question.getQuesAnswer().equals("正确")) {
                rightAnswer = new String[1];
                rightAnswer[0] = "true";
                return rightAnswer;
            }
            if (question.getQuesAnswer().equals("错误")) {
                rightAnswer = new String[1];
                rightAnswer[0] = "false";
                return rightAnswer;
            }
        }
        //填空题答案
		/*if(question.getQuestionType() == QuesStructType.BOOL_ANSWER_QUESTION){
			rightAnswer = question.getQuesAnswer().split("##");
			return rightAnswer;
		}*/
        rightAnswer = new String[1];
        rightAnswer[0] = question.getQuesAnswer();
        return rightAnswer;
    }

    /**
     * html中添加音频标签
     *
     * @param defaultQuestion
     * @param examId
     * @param courseCode
     * @param groupCode
     * @param question
     */
    private void appendAudioFlag(DefaultQuestion defaultQuestion, String examId, String courseCode, String groupCode, Question question) {
        if (question.getHasAudio() != null && question.getHasAudio() == true) {
            //1.判断questionDto是否含有音频，如果有添加音频播放次数
            AudioTimeConfig audioTimeConfig = Model.of(audioTimeConfigRepo.findOne(Example.of(new AudioTimeConfig(examId, courseCode, groupCode, question.getId()))));
            if (audioTimeConfig != null) {
                //2.1 取到题干，给a标签添加url
                String quesBody = null;
                if (StringUtils.isNotBlank(defaultQuestion.getMasterVersion().getBody())) {
                    //套题
                    quesBody = defaultQuestion.getMasterVersion().getBody();
                    defaultQuestion.getMasterVersion().setBody(buildBody(quesBody, audioTimeConfig.getPlayTime()));
                } else {
                    DefaultQuestionUnit defaultQuestionUnit = (DefaultQuestionUnit) defaultQuestion.getMasterVersion().getQuestionUnitList().get(0);
                    quesBody = defaultQuestionUnit.getBody();
                    defaultQuestionUnit.setBody(buildBody(quesBody, audioTimeConfig.getPlayTime()));
                    if (defaultQuestionUnit.getQuestionType() == QuestionType.SINGLE_CHOICE || defaultQuestionUnit.getQuestionType() == QuestionType.MULTIPLE_CHOICE) {
                        List<DefaultQuestionOption> questionOptionList = defaultQuestionUnit.getQuestionOptionList();
                        if (questionOptionList != null && questionOptionList.size() > 0) {
                            for (int i = 0; i < questionOptionList.size(); i++) {
                                DefaultQuestionOption defaultQuestionOption = questionOptionList.get(i);
                                defaultQuestionOption.setBody(buildBody(defaultQuestionOption.getBody(), audioTimeConfig.getPlayTime()));
                            }
                        }
                    }
                }
            } else {
                String quesBody = null;
                if (StringUtils.isNotBlank(defaultQuestion.getMasterVersion().getBody())) {
                    //套题
                    quesBody = defaultQuestion.getMasterVersion().getBody();
                    defaultQuestion.getMasterVersion().setBody(buildBody(quesBody, null));
                } else {
                    DefaultQuestionUnit defaultQuestionUnit = (DefaultQuestionUnit) defaultQuestion.getMasterVersion().getQuestionUnitList().get(0);
                    quesBody = defaultQuestionUnit.getBody();
                    defaultQuestionUnit.setBody(buildBody(quesBody, null));
                    if (defaultQuestionUnit.getQuestionType() == QuestionType.SINGLE_CHOICE || defaultQuestionUnit.getQuestionType() == QuestionType.MULTIPLE_CHOICE) {
                        List<DefaultQuestionOption> questionOptionList = defaultQuestionUnit.getQuestionOptionList();
                        if (questionOptionList != null && questionOptionList.size() > 0) {
                            for (int i = 0; i < questionOptionList.size(); i++) {
                                DefaultQuestionOption defaultQuestionOption = questionOptionList.get(i);
                                defaultQuestionOption.setBody(buildBody(defaultQuestionOption.getBody(), null));
                            }
                        }
                    }
                }
            }
        }
    }

    /**
     * 给题目和选项添加url
     *
     * @param body
     * @param playTime
     * @return
     */
    public String buildBody(String body, Integer playTime) {
        String[] bodyStrings = body.split("></a>");
        if (bodyStrings.length > 1) {
            String resultBody = "";
            for (int i = 0; i < bodyStrings.length; i++) {
                String containAStr = bodyStrings[i];
                if (containAStr.indexOf("<a") > -1) {
                    String questionAudioId = matchAudioName(containAStr, "a", "id");
                    QuestionAudio questionAudio = questionAudioService.findAudioById(questionAudioId);
                    if (questionAudio != null) {
                        String url = upYunProperty.getDownloadUrl() + questionAudio.getFileUrl();
                        if (playTime != null) {
                            containAStr += " question-audio url=\"" + url + "\" playTime=\"" + playTime + "\"" + "></a>";
                        } else {
                            containAStr += " question-audio url=\"" + url + "\"" + "></a>";
                        }
                    }
                }
                resultBody += containAStr;
            }
            return resultBody;
        } else {
            return body;
        }
    }

    /**
     * 获取一段html中某个标签的值
     *
     * @param source
     * @param element
     * @param attr
     * @return
     */
    private String matchAudioName(String source, String element, String attr) {
        String reg = "<" + element + "[^<>]*?\\s" + attr + "=['\"]?(.*?)['\"]?(\\s.*?)";
        Matcher m = Pattern.compile(reg).matcher(source);
        while (m.find()) {
            return m.group(1);
        }
        return "";
    }

    /**
     * 检查所有题目是否为客观题
     *
     * @param paperDetailUnits
     * @return
     */
    private boolean checkIsAllQbjectiveQuestion(List<PaperDetailUnit> paperDetailUnits) {
        for (PaperDetailUnit paperDetailUnit : paperDetailUnits) {
            Question question = paperDetailUnit.getQuestion();
            //填空或问答
            if (question.getQuestionType() == QuesStructType.FILL_BLANK_QUESTION
                    || question.getQuestionType() == QuesStructType.TEXT_ANSWER_QUESTION) {
                return false;
            }
            if (question.getQuestionType() == QuesStructType.NESTED_ANSWER_QUESTION) {
                List<Question> subQuestions = question.getSubQuestions();
                for (Question subQuestion : subQuestions) {
                    if (subQuestion.getQuestionType() == QuesStructType.FILL_BLANK_QUESTION
                            || subQuestion.getQuestionType() == QuesStructType.TEXT_ANSWER_QUESTION) {
                        return false;
                    }
                }
            }
        }
        return true;
    }

    @Override
    public DefaultPaper getBaseDefaultPaper(String paperId) {
        Paper basePaper = Model.of(paperRepo.findById(paperId));
        if (basePaper == null) {
            log.error("该考试和课程下调卷规则中该类型试卷不存在,请检查调卷规则,调卷程序退出");
            throw new StatusException("Q-020560", "该考试和课程下调卷规则中试卷不存在,请重新制定调卷规则");
        }

        //构建试卷结构
        DefaultPaper defaultPaper = this.buildDefaultByBasePaper(basePaper, null, null, null);
        return defaultPaper;
    }

    @Override
    public Map<String, DefaultQuestion> getDefaultQuestions(Set<String> questionIds) {
        Map<String, DefaultQuestion> map = new HashMap<String, DefaultQuestion>();
        List<Question> questions = quesRepo.findByIdIn(questionIds);
        if (CollectionUtils.isEmpty(questions)) {
            log.error("根据试题id的集合没有查询到试题结合");
            throw new StatusException("Q-020572", "根据试题id的集合没有查询到试题结合");
        }
        for (Question question : questions) {
            DefaultQuestion defaultQuestion = getDefaultQuestion(null, null, null, question.getId());
            map.put(question.getId(), defaultQuestion);
        }
        return map;
    }

    @Override
    public List<String> getAnswer(String questionId) {
        List<String> list = new ArrayList<String>();
        Question question = Model.of(quesRepo.findById(questionId));
        if (question.getQuestionType() == QuesStructType.NESTED_ANSWER_QUESTION) {
            List<Question> subList = question.getSubQuestions();
            if (subList != null && subList.size() > 0) {
                String answer = "";
                for (Question subQuestion : subList) {
                    if (subQuestion.getQuestionType() == QuesStructType.SINGLE_ANSWER_QUESTION || subQuestion.getQuestionType() == QuesStructType.MULTIPLE_ANSWER_QUESTION) {
                        String[] answers = getSelectQuestionAnswer(subQuestion.getQuesOptions());
                        for (int i = 0; i < answers.length; i++) {
                            if (i == 0) {
                                answer = answers[i];
                            }
                            answer = answer + "," + answers[i];
                        }
                    } else if (subQuestion.getQuestionType() == QuesStructType.BOOL_ANSWER_QUESTION) {
                        if (subQuestion.getQuesAnswer().endsWith("正确")) {
                            answer = "true";
                        } else {
                            answer = "false";
                        }
                    } else {
                        answer = subQuestion.getQuesAnswer();
                    }
                    list.add(answer);
                }
            }
        } else {
            String answer = "";
            if (question.getQuestionType() == QuesStructType.SINGLE_ANSWER_QUESTION || question.getQuestionType() == QuesStructType.MULTIPLE_ANSWER_QUESTION) {
                String[] answers = getSelectQuestionAnswer(question.getQuesOptions());
                for (int i = 0; i < answers.length; i++) {
                    if (i == 0) {
                        answer = answers[i];
                    }
                    answer = answer + "," + answers[i];
                }
            } else if (question.getQuestionType() == QuesStructType.BOOL_ANSWER_QUESTION) {
                if (question.getQuesAnswer().endsWith("正确")) {
                    answer = "true";
                } else {
                    answer = "false";
                }
            } else {
                answer = question.getQuesAnswer();
            }
            list.add(answer);
        }
        return list;
    }

    @Override
    public String getQuestionStructure(String paperId) throws Exception {
        String json = paperService.findQuestionStructure(paperId);
        return json;
    }

}
