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

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.bson.types.ObjectId;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

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.Model;
import cn.com.qmth.examcloud.core.questions.base.enums.PaperStructType;
import cn.com.qmth.examcloud.core.questions.base.enums.PaperType;
import cn.com.qmth.examcloud.core.questions.base.enums.QuestionDifficulty;
import cn.com.qmth.examcloud.core.questions.base.exception.QuesNotEnoughException;
import cn.com.qmth.examcloud.core.questions.base.question.enums.QuesStructType;
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.PaperStructRepo;
import cn.com.qmth.examcloud.core.questions.dao.entity.Course;
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.PaperDetailStruct;
import cn.com.qmth.examcloud.core.questions.dao.entity.PaperDetailUnit;
import cn.com.qmth.examcloud.core.questions.dao.entity.PaperStruct;
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.PaperDetailUnitService;
import cn.com.qmth.examcloud.core.questions.service.PaperService;
import cn.com.qmth.examcloud.core.questions.service.bean.context.DetailContext;
import cn.com.qmth.examcloud.core.questions.service.bean.context.PaperContext;
import cn.com.qmth.examcloud.core.questions.service.bean.context.UnitContext;
import cn.com.qmth.examcloud.core.questions.service.bean.dto.GenPaperDto;
import cn.com.qmth.examcloud.core.questions.service.bean.dto.NumberDto;
import cn.com.qmth.examcloud.core.questions.service.util.PaperUtil;

@Service
public class GenPaperService {

    private static final Logger LOG = LoggerFactory.getLogger(GenPaperService.class);

    @Autowired
    PaperRepo paperRepo;

    @Autowired
    PaperDetailRepo paperDetailRepo;

    @Autowired
    PaperDetailUnitRepo unitRepo;

    @Autowired
    PaperStructRepo paperStructRepo;

    @Autowired
    CourseService courseService;

    @Autowired
    PaperService paperService;

    @Autowired
    PaperDetailUnitService paperDetailUnitService;

    /**
     * 精确组卷，根据设定试卷结构组卷
     *
     * @return
     */
    @SuppressWarnings("unchecked")
    public Map<String, Object> genPaper(GenPaperDto genPaperDto) {
        LOG.debug("开始组卷.....");
        String msg = "";
        Map<String, Object> paperMsgMap = new HashMap<>();
        LinkedList<Question> questions = new LinkedList<>();
        //查询试卷结构
        long start = System.currentTimeMillis();
        PaperStruct paperStruct = Model.of(paperStructRepo.findById(genPaperDto.getPaperStructId()));
        if (paperStruct == null) {
            paperMsgMap.put("msg", "试卷结构不存在");
            return paperMsgMap;
        }
        PaperContext paperContext = new PaperContext(paperStruct, genPaperDto.getConditions());
        List<UnitContext> unitContexts = new LinkedList<>();
        List<DetailContext> detailContexts = paperContext.getDetails();
        for (DetailContext dc : detailContexts) {
            unitContexts.addAll(dc.getUnits());
        }
        List<Paper> papers = paperRepo.findByIdIn(genPaperDto.getPaperIds());
        List<PaperDetailUnit> unitList = new ArrayList<>();
        for (Paper oldPaper : papers) {
            //unitList.addAll(unitRepo.findByPaperOrderByNumber(oldPaper));
            for (PaperDetailUnit paperDetailUnit : unitRepo.findByPaperOrderByNumber(oldPaper)) {
                unitList.add(paperDetailUnit);
            }
        }
        Set<PaperDetailUnit> spareUnits = new HashSet<>();
        spareUnits.addAll(unitList);
        long total = (System.currentTimeMillis() - start) / 1000;
        LOG.debug("total:" + total);
    	
    	/*for (PaperDetailUnit unit : spareUnits) {
            Question question = unit.getQuestion();
            //根据questionId查询题库中大题来源
            List<PaperDetailUnit> units = unitRepo.findByQuestion(question);
            for(PaperDetailUnit oldUnit:units){
            	Paper paper = oldUnit.getPaper();
            	if(paper.getPaperType() == PaperType.IMPORT){
            		 question.setQuesName(oldUnit.getPaperDetail().getName());
            		 break;
            	}
            }
            question.setQuesName(unit.getPaperDetail().getName());
            questions.add(question);
        }*/

        List<String> oIds = new ArrayList<>();
        for (PaperDetailUnit unit : spareUnits) {
            oIds.add(unit.getQuestion().getId());
        }
        LOG.debug("total2.....--------实际原题数量:" + oIds.size());
        long start2 = System.currentTimeMillis();
        List<PaperDetailUnit> oDetailUnits = paperDetailUnitService.findByQuestionsAndPaperType(oIds, PaperType.IMPORT);
        long total2 = (System.currentTimeMillis() - start2) / 1000;
        LOG.debug("total2....." + total2 + "--------查询原题数量:" + oDetailUnits.size());
        long start4 = System.currentTimeMillis();
        for (PaperDetailUnit oldUnit : oDetailUnits) {
            if (oldUnit.getPaper().getPaperType() == PaperType.IMPORT) {
                Question question = oldUnit.getQuestion();
                if (question.getPublicity() == null) {
                    question.setPublicity(true);
                }
                if (StringUtils.isBlank(question.getDifficulty())) {
                    question.setDifficulty("中");
                }
                question.setQuesName(oldUnit.getPaperDetail().getName());
                question.setPropertyGroup(bulidGroup(question));
                questions.add(question);
            }
        }
        long total4 = (System.currentTimeMillis() - start4) / 1000;
        LOG.debug("循环耗时....." + total4 + "--------最终原题数量:" + questions.size());
        Collections.shuffle(questions);
        int maxLoopCount = questions.size() * 2;
        int selectCount = 0;
        int maxCount = unitContexts.size();
        int loopCount = 0;
        while (questions.size() > 0 && (selectCount < maxCount) && loopCount < maxLoopCount) {
            Question question = questions.removeFirst();
            boolean structTypeMatch = false;
            boolean selected = false;
            for (UnitContext uc : unitContexts) {
                if (checkQuesType(uc, question)) {
                    structTypeMatch = true;
                    if (uc.check(question)) {
                        uc.select(question);
                        selected = true;
                        selectCount++;
                        break;
                    }
                }
            }
            if (structTypeMatch && !selected) {
                questions.addLast(question);
            }
            loopCount++;
        }
        Set<Question> quesSet = paperContext.getSelectQues();
        if (quesSet.size() < unitContexts.size()) {
            msg = "匹配的题源不足，请核查";
            paperMsgMap.put("msg", msg);
            return paperMsgMap;
        }
        List<Object> list = paperContext.build(paperStruct);
        if (list != null && list.size() == 3) {
            Paper paper = (Paper) list.get(0);
            List<PaperDetail> paperDetails = (List<PaperDetail>) list.get(1);
            List<PaperDetailUnit> paperDetailunits = (List<PaperDetailUnit>) list.get(2);
            // 补全paper属性
            paper.setExamRemark(paperStruct.getExamRemark());
            paper.setName(genPaperDto.getPaperName());
            paper.setCourseNo(genPaperDto.getCourseNo());
            paper.setCourseName(genPaperDto.getCourseName());
            Course course = courseService.getCourse(Long.valueOf(genPaperDto.getOrgId()), genPaperDto.getCourseNo());
            paper.setCourse(course);
            paper.setCreator(genPaperDto.getCreator());
            paper.setOrgId(genPaperDto.getOrgId());
            paper.setLevel(genPaperDto.getLevel());
            paper.setCreateTime(CommonUtils.getCurDateTime());
            paper.setUnitCount(this.getTotalQuesNum(paperDetailunits));
            paper.setPaperType(PaperType.GENERATE);
            // 数据入库
            long start3 = System.currentTimeMillis();
            paper = this.persistentPaper(PaperStructType.EXACT, paperDetailunits, paperDetails, paper);
            long total3 = (System.currentTimeMillis() - start3) / 1000;
            LOG.debug("total3....." + total3);
            msg = "success";
            paperMsgMap.put("paper", paper);
            paperMsgMap.put("msg", msg);
        }
        return paperMsgMap;
    }

