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.", )