package com.qxgmat.service.inline; import com.github.pagehelper.Page; import com.nuliji.tools.AbstractService; import com.nuliji.tools.PageResult; import com.nuliji.tools.Transform; import com.nuliji.tools.exception.ParameterException; import com.nuliji.tools.exception.SystemException; import com.nuliji.tools.mybatis.Example; import com.qxgmat.data.constants.enums.module.StructModule; import com.qxgmat.data.constants.enums.status.DirectionStatus; import com.qxgmat.data.dao.QuestionNoMapper; import com.qxgmat.data.dao.entity.Question; import com.qxgmat.data.dao.entity.QuestionNo; import com.qxgmat.data.dao.entity.UserCollectQuestion; import com.qxgmat.data.dao.entity.UserQuestion; import com.qxgmat.data.inline.PaperStat; import com.qxgmat.data.relation.QuestionNoRelationMapper; import com.qxgmat.data.relation.entity.QuestionDifficultRelation; import com.qxgmat.data.relation.entity.QuestionNoRelation; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import javax.annotation.Resource; import java.util.*; import java.util.stream.Collectors; @Service public class QuestionNoService extends AbstractService { private static final Logger logger = LoggerFactory.getLogger(QuestionNoService.class); protected boolean SOFT_FLAG = false; @Resource private QuestionNoMapper questionNoMapper; @Resource private QuestionNoRelationMapper questionNoRelationMapper; @Resource private QuestionService questionService; /** * 根据题干搜索相似题目: 相似度80% * @param page * @param size * @param stem * @return */ public PageResult searchStem(int page, int size, String stem){ // String[] stems = stem.replaceAll("\\.?,?!?:?;?\\??", "").split(" "); Page p = page(()->{ questionNoRelationMapper.searchStem(stem); }, page, size); Collection ids = Transform.getIds(p, QuestionNo.class, "id"); // 获取详细数据 List list = select(ids); return new PageResult<>(relation(list), p.getTotal()); } /** * 根据题目编号搜索相似题目 * @param page * @param size * @param keyword * @param module * @return */ public PageResult searchNo(int page, int size, String keyword, String module, Integer[] ids){ Example example = new Example(QuestionNo.class); if(keyword != null) example.and( example.createCriteria() .andLike("title", "%"+keyword+"%") ); if (module != null) example.and( example.createCriteria() .andEqualTo("module", module) ); if (ids != null) example.and( example.createCriteria() .andIn("id", Arrays.stream(ids).collect(Collectors.toList())) ); example.and( example.createCriteria() .andIsNull("deleteTime") ); example.orderBy("id").asc(); Page p = page(()->select(questionNoMapper, example), page, size); logger.info("SearchNo result: {}", p.toString()); return new PageResult<>(relation(p), p.getTotal()); } /** * 根据题目编号搜索相似题目 * @param page * @param size * @param keyword * @return */ public Page searchStemFulltext(int page, int size, String keyword, String[] questionTypes, String module, Integer[] structIds, String place, String difficult, Integer qxCatId, String order, DirectionStatus direction){ if (direction == null){ direction = DirectionStatus.DESC; } String finalOrder = order; DirectionStatus finalDirection = direction; Page p = page(()->{ questionNoRelationMapper.searchStemFulltext(keyword, questionTypes, module, structIds, place, difficult, qxCatId, finalOrder, finalDirection.key); }, page, size); Collection ids = Transform.getIds(p, QuestionNo.class, "id"); // 获取详细数据 List list = select(ids); List relationList = relation(list); Transform.replace(p, relationList, QuestionNoRelation.class, "id"); return p; } /** * 根据题目编号搜索相似题目 * @param page * @param size * @param keyword * @return */ public Page searchNoFulltext(int page, int size, String keyword, String module, Integer qxCatId){ Page p = page(()->{ questionNoRelationMapper.searchNoFulltext(keyword, module, qxCatId); }, page, size); Collection ids = Transform.getIds(p, QuestionNo.class, "id"); // 获取详细数据 List list = select(ids); Transform.replace(p, list, QuestionNo.class, "id"); return p; } /** * 获取结构模块下的题目列表: 按序号排列 * @param module * @param structId * @return */ public List listByStruct(StructModule module, Integer structId){ Example example = new Example(QuestionNo.class); example.and( example.createCriteria() .andEqualTo("module", module.key) .andGreaterThan("questionId", 0) .andCondition(String.format(formatSet, structId, "module_struct")) ); example.and( example.createCriteria() .andIsNull("deleteTime") ); example.orderBy("no").asc(); return select(questionNoMapper, example); } /** * 获取结构模块下的题目列表: 按序号排列 * @param module * @param structIds * @return */ public List listByStruct(StructModule module, Integer[] structIds){ Example example = new Example(QuestionNo.class); example.and( example.createCriteria() .andEqualTo("module", module.key) .andGreaterThan("questionId", 0) ); if (structIds != null){ Example.Criteria criteria = example.createCriteria(); for(Integer structId : structIds){ criteria.orCondition(String.format(formatSet, structId, "module_struct")); } example.and(criteria); } example.and( example.createCriteria() .andIsNull("deleteTime") ); example.orderBy("no").asc(); return select(questionNoMapper, example); } /** * 获取结构模块下的题目列表: 按序号排列 * @param module * @param structId * @return */ public List listWithRelationByStruct(StructModule module, Integer structId){ return relation(listByStruct(module, structId)); } /** * 根据题目标号列表获取题目 * @param nos * @param module * @return */ public List listWithRelationByNos(String[] nos, String module){ if (nos.length == 0) return new ArrayList<>(); Example example = new Example(QuestionNo.class); example.and( example.createCriteria() .andIn("no", Arrays.stream(nos).collect(Collectors.toList())) ); if (module != null) example.and( example.createCriteria() .andEqualTo("module", module) ); example.and( example.createCriteria() .andIsNull("deleteTime") ); List p = select(questionNoMapper, example); return relation(p); } /** * 根据题目获取关联的题目编号 * @param questionId * @return */ public List listByQuestion(Number questionId){ Example example = new Example(QuestionNo.class); example.and( example.createCriteria() .andEqualTo("questionId", questionId) ); example.and( example.createCriteria() .andIsNull("deleteTime") ); return select(questionNoMapper, example); } /** * 根据题目编号id列表获取关联题目 * @param ids * @return */ public List listWithRelationByIds(Number[] ids){ List p = select(questionNoMapper, ids); return relation(p); } /** * 根据题目编号id列表获取关联题目 * @param ids * @return */ public Map mapWithRelationByIds(Number[] ids){ List p = select(questionNoMapper, ids); List list = relation(p); Map map = new HashMap<>(); for(QuestionNoRelation relation : list){ map.put(relation.getId(), relation); } return map; } /** * 根据题目编号id获取关联题目 * @param id * @return */ public QuestionNoRelation getWithRelation(Number id){ QuestionNo questionNo = get(id); return relation(questionNo); } /** * 随机获取对应模块下的试题:排除已做试题 * @param structId * @param filterIds * @return */ public Integer randomExamination(Integer structId, Collection targetTypes, Collection filterIds){ List questionNoList = questionNoRelationMapper.randomExamination(structId, targetTypes, filterIds, 1); if (questionNoList.size() > 0){ return questionNoList.get(0).getId(); }else{ return null; } } /** * 随机批量获取对应模块下的试题:排除已做试题 * @param structId * @param targetTypes * @param filterIds * @param size * @return */ public Integer[] randomExaminationList(Integer structId, Collection targetTypes, Collection filterIds, Integer size){ List questionNoList = questionNoRelationMapper.randomExamination(structId, targetTypes, filterIds, size); if (questionNoList.size() > 0){ Integer[] ids = new Integer[questionNoList.size()]; for(int i = 0; i< questionNoList.size(); i++){ ids[i] = questionNoList.get(i).getId(); } return ids; }else{ return new Integer[0]; } } /** * 获取该struct下指定类型的所有题目信息 * @param structId * @param targetTypes * @return */ public List allExaminationByType(Integer structId, Collection targetTypes){ return questionNoRelationMapper.allExaminationByType(structId, targetTypes); } /** * 随机查找模考阅读题 * @param structId * @param number * @param filterIds * @return */ public Integer[] randomExaminationRc(Integer structId, Integer number, Collection filterIds){ Example example = new Example(QuestionNo.class); example.and( example.createCriteria() .andGreaterThan("questionId", 0) .andCondition(String.format(formatSet, structId, "module_struct")) .andEqualTo("relationNumber", number) .andNotIn("id", filterIds) ); example.and( example.createCriteria() .andIsNull("deleteTime") ); example.setOrderByClause("RAND()"); QuestionNo questionNo = one(questionNoMapper, example); if (questionNo == null){ throw new ParameterException("阅读题查找失败"); } return Arrays.stream(questionNo.getRelationQuestion()).boxed().toArray(Integer[]::new); } /** * 绑定no和question * @param ids * @param questionId * @return */ public Boolean bindQuestion(Integer[] ids, Integer questionId){ if (ids == null || ids.length == 0) return false; Example example = new Example(QuestionNo.class); example.and( example.createCriteria() .andIn("id", Arrays.stream(ids).collect(Collectors.toList())) ); int result = update(questionNoMapper, example, QuestionNo.builder() .questionId(questionId) .deleteTime(null) .build()); return result > 0; } /** * 设定编号关联关系, 并设定题目数量 * @param ids * @return */ public Boolean relationQuestion(int[] ids){ if (ids.length == 0) return false; Example example = new Example(QuestionNo.class); example.and( example.createCriteria() .andIn("id", Arrays.stream(ids).boxed().collect(Collectors.toList())) ); int result = update(questionNoMapper, example, QuestionNo.builder() .relationQuestion(ids) .relationNumber(ids.length) .deleteTime(null) .build()); return result > 0; } /** * 根据题目获取总试卷统计信息 * @param questionNoList * @return */ public PaperStat statPaper(List questionNoList){ PaperStat stat = new PaperStat(); Integer totalTime = 0; Integer totalNumber = 0; Integer totalCorrect = 0; for(QuestionNo questionNo : questionNoList){ if (questionNo == null) continue; totalTime += questionNo.getTotalTime(); totalNumber += questionNo.getTotalNumber(); totalCorrect += questionNo.getTotalCorrect(); } stat.setTotalCorrect(totalCorrect); stat.setTotalNumber(totalNumber); stat.setTotalTime(totalTime); return stat; } /** * 累加做题记录到questionNo * @param question */ public void accumulation(UserQuestion question){ questionNoRelationMapper.accumulation(question.getQuestionNoId(), 1, question.getUserTime(), question.getIsCorrect()); } /** * 累加收藏记录到questionNo * @param question */ public void accumulationCollect(UserCollectQuestion question, int collect){ questionNoRelationMapper.accumulationCollect(question.getQuestionNoId(), collect); } /** * 根据试卷分组获取统计信息 * @param questionNoIdsMap * @return */ public Map statPaperMap(Map questionNoIdsMap){ Map relationMap = new HashMap<>(); List ids = new ArrayList<>(); for(Integer[] questionNoIds : questionNoIdsMap.values()){ ids.addAll(Arrays.stream(questionNoIds).collect(Collectors.toList())); } List questionNoList = select(ids); Map questionNoMap = Transform.getMap(questionNoList, QuestionNo.class, "id"); List l = new ArrayList<>(); for(Integer k: questionNoIdsMap.keySet()){ l.clear(); for (Integer questionNoId : questionNoIdsMap.get(k)){ l.add((QuestionNo)questionNoMap.get(questionNoId)); } relationMap.put(k, statPaper(l)); } return relationMap; } /** * 根据试卷分组获取统计信息 * @param questionNoIdsMap * @return */ public Map> questionTypeMap(Map questionNoIdsMap){ Map> relationMap = new HashMap<>(); List ids = new ArrayList<>(); for(Integer[] questionNoIds : questionNoIdsMap.values()){ ids.addAll(Arrays.stream(questionNoIds).collect(Collectors.toList())); } List questionNoList = select(ids); List relationList = relation(questionNoList); Map questionNoMap = Transform.getMap(relationList, QuestionNoRelation.class, "id"); for(Integer k: questionNoIdsMap.keySet()){ List l = new ArrayList<>(); for (Integer questionNoId : questionNoIdsMap.get(k)){ QuestionNoRelation relation = (QuestionNoRelation)questionNoMap.get(questionNoId); if (relation == null) continue; if (relation.getQuestion() == null) continue; if (!l.contains(relation.getQuestion().getQuestionType())){ l.add(relation.getQuestion().getQuestionType()); } } relationMap.put(k, l); } return relationMap; } public List relation(List p){ List relationList = Transform.convert(p, QuestionNoRelation.class); Collection questionIds = Transform.getIds(p, QuestionNo.class, "questionId"); List questions = questionService.select(questionIds); Transform.combine(relationList, questions, QuestionNoRelation.class, "questionId", "question", Question.class, "id"); return relationList; } public QuestionNoRelation relation(QuestionNo p){ QuestionNoRelation relation = Transform.convert(p, QuestionNoRelation.class); Question question = questionService.get(p.getQuestionId()); relation.setQuestion(question); return relation; } /** * 通过题目编号获取 * @param title * @return */ public QuestionNo getByNo(String title, String module){ return one(questionNoMapper, QuestionNo.builder().title(title).module(module).build()); } @Transactional public QuestionNo add(QuestionNo question){ QuestionNo in = getByNo(question.getTitle(), question.getModule()); if (in != null){ if (in.getQuestionId() == 0){ return in; } throw new ParameterException("题目已经存在"); } int result = insert(questionNoMapper, question); question = one(questionNoMapper, question.getId()); if(question == null){ throw new SystemException("题目添加失败"); } return question; } @Transactional public QuestionNo edit(QuestionNo question){ QuestionNo in = one(questionNoMapper, question.getId()); if(in == null){ throw new ParameterException("题目不存在"); } int result = update(questionNoMapper, question); return question; } public boolean delete(Number id){ QuestionNo in = one(questionNoMapper, id); if(in == null){ throw new ParameterException("题目不存在"); } int result = delete(questionNoMapper, id, true); return result > 0; } public QuestionNo get(Number id){ QuestionNo in = one(questionNoMapper, id); if(in == null){ throw new ParameterException("题目不存在"); } return in; } public Page select(int page, int pageSize){ return select(questionNoMapper, page, pageSize); } public Page select(Integer[] ids){ return page(()->select(questionNoMapper, ids), 1, ids.length); } public List select(Collection ids){ return select(questionNoMapper, ids); } }