diff --git a/Semesterprojekt/docs/enhancement-ideas.md b/Semesterprojekt/docs/enhancement-ideas.md index 903a5c3..432d408 100644 --- a/Semesterprojekt/docs/enhancement-ideas.md +++ b/Semesterprojekt/docs/enhancement-ideas.md @@ -26,6 +26,19 @@ alle Phasen 1–7 grün. Ziel: deutlich mehr Tiefe und Politur. - **GUI (Swing)**: mehr als ein `JTextArea` – Farben, Stile, evtl. Panels, Statusanzeige, Bilder/Icons. +**Festgelegt (Zielbild Konsole):** Stufe **B als Baseline** (Boxed Heading, +gelabelte Sektionen, persistente HUD-Zeile: Ort · Gold · Zug · Licht), **ASCII-Art +nur für große Momente** (Spielstart, Finale, Schlüsselräume). Semantische +Farb-Rollen: Items / NPCs / Exits / Heading / Gefahr. + +**Designprinzipien:** +- **Nicht überladen / Progressive Disclosure** – Raumeintritt zeigt nur das + Wesentliche (Ort, kurze Beschreibung, Auffälliges); Details auf Abruf + (`examine`, `look`). +- **Info auf Regionen verteilen statt Text stapeln** – die **Karte ersetzt die + „Exits:"-Zeile**. GUI: persistentes Map-Panel macht die Exit-Zeile überflüssig. + Konsole: kompakte Mini-Map (bei `map` bzw. knapp beim Raumeintritt). + ### 2. Nerd Fonts / Glyphen – das Installationsproblem - Nerd-Font-Glyphen (Icons) sehen gut aus, müssen aber auf dem System des diff --git a/Semesterprojekt/docs/superpowers/specs/2026-05-31-presentation-layer-design.md b/Semesterprojekt/docs/superpowers/specs/2026-05-31-presentation-layer-design.md new file mode 100644 index 0000000..e73738e --- /dev/null +++ b/Semesterprojekt/docs/superpowers/specs/2026-05-31-presentation-layer-design.md @@ -0,0 +1,222 @@ +# Spec: Präsentations-/Ausgabe-Schicht (Teilprojekt 1) + +Stand: 2026-05-31. Erstes Teilprojekt aus [enhancement-ideas.md](../../enhancement-ideas.md). +Baut auf der v1.0-Baseline (Tag `v1.0`) auf. + +## 1. Kontext & Ziel + +`GameIO` bietet aktuell nur `readLine()` + `write(String)`; beide Frontends +(`ConsoleIO`, `SwingIO`) schieben rohen Text durch. Ziel: **reichere, strukturierte +Ausgabe** in beiden Modi, ohne den für beide Frontends **identischen Game-Loop** +aufzugeben (Kernwert der Architektur). + +Zielbild (bestätigt im Brainstorming): +- Konsole: **Stufe B** – Boxed Heading, gelabelte Sektionen, persistente HUD-Zeile; + ASCII-Art nur für große Momente. +- GUI ist der **Fokus** (mehr Freiheit), Konsole wird weiter unterstützt. +- Semantische Farb-Rollen für Items / NPCs / Exits / Headings / Gefahr. +- **Progressive Disclosure** (nicht überladen) und **Info auf Regionen verteilen** + (Karte ersetzt später die Exit-Zeile). + +## 2. Scope + +**In Scope:** +- Semantisches Ausgabe-Modell (`Style`, `Span`, `StyledText` + Builder). +- High-Level-Views: `RoomView`, `Hud`. +- Erweiterung der `GameIO`-Schnittstelle (additiv, `write(String)` bleibt als Default). +- `ConsoleIO` als Renderer: ANSI-Farben + Box-Drawing (Stufe B), HUD-Zeile, + ASCII-Art-Banner-Mechanismus, gestufte Glyph-Fähigkeit. +- `SwingIO` als Renderer: Region-Layout (HUD oben, Output mittig, Seitenpanel + rechts reserviert, Input unten), `JTextPane`/`StyledDocument`, **gebündelter Font**. +- Migration der bestehenden Commands auf die neue API; `TestIO` angepasst. + +**Out of Scope (jeweils eigene spätere Specs):** +- Tatsächliches Zeichnen der **Karte** (Teilprojekt 2) – Seitenpanel ist nur Slot, + zeigt bis dahin die Exit-Liste. +- **Hauptmenü/Settings** (6), **Speichern/Laden** (7), **Musik** (8). +- Neue **Inhalte/Mechaniken** (Quests, Licht, Item-Kombination). + +Die Schnittstellen lassen bewusst Slots (Seitenpanel, HUD-Felder) für diese +späteren Teile. + +## 3. Architektur (Approach 2) + +**Commands erzeugen Bedeutung, kein Format.** Ein Command baut ein semantisches +Objekt (`StyledText` oder eine View) und übergibt es an `GameIO`. Jedes Frontend +**rendert** es selbst: `ConsoleIO` → ANSI/Box-Drawing, `SwingIO` → Swing-Komponenten +und **eigenes Layout**. Der Game-Loop bleibt unverändert. + +```mermaid +flowchart LR + CMD["Command
(z.B. LookCommand)"] -- "baut" --> VIEW["RoomView / StyledText / Hud
(semantisch, kein Format)"] + VIEW -- "GameIO.showRoom() / print() / setHud()" --> IO{{"GameIO"}} + IO --> CON["ConsoleIO
ANSI + Box-Drawing"] + IO --> GUI["SwingIO
JTextPane + Panels"] +``` + +## 4. Komponenten & API + +Neues Subpackage `io.text` für das Modell **und** die Views (`Style`, `Span`, +`StyledText`, `RoomView`, `Hud`); die Renderer (`ConsoleIO`, `SwingIO`) bleiben in `io`. + +### 4.1 Style (enum) + +```java +public enum Style { PLAIN, HEADING, ITEM, NPC, EXIT, DANGER, DIM } +``` + +Kleines, bewusst begrenztes Rollen-Set. Mapping auf konkrete Farben/Attribute +liegt im jeweiligen Renderer, nicht am Style. + +### 4.2 Span & StyledText + +```java +public record Span(String text, Style style) {} + +public final class StyledText { + private final List spans; // immutable + public List spans() { ... } + public String plainText() { ... } // Spans konkateniert, ohne Format + + public static StyledText of(String s) { ... } // ein PLAIN-Span + public static Builder builder() { ... } + + public static final class Builder { + Builder plain(String s); Builder heading(String s); + Builder item(String s); Builder npc(String s); + Builder exit(String s); Builder danger(String s); + Builder dim(String s); StyledText build(); + } +} +``` + +Beispiel: +```java +io.print(StyledText.builder() + .plain("You pick up ").item("the brass lamp").plain(".").build()); +``` +Zeilenumbrüche stehen als `\n` im Text der Spans. + +### 4.3 Views + +```java +public record RoomView(String name, String description, + List items, List npcs, + List exits) {} + +public record Hud(String location, int gold, int turn, boolean lightOn) {} +``` + +Views tragen bereits **anzeigefertige Strings** (Namen aufgelöst), aber **kein +Layout**. `RoomView.exits` versorgt vorerst das GUI-Seitenpanel; sobald Teilprojekt 2 +die Karte zeichnet, blendet der GUI-Renderer die Exit-Sektion aus. + +### 4.4 GameIO (erweitert, additiv) + +```java +public interface GameIO { + String readLine(); + void print(StyledText text); // gestylter Ausgabe-Block + void showRoom(RoomView room); // High-Level-Raumansicht + void setHud(Hud hud); // HUD-Region aktualisieren + + default void write(String s) { // Komfort + Rückwärtskompatibilität + print(StyledText.of(s)); + } +} +``` + +`write(String)` bleibt als Default → bestehende Aufrufstellen kompilieren weiter; +Migration kann schrittweise erfolgen. + +### 4.5 ConsoleIO (Renderer) + +- `print`: Spans → ANSI-Sequenzen (Rollen→Farbe), dann `println`. +- `showRoom`: Stufe-B-Layout mit Box-Drawing-Rahmen (Heading + Sektionen + „You see / Here is / Exits"), Rollen-Farben. +- `setHud`: dim gefärbte Statuszeile (`[ Kitchen · 0 gold · turn 7 · light: off ]`). +- **ASCII-Art-Banner**: Methode/Helfer für große Momente (Start, Finale); Kunst aus + Ressourcen geladen. Mechanismus in Scope, konkrete Kunstwerke folgen mit Inhalten. +- **Konfiguration** (Defaults sicher, Verdrahtung mit Settings-Menü später): + - `ColorMode`: an/aus; Auto-Erkennung (`System.console() == null` → keine ANSI). + - `GlyphMode`: `ASCII | UNICODE | GLYPH`, Default `UNICODE` (Box-Drawing breit + unterstützt; Nerd-Glyphen nur bei explizitem Opt-in). Bei `ASCII` degradieren + die Rahmen auf `+`, `-`, `|` statt der Unicode-Box-Drawing-Zeichen. + +### 4.6 SwingIO (Renderer) + Layout + +Region-Layout (bestätigt, Variante A): +- **NORTH**: HUD-Leiste (`JPanel` mit `JLabel`s) – Ort · Gold · Zug · Licht. +- **CENTER**: `JTextPane` mit `StyledDocument` (Farben/Stile via `AttributeSet` pro + `Style`), scrollbar. +- **EAST**: Seitenpanel, reserviert für Karte; zeigt bis dahin `RoomView.exits` als Liste. +- **SOUTH**: Eingabefeld (bestehende `LinkedBlockingQueue`-Brücke bleibt). + +**Gebündelter Font:** `.ttf` unter `src/main/resources/fonts/`, via +`Font.createFont(Font.TRUETYPE_FONT, stream)` geladen und registriert → Farben und +**Glyphen funktionieren ohne Installation auf dem Spieler-System**. Fallback auf +`Font.MONOSPACED` bei Ladefehler (geloggt). + +`print`/`showRoom` schreiben gestylte Spans in das `JTextPane`; `setHud` aktualisiert +die Labels. Alle Swing-Mutationen via `SwingUtilities.invokeLater` (wie bisher). + +## 5. Datenfluss + +``` +Command → baut RoomView/StyledText/Hud → GameIO.{showRoom|print|setHud} + → Frontend-Renderer → Konsole (ANSI) bzw. GUI (Swing) +``` +Game-Loop, Parser, Registry, Domain: **unverändert**. + +## 6. Nerd-Font / Glyph-Strategie (zusammengefasst) + +- **GUI**: Font mitliefern (bundled `.ttf`) → Problem gelöst, keine Installation nötig. +- **Konsole**: Font nicht kontrollierbar → **gestufte Fallbacks** (`ASCII` → + `UNICODE`-Box-Drawing → `GLYPH`). Default `UNICODE`. Keine harte Abhängigkeit von + installierten Nerd Fonts. + +## 7. Migration der Commands & Tests + +- `LookCommand`: statt `StringBuilder` eine `RoomView` bauen → `io.showRoom(view)`. +- Übrige Commands (`Take`, `Drop`, `Use`, `Read`, `Examine`, `Talk`, `Give`, + `Inventory`, `Help`): `io.print(StyledText…)` mit Rollen, wo es Mehrwert bringt; + sonst genügt das Default-`write(String)`. Schrittweise, nicht Big-Bang. +- `TestIO`: implementiert `print`/`showRoom`/`setHud` durch **Flattening auf + Klartext** (`StyledText.plainText()` bzw. RoomView→Textblock), abgelegt in + `outputs`. `lastOutput()`/`allOutput()` liefern weiterhin Klartext → die + bestehenden `.contains(...)`-Assertions der 67 Tests bleiben gültig. + +## 8. Fehlerbehandlung + +| Fall | Verhalten | +|---|---| +| Gebündelter Font nicht ladbar | Log-Warnung, Fallback `Font.MONOSPACED` | +| Terminal ohne ANSI / Umleitung | Auto-Erkennung → Farben aus, reiner Text | +| `GlyphMode=GLYPH` ohne passende Terminal-Font | Nutzer-Opt-in; kein Auto-Fallback nötig, Default bleibt `UNICODE` | +| `null`-Text an `StyledText.of` | `IllegalArgumentException` (wie bestehende Konventionen) | + +## 9. Testing-Strategie + +- **Unit**: `StyledText`-Builder & `plainText()`, `Span`, Immutabilität von + `RoomView`/`Hud`. +- **ConsoleIO**: Rendern einer bekannten `RoomView`/`Hud` mit Farbe AUS gegen einen + `StringWriter`/`PrintStream` (Test-Konstruktor existiert bereits) → strukturelle + Assertions (Heading, Labels, Exit-Namen). +- **Command-Tests**: laufen unverändert über das angepasste `TestIO` (Klartext). +- **SwingIO**: nicht unit-getestet (EDT/Swing); Logik dünn halten, manueller + Smoke-Test. Verifikation per `mvn exec:java@gui`. + +## 10. Handoffs an spätere Teilprojekte + +- **Karte (2)**: GUI-Seitenpanel + künftige `showMap(MapView)`-Methode; + `RoomView.exits` ist bis dahin Platzhalter-Quelle. +- **Menü/Settings (6)**: verdrahtet später `ColorMode`/`GlyphMode`/Lautstärke. +- **Save (7)**, **Musik (8)**: nutzen die HUD/Region-Slots, hier nicht implementiert. + +## 11. Offene Detailfragen (in Implementierung entscheidbar) + +- Konkrete Wahl des gebündelten Fonts (freier Monospace bzw. Nerd-Font-Variante, + Lizenz prüfen). +- Exakte ANSI-Farbpalette pro Rolle. +- Ob `Hud` schon ein `lightOn` führt, obwohl die Licht-Mechanik erst mit den Inhalten + kommt → Feld vorsehen, vorerst konstant `false`/ausgeblendet.