xiaof 4 سال پیش
والد
کامیت
9df8205f84
61فایلهای تغییر یافته به همراه4224 افزوده شده و 509 حذف شده
  1. 1 1
      teachcloud-common/src/main/java/com/qmth/teachcloud/common/service/impl/SysUserServiceImpl.java
  2. 5 5
      teachcloud-report-business/src/main/java/com/qmth/teachcloud/report/business/bean/dto/query/BasicExamRecordDto.java
  3. 142 0
      teachcloud-report-business/src/main/java/com/qmth/teachcloud/report/business/bean/result/CourseDimensionResult.java
  4. 29 0
      teachcloud-report-business/src/main/java/com/qmth/teachcloud/report/business/bean/result/TAExamCourseCollegeInspectResult.java
  5. 291 0
      teachcloud-report-business/src/main/java/com/qmth/teachcloud/report/business/bean/result/TAExamCourseTeacherResult.java
  6. 60 0
      teachcloud-report-business/src/main/java/com/qmth/teachcloud/report/business/bean/result/TBAnswerResult.java
  7. 63 0
      teachcloud-report-business/src/main/java/com/qmth/teachcloud/report/business/bean/result/TBPaperStructResult.java
  8. 268 184
      teachcloud-report-business/src/main/java/com/qmth/teachcloud/report/business/entity/TAExamCourse.java
  9. 18 6
      teachcloud-report-business/src/main/java/com/qmth/teachcloud/report/business/entity/TAExamCourseCollegeInspectDio.java
  10. 106 45
      teachcloud-report-business/src/main/java/com/qmth/teachcloud/report/business/entity/TAExamCourseCollegeTeacher.java
  11. 6 6
      teachcloud-report-business/src/main/java/com/qmth/teachcloud/report/business/entity/TAExamCourseRecord.java
  12. 65 40
      teachcloud-report-business/src/main/java/com/qmth/teachcloud/report/business/entity/TAExamCourseRecordDio.java
  13. 45 20
      teachcloud-report-business/src/main/java/com/qmth/teachcloud/report/business/entity/TAExamCourseRecordMod.java
  14. 59 23
      teachcloud-report-business/src/main/java/com/qmth/teachcloud/report/business/entity/TAExamTotal.java
  15. 49 12
      teachcloud-report-business/src/main/java/com/qmth/teachcloud/report/business/entity/TAPaperStruct.java
  16. 6 6
      teachcloud-report-business/src/main/java/com/qmth/teachcloud/report/business/entity/TBExamStudent.java
  17. 29 0
      teachcloud-report-business/src/main/java/com/qmth/teachcloud/report/business/enums/LevelRuleEnum.java
  18. 23 0
      teachcloud-report-business/src/main/java/com/qmth/teachcloud/report/business/enums/QuantileEnum.java
  19. 29 0
      teachcloud-report-business/src/main/java/com/qmth/teachcloud/report/business/enums/ValidityEnum.java
  20. 10 1
      teachcloud-report-business/src/main/java/com/qmth/teachcloud/report/business/mapper/TAExamCourseCollegeInspectDioMapper.java
  21. 12 0
      teachcloud-report-business/src/main/java/com/qmth/teachcloud/report/business/mapper/TAExamCourseCollegeInspectMapper.java
  22. 13 0
      teachcloud-report-business/src/main/java/com/qmth/teachcloud/report/business/mapper/TAExamCourseCollegeTeacherMapper.java
  23. 31 0
      teachcloud-report-business/src/main/java/com/qmth/teachcloud/report/business/mapper/TBAnswerMapper.java
  24. 13 0
      teachcloud-report-business/src/main/java/com/qmth/teachcloud/report/business/mapper/TBDimensionMapper.java
  25. 10 1
      teachcloud-report-business/src/main/java/com/qmth/teachcloud/report/business/mapper/TBModuleConfigMapper.java
  26. 12 0
      teachcloud-report-business/src/main/java/com/qmth/teachcloud/report/business/mapper/TBPaperStructMapper.java
  27. 105 0
      teachcloud-report-business/src/main/java/com/qmth/teachcloud/report/business/service/AnalyzeForStudentService.java
  28. 6 1
      teachcloud-report-business/src/main/java/com/qmth/teachcloud/report/business/service/TAExamCourseCollegeInspectDioService.java
  29. 11 0
      teachcloud-report-business/src/main/java/com/qmth/teachcloud/report/business/service/TAExamCourseCollegeInspectService.java
  30. 13 0
      teachcloud-report-business/src/main/java/com/qmth/teachcloud/report/business/service/TAExamCourseCollegeTeacherService.java
  31. 11 0
      teachcloud-report-business/src/main/java/com/qmth/teachcloud/report/business/service/TAExamCourseService.java
  32. 30 0
      teachcloud-report-business/src/main/java/com/qmth/teachcloud/report/business/service/TBAnswerService.java
  33. 12 0
      teachcloud-report-business/src/main/java/com/qmth/teachcloud/report/business/service/TBDimensionService.java
  34. 9 1
      teachcloud-report-business/src/main/java/com/qmth/teachcloud/report/business/service/TBModuleConfigService.java
  35. 11 0
      teachcloud-report-business/src/main/java/com/qmth/teachcloud/report/business/service/TBPaperStructService.java
  36. 1605 0
      teachcloud-report-business/src/main/java/com/qmth/teachcloud/report/business/service/impl/AnalyzeForStudentServiceImpl.java
  37. 25 0
      teachcloud-report-business/src/main/java/com/qmth/teachcloud/report/business/service/impl/TAExamCourseCollegeInspectDioServiceImpl.java
  38. 18 0
      teachcloud-report-business/src/main/java/com/qmth/teachcloud/report/business/service/impl/TAExamCourseCollegeInspectServiceImpl.java
  39. 15 0
      teachcloud-report-business/src/main/java/com/qmth/teachcloud/report/business/service/impl/TAExamCourseCollegeTeacherServiceImpl.java
  40. 81 10
      teachcloud-report-business/src/main/java/com/qmth/teachcloud/report/business/service/impl/TAExamCourseServiceImpl.java
  41. 30 0
      teachcloud-report-business/src/main/java/com/qmth/teachcloud/report/business/service/impl/TBAnswerServiceImpl.java
  42. 19 0
      teachcloud-report-business/src/main/java/com/qmth/teachcloud/report/business/service/impl/TBDimensionServiceImpl.java
  43. 1 1
      teachcloud-report-business/src/main/java/com/qmth/teachcloud/report/business/service/impl/TBExamStudentServiceImpl.java
  44. 9 0
      teachcloud-report-business/src/main/java/com/qmth/teachcloud/report/business/service/impl/TBModuleConfigServiceImpl.java
  45. 18 0
      teachcloud-report-business/src/main/java/com/qmth/teachcloud/report/business/service/impl/TBPaperStructServiceImpl.java
  46. 33 0
      teachcloud-report-business/src/main/java/com/qmth/teachcloud/report/business/utils/AnalyzeScopeUtil.java
  47. 65 0
      teachcloud-report-business/src/main/java/com/qmth/teachcloud/report/business/utils/ConversionUtils.java
  48. 184 0
      teachcloud-report-business/src/main/java/com/qmth/teachcloud/report/business/utils/MathUtil.java
  49. 142 142
      teachcloud-report-business/src/main/resources/db/init-table.sql
  50. 24 0
      teachcloud-report-business/src/main/resources/mapper/TAExamCourseCollegeInspectDioMapper.xml
  51. 31 0
      teachcloud-report-business/src/main/resources/mapper/TAExamCourseCollegeInspectMapper.xml
  52. 48 0
      teachcloud-report-business/src/main/resources/mapper/TAExamCourseCollegeTeacherMapper.xml
  53. 75 0
      teachcloud-report-business/src/main/resources/mapper/TBAnswerMapper.xml
  54. 55 0
      teachcloud-report-business/src/main/resources/mapper/TBDimensionMapper.xml
  55. 1 1
      teachcloud-report-business/src/main/resources/mapper/TBExamRecordMapper.xml
  56. 10 0
      teachcloud-report-business/src/main/resources/mapper/TBModuleConfigMapper.xml
  57. 26 0
      teachcloud-report-business/src/main/resources/mapper/TBPaperStructMapper.xml
  58. 4 3
      teachcloud-report/src/main/java/com/qmth/teachcloud/report/api/BasicDatasourceController.java
  59. 11 0
      teachcloud-report/src/main/java/com/qmth/teachcloud/report/api/CourseController.java
  60. 1 0
      teachcloud-report/src/main/resources/application-dev.properties
  61. 90 0
      teachcloud-report/src/test/java/com/qmth/teachcloud/report/AnalyzeForStudentServiceTest.java

+ 1 - 1
teachcloud-common/src/main/java/com/qmth/teachcloud/common/service/impl/SysUserServiceImpl.java

@@ -247,7 +247,7 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
                 .eq(SysUser::getLoginName,teacherCode)
                 .eq(SysUser::getRealName,teacherName));
         SysRole sysRole = sysRoleService.getOne(new QueryWrapper<SysRole>().lambda().eq(SysRole::getType,RoleTypeEnum.TEACHER));
-        tbSchoolTeacherList = tbSchoolTeacherList.stream().filter(e -> Arrays.asList(e.getRoleIds()).contains(sysRole.getId())).collect(Collectors.toList());
+//        tbSchoolTeacherList = tbSchoolTeacherList.stream().filter(e -> Arrays.asList(e.getRoleIds()).contains(sysRole.getId())).collect(Collectors.toList());
         if (tbSchoolTeacherList.size() != 1){
             throw ExceptionResultEnum.ERROR.exception("教师基础数据信息异常");
         }

+ 5 - 5
teachcloud-report-business/src/main/java/com/qmth/teachcloud/report/business/bean/dto/query/BasicExamRecordDto.java

