| | |
| | |
| | |
| |
|
| |
|
| | class AdviceChat extends SarcasticChat {
|
| | constructor() {
|
| | super();
|
| | this.adviceCount = 0;
|
| | this.inversionCount = 0;
|
| | this.userToneHistory = [];
|
| | this.botStyleHistory = [];
|
| | }
|
| |
|
| | connectToChat(username) {
|
| | this.connect(username);
|
| | }
|
| |
|
| | displayMessage(messageData) {
|
| |
|
| | const messageElement = document.createElement('div');
|
| | messageElement.className = `chat-message ${messageData.is_bot ? 'bot-message' : ''}`;
|
| |
|
| | let sentimentIndicator = '';
|
| | let avatarIcon = '';
|
| |
|
| | if (messageData.is_bot) {
|
| |
|
| | const botStyle = messageData.sentiment || 'neutral';
|
| | const userWas = messageData.user_was || 'neutral';
|
| |
|
| | avatarIcon = '<i class="fas fa-brain text-terminal-accent"></i>';
|
| | sentimentIndicator = `
|
| | <div class="sentiment-indicator mb-2">
|
| | <small class="text-muted">
|
| | You were: <span class="badge ${userWas === 'rude' ? 'bg-warning' : 'bg-success'}">${userWas}</span>
|
| | → I'm being: <span class="badge ${botStyle === 'nice' ? 'bg-success' : 'bg-warning'}">${botStyle}</span>
|
| | <i class="fas fa-exchange-alt text-terminal-green ms-1"></i>
|
| | </small>
|
| | </div>
|
| | `;
|
| |
|
| |
|
| | this.inversionCount++;
|
| | this.updateStats();
|
| |
|
| |
|
| | this.botStyleHistory.push(botStyle);
|
| | this.updateBotStyleDisplay(botStyle);
|
| | } else {
|
| | avatarIcon = '<i class="fas fa-user text-terminal-green"></i>';
|
| |
|
| |
|
| |
|
| | 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 = `
|
| | <div class="message-header">
|
| | ${avatarIcon}
|
| | <span class="message-username ${messageData.is_bot ? 'text-terminal-accent' : 'text-terminal-green'}">${this.escapeHtml(messageData.username)}</span>
|
| | <span class="message-timestamp">${messageData.timestamp}</span>
|
| | </div>
|
| | ${sentimentIndicator}
|
| | <div class="message-content">
|
| | ${this.formatAdviceMessage(messageData.message)}
|
| | </div>
|
| | `;
|
| |
|
| |
|
| | this.chatMessages.appendChild(messageElement);
|
| |
|
| |
|
| | if (messageData.is_bot && window.terminalEffects) {
|
| | window.terminalEffects.powerOnEffect(messageElement);
|
| |
|
| |
|
| | 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);
|
| |
|
| |
|
| | 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, `<span class="text-terminal-accent">${keyword}</span>`);
|
| | });
|
| |
|
| |
|
| | 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, `<span class="text-terminal-green">${expression}</span>`);
|
| | });
|
| |
|
| |
|
| | formatted = formatted.replace(/:\)/g, '😊');
|
| | formatted = formatted.replace(/:\(/g, '😔');
|
| | formatted = formatted.replace(/:D/g, '😄');
|
| |
|
| | return formatted;
|
| | }
|
| |
|
| | detectUserTone(message) {
|
| | const messageLower = message.toLowerCase();
|
| |
|
| |
|
| | 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() {
|
| |
|
| | const adviceCountElement = document.getElementById('adviceCount');
|
| | if (adviceCountElement) {
|
| | adviceCountElement.textContent = this.adviceCount;
|
| | }
|
| |
|
| |
|
| | const inversionCountElement = document.getElementById('inversionCount');
|
| | if (inversionCountElement) {
|
| | inversionCountElement.textContent = this.inversionCount;
|
| | }
|
| |
|
| |
|
| | super.updateStats();
|
| | }
|
| |
|
| | sendMessage() {
|
| | const message = this.messageInput.value.trim();
|
| | if (!message) return;
|
| |
|
| |
|
| | const now = Date.now();
|
| | if (now - this.lastMessageTime < 1000) {
|
| | this.showSystemMessage('Slow down there! One advice request per second.', 'warning');
|
| | return;
|
| | }
|
| | this.lastMessageTime = now;
|
| |
|
| |
|
| | this.socket.emit('send_message', {
|
| | message: message,
|
| | mode: 'advice'
|
| | });
|
| |
|
| |
|
| | this.messageInput.value = '';
|
| | this.messageCount++;
|
| | this.updateStats();
|
| |
|
| |
|
| | this.stopTyping();
|
| |
|
| |
|
| | if (window.terminalEffects) {
|
| | window.terminalEffects.showNetworkActivity();
|
| | }
|
| |
|
| |
|
| | if (message.includes('?') || message.toLowerCase().includes('advice')) {
|
| |
|
| | setTimeout(() => {
|
| | const typingIndicator = document.getElementById('typingIndicator');
|
| | if (typingIndicator) {
|
| | typingIndicator.innerHTML = '<i class="fas fa-brain"></i> 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 = `
|
| | <div class="message-content ${textClass}" style="border-left-color: currentColor;">
|
| | <i class="${iconClass} me-2"></i>${this.escapeHtml(message)}
|
| | </div>
|
| | `;
|
| |
|
| | this.chatMessages.appendChild(messageElement);
|
| | this.scrollToBottom();
|
| | }
|
| |
|
| |
|
| | 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);
|
| | }
|
| |
|
| |
|
| | trackEngagement(action) {
|
| | const engagementData = {
|
| | timestamp: new Date().toISOString(),
|
| | action: action,
|
| | user_tone_history: this.userToneHistory.slice(-5),
|
| | bot_style_history: this.botStyleHistory.slice(-5),
|
| | total_advice_requests: this.adviceCount,
|
| | total_inversions: this.inversionCount
|
| | };
|
| |
|
| |
|
| | console.log('Engagement tracked:', engagementData);
|
| | }
|
| |
|
| |
|
| | connect(username) {
|
| | super.connect(username);
|
| |
|
| |
|
| | this.socket.on('advice_response', (data) => {
|
| | this.trackEngagement('advice_received');
|
| |
|
| | });
|
| |
|
| |
|
| | this.socket.on('connect', () => {
|
| | setTimeout(() => {
|
| | this.displayAdviceWelcome();
|
| | }, 3000);
|
| | });
|
| | }
|
| | }
|
| |
|
| |
|
| | let adviceChat;
|
| |
|
| | function initializeAdviceChat(username) {
|
| | adviceChat = new AdviceChat();
|
| | adviceChat.connectToChat(username);
|
| | }
|
| |
|
| |
|
| | window.initializeAdviceChat = initializeAdviceChat;
|
| | window.AdviceChat = AdviceChat; |