    /**
     * 校验来源大题名称
     *
     * @param uc
     * @param question
     * @return
     */
    private boolean checkQuesType(UnitContext uc, Question question) {
        List<String> quesNames = uc.getUnitStruct().getQuesNames();
        if (quesNames != null && quesNames.size() > 0) {
            if (quesNames.contains(question.getQuesName()) && !uc.finish() && (uc.getUnitStruct().getQuestionType() == question.getQuestionType())) {
                if(QuestionDifficulty.ANY.getName().equals(uc.getUnitStruct().getDifficulty())) {//难度不限
                    if (question.getPublicity().equals(uc.getUnitStruct().getPublicity())) {
                        return true;
                    }
                }else {
	            	if (question.getPropertyGroup() != null) {
	                    if (question.getPropertyGroup().contains(uc.getUnitStruct().getPropertyGroup())) {
	                        return true;
	                    }
	                }
                }
            }
        }
        return false;
    }

    /**
     * 按分数在选定的试卷中随机抽取题,组成一套新的试卷
     *
     * @param genPaperDto
     * @return Map<String, Object>
     * @author weiwenhai
     */
    public Map<String, Object> genPaperByScore(GenPaperDto genPaperDto, User user) {
        Map<String, Object> paperMsgMap = extractByQuestioScore(genPaperDto, user);
        return paperMsgMap;
    }

    //计算试题集合总分
    private Double sum(List<PaperDetailUnit> unitList) {
        Double sum = 0.0;
        if (unitList != null && unitList.size() > 0) {
            for (PaperDetailUnit paperDetailUnit : unitList) {
                sum = sum + paperDetailUnit.getScore();
            }
            return sum;
        }
        return sum;
    }

