// ======================================== // FICHIER: ErrorLegere.js // RESPONSABILITÉ: Erreurs LÉGÈRES (50% articles) // Micro-erreurs très subtiles - quasi indétectables // ======================================== const { logSh } = require('../../ErrorReporting'); /** * DÉFINITIONS ERREURS LÉGÈRES * Probabilité globale: 50% des articles * Maximum: 3 erreurs légères par article */ const ERREURS_LEGERES = { // ======================================== // DOUBLE ESPACE // ======================================== double_espace: { name: 'Double espace', probability: 0.30, examples: [ { pattern: 'de votre', error: 'de votre' }, { pattern: 'pour la', error: 'pour la' } ], apply: (content) => { let modified = content; let applied = false; // Insérer double espace aléatoirement const words = content.split(' '); if (words.length < 10) return { content: modified, applied }; const targetIndex = Math.floor(Math.random() * (words.length - 1)); words[targetIndex] = words[targetIndex] + ' '; // Ajouter espace supplémentaire modified = words.join(' '); applied = true; logSh(` · Erreur légère: double espace à position ${targetIndex}`, 'DEBUG'); return { content: modified, applied }; } }, // ======================================== // TRAIT D'UNION OUBLIÉ // ======================================== trait_union_oublie: { name: 'Trait d\'union oublié', probability: 0.25, examples: [ { pattern: "c'est-à-dire", error: "c'est à dire" }, { pattern: 'peut-être', error: 'peut être' }, { pattern: 'vis-à-vis', error: 'vis à vis' } ], apply: (content) => { let modified = content; let applied = false; // Supprimer traits d'union const patterns = [ { from: /\bc'est-à-dire\b/gi, to: "c'est à dire" }, { from: /\bpeut-être\b/gi, to: 'peut être' }, { from: /\bvis-à-vis\b/gi, to: 'vis à vis' } ]; for (const pattern of patterns) { if (applied) break; if (modified.match(pattern.from) && Math.random() < 0.6) { modified = modified.replace(pattern.from, pattern.to); applied = true; logSh(` · Erreur légère: trait d'union oublié`, 'DEBUG'); break; } } return { content: modified, applied }; } }, // ======================================== // ESPACE AVANT PONCTUATION // ======================================== espace_avant_ponctuation: { name: 'Espace avant ponctuation manquante', probability: 0.20, examples: [ { pattern: 'qualité ?', error: 'qualité?' }, { pattern: 'résistance !', error: 'résistance!' } ], apply: (content) => { let modified = content; let applied = false; // Supprimer espace avant ? ou ! if (Math.random() < 0.5) { modified = modified.replace(/ \?/g, '?'); if (modified !== content) { applied = true; logSh(` · Erreur légère: espace manquant avant "?"`, 'DEBUG'); } } else { modified = modified.replace(/ !/g, '!'); if (modified !== content) { applied = true; logSh(` · Erreur légère: espace manquant avant "!"`, 'DEBUG'); } } return { content: modified, applied }; } }, // ======================================== // MAJUSCULE INCORRECTE // ======================================== majuscule_incorrecte: { name: 'Majuscule incorrecte', probability: 0.15, examples: [ { pattern: 'la France', error: 'la france' }, { pattern: 'Toutenplaque', error: 'toutenplaque' } ], apply: (content) => { let modified = content; let applied = false; // Mettre en minuscule un nom propre const properNouns = ['France', 'Paris', 'Toutenplaque']; for (const noun of properNouns) { if (applied) break; const regex = new RegExp(`\\b${noun}\\b`, 'g'); if (modified.match(regex) && Math.random() < 0.4) { modified = modified.replace(regex, noun.toLowerCase()); applied = true; logSh(` · Erreur légère: majuscule incorrecte sur "${noun}"`, 'DEBUG'); break; } } return { content: modified, applied }; } }, // ======================================== // APOSTROPHE DROITE (au lieu de courbe) // ======================================== apostrophe_droite: { name: 'Apostrophe droite au lieu de courbe', probability: 0.10, examples: [ { pattern: "l'article", error: "l'article" }, { pattern: "d'une", error: "d'une" } ], apply: (content) => { let modified = content; let applied = false; // Remplacer apostrophe courbe par droite const apostropheCourbe = '\u2019'; // ' (apostrophe typographique) if (modified.includes(apostropheCourbe) && Math.random() < 0.5) { // Remplacer UNE occurrence seulement const index = modified.indexOf(apostropheCourbe); if (index !== -1) { modified = modified.substring(0, index) + "'" + modified.substring(index + 1); applied = true; logSh(` · Erreur légère: apostrophe droite au lieu de courbe`, 'DEBUG'); } } return { content: modified, applied }; } } }; /** * APPLIQUER ERREURS LÉGÈRES * @param {string} content - Contenu à modifier * @param {number} maxErrors - Maximum erreurs légères (défaut: 3) * @param {object} tracker - HumanSimulationTracker instance * @returns {object} - { content, errorsApplied, errorTypes } */ function applyErrorsLegeres(content, maxErrors = 3, tracker = null) { let modified = content; let errorsApplied = 0; const errorTypes = []; // Vérifier avec tracker combien d'erreurs légères déjà appliquées if (tracker && tracker.legereErrorsApplied >= maxErrors) { logSh(`🚫 Erreurs légères bloquées: déjà ${tracker.legereErrorsApplied} erreur(s) dans cet article`, 'DEBUG'); return { content: modified, errorsApplied: 0, errorTypes: [] }; } // Appliquer jusqu'à maxErrors const availableErrors = Object.keys(ERREURS_LEGERES); while (errorsApplied < maxErrors && availableErrors.length > 0) { // Sélectionner type aléatoire const randomIndex = Math.floor(Math.random() * availableErrors.length); const selectedType = availableErrors[randomIndex]; const errorDefinition = ERREURS_LEGERES[selectedType]; logSh(`🎲 Tentative erreur légère: ${errorDefinition.name}`, 'DEBUG'); // Appliquer const result = errorDefinition.apply(modified); if (result.applied) { modified = result.content; errorsApplied++; errorTypes.push(selectedType); logSh(`✅ Erreur légère appliquée: ${errorDefinition.name}`, 'DEBUG'); // Marquer dans tracker if (tracker) { tracker.legereErrorsApplied = (tracker.legereErrorsApplied || 0) + 1; } } // Retirer de la liste pour éviter doublon availableErrors.splice(randomIndex, 1); } return { content: modified, errorsApplied, errorTypes }; } /** * OBTENIR STATISTIQUES ERREURS LÉGÈRES */ function getErrorLegereStats() { return { totalTypes: Object.keys(ERREURS_LEGERES).length, types: Object.keys(ERREURS_LEGERES), globalProbability: '50%', maxPerArticle: 3 }; } // ============= EXPORTS ============= module.exports = { ERREURS_LEGERES, applyErrorsLegeres, getErrorLegereStats };