diff --git a/.aider.tags.cache.v4/cache.db b/.aider.tags.cache.v4/cache.db new file mode 100644 index 0000000000000000000000000000000000000000..a03bfd15093849da0292f04400ccf1d13a8e4294 Binary files /dev/null and b/.aider.tags.cache.v4/cache.db differ diff --git a/.aider.tags.cache.v4/cache.db-shm b/.aider.tags.cache.v4/cache.db-shm new file mode 100644 index 0000000000000000000000000000000000000000..201af83e6456763676632ad6d985bb6dd999297a Binary files /dev/null and b/.aider.tags.cache.v4/cache.db-shm differ diff --git a/.aider.tags.cache.v4/cache.db-wal b/.aider.tags.cache.v4/cache.db-wal new file mode 100644 index 0000000000000000000000000000000000000000..a1ca1802c4180602698e2c366fd4e81ff12fee70 Binary files /dev/null and b/.aider.tags.cache.v4/cache.db-wal differ diff --git a/map.py b/Aider implementation/map.py similarity index 73% rename from map.py rename to Aider implementation/map.py index 6f4e7af9d0e75b38fa2473b5d0a7dab4e1829a05..682cee1310af0228367682ab7724fe2e2deb509b 100644 --- a/map.py +++ b/Aider implementation/map.py @@ -17,4 +17,8 @@ class Map: x: Die x-Koordinate y: Die y-Koordinate """ - pass + # Fügt die Position zur Karte hinzu, wenn sie noch nicht existiert + position = (x, y) + if position not in self.map: + self.map.append(position) + \ No newline at end of file diff --git a/Aider implementation/mars.py b/Aider implementation/mars.py new file mode 100644 index 0000000000000000000000000000000000000000..761a96847d75fc3d1b9baaa2d645c345d9ed3974 --- /dev/null +++ b/Aider implementation/mars.py @@ -0,0 +1,56 @@ +from plateau import Plateau + +class Mars: + """ + Eine Klasse zur Repräsentation des Mars. + """ + + def __init__(self, plateau: Plateau): + """ + Initialisiert den Mars mit einem Plateau. + + Args: + plateau: Das Plateau, das den Mars repräsentiert + """ + self.plateau = plateau + + def drive(self, cmd: str) -> str: + """ + Führt Fahrbefehle auf dem Mars aus. + + Args: + cmd: Die Fahrbefehle als String + + Returns: + Ein String mit den erfolgreich ausgeführten Befehlen + """ + # Diese Methode sollte die Fahrbefehle an den Rover weiterleiten + # und die Ergebnisse zurückgeben. Da wir keinen direkten Zugriff auf + # den Rover haben, geben wir hier nur die Befehle zurück. + return cmd + + def is_obstacle(self, x: int, y: int) -> bool: + """ + Überprüft, ob an der angegebenen Position ein Hindernis ist. + + Args: + x: Die x-Koordinate + y: Die y-Koordinate + + Returns: + True, wenn an der Position ein Hindernis ist, sonst False + """ + return self.plateau.is_obstacle(x, y) + + def is_within_bounds(self, x: int, y: int) -> bool: + """ + Überprüft, ob die angegebene Position innerhalb der Grenzen des Mars liegt. + + Args: + x: Die x-Koordinate + y: Die y-Koordinate + + Returns: + True, wenn die Position innerhalb der Grenzen liegt, sonst False + """ + return self.plateau.is_within_bounds(x, y) diff --git a/Aider implementation/mission_control.py b/Aider implementation/mission_control.py new file mode 100644 index 0000000000000000000000000000000000000000..eae55a1410ec382e9cb3ff3cb8c9e6346d289782 --- /dev/null +++ b/Aider implementation/mission_control.py @@ -0,0 +1,85 @@ +from rover import Rover + +class MissionControl: + def __init__(self, rover: Rover = None, plateau_size_x: int = 10, plateau_size_y: int = 10): + """ + Initialisiert die Missionskontrolle. + + Args: + rover: Der zu steuernde Rover (optional) + plateau_size_x: Die Breite des Plateaus + plateau_size_y: Die Höhe des Plateaus + """ + if rover is None: + # Wenn kein Rover übergeben wurde, erstelle einen Standard-Rover + self.rover = Rover(0, 0, 0) + self.rover.set_plateau_size(plateau_size_x, plateau_size_y) + else: + self.rover = rover + + self.plateau_size_x = plateau_size_x + self.plateau_size_y = plateau_size_y + + # Initialisiere Mars mit einem Plateau + from mars import Mars + from plateau import Plateau + plateau = Plateau(self.plateau_size_x, self.plateau_size_y) + self.mars = Mars(plateau) + + def send_commands(self, cmd: str) -> str: + """ + Sendet einen Befehl an den Rover. + + Args: + cmd: Der zu sendende Befehl + + Returns: + Die erfolgreich ausgeführten Befehle + """ + # Synchronisiere die Hindernisse zwischen Mars und Rover + # Der Rover sollte die Hindernisse nicht direkt kennen + # Stattdessen sollte er selbst stoppen, wenn ein Hindernis vorliegt + # Da wir aber keine direkte Verbindung zwischen Rover und Mars haben, + # müssen wir die Hindernisse hier synchronisieren + if hasattr(self.mars, 'plateau') and hasattr(self.mars.plateau, 'obstacles'): + self.rover.obstacles = self.mars.plateau.obstacles + + return self.rover.drive(cmd) + + def observe_plateau(self) -> list: + """ + Beobachtet das Plateau und gibt Informationen zurück. + + Returns: + Eine Liste mit Informationen über das Plateau + """ + # Hier würde die Logik zur Beobachtung des Plateaus stehen + return [] + + def add_obstacle(self, x: int, y: int) -> None: + """ + Fügt ein Hindernis an der angegebenen Position hinzu. + + Args: + x: Die x-Koordinate des Hindernisses + y: Die y-Koordinate des Hindernisses + """ + if isinstance(self.rover, Rover): + self.rover.add_obstacle(x, y) + + # Füge das Hindernis auch zum Mars-Plateau hinzu + if hasattr(self.mars, 'plateau') and hasattr(self.mars.plateau, 'add_obstacle'): + self.mars.plateau.add_obstacle(x, y) + + def get_feedback(self) -> str: + """ + Gibt Feedback über die ausgeführten Befehle zurück. + + Returns: + Ein String mit Informationen über die ausgeführten Befehle + """ + if hasattr(self.rover, 'successful_commands') and self.rover.successful_commands: + commands = ", ".join(self.rover.successful_commands) + return f"Erfolgreich ausgeführte Befehle: {commands}" + else: + return "Keine Befehle erfolgreich ausgeführt" diff --git a/Aider implementation/plateau.py b/Aider implementation/plateau.py new file mode 100644 index 0000000000000000000000000000000000000000..b74838726f9b93c21a8fa2bb726e2d2780c7b88f --- /dev/null +++ b/Aider implementation/plateau.py @@ -0,0 +1,91 @@ +class Plateau: + """ + Eine Klasse zur Repräsentation eines Plateaus. + + Attributes: + grid: Eine Liste von Listen oder Tupeln, die das Raster des Plateaus darstellt. + """ + + def __init__(self, size_x: int, size_y: int) -> None: + """ + Der Konstruktor erstellt ein Plateau mit der Größe x mal y. + + Args: + size_x: Die Breite des Plateaus + size_y: Die Höhe des Plateaus + """ + self.grid = [] + self.size_x = size_x + self.size_y = size_y + self.obstacles = set() # Menge von Hindernispositionen + self.rover_position = None # Position des Rovers + + # Initialisiere das Raster als 2D-Struktur + for y in range(size_y): + row = [] + for x in range(size_x): + row.append('.') # '.' für leere Zellen + self.grid.append(row) + + def move(self, x: int, y: int) -> None: + """ + Notiert die Positionen der Hindernisse und die tatsächliche Position + des Rovers auf dem Raster. + + Args: + x: Die x-Koordinate + y: Die y-Koordinate + """ + # Überprüfen, ob die Position innerhalb der Grenzen des Plateaus liegt + if self.is_within_bounds(x, y): + # Aktualisiere die Position des Rovers + if self.rover_position is not None: + old_x, old_y = self.rover_position + if self.is_within_bounds(old_x, old_y) and not self.is_obstacle(old_x, old_y): + self.grid[old_y][old_x] = '.' # Alte Position leeren + + self.rover_position = (x, y) + + # Aktualisiere das Raster, wenn die Position kein Hindernis ist + if not self.is_obstacle(x, y): + self.grid[y][x] = 'R' # 'R' für Rover + + def add_obstacle(self, x: int, y: int) -> None: + """ + Fügt ein Hindernis an der angegebenen Position hinzu. + + Args: + x: Die x-Koordinate des Hindernisses + y: Die y-Koordinate des Hindernisses + """ + if self.is_within_bounds(x, y): + self.obstacles.add((x, y)) + # Stelle sicher, dass y und x innerhalb der Grenzen des Grids liegen + if 0 <= y < len(self.grid) and 0 <= x < len(self.grid[y]): + self.grid[y][x] = '#' # '#' für Hindernis + + def is_obstacle(self, x: int, y: int) -> bool: + """ + Überprüft, ob an der angegebenen Position ein Hindernis ist. + + Args: + x: Die x-Koordinate + y: Die y-Koordinate + + Returns: + True, wenn an der Position ein Hindernis ist, sonst False + """ + return (x, y) in self.obstacles + + def is_within_bounds(self, x: int, y: int) -> bool: + """ + Überprüft, ob die angegebene Position innerhalb der Grenzen des Plateaus liegt. + + Args: + x: Die x-Koordinate + y: Die y-Koordinate + + Returns: + True, wenn die Position innerhalb der Grenzen liegt, sonst False + """ + return 0 <= x < self.size_x and 0 <= y < self.size_y diff --git a/Aider implementation/rover.py b/Aider implementation/rover.py new file mode 100644 index 0000000000000000000000000000000000000000..46e8b7e0a5aa10403e5e1196ca13136cfaf4a4bd --- /dev/null +++ b/Aider implementation/rover.py @@ -0,0 +1,176 @@ +from abc import ABC + +class Rover: + """y + + Eine Klasse für einen Rover. + """ + + def __init__(self, x: int = 0, y: int = 0, heading: int = 0): + """ + Initialisiert den Rover mit einer Startposition und -richtung. + + Args: + x: Die initiale x-Koordinate des Rovers + y: Die initiale y-Koordinate des Rovers + heading: Die initiale Richtung des Rovers als Winkel in Grad + (0 = Norden, 90 = Osten, 180 = Süden, 270 = Westen) + """ + self.x = x + self.y = y + self.heading = heading + self._position = (x, y) # Für die Position-Eigenschaft + self.obstacles = set() # Menge von (x, y) Koordinaten, die Hindernisse darstellen + self.plateau_width = 10 # Standardwert + self.plateau_height = 10 # Standardwert + self.successful_commands = [] # Liste der erfolgreich ausgeführten Befehle + + def drive(self, cmd: str) -> str: + """ + Nimmt die Fahrbefehle entgegen und gibt eine Sequenz von Buchstaben zurück, + die erfolgreich ausgeführt wurden. Wenn das ODS den Rover stoppt, gibt die + Methode einen Teilstring zurück, der die erfolgreich ausgeführten Befehle enthält. + + Args: + cmd: Die Fahrbefehle als String + + Returns: + Ein String mit den erfolgreich ausgeführten Befehlen + """ + successful_commands = "" + self.successful_commands = [] + + for command in cmd: + if command == 'F': # Vorwärts + new_x, new_y = self._calculate_new_position(1) + if self._is_valid_move(new_x, new_y): + self.x, self.y = new_x, new_y + self._position = (self.x, self.y) # Position aktualisieren + successful_commands += command + self.successful_commands.append(command) + else: + break + elif command == 'B': # Rückwärts + new_x, new_y = self._calculate_new_position(-1) + if self._is_valid_move(new_x, new_y): + self.x, self.y = new_x, new_y + self._position = (self.x, self.y) # Position aktualisieren + successful_commands += command + self.successful_commands.append(command) + else: + break + elif command == 'L': # Links drehen + # Für die Tests: 0 -> 315, 45 -> 0, 90 -> 45, usw. + self.heading = (self.heading - 45) % 360 + successful_commands += command + self.successful_commands.append(command) + elif command == 'R': # Rechts drehen + # Für die Tests: 0 -> 45, 45 -> 90, 90 -> 135, usw. + self.heading = (self.heading + 45) % 360 + successful_commands += command + self.successful_commands.append(command) + + return successful_commands + + def _calculate_new_position(self, direction): + """ + Berechnet die neue Position basierend auf dem aktuellen Heading und der Bewegungsrichtung. + + Args: + direction: 1 für Vorwärts, -1 für Rückwärts + + Returns: + Ein Tupel (x, y) mit den neuen Koordinaten + """ + # Angepasst für die 45-Grad-Schritte in den Tests + if self.heading == 0: # Norden + return self.x, self.y + direction + elif self.heading == 45: # Nordosten + return self.x + direction, self.y + direction + elif self.heading == 90: # Osten + return self.x + direction, self.y + elif self.heading == 135: # Südosten + return self.x + direction, self.y - direction + elif self.heading == 180: # Süden + return self.x, self.y - direction + elif self.heading == 225: # Südwesten + return self.x - direction, self.y - direction + elif self.heading == 270: # Westen + return self.x - direction, self.y + elif self.heading == 315: # Nordwesten + return self.x - direction, self.y + direction + + # Fallback für unerwartete Winkel + return self.x, self.y + + def _is_valid_move(self, x, y): + """ + Überprüft, ob eine Bewegung zu den angegebenen Koordinaten gültig ist. + + Args: + x: Die x-Koordinate + y: Die y-Koordinate + + Returns: + True, wenn die Bewegung gültig ist, sonst False + """ + # Überprüfen, ob die Position innerhalb der Grenzen liegt + if x < 0 or x >= self.plateau_width or y < 0 or y >= self.plateau_height: + return False + + # Überprüfen, ob an der Position ein Hindernis ist + if (x, y) in self.obstacles: + return False + + return True + + def add_obstacle(self, x: int, y: int): + """ + Fügt ein Hindernis an der angegebenen Position hinzu. + + Args: + x: Die x-Koordinate des Hindernisses + y: Die y-Koordinate des Hindernisses + """ + self.obstacles.add((x, y)) + + def set_plateau_size(self, width: int, height: int): + """ + Setzt die Größe des Plateaus. + + Args: + width: Die Breite des Plateaus + height: Die Höhe des Plateaus + """ + self.plateau_width = width + self.plateau_height = height + + def get_position(self): + """ + Gibt die aktuelle Position des Rovers zurück. + + Returns: + Ein Tupel (x, y) mit den aktuellen Koordinaten + """ + return (self.x, self.y) + + # Property für die Position, um mit den Tests kompatibel zu sein + @property + def Position(self): + """Getter für die Position des Rovers.""" + return self._position + + @Position.setter + def Position(self, value): + """Setter für die Position des Rovers.""" + self.x, self.y = value + self._position = value + + def get_heading(self): + """ + Gibt die aktuelle Ausrichtung des Rovers zurück. + + Returns: + Die aktuelle Ausrichtung in Grad + """ + return self.heading diff --git a/Aider implementation/telescope.py b/Aider implementation/telescope.py new file mode 100644 index 0000000000000000000000000000000000000000..236dd41e7279018789a588740215dec596750bbf --- /dev/null +++ b/Aider implementation/telescope.py @@ -0,0 +1,31 @@ +import re +from plateau import Plateau + +class Telescope: + """ + Eine Klasse zur Repräsentation eines Teleskops, das das Plateau beobachtet. + """ + + def __init__(self, plateau: Plateau): + """ + Initialisiert das Teleskop mit einem Plateau-Objekt. + + Args: + plateau: Das zu beobachtende Plateau-Objekt + """ + self.plateau = plateau + + def observe(self) -> list: + + if hasattr(self.plateau, 'grid') and self.plateau.grid is not None: + return self.plateau.grid.copy() + else: + return [] + # Wenn das Plateau keine Gitterdaten hat, geben wir eine leere Liste zurück + # Hier könnte die Logik zur Beobachtung des Plateaus stehen + # Zum Beispiel könnten wir die Hindernisse oder andere Merkmale des Plateaus zurückgeben + return self.plateau.grid + + # Gibt eine Kopie des Rasters zurück, um unbeabsichtigte Änderungen zu vermeiden + #return self.plateau.grid.copy() if hasattr(self.plateau, 'grid') else [] + \ No newline at end of file diff --git a/Aider implementation/test_rover.py b/Aider implementation/test_rover.py new file mode 100644 index 0000000000000000000000000000000000000000..3bb67894126d3f9de0a5f15ff4bb4e744bae5486 --- /dev/null +++ b/Aider implementation/test_rover.py @@ -0,0 +1,29 @@ +from rover import Rover +from mission_control import MissionControl + +def test_rover_movement(): + # Erstelle einen Rover + rover = Rover(0, 0, 0) # x=0, y=0, heading=0 (Norden) + rover.set_plateau_size(5, 5) + + # Füge ein Hindernis hinzu + rover.add_obstacle(0, 5) + + # Teste Vorwärtsbewegung + result = rover.drive("FFF") + print(f"Befehl 'FFF', Ergebnis: '{result}', Position: ({rover.x}, {rover.y}), Heading: {rover.heading}") + + # Teste Drehung und Bewegung + rover = Rover(0, 0, 0) + rover.set_plateau_size(5, 5) + result = rover.drive("FRFLF") + print(f"Befehl 'FRFLF', Ergebnis: '{result}', Position: ({rover.x}, {rover.y}), Heading: {rover.heading}") + + # Teste MissionControl + mission = MissionControl(plateau_size_x=10, plateau_size_y=10) + mission.add_obstacle(2, 2) + result = mission.send_commands("FFRFF") + print(f"MissionControl Befehl 'FFRFF', Ergebnis: '{result}', Position: ({mission.rover.x}, {mission.rover.y})") + +if __name__ == "__main__": + test_rover_movement() diff --git a/README.md b/README.md index 73bf11b72e0ca0e6168cd1899841683c9387f6b2..15af33389e1bab5810001c60ea8b706e485628b5 100644 --- a/README.md +++ b/README.md @@ -476,3 +476,34 @@ Include the following: > Aider hatte hier Probleme, es passierte zunächst nichts, im anschluss wurde die Klasse 3 mal erstellt. +### Erstellung der Mission Control Klasse + +Create a new file named `mission_control.py` and define the `MissionControl` class within it. + +Include the following: +- Define a basic constructor `__init__(self)`. +- Add a class docstring explaining its purpose based on the diagram and the plan: "A class for controlling the mission, coordinating interactions between Map, Telescope, Mars, and Rover." +- Use `pass` inside the `__init__` method body for now. + +### Functional code + +Aider nach der erstellung der Struktur bitten, funktionale Codes zu implementieren. + +Okay, the basic structure for all classes is now set up in separate files. Please proceed with implementing the actual logic for the methods (`__init__`, `move`, `drive`, `observe`, etc.) within these classes, based on the UML diagram and the descriptions we discussed from the assignment. Replace the `pass` statements with functional code. + +> aider hat die Plateu klasse nicht miteinbezogen + +Please update the `plateau.py` file to implement the methods in the `Plateau` class. + +- In the `__init__` method, initialize the `self.grid` attribute to be a 2D structure (list of lists or similar) of the specified `size_x` and `size_y`. +- Implement the `move(self, x: int, y: int) -> None` method. This method should update the plateau's grid to note the position of obstacles and the rover's current position. (You might need to decide on a simple representation for the grid content, e.g., '.' for empty, '#' for obstacle, 'R' for rover). +- Add and implement the method `is_obstacle(self, x: int, y: int) -> bool`. This method should check the grid at `(x, y)` to see if there's an obstacle. +- Add and implement the method `is_within_bounds(self, x: int, y: int) -> bool`. This method should check if the coordinates `(x, y)` are within the `size_x` and `size_y` dimensions of the plateau. +- Ensure existing docstrings are kept and updated if needed. + +#### Aider bekommt die Anweisung die Drive Methode zu implementieren und einen test script um die funktionalitöt zu testen + +> Aider hatte wieder das selbe Problem wie im 1. statement, das modell musste wieder gewechselt werden. + + + diff --git a/Unittest.py b/Unittest.py index 806448c4a8b27944d493d6d16a3c51c257332476..617bc9bfcd16be6c30d099f1851a0dec25544d1d 100644 --- a/Unittest.py +++ b/Unittest.py @@ -1,8 +1,16 @@ import sys import os -from Pyscript import MissionControl, Plateau, Rover, Mars +#from Pyscript import MissionControl, Plateau, Rover, Mars +from plateau import Plateau +from mars import Mars +from rover import Rover +from mission_control import MissionControl +from telescope import Telescope +from map import Map import unittest +import telescope + # ---US01: Als Mars Mission Control möchte ich den Mars Rover steuern, um die grundlegende Interaktion und Kontrolle über den Rover zu ermöglichen. # TC01.01: Gültiger Vorwärtsbefehl: Überprüft, ob der Rover sich korrekt um ein Feld vorwärts bewegt, wenn der Befehl "F" empfangen wird. # TC01.02: Mehrfache gültige Vorwärtsbefehle: Überprüft, ob der Rover sich korrekt um mehrere Felder vorwärts bewegt, wenn eine Zeichenkette mit mehreren "F" Befehlen empfangen wird. @@ -13,13 +21,27 @@ import unittest class TestRoverMovment(unittest.TestCase): def setUp(self): - self.mission_control = MissionControl(5, 5, set()) # Initialisiere MissionControl - self.mission_control.rover.Position = (0, 0) # Setze die Startposition des Rovers - self.mission_control.rover.heading = 0 # Setze die Startausrichtung des Rovers - self.mission_control.rover.path = [(0, 0)] - self.mission_control.rover_heading_path = [0] - self.mission_control.mars.plateau.obstacles = set() # Initialisiere Hindernisse (falls benötigt) - + self.plateau = Plateau(5, 5) # Initialisiere Plateau + self.plateau.add_obstacle(1,1) + self.plateau.add_obstacle(3,3) + self.plateau.move(0, 0) # Setze die Startposition des Plateaus + self.telescope = Telescope(self.plateau) # Initialisiere Teleskop mit Plateau + self.mars = Mars(self.plateau) # Initialisiere Mars mit Plateau + self.rover = Rover(0, 0, 0) # Initialisiere Rover + self.rover.set_plateau_size(5, 5) # Setze die Größe des Plateaus für den Rover + self.mission_control=MissionControl(rover=self.rover,plateau_size_x=5, plateau_size_y=5) # Initialisiere MissionControl mit Rover und Plateau + self.telescope= Telescope(self.plateau) + self.map = Map() + #self.mission_control = MissionControl(5, 5, set()) # Initialisiere MissionControl + #self.plateau = Plateau(5, 5) # Initialisiere Plateau + #self.rover = Rover(0, 0, 0) # Initialisiere Rover + #self.mission_control=MissionControl(rover=self.rover, plateau_size_x=5, plateau_size_y=5) # Initialisiere MissionControl mit Rover und Plateau + #self.mission_control.rover.Position = (0, 0) # Setze die Startposition des Rovers + #self.mission_control.rover.heading = 0 # Setze die Startausrichtung des Rovers + #self.mission_control.rover.path = [(0, 0)] + #self.mission_control.rover_heading_path = [0] + #self.mission_control.mars.plateau.obstacles = set() # Initialisiere Hindernisse (falls benötigt) + def test_move_forwward_once(self): self.mission_control.send_commands("F") @@ -172,15 +194,15 @@ class TestRoverMovment(unittest.TestCase): def test_obstacle_in_command_sequence(self): self.mission_control.rover.Position = (0, 0) - self.mission_control.mars.plateau.obstacles = [(0, 1)] + self.mission_control.mars.plateau.obstacles = [(0, 2)] self.mission_control.send_commands("FFRBLF") - self.assertEqual(self.mission_control.rover.get_position(), (0, 0)) + self.assertEqual(self.mission_control.rover.get_position(), (0, 1)) def test_no_obstacle(self): - self.mission_control.rover.Position = (0, 0) + self.mission_control.rover.Position = (0, 1) self.mission_control.mars.plateau.obstacles = [] self.mission_control.send_commands("F") - self.assertEqual(self.mission_control.rover.get_position(), (0, 1)) + self.assertEqual(self.mission_control.rover.get_position(), (0, 2)) # ---US08: Als Mars Mission Control möchte ich, dass der Rover vor einem Bewegungsschritt (vorwärts/rückwärts) prüft, ob das Zielquadrat außerhalb der Grenzen des Plateaus liegt, um zu verhindern, dass der Rover das zugewiesene Operationsgebiet verlässt und möglicherweise verloren geht oder beschädigt wird. # TC08.01: Vorwärtsbewegung über den Rand: Überprüft, ob der Rover die Vorwärtsbewegung stoppt, wenn sie über den Rand des Plateaus hinausführen würde. @@ -256,6 +278,44 @@ class TestRoverMovment(unittest.TestCase): print(feedback) self.assertIn("Erfolgreich ausgeführte Befehle: F, B", feedback) +# TC12.01: Überprüfen, ob das Plateau-Objekt bei der Initialisierung korrekt gespeichert wird. +# TC12.02: Überprüfen, ob die observe-Methode den Inhalt des Grids vom Plateau zurückgibt. +# TC12.03: Überprüfen, ob die observe-Methode eine Kopie des Grids zurückgibt (nicht das Originalobjekt). +# TC12.04: Überprüfen, ob observe eine leere Liste zurückgibt, wenn das Grid fehlt oder None ist. + + def test_observe_plateau_initialization(self): + real_plateau = Plateau(5, 5) + telescope = Telescope(real_plateau) + self.assertEqual(telescope.plateau, real_plateau) + print("Test observe_plateau_initialization erfolgreich!") + + def test_observe_returns_grid(self): + real_plateau = Plateau(3, 3) + real_plateau.add_obstacle(1, 1) + real_plateau.move(0, 0) + expected_grid = [['R', '.', '.'], ['.', '#', '.'], ['.', '.', '.']] + telescope = Telescope(real_plateau) + observed_grid = telescope.observe() + self.assertEqual(observed_grid, expected_grid) + print("Test observe_returns_grid erfolgreich!") + + def test_observe_returns_copy_of_grid(self): + real_plateau = Plateau(3, 3) + real_plateau.add_obstacle(1, 1) + real_plateau.move(0, 0) + telescope = Telescope(real_plateau) + observed_grid = telescope.observe() + observed_grid[0][0] = '.' + self.assertEqual(observed_grid[0][0], real_plateau.grid[0][0]) + print("Test observe_returns_copy_of_grid erfolgreich!") + + def test_observe_returns_empty_list(self): + real_plateau = Plateau(3, 3) + telescope = Telescope(real_plateau) + telescope.plateau.grid = None # Setze das Grid auf None + observed_grid = telescope.observe() + self.assertEqual(observed_grid, []) + print("Test observe_returns_empty_list erfolgreich!") if __name__ == '__main__': diff --git a/UseCase7.md b/User storys and Use Cases/UseCase7.md similarity index 100% rename from UseCase7.md rename to User storys and Use Cases/UseCase7.md diff --git a/UserStroys_uebersicht.md b/User storys and Use Cases/UserStroys_uebersicht.md similarity index 100% rename from UserStroys_uebersicht.md rename to User storys and Use Cases/UserStroys_uebersicht.md diff --git a/useCase0.md b/User storys and Use Cases/useCase0.md similarity index 100% rename from useCase0.md rename to User storys and Use Cases/useCase0.md diff --git a/useCase1.md b/User storys and Use Cases/useCase1.md similarity index 100% rename from useCase1.md rename to User storys and Use Cases/useCase1.md diff --git a/useCase10.md b/User storys and Use Cases/useCase10.md similarity index 100% rename from useCase10.md rename to User storys and Use Cases/useCase10.md diff --git a/useCase11.md b/User storys and Use Cases/useCase11.md similarity index 100% rename from useCase11.md rename to User storys and Use Cases/useCase11.md diff --git a/useCase2.md b/User storys and Use Cases/useCase2.md similarity index 100% rename from useCase2.md rename to User storys and Use Cases/useCase2.md diff --git a/useCase3.md b/User storys and Use Cases/useCase3.md similarity index 100% rename from useCase3.md rename to User storys and Use Cases/useCase3.md diff --git a/useCase4.md b/User storys and Use Cases/useCase4.md similarity index 100% rename from useCase4.md rename to User storys and Use Cases/useCase4.md diff --git a/useCase5.md b/User storys and Use Cases/useCase5.md similarity index 100% rename from useCase5.md rename to User storys and Use Cases/useCase5.md diff --git a/useCase6.md b/User storys and Use Cases/useCase6.md similarity index 100% rename from useCase6.md rename to User storys and Use Cases/useCase6.md diff --git a/useCase8.md b/User storys and Use Cases/useCase8.md similarity index 100% rename from useCase8.md rename to User storys and Use Cases/useCase8.md diff --git a/useCase9.md b/User storys and Use Cases/useCase9.md similarity index 100% rename from useCase9.md rename to User storys and Use Cases/useCase9.md diff --git a/__pycache__/Pyscript.cpython-311.pyc b/__pycache__/Pyscript.cpython-311.pyc index 23b7e71dd730b05039c6a452f11dba925a37689e..bbc357719fb11089430956a3f5002e3d13784c51 100644 Binary files a/__pycache__/Pyscript.cpython-311.pyc and b/__pycache__/Pyscript.cpython-311.pyc differ diff --git a/__pycache__/map.cpython-311.pyc b/__pycache__/map.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9bfff72eeed3186eca6003bf01e0a7649e7d1364 Binary files /dev/null and b/__pycache__/map.cpython-311.pyc differ diff --git a/__pycache__/mars.cpython-311.pyc b/__pycache__/mars.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4fae670c7ddab4439cfca045a654bd477baf5976 Binary files /dev/null and b/__pycache__/mars.cpython-311.pyc differ diff --git a/__pycache__/mission_control.cpython-311.pyc b/__pycache__/mission_control.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..be4951f11bbce503cec98a2c8fff6521eef0c478 Binary files /dev/null and b/__pycache__/mission_control.cpython-311.pyc differ diff --git a/__pycache__/plateau.cpython-311.pyc b/__pycache__/plateau.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a215f616b524bb2427167f23134530e9667bd18b Binary files /dev/null and b/__pycache__/plateau.cpython-311.pyc differ diff --git a/__pycache__/rover.cpython-311.pyc b/__pycache__/rover.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1b3b454e3a89c0719b1fe2e76f924f1cade0de6f Binary files /dev/null and b/__pycache__/rover.cpython-311.pyc differ diff --git a/__pycache__/telescope.cpython-311.pyc b/__pycache__/telescope.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f59be9dd2aa4059087c2f9dee15eef61ad6d502e Binary files /dev/null and b/__pycache__/telescope.cpython-311.pyc differ diff --git a/mars.py b/mars.py deleted file mode 100644 index 2424a3897b182320d97ddb3a0c887b1972e6a9f9..0000000000000000000000000000000000000000 --- a/mars.py +++ /dev/null @@ -1,16 +0,0 @@ -class Mars: - """ - Eine Klasse zur Repräsentation des Mars. - """ - - def drive(self, cmd: str) -> str: - """ - Führt Fahrbefehle auf dem Mars aus. - - Args: - cmd: Die Fahrbefehle als String - - Returns: - Ein String mit den erfolgreich ausgeführten Befehlen - """ - pass diff --git a/mission_control.py b/mission_control.py deleted file mode 100644 index 9feab5f8bb3a24b58d11b71d8782155cec30cf1a..0000000000000000000000000000000000000000 --- a/mission_control.py +++ /dev/null @@ -1,11 +0,0 @@ -class MissionControl: - """ - Eine Klasse zur Steuerung der Mission, die die Interaktionen zwischen - Map, Telescope, Mars und Rover koordiniert. - """ - - def __init__(self): - """ - Initialisiert die Missionskontrolle. - """ - pass diff --git a/plateau.py b/plateau.py deleted file mode 100644 index 378d8caf5d10ec63a2989bb26e431760e3194c3d..0000000000000000000000000000000000000000 --- a/plateau.py +++ /dev/null @@ -1,31 +0,0 @@ -class Plateau: - """ - Eine Klasse zur Repräsentation eines Plateaus. - - Attributes: - grid: Eine Liste von Listen oder Tupeln, die das Raster des Plateaus darstellt. - """ - - def __init__(self, size_x: int, size_y: int) -> None: - """ - Der Konstruktor erstellt ein Plateau mit der Größe x mal y. - - Args: - size_x: Die Breite des Plateaus - size_y: Die Höhe des Plateaus - """ - self.grid = [] - self.size_x = size_x - self.size_y = size_y - pass - - def move(self, x: int, y: int) -> None: - """ - Notiert die Positionen der Hindernisse und die tatsächliche Position - des Rovers auf dem Raster. - - Args: - x: Die x-Koordinate - y: Die y-Koordinate - """ - pass diff --git a/rover.py b/rover.py deleted file mode 100644 index 1d76dd30e98e0ebb84bd0e6fde3c1e5b5068eea0..0000000000000000000000000000000000000000 --- a/rover.py +++ /dev/null @@ -1,21 +0,0 @@ -from abc import ABC, abstractmethod - -class Rover(ABC): - """ - Eine abstrakte Basisklasse für einen Rover. - """ - - @abstractmethod - def drive(self, cmd: str) -> str: - """ - Nimmt die Fahrbefehle entgegen und gibt eine Sequenz von Buchstaben zurück, - die erfolgreich ausgeführt wurden. Wenn das ODS den Rover stoppt, gibt die - Methode einen Teilstring zurück, der die erfolgreich ausgeführten Befehle enthält. - - Args: - cmd: Die Fahrbefehle als String - - Returns: - Ein String mit den erfolgreich ausgeführten Befehlen - """ - pass diff --git a/.gitignore b/stuff/.gitignore similarity index 100% rename from .gitignore rename to stuff/.gitignore diff --git a/Screenshot 2025-05-09 161055.png b/stuff/Screenshot 2025-05-09 161055.png similarity index 100% rename from Screenshot 2025-05-09 161055.png rename to stuff/Screenshot 2025-05-09 161055.png diff --git a/hello_world.py b/stuff/hello_world.py similarity index 100% rename from hello_world.py rename to stuff/hello_world.py diff --git a/telescope.py b/telescope.py deleted file mode 100644 index f9c0eb9819d3066226bdd672c8b50784df75e943..0000000000000000000000000000000000000000 --- a/telescope.py +++ /dev/null @@ -1,25 +0,0 @@ -from plateau import Plateau - -class Telescope: - """ - Eine Klasse zur Repräsentation eines Teleskops, das das Plateau beobachtet. - """ - - def __init__(self, plateau: Plateau): - """ - Initialisiert das Teleskop mit einem Plateau-Objekt. - - Args: - plateau: Das zu beobachtende Plateau-Objekt - """ - self.plateau = plateau - - def observe(self) -> list: - """ - Beobachtet das Raster des Plateaus. - - Returns: - Das Raster des Plateaus (grid) - """ - # Gibt eine Kopie des Rasters zurück, um unbeabsichtigte Änderungen zu vermeiden - return self.plateau.grid.copy() if hasattr(self.plateau, 'grid') else []