class TacticalAlgorithm extends HTMLElement { connectedCallback() { this.attachShadow({ mode: 'open' }); this.shadowRoot.innerHTML = `
TAMP-ALGORITHM v4.2
READY
--
Success
--
Risk Index
CI 95%
--
Est. Casualties
--
Duration (Hrs)
┌─ MULTI-FACTOR RISK ANALYSIS ─┐
TERRAIN
0%
ENEMY
0%
INTEL
0%
WEATHER
0%
LOGISTICS
0%
┌─ TACTICAL RECOMMENDATIONS ─┐
Awaiting tactical parameters for analysis...
`; } analyze(params) { // Null checks for shadow DOM elements if (!this.shadowRoot) { console.error('TacticalAlgorithm: Shadow DOM not initialized'); return null; } const statusEl = this.shadowRoot.getElementById('algo-status'); if (statusEl) { statusEl.textContent = 'ANALYZING'; statusEl.classList.add('analyzing'); } // Use Web Worker if available for non-blocking UI if (window.tampWorkerPool) { window.tampWorkerPool.analyze( params, (percent) => { // Progress callback - update UI if (statusEl) statusEl.textContent = `SIM ${percent}%`; }, (result) => { // Completion callback this.renderAnalysisResults(result); if (window.auditLogger) { window.auditLogger.addLog({ event: 'TAMP_WORKER_COMPLETE', user: 'System', status: 'SUCCESS', details: `Success: ${result.successRate}%, Risk: ${result.riskIndex}` }); } } ); return { status: 'PROCESSING', method: 'WORKER' }; } // Fallback to synchronous calculation for small simulations only return this.analyzeSync(params, statusEl); } analyzeSync(params, statusEl) { const { terrain, enemy, objective, resources } = params; const terrainRiskMatrix = { desert: { risk: 0.65, multiplier: 1.2, weather: 0.8 }, urban: { risk: 0.85, multiplier: 1.5, weather: 0.5 }, forest: { risk: 0.72, multiplier: 1.3, weather: 0.7 }, mountain: { risk: 0.78, multiplier: 1.6, weather: 0.9 }, cyber: { risk: 0.55, multiplier: 0.8, weather: 0.1 }, naval: { risk: 0.70, multiplier: 1.4, weather: 0.95 } }; const enemyThreatMatrix = { terrorist: { risk: 0.62, unpredictable: 0.7, tech_level: 0.4 }, militia: { risk: 0.55, unpredictable: 0.5, tech_level: 0.3 }, state_actor: { risk: 0.88, unpredictable: 0.3, tech_level: 0.9 }, hackers: { risk: 0.58, unpredictable: 0.8, tech_level: 0.85 }, insurgent: { risk: 0.65, unpredictable: 0.6, tech_level: 0.35 } }; const objectiveComplexity = { 'neutraliser le leader': 0.85, 'extraction': 0.75, 'reconnaissance': 0.45, 'sabotage': 0.70, 'defensive': 0.55, 'default': 0.65 }; const resourceStrength = this.parseResourceStrength(resources); const simulations = 1000; // Reduced for sync to prevent UI blocking let successCount = 0; const outcomes = []; // Chunk processing to prevent UI freeze const chunkSize = 100; const chunks = Math.ceil(simulations / chunkSize); const processChunk = (chunkIndex) => { if (chunkIndex >= chunks) { // Finalize results const successRate = (successCount / simulations * 100).toFixed(1); const avgCasualties = outcomes.reduce((sum, o) => sum + o.casualties, 0) / outcomes.length; const avgDuration = outcomes.reduce((sum, o) => sum + o.duration, 0) / outcomes.length; const terrainData = terrainRiskMatrix[terrain] || terrainRiskMatrix.desert; const enemyData = enemyThreatMatrix[enemy] || enemyThreatMatrix.terrorist; const result = { successRate, riskIndex: Math.round((terrainData.risk + enemyData.risk) * 50), casualties: avgCasualties.toFixed(1), duration: avgDuration.toFixed(0), factors: { terrainRisk: Math.round(terrainData.risk * 100), enemyRisk: Math.round(enemyData.risk * 100), intelRisk: Math.round((1 - resourceStrength) * 100), weatherRisk: Math.round(Math.random() * 100), logisticsRisk: Math.round((1 - resourceStrength) * 80) } }; this.renderAnalysisResults(result); return; } // Process chunk for (let i = 0; i < chunkSize && (chunkIndex * chunkSize + i) < simulations; i++) { const terrainVariance = terrainRiskMatrix[terrain].risk + (Math.random() - 0.5) * 0.2; const enemyVariance = enemyThreatMatrix[enemy].risk + (Math.random() - 0.5) * 0.15; const resourceModifier = resourceStrength * 0.25; const complexityPenalty = (objectiveComplexity[objective?.toLowerCase()] || objectiveComplexity.default) * 0.2; const successProbability = 0.5 + (1 - terrainVariance) * 0.25 + (1 - enemyVariance) * 0.3 + resourceModifier - complexityPenalty; const outcome = Math.random() < successProbability ? 1 : 0; successCount += outcome; outcomes.push({ success: outcome, casualties: Math.floor(Math.random() * (outcome ? 3 : 15) + (outcome ? 0 : 2)), duration: Math.floor(Math.random() * 24 + 4) }); } // Update progress if (statusEl) { statusEl.textContent = `SIM ${Math.round((chunkIndex / chunks) * 100)}%`; } // Schedule next chunk setTimeout(() => processChunk(chunkIndex + 1), 0); }; processChunk(0); return { status: 'PROCESSING', method: 'SYNC_CHUNKED' }; } renderAnalysisResults(result) { if (!this.shadowRoot) return; const statusEl = this.shadowRoot.getElementById('algo-status'); if (statusEl) { statusEl.textContent = 'COMPLETE'; statusEl.classList.remove('analyzing'); } // Update success circle const circle = this.shadowRoot.getElementById('success-circle'); if (circle) { const circumference = 2 * Math.PI * 50; const offset = circumference - (parseFloat(result.successRate) / 100) * circumference; circle.style.strokeDashoffset = offset; if (result.successRate >= 70) circle.style.stroke = '#22c55e'; else if (result.successRate >= 50) circle.style.stroke = '#f59e0b'; else circle.style.stroke = '#ef4444'; } const elements = { 'success-rate': result.successRate + '%', 'risk-index': result.riskIndex, 'casualty-proj': result.casualties, 'duration-est': result.duration + 'h' }; Object.entries(elements).forEach(([id, value]) => { const el = this.shadowRoot.getElementById(id); if (el) el.textContent = value; }); // Animate risk bars if (result.factors) { Object.entries(result.factors).forEach(([key, value]) => { const barId = `risk-${key.replace('Risk', '')}`; const valId = `risk-${key.replace('Risk', '')}-val`; this.animateRiskBar(barId, valId, value); }); } // Generate and update recommendations const recommendations = this.generateRecommendations({ terrain: result.terrain, enemy: result.enemy, successRate: result.successRate, overallRiskIndex: result.riskIndex, terrainRisk: result.factors?.terrainRisk, enemyRisk: result.factors?.enemyRisk }); this.updateRecommendations(recommendations); } parseResourceStrength(resources) { // Parse resource string and calculate strength index (0-1) let strength = 0.5; // baseline if (resources) { const lower = resources.toLowerCase(); if (lower.includes('drones')) strength += 0.15; if (lower.includes('hélicoptère') || lower.includes('helicopter')) strength += 0.2; if (lower.includes('sniper')) strength += 0.1; if (lower.includes('tank') || lower.includes('blindé')) strength += 0.25; const numbers = lower.match(/\d+/g); if (numbers) { const troopCount = parseInt(numbers[0]); if (troopCount >= 50) strength += 0.2; else if (troopCount >= 20) strength += 0.1; } } return Math.min(strength, 1); } animateRiskBar(barId, valId, value) { const bar = this.shadowRoot.getElementById(barId); const val = this.shadowRoot.getElementById(valId); // Determine color based on risk level let color = '#22c55e'; // Green if (value >= 70) color = '#ef4444'; // Red else if (value >= 40) color = '#f59e0b'; // Orange setTimeout(() => { bar.style.width = value + '%'; bar.style.backgroundColor = color; val.textContent = value + '%'; }, Math.random() * 300 + 100); } generateRecommendations(analysis) { const recs = []; // Terrain-based recommendations if (analysis.terrainRisk >= 70) { recs.push('CRITICAL: Terrain advantage heavily favors enemy. Consider alternate insertion points.'); } else if (analysis.terrain === 'urban') { recs.push('Deploy drones for building reconnaissance before ground team entry.'); } else if (analysis.terrain === 'forest') { recs.push('Use thermal imaging for enemy detection in dense canopy.'); } else if (analysis.terrain === 'mountain') { recs.push('Acclimatization period required for high-altitude operations.'); } // Enemy-based recommendations if (analysis.enemy === 'state_actor') { recs.push('Expect advanced counter-surveillance. Use encryption level MAXIMUM.'); } else if (analysis.enemy === 'terrorist') { recs.push('Prepare for IEDs and suicide tactics. Maintain minimum safe distance.'); } else if (analysis.enemy === 'hackers') { recs.push('Offline operation mode recommended. EMP countermeasures ready.'); } // Risk-based recommendations if (analysis.overallRiskIndex >= 70) { recs.push('HIGH RISK: Authorization from Command Center required for mission execution.'); } else if (analysis.overallRiskIndex >= 50) { recs.push('MEDIUM RISK: Ensure extraction plan is in place before insertion.'); } // Intel-based recommendations if (analysis.intelRisk >= 60) { recs.push('WARNING: Insufficient intelligence. Recommend 24hr surveillance period.'); } // Success rate recommendations if (parseFloat(analysis.successRate) >= 80) { recs.push('EXCELLENT: Mission parameters optimal. Proceed with confidence.'); } else if (parseFloat(analysis.successRate) < 40) { recs.push('ABORT: Success probability below acceptable threshold. Re-evaluate strategy.'); } return recs.slice(0, 5); } updateRecommendations(recommendations) { const list = this.shadowRoot.getElementById('rec-list'); list.innerHTML = recommendations.map(rec => `
${rec}
`).join(''); } } customElements.define('tactical-algorithm', TacticalAlgorithm);