浏览代码

动态组卷分配方法

mingfu 1 月之前
父节点
当前提交
cd2b801f11

+ 143 - 0
ie-admin/src/main/java/com/ruoyi/web/service/ExamService.java

@@ -0,0 +1,143 @@
+package com.ruoyi.web.service;
+
+import com.alibaba.fastjson2.util.DateUtils;
+import com.google.common.collect.Lists;
+import com.ruoyi.common.utils.SecurityUtils;
+import com.ruoyi.enums.ExamineeStatus;
+import com.ruoyi.enums.PaperStatus;
+import com.ruoyi.enums.PaperType;
+import com.ruoyi.learn.domain.*;
+import com.ruoyi.learn.mapper.LearnExamineeMapper;
+import com.ruoyi.learn.mapper.LearnKnowledgeTreeMapper;
+import com.ruoyi.learn.mapper.LearnPaperMapper;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.Calendar;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * 考试服务
+ */
+@Service
+public class ExamService {
+    private final LearnPaperMapper paperMapper;
+    private final LearnKnowledgeTreeMapper knowledgeTreeMapper;
+    private final LearnExamineeMapper examineeMapper;
+    private final PaperService paperService;
+
+    public ExamService(LearnPaperMapper paperMapper, LearnKnowledgeTreeMapper knowledgeTreeMapper, LearnExamineeMapper examineeMapper, PaperService paperService) {
+        this.paperMapper = paperMapper;
+        this.knowledgeTreeMapper = knowledgeTreeMapper;
+        this.examineeMapper = examineeMapper;
+        this.paperService = paperService;
+    }
+
+    /**
+     * 开卷 (卷, 实时组卷)
+     * @return
+     */
+    public AnswerSheet openExaminee(PaperType paperType, Long relatedId) {
+        if(PaperType.Practice.equals(paperType)) { // TODO 先连接学生的定向信息
+            return openExaminee(relatedId, SecurityUtils.getUserId(), "");
+        }
+        return openExaminee(paperType, relatedId, SecurityUtils.getUserId(), "");
+    }
+
+    /**
+     * 临时保存
+     */
+    public void updateAnswerSheet(AnswerSheet answer) {
+
+    }
+
+    /**
+     * 交卷
+     * @param answer
+     */
+    public void commitAnswerSheet(AnswerSheet answer) {
+
+    }
+
+    public AnswerSheet openExaminee(PaperType paperType, Long paperId, Long studentId, String directKey) {
+        AnswerSheet answerSheet = new AnswerSheet();
+
+        LearnPaper paper = paperMapper.selectLearnPaperById(paperId);
+
+        LearnExaminee learnExaminee = new LearnExaminee();
+        learnExaminee.setStudentId(studentId);
+        learnExaminee.setPaperId(paperId);
+        learnExaminee.setPaperType(paperType.getVal());
+        learnExaminee.setState(ExamineeStatus.Exam.getVal());
+        List<LearnExaminee> examineeList = examineeMapper.selectLearnExamineeList(learnExaminee);
+        if (CollectionUtils.isNotEmpty(examineeList)) {
+            learnExaminee = examineeList.get(0);
+        } else {
+            learnExaminee.setState(ExamineeStatus.Exam.getVal());
+            learnExaminee.setBeginTime(new Date());
+            examineeMapper.insertLearnExaminee(learnExaminee);
+        }
+        return answerSheet;
+    }
+
+    /**
+     * 根据知识点生成一次性练习卷并开始做题
+     * @return
+     */
+    @Transactional(rollbackFor = Exception.class)
+    public AnswerSheet openExaminee(Long knowledgeId, Long studentId, String directKey) {
+        AnswerSheet answerSheet = new AnswerSheet();
+
+        LearnKnowledgeTree knowledgeTree = knowledgeTreeMapper.selectLearnKnowledgeTreeById(knowledgeId);
+        LearnPaper paper = new LearnPaper();
+        paper.setPaperType(PaperType.Practice.name());
+        paper.setRelateId(knowledgeId);
+        paper.setYear(Calendar.getInstance().get(Calendar.YEAR));
+        paper.setStatus(PaperStatus.TmpValid.getVal());
+        paper.setDirectKey(StringUtils.trimToEmpty(directKey));
+        List<LearnPaper> paperList = paperMapper.selectLearnPaperList(paper);
+        if (CollectionUtils.isNotEmpty(paperList)) { // 有未做完的
+            LearnExaminee learnExaminee = new LearnExaminee();
+            learnExaminee.setStudentId(studentId);
+            learnExaminee.setPaperId(paperList.get(0).getId());
+            learnExaminee.setPaperType(PaperType.Practice.getVal());
+            List<LearnExaminee> examineeList = examineeMapper.selectLearnExamineeList(learnExaminee);
+            if (CollectionUtils.isNotEmpty(examineeList)) {
+                examineeList.get(0);
+                return answerSheet;
+            }
+            // 关闭试卷
+            LearnPaper up = new LearnPaper();
+            up.setId(learnExaminee.getPaperId());
+            up.setStatus(PaperStatus.Valid.getVal());
+            paperMapper.updateLearnPaper(up);
+        }
+
+        PaperService.PaperDef paperDef = new PaperService.PaperDef();
+        paperDef.setTotal(15L);
+        paperDef.setFillExclude(true);
+        paperDef.setKnowIds(Lists.newArrayList(knowledgeId));
+        List<PaperService.TypeDef> typeDefList= Lists.newArrayList();
+        typeDefList.add(new PaperService.TypeDef("单选题", "单选题", 80, 1));
+        typeDefList.add(new PaperService.TypeDef("判断题", "判断题", 10, 2));
+        paperDef.setTypes(typeDefList);
+        List<LearnPaperQuestion> pqList = paperService.getQuestions(studentId,  paperDef);
+
+        paper.setPaperSource(0);
+        paper.setSubjectId(knowledgeTree.getSubjectId());
+        paper.setPaperName(studentId + "-" + knowledgeTree.getName() + "-" + DateUtils.format(new Date(), "yyyyMMddHHmmss"));
+        paperService.savePaper(paper, pqList);
+
+        LearnExaminee learnExaminee = new LearnExaminee();
+        learnExaminee.setStudentId(studentId);
+        learnExaminee.setPaperType(PaperType.Practice.getVal());
+        learnExaminee.setPaperId(paper.getId());
+        learnExaminee.setState(ExamineeStatus.Exam.getVal());
+        learnExaminee.setBeginTime(new Date());
+        examineeMapper.insertLearnExaminee(learnExaminee);
+        return answerSheet;
+    }
+}