@@ -22,7 +22,7 @@ public class BasicExamRecordDto {
     private String ticketNumber;
     private String studentCode;
     private Boolean absent;
-    private Boolean current;
+    private Boolean studentCurrent;
     private Long tbExamRecordId;
     private Long paperId;
     private String paperType;
@@ -142,12 +142,12 @@ public class BasicExamRecordDto {
         this.absent = absent;
     }
 
-    public Boolean getCurrent() {
-        return current;
+    public Boolean getStudentCurrent() {
+        return studentCurrent;
     }
 
-    public void setCurrent(Boolean current) {
-        this.current = current;
+    public void setStudentCurrent(Boolean studentCurrent) {
+        this.studentCurrent = studentCurrent;
     }
 
     public Long getTbExamRecordId() {

+ 142 - 0
teachcloud-report-business/src/main/java/com/qmth/teachcloud/report/business/bean/result/CourseDimensionResult.java

@@ -0,0 +1,142 @@
+package com.qmth.teachcloud.report.business.bean.result;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
+import io.swagger.annotations.ApiModelProperty;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+/**
+ * @Description: 课程维度result
+ * @Param:
+ * @return:
+ * @Author: wangliang
+ * @Date: 2021/6/10
+ */
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class CourseDimensionResult implements Serializable {
+
+    @ApiModelProperty(value = "考试id")
+    @JsonSerialize(using = ToStringSerializer.class)
+    private Long examId;
+
+    @ApiModelProperty(value = "考试编码")
+    private String examCode;
+
+    @ApiModelProperty(value = "科目编码")
+    private String courseCode;
+
+    @ApiModelProperty(value = "模块")
+    private String module;
+
+    @ApiModelProperty(value = "维度编码")
+    private String dimensionCode;
+
+    @ApiModelProperty(value = "维度名称")
+    private String dimensionName;
+
+    @ApiModelProperty(value = "简介")
+    private String interpretation;
+
+    @ApiModelProperty(value = "共计")
+    private Integer totalCount;
+
+    @ApiModelProperty(value = "学校比率")
+    private BigDecimal schScoreRate;
+
+    @ApiModelProperty(value = "学院比率")
+    private BigDecimal colScoreRate;
+
+    @ApiModelProperty(value = "学院名称")
+    private String collegeName;
+
+    public Long getExamId() {
+        return examId;
+    }
+
+    public void setExamId(Long examId) {
+        this.examId = examId;
+    }
+
+    public String getExamCode() {
+        return examCode;
+    }
+
+    public void setExamCode(String examCode) {
+        this.examCode = examCode;
+    }
+
+    public String getCourseCode() {
+        return courseCode;
+    }
+
+    public void setCourseCode(String courseCode) {
+        this.courseCode = courseCode;
+    }
+
+    public String getModule() {
+        return module;
+    }
+
+    public void setModule(String module) {
+        this.module = module;
+    }
+
+    public String getDimensionCode() {
+        return dimensionCode;
+    }
+
+    public void setDimensionCode(String dimensionCode) {
+        this.dimensionCode = dimensionCode;
+    }
+
+    public String getDimensionName() {
+        return dimensionName;
+    }
+
+    public void setDimensionName(String dimensionName) {
+        this.dimensionName = dimensionName;
+    }
+
+    public String getInterpretation() {
+        return interpretation;
+    }
+
+    public void setInterpretation(String interpretation) {
+        this.interpretation = interpretation;
+    }
+
+    public Integer getTotalCount() {
+        return totalCount;
+    }
+
+    public void setTotalCount(Integer totalCount) {
+        this.totalCount = totalCount;
+    }
+
+    public BigDecimal getSchScoreRate() {
+        return schScoreRate;
+    }
+
+    public void setSchScoreRate(BigDecimal schScoreRate) {
+        this.schScoreRate = schScoreRate;
+    }
+
+    public BigDecimal getColScoreRate() {
+        return colScoreRate;
+    }
+
+    public void setColScoreRate(BigDecimal colScoreRate) {
+        this.colScoreRate = colScoreRate;
+    }
+
+    public String getCollegeName() {
+        return collegeName;
+    }
+
+    public void setCollegeName(String collegeName) {
+        this.collegeName = collegeName;
+    }
+}

+ 29 - 0
teachcloud-report-business/src/main/java/com/qmth/teachcloud/report/business/bean/result/TAExamCourseCollegeInspectResult.java

@@ -0,0 +1,29 @@
+package com.qmth.teachcloud.report.business.bean.result;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.qmth.teachcloud.report.business.entity.TAExamCourseCollegeInspect;
+import io.swagger.annotations.ApiModelProperty;
+
+import java.io.Serializable;
+
+/**
+ * @Description: 参考课程考察学院维度分析 result
+ * @Param:
+ * @return:
+ * @Author: wangliang
+ * @Date: 2021/6/10
+ */
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class TAExamCourseCollegeInspectResult extends TAExamCourseCollegeInspect implements Serializable {
+
+    @ApiModelProperty(value = "学院名称")
+    private String collegeName;
+
+    public String getCollegeName() {
+        return collegeName;
+    }
+
+    public void setCollegeName(String collegeName) {
+        this.collegeName = collegeName;
+    }
+}

+ 291 - 0
teachcloud-report-business/src/main/java/com/qmth/teachcloud/report/business/bean/result/TAExamCourseTeacherResult.java

@@ -0,0 +1,291 @@
+package com.qmth.teachcloud.report.business.bean.result;
+
+import io.swagger.annotations.ApiModelProperty;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+/**
+ * @Description: TAExamCourseTeacherResult
+ * @Param:
+ * @return:
+ * @Author: wangliang
+ * @Date: 2021/6/10
+ */
+public class TAExamCourseTeacherResult implements Serializable {
+
+    @ApiModelProperty(value = "老师姓名")
+    private String teacherName;
+
+    @ApiModelProperty(value = "学院参考人数")
+    private Integer colRealityCount;
+
+    @ApiModelProperty(value = "学院总人数")
+    private Integer colTotalCount;
+
+    @ApiModelProperty(value = "学院缺考人数")
+    private Integer colAbsentCount;
+
+    @ApiModelProperty(value = "学院最低分")
+    private BigDecimal colMinScore;
+
+    @ApiModelProperty(value = "学院最高分")
+    private BigDecimal colMaxScore;
+
+    @ApiModelProperty(value = "学院平均分")
+    private BigDecimal colAvgScore;
+
+    @ApiModelProperty(value = "学院上四分位数")
+    private BigDecimal colUpperQuartile;
+
+    @ApiModelProperty(value = "学院中位数")
+    private BigDecimal colMedian;
+
+    @ApiModelProperty(value = "学院下四分位数")
+    private BigDecimal colLowerQuartile;
+
+    @ApiModelProperty(value = "学院授课学生分数众数")
+    private String colMode;
+
+    @ApiModelProperty(value = "学院授课学生分数标准差")
+    private BigDecimal colStandardDeviation;
+
+    @ApiModelProperty(value = "学院相对位置")
+    private BigDecimal colRelativePosition;
+
+    @ApiModelProperty(value = "学校参考人数")
+    private Integer schRealityCount;
+
+    @ApiModelProperty(value = "学校总人数")
+    private Integer schTotalCount;
+
+    @ApiModelProperty(value = "学校缺考人数")
+    private Integer schAbsentCount;
+
+    @ApiModelProperty(value = "学校最低分")
+    private BigDecimal schMinScore;
+
+    @ApiModelProperty(value = "学校最高分")
+    private BigDecimal schMaxScore;
+
+    @ApiModelProperty(value = "学校平均分")
+    private BigDecimal schAvgScore;
+
+    @ApiModelProperty(value = "学校上四分位数")
+    private BigDecimal schUpperQuartile;
+
+    @ApiModelProperty(value = "学校中位数")
+    private BigDecimal schMedian;
+
+    @ApiModelProperty(value = "学校下四分位数")
+    private BigDecimal schLowerQuartile;
+
+    @ApiModelProperty(value = "学校授课学生分数众数")
+    private String schMode;
+
+    @ApiModelProperty(value = "学校授课学生分数标准差")
+    private BigDecimal schStandardDeviation;
+
+    @ApiModelProperty(value = "学校相对位置")
+    private BigDecimal schRelativePosition;
+
+    public String getTeacherName() {
+        return teacherName;
+    }
+
+    public void setTeacherName(String teacherName) {
+        this.teacherName = teacherName;
+    }
+
+    public Integer getColRealityCount() {
+        return colRealityCount;
+    }
+
+    public void setColRealityCount(Integer colRealityCount) {
+        this.colRealityCount = colRealityCount;
+    }
+
+    public Integer getColTotalCount() {
+        return colTotalCount;
+    }
+
+    public void setColTotalCount(Integer colTotalCount) {
+        this.colTotalCount = colTotalCount;
+    }
+
+    public Integer getColAbsentCount() {
+        return colAbsentCount;
+    }
+
+    public void setColAbsentCount(Integer colAbsentCount) {
+        this.colAbsentCount = colAbsentCount;
+    }
+
+    public BigDecimal getColMinScore() {
+        return colMinScore;
+    }
+
+    public void setColMinScore(BigDecimal colMinScore) {
+        this.colMinScore = colMinScore;
+    }
+
+    public BigDecimal getColMaxScore() {
+        return colMaxScore;
+    }
+
+    public void setColMaxScore(BigDecimal colMaxScore) {
+        this.colMaxScore = colMaxScore;
+    }
+
+    public BigDecimal getColAvgScore() {
+        return colAvgScore;
+    }
+
+    public void setColAvgScore(BigDecimal colAvgScore) {
+        this.colAvgScore = colAvgScore;
+    }
+
+    public BigDecimal getColUpperQuartile() {
+        return colUpperQuartile;
+    }
+
+    public void setColUpperQuartile(BigDecimal colUpperQuartile) {
+        this.colUpperQuartile = colUpperQuartile;
+    }
+
+    public BigDecimal getColMedian() {
+        return colMedian;
+    }
+
+    public void setColMedian(BigDecimal colMedian) {
+        this.colMedian = colMedian;
+    }
+
+    public BigDecimal getColLowerQuartile() {
+        return colLowerQuartile;
+    }
+
+    public void setColLowerQuartile(BigDecimal colLowerQuartile) {
+        this.colLowerQuartile = colLowerQuartile;
+    }
+
+    public String getColMode() {
+        return colMode;
+    }
+
+    public void setColMode(String colMode) {
+        this.colMode = colMode;
+    }
+
+    public BigDecimal getColStandardDeviation() {
+        return colStandardDeviation;
+    }
+
+    public void setColStandardDeviation(BigDecimal colStandardDeviation) {
+        this.colStandardDeviation = colStandardDeviation;
+    }
+
+    public BigDecimal getColRelativePosition() {
+        return colRelativePosition;
+    }
+
+    public void setColRelativePosition(BigDecimal colRelativePosition) {
+        this.colRelativePosition = colRelativePosition;
+    }
+
+    public Integer getSchRealityCount() {
+        return schRealityCount;
+    }
+
+    public void setSchRealityCount(Integer schRealityCount) {
+        this.schRealityCount = schRealityCount;
+    }
+
+    public Integer getSchTotalCount() {
+        return schTotalCount;
+    }
+
+    public void setSchTotalCount(Integer schTotalCount) {
+        this.schTotalCount = schTotalCount;
+    }
+
+    public Integer getSchAbsentCount() {
+        return schAbsentCount;
+    }
+
+    public void setSchAbsentCount(Integer schAbsentCount) {
+        this.schAbsentCount = schAbsentCount;
+    }
+
+    public BigDecimal getSchMinScore() {
+        return schMinScore;
+    }
+
+    public void setSchMinScore(BigDecimal schMinScore) {
+        this.schMinScore = schMinScore;
+    }
+
+    public BigDecimal getSchMaxScore() {
+        return schMaxScore;
+    }
+
+    public void setSchMaxScore(BigDecimal schMaxScore) {
+        this.schMaxScore = schMaxScore;
+    }
+
+    public BigDecimal getSchAvgScore() {
+        return schAvgScore;
+    }
+
+    public void setSchAvgScore(BigDecimal schAvgScore) {
+        this.schAvgScore = schAvgScore;
+    }
+
+    public BigDecimal getSchUpperQuartile() {
+        return schUpperQuartile;
+    }
+
+    public void setSchUpperQuartile(BigDecimal schUpperQuartile) {
+        this.schUpperQuartile = schUpperQuartile;
+    }
+
+    public BigDecimal getSchMedian() {
+        return schMedian;
+    }
+
+    public void setSchMedian(BigDecimal schMedian) {
+        this.schMedian = schMedian;
+    }
+
+    public BigDecimal getSchLowerQuartile() {
+        return schLowerQuartile;
+    }
+
+    public void setSchLowerQuartile(BigDecimal schLowerQuartile) {
+        this.schLowerQuartile = schLowerQuartile;
+    }
+
+    public String getSchMode() {
+        return schMode;
+    }
+
+    public void setSchMode(String schMode) {
+        this.schMode = schMode;
+    }
+
+    public BigDecimal getSchStandardDeviation() {
+        return schStandardDeviation;
+    }
+
+    public void setSchStandardDeviation(BigDecimal schStandardDeviation) {
+        this.schStandardDeviation = schStandardDeviation;
+    }
+
+    public BigDecimal getSchRelativePosition() {
+        return schRelativePosition;
+    }
+
+    public void setSchRelativePosition(BigDecimal schRelativePosition) {
+        this.schRelativePosition = schRelativePosition;
+    }
+}

+ 60 - 0
teachcloud-report-business/src/main/java/com/qmth/teachcloud/report/business/bean/result/TBAnswerResult.java

@@ -0,0 +1,60 @@
+package com.qmth.teachcloud.report.business.bean.result;
+
+import io.swagger.annotations.ApiModelProperty;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+/**
+ * @Description: TBAnswerResult
+ * @Param:
+ * @return:
+ * @Author: wangliang
+ * @Date: 2021/6/10
+ */
+public class TBAnswerResult implements Serializable {
+
+    @ApiModelProperty(value = "试卷类型")
+    private String paperType;
+
+    @ApiModelProperty(value = "得分率")
+    private BigDecimal scoreRate;
+
+    @ApiModelProperty(value = "难度")
+    private String difficult;
+
+    @ApiModelProperty(value = "学院名称")
+    private String collegeName;
+
+    public String getPaperType() {
+        return paperType;
+    }
+
+    public void setPaperType(String paperType) {
+        this.paperType = paperType;
+    }
+
+    public BigDecimal getScoreRate() {
+        return scoreRate;
+    }
+
+    public void setScoreRate(BigDecimal scoreRate) {
+        this.scoreRate = scoreRate;
+    }
+
+    public String getDifficult() {
+        return difficult;
+    }
+
+    public void setDifficult(String difficult) {
+        this.difficult = difficult;
+    }
+
+    public String getCollegeName() {
+        return collegeName;
+    }
+
+    public void setCollegeName(String collegeName) {
+        this.collegeName = collegeName;
+    }
+}

+ 63 - 0
teachcloud-report-business/src/main/java/com/qmth/teachcloud/report/business/bean/result/TBPaperStructResult.java

@@ -0,0 +1,63 @@
+package com.qmth.teachcloud.report.business.bean.result;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.qmth.teachcloud.report.business.entity.TBPaperStruct;
+import io.swagger.annotations.ApiModelProperty;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+/**
+ * @Description: 试卷结构result
+ * @Param:
+ * @return:
+ * @Author: wangliang
+ * @Date: 2021/6/10
+ */
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class TBPaperStructResult extends TBPaperStruct implements Serializable {
+
+    @ApiModelProperty(value = "试卷类型")
+    private String paperType;
+
+    @ApiModelProperty(value = "得分率")
+    private BigDecimal scoreRate;
+
+    @ApiModelProperty(value = "难度")
+    private String difficult;
+
+    @ApiModelProperty(value = "效度")
+    private BigDecimal validity;
+
+    public String getPaperType() {
+        return paperType;
+    }
+
+    public void setPaperType(String paperType) {
+        this.paperType = paperType;
+    }
+
+    public BigDecimal getScoreRate() {
+        return scoreRate;
+    }
+
+    public void setScoreRate(BigDecimal scoreRate) {
+        this.scoreRate = scoreRate;
+    }
+
+    public String getDifficult() {
+        return difficult;
+    }
+
+    public void setDifficult(String difficult) {
+        this.difficult = difficult;
+    }
+
+    public BigDecimal getValidity() {
+        return validity;
+    }
+
+    public void setValidity(BigDecimal validity) {
+        this.validity = validity;
+    }
+}

+ 268 - 184
teachcloud-report-business/src/main/java/com/qmth/teachcloud/report/business/entity/TAExamCourse.java

@@ -33,42 +33,59 @@ public class TAExamCourse implements Serializable {
     @TableField(value = "exam_id")
     private Long examId;
 
+    @ApiModelProperty(value = "考试名称(冗余)")
+    @TableField(value = "exam_name")
+    private String examName;
+
     @ApiModelProperty(value = "科目编码")
     @TableField(value = "course_code")
     private String courseCode;
 
+    @ApiModelProperty(value = "科目名称")
+    @TableField(value = "course_name")
+    private String courseName;
+
     @ApiModelProperty(value = "学校id(冗余)")
     @JsonSerialize(using = ToStringSerializer.class)
     @TableField(value = "school_id")
     private Long schoolId;
 
-    @ApiModelProperty(value = "考试名称(冗余)")
-    @TableField(value = "exam_name")
-    private String examName;
-
-    @ApiModelProperty(value = "科目名称")
-    @TableField(value = "course_name")
-    private String courseName;
-
-    @ApiModelProperty(value = "试卷满分")
-    @TableField(value = "total_score")
-    private BigDecimal totalScore;
+    @ApiModelProperty(value = "开课学院id")
+    @JsonSerialize(using = ToStringSerializer.class)
+    @TableField(value = "teach_college_id")
+    private Long teachCollegeId;
 
-    @ApiModelProperty(value = "最低分")
-    @TableField(value = "min_score")
-    private BigDecimal minScore;
+    @ApiModelProperty(value = "开课学院名称")
+    @TableField(value = "teach_college_name")
+    private String teachCollegeName;
 
-    @ApiModelProperty(value = "最高分")
-    @TableField(value = "max_score")
-    private BigDecimal maxScore;
+    @ApiModelProperty(value = "考察学院数量")
+    @TableField(value = "inspect_college_count")
+    private Integer inspectCollegeCount;
 
-    @ApiModelProperty(value = "全体参考平均分")
+    @ApiModelProperty(value = "总体平均分")
     @TableField(value = "avg_score")
     private BigDecimal avgScore;
 
-    @ApiModelProperty(value = "难度系数(得分率)")
-    @TableField(value = "score_rate")
-    private BigDecimal scoreRate;
+    @ApiModelProperty(value = "通过人数")
+    @TableField(value = "pass_count")
+    private Integer passCount;
+
+    @ApiModelProperty(value = "通过率")
+    @TableField(value = "pass_rate")
+    private BigDecimal passRate;
+
+    @ApiModelProperty(value = "应届通过人数")
+    @TableField(value = "current_pass_count")
+    private Integer currentPassCount;
+
+    @ApiModelProperty(value = "应届通过率")
+    @TableField(value = "current_pass_rate")
+    private BigDecimal currentPassRate;
+
+    @ApiModelProperty(value = "试卷满分")
+    @TableField(value = "total_score")
+    private BigDecimal totalScore;
 
     @ApiModelProperty(value = "实际参考人数")
     @TableField(value = "reality_count")
@@ -82,29 +99,77 @@ public class TAExamCourse implements Serializable {
     @TableField(value = "total_count")
     private Integer totalCount;
 
-    @ApiModelProperty(value = "本次科目难度")
-    @TableField(value = "difficulty")
-    private String difficulty;
+    @ApiModelProperty(value = "最低分")
+    @TableField(value = "current_min_score")
+    private BigDecimal currentMinScore;
+
+    @ApiModelProperty(value = "最高分")
+    @TableField(value = "current_max_score")
+    private BigDecimal currentMaxScore;
+
+    @ApiModelProperty(value = "全体参考平均分")
+    @TableField(value = "current_avg_score")
+    private BigDecimal currentAvgScore;
+
+    @ApiModelProperty(value = "难度系数(得分率)")
+    @TableField(value = "current_score_rate")
+    private BigDecimal currentScoreRate;
+
+    @ApiModelProperty(value = "应届实际考试人数")
+    @TableField(value = "current_reality_count")
+    private Integer currentRealityCount;
+
+    @ApiModelProperty(value = "应届缺考人数")
+    @TableField(value = "current_absent_count")
+    private Integer currentAbsentCount;
+
+    @ApiModelProperty(value = "应届总考试人数")
+    @TableField(value = "current_total_count")
+    private Integer currentTotalCount;
+
+    @ApiModelProperty(value = "应届实际考试人数占比")
+    @TableField(value = "current_reality_rate")
+    private BigDecimal currentRealityRate;
+
+    @ApiModelProperty(value = "往届实际考试人数")
+    @TableField(value = "past_reality_count")
+    private Integer pastRealityCount;
+
+    @ApiModelProperty(value = "往届缺考人数")
+    @TableField(value = "past_absent_count")
+    private Integer pastAbsentCount;
+
+    @ApiModelProperty(value = "往届总人数")
+    @TableField(value = "past_total_count")
+    private Integer pastTotalCount;
+
+    @ApiModelProperty(value = "往届实际考试人数占比")
+    @TableField(value = "past_reality_rate")
+    private BigDecimal pastRealityRate;
 
     @ApiModelProperty(value = "上四分位数")
-    @TableField(value = "upper_quartile")
-    private BigDecimal upperQuartile;
+    @TableField(value = "current_upper_quartile")
+    private BigDecimal currentUpperQuartile;
 
     @ApiModelProperty(value = "中位数")
-    @TableField(value = "median")
-    private BigDecimal median;
+    @TableField(value = "current_median")
+    private BigDecimal currentMedian;
 
     @ApiModelProperty(value = "下四分位数")
-    @TableField(value = "lower_quartile")
-    private BigDecimal lowerQuartile;
+    @TableField(value = "current_lower_quartile")
+    private BigDecimal currentLowerQuartile;
 
     @ApiModelProperty(value = "众数")
-    @TableField(value = "mode")
-    private String mode;
+    @TableField(value = "current_mode")
+    private String currentMode;
 
     @ApiModelProperty(value = "标准差")
-    @TableField(value = "standard_deviation")
-    private BigDecimal standardDeviation;
+    @TableField(value = "current_standard_deviation")
+    private BigDecimal currentStandardDeviation;
+
+    @ApiModelProperty(value = "本次科目难度(应届)")
+    @TableField(value = "difficulty")
+    private String difficulty;
 
     @ApiModelProperty(value = "总体卷面平均分")
     @TableField(value = "paper_avg_score")
@@ -126,42 +191,57 @@ public class TAExamCourse implements Serializable {
     @TableField(value = "coefficient")
     private BigDecimal coefficient;
 
-    @ApiModelProperty(value = "开课学院id")
-    @JsonSerialize(using = ToStringSerializer.class)
-    @TableField(value = "teach_college_id")
-    private Long teachCollegeId;
+    public static long getSerialVersionUID() {
+        return serialVersionUID;
+    }
 
-    @ApiModelProperty(value = "开课学院名称")
-    @TableField(value = "teach_college_name")
-    private String teachCollegeName;
+    public Long getId() {
+        return id;
+    }
 
-    @ApiModelProperty(value = "考察学院数量")
-    @TableField(value = "inspect_college_count")
-    private Integer inspectCollegeCount;
+    public void setId(Long id) {
+        this.id = id;
+    }
 
-    @ApiModelProperty(value = "应届实际考试人数占比")
-    @TableField(value = "current_reality_rate")
-    private BigDecimal currentRealityRate;
+    public Long getExamId() {
+        return examId;
+    }
 
-    @ApiModelProperty(value = "应届总考试人数")
-    @TableField(value = "current_total_count")
-    private Integer currentTotalCount;
+    public void setExamId(Long examId) {
+        this.examId = examId;
+    }
 
-    @ApiModelProperty(value = "应届实际考试人数")
-    @TableField(value = "current_reality_count")
-    private Integer currentRealityCount;
+    public String getExamName() {
+        return examName;
+    }
 
-    @ApiModelProperty(value = "往届实际考试人数占比")
-    @TableField(value = "past_reality_rate")
-    private BigDecimal pastRealityRate;
+    public void setExamName(String examName) {
+        this.examName = examName;
+    }
 
-    @ApiModelProperty(value = "往届总考试人数")
-    @TableField(value = "past_total_count")
-    private Integer pastTotalCount;
+    public String getCourseCode() {
+        return courseCode;
+    }
 
-    @ApiModelProperty(value = "往届实际考试人数")
-    @TableField(value = "past_reality_count")
-    private Integer pastRealityCount;
+    public void setCourseCode(String courseCode) {
+        this.courseCode = courseCode;
+    }
+
+    public String getCourseName() {
+        return courseName;
+    }
+
+    public void setCourseName(String courseName) {
+        this.courseName = courseName;
+    }
+
+    public Long getSchoolId() {
+        return schoolId;
+    }
+
+    public void setSchoolId(Long schoolId) {
+        this.schoolId = schoolId;
+    }
 
     public Long getTeachCollegeId() {
         return teachCollegeId;
@@ -187,208 +267,212 @@ public class TAExamCourse implements Serializable {
         this.inspectCollegeCount = inspectCollegeCount;
     }
 
-    public BigDecimal getCurrentRealityRate() {
-        return currentRealityRate;
+    public BigDecimal getAvgScore() {
+        return avgScore;
     }
 
-    public void setCurrentRealityRate(BigDecimal currentRealityRate) {
-        this.currentRealityRate = currentRealityRate;
+    public void setAvgScore(BigDecimal avgScore) {
+        this.avgScore = avgScore;
     }
 
-    public Integer getCurrentTotalCount() {
-        return currentTotalCount;
+    public Integer getPassCount() {
+        return passCount;
     }
 
-    public void setCurrentTotalCount(Integer currentTotalCount) {
-        this.currentTotalCount = currentTotalCount;
+    public void setPassCount(Integer passCount) {
+        this.passCount = passCount;
     }
 
-    public Integer getCurrentRealityCount() {
-        return currentRealityCount;
+    public BigDecimal getPassRate() {
+        return passRate;
     }
 
-    public void setCurrentRealityCount(Integer currentRealityCount) {
-        this.currentRealityCount = currentRealityCount;
+    public void setPassRate(BigDecimal passRate) {
+        this.passRate = passRate;
     }
 
-    public BigDecimal getPastRealityRate() {
-        return pastRealityRate;
+    public Integer getCurrentPassCount() {
+        return currentPassCount;
     }
 
-    public void setPastRealityRate(BigDecimal pastRealityRate) {
-        this.pastRealityRate = pastRealityRate;
+    public void setCurrentPassCount(Integer currentPassCount) {
+        this.currentPassCount = currentPassCount;
     }
 
-    public Integer getPastTotalCount() {
-        return pastTotalCount;
+    public BigDecimal getCurrentPassRate() {
+        return currentPassRate;
     }
 
-    public void setPastTotalCount(Integer pastTotalCount) {
-        this.pastTotalCount = pastTotalCount;
+    public void setCurrentPassRate(BigDecimal currentPassRate) {
+        this.currentPassRate = currentPassRate;
     }
 
-    public Integer getPastRealityCount() {
-        return pastRealityCount;
+    public BigDecimal getTotalScore() {
+        return totalScore;
     }
 
-    public void setPastRealityCount(Integer pastRealityCount) {
-        this.pastRealityCount = pastRealityCount;
+    public void setTotalScore(BigDecimal totalScore) {
+        this.totalScore = totalScore;
     }
 
-    public BigDecimal getPaperAvgScore() {
-        return paperAvgScore;
+    public Integer getRealityCount() {
+        return realityCount;
     }
 
-    public void setPaperAvgScore(BigDecimal paperAvgScore) {
-        this.paperAvgScore = paperAvgScore;
+    public void setRealityCount(Integer realityCount) {
+        this.realityCount = realityCount;
     }
 
-    public BigDecimal getPaperCurrentAvgScore() {
-        return paperCurrentAvgScore;
+    public Integer getAbsentCount() {
+        return absentCount;
     }
 
-    public void setPaperCurrentAvgScore(BigDecimal paperCurrentAvgScore) {
-        this.paperCurrentAvgScore = paperCurrentAvgScore;
+    public void setAbsentCount(Integer absentCount) {
+        this.absentCount = absentCount;
     }
 
-    public BigDecimal getPaperPassRate() {
-        return paperPassRate;
+    public Integer getTotalCount() {
+        return totalCount;
     }
 
-    public void setPaperPassRate(BigDecimal paperPassRate) {
-        this.paperPassRate = paperPassRate;
+    public void setTotalCount(Integer totalCount) {
+        this.totalCount = totalCount;
     }
 
-    public BigDecimal getPaperCurrentPassRate() {
-        return paperCurrentPassRate;
+    public BigDecimal getCurrentMinScore() {
+        return currentMinScore;
     }
 
-    public void setPaperCurrentPassRate(BigDecimal paperCurrentPassRate) {
-        this.paperCurrentPassRate = paperCurrentPassRate;
+    public void setCurrentMinScore(BigDecimal currentMinScore) {
+        this.currentMinScore = currentMinScore;
     }
 
-    public BigDecimal getCoefficient() {
-        return coefficient;
+    public BigDecimal getCurrentMaxScore() {
+        return currentMaxScore;
     }
 
-    public void setCoefficient(BigDecimal coefficient) {
-        this.coefficient = coefficient;
+    public void setCurrentMaxScore(BigDecimal currentMaxScore) {
+        this.currentMaxScore = currentMaxScore;
     }
 
-    public static long getSerialVersionUID() {
-        return serialVersionUID;
+    public BigDecimal getCurrentAvgScore() {
+        return currentAvgScore;
     }
 
-    public Long getId() {
-        return id;
+    public void setCurrentAvgScore(BigDecimal currentAvgScore) {
+        this.currentAvgScore = currentAvgScore;
     }
 
-    public void setId(Long id) {
-        this.id = id;
+    public BigDecimal getCurrentScoreRate() {
+        return currentScoreRate;
     }
 
-    public Long getExamId() {
-        return examId;
+    public void setCurrentScoreRate(BigDecimal currentScoreRate) {
+        this.currentScoreRate = currentScoreRate;
     }
 
-    public void setExamId(Long examId) {
-        this.examId = examId;
+    public Integer getCurrentRealityCount() {
+        return currentRealityCount;
     }
 
-    public String getCourseCode() {
-        return courseCode;
+    public void setCurrentRealityCount(Integer currentRealityCount) {
+        this.currentRealityCount = currentRealityCount;
     }
 
-    public void setCourseCode(String courseCode) {
-        this.courseCode = courseCode;
+    public Integer getCurrentAbsentCount() {
+        return currentAbsentCount;
     }
 
-    public Long getSchoolId() {
-        return schoolId;
+    public void setCurrentAbsentCount(Integer currentAbsentCount) {
+        this.currentAbsentCount = currentAbsentCount;
     }
 
-    public void setSchoolId(Long schoolId) {
-        this.schoolId = schoolId;
+    public Integer getCurrentTotalCount() {
+        return currentTotalCount;
     }
 
-    public String getExamName() {
-        return examName;
+    public void setCurrentTotalCount(Integer currentTotalCount) {
+        this.currentTotalCount = currentTotalCount;
     }
 
-    public void setExamName(String examName) {
-        this.examName = examName;
+    public BigDecimal getCurrentRealityRate() {
+        return currentRealityRate;
     }
 
-    public String getCourseName() {
-        return courseName;
+    public void setCurrentRealityRate(BigDecimal currentRealityRate) {
+        this.currentRealityRate = currentRealityRate;
     }
 
-    public void setCourseName(String courseName) {
-        this.courseName = courseName;
+    public Integer getPastRealityCount() {
+        return pastRealityCount;
     }
 
-    public BigDecimal getTotalScore() {
-        return totalScore;
+    public void setPastRealityCount(Integer pastRealityCount) {
+        this.pastRealityCount = pastRealityCount;
     }
 
-    public void setTotalScore(BigDecimal totalScore) {
-        this.totalScore = totalScore;
+    public Integer getPastAbsentCount() {
+        return pastAbsentCount;
     }
 
-    public BigDecimal getMinScore() {
-        return minScore;
+    public void setPastAbsentCount(Integer pastAbsentCount) {
+        this.pastAbsentCount = pastAbsentCount;
     }
 
-    public void setMinScore(BigDecimal minScore) {
-        this.minScore = minScore;
+    public Integer getPastTotalCount() {
+        return pastTotalCount;
     }
 
-    public BigDecimal getMaxScore() {
-        return maxScore;
+    public void setPastTotalCount(Integer pastTotalCount) {
+        this.pastTotalCount = pastTotalCount;
     }
 
-    public void setMaxScore(BigDecimal maxScore) {
-        this.maxScore = maxScore;
+    public BigDecimal getPastRealityRate() {
+        return pastRealityRate;
     }
 
-    public BigDecimal getAvgScore() {
-        return avgScore;
+    public void setPastRealityRate(BigDecimal pastRealityRate) {
+        this.pastRealityRate = pastRealityRate;
     }
 
-    public void setAvgScore(BigDecimal avgScore) {
-        this.avgScore = avgScore;
+    public BigDecimal getCurrentUpperQuartile() {
+        return currentUpperQuartile;
     }
 
-    public BigDecimal getScoreRate() {
-        return scoreRate;
+    public void setCurrentUpperQuartile(BigDecimal currentUpperQuartile) {
+        this.currentUpperQuartile = currentUpperQuartile;
     }
 
-    public void setScoreRate(BigDecimal scoreRate) {
-        this.scoreRate = scoreRate;
+    public BigDecimal getCurrentMedian() {
+        return currentMedian;
     }
 
-    public Integer getRealityCount() {
-        return realityCount;
+    public void setCurrentMedian(BigDecimal currentMedian) {
+        this.currentMedian = currentMedian;
     }
 
-    public void setRealityCount(Integer realityCount) {
-        this.realityCount = realityCount;
+    public BigDecimal getCurrentLowerQuartile() {
+        return currentLowerQuartile;
     }
 
-    public Integer getAbsentCount() {
-        return absentCount;
+    public void setCurrentLowerQuartile(BigDecimal currentLowerQuartile) {
+        this.currentLowerQuartile = currentLowerQuartile;
     }
 
-    public void setAbsentCount(Integer absentCount) {
-        this.absentCount = absentCount;
+    public String getCurrentMode() {
+        return currentMode;
     }
 
-    public Integer getTotalCount() {
-        return totalCount;
+    public void setCurrentMode(String currentMode) {
+        this.currentMode = currentMode;
     }
 
-    public void setTotalCount(Integer totalCount) {
-        this.totalCount = totalCount;
+    public BigDecimal getCurrentStandardDeviation() {
+        return currentStandardDeviation;
+    }
+
+    public void setCurrentStandardDeviation(BigDecimal currentStandardDeviation) {
+        this.currentStandardDeviation = currentStandardDeviation;
     }
 
     public String getDifficulty() {
@@ -399,43 +483,43 @@ public class TAExamCourse implements Serializable {
         this.difficulty = difficulty;
     }
 
-    public BigDecimal getUpperQuartile() {
-        return upperQuartile;
+    public BigDecimal getPaperAvgScore() {
+        return paperAvgScore;
     }
 
-    public void setUpperQuartile(BigDecimal upperQuartile) {
-        this.upperQuartile = upperQuartile;
+    public void setPaperAvgScore(BigDecimal paperAvgScore) {
+        this.paperAvgScore = paperAvgScore;
     }
 
-    public BigDecimal getMedian() {
-        return median;
+    public BigDecimal getPaperCurrentAvgScore() {
+        return paperCurrentAvgScore;
     }
 
-    public void setMedian(BigDecimal median) {
-        this.median = median;
+    public void setPaperCurrentAvgScore(BigDecimal paperCurrentAvgScore) {
+        this.paperCurrentAvgScore = paperCurrentAvgScore;
     }
 
-    public BigDecimal getLowerQuartile() {
-        return lowerQuartile;
+    public BigDecimal getPaperPassRate() {
+        return paperPassRate;
     }
 
-    public void setLowerQuartile(BigDecimal lowerQuartile) {
-        this.lowerQuartile = lowerQuartile;
+    public void setPaperPassRate(BigDecimal paperPassRate) {
+        this.paperPassRate = paperPassRate;
     }
 
-    public String getMode() {
-        return mode;
+    public BigDecimal getPaperCurrentPassRate() {
+        return paperCurrentPassRate;
     }
 
-    public void setMode(String mode) {
-        this.mode = mode;
+    public void setPaperCurrentPassRate(BigDecimal paperCurrentPassRate) {
+        this.paperCurrentPassRate = paperCurrentPassRate;
     }
 
-    public BigDecimal getStandardDeviation() {
-        return standardDeviation;
+    public BigDecimal getCoefficient() {
+        return coefficient;
     }
 
-    public void setStandardDeviation(BigDecimal standardDeviation) {
-        this.standardDeviation = standardDeviation;
+    public void setCoefficient(BigDecimal coefficient) {
+        this.coefficient = coefficient;
     }
 }

+ 18 - 6
teachcloud-report-business/src/main/java/com/qmth/teachcloud/report/business/entity/TAExamCourseCollegeInspectDio.java

@@ -48,8 +48,12 @@ public class TAExamCourseCollegeInspectDio implements Serializable {
 
     @ApiModelProperty(value = "学院id")
     @JsonSerialize(using = ToStringSerializer.class)
-    @TableField(value = "college_id")
-    private Long collegeId;
+    @TableField(value = "inspect_college_id")
+    private Long inspectCollegeId;
+
+    @ApiModelProperty(value = "学院名称")
+    @TableField(value = "inspect_college_name")
+    private String inspectCollegeName;
 
     @ApiModelProperty(value = "模块类型")
     @TableField(value = "dimension_type")
@@ -111,12 +115,20 @@ public class TAExamCourseCollegeInspectDio implements Serializable {
         this.examId = examId;
     }
 
-    public Long getCollegeId() {
-        return collegeId;
+    public Long getInspectCollegeId() {
+        return inspectCollegeId;
+    }
+
+    public void setInspectCollegeId(Long inspectCollegeId) {
+        this.inspectCollegeId = inspectCollegeId;
+    }
+
+    public String getInspectCollegeName() {
+        return inspectCollegeName;
     }
 
-    public void setCollegeId(Long collegeId) {
-        this.collegeId = collegeId;
+    public void setInspectCollegeName(String inspectCollegeName) {
+        this.inspectCollegeName = inspectCollegeName;
     }
 
     public String getDimensionType() {

+ 106 - 45
teachcloud-report-business/src/main/java/com/qmth/teachcloud/report/business/entity/TAExamCourseCollegeTeacher.java

@@ -28,16 +28,16 @@ public class TAExamCourseCollegeTeacher implements Serializable {
     @TableId(value = "id")
     private Long id;
 
-    @ApiModelProperty(value = "学校id(冗余)")
-    @JsonSerialize(using = ToStringSerializer.class)
-    @TableField(value = "school_id")
-    private Long schoolId;
-
     @ApiModelProperty(value = "考试id")
     @JsonSerialize(using = ToStringSerializer.class)
     @TableField(value = "exam_id")
     private Long examId;
 
+    @ApiModelProperty(value = "学校id(冗余)")
+    @JsonSerialize(using = ToStringSerializer.class)
+    @TableField(value = "school_id")
+    private Long schoolId;
+
     @ApiModelProperty(value = "科目编码")
     @TableField(value = "course_code")
     private String courseCode;
@@ -46,11 +46,6 @@ public class TAExamCourseCollegeTeacher implements Serializable {
     @TableField(value = "course_name")
     private String courseName;
 
-    @ApiModelProperty(value = "学院id")
-    @JsonSerialize(using = ToStringSerializer.class)
-    @TableField(value = "college_id")
-    private Long collegeId;
-
     @ApiModelProperty(value = "授课教师id")
     @JsonSerialize(using = ToStringSerializer.class)
     @TableField(value = "teacher_id")
@@ -60,13 +55,17 @@ public class TAExamCourseCollegeTeacher implements Serializable {
     @TableField(value = "teacher_name")
     private String teacherName;
 
-    @ApiModelProperty(value = "授课学生最低分")
-    @TableField(value = "min_score")
-    private BigDecimal minScore;
+    @ApiModelProperty(value = "授课学生最低分(赋分)")
+    @TableField(value = "min_score_assign")
+    private BigDecimal minScoreAssign;
 
-    @ApiModelProperty(value = "授课学生最高分")
-    @TableField(value = "max_score")
-    private BigDecimal maxScore;
+    @ApiModelProperty(value = "授课学生最高分(赋分)")
+    @TableField(value = "max_score_assign")
+    private BigDecimal maxScoreAssign;
+
+    @ApiModelProperty(value = "授课学生平均分(赋分)")
+    @TableField(value = "avg_score_assign")
+    private BigDecimal avgScoreAssign;
 
     @ApiModelProperty(value = "授课学生平均分")
     @TableField(value = "avg_score")
@@ -108,17 +107,31 @@ public class TAExamCourseCollegeTeacher implements Serializable {
     @TableField(value = "total_count")
     private Integer totalCount;
 
-    @ApiModelProperty(value = "学院名称(冗余)")
-    @TableField(value = "college_name")
-    private String collegeName;
+    @ApiModelProperty(value = "考察学院id")
+    @JsonSerialize(using = ToStringSerializer.class)
+    @TableField(value = "inspect_college_id")
+    private Long inspectCollegeId;
 
-    public Long getSchoolId() {
-        return schoolId;
-    }
+    @ApiModelProperty(value = "考察学院名称")
+    @TableField(value = "inspect_college_name")
+    private String inspectCollegeName;
 
-    public void setSchoolId(Long schoolId) {
-        this.schoolId = schoolId;
-    }
+    @ApiModelProperty(value = "开课学院id")
+    @JsonSerialize(using = ToStringSerializer.class)
+    @TableField(value = "teach_college_id")
+    private Long teachCollegeId;
+
+    @ApiModelProperty(value = "开课学院名称")
+    @TableField(value = "teach_college_name")
+    private String teachCollegeName;
+
+    @ApiModelProperty(value = "在考察学院排名")
+    @TableField(value = "teacher_rank")
+    private Integer teacherRank;
+
+    @ApiModelProperty(value = "在考察学院教师总人数")
+    @TableField(value = "teacher_count")
+    private Integer teacherCount;
 
     public static long getSerialVersionUID() {
         return serialVersionUID;
@@ -156,14 +169,6 @@ public class TAExamCourseCollegeTeacher implements Serializable {
         this.courseName = courseName;
     }
 
-    public Long getCollegeId() {
-        return collegeId;
-    }
-
-    public void setCollegeId(Long collegeId) {
-        this.collegeId = collegeId;
-    }
-
     public Long getTeacherId() {
         return teacherId;
     }
@@ -180,20 +185,28 @@ public class TAExamCourseCollegeTeacher implements Serializable {
         this.teacherName = teacherName;
     }
 
-    public BigDecimal getMinScore() {
-        return minScore;
+    public BigDecimal getMinScoreAssign() {
+        return minScoreAssign;
+    }
+
+    public void setMinScoreAssign(BigDecimal minScoreAssign) {
+        this.minScoreAssign = minScoreAssign;
     }
 
-    public void setMinScore(BigDecimal minScore) {
-        this.minScore = minScore;
+    public BigDecimal getMaxScoreAssign() {
+        return maxScoreAssign;
     }
 
-    public BigDecimal getMaxScore() {
-        return maxScore;
+    public void setMaxScoreAssign(BigDecimal maxScoreAssign) {
+        this.maxScoreAssign = maxScoreAssign;
     }
 
-    public void setMaxScore(BigDecimal maxScore) {
-        this.maxScore = maxScore;
+    public BigDecimal getAvgScoreAssign() {
+        return avgScoreAssign;
+    }
+
+    public void setAvgScoreAssign(BigDecimal avgScoreAssign) {
+        this.avgScoreAssign = avgScoreAssign;
     }
 
     public BigDecimal getAvgScore() {
@@ -276,11 +289,59 @@ public class TAExamCourseCollegeTeacher implements Serializable {
         this.totalCount = totalCount;
     }
 
-    public String getCollegeName() {
-        return collegeName;
+    public Long getInspectCollegeId() {
+        return inspectCollegeId;
+    }
+
+    public void setInspectCollegeId(Long inspectCollegeId) {
+        this.inspectCollegeId = inspectCollegeId;
+    }
+
+    public String getInspectCollegeName() {
+        return inspectCollegeName;
+    }
+
+    public void setInspectCollegeName(String inspectCollegeName) {
+        this.inspectCollegeName = inspectCollegeName;
+    }
+
+    public Long getTeachCollegeId() {
+        return teachCollegeId;
+    }
+
+    public void setTeachCollegeId(Long teachCollegeId) {
+        this.teachCollegeId = teachCollegeId;
+    }
+
+    public String getTeachCollegeName() {
+        return teachCollegeName;
+    }
+
+    public void setTeachCollegeName(String teachCollegeName) {
+        this.teachCollegeName = teachCollegeName;
+    }
+
+    public Integer getTeacherRank() {
+        return teacherRank;
+    }
+
+    public void setTeacherRank(Integer teacherRank) {
+        this.teacherRank = teacherRank;
+    }
+
+    public Integer getTeacherCount() {
+        return teacherCount;
     }
 
-    public void setCollegeName(String collegeName) {
-        this.collegeName = collegeName;
+    public void setTeacherCount(Integer teacherCount) {
+        this.teacherCount = teacherCount;
+    }
+
+    public Long getSchoolId() {
+        return schoolId;
+    }
+
+    public void setSchoolId(Long schoolId) {
+        this.schoolId = schoolId;
     }
 }

+ 6 - 6
teachcloud-report-business/src/main/java/com/qmth/teachcloud/report/business/entity/TAExamCourseRecord.java

@@ -119,8 +119,8 @@ public class TAExamCourseRecord implements Serializable {
     private Boolean absent;
 
     @ApiModelProperty(value = "是否应届")
-    @TableField(value = "current")
-    private Boolean current;
+    @TableField(value = "student_current")
+    private Boolean studentCurrent;
 
     public static long getSerialVersionUID() {
         return serialVersionUID;
@@ -302,12 +302,12 @@ public class TAExamCourseRecord implements Serializable {
         this.absent = absent;
     }
 
-    public Boolean getCurrent() {
-        return current;
+    public Boolean getStudentCurrent() {
+        return studentCurrent;
     }
 
-    public void setCurrent(Boolean current) {
-        this.current = current;
+    public void setStudentCurrent(Boolean studentCurrent) {
+        this.studentCurrent = studentCurrent;
     }
 
     public Long getSchoolId() {

+ 65 - 40
teachcloud-report-business/src/main/java/com/qmth/teachcloud/report/business/entity/TAExamCourseRecordDio.java

@@ -28,16 +28,16 @@ public class TAExamCourseRecordDio implements Serializable {
     @TableId(value = "id")
     private Long id;
 
-    @ApiModelProperty(value = "学校id(冗余)")
-    @JsonSerialize(using = ToStringSerializer.class)
-    @TableField(value = "school_id")
-    private Long schoolId;
-
     @ApiModelProperty(value = "基础考生成绩记录表id")
     @JsonSerialize(using = ToStringSerializer.class)
     @TableField(value = "exam_record_id")
     private Long examRecordId;
 
+    @ApiModelProperty(value = "学校id(冗余)")
+    @JsonSerialize(using = ToStringSerializer.class)
+    @TableField(value = "school_id")
+    private Long schoolId;
+
     @ApiModelProperty(value = "试卷id")
     @JsonSerialize(using = ToStringSerializer.class)
     @TableField(value = "paper_id")
@@ -48,18 +48,18 @@ public class TAExamCourseRecordDio implements Serializable {
     @TableField(value = "exam_id")
     private Long examId;
 
+    @ApiModelProperty(value = "模块类型")
+    @TableField(value = "dimension_type")
+    private String dimensionType;
+
     @ApiModelProperty(value = "课程编号")
     @TableField(value = "course_code")
     private String courseCode;
 
-    @ApiModelProperty(value = "科目名称")
+    @ApiModelProperty(value = "课程名称")
     @TableField(value = "course_name")
     private String courseName;
 
-    @ApiModelProperty(value = "模块类型")
-    @TableField(value = "dimension_type")
-    private String dimensionType;
-
     @ApiModelProperty(value = "维度编号")
     @TableField(value = "dimension_code")
     private String dimensionCode;
@@ -76,13 +76,14 @@ public class TAExamCourseRecordDio implements Serializable {
     @TableField(value = "proficiency")
     private String proficiency;
 
-    public Long getSchoolId() {
-        return schoolId;
-    }
+    @ApiModelProperty(value = "所属考察学院id")
+    @JsonSerialize(using = ToStringSerializer.class)
+    @TableField(value = "inspect_college_id")
+    private Long inspectCollegeId;
 
-    public void setSchoolId(Long schoolId) {
-        this.schoolId = schoolId;
-    }
+    @ApiModelProperty(value = "所属考察学院名称")
+    @TableField(value = "inspect_college_name")
+    private String inspectCollegeName;
 
     public static long getSerialVersionUID() {
         return serialVersionUID;
@@ -112,30 +113,6 @@ public class TAExamCourseRecordDio implements Serializable {
         this.paperId = paperId;
     }
 
-    public Long getExamId() {
-        return examId;
-    }
-
-    public void setExamId(Long examId) {
-        this.examId = examId;
-    }
-
-    public String getCourseCode() {
-        return courseCode;
-    }
-
-    public void setCourseCode(String courseCode) {
-        this.courseCode = courseCode;
-    }
-
-    public String getCourseName() {
-        return courseName;
-    }
-
-    public void setCourseName(String courseName) {
-        this.courseName = courseName;
-    }
-
     public String getDimensionType() {
         return dimensionType;
     }
@@ -175,4 +152,52 @@ public class TAExamCourseRecordDio implements Serializable {
     public void setProficiency(String proficiency) {
         this.proficiency = proficiency;
     }
+
+    public Long getExamId() {
+        return examId;
+    }
+
+    public void setExamId(Long examId) {
+        this.examId = examId;
+    }
+
+    public String getCourseCode() {
+        return courseCode;
+    }
+
+    public void setCourseCode(String courseCode) {
+        this.courseCode = courseCode;
+    }
+
+    public String getCourseName() {
+        return courseName;
+    }
+
+    public void setCourseName(String courseName) {
+        this.courseName = courseName;
+    }
+
+    public Long getInspectCollegeId() {
+        return inspectCollegeId;
+    }
+
+    public void setInspectCollegeId(Long inspectCollegeId) {
+        this.inspectCollegeId = inspectCollegeId;
+    }
+
+    public String getInspectCollegeName() {
+        return inspectCollegeName;
+    }
+
+    public void setInspectCollegeName(String inspectCollegeName) {
+        this.inspectCollegeName = inspectCollegeName;
+    }
+
+    public Long getSchoolId() {
+        return schoolId;
+    }
+
+    public void setSchoolId(Long schoolId) {
+        this.schoolId = schoolId;
+    }
 }

+ 45 - 20
teachcloud-report-business/src/main/java/com/qmth/teachcloud/report/business/entity/TAExamCourseRecordMod.java

@@ -48,18 +48,18 @@ public class TAExamCourseRecordMod implements Serializable {
     @TableField(value = "exam_id")
     private Long examId;
 
-    @ApiModelProperty(value = "考号")
-    @TableField(value = "student_code")
-    private String studentCode;
-
     @ApiModelProperty(value = "课程编号")
     @TableField(value = "course_code")
     private String courseCode;
 
-    @ApiModelProperty(value = "科目名称")
+    @ApiModelProperty(value = "课程名称")
     @TableField(value = "course_name")
     private String courseName;
 
+    @ApiModelProperty(value = "考号")
+    @TableField(value = "student_code")
+    private String studentCode;
+
     @ApiModelProperty(value = "考察模块名称")
     @TableField(value = "module_type")
     private String moduleType;
@@ -85,20 +85,21 @@ public class TAExamCourseRecordMod implements Serializable {
     private Integer colRank;
 
     @ApiModelProperty(value = "百分等级数")
-    @TableField(value = "percentGrade")
+    @TableField(value = "percent_grade")
     private Integer percentGrade;
 
     @ApiModelProperty(value = "等级(不确定百分等级、排名等级、得分率等级)")
     @TableField(value = "level")
     private String level;
 
-    public Long getSchoolId() {
-        return schoolId;
-    }
+    @ApiModelProperty(value = "考生所属考察学院id")
+    @JsonSerialize(using = ToStringSerializer.class)
+    @TableField(value = "inspect_college_id")
+    private Long inspectCollegeId;
 
-    public void setSchoolId(Long schoolId) {
-        this.schoolId = schoolId;
-    }
+    @ApiModelProperty(value = "考生所属考察学院名称")
+    @TableField(value = "inspect_college_name")
+    private String inspectCollegeName;
 
     public static long getSerialVersionUID() {
         return serialVersionUID;
@@ -200,14 +201,6 @@ public class TAExamCourseRecordMod implements Serializable {
         this.examId = examId;
     }
 
-    public String getStudentCode() {
-        return studentCode;
-    }
-
-    public void setStudentCode(String studentCode) {
-        this.studentCode = studentCode;
-    }
-
     public String getCourseCode() {
         return courseCode;
     }
@@ -223,4 +216,36 @@ public class TAExamCourseRecordMod implements Serializable {
     public void setCourseName(String courseName) {
         this.courseName = courseName;
     }
+
+    public Long getInspectCollegeId() {
+        return inspectCollegeId;
+    }
+
+    public void setInspectCollegeId(Long inspectCollegeId) {
+        this.inspectCollegeId = inspectCollegeId;
+    }
+
+    public String getInspectCollegeName() {
+        return inspectCollegeName;
+    }
+
+    public void setInspectCollegeName(String inspectCollegeName) {
+        this.inspectCollegeName = inspectCollegeName;
+    }
+
+    public Long getSchoolId() {
+        return schoolId;
+    }
+
+    public void setSchoolId(Long schoolId) {
+        this.schoolId = schoolId;
+    }
+
+    public String getStudentCode() {
+        return studentCode;
+    }
+
+    public void setStudentCode(String studentCode) {
+        this.studentCode = studentCode;
+    }
 }

+ 59 - 23
teachcloud-report-business/src/main/java/com/qmth/teachcloud/report/business/entity/TAExamTotal.java

@@ -27,23 +27,23 @@ public class TAExamTotal implements Serializable {
     @TableId(value = "id")
     private Long id;
 
-    @ApiModelProperty(value = "学校id(冗余)")
-    @JsonSerialize(using = ToStringSerializer.class)
-    @TableField(value = "school_id")
-    private Long schoolId;
-
     @ApiModelProperty(value = "基础考试表id")
     @JsonSerialize(using = ToStringSerializer.class)
     @TableField(value = "exam_id")
     private Long examId;
 
+    @ApiModelProperty(value = "学校id(冗余)")
+    @JsonSerialize(using = ToStringSerializer.class)
+    @TableField(value = "school_id")
+    private Long schoolId;
+
     @ApiModelProperty(value = "考察学院总数")
     @TableField(value = "college_count")
     private Integer collegeCount;
 
-    @ApiModelProperty(value = "考察学院")
+    @ApiModelProperty(value = "考察学院名称")
     @TableField(value = "college_names")
-    private Integer collegeNames;
+    private String collegeNames;
 
     @ApiModelProperty(value = "课程总数")
     @TableField(value = "course_count")
@@ -69,18 +69,22 @@ public class TAExamTotal implements Serializable {
     @TableField(value = "absent_count")
     private Integer absentCount;
 
+    @ApiModelProperty(value = "总课次")
+    @TableField(value = "total_course_times")
+    private int totalCourseTimes;
+
+    @ApiModelProperty(value = "实际课次")
+    @TableField(value = "reality_course_times")
+    private int realityCourseTimes;
+
+    @ApiModelProperty(value = "缺考课次")
+    @TableField(value = "absent_course_times")
+    private int absentCourseTimes;
+
     @ApiModelProperty(value = "考试时间")
     @TableField(value = "exam_time")
     private String examTime;
 
-    public Long getSchoolId() {
-        return schoolId;
-    }
-
-    public void setSchoolId(Long schoolId) {
-        this.schoolId = schoolId;
-    }
-
     public static long getSerialVersionUID() {
         return serialVersionUID;
     }
@@ -109,14 +113,6 @@ public class TAExamTotal implements Serializable {
         this.collegeCount = collegeCount;
     }
 
-    public Integer getCollegeNames() {
-        return collegeNames;
-    }
-
-    public void setCollegeNames(Integer collegeNames) {
-        this.collegeNames = collegeNames;
-    }
-
     public Integer getCourseCount() {
         return courseCount;
     }
@@ -172,4 +168,44 @@ public class TAExamTotal implements Serializable {
     public void setExamTime(String examTime) {
         this.examTime = examTime;
     }
+
+    public int getTotalCourseTimes() {
+        return totalCourseTimes;
+    }
+
+    public void setTotalCourseTimes(int totalCourseTimes) {
+        this.totalCourseTimes = totalCourseTimes;
+    }
+
+    public int getRealityCourseTimes() {
+        return realityCourseTimes;
+    }
+
+    public void setRealityCourseTimes(int realityCourseTimes) {
+        this.realityCourseTimes = realityCourseTimes;
+    }
+
+    public int getAbsentCourseTimes() {
+        return absentCourseTimes;
+    }
+
+    public void setAbsentCourseTimes(int absentCourseTimes) {
+        this.absentCourseTimes = absentCourseTimes;
+    }
+
+    public String getCollegeNames() {
+        return collegeNames;
+    }
+
+    public void setCollegeNames(String collegeNames) {
+        this.collegeNames = collegeNames;
+    }
+
+    public Long getSchoolId() {
+        return schoolId;
+    }
+
+    public void setSchoolId(Long schoolId) {
+        this.schoolId = schoolId;
+    }
 }

+ 49 - 12
teachcloud-report-business/src/main/java/com/qmth/teachcloud/report/business/entity/TAPaperStruct.java

@@ -28,15 +28,28 @@ public class TAPaperStruct implements Serializable {
     @TableId(value = "id")
     private Long id;
 
+    @ApiModelProperty(value = "基础试卷结构表id")
+    @JsonSerialize(using = ToStringSerializer.class)
+    @TableField(value = "paper_struct_id")
+    private Long paperStructId;
+
+    @ApiModelProperty(value = "考试id")
+    @JsonSerialize(using = ToStringSerializer.class)
+    @TableField(value = "exam_id")
+    private Long examId;
+
     @ApiModelProperty(value = "学校id(冗余)")
     @JsonSerialize(using = ToStringSerializer.class)
     @TableField(value = "school_id")
     private Long schoolId;
 
-    @ApiModelProperty(value = "基础试卷结构表id")
-    @JsonSerialize(using = ToStringSerializer.class)
-    @TableField(value = "paper_struct_id")
-    private Long paperStructId;
+    @ApiModelProperty(value = "课程编号")
+    @TableField(value = "course_code")
+    private String courseCode;
+
+    @ApiModelProperty(value = "课程名称")
+    @TableField(value = "course_name")
+    private String courseName;
 
     @ApiModelProperty(value = "得分率")
     @TableField(value = "score_rate")
@@ -50,14 +63,6 @@ public class TAPaperStruct implements Serializable {
     @TableField(value = "validity")
     private BigDecimal validity;
 
-    public Long getSchoolId() {
-        return schoolId;
-    }
-
-    public void setSchoolId(Long schoolId) {
-        this.schoolId = schoolId;
-    }
-
     public static long getSerialVersionUID() {
         return serialVersionUID;
     }
@@ -101,4 +106,36 @@ public class TAPaperStruct implements Serializable {
     public void setValidity(BigDecimal validity) {
         this.validity = validity;
     }
+
+    public Long getExamId() {
+        return examId;
+    }
+
+    public void setExamId(Long examId) {
+        this.examId = examId;
+    }
+
+    public String getCourseCode() {
+        return courseCode;
+    }
+
+    public void setCourseCode(String courseCode) {
+        this.courseCode = courseCode;
+    }
+
+    public String getCourseName() {
+        return courseName;
+    }
+
+    public void setCourseName(String courseName) {
+        this.courseName = courseName;
+    }
+
+    public Long getSchoolId() {
+        return schoolId;
+    }
+
+    public void setSchoolId(Long schoolId) {
+        this.schoolId = schoolId;
+    }
 }

+ 6 - 6
teachcloud-report-business/src/main/java/com/qmth/teachcloud/report/business/entity/TBExamStudent.java

@@ -91,8 +91,8 @@ public class TBExamStudent implements Serializable {
     private Boolean absent;
 
     @ApiModelProperty(value = "是否本届,false:非本届,true:本届")
-    @TableField(value = "current")
-    private Boolean current;
+    @TableField(value = "student_current")
+    private Boolean studentCurrent;
 
     public Long getSchoolId() {
         return schoolId;
@@ -218,11 +218,11 @@ public class TBExamStudent implements Serializable {
         this.absent = absent;
     }
 
-    public Boolean getCurrent() {
-        return current;
+    public Boolean getStudentCurrent() {
+        return studentCurrent;
     }
 
-    public void setCurrent(Boolean current) {
-        this.current = current;
+    public void setStudentCurrent(Boolean studentCurrent) {
+        this.studentCurrent = studentCurrent;
     }
 }

+ 29 - 0
teachcloud-report-business/src/main/java/com/qmth/teachcloud/report/business/enums/LevelRuleEnum.java

@@ -0,0 +1,29 @@
+package com.qmth.teachcloud.report.business.enums;
+
+public enum LevelRuleEnum {
+    PERCENT_GRADE("百分等级","percentGrade","按照学院百分等级排"),
+    SCORE_RATE("得分率","scoreRate","按照得分率排"),
+    COLLEGE_RANK("排名","colRank","按照在学院排名排")
+    ;
+    LevelRuleEnum(String value, String attribute, String desc){
+        this.value = value;
+        this.attribute = attribute;
+        this.desc = desc;
+    }
+
+    private final String value;
+    private final String attribute;
+    private final String desc;
+
+    public String getValue() {
+        return value;
+    }
+
+    public String getAttribute() {
+        return attribute;
+    }
+
+    public String getDesc() {
+        return desc;
+    }
+}

+ 23 - 0
teachcloud-report-business/src/main/java/com/qmth/teachcloud/report/business/enums/QuantileEnum.java

@@ -0,0 +1,23 @@
+package com.qmth.teachcloud.report.business.enums;
+
+
+public enum QuantileEnum {
+    UPPER_QUARTILE(0.25,"上四分位数"),
+    MEDIAN(0.5,"中位数"),
+    LOWER_QUARTILE(0.75,"下四分位数"),
+    ;
+    QuantileEnum(double value, String desc) {
+        this.value = value;
+        this.desc = desc;
+    }
+    private final double value;
+    private final String desc;
+
+    public double getValue() {
+        return value;
+    }
+
+    public String getDesc() {
+        return desc;
+    }
+}

+ 29 - 0
teachcloud-report-business/src/main/java/com/qmth/teachcloud/report/business/enums/ValidityEnum.java

@@ -0,0 +1,29 @@
+package com.qmth.teachcloud.report.business.enums;
+
+
+public enum ValidityEnum {
+    VALIDITY_FOR_PERCENT_GRADE(73,27,"百分等级大于等于73的学生和后百分等级小于等于27的学生作为效度参考标准"),
+    VALIDITY_FOR_RANK(0.27,0.73,"排名在前27/100的学生和排名在后27/100成绩作为效度参考标准"),
+    ;
+    private final double topLimitPercent;
+    private final double lowLimitPercent;
+    private final String desc;
+
+    public double getTopLimitPercent() {
+        return topLimitPercent;
+    }
+
+    public double getLowLimitPercent() {
+        return lowLimitPercent;
+    }
+
+    public String getDesc() {
+        return desc;
+    }
+
+    ValidityEnum(double topLimitPercent, double lowLimitPercent, String desc) {
+        this.topLimitPercent = topLimitPercent;
+        this.lowLimitPercent = lowLimitPercent;
+        this.desc = desc;
+    }
+}

+ 10 - 1
teachcloud-report-business/src/main/java/com/qmth/teachcloud/report/business/mapper/TAExamCourseCollegeInspectDioMapper.java

@@ -2,6 +2,9 @@ package com.qmth.teachcloud.report.business.mapper;
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.qmth.teachcloud.report.business.entity.TAExamCourseCollegeInspectDio;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
 
 /**
  * <p>
@@ -12,5 +15,11 @@ import com.qmth.teachcloud.report.business.entity.TAExamCourseCollegeInspectDio;
  * @since 2021-06-01
  */
 public interface TAExamCourseCollegeInspectDioMapper extends BaseMapper<TAExamCourseCollegeInspectDio> {
-
+    /**
+     * 根据考试编号和课程编号和‘t_a_exam_course_record_dio’表向‘t_a_exam_course_college_inspect_dio’表插入数据
+     * @param examId 考试id
+     * @param courseCode 课程编号
+     * @return 从资源表查出的结果集
+     */
+    List<TAExamCourseCollegeInspectDio> findByTAExamCourseRecordDio(@Param("examId") Long examId, @Param("courseCode") String courseCode);
 }

+ 12 - 0
teachcloud-report-business/src/main/java/com/qmth/teachcloud/report/business/mapper/TAExamCourseCollegeInspectMapper.java

@@ -1,7 +1,11 @@
 package com.qmth.teachcloud.report.business.mapper;
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.qmth.teachcloud.report.business.bean.result.TAExamCourseCollegeInspectResult;
 import com.qmth.teachcloud.report.business.entity.TAExamCourseCollegeInspect;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
 
 /**
  * <p>
@@ -13,4 +17,12 @@ import com.qmth.teachcloud.report.business.entity.TAExamCourseCollegeInspect;
  */
 public interface TAExamCourseCollegeInspectMapper extends BaseMapper<TAExamCourseCollegeInspect> {
 
+    /**
+     * 查找科目维度
+     *
+     * @param examId
+     * @param courseCode
+     * @return
+     */
+    List<TAExamCourseCollegeInspectResult> findCourseDescriptiveStatisticsForCollege(@Param("examId") Long examId, @Param("courseCode") String courseCode);
 }

+ 13 - 0
teachcloud-report-business/src/main/java/com/qmth/teachcloud/report/business/mapper/TAExamCourseCollegeTeacherMapper.java

@@ -3,11 +3,14 @@ package com.qmth.teachcloud.report.business.mapper;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.qmth.teachcloud.report.business.bean.result.TAExamCourseTeacherResult;
 import com.qmth.teachcloud.report.business.bean.result.TeacherClassRankResult;
 import com.qmth.teachcloud.report.business.bean.result.TeacherMyClassRankResult;
 import com.qmth.teachcloud.report.business.entity.TAExamCourseCollegeTeacher;
 import org.apache.ibatis.annotations.Param;
 
+import java.util.List;
+
 /**
  * <p>
  * 参考课程学院下授课教师维度分析表 Mapper 接口
@@ -23,4 +26,14 @@ public interface TAExamCourseCollegeTeacherMapper extends BaseMapper<TAExamCours
     IPage<TeacherMyClassRankResult> listMyClassRank(@Param("page") Page<TeacherMyClassRankResult> page, @Param("schoolId") Long schoolId, @Param("semester") String semester, @Param("examId") Long examId, @Param("teacherId") Long teacherId, @Param("courseCode") String courseCode, @Param("inspectCollegeId") Long inspectCollegeId);
 
     IPage<TAExamCourseCollegeTeacher> listAllTeacherClassRank(@Param("page") Page<TAExamCourseCollegeTeacher> page, @Param("schoolId") Long schoolId, @Param("semester") String semester, @Param("examId") Long examId, @Param("teachCollegeId") Long teachCollegeId, @Param("courseCode") String courseCode, @Param("teacherId") Long teacherId);
+
+    /**
+     * 查询老师得分
+     *
+     * @param examId
+     * @param courseCode
+     * @param collegeId
+     * @return
+     */
+    List<TAExamCourseTeacherResult> findTeacherInfo(@Param("examId") Long examId, @Param("courseCode") String courseCode, @Param("collegeId") Long collegeId);
 }

+ 31 - 0
teachcloud-report-business/src/main/java/com/qmth/teachcloud/report/business/mapper/TBAnswerMapper.java

@@ -1,7 +1,13 @@
 package com.qmth.teachcloud.report.business.mapper;
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.qmth.teachcloud.report.business.bean.dto.query.BasicAnswerDto;
+import com.qmth.teachcloud.report.business.bean.dto.query.ValidAnswerDetailDto;
+import com.qmth.teachcloud.report.business.bean.result.TBAnswerResult;
 import com.qmth.teachcloud.report.business.entity.TBAnswer;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
 
 /**
  * <p>
@@ -13,4 +19,29 @@ import com.qmth.teachcloud.report.business.entity.TBAnswer;
  */
 public interface TBAnswerMapper extends BaseMapper<TBAnswer> {
 
+    /**
+     * 根据试卷id查找考该试卷的所有考生作答记录详情
+     *
+     * @param paperId 试卷id
+     * @return 作答记录数据
+     */
+    List<BasicAnswerDto> findByPaperId(@Param("paperId") Long paperId);
+
+    /**
+     * 查找试卷结构效度数据
+     *
+     * @param examId     考试id
+     * @param courseCode 课程编号
+     * @return 结果
+     */
+    List<ValidAnswerDetailDto> findValid(@Param("examId") Long examId, @Param("courseCode") String courseCode);
+
+    /**
+     * 查找有效答案
+     *
+     * @param examId
+     * @param courseCode
+     * @return
+     */
+    List<TBAnswerResult> findValidAnswerDetail(@Param("examId") Long examId, @Param("courseCode") String courseCode);
 }

+ 13 - 0
teachcloud-report-business/src/main/java/com/qmth/teachcloud/report/business/mapper/TBDimensionMapper.java

@@ -1,7 +1,11 @@
 package com.qmth.teachcloud.report.business.mapper;
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.qmth.teachcloud.report.business.bean.result.CourseDimensionResult;
 import com.qmth.teachcloud.report.business.entity.TBDimension;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
 
 /**
  * <p>
@@ -13,4 +17,13 @@ import com.qmth.teachcloud.report.business.entity.TBDimension;
  */
 public interface TBDimensionMapper extends BaseMapper<TBDimension> {
 
+    /**
+     * 查找维度信息
+     *
+     * @param examId
+     * @param courseCode
+     * @param collegeId
+     * @return
+     */
+    List<CourseDimensionResult> findDimensionInfo(@Param("examId") Long examId, @Param("courseCode") String courseCode, @Param("collegeId") Long collegeId);
 }

+ 10 - 1
teachcloud-report-business/src/main/java/com/qmth/teachcloud/report/business/mapper/TBModuleConfigMapper.java

@@ -2,6 +2,9 @@ package com.qmth.teachcloud.report.business.mapper;
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.qmth.teachcloud.report.business.entity.TBModuleConfig;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
 
 /**
  * <p>
@@ -12,5 +15,11 @@ import com.qmth.teachcloud.report.business.entity.TBModuleConfig;
  * @since 2021-06-01
  */
 public interface TBModuleConfigMapper extends BaseMapper<TBModuleConfig> {
-
+    /**
+     * 根据考试id和课程编号查询不重复的模块信息
+     * @param examId 考试id
+     * @param courseCode 课程编号
+     * @return 模块信息
+     */
+    List<TBModuleConfig> findDistinctModuleInfoByExamIdAndCourseCode(@Param("examId") Long examId, @Param("courseCode") String courseCode);
 }

+ 12 - 0
teachcloud-report-business/src/main/java/com/qmth/teachcloud/report/business/mapper/TBPaperStructMapper.java

@@ -1,7 +1,11 @@
 package com.qmth.teachcloud.report.business.mapper;
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.qmth.teachcloud.report.business.bean.result.TBPaperStructResult;
 import com.qmth.teachcloud.report.business.entity.TBPaperStruct;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
 
 /**
  * <p>
@@ -13,4 +17,12 @@ import com.qmth.teachcloud.report.business.entity.TBPaperStruct;
  */
 public interface TBPaperStructMapper extends BaseMapper<TBPaperStruct> {
 
+    /**
+     * 查找试卷结构
+     *
+     * @param examId
+     * @param courseCode
+     * @return
+     */
+    List<TBPaperStructResult> findQuestionInfo(@Param("examId") Long examId, @Param("courseCode") String courseCode);
 }

+ 105 - 0
teachcloud-report-business/src/main/java/com/qmth/teachcloud/report/business/service/AnalyzeForStudentService.java

@@ -0,0 +1,105 @@
+package com.qmth.teachcloud.report.business.service;
+
+/**
+ * @Description: 对个人看板的分析
+ * @Author: CaoZixuan
+ * @Date: 2021-06-06
+ */
+public interface AnalyzeForStudentService {
+
+    /**
+     * 构建考试课程分析表 't_a_exam_course'
+     * @param examId 考试id
+     * @param courseCode 课程编号
+     * @return 结果
+     */
+    String buildAnalyzeExamCourse(Long examId,String courseCode);
+    /**
+     * 构建考试记录分析表数据 't_a_exam_course_record'
+     * @param examId 考试id
+     * @param courseCode 课程编号
+     * @return 结果
+     */
+    String buildAnalyzeExamCourseRecord(Long examId,String courseCode);
+
+    /**
+     * 构建以考试课程-考察学院维度的分析表 't_a_exam_course_college_inspect'
+     * @param examId 考试id
+     * @param courseCode 课程编号
+     * @return 结果
+     */
+    String buildAnalyzeExamCourseCollegeInspect(Long examId,String courseCode);
+
+    // TODO: 2021/6/7 专业
+
+    /**
+     * 构建考试课程-班级维度的分析表 ’t_a_exam_course_clazz‘
+     * @param examId 考试id
+     * @param courseCode 课程编号
+     * @return 结果
+     */
+    String buildAnalyzeExamCourseClazz(Long examId,String courseCode);
+
+    /**
+     * 分析计算某科目考试的所有考察点得分率并将计算结果插入't_a_exam_course_dio'和't_a_exam_course_record_dio'和‘t_a_exam_course_record_mod’表中
+     * <p>计算公式
+     * 个人得分率 = 该学生在该考察点的得分/该考察点在此次考试所占分数
+     * 平均得分率 = 参考学生在该考察点的得分平均值/该考察点在此次考试所占分数
+     * </p>
+     *
+     * <p>计算过程
+     * 1.获取该科目考试所有参考学生的数据源
+     * 2.获取该科目考试的试卷结构的数据信息
+     * 3.获取该科目考试所有考察点的数据源
+     * 4.获取该科目考试考生每题答题记录详情数据源
+     *
+     * 5.计算每个考察点所对应的题目集合
+     * 6.计算每个考察点在此次考试所占分数
+     * 7.计算每个考生各个知识点得分率并更新't_a_exam_course_record_dio'表
+     * 8.计算此次考试各个考察点得分率并插入't_a_exam_course_dio'表
+     * </p>
+     * @param examId 考试id
+     * @param courseCode 课程编号
+     * @return 结果
+     */
+    String AnalyzePointScoreRate(Long examId,String courseCode) throws Exception;
+
+    /**
+     * 构建考试课程考察学院维度分析表
+     * @param examId 考试id
+     * @param courseCode 课程编号
+     * @return 结果
+     */
+    String buildAnalyzeExamCourseCollegeInspectDio(Long examId,String courseCode);
+
+    /**
+     * 构建分析试卷结构表 't_a_paper_struct'表
+     * @param examId 考试id
+     * @param courseCode 课程编号
+     * @return 结果
+     */
+    String buildAnalyzePaperStruct(Long examId,String courseCode);
+
+    /**
+     * 构建表 ‘t_a_exam_total’
+     * @param examId 考试id
+     * @return 结果
+     */
+    String buildAnalyzeExamTotal(Long examId);
+
+    /**
+     * 构建表 't_a_exam_course_college_teacher'
+     * @param examId 考试id
+     * @param courseCode 课程编号
+     * @return 结果
+     */
+    String buildAnalyzeExamCourseCollegeTeacher(Long examId,String courseCode);
+
+    /**
+     * 构建表 't_a_exam_course_teacher'
+     * @param examId 考试id
+     * @param courseCode 课程编号
+     * @return 结果
+     */
+    String buildAnalyzeExamCourseTeacher(Long examId,String courseCode);
+}

+ 6 - 1
teachcloud-report-business/src/main/java/com/qmth/teachcloud/report/business/service/TAExamCourseCollegeInspectDioService.java

@@ -12,5 +12,10 @@ import com.qmth.teachcloud.report.business.entity.TAExamCourseCollegeInspectDio;
  * @since 2021-06-01
  */
 public interface TAExamCourseCollegeInspectDioService extends IService<TAExamCourseCollegeInspectDio> {
-
+    /**
+     * 根据考试编号和课程编号和‘t_a_exam_course_record_dio’表向‘t_a_exam_course_college_inspect_dio’表插入数据
+     * @param examId 考试id
+     * @param courseCode 课程编号
+     */
+    void insertByTAExamCourseRecordDio(Long examId,String courseCode);
 }

+ 11 - 0
teachcloud-report-business/src/main/java/com/qmth/teachcloud/report/business/service/TAExamCourseCollegeInspectService.java

@@ -1,8 +1,11 @@
 package com.qmth.teachcloud.report.business.service;
 
 import com.baomidou.mybatisplus.extension.service.IService;
+import com.qmth.teachcloud.report.business.bean.result.TAExamCourseCollegeInspectResult;
 import com.qmth.teachcloud.report.business.entity.TAExamCourseCollegeInspect;
 
+import java.util.List;
+
 /**
  * <p>
  * 参考课程考察学院维度分析表 服务类
@@ -13,4 +16,12 @@ import com.qmth.teachcloud.report.business.entity.TAExamCourseCollegeInspect;
  */
 public interface TAExamCourseCollegeInspectService extends IService<TAExamCourseCollegeInspect> {
 
+    /**
+     * 查找科目维度
+     *
+     * @param examId
+     * @param courseCode
+     * @return
+     */
+    List<TAExamCourseCollegeInspectResult> findCourseDescriptiveStatisticsForCollege(Long examId, String courseCode);
 }

+ 13 - 0
teachcloud-report-business/src/main/java/com/qmth/teachcloud/report/business/service/TAExamCourseCollegeTeacherService.java

@@ -2,10 +2,13 @@ package com.qmth.teachcloud.report.business.service;
 
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.service.IService;
+import com.qmth.teachcloud.report.business.bean.result.TAExamCourseTeacherResult;
 import com.qmth.teachcloud.report.business.bean.result.TeacherClassRankResult;
 import com.qmth.teachcloud.report.business.bean.result.TeacherMyClassRankResult;
 import com.qmth.teachcloud.report.business.entity.TAExamCourseCollegeTeacher;
 
+import java.util.List;
+
 /**
  * <p>
  * 参考课程学院下授课教师维度分析表 服务类
@@ -21,4 +24,14 @@ public interface TAExamCourseCollegeTeacherService extends IService<TAExamCourse
     IPage<TeacherMyClassRankResult> listMyClassRank(String semester, Long examId, Long teacherId, String courseCode, Long inspectCollegeId, Integer pageNumber, Integer pageSize);
 
     IPage<TAExamCourseCollegeTeacher> listAllTeacherClassRank(String semester, Long examId, Long teachCollegeId, String courseCode, Long teacherId, Integer pageNumber, Integer pageSize);
+
+    /**
+     * 查询老师得分
+     *
+     * @param examId
+     * @param courseCode
+     * @param collegeId
+     * @return
+     */
+    List<TAExamCourseTeacherResult> findTeacherInfo(Long examId, String courseCode, Long collegeId);
 }

+ 11 - 0
teachcloud-report-business/src/main/java/com/qmth/teachcloud/report/business/service/TAExamCourseService.java

@@ -47,4 +47,15 @@ public interface TAExamCourseService extends IService<TAExamCourse> {
     IPage<TAExamCourseResult> surveyAspointsList(IPage<Map> iPage, Long schoolId, Long examId, String courseCode, PublishStatusEnum publishStatus);
 
     Map<String, Object> getGradeDistribute(String semester, Long examId, String courseCode);
+
+    /**
+     * 考查课程考试分析接口
+     *
+     * @param examId
+     * @param semester
+     * @param courseCode
+     * @param schoolId
+     * @return
+     */
+    List<Object> surveyInspectAnalyseView(Long examId, SemesterEnum semester, String courseCode, Long schoolId);
 }

+ 30 - 0
teachcloud-report-business/src/main/java/com/qmth/teachcloud/report/business/service/TBAnswerService.java

@@ -1,8 +1,13 @@
 package com.qmth.teachcloud.report.business.service;
 
 import com.baomidou.mybatisplus.extension.service.IService;
+import com.qmth.teachcloud.report.business.bean.dto.query.BasicAnswerDto;
+import com.qmth.teachcloud.report.business.bean.dto.query.ValidAnswerDetailDto;
+import com.qmth.teachcloud.report.business.bean.result.TBAnswerResult;
 import com.qmth.teachcloud.report.business.entity.TBAnswer;
 
+import java.util.List;
+
 /**
  * <p>
  * 基础考生作答记录详情表 服务类
@@ -13,4 +18,29 @@ import com.qmth.teachcloud.report.business.entity.TBAnswer;
  */
 public interface TBAnswerService extends IService<TBAnswer> {
 
+    /**
+     * 根据试卷id查询参与该试卷的考生详细作答记录
+     *
+     * @param paperId 试卷id
+     * @return 考生作答记录
+     */
+    List<BasicAnswerDto> findByPaperId(Long paperId);
+
+    /**
+     * 查找试卷结构效度数据
+     *
+     * @param examId     考试id
+     * @param courseCode 课程编号
+     * @return 结果
+     */
+    List<ValidAnswerDetailDto> findValid(Long examId, String courseCode);
+
+    /**
+     * 查找有效答案
+     *
+     * @param examId
+     * @param courseCode
+     * @return
+     */
+    List<TBAnswerResult> findValidAnswerDetail(Long examId, String courseCode);
 }

+ 12 - 0
teachcloud-report-business/src/main/java/com/qmth/teachcloud/report/business/service/TBDimensionService.java

@@ -1,8 +1,11 @@
 package com.qmth.teachcloud.report.business.service;
 
 import com.baomidou.mybatisplus.extension.service.IService;
+import com.qmth.teachcloud.report.business.bean.result.CourseDimensionResult;
 import com.qmth.teachcloud.report.business.entity.TBDimension;
 
+import java.util.List;
+
 /**
  * <p>
  * 考察点维度基础表 服务类
@@ -13,4 +16,13 @@ import com.qmth.teachcloud.report.business.entity.TBDimension;
  */
 public interface TBDimensionService extends IService<TBDimension> {
 
+    /**
+     * 查找维度信息
+     *
+     * @param examId
+     * @param courseCode
+     * @param collegeId
+     * @return
+     */
+    List<CourseDimensionResult> findDimensionInfo(Long examId, String courseCode, Long collegeId);
 }

+ 9 - 1
teachcloud-report-business/src/main/java/com/qmth/teachcloud/report/business/service/TBModuleConfigService.java

@@ -3,6 +3,8 @@ package com.qmth.teachcloud.report.business.service;
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.qmth.teachcloud.report.business.entity.TBModuleConfig;
 
+import java.util.List;
+
 /**
  * <p>
  * 考察点模块配置表 服务类
@@ -12,5 +14,11 @@ import com.qmth.teachcloud.report.business.entity.TBModuleConfig;
  * @since 2021-06-01
  */
 public interface TBModuleConfigService extends IService<TBModuleConfig> {
-
+    /**
+     * 根据考试id和课程编号查询不重复的模块信息
+     * @param examId 考试id
+     * @param courseCode 课程编号
+     * @return 模块信息
+     */
+    List<TBModuleConfig> findDistinctModuleInfoByExamIdAndCourseCode(Long examId, String courseCode);
 }

+ 11 - 0
teachcloud-report-business/src/main/java/com/qmth/teachcloud/report/business/service/TBPaperStructService.java

@@ -1,8 +1,11 @@
 package com.qmth.teachcloud.report.business.service;
 
 import com.baomidou.mybatisplus.extension.service.IService;
+import com.qmth.teachcloud.report.business.bean.result.TBPaperStructResult;
 import com.qmth.teachcloud.report.business.entity.TBPaperStruct;
 
+import java.util.List;
+
 /**
  * <p>
  * 试卷结构表 服务类
@@ -13,4 +16,12 @@ import com.qmth.teachcloud.report.business.entity.TBPaperStruct;
  */
 public interface TBPaperStructService extends IService<TBPaperStruct> {
 
+    /**
+     * 查找试卷结构
+     *
+     * @param examId
+     * @param courseCode
+     * @return
+     */
+    List<TBPaperStructResult> findQuestionInfo(Long examId, String courseCode);
 }

+ 1605 - 0
teachcloud-report-business/src/main/java/com/qmth/teachcloud/report/business/service/impl/AnalyzeForStudentServiceImpl.java

@@ -0,0 +1,1605 @@
+package com.qmth.teachcloud.report.business.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.qmth.teachcloud.common.contant.SystemConstant;
+import com.qmth.teachcloud.common.entity.SysOrg;
+import com.qmth.teachcloud.common.enums.ExceptionResultEnum;
+import com.qmth.teachcloud.common.service.BasicCourseService;
+import com.qmth.teachcloud.common.service.SysOrgService;
+import com.qmth.teachcloud.common.service.SysUserService;
+import com.qmth.teachcloud.report.business.bean.dto.query.BasicAnswerDto;
+import com.qmth.teachcloud.report.business.bean.dto.query.ValidAnswerDetailDto;
+import com.qmth.teachcloud.report.business.entity.*;
+import com.qmth.teachcloud.report.business.enums.LevelRuleEnum;
+import com.qmth.teachcloud.report.business.enums.QuantileEnum;
+import com.qmth.teachcloud.report.business.enums.ValidityEnum;
+import com.qmth.teachcloud.report.business.service.*;
+import com.qmth.teachcloud.report.business.utils.AnalyzeScopeUtil;
+import com.qmth.teachcloud.report.business.utils.ConversionUtils;
+import com.qmth.teachcloud.report.business.utils.MathUtil;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import javax.annotation.Resource;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.math.BigDecimal;
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * @Description: 学生看板数据计算
+ * @Author: CaoZixuan
+ * @Date: 2021-06-06
+ */
+@Service
+public class AnalyzeForStudentServiceImpl implements AnalyzeForStudentService {
+    @Resource
+    private TAExamCourseRecordService taExamCourseRecordService;
+    @Resource
+    private TBExamCourseService tbExamCourseService;
+    @Resource
+    private TBCommonLevelConfigService tbCommonLevelConfigService;
+    @Resource
+    private TBCommonRankLevelConfigService tbCommonRankLevelConfigService;
+    @Resource
+    private BasicCourseService basicCourseService;
+    @Resource
+    private TAExamCourseCollegeInspectService taExamCourseCollegeInspectService;
+    @Resource
+    private TBPaperService tbPaperService;
+    @Resource
+    private TBExamStudentService tbExamStudentService;
+    @Resource
+    private SysOrgService sysOrgService;
+    @Resource
+    private TBExamService tbExamService;
+    @Resource
+    private TAExamCourseService taExamCourseService;
+    @Resource
+    private TAExamCourseClazzService taExamCourseClazzService;
+    @Resource
+    private TBDimensionService tbDimensionService;
+    @Resource
+    private TAExamCourseDioService taExamCourseDioService;
+    @Resource
+    private TAExamCourseRecordDioService taExamCourseRecordDioService;
+    @Resource
+    private TAExamCourseRecordModService taExamCourseRecordModService;
+    @Resource
+    private TBPaperStructService tbPaperStructService;
+    @Resource
+    private TBAnswerService tbAnswerService;
+    @Resource
+    private TBModuleConfigService tbModuleConfigService;
+    @Resource
+    private TBModuleProficiencyService tbModuleProficiencyService;
+    @Resource
+    private TAExamCourseCollegeInspectDioService taExamCourseCollegeInspectDioService;
+    @Resource
+    private TAPaperStructService taPaperStructService;
+    @Resource
+    private TAExamTotalService taExamTotalService;
+    @Resource
+    private TAExamCourseCollegeTeacherService taExamCourseCollegeTeacherService;
+    @Resource
+    private TAExamCourseTeacherService taExamCourseTeacherService;
+    @Resource
+    private SysUserService sysUserService;
+
+
+    @Transactional(rollbackFor = Exception.class)
+    @Override
+    public String buildAnalyzeExamCourse(Long examId, String courseCode) {
+        List<String> effectiveCourseCodeList = tbExamCourseService.findEffectiveByExamId(examId,courseCode);
+        // 考试下考生作答数据源
+        List<TAExamCourseRecord> dataSource = taExamCourseRecordService.list(new QueryWrapper<TAExamCourseRecord>().lambda()
+                .eq(TAExamCourseRecord::getExamId,examId));
+        List<TAExamCourse> taExamCourseList = new ArrayList<>();
+        // 有效的课程
+        for (String effectiveCourseCode : effectiveCourseCodeList) {
+            // 原数据删除
+            taExamCourseService.remove(new QueryWrapper<TAExamCourse>().lambda()
+                    .eq(TAExamCourse::getExamId,examId)
+                    .eq(TAExamCourse::getCourseCode,effectiveCourseCode));
+
+            // TODO: 2021/6/7 查询试卷信息AB卷的准确方式(目前AB卷规则视为一致)
+            List<TBPaper> tbPaperList = tbPaperService.list(new QueryWrapper<TBPaper>().lambda()
+                    .eq(TBPaper::getExamId,examId).eq(TBPaper::getCourseCode,effectiveCourseCode));
+            if (tbPaperList.size() < 1){
+                throw ExceptionResultEnum.ERROR.exception("未找到试卷基础信息");
+            }
+            TBPaper tbPaper = tbPaperList.get(0);
+            // 通过分
+            BigDecimal passScore = tbPaper.getPassScore();
+            // 满分
+            BigDecimal totalScore = tbPaper.getTotalScore();
+            // 赋分系数
+            BigDecimal coefficient = tbPaper.getCoefficient();
+
+            /*
+                该课程总体学生成绩分析
+             */
+            // 该课程考生数据
+            List<TAExamCourseRecord> totalDatasource = dataSource.stream()
+                    .filter(e -> effectiveCourseCode.equals(e.getCourseCode())).collect(Collectors.toList());
+            int totalCount = totalDatasource.size();
+            long realityCount = totalDatasource.stream().filter(e -> !e.getAbsent()).count();
+            long absentCount = totalDatasource.stream().filter(TAExamCourseRecord::getAbsent).count();
+            if (totalCount != realityCount + absentCount){
+                throw ExceptionResultEnum.ERROR.exception("考试人数数据异常");
+            }
+            // 赋分数据集合
+            // -------------------赋分------------------------
+            List<Double> totalScoreList = totalDatasource.stream().filter(e -> !e.getAbsent()).map(e -> e.getAssignedScore().doubleValue()).collect(Collectors.toList());
+            DoubleSummaryStatistics totalStatistics = totalScoreList.stream().collect(Collectors.summarizingDouble(e -> e));
+            double avgScore = totalStatistics.getAverage();
+            long passCount = totalScoreList.stream().filter(e -> e >= passScore.doubleValue()).count();
+            BigDecimal passRate = BigDecimal.valueOf(passCount).divide(BigDecimal.valueOf(realityCount),4,BigDecimal.ROUND_HALF_DOWN);
+
+            // -------------------卷面分------------------------
+            List<Double> paperTotalScoreList = totalDatasource.stream().filter(e -> !e.getAbsent()).map(e -> e.getTotalScore().doubleValue()).collect(Collectors.toList());
+            DoubleSummaryStatistics paperTotalStatistics = paperTotalScoreList.stream().collect(Collectors.summarizingDouble(e -> e));
+            double paperAvgScore = paperTotalStatistics.getAverage();
+            long paperPassCount = paperTotalScoreList.stream().filter(e -> e >= passScore.doubleValue()).count();
+            BigDecimal paperPassRate = BigDecimal.valueOf(paperPassCount).divide(BigDecimal.valueOf(realityCount),4,BigDecimal.ROUND_HALF_DOWN);
+
+
+
+            /*
+                该课程往届生成绩分析
+             */
+            // 该课程往届数据
+            List<TAExamCourseRecord> pastDatasource = totalDatasource.stream()
+                    .filter(e -> !e.getStudentCurrent()).collect(Collectors.toList());
+            int pastTotalCount = pastDatasource.size();
+            long pastRealityCount = pastDatasource.stream().filter(e -> !e.getAbsent()).count();
+            long pastAbsentCount = pastDatasource.stream().filter(TAExamCourseRecord::getAbsent).count();
+            if (pastTotalCount != pastRealityCount + pastAbsentCount){
+                throw ExceptionResultEnum.ERROR.exception("考试往届生人数数据异常");
+            }
+            BigDecimal pastRealityRate = BigDecimal.valueOf(pastRealityCount).divide(BigDecimal.valueOf(realityCount),4,BigDecimal.ROUND_HALF_DOWN);
+
+            /*
+                该课程应届生成绩分析
+             */
+            // 该课程下应届数据
+            List<TAExamCourseRecord> currentDatasource = totalDatasource.stream()
+                    .filter(TAExamCourseRecord::getStudentCurrent).collect(Collectors.toList());
+            // 人数统计
+            int currentTotalCount = currentDatasource.size();
+            long currentRealityCount = currentDatasource.stream().filter(e -> !e.getAbsent()).count();
+            long currentAbsentCount = currentDatasource.stream().filter(TAExamCourseRecord::getAbsent).count();
+            if (currentTotalCount != currentRealityCount + currentAbsentCount){
+                throw ExceptionResultEnum.ERROR.exception("考试应届生人数数据异常");
+            }
+            BigDecimal currentRealityRate = BigDecimal.valueOf(currentRealityCount).divide(BigDecimal.valueOf(realityCount),4,BigDecimal.ROUND_HALF_DOWN);
+
+            // 通过率统计
+            List<Double> currentScoreList = currentDatasource.stream().filter(e -> !e.getAbsent()).map(e -> e.getAssignedScore().doubleValue()).collect(Collectors.toList());
+            DoubleSummaryStatistics currentStatistics = currentScoreList.stream().collect(Collectors.summarizingDouble(e -> e));
+            long currentPassCount = currentScoreList.stream().filter(e -> e >= passScore.doubleValue()).count();
+            BigDecimal currentPassRate = BigDecimal.valueOf(currentPassCount).divide(BigDecimal.valueOf(currentRealityCount),4,BigDecimal.ROUND_HALF_DOWN);
+
+            // 描述统计
+            double currentMinScore = currentStatistics.getMin();
+            double currentMaxScore = currentStatistics.getMax();
+            double currentAvgScore = currentStatistics.getAverage();
+
+            // 计算众数
+            String currentMode = MathUtil.calculateMode(currentScoreList);
+            // 计算上四分位数
+            double currentUpperQuartile = MathUtil.calculateQuantile(currentScoreList, QuantileEnum.UPPER_QUARTILE.getValue());
+            // 计算中位数
+            double currentMedian = MathUtil.calculateQuantile(currentScoreList, QuantileEnum.MEDIAN.getValue());
+            // 计算下四分位数
+            double currentLowerQuartile = MathUtil.calculateQuantile(currentScoreList, QuantileEnum.LOWER_QUARTILE.getValue());
+
+            // 极端情况下分位数值处理
+            if (currentUpperQuartile == 0) {
+                currentUpperQuartile = currentMedian;
+            }
+            if (currentLowerQuartile == 0) {
+                currentLowerQuartile = currentMedian;
+            }
+            // 计算标准差
+            double currentStandardDeviation = MathUtil.calculateStandardDeviation(currentScoreList);
+
+            // TODO: 2021/6/7 难度系数使用标准分计算
+            BigDecimal scoreRate;
+            double standardAvgScore = currentDatasource.stream().collect(Collectors.summarizingDouble(e -> e.getTotalScore().doubleValue())).getAverage();
+            if (standardAvgScore != 0 && totalScore.compareTo(BigDecimal.ZERO) > 0) {
+                scoreRate = BigDecimal.valueOf(standardAvgScore).divide(totalScore,4,BigDecimal.ROUND_HALF_DOWN);
+            } else {
+                scoreRate = BigDecimal.ZERO;
+            }
+            // 难度系数保留1位数
+            scoreRate = scoreRate.setScale(1,BigDecimal.ROUND_HALF_DOWN); // 难度系数保留1位有效数字
+            String difficulty = this.handleLevel(examId,effectiveCourseCode,"难度等级", scoreRate.doubleValue());
+            //--------------------------应届-卷面成绩-----------------------
+            List<Double> paperCurrentScoreList = currentDatasource.stream().filter(e -> !e.getAbsent()).map(e -> e.getTotalScore().doubleValue()).collect(Collectors.toList());
+            DoubleSummaryStatistics paperCurrentStatistics = paperCurrentScoreList.stream().collect(Collectors.summarizingDouble(e -> e));
+            double paperCurrentAvgScore = paperCurrentStatistics.getAverage();
+            long paperCurrentPassCount = paperCurrentScoreList.stream().filter(e -> e >= passScore.doubleValue()).count();
+            BigDecimal paperCurrentPassRate = BigDecimal.valueOf(paperCurrentPassCount).divide(BigDecimal.valueOf(currentRealityCount),4,BigDecimal.ROUND_HALF_DOWN);
+
+            /*
+                学院信息
+             */
+            // TODO: 2021/6/7 考察学院数量算进去往届和缺考的吗
+            List<TBExamStudent> tbExamStudentList = tbExamStudentService.list(new QueryWrapper<TBExamStudent>().lambda()
+                    .eq(TBExamStudent::getExamId,examId).eq(TBExamStudent::getCourseCode,effectiveCourseCode));
+
+            List<Long> teachCollegeIdList = tbExamStudentList.stream().map(TBExamStudent::getTeachCollegeId).distinct().collect(Collectors.toList());
+            List<Long> inspectCollegeIdList = tbExamStudentList.stream().map(TBExamStudent::getInspectCollegeId).distinct().collect(Collectors.toList());
+            if (teachCollegeIdList.size() != 1){
+                throw ExceptionResultEnum.ERROR.exception("该课程有多个开课学院异常");
+            }
+            Long teachCollegeId = teachCollegeIdList.get(0);
+            SysOrg tbSchoolCollege = sysOrgService.getById(teachCollegeId);
+            String teachCollegeName;
+            if (Objects.isNull(tbSchoolCollege)){
+                teachCollegeName = SystemConstant.DEFAULT_SIGN;
+            }else {
+                teachCollegeName= tbSchoolCollege.getName();
+            }
+            int inspectCollegeCount = inspectCollegeIdList.size();
+
+            /*
+                组装
+             */
+            TBExam tbExam = tbExamService.getById(examId);
+            TAExamCourse taExamCourse = new TAExamCourse();
+            taExamCourse.setId(SystemConstant.getDbUuid());
+            taExamCourse.setExamId(examId);
+            taExamCourse.setExamName(tbExam.getExamName());
+            taExamCourse.setCourseCode(effectiveCourseCode);
+            taExamCourse.setCourseName(basicCourseService.findByCourseCode(effectiveCourseCode).getName());
+            taExamCourse.setSchoolId(tbExam.getSchoolId());
+            taExamCourse.setTeachCollegeId(teachCollegeId);
+            taExamCourse.setTeachCollegeName(teachCollegeName);
+            taExamCourse.setInspectCollegeCount(inspectCollegeCount);
+            taExamCourse.setAvgScore(BigDecimal.valueOf(avgScore));
+            taExamCourse.setPassCount((int) passCount);
+            taExamCourse.setPassRate(passRate);
+            taExamCourse.setCurrentPassCount((int) currentPassCount);
+            taExamCourse.setCurrentPassRate(currentPassRate);
+            taExamCourse.setTotalScore(totalScore);
+            taExamCourse.setRealityCount((int) realityCount);
+            taExamCourse.setAbsentCount((int) absentCount);
+            taExamCourse.setTotalCount(totalCount);
+            taExamCourse.setCurrentMinScore(BigDecimal.valueOf(currentMinScore));
+            taExamCourse.setCurrentMaxScore(BigDecimal.valueOf(currentMaxScore));
+            taExamCourse.setCurrentAvgScore(BigDecimal.valueOf(currentAvgScore));
+            taExamCourse.setCurrentScoreRate(scoreRate);
+            taExamCourse.setCurrentRealityCount((int) currentRealityCount);
+            taExamCourse.setCurrentAbsentCount((int) currentAbsentCount);
+            taExamCourse.setCurrentTotalCount(currentTotalCount);
+            taExamCourse.setCurrentRealityRate(currentRealityRate);
+            taExamCourse.setPastRealityCount((int) pastRealityCount);
+            taExamCourse.setPastAbsentCount((int) pastAbsentCount);
+            taExamCourse.setPastTotalCount(pastTotalCount);
+            taExamCourse.setPastRealityRate(pastRealityRate);
+            taExamCourse.setCurrentUpperQuartile(BigDecimal.valueOf(currentUpperQuartile));
+            taExamCourse.setCurrentMedian(BigDecimal.valueOf(currentMedian));
+            taExamCourse.setCurrentLowerQuartile(BigDecimal.valueOf(currentLowerQuartile));
+            taExamCourse.setCurrentMode(currentMode);
+            taExamCourse.setCurrentStandardDeviation(BigDecimal.valueOf(currentStandardDeviation));
+            taExamCourse.setDifficulty(difficulty);
+            taExamCourse.setPaperAvgScore(BigDecimal.valueOf(paperAvgScore));
+            taExamCourse.setPaperPassRate(paperPassRate);
+            taExamCourse.setPaperCurrentAvgScore(BigDecimal.valueOf(paperCurrentAvgScore));
+            taExamCourse.setPaperCurrentPassRate(paperCurrentPassRate);
+            taExamCourse.setCoefficient(coefficient);
+            taExamCourseList.add(taExamCourse);
+        }
+        taExamCourseService.saveBatch(taExamCourseList);
+        return " 't_a_exam_course' 表构建完毕 "  ;
+    }
+
+    @Transactional(rollbackFor = Exception.class)
+    @Override
+    public String buildAnalyzeExamCourseRecord(Long examId,String courseCode) {
+        // 获取本次考试所有考试记录数据源
+        List<TAExamCourseRecord> taExamCourseRecordDatasource = taExamCourseRecordService.list(new QueryWrapper<TAExamCourseRecord>().lambda()
+                .eq(TAExamCourseRecord::getExamId,examId)
+                .eq(TAExamCourseRecord::getAbsent,false)
+                .eq(TAExamCourseRecord::getStudentCurrent,true));
+
+        List<String> effectiveCourseCodeList = tbExamCourseService.findEffectiveByExamId(examId,courseCode);
+
+        for (String effectiveCourseCode : effectiveCourseCodeList) {
+            List<TAExamCourse> taExamCourseList = taExamCourseService.list(new QueryWrapper<TAExamCourse>().lambda()
+                    .eq(TAExamCourse::getExamId,examId)
+                    .eq(TAExamCourse::getCourseCode,effectiveCourseCode));
+            if (taExamCourseList.size() != 1){
+                throw ExceptionResultEnum.ERROR.exception("考试课程分析数据获取失败");
+            }
+            TAExamCourse taExamCourse = taExamCourseList.get(0);
+            BigDecimal avgScore = taExamCourse.getAvgScore();
+            BigDecimal standardDeviation = taExamCourse.getCurrentStandardDeviation();
+
+            List<TAExamCourseRecord> dataSource = taExamCourseRecordDatasource.stream().filter(e -> effectiveCourseCode.equals(e.getCourseCode())).collect(Collectors.toList());
+            for (TAExamCourseRecord taExamCourseRecord : dataSource) {
+                BigDecimal totalScore = taExamCourseRecord.getTotalScore(); // 标准分
+                long lowCount = dataSource.stream().filter(e -> e.getTotalScore().compareTo(totalScore) < 0).count(); // 低于我的人数
+                long sameCount = dataSource.stream().filter(e -> e.getTotalScore().compareTo(totalScore) == 0).count(); // 和我相同的人数
+                int totalCount = dataSource.size(); //总人数
+                // 标准回归系数
+                BigDecimal standardizedCoefficients = (taExamCourseRecord.getAssignedScore().subtract(avgScore)).divide(standardDeviation,4,BigDecimal.ROUND_HALF_DOWN);
+
+                int percentGrade = this.handlePercentGrade(BigDecimal.valueOf(lowCount),BigDecimal.valueOf(sameCount),BigDecimal.valueOf(totalCount));
+                taExamCourseRecord.setPercentGrade(percentGrade);
+
+                String scoreLevel = this.handleLevel(examId,effectiveCourseCode,"百分等级",percentGrade);
+                taExamCourseRecord.setScoreLevel(scoreLevel);
+                taExamCourseRecord.setStandardizedCoefficients(standardizedCoefficients);
+                this.buildColData(taExamCourseRecord,dataSource); // 总成绩在学院的排名、排名等级档位、超过学院百分比
+            }
+            taExamCourseRecordService.saveOrUpdateBatch(dataSource);
+        }
+        return " 't_a_exam_course_record' 表更新完成";
+    }
+
+    @Transactional(rollbackFor = Exception.class)
+    @Override
+    public String buildAnalyzeExamCourseCollegeInspect(Long examId, String courseCode) {
+        List<TAExamCourseRecord> recordDatasource = taExamCourseRecordService.list(new QueryWrapper<TAExamCourseRecord>().lambda()
+                .eq(TAExamCourseRecord::getExamId,examId));
+        // 可分析有效课程信息
+        List<String> effectiveCourseCodeList = tbExamCourseService.findEffectiveByExamId(examId,courseCode);
+        List<TAExamCourseCollegeInspect> inspectCollegeList = new ArrayList<>();
+
+        for (String effectiveCourseCode : effectiveCourseCodeList) {
+            // 删除原有数据
+            taExamCourseCollegeInspectService.remove(new QueryWrapper<TAExamCourseCollegeInspect>().lambda()
+                    .eq(TAExamCourseCollegeInspect::getExamId,examId).eq(TAExamCourseCollegeInspect::getCourseCode,effectiveCourseCode));
+
+            // 本课程下所有应届考生考生记录
+            List<TAExamCourseRecord> recordCourseCurrentDatasource = recordDatasource.stream()
+                    .filter(e -> effectiveCourseCode.equals(e.getCourseCode()) && e.getStudentCurrent()).collect(Collectors.toList());
+
+            List<Long> inspectCollegeIdList = recordCourseCurrentDatasource.stream().filter(e -> !e.getAbsent()).map(TAExamCourseRecord::getInspectCollegeId).distinct().collect(Collectors.toList());
+            for (Long collegeId : inspectCollegeIdList) {
+                List<TAExamCourseRecord> collegeEffectiveRecordDatasource = recordCourseCurrentDatasource.stream()
+                        .filter(e -> collegeId.equals(e.getInspectCollegeId())).collect(Collectors.toList());
+                // 课程-学院 总应届人数
+                int totalCount = collegeEffectiveRecordDatasource.size();
+                // 有效分析数据源
+                List<TAExamCourseRecord> effectiveList = collegeEffectiveRecordDatasource.stream().filter(e -> !e.getAbsent()).collect(Collectors.toList());
+                // 课程-学院 总应届实考人数
+                int realityCount = effectiveList.size();
+                // 课程-学院 总缺考应届人数
+                int absentCount = totalCount - realityCount;
+
+                List<Double> assignedScoreList = effectiveList.stream().map(e -> e.getAssignedScore().doubleValue()).collect(Collectors.toList());
+                DoubleSummaryStatistics doubleSummaryStatistics = assignedScoreList.stream().collect(Collectors.summarizingDouble(e -> e));
+                double minScore = doubleSummaryStatistics.getMin();
+                double maxScore = doubleSummaryStatistics.getMax();
+                double avgScore = doubleSummaryStatistics.getAverage();
+                String mode = MathUtil.calculateMode(assignedScoreList);
+                double upperQuartile = MathUtil.calculateQuantile(assignedScoreList, QuantileEnum.UPPER_QUARTILE.getValue());
+                double median = MathUtil.calculateQuantile(assignedScoreList, QuantileEnum.MEDIAN.getValue());
+                double lowerQuartile = MathUtil.calculateQuantile(assignedScoreList, QuantileEnum.LOWER_QUARTILE.getValue());
+
+                // TODO: 2021/6/7 缺考的学院信息处理
+                if (effectiveList.size() == 0){
+                    minScore = 0;
+                    maxScore = 0;
+                    avgScore = 0;
+                    mode = "";
+                    upperQuartile = 0;
+                    median = 0;
+                    lowerQuartile = 0;
+                }
+
+                // 极端情况下分位数值处理
+                if (upperQuartile == 0) {
+                    upperQuartile = median;
+                }
+                if (lowerQuartile == 0) {
+                    lowerQuartile = median;
+                }
+                double standardDeviation = MathUtil.calculateStandardDeviation(assignedScoreList);
+                // 相对位置
+                double relativePosition = effectiveList.stream().collect(Collectors.summarizingDouble(e -> e.getStandardizedCoefficients().doubleValue())).getAverage();
+
+                TAExamCourseCollegeInspect taExamCourseCollegeInspect = new TAExamCourseCollegeInspect();
+                taExamCourseCollegeInspect.setId(SystemConstant.getDbUuid());
+                taExamCourseCollegeInspect.setExamId(examId);
+                taExamCourseCollegeInspect.setSchoolId(tbExamService.getById(examId).getSchoolId());
+                taExamCourseCollegeInspect.setCourseCode(effectiveCourseCode);
+                taExamCourseCollegeInspect.setCourseName(basicCourseService.findByCourseCode(effectiveCourseCode).getName());
+                taExamCourseCollegeInspect.setCollegeId(collegeId);
+                taExamCourseCollegeInspect.setMaxScore(BigDecimal.valueOf(maxScore));
+                taExamCourseCollegeInspect.setMinScore(BigDecimal.valueOf(minScore));
+                taExamCourseCollegeInspect.setAvgScore(BigDecimal.valueOf(avgScore));
+                taExamCourseCollegeInspect.setRealityCount(realityCount);
+                taExamCourseCollegeInspect.setAbsentCount(absentCount);
+                taExamCourseCollegeInspect.setTotalCount(totalCount);
+                taExamCourseCollegeInspect.setUpperQuartile(BigDecimal.valueOf(upperQuartile));
+                taExamCourseCollegeInspect.setMedian(BigDecimal.valueOf(median));
+                taExamCourseCollegeInspect.setLowerQuartile(BigDecimal.valueOf(lowerQuartile));
+                taExamCourseCollegeInspect.setMode(mode);
+                taExamCourseCollegeInspect.setStandardDeviation(BigDecimal.valueOf(standardDeviation));
+                taExamCourseCollegeInspect.setRelativePosition(BigDecimal.valueOf(relativePosition));
+                inspectCollegeList.add(taExamCourseCollegeInspect);
+            }
+        }
+        taExamCourseCollegeInspectService.saveBatch(inspectCollegeList);
+        return "t_a_exam_course_college_inspect";
+    }
+
+    @Transactional(rollbackFor = Exception.class)
+    @Override
+    public String buildAnalyzeExamCourseClazz(Long examId, String courseCode) {
+        List<TAExamCourseRecord> recordDatasource = taExamCourseRecordService.list(new QueryWrapper<TAExamCourseRecord>().lambda()
+                .eq(TAExamCourseRecord::getExamId,examId));
+        // 可分析有效课程信息
+        List<String> effectiveCourseCodeList = tbExamCourseService.findEffectiveByExamId(examId,courseCode);
+
+        List<TAExamCourseClazz> taExamCourseClazzList = new ArrayList<>();
+        for (String effectiveCourseCode : effectiveCourseCodeList) {
+            // 删除原有数据
+            taExamCourseClazzService.remove(new QueryWrapper<TAExamCourseClazz>().lambda()
+                    .eq(TAExamCourseClazz::getExamId,examId)
+                    .eq(TAExamCourseClazz::getCourseCode,effectiveCourseCode));
+
+            List<TAExamCourseRecord> recordCourseCurrentDatasource = recordDatasource.stream()
+                    .filter(e -> effectiveCourseCode.equals(e.getCourseCode()) && e.getStudentCurrent()).collect(Collectors.toList());
+            List<Long> clazzIdList = recordCourseCurrentDatasource.stream().filter(e -> !e.getAbsent()).map(TAExamCourseRecord::getClazzId).distinct().collect(Collectors.toList());
+            for (Long clazzId : clazzIdList) {
+                List<TAExamCourseRecord> clazzEffectiveRecordDatasource = recordCourseCurrentDatasource.stream()
+                        .filter(e -> clazzId.equals(e.getClazzId())).collect(Collectors.toList());
+
+                // 课程-班级 总应届人数
+                int totalCount = clazzEffectiveRecordDatasource.size();
+                // 有效分析数据源
+                List<TAExamCourseRecord> effectiveList = clazzEffectiveRecordDatasource.stream().filter(e -> !e.getAbsent()).collect(Collectors.toList());
+                // 课程-班级 总应届实考人数
+                int realityCount = effectiveList.size();
+                // 课程-班级 总缺考应届人数
+                int absentCount = totalCount - realityCount;
+                List<Double> assignedScoreList = effectiveList.stream().map(e -> e.getAssignedScore().doubleValue()).collect(Collectors.toList());
+
+                DoubleSummaryStatistics doubleSummaryStatistics = assignedScoreList.stream().collect(Collectors.summarizingDouble(e -> e));
+                double minScore = doubleSummaryStatistics.getMin();
+                double maxScore = doubleSummaryStatistics.getMax();
+                double avgScore = doubleSummaryStatistics.getAverage();
+
+                List<TBExamStudent> tbExamStudentList = tbExamStudentService.list(new QueryWrapper<TBExamStudent>().lambda()
+                        .eq(TBExamStudent::getExamId,examId)
+                        .eq(TBExamStudent::getCourseCode,effectiveCourseCode)
+                        .eq(TBExamStudent::getClazzId,clazzId));
+                List<Long> teachCollegeIdList = tbExamStudentList.stream().map(TBExamStudent::getTeachCollegeId).distinct().collect(Collectors.toList());
+                String collegeName = "";
+                for (Long collegeId : teachCollegeIdList) {
+                    SysOrg tbSchoolCollege = sysOrgService.getById(collegeId);
+                    if (Objects.isNull(tbSchoolCollege)){
+                        collegeName = collegeName + SystemConstant.DEFAULT_SIGN + ",";
+                    } else {
+                        collegeName = collegeName + tbSchoolCollege.getName() + ",";
+                    }
+                }
+                collegeName = collegeName.substring(0,collegeName.length() - 1);
+
+                TAExamCourseClazz taExamCourseClazz = new TAExamCourseClazz();
+                taExamCourseClazz.setId(SystemConstant.getDbUuid());
+                taExamCourseClazz.setExamId(examId);
+                taExamCourseClazz.setSchoolId(tbExamService.getById(examId).getSchoolId());
+                taExamCourseClazz.setCourseCode(effectiveCourseCode);
+                taExamCourseClazz.setCourseName(basicCourseService.findByCourseCode(effectiveCourseCode).getName());
+                taExamCourseClazz.setClazzId(clazzId);
+                taExamCourseClazz.setMaxScore(BigDecimal.valueOf(maxScore));
+                taExamCourseClazz.setMinScore(BigDecimal.valueOf(minScore));
+                taExamCourseClazz.setAvgScore(BigDecimal.valueOf(avgScore));
+                taExamCourseClazz.setRealityCount(realityCount);
+                taExamCourseClazz.setAbsentCount(absentCount);
+                taExamCourseClazz.setTotalCount(totalCount);
+                taExamCourseClazz.setCollegeName(collegeName);
+                taExamCourseClazzList.add(taExamCourseClazz);
+            }
+        }
+        taExamCourseClazzService.saveBatch(taExamCourseClazzList);
+        return " 't_a_exam_course_clazz'表构建成功 ";
+    }
+
+    @Transactional(rollbackFor = Exception.class)
+    @Override
+    public String AnalyzePointScoreRate(Long examId, String courseCode) throws Exception {
+        // 可分析有效课程信息
+        List<String> effectiveCourseCodeList = tbExamCourseService.findEffectiveByExamId(examId,courseCode);
+
+        List<TAExamCourseRecord> dataSource = taExamCourseRecordService.list(new QueryWrapper<TAExamCourseRecord>().lambda()
+                .eq(TAExamCourseRecord::getExamId,examId));
+
+        // 循环进入每次考试课程下
+        for (String effectiveCourseCode : effectiveCourseCodeList) {
+            // 有效考生作答数据源
+            List<TAExamCourseRecord> effectiveDatasource = dataSource.stream()
+                    .filter(e -> effectiveCourseCode.equals(e.getCourseCode()) && !e.getAbsent() && e.getStudentCurrent()).collect(Collectors.toList());
+
+            // 考察点数据源
+            List<TBDimension> dimensionDatasource = tbDimensionService.list(new QueryWrapper<TBDimension>().lambda()
+                    .eq(TBDimension::getExamId,examId)
+                    .eq(TBDimension::getCourseCode,courseCode));
+
+            if (dimensionDatasource.size() < 1){
+                continue;
+            }
+
+            // 删除原数据
+            taExamCourseDioService.remove(new QueryWrapper<TAExamCourseDio>().lambda()
+                    .eq(TAExamCourseDio::getExamId,examId)
+                    .eq(TAExamCourseDio::getCourseCode,effectiveCourseCode));
+
+            taExamCourseRecordDioService.remove(new QueryWrapper<TAExamCourseRecordDio>().lambda()
+                    .eq(TAExamCourseRecordDio::getExamId,examId)
+                    .eq(TAExamCourseRecordDio::getCourseCode,effectiveCourseCode));
+
+            taExamCourseRecordModService.remove(new QueryWrapper<TAExamCourseRecordMod>().lambda()
+                    .eq(TAExamCourseRecordMod::getExamId,examId)
+                    .eq(TAExamCourseRecordMod::getCourseCode,courseCode));
+
+            List<TBPaper> tbPaperList = tbPaperService.list(new QueryWrapper<TBPaper>().lambda()
+                    .eq(TBPaper::getExamId,examId)
+                    .eq(TBPaper::getCourseCode,courseCode));
+
+            if (tbPaperList.size() == 0){
+                throw ExceptionResultEnum.ERROR.exception("试卷基础数据查找失败");
+            }
+            for (TBPaper tbPaper : tbPaperList) {
+                String paperType = tbPaper.getPaperType();
+                Long paperId = tbPaper.getId();
+                // 试卷结构数据源
+                List<TBPaperStruct> tbPaperStructList = tbPaperStructService.list(new QueryWrapper<TBPaperStruct>().lambda()
+                        .eq(TBPaperStruct::getPaperId,paperId));
+                if (tbPaperStructList.size() == 0){
+                    throw ExceptionResultEnum.ERROR.exception("试卷结构数据查找失败");
+                }
+                // 该试卷下所有考生作答数据
+                List<BasicAnswerDto> answerDtoList = tbAnswerService.findByPaperId(paperId);
+                if (answerDtoList.size() == 0){
+                    throw ExceptionResultEnum.ERROR.exception("试卷id为[" + paperId + "]的考生作答详细记录不存在");
+                }
+
+                // 5.计算每个考察点所对应的题目集合
+                Map<String, List<TBPaperStruct>> pointToPaper = this.handlePointToPaper(dimensionDatasource, tbPaperStructList, examId,courseCode);
+
+                // 计算每个模块对应的题目集合
+                Map<String, List<TBPaperStruct>> moduleToPaper = this.handleModuleToPaper(dimensionDatasource, tbPaperStructList, examId, courseCode);
+
+                // 6.计算每个考察点在此次考试所占分数
+                Map<String, Object> everyPointTotalScore = this.handleEveryPointTotalScore(pointToPaper);
+
+                // 计算每个模块在此次考试中所占分数
+                Map<String, Object> everyModuleTotalScore = this.handleEveryPointTotalScore(moduleToPaper);
+
+                // TODO: 2021/6/7 数据组装
+                // 7.计算每个考生各个考察点和考察模块得分率并更新't_a_exam_course_record_dio'表和't_a_exam_course_record_mod'表
+                List<TAExamCourseRecordDio> taExamCourseRecordDioList = new ArrayList<>();
+                List<TAExamCourseRecordMod> taExamCourseRecordModList = new ArrayList<>();
+                for (TAExamCourseRecord taExamCourseRecord : effectiveDatasource) {
+                    Long inspectCollegeId = taExamCourseRecord.getInspectCollegeId();
+                    String inspectCollegeName = sysOrgService.getById(inspectCollegeId).getName();
+                    List<BasicAnswerDto> oneStudentAnswerDetailDataSource = answerDtoList.stream()
+                            .filter(e -> taExamCourseRecord.getExamRecordId().equals(e.getExamRecordId()))
+                            .collect(Collectors.toList());
+                    if (oneStudentAnswerDetailDataSource.size() == 0){
+                        continue; // 当AB卷时,examPaperTikDataSource还是整体数据,所以会匹配不到,匹配不到的说明不是本套试卷,因此匹配不到的不能处理。
+                    }
+                    // 考察点得分率
+                    for (String s : pointToPaper.keySet()) { // 遍历考察知识点所对应的题目集合键值对
+                        List<TBPaperStruct> paperStructList = pointToPaper.get(s);
+
+                        final String split = SystemConstant.HYPHEN;
+                        Set<String> questionIndex = paperStructList
+                                .stream()
+                                .map(e -> e.getNumberType() + split + e.getBigQuestionNumber() + split + e.getSmallQuestionNumber())
+                                .collect(Collectors.toSet()); // 该考察点考察到的所有试题在试卷结构(paper)中'题号类型-大题号-小题号'组成的索引集合
+
+
+                        // 获取学生在该知识点的总得分
+                        double studentScore = oneStudentAnswerDetailDataSource.stream()
+                                .filter(e -> questionIndex.contains(e.getNumberType() + split + e.getMainNumber() + split + e.getSubNumber()))
+                                .collect(Collectors.summarizingDouble(e -> e.getScore().doubleValue()))
+                                .getSum();  // 查找该考察点所考察的所有试题在试卷结构(paper)中的索引('题号类型-大题号-小题号')包含该学生每题答题记录的索引的答题记录信息,计算描述统计
+
+                        // 获取该知识点在试卷中的总得分
+                        double totalScore = (double) everyPointTotalScore.get(s);
+
+                        // 获取该知识点该学生的得分率
+                        double rate;
+                        if (totalScore != 0 && studentScore != 0) {
+                            rate = studentScore / totalScore;
+                        } else {
+                            rate = 0;
+                        }
+
+                        //组装taExamCourseRecordDio数据
+                        TAExamCourseRecordDio taExamCourseRecordDio = new TAExamCourseRecordDio();
+                        taExamCourseRecordDio.setId(SystemConstant.getDbUuid());
+                        taExamCourseRecordDio.setSchoolId(tbExamService.getById(examId).getSchoolId());
+                        taExamCourseRecordDio.setExamRecordId(taExamCourseRecord.getExamRecordId());
+                        taExamCourseRecordDio.setPaperId(taExamCourseRecord.getPaperId());
+                        taExamCourseRecordDio.setExamId(taExamCourseRecord.getExamId());
+                        taExamCourseRecordDio.setCourseCode(effectiveCourseCode);
+                        taExamCourseRecordDio.setCourseName(basicCourseService.findByCourseCode(effectiveCourseCode).getName());
+                        String[] dimCodeArr = s.split("-");
+                        if (dimCodeArr.length != 2) {
+                            throw ExceptionResultEnum.ERROR.exception("获得的考察点标识不符合标准,标准为 type-dimensionCode,结果为:  " + s);
+                        }
+                        String dimensionType = dimCodeArr[0];
+                        String dimensionCode = dimCodeArr[1];
+                        taExamCourseRecordDio.setDimensionType(dimensionType);
+                        taExamCourseRecordDio.setDimensionCode(dimensionCode);
+                        taExamCourseRecordDio.setStudentScore(BigDecimal.valueOf(studentScore));
+                        taExamCourseRecordDio.setScoreRate(BigDecimal.valueOf(rate));
+                        taExamCourseRecordDio.setProficiency(this.handleModuleProficiency(examId,effectiveCourseCode, dimensionType, rate));
+                        taExamCourseRecordDio.setInspectCollegeId(inspectCollegeId);
+                        taExamCourseRecordDio.setInspectCollegeName(inspectCollegeName);
+                        taExamCourseRecordDioList.add(taExamCourseRecordDio);
+                    }
+                    // 考察模块得分率
+                    for (String s : moduleToPaper.keySet()) { // 遍历考察模块对应的题目集合键值对
+                        List<TBPaperStruct> paperStructList = moduleToPaper.get(s);
+
+                        final String split = SystemConstant.HYPHEN;
+
+                        Set<String> questionIndex = paperStructList
+                                .stream()
+                                .map(e -> e.getNumberType() + split + e.getBigQuestionNumber() + split + e.getSmallQuestionNumber())
+                                .collect(Collectors.toSet()); // 该考察点考察到的所有试题在试卷结构(paper)中'题号类型-大题号-小题号'组成的索引集合
+
+                        // 获取学生在该知识点的总得分
+                        double studentScore = oneStudentAnswerDetailDataSource.stream()
+                                .filter(e -> questionIndex.contains(e.getNumberType() + split + e.getMainNumber() + split + e.getSubNumber()))
+                                .collect(Collectors.summarizingDouble(e -> e.getScore().doubleValue()))
+                                .getSum();  // 查找该考察点所考察的所有试题在试卷结构(paper)中的索引('题号类型-大题号-小题号')包含该学生每题答题记录的索引的答题记录信息,计算描述统计
+
+
+                        // 获取该知识点在试卷中的总得分
+                        double totalScore = (double) everyModuleTotalScore.get(s);
+
+                        // 获取该知识点该学生的得分率
+                        double rate;
+                        if (totalScore != 0 && studentScore != 0) {
+                            rate = studentScore / totalScore;
+                        } else {
+                            rate = 0;
+                        }
+                        TAExamCourseRecordMod taExamCourseRecordMod = new TAExamCourseRecordMod();
+                        taExamCourseRecordMod.setId(SystemConstant.getDbUuid());
+                        taExamCourseRecordMod.setExamRecordId(taExamCourseRecord.getExamRecordId());
+                        taExamCourseRecordMod.setPaperId(taExamCourseRecord.getPaperId());
+                        taExamCourseRecordMod.setExamId(taExamCourseRecord.getExamId());
+                        taExamCourseRecordMod.setSchoolId(tbExamService.getById(examId).getSchoolId());
+                        taExamCourseRecordMod.setCourseCode(effectiveCourseCode);
+                        taExamCourseRecordMod.setCourseName(basicCourseService.findByCourseCode(effectiveCourseCode).getName());
+                        taExamCourseRecordMod.setModuleType(s);
+                        taExamCourseRecordMod.setTotalScore(BigDecimal.valueOf(studentScore));
+                        taExamCourseRecordMod.setScoreRate(BigDecimal.valueOf(rate));
+                        taExamCourseRecordMod.setFullScore(BigDecimal.valueOf(totalScore));
+                        taExamCourseRecordMod.setProficiency(this.handleModuleProficiency(examId,effectiveCourseCode,s,rate));
+                        taExamCourseRecordMod.setInspectCollegeId(inspectCollegeId);
+                        taExamCourseRecordMod.setInspectCollegeName(inspectCollegeName);
+                        taExamCourseRecordModList.add(taExamCourseRecordMod);
+                    }
+                }
+                taExamCourseRecordDioService.saveBatch(taExamCourseRecordDioList);
+                taExamCourseRecordModService.saveBatch(taExamCourseRecordModList);
+
+                // 8.计算此次考试各个考察点得分率并插入't_a_exam_course_dio'表
+                List<TAExamCourseDio> taExamCourseDioList = new ArrayList<>();
+                for (String s : everyPointTotalScore.keySet()) {
+                    String[] dimCodeArr = s.split("-");
+                    if (dimCodeArr.length != 2) {
+                        throw ExceptionResultEnum.ERROR.exception("获得的考察点标识不符合标准,标准为 type-dimensionCode,结果为:  " + s);
+                    }
+                    String dimensionType = dimCodeArr[0];
+                    String dimensionCode = dimCodeArr[1];
+                    double totalScore = (double) everyPointTotalScore.get(s);
+                    double avgScore = taExamCourseRecordDioList.stream()
+                            .filter(e -> dimensionType.equals(e.getDimensionType()) && dimensionCode.equals(e.getDimensionCode()))
+                            .collect(Collectors.summarizingDouble(e -> e.getStudentScore().doubleValue()))
+                            .getAverage();
+                    double rate;
+                    if (totalScore != 0 && avgScore != 0) {
+                        rate = avgScore / totalScore;
+                    } else {
+                        rate = 0;
+                    }
+                    double totalCount = pointToPaper.get(s).size();
+
+                    //组装't_a_exam_course_dio'数据
+                    TAExamCourseDio taExamCourseDio = new TAExamCourseDio();
+                    taExamCourseDio.setId(SystemConstant.getDbUuid());
+                    taExamCourseDio.setExamId(examId);
+                    taExamCourseDio.setSchoolId(tbExamService.getById(examId).getSchoolId());
+                    taExamCourseDio.setCourseCode(effectiveCourseCode);
+                    taExamCourseDio.setCourseName(basicCourseService.findByCourseCode(courseCode).getName());
+                    taExamCourseDio.setPaperId(paperId);
+                    taExamCourseDio.setDimensionType(dimensionType);
+                    taExamCourseDio.setDimensionCode(dimensionCode);
+                    taExamCourseDio.setScoreRate(BigDecimal.valueOf(rate));
+                    taExamCourseDio.setTotalScore(BigDecimal.valueOf(totalScore));
+                    taExamCourseDio.setTotalCount(BigDecimal.valueOf(totalCount));
+
+                    taExamCourseDioList.add(taExamCourseDio);
+                }
+                taExamCourseDioService.saveBatch(taExamCourseDioList);
+            }
+
+            List<TAExamCourseRecordMod> examCourseRecordModList = taExamCourseRecordModService.list(new QueryWrapper<TAExamCourseRecordMod>().lambda()
+                    .eq(TAExamCourseRecordMod::getExamId,examId)
+                    .eq(TAExamCourseRecordMod::getCourseCode,effectiveCourseCode));
+
+            // 计算该考生在该模块得分率在该学院排名
+            List<TBModuleConfig> tbModuleConfigList = tbModuleConfigService.findDistinctModuleInfoByExamIdAndCourseCode(examId,effectiveCourseCode);
+            for (TAExamCourseRecordMod taExamCourseRecordMod : examCourseRecordModList) {
+                String moduleType = taExamCourseRecordMod.getModuleType();
+                Long myCollegeId = taExamCourseRecordMod.getInspectCollegeId();
+                List<TAExamCourseRecordMod> sameColModuleList = examCourseRecordModList.stream().filter(e -> e.getInspectCollegeId().equals(myCollegeId)).collect(Collectors.toList()); // 同学院下学生该模块数据
+
+                // 计算模块得分率在学院的排名和排名等级
+                double size = sameColModuleList.size();
+
+
+                BigDecimal myScoreRate = taExamCourseRecordMod.getScoreRate();
+                double myNumber = sameColModuleList.stream().filter(e -> e.getScoreRate().compareTo(myScoreRate) > 0 ).count() + 1; //我在学院的排名
+                taExamCourseRecordMod.setColRank((int) myNumber);
+
+
+                // 计算模块得分率在学院的百分等级
+                double lowCount = sameColModuleList.stream().filter(e -> e.getScoreRate().compareTo(myScoreRate) < 0).count(); // 在学院该模块得分低于我的人数
+                double sameCount = sameColModuleList.stream().filter(e -> e.getScoreRate().compareTo(myScoreRate) == 0).count(); // 在学院该模块得分等于我的人数
+                double totalCount = sameColModuleList.size(); // 该学院总人数
+                int percentGrade = this.handlePercentGrade(BigDecimal.valueOf(lowCount),BigDecimal.valueOf(sameCount), BigDecimal.valueOf(totalCount)); // 该学生该模块成绩在该学院的百分等级
+                taExamCourseRecordMod.setPercentGrade(percentGrade);
+
+                // 计算模块等级
+                List<TBModuleConfig> formulaList = tbModuleConfigList.stream().filter(e -> e.getModuleType().equals(moduleType)).collect(Collectors.toList());
+                if (formulaList.size() != 1) {
+                    throw ExceptionResultEnum.ERROR.exception("数据异常");
+                }
+                String formula = formulaList.get(0).getFormula();
+                LevelRuleEnum[] levelRuleEnumArr = LevelRuleEnum.values();
+                for (LevelRuleEnum levelRuleEnum : levelRuleEnumArr) {
+                    if (formula.equals(levelRuleEnum.getValue())) {
+                        Field field = taExamCourseRecordMod.getClass().getDeclaredField(levelRuleEnum.getAttribute()); //对应属性
+                        Method getMethod = taExamCourseRecordMod.getClass().getDeclaredMethod("get" + ConversionUtils.initCap(field.getName())); // 找到该属性的方法
+
+                        double value = Double.parseDouble(String.valueOf(getMethod.invoke(taExamCourseRecordMod)));
+                        if (!formula.equals(LevelRuleEnum.COLLEGE_RANK.getValue())) {  // 当计算规则不为学院排名时,为了方便计算,将minNumber设置为1 使其无效
+                            size = -1;
+                        }
+                        taExamCourseRecordMod.setLevel(this.handleModuleRankLevel(examId,courseCode,moduleType, value, size));
+                    }
+                }
+            }
+            taExamCourseRecordModService.updateBatchById(examCourseRecordModList);
+
+        }
+        return "维度表构建完毕";
+    }
+
+    @Transactional(rollbackFor = Exception.class)
+    @Override
+    public String buildAnalyzeExamCourseCollegeInspectDio(Long examId, String courseCode) {
+        // 可分析有效课程信息
+        List<String> effectiveCourseCodeList = tbExamCourseService.findEffectiveByExamId(examId,courseCode);
+        for (String effectiveCourseCode : effectiveCourseCodeList) {
+            // 删除原有数据
+            taExamCourseCollegeInspectDioService.remove(new QueryWrapper<TAExamCourseCollegeInspectDio>().lambda()
+                    .eq(TAExamCourseCollegeInspectDio::getExamId,examId)
+                    .eq(TAExamCourseCollegeInspectDio::getCourseCode,effectiveCourseCode));
+
+            taExamCourseCollegeInspectDioService.insertByTAExamCourseRecordDio(examId,courseCode);
+        }
+        return "'t_a_exam_course_college_inspect_dio'表构建完成 ";
+    }
+
+    @Transactional(rollbackFor = Exception.class)
+    @Override
+    public String buildAnalyzePaperStruct(Long examId, String courseCode) {
+        // 可分析有效课程信息
+        List<String> effectiveCourseCodeList = tbExamCourseService.findEffectiveByExamId(examId,courseCode);
+        for (String effectiveCourseCode : effectiveCourseCodeList) {
+            List<TBPaper> tbPaperList = tbPaperService.list(new QueryWrapper<TBPaper>().lambda()
+                    .eq(TBPaper::getExamId,examId).eq(TBPaper::getCourseCode,effectiveCourseCode));
+            if (tbPaperList.size() == 0){
+                throw ExceptionResultEnum.ERROR.exception("基础试卷信息异常");
+            }
+            // 删除原有数据
+            taPaperStructService.remove(new QueryWrapper<TAPaperStruct>().lambda()
+                    .eq(TAPaperStruct::getExamId,examId)
+                    .eq(TAPaperStruct::getCourseCode,effectiveCourseCode));
+            List<TAPaperStruct> taPaperStructList = new ArrayList<>();
+            // 该课程有效试卷结构数据
+            List<ValidAnswerDetailDto> answerDetailDtoList = tbAnswerService.findValid(examId,courseCode);
+            for (TBPaper tbPaper : tbPaperList) {
+                Long paperId = tbPaper.getId();
+                String paperType = tbPaper.getPaperType();
+                List<TBPaperStruct> tbPaperStructList = tbPaperStructService.list(new QueryWrapper<TBPaperStruct>().lambda()
+                        .eq(TBPaperStruct::getPaperId,paperId));
+                if (tbPaperStructList.size() == 0){
+                    throw ExceptionResultEnum.ERROR.exception("试卷结构数据异常");
+                }
+                for (TBPaperStruct paperStruct : tbPaperStructList) {
+                    String numberType = paperStruct.getNumberType();
+                    String mainNumber = paperStruct.getBigQuestionNumber();
+                    String subNumber = paperStruct.getSmallQuestionNumber();
+
+                    List<ValidAnswerDetailDto> oneQuestionAnswerDetailList = answerDetailDtoList
+                            .stream().filter(e -> paperType.equals(e.getPaperType()) &&
+                                    numberType.equals(e.getNumberType()) &&
+                                    mainNumber.equals(e.getMainNumber()) &&
+                                    subNumber.equals(e.getSubNumber())).collect(Collectors.toList()); //某道小题的所有参考学生作答信息(并且按照该科目的参考学生百分等级从高到低排序了)
+
+                    DoubleSummaryStatistics descriptiveStatistics = oneQuestionAnswerDetailList.stream()
+                            .collect(Collectors.summarizingDouble(e -> e.getScore().doubleValue()));
+                    BigDecimal fullScore = paperStruct.getFullScore();
+                    double scoreAvg = descriptiveStatistics.getAverage();
+                    BigDecimal scoreRate = BigDecimal.valueOf(scoreAvg).divide(fullScore,4,BigDecimal.ROUND_HALF_DOWN);
+                    scoreRate = scoreRate.setScale(1,BigDecimal.ROUND_HALF_DOWN);
+                    String difficult = this.analyzeDifficult(examId,courseCode, scoreRate.doubleValue());
+
+                    double validity = this.calculateValidity(oneQuestionAnswerDetailList, fullScore.doubleValue());
+
+                    TAPaperStruct taPaperStruct = new TAPaperStruct();
+                    taPaperStruct.setId(SystemConstant.getDbUuid());
+                    taPaperStruct.setPaperStructId(paperStruct.getId());
+                    taPaperStruct.setExamId(examId);
+                    taPaperStruct.setSchoolId(tbExamService.getById(examId).getSchoolId());
+                    taPaperStruct.setCourseCode(courseCode);
+                    taPaperStruct.setCourseName(basicCourseService.findByCourseCode(courseCode).getName());
+                    taPaperStruct.setScoreRate(scoreRate);
+                    taPaperStruct.setDifficult(difficult);
+                    taPaperStruct.setValidity(BigDecimal.valueOf(validity));
+                    taPaperStructList.add(taPaperStruct);
+                }
+            }
+            taPaperStructService.saveBatch(taPaperStructList);
+        }
+        // TODO: 2021/6/8 部分效度有问题 
+        return " 't_a_paper_struct'表构建成功 ";
+    }
+
+    @Transactional(rollbackFor = Exception.class)
+    @Override
+    public String buildAnalyzeExamTotal(Long examId) {
+        // 删除原数据
+        taExamTotalService.remove(new QueryWrapper<TAExamTotal>().lambda()
+                .eq(TAExamTotal::getExamId,examId));
+
+        // 数据源
+        List<TAExamCourseRecord> taExamCourseRecordList = taExamCourseRecordService.list(new QueryWrapper<TAExamCourseRecord>().lambda()
+                .eq(TAExamCourseRecord::getExamId,examId));
+
+        //考察学院
+        // TODO: 2021/6/8 是否计算只有缺考的学院 是否计算只有往届的学院
+        List<Long> inspectCollegeInfo = taExamCourseRecordList.stream()
+                .map(TAExamCourseRecord::getInspectCollegeId).distinct().collect(Collectors.toList());
+        // 考察学院数量
+        int collegeCount = inspectCollegeInfo.size();
+        String inspectCollegeNames = "";
+        if (collegeCount > 0){
+            for (Long inspectCollegeId : inspectCollegeInfo) {
+                SysOrg college = sysOrgService.getById(inspectCollegeId);
+                inspectCollegeNames = inspectCollegeNames + college.getName() + "、";
+            }
+            // 考察学院名称
+            inspectCollegeNames = inspectCollegeNames.substring(0,inspectCollegeNames.length() - 1);
+        }
+
+        // 课程
+        List<String> courseInfo = taExamCourseRecordList.stream()
+                .map(TAExamCourseRecord::getCourseCode).distinct().collect(Collectors.toList());
+        int courseCount = courseInfo.size();
+
+        // 总人数
+        List<Long> studentInfo = taExamCourseRecordList.stream()
+                .map(TAExamCourseRecord::getStudentId).distinct().collect(Collectors.toList());
+        int totalCount = studentInfo.size();
+
+        // ------只要有一门考试了就不算缺考
+        List<Long> studentRealityInfo = taExamCourseRecordList.stream()
+                .filter(e -> !e.getAbsent())
+                .map(TAExamCourseRecord::getStudentId).distinct().collect(Collectors.toList());
+        int realityCount = studentRealityInfo.size();
+        int absentCount = totalCount - realityCount;
+
+        // 课次
+        int totalCourseTimes = taExamCourseRecordList.size();
+        int realityCourseTimes = (int) taExamCourseRecordList.stream().filter(e -> !e.getAbsent()).count();
+        int absentCourseTimes = (int) taExamCourseRecordList.stream().filter(TAExamCourseRecord::getAbsent).count();
+
+        // 考试时间
+        TBExam tbExam = tbExamService.getById(examId);
+        String examTime = tbExam.getExamTime();
+
+        TAExamTotal taExamTotal = new TAExamTotal();
+        taExamTotal.setId(SystemConstant.getDbUuid());
+        taExamTotal.setExamId(examId);
+        taExamTotal.setSchoolId(tbExamService.getById(examId).getSchoolId());
+        taExamTotal.setCollegeCount(collegeCount);
+        taExamTotal.setCollegeNames(inspectCollegeNames);
+        taExamTotal.setCourseCount(courseCount);
+        taExamTotal.setPublicCourseCount(0);
+        taExamTotal.setMajorCourseCount(courseCount);
+        taExamTotal.setTotalCount(totalCount);
+        taExamTotal.setRealityCount(realityCount);
+        taExamTotal.setAbsentCount(absentCount);
+        taExamTotal.setTotalCourseTimes(totalCourseTimes);
+        taExamTotal.setRealityCourseTimes(realityCourseTimes);
+        taExamTotal.setAbsentCourseTimes(absentCourseTimes);
+        taExamTotal.setExamTime(examTime);
+
+        taExamTotalService.save(taExamTotal);
+        return " 't_a_exam_total'表构建完毕 ";
+    }
+
+    @Transactional(rollbackFor = Exception.class)
+    @Override
+    public String buildAnalyzeExamCourseCollegeTeacher(Long examId, String courseCode) {
+        // 可分析有效课程信息
+        List<String> effectiveCourseCodeList = tbExamCourseService.findEffectiveByExamId(examId,courseCode);
+        for (String effectiveCourseCode : effectiveCourseCodeList) {
+            // 删除该课程原有分析
+            taExamCourseCollegeTeacherService.remove(new QueryWrapper<TAExamCourseCollegeTeacher>().lambda()
+                    .eq(TAExamCourseCollegeTeacher::getExamId,examId)
+                    .eq(TAExamCourseCollegeTeacher::getCourseCode,courseCode));
+
+            List<TAExamCourseCollegeTeacher> taExamCourseCollegeTeacherList = new ArrayList<>();
+            // 整体该课程下数据源
+            List<TAExamCourseRecord> dataSource = taExamCourseRecordService.list(new QueryWrapper<TAExamCourseRecord>().lambda()
+                    .eq(TAExamCourseRecord::getExamId,examId)
+                    .eq(TAExamCourseRecord::getCourseCode,courseCode));
+
+            // 考察学院
+            Set<Long> inspectCollegeIdSet = dataSource.stream().map(TAExamCourseRecord::getInspectCollegeId).collect(Collectors.toSet());
+
+
+            for (Long inspectCollegeId : inspectCollegeIdSet) {
+                // 算教师排名用
+                List<TAExamCourseCollegeTeacher> rankTempList = new ArrayList<>();
+                // 该考察学院维度下授课教师
+                Set<Long> teacherIdSet = dataSource.stream()
+                        .filter(e -> inspectCollegeId.equals(e.getInspectCollegeId()))
+                        .map(TAExamCourseRecord::getTeacherId)
+                        .collect(Collectors.toSet());
+
+                // 教师人数
+                int teacherCount = teacherIdSet.size();
+                for (Long teacherId : teacherIdSet) {
+                    // 该教师数据
+                    List<TAExamCourseRecord> teacherRecordList = dataSource.stream()
+                            .filter(e -> inspectCollegeId.equals(e.getInspectCollegeId()) && teacherId.equals(e.getTeacherId()) && e.getStudentCurrent())
+                            .collect(Collectors.toList());
+
+                    // 学生人数
+                    int totalCount = teacherRecordList.size();
+                    List<TAExamCourseRecord> teacherEffectiveList = teacherRecordList.stream().filter(e -> !e.getAbsent()).collect(Collectors.toList());
+                    int realityCount = teacherEffectiveList.size();
+                    if (realityCount == 0){
+                        continue;
+                    }
+                    int absentCount = totalCount - realityCount;
+
+                    // 成绩统计
+                    DoubleSummaryStatistics describeStatistic = teacherEffectiveList.stream()
+                            .collect(Collectors.summarizingDouble(e -> e.getAssignedScore().doubleValue())); // 学生赋分的描述统计
+                    double minScoreAssign = describeStatistic.getMin();
+                    double maxScoreAssign = describeStatistic.getMax();
+                    double avgScoreAssign = describeStatistic.getAverage();
+                    double avgScore = teacherEffectiveList.stream()
+                            .collect(Collectors.summarizingDouble(e -> e.getTotalScore().doubleValue())).getAverage();
+                    List<Double> assignedScore = teacherEffectiveList.stream().map(e -> e.getAssignedScore().doubleValue()).collect(Collectors.toList());
+                    // 计算上四分位数
+                    double upperQuartile = MathUtil.calculateQuantile(assignedScore, QuantileEnum.UPPER_QUARTILE.getValue());
+
+                    // 计算中位数
+                    double median = MathUtil.calculateQuantile(assignedScore, QuantileEnum.MEDIAN.getValue());
+
+                    // 计算下四分位数
+                    double lowerQuartile = MathUtil.calculateQuantile(assignedScore, QuantileEnum.LOWER_QUARTILE.getValue());
+
+                    // 极端情况下分位数值处理
+                    if (upperQuartile == 0) {
+                        upperQuartile = median;
+                    }
+                    if (lowerQuartile == 0) {
+                        lowerQuartile = median;
+                    }
+
+                    String mode = MathUtil.calculateMode(assignedScore); // 众数
+                    double standardDeviation = MathUtil.calculateStandardDeviation(assignedScore); // 标准差
+
+                    double relativePosition = teacherEffectiveList.stream()
+                            .collect(Collectors.summarizingDouble(e -> e.getStandardizedCoefficients().doubleValue())).getAverage(); // 相对位置
+
+                    // 开课学院数据
+                    List<Long> teachCollegeIdList = teacherEffectiveList.stream().map(TAExamCourseRecord::getTeachCollegeId).distinct().collect(Collectors.toList());
+                    if (teachCollegeIdList.size() > 1){
+                        throw ExceptionResultEnum.ERROR.exception("有多个开课学院");
+                    }
+                    Long teachCollegeId = teachCollegeIdList.get(0);
+                    String teachCollegeName = SystemConstant.DEFAULT_SIGN;
+                    if (teachCollegeId > 0){
+                        teachCollegeName = sysOrgService.getById(teachCollegeId).getName();
+                    }
+
+                    TAExamCourseCollegeTeacher taExamCourseCollegeTeacher = new TAExamCourseCollegeTeacher();
+                    taExamCourseCollegeTeacher.setId(SystemConstant.getDbUuid());
+                    taExamCourseCollegeTeacher.setExamId(examId);
+                    taExamCourseCollegeTeacher.setSchoolId(tbExamService.getById(examId).getSchoolId());
+                    taExamCourseCollegeTeacher.setCourseCode(effectiveCourseCode);
+                    taExamCourseCollegeTeacher.setCourseName(basicCourseService.findByCourseCode(effectiveCourseCode).getName());
+                    taExamCourseCollegeTeacher.setTeacherId(teacherId);
+                    taExamCourseCollegeTeacher.setTeacherName(sysUserService.getById(teacherId).getRealName());
+                    taExamCourseCollegeTeacher.setMinScoreAssign(BigDecimal.valueOf(minScoreAssign));
+                    taExamCourseCollegeTeacher.setMaxScoreAssign(BigDecimal.valueOf(maxScoreAssign));
+                    taExamCourseCollegeTeacher.setAvgScoreAssign(BigDecimal.valueOf(avgScoreAssign));
+                    taExamCourseCollegeTeacher.setAvgScore(BigDecimal.valueOf(avgScore));
+                    taExamCourseCollegeTeacher.setUpperQuartile(BigDecimal.valueOf(upperQuartile));
+                    taExamCourseCollegeTeacher.setMedian(BigDecimal.valueOf(median));
+                    taExamCourseCollegeTeacher.setLowerQuartile(BigDecimal.valueOf(lowerQuartile));
+                    taExamCourseCollegeTeacher.setMode(mode);
+                    taExamCourseCollegeTeacher.setStandardDeviation(BigDecimal.valueOf(standardDeviation));
+                    taExamCourseCollegeTeacher.setRelativePosition(BigDecimal.valueOf(relativePosition));
+                    taExamCourseCollegeTeacher.setRealityCount(realityCount);
+                    taExamCourseCollegeTeacher.setTotalCount(totalCount);
+                    taExamCourseCollegeTeacher.setAbsentCount(absentCount);
+                    taExamCourseCollegeTeacher.setInspectCollegeId(inspectCollegeId);
+                    taExamCourseCollegeTeacher.setInspectCollegeName(sysOrgService.getById(inspectCollegeId).getName());
+                    taExamCourseCollegeTeacher.setTeacherCount(teacherCount);
+                    taExamCourseCollegeTeacher.setTeachCollegeId(teachCollegeId);
+                    taExamCourseCollegeTeacher.setTeachCollegeName(teachCollegeName);
+                    rankTempList.add(taExamCourseCollegeTeacher);
+                }
+                // 计算教师排名
+                for (TAExamCourseCollegeTeacher taExamCourseCollegeTeacher : rankTempList) {
+                    BigDecimal thisAvgScoreAssign = taExamCourseCollegeTeacher.getAvgScoreAssign();
+                    int rank = (int) (rankTempList.stream().filter(e -> e.getAvgScoreAssign().compareTo(thisAvgScoreAssign) > 0).count() + 1);
+                    taExamCourseCollegeTeacher.setTeacherRank(rank);
+                    taExamCourseCollegeTeacherList.add(taExamCourseCollegeTeacher);
+                }
+            }
+            taExamCourseCollegeTeacherService.saveBatch(taExamCourseCollegeTeacherList);
+
+        }
+        return " 't_a_exam_course_college_teacher' 表构建我那成";
+    }
+
+    @Transactional(rollbackFor = Exception.class)
+    @Override
+    public String buildAnalyzeExamCourseTeacher(Long examId, String courseCode) {
+        // 可分析有效课程信息
+        List<String> effectiveCourseCodeList = tbExamCourseService.findEffectiveByExamId(examId,courseCode);
+        for (String effectiveCourseCode : effectiveCourseCodeList) {
+            taExamCourseTeacherService.remove(new QueryWrapper<TAExamCourseTeacher>().lambda()
+                    .eq(TAExamCourseTeacher::getExamId,examId)
+                    .eq(TAExamCourseTeacher::getCourseCode,courseCode));
+
+            List<TAExamCourseTeacher> taExamCourseTeacherList = new ArrayList<>();
+            List<TAExamCourseRecord> dataSource = taExamCourseRecordService.list(new QueryWrapper<TAExamCourseRecord>().lambda()
+                    .eq(TAExamCourseRecord::getExamId,examId).eq(TAExamCourseRecord::getCourseCode,effectiveCourseCode));
+            List<TAExamCourseRecord> currentSource = dataSource.stream().filter(TAExamCourseRecord::getStudentCurrent).collect(Collectors.toList());
+
+            Set<Long> teacherIdList = currentSource.stream().map(TAExamCourseRecord::getTeacherId).collect(Collectors.toSet());
+            for (Long teacherId : teacherIdList) {
+                List<TAExamCourseRecord> teacherRecordList = currentSource.stream()
+                        .filter(e -> teacherId.equals(e.getTeacherId())).collect(Collectors.toList());
+                int totalCount = teacherRecordList.size();
+                List<TAExamCourseRecord> effectiveList = teacherRecordList.stream().filter(e -> !e.getAbsent()).collect(Collectors.toList());
+                if (effectiveList.size() == 0){
+                    continue;
+                }
+                int realityCount = effectiveList.size();
+                int absentCount = totalCount - realityCount;
+
+                DoubleSummaryStatistics describeStatistic = effectiveList.stream()
+                        .collect(Collectors.summarizingDouble(e -> e.getAssignedScore().doubleValue())); // 学生赋分的描述统计
+                double minScore = describeStatistic.getMin();
+                double maxScore = describeStatistic.getMax();
+                double avgScore = describeStatistic.getAverage();
+
+                List<Double> assignedScore = effectiveList.stream().map(e -> e.getAssignedScore().doubleValue()).collect(Collectors.toList());
+                // 计算上四分位数
+                double upperQuartile = MathUtil.calculateQuantile(assignedScore, QuantileEnum.UPPER_QUARTILE.getValue());
+
+                // 计算中位数
+                double median = MathUtil.calculateQuantile(assignedScore, QuantileEnum.MEDIAN.getValue());
+
+                // 计算下四分位数
+                double lowerQuartile = MathUtil.calculateQuantile(assignedScore, QuantileEnum.LOWER_QUARTILE.getValue());
+
+                // 极端情况下分位数值处理
+                if (upperQuartile == 0) {
+                    upperQuartile = median;
+                }
+                if (lowerQuartile == 0) {
+                    lowerQuartile = median;
+                }
+                String mode = MathUtil.calculateMode(assignedScore); // 众数
+                double standardDeviation = MathUtil.calculateStandardDeviation(assignedScore); // 标准差
+
+                // 相对位置
+                double relativePosition = effectiveList.stream()
+                        .collect(Collectors.summarizingDouble(e -> e.getStandardizedCoefficients().doubleValue())).getAverage();
+
+
+                TAExamCourseTeacher taExamCourseTeacher = new TAExamCourseTeacher();
+                taExamCourseTeacher.setId(SystemConstant.getDbUuid());
+                taExamCourseTeacher.setExamId(examId);
+                taExamCourseTeacher.setSchoolId(tbExamService.getById(examId).getSchoolId());
+                taExamCourseTeacher.setCourseCode(effectiveCourseCode);
+                taExamCourseTeacher.setCourseName(basicCourseService.findByCourseCode(effectiveCourseCode).getName());
+                taExamCourseTeacher.setTeacherId(teacherId);
+                taExamCourseTeacher.setTeacherName(sysUserService.getById(teacherId).getRealName());
+                taExamCourseTeacher.setMinScore(BigDecimal.valueOf(minScore));
+                taExamCourseTeacher.setMaxScore(BigDecimal.valueOf(maxScore));
+                taExamCourseTeacher.setAvgScore(BigDecimal.valueOf(avgScore));
+                taExamCourseTeacher.setUpperQuartile(BigDecimal.valueOf(upperQuartile));
+                taExamCourseTeacher.setMedian(BigDecimal.valueOf(median));
+                taExamCourseTeacher.setLowerQuartile(BigDecimal.valueOf(lowerQuartile));
+                taExamCourseTeacher.setMode(mode);
+                taExamCourseTeacher.setStandardDeviation(BigDecimal.valueOf(standardDeviation));
+                taExamCourseTeacher.setRelativePosition(BigDecimal.valueOf(relativePosition));
+                taExamCourseTeacher.setTotalCount(totalCount);
+                taExamCourseTeacher.setRealityCount(realityCount);
+                taExamCourseTeacher.setAbsentCount(absentCount);
+                taExamCourseTeacherList.add(taExamCourseTeacher);
+            }
+            taExamCourseTeacherService.saveBatch(taExamCourseTeacherList);
+        }
+        return " 't_a_exam_course_teacher'表构建完毕 ";
+    }
+
+    /**
+     * 计算百分位等级
+     *
+     * @param lowCount   低于我的成绩的人数
+     * @param sameCount  和我成绩相同的人数
+     * @param totalCount 总人数
+     * @return 百分位等级
+     */
+    private int handlePercentGrade(BigDecimal lowCount, BigDecimal sameCount, BigDecimal totalCount) {
+        // ((lowCount + sameCount * 0.5) / totalCount) * 100
+        BigDecimal percentGrade = (lowCount.add(sameCount.multiply(new BigDecimal("0.5"))))
+                .divide(totalCount,4,BigDecimal.ROUND_HALF_DOWN).multiply(new BigDecimal("100"));
+        int result = percentGrade.setScale(0,BigDecimal.ROUND_HALF_DOWN).intValue();
+        if (result == 100) {
+            result = 99;
+        }
+        if (result == 0) {
+            result = 1;
+        }
+        return result;
+    }
+
+    /**
+     * 处理计算百分等级和难度等级档位
+     *
+     * @param type  档位类型(百分等级、难度系数)
+     * @param value 值
+     * @return 档位
+     */
+    private String handleLevel(Long examId,String courseCode, String type, double value) {
+        List<TBCommonLevelConfig> levelList = tbCommonLevelConfigService.list(new QueryWrapper<TBCommonLevelConfig>().lambda()
+                .eq(TBCommonLevelConfig::getExamId,examId)
+                .eq(TBCommonLevelConfig::getCourseCode,courseCode)
+                .eq(TBCommonLevelConfig::getLevelType,type));
+        String level = "";
+        if ("百分等级".equals(type) || "难度等级".equals(type)) {
+            for (TBCommonLevelConfig levelTemp : levelList) {
+                Map<String, Object> scopeMap = AnalyzeScopeUtil.analyzeScope(levelTemp.getScope());
+                if ("(".equals(scopeMap.get("minSign")) && ")".equals(scopeMap.get("maxSign"))) {
+                    if (Double.parseDouble(String.valueOf(scopeMap.get("minValue"))) < value && value < Double.parseDouble(String.valueOf(scopeMap.get("maxValue")))) {
+                        level = levelTemp.getInterpret();
+                    }
+                } else if ("(".equals(scopeMap.get("minSign")) && "]".equals(scopeMap.get("maxSign"))) {
+                    if (Double.parseDouble(String.valueOf(scopeMap.get("minValue"))) < value && value <= Double.parseDouble(String.valueOf(scopeMap.get("maxValue")))) {
+                        level = levelTemp.getInterpret();
+                    }
+                } else if ("[".equals(scopeMap.get("minSign")) && ")".equals(scopeMap.get("maxSign"))) {
+                    if (Double.parseDouble(String.valueOf(scopeMap.get("minValue"))) <= value && value < Double.parseDouble(String.valueOf(scopeMap.get("maxValue")))) {
+                        level = levelTemp.getInterpret();
+                    }
+                } else if ("[".equals(scopeMap.get("minSign")) && "]".equals(scopeMap.get("maxSign"))) {
+                    if (Double.parseDouble(String.valueOf(scopeMap.get("minValue"))) <= value && value <= Double.parseDouble(String.valueOf(scopeMap.get("maxValue")))) {
+                        level = levelTemp.getInterpret();
+                    }
+                }
+            }
+            if (level == null || level.length() == 0) {
+                throw ExceptionResultEnum.ERROR.exception("范围解析异常");
+            }
+        } else {
+            throw ExceptionResultEnum.ERROR.exception("没有进行计算的等级类型 : " + type);
+        }
+        return level;
+    }
+
+    /**
+     * 构建和学院比较的有关信息(超过学院百分比、排名、排名等级)
+     * @param taExamCourseRecord 该学生数据
+     * @param taExamCourseRecordList 该课程下学生数据
+     */
+    private void buildColData(TAExamCourseRecord taExamCourseRecord, List<TAExamCourseRecord> taExamCourseRecordList) {
+
+        //查询出该学生所在学院的全体学生在该科目的考试情况
+        List<TAExamCourseRecord> examRecordSameCol = taExamCourseRecordList.stream()
+                .filter(e -> taExamCourseRecord.getInspectCollegeId().equals(e.getInspectCollegeId())).collect(Collectors.toList()); // 同考察学院考生数据
+
+        //计算超过学院百分比
+        double lowCount = examRecordSameCol.stream().filter(e -> e.getAssignedScore().compareTo(taExamCourseRecord.getAssignedScore()) < 0).count();
+        BigDecimal overCollegeRate;
+        if (examRecordSameCol.size() > 1) {
+            overCollegeRate = BigDecimal.valueOf(lowCount).divide(BigDecimal.valueOf(examRecordSameCol.size() - 1),4,BigDecimal.ROUND_HALF_DOWN);
+        } else {
+            overCollegeRate = BigDecimal.ONE;
+        }
+        taExamCourseRecord.setOverCollegeRate(overCollegeRate);
+
+        //计算在学院的排名
+        double overCount = examRecordSameCol.stream().filter(e -> e.getAssignedScore().compareTo(taExamCourseRecord.getAssignedScore()) > 0).count();
+        double myNumber = overCount + 1;
+        taExamCourseRecord.setColRank((int) myNumber);
+
+        //计算在学院排名的档次
+        double size = examRecordSameCol.size();
+        List<TBCommonRankLevelConfig> tbCommonRankLevelConfigList = tbCommonRankLevelConfigService.list(new QueryWrapper<TBCommonRankLevelConfig>().lambda()
+                .eq(TBCommonRankLevelConfig::getExamId,taExamCourseRecord.getExamId())
+                .eq(TBCommonRankLevelConfig::getCourseCode,taExamCourseRecord.getCourseCode()));
+
+
+
+        if (tbCommonRankLevelConfigList.size() < 1) {
+            throw ExceptionResultEnum.ERROR.exception("试卷基础信息不匹配");
+        }
+        String myLevel = "";
+        if (size < tbCommonRankLevelConfigList.size()) {
+            myLevel = String.valueOf(tbCommonRankLevelConfigList.get((int) (myNumber - 1)).getLevel());
+        } else {
+            for (TBCommonRankLevelConfig temp : tbCommonRankLevelConfigList) {
+
+                Map<String, Object> scopeMap = AnalyzeScopeUtil.analyzeScope(temp.getScope());
+                if ("(".equals(scopeMap.get("minSign")) && ")".equals(scopeMap.get("maxSign"))) {
+                    if (Double.parseDouble(String.valueOf(scopeMap.get("minValue"))) * size < myNumber && myNumber < Double.parseDouble(String.valueOf(scopeMap.get("maxValue"))) * size) {
+                        myLevel = temp.getLevel();
+                    }
+                } else if ("(".equals(scopeMap.get("minSign")) && "]".equals(scopeMap.get("maxSign"))) {
+                    if (Double.parseDouble(String.valueOf(scopeMap.get("minValue"))) * size < myNumber && myNumber <= Double.parseDouble(String.valueOf(scopeMap.get("maxValue"))) * size) {
+                        myLevel = temp.getLevel();
+                    }
+                } else if ("[".equals(scopeMap.get("minSign")) && ")".equals(scopeMap.get("maxSign"))) {
+                    if (Double.parseDouble(String.valueOf(scopeMap.get("minValue"))) * size <= myNumber && myNumber < Double.parseDouble(String.valueOf(scopeMap.get("maxValue"))) * size) {
+                        myLevel = temp.getLevel();
+                    }
+                } else if ("[".equals(scopeMap.get("minSign")) && "]".equals(scopeMap.get("maxSign"))) {
+                    if (Double.parseDouble(String.valueOf(scopeMap.get("minValue"))) * size <= myNumber && myNumber <= Double.parseDouble(String.valueOf(scopeMap.get("maxValue"))) * size) {
+                        myLevel = temp.getLevel();
+                    }
+                }
+            }
+        }
+        if (myLevel == null || myLevel.length() == 0) {
+            throw ExceptionResultEnum.ERROR.exception("范围解析异常");
+        }
+        taExamCourseRecord.setRankLevel(myLevel);
+    }
+
+    /**
+     * 计算每个考察点所对应的该考试所有题目信息集合(如果要仅记录本次考试匹配到的考察点,那么要判断只有当paperList.size() > 0的结果才put进Map键值对)
+     * 通过模块枚举类进行匹配,可以在枚举类横向扩展维度但要和paper表结构对应
+     *
+     * @param dimensionDatasource 知识点数据源
+     * @param tbPaperStructList   试卷结构数据源
+     * @param examId  考试id
+     * @param courseCode  课程编号
+     * @return 键值对 (类型-考察点 -> 考察此考察点的题目信息集合) 例如 :”知识模块-A“,List<>
+     */
+    private Map<String, List<TBPaperStruct>> handlePointToPaper(List<TBDimension> dimensionDatasource, List<TBPaperStruct> tbPaperStructList, Long examId, String courseCode) throws NoSuchFieldException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
+        Map<String, List<TBPaperStruct>> pointToPaper = new HashMap<>();
+
+        // 模块配置信息
+        List<TBModuleConfig> tbModuleConfigList = tbModuleConfigService.findDistinctModuleInfoByExamIdAndCourseCode(examId, courseCode);
+        if (tbModuleConfigList.size() < 1){
+            throw ExceptionResultEnum.ERROR.exception("基础模块信息异常");
+        }
+
+        for (TBModuleConfig value : tbModuleConfigList) {
+
+            //每个考察点所对应的题目集合
+            List<TBDimension> pointList = dimensionDatasource
+                    .stream().filter(e -> value.getModuleType().equals(e.getDimensionType())).collect(Collectors.toList());  //对应某个模块的考察点集合
+
+            Set<String> keysOne = pointList.stream().map(TBDimension::getCodePrimary).collect(Collectors.toSet());   //考察点一级维度不重复的code集合
+            Set<String> keysTwo = pointList.stream().map(TBDimension::getCodeSecond).collect(Collectors.toSet());   //考察点二级维度不重复的code集合
+
+            for (String tmpOne : keysOne) {
+                List<TBPaperStruct> paperStructList = new ArrayList<>();
+                for (TBPaperStruct paperStruct : tbPaperStructList) {
+                    Field field = paperStruct.getClass().getDeclaredField(value.getAttribute()); //获取该模块对应试卷结构中的属性
+                    Method getMethod = paperStruct.getClass().getDeclaredMethod("get" + ConversionUtils.initCap(field.getName())); //获取该属性的get方法
+                    String dimensions = (String) getMethod.invoke(paperStruct); //调用该属性的get方法获取改题目的考察点
+                    if (dimensions != null && dimensions.length() > 0) {
+                        if (dimensions.contains(tmpOne)) {
+                            paperStructList.add(paperStruct);  //如果该题目包含考察点,则记录该题目
+                        }
+                    }
+                }
+                if (paperStructList.size() > 0) {
+                    // 只记录试卷结构中出现的考察点包含的题目
+                    pointToPaper.put(value.getModuleType() + "-" + tmpOne, paperStructList);
+                }
+            }
+
+            for (String tmpTwo : keysTwo) {
+                List<TBPaperStruct> paperStructList = new ArrayList<>();
+                for (TBPaperStruct paperStruct : tbPaperStructList) {
+                    Field field = paperStruct.getClass().getDeclaredField(value.getAttribute());
+                    Method getMethod = paperStruct.getClass().getDeclaredMethod("get" + ConversionUtils.initCap(field.getName()));
+                    String dimensions = (String) getMethod.invoke(paperStruct);
+                    if (dimensions != null && dimensions.length() > 0) {
+                        if (Arrays.asList(dimensions.split(",")).contains(tmpTwo)) {
+                            paperStructList.add(paperStruct);
+                        }
+                    }
+                }
+                if (paperStructList.size() > 0) {
+                    // 只记录试卷结构中出现的考察点包含的题目
+                    pointToPaper.put(value.getModuleType() + "-" + tmpTwo, paperStructList);
+                }
+            }
+        }
+        return pointToPaper;
+    }
+
+    /**
+     * 计算每个考察模块对应的题目集合
+     *
+     * @param dimensionDatasource 知识点数据源
+     * @param tbPaperStructList   试卷结构数据源
+     * @param examId  考试id
+     * @param courseCode  课程编号
+     * @return 键值对 (考察模块 -> 考察此考模块的题目信息集合) 例如 :”知识模块“,List<>
+     * @throws Exception 反射异常
+     */
+    private Map<String, List<TBPaperStruct>> handleModuleToPaper(List<TBDimension> dimensionDatasource, List<TBPaperStruct> tbPaperStructList, Long examId, String courseCode) throws Exception {
+        Map<String, List<TBPaperStruct>> result = new HashMap<>();
+
+        // 模块配置信息
+        List<TBModuleConfig> tbModuleConfigList = tbModuleConfigService.findDistinctModuleInfoByExamIdAndCourseCode(examId, courseCode);
+        if (tbModuleConfigList.size() < 1){
+            throw ExceptionResultEnum.ERROR.exception("基础模块信息异常");
+        }
+
+        List<String> realityTypes = dimensionDatasource.stream().map(TBDimension::getDimensionType).collect(Collectors.toList()); // 以知识点表中的模块类型为准
+//        int tmp = 0;
+        for (TBModuleConfig module : tbModuleConfigList) {
+            String moduleType = module.getModuleType(); // 模块名称
+            if (realityTypes.contains(moduleType)) {
+//                tmp++;
+                String attribute = module.getAttribute(); // 对应paper表列名称
+                List<TBPaperStruct> paperStructList = new ArrayList<>();
+
+                for (TBPaperStruct paperStruct : tbPaperStructList) {
+                    Field field = paperStruct.getClass().getDeclaredField(attribute);
+                    Method getMethod = paperStruct.getClass().getDeclaredMethod("get" + ConversionUtils.initCap(field.getName()));
+                    String value = (String) getMethod.invoke(paperStruct);
+                    if (value != null && value.length() != 0) {
+                        paperStructList.add(paperStruct);
+                    }
+                }
+                result.put(moduleType, paperStructList);
+            }
+        }
+        return result;
+    }
+
+    /**
+     * 计算每个模块或考察点在该考试中的分数
+     * (其实就是计算试题集合总分)
+     *
+     * @param questionMap 考察点或模块对应的题目信息集合
+     * @return 键值对 (考察点 -> 该考察点在此次考试所占分数) 例如 :”知识模块-A“,46.0000、(模块 -> 该考察点在此次考试所占分数) 例如 :”能力模块“,75.0000
+     */
+    private Map<String, Object> handleEveryPointTotalScore(Map<String, List<TBPaperStruct>> questionMap) {
+        Map<String, Object> result = new HashMap<>();
+        for (String s : questionMap.keySet()) {
+            List<TBPaperStruct> paperList = questionMap.get(s);
+            double totalScore = paperList.stream().collect(Collectors.summarizingDouble(e -> e.getFullScore().doubleValue())).getSum();
+            result.put(s, totalScore);
+        }
+        return result;
+    }
+
+    /**
+     * 根据考察点得分率计算该考察点的熟练度
+     *
+     * @param examId  考试id
+     * @param courseCode  课程编号
+     * @param dimensionType 考察点类型
+     * @param value   得分率
+     * @return 熟练度等级
+     */
+    private String handleModuleProficiency(Long examId, String courseCode, String dimensionType, double value) {
+        List<TBModuleProficiency> tbModuleProficiencyList = tbModuleProficiencyService.list(new QueryWrapper<TBModuleProficiency>().lambda()
+                .eq(TBModuleProficiency::getExamId,examId)
+                .eq(TBModuleProficiency::getCourseCode,courseCode)
+                .eq(TBModuleProficiency::getModuleType,dimensionType));
+
+        if (tbModuleProficiencyList.size() < 1) {
+            throw ExceptionResultEnum.ERROR.exception("模块二级维度熟练度配置信息不存在");
+        }
+        String level = "";
+        for (TBModuleProficiency tbModuleProficiency : tbModuleProficiencyList) {
+            if (tbModuleProficiency.getScope() == null) {
+                continue;
+            }
+            Map<String, Object> scopeMap = AnalyzeScopeUtil.analyzeScope(tbModuleProficiency.getScope());
+            if ("(".equals(scopeMap.get("minSign")) && ")".equals(scopeMap.get("maxSign"))) {
+                if (Double.parseDouble(String.valueOf(scopeMap.get("minValue"))) < value && value < Double.parseDouble(String.valueOf(scopeMap.get("maxValue")))) {
+                    level = tbModuleProficiency.getLevel();
+                }
+            } else if ("(".equals(scopeMap.get("minSign")) && "]".equals(scopeMap.get("maxSign"))) {
+                if (Double.parseDouble(String.valueOf(scopeMap.get("minValue"))) < value && value <= Double.parseDouble(String.valueOf(scopeMap.get("maxValue")))) {
+                    level = tbModuleProficiency.getLevel();
+                }
+            } else if ("[".equals(scopeMap.get("minSign")) && ")".equals(scopeMap.get("maxSign"))) {
+                if (Double.parseDouble(String.valueOf(scopeMap.get("minValue"))) <= value && value < Double.parseDouble(String.valueOf(scopeMap.get("maxValue")))) {
+                    level = tbModuleProficiency.getLevel();
+                }
+            } else if ("[".equals(scopeMap.get("minSign")) && "]".equals(scopeMap.get("maxSign"))) {
+                if (Double.parseDouble(String.valueOf(scopeMap.get("minValue"))) <= value && value <= Double.parseDouble(String.valueOf(scopeMap.get("maxValue")))) {
+                    level = tbModuleProficiency.getLevel();
+                }
+            }
+        }
+        return level;
+    }
+
+    /**
+     * 处理学生在该模块成绩在该学院的排名等级
+     *
+     * @param examId  考试id
+     * @param courseCode  考试编号
+     * @param module 模块类型
+     * @param value  值(排名、得分率、百分等级)
+     * @param size   该学院最低分排名(当其不为排名时,赋值-1)
+     * @return 排名等级编号
+     */
+    private String handleModuleRankLevel(Long examId, String courseCode, String module, double value, double size) {
+        List<TBModuleConfig> tbModuleConfigList = tbModuleConfigService.list(new QueryWrapper<TBModuleConfig>().lambda()
+                .eq(TBModuleConfig::getExamId,examId)
+                .eq(TBModuleConfig::getCourseCode,courseCode)
+                .eq(TBModuleConfig::getModuleType,module));
+
+        String result = null;
+        if (size < tbModuleConfigList.size() && size > 0) {
+            tbModuleConfigList = tbModuleConfigList.stream()
+                    .sorted((o1, o2) -> o1.getLevelCode().compareToIgnoreCase(o2.getLevelCode()))
+                    .collect(Collectors.toList());
+            result = tbModuleConfigList.get((int) (size - 1)).getLevelCode();
+        } else {
+            if (size < 0) {
+                size = -size;
+            }
+            for (TBModuleConfig tbModuleConfig : tbModuleConfigList) {
+                Map<String, Object> scopeMap = AnalyzeScopeUtil.analyzeScope(tbModuleConfig.getScope());
+                if ("(".equals(scopeMap.get("minSign")) && ")".equals(scopeMap.get("maxSign"))) {
+                    if (Double.parseDouble(String.valueOf(scopeMap.get("minValue"))) * size < value && value < Double.parseDouble(String.valueOf(scopeMap.get("maxValue"))) * size) {
+                        result = tbModuleConfig.getLevelCode();
+                    }
+                } else if ("(".equals(scopeMap.get("minSign")) && "]".equals(scopeMap.get("maxSign"))) {
+                    if (Double.parseDouble(String.valueOf(scopeMap.get("minValue"))) * size < value && value <= Double.parseDouble(String.valueOf(scopeMap.get("maxValue"))) * size) {
+                        result = tbModuleConfig.getLevelCode();
+                    }
+                } else if ("[".equals(scopeMap.get("minSign")) && ")".equals(scopeMap.get("maxSign"))) {
+                    if (Double.parseDouble(String.valueOf(scopeMap.get("minValue"))) * size <= value && value < Double.parseDouble(String.valueOf(scopeMap.get("maxValue"))) * size) {
+                        result = tbModuleConfig.getLevelCode();
+                    }
+                } else if ("[".equals(scopeMap.get("minSign")) && "]".equals(scopeMap.get("maxSign"))) {
+                    if (Double.parseDouble(String.valueOf(scopeMap.get("minValue"))) * size <= value && value <= Double.parseDouble(String.valueOf(scopeMap.get("maxValue"))) * size) {
+                        result = tbModuleConfig.getLevelCode();
+                    }
+                }
+            }
+        }
+        if (result == null || result.length() == 0) {
+            throw ExceptionResultEnum.ERROR.exception("范围解析异常");
+        }
+        return result;
+    }
+
+    /**
+     * 根据得分率计算每道题目的难度
+     *
+     * @param examId  考试id
+     * @param courseCode 课程编号
+     * @param scoreRate 题目得分率
+     * @return 难度
+     */
+    private String analyzeDifficult(Long examId, String courseCode, double scoreRate) {
+        List<TBCommonLevelConfig> levelConfigList = tbCommonLevelConfigService.list(new QueryWrapper<TBCommonLevelConfig>().lambda()
+                .eq(TBCommonLevelConfig::getExamId,examId)
+                .eq(TBCommonLevelConfig::getCourseCode,courseCode)
+                .eq(TBCommonLevelConfig::getLevelType,"难度等级"));
+        String difficult = "";
+        for (TBCommonLevelConfig levelConfig : levelConfigList) {
+            Map<String, Object> scopeMap = AnalyzeScopeUtil.analyzeScope(levelConfig.getScope());
+            String minSign = String.valueOf(scopeMap.get("minSign"));
+            String maxSign = String.valueOf(scopeMap.get("maxSign"));
+            double minValue = Double.parseDouble(String.valueOf(scopeMap.get("minValue")));
+            double maxValue = Double.parseDouble(String.valueOf(scopeMap.get("maxValue")));
+            if ("(".equals(minSign) && ")".equals(maxSign)) {
+                if (minValue < scoreRate && scoreRate < maxValue) {
+                    difficult = levelConfig.getInterpret();
+                }
+            } else if ("(".equals(minSign) && "]".equals(maxSign)) {
+                if (minValue < scoreRate && scoreRate <= maxValue) {
+                    difficult = levelConfig.getInterpret();
+                }
+            } else if ("[".equals(minSign) && ")".equals(maxSign)) {
+                if (minValue <= scoreRate && scoreRate < maxValue) {
+                    difficult = levelConfig.getInterpret();
+                }
+            } else if ("[".equals(minSign) && "]".equals(maxSign)) {
+                if (minValue <= scoreRate && scoreRate <= maxValue) {
+                    difficult = levelConfig.getInterpret();
+                }
+            }
+        }
+        if (difficult == null || difficult.length() < 1) {
+            difficult = "容易";
+        }
+        return difficult;
+    }
+
+    /**
+     * 计算某个小题的题目鉴别度
+     *
+     * @param oneQuestionAnswerDetailList 某个小题的所有参考学生作答情况列表(且按照参考学生百分等级降序排列)
+     * @param fullScore                   该小题总分
+     * @return 鉴别度
+     */
+    private double calculateValidity(List<ValidAnswerDetailDto> oneQuestionAnswerDetailList, double fullScore) {
+        List<ValidAnswerDetailDto> sortList = oneQuestionAnswerDetailList.stream().sorted(((o1, o2) -> {
+            double compare1 = o1.getPercentGrade();
+            double compare2 = o2.getPercentGrade();
+            return Double.compare(compare2, compare1);
+        })).collect(Collectors.toList());
+
+        int rank = 0;
+        int number = 0;
+        double value = 10000;
+        for (ValidAnswerDetailDto temp : sortList) {
+            double compareValue = temp.getPercentGrade();
+            number++;
+            if (compareValue < value) {
+                rank = number;
+                value = compareValue;
+            }
+            temp.setRank(rank);
+        }
+        double endRank = sortList.get(sortList.size() - 1).getRank();
+        double topRank = ValidityEnum.VALIDITY_FOR_RANK.getTopLimitPercent() * endRank;
+        double lowRank = ValidityEnum.VALIDITY_FOR_RANK.getLowLimitPercent() * endRank;
+
+        // 计算题目效度
+        double topScopeAvgScoreRate = sortList.stream()
+                .filter(e -> topRank >= e.getRank())
+                .collect(Collectors.summarizingDouble(e -> e.getScore().doubleValue()))
+                .getAverage() / fullScore; // 优秀部分统计有效区间平均得分率
+
+        double lowScopeAvgScoreRate = sortList.stream()
+                .filter(e -> lowRank <= e.getRank())
+                .collect(Collectors.summarizingDouble(e -> e.getScore().doubleValue()))
+                .getAverage() / fullScore; // 较差部分统计有效区间平均得分率
+
+        return topScopeAvgScoreRate - lowScopeAvgScoreRate;
+    }
+}

+ 25 - 0
teachcloud-report-business/src/main/java/com/qmth/teachcloud/report/business/service/impl/TAExamCourseCollegeInspectDioServiceImpl.java

@@ -1,10 +1,18 @@
 package com.qmth.teachcloud.report.business.service.impl;
 
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.qmth.teachcloud.common.contant.SystemConstant;
+import com.qmth.teachcloud.common.enums.ExceptionResultEnum;
+import com.qmth.teachcloud.common.util.ServletUtil;
 import com.qmth.teachcloud.report.business.entity.TAExamCourseCollegeInspectDio;
 import com.qmth.teachcloud.report.business.mapper.TAExamCourseCollegeInspectDioMapper;
 import com.qmth.teachcloud.report.business.service.TAExamCourseCollegeInspectDioService;
+import com.qmth.teachcloud.report.business.service.TBExamService;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import javax.annotation.Resource;
+import java.util.List;
 
 /**
  * <p>
@@ -16,5 +24,22 @@ import org.springframework.stereotype.Service;
  */
 @Service
 public class TAExamCourseCollegeInspectDioServiceImpl extends ServiceImpl<TAExamCourseCollegeInspectDioMapper, TAExamCourseCollegeInspectDio> implements TAExamCourseCollegeInspectDioService {
+    @Resource
+    private TAExamCourseCollegeInspectDioMapper taExamCourseCollegeInspectDioMapper;
+    @Resource
+    private TBExamService tbExamService;
 
+    @Transactional(rollbackFor = Exception.class)
+    @Override
+    public void insertByTAExamCourseRecordDio(Long examId, String courseCode) {
+        if (examId == 0 || courseCode == null || courseCode.length() == 0){
+            throw ExceptionResultEnum.ERROR.exception("参数异常");
+        }
+        List<TAExamCourseCollegeInspectDio> taExamCourseCollegeInspectDioList = taExamCourseCollegeInspectDioMapper.findByTAExamCourseRecordDio(examId,courseCode);
+        for (TAExamCourseCollegeInspectDio taExamCourseCollegeInspectDio : taExamCourseCollegeInspectDioList) {
+            taExamCourseCollegeInspectDio.setSchoolId(tbExamService.getById(taExamCourseCollegeInspectDio.getExamId()).getSchoolId());
+            taExamCourseCollegeInspectDio.setId(SystemConstant.getDbUuid());
+        }
+        this.saveBatch(taExamCourseCollegeInspectDioList);
+    }
 }

+ 18 - 0
teachcloud-report-business/src/main/java/com/qmth/teachcloud/report/business/service/impl/TAExamCourseCollegeInspectServiceImpl.java

@@ -1,11 +1,15 @@
 package com.qmth.teachcloud.report.business.service.impl;
 
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.qmth.teachcloud.report.business.bean.result.TAExamCourseCollegeInspectResult;
 import com.qmth.teachcloud.report.business.entity.TAExamCourseCollegeInspect;
 import com.qmth.teachcloud.report.business.mapper.TAExamCourseCollegeInspectMapper;
 import com.qmth.teachcloud.report.business.service.TAExamCourseCollegeInspectService;
 import org.springframework.stereotype.Service;
 
+import javax.annotation.Resource;
+import java.util.List;
+
 /**
  * <p>
  * 参考课程考察学院维度分析表 服务实现类
@@ -17,4 +21,18 @@ import org.springframework.stereotype.Service;
 @Service
 public class TAExamCourseCollegeInspectServiceImpl extends ServiceImpl<TAExamCourseCollegeInspectMapper, TAExamCourseCollegeInspect> implements TAExamCourseCollegeInspectService {
 
+    @Resource
+    TAExamCourseCollegeInspectMapper taExamCourseCollegeInspectMapper;
+
+    /**
+     * 查找科目维度
+     *
+     * @param examId
+     * @param courseCode
+     * @return
+     */
+    @Override
+    public List<TAExamCourseCollegeInspectResult> findCourseDescriptiveStatisticsForCollege(Long examId, String courseCode) {
+        return taExamCourseCollegeInspectMapper.findCourseDescriptiveStatisticsForCollege(examId, courseCode);
+    }
 }

+ 15 - 0
teachcloud-report-business/src/main/java/com/qmth/teachcloud/report/business/service/impl/TAExamCourseCollegeTeacherServiceImpl.java

@@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.qmth.teachcloud.common.util.ServletUtil;
+import com.qmth.teachcloud.report.business.bean.result.TAExamCourseTeacherResult;
 import com.qmth.teachcloud.report.business.bean.result.TeacherClassRankResult;
 import com.qmth.teachcloud.report.business.bean.result.TeacherMyClassRankResult;
 import com.qmth.teachcloud.report.business.entity.TAExamCourseCollegeTeacher;
@@ -12,6 +13,7 @@ import com.qmth.teachcloud.report.business.service.TAExamCourseCollegeTeacherSer
 import org.springframework.stereotype.Service;
 
 import javax.annotation.Resource;
+import java.util.List;
 
 /**
  * <p>
@@ -50,4 +52,17 @@ public class TAExamCourseCollegeTeacherServiceImpl extends ServiceImpl<TAExamCou
         IPage<TAExamCourseCollegeTeacher> listPage = taExamCourseCollegeTeacherMapper.listAllTeacherClassRank(page, schoolId, semester, examId, teachCollegeId, courseCode, teacherId);
         return listPage;
     }
+
+    /**
+     * 查询老师得分
+     *
+     * @param examId
+     * @param courseCode
+     * @param collegeId
+     * @return
+     */
+    @Override
+    public List<TAExamCourseTeacherResult> findTeacherInfo(Long examId, String courseCode, Long collegeId) {
+        return taExamCourseCollegeTeacherMapper.findTeacherInfo(examId, courseCode, collegeId);
+    }
 }

+ 81 - 10
teachcloud-report-business/src/main/java/com/qmth/teachcloud/report/business/service/impl/TAExamCourseServiceImpl.java

@@ -1,25 +1,24 @@
 package com.qmth.teachcloud.report.business.service.impl;
 
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.qmth.teachcloud.common.entity.SysUser;
+import com.qmth.teachcloud.common.enums.ExceptionResultEnum;
 import com.qmth.teachcloud.common.util.ServletUtil;
-import com.qmth.teachcloud.report.business.bean.result.TAExamCourseResult;
-import com.qmth.teachcloud.report.business.entity.TAExamCourse;
-import com.qmth.teachcloud.report.business.entity.TAExamCourseRecord;
+import com.qmth.teachcloud.report.business.bean.result.*;
+import com.qmth.teachcloud.report.business.entity.*;
 import com.qmth.teachcloud.report.business.enums.PublishStatusEnum;
 import com.qmth.teachcloud.report.business.enums.SemesterEnum;
 import com.qmth.teachcloud.report.business.mapper.TAExamCourseMapper;
 import com.qmth.teachcloud.report.business.mapper.TAExamCourseRecordMapper;
-import com.qmth.teachcloud.report.business.service.TAExamCourseService;
+import com.qmth.teachcloud.report.business.service.*;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
 import javax.annotation.Resource;
 import java.math.BigDecimal;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 
 /**
  * <p>
@@ -38,6 +37,27 @@ public class TAExamCourseServiceImpl extends ServiceImpl<TAExamCourseMapper, TAE
     @Resource
     TAExamCourseRecordMapper taExamCourseRecordMapper;
 
+    @Resource
+    TBPaperService tbPaperService;
+
+    @Resource
+    TAExamCourseCollegeInspectService taExamCourseCollegeInspectService;
+
+    @Resource
+    TBDimensionService tbDimensionService;
+
+    @Resource
+    TBCommonLevelConfigService tbCommonLevelConfigService;
+
+    @Resource
+    TBPaperStructService tbPaperStructService;
+
+    @Resource
+    TBAnswerService tbAnswerService;
+
+    @Resource
+    TAExamCourseCollegeTeacherService taExamCourseCollegeTeacherService;
+
     /**
      * 开课课程考试总览列表接口
      *
@@ -94,9 +114,9 @@ public class TAExamCourseServiceImpl extends ServiceImpl<TAExamCourseMapper, TAE
             // 本分数段人数
             long totalScoreCount = taExamCourseRecords.stream().filter(m -> m.getAssignedScore().doubleValue() >= startScore && m.getAssignedScore().doubleValue() <= endScore).count();
             // 应届有效人数
-            long totalCurrentCount = taExamCourseRecords.stream().filter(m -> m.getCurrent()).count();
+            long totalCurrentCount = taExamCourseRecords.stream().filter(TAExamCourseRecord::getStudentCurrent).count();
             // 本分数段应届有效人数
-            long totalScoreCurrentCount = taExamCourseRecords.stream().filter(m -> m.getCurrent() && m.getAssignedScore().doubleValue() >= startScore && m.getAssignedScore().doubleValue() <= endScore).count();
+            long totalScoreCurrentCount = taExamCourseRecords.stream().filter(m -> m.getStudentCurrent() && m.getAssignedScore().doubleValue() >= startScore && m.getAssignedScore().doubleValue() <= endScore).count();
             Map<String, Object> objectMap = new HashMap<>();
             objectMap.put("scores", String.join(",", str));
             objectMap.put("totalRealityCount", totalRealityCount);
@@ -108,4 +128,55 @@ public class TAExamCourseServiceImpl extends ServiceImpl<TAExamCourseMapper, TAE
         map.put("grades", mapList);
         return map;
     }
+
+    /**
+     * 考查课程考试分析接口
+     *
+     * @param examId
+     * @param semester
+     * @param courseCode
+     * @param schoolId
+     * @return
+     */
+    @Override
+    public List<Object> surveyInspectAnalyseView(Long examId, SemesterEnum semester, String courseCode, Long schoolId) {
+        SysUser sysUser = (SysUser) ServletUtil.getRequestUser();
+        if (Objects.isNull(sysUser)) {
+            throw ExceptionResultEnum.NOT_LOGIN.exception();
+        }
+        //查找试卷
+        QueryWrapper<TBPaper> tbPaperQueryWrapper = new QueryWrapper<>();
+        tbPaperQueryWrapper.lambda().eq(TBPaper::getExamId, examId)
+                .eq(TBPaper::getCourseCode, courseCode);
+        List<TBPaper> tbPaperList = tbPaperService.list(tbPaperQueryWrapper);
+
+        //查找科目学院维度
+        List<TAExamCourseCollegeInspectResult> taExamCourseCollegeInspectResultList = taExamCourseCollegeInspectService.findCourseDescriptiveStatisticsForCollege(examId, courseCode);
+
+        //查找维度
+        List<CourseDimensionResult> courseDimensionResultList = tbDimensionService.findDimensionInfo(examId, courseCode, sysUser.getOrgId());
+
+        //查找难易度
+        QueryWrapper<TBCommonLevelConfig> tbCommonLevelConfigQueryWrapper = new QueryWrapper<>();
+        tbCommonLevelConfigQueryWrapper.lambda().eq(TBCommonLevelConfig::getExamId, examId)
+                .eq(TBCommonLevelConfig::getCourseCode, courseCode)
+                .eq(TBCommonLevelConfig::getLevelType, "难度等级");
+        List<TBCommonLevelConfig> tbCommonLevelConfigList = tbCommonLevelConfigService.list(tbCommonLevelConfigQueryWrapper);
+
+        //查找试卷结构
+        List<TBPaperStructResult> tbPaperStructList = tbPaperStructService.findQuestionInfo(examId, courseCode);
+
+        //查找答题记录
+        List<TBAnswerResult> tbAnswerResultList = tbAnswerService.findValidAnswerDetail(examId, courseCode);
+
+        //查找老师得分
+        List<TAExamCourseTeacherResult> taExamCourseTeacherResultList = taExamCourseCollegeTeacherService.findTeacherInfo(examId, courseCode, sysUser.getOrgId());
+
+        //查找维度
+        QueryWrapper<TBDimension> tbDimensionQueryWrapper = new QueryWrapper<>();
+        tbDimensionQueryWrapper.lambda().eq(TBDimension::getExamId, examId)
+                .eq(TBDimension::getCourseCode, courseCode);
+        List<TBDimension> tbDimensionList = tbDimensionService.list(tbDimensionQueryWrapper);
+        return null;
+    }
 }

+ 30 - 0
teachcloud-report-business/src/main/java/com/qmth/teachcloud/report/business/service/impl/TBAnswerServiceImpl.java

@@ -1,11 +1,17 @@
 package com.qmth.teachcloud.report.business.service.impl;
 
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.qmth.teachcloud.report.business.bean.dto.query.BasicAnswerDto;
+import com.qmth.teachcloud.report.business.bean.dto.query.ValidAnswerDetailDto;
+import com.qmth.teachcloud.report.business.bean.result.TBAnswerResult;
 import com.qmth.teachcloud.report.business.entity.TBAnswer;
 import com.qmth.teachcloud.report.business.mapper.TBAnswerMapper;
 import com.qmth.teachcloud.report.business.service.TBAnswerService;
 import org.springframework.stereotype.Service;
 
+import javax.annotation.Resource;
+import java.util.List;
+
 /**
  * <p>
  * 基础考生作答记录详情表 服务实现类
@@ -17,4 +23,28 @@ import org.springframework.stereotype.Service;
 @Service
 public class TBAnswerServiceImpl extends ServiceImpl<TBAnswerMapper, TBAnswer> implements TBAnswerService {
 
+    @Resource
+    private TBAnswerMapper tbAnswerMapper;
+
+    @Override
+    public List<BasicAnswerDto> findByPaperId(Long paperId) {
+        return tbAnswerMapper.findByPaperId(paperId);
+    }
+
+    @Override
+    public List<ValidAnswerDetailDto> findValid(Long examId, String courseCode) {
+        return tbAnswerMapper.findValid(examId, courseCode);
+    }
+
+    /**
+     * 查找有效答案
+     *
+     * @param examId
+     * @param courseCode
+     * @return
+     */
+    @Override
+    public List<TBAnswerResult> findValidAnswerDetail(Long examId, String courseCode) {
+        return tbAnswerMapper.findValidAnswerDetail(examId, courseCode);
+    }
 }

+ 19 - 0
teachcloud-report-business/src/main/java/com/qmth/teachcloud/report/business/service/impl/TBDimensionServiceImpl.java

@@ -1,11 +1,15 @@
 package com.qmth.teachcloud.report.business.service.impl;
 
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.qmth.teachcloud.report.business.bean.result.CourseDimensionResult;
 import com.qmth.teachcloud.report.business.entity.TBDimension;
 import com.qmth.teachcloud.report.business.mapper.TBDimensionMapper;
 import com.qmth.teachcloud.report.business.service.TBDimensionService;
 import org.springframework.stereotype.Service;
 
+import javax.annotation.Resource;
+import java.util.List;
+
 /**
  * <p>
  * 考察点维度基础表 服务实现类
@@ -17,4 +21,19 @@ import org.springframework.stereotype.Service;
 @Service
 public class TBDimensionServiceImpl extends ServiceImpl<TBDimensionMapper, TBDimension> implements TBDimensionService {
 
+    @Resource
+    TBDimensionMapper tbDimensionMapper;
+
+    /**
+     * 查找维度信息
+     *
+     * @param examId
+     * @param courseCode
+     * @param collegeId
+     * @return
+     */
+    @Override
+    public List<CourseDimensionResult> findDimensionInfo(Long examId, String courseCode, Long collegeId) {
+        return tbDimensionMapper.findDimensionInfo(examId, courseCode, collegeId);
+    }
 }

+ 1 - 1
teachcloud-report-business/src/main/java/com/qmth/teachcloud/report/business/service/impl/TBExamStudentServiceImpl.java

@@ -177,7 +177,7 @@ public class TBExamStudentServiceImpl extends ServiceImpl<TBExamStudentMapper, T
                 ExamStudentTypeDto examStudentTypeDto = (ExamStudentTypeDto) tempList.get(y);
                 if (StringUtils.isNotBlank(examStudentTypeDto.getCurrent())) {
                     UpdateWrapper<TBExamStudent> updateWrapper = new UpdateWrapper<>();
-                    updateWrapper.lambda().set(TBExamStudent::getCurrent, "应届".equals(examStudentTypeDto.getCurrent().trim()))
+                    updateWrapper.lambda().set(TBExamStudent::getStudentCurrent, "应届".equals(examStudentTypeDto.getCurrent().trim()))
                             .eq(TBExamStudent::getExamId, examId)
                             .eq(TBExamStudent::getTicketNumber, examStudentTypeDto.getTicketNumber().trim())
                             .eq(TBExamStudent::getCourseCode, examStudentTypeDto.getCourseCode().trim());

+ 9 - 0
teachcloud-report-business/src/main/java/com/qmth/teachcloud/report/business/service/impl/TBModuleConfigServiceImpl.java

@@ -6,6 +6,9 @@ import com.qmth.teachcloud.report.business.mapper.TBModuleConfigMapper;
 import com.qmth.teachcloud.report.business.service.TBModuleConfigService;
 import org.springframework.stereotype.Service;
 
+import javax.annotation.Resource;
+import java.util.List;
+
 /**
  * <p>
  * 考察点模块配置表 服务实现类
@@ -16,5 +19,11 @@ import org.springframework.stereotype.Service;
  */
 @Service
 public class TBModuleConfigServiceImpl extends ServiceImpl<TBModuleConfigMapper, TBModuleConfig> implements TBModuleConfigService {
+    @Resource
+    private TBModuleConfigMapper tbModuleConfigMapper;
 
+    @Override
+    public List<TBModuleConfig> findDistinctModuleInfoByExamIdAndCourseCode(Long examId, String courseCode) {
+        return tbModuleConfigMapper.findDistinctModuleInfoByExamIdAndCourseCode(examId, courseCode);
+    }
 }

+ 18 - 0
teachcloud-report-business/src/main/java/com/qmth/teachcloud/report/business/service/impl/TBPaperStructServiceImpl.java

@@ -1,11 +1,15 @@
 package com.qmth.teachcloud.report.business.service.impl;
 
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.qmth.teachcloud.report.business.bean.result.TBPaperStructResult;
 import com.qmth.teachcloud.report.business.entity.TBPaperStruct;
 import com.qmth.teachcloud.report.business.mapper.TBPaperStructMapper;
 import com.qmth.teachcloud.report.business.service.TBPaperStructService;
 import org.springframework.stereotype.Service;
 
+import javax.annotation.Resource;
+import java.util.List;
+
 /**
  * <p>
  * 试卷结构表 服务实现类
@@ -17,4 +21,18 @@ import org.springframework.stereotype.Service;
 @Service
 public class TBPaperStructServiceImpl extends ServiceImpl<TBPaperStructMapper, TBPaperStruct> implements TBPaperStructService {
 
+    @Resource
+    TBPaperStructMapper tbPaperStructMapper;
+
+    /**
+     * 查找试卷结构
+     *
+     * @param examId
+     * @param courseCode
+     * @return
+     */
+    @Override
+    public List<TBPaperStructResult> findQuestionInfo(Long examId, String courseCode) {
+        return tbPaperStructMapper.findQuestionInfo(examId, courseCode);
+    }
 }

+ 33 - 0
teachcloud-report-business/src/main/java/com/qmth/teachcloud/report/business/utils/AnalyzeScopeUtil.java

@@ -0,0 +1,33 @@
+package com.qmth.teachcloud.report.business.utils;
+
+
+import com.qmth.teachcloud.common.enums.ExceptionResultEnum;
+
+import java.util.HashMap;
+import java.util.Map;
+
+
+public class AnalyzeScopeUtil {
+    public static Map<String,Object> analyzeScope(String scope) {
+        if (scope == null || scope.length() < 1) {
+            throw ExceptionResultEnum.ERROR.exception("没有找到范围取值");
+        }
+        String tmp = scope.substring(1, scope.length() - 1);
+        String[] valueArr = tmp.split(",");
+        if (valueArr.length != 2){
+            throw ExceptionResultEnum.ERROR.exception("范围解析异常");
+        }
+
+        String minValue = valueArr[0];
+        String maxValue = valueArr[1];
+        String minSign = scope.substring(0,1);
+        String maxSign = scope.substring(scope.length() - 1);
+
+        Map<String,Object> result = new HashMap<>();
+        result.put("minValue",minValue);
+        result.put("maxValue",maxValue);
+        result.put("minSign",minSign);
+        result.put("maxSign",maxSign);
+        return result;
+    }
+}

+ 65 - 0
teachcloud-report-business/src/main/java/com/qmth/teachcloud/report/business/utils/ConversionUtils.java

@@ -0,0 +1,65 @@
+package com.qmth.teachcloud.report.business.utils;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+public class ConversionUtils {
+    /**
+     * 将属性的值从String类型转换成他们各自对应的数据类型的值
+     *
+     * @param type  属性的类型
+     * @param value 属性的值
+     * @return 对应数据类型的值
+     */
+    public static Object convertAttributeValue(String type, String value) throws ParseException {
+        Object result;
+        if ("int".equals(type)) {
+            if (value != null && value.length() != 0){
+                result = Integer.parseInt(value);
+            }else {
+                result = 0;
+            }
+        } else if ("double".equals(type)) {
+            if (value != null && value.length() != 0) {
+                result = Double.parseDouble(value);
+            }else {
+                result = 0;
+            }
+        } else if ("long".equals(type)) {
+            if (value != null && value.length() != 0) {
+                result = Long.parseLong(value);
+            }else {
+                result = 0;
+            }
+        } else if ("Date".equals(type)) {
+            SimpleDateFormat sdf = null;
+            if(value.matches("\\d{4}-\\d{2}-\\d{2}")){
+                sdf = new SimpleDateFormat("yyyy-mm-dd");
+            }else if (value.matches("\\d{4}-\\d{2}-\\d{2} \\d{2}\\d{2}\\d{2}")){
+                sdf = new SimpleDateFormat("yyyy-mm-dd HH:mm:ss");
+            } else {
+                return new Date();
+            }
+            return sdf.parse(value);
+        } else {
+            return value;
+        }
+        return result;
+    }
+
+    /**
+     * 实现首字母大写
+     * @param str 源字符串
+     * @return 大写处理后的字符串
+     */
+    public static String initCap(String str){
+        if (str == null || "".equals(str)){
+            return str;
+        }else if (str.length() == 1){
+            return str.toUpperCase();
+        }else {
+            return str.substring(0,1).toUpperCase() + str.substring(1);
+        }
+    }
+}

+ 184 - 0
teachcloud-report-business/src/main/java/com/qmth/teachcloud/report/business/utils/MathUtil.java

@@ -0,0 +1,184 @@
+package com.qmth.teachcloud.report.business.utils;
+
+import java.text.DecimalFormat;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+/**
+ * @Description:
+ * @Author: CaoZixuan
+ * @Date:
+ */
+public class MathUtil {
+    /**
+     * 计算方差
+     *
+     * @param x double[]
+     * @return 方差
+     */
+    public static double calculateVariance(List<Double> x) {
+        int m = x.size();
+        double sum = 0;
+        for (double v : x) {//求和
+            sum += v;
+        }
+        double dAve = sum / m;//求平均值
+        double dVar = 0;
+        for (double v : x) {//求方差
+            dVar += (v - dAve) * (v - dAve);
+        }
+        return dVar / m;
+    }
+
+    /**
+     * 计算标准差
+     *
+     * @param x double[]
+     * @return 标准差
+     */
+    public static double calculateStandardDeviation(List<Double> x) {
+        return Math.sqrt(calculateVariance(x));
+    }
+
+    /**
+     * 计算众数
+     *
+     * @param x 要计算的数组
+     * @return 众数
+     */
+    public static String calculateMode(List<Double> x) {
+        x = x.stream().map(MathUtil::formatDouble2).collect(Collectors.toList()); // 给数据源保留两位有效数字后再取众数
+
+        Map<Double, Integer> map = new HashMap<>();
+        for (double v : x) {
+            Integer count = map.get(v);
+            if (count == null) {
+                count = 1;
+            } else {
+                count++;
+            }
+            map.put(v, count);
+        }
+        StringBuilder mode = new StringBuilder();
+
+        int maxValue = 0;
+        for (Double aDouble : map.keySet()) {
+            Integer value = map.get(aDouble);
+            if (value > maxValue) {
+                maxValue = value;
+            }
+        }
+        if (maxValue > 1) {
+            for (Double aDouble : map.keySet()) {
+                Integer value = map.get(aDouble);
+                if (value == maxValue) {
+                    mode.append(aDouble).append(",");
+                }
+            }
+            mode = new StringBuilder(mode.substring(0, mode.length() - 1));
+        }
+        return mode.toString();
+    }
+
+    /**
+     * 计算分位数
+     *
+     * @param x     数据源
+     * @param split 分位数值(上四分位:0.25、中位数:0.5、下四分位:0.75、。。。。。。)
+     * @return 值
+     */
+    public static double calculateQuantile(List<Double> x, double split) {
+        List<Double> sortList = x.stream().sorted((o1, o2) -> {
+            if (o1.equals(o2)) {
+                return 0;
+            } else if (o1 < o2) {
+                return -1;
+            } else {
+                return 1;
+            }
+        }).collect(Collectors.toList());
+
+        int totalNumber = sortList.size();
+        double position = (totalNumber + 1) * split;
+        int index = (int) position;
+        if (position < 1 || position > totalNumber) {
+            return 0;
+        }
+        if ((double) index == position) {
+            return sortList.get(index - 1);
+        }
+        double thisPower = 1 - (position - index);
+        double nextPower = position - index;
+        return sortList.get(index - 1) * thisPower + sortList.get(index) * nextPower;
+    }
+
+    /**
+     * double保留2位小数
+     *
+     * @param d double
+     * @return 保留后的值
+     */
+    public static double formatDouble2(double d) {
+        DecimalFormat df = new DecimalFormat("#.00");
+
+        return Double.parseDouble(df.format(d));
+    }
+
+    /**
+     * double保留1位小数
+     *
+     * @param d double
+     * @return 保留后的值
+     */
+    public static double formatDouble1(double d) {
+        DecimalFormat df = new DecimalFormat("#.0");
+
+        return Double.parseDouble(df.format(d));
+    }
+
+    /**
+     * double保留整数
+     *
+     * @param d double
+     * @return 保留后的值
+     */
+    public static double formatDouble0(double d) {
+        DecimalFormat df = new DecimalFormat("#");
+
+        return Double.parseDouble(df.format(d));
+    }
+
+    /**
+     * 给譬如 A1 B1 B2 B10 C2 这样的特殊字符串集合排序
+     *
+     * @param dimensionSet 考察点字符串
+     * @return 排序结果
+     */
+    public static List<String> sortDimension(List<String> dimensionSet) {
+        return dimensionSet.stream().sorted((o1, o2) -> {
+            int compareResult = o1.substring(0, 1).compareToIgnoreCase(o2.substring(0, 1));
+            if (compareResult > 0) {
+                return 1;
+            } else if (compareResult < 0) {
+                return -1;
+            } else {
+                int cell1 = 0;
+                int cell2 = 0;
+                if (o1.length() > 1) {
+                    cell1 = Integer.parseInt(o1.substring(1));
+                }
+                if (o2.length() > 1) {
+                    cell2 = Integer.parseInt(o2.substring(1));
+                }
+                if (cell1 >= cell2) {
+                    return 1;
+                } else {
+                    return -1;
+                }
+            }
+        }).collect(Collectors.toList());
+    }
+
+}

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 142 - 142
teachcloud-report-business/src/main/resources/db/init-table.sql


+ 24 - 0
teachcloud-report-business/src/main/resources/mapper/TAExamCourseCollegeInspectDioMapper.xml

@@ -2,4 +2,28 @@
 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 <mapper namespace="com.qmth.teachcloud.report.business.mapper.TAExamCourseCollegeInspectDioMapper">
 
+    <select id="findByTAExamCourseRecordDio"
+            resultType="com.qmth.teachcloud.report.business.entity.TAExamCourseCollegeInspectDio">
+        SELECT
+            exam_id AS examId,
+            course_code AS courseCode,
+            MAX(course_name) AS courseName,
+            inspect_college_id AS inspectCollegeId,
+            MAX(inspect_college_name) AS inspectCollegeName,
+            dimension_type AS dimensionType,
+            dimension_code AS dimensionCode,
+            AVG(student_score) AS avgScore,
+            AVG(score_rate) AS scoreRate
+        FROM
+            t_a_exam_course_record_dio
+        <where>
+            <if test="examId > 0">
+                and exam_id = #{examId}
+            </if>
+            <if test="courseCode != null and courseCode.length > 0">
+                and course_code = #{courseCode}
+            </if>
+        </where>
+        GROUP BY exam_id , course_code , inspect_college_id , dimension_type , dimension_code;
+    </select>
 </mapper>

+ 31 - 0
teachcloud-report-business/src/main/resources/mapper/TAExamCourseCollegeInspectMapper.xml

@@ -2,4 +2,35 @@
 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 <mapper namespace="com.qmth.teachcloud.report.business.mapper.TAExamCourseCollegeInspectMapper">
 
+    <select id="findCourseDescriptiveStatisticsForCollege" resultType="com.qmth.teachcloud.report.business.bean.result.TAExamCourseCollegeInspectResult">
+        select
+            so.name as collegeName,
+            round(convert(taecci.max_score, decimal(10, 4)), 2) as maxScore,
+            round(convert(taecci.min_score, decimal(10, 4)), 2) as minScore,
+            round(convert(taecci.avg_score, decimal(10, 4)), 2) as avgScore,
+            taecci.reality_count as realityCount,
+            taecci.absent_count as absentCount,
+            taecci.total_count as totalCount,
+            round(convert(taecci.upper_quartile, decimal(10, 4)), 2) as upperQuartile,
+            round(convert(taecci.median, decimal(10, 4)), 2) as median,
+            round(convert(taecci.lower_quartile, decimal(10, 4)), 2) as lowerQuartile,
+            taecci.mode,
+            round(convert(taecci.standard_deviation, decimal(10, 4)), 2) as standardDeviation,
+            round(convert(taecci.relative_position, decimal(10, 4)), 2) as relativePosition
+        from
+            t_a_exam_course_college_inspect taecci
+        join sys_org so on
+            so.id = taecci.college_id
+        <where>
+            <if test="courseCode != null and courseCode != ''">
+                and taecci.course_code = #{courseCode}
+            </if>
+            <if test="examId != null and examId != ''">
+                and taecci.exam_id = #{examId}
+            </if>
+            <if test="schoolId != null and schoolId != ''">
+                and taecci.school_id = #{schoolId}
+            </if>
+        </where>
+    </select>
 </mapper>

+ 48 - 0
teachcloud-report-business/src/main/resources/mapper/TAExamCourseCollegeTeacherMapper.xml

@@ -33,6 +33,7 @@
             </if>
         </where>
     </select>
+
     <select id="listMyClassRank"
             resultType="com.qmth.teachcloud.report.business.bean.result.TeacherMyClassRankResult">
         SELECT
@@ -65,6 +66,7 @@
             </if>
         </where>
     </select>
+
     <select id="listAllTeacherClassRank"
             resultType="com.qmth.teachcloud.report.business.entity.TAExamCourseCollegeTeacher">
         SELECT
@@ -98,4 +100,50 @@
             </if>
         </where>
     </select>
+
+    <select id="findTeacherInfo" resultType="com.qmth.teachcloud.report.business.bean.result.TAExamCourseTeacherResult">
+        SELECT
+            col.teacher_name AS teacherName,
+            col.reality_count AS colRealityCount,
+            col.total_count AS colTotalCount,
+            col.absent_count AS colAbsentCount,
+            round(convert(col.min_score_assign , decimal(10, 4)), 2) AS colMinScore,
+            round(convert(col.max_score_assign , decimal(10, 4)), 2) AS colMaxScore,
+            round(convert(col.avg_score_assign , decimal(10, 4)), 2) AS colAvgScore,
+            round(convert(col.upper_quartile, decimal(10, 4)), 2) AS colUpperQuartile,
+            round(convert(col.median, decimal(10, 4)), 2) AS colMedian,
+            round(convert(col.lower_quartile, decimal(10, 4)), 2) AS colLowerQuartile,
+            col.mode AS colMode,
+            round(convert(col.standard_deviation, decimal(10, 4)), 2) AS colStandardDeviation,
+            round(convert(col.relative_position, decimal(10, 4)), 2) AS colRelativePosition,
+            sch.reality_count AS schRealityCount,
+            sch.total_count AS schTotalCount,
+            sch.absent_count AS schAbsentCount,
+            round(convert(sch.min_score, decimal(10, 4)), 2) AS schMinScore,
+            round(convert(sch.max_score, decimal(10, 4)), 2) AS schMaxScore,
+            round(convert(sch.avg_score, decimal(10, 4)), 2) AS schAvgScore,
+            round(convert(sch.upper_quartile, decimal(10, 4)), 2) AS schUpperQuartile,
+            round(convert(sch.median, decimal(10, 4)), 2) AS schMedian,
+            round(convert(sch.lower_quartile, decimal(10, 4)), 2) AS schLowerQuartile,
+            sch.mode AS schMode,
+            round(convert(sch.standard_deviation, decimal(10, 4)), 2) AS schStandardDeviation,
+            round(convert(sch.relative_position, decimal(10, 4)), 2) AS schRelativePosition
+        FROM
+             t_a_exam_course_college_teacher col
+        INNER JOIN  t_a_exam_course_teacher sch ON
+            col.exam_id = sch.exam_id
+            AND col.course_code = sch.course_code
+            AND col.teacher_name = sch.teacher_name
+        <where>
+            <if test="examId != null and examId != ''">
+                and col.exam_id = #{examId}
+            </if>
+            <if test="courseCode != null and courseCode != ''">
+                and col.course_code = #{courseCode}
+            </if>
+            <if test="collegeId != null and collegeId != ''">
+                and col.inspect_college_id = #{collegeId}
+            </if>
+        </where>
+    </select>
 </mapper>

+ 75 - 0
teachcloud-report-business/src/main/resources/mapper/TBAnswerMapper.xml

@@ -2,4 +2,79 @@
 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 <mapper namespace="com.qmth.teachcloud.report.business.mapper.TBAnswerMapper">
 
+    <select id="findByPaperId" resultType="com.qmth.teachcloud.report.business.bean.dto.query.BasicAnswerDto">
+        SELECT
+            t0.id AS answerId,
+            t0.exam_record_id AS examRecordId,
+            t0.number_type AS numberType,
+            t0.main_number AS mainNumber,
+            t0.sub_number AS subNumber,
+            t0.answer,
+            t0.score,
+            t0.path,
+            t0.time,
+            t1.exam_id AS examId,
+            t1.paper_id AS paperId,
+            t1.paper_type AS paperType,
+            t1.exam_student_id AS examStudentId,
+            t1.subjective_score AS subjectiveScore,
+            t1.objective_score AS objectiveScore,
+            t1.total_score AS totalScore
+        FROM
+            t_b_answer t0
+                INNER JOIN
+            t_b_exam_record t1 ON t0.exam_record_id = t1.id
+        WHERE
+            t1.paper_id = #{paperId}
+    </select>
+
+    <select id="findValid"
+            resultType="com.qmth.teachcloud.report.business.bean.dto.query.ValidAnswerDetailDto">
+        SELECT
+            answer.id AS answerId,
+            answer.exam_record_id AS examRecordId,
+            answer.number_type AS numberType,
+            answer.main_number AS mainNumber,
+            answer.sub_number AS subNumber,
+            answer.score,
+            record.id AS taExamRecordId,
+            record.percent_grade AS percentGrade,
+            record.paper_id AS paperId,
+            record.paper_type AS paperType
+        FROM
+            t_b_answer answer
+                INNER JOIN
+            t_a_exam_course_record record ON answer.exam_record_id = record.exam_record_id
+        WHERE
+            record.absent = 0 AND record.student_current = 1
+          AND record.exam_id = #{examId}
+          AND record.course_code = #{courseCode};
+    </select>
+
+    <select id="findValidAnswerDetail" resultType="com.qmth.teachcloud.report.business.bean.result.TBAnswerResult">
+        SELECT
+            tik.paper_type AS paperType,
+            det.score / tbps.full_score AS scoreRate,
+            pap.difficult AS difficult,
+            (select so.name from sys_org so where so.id = tik.inspect_college_id) AS collegeName
+        FROM
+            t_b_answer det
+        INNER JOIN t_a_exam_course_record tik ON
+            det.exam_record_id = tik.exam_record_id
+        INNER JOIN t_a_paper_struct pap ON
+            tik.exam_id = pap.exam_id
+            AND tik.course_code = pap.course_code
+        JOIN t_b_paper_struct tbps on
+            tbps.id = pap.paper_struct_id
+            AND det.sub_number = tbps.small_question_number
+        <where>
+            <if test="examId != null and examId != ''">
+                and tik.exam_id = #{examId}
+            </if>
+            <if test="courseCode != null and courseCode != ''">
+                and tik.course_code = #{courseCode}
+            </if>
+            and tik.absent = 0
+        </where>
+    </select>
 </mapper>

+ 55 - 0
teachcloud-report-business/src/main/resources/mapper/TBDimensionMapper.xml

@@ -2,4 +2,59 @@
 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 <mapper namespace="com.qmth.teachcloud.report.business.mapper.TBDimensionMapper">
 
+    <select id="findDimensionInfo" resultType="com.qmth.teachcloud.report.business.bean.result.CourseDimensionResult">
+        SELECT
+            tmp.exam_id AS examId,
+            (select tbe.exam_code from t_b_exam tbe where tbe.id = tmp.exam_id) as examCode,
+            tmp.course_code AS courseCode,
+            tmp.dimension_type AS module,
+            code_primary AS dimensionCode,
+            name_primary AS dimensionName,
+            interpretation,
+            total_count AS totalCount,
+            round(CONVERT( papDio.score_rate * 100 , DECIMAL (10 , 4 )),2) AS schScoreRate,
+            round(CONVERT( colDio.score_rate * 100 , DECIMAL (10 , 4 )),2) AS colScoreRate,
+            colDio.inspect_college_name AS collegeName
+        FROM
+            (SELECT
+                 exam_id,
+                 course_code,
+                 dimension_type,
+                 code_primary,
+                 name_primary,
+                 interpretation
+             FROM
+                 t_b_dimension
+             GROUP BY exam_id, course_code , dimension_type , code_primary , name_primary , interpretation) tmp
+                INNER JOIN
+            (SELECT
+                 exam_id,
+                 course_code,
+                 dimension_type,
+                 dimension_code,
+                 AVG(score_rate) AS score_rate,
+                 AVG(total_count) AS total_count
+             FROM
+                  t_a_exam_course_dio
+             GROUP BY exam_id , course_code , dimension_type , dimension_code) papDio ON tmp.code_primary = papDio.dimension_code
+                AND tmp.dimension_type = papDio.dimension_type
+                AND tmp.exam_id = papDio.exam_id
+                AND tmp.course_code = papDio.course_code
+                INNER JOIN
+            t_a_exam_course_college_inspect_dio colDio ON tmp.code_primary = colDio.dimension_code
+                AND tmp.dimension_type = colDio.dimension_type
+                AND papDio.exam_id = colDio.exam_id
+                AND papDio.course_code = colDio.course_code
+                <where>
+                    <if test="examId != null and examId != ''">
+                        and papDio.exam_id = #{examId}
+                    </if>
+                    <if test="courseCode != null and courseCode != ''">
+                        and papDio.course_code = #{courseCode}
+                    </if>
+                    <if test="collegeId != null and collegeId != ''">
+                        and inspect_college_id = #{collegeId}
+                    </if>
+                </where>
+    </select>
 </mapper>

+ 1 - 1
teachcloud-report-business/src/main/resources/mapper/TBExamRecordMapper.xml

@@ -19,7 +19,7 @@
             ticket_number AS ticketNumber,
             student_code AS studentCode,
             absent AS absent,
-            current,
+            student_current as studentCurrent,
             br.id AS tbExamRecordId,
             paper_id AS paperId,
             paper_type AS paperType,

+ 10 - 0
teachcloud-report-business/src/main/resources/mapper/TBModuleConfigMapper.xml

@@ -2,4 +2,14 @@
 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 <mapper namespace="com.qmth.teachcloud.report.business.mapper.TBModuleConfigMapper">
 
+    <select id="findDistinctModuleInfoByExamIdAndCourseCode"
+            resultType="com.qmth.teachcloud.report.business.entity.TBModuleConfig">
+        SELECT
+            module_type, attribute , max(formula) as formula
+        FROM
+            t_b_module_config
+        WHERE
+            exam_id = #{examId} AND course_code = #{courseCode}
+        GROUP BY exam_id , course_code , module_type , attribute;
+    </select>
 </mapper>

+ 26 - 0
teachcloud-report-business/src/main/resources/mapper/TBPaperStructMapper.xml

@@ -2,4 +2,30 @@
 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 <mapper namespace="com.qmth.teachcloud.report.business.mapper.TBPaperStructMapper">
 
+    <select id="findQuestionInfo" resultType="com.qmth.teachcloud.report.business.bean.result.TBPaperStructResult">
+        SELECT
+            tbp.paper_type AS paperType,
+            tbps.big_question_number AS mainNumber,
+            tbps.small_question_number AS subNumber,
+            tbps.full_score AS fullScore,
+            tbps.knowledge_dimension AS knowledgeDimension,
+            tbps.ability_dimension AS abilityDimension,
+            round(convert(taps.score_rate * 100,decimal(10,4)),2) AS scoreRate,
+            taps.difficult,
+            convert(taps.validity,decimal(10,4)) AS validity
+        FROM
+            t_b_paper_struct tbps
+            join t_a_paper_struct taps
+            on taps.paper_struct_id = tbps.id
+            join t_b_paper tbp
+            on tbp.id = paper_id
+        <where>
+            <if test="examId != null and examId != ''">
+                and tbp.exam_id = #{examId}
+            </if>
+            <if test="courseCode != null and courseCode != ''">
+                and tbp.course_code = #{courseCode}
+            </if>
+        </where>
+    </select>
 </mapper>

+ 4 - 3
teachcloud-report/src/main/java/com/qmth/teachcloud/report/api/BasicDatasourceController.java

@@ -4,6 +4,7 @@ import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.google.common.collect.Lists;
+import com.qmth.boot.api.constant.ApiConstant;
 import com.qmth.teachcloud.common.bean.params.UserSaveParams;
 import com.qmth.teachcloud.common.contant.SystemConstant;
 import com.qmth.teachcloud.common.entity.BasicCourse;
@@ -48,7 +49,7 @@ import java.util.stream.Collectors;
  */
 @Api(tags = "数据源处理controller")
 @RestController
-@RequestMapping("/${prefix.url.wuda}/datasource")
+@RequestMapping(ApiConstant.DEFAULT_URI_PREFIX + "/${prefix.url.datasource}")
 public class BasicDatasourceController {
     @Resource
     private TBPaperService tbPaperService;
@@ -597,7 +598,7 @@ public class BasicDatasourceController {
                 tbExamStudent.setTicketNumber(examNumber);
                 tbExamStudent.setAbsent(status == 2);
                 // 全部设置为本届
-                tbExamStudent.setCurrent(true);
+                tbExamStudent.setStudentCurrent(true);
                 tbExamStudentList.add(tbExamStudent);
 
                 // TODO: 2021/6/2 创建考生-考试记录关系表(全批次删除并新增)
@@ -744,7 +745,7 @@ public class BasicDatasourceController {
                     taExamCourseRecord.setMajorId(basicExamRecordDto.getMajorId());
                     taExamCourseRecord.setTotalScore(myScore);
                     taExamCourseRecord.setAbsent(basicExamRecordDto.getAbsent());
-                    taExamCourseRecord.setCurrent(basicExamRecordDto.getCurrent());
+                    taExamCourseRecord.setStudentCurrent(basicExamRecordDto.getStudentCurrent());
                     taExamCourseRecordList.add(taExamCourseRecord);
                 }
                 taExamCourseRecordDatasource.addAll(taExamCourseRecordList);

+ 11 - 0
teachcloud-report/src/main/java/com/qmth/teachcloud/report/api/CourseController.java

@@ -36,6 +36,17 @@ public class CourseController {
         return ResultUtil.ok(taExamCourseService.surveyTeacherList(new Page<>(pageNumber, pageSize), SystemConstant.convertIdToLong(examId), semester, SystemConstant.convertIdToLong(schoolId)));
     }
 
+    @ApiOperation(value = "考查课程考试分析接口")
+    @RequestMapping(value = "/survey_inspect_analyse/view", method = RequestMethod.POST)
+    @ApiResponses({@ApiResponse(code = 200, message = "考试科目信息", response = TAExamCourseResult.class)})
+    public Result surveyInspectAnalyseView(@ApiParam(value = "考试id", required = true) @RequestParam String examId,
+                                           @ApiParam(value = "学期", required = true) @RequestParam SemesterEnum semester,
+                                           @ApiParam(value = "科目编码", required = true) @RequestParam String courseCode,
+                                           @ApiParam(value = "学校id", required = true) @RequestParam String schoolId) {
+
+        return ResultUtil.ok();
+    }
+
     @ApiOperation(value = "赋分管理列表接口")
     @RequestMapping(value = "/survey_aspoints/list", method = RequestMethod.POST)
     @ApiResponses({@ApiResponse(code = 200, message = "考试科目信息", response = TAExamCourseResult.class)})

+ 1 - 0
teachcloud-report/src/main/resources/application-dev.properties

@@ -90,6 +90,7 @@ prefix.url.reportWuda=report/wuda/open
 prefix.url.reportSchool=report/school
 prefix.url.reportCourse=report/course
 prefix.url.reportExamStudent=report/exam_student
+prefix.url.datasource=report/datasource
 
 #\u65E5\u5FD7\u914D\u7F6E
 com.qmth.logging.root-level=info

+ 90 - 0
teachcloud-report/src/test/java/com/qmth/teachcloud/report/AnalyzeForStudentServiceTest.java

@@ -0,0 +1,90 @@
+package com.qmth.teachcloud.report;
+
+import com.qmth.teachcloud.report.business.service.AnalyzeForStudentService;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import javax.annotation.Resource;
+
+/**
+ * @Description:
+ * @Author: CaoZixuan
+ * @Date:
+ */
+@SpringBootTest(classes = {TeachcloudReportApplication.class})
+@RunWith(SpringRunner.class)
+public class AnalyzeForStudentServiceTest {
+    @Resource
+    private AnalyzeForStudentService analyzeForStudentService;
+    @Test
+    public void buildAnalyzeExamCourse() {
+        Long examId = 1L;
+        String courseCode = "1013";
+        System.out.println(analyzeForStudentService.buildAnalyzeExamCourse(examId,courseCode));
+
+    }
+
+    @Test
+    public void buildAnalyzeExamCourseRecord() {
+        Long examId = 1L;
+        String courseCode = "1013";
+        System.out.println(analyzeForStudentService.buildAnalyzeExamCourseRecord(examId,courseCode));
+    }
+
+    @Test
+    public void buildAnalyzeExamCourseCollegeInspectByOther() {
+        Long examId = 1L;
+        String courseCode = "1013";
+        System.out.println(analyzeForStudentService.buildAnalyzeExamCourseCollegeInspect(examId,courseCode));
+    }
+
+    @Test
+    public void buildAnalyzeExamCourseClazz() {
+        Long examId = 1L;
+        String courseCode = "1013";
+        System.out.println(analyzeForStudentService.buildAnalyzeExamCourseClazz(examId,courseCode));
+    }
+
+    @Test
+    public void analyzePointScoreRate() throws Exception {
+        Long examId = 1L;
+        String courseCode = "1013";
+        analyzeForStudentService.AnalyzePointScoreRate(examId,courseCode);
+    }
+
+    @Test
+    public void buildAnalyzeExamCourseCollegeInspectDio() {
+        Long examId = 1L;
+        String courseCode = "1013";
+        System.out.println(analyzeForStudentService.buildAnalyzeExamCourseCollegeInspectDio(examId,courseCode));
+    }
+
+    @Test
+    public void buildAnalyzePaperStruct() {
+        Long examId = 1L;
+        String courseCode = "1013";
+        System.out.println(analyzeForStudentService.buildAnalyzePaperStruct(examId,courseCode));
+    }
+
+    @Test
+    public void buildAnalyzeExamTotal() {
+        Long examId = 1L;
+        System.out.println(analyzeForStudentService.buildAnalyzeExamTotal(examId));
+    }
+
+    @Test
+    public void buildAnalyzeExamCourseCollegeTeacher() {
+        Long examId = 1L;
+        String courseCode = "1013";
+        System.out.println(analyzeForStudentService.buildAnalyzeExamCourseCollegeTeacher(examId,courseCode));
+    }
+
+    @Test
+    public void buildAnalyzeExamCourseTeacher() {
+        Long examId = 1L;
+        String courseCode = "1013";
+        System.out.println(analyzeForStudentService.buildAnalyzeExamCourseTeacher(examId,courseCode));
+    }
+}

برخی فایل ها در این مقایسه diff نمایش داده نمی شوند زیرا تعداد فایل ها بسیار زیاد است