Explorar el Código

feat: 增加quiz相关11个api的stub

XuShengTao hace 6 años
padre
commit
bccc75e152

+ 58 - 0
config/application-dev.yml

@@ -0,0 +1,58 @@
+spring:
+  datasource:
+    url: jdbc:mysql://120.78.159.171:19999/helper?setUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8
+    driver-class-name: com.mysql.cj.jdbc.Driver
+    username: root
+    password: password
+  jpa:
+    open-in-view: true
+    hibernate:
+      ddl-auto: update
+    database: mysql
+    database-platform: org.hibernate.dialect.MySQL8Dialect
+#    show-sql: true
+  http:
+    encoding:
+      force: true
+  redis:
+    host: 120.78.159.171
+    port: 6379
+  data:
+    redis:
+      repositories:
+        enabled: false
+  mail:
+    host: smtp.163.com
+    username: seecoder@163.com
+    password: seec67NJU
+    properties:
+      mail:
+        smtp:
+          auth: true
+          socketFactory:
+            class: javax.net.ssl.SSLSocketFactory
+            port: 465
+          starttls:
+            enable: true
+            required: true
+  servlet:
+    multipart:
+      max-file-size: 50MB
+      max-request-size: 100MB
+aliyun:
+  oss:
+    endpoint: oss-cn-hangzhou.aliyuncs.com
+    accessKeyId: LTAI4Fi1qmL4iuhH8t7G7r2H
+    accessKeySecret: 7tJWyQqa0cMkQGaPMMvtH6c0VLiOO2
+    bucketName: seec-helper-pdf
+  sms:
+    accessKeyId: LTAI4FiAXXyNfYJLweBXpKPx
+    accessSecret: IBoC7KGkZHOvxZQIfQgp98ZY48AVjW
+    signName: seeccoder
+    templateCode: SMS_181555598
+
+# 自定义数据
+helper:
+  mail:
+    from: ${spring.mail.username}
+    subject: seeccoder

+ 103 - 0
src/main/java/nju/seec/helper/controller/QuestionController.java

