sky 5 лет назад
Родитель
Сommit
fd94bab0a5

+ 16 - 0
seec-data-server/src/main/java/cn/seecoder/data/server/controller/EvaluateController.java

@@ -1,5 +1,8 @@
 package cn.seecoder.data.server.controller;
 
+import cn.seecoder.data.server.dto.evaluate.Response;
+import cn.seecoder.data.server.errorAndExceptions.ErrorCodeEnum;
+import cn.seecoder.data.server.service.EvaluateService;
 import cn.seecoder.data.server.vo.knowledge.*;
 import cn.seecoder.data.server.repository.GeneralRecordRepository;
 import cn.seecoder.data.server.repository.knowledge.KnowledgeRepository;
@@ -9,6 +12,8 @@ import org.springframework.web.bind.annotation.PathVariable;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
 
+import java.util.Map;
+
 @RestController
 public class EvaluateController {
 
@@ -18,10 +23,21 @@ public class EvaluateController {
     @Autowired
     KnowledgeRepository knowledgeRepository;
 
+    @Autowired
+    EvaluateService evaluateService;
+
     @RequestMapping("/user/{id}")
     public KnowledgePointVO getEvaluate(@PathVariable("id") Integer id){
         GeneralServiceImpl generalService = new GeneralServiceImpl(generalRecordRepository,knowledgeRepository);
         KnowledgePointVO root = generalService.getTreeNode(332);
         return root;
     }
+
+    @RequestMapping("/eval/analysis/{examId}")
+    public Response<Object> evalAnalysisByExamId(@PathVariable("examId") Integer examId) {
+        Map<String, Map<String, Double>> res = evaluateService.analyzeEvalTest(examId);
+        ErrorCodeEnum serviceErrorD0001 = ErrorCodeEnum.SERVICE_ERROR_D0001;
+        if(res == null) return Response.buildFailure(serviceErrorD0001.getCode(),serviceErrorD0001.getDescription());
+        return Response.buildSuccess(evaluateService.analyzeEvalTest(examId));
+    }
 }

+ 40 - 0
seec-data-server/src/main/java/cn/seecoder/data/server/dto/evaluate/ExamDetailsDto.java

@@ -0,0 +1,40 @@
+package cn.seecoder.data.server.dto.evaluate;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.time.LocalDateTime;
+import java.util.List;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class ExamDetailsDto {
+    /*
+    * {
+        "examId": 7,
+        "examName": "Java开发招聘",
+        "position": "Java开发",
+        "skills": [
+        "Java",
+        "MySQL"
+        ],
+        "difficulty": 0,
+        "startTime": "2020-11-18 10:00:00",
+        "endTime": "2020-11-18 16:43:00",
+        "comment": "hahahahha"
+        },
+    * */
+    private Integer examId;
+    private String examName;
+    private String position;
+    private List<String> skills;
+    private Integer difficulty;
+    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern="yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime startTime;
+    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern="yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime endTime;
+    private String comment;
+}

+ 7 - 1
seec-data-server/src/main/java/cn/seecoder/data/server/dto/evaluate/ExamQuestionAndScoreDto.java

@@ -1,10 +1,16 @@
 package cn.seecoder.data.server.dto.evaluate;
 
+import lombok.AllArgsConstructor;
+import lombok.Builder;
 import lombok.Data;
+import lombok.NoArgsConstructor;
 
 import java.util.Map;
 
 @Data
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
 public class ExamQuestionAndScoreDto {
-    private Map<String, Integer> questionAndScore;
+    private Map<String, Double> questionAndScore;
 }

+ 7 - 1
seec-data-server/src/main/java/cn/seecoder/data/server/dto/evaluate/ExamRecordDto.java

@@ -1,10 +1,15 @@
 package cn.seecoder.data.server.dto.evaluate;
 
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.AllArgsConstructor;
 import lombok.Data;
+import lombok.NoArgsConstructor;
 
 import java.time.LocalDateTime;
 
 @Data
+@AllArgsConstructor
+@NoArgsConstructor
 public class ExamRecordDto {
     /*
         "id": 162,
@@ -17,9 +22,10 @@ public class ExamRecordDto {
     * */
     private Integer id;
     private String questionId;
-    private Integer actualScore;
+    private Double actualScore;
     private Integer studentId;
     private String submitAnswer;
+    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern="yyyy-MM-dd HH:mm:ss")
     private LocalDateTime submitTime;
     private String message;
 }

