Beispiel #1
0
class ExampleTestPlanet(unittest.TestCase):
    def setUp(self):
        """
        Instantiates the planet data structure and fills it with paths

        example planet:

        +--+
        |  |
        +-0,3------+
           |       |
          0,2-----2,2 (target)
           |      /
        +-0,1    /
        |  |    /
        +-0,0-1,0
           |
        (start)

        """

        # set your data structure
        self.planet = Planet()

        # add the paths
        self.planet.add_path(((0, 0), Direction.NORTH),
                             ((0, 1), Direction.SOUTH), 1)
        self.planet.add_path(((0, 1), Direction.WEST),
                             ((0, 0), Direction.WEST), 1)

    def test_target_not_reachable_with_loop(self):
        # does the shortest path algorithm loop infinitely?
        # there is no shortest path
        self.assertIsNone(self.planet.shortest_path((0, 0), (1, 2)))
Beispiel #2
0
class ExampleTestPlanet(unittest.TestCase):
    def setUp(self):
        """
        Instantiates the planet data structure and fills it with paths

        example planet:

        +--+
        |  |
        +-0,3------+
           |       |
          0,2-----2,2 (target)
           |      /
        +-0,1    /
        |  |    /
        +-0,0-1,0
           |
        (start)

        """

        # set your data structure
        self.planet = Planet()

        # add the paths
        self.planet.add_path(((0, 0), Direction.NORTH),
                             ((0, 1), Direction.SOUTH), 1)
        self.planet.add_path(((0, 1), Direction.WEST),
                             ((0, 0), Direction.WEST), 1)
Beispiel #3
0
class ExampleTestPlanet(unittest.TestCase):
    def setUp(self):
        """
        Instantiates the planet data structure and fills it with paths

        +--+
        |  |
        +-0,3------+
           |       |
          0,2-----2,2 (target)
           |      /
        +-0,1    /
        |  |    /
        +-0,0-1,0
           |
        (start)

        """
        # Initialize your data structure here
        self.planet = Planet()
        self.planet.add_path(((0, 0), Direction.NORTH), ((0, 1), Direction.SOUTH), 1)
        self.planet.add_path(((0, 1), Direction.WEST), ((0, 0), Direction.WEST), 1)

    @unittest.skip('Example test, should not count in final test results')
    def test_target_not_reachable_with_loop(self):
        """
        This test should check that the shortest-path algorithm does not get stuck in a loop between two points while
        searching for a target not reachable nearby

        Result: Target is not reachable
        """
        self.assertIsNone(self.planet.shortest_path((0, 0), (1, 2)))
class Communication:
    """
        Class to hold the MQTT client
        Feel free to add functions, change the constructor and the example send_message() to satisfy your requirements and thereby solve the task according to the specifications
    """
    def __init__(self, mqtt_client):
        """ Initializes communication module, connect to server, subscribe, etc. """
        # THESE TWO VARIABLES MUST NOT BE CHANGED
        self.client = mqtt_client
        self.client.on_message = self.on_message
        # ADD YOUR VARIABLES HERE
        # Basic configuration of MQTT
        # Wichtig?
        self.client.on_message = self.on_message_excepthandler

        self.client.username_pw_set('118', password='******') # Your group credentials
        self.client.connect('mothership.inf.tu-dresden.de', port=8883)
        self.client.subscribe('explorer/118', qos=1) # Subscribe to topic explorer/xxx

        # self.send_ready()
        # Start listening to incoming messages
        self.client.loop_start()

        #self.timer()
        self.planet = Planet()



    #Parameter:
        self.data = None
        self.topic = "explorer/118"
        self.planet_Chan = None

        self.aktX = None
        self.aktY = None
        self.direc = None



    # this is a helper method that catches errors and prints them
    # it is necessary because on_message is called by paho-mqtt in a different thread and exceptions
    # are not handled in that thread
    #
    # you don't need to change this method at all
    def on_message_excepthandler(self, client, data, message):
        try:
            self.on_message(client, data, message)
        except:
            import traceback
            traceback.print_exc()
            raise


    # THIS FUNCTIONS SIGNATURE MUST NOT BE CHANGED
    def on_message(self, client, data, message):
        """ Handles the callback if any message arrived """

        print('Got message with topic "{}":'.format(message.topic))
        data = json.loads(message.payload.decode('utf-8'))
        print(json.dumps(data, indent=2))
        print('\n')

        self.data = data

        self.typ_Entsch()
        #self.timer()

    #Timer: jede 2 Sekunden warten:
    def timer(self):
        t0 = time.time()
        while (time.time()-t0) < 2:
            pass
        print("neue Message kommt!")


    def typ_Entsch(self): #Test
        #print("schon in typ_Epntsch")
        von = self.data["from"]
        nach = self.data["type"]

        if von == "server" and nach == "planet":
            payload = self.data["payload"]
            planetName = payload["planetName"]
            self.planet_Chan = 'planet/'+planetName+'-118'
            self.client.subscribe(self.planet_Chan, qos=1)
            self.aktX = payload["startX"]
            self.aktY = payload["startY"]
            print(self.aktX, self.aktY)

        elif von == "server" and nach == "pathSelect":
            self.serverPath()
        elif von == "server" and nach == "path":
            self.set_korrePos()




    def send_ready(self):
        erk = '{"from": "client", "type": "ready"}'
        self.client.publish("explorer/118", erk, qos=1)

    def send_test(self):
        mess = '{"from": "client", "type": "testplanet", "payload": {"planetName":"Hawkeye"}}'
        self.client.publish("explorer/118", mess, qos=1)


    def set_korrePos(self):
        korre_pos = self.data["payload"]
        startX = int(korre_pos["startX"])
        startY = int(korre_pos["startY"])
        startDir = korre_pos["startDirection"]
        endX = int(korre_pos["endX"])
        endY = int(korre_pos["endY"])
        endDir = korre_pos["endDirection"]
        weight = int(korre_pos["pathWeight"])

        self.aktX = endX
        self.aktY = endY
        self.direc = endDir

        self.planet.add_path(((startX, startY), startDir), ((endX, endY), endDir), weight)

        return [(endX, endY), endDir]


    def pruefDaten(self):
        self.pathStat = "free"
        print(self.planet_Chan)
        pruef = '{"from":"client", "type":"path", "payload": {"startX": '+str(13)+', "startY": '+str(37)+', "startDirection": "N", "endX": '+str(13)+', "endY": '+str(38)+', "endDirection": "S", "pathStatus": "'+str(self.pathStat)+'"} }'
        self.client.publish(self.planet_Chan, pruef, qos=1)

    def pruefDaten2(self):
        self.pathStat = "free"
        print(self.planet_Chan)
        pruef = '{"from":"client", "type":"path", "payload": {"startX": '+str(13)+', "startY": '+str(38)+', "startDirection": "N", "endX": '+str(14)+', "endY": '+str(39)+', "endDirection": "W", "pathStatus": "'+str(self.pathStat)+'"} }'
        self.client.publish(self.planet_Chan, pruef, qos=1)

    def pruefDaten3(self):
        self.pathStat = "free"
        print(self.planet_Chan)
        pruef = '{"from":"client", "type":"path", "payload": {"startX": '+str(14)+', "startY": '+str(39)+', "startDirection": "S", "endX": '+str(15)+', "endY": '+str(37)+', "endDirection": "W", "pathStatus": "'+str(self.pathStat)+'"} }'
        self.client.publish(self.planet_Chan, pruef, qos=1)

    def pruefDaten4(self):
        self.pathStat = "free"
        print(self.planet_Chan)
        pruef = '{"from":"client", "type":"path", "payload": {"startX": '+str(15)+', "startY": '+str(37)+', "startDirection": "E", "endX": '+str(17)+', "endY": '+str(37)+', "endDirection": "W", "pathStatus": "'+str(self.pathStat)+'"} }'
        self.client.publish(self.planet_Chan, pruef, qos=1)

    def pruefDaten5(self):
        self.pathStat = "free"
        print(self.planet_Chan)
        pruef = '{"from":"client", "type":"path", "payload": {"startX": '+str(17)+', "startY": '+str(37)+', "startDirection": "N", "endX": '+str(17)+', "endY": '+str(38)+', "endDirection": "W", "pathStatus": "'+str(self.pathStat)+'"} }'
        self.client.publish(self.planet_Chan, pruef, qos=1)

    def pathSelect(self, node):
        result = self.planet.unknown_paths(node)
        startX = result[0][0]
        startY = result[0][1]
        startDir = result[1].value

        self.aktX = startX
        self.aktY = startY
        self.direc = startDir

        select = '{"from":"client", "type":"pathSelect", "payload": {"startX": '+str(startX)+', "startY": '+str(startY)+', "startDirection": "'+str(startDir)+'"} }'

        self.client.publish(self.planet_Chan, select, qos=1)

        return self.direc

    def serverPath(self):
        path_server = self.data["payload"]
        startDir = path_server["startDirection"]

        self.direc = startDir

        return Direction(startDir)
