text: import cv2, time, pydot, sys
  
  import networkx as nx
  from networkx.drawing.nx_pydot import write_dot
  
  import matplotlib.pyplot as plt
  from itertools import permutations
  
  from src.Dijkstra import dijkstra
  from src.Board import Board
  
  graph = {}
  pos = {}
  board = Board()
  G = nx.Graph()
  
  def saveImage():
      # get color
      edges = G.edges()
      colors = [G[u][v]['color'] for u,v in edges]
      widths = [G[u][v]['width'] for u,v in edges]
  
      # draw graph
      #font_color='b'
      nx.draw(G, pos, edges=edges, edge_color=colors, width=widths, with_labels=True)
  
      # save to root dir as png
      plt.savefig("out/Graph.png")
      
      # clear image to prevent overlap
      plt.clf()
  
  # TODO: check deeper cul de sac's and fix them
  # CUrrent implementation only finds them.
  def cul_de_sac(path):
      
      nodes = []
      
      for i in range(len(path)-1):
          for j in range(i+1, len(path)):
              if path[i] == path[j]:
                  nodes.append(path[i])
      
      print("nodes visited more than once:")
      print(nodes)
  
  def drawImage():
      # read image and show
      img = cv2.imread('out/Graph.png', 1)
      cv2.imshow('image', img)
      cv2.waitKey(1)
  
  def closeWindows():
      cv2.destroyAllWindows()
  
  def update():
      saveImage()
      drawImage()
  
  def visualizePath(G, path):
      # make path red
      for i in range(len(path)-1):
          G.add_edge(path[i], path[i+1], color='r', width=4.0)
  
      # draw new path and pause
      update()
      time.sleep(0.5)
  
      # make path normal again
      for i in range(len(path)-1):
          G.add_edge(path[i], path[i+1], color='g', width=2.0)
  
  # bool indicates wether to use nx's dijkstra or src dijkstra.
  def tryPath(homemade, perm):
      
      # paths are all the seperate paths between nodes, eg. Edinburgh -> Sochi, Sochi -> Stockholm
      paths = []
      weight = 0
  
      if homemade:
          # get path between nodes using homemade dijkstra
          for i in range(len(perm)-1):
              print("using homemade")
              paths, weight = dijkstra(graph, perm[i], perm[i+1])
              paths.append(paths)
      else:
          # get path between nodes using nx dijkstra
          for i in range(len(perm)-1):
              paths.append(nx.dijkstra_path(G, perm[i], perm[i+1]))
  
      # unfiy all paths into one path
      path = []
      for i in range(len(paths)):
          if i == 0:
              for node in paths[i]:
                  path.append(node)
                  continue
          if path[-1] == paths[i][0]:
              for node in paths[i][1:]:
                  path.append(node)
                  
      # if using nx dijkstra i need to calculate the weight manualy
      if not homemade:           
          # get weight for path
          for i in range(len(path)-1):
              try:
                  weight += graph[path[i]][path[i+1]]
              except TypeError:
                  exit("Wrong list format on:\n"+ str(path))
  
      return path, weight
  
  def MapAndGoals(sysArgv):
      
      if(sysArgv):
          # Enter map name, then goals, seperated by spaces.
          mapName = sys.argv[1]
          goals = sys.argv[2:]
      else:
          print("Enter map name")
          mapName = input()
          print("Enter goals, seperate with space.")
          goals = input().split(" ")
  
      global graph
      global pos
      
      graph, pos = board.getMap(mapName)
      if not goals or len(goals) == 1:
          exit("Not enough goals.")
  
      return mapName, goals
  
  def main():
      # input method
      sysArgv = True
      mapName, goals = MapAndGoals(sysArgv)
      
      # add nodes, 47 total
      G.add_nodes_from(graph.keys())
  
      # add edges, 180 total
      for node1, edges in graph.items():
          for node2, weight in edges.items():
              if not G.has_edge(node1, node2) or not G.has_edge(node2, node1): # skip duplicates
                  G.add_edge(node1, node2, weight=weight, color='g', width=2.0)
  
      update()
      time.sleep(1)
  
      # permutate goals
      perms = list(permutations(goals))
  
      # get rid of reversed copies
      for i in range(len(perms)-1):
          for j in range(i, len(perms)-1):
              if perms[j] == perms[i][::-1]:
                  perms.pop(j)
  
      # try each permutated path
      routes = []
      for perm in perms:
          path, weight = tryPath(False, perm)
          routes.append([path, weight])
  
      # visualize all the permutated paths, after this the weights are removed from the edges
      for path, weight in routes:
          visualizePath(G, path)
      
      # find shortest permutated path
      lowest = 0
      for i in range(len(routes)):
          if routes[i][1] < routes[lowest][1]:
              lowest = i
  
      path, weight = routes[lowest]
      visualizePath(G, path)
      print(path, weight)
      cul_de_sac(path)
      
      # pause to see image
      time.sleep(4) 
      
      closeWindows()
      exit("Closing...")
      
  if __name__ == '__main__':
      main()
  