Vier Korrekturen aus der Nachprüfung. **Naht in der linken Fensterfront.** Sie stammte von zwei getrennten Fotoflächen — vorne und links. Eine Stossstelle lässt sich nicht wegblenden; sie verschwindet nur, wenn es keine zwei Bilder mehr gibt. Die Kulisse ist jetzt eine gekrümmte Fläche mit einer einzigen Panoramadatei: auf einem durchgehenden Zylinder ist eine Naht geometrisch unmöglich. Das Panorama entsteht einmalig aus den beiden Referenzfotos (`scripts/build-basel-panorama.mjs`), jede Quelle genau einmal — kein Kacheln, kein Spiegeln. Das gute Motiv vom Tischende bleibt in Ausschnitt und Farbe unverändert und steht weiterhin in der Frontscheibe; die Panoramaaufnahme setzt es nach links fort, helligkeitsangeglichen und über 320 Pixel überblendet. Aus der Fortsetzung wird nur der Abschnitt östlich des Münsters verwendet — beide Vorlagen zeigen es, nebeneinander stünde es zweimal im Bild. Himmel und Wasser sind aus den Randzeilen gestreckt, damit oben und unten keine Bildgrenze bleibt. **Stühle und Körper entfernt.** Sitzmöbel, Rümpfe, Schultern, Hälse, Arme und Hinterköpfe sind ersatzlos weg. Die Agenten bestehen nur noch aus ihrem runden Porträt mit weissem Ring. **Positionen neu.** Ferdi und Bruno sind die direkten Nachbarn links und rechts vorne, die übrigen gestaffelt dahinter, Thomas unverändert vis-à-vis. Die Kreise liegen deutlich über der Blickachse: lagen sie auf Augenhöhe, projizierten alle fünf auf fast dieselbe Bildhöhe und die hinteren verschwanden hinter den vorderen — seitliches Auseinanderziehen half dagegen nicht, weil ein tieferer Platz in der Perspektive zur Mitte wandert. Dazu ein echter Fehler, der dabei auffiel: die grosszügigen Trefferquader der vorderen Kreise fingen die Strahlen der hinteren ab, ein Klick auf Livia landete bei Ferdi. Die Trefferfläche ist jetzt eine Kugel knapp um den sichtbaren Kreis. **Bildschärfe.** Die Textur wird auf einen mittigen quadratischen Ausschnitt begrenzt — ohne das zieht die Kreisgeometrie ein liegendes Foto in die Breite, was Gesichter verzerrt und Schärfe kostet. Dazu anisotrope Filterung und Mipmaps. Höher aufgelöste Originale der fünf Agenten waren nicht auffindbar: die Porträts in `Agenten_Verwaltung_Fotos.html` liegen zwar in 256×256 vor, gehören aber zu einer anderen Belegschaft — geprüft und verworfen, statt Gesichter zu vertauschen. **Ortsangabe** unten rechts entfernt. **Menü** liegt bündig an der rechten Fensterkante: der Spalt kam vom Anker am eingerückten Menüsymbol, jetzt ist das Klappmenü an eine Bildschirmstelle gebunden. Geprüft: 422 Tests, Typecheck, Build, ESLint, Token-Schwelle (884/925). Im Browser 1280 und 1600 px: sechs Beschriftungen ohne Überlappung, sechs Kreise ohne Überlappung, alle sechs per Maus auf der richtigen Subpage, Menü bündig ohne waagrechten Scrollbalken, keine Konsolenfehler. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
89 lines
2.9 KiB
TypeScript
89 lines
2.9 KiB
TypeScript
import { AGENT_WORKSPACES } from '../../lib/agentWorkspaces'
|
|
import { AGENT_SUPERVISOR } from '../../lib/agentWorkspaces'
|
|
|
|
/**
|
|
* Sitzordnung im 3D-Meetingraum (Runde 6, §5/§6/§7).
|
|
*
|
|
* Eine einzige Tabelle bestimmt, wer wo sitzt. Namen, Funktionen, Porträts und
|
|
* Zielseiten kommen dabei nicht von hier, sondern aus `AGENT_WORKSPACES` —
|
|
* derselben zentralen Konfiguration, die Menü und Seitenköpfe verwenden. Hier
|
|
* steht ausschliesslich die Geometrie (§24, Schritt 7: nichts doppelt pflegen).
|
|
*
|
|
* Koordinaten sind Meter im Weltsystem der Szene:
|
|
* - x: negativ = links vom Betrachter, positiv = rechts
|
|
* - z: 0 am Kopfende des Betrachters, negativ = in den Raum hinein
|
|
*
|
|
* Die Agenten wechseln die Tischseite in der Reihenfolge der Konfiguration
|
|
* (Ferdi links, Bruno rechts, Livia links, …). Das verteilt sie gleichmässig,
|
|
* hält die Abstände gross genug, dass sich niemand überlappt, und macht den
|
|
* Arbeitsablauf auch am Tisch ablesbar.
|
|
*/
|
|
|
|
/** Auf welcher Tischseite ein Platz liegt. */
|
|
export const SeatSide = {
|
|
LEFT: 'LEFT',
|
|
RIGHT: 'RIGHT',
|
|
/** Kopfende gegenüber dem Betrachter — nur Thomas. */
|
|
HEAD: 'HEAD',
|
|
} as const
|
|
export type SeatSide = typeof SeatSide[keyof typeof SeatSide]
|
|
|
|
export interface MeetingSeat {
|
|
/** Agenten-ID; identisch mit `AGENT_PHOTOS` und den Mockdaten. */
|
|
id: string
|
|
name: string
|
|
role: string
|
|
/** Zielseite des Klicks. */
|
|
path: string
|
|
side: SeatSide
|
|
/** Sitzposition in Metern. */
|
|
x: number
|
|
z: number
|
|
}
|
|
|
|
/**
|
|
* Sitzplätze der fünf Agenten, in Metern (Runde 6, §3.2).
|
|
*
|
|
* Ferdi und Bruno sind die direkten Nachbarn des Betrachters — einer links,
|
|
* einer rechts, schräg frontal und dicht an der vorderen Tischkante. Dadurch
|
|
* entsteht hinter ihnen Platz, in dem die übrigen drei gestaffelt Raum haben,
|
|
* ohne sich zu überlagern.
|
|
*
|
|
* Vorher standen alle fünf zu weit hinten und drängten sich am Fluchtpunkt.
|
|
*/
|
|
const PLAETZE: Record<string, { side: SeatSide; x: number; z: number }> = {
|
|
ferdi: { side: SeatSide.LEFT, x: -1.14, z: -1.20 },
|
|
bruno: { side: SeatSide.RIGHT, x: 1.14, z: -1.20 },
|
|
livia: { side: SeatSide.LEFT, x: -1.42, z: -2.90 },
|
|
nora: { side: SeatSide.RIGHT, x: 1.42, z: -2.90 },
|
|
sina: { side: SeatSide.LEFT, x: -1.30, z: -4.75 },
|
|
}
|
|
|
|
/**
|
|
* Notplatz für einen Agenten ohne Eintrag oben — sichtbar hinten rechts statt
|
|
* lautlos im Nichts.
|
|
*/
|
|
const FALLBACK = { side: SeatSide.RIGHT, x: 1.30, z: -4.75 }
|
|
|
|
/** Kopfende gegenüber. Unverändert: die Position wirkt gut (§3.2). */
|
|
const HEAD_Z = -6.75
|
|
|
|
export const MEETING_SEATS: MeetingSeat[] = [
|
|
...AGENT_WORKSPACES.map(agent => ({
|
|
id: agent.id,
|
|
name: agent.name,
|
|
role: agent.role,
|
|
path: agent.path,
|
|
...(PLAETZE[agent.id] ?? FALLBACK),
|
|
})),
|
|
{
|
|
id: AGENT_SUPERVISOR.id,
|
|
name: AGENT_SUPERVISOR.name,
|
|
role: AGENT_SUPERVISOR.role,
|
|
path: AGENT_SUPERVISOR.path,
|
|
side: SeatSide.HEAD,
|
|
x: 0,
|
|
z: HEAD_Z,
|
|
},
|
|
]
|