Beispiel #5
0
class Robot:

    def __init__(self, mqtt_client, logger):
        # Create Planet and planet_name variable
        self.planet = Planet()
        self.planet_name = None

        # Setup Sensors, Motors and Odometry
        self.rm = ev3.LargeMotor("outB")
        self.lm = ev3.LargeMotor("outC")
        self.sound = ev3.Sound()
        self.odometry = Odometry(self.lm, self.rm)
        self.motors = Motors(self.odometry)
        self.cs = ColorSensor(self.motors)
        self.us = Ultrasonic()

        # Setup Communication
        self.communication = Communication(mqtt_client, logger, self)

        # Create variable to write to from communication
        self.start_location = None
        self.end_location = None
        self.path_choice = None
        self.running = True

    def run(self):
        counter = 0
        bottle_detected = False
        previous_l, previous_r, previous_b = 0, 0, 350

        start_message = """
##################################
#                                #
#     RoboLab Praktikum 2020     #
#      Exploration by Paula      #
#          ❰❱ with ❤ by          #
#        Eric, Marc, Nico        #
#                                #
##################################
                        """
        # Print start screen
        print(start_message)

        # Calibrate colors for better color accuracy
        self.cs.calibrate_colors()

        # Wait until we want to start
        print("» Press Button to start")
        sensors.button_pressed()
        start_time = time.time()
        print(time.strftime("Starttime: %H:%M:%S", time.localtime()))

        print("Lets start to explore...")

        # Start fancy features
        feature_threads = features.start_features(self)

        # Main robot loop
        while self.running:
            # Test if robot detect an obstacle
            if self.us.get_distance() < 15:
                # Rotate robot to drive back, and save that an obstacle was detected
                self.sound.play("/home/robot/src/assets/found.wav")
                print("Obstacle detected")
                self.cs.rotate_to_path(180)
                bottle_detected = True
                continue

            # Test if robot reached node
            if self.cs.get_node() in ["blue", "red"] and counter == 0:
                counter += 1

                # Drive to center of node to better scanning
                self.motors.drive_in_center_of_node(100, 2)

                # Check if robot reached first node
                if self.planet_name is None:
                    # Tell mothership to send planet information (planet_name and start coordinates)
                    self.communication.send_ready()

                    # Wait until message is received
                    while self.planet_name is None:
                        pass

                    # Reset odometry of last path, not used for first path
                    self.odometry.reset_list()

                    # Current robot orientation
                    forward_dir = self.start_location[1]

                    # End-position and direction of incoming path
                    self.end_location = (self.start_location[0], (forward_dir + 180) % 360)

                    # Save path as blocked for better path calculation
                    self.planet.add_path(self.end_location, self.end_location, -1)
                else:
                    # Test if path is known
                    if self.start_location[0] in self.planet.planet_dict \
                            and self.start_location[1] in self.planet.planet_dict[self.start_location[0]]:
                        # Get end node from planet dictionary
                        ((x, y), send_dir, _) = self.planet.planet_dict[self.start_location[0]][self.start_location[1]]

                        # Reset odometry of last path, not used for first path
                        self.odometry.reset_list()
                    else:
                        # Calculate postion and direction from odometry
                        x, y, forward_dir = self.odometry.calculate_path(
                            self.start_location[1], bottle_detected, self.start_location[0][0], self.start_location[0][1])

                        # Direction facing back, used for path-message
                        send_dir = (forward_dir + 180) % 360

                    # Send path to mothership get real position and direction
                    self.communication.send_path(self.start_location, ((x, y), send_dir), bottle_detected)

                    # Wait until message is received
                    while self.end_location is None:
                        pass

                # Position of current node
                current_pos = self.end_location[0]
                # Direction of robot
                forward_dir = (self.end_location[1] + 180) % 360

                # Test if robot already scanned node
                if current_pos in self.planet.scanned_nodes:
                    # If scanned, wait if mothership sends information like target and pathUnveiled
                    time.sleep(2)
                else:
                    # Scan node for posible directions
                    possible_dirs = self.cs.analyze(forward_dir)

                    # Save direction into unexlored edges if they aren't in the planet dictionary
                    for d in possible_dirs:
                        if current_pos not in self.planet.planet_dict \
                                or d not in self.planet.planet_dict[current_pos].keys():
                            self.planet.add_unexplored_edge(current_pos, d)

                    # Mark node as scanned
                    self.planet.scanned_nodes.append(current_pos)

                # Test if robot reached the target
                if current_pos == self.planet.target:
                    # Send targetReached to mothership
                    self.communication.send_target_reached("Target reached!")

                    # Wait until confirmation
                    while self.running:
                        pass
                    self.sound.play("/home/robot/src/assets/smb_stage_clear.wav")
                    continue

                # Calculate next direction based on planet information and posible directions
                next_dir = self.choose_dir()

                # If no direction is found: Exloration completed
                if next_dir == -1:
                    # Send explorationCompleted to mothership
                    self.communication.send_exploration_completed("Exloration completed!")

                    # Wait until confirmation
                    while self.running:
                        pass
                    self.sound.play("/home/robot/src/assets/metroid.wav")
                    continue

                # Save new starting postion for next path
                self.start_location = (self.end_location[0], next_dir)

                # Rotate to new path
                self.cs.select_new_path(forward_dir, next_dir)

                # Reset variables
                self.end_location = None
                bottle_detected = False
                self.odometry.reset_position()
            else:
                # Follow line and save last data for next tick
                previous_l, previous_r, previous_b = self.motors.follow_line(self.cs, previous_l, previous_r, previous_b)
                # new (better solution?) -> multiple times calles -> ticks_previous needed
                counter = 0

        print(time.strftime("Endtime: %H:%M:%S", time.localtime()))
        delta = (time.time() - start_time) / 60
        print("Timedelta: %.2f min" % delta)

        for thread in feature_threads:
            thread.join()

    def choose_dir(self):
        # Next direction, -1 = no direction found
        choice = -1

        # Test if target is set
        if self.planet.target is not None:
            # Calculate shortest path to target
            shortest = self.planet.shortest_path(self.end_location[0], self.planet.target)

            # Test if target is reachable
            if shortest is not None:
                # Select first direction to get to target
                choice = shortest[0][1]

        # Test if no direction is set (no target or target not reachable)
        if choice == -1:
            # Nodes which need be explored
            incomplete_nodes = []
            # Shortest distance to unexplored node
            distance = math.inf
            # Nearest node
            nearest = None

            # Collect all node, which have open paths
            for node in self.planet.unexplored_edges.keys():
                incomplete_nodes.append(node)

            # Collect all node, which aren't scanned
            for node in self.planet.get_nodes():
                if node not in self.planet.scanned_nodes:
                    incomplete_nodes.append(node)

            # Test if all nodes are explored
            if len(incomplete_nodes) == 0:
                return -1

            # Calculate nearest open node
            for node in incomplete_nodes:
                cur = self.planet.shortest_distance(self.end_location[0], node)
                if cur < distance:
                    distance = cur
                    nearest = node

            # Test if no open node is reachable (explorationCompleted)
            if distance == math.inf:
                return -1
            # Test if open node is reached, choose first open path
            elif distance == 0:
                choice = self.planet.unexplored_edges[nearest][0]
            # Otherwise drive to open node (select first direction to get to open node)
            else:
                choice = self.planet.shortest_next_dir(self.end_location[0], nearest)

        # Send pathSelect to mothership
        self.communication.send_path_select((self.end_location[0], choice))

        # Wait until message receive or 3sec (answer optional)
        start_time = time.time()
        while self.path_choice is None and time.time() - start_time < 3.0:
            pass

        # Test if mothership overwrites direction, use forced direction
        if self.path_choice is not None:
            choice = self.path_choice
        print("Next direction: %s" % Direction(choice))

        # Reset Variable
        self.path_choice = None

        # Play sound
        self.sound.play("/home/robot/src/assets/codecover.wav")

        return choice