@@ -0,0 +1,103 @@
+package nju.seec.helper.controller;
+
+import nju.seec.helper.aspect.auth.Auth;
+import nju.seec.helper.controller.response.PageResponse;
+import nju.seec.helper.dao.CourseDAO;
+import nju.seec.helper.dao.SlideDAO;
+import nju.seec.helper.dto.LoginUser;
+import nju.seec.helper.util.enums.QuizState;
+import nju.seec.helper.util.enums.SlideState;
+import nju.seec.helper.util.enums.UserType;
+import nju.seec.helper.vo.CourseVO;
+import nju.seec.helper.vo.SlideVO;
+import nju.seec.helper.vo.quiz.ChoiceQuestionVO;
+import nju.seec.helper.vo.quiz.QuestionVO;
+import nju.seec.helper.vo.quiz.QuizVO;
+import nju.seec.helper.vo.quiz.TrueOrFalseQuestionVO;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.web.PageableDefault;
+import org.springframework.expression.ParseException;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.*;
+
+import static nju.seec.helper.controller.QuizController.ChoiceQ;
+import static nju.seec.helper.controller.QuizController.TFQ;
+import static nju.seec.helper.controller.QuizController.objectMapper;
+/**
+ * 题库
+ *
+ * @doc http://47.100.18.120:3000/SEEC-BOK/API-DOC/src/master/helper/api/Quiz-%e6%b5%8b%e8%af%95.md
+ */
+@RestController
+@RequestMapping("/api/question")
+public class QuestionController {
+    @Autowired
+    private CourseDAO courseDAO;
+    @Autowired
+    private SlideDAO slideDAO;
+    /**
+     * 获得题目列表
+     */
+    @Auth(roles = {UserType.TEACHER}, message = "获得题目列表")
+    @GetMapping("")
+    public Map getQuestionList(LoginUser user, String stem,  @PageableDefault(Integer.MAX_VALUE) Pageable pageable) {
+        List<QuestionVO> Questions=new ArrayList<>();
+        Questions.add(ChoiceQ());
+        Questions.add(TFQ());
+        Map ret=new LinkedHashMap(2);
+        ret.put("questions",Questions);
+        ret.put("page",PageResponse.PageInfo.of(1,5,1,1));
+        return ret;
+    }
+
+    /**
+     * 创建题目
+     */
+    @Auth(roles = {UserType.TEACHER}, message = "创建题目")
+    @PostMapping("")
+    public QuestionVO PostQuestion(LoginUser user,  @RequestBody Map question) {
+
+        if(question.get("kind")==null){throw new ParseException('1',"no kind");}
+        String kind = (String)question.get("kind");
+        switch (kind){
+            case "CHOICE":
+                return (objectMapper.convertValue(question, ChoiceQuestionVO.class));
+            case "TRUE_FALSE":
+                return (objectMapper.convertValue(question, TrueOrFalseQuestionVO.class));
+        }
+        throw new ParseException('1',"parse failed:"+question.toString());
+    }
+
+    /**
+     * 更新题目
+     */
+    @Auth(roles = {UserType.TEACHER}, message = "更新题目")
+    @PutMapping("/{questionId}")
+    public QuestionVO updateQuestion(LoginUser user, @RequestBody Map question, @PathVariable("questionId") String questionId) {
+
+        if(question.get("kind")==null){throw new ParseException('1',"no kind");}
+        String kind = (String)question.get("kind");
+        switch (kind){
+            case "CHOICE":
+                return (objectMapper.convertValue(question, ChoiceQuestionVO.class));
+            case "TRUE_FALSE":
+                return (objectMapper.convertValue(question, TrueOrFalseQuestionVO.class));
+        }
+        throw new ParseException('1',"parse failed:"+question.toString());
+    }
+
+
+    /**
+     * 更新题目
+     */
+    @Auth(roles = {UserType.TEACHER}, message = "更新题目")
+    @DeleteMapping("/{questionId}")
+    public Map deleteQuestion(LoginUser user, @PathVariable("questionId") String questionId) {
+
+        Map map=new HashMap();
+        map.put("message","success");
+        return map;
+    }
+}

+ 172 - 0
src/main/java/nju/seec/helper/controller/QuizController.java

