diff --git a/conzept.html b/conzept.html new file mode 100644 index 0000000..b506a6a --- /dev/null +++ b/conzept.html @@ -0,0 +1,604 @@ + + + + + + Projekt-Blaupause: KI-Krimi-Dinner "Projekt Chimera" + + + + + + +
+
+ +
+

Projekt-Blaupause: KI-Krimi-Dinner "Projekt Chimera"

+
+
+ Version + 3.0 (Final & Complete UI) +
+
+ Autor + D. Schuhbaum & S. Altschäffl +
+
+ Datum + 03.10.2025 +
+
+
+ +
+

1. Projektübersicht

+

"Projekt Chimera" ist ein hybrides Krimi-Dinner-Erlebnis, das physische soziale Interaktion mit einer digitalen App-Komponente verbindet. Das Alleinstellungsmerkmal ist der Einsatz einer zweistufigen KI-Architektur, die nicht nur einzigartige narrative Szenarien generiert, sondern diese auch proaktiv auf logische Konsistenz validiert und korrigiert.

+

Die Architektur basiert auf einer klaren Trennung: Supabase dient als dedizierter Service für die Benutzerauthentifizierung, während alle Spieldaten (Szenarien, Spieler, Spielstände) in einer separaten, dedizierten PostgreSQL-Datenbank gehostet werden. Ein zentrales FastAPI-Backend fungiert als sichere Schnittstelle zwischen den Clients und beiden Diensten.

+
+ +
+

2. Narratives Design & Validierung

+

Die Generierung jedes Spiels folgt einem strengen, zweistufigen Prozess, um die narrative Qualität und logische Integrität zu gewährleisten.

+ +
+
+

Schritt 1: Kreative Generierung (Der "Autor")

+

In dieser Phase agiert die KI als kreativer Autor. Sie erhält einen umfassenden Prompt, der die gewünschten Rahmenbedingungen (Szenario-Beschreibung, Rundenanzahl) vorgibt. Die genaue Spieleranzahl wird dynamisch aus der Lobby übernommen, kurz bevor die KI die Generierung startet.

+
    +
  • Hintergrundgeschichte: Der Rahmen des Geschehens und der Grund für das Zusammentreffen.
  • +
  • Charaktere: Detaillierte Rollen mit Persönlichkeit, Beziehungen und öffentlichen Informationen.
  • +
  • Geheimnisse & Ziele: Private Geheimnisse und spielrelevante Ziele für jeden Charakter.
  • +
  • Der Mord & lückenloser Zeitstrahl: Definition des Verbrechens und Etablierung eines kontinuierlichen Zeitstrahls für jeden Charakter (z.B. "16:30-16:45: Aktion A"), um Alibis nachvollziehbar zu machen.
  • +
  • Beziehungsgeflecht: Eine Matrix der komplexen Beziehungen zwischen allen Charakteren.
  • +
  • Hinweise: Ein Set von Hinweisen, die den Mörder belasten oder falsche Fährten legen, aufgeteilt auf die gewählte Rundenanzahl.
  • +
+
+
+

Schritt 2: Logische Validierung & Korrektur (Der "Logik-Lektor")

+

Der rohe Output aus Schritt 1 wird nun an eine zweite KI-Instanz übergeben, die als akribischer Logik-Lektor agiert. Die KI wird instruiert, das gesamte Szenario anhand einer Checkliste von potenziellen Fehlern zu überprüfen:

+
    +
  • Widersprüche in Zeitlinien: Passen Alibis und die Zeitblöcke auf den Zeitstrahlen aller Charaktere lückenlos und widerspruchsfrei zusammen?
  • +
  • Motiv-Konsistenz: Ist das Motiv des Mörders stark genug und logisch begründet?
  • +
  • Hinweis-Validität: Führt mindestens ein entscheidender Hinweis logisch zum Täter? Sind falsche Fährten subtil?
  • +
  • Charakter-Konsistenz: Handeln die Charaktere gemäß ihrer beschriebenen Persönlichkeit und Ziele?
  • +
  • Regelkonformität: Ist das Spiel fair und lösbar?
  • +
+

Die KI korrigiert gefundene Fehler minimalinvasiv, um die kreative Essenz nicht zu verändern, und gibt ein logisch wasserdichtes Spielszenario aus.

+
+
+
+ +
+

3. Technische Architektur

+

Die Architektur ist auf maximale Kontrolle und Skalierbarkeit ausgelegt. Die React Native-Clients kommunizieren ausschließlich mit dem FastAPI-Backend. Supabase wird als reiner Authentifizierungs-Provider genutzt. Echtzeit-Updates werden über eine WebSocket-Verbindung vom FastAPI-Server an die Clients gepusht.

