"""Lēmuma punkta strukturēšana ar noteikumiem (bez valodas modeļa): darbības veids, adresāti un termiņš. Punkta teksts paliek burtiski; šie lauki ir tikai norādes, kas izgūtas no teksta: kind — pēc punkta sākuma darbības vārda (Pieņemt zināšanai, Atbalstīt, Uzdot …); parties — institūcijas, kas tekstā minētas datīvā („Ekonomikas ministrijai”; ne „… pašvaldībai piederošs”), ar VPK ID, un pašvaldības ar ATVK kodu no Pašvaldību reģistra; deadline — „līdz 2026. gada 10. novembrim” → 2026-11-10. Ja kaut ko nevar droši noteikt, lauks paliek tukšs — neko nemin. """ import re from lxml import etree MONTHS = {"janvārim": 1, "februārim": 2, "martam": 3, "aprīlim": 4, "maijam": 5, "jūnijam": 6, "jūlijam": 7, "augustam": 8, "septembrim": 9, "oktobrim": 10, "novembrim": 11, "decembrim": 12} RE_DATE = re.compile(r"līdz\s+(\d{4})\.\s*gada\s+(\d{1,2})\.\s*(" + "|".join(MONTHS) + r")", re.I) RE_DATE2 = re.compile(r"līdz\s+(\d{1,2})\.(\d{1,2})\.(\d{4})\.?") # darbības vārds → darbības veids. Meklē pirmo no šiem vārdiem punkta tekstā (ārpus pēdiņām), jo punkts var sākties # ar pamatojumu („Saskaņā ar … likuma 4. pantu atļaut …”, „Lai nodrošinātu …, atbalstīt …”). KINDS = [ ("pieņemt zināšanai", "note"), ("zināšanai", "note"), ("ņemt vērā", "note"), ("atzīt par spēku zaudējušu", "repeal"), ("atcelt", "repeal"), ("pieņemt", "adopt"), ("apstiprināt", "approve"), ("atbalstīt", "support"), ("neatbalstīt", "reject"), ("aicināt", "invite"), ("uzdot", "task"), ("piešķirt", "allocate"), ("atļaut", "permit"), ("pilnvarot", "authorise"), ("noteikt", "determine"), ("atzīt", "determine"), ("izteikt", "amend"), ("papildināt", "amend"), ("svītrot", "amend"), ("izdarīt", "amend"), ("grozīt", "amend"), ("nodot", "transfer"), ("pārņemt", "transfer"), ("izveidot", "establish"), ("iecelt", "appoint"), ("atbrīvot", "dismiss"), ("pirkt", "purchase"), ("iegādāties", "purchase"), ] KIND_VALUES = sorted({k for _, k in KINDS} | {"task", "part", "provision"}) def dative_word(w): lw = w.lower() for a, b in (("ija", "ijai"), ("ais", "ajam"), ("ā", "ajai"), ("is", "im"), ("us", "um"), ("a", "ai"), ("e", "ei"), ("s", "am"), ("š", "am")): if lw.endswith(a): return w[: len(w) - len(a)] + b return None def dative(name): """„Valsts ieņēmumu dienests” → „Valsts ieņēmumu dienestam”; „Centrālā finanšu un līgumu aģentūra” → „Centrālajai finanšu un līgumu aģentūrai”. Locās galvenais vārds (pēdējais) un noteiktās galotnes īpašības vārdi (-ais, -ā); ģenitīva vārdi paliek.""" words = name.split() d = dative_word(words[-1]) if not d: return None out = [dative_word(w) if re.search(r"(ais|ā)$", w.lower()) else w for w in words[:-1]] + [d] return " ".join(out) def title_case(name): """Reģistrā budžeta iestāžu nosaukumi ir lielajiem burtiem; salīdzināšanai — mazajiem.""" return name.lower() class Registers: """Valsts institūciju reģistrs (VPK ID) un Pašvaldību reģistrs (ATVK) → datīva formas.""" def __init__(self, org_xml, pas_xml): self.forms = [] # (forma mazajiem burtiem, 'org'|'atvk', id) r = etree.fromstring(org_xml) for o in r: if not isinstance(o.tag, str) or etree.QName(o).localname != "Organization" or o.get("validTo"): continue name = next((c.text for c in o if etree.QName(c).localname == "Name"), "") or "" name = re.sub(r"^LATVIJAS REPUBLIKAS ", "", name) if o.get("kind") in ("group", "office"): continue d = dative(title_case(name)) if d: self.forms.append((d, "org", o.get("id"))) if o.get("kind") == "ministry" and title_case(name).endswith(" ministrija"): stem = title_case(name)[: -len("ministrija")] self.forms += [(stem + "ministram", "minister", o.get("id")), (stem + "ministrei", "minister", o.get("id"))] self.forms.append(("ministru prezidentam", "org", "00-0001")) p = etree.fromstring(pas_xml) for m in p: if not isinstance(m.tag, str) or etree.QName(m).localname != "Municipality": continue name = next(c.text for c in m if etree.QName(c).localname == "Name") if m.get("kind") == "novads": stem = name[: -len(" novads")] forms = [f"{stem} novada pašvaldībai"] else: gen = name + "s" if name[-1] in "ae" else name forms = [f"{gen} valstspilsētas pašvaldībai", f"{gen} pašvaldībai"] for f in forms: self.forms.append((f.lower(), "atvk", m.get("atvk"))) # garākās formas pirmās, lai „Valsts ieņēmumu dienestam” nesakristu ar īsāku formu tās iekšienē self.forms.sort(key=lambda x: -len(x[0])) def parties(self, text): low, found, taken = text.lower(), [], [] for form, kind, ident in self.forms: for m in re.finditer(r"(?