@@ -0,0 +1,172 @@
+package nju.seec.helper.controller;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import nju.seec.helper.aspect.auth.Auth;
+import nju.seec.helper.controller.response.PageResponse;
+import nju.seec.helper.dao.CourseDAO;
+import nju.seec.helper.dao.SlideDAO;
+import nju.seec.helper.dto.LoginUser;
+import nju.seec.helper.dto.QuizAnswerDTO;
+import nju.seec.helper.dto.QuizDTO;
+import nju.seec.helper.dto.QuizUpdateDTO;
+import nju.seec.helper.entity.User;
+import nju.seec.helper.util.Consts;
+import nju.seec.helper.util.enums.QuestionKindState;
+import nju.seec.helper.util.enums.QuizState;
+import nju.seec.helper.util.enums.SlideState;
+import nju.seec.helper.util.enums.UserType;
+import nju.seec.helper.vo.CourseVO;
+import nju.seec.helper.vo.SlideVO;
+import nju.seec.helper.vo.quiz.ChoiceQuestionVO;
+import nju.seec.helper.vo.quiz.QuestionVO;
+import nju.seec.helper.vo.quiz.QuizVO;
+import nju.seec.helper.vo.quiz.TrueOrFalseQuestionVO;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.web.PageableDefault;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpSession;
+import java.util.*;
+
+/**
+ * 测试
+ *
+ * @doc http://47.100.18.120:3000/SEEC-BOK/API-DOC/src/master/helper/api/Quiz-%e6%b5%8b%e8%af%95.md
+ */
+@RestController
+@RequestMapping("/api/quiz")
+public class QuizController {
+    @Autowired
+    private CourseDAO courseDAO;
+    @Autowired
+    private SlideDAO slideDAO;
+    /**
+     * 获得测试列表
+     */
+    @Auth(roles = {UserType.STUDENT}, message = "获得测试列表")
+    @GetMapping("")
+    public Map getBasicQuizList(LoginUser user, String slideId, boolean subscribe,
+                      QuizState state	, @PageableDefault(Integer.MAX_VALUE) Pageable pageable) {
+        List quizs=new ArrayList<QuizVO>();
+        quizs.add(QuizVO.builder().questionNumber(1).state(QuizState.NOT_STARTED)
+                .name("第一次测试").QuizId("1").quizTime(SlideState.IN_CLASS)
+                .courseVO(new CourseVO(courseDAO.getOne(1)))
+                .slide(new SlideVO(slideDAO.getOne(1))).build());
+        Map ret=new LinkedHashMap(2);
+        ret.put("quizs",quizs);
+        ret.put("page",PageResponse.PageInfo.of(1,5,1,1));
+        return ret;
+    }
+
+    /**
+     * 获得某一测试的详细内容
+     */
+    @Auth(roles = {UserType.STUDENT}, message = "获得某一测试的详细内容")
+    @GetMapping("/{quizId}")
+    public QuizVO GetOneQuiz(LoginUser user, @PathVariable("quizId") String quizId) {
+        List<QuestionVO> Questions=new ArrayList<>();
+        Questions.add(ChoiceQ());
+        Questions.add(TFQ());
+        return QuizVO.builder().questionNumber(1).state(QuizState.NOT_STARTED)
+                .name("第一次测试").QuizId("1").quizTime(SlideState.IN_CLASS)
+                .courseVO(new CourseVO(courseDAO.getOne(1)))
+                .slide(new SlideVO(slideDAO.getOne(1))).questions(Questions).build();
+    }
+
+    /**
+     * 创建测试
+     */
+    @Auth(roles = {UserType.TEACHER}, message = "创建测试")
+    @PostMapping("")
+    public QuizVO CreateQuiz(LoginUser user, QuizDTO newQuiz) {
+        List<QuestionVO> Questions=new ArrayList<>();
+        Questions.add(ChoiceQ());
+        Questions.add(TFQ());
+        return QuizVO.builder().questionNumber(1).state(QuizState.NOT_STARTED)
+                .name("第一次测试").QuizId("1").quizTime(SlideState.IN_CLASS)
+                .courseVO(new CourseVO(courseDAO.getOne(1)))
+                .slide(new SlideVO(slideDAO.getOne(1))).questions(Questions).build();
+    }
+
+    /**
+     * 修改测试 (仅限未开始时可以修改)
+     */
+    @Auth(roles = {UserType.TEACHER}, message = "修改测试")
+    @PutMapping("/{quizId}")
+    public QuizVO updateQuiz(LoginUser user, QuizUpdateDTO newQuiz, @PathVariable("quizId") String quizId) {
+        List<QuestionVO> Questions=new ArrayList<>();
+        Questions.add(ChoiceQ());
+        Questions.add(TFQ());
+        return QuizVO.builder().questionNumber(1).state(QuizState.NOT_STARTED)
+                .name("第一次测试").QuizId("1").quizTime(SlideState.IN_CLASS)
+                .courseVO(new CourseVO(courseDAO.getOne(1)))
+                .slide(new SlideVO(slideDAO.getOne(1))).questions(Questions).build();
+    }
+
+    /**
+     * 删除测试 (仅限未开始时可以删除)
+     */
+    @Auth(roles = {UserType.TEACHER}, message = "删除测试")
+    @DeleteMapping("/{quizId}")
+    public Map deleteQuiz(LoginUser user, @PathVariable("quizId") String quizId) {
+        Map map=new HashMap();
+        map.put("message","success");
+        return map;
+    }
+
+    /**
+     * 获得测试结果统计
+     */
+    @Auth(roles = {UserType.TEACHER}, message = "获得测试结果统计")
+    @GetMapping("/{quizId}/result")
+    public Map getQuizResult(LoginUser user, @PathVariable("quizId") String quizId) {
+        Map map=new HashMap();
+        map.put("message","success");
+        map.put("avarage","88");
+        return map;
+    }
+    /**
+     * 提交答案
+     */
+    static ObjectMapper objectMapper = new ObjectMapper();
+
+    @Auth(roles = {UserType.STUDENT}, message = "提交答案")
+    @PutMapping("/{quizId}/student-answer")
+    public Map putStudentAnswer(LoginUser user, @PathVariable("quizId") String quizId, @RequestBody QuizAnswerDTO quizAnswerDTO) {
+
+        Map map=new HashMap();
+        map.put("message","fail to parse body");
+        List<QuestionVO> questions=new ArrayList<>();
+        for(Object q:quizAnswerDTO.getAnswers()){
+            final Map question = (Map) q;
+            if(question.get("kind")==null){return map;}
+            String kind = (String)question.get("kind");
+            switch (kind){
+                case "CHOICE":
+                    questions.add(objectMapper.convertValue(q, ChoiceQuestionVO.class));
+                    break;
+                case "TRUE_FALSE":
+                    questions.add(objectMapper.convertValue(q, TrueOrFalseQuestionVO.class));
+                    break;
+            }
+        }
+        map.put("message","success");
+        map.put("echo",questions);
+        return map;
+    }
+    // --------------------------------stub---------------------------------------
+    static ChoiceQuestionVO ChoiceQ(){
+        Map<String,String> map =new LinkedHashMap<>();
+        map.put("A","This is A");
+        map.put("B","This is B");
+        map.put("C","This is C");
+        map.put("D","This is D");
+        return ChoiceQuestionVO.builder().QuizId("1").studentAnswer("A").stem("这是一道测试选择题").name("t1")
+                .pass(true).answer("A").analysis("这里是分析").kind(QuestionKindState.CHOICE).options(map).build();
+    }
+    static TrueOrFalseQuestionVO TFQ(){
+        return TrueOrFalseQuestionVO.builder().QuizId("2").studentAnswer(true).stem("这是一道测试判断题").name("t2")
+                .pass(true).answer(false).analysis("这里是分析").kind(QuestionKindState.TRUE_FALSE).build();
+    }
+}

