package com.jiayue.ipfcst.calculate.service;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;

public class CalculateMethod {


  /**
   * 准确率计算
   * 均方根
   * @param data 计算数据
   * @param cap 装机容量
   * @return 准确率
   */
  public static BigDecimal calculateC1(List<Map<String,BigDecimal>> data, BigDecimal cap) throws Exception {
    String dataSize  = String.valueOf(data.size());
    BigDecimal size = new BigDecimal(dataSize);
    double sqrtN = Math.sqrt(size.doubleValue());
    BigDecimal sqrtBig = new BigDecimal(sqrtN).setScale(8,BigDecimal.ROUND_HALF_UP);
    BigDecimal p2 = cap.multiply(sqrtBig).setScale(8,BigDecimal.ROUND_HALF_UP);

    BigDecimal differenceSum = IAccuracyPassRateCalculate.ZERO;
    for(Map<String,BigDecimal> map:data){
      BigDecimal sj =  map.get("sj");
      BigDecimal yc = map.get("yc");
      BigDecimal difference = sj.subtract(yc);
      BigDecimal differenceValue = difference.multiply(difference);
      differenceSum = differenceSum.add(differenceValue);
    }
    double sqrt = Math.sqrt(differenceSum.doubleValue());
    BigDecimal p1 = new BigDecimal(sqrt).setScale(8,BigDecimal.ROUND_HALF_UP);

    BigDecimal p = p1.divide(p2,4,BigDecimal.ROUND_HALF_UP);
    BigDecimal result = IAccuracyPassRateCalculate.ONE.subtract(p).multiply(IAccuracyPassRateCalculate.HUNDRED).setScale(2,BigDecimal.ROUND_HALF_UP);
    result = filterResult(result);
    return result;
  }

  /**
   * 准确率计算
   * 绝对值
   * @param data 计算数据
   * @param cap 装机容量
   * @return 准确率
   */
  public static BigDecimal calculateC2(List<Map<String, BigDecimal>> data,BigDecimal cap) throws Exception {
    BigDecimal p1 = IAccuracyPassRateCalculate.ZERO;
    String dataSize  = String.valueOf(data.size());
    BigDecimal size = new BigDecimal(dataSize);
    BigDecimal p2 = cap.multiply(size);
    for (Map<String, BigDecimal> map : data) {
      BigDecimal sj = map.get("sj");
      BigDecimal yc = map.get("yc");
      BigDecimal difference  = sj.subtract(yc).abs();
      p1 = p1.add(difference);
    }
    BigDecimal p = p1.divide(p2,4,BigDecimal.ROUND_HALF_UP);
    BigDecimal result = IAccuracyPassRateCalculate.ONE.subtract(p).multiply(IAccuracyPassRateCalculate.HUNDRED).setScale(2,BigDecimal.ROUND_HALF_UP);
    result = filterResult(result);
    return result;
  }
  /**
   * 准确率计算
   *
   * @param yc 预测值
   * @param sj 实际值
   * @return 准确率
   */
  public static BigDecimal calculateC3(BigDecimal yc, BigDecimal sj) throws Exception {
    // 差值=实际-预测功率
    BigDecimal difference = sj.subtract(yc);
    //错误值= |差值/预测功率|*100
    BigDecimal errorValue = difference.divide(yc, 8, BigDecimal.ROUND_HALF_UP).abs().multiply(IAccuracyPassRateCalculate.HUNDRED);
    // (100-错误值)  四舍五入保留两位小数
    BigDecimal result =IAccuracyPassRateCalculate.HUNDRED.subtract(errorValue).setScale(2, BigDecimal.ROUND_HALF_UP);
    result = filterResult(result);
    return result;
  }

