package com.xhkjedu.smarking.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.xhkjedu.smarking.config.ConfigKey;
import com.xhkjedu.smarking.mapper.report.reportother.MsrReportparamMapper;
import com.xhkjedu.smarking.model.report.reportother.MsrReportparam;
import com.xhkjedu.smarking.model.report.reportstu.MsrStudent;
import com.xhkjedu.smarking.vo.paper.PaperFileVo;
import com.xhkjedu.smarking.vo.report.reportother.*;
import com.xhkjedu.smarking.vo.report.reportsubject.SectionScoreVo;
import com.xhkjedu.utils.N_Utils;
import com.xhkjedu.vo.PageResult;
import com.xhkjedu.vo.ResultVo;
import lombok.extern.slf4j.Slf4j;

import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * @author ywx
 * @className ClassUtil
 * @description
 * @date 2022/2/21 17:20
 **/
@Slf4j
public class MarkingUtil {
    public static Map<String, String> uriMap = new ConcurrentHashMap<>();

    /**
     * 删除Html标签
     */
    public static String htmlRemoveTag(String inputString) {
        if (inputString == null)
            return null;
        String htmlStr = inputString; // 含html标签的字符串
        String textStr = "";
        java.util.regex.Pattern p_script;
        java.util.regex.Matcher m_script;
        java.util.regex.Pattern p_style;
        java.util.regex.Matcher m_style;
        java.util.regex.Pattern p_html;
        java.util.regex.Matcher m_html;
        try {
            // 定义script的正则表达式{或<script[^>]*?>[\\s\\S]*?<\\/script>
            String regEx_script = "<[\\s]*?script[^>]*?>[\\s\\S]*?<[\\s]*?\\/[\\s]*?script[\\s]*?>";
            // 定义style的正则表达式{或<style[^>]*?>[\\s\\S]*?<\\/style>
            String regEx_style = "<[\\s]*?style[^>]*?>[\\s\\S]*?<[\\s]*?\\/[\\s]*?style[\\s]*?>";
            String regEx_html = "<[^>]+>"; // 定义HTML标签的正则表达式
            p_script = Pattern.compile(regEx_script, Pattern.CASE_INSENSITIVE);
            m_script = p_script.matcher(htmlStr);
            htmlStr = m_script.replaceAll(""); // 过滤script标签
            p_style = Pattern.compile(regEx_style, Pattern.CASE_INSENSITIVE);
            m_style = p_style.matcher(htmlStr);
            htmlStr = m_style.replaceAll(""); // 过滤style标签
            p_html = Pattern.compile(regEx_html, Pattern.CASE_INSENSITIVE);
            m_html = p_html.matcher(htmlStr);
            htmlStr = m_html.replaceAll(""); // 过滤html标签
            textStr = htmlStr;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return textStr;// 返回文本字符串
    }

    /*
     * @Description 判断两个字符串的关系
     * @Date 2024/10/29 10:23:58
     * @Author WN
     * @Param [str1, str2]
     * @Return int
     **/
    public static int isEqualStringCheck(String str1, String str2) {
        char[] charArray1 = str1.toCharArray();
        char[] charArray2 = str2.toCharArray();
        Arrays.sort(charArray1);
        Arrays.sort(charArray2);
        int eqResult = 0;// 0代表不相等 1表示两个字符串相等 2代表字符串1包含字符串2
        if (Arrays.equals(charArray1, charArray2)) {
            eqResult = 1;
        }

        if (Collections.singletonList(charArray1).contains(charArray2)) {
            eqResult = 2;
        }

        return eqResult;
    }

    /*
     * @Description 客观题自动批阅
     * @Date 2024/11/5 11:18:30
     * @Author WN
     * @Param [stuanswer, q]
     * @Return java.lang.Double
     **/
    public static Double checkObjectiveStuAnswer(String stuanswer, int ctype, String qanswer, Double loseoption, Double qscore) {
        String qanswerCort = JSON.parseArray(qanswer, String.class).get(0);// 试题正确答案
        Double stuscore = 0D;
        if (N_Utils.isNotEmpty(stuanswer)) {
            if (ctype == 1 || ctype == 4 || ctype == 5 || ctype == 6) {
                if (qanswerCort.equalsIgnoreCase(stuanswer)) {
                    stuscore = qscore;
                }
            } else if (ctype == 2) {
                // 多选题进行判断，
                int isEqualStr = isEqualStringCheck(qanswerCort, stuanswer);
                if (isEqualStr == 1) {
                    stuscore = qscore;
                } else if (isEqualStr == 2) {
                    stuscore = loseoption;// 少选得分
                }
            }
        }
        return stuscore;
    }


    /**
     * 提供精确的加法运算。
     *
     * @param v1 被加数
     * @param v2 加数
     * @return 两个参数的和
     */
    public static double add(Object v1, Object v2) {
        if (v1 == null) v1 = 0;
        if (v2 == null) v2 = 0;
        BigDecimal b1 = new BigDecimal(v1.toString());
        BigDecimal b2 = new BigDecimal(v2.toString());
        return b1.add(b2).doubleValue();
    }

    // 两数相减
    public static long subtract(long a, long b) {
        BigInteger biginta = new BigInteger(a + "");
        BigInteger bigintb = new BigInteger(b + "");
        return biginta.subtract(bigintb).longValue();

    }

    // 两数相减
    public static Integer subtractInt(Integer a, Integer b) {
        BigInteger biginta = new BigInteger(a + "");
        BigInteger bigintb = new BigInteger(b + "");
        return biginta.subtract(bigintb).intValue();

    }

    /**
     * 提供精确的乘法运算。
     *
     * @param v1 被乘数
     * @param v2 乘数
     * @return 两个参数的积
     */
    public static double mul(double v1, double v2) {
        BigDecimal b1 = new BigDecimal(Double.toString(v1));
        BigDecimal b2 = new BigDecimal(Double.toString(v2));
        return b1.multiply(b2).doubleValue();
    }

    /**
     * 提供（相对）精确的除法运算，当发生除不尽的情况时，精确到 小数点以后2位，以后的数字舍弃。
     *
     * @param v1 被除数
     * @param v2 除数
     * @return 两个参数的商
     */
    public static double div(Object v1, Object v2) {
        BigDecimal b1 = new BigDecimal(v1.toString());
        BigDecimal b2 = new BigDecimal(v2.toString());
        return b1.divide(b2, 2, BigDecimal.ROUND_DOWN).doubleValue();
    }

    /**
     * @Description 计算平均分
     * @Date 2024/11/19 11:30
     * @Author YWX
     * @Param [v1, v2]
     * @Return double
     **/
    public static double avg(Object v1, Object v2) {
        return div(add(v1, v2), 2);
    }

    /**
     * 向上取值
     *
     * @param score    原始得分
     * @param interval 取值间隔
     * @return 向上取值后的结果
     */
    public static double roundUp(double score, double interval) {
        return Math.ceil(score / interval) * interval;
    }

    /**
     * 向下取值
     *
     * @param score    原始得分
     * @param interval 取值间隔
     * @return 向下取值后的结果
     */
    public static double roundDown(double score, double interval) {
        return Math.floor(score / interval) * interval;
    }

    /**
     * 计算总分并处理超过满分的情况
     *
     * @param scores   得分数组
     * @param interval 取值间隔
     * @param maxScore 满分
     * @return 最终总分
     */
    public static double calculateTotalScore(double[] scores, double interval, double maxScore) {
        double totalScore = 0.0;

        for (double score : scores) {
            totalScore += roundUp(score, interval);
        }

        return Math.min(totalScore, maxScore);
    }

    /**
     * 计算两个分数之间的分差
     *
     * @param score1 第一个分数
     * @param score2 第二个分数
     * @return 分差
     */
    public static double scoreDiff(Object score1, Object score2) {
        return Math.abs(sub(score1, score2));
    }


    /**
     * 提供精确的减法运算。
     *
     * @param v1 被减数
     * @param v2 减数
     * @return 两个参数的差
     */
    public static double sub(Object v1, Object v2) {
        BigDecimal b1 = new BigDecimal(v1.toString());
        BigDecimal b2 = new BigDecimal(v2.toString());
        return b1.subtract(b2).doubleValue();
    }

    // 字符串转为时间戳(秒)
    public static long strToTimestamp(String str) {
        if (str == null || str.isEmpty()) return 0;
        DateTimeFormatter ftf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        LocalDateTime parse = LocalDateTime.parse(str, ftf);
        return LocalDateTime.from(parse).atZone(ZoneId.systemDefault()).toEpochSecond();
    }

    /**
     * @Description 字符串转时间戳
     * @Param [time]
     * @Return int
     * @Author wn
     * @Date 2022/10/27 11:36
     **/
    public static long getTimestrToTimetamp(String time) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date date = new Date();
        try {
            date = sdf.parse(time);
        } catch (Exception e) {
            log.error("字符串转时间戳出错：" + e.getMessage());
        }
        return date.getTime() / 1000;
    }

