|
@@ -1,1126 +0,0 @@
|
|
-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.math.BigDecimal;
|
|
|
|
-import java.util.ArrayList;
|
|
|
|
-import java.util.Collections;
|
|
|
|
-import java.util.Comparator;
|
|
|
|
-import java.util.HashMap;
|
|
|
|
-import java.util.HashSet;
|
|
|
|
-import java.util.List;
|
|
|
|
-import java.util.Map;
|
|
|
|
-import java.util.Set;
|
|
|
|
-import java.util.regex.Matcher;
|
|
|
|
-import java.util.regex.Pattern;
|
|
|
|
-import java.util.stream.Collectors;
|
|
|
|
-
|
|
|
|
-import javax.servlet.http.HttpServletResponse;
|
|
|
|
-import javax.xml.bind.JAXBElement;
|
|
|
|
-
|
|
|
|
-import main.java.com.UpYun;
|
|
|
|
-
|
|
|
|
-import org.apache.commons.io.FileUtils;
|
|
|
|
-import org.apache.commons.lang3.StringUtils;
|
|
|
|
-import org.docx4j.XmlUtils;
|
|
|
|
-import org.docx4j.jaxb.Context;
|
|
|
|
-import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
|
|
|
|
-import org.docx4j.wml.Body;
|
|
|
|
-import org.docx4j.wml.P;
|
|
|
|
-import org.docx4j.wml.R;
|
|
|
|
-import org.docx4j.wml.Text;
|
|
|
|
-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.core.enums.CourseLevel;
|
|
|
|
-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.PaperExpDto;
|
|
|
|
-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.ExamPaper;
|
|
|
|
-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.PaperDetail;
|
|
|
|
-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.QuesOption;
|
|
|
|
-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.BeanCopierUtil;
|
|
|
|
-import com.qmth.cqb.utils.CommonUtils;
|
|
|
|
-import com.qmth.cqb.utils.FileDisposeUtil;
|
|
|
|
-import com.qmth.cqb.utils.enums.ExamFileType;
|
|
|
|
-import com.qmth.cqb.utils.exception.PaperException;
|
|
|
|
-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
|
|
|
|
- PaperRepo paperRepo;
|
|
|
|
-
|
|
|
|
- @Autowired
|
|
|
|
- PaperService paperService;
|
|
|
|
-
|
|
|
|
- @Autowired
|
|
|
|
- PaperDetailRepo paperDetailRepo;
|
|
|
|
-
|
|
|
|
- @Autowired
|
|
|
|
- PaperDetailUnitRepo paperDetailUnitRepo;
|
|
|
|
-
|
|
|
|
- @Autowired
|
|
|
|
- ExamFileService examFileService;
|
|
|
|
-
|
|
|
|
- @Autowired
|
|
|
|
- private PaperDetailService paperDetailService;
|
|
|
|
-
|
|
|
|
- @Autowired
|
|
|
|
- private QuestionAudioService questionAudioService;
|
|
|
|
-
|
|
|
|
- @Autowired
|
|
|
|
- QuesRepo quesRepo;
|
|
|
|
-
|
|
|
|
- @Autowired
|
|
|
|
- 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;
|
|
|
|
-
|
|
|
|
- @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, "/");
|
|
|
|
-
|
|
|
|
- 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);
|
|
|
|
- } catch (Exception e) {
|
|
|
|
- e.printStackTrace();
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * 下载试卷相关文件
|
|
|
|
- * @param id
|
|
|
|
- * @param response
|
|
|
|
- * @throws Exception
|
|
|
|
- */
|
|
|
|
- public abstract void downloadPaper(String paperId, HttpServletResponse response)throws Exception;
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * 上传试卷相关文件
|
|
|
|
- * @param orgName
|
|
|
|
- * @param examName
|
|
|
|
- * @param paperId
|
|
|
|
- * @throws Exception
|
|
|
|
- */
|
|
|
|
- public abstract void uploadFile(ExtractConfig extractConfig,String paperId,ExportStructure exportStructure,AccessUser accessUser) throws Exception;
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * 公共方法
|
|
|
|
- * 初始化导出试卷DTO
|
|
|
|
- * @param id
|
|
|
|
- * @return
|
|
|
|
- */
|
|
|
|
- public PaperExp initExportPaper(String paperId) throws Exception {
|
|
|
|
- Paper paper = paperRepo.findOne(paperId);
|
|
|
|
- paperService.formatPaper(paper, null);
|
|
|
|
- if (paper == null) {
|
|
|
|
- throw new PaperException("该试卷不存在");
|
|
|
|
- }
|
|
|
|
- // 创建paperDto
|
|
|
|
- PaperExp paperExp = BeanCopierUtil.copyProperties(paper, PaperExp.class);
|
|
|
|
- paperExp.setCourseLevel(paper.getLevel()==null?CourseLevel.ALL.getName():paper.getLevel().getName());
|
|
|
|
- List<PaperDetailExp> objectiveDetails = new ArrayList<PaperDetailExp>();// 客观题
|
|
|
|
- List<PaperDetailExp> subjectiveDetails = new ArrayList<PaperDetailExp>();// 主观题
|
|
|
|
- double objectiveScore = 0;
|
|
|
|
- double subjectiveScore = 0;
|
|
|
|
- paperExp.setTitle(CommonUtils.PAPER_TITLE);
|
|
|
|
- paperExp.setSubTitle(CommonUtils.PAPER_SUB_TITLE);
|
|
|
|
- // 获取大题
|
|
|
|
- List<PaperDetail> paperDetails = paperDetailRepo.findByPaperOrderByNumber(paper);
|
|
|
|
- int objectNumber = 1;// 客观题大题序号
|
|
|
|
- int objetcUnitSum = 0;
|
|
|
|
- for (int i = 0; i < paperDetails.size(); i++) {
|
|
|
|
- PaperDetailExp paperDetailExp = BeanCopierUtil.copyProperties(paperDetails.get(i), PaperDetailExp.class);
|
|
|
|
- List<PaperDetailUnit> paperDetailUnits = paperDetailUnitRepo.findByPaperDetailOrderByNumber(paperDetails.get(i));
|
|
|
|
- // 把大题分类 :客观题和主观题
|
|
|
|
- List<PaperDetailUnitExp> paperDetailUnitExps = BeanCopierUtil.copyPropertiesOfList(paperDetailUnits,PaperDetailUnitExp.class);
|
|
|
|
- // 选择题,套题下选择题 选项顺序重新排列
|
|
|
|
- paperService.reorderChoicequestionOption(paperDetailUnitExps);
|
|
|
|
- paperDetailExp.setPaperDetailUnits(paperDetailUnitExps);
|
|
|
|
- boolean isSubjective = false;// 判断主观题和客观题
|
|
|
|
- if (paperDetailUnits.get(0).getQuestionType() == QuesStructType.NESTED_ANSWER_QUESTION) {
|
|
|
|
- for (Question ques : paperDetailUnits.get(0).getQuestion().getSubQuestions()) {
|
|
|
|
- if (ques.getQuestionType() == QuesStructType.TEXT_ANSWER_QUESTION) {
|
|
|
|
- isSubjective = true;
|
|
|
|
- break;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- } else if (paperDetailUnits.get(0).getQuestionType() == QuesStructType.TEXT_ANSWER_QUESTION
|
|
|
|
- ||paperDetailUnits.get(0).getQuestionType() == QuesStructType.FILL_BLANK_QUESTION) {
|
|
|
|
- isSubjective = true;
|
|
|
|
- }
|
|
|
|
- if (isSubjective) {
|
|
|
|
- subjectiveDetails.add(paperDetailExp);
|
|
|
|
- subjectiveScore += paperDetailExp.getScore();
|
|
|
|
- }else{
|
|
|
|
- objectiveDetails.add(paperDetailExp);
|
|
|
|
- paperDetailExp.setNumber(objectNumber);
|
|
|
|
- paperDetailExp.setCnNum(CommonUtils.toCHNum(objectNumber));
|
|
|
|
- objectiveScore += paperDetailExp.getScore();
|
|
|
|
- objetcUnitSum += paperDetailExp.getUnitCount();
|
|
|
|
- objectNumber++;
|
|
|
|
- }
|
|
|
|
- setExpTitle(paperDetailExp);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- paperExp.setObjectiveDetails(objectiveDetails);
|
|
|
|
- paperExp.setSubjectiveDetails(subjectiveDetails);
|
|
|
|
- paperExp.setObjectiveScore(objectiveScore);
|
|
|
|
- paperExp.setSubjectiveScore(subjectiveScore);
|
|
|
|
- if (objectiveDetails.size() > 0) {
|
|
|
|
- setUnitExpNumber(objectiveDetails, 0);
|
|
|
|
- appendScoreToQuestionBody(objectiveDetails);
|
|
|
|
- }
|
|
|
|
- if (subjectiveDetails.size() > 0) {
|
|
|
|
- for (PaperDetailExp subDetail : subjectiveDetails) {
|
|
|
|
- subDetail.setNumber(objectNumber);
|
|
|
|
- subDetail.setCnNum(CommonUtils.toCHNum(objectNumber));
|
|
|
|
- objectNumber++;
|
|
|
|
- }
|
|
|
|
- setUnitExpNumber(subjectiveDetails, objetcUnitSum);
|
|
|
|
- appendScoreToQuestionBody(subjectiveDetails);
|
|
|
|
- }
|
|
|
|
- return paperExp;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
-
|
|
|
|
- public void setExpTitle(PaperDetailExp paperDetailExp) {
|
|
|
|
- String title = "";
|
|
|
|
- String totalScore = BigDecimal.valueOf(paperDetailExp.getScore()).stripTrailingZeros().toPlainString();
|
|
|
|
- QuesStructType type = paperDetailExp.getPaperDetailUnits().get(0).getQuestionType();
|
|
|
|
- String questionScore = checkPaperDetailUnitScore(paperDetailExp);
|
|
|
|
- String scoreString = questionScore==null?"":"每小题"+questionScore+"分";
|
|
|
|
- if (type == QuesStructType.SINGLE_ANSWER_QUESTION) {
|
|
|
|
- paperDetailExp.setName("单项选择题");
|
|
|
|
- title = "(本大题共" + paperDetailExp.getUnitCount() + "小题,"
|
|
|
|
- + scoreString + "共" + totalScore + "分)。"
|
|
|
|
- + "在每小题列出的四个备选中只有一个符合题目要求的,请将其选出并将“答题卡”的相应代码涂黑,错涂、多涂或未涂均无分";
|
|
|
|
- } else if (type == QuesStructType.BOOL_ANSWER_QUESTION) {
|
|
|
|
- paperDetailExp.setName("判断题");
|
|
|
|
- title = "(本大题共" + paperDetailExp.getUnitCount() + "小题,"+ scoreString + "共" + totalScore+ "分。正确的填涂A、错误填涂B。错涂、多涂或未涂均无分)";
|
|
|
|
- } else if (type == QuesStructType.FILL_BLANK_QUESTION) {
|
|
|
|
- paperDetailExp.setName("填空题");
|
|
|
|
- int blankNum = 0;
|
|
|
|
- for (PaperDetailUnitExp unit:paperDetailExp.getPaperDetailUnits()){
|
|
|
|
- String tempStr = unit.getQuestion().getQuesBody().replaceAll(FILL_BLANK_QUESTION_FLAG, "");
|
|
|
|
- int lenTimes = (unit.getQuestion().getQuesBody().length() - tempStr.length()) / FILL_BLANK_QUESTION_FLAG.length();// 出现的次数
|
|
|
|
- blankNum += lenTimes;
|
|
|
|
- }
|
|
|
|
- title = "(本大题共"+blankNum+"个空格,将每空答在答题卡 “1—" +blankNum+"”相应的序号上。"+"共"+totalScore + "分)";
|
|
|
|
- } else {
|
|
|
|
- title = "(本大题共"+paperDetailExp.getUnitCount()+"小题,"+scoreString+"共"+totalScore+"分)";
|
|
|
|
- }
|
|
|
|
- paperDetailExp.setTitle(title);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * 校验大题下的小题分数是不是一样
|
|
|
|
- *
|
|
|
|
- * @param paperDetailExp
|
|
|
|
- * @return 如果分数一样,返回分数
|
|
|
|
- * 如果分数不一样,返回 null
|
|
|
|
- */
|
|
|
|
- protected String checkPaperDetailUnitScore(PaperDetailExp paperDetailExp) {
|
|
|
|
- List<PaperDetailUnitExp> paperDetailUnitExps = paperDetailExp.getPaperDetailUnits();
|
|
|
|
- Set<Double> scoreSet = new HashSet<Double>();
|
|
|
|
- for (PaperDetailUnitExp unitExp : paperDetailUnitExps) {
|
|
|
|
- if(unitExp.getQuestionType()==QuesStructType.NESTED_ANSWER_QUESTION){
|
|
|
|
- List<Double> subScoreList = unitExp.getSubScoreList();
|
|
|
|
- for(Double score:subScoreList){
|
|
|
|
- scoreSet.add(score);
|
|
|
|
- }
|
|
|
|
- }else{
|
|
|
|
- scoreSet.add(unitExp.getScore());
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- if(scoreSet.size() == 1){
|
|
|
|
- return scoreSet.iterator().next()+"";
|
|
|
|
- }
|
|
|
|
- return null;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- protected void setUnitExpNumber(List<PaperDetailExp> paperDetails,int startIndxt) throws Exception {
|
|
|
|
- int subNum = startIndxt;
|
|
|
|
- for (PaperDetailExp paperDetail : paperDetails) {
|
|
|
|
- List<PaperDetailUnitExp> paperDetailUnitExpList = paperDetail.getPaperDetailUnits();
|
|
|
|
- //对大题下的小题进行排序
|
|
|
|
- Collections.sort(paperDetailUnitExpList);
|
|
|
|
- for (PaperDetailUnitExp paperDetailUnit:paperDetailUnitExpList) {
|
|
|
|
- List<QuesOption> optionList = paperDetailUnit.getQuestion().getQuesOptions();
|
|
|
|
- if (optionList != null && optionList.size() > 0) {
|
|
|
|
- int index = 0;
|
|
|
|
- for (QuesOption quesOption : optionList) {
|
|
|
|
- quesOption.setOptionBodyWord(setOptionNum(quesOption.getOptionBodyWord(),getOptionNum(index)));
|
|
|
|
- index++;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- List<Question> subQuesList = paperDetailUnit.getQuestion().getSubQuestions();
|
|
|
|
- Question question = paperDetailUnit.getQuestion();
|
|
|
|
- // 套题序号
|
|
|
|
- if (subQuesList != null && subQuesList.size() > 0) {
|
|
|
|
- question.setQuesBodyWord(replaceQuesBlank(question.getQuesBodyWord(),subNum + 1));
|
|
|
|
- for (Question subQues : subQuesList) {
|
|
|
|
- int curSubNum = ++subNum;
|
|
|
|
- subQues.setQuesBodyWord(setSubQuesNum(subQues.getQuesBodyWord(),curSubNum));
|
|
|
|
- subQues.setQuesAnswerWord(setSubQuesNum(subQues.getQuesAnswerWord(),curSubNum));
|
|
|
|
- subQues.setQuesBodyWord(replaceQuesBlank(subQues.getQuesBodyWord(),curSubNum));
|
|
|
|
- List<QuesOption> subOptionList = subQues.getQuesOptions();
|
|
|
|
- if (subOptionList != null && subOptionList.size() > 0) {
|
|
|
|
- int sub_index = 0;
|
|
|
|
- for (QuesOption quesOption : subOptionList) {
|
|
|
|
- quesOption.setOptionBodyWord(setOptionNum(quesOption.getOptionBodyWord(),getOptionNum(sub_index)));
|
|
|
|
- sub_index++;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- } else {
|
|
|
|
- int curSubNum = ++subNum;
|
|
|
|
- question.setQuesBodyWord(setSubQuesNum(question.getQuesBodyWord(), paperDetailUnit.getNumber()));
|
|
|
|
- question.setQuesAnswerWord(setSubQuesNum(question.getQuesAnswerWord(),paperDetailUnit.getNumber()));
|
|
|
|
- question.setQuesBodyWord(replaceQuesBlank(question.getQuesBodyWord(),paperDetailUnit.getNumber()));
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * 替换填空
|
|
|
|
- * 将###替换为下划线_______
|
|
|
|
- * @param wordMl
|
|
|
|
- * @param num
|
|
|
|
- * @return
|
|
|
|
- * @throws Exception
|
|
|
|
- */
|
|
|
|
- protected String replaceQuesBlank(String wordMl,int num) throws Exception {
|
|
|
|
- String tmpStr = DocxProcessUtil.BODY_HEADER + wordMl + DocxProcessUtil.BODY_TAIL;
|
|
|
|
- Body body = (Body)XmlUtils.unmarshalString(tmpStr,Context.jc,Body.class);
|
|
|
|
- List<Object> pList = body.getContent();
|
|
|
|
- int index = 0;
|
|
|
|
- int cur = 0;
|
|
|
|
- Map<Integer,String> curMap = new HashMap<Integer,String>();
|
|
|
|
- for(Object pObj:pList){
|
|
|
|
- if(pObj.getClass().equals(P.class)){
|
|
|
|
- List<Object> pContent = ((P)pObj).getContent();
|
|
|
|
- for(Object rObj:pContent){
|
|
|
|
- if(rObj.getClass().equals(R.class)){
|
|
|
|
- List<Object> rContent = ((R)rObj).getContent();
|
|
|
|
- for(Object tObj:rContent){
|
|
|
|
- if (tObj instanceof JAXBElement)
|
|
|
|
- tObj = ((JAXBElement<?>) tObj).getValue();
|
|
|
|
- if(tObj.getClass().equals(Text.class)){
|
|
|
|
- Text text = (Text)tObj;
|
|
|
|
- String str = text.getValue();
|
|
|
|
- str = str.replaceAll("###","______");
|
|
|
|
- text.setValue(str);
|
|
|
|
- if(str.matches("##\\d{1,}##")){
|
|
|
|
- int curNum = num + index;
|
|
|
|
- text.setValue("___"+(curNum)+"___");
|
|
|
|
- index++;
|
|
|
|
- }else if(str.startsWith("#") || str.equals("___")){
|
|
|
|
- curMap.put(cur,str);
|
|
|
|
- text.setValue("");
|
|
|
|
- }else if(str.matches("^\\d{1,}$")){
|
|
|
|
- String preStr = curMap.get(cur - 1);
|
|
|
|
- if(!StringUtils.isEmpty(preStr) && preStr.startsWith("#")){
|
|
|
|
- int curNum = num + index;
|
|
|
|
- text.setValue("___"+(curNum)+"___");
|
|
|
|
- index++;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- cur++;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- StringBuffer pWordMl = new StringBuffer();
|
|
|
|
- for(Object pObj:pList){
|
|
|
|
- if(pObj instanceof P){
|
|
|
|
- pWordMl.append(DocxProcessUtil.formatPWordMl(XmlUtils.marshaltoString(pObj)));
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- return pWordMl.toString();
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * 将数字1,2,3,4转化成A,B,C,D
|
|
|
|
- * @param number
|
|
|
|
- * @return
|
|
|
|
- */
|
|
|
|
- protected String getOptionNum(int number){
|
|
|
|
- char optionNum = (char)(65 + number);
|
|
|
|
- return String.valueOf(optionNum);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * 获取当前试卷下所有试题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;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * 设置题号
|
|
|
|
- * @param quesBodyWordMl
|
|
|
|
- * @param num
|
|
|
|
- * @return
|
|
|
|
- * @throws Exception
|
|
|
|
- */
|
|
|
|
- public String setSubQuesNum(String quesBodyWordMl,int num) throws Exception {
|
|
|
|
- String tmpStr = DocxProcessUtil.BODY_HEADER + quesBodyWordMl + DocxProcessUtil.BODY_TAIL;
|
|
|
|
- Body body = (Body)XmlUtils.unmarshalString(tmpStr,Context.jc,Body.class);
|
|
|
|
- List<Object> pList = body.getContent();
|
|
|
|
- int index = 0;
|
|
|
|
- for(Object pObj:pList){
|
|
|
|
- if(index > 0){
|
|
|
|
- break;
|
|
|
|
- }
|
|
|
|
- P p = (P) pObj;
|
|
|
|
- List<Object> pContent = p.getContent();
|
|
|
|
- R run = new R();
|
|
|
|
- Text text = new Text();
|
|
|
|
- text.setValue(num+". ");
|
|
|
|
- run.getContent().add(text);
|
|
|
|
- pContent.add(0,run);
|
|
|
|
- index++;
|
|
|
|
- }
|
|
|
|
- StringBuffer pWordMl = new StringBuffer();
|
|
|
|
- for(Object pObj:pList){
|
|
|
|
- if(pObj instanceof P){
|
|
|
|
- pWordMl.append(DocxProcessUtil.formatPWordMl(XmlUtils.marshaltoString(pObj)));
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- return pWordMl.toString();
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * 设置选项号
|
|
|
|
- * @param optionWordMl
|
|
|
|
- * @param num
|
|
|
|
- * @return
|
|
|
|
- * @throws Exception
|
|
|
|
- */
|
|
|
|
- public String setOptionNum(String optionWordMl,String num) throws Exception {
|
|
|
|
- String tmpStr = DocxProcessUtil.BODY_HEADER + optionWordMl + DocxProcessUtil.BODY_TAIL;
|
|
|
|
- Body body = (Body)XmlUtils.unmarshalString(tmpStr,Context.jc,Body.class);
|
|
|
|
- List<Object> pList = body.getContent();
|
|
|
|
- int index = 0;
|
|
|
|
- for(Object pObj:pList){
|
|
|
|
- if(index > 0){
|
|
|
|
- break;
|
|
|
|
- }
|
|
|
|
- P p = (P) pObj;
|
|
|
|
- List<Object> pContent = p.getContent();
|
|
|
|
- R run = new R();
|
|
|
|
- Text text = new Text();
|
|
|
|
- text.setValue(num+". ");
|
|
|
|
- run.getContent().add(text);
|
|
|
|
- pContent.add(0,run);
|
|
|
|
- index++;
|
|
|
|
- }
|
|
|
|
- StringBuffer pWordMl = new StringBuffer();
|
|
|
|
- for(Object pObj:pList){
|
|
|
|
- if(pObj instanceof P){
|
|
|
|
- pWordMl.append(DocxProcessUtil.formatPWordMl(XmlUtils.marshaltoString(pObj)));
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- return pWordMl.toString();
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * 当大题下小题分数不是全部一样时,在小题题干后面加上小题的分数
|
|
|
|
- * @param details
|
|
|
|
- * @throws Exception
|
|
|
|
- */
|
|
|
|
- protected void appendScoreToQuestionBody(List<PaperDetailExp> details) throws Exception{
|
|
|
|
- for(PaperDetailExp paperDetailExp:details){
|
|
|
|
- if(checkPaperDetailUnitScore(paperDetailExp)==null){
|
|
|
|
- for(PaperDetailUnitExp paperDetailUnit:paperDetailExp.getPaperDetailUnits()){
|
|
|
|
- Question question = paperDetailUnit.getQuestion();
|
|
|
|
- String questionBodyWord = appendScoreToQuestionBody(question.getQuesBodyWord(),paperDetailUnit.getScore());
|
|
|
|
- question.setQuesBodyWord(questionBodyWord);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * 在题干上设置分数
|
|
|
|
- * @throws Exception
|
|
|
|
- */
|
|
|
|
- protected String appendScoreToQuestionBody(String quesBodyWordMl,double score) throws Exception{
|
|
|
|
- String tmpStr = DocxProcessUtil.BODY_HEADER + quesBodyWordMl + DocxProcessUtil.BODY_TAIL;
|
|
|
|
- Body body = (Body)XmlUtils.unmarshalString(tmpStr,Context.jc,Body.class);
|
|
|
|
- List<Object> pList = body.getContent();
|
|
|
|
- int index = 0;
|
|
|
|
- for(Object pObj:pList){
|
|
|
|
- if(index < pList.size()-1){
|
|
|
|
- break;
|
|
|
|
- }
|
|
|
|
- P p = (P) pObj;
|
|
|
|
- List<Object> pContent = p.getContent();
|
|
|
|
- R run = new R();
|
|
|
|
- Text text = new Text();
|
|
|
|
- int scoreInt = (int)score;
|
|
|
|
- text.setValue("("+scoreInt+"分)");
|
|
|
|
- run.getContent().add(text);
|
|
|
|
- pContent.add(run);
|
|
|
|
- index++;
|
|
|
|
- }
|
|
|
|
- StringBuffer pWordMl = new StringBuffer();
|
|
|
|
- for(Object pObj:pList){
|
|
|
|
- if(pObj instanceof P){
|
|
|
|
- pWordMl.append(DocxProcessUtil.formatPWordMl(XmlUtils.marshaltoString(pObj)));
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- return pWordMl.toString();
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * 创建机考文件,并打包上传至又拍云
|
|
|
|
- * @param paperId
|
|
|
|
- * @param currNum
|
|
|
|
- * ObjectId("591ead1290994d57cd453464")
|
|
|
|
- * @throws IOException
|
|
|
|
- */
|
|
|
|
- protected void uploadComputerTestFile(ExtractConfig extractConfig,AccessUser accessUser) throws IOException{
|
|
|
|
- List<ComputerTestPaper> computerTestPaperList = 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());
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * 构建机考数据包实体类
|
|
|
|
- * @param extractConfig
|
|
|
|
- * @return
|
|
|
|
- */
|
|
|
|
- private List<ComputerTestPaper> buildComputerTestPapers(ExtractConfig extractConfig){
|
|
|
|
- List<ExamPaper> examPapers = extractConfig.getExamPaperList();
|
|
|
|
- List<ComputerTestPaper> computerTestPapers = new ArrayList<ComputerTestPaper>();
|
|
|
|
- //循环得到试卷
|
|
|
|
- for(ExamPaper examPaper:examPapers){
|
|
|
|
- Paper paper = examPaper.getPaper();
|
|
|
|
- //得到所有旧对象的大题对象
|
|
|
|
- List<PaperDetail> paperDetails = paperService.findPaperDetailsById(paper.getId());
|
|
|
|
- //通过 paper 对象 ,生成新的 ComputerTestPaper 对象
|
|
|
|
- ComputerTestPaper computerTestPaper = new ComputerTestPaper(paper,examPaper.getGroupCode());
|
|
|
|
- List<ComputerTestPaperDetail> details = new ArrayList<ComputerTestPaperDetail>();
|
|
|
|
- //遍历所有旧大题对象,得到小题对象的集合
|
|
|
|
- for(PaperDetail paperDetail:paperDetails){
|
|
|
|
- List<PaperDetailUnit> paperDetailUnits = paperDetailService.getUnitsByPaperDetailId(paperDetail.getId());
|
|
|
|
- ComputerTestPaperDetail computerTestPaperDetail = new ComputerTestPaperDetail(paperDetail);
|
|
|
|
- List<ComputerTestQuestion> questions = new ArrayList<ComputerTestQuestion>();
|
|
|
|
- //遍历所有的小题对象
|
|
|
|
- for(int i = 0;i<paperDetailUnits.size();i++){
|
|
|
|
- PaperDetailUnit paperDetailUnit = paperDetailUnits.get(i);
|
|
|
|
- //根据旧的小题对象,生成新的小题对象
|
|
|
|
- ComputerTestQuestion computerTestQuestion = new ComputerTestQuestion(paperDetailUnit);
|
|
|
|
- //设置小题题号
|
|
|
|
- computerTestQuestion.setNumber(i+1);
|
|
|
|
- //得到小题题干
|
|
|
|
- computerTestQuestion.setBody(getBody(paperDetailUnit.getQuestion()));
|
|
|
|
- //得到小题所有选项
|
|
|
|
- computerTestQuestion.setOptions(getOption(paperDetailUnit.getQuestion()));
|
|
|
|
- //查询小题中的 套题
|
|
|
|
- List<Question> subQuestionsList = paperDetailUnit.getQuestion().getSubQuestions();
|
|
|
|
- //判断这个小题中是否有套题
|
|
|
|
- if(subQuestionsList!=null&&subQuestionsList.size()>0){
|
|
|
|
- List<ComputerTestQuestion> subQuestions = new ArrayList<ComputerTestQuestion>();
|
|
|
|
- //遍历每个套题
|
|
|
|
- for(int j = 0;j<subQuestionsList.size();j++){
|
|
|
|
- Question subQuestion = subQuestionsList.get(j);
|
|
|
|
- ComputerTestQuestion subcomputerTestQuestion = new ComputerTestQuestion(subQuestion);
|
|
|
|
- //设置套题中小题题号
|
|
|
|
- subcomputerTestQuestion.setNumber(j+1);
|
|
|
|
- subcomputerTestQuestion.setBody(getBody(subQuestion));
|
|
|
|
- subcomputerTestQuestion.setOptions(getOption(subQuestion));
|
|
|
|
- subQuestions.add(subcomputerTestQuestion);
|
|
|
|
- }
|
|
|
|
- computerTestQuestion.setSubQuestions(subQuestions);
|
|
|
|
- }
|
|
|
|
- questions.add(computerTestQuestion);
|
|
|
|
- }
|
|
|
|
- computerTestPaperDetail.setQuestions(questions);
|
|
|
|
- //paperDetail中的题数(unitCount)可能不准确,这里以questions的实际size为准
|
|
|
|
- computerTestPaperDetail.setQuestionCount(questions.size());
|
|
|
|
- details.add(computerTestPaperDetail);
|
|
|
|
- }
|
|
|
|
- computerTestPaper.setDetails(details);
|
|
|
|
- computerTestPapers.add(computerTestPaper);
|
|
|
|
- }
|
|
|
|
- return computerTestPapers;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- private Sections getBody(Question question){
|
|
|
|
- Sections body = new Sections();
|
|
|
|
- List<Section> sections = new ArrayList<Section>();
|
|
|
|
- //得到小题题干
|
|
|
|
- String questionBodyString = question.getQuesBody();
|
|
|
|
- //得到小题题干行数
|
|
|
|
- String[] questionRowStrings = questionBodyString.split("</p>");
|
|
|
|
- for(int i = 0;i<questionRowStrings.length;i++){
|
|
|
|
- Section section = new Section();
|
|
|
|
- //将小题题干拆分为Block集合
|
|
|
|
- section.setBlocks(disposeQuestionBodyOrOption(questionRowStrings[i]));
|
|
|
|
- sections.add(section);
|
|
|
|
- }
|
|
|
|
- body.setSections(sections);
|
|
|
|
- return body;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- private List<ComputerTestOption> getOption(Question question){
|
|
|
|
- //得到小题选项
|
|
|
|
- List<QuesOption> quesOptions = question.getQuesOptions();
|
|
|
|
- List<ComputerTestOption> options = new ArrayList<ComputerTestOption>();
|
|
|
|
- //遍历小题选项
|
|
|
|
- if(quesOptions!=null&&quesOptions.size()>0){
|
|
|
|
- for(QuesOption quesOption: quesOptions){
|
|
|
|
- ComputerTestOption option = new ComputerTestOption();
|
|
|
|
- option.setNumber(new Integer(quesOption.getNumber()));
|
|
|
|
- option.setCorrect(quesOption.getIsCorrect()==1?true:false);
|
|
|
|
- Sections body = new Sections();
|
|
|
|
-
|
|
|
|
- List<Section> sections = new ArrayList<Section>();
|
|
|
|
- //得到小题选项
|
|
|
|
- String optionString = quesOption.getOptionBody();
|
|
|
|
- String[] optionStrings = optionString.split("</p>");
|
|
|
|
- for(int i = 0;i<optionStrings.length;i++){
|
|
|
|
- Section section = new Section();
|
|
|
|
- section.setBlocks(disposeQuestionBodyOrOption(optionStrings[i]));
|
|
|
|
- sections.add(section);
|
|
|
|
- }
|
|
|
|
- body.setSections(sections);
|
|
|
|
- option.setBody(body);
|
|
|
|
- options.add(option);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- return options;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- private List<Block> disposeQuestionBodyOrOption(String questionRow) {
|
|
|
|
- List<Block> blocks = new ArrayList<Block>();
|
|
|
|
- //去掉每行里面的<p>,<span>,</span>标签
|
|
|
|
- questionRow = questionRow.replaceAll("<p>", "")
|
|
|
|
- .replaceAll("</p>", "")
|
|
|
|
- .replaceAll("<span>", "")
|
|
|
|
- .replaceAll("</span>", "")
|
|
|
|
- .replaceAll("</a>", "");
|
|
|
|
- String[] questionRowStrings = questionRow.split("<|/>|>");
|
|
|
|
- for(int i = 0;i<questionRowStrings.length;i++){
|
|
|
|
- Block block = new Block();
|
|
|
|
- //判断是否有图片
|
|
|
|
- if(questionRowStrings[i].startsWith("img")){
|
|
|
|
- questionRowStrings[i] = "<"+questionRowStrings[i]+">";
|
|
|
|
- Map<String, Object> param = new HashMap<String, Object>();
|
|
|
|
- //需要继续做截取,取到Parma
|
|
|
|
- block.setType("image");
|
|
|
|
- //获取图片的路径
|
|
|
|
- List<String> strSrcList = getImg(questionRowStrings[i], "src");
|
|
|
|
- if(strSrcList.size()>0){
|
|
|
|
- String strSrc = strSrcList.get(0).replaceAll("src=\"", "").replaceAll("\"", "");
|
|
|
|
- block.setValue(strSrc);
|
|
|
|
- }
|
|
|
|
- //获取图片的高度
|
|
|
|
- List<String> strHeightList = getImg(questionRowStrings[i], "height");
|
|
|
|
- if(strHeightList.size()>0){
|
|
|
|
- String strHeight = strHeightList.get(0).replaceAll("height=\"", "").replaceAll("\"", "");
|
|
|
|
- param.put("height", strHeight);
|
|
|
|
- }
|
|
|
|
- //获取图片的宽度
|
|
|
|
- List<String> strWidthList = getImg(questionRowStrings[i], "width");
|
|
|
|
- if(strHeightList.size()>0){
|
|
|
|
- String strWidth = strWidthList.get(0).replaceAll("width=\"", "").replaceAll("\"", "");
|
|
|
|
- param.put("width", strWidth);
|
|
|
|
- }
|
|
|
|
- block.setParam(param);
|
|
|
|
- blocks.add(block);
|
|
|
|
- }else if(questionRowStrings[i].startsWith("a")
|
|
|
|
- &&questionRowStrings[i].contains("id")
|
|
|
|
- &&questionRowStrings[i].contains("name")){ //处理音频
|
|
|
|
- questionRowStrings[i] = "<"+questionRowStrings[i]+">";
|
|
|
|
- block.setType("audio");
|
|
|
|
- block.setValue(CommonUtils.getAttrValue(questionRowStrings[i],"id"));
|
|
|
|
- blocks.add(block);
|
|
|
|
- }else{
|
|
|
|
- block.setType("text");
|
|
|
|
- questionRowStrings[i] = questionRowStrings[i].replaceAll(" ","");
|
|
|
|
- block.setValue(questionRowStrings[i]);
|
|
|
|
- blocks.add(block);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- return blocks;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * 获取图片里面的路径,长度,宽度
|
|
|
|
- * @param s
|
|
|
|
- * @param str
|
|
|
|
- * @return
|
|
|
|
- */
|
|
|
|
- private List<String> getImg(String s,String str)
|
|
|
|
- {
|
|
|
|
- String regex;
|
|
|
|
- List<String> list = new ArrayList<String>();
|
|
|
|
- regex = str + "=\"(.*?)\"";
|
|
|
|
- Pattern pa = Pattern.compile(regex, Pattern.DOTALL);
|
|
|
|
- Matcher ma = pa.matcher(s);
|
|
|
|
- while (ma.find())
|
|
|
|
- {
|
|
|
|
- list.add(ma.group());
|
|
|
|
- }
|
|
|
|
- return list;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * 生成试卷或答案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 = paperExp.getObjectiveDetails();
|
|
|
|
- //根据试卷结构导出设置中的数量补齐客观题
|
|
|
|
- fillObjectiveQuestions(objectiveDetails,questionTypeNums);
|
|
|
|
- List<ObjectiveQuestionStructure> objectiveQuestionStructureList = new ArrayList<ObjectiveQuestionStructure>();
|
|
|
|
- for(PaperDetailExp paperDetailExp:objectiveDetails){
|
|
|
|
- for(PaperDetailUnitExp unit:paperDetailExp.getPaperDetailUnits()){
|
|
|
|
- objectiveQuestionStructureList.add(new ObjectiveQuestionStructure(paperExp,paperDetailExp,unit));
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- 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 objectiveDetails
|
|
|
|
- * @param questionTypeNums
|
|
|
|
- */
|
|
|
|
- public void fillObjectiveQuestions(List<PaperDetailExp> objectiveDetails,List<QuestionTypeNum> questionTypeNums) {
|
|
|
|
- List<QuesStructType> types = new ArrayList<QuesStructType>();
|
|
|
|
- for(PaperDetailExp paperDetailExp:objectiveDetails){
|
|
|
|
- List<PaperDetailUnitExp> paperDetailUnits = paperDetailExp.getPaperDetailUnits();
|
|
|
|
- types.add(paperDetailUnits.get(0).getQuestionType());
|
|
|
|
- }
|
|
|
|
- for(PaperDetailExp paperDetailExp:objectiveDetails){
|
|
|
|
- List<PaperDetailUnitExp> paperDetailUnits = paperDetailExp.getPaperDetailUnits();
|
|
|
|
- //1.将大题中的小题排序
|
|
|
|
- Collections.sort(paperDetailUnits);
|
|
|
|
- //2.将小题的number重新设置
|
|
|
|
- for(int i = 0;i<paperDetailUnits.size();i++){
|
|
|
|
- PaperDetailUnitExp paperDetailUnitExp = paperDetailUnits.get(i);
|
|
|
|
- paperDetailUnitExp.setNumber(i+1);
|
|
|
|
- }
|
|
|
|
- //3.根据试卷结构导出设置中的数量补齐客观题
|
|
|
|
- QuesStructType type = paperDetailUnits.get(0).getQuestionType();
|
|
|
|
- int unitSize = paperDetailUnits.size();//当前小题的数量
|
|
|
|
- for(QuestionTypeNum questionTypeNum:questionTypeNums){
|
|
|
|
- if(questionTypeNum.getQuantity()==null){
|
|
|
|
- continue;
|
|
|
|
- }
|
|
|
|
- if(type==questionTypeNum.getQuestionType()){
|
|
|
|
- int length = questionTypeNum.getQuantity()-unitSize;
|
|
|
|
- for(int i = 0;i<length;i++){
|
|
|
|
- PaperDetailUnitExp paperDetailUnitExp = new PaperDetailUnitExp();
|
|
|
|
- paperDetailUnitExp.setQuestionType(type);
|
|
|
|
- paperDetailUnitExp.setScore((double) 0);
|
|
|
|
- paperDetailUnitExp.setNumber(unitSize+(i+1));
|
|
|
|
- Question question = new Question();
|
|
|
|
- question.setQuesAnswer("#");
|
|
|
|
- paperDetailUnitExp.setQuestion(question);
|
|
|
|
- paperDetailUnits.add(paperDetailUnitExp);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- //添加试卷中没有的题型
|
|
|
|
- for(QuestionTypeNum questionTypeNum:questionTypeNums){
|
|
|
|
- if(!types.contains(questionTypeNum.getQuestionType())){
|
|
|
|
- PaperDetailExp paperDetailExp = new PaperDetailExp();
|
|
|
|
- paperDetailExp.setNumber(objectiveDetails.size()+1);
|
|
|
|
- List<PaperDetailUnitExp> paperDetailUnits = new ArrayList<PaperDetailUnitExp>();
|
|
|
|
- for(int i = 0;i<questionTypeNum.getQuantity();i++){
|
|
|
|
- PaperDetailUnitExp paperDetailUnitExp = new PaperDetailUnitExp();
|
|
|
|
- paperDetailUnitExp.setQuestionType(questionTypeNum.getQuestionType());
|
|
|
|
- paperDetailUnitExp.setScore((double) 0);
|
|
|
|
- paperDetailUnitExp.setNumber((i+1));
|
|
|
|
- Question question = new Question();
|
|
|
|
- question.setQuesAnswer("#");
|
|
|
|
- paperDetailUnitExp.setQuestion(question);
|
|
|
|
- paperDetailUnits.add(paperDetailUnitExp);
|
|
|
|
- }
|
|
|
|
- paperDetailExp.setPaperDetailUnits(paperDetailUnits);
|
|
|
|
- objectiveDetails.add(paperDetailExp);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * 检查客观题数量是否小于试卷结构导出设置的数量
|
|
|
|
- * @param paperExp
|
|
|
|
- * @param objectiveDetails
|
|
|
|
- * @param questionTypeNums
|
|
|
|
- * @return
|
|
|
|
- */
|
|
|
|
- protected void checkObjectiveDetailsNum(PaperExp paperExp,List<PaperDetailExp> objectiveDetails,List<QuestionTypeNum> questionTypeNums) {
|
|
|
|
- for(PaperDetailExp paperDetailExp:objectiveDetails){
|
|
|
|
- for(QuestionTypeNum typeNum:questionTypeNums){
|
|
|
|
- QuesStructType quesStructType = paperDetailExp.getPaperDetailUnits().get(0).getQuestionType();
|
|
|
|
- if(typeNum.getQuestionType()==quesStructType){
|
|
|
|
- if(paperDetailExp.getUnitCount()>typeNum.getQuantity()){
|
|
|
|
- throw new RuntimeException("课程最大题量超出设定范围,请核实后重新设置导出规则!");
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * 获得主观题导出结构,并上传至又拍云
|
|
|
|
- * @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 = paperExp.getSubjectiveDetails();
|
|
|
|
- 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 papers
|
|
|
|
- * @param zipFileName
|
|
|
|
- * @throws Exception
|
|
|
|
- */
|
|
|
|
- public void downloadPapers(List<Paper> papers,String zipFileName) throws Exception {
|
|
|
|
- for(int i=0;i<papers.size();i++){
|
|
|
|
- PaperExp paperExp = initExportPaper(papers.get(i).getId());
|
|
|
|
- if(paperExp!=null){
|
|
|
|
- String paperfileName = paperExp.getCourseNo()+"_"+ExamFileType.PAPER.getName()+DOCX_SUFFIX;
|
|
|
|
- File file = new File(TEMP_FILE_EXP+File.separator+zipFileName+File.separator+paperfileName);
|
|
|
|
- DocxProcessUtil.exportWordNew(paperExp, file,SXSF_TEMPLATE_PAPER);
|
|
|
|
- DocxProcessUtil.processImage(zipFileName+File.separator+paperfileName,getPkgList(papers.get(i).getId()));
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * 导出答案
|
|
|
|
- * @param papers
|
|
|
|
- * @param zipFileName
|
|
|
|
- * @throws Exception
|
|
|
|
- */
|
|
|
|
- public void downloadPaperAnswer(List<Paper> papers,String zipFileName) throws Exception {
|
|
|
|
- for(int i=0;i<papers.size();i++){
|
|
|
|
- PaperExp paperExp = initExportPaper(papers.get(i).getId());
|
|
|
|
- if(paperExp!=null){
|
|
|
|
- String answerFileName = paperExp.getCourseNo()+"_"+ExamFileType.ANSWER.getName()+DOCX_SUFFIX;
|
|
|
|
- File file = new File(TEMP_FILE_EXP+File.separator+zipFileName+File.separator+answerFileName);
|
|
|
|
- DocxProcessUtil.exportWordNew(paperExp,file,SXSF_TEMPLATE_ANSWER);
|
|
|
|
- DocxProcessUtil.processImage(zipFileName+File.separator+answerFileName,getPkgList(papers.get(i).getId()));
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
-}
|
|
|
|
-
|
|
|