+ 13 - 9
seec-data-server/src/main/java/cn/seecoder/data/server/dto/evaluate/Response.java

@@ -1,35 +1,39 @@
 package cn.seecoder.data.server.dto.evaluate;
 
+import lombok.AllArgsConstructor;
 import lombok.Data;
+import lombok.NoArgsConstructor;
 
 import java.io.Serializable;
 
 @Data
+@NoArgsConstructor
+@AllArgsConstructor
 public class  Response<T> implements Serializable {
 
-    private Integer code;
+    private String code;
 
     private String msg;
 
     private T result;
 
-    public Response(Integer code, String msg, T data) {
-        this.code = code;
-        this.msg = msg;
-        this.result = data;
-    }
+//    public Response(String code, String msg, T data) {
+//        this.code = code;
+//        this.msg = msg;
+//        this.result = data;
+//    }
 
 
     public static Response buildSuccess() {
-        return new Response(200, "", null);
+        return new Response("000000", "成功", null);
     }
 
 
     public static <T> Response<T> buildSuccess(T result) {
-        return new Response<T>(200, "", result);
+        return new Response<T>("000000", "", result);
     }
 
-    public static Response buildFailure(Integer code, String message) {
+    public static Response buildFailure(String code, String message) {
         return new Response(code,message, null);
     }
 }

+ 201 - 0
seec-data-server/src/main/java/cn/seecoder/data/server/errorAndExceptions/ErrorCodeEnum.java

@@ -0,0 +1,201 @@
+package cn.seecoder.data.server.errorAndExceptions;
+
+/**
+ * 阿里巴巴Java编码规范,错误码
+ */
+public enum ErrorCodeEnum {
+    SUCCESS("00000", "成功"),
+    USER_ERROR_0001("A0001", "用户端错误"),
+    USER_ERROR_A0100("A0100", "用户注册错误"),
+    USER_ERROR_A0101("A0101", "用户未同意隐私协议"),
+    USER_ERROR_A0102("A0102", "注册国家或地区受限"),
+    USER_ERROR_A0110("A0110", "用户名校验失败"),
+    USER_ERROR_A0111("A0111", "用户名已存在"),
+    USER_ERROR_A0112("A0112", "用户名包含敏感词"),
+    USER_ERROR_A0113("A0113", "用户名包含特殊字符"),
+    USER_ERROR_A0120("A0120", "密码校验失败"),
+    USER_ERROR_A0121("A0121", "密码长度不够"),
+    USER_ERROR_A0122("A0122", "密码强度不够"),
+    USER_ERROR_A0130("A0130", "校验码输入错误"),
+    USER_ERROR_A0131("A0131", "短信校验码输入错误"),
+    USER_ERROR_A0132("A0132", "邮件校验码输入错误"),
+    USER_ERROR_A0133("A0133", "语音校验码输入错误"),
+    USER_ERROR_A0140("A0140", "用户证件异常"),
+    USER_ERROR_A0141("A0141", "用户证件类型未选择"),
+    USER_ERROR_A0142("A0142", "大陆身份证编号校验非法"),
+    USER_ERROR_A0143("A0143", "护照编号校验非法"),
+    USER_ERROR_A0144("A0144", "军官证编号校验非法"),
+    USER_ERROR_A0150("A0150", "用户基本信息校验失败"),
+    USER_ERROR_A0151("A0151", "手机格式校验失败"),
+    USER_ERROR_A0152("A0152", "地址格式校验失败"),
+    USER_ERROR_A0153("A0153", "邮箱格式校验失败"),
+    USER_ERROR_A0200("A0200", "用户登陆异常"),
+    USER_ERROR_A0201("A0201", "用户账户不存在"),
+    USER_ERROR_A0202("A0202", "用户账户被冻结"),
+    USER_ERROR_A0203("A0203", "用户账户已作废"),
+    USER_ERROR_A0210("A0210", "用户密码错误"),
+    USER_ERROR_A0211("A0211", "用户输入密码次数超限"),
+    USER_ERROR_A0220("A0220", "用户身份校验失败"),
+    USER_ERROR_A0221("A0221", "用户指纹识别失败"),
+    USER_ERROR_A0222("A0222", "用户面容识别失败"),
+    USER_ERROR_A0223("A0223", "用户未获得第三方登陆授权"),
+    USER_ERROR_A0230("A0230", "用户登陆已过期"),
+    USER_ERROR_A0240("A0240", "用户验证码错误"),
+    USER_ERROR_A0241("A0241", "用户验证码尝试次数超限"),
+    USER_ERROR_A0300("A0300", "访问权限异常"),
+    USER_ERROR_A0301("A0301", "访问未授权"),
+    USER_ERROR_A0302("A0302", "正在授权中"),
+    USER_ERROR_A0303("A0303", "用户授权申请被拒绝"),
+    USER_ERROR_A0310("A0310", "因访问对象隐私设置被拦截"),
+    USER_ERROR_A0311("A0311", "授权已过期"),
+    USER_ERROR_A0312("A0312", "无权限使用API"),
+    USER_ERROR_A0320("A0320", "用户访问被拦截"),
+    USER_ERROR_A0321("A0321", "黑名单用户"),
+    USER_ERROR_A0322("A0322", "账号被冻结"),
+    USER_ERROR_A0323("A0323", "非法IP地址"),
+    USER_ERROR_A0324("A0324", "网关访问受限"),
+    USER_ERROR_A0325("A0325", "地域黑名单"),
+    USER_ERROR_A0330("A0330", "服务已欠费"),
+    USER_ERROR_A0340("A0340", "用户签名异常"),
+    USER_ERROR_A0341("A0341", "RSA签名错误"),
+    USER_ERROR_A0400("A0400", "用户请求参数错误"),
+    USER_ERROR_A0401("A0401", "包含非法恶意跳转链接"),
+    USER_ERROR_A0402("A0402", "无效的用户输入"),
+    USER_ERROR_A0410("A0410", "请求必填参数为空"),
+    USER_ERROR_A0411("A0411", "用户订单号为空"),
+    USER_ERROR_A0412("A0412", "订购数量为空"),
+    USER_ERROR_A0413("A0413", "缺少时间戳参数"),
+    USER_ERROR_A0414("A0414", "非法的时间戳参数"),
+    USER_ERROR_A0420("A0420", "请求参数值超出允许的范围"),
+    USER_ERROR_A0421("A0421", "参数格式不匹配"),
+    USER_ERROR_A0422("A0422", "地址不在服务范围"),
+    USER_ERROR_A0423("A0423", "时间不在服务范围"),
+    USER_ERROR_A0424("A0424", "金额超出限制"),
+    USER_ERROR_A0425("A0425", "数量超出限制"),
+    USER_ERROR_A0426("A0426", "请求批量处理总个数超出限制"),
+    USER_ERROR_A0427("A0427", "请求JSON解析失败"),
+    USER_ERROR_A0430("A0430", "用户输入内容非法"),
+    USER_ERROR_A0431("A0431", "包含违禁敏感词"),
+    USER_ERROR_A0432("A0432", "图片包含违禁信息"),
+    USER_ERROR_A0433("A0433", "文件侵犯版权"),
+    USER_ERROR_A0440("A0440", "用户操作异常"),
+    USER_ERROR_A0441("A0441", "用户支付超时"),
+    USER_ERROR_A0442("A0442", "确认订单超时"),
+    USER_ERROR_A0443("A0443", "订单已关闭"),
+    USER_ERROR_A0500("A0500", "用户请求服务异常"),
+    USER_ERROR_A0501("A0501", "请求次数超出限制"),
+    USER_ERROR_A0502("A0502", "请求并发数超出限制"),
+    USER_ERROR_A0503("A0503", "用户操作请等待"),
+    USER_ERROR_A0504("A0504", "WebSocket连接异常"),
+    USER_ERROR_A0505("A0505", "WebSocket连接断开"),
+    USER_ERROR_A0506("A0506", "用户重复请求"),
+    USER_ERROR_A0600("A0600", "用户资源异常"),
+    USER_ERROR_A0601("A0601", "账户余额不足"),
+    USER_ERROR_A0602("A0602", "用户磁盘空间不足"),
+    USER_ERROR_A0603("A0603", "用户内存空间不足"),
+    USER_ERROR_A0604("A0604", "用户OSS容量不足"),
+    USER_ERROR_A0605("A0605", "用户配额已用光"),
+    USER_ERROR_A0700("A0700", "用户上传文件异常"),
+    USER_ERROR_A0701("A0701", "用户上传文件类型不匹配"),
+    USER_ERROR_A0702("A0702", "用户上传文件太大"),
+    USER_ERROR_A0703("A0703", "用户上传图片太大"),
+    USER_ERROR_A0704("A0704", "用户上传视频太大"),
+    USER_ERROR_A0705("A0705", "用户上传压缩文件太大"),
+    USER_ERROR_A0800("A0800", "用户当前版本异常"),
+    USER_ERROR_A0801("A0801", "用户安装版本与系统不匹配"),
+    USER_ERROR_A0802("A0802", "用户安装版本过低"),
+    USER_ERROR_A0803("A0803", "用户安装版本过高"),
+    USER_ERROR_A0804("A0804", "用户安装版本已过期"),
+    USER_ERROR_A0805("A0805", "用户API请求版本不匹配"),
+    USER_ERROR_A0806("A0806", "用户API请求版本过高"),
+    USER_ERROR_A0807("A0807", "用户API请求版本过低"),
+    USER_ERROR_A0900("A0900", "用户隐私未授权"),
+    USER_ERROR_A0901("A0901", "用户隐私未签署"),
+    USER_ERROR_A0902("A0902", "用户摄像头未授权"),
+    USER_ERROR_A0903("A0903", "用户相机未授权"),
+    USER_ERROR_A0904("A0904", "用户图片库未授权"),
+    USER_ERROR_A0905("A0905", "用户文件未授权"),
+    USER_ERROR_A0906("A0906", "用户位置信息未授权"),
+    USER_ERROR_A0907("A0907", "用户通讯录未授权"),
+    USER_ERROR_A1000("A1000", "用户设备异常"),
+    USER_ERROR_A1001("A1001", "用户相机异常"),
+    USER_ERROR_A1002("A1002", "用户麦克风异常"),
+    USER_ERROR_A1003("A1003", "用户听筒异常"),
+    USER_ERROR_A1004("A1004", "用户扬声器异常"),
+    USER_ERROR_A1005("A1005", "用户GPS定位异常"),
+    SYSTEM_ERROR_B0001("B0001", "系统执行出错"),
+    SYSTEM_ERROR_B0100("B0100", "系统执行超时"),
+    SYSTEM_ERROR_B0101("B0101", "系统订单处理超时"),
+    SYSTEM_ERROR_B0200("B0200", "系统容灾功能被触发"),
+    SYSTEM_ERROR_B0210("B0210", "系统限流"),
+    SYSTEM_ERROR_B0220("B0220", "系统功能降级"),
+    SYSTEM_ERROR_B0300("B0300", "系统资源异常"),
+    SYSTEM_ERROR_B0310("B0310", "系统资源耗尽"),
+    SYSTEM_ERROR_B0311("B0311", "系统磁盘空间耗尽"),
+    SYSTEM_ERROR_B0312("B0312", "系统内存耗尽"),
+    SYSTEM_ERROR_B0313("B0313", "文件句柄耗尽"),
+    SYSTEM_ERROR_B0314("B0314", "系统连接池耗尽"),
+    SYSTEM_ERROR_B0315("B0315", "系统线程池耗尽"),
+    SYSTEM_ERROR_B0320("B0320", "系统资源访问异常"),
+    SYSTEM_ERROR_B0321("B0321", "系统读取磁盘文件失败"),
+    SERVICE_ERROR_C0001("C0001", "调用第三方服务出错"),
+    SERVICE_ERROR_C0100("C0100", "中间件服务出错"),
+    SERVICE_ERROR_C0110("C0110", "RPC服务出错"),
+    SERVICE_ERROR_C0111("C0111", "RPC服务未找到"),
+    SERVICE_ERROR_C0112("C0112", "RPC服务未注册"),
+    SERVICE_ERROR_C0113("C0113", "接口不存在"),
+    SERVICE_ERROR_C0120("C0120", "消息服务出错"),
+    SERVICE_ERROR_C0121("C0121", "消息投递出错"),
+    SERVICE_ERROR_C0122("C0122", "消息消费出错"),
+    SERVICE_ERROR_C0123("C0123", "消息订阅出错"),
+    SERVICE_ERROR_C0124("C0124", "消息分组未查到"),
+    SERVICE_ERROR_C0130("C0130", "缓存服务出错"),
+    SERVICE_ERROR_C0131("C0131", "key长度超过限制"),
+    SERVICE_ERROR_C0132("C0132", "value长度超过限制"),
+    SERVICE_ERROR_C0133("C0133", "存储容量已满"),
+    SERVICE_ERROR_C0134("C0134", "不支持的数据格式"),
+    SERVICE_ERROR_C0140("C0140", "配置服务出错"),
+    SERVICE_ERROR_C0150("C0150", "网络资源服务出错"),
+    SERVICE_ERROR_C0151("C0151", "VPN服务出错"),
+    SERVICE_ERROR_C0152("C0152", "CDN服务出错"),
+    SERVICE_ERROR_C0153("C0153", "域名解析服务出错"),
+    SERVICE_ERROR_C0154("C0154", "网关服务出错"),
+    SERVICE_ERROR_C0200("C0200", "第三方系统执行超时"),
+    SERVICE_ERROR_C0210("C0210", "RPC执行超时"),
+    SERVICE_ERROR_C0220("C0220", "消息投递超时"),
+    SERVICE_ERROR_C0230("C0230", "缓存服务超时"),
+    SERVICE_ERROR_C0240("C0240", "配置服务超时"),
+    SERVICE_ERROR_C0250("C0250", "数据库服务超时"),
+    SERVICE_ERROR_C0300("C0300", "数据库服务出错"),
+    SERVICE_ERROR_C0311("C0311", "表不存在"),
+    SERVICE_ERROR_C0312("C0312", "列不存在"),
+    SERVICE_ERROR_C0321("C0321", "多表关联中存在多个相同名称的列"),
+    SERVICE_ERROR_C0331("C0331", "数据库死锁"),
+    SERVICE_ERROR_C0341("C0341", "主键冲突"),
+    SERVICE_ERROR_C0400("C0400", "第三方容灾系统被触发"),
+    SERVICE_ERROR_C0401("C0401", "第三方系统限流"),
+    SERVICE_ERROR_C0402("C0402", "第三方功能降级"),
+    SERVICE_ERROR_C0500("C0500", "通知服务出错"),
+    SERVICE_ERROR_C0501("C0501", "短信提醒服务失败"),
+    SERVICE_ERROR_C0502("C0502", "语音提醒服务失败"),
+    SERVICE_ERROR_C0503("C0503", "邮件提醒服务失败"),
+
+    SERVICE_ERROR_D0001("D0001", "无本次考试记录");
+
+
+    private final String code;
+    private final String description;
+
+    ErrorCodeEnum(String code, String description) {
+        this.code = code;
+        this.description = description;
+    }
+
+    public String getCode() {
+        return code;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+}

+ 1 - 1
seec-data-server/src/main/java/cn/seecoder/data/server/service/EvaluateService.java

@@ -6,5 +6,5 @@ public interface EvaluateService {
 
     public double getQuestionScore(int userId,String dataSource);
 
-    public Map<String, Map<String,Integer>> analyzeEvalTest(Integer examId);
+    public Map<String, Map<String,Double>> analyzeEvalTest(Integer examId);
 }

+ 96 - 11
seec-data-server/src/main/java/cn/seecoder/data/server/service/Impl/EvaluateServiceImpl.java

@@ -3,15 +3,22 @@ package cn.seecoder.data.server.service.Impl;
 import cn.seecoder.bok.client.SeecoderBokClient;
 import cn.seecoder.bok.common.vo.QuestionVO;
 import cn.seecoder.data.server.domain.GeneralRecordDao;
+import cn.seecoder.data.server.domain.knowledge.KnowledgeDao;
 import cn.seecoder.data.server.dto.evaluate.ExamQuestionAndScoreDto;
+import cn.seecoder.data.server.dto.evaluate.ExamRecordDto;
 import cn.seecoder.data.server.dto.evaluate.Response;
 import cn.seecoder.data.server.repository.GeneralRecordRepository;
+import cn.seecoder.data.server.repository.knowledge.KnowledgeRepository;
 import cn.seecoder.data.server.service.EvaluateService;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.ParameterizedTypeReference;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.ResponseEntity;
 import org.springframework.stereotype.Service;
 import org.springframework.web.client.RestTemplate;
 
 import java.util.*;
+import java.util.concurrent.atomic.AtomicReference;
 
 @Service
 public class EvaluateServiceImpl implements EvaluateService {
@@ -19,6 +26,9 @@ public class EvaluateServiceImpl implements EvaluateService {
     @Autowired
     private GeneralRecordRepository generalRecordRepository;
 
+    @Autowired
+    private KnowledgeRepository knowledgeRepository;
+
     public EvaluateServiceImpl(GeneralRecordRepository generalRecordRepository){
         this.generalRecordRepository = generalRecordRepository;
     }
@@ -48,21 +58,96 @@ public class EvaluateServiceImpl implements EvaluateService {
     }
 
     @Override
-    public Map<String, Map<String, Integer>> analyzeEvalTest(Integer examId) {
-        Map<String, Map<String, Integer>> evalTestResult = new HashMap<>();
-        evalTestResult.put("all", new HashMap<>());
-        evalTestResult.put("avg", new HashMap<>());
+    public Map<String, Map<String, Double>> analyzeEvalTest(Integer examId) {
+        final String urlQuestionScore = "http://47.111.95.164:8080/api/exam/{examId}/questions";
+        final String urlRecord = "http://47.111.95.164:8080/api/record/{examId}";
+        SeecoderBokClient seecoderBokClient = new SeecoderBokClient("http://bok.seec.seecoder.cn");
+
+        Map<String, Map<String, Double>> evalTestResult = new HashMap<>();
+        Map<String, Double> allMap = new HashMap<>();
+        Map<String, Double> avgMap = new HashMap<>();
 
         RestTemplate restTemplate = new RestTemplate();
-//        Response<ExamQuestionAndScoreDto> response = Response.buildSuccess(new ExamQuestionAndScoreDto());
         Map<String, Integer> param = new HashMap<>();
         param.put("examId", examId);
-        try {
-            Response<ExamQuestionAndScoreDto> r = restTemplate.getForObject("http://47.111.95.164:8080/api/exam/{examId}/questions", Response.class,param);
-            System.out.println(r.getResult());
-        } catch (Exception e) {
-            e.printStackTrace();
-        }
+
+        ParameterizedTypeReference<Response<ExamQuestionAndScoreDto>> responseType1 = new ParameterizedTypeReference<Response<ExamQuestionAndScoreDto>>() {};
+        ResponseEntity<Response<ExamQuestionAndScoreDto>> r1 = restTemplate.exchange(urlQuestionScore, HttpMethod.GET,null,responseType1,param );
+        ExamQuestionAndScoreDto examQuestionAndScoreDto = Objects.requireNonNull(r1.getBody()).getResult();
+
+        if(examQuestionAndScoreDto == null) return null;
+
+        Map<String, List<String>> questionIdMapToKnowledges = new HashMap<>();
+        examQuestionAndScoreDto.getQuestionAndScore().forEach((k,v) -> {
+            if(!questionIdMapToKnowledges.containsKey(k)) questionIdMapToKnowledges.put(k,new LinkedList<>());
+            Optional<QuestionVO> questionById = seecoderBokClient.getQuestionById(k);
+            if(questionById.isPresent()) {
+              QuestionVO questionVO = questionById.get();
+                List<String> knowledgeAbbs = questionVO.getKnowledgeId();
+                knowledgeAbbs.forEach(abbr -> {
+                    KnowledgeDao knowledgeDao = knowledgeRepository.findByAbbreviation(abbr);
+                    String knowLedgeName = knowledgeDao.getName();
+                    questionIdMapToKnowledges.get(k).add(knowLedgeName);
+                    if(!allMap.containsKey(knowLedgeName)) {
+                        allMap.put(knowLedgeName, 0.0);
+                    }
+                    allMap.put(knowLedgeName,allMap.get(knowLedgeName)+v);
+                });
+            }
+        });
+
+        ParameterizedTypeReference<Response<List<ExamRecordDto>>> responseType2 = new ParameterizedTypeReference<Response<List<ExamRecordDto>>>() {};
+        ResponseEntity<Response<List<ExamRecordDto>>> r2 = restTemplate.exchange(urlRecord, HttpMethod.GET,null,responseType2,param );
+        List<ExamRecordDto> examDetailsDtos = Objects.requireNonNull(r2.getBody()).getResult();
+
+        Map<String,ExamRecordDto> highestScoreMap = new HashMap<>(); // `sid**qid` : sid, qid ,highestScore
+        examDetailsDtos.forEach(examRecordDto -> {
+            String questionId = examRecordDto.getQuestionId();
+            String studentId = String.valueOf(examRecordDto.getStudentId());
+            String key = studentId + "**" + questionId;
+            if(!highestScoreMap.containsKey(key)) {
+                highestScoreMap.put(key,examRecordDto);
+            } else {
+                ExamRecordDto tmpExamRecordDto = highestScoreMap.get(key);
+                if(examRecordDto.getActualScore()>tmpExamRecordDto.getActualScore()) {
+                    highestScoreMap.put(key,examRecordDto);
+                }
+            }
+        });
+
+        highestScoreMap.values().forEach(examRecordDto -> {
+            String studentId = String.valueOf(examRecordDto.getStudentId());
+            String questionId = examRecordDto.getQuestionId();
+            Double actualScore = examRecordDto.getActualScore();
+            if (!evalTestResult.containsKey(studentId)) {
+                evalTestResult.put(studentId,new HashMap<>());
+            }
+            questionIdMapToKnowledges.get(questionId).forEach(knowledgeName -> {
+                Map<String, Double> studentMap = evalTestResult.get(studentId);
+                if(!studentMap.containsKey(knowledgeName)) {
+                    studentMap.put(knowledgeName, 0.0);
+                }
+                studentMap.put(knowledgeName, studentMap.get(knowledgeName)+actualScore);
+            });
+        });
+
+        AtomicReference<Integer> count = new AtomicReference<>(0);
+        allMap.forEach((knowlwdgeName, maxScore) -> {
+            avgMap.put(knowlwdgeName, 0.0);
+        });
+        evalTestResult.forEach((studentId, knowledgeScoreMap) -> {
+            count.updateAndGet(v -> v + 1);
+            allMap.forEach((knowledgeName, maxScore) -> {
+                if(knowledgeScoreMap.containsKey(knowledgeName))
+                    avgMap.put(knowledgeName,avgMap.get(knowledgeName)+knowledgeScoreMap.get(knowledgeName));
+                else
+                    knowledgeScoreMap.put(knowledgeName, 0.0);
+            });
+        });
+        avgMap.forEach((knowledgeName,avgScore)->{avgMap.put(knowledgeName,avgScore/count.get());});
+        evalTestResult.put("all",allMap);
+        evalTestResult.put("avg",avgMap);
+
         return evalTestResult;
     }
 }

+ 45 - 3
seec-data-server/src/test/java/cn/seecoder/data/server/service/EvaluateServiceTest.java

@@ -1,17 +1,29 @@
 package cn.seecoder.data.server.service;
 
-import config.EvaluateServiceTestConfig;
+import cn.seecoder.data.server.dto.evaluate.ExamDetailsDto;
+import cn.seecoder.data.server.dto.evaluate.ExamQuestionAndScoreDto;
+import cn.seecoder.data.server.dto.evaluate.Response;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
 import org.junit.jupiter.api.Test;
 import org.junit.runner.RunWith;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.core.ParameterizedTypeReference;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.ResponseEntity;
 import org.springframework.test.context.ContextConfiguration;
 import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.web.client.RestTemplate;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
 
 import static org.junit.jupiter.api.Assertions.*;
 
 @RunWith(SpringJUnit4ClassRunner.class)
-@ContextConfiguration(classes = EvaluateSe nrviceTestConfig.class)
+@SpringBootTest
 class EvaluateServiceTest {
 
     @Autowired
@@ -19,6 +31,36 @@ class EvaluateServiceTest {
 
     @Test
     void analyzeEvalTest() {
-        evaluateService.analyzeEvalTest(1);
+        System.out.println(evaluateService.analyzeEvalTest(3));
+    }
+
+    @Test
+    void test() throws JsonProcessingException {
+        RestTemplate restTemplate = new RestTemplate();
+        String s = restTemplate.getForObject("http://47.111.95.164:8080/api/exam/1/questions",String.class);
+        System.out.println(s);
+
+        Map<String, Double> m = new HashMap<>();
+        m.put("19037",25.0);
+        m.put("19033",25.0);
+        m.put("19034",25.0);
+        m.put("19030",25.0);
+        m.put("19031",25.0);
+        Response<ExamQuestionAndScoreDto> r = Response.buildSuccess(ExamQuestionAndScoreDto.builder().questionAndScore(m).build());
+        ObjectMapper objectMapper = new ObjectMapper();
+        String ss = objectMapper.writeValueAsString(r);
+        System.out.println(ss);
+    }
+
+    @Test
+    public void test2() {
+        RestTemplate restTemplate = new RestTemplate();
+        Map<String,String> param = new HashMap<>();
+        param.put("startTime","2019-01-01 00:00:00");
+        param.put("endTime","2021-12-30 00:00:00");
+        String url = "http://47.111.95.164:8080/api/exam/list/range?startTime={startTime}&endTime={endTime}";
+        ParameterizedTypeReference<Response<List<ExamDetailsDto>>> responseType = new ParameterizedTypeReference<Response<List<ExamDetailsDto>>>() {};
+        ResponseEntity<Response<List<ExamDetailsDto>>> r = restTemplate.exchange(url, HttpMethod.GET,null,responseType,param );
+        System.out.println(r.getBody());
     }
 }

+ 0 - 23
seec-data-server/src/test/java/config/EvaluateServiceTestConfig.java

@@ -1,23 +0,0 @@
-package config;
-
-import cn.seecoder.data.server.domain.GeneralRecordDao;
-import cn.seecoder.data.server.repository.GeneralRecordRepository;
-import cn.seecoder.data.server.service.EvaluateService;
-import cn.seecoder.data.server.service.Impl.EvaluateServiceImpl;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.data.domain.Example;
-import org.springframework.data.domain.Page;
-import org.springframework.data.domain.Pageable;
-import org.springframework.data.domain.Sort;
-
-import java.util.List;
-import java.util.Optional;
-
-@Configuration
-public class EvaluateServiceTestConfig {
-    @Bean
-    public EvaluateService evaluateService() {
-        return new EvaluateServiceImpl(null);
-    }
-}