+ 332 - 0
ie-admin/src/main/java/com/ruoyi/web/service/PaperService.java

@@ -0,0 +1,332 @@
+package com.ruoyi.web.service;
+
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson2.JSONObject;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+import com.ruoyi.common.utils.bean.BeanUtils;
+import com.ruoyi.enums.PaperStatus;
+import com.ruoyi.enums.PaperType;
+import com.ruoyi.learn.domain.*;
+import com.ruoyi.learn.mapper.*;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.apache.commons.lang3.tuple.Pair;
+import org.springframework.stereotype.Service;
+
+import java.util.*;
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+/**
+ * 考卷服务
+ */
+@Service
+public class PaperService {
+    private final LearnPaperMapper paperMapper;
+    private final LearnPaperQuestionMapper paperQuestionMapper;
+    private final LearnQuestionsMapper questionsMapper;
+
+
+    PaperService(LearnPaperMapper paperMapper, LearnPaperQuestionMapper paperQuestionMapper, LearnQuestionsMapper questionsMapper) {
+        this.paperMapper = paperMapper;
+        this.paperQuestionMapper = paperQuestionMapper;
+        this.questionsMapper = questionsMapper;
+    }
+
+    public void test() {
+//        PaperDef paperDef = new PaperDef();
+//        paperDef.setFillExclude(true);
+//        paperDef.setKnowIds(Lists.newArrayList(133614L,130166L,130187L));
+//        List<TypeDef> typeDefList= Lists.newArrayList();
+//        typeDefList.add(new TypeDef("单选题", "单选题", 80, 1));
+//        typeDefList.add(new TypeDef("判断题", "判断题", 10, 2));
+//        paperDef.setTypes(typeDefList);
+//        getQuestions(1L, 100L, paperDef);
+    }
+
+    /**
+     * 加载试卷
+     * @param paperId
+     * @return
+     */
+    public PaperVO loadPaper(Long paperId) {
+        PaperVO result = new PaperVO();
+        LearnPaper learnPaper = paperMapper.selectLearnPaperById(paperId);
+        BeanUtils.copyProperties(learnPaper, result);
+        List<LearnQuestions> questions = questionsMapper.selectQuestionByPaperId(paperId);
+        result.setQuestions(questions.stream().map(t -> {
+            PaperVO.QuestionSeq qs = new PaperVO.QuestionSeq();
+            BeanUtils.copyProperties(t, qs);
+            return qs;
+        }).collect(Collectors.toList()));
+        return result;
+    }
+
+    /**
+     * 根据院校专业要求生成模拟试卷
+     * @return
+     */
+    public Pair<LearnPaper, List<LearnPaperQuestion>> buildSimulatedPaper(LearnDirectedKnowledge directedKnowledge) {
+        LearnPaper paper = new LearnPaper();
+        paper.setPaperType(PaperType.Simulated.name());
+        paper.setRelateId(directedKnowledge.getId()); // 定向ID
+        paper.setYear(directedKnowledge.getYear());
+        paper.setStatus(PaperStatus.Valid.getVal());
+        paper.setDirectKey(directedKnowledge.getDirectKey());
+
+        PaperService.PaperDef paperDef = JSONObject.parseObject(directedKnowledge.getConditions(), PaperDef.class);
+        paperDef.setKnowIds(Stream.of(directedKnowledge.getKnowledges().split(",")).map(Long::valueOf).collect(Collectors.toList()));
+        paperDef.setTypes(JSONArray.parseArray(directedKnowledge.getQuestionTypes(), TypeDef.class));
+        return buildPaper(null, paper, paperDef);
+    }
+
+    /**
+     * 根据试卷定义生成试卷
+     * @param studentId
+     * @param paper
+     * @param paperDef
+     * @return
+     */
+    public Pair<LearnPaper, List<LearnPaperQuestion>> buildPaper(Long studentId, LearnPaper paper, PaperService.PaperDef paperDef) {
+        if(null == studentId){
+            paperDef.setFillExclude(false);
+        }
+        List<LearnPaperQuestion> pqList = getQuestions(studentId, paperDef);
+        return Pair.of(paper, pqList);
+    }
+
+    /**
+     * 保存试卷
+     * @param paper
+     * @param pqList
+     * @return
+     */
+    public LearnPaper savePaper(LearnPaper paper, List<LearnPaperQuestion> pqList) {
+        paper.setNumber(pqList.size());
+        paper.setFenshu(0);
+        paperMapper.insertLearnPaper(paper);
+        Long paperId = paper.getId();
+        pqList.stream().forEach(t -> {
+            t.setPaperId(paperId);
+            paperQuestionMapper.insertLearnPaperQuestion(t);
+        });
+        return paper;
+    }
+
+    /**
+     * 动态组卷查题
+     * @param studentId
+     * @param paperDef
+     * @return
+     */
+    public List<LearnPaperQuestion> getQuestions(Long studentId, PaperDef paperDef) {
+        // 题型分布定义, 知识点列表, 分值定义
+        // 统计知识点+类型的有效数量 TODO 总量可以缓存
+        Map<String, KnowTypeAssign> knowTypeAssignMap = Maps.newHashMap();
+        List<String> typeSet = paperDef.getTypes().stream().map(TypeDef::getType).collect(Collectors.toList());
+        Map cond = Maps.newHashMap();
+        cond.put("studentId", studentId);
+        cond.put("knowIds", paperDef.getKnowIds());
+        cond.put("types", typeSet);
+        setValue(knowTypeAssignMap, cond, 1); // 填充排除总量
+        if (paperDef.fillExclude) {
+            cond.remove("studentId");
+            setValue(knowTypeAssignMap, cond, 2); // 按需填充总量
+        }
+
+        // 循环补充未做+已做,如果知识点总数不够时才填充其他知识点的
+        Long lackTotal = paperDef.getTotal();
+        AtomicLong assignCount = new AtomicLong(0);
+        Map<Long, Integer> knowTypesMap = Maps.newHashMap();
+        int typeCount = paperDef.getTypes().size();
+        for (Long knowId : paperDef.getKnowIds()) {
+            knowTypesMap.put(knowId, typeCount);
+        }
+        Set<Long> knowSet = Sets.newHashSet(paperDef.getKnowIds());
+        Long minKnowTypeCount = Long.MAX_VALUE;
+        do {
+            Integer knowCount = knowSet.size();
+            knowSet.clear();
+            for (Long knowId : paperDef.getKnowIds()) {
+                typeCount = knowTypesMap.get(knowId);
+                if (0 == typeCount) {
+                    continue;
+                }
+                Long avgKnowTypeCount = Math.min(minKnowTypeCount, lackTotal / knowCount / typeCount);
+                if(avgKnowTypeCount == 0 && lackTotal > 0) {
+                    avgKnowTypeCount = 1L;
+                }
+                typeCount = 0;
+                for (TypeDef typeDef : paperDef.getTypes()) {
+                    Long tmpMinKnowTypeCount = assignKnownCount(knowId, typeDef.getType(), knowTypeAssignMap, avgKnowTypeCount, paperDef.fillExclude, assignCount);
+                    if (tmpMinKnowTypeCount > 0) {
+                        minKnowTypeCount = Math.min(minKnowTypeCount, tmpMinKnowTypeCount);
+                        knowSet.add(knowId);
+                        typeCount++;
+                    }
+                }
+                knowTypesMap.put(knowId, typeCount);
+            }
+            lackTotal = paperDef.getTotal() - assignCount.get();
+            if (lackTotal <= 0 || knowSet.isEmpty()) {
+                break;
+            }
+        } while (true);
+
+        // 知识点已经分配,准备题型分配
+        LearnQuestions qCond = new LearnQuestions();
+        Random random = new Random();
+        List<LearnPaperQuestion> pqList = Lists.newArrayList();
+        Set<Long> existQuestionIdSet = Sets.newHashSet();
+        for (TypeDef typeDef : paperDef.getTypes()) {
+            for (Long knowId : paperDef.getKnowIds()) {
+                String key = knowId + "_" + typeDef.getType();
+                KnowTypeAssign ktc = knowTypeAssignMap.get(key);
+                qCond.setKnowledgeId(ktc.getKnowId());
+                qCond.setQtpye(ktc.getType());
+                if(ktc.exclAssign > 0){
+                    qCond.setId(studentId);
+                    qCond.setNumber(ktc.assign > 500 ? (long) random.nextInt(ktc.exclAssign.intValue() - 500) :  0L);
+                    List<LearnQuestions> questions = questionsMapper.selectQuestionsForPaper(qCond);
+                    addRandomList(questions, random, paperDef.getTotal(), ktc.exclAssign, typeDef.getScore(), existQuestionIdSet, pqList);
+                }
+                if(ktc.assign > 0L) {
+                    qCond.setId(null);
+                    qCond.setNumber(ktc.assign > 500 ? (long) random.nextInt(ktc.assign.intValue() - 500) :  0L);
+                    List<LearnQuestions> questions = questionsMapper.selectQuestionsForPaper(qCond);
+                    addRandomList(questions, random, paperDef.getTotal(), ktc.exclAssign, typeDef.getScore(), existQuestionIdSet, pqList);
+                }
+
+            }
+        }
+        return pqList;
+    }
+
+    private void addRandomList(List<LearnQuestions> questions, Random random, Long totalCount, Long count, Integer score, Set<Long> existQuestionIdSet, List<LearnPaperQuestion> pqList) {
+        while(count > 0 && questions.size() > 0) {
+            LearnQuestions q = questions.size() > 1 ? questions.remove(random.nextInt(questions.size() - 1)) : questions.remove(0);
+            if(existQuestionIdSet.add(q.getId())) {
+                LearnPaperQuestion pq = new LearnPaperQuestion();
+                pq.setSeq(pqList.size() + 1);
+                pq.setScore(score);
+                pq.setQuestionId(q.getId());
+                pqList.add(pq);
+                count--;
+                if(pqList.size() == totalCount) {
+                    break;
+                }
+            }
+        }
+    }
+
+    /**
+     * 给指定类型分配
+     * @param knowId
+     * @param qtype
+     * @param knowTypeAssignMap
+     * @param knowTypeCount
+     * @param fillExclude
+     * @param assignCount
+     */
+    private Long assignKnownCount(Long knowId, String qtype, Map<String, KnowTypeAssign> knowTypeAssignMap, Long knowTypeCount, Boolean fillExclude,
+                                  AtomicLong assignCount) {
+        String key = knowId + "_" + qtype;
+        KnowTypeAssign knowTypeAssign = knowTypeAssignMap.get(key);
+        long lackCount;
+        if (knowTypeAssign.exclCount > 0) {
+            lackCount = knowTypeCount - knowTypeAssign.exclCount;
+            if (lackCount <= 0) { // 足量
+                assignCount.getAndAdd(knowTypeCount);
+                knowTypeAssign.exclCount -= knowTypeCount;
+                knowTypeAssign.exclAssign += knowTypeCount;
+            } else { // 不足时且还有时全转
+                assignCount.getAndAdd(knowTypeAssign.exclCount);
+                knowTypeAssign.exclAssign += knowTypeAssign.exclCount;
+                knowTypeAssign.exclCount = 0L;
+            }
+        } else {
+            lackCount = knowTypeCount;
+        }
+        long lack = 0;
+        if (lackCount > 0) { // 差额优先补充已做过的
+            if(fillExclude && knowTypeAssign.total > 0) {
+                lack = lackCount - knowTypeAssign.total;
+                if (lack <= 0) { // 足量
+                    assignCount.getAndAdd(lackCount);
+                    knowTypeAssign.total -= lackCount;
+                    knowTypeAssign.assign += lackCount;
+                } else { // 不足时全转
+                    assignCount.getAndAdd(knowTypeAssign.total);
+                    knowTypeAssign.assign += knowTypeAssign.total;
+                    knowTypeAssign.total = 0L;
+                }
+            } else {
+                lack = lackCount;
+            }
+        }
+        if(lackCount < 0) {
+            return -lackCount;
+        } else if(lack < 0) {
+            return -lack;
+        }
+        return 0L;
+    }
+
+    /**
+     * 合并 排除总量和总量
+     * @param knowTypeAssignMap
+     * @param cond
+     * @param index 1 free 2 total
+     */
+    private void setValue(Map<String, KnowTypeAssign> knowTypeAssignMap, Map cond, Integer index) {
+        for (LearnQuestions q : questionsMapper.statByKnowledgeType(cond)) {
+            String key = q.getKnowledgeId() + "_" + q.getQtpye();
+            KnowTypeAssign knowTypeAssign = knowTypeAssignMap.get(key);
+            if (null == knowTypeAssign) {
+                knowTypeAssign = new KnowTypeAssign();
+                knowTypeAssign.setKnowId(q.getKnowledgeId());
+                knowTypeAssign.setType(q.getQtpye());
+                knowTypeAssignMap.put(key, knowTypeAssign);
+            }
+            if (1 == index) {
+                knowTypeAssign.total = 0L;
+                knowTypeAssign.exclAssign = 0L;
+                knowTypeAssign.assign = 0L;
+                knowTypeAssign.exclCount = q.getNumber();
+            } else {
+                knowTypeAssign.total = q.getNumber() - knowTypeAssign.exclCount;
+            }
+        }
+    }
+
+    @Data
+    public static class KnowTypeAssign {
+        Long knowId;
+        String type;
+        Long exclAssign; // 分配个数
+        Long assign; // 全量分配个数
+        Long exclCount; // 排除总数
+        Long total; // 全量总数
+    }
+
+    @Data
+    @AllArgsConstructor
+    @NoArgsConstructor
+    public static class TypeDef {
+        String title;
+        String type;
+        Integer count;
+        Integer score;
+    }
+    @Data
+    public static class PaperDef {
+        Long total;
+        List<Long> knowIds;
+        Boolean fillExclude; // 不足时是否填充排除的
+        List<TypeDef> types;
+    }
+}

