gaoxing 8 роки тому
батько
коміт
b9eea277b0

+ 1 - 1
cqb-comm-utils/src/main/java/com/qmth/cqb/utils/enums/ExtractPolicy.java

@@ -2,7 +2,7 @@ package com.qmth.cqb.utils.enums;
 
 public enum ExtractPolicy {
 	
-	ExtractPolicy("RANDOM_PAPER","随机抽卷");
+	RANDOM_POLICY("RANDOM_PAPER","随机抽卷");
 	
 	private String key;
 	private String value;

+ 8 - 0
cqb-gen-paper/src/main/java/com/qmth/cqb/genpaper/condition/Condition.java

@@ -0,0 +1,8 @@
+package com.qmth.cqb.genpaper.condition;
+
+public interface Condition {
+	
+	public String  getName();
+	public String  getCode();
+
+}

+ 83 - 0
cqb-gen-paper/src/main/java/com/qmth/cqb/genpaper/context/Context.java

@@ -0,0 +1,83 @@
+package com.qmth.cqb.genpaper.context;
+
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import com.qmth.cqb.genpaper.condition.Condition;
+import com.qmth.cqb.genpaper.valve.Valve;
+import com.qmth.cqb.question.model.Question;
+
+public abstract class Context implements Valve {
+
+    protected List<Valve> valves;
+
+    protected List<Condition> conditions;
+
+    protected Set<Question> selectQues;
+
+    public Context(List<Condition> conditions) {
+        this.valves = new LinkedList<>();
+        this.conditions = new LinkedList<>();
+        this.selectQues = new HashSet<>();
+
+        if (conditions != null) {
+            this.conditions.addAll(conditions);
+        }
+    }
+
+    public boolean check(Question question) {
+        for (Valve valve : valves) {
+            if (!valve.check(question)) {
+                return false;
+            }
+        }
+        return true;
+
+    }
+
+    public void select(Question question) {
+        for (Valve valve : valves) {
+            valve.select(question);
+        }
+        selectQues.add(question);
+    }
+
+    public abstract boolean finish();
+
+    public Map<String, String> status() {
+        return null;
+
+    }
+
+    public void reset() {
+
+    }
+
+    public List<Valve> getValves() {
+        return valves;
+    }
+
+    public void setValves(List<Valve> valves) {
+        this.valves = valves;
+    }
+
+    public List<Condition> getConditions() {
+        return conditions;
+    }
+
+    public void setConditions(List<Condition> conditions) {
+        this.conditions = conditions;
+    }
+
+    public Set<Question> getSelectQues() {
+        return selectQues;
+    }
+
+    public void setSelectQues(Set<Question> selectQues) {
+        this.selectQues = selectQues;
+    }
+
+}

+ 54 - 0
cqb-gen-paper/src/main/java/com/qmth/cqb/genpaper/context/DetailContext.java

@@ -0,0 +1,54 @@
+package com.qmth.cqb.genpaper.context;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import com.qmth.cqb.genpaper.condition.Condition;
+import com.qmth.cqb.paper.model.PaperDetailStruct;
+import com.qmth.cqb.paper.model.PaperDetailUnitStruct;
+import com.qmth.cqb.question.model.Question;
+
+public class DetailContext extends Context {
+
+    private PaperContext paperContext;
+
+    private PaperDetailStruct detailStruct;
+
+    private List<UnitContext> units;
+
+    public DetailContext(PaperDetailStruct detailStruct, PaperContext paperContext, List<Condition> conditions) {
+        super(conditions);
+        this.detailStruct = detailStruct;
+        this.units = new LinkedList<UnitContext>();
+
+        for (PaperDetailUnitStruct unit : detailStruct.getPaperDetailUnitStructs()) {
+            units.add(new UnitContext(unit, this, conditions));
+        }
+    }
+
+    public boolean check(Question question) {
+        return super.check(question) && paperContext.check(question);
+    }
+
+    public void select(Question question) {
+        super.select(question);
+        paperContext.select(question);
+    }
+
+    public boolean finish() {
+        return selectQues.size() == units.size();
+    }
+
+    public PaperContext getPaperContext() {
+        return paperContext;
+    }
+
+    public PaperDetailStruct getDetailStruct() {
+        return detailStruct;
+    }
+
+    public List<UnitContext> getUnits() {
+        return units;
+    }
+
+}

+ 50 - 0
cqb-gen-paper/src/main/java/com/qmth/cqb/genpaper/context/PaperContext.java

@@ -0,0 +1,50 @@
+package com.qmth.cqb.genpaper.context;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import com.qmth.cqb.genpaper.condition.Condition;
+import com.qmth.cqb.paper.model.PaperDetailStruct;
+import com.qmth.cqb.paper.model.PaperStruct;
+import com.qmth.cqb.question.model.Question;
+
+public class PaperContext extends Context {
+
+    private PaperStruct paperStruct;
+
+    private List<DetailContext> details;
+
+    public PaperContext(PaperStruct paperStruct, List<Condition> conditions) {
+        super(conditions);
+        this.paperStruct = paperStruct;
+        this.details = new LinkedList<DetailContext>();
+        for (PaperDetailStruct pd : paperStruct.getPaperDetailStructs()) {
+            details.add(new DetailContext(pd, this,conditions));
+        }
+    }
+
+    public boolean check(Question question) {
+        return super.check(question);
+    }
+
+    public void select(Question question) {
+        super.select(question);
+    }
+
+    public boolean finish() {
+        boolean finish = false;
+        for (DetailContext dc : details) {
+            finish = dc.finish() && finish;
+        }
+        return finish;
+    }
+
+    public PaperStruct getPaperStruct() {
+        return paperStruct;
+    }
+
+    public List<DetailContext> getDetails() {
+        return details;
+    }
+
+}

+ 43 - 0
cqb-gen-paper/src/main/java/com/qmth/cqb/genpaper/context/UnitContext.java

@@ -0,0 +1,43 @@
+package com.qmth.cqb.genpaper.context;
+
+import java.util.List;
+
+import com.qmth.cqb.genpaper.condition.Condition;
+import com.qmth.cqb.paper.model.PaperDetailUnitStruct;
+import com.qmth.cqb.question.model.Question;
+
+public class UnitContext extends Context {
+
+    private DetailContext detailContext;
+
+    private PaperDetailUnitStruct unitStruct;
+
+    public UnitContext(PaperDetailUnitStruct unitStruct, DetailContext detailContext, List<Condition> conditions) {
+        super(conditions);
+        this.unitStruct = unitStruct;
+        this.detailContext = detailContext;
+
+    }
+
+    public boolean check(Question question) {
+        return super.check(question) && detailContext.check(question);
+    }
+
+    public void select(Question question) {
+        super.select(question);
+        detailContext.select(question);
+    }
+
+    public boolean finish() {
+        return selectQues.size() > 0;
+    }
+
+    public DetailContext getDetailContext() {
+        return detailContext;
+    }
+
+    public PaperDetailUnitStruct getUnitStruct() {
+        return unitStruct;
+    }
+
+}

+ 366 - 0
cqb-gen-paper/src/main/java/com/qmth/cqb/genpaper/service/GenPaperService.java

@@ -0,0 +1,366 @@
+package com.qmth.cqb.genpaper.service;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import com.qmth.cqb.genpaper.condition.Condition;
+import com.qmth.cqb.genpaper.context.DetailContext;
+import com.qmth.cqb.genpaper.context.PaperContext;
+import com.qmth.cqb.genpaper.context.UnitContext;
+import com.qmth.cqb.paper.dao.PaperDetailRepo;
+import com.qmth.cqb.paper.dao.PaperDetailUnitRepo;
+import com.qmth.cqb.paper.dao.PaperRepo;
+import com.qmth.cqb.paper.dao.PaperStructRepo;
+import com.qmth.cqb.paper.model.Paper;
+import com.qmth.cqb.paper.model.PaperDetail;
+import com.qmth.cqb.paper.model.PaperDetailUnit;
+import com.qmth.cqb.paper.model.PaperStruct;
+import com.qmth.cqb.question.model.Question;
+import com.qmth.cqb.utils.CommonUtils;
+import com.qmth.cqb.utils.enums.QuesStructType;
+
+@Service
+public class GenPaperService {
+
+    @Autowired
+    PaperRepo paperRepo;
+
+    @Autowired
+    PaperDetailRepo paperDetailRepo;
+
+    @Autowired
+    PaperDetailUnitRepo unitRepo;
+
+    @Autowired
+    PaperStructRepo paperStructRepo;
+
+    /**
+     * 按分数在选定的试卷中随机抽取题,组成一套新的试卷
+     * 
+     * @param paperMap
+     *            key:指定的试卷Id,value:需要抽取的分数
+     * @return 试卷
+     */
+    public Paper genPaperByScore(Map<String, Double> paperMap, String paperName) {
+        List<PaperDetailUnit> selectedUnits = new ArrayList<PaperDetailUnit>();// 选中的小题
+        if (paperMap != null && paperMap.size() > 0) {
+            for (String paperId : paperMap.keySet()) {
+                Double totalScore = paperMap.get(paperId);
+                Paper oldPaper = paperRepo.findOne(paperId);
+                List<PaperDetailUnit> unitList = unitRepo.findByPaper(oldPaper);
+                Collections.shuffle(unitList);// 随机乱序之后再根据分数取题
+                double sum = 0;
+                for (PaperDetailUnit pdu : unitList) {
+                    sum += pdu.getScore();
+                    if (sum <= totalScore) {// 5 10 15 20 25 30
+                        selectedUnits.add(pdu);// 1 2 3 4 5 6
+                    } else {
+                        break;
+                    }
+                }
+            }
+        }
+
+        return this.constuctPaper(selectedUnits, paperName);
+
+    }
+
+    /**
+     * 按每套试卷需要抽取的题目数量随机抽取题,组成一套新的试卷
+     * 
+     * @param paperMap
+     *            key:指定的试卷Id,value:需要抽取试题数量
+     * @param paperName
+     *            试卷名称
+     * @return
+     */
+    public Paper genPaperByQuestionNum(Map<String, Integer> paperMap, String paperName) {
+        List<PaperDetailUnit> selectedUnits = new ArrayList<PaperDetailUnit>();// 选中的小题
+        if (paperMap != null && paperMap.size() > 0) {
+            for (String paperId : paperMap.keySet()) {
+                int unitNum = paperMap.get(paperId);
+                Paper oldPaper = paperRepo.findOne(paperId);
+                List<PaperDetailUnit> unitList = unitRepo.findByPaper(oldPaper);
+                Collections.shuffle(unitList);// 随机乱序之后再取题
+                if (unitList.size() >= unitNum) {
+                    for (int i = 0; i < unitNum; i++) {
+                        selectedUnits.add(unitList.get(i));
+                        unitList.remove(i);
+                    }
+                }
+                for (PaperDetailUnit pdu : selectedUnits) {
+                    if (pdu.getQuestionType().getId() == 6L && pdu.getQuestion().getSubQuestions().size() > 1) {// 假如是套题,要计算下面小题数量
+                        selectedUnits.remove(pdu);// 删除掉这道套题
+                        for (PaperDetailUnit oldPdu : unitList) {
+                            if (pdu.getQuestionType().getId() != 6L) {// 从原来的集合中取一个不是套题的加进去
+                                selectedUnits.add(oldPdu);
+                                break;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        return this.constuctPaper(selectedUnits, paperName);
+
+    }
+
+    /**
+     * 构造大题
+     * 
+     * @param units
+     * @param number
+     * @param detailName
+     *            大题名称
+     * @return
+     */
+    public PaperDetail constuctPaperDeatil(List<PaperDetailUnit> units, int number, String detailName) {
+        PaperDetail pd = new PaperDetail();
+        if (units != null && units.size() > 0) {
+            Double score = 0d;
+            for (PaperDetailUnit pdu : units) {
+                score += pdu.getScore();
+
+            }
+            pd.setName(detailName);
+            pd.setUnitCount(units.size());
+            pd.setScore(score);
+            pd.setNumber(number);
+            pd.setCreateTime(CommonUtils.getCurDateTime());
+            for (PaperDetailUnit pdu : units) {
+                pdu.setPaperDetail(pd);
+            }
+        }
+        return pd;
+
+    }
+
+    /**
+     * 根据大题集合构造paper
+     * 
+     * @param details
+     * @return
+     */
+    public Paper constuctPaperByPaperDetails(List<PaperDetail> details, String paperName) {
+        Paper paper = new Paper();
+        if (details != null && details.size() > 0) {
+            Double score = 0d;
+            for (PaperDetail pd : details) {
+                score += pd.getScore();
+
+            }
+            paper.setName(paperName);
+            paper.setPaperDetailCount(details.size());
+            paper.setTotalScore(score);
+            paper.setCreateTime(CommonUtils.getCurDateTime());
+            for (PaperDetail pdu : details) {
+                pdu.setPaper(paper);
+            }
+        }
+        return paper;
+
+    }
+
+    /**
+     * 随机构造试卷,根据小题类型 没有定义试卷结构
+     * 
+     * @param units
+     * @param number
+     * @param quesName
+     * @return
+     */
+    public Paper constuctPaper(List<PaperDetailUnit> selectedUnits, String paperName) {
+        Paper paper = new Paper();
+        List<PaperDetailUnit> singUnits = new ArrayList<PaperDetailUnit>();
+        List<PaperDetailUnit> multipleUnits = new ArrayList<PaperDetailUnit>();
+        List<PaperDetailUnit> boolUnits = new ArrayList<PaperDetailUnit>();
+        List<PaperDetailUnit> blankUnits = new ArrayList<PaperDetailUnit>();
+        List<PaperDetailUnit> textUnits = new ArrayList<PaperDetailUnit>();
+        List<PaperDetailUnit> nestUnits = new ArrayList<PaperDetailUnit>();
+        for (PaperDetailUnit pdu : selectedUnits) {
+            switch (pdu.getQuestionType()) {
+            case SINGLE_ANSWER_QUESTION:
+                singUnits.add(pdu);
+                break;
+            case MULTIPLE_ANSWER_QUESTION:
+                multipleUnits.add(pdu);
+                break;
+            case BOOL_ANSWER_QUESTION:
+                boolUnits.add(pdu);
+                break;
+            case FILL_BLANK_QUESTION:
+                blankUnits.add(pdu);
+                break;
+            case TEXT_ANSWER_QUESTION:
+                textUnits.add(pdu);
+                break;
+            case NESTED_ANSWER_QUESTION:
+                nestUnits.add(pdu);
+                break;
+
+            }
+        }
+        PaperDetail singPd = this.constuctPaperDeatil(singUnits, 1, QuesStructType.SINGLE_ANSWER_QUESTION.getName());
+        PaperDetail multipePd = this.constuctPaperDeatil(multipleUnits, 2,
+                QuesStructType.MULTIPLE_ANSWER_QUESTION.getName());
+        PaperDetail boolPd = this.constuctPaperDeatil(boolUnits, 3, QuesStructType.BOOL_ANSWER_QUESTION.getName());
+        PaperDetail blankPd = this.constuctPaperDeatil(blankUnits, 4, QuesStructType.FILL_BLANK_QUESTION.getName());
+        PaperDetail textPd = this.constuctPaperDeatil(textUnits, 5, QuesStructType.TEXT_ANSWER_QUESTION.getName());
+        PaperDetail nestPd = this.constuctPaperDeatil(nestUnits, 6, QuesStructType.NESTED_ANSWER_QUESTION.getName());
+        selectedUnits.clear();
+        List<PaperDetail> pds = new ArrayList<PaperDetail>();
+        int paperDetailCount = 0;// 大题数量
+        Double totalScore = 0d;
+        if (singPd.getUnitCount() > 0) {
+            paperDetailCount = paperDetailCount + 1;
+            totalScore += singPd.getScore();
+            pds.add(singPd);
+            selectedUnits.addAll(singUnits);
+        } else if (multipePd.getUnitCount() > 0) {
+            paperDetailCount = paperDetailCount + 1;
+            totalScore += singPd.getScore();
+            pds.add(multipePd);
+            selectedUnits.addAll(multipleUnits);
+        } else if (boolPd.getUnitCount() > 0) {
+            paperDetailCount = paperDetailCount + 1;
+            totalScore += singPd.getScore();
+            pds.add(boolPd);
+            selectedUnits.addAll(boolUnits);
+        } else if (blankPd.getUnitCount() > 0) {
+            paperDetailCount = paperDetailCount + 1;
+            totalScore += singPd.getScore();
+            pds.add(blankPd);
+            selectedUnits.addAll(blankUnits);
+        } else if (textPd.getUnitCount() > 0) {
+            paperDetailCount = paperDetailCount + 1;
+            totalScore += singPd.getScore();
+            pds.add(textPd);
+            selectedUnits.addAll(textUnits);
+        } else if (nestPd.getUnitCount() > 0) {
+            paperDetailCount = nestPd.getUnitCount() + paperDetailCount;
+            totalScore += singPd.getScore();
+            pds.add(nestPd);
+            selectedUnits.addAll(nestUnits);
+        }
+
+        paper.setName(paperName);
+        paper.setTotalScore(totalScore);
+        paper.setPaperDetailCount(paperDetailCount);
+        // 数据入库
+        paper = this.persistentPaper(pds, selectedUnits, paper);
+        return paper;
+
+    }
+
+    /**
+     * 数据入库
+     * 
+     * @param details
+     * @param selectedUnits
+     * @param paper
+     * @return
+     */
+    public Paper persistentPaper(List<PaperDetail> details, List<PaperDetailUnit> selectedUnits, Paper paper) {
+        for (PaperDetail pd : details) {
+            pd.setPaper(paper);
+        }
+        for (PaperDetailUnit pdu : selectedUnits) {
+            pdu.setPaper(paper);
+        }
+        unitRepo.save(selectedUnits);
+        paperDetailRepo.save(details);
+        paperRepo.save(paper);
+        return paper;
+
+    }
+
+    /**
+     * 精确组卷,根据设定试卷结构组卷
+     * 
+     * @param paperIds
+     *            取题范围
+     * @param paperStruct
+     *            设定的试卷结构
+     * @param conditions
+     *            筛选条件
+     * @return
+     */
+    public Paper genPaper(List<String> paperIds, PaperStruct paperStruct, List<Condition> conditions) {
+        LinkedList<Question> questions = new LinkedList<Question>();// 所有试题集合
+        PaperContext paperContext = new PaperContext(paperStruct, conditions);
+        List<UnitContext> unitContexts = new LinkedList<UnitContext>();
+        List<DetailContext> detailContexts = paperContext.getDetails();
+        for (DetailContext dc : detailContexts) {
+            unitContexts.addAll(dc.getUnits());
+        }
+        List<Paper> papers = (List<Paper>) paperRepo.findAll(paperIds);
+        for (Paper oldPaper : papers) {
+            List<PaperDetailUnit> unitList = unitRepo.findByPaper(oldPaper);
+            for (PaperDetailUnit unit : unitList) {
+                questions.add(unit.getQuestion());
+            }
+
+        }
+        Collections.shuffle(questions);
+        int maxLoopCount = questions.size() * 2;
+        int selectCount = 0;
+        int maxCount = unitContexts.size();
+        int loopCount = 0;
+        while (questions.size() > 0 && (selectCount < maxCount) && loopCount < maxLoopCount) {
+            Question question = questions.removeFirst();
+            boolean structTypeMatch = false;
+            boolean selected = false;
+            for (UnitContext uc : unitContexts) {
+                if (uc.getUnitStruct().getQuestionType() == question.getQuestionType() && !uc.finish()) {
+                    structTypeMatch = true;
+                    if (uc.check(question)) {
+                        uc.select(question);
+                        selected = true;
+                        selectCount++;
+                        break;
+                    }
+                }
+            }
+            if (structTypeMatch && !selected) {
+                questions.addLast(question);
+            }
+            loopCount++;
+        }
+
+        Set<Question> quesSet = paperContext.getSelectQues();
+        List<PaperDetail> paperDetails = new ArrayList<PaperDetail>();
+        List<PaperDetailUnit> paperDetailunits = new ArrayList<PaperDetailUnit>();
+        for (DetailContext dc : detailContexts) {
+            List<PaperDetailUnit> unitsTemp = new ArrayList<PaperDetailUnit>();
+            List<UnitContext> units = dc.getUnits();
+            for (UnitContext uc : units) {
+                for (Question ques : quesSet) {
+                    if (uc.getUnitStruct().getQuestionType() == ques.getQuestionType()) {
+                        PaperDetailUnit pdu = new PaperDetailUnit();
+                        pdu.setCreateTime(CommonUtils.getCurDateTime());
+                        pdu.setQuestion(ques);
+                        pdu.setQuestionType(ques.getQuestionType());
+                        pdu.setScore(uc.getUnitStruct().getScore());
+                        unitsTemp.add(pdu);
+                    }
+
+                }
+
+            }
+            paperDetails.add(this.constuctPaperDeatil(unitsTemp, dc.getDetailStruct().getNumber(),
+                    dc.getDetailStruct().getName()));
+            paperDetailunits.addAll(unitsTemp);
+        }
+        Paper paper = this.constuctPaperByPaperDetails(paperDetails, paperStruct.getName());
+        this.persistentPaper(paperDetails, paperDetailunits, paper);
+        return paper;
+    }
+}

+ 17 - 0
cqb-gen-paper/src/main/java/com/qmth/cqb/genpaper/valve/Valve.java

@@ -0,0 +1,17 @@
+package com.qmth.cqb.genpaper.valve;
+
+import java.util.Map;
+
+import com.qmth.cqb.question.model.Question;
+
+public interface Valve {
+	
+	public boolean check(Question question);
+	
+	public void select(Question question);
+	
+	public Map<String,String> status();
+	
+	public void reset();
+
+}

+ 6 - 1
cqb-gen-paper/src/main/java/com/qmth/cqb/genpaper/web/GenPaperController.java

@@ -3,10 +3,15 @@ package com.qmth.cqb.genpaper.web;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Controller;
 
+import com.qmth.cqb.genpaper.service.GenPaperService;
+
 /**
  * Created by songyue on 16/12/28.
  */
 @Controller
 public class GenPaperController {
-   
+
+    @Autowired
+    GenPaperService genPaperService;
+
 }

+ 14 - 8
cqb-question-resource/src/main/java/com/qmth/cqb/question/model/QuestionType.java

@@ -22,6 +22,16 @@ public class QuestionType implements Serializable{
 		return serialVersionUID;
 	}
 
+	public String getName() {
+		return name;
+	}
+
+	public void setName(String name) {
+		this.name = name;
+	}
+	
+
+
 	public QuesStructType getQuesType() {
 		return quesType;
 	}
@@ -30,12 +40,8 @@ public class QuestionType implements Serializable{
 		this.quesType = quesType;
 	}
 
-	public String getName() {
-		return name;
-	}
-
-	public void setName(String name) {
-		this.name = name;
+	public static long getSerialversionuid() {
+		return serialVersionUID;
 	}
 
 	public Map getParams() {
@@ -49,8 +55,8 @@ public class QuestionType implements Serializable{
 	public QuestionType() {
     }
 
-	public QuestionType(QuesStructType quesType,String name) {
-		this.quesType = quesType;
+	public QuestionType(QuesStructType quesStructType,String name) {
+		this.quesType = quesStructType;
 		this.name = name;
 	}
 }

+ 1 - 1
cqb-starter/src/test/java/com/qmth/cqb/AppTest.java

@@ -226,7 +226,7 @@ public class AppTest {
         ExtractConfig extractConfig = new ExtractConfig();
         extractConfig.setExamId((long)1);
         extractConfig.setCourseCode("1");
-        extractConfig.setPolicy(ExtractPolicy.ExtractPolicy);
+        extractConfig.setPolicy(ExtractPolicy.RANDOM_POLICY);
         extractConfigRepo.save(extractConfig);
     }