|
|
@@ -0,0 +1,68 @@
|
|
|
+package cn.seecoder.data.server.service.Impl;
|
|
|
+
|
|
|
+import cn.seecoder.data.server.domain.CoderDao;
|
|
|
+import cn.seecoder.data.server.repository.CoderRepository;
|
|
|
+import cn.seecoder.data.server.service.CoderService;
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+
|
|
|
+import java.time.LocalDateTime;
|
|
|
+import java.util.ArrayList;
|
|
|
+import java.util.Comparator;
|
|
|
+import java.util.List;
|
|
|
+import java.util.concurrent.atomic.AtomicReference;
|
|
|
+
|
|
|
+@Service
|
|
|
+public class CoderServiceImpl implements CoderService {
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ CoderRepository coderRepository;
|
|
|
+
|
|
|
+ final double HEIGH = 1.05;
|
|
|
+ final double HEIGH_MIDDLE = 1.0;
|
|
|
+ final double MIDDLE_LOW = 0.95;
|
|
|
+ final double LOW = 0.85;
|
|
|
+
|
|
|
+ final double MAX_SCORE = 100;
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public double getCoderGrade(Integer userId) {
|
|
|
+ AtomicReference<Double> grade = new AtomicReference<>(0.0);
|
|
|
+ AtomicReference<Double> sumGrade = new AtomicReference<>(0.0);
|
|
|
+ List<CoderDao> coderInfoByUser = coderRepository.findByUserId(userId);
|
|
|
+ coderInfoByUser.forEach(info -> {
|
|
|
+ double[] weight = new double[]{1.0, 1.0};
|
|
|
+ Integer score = info.getScore();
|
|
|
+ Integer problemId = info.getProblemId();
|
|
|
+ Integer examId = info.getExamId();
|
|
|
+ LocalDateTime lastCommitAt = info.getSubmitAt();
|
|
|
+ List<CoderDao> coderDaoList = coderRepository.findByExamIdAndProblemIdOrderByLastCommitAt(examId, problemId);
|
|
|
+
|
|
|
+ ArrayList<LocalDateTime> commitTimeQuartiles = new ArrayList<>(3);
|
|
|
+ commitTimeQuartiles.add(coderDaoList.get(coderDaoList.size()/4).getSubmitAt());
|
|
|
+ commitTimeQuartiles.add(coderDaoList.get(coderDaoList.size()*2/4).getSubmitAt());
|
|
|
+ commitTimeQuartiles.add(coderDaoList.get(coderDaoList.size()*3/4).getSubmitAt());
|
|
|
+ if(lastCommitAt.compareTo(commitTimeQuartiles.get(0))<=0) weight[0] = HEIGH;
|
|
|
+ else if(lastCommitAt.compareTo(commitTimeQuartiles.get(1))<=0) weight[0] = HEIGH_MIDDLE;
|
|
|
+ else if(lastCommitAt.compareTo(commitTimeQuartiles.get(2))<=0) weight[0] = MIDDLE_LOW;
|
|
|
+ else weight[0] = LOW;
|
|
|
+
|
|
|
+ Comparator<? super CoderDao> comparator = (Comparator<CoderDao>) (coderDao, t1) -> coderDao.getScore() - t1.getScore();
|
|
|
+ coderDaoList.sort(comparator);
|
|
|
+ ArrayList<Integer> scoreQuartiles = new ArrayList<>(3);
|
|
|
+ scoreQuartiles.add(coderDaoList.get(coderDaoList.size()/4).getScore());
|
|
|
+ scoreQuartiles.add(coderDaoList.get(coderDaoList.size()*2/4).getScore());
|
|
|
+ scoreQuartiles.add(coderDaoList.get(coderDaoList.size()*3/4).getScore());
|
|
|
+ if(score.compareTo(scoreQuartiles.get(0))<=0) weight[1] = HEIGH;
|
|
|
+ else if(score.compareTo(scoreQuartiles.get(1))<=0) weight[1] = HEIGH_MIDDLE;
|
|
|
+ else if(score.compareTo(scoreQuartiles.get(2))<=0) weight[1] = MIDDLE_LOW;
|
|
|
+ else weight[1] = LOW;
|
|
|
+
|
|
|
+ grade.updateAndGet(v -> v + weight[0] * weight[1] * score);
|
|
|
+ sumGrade.updateAndGet(v -> v + MAX_SCORE);
|
|
|
+ });
|
|
|
+
|
|
|
+ double result = grade.get() / sumGrade.get();
|
|
|
+ return Math.min(result, 1.0);
|
|
|
+ }
|
|
|
+}
|