monish563/NU-KIOSK-API
0
1"""Helper functions for faculty record lookups used by multiple blueprints."""2 3from __future__ import annotations4 5import difflib6from typing import Any, Dict, List, Optional, Tuple7 8from ..data.utils import canonicalize_name, generate_name_variants9from .base import AnalysisContext10 11 12def _lookup_record(context: AnalysisContext, target_name: str) -> Tuple[Any, List[str], Optional[Dict[str, Any]]]:13 """Return the faculty record matching ``target_name`` and any lookup notes."""14 15 notes: List[str] = []16 dataset = context.catalog.get("faculty")17 record = dataset.get_by_key(target_name)18 if record is None:19 target_canonical = canonicalize_name(target_name)20 for row in dataset.records:21 if canonicalize_name(row.get("Name", "")) == target_canonical:22 record = row23 break24 if record is None:25 candidates = [row.get("Name", "") for row in dataset.records if row.get("Name")]26 closest = difflib.get_close_matches(target_name, candidates, n=1, cutoff=0.6)27 if closest:28 record = dataset.get_by_key(closest[0])29 notes.append(f"Showing results for '{closest[0]}' (closest match).")30 # Fallback: some names appear only in office-assignment CSVs (e.g., "Bain,Connor").31 # Try to match those assignee names back into the faculty roster using32 # common name permutations.33 office_row: Optional[Dict[str, Any]] = None34 if record is None:35 offices = context.catalog.try_get("faculty_offices")36 if offices:37 for row in offices.records:38 assignee = row.get("Assignee Name") or row.get("Assignee") or row.get("Name")39 if not assignee:40 continue41 # If the assignee directly matches the target name (or its variants),42 # prefer returning the matched faculty roster row when available; if43 # no roster row matches, keep the office row as a fallback to emit44 # office/location facts.45 matched = False46 for variant in generate_name_variants(assignee):47 # If the variant matches the requested target, consider it a hit.48 if canonicalize_name(variant) == canonicalize_name(target_name):49 candidate = dataset.get_by_key(variant)50 if candidate is not None:51 record = candidate52 notes.append(f"Matched '{assignee}' from faculty offices to roster entry '{candidate.get('Name')}'.")53 matched = True54 break55 # remember office row as fallback if no roster entry exists56 office_row = row57 matched = True58 break59 if matched:60 break61 return record, notes, office_row62 