package com.huatek.busi.util;

import cn.hutool.core.util.StrUtil;
import com.huatek.busi.vo.epa.EpaEvaluateDataVo;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat;

/**
 * 变压器评测计算公式
 */
public class TransformerFormulaCal {
    private static volatile TransformerFormulaCal transformerFormulaSingleton = null;

    private TransformerFormulaCal() {
    }

    public static TransformerFormulaCal getInstance() {
        if (transformerFormulaSingleton == null) {
            synchronized (TransformerFormulaCal.class) {
                if (transformerFormulaSingleton == null) {
                    transformerFormulaSingleton = new TransformerFormulaCal();
                }
            }
        }
        return transformerFormulaSingleton;
    }

    /**
     * 计算变压器环境等级系数
     *
     * @param level 环境等级
     * @return Double
     */
    public Double calcEnvironmentCoefficient(String level) {
        if (StrUtil.isBlank(level)) {
            return 1d;
        }
        double coefficient = 1d;
        if (level.equals("1")) {
            coefficient = 1d;
        } else if (level.equals("2")) {
            coefficient = 1.05d;
        } else if (level.equals("3")) {
            coefficient = 1.15d;
        } else if (level.equals("4")) {
            coefficient = 1.3d;
        }
        return coefficient;
    }

    /**
     * ƒE=环境系数：表8（运行环境对应的环境修正系数）
     * 环境恶劣等级0级=1（7天平均温度≦10℃   ）
     * 环境恶劣等1级=1.05（7天平均温度≦25℃）
     * 环境恶劣等级2级=1.1（7天平均温度≦35℃），
     * 环境恶劣等级3级=1.15（7天平均温度≦40℃）
     * 环境恶劣等级4级=1.3（7天平均温度≦45℃），
     */
    public Double calcEnvironmentCoefficient(double temperature) {
        Double coefficient = 1d;
        if (temperature <= 10d) {
            coefficient = 1.0d;
        } else if (temperature > 10 && temperature <= 25d) {
            coefficient = 1.05d;
        } else if (temperature > 25 && temperature <= 35d) {
            coefficient = 1.1d;
        } else if (temperature > 35 && temperature <= 40d) {
            coefficient = 1.15d;
        } else if (temperature > 40 && temperature < 45d) {
            coefficient = 1.3d;
        } else {
            coefficient = 1.3d;
        }
        return coefficient;
    }


    /**
     * 计算负荷系数
     *
     * @param load 负荷率值
     * @return Double
     */
    public Double calcLoadCoefficient(double load) {
        Double coefficient = 1d;
        if (load > 0.0 && load < 40d) {
            coefficient = 1.0d;
        } else if (load >= 40 && load < 60d) {
            coefficient = 1.05d;
        } else if (load >= 60 && load < 70d) {
            coefficient = 1.1d;
        } else if (load >= 70 && load < 80d) {
            coefficient = 1.25d;
        } else if (load >= 80 && load < 100d) {
            coefficient = 1.6d;
        } else {
            coefficient = 1d;
        }
        return coefficient;
    }

    /**
     * 计算变压器预期寿命
     *
     * @param FL 负荷率
     * @param FE 环境等级
     * @param TD 设计寿命TD
     * @return Double
     */
    public Double calcExpectRunningLife(double FL, double FE, double TD) {
        double d = TD / (FL * FE);
        return new BigDecimal(d).setScale(3, RoundingMode.HALF_UP).doubleValue();
    }

    /**
     * 为变压器初始老化系数
     * B0= (ln⁡(1-X_HI ) - ln⁡ (1-X_HI0))/(T2-T1)
     * X_HI ---> 为设备在 T2 时刻健康水平指数， 取值范围为 0~1； X_HI0 ---> 为设备的初始投运日期 T1
     * 时刻的健康水平指数， 取 0.95 (T2-T1) ---> 实际预期寿命 life
     *
     * @param life 预期寿命
     * @return Double
     */
    public Double calcInitAgingCoefficient(double life) {
        double START = 1d - Constant.END_INDEX;
        double END = 1d - Constant.INIT_INDEX;
        double temp = Math.log(START) - Math.log(END);
        double value = temp / life;
        return new BigDecimal(value).setScale(4, RoundingMode.HALF_UP).doubleValue();
    }

