Files
Anonyme/app/utils/generateAnonymizedText.ts
2025-09-15 19:05:59 +02:00

97 lines
2.9 KiB
TypeScript

import { EntityMapping } from "@/app/config/entityLabels";
// Fonction améliorée pour résoudre les chevauchements d'entités
const resolveOverlaps = (mappings: EntityMapping[]): EntityMapping[] => {
if (mappings.length <= 1) return mappings;
// Trier par position de début, puis par score/longueur
const sorted = [...mappings].sort((a, b) => {
if (a.start !== b.start) return a.start - b.start;
// En cas d'égalité, privilégier l'entité la plus longue
return (b.end - b.start) - (a.end - a.start);
});
const resolved: EntityMapping[] = [];
for (const current of sorted) {
// Vérifier si cette entité chevauche avec une entité déjà acceptée
let hasConflict = false;
for (const existing of resolved) {
// Détecter tout type de chevauchement
const overlap = (
(current.start >= existing.start && current.start < existing.end) ||
(current.end > existing.start && current.end <= existing.end) ||
(current.start <= existing.start && current.end >= existing.end)
);
if (overlap) {
hasConflict = true;
break;
}
}
if (!hasConflict) {
resolved.push(current);
}
}
return resolved.sort((a, b) => a.start - b.start);
};
// Fonction pour nettoyer et valider les mappings
const cleanMappings = (mappings: EntityMapping[], originalText: string): EntityMapping[] => {
return mappings.filter(mapping => {
// Vérifier que les indices sont valides
if (mapping.start < 0 || mapping.end < 0) return false;
if (mapping.start >= originalText.length) return false;
if (mapping.end > originalText.length) return false;
if (mapping.start >= mapping.end) return false;
// Vérifier que le texte correspond
const extractedText = originalText.slice(mapping.start, mapping.end);
return extractedText === mapping.text;
});
};
export const generateAnonymizedText = (
originalText: string,
mappings: EntityMapping[]
): string => {
if (!originalText || !mappings || mappings.length === 0) {
return originalText;
}
// Nettoyer et valider les mappings
const cleanedMappings = cleanMappings(mappings, originalText);
// Résoudre les chevauchements
const resolvedMappings = resolveOverlaps(cleanedMappings);
let result = "";
let lastIndex = 0;
for (const mapping of resolvedMappings) {
// Sécurité supplémentaire
if (mapping.start < lastIndex) continue;
// Ajouter le texte avant l'entité
result += originalText.slice(lastIndex, mapping.start);
// Utiliser la valeur de remplacement appropriée
let replacement = mapping.replacementValue;
if (!replacement) {
replacement = mapping.displayName || `[${mapping.entity_type}]`;
}
result += replacement;
lastIndex = mapping.end;
}
// Ajouter le reste du texte
result += originalText.slice(lastIndex);
return result;
};