QuizStudentAnswerServiceImpl.java 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. package nju.seec.helper.service.impl;
  2. import cn.hutool.core.util.StrUtil;
  3. import com.google.common.collect.Maps;
  4. import nju.seec.helper.aspect.auth.LoginUser;
  5. import nju.seec.helper.dao.QuizDAO;
  6. import nju.seec.helper.dao.QuizStudentAnswerDAO;
  7. import nju.seec.helper.dao.UserDAO;
  8. import nju.seec.helper.dto.question.StudentAnswerDTO;
  9. import nju.seec.helper.entity.Quiz;
  10. import nju.seec.helper.entity.QuizStudentAnswer;
  11. import nju.seec.helper.entity.User;
  12. import nju.seec.helper.enums.ExceptionType;
  13. import nju.seec.helper.exception.HelperException;
  14. import nju.seec.helper.service.QuestionService;
  15. import nju.seec.helper.service.QuizStudentAnswerService;
  16. import nju.seec.helper.vo.question.BaseQuestionVO;
  17. import nju.seec.helper.vo.quiz.QuizStudentAnswerStatisticVO;
  18. import nju.seec.helper.vo.quiz.QuizStudentAnswerVO;
  19. import org.springframework.data.domain.Page;
  20. import org.springframework.data.domain.Pageable;
  21. import org.springframework.stereotype.Service;
  22. import org.springframework.transaction.annotation.Transactional;
  23. import java.math.BigDecimal;
  24. import java.math.RoundingMode;
  25. import java.util.List;
  26. import java.util.Map;
  27. import java.util.concurrent.atomic.AtomicInteger;
  28. /**
  29. * @author cst
  30. */
  31. @Service
  32. public class QuizStudentAnswerServiceImpl implements QuizStudentAnswerService {
  33. private final QuizDAO quizDAO;
  34. private final UserDAO userDAO;
  35. private final QuizStudentAnswerDAO quizStudentAnswerDAO;
  36. private final QuestionService questionService;
  37. public QuizStudentAnswerServiceImpl(QuizDAO quizDAO, UserDAO userDAO, QuizStudentAnswerDAO quizStudentAnswerDAO, QuestionService questionService) {
  38. this.quizDAO = quizDAO;
  39. this.userDAO = userDAO;
  40. this.quizStudentAnswerDAO = quizStudentAnswerDAO;
  41. this.questionService = questionService;
  42. }
  43. @Transactional(rollbackFor = Exception.class)
  44. @Override
  45. public QuizStudentAnswerVO submitQuizStudentAnswer(LoginUser user, Long quizId, StudentAnswerDTO studentAnswerDTO) {
  46. Quiz quiz = quizDAO.findQuizById(quizId);
  47. switch (quiz.getState()) {
  48. case NOT_STARTED:
  49. throw HelperException.of(ExceptionType.FORBIDDEN, "测试未开始,无法提交");
  50. case CLOSED:
  51. throw HelperException.of(ExceptionType.FORBIDDEN, "测试已关闭,无法提交");
  52. default:
  53. break;
  54. }
  55. User student = userDAO.findUserById(user.getId());
  56. QuizStudentAnswer quizStudentAnswer = quizStudentAnswerDAO.findByQuizAndStudent(quiz, student).orElse(new QuizStudentAnswer());
  57. if (quizStudentAnswer.getSubmitNumber() >= quiz.getMaxSubmitNumber()) {
  58. throw HelperException.of(ExceptionType.FORBIDDEN, StrUtil.format("已达最大提交次数{}次,无法再提交", quiz.getMaxSubmitNumber()));
  59. }
  60. // 计算得分
  61. List<BaseQuestionVO> questionVOList = questionService.getQuestionsByIds(quiz.getQuestions());
  62. AtomicInteger correct = new AtomicInteger();
  63. Map<String, StudentAnswerDTO.AnswerRecordDTO> records = studentAnswerDTO.getRecords();
  64. questionVOList.forEach(baseQuestionVO -> {
  65. String questionId = baseQuestionVO.getId();
  66. Object answer;
  67. if (records.get(questionId) != null) {
  68. answer = records.get(questionId).getAnswer();
  69. } else {
  70. answer = quizStudentAnswer.getAnswers().get(questionId);
  71. }
  72. if (baseQuestionVO.pass(answer)) {
  73. correct.getAndIncrement();
  74. }
  75. quizStudentAnswer.getAnswers().put(questionId, answer);
  76. });
  77. BigDecimal score = BigDecimal.valueOf(correct.get() * 100).divide(BigDecimal.valueOf(questionVOList.size()), 2, RoundingMode.HALF_UP);
  78. // 计算完毕
  79. quizStudentAnswer.setQuiz(quiz)
  80. .setStudent(student)
  81. .setSubmitNumber(quizStudentAnswer.getSubmitNumber() + 1)
  82. .setScore(score);
  83. questionService.record(user, studentAnswerDTO);
  84. return new QuizStudentAnswerVO(quizStudentAnswerDAO.save(quizStudentAnswer), questionVOList);
  85. }
  86. @Transactional(readOnly = true)
  87. @Override
  88. public Page<QuizStudentAnswerVO> getQuizStudentAnswers(LoginUser user, Long quizId, String key, Pageable pageable) {
  89. return quizStudentAnswerDAO.findByQuizIdAndKey(quizId, key, pageable).map(quizStudentAnswer -> new QuizStudentAnswerVO(quizStudentAnswer, questionService.getQuestionsByIds(quizDAO.findQuizById(quizId).getQuestions())));
  90. }
  91. @Transactional(readOnly = true)
  92. @Override
  93. public QuizStudentAnswerVO getQuizStudentAnswer(LoginUser user, Long quizId) {
  94. return quizStudentAnswerDAO
  95. .findByQuizAndStudent(quizDAO.findQuizById(quizId), userDAO.findUserById(user.getId()))
  96. .map(quizStudentAnswer -> new QuizStudentAnswerVO(quizStudentAnswer, questionService.getQuestionsByIds(quizDAO.findQuizById(quizId).getQuestions())))
  97. .orElse(null);
  98. }
  99. @Transactional(readOnly = true)
  100. @Override
  101. public QuizStudentAnswerStatisticVO getQuizStudentAnswerStatistic(LoginUser user, Long quizId) {
  102. List<QuizStudentAnswer> quizStudentAnswers = quizStudentAnswerDAO.findByQuiz(quizDAO.findQuizById(quizId));
  103. Map<BigDecimal, Integer> scores = Maps.newHashMapWithExpectedSize(quizStudentAnswers.size());
  104. Map<Integer, Integer> submitNums = Maps.newHashMapWithExpectedSize(quizStudentAnswers.size());
  105. quizStudentAnswers.forEach(
  106. quizStudentAnswer -> {
  107. scores.merge(quizStudentAnswer.getScore(), 1, Integer::sum);
  108. submitNums.merge(quizStudentAnswer.getSubmitNumber(), 1, Integer::sum);
  109. }
  110. );
  111. return QuizStudentAnswerStatisticVO.of(quizId, scores, submitNums);
  112. }
  113. }