console.log("🚀 Cortexa JS Loaded - Production Version"); // ================= API CONFIGURATION - FIXED ================= const BASE_URL = ""; const API_URL = BASE_URL + "/chat"; const ENDPOINTS = { chat: BASE_URL + "/chat", uploadDocument: BASE_URL + "/upload-document", generateAudio: BASE_URL + "/generate-audio", youtubeSearch: BASE_URL + "/youtube-search", youtubeVideoInfo: BASE_URL + "/youtube-video-info", health: BASE_URL + "/health", models: BASE_URL + "/models", chats: BASE_URL + "/api/chats" }; console.log("✅ Backend URL:", BASE_URL); console.log("✅ Chat API:", API_URL); // ================= GLOBAL VARIABLES ================= let currentChatId = null; let currentProjectId = null; let currentDocument = null; let currentAudioMode = 'simple'; let mediaRecorder = null; let audioChunks = []; let isRecording = false; let currentAudio = null; let currentAudioText = null; // In-memory cache of the currently-loaded chat list (used for both // logged-in / backend-synced and guest / session-only modes). let sessionChatsCache = []; // ================= AUTH HELPERS ================= function getAuthToken() { return localStorage.getItem("access_token") || null; } function isLoggedIn() { return !!getAuthToken(); } function authHeaders() { const token = getAuthToken(); return token ? { "Authorization": "Bearer " + token } : {}; } function getCurrentUser() { return localStorage.getItem("email") || "guest"; } // ================= CHAT STORAGE (backend when logged in, session-only otherwise) ================= // IMPORTANT: chats are never persisted to a shared localStorage key anymore. // Logged-in users' chats live in the backend, scoped strictly to their // account by the server (JWT-verified on every request). Guests get an // in-memory-only chat list that disappears when the tab closes, so nothing // leaks to the next person who opens the app on a shared device. async function getChats() { if (isLoggedIn()) { try { const res = await fetch(ENDPOINTS.chats, { method: "GET", headers: { ...authHeaders() } }); if (res.status === 401) { // Token expired/invalid — treat as logged out localStorage.removeItem("access_token"); sessionChatsCache = []; return []; } const data = await res.json(); sessionChatsCache = data.chats || []; return sessionChatsCache; } catch (err) { console.error("Failed to load chats from server:", err); return sessionChatsCache; } } // Guest mode: session-only, never written to a shared localStorage key return sessionChatsCache; } async function persistChat(chatId, title, messages) { if (isLoggedIn()) { try { const res = await fetch(ENDPOINTS.chats, { method: "POST", headers: { "Content-Type": "application/json", ...authHeaders() }, body: JSON.stringify({ chat_id: chatId, title: title, messages: messages }) }); const data = await res.json(); return data.chat ? data.chat.id : chatId; } catch (err) { console.error("Failed to save chat to server:", err); return chatId; } } // Guest mode: keep it in memory for this tab/session only return chatId; } async function removeChat(chatId) { if (isLoggedIn()) { try { await fetch(ENDPOINTS.chats + "/" + chatId, { method: "DELETE", headers: { ...authHeaders() } }); } catch (err) { console.error("Failed to delete chat on server:", err); } } sessionChatsCache = sessionChatsCache.filter(c => c.id !== chatId); } // Call this from your logout button handler so nothing lingers for the // next person on a shared browser. window.clearLocalSessionOnLogout = function() { localStorage.removeItem("access_token"); localStorage.removeItem("email"); sessionChatsCache = []; currentChatId = null; }; function getProjects() { const user = getCurrentUser(); return JSON.parse(localStorage.getItem("projects_" + user)) || []; } function saveProjects(projects) { const user = getCurrentUser(); localStorage.setItem("projects_" + user, JSON.stringify(projects)); } // ================= HELPER FUNCTIONS ================= function escapeHtml(text) { if (!text) return ''; const div = document.createElement('div'); div.textContent = text; return div.innerHTML; } function showToast(message, type) { type = type || 'info'; let toast = document.getElementById('customToast'); if (!toast) { toast = document.createElement('div'); toast.id = 'customToast'; toast.className = 'toast-message'; document.body.appendChild(toast); } toast.style.background = type === 'error' ? 'linear-gradient(90deg, #ef4444, #dc2626)' : 'linear-gradient(90deg, #22c55e, #16a34a)'; toast.textContent = message; toast.style.animation = 'none'; void toast.offsetWidth; toast.style.animation = 'fadeSlide 3s ease forwards'; } // ================= FORMAT FUNCTION ================= function formatContent(content) { if (!content) return ''; var formatted = content.replace(/\n/g, '
'); formatted = formatted.replace(/\*\*(.*?)\*\*/g, '$1'); formatted = formatted.replace(/\*(.*?)\*/g, '$1'); formatted = formatted.replace(/^[\•\-\*]\s/gm, '• '); return formatted; } // ================= DISPLAY MESSAGE FUNCTION ================= function displayMessage(text, sender) { var chatBox = document.getElementById("searchResults"); if (!chatBox) { console.error("searchResults container not found!"); return; } var msgDiv = document.createElement("div"); msgDiv.className = sender === "user" ? "user-bubble" : "ai-bubble"; var formattedText = formatContent(text); var senderName = sender === "user" ? "You" : "Cortexa"; msgDiv.innerHTML = '
' + senderName + '
' + formattedText + '
'; var id = "msg-" + Date.now() + "-" + Math.random(); msgDiv.id = id; chatBox.appendChild(msgDiv); chatBox.scrollTo({ top: chatBox.scrollHeight, behavior: 'smooth' }); return id; } function updateMessage(id, newText) { var msg = document.getElementById(id); if (msg) { var contentDiv = msg.querySelector(".chat-content"); if (contentDiv) { contentDiv.innerHTML = formatContent(newText); } } } // ================= MAIN CHAT FUNCTION ================= window.performSearch = async function() { console.log("🔵 performSearch called"); var queryInput = document.getElementById('searchInput'); if (!queryInput) { console.error("❌ searchInput not found!"); return; } var query = queryInput.value.trim(); if (!query) { console.log("Empty query"); return; } displayMessage(query, 'user'); queryInput.value = ''; var loadingId = displayMessage('Thinking...', 'bot'); try { var requestBody = { message: query, document_content: currentDocument && currentDocument.content ? currentDocument.content : null, audio: false }; console.log("📤 Sending to:", ENDPOINTS.chat); var response = await fetch(ENDPOINTS.chat, { method: "POST", headers: { "Content-Type": "application/json", "Accept": "application/json" }, body: JSON.stringify(requestBody) }); const rawText = await response.text(); if (!response.ok) { throw new Error("HTTP " + response.status + ": " + rawText.substring(0, 300)); } let data; try { data = JSON.parse(rawText); } catch (jsonError) { throw new Error("Backend returned invalid JSON: " + rawText.substring(0, 300)); } if (data.response) { updateMessage(loadingId, data.response); await saveCurrentChat(query, data.response); } else { updateMessage(loadingId, "⚠️ Backend connected, but no AI response was returned.\n\nResponse: " + JSON.stringify(data)); } } catch (error) { console.error("❌ Chat error:", error); updateMessage(loadingId, "⚠️ Error connecting to AI.\n\nDetails: " + error.message + "\n\nMake sure the backend is running and accessible."); } } // ================= SAVE CHAT (backend-synced when logged in) ================= async function saveCurrentChat(userMessage, aiResponse) { if (!currentChatId) { var title = userMessage.substring(0, 30); var messages = [ { role: 'user', content: userMessage, timestamp: new Date().toISOString() }, { role: 'assistant', content: aiResponse, timestamp: new Date().toISOString() } ]; var newId = await persistChat(null, title, messages); currentChatId = newId; sessionChatsCache.unshift({ id: newId, title: title, messages: messages, created_at: new Date().toISOString(), updated_at: new Date().toISOString() }); } else { var chatIndex = sessionChatsCache.findIndex(function(c) { return c.id === currentChatId; }); var existingMessages = chatIndex !== -1 ? sessionChatsCache[chatIndex].messages : []; var newMessages = existingMessages.concat([ { role: 'user', content: userMessage, timestamp: new Date().toISOString() }, { role: 'assistant', content: aiResponse, timestamp: new Date().toISOString() } ]); var title = (chatIndex !== -1 && newMessages.length > 2) ? sessionChatsCache[chatIndex].title : userMessage.substring(0, 30); await persistChat(currentChatId, title, newMessages); if (chatIndex !== -1) { sessionChatsCache[chatIndex].messages = newMessages; sessionChatsCache[chatIndex].title = title; } } await loadChats(); } // ================= ADD WELCOME MESSAGE ================= function addWelcomeMessage() { var container = document.getElementById("searchResults"); if (!container) return; if (container.children.length === 0) { displayMessage("👋 Hi! I'm Cortexa. Ask me anything! 💙", 'bot'); } } // ================= LOAD CHATS ================= async function loadChats() { var container = document.getElementById("chatList"); if (!container) return; var chats = await getChats(); if (chats.length === 0) { container.innerHTML = '
No chats yet
'; return; } container.innerHTML = ""; chats.slice(0, 20).forEach(function(chat) { var div = document.createElement("div"); div.className = "chat-item" + (currentChatId === chat.id ? ' active' : ''); div.setAttribute('data-chat-id', chat.id); div.innerHTML = '💬 ' + escapeHtml(chat.title.substring(0, 35)) + '
'; container.appendChild(div); }); } // ================= LOAD PROJECTS ================= function loadProjects() { var container = document.getElementById("projectListRight"); if (!container) return; var projects = getProjects(); if (projects.length === 0) { container.innerHTML = '
No projects yet
'; return; } container.innerHTML = ""; projects.slice(0, 10).forEach(function(project) { var div = document.createElement("div"); div.className = "project-item"; div.setAttribute('data-project-id', project.id); div.innerHTML = '📁 ' + escapeHtml(project.name.substring(0, 35)); container.appendChild(div); }); } // ================= CHAT MANAGEMENT ================= window.loadChatById = async function(chatId) { var chats = await getChats(); var chat = chats.find(function(c) { return c.id === chatId; }); if (chat) { currentChatId = chat.id; var container = document.getElementById("searchResults"); if (container) { container.innerHTML = ""; chat.messages.forEach(function(msg) { displayMessage(msg.content, msg.role === 'user' ? 'user' : 'bot'); }); } await loadChats(); showToast("Chat loaded!"); } } window.deleteChatById = async function(chatId) { if (confirm("Delete this chat?")) { await removeChat(chatId); if (currentChatId === chatId) { currentChatId = null; var container = document.getElementById("searchResults"); if (container) { container.innerHTML = ""; addWelcomeMessage(); } } await loadChats(); showToast("🗑️ Chat deleted!"); } var dropdown = document.getElementById("chat-dropdown-" + chatId); if (dropdown) dropdown.classList.remove('show'); } window.startNewChat = function(e) { if (e) e.preventDefault(); currentChatId = null; var container = document.getElementById("searchResults"); if (container) { container.innerHTML = ""; addWelcomeMessage(); } loadChats(); showToast("✨ New chat started!"); } window.toggleChatMenu = function(event, chatId) { event.stopPropagation(); document.querySelectorAll('.chat-dropdown.show').forEach(function(dropdown) { if (dropdown.id !== "chat-dropdown-" + chatId) { dropdown.classList.remove('show'); } }); var dropdown = document.getElementById("chat-dropdown-" + chatId); if (!dropdown) return; dropdown.classList.toggle('show'); setTimeout(function() { dropdown.classList.remove('show'); }, 3000); } window.togglePlusDropdown = function() { var dropdown = document.getElementById('plusDropdown'); if (dropdown) dropdown.classList.toggle('show'); } window.shareChat = async function() { if (currentChatId) { var chats = await getChats(); var chat = chats.find(function(c) { return c.id === currentChatId; }); if (chat) { var shareText = chat.title + '\n\n' + chat.messages.map(function(m) { return (m.role === 'user' ? 'You' : 'Cortexa') + ': ' + m.content; }).join('\n\n'); navigator.clipboard.writeText(shareText); showToast("✅ Chat copied to clipboard!"); } } else { showToast("❌ No active chat to share!"); } } window.deleteChat = async function() { if (currentChatId) { if (confirm("Delete this chat?")) { await removeChat(currentChatId); currentChatId = null; var container = document.getElementById("searchResults"); if (container) { container.innerHTML = ""; addWelcomeMessage(); } await loadChats(); showToast("🗑️ Current chat deleted!"); } } else { showToast("❌ No active chat to delete!"); } } window.pinChat = function() { showToast("📌 Pin feature coming soon!"); } window.createProject = function() { var name = prompt("Enter project name:"); if (name && name.trim() !== "") { var projects = getProjects(); var newProject = { id: 'project_' + Date.now(), name: name.trim(), created_at: new Date().toLocaleString() }; projects.push(newProject); saveProjects(projects); loadProjects(); showToast("✅ Project \"" + name + "\" created!"); } } // ================= DOCUMENT CHAT ================= window.documentChat = function() { var input = document.createElement('input'); input.type = 'file'; input.accept = '.txt,.pdf,.docx'; input.onchange = async function(e) { var file = e.target.files[0]; if (file) { var formData = new FormData(); formData.append('file', file); showToast("📄 Uploading document..."); try { var response = await fetch(ENDPOINTS.uploadDocument, { method: 'POST', body: formData }); var data = await response.json(); if (!response.ok) { throw new Error(data.error || "Upload failed"); } currentDocument = data; showToast("✅ Document \"" + file.name + "\" loaded! You can now ask questions about it."); displayMessage("📄 **Document loaded:** " + file.name + "\n\nYou can now ask me questions about this document!", 'bot'); } catch (error) { console.error("❌ Document upload error:", error); showToast("❌ Error uploading document: " + error.message, "error"); } } }; input.click(); } // ================= AUDIO MODE ================= window.openAudioMode = function() { var modal = document.getElementById('audioModal'); if (modal) modal.style.display = 'flex'; } window.closeAudioMode = function() { var modal = document.getElementById('audioModal'); if (modal) modal.style.display = 'none'; } window.setAudioMode = function(mode, btn) { currentAudioMode = mode; document.querySelectorAll('.mode-btn').forEach(function(b) { return b.classList.remove('active'); }); btn.classList.add('active'); showToast("🎵 Audio mode: " + mode); } window.toggleMicrophone = async function() { var micBtn = document.getElementById('micButton'); var statusDiv = document.getElementById('micStatus'); if (!isRecording) { try { var stream = await navigator.mediaDevices.getUserMedia({ audio: true }); mediaRecorder = new MediaRecorder(stream); audioChunks = []; mediaRecorder.ondataavailable = function(event) { audioChunks.push(event.data); }; mediaRecorder.onstop = async function() { var audioBlob = new Blob(audioChunks, { type: 'audio/wav' }); statusDiv.innerHTML = '🎤 Speech detected! Processing...'; showToast("🎤 Voice input received! Please type your question for now (voice-to-text coming soon)"); statusDiv.innerHTML = 'Click microphone to speak'; isRecording = false; micBtn.classList.remove('listening'); stream.getTracks().forEach(function(track) { return track.stop(); }); }; mediaRecorder.start(); isRecording = true; micBtn.classList.add('listening'); statusDiv.innerHTML = '🔴 Recording... Click again to stop'; } catch (err) { console.error('Microphone error:', err); statusDiv.innerHTML = '❌ Microphone access denied'; showToast("Microphone access denied", "error"); } } else { if (mediaRecorder && isRecording) { mediaRecorder.stop(); } } } // ================= SEND AUDIO QUERY ================= window.sendAudioQuery = async function() { var queryInput = document.getElementById('audioQueryInput'); var query = queryInput.value.trim(); if (!query) { showToast("Please enter a question", "error"); return; } var responseArea = document.getElementById('audioResponseArea'); var responseText = document.getElementById('responseText'); responseArea.style.display = 'block'; responseText.innerHTML = 'Generating response...'; try { var requestBody = { message: query, audio: true }; var response = await fetch(ENDPOINTS.chat, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(requestBody) }); var data = await response.json(); currentAudioText = data.response; responseText.innerHTML = formatContent(data.response); var audioResponse = await fetch(ENDPOINTS.generateAudio, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ text: data.response }) }); var audioData = await audioResponse.json(); if (audioData.audio_url) { var audioPlayer = document.getElementById('audioPlayer'); audioPlayer.src = BASE_URL + audioData.audio_url; document.getElementById('audioPlayerContainer').style.display = 'block'; } } catch (error) { console.error("Audio error:", error); responseText.innerHTML = '❌ Error generating response'; showToast("Error connecting to AI", "error"); } } window.playAudioResponse = function() { var audio = document.getElementById('audioPlayer'); if (audio && audio.src) { audio.play(); } else { showToast("No audio available", "error"); } } window.pauseAudioResponse = function() { var audio = document.getElementById('audioPlayer'); if (audio) audio.pause(); } window.stopAudioResponse = function() { var audio = document.getElementById('audioPlayer'); if (audio) { audio.pause(); audio.currentTime = 0; } } window.downloadAudioResponse = function() { var audio = document.getElementById('audioPlayer'); if (audio && audio.src) { var a = document.createElement('a'); a.href = audio.src; a.download = 'cortexa_audio.mp3'; a.click(); showToast("Downloading audio..."); } else { showToast("No audio available", "error"); } } // ================= VIDEO MODE ================= window.openVideoMode = function() { var modal = document.getElementById('videoModal'); if (modal) modal.style.display = 'flex'; switchVideoTab('youtube'); } window.closeVideoMode = function() { var modal = document.getElementById('videoModal'); if (modal) modal.style.display = 'none'; } window.switchVideoTab = function(tab) { var youtubeTab = document.getElementById('youtubeTab'); var libraryTab = document.getElementById('libraryTab'); var btns = document.querySelectorAll('.tab-btn'); btns.forEach(function(btn) { return btn.classList.remove('active'); }); if (tab === 'youtube') { if (youtubeTab) youtubeTab.style.display = 'block'; if (libraryTab) libraryTab.style.display = 'none'; if (btns[0]) btns[0].classList.add('active'); } else { if (youtubeTab) youtubeTab.style.display = 'none'; if (libraryTab) libraryTab.style.display = 'block'; if (btns[1]) btns[1].classList.add('active'); loadVideoLibrary(); } } // ================= YOUTUBE SEARCH ================= window.searchYouTube = async function() { var query = document.getElementById('youtubeSearchQuery').value; if (!query) { showToast("Please enter a search term", "error"); return; } showToast("🔍 Searching YouTube..."); var resultsDiv = document.getElementById('youtubeResults'); if (!resultsDiv) return; resultsDiv.innerHTML = '
🔍 Searching for videos...
'; try { var response = await fetch(ENDPOINTS.youtubeSearch + "?query=" + encodeURIComponent(query) + "&max_results=12"); var data = await response.json(); if (data.error) { resultsDiv.innerHTML = '
❌ ' + data.error + '
'; showToast(data.error, "error"); return; } if (!data.videos || data.videos.length === 0) { resultsDiv.innerHTML = '
😕 No videos found. Try a different search term.
'; return; } resultsDiv.innerHTML = '