    //通过题目分数组卷
    private Map<String, Object> extractByQuestioScore(GenPaperDto genPaperDto, User user) {
        Map<String, Object> paperMsgMap = new HashMap<>();
        //获取所有试卷与分数
        //Map<String, Double> paperMap = genPaperDto.getSimpleParams();
        Map<String, NumberDto> paperMap = genPaperDto.getSimpleParams();
        if (paperMap != null && paperMap.size() > 0) {
            //定义随机选中的小题集合
            List<PaperDetailUnit> selectedUnits = new ArrayList<>();
            //将所有小题按questionId去重，并按试卷分类
            Map<String, List<PaperDetailUnit>> unitMap = sortUnitsByPaper(paperMap,genPaperDto.getFrozenPaperIds());
            //随机抽题
            for (String paperId : paperMap.keySet()) {
                NumberDto numberDto = paperMap.get(paperId);
                //随机抽取分数
                Double needScore = numberDto.getCount();
                //取到该试卷下所有小题
                List<PaperDetailUnit> unitList = unitMap.get(paperId);
                //试卷总分
                double sum = sum(unitList);
                Paper paper = Model.of(paperRepo.findById(paperId));
                if (sum < needScore.doubleValue() || needScore.doubleValue() == 0) {
                    if (needScore.doubleValue() == 0) {
                        paperMsgMap.put("msg", "\"" + paper.getName() + "\"试卷，组卷分数不能为0");
                        return paperMsgMap;
                    }
                    paperMsgMap.put("msg", "\"" + paper.getName() + "\"试卷，分数不够");
                    return paperMsgMap;
                }
                //将所有试题按照 公开度  和  难度   进行分类
                Map<String, List<PaperDetailUnit>> paperUnitMap = sortUnitsByProperty(unitList);
//                List<PaperDetailUnit> newDetailUnits = new ArrayList<>();
                //获取公开简单数量
                if (numberDto.getPublicSimple() > 0) {
                    Double needUnitScore = numberDto.getPublicSimple();
                    List<PaperDetailUnit> units = paperUnitMap.get("true-易");
                    //公开简单总分
                    Double unitsScore = sum(units);
                    if (units == null || needUnitScore > unitsScore) {
                        paperMsgMap.put("msg", "\"" + paper.getName() + "\"试卷，题源不够");
                        return paperMsgMap;
                    }
                    try {
						commonScoreList(needUnitScore, units, selectedUnits, genPaperDto.getCreator());
					} catch (QuesNotEnoughException e) {
						paperMsgMap.put("msg", "\"" + paper.getName() + "\"试卷，题源不够");
                        return paperMsgMap;
					}
                }
                //获取公开中等数量
                if (numberDto.getPublicMedium() > 0) {
                    Double needUnitScore = numberDto.getPublicMedium();
                    List<PaperDetailUnit> units = paperUnitMap.get("true-中");
                    //公开中等总分
                    Double unitsScore = sum(units);
                    if (units == null || needUnitScore > unitsScore) {
                        paperMsgMap.put("msg", "\"" + paper.getName() + "\"试卷，题源不够");
                        return paperMsgMap;
                    }
                    try {
						commonScoreList(needUnitScore, units, selectedUnits, genPaperDto.getCreator());
					} catch (QuesNotEnoughException e) {
						paperMsgMap.put("msg", "\"" + paper.getName() + "\"试卷，题源不够");
                        return paperMsgMap;
					}
                }
                //获取公开困难数量
                if (numberDto.getPublicDifficulty() > 0) {
                    Double needUnitScore = numberDto.getPublicDifficulty();
                    List<PaperDetailUnit> units = paperUnitMap.get("true-难");
                    //公开困难总分
                    Double unitsScore = sum(units);
                    if (units == null || needUnitScore > unitsScore) {
                        paperMsgMap.put("msg", "\"" + paper.getName() + "\"试卷，题源不够");
                        return paperMsgMap;
                    }
                    try {
						commonScoreList(needUnitScore, units, selectedUnits, genPaperDto.getCreator());
					} catch (QuesNotEnoughException e) {
						paperMsgMap.put("msg", "\"" + paper.getName() + "\"试卷，题源不够");
                        return paperMsgMap;
					}
                }
                //获取非公开简单
                if (numberDto.getNoPublicSimple() > 0) {
                    Double needUnitScore = numberDto.getNoPublicSimple();
                    List<PaperDetailUnit> units = paperUnitMap.get("false-易");
                    //非公开简单总分
                    Double unitsScore = sum(units);
                    if (units == null || needUnitScore > unitsScore) {
                        paperMsgMap.put("msg", "\"" + paper.getName() + "\"试卷，题源不够");
                        return paperMsgMap;
                    }
                    try {
						commonScoreList(needUnitScore, units, selectedUnits, genPaperDto.getCreator());
					} catch (QuesNotEnoughException e) {
						paperMsgMap.put("msg", "\"" + paper.getName() + "\"试卷，题源不够");
                        return paperMsgMap;
					}
                }
                //获取非公开中等
                if (numberDto.getNoPublicMedium() > 0) {
                    Double needUnitScore = numberDto.getNoPublicMedium();
                    List<PaperDetailUnit> units = paperUnitMap.get("false-中");
                    //非公开中等总分
                    Double unitsScore = sum(units);
                    if (units == null || needUnitScore > unitsScore) {
                        paperMsgMap.put("msg", "\"" + paper.getName() + "\"试卷，题源不够");
                        return paperMsgMap;
                    }
                    try {
						commonScoreList(needUnitScore, units, selectedUnits, genPaperDto.getCreator());
					} catch (QuesNotEnoughException e) {
						paperMsgMap.put("msg", "\"" + paper.getName() + "\"试卷，题源不够");
                        return paperMsgMap;
					}
                }
                //获取非公开困难
                if (numberDto.getNoPublicDifficulty() > 0) {
                    Double needUnitScore = numberDto.getNoPublicDifficulty();
                    List<PaperDetailUnit> units = paperUnitMap.get("false-难");
                    //非公开困难总分
                    Double unitsScore = sum(units);
                    if (units == null || needUnitScore > unitsScore) {
                        paperMsgMap.put("msg", "\"" + paper.getName() + "\"试卷，题源不够");
                        return paperMsgMap;
                    }
                    try {
						commonScoreList(needUnitScore, units, selectedUnits, genPaperDto.getCreator());
					} catch (QuesNotEnoughException e) {
						paperMsgMap.put("msg", "\"" + paper.getName() + "\"试卷，题源不够");
                        return paperMsgMap;
					}
                }
                //生成随机抽取的题号
    		  /*List<Integer> questionsIndex = new ArrayList<>();
    			questionsIndex = CommonUtils.getRandom(questionsIndex, unitList.size(), unitList.size());
    			//定义随机抽题的数量
    			double lastScore = 0;
    			for(Integer index:questionsIndex){
    				PaperDetailUnit newUnit = unitList.get(index);
    				//如果抽题的数量大于所需的题量，跳出循环
    				if(lastScore >= needScore.doubleValue()){
    					break;
    				}
    				lastScore += newUnit.getScore();
					newUnit.setId(null);
					newUnit.setCreator(genPaperDto.getCreator());
					newUnit.setCreateTime(CommonUtils.getCurDateTime());
					newUnit.setPaperType(PaperType.GENERATE);
					newDetailUnits.add(newUnit);
    			}*/
//                selectedUnits.addAll(newDetailUnits);
            }
            if (selectedUnits == null || selectedUnits.size() < 1) {
                paperMsgMap.put("msg", "组卷分数为0，组卷失败");
                return paperMsgMap;
            }
            //把集合里面的小题按相同的大题分类
            Map<String, List<PaperDetailUnit>> map = sortPaperDeatilUnit(selectedUnits);
            //构建新的大题
            List<PaperDetail> paperDetails = buildPaperDetail(map, genPaperDto);
            //构建新的试卷
            Paper paper = buildPaper(map, genPaperDto, paperDetails, user);
            paperMsgMap.put("paper", paper);
            paperMsgMap.put("msg", "success");
            return paperMsgMap;
        }
        return null;
    }

    /**
     * 按每套试卷需要抽取的题目数量随机抽取题,组成一套新的试卷
     *
     * @param genPaperDto
     * @return Map<String, Object>
     * @author weiwenhai
     */
    public Map<String, Object> genPaperByQuestionNum(GenPaperDto genPaperDto, User user) {
        Map<String, Object> paperMsgMap = extractByQuestionNum(genPaperDto, user);
        return paperMsgMap;
    }

