"""Drucksache-Typ-Normalisierung (#127). Jeder Landtag hat eigene Bezeichnungen für Dokumenttypen. Dieses Modul normalisiert sie auf einheitliche Kategorien und bestimmt ob eine Drucksache abstimmbar ist (= GWÖ-Bewertung sinnvoll). """ # Normierte Kategorien ANTRAG = "antrag" GESETZENTWURF = "gesetzentwurf" AENDERUNGSANTRAG = "aenderungsantrag" DRINGLICHKEITSANTRAG = "dringlichkeitsantrag" ENTSCHLIESSUNGSANTRAG = "entschliessungsantrag" BESCHLUSSEMPFEHLUNG = "beschlussempfehlung" KLEINE_ANFRAGE = "kleine_anfrage" GROSSE_ANFRAGE = "grosse_anfrage" UNTERRICHTUNG = "unterrichtung" PETITION = "petition" WAHLVORSCHLAG = "wahlvorschlag" BERICHT = "bericht" SONSTIGE = "sonstige" ABSTIMMBARE_TYPEN = { ANTRAG, GESETZENTWURF, AENDERUNGSANTRAG, DRINGLICHKEITSANTRAG, ENTSCHLIESSUNGSANTRAG, } # Übersetzungstabelle: Original-Typ (lowercase) → normierter Typ. # Keys werden case-insensitive + substring-matched. # Reihenfolge: spezifischere zuerst (z.B. "kleine anfrage" vor "anfrage"). _TYP_MAP = [ # Abstimmbar ("gesetzentwurf", GESETZENTWURF), ("änderungsantrag", AENDERUNGSANTRAG), ("aenderungsantrag", AENDERUNGSANTRAG), ("dringlichkeitsantrag", DRINGLICHKEITSANTRAG), ("entschließungsantrag", ENTSCHLIESSUNGSANTRAG), ("entschliessungsantrag", ENTSCHLIESSUNGSANTRAG), ("antrag gemäß", ANTRAG), ("antrag", ANTRAG), # Nicht abstimmbar ("kleine anfrage", KLEINE_ANFRAGE), ("große anfrage", GROSSE_ANFRAGE), ("grosse anfrage", GROSSE_ANFRAGE), ("anfrage", KLEINE_ANFRAGE), ("beschlussempfehlung", BESCHLUSSEMPFEHLUNG), ("unterrichtung", UNTERRICHTUNG), ("bericht", BERICHT), ("mitteilung", UNTERRICHTUNG), ("vorlage", UNTERRICHTUNG), ("petition", PETITION), ("wahlvorschlag", WAHLVORSCHLAG), ("stellungnahme", SONSTIGE), ("drucksache", SONSTIGE), ] def normalize_typ(original: str) -> str: """Normalisiert einen BL-spezifischen Typ-String auf eine Kategorie. Case-insensitiv, Substring-Match, spezifischere Patterns zuerst. """ if not original: return SONSTIGE low = original.lower().strip() for pattern, norm in _TYP_MAP: if pattern in low: return norm return SONSTIGE def ist_abstimmbar(typ_normiert: str) -> bool: """Prüft ob ein normierter Typ zur Abstimmung steht. ``sonstige`` wird durchgelassen (benefit of the doubt) — wenn der Adapter den Typ nicht bestimmen kann (z.B. NRW liefert nur "Drucksache"), wird der echte Check erst beim Analysieren gemacht (aus dem Dokument-Text). """ return typ_normiert in ABSTIMMBARE_TYPEN or typ_normiert == SONSTIGE def ist_abstimmbar_original(original: str) -> bool: """Convenience: prüft direkt am Original-Typ-String.""" return ist_abstimmbar(normalize_typ(original))