  /**
   * 准确率计算
   *
   * @param data 准确率计算数据
   * @return 准确率
   */
  public static BigDecimal  calculateC4(List<Map<String, BigDecimal>> data) throws Exception {
    BigDecimal sum = IAccuracyPassRateCalculate.ZERO;
    BigDecimal differenceSum = IAccuracyPassRateCalculate.ZERO;
    BigDecimal doubleValue = new BigDecimal("2");

    for (Map<String, BigDecimal> map : data) {
      BigDecimal sj = map.get("sj");
      BigDecimal yc = map.get("yc");
      BigDecimal errorValue = sj.subtract(yc).abs();
      differenceSum = differenceSum.add(errorValue);
    }

    for (Map<String, BigDecimal> map : data) {
      BigDecimal sj = map.get("sj");
      BigDecimal yc = map.get("yc");
      BigDecimal half = new BigDecimal("0.5");
      BigDecimal difference = sj.subtract(yc).abs();
      BigDecimal b2 = difference.divide(differenceSum, 8, BigDecimal.ROUND_HALF_UP);

      BigDecimal sjYcSum = sj.add(yc);
      BigDecimal b1 = sj.divide(sjYcSum, 8, BigDecimal.ROUND_HALF_UP).subtract(half).abs();

      BigDecimal b = b1.multiply(b2).setScale(8, BigDecimal.ROUND_HALF_UP);

      sum = sum.add(b).setScale(8, BigDecimal.ROUND_HALF_UP);
    }

    BigDecimal differenceValue = sum.multiply(doubleValue).setScale(4, BigDecimal.ROUND_HALF_UP);
    BigDecimal result = IAccuracyPassRateCalculate.ONE.subtract(differenceValue).multiply(IAccuracyPassRateCalculate.HUNDRED).setScale(2,BigDecimal.ROUND_HALF_UP);
    result = filterResult(result);
    return result;
  }
  /**
   * 准确率计算
   *
   * @param data 准确率计算数据
   * @return 准确率
   */
  public static BigDecimal  calculateC5(List<Map<String, BigDecimal>> data) throws Exception {
    String size = String.valueOf(data.size());
    BigDecimal n = new BigDecimal(size);
    BigDecimal b1 = IAccuracyPassRateCalculate.ONE.divide(n,8,BigDecimal.ROUND_HALF_UP);
    BigDecimal b2 = IAccuracyPassRateCalculate.ZERO;
    for(Map<String, BigDecimal> map :data){
      BigDecimal sj = map.get("sj");
      BigDecimal yc = map.get("yc");
      BigDecimal cap = map.get("cap");
      BigDecimal difference =  sj.subtract(yc);
      BigDecimal p1 = difference.divide(cap,8,BigDecimal.ROUND_HALF_UP);
      BigDecimal p = p1.multiply(p1).setScale(8,BigDecimal.ROUND_HALF_UP);
      b2 = b2.add(p);
    }

    BigDecimal value = b1.multiply(b2).setScale(8,BigDecimal.ROUND_HALF_UP);
    double sqrt = Math.sqrt(value.doubleValue());
    BigDecimal sqrtBig = new BigDecimal(sqrt).setScale(8,BigDecimal.ROUND_HALF_UP);
    BigDecimal result = IAccuracyPassRateCalculate.ONE.subtract(sqrtBig)
      .multiply(IAccuracyPassRateCalculate.HUNDRED).setScale(2,BigDecimal.ROUND_HALF_UP);
    result = filterResult(result);
    return result;

  }