📹 Search Results (' + data.videos.length + ' videos)

Click on any video to get AI summary

' + data.videos.map(function(video) { return '
' + escapeHtml(video.title) + '
' + (video.duration || 'N/A') + '

' + escapeHtml(video.title.substring(0, 70)) + '

' + escapeHtml(video.channel) + '

👁️ ' + (video.views || 'N/A') + ' views

'; }).join('') + '
'; showToast("Found " + data.videos.length + " videos!"); } catch (error) { console.error('Search error:', error); resultsDiv.innerHTML = '
❌ Failed to search YouTube. Make sure backend is running.
'; showToast("Error connecting to backend", "error"); } } // ================= YOUTUBE VIDEO INFO ================= window.getVideoInfoAndSummary = async function(videoId, videoTitle) { showToast("📹 Getting video information and generating AI summary..."); var infoDiv = document.getElementById('youtubeVideoInfo'); if (!infoDiv) return; infoDiv.style.display = 'block'; infoDiv.innerHTML = '
🧠 Analyzing video content...
'; try { var infoResponse = await fetch(ENDPOINTS.youtubeVideoInfo + "?video_id=" + videoId); var videoInfo = await infoResponse.json(); if (videoInfo.error) { infoDiv.innerHTML = '
❌ ' + videoInfo.error + '
'; return; } var summaryPrompt = 'Please provide a comprehensive summary of this YouTube video:\n\nTitle: ' + (videoTitle || videoInfo.title) + '\nChannel: ' + (videoInfo.channel || 'Unknown') + '\nDescription: ' + (videoInfo.description || 'No description available') + '\n\nPlease provide:\n1. Main topic/theme of the video\n2. 5-7 key points covered\n3. Important takeaways\n4. Who should watch this video\n5. A brief one-paragraph summary\n\nFormat the response in a clean, organized way with emojis for each section.'; var summaryResponse = await fetch(ENDPOINTS.chat, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ message: summaryPrompt, document_content: null, audio: false }) }); var summaryData = await summaryResponse.json(); var aiSummary = summaryData.response || "Summary generation failed. Please try again."; infoDiv.innerHTML = '

