from geopy.geocoders import Nominatim from geopy import distance import openrouteservice from openrouteservice.exceptions import ApiError import os from dotenv import load_dotenv load_dotenv() def get_coords_from_address(address: str) -> str: """ Converts a street address into latitude and longitude coordinates. Args: address (str): The address to search for (e.g., "Eiffel Tower, Paris"). Returns: str: A formatted string with the coordinates "Lat: XX.XXXX, Lon: YY.YYYY" or an error message if the address is not found. """ try: geolocator = Nominatim(user_agent="geocalc_mcp_app_hackathon") location = geolocator.geocode(address) if location: # If a location is found, format the latitude and longitude into a string. lat = round(location.latitude, 4) lon = round(location.longitude, 4) return f"Lat: {lat}, Lon: {lon}" else: return "Address not found. Please try being more specific. E.g., '1600 Amphitheatre Parkway, Mountain View, CA'" except Exception as e: print(f"An error occurred: {e}") return "An error occurred while trying to contact the geocoding service." def calculate_distance(lat1: float, lon1: float, lat2: float, lon2: float, unit: str = "km") -> str: """ Calculates the distance between two points on the Earth's surface using the Haversine formula. Args: lat1 (float): Latitude of the first point. lon1 (float): Longitude of the first point. lat2 (float): Latitude of the second point. lon2 (float): Longitude of the second point. unit (str, optional): Unit of measurement for the distance. Default is "km". Returns: float: The distance between the two points in kilometers. """ print("calculate_distance", lat1, lon1, lat2, lon2, unit) if unit == "km": return distance.distance((lat1, lon1), (lat2, lon2)).km else: return distance.distance((lat1, lon1), (lat2, lon2)).miles # This is now a standard, synchronous function def get_route_details(start_lat: float, start_lon: float, end_lat: float, end_lon: float, mode: str) -> str: """ Calculates route distance and duration using the OpenRouteService API. Args: start_lat (float): Latitude of the starting point. start_lon (float): Longitude of the starting point. end_lat (float): Latitude of the ending point. end_lon (float): Longitude of the ending point. mode (str): The mode of transportation (e.g., "car", "walk", "bike"). Returns: str: A string containing the route distance and duration. """ profile_map = { "car": "driving-car", "walk": "foot-walking", "bike": "cycling-road" } if mode not in profile_map: return "Invalid mode. Please use 'car', 'walk', or 'bike'." ORS_API_KEY = os.getenv("ORS_API_KEY") client_ors = openrouteservice.Client(key=ORS_API_KEY) coords = ((start_lon, start_lat), (end_lon, end_lat)) try: # Call the directions API routes = client_ors.directions( coordinates=coords, profile=profile_map[mode], ) # Extract summary data from the response summary = routes['routes'][0]['summary'] print("get_route_details summary:", summary) distance_km = round(summary['distance'] / 1000, 1) # Distance in meters duration_sec = summary['duration'] # Duration in seconds # Format the duration into hours and minutes hours = int(duration_sec // 3600) minutes = int((duration_sec % 3600) // 60) return f"The route by {mode} is {distance_km} km and will take approximately {hours} hours and {minutes} minutes." except ApiError as e: return f"Could not find a route. API Error: {e}" except Exception as e: return f"An unexpected error occurred: {e}"