    /**
     * 计算变压器主绝缘老化状态健康指数
     *
     * @param B0      变压器初始老化系数
     * @param runTime 运行时长
     * @return Double
     */
    public Double calcAgingHealthIndex(double B0, double runTime) {
        double tmp = 1d - Constant.INIT_INDEX;
        double pow = Math.pow(Constant.E, B0 * runTime);
        double value = 1 - (tmp * pow);
//        double value = tmp * pow;
        return new BigDecimal(value).doubleValue();
    }

    /**
     * 计算变压器绕组热点温度
     *
     * @param temp1 顶层油温
     * @param temp2 绕组测温最高点温度
     * @return Double
     * 计算公式： envvTemp + temp1*((1+r*k^2 )/(1+r))^x + hgr*k^y
     */
    public Double calcHotPointTemprature(double temp1, double temp2) {
        double envTemp = Constant.ENVIRONMENT_TEMPERATURE;
        double r = Constant.R;
        double k = Constant.K_NEW;
        double x = Constant.X;
        double y = Constant.Y;
        double hgr = temp2 - temp1;
        double t1 = temp1 * Math.pow(((1d + r * Math.pow(k, 2d)) / (1d + r)), x);
        double t2 = hgr * Math.pow(k, y);
        double result = envTemp + t1 + t2;
        return new BigDecimal(result).setScale(4, RoundingMode.HALF_UP).doubleValue();
    }

    /**
     * 计算变压器绕组热点温度2
     *
     * @param environmentTemperature 环境温度
     * @param indexOfOil             油指数
     * @param loadCoefficient        负载系数，负载电流/额定电流
     * @param topOilTemperature      顶层油温
     * @param lossRatio              额定电流下的负载损耗和空载损耗之比
     * @param windingTemperature     绕组测温最高点温度
     * @param windingIndex           绕组指数
     * @return Double
     * 计算公式： envvTemp + temp1*((1+r*k^2 )/(1+r))^x + hgr*k^y
     */
    public Double calcHotPointTemprature2(double environmentTemperature, double indexOfOil, double loadCoefficient, double topOilTemperature, double lossRatio, double windingTemperature, double windingIndex) {
        double envTemp = environmentTemperature;
        double r = lossRatio;
        double k = loadCoefficient;
        double x = indexOfOil;
        double y = windingIndex;
        double hgr = windingTemperature - topOilTemperature;
        double t1 = topOilTemperature * Math.pow(((1d + r * Math.pow(k, 2d)) / (1d + r)), x);
        double t2 = hgr * Math.pow(k, y);
        double result = envTemp + t1 + t2;
        return new BigDecimal(result).setScale(4, RoundingMode.HALF_UP).doubleValue();

    }


    /**
     * 热点温度高于400℃时，用此公式计算热点温度
     *
     * @param _C2H4 c2h4测量值
     * @param _C2H6 c2h6测量值
     * @return Double
     * 计算公式： T=322lg(c2h4/c2h6) +525
     */
    public Double getTemperater_A(double _C2H4, double _C2H6) {
        // A  C2H4/C2H6
        double T = 322d * Math.log10(_C2H4 / _C2H6) + 525d;
        return new BigDecimal(T).setScale(4, RoundingMode.HALF_UP).doubleValue();
    }

    /**
     * 计算V值
     *
     * @param temp 热点温度
     * @return Double
     * 计算公式： V=2^((temp-98)/6)
     */
    public Double calcVValue(double temp) {
        double pow = (temp - 98d) / 6d;
        double result = Math.pow(2d, pow);
        return new BigDecimal(result).setScale(4, RoundingMode.HALF_UP).doubleValue();
    }

    /**
     * 计算绕组测温老化率
     *
     * @param B  变压器最终老化系数
     * @param v1 原边一个测温最大值C1计算所得
     * @param v2 副边一个测温最大值C2计算所得
     * @return Double
     */
    public Double calcAgingHealthIndexNew(double B, double v1, double v2) {
        double v = (v1 + v2) / 2d;
        double result = B * v;
        return new BigDecimal(result).setScale(4, RoundingMode.HALF_UP).doubleValue();
    }