+ 12 - 0
ie-system/src/main/java/com/ruoyi/enums/PaperStatus.java

@@ -0,0 +1,12 @@
+package com.ruoyi.enums;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+@Getter
+@AllArgsConstructor
+public enum PaperStatus {
+    Invalid(0), Valid(1), TmpInvalid(3), TmpValid(4);
+
+    private final Integer val;
+}

+ 3 - 3
ie-system/src/main/java/com/ruoyi/learn/domain/LearnDirectedKnowledge.java

@@ -20,7 +20,7 @@ public class LearnDirectedKnowledge extends BaseEntity
 
 
     /** 年度 */
     /** 年度 */
     @Excel(name = "年度")
     @Excel(name = "年度")
-    private Long year;
+    private Integer year;
 
 
     /** 定向Key */
     /** 定向Key */
     @Excel(name = "定向Key")
     @Excel(name = "定向Key")
@@ -72,12 +72,12 @@ public class LearnDirectedKnowledge extends BaseEntity
         return id;
         return id;
     }
     }
 
 
-    public void setYear(Long year) 
+    public void setYear(Integer year)
     {
     {
         this.year = year;
         this.year = year;
     }
     }
 
 
-    public Long getYear() 
+    public Integer getYear()
     {
     {
         return year;
         return year;
     }
     }

