Spaces:
Sleeping
Sleeping
File size: 7,473 Bytes
c2b7a7b | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 | """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
|