package com.xhkjedu.sexam.utils;

import com.xhkjedu.utils.N_Utils;
import lombok.extern.slf4j.Slf4j;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @ClassName StudyUtil
 * Description study模块用到的工具类
 * Author WN
 * Date 2022/2/21 10:01
 **/
@Slf4j
public class ExamUtil {
    public static Map<String, String> uriMap = new ConcurrentHashMap<>();
    // 默认除法运算精度
    private static final int DEF_DIV_SCALE = 2;

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

    /**
     * 提供（相对）精确的除法运算。当发生除不尽的情况时，由scale参数指 定精度，以后的数字舍弃。
     *
     * @param v1    被除数
     * @param v2    除数
     * @param scale 表示表示需要精确到小数点以后几位。
     * @return 两个参数的商
     */
    public static double div(double v1, double v2, int scale) {
        if (scale < 0) {
            throw new IllegalArgumentException("The   scale   must   be   a   positive   integer   or   zero");
        }
        BigDecimal b1 = new BigDecimal(Double.toString(v1));
        BigDecimal b2 = new BigDecimal(Double.toString(v2));
        return b1.divide(b2, scale, BigDecimal.ROUND_DOWN).doubleValue();
    }

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

    /**
     * 提供精确的小数位四舍五入处理。
     *
     * @param v     需要四舍五入的数字
     * @param scale 小数点后保留几位
     * @return 四舍五入后的结果
     */
    public static double round(double v, int scale) {
        if (scale < 0) {
            throw new IllegalArgumentException("The   scale   must   be   a   positive   integer   or   zero");
        }
        BigDecimal b = new BigDecimal(Double.toString(v));
        BigDecimal one = new BigDecimal("1");
        return b.divide(one, scale, BigDecimal.ROUND_HALF_UP).doubleValue();
    }

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

    /**
     * 提供精确的乘法运算。
     *
     * @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();
    }

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

    //两数相减
    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 占比如80%写作0.8
     * @return
     */
    public static double getScoreRateScore(double v1, double v2) {
        BigDecimal b1 = new BigDecimal(Double.toString(v1));
        BigDecimal b2 = new BigDecimal(Double.toString(v2));

        return b1.multiply(b2).setScale(0, BigDecimal.ROUND_HALF_UP).doubleValue();
    }

    //方差s^2=[(x1-x)^2 +...(xn-x)^2]/n 或者s^2=[(x1-x)^2 +...(xn-x)^2]/(n-1)
    public static double variance(List<Double> x) {
        int m = x.size();
        double sum = 0;
        for (int i = 0; i < m; i++) {//求和
            sum += x.get(i);
        }
        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 standardDiviation(List<Double> x) {
        return Math.sqrt(variance(x));
    }

    /**
     * 根据本次排名和参数计算下次的目标
     *
     * @param countschool:本次排名
     * @param goalparam：进步目标参数
     * @return
     */
    public static Integer getUserGroupGoalByParam(Integer countschool, String goalparam) {
        if (countschool != null && (1 == countschool || 2 == countschool)) {//若本次是第一名或者第二名，则下次目标一定是第一名
            return 1;
        } else {
            BigDecimal count = countschool == null || N_Utils.isEmpty(goalparam) ? new BigDecimal(0) :
                    new BigDecimal(goalparam).multiply(new BigDecimal(countschool.toString()));//进步的名次
            Integer thiscount = countschool == null ? 0 : new BigDecimal(countschool.toString()).subtract(count).intValue();
            //舍弃小数点
            return thiscount;
        }
    }
}