+ 24 - 12
ie-system/src/main/java/com/ruoyi/learn/domain/LearnPaper.java

@@ -28,23 +28,27 @@ public class LearnPaper extends BaseEntity
 
 
     /** 创建年度 */
     /** 创建年度 */
     @Excel(name = "创建年度")
     @Excel(name = "创建年度")
-    private Long year;
+    private Integer year;
 
 
     /** 历年真题,模拟卷,必刷题;组卷;练习卷;刷题卷;know_test-知识点,auto-基础题库,high_error-高频错题,smart_test-智能刷题,paper-真题,试卷 */
     /** 历年真题,模拟卷,必刷题;组卷;练习卷;刷题卷;know_test-知识点,auto-基础题库,high_error-高频错题,smart_test-智能刷题,paper-真题,试卷 */
     @Excel(name = "历年真题,模拟卷,必刷题;组卷;练习卷;刷题卷;know_test-知识点,auto-基础题库,high_error-高频错题,smart_test-智能刷题,paper-真题,试卷")
     @Excel(name = "历年真题,模拟卷,必刷题;组卷;练习卷;刷题卷;know_test-知识点,auto-基础题库,high_error-高频错题,smart_test-智能刷题,paper-真题,试卷")
     private String paperType;
     private String paperType;
 
 
