dp-zp-agent/tools/crzp/answering/units.py
2026-11-15 16:27:08 +01:00

94 lines
4.2 KiB
Python

"""Verified CRZP workplace codes (the numbers after the school name).
CRZP writes a TUKE work as "Technická univerzita v Košiciach 1040 104005" and
does not publish what the codes mean. Only codes supported by the records are
named here:
- 104005 = KEMT: the works supervised by KEMT staff known from ZP Wiki
(Hládek, Staš, Ondáš, Pleva, Juhár, Galajda, Drutarovský, Čižmár, Viszlay)
carry 104005 in CRZP (checked on 2026-11-14 over the cached records, e.g.
Hládek 69 of 71, Staš 33 of 33, Ondáš 30 of 31);
- 1040 = FEI: every 104005 record starts with 1040 and KEMT belongs to FEI
(the ZP Wiki domain is zp.kemt.fei.tuke.sk).
Older records (about until 2015) write the department by name ("1040 Katedra
elektroniky a multimediálnych telekomunikácií") instead of 104005; CRZP indexes
that text too, so a workplace is searched by every form in "search" and the
name is matched as written.
Other TUKE department codes are named only when workplaces.json holds a name
learned from CRZP records with enough votes (see workplaces.py); such a
workplace can be asked by its acronym ("na KPI") or name and is searched by
its code and its old written name. Codes without evidence stay numbers
("pracovisko 104009"), never guessed.
"""
from __future__ import annotations
import re
from tools.crzp.answering import workplaces
from tools.crzp.source.parse import fold
VERIFIED = {
"kemt": {"school": "tuke", "code": "104005", "label": "KEMT FEI",
"text": "katedra elektroniky a multimedialnych telekomunikacii",
"search": ["104005", "Katedra elektroniky a multimediálnych telekomunikácií"]},
"fei": {"school": "tuke", "code": "1040", "label": "FEI", "text": "fakulta elektrotechniky a informatiky",
"search": ["1040"]}, # old FEI records also start with 1040
}
CUES = {
"kemt": r"\bkemt\b|katedr\w* elektroniky a multimedi",
"fei": r"\bfei\b|fakult\w* elektrotechniky a informatiky",
}
def _learned_units() -> dict:
"""Departments named in workplaces.json, keyed by their acronym ("kpi")."""
units = {}
for short, (code, entry) in workplaces.by_acronym(workplaces.TUKE).items():
if short in VERIFIED or code in {u["code"] for u in VERIFIED.values()}:
continue
units[short] = {"school": "tuke", "code": code, "label": f"{entry['short']} FEI" if code.startswith("1040")
else entry["short"], "text": fold(entry["name"]), "search": [code, entry["name"]],
"learned": True}
words = [w for w in fold(entry["name"]).split() if w not in workplaces.SMALL_WORDS]
CUES[short] = r"\b" + re.escape(short) + r"\b|" + r"\w*\s+(?:\w+\s+)?".join(re.escape(w[:5]) for w in words)
return units
UNITS = {**VERIFIED, **_learned_units()}
ORDER = ["kemt", *[k for k in UNITS if UNITS[k].get("learned")], "fei"] # the most specific unit first
def unit_in_question(question: str) -> str | None:
"""The most specific known unit the question names (a department before FEI)."""
low = fold(question)
return next((key for key in ORDER if re.search(fold(CUES[key]) if key in ("kemt", "fei") else CUES[key], low)), None)
def _tuke(row: dict) -> bool:
return fold(row.get("school") or "") == "technicka univerzita v kosiciach"
def in_unit(row: dict, key: str) -> bool:
unit = row.get("school_unit") or ""
if not _tuke(row):
return False
if key == "fei" and in_unit(row, "kemt"):
return True
return UNITS[key]["code"] in unit.split() or UNITS[key]["text"] in fold(unit)
def unit_label(row: dict) -> str:
""""FEI, KEMT" for verified codes; unverified codes stay as "pracovisko 104009";
a department written by name is kept as written."""
unit = row.get("school_unit") or ""
if not unit or not _tuke(row):
return unit
names = []
for part in re.findall(r"\d+|[^\d]+", unit):
part = part.strip(" ,")
if not part:
continue
known = next((u["label"].split()[0] for u in VERIFIED.values() if u["code"] == part), None)
entry = workplaces.name_of(workplaces.TUKE, part) if part.isdigit() and not known else None
names.append(known or (f"{entry['name']} ({part})" if entry else f"pracovisko {part}" if part.isdigit() else part))
return ", ".join(names)