✅ ' + escapeHtml(videoInfo.title || videoTitle) + '

📺 Channel: ' + escapeHtml(videoInfo.channel || 'N/A') + '

👁️ Views: ' + parseInt(videoInfo.views || 0).toLocaleString() + '

👍 Likes: ' + parseInt(videoInfo.likes || 0).toLocaleString() + '

⏱️ Duration: ' + (videoInfo.duration || 'N/A') + '

🤖 AI GENERATED SUMMARY

' + formatContent(aiSummary) + '
📝 Video Description

' + escapeHtml((videoInfo.description || 'No description').substring(0, 1000)) + '

'; document.getElementById('youtubeOptions').style.display = 'block'; showToast("✅ AI Summary generated successfully!"); } catch (error) { console.error('Error:', error); infoDiv.innerHTML = '
❌ Error generating summary. Please try again.
'; showToast("Error generating summary", "error"); } } window.closeVideoInfo = function() { var infoDiv = document.getElementById('youtubeVideoInfo'); if (infoDiv) infoDiv.style.display = 'none'; } window.openInYouTube = function(videoId) { var youtubeUrl = 'https://www.youtube.com/watch?v=' + videoId; window.open(youtubeUrl, '_blank'); showToast("📺 Opening YouTube in new tab..."); } window.copySummaryToClipboard = function() { var summaryText = document.querySelector('.summary-text')?.innerText; if (summaryText) { navigator.clipboard.writeText(summaryText); showToast("📋 Summary copied to clipboard!"); } else { showToast("No summary to copy", "error"); } } window.downloadSummaryAsFile = function() { var summaryText = document.querySelector('.summary-text')?.innerText; if (summaryText) { var blob = new Blob([summaryText], { type: 'text/plain' }); var url = URL.createObjectURL(blob); var a = document.createElement('a'); a.href = url; a.download = 'video_summary.txt'; a.click(); URL.revokeObjectURL(url); showToast("💾 Summary downloaded!"); } else { showToast("No summary to download", "error"); } } window.saveVideoToLibrary = function(videoId, videoTitle) { var user = getCurrentUser(); var savedVideos = JSON.parse(localStorage.getItem("videos_" + user) || '[]'); if (!savedVideos.some(function(v) { return v.id === videoId; })) { var newVideo = { id: videoId, title: videoTitle, url: 'https://youtube.com/watch?v=' + videoId, date: new Date().toLocaleString(), thumbnail: 'https://img.youtube.com/vi/' + videoId + '/mqdefault.jpg' }; savedVideos.push(newVideo); localStorage.setItem("videos_" + user, JSON.stringify(savedVideos)); showToast("💾 Video saved to library!"); loadVideoLibrary(); } else { showToast("Video already in library!"); } } function loadVideoLibrary() { var user = getCurrentUser(); var libraryDiv = document.getElementById('videoLibraryList'); if (!libraryDiv) return; var savedVideos = JSON.parse(localStorage.getItem("videos_" + user) || '[]'); if (savedVideos.length === 0) { libraryDiv.innerHTML = '
📭 No saved videos. Search and save videos to see them here!
'; return; } libraryDiv.innerHTML = '
' + savedVideos.map(function(video) { return '
' + escapeHtml(video.title) + '

' + escapeHtml(video.title.substring(0, 50)) + '

Saved: ' + video.date + '

