| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347 |
- package nju.seec.helper.service.impl;
- import nju.seec.helper.dao.*;
- import nju.seec.helper.dto.QuestionStudentAnswerDTO;
- import nju.seec.helper.entity.*;
- import nju.seec.helper.service.QuizService;
- import nju.seec.helper.util.BokUtil;
- import nju.seec.helper.util.enums.ExceptionType;
- import nju.seec.helper.util.enums.QuizState;
- import nju.seec.helper.util.enums.SlideState;
- import nju.seec.helper.util.enums.UserType;
- import nju.seec.helper.util.exception.HelperException;
- import nju.seec.helper.vo.quiz.BaseQuestionVO;
- import nju.seec.helper.vo.quiz.QuizResultVO;
- import nju.seec.helper.vo.quiz.QuizVO;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.data.domain.Page;
- import org.springframework.data.domain.Pageable;
- import org.springframework.stereotype.Service;
- import org.springframework.transaction.annotation.Transactional;
- import org.springframework.util.Assert;
- import java.util.*;
- import java.util.stream.Collectors;
- @Service
- public class QuizServiceImpl implements QuizService {
- private final SlideDAO slideDAO;
- private final QuizDAO quizDAO;
- private final QuizStudentAnswerDAO quizStudentAnswerDAO;
- private final ChooseDAO chooseDAO;
- private final CourseDAO courseDAO;
- private final UserDAO userDAO;
- private final BokUtil bokUtil;
- @Autowired
- public QuizServiceImpl(SlideDAO slideDAO, QuizDAO quizDAO, QuizStudentAnswerDAO quizStudentAnswerDAO, ChooseDAO chooseDAO, CourseDAO courseDAO, UserDAO userDAO, BokUtil bokUtil) {
- this.slideDAO = slideDAO;
- this.quizDAO = quizDAO;
- this.quizStudentAnswerDAO = quizStudentAnswerDAO;
- this.chooseDAO = chooseDAO;
- this.courseDAO = courseDAO;
- this.userDAO = userDAO;
- this.bokUtil = bokUtil;
- }
- @Override
- @Transactional(rollbackFor = Exception.class)
- public Quiz createQuiz(String name, Long uid, SlideState quizTime,
- Long slideId, List<String> questions){
- User teacher =new User();
- teacher.setId(uid);
- Slide slide = slideDAO.findSlideById(slideId);
- Course course = new Course();
- course.setId(slide.getCourseId());
- Quiz quiz = new Quiz();
- quiz.setCourse(course);
- quiz.setName(name);
- quiz.setQuestions(questions);
- quiz.setQuizTime(quizTime);
- quiz.setSlide(slide);
- quiz.setTeacher(teacher);
- checkQuizState(quiz,slide);
- quiz=quizDAO.saveAndFlush(quiz);
- return quiz;
- }
- @Override
- public String deleteQuiz(Long quizId) {
- Quiz quiz =quizDAO.findQuizById(quizId);
- if(quiz.getState()!=QuizState.NOT_STARTED){throw HelperException.of(ExceptionType.FORBIDDEN,"不能删除已经开始的测试!");}
- quizDAO.delete(quiz);
- return "delete success";
- }
- @Override
- @Transactional(rollbackFor = Exception.class)
- public Quiz modifyQuiz(Long quizId, String name, List<String> questions, SlideState quizTime, String slideId) {
- Quiz quiz =quizDAO.findQuizById(quizId);
- if(quiz.getState()!=QuizState.NOT_STARTED){throw HelperException.of(ExceptionType.FORBIDDEN,"不能修改已经开始的测试!");}
- if(name!=null) {
- quiz.setName(name);
- }
- if(questions!=null) {
- quiz.setQuestions(questions);
- }
- if(quizTime!=null) {
- quiz.setQuizTime(quizTime);
- checkQuizState(quiz,quiz.getSlide());
- }
- return quizDAO.saveAndFlush(quiz);
- }
- @Override
- public Page<Quiz> getAllBasicQuizByUser(Pageable pageable, QuizState state, Long uid) {
- User user=userDAO.findUserById(uid);
- //todo: 这里写的太狗屎了,可以用重写sql或者用实例查询
- if(user.getType().equals(UserType.STUDENT)){
- final Set<Long> courseIdsByStudentId = chooseDAO.findCourseIdsByStudentId(uid);
- final Set<Course> collect = courseIdsByStudentId.stream().map(i -> {
- Course c = new Course();
- c.setId(i);
- return c;
- }).collect(Collectors.toSet());
- if(state!=null){
- return quizDAO.findAllByCourseInAndState(collect,state,pageable);
- }else{
- return quizDAO.findAllByCourseIn(collect,pageable);
- }
- }else{
- if(state!=null){
- return quizDAO.findByTeacherAndState(user,state,pageable);
- }else{
- return quizDAO.findByTeacher(user,pageable);
- }
- }
- }
- @Override
- public List<QuizResultVO> getQuizResult(Long quizId) {
- Assert.notNull(quizId,"错误的测试!");
- final Quiz quiz = quizDAO.findQuizById(quizId);
- if(quiz.getState()!=QuizState.CLOSED){throw new RuntimeException("测试未关闭,无法得到测试结果");}
- List<QuizResultVO> retList=new ArrayList<>();
- final List<StudentScore> studentScoreList = quiz.getStudentScore();
- Map<Long,List<QuizStudentAnswer>> idQuizStudentAnswerMap=new HashMap<>();
- for(QuizStudentAnswer qsa:quizStudentAnswerDAO.findAllByQuiz(quiz)){
- idQuizStudentAnswerMap.computeIfAbsent(qsa.getStudent().getId(), k -> new ArrayList<>());
- idQuizStudentAnswerMap.get(qsa.getStudent().getId()).add(qsa);
- }
- for(StudentScore studentScore:studentScoreList){
- final User student = studentScore.getStudent();
- final List<QuizStudentAnswer> list = idQuizStudentAnswerMap.get(student.getId());
- retList.add(new QuizResultVO(studentScore,student,list));
- }
- return retList;
- }
- @Override
- public void modifySlideState(Slide slide) {
- final List<Quiz> quizzes = quizDAO.findAllBySlide(slide);
- quizzes.forEach(quiz->checkQuizState(quiz,slide));
- }
- @Override
- @Transactional(rollbackFor = Exception.class)
- public Integer upStudentAnswer(Long quizId, Long uid, List<QuestionStudentAnswerDTO> answers) {
- Assert.notNull(quizId,"错误的测试!");
- final Quiz quiz = quizDAO.findQuizById(quizId);
- if(quiz.getState()!=QuizState.ONGOING){throw HelperException.of(ExceptionType.FORBIDDEN,"不能提交尚未开始的作业!");}
- User student =new User();student.setId(uid);
- Set<QuizStudentAnswer> quizAnswers = quizStudentAnswerDAO.findByStudentAndQuiz(student,quiz);
- Set<String> questionIdSet = new HashSet<>(quiz.getQuestions());
- Map<String,QuizStudentAnswer> qsaMap=new HashMap<>(questionIdSet.size());
- for(QuizStudentAnswer qsa: quizAnswers){
- qsaMap.put(qsa.getQuestionId(),qsa);
- }
- //确定被更新或者新建的学生答案提交
- List<QuizStudentAnswer> quizStudentAnswers=new ArrayList<>();
- for(QuestionStudentAnswerDTO studentAnswer:answers){
- String id = studentAnswer.getQuestionId();
- String answer = studentAnswer.getStudentAnswer().toString();
- if(!questionIdSet.contains(id)){break;}
- if(qsaMap.get(id)!=null){
- if(qsaMap.get(id).getStudentAnswer().equals(answer)){
- continue;
- }
- qsaMap.get(id).setStudentAnswer(answer);
- System.out.println(answer);
- quizStudentAnswers.add(qsaMap.get(id));
- }else {
- QuizStudentAnswer qsa=QuizStudentAnswer.builder()
- .questionId(id).quiz(quiz).student(student).studentAnswer(answer)
- .build();
- quizStudentAnswers.add(qsa);
- }
- }
- Integer savedNum=quizStudentAnswers.size();
- quizStudentAnswerDAO.saveAll(quizStudentAnswers);
- return savedNum;
- }
- @Override
- public Page<Quiz> getAllBasicQuizBySlide(Long slideId, Pageable pageable, QuizState state, Long uid) {
- Assert.notNull(slideId,"错误的幻灯片!");
- Slide slide=new Slide();
- slide.setId(slideId);
- if(state!=null) {
- return quizDAO.findAllBySlideAndState(slide, state, pageable);
- }
- else {
- return quizDAO.findAllBySlide(slide, pageable);
- }
- }
- @Override
- @Transactional(rollbackFor = Exception.class)
- public QuizState checkQuizState(Quiz quiz, Slide slide) {
- int quizTime = quiz.getQuizTime().getNum();
- int slideTime = slide.getState().getNum();
- if (quiz.getId() == null){
- //未持久化的quiz
- quiz.setState(slideTime < quizTime ? QuizState.NOT_STARTED : QuizState.ONGOING);
- }
- else {
- //持久化后,不仅仅需要推进状态,还需要判分,保存等步骤
- if (slideTime < quizTime) {
- if(quiz.getState().equals(QuizState.NOT_STARTED)){return QuizState.NOT_STARTED;}
- //未开始
- quiz.setState(QuizState.NOT_STARTED);
- } else if (slideTime == quizTime) {
- if(quiz.getState().equals(QuizState.ONGOING)){return QuizState.ONGOING;}
- quiz.setState(QuizState.ONGOING);
- } else {
- if(quiz.getState().equals(QuizState.CLOSED)){return QuizState.CLOSED;}
- quiz.setState(QuizState.CLOSED);
- Set<QuizStudentAnswer> quizAnswers = quizStudentAnswerDAO.findAllByQuiz(quiz);
- final Set<Long> studentIds = chooseDAO.findStudentIdsByCourseId(slide.getCourseId());
- Student2QuestionId2Answer triadMap = new Student2QuestionId2Answer(studentIds, quiz.getQuestions().size());
- //将已经作答的学生答案加入
- for (QuizStudentAnswer answers : quizAnswers) {
- triadMap.addAnswer(answers);
- }
- //生成未作答的学生答案
- triadMap.fullAnswer(quiz);
- //检查答案,赋分
- triadMap.checkAnswerAndFullPass(bokUtil.bokFindByIdIn(quiz.getQuestions()), quiz);
- //保存现场
- quizStudentAnswerDAO.saveAll(triadMap.getAll());
- }
- quizDAO.save(quiz);
- }
- return quiz.getState();
- }
- @Override
- public QuizState checkQuizState(Long quizId, Long slideId){
- Quiz quiz=quizDAO.findQuizById(quizId);
- Slide slide=slideDAO.findSlideById(slideId);
- return checkQuizState(quiz,slide);
- }
- private class Student2QuestionId2Answer {
- Map<Long,Map<String,QuizStudentAnswer>> student2QuestionId2Answer;
- Student2QuestionId2Answer(Set<Long> studentIds, Integer quizQuestionSize) {
- student2QuestionId2Answer =new LinkedHashMap<>(studentIds.size());
- for(Long studentId:studentIds){
- Map<String,QuizStudentAnswer> questionId2Answer= new LinkedHashMap<>(quizQuestionSize);
- student2QuestionId2Answer.put(studentId,questionId2Answer);
- }
- }
- void addAnswer(QuizStudentAnswer answers){
- Map<String, QuizStudentAnswer> stringQuizStudentAnswerMap = student2QuestionId2Answer.get(answers.getStudent().getId());
- if(stringQuizStudentAnswerMap==null){
- return ;
- }
- stringQuizStudentAnswerMap.put(answers.getQuestionId(),answers);
- }
- void fullAnswer(Quiz quiz){
- List<String> questions=quiz.getQuestions();
- student2QuestionId2Answer.forEach((studentId, map)->{
- if(questions.size()!=map.size()){
- for(String questionId:questions){
- if(map.get(questionId)==null){
- User student =new User();student.setId(studentId);
- QuizStudentAnswer qsa=QuizStudentAnswer.builder()
- .questionId(questionId).quiz(quiz).student(student)
- .build();
- map.put(questionId,qsa);
- }
- }
- }
- });
- }
- void checkAnswerAndFullPass(List<BaseQuestionVO> questionVos, Quiz quiz){
- if(quiz.getStudentScore()==null){quiz.setStudentScore(new ArrayList<>(student2QuestionId2Answer.size()));}
- student2QuestionId2Answer.forEach((studentId, map)->{
- int passCount=0;
- for(BaseQuestionVO vo:questionVos){
- final String studentAnswer = map.get(vo.getQuestionId()).getStudentAnswer();
- boolean pass=vo.checkAnswer(studentAnswer);
- if(pass){passCount++;}
- map.get(vo.getQuestionId()).setPass(pass);
- }
- Double score = (100.0*passCount)/questionVos.size();
- User student =new User();student.setId(studentId);
- StudentScore studentScore=new StudentScore();
- studentScore.setQuizId(quiz.getId());
- studentScore.setScore(Long.valueOf(Math.round(score)).intValue());
- studentScore.setStudent(student);
- quiz.getStudentScore().add(studentScore);
- });
- }
- List<QuizStudentAnswer> getAll(){
- List<QuizStudentAnswer> list=new ArrayList<>();
- for(Long sid: student2QuestionId2Answer.keySet()){
- list.addAll(student2QuestionId2Answer.get(sid).values());
- }
- return list;
- }
- }
- @Override
- public QuizVO combineQuiz(Long quizId){
- Assert.notNull(quizId,"错误的测试!");
- final Quiz quizById = quizDAO.findQuizById(quizId);
- final List<BaseQuestionVO> questionVoS = bokUtil.bokFindByIdIn(quizById.getQuestions());
- return new QuizVO(quizById,questionVoS);
- }
- @Override
- public QuizVO combineQuizWithAnswer(Long quizId, Long uid,UserType userType){
- Assert.notNull(quizId,"错误的测试!");
- final Quiz quizById = quizDAO.findQuizById(quizId);
- User student =new User();
- student.setId(uid);
- if(userType==null||userType.equals(UserType.TEACHER)){
- //向老师展示
- List<BaseQuestionVO> questionVoS = bokUtil.bokFindByIdIn(quizById.getQuestions());
- return new QuizVO(quizById,questionVoS);
- }
- if(quizById.getState().equals(QuizState.NOT_STARTED)){
- //未开始看不到题目
- return new QuizVO(quizById);
- }
- List<BaseQuestionVO> questionVos = bokUtil.bokFindByIdIn(quizById.getQuestions());
- final Set<QuizStudentAnswer> quizAnswers = quizStudentAnswerDAO.findByStudentAndQuiz(student,quizById);
- Map<String,QuizStudentAnswer> qsaMap=new HashMap<>(quizAnswers.size());
- for(QuizStudentAnswer qsa: quizAnswers){
- qsaMap.put(qsa.getQuestionId(),qsa);
- }
- for(BaseQuestionVO vo:questionVos){
- if(qsaMap.get(vo.getQuestionId())!=null){
- vo.exAddAnswer(qsaMap.get(vo.getQuestionId()));
- }
- }
- return new QuizVO(quizById,questionVos);
- }
- }
|