Beispiel #6
0
class YourFirstTestPlanet(unittest.TestCase):
    def setUp(self):
        """

        Planet:

            +--+
            |  |
            +-0,3------+
               |       |
              0,2-----2,2 (target)
               |      /
            +-0,1    /
            |  |    /
            +-0,0-1,0
               |
            (start)

        Instantiates the planet data structure and fills it with paths

        MODEL YOUR TEST PLANET HERE (if you'd like):

        """
        # set your data structure
        self.planet = Planet()

        # ADD YOUR PATHS HERE:
        # self.planet.add_path(...)
        '''
        self.planet.add_path(((0, 0), Direction.NORTH), ((0, 1), Direction.SOUTH), 1)
        self.planet.add_path(((0, 0), Direction.WEST), ((0, 1), Direction.WEST), 2)
        self.planet.add_path(((0, 0), Direction.EAST), ((1, 0), Direction.WEST), 1)
        self.planet.add_path(((0, 1), Direction.NORTH), ((0, 2), Direction.SOUTH), 1)
        self.planet.add_path(((0, 2), Direction.NORTH), ((0, 3), Direction.SOUTH), 1)
        self.planet.add_path(((0, 2), Direction.EAST), ((2, 2), Direction.WEST), 2)
        self.planet.add_path(((0, 3), Direction.NORTH), ((0, 3), Direction.WEST), 2)
        self.planet.add_path(((0, 3), Direction.EAST), ((2, 2), Direction.NORTH), 3)
        self.planet.add_path(((1, 0), Direction.NORTH), ((2, 2), Direction.SOUTH), 3)
        '''

    def test_add_paths(self):
        self.planet.add_path(((0, 0), Direction.NORTH),
                             ((0, 1), Direction.SOUTH), 1)
        self.planet.add_path(((0, 0), Direction.WEST),
                             ((0, 1), Direction.WEST), 2)
        self.planet.add_path(((0, 0), Direction.EAST),
                             ((1, 0), Direction.WEST), 1)
        self.planet.add_path(((0, 1), Direction.NORTH),
                             ((0, 2), Direction.SOUTH), 1)
        self.planet.add_path(((0, 2), Direction.NORTH),
                             ((0, 3), Direction.SOUTH), 1)
        self.planet.add_path(((0, 2), Direction.EAST),
                             ((2, 2), Direction.WEST), 2)
        self.planet.add_path(((0, 3), Direction.NORTH),
                             ((0, 3), Direction.WEST), 2)
        self.planet.add_path(((0, 3), Direction.EAST),
                             ((2, 2), Direction.NORTH), 3)
        self.planet.add_path(((1, 0), Direction.NORTH),
                             ((2, 2), Direction.SOUTH), 3)
        pprint.pprint(self.planet.planetKarte)

    def test_get_paths(self):
        self.planet.get_paths()
        pprint.pprint(self.planet.planetPaths)
        """
        print(sorted(self.planet.planetPaths))
        print(list(range(0,10)))

        l = [(1, 5),(2,5),(3,5)]

        for k,v in l:
            print(k, v)

        for s,v, in self.planet.planetPaths.items():
            print("!")
            print(s)
            #print(v)

            for k,v in self.planet.planetPaths.get(s).items():
                print(s, v[0], v[2])
                #print(v)
        """

    def test_integrity(self):
        # were all paths added correctly to the planet
        # check if add_path() works by using get_paths()
        self.assertEqual(
            self.planet.get_paths(), {
                (0, 0): {
                    Direction.NORTH: ((0, 1), Direction.SOUTH, 1),
                    Direction.EAST: ((1, 0), Direction.WEST, 1),
                    Direction.WEST: ((0, 1), Direction.WEST, 2)
                },
                (0, 1): {
                    Direction.NORTH: ((0, 2), Direction.SOUTH, 1),
                    Direction.SOUTH: ((0, 0), Direction.NORTH, 1),
                    Direction.WEST: ((0, 0), Direction.WEST, 2)
                },
                (0, 2): {
                    Direction.NORTH: ((0, 3), Direction.SOUTH, 1),
                    Direction.EAST: ((2, 2), Direction.WEST, 2),
                    Direction.SOUTH: ((0, 1), Direction.NORTH, 1)
                },
                (0, 3): {
                    Direction.NORTH: ((0, 3), Direction.WEST, 2),
                    Direction.EAST: ((2, 2), Direction.NORTH, 3),
                    Direction.SOUTH: ((0, 2), Direction.NORTH, 1),
                    Direction.WEST: ((0, 3), Direction.NORTH, 2)
                },
                (1, 0): {
                    Direction.NORTH: ((2, 2), Direction.SOUTH, 3),
                    Direction.WEST: ((0, 0), Direction.EAST, 1)
                },
                (2, 2): {
                    Direction.NORTH: ((0, 3), Direction.EAST, 3),
                    Direction.SOUTH: ((1, 0), Direction.NORTH, 3),
                    Direction.WEST: ((0, 2), Direction.EAST, 2)
                }
            })

        #self.fail('implement me!')

    def test_empty_planet(self):
        self.assertEqual(self.planet.shortest_path((0, 0), (1, 2)), [])

    def test_target_not_reachable(self):
        self.planet.add_path(((0, 0), Direction.NORTH),
                             ((0, 1), Direction.SOUTH), 1)
        self.planet.add_path(((0, 0), Direction.WEST),
                             ((0, 1), Direction.WEST), 2)
        self.planet.add_path(((0, 0), Direction.EAST),
                             ((1, 0), Direction.WEST), 1)
        self.planet.add_path(((0, 1), Direction.NORTH),
                             ((0, 2), Direction.SOUTH), 1)
        self.planet.add_path(((0, 2), Direction.NORTH),
                             ((0, 3), Direction.SOUTH), 1)
        self.planet.add_path(((0, 2), Direction.EAST),
                             ((2, 2), Direction.WEST), 2)
        self.planet.add_path(((0, 3), Direction.NORTH),
                             ((0, 3), Direction.WEST), 2)
        self.planet.add_path(((0, 3), Direction.EAST),
                             ((2, 2), Direction.NORTH), 3)
        self.planet.add_path(((1, 0), Direction.NORTH),
                             ((2, 2), Direction.SOUTH), 3)
        self.assertEqual(self.planet.shortest_path((0, 0), (1, 2)), [])
        #self.fail('implement me!')

    def test_shortest_path(self):
        # at least 2 possible paths
        self.planet.add_path(((0, 0), Direction.NORTH),
                             ((0, 1), Direction.SOUTH), 1)
        self.planet.add_path(((0, 0), Direction.WEST),
                             ((0, 1), Direction.WEST), 2)
        self.planet.add_path(((0, 0), Direction.EAST),
                             ((1, 0), Direction.WEST), 1)
        self.planet.add_path(((0, 1), Direction.NORTH),
                             ((0, 2), Direction.SOUTH), 2)
        self.planet.add_path(((0, 2), Direction.NORTH),
                             ((0, 3), Direction.SOUTH), 1)
        self.planet.add_path(((0, 2), Direction.EAST),
                             ((2, 2), Direction.WEST), 2)
        self.planet.add_path(((0, 3), Direction.NORTH),
                             ((0, 3), Direction.WEST), 2)
        self.planet.add_path(((0, 3), Direction.EAST),
                             ((2, 2), Direction.NORTH), 3)
        self.planet.add_path(((1, 0), Direction.NORTH),
                             ((2, 2), Direction.SOUTH), 3)
        #self.planet.get_paths()
        self.assertEqual(self.planet.shortest_path((0, 0), (2, 2)),
                         [((0, 0), Direction.EAST), ((1, 0), Direction.NORTH)])

        #print(self.planet.planetPaths.items())
        #self.fail('implement me!')

    def test_same_length(self):
        # at least 2 possible paths with the same weight
        self.planet.add_path(((0, 0), Direction.NORTH),
                             ((0, 1), Direction.SOUTH), 1)
        self.planet.add_path(((0, 0), Direction.WEST),
                             ((0, 1), Direction.WEST), 2)
        self.planet.add_path(((0, 0), Direction.EAST),
                             ((1, 0), Direction.WEST), 1)
        self.planet.add_path(((0, 1), Direction.NORTH),
                             ((0, 2), Direction.SOUTH), 1)
        self.planet.add_path(((0, 2), Direction.NORTH),
                             ((0, 3), Direction.SOUTH), 1)
        self.planet.add_path(((0, 2), Direction.EAST),
                             ((2, 2), Direction.WEST), 2)
        self.planet.add_path(((0, 3), Direction.NORTH),
                             ((0, 3), Direction.WEST), 2)
        self.planet.add_path(((0, 3), Direction.EAST),
                             ((2, 2), Direction.NORTH), 3)
        self.planet.add_path(((1, 0), Direction.NORTH),
                             ((2, 2), Direction.SOUTH), 4)
        self.assertEqual(self.planet.shortest_path((0, 0), (
            2,
            2,
        )), ([((0, 0), 0), ((0, 1), 0), ((0, 2), 90)] or [((0, 0), 90),
                                                          ((1, 0), 0)]))
        #self.fail('implement me!')

    def test_shortest_path_with_loop(self):
        # does the shortest path algorithm loop infinitely?
        # there is a shortest path
        self.planet.add_path(((0, 0), Direction.NORTH),
                             ((0, 1), Direction.SOUTH), 1)
        self.planet.add_path(((0, 0), Direction.WEST),
                             ((0, 1), Direction.WEST), 2)
        self.planet.add_path(((0, 0), Direction.EAST),
                             ((1, 0), Direction.WEST), 1)
        self.planet.add_path(((0, 1), Direction.NORTH),
                             ((0, 2), Direction.SOUTH), 1)
        self.planet.add_path(((0, 2), Direction.NORTH),
                             ((0, 3), Direction.SOUTH), 1)
        self.planet.add_path(((0, 2), Direction.EAST),
                             ((2, 2), Direction.WEST), 5)
        self.planet.add_path(((0, 3), Direction.NORTH),
                             ((0, 3), Direction.WEST), 2)
        self.planet.add_path(((0, 3), Direction.EAST),
                             ((2, 2), Direction.NORTH), 3)
        self.planet.add_path(((1, 0), Direction.NORTH),
                             ((2, 2), Direction.SOUTH), 3)
        self.assertEqual(self.planet.shortest_path((0, 2), (
            2,
            2,
        )), [((0, 2), 0), ((0, 3), 90)])
        #self.fail('implement me!')

    def test_target_not_reachable_with_loop(self):
        #there is no shortest path
        self.planet.add_path(((0, 0), Direction.NORTH),
                             ((0, 1), Direction.SOUTH), 1)
        self.planet.add_path(((0, 1), Direction.EAST),
                             ((1, 1), Direction.WEST), 1)
        self.planet.add_path(((0, 0), Direction.WEST),
                             ((1, 0), Direction.EAST), 1)
        self.planet.add_path(((1, 0), Direction.NORTH),
                             ((1, 1), Direction.SOUTH), 1)
        self.planet.add_path(((0, 0), Direction.NORTH),
                             ((1, 1), Direction.SOUTH), 2)
        self.planet.add_path(((0, 1), Direction.EAST),
                             ((1, 0), Direction.WEST), 2)
        self.planet.add_path(((0, 0), Direction.WEST),
                             ((0, 0), Direction.NORTH), 1)

        self.assertEqual(self.planet.shortest_path((0, 0), (5, 5)), [])
        #self.fail('implement me!')

    def test_target_not_reacheable_blocked(self):
        self.planet.add_path(((0, 0), Direction.NORTH),
                             ((0, 1), Direction.SOUTH), 1)
        self.planet.add_path(((0, 0), Direction.WEST),
                             ((0, 1), Direction.WEST), 2)
        self.planet.add_path(((0, 0), Direction.EAST),
                             ((1, 0), Direction.WEST), 1)
        self.planet.add_path(((0, 1), Direction.NORTH),
                             ((0, 2), Direction.SOUTH), 1)
        self.planet.add_path(((0, 2), Direction.NORTH),
                             ((0, 3), Direction.SOUTH), -1)
        self.planet.add_path(((0, 2), Direction.EAST),
                             ((2, 2), Direction.WEST), 2)
        #self.planet.add_path(((0, 3), Direction.NORTH), ((0, 3), Direction.WEST), 2)
        #self.planet.add_path(((0, 3), Direction.EAST), ((2, 2), Direction.NORTH), 3)
        self.planet.add_path(((1, 0), Direction.NORTH),
                             ((2, 2), Direction.SOUTH), 3)
        self.assertEqual(self.planet.shortest_path((0, 0), (0, 3)), [])

    def test_target_not_reacheable_blocked_with_loop(self):
        self.planet.add_path(((0, 0), Direction.NORTH),
                             ((0, 1), Direction.SOUTH), 1)
        self.planet.add_path(((0, 0), Direction.WEST),
                             ((0, 1), Direction.WEST), 2)
        self.planet.add_path(((0, 0), Direction.EAST),
                             ((1, 0), Direction.WEST), 1)
        self.planet.add_path(((0, 1), Direction.NORTH),
                             ((0, 2), Direction.SOUTH), 1)
        self.planet.add_path(((0, 2), Direction.NORTH),
                             ((0, 3), Direction.SOUTH), -1)
        self.planet.add_path(((0, 2), Direction.EAST),
                             ((2, 2), Direction.WEST), 2)

        self.planet.add_path(((0, 0), Direction.NORTH),
                             ((0, 0), Direction.WEST), 1)
        # self.planet.add_path(((0, 3), Direction.EAST), ((2, 2), Direction.NORTH), 3)
        self.planet.add_path(((1, 0), Direction.NORTH),
                             ((2, 2), Direction.SOUTH), 3)
        self.assertEqual(self.planet.shortest_path((0, 0), (0, 3)), [])
        pass

    def test_shortest_path_with_blocked(self):
        self.planet.add_path(((0, 0), Direction.NORTH),
                             ((0, 1), Direction.SOUTH), 1)
        self.planet.add_path(((0, 0), Direction.WEST),
                             ((0, 1), Direction.WEST), 2)
        self.planet.add_path(((0, 0), Direction.EAST),
                             ((1, 0), Direction.WEST), -1)
        self.planet.add_path(((0, 1), Direction.NORTH),
                             ((0, 2), Direction.SOUTH), -1)
        self.planet.add_path(((0, 2), Direction.NORTH),
                             ((0, 3), Direction.SOUTH), 1)
        self.planet.add_path(((0, 2), Direction.EAST),
                             ((2, 2), Direction.WEST), 2)
        self.planet.add_path(((0, 3), Direction.NORTH),
                             ((0, 3), Direction.WEST), 2)
        self.planet.add_path(((0, 3), Direction.EAST),
                             ((2, 2), Direction.NORTH), 3)
        self.planet.add_path(((1, 0), Direction.NORTH),
                             ((2, 2), Direction.SOUTH), 3)

        pass

    def test_add_path_twice(self):
        # at least 2 possible paths
        self.planet.add_path(((0, 0), Direction.NORTH),
                             ((0, 1), Direction.SOUTH), -1)
        self.planet.add_path(((0, 0), Direction.WEST),
                             ((0, 1), Direction.WEST), 2)

        self.assertEqual(self.planet.planetPaths, self.planet.get_paths())
        # self.planet.get_paths()
        print(self.planet.planetPaths)

    def test_add_path_bidirectional(self):
        self.planet.add_path(((0, 0), Direction.WEST),
                             ((0, 1), Direction.WEST), 2)
        map_test = {
            (0, 0): {
                Direction.WEST: ((0, 1), Direction.WEST, 2)
            },
            (0, 1): {
                Direction.WEST: ((0, 0), Direction.WEST, 2)
            }
        }
        self.assertEqual(self.planet.get_paths(), map_test)
        pass
