uncln 4 роки тому
батько
коміт
4e86ada5e7

+ 11 - 0
pom.xml

@@ -137,6 +137,17 @@
 			<version>0.1.0</version>
 		</dependency>
 
+		<!--日志服务-->
+		<dependency>
+			<groupId>com.nju.edu</groupId>
+			<artifactId>seecoder-logTracking-client</artifactId>
+			<version>0.1.0</version>
+		</dependency>
+
+		<dependency>
+			<groupId>org.slf4j</groupId>
+			<artifactId>slf4j-api</artifactId>
+		</dependency>
 
 		<dependency>
 			<groupId>org.springframework.boot</groupId>

+ 18 - 0
src/main/java/com/nju/edu/eval/model/vo/logdata/AnswerDTO.java

@@ -0,0 +1,18 @@
+package com.nju.edu.eval.model.vo.logdata;
+
+import com.alibaba.fastjson.annotation.JSONField;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class AnswerDTO {
+
+    @JSONField(name = "question_id")
+    private String questionId;
+
+    @JSONField(name = "question_score")
+    private double questionScore;
+}

+ 38 - 0
src/main/java/com/nju/edu/eval/model/vo/logdata/ExamLog.java

@@ -0,0 +1,38 @@
+package com.nju.edu.eval.model.vo.logdata;
+
+import com.alibaba.fastjson.annotation.JSONField;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.Date;
+import java.util.List;
+
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class ExamLog {
+
+    @JSONField(name = "exam_id")
+    private Integer examId;
+
+    @JSONField(name = "exam_score")
+    private Double examScore;
+
+    @JSONField(name = "questions")
+    private List<AnswerDTO> questions;
+
+    @JSONField(name = "difficulty")
+    private Integer difficulty;
+
+    @JSONField(name = "update_time", format="yyyy-MM-dd HH:mm:ss")
+    private Date updateTime;
+
+    @JSONField(name = "start_time", format="yyyy-MM-dd HH:mm:ss")
+    private Date startTime;
+
+    @JSONField(name = "end_time", format="yyyy-MM-dd HH:mm:ss")
+    private Date endTime;
+
+}

+ 45 - 0
src/main/java/com/nju/edu/eval/model/vo/logdata/ExamRecordLog.java

@@ -0,0 +1,45 @@
+package com.nju.edu.eval.model.vo.logdata;
+
+import com.alibaba.fastjson.annotation.JSONField;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.Date;
+import java.util.List;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class ExamRecordLog {
+
+    /**
+     * 试卷Id
+     */
+    @JSONField(name="exam_id")
+    private Integer examId;
+
+    /**
+     * 用户Id
+     */
+    @JSONField(name="student_id")
+    private Integer studentId;
+
+    /**
+     * 提交时间
+     */
+    @JSONField(name="submit_time", format="yyyy-MM-dd HH:mm:ss")
+    private Date submitTime;
+
+    /**
+     * 得分
+     */
+    @JSONField(name="score")
+    private Double score;
+
+    /**
+     * 得分
+     */
+    @JSONField(name="error_ques")
+    private List<AnswerDTO> errorQuestions;
+}

+ 23 - 0
src/main/java/com/nju/edu/eval/service/serviceImpl/ExamServiceImpl.java

@@ -1,6 +1,7 @@
 package com.nju.edu.eval.service.serviceImpl;
 
 import cn.seecoder.bok.common.QuestionType;
+import com.alibaba.fastjson.JSON;
 import com.nju.edu.eval.data.dao.ExamDao;
 import com.nju.edu.eval.data.dao.SampleExamPaperDao;
 import com.nju.edu.eval.data.dao.ScoreDao;
@@ -12,10 +13,12 @@ import com.nju.edu.eval.data.entity.User;
 import com.nju.edu.eval.exception.MyServiceException;
 import com.nju.edu.eval.manager.QuestionManager;
 import com.nju.edu.eval.model.vo.exam.*;
