{
"llm" : {
"feedback" : "# Exercise: address\n\n### Correctness\n- Die Invariante für `zipCode` lautet „positiv und vierstellig“; deine Prüfung stellt nur „vierstellig“ sicher, aber nicht explizit „positiv“ (du erlaubst damit z.B. keine negativen vierstelligen Zahlen, aber die Positiv-Bedingung ist nicht separat abgebildet). \n\n### Suggestion\n- Überlege, wie du in `setZipCode` klar und eindeutig beide Bedingungen abprüfst: einmal die Anzahl Ziffern (vierstellig) und zusätzlich „größer als 0“ als eigene Invariante, damit die Anforderungen 1:1 erfüllt sind.\n\n### Code Style\n- In `format()` könntest du direkt auf die Felder zugreifen statt über Getter (ist innerhalb der Klasse üblich), oder konsequent überall Getter verwenden—hauptsache einheitlich.\n- Die Fehlermeldungen sind teils gemischt (Deutsch/Englisch, z.B. „zipCode muss 4 stellig sein“ vs. „Street …“); einheitliche Sprache/Begriffe würden die Lesbarkeit verbessern.\n\n\n# Exercise: timespan\n\n### Correctness\n- Im Konstruktor ist die Precondition für „Zeitspannen sind nie negativ“ nicht korrekt: Durch die Bedingung `(minutes >= 0 && hours >= 0) || hours * 60 + minutes >= 0` erlaubst du Fälle wie `hours = -1, minutes = 120` (totalMinutes = 60), wodurch von außen `getHours()` negativ sein kann, obwohl die Invariante aus Sicht des Clients eine nicht-negative Zeitspanne verlangt.\n- In `add` setzt du die Precondition für „Zeitspannen können nur verlängert werden“ nicht passend um: Du erlaubst negative Parameter, solange `hours*60 + minutes >= 0` ist, und du erlaubst auch Fälle, in denen die Zeitspanne effektiv kleiner wird (z.B. durch negative Stunden und wenige positive Minuten), was gegen `totalMinutes ≥ old(totalMinutes)` verstößt.\n\n### Suggestion\n- Formuliere die Konstruktor-Precondition so, dass nach der Normalisierung (Minuten umgerechnet) die Zeitspanne aus Client-Sicht nicht negativ sein kann; überprüfe dabei insbesondere, ob du negative Stunden überhaupt zulassen willst, selbst wenn die Gesamtminuten am Ende positiv wären.\n- Für `add`: Überlege, welche Bedingung tatsächlich garantiert, dass `totalMinutes()` nach dem Aufruf mindestens so groß ist wie vorher. Eine Prüfung nur auf die Summe der *Parameter* reicht nicht, wenn du gleichzeitig negative Werte zulässt oder intern wieder „ausgleichst“.\n\n### Code Style\n- Die Bedingungen im Konstruktor sind schwer lesbar und redundant (`minutes >= 0 && hours >= 0` vs. `hours*60 + minutes >= 0`); vereinfache sie zu einer klaren, zielgerichteten Precondition.\n- Die Normalisierung der Minuten (while-Schleifen) ist doppelt implementiert (im Konstruktor und in `add`); vermeide Code-Duplikation, z.B. durch Wiederverwendung einer gemeinsamen Logik.\n- `IllegalArgumentException()` ohne Nachricht erschwert das Debugging; eine kurze, präzise Fehlermeldung wäre hilfreicher.\n\n\n# Exercise: asteroids\n\n### Correctness\n- Du hast nur Teil (a) umgesetzt; es fehlen die geforderte Klasse `Asteroid`, das Erzeugen/Bewegen/Zeichnen mehrerer Asteroiden, das Entfernen von Asteroiden beim Verlassen des Spielfelds, sowie die Kollisionserkennung und Game-Over-Anzeige.\n- Für (a) verlangte die Aufgabe zusätzliche Attribute für die Spielfeldbegrenzung **und** eine definierte Klasseninvariante; bei dir sind die Grenzen nur als lokale Variablen (`maxX`, `maxY`) in `move()` vorhanden und keine Invariante ist ersichtlich.\n- Die Spielfeldgrenzen sind in `Falcon` fest auf `512/768` verdrahtet; damit bleibt der Falcon nicht korrekt „im Spielfeld“, falls die tatsächlichen Spielgrössen (Konstanten in `AsteroidsGame`) geändert werden oder das Spielfeld anders initialisiert wird.\n\n### Suggestion\n- Schau dir die Aufgabenteile (b)–(d) an und geh Schritt für Schritt vor: erst eine `Asteroid`-Klasse analog zu `Falcon`, dann in `AsteroidsGame` eine Sammlung/Array von Asteroiden verwalten (spawnen, bewegen, zeichnen), danach das Entfernen unten, und am Schluss die Kollisionsprüfung + Game-Over.\n- Damit (a) wirklich den Anforderungen entspricht: überlege dir, welche Werte zur Spielfeldbegrenzung dauerhaft zum Zustand des `Falcon` gehören sollten (Attribute) und wie du die „Falcon bleibt im Feld“-Bedingung als Invariante formulierst/absicherst (z.B. nach Konstruktor und nach `move()`).\n- Statt die Grenzen im `Falcon` zu „raten“ (512/768), überlege, wie du sie aus `AsteroidsGame` an den `Falcon` übergeben kannst, sodass Falcon und Spielfeldgrössen konsistent bleiben.\n\n### Code Style\n- „Magic numbers“ (`512`, `768`) im `Falcon`: diese Werte sollten nicht im Bewegungs-Code fest codiert sein, sondern als benannte Konstanten/Attribute (und idealerweise nicht doppelt im Projekt vorkommen).\n- Die Hilfsmethode `clamp` ist ok, aber die Logik in `move()` wäre lesbarer, wenn klarer wäre, wofür `maxX/maxY` stehen (z.B. als Felder mit sprechenden Namen statt lokale Variablen).\n\n\n# Exercise: bosses\n\n### Correctness\n- `findCommonSuperiorWith`: Du überspringst bei der inneren Schleife den Fall, dass `other` selbst (also `b` am Anfang) schon gleich `a` ist, weil du zuerst `b = b.getBoss()` machst und erst danach vergleichst. Dadurch kann z.B. `sara.findCommonSuperiorWith(headOfSales)` fälschlich `CEO` statt `headOfSales` liefern.\n- `findCommonSuperiorWith`: Wenn es keinen gemeinsamen Vorgesetzten gibt, soll `null` zurückgegeben werden. Du gibst am Ende `a` zurück, was zwar oft `null` ist, aber das ist eher zufällig durch den Schleifenverlauf – konzeptionell sollte klar `null` zurückkommen, nicht “der aktuelle Schleifenzeiger”.\n\n### Suggestion\n- Für `findCommonSuperiorWith`: Achte darauf, dass “jede Person ihre eigene Vorgesetzte ist”. Das heißt: Vergleiche auch die aktuelle Person `b` (beginnend bei `other`) mit `a`, bevor du zu `b.getBoss()` weitergehst.\n- Für `findCommonSuperiorWith`: Überlege dir, was du genau zurückgeben willst, wenn du einen Treffer findest: den gemeinsamen Vorgesetzten (also `a` bzw. `b` zum Zeitpunkt des Vergleichs), nicht erst nach einem weiteren `getBoss()`-Schritt.\n- Für den Rückgabefall “kein gemeinsamer Vorgesetzter”: Mach den Rückgabewert unabhängig davon, wie deine Schleifenvariable am Ende steht, sondern gib explizit den geforderten Wert zurück.\n\n### Code Style\n- `findCommonSuperiorWith`: Die innere Schleife ist etwas schwer zu lesen, weil du `b` zuerst veränderst und danach vergleichst. Lesbarer ist meist: erst prüfen, dann zum Boss gehen (klarere Kontrollstruktur).\n- `isSuperiorOf`: Du überschreibst den Parameter `other`. Funktional ok, aber als Stil ist es oft verständlicher, eine lokale Laufvariable zu verwenden (z.B. “current”), damit der Eingabeparameter unverändert bleibt.\n\n\n# Exercise: smarthome\n\n### Correctness\n- In `turnNextRoomBright()` ist die Bedingung in der `while`-Schleife in falscher Reihenfolge: Du greifst auf `rooms[i]` zu, bevor geprüft wird, ob `i` noch im gültigen Bereich ist. Das kann bei einem leeren Haus bzw. bei bestimmten Randfällen zu einem Fehler führen.\n- `findBedrooms()` erfüllt die Vorgabe nicht ganz: Laut Aufgabenstellung darf das zurückgegebene Array auch **größer als nötig** sein und **null-Einträge** enthalten, soll aber **maximal** so groß sein wie `rooms.length`. Du gibst dagegen immer ein Array zurück, das **genau** so groß ist wie die Anzahl gefundener Bedrooms und enthält keine `null`s.\n\n### Suggestion\n- Schau dir bei `turnNextRoomBright()` die Auswertungsreihenfolge von `&&` an und stelle sicher, dass ein Index-Check immer passiert, bevor du `rooms[i]` verwendest. Alternativ kannst du die Schleifenstruktur so wählen, dass `rooms[i]` erst im sicheren Bereich gelesen wird.\n- Überlege bei `findBedrooms()`, wie du ein Array mit Länge `rooms.length` füllen könntest und dabei einen separaten Zähler führst, an welche Position du das nächste Bedroom schreibst. So bleiben nicht benutzte Plätze automatisch `null`.\n\n3. Code Style:\n- Das `HashMap<String, Lamp> lampMap` plus `getLampByName()` ist für die gestellten Anforderungen nicht nötig und macht die Klasse unnötig komplex (und erhöht die Gefahr von Inkonsistenzen, falls später Lampen/Rooms geändert würden).\n- `lampMap` sollte mindestens `private` sein (Kapselung); aktuell ist es package-private.\n- In `fullBright()` ist `lamp.getBrightness() >= 1.0` etwas “magisch” (Floating-Point-Vergleich). Besser wäre, semantisch klarer zu prüfen (z.B. exakt 1.0 setzen/erwarten oder mit Toleranz), auch wenn es hier meist funktioniert.\n",
"status" : "SUCCESS"
}
}