Spaces:
Sleeping
Sleeping
| """Helper functions for faculty record lookups used by multiple blueprints.""" | |
| from __future__ import annotations | |
| import difflib | |
| from typing import Any, Dict, List, Optional, Tuple | |
| from ..data.utils import canonicalize_name, generate_name_variants | |
| from .base import AnalysisContext | |
| def _lookup_record(context: AnalysisContext, target_name: str) -> Tuple[Any, List[str], Optional[Dict[str, Any]]]: | |
| """Return the faculty record matching ``target_name`` and any lookup notes.""" | |
| notes: List[str] = [] | |
| dataset = context.catalog.get("faculty") | |
| record = dataset.get_by_key(target_name) | |
| if record is None: | |
| target_canonical = canonicalize_name(target_name) | |
| for row in dataset.records: | |
| if canonicalize_name(row.get("Name", "")) == target_canonical: | |
| record = row | |
| break | |
| if record is None: | |
| candidates = [row.get("Name", "") for row in dataset.records if row.get("Name")] | |
| closest = difflib.get_close_matches(target_name, candidates, n=1, cutoff=0.6) | |
| if closest: | |
| record = dataset.get_by_key(closest[0]) | |
| notes.append(f"Showing results for '{closest[0]}' (closest match).") | |
| # Fallback: some names appear only in office-assignment CSVs (e.g., "Bain,Connor"). | |
| # Try to match those assignee names back into the faculty roster using | |
| # common name permutations. | |
| office_row: Optional[Dict[str, Any]] = None | |
| if record is None: | |
| offices = context.catalog.try_get("faculty_offices") | |
| if offices: | |
| for row in offices.records: | |
| assignee = row.get("Assignee Name") or row.get("Assignee") or row.get("Name") | |
| if not assignee: | |
| continue | |
| # If the assignee directly matches the target name (or its variants), | |
| # prefer returning the matched faculty roster row when available; if | |
| # no roster row matches, keep the office row as a fallback to emit | |
| # office/location facts. | |
| matched = False | |
| for variant in generate_name_variants(assignee): | |
| # If the variant matches the requested target, consider it a hit. | |
| if canonicalize_name(variant) == canonicalize_name(target_name): | |
| candidate = dataset.get_by_key(variant) | |
| if candidate is not None: | |
| record = candidate | |
| notes.append(f"Matched '{assignee}' from faculty offices to roster entry '{candidate.get('Name')}'.") | |
| matched = True | |
| break | |
| # remember office row as fallback if no roster entry exists | |
| office_row = row | |
| matched = True | |
| break | |
| if matched: | |
| break | |
| return record, notes, office_row | |