605 lines
50 KiB
HTML
605 lines
50 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="de">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Projekt-Blaupause: KI-Krimi-Dinner "Projekt Chimera"</title>
|
|
<!-- TailwindCSS & Mermaid.js via CDN -->
|
|
<script src="https://cdn.tailwindcss.com"></script>
|
|
<script src="https://cdn.jsdelivr.net/npm/mermaid@10.9.1/dist/mermaid.min.js"></script>
|
|
<style>
|
|
/* Minimal body styles to prevent flash of unstyled content */
|
|
body {
|
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
|
|
background-color: #f9fafb;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body class="bg-gray-100 text-gray-800">
|
|
<div class="container mx-auto max-w-7xl p-4 sm:p-8">
|
|
<div class="bg-white rounded-xl shadow-lg p-6 sm:p-10">
|
|
|
|
<header class="mb-10 text-center border-b pb-8">
|
|
<h1 class="text-4xl sm:text-5xl font-bold text-gray-900">Projekt-Blaupause: KI-Krimi-Dinner "Projekt Chimera"</h1>
|
|
<div class="mt-6 grid grid-cols-1 sm:grid-cols-3 gap-4 max-w-2xl mx-auto">
|
|
<div class="bg-gray-50 p-3 rounded-lg">
|
|
<span class="block text-xs font-semibold text-gray-500 uppercase tracking-wider">Version</span>
|
|
<span class="text-gray-800 font-medium">3.0 (Final & Complete UI)</span>
|
|
</div>
|
|
<div class="bg-gray-50 p-3 rounded-lg">
|
|
<span class="block text-xs font-semibold text-gray-500 uppercase tracking-wider">Autor</span>
|
|
<span class="text-gray-800 font-medium">D. Schuhbaum & S. Altschäffl</span>
|
|
</div>
|
|
<div class="bg-gray-50 p-3 rounded-lg">
|
|
<span class="block text-xs font-semibold text-gray-500 uppercase tracking-wider">Datum</span>
|
|
<span class="text-gray-800 font-medium">03.10.2025</span>
|
|
</div>
|
|
</div>
|
|
</header>
|
|
|
|
<section class="mb-10">
|
|
<h2 class="text-2xl font-semibold text-gray-800 border-b pb-2 mb-4">1. Projektübersicht</h2>
|
|
<p>"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.</p>
|
|
<p>Die Architektur basiert auf einer klaren Trennung: <strong>Supabase</strong> dient als dedizierter Service für die Benutzerauthentifizierung, während alle Spieldaten (Szenarien, Spieler, Spielstände) in einer <strong>separaten, dedizierten PostgreSQL-Datenbank</strong> gehostet werden. Ein zentrales <strong>FastAPI-Backend</strong> fungiert als sichere Schnittstelle zwischen den Clients und beiden Diensten.</p>
|
|
</section>
|
|
|
|
<section class="mb-10">
|
|
<h2 class="text-2xl font-semibold text-gray-800 border-b pb-2 mb-4">2. Narratives Design & Validierung</h2>
|
|
<p>Die Generierung jedes Spiels folgt einem strengen, zweistufigen Prozess, um die narrative Qualität und logische Integrität zu gewährleisten.</p>
|
|
|
|
<div class="mt-6 space-y-6">
|
|
<div>
|
|
<h3 class="text-xl font-semibold mb-2">Schritt 1: Kreative Generierung (Der "Autor")</h3>
|
|
<p>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.</p>
|
|
<ul class="list-disc list-inside space-y-2 bg-gray-50 p-4 rounded-lg mt-4">
|
|
<li><strong>Hintergrundgeschichte:</strong> Der Rahmen des Geschehens und der Grund für das Zusammentreffen.</li>
|
|
<li><strong>Charaktere:</strong> Detaillierte Rollen mit Persönlichkeit, Beziehungen und öffentlichen Informationen.</li>
|
|
<li><strong>Geheimnisse & Ziele:</strong> Private Geheimnisse und spielrelevante Ziele für jeden Charakter.</li>
|
|
<li><strong>Der Mord & lückenloser Zeitstrahl:</strong> 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.</li>
|
|
<li><strong>Beziehungsgeflecht:</strong> Eine Matrix der komplexen Beziehungen zwischen allen Charakteren.</li>
|
|
<li><strong>Hinweise:</strong> Ein Set von Hinweisen, die den Mörder belasten oder falsche Fährten legen, aufgeteilt auf die gewählte Rundenanzahl.</li>
|
|
</ul>
|
|
</div>
|
|
<div>
|
|
<h3 class="text-xl font-semibold mb-2">Schritt 2: Logische Validierung & Korrektur (Der "Logik-Lektor")</h3>
|
|
<p>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:</p>
|
|
<ul class="list-disc list-inside space-y-2 bg-gray-50 p-4 rounded-lg mt-4">
|
|
<li><strong>Widersprüche in Zeitlinien:</strong> Passen Alibis und die Zeitblöcke auf den Zeitstrahlen aller Charaktere lückenlos und widerspruchsfrei zusammen?</li>
|
|
<li><strong>Motiv-Konsistenz:</strong> Ist das Motiv des Mörders stark genug und logisch begründet?</li>
|
|
<li><strong>Hinweis-Validität:</strong> Führt mindestens ein entscheidender Hinweis logisch zum Täter? Sind falsche Fährten subtil?</li>
|
|
<li><strong>Charakter-Konsistenz:</strong> Handeln die Charaktere gemäß ihrer beschriebenen Persönlichkeit und Ziele?</li>
|
|
<li><strong>Regelkonformität:</strong> Ist das Spiel fair und lösbar?</li>
|
|
</ul>
|
|
<p class="mt-4">Die KI korrigiert gefundene Fehler minimalinvasiv, um die kreative Essenz nicht zu verändern, und gibt ein logisch wasserdichtes Spielszenario aus.</p>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<section class="mb-10">
|
|
<h2 class="text-2xl font-semibold text-gray-800 border-b pb-2 mb-4">3. Technische Architektur</h2>
|
|
<p class="mb-4">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.</p>
|
|
|
|
<div class="bg-gray-50 p-4 sm:p-8 rounded-lg w-full overflow-x-auto">
|
|
<pre class="mermaid text-center">
|
|
graph TD
|
|
subgraph "Spieler-Geräte"
|
|
P1["React Native Apps"]
|
|
end
|
|
|
|
subgraph "Authentifizierung"
|
|
Auth["Supabase Auth"]
|
|
end
|
|
|
|
subgraph "Sicheres Backend"
|
|
FastAPI["FastAPI Server <br> 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
|
|
</pre>
|
|
</div>
|
|
|
|
<h3 class="text-xl font-semibold mt-6 mb-3">Datenfluss-Beschreibung:</h3>
|
|
<ol class="list-decimal list-inside space-y-3">
|
|
<li><strong>Authentifizierung:</strong> Der Benutzer authentifiziert sich in der React Native-App direkt bei <strong>Supabase Auth</strong>. Die App erhält ein JWT (JSON Web Token).</li>
|
|
<li><strong>API-Anfragen:</strong> Für <strong>alle</strong> spielrelevanten Aktionen sendet die App eine Anfrage an den <strong>FastAPI-Server</strong> und fügt das JWT von Supabase in den Authorization-Header ein. FastAPI validiert dieses Token.</li>
|
|
<li><strong>KI-Generierung:</strong> Für die Spielerstellung ruft der FastAPI-Server die <strong>OpenAI-API</strong> auf.</li>
|
|
<li><strong>Datenbank-Interaktion:</strong> FastAPI ist die <strong>einzige</strong> Komponente, die mit der <strong>dedizierten PostgreSQL-Datenbank</strong> kommuniziert.</li>
|
|
<li><strong>Echtzeit-Updates:</strong> Die Clients bauen eine <strong>WebSocket-Verbindung</strong> zum FastAPI-Server auf. Bei Änderungen pusht der Server Updates an alle verbundenen Clients.</li>
|
|
</ol>
|
|
</section>
|
|
|
|
<section class="mb-10">
|
|
<h2 class="text-2xl font-semibold text-gray-800 border-b pb-2 mb-4">4. User Interface (UI) Konzept</h2>
|
|
<p class="mb-6">Die UI-Konzepte werden als klare, moderne Wireframes visualisiert, um den gesamten App-Flow von der Erstellung bis zum Spiel darzustellen.</p>
|
|
<div class="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-8">
|
|
|
|
<!-- Wireframe 1: Login -->
|
|
<div class="bg-gray-50 p-4 rounded-lg border">
|
|
<h3 class="text-lg font-semibold mb-3 text-center">1. Login</h3>
|
|
<div class="bg-white w-full max-w-sm mx-auto aspect-[9/19.5] rounded-2xl shadow-lg p-3 border flex flex-col">
|
|
<div class="text-center pt-8 pb-6">
|
|
<h4 class="font-bold text-xl tracking-tight">PROJEKT CHIMERA</h4>
|
|
</div>
|
|
<div class="px-3 space-y-3 flex-grow">
|
|
<input type="text" placeholder="E-Mail-Adresse" class="w-full border rounded-md p-2 text-sm bg-gray-100 focus:outline-none focus:ring-2 focus:ring-blue-500">
|
|
<input type="password" placeholder="Passwort" class="w-full border rounded-md p-2 text-sm bg-gray-100 focus:outline-none focus:ring-2 focus:ring-blue-500">
|
|
<button class="w-full bg-blue-600 text-white rounded-md py-2 font-semibold hover:bg-blue-700 transition-colors">Anmelden</button>
|
|
<p class="text-center text-xs text-gray-500">Noch kein Konto? <a href="#" class="font-semibold text-blue-600">Jetzt registrieren</a></p>
|
|
</div>
|
|
<div class="h-8"></div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Wireframe 2: Registration -->
|
|
<div class="bg-gray-50 p-4 rounded-lg border">
|
|
<h3 class="text-lg font-semibold mb-3 text-center">2. Registrierung</h3>
|
|
<div class="bg-white w-full max-w-sm mx-auto aspect-[9/19.5] rounded-2xl shadow-lg p-3 border flex flex-col">
|
|
<div class="text-center pt-8 pb-6">
|
|
<h4 class="font-bold text-xl tracking-tight">Konto erstellen</h4>
|
|
</div>
|
|
<div class="px-3 space-y-3 flex-grow">
|
|
<input type="text" placeholder="E-Mail-Adresse" class="w-full border rounded-md p-2 text-sm bg-gray-100 focus:outline-none focus:ring-2 focus:ring-blue-500">
|
|
<input type="password" placeholder="Passwort" class="w-full border rounded-md p-2 text-sm bg-gray-100 focus:outline-none focus:ring-2 focus:ring-blue-500">
|
|
<input type="password" placeholder="Passwort bestätigen" class="w-full border rounded-md p-2 text-sm bg-gray-100 focus:outline-none focus:ring-2 focus:ring-blue-500">
|
|
<button class="w-full bg-blue-600 text-white rounded-md py-2 font-semibold hover:bg-blue-700 transition-colors">Registrieren</button>
|
|
<p class="text-center text-xs text-gray-500">Bereits ein Konto? <a href="#" class="font-semibold text-blue-600">Zum Login</a></p>
|
|
</div>
|
|
<div class="h-8"></div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Wireframe 3: Home Dashboard -->
|
|
<div class="bg-gray-50 p-4 rounded-lg border">
|
|
<h3 class="text-lg font-semibold mb-3 text-center">3. Home Dashboard</h3>
|
|
<div class="bg-white w-full max-w-sm mx-auto aspect-[9/19.5] rounded-2xl shadow-lg p-3 border flex flex-col">
|
|
<div class="p-4 flex justify-between items-center border-b">
|
|
<h4 class="font-bold text-lg">Deine Spiele</h4>
|
|
<button class="text-xs text-gray-500 hover:text-blue-600">Logout</button>
|
|
</div>
|
|
<div class="p-3 flex-grow overflow-y-auto space-y-3">
|
|
<div class="bg-gray-100 border rounded-lg p-3">
|
|
<p class="font-bold">Tech-Konferenz 2035</p>
|
|
<p class="text-xs text-gray-600 mt-1">Status: <span class="font-semibold text-green-600">Aktiv (Runde 2/3)</span></p>
|
|
<button class="w-full mt-2 bg-blue-600 text-white rounded-md py-1 text-sm font-semibold">Weiterspielen</button>
|
|
</div>
|
|
<div class="bg-gray-100 border rounded-lg p-3">
|
|
<p class="font-bold">Villa Vendetta</p>
|
|
<p class="text-xs text-gray-600 mt-1">Status: <span class="font-semibold text-gray-500">Lobby (0 Spieler)</span></p>
|
|
<button class="w-full mt-2 bg-blue-600 text-white rounded-md py-1 text-sm font-semibold">Zur Lobby</button>
|
|
</div>
|
|
</div>
|
|
<div class="p-3 grid grid-cols-2 gap-3 border-t">
|
|
<button class="bg-green-100 text-green-800 rounded-md py-2 font-semibold text-sm hover:bg-green-200">Neues Spiel</button>
|
|
<button class="bg-gray-100 text-gray-800 rounded-md py-2 font-semibold text-sm hover:bg-gray-200">Beitreten</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Wireframe 4: Spiel erstellen -->
|
|
<div class="bg-gray-50 p-4 rounded-lg border">
|
|
<h3 class="text-lg font-semibold mb-3 text-center">4. Spiel erstellen (Host)</h3>
|
|
<div class="bg-white w-full max-w-sm mx-auto aspect-[9/19.5] rounded-2xl shadow-lg p-3 border flex flex-col">
|
|
<div class="text-center pt-4 pb-3 border-b">
|
|
<h4 class="font-bold text-lg">Neues Spiel erstellen</h4>
|
|
</div>
|
|
<div class="px-3 py-4 flex-grow space-y-4">
|
|
<div>
|
|
<label class="font-semibold text-sm">Szenario-Beschreibung</label>
|
|
<textarea placeholder="z.B. Ein Mord auf einer Tech-Konferenz im Jahr 2035..." class="w-full mt-1 border rounded-md p-2 text-sm bg-gray-100 focus:outline-none focus:ring-2 focus:ring-blue-500 h-24"></textarea>
|
|
</div>
|
|
<div>
|
|
<label class="font-semibold text-sm">Rundenanzahl</label>
|
|
<div class="flex items-center justify-between mt-1">
|
|
<input type="range" min="2" max="5" value="3" class="w-full">
|
|
<span class="ml-4 font-bold text-lg w-8 text-center">3</span>
|
|
</div>
|
|
</div>
|
|
<div class="text-xs text-gray-500">
|
|
<p>Die Spieleranzahl ist flexibel (mind. 3 Spieler) und wird in der Lobby durch die Anzahl der beigetretenen Spieler bestimmt.</p>
|
|
</div>
|
|
</div>
|
|
<div class="px-3 pb-3">
|
|
<button class="w-full bg-blue-600 text-white rounded-md py-2 font-semibold hover:bg-blue-700 transition-colors">Szenario generieren & Lobby öffnen</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Wireframe 5: Host-Lobby (Initial) -->
|
|
<div class="bg-gray-50 p-4 rounded-lg border">
|
|
<h3 class="text-lg font-semibold mb-3 text-center">5. Host-Lobby</h3>
|
|
<div class="bg-white w-full max-w-sm mx-auto aspect-[9/19.5] rounded-2xl shadow-lg p-3 border flex flex-col">
|
|
<div class="text-center pt-4 pb-3 border-b">
|
|
<p class="text-xs text-gray-500">Spiel-Lobby</p>
|
|
<h4 class="font-bold text-lg">Tech-Konferenz 2035</h4>
|
|
</div>
|
|
<div class="px-3 py-4 text-center flex-grow">
|
|
<p class="text-sm text-gray-600">Teile diesen Code mit deinen Mitspielern:</p>
|
|
<div class="my-3 bg-blue-50 border-2 border-dashed border-blue-200 text-blue-800 font-bold text-3xl tracking-widest py-3 rounded-lg">
|
|
GHY-781
|
|
</div>
|
|
<h5 class="font-semibold text-left mt-6 mb-2">Beigetretene Spieler (3)</h5>
|
|
<ul class="space-y-2 text-left">
|
|
<li class="bg-gray-100 p-2 rounded-md flex justify-between items-center"><span>Maria</span> <button class="text-red-500 text-xs">Entfernen</button></li>
|
|
<li class="bg-gray-100 p-2 rounded-md flex justify-between items-center"><span>Jonas</span> <button class="text-red-500 text-xs">Entfernen</button></li>
|
|
<li class="bg-gray-100 p-2 rounded-md flex justify-between items-center"><span>Sandra</span> <button class="text-red-500 text-xs">Entfernen</button></li>
|
|
</ul>
|
|
</div>
|
|
<div class="px-3 pb-3 space-y-2">
|
|
<button class="w-full bg-red-100 text-red-800 rounded-md py-2 font-semibold text-xs hover:bg-red-200">Szenario verwerfen & Neu generieren</button>
|
|
<button class="w-full bg-green-600 text-white rounded-md py-2 font-semibold">Spiel starten (3 Spieler)</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Wireframe 6: Spieler-Ansicht (Rolle) -->
|
|
<div class="bg-gray-50 p-4 rounded-lg border">
|
|
<h3 class="text-lg font-semibold mb-3 text-center">6. Spieler-Ansicht (Rolle)</h3>
|
|
<div class="bg-white w-full max-w-sm mx-auto aspect-[9/19.5] rounded-2xl shadow-lg p-3 border flex flex-col">
|
|
<div class="p-3 text-center border-b">
|
|
<p class="text-xs text-gray-400">Deine Rolle</p>
|
|
<h4 class="font-bold text-lg">Dr. Aris Thorne</h4>
|
|
</div>
|
|
<div class="flex border-b">
|
|
<button class="flex-1 p-2 text-sm font-semibold border-b-2 border-blue-600 text-blue-600">Rolle</button>
|
|
<button class="flex-1 p-2 text-sm font-semibold text-gray-400 hover:bg-gray-50">Hinweise</button>
|
|
<button class="flex-1 p-2 text-sm font-semibold text-gray-400 hover:bg-gray-50">Charaktere</button>
|
|
<button class="flex-1 p-2 text-sm font-semibold text-gray-400 hover:bg-gray-50">Zeitstrahl</button>
|
|
</div>
|
|
<div class="p-3 flex-grow overflow-y-auto text-sm text-gray-700 space-y-3">
|
|
<h5 class="font-bold">Deine Ziele:</h5>
|
|
<ul class="list-disc list-inside text-xs space-y-1">
|
|
<li>Finde heraus, wer deine Forschung sabotiert hat.</li>
|
|
<li>Verhindere, dass dein Geheimnis über das gescheiterte Experiment ans Licht kommt.</li>
|
|
</ul>
|
|
<h5 class="font-bold pt-2">Deine Geheimnisse:</h5>
|
|
<p class="text-xs">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.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Wireframe 6: Spieler-Ansicht (Hinweise) -->
|
|
<div class="bg-gray-50 p-4 rounded-lg border">
|
|
<h3 class="text-lg font-semibold mb-3 text-center">6. Spieler-Ansicht (Hinweise)</h3>
|
|
<div class="bg-white w-full max-w-sm mx-auto aspect-[9/19.5] rounded-2xl shadow-lg p-3 border flex flex-col">
|
|
<div class="p-3 text-center border-b">
|
|
<p class="text-xs text-gray-400">Deine Rolle</p>
|
|
<h4 class="font-bold text-lg">Dr. Aris Thorne</h4>
|
|
</div>
|
|
<div class="flex border-b">
|
|
<button class="flex-1 p-2 text-sm font-semibold text-gray-400 hover:bg-gray-50">Rolle</button>
|
|
<button class="flex-1 p-2 text-sm font-semibold border-b-2 border-blue-600 text-blue-600 relative">Hinweise<span class="absolute top-1 right-2 w-2 h-2 bg-red-500 rounded-full"></span></button>
|
|
<button class="flex-1 p-2 text-sm font-semibold text-gray-400 hover:bg-gray-50">Charaktere</button>
|
|
<button class="flex-1 p-2 text-sm font-semibold text-gray-400 hover:bg-gray-50">Zeitstrahl</button>
|
|
</div>
|
|
<div class="p-3 flex-grow overflow-y-auto text-sm text-gray-700 space-y-4">
|
|
<div>
|
|
<h5 class="font-bold text-base">Runde 2 (18:00 - 19:00 Uhr)</h5>
|
|
<div class="bg-yellow-50 border border-yellow-200 rounded-lg p-3 mt-2">
|
|
<p class="font-semibold text-xs text-yellow-800">HINWEIS #3</p>
|
|
<p class="text-xs text-yellow-900 mt-1">Ein zerrissener Brief wurde gefunden. Die Worte "Schulden" und "letzte Warnung" sind lesbar.</p>
|
|
</div>
|
|
</div>
|
|
<div class="opacity-60">
|
|
<h5 class="font-bold text-base">Runde 1 (16:00 - 18:00 Uhr)</h5>
|
|
<div class="bg-gray-100 border rounded-lg p-3 mt-2">
|
|
<p class="font-semibold text-xs text-gray-600">HINWEIS #1</p>
|
|
<p class="text-xs text-gray-700 mt-1">Das Opfer wurde mit einem schweren Gegenstand erschlagen.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Wireframe 7: Spieler-Ansicht (Charaktere) -->
|
|
<div class="bg-gray-50 p-4 rounded-lg border">
|
|
<h3 class="text-lg font-semibold mb-3 text-center">7. Spieler-Ansicht (Charaktere)</h3>
|
|
<div class="bg-white w-full max-w-sm mx-auto aspect-[9/19.5] rounded-2xl shadow-lg p-3 border flex flex-col">
|
|
<div class="p-3 text-center border-b">
|
|
<p class="text-xs text-gray-400">Deine Rolle</p>
|
|
<h4 class="font-bold text-lg">Dr. Aris Thorne</h4>
|
|
</div>
|
|
<div class="flex border-b">
|
|
<button class="flex-1 p-2 text-sm font-semibold text-gray-400 hover:bg-gray-50">Rolle</button>
|
|
<button class="flex-1 p-2 text-sm font-semibold text-gray-400 hover:bg-gray-50">Hinweise</button>
|
|
<button class="flex-1 p-2 text-sm font-semibold border-b-2 border-blue-600 text-blue-600">Charaktere</button>
|
|
<button class="flex-1 p-2 text-sm font-semibold text-gray-400 hover:bg-gray-50">Zeitstrahl</button>
|
|
</div>
|
|
<div class="p-3 flex-grow overflow-y-auto text-sm text-gray-700 space-y-3">
|
|
<div class="bg-gray-50 border rounded-lg p-3">
|
|
<p class="font-bold">Evelyn Reed (CEO)</p>
|
|
<p class="text-xs text-gray-600 mt-1">Die ehrgeizige CEO des Konkurrenzunternehmens. Es ist bekannt, dass sie und das Opfer eine erbitterte Rivalität pflegten.</p>
|
|
</div>
|
|
<div class="bg-gray-50 border rounded-lg p-3">
|
|
<p class="font-bold">Ivan Petrov (Sicherheitschef)</p>
|
|
<p class="text-xs text-gray-600 mt-1">Der loyale, aber jähzornige Sicherheitschef. Er war für den Schutz des Opfers verantwortlich.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Wireframe 7: Spieler-Ansicht (Zeitstrahl) -->
|
|
<div class="bg-gray-50 p-4 rounded-lg border">
|
|
<h3 class="text-lg font-semibold mb-3 text-center">7. Spieler-Ansicht (Zeitstrahl)</h3>
|
|
<div class="bg-white w-full max-w-sm mx-auto aspect-[9/19.5] rounded-2xl shadow-lg p-3 border flex flex-col">
|
|
<div class="p-3 text-center border-b">
|
|
<p class="text-xs text-gray-400">Deine Rolle</p>
|
|
<h4 class="font-bold text-lg">Dr. Aris Thorne</h4>
|
|
</div>
|
|
<div class="flex border-b">
|
|
<button class="flex-1 p-2 text-sm font-semibold text-gray-400 hover:bg-gray-50">Rolle</button>
|
|
<button class="flex-1 p-2 text-sm font-semibold text-gray-400 hover:bg-gray-50">Hinweise</button>
|
|
<button class="flex-1 p-2 text-sm font-semibold text-gray-400 hover:bg-gray-50">Charaktere</button>
|
|
<button class="flex-1 p-2 text-sm font-semibold border-b-2 border-blue-600 text-blue-600">Zeitstrahl</button>
|
|
</div>
|
|
<div class="p-3 flex-grow overflow-y-auto text-sm text-gray-700">
|
|
<h5 class="font-bold text-base mb-4">Dein persönlicher Zeitstrahl</h5>
|
|
<div class="relative border-l-2 border-gray-200 space-y-4">
|
|
<div class="relative pl-6">
|
|
<div class="absolute -left-[7px] top-1 w-3 h-3 bg-blue-500 rounded-full border-2 border-white"></div>
|
|
<div class="bg-blue-50 p-2 rounded-lg border border-blue-100">
|
|
<p class="font-semibold text-xs text-blue-800">16:30 - 16:45 Uhr</p>
|
|
<p class="text-xs text-blue-900 mt-1">Streitgespräch mit dem Opfer im Labor.</p>
|
|
</div>
|
|
</div>
|
|
<div class="relative pl-6">
|
|
<div class="absolute -left-[7px] top-1 w-3 h-3 bg-gray-400 rounded-full border-2 border-white"></div>
|
|
<div class="bg-gray-50 p-2 rounded-lg border border-gray-200">
|
|
<p class="font-semibold text-xs text-gray-600">16:45 - 17:00 Uhr</p>
|
|
<p class="text-xs text-gray-700 mt-1">Alleine im Büro, E-Mails beantwortet.</p>
|
|
</div>
|
|
</div>
|
|
<div class="relative pl-6">
|
|
<div class="absolute -left-[7px] top-1 w-3 h-3 bg-green-500 rounded-full border-2 border-white"></div>
|
|
<div class="bg-green-50 p-2 rounded-lg border border-green-100">
|
|
<p class="font-semibold text-xs text-green-800">17:00 - 17:20 Uhr</p>
|
|
<p class="text-xs text-green-900 mt-1">Gespräch mit Ivan Petrov in der Cafeteria. <span class="font-bold">(Dein Alibi)</span></p>
|
|
</div>
|
|
</div>
|
|
<div class="relative pl-6">
|
|
<div class="absolute -left-[7px] top-1 w-3 h-3 bg-red-500 rounded-full ring-2 ring-red-200 border-2 border-white"></div>
|
|
<div class="bg-red-50 p-2 rounded-lg border border-red-100">
|
|
<p class="font-semibold text-xs text-red-800">ca. 17:30 Uhr (TODESZEITPUNKT)</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Wireframe 8: Auflösung -->
|
|
<div class="bg-gray-50 p-4 rounded-lg border">
|
|
<h3 class="text-lg font-semibold mb-3 text-center">8. Auflösung</h3>
|
|
<div class="bg-white w-full max-w-sm mx-auto aspect-[9/19.5] rounded-2xl shadow-lg p-3 border flex flex-col">
|
|
<div class="text-center pt-4 pb-3 border-b bg-red-50">
|
|
<h4 class="font-bold text-lg text-red-700">Der Mörder war...</h4>
|
|
<p class="text-xl font-bold">Ivan Petrov!</p>
|
|
</div>
|
|
<div class="p-3 flex-grow overflow-y-auto text-sm text-gray-700 space-y-3">
|
|
<p class="text-xs">Sein Motiv war Rache, da das Opfer ihn erpresst hat. Die Mordwaffe war ein schwerer Schraubenschlüssel aus dem Werkzeugraum.</p>
|
|
<h5 class="font-semibold pt-2">Abstimmungsergebnis</h5>
|
|
<ul class="text-xs space-y-1">
|
|
<li>Du hast für <strong>Evelyn Reed</strong> gestimmt.</li>
|
|
<li>Maria hat für <strong>Ivan Petrov</strong> gestimmt. (Korrekt!)</li>
|
|
<li>Jonas hat für <strong>Sandra</strong> gestimmt.</li>
|
|
</ul>
|
|
</div>
|
|
<div class="p-3 border-t">
|
|
<button class="w-full bg-blue-600 text-white rounded-md py-2 font-semibold text-sm hover:bg-blue-700">Alle Geschichten lesen</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Wireframe 9: Host Dashboard -->
|
|
<div class="bg-gray-50 p-4 rounded-lg border">
|
|
<h3 class="text-lg font-semibold mb-3 text-center">9. Host Notfall-Dashboard</h3>
|
|
<div class="bg-white w-full max-w-sm mx-auto aspect-[9/19.5] rounded-2xl shadow-lg p-3 border flex flex-col">
|
|
<div class="text-center pt-4 pb-3 border-b">
|
|
<h4 class="font-bold text-lg text-red-600">Host Notfall-Dashboard</h4>
|
|
<p class="text-xs text-gray-500">Spoiler-freie Steuerung (im Spiel)</p>
|
|
</div>
|
|
<div class="px-3 py-4 flex-grow space-y-4">
|
|
<div>
|
|
<h5 class="font-semibold mb-2">Spiel-Steuerung</h5>
|
|
<div class="space-y-2">
|
|
<button class="w-full bg-yellow-500 text-white rounded-md py-2 text-sm font-semibold hover:bg-yellow-600">Spiel Pausieren</button>
|
|
<button class="w-full bg-orange-500 text-white rounded-md py-2 text-sm font-semibold hover:bg-orange-600">Nächste Runde erzwingen</button>
|
|
</div>
|
|
</div>
|
|
<div>
|
|
<h5 class="font-semibold mb-2">Experten-Optionen</h5>
|
|
<button class="w-full bg-purple-600 text-white rounded-md py-2 text-sm font-semibold hover:bg-purple-700">Hinweise neu generieren</button>
|
|
<p class="text-xs text-gray-500 mt-1">Achtung: Generiert nur die Hinweise für die AKTUELLE Runde neu. Nur nutzen, wenn Hinweise fehlerhaft wirken.</p>
|
|
</div>
|
|
<div class="pt-4">
|
|
<h5 class="font-semibold mb-2 text-red-700">Gefahrenzone</h5>
|
|
<button class="w-full bg-red-600 text-white rounded-md py-2 text-sm font-semibold hover:bg-red-700">Spiel komplett neu starten</button>
|
|
<p class="text-xs text-gray-500 mt-1">Beendet das Spiel für alle und startet die Lobby neu.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<section class="mb-10">
|
|
<h2 class="text-2xl font-semibold text-gray-800 border-b pb-2 mb-4">5. API-Endpunkte & Datenbank-Interaktion</h2>
|
|
<div class="space-y-6">
|
|
<div>
|
|
<h3 class="text-xl font-semibold mb-3">FastAPI-Backend (erweitert)</h3>
|
|
<p class="mb-3">Das Backend wird zur zentralen API für die gesamte Spiellogik. Alle Endpunkte erfordern ein gültiges Supabase JWT.</p>
|
|
<ul class="list-disc list-inside space-y-2 bg-gray-50 p-4 rounded-lg">
|
|
<li><code>POST /game/create</code>: Erstellt ein neues Spiel, ruft OpenAI auf, speichert in PG_DB.</li>
|
|
<li><code>POST /game/{game_code}/join</code>: Fügt einen Spieler zu einem Spiel hinzu.</li>
|
|
<li><code>GET /game/{game_code}/state</code>: Ruft den aktuellen Zustand eines Spiels ab.</li>
|
|
<li><code>POST /game/{game_code}/vote</code>: Gibt eine Stimme für einen Charakter ab.</li>
|
|
<li><code>GET /game/{game_code}/character</code>: Ruft die Charakterdetails für den authentifizierten Spieler ab.</li>
|
|
<li><code>/ws/{game_code}</code>: WebSocket-Endpunkt für Echtzeit-Updates.</li>
|
|
</ul>
|
|
</div>
|
|
<div>
|
|
<h3 class="text-xl font-semibold mb-3">Client-Interaktionen</h3>
|
|
<ul class="list-disc list-inside space-y-2">
|
|
<li><strong>Supabase Auth (`supabase-js`):</strong> Wird in der React Native App ausschließlich für Login, Registrierung und die Verwaltung des Auth-Zustands (JWT) verwendet.</li>
|
|
<li><strong>API-Client (z.B. Axios):</strong> Wird für alle HTTP-Anfragen an das FastAPI-Backend genutzt.</li>
|
|
<li><strong>WebSocket-Client:</strong> Wird verwendet, um die Echtzeit-Verbindung zum <code>/ws/...</code> Endpunkt des Backends herzustellen und auf Updates zu lauschen.</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<section class="mb-10">
|
|
<h2 class="text-2xl font-semibold text-gray-800 border-b pb-2 mb-4">6. Datenmodelle & `game_data` Detailbeschreibung</h2>
|
|
<p class="mb-4">Die dedizierte PostgreSQL-Datenbank enthält die gesamte Spiellogik, während Supabase ausschließlich für die Identitätsverwaltung zuständig ist.</p>
|
|
|
|
<h3 class="text-xl font-semibold mt-6 mb-3">Dedizierte PostgreSQL-Datenbank (Spieldaten)</h3>
|
|
<div class="space-y-8">
|
|
<div class="overflow-x-auto">
|
|
<h4 class="font-semibold mb-2 text-lg">Tabelle: `games`</h4>
|
|
<div class="rounded-lg border">
|
|
<table class="min-w-full divide-y divide-gray-200">
|
|
<thead class="bg-gray-50">
|
|
<tr>
|
|
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Spalte</th>
|
|
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Datentyp</th>
|
|
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Beschreibung</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody class="bg-white divide-y divide-gray-200">
|
|
<tr><td class="px-6 py-4">id</td><td class="px-6 py-4">uuid</td><td class="px-6 py-4">Eindeutige ID für ein Spiel.</td></tr>
|
|
<tr class="bg-gray-50"><td class="px-6 py-4">created_at</td><td class="px-6 py-4">timestamp</td><td class="px-6 py-4">Zeitstempel der Erstellung.</td></tr>
|
|
<tr><td class="px-6 py-4">host_id</td><td class="px-6 py-4">uuid</td><td class="px-6 py-4">Referenz auf die User-ID des Hosts aus Supabase.</td></tr>
|
|
<tr class="bg-gray-50"><td class="px-6 py-4">game_code</td><td class="px-6 py-4">varchar</td><td class="px-6 py-4">Kurzer Code zum Beitreten (z.B. "GHY-781"). <strong>Indiziert!</strong></td></tr>
|
|
<tr><td class="px-6 py-4">status</td><td class="px-6 py-4">varchar</td><td class="px-6 py-4">Aktueller Status (setup, lobby, active, finished).</td></tr>
|
|
<tr class="bg-gray-50"><td class="px-6 py-4">game_data</td><td class="px-6 py-4">jsonb</td><td class="px-6 py-4">Das komplette KI-generierte Szenario.</td></tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
<div class="overflow-x-auto">
|
|
<h4 class="font-semibold mb-2 text-lg mt-6">Tabelle: `players`</h4>
|
|
<div class="rounded-lg border">
|
|
<table class="min-w-full divide-y divide-gray-200">
|
|
<thead class="bg-gray-50">
|
|
<tr>
|
|
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Spalte</th>
|
|
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Datentyp</th>
|
|
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Beschreibung</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody class="bg-white divide-y divide-gray-200">
|
|
<tr><td class="px-6 py-4">id</td><td class="px-6 py-4">uuid</td><td class="px-6 py-4">Eindeutiger Eintrag für einen Spieler in einem Spiel.</td></tr>
|
|
<tr class="bg-gray-50"><td class="px-6 py-4">game_id</td><td class="px-6 py-4">uuid</td><td class="px-6 py-4">Verweist auf das zugehörige Spiel in `games`.</td></tr>
|
|
<tr><td class="px-6 py-4">player_id</td><td class="px-6 py-4">uuid</td><td class="px-6 py-4">Referenz auf die User-ID aus Supabase (kann `NULL` sein).</td></tr>
|
|
<tr class="bg-gray-50"><td class="px-6 py-4">player_name</td><td class="px-6 py-4">varchar</td><td class="px-6 py-4">Der im Spiel angezeigte Name des Spielers.</td></tr>
|
|
<tr><td class="px-6 py-4">character_id</td><td class="px-6 py-4">varchar</td><td class="px-6 py-4">Verknüpft den Spieler mit seiner Rolle im `game_data`-JSON.</td></tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="bg-blue-50 border-l-4 border-blue-500 text-blue-800 p-4 rounded-lg mt-6">
|
|
<h3 class="text-xl font-semibold mb-3">Die `game_data` (jsonb) Spalte: Der "digitale Spielkarton"</h3>
|
|
<p>Diese einzelne Spalte ist das narrative Herzstück jedes Spiels. Hier wird das gesamte, von der KI generierte und validierte JSON-Objekt gespeichert.</p>
|
|
</div>
|
|
</section>
|
|
|
|
<section class="mb-10">
|
|
<h2 class="text-2xl font-semibold text-gray-800 border-b pb-2 mb-4">7. Prompt-Engineering-Strategie</h2>
|
|
<div class="space-y-8 mt-6">
|
|
<div class="bg-gray-50 p-5 rounded-lg">
|
|
<h3 class="text-xl font-semibold mb-3">Prompt 1: Der kreative Autor</h3>
|
|
<h4 class="font-semibold text-gray-700">System-Prompt:</h4>
|
|
<p class="mb-3 p-3 bg-gray-200 rounded text-sm">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.</p>
|
|
<h4 class="font-semibold text-gray-700">User-Prompt (Beispiel):</h4>
|
|
<p class="p-3 bg-gray-200 rounded text-sm">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.</p>
|
|
</div>
|
|
<div class="bg-gray-50 p-5 rounded-lg">
|
|
<h3 class="text-xl font-semibold mb-3">Prompt 2: Der Logik-Lektor</h3>
|
|
<h4 class="font-semibold text-gray-700">System-Prompt:</h4>
|
|
<p class="mb-3 p-3 bg-gray-200 rounded text-sm">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.</p>
|
|
<h4 class="font-semibold text-gray-700">User-Prompt:</h4>
|
|
<p class="p-3 bg-gray-200 rounded text-sm">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.<br><br><em>[Hier wird das gesamte JSON aus Schritt 1 eingefügt]</em></p>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<section class="mb-10">
|
|
<h2 class="text-2xl font-semibold text-gray-800 border-b pb-2 mb-4">8. User Journey & Spielablauf</h2>
|
|
<p>Der Lebenszyklus eines Spiels ist in mehrere Phasen unterteilt, wobei jede Runde einem definierten Zeitfenster entspricht, um den Zeitstrahl zu strukturieren.</p>
|
|
<ol class="list-decimal list-inside space-y-4">
|
|
<li><strong>Phase 0: Generierung & Vorbereitung (<code>status: setup</code>)</strong>
|
|
<p class="text-sm text-gray-600 ml-6">Der Host kann ein Spiel generieren, lange bevor es stattfindet. In dieser Phase erhält er den Einladungscode und eine <strong>spoiler-freie Übersicht</strong> über Thema und Charakter-Namen zur Vorbereitung.</p>
|
|
</li>
|
|
<li><strong>Phase 1: Lobby (<code>status: lobby</code>)</strong>
|
|
<p class="text-sm text-gray-600 ml-6">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.</p>
|
|
</li>
|
|
<li><strong>Phase 2: Rollenverteilung</strong>
|
|
<p class="text-sm text-gray-600 ml-6">Nach dem Spielstart weist das Backend jedem Spieler eine Rolle zu und sendet die geheimen Informationen an das jeweilige Gerät.</p>
|
|
</li>
|
|
<li><strong>Phase 3: Spielrunden (<code>status: active</code>)</strong>
|
|
<p class="text-sm text-gray-600 ml-6">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.</p>
|
|
</li>
|
|
<li><strong>Phase 4: Abstimmung & Auflösung (<code>status: finished</code>)</strong>
|
|
<p class="text-sm text-gray-600 ml-6">Nach der letzten Runde wird die Abstimmung freigeschaltet. Danach folgt die Auflösung, bei der der Mörder und alle Geheimnisse enthüllt werden.</p>
|
|
</li>
|
|
</ol>
|
|
</section>
|
|
|
|
<section class="mb-10">
|
|
<h2 class="text-2xl font-semibold text-gray-800 border-b pb-2 mb-4">9. Geschäftsmodell & Monetarisierung</h2>
|
|
<p>Die App wird kein kostenloses Basis-Modell anbieten. Die Monetarisierung erfolgt direkt über die Nutzung der Spiunktion.</p>
|
|
<div class="grid md:grid-cols-2 gap-6 mt-6">
|
|
<div class="bg-gray-50 p-4 rounded-lg">
|
|
<h3 class="font-semibold text-lg mb-2">Abonnement-Modell</h3>
|
|
<p class="text-sm">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).</p>
|
|
</div>
|
|
<div class="bg-gray-50 p-4 rounded-lg">
|
|
<h3 class="font-semibold text-lg mb-2">Einmalkauf (Pay-per-Game)</h3>
|
|
<p class="text-sm">Alternativ zum Abo können Nutzer einzelne Spiele per Einmalkauf freischalten. Dies bietet maximale Flexibilität für Gelegenheitsspieler.</p>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<section class="mb-10">
|
|
<h2 class="text-2xl font-semibold text-gray-800 border-b pb-2 mb-4">10. Skalierbarkeit, Kosten & Fehlerbehandlung</h2>
|
|
<ul class="list-disc list-inside space-y-3 mt-6">
|
|
<li><strong>Kostenkontrolle (OpenAI):</strong> Ein <strong>Rate-Limiting</strong> auf dem <code>/game/create</code> Endpunkt verhindert Missbrauch (z.B. nur ein Spiel alle 5 Minuten pro Nutzer).</li>
|
|
<li><strong>Fehlerbehandlung bei Generierung:</strong> Schlägt der OpenAI-Call fehl, unternimmt das Backend automatisch 1-2 erneute Versuche, bevor es einen Fehler an den Host meldet.</li>
|
|
<li><strong>Nahtloses Wiederverbinden:</strong> Spieler können jederzeit wieder in ein laufendes Spiel einsteigen (z.B. nach Verbindungsabbruch) und erhalten den aktuellen Spielzustand.</li>
|
|
<li><strong>Notfall-Dashboard (Host):</strong> 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.</li>
|
|
</ul>
|
|
</section>
|
|
|
|
<section>
|
|
<h2 class="text-2xl font-semibold text-gray-800 border-b pb-2 mb-4">11. Rechtliches & Datenschutz</h2>
|
|
<p class="mt-6">Aufgrund der Verarbeitung von E-Mail-Adressen für die Authentifizierung sind folgende Punkte für den Launch zwingend erforderlich:</p>
|
|
<ul class="list-disc list-inside space-y-2">
|
|
<li><strong>DSGVO-konforme Datenschutzerklärung:</strong> Beschreibt, welche Daten zu welchem Zweck verarbeitet werden.</li>
|
|
<li><strong>Impressum:</strong> Gesetzlich vorgeschriebene Angabe des Betreibers.</li>
|
|
<li><strong>Löschung des Accounts:</strong> Eine einfache Möglichkeit für Nutzer, ihren Account und alle Daten zu löschen.</li>
|
|
</ul>
|
|
</section>
|
|
</div>
|
|
</div>
|
|
<script>
|
|
mermaid.initialize({ startOnLoad: true });
|
|
</script>
|
|
</body>
|
|
</html>
|