// State Management
let isTyping = false;
let messageHistory = [];
let recognition = null;
// Initialize Speech Recognition
if ('webkitSpeechRecognition' in window || 'SpeechRecognition' in window) {
const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
recognition = new SpeechRecognition();
recognition.lang = 'pt-BR';
recognition.continuous = false;
recognition.interimResults = false;
}
// DOM Elements
const chatContainer = document.getElementById('chatContainer');
const messageForm = document.getElementById('messageForm');
const messageInput = document.getElementById('messageInput');
const sendBtn = document.getElementById('sendBtn');
const voiceModal = document.getElementById('voiceModal');
const voiceText = document.getElementById('voiceText');
// Knowledge Base
const knowledgeBase = {
greetings: {
patterns: ['oi', 'olá', 'ola', 'hey', 'e aí', 'e ai', 'bom dia', 'boa tarde', 'boa noite', 'salve'],
responses: [
'Oi! Como posso ajudar você hoje? 😊',
'Olá! Que bom ver você por aqui! ✨',
'Hey! Pronto para ajudar! 🚀',
'Bem-vindo! O que posso fazer por você?'
]
},
time: {
patterns: ['hora', 'horas', 'que horas', 'horário', 'horario'],
responses: () => {
const now = new Date();
const timeString = now.toLocaleTimeString('pt-BR', {
hour: '2-digit',
minute: '2-digit'
});
return `🕐 Agora são ${timeString}`;
}
},
date: {
patterns: ['data', 'data de hoje', 'que dia é hoje', 'dia de hoje'],
responses: () => {
const now = new Date();
const dateString = now.toLocaleDateString('pt-BR', {
weekday: 'long',
year: 'numeric',
month: 'long',
day: 'numeric'
});
return `📅 Hoje é ${dateString}`;
}
},
weather: {
patterns: ['clima', 'tempo', 'previsão', 'previsao', 'temperatura', 'está frio', 'está calor', 'ta frio', 'ta calor'],
responses: [
'🌤️ Não tenho acesso a dados meteorológicos em tempo real, mas posso sugerir que você verifique um app de clima confiável!',
'☀️ Infelizmente não consigo verificar o clima agora. Recomendo olhar o Weather.com ou o app do seu celular.'
]
},
jokes: {
patterns: ['piada', 'conta uma piada', 'me faça rir', 'me faz rir', 'algo engraçado'],
responses: [
'😄 Por que o computador foi ao médico? Porque estava com vírus! 🦠',
'😂 O que o pato disse para a pata? Vem quá! 🦆',
'🤣 Qual é o animal mais antigo? A zebra, porque está em preto e branco! 🦓',
'😅 Por que o livro de matemática se suicidou? Porque tinha muitos problemas! 📚',
'🤪 O que é um pontinho amarelo no alto de um prédio? Uma ervilha com vertigem! 🟡'
]
},
capital: {
patterns: ['capital', 'capital da', 'qual a capital'],
responses: {
'frança': '🇫🇷 A capital da França é Paris, também conhecida como Cidade Luz!',
'brasil': '🇧🇷 A capital do Brasil é Brasília, inaugurada em 1960!',
'japão': '🇯🇵 A capital do Japão é Tóquio, a maior metrópole do mundo!',
'estados unidos': '🇺🇸 A capital dos Estados Unidos é Washington, D.C.!',
'argentina': '🇦🇷 A capital da Argentina é Buenos Aires!',
'portugal': '🇵🇹 A capital de Portugal é Lisboa!',
'espanha': '🇪🇸 A capital da Espanha é Madri!',
'itália': '🇮🇹 A capital da Itália é Roma!',
'alemanha': '🇩🇪 A capital da Alemanha é Berlim!',
'canadá': '🇨🇦 A capital do Canadá é Ottawa!'
}
},
thanks: {
patterns: ['obrigado', 'obrigada', 'valeu', 'agradeço', 'thanks', 'ty'],
responses: [
'Por nada! 😊 Estou aqui para ajudar!',
'De nada! Fico feliz em poder ajudar! ✨',
'Não há de quê! Precisar de mais alguma coisa? 🙌'
]
},
calculator: {
patterns: ['calcular', 'quanto é', 'resultado de', '+', '-', '*', '/', 'x'],
responses: (message) => {
try {
// Remove non-math characters and evaluate
const cleanExpression = message.replace(/[^0-9+\-*/().\s]/g, '').replace(/x/g, '*');
if (!cleanExpression) return null;
const result = Function('"use strict"; return (' + cleanExpression + ')')();
return `🧮 O resultado de ${cleanExpression.replace('*', '×')} é ${result}`;
} catch {
return null;
}
}
},
name: {
patterns: ['seu nome', 'como se chama', 'quem é você', 'quem e voce', 'qual seu nome'],
responses: [
'Eu sou a Nova, sua assistente virtual! 🤖✨',
'Me chamo Nova! Fui criada para ajudar você com o que precisar!',
'Olá! Eu sou Nova, prazer em conhecê-lo! 💜'
]
},
help: {
patterns: ['ajuda', 'help', 'o que você faz', 'o que voce faz', 'capacidades'],
responses: [
'🛠️ **O que posso fazer:**\n\n• 🕐 Informar data e hora\n• 🌍 Responder sobre capitais\n• 😄 Contar piadas\n• 🧮 Fazer cálculos simples\n• 💬 Conversar sobre diversos assuntos\n\n**Tente perguntar:**\n• "Que horas são?"\n• "Qual a capital do Japão?"\n• "Quanto é 25 x 4?"'
]
},
music: {
patterns: ['música', 'musica', 'tocar', 'spotify', 'youtube music'],
responses: [
'🎵 Não consigo tocar música diretamente, mas posso sugerir que você use Spotify, YouTube Music ou Apple Music!',
'🎧 Para ouvir música, recomendo abrir seu app de streaming favorito!'
]
},
news: {
patterns: ['notícias', 'noticias', 'últimas notícias', 'novidades'],
responses: [
'📰 Não tenho acesso a notícias em tempo real. Sugiro verificar sites como G1, Folha, ou Estadão para informações atualizadas!'
]
},
motivation: {
patterns: ['motivação', 'motivacao', 'ânimo', 'animo', 'triste', 'deprimido', 'incentivo'],
responses: [
'💪 "O único limite para o nosso crescimento é a nossa própria determinação."\n\nVocê é mais forte do que imagina! ✨',
'🌟 "Não importa quantas vezes você caia, o que importa é quantas vezes você se levanta."\n\nVai dar tudo certo! 💜',
'⭐ "Acredite em você mesmo e tudo será possível!"\n\nVocê tem potencial para conquistar grandes coisas! 🚀'
]
}
};
// Auto-resize textarea
function autoResize(textarea) {
textarea.style.height = 'auto';
textarea.style.height = Math.min(textarea.scrollHeight, 120) + 'px';
}
// Handle Enter key
function handleKeyDown(e) {
if (e.key === 'Enter' && !e.shiftKey) {
e.preventDefault();
messageForm.dispatchEvent(new Event('submit'));
}
}
// Send suggestion
function sendSuggestion(text) {
messageInput.value = text;
messageForm.dispatchEvent(new Event('submit'));
}
// Create message element
function createMessageElement(text, isUser = false) {
const wrapper = document.createElement('div');
wrapper.className = `flex ${isUser ? 'justify-end' : 'justify-start'} message-bubble`;
const content = document.createElement('div');
content.className = `max-w-[80%] md:max-w-[70%] px-4 py-3 rounded-2xl ${
isUser
? 'gradient-bg text-white rounded-br-md'
: 'bg-white border border-gray-100 text-gray-800 rounded-bl-md shadow-sm'
}`;
// Parse markdown-like formatting
const formattedText = text
.replace(/\*\*(.*?)\*\*/g, '$1')
.replace(/\n/g, '
');
content.innerHTML = formattedText;
wrapper.appendChild(content);
return wrapper;
}
// Create typing indicator
function createTypingIndicator() {
const wrapper = document.createElement('div');
wrapper.id = 'typingIndicator';
wrapper.className = 'flex justify-start message-bubble';
const content = document.createElement('div');
content.className = 'bg-white border border-gray-100 px-4 py-3 rounded-2xl rounded-bl-md shadow-sm';
content.innerHTML = `