yqq 4 anos atrás
commit
8c3e4f778a
36 arquivos alterados com 3033 adições e 0 exclusões
  1. 167 0
      pom.xml
  2. 17 0
      src/main/java/com/zsy/sass/SassApplication.java
  3. 28 0
      src/main/java/com/zsy/sass/common/enums/ZSYLevelCountType.java
  4. 27 0
      src/main/java/com/zsy/sass/common/exception/ZSYApiException.java
  5. 35 0
      src/main/java/com/zsy/sass/common/exception/ZSYAuthException.java
  6. 27 0
      src/main/java/com/zsy/sass/common/exception/ZSYDbException.java
  7. 27 0
      src/main/java/com/zsy/sass/common/exception/ZSYForbiddenException.java
  8. 14 0
      src/main/java/com/zsy/sass/common/exception/ZSYMark.java
  9. 27 0
      src/main/java/com/zsy/sass/common/exception/ZSYServerException.java
  10. 29 0
      src/main/java/com/zsy/sass/common/exception/ZSYServiceException.java
  11. 35 0
      src/main/java/com/zsy/sass/common/exception/ZSYTokenCreateException.java
  12. 35 0
      src/main/java/com/zsy/sass/common/exception/ZSYTokenValidException.java
  13. 580 0
      src/main/java/com/zsy/sass/common/tools/RedisUtil.java
  14. 231 0
      src/main/java/com/zsy/sass/common/tools/ZSYResult.java
  15. 104 0
      src/main/java/com/zsy/sass/config/RedisConfig.java
  16. 124 0
      src/main/java/com/zsy/sass/model/bo/StudentExam.java
  17. 132 0
      src/main/java/com/zsy/sass/model/dto/request/SchoolLevelCountReqDTO.java
  18. 122 0
      src/main/java/com/zsy/sass/model/dto/response/SchoolLevelCountNewResDTO.java
  19. 122 0
      src/main/java/com/zsy/sass/model/pojo/Exam.java
  20. 59 0
      src/main/java/com/zsy/sass/model/pojo/User.java
  21. 45 0
      src/main/java/com/zsy/sass/report/controller/ExamController.java
  22. 62 0
      src/main/java/com/zsy/sass/report/controller/ExamReportController.java
  23. 29 0
      src/main/java/com/zsy/sass/report/controller/RedisController.java
  24. 20 0
      src/main/java/com/zsy/sass/report/dao/ExamDao.java
  25. 30 0
      src/main/java/com/zsy/sass/report/dao/ExamReportDao.java
  26. 5 0
      src/main/java/com/zsy/sass/report/dao/RedisDao.java
  27. 30 0
      src/main/java/com/zsy/sass/report/dao/impl/ExamDaoImpl.java
  28. 74 0
      src/main/java/com/zsy/sass/report/dao/impl/ExamReportDaoImpl.java
  29. 14 0
      src/main/java/com/zsy/sass/report/dao/impl/RedisDaoImpl.java
  30. 32 0
      src/main/java/com/zsy/sass/report/service/ExamReportService.java
  31. 15 0
      src/main/java/com/zsy/sass/report/service/ExamService.java
  32. 6 0
      src/main/java/com/zsy/sass/report/service/RedisService.java
  33. 635 0
      src/main/java/com/zsy/sass/report/service/impl/ExamReportServiceImpl.java
  34. 27 0
      src/main/java/com/zsy/sass/report/service/impl/ExamServiceImpl.java
  35. 29 0
      src/main/java/com/zsy/sass/report/service/impl/RedisServiceImpl.java
  36. 38 0
      src/main/resources/application.properties

+ 167 - 0
pom.xml

@@ -0,0 +1,167 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.springframework.boot</groupId>
+        <artifactId>spring-boot-starter-parent</artifactId>
+        <version>2.1.6.RELEASE</version>
+        <relativePath/> <!-- lookup parent from repository -->
+    </parent>
+    <groupId>com.zsy</groupId>
+    <artifactId>sass</artifactId>
+    <version>0.0.1-SNAPSHOT</version>
+    <name>sass</name>
+    <description>Demo project for Spring Boot</description>
+
+    <properties>
+        <java.version>1.8</java.version>
+    </properties>
+
+    <dependencies>
+        <!--web相关依赖-->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <!--JDBC-->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-jdbc</artifactId>
+        </dependency>
+        <!--mysql-->
+        <dependency>
+            <groupId>mysql</groupId>
+            <artifactId>mysql-connector-java</artifactId>
+            <version>5.1.47</version>
+        </dependency>
+        <!-- redis -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-data-redis</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>fastjson</artifactId>
+            <version>1.2.46</version>
+        </dependency>
+        <!--<dependency>
+            <groupId>com.google.guava</groupId>
+            <artifactId>guava</artifactId>
+            <version>19.0</version>
+        </dependency>-->
+        <!-- https://mvnrepository.com/artifact/com.google.code.gson/gson -->
+        <dependency>
+            <groupId>com.google.code.gson</groupId>
+            <artifactId>gson</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.springfox</groupId>
+            <artifactId>springfox-swagger2</artifactId>
+            <version>2.7.0</version>
+        </dependency>
+        <!--<dependency>
+            <groupId>com.zhixinhuixue</groupId>
+            <artifactId>jdbc</artifactId>
+            <version>2.0</version>
+        </dependency>-->
+
+        <!--HBase依赖 -->
+        <dependency>
+            <groupId>org.apache.hbase</groupId>
+            <artifactId>hbase-client</artifactId>
+            <version>2.1.0</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.slf4j</groupId>
+                    <artifactId>slf4j-log4j12</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.data</groupId>
+            <artifactId>spring-data-hadoop</artifactId>
+            <version>2.1.2.RELEASE</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.hadoop</groupId>
+            <artifactId>hadoop-hdfs</artifactId>
+            <version>3.0.0</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.data</groupId>
+            <artifactId>spring-data-hadoop-core</artifactId>
+            <version>2.1.2.RELEASE</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.hbase</groupId>
+            <artifactId>hbase</artifactId>
+            <version>2.1.0</version>
+            <type>pom</type>
+        </dependency>
+
+
+
+        <!--HBase依赖 -->
+
+        <!-- https://mvnrepository.com/artifact/edu.stanford.nlp/stanford-corenlp -->
+ <!--       <dependency>
+            <groupId>edu.stanford.nlp</groupId>
+            <artifactId>stanford-corenlp</artifactId>
+            <version>${stanford.corenlp.version}</version>
+        </dependency>-->
+        <!--<dependency>
+            <groupId>edu.stanford.nlp</groupId>
+            <artifactId>stanford-corenlp</artifactId>
+            <version>${stanford.corenlp.version}</version>
+            <classifier>models</classifier>
+        </dependency>-->
+   <!--     <dependency>
+            <groupId>edu.stanford.nlp</groupId>
+            <artifactId>stanford-corenlp</artifactId>
+            <version>${stanford.corenlp.version}</version>
+            <classifier>models-english</classifier>
+        </dependency>-->
+
+        <!--<dependency>
+            <groupId>org.springframework.kafka</groupId>
+            <artifactId>spring-kafka</artifactId>
+        </dependency>-->
+        <!--prometheus监控  https://prometheus.io/docs/introduction/overview/-->
+        <!--<dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-actuator</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>io.micrometer</groupId>
+            <artifactId>micrometer-registry-prometheus</artifactId>
+            <version>1.1.3</version>
+        </dependency>-->
+
+        <!--prometheus监控  https://prometheus.io/docs/introduction/overview/-->
+
+        <!--<dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+            <optional>true</optional>
+        </dependency>-->
+
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>

+ 17 - 0
src/main/java/com/zsy/sass/SassApplication.java

@@ -0,0 +1,17 @@
+package com.zsy.sass;
+
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+
+@SpringBootApplication
+public class SassApplication {
+
+    public static void main(String[] args) {
+        SpringApplication.run(SassApplication.class, args);
+
+    }
+
+
+}

+ 28 - 0
src/main/java/com/zsy/sass/common/enums/ZSYLevelCountType.java

@@ -0,0 +1,28 @@
+package com.zsy.sass.common.enums;
+
+public enum ZSYLevelCountType {
+    SCORE_COUNT(0,"按分数分档"),NUM_COUNT(1,"按人数分档"),DEFAYLT_COUNT(2,"恢复默认");
+    private int value;
+    private String name;
+
+    ZSYLevelCountType(int value, String name) {
+        this.value = value;
+        this.name = name;
+    }
+
+    public int getValue() {
+        return value;
+    }
+
+    public String getName() {
+        return name;
+    }
+    public String getName(int value){
+        for(ZSYLevelCountType type:ZSYLevelCountType.values()){
+            if(value==type.value){
+                return type.name;
+            }
+        }
+        return "";
+    }
+}

+ 27 - 0
src/main/java/com/zsy/sass/common/exception/ZSYApiException.java

@@ -0,0 +1,27 @@
+package com.zsy.sass.common.exception;
+
+/**
+ * 调用外部HTTP接口异常
+ *
+ * @author Live.InPast
+ * @date 2018/10/23
+ */
+public class ZSYApiException extends RuntimeException {
+
+    /**
+     * 构造函数
+     * @param errMsg
+     * @param cause
+     */
+    public ZSYApiException(String errMsg, Throwable cause) {
+        super(errMsg,cause);
+    }
+
+    /**
+     * 构造函数
+     * @param errMsg
+     */
+    public ZSYApiException(String errMsg) {
+        super(errMsg);
+    }
+}

+ 35 - 0
src/main/java/com/zsy/sass/common/exception/ZSYAuthException.java

@@ -0,0 +1,35 @@
+package com.zsy.sass.common.exception;
+
+/**
+ * 授权失败
+ *
+ * @author Live.InPast
+ * @date 2018/10/23
+ */
+public class ZSYAuthException extends RuntimeException {
+
+    /**
+     * 构造函数
+     */
+    public ZSYAuthException() {
+
+    }
+
+    /**
+     * 构造函数
+     * @param errMsg
+     */
+    public ZSYAuthException(String errMsg) {
+        super(errMsg);
+    }
+
+    /**
+     * 构造函数
+     * @param errMsg
+     * @param cause
+     */
+    public ZSYAuthException(String errMsg, Throwable cause) {
+        super(errMsg,cause);
+    }
+
+}

+ 27 - 0
src/main/java/com/zsy/sass/common/exception/ZSYDbException.java

@@ -0,0 +1,27 @@
+package com.zsy.sass.common.exception;
+
+/**
+ * 数据库操作异常
+ *
+ * @author Live.InPast
+ * @date 20118/10/23
+ */
+public class ZSYDbException extends RuntimeException {
+
+    /**
+     * 构造函数
+     * @param errMsg
+     * @param cause
+     */
+    public ZSYDbException(String errMsg, Throwable cause) {
+        super(errMsg,cause);
+    }
+
+    /**
+     * 构造函数
+     * @param errMsg
+     */
+    public ZSYDbException(String errMsg) {
+        super(errMsg);
+    }
+}

+ 27 - 0
src/main/java/com/zsy/sass/common/exception/ZSYForbiddenException.java

@@ -0,0 +1,27 @@
+package com.zsy.sass.common.exception;
+
+/**
+ * 禁止访问异常
+ *
+ * @author Live.InPast
+ * @date 2018/11/30
+ */
+public class ZSYForbiddenException extends RuntimeException {
+
+    /**
+     * 构造函数
+     * @param errMsg
+     * @param cause
+     */
+    public ZSYForbiddenException(String errMsg, Throwable cause) {
+        super(errMsg,cause);
+    }
+
+    /**
+     * 构造函数
+     * @param errMsg
+     */
+    public ZSYForbiddenException(String errMsg) {
+        super(errMsg);
+    }
+}

+ 14 - 0
src/main/java/com/zsy/sass/common/exception/ZSYMark.java

@@ -0,0 +1,14 @@
+package com.zsy.sass.common.exception;
+
+/**
+ * Created by gj on 19-4-22.
+ * 标记 标记后的bean配置可以不加载
+ * 配合
+ * @ComponentScan(value = "cn.wyn",
+ *         excludeFilters = { @ComponentScan.Filter(
+ *         type = FilterType.ANNOTATION,
+ *         classes = {ZSYMark.class})}
+ *         使用
+ */
+public @interface ZSYMark {
+}

+ 27 - 0
src/main/java/com/zsy/sass/common/exception/ZSYServerException.java

@@ -0,0 +1,27 @@
+package com.zsy.sass.common.exception;
+
+/**
+ * 服务异常
+ *
+ * @author Live.InPast
+ * @date 2018/10/23
+ */
+public class ZSYServerException extends RuntimeException {
+
+    /**
+     * 构造函数
+     * @param errMsg
+     * @param cause
+     */
+    public ZSYServerException(String errMsg, Throwable cause) {
+        super(errMsg,cause);
+    }
+
+    /**
+     * 构造函数
+     * @param errMsg
+     */
+    public ZSYServerException(String errMsg) {
+        super(errMsg);
+    }
+}

+ 29 - 0
src/main/java/com/zsy/sass/common/exception/ZSYServiceException.java