    //通过题目数量组卷
    private Map<String, Object> extractByQuestionNum(GenPaperDto genPaperDto, User user) {
        Map<String, Object> paperMsgMap = new HashMap<>();
        //获取所有试卷与抽题数
        Map<String, NumberDto> paperMap = genPaperDto.getSimpleParams();
        if (paperMap != null && paperMap.size() > 0) {
            //定义随机选中的小题集合
            List<PaperDetailUnit> selectedUnits = new ArrayList<>();
            //将所有小题按questionId去重，并按试卷分类
            Map<String, List<PaperDetailUnit>> unitMap = sortUnitsByPaper(paperMap,genPaperDto.getFrozenPaperIds());
            //随机抽题
            for (String paperId : paperMap.keySet()) {
                //随机抽题数量
                NumberDto numberDto = paperMap.get(paperId);
                Integer needNumber = Integer.valueOf(numberDto.getCount().intValue());
                //取到该试卷下所有小题
                List<PaperDetailUnit> unitList = unitMap.get(paperId);
                //计算所有题目数量
                int questionSum = countQuestions(unitList);
                Paper paper = Model.of(paperRepo.findById(paperId));
                if (needNumber > questionSum || needNumber == 0) {
                    if (needNumber == 0) {
                        paperMsgMap.put("msg", "\"" + paper.getName() + "\"试卷，组卷数量不能为0");
                        return paperMsgMap;
                    }
                    paperMsgMap.put("msg", "\"" + paper.getName() + "\"试卷，题源不够");
                    return paperMsgMap;
                }
                //将所有试题按照 公开度  和  难度   进行分类
                Map<String, List<PaperDetailUnit>> paperUnitMap = sortUnitsByProperty(unitList);
//                List<PaperDetailUnit> newDetailUnits = new ArrayList<>();
                //获取公开简单数量
                if (numberDto.getPublicSimple() > 0) {
                    Integer needUnits = Integer.valueOf(numberDto.getPublicSimple().intValue());
                    List<PaperDetailUnit> units = paperUnitMap.get("true-易");
                    if (units == null || needUnits > units.size()) {
                        paperMsgMap.put("msg", "\"" + paper.getName() + "\"试卷，题源不够");
                        return paperMsgMap;
                    }
                    try {
						commonNumList(needUnits, units, selectedUnits, genPaperDto.getCreator());
					} catch (QuesNotEnoughException e) {
						paperMsgMap.put("msg", "\"" + paper.getName() + "\"试卷，题源不够");
                        return paperMsgMap;
					}
                }
                //获取公开中等数量
                if (numberDto.getPublicMedium() > 0) {
                    Integer needUnits = Integer.valueOf(numberDto.getPublicMedium().intValue());
                    List<PaperDetailUnit> units = paperUnitMap.get("true-中");
                    if (units == null || needUnits > units.size()) {
                        paperMsgMap.put("msg", "\"" + paper.getName() + "\"试卷，题源不够");
                        return paperMsgMap;
                    }
                    try {
						commonNumList(needUnits, units, selectedUnits, genPaperDto.getCreator());
					} catch (QuesNotEnoughException e) {
						paperMsgMap.put("msg", "\"" + paper.getName() + "\"试卷，题源不够");
                        return paperMsgMap;
					}
                }
                //获取公开困难数量
                if (numberDto.getPublicDifficulty() > 0) {
                    Integer needUnits = Integer.valueOf(numberDto.getPublicDifficulty().intValue());
                    List<PaperDetailUnit> units = paperUnitMap.get("true-难");
                    if (units == null || needUnits > units.size()) {
                        paperMsgMap.put("msg", "\"" + paper.getName() + "\"试卷，题源不够");
                        return paperMsgMap;
                    }
                    try {
						commonNumList(needUnits, units, selectedUnits, genPaperDto.getCreator());
					} catch (QuesNotEnoughException e) {
						paperMsgMap.put("msg", "\"" + paper.getName() + "\"试卷，题源不够");
                        return paperMsgMap;
					}
                }
                //获取非公开简单
                if (numberDto.getNoPublicSimple() > 0) {
                    Integer needUnits = Integer.valueOf(numberDto.getNoPublicSimple().intValue());
                    List<PaperDetailUnit> units = paperUnitMap.get("false-易");
                    if (units == null || needUnits > units.size()) {
                        paperMsgMap.put("msg", "\"" + paper.getName() + "\"试卷，题源不够");
                        return paperMsgMap;
                    }
                    try {
						commonNumList(needUnits, units, selectedUnits, genPaperDto.getCreator());
					} catch (QuesNotEnoughException e) {
						paperMsgMap.put("msg", "\"" + paper.getName() + "\"试卷，题源不够");
                        return paperMsgMap;
					}
                }
                //获取非公开中等
                if (numberDto.getNoPublicMedium() > 0) {
                    Integer needUnits = Integer.valueOf(numberDto.getNoPublicMedium().intValue());
                    List<PaperDetailUnit> units = paperUnitMap.get("false-中");
                    if (units == null || needUnits > units.size()) {
                        paperMsgMap.put("msg", "\"" + paper.getName() + "\"试卷，题源不够");
                        return paperMsgMap;
                    }
                    try {
						commonNumList(needUnits, units, selectedUnits, genPaperDto.getCreator());
					} catch (QuesNotEnoughException e) {
						paperMsgMap.put("msg", "\"" + paper.getName() + "\"试卷，题源不够");
                        return paperMsgMap;
					}
                }
                //获取非公开困难
                if (numberDto.getNoPublicDifficulty() > 0) {
                    Integer needUnits = Integer.valueOf(numberDto.getNoPublicDifficulty().intValue());
                    List<PaperDetailUnit> units = paperUnitMap.get("false-难");
                    if (units == null || needUnits > units.size()) {
                        paperMsgMap.put("msg", "\"" + paper.getName() + "\"试卷，题源不够");
                        return paperMsgMap;
                    }
                    try {
						commonNumList(needUnits, units, selectedUnits, genPaperDto.getCreator());
					} catch (QuesNotEnoughException e) {
						paperMsgMap.put("msg", "\"" + paper.getName() + "\"试卷，题源不够");
                        return paperMsgMap;
					}
                }
                //生成随机抽取的题号
    			/*List<Integer> questionsIndex = new ArrayList<>();
    			questionsIndex = CommonUtils.getRandom(questionsIndex, unitList.size(), unitList.size());*/
                //定义随机抽题的数量
    			/*int lastNumber = 0;
    			
    			for(Integer index:questionsIndex){
    				PaperDetailUnit newUnit = unitList.get(index);
    				//如果抽题的数量大于所需的题量，跳出循环
    				if(lastNumber >= needNumber){
    					break;
    				}
    				//如果是套题，取子题数量
    				if(unitList.get(index).getQuestion().getQuestionType() == QuesStructType.NESTED_ANSWER_QUESTION){
    					List<Question> subQuestions = newUnit.getQuestion().getSubQuestions();
    					lastNumber += subQuestions.size();
    				}else {
    					lastNumber += 1;
					}
					newUnit.setId(null);
					newUnit.setCreator(genPaperDto.getCreator());
					newUnit.setCreateTime(CommonUtils.getCurDateTime());
					newUnit.setPaperType(PaperType.GENERATE);
					newDetailUnits.add(newUnit);
    			}*/
//                selectedUnits.addAll(newDetailUnits);
            }
            if (selectedUnits == null || selectedUnits.size() < 1) {
                paperMsgMap.put("msg", "试题数量为0，组卷失败");
                return paperMsgMap;
            }
            //把集合里面的小题按相同的大题分类
            Map<String, List<PaperDetailUnit>> map = sortPaperDeatilUnit(selectedUnits);
            //构建新的大题
            List<PaperDetail> paperDetails = buildPaperDetail(map, genPaperDto);
            //构建新的试卷
            Paper paper = buildPaper(map, genPaperDto, paperDetails, user);
            paperMsgMap.put("paper", paper);
            paperMsgMap.put("msg", "success");
        }
        return paperMsgMap;
    }

