diff --git a/Aider implementation/map.py b/Aider implementation/map.py new file mode 100644 index 0000000000000000000000000000000000000000..682cee1310af0228367682ab7724fe2e2deb509b --- /dev/null +++ b/Aider implementation/map.py @@ -0,0 +1,24 @@ +class Map: + """ + Eine Klasse zur Repräsentation einer Karte. + + Attributes: + map: Eine Liste von Listen oder Tupeln, die die Karte darstellt. + """ + + def __init__(self): + self.map = [] # Liste von Listen oder Tupeln + + def move(self, x: int, y: int) -> None: + """ + Bewegt ein Objekt auf der Karte zu den angegebenen Koordinaten. + + Args: + x: Die x-Koordinate + y: Die y-Koordinate + """ + # 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/Pyscript.py b/Pyscript.py index 96359a63db66adbecd435f81479474278caf59b5..30b25da6514f8a26f5b8f5c134a6d02c985c933f 100644 --- a/Pyscript.py +++ b/Pyscript.py @@ -220,43 +220,6 @@ class MissionControl: print(f" Rover-Ausrichtungs-Pfad: {self.rover_heading_path}") # Beispielausgabe der Pfade print(f" Hindernisse: {self.mars.plateau.obstacles}") # Beispielausgabe der Hindernisse -class Telescope: - def __init__(self, map_object): - """ - Initialisiert ein Teleskop-Objekt mit einem Map- oder Plateau-Objekt - - Args: - map_object: Ein Map- oder Plateau-Objekt, das beobachtet werden soll - """ - self.map_object = map_object - - def observe(self): - """ - Beobachtet die Karte und gibt die Koordinaten aller besetzten Zellen zurück - - Returns: - List[Tuple[int, int]]: Liste von Koordinaten besetzter Zellen (Hindernisse oder Rover) - """ - occupied_cells = [] - - # Versuche, auf die Kartendaten zuzugreifen - if hasattr(self.map_object, 'grid'): - grid_data = getattr(self.map_object, 'grid') - elif hasattr(self.map_object, 'map'): - grid_data = getattr(self.map_object, 'map') - - # Wenn das Objekt ein Plateau ist, füge die Hindernisse hinzu - if hasattr(self.map_object, 'obstacles'): - obstacles = getattr(self.map_object, 'obstacles') - occupied_cells.extend(list(obstacles)) - - # Wenn das Objekt ein Mars ist, greife auf das Plateau zu - if hasattr(self.map_object, 'plateau') and hasattr(self.map_object.plateau, 'obstacles'): - obstacles = getattr(self.map_object.plateau, 'obstacles') - occupied_cells.extend(list(obstacles)) - - return occupied_cells - if __name__ == "__main__": # Beispielinitialisierung mission_control = MissionControl(5, 5, {(2, 2), (3, 4)}) diff --git a/README.md b/README.md index d0bb08e67590aa884f7b706392c3ed80fc0c9d26..15af33389e1bab5810001c60ea8b706e485628b5 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,4 @@ + | **USE CASE 0** | Mars Rover steuern | |----------------|--------------------| | **Goal in Context** | Befehle an den Mars Rover senden. | @@ -350,4 +351,159 @@ | 3 | Zeige nur die aktuelle Position. | | 3 | Zeige die aktuelle Position und die Ausrichtung (z.B. durch einen Pfeil). | | 4 | Zeige den gesamten bisher zurückgelegten Pfad. | -| 4 | Zeige den Pfad der letzten X Zeiteinheiten oder Y Distanz. | \ No newline at end of file +| 4 | Zeige den Pfad der letzten X Zeiteinheiten oder Y Distanz. | + +| **USE CASE 12** | Karte/Plateau mit Teleskop beobachten | +|-----------------|-------------------------------------------| +| **Goal in Context** | Identifizieren und Zurückgeben der Koordinaten von Hindernissen (als "besetzte Zellen" interpretiert) auf einer Karte oder einem Plateau mithilfe des Teleskops. | +| **Scope & Level** | System: Mars Mission Control Beobachtungssystem (Teleskop-Modul)<br>Level: Primary Task | +| **Preconditions** | Das Teleskop-Objekt wurde mit einem gültigen Karten- oder Plateau-Objekt initialisiert (`map_object`). Das Beobachtungssystem ist aktiv. Das Karten-/Plateau-Objekt kann Informationen über Hindernisse (`obstacles`) bereitstellen. | +| **Success End Condition** | Das Teleskop hat die Beobachtung erfolgreich durchgeführt und eine Liste der Koordinaten aller identifizierten Hindernisse (besetzte Zellen) korrekt zurückgegeben. Die Daten stehen der Mars Mission Control oder einem anfordernden System zur Verfügung. | +| **Failed End Condition** | Das Teleskop konnte die Beobachtung nicht durchführen (z.B. aufgrund eines nicht korrekt initialisierten `map_object` oder fehlender `obstacles`-Daten im `map_object`). Die zurückgegebene Liste ist fehlerhaft, unvollständig oder es wird ein Fehler gemeldet. | +| **Primary, Secondary Actors** | Primary Actor: Mars Mission Control (oder ein anderes System, z.B. Pfadplanung)<br>Secondary Actors: Teleskop-Objekt, Karten-/Plateau-Objekt | +| **Trigger** | Die Mars Mission Control oder ein automatisiertes System fordert eine Beobachtung der Karte/des Plateaus über die `observe()`-Methode des Teleskops an. | +## DESCRIPTION +| **Step** | **Action** | +|----------|------------| +| 1 | Die `observe()`-Methode des Teleskops wird aufgerufen. | +| 2 | Das Teleskop greift auf das ihm bei der Initialisierung zugewiesene `map_object` (Karte/Plateau) zu. | +| 3 | Das Teleskop prüft, ob das `map_object` direkt ein `obstacles`-Attribut besitzt oder ob ein darin enthaltenes `plateau`-Objekt ein `obstacles`-Attribut besitzt. | +| 4 | Wenn ein `obstacles`-Attribut gefunden wird, extrahiert das Teleskop die Liste der Koordinaten der Hindernisse. | +| 5 | Das Teleskop gibt die gesammelte Liste der Hinderniskoordinaten als "besetzte Zellen" zurück. | +| 6 | Die Mars Mission Control oder das anfordernde System empfängt die Liste der besetzten Zellen für weitere Verarbeitung oder Anzeige. | +## EXTENSIONS +| **Step** | **Branching Action** | +|----------|----------------------| +| 2a | **Wenn das `map_object` im Teleskop nicht korrekt initialisiert oder nicht zugreifbar ist:** Die `observe()`-Methode gibt eine Fehlermeldung oder eine leere Liste mit einer entsprechenden Protokollierung zurück. | +| 3a | **Wenn im `map_object` (oder dessen `plateau`-Attribut) kein `obstacles`-Attribut gefunden wird:** Das Teleskop gibt eine leere Liste zurück (da keine Hindernisse über dieses Attribut definiert sind). | +| 4a | **Wenn das `obstacles`-Attribut vorhanden, aber leer ist oder ein unerwartetes Format hat:** Das Teleskop gibt eine leere Liste oder die verarbeitbaren Teile zurück und protokolliert ggf. eine Warnung. | +| 6a | **Wenn die Übermittlung der Daten an das anfordernde System fehlschlägt:** Protokolliere den Fehler im System. | +## SUB-VARIATIONS +| **Step** | **Branching Action** | +|----------|----------------------| +| 3 | Das Teleskop könnte erweitert werden, um auch auf andere Attribute des `map_object` (z.B. `grid` oder `map` wie im Code angedeutet, aber nicht für `occupied_cells` genutzt) zuzugreifen, um weitere Arten von besetzten Zellen (z.B. Rover-Positionen, wenn separat geführt) zu identifizieren. | +| 5 | Die zurückgegebenen Koordinaten werden in einem spezifischen Format für eine direkte Visualisierung aufbereitet (z.B. als Overlay für USE CASE 11). | +| 5 | Die zurückgegebenen Koordinaten werden für eine automatisierte Kollisionsprüfung oder Pfadplanung verwendet. | + +::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +--- +# Vorgehensweise Aufgabe6 + +Aufsetzen von Aider -konnte nicht meine Python.exe bzw den Path nicht finden. weshalb folgender code genutzt wurde: +#### & "$HOME\.local\bin\aider.exe" --model openrouter/deepseek/deepseek-coder --api-key openrouter-... + +- Aider erstellte Korrekt eine Hello world.py +- Aider konnte auch erfolgreich änderungen an der File vornehmen, durch die implementierung eines Calculators. +- Bei dem Wechsel auf mein Roverscript: Pyscript.py begann sich aider seltsam zu verhalten. +- Es fanden keine Änderungen mehr in Pyscript.py mehr statt und die Prozesse welche im Terminal liefen hatten keinen Bezug zu dem Code oder dem gegebenen befehl. Auch nicht mehr bei der Hello World.Py +- FIX: Recherche in der Offizielen Doku ergab das zunächst das Terminal mit /clear gesäubert werden muss und das Model mit /model gewechselt werden muss. Ich wechselte auf das Sonnet model. Das Problem war behoben + +### Erste implementierung der Telescope klasse +- Zunächst sollte via /ask ein Plan erstellt werden wie eine Mögliche implementierung aussehen soll +- im nächsten Schritt gab ich die Anweisung den vorgeschlagenen Code zu implementieren: + +#### Please add a new class called `Telescope` to Pyscript.py. +#### +#### The class should: +#### - Take a `Map` or `Plateau` object as input in the constructor. +#### - Provide a method `observe(self) -> List[Tuple[int, int]]` that returns the coordinates of all occupied cells (i.e., obstacles or rovers). +#### - Access the map/grid data from the given object, using `getattr()` to support either `.grid` or `.map`. + +'''Aufgabe wurde falsch angegangen weshlb ich paar dinge überarbeiten musste''' +### Erstellung der Plateu Klasse + +folgender prompt wurde verwendet: + +Create a new file named `plateau.py` and define the `Plateau` class within it. + +Include the following: +- An attribute named `grid` which should be represented as a list of lists or a list of tuples, as noted in the diagram ("grid is a list of list or a list of tuples"). +- Define the constructor `__init__(self, size_x: int, size_y: int) -> None`. Add the docstring based on the diagram note: "The init constructor creates a plateau with x times y size." +- Define the method `move(self, x: int, y: int) -> None`. Add the docstring based on the diagram note: "notes the obstacles' positions and the true position of the rover on the grid." +- Add a class docstring explaining its purpose and the `grid` attribute. +- Use `pass` inside the method bodies for now, as we are only creating the structure.Create a new file named `plateau.py` and define the `Plateau` class within it. + +Include the following: +- An attribute named `grid` which should be represented as a list of lists or a list of tuples, as noted in the diagram ("grid is a list of list or a list of tuples"). +- Define the constructor `__init__(self, size_x: int, size_y: int) -> None`. Add the docstring based on the diagram note: "The init constructor creates a plateau with x times y size." +- Define the method `move(self, x: int, y: int) -> None`. Add the docstring based on the diagram note: "notes the obstacles' positions and the true position of the rover on the grid." +- Add a class docstring explaining its purpose and the `grid` attribute. +- Use `pass` inside the method bodies for now, as we are only creating the structure. + +### Erstellung der Map Klasse + +Create a new file named `map.py` and define the `Map` class within it. + +Include the following: +- An attribute named `map` which should be represented as a list of lists or a list of tuples, as noted in the diagram ("map is a list of list or a list of tuples"). +- Define the method `move(self, x: int, y: int) -> None`. +- Add a class docstring explaining its purpose and the `map` attribute. +- Add a method docstring for the `move` method. +- Use `pass` inside the method body for now. + +### Erstellung der Rover Klasse + +Prompt: + +Create a new file named `rover.py` and define the `Rover` class within it. + +This class should be an **abstract base class**. +- Import the necessary modules from `abc` (`ABC` and `abstractmethod`). +- The `Rover` class must inherit from `ABC`. +- Define an abstract method `drive(self, cmd: str) -> str`. +- Add a method docstring for `drive` based on the diagram note: "takes the drive commands and returns a sequence of letters, which were successfully executed. If the ODS stops the rover, the method returns a substring containing successfully executed commands." +- Add a class docstring indicating it's an abstract base class for a rover. + +### Erstellung der Mars Klasse + +Create a new file named `mars.py` and define the `Mars` class within it. + +Include the following: +- Define the method `drive(self, cmd: str) -> str`. +- Add a class docstring explaining its purpose ("Eine Klasse zur Repräsentation des Mars."). +- Add a method docstring for the `drive` method based on the diagram and your previous plan ("Führt Fahrbefehle auf dem Mars aus." etc.). +- Use `pass` inside the method body for now. + +### Erstellung der Telescope Klasse: + +Create a new file named `telescope.py` and define the `Telescope` class within it. + +Include the following: +- Define a constructor `__init__(self, plateau)`. Add a docstring: "Initializes the Telescope with a Plateau object." Also store the `plateau` object as an instance attribute (e.g., `self.plateau = plateau`). +- Define the method `observe(self) -> any`. Add a docstring based on the diagram note: "Observes the Plateau's grid." +- Add a class docstring explaining its purpose ("Eine Klasse zur Repräsentation eines Teleskops, das das Plateau beobachtet."). +- Use `pass` inside the method body for now. + +> 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__/hello_world.cpython-311.pyc b/__pycache__/hello_world.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1e6a0402d90b212793219b3a1b4c3eb15a3415c6 Binary files /dev/null and b/__pycache__/hello_world.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/stuff/.gitignore b/stuff/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..b0ac3ed9c09f528e05b0668aacb8b046dd3bdcb5 --- /dev/null +++ b/stuff/.gitignore @@ -0,0 +1 @@ +.aider* diff --git a/stuff/Screenshot 2025-05-09 161055.png b/stuff/Screenshot 2025-05-09 161055.png new file mode 100644 index 0000000000000000000000000000000000000000..9de2168790425f92af12db7cea3d4dc8c35248f0 Binary files /dev/null and b/stuff/Screenshot 2025-05-09 161055.png differ 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/testcases b/testcases new file mode 100644 index 0000000000000000000000000000000000000000..1ccf07f050c52fb589eb193d3151b7357a9b5dc9 --- /dev/null +++ b/testcases @@ -0,0 +1,68 @@ +# ---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. +# TC01.03: Vorwärtsbefehl bei Drehung: Überprüft, ob der Rover sich nach einer Drehung korrekt vorwärts bewegt. +# TC01.04: Ungültiger Befehl in der Zeichenkette: Überprüft, wie der Rover mit einer Zeichenkette umgeht, die einen ungültigen Befehl enthält (ungültige Befehle werden ignoriert). +# TC01.05: Leerer Befehl: Überprüft, was passiert, wenn ein leerer Befehl gesendet wird (Rover bleibt unverändert). + +# ---US02: Als Mars Mission Control möchte ich dem Rover einen Befehl zum Rückwärtsfahren ('B') geben können, um dem Rover zu ermöglichen, sich von Hindernissen zu entfernen oder präzisere Manöver durchzuführen. +# TC02.01: Gültiger Rückwärtsbefehl: Überprüft, ob der Rover sich korrekt um ein Feld zurückbewegt, wenn der Befehl "B" empfangen wird. +# TC02.02: Mehrfache gültige Rückwärtsbefehle: Überprüft, ob der Rover sich korrekt um mehrere Felder rückwärts bewegt, wenn eine Zeichenkette mit mehreren "B" Befehlen empfangen wird. +# TC02.03: Rückwärtsbefehl nach Drehung: Überprüft, ob der Rover sich nach einer Drehung korrekt rückwärts bewegt. +# TC02.04: Rückwärts- und Vorwärtsbefehle kombinieren: Überprüft, ob Vorwärts- und Rückwärtsbefehle in einer Befehlskette korrekt verarbeitet werden. + +# ---US03: Als Mars Mission Control möchte ich dem Rover einen Befehl zum Linksdrehen ('L') geben können, um die Ausrichtung des Rovers anzupassen und ihn in eine neue Richtung zu lenken. +# TC03.01: Gültiger Linksdrehungsbefehl: Überprüft, ob der Rover sich um 45 Grad nach links dreht, wenn der Befehl "L" empfangen wird. +# TC03.02: Mehrfache gültige Linksdrehungsbefehle: Überprüft, ob der Rover sich korrekt um mehrere 45-Grad-Schritte nach links dreht, wenn eine Zeichenkette mit mehreren "L" Befehlen empfangen wird. +# TC03.03: Linksdrehung und Bewegung kombinieren: Überprüft, ob Linksdrehungen mit Bewegungsbefehlen (F, B) korrekt kombiniert werden können. + +# ---US04: Als Mars Mission Control möchte ich dem Rover einen Befehl zum Rechtsdrehen ('R') geben können, um die Ausrichtung des Rovers anzupassen und ihn in eine neue Richtung zu lenken. +# TC04.01: Gültiger Rechtsdrehungsbefehl: Überprüft, ob der Rover sich um 45 Grad nach rechts dreht, wenn der Befehl "R" empfangen wird. +# TC04.02: Mehrfache gültige Rechtsdrehungsbefehle: Überprüft, ob der Rover sich korrekt um mehrere 45-Grad-Schritte nach rechts dreht, wenn eine Zeichenkette mit mehreren "R" Befehlen empfangen wird. +# TC04.03: Rechtsdrehung und Bewegung kombinieren: Überprüft, ob Rechtsdrehungen mit Bewegungsbefehlen (F, B) korrekt kombiniert werden können. + +# ---US05: Als Mars Mission Control möchte ich dem Rover eine Zeichenkette mit mehreren Befehlen senden können (z.B. "FFRBLF"), um komplexe Bewegungsabläufe und Manöver effizient in einer einzigen Anweisung zu übermitteln. +# TC05.01: Komplexe Befehlssequenz: Überprüft, ob eine lange und komplexe Zeichenkette mit verschiedenen Befehlen korrekt ausgeführt wird. +# TC05.02: Wiederholte Befehle: Überprüft, ob sich wiederholte Befehle in einer Sequenz korrekt ausführen lassen. +# TC05.03: Leere Befehlssequenz: Überprüft, was passiert, wenn eine leere Befehlssequenz gesendet wird. +# TC05.04: Befehlssequenz mit ungültigen Befehlen: Überprüft, ob ungültige Befehle in einer Befehlssequenz ignoriert werden und die gültigen Befehle ausgeführt werden. + +# ---US06: Als Mars Mission Control möchte ich, dass der Rover vor einem Bewegungsschritt (vorwärts/rückwärts) prüft, ob sich ein Hindernis im Zielquadrat befindet, um Kollisionen mit unvorhergesehenen Objekten auf der Marsoberfläche zu vermeiden und die Sicherheit des Rovers zu gewährleisten. +# TC06.01: Hindernis bei Vorwärtsbewegung: Überprüft, ob der Rover die Vorwärtsbewegung stoppt, wenn ein Hindernis im Zielquadrat ist. +# TC06.02: Hindernis bei Rückwärtsbewegung: Überprüft, ob der Rover die Rückwärtsbewegung stoppt, wenn ein Hindernis im Zielquadrat ist. +# TC06.03: Hindernis nach Drehung: Überprüft, ob die Vorwärtsbewegung nach einer Drehung stoppt, wenn ein Hindernis im Zielquadrat ist. +# TC06.04: Mehrere Befehle mit Hindernis: Überprüft, ob die gesamte Befehlssequenz abbricht, wenn ein Hindernis auftritt. +# TC06.05: Kein Hindernis: Überprüft, ob die Bewegung fortgesetzt wird, wenn kein Hindernis vorhanden ist. + +# ---US07(Redundant): Als Mars Mission Control möchte ich, dass der Rover seine Bewegung und alle nachfolgenden Befehle in der Sequenz abbricht, wenn ein Hindernis erkannt wird, um sicherzustellen, dass der Rover nicht in ein Hindernis fährt und um weitere potenziell schädliche Aktionen zu verhindern. +# TC07.01: Abbruch bei Vorwärtsbewegung mit Hindernis: Überprüft, ob die Befehlssequenz abbricht, wenn ein Hindernis bei der Vorwärtsbewegung erkannt wird. +# TC07.02: Abbruch bei Rückwärtsbewegung mit Hindernis: Überprüft, ob die Befehlssequenz abbricht, wenn ein Hindernis bei der Rückwärtsbewegung erkannt wird. +# TC07.03: Abbruch nach Drehung mit Hindernis: Überprüft, ob die Befehlssequenz abbricht, wenn ein Hindernis nach einer Drehung erkannt wird. +# TC07.04: Teilweise Ausführung und Abbruch: Überprüft, welche Befehle vor dem Abbruch ausgeführt wurden. + +# ---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. +# TC08.02: Rückwärtsbewegung über den Rand: Überprüft, ob der Rover die Rückwärtsbewegung stoppt, wenn sie über den Rand des Plateaus hinausführen würde. +# TC08.03: Bewegung nach Drehung über den Rand: Überprüft, ob die Bewegung nach einer Drehung stoppt, wenn sie über den Rand des Plateaus hinausführen würde. +# TC08.04: Mehrere Befehle über den Rand: Überprüft, ob die gesamte Befehlssequenz abbricht, wenn der Rand erreicht wird. +# TC08.05: Bewegung am Rand: Überprüft, ob die Bewegung am Rand des Plateaus erlaubt ist. + +# ---US09(redundant) Als Mars Mission Control möchte ich, dass der Rover seine Bewegung und alle nachfolgenden Befehle in der Sequenz abbricht, wenn der Rand des Plateaus erreicht würde, um sicherzustellen, dass der Rover innerhalb der sicheren Operationsgrenzen bleibt und keine unnötigen Risiken eingeht. +# TC09.01: Abbruch bei Vorwärtsbewegung über den Rand: Überprüft, ob die Befehlssequenz abbricht, wenn die Vorwärtsbewegung über den Rand führen würde. +# TC09.02: Abbruch bei Rückwärtsbewegung über den Rand: Überprüft, ob die Befehlssequenz abbricht, wenn die Rückwärtsbewegung über den Rand führen würde. +# TC09.03: Abbruch nach Drehung über den Rand: Überprüft, ob die Befehlssequenz abbricht, wenn die Bewegung nach einer Drehung über den Rand führen würde. +# TC09.04: Teilweise Ausführung und Abbruch am Rand: Überprüft, welche Befehle vor dem Abbruch am Rand ausgeführt wurden. + +# ---US10: Als Mars Mission Control möchte ich vom Rover eine Rückmeldung erhalten, welche Befehle einer Sequenz erfolgreich ausgeführt wurden, bevor ein Stopp erfolgte, um den Fortschritt der Rover-Mission zu verfolgen und zu verstehen, welche Aktionen erfolgreich waren und wo Probleme aufgetreten sind. +# TC10.01: Rückmeldung bei erfolgreicher Ausführung: Überprüft, ob der Rover eine Rückmeldung gibt, wenn alle Befehle erfolgreich ausgeführt wurden. +# TC10.02: Rückmeldung bei Stopp wegen Hindernis: Überprüft, ob der Rover eine Rückmeldung gibt, welche Befehle vor dem Stopp wegen eines Hindernisses ausgeführt wurden. +# TC10.03: Rückmeldung bei Stopp wegen Rand: Überprüft, ob der Rover eine Rückmeldung gibt, welche Befehle vor dem Stopp wegen des Plateaurandes ausgeführt wurden. +# TC10.04: Rückmeldung bei leerer Befehlssequenz: Überprüft, ob der Rover eine leere Rückmeldung gibt, wenn die Befehlssequenz leer ist. +# TC10.05: Rückmeldung bei ungültigen Befehlen: Überprüft, wie ungültige Befehle in der Rückmeldung behandelt werden (z.B. ausgelassen oder markiert). + +# ---US11: Als Mars Mission Control möchte ich die relative Position und Ausrichtung des Rovers basierend auf den erfolgreichen Befehlen auf meiner eigenen Karte nachverfolgen, um eine genaue Vorstellung der aktuellen Position und Ausrichtung des Rovers auf der Marsoberfläche zu haben und zukünftige Befehle präzise planen zu können. +# TC11.01: Korrekte Positionsaktualisierung: Überprüft, ob die Position des Rovers auf der Karte von MissionControl korrekt aktualisiert wird. +# TC11.02: Korrekte Ausrichtungsaktualisierung: Überprüft, ob die Ausrichtung des Rovers auf der Karte von MissionControl korrekt aktualisiert wird. +# TC11.03: Positionsaktualisierung nach komplexer Sequenz: Überprüft, ob die Position nach einer komplexen Befehlssequenz korrekt ist. +# TC11.04: Ausrichtungsaktualisierung nach komplexer Sequenz: Überprüft, ob die Ausrichtung nach einer komplexen Befehlssequenz korrekt ist. +# TC11.05: Positionsaktualisierung bei Abbruch: Überprüft, ob die Position auf der Karte korrekt ist, wenn die Befehlssequenz aufgrund eines Hindernisses oder des Plateaurandes abbricht. \ No newline at end of file