Beispiel #7
0
class TestRoboLabPlanet(unittest.TestCase):
    def setUp(self):
        """
        Instantiates the planet data structure and fills it with paths

        MODEL YOUR TEST PLANET HERE (if you'd like):

        """

        """
        planet planet:
        
        (0, 2)----4----(2, 2)
          |              |
          1              2
          |              |
        (0, 0)----2----(2, 0)
        """
        self.planet = Planet()

        self.planet.add_path(((0, 0), Direction.EAST), ((2, 0), Direction.WEST), 2)
        self.planet.add_path(((0, 0), Direction.NORTH), ((0, 2), Direction.SOUTH), 1)
        self.planet.add_path(((0, 2), Direction.EAST), ((2, 2), Direction.WEST), 4)
        self.planet.add_path(((2, 2), Direction.SOUTH), ((2, 0), Direction.NORTH), 2)

        """
                planet same:

                                            +--1--+
                (0, 2)---4---(2, 2)         |     |
                   |            |           |     |
                   1            2           +---(3, 2)
                   |            |
                (0, 0)---1---(2, 0)
                   |            |
                   |            |
                   +-----1------+
        """

        self.same = Planet()

        self.same.add_path(((0, 0), Direction.EAST), ((2, 0), Direction.WEST), 1)
        self.same.add_path(((0, 0), Direction.NORTH), ((0, 2), Direction.SOUTH), 1)
        self.same.add_path(((0, 2), Direction.EAST), ((2, 2), Direction.WEST), 4)
        self.same.add_path(((2, 0), Direction.NORTH), ((2, 2), Direction.SOUTH), 2)
        self.same.add_path(((3, 2), Direction.WEST), ((3, 2), Direction.NORTH), 1)
        self.same.add_path(((0, 0), Direction.SOUTH), ((2, 0), Direction.SOUTH), 1)

        """
            planet blocked:
            X = blocked edge
            
        +----(0, 2)------3-------(2, 2)----+
        |       |                  |       |
        |       |             +----+       |
        |       |             |            |
        |       |       +--X--+            |
        1       |       |                  1
        |       X-----(1, 1)---X           |
        |               |      |           |
        +----(0, 0)-----X      +---(2, 0)--+
                |                    |
                +---------2----------+
        """
        self.blocked = Planet()

        self.blocked.add_path(((0, 0), Direction.EAST), ((1, 1), Direction.SOUTH), -1)
        self.blocked.add_path(((0, 0), Direction.SOUTH), ((2, 0), Direction.SOUTH), 2)
        self.blocked.add_path(((0, 0), Direction.WEST), ((0, 2), Direction.WEST), 1)
        self.blocked.add_path(((0, 2), Direction.SOUTH), ((1, 1), Direction.WEST), -1)
        self.blocked.add_path(((0, 2), Direction.EAST), ((2, 2), Direction.WEST), 3)
        self.blocked.add_path(((2, 0), Direction.WEST), ((1, 1), Direction.EAST), -1)
        self.blocked.add_path(((2, 0), Direction.EAST), ((2, 2), Direction.EAST), 1)
        self.blocked.add_path(((2, 2), Direction.SOUTH), ((1, 1), Direction.NORTH), -1)

        """
        planet big:
        X = blocked edge
        
            +-1-+                         +--1-+
            |   |                         |    |
            |   |                         |    |
        (-1, 3)-+                         +--(3, 3)-------1---------+
                                                |                   |
                  +-------1--------+            2                   |
                  |                |            |                   |
            +--(0, 2)-----4-----(2, 2)---+   (3, 2)---2----+        |
            |     |                |     |      |          |        |
            |     |                |     |      1          |        |
            1     1                2     +-2-(3, 1)---3--(4, 1)-----+
            |     |                |                       |
            |     |                |                       |
            +--(0, 0)-----1-----(2, 0)---X---(3, 0)        1
                  |                |                       |
                  +-------1--------+                       |
                                                         (4, -1)
        """

        self.big = Planet()

        self.big.add_path(((0, 0), Direction.EAST), ((2, 0), Direction.WEST), 1)
        self.big.add_path(((0, 0), Direction.NORTH), ((0, 2), Direction.SOUTH), 1)
        self.big.add_path(((0, 0), Direction.WEST), ((0, 2), Direction.WEST), 1)
        self.big.add_path(((0, 2), Direction.EAST), ((2, 2), Direction.WEST), 4)
        self.big.add_path(((0, 2), Direction.NORTH), ((2, 2), Direction.NORTH), 1)
        self.big.add_path(((2, 2), Direction.SOUTH), ((2, 0), Direction.NORTH), 2)
        self.big.add_path(((2, 2), Direction.EAST), ((3, 1), Direction.WEST), 2)
        self.big.add_path(((-1, 3), Direction.EAST), ((-1, 3), Direction.NORTH), 1)
        self.big.add_path(((0, 0), Direction.SOUTH), ((2, 0), Direction.SOUTH), 1)
        self.big.add_path(((2, 0), Direction.EAST), ((3, 0), Direction.WEST), -1)
        self.big.add_path(((3, 1), Direction.NORTH), ((3, 2), Direction.SOUTH), 1)
        self.big.add_path(((3, 1), Direction.EAST), ((4, 1), Direction.WEST), 3)
        self.big.add_path(((3, 2), Direction.EAST), ((4, 1), Direction.NORTH), 2)
        self.big.add_path(((3, 2), Direction.NORTH), ((3, 3), Direction.SOUTH), 2)
        self.big.add_path(((3, 3), Direction.EAST), ((4, 1), Direction.EAST), 1)
        self.big.add_path(((4, 1), Direction.SOUTH), ((4, -1), Direction.NORTH), 1)
        self.big.add_path(((3, 3), Direction.WEST), ((3, 3), Direction.NORTH), 1)

        """
        planet one_path:
        X = blocked edge
                           +---X----(3, 3)-----+
                           |          |        |
                           |          |        |
        (0, 2)-----X-----(2, 2)---1---+        |
          |                |                   |
          |                |                   |
          X                X                   |
          |                |                   |
          |                |                   |
        (0, 0)-----X-----(2, 0)--------4-------+
          |                |
          +--------1-------+
        """

        self.one_path = Planet()

        self.one_path.add_path(((0, 0), Direction.NORTH), ((0, 2), Direction.SOUTH), -1)
        self.one_path.add_path(((0, 0), Direction.EAST), ((2, 0), Direction.WEST), -1)
        self.one_path.add_path(((0, 0), Direction.SOUTH), ((2, 0), Direction.SOUTH), 1)
        self.one_path.add_path(((0, 2), Direction.EAST), ((2, 2), Direction.WEST), -1)
        self.one_path.add_path(((2, 0), Direction.NORTH), ((2, 2), Direction.SOUTH), -1)
        self.one_path.add_path(((2, 0), Direction.EAST), ((3, 3), Direction.EAST), 4)
        self.one_path.add_path(((2, 2), Direction.NORTH), ((3, 3), Direction.WEST), -1)
        self.one_path.add_path(((2, 2), Direction.EAST), ((3, 3), Direction.SOUTH), 1)

        """
        planet loops:
        
        +--1--+               +---1--+
        |     |               |      |
        |     |               |      |
        +---(0, 2)----1-----(2, 2)---+
              |               |
              |               |
              1               1
              |               |
              |               |
        +---(0, 0)----1-----(2, 0)--+
        |     |               |     |
        |     |               |     |
        +--1--+               +--1--+
        """

        self.loops = Planet()

        self.loops.add_path(((0, 0), Direction.WEST), ((0, 0), Direction.SOUTH), 1)
        self.loops.add_path(((0, 0), Direction.NORTH), ((0, 2), Direction.SOUTH), 1)
        self.loops.add_path(((0, 0), Direction.EAST), ((2, 0), Direction.WEST), 1)
        self.loops.add_path(((0, 2), Direction.WEST), ((0, 2), Direction.NORTH), 1)
        self.loops.add_path(((0, 2), Direction.EAST), ((2, 2), Direction.WEST), 1)
        self.loops.add_path(((2, 0), Direction.SOUTH), ((2, 0), Direction.EAST), 1)
        self.loops.add_path(((2, 0), Direction.NORTH), ((2, 2), Direction.SOUTH), 1)
        self.loops.add_path(((2, 2), Direction.NORTH), ((2, 2), Direction.EAST), 1)

        self.empty = Planet()

    def test_integrity(self):
        """
        This test should check that the dictionary returned by "planet.get_paths()" matches the expected structure
        """

        b = self.planet.get_paths()
        self.assertEqual({(0, 0): {Direction.EAST: ((2, 0), Direction.WEST, 2),
                                   Direction.NORTH: ((0, 2), Direction.SOUTH, 1)},
                          (2, 0): {Direction.WEST: ((0, 0), Direction.EAST, 2),
                                   Direction.NORTH: ((2, 2), Direction.SOUTH, 2)},
                          (0, 2): {Direction.SOUTH: ((0, 0), Direction.NORTH, 1),
                                   Direction.EAST: ((2, 2), Direction.WEST, 4)},
                          (2, 2): {Direction.WEST: ((0, 2), Direction.EAST, 4),
                                   Direction.SOUTH: ((2, 0), Direction.NORTH, 2)}}, b)

    def test_empty_planet(self):
        """
        This test should check that an empty planet really is empty
        """

        empty_planet = self.empty.planet_dict

        self.assertFalse(empty_planet)

    def test_target(self):
        """
        This test should check that the shortest-path algorithm implemented works.

        Requirement: Minimum distance is three nodes (two paths in list returned)
        """

        path_1 = self.planet.shortest_path((0, 0), (2, 2))
        path_2 = self.big.shortest_path((3, 2), (2, 0))
        path_3 = self.blocked.shortest_path((2, 0), (0, 2))

        self.assertEqual([((0, 0), Direction.EAST), ((2, 0), Direction.NORTH)], path_1)
        self.assertEqual([((3, 2), Direction.SOUTH), ((3, 1), Direction.WEST), ((2, 2), Direction.SOUTH)], path_2)
        self.assertEqual([((2, 0), Direction.SOUTH), ((0, 0), Direction.WEST)], path_3)

    def test_target_not_reachable(self):
        """
        This test should check that a target outside the map or at an unexplored node is not reachable
        """
        # (3, 3) is not in the map and is therefore currently unexplored/unreachable.
        path_1 = self.planet.shortest_path((0, 0), (3, 3))

        # (-1, -1) is not in the map and is therefore currently unexplored/unreachable.
        path_2 = self.planet.shortest_path((0, 0), (-1, -1))

        self.assertIsNone(path_1)
        self.assertIsNone(path_2)

    def test_same_length(self):
        """
        This test should check that the shortest-path algorithm implemented also can return alternative routes with the
        same cost (weight) to a specific target

        Requirement: Minimum of two paths with same cost exists, only one is returned by the logic implemented
        """

        shortest_same_1 = self.same.shortest_path((0, 0), (2, 2))
        my_list_of_paths_1 = []
        my_list_of_paths_1.append(shortest_same_1)

        shortest_same_2 = self.big.shortest_path((0, 0), (4, -1))
        my_list_of_paths_2 = []
        my_list_of_paths_2.append(shortest_same_2)

        shortest_same_3 = self.loops.shortest_path((0, 0), (2, 2))
        my_list_of_paths_3 = []
        my_list_of_paths_3.append(shortest_same_3)

        self.assertEqual(len(shortest_same_1), 2)
        self.assertEqual(len(my_list_of_paths_1), 1)
        self.assertEqual([((0, 0), Direction.EAST), ((2, 0), Direction.NORTH)], shortest_same_1)

        self.assertEqual(len(shortest_same_2), 5)
        self.assertEqual(len(my_list_of_paths_2), 1)
        self.assertEqual([((0, 0), Direction.NORTH), ((0, 2), Direction.NORTH),
                          ((2, 2), Direction.EAST), ((3, 1), Direction.EAST), ((4, 1), Direction.SOUTH)], shortest_same_2)

        self.assertEqual(len(shortest_same_3), 2)
        self.assertEqual(len(my_list_of_paths_3), 1)
        self.assertEqual([((0, 0), Direction.EAST), ((2, 0), Direction.NORTH)], shortest_same_3)

    def test_target_with_loop(self):
        """
        This test should check that the shortest-path algorithm does not get stuck in a loop between two points while
        searching for a target nearby

        Result: Target is reachable
        """

        shortest_1 = self.same.shortest_path((0, 0), (2, 2))
        shortest_2 = self.big.shortest_path((0, 0), (4, -1))
        shortest_3 = self.loops.shortest_path((0, 0), (2, 2))

        self.assertIsNotNone(shortest_1)
        self.assertIsNotNone(shortest_2)
        self.assertIsNotNone(shortest_3)

    def test_target_not_reachable_with_loop(self):
        """
        This test should check that the shortest-path algorithm does not get stuck in a loop between two points while
        searching for a target not reachable nearby

        Result: Target is not reachable
        """

        # (-1, 3) is located in the map but cannot be reached.
        path_1 = self.big.shortest_path((0, 0), (-1, 3))

        # (3, 2) is located in the map but cannot be reached.
        path_2 = self.same.shortest_path((0, 0), (3, 2))

        self.assertIsNone(path_1)
        self.assertIsNone(path_2)

    def test_target_reached(self):
        """
        This test checks that the shortest-path algorithm recognizes when the robot has reached the target.

        Result: Target reached
        """

        path = self.blocked.shortest_path((0, 0), (0, 0))
        self.assertFalse(path)

    def test_target_blocked(self):
        """
        This test checks that the shortest-path algorithm will not return a shortest path or get caught in a loop when
        the target is only connected to blocked edges.

        Result: Target is unreachable
        """

        path_1 = self.big.shortest_path((0, 0), (3, 0))
        path_2 = self.blocked.shortest_path((0, 0), (1, 1))

        self.assertIsNone(path_1)
        self.assertIsNone(path_2)

    def test_start_blocked(self):
        """
        This test checks that the shortest-path algorithm will not return a shortest path or get caught in a loop when
        the start node is only connected to blocked edges.

        Result: Target is unreachable
        """

        path_1 = self.big.shortest_path((3, 0), (0, 0))
        path_2 = self.blocked.shortest_path((1, 1), (0, 0))

        self.assertIsNone(path_1)
        self.assertIsNone(path_2)

    def avoid_blocked(self):
        """
        This test checks that the shortest-path algorithm avoids blocked edges when searching for a shortest path.

        Result: Only one path without blocked edges exists, and that is the path that is returned.
        """

        path = self.one_path.shortest_path((0, 0), (2, 2))

        self.assertEqual([((0, 0), Direction.SOUTH), ((2, 0), Direction.EAST), ((3, 3), Direction.SOUTH)], path)
