import Users
import tool
import tool as T
import constants as C
import math
import GDOP
import resourceAlloc as RA

#计算用户平均gdop
def function_gdop(users,uavs_pos,c_association,p_association,r_p):
    # p_association=tool.get_p_association(users,uavs_pos,c_association,len(users)*2)
    sum=0
    g=[]
    for user_index in p_association:
        uavs=[]
        uavs.append(uavs_pos[c_association[user_index]])
        for uav_index in p_association[user_index]:
            uavs.append(uavs_pos[uav_index])
        gdop=GDOP.calculate_gdop(uavs,users[user_index])
        g.append(gdop)
        sum += gdop
        # if gdop>C.G_max/(r_p[user_index]):
        #     sum+=gdop*10**6
        # else:
        #     sum+=gdop
    return g

def real_gdop(users,uavs_pos,c_association,p_association,r_p):
    sum = 0
    for user_index in p_association:
        uavs = []
        uavs.append(uavs_pos[c_association[user_index]])
        for uav_index in p_association[user_index]:
            uavs.append(uavs_pos[uav_index])
        gdop = GDOP.calculate_gdop(uavs, users[user_index])
        sum += gdop
    return sum

def energy(pre_uavs,uavs,time_slot=C.time_slot,speed=C.speed):
    sum_e=0
    for i in range(len(pre_uavs)):
        dis=T.calculate_3d_distance_uavs(pre_uavs[i],uavs[i])
        fly_energy=T.cal_fly_energy(dis,speed)
        if fly_energy!=0:
            # hover_energy = (C.P0 + C.P1) * (time_slot - dis / speed)
            hover_energy=(C.P0+C.P1)*(time_slot-dis/speed)
        #     10.5*(uavs[i][2]-30)
        else:
            hover_energy = (C.P0 + C.P1) * (time_slot - dis / speed)
            if hover_energy<0:
                hover_energy=0
        sum_e+=fly_energy+hover_energy

    # print(sum_e/len(pre_uavs))
    return sum_e
def function_rate(uavs,users,uav_to_user,p_all,b_all,r_c):
    rate=[]
    u=1.21
    for i in range(len(uavs)):
        for j in uav_to_user[i]:
            p_alloc=p_all[i]
            b_alloc=b_all[i]
            cur_rate = tool.cal_rate(b_alloc[j], p_alloc[j], uavs[i], users[j])
            # if cur_rate<C.R_min*r_c[j]*u:
            #     cur_rate=-100
            rate.append(cur_rate)
    return rate
def real_rate(uavs,users,uav_to_user,p_all,b_all,r_c):
    rate=[]
    for i in range(len(uavs)):
        for j in uav_to_user[i]:
            p_alloc=p_all[i]
            b_alloc=b_all[i]
            cur_rate = tool.cal_rate(b_alloc[j], p_alloc[j], uavs[i], users[j])
            rate.append(cur_rate)
    return rate
def objective_resource_u(uavs_pos,users,r_c):
    c_association = T.get_c_association(users, uavs_pos, math.ceil(len(users) / len(uavs_pos)))
    p_association = T.get_p_association(users, uavs_pos, c_association, len(users) * 2 / len(uavs_pos))
    uav_to_user = T.get_uav_to_user(c_association, uavs_pos)
    p_all,b_all,rate= RA.resource_alloc_u(users, uavs_pos, r_c, p_association, uav_to_user)
    return c_association,p_association,p_all,b_all
def objective_resource(uavs_pos,users,r_c):
    c_association = T.get_c_association(users, uavs_pos, math.ceil(len(users) / len(uavs_pos)))
    p_association = T.get_p_association(users, uavs_pos, c_association, len(users) * 2 / len(uavs_pos))
    uav_to_user = T.get_uav_to_user(c_association, uavs_pos)
    p_all,b_all,rate= RA.resource_alloc(users, uavs_pos, r_c, p_association, uav_to_user)
    return c_association,p_association,p_all,b_all
def objective_resource_avg(uavs_pos,users,r_c):
    c_association = T.get_c_association(users, uavs_pos, math.ceil(len(users) / len(uavs_pos)))
    p_association = T.get_p_association(users, uavs_pos, c_association, len(users) * 2 / len(uavs_pos))
    uav_to_user = T.get_uav_to_user(c_association, uavs_pos)
    p_all,b_all,rate= RA.resource_alloc_avg(users,uavs_pos,r_c,p_association,uav_to_user)
    return c_association,p_association,p_all,b_all

def objective_resource_proportion(uavs_pos,users,r_c):
    c_association = T.get_c_association(users, uavs_pos, math.ceil(len(users) / len(uavs_pos)))
    p_association = T.get_p_association(users, uavs_pos, c_association, len(users) * 2 / len(uavs_pos))
    uav_to_user = T.get_uav_to_user(c_association, uavs_pos)
    p_all,b_all,rate= RA.resource_alloc_proportion(users,uavs_pos,r_c,p_association,uav_to_user)
    return c_association,p_association,p_all,b_all

