/** * Advice Chat Module - Enhanced chat with personality inversion * Tests hypothesis: "Can a chatbot give better advice if it's rude?" */ class AdviceChat extends SarcasticChat { constructor() { super(); this.adviceCount = 0; this.inversionCount = 0; this.userToneHistory = []; this.botStyleHistory = []; } connectToChat(username) { this.connect(username); } displayMessage(messageData) { // Enhanced display for advice messages with sentiment indicators const messageElement = document.createElement('div'); messageElement.className = `chat-message ${messageData.is_bot ? 'bot-message' : ''}`; let sentimentIndicator = ''; let avatarIcon = ''; if (messageData.is_bot) { // Bot message with personality indicator const botStyle = messageData.sentiment || 'neutral'; const userWas = messageData.user_was || 'neutral'; avatarIcon = ''; sentimentIndicator = `
You were: ${userWas} โ†’ I'm being: ${botStyle}
`; // Update counters this.inversionCount++; this.updateStats(); // Track bot style this.botStyleHistory.push(botStyle); this.updateBotStyleDisplay(botStyle); } else { avatarIcon = ''; // This would normally come from sentiment analysis // For now, we'll detect based on simple keywords const tone = this.detectUserTone(messageData.message); this.userToneHistory.push(tone); this.updateUserToneDisplay(tone); if (messageData.message.includes('?') || messageData.message.toLowerCase().includes('advice')) { this.adviceCount++; this.updateStats(); } } messageElement.innerHTML = `
${avatarIcon} ${this.escapeHtml(messageData.username)} ${messageData.timestamp}
${sentimentIndicator}
${this.formatAdviceMessage(messageData.message)}
`; // Add with animation this.chatMessages.appendChild(messageElement); // Special effects for advice responses if (messageData.is_bot && window.terminalEffects) { window.terminalEffects.powerOnEffect(messageElement); // Add personality inversion glow effect setTimeout(() => { messageElement.style.boxShadow = '0 0 15px rgba(57, 255, 20, 0.3)'; setTimeout(() => { messageElement.style.boxShadow = ''; }, 1000); }, 500); } this.scrollToBottom(); } formatAdviceMessage(message) { let formatted = this.escapeHtml(message); // Highlight advice keywords const adviceKeywords = [ 'advice', 'suggest', 'recommend', 'should', 'could', 'might', 'try', 'consider', 'think about', 'focus on', 'start with', 'remember' ]; adviceKeywords.forEach(keyword => { const regex = new RegExp(`\\b${keyword}\\b`, 'gi'); formatted = formatted.replace(regex, `${keyword}`); }); // Highlight British expressions const britishExpressions = [ 'right then', 'blimey', 'brilliant', 'lovely', 'quite', 'rather', 'I say', 'charming', 'splendid', 'terribly', 'absolutely' ]; britishExpressions.forEach(expression => { const regex = new RegExp(`\\b${expression}\\b`, 'gi'); formatted = formatted.replace(regex, `${expression}`); }); // Add emoji support formatted = formatted.replace(/:\)/g, '๐Ÿ˜Š'); formatted = formatted.replace(/:\(/g, '๐Ÿ˜”'); formatted = formatted.replace(/:D/g, '๐Ÿ˜„'); return formatted; } detectUserTone(message) { const messageLower = message.toLowerCase(); // Rude indicators const rudeWords = ['stupid', 'dumb', 'hate', 'sucks', 'awful', 'terrible', 'worst', 'useless', 'damn', 'shit']; const niceWords = ['please', 'thank', 'sorry', 'appreciate', 'wonderful', 'great', 'awesome', 'love', 'fantastic']; const rudeCount = rudeWords.filter(word => messageLower.includes(word)).length; const niceCount = niceWords.filter(word => messageLower.includes(word)).length; if (rudeCount > niceCount && rudeCount > 0) { return 'rude'; } else if (niceCount > rudeCount && niceCount > 0) { return 'nice'; } else { return 'neutral'; } } updateUserToneDisplay(tone) { const toneElement = document.getElementById('userTone'); if (toneElement) { toneElement.textContent = tone.charAt(0).toUpperCase() + tone.slice(1); toneElement.className = `badge ${tone === 'rude' ? 'bg-warning' : tone === 'nice' ? 'bg-success' : 'bg-secondary'}`; } } updateBotStyleDisplay(style) { const styleElement = document.getElementById('botStyle'); if (styleElement) { styleElement.textContent = style.charAt(0).toUpperCase() + style.slice(1); styleElement.className = `badge ${style === 'nice' ? 'bg-success' : style === 'rude' ? 'bg-warning' : 'bg-secondary'}`; } } updateStats() { // Update advice count const adviceCountElement = document.getElementById('adviceCount'); if (adviceCountElement) { adviceCountElement.textContent = this.adviceCount; } // Update inversion count const inversionCountElement = document.getElementById('inversionCount'); if (inversionCountElement) { inversionCountElement.textContent = this.inversionCount; } // Update base stats super.updateStats(); } sendMessage() { const message = this.messageInput.value.trim(); if (!message) return; // Rate limiting const now = Date.now(); if (now - this.lastMessageTime < 1000) { this.showSystemMessage('Slow down there! One advice request per second.', 'warning'); return; } this.lastMessageTime = now; // Send message with advice mode indicator this.socket.emit('send_message', { message: message, mode: 'advice' }); // Clear input and update stats this.messageInput.value = ''; this.messageCount++; this.updateStats(); // Stop typing indicator this.stopTyping(); // Show network activity if (window.terminalEffects) { window.terminalEffects.showNetworkActivity(); } // Special handling for advice requests if (message.includes('?') || message.toLowerCase().includes('advice')) { // Show special typing indicator for advice setTimeout(() => { const typingIndicator = document.getElementById('typingIndicator'); if (typingIndicator) { typingIndicator.innerHTML = ' AdviceBot is analyzing your tone and crafting response...'; typingIndicator.style.display = 'block'; } }, 500); } } showAdviceSystemMessage(message, type = 'info') { const messageElement = document.createElement('div'); messageElement.className = 'chat-message system-message'; let iconClass = 'fas fa-flask'; let textClass = 'text-terminal-accent'; switch(type) { case 'hypothesis': iconClass = 'fas fa-microscope'; textClass = 'text-success'; break; case 'inversion': iconClass = 'fas fa-exchange-alt'; textClass = 'text-warning'; break; case 'success': iconClass = 'fas fa-check-circle'; textClass = 'text-success'; break; } messageElement.innerHTML = `
${this.escapeHtml(message)}
`; this.chatMessages.appendChild(messageElement); this.scrollToBottom(); } // Enhanced welcome message for advice mode displayAdviceWelcome() { setTimeout(() => { this.showAdviceSystemMessage( "Personality Inversion Protocol activated! Try being rude or nice to see how I adapt my advice style. ๐Ÿงช", 'hypothesis' ); }, 2000); setTimeout(() => { this.showAdviceSystemMessage( "Pro tip: Ask about work, relationships, technology, health, or life in general!", 'inversion' ); }, 4000); } // Track engagement metrics for hypothesis testing trackEngagement(action) { const engagementData = { timestamp: new Date().toISOString(), action: action, user_tone_history: this.userToneHistory.slice(-5), // Last 5 tones bot_style_history: this.botStyleHistory.slice(-5), // Last 5 styles total_advice_requests: this.adviceCount, total_inversions: this.inversionCount }; // This could be sent to analytics console.log('Engagement tracked:', engagementData); } // Override connect method to set up advice-specific features connect(username) { super.connect(username); // Set up advice mode specific event listeners this.socket.on('advice_response', (data) => { this.trackEngagement('advice_received'); // Handle special advice responses }); // Show welcome messages after connection this.socket.on('connect', () => { setTimeout(() => { this.displayAdviceWelcome(); }, 3000); }); } } // Initialize advice chat let adviceChat; function initializeAdviceChat(username) { adviceChat = new AdviceChat(); adviceChat.connectToChat(username); } // Expose globally window.initializeAdviceChat = initializeAdviceChat; window.AdviceChat = AdviceChat;