+import com.nju.edu.eval.model.vo.logdata.ExamLog;
 import com.nju.edu.eval.model.vo.question.QuestionAndScoreVO;
 import com.nju.edu.eval.service.ExamService;
 import com.nju.edu.eval.service.convertor.ExamConvertor;
 import com.nju.edu.eval.util.InviteCodeUtil;
+import com.nju.edu.eval.util.LogTracingUtil;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.data.domain.Page;
 import org.springframework.data.domain.PageRequest;
@@ -65,7 +68,12 @@ public class ExamServiceImpl implements ExamService {
         } else {
             exam.setAntiCheating(0);
         }
+
         examDao.save(exam);
+
+        // 日志输出
+        LogTracingUtil.logExam(exam, 0);
+
 //        List<CompleteQuestionVO> questionVOs = questionManager.getRecommendQuestions(examVO.getSkills(), examVO.getDifficulty());
         return new NewExamVO(exam.getId(), exam.getInviteCode(), exam.getDifficulty());
     }
@@ -141,6 +149,9 @@ public class ExamServiceImpl implements ExamService {
 //        }
         exam.setQuestionAndScore(questionScoreMap);
         examDao.save(exam);
+
+        // 日志输出
+        LogTracingUtil.logExam(exam, 1);
     }
 
     @Override
@@ -152,6 +163,9 @@ public class ExamServiceImpl implements ExamService {
             }
             exam.setEndTime(endTime);
             examDao.save(exam);
+
+            // 日志输出
+            LogTracingUtil.logExam(exam, 1);
         } else {
             throw new MyServiceException("A0411", "没有对应的考试");
         }
@@ -235,6 +249,9 @@ public class ExamServiceImpl implements ExamService {
         Map<String, Double> questionAndScore = new HashMap<>(sampleExamPaper.getQuestionAndScore());
         exam.setQuestionAndScore(questionAndScore);
         examDao.save(exam);
+
+        // 日志输出
+        LogTracingUtil.logExam(exam, 0);
     }
 
     @Override
@@ -246,6 +263,9 @@ public class ExamServiceImpl implements ExamService {
 
         exam.setExamName(name);
         examDao.save(exam);
+
+        // 日志输出
+        LogTracingUtil.logExam(exam, 1);
         return true;
     }
 
@@ -258,6 +278,9 @@ public class ExamServiceImpl implements ExamService {
 
         exam.setIsHidden(hidden);
         examDao.save(exam);
+
+        // 日志输出
+        LogTracingUtil.logExam(exam, 1);
         return true;
     }
 

+ 26 - 5
src/main/java/com/nju/edu/eval/service/serviceImpl/JudgeServiceImpl.java

@@ -21,15 +21,17 @@ import com.nju.edu.eval.model.vo.judge.CodeJudgeVO;
 import com.nju.edu.eval.model.vo.judge.ObjectiveJudgeResOfExerciseVO;
 import com.nju.edu.eval.model.vo.judge.ObjectiveJudgeResVO;
 import com.nju.edu.eval.model.vo.judge.ObjectiveJudgeVO;
+import com.nju.edu.eval.model.vo.logdata.AnswerDTO;
+import com.nju.edu.eval.model.vo.logdata.ExamRecordLog;
 import com.nju.edu.eval.model.vo.question.CompleteQuestionVO;
 import com.nju.edu.eval.publicdatas.enums.CodeJudgeResultType;
 import com.nju.edu.eval.service.JudgeService;
+import com.nju.edu.eval.util.LogTracingUtil;
+import com.nju.edu.logTracking.enums.SeecSystem;
+import org.apache.logging.log4j.LogBuilder;
 import org.springframework.stereotype.Service;
 
