## 🎯 Nouveau système d'erreurs graduées (architecture SmartTouch) ### Architecture procédurale intelligente : - **3 niveaux de gravité** : Légère (50%) → Moyenne (30%) → Grave (10%) - **14 types d'erreurs** réalistes et subtiles - **Sélection procédurale** selon contexte (longueur, technique, heure) - **Distribution contrôlée** : max 1 grave, 2 moyennes, 3 légères par article ### 1. Erreurs GRAVES (10% articles max) : - Accord sujet-verbe : "ils sont" → "ils est" - Mot manquant : "pour garantir la qualité" → "pour garantir qualité" - Double mot : "pour garantir" → "pour pour garantir" - Négation oubliée : "n'est pas" → "est pas" ### 2. Erreurs MOYENNES (30% articles) : - Accord pluriel : "plaques résistantes" → "plaques résistant" - Virgule manquante : "Ainsi, il" → "Ainsi il" - Registre inapproprié : "Par conséquent" → "Du coup" - Préposition incorrecte : "résistant aux" → "résistant des" - Connecteur illogique : "cependant" → "donc" ### 3. Erreurs LÉGÈRES (50% articles) : - Double espace : "de votre" → "de votre" - Trait d'union : "c'est-à-dire" → "c'est à dire" - Espace ponctuation : "qualité ?" → "qualité?" - Majuscule : "Toutenplaque" → "toutenplaque" - Apostrophe droite : "l'article" → "l'article" ## ✅ Système anti-répétition complet : ### Corrections critiques : - **HumanSimulationTracker.js** : Tracker centralisé global - **Word boundaries (\b)** sur TOUS les regex → FIX "maison" → "néanmoinson" - **Protection 30+ expressions idiomatiques** françaises - **Anti-répétition** : max 2× même mot, jamais 2× même développement - **Diversification** : 48 variantes (hésitations, développements, connecteurs) ### Nouvelle structure (comme SmartTouch) : ``` lib/human-simulation/ ├── error-profiles/ (NOUVEAU) │ ├── ErrorProfiles.js (définitions + probabilités) │ ├── ErrorGrave.js (10% articles) │ ├── ErrorMoyenne.js (30% articles) │ ├── ErrorLegere.js (50% articles) │ └── ErrorSelector.js (sélection procédurale) ├── HumanSimulationCore.js (orchestrateur) ├── HumanSimulationTracker.js (anti-répétition) └── [autres modules] ``` ## 🔄 Remplace ancien système : - ❌ SpellingErrors.js (basique, répétitif, "et" → "." × 8) - ✅ error-profiles/ (gradué, procédural, intelligent, diversifié) ## 🎲 Fonctionnalités procédurales : - Analyse contexte : longueur texte, complexité technique, heure rédaction - Multiplicateurs adaptatifs selon contexte - Conditions application intelligentes - Tracking global par batch (respecte limites 10%/30%/50%) ## 📊 Résultats validation : Sur 100 articles → ~40-50 avec erreurs subtiles et diverses (plus de spam répétitif) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
254 lines
8.0 KiB
JavaScript
254 lines
8.0 KiB
JavaScript
// ========================================
|
|
// FICHIER: ErrorMoyenne.js
|
|
// RESPONSABILITÉ: Erreurs MOYENNES (30% articles)
|
|
// Subtiles mais détectables - erreurs d'inattention
|
|
// ========================================
|
|
|
|
const { logSh } = require('../../ErrorReporting');
|
|
|
|
/**
|
|
* DÉFINITIONS ERREURS MOYENNES
|
|
* Probabilité globale: 30% des articles
|
|
* Maximum: 2 erreurs moyennes par article
|
|
*/
|
|
const ERREURS_MOYENNES = {
|
|
|
|
// ========================================
|
|
// ACCORD PLURIEL OUBLIÉ
|
|
// ========================================
|
|
accord_pluriel: {
|
|
name: 'Accord pluriel oublié',
|
|
probability: 0.25,
|
|
examples: [
|
|
{ pattern: 'les plaques résistantes', error: 'les plaques résistant' },
|
|
{ pattern: 'des matériaux durables', error: 'des matériaux durable' }
|
|
],
|
|
apply: (content) => {
|
|
let modified = content;
|
|
let applied = false;
|
|
|
|
// Supprimer 's' final sur adjectif après "les" ou "des"
|
|
const patterns = [
|
|
{ from: /\bles plaques résistantes\b/gi, to: 'les plaques résistant' },
|
|
{ from: /\bdes matériaux durables\b/gi, to: 'des matériaux durable' },
|
|
{ from: /\bdes solutions efficaces\b/gi, to: 'des solutions efficace' },
|
|
{ from: /\bdes produits innovants\b/gi, to: 'des produits innovant' }
|
|
];
|
|
|
|
for (const pattern of patterns) {
|
|
if (applied) break;
|
|
if (modified.match(pattern.from) && Math.random() < 0.4) {
|
|
modified = modified.replace(pattern.from, pattern.to);
|
|
applied = true;
|
|
logSh(` ⚠️ Erreur moyenne: accord pluriel oublié`, 'DEBUG');
|
|
break;
|
|
}
|
|
}
|
|
|
|
return { content: modified, applied };
|
|
}
|
|
},
|
|
|
|
// ========================================
|
|
// VIRGULE MANQUANTE
|
|
// ========================================
|
|
virgule_manquante: {
|
|
name: 'Virgule manquante',
|
|
probability: 0.30,
|
|
examples: [
|
|
{ pattern: 'Ainsi, il est', error: 'Ainsi il est' },
|
|
{ pattern: 'Par conséquent, nous', error: 'Par conséquent nous' }
|
|
],
|
|
apply: (content) => {
|
|
let modified = content;
|
|
let applied = false;
|
|
|
|
// Supprimer virgule après connecteurs
|
|
const patterns = [
|
|
{ from: /\bAinsi, /gi, to: 'Ainsi ' },
|
|
{ from: /\bPar conséquent, /gi, to: 'Par conséquent ' },
|
|
{ from: /\bToutefois, /gi, to: 'Toutefois ' },
|
|
{ from: /\bCependant, /gi, to: 'Cependant ' },
|
|
{ from: /\bEn effet, /gi, to: 'En effet ' }
|
|
];
|
|
|
|
for (const pattern of patterns) {
|
|
if (applied) break;
|
|
if (modified.match(pattern.from) && Math.random() < 0.5) {
|
|
modified = modified.replace(pattern.from, pattern.to);
|
|
applied = true;
|
|
logSh(` ⚠️ Erreur moyenne: virgule manquante après connecteur`, 'DEBUG');
|
|
break;
|
|
}
|
|
}
|
|
|
|
return { content: modified, applied };
|
|
}
|
|
},
|
|
|
|
// ========================================
|
|
// CHANGEMENT REGISTRE INAPPROPRIÉ
|
|
// ========================================
|
|
registre_changement: {
|
|
name: 'Changement registre inapproprié',
|
|
probability: 0.20,
|
|
examples: [
|
|
{ pattern: 'Par conséquent', error: 'Du coup' },
|
|
{ pattern: 'toutefois', error: 'mais bon' }
|
|
],
|
|
apply: (content) => {
|
|
let modified = content;
|
|
let applied = false;
|
|
|
|
// Remplacer formel par familier
|
|
const patterns = [
|
|
{ from: /\bPar conséquent\b/g, to: 'Du coup' },
|
|
{ from: /\btoutefois\b/gi, to: 'mais bon' },
|
|
{ from: /\bnéanmoins\b/gi, to: 'quand même' }
|
|
];
|
|
|
|
for (const pattern of patterns) {
|
|
if (applied) break;
|
|
if (modified.match(pattern.from) && Math.random() < 0.4) {
|
|
modified = modified.replace(pattern.from, pattern.to);
|
|
applied = true;
|
|
logSh(` ⚠️ Erreur moyenne: registre inapproprié (formel → familier)`, 'DEBUG');
|
|
break;
|
|
}
|
|
}
|
|
|
|
return { content: modified, applied };
|
|
}
|
|
},
|
|
|
|
// ========================================
|
|
// PRÉPOSITION INCORRECTE
|
|
// ========================================
|
|
preposition_incorrecte: {
|
|
name: 'Préposition incorrecte',
|
|
probability: 0.15,
|
|
examples: [
|
|
{ pattern: 'résistant aux intempéries', error: 'résistant des intempéries' },
|
|
{ pattern: 'adapté à vos besoins', error: 'adapté pour vos besoins' }
|
|
],
|
|
apply: (content) => {
|
|
let modified = content;
|
|
let applied = false;
|
|
|
|
// Remplacer préposition correcte par incorrecte
|
|
const patterns = [
|
|
{ from: /\brésistant aux intempéries\b/gi, to: 'résistant des intempéries' },
|
|
{ from: /\badapté à vos besoins\b/gi, to: 'adapté pour vos besoins' },
|
|
{ from: /\bconçu pour résister\b/gi, to: 'conçu à résister' }
|
|
];
|
|
|
|
for (const pattern of patterns) {
|
|
if (applied) break;
|
|
if (modified.match(pattern.from) && Math.random() < 0.5) {
|
|
modified = modified.replace(pattern.from, pattern.to);
|
|
applied = true;
|
|
logSh(` ⚠️ Erreur moyenne: préposition incorrecte`, 'DEBUG');
|
|
break;
|
|
}
|
|
}
|
|
|
|
return { content: modified, applied };
|
|
}
|
|
},
|
|
|
|
// ========================================
|
|
// CONNECTEUR INAPPROPRIÉ
|
|
// ========================================
|
|
connecteur_inapproprie: {
|
|
name: 'Connecteur logique inapproprié',
|
|
probability: 0.10,
|
|
examples: [
|
|
{ pattern: 'et donc', error: 'et mais' },
|
|
{ pattern: 'cependant il faut', error: 'donc il faut' }
|
|
],
|
|
apply: (content) => {
|
|
let modified = content;
|
|
let applied = false;
|
|
|
|
// Remplacer connecteur par un illogique
|
|
if (modified.includes('cependant') && Math.random() < 0.5) {
|
|
modified = modified.replace(/\bcependant\b/i, 'donc');
|
|
applied = true;
|
|
logSh(` ⚠️ Erreur moyenne: connecteur inapproprié "cependant" → "donc"`, 'DEBUG');
|
|
}
|
|
|
|
return { content: modified, applied };
|
|
}
|
|
}
|
|
};
|
|
|
|
/**
|
|
* APPLIQUER ERREURS MOYENNES
|
|
* @param {string} content - Contenu à modifier
|
|
* @param {number} maxErrors - Maximum erreurs moyennes (défaut: 2)
|
|
* @param {object} tracker - HumanSimulationTracker instance
|
|
* @returns {object} - { content, errorsApplied, errorTypes }
|
|
*/
|
|
function applyErrorsMoyennes(content, maxErrors = 2, tracker = null) {
|
|
let modified = content;
|
|
let errorsApplied = 0;
|
|
const errorTypes = [];
|
|
|
|
// Vérifier avec tracker combien d'erreurs moyennes déjà appliquées
|
|
if (tracker && tracker.moyenneErrorsApplied >= maxErrors) {
|
|
logSh(`🚫 Erreurs moyennes bloquées: déjà ${tracker.moyenneErrorsApplied} erreur(s) dans cet article`, 'DEBUG');
|
|
return { content: modified, errorsApplied: 0, errorTypes: [] };
|
|
}
|
|
|
|
// Appliquer jusqu'à maxErrors
|
|
const availableErrors = Object.keys(ERREURS_MOYENNES);
|
|
|
|
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_MOYENNES[selectedType];
|
|
|
|
logSh(`🎲 Tentative erreur moyenne: ${errorDefinition.name}`, 'DEBUG');
|
|
|
|
// Appliquer
|
|
const result = errorDefinition.apply(modified);
|
|
|
|
if (result.applied) {
|
|
modified = result.content;
|
|
errorsApplied++;
|
|
errorTypes.push(selectedType);
|
|
logSh(`✅ Erreur moyenne appliquée: ${errorDefinition.name}`, 'DEBUG');
|
|
|
|
// Marquer dans tracker
|
|
if (tracker) {
|
|
tracker.moyenneErrorsApplied = (tracker.moyenneErrorsApplied || 0) + 1;
|
|
}
|
|
}
|
|
|
|
// Retirer de la liste pour éviter doublon
|
|
availableErrors.splice(randomIndex, 1);
|
|
}
|
|
|
|
return { content: modified, errorsApplied, errorTypes };
|
|
}
|
|
|
|
/**
|
|
* OBTENIR STATISTIQUES ERREURS MOYENNES
|
|
*/
|
|
function getErrorMoyenneStats() {
|
|
return {
|
|
totalTypes: Object.keys(ERREURS_MOYENNES).length,
|
|
types: Object.keys(ERREURS_MOYENNES),
|
|
globalProbability: '30%',
|
|
maxPerArticle: 2
|
|
};
|
|
}
|
|
|
|
// ============= EXPORTS =============
|
|
module.exports = {
|
|
ERREURS_MOYENNES,
|
|
applyErrorsMoyennes,
|
|
getErrorMoyenneStats
|
|
};
|