import numpy as np

def RSE(pred, true):
    return np.sqrt(np.sum((true-pred)**2)) / np.sqrt(np.sum((true-true.mean())**2))

def CORR(pred, true):
    u = ((true-true.mean(0))*(pred-pred.mean(0))).sum(0) 
    d = np.sqrt(((true-true.mean(0))**2*(pred-pred.mean(0))**2).sum(0))
    return (u/d).mean(-1)

def MAE(pred, true):
    return np.mean(np.abs(pred-true))

def MSE(pred, true):
    return np.mean((pred-true)**2)

def RMSE(pred, true):
    return np.sqrt(MSE(pred, true))

def MAPE(pred, true):
    return np.mean(np.abs((pred - true) / true))

def MSPE(pred, true):
    return np.mean(np.square((pred - true) / true))

def metric(pred, true):
    mae = MAE(pred, true)
    mse = MSE(pred, true)
    rmse = RMSE(pred, true)
    mape = MAPE(pred, true)
    mspe = MSPE(pred, true)
    
    return mae,mse,rmse,mape,mspe


# ShortTerm percentage
def ST(pred, true):
    return np.abs((pred-true)/pred*100)


# ShortTerm percentage 西北  把不计入的点准确率赋值为-1
def ST_xibei(pred, true, cap):
    # pred_8 = pred
    a = np.abs(true-pred)
    b = true-pred
    precentage = []
    sum = 0
    num1 =0 #过低预测计数
    num2 = 0 #过高预测计数
    for i in range(len(pred)):
        if pred[i] == 0:
            if true[i] < cap*0.03:
                precentage.append(-1)
                pass
            else:
                precentage.append(0)
        elif true[i] == 0:
            if pred[i] < cap*0.03:
                precentage.append(-1)
                pass
            else:
                precentage.append(0)
        # 小于装机容量 0.03不计
        elif pred[i] < cap*0.03 and true[i] < cap*0.03:
            precentage.append(-1)
            pass
        else:
            tmp = 1-a[i]/pred[i]
            if tmp<0:
                # print("超低预测 差值{} 真实值{} 预测值{}".format(a[i], true[i], pred[i]))
                num1+=1
                precentage.append(0)
            else:
                if tmp<0.5 and b[i]>0:
                    # print("过低预测 差值{} 真实值{} 预测值{}".format(a[i], true[i], pred[i]))
                    num1+=1
                elif tmp < 0.5 and b[i] < 0:
                    # print("过高预测 差值{} 真实值{} 预测值{}".format(a[i], true[i], pred[i]))
                    num2+=1
                precentage.append(tmp*100)
    print("过低预测{} 过高预测{}".format(num1, num2))
    for i in precentage:
        sum += i
    mean = sum / len(precentage)
    return precentage,mean

# ShortTerm percentage 西北  输出低预测和高预测
def ST_xibei_2(pred, true,cap):
    # pred_8 = pred
    a = np.abs(true-pred)
    b = true-pred
    precentage = []
    sum = 0
    num1 =0
    num2 = 0
    for i in range(len(pred)):
        if pred[i] == 0:
            if true[i] < cap*0.03:
                # precentage.append(100)
                pass
            else:
                precentage.append(0)
        elif true[i] == 0:
            if pred[i] < cap*0.03:
                # precentage.append(100)
                pass
            else:
                precentage.append(0)
        # 小于装机容量 0.03不计
        elif pred[i] < cap*0.03 and true[i] < cap*0.03:
            pass
        else:
            tmp = 1-a[i]/pred[i]
            if tmp<0:
                # print("超低预测 差值{} 真实值{} 预测值{}".format(a[i], true[i], pred[i]))
                num1+=1
                precentage.append(0)
            else:
                if tmp<0.5 and b[i]>0:
                    # print("过低预测 差值{} 真实值{} 预测值{}".format(a[i], true[i], pred[i]))
                    num1+=1
                elif tmp < 0.5 and b[i] < 0:
                    # print("过高预测 差值{} 真实值{} 预测值{}".format(a[i], true[i], pred[i]))
                    num2+=1
                precentage.append(tmp*100)
    print("过低预测{} 过高预测{}".format(num1, num2))
    for i in precentage:
        sum += i
    mean = sum / len(precentage)
    return precentage,mean

