def add_tank_get_score(num_junctions, avg_initial_pressure_at_each_junc):
    global tank_elev_array
    network = Network(inp_file)

    junc_elev_array = []
    junc_x_y_array = []
    junc_id_array = []

    score_array = []

    # this loop add a tank to Node 1, calculate the peak-demand average pressure, stores it, and deletes the tank
    # it then adds a tank to Node 2 and repeats until all nodal locations are scored

    for junction in range(num_junctions):
        junc_elev_array.append(network.ep.ENgetnodevalue(junction + 1, 0))
        junc_x_y_array.append(network.ep.ENgetcoord(junction + 1))
        junc_id_array.append(network.ep.ENgetnodeid(junction + 1))

        optimum_elevation = junc_elev_array[
            junction] + avg_initial_pressure_at_each_junc[junction]

        tank_elev_array.append(optimum_elevation)

        network.add_tank(uid='balancing_tank',
                         x=junc_x_y_array[junction][0],
                         y=junc_x_y_array[junction][1],
                         elevation=optimum_elevation,
                         diameter=100,
                         maxlevel=1000,
                         minlevel=0,
                         tanklevel=0)

        network.add_pipe(uid='balancing_tank_pipe',
                         from_node=junc_id_array[junction],
                         to_node='balancing_tank',
                         diameter=1000,
                         length=10,
                         roughness=1E9,
                         check_valve=False)

        network.save_inputfile(inp_file)

        junction_score = score_pressure_array(
            solve_and_return_pressures(num_junctions))

        score_array.append(junction_score)
        print("Junction index ", score_index_counter, " : ", junction_score)

        network.delete_link('balancing_tank_pipe')
        network.delete_node('balancing_tank')
        network.reset()

        network.save_inputfile(inp_file)

    return score_array
class NetworkAgent:

    def __init__(self, filename='anytown_master.inp'): 

        # load network
        self.network = Network(filename)
        self.network.solve()

        # for control
        self.speed_limit = (0.7, 1.2)

        # danger zone 
        self.junction_threshold = (15, 120)
        self.state = None

        # function to get the effeciency of the pump(s) 
        self.eff = None

        # speed increase/decrease resolution 
        self.stepsize = 0.1
        self.network.solve()
        self._calc_effeciency('E1')


    def _calc_effeciency(self, curve_id):
        curve = None
        for x in self.network.curves:
            if curve_id in x.uid:
                flow = [ value[0] for value  in x.values] 
                y = [value[1] for value in  x.values]
                curve = np.poly1d(np.polyfit(flow,y,4))
        if not curve:
            logging.info('no curve found with id{}'.format(curve_id))
        self.eff = curve



    def reset(self):
        # epynet has its own reset function
        # self._calc_effeciency('E1')
        #optimize  
        from scipy.optimize import minimize
        # initial guess is 0.8 thats the speed
        self.res = minimize(self.find_opt,1.2, method='Nelder-Mead', options={'disp':True}, bounds = self.speed_limit)
        print(self.res.x)
        self.network.reset()

    def find_opt(self, x):
        """
        x : pump's speed
        returns: effeciency
        """
        # change speed 
        self.network.pumps['78'].speed = x 
        self.network.solve()
        eff = self.calc_eff()
        # - sign because we need the maximum value 
        return - eff


    def step(self):
        x = self.network.solve()
        print('solve function returns: {}'.format(x))

    
    def calc_eff(self):

        # get only one pump with id 78
        # complicated networks will be harder than this
        flow  = self.network.pumps['78'].flow
        print('flow is: {}'.format(flow))

        speed = self.network.pumps['78'].speed

        true_flow = float(flow/speed)

        return self.eff(true_flow)


    def junction_head(self):
        return list(self.network.junctions.head)


    def junction_demand(self):
        return list(self.network.junctions.demand)


    def junction_pressure(self):
        return list(self.network.junctions.pressure)


    def _action_increase_speed(self):
        # check if it's within the limits
        if self.network.pumps['78'].speed + self.stepsize > self.speed_limit[1]:
            return
        self.network.pumps['78'].speed += self.stepsize


    def _action_decrease_speed(self):
        if self.network.pumps['78'].speed - self.stepsize < self.speed_limit[1]:
            return
        self.network.pumps['78'].speed -= self.stepsize