+ 13 - 0
src/main/java/nju/seec/helper/dto/QuizAnswerDTO.java

@@ -0,0 +1,13 @@
+package nju.seec.helper.dto;
+
+import lombok.Data;
+import nju.seec.helper.vo.quiz.QuestionVO;
+import nju.seec.helper.vo.quiz.TrueOrFalseQuestionVO;
+
+import java.util.List;
+import java.util.Map;
+
+@Data
+public class QuizAnswerDTO {
+    List answers;
+}

+ 27 - 0
src/main/java/nju/seec/helper/dto/QuizDTO.java

@@ -0,0 +1,27 @@
+package nju.seec.helper.dto;
+
+import lombok.Data;
+import nju.seec.helper.util.enums.SlideState;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+import java.util.List;
+
+//interface QuizDTO {
+//  name: string; // 测试名
+//  quizTime: SlideState; // 测试时间
+//  slideId: number; // 幻灯片 id
+//  questions: number[]; // 题目 id;
+//}
+@Data
+public class QuizDTO {
+    @NotBlank
+    String name;
+    @NotNull
+    SlideState quizTime;
+    @NotBlank
+    String slideId;
+    @NotBlank
+    List questions;
+
+}

+ 29 - 0
src/main/java/nju/seec/helper/dto/QuizUpdateDTO.java

@@ -0,0 +1,29 @@
+package nju.seec.helper.dto;
+
+import lombok.Data;
+import nju.seec.helper.util.enums.SlideState;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+import java.util.List;
+
+//interface QuizDTO {
+//  name: string; // 测试名
+//  quizTime: SlideState; // 测试时间
+//  slideId: number; // 幻灯片 id
+//  questions: number[]; // 题目 id;
+//}
+@Data
+public class QuizUpdateDTO {
+    @NotBlank
+    String id;
+    @NotBlank
+    String name;
+    @NotNull
+    SlideState quizTime;
+    @NotBlank
+    String slideId;
+    @NotBlank
+    List questions;
+
+}

