package com.qxueyou.scc.exam.service.impl; import java.math.BigDecimal; import java.math.BigInteger; import java.util.*; import com.qxueyou.scc.base.util.*; import com.qxueyou.scc.exam.model.*; import com.qxueyou.scc.exam.service.IExamBatchService; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; import com.qxueyou.scc.base.model.Pager; import com.qxueyou.scc.base.model.Result; import com.qxueyou.scc.base.service.ICacheService; import com.qxueyou.scc.base.service.impl.CommonAppService; import com.qxueyou.scc.exam.service.IExamPaperService; import com.qxueyou.scc.exam.service.IExamService; import com.qxueyou.scc.exercise.model.ExerciseExamReGroup; import com.qxueyou.scc.exercise.model.ExerciseGroup; import com.qxueyou.scc.exercise.model.ExerciseItem; import com.qxueyou.scc.exercise.model.ExerciseItemSet; import com.qxueyou.scc.exercise.model.ExerciseRecord; import com.qxueyou.scc.exercise.service.IExerciseGroupService; import com.qxueyou.scc.exercise.service.IExerciseVerService; import com.qxueyou.scc.msg.model.MsgInfo; import com.qxueyou.scc.msg.service.IMsgInfoService; /** * 考试管理服务层 * * @author kevin * @createTime 2017-11-1 */ @Service public class ExamService extends CommonAppService implements IExamService { @Autowired ICacheService cacheService; @Autowired IExerciseVerService exerciseVerService; @Autowired IExamPaperService examPaperService; @Autowired IExerciseGroupService exerciseGroupService; @Autowired private StringRedisTemplate stringRedisTemplate; @Autowired IMsgInfoService msgInfoService; @Autowired IExamBatchService examBatchService; @Override public List list(String keyword,String classId,String subjectId,Short status, Integer pageSize,Integer pageNum) { StringBuffer hql = new StringBuffer(500); hql.append("from ExamInfo e where e.examName like ? and e.createId=? "); List params = CollectionUtils.newList('%' + keyword.trim() + '%',ClientUtils.getUserId()); if(status!=null){ hql.append(" and e.examStatus = ? "); params.add(status); } if(StringUtils.isNotEmpty(classId)){ hql.append(" and exists( select 1 from ExamBatchClassRe r where e.examId = r.examId and r.deleteFlag is false and r.classId=?) "); params.add(classId); } if(StringUtils.isNotEmpty(subjectId)){ hql.append(" and e.subjectId = ? "); params.add(subjectId); } hql.append(" and e.deleteFlag is false order by e.createTime desc"); return findList(hql.toString(),new Pager(pageSize, pageNum),params, ExamInfo.class); } @Override public int listCount(String keyword,String classId,String subjectId,Short status) { StringBuffer hql = new StringBuffer(500); hql.append("from ExamInfo e where e.examName like ? and e.createId=? "); List params = CollectionUtils.newList('%' + keyword.trim() + '%',ClientUtils.getUserId()); if(status!=null){ hql.append(" and e.examStatus = ? "); params.add(status); } if(StringUtils.isNotEmpty(classId)){ hql.append(" and exists( select 1 from ExamBatchClassRe r where e.examId = r.examId and r.deleteFlag is false and r.classId=?) "); params.add(classId); } if(StringUtils.isNotEmpty(subjectId)){ hql.append(" and e.subjectId = ? "); params.add(subjectId); } hql.append(" and e.deleteFlag is false"); return findCount(hql.toString(),params); } @Override public List listResult(String examId,String[] examBatchIds, String classId,String keyword, Integer pageSize, Integer pageNum) { StringBuffer hql = new StringBuffer(1000); hql.append("from ExamResultV v where v.studentName like :studentName"); Map params = CollectionUtils.newObjectMap("studentName", '%' + keyword.trim() + '%'); if(!StringUtils.isEmpty(examId)){ hql.append(" and v.examId=:examId"); params.put("examId", examId); } if(examBatchIds!=null && examBatchIds.length>0){ hql.append(" and v.id.examBatchId in (:examBatchIds)"); params.put("examBatchIds", examBatchIds); } if(!StringUtils.isEmpty(classId)){ hql.append(" and v.id.classId=:classId"); params.put("classId", classId); } hql.append(" order by v.id.examBatchId,v.score desc"); return this.findByComplexHql(hql.toString(), new Pager(pageSize,pageNum), params, ExamResultV.class); } @Override public int listResultCount(String examId,String[] examBatchIds,String classId,String keyword) { StringBuffer hql = new StringBuffer(1000); hql.append("from ExamResultV v where v.studentName like :studentName"); Map params = CollectionUtils.newObjectMap("studentName", '%' + keyword.trim() + '%'); if(!StringUtils.isEmpty(examId)){ hql.append(" and v.examId=:examId"); params.put("examId", examId); } if(examBatchIds!=null && examBatchIds.length>0){ hql.append(" and v.id.examBatchId in (:examBatchIds)"); params.put("examBatchIds", examBatchIds); } if(!StringUtils.isEmpty(classId)){ hql.append(" and v.id.classId=:classId"); params.put("classId", classId); } return this.findCountByComplexHql(hql.toString(),params); } @Override public List listStudentExam(String keyword, String [] classIds, String subjectId, Integer status, Integer pageSize, Integer pageNum,String userId) { StringBuffer hql = new StringBuffer(1000); hql.append("from ExamResultV v where v.examName like :examName and v.examStatus=:examStatus and v.userId=:userId and v.id.classId in (:classIds) "); Map params = CollectionUtils.newObjectMap("examName", keyword.trim()+'%',"examStatus",ExamInfo.STATUS_PUBLISH,"userId",userId,"classIds",classIds); if(!StringUtils.isEmpty(subjectId)){ hql.append(" and v.subjectId=:subjectId "); params.put("subjectId", subjectId); } //根据状态查询:1未开始,2未交卷,3已交卷,4逾期未交,5已批阅 if(status != null) { switch(status){ case 1:hql.append(" and v.status is null") ;break; case 2:hql.append(" and v.status = :status");params.put("status", ExerciseRecord.STATUS_SUBMIT);break; case 3:hql.append(" and v.status = :status");params.put("status", ExerciseRecord.STATUS_NOT_SUBMIT);break; case 4:hql.append(" and (v.status is null or v.status=0) and v.end_Time < sysdate() ");break; case 5:hql.append(" and v.status = :status");params.put("status", ExerciseRecord.STATUS_CHECK);break; default:break; } } hql.append(" order by v.startTime desc "); return this.findByComplexHql(hql.toString(),new Pager(pageSize,pageNum),params,ExamResultV.class); } @Override public List studentExam(String[] classIds) { StringBuffer hql = new StringBuffer(1000); hql.append("from ExamResultV v where v.examStatus=:examStatus and v.userId=:userId and v.id.classId in (:classIds)"); Map params = CollectionUtils.newObjectMap ("examStatus",ExamInfo.STATUS_PUBLISH,"userId",ClientUtils.getUserId(),"classIds",classIds); hql.append(" order by v.endTime desc "); return this.findByComplexHql(hql.toString(),params,ExamResultV.class); } @Override public int listStudentExamCount(String keyword,String [] classIds,String subjectId,Integer status) { StringBuffer hql = new StringBuffer(1000); hql.append("from ExamResultV v where v.examName like :examName and v.examStatus=:examStatus and v.userId=:userId and v.id.classId in (:classIds)"); Map params = CollectionUtils.newObjectMap("examName", keyword.trim() + '%',"examStatus",ExamInfo.STATUS_PUBLISH, "userId",ClientUtils.getUserId(),"classIds",classIds); if(!StringUtils.isEmpty(subjectId)){ hql.append(" and v.subjectId=:subjectId "); params.put("subjectId", subjectId); } //根据状态查询:1未开始,2未交卷,3已交卷,4逾期未交,5已批阅 if(status != null) { switch(status){ case 1:hql.append(" and v.status is null") ;break; case 2:hql.append(" and v.status = :status");params.put("status", ExerciseRecord.STATUS_SUBMIT);break; case 3:hql.append(" and v.status = :status");params.put("status", ExerciseRecord.STATUS_NOT_SUBMIT);break; case 4:hql.append(" and (v.status is null or v.status=0) and v.end_Time < sysdate() ");break; case 5:hql.append(" and v.status = :status");params.put("status", ExerciseRecord.STATUS_CHECK);break; default:break; } } return this.findCountByComplexHql(hql.toString(),params); } @Override public void addRemedy(String examId,Date startTime,Date endTime) { //根据考试ID获取考试信息 ExamInfo examInfo = queryExamDetail(examId); //根据考试ID获取对应的批次信息 String hql = "from ExamBatchInfo where examId=? and deleteFlag is false"; List list = this.find(hql, CollectionUtils.newList(examId), ExamBatchInfo.class); List remedylist = new ArrayList<>(list.size()); //根据考试ID获取对应的题目设置 List exerciseItemSets = queryExerciseItemSet(examId); List exerciseItemSetses = new ArrayList<>(exerciseItemSets.size()); //... List reExamPapers = examInfo.getReExamPapers(); List reExamPaperses = new ArrayList<>(reExamPapers.size()); //复制信息 ExamInfo examInfo1=new ExamInfo(); //重新指向一个对象并复制属性 BeanUtils.copyProperties(examInfo,examInfo1); //设置考试名称 examInfo1.setExamName(examInfo1.getExamName()+"(补考"+new Date().getTime()+")"); //设置新指向批次集合 examInfo1.setExamBatchInfos(remedylist); examInfo1.setExerciseItemSets(exerciseItemSetses); //设置新指向试卷集合 reExamPapers.forEach(reExamPaper -> reExamPaperses.add(reExamPaper)); examInfo1.setReExamPapers(reExamPaperses); String examremedyId = addExam(examInfo1); //设置新指向题目设置集合并复制添加 exerciseItemSets.forEach(exerciseItemSet -> { ExerciseItemSet exerciseItemSet1 = new ExerciseItemSet(); BeanUtils.copyProperties(exerciseItemSet,exerciseItemSet1); exerciseItemSet1.setExerciseInfoId(examremedyId); TraceUtils.setCreateTrace(exerciseItemSet1); this.insert(exerciseItemSet1); exerciseItemSetses.add(exerciseItemSet1); }); //根据考试ID获取题库关联信息 String ql = "from ExerciseExamReGroup where examId=? and deleteFlag is false"; List exerciseExamReGroups = this.find(ql, CollectionUtils.newList(examId), ExerciseExamReGroup.class); exerciseExamReGroups.forEach(exerciseExamReGroup -> { ExerciseExamReGroup exerciseExamReGroup1 = new ExerciseExamReGroup(); BeanUtils.copyProperties(exerciseExamReGroup,exerciseExamReGroup1); //设置考试ID保存信息 exerciseExamReGroup1.setExamId(examremedyId); TraceUtils.setCreateTrace(exerciseExamReGroup1); this.insert(exerciseExamReGroup1); }); //循环复制批次 for (ExamBatchInfo examBatchInfo : list) { String remedyExamBatchId = UUIDUtils.generateSpecialUuid(32); List reClasses = examBatchInfo.getReClasses(); List examBatchClassRes = new ArrayList<>(); reClasses.forEach(reClass -> { //新建bean ExamBatchClassRe examBatchClassRe = new ExamBatchClassRe(); //复制属性 BeanUtils.copyProperties(reClass,examBatchClassRe); //修改考试ID以及批次ID examBatchClassRe.setExamId(examremedyId); examBatchClassRe.setExamBatchId(remedyExamBatchId); examBatchClassRe.setExamClassReId(UUIDUtils.generateSpecialUuid(32)); examBatchClassRes.add(examBatchClassRe); }); ExamBatchInfo examBatchInfo1 = new ExamBatchInfo(); BeanUtils.copyProperties(examBatchInfo,examBatchInfo1); //设置批次考试ID为补考的ID examBatchInfo1.setExamId(examremedyId); //设置开始结束时间 examBatchInfo1.setStartTime(startTime); examBatchInfo1.setEndTime(endTime); examBatchInfo1.setExamBatchId(remedyExamBatchId); examBatchInfo1.setReClasses(examBatchClassRes); //添加批次 examBatchService.addExamBatch(examBatchInfo1); remedylist.add(examBatchInfo1); } } @Override public String addExam(ExamInfo examInfo) { TraceUtils.setCreateTrace(examInfo); examInfo.setExamStatus(ExamInfo.STATUS_DRAFT); this.insert(examInfo); return examInfo.getExamId(); } @Override public Result deleteExam(String[] examIds) { Result result = new Result(true); if (examIds != null && examIds.length > 0) { String hql = "update ExamInfo set deleteFlag = true where examId=?"; //判断ID里是否包含补考考试 ExamInfo examInfo = queryReExam(); if (examInfo!=null) { for (String examId : examIds) { if (examId.equals(examInfo.getExamId())){ result.setSuccess(false); result.setMsg("含有补考考试,不可删除"); return result; } } } result = bulkUpdateInLoop(hql, examIds); } return result; } @Override public Result updateExam(ExamInfo param) { ExamInfo examInfo = read(ExamInfo.class, param.getExamId()); if (examInfo == null) { return new Result(false, "考试不存在"); } TraceUtils.setUpdateTrace(examInfo); examInfo.setExamName(param.getExamName()); examInfo.setSubjectId(param.getSubjectId()); examInfo.setDurationMin(param.getDurationMin()); // examInfo.setMaxLateMin(param.getMaxLateMin()); examInfo.setShowCorrectAnswer(param.getShowCorrectAnswer()); examInfo.setShowScore(param.getShowScore()); examInfo.setShowAnalyse(param.getShowAnalyse()); examInfo.setShowType(param.getShowType()); examInfo.setShowScoreTime(param.getShowScoreTime()); return save(examInfo); } @Override public Result updateExamPaperInfo(ExamInfo param) { ExamInfo examInfo = read(ExamInfo.class, param.getExamId()); if (examInfo != null) { TraceUtils.setUpdateTrace(examInfo); examInfo.setExamType(param.getExamType()); examInfo.setTotalScore(param.getTotalScore()); examInfo.setPassingScore(param.getPassingScore()); //如果是随机组卷 if(ExamInfo.EXAM_TYPE_RANDOM==examInfo.getExamType()||ExamInfo.EXAM_TYPE_RANDOM_BY_GROUP==examInfo.getExamType()){ // 删除之前的Exercise关联的group this.bulkUpdate("update ExerciseExamReGroup set deleteFlag = 1 where examId = ?",new Object[] { param.getExamId()}); List lstExerciseItemSet = param.getExerciseItemSets(); // 保存题目类型 if (lstExerciseItemSet != null && lstExerciseItemSet.size() > 0) { // 删除历史数据 this.bulkUpdate("update ExerciseItemSet set deleteFlag = 1 where deleteFlag is false and exerciseInfoId = ?", new Object[] { param.getExamId()}); for (ExerciseItemSet itemSet : lstExerciseItemSet) { TraceUtils.setCreateTrace(itemSet); itemSet.setExerciseInfoId(param.getExamId()); this.save(itemSet); } } //保存考试,源题目组信息 String [] sourceGroupIds = param.getSourceGroupIds().split(","); // 保存关联练习组 if (sourceGroupIds != null && sourceGroupIds.length > 0) { ExerciseExamReGroup reGroup = null; for (String groupId : sourceGroupIds) { reGroup = new ExerciseExamReGroup(); reGroup.setGroupId(groupId); reGroup.setDeleteFlag(false); reGroup.setType(ExerciseExamReGroup.GROUP_TYPE_SOURCE); reGroup.setExamId(param.getExamId()); TraceUtils.setCreateTrace(reGroup); this.save(reGroup); } } }else{ // 删除原来的关联关系 String hql = "update ExamReExamPaper set deleteFlag = true where examId=? "; this.bulkUpdate(hql, new Object[] { param.getExamId() }); List lstExamReExamPaper = param.getReExamPapers(); String[] arrPaperCode = new String[] { "A", "B", "C", "D" }; if (lstExamReExamPaper != null && lstExamReExamPaper.size() > 0) { for (int i = 0; i < lstExamReExamPaper.size(); i++) { TraceUtils.setCreateTrace(lstExamReExamPaper.get(i)); lstExamReExamPaper.get(i).setExamPaperId(lstExamReExamPaper.get(i).getExamPaperId()); lstExamReExamPaper.get(i).setExamId(param.getExamId()); lstExamReExamPaper.get(i).setRelationPaperCode(arrPaperCode[i]); this.insert(lstExamReExamPaper.get(i)); } } } } return save(examInfo); } @Override public Result doPublishExam(String[] examIds) { Map pramMap = null; if (examIds != null && examIds.length > 0) { pramMap = new HashMap(1); pramMap.put("examIds", examIds); String hql = "from ExamInfo where examId in (:examIds)"; List lstExamInfo = this.findByComplexHql(hql, pramMap, ExamInfo.class); for (ExamInfo examInfo : lstExamInfo) { if (ExamInfo.STATUS_DRAFT != examInfo.getExamStatus()) { return new Result(false, "只有草稿状态的考试,才能发布。"); } examInfo.setExamStatus(ExamInfo.STATUS_PUBLISH); TraceUtils.setUpdateTrace(examInfo); save(examInfo); this.doExamPublishMsg(examInfo.getExamId()); } } else { return new Result(false, "没有选择要发布的考试。"); } return new Result(true); } private void doExamPublishMsg(String examId){ ExamInfo examInfo = this.read(ExamInfo.class, examId); String hql = "select id.examBatchId as examBatchId,id.classId as classId,recordId as recordId ,userId as userId from ExamResultV where examId=:examId"; List> lstInfo = this.findListWithMapByHql(hql,CollectionUtils.newObjectMap("examId",examId)); if(lstInfo!=null && lstInfo.size()>0){ for(Map temp:lstInfo){ Map attrs = CollectionUtils.newStringMap("examId",examId,"examName",examInfo.getExamName(), "subjectId",examInfo.getSubjectId(),"subjectName",examInfo.getSubject().getName(), "examBatchId",(String)temp.get("examBatchId"),"classId",(String)temp.get("classId"),"recordId",(String)temp.get("recordId")); msgInfoService.doSendTextMsgToUsers(new String[]{(String)temp.get("userId")},MsgInfo.TYPE_EXAM, "发布了考试", attrs); } } } @Scheduled(cron = " 0 0/5 * * * ?") protected void doTimer() { // System.out.println("执行考试提醒定时器"); Calendar cal =Calendar.getInstance(); cal.add(Calendar.HOUR, 1); Date beginDate = cal.getTime(); cal.add(Calendar.MINUTE, 5); Date endDate = cal.getTime(); String hql = "select b.examBatchId from ExamBatchInfo b ,ExamInfo f where b.examId = f.examId " + " and b.startTime>=? and b.startTime lstBatchIds = this.find(hql,CollectionUtils.newList(beginDate,endDate,ExamInfo.STATUS_PUBLISH), String.class); if(lstBatchIds!=null && lstBatchIds.size()>0){ for(String batchId:lstBatchIds){ this.doExamRemindMsg(batchId,MsgInfo.TYPE_REMIND, "考试马上开始了,请做好考试准备"); } } } private void doExamRemindMsg(String batchId,short type,String msg){ ExamBatchInfo batchInfo = this.read(ExamBatchInfo.class, batchId); ExamInfo examInfo = batchInfo.getExamInfo(); Map attrs = CollectionUtils.newStringMap("examId",examInfo.getExamId(),"examName",examInfo.getExamName(),"remindType","exam", "subjectId",examInfo.getSubjectId(),"subjectName",examInfo.getSubject().getName(), "examBatchId",batchInfo.getExamBatchId(),"creator",batchInfo.getCreator(), "startTime",String.valueOf(batchInfo.getStartTime().getTime()), "endTime",String.valueOf(batchInfo.getEndTime().getTime()), "examBatchNo",String.valueOf(batchInfo.getExamBatchNo())); msgInfoService.doSendTextMsgToUsers(new String[]{batchInfo.getCreateId()},type, msg, attrs); } @Override public Result doRevokeExam(String[] examIds) { Map pramMap = null; if (examIds != null && examIds.length > 0) { pramMap = new HashMap(1); pramMap.put("examIds", examIds); String hql = "from ExamInfo where examId in (:examIds)"; List lstExamInfo = this.findByComplexHql(hql, pramMap, ExamInfo.class); for (ExamInfo examInfo : lstExamInfo) { if (ExamInfo.STATUS_PUBLISH != examInfo.getExamStatus()) { return new Result(false, "只有发布状态的考试,才能撤回"); } examInfo.setExamStatus(ExamInfo.STATUS_DRAFT); TraceUtils.setUpdateTrace(examInfo); save(examInfo); } } else { return new Result(false, "没有选择要撤回的考试"); } return new Result(true); } @Override public ExamInfo queryExamDetail(String examId) { ExamInfo examInfo = this.read(ExamInfo.class, examId); examInfo.setSubjectName(examInfo.getSubject().getName()); if(examInfo.getExamType() == ExamInfo.EXAM_TYPE_RANDOM || examInfo.getExamType() == ExamInfo.EXAM_TYPE_RANDOM_BY_GROUP){ List lstGroup = queryExamGroups(examId, ExerciseExamReGroup.GROUP_TYPE_SOURCE); examInfo.setSourceGroupIds(StringUtils.join(QBeanUtils.listPropertyVal(lstGroup, "groupId"),",")); examInfo.setSourceGroupNames(StringUtils.join(QBeanUtils.listPropertyVal(lstGroup, "name"),",")); } return examInfo; } @Override public ExamInfo queryReExam() { // 查询是否有进行中的考试 ExamInfo examInfo = this.findUnique( "from ExamInfo where maxLateMin=? and deleteFlag is false ", CollectionUtils.newList((short)1), ExamInfo.class); return examInfo; } /** * 开始考试 * * @param * @return */ @Override public Result doStartExam(String examBatchId, String classId, String studentUserId) { ExamBatchInfo examBatchInfo = this.read(ExamBatchInfo.class, examBatchId); ExamInfo examInfo = examBatchInfo.getExamInfo(); List lstItemSets = queryExerciseItemSet(examBatchInfo.getExamId()); ExerciseRecord record = this.doInitExerciseRecord(examBatchInfo, lstItemSets, classId, studentUserId); Map resultData = CollectionUtils.newObjectMap("exerciseRecordId", record.getRecordId(),"submitTime",record.getSubmitTime(), //TODO "remainingSeconds",record.getRemainingSeconds(),"itemSet", lstItemSets,"subjectName", examInfo.getSubject().getName()); // 如果已提交就查询用户答案信息 //TODO 暂时不可以查看考试答案,已提交就不可以进入 if (Integer.valueOf(record.getStatus())> 0) { resultData.put("studentScore", record.getScore()); resultData.put("objStudentScore", record.getObjScore()==null?BigDecimal.ZERO:record.getObjScore()); return new Result(false,"考试已提交"); } //获取考试 String ql="select i from ExamInfo i , ExamBatchClassRe r where i.deleteFlag is false and r.examBatchId=? and r.examId=i.examId"; ExamInfo exam = this.findUnique(ql, CollectionUtils.newList(examBatchId), ExamInfo.class); //添加考试总时长 resultData.put("durationMin",exam.getDurationMin()); resultData.put("groupId", record.getExerciseGroupId()); resultData.put("totalScore", examInfo.getTotalScore()); resultData.put("accuracy", record.getAccuracy()); resultData.put("userAnswers", this.queryUserAnswers(record.getRecordId())); resultData.put("paperInfo", this.getUserExamPaperInfo(record.getExerciseGroupId(),examInfo.getExamType(),(float)examInfo.getTotalScore(),lstItemSets)); return new Result(true,"",resultData); } /** * 开始补考考试 * * @param examId * @return */ @Override public Result doStartReExam(String examId,String studentUserId) { ExamInfo examInfo = this.read(ExamInfo.class, examId); List lstItemSets = queryExerciseItemSet(examId); ExerciseRecord record = this.doInitReExerciseRecord(examInfo, lstItemSets, studentUserId); Map resultData = CollectionUtils.newObjectMap("exerciseRecordId", record.getRecordId(),"submitTime",record.getSubmitTime(), //TODO "remainingSeconds",record.getRemainingSeconds(),"itemSet", lstItemSets,"subjectName", examInfo.getSubject().getName()); //添加考试总时长 resultData.put("durationMin",examInfo.getDurationMin()); resultData.put("groupId", record.getExerciseGroupId()); resultData.put("totalScore", examInfo.getTotalScore()); resultData.put("accuracy", record.getAccuracy()); resultData.put("userAnswers", this.queryUserAnswers(record.getRecordId())); resultData.put("paperInfo", this.getUserExamPaperInfo(record.getExerciseGroupId(),examInfo.getExamType(),(float)examInfo.getTotalScore(),lstItemSets)); return new Result(true,"",resultData); } /** * 判断是否是随机考试 * @param examType * @return */ private boolean checkIsRandomExam(short examType){ return ExamInfo.EXAM_TYPE_RANDOM==examType || ExamInfo.EXAM_TYPE_RANDOM_BY_GROUP==examType; } /** * 获取考试试卷信息 * @param examId * @param groupId * @param examType * @param totalSocre * @return */ private ExamPaperInfo getUserExamPaperInfo(String groupId,short examType,float totalSocre){ ExamPaperInfo examPaperInfo = null; if(checkIsRandomExam(examType)){ examPaperInfo= new ExamPaperInfo(); examPaperInfo.setGroupId(groupId); examPaperInfo.setTotalScore(new Float(totalSocre).shortValue()); examPaperInfo.setExerciseGroup(exerciseGroupService.queryExerciseGroupDetail(groupId)); List examPaperSectionInfos = new ArrayList<>(); examPaperInfo.setSectionInfos(examPaperSectionInfos); }else{ examPaperInfo = examPaperService.queryExamPaperByGroupId(groupId); examPaperInfo = examPaperService.queryExamPaperDetail(examPaperInfo.getExamPaperId()); } return examPaperInfo; } /** * 手动添加题目位置信息 * @param groupId * @param examType * @param totalSocre * @param lstItemSets * @return */ private ExamPaperInfo getUserExamPaperInfo(String groupId,short examType,float totalSocre,List lstItemSets){ ExamPaperInfo examPaperInfo = null; if(checkIsRandomExam(examType)){ examPaperInfo= new ExamPaperInfo(); examPaperInfo.setGroupId(groupId); //TODO examPaperInfo.setPaperStatus(new Integer(1).shortValue()); examPaperInfo.setOrgId("1"); examPaperInfo.setTotalScore(new Float(totalSocre).shortValue()); examPaperInfo.setExerciseGroup(exerciseGroupService.queryExerciseGroupDetail(groupId)); List examPaperSectionInfos = new ArrayList<>(); int count=0; for (int i=0;i0) { examPaperSectionInfo.setGroupId(groupId); //设置开始结束 examPaperSectionInfo.setItemStartOrder((short)count); //获取题目设置的count,下次循环用 count+=itemCount; examPaperSectionInfo.setItemEndOrder((short)count); //名称 examPaperSectionInfo.setSectionName(String.valueOf(lstItemSets.get(i).getItemType())); examPaperSectionInfos.add(examPaperSectionInfo); } } examPaperInfo.setSectionInfos(examPaperSectionInfos); }else{ examPaperInfo = examPaperService.queryExamPaperByGroupId(groupId); examPaperInfo = examPaperService.queryExamPaperDetail(examPaperInfo.getExamPaperId()); List examPaperSectionInfos = new ArrayList<>(); int count=0; //获取试卷里的各种题数量设置 Map statisticsMap = examPaperService.queryExamPaperItemsStatistic(new String[]{examPaperInfo.getExamPaperId()}); //把设置封装成itemSets lstItemSets=new ArrayList(); //单选 ExerciseItemSet exerciseItemSet1 = new ExerciseItemSet(); exerciseItemSet1.setItemCount(statisticsMap.get(examPaperInfo.getExamPaperId()).getSingleSelectCount()); exerciseItemSet1.setItemType((short) 1); lstItemSets.add(exerciseItemSet1); //多选 ExerciseItemSet exerciseItemSet2 = new ExerciseItemSet(); exerciseItemSet2.setItemCount(statisticsMap.get(examPaperInfo.getExamPaperId()).getMultiSelectCount()); exerciseItemSet2.setItemType((short) 2); lstItemSets.add(exerciseItemSet2); //判断 ExerciseItemSet exerciseItemSet3 = new ExerciseItemSet(); exerciseItemSet3.setItemCount(statisticsMap.get(examPaperInfo.getExamPaperId()).getJudgeCount()); exerciseItemSet3.setItemType((short) 3); lstItemSets.add(exerciseItemSet3); // ExerciseItemSet exerciseItemSet8 = new ExerciseItemSet(); exerciseItemSet8.setItemCount(statisticsMap.get(examPaperInfo.getExamPaperId()).getQuestionCount()); exerciseItemSet8.setItemType((short) 8); lstItemSets.add(exerciseItemSet8); // ExerciseItemSet exerciseItemSet4 = new ExerciseItemSet(); exerciseItemSet4.setItemCount(statisticsMap.get(examPaperInfo.getExamPaperId()).getFillBlanksCount()); exerciseItemSet4.setItemType((short) 4); lstItemSets.add(exerciseItemSet4); //将itemSets设置成页面要用到的ExamPaperSectionInfo设置 for (int i=0;i0) { examPaperSectionInfo.setGroupId(groupId); //设置开始结束 examPaperSectionInfo.setItemStartOrder((short)count); //获取题目设置的count,下次循环用 count+=itemCount; examPaperSectionInfo.setItemEndOrder((short)count); //名称 examPaperSectionInfo.setSectionName(String.valueOf(lstItemSets.get(i).getItemType())); examPaperSectionInfos.add(examPaperSectionInfo); } } examPaperInfo.setSectionInfos(examPaperSectionInfos); } return examPaperInfo; } /** * 获取用户答题信息 * @param recordId * @return */ private List> queryUserAnswers(String recordId){ return this.findListWithMapByHql( "select u.answerUId as answerUId, u.exerciseItemId as exerciseId,u.answer as answer,u.correct as correct,u.teacherScore as teacherScore,i.type as type" + " from ExerciseItemAnswerU u,ExerciseItem i where u.exerciseItemId = i.exerciseId and u.exerciseRecordId=:recordId and u.deleteFlag is false order by u.createTime asc ", CollectionUtils.newObjectMap("recordId", recordId)); } /** * 获取用户的考试记录,如果不存在则创建并返回 * @param examBatchInfo * @param itemSets * @param classId * @param studentUserId * @return */ private ExerciseRecord doInitExerciseRecord(ExamBatchInfo examBatchInfo,List itemSets,String classId,String studentUserId){ String[] examTypes = new String[] { "A", "B", "C", "D" }; String examBatchId = examBatchInfo.getExamBatchId(); String examId = examBatchInfo.getExamId(); short examBatchNo = examBatchInfo.getExamBatchNo(); short examType = examBatchInfo.getExamInfo().getExamType(); int remainingSeconds = examBatchInfo.getExamInfo().getDurationMin()*60; // 查询是否有进行中的考试 ExerciseRecord record = this.findUnique( "from ExerciseRecord where examBatchId=? and classId=? and userId = ? and deleteFlag is false ", CollectionUtils.newList(examBatchId,classId,StringUtils.isNotEmpty(studentUserId) ? studentUserId : ClientUtils.getUserId()), ExerciseRecord.class); if (record==null) { String groupId = null; String cacheKey = "EXAM_DO_COUNT_".concat(examBatchId); int doCount = this.getCachedRecordCount(cacheKey,examBatchId); //随机创建题目组 if(checkIsRandomExam(examType)){ String newGroupName = examId+"-"+examBatchNo+"-随机试卷题库-"+(++doCount); //查题库 List lstSourceGroup = queryExamGroups(examId, ExerciseExamReGroup.GROUP_TYPE_SOURCE); String[] sourceGroupIds = QBeanUtils.listPropertyVal(lstSourceGroup, "groupId").toArray(new String[lstSourceGroup.size()]); groupId = this.exerciseGroupService.doCreateRandomExerciseGroup(newGroupName,ExerciseGroup.TYPE_EXERCISE_EXAM_ITEM,sourceGroupIds,itemSets); }else{ groupId = examPaperService.queryExamPaperByCode(examId,examTypes[doCount % examType]).getGroupId(); } record = this.insertExerRecord(examBatchInfo,itemSets,groupId,classId,remainingSeconds); stringRedisTemplate.opsForValue().increment(cacheKey, 1); //+1 } return record; } /** * 创建补考考试记录 * @param examBatchInfo * @param itemSets * @param studentUserId * @return */ private ExerciseRecord doInitReExerciseRecord(ExamInfo examInfo,List itemSets,String studentUserId){ String[] examTypes = new String[] { "A", "B", "C", "D" }; // String examBatchId = examBatchInfo.getExamBatchId(); String examId = examInfo.getExamId(); // short examBatchNo = examBatchInfo.getExamBatchNo(); short examType = examInfo.getExamType(); int remainingSeconds = examInfo.getDurationMin()*60; //创建考试记录 String groupId = null; String cacheKey = "EXAM_DO_COUNT_".concat(examId); int doCount = this.getCachedRecordCount(cacheKey,examId); //随机创建题目组 if(checkIsRandomExam(examType)){ String newGroupName = examId+"-"+UUIDUtils.generateSpecialUuid(4)+"-随机试卷题库-"+(++doCount); //查题库 List lstSourceGroup = queryExamGroups(examId, ExerciseExamReGroup.GROUP_TYPE_SOURCE); String[] sourceGroupIds = QBeanUtils.listPropertyVal(lstSourceGroup, "groupId").toArray(new String[lstSourceGroup.size()]); groupId = this.exerciseGroupService.doCreateRandomExerciseGroup(newGroupName,ExerciseGroup.TYPE_EXERCISE_EXAM_ITEM,sourceGroupIds,itemSets); }else{ groupId = examPaperService.queryExamPaperByCode(examId,examTypes[doCount % examType]).getGroupId(); } ExerciseRecord record = this.insertReExerRecord(examInfo,itemSets,groupId,remainingSeconds); stringRedisTemplate.opsForValue().increment(cacheKey, 1); //+1 return record; } // 获取正在做试卷的学生数 private int getCachedRecordCount(String cacheKey,String examBatchId){ String cacheCount = stringRedisTemplate.opsForValue().get(cacheKey); int doCount = StringUtils.isEmpty(cacheCount) ? 0 : Integer.valueOf(cacheCount); if (doCount == 0) { doCount = this.findCount("from ExerciseRecord where examBatchId=? and deleteFlag is false", CollectionUtils.newList(examBatchId)); } return doCount; } private ExerciseRecord insertExerRecord(ExamBatchInfo examBatchInfo,List itemSets,String groupId,String classId,int remainingSeconds) { ExamInfo examInfo = examBatchInfo.getExamInfo(); ExerciseRecord record = new ExerciseRecord(); record.setDeleteFlag(false); record.setExerciseGroupId(groupId); record.setExamBatchId(examBatchInfo.getExamBatchId()); record.setDoCount(BigInteger.ZERO); record.setCorrectCount(BigInteger.ZERO); record.setTitleMaxNumber("0"); record.setStatus("0"); record.setClassId(classId); record.setRemainingSeconds(remainingSeconds); record.setScore(BigDecimal.ZERO); record.setUserId(ClientUtils.getUserId()); record.setOrgId(ClientUtils.getOrgId()); //获取考试题目统计信息,并保存 Map result = this.queryItemStatics(itemSets, groupId); record.setTotalScore(new BigDecimal(examInfo.getTotalScore())); record.setPassingScore(new BigDecimal(examInfo.getPassingScore())); record.setSubTotalScore((BigDecimal)result.get("subTotalScore")); record.setObjTotalScore((BigDecimal)result.get("objTotalScore")); record.setSubItemCount((int)result.get("subItemCount")); record.setObjItemCount((int)result.get("objItemCount")); TraceUtils.setCreateTrace(record); this.save(record); return record; } //设置补考考试记录 private ExerciseRecord insertReExerRecord(ExamInfo examInfo,List itemSets,String groupId,int remainingSeconds) { // ExamInfo examInfo = examBatchInfo.getExamInfo(); ExerciseRecord record = new ExerciseRecord(); record.setDeleteFlag(false); record.setExerciseGroupId(groupId); //因为没有批次,所有时间所有人都可以考,所以这里将批次ID设置成考试ID record.setExamBatchId(examInfo.getExamId()); record.setDoCount(BigInteger.ZERO); record.setCorrectCount(BigInteger.ZERO); record.setTitleMaxNumber("0"); record.setStatus("0"); //不设置classID // record.setClassId(classId); record.setRemainingSeconds(remainingSeconds); record.setScore(BigDecimal.ZERO); record.setUserId(ClientUtils.getUserId()); record.setOrgId(ClientUtils.getOrgId()); //获取考试题目统计信息,并保存 Map result = this.queryItemStatics(itemSets, groupId); record.setTotalScore(new BigDecimal(examInfo.getTotalScore())); record.setPassingScore(new BigDecimal(examInfo.getPassingScore())); record.setSubTotalScore((BigDecimal)result.get("subTotalScore")); record.setObjTotalScore((BigDecimal)result.get("objTotalScore")); record.setSubItemCount((int)result.get("subItemCount")); record.setObjItemCount((int)result.get("objItemCount")); TraceUtils.setCreateTrace(record); this.save(record); return record; } /** * 获取补考记录集合 * @param examId * @param userId * @return */ @Override public Result getReExamRecordList(String examId, String userId) { // 查询是否有进行中的考试 List exerciseRecords = this.find( "from ExerciseRecord where examBatchId=? and userId = ? and deleteFlag is false ", CollectionUtils.newList(examId, StringUtils.isNotEmpty(userId) ? userId : ClientUtils.getUserId()), ExerciseRecord.class); return new Result(true,"",exerciseRecords); } private Map queryItemStatics(List itemSets,String groupId){ float subTotalScore = 0,objTotalScore=0; int subItemCount=0,objItemCount=0; //如果是随机组卷 if(itemSets!=null && itemSets.size()>0){ for(ExerciseItemSet s:itemSets){ if(s.getItemType()==ExerciseItem.TYPE_ESSAY_QUESTION){ subTotalScore+= s.getItemCount()*s.getRightScore(); subItemCount+=s.getItemCount(); }else{ objTotalScore += s.getItemCount()*s.getRightScore(); objItemCount += s.getItemCount(); } } }else{ List lstItems = this.find("from ExamItemV where id.groupId=?",CollectionUtils.newList(groupId),ExamItemV.class); if(lstItems!=null && lstItems.size()>0){ for(ExamItemV v: lstItems){ if(v.getItemType()==ExerciseItem.TYPE_ESSAY_QUESTION){ subTotalScore+= v.getItemScore(); ++subItemCount; }else{ objTotalScore += v.getItemScore(); ++objItemCount; } } } } Map result = new HashMap(); result.put("subTotalScore", new BigDecimal(subTotalScore)); result.put("objTotalScore", new BigDecimal(objTotalScore)); result.put("subItemCount", subItemCount); result.put("objItemCount", objItemCount); return result; } @Override public int getExamCount(String classId, String userId) { // 查询记录数 String hqlCount = "from ExamInfo i, ExamBatchInfo b,ExamBatchClassRe r WHERE " + " i.examId=b.examId and b.examBatchId = r.examBatchId AND r.classId =:classId AND i.examStatus=:examStatus AND b.deleteFlag is false AND r.deleteFlag is false "; int examCount = findCountByComplexHql(hqlCount, CollectionUtils.newObjectMap("classId", classId, "examStatus", ExamInfo.STATUS_PUBLISH)); return examCount; } /** * 查询考试关联的题目组 * @param examId * @param * @return 题目组Map */ private List queryExamGroups(String examId,Short reType){ return this.find( "select p from ExerciseExamReGroup g,ExerciseGroup p where g.groupId = p.groupId and g.examId=? and g.type=? and g.deleteFlag is false", CollectionUtils.newList(examId,reType) , ExerciseGroup.class); } /** * 查询考试关联的题目配置信息 * @param examId * @param * @return */ private List queryExerciseItemSet(String examId){ return this.find( "from ExerciseItemSet s where s.deleteFlag is false and s.exerciseInfoId=?", CollectionUtils.newList(examId) , ExerciseItemSet.class); } @Override public int getUnCommitExamCount(String classId, String userId) { String sql = "SELECT c.exam_id, c.exam_name, c.exam_batch_Id, c.start_Time, c.end_Time, " + "c.class_id, d.exercise_Group_Id, d.score, d. STATUS FROM ( SELECT i.exam_Id, " + "i.exam_Name, b.exam_Batch_Id, b.start_Time,b.end_Time, r.class_Id FROM Exam_Info i, " + "Exam_Batch_Info b, Exam_Class_Re r WHERE i.exam_Id = b.exam_Id AND b.exam_Batch_Id " + "= r.exam_Batch_Id AND r.class_Id =:classId AND i.exam_status = 1 AND b.delete_Flag" + "= 0 AND r.delete_Flag = 0 ) c LEFT OUTER JOIN ( SELECT * FROM Exercise_Record " + "d WHERE d.delete_Flag = 0 AND d.user_id =:userId ) d ON c.exam_Batch_Id = d.exam_Batch_Id " + "AND c.class_id = d.class_id where ifnull(d.status,0)= 0 and (c.end_Time - CURRENT_TIMESTAMP ()) < 0 "; List list = findByComplexSql(sql, CollectionUtils.newObjectMap("classId", classId, "userId", userId), Object[].class); return list.size(); } @Override public int getToBeCommitExamCount(String classId, String userId) { String sql = "SELECT c.exam_id, c.exam_name, c.exam_batch_Id, c.start_Time, c.end_Time, " + "c.class_id, d.exercise_Group_Id, d.score, d. STATUS FROM ( SELECT i.exam_Id, " + "i.exam_Name, b.exam_Batch_Id, b.start_Time,b.end_Time, r.class_Id FROM Exam_Info i, " + "Exam_Batch_Info b, Exam_Class_Re r WHERE i.exam_Id = b.exam_Id AND b.exam_Batch_Id " + "= r.exam_Batch_Id AND r.class_Id =:classId AND i.exam_status = 1 AND b.delete_Flag" + "= 0 AND r.delete_Flag = 0 ) c LEFT OUTER JOIN ( SELECT * FROM Exercise_Record " + "d WHERE d.delete_Flag = 0 AND d.user_id =:userId ) d ON c.exam_Batch_Id = d.exam_Batch_Id " + "AND c.class_id = d.class_id where ifnull(d.status,0)= 0 and (c.end_Time - CURRENT_TIMESTAMP ()) > 0 "; List list = findByComplexSql(sql, CollectionUtils.newObjectMap("classId", classId, "userId", userId), Object[].class); return list.size(); } @Override public int getCommitExamCount(String classId, String userId) { String sql = "SELECT c.exam_id, c.exam_name, c.exam_batch_Id, c.start_Time, c.end_Time, " + "c.class_id, d.exercise_Group_Id, d.score, d. STATUS FROM ( SELECT i.exam_Id, " + "i.exam_Name, b.exam_Batch_Id, b.start_Time,b.end_Time, r.class_Id FROM Exam_Info i, " + "Exam_Batch_Info b, Exam_Class_Re r WHERE i.exam_Id = b.exam_Id AND b.exam_Batch_Id " + "= r.exam_Batch_Id AND r.class_Id =:classId AND i.exam_status = 1 AND b.delete_Flag" + "= 0 AND r.delete_Flag = 0 ) c LEFT OUTER JOIN ( SELECT * FROM Exercise_Record " + "d WHERE d.delete_Flag = 0 AND d.user_id =:userId ) d ON c.exam_Batch_Id = d.exam_Batch_Id " + "AND c.class_id = d.class_id where d.status > 0"; List list = findByComplexSql(sql, CollectionUtils.newObjectMap("classId", classId, "userId", userId), Object[].class); return list.size(); } @Override public Map queryExamResultStatusCount(List lstExamIds) { if(lstExamIds == null || lstExamIds.size()==0){ return null; } String hql = "select examId||'-'||status ,count(1) from ExamResultV " + "where examId in(:examIds) group by examId,status"; List lstResult = this.findByComplexHql(hql, CollectionUtils.newObjectMap("examIds",lstExamIds.toArray(new String[lstExamIds.size()])), Object[].class); Map resultMap = new HashMap(lstResult.size()); for(Object[] o:lstResult){ resultMap.put((String)o[0],((Long)o[1]).intValue()); } return resultMap; } }