package com.zcxk.core.utils;

import cn.hutool.core.util.NumberUtil;

import java.math.BigDecimal;

/**
 * @author Andy
 * @description: 数字处理
 * @date 2021/7/16
 * @version V1.0
 **/
public class NumberDistri {

    /**
     * splitNum:将数字num拆分成随机的size份. <br/>
     *
     * @param number 要拆分的数字
     * @param size 拆分的个数
     * @since JDK 1.6
     */
    public static int[] splitNum(int number, int size) {
        // 估算总倍数
        int times = getTimes(number, size);
        //分配总数量
        int num = number / times;

        int[] result = new int[size];
        // 分配平均数
        int avg = 1 * times;
        // 真实值和估算值之差
        int remain = number - num * times;

        // 分配人数小于10时，平均分配
        if (size <= 10) {
            int real = (num / size) * times;
            avg = real + (number - size * real) / size;
            remain = number - size * avg;
        }

        // 先给每个赋值1，避免出现没有分配到的情况
        for (int i = 0; i < size; i++) {
            if (remain > 0 && remain - i > 0) {
                result[i] = avg + 1;
            } else {
                result[i] = avg;
            }
            num--;
        }

        // 分配数大于10,则随机在分配
        if (size > 10) {
            int max = (num / size) * 3;
            int index = 0;
            int small = Integer.MAX_VALUE;
            for (int i = 0; i < size; i++) {
                int temp = generateNum(num, max);
                if (temp < small) {
                    index = i;
                    small = temp;
                }
                if (temp > 0) {
                    result[i] += temp * times;
                    num -= temp;
                    if (num == 0) {
                        break;
                    }
                }
            }
            if (num > 0) {
                result[index] += num * times;
            }
        }

        return result;
    }


    /**
     * getTimes:获取推荐倍数. <br/>
     *
     * @author liangxp
     * @since JDK 1.6
     */
    public static int getTimes(int num, int size) {
        int times = num / size;
        if (times > 10 && times < 100) {
            times = 10;
        } else if (times > 100 && times < 1000) {
            times = 100;
        } else if (times > 1000 && times < 10000) {
            times = 1000;
        } else if (times > 10000 && times < 100000) {
            times = 10000;
        } else if (times > 100000 && times < 1000000) {
            times = 100000;
        } else if (times > 1000000 && times < 10000000) {
            times = 1000000;
        } else if (times > 10000000 && times < 100000000) {
            times = 10000000;
        } else if (times > 100000000 && times < 1000000000) {
            times = 100000000;
        }
        return times;
    }

    /**
     * generateNum:获取num内的不大于max的随机数. <br/>
     *
     * @author liangxp
     * @since JDK 1.6
     */
    public static int generateNum(int num, int max) {
        int temp = 0;
        do {
            temp = getRamdom(num);
        } while (temp > max);
        return temp;
    }


    public static int getRamdom(int num) {
        return (int) (Math.random() * num);
    }

    /**
     * 乘法
     *
     * @param v double
     *
     * double
     * @return double
     */
    public static double multiplyDoub(double... v) {
        BigDecimal b = BigDecimal.valueOf(v[0]);
        for (int i = 1; i < v.length; i++) {
            BigDecimal b2 = BigDecimal.valueOf(v[i]);
            b = b.multiply(b2);
        }
        return b.doubleValue();
    }

    /**
     * 乘法
     *
     * @param places 四舍五入保留小数点 位数
     * @param v double
     * @return double
     */
    public static double multiplyDoubPlaces(int places, double... v) {
        BigDecimal b = BigDecimal.valueOf(v[0]);
        for (int i = 1; i < v.length; i++) {
            BigDecimal b2 = BigDecimal.valueOf(v[i]);
            b = b.multiply(b2);
        }
        return b.setScale(places, BigDecimal.ROUND_HALF_UP).doubleValue();
    }

    /**
     * 除法 提供精确的小数位四舍五入处理。
     *
     * @param v 计算值（除数）-需要四舍五入的数字
     * @param scale 小数点后保留几位
     * @return 四舍五入后的结果
     */
    public static double dividePlaces(int scale, double... v) {
        if (scale < 0) {
            throw new IllegalArgumentException("The scale must be a positive integer or zero");
        }
        BigDecimal b = BigDecimal.valueOf(v[0]);
        for (int i = 1; i < v.length; i++) {
            BigDecimal b2 = BigDecimal.valueOf(v[i]);
            b = b.divide(b2, scale, BigDecimal.ROUND_HALF_UP);
        }
        return b.doubleValue();
    }


    /**
     * 加法
     *
     * double
     *
     * @param v double
     * @return double
     */
    public static double add(double... v) {
        BigDecimal b = BigDecimal.valueOf(v[0]);
        for (int i = 1; i < v.length; i++) {
            BigDecimal b2 = BigDecimal.valueOf(v[i]);
            b = b.add(b2);
        }
        return b.doubleValue();
    }


    /**
     * 减法
     *
     * double
     *
     * @param v double
     * @return double
     */
    public static double subtract(double... v) {
        BigDecimal b = BigDecimal.valueOf(v[0]);
        for (int i = 1; i < v.length; i++) {
            BigDecimal b2 = BigDecimal.valueOf(v[i]);
            b = b.subtract(b2);
        }
        return b.doubleValue();
    }


    /**
     * 减法
     *
     * @param places 四舍五入保留小数点 位数
     * @param v double
     * @return double
     */
    public static double subtractPlaces(int places, double... v) {
        BigDecimal b = BigDecimal.valueOf(v[0]);
        for (int i = 1; i < v.length; i++) {
            BigDecimal b2 = BigDecimal.valueOf(v[i]);
            b = b.subtract(b2);
        }
        return b.setScale(places, BigDecimal.ROUND_HALF_UP).doubleValue();
    }

    /**
     * 保留几位小数点
     *
     * @param places 四舍五入
     * @return double
     */
    public static double doubPlaces(int places, double v) {
        BigDecimal b = BigDecimal.valueOf(v);
        return b.setScale(places, BigDecimal.ROUND_HALF_UP).doubleValue();
    }

    /*
     * @description 比较Integer是否相等
     * @param num1
     * @param num2
     * @return
     **/
    public static boolean integerEquals(Integer num1, Integer num2){
        if(num1 == null && num2 == null)return true;
        if(num1 != null  && num2 != null){
            return NumberUtil.equals(num1,num2);
        }else {
            return false;
        }
    }

}
