"""Détection de la pertinence guadeloupéenne et ultramarine d'un texte. Le tableau A de l'annexe cote lui-même les 27 lois promulguées ; le tableau B ne cote pas les textes en cours. Pour ces derniers, la cotation est déduite du vocabulaire employé par le rapport, avec des poids déclarés dans `pipeline/config.yaml`. Toute cotation obtenue ainsi est signalée : le texte porte `a_verifier = 1` et un motif explicite. L'interface l'affiche comme telle. Une cotation déduite n'est pas une cotation établie. """ from __future__ import annotations import functools import re from dataclasses import dataclass import yaml from pipeline import chemins from pipeline.modeles import Pertinence from pipeline.parseurs.dates_fr import sans_accents @dataclass(slots=True) class Cotation: """Résultat d'une détection, avec ce qui l'a motivée.""" pertinence: Pertinence | None score: int expressions: list[str] @property def note(self) -> str | None: if not self.expressions: return None return "Détecté d'après : " + ", ".join(self.expressions[:6]) @functools.lru_cache(maxsize=1) def _configuration() -> dict: return yaml.safe_load(chemins.CONFIG.read_text(encoding="utf-8")) @functools.lru_cache(maxsize=1) def _motifs() -> list[tuple[re.Pattern[str], str, int]]: """Compile un motif par expression, ancré sur des frontières de mot.""" expressions = _configuration()["guadeloupe"]["expressions"] compiles: list[tuple[re.Pattern[str], str, int]] = [] for expression, poids in expressions.items(): plat = sans_accents(str(expression)).lower() compiles.append((re.compile(rf"(? Cotation: """Cote la pertinence guadeloupéenne d'un ensemble de fragments de texte.""" plat = sans_accents(" ".join(f for f in fragments if f)).lower() if not plat.strip(): return Cotation(pertinence=None, score=0, expressions=[]) score = 0 trouvees: list[str] = [] for motif, expression, poids in _motifs(): if motif.search(plat): score += poids trouvees.append(expression) seuils = _configuration()["guadeloupe"]["seuils"] if score >= seuils["forte"]: pertinence = Pertinence.FORTE elif score >= seuils["moyenne"]: pertinence = Pertinence.MOYENNE elif score >= seuils["faible"]: pertinence = Pertinence.FAIBLE else: pertinence = None return Cotation(pertinence=pertinence, score=score, expressions=trouvees) MOTIF_VERIFICATION = ( "Pertinence Guadeloupe déduite automatiquement : l'annexe du rapport ne " "cote que les lois promulguées, pas les textes encore en discussion." )