  /**
   * 准确率计算
   *
   * @param data 准确率计算数据
   * @return 准确率
   */
  public static BigDecimal  calculateC6(List<Map<String, BigDecimal>> data) throws Exception {
    String size = String.valueOf(data.size());
    BigDecimal n = new BigDecimal(size);
    BigDecimal b1 = IAccuracyPassRateCalculate.ONE.divide(n,8,BigDecimal.ROUND_HALF_UP);
    BigDecimal b2 = IAccuracyPassRateCalculate.ZERO;
    for(Map<String, BigDecimal> map :data){
      BigDecimal sj = map.get("sj");
      BigDecimal yc = map.get("yc");
      BigDecimal difference =  sj.subtract(yc);
      BigDecimal p1 = difference.divide(sj,8,BigDecimal.ROUND_HALF_UP);
      BigDecimal p = p1.multiply(p1).setScale(8,BigDecimal.ROUND_HALF_UP);
      b2 = b2.add(p);
    }
    BigDecimal value = b1.multiply(b2).setScale(8,BigDecimal.ROUND_HALF_UP);
    double sqrt = Math.sqrt(value.doubleValue());
    BigDecimal sqrtBig = new BigDecimal(sqrt).setScale(4,BigDecimal.ROUND_HALF_UP);
    BigDecimal result = IAccuracyPassRateCalculate.ONE.subtract(sqrtBig)
      .multiply(IAccuracyPassRateCalculate.HUNDRED);
    result = filterResult(result);
    return result;

  }

  /**
   * 准确率计算
   *
   * @param data 准确率计算数据
   * @param cap 装机容量
   * @return 准确率
   */
  public static BigDecimal  calculateC7(List<Map<String, BigDecimal>> data,BigDecimal cap) throws Exception {
    BigDecimal b3 = IAccuracyPassRateCalculate.ZERO;
    for(Map<String, BigDecimal> map:data){
      BigDecimal sj = map.get("sj");
      BigDecimal yc = map.get("yc");
      b3 = sj.subtract(yc).abs().add(b3);
    }
    //当所有点位的预测和实际相减之和为0 ，说明所有点 预测和实际相等 那么准确率是100%
    if(b3.floatValue() == IAccuracyPassRateCalculate.ZERO.floatValue()){
      return IAccuracyPassRateCalculate.HUNDRED;
    }else{
      BigDecimal sum = IAccuracyPassRateCalculate.ZERO;
      for(Map<String, BigDecimal> map:data){
        BigDecimal sj = map.get("sj");
        BigDecimal yc = map.get("yc");
        BigDecimal b2 = sj.subtract(yc);
        BigDecimal b1 = b2.abs().divide(b3,8,BigDecimal.ROUND_HALF_UP);
        BigDecimal b = b2.multiply(b2).multiply(b1).setScale(8,BigDecimal.ROUND_HALF_UP);
        sum = sum.add(b);
      }
      double sqrt = Math.sqrt(sum.doubleValue());
      BigDecimal sqrtBig = new BigDecimal(sqrt).setScale(8,BigDecimal.ROUND_HALF_UP);
      BigDecimal p = sqrtBig.divide(cap,4,BigDecimal.ROUND_HALF_UP);
      BigDecimal result = IAccuracyPassRateCalculate.ONE.subtract(p).multiply(IAccuracyPassRateCalculate.HUNDRED);
      result = filterResult(result);
      return result;

    }
  }

  /**
   * 准确率计算
   *
   * @param data 准确率计算数据
   * @return 准确率
   */
  public static BigDecimal  calculateC8(List<Map<String, BigDecimal>> data) throws Exception {
    String size = String.valueOf(data.size());
    BigDecimal n = new  BigDecimal(size);
    BigDecimal eSum = IAccuracyPassRateCalculate.ZERO;

    for(Map<String, BigDecimal> map:data){
      BigDecimal sj = map.get("sj");
      BigDecimal yc = map.get("yc");
      BigDecimal errorValue = yc.subtract(sj).divide(yc,8,BigDecimal.ROUND_HALF_UP).abs();
      if(errorValue.floatValue() >= IAccuracyPassRateCalculate.ONE.floatValue()){
        eSum = eSum.add(IAccuracyPassRateCalculate.ONE);
      }else{
        eSum = eSum.add(errorValue);
      }
    }
    BigDecimal error = eSum.divide(n,8,BigDecimal.ROUND_HALF_UP);
    BigDecimal result = IAccuracyPassRateCalculate.ONE.subtract(error).multiply(IAccuracyPassRateCalculate.HUNDRED)
      .setScale(2,BigDecimal.ROUND_HALF_UP);
    result = filterResult(result);
    return result;
  }