    /**
     * 按数量公共抽题方法
     *
     * @param needUnits
     * @param units
     * @param selectedUnits
     * @param name
     * @return
     * @throws QuesNotEnoughException 
     */
    private void commonNumList(Integer needUnits, List<PaperDetailUnit> units, List<PaperDetailUnit> selectedUnits, String name) throws QuesNotEnoughException {
        Collections.shuffle(units);
        int lastNumber = 0;
        for (PaperDetailUnit newUnit:units) {
            //如果抽题的数量大于所需的题量，跳出循环
            if (lastNumber >= needUnits) {
                break;
            }
            if(checkExist(selectedUnits, newUnit)) {
            	continue;
            }
            //如果是套题，取子题数量
            if (newUnit.getQuestion().getQuestionType() == QuesStructType.NESTED_ANSWER_QUESTION) {
                List<Question> subQuestions = newUnit.getQuestion().getSubQuestions();
                lastNumber += subQuestions.size();
            } else {
                lastNumber += 1;
            }
            newUnit.setId(null);
            newUnit.setCreator(name);
            newUnit.setCreateTime(CommonUtils.getCurDateTime());
            selectedUnits.add(newUnit);
        }
        if(lastNumber<needUnits) {
        	throw new QuesNotEnoughException(); 
        }
    }

    /**
     * 按分数公共抽题方法
     *
     * @param needUnitScore
     * @param units
     * @param selectedUnits
     * @param name
     * @return
     * @throws QuesNotEnoughException 
     */
    private void commonScoreList(Double needUnitScore, List<PaperDetailUnit> units, List<PaperDetailUnit> selectedUnits, String name) throws QuesNotEnoughException {
        Collections.shuffle(units);
        double sum = 0.0;
        for (PaperDetailUnit unit : units) {
            if (sum >= needUnitScore) {
                break;
            }
            if(checkExist(selectedUnits, unit)) {
            	continue;
            }
            PaperDetailUnit newUnit = unit;
            sum += newUnit.getScore();
            newUnit.setId(null);
            newUnit.setCreator(name);
            newUnit.setCreateTime(CommonUtils.getCurDateTime());
            selectedUnits.add(newUnit);
        }
        if(sum<needUnitScore) {
        	throw new QuesNotEnoughException(); 
        }
    }
    
    private boolean checkExist(List<PaperDetailUnit> selectedUnits,PaperDetailUnit unit) {
    	for(PaperDetailUnit pu:selectedUnits) {
    		if(pu.equals(unit)) {
    			return true;
    		}
    	}
    	return false;
    }

    //将所有小题并按试卷分类
    private Map<String, List<PaperDetailUnit>> sortUnitsByPaper(Map<String, NumberDto> paperMap,List<String> frozenPaperIds) {
        if (paperMap == null || paperMap.isEmpty()) {
            return new HashMap<>();
        }
        
        //冻结小题id集合
        Set<String> frozenQuestionIds = new HashSet<>();

        //所有小题集合
        List<PaperDetailUnit> oldUnits = new ArrayList<>();
        
        //取到所有冻结小题
        if(CollectionUtils.isNotEmpty(frozenPaperIds)) {
        	for (String paperId : frozenPaperIds) {
        		//取到所有小题
                Paper paper = Model.of(paperRepo.findById(paperId));
                List<PaperDetailUnit> unitList = unitRepo.findByPaperOrderByNumber(paper);
                oldUnits.addAll(unitList);
                //加入到冻结小题集合
            	List<String> tempIds=unitList.stream().map(dto -> dto.getQuestion().getId()).distinct().collect(Collectors.toList());
        		frozenQuestionIds.addAll(tempIds);
        	}
        }

        //取到试卷id
        for (String paperId : paperMap.keySet()) {
        	if(CollectionUtils.isNotEmpty(frozenPaperIds)) {
            	if(!frozenPaperIds.contains(paperId)) {
            		//取到所有非冻结小题
    	            Paper paper = Model.of(paperRepo.findById(paperId));
    	            List<PaperDetailUnit> unitList = unitRepo.findByPaperOrderByNumber(paper);
    	            for(PaperDetailUnit pdu:unitList) {
    	            	if(!frozenQuestionIds.contains(pdu.getQuestion().getId())) {
    	            		oldUnits.add(pdu);
    	            	}
    	            }
            	}
        	}else {
        		//取到所有非冻结小题
	            Paper paper = Model.of(paperRepo.findById(paperId));
	            List<PaperDetailUnit> unitList = unitRepo.findByPaperOrderByNumber(paper);
	            oldUnits.addAll(unitList);
        	}
        }

//        如果是卷库来源，进行questionId去重(变更，不去重)
//        Set<PaperDetailUnit> spareUnits = new HashSet<>();
//        spareUnits.addAll(oldUnits);
        Map<String, List<PaperDetailUnit>> map = new HashMap<>();

        List<PaperDetailUnit> units;
        for (PaperDetailUnit unit : oldUnits) {
            if (map.get(unit.getPaper().getId()) == null) {
                units = new ArrayList<>();
            } else {
                units = map.get(unit.getPaper().getId());
            }

            units.add(unit);
            map.put(unit.getPaper().getId(), units);
        }

        return map;
    }

    //将试卷下面的所有小题按照 公开度  和   难度  进行分类
    private Map<String, List<PaperDetailUnit>> sortUnitsByProperty(List<PaperDetailUnit> units) {
        Map<String, List<PaperDetailUnit>> map = new HashMap<>();
        if (units != null && units.size() > 0) {
            for (PaperDetailUnit unit : units) {
                Question question = unit.getQuestion();
                if (question.getPublicity() == null) {
                    question.setPublicity(true);
                }
                if (StringUtils.isBlank(question.getDifficulty())) {
                    question.setDifficulty("中");
                }
                String key = question.getPublicity() + "-" + question.getDifficulty();
                List<PaperDetailUnit> units2 = null;
                if (map.get(key) != null && map.get(key).size() > 0) {
                    units2 = map.get(key);
                } else {
                    units2 = new ArrayList<>();
                }
                units2.add(unit);
                map.put(key, units2);
            }
            return map;
        }
        return null;
    }

