""" Demonstration script showing practical usage of the RoadTripService. This script demonstrates real-world scenarios for using the OSM Road Trip Service in the ThrillWiki application. """ from parks.models import Park from parks.services import RoadTripService import os import django # Setup Django os.environ.setdefault("DJANGO_SETTINGS_MODULE", "thrillwiki.settings") django.setup() def demo_florida_theme_park_trip(): """ Demonstrate planning a Florida theme park road trip. """ print("πŸ–οΈ Florida Theme Park Road Trip Planner") print("=" * 50) service = RoadTripService() # Define Florida theme parks with addresses florida_parks = [ ("Magic Kingdom", "Magic Kingdom Dr, Orlando, FL 32830"), ( "Universal Studios Florida", "6000 Universal Blvd, Orlando, FL 32819", ), ("SeaWorld Orlando", "7007 Sea World Dr, Orlando, FL 32821"), ("Busch Gardens Tampa", "10165 McKinley Dr, Tampa, FL 33612"), ] print("Planning trip for these Florida parks:") park_coords = {} for name, address in florida_parks: print(f"\nπŸ“ Geocoding {name}...") coords = service.geocode_address(address) if coords: park_coords[name] = coords print( f" βœ… Located at { coords.latitude:.4f}, { coords.longitude:.4f}" ) else: print(f" ❌ Could not geocode {address}") if len(park_coords) < 2: print("❌ Need at least 2 parks to plan a trip") return # Calculate distances between all parks print("\nπŸ—ΊοΈ Distance Matrix:") park_names = list(park_coords.keys()) for i, park1 in enumerate(park_names): for j, park2 in enumerate(park_names): if i < j: # Only calculate each pair once route = service.calculate_route(park_coords[park1], park_coords[park2]) if route: print(f" {park1} ↔ {park2}") print( f" { route.formatted_distance}, { route.formatted_duration}" ) # Find central park for radiating searches print("\n🎒 Parks within 100km of Magic Kingdom:") magic_kingdom_coords = park_coords.get("Magic Kingdom") if magic_kingdom_coords: for name, coords in park_coords.items(): if name != "Magic Kingdom": route = service.calculate_route(magic_kingdom_coords, coords) if route: print( f" {name}: { route.formatted_distance} ({ route.formatted_duration})" ) def demo_cross_country_road_trip(): """ Demonstrate planning a cross-country theme park road trip. """ print("\n\nπŸ‡ΊπŸ‡Έ Cross-Country Theme Park Road Trip") print("=" * 50) service = RoadTripService() # Major theme parks across the US major_parks = [ ("Disneyland", "1313 Disneyland Dr, Anaheim, CA 92802"), ("Cedar Point", "1 Cedar Point Dr, Sandusky, OH 44870"), ( "Six Flags Magic Mountain", "26101 Magic Mountain Pkwy, Valencia, CA 91355", ), ("Walt Disney World", "Walt Disney World Resort, Orlando, FL 32830"), ] print("Geocoding major US theme parks:") park_coords = {} for name, address in major_parks: print(f"\nπŸ“ {name}...") coords = service.geocode_address(address) if coords: park_coords[name] = coords print(f" βœ… {coords.latitude:.4f}, {coords.longitude:.4f}") if len(park_coords) >= 3: # Calculate an optimized route if we have DB parks print("\nπŸ›£οΈ Optimized Route Planning:") print("Note: This would work with actual Park objects from the database") # Show distances for a potential route route_order = [ "Disneyland", "Six Flags Magic Mountain", "Cedar Point", "Walt Disney World", ] total_distance = 0 total_time = 0 for i in range(len(route_order) - 1): from_park = route_order[i] to_park = route_order[i + 1] if from_park in park_coords and to_park in park_coords: route = service.calculate_route( park_coords[from_park], park_coords[to_park] ) if route: total_distance += route.distance_km total_time += route.duration_minutes print(f" {i + 1}. {from_park} β†’ {to_park}") print( f" { route.formatted_distance}, { route.formatted_duration}" ) print("\nπŸ“Š Trip Summary:") print(f" Total Distance: {total_distance:.1f}km") print( f" Total Driving Time: { total_time // 60}h { total_time % 60}min" ) print(f" Average Distance per Leg: {total_distance / 3:.1f}km") def demo_database_integration(): """ Demonstrate working with actual parks from the database. """ print("\n\nπŸ—„οΈ Database Integration Demo") print("=" * 50) service = RoadTripService() # Get parks that have location data parks_with_location = Park.objects.filter( location__point__isnull=False ).select_related("location")[:5] if not parks_with_location: print("❌ No parks with location data found in database") return print(f"Found {len(parks_with_location)} parks with location data:") for park in parks_with_location: coords = park.coordinates if coords: print(f" 🎒 {park.name}: {coords[0]:.4f}, {coords[1]:.4f}") # Demonstrate nearby park search if len(parks_with_location) >= 1: center_park = parks_with_location[0] print(f"\nπŸ” Finding parks within 500km of {center_park.name}:") nearby_parks = service.get_park_distances(center_park, radius_km=500) if nearby_parks: print(f" Found {len(nearby_parks)} nearby parks:") for result in nearby_parks[:3]: # Show top 3 park = result["park"] print( f" πŸ“ { park.name}: { result['formatted_distance']} ({ result['formatted_duration']})" ) else: print(" No nearby parks found (may need larger radius)") # Demonstrate multi-park trip planning if len(parks_with_location) >= 3: selected_parks = list(parks_with_location)[:3] print("\nπŸ—ΊοΈ Planning optimized trip for 3 parks:") for park in selected_parks: print(f" - {park.name}") trip = service.create_multi_park_trip(selected_parks) if trip: print("\nβœ… Optimized Route:") print(f" Total Distance: {trip.formatted_total_distance}") print(f" Total Duration: {trip.formatted_total_duration}") print(" Route:") for i, leg in enumerate(trip.legs, 1): print(f" {i}. {leg.from_park.name} β†’ {leg.to_park.name}") print( f" { leg.route.formatted_distance}, { leg.route.formatted_duration}" ) else: print(" ❌ Could not optimize trip route") def demo_geocoding_fallback(): """ Demonstrate geocoding parks that don't have coordinates. """ print("\n\n🌍 Geocoding Demo") print("=" * 50) service = RoadTripService() # Get parks without location data parks_without_coords = Park.objects.filter( location__point__isnull=True ).select_related("location")[:3] if not parks_without_coords: print("βœ… All parks already have coordinates") return print(f"Found {len(parks_without_coords)} parks without coordinates:") for park in parks_without_coords: print(f"\n🎒 {park.name}") if hasattr(park, "location") and park.location: location = park.location address_parts = [ park.name, location.street_address, location.city, location.state, location.country, ] address = ", ".join(part for part in address_parts if part) print(f" Address: {address}") # Try to geocode success = service.geocode_park_if_needed(park) if success: coords = park.coordinates print(f" βœ… Geocoded to: {coords[0]:.4f}, {coords[1]:.4f}") else: print(" ❌ Geocoding failed") else: print(" ❌ No location data available") def demo_cache_performance(): """ Demonstrate caching performance benefits. """ print("\n\n⚑ Cache Performance Demo") print("=" * 50) service = RoadTripService() import time # Test address for geocoding test_address = "Disneyland, Anaheim, CA" print(f"Testing cache performance with: {test_address}") # First request (cache miss) print("\n1️⃣ First request (cache miss):") start_time = time.time() coords1 = service.geocode_address(test_address) first_duration = time.time() - start_time if coords1: print(f" βœ… Result: {coords1.latitude:.4f}, {coords1.longitude:.4f}") print(f" ⏱️ Duration: {first_duration:.2f} seconds") # Second request (cache hit) print("\n2️⃣ Second request (cache hit):") start_time = time.time() coords2 = service.geocode_address(test_address) second_duration = time.time() - start_time if coords2: print(f" βœ… Result: {coords2.latitude:.4f}, {coords2.longitude:.4f}") print(f" ⏱️ Duration: {second_duration:.2f} seconds") if first_duration > second_duration: speedup = first_duration / second_duration print(f" πŸš€ Cache speedup: {speedup:.1f}x faster") if ( coords1.latitude == coords2.latitude and coords1.longitude == coords2.longitude ): print(" βœ… Results identical (cache working)") def main(): """ Run all demonstration scenarios. """ print("🎒 ThrillWiki Road Trip Service Demo") print("This demo shows practical usage scenarios for the OSM Road Trip Service") try: demo_florida_theme_park_trip() demo_cross_country_road_trip() demo_database_integration() demo_geocoding_fallback() demo_cache_performance() print("\n" + "=" * 50) print("πŸŽ‰ Demo completed successfully!") print("\nThe Road Trip Service is ready for integration into ThrillWiki!") print("\nKey Features Demonstrated:") print("βœ… Geocoding theme park addresses") print("βœ… Route calculation with distance/time") print("βœ… Multi-park trip optimization") print("βœ… Database integration with Park models") print("βœ… Caching for performance") print("βœ… Rate limiting for OSM compliance") print("βœ… Error handling and fallbacks") except Exception as e: print(f"\n❌ Demo failed with error: {e}") import traceback traceback.print_exc() if __name__ == "__main__": main()