Pārlūkot izejas kodu

美术阅卷10月新增需求-新增仲裁自动打回

wangliang 5 gadi atpakaļ
vecāks
revīzija
5e5cd162df

+ 139 - 0
stmms-ms-commons/src/main/java/cn/com/qmth/stmms/ms/commons/constant/ArbitrateCallback.java

@@ -0,0 +1,139 @@
+package cn.com.qmth.stmms.ms.commons.constant;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
+/**
+ * @Description: 仲裁自动打回算法
+ * @Param:
+ * @return:
+ * @Author: wangliang
+ * @Date: 2019/11/6
+ */
+public class ArbitrateCallback {
+    private static Logger LOGGER = LoggerFactory.getLogger(ArbitrateCallback.class);
+
+    public static char[] LEVELS = new char[5];//各评卷员评选的档位数组
+
+    public static int MAX_DISTANCE = 2 //仲裁档位
+            , SUM_DISTANCE = 2 * 2 + 1;//最大落差档位和
+
+    /**
+     * 自动打回算法
+     *
+     * @param levelList
+     * @param maxDistance
+     * @return
+     */
+    public static List<String> judge(List<String> levelList, int maxDistance) {
+        MAX_DISTANCE = maxDistance;
+        SUM_DISTANCE = MAX_DISTANCE * 2 + 1;
+        List<String> resultList = null;
+        Collections.sort(levelList);
+        for (int i = 0; i < levelList.size(); i++) {
+            LEVELS[i] = levelList.get(i).charAt(0);
+        }
+        List<Distance> result = judge(LEVELS);
+        if (Objects.nonNull(result)) {
+            resultList = result.stream().map(o -> String.valueOf(o.c)).collect(Collectors.toList());
+            LOGGER.info("LEVELS:{},需要打回的档位为:{}", LEVELS, resultList);
+        }
+        return resultList;
+    }
+
+//    public static void main(String[] args) {
+//        Scanner scanner = new Scanner(System.in);
+//        LOGGER.info("请输入5个需要仲裁的档位:");
+//        String[] strs = new String[5];
+//        int index = 0;
+//        while (scanner.hasNext()) {
+//            strs[index] = scanner.next().toUpperCase();
+//            index++;
+//            if (index > 4) {
+//                break;
+//            }
+//        }
+//        scanner.close();
+//        Arrays.sort(strs);
+//        for (int i = 0; i < strs.length; i++) {
+//            LEVELS[i] = strs[i].charAt(0);
+//        }
+//        LOGGER.info(JSONObject.toJSONString(LEVELS));
+//
+//        String content = new StringBuffer(String.valueOf(LEVELS[0])).append(LEVELS[1]).append(LEVELS[2])
+//                .append(LEVELS[3]).append(LEVELS[4]).toString();
+//        List<Distance> output = judge(LEVELS);
+//        if (Objects.nonNull(output)) {
+//            LOGGER.info("content:{},需要打回的档位为:{}", content, JSONObject.toJSONString(output));
+//            List<String> list = output.stream().map(o -> String.valueOf(o.c)).collect(Collectors.toList());
+//            LOGGER.info("list:{}", list);
+//        }
+//    }
+
+    /**
+     * 计算档位最大落差档位和档位和
+     *
+     * @param levels
+     * @return
+     */
+    public static List<Distance> judge(char[] levels) {
+        List<Distance> result = new ArrayList<>();
+        for (char c : levels) {
+            Distance d = new Distance(c);
+            for (char other : levels) {
+                int distance = Math.abs(c - other);
+                d.max = Math.max(d.max, distance);
+                d.sum += distance;
+            }
+            if (d.max >= MAX_DISTANCE && d.sum > SUM_DISTANCE) {
+                result.add(d);
+            }
+        }
+        return result;
+    }
+
+    /**
+     * 档位计算类[档位,最大档位落差,最大档位落差和]
+     */
+    static class Distance {
+        char c;
+        int max;
+        int sum;
+
+        public Distance(char c) {
+            this.c = c;
+            this.max = 0;
+            this.sum = 0;
+        }
+
+        public char getC() {
+            return c;
+        }
+
+        public void setC(char c) {
+            this.c = c;
+        }
+
+        public int getMax() {
+            return max;
+        }
+
+        public void setMax(int max) {
+            this.max = max;
+        }
+
+        public int getSum() {
+            return sum;
+        }
+
+        public void setSum(int sum) {
+            this.sum = sum;
+        }
+    }
+}