+ 5 - 0
src/main/java/nju/seec/helper/service/QuizService.java

@@ -0,0 +1,5 @@
+package nju.seec.helper.service;
+
+public interface QuizService {
+
+}

+ 8 - 0
src/main/java/nju/seec/helper/service/impl/QuizServiceImpl.java

@@ -0,0 +1,8 @@
+package nju.seec.helper.service.impl;
+
+import nju.seec.helper.service.QuizService;
+import org.springframework.stereotype.Service;
+
+@Service
+public class QuizServiceImpl implements QuizService {
+}

+ 20 - 0
src/main/java/nju/seec/helper/util/enums/QuestionKindState.java

@@ -0,0 +1,20 @@
+package nju.seec.helper.util.enums;
+
+/**
+ * @author cst
+ */
+public enum QuestionKindState {
+    CHOICE("选择题"), TRUE_FALSE("判断题");
+    private String name;
+    QuestionKindState(String name){
+        this.name=name;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+}

+ 20 - 0
src/main/java/nju/seec/helper/util/enums/QuizState.java

@@ -0,0 +1,20 @@
+package nju.seec.helper.util.enums;
+
+/**
+ * @author cst
+ */
+public enum QuizState {
+    NOT_STARTED("未开始"), ONGOING("正在进行"), CLOSED("已结束");
+    private String name;
+    QuizState(String name){
+        this.name=name;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+}

+ 33 - 0
src/main/java/nju/seec/helper/vo/quiz/ChoiceQuestionVO.java

@@ -0,0 +1,33 @@
+package nju.seec.helper.vo.quiz;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.experimental.SuperBuilder;
+
+import java.util.Map;
+
+@Data
+@SuperBuilder
+@AllArgsConstructor
+@NoArgsConstructor
+public class ChoiceQuestionVO extends QuestionVO{
+    @JsonProperty(value = "options")
+    private Map<String,String> options;
+    @JsonProperty(value = "answer")
+    private String answer;
+    @JsonProperty(value = "analysis")
+    private String analysis;
+    @JsonProperty(value = "studentAnswer")
+    private String studentAnswer;
+    @JsonProperty(value = "pass")
+    private boolean pass;
+}
+//kind: "CHOICE";
+//  options: {
+//    [key: string]: string;
+//  };
+//  answer: string; // 答案 [与 options 的 key 一致]
+//  analysis?: string; // 解析

+ 76 - 0
src/main/java/nju/seec/helper/vo/quiz/QuestionVO.java

@@ -0,0 +1,76 @@
+package nju.seec.helper.vo.quiz;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.experimental.SuperBuilder;
+import nju.seec.helper.util.enums.QuestionKindState;
+import nju.seec.helper.vo.CourseVO;
+import org.springframework.beans.BeanUtils;
+/**
+ * @author XuShengTao
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@SuperBuilder
+public abstract class QuestionVO {
+    @JsonProperty(value = "id")
+    private String QuizId;
+    @JsonProperty(value = "name")
+    private String name;
+    @JsonProperty(value = "kind")
+    private QuestionKindState kind;
+    @JsonProperty(value = "stem")
+    private String stem;
+}
+//QuestionSerializer
+//问题的详细定义
+//
+//Attribute
+//type QuestionSerializer =
+//  | ChoiceQuestionSerializer
+//  | TrueOrFalseQuestionSerializer;
+//
+//type QuestionWithoutAnswerSerializer = Omit<
+//  QuestionSerializer,
+//  "answer" | "analysis"
+//>;
+//
+//type QuestionWithStudentAnswerSerializer =
+//  | ChoiceQuestionWithStudentAnswer
+//  | TrueOrFalseQuestionWithStudentAnswer;
+//
+//interface Question {
+//  id: number; // 题目id
+//  kind: "CHOICE" | "TRUE_FALSE";
+//  stem: string; // 题干
+//}
+//
+//interface ChoiceQuestionSerializer extends Question {
+//  kind: "CHOICE";
+//  options: {
+//    [key: string]: string;
+//  };
+//  answer: string; // 答案 [与 options 的 key 一致]
+//  analysis?: string; // 解析
+//}
+//
+//interface ChoiceQuestionWithStudentAnswer extends ChoiceQuestionSerializer {
+//  studentAnswer: string;
+//  pass: boolean; // 是否正确
+//}
+//
+//interface TrueOrFalseQuestionSerializer extends Question {
+//  kind: "TRUE_FALSE";
+//  answer: boolean; // 答案
+//  analysis?: string; // 解析
+//}
+//
+//interface TrueOrFalseQuestionWithStudentAnswer
+//  extends TrueOrFalseQuestionSerializer {
+//  studentAnswer: boolean;
+//  pass: boolean; // 是否正确
+//}

+ 65 - 0
src/main/java/nju/seec/helper/vo/quiz/QuizVO.java

@@ -0,0 +1,65 @@
+package nju.seec.helper.vo.quiz;
+
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Builder;
+import lombok.Data;
+import nju.seec.helper.entity.Slide;
+import nju.seec.helper.util.enums.QuizState;
+import nju.seec.helper.util.enums.SlideState;
+import nju.seec.helper.vo.CourseVO;
+import nju.seec.helper.vo.SlideVO;
+
+import java.util.List;
+
+@Data
+@Builder
+public class QuizVO {
+    @JsonProperty(value = "id")
+    private String QuizId;
+    @JsonProperty(value = "name")
+    private String name;
+    @JsonProperty(value = "state")
+    private QuizState state;
+    @JsonProperty(value = "course")
+    private CourseVO courseVO;
+    @JsonProperty(value = "quizTime")
+    private SlideState quizTime;
+    @JsonProperty(value = "slide")
+    private SlideVO slide;
+    @JsonProperty(value = "questionNumber")
+    private Integer questionNumber;
+    @JsonProperty(value = "questions")
+    private List<QuestionVO> questions;
+}
+// http://47.100.18.120:3000/SEEC-BOK/API-DOC/src/master/helper/serializer/QuizSerializer.md
+// /** 已实现的枚举类 */
+//    type SlideState =
+//  | "DRAFT"
+//          | "BEFORE_CLASS" // 课前
+//          | "IN_CLASS" // 课中
+//          | "AFTER_CLASS" // 课后
+//          | "FINISH"; // 最终截止
+//
+//          type QuizState =
+//          | "NOT_STARTED" // 未开始
+//          | "ONGOING" // 正在进行
+//          | "CLOSED"; // 已结束
+//
+//interface QuizSerializer<T extends QuizState> {
+//    id: number;
+//    name: string; // 测试名
+//    state: T; // 考试状态
+//    course: CourseSerializer; // 课程详情
+//    quizTime: SlideState;
+//    slide: SlideSerializer;
+//    questions: Array<
+//            T extends "CLOSED"
+//            ? QuestionWithStudentAnswerSerializer
+//      : QuestionWithoutAnswerSerializer
+//  >;
+//}
+//
+//interface QuizBasicSerialzer extends Omit<QuizSerialzier, "questions"> {
+//        questionNumber: number; // 题目数量
+//        }

+ 25 - 0
src/main/java/nju/seec/helper/vo/quiz/TrueOrFalseQuestionVO.java

@@ -0,0 +1,25 @@
+package nju.seec.helper.vo.quiz;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.experimental.SuperBuilder;
+
+import java.util.Map;
+
+@Data
+@SuperBuilder
+@AllArgsConstructor
+@NoArgsConstructor
+public class TrueOrFalseQuestionVO extends QuestionVO{
+    @JsonProperty(value = "answer")
+    private boolean answer;
+    @JsonProperty(value = "analysis")
+    private String analysis;
+    @JsonProperty(value = "studentAnswer")
+    private boolean studentAnswer;
+    @JsonProperty(value = "pass")
+    private boolean pass;
+}