Toter Code und ungenutzte APIs in CORE/INPUT #9

Closed
opened 2026-08-31 21:01:56 +02:00 by gilli · 1 comment
Owner

⁨⁩⁨Toter Code und ungenutzte APIs in CORE/INPUT⁩ ⁨⁩#⁨9⁩⁨⁩"
By ⁨⁩⁨gilli⁩⁨⁩ — ⁨⁨⁩Closed⁨⁩⁩
cleanup
low
maintainability

Komponente: CORE, INPUT, GAME
Betroffene Version: main @ 238ed66, index.html

AGENTS.md verlangt „Vermeide unnötige globale Variablen“ und „keine magischen Zahlen, wenn eine
Konstante sinnvoll ist“. Folgende Strukturen sind implementiert, aber nie wirksam – sie erzeugen
den Eindruck implementierter Features, die es nicht sind:

# Fundstelle Zeile(n) Befund
1 nextEdgeAfter(world, x) 485–495, Export 1287 Definiert und aus CORE exportiert, von CORE/RENDER/GAME niemals aufgerufen. Kanten-/Coyote-Logik läuft ausschließlich über groundAt().
2 INPUT.state.pauseEdge 2060 Nie geschrieben, nie gelesen (Pause läuft direkt über hooks.onPause()).
3 INPUT.state.restartEdge 2060 Wie oben (Restart über hooks.onRestart()).
4 INPUT.state.muteEdge 2060 Wie oben (Mute über hooks.onMute()).
5 INPUT.state.focusEdge 2059, Schreibzugriff 2120 Wird gesetzt, aber nie verbraucht – consume() enthält keinen focus-Anteil. Fokus funktioniert nur über den zweiten, separaten Listener in boot() (siehe Issue #8).
6 INPUT.state.pointerHook / cmd.hookGrabTarget 2061, 2084 hookGrabTarget wird in das Commando kopiert, aber von playerCmd() nie gelesen. state.pointerHook wird nie gesetzt (nur in consume() auf null zurückgesetzt). → „Haken direkt anklicken“ ist faktisch ein generischer Greifvorgang; eine gezielte Zielauswahl existiert nicht.
7 hook.disabled 941, 559, 1010 Wird beim Anlegen auf false gesetzt und in findGrab() abgefragt, aber nirgends auf true gesetzt. Der Mechanismus „Haken deaktivieren“ ist tot.
8 KEYMAP-Schlüssel "KeyW Jump" 2102 Kann von keinem Browser erzeugt werden (code ist KeyW, key ist w). Vermutlicher Tippfehler-Überrest; KeyW wird separat für reel behandelt (Zeile 2116).
9 makeBody(...).spin 549 Initialisiert, nie verwendet.
10 CSS-Selektor #countdown 191, 196 Existiert nicht im DOM (richtig wäre #countdownBg); beide Regeln greifen nicht. #countdown .overlay { background:none } ebenso wirkungslos.

Auswirkung

  • Irreführende API: Wer hook.disabled setzt oder auf cmd.hookGrabTarget baut, bekommt
    stillschweigend kein Verhalten.
  • Erschwerte Wartung der Ein-Datei-Struktur, gerade weil die Datei bewusst modular aufgebaut ist.
  • Issue #6 verstößt gegen die Anforderung „Haken direkt anklicken: greifen (wenn erreichbar)“ –
    das Anklicken funktioniert nur, weil danach generisch grab ausgelöst wird; der angeklickte
    Haken wird ignoriert (bei zwei erreichbaren Haken entscheidet findGrab()).

Lösungsvorschlag

  • Ungenutzte Felder/Funktionen entfernen (nextEdgeAfter, *Edge, spin, #countdown-CSS).
  • focusEdge zu einem echten Signal machen (in consume() aufnehmen) und den Doppel-Listener
    entfernen.
  • pointerHook/hookGrabTarget implementieren oder die Dokumentation/Tooltips anpassen, dass
    Anklicken generisch greift.
  • hook.disabled entfernen oder eine Nutzung (z. B. Haken nach grabs > N sperren) einbauen.
  • KEYMAP-Tippfehler bereinigen.

Dokumentiert in issues/09-toter-code-ungenutzte-apis.md (Commit c171694).

1 comments

⁨⁩⁨Toter Code und ungenutzte APIs in CORE/INPUT⁩ ⁨⁩#⁨9⁩⁨⁩" By ⁨⁩⁨gilli⁩⁨⁩ — ⁨⁨⁩Closed⁨⁩⁩ cleanup low maintainability > **Komponente:** CORE, INPUT, GAME > **Betroffene Version:** `main` @ `238ed66`, `index.html` > > AGENTS.md verlangt „Vermeide unnötige globale Variablen“ und „keine magischen Zahlen, wenn eine > Konstante sinnvoll ist“. Folgende Strukturen sind implementiert, aber nie wirksam – sie erzeugen > den Eindruck implementierter Features, die es nicht sind: > > | # | Fundstelle | Zeile(n) | Befund | > |---|---|---|---| > | 1 | `nextEdgeAfter(world, x)` | 485–495, Export 1287 | Definiert und aus CORE exportiert, von CORE/RENDER/GAME **niemals aufgerufen**. Kanten-/Coyote-Logik läuft ausschließlich über `groundAt()`. | > | 2 | `INPUT.state.pauseEdge` | 2060 | Nie geschrieben, nie gelesen (Pause läuft direkt über `hooks.onPause()`). | > | 3 | `INPUT.state.restartEdge` | 2060 | Wie oben (Restart über `hooks.onRestart()`). | > | 4 | `INPUT.state.muteEdge` | 2060 | Wie oben (Mute über `hooks.onMute()`). | > | 5 | `INPUT.state.focusEdge` | 2059, Schreibzugriff 2120 | Wird gesetzt, aber nie verbraucht – `consume()` enthält keinen `focus`-Anteil. Fokus funktioniert nur über den zweiten, separaten Listener in `boot()` (siehe Issue #8). | > | 6 | `INPUT.state.pointerHook` / `cmd.hookGrabTarget` | 2061, 2084 | `hookGrabTarget` wird in das Commando kopiert, aber von `playerCmd()` nie gelesen. `state.pointerHook` wird nie gesetzt (nur in `consume()` auf `null` zurückgesetzt). → „Haken direkt anklicken“ ist faktisch ein generischer Greifvorgang; eine gezielte Zielauswahl existiert nicht. | > | 7 | `hook.disabled` | 941, 559, 1010 | Wird beim Anlegen auf `false` gesetzt und in `findGrab()` abgefragt, aber **nirgends** auf `true` gesetzt. Der Mechanismus „Haken deaktivieren“ ist tot. | > | 8 | `KEYMAP`-Schlüssel `"KeyW Jump"` | 2102 | Kann von keinem Browser erzeugt werden (`code` ist `KeyW`, `key` ist `w`). Vermutlicher Tippfehler-Überrest; `KeyW` wird separat für `reel` behandelt (Zeile 2116). | > | 9 | `makeBody(...).spin` | 549 | Initialisiert, nie verwendet. | > | 10 | CSS-Selektor `#countdown` | 191, 196 | Existiert nicht im DOM (richtig wäre `#countdownBg`); beide Regeln greifen nicht. `#countdown .overlay { background:none }` ebenso wirkungslos. | > > ## Auswirkung > > * Irreführende API: Wer `hook.disabled` setzt oder auf `cmd.hookGrabTarget` baut, bekommt > stillschweigend kein Verhalten. > * Erschwerte Wartung der Ein-Datei-Struktur, gerade weil die Datei bewusst modular aufgebaut ist. > * Issue #6 verstößt gegen die Anforderung „Haken direkt anklicken: greifen (wenn erreichbar)“ – > das Anklicken funktioniert nur, weil danach generisch `grab` ausgelöst wird; der angeklickte > Haken wird ignoriert (bei zwei erreichbaren Haken entscheidet `findGrab()`). > > ## Lösungsvorschlag > > * Ungenutzte Felder/Funktionen entfernen (`nextEdgeAfter`, `*Edge`, `spin`, `#countdown`-CSS). > * `focusEdge` zu einem echten Signal machen (in `consume()` aufnehmen) und den Doppel-Listener > entfernen. > * `pointerHook`/`hookGrabTarget` implementieren oder die Dokumentation/Tooltips anpassen, dass > Anklicken generisch greift. > * `hook.disabled` entfernen oder eine Nutzung (z. B. Haken nach `grabs > N` sperren) einbauen. > * KEYMAP-Tippfehler bereinigen. > > --- > > *Dokumentiert in `issues/09-toter-code-ungenutzte-apis.md` (Commit `c171694`).* 1 comments
Author
Owner

Erledigt in 8738b91 (main, gepusht).

Was jetzt anders ist

# Fundstelle Behandlung
1 nextEdgeAfter entfernt, inkl. Export. Kanten/Coyote laufen weiter ausschließlich über groundAt()/groundEdgeAfter().
2–4 pauseEdge / restartEdge / muteEdge entfernt. Pause, Neustart und Ton bleiben auf den hooks-Callbacks.
5 focusEdge war mit 9cd8ba8 (#8) schon weg – der zweite Listener in boot() existiert nicht mehr, Fokus läuft über die KEYMAP → hooks.onFocus. Jetzt zusätzlich geprüft: kein *Edge-Flag ohne Leser im Dokument.
6 pointerHook / hookGrabTarget implementiert, nicht nur dokumentiert: pointerdown setzt INPUT.state.pointerHook = h, consume() gibt es als cmd.hookGrabTarget weiter und löscht es nach genau einem Schritt, playerCmd() meldet die Verfügbarkeit vor dem Verbrauch, stepBody() löst über das neue CORE.grabTarget() auf.
7 hook.disabled ersatzlos gestrichen (auch hook.grabs). Die Alternative „nach grabs > N sperren“ wäre ein Balancing-Eingriff gewesen, kein Cleanup – und ohne Bedarf.
8 "KeyW Jump" entfernt; KeyW hängt unverändert an der Haspel.
9 makeBody().spin entfernt (die Fragment-Rotation im Renderer ist ein eigenes Feld).
10 #countdown / #countdown .overlay entfernt; die Regeln trugen nichts, #countdownBg leistet alles.

Neu in CORE: grabTarget(b, world, target) und grabbable(b, h). Genommen wird
das Ziel nur, wenn es in derselben Welt liegt und dieselbe Schwelle erfüllt wie die
freie Auswahl (Seilkühlzeit, GRAB_RADIUS, d ≥ 8); sonst Rückfall auf findGrab() –
ein Klick darf nie schlechter stehen als vorher. Tastatur, Autopilot und Solver bleiben
ungerichtet (target = null). Hilfe-Text sagt jetzt, was stimmt: „Haken direkt anklicken =
genau diesen greifen“.

Abdeckung

  • tests/issue9.mjs – tote Stellen in Quelle und Laufzeit (Exporte, makeBody-Form,
    KEYMAP-Schlüssel gegen die code/key-Form, jeder CSS-#id-Selektor gegen die ids des
    Dokuments) plus die neue Kette über den echten Pointer-Listener (per Klammerzähler
    extrahiertes INPUT und GAME.playerCmd, Technik wie #4): Ziel gewinnt gegen die freie
    Auswahl, Rückfall bei fremdem / kaltgestelltem / unerreichbarem Ziel, Ziel wird genau
    einmal verbraucht, Tastaturgriff bleibt ungerichtet.
  • tests/browser_issue9.py – echter Mausklick im echten Dokument, zwei erreichbare Haken
    (A 215 px, B 164 px, GRAB_RADIUS 225; freie Auswahl nimmt B): Klick auf A → hängt an A,
    Klick auf B → hängt an B, Klick weit neben beide → kein Griff, Leertaste → ungerichtet.
    Dazu die Wache, dass die gestrichenen CSS-Regeln nichts getragen haben (Countdown
    zentriert, #countdownBg zeigdurchlässig) und kein Konsolenfehler.

Rot → Grün

Gegen git show HEAD:index.html: tests/issue9.mjs 14 Prüfungen rot (u. a.
grabTarget fehlt, pauseEdge-Trio, disabled, grabs, spin, KeyW Jump,
#countdown), tests/browser_issue9.py 3 rot – Kernbefund: Klick auf A hängt die Figur
an B
. Nach dem Fix beide Suiten grün, controls grün in beiden Fassungen.
./tests/run-all.sh 1: alle Suiten grün (inkl. Soak).

Die Test-Fixtures, die disabled: false, grabs: 0 und b.spin = 0 nachbauten, sind
ebenfalls bereinigt (issue3, issue4, issue14, browser_smoke).

Erledigt in `8738b91` (main, gepusht). **Was jetzt anders ist** | # | Fundstelle | Behandlung | |---|---|---| | 1 | `nextEdgeAfter` | entfernt, inkl. Export. Kanten/Coyote laufen weiter ausschließlich über `groundAt()`/`groundEdgeAfter()`. | | 2–4 | `pauseEdge` / `restartEdge` / `muteEdge` | entfernt. Pause, Neustart und Ton bleiben auf den `hooks`-Callbacks. | | 5 | `focusEdge` | war mit `9cd8ba8` (#8) schon weg – der zweite Listener in `boot()` existiert nicht mehr, Fokus läuft über die `KEYMAP` → `hooks.onFocus`. Jetzt zusätzlich geprüft: kein `*Edge`-Flag ohne Leser im Dokument. | | 6 | `pointerHook` / `hookGrabTarget` | **implementiert**, nicht nur dokumentiert: `pointerdown` setzt `INPUT.state.pointerHook = h`, `consume()` gibt es als `cmd.hookGrabTarget` weiter und löscht es nach genau einem Schritt, `playerCmd()` meldet die Verfügbarkeit **vor** dem Verbrauch, `stepBody()` löst über das neue `CORE.grabTarget()` auf. | | 7 | `hook.disabled` | ersatzlos gestrichen (auch `hook.grabs`). Die Alternative „nach `grabs > N` sperren“ wäre ein Balancing-Eingriff gewesen, kein Cleanup – und ohne Bedarf. | | 8 | `"KeyW Jump"` | entfernt; `KeyW` hängt unverändert an der Haspel. | | 9 | `makeBody().spin` | entfernt (die Fragment-Rotation im Renderer ist ein eigenes Feld). | | 10 | `#countdown` / `#countdown .overlay` | entfernt; die Regeln trugen nichts, `#countdownBg` leistet alles. | Neu in `CORE`: `grabTarget(b, world, target)` und `grabbable(b, h)`. Genommen wird das Ziel nur, wenn es in **derselben** Welt liegt und dieselbe Schwelle erfüllt wie die freie Auswahl (Seilkühlzeit, `GRAB_RADIUS`, `d ≥ 8`); sonst Rückfall auf `findGrab()` – ein Klick darf nie schlechter stehen als vorher. Tastatur, Autopilot und Solver bleiben ungerichtet (`target` = null). Hilfe-Text sagt jetzt, was stimmt: „Haken direkt anklicken = genau diesen greifen“. **Abdeckung** * `tests/issue9.mjs` – tote Stellen in Quelle und Laufzeit (Exporte, `makeBody`-Form, KEYMAP-Schlüssel gegen die `code`/`key`-Form, jeder CSS-`#id`-Selektor gegen die ids des Dokuments) plus die neue Kette über den echten Pointer-Listener (per Klammerzähler extrahiertes `INPUT` und `GAME.playerCmd`, Technik wie #4): Ziel gewinnt gegen die freie Auswahl, Rückfall bei fremdem / kaltgestelltem / unerreichbarem Ziel, Ziel wird genau einmal verbraucht, Tastaturgriff bleibt ungerichtet. * `tests/browser_issue9.py` – echter Mausklick im echten Dokument, zwei erreichbare Haken (A 215 px, B 164 px, `GRAB_RADIUS` 225; freie Auswahl nimmt B): Klick auf A → hängt an A, Klick auf B → hängt an B, Klick weit neben beide → kein Griff, Leertaste → ungerichtet. Dazu die Wache, dass die gestrichenen CSS-Regeln nichts getragen haben (Countdown zentriert, `#countdownBg` zeigdurchlässig) und kein Konsolenfehler. **Rot → Grün** Gegen `git show HEAD:index.html`: `tests/issue9.mjs` 14 Prüfungen rot (u. a. `grabTarget` fehlt, `pauseEdge`-Trio, `disabled`, `grabs`, `spin`, `KeyW Jump`, `#countdown`), `tests/browser_issue9.py` 3 rot – Kernbefund: *Klick auf A hängt die Figur an B*. Nach dem Fix beide Suiten grün, controls grün in beiden Fassungen. `./tests/run-all.sh 1`: alle Suiten grün (inkl. Soak). Die Test-Fixtures, die `disabled: false, grabs: 0` und `b.spin = 0` nachbauten, sind ebenfalls bereinigt (`issue3`, `issue4`, `issue14`, `browser_smoke`).
gilli closed this issue 2026-09-01 15:07:43 +02:00
Sign in to join this conversation.
No description provided.