+ 94 - 70
stmms-ms-marking/src/main/java/cn/com/qmth/stmms/ms/marking/service/MarkingService.java

@@ -1,30 +1,21 @@
 package cn.com.qmth.stmms.ms.marking.service;
 
-import java.util.Date;
-import java.util.List;
-import java.util.Objects;
-import java.util.OptionalDouble;
-
+import cn.com.qmth.stmms.ms.commons.constant.ArbitrateCallback;
+import cn.com.qmth.stmms.ms.core.domain.*;
+import cn.com.qmth.stmms.ms.core.domain.task.MarkTask;
 import cn.com.qmth.stmms.ms.core.domain.user.MarkUser;
-import cn.com.qmth.stmms.ms.core.repository.MarkUserRepo;
+import cn.com.qmth.stmms.ms.core.domain.user.Role;
+import cn.com.qmth.stmms.ms.core.repository.*;
 import cn.com.qmth.stmms.ms.marking.config.MarkingConfig;
 import cn.com.qmth.stmms.ms.marking.service.arbitration.ArbitrationService;
-
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
-import cn.com.qmth.stmms.ms.core.domain.Level;
-import cn.com.qmth.stmms.ms.core.domain.MarkStage;
-import cn.com.qmth.stmms.ms.core.domain.MarkSubject;
-import cn.com.qmth.stmms.ms.core.domain.Paper;
-import cn.com.qmth.stmms.ms.core.domain.task.MarkTask;
-import cn.com.qmth.stmms.ms.core.repository.LevelRepo;
-import cn.com.qmth.stmms.ms.core.repository.MarkSubjectRepo;
-import cn.com.qmth.stmms.ms.core.repository.MarkTaskRepo;
-import cn.com.qmth.stmms.ms.core.repository.PaperRepo;
+import java.util.*;
+import java.util.stream.Collectors;
 
 /**
  * 评卷,分档仲裁及打分服务
@@ -51,10 +42,13 @@ public class MarkingService {
 
     @Autowired
     private LevelRepo levelRepo;
-    
+
     @Autowired
     private MarkSubjectRepo markSubjectRepo;
 
+    @Autowired
+    MarkLogRepo markLogRepo;
+
     /**
      * 提交分档。如果每个评卷都提交了,则进行仲裁判定,如果没有触发仲裁就定档
      *
@@ -73,31 +67,31 @@ public class MarkingService {
             return markTask;
         }
         /**
-        阀值判断
+         阀值判断
 
-        //控制分档比例
-        List<Level> levels = levelRepo.findByWorkId(markTask.getWorkId());
-        Level targetLevel = null;
-        for (Level l : levels) {
-            if (l.getCode().equals(levelCode)) {
-                targetLevel = l;
-                break;
-            }
-        }
-        int pt = targetLevel.getPt();
-        int count = markTaskRepo.countByWorkIdAndSubjectAndMarkerIdAndStageAndResult(markTask.getWorkId(), markTask.getSubject(), markTask.getMarkerId(), markTask.getStage(), levelCode);
-        int total = markTaskRepo.countByWorkIdAndSubjectAndMarkerIdAndStage(markTask.getWorkId(), markTask.getSubject(), markTask.getMarkerId(), markTask.getStage());
+         //控制分档比例
+         List<Level> levels = levelRepo.findByWorkId(markTask.getWorkId());
+         Level targetLevel = null;
+         for (Level l : levels) {
+         if (l.getCode().equals(levelCode)) {
+         targetLevel = l;
+         break;
+         }
+         }
+         int pt = targetLevel.getPt();
+         int count = markTaskRepo.countByWorkIdAndSubjectAndMarkerIdAndStageAndResult(markTask.getWorkId(), markTask.getSubject(), markTask.getMarkerId(), markTask.getStage(), levelCode);
+         int total = markTaskRepo.countByWorkIdAndSubjectAndMarkerIdAndStage(markTask.getWorkId(), markTask.getSubject(), markTask.getMarkerId(), markTask.getStage());
 
-        if ((count + 1.0D) / total * 1.0D > pt / 100.D) {
-            throw new RuntimeException(levelCode + "档已满,占比总阀值已达" + pt + "%。");
-        }
-        //判断考点阀值是否已满
-        int kdpt = targetLevel.getKdpt();
-        int kdcount = markTaskRepo.countByWorkIdAndSubjectAndMarkerIdAndStageAndQuestionIdAndResult(markTask.getWorkId(), markTask.getSubject(), markTask.getMarkerId(), markTask.getStage(), markTask.getQuestionId(), levelCode);
-        int kdtotal = markTaskRepo.countByWorkIdAndSubjectAndMarkerIdAndStageAndQuestionId(markTask.getWorkId(), markTask.getSubject(), markTask.getMarkerId(), markTask.getStage(), markTask.getQuestionId());
-        if ((kdcount + 1.0D) / kdtotal * 1.0D > kdpt / 100.D) {
-            throw new RuntimeException(levelCode + "档已满,考点阀值已达" + kdpt + "%。");
-        }
+         if ((count + 1.0D) / total * 1.0D > pt / 100.D) {
+         throw new RuntimeException(levelCode + "档已满,占比总阀值已达" + pt + "%。");
+         }
+         //判断考点阀值是否已满
+         int kdpt = targetLevel.getKdpt();
+         int kdcount = markTaskRepo.countByWorkIdAndSubjectAndMarkerIdAndStageAndQuestionIdAndResult(markTask.getWorkId(), markTask.getSubject(), markTask.getMarkerId(), markTask.getStage(), markTask.getQuestionId(), levelCode);
+         int kdtotal = markTaskRepo.countByWorkIdAndSubjectAndMarkerIdAndStageAndQuestionId(markTask.getWorkId(), markTask.getSubject(), markTask.getMarkerId(), markTask.getStage(), markTask.getQuestionId());
+         if ((kdcount + 1.0D) / kdtotal * 1.0D > kdpt / 100.D) {
+         throw new RuntimeException(levelCode + "档已满,考点阀值已达" + kdpt + "%。");
+         }
          */
 
         MarkUser maker = markUserRepo.findOne(markTask.getMarkerId());
