{
"llm" : {
"feedback" : "# Exercise: address\n\n### Correctness\n- In `getCity()` prüfst du `city.isEmpty()` und wirfst ggf. eine `IllegalArgumentException`; ein Getter soll hier gemäss Aufgabenstellung keine Argumente validieren (es gibt ja keine) und kann zudem bei `city == null` eine `NullPointerException` auslösen. Die Invarianten sollen im Konstruktor und in den Settern erzwungen werden.\n\n### Suggestion\n- Verschiebe die Logik zur Sicherstellung von `city != null` und `!city.isEmpty()` vollständig in Konstruktor und `setCity(...)`, und lass den Getter einfach den gespeicherten Wert zurückgeben (ohne zusätzliche Prüfungen).\n\n### Code Style\n- Du hast die gleiche Validierungslogik mehrfach (z.B. für `street`/`city` und `zipCode`) in Konstruktor und Settern; überlege dir eine private Hilfsmethode, um Duplikate zu vermeiden und Änderungen zentral zu halten.\n- Die Fehlermeldung bei `zipCode` sagt „muss positiv sein“, geprüft wird aber „vierstellig“ (1000–9999); passe die Message an die tatsächliche Regel an, damit sie klarer ist.\n\n\n# Exercise: timespan\n\n### Correctness\n- Im Konstruktor fehlen sinnvolle Preconditions: Negative Startwerte für `hours`/`minutes` werden nicht direkt verhindert, obwohl `totalMinutes >= 0` gefordert ist.\n- In `add` prüfst du `totalMinutes() < 0` vor dem Addieren; damit verhinderst du keine negativen Parameter und erfüllst die Precondition für `add` nicht zuverlässig (Zeitspanne darf nicht verkürzt/negativ werden).\n- Die Bedingung `if(totalMinutes() >= this.minutes)` ist fachlich nicht die geforderte Invariante `totalMinutes >= old(totalMinutes)` und kann Verlängerungen fälschlich verhindern bzw. Verkürzungen nicht sauber abfangen.\n- `0 ≤ getMinutes ≤ 59` wird nicht in allen Fällen garantiert: Wenn `minutes` nach dem Addieren negativ wird, korrigiert `checkMinutes()` das nicht so, dass `getMinutes()` am Ende sicher im Bereich 0..59 liegt.\n- In `checkMinutes()` ist der Zweig für `this.minutes < 0` logisch falsch/unvollständig (du passt Stunden an, aber Minuten bleiben negativ), dadurch bleibt die beobachtbare Invariante verletzt.\n\n### Suggestion\n- Überlege dir für Konstruktor und `add` jeweils: Welche Eingaben müssen verboten sein, damit `totalMinutes` niemals negativ wird und nach `add` nicht kleiner als vorher? Prüfe diese Bedingungen anhand der *Parameter* bzw. anhand von *alt vs. neuem* `totalMinutes`.\n- Für die “nicht verkürzen”-Regel hilft es, vor dem Ändern den alten Gesamtwert zu merken und nach dem geplanten Addieren zu vergleichen, statt `totalMinutes()` mit `this.minutes` zu vergleichen.\n- Stell sicher, dass die Normalisierung der Minuten (Übertrag in Stunden) immer so endet, dass `minutes` im Bereich 0..59 ist—auch wenn die Eingaben ungültig sind solltest du eher vorher abbrechen (Precondition) als nachher “reparieren”.\n- In der Negativ-Minuten-Korrektur: Wenn du Minuten “ausleihst”/anpasst, muss am Ende sowohl `hours` als auch `minutes` konsistent sein, sonst bleibt `getMinutes()` negativ.\n\n### Code Style\n- `this.totalMinutes();` in `add` hat keinen Effekt (Rückgabewert wird ignoriert) und kann entfernt werden.\n- Fehlermeldung `\"negativ\"` ist wenig aussagekräftig; nutze eine klarere Message, die sagt *welcher* Wert/Parameter ungültig ist.\n- `checkMinutes()` mischt Korrekturlogik für `>= 60` und `< 0`; das macht es schwer zu verstehen/testen. Besser wäre eine klar definierte Normalisierung (und für negative Werte konsequent per Exception statt “Fix”).\n\n\n# Exercise: asteroids\n\n### Correctness\n- Du hältst den Falcon nicht **im Spielfeld**, sondern lässt ihn bei Über-/Unterschreiten der Grenzen **auf die andere Seite “springen”** (Wrap-around). Gefordert ist, dass er immer innerhalb der Spielfeldgrenzen bleibt.\n- Die Grenzen sind bei dir **hart codiert** (`500`, `20`, `800`, `10`) und nicht als **zusätzliche Attribute für die Spielfeldbegrenzung** modelliert, wie in der Aufgabe verlangt.\n- Eine **Klasseninvariante**, welche die Position des Falcons einschränkt, ist nicht definiert/abgebildet (z.B. als klarer Zustand, der nach Konstruktor/`move` immer gelten muss).\n- Die weiteren Aufgabenteile (Klasse `Asteroid`, Asteroiden spawnen/entfernen, Kollisionserkennung, Game-Over) sind nicht implementiert.\n\n### Suggestion\n- Statt die Position auf die andere Seite zu setzen, überlege dir, wie du `x` und `y` nach dem Bewegen so begrenzen kannst, dass sie **nie kleiner als die minimale Grenze und nie grösser als die maximale Grenze** werden.\n- Nimm die Spielfeldgrenzen als **Felder im Falcon** (z.B. min/max für x/y) auf, und setze sie über den Konstruktor oder über sinnvolle Konstanten, sodass die Invariante überhaupt formuliert werden kann.\n- Formuliere für dich explizit die Invariante (z.B. “nach jedem öffentlichen Methodenaufruf gilt …”) und stelle sicher, dass `move()` diese Invariante **immer** wiederherstellt.\n- Für die restlichen Teile: fang mit einer einzelnen `Asteroid`-Instanz an (wie im Tipp), dann erst Array/Spawning/Entfernen, und zuletzt `collidesWith` mit der Distanzformel und Abbruch der Hauptschleife.\n\n### Code Style\n- Vermeide “Magic Numbers” wie `500`, `20`, `800`, `10`; nutze benannte Konstanten/Felder, damit klar ist, welche Grenze was bedeutet.\n- `System.out.println` in `move()` macht die Spielschleife sehr laut/slow; Debug-Ausgaben lieber entfernen oder nur gezielt aktivieren.\n- Die Einrückung/Leerzeilen sind teils unnötig (z.B. im Konstruktor); einheitlicher Stil hilft beim Lesen.\n\n\n# Exercise: bosses\n\n### Correctness\n- In `findCommonSuperiorWith(other)` verwendest du beim ersten Vergleich `commonSuperior.equals(superior)`. Da `Employee` kein eigenes `equals` überschreibt, ist das zwar aktuell identisch zu `==`, aber deine übrige Logik arbeitet sonst konsequent mit Referenz-Identität (`==`). Das ist inkonsistent und kann zu falschem Verhalten führen, falls später `equals` implementiert wird (oder wenn die Aufgabe eigentlich explizit Objektidentität meint).\n\n### Suggestion\n- Entscheide dich in `findCommonSuperiorWith` für **eine** Vergleichsstrategie (entweder überall Identität oder überall `equals`) und zieh sie konsequent durch. Überlege dabei, was in dieser Hierarchie gemeint ist: „gleiche Person“ normalerweise als **gleiches Objekt** (Referenz), nicht „gleicher Name“.\n\n### Code Style\n- `import java.util.ArrayList;` und die ganze Liste ist für diese Aufgabe nicht nötig; die Aufgabenbeschreibung zielt auf eine sequentielle Suche entlang der `boss`-Kette ab. Eine Lösung ohne zusätzliche Datenstruktur ist hier typischer und einfacher zu begründen (Stichwort Schleifeninvariante).\n- Benennung: `commonSuperior` ist in der ersten Phase eigentlich nicht „common“, sondern der aktuelle Kandidat entlang der `this`-Kette. Ein neutralerer Name (z.B. „current“) würde die Lesbarkeit verbessern.\n- Du hast ein `if(this == other) return this;` am Anfang von `findCommonSuperiorWith`, das ist ok, aber es ist redundant, weil deine spätere Logik den Fall auch abdecken könnte (weniger Sonderfälle = leichter nachvollziehbar).\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(); ... }`), verlangt ist aber **genau eine (beliebige) Lampe pro Bedroom**.\n- `nightMode`: In der Hallway wird keine Lampe eingeschaltet; du setzt dort zwar teils die Helligkeit (`if(room == findHallway()) lamp.setBrightness(0.3);`), aber die Lampen bleiben durch das vorherige `lamp.turnOff()` aus.\n- `nightMode`: „Alle anderen Lampen werden ausgeschaltet“ ist durch die verschachtelten Schleifen nicht sauber sichergestellt, weil du Lampen mehrfach (und abhängig von `room != rb`) an/aus schaltest; das führt leicht dazu, dass am Ende unerwartete Lampen an bleiben bzw. falsche Zustände entstehen.\n- `findBedrooms`: Das Rückgabe-Array darf laut Aufgabe **maximal so gross wie die Gesamtanzahl der Räume** sein und **darf grösser als nötig sein und null-Einträge enthalten**. Du gibst aber ein Array **genau in Treffergröße** zurück; das erfüllt die Aussage „darf“ zwar, aber falls in eurer Aufgabenstellung/Tests explizit mit „kann null-Einträge enthalten“ gerechnet wird, könnte deine Variante nicht passen.\n\n### Suggestion\n- `nightMode`: Denk die Aufgabe in zwei klaren Phasen: (1) Zuerst wirklich **alles ausschalten**, (2) dann in den ausgewählten Räumen (Hallway + alle Bedrooms) **jeweils genau eine Lampe auswählen** (z.B. die erste im Array) und nur diese einschalten und auf 0.3 setzen.\n- `nightMode`: Vermeide es, innerhalb der „alle Räume“-Schleife wieder über alle Bedrooms zu iterieren. Besser: Hole dir einmal `hallway` und einmal `bedrooms` und arbeite diese strukturiert ab, damit du nicht Zustände gegenseitig überschreibst.\n- `nightMode`: Wenn du die Hallway behandelst, stelle sicher, dass du dort **auch wirklich eine Lampe einschaltest** (nicht nur Brightness setzen).\n- `findBedrooms`: Falls du auf Nummer sicher gehen willst bezüglich der genauen Aufgabenformulierung: Überlege, ob du ein Array in Größe `rooms.length` zurückgeben willst und die gefundenen Bedrooms vorne einträgst (Rest bleibt `null`).\n\n### Code Style\n- Viele Debug-`System.out.println` in `getLampByName` (und die Methode selbst) wirken wie übrig gebliebenes Test-/Hilfscode und gehören nicht zur Aufgabenlösung.\n- `HashMap lampDirectory` wird für die geforderten Methoden nirgends benötigt und erhöht unnötig Komplexität/Zustand in `Home`.\n- In `randomize` erzeugst du für jede Lampe ein neues `Random`-Objekt; üblich ist, **ein** `Random` zu erstellen und wiederzuverwenden.\n- Unbenutzte Variablen in `nightMode` (`isOn`, `isOnB`) sowie doppeltes Ausschalten (erst Hallway-Lampen aus, später sowieso alle Lampen aus) machen den Code schwerer lesbar.\n- Sehr tiefe Verschachtelung in `nightMode`; hier wären kleine Hilfsmethoden (z.B. „alle ausschalten“, „eine Lampe in Raum einschalten mit Brightness“) deutlich klarer.\n",
"status" : "SUCCESS"
}
}