'; }).join('') + '
'; } window.removeFromLibrary = function(videoId) { var user = getCurrentUser(); var savedVideos = JSON.parse(localStorage.getItem("videos_" + user) || '[]'); savedVideos = savedVideos.filter(function(v) { return v.id !== videoId; }); localStorage.setItem("videos_" + user, JSON.stringify(savedVideos)); loadVideoLibrary(); showToast("🗑️ Video removed from library"); } // ================= REPORT MODE ================= window.openReportMode = function() { var modal = document.getElementById('reportModal'); if (modal) { modal.style.display = 'flex'; } } window.closeReportMode = function() { var modal = document.getElementById('reportModal'); if (modal) modal.style.display = 'none'; } window.generateReport = async function() { var topic = document.getElementById('reportTopicInput').value; if (!topic) { showToast("Please enter a topic", "error"); return; } var format = document.getElementById('reportFormat')?.value || 'PDF Document'; var includeCharts = document.getElementById('includeCharts')?.checked || false; var includeTables = document.getElementById('includeTables')?.checked || false; var includeExecutive = document.getElementById('includeExecutive')?.checked || true; var includeRecommendations = document.getElementById('includeRecommendations')?.checked || true; var includeAppendix = document.getElementById('includeAppendix')?.checked || false; var progressDiv = document.getElementById('reportProgress'); var progressFill = document.getElementById('reportProgressFill'); var displayDiv = document.getElementById('reportDisplay'); var contentDiv = document.getElementById('reportContent'); if (progressDiv) { progressDiv.style.display = 'block'; progressDiv.innerHTML = '

📊 Generating comprehensive report on "' + topic.substring(0, 50) + '"...