+    /** 试卷状态 */
+    @Excel(name = "试卷状态 0无效 1有效 3临卷无效 4临卷有效")
+    private Integer status;
+
     /** 试卷题数 */
     /** 试卷题数 */
     @Excel(name = "试卷题数")
     @Excel(name = "试卷题数")
-    private String number;
+    private Integer number;
 
 
     /** 试卷总分数 */
     /** 试卷总分数 */
     @Excel(name = "试卷总分数")
     @Excel(name = "试卷总分数")
-    private Long fenshu;
+    private Integer fenshu;
 
 
     /** 试券来源 */
     /** 试券来源 */
     @Excel(name = "试券来源")
     @Excel(name = "试券来源")
-    private Long paperSource;
+    private Integer paperSource;
 
 
     /** 定向key */
     /** 定向key */
     @Excel(name = "定向key")
     @Excel(name = "定向key")
@@ -104,12 +108,12 @@ public class LearnPaper extends BaseEntity
         return paperName;
         return paperName;
     }
     }
 
 
-    public void setYear(Long year) 
+    public void setYear(Integer year)
     {
     {
         this.year = year;
         this.year = year;
     }
     }
 
 
-    public Long getYear() 
+    public Integer getYear()
     {
     {
         return year;
         return year;
     }
     }
