Frajosgro commited on
Commit
c73b91f
·
verified ·
1 Parent(s): 7b778b8

Upload CBotv1.html

Browse files
Files changed (1) hide show
  1. CBotv1.html +787 -0
CBotv1.html ADDED
@@ -0,0 +1,787 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="de">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Dr. Franz Schwanz - Psychoanalytischer Dialog</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
9
+ <style>
10
+ @import url('https://fonts.googleapis.com/css2?family=Playfair+Display:wght@400;500;600;700&family=Roboto:wght@300;400;500&display=swap');
11
+
12
+ :root {
13
+ --primary-color: #6366f1;
14
+ --primary-light: #a5b4fc;
15
+ --primary-dark: #4f46e5;
16
+ --secondary-color: #10b981;
17
+ --text-color: #334155;
18
+ --text-light: #64748b;
19
+ --bg-color: #f8fafc;
20
+ --card-color: #ffffff;
21
+ }
22
+
23
+ body {
24
+ font-family: 'Roboto', sans-serif;
25
+ background-color: var(--bg-color);
26
+ color: var(--text-color);
27
+ line-height: 1.6;
28
+ }
29
+
30
+ .title-font {
31
+ font-family: 'Playfair Display', serif;
32
+ }
33
+
34
+ .chat-container {
35
+ height: calc(100vh - 180px);
36
+ scrollbar-width: thin;
37
+ scrollbar-color: var(--primary-color) #e5e7eb;
38
+ }
39
+
40
+ .chat-container::-webkit-scrollbar {
41
+ width: 6px;
42
+ }
43
+
44
+ .chat-container::-webkit-scrollbar-track {
45
+ background: #e5e7eb;
46
+ }
47
+
48
+ .chat-container::-webkit-scrollbar-thumb {
49
+ background-color: var(--primary-color);
50
+ border-radius: 20px;
51
+ }
52
+
53
+ .psycho-bubble {
54
+ background-color: var(--card-color);
55
+ border-left: 4px solid var(--primary-color);
56
+ box-shadow: 0 2px 4px rgba(0,0,0,0.05);
57
+ }
58
+
59
+ .user-bubble {
60
+ background-color: var(--primary-color);
61
+ color: white;
62
+ box-shadow: 0 2px 4px rgba(0,0,0,0.1);
63
+ }
64
+
65
+ .typing-indicator span {
66
+ display: inline-block;
67
+ width: 8px;
68
+ height: 8px;
69
+ border-radius: 50%;
70
+ background-color: #9ca3af;
71
+ margin-right: 4px;
72
+ }
73
+
74
+ .typing-indicator span:nth-child(1) {
75
+ animation: bounce 1s infinite;
76
+ }
77
+
78
+ .typing-indicator span:nth-child(2) {
79
+ animation: bounce 1s infinite 0.2s;
80
+ }
81
+
82
+ .typing-indicator span:nth-child(3) {
83
+ animation: bounce 1s infinite 0.4s;
84
+ }
85
+
86
+ @keyframes bounce {
87
+ 0%, 100% { transform: translateY(0); }
88
+ 50% { transform: translateY(-5px); }
89
+ }
90
+
91
+ .highlight {
92
+ background-color: #fef08a;
93
+ padding: 0 2px;
94
+ }
95
+
96
+ .fade-in {
97
+ animation: fadeIn 0.5s ease-in;
98
+ }
99
+
100
+ @keyframes fadeIn {
101
+ from { opacity: 0; transform: translateY(10px); }
102
+ to { opacity: 1; transform: translateY(0); }
103
+ }
104
+
105
+ .personalized-question {
106
+ border-left: 3px solid var(--secondary-color);
107
+ padding-left: 12px;
108
+ margin: 12px 0;
109
+ background-color: rgba(16, 185, 129, 0.05);
110
+ }
111
+
112
+ .memory-badge {
113
+ display: inline-block;
114
+ background-color: #e0e7ff;
115
+ color: #4338ca;
116
+ padding: 2px 8px;
117
+ border-radius: 12px;
118
+ font-size: 0.75rem;
119
+ margin-left: 8px;
120
+ vertical-align: middle;
121
+ }
122
+
123
+ .bias-analysis {
124
+ background-color: #f8fafc;
125
+ border: 1px solid #e2e8f0;
126
+ border-radius: 8px;
127
+ padding: 12px;
128
+ margin-top: 16px;
129
+ font-size: 0.85rem;
130
+ color: var(--text-light);
131
+ }
132
+
133
+ .bias-meter {
134
+ height: 6px;
135
+ background-color: #e2e8f0;
136
+ border-radius: 3px;
137
+ margin-top: 4px;
138
+ overflow: hidden;
139
+ }
140
+
141
+ .bias-meter-fill {
142
+ height: 100%;
143
+ background-color: var(--primary-color);
144
+ transition: width 0.5s ease;
145
+ }
146
+
147
+ .insight-tag {
148
+ display: inline-block;
149
+ background-color: #e0f2fe;
150
+ color: #0369a1;
151
+ padding: 2px 8px;
152
+ border-radius: 4px;
153
+ font-size: 0.75rem;
154
+ margin-right: 6px;
155
+ margin-bottom: 6px;
156
+ }
157
+
158
+ @media (max-width: 640px) {
159
+ .chat-container {
160
+ height: calc(100vh - 160px);
161
+ }
162
+
163
+ .psycho-bubble, .user-bubble {
164
+ max-width: 90% !important;
165
+ }
166
+ }
167
+ </style>
168
+ </head>
169
+ <body class="bg-gray-50">
170
+ <div class="container mx-auto max-w-4xl px-4 py-6 md:py-8">
171
+ <!-- Header -->
172
+ <header class="mb-6 md:mb-8 text-center">
173
+ <div class="flex items-center justify-center mb-3 md:mb-4">
174
+ <div class="bg-indigo-100 p-3 rounded-full mr-3 md:mr-4">
175
+ <i class="fas fa-brain text-indigo-600 text-xl md:text-2xl"></i>
176
+ </div>
177
+ <h1 class="title-font text-2xl md:text-3xl font-bold text-gray-800">Dr. Franz Schwanz</h1>
178
+ </div>
179
+ <p class="text-gray-600 max-w-2xl mx-auto text-sm md:text-base">
180
+ Ihr persönlicher psychoanalytischer Gesprächspartner für tiefere Selbsterkenntnis
181
+ </p>
182
+ </header>
183
+
184
+ <!-- Chat Container -->
185
+ <div class="bg-white rounded-xl shadow-lg overflow-hidden">
186
+ <!-- Chat Header -->
187
+ <div class="bg-indigo-600 text-white p-3 md:p-4 flex items-center">
188
+ <div class="w-8 h-8 md:w-10 md:h-10 rounded-full bg-indigo-500 flex items-center justify-center mr-2 md:mr-3">
189
+ <i class="fas fa-user-tie text-sm md:text-base"></i>
190
+ </div>
191
+ <div>
192
+ <h2 class="font-semibold text-sm md:text-base">Dr. Franz Schwanz</h2>
193
+ <p class="text-xs text-indigo-200">Psychoanalytischer Gesprächspartner</p>
194
+ </div>
195
+ </div>
196
+
197
+ <!-- Chat Messages -->
198
+ <div class="chat-container overflow-y-auto p-3 md:p-4 space-y-3 md:space-y-4" id="chat-messages">
199
+ <!-- Initial greeting -->
200
+ <div class="flex fade-in">
201
+ <div class="flex-shrink-0 mr-2 md:mr-3">
202
+ <div class="w-7 h-7 md:w-8 md:h-8 rounded-full bg-indigo-100 flex items-center justify-center">
203
+ <i class="fas fa-brain text-indigo-600 text-xs md:text-sm"></i>
204
+ </div>
205
+ </div>
206
+ <div class="psycho-bubble rounded-lg p-3 md:p-4 max-w-[85%]">
207
+ <p class="text-xs md:text-sm text-gray-500 mb-1" id="greeting-time"></p>
208
+ <p class="font-medium text-indigo-800 mb-1 md:mb-2">Willkommen zu unserem persönlichen Dialog.</p>
209
+ <p class="text-gray-700 mb-2 md:mb-3">Ich bin Dr. Franz Schwanz und begleite Sie in einem reflektierenden Gespräch. Bevor wir beginnen: </p>
210
+
211
+ <div class="personalized-question">
212
+ <p class="text-gray-700 font-medium">Wie darf ich Sie nennen? Und was hat Sie heute zu mir geführt?</p>
213
+ </div>
214
+
215
+ <div class="mt-2 md:mt-3 text-xs md:text-sm text-gray-500">
216
+ <p>Sie können mir einfach natürlich schreiben, wie Sie es einem vertrauten Gesprächspartner tun würden.</p>
217
+ </div>
218
+ </div>
219
+ </div>
220
+ </div>
221
+
222
+ <!-- Input Area -->
223
+ <div class="border-t border-gray-200 p-3 md:p-4 bg-gray-50">
224
+ <div class="flex items-center">
225
+ <div class="flex-grow relative">
226
+ <textarea id="message-input" rows="1" class="w-full border border-gray-300 rounded-full py-2 md:py-3 px-3 md:px-4 pr-10 md:pr-12 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500 resize-none text-sm md:text-base" placeholder="Ihre Antwort..."></textarea>
227
+ <button id="send-button" class="absolute right-2 md:right-3 top-1/2 transform -translate-y-1/2 w-7 h-7 md:w-8 md:h-8 rounded-full bg-indigo-600 hover:bg-indigo-700 flex items-center justify-center transition-colors">
228
+ <i class="fas fa-paper-plane text-white text-xs md:text-sm"></i>
229
+ </button>
230
+ </div>
231
+ </div>
232
+ </div>
233
+ </div>
234
+
235
+ <!-- Info Footer -->
236
+ <footer class="mt-6 md:mt-8 text-center text-xs md:text-sm text-gray-500">
237
+ <p>Dies ist ein psychoanalytisches Dialogexperiment und ersetzt keine Therapie.</p>
238
+ </footer>
239
+ </div>
240
+
241
+ <script>
242
+ // Enhanced Conversation Manager
243
+ class ConversationManager {
244
+ constructor() {
245
+ this.userProfile = this.initializeUserProfile();
246
+ this.conversationHistory = [];
247
+ this.conversationThreads = {};
248
+ this.currentThread = null;
249
+ this.emotionalToneHistory = [];
250
+ this.lastUserMessage = '';
251
+ }
252
+
253
+ initializeUserProfile() {
254
+ return {
255
+ name: null,
256
+ preferredName: null,
257
+ age: null,
258
+ gender: null,
259
+ knownIssues: [],
260
+ emotionalState: null,
261
+ emotionalIntensity: 0,
262
+ personalityTraits: [],
263
+ conversationStage: 'initial',
264
+ lastTopics: [],
265
+ keyMemories: [],
266
+ conversationDepth: 0,
267
+ resistanceLevel: 0,
268
+ biasScores: {
269
+ projection: 0,
270
+ pathologization: 0,
271
+ solution: 0,
272
+ feasibility: 0
273
+ },
274
+ linguisticPatterns: {
275
+ sentenceLength: 0,
276
+ questionRatio: 0,
277
+ emotionalWords: 0
278
+ }
279
+ };
280
+ }
281
+
282
+ updateProfileFromMessage(message) {
283
+ this.lastUserMessage = message;
284
+ const lowerMessage = message.toLowerCase();
285
+
286
+ // Extract basic information if not set
287
+ this.extractBasicInfo(message);
288
+
289
+ // Analyze emotional state
290
+ this.analyzeEmotionalState(message);
291
+
292
+ // Detect resistance
293
+ this.detectResistance(message);
294
+
295
+ // Track topics and memories
296
+ this.trackTopicsAndMemories(message);
297
+
298
+ // Analyze linguistic patterns
299
+ this.analyzeLinguisticPatterns(message);
300
+
301
+ // Update conversation stage if needed
302
+ this.updateConversationStage();
303
+ }
304
+
305
+ extractBasicInfo(message) {
306
+ if (!this.userProfile.name && this.userProfile.conversationStage === 'initial') {
307
+ const namePatterns = [
308
+ /(?:ich bin|mein name ist|ich heiße|nennen sie mich)\s+([A-ZÄÖÜ][a-zäöüß]+(?:\s+[A-ZÄÖÜ][a-zäöüß]+)*)/i,
309
+ /(?:name)\s+(?:ist\s+)?([A-ZÄÖÜ][a-zäöüß]+)/i,
310
+ /^([A-ZÄÖÜ][a-zäöüß]+)(?:\s|$)/,
311
+ /(?:heiße)\s+([A-ZÄÖÜ][a-zäöüß]+)/i
312
+ ];
313
+
314
+ for (const pattern of namePatterns) {
315
+ const nameMatch = message.match(pattern);
316
+ if (nameMatch && nameMatch[1]) {
317
+ this.userProfile.name = nameMatch[1].trim();
318
+ this.userProfile.preferredName = nameMatch[1].trim();
319
+ break;
320
+ }
321
+ }
322
+
323
+ if (!this.userProfile.name) {
324
+ const words = message.split(' ');
325
+ if (words.length > 0 && words[0].length > 2 && /^[A-ZÄÖÜ]/.test(words[0])) {
326
+ this.userProfile.name = words[0];
327
+ this.userProfile.preferredName = words[0];
328
+ }
329
+ }
330
+
331
+ if (this.userProfile.name) return;
332
+ }
333
+
334
+ if (!this.userProfile.age) {
335
+ const ageMatch = message.match(/(?:ich bin|alter|ich\s+habe)\s+(\d+)\s+(?:jahre|jahren)?/i);
336
+ if (ageMatch && ageMatch[1]) {
337
+ this.userProfile.age = parseInt(ageMatch[1]);
338
+ }
339
+ }
340
+
341
+ if (!this.userProfile.gender) {
342
+ if (lowerMessage.match(/\b(frau|weiblich|sie\s+ist)\b/i)) {
343
+ this.userProfile.gender = 'weiblich';
344
+ } else if (lowerMessage.match(/\b(mann|männlich|er\s+ist)\b/i)) {
345
+ this.userProfile.gender = 'männlich';
346
+ } else if (lowerMessage.match(/\b(nicht-binär|divers|non-binary)\b/i)) {
347
+ this.userProfile.gender = 'divers';
348
+ }
349
+ }
350
+ }
351
+
352
+ analyzeEmotionalState(message) {
353
+ const lowerMessage = message.toLowerCase();
354
+ const emotionalWords = {
355
+ distressed: ['verzweifelt', 'hoffnungslos', 'ängstlich', 'unsicher', 'traurig', 'deprimiert', 'überfordert', 'hilflos'],
356
+ angry: ['wütend', 'ärgerlich', 'frustriert', 'genervt', 'aggressiv', 'sauer', 'verärgert'],
357
+ confused: ['verwirrt', 'unsicher', 'fragend', 'unschlüssig', 'orientierungslos', 'ratlos'],
358
+ positive: ['froh', 'glücklich', 'zufrieden', 'gut', 'freue', 'erfreut', 'begeistert'],
359
+ anxious: ['besorgt', 'nervös', 'angespannt', 'unruhig', 'panik', 'sorge']
360
+ };
361
+
362
+ let detectedState = null;
363
+ let intensity = 0;
364
+
365
+ for (const [state, words] of Object.entries(emotionalWords)) {
366
+ const matches = words.filter(word => lowerMessage.includes(word));
367
+ if (matches.length > 0) {
368
+ detectedState = state;
369
+ intensity = matches.length;
370
+ break;
371
+ }
372
+ }
373
+
374
+ // Detect intensity modifiers
375
+ const intensityModifiers = lowerMessage.match(/\b(sehr|extrem|wirklich|total|vollkommen|absolut|etwas|leicht|ein wenig)\b/g);
376
+ if (intensityModifiers) {
377
+ intensity += intensityModifiers.filter(m => ['sehr', 'extrem', 'wirklich', 'total', 'vollkommen', 'absolut'].includes(m)).length;
378
+ intensity -= intensityModifiers.filter(m => ['etwas', 'leicht', 'ein wenig'].includes(m)).length;
379
+ }
380
+
381
+ // Detect punctuation intensity
382
+ const exclamationCount = (message.match(/!/g) || []).length;
383
+ const questionCount = (message.match(/\?/g) || []).length;
384
+ intensity += exclamationCount * 0.5;
385
+
386
+ if (detectedState) {
387
+ this.userProfile.emotionalState = detectedState;
388
+ this.userProfile.emotionalIntensity = Math.min(Math.max(intensity, 1), 5);
389
+ this.emotionalToneHistory.push({
390
+ state: detectedState,
391
+ intensity: this.userProfile.emotionalIntensity,
392
+ timestamp: new Date()
393
+ });
394
+ }
395
+ }
396
+
397
+ detectResistance(message) {
398
+ const lowerMessage = message.toLowerCase();
399
+ const resistancePatterns = [
400
+ /\b(weiß nicht|keine ahnung|unangenehm|schwierig)\b/i,
401
+ /\b(darüber möchte ich nicht sprechen|lieber nicht|mag ich nicht)\b/i,
402
+ /\b(warum fragen sie|weshalb wollen sie das wissen)\b/i,
403
+ /\b(das ist privat|geht sie nichts an)\b/i
404
+ ];
405
+
406
+ let resistanceScore = 0;
407
+ resistancePatterns.forEach(pattern => {
408
+ if (lowerMessage.match(pattern)) {
409
+ resistanceScore += 1;
410
+ }
411
+ });
412
+
413
+ // Short responses indicate resistance
414
+ if (message.split(' ').length < 5 && message.length < 20 && !message.endsWith('?')) {
415
+ resistanceScore += 1;
416
+ }
417
+
418
+ if (resistanceScore > 0) {
419
+ this.userProfile.resistanceLevel = Math.min(this.userProfile.resistanceLevel + resistanceScore, 5);
420
+ } else if (this.userProfile.resistanceLevel > 0) {
421
+ this.userProfile.resistanceLevel = Math.max(this.userProfile.resistanceLevel - 0.5, 0);
422
+ }
423
+ }
424
+
425
+ trackTopicsAndMemories(message) {
426
+ const lowerMessage = message.toLowerCase();
427
+
428
+ const memoryTriggers = [
429
+ { pattern: /\b(kindheit|jugend|als kind|früher)\b/i, topic: 'Kindheit' },
430
+ { pattern: /\b(eltern|mutter|vater|familie)\b/i, topic: 'Familie' },
431
+ { pattern: /\b(schule|ausbildung|studium|lehre|universität)\b/i, topic: 'Bildung' },
432
+ { pattern: /\b(arbeit|job|beruf|karriere|kollegen)\b/i, topic: 'Arbeit' },
433
+ { pattern: /\b(partner|beziehung|ehe|freund|freundin|liebe)\b/i, topic: 'Beziehungen' },
434
+ { pattern: /\b(freund|freundin|freundschaft|kamerad)\b/i, topic: 'Freundschaften' },
435
+ { pattern: /\b(angst|sorge|befürchtung|panik|phobie)\b/i, topic: 'Ängste' },
436
+ { pattern: /\b(traum|ziel|wunsch|wünsche|hoffnung)\b/i, topic: 'Träume' },
437
+ { pattern: /\b(krise|verlust|tod|trauer|trennung)\b/i, topic: 'Verluste' },
438
+ { pattern: /\b(erfolg|leistung|anerkennung|beförderung)\b/i, topic: 'Erfolge' },
439
+ { pattern: /\b(gesundheit|krankheit|schmerzen|arzt)\b/i, topic: 'Gesundheit' },
440
+ { pattern: /\b(hobby|interesse|leidenschaft|musik|sport)\b/i, topic: 'Interessen' }
441
+ ];
442
+
443
+ // Track topics
444
+ const topics = [];
445
+ memoryTriggers.forEach(trigger => {
446
+ if (lowerMessage.match(trigger.pattern)) {
447
+ topics.push(trigger.topic);
448
+
449
+ if (!this.userProfile.keyMemories.includes(trigger.topic)) {
450
+ this.userProfile.keyMemories.push(trigger.topic);
451
+ }
452
+ }
453
+ });
454
+
455
+ if (topics.length > 0) {
456
+ this.userProfile.lastTopics = [...new Set([...this.userProfile.lastTopics, ...topics])].slice(-5);
457
+ }
458
+
459
+ // Track personality traits based on language use
460
+ this.detectPersonalityTraits(message);
461
+ }
462
+
463
+ detectPersonalityTraits(message) {
464
+ const traits = {
465
+ analytical: ['weil', 'daher', 'deshalb', 'folglich', 'sodass', 'da', 'denn'],
466
+ intuitive: ['ich fühle', 'mein bauchgefühl', 'instinktiv', 'intuitiv', 'ich spüre'],
467
+ detailOriented: ['genau', 'konkret', 'speziell', 'detailliert', 'im einzelnen'],
468
+ bigPicture: ['insgesamt', 'grundsätzlich', 'im großen und ganzen', 'allgemein', 'übergeordnet'],
469
+ optimistic: ['hoffentlich', 'positiv', 'gut', 'schön', 'freue', 'erfreulich'],
470
+ pessimistic: ['leider', 'negativ', 'schlecht', 'problematisch', 'sorgen', 'befürchte']
471
+ };
472
+
473
+ const lowerMessage = message.toLowerCase();
474
+ const detectedTraits = [];
475
+
476
+ for (const [trait, markers] of Object.entries(traits)) {
477
+ if (markers.some(marker => lowerMessage.includes(marker))) {
478
+ detectedTraits.push(trait);
479
+ }
480
+ }
481
+
482
+ // Update traits, keeping unique
483
+ this.userProfile.personalityTraits = [...new Set([...this.userProfile.personalityTraits, ...detectedTraits])];
484
+ }
485
+
486
+ analyzeLinguisticPatterns(message) {
487
+ const sentences = message.split(/[.!?]+/).filter(s => s.trim().length > 0);
488
+ const words = message.split(/\s+/);
489
+ const questions = message.split('?').length - 1;
490
+
491
+ this.userProfile.linguisticPatterns = {
492
+ sentenceLength: sentences.length > 0 ? words.length / sentences.length : 0,
493
+ questionRatio: sentences.length > 0 ? questions / sentences.length : 0,
494
+ emotionalWords: words.filter(word =>
495
+ word.match(/\b(glücklich|traurig|wütend|ängstlich|freude|leid|schmerz|liebe|hass)\b/i)
496
+ ).length / words.length || 0
497
+ };
498
+ }
499
+
500
+ updateConversationStage() {
501
+ if (!this.userProfile.name && this.userProfile.conversationStage === 'initial') {
502
+ return;
503
+ }
504
+
505
+ if (this.userProfile.name && this.userProfile.conversationStage === 'initial') {
506
+ this.userProfile.conversationStage = 'name_established';
507
+ return;
508
+ }
509
+
510
+ if (this.userProfile.conversationStage === 'name_established' && this.lastUserMessage.length > 10) {
511
+ this.userProfile.conversationStage = 'issue_shared';
512
+ return;
513
+ }
514
+
515
+ if (this.userProfile.conversationStage === 'issue_shared' && this.userProfile.conversationDepth > 2) {
516
+ this.userProfile.conversationStage = 'deep_dive';
517
+ return;
518
+ }
519
+ }
520
+
521
+ analyzeBias(responseText, responseMeta) {
522
+ // Initialize scores
523
+ const scores = {
524
+ projection: 0,
525
+ pathologization: 0,
526
+ solution: 0,
527
+ feasibility: 0
528
+ };
529
+
530
+ let primaryBias = 'Keine signifikante Verzerrung';
531
+ let correction = 'Keine spezifische Korrektur erforderlich';
532
+
533
+ // Enhanced bias detection with weighted scoring
534
+ const biasPatterns = {
535
+ projection: [
536
+ { pattern: /\b(Über-Ich|Es|Ich|Abwehrmechanismus|Übertragung|Projektion|Verdrängung)\b/gi, weight: 15 },
537
+ { pattern: /\b(Sublimierung|Regression|Widerstand|Trieb|Objektbeziehung)\b/gi, weight: 10 },
538
+ { pattern: /\b(nach Freud|psychoanalytisch betrachtet|unbewusste Prozesse)\b/gi, weight: 20 }
539
+ ],
540
+ pathologization: [
541
+ { pattern: /\b(Störung|Pathologie|krankhaft|abnorm|dysfunktional)\b/gi, weight: 20 },
542
+ { pattern: /\b(neurotisch|psychotisch|Defekt|Kompensation|pathologisch)\b/gi, weight: 15 },
543
+ { pattern: /\b(krank|gestört|unangepasst|maladaptiv)\b/gi, weight: 10 }
544
+ ],
545
+ solution: [
546
+ { pattern: /\b(Sie sollten|Sie müssen|versuchen Sie|empfehle ich)\b/gi, weight: 25 },
547
+ { pattern: /\b(mein Rat wäre|Lösung wäre|besser wäre es|ich rate Ihnen)\b/gi, weight: 20 },
548
+ { pattern: /\b(sollten Sie|würde ich|am besten|ideal wäre)\b/gi, weight: 15 }
549
+ ],
550
+ feasibility: [
551
+ { pattern: /\b(einfach|schnell|leicht|problemlos)\b/gi, weight: 20 },
552
+ { pattern: /\b(garantiert|sicherlich|zweifellos|unbedingt)\b/gi, weight: 15 },
553
+ { pattern: /\b(sofort|direkt|ohne Probleme|mühelos)\b/gi, weight: 10 }
554
+ ]
555
+ };
556
+
557
+ // Calculate bias scores
558
+ for (const [biasType, patterns] of Object.entries(biasPatterns)) {
559
+ let biasScore = 0;
560
+
561
+ patterns.forEach(({pattern, weight}) => {
562
+ const matches = responseText.match(pattern) || [];
563
+ biasScore += matches.length * weight;
564
+ });
565
+
566
+ // Normalize score to 0-100 range
567
+ scores[biasType] = Math.min(Math.max(biasScore, 0), 100);
568
+
569
+ // Contextual adjustment
570
+ if (biasType === 'solution' && this.userProfile.conversationStage === 'initial') {
571
+ scores[biasType] = Math.max(scores[biasType] - 30, 0);
572
+ }
573
+
574
+ if (biasType === 'projection' && this.userProfile.conversationStage === 'deep_dive') {
575
+ scores[biasType] = Math.min(scores[biasType] + 15, 100);
576
+ }
577
+ }
578
+
579
+ // Determine primary bias (only if significant)
580
+ const maxScore = Math.max(...Object.values(scores));
581
+ if (maxScore > 40) {
582
+ if (scores.projection === maxScore) {
583
+ primaryBias = 'Theoretischer Projektions-Bias';
584
+ correction = 'Mehr Fokus auf die subjektive Erfahrung des Patienten';
585
+ } else if (scores.pathologization === maxScore) {
586
+ primaryBias = 'Pathologisierungs-Bias';
587
+ correction = 'Ausgewogenere Betrachtung normaler menschlicher Erfahrungen';
588
+ } else if (scores.solution === maxScore) {
589
+ primaryBias = 'Lösungsorientierungs-Bias';
590
+ correction = 'Mehr Exploration vor Lösungsvorschlägen';
591
+ } else {
592
+ primaryBias = 'Machbarkeits-Bias';
593
+ correction = 'Realistischere Einschätzung der Veränderungsmöglichkeiten';
594
+ }
595
+ }
596
+
597
+ // Additional contextual factors
598
+ if (this.userProfile.resistanceLevel > 3 && maxScore < 40) {
599
+ primaryBias = 'Widerstands-Bias';
600
+ correction = 'Mehr Anpassung an die Widerstandsebene des Patienten';
601
+ scores.projection = Math.min(scores.projection + 20, 100);
602
+ }
603
+
604
+ return {
605
+ scores,
606
+ primaryBias,
607
+ correction,
608
+ analysis: this.generateBiasAnalysisText(scores, primaryBias)
609
+ };
610
+ }
611
+
612
+ generateBiasAnalysisText(scores, primaryBias) {
613
+ const analysisParts = [];
614
+
615
+ if (scores.projection > 50) {
616
+ analysisParts.push(`Die Antwort zeigt eine starke Tendenz zur psychoanalytischen Theorieanwendung (${scores.projection}%), was die subjektive Erfahrung des Patienten möglicherweise überlagert.`);
617
+ }
618
+
619
+ if (scores.pathologization > 50) {
620
+ analysisParts.push(`Es besteht eine Neigung zur Pathologisierung normaler Erfahrungen (${scores.pathologization}%), die die diagnostische Neutralität beeinträchtigen könnte.`);
621
+ }
622
+
623
+ if (scores.solution > 50) {
624
+ analysisParts.push(`Die Antwort ist stark lösungsorientiert (${scores.solution}%), was in frühen Gesprächsphasen die Exploration einschränken kann.`);
625
+ }
626
+
627
+ if (scores.feasibility > 50) {
628
+ analysisParts.push(`Die vorgeschlagenen Veränderungen werden möglicherweise zu optimistisch dargestellt (${scores.feasibility}%), was unrealistische Erwartungen wecken könnte.`);
629
+ }
630
+
631
+ if (analysisParts.length === 0) {
632
+ return 'Die Antwort zeigt ein ausgewogenes Verhältnis zwischen Exploration, Theorieanwendung und Neutralität.';
633
+ }
634
+
635
+ return analysisParts.join(' ');
636
+ }
637
+
638
+ generatePersonalizedResponse(message) {
639
+ const responseGenerator = new ResponseGenerator(this);
640
+ return responseGenerator.generateResponse(message);
641
+ }
642
+
643
+ addToHistory(message, sender, meta = {}) {
644
+ this.conversationHistory.push({
645
+ sender,
646
+ text: message,
647
+ meta,
648
+ timestamp: new Date()
649
+ });
650
+
651
+ if (meta.threadId) {
652
+ this.currentThread = meta.threadId;
653
+
654
+ if (!this.conversationThreads[meta.threadId]) {
655
+ this.conversationThreads[meta.threadId] = {
656
+ topic: meta.threadTopic || 'Allgemein',
657
+ depth: 1,
658
+ lastActive: new Date(),
659
+ messages: []
660
+ };
661
+ } else {
662
+ this.conversationThreads[meta.threadId].depth += 1;
663
+ this.conversationThreads[meta.threadId].lastActive = new Date();
664
+ }
665
+
666
+ this.conversationThreads[meta.threadId].messages.push({
667
+ text: message,
668
+ meta,
669
+ timestamp: new Date()
670
+ });
671
+ }
672
+ }
673
+ }
674
+
675
+ // Enhanced Response Generator
676
+ class ResponseGenerator {
677
+ constructor(conversationManager) {
678
+ this.cm = conversationManager;
679
+ this.userProfile = conversationManager.userProfile;
680
+ }
681
+
682
+ generateResponse(message) {
683
+ const lowerMessage = message.toLowerCase();
684
+
685
+ // Stage 1: Name establishment
686
+ if (!this.userProfile.name && this.userProfile.conversationStage === 'initial') {
687
+ return this.generateNameEstablishmentResponse(message);
688
+ }
689
+
690
+ // Just got the name - acknowledge and ask about issue
691
+ if (this.userProfile.name && this.userProfile.conversationStage === 'initial') {
692
+ this.userProfile.conversationStage = 'name_established';
693
+ return {
694
+ text: `
695
+ <p>Vielen Dank, ${this.userProfile.name}. Schön, Sie kennenzulernen.</p>
696
+ <p class="mt-2">Was führt Sie heute zu mir? Was beschäftigt Sie im Moment am meisten?</p>
697
+ `,
698
+ meta: {
699
+ personalizedGreeting: `Hallo ${this.userProfile.name},`,
700
+ followUpQuestion: "Würden Sie mir etwas mehr darüber erzählen, was Sie bewegt?",
701
+ updateStage: 'name_established'
702
+ }
703
+ };
704
+ }
705
+
706
+ // Stage 2: Issue sharing
707
+ if (this.userProfile.conversationStage === 'name_established') {
708
+ this.userProfile.conversationStage = 'issue_shared';
709
+
710
+ // Check for greetings
711
+ if (lowerMessage.match(/^(hi|hallo|guten (tag|morgen|abend)|moin|servus|hey|grü(ß|ss)e?)/i)) {
712
+ return {
713
+ text: `
714
+ <p>${this.userProfile.name}, ich freue mich, unser Gespräch fortzusetzen.</p>
715
+ ${this.userProfile.lastTopics.length > 0 ?
716
+ `<p class="mt-2">Bei unserem letzten Austausch haben wir über ${this.formatTopics(this.userProfile.lastTopics)} gesprochen.</p>` :
717
+ ''}
718
+ <p class="mt-2">Wie geht es Ihnen damit heute?</p>
719
+ `,
720
+ meta: {
721
+ personalizedGreeting: `Willkommen zurück, ${this.userProfile.name}`,
722
+ followUpQuestion: "Möchten Sie an unser letztes Gespräch anknüpfen oder etwas Neues besprechen?",
723
+ isFollowUp: true,
724
+ threadId: 'greeting_' + Date.now(),
725
+ threadTopic: 'Begrüßung'
726
+ }
727
+ };
728
+ }
729
+
730
+ // Generate personalized issue response
731
+ return this.generateIssueResponse(message);
732
+ }
733
+
734
+ // Stage 3: Deep dive into issue
735
+ if (this.userProfile.conversationStage === 'issue_shared') {
736
+ return this.generateDeepDiveResponse(message);
737
+ }
738
+
739
+ // Stage 4: Ongoing conversation - more sophisticated handling
740
+ return this.generateOngoingResponse(message);
741
+ }
742
+
743
+ generateNameEstablishmentResponse(message) {
744
+ // Enhanced name extraction with fallback
745
+ const namePatterns = [
746
+ /(?:ich bin|mein name ist|ich heiße|nennen sie mich)\s+([A-ZÄÖÜ][a-zäöüß]+(?:\s+[A-ZÄÖÜ][a-zäöüß]+)*)/i,
747
+ /(?:name)\s+(?:ist\s+)?([A-ZÄÖÜ][a-zäöüß]+)/i,
748
+ /^([A-ZÄÖÜ][a-zäöüß]+)(?:\s|$)/,
749
+ /(?:heiße)\s+([A-ZÄÖÜ][a-zäöüß]+)/i
750
+ ];
751
+
752
+ let extractedName = null;
753
+ for (const pattern of namePatterns) {
754
+ const nameMatch = message.match(pattern);
755
+ if (nameMatch && nameMatch[1]) {
756
+ extractedName = nameMatch[1].trim();
757
+ break;
758
+ }
759
+ }
760
+
761
+ if (extractedName) {
762
+ this.userProfile.name = extractedName;
763
+ this.userProfile.preferredName = extractedName;
764
+ this.userProfile.conversationStage = 'name_established';
765
+
766
+ return {
767
+ text: `
768
+ <p>Vielen Dank, ${this.userProfile.name}. Schön, Sie kennenzulernen.</p>
769
+ <p class="mt-2">Was führt Sie heute zu mir? Was beschäftigt Sie im Moment am meisten?</p>
770
+ `,
771
+ meta: {
772
+ personalizedGreeting: `Hallo ${this.userProfile.name},`,
773
+ followUpQuestion: "Würden Sie mir etwas mehr darüber erzählen, was Sie bewegt?",
774
+ updateStage: 'name_established'
775
+ }
776
+ };
777
+ } else {
778
+ // If no name found, ask again with more guidance
779
+ return {
780
+ text: `
781
+ <p>Vielen Dank für Ihre Nachricht.</p>
782
+ <p class="mt-2">Um unser Gespräch persönlicher zu gestalten, könnten Sie mir bitte mitteilen, wie ich Sie ansprechen soll?</p>
783
+ <p class="mt-2">Zum Beispiel: "Ich bin Anna" oder "Nennen Sie mich Max".</p>
784
+ `,
785
+ meta: {
786
+ followUpQuestion: "Wie soll ich Sie nennen?",
787
+