Skip to content
Snippets Groups Projects
Commit 34bebf88 authored by Muhamed's avatar Muhamed
Browse files

Merge branch 'Develop'

parents 469cba6b a944268c
Branches
No related tags found
No related merge requests found
Showing
with 721 additions and 50 deletions
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
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)
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"
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
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
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
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()
...@@ -220,43 +220,6 @@ class MissionControl: ...@@ -220,43 +220,6 @@ class MissionControl:
print(f" Rover-Ausrichtungs-Pfad: {self.rover_heading_path}") # Beispielausgabe der Pfade print(f" Rover-Ausrichtungs-Pfad: {self.rover_heading_path}") # Beispielausgabe der Pfade
print(f" Hindernisse: {self.mars.plateau.obstacles}") # Beispielausgabe der Hindernisse 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__": if __name__ == "__main__":
# Beispielinitialisierung # Beispielinitialisierung
mission_control = MissionControl(5, 5, {(2, 2), (3, 4)}) mission_control = MissionControl(5, 5, {(2, 2), (3, 4)})
... ...
......
| **USE CASE 0** | Mars Rover steuern | | **USE CASE 0** | Mars Rover steuern |
|----------------|--------------------| |----------------|--------------------|
| **Goal in Context** | Befehle an den Mars Rover senden. | | **Goal in Context** | Befehle an den Mars Rover senden. |
...@@ -351,3 +352,158 @@ ...@@ -351,3 +352,158 @@
| 3 | Zeige die aktuelle Position und die Ausrichtung (z.B. durch einen Pfeil). | | 3 | Zeige die aktuelle Position und die Ausrichtung (z.B. durch einen Pfeil). |
| 4 | Zeige den gesamten bisher zurückgelegten Pfad. | | 4 | Zeige den gesamten bisher zurückgelegten Pfad. |
| 4 | Zeige den Pfad der letzten X Zeiteinheiten oder Y Distanz. | | 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.
import sys import sys
import os 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 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. # ---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.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.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,12 +21,26 @@ import unittest ...@@ -13,12 +21,26 @@ import unittest
class TestRoverMovment(unittest.TestCase): class TestRoverMovment(unittest.TestCase):
def setUp(self): def setUp(self):
self.mission_control = MissionControl(5, 5, set()) # Initialisiere MissionControl self.plateau = Plateau(5, 5) # Initialisiere Plateau
self.mission_control.rover.Position = (0, 0) # Setze die Startposition des Rovers self.plateau.add_obstacle(1,1)
self.mission_control.rover.heading = 0 # Setze die Startausrichtung des Rovers self.plateau.add_obstacle(3,3)
self.mission_control.rover.path = [(0, 0)] self.plateau.move(0, 0) # Setze die Startposition des Plateaus
self.mission_control.rover_heading_path = [0] self.telescope = Telescope(self.plateau) # Initialisiere Teleskop mit Plateau
self.mission_control.mars.plateau.obstacles = set() # Initialisiere Hindernisse (falls benötigt) 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): def test_move_forwward_once(self):
...@@ -172,15 +194,15 @@ class TestRoverMovment(unittest.TestCase): ...@@ -172,15 +194,15 @@ class TestRoverMovment(unittest.TestCase):
def test_obstacle_in_command_sequence(self): def test_obstacle_in_command_sequence(self):
self.mission_control.rover.Position = (0, 0) 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.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): 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.mars.plateau.obstacles = []
self.mission_control.send_commands("F") 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. # ---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.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): ...@@ -256,6 +278,44 @@ class TestRoverMovment(unittest.TestCase):
print(feedback) print(feedback)
self.assertIn("Erfolgreich ausgeführte Befehle: F, B", 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__': if __name__ == '__main__':
... ...
......
File moved
File moved
File moved
File moved
File moved
File moved
File moved
File moved
File moved
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please to comment