@@ -124,32 +128,40 @@ public class LearnPaper extends BaseEntity
         return paperType;
         return paperType;
     }
     }
 
 
-    public void setNumber(String number) 
+    public void setNumber(Integer number)
     {
     {
         this.number = number;
         this.number = number;
     }
     }
 
 
-    public String getNumber() 
+    public Integer getNumber()
     {
     {
         return number;
         return number;
     }
     }
 
 
-    public void setFenshu(Long fenshu) 
+    public Integer getStatus() {
+        return status;
+    }
+
+    public void setStatus(Integer status) {
+        this.status = status;
+    }
+
+    public void setFenshu(Integer fenshu)
     {
     {
         this.fenshu = fenshu;
         this.fenshu = fenshu;
     }
     }
 
 
-    public Long getFenshu() 
+    public Integer getFenshu()
     {
     {
         return fenshu;
         return fenshu;
     }
     }
 
 
-    public void setPaperSource(Long paperSource) 
+    public void setPaperSource(Integer paperSource)
     {
     {
         this.paperSource = paperSource;
         this.paperSource = paperSource;
     }
     }
 
 
-    public Long getPaperSource() 
+    public Integer getPaperSource()
     {
     {
         return paperSource;
         return paperSource;
     }
     }

+ 6 - 6
ie-system/src/main/java/com/ruoyi/learn/domain/LearnPaperQuestion.java

