document.addEventListener('DOMContentLoaded', () => { /* --- Clock --- */ function updateClock() { const now = new Date(); const timeString = now.toLocaleTimeString('en-US', { hour12: false }); const clockEl = document.getElementById('clock'); if(clockEl) clockEl.textContent = timeString; } setInterval(updateClock, 1000); updateClock(); /* --- Operation Control Logic --- */ let simState = 'IDLE'; // IDLE, RUNNING, PAUSED let simTime = 0; let simInterval = null; let progress = 0; const statusText = document.getElementById('sim-status-text'); const timerText = document.getElementById('sim-timer'); const progressBar = document.getElementById('sim-progress'); const btnAdvance = document.getElementById('btn-advance'); const btnPause = document.getElementById('btn-pause'); const btnReset = document.getElementById('btn-reset'); function formatTime(seconds) { const h = Math.floor(seconds / 3600).toString().padStart(2, '0'); const m = Math.floor((seconds % 3600) / 60).toString().padStart(2, '0'); const s = (seconds % 60).toString().padStart(2, '0'); return `${h}:${m}:${s}`; } function updateUI() { statusText.textContent = simState; // Color coding based on state statusText.classList.remove('text-neon-green', 'text-neon-orange', 'text-gray-500'); if (simState === 'RUNNING') { statusText.classList.add('text-neon-green'); statusText.classList.add('animate-pulse'); } else if (simState === 'PAUSED') { statusText.classList.add('text-neon-orange'); statusText.classList.remove('animate-pulse'); } else { statusText.classList.add('text-gray-500'); statusText.classList.remove('animate-pulse'); } timerText.textContent = formatTime(simTime); progressBar.style.width = `${progress}%`; } btnAdvance.addEventListener('click', () => { if (simState === 'RUNNING') return; // Already running simState = 'RUNNING'; statusText.classList.add('animate-pulse'); simInterval = setInterval(() => { simTime++; progress = (simTime % 60) / 60 * 100; // Loop progress for demo updateUI(); if (simTime % 60 === 0 && simTime > 0) { addAiMessage("Simulation milestone reached. Analyzing vector performance...", false); } }, 1000); updateUI(); addAiMessage("Simulation sequence initiated. Engines firing.", false); }); btnPause.addEventListener('click', () => { if (simState !== 'RUNNING') return; simState = 'PAUSED'; clearInterval(simInterval); updateUI(); addAiMessage("Simulation paused. Awaiting command.", false); }); btnReset.addEventListener('click', () => { simState = 'IDLE'; clearInterval(simInterval); simTime = 0; progress = 0; updateUI(); addAiMessage("Simulation reset. All parameters normalized.", false); }); /* --- AI Companion & NLP --- */ const chatHistory = document.getElementById('chat-history'); const aiInput = document.getElementById('ai-input'); const voiceBtn = document.getElementById('voice-btn'); const nlpStatus = document.getElementById('nlp-status'); const cmdChips = document.querySelectorAll('.cmd-chip'); function addAiMessage(text, isUser = false) { const div = document.createElement('div'); div.className = `flex items-start gap-3 ${isUser ? 'flex-row-reverse' : ''}`; const iconColor = isUser ? 'bg-neon-green/20 text-neon-green' : 'bg-gradient-to-br from-gray-700 to-gray-900 text-neon-gold'; const icon = isUser ? '' : ''; const bubbleColor = isUser ? 'bg-neon-green/10 border-neon-green/30' : 'bg-void-700 border-gray-700'; div.innerHTML = `
${icon}

${text}

`; chatHistory.appendChild(div); chatHistory.scrollTop = chatHistory.scrollHeight; feather.replace(); } function handleCommand(text) { const lower = text.toLowerCase(); let response = ""; if (lower.includes("pause") || lower.includes("stop")) { if (simState === 'RUNNING') btnPause.click(); response = "Acknowledged. Pausing operations."; } else if (lower.includes("start") || lower.includes("advance") || lower.includes("resume")) { if (simState !== 'RUNNING') btnAdvance.click(); response = "Acknowledged. Advancing simulation."; } else if (lower.includes("reset")) { btnReset.click(); response = "System resetting to initial state."; } else if (lower.includes("status") || lower.includes("report")) { response = `Current Status: ${simState}. Runtime: ${formatTime(simTime)}. Progress: ${Math.floor(progress)}%.`; } else if (lower.includes("hello") || lower.includes("hi")) { response = "Greetings, Commander. Systems nominal."; } else { response = `I received: "${text}". Please clarify the tactical directive.`; } addAiMessage(text, true); setTimeout(() => addAiMessage(response, false), 600); } // Text Input aiInput.addEventListener('keypress', (e) => { if (e.key === 'Enter' && aiInput.value.trim()) { handleCommand(aiInput.value); aiInput.value = ''; } }); // Chip Inputs cmdChips.forEach(chip => { chip.addEventListener('click', () => { handleCommand(chip.textContent); }); }); // NLP / Web Speech API if ('webkitSpeechRecognition' in window || 'SpeechRecognition' in window) { const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition; const recognition = new SpeechRecognition(); recognition.continuous = false; recognition.lang = 'en-US'; recognition.interimResults = false; recognition.onstart = () => { nlpStatus.textContent = "LISTENING..."; nlpStatus.classList.remove('text-gray-400', 'border-gray-600'); nlpStatus.classList.add('text-neon-red', 'border-neon-red', 'animate-pulse'); voiceBtn.classList.add('text-neon-red'); }; recognition.onend = () => { nlpStatus.textContent = "VOICE OFF"; nlpStatus.classList.add('text-gray-400', 'border-gray-600'); nlpStatus.classList.remove('text-neon-red', 'border-neon-red', 'animate-pulse'); voiceBtn.classList.remove('text-neon-red'); }; recognition.onresult = (event) => { const transcript = event.results[0][0].transcript; handleCommand(transcript); }; voiceBtn.addEventListener('click', () => { recognition.start(); }); } else { voiceBtn.style.display = 'none'; console.log("Web Speech API not supported in this browser."); } });