package org.dromara.system.service.impl.score;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.api.client.util.SecurityUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.dromara.common.core.constant.CacheConstants;
import org.dromara.common.core.domain.model.LoginUser;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import org.dromara.common.redis.utils.RedisUtils;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.system.controller.system.SysDictTypeController;
import org.dromara.system.domain.FormalParentsStudent;
import org.dromara.system.domain.FormalTeacherClass;
import org.dromara.system.domain.SysUser;
import org.dromara.system.domain.score.ScoreData;
import org.dromara.system.domain.score.ScoreDataDetail;
import org.dromara.system.domain.score.ScoreDataMf;
import org.dromara.system.domain.score.ScoreDataStudent;
import org.dromara.system.domain.score.bo.ScoreDataBo;
import org.dromara.system.domain.score.bo.ScoreDataDetailBo;
import org.dromara.system.domain.score.bo.ScoreDataMfBo;
import org.dromara.system.domain.score.bo.ScoreDataStudentBo;
import org.dromara.system.domain.score.vo.ScoreDataDetailVo;
import org.dromara.system.domain.score.vo.ScoreDataMfVo;
import org.dromara.system.domain.score.vo.ScoreDataStudentVo;
import org.dromara.system.domain.score.vo.ScoreDataVo;
import org.dromara.system.domain.vo.FormalTeacherClassVo;
import org.dromara.system.domain.vo.SysDictDataVo;
import org.dromara.system.mapper.FormalParentsStudentMapper;
import org.dromara.system.mapper.FormalTeacherClassMapper;
import org.dromara.system.mapper.SysDictTypeMapper;
import org.dromara.system.mapper.score.ScoreDataDetailMapper;
import org.dromara.system.mapper.score.ScoreDataMapper;
import org.dromara.system.mapper.score.ScoreDataMfMapper;
import org.dromara.system.mapper.score.ScoreDataStudentMapper;
import org.dromara.system.service.impl.SysDictTypeServiceImpl;
import org.dromara.system.service.score.IScoreDataService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.*;
import java.util.stream.Collectors;

import static org.dromara.common.core.constant.CacheConstants.*;

/**
 * 成绩Service业务层处理
 *
 * @author boman
 * @date 2023-08-17
 */
@RequiredArgsConstructor
@Service
public class ScoreDataServiceImpl implements IScoreDataService {

    private final ScoreDataMapper baseMapper;
    private final SysDictTypeServiceImpl sysDictTypeService;
    private final ScoreDataStudentMapper scoreDataStudentMapper;
    private final ScoreDataDetailMapper scoreDataDetailMapper;
    private final ScoreDataMfMapper scoreDataMfMapper;
    @Autowired
    private FormalTeacherClassMapper formalTeacherClassMapper;

    @Autowired
    private FormalParentsStudentMapper formalParentsStudentMapper;


    /**
     * 查询成绩
     */
    @Override
    public ScoreDataVo queryById(Long scoreId) {
        return baseMapper.selectVoById(scoreId);
    }

    /**
     * 查询成绩列表
     */
    @Override
    public TableDataInfo<ScoreDataVo> queryPageList(ScoreDataBo bo, PageQuery pageQuery) {
        Page<ScoreDataVo> result = new Page<>();
        StringBuilder classId = new StringBuilder("0,");
        Map<String, Object> params = bo.getParams();
        String role = "admin";
        if (params != null && params.size() > 0) {
            role = (String) params.get("role");
        }
        if ("teacher".equals(role)) {
            FormalTeacherClass formalTeacherClass = new FormalTeacherClass();
            formalTeacherClass.setTeacherId(LoginHelper.getUserId());
            List<FormalTeacherClassVo> formalTeacherClasses = formalTeacherClassMapper.selectFormalTeacherClassList(formalTeacherClass);
            if (formalTeacherClasses != null && formalTeacherClasses.size() > 0) {
                for (FormalTeacherClassVo teacherClass : formalTeacherClasses) {
                    classId.append(teacherClass.getClassId()).append(",");
                }
            }
            if (StringUtils.isNotBlank(classId.toString())) {
                classId = new StringBuilder(classId.substring(0, classId.length() - 1));
            }
            bo.setScoreClassId(classId.toString());
            LambdaQueryWrapper<ScoreData> lqw = buildQueryWrapper(bo);
            result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        } else if ("parents".equals(role)) {
            FormalParentsStudent formalParentsStudent = new FormalParentsStudent();
            formalParentsStudent.setParentsId(LoginHelper.getUserId());
            List<FormalParentsStudent> formalParentsStudents = formalParentsStudentMapper.selectFormalParentsStudentList(formalParentsStudent);
            for (FormalParentsStudent parentsStudent : formalParentsStudents) {
                classId.append(parentsStudent.getClassId()).append(",");
            }
            if (StringUtils.isNotBlank(classId.toString())) {
                classId = new StringBuilder(classId.substring(0, classId.length() - 1));
            }

            bo.setScoreClassId(classId.toString());
            LambdaQueryWrapper<ScoreData> lqw = buildQueryWrapper(bo);
            result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        } else if ("admin".equals(role)) {
            LambdaQueryWrapper<ScoreData> lqw = buildQueryWrapper(bo);
            result = baseMapper.selectVoPage(pageQuery.build(), lqw);

        }
        //赋值查看率
        if (result != null && result.getSize() > 0) {
            DecimalFormat df = new DecimalFormat("##.0%");
            String percent = "0.00%";
            List<ScoreDataVo> records = result.getRecords();
            for (ScoreDataVo data : records) {
                //全部人数
                double chaKanAll = 0D;
                double chaKanCount = 0D;
                if (ObjectUtils.isNotEmpty(RedisUtils.getCacheObject(SCORE_PEOPLE_ALL + data.getScoreId()))) {
                    chaKanAll = (int) RedisUtils.getCacheObject(SCORE_PEOPLE_ALL + data.getScoreId());
                    if (ObjectUtils.isNotEmpty(RedisUtils.getCacheObject(SCORE_PEOPLE_CHAKAN_COUNT + data.getScoreId()))) {
                        //已查看
                        chaKanCount = (int) RedisUtils.getCacheObject(SCORE_PEOPLE_CHAKAN_COUNT + data.getScoreId());
                    }
                }
                double weiChaKan = chaKanAll;
                if (chaKanAll > 0 && chaKanCount >= 0) {
                    weiChaKan = chaKanAll - chaKanCount;
                    double z = chaKanCount / chaKanAll;
                    if (Math.abs(z) >= 0.1) {
                        //计算百分比
                        percent = df.format(z);
                    }
                }
                data.setChaKan(chaKanCount);
                data.setWeiChaKan(weiChaKan);
                data.setPercentage(percent);
            }
        }
        return TableDataInfo.build(result);
    }