@@ -0,0 +1,29 @@
+package com.zsy.sass.common.exception;
+
+/**
+ * 业务异常
+ *
+ * @author Live.InPast
+ * @date 2018/10/23
+ */
+public class ZSYServiceException extends RuntimeException {
+
+
+    /**
+     * 构造函数
+     * @param errMsg
+     * @param cause
+     */
+    public ZSYServiceException(String errMsg, Throwable cause) {
+        super(errMsg,cause);
+    }
+
+    /**
+     * 构造函数
+     * @param errMsg
+     */
+    public ZSYServiceException(String errMsg) {
+        super(errMsg);
+    }
+
+}

+ 35 - 0
src/main/java/com/zsy/sass/common/exception/ZSYTokenCreateException.java

@@ -0,0 +1,35 @@
+package com.zsy.sass.common.exception;
+
+/**
+ * Token授权失败异常
+ *
+ * @author Live.InPast
+ * @date 2018/11/16
+ */
+public class ZSYTokenCreateException extends RuntimeException {
+
+    /**
+     * 构造函数
+     */
+    public ZSYTokenCreateException() {
+
+    }
+
+    /**
+     * 构造函数
+     * @param errMsg
+     */
+    public ZSYTokenCreateException(String errMsg) {
+        super(errMsg);
+    }
+
+    /**
+     * 构造函数
+     * @param errMsg
+     * @param cause
+     */
+    public ZSYTokenCreateException(String errMsg, Throwable cause) {
+        super(errMsg,cause);
+    }
+
+}

+ 35 - 0
src/main/java/com/zsy/sass/common/exception/ZSYTokenValidException.java

@@ -0,0 +1,35 @@
+package com.zsy.sass.common.exception;
+
+/**
+ * Token验证失败异常
+ *
+ * @author Live.InPast
+ * @date 2018/10/23
+ */
+public class ZSYTokenValidException extends RuntimeException {
+
+    /**
+     * 构造函数
+     */
+    public ZSYTokenValidException() {
+
+    }
+
+    /**
+     * 构造函数
+     * @param errMsg
+     */
+    public ZSYTokenValidException(String errMsg) {
+        super(errMsg);
+    }
+
+    /**
+     * 构造函数
+     * @param errMsg
+     * @param cause
+     */
+    public ZSYTokenValidException(String errMsg, Throwable cause) {
+        super(errMsg,cause);
+    }
+
+}

+ 580 - 0
src/main/java/com/zsy/sass/common/tools/RedisUtil.java

