xiatian 2 роки тому
батько
коміт
7f7a3ae806

+ 299 - 296
examcloud-core-questions-api-provider/src/main/java/cn/com/qmth/examcloud/core/questions/api/controller/ExtractConfigController.java

@@ -1,6 +1,5 @@
 package cn.com.qmth.examcloud.core.questions.api.controller;
 
-
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
@@ -47,7 +46,6 @@ import cn.com.qmth.examcloud.web.support.ControllerSupport;
 import cn.com.qmth.examcloud.web.support.Naked;
 import io.swagger.annotations.ApiOperation;
 
-
 /**
  * @author chenken
  * @date 2017年4月14日 下午6:05:37
@@ -58,317 +56,322 @@ import io.swagger.annotations.ApiOperation;
 @Controller
 @RequestMapping("${api_cqb}/")
 public class ExtractConfigController extends ControllerSupport {
-    private static final Logger LOG = LoggerFactory.getLogger(ExtractConfigController.class);
+	private static final Logger LOG = LoggerFactory.getLogger(ExtractConfigController.class);
+
+	@Autowired
+	private ExtractConfigService extractConfigService;
+
+	@Autowired
+	private ExtractConfigFileService extractConfigFileService;
+
+	@Autowired
+	private ExtractConfigCache extractConfigCache;
 
-    @Autowired
-    private ExtractConfigService extractConfigService;
+	@DataRule(type = DataRuleType.COURSE)
+	@ApiOperation(value = "根据考试ID和课程ID获取调卷规则", notes = "根据考试ID和课程ID获取调卷规则")
+	@GetMapping(value = "/findPageExtractConfig/{currentPage}/{pageSize}")
+	public ResponseEntity<Object> findPageExtractConfig(@PathVariable int currentPage, @PathVariable int pageSize,
+			@RequestParam("examId") Long examId, @RequestParam("courseNo") String courseNo) {
+		try {
+			User user = getAccessUser();
+			UserDataRule ud = getUserDataRule(DataRuleType.COURSE);
+			Page<ExtractConfig> extractConfigPageList = extractConfigService.findPageExtractConfig(currentPage,
+					pageSize, examId, courseNo, String.valueOf(user.getRootOrgId()), ud);
+			return new ResponseEntity<>(extractConfigPageList, HttpStatus.OK);
+		} catch (Exception e) {
+			LOG.error(e.getMessage(), e);
+			throw new StatusException("Q-050065", e.getMessage());
+		}
+	}
 
-    @Autowired
-    private ExtractConfigFileService extractConfigFileService;
+	@ApiOperation(value = "保存调卷规则", notes = "保存调卷规则")
+	@PutMapping(value = "/extractConfig/{isBuildFile}")
+	public ResponseEntity<Object> saveExtractConfig(@PathVariable Integer isBuildFile,
+			@RequestBody ExtractConfig extractConfig, @RequestParam(required = false) PaperSeqMode seqMode) {
+		if (extractConfig.getCallType() == null) {
+			throw new StatusException("CallType不能为空");
+		}
+		String changeInfo = null;
+		if (extractConfig.getId() != null) {
+			changeInfo = getChangeInfo(extractConfig);
+		}
+		User user = getAccessUser();
+		extractConfig.setOrgId(user.getRootOrgId() + "");
+		extractConfig.setOrgName(user.getRootOrgName());
+		if (!CallType.RANDOM_PAPER.equals(extractConfig.getCallType())) {
+			extractConfigFileService.saveExtractConfigAndBuildPaperFile(extractConfig, isBuildFile, user, seqMode);
+		} else {
+			if (extractConfig.getRandomPaperId() == null) {
+				throw new StatusException("请选择随机抽题模板");
+			}
+			if (extractConfig.getPlayTime() == null) {
+				throw new StatusException("请填写音频播放次数");
+			}
+			extractConfigService.saveExtractConfig(extractConfig);
+		}
 
-    @Autowired
-    private ExtractConfigCache extractConfigCache;
+		// 清除缓存
+		extractConfigCache.remove(extractConfig.getExamId(), extractConfig.getCourseCode());
+		if (extractConfig.getId() == null) {
+			ReportsUtil.report(
+					new AdminOperateReport(user.getRootOrgId(), user.getUserId(), AdminOperateType.TYPE23.getDesc(),
+							"课程ID:" + extractConfig.getCourse().getId() + " 考试ID:" + extractConfig.getExamId()));
+		} else {
+			if (changeInfo != null) {
+				ReportsUtil.report(new AdminOperateReport(user.getRootOrgId(), user.getUserId(),
+						AdminOperateType.TYPE24.getDesc(), "课程ID:" + extractConfig.getCourse().getId() + " 考试ID:"
+								+ extractConfig.getExamId() + changeInfo));
+			}
+		}
+		return new ResponseEntity<>(HttpStatus.OK);
+	}
 
-    @DataRule(type = DataRuleType.COURSE)
-    @ApiOperation(value = "根据考试ID和课程ID获取调卷规则", notes = "根据考试ID和课程ID获取调卷规则")
-    @GetMapping(value = "/findPageExtractConfig/{currentPage}/{pageSize}")
-    public ResponseEntity<Object> findPageExtractConfig(@PathVariable int currentPage,
-                                                        @PathVariable int pageSize,
-                                                        @RequestParam("examId") Long examId,
-                                                        @RequestParam("courseNo") String courseNo) {
-        try {
-            User user = getAccessUser();
-            UserDataRule ud = getUserDataRule(DataRuleType.COURSE);
-            Page<ExtractConfig> extractConfigPageList = extractConfigService.findPageExtractConfig(currentPage, pageSize, examId, courseNo, String.valueOf(user.getRootOrgId()),ud);
-            return new ResponseEntity<>(extractConfigPageList, HttpStatus.OK);
-        } catch (Exception e) {
-            LOG.error(e.getMessage(), e);
-            throw new StatusException("Q-050065", e.getMessage());
-        }
-    }
+	private String getChangeInfo(ExtractConfig now) {
+		ExtractConfig old = extractConfigService.findConfigById(now.getId());
+		StringBuilder sb = new StringBuilder();
+		if (!CallType.RANDOM_PAPER.equals(now.getCallType())) {
+			boolean paperChange = paperChange(old, now);
+			if (paperChange) {
+				sb.append("修改试卷选定,");
+			}
+			if (!paperChange && paperWeightChange(old, now)) {
+				sb.append("修改试卷选取几率,");
+			}
+			if (old.getScrambling_the_question_order() != now.getScrambling_the_question_order()) {
+				sb.append("修改客观题小题乱序,");
+			}
+			if (old.getScrambling_the_option_order() != now.getScrambling_the_option_order()) {
+				sb.append("修改客观题选项乱序,");
+			}
+			if (old.getIfFinish() != now.getIfFinish()) {
+				sb.append("修改是否生成文件,");
+			}
+		} else {
+			if (old.getRandomPaperId() != now.getRandomPaperId()) {
+				sb.append("修改随机抽题模板,");
+			}
+			if (old.getPlayTime() != now.getPlayTime()) {
+				sb.append("修改音频播放次数,");
+			}
+		}
+		if (sb.length() != 0) {
+			sb.deleteCharAt(sb.length() - 1);
+			return " 修改内容:" + sb.toString();
+		}
+		return null;
+	}
 
-    @ApiOperation(value = "保存调卷规则", notes = "保存调卷规则")
-    @PutMapping(value = "/extractConfig/{isBuildFile}")
-    public ResponseEntity<Object> saveExtractConfig(@PathVariable Integer isBuildFile, @RequestBody ExtractConfig extractConfig, @RequestParam(required = false) PaperSeqMode seqMode) {
-    	if(extractConfig.getCallType()==null) {
-    		throw new StatusException("CallType不能为空");
-    	}
-    	String changeInfo=null;
-    	if(extractConfig.getId()!=null) {
-    		changeInfo=getChangeInfo(extractConfig);
-    	}
-        User user = getAccessUser();
-        extractConfig.setOrgId(user.getRootOrgId() + "");
-        extractConfig.setOrgName(user.getRootOrgName());
-        if(!CallType.RANDOM_PAPER.equals(extractConfig.getCallType())) {
-        	extractConfigFileService.saveExtractConfigAndBuildPaperFile(extractConfig, isBuildFile, user,seqMode);
-        }else {
-        	if(extractConfig.getRandomPaperId()==null) {
-        		throw new StatusException("请选择随机抽题模板");
-        	}
-        	if(extractConfig.getPlayTime()==null) {
-        		throw new StatusException("请填写音频播放次数");
-        	}
-        	extractConfigService.saveExtractConfig(extractConfig);
-        }
+	private boolean paperChange(ExtractConfig old, ExtractConfig now) {
+		if (old.getExamPaperList().size() != now.getExamPaperList().size()) {
+			return true;
+		}
+		for (int i = 0; i < old.getExamPaperList().size(); i++) {
+			ExamPaper oldPaper = old.getExamPaperList().get(i);
+			ExamPaper nowPaper = now.getExamPaperList().get(i);
+			if (!oldPaper.getPaper().getId().equals(nowPaper.getPaper().getId())) {
+				return true;
+			}
+		}
+		return false;
+	}
 
-        //清除缓存
-        extractConfigCache.remove(extractConfig.getExamId(), extractConfig.getCourseCode());
-        if(extractConfig.getId()==null) {
-        	ReportsUtil.report(new AdminOperateReport(user.getRootOrgId(), user.getUserId(), AdminOperateType.TYPE23.getDesc(),"课程ID:"+extractConfig.getCourse().getId()+" 考试ID:"+extractConfig.getExamId()));
-        }else {
-        	if(changeInfo!=null) {
-        		ReportsUtil.report(new AdminOperateReport(user.getRootOrgId(), user.getUserId(), AdminOperateType.TYPE24.getDesc(),"课程ID:"+extractConfig.getCourse().getId()+" 考试ID:"+extractConfig.getExamId()+changeInfo));
-        	}
-        }
-        return new ResponseEntity<>(HttpStatus.OK);
-    }
-    
-    private String getChangeInfo(ExtractConfig now) {
-    	ExtractConfig old=extractConfigService.findConfigById(now.getId());
-    	StringBuilder sb=new StringBuilder();
-    	boolean paperChange=paperChange(old, now);
-    	if(paperChange) {
-    		sb.append("修改试卷选定,");
-    	}
-    	if(!paperChange&&paperWeightChange(old, now)) {
-    		sb.append("修改试卷选取几率,");
-    	}
-    	if(old.getScrambling_the_question_order()!=now.getScrambling_the_question_order()) {
-    		sb.append("修改客观题小题乱序,");
-    	}
-    	if(old.getScrambling_the_option_order()!=now.getScrambling_the_option_order()) {
-    		sb.append("修改客观题选项乱序,");
-    	}
-    	if(old.getIfFinish()!=now.getIfFinish()) {
-    		sb.append("修改是否生成文件,");
-    	}
-    	if(sb.length()!=0) {
-    		sb.deleteCharAt(sb.length()-1);
-    		return " 修改内容:"+sb.toString();
-    	}
-    	return null;
-    }
-    
-    private boolean paperChange(ExtractConfig old,ExtractConfig now) {
-    	if(old.getExamPaperList().size()!=now.getExamPaperList().size()) {
-    		return true;
-    	}
-    	for(int i=0;i<old.getExamPaperList().size();i++) {
-    		ExamPaper oldPaper=old.getExamPaperList().get(i);
-    		ExamPaper nowPaper=now.getExamPaperList().get(i);
-    		if(!oldPaper.getPaper().getId().equals(nowPaper.getPaper().getId())) {
-    			return true;
-    		}
-    	}
-    	return false;
-    }
-    
-    private boolean paperWeightChange(ExtractConfig old,ExtractConfig now) {
-    	for(int i=0;i<old.getExamPaperList().size();i++) {
-    		ExamPaper oldPaper=old.getExamPaperList().get(i);
-    		ExamPaper nowPaper=now.getExamPaperList().get(i);
-    		if(!oldPaper.getWeight().equals(nowPaper.getWeight())) {
-    			return true;
-    		}
-    	}
-    	return false;
-    }
+	private boolean paperWeightChange(ExtractConfig old, ExtractConfig now) {
+		for (int i = 0; i < old.getExamPaperList().size(); i++) {
+			ExamPaper oldPaper = old.getExamPaperList().get(i);
+			ExamPaper nowPaper = now.getExamPaperList().get(i);
+			if (!oldPaper.getWeight().equals(nowPaper.getWeight())) {
+				return true;
+			}
+		}
+		return false;
+	}
 
-    @ApiOperation(value = "根据ID获取调卷规则", notes = "根据ID获取调卷规则")
-    @GetMapping(value = "/extractConfig/{id}")
-    public ResponseEntity<ExtractConfig> findExtractConfigById(@PathVariable String id) {
-        ExtractConfig extractConfig = extractConfigService.findConfigById(id);
-        return new ResponseEntity<ExtractConfig>(extractConfig, HttpStatus.OK);
-    }
+	@ApiOperation(value = "根据ID获取调卷规则", notes = "根据ID获取调卷规则")
+	@GetMapping(value = "/extractConfig/{id}")
+	public ResponseEntity<ExtractConfig> findExtractConfigById(@PathVariable String id) {
+		ExtractConfig extractConfig = extractConfigService.findConfigById(id);
+		return new ResponseEntity<ExtractConfig>(extractConfig, HttpStatus.OK);
+	}
 
-    @DataRule(type = DataRuleType.COURSE)
-    @ApiOperation(value = "根据考试Id获取已经制定的调卷规则", notes = "根据考试Id获取已经制定的调卷规则")
-    @GetMapping(value = "/findCourseByExtractConfig/{examId}")
-    public ResponseEntity<Object> findCourseByExtractConfig(@PathVariable Long examId) {
-        User user = getAccessUser();
-        UserDataRule ud = getUserDataRule(DataRuleType.COURSE);
-        List<CouresInfo> courseCodeList = extractConfigService.findCourseByExtractConfig(examId, user.getRootOrgId().toString(),ud);
-        return new ResponseEntity<>(courseCodeList, HttpStatus.OK);
-    }
+	@DataRule(type = DataRuleType.COURSE)
+	@ApiOperation(value = "根据考试Id获取已经制定的调卷规则", notes = "根据考试Id获取已经制定的调卷规则")
+	@GetMapping(value = "/findCourseByExtractConfig/{examId}")
+	public ResponseEntity<Object> findCourseByExtractConfig(@PathVariable Long examId) {
+		User user = getAccessUser();
+		UserDataRule ud = getUserDataRule(DataRuleType.COURSE);
+		List<CouresInfo> courseCodeList = extractConfigService.findCourseByExtractConfig(examId,
+				user.getRootOrgId().toString(), ud);
+		return new ResponseEntity<>(courseCodeList, HttpStatus.OK);
+	}
 
-    @ApiOperation(value = "根据考试ID和课程ID获取调卷规则", notes = "根据考试ID和课程ID获取调卷规则")
-    @GetMapping(value = "/extractConfig/{examId}/{courseCode}")
-    public ResponseEntity<ExtractConfig> findExtractConfig(@PathVariable Long examId, @PathVariable String courseCode) {
-        ExtractConfig condition = new ExtractConfig();
-        condition.setExamId(examId);
-        condition.setCourseCode(courseCode);
-        ExtractConfig extractConfig = extractConfigService.findConfig(condition);
-        return new ResponseEntity<ExtractConfig>(extractConfig, HttpStatus.OK);
-    }
+	@ApiOperation(value = "根据考试ID和课程ID获取调卷规则", notes = "根据考试ID和课程ID获取调卷规则")
+	@GetMapping(value = "/extractConfig/{examId}/{courseCode}")
+	public ResponseEntity<ExtractConfig> findExtractConfig(@PathVariable Long examId, @PathVariable String courseCode) {
+		ExtractConfig condition = new ExtractConfig();
+		condition.setExamId(examId);
+		condition.setCourseCode(courseCode);
+		ExtractConfig extractConfig = extractConfigService.findConfig(condition);
+		return new ResponseEntity<ExtractConfig>(extractConfig, HttpStatus.OK);
+	}
 
-    @Naked
-    @ApiOperation(value = "抽取考试试卷", notes = "抽取考试试卷")
-    @GetMapping(value = "/extract/{exam_id}/{course_code}/{group_code}")
-    public ResponseEntity<Object> extract(@PathVariable Long exam_id, @PathVariable String course_code, @PathVariable String group_code) {
-        try {
-            Map<String, Object> returnMap = extractConfigService.extractExamPaper(exam_id, course_code, group_code);
-            if (returnMap.get("errorMsg") == null) {
-                PaperDto paperDto = (PaperDto) returnMap.get("paperDto");
-                return new ResponseEntity<>(paperDto, HttpStatus.OK);
-            } else {
-                return new ResponseEntity<>(returnMap.get("errorMsg") + "", HttpStatus.OK);
-            }
-        } catch (Exception e) {
-            LOG.error("抽卷失败", e);
-            return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
-        }
-    }
+	@Naked
+	@ApiOperation(value = "抽取考试试卷", notes = "抽取考试试卷")
+	@GetMapping(value = "/extract/{exam_id}/{course_code}/{group_code}")
+	public ResponseEntity<Object> extract(@PathVariable Long exam_id, @PathVariable String course_code,
+			@PathVariable String group_code) {
+		try {
+			Map<String, Object> returnMap = extractConfigService.extractExamPaper(exam_id, course_code, group_code);
+			if (returnMap.get("errorMsg") == null) {
+				PaperDto paperDto = (PaperDto) returnMap.get("paperDto");
+				return new ResponseEntity<>(paperDto, HttpStatus.OK);
+			} else {
+				return new ResponseEntity<>(returnMap.get("errorMsg") + "", HttpStatus.OK);
+			}
+		} catch (Exception e) {
+			LOG.error("抽卷失败", e);
+			return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
+		}
+	}
 
-    @Naked
-    @ApiOperation(value = "抽取单个试题", notes = "抽取单个试题")
-    @GetMapping(value = "/extractQues/{examId}/{courseCode}/{groupCode}/{paperDetailUnitId}")
-    public ResponseEntity<Object> extractQuestion(@PathVariable String examId,
-                                                  @PathVariable String courseCode,
-                                                  @PathVariable String groupCode,
-                                                  @PathVariable String paperDetailUnitId) {
-        try {
-            QuestionDto questionDto = extractConfigService.extractExamQuestion(examId, courseCode, groupCode, paperDetailUnitId);
-            return new ResponseEntity<>(questionDto, HttpStatus.OK);
-        } catch (Exception e) {
-            LOG.error("抽题失败", e);
-            return new ResponseEntity<>("抽题失败:" + e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
-        }
+	@Naked
+	@ApiOperation(value = "抽取单个试题", notes = "抽取单个试题")
+	@GetMapping(value = "/extractQues/{examId}/{courseCode}/{groupCode}/{paperDetailUnitId}")
+	public ResponseEntity<Object> extractQuestion(@PathVariable String examId, @PathVariable String courseCode,
+			@PathVariable String groupCode, @PathVariable String paperDetailUnitId) {
+		try {
+			QuestionDto questionDto = extractConfigService.extractExamQuestion(examId, courseCode, groupCode,
+					paperDetailUnitId);
+			return new ResponseEntity<>(questionDto, HttpStatus.OK);
+		} catch (Exception e) {
+			LOG.error("抽题失败", e);
+			return new ResponseEntity<>("抽题失败:" + e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
+		}
 
-    }
+	}
 
-    @Naked
-    @ApiOperation(value = "判断试卷中的题是否都为客观题(单选、多选、判断),包括套题中的小题",
-            notes = "判断试卷中的题是否都为客观题(单选、多选、判断),包括套题中的小题")
-    @GetMapping(value = "/checkObjective/{paperId}")
-    public ResponseEntity<Map<String, Object>> checkIsAllObjectiveQuestion(@PathVariable String paperId) {
-        Map<String, Object> quesMap = new HashMap<>();
-        try {
-            if (StringUtils.isBlank(paperId)) {
-                quesMap.put("message", "paperId不能为空");
-                return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
-            }
-            boolean result = extractConfigService.checkIsAllQbjectiveQuestion(paperId);
-            quesMap.put("result", result);
-            quesMap.put("message", result ? "全为客观题" : "不全为客观题");
-            return new ResponseEntity<>(quesMap, HttpStatus.OK);
-        } catch (Exception e) {
-            LOG.error("调用checkIsAllQbjectiveQuestion失败", e);
-            quesMap.put("result", "error");
-            quesMap.put("message", "调用失败");
-            return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
-        }
-    }
+	@Naked
+	@ApiOperation(value = "判断试卷中的题是否都为客观题(单选、多选、判断),包括套题中的小题", notes = "判断试卷中的题是否都为客观题(单选、多选、判断),包括套题中的小题")
+	@GetMapping(value = "/checkObjective/{paperId}")
+	public ResponseEntity<Map<String, Object>> checkIsAllObjectiveQuestion(@PathVariable String paperId) {
+		Map<String, Object> quesMap = new HashMap<>();
+		try {
+			if (StringUtils.isBlank(paperId)) {
+				quesMap.put("message", "paperId不能为空");
+				return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
+			}
+			boolean result = extractConfigService.checkIsAllQbjectiveQuestion(paperId);
+			quesMap.put("result", result);
+			quesMap.put("message", result ? "全为客观题" : "不全为客观题");
+			return new ResponseEntity<>(quesMap, HttpStatus.OK);
+		} catch (Exception e) {
+			LOG.error("调用checkIsAllQbjectiveQuestion失败", e);
+			quesMap.put("result", "error");
+			quesMap.put("message", "调用失败");
+			return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
+		}
+	}
 
-    @Naked
-    @ApiOperation(value = "导出单张考试试卷、答案、试卷结构", notes = "导出单张考试试卷、答案、试卷结构")
-    @GetMapping(value = "/exportSingleExamPaperInfo/{orgId}/{exportWay}/{examId}/{courseId}/{exportContentList}/{loginName}")
-    public void exportSingleExamPaperInfo(HttpServletResponse response,
-                                          @PathVariable String exportWay,
-                                          @PathVariable String orgId,
-                                          @PathVariable String examId,
-                                          @PathVariable String courseId,
-                                          @PathVariable String exportContentList,
-                                          @PathVariable String loginName,
-                                          @RequestParam(required = false) String psw) {
-        ExportPaperInfoModel exportModel = new ExportPaperInfoModel();
-        exportModel.setExportWay(ExportWay.strToEnum(exportWay));
-        exportModel.setExamId(examId);
-        exportModel.setCourseId(courseId);
-        String[] exportContentArray = exportContentList.split(",");
-        List<String> list = new ArrayList<>();
-        for (int i = 0; i < exportContentArray.length; i++) {
-            list.add(exportContentArray[i]);
-        }
-        exportModel.setExportContentList(list);
-        try {
-            extractConfigFileService.exportExamPaperInfo(exportModel, response, loginName, orgId, psw);
-        } catch (Exception e) {
-            LOG.error(e.getMessage(), e);
-        }
-    }
+	@Naked
+	@ApiOperation(value = "导出单张考试试卷、答案、试卷结构", notes = "导出单张考试试卷、答案、试卷结构")
+	@GetMapping(value = "/exportSingleExamPaperInfo/{orgId}/{exportWay}/{examId}/{courseId}/{exportContentList}/{loginName}")
+	public void exportSingleExamPaperInfo(HttpServletResponse response, @PathVariable String exportWay,
+			@PathVariable String orgId, @PathVariable String examId, @PathVariable String courseId,
+			@PathVariable String exportContentList, @PathVariable String loginName,
+			@RequestParam(required = false) String psw) {
+		ExportPaperInfoModel exportModel = new ExportPaperInfoModel();
+		exportModel.setExportWay(ExportWay.strToEnum(exportWay));
+		exportModel.setExamId(examId);
+		exportModel.setCourseId(courseId);
+		String[] exportContentArray = exportContentList.split(",");
+		List<String> list = new ArrayList<>();
+		for (int i = 0; i < exportContentArray.length; i++) {
+			list.add(exportContentArray[i]);
+		}
+		exportModel.setExportContentList(list);
+		try {
+			extractConfigFileService.exportExamPaperInfo(exportModel, response, loginName, orgId, psw);
+		} catch (Exception e) {
+			LOG.error(e.getMessage(), e);
+		}
+	}
 
-    @ApiOperation(value = "导出试卷文件前校验", notes = "导出试卷文件前校验")
-    @GetMapping(value = "/exportBatchExamPaperInfoCheck/{exportWay}/{examId}")
-    public ResponseEntity<Object> exportExamPaperInfoCheck(HttpServletResponse response,
-                                                           @PathVariable String exportWay,
-                                                           @PathVariable String examId) {
-        ExportPaperInfoModel exportModel = new ExportPaperInfoModel();
-        exportModel.setExportWay(ExportWay.strToEnum(exportWay));
-        exportModel.setExamId(examId);
-        try {
-            extractConfigFileService.exportExamPaperInfoCheck(exportModel, response);
-            return new ResponseEntity<>(HttpStatus.OK);
-        } catch (Exception e) {
-            LOG.error(e.getMessage(), e);
-            throw new StatusException("Q-050200", e.getMessage());
-        }
-    }
+	@ApiOperation(value = "导出试卷文件前校验", notes = "导出试卷文件前校验")
+	@GetMapping(value = "/exportBatchExamPaperInfoCheck/{exportWay}/{examId}")
+	public ResponseEntity<Object> exportExamPaperInfoCheck(HttpServletResponse response, @PathVariable String exportWay,
+			@PathVariable String examId) {
+		ExportPaperInfoModel exportModel = new ExportPaperInfoModel();
+		exportModel.setExportWay(ExportWay.strToEnum(exportWay));
+		exportModel.setExamId(examId);
+		try {
+			extractConfigFileService.exportExamPaperInfoCheck(exportModel, response);
+			return new ResponseEntity<>(HttpStatus.OK);
+		} catch (Exception e) {
+			LOG.error(e.getMessage(), e);
+			throw new StatusException("Q-050200", e.getMessage());
+		}
+	}
 
-    @Naked
-    @ApiOperation(value = "导出整个考试下所有 课程的试卷、答案、试卷结构", notes = "导出整个考试下所有 课程的试卷、答案、试卷结构")
-    @GetMapping(value = "/exportBatchExamPaperInfo/{orgId}/{exportWay}/{examId}/{exportContentList}/{loginName}")
-    public void exportBatchExamPaperInfo(HttpServletResponse response,
-                                         @PathVariable String exportWay,
-                                         @PathVariable String orgId,
-                                         @PathVariable String examId,
-                                         @PathVariable String exportContentList,
-                                         @PathVariable String loginName) {
-        ExportPaperInfoModel exportModel = new ExportPaperInfoModel();
-        exportModel.setExportWay(ExportWay.strToEnum(exportWay));
-        exportModel.setExamId(examId);
-        String[] exportContentArray = exportContentList.split(",");
-        List<String> list = new ArrayList<>();
-        for (int i = 0; i < exportContentArray.length; i++) {
-            list.add(exportContentArray[i]);
-        }
-        exportModel.setExportContentList(list);
-        try {
-            extractConfigFileService.exportExamPaperInfo(exportModel, response, loginName, orgId, null);
-        }  catch (StatusException e) {
-            throw e;
-        }	catch (Exception e) {
-            throw new StatusException("500","系统错误",e);
-        }
-    }
+	@Naked
+	@ApiOperation(value = "导出整个考试下所有 课程的试卷、答案、试卷结构", notes = "导出整个考试下所有 课程的试卷、答案、试卷结构")
+	@GetMapping(value = "/exportBatchExamPaperInfo/{orgId}/{exportWay}/{examId}/{exportContentList}/{loginName}")
+	public void exportBatchExamPaperInfo(HttpServletResponse response, @PathVariable String exportWay,
+			@PathVariable String orgId, @PathVariable String examId, @PathVariable String exportContentList,
+			@PathVariable String loginName) {
+		ExportPaperInfoModel exportModel = new ExportPaperInfoModel();
+		exportModel.setExportWay(ExportWay.strToEnum(exportWay));
+		exportModel.setExamId(examId);
+		String[] exportContentArray = exportContentList.split(",");
+		List<String> list = new ArrayList<>();
+		for (int i = 0; i < exportContentArray.length; i++) {
+			list.add(exportContentArray[i]);
+		}
+		exportModel.setExportContentList(list);
+		try {
+			extractConfigFileService.exportExamPaperInfo(exportModel, response, loginName, orgId, null);
+		} catch (StatusException e) {
+			throw e;
+		} catch (Exception e) {
+			throw new StatusException("500", "系统错误", e);
+		}
+	}
 
-    @Naked
-    @ApiOperation(value = "根据试卷id抽取考试试卷", notes = "根据试卷id抽取考试试卷")
-    @GetMapping(value = "/extract/paper/{paperId}")
-    public ResponseEntity<Object> extractPaper(@PathVariable String paperId) {
-        try {
-            Map<String, Object> returnMap = extractConfigService.extractPaper(paperId);
-            if (returnMap.get("errorMsg") == null) {
-                PaperDto paperDto = (PaperDto) returnMap.get("paperDto");
-                return new ResponseEntity<>(paperDto, HttpStatus.OK);
-            } else {
-                return new ResponseEntity<>(returnMap.get("errorMsg") + "", HttpStatus.OK);
-            }
-        } catch (Exception e) {
-            LOG.error("抽卷失败", e);
-            return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
-        }
-    }
+	@Naked
+	@ApiOperation(value = "根据试卷id抽取考试试卷", notes = "根据试卷id抽取考试试卷")
+	@GetMapping(value = "/extract/paper/{paperId}")
+	public ResponseEntity<Object> extractPaper(@PathVariable String paperId) {
+		try {
+			Map<String, Object> returnMap = extractConfigService.extractPaper(paperId);
+			if (returnMap.get("errorMsg") == null) {
+				PaperDto paperDto = (PaperDto) returnMap.get("paperDto");
+				return new ResponseEntity<>(paperDto, HttpStatus.OK);
+			} else {
+				return new ResponseEntity<>(returnMap.get("errorMsg") + "", HttpStatus.OK);
+			}
+		} catch (Exception e) {
+			LOG.error("抽卷失败", e);
+			return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
+		}
+	}
 
-    @Naked
-    @ApiOperation(value = "测试获取试卷Dto", notes = "测试获取试卷Dto")
-    @GetMapping(value = "/extract/getPaperDto/{paperId}")
-    public ResponseEntity<Object> getPaperDto(@PathVariable String paperId) {
-        try {
-            PaperDto paperDto = extractConfigService.getPaperDtoByPaperNew(paperId);
-            return new ResponseEntity<>(paperDto, HttpStatus.OK);
-        } catch (Exception e) {
-            LOG.error("获取试卷Dto失败", e);
-            return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
-        }
-    }
+	@Naked
+	@ApiOperation(value = "测试获取试卷Dto", notes = "测试获取试卷Dto")
+	@GetMapping(value = "/extract/getPaperDto/{paperId}")
+	public ResponseEntity<Object> getPaperDto(@PathVariable String paperId) {
+		try {
+			PaperDto paperDto = extractConfigService.getPaperDtoByPaperNew(paperId);
+			return new ResponseEntity<>(paperDto, HttpStatus.OK);
+		} catch (Exception e) {
+			LOG.error("获取试卷Dto失败", e);
+			return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
+		}
+	}
 
-    @Naked
-    @ApiOperation(value = "通过试卷id得到答案", notes = "通过试卷id得到答案")
-    @GetMapping(value = "/extract/getAnswerHtml/{paperId}")
-    public ResponseEntity<Object> getAnswerHtml(@PathVariable String paperId) {
-        String answerHtml = extractConfigService.getAnswerHtml(paperId);
-        return new ResponseEntity<>(answerHtml, HttpStatus.OK);
-    }
+	@Naked
+	@ApiOperation(value = "通过试卷id得到答案", notes = "通过试卷id得到答案")
+	@GetMapping(value = "/extract/getAnswerHtml/{paperId}")
+	public ResponseEntity<Object> getAnswerHtml(@PathVariable String paperId) {
+		String answerHtml = extractConfigService.getAnswerHtml(paperId);
+		return new ResponseEntity<>(answerHtml, HttpStatus.OK);
+	}
 
-}	
+}

+ 677 - 628
examcloud-core-questions-service/src/main/java/cn/com/qmth/examcloud/core/questions/service/impl/ExtractConfigProviderServiceImpl.java

@@ -1,37 +1,64 @@
 package cn.com.qmth.examcloud.core.questions.service.impl;
 
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Example;
+import org.springframework.stereotype.Service;
+
+import cn.com.qmth.examcloud.api.commons.enums.CallType;
 import cn.com.qmth.examcloud.commons.exception.StatusException;
 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.dao.AudioTimeConfigRepo;
+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.QuesRepo;
+import cn.com.qmth.examcloud.core.questions.dao.entity.AudioTimeConfig;
+import cn.com.qmth.examcloud.core.questions.dao.entity.ExamPaper;
+import cn.com.qmth.examcloud.core.questions.dao.entity.ExtractConfig;
+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.QuesOption;
+import cn.com.qmth.examcloud.core.questions.dao.entity.Question;
+import cn.com.qmth.examcloud.core.questions.dao.entity.QuestionAudio;
+import cn.com.qmth.examcloud.core.questions.service.ExtractConfigProviderService;
+import cn.com.qmth.examcloud.core.questions.service.ExtractConfigService;
+import cn.com.qmth.examcloud.core.questions.service.PaperService;
+import cn.com.qmth.examcloud.core.questions.service.QuesService;
+import cn.com.qmth.examcloud.core.questions.service.QuestionAudioService;
 import cn.com.qmth.examcloud.core.questions.service.bean.QuestionAnswerConvert;
 import cn.com.qmth.examcloud.core.questions.service.bean.extract.ExtractConfigPaper;
 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.DefaultQuestion;
+import cn.com.qmth.examcloud.question.commons.core.question.DefaultQuestionOption;
+import cn.com.qmth.examcloud.question.commons.core.question.DefaultQuestionStructure;
+import cn.com.qmth.examcloud.question.commons.core.question.DefaultQuestionUnit;
 import cn.com.qmth.examcloud.question.commons.core.question.QuestionType;
-import cn.com.qmth.examcloud.question.commons.core.question.*;
 import cn.com.qmth.examcloud.support.cache.CacheHelper;
 import cn.com.qmth.examcloud.support.cache.bean.ExtractConfigCacheBean;
 import cn.com.qmth.examcloud.support.cache.bean.ExtractConfigDetailCacheBean;
 import cn.com.qmth.examcloud.support.cache.bean.ExtractConfigPaperCacheBean;
 import cn.com.qmth.examcloud.support.filestorage.FileStorageUtil;
-import org.apache.commons.collections.CollectionUtils;
-import org.apache.commons.lang3.StringUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-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
@@ -43,617 +70,639 @@ import java.util.stream.Collectors;
 @Service("extractConfigCloudService")
 public class ExtractConfigProviderServiceImpl implements ExtractConfigProviderService {
 
-    private static final Logger LOG = LoggerFactory.getLogger(ExtractConfigProviderServiceImpl.class);
-
-    @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 SysProperty sysProperty;
-
-    @Override
-    public ExtractConfigCacheBean getExtractConfig(Long examId, String courseCode) {
-        ExtractConfig extractConfig = extractConfigService.findConfig(new ExtractConfig(examId, courseCode));
-        if (extractConfig == null) {
-            throw new StatusException("500", "该课程调卷规则未制定,请联系学校!");
-        }
-
-        List<ExamPaper> examPapers = extractConfig.getExamPaperList();
-        if (CollectionUtils.isEmpty(examPapers)) {
-            throw new StatusException("500", "可供抽取的试卷集合为空!");
-        }
-
-        ExtractConfigCacheBean cacheBean = new ExtractConfigCacheBean();
-        cacheBean.setId(extractConfig.getId());
-        cacheBean.setExamId(examId);
-        cacheBean.setCourseCode(courseCode);
-        cacheBean.setRandomPaperId(extractConfig.getRandomPaperId());
-        cacheBean.setPlayTime(extractConfig.getPlayTime());
-        cacheBean.setSortQuestionOrder(extractConfig.getScrambling_the_question_order() != 0);
-        cacheBean.setSortOptionOrder(extractConfig.getScrambling_the_option_order() != 0);
-
-        List<ExtractConfigDetailCacheBean> details = new ArrayList<>();
-        for (ExamPaper examPaper : examPapers) {
-            details.add(new ExtractConfigDetailCacheBean(examPaper.getGroupCode(), examPaper.getPaper().getId(), examPaper.getWeight()));
-        }
-        cacheBean.setDetails(details);
-
-        return cacheBean;
-    }
-
-    @Override
-    public ExtractConfigPaperCacheBean getExtractConfigPaper(Long examId, String courseCode, String groupCode, String paperId) {
-        DefaultPaper defaultPaper = this.buildDefaultByBasePaper(paperId, examId, courseCode, groupCode);
-
-        ExtractConfigPaperCacheBean cacheBean = new ExtractConfigPaperCacheBean();
-        cacheBean.setDefaultPaper(defaultPaper);
-        return cacheBean;
-    }
-
-    @Override
-    public ExtractConfigPaper getDefaultPaper(Long examId, String courseCode, String groupCode) {
-        LOG.info("调卷开始...");
-
-        ExtractConfigCacheBean extractConfigCache = CacheHelper.getExtractConfig(examId, courseCode);
-        if (extractConfigCache == null) {
-            throw new StatusException("500", "该课程调卷规则未制定,请联系学校!");
-        }
-
-        final String msg = "该考试和课程下调卷规则中试卷不存在,请重新制定调卷规则!";
-        Map<String, String> paperTypeMaps = this.getExamPaperByProbability(extractConfigCache.getDetails());
-        if (paperTypeMaps.isEmpty()) {
-            throw new StatusException("500", msg);
-        }
-
-        String basePaperId = paperTypeMaps.get(groupCode);
-        if (StringUtils.isEmpty(basePaperId)) {
-            throw new StatusException("500", msg);
-        }
-
-        LOG.info("构建试卷结构..." + basePaperId);
-        ExtractConfigPaperCacheBean extractConfigPaperCache = CacheHelper.getExtractConfigPaper(examId, courseCode, groupCode, basePaperId);
-        if (extractConfigPaperCache == null) {
-            throw new StatusException("500", msg);
-        }
-
-        ExtractConfigPaper result = new ExtractConfigPaper();
-        result.setDefaultPaper(extractConfigPaperCache.getDefaultPaper());
-        result.setPaperId(basePaperId);
-        result.setSortQuestionOrder(extractConfigCache.getSortQuestionOrder());
-        result.setSortOptionOrder(extractConfigCache.getSortOptionOrder());
-        return result;
-    }
-
-    /**
-     * 每个试卷类型取出一套试卷
-     * {A:paperId,B:paperId} A是试卷类型,paperId是A类型下选定的试卷ID
-     */
-    private Map<String, String> getExamPaperByProbability(List<ExtractConfigDetailCacheBean> examPapers) {
-        if (CollectionUtils.isEmpty(examPapers)) {
-            throw new StatusException("500", "可供抽取的试卷集合为空!");
-        }
-
-        Map<String, List<ExtractConfigDetailCacheBean>> examPaperMaps = new HashMap<>();
-        for (ExtractConfigDetailCacheBean examPaper : examPapers) {
-            if (examPaperMaps.containsKey(examPaper.getGroupCode())) {
-                examPaperMaps.get(examPaper.getGroupCode()).add(examPaper);
-            } else {
-                List<ExtractConfigDetailCacheBean> list = new ArrayList<>();
-                list.add(examPaper);
-                examPaperMaps.put(examPaper.getGroupCode(), list);
-            }
-        }
-
-        Map<String, String> paperTypeMaps = new HashMap<>();
-        for (Map.Entry<String, List<ExtractConfigDetailCacheBean>> entry : examPaperMaps.entrySet()) {
-            List<ExtractConfigDetailCacheBean> list = examPaperMaps.get(entry.getKey());
-
-            String paperId = this.getPaperByProbability(list);
-            if (StringUtils.isEmpty(paperId)) {
-                continue;
-            }
-
-            paperTypeMaps.put(entry.getKey(), paperId);
-        }
-
-        return paperTypeMaps;
-    }
-
-    /**
-     * 根据设定几率取出一套试卷
-     */
-    private String getPaperByProbability(List<ExtractConfigDetailCacheBean> examPapers) {
-        int sum = 0;
-        for (ExtractConfigDetailCacheBean examPaper : examPapers) {
-            sum += examPaper.getWeight();
-        }
-
-        // 从1开始  
-        int r = new Random().nextInt(sum) + 1;
-        for (ExtractConfigDetailCacheBean examPaper : examPapers) {
-            r -= examPaper.getWeight();
-            if (r <= 0) {
-                return examPaper.getPaperId();// 选中
-            }
-        }
-
-        return null;
-    }
-
-    /**
-     * 根据paper对象构建DefaultPaper对象
-     */
-    public DefaultPaper buildDefaultByBasePaper(String basePaperId, Long examId, String courseCode, String groupCode) {
-        Paper basePaper = Model.of(paperRepo.findById(basePaperId));
-        return this.buildDefaultByBasePaper(basePaper, examId, courseCode, groupCode);
-    }
-
-    /**
-     * 根据paper对象构建DefaultPaper对象
-     */
-    public DefaultPaper buildDefaultByBasePaper(Paper basePaper, Long examId, String courseCode, String groupCode) {
-        LOG.debug("开始包装网考需要的试卷结构...");
-
-        //获取大题
-        List<PaperDetail> paperDetails = paperDetailRepo.findByPaper(basePaper);
-
-        //排序大题
-        Collections.sort(paperDetails);
-
-        //将小题全部取出来,只取一次,减少对数据库的查询
-        List<PaperDetailUnit> allPaperDetailUnits = paperDetailUnitRepo.findByPaper(basePaper);
-        boolean fullyObjective = checkIsAllQbjectiveQuestion(allPaperDetailUnits);
-
-        //根据大题id将小题归类
-        Map<String, List<PaperDetailUnit>> pduMap = allPaperDetailUnits.stream().collect(Collectors.groupingBy(PaperDetailUnit::getDetailId));
-
-        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 (CollectionUtils.isEmpty(paperDetailUnits)) {
-                LOG.warn("试卷大题下面没有小题!");
-                throw new StatusException("500", "考试试卷有误,请联系老师!");
-            }
-
-            //按题号顺序排序
-            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()) {
-                        AudioTimeConfig find = new AudioTimeConfig(examId.toString(), courseCode, groupCode, paperDetailUnit.getQuestion().getId());
-                        AudioTimeConfig audioTimeConfig = Model.of(audioTimeConfigRepo.findOne(Example.of(find)));
-                        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) {
-        Question question = Model.of(quesRepo.findById(questionId));
-        if (question == null) {
-            throw new StatusException("500", "试题不存在!");
-        }
-        quesService.formatQues(question);
-
-        //封装成新的题单元集合
-        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) {
-            appendAudioFlag(defaultQuestion, String.valueOf(examId), courseCode, groupCode, question);
-        }
-
-        // 获取试题信息带答案(敏感信息日志,用于排查调用者)
-        LOG.warn("$$$getQuestionWithAnswer questionId:{} examId:{} courseCode:{} groupCode:{}",
-                questionId, examId, courseCode, groupCode);
-        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(QuestionAnswerConvert.parseQuestionOptionAnswers(quesOptions));
-        } else {
-            defaultQuestionUnit.setRightAnswer(QuestionAnswerConvert.parseQuestionAnswers(question));
-        }
-
-        return defaultQuestionUnit;
-    }
-
-    /**
-     * 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 = sysProperty.getDomain() + questionAudio.getFileUrl();
-                        //通用存储
-                        String url = FileStorageUtil.realPath(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);
-        if (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<>();
-        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<>();
-        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 = QuestionAnswerConvert.parseQuestionOptionAnswers(subQuestion.getQuesOptions());
-                        answer = StringUtils.join(answers, ",");
-                    } 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 = QuestionAnswerConvert.parseQuestionOptionAnswers(question.getQuesOptions());
-                answer = StringUtils.join(answers, ",");
-            } 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;
-    }
+	private static final Logger LOG = LoggerFactory.getLogger(ExtractConfigProviderServiceImpl.class);
+
+	@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 SysProperty sysProperty;
+
+	@Override
+	public ExtractConfigCacheBean getExtractConfig(Long examId, String courseCode) {
+		ExtractConfig extractConfig = extractConfigService.findConfig(new ExtractConfig(examId, courseCode));
+		if (extractConfig == null) {
+			throw new StatusException("500", "该课程调卷规则未制定,请联系学校!");
+		}
+		if (CallType.WHOLE_SET.equals(extractConfig.getCallType())) {
+			if (CollectionUtils.isEmpty(extractConfig.getExamPaperList())) {
+				throw new StatusException("500", "可供抽取的试卷集合为空!");
+			}
+		}
+
+		ExtractConfigCacheBean cacheBean = new ExtractConfigCacheBean();
+		cacheBean.setId(extractConfig.getId());
+		cacheBean.setExamId(examId);
+		cacheBean.setCallType(extractConfig.getCallType());
+		cacheBean.setCourseCode(courseCode);
+		cacheBean.setRandomPaperId(extractConfig.getRandomPaperId());
+		cacheBean.setPlayTime(extractConfig.getPlayTime());
+		cacheBean.setSortQuestionOrder(extractConfig.getScrambling_the_question_order() != 0);
+		cacheBean.setSortOptionOrder(extractConfig.getScrambling_the_option_order() != 0);
+
+		if (CallType.WHOLE_SET.equals(extractConfig.getCallType())) {
+			List<ExtractConfigDetailCacheBean> details = new ArrayList<>();
+			for (ExamPaper examPaper : extractConfig.getExamPaperList()) {
+				details.add(new ExtractConfigDetailCacheBean(examPaper.getGroupCode(), examPaper.getPaper().getId(),
+						examPaper.getWeight()));
+			}
+			cacheBean.setDetails(details);
+		}
+
+		return cacheBean;
+	}
+
+	@Override
+	public ExtractConfigPaperCacheBean getExtractConfigPaper(Long examId, String courseCode, String groupCode,
+			String paperId) {
+		DefaultPaper defaultPaper = this.buildDefaultByBasePaper(paperId, examId, courseCode, groupCode);
+
+		ExtractConfigPaperCacheBean cacheBean = new ExtractConfigPaperCacheBean();
+		cacheBean.setDefaultPaper(defaultPaper);
+		return cacheBean;
+	}
+
+	@Override
+	public ExtractConfigPaper getDefaultPaper(Long examId, String courseCode, String groupCode) {
+		LOG.info("调卷开始...");
+
+		ExtractConfigCacheBean extractConfigCache = CacheHelper.getExtractConfig(examId, courseCode);
+		if (extractConfigCache == null) {
+			throw new StatusException("500", "该课程调卷规则未制定,请联系学校!");
+		}
+
+		final String msg = "该考试和课程下调卷规则中试卷不存在,请重新制定调卷规则!";
+		Map<String, String> paperTypeMaps = this.getExamPaperByProbability(extractConfigCache.getDetails());
+		if (paperTypeMaps.isEmpty()) {
+			throw new StatusException("500", msg);
+		}
+
+		String basePaperId = paperTypeMaps.get(groupCode);
+		if (StringUtils.isEmpty(basePaperId)) {
+			throw new StatusException("500", msg);
+		}
+
+		LOG.info("构建试卷结构..." + basePaperId);
+		ExtractConfigPaperCacheBean extractConfigPaperCache = CacheHelper.getExtractConfigPaper(examId, courseCode,
+				groupCode, basePaperId);
+		if (extractConfigPaperCache == null) {
+			throw new StatusException("500", msg);
+		}
+
+		ExtractConfigPaper result = new ExtractConfigPaper();
+		result.setDefaultPaper(extractConfigPaperCache.getDefaultPaper());
+		result.setPaperId(basePaperId);
+		result.setSortQuestionOrder(extractConfigCache.getSortQuestionOrder());
+		result.setSortOptionOrder(extractConfigCache.getSortOptionOrder());
+		return result;
+	}
+
+	/**
+	 * 每个试卷类型取出一套试卷 {A:paperId,B:paperId} A是试卷类型,paperId是A类型下选定的试卷ID
+	 */
+	private Map<String, String> getExamPaperByProbability(List<ExtractConfigDetailCacheBean> examPapers) {
+		if (CollectionUtils.isEmpty(examPapers)) {
+			throw new StatusException("500", "可供抽取的试卷集合为空!");
+		}
+
+		Map<String, List<ExtractConfigDetailCacheBean>> examPaperMaps = new HashMap<>();
+		for (ExtractConfigDetailCacheBean examPaper : examPapers) {
+			if (examPaperMaps.containsKey(examPaper.getGroupCode())) {
+				examPaperMaps.get(examPaper.getGroupCode()).add(examPaper);
+			} else {
+				List<ExtractConfigDetailCacheBean> list = new ArrayList<>();
+				list.add(examPaper);
+				examPaperMaps.put(examPaper.getGroupCode(), list);
+			}
+		}
+
+		Map<String, String> paperTypeMaps = new HashMap<>();
+		for (Map.Entry<String, List<ExtractConfigDetailCacheBean>> entry : examPaperMaps.entrySet()) {
+			List<ExtractConfigDetailCacheBean> list = examPaperMaps.get(entry.getKey());
+
+			String paperId = this.getPaperByProbability(list);
+			if (StringUtils.isEmpty(paperId)) {
+				continue;
+			}
+
+			paperTypeMaps.put(entry.getKey(), paperId);
+		}
+
+		return paperTypeMaps;
+	}
+
+	/**
+	 * 根据设定几率取出一套试卷
+	 */
+	private String getPaperByProbability(List<ExtractConfigDetailCacheBean> examPapers) {
+		int sum = 0;
+		for (ExtractConfigDetailCacheBean examPaper : examPapers) {
+			sum += examPaper.getWeight();
+		}
+
+		// 从1开始
+		int r = new Random().nextInt(sum) + 1;
+		for (ExtractConfigDetailCacheBean examPaper : examPapers) {
+			r -= examPaper.getWeight();
+			if (r <= 0) {
+				return examPaper.getPaperId();// 选中
+			}
+		}
+
+		return null;
+	}
+
+	/**
+	 * 根据paper对象构建DefaultPaper对象
+	 */
+	public DefaultPaper buildDefaultByBasePaper(String basePaperId, Long examId, String courseCode, String groupCode) {
+		Paper basePaper = Model.of(paperRepo.findById(basePaperId));
+		return this.buildDefaultByBasePaper(basePaper, examId, courseCode, groupCode);
+	}
+
+	/**
+	 * 根据paper对象构建DefaultPaper对象
+	 */
+	public DefaultPaper buildDefaultByBasePaper(Paper basePaper, Long examId, String courseCode, String groupCode) {
+		LOG.debug("开始包装网考需要的试卷结构...");
+
+		// 获取大题
+		List<PaperDetail> paperDetails = paperDetailRepo.findByPaper(basePaper);
+
+		// 排序大题
+		Collections.sort(paperDetails);
+
+		// 将小题全部取出来,只取一次,减少对数据库的查询
+		List<PaperDetailUnit> allPaperDetailUnits = paperDetailUnitRepo.findByPaper(basePaper);
+		boolean fullyObjective = checkIsAllQbjectiveQuestion(allPaperDetailUnits);
+
+		// 根据大题id将小题归类
+		Map<String, List<PaperDetailUnit>> pduMap = allPaperDetailUnits.stream()
+				.collect(Collectors.groupingBy(PaperDetailUnit::getDetailId));
+
+		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 (CollectionUtils.isEmpty(paperDetailUnits)) {
+				LOG.warn("试卷大题下面没有小题!");
+				throw new StatusException("500", "考试试卷有误,请联系老师!");
+			}
+
+			// 按题号顺序排序
+			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()) {
+						AudioTimeConfig find = new AudioTimeConfig(examId.toString(), courseCode, groupCode,
+								paperDetailUnit.getQuestion().getId());
+						AudioTimeConfig audioTimeConfig = Model.of(audioTimeConfigRepo.findOne(Example.of(find)));
+						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) {
+		Question question = Model.of(quesRepo.findById(questionId));
+		if (question == null) {
+			throw new StatusException("500", "试题不存在!");
+		}
+		quesService.formatQues(question);
+
+		// 封装成新的题单元集合
+		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) {
+			appendAudioFlag(defaultQuestion, String.valueOf(examId), courseCode, groupCode, question);
+		}
+
+		// 获取试题信息带答案(敏感信息日志,用于排查调用者)
+		LOG.warn("$$$getQuestionWithAnswer questionId:{} examId:{} courseCode:{} groupCode:{}", questionId, examId,
+				courseCode, groupCode);
+		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(QuestionAnswerConvert.parseQuestionOptionAnswers(quesOptions));
+		} else {
+			defaultQuestionUnit.setRightAnswer(QuestionAnswerConvert.parseQuestionAnswers(question));
+		}
+
+		return defaultQuestionUnit;
+	}
+
+	/**
+	 * 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 = sysProperty.getDomain() + questionAudio.getFileUrl();
+						// 通用存储
+						String url = FileStorageUtil.realPath(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);
+		if (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<>();
+		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<>();
+		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 = QuestionAnswerConvert
+								.parseQuestionOptionAnswers(subQuestion.getQuesOptions());
+						answer = StringUtils.join(answers, ",");
+					} 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 = QuestionAnswerConvert.parseQuestionOptionAnswers(question.getQuesOptions());
+				answer = StringUtils.join(answers, ",");
+			} 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;
+	}
 
 }

+ 10 - 5
examcloud-core-questions-service/src/main/java/cn/com/qmth/examcloud/core/questions/service/impl/ExtractConfigServiceImpl.java

@@ -190,21 +190,26 @@ public class ExtractConfigServiceImpl implements ExtractConfigService {
     @Transactional
     @Override
     public void saveExtractConfig(ExtractConfig extractConfig) {
+        Course course = courseService.getCourse(Long.valueOf(extractConfig.getOrgId()), extractConfig.getCourseCode());
+        extractConfig.setCourse(course);
+        extractConfig.setCourseName(course.getName());
 		// 新增,id为空
 		if (StringUtils.isBlank(extractConfig.getId())) {
 			// 先查询
 			ExtractConfig tempConfig = this.findConfig(extractConfig);
 			if (tempConfig != null) {
-				extractConfig.setId(tempConfig.getId());
-			}else {
-		        Course course = courseService.getCourse(Long.valueOf(extractConfig.getOrgId()), extractConfig.getCourseCode());
-		        extractConfig.setCourse(course);
-		        extractConfig.setCourseName(course.getName());
+				tempConfig.setRandomPaperId(extractConfig.getRandomPaperId());
+				tempConfig.setPlayTime(extractConfig.getPlayTime());
+				tempConfig.setCourseName(course.getName());
+				tempConfig.setCourse(course);
+				extractConfig=tempConfig;
 			}
 		}else {
 			ExtractConfig tempConfig = Model.of(extractConfigRepo.findById(extractConfig.getId()));
 			tempConfig.setRandomPaperId(extractConfig.getRandomPaperId());
 			tempConfig.setPlayTime(extractConfig.getPlayTime());
+			tempConfig.setCourseName(course.getName());
+			tempConfig.setCourse(course);
 			extractConfig=tempConfig;
 		}
         extractConfigRepo.save(extractConfig);