/**
* 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 = `
${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;