    //构建新的试卷
    private Paper buildPaper(Map<String, List<PaperDetailUnit>> map, GenPaperDto genPaperDto, List<PaperDetail> paperDetails, User user) {
        Paper paper = this.constuctPaperByPaperDetails(paperDetails, genPaperDto);
        double sum = 0;
        for (String name : map.keySet()) {
            List<PaperDetailUnit> units = map.get(name);
            for (PaperDetailUnit unit : units) {
                if (unit.getQuestion().getScore() == null) {
                    unit.setScore(0d);
                }
                if (unit.getQuestion().getDifficultyDegree() == null) {
                    unit.getQuestion().setDifficultyDegree(0.5);
                }
                sum += unit.getScore() * unit.getQuestion().getDifficultyDegree();
            }
        }
        if (paper.getTotalScore() < 0.1) {
            paper.setDifficultyDegree(0d);
        } else {
            BigDecimal b = BigDecimal.valueOf(sum / paper.getTotalScore());
            Double difficulty = b.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
            //赋值难度
            paper.setDifficultyDegree(difficulty);
        }
        paper = paperRepo.save(paper);
        int number = 0;
        int allQuesCount = 0;
        for (int i = 0; i < paperDetails.size(); i++) {
            int count = 0;
            int nestQusNum = 0;
            PaperDetail paperDetail = paperDetails.get(i);
            paperDetail.setNumber(i + 1);
            paperDetail.setPaper(paper);
            paperDetail = paperDetailRepo.save(paperDetail);
            List<PaperDetailUnit> units = map.get(paperDetail.getName());
            for (int j = 0; j < units.size(); j++) {
                if (units.get(j).getQuestion() != null
                        && units.get(j).getQuestion().getSubQuestions() != null
                        && units.get(j).getQuestion().getSubQuestions().size() > 0) {
                    nestQusNum += units.get(j).getQuestion().getSubQuestions().size() - 1;
                }
                PaperDetailUnit paperDetailUnit = units.get(j);
                paperDetailUnit.setPaper(paper);
                paperDetailUnit.setPaperDetail(paperDetail);
                paperDetailUnit.setNumber(number + 1);
                paperDetailUnit.setPaperType(PaperType.GENERATE);
                unitRepo.save(paperDetailUnit);
                number++;
            }
            count = units.size() + nestQusNum;
            allQuesCount += count;
        }
        paper.setUnitCount(allQuesCount);
        paper.setAuditStatus(false);
        paper = paperRepo.save(paper);
        return paper;
    }

    //构建新的大题
    private List<PaperDetail> buildPaperDetail(Map<String, List<PaperDetailUnit>> map, GenPaperDto genPaperDto) {
        //定义新的大题集合
        List<PaperDetail> paperDetails = new ArrayList<>();
        for (String name : map.keySet()) {
            Double score = 0d;
            BigDecimal b1 = BigDecimal.valueOf(score);
            PaperDetail paperDetail = new PaperDetail();
            paperDetail.setName(name);
            paperDetail.setCreateTime(CommonUtils.getCurDateTime());
            paperDetail.setCreator(genPaperDto.getCreator());
            List<PaperDetailUnit> paperDetailUnits = map.get(name);
            for (PaperDetailUnit unit : paperDetailUnits) {
                //score += unit.getQuestion().getScore();
                if (unit.getScore() == null) {
                    unit.setScore(0d);
                }
                BigDecimal b2 = BigDecimal.valueOf(unit.getScore());
                b1 = b1.add(b2);
            }
            paperDetail.setScore(b1.doubleValue());
            paperDetail.setUnitCount(paperDetailUnits.size());
            paperDetail.setPaperDetailUnits(map.get(paperDetail.getName()));
            paperDetails.add(paperDetail);
        }
        PaperUtil.sortDetails(paperDetails);
        return paperDetails;
    }
    
    

    //把集合里面相同大题的小题分类
    private Map<String, List<PaperDetailUnit>> sortPaperDeatilUnit(List<PaperDetailUnit> selectedUnits) {
        Map<String, List<PaperDetailUnit>> map = new HashMap<>();
        List<PaperDetailUnit> units = null;
        if (selectedUnits != null && selectedUnits.size() > 0) {
            for (PaperDetailUnit unit : selectedUnits) {
                String name = unit.getPaperDetail().getName();
                if (map.get(name) != null) {
                    units = map.get(name);
                } else {
                    units = new ArrayList<>();
                }
                units.add(unit);
                map.put(name, units);
            }
        }
        return map;
    }

    //计算所有题目数量
    private int countQuestions(List<PaperDetailUnit> unitList) {
        int sum = 0;
        if (unitList != null && unitList.size() > 0) {
            for (PaperDetailUnit unit : unitList) {
                if (unit.getQuestion().getQuestionType() == QuesStructType.NESTED_ANSWER_QUESTION) {
                    List<Question> subQuestions = unit.getQuestion().getSubQuestions();
                    sum += subQuestions.size();
                } else {
                    sum += 1;
                }
            }
        }
        return sum;
    }

    /**
     * 根据大题集合构造paper
     *
     * @param details
     * @return
     */
    public Paper constuctPaperByPaperDetails(List<PaperDetail> details, GenPaperDto genPaperDto) {
        Paper paper = new Paper();
        if (details != null && details.size() > 0) {
            Double score = 0d;
            BigDecimal b1 = BigDecimal.valueOf(score);
            for (PaperDetail pd : details) {
                BigDecimal b2 = BigDecimal.valueOf(pd.getScore() == null ? 0d : pd.getScore());
                b1 = b1.add(b2);
            }
            paper.setId(new ObjectId().toString());
            paper.setName(genPaperDto.getPaperName());
            paper.setCourseNo(genPaperDto.getCourseNo());
            paper.setCourseName(genPaperDto.getCourseName());
            Course course = courseService.getCourse(Long.valueOf(genPaperDto.getOrgId()), genPaperDto.getCourseNo());
            paper.setCourse(course);
            paper.setCreator(genPaperDto.getCreator());
            paper.setCreateTime(CommonUtils.getCurDateTime());
            paper.setPaperDetailCount(details.size());
            paper.setTotalScore(b1.doubleValue());
            paper.setPaperType(PaperType.GENERATE);
            paper.setOrgId(genPaperDto.getOrgId());
            paper.setLevel(genPaperDto.getLevel());
        }
        return paper;

    }

    /**
     * 数据入库
     *
     * @param details
     * @param selectedUnits
     * @param paper
     * @return
     */
    public Paper persistentPaper(PaperStructType paperStructType,
                                 List<PaperDetailUnit> selectedUnits,
                                 List<PaperDetail> details,
                                 Paper paper) {
        LOG.debug("3.....");
        paper = paperRepo.save(paper);
        for (PaperDetail pd : details) {
            pd.setPaper(paper);
        }
        paperDetailRepo.saveAll(details);
        for (PaperDetailUnit pdu : selectedUnits) {
            pdu.setPaper(paper);
        }
        unitRepo.saveAll(selectedUnits);
        //给试卷中的小题设置number
        List<PaperDetail> paperDetails = paperDetailRepo.findByPaperOrderByNumber(paper);
        int index = 0;
        for (PaperDetail paperDetail : paperDetails) {
            List<PaperDetailUnit> paperDetailUnits = unitRepo.findByPaperDetailOrderByNumber(paperDetail);
            for (int i = 0; i < paperDetailUnits.size(); i++) {
                index++;
                PaperDetailUnit paperDetailUnit = paperDetailUnits.get(i);
                paperDetailUnit.setNumber(index);

                //重新计算套题小题分
                if (paperStructType != PaperStructType.SIMPLE) {
                    Question question = paperDetailUnit.getQuestion();
                    if (question != null && question.getQuestionType() == QuesStructType.NESTED_ANSWER_QUESTION) {
                        List<Question> subQuestions = question.getSubQuestions();
                        List<Double> subScoreList = new ArrayList<>();
                        if (subQuestions != null && subQuestions.size() > 0) {
                            int subQuesLen = subQuestions.size();
                            double subTotalScore = paperDetailUnit.getScore();
                            for (int j = 0; j < subQuesLen; j++) {
                                double avgScore = subTotalScore / subQuestions.size();
                                //向下取整,包含0.5
                                double formatScore = CommonUtils.formatDoubleFloor(avgScore);
                                if (j == subQuesLen - 1) {
                                    BigDecimal b1 = BigDecimal.valueOf(subTotalScore);
                                    BigDecimal b2 = BigDecimal.valueOf(formatScore * j);
                                    subScoreList.add(b1.subtract(b2).doubleValue());
                                } else {
                                    subScoreList.add(formatScore);
                                }
                            }
                            paperDetailUnit.setSubScoreListNew(subScoreList);
                        }
                    }
                }
            }
            unitRepo.saveAll(paperDetailUnits);
        }
        paper.setDifficultyDegree(paperService.reSetDifficulty(paper, paper.getTotalScore()));
        paper.setAuditStatus(false);
        paper = paperRepo.save(paper);
        return paper;
    }