@@ -0,0 +1,580 @@
+package com.zsy.sass.common.tools;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.BoundListOperations;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.stereotype.Component;
+import org.springframework.util.CollectionUtils;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * redisTemplate封装
+ *
+ */
+@Component
+public class RedisUtil {
+
+    @Autowired
+    private RedisTemplate<String, Object> redisTemplate;
+
+    public RedisUtil(RedisTemplate<String, Object> redisTemplate) {
+        this.redisTemplate = redisTemplate;
+    }
+
+    /**
+     * 指定缓存失效时间
+     * @param key 键
+     * @param time 时间(秒)
+     * @return
+     */
+    public boolean expire(String key,long time){
+        try {
+            if(time>0){
+                redisTemplate.expire(key, time, TimeUnit.SECONDS);
+            }
+            return true;
+        } catch (Exception e) {
+            e.printStackTrace();
+            return false;
+        }
+    }
+
+    /**
+     * 根据key 获取过期时间
+     * @param key 键 不能为null
+     * @return 时间(秒) 返回0代表为永久有效
+     */
+    public long getExpire(String key){
+        return redisTemplate.getExpire(key,TimeUnit.SECONDS);
+    }
+
+    /**
+     * 判断key是否存在
+     * @param key 键
+     * @return true 存在 false不存在
+     */
+    public boolean hasKey(String key){
+        try {
+            return redisTemplate.hasKey(key);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return false;
+        }
+    }
+
+    /**
+     * 删除缓存
+     * @param key 可以传一个值 或多个
+     */
+    @SuppressWarnings("unchecked")
+    public void del(String ... key){
+        if(key!=null&&key.length>0){
+            if(key.length==1){
+                redisTemplate.delete(key[0]);
+            }else{
+                redisTemplate.delete(CollectionUtils.arrayToList(key));
+            }
+        }
+    }
+
+    //============================String=============================
+    /**
+     * 普通缓存获取
+     * @param key 键
+     * @return 值
+     */
+    public Object get(String key){
+        return key==null?null:redisTemplate.opsForValue().get(key);
+    }
+
+    /**
+     * 普通缓存放入
+     * @param key 键
+     * @param value 值
+     * @return true成功 false失败
+     */
+    public boolean set(String key,Object value) {
+        try {
+            redisTemplate.opsForValue().set(key, value);
+            return true;
+        } catch (Exception e) {
+            e.printStackTrace();
+            return false;
+        }
+    }
+
+    /**
+     * 普通缓存放入并设置时间
+     * @param key 键
+     * @param value 值
+     * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期
+     * @return true成功 false 失败
+     */
+    public boolean set(String key,Object value,long time){
+        try {
+            if(time>0){
+                redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
+            }else{
+                set(key, value);
+            }
+            return true;
+        } catch (Exception e) {
+            e.printStackTrace();
+            return false;
+        }
+    }
+
+    /**
+     * 递增
+     * @param key 键
+     * @param delta 要增加几(大于0)
+     * @return
+     */
+    public long incr(String key, long delta){
+        if(delta<0){
+            throw new RuntimeException("递增因子必须大于0");
+        }
+        return redisTemplate.opsForValue().increment(key, delta);
+    }
+
+    /**
+     * 递减
+     * @param key 键
+     * @param delta 要减少几(小于0)
+     * @return
+     */
+    public long decr(String key, long delta){
+        if(delta<0){
+            throw new RuntimeException("递减因子必须大于0");
+        }
+        return redisTemplate.opsForValue().increment(key, -delta);
+    }
+
+    //================================Map=================================
+    /**
+     * HashGet
+     * @param key 键 不能为null
+     * @param item 项 不能为null
+     * @return 值
+     */
+    public Object hget(String key,String item){
+        return redisTemplate.opsForHash().get(key, item);
+    }
+
+    /**
+     * 获取hashKey对应的所有键值
+     * @param key 键
+     * @return 对应的多个键值
+     */
+    public Map<Object,Object> hmget(String key){
+        return redisTemplate.opsForHash().entries(key);
+    }
+
+    /**
+     * HashSet
+     * @param key 键
+     * @param map 对应多个键值
+     * @return true 成功 false 失败
+     */
+    public boolean hmset(String key, Map<String,Object> map){
+        try {
+            redisTemplate.opsForHash().putAll(key, map);
+            return true;
+        } catch (Exception e) {
+            e.printStackTrace();
+            return false;
+        }
+    }
+
+    /**
+     * HashSet 并设置时间
+     * @param key 键
+     * @param map 对应多个键值
+     * @param time 时间(秒)
+     * @return true成功 false失败
+     */
+    public boolean hmset(String key, Map<String,Object> map, long time){
+        try {
+            redisTemplate.opsForHash().putAll(key, map);
+            if(time>0){
+                expire(key, time);
+            }
+            return true;
+        } catch (Exception e) {
+            e.printStackTrace();
+            return false;
+        }
+    }
+
+    /**
+     * 向一张hash表中放入数据,如果不存在将创建
+     * @param key 键
+     * @param item 项
+     * @param value 值
+     * @return true 成功 false失败
+     */
+    public boolean hset(String key,String item,Object value) {
+        try {
+            redisTemplate.opsForHash().put(key, item, value);
+            return true;
+        } catch (Exception e) {
+            e.printStackTrace();
+            return false;
+        }
+    }
+
+    /**
+     * 向一张hash表中放入数据,如果不存在将创建
+     * @param key 键
+     * @param item 项
+     * @param value 值
+     * @param time 时间(秒)  注意:如果已存在的hash表有时间,这里将会替换原有的时间
+     * @return true 成功 false失败
+     */
+    public boolean hset(String key,String item,Object value,long time) {
+        try {
+            redisTemplate.opsForHash().put(key, item, value);
+            if(time>0){
+                expire(key, time);
+            }
+            return true;
+        } catch (Exception e) {
+            e.printStackTrace();
+            return false;
+        }
+    }
+
+    /**
+     * 删除hash表中的值
+     * @param key 键 不能为null
+     * @param item 项 可以使多个 不能为null
+     */
+    public void hdel(String key, Object... item){
+        redisTemplate.opsForHash().delete(key,item);
+    }
+
+    /**
+     * 判断hash表中是否有该项的值
+     * @param key 键 不能为null
+     * @param item 项 不能为null
+     * @return true 存在 false不存在
+     */
+    public boolean hHasKey(String key, String item){
+        return redisTemplate.opsForHash().hasKey(key, item);
+    }
+
+    /**
+     * hash递增 如果不存在,就会创建一个 并把新增后的值返回
+     * @param key 键
+     * @param item 项
+     * @param by 要增加几(大于0)
+     * @return
+     */
+    public double hincr(String key, String item,double by){
+        return redisTemplate.opsForHash().increment(key, item, by);
+    }
+
+    /**
+     * hash递减
+     * @param key 键
+     * @param item 项
+     * @param by 要减少记(小于0)
+     * @return
+     */
+    public double hdecr(String key, String item,double by){
+        return redisTemplate.opsForHash().increment(key, item,-by);
+    }
+
+    //============================set=============================
+    /**
+     * 根据key获取Set中的所有值
+     * @param key 键
+     * @return
+     */
+    public Set<Object> sGet(String key){
+        try {
+            return redisTemplate.opsForSet().members(key);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
+
+    /**
+     * 根据value从一个set中查询,是否存在
+     * @param key 键
+     * @param value 值
+     * @return true 存在 false不存在
+     */
+    public boolean sHasKey(String key,Object value){
+        try {
+            return redisTemplate.opsForSet().isMember(key, value);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return false;
+        }
+    }
+
+    /**
+     * 将数据放入set缓存
+     * @param key 键
+     * @param values 值 可以是多个
+     * @return 成功个数
+     */
+    public long sSet(String key, Object...values) {
+        try {
+            return redisTemplate.opsForSet().add(key, values);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return 0;
+        }
+    }
+
+    /**
+     * 将set数据放入缓存
+     * @param key 键
+     * @param time 时间(秒)
+     * @param values 值 可以是多个
+     * @return 成功个数
+     */
+    public long sSetAndTime(String key,long time,Object...values) {
+        try {
+            Long count = redisTemplate.opsForSet().add(key, values);
+            if(time>0) {
+                expire(key, time);
+            }
+            return count;
+        } catch (Exception e) {
+            e.printStackTrace();
+            return 0;
+        }
+    }
+
+    /**
+     * 获取set缓存的长度
+     * @param key 键
+     * @return
+     */
+    public long sGetSetSize(String key){
+        try {
+            return redisTemplate.opsForSet().size(key);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return 0;
+        }
+    }
+
+    /**
+     * 移除值为value的
+     * @param key 键
+     * @param values 值 可以是多个
+     * @return 移除的个数
+     */
+    public long setRemove(String key, Object ...values) {
+        try {
+            Long count = redisTemplate.opsForSet().remove(key, values);
+            return count;
+        } catch (Exception e) {
+            e.printStackTrace();
+            return 0;
+        }
+    }
+    //===============================list=================================
+    /**
+     * 获取list缓存的内容
+     * @param key 键
+     * @param start 开始
+     * @param end 结束  0 到 -1代表所有值
+     * @return
+     */
+    public List<Object> lGet(String key, long start, long end){
+        try {
+            return redisTemplate.opsForList().range(key, start, end);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
+
+    /**
+     * 获取list缓存的长度
+     * @param key 键
+     * @return
+     */
+    public long lGetListSize(String key){
+        try {
+            return redisTemplate.opsForList().size(key);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return 0;
+        }
+    }
+
+    /**
+     * 通过索引 获取list中的值
+     * @param key 键
+     * @param index 索引  index>=0时, 0 表头,1 第二个元素,依次类推;index<0时,-1,表尾,-2倒数第二个元素,依次类推
+     * @return
+     */
+    public Object lGetIndex(String key,long index){
+        try {
+            return redisTemplate.opsForList().index(key, index);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
+
+    /**
+     * 将list放入缓存
+     * @param key 键
+     * @param value 值
+     * @return
+     */
+    public boolean lSet(String key, Object value) {
+        try {
+            redisTemplate.opsForList().rightPush(key, value);
+            return true;
+        } catch (Exception e) {
+            e.printStackTrace();
+            return false;
+        }
+    }
+
+    /**
+     * 将list放入缓存
+     * @param key 键
+     * @param value 值
+     * @param time 时间(秒)
+     * @return
+     */
+    public boolean lSet(String key, Object value, long time) {
+        try {
+            redisTemplate.opsForList().rightPush(key, value);
+            if (time > 0) {
+                expire(key, time);
+            }
+            return true;
+        } catch (Exception e) {
+            e.printStackTrace();
+            return false;
+        }
+    }
+
+    /**
+     * 将list放入缓存
+     * @param key 键
+     * @param value 值
+     * @return
+     */
+    public boolean lSet(String key, List<Object> value) {
+        try {
+            redisTemplate.opsForList().rightPushAll(key, value);
+            return true;
+        } catch (Exception e) {
+            e.printStackTrace();
+            return false;
+        }
+    }
+
+    /**
+     * 将list放入缓存
+     * @param key 键
+     * @param value 值
+     * @param time 时间(秒)
+     * @return
+     */
+    public boolean lSet(String key, List<Object> value, long time) {
+        try {
+            redisTemplate.opsForList().rightPushAll(key, value);
+            if (time > 0) {
+                expire(key, time);
+            }
+            return true;
+        } catch (Exception e) {
+            e.printStackTrace();
+            return false;
+        }
+    }
+
+    /**
+     * 根据索引修改list中的某条数据
+     * @param key 键
+     * @param index 索引
+     * @param value 值
+     * @return
+     */
+    public boolean lUpdateIndex(String key, long index,Object value) {
+        try {
+            redisTemplate.opsForList().set(key, index, value);
+            return true;
+        } catch (Exception e) {
+            e.printStackTrace();
+            return false;
+        }
+    }
+
+    /**
+     * 移除N个值为value
+     * @param key 键
+     * @param count 移除多少个
+     * @param value 值
+     * @return 移除的个数
+     */
+    public long lRemove(String key,long count,Object value) {
+        try {
+            Long remove = redisTemplate.opsForList().remove(key, count, value);
+            return remove;
+        } catch (Exception e) {
+            e.printStackTrace();
+            return 0;
+        }
+    }
+
+    /**
+     * 模糊查询获取key值
+     * @param pattern
+     * @return
+     */
+    public Set keys(String pattern){
+        return redisTemplate.keys(pattern);
+    }
+
+    /**
+     * 使用Redis的消息队列
+     * @param channel
+     * @param message 消息内容
+     */
+    public void convertAndSend(String channel, Object message){
+        redisTemplate.convertAndSend(channel,message);
+    }
+
+    /**
+     * 根据起始结束序号遍历Redis中的list
+     * @param listKey
+     * @param start  起始序号
+     * @param end  结束序号
+     * @return
+     */
+    public List<Object> rangeList(String listKey, long start, long end) {
+        //绑定操作
+        BoundListOperations<String, Object> boundValueOperations = redisTemplate.boundListOps(listKey);
+        //查询数据
+        return boundValueOperations.range(start, end);
+    }
+    /**
+     * 弹出右边的值 --- 并且移除这个值
+     * @param listKey
+     */
+    public Object rifhtPop(String listKey){
+        //绑定操作
+        BoundListOperations<String, Object> boundValueOperations = redisTemplate.boundListOps(listKey);
+        return boundValueOperations.rightPop();
+    }
+
+    //=========BoundListOperations 用法 End============
+
+}

+ 231 - 0
src/main/java/com/zsy/sass/common/tools/ZSYResult.java

@@ -0,0 +1,231 @@
+package com.zsy.sass.common.tools;
+
+import com.alibaba.fastjson.JSONObject;
+import com.alibaba.fastjson.serializer.SerializerFeature;
+import com.alibaba.fastjson.serializer.ValueFilter;
+import com.google.common.base.Strings;
+import com.zsy.sass.common.exception.*;
+
+
+import java.io.Serializable;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * 知心慧学微服务统一返回值
+ *
+ * @author Live.InPast
+ * @date 2018/10/23
+ */
+public class ZSYResult<T> implements Serializable {
+
+	/**
+	 * 成功
+	 */
+	public static final String SUCCESS = "00";
+
+	/**
+	 * 通用失败(业务异常)
+	 */
+	public static final String FAIL = "01";
+
+	/**
+	 * 请求参数错误
+	 */
+	public static final String PARAM_ERROR = "400";
+
+	/**
+	 * 数据异常
+	 */
+	public static final String CODE_ERROR = "401";
+
+	/**
+	 * 数据库操作异常
+	 */
+	public static final String DB_ERROR = "402";
+
+	/**
+	 * 禁止访问异常
+	 */
+	public static final String FORBIDDEN = "403";
+
+	/**
+	 * 调用外部http接口异常
+	 */
+	public static final String API_ERROR = "407";
+
+	/**
+	 * 服务异常
+	 */
+	public static final String SERVER_ERROR = "500";
+
+	/**
+	 * 需要登录
+	 */
+	public static final String NEED_LOGIN = "10000";
+
+	/**
+	 * 需要重新授权
+	 */
+	public static final String NEED_AUTHORIATION = "10001";
+
+	public static final  String ERR_OK_MSG = "执行成功";
+	public static final  String ERR_FAIL_MSG = "执行失败";
+	public static final String ERR_NEED_LOGIN_MSG = "Token验证失败";
+
+	/**
+	 * 最大整数,超过该数前端将丢失精度
+	 */
+	private static final Long MAX_VALUE_TO_STRING = 9007199254740992L;
+
+
+	/**
+	 * 操作码
+	 * 00 代表成功
+	 * XX 代表失败
+	 */
+	private String errCode;
+
+	/**
+	 * 操作说明
+	 */
+	private String errMsg;
+
+	/**
+	 * 附加数据
+	 */
+	private T data;
+
+	private ZSYResult(){}
+
+	private ZSYResult(String errCode){
+		this.errCode = errCode;
+	}
+
+	/**
+	 * 成功
+	 * @return
+	 */
+	public static ZSYResult success(){
+		ZSYResult result = new ZSYResult(SUCCESS);
+		result.errMsg = ERR_OK_MSG;
+		return result;
+	}
+
+	/**
+	 * 失败
+	 * @return
+	 */
+	public static ZSYResult fail(){
+		ZSYResult result = new ZSYResult(FAIL);
+		result.errMsg = ERR_FAIL_MSG;
+		return result;
+	}
+	public static ZSYResult fail(String errCode){
+		ZSYResult result = new ZSYResult(errCode);
+		result.errMsg = ERR_FAIL_MSG;
+		return result;
+	}
+
+
+	/**
+	 * 设置返回结果
+	 * @param errMsg
+	 * @return
+	 */
+	public ZSYResult msg(String errMsg){
+		this.errMsg = errMsg;
+		return this;
+	}
+
+	/**
+	 * 设置返回数据
+	 * @return
+	 */
+	public ZSYResult data(T data){
+		this.data = data;
+		return this;
+	}
+
+
+	/**
+	 * 构建返回值(已过时)
+	 * @return
+	 */
+	@Deprecated
+	public String build(){
+		if (Strings.isNullOrEmpty(this.errCode)){
+			this.errCode = FAIL;
+			this.errMsg = ERR_FAIL_MSG;
+		}
+		return JSONObject.toJSONString(this, (ValueFilter) (object, name, value) -> {
+			if (value instanceof Long &&
+					((Long) value).longValue() > MAX_VALUE_TO_STRING){
+				return value.toString();
+			}
+			if (value instanceof List) {
+				return ((List) value).stream().map(val->{
+					if (val instanceof Long &&
+							((Long) value).longValue() > MAX_VALUE_TO_STRING){
+						return val.toString();
+					}
+					return val;
+				}).collect(Collectors.toList());
+			}
+
+			return value;
+		}, SerializerFeature.WriteMapNullValue,
+				SerializerFeature.WriteNullListAsEmpty,
+				SerializerFeature.WriteNullStringAsEmpty);
+	}
+
+	/**
+	 * 内部服务数据处理
+	 * @return
+	 */
+	public static ZSYResult attach(Object t){
+		return success().data(t);
+	}
+
+	/**
+	 * 内部服务数据获取
+	 * @return
+	 */
+	public T get(){
+		if (Strings.isNullOrEmpty(this.errCode)) {
+			throw new ZSYServiceException(this.errMsg);
+		}
+		if (!this.errCode.equals(SUCCESS)){
+			switch (this.errCode){
+				case DB_ERROR:
+					throw new ZSYDbException(this.errMsg);
+				case API_ERROR:
+					throw new ZSYApiException(this.errMsg);
+				case SERVER_ERROR:
+					throw new ZSYServerException(this.errMsg);
+				case NEED_LOGIN:
+					throw new ZSYTokenValidException(this.errMsg);
+				default:
+					throw new ZSYServiceException(this.errMsg);
+			}
+		}
+		if (this.data==null){
+			return null;
+		}
+		return this.data;
+	}
+
+
+	public String getErrCode() {
+		return errCode;
+	}
+
+	public String getErrMsg() {
+		return errMsg;
+	}
+
+	public T getData() {
+		return data;
+	}
+
+}

+ 104 - 0
src/main/java/com/zsy/sass/config/RedisConfig.java

@@ -0,0 +1,104 @@
+package com.zsy.sass.config;
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.PropertyAccessor;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.springframework.cache.annotation.CachingConfigurerSupport;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.redis.connection.RedisConnectionFactory;
+import org.springframework.data.redis.core.*;
+import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
+import org.springframework.data.redis.serializer.StringRedisSerializer;
+
+/**
+ * springboot RedisTemplate 自动配置比较简陋
+ * 自定义 RedisTemplate 配置
+ */
+@Configuration
+public class RedisConfig extends CachingConfigurerSupport {
+
+    @Bean
+    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory){
+
+        RedisTemplate<String, Object> template = new RedisTemplate<>();
+        //配置连接工厂
+        template.setConnectionFactory(factory);
+        //使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值(默认使用JDK的序列化方式)
+        Jackson2JsonRedisSerializer jsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
+
+        ObjectMapper objectMapper = new ObjectMapper();
+        // 指定要序列化的域,field,get和set,以及修饰符范围,ANY是都有包括private和public
+        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
+        // 指定序列化输入的类型,类必须是非final修饰的,final修饰的类,比如String,Integer等会跑出异常
+        objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
+        jsonRedisSerializer.setObjectMapper(objectMapper);
+
+        // 值采用json序列化
+        template.setValueSerializer(jsonRedisSerializer);
+        //使用StringRedisSerializer来序列化和反序列化redis的key值
+        template.setKeySerializer(new StringRedisSerializer());
+
+        // 设置hash key 和value序列化模式
+        template.setHashKeySerializer(new StringRedisSerializer());
+        template.setHashValueSerializer(jsonRedisSerializer);
+        template.afterPropertiesSet();
+
+        return template;
+    }
+
+    /**
+     * 对hash类型的数据操作
+     *
+     * @param redisTemplate
+     * @return
+     */
+    @Bean
+    public HashOperations<String, String, Object> hashOperations(RedisTemplate<String, Object> redisTemplate) {
+        return redisTemplate.opsForHash();
+    }
+
+    /**
+     * 对redis字符串类型数据操作
+     *
+     * @param redisTemplate
+     * @return
+     */
+    @Bean
+    public ValueOperations<String, Object> valueOperations(RedisTemplate<String, Object> redisTemplate) {
+        return redisTemplate.opsForValue();
+    }
+
+    /**
+     * 对链表类型的数据操作
+     *
+     * @param redisTemplate
+     * @return
+     */
+    @Bean
+    public ListOperations<String, Object> listOperations(RedisTemplate<String, Object> redisTemplate) {
+        return redisTemplate.opsForList();
+    }
+
+    /**
+     * 对无序集合类型的数据操作
+     *
+     * @param redisTemplate
+     * @return
+     */
+    @Bean
+    public SetOperations<String, Object> setOperations(RedisTemplate<String, Object> redisTemplate) {
+        return redisTemplate.opsForSet();
+    }
+
+    /**
+     * 对有序集合类型的数据操作
+     *
+     * @param redisTemplate
+     * @return
+     */
+    @Bean
+    public ZSetOperations<String, Object> zSetOperations(RedisTemplate<String, Object> redisTemplate) {
+        return redisTemplate.opsForZSet();
+    }
+}

+ 124 - 0
src/main/java/com/zsy/sass/model/bo/StudentExam.java

@@ -0,0 +1,124 @@
+package com.zsy.sass.model.bo;
+
+/**
+ * Created by yqq on 2019/6/28.
+ */
+public class StudentExam {
+
+    /**
+     * 学生ID
+     */
+    private String studentId;
+
+    /**
+     * 学校ID
+     */
+    private String schoolId;
+
+    /**
+     * 班级ID
+     */
+    private String classId;
+
+    /**
+     * 班级名称
+     */
+    private String clazzName;
+
+    /**
+     * 考试ID
+     */
+    private String examId;
+
+    /**
+     * 得分
+     */
+    private Double scoring;
+
+    /**
+     *是否缺考
+     */
+    private Integer missExam;
+
+    /**
+     * 学科
+     */
+    private Integer subjectId;
+
+    /**
+     * 试卷总分
+     */
+    private Double totalScore;
+
+    public String getStudentId() {
+        return studentId;
+    }
+
+    public void setStudentId(String studentId) {
+        this.studentId = studentId;
+    }
+
+    public String getSchoolId() {
+        return schoolId;
+    }
+
+    public void setSchoolId(String schoolId) {
+        this.schoolId = schoolId;
+    }
+
+    public String getClassId() {
+        return classId;
+    }
+
+    public void setClassId(String classId) {
+        this.classId = classId;
+    }
+
+    public String getClazzName() {
+        return clazzName;
+    }
+
+    public void setClazzName(String clazzName) {
+        this.clazzName = clazzName;
+    }
+
+    public String getExamId() {
+        return examId;
+    }
+
+    public void setExamId(String examId) {
+        this.examId = examId;
+    }
+
+    public Double getScoring() {
+        return scoring;
+    }
+
+    public void setScoring(Double scoring) {
+        this.scoring = scoring;
+    }
+
+    public Integer getMissExam() {
+        return missExam;
+    }
+
+    public void setMissExam(Integer missExam) {
+        this.missExam = missExam;
+    }
+
+    public Integer getSubjectId() {
+        return subjectId;
+    }
+
+    public void setSubjectId(Integer subjectId) {
+        this.subjectId = subjectId;
+    }
+
+    public Double getTotalScore() {
+        return totalScore;
+    }
+
+    public void setTotalScore(Double totalScore) {
+        this.totalScore = totalScore;
+    }
+}

+ 132 - 0
src/main/java/com/zsy/sass/model/dto/request/SchoolLevelCountReqDTO.java

@@ -0,0 +1,132 @@
+package com.zsy.sass.model.dto.request;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+
+import javax.validation.constraints.*;
+import java.math.BigDecimal;
+import java.util.List;
+
+/**
+ * Created by yqq on 2019/6/27.
+ */
+@ApiModel
+public class SchoolLevelCountReqDTO {
+
+    @ApiModelProperty("考试ID")
+    @NotBlank(message = "考试ID不能为空")
+    private String examId;
+
+    @ApiModelProperty("学校ID")
+    @NotBlank(message = "学校ID不能为空")
+    private String schoolId;
+
+    @ApiModelProperty("0:按分数; 1:按人数;2:恢复默认")
+    @NotNull(message = "类型不能为空")
+    @Min(value = 0,message = "类型不合法")
+    @Max(value = 2,message = "类型不合法")
+    private Integer type;
+
+    @ApiModelProperty("A档线分数")
+    private BigDecimal levelA;
+
+    @ApiModelProperty("B档线分数")
+    private BigDecimal levelB;
+
+    @ApiModelProperty("C档线分数")
+    private BigDecimal levelC;
+
+    @ApiModelProperty("A档线人数")
+    private Integer numA;
+
+    @ApiModelProperty("B档线人数")
+    private Integer numB;
+
+    @ApiModelProperty("C档线人数")
+    private Integer numC;
+
+    @ApiModelProperty("考试学科集合")
+    @NotNull(message = "学科ID集合不能为空")
+    @NotEmpty(message = "学科ID集合不能为空")
+    private List<String> subjectIds;
+
+    public String getExamId() {
+        return examId;
+    }
+
+    public void setExamId(String examId) {
+        this.examId = examId;
+    }
+
+    public String getSchoolId() {
+        return schoolId;
+    }
+
+    public void setSchoolId(String schoolId) {
+        this.schoolId = schoolId;
+    }
+
+    public Integer getType() {
+        return type;
+    }
+
+    public void setType(Integer type) {
+        this.type = type;
+    }
+
+    public BigDecimal getLevelA() {
+        return levelA;
+    }
+
+    public void setLevelA(BigDecimal levelA) {
+        this.levelA = levelA;
+    }
+
+    public BigDecimal getLevelB() {
+        return levelB;
+    }
+
+    public void setLevelB(BigDecimal levelB) {
+        this.levelB = levelB;
+    }
+
+    public BigDecimal getLevelC() {
+        return levelC;
+    }
+
+    public void setLevelC(BigDecimal levelC) {
+        this.levelC = levelC;
+    }
+
+    public Integer getNumA() {
+        return numA;
+    }
+
+    public void setNumA(Integer numA) {
+        this.numA = numA;
+    }
+
+    public Integer getNumB() {
+        return numB;
+    }
+
+    public void setNumB(Integer numB) {
+        this.numB = numB;
+    }
+
+    public Integer getNumC() {
+        return numC;
+    }
+
+    public void setNumC(Integer numC) {
+        this.numC = numC;
+    }
+
+    public List<String> getSubjectIds() {
+        return subjectIds;
+    }
+
+    public void setSubjectIds(List<String> subjectIds) {
+        this.subjectIds = subjectIds;
+    }
+}

+ 122 - 0
src/main/java/com/zsy/sass/model/dto/response/SchoolLevelCountNewResDTO.java

@@ -0,0 +1,122 @@
+package com.zsy.sass.model.dto.response;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+
+import java.math.BigDecimal;
+
+@ApiModel
+public class SchoolLevelCountNewResDTO {
+    @ApiModelProperty("班级名称")
+    private String clazzName;
+
+    @ApiModelProperty("有效考试人数")
+    private Integer studentNum;
+
+    @ApiModelProperty("A档线信息")
+    private LevelStudentAndScore levelA;
+
+    @ApiModelProperty("B档线信息")
+    private LevelStudentAndScore levelB;
+
+    @ApiModelProperty("C档线信息")
+    private LevelStudentAndScore levelC;
+
+    public String getClazzName() {
+        return clazzName;
+    }
+
+    public void setClazzName(String clazzName) {
+        this.clazzName = clazzName;
+    }
+
+    public Integer getStudentNum() {
+        return studentNum;
+    }
+
+    public void setStudentNum(Integer studentNum) {
+        this.studentNum = studentNum;
+    }
+
+    public LevelStudentAndScore getLevelA() {
+        return levelA;
+    }
+
+    public void setLevelA(LevelStudentAndScore levelA) {
+        this.levelA = levelA;
+    }
+
+    public LevelStudentAndScore getLevelB() {
+        return levelB;
+    }
+
+    public void setLevelB(LevelStudentAndScore levelB) {
+        this.levelB = levelB;
+    }
+
+    public LevelStudentAndScore getLevelC() {
+        return levelC;
+    }
+
+    public void setLevelC(LevelStudentAndScore levelC) {
+        this.levelC = levelC;
+    }
+
+    @ApiModel
+    public static class LevelStudentAndScore {
+        @ApiModelProperty("人数")
+        private Integer num;
+
+        @ApiModelProperty("累计人数")
+        private Integer countNum;
+
+        @ApiModelProperty("分数线")
+        private BigDecimal score;
+
+        @ApiModelProperty("达线率")
+        private BigDecimal rate;
+
+        @ApiModelProperty("平均分")
+        private BigDecimal avgScoring;
+
+        public Integer getCountNum() {
+            return countNum;
+        }
+
+        public void setCountNum(Integer countNum) {
+            this.countNum = countNum;
+        }
+
+        public BigDecimal getAvgScoring() {
+            return avgScoring;
+        }
+
+        public void setAvgScoring(BigDecimal avgScoring) {
+            this.avgScoring = avgScoring;
+        }
+
+        public Integer getNum() {
+            return num;
+        }
+
+        public void setNum(Integer num) {
+            this.num = num;
+        }
+
+        public BigDecimal getScore() {
+            return score;
+        }
+
+        public void setScore(BigDecimal score) {
+            this.score = score;
+        }
+
+        public BigDecimal getRate() {
+            return rate;
+        }
+
+        public void setRate(BigDecimal rate) {
+            this.rate = rate;
+        }
+    }
+}

+ 122 - 0
src/main/java/com/zsy/sass/model/pojo/Exam.java

@@ -0,0 +1,122 @@
+package com.zsy.sass.model.pojo;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * Created by yqq on 2019/6/27.
+ */
+public class Exam implements Serializable {
+
+    private static final long serialVersionUID = 3537921742065870581L;
+
+    private Long exam_id;
+    private String exam_name;
+    private int grade;
+    private int type;
+    private String remark;
+    private Long begin_time;
+    private Long end_time;
+    private String signup;
+    private Long mech_id;
+    private int status;
+    private Long create_by;
+    private Long create_time;
+
+
+    public Long getExam_id() {
+        return exam_id;
+    }
+
+    public void setExam_id(Long exam_id) {
+        this.exam_id = exam_id;
+    }
+
+    public String getExam_name() {
+        return exam_name;
+    }
+
+    public void setExam_name(String exam_name) {
+        this.exam_name = exam_name;
+    }
+
+    public int getGrade() {
+        return grade;
+    }
+
+    public void setGrade(int grade) {
+        this.grade = grade;
+    }
+
+    public int getType() {
+        return type;
+    }
+
+    public void setType(int type) {
+        this.type = type;
+    }
+
+    public String getRemark() {
+        return remark;
+    }
+
+    public void setRemark(String remark) {
+        this.remark = remark;
+    }
+
+    public Long getBegin_time() {
+        return begin_time;
+    }
+
+    public void setBegin_time(Long begin_time) {
+        this.begin_time = begin_time;
+    }
+
+    public Long getEnd_time() {
+        return end_time;
+    }
+
+    public void setEnd_time(Long end_time) {
+        this.end_time = end_time;
+    }
+
+    public String getSignup() {
+        return signup;
+    }
+
+    public void setSignup(String signup) {
+        this.signup = signup;
+    }
+
+    public Long getMech_id() {
+        return mech_id;
+    }
+
+    public void setMech_id(Long mech_id) {
+        this.mech_id = mech_id;
+    }
+
+    public int getStatus() {
+        return status;
+    }
+
+    public void setStatus(int status) {
+        this.status = status;
+    }
+
+    public Long getCreate_by() {
+        return create_by;
+    }
+
+    public void setCreate_by(Long create_by) {
+        this.create_by = create_by;
+    }
+
+    public Long getCreate_time() {
+        return create_time;
+    }
+
+    public void setCreate_time(Long create_time) {
+        this.create_time = create_time;
+    }
+}

+ 59 - 0
src/main/java/com/zsy/sass/model/pojo/User.java

@@ -0,0 +1,59 @@
+package com.zsy.sass.model.pojo;
+
+import java.util.Date;
+
+/**
+ * Created by yqq on 2019/7/18.
+ */
+public class User {
+
+    private String uid;
+
+    private String name;
+
+    private Integer age;
+
+    private Date birthday;
+
+    public User() {
+    }
+
+    public User(String uid, String name, Integer age, Date birthday) {
+        this.uid = uid;
+        this.name = name;
+        this.age = age;
+        this.birthday = birthday;
+    }
+
+    public String getUid() {
+        return uid;
+    }
+
+    public void setUid(String uid) {
+        this.uid = uid;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public Integer getAge() {
+        return age;
+    }
+
+    public void setAge(Integer age) {
+        this.age = age;
+    }
+
+    public Date getBirthday() {
+        return birthday;
+    }
+
+    public void setBirthday(Date birthday) {
+        this.birthday = birthday;
+    }
+}

+ 45 - 0
src/main/java/com/zsy/sass/report/controller/ExamController.java

@@ -0,0 +1,45 @@
+package com.zsy.sass.report.controller;
+
+import com.zsy.sass.common.tools.ZSYResult;
+import com.zsy.sass.model.pojo.Exam;
+import com.zsy.sass.report.service.ExamService;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.*;
+import java.util.List;
+
+
+
+/**
+ * Created by yqq on 2019/6/27.
+ */
+@RestController
+@RequestMapping("/exam")
+public class ExamController {
+
+    private static final Log log = LogFactory.getLog(ExamController.class);
+
+    @Autowired
+    private ExamService examService;
+
+    @RequestMapping(value = "/findAll", method = RequestMethod.GET)
+    public String findAll(){
+        log.info("find all exams");
+        return ZSYResult.success().data(examService.findAll()).build();
+    }
+
+
+
+
+
+
+
+
+
+
+
+
+
+}

+ 62 - 0
src/main/java/com/zsy/sass/report/controller/ExamReportController.java

@@ -0,0 +1,62 @@
+package com.zsy.sass.report.controller;
+
+import com.zsy.sass.common.tools.ZSYResult;
+import com.zsy.sass.model.dto.request.SchoolLevelCountReqDTO;
+import com.zsy.sass.model.dto.response.SchoolLevelCountNewResDTO;
+import com.zsy.sass.report.service.ExamReportService;
+import io.swagger.annotations.*;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import javax.validation.Valid;
+import java.util.List;
+
+/**
+ * Created by yqq on 2019/6/27.
+ */
+@RestController
+@RequestMapping("/exam-report")
+public class ExamReportController {
+
+    private static final Log log = LogFactory.getLog(ExamReportController.class);
+
+    @Autowired
+    private ExamReportService examReportService;
+
+    @ApiOperation("通过id查询考试")
+    @RequestMapping(value = "/find-exam/{id}", method = RequestMethod.GET)
+    public String findExamById(@PathVariable("id") Long id){
+        log.info("find a exam");
+        return ZSYResult.success().data(examReportService.findExamById(id)).build();
+    }
+
+
+    /**
+     * 本校报告-分档达线统计
+     */
+    @ApiOperation("sass本校报告-分档达线统计")
+    @ApiResponses({@ApiResponse(code = 200, message = "执行成功",response = SchoolLevelCountNewResDTO.class)})
+    @PostMapping("/school/level")
+    public String levelCount(@Valid @RequestBody SchoolLevelCountReqDTO countReqDTO){
+        SchoolLevelCountNewResDTO vo = examReportService.levelCount(countReqDTO);
+        return ZSYResult.success().data(vo).build();
+    }
+
+    /**
+     * 本校报告-分档达线统计列表
+     */
+    @ApiOperation("sass本校报告-分档达线统计")
+    @PostMapping("/school/level/list")
+    public String levelCountList(@Valid @RequestBody SchoolLevelCountReqDTO countReqDTO){
+        List<SchoolLevelCountNewResDTO> list = examReportService.levelCountList(countReqDTO);
+        return ZSYResult.success().data(list).build();
+    }
+
+
+    /**
+     * 本校报告-分档达线统计列表导出
+     */
+
+}

+ 29 - 0
src/main/java/com/zsy/sass/report/controller/RedisController.java

@@ -0,0 +1,29 @@
+package com.zsy.sass.report.controller;
+
+
+import com.zsy.sass.common.tools.ZSYResult;
+import com.zsy.sass.report.service.RedisService;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+@RequestMapping("/redis")
+public class RedisController {
+
+    private static final Log log = LogFactory.getLog(RedisController.class);
+
+    @Autowired
+    private RedisService redisServiceImpl;
+
+    @RequestMapping(value = "/findExamInfo/{key}", method = RequestMethod.GET)
+    public String findExamInfo(@PathVariable("key") String key){
+        log.info("info of exams");
+        return ZSYResult.success().data(redisServiceImpl.findExamInfo(key)).build();
+    }
+
+}

+ 20 - 0
src/main/java/com/zsy/sass/report/dao/ExamDao.java

@@ -0,0 +1,20 @@
+package com.zsy.sass.report.dao;
+
+import com.zsy.sass.model.pojo.Exam;
+import java.util.List;
+
+/**
+ * Created by yqq on 2019/6/27.
+ */
+public interface ExamDao {
+
+    /**
+     *find exam by id
+     */
+    Exam findByID(Long exam_id);
+
+    /**
+     * find all exam
+     */
+    List<Exam> findAll();
+}

+ 30 - 0
src/main/java/com/zsy/sass/report/dao/ExamReportDao.java

@@ -0,0 +1,30 @@
+package com.zsy.sass.report.dao;
+
+import com.zsy.sass.model.bo.StudentExam;
+import com.zsy.sass.model.pojo.Exam;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+/**
+ * Created by yqq on 2019/6/27.
+ */
+public interface ExamReportDao {
+
+    /**
+     *find exam by id
+     */
+    Exam findExamById(Long id);
+
+    /**
+     * student exam info
+     * @param examId
+     * @param schoolId
+     * @param subjectIds
+     * @return
+     */
+    List<StudentExam> selectByExamId(String examId, String schoolId, List<String> subjectIds);
+
+
+    BigDecimal getTotalScoreByExamIdAndSubjectIds(String examId, List<String> subjectIds);
+}

+ 5 - 0
src/main/java/com/zsy/sass/report/dao/RedisDao.java

@@ -0,0 +1,5 @@
+package com.zsy.sass.report.dao;
+
+public interface RedisDao {
+    String findExamInfo();
+}

+ 30 - 0
src/main/java/com/zsy/sass/report/dao/impl/ExamDaoImpl.java

@@ -0,0 +1,30 @@
+package com.zsy.sass.report.dao.impl;
+
+import com.zsy.sass.model.pojo.Exam;
+import com.zsy.sass.report.dao.ExamDao;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.jdbc.core.BeanPropertyRowMapper;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.stereotype.Repository;
+import java.util.List;
+
+/**
+ * Created by yqq on 2019/6/27.
+ */
+@Repository
+public class ExamDaoImpl implements ExamDao {
+
+    @Autowired
+    private JdbcTemplate jdbcTemplate;
+
+    @Override
+    public Exam findByID(Long exam_id) {
+        return null;
+    }
+
+    @Override
+    public List<Exam> findAll() {
+        String sql = "select * from exam";
+        return jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(Exam.class));
+    }
+}

+ 74 - 0
src/main/java/com/zsy/sass/report/dao/impl/ExamReportDaoImpl.java

@@ -0,0 +1,74 @@
+package com.zsy.sass.report.dao.impl;
+
+//import com.zhixinhuixue.jdbc.context.ZSYDao;
+
+import com.zsy.sass.model.bo.StudentExam;
+import com.zsy.sass.model.pojo.Exam;
+import com.zsy.sass.report.dao.ExamReportDao;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.jdbc.core.BeanPropertyRowMapper;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.stereotype.Repository;
+import java.math.BigDecimal;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * Created by yqq on 2019/6/27.
+ */
+@Repository
+public class ExamReportDaoImpl implements ExamReportDao {
+
+    @Autowired
+    private JdbcTemplate jdbcTemplate;
+
+
+
+
+    @Override
+    public Exam findExamById(Long id) {
+        String sql = "select * from exam where exam_id = ?";
+        return jdbcTemplate.queryForObject(sql, new Object[]{id},new BeanPropertyRowMapper<>(Exam.class));
+    }
+
+    @Override
+    public List<StudentExam> selectByExamId(String examId, String schoolId, List<String> subjectIds) {
+        StringBuffer sql = new StringBuffer();
+
+        sql.append(" SELECT ");
+        sql.append("     ess.exam_id, ");
+        sql.append("     ess.school_id, ");
+        sql.append("     ess.class_id, ");
+        sql.append("     ess.student_id, ");
+        sql.append("     ess.subject_id, ");
+        sql.append("     ess.is_miss_exam, ");
+        sql.append("     ess.scoring, ");
+        sql.append("     exam_class.class_name, ");
+        sql.append("     exam_subject.total_score ");
+        sql.append(" FROM ");
+        sql.append("     exam_subject_student ess ");
+        sql.append("     LEFT JOIN exam_subject ON ess.exam_id = exam_subject.exam_id ");
+        sql.append("     AND ess.subject_id = exam_subject.subject_id ");
+        sql.append("     LEFT JOIN exam_class ON ess.exam_id = exam_class.exam_id ");
+        sql.append("     AND ess.school_id = exam_class.school_id ");
+        sql.append("     AND ess.class_id = exam_class.class_id ");
+        sql.append(" WHERE ");
+        sql.append("     ess.exam_id = ? ");
+        sql.append("     AND ess.school_id = ? ");
+        sql.append("     AND ess.subject_id in("+subjectIds.stream().map(subjectId -> "?").collect(Collectors.joining(",")) +")");
+
+
+
+        //return selectList(sql.toString(),StudentExamBOMap, builder.get());
+
+        return null;
+    }
+
+    @Override
+    public BigDecimal getTotalScoreByExamIdAndSubjectIds(String examId, List<String> subjectIds) {
+
+        String sql = "SELECT sum(exam_subject.total_score) as totalScore from exam_subject where exam_subject.exam_id =? and exam_subject.subject_id in ("+subjectIds.stream().map(subjectId -> "?").collect(Collectors.joining(",")) +")";
+        jdbcTemplate.queryForMap(sql,new Object[]{examId});
+        return null;
+    }
+}

+ 14 - 0
src/main/java/com/zsy/sass/report/dao/impl/RedisDaoImpl.java

@@ -0,0 +1,14 @@
+package com.zsy.sass.report.dao.impl;
+
+import com.zsy.sass.report.dao.RedisDao;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public class RedisDaoImpl implements RedisDao {
+
+    @Override
+    public String findExamInfo() {
+
+        return null;
+    }
+}

+ 32 - 0
src/main/java/com/zsy/sass/report/service/ExamReportService.java

@@ -0,0 +1,32 @@
+package com.zsy.sass.report.service;
+
+import com.zsy.sass.model.dto.request.SchoolLevelCountReqDTO;
+import com.zsy.sass.model.dto.response.SchoolLevelCountNewResDTO;
+import com.zsy.sass.model.pojo.Exam;
+
+import java.util.List;
+
+/**
+ * Created by yqq on 2019/6/27.
+ */
+public interface ExamReportService {
+
+    /**
+     *find exam by id
+     */
+    Exam findExamById(Long id);
+
+    /**
+     * sass本校报告-分档达线统计
+     * @param countReqDTO
+     * @return
+     */
+    SchoolLevelCountNewResDTO levelCount(SchoolLevelCountReqDTO countReqDTO);
+
+    /**
+     * sass本校报告-分档达线统计列表
+     * @param countReqDTO
+     * @return
+     */
+    List<SchoolLevelCountNewResDTO> levelCountList(SchoolLevelCountReqDTO countReqDTO);
+}

+ 15 - 0
src/main/java/com/zsy/sass/report/service/ExamService.java

@@ -0,0 +1,15 @@
+package com.zsy.sass.report.service;
+
+import com.zsy.sass.model.pojo.Exam;
+import java.util.List;
+
+/**
+ * Created by yqq on 2019/6/27.
+ */
+public interface ExamService {
+
+    /**
+     * find all exam
+     */
+    List<Exam> findAll();
+}

+ 6 - 0
src/main/java/com/zsy/sass/report/service/RedisService.java

@@ -0,0 +1,6 @@
+package com.zsy.sass.report.service;
+
+public interface RedisService {
+
+    String findExamInfo(String key);
+}

+ 635 - 0
src/main/java/com/zsy/sass/report/service/impl/ExamReportServiceImpl.java

@@ -0,0 +1,635 @@
+package com.zsy.sass.report.service.impl;
+
+import com.google.common.collect.Lists;
+import com.zsy.sass.common.enums.ZSYLevelCountType;
+import com.zsy.sass.common.exception.ZSYServiceException;
+import com.zsy.sass.model.bo.StudentExam;
+import com.zsy.sass.model.dto.request.SchoolLevelCountReqDTO;
+import com.zsy.sass.model.dto.response.SchoolLevelCountNewResDTO;
+import com.zsy.sass.model.pojo.Exam;
+import com.zsy.sass.report.dao.ExamReportDao;
+import com.zsy.sass.report.service.ExamReportService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.util.CollectionUtils;
+import java.math.BigDecimal;
+import java.security.PrivateKey;
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * Created by yqq on 2019/6/27.
+ */
+@Service
+public class ExamReportServiceImpl implements ExamReportService {
+
+    @Autowired
+    private ExamReportDao examReportDao;
+
+    //保留四位小数
+    protected static final int SCALE_4 = 4;
+    //保留两位小数
+    protected static final int SCALE_2 = 2;
+
+    //百分比换算率
+    protected static final BigDecimal DECIMAL_TO_PERCENT = BigDecimal.valueOf(100);
+
+    @Override
+    public Exam findExamById(Long id) {
+        return examReportDao.findExamById(id);
+    }
+
+    @Override
+    public SchoolLevelCountNewResDTO levelCount(SchoolLevelCountReqDTO reqDTO) {
+        //check args
+        check(reqDTO);
+        SchoolLevelCountNewResDTO resDTO = new SchoolLevelCountNewResDTO();
+        SchoolLevelCountNewResDTO.LevelStudentAndScore levelA = new SchoolLevelCountNewResDTO.LevelStudentAndScore();
+        SchoolLevelCountNewResDTO.LevelStudentAndScore levelB = new SchoolLevelCountNewResDTO.LevelStudentAndScore();
+        SchoolLevelCountNewResDTO.LevelStudentAndScore levelC = new SchoolLevelCountNewResDTO.LevelStudentAndScore();
+
+        String examId = reqDTO.getExamId();
+        List<String> subjectIds = reqDTO.getSubjectIds();
+        String schoolId = reqDTO.getSchoolId();
+
+        List<StudentExam> studentExamList = examReportDao.selectByExamId(examId,schoolId,subjectIds);
+        if(CollectionUtils.isEmpty(studentExamList)){
+            throw new ZSYServiceException("查询不到考试成绩");
+        }
+        //查所选考试学科总分
+        BigDecimal totalScore = examReportDao.getTotalScoreByExamIdAndSubjectIds(examId, subjectIds);
+        //按所选学科合并
+        List<StudentExam> sepList = separete(studentExamList);
+        //设置所选学科总分
+        for (StudentExam studentExam : sepList) {
+            studentExam.setTotalScore(totalScore.doubleValue());
+        }
+
+        //去掉缺考学生
+        List<StudentExam> examList = sepList.stream().filter(vo -> vo.getMissExam() == 0).collect(Collectors.toList());
+        if(CollectionUtils.isEmpty(examList)){
+            throw new ZSYServiceException("查询不到考试成绩");
+        }
+        //查询方式一:按照分数分档
+        if (reqDTO.getType() == ZSYLevelCountType.SCORE_COUNT.getValue()) {
+            //找出所有分数 >= A档 的学生
+            List<StudentExam> listA = examList.stream().filter(studentExam -> BigDecimal.valueOf(studentExam.getScoring()).compareTo(reqDTO.getLevelA()) >= 0)
+                    .collect(Collectors.toList());
+            levelA.setNum(listA.size());
+            BigDecimal avglistA = BigDecimal.valueOf(listA.stream().mapToDouble(StudentExam::getScoring).average().orElse(0D))
+                    .setScale(2, BigDecimal.ROUND_DOWN);
+            levelA.setAvgScoring(avglistA);
+            levelA.setScore(reqDTO.getLevelA());
+
+            //找出所有分数 >= B档&&分数小于A档的学生 例如 A档 200分 B档 150 分 C档 100 分  B档就是200>score>=150
+            List<StudentExam> listB = examList.stream().filter(studentExam -> BigDecimal.valueOf(studentExam.getScoring()).compareTo(reqDTO.getLevelB()) >= 0)
+                    .filter(studentExam -> BigDecimal.valueOf(studentExam.getScoring()).compareTo(reqDTO.getLevelA()) < 0)
+                    .collect(Collectors.toList());
+            Long countB = examList.stream().filter(studentExam -> BigDecimal.valueOf(studentExam.getScoring()).compareTo(reqDTO.getLevelB()) >= 0).count();
+            levelB.setNum(listB.size());
+            levelB.setCountNum(countB.intValue());
+            BigDecimal avgB = BigDecimal.valueOf(listB.stream().mapToDouble(StudentExam::getScoring).average().orElse(0D)).setScale(2, BigDecimal.ROUND_DOWN);
+            levelB.setAvgScoring(avgB);
+            levelB.setScore(reqDTO.getLevelB());
+
+            //找出所有分数 >= C档 的学生
+            List<StudentExam> listC = examList.stream()
+                    .filter(studentExam -> BigDecimal.valueOf(studentExam.getScoring()).compareTo(reqDTO.getLevelC()) >= 0)
+                    .filter(studentExam -> BigDecimal.valueOf(studentExam.getScoring()).compareTo(reqDTO.getLevelB()) < 0)
+                    .collect(Collectors.toList());
+
+            Long countC = examList.stream()
+                    .filter(exam -> BigDecimal.valueOf(exam.getScoring()).compareTo(reqDTO.getLevelC()) >= 0).count();
+            levelC.setNum(listC.size());
+            levelC.setCountNum(countC.intValue());
+            BigDecimal avgC = BigDecimal.valueOf(listC.stream().mapToDouble(StudentExam::getScoring).average().orElse(0D)).setScale(2, BigDecimal.ROUND_DOWN);
+            levelC.setAvgScoring(avgC);
+            levelC.setScore(reqDTO.getLevelC());
+
+        }
+
+        //查询方式二:按照人数分档
+        //需求:A档线 设置 100人,就是年级前100名。 B档线设置150人,那就是去掉前100名。在往后取150名(简单来说,就是后面的不包含前面的)
+        //全年级 成绩 倒序 200  157  150  135 126 110
+        List<StudentExam> sortList = examList.stream().sorted(Comparator.comparing(StudentExam::getScoring).reversed()).collect(Collectors.toList());
+        if (reqDTO.getType() == ZSYLevelCountType.NUM_COUNT.getValue()) {
+            if (reqDTO.getNumA() + reqDTO.getNumB() + reqDTO.getNumC() > sortList.size()) {
+                throw new ZSYServiceException("人数填写错误,本次考试一共:" + sortList.size() + "人");
+            }
+            //找出全年级 前xx名  A档人数
+            List<StudentExam> listA = sortList.stream().skip(0).limit(reqDTO.getNumA()).collect(Collectors.toList());
+            levelA.setScore(BigDecimal.valueOf(listA.get(listA.size() - 1).getScoring()));//A档最后一名的成绩
+            levelA.setNum(listA.size());
+            BigDecimal avgA = BigDecimal.valueOf(listA.stream().mapToDouble(StudentExam::getScoring).average().orElse(0D)).setScale(2, BigDecimal.ROUND_DOWN);
+            levelA.setAvgScoring(avgA);
+
+            //找出全年级 前xx名  B档人数
+            List<StudentExam> listB = sortList.stream().skip(reqDTO.getNumA()).limit(reqDTO.getNumB()).collect(Collectors.toList());
+            if (!CollectionUtils.isEmpty(listB)) {
+                levelB.setScore(BigDecimal.valueOf(listB.get(listB.size() - 1).getScoring()));//B档最后一名的成绩
+                levelB.setNum(listB.size());
+                BigDecimal avgB = BigDecimal.valueOf(listB.stream().mapToDouble(StudentExam::getScoring).average().orElse(0D)).setScale(2, BigDecimal.ROUND_DOWN);
+                levelB.setAvgScoring(avgB);
+                levelB.setCountNum(listB.size() + listA.size());
+            }
+
+            //找出全年级 前xx名  C档人数
+            List<StudentExam> listC = sortList.stream().skip(reqDTO.getNumA() + reqDTO.getNumB()).limit(reqDTO.getNumC()).collect(Collectors.toList());
+            if (!CollectionUtils.isEmpty(listC)) {
+                levelC.setScore(BigDecimal.valueOf(listC.get(listC.size() - 1).getScoring()));//C档最后一名的成绩
+                levelC.setNum(listC.size());
+                BigDecimal avgC = BigDecimal.valueOf(listC.stream().mapToDouble(StudentExam::getScoring).average().orElse(0D)).setScale(2, BigDecimal.ROUND_DOWN);
+                levelC.setAvgScoring(avgC);
+                levelC.setCountNum(listB.size() + listA.size() + listC.size());
+            }
+
+        }
+
+        //默认分档
+        if (reqDTO.getType() == ZSYLevelCountType.DEFAYLT_COUNT.getValue()) {
+            return defaultCount(examList);
+        }
+
+        resDTO.setLevelA(levelA);
+        resDTO.setLevelB(levelB);
+        resDTO.setLevelC(levelC);
+        return resDTO;
+    }
+
+    /**
+     *
+     * @param reqDTO
+     * @return
+     */
+    @Override
+    public List<SchoolLevelCountNewResDTO> levelCountList(SchoolLevelCountReqDTO reqDTO) {
+        //check args
+        check(reqDTO);
+
+        String examId = reqDTO.getExamId();
+        List<String> subjectIds = reqDTO.getSubjectIds();
+        String schoolId = reqDTO.getSchoolId();
+
+        List<StudentExam> studentExamList = examReportDao.selectByExamId(examId,schoolId,subjectIds);
+        if(CollectionUtils.isEmpty(studentExamList)){
+            throw new ZSYServiceException("查询不到考试成绩");
+        }
+        //查所选考试学科总分
+        BigDecimal totalScore = examReportDao.getTotalScoreByExamIdAndSubjectIds(examId, subjectIds);
+        //按所选学科合并
+        List<StudentExam> sepList = separete(studentExamList);
+        //设置所选学科总分
+        for (StudentExam studentExam : sepList) {
+            studentExam.setTotalScore(totalScore.doubleValue());
+        }
+
+        //filter this students of missing exam
+        List<StudentExam> examList = sepList.stream().filter(vo -> vo.getMissExam() == 0).collect(Collectors.toList());
+        if(CollectionUtils.isEmpty(examList)){
+            throw new ZSYServiceException("查询不到考试成绩");
+        }
+
+        //response resalut data
+        List<SchoolLevelCountNewResDTO> resDTOList = Lists.newArrayList();
+
+        //查询方式一:按照分数分档
+        if (reqDTO.getType() == ZSYLevelCountType.SCORE_COUNT.getValue()) {
+
+            SchoolLevelCountNewResDTO schoolLevelCountNewResDTO = new SchoolLevelCountNewResDTO();
+            SchoolLevelCountNewResDTO.LevelStudentAndScore levelA = new SchoolLevelCountNewResDTO.LevelStudentAndScore();
+            SchoolLevelCountNewResDTO.LevelStudentAndScore levelB = new SchoolLevelCountNewResDTO.LevelStudentAndScore();
+            SchoolLevelCountNewResDTO.LevelStudentAndScore levelC = new SchoolLevelCountNewResDTO.LevelStudentAndScore();
+            schoolLevelCountNewResDTO.setClazzName("全年级");
+            schoolLevelCountNewResDTO.setStudentNum(examList.size());
+
+
+            List<StudentExam> sortList = examList.stream().sorted(Comparator.comparing(StudentExam::getScoring).reversed()).collect(Collectors.toList());
+
+            //满足找出分数 >= A 档线的学生
+            List<StudentExam> listA = sortList.stream().filter(studentExam -> BigDecimal.valueOf(studentExam.getScoring()).compareTo(reqDTO.getLevelA()) >= 0).collect(Collectors.toList());
+            levelA.setNum(listA.size());
+            levelA.setRate(getRatioPercent(listA.size(), sortList.size()));//达线率=达线人数/考试总人数
+            schoolLevelCountNewResDTO.setLevelA(levelA);
+
+            // B档线的学生
+            List<StudentExam> listB = sortList.stream()
+                    .filter(studentExam -> BigDecimal.valueOf(studentExam.getScoring()).compareTo(reqDTO.getLevelB()) >= 0)
+                    .filter(studentExam -> BigDecimal.valueOf(studentExam.getScoring()).compareTo(reqDTO.getLevelA()) < 0)
+                    .collect(Collectors.toList());
+
+            levelB.setNum(listB.size() + listA.size());
+            levelB.setRate(getRatioPercent(listB.size() + listA.size(), sortList.size()));//达线率=达线人数/考试总人数
+            schoolLevelCountNewResDTO.setLevelB(levelB);
+            // C档线的学生
+            List<StudentExam> listC = sortList.stream()
+                    .filter(studentExam -> BigDecimal.valueOf(studentExam.getScoring()).compareTo(reqDTO.getLevelC()) >= 0)
+                    .filter(studentExam -> BigDecimal.valueOf(studentExam.getScoring()).compareTo(reqDTO.getLevelB()) < 0)
+                    .collect(Collectors.toList());
+
+            levelC.setNum(listC.size() + listB.size() + listA.size());
+            levelC.setRate(getRatioPercent(listC.size() + listB.size() + listA.size(), sortList.size()));//达线率=达线人数/考试总人数
+            schoolLevelCountNewResDTO.setLevelC(levelC);
+            //添加列表第一行数据
+            resDTOList.add(schoolLevelCountNewResDTO);
+            //按班级统计
+            Map<String, List<StudentExam>> map = examList.stream().collect(Collectors.groupingBy(StudentExam::getClassId, LinkedHashMap::new, Collectors.toList()));
+
+            map.forEach((key, value) -> {
+                SchoolLevelCountNewResDTO clazzInfo = new SchoolLevelCountNewResDTO();
+                SchoolLevelCountNewResDTO.LevelStudentAndScore clazzLevelA = new SchoolLevelCountNewResDTO.LevelStudentAndScore();
+                SchoolLevelCountNewResDTO.LevelStudentAndScore clazzLevelB = new SchoolLevelCountNewResDTO.LevelStudentAndScore();
+                SchoolLevelCountNewResDTO.LevelStudentAndScore clazzLevelC = new SchoolLevelCountNewResDTO.LevelStudentAndScore();
+                clazzInfo.setClazzName(value.get(0).getClazzName());
+                clazzInfo.setStudentNum(value.size());
+                List<StudentExam> clazzListA = value.stream().filter(v -> BigDecimal.valueOf(v.getScoring()).compareTo(reqDTO.getLevelA()) >= 0).collect(Collectors.toList());
+                clazzLevelA.setNum(clazzListA.size());
+                clazzLevelA.setRate(getRatioPercent(clazzListA.size(), value.size()));
+
+                List<StudentExam> clazzListB = value.stream()
+                        .filter(v -> BigDecimal.valueOf(v.getScoring()).compareTo(reqDTO.getLevelB()) >= 0)
+                        .filter(v -> BigDecimal.valueOf(v.getScoring()).compareTo(reqDTO.getLevelA()) < 0)
+                        .collect(Collectors.toList());
+                clazzLevelB.setNum(clazzListB.size() + clazzListA.size());
+                clazzLevelB.setRate(getRatioPercent(clazzListB.size() + clazzListA.size(), value.size()));
+
+                List<StudentExam> clazzListC = value.stream()
+                        .filter(v -> BigDecimal.valueOf(v.getScoring()).compareTo(reqDTO.getLevelC()) >= 0)
+                        .filter(v -> BigDecimal.valueOf(v.getScoring()).compareTo(reqDTO.getLevelB()) < 0)
+                        .collect(Collectors.toList());
+                clazzLevelC.setNum(clazzListC.size() + clazzListB.size() + clazzListA.size());
+                clazzLevelC.setRate(getRatioPercent(clazzListC.size() + clazzListB.size() + clazzListA.size(), value.size()));
+
+                clazzInfo.setLevelA(clazzLevelA);
+                clazzInfo.setLevelB(clazzLevelB);
+                clazzInfo.setLevelC(clazzLevelC);
+                resDTOList.add(clazzInfo);
+            });
+
+        }
+
+        //查询方式二:按照人数分档
+        if (reqDTO.getType() == ZSYLevelCountType.NUM_COUNT.getValue()) {
+
+            if (reqDTO.getNumA()+reqDTO.getNumB()+reqDTO.getNumC() > examList.size()) {
+                throw new ZSYServiceException("人数填写错误,本次考试一共"+examList.size()+"人");
+            }
+
+            SchoolLevelCountNewResDTO schoolLevelCountNewResDTO = new SchoolLevelCountNewResDTO();
+            SchoolLevelCountNewResDTO.LevelStudentAndScore levelA = new SchoolLevelCountNewResDTO.LevelStudentAndScore();
+            SchoolLevelCountNewResDTO.LevelStudentAndScore levelB = new SchoolLevelCountNewResDTO.LevelStudentAndScore();
+            SchoolLevelCountNewResDTO.LevelStudentAndScore levelC = new SchoolLevelCountNewResDTO.LevelStudentAndScore();
+            schoolLevelCountNewResDTO.setClazzName("全年级");
+            schoolLevelCountNewResDTO.setStudentNum(examList.size());
+            List<StudentExam> sortList = examList.stream().sorted(Comparator.comparing(StudentExam::getScoring).reversed()).collect(Collectors.toList());
+            //累计达线
+            List<StudentExam> countListABC = Lists.newArrayList();
+            List<StudentExam> countListAB = Lists.newArrayList();
+            //A档累计达线
+            List<StudentExam> listA = sortList.stream().skip(0).limit(reqDTO.getNumA()).collect(Collectors.toList());
+            countListABC.addAll(listA);
+            countListAB.addAll(listA);
+            levelA.setNum(listA.size());
+            levelA.setRate(getRatioPercent(listA.size(), sortList.size()));//达线率=达线人数/考试总人数
+            //levelA.setScore(BigDecimal.valueOf(listA.get(listA.size() - 1).getScoring()));
+            schoolLevelCountNewResDTO.setLevelA(levelA);
+
+            //B档累计达线
+            List<StudentExam> listB = sortList.stream().skip(reqDTO.getNumA()).limit(reqDTO.getNumB()).collect(Collectors.toList());
+            countListABC.addAll(listB);
+            countListAB.addAll(listB);
+            levelB.setNum(listA.size()+listB.size());
+            levelB.setRate(getRatioPercent(listA.size()+listB.size(), sortList.size()));//达线率=达线人数/考试总人数
+            schoolLevelCountNewResDTO.setLevelB(levelB);
+
+            //C档累计达线
+            List<StudentExam> listC = sortList.stream().skip(reqDTO.getNumA()+reqDTO.getNumB()).limit(reqDTO.getNumC()).collect(Collectors.toList());
+            countListABC.addAll(listC);
+            levelC.setNum(listA.size()+listB.size()+listC.size());
+            levelC.setRate(getRatioPercent(listA.size()+listB.size()+listC.size(), sortList.size()));//达线率=达线人数/考试总人数
+            schoolLevelCountNewResDTO.setLevelB(levelC);
+
+            //添加列表第一行数据
+            resDTOList.add(schoolLevelCountNewResDTO);
+
+            //按班级统计
+            //达到分档线的学生
+            Map<String, List<StudentExam>> map = countListABC.stream().collect(Collectors.groupingBy(StudentExam::getClassId, LinkedHashMap::new, Collectors.toList()));
+            //所有学生
+            Map<String, List<StudentExam>> mapAll = examList.stream().collect(Collectors.groupingBy(StudentExam::getClassId, LinkedHashMap::new, Collectors.toList()));
+
+            map.forEach((key, value) -> {
+                SchoolLevelCountNewResDTO clazzInfo = new SchoolLevelCountNewResDTO();
+                clazzInfo.setClazzName(value.get(0).getClazzName());
+                clazzInfo.setStudentNum(mapAll.get(key).size());
+
+                SchoolLevelCountNewResDTO.LevelStudentAndScore clazzLevelA = new SchoolLevelCountNewResDTO.LevelStudentAndScore();
+                SchoolLevelCountNewResDTO.LevelStudentAndScore clazzLevelB = new SchoolLevelCountNewResDTO.LevelStudentAndScore();
+                SchoolLevelCountNewResDTO.LevelStudentAndScore clazzLevelC = new SchoolLevelCountNewResDTO.LevelStudentAndScore();
+
+                clazzLevelA.setNum(listA.stream().filter(c -> c.getClassId().equals(key)).collect(Collectors.toList()).size());
+                clazzLevelA.setRate(getRatioPercent(clazzLevelA.getNum(), clazzInfo.getStudentNum()));
+                clazzLevelB.setNum(countListAB.stream().filter(c -> c.getClassId().equals(key)).collect(Collectors.toList()).size());
+                clazzLevelB.setRate(getRatioPercent(clazzLevelB.getNum(), clazzInfo.getStudentNum()));
+                clazzLevelC.setNum(countListABC.stream().filter(c -> c.getClassId().equals(key)).collect(Collectors.toList()).size());
+                clazzLevelC.setRate(getRatioPercent(clazzLevelC.getNum(), clazzInfo.getStudentNum()));
+                clazzInfo.setLevelA(clazzLevelA);
+                clazzInfo.setLevelB(clazzLevelB);
+                clazzInfo.setLevelC(clazzLevelC);
+                resDTOList.add(clazzInfo);
+                mapAll.remove(key);
+            });
+
+            mapAll.forEach((k, v) -> {
+                SchoolLevelCountNewResDTO clazzInfo = new SchoolLevelCountNewResDTO();
+                clazzInfo.setClazzName(v.get(0).getClazzName());
+                clazzInfo.setStudentNum(v.size());
+                SchoolLevelCountNewResDTO.LevelStudentAndScore clazzLevelA = new SchoolLevelCountNewResDTO.LevelStudentAndScore();
+                SchoolLevelCountNewResDTO.LevelStudentAndScore clazzLevelB = new SchoolLevelCountNewResDTO.LevelStudentAndScore();
+                SchoolLevelCountNewResDTO.LevelStudentAndScore clazzLevelC = new SchoolLevelCountNewResDTO.LevelStudentAndScore();
+                clazzLevelA.setNum(0);
+                clazzLevelA.setRate(new BigDecimal(0));
+                clazzLevelB.setNum(0);
+                clazzLevelB.setRate(new BigDecimal(0));
+                clazzLevelC.setNum(0);
+                clazzLevelC.setRate(new BigDecimal(0));
+                clazzInfo.setLevelA(clazzLevelA);
+                clazzInfo.setLevelB(clazzLevelB);
+                clazzInfo.setLevelC(clazzLevelC);
+                resDTOList.add(clazzInfo);
+            });
+        }
+
+        //默认分档 达线统计列表
+        if (reqDTO.getType() == ZSYLevelCountType.DEFAYLT_COUNT.getValue()) {
+            return defaultLevelList(examList);
+        }
+
+        return resDTOList;
+    }
+
+    /**
+     * 分档统计默认设置
+     * @param examList
+     * @return
+     */
+    private SchoolLevelCountNewResDTO defaultCount(List<StudentExam> examList) {
+        SchoolLevelCountNewResDTO resDTO = new SchoolLevelCountNewResDTO();
+        SchoolLevelCountNewResDTO.LevelStudentAndScore levelA = new SchoolLevelCountNewResDTO.LevelStudentAndScore();
+        SchoolLevelCountNewResDTO.LevelStudentAndScore levelB = new SchoolLevelCountNewResDTO.LevelStudentAndScore();
+        SchoolLevelCountNewResDTO.LevelStudentAndScore levelC = new SchoolLevelCountNewResDTO.LevelStudentAndScore();
+
+        //全年级 成绩 倒序
+        List<StudentExam> sortList = examList.stream().sorted(Comparator.comparing(StudentExam::getScoring).reversed()).collect(Collectors.toList());
+        //全年级  实际考试人数
+        long studentNum = examList.size();
+        if (studentNum < 10) {
+            throw new ZSYServiceException("人数少于10,无法统计");
+        }
+        Double num = studentNum * 0.1;
+        //3个维度 10% 20% 50%
+        //计算公式 总人数的10%,看这10%里最后一名的得分,在查询分数 >= 这个得分的人数
+        StudentExam studentAndScoreBO = sortList.get(num.intValue() - 1 < 0 ? 0 : num.intValue() - 1);
+        List<StudentExam> collect = sortList.stream().filter(list -> list.getScoring().compareTo(studentAndScoreBO.getScoring()) >= 0).collect(Collectors.toList());
+        levelA.setScore(BigDecimal.valueOf(studentAndScoreBO.getScoring()));//A档最后一名的成绩
+        levelA.setNum(collect.size());
+        BigDecimal avgA = BigDecimal.valueOf(collect.stream().mapToDouble(StudentExam::getScoring).average().orElse(0D)).setScale(2, BigDecimal.ROUND_DOWN);
+        levelA.setAvgScoring(avgA);
+        levelA.setRate(new BigDecimal(10));
+        resDTO.setLevelA(levelA);
+
+        //20%
+        Double numB = studentNum * 0.2;
+        StudentExam studentAndScoreBOB = sortList.get(numB.intValue() - 1 < 0 ? 0 : numB.intValue() - 1);
+        List<StudentExam> listB = examList.stream()
+                .filter(exam -> BigDecimal.valueOf(exam.getScoring()).compareTo(BigDecimal.valueOf(studentAndScoreBOB.getScoring())) >= 0)
+                .filter(exam -> BigDecimal.valueOf(exam.getScoring()).compareTo(BigDecimal.valueOf(studentAndScoreBO.getScoring())) < 0)
+                .collect(Collectors.toList());
+
+        List<StudentExam> listAB = sortList.stream().filter(list -> list.getScoring().compareTo(studentAndScoreBOB.getScoring()) >= 0).collect(Collectors.toList());
+        BigDecimal avgB = BigDecimal.valueOf(listB.stream().mapToDouble(StudentExam::getScoring).average().orElse(0D)).setScale(2, BigDecimal.ROUND_DOWN);
+
+        levelB.setAvgScoring(avgB);
+        levelB.setRate(new BigDecimal(20));
+        levelB.setNum(listB.size());
+        levelB.setCountNum(listAB.size());//20%的人数
+        levelB.setScore(BigDecimal.valueOf(studentAndScoreBOB.getScoring()));
+
+        //50%
+        Double numC = studentNum * 0.5;
+        StudentExam studentAndScoreBOC = sortList.get(numC.intValue() - 1);
+        List<StudentExam> lisABC = sortList.stream().filter(list -> list.getScoring().compareTo(studentAndScoreBOC.getScoring()) >= 0).collect(Collectors.toList());
+        List<StudentExam> listC = examList.stream()
+                .filter(exam -> BigDecimal.valueOf(exam.getScoring()).compareTo(BigDecimal.valueOf(studentAndScoreBOC.getScoring())) >= 0)
+                .filter(exam -> BigDecimal.valueOf(exam.getScoring()).compareTo(BigDecimal.valueOf(studentAndScoreBOB.getScoring())) < 0)
+                .collect(Collectors.toList());
+        BigDecimal avgC = BigDecimal.valueOf(listC.stream().mapToDouble(StudentExam::getScoring).average().orElse(0D)).setScale(2, BigDecimal.ROUND_DOWN);
+
+        levelC.setAvgScoring(avgC);
+        levelC.setRate(new BigDecimal(50));
+        levelC.setNum(listC.size());
+        levelC.setCountNum(lisABC.size());//50%的人数
+        levelC.setScore(BigDecimal.valueOf(studentAndScoreBOC.getScoring()));
+
+        resDTO.setLevelA(levelA);
+        resDTO.setLevelB(levelB);
+        resDTO.setLevelC(levelC);
+
+        return resDTO;
+    }
+
+    /**
+     *  同一考生各个学科考试成绩累加,所有学科缺考为缺考,
+     *  对多门学科统计,只要有一门学科有考试,则算不缺考
+     * @param list
+     * @return
+     */
+    private List<StudentExam> separete(List<StudentExam> list){
+
+        Map<String,StudentExam> map = new HashMap<>();
+        for(StudentExam vo:list){
+            String studentId = vo.getStudentId();
+            if(map.containsKey(studentId)){
+                StudentExam studentExam = map.get(studentId);
+                //合并得分
+                studentExam.setScoring(studentExam.getScoring()+vo.getScoring());
+                //缺考,所有考试缺考为缺考
+                if(studentExam.getMissExam()==0 || vo.getMissExam() == 0){
+                    studentExam.setMissExam(0);
+                }else {
+                    studentExam.setMissExam(1);
+                }
+                map.put(studentId,studentExam);
+            }else {
+                map.put(studentId,vo);
+            }
+        }
+
+        List<StudentExam> listNew = new ArrayList<>(map.values());
+        return listNew;
+    }
+
+    /**
+     * check args
+     * @param reqDTO
+     */
+    private void check(SchoolLevelCountReqDTO reqDTO) {
+        //学科不能为空
+        List<String> subjectIds = reqDTO.getSubjectIds();
+        if(subjectIds == null || subjectIds.isEmpty()){
+            throw new ZSYServiceException("考试学科不能为空");
+        }
+        //如果是按照分数分档
+        if (reqDTO.getType() == ZSYLevelCountType.SCORE_COUNT.getValue()) {
+            if (reqDTO.getLevelA() == null || reqDTO.getLevelB() == null || reqDTO.getLevelC() == null) {
+                throw new ZSYServiceException("分数不能为空");
+            }
+            if (reqDTO.getLevelA().compareTo(new BigDecimal(0)) <= 0
+                    || reqDTO.getLevelB().compareTo(new BigDecimal(0)) <= 0
+                    || reqDTO.getLevelC().compareTo(new BigDecimal(0)) <= 0) {
+                throw new ZSYServiceException("分数必须大于0");
+            }
+
+            if (reqDTO.getLevelA().compareTo(reqDTO.getLevelB()) <= 0 || reqDTO.getLevelB().compareTo(reqDTO.getLevelC()) <= 0) {
+                throw new ZSYServiceException("A档线必须大于B档线,B档线必须大于C档线");
+            }
+        }
+
+        //如果是按照人数分档
+        if (reqDTO.getType() == ZSYLevelCountType.NUM_COUNT.getValue()) {
+            if (reqDTO.getNumA() == null || reqDTO.getNumB() == null || reqDTO.getNumC() == null) {
+                throw new ZSYServiceException("人数不能为空");
+            }
+            if (reqDTO.getNumA() <= 0 || reqDTO.getNumB() <= 0 || reqDTO.getNumC() <= 0) {
+                throw new ZSYServiceException("人数必须大于0");
+            }
+        }
+
+
+
+    }
+
+    /**
+     * 达线率
+     *
+     * @param divisor  除数
+     * @param dividend 被除数
+     * @return
+     */
+    private BigDecimal getRatioPercent(int divisor, int dividend) {
+        if (dividend == 0) {
+            return BigDecimal.ZERO.setScale(SCALE_2, BigDecimal.ROUND_DOWN);
+        }
+        return BigDecimal.valueOf(divisor)
+                .divide(BigDecimal.valueOf(dividend), SCALE_4, BigDecimal.ROUND_DOWN)
+                .multiply(DECIMAL_TO_PERCENT).setScale(SCALE_2, BigDecimal.ROUND_DOWN);
+    }
+
+
+    /**
+     * 默认分档 达线统计列表
+     * 10% 20% 50%
+     * @param examList
+     * @return
+     */
+    private List<SchoolLevelCountNewResDTO> defaultLevelList(List<StudentExam> examList){
+
+        List<SchoolLevelCountNewResDTO> resDTOList = Lists.newArrayList();
+        SchoolLevelCountNewResDTO schoolLevelCountNewResDTO = new SchoolLevelCountNewResDTO();
+        SchoolLevelCountNewResDTO.LevelStudentAndScore levelA = new SchoolLevelCountNewResDTO.LevelStudentAndScore();
+        SchoolLevelCountNewResDTO.LevelStudentAndScore levelB = new SchoolLevelCountNewResDTO.LevelStudentAndScore();
+        SchoolLevelCountNewResDTO.LevelStudentAndScore levelC = new SchoolLevelCountNewResDTO.LevelStudentAndScore();
+
+        schoolLevelCountNewResDTO.setClazzName("全年级");
+        int studentNum = examList.size();
+        if (studentNum < 10) {
+            throw new ZSYServiceException("人数少于10,无法统计");
+        }
+        schoolLevelCountNewResDTO.setStudentNum(studentNum);
+        //全年级按照分数 倒序 排序
+        List<StudentExam> sortList = examList.stream().sorted(Comparator.comparing(StudentExam::getScoring).reversed()).collect(Collectors.toList());
+        //10%
+        Double numA = studentNum*0.1;
+        StudentExam studentExamA = sortList.get(numA.intValue() - 1 < 0 ? 0 : numA.intValue() - 1);
+        List<StudentExam> listA = sortList.stream().filter(list -> list.getScoring().compareTo(studentExamA.getScoring()) >= 0).collect(Collectors.toList());
+        levelA.setScore(BigDecimal.valueOf(studentExamA.getScoring()));//A档最后一名的成绩
+        levelA.setNum(listA.size());
+        BigDecimal avgA = BigDecimal.valueOf(listA.stream().mapToDouble(StudentExam::getScoring).average().orElse(0D)).setScale(2, BigDecimal.ROUND_DOWN);
+        levelA.setAvgScoring(avgA);
+        levelA.setRate(getRatioPercent(listA.size(), studentNum));
+        //20%
+        Double numB = studentNum * 0.2;
+        StudentExam studentExamB = sortList.get(numB.intValue() - 1 < 0 ? 0 : numB.intValue() - 1);
+        List<StudentExam> listB = sortList.stream()
+                .filter(exam -> BigDecimal.valueOf(exam.getScoring()).compareTo(BigDecimal.valueOf(studentExamB.getScoring())) >= 0)
+                .filter(exam -> BigDecimal.valueOf(exam.getScoring()).compareTo(BigDecimal.valueOf(studentExamA.getScoring())) < 0)
+                .collect(Collectors.toList());
+
+        List<StudentExam> listAB = sortList.stream().filter(list -> list.getScoring().compareTo(studentExamB.getScoring()) >= 0).collect(Collectors.toList());
+        BigDecimal avgB = BigDecimal.valueOf(listB.stream().mapToDouble(StudentExam::getScoring).average().orElse(0D)).setScale(2, BigDecimal.ROUND_DOWN);
+
+        levelB.setAvgScoring(avgB);
+        levelB.setRate(getRatioPercent(listB.size(), studentNum));
+        levelB.setNum(listB.size());// B档分数人数
+        levelB.setCountNum(listAB.size());//B档分数累计人数 20%的人数
+        levelB.setScore(BigDecimal.valueOf(studentExamB.getScoring()));
+
+        //50%
+        Double numC = studentNum * 0.5;
+        StudentExam studentExamC = sortList.get(numC.intValue() - 1 < 0 ? 0 : numC.intValue() - 1);
+        List<StudentExam> listABC = sortList.stream().filter(list -> list.getScoring().compareTo(studentExamC.getScoring()) >= 0).collect(Collectors.toList());
+        List<StudentExam> listC = sortList.stream()
+                .filter(exam -> BigDecimal.valueOf(exam.getScoring()).compareTo(BigDecimal.valueOf(studentExamC.getScoring())) >= 0)
+                .filter(exam -> BigDecimal.valueOf(exam.getScoring()).compareTo(BigDecimal.valueOf(studentExamB.getScoring())) < 0)
+                .collect(Collectors.toList());
+
+        BigDecimal avgC = BigDecimal.valueOf(listC.stream().mapToDouble(StudentExam::getScoring).average().orElse(0D)).setScale(2, BigDecimal.ROUND_DOWN);
+        levelC.setAvgScoring(avgC);
+        levelC.setRate(getRatioPercent(listABC.size(), studentNum));
+        levelC.setNum(listC.size());
+        levelC.setCountNum(listABC.size());//50%的人数
+        levelC.setScore(BigDecimal.valueOf(studentExamC.getScoring()));
+        schoolLevelCountNewResDTO.setLevelA(levelA);
+        schoolLevelCountNewResDTO.setLevelB(levelB);
+        schoolLevelCountNewResDTO.setLevelC(levelC);
+        //列表第一行数据 全年级
+        resDTOList.add(schoolLevelCountNewResDTO);
+        //按班级统计
+        Map<String, List<StudentExam>> map = examList.stream().collect(Collectors.groupingBy(StudentExam::getClassId, LinkedHashMap::new, Collectors.toList()));
+
+
+        map.forEach((key, value) -> {
+            SchoolLevelCountNewResDTO clazzInfo = new SchoolLevelCountNewResDTO();
+            SchoolLevelCountNewResDTO.LevelStudentAndScore clazzLevelA = new SchoolLevelCountNewResDTO.LevelStudentAndScore();
+            SchoolLevelCountNewResDTO.LevelStudentAndScore clazzLevelB = new SchoolLevelCountNewResDTO.LevelStudentAndScore();
+            SchoolLevelCountNewResDTO.LevelStudentAndScore clazzLevelC = new SchoolLevelCountNewResDTO.LevelStudentAndScore();
+            clazzInfo.setClazzName(value.get(0).getClazzName());
+            clazzInfo.setStudentNum(value.size());
+            List<StudentExam> clazzListA = value.stream().filter(v -> BigDecimal.valueOf(v.getScoring()).compareTo(levelA.getScore()) >= 0).collect(Collectors.toList());
+            clazzLevelA.setNum(clazzListA.size());
+            clazzLevelA.setRate(getRatioPercent(clazzListA.size(), value.size()));
+
+            List<StudentExam> clazzListB = value.stream()
+                    .filter(v -> BigDecimal.valueOf(v.getScoring()).compareTo(levelB.getScore()) >= 0)
+                    .filter(v -> BigDecimal.valueOf(v.getScoring()).compareTo(levelA.getScore()) < 0)
+                    .collect(Collectors.toList());
+            clazzLevelB.setNum(clazzListB.size() + clazzListA.size());
+            clazzLevelB.setRate(getRatioPercent(clazzListB.size() + clazzListA.size(), value.size()));
+
+            List<StudentExam> clazzListC = value.stream()
+                    .filter(v -> BigDecimal.valueOf(v.getScoring()).compareTo(levelC.getScore()) >= 0)
+                    .filter(v -> BigDecimal.valueOf(v.getScoring()).compareTo(levelB.getScore()) < 0)
+                    .collect(Collectors.toList());
+            clazzLevelC.setNum(clazzListC.size() + clazzListB.size() + clazzListA.size());
+            clazzLevelC.setRate(getRatioPercent(clazzListC.size() + clazzListB.size() + clazzListA.size(), value.size()));
+
+            clazzInfo.setLevelA(clazzLevelA);
+            clazzInfo.setLevelB(clazzLevelB);
+            clazzInfo.setLevelC(clazzLevelC);
+            resDTOList.add(clazzInfo);
+        });
+
+        return resDTOList;
+    }
+
+
+}

+ 27 - 0
src/main/java/com/zsy/sass/report/service/impl/ExamServiceImpl.java

@@ -0,0 +1,27 @@
+package com.zsy.sass.report.service.impl;
+
+import com.zsy.sass.model.pojo.Exam;
+import com.zsy.sass.report.dao.ExamDao;
+import com.zsy.sass.report.service.ExamService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import java.util.List;
+
+/**
+ * Created by yqq on 2019/6/27.
+ */
+@Service
+public class ExamServiceImpl implements ExamService {
+
+    @Autowired
+    private ExamDao examDao;
+
+    @Override
+    public List<Exam> findAll() {
+
+        String name = null;
+
+        List<Exam> examList = examDao.findAll();
+        return examList;
+    }
+}

+ 29 - 0
src/main/java/com/zsy/sass/report/service/impl/RedisServiceImpl.java

@@ -0,0 +1,29 @@
+package com.zsy.sass.report.service.impl;
+
+import com.zsy.sass.common.tools.RedisUtil;
+import com.zsy.sass.report.dao.RedisDao;
+import com.zsy.sass.report.service.RedisService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import javax.annotation.Resource;
+import java.util.Map;
+
+@Service
+public class RedisServiceImpl implements RedisService {
+
+    @Autowired
+    private RedisDao redisDaoImpl;
+
+    @Resource
+    private RedisUtil redisUtil;
+
+    @Override
+    public String findExamInfo(String key) {
+
+        Object sm1 = redisUtil.hget(key, "599:6582234412584330221");
+
+        System.out.println("sm---->"+sm1);
+
+        return sm1.toString();
+    }
+}

+ 38 - 0
src/main/resources/application.properties

@@ -0,0 +1,38 @@
+server.port=8081
+server.servlet.context-path=/sass
+# mysql相关配置
+spring.datasource.url=jdbc:mysql://192.168.1.210:3307/data_mining?useUnicode=true&characterEncoding=utf-8&useSSL=false
+spring.datasource.username=zsy
+spring.datasource.password=lc12345
+spring.datasource.driver-class-name=com.mysql.jdbc.Driver
+
+# prometheus
+#management.endpoint.metrics.enabled=true
+#management.endpoints.web.exposure.include=*
+#management.endpoint.prometheus.enabled=true
+#management.metrics.export.prometheus.enabled=true
+
+
+# redis
+# Redis数据库索引
+spring.redis.database=10
+# Redis服务器地址
+spring.redis.host=192.168.1.240
+# Redis服务器连接端口
+spring.redis.port=6379
+# Redis服务器连接密码(默认为空)
+spring.redis.password=
+# 连接池最大连接数(使用负值表示没有限制)
+spring.redis.pool.max-active=200
+# 连接池最大阻塞等待时间(使用负值表示没有限制)
+spring.redis.pool.max-wait=-1
+# 连接池中的最大空闲连接
+spring.redis.pool.max-idle=10
+# 连接池中的最小空闲连接
+spring.redis.pool.min-idle=0
+# 连接超时时间(毫秒)
+# spring.redis.timeout=1000
+
+
+
+