# ShortTerm percentage 西北  输出低预测和高预测 超低预测（超低预测准确率直接为0）
def ST_xibei_xiangxi(pred, true,cap):
    # pred_8 = pred
    a = np.abs(true-pred)
    b = true-pred
    precentage = []
    sum = 0
    num1 =0
    num2 = 0
    num3 = 0 #超低预测 预测值不为0
    num4 = 0 #超高预测
    num5 = 0 #超低预测 预测值为0 真实值大于0.03*cap
    print('-----------------评测---------------')
    for i in range(len(pred)):
        if pred[i] == 0:
            if true[i] < cap*0.03:
                pass
            else:
                precentage.append(0)
                num5 += 1
                print('预测值为0 超低点实际值：',true[i])
        elif true[i] == 0:
            if pred[i] < cap*0.03:
                pass
            else:
                precentage.append(0)
                # print('超高点预测值：',pred[i])
                num4 +=1
        # 小于装机容量 0.03不计
        elif pred[i] < cap*0.03 and true[i] < cap*0.03:
            pass
        else:
            tmp = 1-a[i]/pred[i]
            if tmp<0:
                # print("超低预测 差值{} 真实值{} 预测值{}".format(a[i], true[i], pred[i]))
                num3+=1
                # print('超低点预测值：', pred[i])
                precentage.append(0)
            else:
                if tmp<0.5 and b[i]>0:
                    # print("过低预测 差值{} 真实值{} 预测值{}".format(a[i], true[i], pred[i]))
                    num1+=1
                elif tmp < 0.5 and b[i] < 0:
                    # print("过高预测 差值{} 真实值{} 预测值{}".format(a[i], true[i], pred[i]))
                    num2+=1
                precentage.append(tmp*100)
    print("过低预测{} 过高预测{} 超低{} 超高{} 超低为0点{}".format(num1, num2,num3,num4,num5))
    for i in precentage:
        sum += i
    mean = sum / len(precentage)
    return precentage,mean



# ShortTerm percentage 西北  输出详细信息
def ST_xibei_1(pred, true):
    # pred_8 = pred
    cap = 1000
    a = np.abs(true-pred)
    b = true-pred
    precentage = []
    sum = 0
    num1 =0
    num2 = 0
    sub_index=[]
    for i in range(len(pred)):
        if pred[i] == 0:
            if true[i] < cap*0.03:
                # precentage.append(100)
                pass
            else:
                precentage.append(0)
                sub_index.append(i)
        elif true[i] == 0:
            if pred[i] < cap*0.03:
                # precentage.append(100)
                pass
            else:
                precentage.append(0)
                sub_index.append(i)
        # 小于装机容量 0.03不计
        elif pred[i] < cap*0.03 and true[i] < cap*0.03:
            pass
        else:
            tmp = 1-a[i]/pred[i]
            if tmp<0:
                # print("超低预测 差值{} 真实值{} 预测值{}".format(a[i], true[i], pred[i]))
                num1+=1
                precentage.append(0)
                sub_index.append(i)
            else:
                if tmp<0.5 and b[i]>0:
                    # print("过低预测 差值{} 真实值{} 预测值{}".format(a[i], true[i], pred[i]))
                    num1+=1
                    sub_index.append(i)
                    precentage.append(tmp * 100)
                elif tmp < 0.5 and b[i] < 0:
                    # print("过高预测 差值{} 真实值{} 预测值{}".format(a[i], true[i], pred[i]))
                    num2+=1
                    sub_index.append(i)
                    precentage.append(tmp * 100)
                # precentage.append(tmp*100)
    print("过低预测{} 过高预测{}".format(num1, num2))
    for i in precentage:
        sum += i
    mean = sum / len(precentage)
    return precentage,mean,sub_index