    /**
     * 获取所试题数量
     *
     * @param units
     * @return
     */
    public int getTotalQuesNum(List<PaperDetailUnit> units) {
        int totalQuesNum = units.size();
        int nestQuesNum = 0;
        for (PaperDetailUnit unit : units) {
            if (unit.getQuestionType() == QuesStructType.NESTED_ANSWER_QUESTION) {
                nestQuesNum += unit.getQuestion().getSubQuestions().size() - 1;
            }
        }
        return totalQuesNum + nestQuesNum;
    }


    /**
     * 蓝图组卷，根据设定试卷结构组卷
     *
     * @param genPaperDto
     * @return
     */
    @SuppressWarnings("unchecked")
    public Map<String, Object> genBluePaper(GenPaperDto genPaperDto) {
        LOG.debug("开始蓝图组卷.....");
        String msg = "";
        Map<String, Object> paperMsgMap = new HashMap<>();
        LinkedList<Question> questions = new LinkedList<>();
        //查询试卷结构
        long start = System.currentTimeMillis();
        PaperStruct paperStruct = Model.of(paperStructRepo.findById(genPaperDto.getPaperStructId()));
        if (paperStruct == null) {
            paperMsgMap.put("msg", "试卷结构不存在");
            return paperMsgMap;
        }
        PaperContext paperContext = new PaperContext(paperStruct, genPaperDto.getConditions());
        List<UnitContext> unitContexts = new LinkedList<>();
        List<DetailContext> detailContexts = paperContext.getDetails();
        for (DetailContext dc : detailContexts) {
            unitContexts.addAll(dc.getUnits());
        }
        List<Paper> papers = (List<Paper>) paperRepo.findByIdIn(genPaperDto.getPaperIds());
        List<PaperDetailUnit> unitList = new ArrayList<>();
        for (Paper oldPaper : papers) {
            //unitList.addAll(unitRepo.findByPaperOrderByNumber(oldPaper));
            for (PaperDetailUnit paperDetailUnit : unitRepo.findByPaperOrderByNumber(oldPaper)) {
                unitList.add(paperDetailUnit);
            }
        }
        Set<PaperDetailUnit> spareUnits = new HashSet<>();
        spareUnits.addAll(unitList);
        long total = (System.currentTimeMillis() - start) / 1000;
        LOG.debug("total:" + total);
    	
    	/*for (PaperDetailUnit unit : spareUnits) {
            Question question = unit.getQuestion();
            //根据questionId查询题库中大题来源
            List<PaperDetailUnit> units = unitRepo.findByQuestion(question);
            for(PaperDetailUnit oldUnit:units){
            	Paper paper = oldUnit.getPaper();
            	if(paper.getPaperType() == PaperType.IMPORT){
            		 question.setQuesName(oldUnit.getPaperDetail().getName());
            		 break;
            	}
            }
            question.setPropertyGroup(bulidPropertyGroup(question));
            questions.add(question);
        }*/

        List<String> oIds = new ArrayList<>();
        for (PaperDetailUnit unit : spareUnits) {
            oIds.add(unit.getQuestion().getId());
        }
        LOG.debug("total2.....--------实际原题数量:" + oIds.size());
        long start2 = System.currentTimeMillis();
        List<PaperDetailUnit> oDetailUnits = paperDetailUnitService.findByQuestionsAndPaperType(oIds, PaperType.IMPORT);
        long total2 = (System.currentTimeMillis() - start2) / 1000;
        LOG.debug("total2....." + total2 + "--------查询原题数量:" + oDetailUnits.size());
        long start4 = System.currentTimeMillis();
        for (PaperDetailUnit oldUnit : oDetailUnits) {
            if (oldUnit.getPaper().getPaperType() == PaperType.IMPORT) {
                oldUnit.getQuestion().setQuesName(oldUnit.getPaperDetail().getName());
                oldUnit.getQuestion().setPropertyGroup(bulidPropertyGroup(oldUnit.getQuestion()));
                questions.add(oldUnit.getQuestion());
            }
        }
        long total4 = (System.currentTimeMillis() - start4) / 1000;
        LOG.debug("循环耗时....." + total4 + "--------最终原题数量:" + questions.size());
        /*for (Paper oldPaper : papers) {
            List<PaperDetailUnit> unitList = unitRepo.findByPaperOrderByNumber(oldPaper);
            for (PaperDetailUnit unit : unitList) {
                Question question = unit.getQuestion();
                question.setQuesName(unit.getPaperDetail().getName());
                question.setPropertyGroup(bulidPropertyGroup(question));
                questions.add(question);
            }

        }*/
        Collections.shuffle(questions);
        int maxLoopCount = questions.size() * 2;
        int selectCount = 0;
        int maxCount = unitContexts.size();
        int loopCount = 0;
        while (questions.size() > 0 && (selectCount < maxCount) && loopCount < maxLoopCount) {
            Question question = questions.removeFirst();
            boolean structTypeMatch = false;
            boolean selected = false;
            for (UnitContext uc : unitContexts) {
                if (checkBlueQuesType(uc, question)) {
                    structTypeMatch = true;
                    if (uc.check(question)) {
                        uc.select(question);
                        selected = true;
                        selectCount++;
                        break;
                    }
                }
            }
            if (structTypeMatch && !selected) {
                questions.addLast(question);
            }
            loopCount++;
        }
        Set<Question> quesSet = paperContext.getSelectQues();
        if (quesSet.size() < unitContexts.size()) {
            msg = "匹配的题源不足，请核查";
            paperMsgMap.put("msg", msg);
            return paperMsgMap;
        }
        List<Object> list = paperContext.build(paperStruct);
        if (list != null && list.size() == 3) {
            Paper paper = (Paper) list.get(0);
            List<PaperDetail> paperDetails = (List<PaperDetail>) list.get(1);
            List<PaperDetailUnit> paperDetailunits = (List<PaperDetailUnit>) list.get(2);
            // 补全paper属性
            paper.setExamRemark(paperStruct.getExamRemark());
            paper.setName(genPaperDto.getPaperName());
            paper.setCourseNo(genPaperDto.getCourseNo());
            paper.setCourseName(genPaperDto.getCourseName());
            Course course = courseService.getCourse(Long.valueOf(genPaperDto.getOrgId()), genPaperDto.getCourseNo());
            paper.setCourse(course);
            paper.setCreator(genPaperDto.getCreator());
            paper.setOrgId(genPaperDto.getOrgId());
            paper.setLevel(genPaperDto.getLevel());
            paper.setCreateTime(CommonUtils.getCurDateTime());
            paper.setUnitCount(this.getTotalQuesNum(paperDetailunits));
            paper.setPaperType(PaperType.GENERATE);
            // 数据入库
            paper = this.persistentPaper(PaperStructType.BLUEPRINT, paperDetailunits, paperDetails, paper);
            msg = "success";
            paperMsgMap.put("paper", paper);
            paperMsgMap.put("msg", msg);
        }
        return paperMsgMap;
    }