@@ -123,9 +117,36 @@ public class MarkingService {
             if (result) {
                 //仲裁
                 paper.arbitrate();
+                List<String> levels = markTasks.stream().map(o -> o.getResult()).collect(Collectors.toList());
+                //20191107wangliang加入仲裁自动打回算法
+                List<String> list = ArbitrateCallback.judge(levels, markingConfig.getDeviation());
+                if (Objects.nonNull(list) && list.size() > 0) {
+                    paper.reject(null);
+                    String operResult = "-";
+                    List<MarkLog> markLogList = new ArrayList<>();
+                    for (String s : list) {
+                        for (MarkTask m : markTasks) {
+                            if (Objects.equals(s, m.getResult())) {
+                                m.setRejected(true);
+                                m.setOriginLevel(markTask.getResult());
+                                m.setResult(null);
+                                MarkLog markLogPrev = markLogRepo.findTopByCreateUserIdAndOperTypeAndSubjectAndExamNumberOrderByCreateTimeDesc(-1L, MarkLogOperType.SYSTEM_CALLBACK_LEVEl.getId(), markTask.getSubject().toString(), paper.getExamNumber());
+                                if (Objects.nonNull(markLogPrev)) {
+                                    operResult = Optional.ofNullable(markLogPrev.getOperDataAfter()).orElse("-");
+                                }
+                                //加入打回日志
+                                MarkLog markLog = new MarkLog(-1L, Role.ADMIN.getName(), Role.ADMIN, markTask.getSubject(), paper.getExamNumber(), paper.getStudentName(), MarkLogOperType.SYSTEM_CALLBACK_LEVEl.getId(), paper.getWorkId(), paper.getId(), markTask.getStage(), operResult, s, "仲裁自动打回");
+                                markLogList.add(markLog);
+                            }
+                        }
+                    }
+                    markTaskRepo.save(markTasks);
+                    paperRepo.save(paper);
+                    markLogRepo.save(markLogList);
+                }
             } else {
                 //定档
-                DeterResult determine = determineLevelService.determine(markingConfig.isMajority(),markTasks.toArray(sources));
+                DeterResult determine = determineLevelService.determine(markingConfig.isMajority(), markTasks.toArray(sources));
                 paper.determineLevel(determine.getResult());
                 if (determine.getDeterType() == DetermineLevelService.DeterType.WEIGHT) {
                     paper.setMarkedLogic(true);
@@ -145,7 +166,7 @@ public class MarkingService {
      * @param level
      */
     @Transactional
-    public Paper levelMarkPaper(Paper paper, String level,boolean isSample) {
+    public Paper levelMarkPaper(Paper paper, String level, boolean isSample) {
         //2019.10.12 湖北美术统考去掉标准卷设置数量
 //    	if(isSample){
 //    		MarkSubject markSubject = markSubjectRepo.findOne(paper.getWorkId() + "-" + paper.getSubject().toString());
@@ -154,15 +175,15 @@ public class MarkingService {
 //    			throw new RuntimeException("标准卷上限已达到");
 //    		}
 //    	}
-    	paper.determineLevel(level);
-    	paper.setMarkByLeader(true);
-    	paper.setSample(isSample);
-    	paperRepo.save(paper);
-    	List<MarkTask> markTasks = markTaskRepo.findByPaperIdAndStage(paper.getId(), MarkStage.LEVEL);
-    	for (MarkTask markTask : markTasks) {
-    		markTask.setResult(level);
-    	}
-    	markTaskRepo.save(markTasks);
+        paper.determineLevel(level);
+        paper.setMarkByLeader(true);
+        paper.setSample(isSample);
+        paperRepo.save(paper);
+        List<MarkTask> markTasks = markTaskRepo.findByPaperIdAndStage(paper.getId(), MarkStage.LEVEL);
+        for (MarkTask markTask : markTasks) {
+            markTask.setResult(level);
+        }
+        markTaskRepo.save(markTasks);
         return paper;
     }
 
@@ -171,7 +192,8 @@ public class MarkingService {
      * 更新试卷状态
      * 更新评卷任务状态为打回
      * 如果评卷任务的档位和建议档位一致,不打回该任务
-     *  @param paper
+     *
+     * @param paper
      * @param redoLevel 建议重评档位
      * @param ranges
      */
@@ -188,9 +210,9 @@ public class MarkingService {
                 markTask.setResult(null);
             }*/
             String[] range = ranges.split(",");
-            if(range.length > 0){
+            if (range.length > 0) {
                 for (String r : range) {
-                    if(Objects.equals(String.valueOf(markTask.getMarkerId()), r)){
+                    if (Objects.equals(String.valueOf(markTask.getMarkerId()), r)) {
                         markTask.setRejected(true);
                         markTask.setOriginLevel(markTask.getResult());
                         markTask.setResult(null);
@@ -232,25 +254,27 @@ public class MarkingService {
         }
         return markTask;
     }
+
     /**
      * 跳过该任务,最后处理
+     *
      * @param markTaskId
      */
     @Transactional
-	public MarkTask skip(Long markTaskId) {
-		try {
-			MarkTask m = markTaskRepo.findOne(markTaskId);
-			Integer randomSeq = markTaskRepo.findRandomSeqByWorkIdAndSubjectAndMarkerIdAndStageAndQuestionId(m.getWorkId(), m.getSubject(),m.getMarkerId(), m.getStage(), m.getQuestionId());
-			if(randomSeq == null){
-				randomSeq = 0;
-			}
-			m.setRandomSeq(randomSeq+1);
-			markTaskRepo.save(m);
-			return m;
-		} catch (Exception e) {
-			e.printStackTrace();
-			throw new RuntimeException("该任务可能被占用,跳过失败");
-		}
-		
-	}
+    public MarkTask skip(Long markTaskId) {
+        try {
+            MarkTask m = markTaskRepo.findOne(markTaskId);
+            Integer randomSeq = markTaskRepo.findRandomSeqByWorkIdAndSubjectAndMarkerIdAndStageAndQuestionId(m.getWorkId(), m.getSubject(), m.getMarkerId(), m.getStage(), m.getQuestionId());
+            if (randomSeq == null) {
+                randomSeq = 0;
+            }
+            m.setRandomSeq(randomSeq + 1);
+            markTaskRepo.save(m);
+            return m;
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new RuntimeException("该任务可能被占用,跳过失败");
+        }
+
+    }
 }