# UltraShortTerm percentage
def UST_huabei(pred, true):
    a = np.abs(pred-true)
    ust4hour=[]
    ust1day=[]
    count = 0
    buji = 0
    for i in range(15,len(true),1):
        num1 = 0
        num2 = 0
        for j in range(16):
            num1 = num1 + a[i-j, j, 0]
            num2 = num2 + pred[i-j, j, 0]
        if (num2 / 16) < 0.6 and true[i,0,0] < 0.6:
            ele = 0
            buji += 1
        else:
            ele = num1 / num2 if num1 / num2 < 1 else 1
        ust4hour.append(ele)
        count += 1
        if count % 96 == 0:
            ele = 0
            for k in range(len(ust4hour)-96,len(ust4hour)):
                ele = ele + ust4hour[k]
            ust1day.append((1-ele/(96-buji))*100)
            buji = 0
    return ust4hour, ust1day


# UltraShortTerm percentage 西北地区
def UST_XiBei(pred, true, capacity):
    pt_sub = np.abs(pred - true)
    ust1day = []
    denominator = 0
    ele = 0
    for i in range(0, len(true), 1):
        if pred[i]>=capacity*0.03 or true[i]>=capacity*0.03:
            ele += abs((true[i]/(true[i]+pred[i]))-0.5)*pt_sub[i]
            denominator += pt_sub[i] #分母累加
        #每遍历96点 计算
        if (i+1)%96==0:
            ele = 1-(2*ele/denominator)
            ust1day.append(ele)
            # 清零重新累加
            ele = 0
            denominator = 0
    ust_sum = 0
    for i in ust1day:
        ust_sum += i
    mean = ust_sum / len(ust1day) * 100
    return ust1day, mean




# UltraShortTerm percentage 西北地区
def UST_XiBei_old(pred, true, capacity):
    a = np.abs(pred - true)
    pos = 8
    ust1day = []
    count = 0
    num1 = []
    num2 = 0
    num3 = []
    jilu = []

    for i in range(0, len(true), 1):
        if pred[i] >= capacity*0.03 or true[i] >= capacity*0.03:
            jilu.append(i)
            num1.append(abs(true[i] / (pred[i] + true[i]) - 0.5))
            num2 += a[i]
        count += 1
        if count % 96 == 0:
            ele = 0
            for j in jilu:
                num3.append(a[j] / num2)
            for k in range(len(num1)):
                ele += num1[k] * num3[k]
            ust1day.append(1 - 2 * ele)
            num1.clear()
            num2 = 0
            num3.clear()
            jilu.clear()
    sum =0
    for i in ust1day:
        sum += i
    mean = sum / len(ust1day)
    return ust1day, mean


def UST_ShanDong_wind(pred, true, capacity):
    tmp_s = []
    for i in range(len(pred)//96):
        sub_pred = pred[i*96:(i+1)*96]
        sub_true = true[i*96:(i+1)*96]
        tmp = (1-np.sqrt(np.mean((sub_pred - sub_true)**2))/capacity)*100
        tmp_s.append(tmp)
    # for i in range(20):
    #     print(tmp_s[i])
    mean = np.mean(tmp_s)
    return mean

#每个时点对未来16个点做出预测
def UST_XiBei_16(pred, true, capacity):
    a = np.abs(pred - true)
    pos = 8
    ust1day = []
    count = 0
    num1 = []
    num2 = 0
    num3 = []
    jilu = []

    for i in range(0, len(true), 1):
        if pred[i][pos] >= capacity*0.03 or true[i][pos] >= capacity*0.03:
            jilu.append(i)
            num1.append(abs(true[i][pos] / (pred[i][pos] + true[i][pos]) - 0.5))
            num2 += a[i][pos]
        count += 1
        if count % 96 == 0:
            ele = 0
            for j in jilu:
                num3.append(a[j][pos] / num2)
            for k in range(len(num1)):
                ele += num1[k] * num3[k]
            ust1day.append(1 - 2 * ele)
            num1.clear()
            num2 = 0
            num3.clear()
            jilu.clear()
    return ust1day