kiosk_vanilla / backend /tools /location.py
Monish Vijay Kumar
Deploy Northwestern CS Kiosk Docker Space with checkpoint and inference runtime
7056be6
Raw
History Blame
7.47 kB
"""Blueprint that returns location information for faculty, staff, or students."""
from __future__ import annotations
from typing import Any, Dict, List, Optional
from .base import AnalysisContext, Blueprint, BlueprintResult, Fact
from .faculty_profile import _lookup_record
from ..data.utils import canonicalize_name
class LocationBlueprint(Blueprint):
"""Return where a person (faculty, staff, or student) can be found on campus.
Automatically detects whether the name matches a faculty member, staff member,
or student and returns the appropriate location information.
"""
name = "location"
def run(self, context: AnalysisContext, **kwargs: Any) -> BlueprintResult:
target_name = (kwargs.get("name") or kwargs.get("person") or "").strip()
if not target_name:
return BlueprintResult(self.name, kwargs, facts=[], notes=["No name provided."])
facts: List[Fact] = []
notes: List[str] = []
found_faculty = False
found_staff = False
found_student = False
# Try faculty lookup first
faculty_facts, faculty_notes, found_faculty = self._lookup_faculty_location(context, target_name)
facts.extend(faculty_facts)
notes.extend(faculty_notes)
# Try staff lookup
staff_facts, staff_notes, found_staff = self._lookup_staff_location(context, target_name)
facts.extend(staff_facts)
notes.extend(staff_notes)
# Try student lookup
student_facts, student_notes, found_student = self._lookup_student_seating(context, target_name)
facts.extend(student_facts)
notes.extend(student_notes)
# If none found, report not found
if not found_faculty and not found_staff and not found_student:
return BlueprintResult(
self.name,
kwargs,
facts=[],
notes=[f"'{target_name}' not found in faculty, staff, or student records."],
)
return BlueprintResult(self.name, kwargs, facts=facts, notes=notes)
def _lookup_faculty_location(
self, context: AnalysisContext, target_name: str
) -> tuple[List[Fact], List[str], bool]:
"""Look up faculty office location. Returns (facts, notes, found)."""
record, lookup_notes, office_row = _lookup_record(context, target_name)
if record is None and office_row is None:
return [], [], False
facts: List[Fact] = []
notes = list(lookup_notes)
# Try to resolve office through relationship
office_matches = []
if record is not None:
office_matches = context.catalog.resolve_relationship("faculty_to_office", record)
if office_matches:
office_row = office_matches[0]
office_entity = context.catalog.try_get("faculty_offices")
office_source = office_entity.origin if office_entity else None
building = (office_row.get("Building") or "").strip()
room = (office_row.get("Room") or office_row.get("Room Location") or "").strip()
location = " ".join(bit for bit in (building, room) if bit).strip()
facts.append(
Fact(
subject=record["Name"],
predicate="office",
value=location or "Office location unavailable",
source=office_source,
)
)
elif office_row is not None:
# Matched office assignment but no roster record
office_entity = context.catalog.try_get("faculty_offices")
office_source = office_entity.origin if office_entity else None
building = (office_row.get("Building") or office_row.get("Location") or "").strip()
room = (office_row.get("Room") or office_row.get("Room Location") or "").strip()
location = " ".join(bit for bit in (building, room) if bit).strip()
facts.append(
Fact(
subject=office_row.get("Assignee Name") or target_name,
predicate="office",
value=location or "Office location unavailable",
source=office_source,
)
)
elif record is not None:
notes.append(f"No office assignment found for {record['Name']}.")
return facts, notes, (record is not None or office_row is not None)
def _lookup_staff_location(
self, context: AnalysisContext, target_name: str
) -> tuple[List[Fact], List[str], bool]:
"""Look up staff office location. Returns (facts, notes, found)."""
staff = context.catalog.try_get("staff")
if not staff:
return [], [], False
record = None
canonical_target = canonicalize_name(target_name)
for row in staff.records:
if canonicalize_name(row.get("Name", "")) == canonical_target:
record = row
break
if record is None:
return [], [], False
facts: List[Fact] = []
notes: List[str] = []
location = (record.get("Room Location") or "").strip()
if location and location.lower() not in {"not listed", "n/a", "none", ""}:
facts.append(
Fact(
subject=record.get("Name", target_name),
predicate="office",
value=location,
source=staff.origin,
confidence=0.9,
)
)
else:
notes.append(f"No office location listed for {record.get('Name', target_name)}.")
return facts, notes, True
def _lookup_student_seating(
self, context: AnalysisContext, target_name: str
) -> tuple[List[Fact], List[str], bool]:
"""Look up student seating location. Returns (facts, notes, found)."""
students = context.catalog.try_get("students")
if not students:
return [], [], False
record = None
canonical_target = canonicalize_name(target_name)
for row in students.records:
if canonicalize_name(row.get("Name")) == canonical_target:
record = row
break
if record is None:
return [], [], False
seating = context.catalog.resolve_relationship("student_to_mudd_seat", record)
seating_entity = context.catalog.try_get("mudd_seating")
seating_origin = seating_entity.origin if seating_entity else None
facts: List[Fact] = []
for seat in seating:
facts.append(
Fact(
subject=record.get("Name", target_name),
predicate="seating",
value={
"room": seat.get("Room Number"),
"desk": seat.get("Desk Number"),
"track": seat.get("Track"),
"advisor": seat.get("Advocate/Advisor"),
"email": seat.get("Email address"),
},
source=seating_origin,
confidence=0.8,
)
)
notes: List[str] = []
if not facts:
notes.append(f"No seating assignment listed for {record['Name']}.")
return facts, notes, True