-import java.util.Date;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 import java.util.stream.Collectors;
 
 /**
@@ -70,6 +72,9 @@ public class JudgeServiceImpl implements JudgeService {
             scoreDao.save(score);
             List<QuestionRecord> records = score.getRecords();
 
+            // 存储用以打日志的错题集
+            List<AnswerDTO> err = new ArrayList<>();
+
             double curScore = 0.0;
             // 存储用户提交的记录
             for (Map.Entry<String, StudentAnswerDTO.AnswerRecordDTO> entry : objectiveJudgeVO.getRecords().entrySet()) {
@@ -79,15 +84,24 @@ public class JudgeServiceImpl implements JudgeService {
                 double scoreOfQuestion = exam.getQuestionAndScore().get(questionId);
                 // 看该题是否正确
                 boolean isTrue = judgedAnswersVO.getAnswers().get(questionId).getCorrect();
+                // 填入错题集
+                if (!isTrue)
+                    err.add(new AnswerDTO(questionId, scoreOfQuestion));
                 double actualScore = isTrue ? scoreOfQuestion : 0;
                 curScore += actualScore;
                 QuestionRecord questionRecord = new QuestionRecord(user, exam, entry.getKey(), score, (String) entry.getValue().getAnswer(), actualScore, currentTime);
                 records.add(questionRecord);
             }
+
+
             double maxScore = Math.max(score.getScore() - score.getObjectiveScore() + curScore, score.getScore());
             score.setObjectiveScore(Math.max(curScore, score.getObjectiveScore()));
             score.setScore(maxScore);
-            scoreDao.save(score);
+            scoreDao.save(score);;
+
+            // 提交记录日志
+            LogTracingUtil.logRecord(new ExamRecordLog(examId, userId, currentTime, curScore, err));
+
             return new ObjectiveJudgeResVO(judgedAnswersVO.getSubmitAt(), judgedAnswersVO.getSubmitNumber());
 
         } catch (ThirdPartyServiceException exception) {
@@ -158,6 +172,13 @@ public class JudgeServiceImpl implements JudgeService {
             double maxScore = Math.max(score.getScore() - preScore + curScore, score.getScore());
             score.setScore(maxScore);
             scoreDao.save(score);
+
+            // 提交记录日志
+            List<AnswerDTO> err = new ArrayList<>();
+            if (curScore != scoreOfQuestion)
+                err.add(new AnswerDTO(questionId, scoreOfQuestion));
+            LogTracingUtil.logRecord(new ExamRecordLog(examId, userId, currentTime, curScore, err));
+
             return judgeResult;
         } catch (ThirdPartyServiceException exception) {
             throw new MyServiceException(exception.getCode(), exception.getMessage());

+ 76 - 0
src/main/java/com/nju/edu/eval/util/LogTracingUtil.java

@@ -0,0 +1,76 @@
+package com.nju.edu.eval.util;
+
+import Utils.LogBuilder;
+import client.LogTrackingClient;
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.serializer.SerializerFeature;
+import com.nju.edu.eval.data.entity.Exam;
+import com.nju.edu.eval.model.vo.logdata.AnswerDTO;
+import com.nju.edu.eval.model.vo.logdata.ExamLog;
+import com.nju.edu.eval.model.vo.logdata.ExamRecordLog;
+import com.nju.edu.logTracking.enums.SeecSystem;
+import lombok.extern.slf4j.Slf4j;
+import org.slf4j.Logger;
+
+import java.util.Date;
+import java.util.List;
+import java.util.stream.Collectors;
+
+@Slf4j
+public class LogTracingUtil {
+
+    private static final Logger logger = LoggerUtil.getLogger(LogTracingUtil.class);
+
+    public static void logToAnalysis(String data, int type) {
+        // String data = "This is an example";
+
+        //此为logBuilder,若不想使用也可自己构建log
+        //注:此logBuilder在调用build方法时会自动添加created_time属性,值为当前时间戳
+
+        String logData = "";
+
+        try {
+            logData= LogBuilder
+                    .getBuilder()
+                    .target(SeecSystem.EVAL.getName()) // 等待分配enum后修改
+                    .source(SeecSystem.EVAL.getName())
+                    .operationType(type)
+                    .data(data)
+                    .message("OK")
+                    .build();
+
+            //最简单使用方法,默认为medium级别
+//            LogTrackingClient
+//                    .getClient()
+//                    .log(logData)
+//                    .publish();
+            //LoggerUtil.info(logger, "SMART--->" + log);
+
+            LoggerUtil.info(logger, "SMART--->" + logData);
+
+        }catch(Exception e){
+            LoggerUtil.info(logger, "SMART--->" + logData);
+            //System.out.println("构建日志数据失败");
+            e.printStackTrace();
+        }
+    }
+
+    public static void logExam(Exam exam, int type) {
+        try {
+            List<AnswerDTO> answerDTOS = exam.getQuestionAndScore().entrySet().stream().
+                    map(et -> new AnswerDTO(et.getKey(), et.getValue())).collect(Collectors.toList());
+            double totalGrade = exam.getQuestionAndScore().values().stream().collect(Collectors.summarizingInt(x -> x.intValue())).getSum();
+
+            ExamLog examLog = new ExamLog(exam.getId(), totalGrade, answerDTOS, exam.getDifficulty(), new Date(), exam.getStartTime(), exam.getEndTime());
+
+            logToAnalysis(JSON.toJSONStringWithDateFormat(examLog, "yyyy-MM-dd HH:mm:ss", SerializerFeature.WriteDateUseDateFormat), type);
+        }catch (Exception e){
+            System.out.println("构建日志数据失败");
+            e.printStackTrace();
+        }
+    }
+
+    public static void logRecord(ExamRecordLog examRecordLog) {
+        logToAnalysis(JSON.toJSONStringWithDateFormat(examRecordLog, "yyyy-MM-dd HH:mm:ss", SerializerFeature.WriteDateUseDateFormat), 2);
+    }
+}

+ 37 - 0
src/main/java/com/nju/edu/eval/util/LoggerUtil.java

@@ -0,0 +1,37 @@
+package com.nju.edu.eval.util;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class LoggerUtil {
+
+    public static Logger getLogger(Class<?> className){
+        return LoggerFactory.getLogger(className);
+    }
+
+    public static void info(Logger logger, String info, Object... parameters){
+        logger.info(info, parameters);
+    }
+
+    public static void warn(Logger logger, String info, Object... parameters){
+        logger.warn(info, parameters);
+    }
+
+    public static void warn(Logger logger, Exception e, String info, Object... parameters) {
+        logger.warn("", e);
+        logger.warn(info, parameters);
+    }
+
+    public static void  error(Logger logger, String info, Object... parameters) {
+        logger.error(info, parameters);
+    }
+
+    public static void error(Logger logger, Exception e, String info, Object... parameters) {
+        logger.error("", e);
+        logger.error(info, parameters);
+    }
+
+    public static void debug(Logger logger, String info, Object... parameters) {
+        logger.debug(info, parameters);
+    }
+}

+ 6 - 0
src/main/resources/application-prod.yml

@@ -39,3 +39,9 @@ objective-judgement-client:
 
 code-judgement-client:
   host: https://oj.seec.seecoder.cn
+
+logging:
+  file:
+    name: /log/eval.log
+  level:
+    root: info

+ 9 - 3
src/main/resources/application-test.yml

@@ -2,9 +2,9 @@ server:
   port: 8081
 spring:
   datasource:
-    url: jdbc:mysql://47.111.95.164:3306/eval?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=UTF-8&useSSL=false
+    url: jdbc:mysql://127.0.0.1:3306/eval?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=UTF-8&useSSL=false
     username: root
-    password: mysqltcj
+    password: root
     driverClassName: com.mysql.cj.jdbc.Driver
     hikari:
       max-lifetime: 600000
@@ -43,4 +43,10 @@ objective-judgement-client:
 #  host: http://localhost:8088
 
 code-judgement-client:
-  host: http://oj.seec.seecoder.cn
+  host: http://oj.seec.seecoder.cn
+
+logging:
+  file:
+    name: /log/eval.log
+  level:
+    root: info