  /**
   *
   * @param rootMeanSquareData 准确率计算数据
   * @return 准确率
   */
  public static BigDecimal  calculateC9(List<Map<String, BigDecimal>> rootMeanSquareData) throws Exception {
    BigDecimal result = IAccuracyPassRateCalculate.ZERO;
    BigDecimal sumValue = IAccuracyPassRateCalculate.ZERO;
    BigDecimal calculationValue = IAccuracyPassRateCalculate.ZERO;
    BigDecimal squareValue = IAccuracyPassRateCalculate.ZERO;
    BigDecimal sj = IAccuracyPassRateCalculate.ZERO;
    BigDecimal yc = IAccuracyPassRateCalculate.ZERO;
    BigDecimal openCapacity = IAccuracyPassRateCalculate.ZERO;
    //循环场站数据(从当日0点到现在时刻的前15分钟)，计算均方根准确率
    for(Map<String, BigDecimal> map : rootMeanSquareData){
      sj = map.get("sj");
      yc = map.get("yc");
      openCapacity = map.get("openCapacity");
      // ((此刻的实际功率-此刻的预测功率)/此刻的开机容量)
      calculationValue = sj.subtract(yc).divide(openCapacity,8, BigDecimal.ROUND_HALF_UP);
      // 求平方
      squareValue = calculationValue.multiply(calculationValue);
      // 求和
      sumValue = sumValue.add(squareValue);
    }
    // 和/样本个数
    sumValue = sumValue.divide(BigDecimal.valueOf(rootMeanSquareData.size()),8, BigDecimal.ROUND_HALF_UP);
    // 求平方根
    result = new BigDecimal(Math.sqrt(sumValue.doubleValue()));
    // (1-result)*100
    result = IAccuracyPassRateCalculate.ONE.subtract(result).multiply(IAccuracyPassRateCalculate.HUNDRED);
    result = result.setScale(2, BigDecimal.ROUND_HALF_UP);
    return result;
  }

  /**
   * 过滤结果 <0=0  >100=100
   * @param result 过滤前的结果
   * @return 过滤后的结果
   */
  private static BigDecimal filterResult(BigDecimal result){
    //当结果为负数时，说明偏差过大，准确率为0
    if(result.floatValue()<IAccuracyPassRateCalculate.ZERO.floatValue()){
      result = IAccuracyPassRateCalculate.ZERO;
    }
    if(result.floatValue()>IAccuracyPassRateCalculate.HUNDRED.floatValue()){
      result = IAccuracyPassRateCalculate.HUNDRED;
    }
    return result;
  }

  /**
   * 合格率计算
   *
   * @param data 准确率计算数据
   * @param compare 合格率对比值
   * @return 准确率
   */
  public static BigDecimal calculateB1(List<Map<String, BigDecimal>> data,BigDecimal compare){
    int size = data.size();
    BigDecimal n = new BigDecimal(String.valueOf(size));
    BigDecimal b2 = IAccuracyPassRateCalculate.ZERO;
    for(Map<String, BigDecimal> map :data){
      BigDecimal sj = map.get("sj");
      BigDecimal yc = map.get("yc");
      BigDecimal cap = map.get("cap");
      BigDecimal difference =  sj.subtract(yc);
      BigDecimal p1 = difference.divide(cap,8,BigDecimal.ROUND_HALF_UP).abs();
      BigDecimal p = IAccuracyPassRateCalculate.ONE.subtract(p1).multiply(IAccuracyPassRateCalculate.HUNDRED);
      if(p.floatValue()>=compare.floatValue()){
        b2 = b2.add(IAccuracyPassRateCalculate.ONE);
      }
    }
    BigDecimal result = b2.divide(n,4,BigDecimal.ROUND_HALF_UP).multiply(IAccuracyPassRateCalculate.HUNDRED).setScale(2,BigDecimal.ROUND_HALF_UP);
    result = filterResult(result);
    return result;
  }

}
