package com.qmth.teachcloud.report.business.utils;

import java.text.DecimalFormat;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @Description:
 * @Author: CaoZixuan
 * @Date:
 */
public class MathUtil {
    /**
     * 计算方差
     *
     * @param x double[]
     * @return 方差
     */
    public static double calculateVariance(List<Double> x) {
        int m = x.size();
        double sum = 0;
        for (double v : x) {//求和
            sum += v;
        }
        double dAve = sum / m;//求平均值
        double dVar = 0;
        for (double v : x) {//求方差
            dVar += (v - dAve) * (v - dAve);
        }
        return dVar / m;
    }

    /**
     * 计算标准差
     *
     * @param x double[]
     * @return 标准差
     */
    public static double calculateStandardDeviation(List<Double> x) {
        return Math.sqrt(calculateVariance(x));
    }

    /**
     * 计算众数
     *
     * @param x 要计算的数组
     * @return 众数
     */
    public static String calculateMode(List<Double> x) {
        x = x.stream().map(MathUtil::formatDouble2).collect(Collectors.toList()); // 给数据源保留两位有效数字后再取众数

        Map<Double, Integer> map = new HashMap<>();
        for (double v : x) {
            Integer count = map.get(v);
            if (count == null) {
                count = 1;
            } else {
                count++;
            }
            map.put(v, count);
        }
        StringBuilder mode = new StringBuilder();

        int maxValue = 0;
        for (Double aDouble : map.keySet()) {
            Integer value = map.get(aDouble);
            if (value > maxValue) {
                maxValue = value;
            }
        }
        if (maxValue > 1) {
            for (Double aDouble : map.keySet()) {
                Integer value = map.get(aDouble);
                if (value == maxValue) {
                    mode.append(aDouble).append(",");
                }
            }
            mode = new StringBuilder(mode.substring(0, mode.length() - 1));
        }
        return mode.toString();
    }

    /**
     * 计算分位数
     *
     * @param x     数据源
     * @param split 分位数值（上四分位：0.25、中位数：0.5、下四分位：0.75、。。。。。。）
     * @return 值
     */
    public static double calculateQuantile(List<Double> x, double split) {
        List<Double> sortList = x.stream().sorted((o1, o2) -> {
            if (o1.equals(o2)) {
                return 0;
            } else if (o1 < o2) {
                return -1;
            } else {
                return 1;
            }
        }).collect(Collectors.toList());

        int totalNumber = sortList.size();
        double position = (totalNumber + 1) * split;
        int index = (int) position;
        if (position < 1 || position > totalNumber) {
            return 0;
        }
        if ((double) index == position) {
            return sortList.get(index - 1);
        }
        double thisPower = 1 - (position - index);
        double nextPower = position - index;
        return sortList.get(index - 1) * thisPower + sortList.get(index) * nextPower;
    }

    /**
     * double保留2位小数
     *
     * @param d double
     * @return 保留后的值
     */
    public static double formatDouble2(double d) {
        DecimalFormat df = new DecimalFormat("#.00");
        return Double.parseDouble(df.format(d));
    }

    /**
     * double保留1位小数
     *
     * @param d double
     * @return 保留后的值
     */
    public static double formatDouble1(double d) {
        DecimalFormat df = new DecimalFormat("#.0");

        return Double.parseDouble(df.format(d));
    }

    /**
     * double保留整数
     *
     * @param d double
     * @return 保留后的值
     */
    public static double formatDouble0(double d) {
        DecimalFormat df = new DecimalFormat("#");

        return Double.parseDouble(df.format(d));
    }

    /**
     * 给譬如 A1 B1 B2 B10 C2 这样的特殊字符串集合排序
     *
     * @param dimensionSet 考查点字符串
     * @return 排序结果
     */
    public static List<String> sortDimension(List<String> dimensionSet) {
        return dimensionSet.stream().sorted((o1, o2) -> {
            int compareResult = o1.substring(0, 1).compareToIgnoreCase(o2.substring(0, 1));
            if (compareResult > 0) {
                return 1;
            } else if (compareResult < 0) {
                return -1;
            } else {
                int cell1 = 0;
                int cell2 = 0;
                if (o1.length() > 1) {
                    cell1 = Integer.parseInt(o1.substring(1));
                }
                if (o2.length() > 1) {
                    cell2 = Integer.parseInt(o2.substring(1));
                }
                if (cell1 >= cell2) {
                    return 1;
                } else {
                    return -1;
                }
            }
        }).collect(Collectors.toList());
    }

}