def objective(pre_uavs,uavs_pos,users,r_c,r_p,p_all,b_all,c_association,p_association):
    uav_to_user = T.get_uav_to_user(c_association, uavs_pos)
    rate=function_rate(uavs_pos,users,uav_to_user,p_all,b_all,r_c)
    # r=sum(rate)*10**6
    r=sum(rate)
    u=1.21
    gdop = function_gdop(users, uavs_pos, c_association, p_association, r_p)
    # e = energy(pre_uavs, uavs_pos)
    objective=r-sum(gdop)
    for i in range(len(rate)):
        if rate[i]<C.R_min*r_c[i]:
            objective-=10
        if gdop[i]>C.G_max/r_p[i]:
            objective-=10
    # print("能耗：",e)
    return objective, r / len(rate), sum(gdop) / len(users)
    # return (r - gdop) - e, r / len(rate), gdop / len(users)

def real_objective(pre_uavs,uavs_pos,users,r_c,r_p,p_all,b_all,c_association,p_association,time_slot):
    uav_to_user = T.get_uav_to_user(c_association, uavs_pos)
    rate = real_rate(uavs_pos, users, uav_to_user, p_all, b_all,r_c)
    r = sum(rate)
    # r = sum(rate)
    gdop = real_gdop(users, uavs_pos, c_association, p_association, r_p)
    # e = energy(pre_uavs, uavs_pos,time_slot)
    # print("能耗：", e)
    objective = r-gdop
    return objective, r / len(rate), gdop / len(users)
    # return (r - gdop) / e,e, r / len(rate), gdop / len(users)

def gdop_satisfaction(users,uavs_pos,c_association,p_association,r_p):
    # p_association=tool.get_p_association(users,uavs_pos,c_association,len(users)*2)
    sum=0
    g=[]
    for user_index in p_association:
        uavs=[]
        uavs.append(uavs_pos[c_association[user_index]])
        for uav_index in p_association[user_index]:
            uavs.append(uavs_pos[uav_index])
        gdop=GDOP.calculate_gdop(uavs,users[user_index])
        g.append(gdop)
        if gdop>C.G_max/(r_p[user_index]):
            continue
        else:
            sum+=1
    return sum/len(users)
def rate_satisfaction(uavs,users,uav_to_user,p_all,b_all,r_c):
    num=0
    for i in range(len(uavs)):
        for j in uav_to_user[i]:
            p_alloc=p_all[i]
            b_alloc=b_all[i]
            cur_rate = tool.cal_rate(b_alloc[j], p_alloc[j], uavs[i], users[j])
            if round(cur_rate,4)>=C.R_min*r_c[j]:
                num+=1
    return num/len(users)

def cal_satisfaction(uavs,users,p_all,b_all,r_c,r_p, c_association,p_association):
    g=gdop_satisfaction(users,uavs,c_association,p_association,r_p)
    uav_to_user = T.get_uav_to_user(c_association, uavs)
    r=rate_satisfaction(uavs,users,uav_to_user,p_all,b_all,r_c)
    return r,g

def resource_objective(e,uavs_pos,users,r_p,p_all,b_all,c_association,p_association):
    uav_to_user = T.get_uav_to_user(c_association, uavs_pos)
    rate = function_rate(uavs_pos, users, uav_to_user, p_all, b_all)
    r = sum(rate) * 10 ** 6
    gdop = real_gdop(users, uavs_pos, c_association, p_association, r_p)
    return (r - gdop) / e, r / len(rate), gdop / len(users)

def objective_func(pre_uavs,uavs_pos,users,r_c,r_p,*args):
    c_association = T.get_c_association(users, uavs_pos, math.ceil(len(users) / len(uavs_pos)))
    p_association = T.get_p_association(users, uavs_pos, c_association, len(users) * 2 / len(uavs_pos))
    uav_to_user = T.get_uav_to_user(c_association, uavs_pos)
    p_all,b_all,rate= RA.resource_alloc_avg(users, uavs_pos, r_c, p_association, uav_to_user)
    r=sum(rate)
    gdop = function_gdop(users, uavs_pos, c_association, p_association,r_p)
    # e=energy(pre_uavs,uavs_pos)
    # print(e)
    # print(p_all,b_all)
    # print("rate:",rate,r)
    # print("gdop:", gdop)
    return r - sum(gdop),r/len(rate),sum(gdop)/len(users)

def objective_func_optimal(pre_uavs,uavs_pos,users,r_c,r_p,*args):
    c_association = T.get_c_association(users, uavs_pos, math.ceil(len(users) / len(uavs_pos)))
    p_association = T.get_p_association(users, uavs_pos, c_association, len(users) * 2 / len(uavs_pos))
    uav_to_user = T.get_uav_to_user(c_association, uavs_pos)
    p_all,b_all,rate= RA.resource_alloc_u(users, uavs_pos, r_c, p_association, uav_to_user)
    r=sum(rate)
    gdop = function_gdop(users, uavs_pos, c_association, p_association, r_p)
    # e=energy(pre_uavs,uavs_pos)
    # print(p_all, b_all)
    # print("rate:", rate,r)
    # print("gdop:", gdop)
    return r - sum(gdop),r/len(rate),sum(gdop)/len(users)

