package com.qxueyou.scc.exercise.service.impl;
|
|
import java.io.BufferedReader;
|
import java.io.File;
|
import java.io.FileInputStream;
|
import java.io.FileNotFoundException;
|
import java.io.FileReader;
|
import java.io.FileWriter;
|
import java.io.IOException;
|
import java.io.InputStream;
|
import java.math.BigInteger;
|
import java.util.ArrayList;
|
import java.util.List;
|
import java.util.Map;
|
|
import org.apache.commons.beanutils.BeanUtils;
|
import org.apache.commons.io.FileUtils;
|
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.lang3.StringUtils;
|
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.Logger;
|
import org.apache.poi.POIXMLDocument;
|
import org.apache.poi.POIXMLTextExtractor;
|
import org.apache.poi.hwpf.extractor.WordExtractor;
|
import org.apache.poi.openxml4j.opc.OPCPackage;
|
import org.apache.poi.xwpf.extractor.XWPFWordExtractor;
|
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
import org.springframework.stereotype.Service;
|
|
import com.qxueyou.scc.base.model.Result;
|
import com.qxueyou.scc.base.service.IFileUploadService;
|
import com.qxueyou.scc.base.service.impl.CommonAppService;
|
import com.qxueyou.scc.base.util.ClientUtils;
|
import com.qxueyou.scc.base.util.CollectionUtils;
|
import com.qxueyou.scc.base.util.TraceUtils;
|
import com.qxueyou.scc.base.util.UUIDUtils;
|
import com.qxueyou.scc.config.SccConfig;
|
import com.qxueyou.scc.exercise.model.ExerciseGroupItemRe;
|
import com.qxueyou.scc.exercise.model.ExerciseItem;
|
import com.qxueyou.scc.exercise.model.ExerciseItemAnalisi;
|
import com.qxueyou.scc.exercise.model.ExerciseItemData;
|
import com.qxueyou.scc.exercise.model.ExerciseItemOption;
|
import com.qxueyou.scc.exercise.model.ExerciseOptionData;
|
import com.qxueyou.scc.exercise.service.IExercisePyService;
|
|
@Service
|
@EnableConfigurationProperties(SccConfig.class)
|
public class ExercisePyService extends CommonAppService implements
|
IExercisePyService {
|
|
@Autowired
|
SccConfig sccConfig;
|
|
@Autowired
|
IFileUploadService fileUploadService;
|
|
private static Logger log = LogManager.getLogger("ExercisePyService");
|
|
/**
|
* 上传解析
|
*/
|
public Map<String, Object> parserPyExercise(String groupId, String fullPath,
|
String module) {
|
|
File file = downloadFile(groupId, fullPath, module);
|
List<String> lst = generateLstFromFile(file, fullPath);
|
|
if (null == lst || lst.isEmpty()) {
|
return CollectionUtils.newObjectMap("resultCode",0,"msg","文档解析内容为空");
|
}
|
|
return exerciseParsePy(lst, fullPath);
|
|
}
|
|
/**
|
* 校验
|
*
|
* @param content
|
* 习题文本内容
|
* @return
|
*/
|
public Map<String, Object> validatePyExercise(String content) {
|
|
String[] arrLine = content.split("\n");
|
List<String> lst = new ArrayList<String>(arrLine.length);
|
|
for(int i =0;i<arrLine.length;i++ ){
|
if(StringUtils.isBlank(arrLine[i])){
|
continue ;
|
}
|
lst.add(arrLine[i]);
|
}
|
|
// 判断:是否为空
|
if (null == lst || lst.isEmpty()) {
|
return CollectionUtils.newObjectMap("resultCode",0,"msg","文档解析内容为空");
|
}
|
|
return exerciseParsePy(lst, "" );
|
|
}
|
|
public Result doImportPyExercise(List<ExerciseItemData> lstItems,String groupId) {
|
|
if(null == lstItems || lstItems.isEmpty()){
|
return new Result(false, "没有记录");
|
}
|
|
ExerciseGroupItemRe re ;
|
ExerciseItemAnalisi analysis;
|
ExerciseItemOption option ;
|
ExerciseItem item ;
|
|
int itemOrder = 0;
|
String hql = "from ExerciseGroupItemRe r where r.exerciseGroupId = ? order by r.itemOrder desc ";
|
ExerciseGroupItemRe groupRe = this.findUnique(hql, CollectionUtils.newList(groupId), ExerciseGroupItemRe.class);
|
if( null != groupRe ){
|
itemOrder = groupRe.getItemOrder() ;
|
}
|
|
|
|
BigInteger iCount = BigInteger.ZERO ;
|
try {
|
|
for(ExerciseItemData data : lstItems){
|
|
item = new ExerciseItem();
|
re = new ExerciseGroupItemRe();
|
|
BeanUtils.copyProperties(item, data);
|
item.setDeleteFlag(false);
|
TraceUtils.setCreateTrace(item);
|
this.save(item);
|
|
iCount = iCount.add(BigInteger.ONE);
|
|
BeanUtils.copyProperties(re, data);
|
itemOrder++;
|
re.setDeleteFlag(false);
|
re.setExerciseGroupId(groupId);
|
re.setExerciseItemId(item.getExerciseId());
|
re.setItemOrder(itemOrder);
|
re.setDeleteFlag(false);
|
this.save(re);
|
|
if(StringUtils.isNotBlank(data.getAnalysis())){
|
analysis = new ExerciseItemAnalisi();
|
BeanUtils.copyProperties(analysis, data);
|
TraceUtils.setCreateTrace(analysis);
|
analysis.setDeleteFlag(false);
|
analysis.setExerciseItemId(item.getExerciseId());
|
this.save(analysis);
|
}
|
|
if( data.getOptions() != null && !data.getOptions().isEmpty() ){
|
|
for( ExerciseOptionData opt : data.getOptions() ){
|
option = new ExerciseItemOption();
|
BeanUtils.copyProperties(option, opt);
|
TraceUtils.setCreateTrace(option);
|
option.setDeleteFlag(false);
|
option.setExerciseItemId(item.getExerciseId());
|
this.save(option);
|
}
|
|
}
|
|
}
|
|
this.bulkUpdate("update ExerciseGroup set allCount = allCount + ? , " +
|
" updateTime = sysdate(), updateId = ? , updator = ? where groupId = ? " ,
|
new Object[]{ iCount,ClientUtils.getUserId(), ClientUtils.getUserName(), groupId } );
|
|
} catch (Exception e) {
|
log.error("解析习题copyProperties 失败:" ,e );
|
return new Result(false , "服务器内部转换错误");
|
}
|
|
return new Result(true , "成功导入" + iCount + "道习题");
|
}
|
|
|
private Map<String, Object> exerciseParsePy(List<String> lst, String fullPath) {
|
|
return pyExerciseParseByParam(lst, lst.size());
|
//return pyExerciseParseByCache(lst, lst.size());
|
|
|
}
|
|
/**
|
* post传参
|
* @param key
|
* @param size
|
* @return
|
* @throws Exception
|
*/
|
private Map<String, Object> pyExerciseParseByParam(List<String> lst0, int size) {
|
|
return null;
|
|
}
|
|
|
|
/**
|
* 缓存版本
|
* @param key
|
* @param size
|
* @return
|
* @throws Exception
|
*/
|
|
@SuppressWarnings("unused")
|
private Map<String, Object> pyExerciseParseByCache(List<String> lst, int size){
|
|
return null;
|
|
}
|
|
|
private File downloadFile(String groupId, String fullPath, String module) {
|
|
String filePart[] = fullPath.split("\\.");
|
String fileType = filePart[filePart.length - 1];
|
String uuid = UUIDUtils.generateUUID();
|
String filePath = ExerciseService.class.getClassLoader()
|
.getResource("../uploads").getPath()
|
.concat("exercise/" + uuid + "/" + uuid + "." + fileType);
|
|
return fileUploadService.doGetOssFile(fullPath, filePath, module,
|
ClientUtils.getUserId());
|
|
}
|
|
private List<String> generateLstFromFile(File file, String fullPath) {
|
|
String txtFilePath = transformDocToTxt(file);
|
|
List<String> lst = new ArrayList<String>(100);
|
|
FileReader reader = null;
|
BufferedReader br = null;
|
try {
|
reader = new FileReader(txtFilePath);
|
br = new BufferedReader(reader);
|
|
String currLine = "";
|
while ((currLine = br.readLine()) != null) {
|
if (StringUtils.isNotBlank(currLine)) {
|
lst.add(currLine);
|
}
|
}
|
} catch (Exception e) {
|
log.error("解析练习txt文档失败:" + fullPath, e);
|
} finally {
|
IOUtils.closeQuietly(br);
|
IOUtils.closeQuietly(reader);
|
}
|
|
File txt = new File(txtFilePath);
|
FileUtils.deleteQuietly(txt);
|
|
return lst;
|
|
}
|
|
/**
|
* 从office转换到txt:2007转换:自带序号格式会丢失;2003会解析出来
|
*
|
* @param file
|
* @return
|
*/
|
private String transformDocToTxt(File file) {
|
InputStream is = null;
|
FileWriter writer = null;
|
String strText = "";
|
|
try {
|
String fileExtention = fileExtension(file.getName());
|
is = new FileInputStream(file.getAbsolutePath());
|
|
if ("doc".equals(fileExtention)) {
|
WordExtractor extractor = new WordExtractor(is);
|
// 获取Word文件中的文本+自带序号
|
strText = extractor.getText();
|
extractor.close();
|
} else if ("docx".equals(fileExtention)) {
|
OPCPackage opcPackage = POIXMLDocument.openPackage(file
|
.getAbsolutePath());
|
POIXMLTextExtractor extractor = new XWPFWordExtractor(
|
opcPackage);
|
// 只能获取Word文件中的文本,不能取到office序号
|
strText = extractor.getText();
|
extractor.close();
|
} else {
|
throw new RuntimeException("文件格式错误, 请上传word文档(.doc及.docx)格式",
|
null);
|
}
|
|
// 将得到的文本全角转半角
|
strText = formatFullToHalf(strText);
|
|
// 解决空格保存为txt的时候,乱码为?
|
byte bytes[] = { (byte) 0xC2, (byte) 0xA0 };
|
String UTFSpace = new String(bytes, "UTF-8");
|
strText = strText.replaceAll(UTFSpace, " ");
|
|
File txtFile = new File(file.getParentFile().getAbsolutePath()
|
+ "/"
|
+ file.getName().substring(0,
|
file.getName().lastIndexOf(".")) + ".txt");
|
writer = new FileWriter(txtFile, true);
|
writer.write(strText);
|
|
return txtFile.getAbsolutePath();
|
|
} catch (FileNotFoundException e) {
|
throw new RuntimeException("office文档未找到", e);
|
} catch (IOException e) {
|
throw new RuntimeException("office文档读取失败", e);
|
} catch (Exception e) {
|
throw new RuntimeException(e.getMessage(), e);
|
} finally {
|
IOUtils.closeQuietly(writer);
|
IOUtils.closeQuietly(is);
|
}
|
}
|
|
/**
|
* 全角转半角
|
*
|
* @param oriText
|
* @return
|
*/
|
private String formatFullToHalf(String oriText) {
|
if (null == oriText || oriText.length() <= 0) {
|
return "";
|
}
|
|
char[] charArray = oriText.toCharArray();
|
// 对全角字符转换的char数组遍历
|
for (int i = 0; i < charArray.length; ++i) {
|
int charIntValue = (int) charArray[i];
|
|
// 如果符合转换关系,将对应下标之间减掉偏移量65248;如果是空格的话,直接做转换
|
if (charIntValue >= 65281 && charIntValue <= 65374) {
|
charArray[i] = (char) (charIntValue - 65248);
|
} else if (charIntValue == 12288) {
|
charArray[i] = (char) 32;
|
} else if (charIntValue == 58033) {
|
// 空格
|
charArray[i] = (char) 32;
|
} else if (charIntValue == 65380) {
|
// 顿号
|
charArray[i] = (char) 12289;
|
} else if (charIntValue == 65377) {
|
// 句号
|
charArray[i] = (char) 12290;
|
}
|
}
|
return new String(charArray);
|
|
}
|
|
/**
|
* 解析文件后缀
|
*
|
* @param filename
|
* @return
|
*/
|
private String fileExtension(String filename) {
|
|
return filename.substring(filename.lastIndexOf('.') + 1,
|
filename.length());
|
}
|
|
}
|