    /**
     * 按照升序计算权重
     * 升序公式：0≦ x ＜a y(x)=0 a≦ x ＜b y(x)=(x-a)/(b-a) b≦x y(x)=1
     *
     * @param a        阈值
     * @param b        阈值
     * @param x        实际值
     * @param weight   权重
     * @param isAttend 是否参与评测：0:不参与  1：参与
     * @return
     */
    public Double clacFormulaAsc(double a, double b, double x, double weight, String isAttend) {
        if (isAttend.equals("0")) {
            return 0d;
        }
        if (weight == 0d) {
            return 0d;
        }

        double value = 1d;
        if (x >= 0d && x < a) {
            value = 0d;
        } else if (x >= a && x < b) {
            value = (x - a) / (b - a);
        } else if (x >= b) {
            value = 1d;
        }
        double d = value * weight;
        return new BigDecimal(d).setScale(4, RoundingMode.HALF_UP).doubleValue();
    }

    /**
     * 按照降序计算权重
     * 降序公式：0≦ x ＜a y(x)=1 a≦ x ＜b y(x)=(b-x)/(b-a) b≦x y(x)=0
     *
     * @param a        阈值
     * @param b        阈值
     * @param x        实际值
     * @param weight   权重
     * @param isAttend 是否参与评测：0:不参与  1：参与
     * @return Double
     */
    public Double clacFormulaDesc(double a, double b, double x, double weight, String isAttend) {
        if (isAttend.equals("0")) {
            return 0d;
        }
        if (weight == 0d) {
            return 0d;
        }

        double value = 1d;
        if (x >= 0d && x < a) {
            value = 1d;
        } else if (x >= a && x < b) {
            value = (b - x) / (b - a);
        } else if (x >= b) {
            value = 0d;
        }
        double d = value * weight;
        return new BigDecimal(d).setScale(4, RoundingMode.HALF_UP).doubleValue();
    }

    /**
     * 按照升序计算
     * 升序公式：0≦ x ＜a y(x)=0 a≦ x ＜b y(x)=(x-a)/(b-a) b≦x y(x)=1
     *
     * @param a        阈值
     * @param b        阈值
     * @param x        实际值
     * @param isAttend 是否参与评测：0:不参与  1：参与
     * @return
     */
    public Double clacFormulaAsc2(double a, double b, double x, String isAttend) {
        if (isAttend.equals("0")) {
            return 0d;
        }

        double value = 1d;
        if (x >= 0d && x < a) {
            value = 0d;
        } else if (x >= a && x < b) {
            value = (x - a) / (b - a);
        } else if (x >= b) {
            value = 1d;
        }
        return new BigDecimal(value).setScale(4, RoundingMode.HALF_UP).doubleValue();
    }

    /**
     * 按照降序计算
     * 降序公式：0≦ x ＜a y(x)=1 a≦ x ＜b y(x)=(b-x)/(b-a) b≦x y(x)=0
     *
     * @param a        阈值
     * @param b        阈值
     * @param x        实际值
     * @param isAttend 是否参与评测：0:不参与  1：参与
     * @return Double
     */
    public Double clacFormulaDesc2(double a, double b, double x, String isAttend) {
        if (isAttend.equals("0")) {
            return 0d;
        }

        double value = 1d;
        if (x >= 0d && x < a) {
            value = 1d;
        } else if (x >= a && x < b) {
            value = (b - x) / (b - a);
        } else if (x >= b) {
            value = 0d;
        }
        return new BigDecimal(value).setScale(4, RoundingMode.HALF_UP).doubleValue();
    }

