/**
 * 
 */
package com.huatek.busi.util;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.temporal.ChronoUnit;

import org.jsoup.helper.StringUtil;

/**
 * @ClassName: TransformerFormulaSingleton
 * @FullClassPath: com.huatek.busi.util.TransformerFormulaSingleton
 * @Description: 变压器评测公式
 * @author: Arno
 * @date: Aug 30, 2019 2:16:22 PM
 * @version: 1.0
 */

public class TransformerFormulaSingleton {

	private static TransformerFormulaSingleton signleton = new TransformerFormulaSingleton();

	private TransformerFormulaSingleton() {
	}

	public static TransformerFormulaSingleton getInstance() {
		return signleton;
	}

	/** @Fields retire_index : 为变压器退役时的健康指数 */
	public static final Double END_INDEX = 0.35d;

	/** @Fields init_index : 为变压器初始运行的健康指数 */
	public static final Double INIT_INDEX = 0.95;

	/** @Fields E : 常量指数 */
	public static final Double E = Math.E;
	
	//相关系数
	public  static final double K = 0.57d;
	
	public  static final double C = 13.4d;

	/**
	 * @Title: calcLoadCoefficient
	 * @Description: 计算负荷系数
	 * @createDate: Sep 6, 2018 6:59:41 PM
	 * @param loadValue
	 *            负荷率值（）
	 * @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;
	}

	/**
	 * @Title: calcEnvironmenCoefficient
	 * @Description: 计算变压器环境等级系数
	 * @createDate: Sep 6, 2018 7:08:07 PM
	 * @param level
	 *            环境等级
	 * @return Double
	 */
	public Double calcEnvironmenCoefficient(String level) {
		if (StringUtil.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;
	}

	/**
	 * @Title: calcExpectRunningLife
	 * @Description: 计算变压器预期寿命
	 * @createDate: Sep 6, 2018 7:47:19 PM
	 * @param FL
	 *            负荷率
	 * @param FE
	 *            环境等级
	 * @param TD
	 *            设计寿命TD
	 * @return Double
	 * 
	 *         T=TD/(FL*FE) ---作为变压器的设计寿命TD
	 */
	public Double calcExpectRunningLife(double FL, double FE, double TD) {
		double d = TD / (FL * FE);
		return new BigDecimal(d).setScale(3, RoundingMode.HALF_UP).doubleValue();
	}

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

	/**
	 * @Title: calcAgingHealthIndex
	 * @Description: 计算变压器主绝缘老化状态健康指数
	 * @createDate: Aug 30, 2019 3:39:19 PM
	 * @param B0
	 *            变压器初始老化系数
	 * @param runTime
	 *            运行时长
	 * @return Double
	 * 
	 * 
	 * 
	 */
	public Double calcAgingHealthIndex(double B0, double runTime) {
		double tmp = 1d - INIT_INDEX;
		double pow = Math.pow(E, B0 * runTime);
		double value = 1 - tmp * pow;
		return new BigDecimal(value).setScale(4, RoundingMode.HALF_UP).doubleValue();
	}

	/**
	 * @Title: calcDateBetween
	 * @Description: 计算俩个日期之间差数
	 * @createDate: Aug 30, 2019 6:03:31 PM
	 * @param begin
	 *            开始时间
	 * @param end
	 *            结束时间
	 * @return Long
	 */
	public Long calcDateDifference(LocalDate begin, LocalDate end, String type) {
		switch (type) {
		case "YEARS":
			return ChronoUnit.YEARS.between(begin, end);
		case "MONTHS":
			return ChronoUnit.MONTHS.between(begin, end);
		case "WEEKS":
			return ChronoUnit.WEEKS.between(begin, end);
		case "DAYS":
			return ChronoUnit.DAYS.between(begin, end);
		case "HOURS":
			return ChronoUnit.HOURS.between(begin, end);
		case "MINUTES":
			return ChronoUnit.MINUTES.between(begin, end);
		case "SECONDS":
			return ChronoUnit.SECONDS.between(begin, end);
		case "MILLIS":
			return ChronoUnit.MILLIS.between(begin, end);
		default:
			return 0L;
		}
	}

	/**
	 * @Title: clacFormulaDesc
	 * @Description: 按照降序计算权重
	 * @createDate: Sep 8, 2018 10:53:55 AM
	 * @param a
	 *            阈值
	 * @param b
	 *            阈值
	 * @param x
	 *            实际值
	 * @param weight
	 *            权重
	 * @return Double
	 * @throws 降序公式
	 *             0≦ x ＜a y(x)=1 a≦ x ＜b y(x)=(b-x)/(b-a) b≦x y(x)=0
	 */
	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();
	}

	/**
	 * @Title: clacFormulaAsc
	 * @Description: 按照升序计算权重
	 * @createDate: Sep 8, 2018 10:53:55 AM
	 * @param a
	 *            阈值
	 * @param b
	 *            阈值
	 * @param x
	 *            实际值
	 * @param weight
	 *            权重
	 * @return double
	 * @throws 降序公式
	 *             0≦ x ＜a y(x)=0 a≦ x ＜b y(x)=(x-a)/(b-a) b≦x y(x)=1
	 */
	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();
	}
	
	
	/** 
	* @Title: defectRiskCorrection 
	* @Description: 缺陷风险修正 
	* @createDate: Sep 4, 2019 4:50:27 PM
	* @param    value  实际值
	* @return   double  
	* 
	*   缺陷风险得分
	*       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）
	*/ 
	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;
		}
	}
	
	
	/** 
	* @Title: clacFutureFailureRate 
	* @Description: 计算未来故障率 
	* @createDate: Sep 15, 2018 1:18:18 PM
	* @param    value 健康指数
	* @return   double    
	*/ 
	public double clacFutureFailureRate(double value){
		double  tmp = 1-value;
		double tmp2 = tmp*C;
		double tmp3 = Math.pow( Math.E, tmp2);
		double d = K/tmp3;
		return new BigDecimal(d).setScale(4, RoundingMode.HALF_UP).doubleValue();
	}
	
	/** 
	* @Title: calcL 
	* @Description: 计算监测时间内寿命损失率 
	* @createDate: Sep 27, 2018 10:54:36 AM
	* @return   double    
	* @throws 
	* 	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
	*/ 
	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 ;
	}
	
	/** 
	* @Title: calcSurplus 
	* @Description: 计算剩余寿命 
	* @createDate: Sep 20, 2018 3:13:54 PM
	* @param   
	* @return   double    
	* ln(1-endIndex)-ln(1-xh)/b
	*/ 
	public  double   calcSurplus(double xh, double b) {
		double start = 1d-END_INDEX;
		double  end= 1d-xh;
		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();
	}
}