    /**
     * 查询成绩列表
     */
    @Override
    public List<ScoreDataVo> queryList(ScoreDataBo bo) {
        LambdaQueryWrapper<ScoreData> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<ScoreData> buildQueryWrapper(ScoreDataBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<ScoreData> lqw = Wrappers.lambdaQuery();
        String scoreType = bo.getScoreType();
        if (StringUtils.isNotBlank(scoreType) && "5".equals(scoreType)) {
            //说明是统计查询成绩列表的全部 = score_type != 4
            lqw.ne(ScoreData::getScoreTitle, "4");
        }
        if (StringUtils.isNotBlank(scoreType) && !"5".equals(scoreType)) {
            //说明是统计查询成绩列表的全部 = score_type != 4
            lqw.eq(ScoreData::getScoreTitle, scoreType);
        }
        lqw.eq(StringUtils.isNotBlank(bo.getScoreTitle()), ScoreData::getScoreTitle, bo.getScoreTitle());
        lqw.eq(StringUtils.isNotBlank(bo.getScoreTime()), ScoreData::getScoreTime, bo.getScoreTime());
        lqw.like(StringUtils.isNotBlank(bo.getScoreClassName()), ScoreData::getScoreClassName, bo.getScoreClassName());
        lqw.eq(StringUtils.isNotBlank(bo.getPrivacyType()), ScoreData::getPrivacyType, bo.getPrivacyType());
        lqw.eq(StringUtils.isNotBlank(bo.getAvg()), ScoreData::getAvg, bo.getAvg());
        if (bo.getScoreClassId() != null) {
            lqw.apply("find_in_set(score_class_id,'" + bo.getScoreClassId() + "')");
        }
        return lqw;
    }

    /**
     * 新增成绩
     */
    @Override
    public Boolean insertByBo(ScoreDataBo bo) {

        DecimalFormat df = new DecimalFormat("#.00");
        ScoreData add = MapstructUtils.convert(bo, ScoreData.class);
        //validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        Long scoreId = add.getScoreId();
        if (flag) {
            bo.setScoreId(scoreId);
        }
        //班级总分
        double classZf = 0D;
        //获取各科成绩满分
        List<ScoreDataMfBo> scoreDataMfBoList = bo.getScoreDataMfBoList();
        //组装一个学科 满分的MAP
        Map<String, String> map = new HashMap<>();
        if (scoreDataMfBoList != null && scoreDataMfBoList.size() > 0) {
            for (ScoreDataMfBo scoreDataMfBo : scoreDataMfBoList) {
                scoreDataMfBo.setScoreId(scoreId);
                map.put(scoreDataMfBo.getXueke(), scoreDataMfBo.getManfen());
            }
            scoreDataMfMapper.insertBatch(MapstructUtils.convert(scoreDataMfBoList, org.dromara.system.domain.score.ScoreDataMf.class));
        }
        //从考试信息中获取所有学生信息,在获取该学生所有考试成绩
        List<ScoreDataStudentBo> scoreDataStudentBoList = bo.getScoreDataStudentBoList();
        if (scoreDataStudentBoList != null && scoreDataStudentBoList.size() > 0) {
            for (ScoreDataStudentBo scoreDataStudentBo : scoreDataStudentBoList) {
                List<ScoreDataDetailBo> scoreDataDetailBoList = scoreDataStudentBo.getScoreDataDetailBoList();
                if (scoreDataDetailBoList != null && scoreDataDetailBoList.size() > 0) {
                    double zf = 0D;
                    //计算总分
                    for (ScoreDataDetailBo scoreDataDetailBo : scoreDataDetailBoList) {
                        //总分 = 总分 + 单科成绩
                        zf = zf + scoreDataDetailBo.getScore();
                        scoreDataDetailBo.setScoreId(scoreId);
                        scoreDataDetailBo.setScoreDataName(scoreDataStudentBo.getScoreDataName());
                        scoreDataDetailBo.setStudentNumber(scoreDataStudentBo.getStudentNumber());
                        //scoreDataDetailBo.setScoreDataNameId(scoreDataStudentBo.getScoreDataNameId());
                        //插入满分
                        scoreDataDetailBo.setManfen(map.get(scoreDataDetailBo.getXueke()));
                    }
                    classZf = classZf + zf;
                    scoreDataStudentBo.setZongfen(zf);
                    //计算个人平均分 = 总分/学科数
                    scoreDataStudentBo.setAvg(String.valueOf(df.format(zf / scoreDataDetailBoList.size())));
                    scoreDataStudentBo.setScoreId(scoreId);

                    scoreDataDetailMapper.insertBatch(MapstructUtils.convert(scoreDataDetailBoList, ScoreDataDetail.class));

                }
            }
            //成绩排序
            scoreDataStudentBoList = scoreDataStudentBoList.stream().sorted(Comparator.comparingDouble(ScoreDataStudentBo::getZongfen).reversed()).collect(Collectors.toList());
            int index = 0;// 排名
            double lastScore = -1;// 最近一次的分
            for (int i = 0; i < scoreDataStudentBoList.size(); i++) {
                ScoreDataStudentBo studentBo = scoreDataStudentBoList.get(i);
                if (Double.compare(lastScore, studentBo.getZongfen()) != 0) {
                    // 如果成绩和上一名的成绩不相同,那么排名+1
                    lastScore = studentBo.getZongfen();
                    index++;
                }
                studentBo.setScoreSort(index);
            }
            scoreDataStudentMapper.insertBatch(MapstructUtils.convert(scoreDataStudentBoList, ScoreDataStudent.class));

            //计算班级总分平均分=各学生总分/学生人数
            String classAvg = df.format(classZf / scoreDataStudentBoList.size());
            add.setAvg(Double.parseDouble(classAvg));
            baseMapper.updateById(add);
            RedisUtils.setCacheObject(SCORE_PEOPLE_ALL + scoreId, scoreDataStudentBoList.size());
            RedisUtils.setCacheObject(SCORE_PEOPLE_CHAKAN_COUNT + scoreId, 0);
        }
        return flag;
    }

    /**
     * 修改成绩
     */
    @Override
    public Boolean updateByBo(ScoreDataBo bo) {
        ScoreData update = MapstructUtils.convert(bo, ScoreData.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(ScoreData entity) {
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 批量删除成绩
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if (isValid) {
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteBatchIds(ids) > 0;
    }

    /**
     * 后台首页成绩统计排名
     */
    @Override
    public List<ScoreDataStudentVo> indexPaiMing(ScoreData scoreData) {
        List<ScoreDataStudentVo> scoreDataStudents = scoreDataStudentMapper.selectScoreDataByScoreClassId(scoreData.getScoreClassId());
        if (scoreDataStudents != null && scoreDataStudents.size() > 0) {
            scoreDataStudents = scoreDataStudents.subList(0, Math.min(scoreDataStudents.size(), 10));
        }
        return scoreDataStudents;
    }

    /**
     * 后台首页成绩统计分段人数饼图最新一次考试
     */
    @Override
    public Map<String, Object> indexBingTu(ScoreData scoreData) {
        //获取缓存的数据
        Map<String, Object> cacheMap = RedisUtils.getCacheMap(CacheConstants.FEN_DUAN_NEW + scoreData.getScoreClassId());
        //获取班级id对应的最新考试id
        String scoreDataId = RedisUtils.getCacheObject(CacheConstants.SCORE_ID + scoreData.getScoreClassId());
        boolean flag = false;
        if (cacheMap != null) {
            //获取redis缓存的考试id
            String scoreId = String.valueOf(cacheMap.get("scoreId"));
            //判断最新一次考试id和缓存id是否匹配
            if (scoreDataId != null && scoreDataId.equals(scoreId)) {
                //说明缓存就是最新的
                return cacheMap;
            } else {
                //说明缓存数据不是最新的需要放到对比数据key中去 成为对比数据
                flag = true;
            }
        }
        Map<String, Object> map = new HashMap<>(8);
        int a = 0, b = 0, c = 0, d = 0, e = 0, f = 0, g = 0, h = 0;
        map.put("One", a);
        map.put("Tow", b);
        map.put("Thr", c);
        map.put("For", d);
        map.put("Fiv", e);
        map.put("Six", f);
        map.put("Sev", g);
        map.put("Eig", h);
        List<ScoreDataStudentVo> scoreDataStudents = scoreDataStudentMapper.selectScoreDataByScoreClassId(scoreData.getScoreClassId());

        if (scoreDataStudents != null && scoreDataStudents.size() > 0) {
            double zongfen = 0;
            //计算各个分数段有多少人
            for (ScoreDataStudentVo scoreDataStudent : scoreDataStudents) {
                zongfen = scoreDataStudent.getZongfen();
                if (zongfen >= 0 && zongfen <= 100) {
                    a++;
                } else if (zongfen > 100 && zongfen <= 200) {
                    b++;
                } else if (zongfen > 200 && zongfen <= 300) {
                    c++;
                } else if (zongfen > 300 && zongfen <= 400) {
                    d++;
                } else if (zongfen > 400 && zongfen <= 500) {
                    e++;
                } else if (zongfen > 500 && zongfen <= 600) {
                    f++;
                } else if (zongfen > 600 && zongfen <= 700) {
                    g++;
                } else if (zongfen > 700) {
                    h++;
                }
            }
            map.put("One", a);
            map.put("Tow", b);
            map.put("Thr", c);
            map.put("For", d);
            map.put("Fiv", e);
            map.put("Six", f);
            map.put("Sev", g);
            map.put("Eig", h);
            map.put("scoreId", scoreDataStudents.get(0).getScoreId());
            //把最新数据放到最新缓存key中
            RedisUtils.setCacheMap(CacheConstants.FEN_DUAN_NEW + scoreData.getScoreClassId(), map);
            RedisUtils.setCacheObject(CacheConstants.SCORE_ID + scoreData.getScoreClassId(), scoreDataStudents.get(0).getScoreId());
            if (flag) {
                //放入对比数据
                RedisUtils.setCacheMap(CacheConstants.FEN_DUAN_LAST + scoreData.getScoreClassId(), cacheMap);
            }
        }
        return map;
    }

    /**
     * 后台首页成绩统计分段人数折线图
     */
    @Override
    public Map<String, Object> indexZheXian(ScoreData scoreData) {
        Map<String, Object> map = new HashMap<>(8);
        //分段
        List<String> x = new ArrayList<>();
        x.add("One");
        x.add("Tow");
        x.add("Thr");
        x.add("For");
        x.add("Fiv");
        x.add("Six");
        x.add("Sev");
        x.add("Eig");
        //本次
        List<Object> y1 = new ArrayList<>();
        //上次
        List<Object> y2 = new ArrayList<>();
        Map<String, Object> cacheMapNew = RedisUtils.getCacheMap(CacheConstants.FEN_DUAN_NEW + scoreData.getScoreClassId());
        Map<String, Object> cacheMapLast = RedisUtils.getCacheMap(CacheConstants.FEN_DUAN_LAST + scoreData.getScoreClassId());
        if (cacheMapNew != null && cacheMapNew.size() > 0) {
            for (String key : cacheMapNew.keySet()) {
                if (!"scoreId".equals(key)) {
                    y1.add(cacheMapNew.get(key));
                    if (cacheMapLast.get(key) != null) {
                        y2.add(cacheMapLast.get(key));
                    } else {
                        y2.add(0);
                    }
                }
            }
        } else {
            for (int i = 0; i < 8; i++) {
                y1.add(0);
                y2.add(0);
            }
        }

        map.put("x", x);
        map.put("y1", y1);
        map.put("y2", y2);
        return map;
    }


    /**
     * 成绩年级统计
     */
    @Override
    public List<ScoreDataStudentVo> gradeRank(ScoreData scoreData) {
        //可以搜索学生姓名&选择班级进行年级排名
        //接收考试时间和考试类型,所有考试时间相同的
        String scoreClassName = scoreData.getScoreClassName();
        //截取两位年级
        String grade = scoreClassName.substring(0, 2);
        scoreData.setScoreClassName(grade);
        //获取年级所有学生排名
        List<ScoreDataStudentVo> scoreDataStudentVos = scoreDataStudentMapper.gradeRank(scoreData);
        Long scoreId = scoreData.getScoreId();
        if (scoreId != null) {
            scoreDataStudentVos = scoreDataStudentVos.stream().filter(scoreDataStudentVo -> scoreDataStudentVo.getScoreId().equals(scoreId)).sorted(Comparator.comparing(ScoreDataStudentVo::getZongfen)).collect(Collectors.toList());
        }
        return scoreDataStudentVos;
    }

    /**
     * 后台首页成绩统计列表
     */
    @Override
    public List<ScoreDataStudentVo> indexList(ScoreData scoreData) {
        //可以搜索学生姓名&选择班级进行年级排名
        //接收考试时间和考试类型,所有考试时间相同的
        String scoreClassName = scoreData.getScoreClassName();
        //截取两位年级
        String grade = scoreClassName.substring(0, 2);
        scoreData.setScoreClassName(grade);
        //先去获取所有的考试学生
        //获取年级所有学生排名
        List<ScoreDataStudentVo> scoreDataStudentVos = scoreDataStudentMapper.gradeRank(scoreData);
        Long scoreId = scoreData.getScoreId();
        Map<String, Double> map = new HashMap<>();
        if (scoreId != null) {
            //过滤出本班学生id
            scoreDataStudentVos = scoreDataStudentVos.stream().filter(scoreDataStudentVo -> scoreDataStudentVo.getScoreId().equals(scoreId)).sorted(Comparator.comparing(ScoreDataStudentVo::getZongfen).reversed()).collect(Collectors.toList());
            //去查询对应学生的具体学科成绩/计算学科平均分
            //获取所有学生的student_number
            List<String> studentNumberList = scoreDataStudentVos.stream().map(ScoreDataStudentVo::getStudentNumber).collect(Collectors.toList());
            List<ScoreDataDetailVo> scoreDataDetailVos = scoreDataDetailMapper.selectListByStudentNumberList(studentNumberList, scoreId);
            //根据学科进行分组
            if (scoreDataDetailVos != null && scoreDataDetailVos.size() > 0) {
                Map<String, List<ScoreDataDetailVo>> xuekeCollect = scoreDataDetailVos.parallelStream().collect(Collectors.groupingBy(ScoreDataDetailVo::getXueke));
                for (String xueke : xuekeCollect.keySet()) {
                    List<ScoreDataDetailVo> scoreDataDetailVosXueke = xuekeCollect.get(xueke);
                    //获取学科总分
                    double sum = scoreDataDetailVosXueke.stream().mapToDouble(ScoreDataDetailVo::getScore).sum();
                    //计算学科平均分 = 学科总分 /人数
                    double xueKeAvg = sum / studentNumberList.size();
                    map.put(xueke, xueKeAvg);
                }
            }
            //总成绩均分
            double sum = scoreDataStudentVos.stream().mapToDouble(ScoreDataStudentVo::getZongfen).sum();
            double zongFenAvg = sum / scoreDataStudentVos.size();

            //给学生对象插入数据
            //对学生成绩根据学生身份证进行分组
            Map<String, List<ScoreDataDetailVo>> studentNumberCollect = scoreDataDetailVos.parallelStream().collect(Collectors.groupingBy(ScoreDataDetailVo::getStudentNumber));
            for (ScoreDataStudentVo scoreDataStudentVo : scoreDataStudentVos) {
                scoreDataStudentVo.setAvg(String.valueOf(zongFenAvg));
                List<ScoreDataDetailVo> scoreDataDetailVosList = studentNumberCollect.get(scoreDataStudentVo.getStudentNumber());
                if (scoreDataDetailVosList != null && scoreDataDetailVosList.size() > 0) {
                    for (ScoreDataDetailVo scoreDataDetailVo : scoreDataDetailVosList) {
                        scoreDataDetailVo.setAvg(String.valueOf(map.get(scoreDataDetailVo.getXueke())));
                    }
                }
                scoreDataStudentVo.setScoreDataDetailVoList(scoreDataDetailVosList);
            }
        }
        return scoreDataStudentVos;
    }


    /**
     * 成绩年级统计
     *
     * @param scoreDatabo
     * @return
     */
    @Override
    public List<ScoreDataDetailVo> xuekeRank(ScoreDataBo scoreDatabo) {
        //可以搜索学生姓名&选择班级进行年级排名
        //接收考试时间和考试类型,所有考试时间相同的
        String scoreClassName = scoreDatabo.getScoreClassName();
        //截取两位年级
        String grade = scoreClassName.substring(0, 2);
        scoreDatabo.setScoreClassName(grade);
        return scoreDataStudentMapper.xuekeRank(scoreDatabo);
    }

    /**
     * 班级总分平均分排名统计
     */
    @Override
    public List<ScoreDataVo> classRank(ScoreData scoreData) {
        //可以搜索学生姓名&选择班级进行年级排名
        //接收考试时间和考试类型,所有考试时间相同的
        String scoreClassName = scoreData.getScoreClassName();
        //截取两位年级
        String grade = scoreClassName.substring(0, 2);
        scoreData.setScoreClassName(grade);
        return baseMapper.classRank(scoreData);
    }

    /**
     * 年级总分平均分排名统计折线
     *
     * @param scoreData
     * @return
     */
    @Override
    public Map<String, Object> classRankZheXian(ScoreData scoreData) {
        Map<String, Object> map = new HashMap<>(3);
        //可以搜索学生姓名&选择班级进行年级排名
        //接收考试时间和考试类型,所有考试时间相同的
        String scoreClassName = scoreData.getScoreClassName();
        //截取两位年级
        String grade = scoreClassName.substring(0, 2);
        scoreData.setScoreClassName(grade);
        //接受考试类型/考试时间/考试班级名称
        //查询出所有对应班级的考试id和平均分
        List<ScoreDataVo> scoreDataVos = baseMapper.avgRank(scoreData);
        if (scoreDataVos != null && scoreDataVos.size() > 0) {
            //年级平均分
            double avg = scoreDataVos.stream().mapToDouble(ScoreDataVo::getAvg).sum() / scoreDataVos.size();
            long[] scoreIds = scoreDataVos.stream().mapToLong(ScoreDataVo::getScoreId).toArray();
            //拿着考试id去查询对应学生
            List<ScoreDataStudentVo> scoreDataStudentVos = scoreDataStudentMapper.selectScoreByScoreIds(scoreIds);
            List<String> x = new ArrayList<>();
            List<Integer> y1 = new ArrayList<>();
            List<Integer> y2 = new ArrayList<>();
            //判断对应班级的对应学生的平均分在年级平均分的位置
            for (ScoreDataVo scoreDataVo : scoreDataVos) {
                //存放X轴数据
                x.add(scoreDataVo.getScoreClassName());
                Long scoreId = scoreDataVo.getScoreId();

                Map<Long, List<ScoreDataStudentVo>> collect = scoreDataStudentVos.stream().collect(Collectors.groupingBy(ScoreDataStudentVo::getScoreId));
                //获取对应考试的学生集合
                List<ScoreDataStudentVo> scoreDataStudentVosList = collect.get(scoreId);
                //进行平均分的判断
                if (scoreDataStudentVosList != null && scoreDataStudentVosList.size() > 0) {
                    List<ScoreDataStudentVo> scoreDataStudentVosListUp = scoreDataStudentVosList.stream().filter(scoreDataStudent -> scoreDataStudent.getZongfen() >= avg)
                        .collect(Collectors.toList());
                    List<ScoreDataStudentVo> scoreDataStudentVosListDown = scoreDataStudentVosList.stream().filter(scoreDataStudent -> scoreDataStudent.getZongfen() < avg)
                        .collect(Collectors.toList());
                    scoreDataVo.setUp(scoreDataStudentVosListUp.size());
                    scoreDataVo.setDown(scoreDataStudentVosListDown.size());
                    y1.add(scoreDataStudentVosListUp.size());
                    y2.add(scoreDataStudentVosListDown.size());
                }
            }
            map.put("x", x);
            map.put("avg", avg);
            map.put("y1", y1);
            map.put("y2", y2);
        }
        return map;
    }

    /**
     * 班级总分平均分人数统计
     */
    @Override
    public List<ScoreDataVo> avgRank(ScoreData scoreData) {
        //可以搜索学生姓名&选择班级进行年级排名
        //接收考试时间和考试类型,所有考试时间相同的
        String scoreClassName = scoreData.getScoreClassName();
        //截取两位年级
        String grade = scoreClassName.substring(0, 2);
        scoreData.setScoreClassName(grade);
        //接受考试类型/考试时间/考试班级名称
        //查询出所有对应班级的考试id和平均分
        List<ScoreDataVo> scoreDataVos = baseMapper.avgRank(scoreData);
        if (scoreDataVos != null && scoreDataVos.size() > 0) {
            //年级平均分
            double avg = scoreDataVos.stream().mapToDouble(ScoreDataVo::getAvg).sum() / scoreDataVos.size();
            long[] scoreIds = scoreDataVos.stream().mapToLong(ScoreDataVo::getScoreId).toArray();
            //拿着考试id去查询对应学生
            List<ScoreDataStudentVo> scoreDataStudentVos = scoreDataStudentMapper.selectScoreByScoreIds(scoreIds);
            //判断对应班级的对应学生的总分在班级总分平均分的位置
            for (ScoreDataVo scoreDataVo : scoreDataVos) {
                Long scoreId = scoreDataVo.getScoreId();
                Map<Long, List<ScoreDataStudentVo>> collect = scoreDataStudentVos.stream().collect(Collectors.groupingBy(ScoreDataStudentVo::getScoreId));
                //获取对应考试的学生集合
                List<ScoreDataStudentVo> scoreDataStudentVosList = collect.get(scoreId);
                //进行平均分的判断
                if (scoreDataStudentVosList != null && scoreDataStudentVosList.size() > 0) {
                    List<ScoreDataStudentVo> scoreDataStudentVosListUp = scoreDataStudentVosList.stream().filter(scoreDataStudent -> scoreDataStudent.getZongfen() >= avg)
                        .collect(Collectors.toList());
                    List<ScoreDataStudentVo> scoreDataStudentVosListDown = scoreDataStudentVosList.stream().filter(scoreDataStudent -> scoreDataStudent.getZongfen()< avg)
                        .collect(Collectors.toList());
                    scoreDataVo.setUp(scoreDataStudentVosListUp.size());
                    scoreDataVo.setDown(scoreDataStudentVosListDown.size());
                }
            }
        }
        return scoreDataVos;
    }

    /**
     * 年级分数段统计
     *
     * @param scoreData
     * @return
     */
    @Override
    public Map<String, Object> bingTuRank(ScoreData scoreData) {
        Map<String, Object> map = new HashMap<>(8);
        int a = 0, b = 0, c = 0, d = 0, e = 0, f = 0, g = 0, h = 0;
        String aZ = "0%", bZ = "0%", cZ = "0%", dZ = "0%", eZ = "0%", fZ = "0%", gZ = "0%", hZ = "0%";
        map.put("One", a);
        map.put("Tow", b);
        map.put("Thr", c);
        map.put("For", d);
        map.put("Fiv", e);
        map.put("Six", f);
        map.put("Sev", g);
        map.put("Eig", h);
        map.put("OneZ", aZ);
        map.put("TowZ", bZ);
        map.put("ThrZ", cZ);
        map.put("ForZ", dZ);
        map.put("FivZ", eZ);
        map.put("SixZ", fZ);
        map.put("SevZ", gZ);
        map.put("EigZ", hZ);
        //可以搜索学生姓名&选择班级进行年级排名
        //接收考试时间和考试类型,所有考试时间相同的
        String scoreClassName = scoreData.getScoreClassName();
        //截取两位年级
        String grade = scoreClassName.substring(0, 2);
        scoreData.setScoreClassName(grade);
        List<ScoreDataVo> scoreDataVos = baseMapper.avgRank(scoreData);
        if (scoreDataVos != null && scoreDataVos.size() > 0) {
            long[] scoreIds = scoreDataVos.stream().mapToLong(ScoreDataVo::getScoreId).toArray();
            //拿着考试id去查询对应学生
            List<ScoreDataStudentVo> scoreDataStudentVos = scoreDataStudentMapper.selectScoreByScoreIds(scoreIds);
            //判断学生的总分所在分数段
            for (ScoreDataStudentVo scoreDataStudentVo : scoreDataStudentVos) {
                Double zongfen = scoreDataStudentVo.getZongfen();
                if (zongfen >= 0 && zongfen <= 100) {
                    a++;
                } else if (zongfen > 100 && zongfen <= 200) {
                    b++;
                } else if (zongfen > 200 && zongfen <= 300) {
                    c++;
                } else if (zongfen > 300 && zongfen <= 400) {
                    d++;
                } else if (zongfen > 400 && zongfen <= 500) {
                    e++;
                } else if (zongfen > 500 && zongfen <= 600) {
                    f++;
                } else if (zongfen > 600 && zongfen <= 700) {
                    g++;
                } else if (zongfen > 700) {
                    h++;
                }
            }
            //总人数
            float  size = scoreDataStudentVos.size();

            if (size > 0) {
                NumberFormat nf = NumberFormat.getPercentInstance();
                nf.setMaximumFractionDigits(2);
                if (a > 0) {
                    map.put("OneZ", nf.format((float) a/size));

                }
                if (b > 0) {
                    map.put("TowZ", nf.format((float) b/size));

                }
                if (c > 0) {
                    map.put("ThrZ", nf.format((float) c/size));

                }
                if (d > 0) {
                    map.put("ForZ", nf.format((float) d/size));

                }
                if (e > 0) {
                    map.put("FivZ", nf.format((float) e/size));

                }
                if (f > 0) {
                    map.put("SixZ", nf.format((float) f/size));

                }
                if (g > 0) {
                    map.put("SevZ", nf.format((float) g/size));

                }
                if (h > 0) {
                    map.put("EigZ", nf.format((float) h/size));

                }
            }
            map.put("One", a);
            map.put("Tow", b);
            map.put("Thr", c);
            map.put("For", d);
            map.put("Fiv", e);
            map.put("Six", f);
            map.put("Sev", g);
            map.put("Eig", h);
        }
        return map;

    }

    /**
     * 查询成绩
     *
     * @param scoreData 成绩主键
     * @return 成绩
     */
    @Override
    public ScoreDataVo selectScoreDataByScoreId(ScoreData scoreData) {
        Long scoreId = scoreData.getScoreId();
        Map<String, Object> params = scoreData.getParams();
        String role = "admin";
        if (params != null && params.size() > 0) {
            role = (String) params.get("role");
        }
        StringBuilder stdId = new StringBuilder("0,");
        ScoreDataVo scoreDataVo = baseMapper.selectVoById(scoreData.getScoreId());
        //查询满分
        LambdaQueryWrapper<ScoreDataMf> lqw = Wrappers.lambdaQuery();
        lqw.eq(ScoreDataMf::getScoreId, scoreData.getScoreId());
        List<ScoreDataMfVo> scoreDataMfVos = scoreDataMfMapper.selectVoList(lqw);
        scoreDataVo.setScoreDataMfVoList(scoreDataMfVos);
        if ("parents".equals(role)) {
            Long userId = LoginHelper.getLoginUser().getUserId();
            //获取该家长的孩子id
            LoginUser user = LoginHelper.getLoginUser();
            FormalParentsStudent formalParentsStudent = new FormalParentsStudent();
            formalParentsStudent.setParentsId(user.getUserId());
            List<FormalParentsStudent> formalParentsStudents = formalParentsStudentMapper.selectFormalParentsStudentList(formalParentsStudent);
            for (FormalParentsStudent parentsStudent : formalParentsStudents) {
                stdId.append(parentsStudent.getId()).append(",");
            }
            if (StringUtils.isNotBlank(stdId.toString())) {
                stdId = new StringBuilder(stdId.substring(0, stdId.length() - 1));
            }

            Map<String, Object> map = new HashMap<>();
            map.put("stdId", stdId.toString());
            scoreData.setParams(map);
            //获取查看人数
            Object chaKanCount = RedisUtils.getCacheObject(SCORE_PEOPLE_CHAKAN_COUNT + scoreId);
            if (ObjectUtils.isEmpty(chaKanCount)) {
                RedisUtils.setCacheObject(SCORE_PEOPLE_CHAKAN_COUNT + scoreId, 1);
            } else {
                //判断该家长是否查看过
                Object cacheObject = RedisUtils.getCacheObject(SCORE_PEOPLE_CHAKAN + scoreId + ":" + userId);
                if (ObjectUtils.isEmpty(cacheObject)) {
                    RedisUtils.setCacheObject(SCORE_PEOPLE_CHAKAN_COUNT + scoreId, Integer.parseInt(String.valueOf(chaKanCount)) + 1);
                }
            }
            //如果是家长要记录到redis中
            RedisUtils.setCacheObject(SCORE_PEOPLE_CHAKAN + scoreId + ":" + userId, userId);
            //查询成绩家长查询自己的孩子

            //查询考试对应的学生和成绩
            List<ScoreDataStudentVo> scoreDataStudentVos = scoreDataStudentMapper.selectScoreDataForParents(scoreData);
            scoreDataVo.setScoreDataStudentVoList(scoreDataStudentVos);
            return scoreDataVo;
        }
        //查询考试对应的学生和成绩
        List<ScoreDataStudentVo> scoreDataStudentVos = scoreDataStudentMapper.selectScoreByScoreId(scoreData.getScoreId());
        scoreDataVo.setScoreDataStudentVoList(scoreDataStudentVos);
        return scoreDataVo;
    }

    /**
     * 学生成绩导入
     *
     * @param maps
     */
    @Override
    public void importData(ScoreDataBo scoreData, List<Map<String, String>> maps) {
        //去字典值中匹配学科名称 sys_subject
        List<SysDictDataVo> sysSubject = sysDictTypeService.selectDictDataByType("sys_subject");
        List<String> xueKeList = sysSubject.stream().map(SysDictDataVo::getDictLabel).collect(Collectors.toList());
        List<ScoreDataStudentBo> scoreDataStudentBoList = new ArrayList<>();
        //获取满分设置
        Map<String, String> manFenMap = maps.get(0);
        if (manFenMap != null) {
            List<ScoreDataMfBo> scoreDataMfBoList = new ArrayList<>();
            for (String xueKe : manFenMap.keySet()) {
                ScoreDataMfBo scoreDataMfBo = new ScoreDataMfBo();
                scoreDataMfBo.setXueke(xueKe);
                scoreDataMfBo.setManfen(manFenMap.get(xueKe));
                scoreDataMfBoList.add(scoreDataMfBo);
            }
            maps.remove(0);
            scoreData.setScoreDataMfBoList(scoreDataMfBoList);
        }
        //处理数据成对象
        for (Map<String, String> map : maps) {
            //每一个Map里面有学生姓名和各科成绩
            //组装成一个ScoreDataBo对象中的
            ScoreDataStudentBo studentBo = new ScoreDataStudentBo();
            studentBo.setScoreDataName(map.get("姓名"));
            studentBo.setStudentNumber(map.get("学号"));
            List<ScoreDataDetailBo> scoreDataDetailBoList = new ArrayList<>();
            for (String key : map.keySet()) {
                if (xueKeList.contains(key)) {
                    ScoreDataDetailBo scoreDataDetailBo = new ScoreDataDetailBo();
                    scoreDataDetailBo.setXueke(key);
                    scoreDataDetailBo.setScore(Double.valueOf(map.get(key)));
                    scoreDataDetailBoList.add(scoreDataDetailBo);
                }
            }
            studentBo.setScoreDataDetailBoList(scoreDataDetailBoList);
            scoreDataStudentBoList.add(studentBo);
        }
        scoreData.setScoreDataStudentBoList(scoreDataStudentBoList);
        this.insertByBo(scoreData);
    }
}
