// ======================================== // FICHIER: HumanSimulationCore.js // RESPONSABILITÉ: Orchestrateur principal Human Simulation // Niveau 5: Temporal & Personality Injection // ======================================== const { logSh } = require('../ErrorReporting'); const { tracer } = require('../trace'); const { calculateFatigue, injectFatigueMarkers, getFatigueProfile } = require('./FatiguePatterns'); const { injectPersonalityErrors, getPersonalityErrorPatterns } = require('./PersonalityErrors'); const { applyTemporalStyle, getTemporalStyle } = require('./TemporalStyles'); const { analyzeContentComplexity, calculateReadabilityScore, preserveKeywords, validateSimulationQuality } = require('./HumanSimulationUtils'); /** * CONFIGURATION PAR DÉFAUT */ const DEFAULT_CONFIG = { fatigueEnabled: true, personalityErrorsEnabled: true, temporalStyleEnabled: true, imperfectionIntensity: 0.8, // FIXÉ: Plus d'intensité (était 0.3) naturalRepetitions: true, qualityThreshold: 0.4, // FIXÉ: Seuil plus bas (était 0.7) maxModificationsPerElement: 5 // FIXÉ: Plus de modifs possibles (était 3) }; /** * ORCHESTRATEUR PRINCIPAL - Human Simulation Layer * @param {object} content - Contenu généré à simuler * @param {object} options - Options de simulation * @returns {object} - { content, stats, fallback } */ async function applyHumanSimulationLayer(content, options = {}) { return await tracer.run('HumanSimulationCore.applyHumanSimulationLayer()', async () => { const startTime = Date.now(); await tracer.annotate({ contentKeys: Object.keys(content).length, elementIndex: options.elementIndex, totalElements: options.totalElements, currentHour: options.currentHour, personality: options.csvData?.personality?.nom }); logSh(`🧠 HUMAN SIMULATION - Début traitement`, 'INFO'); logSh(` 📊 ${Object.keys(content).length} éléments | Position: ${options.elementIndex}/${options.totalElements}`, 'DEBUG'); try { // Configuration fusionnée const config = { ...DEFAULT_CONFIG, ...options }; // Stats de simulation const simulationStats = { elementsProcessed: 0, fatigueModifications: 0, personalityModifications: 0, temporalModifications: 0, totalModifications: 0, qualityScore: 0, fallbackUsed: false }; // Contenu simulé let simulatedContent = { ...content }; // ======================================== // 1. ANALYSE CONTEXTE GLOBAL // ======================================== const globalContext = await analyzeGlobalContext(content, config); logSh(` 🔍 Contexte: fatigue=${globalContext.fatigueLevel.toFixed(2)}, heure=${globalContext.currentHour}h, personnalité=${globalContext.personalityName}`, 'DEBUG'); // ======================================== // 2. TRAITEMENT PAR ÉLÉMENT // ======================================== for (const [elementKey, elementContent] of Object.entries(content)) { await tracer.run(`HumanSimulation.processElement(${elementKey})`, async () => { logSh(` 🎯 Traitement élément: ${elementKey}`, 'DEBUG'); let processedContent = elementContent; let elementModifications = 0; try { // 2a. Simulation Fatigue Cognitive if (config.fatigueEnabled && globalContext.fatigueLevel > 0.1) { // FIXÉ: Seuil plus bas (était 0.3) const fatigueResult = await applyFatigueSimulation(processedContent, globalContext, config); processedContent = fatigueResult.content; elementModifications += fatigueResult.modifications; simulationStats.fatigueModifications += fatigueResult.modifications; logSh(` 💤 Fatigue: ${fatigueResult.modifications} modifications (niveau: ${globalContext.fatigueLevel.toFixed(2)})`, 'DEBUG'); } // 2b. Erreurs Personnalité if (config.personalityErrorsEnabled && globalContext.personalityProfile) { const personalityResult = await applyPersonalitySimulation(processedContent, globalContext, config); processedContent = personalityResult.content; elementModifications += personalityResult.modifications; simulationStats.personalityModifications += personalityResult.modifications; logSh(` 🎭 Personnalité: ${personalityResult.modifications} erreurs injectées`, 'DEBUG'); } // 2c. Style Temporel if (config.temporalStyleEnabled && globalContext.temporalStyle) { const temporalResult = await applyTemporalSimulation(processedContent, globalContext, config); processedContent = temporalResult.content; elementModifications += temporalResult.modifications; simulationStats.temporalModifications += temporalResult.modifications; logSh(` ⏰ Temporel: ${temporalResult.modifications} ajustements (${globalContext.temporalStyle.period})`, 'DEBUG'); } // 2d. Validation Qualité const qualityCheck = validateSimulationQuality(elementContent, processedContent, config.qualityThreshold); if (qualityCheck.acceptable) { simulatedContent[elementKey] = processedContent; simulationStats.elementsProcessed++; simulationStats.totalModifications += elementModifications; logSh(` ✅ Élément simulé: ${elementModifications} modifications totales`, 'DEBUG'); } else { // Fallback: garder contenu original simulatedContent[elementKey] = elementContent; simulationStats.fallbackUsed = true; logSh(` ⚠️ Qualité insuffisante, fallback vers contenu original`, 'WARNING'); } } catch (elementError) { logSh(` ❌ Erreur simulation élément ${elementKey}: ${elementError.message}`, 'WARNING'); simulatedContent[elementKey] = elementContent; // Fallback simulationStats.fallbackUsed = true; } }, { elementKey, originalLength: elementContent?.length }); } // ======================================== // 3. CALCUL SCORE QUALITÉ GLOBAL // ======================================== simulationStats.qualityScore = calculateGlobalQualityScore(content, simulatedContent); // ======================================== // 4. RÉSULTATS FINAUX // ======================================== const duration = Date.now() - startTime; const success = simulationStats.elementsProcessed > 0 && !simulationStats.fallbackUsed; logSh(`🧠 HUMAN SIMULATION - Terminé (${duration}ms)`, 'INFO'); logSh(` ✅ ${simulationStats.elementsProcessed}/${Object.keys(content).length} éléments simulés`, 'INFO'); logSh(` 📊 ${simulationStats.fatigueModifications} fatigue | ${simulationStats.personalityModifications} personnalité | ${simulationStats.temporalModifications} temporel`, 'INFO'); logSh(` 🎯 Score qualité: ${simulationStats.qualityScore.toFixed(2)} | Fallback: ${simulationStats.fallbackUsed ? 'OUI' : 'NON'}`, 'INFO'); await tracer.event('Human Simulation terminée', { success, duration, stats: simulationStats }); return { content: simulatedContent, stats: simulationStats, fallback: simulationStats.fallbackUsed, qualityScore: simulationStats.qualityScore, duration }; } catch (error) { const duration = Date.now() - startTime; logSh(`❌ HUMAN SIMULATION ÉCHOUÉE (${duration}ms): ${error.message}`, 'ERROR'); await tracer.event('Human Simulation échouée', { error: error.message, duration, contentKeys: Object.keys(content).length }); // Fallback complet return { content, stats: { fallbackUsed: true, error: error.message }, fallback: true, qualityScore: 0, duration }; } }, { contentElements: Object.keys(content).length, elementIndex: options.elementIndex, personality: options.csvData?.personality?.nom }); } /** * ANALYSE CONTEXTE GLOBAL */ async function analyzeGlobalContext(content, config) { const elementIndex = config.elementIndex || 0; const totalElements = config.totalElements || Object.keys(content).length; const currentHour = config.currentHour || new Date().getHours(); const personality = config.csvData?.personality; return { fatigueLevel: calculateFatigue(elementIndex, totalElements), fatigueProfile: personality ? getFatigueProfile(personality.nom) : null, personalityName: personality?.nom || 'unknown', personalityProfile: personality ? getPersonalityErrorPatterns(personality.nom) : null, temporalStyle: getTemporalStyle(currentHour), currentHour, elementIndex, totalElements, contentComplexity: analyzeContentComplexity(content) }; } /** * APPLICATION SIMULATION FATIGUE */ async function applyFatigueSimulation(content, globalContext, config) { const fatigueResult = injectFatigueMarkers(content, globalContext.fatigueLevel, { profile: globalContext.fatigueProfile, intensity: config.imperfectionIntensity }); return { content: fatigueResult.content, modifications: fatigueResult.modifications || 0 }; } /** * APPLICATION SIMULATION PERSONNALITÉ */ async function applyPersonalitySimulation(content, globalContext, config) { const personalityResult = injectPersonalityErrors( content, globalContext.personalityProfile, config.imperfectionIntensity ); return { content: personalityResult.content, modifications: personalityResult.modifications || 0 }; } /** * APPLICATION SIMULATION TEMPORELLE */ async function applyTemporalSimulation(content, globalContext, config) { const temporalResult = applyTemporalStyle(content, globalContext.temporalStyle, { intensity: config.imperfectionIntensity }); return { content: temporalResult.content, modifications: temporalResult.modifications || 0 }; } /** * CALCUL SCORE QUALITÉ GLOBAL */ function calculateGlobalQualityScore(originalContent, simulatedContent) { let totalScore = 0; let elementCount = 0; for (const [key, original] of Object.entries(originalContent)) { const simulated = simulatedContent[key]; if (simulated) { const elementScore = calculateReadabilityScore(simulated) * 0.7 + preserveKeywords(original, simulated) * 0.3; totalScore += elementScore; elementCount++; } } return elementCount > 0 ? totalScore / elementCount : 0; } // ============= EXPORTS ============= module.exports = { applyHumanSimulationLayer, analyzeGlobalContext, applyFatigueSimulation, applyPersonalitySimulation, applyTemporalSimulation, calculateGlobalQualityScore, DEFAULT_CONFIG };