Kaynağa Gözat

feat: 新增打分功能

181250114 4 yıl önce
ebeveyn
işleme
f2ea644a1a

+ 23 - 0
src/main/java/com/seecoder/dataanalysis/analysis/DevcloudScoreService.java

@@ -0,0 +1,23 @@
+package com.seecoder.dataanalysis.analysis;
+
+import com.seecoder.dataanalysis.data.entity.devcloud.display.FormatScore;
+
+/**
+ * 根据devcloud的学生行为,为小组和学生进行打分
+ * @author Peng Yiyan
+ * @since 2022/08/20
+ */
+public interface DevcloudScoreService {
+
+    /**
+     * 根据学生id得到对应小组得分情况
+     * @param user_id
+     */
+    FormatScore getGroupScore(int user_id);
+
+    /**
+     * 根据学生id得到对应学生得分情况
+     * @param user_id
+     */
+    FormatScore getStudentScore(int user_id);
+}

+ 5 - 0
src/main/java/com/seecoder/dataanalysis/analysis/impl/DevcloudDataAnalysisServiceImpl.java

@@ -995,6 +995,7 @@ public class DevcloudDataAnalysisServiceImpl implements DevcloudDataAnalysisServ
         List<Contribution> commitContribution = new ArrayList<>();
         for(int i=0;i<userIds.size();i++){
             Contribution contribution = new Contribution();
+            contribution.setUserId(users.get(i).getUserId());
             contribution.setName(users.get(i).getName());
             contribution.setTimes(commitTimes[i]);
             Double value;
@@ -1015,6 +1016,7 @@ public class DevcloudDataAnalysisServiceImpl implements DevcloudDataAnalysisServ
         List<Contribution> testContribution = new ArrayList<>();
         for(int i=0;i<userIds.size();i++){
             Contribution contribution = new Contribution();
+            contribution.setUserId(users.get(i).getUserId());
             contribution.setName(users.get(i).getName());
             contribution.setTimes(testTimes[i]);
             Double value;
@@ -1034,6 +1036,7 @@ public class DevcloudDataAnalysisServiceImpl implements DevcloudDataAnalysisServ
         List<Contribution> deployContribution = new ArrayList<>();
         for(int i=0;i<userIds.size();i++){
             Contribution contribution = new Contribution();
+            contribution.setUserId(users.get(i).getUserId());
             contribution.setName(users.get(i).getName());
             contribution.setTimes(pipeTimes[i]);
             Double value;
@@ -1053,6 +1056,7 @@ public class DevcloudDataAnalysisServiceImpl implements DevcloudDataAnalysisServ
         List<Contribution> bugContribution = new ArrayList<>();
         for(int i=0;i<userIds.size();i++){
             Contribution contribution = new Contribution();
+            contribution.setUserId(users.get(i).getUserId());
             contribution.setName(users.get(i).getName());
             contribution.setTimes(bugTimes[i]);
             Double value;
@@ -1072,6 +1076,7 @@ public class DevcloudDataAnalysisServiceImpl implements DevcloudDataAnalysisServ
         List<Contribution> treeNodeContribution = new ArrayList<>();
         for(int i=0;i<userIds.size();i++){
             Contribution contribution = new Contribution();
+            contribution.setUserId(users.get(i).getUserId());
             contribution.setName(users.get(i).getName());
             contribution.setTimes(treeNodeTimes[i]);
             Double value;

+ 361 - 0
src/main/java/com/seecoder/dataanalysis/analysis/impl/DevcloudScoreServiceImpl.java

@@ -0,0 +1,361 @@
+package com.seecoder.dataanalysis.analysis.impl;
+
+import com.seecoder.dataanalysis.analysis.DevcloudDataAnalysisService;
+import com.seecoder.dataanalysis.analysis.DevcloudScoreService;
+import com.seecoder.dataanalysis.analysis.DisplayService;
+import com.seecoder.dataanalysis.data.entity.devcloud.display.Contribution;
+import com.seecoder.dataanalysis.data.entity.devcloud.display.FormatGroup;
+import com.seecoder.dataanalysis.data.entity.devcloud.display.FormatScore;
+import com.seecoder.dataanalysis.data.entity.devcloud.display.FormatStudent;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@Service
+public class DevcloudScoreServiceImpl implements DevcloudScoreService {
+    @Autowired
+    private DevcloudDataAnalysisService devcloudDataAnalysisService;
+    @Autowired
+    private DisplayService displayService;
+
+    public static final int A = 80;
+    public static final int B = 100;
+
+    public static final int COMMIT_TIME = 80;
+    public static final int COMMIT_TIME_PER = 20;
+    public static final double COMMIT_VALID_RATE = 0.6;
+    public static final int BUG_TIME = 8;
+    public static final int BUG_TIME_PER = 2;
+    public static final double BUG_FINISHED_RATE = 0.9;
+    public static final int NODE_TIME = 50;
+    public static final int NODE_TIME_PER = 12;
+    public static final double NODE_FINISHED_RATE = 0.5;
+    public static final int PIPELINE_TIME = 12;
+    public static final int PIPELINE_TIME_PER = 3;
+    public static final double PIPELINE_SUCCESS_RATE = 0.9;
+
+    public FormatScore getGroupScore(int user_id){
+        FormatScore formatScore = new FormatScore();
+        FormatGroup formatGroup = displayService.getGroupAnalysisById(user_id);
+        //commit
+        int commit_times = formatGroup.getCommit().getCommit_times();
+        int commit_valid_times = formatGroup.getCommit().getValid_commit_times();
+        double commit_valid_rate = (double) commit_valid_times/(double) commit_times;
+        double commitScore1 = 0.0,commitScore2 = 0.0,commitScore=0.0;
+        if(commit_times>=COMMIT_TIME){
+            commitScore1 = 100;
+        }else {
+            commitScore1 = commit_times/COMMIT_TIME * 100;
+        }
+        if(commit_valid_rate>=COMMIT_VALID_RATE){
+            commitScore2 = 100;
+        }else {
+            commitScore2 = commit_valid_rate/COMMIT_VALID_RATE * 100;
+        }
+        commitScore = (commitScore1+commitScore2)/2;
+        formatScore.setCommitScore(commitScore);
+
+        //bugList
+        int bug_times = formatGroup.getBuglist().getBug_times();
+        int bug_finished_times = formatGroup.getBuglist().getFinished_times();
+        double bug_finished_rate = (double)bug_finished_times/(double)bug_times;
+        double bugScore1=0.0,bugScore2=0.0,bugScore=0.0;
+        if(bug_times>=BUG_TIME){
+            bugScore1 = 100;
+        }else {
+            bugScore1 = bug_times/BUG_TIME * 100;
+        }
+        if(bug_finished_rate>=BUG_FINISHED_RATE){
+            bugScore2 = 100;
+        }else {
+            bugScore2 = bug_finished_rate/BUG_FINISHED_RATE * 100;
+        }
+        bugScore = (bugScore1+bugScore2)/2;
+        formatScore.setBugScore(bugScore);
+
+        //nodeList
+        int treeNode_times = formatGroup.getTreeNode().getTreeNode_times();
+        int treeNode_finished_times = formatGroup.getTreeNode().getFinished_treeNode_times();
+        double treeNode_finished_rate = (double) treeNode_finished_times/ (double) treeNode_times;
+        double nodeScore1=0.0,nodeScore2=0.0,nodeScore=0.0;
+        if(treeNode_times>=NODE_TIME){
+            nodeScore1 = 100;
+        }else {
+            nodeScore1 = treeNode_times/NODE_TIME * 100;
+        }
+        if(treeNode_finished_rate>=NODE_FINISHED_RATE){
+            nodeScore2 = 100;
+        }else {
+            nodeScore2 = treeNode_finished_rate/NODE_FINISHED_RATE * 100;
+        }
+        nodeScore = (nodeScore1+nodeScore2)/2;
+        formatScore.setNodeScore(nodeScore);
+
+        //pipeline
+        int pipeline_times = formatGroup.getPipeline().getPipeline_deploy();
+        int pipeline_success_times = formatGroup.getPipeline().getPipeline_pass();
+        double pipeline_success_rate = (double)pipeline_success_times/(double)pipeline_times;
+        double pipelineScore1=0.0,pipelineScore2=0.0,pipelineScore=0.0;
+        if(pipeline_times>=PIPELINE_TIME){
+            pipelineScore1 = 100;
+        }else {
+            pipelineScore1 = pipeline_times/PIPELINE_TIME * 100;
+        }
+        if(pipeline_success_rate>=PIPELINE_SUCCESS_RATE){
+            pipelineScore2 = 100;
+        }else {
+            pipelineScore2 = pipeline_success_rate/PIPELINE_SUCCESS_RATE * 100;
+        }
+        pipelineScore = (nodeScore1+nodeScore2)/2;
+        formatScore.setPipelineScore(pipelineScore);
+
+        //bonus,根据学生的分数占比计算
+        List<Contribution> commitContribution = formatGroup.getCommit().getCommit_contribution();
+        int totalCommit = 0;
+        for(Contribution contribution:commitContribution){
+            totalCommit += contribution.getTimes();
+        }
+        double[] xCommit=new double[commitContribution.size()];
+        if(totalCommit!=0){
+            for(int i=0;i<commitContribution.size();i++){
+                xCommit[i] = commitContribution.get(i).getTimes()/totalCommit;
+            }
+        }
+
+        List<Contribution> bugContribution = formatGroup.getBuglist().getBug_contribution();
+        int totalBug = 0;
+        for(Contribution contribution:bugContribution){
+            totalBug += contribution.getTimes();
+        }
+        double[] xBug=new double[bugContribution.size()];
+        if(totalBug!=0){
+            for(int i=0;i<bugContribution.size();i++){
+                xBug[i] = bugContribution.get(i).getTimes()/totalBug;
+            }
+        }
+
+        List<Contribution> nodeContribution = formatGroup.getTreeNode().getTreeNode_contribution();
+        int totalNode = 0;
+        for(Contribution contribution:nodeContribution){
+            totalNode += contribution.getTimes();
+        }
+        double[] xNode=new double[nodeContribution.size()];
+        if(totalNode!=0){
+            for(int i=0;i<nodeContribution.size();i++){
+                xNode[i] = nodeContribution.get(i).getTimes()/totalNode;
+            }
+        }
+
+        List<Contribution> pipeContribution = formatGroup.getPipeline().getPipeline_contribution();
+        int totalPipe = 0;
+        for(Contribution contribution:pipeContribution){
+            totalPipe += contribution.getTimes();
+        }
+        double[] xPipe=new double[pipeContribution.size()];
+        if(totalPipe!=0){
+            for(int i=0;i<pipeContribution.size();i++){
+                xPipe[i] = pipeContribution.get(i).getTimes()/totalPipe;
+            }
+        }
+
+        double s1=StandardDiviation(xCommit),s2=StandardDiviation(xBug),s3=StandardDiviation(xNode),s4=StandardDiviation(xPipe);
+        double s = 10 - (s1+s2+s3+s4)*10;
+
+        //计算基础四项总分
+        double preScore = Math.ceil((commitScore+bugScore+nodeScore+pipelineScore)/4);
+        double bonus = Math.ceil(s);
+
+        formatScore.setTotalScore(preScore+bonus);
+        formatScore.setBonus(bonus);
+
+        return formatScore;
+    }
+
+
+
+    public FormatScore getStudentScore(int user_id){
+        FormatScore formatScoreMain = getBasicScore(user_id);
+        Map<Integer,Double> totalScore = new HashMap<>();
+        List<Integer> userIds = new ArrayList<>();
+
+        //bonus,根据学生的分数占比计算
+        FormatGroup formatGroup = displayService.getGroupAnalysisById(user_id);
+        Map<Integer,Double> bonusScore = new HashMap<>();
+        List<Contribution> commitContribution = formatGroup.getCommit().getCommit_contribution();
+        List<Contribution> bugContribution = formatGroup.getBuglist().getBug_contribution();
+        List<Contribution> nodeContribution = formatGroup.getTreeNode().getTreeNode_contribution();
+        List<Contribution> pipeContribution = formatGroup.getPipeline().getPipeline_contribution();
+        for(Contribution contribution : commitContribution){
+            int id = contribution.getUserId();
+            userIds.add(id);
+            bonusScore.put(id,bonusScore.getOrDefault(id,0.0)+contribution.getProportion());
+        }
+        for(Contribution contribution : bugContribution){
+            int id = contribution.getUserId();
+            bonusScore.put(id,bonusScore.getOrDefault(id,0.0)+contribution.getProportion());
+        }
+        for(Contribution contribution : nodeContribution){
+            int id = contribution.getUserId();
+            bonusScore.put(id,bonusScore.getOrDefault(id,0.0)+contribution.getProportion());
+        }
+        for(Contribution contribution : pipeContribution){
+            int id = contribution.getUserId();
+            bonusScore.put(id,bonusScore.getOrDefault(id,0.0)+contribution.getProportion());
+        }
+        //遍历计算得到bonus的值
+        for(Map.Entry<Integer,Double> entry : bonusScore.entrySet()){
+            double value = entry.getValue();
+            value = value/4.0 - 0.25;
+            if(value < 0){
+                entry.setValue(0.0);
+            }else {
+                entry.setValue(value);
+            }
+        }
+
+        //使用targetIndex记录目标user_id的位置
+        int index=0,targetIndex=0;
+        double[] ori = new double[userIds.size()];
+        //计算基础四项总分
+        for(int userId : userIds){
+            FormatScore formatScore = getBasicScore(userId);
+            double total = 0.0;
+            total += formatScore.getCommitScore();
+            total += formatScore.getBugScore();
+            total += formatScore.getNodeScore();
+            total += formatScore.getPipelineScore();
+            total = Math.ceil(total/4.0);
+            total += Math.ceil(bonusScore.get(userId));
+            totalScore.put(userId,total);
+            ori[index] = total;
+            if(userId == user_id){
+                targetIndex = index;
+            }
+            index++;
+        }
+
+        //将分数映射到A B上
+        double Xmin = 0.0,Xmax = 0.0;
+        for(int i=0;i<ori.length;i++){
+            double d = ori[i];
+            if(d<=Xmin){
+                Xmin = d;
+            }
+            if(d>=Xmax){
+                Xmax = d;
+            }
+        }
+        if(Xmin != Xmax){
+            for(int i=0;i<ori.length;i++){
+                ori[i] = A + (B-A) / (Xmax-Xmin) * (ori[i]-Xmin);
+            }
+        }
+
+        formatScoreMain.setTotalScore(ori[targetIndex]);
+        formatScoreMain.setBonus(bonusScore.get(user_id));
+
+        return formatScoreMain;
+    }
+
+    //根据学生id计算学生的基础得分
+    public FormatScore getBasicScore(int user_id){
+        FormatScore formatScore = new FormatScore();
+        FormatStudent formatStudent = devcloudDataAnalysisService.getStudentAnalysis(user_id);
+        //commit
+        int commit_times = formatStudent.getCommit().getCommit_times();
+        int commit_valid_times = formatStudent.getCommit().getValid_commit_times();
+        double commit_valid_rate = (double) commit_valid_times/(double) commit_times;
+        double commitScore1 = 0.0,commitScore2 = 0.0,commitScore=0.0;
+        if(commit_times>=COMMIT_TIME_PER){
+            commitScore1 = 100;
+        }else {
+            commitScore1 = commit_times/COMMIT_TIME_PER * 100;
+        }
+        if(commit_valid_rate>=COMMIT_VALID_RATE){
+            commitScore2 = 100;
+        }else {
+            commitScore2 = commit_valid_rate/COMMIT_VALID_RATE * 100;
+        }
+        commitScore = (commitScore1+commitScore2)/2;
+        formatScore.setCommitScore(commitScore);
+
+        //bugList
+        int bug_times = formatStudent.getBuglist().getBug_times();
+        int bug_finished_times = formatStudent.getBuglist().getFinished_times();
+        double bug_finished_rate = (double)bug_finished_times/(double)bug_times;
+        double bugScore1=0.0,bugScore2=0.0,bugScore=0.0;
+        if(bug_times>=BUG_TIME_PER){
+            bugScore1 = 100;
+        }else {
+            bugScore1 = bug_times/BUG_TIME_PER * 100;
+        }
+        if(bug_finished_rate>=BUG_FINISHED_RATE){
+            bugScore2 = 100;
+        }else {
+            bugScore2 = bug_finished_rate/BUG_FINISHED_RATE * 100;
+        }
+        bugScore = (bugScore1+bugScore2)/2;
+        formatScore.setBugScore(bugScore);
+
+        //nodeList
+        int treeNode_times = formatStudent.getTreeNode().getTreeNode_times();
+        int treeNode_finished_times = formatStudent.getTreeNode().getFinished_treeNode_times();
+        double treeNode_finished_rate = (double) treeNode_finished_times/ (double) treeNode_times;
+        double nodeScore1=0.0,nodeScore2=0.0,nodeScore=0.0;
+        if(treeNode_times>=NODE_TIME_PER){
+            nodeScore1 = 100;
+        }else {
+            nodeScore1 = treeNode_times/NODE_TIME_PER * 100;
+        }
+        if(treeNode_finished_rate>=NODE_FINISHED_RATE){
+            nodeScore2 = 100;
+        }else {
+            nodeScore2 = treeNode_finished_rate/NODE_FINISHED_RATE * 100;
+        }
+        nodeScore = (nodeScore1+nodeScore2)/2;
+        formatScore.setNodeScore(nodeScore);
+
+        //pipeline
+        int pipeline_times = formatStudent.getPipeline().getPipeline_deploy();
+        int pipeline_success_times = formatStudent.getPipeline().getPipeline_pass();
+        double pipeline_success_rate = (double)pipeline_success_times/(double)pipeline_times;
+        double pipelineScore1=0.0,pipelineScore2=0.0,pipelineScore=0.0;
+        if(pipeline_times>=PIPELINE_TIME_PER){
+            pipelineScore1 = 100;
+        }else {
+            pipelineScore1 = pipeline_times/PIPELINE_TIME_PER * 100;
+        }
+        if(pipeline_success_rate>=PIPELINE_SUCCESS_RATE){
+            pipelineScore2 = 100;
+        }else {
+            pipelineScore2 = pipeline_success_rate/PIPELINE_SUCCESS_RATE * 100;
+        }
+        pipelineScore = (nodeScore1+nodeScore2)/2;
+        formatScore.setPipelineScore(pipelineScore);
+
+        return formatScore;
+    }
+
+
+    //标准差σ=sqrt(s^2)
+    public static double StandardDiviation(double[] x) {
+        int m=x.length;
+        double sum=0;
+        for(int i=0;i<m;i++){//求和
+            sum+=x[i];
+        }
+        double dAve=sum/m;//求平均值
+        double dVar=0;
+        for(int i=0;i<m;i++){//求方差
+            dVar+=(x[i]-dAve)*(x[i]-dAve);
+        }
+        return Math.sqrt(dVar/(m-1));
+//        return Math.sqrt(dVar/m);
+    }
+
+
+}

+ 5 - 0
src/main/java/com/seecoder/dataanalysis/data/entity/devcloud/display/Contribution.java

@@ -14,6 +14,11 @@ import lombok.experimental.Accessors;
 @Data
 public class Contribution {
 
+    /**
+     * 学生id
+     */
+    private int userId;
+
     /**
      * 学生姓名
      */

+ 46 - 0
src/main/java/com/seecoder/dataanalysis/data/entity/devcloud/display/FormatScore.java

@@ -0,0 +1,46 @@
+package com.seecoder.dataanalysis.data.entity.devcloud.display;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+
+/**
+ * 记录得分情况
+ */
+@AllArgsConstructor
+@Accessors(chain = true)
+@Data
+@NoArgsConstructor
+public class FormatScore {
+
+    /**
+     * 总分
+     */
+    private double totalScore;
+
+    /**
+     * commit得分
+     */
+    private double commitScore;
+
+    /**
+     * bug得分
+     */
+    private double bugScore;
+
+    /**
+     * 需求得分
+     */
+    private double nodeScore;
+
+    /**
+     * 部署得分
+     */
+    private double pipelineScore;
+
+    /**
+     * 额外得分
+     */
+    private double bonus;
+}