'; } var width = 0; var interval = setInterval(function() { width += 10; if (progressFill) progressFill.style.width = width + '%'; }, 200); try { var prompt = 'Generate a comprehensive, professional report about "' + topic + '". The report should include:'; if (includeExecutive) prompt += '\n- Executive Summary'; prompt += '\n- Introduction'; prompt += '\n- Key Findings (at least 5 points with detailed explanations)'; prompt += '\n- Detailed Analysis'; if (includeCharts) prompt += '\n- Charts and Graphs Analysis (describe what charts would show)'; if (includeTables) prompt += '\n- Data Tables (create relevant data tables)'; prompt += '\n- Challenges and Opportunities'; if (includeRecommendations) prompt += '\n- Recommendations (at least 3 actionable recommendations)'; prompt += '\n- Conclusion'; if (includeAppendix) prompt += '\n- Appendix with References and Sources'; prompt += '\n\nFormat the report with proper headings (## for main sections), subheadings (### for subsections), and bullet points. Make it professional, well-structured, data-driven, and suitable for business/academic audience. Use markdown formatting.'; var response = await fetch(ENDPOINTS.chat, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ message: prompt, document_content: null, audio: false }) }); var data = await response.json(); var reportContent = data.response || "Failed to generate report."; reportContent = reportContent.replace(/## (.*?)$/gm, '

$1

'); reportContent = reportContent.replace(/### (.*?)$/gm, '

$1

'); reportContent = reportContent.replace(/\*\*(.*?)\*\*/g, '$1'); reportContent = reportContent.replace(/^- (.*?)$/gm, '
  • $1
  • '); reportContent = reportContent.replace(/\n/g, '
    '); clearInterval(interval); if (progressDiv) progressDiv.style.display = 'none'; if (displayDiv) displayDiv.style.display = 'block'; window.currentReport = { topic: topic, content: reportContent, rawContent: data.response, format: format, date: new Date().toLocaleString(), options: { includeCharts: includeCharts, includeTables: includeTables, includeExecutive: includeExecutive, includeRecommendations: includeRecommendations, includeAppendix: includeAppendix } }; if (contentDiv) { contentDiv.innerHTML = '

    📊 ' + escapeHtml(topic) + '

    📅 Generated: ' + new Date().toLocaleString() + '📄 Format: ' + format + '🤖 Generated by Cortexa AI
    ' + reportContent + '
    '; } showToast("✅ Report generated successfully!"); } catch (error) { clearInterval(interval); if (progressDiv) progressDiv.style.display = 'none'; console.error('Report error:', error); showToast("Error generating report", "error"); } } window.downloadReportAsPDF = function() { var reportContainer = document.getElementById('reportContainer'); if (!reportContainer) { showToast("No report to download! Generate a report first.", "error"); return; } var printWindow = window.open('', '_blank'); printWindow.document.write('' + (window.currentReport?.topic || 'Report') + ' - Cortexa AI' + reportContainer.outerHTML + ''); printWindow.print(); printWindow.close(); showToast("📄 Report sent to printer (save as PDF)"); } window.downloadReportAsDOCX = function() { if (!window.currentReport) { showToast("No report to download! Generate a report first.", "error"); return; } var reportContent = document.getElementById('reportContentText')?.innerText || window.currentReport.rawContent; if (!reportContent) { showToast("No content to download", "error"); return; } var docContent = window.currentReport.topic + '\n' + '='.repeat(50) + '\n\nGenerated on: ' + window.currentReport.date + '\nFormat: ' + window.currentReport.format + '\n\n' + reportContent + '\n\n' + '='.repeat(50) + '\nGenerated by Cortexa AI Report Generator'; var blob = new Blob([docContent], { type: 'application/msword' }); var url = URL.createObjectURL(blob); var a = document.createElement('a'); a.href = url; a.download = window.currentReport.topic.replace(/[^a-z0-9]/gi, '_') + '_report.doc'; a.click(); URL.revokeObjectURL(url); showToast("📄 Report downloaded as DOCX!"); } window.copyReportToClipboard = function() { if (!window.currentReport) { showToast("No report to copy! Generate a report first.", "error"); return; } var reportText = document.getElementById('reportContentText')?.innerText || window.currentReport.rawContent; if (reportText) { navigator.clipboard.writeText(reportText).then(function() { showToast("📋 Report copied to clipboard!"); }).catch(function() { showToast("Failed to copy", "error"); }); } else { showToast("No content to copy", "error"); } } window.shareReport = function() { if (!window.currentReport) { showToast("No report to share! Generate a report first.", "error"); return; } var shareText = '📊 Report: ' + window.currentReport.topic + '\n\n' + (document.getElementById('reportContentText')?.innerText || window.currentReport.rawContent).substring(0, 500) + '...\n\nGenerated on: ' + window.currentReport.date + '\n\nGenerated by Cortexa AI'; navigator.clipboard.writeText(shareText).then(function() { showToast("📤 Report summary copied to clipboard! You can now share it anywhere."); }).catch(function() { showToast("Failed to copy for sharing", "error"); }); } window.saveReportToLibrary = function() { if (!window.currentReport) { showToast("No report to save! Generate a report first.", "error"); return; } var user = getCurrentUser(); var savedReports = JSON.parse(localStorage.getItem("reports_" + user) || '[]'); var reportToSave = { id: 'report_' + Date.now(), title: window.currentReport.topic, content: window.currentReport.rawContent, formattedContent: window.currentReport.content, date: window.currentReport.date, format: window.currentReport.format, options: window.currentReport.options }; savedReports.unshift(reportToSave); localStorage.setItem("reports_" + user, JSON.stringify(savedReports)); showToast("✅ Report \"" + window.currentReport.topic + "\" saved to library!"); } window.printReport = function() { var reportContainer = document.getElementById('reportContainer'); if (!reportContainer) { showToast("No report to print! Generate a report first.", "error"); return; } var printWindow = window.open('', '_blank'); printWindow.document.write('' + (window.currentReport?.topic || 'Report') + ' - Cortexa AI' + reportContainer.outerHTML + ''); printWindow.print(); printWindow.close(); showToast("🖨️ Report sent to printer!"); } window.loadReportFromLibrary = function(reportId) { var user = getCurrentUser(); var savedReports = JSON.parse(localStorage.getItem("reports_" + user) || '[]'); var report = savedReports.find(function(r) { return r.id === reportId; }); if (report) { window.currentReport = { topic: report.title, content: report.formattedContent, rawContent: report.content, date: report.date, format: report.format, options: report.options }; var contentDiv = document.getElementById('reportContent'); if (contentDiv) { contentDiv.innerHTML = '

    📊 ' + escapeHtml(report.title) + '

    📅 Generated: ' + report.date + '📄 Format: ' + report.format + '
    ' + report.formattedContent + '
    '; } document.getElementById('reportDisplay').style.display = 'block'; showToast("✅ Report \"" + report.title + "\" loaded from library!"); } else { showToast("Report not found!", "error"); } } window.openReportLibrary = function() { var user = getCurrentUser(); var savedReports = JSON.parse(localStorage.getItem("reports_" + user) || '[]'); if (savedReports.length === 0) { showToast("No saved reports found!", "info"); return; } var libraryHTML = '

    📚 Saved Reports

    '; savedReports.forEach(function(report) { libraryHTML += '
    ' + escapeHtml(report.title) + '' + report.date + '
    '; }); libraryHTML += '
    '; var modal = document.getElementById('reportLibraryModal'); if (!modal) { modal = document.createElement('div'); modal.id = 'reportLibraryModal'; modal.className = 'report-library-floating-modal'; document.body.appendChild(modal); } modal.innerHTML = libraryHTML; modal.style.display = 'block'; } window.closeReportLibrary = function() { var modal = document.getElementById('reportLibraryModal'); if (modal) modal.style.display = 'none'; } // ============================================ // LEARNING TOOLS - QUIZ GENERATOR // ============================================ window.openLearningTools = function() { var modal = document.getElementById('learningToolsModal'); if (modal) modal.style.display = 'flex'; switchLearningTab('quiz'); } window.closeLearningTools = function() { var modal = document.getElementById('learningToolsModal'); if (modal) modal.style.display = 'none'; } window.switchLearningTab = function(tab) { var quizTab = document.getElementById('quizTab'); var notesTab = document.getElementById('notesTab'); var btns = document.querySelectorAll('.learning-tab-btn'); btns.forEach(function(btn) { return btn.classList.remove('active'); }); if (tab === 'quiz') { if (quizTab) quizTab.style.display = 'block'; if (notesTab) notesTab.style.display = 'none'; if (btns[0]) btns[0].classList.add('active'); } else { if (quizTab) quizTab.style.display = 'none'; if (notesTab) notesTab.style.display = 'block'; if (btns[1]) btns[1].classList.add('active'); } } window.generateQuiz = async function() { var topic = document.getElementById('quizTopicInput').value; if (!topic) { showToast("Please enter a topic", "error"); return; } var numQuestions = document.getElementById('quizCount')?.value || 5; var difficulty = document.getElementById('quizDifficulty')?.value || 'medium'; var questionType = document.getElementById('quizType')?.value || 'mixed'; var progressDiv = document.getElementById('quizProgress'); var progressFill = document.getElementById('quizProgressFill'); var displayDiv = document.getElementById('quizDisplay'); var contentDiv = document.getElementById('quizContent'); if (progressDiv) progressDiv.style.display = 'block'; var width = 0; var interval = setInterval(function() { width += 10; if (progressFill) progressFill.style.width = width + '%'; }, 100); try { var prompt = 'Generate a quiz about "' + topic + '" with exactly ' + numQuestions + ' questions. Difficulty: ' + difficulty + '. Type: ' + questionType + '.\n\nReturn ONLY valid JSON with this exact format:\n{\n "title": "' + topic + ' Quiz",\n "questions": [\n {\n "id": 1,\n "text": "Question text here",\n "type": "mcq",\n "options": ["Option A", "Option B", "Option C", "Option D"],\n "correctAnswer": "Option A",\n "explanation": "Brief explanation"\n }\n ]\n}\n\nFor true/false, options should be ["True", "False"].\nMake questions educational and appropriate for ' + difficulty + ' difficulty.'; var response = await fetch(ENDPOINTS.chat, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ message: prompt, document_content: null, audio: false }) }); var data = await response.json(); var quizData; try { var jsonStr = data.response; var jsonMatch = jsonStr.match(/\{[\s\S]*\}/); if (jsonMatch) jsonStr = jsonMatch[0]; quizData = JSON.parse(jsonStr); } catch (e) { quizData = { title: topic + ' Quiz', questions: Array(parseInt(numQuestions)).fill().map(function(_, i) { return { id: i + 1, text: 'Sample question about ' + topic + ' ' + (i + 1), type: "mcq", options: ["Option A", "Option B", "Option C"], correctAnswer: "Option A", explanation: "This is a sample explanation." }; }) }; } clearInterval(interval); if (progressDiv) progressDiv.style.display = 'none'; if (displayDiv) displayDiv.style.display = 'block'; window.currentQuizData = quizData; window.quizAnswers = {}; var quizHTML = '

    📝 ' + escapeHtml(quizData.title) + '

    Difficulty: ' + difficulty + ' | Questions: ' + quizData.questions.length + '

    '; quizData.questions.forEach(function(q, idx) { var qNum = idx + 1; quizHTML += '

    Question ' + qNum + ': ' + escapeHtml(q.text) + '

    '; var options = q.options || (q.type === 'truefalse' ? ['True', 'False'] : ['Option A', 'Option B', 'Option C']); options.forEach(function(opt) { quizHTML += ''; }); quizHTML += '
    '; }); quizHTML += '
    '; if (contentDiv) contentDiv.innerHTML = quizHTML; showToast("✅ Quiz generated with " + quizData.questions.length + " questions!"); } catch (error) { clearInterval(interval); if (progressDiv) progressDiv.style.display = 'none'; console.error('Quiz error:', error); showToast("Error generating quiz", "error"); } } window.saveQuizAnswer = function(questionNum, answer) { if (!window.quizAnswers) window.quizAnswers = {}; window.quizAnswers[questionNum] = answer; var questionCard = document.querySelector('.quiz-question-card[data-question-id="' + questionNum + '"]'); if (questionCard) { questionCard.style.borderLeft = '4px solid #10b981'; } } window.submitQuizAnswers = function() { if (!window.currentQuizData || !window.currentQuizData.questions) { showToast("No quiz loaded!", "error"); return; } var score = 0; var totalQuestions = window.currentQuizData.questions.length; var results = []; window.currentQuizData.questions.forEach(function(q, idx) { var qNum = idx + 1; var userAnswer = window.quizAnswers ? window.quizAnswers[qNum] : null; var isCorrect = userAnswer === q.correctAnswer; if (isCorrect) { score++; } results.push({ id: qNum, question: q.text, userAnswer: userAnswer || "Not answered", correctAnswer: q.correctAnswer, isCorrect: isCorrect, explanation: q.explanation }); var feedbackDiv = document.getElementById('feedback-' + qNum); if (feedbackDiv) { if (userAnswer) { if (isCorrect) { feedbackDiv.innerHTML = '
    ✅ Correct! ' + (q.explanation || 'Great job!') + '
    '; feedbackDiv.style.backgroundColor = '#d1fae5'; } else { feedbackDiv.innerHTML = '
    ❌ Incorrect!
    Your answer: ' + escapeHtml(userAnswer) + '
    Correct answer: ' + escapeHtml(q.correctAnswer) + '
    ' + (q.explanation ? '📖 ' + q.explanation : '') + '
    '; feedbackDiv.style.backgroundColor = '#fee2e2'; } } else { feedbackDiv.innerHTML = '
    ⚠️ Not answered!
    Correct answer: ' + escapeHtml(q.correctAnswer) + '
    ' + (q.explanation ? '📖 ' + q.explanation : '') + '
    '; feedbackDiv.style.backgroundColor = '#fffbeb'; } feedbackDiv.style.display = 'block'; feedbackDiv.style.padding = '12px'; feedbackDiv.style.borderRadius = '8px'; feedbackDiv.style.marginTop = '10px'; } }); var percentage = Math.round((score / totalQuestions) * 100); var gradeMessage = ''; var gradeIcon = ''; if (percentage >= 90) { gradeMessage = 'Excellent! You\'re a master of this topic! 🏆'; gradeIcon = '🎉'; } else if (percentage >= 70) { gradeMessage = 'Good job! You have a solid understanding! 👍'; gradeIcon = '📚'; } else if (percentage >= 50) { gradeMessage = 'Not bad! Review the material and try again! 💪'; gradeIcon = '📖'; } else { gradeMessage = 'Keep studying! You\'ll get better with practice! 🌟'; gradeIcon = '⭐'; } var resultsContainer = document.getElementById('quizResultsContainer'); if (resultsContainer) { resultsContainer.style.display = 'block'; resultsContainer.innerHTML = '
    ' + gradeIcon + '

    📊 Quiz Results

    ' + score + '/' + totalQuestions + '
    ' + percentage + '%
    ' + gradeMessage + '
    📖 View Detailed Results
    ' + results.map(function(r) { return '

    Q' + r.id + ': ' + escapeHtml(r.question) + '

    Your answer: ' + escapeHtml(r.userAnswer) + '

    Correct: ' + escapeHtml(r.correctAnswer) + '

    ' + (r.explanation ? '

    Explanation: ' + escapeHtml(r.explanation) + '

    ' : '') + '
    '; }).join('') + '
    '; } resultsContainer.scrollIntoView({ behavior: 'smooth', block: 'nearest' }); showToast("Quiz completed! Score: " + score + "/" + totalQuestions + " (" + percentage + "%)"); } window.resetQuizAnswers = function() { window.quizAnswers = {}; document.querySelectorAll('#quizQuestionsContainer input[type="radio"]').forEach(function(radio) { radio.checked = false; }); document.querySelectorAll('.quiz-feedback').forEach(function(feedback) { feedback.style.display = 'none'; feedback.innerHTML = ''; }); document.querySelectorAll('.quiz-question-card').forEach(function(card) { card.style.borderLeft = ''; }); var resultsContainer = document.getElementById('quizResultsContainer'); if (resultsContainer) resultsContainer.style.display = 'none'; showToast("Quiz reset! You can try again."); } window.scrollToWrongAnswers = function() { var wrongFeedbacks = document.querySelectorAll('.wrong-feedback'); if (wrongFeedbacks.length > 0) { wrongFeedbacks[0].scrollIntoView({ behavior: 'smooth', block: 'center' }); showToast("Reviewing " + wrongFeedbacks.length + " incorrect answers..."); } else { showToast("🎉 Perfect score! No wrong answers to review!"); } } window.exportQuizResults = function() { if (!window.currentQuizData || !window.quizAnswers) { showToast("No quiz results to export!", "error"); return; } var exportText = '📝 ' + window.currentQuizData.title + '\n'; exportText += '📅 Date: ' + new Date().toLocaleString() + '\n'; exportText += '📊 Total Questions: ' + window.currentQuizData.questions.length + '\n'; exportText += '="\n\n'; var score = 0; window.currentQuizData.questions.forEach(function(q, idx) { var qNum = idx + 1; var userAnswer = window.quizAnswers[qNum] || "Not answered"; var isCorrect = userAnswer === q.correctAnswer; if (isCorrect) score++; exportText += qNum + '. ' + q.text + '\n'; exportText += ' Your answer: ' + userAnswer + '\n'; exportText += ' Correct answer: ' + q.correctAnswer + '\n'; exportText += ' Result: ' + (isCorrect ? '✓ CORRECT' : '✗ INCORRECT') + '\n'; if (q.explanation) { exportText += ' Explanation: ' + q.explanation + '\n'; } exportText += '\n'; }); var percentage = Math.round((score / window.currentQuizData.questions.length) * 100); exportText += '="\n'; exportText += 'FINAL SCORE: ' + score + '/' + window.currentQuizData.questions.length + ' (' + percentage + '%)\n'; exportText += 'Grade: ' + (percentage >= 70 ? 'PASSED' : 'NEEDS IMPROVEMENT') + '\n'; var blob = new Blob([exportText], { type: 'text/plain' }); var url = URL.createObjectURL(blob); var a = document.createElement('a'); a.href = url; a.download = window.currentQuizData.title.replace(/ /g, '_') + '_results.txt'; a.click(); URL.revokeObjectURL(url); showToast("Quiz results exported!"); } window.exportQuizAsPDF = function() { var content = document.getElementById('quizContent')?.innerHTML; if (content) { var printWindow = window.open('', '_blank'); printWindow.document.write('Quiz' + content + ''); printWindow.print(); } } window.copyQuizToClipboard = function() { if (!window.currentQuizData) return; var quizText = window.currentQuizData.title + '\n\n'; window.currentQuizData.questions.forEach(function(q, idx) { quizText += (idx + 1) + '. ' + q.text + '\n Correct: ' + q.correctAnswer + '\n\n'; }); navigator.clipboard.writeText(quizText); showToast("Quiz copied!"); } window.saveQuizToLibrary = function() { if (!window.currentQuizData) return; var user = getCurrentUser(); var savedQuizzes = JSON.parse(localStorage.getItem("quizzes_" + user) || '[]'); savedQuizzes.push({ id: 'quiz_' + Date.now(), title: window.currentQuizData.title, data: window.currentQuizData, date: new Date().toLocaleString() }); localStorage.setItem("quizzes_" + user, JSON.stringify(savedQuizzes)); showToast("Quiz saved to library!"); } // ============================================ // STUDY NOTES // ============================================ window.generateStudyNotes = async function() { var topic = document.getElementById('notesTopicInput').value; if (!topic) { showToast("Please enter a topic", "error"); return; } var progressDiv = document.getElementById('notesProgress'); var progressFill = document.getElementById('notesProgressFill'); var displayDiv = document.getElementById('notesDisplay'); var contentDiv = document.getElementById('notesContent'); if (progressDiv) progressDiv.style.display = 'block'; var width = 0; var interval = setInterval(function() { width += 10; if (progressFill) progressFill.style.width = width + '%'; }, 100); try { var prompt = 'Create comprehensive study notes about "' + topic + '".\n\nInclude:\n1. Key Concepts (at least 5)\n2. Important Definitions\n3. Summary Points\n4. Key Takeaways\n5. Study Tips\n\nFormat with clear headings, bullet points, and emojis for easy reading.\nMake it organized and educational.'; var response = await fetch(ENDPOINTS.chat, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ message: prompt, document_content: null, audio: false }) }); var data = await response.json(); var notesContent = data.response || "Failed to generate notes."; clearInterval(interval); if (progressDiv) progressDiv.style.display = 'none'; if (displayDiv) displayDiv.style.display = 'block'; if (contentDiv) { contentDiv.innerHTML = '

    📚 Study Notes: ' + escapeHtml(topic) + '

    Generated on: ' + new Date().toLocaleString() + '

    ' + formatContent(notesContent) + '
    '; } window.currentNotes = { topic: topic, content: notesContent, date: new Date().toLocaleString() }; showToast("✅ Study notes generated!"); } catch (error) { clearInterval(interval); if (progressDiv) progressDiv.style.display = 'none'; console.error('Notes error:', error); showToast("Error generating notes", "error"); } } window.exportNotesAsPDF = function() { var content = document.getElementById('notesContent')?.innerHTML; if (content) { var printWindow = window.open('', '_blank'); printWindow.document.write('Study Notes' + content + ''); printWindow.print(); } } window.copyNotesToClipboard = function() { var content = document.getElementById('notesContent')?.innerText; if (content) { navigator.clipboard.writeText(content); showToast("Notes copied!"); } } window.saveNotesToLibrary = function() { if (!window.currentNotes) return; var user = getCurrentUser(); var savedNotes = JSON.parse(localStorage.getItem("notes_" + user) || '[]'); savedNotes.push(window.currentNotes); localStorage.setItem("notes_" + user, JSON.stringify(savedNotes)); showToast("Notes saved to library!"); } window.printNotes = function() { var content = document.getElementById('notesContent')?.innerHTML; if (content) { var printWindow = window.open('', '_blank'); printWindow.document.write('Notes' + content + ''); printWindow.print(); } } window.useChatForLearning = async function(type) { if (!currentChatId) { showToast("No active chat found. Start a chat first!", "error"); return; } var chats = await getChats(); var chat = chats.find(function(c) { return c.id === currentChatId; }); if (!chat || !chat.messages || chat.messages.length === 0) { showToast("No chat content found!", "error"); return; } var lastMessages = chat.messages.slice(-5); var chatContent = lastMessages.map(function(m) { return m.role + ': ' + m.content; }).join('\n\n'); if (type === 'quiz') { document.getElementById('quizTopicInput').value = "Based on this conversation: " + chatContent.substring(0, 200); showToast("✅ Chat content loaded! Click Generate Quiz"); } else if (type === 'notes') { document.getElementById('notesTopicInput').value = "Based on this conversation: " + chatContent.substring(0, 200); showToast("✅ Chat content loaded! Click Generate Notes"); } } window.uploadForLearning = function(type) { var input = document.createElement('input'); input.type = 'file'; input.accept = '.txt,.pdf,.docx'; input.onchange = function() { showToast("Document uploaded for " + type + " generation!"); }; input.click(); } // ============================================ // GAMES MODULE // ============================================ var currentGameType = null; var currentQuizQuestions = []; var currentQuizIndex = 0; var quizScore = 0; var quizTimer = null; var timeLeft = 30; var memoryCards = []; var memoryFlipped = []; var memoryLocked = false; var memoryMatches = 0; var typingCurrentWord = ""; var typingScore = 0; var typingRound = 0; var typingWordsList = []; var triviaQuestions = []; var triviaIndex = 0; var triviaScore = 0; var scrambleCurrentWord = ""; var scrambleCurrentHint = ""; var scrambleScore = 0; var scrambleRound = 0; var scrambleWordsList = []; var tfQuestions = []; var tfIndex = 0; var tfScore = 0; window.openGamesModal = function() { console.log("Opening Games Modal"); var modal = document.getElementById('gamesModal'); if (modal) { modal.style.display = 'flex'; } showGameSelectionScreen(); } window.closeGamesModal = function() { var modal = document.getElementById('gamesModal'); if (modal) modal.style.display = 'none'; if (quizTimer) clearInterval(quizTimer); } function showGameSelectionScreen() { var gameContent = document.getElementById('gameContent'); if (!gameContent) return; gameContent.innerHTML = '
    🏆

    Quiz Race

    Test your knowledge with timed quizzes

    🎴

    Memory Match

    Match terms with definitions

    ⌨️

    Typing Speed

    Improve your typing speed

    ❓

    Trivia Challenge

    Answer random knowledge questions

    🔤

    Word Scramble

    Unscramble the letters to form words

    ✓✗

    True or False

    Test your knowledge with true/false questions

    '; } window.selectGame = function(gameType) { currentGameType = gameType; var gameContent = document.getElementById('gameContent'); if (!gameContent) return; gameContent.innerHTML = '

    ' + getGameTitle(gameType) + '

    '; var activeContainer = document.getElementById('activeGameContainer'); switch(gameType) { case 'quiz-race': loadQuizRaceGame(activeContainer); break; case 'memory-match': loadMemoryMatchGame(activeContainer); break; case 'typing-speed': loadTypingSpeedGame(activeContainer); break; case 'trivia-challenge': loadTriviaChallengeGame(activeContainer); break; case 'word-scramble': loadWordScrambleGame(activeContainer); break; case 'true-false': loadTrueFalseGame(activeContainer); break; default: showGameSelectionScreen(); } } function getGameTitle(gameType) { var titles = { 'quiz-race': '🏆 Quiz Race', 'memory-match': '🎴 Memory Match', 'typing-speed': '⌨️ Typing Speed', 'trivia-challenge': '❓ Trivia Challenge', 'word-scramble': '🔤 Word Scramble', 'true-false': '✓✗ True or False' }; return titles[gameType] || 'Game'; } // ================= QUIZ RACE GAME ================= function loadQuizRaceGame(container) { currentQuizIndex = 0; quizScore = 0; currentQuizQuestions = [ { question: "What is the capital of France?", options: ["London", "Berlin", "Paris", "Madrid"], correct: "Paris" }, { question: "Which planet is known as the Red Planet?", options: ["Mars", "Jupiter", "Venus", "Saturn"], correct: "Mars" }, { question: "Who painted the Mona Lisa?", options: ["Van Gogh", "Picasso", "Da Vinci", "Rembrandt"], correct: "Da Vinci" }, { question: "What is the largest ocean on Earth?", options: ["Atlantic", "Indian", "Arctic", "Pacific"], correct: "Pacific" }, { question: "What is the fastest land animal?", options: ["Lion", "Cheetah", "Leopard", "Tiger"], correct: "Cheetah" } ]; displayQuizQuestion(container); } function displayQuizQuestion(container) { if (currentQuizIndex >= currentQuizQuestions.length) { showQuizResults(container); return; } var q = currentQuizQuestions[currentQuizIndex]; timeLeft = 30; if (quizTimer) clearInterval(quizTimer); quizTimer = setInterval(function() { timeLeft--; var timerEl = document.getElementById('quizTimer'); if (timerEl) { timerEl.textContent = timeLeft; if (timeLeft <= 5) timerEl.style.color = '#ef4444'; if (timeLeft <= 0) { clearInterval(quizTimer); moveToNextQuizQuestion(container); } } }, 1000); container.innerHTML = '
    Question ' + (currentQuizIndex + 1) + '/' + currentQuizQuestions.length + '
    ⭐ Score: ' + quizScore + '
    ⏱️ Time: 30s
    ' + escapeHtml(q.question) + '
    ' + q.options.map(function(opt) { return ''; }).join('') + '
    '; } window.checkQuizAnswer = function(selected, btnElement) { if (quizTimer) clearInterval(quizTimer); var q = currentQuizQuestions[currentQuizIndex]; var feedback = document.getElementById('gameFeedback'); document.querySelectorAll('.game-option-btn').forEach(function(btn) { btn.disabled = true; }); if (selected === q.correct) { quizScore += 10; feedback.innerHTML = '
    ✅ Correct! +10 points
    '; showToast("✅ Correct!"); } else { feedback.innerHTML = '
    ❌ Wrong! Correct answer: ' + q.correct + '
    '; showToast("❌ Wrong answer!"); } setTimeout(function() { moveToNextQuizQuestion(document.getElementById('activeGameContainer')); }, 2000); } function moveToNextQuizQuestion(container) { currentQuizIndex++; if (currentQuizIndex < currentQuizQuestions.length) { displayQuizQuestion(container); } else { showQuizResults(container); } } function showQuizResults(container) { var percentage = Math.round((quizScore / (currentQuizQuestions.length * 10)) * 100); container.innerHTML = '
    ' + (percentage >= 70 ? '🏆' : '📚') + '

    Quiz Complete!

    Final Score: ' + quizScore + '/' + (currentQuizQuestions.length * 10) + '
    ' + percentage + '%
    '; } // ================= MEMORY MATCH GAME ================= function loadMemoryMatchGame(container) { var pairs = [ { pair1: "HTML", pair2: "Web Page" }, { pair1: "CSS", pair2: "Styling" }, { pair1: "JS", pair2: "JavaScript" }, { pair1: "API", pair2: "Interface" }, { pair1: "JSON", pair2: "Data Format" }, { pair1: "DOM", pair2: "Document Object" } ]; memoryCards = []; pairs.forEach(function(pair, idx) { memoryCards.push({ id: idx * 2, value: pair.pair1, matched: false, pairId: idx }); memoryCards.push({ id: idx * 2 + 1, value: pair.pair2, matched: false, pairId: idx }); }); for (var i = memoryCards.length - 1; i > 0; i--) { var j = Math.floor(Math.random() * (i + 1)); var temp = memoryCards[i]; memoryCards[i] = memoryCards[j]; memoryCards[j] = temp; } memoryFlipped = []; memoryLocked = false; memoryMatches = 0; renderMemoryGame(container); } function renderMemoryGame(container) { container.innerHTML = '
    🎴 Memory Match
    Matches: ' + memoryMatches + '/' + (memoryCards.length / 2) + '
    ' + memoryCards.map(function(card, idx) { return '
    ❓
    ' + (card.matched ? '✓' : escapeHtml(card.value)) + '
    '; }).join('') + '
    '; } window.flipMemoryCard = function(index) { if (memoryLocked) return; if (memoryCards[index].matched) return; if (memoryFlipped.includes(index)) return; if (memoryFlipped.length === 2) return; memoryFlipped.push(index); renderMemoryGame(document.getElementById('activeGameContainer')); if (memoryFlipped.length === 2) { checkMemoryMatch(); } } function checkMemoryMatch() { var card1 = memoryCards[memoryFlipped[0]]; var card2 = memoryCards[memoryFlipped[1]]; if (card1.pairId === card2.pairId) { card1.matched = true; card2.matched = true; memoryMatches++; memoryFlipped = []; renderMemoryGame(document.getElementById('activeGameContainer')); showToast("🎉 Match found!"); if (memoryMatches === memoryCards.length / 2) { setTimeout(function() { showToast("🏆 Congratulations! You completed the game!"); }, 500); } } else { memoryLocked = true; setTimeout(function() { memoryFlipped = []; memoryLocked = false; renderMemoryGame(document.getElementById('activeGameContainer')); }, 1000); } } // ================= TYPING SPEED GAME ================= function loadTypingSpeedGame(container) { typingWordsList = ["javascript", "programming", "developer", "computer", "keyboard", "website", "application", "database"]; typingRound = 0; typingScore = 0; loadNextTypingWord(container); } function loadNextTypingWord(container) { if (typingRound >= typingWordsList.length) { showTypingResults(container); return; } typingCurrentWord = typingWordsList[typingRound]; container.innerHTML = '
    Word ' + (typingRound + 1) + '/' + typingWordsList.length + '
    ⭐ Score: ' + typingScore + '
    ' + typingCurrentWord + '
    '; document.getElementById('typingInput')?.focus(); } window.checkTypingWord = function() { var input = document.getElementById('typingInput'); var userInput = input?.value.trim().toLowerCase(); var feedback = document.getElementById('typingFeedback'); var container = document.getElementById('activeGameContainer'); if (userInput === typingCurrentWord) { typingScore += 10; feedback.innerHTML = '
    ✅ Correct! +10 points
    '; showToast("🎉 Correct!"); } else { feedback.innerHTML = '
    ❌ Wrong! The word was: ' + typingCurrentWord + '
    '; showToast("❌ Wrong!"); } setTimeout(function() { typingRound++; loadNextTypingWord(container); }, 1500); } function showTypingResults(container) { var percentage = Math.round((typingScore / (typingWordsList.length * 10)) * 100); container.innerHTML = '
    ⌨️

    Typing Speed Complete!

    Score: ' + typingScore + '/' + (typingWordsList.length * 10) + '
    ' + percentage + '%
    '; } // ================= TRIVIA CHALLENGE ================= function loadTriviaChallengeGame(container) { triviaIndex = 0; triviaScore = 0; triviaQuestions = [ { question: "What is the capital of Japan?", options: ["Seoul", "Beijing", "Tokyo", "Bangkok"], correct: "Tokyo", funFact: "Tokyo is the most populous metropolitan area in the world" }, { question: "Who wrote 'Romeo and Juliet'?", options: ["Charles Dickens", "Jane Austen", "William Shakespeare", "Mark Twain"], correct: "William Shakespeare", funFact: "Written around 1595" }, { question: "What is the chemical symbol for Gold?", options: ["Go", "Gd", "Au", "Ag"], correct: "Au", funFact: "Au comes from Latin 'aurum'" }, { question: "Which country gifted the Statue of Liberty to the USA?", options: ["England", "Spain", "France", "Germany"], correct: "France", funFact: "Gifted in 1886" }, { question: "What is the world's longest river?", options: ["Amazon", "Nile", "Yangtze", "Mississippi"], correct: "Nile", funFact: "The Nile is about 6,650 km long" } ]; displayTriviaQuestion(container); } function displayTriviaQuestion(container) { if (triviaIndex >= triviaQuestions.length) { showTriviaResults(container); return; } var q = triviaQuestions[triviaIndex]; container.innerHTML = '
    Question ' + (triviaIndex + 1) + '/' + triviaQuestions.length + '
    ⭐ Score: ' + triviaScore + '
    ' + escapeHtml(q.question) + '
    ' + q.options.map(function(opt) { return ''; }).join('') + '
    '; } window.checkTriviaAnswer = function(selected, btnElement) { var q = triviaQuestions[triviaIndex]; var feedback = document.getElementById('triviaFeedback'); document.querySelectorAll('.game-option-btn').forEach(function(btn) { btn.disabled = true; }); if (selected === q.correct) { triviaScore += 10; feedback.innerHTML = '
    ✅ Correct! ' + (q.funFact || 'Great job!') + '
    '; showToast("✅ Correct!"); } else { feedback.innerHTML = '
    ❌ Wrong! Correct: ' + q.correct + '. ' + (q.funFact || '') + '
    '; showToast("❌ Wrong!"); } setTimeout(function() { triviaIndex++; displayTriviaQuestion(document.getElementById('activeGameContainer')); }, 2000); } function showTriviaResults(container) { var percentage = Math.round((triviaScore / (triviaQuestions.length * 10)) * 100); container.innerHTML = '
    ' + (percentage >= 70 ? '🏆' : '📚') + '

    Trivia Complete!

    Score: ' + triviaScore + '/' + (triviaQuestions.length * 10) + '
    ' + percentage + '%
    '; } // ================= WORD SCRAMBLE ================= function loadWordScrambleGame(container) { scrambleWordsList = [ { word: "javascript", hint: "A programming language for web" }, { word: "computer", hint: "An electronic device" }, { word: "keyboard", hint: "Used for typing" }, { word: "monitor", hint: "Displays output" }, { word: "internet", hint: "Global network" } ]; scrambleRound = 0; scrambleScore = 0; loadNextScrambleWord(container); } function loadNextScrambleWord(container) { if (scrambleRound >= scrambleWordsList.length) { showScrambleResults(container); return; } var wordObj = scrambleWordsList[scrambleRound]; scrambleCurrentWord = wordObj.word; scrambleCurrentHint = wordObj.hint; var scrambled = scrambleCurrentWord.split(''); for (var i = scrambled.length - 1; i > 0; i--) { var j = Math.floor(Math.random() * (i + 1)); var temp = scrambled[i]; scrambled[i] = scrambled[j]; scrambled[j] = temp; } container.innerHTML = '
    Word ' + (scrambleRound + 1) + '/' + scrambleWordsList.length + '
    ⭐ Score: ' + scrambleScore + '
    ' + scrambled.join(' ').toUpperCase() + '
    💡 Hint: ' + escapeHtml(scrambleCurrentHint) + '
    '; document.getElementById('scrambleGuess')?.focus(); } window.checkScrambleGuess = function() { var input = document.getElementById('scrambleGuess'); var guess = input?.value.trim().toLowerCase(); var feedback = document.getElementById('scrambleFeedback'); var container = document.getElementById('activeGameContainer'); if (guess === scrambleCurrentWord.toLowerCase()) { scrambleScore += 10; feedback.innerHTML = '
    ✅ Correct! +10 points
    '; showToast("🎉 Correct!"); } else { feedback.innerHTML = '
    ❌ Wrong! The word was: ' + scrambleCurrentWord + '
    '; showToast("❌ Wrong!"); } setTimeout(function() { scrambleRound++; loadNextScrambleWord(container); }, 1500); } function showScrambleResults(container) { var percentage = Math.round((scrambleScore / (scrambleWordsList.length * 10)) * 100); container.innerHTML = '
    🔤

    Word Scramble Complete!

    Score: ' + scrambleScore + '/' + (scrambleWordsList.length * 10) + '
    ' + percentage + '%
    '; } // ================= TRUE OR FALSE GAME ================= function loadTrueFalseGame(container) { tfIndex = 0; tfScore = 0; tfQuestions = [ { statement: "The sun rises in the east.", answer: true, explanation: "The sun rises in the east and sets in the west" }, { statement: "Humans have 5 hearts.", answer: false, explanation: "Humans have 1 heart" }, { statement: "Water is H2O.", answer: true, explanation: "Water molecules consist of 2 hydrogen and 1 oxygen atom" }, { statement: "Mount Everest is the tallest mountain.", answer: true, explanation: "Mount Everest is 8,848 meters tall" }, { statement: "The Earth is flat.", answer: false, explanation: "The Earth is actually round (an oblate spheroid)" } ]; displayTrueFalseQuestion(container); } function displayTrueFalseQuestion(container) { if (tfIndex >= tfQuestions.length) { showTrueFalseResults(container); return; } var q = tfQuestions[tfIndex]; container.innerHTML = '
    Question ' + (tfIndex + 1) + '/' + tfQuestions.length + '
    ⭐ Score: ' + tfScore + '
    ' + escapeHtml(q.statement) + '
    '; } window.checkTrueFalseAnswer = function(selected) { var q = tfQuestions[tfIndex]; var feedback = document.getElementById('tfFeedback'); var isCorrect = (selected === q.answer); document.querySelectorAll('.true-btn-large, .false-btn-large').forEach(function(btn) { btn.disabled = true; }); if (isCorrect) { tfScore += 10; feedback.innerHTML = '
    ✅ Correct! ' + q.explanation + '
    '; showToast("✅ Correct!"); } else { feedback.innerHTML = '
    ❌ Wrong! ' + q.explanation + '
    '; showToast("❌ Wrong!"); } setTimeout(function() { tfIndex++; displayTrueFalseQuestion(document.getElementById('activeGameContainer')); }, 2000); } function showTrueFalseResults(container) { var percentage = Math.round((tfScore / (tfQuestions.length * 10)) * 100); container.innerHTML = '
    ' + (percentage >= 70 ? '🏆' : '📚') + '

    True or False Complete!

    Score: ' + tfScore + '/' + (tfQuestions.length * 10) + '
    ' + percentage + '%
    '; } console.log("✅ Cortexa JS Full Version Loaded Successfully!"); console.log("🔗 API URL:", API_URL); console.log("💡 All endpoints configured for production backend");