|
@@ -1,17 +1,38 @@
|
|
|
/*
|
|
|
- * *************************************************
|
|
|
- * Copyright (c) 2018 QMTH. All Rights Reserved.
|
|
|
- * Created by Deason on 2018-07-12 15:33:35.
|
|
|
+ * ************************************************* Copyright (c) 2018 QMTH.
|
|
|
+ * All Rights Reserved. Created by Deason on 2018-07-12 15:33:35.
|
|
|
* *************************************************
|
|
|
*/
|
|
|
|
|
|
package cn.com.qmth.examcloud.core.questions.service.converter;
|
|
|
|
|
|
+import java.io.File;
|
|
|
+import java.util.ArrayList;
|
|
|
+import java.util.HashMap;
|
|
|
+import java.util.HashSet;
|
|
|
+import java.util.List;
|
|
|
+import java.util.Map;
|
|
|
+import java.util.Set;
|
|
|
+
|
|
|
+import org.apache.commons.io.FileUtils;
|
|
|
+import org.apache.commons.lang3.StringUtils;
|
|
|
+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.core.questions.base.IoUtils;
|
|
|
import cn.com.qmth.examcloud.core.questions.base.converter.model.Constants;
|
|
|
import cn.com.qmth.examcloud.core.questions.base.converter.model.PolicyType;
|
|
|
import cn.com.qmth.examcloud.core.questions.base.converter.model.QuesStructType;
|
|
|
-import cn.com.qmth.examcloud.core.questions.base.converter.model.dps.*;
|
|
|
+import cn.com.qmth.examcloud.core.questions.base.converter.model.dps.PaperAnswerDto;
|
|
|
+import cn.com.qmth.examcloud.core.questions.base.converter.model.dps.PaperDetailDto;
|
|
|
+import cn.com.qmth.examcloud.core.questions.base.converter.model.dps.PaperDto;
|
|
|
+import cn.com.qmth.examcloud.core.questions.base.converter.model.dps.PolicyDto;
|
|
|
+import cn.com.qmth.examcloud.core.questions.base.converter.model.dps.PolicyWeightDto;
|
|
|
+import cn.com.qmth.examcloud.core.questions.base.converter.model.dps.QuestionDto;
|
|
|
+import cn.com.qmth.examcloud.core.questions.base.converter.model.dps.QuestionOptionDto;
|
|
|
+import cn.com.qmth.examcloud.core.questions.base.converter.model.dps.SimpleQuestionDto;
|
|
|
import cn.com.qmth.examcloud.core.questions.base.converter.model.platform.PaperDetailVo;
|
|
|
import cn.com.qmth.examcloud.core.questions.base.converter.model.platform.PaperVo;
|
|
|
import cn.com.qmth.examcloud.core.questions.base.converter.model.platform.QuestionVo;
|
|
@@ -26,28 +47,22 @@ import cn.com.qmth.examcloud.core.questions.dao.entity.PaperDetailUnit;
|
|
|
import cn.com.qmth.examcloud.core.questions.dao.entity.Question;
|
|
|
import cn.com.qmth.examcloud.core.questions.service.PaperDetailService;
|
|
|
import cn.com.qmth.examcloud.core.questions.service.PaperService;
|
|
|
-import org.apache.commons.io.FileUtils;
|
|
|
-import org.apache.commons.lang3.StringUtils;
|
|
|
-import org.slf4j.Logger;
|
|
|
-import org.slf4j.LoggerFactory;
|
|
|
-import org.springframework.beans.factory.annotation.Autowired;
|
|
|
-import org.springframework.stereotype.Service;
|
|
|
-
|
|
|
-import java.io.File;
|
|
|
-import java.util.*;
|
|
|
|
|
|
/**
|
|
|
* 分布式印刷考试的试卷转换服务类
|
|
|
*/
|
|
|
@Service
|
|
|
public class PrintExamPaperService {
|
|
|
+
|
|
|
private static Logger log = LoggerFactory.getLogger(PrintExamPaperService.class);
|
|
|
+
|
|
|
@Autowired
|
|
|
private PaperService paperService;
|
|
|
+
|
|
|
@Autowired
|
|
|
private PaperDetailService paperDetailService;
|
|
|
|
|
|
- public void downloadPaper(List<Paper> oldPapers, String dirPath, String password) throws Exception {
|
|
|
+ public void downloadPaper(List<Paper> oldPapers, String dirPath, String password) {
|
|
|
if (oldPapers == null || oldPapers.size() == 0) {
|
|
|
throw new IllegalArgumentException("Paper list size is empty.");
|
|
|
}
|
|
@@ -60,14 +75,14 @@ public class PrintExamPaperService {
|
|
|
}
|
|
|
}
|
|
|
log.info("exportPrintExamPaper start!");
|
|
|
- //提取题库试卷的数据
|
|
|
+ // 提取题库试卷的数据
|
|
|
List<PaperVo> papers = new ArrayList<>();
|
|
|
for (Paper oldPaper : oldPapers) {
|
|
|
List<PaperDetail> oldDetails = paperService.findPaperDetailsById(oldPaper.getId());
|
|
|
if (oldDetails == null || oldDetails.size() == 0) {
|
|
|
continue;
|
|
|
}
|
|
|
- //封装试卷
|
|
|
+ // 封装试卷
|
|
|
PaperVo paper = new PaperVo();
|
|
|
paper.setId(oldPaper.getId());
|
|
|
paper.setName(oldPaper.getName());
|
|
@@ -82,7 +97,7 @@ public class PrintExamPaperService {
|
|
|
if (oldDetailUnits == null || oldDetailUnits.size() == 0) {
|
|
|
continue;
|
|
|
}
|
|
|
- //封装大题
|
|
|
+ // 封装大题
|
|
|
PaperDetailVo detail = new PaperDetailVo();
|
|
|
detail.setNumber(oldDetail.getNumber());
|
|
|
detail.setName(oldDetail.getName());
|
|
@@ -92,7 +107,7 @@ public class PrintExamPaperService {
|
|
|
for (int i = 0; i < oldDetailUnits.size(); i++) {
|
|
|
PaperDetailUnit oldDetailUnit = oldDetailUnits.get(i);
|
|
|
Question oldQuestion = oldDetailUnit.getQuestion();
|
|
|
- //封装试题
|
|
|
+ // 封装试题
|
|
|
QuestionVo question = new QuestionVo();
|
|
|
question.setNumber(i + 1);
|
|
|
question.setId(oldDetailUnit.getId());
|
|
@@ -104,7 +119,7 @@ public class PrintExamPaperService {
|
|
|
question.setOptions(ConvertQuestion.parseOption(oldQuestion));
|
|
|
questions.add(question);
|
|
|
|
|
|
- //封装套题
|
|
|
+ // 封装套题
|
|
|
List<Question> oldSubQuestions = oldQuestion.getSubQuestions();
|
|
|
if (oldSubQuestions == null || oldSubQuestions.size() == 0) {
|
|
|
continue;
|
|
@@ -139,28 +154,28 @@ public class PrintExamPaperService {
|
|
|
/**
|
|
|
* 将题库试卷格式转换为分布式印刷的试卷格式
|
|
|
*/
|
|
|
- public void convert(List<PaperVo> papers, String dirPath, String password) throws Exception {
|
|
|
+ public void convert(List<PaperVo> papers, String dirPath, String password) {
|
|
|
if (papers == null || papers.size() == 0) {
|
|
|
log.warn("No paper to convert.");
|
|
|
return;
|
|
|
}
|
|
|
- //临时目录
|
|
|
+ // 临时目录
|
|
|
dirPath = dirPath.replaceAll("\\\\", "/");
|
|
|
final String tempName = ExamFileType.PRINT_EXAM_PACKAGE.getName() + "_" + FileUtil.generateDateName();
|
|
|
final String tempDir = dirPath + "/" + tempName;
|
|
|
final String tempFilePath = dirPath + "/" + tempName + ".zip";
|
|
|
FileUtil.makeDirs(tempDir);
|
|
|
|
|
|
- //汇总课程编码
|
|
|
+ // 汇总课程编码
|
|
|
Set<String> courseCodes = new HashSet<>();
|
|
|
for (PaperVo paper : papers) {
|
|
|
courseCodes.add(paper.getCourseCode());
|
|
|
}
|
|
|
|
|
|
- //按"课程编码"封装试卷,数据文件转换保存到临时目录
|
|
|
+ // 按"课程编码"封装试卷,数据文件转换保存到临时目录
|
|
|
this.parseCoursePapers(courseCodes, papers, tempDir, password);
|
|
|
|
|
|
- //压缩转换后的数据包
|
|
|
+ // 压缩转换后的数据包
|
|
|
File tempDirFile = new File(tempDir);
|
|
|
File tempFile = new File(tempFilePath);
|
|
|
FileUtil.doZip(tempDirFile, tempFile);
|
|
@@ -171,12 +186,12 @@ public class PrintExamPaperService {
|
|
|
* 按"课程编码"汇总试卷,数据文件转换保存到临时目录
|
|
|
*/
|
|
|
private void parseCoursePapers(Set<String> courseCodes, List<PaperVo> papers, String tempDir, String password) {
|
|
|
- //试卷和答案分开汇总到不同文件夹
|
|
|
+ // 试卷和答案分开汇总到不同文件夹
|
|
|
final String paperDir = tempDir + "/paper";
|
|
|
final String answerDir = tempDir + "/answer";
|
|
|
- String key = null;//加密密匙
|
|
|
+ String key = null;// 加密密匙
|
|
|
if (StringUtils.isNotBlank(password)) {
|
|
|
- //用密码生成密匙
|
|
|
+ // 用密码生成密匙
|
|
|
key = Cryptogram.convertKey(password);
|
|
|
}
|
|
|
JsonMapper mapper = JsonMapper.nonNullMapper();
|
|
@@ -190,7 +205,7 @@ public class PrintExamPaperService {
|
|
|
this.parsePaper(paper, paperList, answerList);
|
|
|
}
|
|
|
if (key != null) {
|
|
|
- //加密试卷和答案
|
|
|
+ // 加密试卷和答案
|
|
|
this.aesPaper(paperList, key);
|
|
|
this.aesAnswer(answerList, key);
|
|
|
}
|
|
@@ -198,7 +213,7 @@ public class PrintExamPaperService {
|
|
|
FileUtil.saveAsFile(paperDir + "/" + courseCode + "/" + Constants.FILE_PAPER, mapper.toJson(paperList));
|
|
|
FileUtil.saveAsFile(paperDir + "/" + courseCode + "/" + Constants.FILE_POLICY, mapper.toJson(policyList));
|
|
|
FileUtil.saveAsFile(answerDir + "/" + courseCode + "/" + Constants.FILE_ANSWER, mapper.toJson(answerList));
|
|
|
- //json = CommonUtils.replaceUnicodeStr(json);//todo
|
|
|
+ // json = CommonUtils.replaceUnicodeStr(json);//todo
|
|
|
}
|
|
|
|
|
|
File paperZipFile = new File(tempDir + "/paper.zip");
|
|
@@ -208,10 +223,10 @@ public class PrintExamPaperService {
|
|
|
FileUtil.doZip(paperDirFile, paperZipFile);
|
|
|
FileUtil.doZip(answerDirFile, answerZipFile);
|
|
|
|
|
|
- short[] paperHeaders = {1, 1};//试卷头信息
|
|
|
- short[] paperAesHeaders = {1, 2};//试卷加密头信息
|
|
|
- short[] answerHeaders = {2, 1};//答案头信息
|
|
|
- short[] answerAesHeaders = {2, 2};//答案加密头信息
|
|
|
+ short[] paperHeaders = { 1, 1 };// 试卷头信息
|
|
|
+ short[] paperAesHeaders = { 1, 2 };// 试卷加密头信息
|
|
|
+ short[] answerHeaders = { 2, 1 };// 答案头信息
|
|
|
+ short[] answerAesHeaders = { 2, 2 };// 答案加密头信息
|
|
|
if (StringUtils.isNotBlank(password)) {
|
|
|
String sign = Cryptogram.md5Key(password);
|
|
|
FileUtil.appendHeader(paperZipFile, paperAesHeaders, sign);
|
|
@@ -224,24 +239,24 @@ public class PrintExamPaperService {
|
|
|
IoUtils.removeFile(paperZipFile);
|
|
|
IoUtils.removeFile(answerZipFile);
|
|
|
|
|
|
- //FileUtils.deleteQuietly(paperDirFile);
|
|
|
- //FileUtils.deleteQuietly(answerDirFile);
|
|
|
+ // FileUtils.deleteQuietly(paperDirFile);
|
|
|
+ // FileUtils.deleteQuietly(answerDirFile);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 解析试卷
|
|
|
*/
|
|
|
private void parsePaper(PaperVo paper, List<PaperDto> paperList, List<PaperAnswerDto> answerList) {
|
|
|
- //试卷类型给默认值A-Z
|
|
|
+ // 试卷类型给默认值A-Z
|
|
|
String paperType = NumUtil.toEnNumber(paperList.size() + 1);
|
|
|
- //封装试卷完整信息
|
|
|
+ // 封装试卷完整信息
|
|
|
PaperDto newPaper = new PaperDto(paper);
|
|
|
newPaper.setPaperType(paperType);
|
|
|
List<PaperDetailVo> details = paper.getDetails();
|
|
|
if (details == null || details.size() == 0) {
|
|
|
throw new IllegalArgumentException("试卷的大题不能为空!");
|
|
|
}
|
|
|
- Double paperScore = 0d;//试卷总分
|
|
|
+ Double paperScore = 0d;// 试卷总分
|
|
|
PaperAnswerDto newAnswer = new PaperAnswerDto(paper.getId());
|
|
|
List<PaperDetailDto> newDetails = new ArrayList<>();
|
|
|
for (PaperDetailVo detail : details) {
|
|
@@ -249,20 +264,20 @@ public class PrintExamPaperService {
|
|
|
if (questions == null || questions.size() == 0) {
|
|
|
throw new IllegalArgumentException("试卷大题下的试题不能为空!");
|
|
|
}
|
|
|
- Double detailScore = 0d;//大题总分
|
|
|
+ Double detailScore = 0d;// 大题总分
|
|
|
PaperDetailDto newDetail = new PaperDetailDto(detail);
|
|
|
for (QuestionVo question : questions) {
|
|
|
- //封装试题
|
|
|
+ // 封装试题
|
|
|
QuestionDto newQuestion = new QuestionDto(question);
|
|
|
- //封装试题答案
|
|
|
+ // 封装试题答案
|
|
|
SimpleQuestionDto simpleQuestion = new SimpleQuestionDto(question);
|
|
|
if (question.hasSubQuestion()) {
|
|
|
- Double questionScore = 0d;//套题总分
|
|
|
+ Double questionScore = 0d;// 套题总分
|
|
|
for (QuestionVo subQuestion : question.getSubQuestions()) {
|
|
|
- //封装子试题
|
|
|
+ // 封装子试题
|
|
|
QuestionDto newSubQuestion = new QuestionDto(subQuestion);
|
|
|
newQuestion.addSubQuestion(newSubQuestion);
|
|
|
- //封装子试题答案
|
|
|
+ // 封装子试题答案
|
|
|
SimpleQuestionDto subSimpleQuestion = new SimpleQuestionDto(subQuestion);
|
|
|
subSimpleQuestion.setNumber(subQuestion.getNumber());
|
|
|
simpleQuestion.addSubQuestion(subSimpleQuestion);
|
|
@@ -288,7 +303,7 @@ public class PrintExamPaperService {
|
|
|
* 解析试卷试题
|
|
|
*/
|
|
|
private List<PaperDetailDto> parseDetails(List<PaperDetailDto> details) {
|
|
|
- //聚合同类题,并重新计算每道大题的总分以及题号顺序
|
|
|
+ // 聚合同类题,并重新计算每道大题的总分以及题号顺序
|
|
|
List<PaperDetailDto> allDetails = new ArrayList<>();
|
|
|
PaperDetailDto singleDetail = new PaperDetailDto(QuesStructType.SINGLE_ANSWER_QUESTION.getName());
|
|
|
PaperDetailDto multipleDetail = new PaperDetailDto(QuesStructType.MULTIPLE_ANSWER_QUESTION.getName());
|
|
@@ -368,7 +383,7 @@ public class PrintExamPaperService {
|
|
|
List<PolicyDto> policyList = new ArrayList<>();
|
|
|
Map<String, List<String>> maps = new HashMap<>();
|
|
|
for (PaperDto paper : papers) {
|
|
|
- //按试卷类型封装试卷ID
|
|
|
+ // 按试卷类型封装试卷ID
|
|
|
List<String> ids = maps.get(paper.getPaperType());
|
|
|
if (ids == null) {
|
|
|
ids = new ArrayList<>();
|
|
@@ -376,7 +391,7 @@ public class PrintExamPaperService {
|
|
|
ids.add(paper.getId());
|
|
|
maps.put(paper.getPaperType(), ids);
|
|
|
}
|
|
|
- //生成默认调卷规则
|
|
|
+ // 生成默认调卷规则
|
|
|
for (Map.Entry<String, List<String>> entry : maps.entrySet()) {
|
|
|
PolicyDto policy = new PolicyDto();
|
|
|
policy.setType(PolicyType.Random.getId());
|
|
@@ -388,7 +403,7 @@ public class PrintExamPaperService {
|
|
|
if (ids.size() == 0) {
|
|
|
continue;
|
|
|
}
|
|
|
- //计算每份试卷的随机抽取权重
|
|
|
+ // 计算每份试卷的随机抽取权重
|
|
|
double weight = 1d / ids.size();
|
|
|
for (String id : ids) {
|
|
|
policy.addWeight(new PolicyWeightDto(id, weight));
|
|
@@ -411,7 +426,7 @@ public class PrintExamPaperService {
|
|
|
List<QuestionOptionDto> options = question.getOptions();
|
|
|
if (options != null) {
|
|
|
for (QuestionOptionDto option : options) {
|
|
|
- String newBody = Cryptogram.aesEncrypt(option.getBody(), key);//加密选项内容
|
|
|
+ String newBody = Cryptogram.aesEncrypt(option.getBody(), key);// 加密选项内容
|
|
|
option.setBody(newBody);
|
|
|
}
|
|
|
}
|
|
@@ -421,15 +436,15 @@ public class PrintExamPaperService {
|
|
|
List<QuestionOptionDto> subOptions = subQuestion.getOptions();
|
|
|
if (subOptions != null) {
|
|
|
for (QuestionOptionDto option : subOptions) {
|
|
|
- String newBody = Cryptogram.aesEncrypt(option.getBody(), key);//加密(子题)选项内容
|
|
|
+ String newBody = Cryptogram.aesEncrypt(option.getBody(), key);// 加密(子题)选项内容
|
|
|
option.setBody(newBody);
|
|
|
}
|
|
|
}
|
|
|
- String newBody = Cryptogram.aesEncrypt(subQuestion.getBody(), key);//加密(子题)题干内容
|
|
|
+ String newBody = Cryptogram.aesEncrypt(subQuestion.getBody(), key);// 加密(子题)题干内容
|
|
|
subQuestion.setBody(newBody);
|
|
|
}
|
|
|
}
|
|
|
- String newBody = Cryptogram.aesEncrypt(question.getBody(), key);//加密题干内容
|
|
|
+ String newBody = Cryptogram.aesEncrypt(question.getBody(), key);// 加密题干内容
|
|
|
question.setBody(newBody);
|
|
|
}
|
|
|
}
|
|
@@ -447,11 +462,11 @@ public class PrintExamPaperService {
|
|
|
List<SimpleQuestionDto> subQuestions = question.getSubQuestions();
|
|
|
if (subQuestions != null) {
|
|
|
for (SimpleQuestionDto subQuestion : subQuestions) {
|
|
|
- String newAnswer = Cryptogram.aesEncrypt(subQuestion.getAnswer(), key);//加密答案内容
|
|
|
+ String newAnswer = Cryptogram.aesEncrypt(subQuestion.getAnswer(), key);// 加密答案内容
|
|
|
subQuestion.setAnswer(newAnswer);
|
|
|
}
|
|
|
}
|
|
|
- String newAnswer = Cryptogram.aesEncrypt(question.getAnswer(), key);//加密答案内容
|
|
|
+ String newAnswer = Cryptogram.aesEncrypt(question.getAnswer(), key);// 加密答案内容
|
|
|
question.setAnswer(newAnswer);
|
|
|
}
|
|
|
}
|
|
@@ -463,12 +478,12 @@ public class PrintExamPaperService {
|
|
|
@SuppressWarnings("unused")
|
|
|
private List<File> parseDataFiles(final String dirPath, File zipFile) throws Exception {
|
|
|
List<File> dataFileList = new ArrayList<>();
|
|
|
- //解压当前文件
|
|
|
+ // 解压当前文件
|
|
|
List<File> fileList = FileUtil.unZip(new File(dirPath), zipFile);
|
|
|
if (fileList == null || fileList.size() == 0) {
|
|
|
return dataFileList;
|
|
|
}
|
|
|
- //解压当前文件内的其它ZIP文件,并提取JSON文件
|
|
|
+ // 解压当前文件内的其它ZIP文件,并提取JSON文件
|
|
|
for (File curFile : fileList) {
|
|
|
if (curFile.getName().toLowerCase().endsWith(Constants.ZIP)) {
|
|
|
final String curDir = FileUtil.getFilePathName(curFile.getAbsolutePath());
|