{
"llm" : {
"feedback" : "# Exercise: address\n\n### Correctness\n- In `getCity()` wirfst du eine `IllegalArgumentException`, wenn `city` leer ist; laut Aufgabenstellung sollen Konstruktor und Setter bei ungültigen Argumenten werfen, nicht die Getter.\n\n### Suggestion\n- Überlege, wo die Invarianten „erzwingend“ geprüft werden müssen, damit der Objektzustand nach dem Setzen/Konstruieren immer gültig bleibt, und ob ein Getter überhaupt jemals „validieren“ sollte, wenn Setter/Konstruktor korrekt arbeiten.\n\n### Code Style\n- Du hast die gleichen Validierungschecks mehrfach (Konstruktor + Setter). Das lässt sich oft durch Wiederverwendung reduzieren (z.B. indem der Konstruktor intern die Setter nutzt oder eine private Validierungsmethode verwendet), damit Änderungen nur an einer Stelle nötig sind.\n- In den Fehlermeldungen bei `zipCode` steht „muss positiv sein“, die eigentliche Bedingung ist aber „vierstellig“; eine präzisere Message wäre hilfreicher.\n\n\n# Exercise: timespan\n\n### Correctness\n- Im Konstruktor prüfst du `totalMinutes()` bevor `hours`/`minutes` überhaupt gesetzt wurden; damit werden die Preconditions nicht korrekt auf den übergebenen Parametern geprüft.\n- Die Precondition „`totalMinutes >= 0`“ wird nicht sauber durchgesetzt: Negative Kombinationen wie `hours = -1, minutes = 30` können je nach Reihenfolge/Checks durchrutschen bzw. werden nicht eindeutig anhand der Parameter bewertet.\n- In `add()` setzt du die Invariante „Zeitspannen können nur verlängert werden“ nicht korrekt um: `saveMin` wird nur in `totalMinutes()` aktualisiert und vor dem Addieren nicht zuverlässig als „old(totalMinutes)“ festgehalten; außerdem führt das `if (saveMin <= totalMinutes())` praktisch zu keiner sinnvollen Absicherung.\n- `getMinutes()` verletzt die geforderte Invariante `0 ≤ getMinutes ≤ 59`: Wenn `minutes > 59` gibst du `hours + 1` zurück (das ist keine Minutenangabe und kann > 59 sein).\n- `add()` verändert den Zustand auch dann potenziell in unerwarteter Weise, weil du erst nach dem Addieren normalisierst; die Invarianten sollen aber für das von außen beobachtbare Verhalten immer gelten (insb. `getMinutes()`), nicht nur „manchmal nach Korrektur“.\n- `checkMinutes()` behandelt negative Minuten in einer Weise, die die Aufgabe gar nicht vorsieht (Zeitspanne darf nicht negativ werden) und kann zu falschen Stundenanpassungen führen (insbesondere wegen Integer-Division bei negativen Zahlen).\n\n### Suggestion\n- Prüfe im Konstruktor die *Parameter* (`hours`, `minutes`) bzw. deren berechnete Gesamtminuten direkt, bevor du irgendetwas am Objektzustand änderst.\n- Für „nur verlängern“ brauchst du in `add()` einen klaren Vergleich zwischen „alte Gesamtminuten“ und „neue Gesamtminuten (alt + delta)“. Überlege dir, wann du den alten Wert speicherst und woraus du den neuen Wert berechnest.\n- Sorge dafür, dass die Normalisierung (Minuten in den Bereich 0..59 umrechnen und Stunden entsprechend erhöhen) so umgesetzt ist, dass `getMinutes()` immer einfach `minutes` zurückgeben kann.\n- Entferne Logik in `getMinutes()`, die Stunden zurückgibt; die Methode soll wirklich nur den Minutenanteil liefern. Wenn Minuten > 59 vorkommen, ist das ein Hinweis, dass du vorher normalisieren musst.\n- Wenn negative Stunden/Minuten in `add()` verboten sind, brauchst du keine nachträgliche Korrektur für negative Minuten in `checkMinutes()`; setze stattdessen klare Preconditions.\n\n### Code Style\n- `saveMin` als veränderliches Feld für „old total minutes“ ist verwirrend und fehleranfällig, weil `totalMinutes()` nebenbei den Zustand verändert; besser wären reine Berechnungen ohne Seiteneffekte.\n- `System.out.println(totalMinutes());` im Konstruktor ist Debug-Ausgabe und gehört nicht in die finale Klasse.\n- Die mehrfachen, teils redundanten `if`-Checks im Konstruktor (inkl. leerer `IllegalArgumentException()` ohne Nachricht) erschweren das Verständnis; formuliere lieber wenige, klare Preconditions mit konsistenter Fehlermeldung.\n- `checkMinutes()` mischt Korrektur für positive und negative Minuten; das macht die Methode unnötig kompliziert für diese Aufgabe.\n\n\n# Exercise: asteroids\n\n### Correctness\n- Teil a verlangt, dass der Falcon *im Spielfeld bleibt* (Begrenzung / Invariante). In deiner `move()`-Methode “wrapst” du aber die Position: wenn er links rausgeht, kommt er rechts wieder rein (und umgekehrt; gleiches bei oben/unten). Das ist nicht “im Feld bleiben”, sondern “Teleportieren am Rand”.\n- Die Invariante soll die Position einschränken; aktuell stellst du sie nicht sicher, weil du `x += vx` / `y += vy` schon ausführst, bevor du begrenzt. Damit ist der Objektzustand kurzzeitig ausserhalb, was einer sauber formulierten/überprüften Invariante widerspricht.\n- Die Aufgabe b–d (Asteroid-Klasse, Spawning/Entfernen, Kollision + Game Over) sind in deinem Attempt nicht umgesetzt.\n\n### Suggestion\n- Überlege dir den Unterschied zwischen “clampen” und “wrappen”: “im Spielfeld bleiben” bedeutet typischerweise, dass `x`/`y` am Rand festgehalten werden (nicht auf die gegenüberliegende Seite springen).\n- Versuch, die Positionsänderung so zu strukturieren, dass `x` und `y` nie einen ungültigen Wert annehmen (z.B. erst neue Werte berechnen, dann begrenzen, dann erst zuweisen).\n- Für die fehlenden Teile: fang klein an (ein einzelner Asteroid im Spiel), dann erweitere auf mehrere (Array/Collection + zufälliges Erzeugen), danach Entfernen beim Verlassen unten, und zuletzt eine Kollisionsmethode, die pro Frame geprüft wird.\n\n### Code Style\n- Die Borders sind als `int`-Felder in jeder Falcon-Instanz gespeichert; das wirkt wie “Konstanten” und könnte klarer als `static final` oder als Parameter aus dem Game kommen (damit WIDTH/HEIGHT nicht “hart” im Falcon verdrahtet sind).\n- `borderTop=760` und `borderBottom=5` sind verwirrend benannt (Top ist normalerweise klein/0, Bottom gross/HEIGHT). Das macht die Bedingungen schwer lesbar.\n- `System.out.println` in `move()` erzeugt sehr viel Konsolen-Output im Game-Loop und stört beim Spielen; Debug-Ausgaben besser entfernen oder nur temporär nutzen.\n- In `move()` verwendest du `double newX = x += vx;` – das mischt Seiteneffekt und neue Variable in einer Zeile und macht es unnötig schwer zu lesen/debuggen.\n\n\n# Exercise: bosses\n\n### Correctness\n- In `findCommonSuperiorWith(other)` prüfst du in der ersten Schleife `if (commonSuperior == superior)` und gibst dann `commonSuperior` zurück, obwohl `commonSuperior` zu diesem Zeitpunkt immer noch `this` ist. Das führt dazu, dass du fälschlicherweise `this` zurückgibst, wenn `other` irgendwo in der Boss-Kette von `other` auf `this` trifft (also wenn `this` Vorgesetzte*r von `other` ist), statt den tatsächlich gefundenen Knoten (`superior`) bzw. den korrekten gemeinsamen Vorgesetzten zurückzugeben.\n\n### Suggestion\n- Schau dir in der ersten `while(superior != null)`-Schleife von `findCommonSuperiorWith` an, welche Variable sich wirklich entlang der Boss-Kette von `other` bewegt (und welche nicht). Überlege dann: Wenn du in dieser Schleife einen Treffer feststellst, welches Objekt ist dann der gemeinsame Vorgesetzte, den du zurückgeben möchtest?\n\n### Code Style\n- `ArrayList<Employee> bosses = new ArrayList<Employee>();` kann idiomatischer als `new ArrayList<>()` geschrieben werden (Diamond Operator).\n- `bosses.contains(commonSuperior)` ist bei `ArrayList` eine lineare Suche; das ist für kleine Daten ok, kann aber bei langen Ketten unnötig teuer werden. Eine `Set`-Struktur wäre hier typischer, falls Performance relevant ist.\n- Die frühe Sonderbehandlung `if (this == other)` ist in beiden Methoden ok, aber bei `findCommonSuperiorWith` wäre sie nicht zwingend nötig, wenn die restliche Logik sauber auf „jede Person ist ihr eigener Boss“ ausgerichtet ist (reduziert Sonderfälle).\n\n\n# Exercise: smarthome\n\n### Correctness\n- `nightMode`: Du schaltest in den Bedrooms aktuell **alle Lampen** ein (innere Schleife `for (Lamp lb : rb.getLamps()) { lb.turnOn(); ... }`), gefordert ist aber **pro Bedroom genau eine (beliebige) Lampe**.\n- `nightMode`: In der Hallway wird bei dir **keine Lampe eingeschaltet**; du setzt höchstens Helligkeit auf 0.3, aber ein `turnOn()` für genau eine Hallway-Lampe passiert nicht.\n- `nightMode`: Du verwendest `findHallway()` zwar, rufst es aber innerhalb der Lampen-Schleifen wiederholt auf und vergleichst mit `==`. Das ist hier besonders kritisch, weil deine Logik dadurch nicht zuverlässig “Hallway genau eine Lampe an, alles andere aus” umsetzt.\n- `findBedrooms`: Laut Aufgabe darf das zurückgegebene Array **größer als nötig** sein und `null` enthalten (max. Anzahl Räume). Dein Array ist immer exakt passend groß; das erfüllt die “darf”-Bedingung zwar, aber wenn die Tests explizit ein Array der Hausgröße erwarten, würdest du scheitern (die Spezifikation lässt beide Varianten zu, aber Aufgaben dieser Art testen manchmal genau das).\n\n### Suggestion\n- Für `nightMode`: Denk in zwei Phasen: (1) wirklich **alles** im ganzen Haus ausschalten, (2) dann gezielt in **Hallway** eine Lampe auswählen und einschalten + Helligkeit 0.3, und für **jedes Bedroom** ebenso genau eine Lampe.\n- Für “genau eine Lampe” pro Raum: Du brauchst pro betroffenen Raum eine Entscheidung wie “nimm die erste Lampe im Array” (oder irgendeine andere feste Wahl) und bearbeite nur diese eine – nicht über alle Lampen iterieren und alle einschalten.\n- Für Hallway-Erkennung: Speichere das Ergebnis von `findHallway()` einmal in einer Variable und arbeite damit weiter, statt es in inneren Schleifen dauernd neu aufzurufen.\n- Falls `findBedrooms` bei dir getestet wird auf “Array-Länge = rooms.length”: Überlege, ob du das Ergebnis-Array in Hausgröße anlegst und die gefundenen Bedrooms nur vorne einträgst (Rest bleibt `null`), statt ein exakt passendes Array zu bauen.\n\n### Code Style\n- In `Home` sind `import java.util.*;` und Debug-`System.out.println(...)` in `getLampByName` unnötig für die Aufgabe und machen die Ausgabe noisy; besser entfernen.\n- `lampDirectory` und `getLampByName` gehören nicht zu den geforderten Methoden und lenken ab (und `getLampByName` wird nirgends genutzt).\n- In `randomize` erzeugst du innerhalb der Lampen-Schleife jedes Mal ein neues `Random`-Objekt (`new Random()`); üblich ist, ein einziges `Random` wiederzuverwenden.\n- In `nightMode` hast du unbenutzte Variablen (`isOn`, `isOnB`, `Room r`/`Lamp[] l1`-Block ist redundant, da du später sowieso alles ausschaltest). Das erschwert das Lesen und Verifizieren der Logik.\n",
"status" : "SUCCESS"
}
}