+ +
+
+                        graph TD
+                            subgraph "Spieler-Geräte"
+                                P1["React Native Apps"]
+                            end
+
+                            subgraph "Authentifizierung"
+                                Auth["Supabase Auth"]
+                            end
+
+                            subgraph "Sicheres Backend"
+                                FastAPI["FastAPI Server 
REST & WebSockets"] + end + + subgraph "Spieldaten-Bank" + PG_DB["PostgreSQL DB"] + end + + subgraph "Externe Dienste" + OAI["OpenAI API"] + end + + %% Verbindungen + P1 -- "1. Login" --> Auth + P1 -- "2. API Calls (mit Token)" --> FastAPI + + FastAPI -- "3. KI Call" --> OAI + FastAPI -- "4. DB-Zugriff" --> PG_DB + + FastAPI -- "5. WebSocket Updates" --> P1 +
+
+ +

Datenfluss-Beschreibung:

+
    +
  1. Authentifizierung: Der Benutzer authentifiziert sich in der React Native-App direkt bei Supabase Auth. Die App erhält ein JWT (JSON Web Token).
  2. +
  3. API-Anfragen: Für alle spielrelevanten Aktionen sendet die App eine Anfrage an den FastAPI-Server und fügt das JWT von Supabase in den Authorization-Header ein. FastAPI validiert dieses Token.
  4. +
  5. KI-Generierung: Für die Spielerstellung ruft der FastAPI-Server die OpenAI-API auf.
  6. +
  7. Datenbank-Interaktion: FastAPI ist die einzige Komponente, die mit der dedizierten PostgreSQL-Datenbank kommuniziert.
  8. +
  9. Echtzeit-Updates: Die Clients bauen eine WebSocket-Verbindung zum FastAPI-Server auf. Bei Änderungen pusht der Server Updates an alle verbundenen Clients.
  10. +
+
+ +
+

4. User Interface (UI) Konzept

+

Die UI-Konzepte werden als klare, moderne Wireframes visualisiert, um den gesamten App-Flow von der Erstellung bis zum Spiel darzustellen.

+
+ + +
+

1. Login

+
+
+

PROJEKT CHIMERA

+
+
+ + + +

Noch kein Konto? Jetzt registrieren

+
+
+
+
+ + +
+

2. Registrierung

+
+
+

Konto erstellen

+
+
+ + + + +

Bereits ein Konto? Zum Login

+
+
+
+
+ + +
+

3. Home Dashboard

+
+
+

Deine Spiele

+ +
+
+
+

Tech-Konferenz 2035

+

Status: Aktiv (Runde 2/3)

+ +
+
+

Villa Vendetta

+

Status: Lobby (0 Spieler)

+ +
+
+
+ + +
+
+
+ + +
+

4. Spiel erstellen (Host)

+
+
+

Neues Spiel erstellen

+
+
+
+ + +
+
+ +
+ + 3 +
+
+
+

Die Spieleranzahl ist flexibel (mind. 3 Spieler) und wird in der Lobby durch die Anzahl der beigetretenen Spieler bestimmt.

+
+
+
+ +
+
+
+ + +
+

5. Host-Lobby

+
+
+

Spiel-Lobby

+

Tech-Konferenz 2035

+
+
+

Teile diesen Code mit deinen Mitspielern:

+
+ GHY-781 +
+
Beigetretene Spieler (3)
+
    +
  • Maria
  • +
  • Jonas
  • +
  • Sandra
  • +
+
+
+ + +
+
+
+ + +
+

6. Spieler-Ansicht (Rolle)

+
+
+

Deine Rolle

+

Dr. Aris Thorne

+
+
+ + + + +
+
+
Deine Ziele:
+
    +
  • Finde heraus, wer deine Forschung sabotiert hat.
  • +
  • Verhindere, dass dein Geheimnis über das gescheiterte Experiment ans Licht kommt.
  • +
+
Deine Geheimnisse:
+

Du hast vor einem Monat bei einem nicht genehmigten Experiment die Stromversorgung der Station überlastet, was zu einem kritischen Ausfall führte. Nur das Opfer wusste davon.

+
+
+
+ + +
+

6. Spieler-Ansicht (Hinweise)

+
+
+

Deine Rolle

+

Dr. Aris Thorne

+
+
+ + + + +
+
+
+
Runde 2 (18:00 - 19:00 Uhr)
+
+

HINWEIS #3

+

Ein zerrissener Brief wurde gefunden. Die Worte "Schulden" und "letzte Warnung" sind lesbar.

+
+
+
+
Runde 1 (16:00 - 18:00 Uhr)
+
+

HINWEIS #1

+

Das Opfer wurde mit einem schweren Gegenstand erschlagen.

+
+
+
+
+
+ + +
+

7. Spieler-Ansicht (Charaktere)

+
+
+

Deine Rolle

+

Dr. Aris Thorne

+
+
+ + + + +
+
+
+

Evelyn Reed (CEO)

+

Die ehrgeizige CEO des Konkurrenzunternehmens. Es ist bekannt, dass sie und das Opfer eine erbitterte Rivalität pflegten.

+
+
+

Ivan Petrov (Sicherheitschef)

+

Der loyale, aber jähzornige Sicherheitschef. Er war für den Schutz des Opfers verantwortlich.

+
+
+
+
+ + +
+

7. Spieler-Ansicht (Zeitstrahl)

+
+
+

Deine Rolle

+

Dr. Aris Thorne

+
+
+ + + + +
+
+
Dein persönlicher Zeitstrahl
+
+
+
+
+

16:30 - 16:45 Uhr

+

Streitgespräch mit dem Opfer im Labor.

+
+
+
+
+
+

16:45 - 17:00 Uhr

+

Alleine im Büro, E-Mails beantwortet.

+
+
+
+
+
+

17:00 - 17:20 Uhr

+

Gespräch mit Ivan Petrov in der Cafeteria. (Dein Alibi)

+
+
+
+
+
+

ca. 17:30 Uhr (TODESZEITPUNKT)

+
+
+
+
+
+
+ + +
+

8. Auflösung

+
+
+

Der Mörder war...

+

Ivan Petrov!

+
+
+

Sein Motiv war Rache, da das Opfer ihn erpresst hat. Die Mordwaffe war ein schwerer Schraubenschlüssel aus dem Werkzeugraum.

+
Abstimmungsergebnis
+
    +
  • Du hast für Evelyn Reed gestimmt.
  • +
  • Maria hat für Ivan Petrov gestimmt. (Korrekt!)
  • +
  • Jonas hat für Sandra gestimmt.
  • +
+
+
+ +
+
+
+ + +
+

9. Host Notfall-Dashboard

+
+
+

Host Notfall-Dashboard

+

Spoiler-freie Steuerung (im Spiel)

+
+
+
+
Spiel-Steuerung
+
+ + +
+
+
+
Experten-Optionen
+ +

Achtung: Generiert nur die Hinweise für die AKTUELLE Runde neu. Nur nutzen, wenn Hinweise fehlerhaft wirken.

+
+
+
Gefahrenzone
+ +

Beendet das Spiel für alle und startet die Lobby neu.

+
+
+
+
+
+
+ +
+

5. API-Endpunkte & Datenbank-Interaktion

+
+
+

FastAPI-Backend (erweitert)

+

Das Backend wird zur zentralen API für die gesamte Spiellogik. Alle Endpunkte erfordern ein gültiges Supabase JWT.

+
    +
  • POST /game/create: Erstellt ein neues Spiel, ruft OpenAI auf, speichert in PG_DB.
  • +
  • POST /game/{game_code}/join: Fügt einen Spieler zu einem Spiel hinzu.
  • +
  • GET /game/{game_code}/state: Ruft den aktuellen Zustand eines Spiels ab.
  • +
  • POST /game/{game_code}/vote: Gibt eine Stimme für einen Charakter ab.
  • +
  • GET /game/{game_code}/character: Ruft die Charakterdetails für den authentifizierten Spieler ab.
  • +
  • /ws/{game_code}: WebSocket-Endpunkt für Echtzeit-Updates.
  • +
+
+
+

Client-Interaktionen

+
    +
  • Supabase Auth (`supabase-js`): Wird in der React Native App ausschließlich für Login, Registrierung und die Verwaltung des Auth-Zustands (JWT) verwendet.
  • +
  • API-Client (z.B. Axios): Wird für alle HTTP-Anfragen an das FastAPI-Backend genutzt.
  • +
  • WebSocket-Client: Wird verwendet, um die Echtzeit-Verbindung zum /ws/... Endpunkt des Backends herzustellen und auf Updates zu lauschen.
  • +
+
+
+
+ +
+

6. Datenmodelle & `game_data` Detailbeschreibung

+

Die dedizierte PostgreSQL-Datenbank enthält die gesamte Spiellogik, während Supabase ausschließlich für die Identitätsverwaltung zuständig ist.

+ +

Dedizierte PostgreSQL-Datenbank (Spieldaten)

+
+
+

Tabelle: `games`

+
+ + + + + + + + + + + + + + + + +
SpalteDatentypBeschreibung
iduuidEindeutige ID für ein Spiel.
created_attimestampZeitstempel der Erstellung.
host_iduuidReferenz auf die User-ID des Hosts aus Supabase.
game_codevarcharKurzer Code zum Beitreten (z.B. "GHY-781"). Indiziert!
statusvarcharAktueller Status (setup, lobby, active, finished).
game_datajsonbDas komplette KI-generierte Szenario.
+
+
+
+

Tabelle: `players`

+
+ + + + + + + + + + + + + + + +
SpalteDatentypBeschreibung
iduuidEindeutiger Eintrag für einen Spieler in einem Spiel.
game_iduuidVerweist auf das zugehörige Spiel in `games`.
player_iduuidReferenz auf die User-ID aus Supabase (kann `NULL` sein).
player_namevarcharDer im Spiel angezeigte Name des Spielers.
character_idvarcharVerknüpft den Spieler mit seiner Rolle im `game_data`-JSON.
+
+
+
+ +
+

Die `game_data` (jsonb) Spalte: Der "digitale Spielkarton"

+

Diese einzelne Spalte ist das narrative Herzstück jedes Spiels. Hier wird das gesamte, von der KI generierte und validierte JSON-Objekt gespeichert.

+
+
+ +
+

7. Prompt-Engineering-Strategie

+
+
+

Prompt 1: Der kreative Autor

+

System-Prompt:

+

Du bist ein preisgekrönter Autor von Kriminalromanen. Deine Aufgabe ist es, ein vollständiges, komplexes und fesselndes Krimi-Dinner-Szenario zu erstellen. Halte dich exakt an die vorgegebene JSON-Struktur.

+

User-Prompt (Beispiel):

+

Erstelle ein Krimi-Dinner-Szenario für 5 Spieler über 3 Runden. Das Thema lautet: "Ein Mord auf einer Tech-Konferenz im Jahr 2035". Erstelle für jeden Charakter einen lückenlosen Zeitstrahl mit Zeitblöcken (z.B. "16:30-16:45") und verteile die Hinweise logisch auf die Runden. Generiere das vollständige Spiel-JSON und stelle sicher, dass der Mord logisch aufgeklärt werden kann.

+
+
+

Prompt 2: Der Logik-Lektor

+

System-Prompt:

+

Du bist ein extrem detailorientierter und logisch denkender Lektor. Deine Aufgabe ist es, das dir vorgelegte Krimi-Szenario auf Widersprüche und Logikfehler zu überprüfen und minimalinvasiv zu korrigieren.

+

User-Prompt:

+

Hier ist ein JSON-Objekt. Bitte agiere als Logik-Lektor. Überprüfe es auf: Zeitlinien-Konflikte (sind die Zeitstrahlen aller Charaktere widerspruchsfrei?), Motiv-Schwäche, Unlösbarkeit, Inkonsistente Charakter-Aktionen. Gib das vollständige, korrigierte JSON zurück.

[Hier wird das gesamte JSON aus Schritt 1 eingefügt]

+
+
+
+ +
+

8. User Journey & Spielablauf

+

Der Lebenszyklus eines Spiels ist in mehrere Phasen unterteilt, wobei jede Runde einem definierten Zeitfenster entspricht, um den Zeitstrahl zu strukturieren.

+
    +
  1. Phase 0: Generierung & Vorbereitung (status: setup) +

    Der Host kann ein Spiel generieren, lange bevor es stattfindet. In dieser Phase erhält er den Einladungscode und eine spoiler-freie Übersicht über Thema und Charakter-Namen zur Vorbereitung.

    +
  2. +
  3. Phase 1: Lobby (status: lobby) +

    Am Tag des Spiels öffnet der Host die Lobby. Die Spieler treten mit dem Code bei. Der Host kann Spieler hinzufügen/entfernen und hat die Option, das Szenario neu zu generieren, bevor er das Spiel startet.

    +
  4. +
  5. Phase 2: Rollenverteilung +

    Nach dem Spielstart weist das Backend jedem Spieler eine Rolle zu und sendet die geheimen Informationen an das jeweilige Gerät.

    +
  6. +
  7. Phase 3: Spielrunden (status: active) +

    Das Spiel verläuft in Runden, die jeweils einem Zeitfenster zugeordnet sind (z.B. Runde 1: 16-18 Uhr). In jeder Runde gibt das System neue Hinweise frei. Spieler können ihren persönlichen Zeitstrahl und alle bisherigen Hinweise einsehen.

    +
  8. +
  9. Phase 4: Abstimmung & Auflösung (status: finished) +

    Nach der letzten Runde wird die Abstimmung freigeschaltet. Danach folgt die Auflösung, bei der der Mörder und alle Geheimnisse enthüllt werden.

    +
  10. +
+
+ +
+

9. Geschäftsmodell & Monetarisierung

+

Die App wird kein kostenloses Basis-Modell anbieten. Die Monetarisierung erfolgt direkt über die Nutzung der Spiunktion.

+
+
+

Abonnement-Modell

+

Nutzer zahlen einen monatlichen oder jährlichen Beitrag und erhalten dafür ein festes Kontingent an Spielen (z.B. die Möglichkeit, 2 Spiele pro Woche zu generieren und zu spielen).

+
+
+

Einmalkauf (Pay-per-Game)

+

Alternativ zum Abo können Nutzer einzelne Spiele per Einmalkauf freischalten. Dies bietet maximale Flexibilität für Gelegenheitsspieler.

+
+
+
+ +
+

10. Skalierbarkeit, Kosten & Fehlerbehandlung

+
    +
  • Kostenkontrolle (OpenAI): Ein Rate-Limiting auf dem /game/create Endpunkt verhindert Missbrauch (z.B. nur ein Spiel alle 5 Minuten pro Nutzer).
  • +
  • Fehlerbehandlung bei Generierung: Schlägt der OpenAI-Call fehl, unternimmt das Backend automatisch 1-2 erneute Versuche, bevor es einen Fehler an den Host meldet.
  • +
  • Nahtloses Wiederverbinden: Spieler können jederzeit wieder in ein laufendes Spiel einsteigen (z.B. nach Verbindungsabbruch) und erhalten den aktuellen Spielzustand.
  • +
  • Notfall-Dashboard (Host): Der Host erhält ein simples, spoiler-freies Admin-Panel, um das Spiel zu pausieren, Runden manuell auszulösen oder als Experte die Hinweise einer Runde neu zu generieren. Für katastrophale Fehler gibt es eine Option zum kompletten Neustart des Spiels.
  • +
+
+ +
+

11. Rechtliches & Datenschutz

+

Aufgrund der Verarbeitung von E-Mail-Adressen für die Authentifizierung sind folgende Punkte für den Launch zwingend erforderlich:

+
    +
  • DSGVO-konforme Datenschutzerklärung: Beschreibt, welche Daten zu welchem Zweck verarbeitet werden.
  • +
  • Impressum: Gesetzlich vorgeschriebene Angabe des Betreibers.
  • +
  • Löschung des Accounts: Eine einfache Möglichkeit für Nutzer, ihren Account und alle Daten zu löschen.
  • +
+
+
+
+ + + diff --git a/package-lock.json b/package-lock.json index d9c5d3e..2e64e03 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,6 +13,7 @@ "@testing-library/react": "^16.3.0", "@testing-library/user-event": "^13.5.0", "bootstrap": "^5.3.5", + "mermaid": "^10.9.1", "react": "^19.1.0", "react-bootstrap": "^2.10.9", "react-dom": "^19.1.0", @@ -81,7 +82,6 @@ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.10.tgz", "integrity": "sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ==", "license": "MIT", - "peer": true, "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.26.2", @@ -722,7 +722,6 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.26.0.tgz", "integrity": "sha512-B+O2DnPc0iG+YXFqOxv2WNuNU97ToWjOomUQ78DouOENWUaM5sVrmet9mcomUGQFwpJd//gvUagXBSdzO1fRKg==", "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" }, @@ -1587,7 +1586,6 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.25.9.tgz", "integrity": "sha512-s5XwpQYCqGerXl+Pu6VDL3x0j2d82eiV77UJ8a2mDHAW7j9SWRqQ2y1fNo1Z74CdcYipl5Z41zvjj4Nfzq36rw==", "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.25.9", "@babel/helper-module-imports": "^7.25.9", @@ -2075,6 +2073,12 @@ "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", "license": "MIT" }, + "node_modules/@braintree/sanitize-url": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/@braintree/sanitize-url/-/sanitize-url-6.0.4.tgz", + "integrity": "sha512-s3jaWicZd0pkP0jf5ysyHUI/RE7MHos6qlToFcGWXVp+ykHOy77OUMrfbgJ9it2C5bow7OIQwYYaHjk9XlBQ2A==", + "license": "MIT" + }, "node_modules/@csstools/normalize.css": { "version": "12.1.1", "resolved": "https://registry.npmjs.org/@csstools/normalize.css/-/normalize.css-12.1.1.tgz", @@ -3102,7 +3106,6 @@ "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==", "license": "MIT", - "peer": true, "funding": { "type": "opencollective", "url": "https://opencollective.com/popperjs" @@ -3539,7 +3542,6 @@ "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.4.0.tgz", "integrity": "sha512-pemlzrSESWbdAloYml3bAJMEfNh1Z7EduzqPKprCH5S341frlpYnUEW0H72dLxa6IsYr+mPno20GiSm+h9dEdQ==", "license": "MIT", - "peer": true, "dependencies": { "@babel/code-frame": "^7.10.4", "@babel/runtime": "^7.12.5", @@ -3748,6 +3750,27 @@ "@types/node": "*" } }, + "node_modules/@types/d3-scale": { + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.9.tgz", + "integrity": "sha512-dLmtwB8zkAeO/juAMfnV+sItKjlsw2lKdZVVy6LRr0cBmegxSABiLEpGVmSJJ8O08i4+sGR6qQtb6WtuwJdvVw==", + "license": "MIT", + "dependencies": { + "@types/d3-time": "*" + } + }, + "node_modules/@types/d3-scale-chromatic": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@types/d3-scale-chromatic/-/d3-scale-chromatic-3.1.0.tgz", + "integrity": "sha512-iWMJgwkK7yTRmWqRB5plb1kadXyQ5Sj8V/zYlFGMUBbIPKQScw+Dku9cAAMgJG+z5GYDoMjWGLVOvjghDEFnKQ==", + "license": "MIT" + }, + "node_modules/@types/d3-time": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.4.tgz", + "integrity": "sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g==", + "license": "MIT" + }, "node_modules/@types/debug": { "version": "4.1.12", "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", @@ -3974,7 +3997,6 @@ "resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.2.tgz", "integrity": "sha512-oxLPMytKchWGbnQM9O7D67uPa9paTNxO7jVoNMXgkkErULBPhPARCfkKL9ytcIJJRGjbsVwW4ugJzyFFvm/Tiw==", "license": "MIT", - "peer": true, "dependencies": { "csstype": "^3.0.2" } @@ -4101,7 +4123,6 @@ "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.62.0.tgz", "integrity": "sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag==", "license": "MIT", - "peer": true, "dependencies": { "@eslint-community/regexpp": "^4.4.0", "@typescript-eslint/scope-manager": "5.62.0", @@ -4155,7 +4176,6 @@ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.62.0.tgz", "integrity": "sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==", "license": "BSD-2-Clause", - "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "5.62.0", "@typescript-eslint/types": "5.62.0", @@ -4525,7 +4545,6 @@ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz", "integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==", "license": "MIT", - "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -4612,7 +4631,6 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "license": "MIT", - "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -5529,7 +5547,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "caniuse-lite": "^1.0.30001688", "electron-to-chromium": "^1.5.73", @@ -6208,6 +6225,15 @@ "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", "license": "MIT" }, + "node_modules/cose-base": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/cose-base/-/cose-base-1.0.3.tgz", + "integrity": "sha512-s9whTXInMSgAp/NVXVNuVxVKzGH2qck3aQlVHxDCdAEPgtMKwc4Wq6/QKhgdEdgbLSi9rBTAcPoRa6JpiG4ksg==", + "license": "MIT", + "dependencies": { + "layout-base": "^1.0.0" + } + }, "node_modules/cosmiconfig": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", @@ -6628,6 +6654,487 @@ "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", "license": "MIT" }, + "node_modules/cytoscape": { + "version": "3.33.1", + "resolved": "https://registry.npmjs.org/cytoscape/-/cytoscape-3.33.1.tgz", + "integrity": "sha512-iJc4TwyANnOGR1OmWhsS9ayRS3s+XQ185FmuHObThD+5AeJCakAAbWv8KimMTt08xCCLNgneQwFp+JRJOr9qGQ==", + "license": "MIT", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/cytoscape-cose-bilkent": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cytoscape-cose-bilkent/-/cytoscape-cose-bilkent-4.1.0.tgz", + "integrity": "sha512-wgQlVIUJF13Quxiv5e1gstZ08rnZj2XaLHGoFMYXz7SkNfCDOOteKBE6SYRfA9WxxI/iBc3ajfDoc6hb/MRAHQ==", + "license": "MIT", + "dependencies": { + "cose-base": "^1.0.0" + }, + "peerDependencies": { + "cytoscape": "^3.2.0" + } + }, + "node_modules/d3": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/d3/-/d3-7.9.0.tgz", + "integrity": "sha512-e1U46jVP+w7Iut8Jt8ri1YsPOvFpg46k+K8TpCb0P+zjCkjkPnV7WzfDJzMHy1LnA+wj5pLT1wjO901gLXeEhA==", + "license": "ISC", + "dependencies": { + "d3-array": "3", + "d3-axis": "3", + "d3-brush": "3", + "d3-chord": "3", + "d3-color": "3", + "d3-contour": "4", + "d3-delaunay": "6", + "d3-dispatch": "3", + "d3-drag": "3", + "d3-dsv": "3", + "d3-ease": "3", + "d3-fetch": "3", + "d3-force": "3", + "d3-format": "3", + "d3-geo": "3", + "d3-hierarchy": "3", + "d3-interpolate": "3", + "d3-path": "3", + "d3-polygon": "3", + "d3-quadtree": "3", + "d3-random": "3", + "d3-scale": "4", + "d3-scale-chromatic": "3", + "d3-selection": "3", + "d3-shape": "3", + "d3-time": "3", + "d3-time-format": "4", + "d3-timer": "3", + "d3-transition": "3", + "d3-zoom": "3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-array": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz", + "integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==", + "license": "ISC", + "dependencies": { + "internmap": "1 - 2" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-axis": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-axis/-/d3-axis-3.0.0.tgz", + "integrity": "sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-brush": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-brush/-/d3-brush-3.0.0.tgz", + "integrity": "sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ==", + "license": "ISC", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-drag": "2 - 3", + "d3-interpolate": "1 - 3", + "d3-selection": "3", + "d3-transition": "3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-chord": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-chord/-/d3-chord-3.0.1.tgz", + "integrity": "sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g==", + "license": "ISC", + "dependencies": { + "d3-path": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-color": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", + "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-contour": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/d3-contour/-/d3-contour-4.0.2.tgz", + "integrity": "sha512-4EzFTRIikzs47RGmdxbeUvLWtGedDUNkTcmzoeyg4sP/dvCexO47AaQL7VKy/gul85TOxw+IBgA8US2xwbToNA==", + "license": "ISC", + "dependencies": { + "d3-array": "^3.2.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-delaunay": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/d3-delaunay/-/d3-delaunay-6.0.4.tgz", + "integrity": "sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A==", + "license": "ISC", + "dependencies": { + "delaunator": "5" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-dispatch": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz", + "integrity": "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-drag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-3.0.0.tgz", + "integrity": "sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==", + "license": "ISC", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-selection": "3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-dsv": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-dsv/-/d3-dsv-3.0.1.tgz", + "integrity": "sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q==", + "license": "ISC", + "dependencies": { + "commander": "7", + "iconv-lite": "0.6", + "rw": "1" + }, + "bin": { + "csv2json": "bin/dsv2json.js", + "csv2tsv": "bin/dsv2dsv.js", + "dsv2dsv": "bin/dsv2dsv.js", + "dsv2json": "bin/dsv2json.js", + "json2csv": "bin/json2dsv.js", + "json2dsv": "bin/json2dsv.js", + "json2tsv": "bin/json2dsv.js", + "tsv2csv": "bin/dsv2dsv.js", + "tsv2json": "bin/dsv2json.js" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-dsv/node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, + "node_modules/d3-ease": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz", + "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-fetch": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-fetch/-/d3-fetch-3.0.1.tgz", + "integrity": "sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw==", + "license": "ISC", + "dependencies": { + "d3-dsv": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-force": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-force/-/d3-force-3.0.0.tgz", + "integrity": "sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==", + "license": "ISC", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-quadtree": "1 - 3", + "d3-timer": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-format": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.0.tgz", + "integrity": "sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-geo": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-3.1.1.tgz", + "integrity": "sha512-637ln3gXKXOwhalDzinUgY83KzNWZRKbYubaG+fGVuc/dxO64RRljtCTnf5ecMyE1RIdtqpkVcq0IbtU2S8j2Q==", + "license": "ISC", + "dependencies": { + "d3-array": "2.5.0 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-hierarchy": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-3.1.2.tgz", + "integrity": "sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-interpolate": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", + "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==", + "license": "ISC", + "dependencies": { + "d3-color": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-path": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz", + "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-polygon": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-polygon/-/d3-polygon-3.0.1.tgz", + "integrity": "sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-quadtree": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-3.0.1.tgz", + "integrity": "sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-random": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-random/-/d3-random-3.0.1.tgz", + "integrity": "sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-sankey": { + "version": "0.12.3", + "resolved": "https://registry.npmjs.org/d3-sankey/-/d3-sankey-0.12.3.tgz", + "integrity": "sha512-nQhsBRmM19Ax5xEIPLMY9ZmJ/cDvd1BG3UVvt5h3WRxKg5zGRbvnteTyWAbzeSvlh3tW7ZEmq4VwR5mB3tutmQ==", + "license": "BSD-3-Clause", + "dependencies": { + "d3-array": "1 - 2", + "d3-shape": "^1.2.0" + } + }, + "node_modules/d3-sankey/node_modules/d3-array": { + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-2.12.1.tgz", + "integrity": "sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ==", + "license": "BSD-3-Clause", + "dependencies": { + "internmap": "^1.0.0" + } + }, + "node_modules/d3-sankey/node_modules/d3-path": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-1.0.9.tgz", + "integrity": "sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg==", + "license": "BSD-3-Clause" + }, + "node_modules/d3-sankey/node_modules/d3-shape": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-1.3.7.tgz", + "integrity": "sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw==", + "license": "BSD-3-Clause", + "dependencies": { + "d3-path": "1" + } + }, + "node_modules/d3-sankey/node_modules/internmap": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/internmap/-/internmap-1.0.1.tgz", + "integrity": "sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw==", + "license": "ISC" + }, + "node_modules/d3-scale": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz", + "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==", + "license": "ISC", + "dependencies": { + "d3-array": "2.10.0 - 3", + "d3-format": "1 - 3", + "d3-interpolate": "1.2.0 - 3", + "d3-time": "2.1.1 - 3", + "d3-time-format": "2 - 4" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-scale-chromatic": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-scale-chromatic/-/d3-scale-chromatic-3.1.0.tgz", + "integrity": "sha512-A3s5PWiZ9YCXFye1o246KoscMWqf8BsD9eRiJ3He7C9OBaxKhAd5TFCdEx/7VbKtxxTsu//1mMJFrEt572cEyQ==", + "license": "ISC", + "dependencies": { + "d3-color": "1 - 3", + "d3-interpolate": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-selection": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz", + "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-shape": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz", + "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==", + "license": "ISC", + "dependencies": { + "d3-path": "^3.1.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-time": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz", + "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==", + "license": "ISC", + "dependencies": { + "d3-array": "2 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-time-format": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz", + "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==", + "license": "ISC", + "dependencies": { + "d3-time": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-timer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", + "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-transition": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-3.0.1.tgz", + "integrity": "sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==", + "license": "ISC", + "dependencies": { + "d3-color": "1 - 3", + "d3-dispatch": "1 - 3", + "d3-ease": "1 - 3", + "d3-interpolate": "1 - 3", + "d3-timer": "1 - 3" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "d3-selection": "2 - 3" + } + }, + "node_modules/d3-zoom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-3.0.0.tgz", + "integrity": "sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==", + "license": "ISC", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-drag": "2 - 3", + "d3-interpolate": "1 - 3", + "d3-selection": "2 - 3", + "d3-transition": "2 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/dagre-d3-es": { + "version": "7.0.13", + "resolved": "https://registry.npmjs.org/dagre-d3-es/-/dagre-d3-es-7.0.13.tgz", + "integrity": "sha512-efEhnxpSuwpYOKRm/L5KbqoZmNNukHa/Flty4Wp62JRvgH2ojwVgPgdYyr4twpieZnyRDdIH7PY2mopX26+j2Q==", + "license": "MIT", + "dependencies": { + "d3": "^7.9.0", + "lodash-es": "^4.17.21" + } + }, "node_modules/damerau-levenshtein": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", @@ -6699,6 +7206,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/dayjs": { + "version": "1.11.19", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.19.tgz", + "integrity": "sha512-t5EcLVS6QPBNqM2z8fakk/NKel+Xzshgt8FFKAn+qwlD1pzZWxh0nVCrvFK7ZDb6XucZeF9z8C7CBWTRIVApAw==", + "license": "MIT" + }, "node_modules/debug": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", @@ -6821,6 +7334,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/delaunator": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/delaunator/-/delaunator-5.0.1.tgz", + "integrity": "sha512-8nvh+XBe96aCESrGOqMp/84b13H9cdKbG5P2ejQCh4d4sK9RL4371qou9drQjMhvnPmhWl5hnmqbEE0fXr9Xnw==", + "license": "ISC", + "dependencies": { + "robust-predicates": "^3.0.2" + } + }, "node_modules/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -7059,6 +7581,15 @@ "url": "https://github.com/fb55/domhandler?sponsor=1" } }, + "node_modules/dompurify": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.3.0.tgz", + "integrity": "sha512-r+f6MYR1gGN1eJv0TVQbhA7if/U7P87cdPl3HN5rikqaBSBxLiCb/b9O+2eG0cxz0ghyU+mU1QkbsOwERMYlWQ==", + "license": "(MPL-2.0 OR Apache-2.0)", + "optionalDependencies": { + "@types/trusted-types": "^2.0.7" + } + }, "node_modules/domutils": { "version": "2.8.0", "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", @@ -7151,6 +7682,12 @@ "integrity": "sha512-FWlQc52z1dXqm+9cCJ2uyFgJkESd+16j6dBEjsgDNuHjBpuIzL8/lRc0uvh1k8RNI6waGo6tcy2DvwkTBJOLDg==", "license": "ISC" }, + "node_modules/elkjs": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/elkjs/-/elkjs-0.9.3.tgz", + "integrity": "sha512-f/ZeWvW/BCXbhGEf1Ujp29EASo/lk1FDnETgNKwJrsVvGZhUWCZyg3xLJjAsxfOmt8KjswHmI5EwCQcPMpOYhQ==", + "license": "EPL-2.0" + }, "node_modules/emittery": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.8.1.tgz", @@ -7469,7 +8006,6 @@ "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", "license": "MIT", - "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", @@ -9693,6 +10229,15 @@ "node": ">= 0.4" } }, + "node_modules/internmap": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz", + "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, "node_modules/invariant": { "version": "2.2.4", "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", @@ -10439,7 +10984,6 @@ "resolved": "https://registry.npmjs.org/jest/-/jest-27.5.1.tgz", "integrity": "sha512-Yn0mADZB89zTtjkPJEXwrac3LHudkQMR+Paqa8uxJHCBr9agxztUifWCyiYrjhMPBoUVBjyny0I7XH6ozDr7QQ==", "license": "MIT", - "peer": true, "dependencies": { "@jest/core": "^27.5.1", "import-local": "^3.0.2", @@ -11519,6 +12063,22 @@ "node": ">=4.0" } }, + "node_modules/katex": { + "version": "0.16.25", + "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.25.tgz", + "integrity": "sha512-woHRUZ/iF23GBP1dkDQMh1QBad9dmr8/PAwNA54VrSOVYgI12MAcE14TqnDdQOdzyEonGzMepYnqBMYdsoAr8Q==", + "funding": [ + "https://opencollective.com/katex", + "https://github.com/sponsors/katex" + ], + "license": "MIT", + "dependencies": { + "commander": "^8.3.0" + }, + "bin": { + "katex": "cli.js" + } + }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", @@ -11528,6 +12088,11 @@ "json-buffer": "3.0.1" } }, + "node_modules/khroma": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/khroma/-/khroma-2.1.0.tgz", + "integrity": "sha512-Ls993zuzfayK269Svk9hzpeGUKob/sIgZzyHYdjQoAdQetRKpOLj+k/QQQ/6Qi0Yz65mlROrfd+Ev+1+7dz9Kw==" + }, "node_modules/kind-of": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", @@ -11583,6 +12148,12 @@ "shell-quote": "^1.8.1" } }, + "node_modules/layout-base": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/layout-base/-/layout-base-1.0.2.tgz", + "integrity": "sha512-8h2oVEZNktL4BH2JCOI90iD1yXwL6iNW7KcCKT2QZgQJR2vbqDsldCTPRU9NifTCqHZci57XvQQ15YTu+sTYPg==", + "license": "MIT" + }, "node_modules/leven": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", @@ -11661,6 +12232,12 @@ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "license": "MIT" }, + "node_modules/lodash-es": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==", + "license": "MIT" + }, "node_modules/lodash.debounce": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", @@ -12094,6 +12671,47 @@ "node": ">= 8" } }, + "node_modules/mermaid": { + "version": "10.9.5", + "resolved": "https://registry.npmjs.org/mermaid/-/mermaid-10.9.5.tgz", + "integrity": "sha512-eRlKEjzak4z1rcXeCd1OAlyawhrptClQDo8OuI8n6bSVqJ9oMfd5Lrf3Q+TdJHewi/9AIOc3UmEo8Fz+kNzzuQ==", + "license": "MIT", + "dependencies": { + "@braintree/sanitize-url": "^6.0.1", + "@types/d3-scale": "^4.0.3", + "@types/d3-scale-chromatic": "^3.0.0", + "cytoscape": "^3.28.1", + "cytoscape-cose-bilkent": "^4.1.0", + "d3": "^7.4.0", + "d3-sankey": "^0.12.3", + "dagre-d3-es": "7.0.13", + "dayjs": "^1.11.7", + "dompurify": "^3.2.4", + "elkjs": "^0.9.0", + "katex": "^0.16.9", + "khroma": "^2.0.0", + "lodash-es": "^4.17.21", + "mdast-util-from-markdown": "^1.3.0", + "non-layered-tidy-tree-layout": "^2.0.2", + "stylis": "^4.1.3", + "ts-dedent": "^2.2.0", + "uuid": "^9.0.0", + "web-worker": "^1.2.0" + } + }, + "node_modules/mermaid/node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/methods": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", @@ -12913,6 +13531,12 @@ "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", "license": "MIT" }, + "node_modules/non-layered-tidy-tree-layout": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/non-layered-tidy-tree-layout/-/non-layered-tidy-tree-layout-2.0.2.tgz", + "integrity": "sha512-gkXMxRzUH+PB0ax9dUN0yYF0S25BqeAYqhgMaLUFmpXLEk7Fcu8f4emJuOAY0V8kjDICxROIKsTAKsV/v355xw==", + "license": "MIT" + }, "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", @@ -13568,7 +14192,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "nanoid": "^3.3.8", "picocolors": "^1.1.1", @@ -14756,7 +15379,6 @@ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", "license": "MIT", - "peer": true, "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -15154,7 +15776,6 @@ "resolved": "https://registry.npmjs.org/react/-/react-19.1.0.tgz", "integrity": "sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==", "license": "MIT", - "peer": true, "engines": { "node": ">=0.10.0" } @@ -15323,7 +15944,6 @@ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.1.0.tgz", "integrity": "sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g==", "license": "MIT", - "peer": true, "dependencies": { "scheduler": "^0.26.0" }, @@ -15402,7 +16022,6 @@ "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz", "integrity": "sha512-F27qZr8uUqwhWZboondsPx8tnC3Ct3SxZA3V5WyEvujRyyNv0VYPhoBg1gZ8/MV5tubQp76Trw8lTv9hzRBa+A==", "license": "MIT", - "peer": true, "engines": { "node": ">=0.10.0" } @@ -16017,12 +16636,17 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/robust-predicates": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/robust-predicates/-/robust-predicates-3.0.2.tgz", + "integrity": "sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==", + "license": "Unlicense" + }, "node_modules/rollup": { "version": "2.79.2", "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.2.tgz", "integrity": "sha512-fS6iqSPZDs3dr/y7Od6y5nha8dW1YnbgtsyotCVvoFGKbERG++CVRFv1meyGDE1SNItQA8BrnCw7ScdAhRJ3XQ==", "license": "MIT", - "peer": true, "bin": { "rollup": "dist/bin/rollup" }, @@ -16095,6 +16719,12 @@ "queue-microtask": "^1.2.2" } }, + "node_modules/rw": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz", + "integrity": "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==", + "license": "BSD-3-Clause" + }, "node_modules/sade": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/sade/-/sade-1.8.1.tgz", @@ -16277,7 +16907,6 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", "license": "MIT", - "peer": true, "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", @@ -17250,6 +17879,12 @@ "postcss": "^8.2.15" } }, + "node_modules/stylis": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.6.tgz", + "integrity": "sha512-yQ3rwFWRfwNUY7H5vpU0wfdkNSnvnJinhF9830Swlaxl03zsOjCfmX0ugac+3LtK0lYSgwL/KXc8oYL3mG4YFQ==", + "license": "MIT" + }, "node_modules/sucrase": { "version": "3.35.0", "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", @@ -17845,6 +18480,15 @@ "integrity": "sha512-c3zayb8/kWWpycWYg87P71E1S1ZL6b6IJxfb5fvsUgsf0S2MVGaDhDXXjDMpdCpfWXqptc+4mXwmiy1ypXqRAA==", "license": "MIT" }, + "node_modules/ts-dedent": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ts-dedent/-/ts-dedent-2.2.0.tgz", + "integrity": "sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==", + "license": "MIT", + "engines": { + "node": ">=6.10" + } + }, "node_modules/ts-interface-checker": { "version": "0.1.13", "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", @@ -17943,7 +18587,6 @@ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", "license": "(MIT OR CC0-1.0)", - "peer": true, "engines": { "node": ">=10" }, @@ -18549,6 +19192,12 @@ "integrity": "sha512-sVWcwhU5mX6crfI5Vd2dC4qchyTqxV8URinzt25XqVh+bHEPGH4C3NPrNionCP7Obx59wrYEbNlw4Z8sjALzZg==", "license": "Apache-2.0" }, + "node_modules/web-worker": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/web-worker/-/web-worker-1.5.0.tgz", + "integrity": "sha512-RiMReJrTAiA+mBjGONMnjVDP2u3p9R1vkcGz6gDIrOMT3oGuYwX2WRMYI9ipkphSuE5XKEhydbhNEJh4NY9mlw==", + "license": "Apache-2.0" + }, "node_modules/webidl-conversions": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz", @@ -18563,7 +19212,6 @@ "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.99.6.tgz", "integrity": "sha512-TJOLrJ6oeccsGWPl7ujCYuc0pIq2cNsuD6GZDma8i5o5Npvcco/z+NKvZSFsP0/x6SShVb0+X2JK/JHUjKY9dQ==", "license": "MIT", - "peer": true, "dependencies": { "@types/eslint-scope": "^3.7.7", "@types/estree": "^1.0.6", @@ -18633,7 +19281,6 @@ "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.15.2.tgz", "integrity": "sha512-0XavAZbNJ5sDrCbkpWL8mia0o5WPOd2YGtxrEiZkBK9FjLppIUK2TgxK6qGD2P3hUXTJNNPVibrerKcx5WkR1g==", "license": "MIT", - "peer": true, "dependencies": { "@types/bonjour": "^3.5.9", "@types/connect-history-api-fallback": "^1.3.5", @@ -19046,7 +19693,6 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", "license": "MIT", - "peer": true, "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", diff --git a/package.json b/package.json index 5aadc12..192725e 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ "react-bootstrap": "^2.10.9", "react-dom": "^19.1.0", "react-jupyter-notebook-viewer": "^1.1.13", + "mermaid": "^10.9.1", "react-router-dom": "^7.5.2", "react-scripts": "5.0.1", "web-vitals": "^2.1.4" diff --git a/src/components/app.jsx b/src/components/app.jsx index b720ddc..fcfa798 100644 --- a/src/components/app.jsx +++ b/src/components/app.jsx @@ -12,11 +12,13 @@ import ServerPage from "./projects/server"; import LanguagestudyPage from "./projects/languageStudy"; import OnlineCasinoPage from "./finalprojects/onlineCasino"; import WohnungUndFahrgemeinschaftenPage from "./finalprojects/wohnungUndFahrgemeinschaften"; +import KrimiDinnerPage from "./finalprojects/krimiDinner"; function Home() { return ; } + function About() { return ; } @@ -52,6 +54,11 @@ function OnlineCasino() { function WohnungUndFahrgemeinschaften() { return } + +function KrimiDinner() { + return +} + function App() { return ( @@ -68,6 +75,7 @@ function App() { } /> } /> } /> + } /> diff --git a/src/components/finalprojects/krimiDinner.jsx b/src/components/finalprojects/krimiDinner.jsx new file mode 100644 index 0000000..432d675 --- /dev/null +++ b/src/components/finalprojects/krimiDinner.jsx @@ -0,0 +1,307 @@ +import React, { useEffect } from "react"; +import { Container, Row, Col, Card, Badge, Table } from "react-bootstrap"; +import mermaid from "mermaid"; + +function KrimiDinner() { + useEffect(() => { + mermaid.initialize({ startOnLoad: false, theme: 'neutral' }); + mermaid.contentLoaded(); + }, []); + + return ( +
+ +
+

Projekt-Blaupause: KI-Krimi-Dinner "Projekt Chimera"

+
+
+ Version + 3.0 (Final & Complete UI) +
+
+ Autor + D. Schuhbaum & S. Altschäffl +
+
+ Datum + 03.10.2025 +
+
+
+ +
+

1. Projektübersicht

+

+ "Projekt Chimera" ist ein hybrides Krimi-Dinner-Erlebnis, das + physische soziale Interaktion mit einer digitalen App-Komponente + verbindet. Das Alleinstellungsmerkmal ist der Einsatz einer + zweistufigen KI-Architektur, die nicht nur einzigartige narrative + Szenarien generiert, sondern diese auch proaktiv auf logische + Konsistenz validiert und korrigiert. +

+

+ Die Architektur basiert auf einer klaren Trennung:{" "} + Supabase dient als dedizierter Service für die + Benutzerauthentifizierung, während alle Spieldaten (Szenarien, + Spieler, Spielstände) in einer{" "} + separaten, dedizierten PostgreSQL-Datenbank{" "} + gehostet werden. Ein zentrales FastAPI-Backend{" "} + fungiert als sichere Schnittstelle zwischen den Clients und + beiden Diensten. +

+
+ +
+

2. Narratives Design & Validierung

+

+ Die Generierung jedes Spiels folgt einem strengen, zweistufigen + Prozess, um die narrative Qualität und logische Integrität zu + gewährleisten. +

+ + + + + Schritt 1: Kreative Generierung (Der "Autor") + + In dieser Phase agiert die KI als kreativer Autor. Sie erhält einen umfassenden Prompt, der die gewünschten Rahmenbedingungen vorgibt. + +
    +
  • Hintergrundgeschichte
  • +
  • Charaktere
  • +
  • Geheimnisse & Ziele
  • +
  • Der Mord & lückenloser Zeitstrahl
  • +
  • Beziehungsgeflecht
  • +
  • Hinweise
  • +
+
+
+ + + + + Schritt 2: Logische Validierung & Korrektur (Der "Logik-Lektor") + + Der rohe Output wird an eine zweite KI-Instanz übergeben, die als akribischer Logik-Lektor agiert und das Szenario auf Fehler überprüft. + +
    +
  • Widersprüche in Zeitlinien
  • +
  • Motiv-Konsistenz
  • +
  • Hinweis-Validität
  • +
  • Charakter-Konsistenz
  • +
  • Regelkonformität
  • +
+
+
+ +
+
+ +
+

3. Technische Architektur

+

+ Die Architektur ist auf maximale Kontrolle und Skalierbarkeit ausgelegt. Die React Native-Clients kommunizieren ausschließlich mit dem FastAPI-Backend. Echtzeit-Updates werden über eine WebSocket-Verbindung gepusht. +

+
+
+              {`
+                graph TD
+                    subgraph "Spieler-Geräte"
+                        P1["React Native Apps"]
+                    end
+                    subgraph "Authentifizierung"
+                        Auth["Supabase Auth"]
+                    end
+                    subgraph "Sicheres Backend"
+                        FastAPI["FastAPI Server 
REST & WebSockets"] + end + subgraph "Spieldaten-Bank" + PG_DB["PostgreSQL DB"] + end + subgraph "Externe Dienste" + OAI["OpenAI API"] + end + P1 -- "1. Login" --> Auth + P1 -- "2. API Calls (mit Token)" --> FastAPI + FastAPI -- "3. KI Call" --> OAI + FastAPI -- "4. DB-Zugriff" --> PG_DB + FastAPI -- "5. WebSocket Updates" --> P1 + `} +
+
+

Datenfluss-Beschreibung:

+
    +
  1. Authentifizierung: Benutzer authentifiziert sich bei Supabase Auth und erhält ein JWT.
  2. +
  3. API-Anfragen: Die App sendet Anfragen mit dem JWT an den FastAPI-Server.
  4. +
  5. KI-Generierung: FastAPI ruft die OpenAI-API für die Spielerstellung auf.
  6. +
  7. Datenbank-Interaktion: FastAPI ist die einzige Komponente, die mit der PostgreSQL-DB kommuniziert.
  8. +
  9. Echtzeit-Updates: Clients bauen eine WebSocket-Verbindung zum FastAPI-Server auf.
  10. +
+
+ +
+

4. User Interface (UI) Konzept

+

Die UI-Konzepte werden als klare, moderne Wireframes visualisiert, um den gesamten App-Flow darzustellen.

+ + {[ + {title: "1. Login", content: "Standard-Login-Formular mit E-Mail und Passwort."}, + {title: "2. Registrierung", content: "Formular zur Erstellung eines neuen Kontos."}, + {title: "3. Home Dashboard", content: "Übersicht der Spiele des Nutzers und Optionen, ein neues Spiel zu starten oder einem beizutreten."}, + {title: "4. Spiel erstellen", content: "Formular zur Definition des Szenarios und der Rundenanzahl."}, + {title: "5. Host-Lobby", content: "Anzeige des Spiel-Codes und der beigetretenen Spieler."}, + {title: "6. Spieler-Ansicht (Rolle)", content: "Anzeige der zugewiesenen Rolle, Ziele und Geheimnisse."}, + {title: "7. Spieler-Ansicht (Hinweise)", content: "Darstellung der pro Runde freigeschalteten Hinweise."}, + {title: "8. Auflösung", content: "Enthüllung des Mörders und des Abstimmungsergebnisses."}, + {title: "9. Host Notfall-Dashboard", content: "Steuerungselemente für den Host, um das Spiel zu managen."} + ].map(item => ( + + + {item.title} + + {item.content} + + + + ))} + +
+ +
+

5. API-Endpunkte & Datenbank-Interaktion

+ + +

FastAPI-Backend

+
    +
  • POST /game/create
  • +
  • POST /game/{'{game_code}'}/join
  • +
  • GET /game/{'{game_code}'}/state
  • +
  • POST /game/{'{game_code}'}/vote
  • +
  • GET /game/{'{game_code}'}/character
  • +
  • /ws/{'{game_code}'}
  • +
+ + +

Client-Interaktionen

+
    +
  • Supabase Auth (`supabase-js`): Nur für Login, Registrierung und Auth-Zustand.
  • +
  • API-Client (z.B. Axios): Für alle HTTP-Anfragen an das FastAPI-Backend.
  • +
  • WebSocket-Client: Für Echtzeit-Verbindung zum Backend.
  • +
+ +
+
+ +
+

6. Datenmodelle

+

Die dedizierte PostgreSQL-Datenbank enthält die gesamte Spiellogik.

+

Tabelle: `games`

+ + + + + + + + + + + +
SpalteDatentypBeschreibung
iduuidEindeutige ID für ein Spiel.
host_iduuidReferenz auf die User-ID des Hosts.
game_codevarcharKurzer Code zum Beitreten.
statusvarcharsetup, lobby, active, finished.
game_datajsonbDas komplette KI-generierte Szenario.
+ +

Tabelle: `players`

+ + + + + + + + + + + +
SpalteDatentypBeschreibung
iduuidEindeutiger Eintrag für einen Spieler.
game_iduuidVerweist auf das zugehörige Spiel.
player_iduuidReferenz auf die User-ID aus Supabase.
player_namevarcharDer im Spiel angezeigte Name.
character_idvarcharVerknüpft den Spieler mit seiner Rolle.
+
+ +
+

7. Prompt-Engineering-Strategie

+ + + + + Prompt 1: Der kreative Autor + System-Prompt: +
Du bist ein preisgekrönter Autor von Kriminalromanen...
+ User-Prompt: +
Erstelle ein Krimi-Dinner-Szenario für 5 Spieler...
+
+
+ + + + + Prompt 2: Der Logik-Lektor + System-Prompt: +
Du bist ein extrem detailorientierter und logisch denkender Lektor...
+ User-Prompt: +
Hier ist ein JSON-Objekt. Bitte agiere als Logik-Lektor...
+
+
+ +
+
+ +
+

8. User Journey & Spielablauf

+
    +
  1. Phase 0: Generierung & Vorbereitung: Host generiert Spiel und erhält Einladungscode.
  2. +
  3. Phase 1: Lobby: Spieler treten bei, Host startet das Spiel.
  4. +
  5. Phase 2: Rollenverteilung: Backend weist Rollen zu und sendet geheime Infos.
  6. +
  7. Phase 3: Spielrunden: System gibt pro Runde neue Hinweise frei.
  8. +
  9. Phase 4: Abstimmung & Auflösung: Abstimmung wird freigeschaltet, Mörder wird enthüllt.
  10. +
+
+ +
+

9. Geschäftsmodell & Monetarisierung

+ + +
+

Abonnement-Modell

+

Nutzer zahlen einen monatlichen oder jährlichen Beitrag für ein festes Kontingent an Spielen.

+
+ + +
+

Einmalkauf (Pay-per-Game)

+

Alternativ können Nutzer einzelne Spiele per Einmalkauf freischalten.

+
+ +
+
+ +
+

10. Skalierbarkeit, Kosten & Fehlerbehandlung

+
    +
  • Kostenkontrolle (OpenAI): Rate-Limiting auf dem Endpunkt zur Spielerstellung.
  • +
  • Fehlerbehandlung bei Generierung: Backend unternimmt automatische Wiederholungsversuche.
  • +
  • Nahtloses Wiederverbinden: Spieler können jederzeit wieder in ein laufendes Spiel einsteigen.
  • +
  • Notfall-Dashboard (Host): Spoiler-freies Admin-Panel für den Host zur Spielsteuerung.
  • +
+
+ +
+

11. Rechtliches & Datenschutz

+
    +
  • DSGVO-konforme Datenschutzerklärung
  • +
  • Impressum
  • +
  • Möglichkeit zur Löschung des Accounts
  • +
+
+ +
+
+ ); +} + +export default KrimiDinner; \ No newline at end of file