|
@@ -1,323 +0,0 @@
|
|
|
-package cn.reghao.tnb.content.app.exam.service;
|
|
|
|
|
-
|
|
|
|
|
-import cn.reghao.tnb.common.auth.AccountRole;
|
|
|
|
|
-import cn.reghao.tnb.common.auth.UserContext;
|
|
|
|
|
-import cn.reghao.tnb.content.app.exam.db.mapper.*;
|
|
|
|
|
-import cn.reghao.tnb.content.app.exam.model.constant.PaperViewType;
|
|
|
|
|
-import cn.reghao.tnb.content.app.exam.model.constant.QuestionType;
|
|
|
|
|
-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.vo.*;
|
|
|
|
|
-import cn.reghao.tnb.content.app.util.redis.ds.RedisHash;
|
|
|
|
|
-import lombok.extern.slf4j.Slf4j;
|
|
|
|
|
-import org.springframework.stereotype.Service;
|
|
|
|
|
-
|
|
|
|
|
-import java.util.*;
|
|
|
|
|
-import java.util.stream.Collectors;
|
|
|
|
|
-
|
|
|
|
|
-/**
|
|
|
|
|
- * @author reghao
|
|
|
|
|
- * @date 2025-08-12 14:48:05
|
|
|
|
|
- */
|
|
|
|
|
-@Slf4j
|
|
|
|
|
-@Service
|
|
|
|
|
-public class PaperViewService {
|
|
|
|
|
- private String keyPrefix = "tnb:exam:result";
|
|
|
|
|
- private final PaperMapper paperMapper;
|
|
|
|
|
- private final PaperQuestionMapper paperQuestionMapper;
|
|
|
|
|
- private final QuestionMapper questionMapper;
|
|
|
|
|
- private final QuestionOptionMapper questionOptionMapper;
|
|
|
|
|
- private final RedisHash redisHash;
|
|
|
|
|
- private PaperAnswerMapper paperAnswerMapper;
|
|
|
|
|
-
|
|
|
|
|
- public PaperViewService(PaperMapper paperMapper, PaperQuestionMapper paperQuestionMapper,
|
|
|
|
|
- QuestionMapper questionMapper, QuestionOptionMapper questionOptionMapper,
|
|
|
|
|
- RedisHash redisHash, PaperAnswerMapper paperAnswerMapper) {
|
|
|
|
|
- this.paperMapper = paperMapper;
|
|
|
|
|
- this.paperQuestionMapper = paperQuestionMapper;
|
|
|
|
|
- this.questionMapper = questionMapper;
|
|
|
|
|
- this.questionOptionMapper = questionOptionMapper;
|
|
|
|
|
- this.redisHash = redisHash;
|
|
|
|
|
- this.paperAnswerMapper = paperAnswerMapper;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private int getRole() {
|
|
|
|
|
- int role = -1;
|
|
|
|
|
- /*if (UserContext.getUserRoles().contains(AccountRole.examAdmin.getValue())) {
|
|
|
|
|
- role = 1;
|
|
|
|
|
- } else if (UserContext.getUserRoles().contains(AccountRole.examUser.getValue())) {
|
|
|
|
|
- role = 2;
|
|
|
|
|
- }*/
|
|
|
|
|
- return role;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public PaperDetail getPaperDetail(int paperId, int viewType, int resultId) {
|
|
|
|
|
- long loginUser = UserContext.getUserId();
|
|
|
|
|
- int role = getRole();
|
|
|
|
|
- Paper paper = paperMapper.findById(paperId);
|
|
|
|
|
- Map<Long, QuestionAnswer> paperAnswers;
|
|
|
|
|
- if (viewType == PaperViewType.PaperPreview.getCode()) {
|
|
|
|
|
- if (role > 1) {
|
|
|
|
|
- // 用户只有做题的权限
|
|
|
|
|
- return new PaperDetail(paperId, 3);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- paperAnswers = getPaperAnswersFromCorrect(paperId);
|
|
|
|
|
- } else if (viewType == PaperViewType.PaperExam.getCode()) {
|
|
|
|
|
- if (role == 1) {
|
|
|
|
|
- // 用户只有管理的权限
|
|
|
|
|
- return new PaperDetail(paperId, 2);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- paperAnswers = getPaperAnswersFromCache(paperId, loginUser);
|
|
|
|
|
- } else if (viewType == PaperViewType.PaperMark.getCode()) {
|
|
|
|
|
- int markType = paper.getMarkType();
|
|
|
|
|
- if (markType == 2) {
|
|
|
|
|
- // 自己批改
|
|
|
|
|
- if (role == 1) {
|
|
|
|
|
- // 试卷由用户自己批改
|
|
|
|
|
- return new PaperDetail(paperId, 4);
|
|
|
|
|
- }
|
|
|
|
|
- } else if (markType == 3) {
|
|
|
|
|
- // 他人批改
|
|
|
|
|
- if (role > 1) {
|
|
|
|
|
- // 用户只有做题的权限
|
|
|
|
|
- return new PaperDetail(paperId, 3);
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // 批改试卷不需要客观题
|
|
|
|
|
- paperAnswers = getPaperAnswersFromResult(paperId, resultId, false);
|
|
|
|
|
- } else if (viewType == PaperViewType.PaperResult.getCode()) {
|
|
|
|
|
- if (role == 1) {
|
|
|
|
|
- // 用户只有管理的权限
|
|
|
|
|
- return new PaperDetail(paperId, 2);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- paperAnswers = getPaperAnswersFromResult(paperId, resultId, true);
|
|
|
|
|
- } else {
|
|
|
|
|
- // 试卷访问类型 viewType 未知
|
|
|
|
|
- return new PaperDetail(paperId, 7);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- int paperViewStatus = 9;
|
|
|
|
|
- Set<Integer> questionTypes = paperAnswers.values().stream()
|
|
|
|
|
- .collect(Collectors.groupingBy(QuestionAnswer::getQuestionType))
|
|
|
|
|
- .keySet();
|
|
|
|
|
- Map<Integer, List<QuestionInfo>> questionMap = getPaperQuestions(paperId).stream()
|
|
|
|
|
- .filter(questionInfo -> {
|
|
|
|
|
- int questionType = questionInfo.getQuestionType();
|
|
|
|
|
- return questionTypes.contains(questionType);
|
|
|
|
|
- })
|
|
|
|
|
- .collect(Collectors.groupingBy(QuestionInfo::getQuestionType));
|
|
|
|
|
- UserResult userResult = new UserResult(paperId, paperAnswers);
|
|
|
|
|
- return new PaperDetail(paper, paperViewStatus, questionMap, userResult);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public List<QuestionInfo> getPaperQuestions(int paperId) {
|
|
|
|
|
- List<PaperQuestion> paperQuestions = paperQuestionMapper.findByPaperId(paperId);
|
|
|
|
|
- // questionId -> pos
|
|
|
|
|
- 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 -> {
|
|
|
|
|
- QuestionInfo questionInfo = getQuestionInfo(question, questionMap);
|
|
|
|
|
- long questionId = question.getQuestionId();
|
|
|
|
|
- boolean child = question.getChild();
|
|
|
|
|
- if (child) {
|
|
|
|
|
- List<QuestionInfo> children = getGroupQuestion(paperId, questionId);
|
|
|
|
|
- questionInfo.setChildren(children);
|
|
|
|
|
- }
|
|
|
|
|
- return questionInfo;
|
|
|
|
|
- }).sorted(Comparator.comparingInt(QuestionInfo::getPos)).collect(Collectors.toList());
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private List<QuestionInfo> getGroupQuestion(int paperId, long pid) {
|
|
|
|
|
- List<Question> questions = questionMapper.findByPid(pid);
|
|
|
|
|
- Map<Long, PaperQuestion> questionMap = paperQuestionMapper.findByPaperIdAndPid(paperId, pid).stream()
|
|
|
|
|
- .collect(Collectors.toMap(PaperQuestion::getQuestionId, k -> k));
|
|
|
|
|
-
|
|
|
|
|
- return questions.stream()
|
|
|
|
|
- .map(question -> getQuestionInfo(question, questionMap))
|
|
|
|
|
- .collect(Collectors.toList());
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private QuestionInfo getQuestionInfo(Question question, Map<Long, PaperQuestion> questionMap) {
|
|
|
|
|
- long questionId = question.getQuestionId();
|
|
|
|
|
- int pos = questionMap.get(questionId).getPos();
|
|
|
|
|
- int score = questionMap.get(questionId).getScore();
|
|
|
|
|
-
|
|
|
|
|
- QuestionInfo questionInfo = new QuestionInfo(pos, question, score);
|
|
|
|
|
- List<QuestionOption> list2 = questionOptionMapper.findByQuestionId(questionId);
|
|
|
|
|
- if (!list2.isEmpty()) {
|
|
|
|
|
- List<QuestionAnswerInfo> answerInfos = list2.stream()
|
|
|
|
|
- .map(QuestionAnswerInfo::new)
|
|
|
|
|
- .sorted(Comparator.comparingInt(QuestionAnswerInfo::getPos))
|
|
|
|
|
- .collect(Collectors.toList());
|
|
|
|
|
- questionInfo.setAnswer(answerInfos);
|
|
|
|
|
- questionInfo.setQuestionOptions(answerInfos);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- return questionInfo;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- 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, questionAnswer);
|
|
|
|
|
- });
|
|
|
|
|
- if (!map.isEmpty()) {
|
|
|
|
|
- return map;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- return getEmptyPaperAnswers(paperId);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * 获取空白的试卷答案
|
|
|
|
|
- *
|
|
|
|
|
- * @param
|
|
|
|
|
- * @return
|
|
|
|
|
- * @date 2025-08-10 18:08:71
|
|
|
|
|
- */
|
|
|
|
|
- private Map<Long, QuestionAnswer> getEmptyPaperAnswers(int paperId) {
|
|
|
|
|
- Map<Long, QuestionAnswer> map = new HashMap<>();
|
|
|
|
|
- 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.QUESTION3.getCode()) {
|
|
|
|
|
- // 单选题和判断题前端使用 radio, 需要 int 类型来表示选中的 radio
|
|
|
|
|
- list.add(-1);
|
|
|
|
|
- } else if (type == QuestionType.QUESTION2.getCode()) {
|
|
|
|
|
- // 多选题前端使用 checkbox, 使用 string[] 来表示选中的 checkbox
|
|
|
|
|
- // 空数组表示没有选中
|
|
|
|
|
- } else {
|
|
|
|
|
- // 填空题和简答题使用空字符串占位
|
|
|
|
|
- list.add("");
|
|
|
|
|
- }
|
|
|
|
|
- questionAnswer.setSubmitAnswer(list.toArray(new Object[0]));
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- map.putIfAbsent(questionId, questionAnswer);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- return map;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private Map<Long, QuestionAnswer> getPaperAnswersFromResult(int paperId, int resultId, boolean hasObjective) {
|
|
|
|
|
- Map<Long, QuestionAnswer> map = new HashMap<>();
|
|
|
|
|
- List<PaperAnswer> paperAnswerList = paperAnswerMapper.findByResultId(resultId);
|
|
|
|
|
- paperAnswerList.forEach(paperAnswer -> {
|
|
|
|
|
- long questionId = paperAnswer.getQuestionId();
|
|
|
|
|
- int questionType = paperAnswer.getQuestionType();
|
|
|
|
|
- if (questionType <= QuestionType.QUESTION3.getCode() && !hasObjective) {
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- PaperQuestion paperQuestion = paperQuestionMapper.findPaperQuestion(paperId, questionId);
|
|
|
|
|
- int correctScore = paperQuestion.getScore();
|
|
|
|
|
- QuestionAnswer questionAnswer = new QuestionAnswer(paperAnswer, correctScore);
|
|
|
|
|
-
|
|
|
|
|
- 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()) {
|
|
|
|
|
- // 单选题和判断题前端使用 radio, 需要 int 类型来表示选中的 radio
|
|
|
|
|
- submitAnswerList = List.of(Integer.parseInt(submitAnswer));
|
|
|
|
|
- } else if (type == QuestionType.QUESTION2.getCode()) {
|
|
|
|
|
- // 多选题前端使用 checkbox, 使用 string[] 来表示选中的 checkbox
|
|
|
|
|
- String[] answerArr = submitAnswer.split(",");
|
|
|
|
|
- submitAnswerList = List.of(answerArr);
|
|
|
|
|
- } else if (type == QuestionType.QUESTION4.getCode()) {
|
|
|
|
|
- // 填空题
|
|
|
|
|
- String[] answerArr = submitAnswer.split(",");
|
|
|
|
|
- submitAnswerList = List.of(answerArr);
|
|
|
|
|
- } else if (type == QuestionType.QUESTION5.getCode()) {
|
|
|
|
|
- // 问答题
|
|
|
|
|
- submitAnswerList = List.of(submitAnswer);
|
|
|
|
|
- } else if (type == QuestionType.QUESTION6.getCode()) {
|
|
|
|
|
- // 组合题
|
|
|
|
|
- submitAnswerList = List.of(submitAnswer);
|
|
|
|
|
- } else {
|
|
|
|
|
- submitAnswerList = List.of(submitAnswer);
|
|
|
|
|
- }
|
|
|
|
|
- questionAnswer.setSubmitAnswer(submitAnswerList.toArray(new Object[0]));
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private Map<Long, QuestionAnswer> getPaperAnswersFromCorrect(int paperId) {
|
|
|
|
|
- Map<Long, QuestionAnswer> map = new HashMap<>();
|
|
|
|
|
- List<PaperQuestion> paperQuestions = paperQuestionMapper.findByPaperId(paperId);
|
|
|
|
|
- Map<Long, PaperQuestion> paperQuestionMap = paperQuestions.stream()
|
|
|
|
|
- .collect(Collectors.toMap(PaperQuestion::getQuestionId, k -> k));
|
|
|
|
|
- //List<Long> questionIds = paperQuestions.stream().map(PaperQuestion::getQuestionId).collect(Collectors.toList());
|
|
|
|
|
- List<Long> questionIds = new ArrayList<>(paperQuestionMap.keySet());
|
|
|
|
|
-
|
|
|
|
|
- List<Question> questions = questionMapper.findByQuestionIds(questionIds);
|
|
|
|
|
- questions.forEach(question -> {
|
|
|
|
|
- long questionId = question.getQuestionId();
|
|
|
|
|
- int type = question.getType();
|
|
|
|
|
- int correctScore = paperQuestionMap.get(questionId).getScore();
|
|
|
|
|
- QuestionAnswer questionAnswer = new QuestionAnswer(question, correctScore);
|
|
|
|
|
-
|
|
|
|
|
- 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;
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|