@@ -28,11 +28,11 @@ public class LearnPaperQuestion extends BaseEntity
 
 
     /** 顺序 */
     /** 顺序 */
     @Excel(name = "顺序")
     @Excel(name = "顺序")
-    private Long seq;
+    private Integer seq;
 
 
     /** 分值 */
     /** 分值 */
     @Excel(name = "分值")
     @Excel(name = "分值")
-    private Long score;
+    private Integer score;
 
 
     public void setId(Long id) 
     public void setId(Long id) 
     {
     {
@@ -64,22 +64,22 @@ public class LearnPaperQuestion extends BaseEntity
         return questionId;
         return questionId;
     }
     }
 
 
-    public void setSeq(Long seq) 
+    public void setSeq(Integer seq)
     {
     {
         this.seq = seq;
         this.seq = seq;
     }
     }
 
 
-    public Long getSeq() 
+    public Integer getSeq()
     {
     {
         return seq;
         return seq;
     }
     }
 
 
-    public void setScore(Long score) 
+    public void setScore(Integer score)
     {
     {
         this.score = score;
         this.score = score;
     }
     }
 
 
-    public Long getScore() 
+    public Integer getScore()
     {
     {
         return score;
         return score;
     }
     }

+ 30 - 0
ie-system/src/main/java/com/ruoyi/learn/domain/PaperVO.java