    /**
     * 精确组卷试题筛选条件
     *
     * @param question
     * @return
     */
    private List<String> bulidGroup(Question question) {
        List<String> propertyGroups = new ArrayList<>();
        propertyGroups.add(String.valueOf(question.getPublicity()) + "-" + question.getDifficulty());
        return propertyGroups;
    }

    /**
     * 构建试题属性组合
     *
     * @param question
     */
    private List<String> bulidPropertyGroup(Question question) {
        String propertyGroup = null;
        List<String> propertyGroups = new ArrayList<>();
        //获取试题关联的多组属性
        List<QuesProperty> quesProperties = question.getQuesProperties();
        if (quesProperties != null && quesProperties.size() > 0) {
            for (QuesProperty quesProperty : quesProperties) {
                if (quesProperty.getSecondProperty() != null) {
                    //有一级  和  二级
                    if (quesProperty.getSecondProperty().getId() == null || StringUtils.isBlank(String.valueOf(quesProperty.getSecondProperty().getId()))) {
                        propertyGroup = String.valueOf(quesProperty.getFirstProperty().getId()) + "-" +
                                String.valueOf(question.getPublicity()) + "-" + question.getDifficulty();
                    } else {
                        propertyGroup = String.valueOf(quesProperty.getFirstProperty().getId()) + "-" +
                                String.valueOf(quesProperty.getSecondProperty().getId()) + "-" +
                                String.valueOf(question.getPublicity()) + "-" + question.getDifficulty();
                    }
                    propertyGroups.add(propertyGroup);
                } else {
                    //有一级  无  二级
                    propertyGroup = String.valueOf(quesProperty.getFirstProperty().getId()) + "-" +
                            String.valueOf(question.getPublicity()) + "-" + question.getDifficulty();
                    propertyGroups.add(propertyGroup);
                }
            }
            return propertyGroups;
        }
        return null;
    }

    /**
     * 校验来源大题名称,题型结构，属性，公开度，难度
     *
     * @param uc
     * @param question
     * @return
     */
    private boolean checkBlueQuesType(UnitContext uc, Question question) {
        List<String> quesNames = uc.getUnitStruct().getQuesNames();
        if (quesNames != null && quesNames.size() > 0) {
            if (quesNames.contains(question.getQuesName()) && !uc.finish() && uc.getUnitStruct().getQuestionType().name().equals(question.getQuestionType().name())) {
                if (question.getPropertyGroup() != null) {
                    if (question.getPropertyGroup().contains(uc.getUnitStruct().getPropertyGroup())) {
                        return true;
                    }
                }
            }
        }
        return false;
    }

	public Map<String, Object> genPaperManual(GenPaperDto genPaperDto) {
		LOG.debug("开始组卷.....");
        String msg = "";
        Map<String, Object> paperMsgMap = new HashMap<>();
        //查询试卷结构
        PaperStruct paperStruct = Model.of(paperStructRepo.findById(genPaperDto.getPaperStructId()));
        if (paperStruct == null) {
            paperMsgMap.put("msg", "试卷结构不存在");
            return paperMsgMap;
        }
        PaperContext paperContext = new PaperContext(paperStruct, genPaperDto.getConditions());
        List<UnitContext> unitContexts = new LinkedList<>();
        List<DetailContext> detailContexts = paperContext.getDetails();
        for (DetailContext dc : detailContexts) {
            unitContexts.addAll(dc.getUnits());
        }

	 	Paper paper = new Paper();
        paper.setPaperDetailCount(paperStruct.getDetailCount());
        paper.setTotalScore(0.0);
        paper.setPaperType(PaperType.GENERATE);
        // 补全paper属性
        paper.setExamRemark(paperStruct.getExamRemark());
        paper.setName(genPaperDto.getPaperName());
        paper.setCourseNo(genPaperDto.getCourseNo());
        paper.setCourseName(genPaperDto.getCourseName());
        Course course = courseService.getCourse(Long.valueOf(genPaperDto.getOrgId()), genPaperDto.getCourseNo());
        paper.setCourse(course);
        paper.setCreator(genPaperDto.getCreator());
        paper.setOrgId(genPaperDto.getOrgId());
        paper.setLevel(genPaperDto.getLevel());
        paper.setCreateTime(CommonUtils.getCurDateTime());
        paper.setUnitCount(0);
        paper.setPaperType(PaperType.GENERATE);
        paper.setDifficultyDegree(0.5);
        paper.setAuditStatus(false);
        // 数据入库
        paperRepo.save(paper);
        List<PaperDetail> paperDetails = buildPaperDetail(paper, paperStruct);
        paperDetailRepo.saveAll(paperDetails);
        
        msg = "success";
        paperMsgMap.put("paper", paper);
        paperMsgMap.put("msg", msg);
        
        
        return paperMsgMap;
	}
	
	private List<PaperDetail> buildPaperDetail(Paper paper,PaperStruct paperStruct) {
        List<PaperDetail> detailList = new ArrayList<>();
        for (PaperDetailStruct pds : paperStruct.getPaperDetailStructs()) {
            PaperDetail paperDetail = new PaperDetail();
            paperDetail.setPaper(paper);
            paperDetail.setNumber(pds.getNumber());
            paperDetail.setName(pds.getName());
            paperDetail.setCreator(paperStruct.getCreator());
            paperDetail.setScore(0.0);
            paperDetail.setUnitCount(0);
            detailList.add(paperDetail);
        }
        return detailList;
	}

}