    /**
     * 计算剩余寿命
     * 计算公式：ln(1-endIndex)-ln(1-xh)/b
     *
     * @param xh 变压器状态修正后最终健康指数
     * @param b  变压器最终老化系数
     * @return
     */
    public double calcSurplus(double xh, double b) {
        double start = 1d - Constant.END_INDEX;
        double end = 1d - xh;
//        double  end= 1d-Constant.INIT_INDEX;
        double log1 = Math.log(start);
        double log2 = Math.log(end);
        double tmp = log1 - log2;
        double d = tmp / b;
        return new BigDecimal(d).setScale(4, RoundingMode.HALF_UP).doubleValue();
    }

    /**
     * 计算监测时间内寿命损失率
     * L = 	时间(小时)	  		   修正值
     * <8 			 		  0.008
     * 8<=x<16			 	  0.015
     * 16<=x<24			  0.022
     * 24<=x<48 			  0.035
     * 48<=x<72 			  0.045
     * x>72 			 	  0.065
     *
     * @param value 变压器过负荷/过热时间
     * @return double
     */
    public double calcL(double value) {
        double L = 0;
        if (value == 0d) {
            L = 0;
        } else if (value > 0d && value <= 8d) {
            L = 0.008d;
        } else if (value > 8d && value <= 16) {
            L = 0.015d;
        } else if (value > 16d && value <= 24) {
            L = 0.022d;
        } else if (value > 24d && value <= 48) {
            L = 0.035d;
        } else if (value > 48d && value <= 72) {
            L = 0.045d;
        } else if (value >= 72d) {
            L = 0.065d;
        }
        return L;
    }

    /**
     * 计算未来故障率
     *
     * @param value 健康指数
     * @return double
     */
    public double clacFutureFailureRate(double value) {
        double tmp = 1 - value;
        double tmp2 = tmp * Constant.C;
        double tmp3 = Math.pow(Math.E, tmp2);
        double d = Constant.K / tmp3;
        return new BigDecimal(d * 100).setScale(4, RoundingMode.HALF_UP).doubleValue();
    }


    /**
     * @param value 实际值
     * @return double
     * <p>
     * 缺陷风险得分
     * 0-1     （修正系数R_1=0.95）、
     * 1-2    （修正系数=0.9）、
     * 2-3    （修正系数=0.85）、
     * 3-4    （修正系数=0.8）、
     * 4-5    （修正系数=0.7）
     * >6    （修正系数=0.65）
     * @Title: defectRiskCorrection
     * @Description: 缺陷风险修正
     * @createDate: Sep 4, 2019 4:50:27 PM
     */
    public Double defectRiskCorrection(double value) {
        if (value == 0d) {
            return 1d;
        } else if (value > 0d && value < 1d) {
            return 0.95d;
        } else if (value >= 1d && value < 2d) {
            return 0.90d;
        } else if (value >= 2d && value < 3d) {
            return 0.85d;
        } else if (value >= 3d && value < 4d) {
            return 0.8d;
        } else if (value >= 4d && value < 5d) {
            return 0.7d;
        } else {
            return 0.65d;
        }
    }

    /**
     * 热点温度计算
     *
     * @param temp            绕组最大温度
     * @param epaEvaluateData 油色谱数据
     *                        公式修改为300度 400度判断后的折算值
     * @return Double
     */
    public Double calculateWindingTemp(BigDecimal temp, EpaEvaluateDataVo epaEvaluateData) {
        double t = 0d;
        if (temp.compareTo(new BigDecimal(400)) > 0) {
            t = (322d) * Math.log10(Double.parseDouble(epaEvaluateData.getC2h4()) / Double.parseDouble(epaEvaluateData.getC2h6())) + (525d);
        } else if (temp.compareTo(new BigDecimal(300)) >= 0 && temp.compareTo(new BigDecimal(400)) <= 0) {
            t = (-1196d) * Math.log10(Double.parseDouble(epaEvaluateData.getCo2()) / Double.parseDouble(epaEvaluateData.getCo())) + (660d);
        } else if (temp.compareTo(new BigDecimal(300)) < 0) {
            t = (-241d) * Math.log10(Double.parseDouble(epaEvaluateData.getCo2()) / Double.parseDouble(epaEvaluateData.getCo())) + (373d);
        }
        double t2 = Math.pow(2, (t - 98) / 6);
        return t / t2;
    }

}
