/* CadetGuide AI Ultimate — v6.1 CLEANED * No Current Affairs, Explain-flow added, defensive fixes */ let cadetGuide = null; class CadetGuideAI { constructor() { this.version = '6.1 CLEANED'; this.currentSubject = 'general'; this.currentClass = '8th'; this.currentBoard = 'PTB'; this.userPreferences = {}; this.conversationHistory = []; this.isTyping = false; this.sessionStartTime = Date.now(); this.messageCount = 0; // explain flow state this.lastExplainTarget = null; // stores last assistant message when user said "explain this" // Storage Keys this.storageKeys = { chatHistory: 'cadetguide_chat_history', userPrefs: 'cadetguide_user_prefs', progress: 'cadetguide_progress', achievements: 'cadetguide_achievements' }; // Subject Engine Registry (detect → solve → suggestions) this.engines = this.buildEngines(); // Periodic table (short) for chemistry MW demo this.periodic = this.loadPeriodicTable(); // Initialize this.initializeApp(); this.loadLocalData(); this.setupEventListeners(); this.displayWelcomeMessage(); } /* ------------------------- Initialization & DOM ------------------------- */ initializeApp() { this.elements = { chatMessages: document.getElementById('chatMessages'), messageInput: document.getElementById('messageInput'), sendButton: document.getElementById('sendButton'), chatForm: document.getElementById('chatForm'), typingIndicator: document.getElementById('typingIndicator'), welcomeScreen: document.getElementById('welcomeScreen'), subjectCards: document.querySelectorAll('.subject-card'), navToggle: document.getElementById('navToggle'), navLinks: document.getElementById('navLinks') }; this.initializeNavigation(); console.log('✅ CadetGuide AI v6.1 Ready'); } initializeNavigation() { const { navToggle, navLinks } = this.elements; if (navToggle && navLinks) { navToggle.addEventListener('click', () => navLinks.classList.toggle('nav-active')); } document.querySelectorAll('.dropdown-toggle').forEach(toggle => { toggle.addEventListener('click', (e) => { if (window.innerWidth <= 768) { e.preventDefault(); toggle.parentElement?.classList.toggle('mobile-open'); } }); }); } setupEventListeners() { const { chatForm, messageInput, sendButton, chatMessages } = this.elements; if (chatForm) { chatForm.addEventListener('submit', (e) => { e.preventDefault(); this.sendMessage(); }); } if (messageInput) { messageInput.addEventListener('input', () => { this.autoResizeTextarea(); this.updateSendButtonState(); }); messageInput.addEventListener('keydown', (e) => { if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); this.sendMessage(); } }); } // Delegated click handling for suggestion chips (no inline JS) if (chatMessages) { chatMessages.addEventListener('click', (e) => { const chip = e.target.closest('.suggestion-chip'); if (chip && chip.dataset.msg) { this.sendMessage(chip.dataset.msg); } }); } // Subject cards if (this.elements.subjectCards && this.elements.subjectCards.forEach) { this.elements.subjectCards.forEach(card => { card.addEventListener('click', () => { const subject = card.dataset.subject; if (subject) this.selectSubject(subject); }); }); } } /* ------------------------------ Data Load/Save ------------------------------ */ loadLocalData() { try { const history = localStorage.getItem(this.storageKeys.chatHistory); if (history) { this.conversationHistory = JSON.parse(history); this.displayConversationHistory(); } const prefs = localStorage.getItem(this.storageKeys.userPrefs); if (prefs) { this.userPreferences = JSON.parse(prefs); } } catch (err) { console.error('Load error:', err); } } saveLocalData() { try { localStorage.setItem(this.storageKeys.chatHistory, JSON.stringify(this.conversationHistory.slice(-100))); localStorage.setItem(this.storageKeys.userPrefs, JSON.stringify(this.userPreferences)); } catch (err) { console.error('Save error:', err); } } /* ------------------------------ Welcome & UI ------------------------------ */ displayWelcomeMessage() { const welcomeMessage = { role: 'assistant', content: `🌟 **Welcome to CadetGuide AI v6.1!**\n\nI'm your advanced tutor across **Math, Physics, Chemistry, Statistics, English, Urdu**, **Islamiyat**, and **Pakistan Studies**.\n\n**What I can do:**\n• 🔢 Solve equations (algebra → calculus)\n• ⚛️ Physics numericals (units & conversions)\n• 🧪 Balance reactions & stoichiometry\n• 📊 Statistics (mean → hypothesis basics)\n• ✍️ English rules, tenses, grammar tips, synonyms\n• 🇵🇰 اردو تشریح / اسلامیات / مطالعہ پاکستان\n\nAsk me anything — I’ll show steps, tips, and methods.`, timestamp: Date.now(), suggestions: [ 'Solve: 2x + 5 = 17', 'Find roots: x^2 - 5x + 6 = 0', 'Physics: mass 10 kg, a 3 m/s^2', 'Chemistry: Balance H2 + O2 → H2O', 'Statistics: mean of 5,7,9,12', 'English: present perfect rules', 'Urdu: غزل کی تشریح', 'Islamiyat: ارکانِ اسلام', 'Pakistan Studies: 1940 Resolution summary' ] }; this.addMessage(welcomeMessage); } getSubjectSuggestions(subject) { const s = { mathematics: ['Quadratic equation', 'Derivative d/dx x^3', 'Integrate sin x', 'Matrix inverse'], physics: ['Calculate F=ma', 'Kinematics v^2 = u^2 + 2as', 'Energy KE = 1/2 mv^2', 'Ohm\u2019s law V=IR'], chemistry: ['Balance equation', 'Molarity example', 'pH of 0.01M HCl', 'Limiting reagent'], statistics: ['Mean/median/mode', 'Variance & std dev', 'Combinations C(n,r)', 'Basic probability'], english: ['All 12 tenses', 'Active vs passive', 'Common articles rules', 'Synonyms for \u201Cimportant\u201D'], urdu: ['نظم کی تشریح', 'محاورات مثال', 'انشا کے اصول', 'الفاظ کے معانی'], islamiyat: ['ارکانِ ایمان', 'نماز کے فرائض', 'زکوٰۃ کے احکام', 'سیرتِ نبوی ﷺ خلاصہ'], pakistan_studies: ['1947–1956 timeline', 'قائدِاعظم تقاریر نکتے', 'آئین 1973 خلاصہ', 'جغرافیہ پاکستان'], general: ['Choose subject', 'Study tips', 'PTB class selection', 'Practice'] }; return s[subject] || s.general; } /* ------------------------------ Messaging Core ------------------------------ */ async sendMessage(text = null) { const msg = (typeof text === 'string' ? text : this.elements.messageInput?.value?.trim()) ?? ''; if (!msg) return; // If input came from UI clear it if (this.elements.messageInput && typeof text !== 'string') { this.elements.messageInput.value = ''; this.updateSendButtonState(); } this.addMessage({ role: 'user', content: msg, timestamp: Date.now() }); this.showTypingIndicator(); try { const response = await this.processMessage(msg); this.hideTypingIndicator(); this.addMessage({ role: 'assistant', content: response.message, timestamp: Date.now(), suggestions: response.suggestions }); this.saveLocalData(); } catch (err) { console.error('Processing error:', err); this.hideTypingIndicator(); this.addMessage({ role: 'assistant', content: 'I hit a snag while solving that, but I\'m here. Try rephrasing or give specific numbers.', timestamp: Date.now(), suggestions: ['Try again', 'Math example', 'Physics example', 'Chemistry example'] }); } } async processMessage(message) { // HANDLE the explain flow: if user says "explain this" or "explain that" capture last assistant msg const lower = message.toLowerCase().trim(); if (/^explain\b|\bexplain\s+this|\bexplain\s+that/i.test(lower)) { const lastAssistant = [...this.conversationHistory].reverse().find(m => m.role === 'assistant'); if (lastAssistant && lastAssistant.content) { this.lastExplainTarget = lastAssistant.content; return { message: 'Sure — I will explain the last answer. Now send a follow-up prompt (e.g., "explain this in simpler terms", or ask a related question).', suggestions: ['Explain in simpler terms', 'Give examples', 'Show steps'] }; } else { return { message: 'There is no previous assistant explanation to expand. Ask a question first or provide a passage to explain.', suggestions: ['Ask a question', 'Provide text to explain'] }; } } if (this.lastExplainTarget) { const relatedScore = this.computeRelatedness(this.lastExplainTarget, message); if (relatedScore >= 0.15) { const explanation = this.generateExplanation(this.lastExplainTarget, message, relatedScore); this.lastExplainTarget = null; return { message: explanation, suggestions: ['More detail', 'Simpler', 'Examples'] }; } else { this.lastExplainTarget = null; const normalResp = await this.routeToEngines(message); normalResp.message = `I checked your follow-up and it doesn't seem related to the last explanation. Responding normally:\n\n${normalResp.message}`; return normalResp; } } return this.routeToEngines(message); } async routeToEngines(message) { for (const key of Object.keys(this.engines)) { const engine = this.engines[key]; try { if (engine.detect(message)) { const result = await engine.solve(message); return this.enhanceResponse(result); } } catch (err) { console.error('Engine error for', key, err); } } return this.enhanceResponse(this.genericHelp(message)); } enhanceResponse(resp) { if (!resp?.message) return resp || { message: 'Sorry, I could not process that.' }; const wc = resp.message.split(/\s+/).length; if (wc < 180) { resp.message += `\n\n**Study Tips:**\n• Practice 3 similar problems\n• Summarize the method in your own words\n• Teach it to a friend\n• Revisit key formulas daily`; } return resp; } genericHelp(message) { return { message: `🎓 **Comprehensive Academic Assistance**\n\nYou asked: \"${this.safeTrim(message, 120)}\"\n\nI support: **Math, Physics, Chemistry, Statistics, English, Urdu, Islamiyat, Pakistan Studies**. Ask a specific problem to see step-by-step working.`, suggestions: ['Pick a subject', 'Give a numeric problem', 'Ask grammar rule', 'Balance an equation'] }; } /* ------------------------------ Engines ------------------------------ */ buildEngines() { const self = this; const MATH = { detect: (m) => /(solve|calculate|integral|derivative|equation|matrix|\^|=|\bx\b|polynomial)/i.test(m), solve: (m) => self.solveMath(m) }; const PHYSICS = { detect: (m) => /(force|mass|acceleration|velocity|energy|kinetic|potential|newton|joule|watt|pressure|v\s*=\s*u\s*\+\s*at|f\s*=\s*ma)/i.test(m), solve: (m) => self.solvePhysics(m) }; const CHEMISTRY = { detect: (m) => /(balance|equation|mol\b|molar|ph\b|acid|base|reaction|→|->|molecular\s+weight)/i.test(m), solve: (m) => self.solveChemistry(m) }; const STATISTICS = { detect: (m) => /(mean|median|mode|variance|standard\s*deviation|std\b|probability|permutation|combination|binomial|normal)/i.test(m), solve: (m) => self.solveStatistics(m) }; const ENGLISH = { detect: (m) => /(english|tense|grammar|article|preposition|passive|active|synonym|writing|improve english)/i.test(m), solve: (m) => self.helpEnglish(m) }; const URDU = { detect: (m) => /(اردو|تشریح|غزل|نثر|محاورہ|الفاظ|معانی)/i.test(m), solve: (m) => self.helpUrdu(m) }; const ISLAMIYAT = { detect: (m) => /(اسلامیات|ارکان|نماز|روزہ|زکوٰ?ۃ|سیرت)/i.test(m), solve: (m) => self.helpIslamiyat(m) }; const PAK_STUDIES = { detect: (m) => /(مطالعہ\s*پاکستان|pakistan\s*studies|1940|1947|1973|قائد|تحریک)/i.test(m), solve: (m) => self.helpPakistanStudies(m) }; const PTB = { detect: (m) => /(ptb|chapter|exercise|class|grade|9th|10th|11th|12th|matric|inter)/i.test(m), solve: (m) => self.handlePTB(m) }; return { mathematics: MATH, physics: PHYSICS, chemistry: CHEMISTRY, statistics: STATISTICS, english: ENGLISH, urdu: URDU, islamiyat: ISLAMIYAT, pakistan_studies: PAK_STUDIES, ptb: PTB, general: { detect: () => true, solve: (m) => self.genericHelp(m) } }; } /* ------------------------------ Math ------------------------------ */ solveMath(message) { const m = message.toLowerCase(); // Quadratic ax^2 + bx + c = 0 (basic parser, still fragile for complex formats) const quad = message.match(/(-?\d*\.?\d+)\s*x\s*(?:\^|[²])\s*2?\s*([+\-]\s*\d*\.?\d*)\s*x\s*([+\-]\s*\d*\.?\d*)\s*=\s*0/); if (quad) { const a = parseFloat(quad[1] || '1'); const b = parseFloat(quad[2].replace(/\s/g, '') || '0'); const c = parseFloat(quad[3].replace(/\s/g, '') || '0'); const D = b*b - 4*a*c; if (D > 0) { const x1 = (-b + Math.sqrt(D)) / (2*a); const x2 = (-b - Math.sqrt(D)) / (2*a); return { message: `🔢 **Quadratic Solution**\n\nEquation: ${a}x² ${b>=0?'+':''}${b}x ${c>=0?'+':''}${c} = 0\nΔ = ${D}\nRoots: x₁ = ${x1.toFixed(4)}, x₂ = ${x2.toFixed(4)}\nVertex: (${(-b/(2*a)).toFixed(2)}, ${((4*a*c - b*b)/(4*a)).toFixed(2)})`, suggestions: ['Graph this', 'Complete the square', 'Factorization method', 'Another quadratic'] }; } else if (D === 0) { const x = -b / (2*a); return { message: `Root (double): x = ${x.toFixed(4)} (Δ=0)`, suggestions: ['Graph', 'Discriminant meaning', 'Another equation'] }; } else { const rp = (-b/(2*a)).toFixed(4), ip = (Math.sqrt(-D)/(2*a)).toFixed(4); return { message: `Complex roots: ${rp} ± ${ip}i (Δ<0)`, suggestions: ['Explain complex roots', 'Another quadratic'] }; } } // Linear ax + b = c const lin = message.match(/(-?\d*\.?\d*)\s*x\s*([+\-]\s*\d+\.?\d*)?\s*=\s*(-?\d+\.?\d*)/i); if (lin) { const a = parseFloat(lin[1] || '1'); const b = parseFloat((lin[2] || '0').replace(/\s/g, '')); const c = parseFloat(lin[3]); if (a === 0) return { message: 'Coefficient a is 0 — not a valid linear equation in x (division by zero).' }; const x = (c - b)/a; return { message: `🔢 **Linear Equation**\n\n${a}x ${b>=0?'+':''}${b} = ${c}\n⇒ x = (${c} - ${b})/${a} = ${x.toFixed(4)}`, suggestions: ['Graph line', 'Parallel/perpendicular lines', 'Solve another'] }; } // Basic arithmetic a op b const ar = message.match(/(\d+(?:\.\d+)?)\s*([+\-*\/^])\s*(\d+(?:\.\d+)?)/); if (ar) { const a = parseFloat(ar[1]); const op = ar[2]; const b = parseFloat(ar[3]); let res = NaN; let name=''; let step=''; switch(op){ case '+': res=a+b; name='Addition'; step=`${a}+${b}=${res}`; break; case '-': res=a-b; name='Subtraction'; step=`${a}-${b}=${res}`; break; case '*': res=a*b; name='Multiplication'; step=`${a}×${b}=${res}`; break; case '/': res=b!==0?a/b:NaN; name='Division'; step=b!==0?`${a}÷${b}=${res}`:'Division by zero'; break; case '^': res=Math.pow(a,b); name='Exponentiation'; step=`${a}^${b}=${res}`; break; } const sci = Number.isFinite(res)?Number(res).toExponential(4):'—'; const r2 = Number.isFinite(res)?res.toFixed(2):'—'; return { message: `🔢 **${name}**\n${step}\nScientific: ${sci}\nRounded(2): ${r2}`, suggestions: ['More calculations', 'Fractions', 'Percentages'] }; } // Derivative stub if (/derivative|d\s*\/\s*dx|differentiate/i.test(m)) { return { message: '✏️ **Derivative Helper**\nCurrently supports basic polynomials. Example: d/dx (ax^n) = a·n·x^(n-1). Provide a specific function like: derivative of 3x^3 - 5x + 7.', suggestions: ['Derivative of x^3', 'Product rule', 'Chain rule'] }; } // Integral stub if (/integral|∫/i.test(m)) { return { message: '∫ **Integral Helper**\nBasic rules: ∫ax^n dx = a·x^(n+1)/(n+1) + C (n≠-1). Give a function to integrate, e.g., ∫(2x + 3) dx.', suggestions: ['Integrate x^2', 'u-substitution', 'Integration by parts'] }; } return { message: 'Math detected. Please provide a specific equation or numbers.', suggestions: ['Solve 2x+5=17', 'Find roots x^2-5x+6=0', 'Derivative d/dx x^3'] }; } /* ------------------------------ Physics ------------------------------ */ solvePhysics(message) { // Extract numbers with simple patterns const mass = this.extractUnit(message, /(\d*\.?\d+)\s*(kg|g|mg)/i); const accel = this.extractUnit(message, /(\d*\.?\d+)\s*(m\/s2|m\/s²)/i); const forceMatch = message.match(/(\d+(?:\.\d+)?)\s*(N|newton)/i); if (mass && accel) { let massVal = parseFloat(mass.value); let accelVal = parseFloat(accel.value); // Convert units if needed if (mass.unit.toLowerCase() === 'g') massVal /= 1000; if (mass.unit.toLowerCase() === 'mg') massVal /= 1000000; const force = massVal * accelVal; return { message: `⚛️ **Newton's Second Law Calculation**\n\n**Given:**\n• Mass (m) = ${mass.value} ${mass.unit} = ${massVal} kg\n• Acceleration (a) = ${accelVal} m/s²\n\n**Formula:** F = ma\n\n**Solution:**\nF = ${massVal} kg × ${accelVal} m/s²\nF = ${force} kg⋅m/s²\nF = ${force} N (Newtons)\n\n**Unit Analysis:**\n• kg × m/s² = kg⋅m/s² = N (Newton)\n• 1 Newton = force needed to accelerate 1 kg at 1 m/s²\n\n**Additional Conversions:**\n• Force in kN: ${(force/1000).toFixed(4)} kN\n• Force in dynes: ${(force * 100000).toExponential(2)} dynes\n• Force in pound-force: ${(force * 0.224809).toFixed(4)} lbf\n\n**Physical Meaning:**\nA ${massVal} kg object accelerating at ${accelVal} m/s² experiences a net force of ${force} N.`, subject: 'physics', suggestions: [ 'Calculate weight (W=mg)', 'Find acceleration', 'Momentum (p=mv)', 'Work done (W=Fd)', 'Power calculation' ] }; } return this.getPhysicsHelp(); } toKg(val, unit){ let v=parseFloat(val); if(/mg/i.test(unit)) return v/1e6; if(/g/i.test(unit)) return v/1000; return v; } extractUnit(text, unitRegex){ const n=text.match(unitRegex); if(!n) return null; return { value:n[1], unit:n[2] }; } extractNumber(text, re){ const m=text.match(re); return m?parseFloat(m[1]):null; } /* ------------------------------ Chemistry ------------------------------ */ solveChemistry(message) { if (/H2/i.test(message) && /O2/i.test(message) && /H2O/i.test(message)) { return { message: `🧪 **Balancing Chemical Equation**\n\n**Unbalanced Equation:** H₂ + O₂ → H₂O\n\n**Step 1:** Count atoms on each side\n• Reactants: H = 2, O = 2\n• Products: H = 2, O = 1\n\n**Step 2:** Balance oxygen atoms\nMultiply H₂O by 2:\nH₂ + O₂ → 2H₂O\n\n**Step 3:** Recount atoms\n• Reactants: H = 2, O = 2\n• Products: H = 4, O = 2\n\n**Step 4:** Balance hydrogen atoms\nMultiply H₂ by 2:\n2H₂ + O₂ → 2H₂O\n\n**Final Check:**\n• Reactants: H = 4, O = 2 ✓\n• Products: H = 4, O = 2 ✓\n\n**Balanced Equation:** 2H₂ + O₂ → 2H₂O\n\n**Meaning:** 2 molecules of hydrogen gas react with 1 molecule of oxygen gas to produce 2 molecules of water.`, subject: 'chemistry', suggestions: [ 'Balance another equation', 'Limiting reagent', 'Percent yield', 'Redox reactions', 'Types of reactions' ] }; } if (/molecular\s+(weight|mass)/i.test(message)) { return { message: '🔬 **Molar Mass Helper**\nWrite the formula like C6H12O6 and I\'ll approximate using a short periodic table sample in code. (Extend the periodic data for full accuracy.)', suggestions: ['Molar mass of H2O', 'Molar mass of CO2'] }; } if (/\bph\b/i.test(message)) { return { message: '🧪 **pH Basics**\npH = -log10[H⁺]. Give concentration, e.g., [H⁺]=1e-3 ⇒ pH=3.', suggestions: ['pH examples', 'Buffer concept', 'Weak acid pKa relation'] }; } return this.getChemistryHelp(); } loadPeriodicTable() { return { H: { name: 'Hydrogen', atomicNumber: 1, atomicWeight: 1.008 }, He: { name: 'Helium', atomicNumber: 2, atomicWeight: 4.0026 }, Li: { name: 'Lithium', atomicNumber: 3, atomicWeight: 6.94 }, Be: { name: 'Beryllium', atomicNumber: 4, atomicWeight: 9.012 }, B: { name: 'Boron', atomicNumber: 5, atomicWeight: 10.81 }, C: { name: 'Carbon', atomicNumber: 6, atomicWeight: 12.011 }, N: { name: 'Nitrogen', atomicNumber: 7, atomicWeight: 14.007 }, O: { name: 'Oxygen', atomicNumber: 8, atomicWeight: 15.999 }, Na: { name: 'Sodium', atomicNumber: 11, atomicWeight: 22.989 }, Mg: { name: 'Magnesium', atomicNumber: 12, atomicWeight: 24.305 }, Al: { name: 'Aluminum', atomicNumber: 13, atomicWeight: 26.982 }, Si: { name: 'Silicon', atomicNumber: 14, atomicWeight: 28.085 }, P: { name: 'Phosphorus', atomicNumber: 15, atomicWeight: 30.974 }, S: { name: 'Sulfur', atomicNumber: 16, atomicWeight: 32.06 }, Cl: { name: 'Chlorine', atomicNumber: 17, atomicWeight: 35.45 }, K: { name: 'Potassium', atomicNumber: 19, atomicWeight: 39.098 }, Ca: { name: 'Calcium', atomicNumber: 20, atomicWeight: 40.078 } }; } /* ------------------------------ Statistics ------------------------------ */ solveStatistics(message) { const nums = (message.match(/(-?\d+(?:\.\d+)?)/g) || []).map(Number); if (/(mean|average)/i.test(message) && nums.length) { const mean = nums.reduce((a, b) => a + b, 0) / nums.length; return { message: `📊 **Mean** of [${nums.join(', ')}] = ${mean}`, suggestions: ['Median', 'Mode', 'Variance & std dev'] }; } if (/median/i.test(message) && nums.length) { const arr = [...nums].sort((a, b) => a - b); const n = arr.length; const med = n % 2 ? arr[(n - 1) / 2] : (arr[n / 2 - 1] + arr[n / 2]) / 2; return { message: `📊 **Median** of [${nums.join(', ')}] = ${med}`, suggestions: ['Mean', 'Mode', 'Quartiles'] }; } if (/mode/i.test(message) && nums.length) { const freq = {}; nums.forEach(x => freq[x] = (freq[x] || 0) + 1); const max = Math.max(...Object.values(freq)); const modes = Object.keys(freq).filter(k => freq[k] === max); return { message: `📊 **Mode**: ${modes.join(', ')} (freq=${max})`, suggestions: ['Mean', 'Variance'] }; } if (/variance|std|standard\s*deviation/i.test(message) && nums.length) { const mean = nums.reduce((a, b) => a + b, 0) / nums.length; const varc = nums.reduce((s, x) => s + (x - mean) ** 2, 0) / nums.length; const std = Math.sqrt(varc); return { message: `📊 **Variance/Std**\nMean=${mean.toFixed(4)}\nVariance=${varc.toFixed(4)}\nStd Dev=${std.toFixed(4)}`, suggestions: ['Sample variance', 'Z-score', 'Normal distribution'] }; } if (/combination|c\(n\s*,?\s*r\)|\bC\(.*\)/i.test(message)) { return { message: 'Combinations C(n,r) = n!/(r!(n−r)!). Give n and r.', suggestions: ['Example: C(10,3)', 'Permutations P(n,r)'] }; } if (/permutation|P\(n\s*,?\s*r\)/i.test(message)) { return { message: 'Permutations P(n,r) = n!/(n−r)!. Give n and r.', suggestions: ['Example: P(10,3)', 'Combinations next'] }; } if (/probability/i.test(message)) { return { message: 'Probability basics: P(A) = favorable / total. Add more details for exact computation.', suggestions: ['Binomial example', 'Conditional probability'] }; } return { message: 'Statistics detected. Ask for mean/median/mode/variance with numbers.', suggestions: ['Mean of 3,5,7,9', 'Variance of 2,4,4,4,5,5,7,9'] }; } /* ------------------------------ English ------------------------------ */ helpEnglish(message) { if (/tense|tenses/i.test(message)) { return { message: `✍️ **12 English Tenses (Quick Map)**\nSimple/Continuous/Perfect/Perfect Continuous × Past/Present/Future with examples.\nE.g., Present Perfect: "I have eaten." Use for actions at unspecified time with present relevance.`, suggestions: ['Active vs Passive', 'Articles A/An/The', 'Prepositions tips'] }; } if (/synonym|synonyms/i.test(message)) { const word = (message.match(/synonyms?\s+for\s+([a-z]+)/i) || [])[1] || 'important'; const dict = { important: ['crucial', 'vital', 'significant', 'essential', 'notable'], good: ['excellent', 'great', 'favorable', 'beneficial', 'sound'] }; const list = dict[word] || dict['important']; return { message: `🔤 **Synonyms for "${word}"**: ${list.join(', ')}`, suggestions: ['Antonyms', 'Use in a sentence'] }; } if (/grammar|improve|rules|article|preposition|passive|active/i.test(message)) { return { message: `📘 **Quick Grammar Tips**\n• Articles: Use *a* before consonant sounds, *an* before vowel sounds, *the* for specifics.\n• Prepositions: "interested in", not *interested on*.\n• Active→Passive: "The team completed the task" → "The task was completed by the team."\n• Writing: Keep sentences clear; prefer strong verbs; avoid fillers.`, suggestions: ['Common errors list', 'Punctuation rules', 'Writing checklist'] }; } return { message: 'English helper ready. Ask about tenses, grammar rules, or synonyms.', suggestions: ['All 12 tenses', 'Synonyms for important', 'Active vs Passive'] }; } /* ------------------------------ Urdu / Islamiyat / Pak Studies ------------------------------ */ helpUrdu(message) { return { message: `🇵🇰 **اردو تشریح**\nمتن پیش کریں — میں الفاظ کے معانی، مرکزی خیال، شاعر/مصنف کا مقصد، اور اسلوب کی وضاحت کے نکات دے دوں گا۔\n**سانچہ:**\n1) مرکزی خیال\n2) تشبیہ و استعارہ\n3) اسلوب و الفاظ\n4) خلاصہ`, suggestions: ['غزل کے اشعار دیں', 'نثر کا اقتباس دیں', 'محاورات کی فہرست'] }; } helpIslamiyat(message) { return { message: `🕋 **اسلامیات خلاصہ**\n• ارکانِ اسلام: شہادت، نماز، روزہ، زکوٰۃ، حج\n• ارکانِ ایمان: ایمان باللہ، ملائکہ، کتب، رسل، آخرت، تقدیر\nسوال پوچھیں میں مختصر دلائل و مثالیں دے دوں گا۔`, suggestions: ['نماز کے فرائض', 'زکوٰۃ کے نصاب'] }; } helpPakistanStudies(message) { return { message: `📚 **مطالعہ پاکستان**\n• قراردادِ لاہور 1940: علیحدہ ریاست کا واضح مطالبہ\n• آزادی 1947: تقسیمِ ہند، مہاجرین کے مسائل\n• آئین 1973: پارلیمانی نظام، بنیادی حقوق\nتفصیل چاہیں تو مخصوص موضوع لکھیں۔`, suggestions: ['1940 کی قرارداد نکات', '1973 کے آئین کے بنیادی حقوق'] }; } /* ------------------------------ PTB Handling ------------------------------ */ handlePTB(message) { const classes = ['Class 1','Class 2','Class 3','Class 4','Class 5','Class 6','Class 7','Class 8','9th','10th','11th','12th']; return { message: `📚 **PTB Curriculum**\nBoard: ${this.currentBoard}\nAvailable Classes: ${classes.join(', ')}\nلکھیں: "9th Math Chapter 1 Exercise 1.1" اور میں رہنمائی کروں گا۔`, suggestions: ['Select 9th', 'Select 10th', 'Math Ch 1', 'Physics Numericals'] }; } /* ------------------------------ Explain Flow Helpers ------------------------------ */ computeRelatedness(textA, textB) { if (!textA || !textB) return 0; const tokenize = s => s.toLowerCase().replace(/[^\w\s]/g, ' ').split(/\s+/).filter(Boolean); const a = tokenize(textA); const b = tokenize(textB); const setA = new Set(a); const common = b.filter(x => setA.has(x)); const ratio = common.length / Math.max(b.length, 1); const lengthFactor = Math.min(1, b.length / 3); return ratio * lengthFactor; } generateExplanation(targetText, followUpPrompt, score) { let base = `🔍 **Explanation (based on previous answer)**\n\n${targetText}\n\n`; base += `**Context from your follow-up:** ${followUpPrompt}\n\n`; base += `**Tailored Explanation:**\n`; if (/simple|simpler|easy|basic|explain like/i.test(followUpPrompt)) { base += 'Here it is in simpler terms: ' + this.summarizePlain(targetText); } else if (/step|steps|show steps|working/i.test(followUpPrompt)) { base += 'Here are the steps to reach that result: ' + this.unrollSteps(targetText); } else { base += this.summarizePlain(targetText) + '\n\nIf you want a different style (step-by-step, simpler, or examples), say so.'; } return base; } summarizePlain(text) { const clean = text.replace(/\n+/g, ' ').replace(/\*\*/g, ''); if (clean.length < 220) return clean; return clean.slice(0, 220) + '... (shortened)'; } unrollSteps(text) { const lines = text.split(/\n+/).map(l => l.trim()).filter(Boolean); if (lines.length <= 1) { const clauses = text.match(/[^.?!]+[.?!]?/g) || [text]; return clauses.slice(0,5).map((c,i)=>`${i+1}. ${c.trim()}`).join('\n'); } return lines.map((l,i)=>`${i+1}. ${l}`).join('\n'); } /* ------------------------------ UI Helpers ------------------------------ */ addMessage(messageData) { this.conversationHistory.push(messageData); this.displayMessage(messageData); this.scrollToBottom(); } displayMessage(messageData) { if (!this.elements.chatMessages) return; const messageDiv = document.createElement('div'); messageDiv.className = `message ${messageData.role}`; const time = new Date(messageData.timestamp).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }); const avatarIcon = messageData.role === 'user' ? 'fa-user' : 'fa-robot'; const avatarClass = messageData.role === 'user' ? 'user' : 'ai'; let suggestionsHtml = ''; if (messageData.suggestions?.length) { const chips = messageData.suggestions.map(s => `${this.escapeHTML(s)}`).join(''); suggestionsHtml = `
${chips}
`; } const safeContent = this.formatMessage(messageData.content); messageDiv.innerHTML = `
${safeContent}
${time}
${suggestionsHtml}
`; this.elements.chatMessages.appendChild(messageDiv); } formatMessage(text) { const esc = this.escapeHTML(String(text ?? '')); return esc .replace(/\*\*(.*?)\*\*/g, '$1') .replace(/\*(.*?)\*/g, '$1') .replace(/\n/g, '
') .replace(/•/g, '• '); } escapeHTML(s) { return String(s).replace(/[&<>"']/g, c => ({ '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' }[c])); } escapeAttr(s) { return String(s).replace(/["]|[']|\\/g, m => (m === '"' ? '"' : m === '\'' ? ''' : '\\')); } safeTrim(s, n) { s = String(s); return s.length > n ? s.slice(0, n - 1) + '…' : s; } displayConversationHistory() { if (!this.elements.chatMessages) return; this.elements.chatMessages.innerHTML = ''; this.conversationHistory.forEach(m => this.displayMessage(m)); this.hideWelcomeScreen(); this.scrollToBottom(); } selectSubject(subject) { this.currentSubject = subject; if (this.elements.subjectCards && this.elements.subjectCards.forEach) this.elements.subjectCards.forEach(c => c.classList.remove('active')); document.querySelector(`[data-subject="${subject}"]`)?.classList.add('active'); const map = { mathematics: '🔢 Mathematics', physics: '⚛️ Physics', chemistry: '🧪 Chemistry', statistics: '📊 Statistics', english: '✍️ English', urdu: '🇵🇰 Urdu', islamiyat: '🕋 Islamiyat', pakistan_studies: '📚 Pakistan Studies', general: '🎓 General' }; this.addMessage({ role: 'assistant', content: `**${map[subject] || 'Subject selected'}**\n\nI\'m ready to help you with ${subject}. What would you like to learn?`, timestamp: Date.now(), suggestions: this.getSubjectSuggestions(subject) }); } quickStart(message) { if (this.elements.messageInput) this.elements.messageInput.value = message; this.sendMessage(message); } showTypingIndicator() { this.elements.typingIndicator?.classList.add('show'); this.scrollToBottom(); } hideTypingIndicator() { this.elements.typingIndicator?.classList.remove('show'); } hideWelcomeScreen() { this.elements.welcomeScreen && (this.elements.welcomeScreen.style.display = 'none'); } autoResizeTextarea() { const t = this.elements.messageInput; if (!t) return; t.style.height = 'auto'; t.style.height = Math.min(t.scrollHeight, 120) + 'px'; } updateSendButtonState() { const { sendButton, messageInput } = this.elements; if (!sendButton || !messageInput) return; sendButton.disabled = messageInput.value.trim().length === 0; } scrollToBottom() { const c = this.elements.chatMessages; if (!c) return; setTimeout(() => { c.scrollTop = c.scrollHeight; }, 80); } /* ------------------------------ Utilities & Actions ------------------------------ */ clearChat() { if (confirm('Clear all messages?')) { this.conversationHistory = []; if (this.elements.chatMessages) this.elements.chatMessages.innerHTML = ''; localStorage.removeItem(this.storageKeys.chatHistory); this.displayWelcomeMessage(); } } shareChat() { const text = this.conversationHistory.map(msg => `${msg.role === 'user' ? 'You' : 'AI'}: ${msg.content}`).join('\n\n'); if (navigator.share) navigator.share({ title: 'CadetGuide Chat', text }); else { navigator.clipboard.writeText(text); alert('Conversation copied!'); } } exportChat() { const text = this.conversationHistory.map(msg => `[${new Date(msg.timestamp).toLocaleString()}] ${msg.role === 'user' ? 'You' : 'AI'}: ${msg.content}`).join('\n\n'); const blob = new Blob([text], { type: 'text/plain' }); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = `cadetguide-chat-${Date.now()}.txt`; a.click(); URL.revokeObjectURL(url); } } // Global helpers for HTML buttons (no inline onclick in suggestions) function selectSubject(subject) { cadetGuide?.selectSubject(subject); } function quickStart(message) { cadetGuide?.quickStart(message); } function clearChat() { cadetGuide?.clearChat(); } function shareChat() { cadetGuide?.shareChat(); } function exportChat() { cadetGuide?.exportChat(); } function toggleTheme() { document.body.setAttribute('data-theme', document.body.getAttribute('data-theme') === 'dark' ? 'light' : 'dark'); } // DOM Ready document.addEventListener('DOMContentLoaded', () => { console.log('🚀 Initializing CadetGuide AI v6.1…'); cadetGuide = new CadetGuideAI(); console.log('✅ CadetGuide AI v6.1 Ready!'); });