def get_snr_gdop(uavs_pos,users,r_c,r_p):
    c_association = T.get_c_association(users, uavs_pos, math.ceil(len(users) / len(uavs_pos)))
    p_association = T.get_p_association(users, uavs_pos, c_association, len(users) * 2 / len(uavs_pos))
    uav_to_user = T.get_uav_to_user(c_association, uavs_pos)
    gdop=[]
    for user_index in p_association:
        uavs=[]
        uavs.append(uavs_pos[c_association[user_index]])
        for uav_index in p_association[user_index]:
            uavs.append(uavs_pos[uav_index])
        g=GDOP.calculate_gdop(uavs,users[user_index])
        gdop.append(g)
    p_all, b_all, rate = RA.resource_alloc_avg(users, uavs_pos, r_c, p_association, uav_to_user)
    return rate,gdop
def fixed_w(wmin,wmax,iter,maxgen,index,fitness):
    # return (wmax +wmin)/2
    return 0.5

def linear_w(wmin,wmax,iter,maxgen,index,fitness):
    return wmax - iter * (wmax - wmin) / maxgen

def adapted_w(wmin,wmax,iter,maxgen,index,fitness):
    avg=sum(fitness)/len(fitness)
    if fitness[index]>avg:
        return wmax
    else:
        w=wmin-(wmax-wmin)*(fitness[index]-min(fitness))/(avg-min(fitness))
        return w
def adapted_w2(wmin,wmax,iter,maxgen,index,fitness):
    avg=sum(fitness)/len(fitness)
    if fitness[index]<=avg:
        return wmax
    else:
        w=wmin+(wmax-wmin)*(max(fitness)-fitness[index])/(max(fitness)-avg)
        # w=wmax-(wmax-wmin)*(fitness[index]-min(fitness))/(max(fitness)-min(fitness))#效果不好
        return w
def adapted_w3(wmin,wmax,iter,maxgen,fitness):
    avg = sum(fitness) / len(fitness)

    A=iter*(math.log(wmax)-math.log(wmin))/maxgen-math.log(wmax)
    w=math.exp(-A)
    return w

def dynamic_c1(iter,maxgen):
    return 2*(math.sin(math.pi/2*(1-iter/maxgen)))**2

def dynamic_c2(iter,maxgen):
    return 2*(math.sin(math.pi*iter/2/maxgen))**2

if __name__ == "__main__":
    users = Users.getUsers("./data3.csv")
    r_c = {}
    r_p = {}
    for i in range(len(users)):
        r_c[i] = 2
    r = 1
    for i in range(len(users)):
        r_p[i] = 2
        r += 1
    # uavs = [[868.34535881, 315.18340086, 50.],
    #         [292.96443022, 729.7612657, 77.75450997],
    #         [732.25467955, 927.62861821, 50.],
    #         [303.40107629, 240.31208079, 150.]]
    # uavs=[[973.06680904,364.12885341,52.61221492],
    #  [655.4558372,85.17834171,84.32290174],
    # [920.58870216,343.97478717,69.12057386,]]
    uavs = [[335, 772, 67], [382, 739, 75], [1758, 1683, 137], [885, 762, 133], [403, 1196, 94], [1049, 358, 88]]
    uavs=[[ 937.13598572,1106.32026504 ,50.        ],
 [1638.73822307,576.42231656,50.        ],
 [ 863.950367,1616.3127536,50.        ],
 [ 264.57183106,364.69333235,138.69332619],
 [ 159.74510169,827.61881448,56.27541847],
 [1035.04791004,808.44053304 , 140.02500318]]
    uavs=[[1672.00438436 ,1012.9975498 ,   50.        ],
 [ 434.16986638 ,1432.14203541 ,  50.        ],
 [ 473.55681971 , 325.27416208 ,  71.45922555],
 [1115.79267858, 1464.40107477 ,  50.        ],
 [1833.57784143 , 263.09076035  , 50.        ],
 [1675.2644499 , 1841.36678341  , 50.        ]]
    c_association = T.get_c_association(users, uavs, math.ceil(len(users) / len(uavs)))
    p_association = T.get_p_association(users, uavs, c_association, len(users) * 2 / len(uavs))
    uav_to_user = T.get_uav_to_user(c_association, uavs)
    p_all, b_all, rate = RA.resource_alloc_avg(users, uavs, r_c, p_association, uav_to_user)
    print(objective(uavs,uavs,users,r_c,r_p,p_all,b_all,c_association,p_association))
    # print(objective_func_optimal(uavs,uavs,users,r_c,r_p))
