97 lines
2.9 KiB
TypeScript
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;
|
|
};
|