Qiddiya-Smart-Guide / src /evaluation.py
munals's picture
Upload 33 files
214f910 verified
from __future__ import annotations
from typing import List
from .models import EvaluationResult, ItineraryPlan, UserRequest
from .data_loader import get_attraction_by_name
EVALUATION_PROMPTS: List[str] = [
"Family with young kids, relaxed pace, must do: Family River Cruise, Sky Carousel.",
"Thrill-seeker solo visitor, high intensity, must do: Falcon Coaster, Desert Drop.",
"Short half-day visit focused on nearby attractions around the hub.",
"Visitor with low walking tolerance, prefer clustered attractions.",
"Group of friends aiming to cover as many roller coasters as possible.",
"Balanced day: mix of family and thrill rides with reasonable walking.",
"Late arrival with focus on evening activities and shows.",
"Highly crowd-averse visitor: minimize queues even if walking more.",
"Accessibility-aware visitor: prefer shorter walks and longer rests.",
"Foodie visitor: prioritize dining and scenic attractions between rides.",
]
def evaluate_itinerary(request: UserRequest, plan: ItineraryPlan) -> EvaluationResult:
must_do_ids = []
for name in request.must_do_attractions:
attr = get_attraction_by_name(name)
if attr:
must_do_ids.append(attr.id)
covered = {s.attraction_id for s in plan.stops}
coverage_ratio = float(
len([mid for mid in must_do_ids if mid in covered]) / max(
len(must_do_ids), 1
)
)
fatigue = plan.total_walking_m / 5000.0 + plan.total_wait_minutes / 300.0
violations: List[str] = []
if coverage_ratio < 0.5 and must_do_ids:
violations.append("Less than half of must-do attractions scheduled.")
if fatigue > 3.0:
violations.append("Estimated fatigue is high for the planned day.")
summary = (
f"Visit from {request.start_time} to {request.end_time}, "
f"intensity={request.intensity_preference}, walking={request.walking_tolerance}, "
f"must-do={', '.join(request.must_do_attractions) or 'none'}."
)
return EvaluationResult(
visit_date=plan.visit_date,
request_summary=summary,
total_wait_minutes=plan.total_wait_minutes,
total_walking_m=plan.total_walking_m,
estimated_fatigue_score=round(fatigue, 2),
must_do_coverage_ratio=round(coverage_ratio, 2),
constraint_violations=violations,
notes="Deterministic heuristic evaluation without external models.",
)