|
|
@@ -7,15 +7,15 @@ import cn.reghao.jutil.jdk.serializer.JsonConverter;
|
|
|
import cn.reghao.tnb.common.auth.UserContext;
|
|
|
import cn.reghao.tnb.common.db.KeyValue;
|
|
|
import cn.reghao.tnb.content.app.exam.db.mapper.*;
|
|
|
+import cn.reghao.tnb.content.app.exam.model.constant.PaperStatus;
|
|
|
import cn.reghao.tnb.content.app.exam.model.constant.QuestionType;
|
|
|
import cn.reghao.tnb.content.app.exam.model.dto.PaperAddDto;
|
|
|
-import cn.reghao.tnb.content.app.exam.model.dto.UserAnswer;
|
|
|
import cn.reghao.tnb.content.app.exam.model.dto.UserResult;
|
|
|
import cn.reghao.tnb.content.app.exam.model.po.*;
|
|
|
+import cn.reghao.tnb.content.app.exam.model.query.ExamQuery;
|
|
|
import cn.reghao.tnb.content.app.exam.model.query.PaperQuery;
|
|
|
import cn.reghao.tnb.content.app.exam.model.vo.*;
|
|
|
import cn.reghao.tnb.content.app.util.redis.ds.RedisHash;
|
|
|
-import org.springframework.data.redis.support.collections.RedisMap;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
import org.springframework.transaction.annotation.Transactional;
|
|
|
|
|
|
@@ -34,21 +34,26 @@ public class PaperService {
|
|
|
private final QuestionOptionMapper questionOptionMapper;
|
|
|
private final RedisHash redisHash;
|
|
|
private String keyPrefix = "tnb:exam:result";
|
|
|
+ private PaperResultMapper paperResultMapper;
|
|
|
+ private PaperAnswerMapper paperAnswerMapper;
|
|
|
|
|
|
public PaperService(PaperMapper paperMapper, PaperQuestionMapper paperQuestionMapper,
|
|
|
QuestionMapper questionMapper, QuestionOptionMapper questionOptionMapper,
|
|
|
- RedisHash redisHash) {
|
|
|
+ RedisHash redisHash, PaperResultMapper paperResultMapper,
|
|
|
+ PaperAnswerMapper paperAnswerMapper) {
|
|
|
this.paperMapper = paperMapper;
|
|
|
this.paperQuestionMapper = paperQuestionMapper;
|
|
|
this.questionMapper = questionMapper;
|
|
|
this.questionOptionMapper = questionOptionMapper;
|
|
|
this.redisHash = redisHash;
|
|
|
+ this.paperResultMapper = paperResultMapper;
|
|
|
+ this.paperAnswerMapper = paperAnswerMapper;
|
|
|
}
|
|
|
|
|
|
public Result createExamPaper(PaperAddDto paperAddDto) {
|
|
|
Paper paper = new Paper(paperAddDto);
|
|
|
- List<PaperQuestion> questions = paperAddDto.getQuestions();
|
|
|
- save(paper, questions);
|
|
|
+ List<PaperQuestion> paperQuestions = paperAddDto.getQuestions();
|
|
|
+ save(paper, paperQuestions);
|
|
|
return Result.success();
|
|
|
}
|
|
|
|
|
|
@@ -58,12 +63,9 @@ public class PaperService {
|
|
|
int paperId = paper.getId();
|
|
|
list.forEach(paperQuestion -> {
|
|
|
paperQuestion.setPaperId(paperId);
|
|
|
- if (!paperQuestion.getChildren().isEmpty()) {
|
|
|
- paperQuestion.setChild(true);
|
|
|
- }
|
|
|
});
|
|
|
|
|
|
- List<PaperQuestion> list1 = list.stream()
|
|
|
+ /*List<PaperQuestion> list1 = list.stream()
|
|
|
.map(paperQuestion -> {
|
|
|
if (paperQuestion.getChildren().isEmpty()) {
|
|
|
return null;
|
|
|
@@ -78,12 +80,12 @@ public class PaperService {
|
|
|
})
|
|
|
.filter(Objects::nonNull)
|
|
|
.flatMap(Collection::stream)
|
|
|
- .collect(Collectors.toList());
|
|
|
+ .collect(Collectors.toList());*/
|
|
|
|
|
|
paperQuestionMapper.saveAll(list);
|
|
|
- if (!list1.isEmpty()) {
|
|
|
+ /*if (!list1.isEmpty()) {
|
|
|
paperQuestionMapper.saveAll(list1);
|
|
|
- }
|
|
|
+ }*/
|
|
|
}
|
|
|
|
|
|
public Result deleteExamPaper(int paperId) {
|
|
|
@@ -92,17 +94,42 @@ public class PaperService {
|
|
|
}
|
|
|
|
|
|
public PageList<PaperView> getExamPapers(PaperQuery paperQuery) {
|
|
|
+ long loginUser = paperQuery.getLoginUser();
|
|
|
int total = paperMapper.countByCriteria(paperQuery);
|
|
|
Page page = paperQuery.getPage();
|
|
|
List<Paper> list = paperMapper.findPaperByPage(page, paperQuery);
|
|
|
- List<PaperView> list1 = list.stream().map(PaperView::new).collect(Collectors.toList());
|
|
|
+ List<PaperView> list1 = list.stream()
|
|
|
+ .map(paper -> {
|
|
|
+ int paperId = paper.getId();
|
|
|
+ int paperType = paper.getStatus();
|
|
|
+ PaperResult paperResult = getPaperResult(paperId, loginUser);
|
|
|
+ int status;
|
|
|
+ // 1. 试卷未完成
|
|
|
+ // 2. 试卷已完成, 待批改
|
|
|
+ // 3. 试卷已完成, 自己批改
|
|
|
+ // 4. 试卷已完成, 已批改
|
|
|
+ if (paperResult == null) {
|
|
|
+ status = 1;
|
|
|
+ } else if (paperResult.getMarked()) {
|
|
|
+ //status = paperResult.getMarked() ? 4 : 2;
|
|
|
+ status = 4;
|
|
|
+ } else if (paperType == 2) {
|
|
|
+ status = 3;
|
|
|
+ } else {
|
|
|
+ status = 2;
|
|
|
+ }
|
|
|
+
|
|
|
+ return new PaperView(paper, status);
|
|
|
+ })
|
|
|
+ .collect(Collectors.toList());
|
|
|
+
|
|
|
return PageList.pageList(page, total, list1);
|
|
|
}
|
|
|
|
|
|
public List<QuestionInfo> getPaperQuestions(int paperId) {
|
|
|
- List<PaperQuestion> questions = paperQuestionMapper.findByPaperId(paperId);
|
|
|
+ List<PaperQuestion> paperQuestions = paperQuestionMapper.findByPaperId(paperId);
|
|
|
// questionId -> pos
|
|
|
- Map<Long, PaperQuestion> questionMap = questions.stream()
|
|
|
+ Map<Long, PaperQuestion> questionMap = paperQuestions.stream()
|
|
|
.collect(Collectors.toMap(PaperQuestion::getQuestionId, k -> k));
|
|
|
List<Question> list1 = questionMapper.findByQuestionIds(new ArrayList<>(questionMap.keySet()));
|
|
|
return list1.stream().map(question -> {
|
|
|
@@ -140,23 +167,32 @@ public class PaperService {
|
|
|
.sorted(Comparator.comparingInt(QuestionAnswerInfo::getPos))
|
|
|
.collect(Collectors.toList());
|
|
|
questionInfo.setAnswer(answerInfos);
|
|
|
+ questionInfo.setQuestionOptions(answerInfos);
|
|
|
}
|
|
|
|
|
|
return questionInfo;
|
|
|
}
|
|
|
|
|
|
- public PaperDetail getPaperDetail(int paperId) {
|
|
|
+ public PaperDetail getPaperDetail(int paperId, int status) {
|
|
|
+ long loginUser = UserContext.getUser();
|
|
|
+ Map<Long, QuestionAnswer> paperAnswers;
|
|
|
+ if (status == PaperStatus.PaperPreview.getCode()) {
|
|
|
+ paperAnswers = getPaperAnswersFromResult(paperId, loginUser);
|
|
|
+ } else if (status == PaperStatus.PaperExam.getCode()) {
|
|
|
+ paperAnswers = getPaperAnswersFromCache(paperId, loginUser);
|
|
|
+ } else if (status == PaperStatus.PaperMark.getCode()) {
|
|
|
+ paperAnswers = getPaperAnswersFromResult(paperId, loginUser);
|
|
|
+ } else if (status == PaperStatus.PaperResult.getCode()) {
|
|
|
+ paperAnswers = getPaperAnswersFromResult(paperId, loginUser);
|
|
|
+ } else {
|
|
|
+ paperAnswers = getPaperAnswersFromResult(paperId, loginUser);
|
|
|
+ }
|
|
|
+
|
|
|
Paper paper = paperMapper.findById(paperId);
|
|
|
- List<QuestionInfo> questions = getPaperQuestions(paperId);
|
|
|
- Map<Integer, List<QuestionInfo>> groupMap = questions.stream()
|
|
|
+ Map<Integer, List<QuestionInfo>> questionMap = getPaperQuestions(paperId).stream()
|
|
|
.collect(Collectors.groupingBy(QuestionInfo::getQuestionType));
|
|
|
-
|
|
|
- Map<Long, List<Object>> cachedUserAnswers = getCachedUserAnswers(paperId);
|
|
|
- UserResult userResult = new UserResult(1, cachedUserAnswers);
|
|
|
-
|
|
|
- PaperDetail paperDetail= new PaperDetail(paper, questions, groupMap);
|
|
|
- paperDetail.setUserResult(userResult);
|
|
|
- return paperDetail;
|
|
|
+ UserResult userResult = new UserResult(paperId, paperAnswers);
|
|
|
+ return new PaperDetail(paper, status, questionMap, userResult);
|
|
|
}
|
|
|
|
|
|
public void cacheUserAnswers(UserResult userResult) {
|
|
|
@@ -164,39 +200,28 @@ public class PaperService {
|
|
|
int paperId = userResult.getPaperId();
|
|
|
String key = String.format("%s:%s:%s", keyPrefix, paperId, loginUser);
|
|
|
|
|
|
- List<UserAnswer> userAnswers = userResult.getUserAnswers();
|
|
|
- for (UserAnswer userAnswer : userAnswers) {
|
|
|
+ List<QuestionAnswer> userAnswers = userResult.getUserAnswers();
|
|
|
+ for (QuestionAnswer userAnswer : userAnswers) {
|
|
|
long questionId = userAnswer.getQuestionId();
|
|
|
- String[] answers = userAnswer.getAnswers();
|
|
|
- //String answersJson = JsonConverter.objectToJson(answers);
|
|
|
- redisHash.hset(key, ""+questionId, answers);
|
|
|
+ redisHash.hset(key, ""+questionId, userAnswer);
|
|
|
}
|
|
|
- /*Map<Long, List<String>> cachedUserAnswers = userResult.getCachedUserAnswers();
|
|
|
- cachedUserAnswers.forEach((k, v) -> {
|
|
|
- redisHash.hset(key, ""+k, v);
|
|
|
- });*/
|
|
|
}
|
|
|
|
|
|
- private Map<Long, List<Object>> getCachedUserAnswers(int paperId) {
|
|
|
- Map<Long, List<Object>> map = new HashMap<>();
|
|
|
-
|
|
|
- long loginUser = UserContext.getUser();
|
|
|
- String key = String.format("%s:%s:%s", keyPrefix, paperId, loginUser);
|
|
|
- Map cachedMap = redisHash.hgetall(key);
|
|
|
- cachedMap.forEach((k, v) -> {
|
|
|
- long questionId = Long.parseLong((String) k);
|
|
|
- Question question = questionMapper.findByQuestionId(questionId);
|
|
|
- int type = question.getType();
|
|
|
- String[] answers = (String[]) v;
|
|
|
- List<Object> objectList;
|
|
|
- if (type == QuestionType.QUESTION1.getCode() || type == QuestionType.QUESTION4.getCode()) {
|
|
|
- objectList = Arrays.stream(answers)
|
|
|
- .map(val -> val.isBlank() ? -1 : Integer.parseInt(val))
|
|
|
- .collect(Collectors.toList());
|
|
|
- } else {
|
|
|
- objectList = Arrays.asList(answers);
|
|
|
+ private Map<Long, QuestionAnswer> getPaperAnswersFromCache(int paperId, long userId) {
|
|
|
+ Map<Long, QuestionAnswer> map = new HashMap<>();
|
|
|
+ String key = String.format("%s:%s:%s", keyPrefix, paperId, userId);
|
|
|
+ redisHash.hgetall(key).forEach((k, v) -> {
|
|
|
+ QuestionAnswer questionAnswer = (QuestionAnswer) v;
|
|
|
+ long questionId = questionAnswer.getQuestionId();
|
|
|
+ Object[] submitAnswer = questionAnswer.getSubmitAnswer();
|
|
|
+ int questionType = questionAnswer.getQuestionType();
|
|
|
+ if (questionType == QuestionType.QUESTION1.getCode()) {
|
|
|
+ if (submitAnswer[0] instanceof String) {
|
|
|
+ Object[] submitAnswer1 = new Object[] {Integer.parseInt((String) submitAnswer[0])};
|
|
|
+ questionAnswer.setSubmitAnswer(submitAnswer1);
|
|
|
+ }
|
|
|
}
|
|
|
- map.put(questionId, objectList);
|
|
|
+ map.put(questionId, questionAnswer);
|
|
|
});
|
|
|
if (!map.isEmpty()) {
|
|
|
return map;
|
|
|
@@ -204,23 +229,125 @@ public class PaperService {
|
|
|
|
|
|
List<QuestionInfo> questions = getPaperQuestions(paperId);
|
|
|
for (QuestionInfo questionInfo : questions) {
|
|
|
+ QuestionAnswer questionAnswer = new QuestionAnswer(questionInfo);
|
|
|
long questionId = questionInfo.getQuestionId();
|
|
|
int type = questionInfo.getQuestionType();
|
|
|
List<QuestionOption> questionOptionList = questionOptionMapper.findByQuestionId(questionId);
|
|
|
long count = questionOptionList.stream().filter(QuestionOption::getCorrect).count();
|
|
|
List<Object> list = new ArrayList<>();
|
|
|
for (int i = 0; i < count; i++) {
|
|
|
- if (type == QuestionType.QUESTION1.getCode() || type == QuestionType.QUESTION4.getCode()) {
|
|
|
+ if (type == QuestionType.QUESTION1.getCode() || type == QuestionType.QUESTION3.getCode()) {
|
|
|
+ // 单选题和判断题前端使用 radio, 需要 int 类型来表示选中的 radio
|
|
|
list.add(-1);
|
|
|
- } else if (type == QuestionType.QUESTION2.getCode() || type == QuestionType.QUESTION3.getCode()) {
|
|
|
+ } else if (type == QuestionType.QUESTION2.getCode()) {
|
|
|
+ // 多选题前端使用 checkbox, 使用 string[] 来表示选中的 checkbox
|
|
|
+ // 空数组表示没有选中
|
|
|
} else {
|
|
|
+ // 填空题和简答题使用空字符串占位
|
|
|
list.add("");
|
|
|
}
|
|
|
+ questionAnswer.setSubmitAnswer(list.toArray(new Object[0]));
|
|
|
}
|
|
|
|
|
|
- map.putIfAbsent(questionId, list);
|
|
|
+ map.putIfAbsent(questionId, questionAnswer);
|
|
|
+ }
|
|
|
+
|
|
|
+ return map;
|
|
|
+ }
|
|
|
+
|
|
|
+ private Map<Long, QuestionAnswer> getPaperAnswersFromResult(int paperId, long userId) {
|
|
|
+ PaperResult paperResult = getPaperResult(paperId, userId);
|
|
|
+ if (paperResult == null) {
|
|
|
+ return getPaperAnswersFromCorrect(paperId);
|
|
|
}
|
|
|
|
|
|
+ int resultId = paperResult.getId();
|
|
|
+ return getPaperAnswersFromResult(resultId);
|
|
|
+ }
|
|
|
+
|
|
|
+ private PaperResult getPaperResult(int paperId, long userId) {
|
|
|
+ ExamQuery examQuery = new ExamQuery.Builder()
|
|
|
+ .loginUser(userId)
|
|
|
+ .paperId(paperId)
|
|
|
+ .build();
|
|
|
+ Page page = examQuery.getPage();
|
|
|
+ List<PaperResult> list = paperResultMapper.findPaperResultByPage(page, examQuery);
|
|
|
+ return list.isEmpty() ? null : list.get(0);
|
|
|
+ }
|
|
|
+
|
|
|
+ private Map<Long, QuestionAnswer> getPaperAnswersFromResult(int resultId) {
|
|
|
+ Map<Long, QuestionAnswer> map = new HashMap<>();
|
|
|
+ List<PaperAnswer> paperAnswerList = paperAnswerMapper.findByResultId(resultId);
|
|
|
+ paperAnswerList.forEach(paperAnswer -> {
|
|
|
+ QuestionAnswer questionAnswer = new QuestionAnswer(paperAnswer);
|
|
|
+ long questionId = paperAnswer.getQuestionId();
|
|
|
+ setSubmitAnswer(paperAnswer, questionAnswer);
|
|
|
+ setCorrectAnswer(questionAnswer);
|
|
|
+ map.put(questionId, questionAnswer);
|
|
|
+ });
|
|
|
+
|
|
|
+ return map;
|
|
|
+ }
|
|
|
+
|
|
|
+ private void setCorrectAnswer(QuestionAnswer questionAnswer) {
|
|
|
+ long questionId = questionAnswer.getQuestionId();
|
|
|
+ List<QuestionOption> list = questionOptionMapper.findByQuestionId(questionId);
|
|
|
+ List<Object> correctAnswers = list.stream()
|
|
|
+ .filter(QuestionOption::getCorrect)
|
|
|
+ .map(QuestionOption::getContent)
|
|
|
+ .collect(Collectors.toList());
|
|
|
+ questionAnswer.setCorrectAnswer(correctAnswers.toArray(new Object[0]));
|
|
|
+ }
|
|
|
+
|
|
|
+ private void setSubmitAnswer(PaperAnswer paperAnswer, QuestionAnswer questionAnswer) {
|
|
|
+ int type = paperAnswer.getQuestionType();
|
|
|
+ String submitAnswer = paperAnswer.getAnswer();
|
|
|
+ List<Object> submitAnswerList;
|
|
|
+ if (type == QuestionType.QUESTION1.getCode() || type == QuestionType.QUESTION3.getCode()) {
|
|
|
+ submitAnswerList = List.of(Integer.parseInt(submitAnswer));
|
|
|
+ } else if (type == QuestionType.QUESTION2.getCode()) {
|
|
|
+ String[] answerArr = submitAnswer.split(",");
|
|
|
+ submitAnswerList = List.of(answerArr);
|
|
|
+ } else {
|
|
|
+ submitAnswerList = List.of(submitAnswer);
|
|
|
+ }
|
|
|
+ questionAnswer.setSubmitAnswer(submitAnswerList.toArray(new Object[0]));
|
|
|
+ }
|
|
|
+
|
|
|
+ @Deprecated
|
|
|
+ private Map<Long, QuestionAnswer> getPaperAnswersFromCorrect(int paperId) {
|
|
|
+ Map<Long, QuestionAnswer> map = new HashMap<>();
|
|
|
+ List<PaperQuestion> paperQuestions = paperQuestionMapper.findByPaperId(paperId);
|
|
|
+ List<Long> questionIds = paperQuestions.stream().map(PaperQuestion::getQuestionId).collect(Collectors.toList());
|
|
|
+ List<Question> questions = questionMapper.findByQuestionIds(questionIds);
|
|
|
+ questions.forEach(question -> {
|
|
|
+ QuestionAnswer questionAnswer = new QuestionAnswer(question);
|
|
|
+ long questionId = question.getQuestionId();
|
|
|
+ int type = question.getType();
|
|
|
+
|
|
|
+ List<QuestionOption> list = questionOptionMapper.findByQuestionId(questionId);
|
|
|
+ // 正确答案
|
|
|
+ List<Object> correctAnswerList;
|
|
|
+ if (type == QuestionType.QUESTION1.getCode() || type == QuestionType.QUESTION3.getCode()) {
|
|
|
+ correctAnswerList = list.stream()
|
|
|
+ .filter(QuestionOption::getCorrect)
|
|
|
+ .map(QuestionOption::getPos)
|
|
|
+ .collect(Collectors.toList());
|
|
|
+ } else if (type == QuestionType.QUESTION2.getCode()) {
|
|
|
+ correctAnswerList = list.stream()
|
|
|
+ .filter(QuestionOption::getCorrect)
|
|
|
+ .map(QuestionOption::getPos)
|
|
|
+ .collect(Collectors.toList());
|
|
|
+ } else {
|
|
|
+ correctAnswerList = list.stream()
|
|
|
+ .filter(QuestionOption::getCorrect)
|
|
|
+ .map(QuestionOption::getContent)
|
|
|
+ .collect(Collectors.toList());
|
|
|
+ }
|
|
|
+
|
|
|
+ questionAnswer.setCorrectAnswer(correctAnswerList.toArray(new Object[0]));
|
|
|
+ map.put(questionId, questionAnswer);
|
|
|
+ });
|
|
|
return map;
|
|
|
}
|
|
|
|