@@ -0,0 +1,30 @@
+package com.ruoyi.learn.domain;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+@ApiModel("试卷")
+public class PaperVO {
+    private Long id;
+    private Long subjectId;
+    private String paperName;
+    private Long year;
+    private String paperType;
+    private String number;
+    private Long score;
+    private String directKey;
+
+    @ApiModelProperty("试题")
+    List<QuestionSeq> questions;
+
+    @Data
+    @ApiModel("试题")
+    public static class QuestionSeq extends LearnQuestions {
+        @ApiModelProperty("序号")
+        Integer seq;
+    }
+}

+ 6 - 0
ie-system/src/main/java/com/ruoyi/learn/mapper/LearnQuestionsMapper.java

@@ -1,6 +1,8 @@
 package com.ruoyi.learn.mapper;
 package com.ruoyi.learn.mapper;
 
 
 import java.util.List;
 import java.util.List;
+import java.util.Map;
+
 import com.ruoyi.learn.domain.LearnQuestions;
 import com.ruoyi.learn.domain.LearnQuestions;
 
 
 /**
 /**
@@ -60,4 +62,8 @@ public interface LearnQuestionsMapper
     public int deleteLearnQuestionsByIds(Long[] ids);
     public int deleteLearnQuestionsByIds(Long[] ids);
 
 
     public List<LearnQuestions> selectQuestionByPaperId(Long paperId);
     public List<LearnQuestions> selectQuestionByPaperId(Long paperId);
+
+    public List<LearnQuestions> statByKnowledgeType(Map cond);
+
+    public List<LearnQuestions> selectQuestionsForPaper(LearnQuestions cond);
 }
 }

+ 31 - 0
ie-system/src/main/resources/mapper/learn/LearnQuestionsMapper.xml

@@ -274,4 +274,35 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
           where pq.`paper_id` = #{paperId}
           where pq.`paper_id` = #{paperId}
           order by pq.`seq`, q.`id`
           order by pq.`seq`, q.`id`
     </select>
     </select>
+
+    <select id="statByKnowledgeType" parameterType="map" resultMap="LearnQuestionsResult">
+       SELECT q.`knowledgeId`, q.`qtpye`, COUNT(*) number
+         FROM `learn_knowledge_question` kq
+         <if test="studentId != null">
+             LEFT JOIN `learn_answer` a ON kq.`question_id` = a.`question_id` AND a.`student_id` = #{studentId}
+         </if>
+         JOIN `learn_questions` q ON q.`id` = kq.`question_id`
+        <where>
+            <if test="knowIds != null"> and kq.`knowledge_id` in <foreach item="id" collection="knowIds" open="(" separator="," close=")">#{id}</foreach></if>
+            <if test="types != null"> and q.`qtpye` in <foreach item="id" collection="types" open="(" separator="," close=")">#{id}</foreach></if>
+            <if test="studentId != null"> AND a.`student_id` IS NULL</if>
+        </where>
+        GROUP BY q.`knowledgeId`, q.`qtpye`
+    </select>
+
+    <select id="selectQuestionsForPaper" parameterType="LearnQuestions" resultMap="LearnQuestionsResult">
+        SELECT q.`id`, q.`knowledgeId`
+        FROM `learn_knowledge_question` kq
+        <if test="id != null">
+            LEFT JOIN `learn_answer` a ON kq.`question_id` = a.`question_id` AND a.`student_id` = #{id}
+        </if>
+        JOIN `learn_questions` q ON q.`id` = kq.`question_id`
+        <where>
+            <if test="qtpye != null  and qtpye != ''"> and qtpye = #{qtpye}</if>
+            <if test="id != null ">  AND a.`student_id` IS NULL</if>
+            <if test="knowledgeId != null "> and knowledgeId = #{knowledgeId}</if>
+        </where>
+        limit #{number}, 500
+    </select>
+
 </mapper>
 </mapper>