|
@@ -0,0 +1,621 @@
|
|
|
+package com.qmth.cqb.paper.service.export;
|
|
|
+
|
|
|
+import java.io.File;
|
|
|
+import java.io.FileNotFoundException;
|
|
|
+import java.io.FileOutputStream;
|
|
|
+import java.io.IOException;
|
|
|
+import java.util.ArrayList;
|
|
|
+import java.util.HashSet;
|
|
|
+import java.util.List;
|
|
|
+import java.util.Set;
|
|
|
+import java.util.stream.Collectors;
|
|
|
+
|
|
|
+import main.java.com.UpYun;
|
|
|
+
|
|
|
+import org.apache.commons.io.FileUtils;
|
|
|
+import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
+import org.springframework.beans.factory.annotation.Value;
|
|
|
+import org.springframework.data.domain.Example;
|
|
|
+
|
|
|
+import cn.com.qmth.examcloud.common.dto.question.enums.QuesStructType;
|
|
|
+import cn.com.qmth.examcloud.common.uac.entity.AccessUser;
|
|
|
+import cn.com.qmth.examcloud.common.util.excel.ExcelWriter;
|
|
|
+
|
|
|
+import com.google.gson.Gson;
|
|
|
+import com.qmth.cqb.paper.dao.AudioTimeConfigRepo;
|
|
|
+import com.qmth.cqb.paper.dao.PaperDetailRepo;
|
|
|
+import com.qmth.cqb.paper.dao.PaperDetailUnitRepo;
|
|
|
+import com.qmth.cqb.paper.dao.PaperRepo;
|
|
|
+import com.qmth.cqb.paper.dto.ObjectiveQuestionStructure;
|
|
|
+import com.qmth.cqb.paper.dto.PaperDetailExp;
|
|
|
+import com.qmth.cqb.paper.dto.PaperDetailUnitExp;
|
|
|
+import com.qmth.cqb.paper.dto.PaperExp;
|
|
|
+import com.qmth.cqb.paper.dto.SubjectiveQuestionStructure;
|
|
|
+import com.qmth.cqb.paper.model.AudioTimeConfig;
|
|
|
+import com.qmth.cqb.paper.model.ExamFile;
|
|
|
+import com.qmth.cqb.paper.model.ExportStructure;
|
|
|
+import com.qmth.cqb.paper.model.ExtractConfig;
|
|
|
+import com.qmth.cqb.paper.model.Paper;
|
|
|
+import com.qmth.cqb.paper.model.PaperDetailUnit;
|
|
|
+import com.qmth.cqb.paper.model.QuestionTypeNum;
|
|
|
+import com.qmth.cqb.paper.model.computerTestModel.Block;
|
|
|
+import com.qmth.cqb.paper.model.computerTestModel.ComputerTestOption;
|
|
|
+import com.qmth.cqb.paper.model.computerTestModel.ComputerTestPaper;
|
|
|
+import com.qmth.cqb.paper.model.computerTestModel.ComputerTestPaperDetail;
|
|
|
+import com.qmth.cqb.paper.model.computerTestModel.ComputerTestQuestion;
|
|
|
+import com.qmth.cqb.paper.model.computerTestModel.Section;
|
|
|
+import com.qmth.cqb.paper.model.computerTestModel.Sections;
|
|
|
+import com.qmth.cqb.paper.service.ExamFileService;
|
|
|
+import com.qmth.cqb.paper.service.PaperDetailService;
|
|
|
+import com.qmth.cqb.paper.service.PaperService;
|
|
|
+import com.qmth.cqb.question.dao.QuesRepo;
|
|
|
+import com.qmth.cqb.question.model.Question;
|
|
|
+import com.qmth.cqb.question.model.QuestionAudio;
|
|
|
+import com.qmth.cqb.question.service.QuestionAudioService;
|
|
|
+import com.qmth.cqb.utils.CommonUtils;
|
|
|
+import com.qmth.cqb.utils.FileDisposeUtil;
|
|
|
+import com.qmth.cqb.utils.enums.ExamFileType;
|
|
|
+import com.qmth.cqb.utils.word.DocxProcessUtil;
|
|
|
+
|
|
|
+import freemarker.template.Configuration;
|
|
|
+import freemarker.template.Template;
|
|
|
+
|
|
|
+/**
|
|
|
+ *
|
|
|
+ * @author chenken
|
|
|
+ * @date 2017年7月15日 下午4:00:24
|
|
|
+ * @company QMTH
|
|
|
+ * @description 导出、上传文件service 父类
|
|
|
+ */
|
|
|
+public abstract class ExportPaperAbstractService {
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ protected PaperRepo paperRepo;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ protected PaperService paperService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ protected PaperDetailRepo paperDetailRepo;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ protected PaperDetailUnitRepo paperDetailUnitRepo;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ protected ExamFileService examFileService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ protected PaperDetailService paperDetailService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ protected QuestionAudioService questionAudioService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ protected BuildComputerTestJsonService buildComputerTestJsonService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ protected InitPaperExpService initPaperExpService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ protected QuesRepo quesRepo;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ protected AudioTimeConfigRepo audioTimeConfigRepo;
|
|
|
+
|
|
|
+ public static final String FILL_BLANK_QUESTION_FLAG = "###";
|
|
|
+
|
|
|
+ public static final String TEMP_FILE_EXP = "docxExport/";
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Word文件后缀
|
|
|
+ */
|
|
|
+ public static final String DOCX_SUFFIX = ".docx";
|
|
|
+ /**
|
|
|
+ * Excel文件后缀
|
|
|
+ */
|
|
|
+ public static final String EXCEL_SUFFIX = ".xlsx";
|
|
|
+ /**
|
|
|
+ * ZIP文件后缀
|
|
|
+ */
|
|
|
+ public static final String ZIP_SUFFIX = ".zip";
|
|
|
+
|
|
|
+ public static final String ENCODING = "UTF-8";
|
|
|
+ /**
|
|
|
+ * 下划线
|
|
|
+ */
|
|
|
+ private static final String UNDERSCORE = "_";
|
|
|
+
|
|
|
+ //陕西师范模板
|
|
|
+ protected static Template SXSF_TEMPLATE_PAPER;
|
|
|
+ protected static Template SXSF_TEMPLATE_ANSWER;
|
|
|
+
|
|
|
+ //电子科大模板
|
|
|
+ protected static Template DZKD_TEMPLATE_PAPER;
|
|
|
+ protected static Template DZKD_TEMPLATE_ANSWER;
|
|
|
+
|
|
|
+ //华中科技大学模板
|
|
|
+ protected static Template HZKJ_TEMPLATE_PAPER;
|
|
|
+ protected static Template HZKJ_TEMPLATE_ANSWER;
|
|
|
+
|
|
|
+ //山东大学
|
|
|
+ protected static Template SDDX_TEMPLATE_PAPER;
|
|
|
+ protected static Template SDDX_TEMPLATE_ANSWER;
|
|
|
+
|
|
|
+ //天津大学
|
|
|
+ protected static Template TJDX_TEMPLATE_PAPER;
|
|
|
+ protected static Template TJDX_TEMPLATE_ANSWER;
|
|
|
+
|
|
|
+ //石油大学模板
|
|
|
+ protected static Template SYDX_TEMPLATE_PAPER;
|
|
|
+ protected static Template SYDX_TEMPLATE_ANSWER;
|
|
|
+
|
|
|
+ //西安交大模板
|
|
|
+ protected static Template XAJD_TEMPLATE_PAPER;
|
|
|
+ protected static Template XAJD_TEMPLATE_ANSWER;
|
|
|
+
|
|
|
+ @Value("${upyun.bucketName}")
|
|
|
+ protected String bucketName;
|
|
|
+
|
|
|
+ @Value("${upyun.userName}")
|
|
|
+ protected String userName;
|
|
|
+
|
|
|
+ @Value("${upyun.password}")
|
|
|
+ protected String password;
|
|
|
+
|
|
|
+ @Value("${upyun.uploadUrl}")
|
|
|
+ protected String uploadUrl;
|
|
|
+
|
|
|
+ @Value("${upyun.downloadUrl}")
|
|
|
+ protected String downloadUrl;
|
|
|
+
|
|
|
+ public static Configuration CONFIGURATION;
|
|
|
+
|
|
|
+ static {
|
|
|
+ try {
|
|
|
+ CONFIGURATION = new Configuration(Configuration.VERSION_2_3_25);
|
|
|
+ // 设置编码
|
|
|
+ CONFIGURATION.setDefaultEncoding(ENCODING);
|
|
|
+ // 设置ftl模板路径
|
|
|
+ CONFIGURATION.setClassForTemplateLoading(DocxProcessUtil.class, "/");
|
|
|
+
|
|
|
+ CONFIGURATION = new Configuration(Configuration.VERSION_2_3_25);
|
|
|
+ // 设置编码
|
|
|
+ CONFIGURATION.setDefaultEncoding(ENCODING);
|
|
|
+ // 设置ftl模板路径
|
|
|
+ CONFIGURATION.setClassForTemplateLoading(DocxProcessUtil.class, "/");
|
|
|
+
|
|
|
+ SXSF_TEMPLATE_PAPER = CONFIGURATION.getTemplate("sxsf_paper_template.ftl", ENCODING);
|
|
|
+ SXSF_TEMPLATE_ANSWER = CONFIGURATION.getTemplate("sxsf_answer_template.ftl", ENCODING);
|
|
|
+
|
|
|
+ DZKD_TEMPLATE_PAPER = CONFIGURATION.getTemplate("dzkd_paper_template.ftl", ENCODING);
|
|
|
+ DZKD_TEMPLATE_ANSWER = CONFIGURATION.getTemplate("dzkd_answer_template.ftl", ENCODING);
|
|
|
+
|
|
|
+ HZKJ_TEMPLATE_PAPER = CONFIGURATION.getTemplate("hzkj_paper_template.ftl", ENCODING);
|
|
|
+ HZKJ_TEMPLATE_ANSWER = CONFIGURATION.getTemplate("hzkj_answer_template.ftl", ENCODING);
|
|
|
+
|
|
|
+ SDDX_TEMPLATE_PAPER = CONFIGURATION.getTemplate("sddx_paper_template.ftl", ENCODING);
|
|
|
+ SDDX_TEMPLATE_ANSWER = CONFIGURATION.getTemplate("sddx_answer_template.ftl", ENCODING);
|
|
|
+
|
|
|
+ TJDX_TEMPLATE_PAPER = CONFIGURATION.getTemplate("tjdx_paper_template.ftl", ENCODING);
|
|
|
+ TJDX_TEMPLATE_ANSWER = CONFIGURATION.getTemplate("tjdx_answer_template.ftl", ENCODING);
|
|
|
+
|
|
|
+ SYDX_TEMPLATE_PAPER = CONFIGURATION.getTemplate("sydx_paper_template.ftl", ENCODING);
|
|
|
+ SYDX_TEMPLATE_ANSWER = CONFIGURATION.getTemplate("sydx_answer_template.ftl", ENCODING);
|
|
|
+
|
|
|
+ XAJD_TEMPLATE_PAPER = CONFIGURATION.getTemplate("xajd_paper_template.ftl", ENCODING);
|
|
|
+ } catch (Exception e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 下载试卷
|
|
|
+ * @param id
|
|
|
+ * @param response
|
|
|
+ * @throws Exception
|
|
|
+ */
|
|
|
+ public abstract void downloadPaper(String paperId,String zipFileName)throws Exception;
|
|
|
+ /**
|
|
|
+ * 下载答案
|
|
|
+ * @param paperId
|
|
|
+ * @param response
|
|
|
+ * @throws Exception
|
|
|
+ */
|
|
|
+ public abstract void downloadPaperAnswer(String paperId,String zipFileName)throws Exception;
|
|
|
+ /**
|
|
|
+ * 上传试卷相关文件
|
|
|
+ * @param orgName
|
|
|
+ * @param examName
|
|
|
+ * @param paperId
|
|
|
+ * @throws Exception
|
|
|
+ */
|
|
|
+ public abstract void uploadFile(ExtractConfig extractConfig,String paperId,ExportStructure exportStructure,AccessUser accessUser) throws Exception;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 创建机考文件,并打包上传至又拍云
|
|
|
+ * @param paperId
|
|
|
+ * @param currNum
|
|
|
+ * ObjectId("591ead1290994d57cd453464")
|
|
|
+ * @throws IOException
|
|
|
+ */
|
|
|
+ protected void uploadComputerTestFile(ExtractConfig extractConfig,AccessUser accessUser) throws IOException{
|
|
|
+ List<ComputerTestPaper> computerTestPaperList = buildComputerTestJsonService.buildComputerTestPapers(extractConfig);
|
|
|
+ String currentTimeStr = CommonUtils.getCurNum();
|
|
|
+ for(int i = 0;i<computerTestPaperList.size();i++){
|
|
|
+ ComputerTestPaper computerTestPaper = computerTestPaperList.get(i);
|
|
|
+ String jsonDirectoryName = currentTimeStr+UNDERSCORE+ExamFileType.COMPUTERTEST_PACKAGE.name()+UNDERSCORE+i;
|
|
|
+ String jsonDirectoryPath = TEMP_FILE_EXP + File.separator + jsonDirectoryName;
|
|
|
+ //新建文件夹
|
|
|
+ File dirFile = new File(jsonDirectoryPath);
|
|
|
+ if(!dirFile.exists()){
|
|
|
+ dirFile.mkdirs();
|
|
|
+ }
|
|
|
+ //下载试卷中的音频文件到jsonDirectoryPath文件夹中
|
|
|
+ downloadQuestionAudio(computerTestPaper,jsonDirectoryPath,extractConfig.getExamId()+"");
|
|
|
+ //将computerTestPaper对象生成JSON文件存放在jsonDirectoryPath中
|
|
|
+ makeComputerTestPaperToJsonFile(extractConfig,computerTestPaper,jsonDirectoryPath);
|
|
|
+ //将文件夹打包成zip压缩包放在docxExport下
|
|
|
+ FileDisposeUtil.fileToZip(jsonDirectoryPath,"docxExport",jsonDirectoryName);
|
|
|
+ //上传zip压缩包到又拍云
|
|
|
+ File zipFile = new File(TEMP_FILE_EXP+jsonDirectoryName+ZIP_SUFFIX);
|
|
|
+ String zipUpyunFilePath = uploadUrl+extractConfig.getOrgId()+"/"+jsonDirectoryName+ZIP_SUFFIX;
|
|
|
+ UpYun upyun = new UpYun(bucketName,userName,password);
|
|
|
+ upyun.writeFile(zipUpyunFilePath,zipFile,true);
|
|
|
+ //保存数据库记录
|
|
|
+ examFileService.saveExamFile(new ExamFile(computerTestPaper,extractConfig,zipUpyunFilePath,ExamFileType.COMPUTERTEST_PACKAGE,ZIP_SUFFIX),accessUser);
|
|
|
+ //删除本地生成的文件
|
|
|
+ zipFile.delete();
|
|
|
+ FileUtils.deleteQuietly(dirFile);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 将computerTestPaper对象生成JSON文件存放在jsonDirectoryPath中
|
|
|
+ * @param extractConfig
|
|
|
+ * @param computerTestPaper
|
|
|
+ * @param jsonDirectoryPath
|
|
|
+ */
|
|
|
+ private void makeComputerTestPaperToJsonFile(ExtractConfig extractConfig,ComputerTestPaper computerTestPaper,String jsonDirectoryPath){
|
|
|
+ //创建新的JSON文件
|
|
|
+ File file = new File(jsonDirectoryPath+File.separator+extractConfig.getCourseCode()+".json");
|
|
|
+ //将对象转成 json对象
|
|
|
+ Gson gson = new Gson();
|
|
|
+ String strJSON = gson.toJson(computerTestPaper);
|
|
|
+ //生成文件流写入JSON文件
|
|
|
+ FileOutputStream outputStream;
|
|
|
+ try {
|
|
|
+ outputStream = new FileOutputStream(file);
|
|
|
+ byte b[] = strJSON.getBytes();
|
|
|
+ outputStream.write(b);
|
|
|
+ outputStream.close();
|
|
|
+ } catch (FileNotFoundException e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ } catch (IOException e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 下载题目音频文件
|
|
|
+ * @param computerTestPaper
|
|
|
+ */
|
|
|
+ private void downloadQuestionAudio(ComputerTestPaper computerTestPaper,String jsonDirectoryPath,String examId){
|
|
|
+ List<ComputerTestPaperDetail> details = computerTestPaper.getDetails();
|
|
|
+ for(ComputerTestPaperDetail detail:details){
|
|
|
+ List<ComputerTestQuestion> questions = detail.getQuestions();
|
|
|
+ for(ComputerTestQuestion computerTestQuestion:questions){
|
|
|
+ getBodyAndOptionAudioFile(computerTestQuestion,computerTestQuestion.getBody(),jsonDirectoryPath,computerTestPaper,examId);
|
|
|
+ List<ComputerTestOption> options = computerTestQuestion.getOptions();
|
|
|
+ for(ComputerTestOption option:options){
|
|
|
+ getBodyAndOptionAudioFile(computerTestQuestion,option.getBody(),jsonDirectoryPath,computerTestPaper,examId);
|
|
|
+ }
|
|
|
+ //子题音频处理
|
|
|
+ //List<ComputerTestQuestion> subQuestions = question.getSubQuestions();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void getBodyAndOptionAudioFile(ComputerTestQuestion computerTestQuestion,Sections bodySections,String jsonDirectoryPath,ComputerTestPaper computerTestPaper,String examId){
|
|
|
+ List<Section> sectionList = bodySections.getSections();
|
|
|
+ for(Section section:sectionList){
|
|
|
+ List<Block> blocks = section.getBlocks();
|
|
|
+ for(Block block:blocks){
|
|
|
+ if("audio".equals(block.getType())){
|
|
|
+ computerTestPaper.setHasVideo(1);
|
|
|
+ PaperDetailUnit paperDetailUnit = paperDetailUnitRepo.findById(computerTestQuestion.getId());
|
|
|
+ QuestionAudio audio = questionAudioService.findAudioById(block.getValue());
|
|
|
+ block.setValue(block.getValue()+"."+audio.getFileSuffixes());
|
|
|
+ if(audio!=null){
|
|
|
+ AudioTimeConfig audioTime = new AudioTimeConfig();
|
|
|
+ audioTime.setCourseCode(computerTestPaper.getCourseCode());
|
|
|
+ audioTime.setExamId(examId);
|
|
|
+ audioTime.setGroupCode(computerTestPaper.getGroupCode());
|
|
|
+ audioTime.setPaperDetailUnit(paperDetailUnit);
|
|
|
+ AudioTimeConfig audioTimeConfig = audioTimeConfigRepo.findOne(Example.of(audioTime));
|
|
|
+ if(audioTimeConfig!=null){
|
|
|
+ block.setPlayTime(audioTimeConfig.getPlayTime());
|
|
|
+ }
|
|
|
+ FileDisposeUtil.saveUrlAs(downloadUrl+audio.getFileUrl(),jsonDirectoryPath+File.separator+block.getValue());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 生成试卷或答案Word,上传至又拍云
|
|
|
+ * @param orgName
|
|
|
+ * @param dataMap
|
|
|
+ * @param extractConfig
|
|
|
+ * @param paperId
|
|
|
+ * @param accessUser
|
|
|
+ */
|
|
|
+ protected void uploadPaperOrAnswerFile(PaperExp paperExp,ExtractConfig extractConfig,AccessUser accessUser,String currNum,Template template,ExamFileType examFileType){
|
|
|
+ String paperfileName = currNum+examFileType.name()+DOCX_SUFFIX;
|
|
|
+ try {
|
|
|
+ DocxProcessUtil.exportWord(paperExp,paperfileName,template);
|
|
|
+ DocxProcessUtil.processImage(paperfileName,getPkgList(paperExp.getId()));
|
|
|
+ File file = new File(TEMP_FILE_EXP+paperfileName);
|
|
|
+ String paperFilePath = uploadUrl+extractConfig.getOrgId()+"/"+paperfileName;
|
|
|
+ UpYun upyun = new UpYun(bucketName,userName,password);
|
|
|
+ upyun.writeFile(paperFilePath,file,true);
|
|
|
+ examFileService.saveExamFile(new ExamFile(paperExp.getId(),extractConfig,paperFilePath,examFileType,DOCX_SUFFIX),accessUser);
|
|
|
+ file.delete();
|
|
|
+ } catch (Exception e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 生成试卷结构,上传至又拍云
|
|
|
+ */
|
|
|
+ protected void uploadPaperStructure(PaperExp paperExp,ExtractConfig extractConfig,AccessUser accessUser,String currNum,List<QuestionTypeNum> questionTypeNums) {
|
|
|
+ exportObjectiveQuestionStructures(paperExp,extractConfig,accessUser,currNum,questionTypeNums);
|
|
|
+ exportSubjectiveQuestionStructures(paperExp,extractConfig,accessUser,currNum);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获得客观题导出结构,并上传至又拍云
|
|
|
+ * @param paperExp
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ protected void exportObjectiveQuestionStructures(PaperExp paperExp,ExtractConfig extractConfig,AccessUser accessUser,String currNum,List<QuestionTypeNum> questionTypeNums){
|
|
|
+ String objectiveFilename = currNum+ExamFileType.PAPER_STRUCTURE_OBJECTIVE.name()+EXCEL_SUFFIX;
|
|
|
+ //得到试卷中的客观大题
|
|
|
+ List<PaperDetailExp> objectiveDetails = getAllObjectiveDetails(paperExp);
|
|
|
+ //根据试卷结构导出设置中的数量补齐客观题
|
|
|
+ List<PaperDetailExp> paperDetailExps = fillObjectiveQuestions(objectiveDetails,questionTypeNums);
|
|
|
+ List<ObjectiveQuestionStructure> objectiveQuestionStructureList = new ArrayList<ObjectiveQuestionStructure>();
|
|
|
+ for(PaperDetailExp paperDetailExp:paperDetailExps){
|
|
|
+ for(PaperDetailUnitExp unit:paperDetailExp.getPaperDetailUnits()){
|
|
|
+ if(unit.getQuestionType() != QuesStructType.NESTED_ANSWER_QUESTION){
|
|
|
+ objectiveQuestionStructureList.add(new ObjectiveQuestionStructure(paperExp,paperDetailExp,unit));
|
|
|
+ }else{
|
|
|
+ List<Question> subQuestions = unit.getQuestion().getSubQuestions();
|
|
|
+ for(Question question:subQuestions){
|
|
|
+ objectiveQuestionStructureList.add(new ObjectiveQuestionStructure(paperExp,paperDetailExp,question));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ ExcelWriter objectiveExcelExporter = new ExcelWriter(ObjectiveQuestionStructure.class);
|
|
|
+ try {
|
|
|
+ File file = new File(TEMP_FILE_EXP+objectiveFilename);
|
|
|
+ FileOutputStream out = new FileOutputStream(file);
|
|
|
+ objectiveExcelExporter.write(objectiveFilename,objectiveQuestionStructureList,out);
|
|
|
+ String objectiveFilePath = uploadUrl+extractConfig.getOrgId()+"/"+objectiveFilename;
|
|
|
+ UpYun upyun = new UpYun(bucketName,userName,password);
|
|
|
+ upyun.writeFile(objectiveFilePath,file,true);
|
|
|
+ examFileService.saveExamFile(new ExamFile(paperExp.getId(),extractConfig,objectiveFilePath,ExamFileType.PAPER_STRUCTURE_OBJECTIVE,EXCEL_SUFFIX),accessUser);
|
|
|
+ file.delete();
|
|
|
+ } catch (FileNotFoundException e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ } catch (IOException e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获得主观题导出结构,并上传至又拍云
|
|
|
+ * @param paperExp
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ protected void exportSubjectiveQuestionStructures(PaperExp paperExp,ExtractConfig extractConfig,AccessUser accessUser,String currNum){
|
|
|
+ String subjectiveFileName = currNum+ExamFileType.PAPER_STRUCTURE_SUBJECTIVE.name()+EXCEL_SUFFIX;
|
|
|
+ List<PaperDetailExp> subjectiveDetails = getAllSubjectiveDetails(paperExp);
|
|
|
+ List<SubjectiveQuestionStructure> subjectiveQuestionStructureList = new ArrayList<SubjectiveQuestionStructure>();
|
|
|
+ for(PaperDetailExp paperDetailExp:subjectiveDetails){
|
|
|
+ for(PaperDetailUnitExp unit:paperDetailExp.getPaperDetailUnits()){
|
|
|
+ subjectiveQuestionStructureList.add(new SubjectiveQuestionStructure(paperExp,paperDetailExp,unit));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ ExcelWriter subjectiveExcelExporter = new ExcelWriter(SubjectiveQuestionStructure.class);
|
|
|
+ try {
|
|
|
+ File file = new File(TEMP_FILE_EXP+subjectiveFileName);
|
|
|
+ FileOutputStream out = new FileOutputStream(file);
|
|
|
+ subjectiveExcelExporter.write(subjectiveFileName,subjectiveQuestionStructureList,out);
|
|
|
+ String subjectiveFilePath = uploadUrl+extractConfig.getOrgId()+"/"+subjectiveFileName;
|
|
|
+ UpYun upyun = new UpYun(bucketName,userName,password);
|
|
|
+ upyun.writeFile(subjectiveFilePath,file,true);
|
|
|
+ examFileService.saveExamFile(new ExamFile(paperExp.getId(),extractConfig,subjectiveFilePath,ExamFileType.PAPER_STRUCTURE_SUBJECTIVE,EXCEL_SUFFIX),accessUser);
|
|
|
+ file.delete();
|
|
|
+ } catch (FileNotFoundException e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ } catch (IOException e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 根据试卷结构导出设置中的数量补齐客观题
|
|
|
+ * @param objectiveDetails
|
|
|
+ * @param questionTypeNums
|
|
|
+ */
|
|
|
+ public List<PaperDetailExp> fillObjectiveQuestions(List<PaperDetailExp> objectiveDetails,List<QuestionTypeNum> questionTypeNums) {
|
|
|
+ //1.得到所有客观题的类型
|
|
|
+ Set<QuesStructType> types = new HashSet<QuesStructType>();
|
|
|
+ for(PaperDetailExp paperDetailExp:objectiveDetails){
|
|
|
+ List<PaperDetailUnitExp> paperDetailUnits = paperDetailExp.getPaperDetailUnits();
|
|
|
+ types.add(paperDetailUnits.get(0).getQuestionType());
|
|
|
+ }
|
|
|
+ List<PaperDetailExp> paperDetailExps = new ArrayList<PaperDetailExp>();
|
|
|
+ //如果没有单选
|
|
|
+ if(!types.contains(QuesStructType.SINGLE_ANSWER_QUESTION)){
|
|
|
+ buildObjectiveQuestion(paperDetailExps,questionTypeNums,QuesStructType.SINGLE_ANSWER_QUESTION);
|
|
|
+ }else{
|
|
|
+ addObjectiveQuestion(paperDetailExps,objectiveDetails, questionTypeNums, QuesStructType.SINGLE_ANSWER_QUESTION);
|
|
|
+ }
|
|
|
+ //如果没有多选
|
|
|
+ if(!types.contains(QuesStructType.MULTIPLE_ANSWER_QUESTION)){
|
|
|
+ buildObjectiveQuestion(paperDetailExps,questionTypeNums,QuesStructType.MULTIPLE_ANSWER_QUESTION);
|
|
|
+ }else{
|
|
|
+ addObjectiveQuestion(paperDetailExps, objectiveDetails, questionTypeNums, QuesStructType.MULTIPLE_ANSWER_QUESTION);
|
|
|
+ }
|
|
|
+ //如果没有判断
|
|
|
+ if(!types.contains(QuesStructType.BOOL_ANSWER_QUESTION)){
|
|
|
+ buildObjectiveQuestion(paperDetailExps,questionTypeNums,QuesStructType.BOOL_ANSWER_QUESTION);
|
|
|
+ }else{
|
|
|
+ addObjectiveQuestion(paperDetailExps, objectiveDetails, questionTypeNums, QuesStructType.BOOL_ANSWER_QUESTION);
|
|
|
+ }
|
|
|
+ return paperDetailExps;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 根据数量和类型构建客观题
|
|
|
+ * @param questionTypeNums
|
|
|
+ * @param quesStructType
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ private void buildObjectiveQuestion(List<PaperDetailExp> paperDetailExps,List<QuestionTypeNum> questionTypeNums,QuesStructType quesStructType){
|
|
|
+ //1.得到需要的题量
|
|
|
+ int quantity = getQuantity(questionTypeNums,quesStructType);
|
|
|
+ //2.构建题目
|
|
|
+ PaperDetailExp paperDetailExp = new PaperDetailExp();
|
|
|
+ List<PaperDetailUnitExp> paperDetailUnits = new ArrayList<PaperDetailUnitExp>();
|
|
|
+ for(int i = 0;i<quantity;i++){
|
|
|
+ paperDetailUnits.add(new PaperDetailUnitExp(quesStructType,i+1));
|
|
|
+ }
|
|
|
+ paperDetailExp.setPaperDetailUnits(paperDetailUnits);
|
|
|
+ paperDetailExp.setNumber(Integer.parseInt(quesStructType.getId()+""));
|
|
|
+ paperDetailExps.add(paperDetailExp);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 补齐需要的客观题
|
|
|
+ * @param objectiveDetails
|
|
|
+ * @param questionTypeNums
|
|
|
+ */
|
|
|
+ private void addObjectiveQuestion(List<PaperDetailExp> paperDetailExps,List<PaperDetailExp> objectiveDetails,List<QuestionTypeNum> questionTypeNums,QuesStructType quesStructType){
|
|
|
+ //得到当前题量
|
|
|
+ int currentSize = 0;
|
|
|
+ for(PaperDetailExp paperDetailExp:objectiveDetails){
|
|
|
+ List<PaperDetailUnitExp> paperDetailUnits = paperDetailExp.getPaperDetailUnits();
|
|
|
+ if(paperDetailUnits.get(0).getQuestionType() == quesStructType){
|
|
|
+ paperDetailExps.add(paperDetailExp);
|
|
|
+ for(PaperDetailUnitExp paperDetailUnitExp:paperDetailUnits){
|
|
|
+ if(paperDetailUnitExp.getQuestionType() != QuesStructType.NESTED_ANSWER_QUESTION){
|
|
|
+ currentSize += 1;
|
|
|
+ }else{
|
|
|
+ currentSize += paperDetailUnitExp.getQuestion().getSubQuestions().size();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ //计算差额、补齐试题
|
|
|
+ int quantity = getQuantity(questionTypeNums,quesStructType)-currentSize;
|
|
|
+ PaperDetailExp paperDetailExp = new PaperDetailExp();
|
|
|
+ List<PaperDetailUnitExp> paperDetailUnits = new ArrayList<PaperDetailUnitExp>();
|
|
|
+ for(int i = 0;i<quantity;i++){
|
|
|
+ int number = currentSize+(i+1);
|
|
|
+ paperDetailUnits.add(new PaperDetailUnitExp(quesStructType,number));
|
|
|
+ }
|
|
|
+ paperDetailExp.setPaperDetailUnits(paperDetailUnits);
|
|
|
+ //设置大题题号
|
|
|
+ paperDetailExp.setNumber(Integer.parseInt(quesStructType.getId()+""));
|
|
|
+ paperDetailExps.add(paperDetailExp);
|
|
|
+ }
|
|
|
+
|
|
|
+ //根据类型得到需要的题量
|
|
|
+ private Integer getQuantity(List<QuestionTypeNum> questionTypeNums,QuesStructType quesStructType){
|
|
|
+ int quantity = 0;
|
|
|
+ for(QuestionTypeNum typeNum:questionTypeNums){
|
|
|
+ if(typeNum.getQuestionType() == quesStructType){
|
|
|
+ quantity = typeNum.getQuantity();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return quantity;
|
|
|
+ }
|
|
|
+ /**
|
|
|
+ * 得到试卷中所有客观大题
|
|
|
+ * 与试题类型枚举:QuesStructType中的ID对应
|
|
|
+ * @param paperExp
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ protected List<PaperDetailExp> getAllObjectiveDetails(PaperExp paperExp){
|
|
|
+ List<PaperDetailExp> objectiveDetails = new ArrayList<PaperDetailExp>();
|
|
|
+ for(PaperDetailExp paperDetailExp:paperExp.getPaperDetails()){
|
|
|
+ if(paperDetailExp.getSortNumber()==1L
|
|
|
+ ||paperDetailExp.getSortNumber()==2L
|
|
|
+ ||paperDetailExp.getSortNumber()==3L){
|
|
|
+ objectiveDetails.add(paperDetailExp);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return objectiveDetails;
|
|
|
+ }
|
|
|
+ /**
|
|
|
+ * 得到所有主观大题
|
|
|
+ * 与试题类型枚举:QuesStructType中的ID对应
|
|
|
+ * @param paperExp
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ protected List<PaperDetailExp> getAllSubjectiveDetails(PaperExp paperExp){
|
|
|
+ List<PaperDetailExp> subjectiveDetails = new ArrayList<PaperDetailExp>();
|
|
|
+ for(PaperDetailExp paperDetailExp:paperExp.getPaperDetails()){
|
|
|
+ if(paperDetailExp.getSortNumber()==4L
|
|
|
+ ||paperDetailExp.getSortNumber()==5L
|
|
|
+ ||paperDetailExp.getSortNumber()==6L){
|
|
|
+ subjectiveDetails.add(paperDetailExp);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return subjectiveDetails;
|
|
|
+ }
|
|
|
+ /**
|
|
|
+ * 检查客观题数量是否小于试卷结构导出设置的数量
|
|
|
+ * @param paperExp
|
|
|
+ * @param objectiveDetails
|
|
|
+ * @param questionTypeNums
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ protected void checkObjectiveDetailsNum(PaperExp paperExp,List<QuestionTypeNum> questionTypeNums) {
|
|
|
+ List<PaperDetailExp> objectiveDetails = getAllObjectiveDetails(paperExp);
|
|
|
+ for(QuestionTypeNum typeNum:questionTypeNums){
|
|
|
+ int currentSize = 0;
|
|
|
+ for(PaperDetailExp paperDetailExp:objectiveDetails){
|
|
|
+ List<PaperDetailUnitExp> paperDetailUnits = paperDetailExp.getPaperDetailUnits();
|
|
|
+ if(paperDetailUnits.get(0).getQuestionType() == typeNum.getQuestionType());{
|
|
|
+ currentSize += paperDetailUnits.size();
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if(currentSize>typeNum.getQuantity()){
|
|
|
+ throw new RuntimeException("课程最大题量超出设定范围,请核实后重新设置导出规则!");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ /**
|
|
|
+ * 获取当前试卷下所有试题WordPkg
|
|
|
+ * @param id
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ protected List<WordprocessingMLPackage> getPkgList(String id){
|
|
|
+ Paper paper = paperRepo.findOne(id);
|
|
|
+ List<WordprocessingMLPackage> wordMLPackages = paperDetailUnitRepo.findByPaperOrderByNumber(paper)
|
|
|
+ .stream().map(PaperDetailUnit::getQuestion).collect(Collectors.toList())
|
|
|
+ .stream().map(Question::getPkgObj).collect(Collectors.toList());
|
|
|
+ return wordMLPackages;
|
|
|
+ }
|
|
|
+
|
|
|
+}
|
|
|
+
|