    /*
     * @Description base64图片上传
     * @Date 2024/10/30 10:57:20
     * @Author WN
     * @Param [stupic, merged, saveFloder]
     * @Return java.lang.String
     **/
    public static String uploadBase64Img(String stupic, Integer merged, String saveFloder) {
        String apiMethod;
        if (merged == 1) {
            // 说明上传的图片为单张保存
            apiMethod = "bs/base";
        } else {
            // 上传的多张图片需要合并为一张
            apiMethod = "bs/mbase_merge";
        }
        String stubase64;// 防止内容被更改
        try {
            stubase64 = URLEncoder.encode(stupic, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            log.error("base64格式化内容出错" + e.getMessage());
            throw new RuntimeException(e);
        }
        // 处理字段那种图片路径,base64转图片
        String params = "base64path=" + stubase64 + "&savefolder=" + saveFloder;
        String fileInfoStr = N_Utils.sendPost(ConfigKey.fileapi + apiMethod, params);
        if (N_Utils.isEmpty(fileInfoStr)) {
            return "";
        }
        ResultVo fileResult = JSON.parseObject(fileInfoStr, ResultVo.class);
        if (fileResult.getCode() == 0 && N_Utils.isNotEmpty(fileResult.getObj())) {
            return fileResult.getObj().toString();
        } else {
            return "";
        }
    }

    /*
     * @Description 批量上传base64图片，返回图片地址及合并后地址(用于试卷上传)
     * @Date 2024/10/30 15:09:05
     * @Author WN
     * @Param [stupic, saveFloder]
     * @Return java.util.List<java.lang.String>
     **/
    public static PaperFileVo uploadBatchBase64ImgPdf(List<String> imgList, String saveFloder) {
        // 处理字段那种图片路径,base64转图片
        String base64path = JSON.toJSONString(imgList);
        try {
            base64path = URLEncoder.encode(base64path, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            log.error("试卷原卷base64格式化内容出错" + e.getMessage());
            throw new RuntimeException(e);
        }

        String params = "base64path=" + base64path + "&savefolder=" + saveFloder + "&column=1";
        String fileInfoStr = N_Utils.sendPost(ConfigKey.fileapi + "bs/more_pdf", params);
        ResultVo fileResult = JSON.parseObject(fileInfoStr, ResultVo.class);
        if (fileResult.getCode() == 0 && N_Utils.isNotEmpty(fileResult.getObj())) {
            return JSONArray.parseObject(fileResult.getObj().toString(), PaperFileVo.class);
        } else {
            return null;
        }
    }

    /*
     * @Description 识别客观题题块单题结果
     * @Date 2024/11/7 14:58:44
     * @Author WN
     * @Param [input]
     * @Return java.util.List<java.lang.String>
     **/
    public static List<String> extractCharacters(String input) {
        List<String> result = new ArrayList<>();
        Pattern pattern = Pattern.compile("\\((.*?)\\)|([^()]+)");
        Matcher matcher = pattern.matcher(input);

        while (matcher.find()) {
            if (matcher.group(1) != null) {
                result.add(matcher.group(1));
            } else if (matcher.group(2) != null) {
                String str = matcher.group(2);
                for (char c : str.toCharArray()) {
                    result.add(c + "");
                }
            }
        }

        return result;
    }

    public static String[] qnArr = {"一", "二", "三", "四", "五", "六", "七", "八", "九", "十", "十一", "十二", "十三", "十四", "十五", "十六", "十七", "十八", "十九", "二十",
            "二十一", "二十二", "二十三", "二十四", "二十五", "二十六", "二十七", "二十八", "二十九", "三十"};

    // 获取题号
    public static String getQnByOrder(Integer qorder) {
        String rtnStr;
        if (qorder == null || qorder == 0 || qorder > 30) {
            rtnStr = qnArr[0];
        }
        rtnStr = qnArr[qorder - 1];
        return rtnStr;
    }

    // 方差s^2=[(x1-x)^2 +...(xn-x)^2]/n 或者s^2=[(x1-x)^2 +...(xn-x)^2]/(n-1)
    public static double fc(List<Double> x) {
        if (N_Utils.isListEmpty(x)) return 0;
        int m = x.size();
        double sum = 0;
        for (Double aDouble : x) {// 求和
            sum += aDouble;
        }
        double dAve = sum / m;// 求平均值
        double dVar = 0;
        for (int i = 0; i < m; i++) {// 求方差
            dVar += (x.get(i) - dAve) * (x.get(i) - dAve);
        }
        return dVar / m;
    }

    // 标准差σ=sqrt(s^2)
    public static double bzc(List<Double> x) {
        if (N_Utils.isListEmpty(x)) return 0;
        return N_Utils.formatDouble(Math.sqrt(fc(x)), 2);
    }


    // 中位数
    public static double zws(List<Double> list) {
        if (N_Utils.isListEmpty(list)) return 0;
        // 先对列表进行排序
        List<Double> sorteList = list.stream().sorted().collect(Collectors.toList());

        int size = sorteList.size();
        if (size % 2 == 1) {
            // 数据个数为奇数，取中间位置的元素
            return sorteList.get(size / 2);
        } else {
            // 数据个数为偶数，取中间两个元素的平均值
            int midIndex1 = size / 2 - 1;
            int midIndex2 = size / 2;
            return (sorteList.get(midIndex1) + sorteList.get(midIndex2)) / 2;
        }
    }

    // 区分度=2×（高分组平均分-低分组平均分）/100
    public static double qfd(List<Double> scores) {
        if (N_Utils.isListEmpty(scores)) return 0;

        int totalCount = scores.size();
        Collections.sort(scores);//对集合排序
        int highCount = (int) Math.ceil(totalCount * 0.27); // 高分组人数
        int lowCount = (int) Math.ceil(totalCount * 0.27);  // 低分组人数

        List<Double> highGroup = new ArrayList<>(scores.subList(totalCount - highCount, totalCount)); // 高分组
        List<Double> lowGroup = new ArrayList<>(scores.subList(0, lowCount)); // 低分组
        // 计算高分组和低分组的平均分
        double highGroupAvg = calculateAverage(highGroup);
        double lowGroupAvg = calculateAverage(lowGroup);
        return div(mul(2, sub(highGroupAvg, lowGroupAvg)), 100);
    }

    // 计算平均分
    public static double calculateAverage(List<Double> scores) {
        if (N_Utils.isListEmpty(scores)) return 0;
        double sum = 0.0;
        for (double score : scores) {
            sum = add(sum, score);
        }
        return div(sum, scores.size());
    }

    //计算占比，保留4为小数，乘以100后2位小数
    public static double calculateRate(Object v1, Object v2) {
        BigDecimal b1 = new BigDecimal(v1.toString());
        BigDecimal b2 = new BigDecimal(v2.toString());

        BigDecimal b3 = b1.divide(b2, 4, BigDecimal.ROUND_DOWN);
        return b3.multiply(new BigDecimal("100")).doubleValue();
    }

    // 众数
    public static List<Double> zs(List<Double> list) {
        List<Double> modes = new ArrayList<>();
        if (N_Utils.isListEmpty(list)) return modes;

        // 使用HashMap来统计每个元素出现的次数
        Map<Double, Long> countMap = list.stream().filter(s -> s > 0).collect(Collectors.groupingBy(e -> e, Collectors.counting()));

        long maxCount = 0;
        // 找出最大的出现次数
        for (long count : countMap.values()) {
            maxCount = Math.max(maxCount, count);
        }

        // 找出所有出现次数等于最大出现次数的元素，即为众数
        for (Map.Entry<Double, Long> entry : countMap.entrySet()) {
            if (entry.getValue() == maxCount) {
                modes.add(entry.getKey());
            }
        }
        return modes;
    }

    // 超均率 =（个人单科得分-全校平均分）÷全校平均分
    public static double cjl(Object v1, Object v2) {
        if (v2 == null || "0".equals(v2)) return 0;

        BigDecimal b1 = new BigDecimal(v1.toString());
        BigDecimal b2 = new BigDecimal(v2.toString());
        return b1.subtract(b2).divide(b2, 2, BigDecimal.ROUND_DOWN).doubleValue();
    }

    // 标准分 班级标准分 =（班级得分-全校平均分）÷年级标准差
    public static double bzf(Double score, Double avgscore, Double bzc) {
        double bzscore = div(sub(score, avgscore), bzc);
        return N_Utils.formatDouble(bzscore, 2);
    }

    // 综合率 固定计算=平均得分率*50%+优秀率*25%+及格率*25%
    public static double zhl(Double v1, Double v2, Double v3) {
        double s1 = mul(v1, 0.5);
        double s2 = mul(v2, 0.25);
        double s3 = mul(v3, 0.25);
        return add(s1, add(s2, s3));
    }

    // 学科上线贡献率  班级学科上线贡献率=（班级学科上线率-班级总分上线率）-（学校学科的上线率-学校总分上线率）
    public static double sxgxl(Double v1, Double v2, Double v3, Double v4) {
        double s1 = sub(v1, v2);
        double s2 = sub(v3, v4);
        return sub(s1, s2);
    }

    // 短板学生 学科短板学生：偏科指数=（单科分值-全科平均分）÷全科标准差 ，如果偏科指数>1,标识此科为短板学科
    public static double dbxs(Double v1, Double v2, Double v3) {
        return div(sub(v1, v2), v3);
    }

    // 鉴别指数 试题鉴别指数 = 前27%的学生得分率-后27%的学生得分率
    // 将学生按总分排序（去掉缺考的学生），取前27%、后27%的学生，分别计算在该题上的得分率，两者之差即为鉴别指数
    public static double jbzs(List<Double> list, Double qscore) {
        List<Double> sortList = list.stream().sorted().collect(Collectors.toList());
        int size = sortList.size();

        if (qscore == 0) return 0.0;
        int highCount = (int) Math.ceil(size * 0.27); // 高分组人数
        int lowCount = (int) Math.ceil(size * 0.27);  // 低分组人数

        // 前27%的学生
        List<Double> topGroup = new ArrayList<>(sortList.subList(size - highCount, size));
        double topScore = topGroup.stream().mapToDouble(Double::doubleValue).sum();
        double topRate = div(topScore, mul(qscore, highCount));

        // 后27%的学生
        List<Double> bottomGroup = new ArrayList<>(sortList.subList(0, lowCount));
        double bottomScore = bottomGroup.stream().mapToDouble(Double::doubleValue).sum();
        double bottomRate = div(bottomScore, mul(qscore, lowCount));

        // 鉴别指数
        return sub(topRate, bottomRate);
    }

    //排名分组计算 参数[总名次，分组数] 如：第一组(第1-10名)
    public static List<RankGroupVo> rankGroup(Integer total, Integer groupNum) {
        List<RankGroupVo> rtnList = new ArrayList<>();
        if (groupNum > total) groupNum = total;

        int average = total / groupNum;
        int remainder = total % groupNum;

        for (int i = 0; i < groupNum; i++) {
            int min;
            int max;
            if (i < remainder) {
                min = average * i + i + 1;
                max = average * (i + 1) + i + 1;
            } else {
                min = average * i + remainder + 1;
                max = average * (i + 1) + remainder;
            }

            RankGroupVo rgvo = new RankGroupVo();
            rgvo.setGroupname("第" + N_Utils.NumberToChn(i + 1) + "组(" + min + "~" + max + ")");
            rgvo.setGroupv("第" + N_Utils.NumberToChn(i + 1) + "组");
            rgvo.setMinvalue(min);
            rgvo.setMaxvalue(max);
            rtnList.add(rgvo);
        }
        return rtnList;
    }

    //分数分组
    public static List<ScoreGroupVo> scoreGroup(Double fullScore, Integer groupNum) {
        List<ScoreGroupVo> groups = new ArrayList<>();
        double groupScore = Math.ceil(fullScore / groupNum);
        double min = 0;
        double max;
        String start = "[";
        String end = ")";
        for (int i = 1; i <= groupNum; i++) {
            ScoreGroupVo vo = new ScoreGroupVo();
            max = min + groupScore;
            if (i == groupNum) {
                if (max > fullScore) {
                    max = fullScore;
                }
                end = "]";
            }
            vo.setGroupname(start + N_Utils.formatDouble(min) + "," + N_Utils.formatDouble(max) + end);
            vo.setMinvalue(min);
            vo.setMaxvalue(max);
            groups.add(vo);
            min = max;
        }
        return groups;
    }

    //处于年级20%得分(v=0.2)
    public static Double cynjdf(List<Double> scores, double v) {
        if (N_Utils.isListEmpty(scores)) return 0.0;
        int totalCount = scores.size();
        int topCount = (int) Math.ceil(totalCount * v); // 计算
        return scores.get(totalCount - topCount);
    }

    //分数排名
    public static Map<Double, Integer> fspm(List<Double> scores) {
        //倒序排
        scores.sort(Collections.reverseOrder());
        // 创建一个地图来存储分数和出现次数
        Map<Double, Integer> scoreCountMap = new HashMap<>();

        int rank = 1;
        Map<Double, List<Double>> collect = scores.stream().collect(Collectors.groupingBy(s -> s, LinkedHashMap::new, Collectors.toList()));
        for (Map.Entry<Double, List<Double>> entry : collect.entrySet()) {
            Double key = entry.getKey();
            scoreCountMap.put(key, rank);
            rank += entry.getValue().size();
        }
        return scoreCountMap;
    }

    //人数排名
    public static Map<Integer, Integer> rspm(List<Integer> nums) {
        //倒序排
        nums.sort(Collections.reverseOrder());
        // 创建一个地图来存储分数和出现次数
        Map<Integer, Integer> scoreCountMap = new HashMap<>();

        int rank = 1;
        Map<Integer, List<Integer>> collect = nums.stream().collect(Collectors.groupingBy(s -> s, LinkedHashMap::new, Collectors.toList()));
        for (Map.Entry<Integer, List<Integer>> entry : collect.entrySet()) {
            Integer key = entry.getKey();
            scoreCountMap.put(key, rank);
            rank += entry.getValue().size();
        }
        return scoreCountMap;
    }

    // 分数段 分数分段（固定步长）
    public static List<RankGroupVo> fdScore(Integer maxScore, Integer minScore, int fdscore, Integer type) {
        List<RankGroupVo> rtnList = new ArrayList<>();
        for (int i = minScore; i < maxScore; i += fdscore) {
            int end = Math.min(i + fdscore, maxScore);

            String groupname;
            if (type.equals(1)) {

                groupname = "[" + i + "~" + end;
                if (end == maxScore) {
                    groupname += "]";
                } else {
                    groupname += ")";
                }
            } else {
                groupname = ">=" + end;
            }

            RankGroupVo rgvo = new RankGroupVo();
            rgvo.setGroupname(groupname);
            rgvo.setMinvalue(i);
            rgvo.setMaxvalue(end);
            rtnList.add(rgvo);
        }
        return rtnList;
    }

    // 分数段 分数分段（不定步长）
    public static List<RankGroupVo> fdScore(List<SzJsonVo> vos, Integer type) {
        List<RankGroupVo> rtnList = new ArrayList<>();
        for (int i = 0; i < vos.size(); i++) {
            SzJsonVo vo = vos.get(i);
            Integer minvalue = N_Utils.obj2Int(vo.getMinvalue());
            Integer maxvalue = N_Utils.obj2Int(vo.getMaxvalue());
            String groupname;
            if (type.equals(1)) {
                groupname = "[" + minvalue + "~" + maxvalue;
                if (i == 0) {
                    groupname += "]";
                } else {
                    groupname += ")";
                }
            } else {
                groupname = ">=" + maxvalue;
            }

            RankGroupVo rgvo = new RankGroupVo();
            rgvo.setGroupname(groupname);
            rgvo.setMinvalue(minvalue);
            rgvo.setMaxvalue(maxvalue);
            rtnList.add(rgvo);
        }
        return rtnList;
    }

    // 分数段 分数分段
    public static List<RankGroupVo> fdScore(Double totalScore, int fdscore) {
        List<RankGroupVo> rtnList = new ArrayList<>();
        for (int i = 0; i < totalScore; i += fdscore) {
            int end = (int) Math.min(i + fdscore, totalScore);

            String groupname = "[" + i + "~" + end;
            if (end == totalScore) {
                groupname += "]";
            } else {
                groupname += ")";
            }

            RankGroupVo rgvo = new RankGroupVo();
            rgvo.setGroupname(groupname);
            rgvo.setMinvalue(i);
            rgvo.setMaxvalue(end);
            rtnList.add(rgvo);
        }
        return rtnList;
    }

    //分数分段 试题1分1段
    public static List<SectionScoreVo> fdScoreForOne(Double totalScore) {
        List<SectionScoreVo> rtnList = new ArrayList<>();
        for (int i = 0; i < totalScore; i++) {
            double end = Math.min(i + 1, totalScore);
            SectionScoreVo rgvo = new SectionScoreVo();
            rgvo.setSectionname("[" + i + "~" + end + ")");
            rgvo.setMinvalue(i);
            rgvo.setMaxvalue(end);
            rtnList.add(rgvo);
        }

        //满分段单独处理
        SectionScoreVo lastvo = new SectionScoreVo();
        lastvo.setSectionname("[" + totalScore + "~" + totalScore + ")");
        lastvo.setMinvalue(totalScore);
        lastvo.setMaxvalue(totalScore);
        rtnList.add(lastvo);

        return rtnList;
    }

    //object转double
    public static double objToDouble(Object v1) {
        if (N_Utils.isEmpty(v1)) return 0.0;
        return Double.parseDouble(v1.toString());
    }

    //等级
    public static String dj(Double dfv, List<SzJsonVo> djList) {
        for (SzJsonVo vo : djList) {
            if (dfv.compareTo(objToDouble(vo.getDjvalue())) >= 0) {
                return vo.getDjkey();
            }
        }
        return "";
    }

    private static int index = 0;

    //根据表达式计算
    public static double evaluate(String expression) {
        index = 0;
        return parseExpression(expression);
    }

    private static double parseExpression(String expr) {
        try {
            double result = parseTerm(expr);
            while (index < expr.length() && (expr.charAt(index) == '+' || expr.charAt(index) == '-')) {
                char op = expr.charAt(index);
                index++;
                if (op == '+') {
                    result += parseTerm(expr);
                } else if (op == '-') {
                    result -= parseTerm(expr);
                }
            }
            return result;
        } catch (Exception e) {
            return 0.0;
        }
    }

    private static double parseTerm(String expr) {
        double result = parseFactor(expr);
        while (index < expr.length() && (expr.charAt(index) == '*' || expr.charAt(index) == '/')) {
            char op = expr.charAt(index);
            index++;
            if (op == '*') {
                result *= parseFactor(expr);
            } else if (op == '/') {
                result /= parseFactor(expr);
            }
        }
        return result;
    }

    private static double parseFactor(String expr) {
        if (expr.charAt(index) == '(') {
            index++;  // Skip '('
            double result = parseExpression(expr);
            index++;  // Skip ')'
            return result;
        } else {
            int start = index;
            while (index < expr.length() && Character.isDigit(expr.charAt(index))) {
                index++;
            }
            return Double.parseDouble(expr.substring(start, index));  // Convert substring to double
        }
    }

    //α信度系数=(k/(k-1))*(1-(∑Si²)/ST²
    public static double axdxs(int k, List<Double> a, double b) {
        if (k <= 1 || b == 0) {
            throw new ArithmeticException("Division by zero is not allowed.");
        }

        double sumA = 0;
        for (double value : a) {
            sumA = MarkingUtil.add(sumA, value);
        }

        return N_Utils.formatDouble((k / (k - 1)) * (1 - (sumA / b)), 2);
    }

    //获取科学分组学生
    public static Map<String, List<MsrStudent>> getSubjectCollect(List<MsrStudent> msrStudents) {
        Map<String, List<MsrStudent>> map = new LinkedHashMap<>();
        LinkedHashMap<String, List<MsrStudent>> collect = msrStudents.stream().collect(Collectors.groupingBy(MsrStudent::getSubjectid, LinkedHashMap::new, Collectors.toList()));
        for (Map.Entry<String, List<MsrStudent>> entry : collect.entrySet()) {
            map.put("0_" + entry.getKey(), entry.getValue());
        }
        return map;
    }

    //学生去重
    public static void studentsDistinct(Map.Entry<String, List<MsrStudent>> entry, Map<String, Integer> rsMap) {
        //list根据学生id去重
        Map<Integer, MsrStudent> map = new HashMap<>();
        for (MsrStudent student : entry.getValue()) {
            map.putIfAbsent(student.getStudentid(), student);
        }
        List<MsrStudent> list = new ArrayList<>(map.values());
        entry.setValue(list);
        if (rsMap != null) rsMap.put(list.get(0).getSubjectid(), list.size());
    }

    //获取报告参数
    public static List<MsrReportparam> getMsrReportParams(MsrReportparamMapper msrReportparamMapper
            , Integer examid, String rpbelong, String reportcode) {
        List<MsrReportparam> list = msrReportparamMapper.listReportparamByRpbelong(examid, rpbelong, reportcode);
        if (N_Utils.isListEmpty(list) && !"all".equals(reportcode)) {
            list = msrReportparamMapper.listReportparamByRpbelong(examid, rpbelong, "all");
        }
        return list;
    }

    // 获取指定字段的值
    public static double getFieldValueAsDouble(Map<String, Object> subject, String field) {
        Object value = subject.get(field);
        if (value instanceof Number) {
            return ((Number) value).doubleValue();
        } else if (value instanceof String && isNumeric((String) value)) {
            return Double.parseDouble((String) value);
        }
        throw new IllegalArgumentException("Unknown or non-numeric field: " + field);
    }

    // 判断字符串是否为数字
    public static boolean isNumeric(String strNum) {
        if (strNum == null) {
            return false;
        }
        try {
            Double.parseDouble(strNum);
        } catch (NumberFormatException nfe) {
            return false;
        }
        return true;
    }

    // 根据指定科目字段排序
    public static List<Map<String, Object>> sortBySubjectField(List<Map<String, Object>> students
            , String fieldValue, String fieldName, Integer od,String listName) {
        if (N_Utils.isEmpty(fieldValue)) {
            if (od.equals(2)) {//降序
                return students.stream().sorted(Comparator.comparing(student -> student.get(fieldName).toString(), Comparator.nullsLast(Comparator.reverseOrder()))).collect(Collectors.toList());
            } else {//升序
                return students.stream().sorted(Comparator.comparing(student -> student.get(fieldName).toString(), Comparator.nullsLast(Comparator.naturalOrder()))).collect(Collectors.toList());
            }
        }
        Comparator<Map<String, Object>> studentComparator = Comparator.comparingDouble((Map<String, Object> student) -> {
            // 获取并转换subjectList为List<Map<String, Object>>
            @SuppressWarnings("unchecked")
            List<Map<String, Object>> subjectList = (List<Map<String, Object>>) student.get(listName);

            // 查找与subjectid匹配的第一个科目，并根据field获取其值
            return subjectList.stream()
                              .filter(subject -> fieldValue.equals(subject.get(fieldName)))
                              .mapToDouble(subject -> MarkingUtil.getFieldValueAsDouble(subject, fieldName))
                              .findFirst().orElse(Double.NaN);
        }); // 如果是数值型字段，通常希望降序排列
        if (od.equals(2)) {
            studentComparator = studentComparator.reversed();
        }

        // 对学生列表进行排序
        return students.stream().sorted(studentComparator).collect(Collectors.toList());
    }

    //分页
    public static PageResult getPageResult(Integer page, Integer pageSize, List<?> list) {
        int start = (page - 1) * pageSize;
        PageResult pageResult = new PageResult();
        pageResult.setTotal(list.size());
        list = list.stream().skip(start).limit(pageSize).collect(Collectors.toList());
        pageResult.setList(list);
        return pageResult;
    }

    // 根据指定字段排序
    public static List<Map<String, Object>> sortByField(List<Map<String, Object>> list, String field, Integer od) {
        if (od.equals(2)) {//降序
            return list.stream().sorted(Comparator.comparing(student -> student.get(field).toString(), Comparator.nullsLast(Comparator.reverseOrder()))).collect(Collectors.toList());
        } else {//升序
            return list.stream().sorted(Comparator.comparing(student -> student.get(field).toString(), Comparator.nullsLast(Comparator.naturalOrder()))).collect(Collectors.toList());
        }
    }

    public static void main(String[] args) {
        List<RankGroupVo> list = fdScore(1.0, 5);
        for (RankGroupVo rgvo : list) {
            System.out.println(rgvo.getGroupname() + ";" + rgvo.getMinvalue() + "-" + rgvo.getMaxvalue());

        }
    }
}