class YourFirstTestPlanet(unittest.TestCase):
    def setUp(self):
        """
        Instantiates the planet data structure and fills it with paths

        MODEL YOUR TEST PLANET HERE (if you'd like):

        """
        # set your data structure
        self.planet = Planet()

        # ADD YOUR PATHS HERE:
        self.planet.add_path(((0, 0), Direction.NORTH),
                             ((0, 1), Direction.SOUTH))
        self.planet.add_path(((0, 0), Direction.EAST),
                             ((0, 1), Direction.EAST))
        self.planet.add_path(((0, 1), Direction.NORTH),
                             ((1, 2), Direction.WEST))
        self.planet.add_path(((1, 2), Direction.SOUTH),
                             ((1, 1), Direction.NORTH))
        self.planet.add_path(((1, 1), Direction.EAST),
                             ((2, 1), Direction.WEST))
        self.planet.add_path(((1, 1), Direction.SOUTH),
                             ((2, 0), Direction.WEST))
        self.planet.add_path(((2, 1), Direction.NORTH),
                             ((2, 2), Direction.SOUTH))
        self.planet.add_path(((2, 2), Direction.NORTH),
                             ((2, 2), Direction.WEST))
        self.planet.add_path(((2, 0), Direction.NORTH),
                             ((2, 1), Direction.SOUTH))
        self.planet.add_path(((2, 0), Direction.EAST),
                             ((4, 0), Direction.WEST))
        self.planet.add_path(((4, 0), Direction.NORTH),
                             ((4, 1), Direction.SOUTH))
        self.planet.add_path(((4, 0), Direction.EAST),
                             ((4, 1), Direction.EAST))

        # todo: implement hulk as tesplanet for testing stuff.

    def test_integrity(self):
        # were all paths added correctly to the planet
        # check if add_path() works by using get_paths()
        self.fail('implement me!')

    def test_empty_planet(self):
        self.fail('implement me!')

    def test_target_not_reachable(self):
        self.fail('implement me!')

    def test_shortest_path(self):
        # at least 2 possible paths
        # self.assertEqual()
        # self.failUnlessEqual
        self.fail('implement me!')

    def test_same_length(self):
        # at least 2 possible paths with the same weight
        self.fail('implement me!')

    def test_shortest_path_with_loop(self):
        # does the shortest path algorithm loop infinitely?
        # there is a shortest path
        self.fail('implement me!')

    def test_target_not_reachable_with_loop(self):
        # there is no shortest path
        self.fail('implement me!')
class TestHulk(unittest.TestCase):
    def setUp(self):
        """
        Instantiates the planet data structure and fills it with paths

        MODEL YOUR TEST PLANET HERE (if you'd like):

        """
        # set your data structure
        self.planet = Planet()
        self.planet.add_path(((13, 37), Direction.NORTH),
                             ((13, 38), Direction.SOUTH), 1)
        self.planet.add_path(((13, 38), Direction.NORTH),
                             ((14, 39), Direction.WEST), 1)
        self.planet.add_path(((14, 39), Direction.SOUTH),
                             ((14, 38), Direction.NORTH), 1)
        self.planet.add_path(((14, 38), Direction.SOUTH),
                             ((15, 37), Direction.WEST), 1)
        self.planet.add_path(((15, 37), Direction.NORTH),
                             ((15, 38), Direction.SOUTH), 1)
        self.planet.add_path(((15, 38), Direction.WEST),
                             ((14, 38), Direction.EAST), 1)
        self.planet.add_path(((17, 37), Direction.SOUTH),
                             ((17, 37), Direction.EAST), -1)
        print(self.planet.shortest_path((14, 38), (17, 37)))

    def test_shortest_path(self):
        print()