QuizStudentAnswerServiceImpl.java 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. package nju.seec.helper.service.impl;
  2. import com.google.common.collect.Maps;
  3. import nju.seec.helper.aspect.auth.LoginUser;
  4. import nju.seec.helper.dao.QuizDAO;
  5. import nju.seec.helper.dao.QuizStudentAnswerDAO;
  6. import nju.seec.helper.dao.UserDAO;
  7. import nju.seec.helper.dto.quiz.QuizStudentAnswerDTO;
  8. import nju.seec.helper.entity.Quiz;
  9. import nju.seec.helper.entity.QuizStudentAnswer;
  10. import nju.seec.helper.entity.User;
  11. import nju.seec.helper.enums.ExceptionType;
  12. import nju.seec.helper.exception.HelperException;
  13. import nju.seec.helper.service.CourseService;
  14. import nju.seec.helper.service.QuestionService;
  15. import nju.seec.helper.service.QuizStudentAnswerService;
  16. import nju.seec.helper.vo.QuizStudentAnswerStatisticVO;
  17. import nju.seec.helper.vo.question.BaseQuestionVO;
  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.AtomicReference;
  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. private final CourseService courseService;
  38. public QuizStudentAnswerServiceImpl(QuizDAO quizDAO, UserDAO userDAO, QuizStudentAnswerDAO quizStudentAnswerDAO, QuestionService questionService, CourseService courseService) {
  39. this.quizDAO = quizDAO;
  40. this.userDAO = userDAO;
  41. this.quizStudentAnswerDAO = quizStudentAnswerDAO;
  42. this.questionService = questionService;
  43. this.courseService = courseService;
  44. }
  45. @Transactional(rollbackFor = Exception.class)
  46. @Override
  47. public QuizStudentAnswerVO submitQuizStudentAnswer(LoginUser user, Long quizId, QuizStudentAnswerDTO quizStudentAnswerDTO) {
  48. Quiz quiz = quizDAO.findQuizById(quizId);
  49. if (!courseService.existsCourseResourcesAuth(user, quiz.getCourse().getId())) {
  50. throw HelperException.of(ExceptionType.FORBIDDEN, "您无权提交该测试的作答");
  51. }
  52. switch (quiz.getState()) {
  53. case NOT_STARTED:
  54. throw HelperException.of(ExceptionType.FORBIDDEN, "测试暂未开始");
  55. case CLOSED:
  56. throw HelperException.of(ExceptionType.FORBIDDEN, "测试已关闭,无法提交");
  57. default:
  58. break;
  59. }
  60. User student = userDAO.findUserById(user.getId());
  61. QuizStudentAnswer quizStudentAnswer = quizStudentAnswerDAO.findByQuizAndStudent(quiz, student).orElse(new QuizStudentAnswer());
  62. if (quizStudentAnswer.getSubmitNumber() >= quiz.getMaxSubmitNumber()) {
  63. throw HelperException.of(ExceptionType.FORBIDDEN, String.format("已达最大提交次数%d次,无法再提交", quiz.getMaxSubmitNumber()));
  64. }
  65. // 计算得分
  66. List<BaseQuestionVO> questionVOList = questionService.getQuestionsByQuiz(quiz);
  67. AtomicReference<Integer> correct = new AtomicReference<>(0);
  68. Map<String, Object> answers = quizStudentAnswerDTO.getAnswers();
  69. questionVOList.forEach(baseQuestionVO -> {
  70. Object answer;
  71. if ((answer = answers.get(baseQuestionVO.getId())) != null && baseQuestionVO.pass(answer)) {
  72. correct.getAndSet(correct.get() + 1);
  73. }
  74. });
  75. BigDecimal score = BigDecimal.valueOf(correct.get() * 100).divide(BigDecimal.valueOf(questionVOList.size()), 2, RoundingMode.HALF_UP);
  76. // 计算完毕
  77. quizStudentAnswer.setQuiz(quiz)
  78. .setStudent(student)
  79. .setAnswers(quizStudentAnswerDTO.getAnswers())
  80. .setSubmitNumber(quizStudentAnswer.getSubmitNumber() + 1)
  81. .setAnswers(answers)
  82. .setScore(score);
  83. return new QuizStudentAnswerVO(quizStudentAnswerDAO.save(quizStudentAnswer), questionVOList);
  84. }
  85. @Transactional(readOnly = true)
  86. @Override
  87. public Page<QuizStudentAnswerVO> getQuizStudentAnswers(LoginUser user, Long quizId, Pageable pageable) {
  88. return quizStudentAnswerDAO.findByQuiz(quizDAO.findQuizById(quizId), pageable).map(quizStudentAnswer -> new QuizStudentAnswerVO(quizStudentAnswer, questionService.getQuestionsByQuiz(quizDAO.findQuizById(quizId))));
  89. }
  90. @Transactional(readOnly = true)
  91. @Override
  92. public QuizStudentAnswerVO getQuizStudentAnswer(LoginUser user, Long quizId) {
  93. return quizStudentAnswerDAO
  94. .findByQuizAndStudent(quizDAO.findQuizById(quizId), userDAO.findUserById(user.getId()))
  95. .map(quizStudentAnswer -> new QuizStudentAnswerVO(quizStudentAnswer, questionService.getQuestionsByQuiz(quizDAO.findQuizById(quizId))))
  96. .orElse(null);
  97. }
  98. @Transactional(readOnly = true)
  99. @Override
  100. public QuizStudentAnswerStatisticVO getQuizStudentAnswerStatistic(LoginUser user, Long quizId) {
  101. List<QuizStudentAnswer> quizStudentAnswers = quizStudentAnswerDAO.findByQuiz(quizDAO.findQuizById(quizId));
  102. Map<BigDecimal, Integer> scores = Maps.newHashMapWithExpectedSize(quizStudentAnswers.size());
  103. Map<Integer, Integer> submitNums = Maps.newHashMapWithExpectedSize(quizStudentAnswers.size());
  104. quizStudentAnswers.forEach(
  105. quizStudentAnswer -> {
  106. scores.merge(quizStudentAnswer.getScore(), 1, Integer::sum);
  107. submitNums.merge(quizStudentAnswer.getSubmitNumber(), 1, Integer::sum);
  108. }
  109. );
  110. return QuizStudentAnswerStatisticVO.of(quizId, scores, submitNums);
  111. }
  112. }