mirror of
https://github.com/pacnpal/thrillwiki_django_no_react.git
synced 2025-12-20 10:51:09 -05:00
fix: Update import paths to use 'apps' prefix for models and services
This commit is contained in:
@@ -5,8 +5,8 @@ This script demonstrates real-world scenarios for using the OSM Road Trip Servic
|
|||||||
in the ThrillWiki application.
|
in the ThrillWiki application.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from parks.models import Park
|
from apps.parks.models import Park
|
||||||
from parks.services import RoadTripService
|
from apps.parks.services import RoadTripService
|
||||||
import os
|
import os
|
||||||
import django
|
import django
|
||||||
|
|
||||||
@@ -14,350 +14,378 @@ import django
|
|||||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "thrillwiki.settings")
|
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "thrillwiki.settings")
|
||||||
django.setup()
|
django.setup()
|
||||||
|
|
||||||
|
# New small helpers and constant to simplify functions and avoid repeated literals
|
||||||
|
MAGIC_KINGDOM = "Magic Kingdom"
|
||||||
|
|
||||||
|
|
||||||
|
def _format_coords(coords):
|
||||||
|
"""
|
||||||
|
Return (lat, lon) tuple or None for a coords object/sequence.
|
||||||
|
Accepts objects with .latitude/.longitude or indexable (lat, lon).
|
||||||
|
"""
|
||||||
|
if not coords:
|
||||||
|
return None
|
||||||
|
lat = getattr(coords, "latitude", None)
|
||||||
|
lon = getattr(coords, "longitude", None)
|
||||||
|
if lat is not None and lon is not None:
|
||||||
|
return (lat, lon)
|
||||||
|
# Fallback to indexable
|
||||||
|
try:
|
||||||
|
return (coords[0], coords[1])
|
||||||
|
except Exception:
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def _print_route_summary(route, indent=" "):
|
||||||
|
"""Safely print route summary fields if route is present."""
|
||||||
|
if not route:
|
||||||
|
return
|
||||||
|
# Use attributes with fallback to dict keys if needed
|
||||||
|
formatted_distance = getattr(route, "formatted_distance", None) or route.get(
|
||||||
|
"formatted_distance", "N/A"
|
||||||
|
) if isinstance(route, dict) else getattr(route, "formatted_distance", "N/A")
|
||||||
|
formatted_duration = getattr(route, "formatted_duration", None) or route.get(
|
||||||
|
"formatted_duration", "N/A"
|
||||||
|
) if isinstance(route, dict) else getattr(route, "formatted_duration", "N/A")
|
||||||
|
print(f"{indent}{formatted_distance}, {formatted_duration}")
|
||||||
|
|
||||||
|
|
||||||
def demo_florida_theme_park_trip():
|
def demo_florida_theme_park_trip():
|
||||||
"""
|
"""
|
||||||
Demonstrate planning a Florida theme park road trip.
|
Demonstrate planning a Florida theme park road trip.
|
||||||
"""
|
"""
|
||||||
print("🏖️ Florida Theme Park Road Trip Planner")
|
print("🏖️ Florida Theme Park Road Trip Planner")
|
||||||
print("=" * 50)
|
print("=" * 50)
|
||||||
|
|
||||||
service = RoadTripService()
|
service = RoadTripService()
|
||||||
|
|
||||||
# Define Florida theme parks with addresses
|
# Define Florida theme parks with addresses
|
||||||
florida_parks = [
|
florida_parks = [
|
||||||
("Magic Kingdom", "Magic Kingdom Dr, Orlando, FL 32830"),
|
(MAGIC_KINGDOM, "Magic Kingdom Dr, Orlando, FL 32830"),
|
||||||
(
|
("Universal Studios Florida", "6000 Universal Blvd, Orlando, FL 32819"),
|
||||||
"Universal Studios Florida",
|
("SeaWorld Orlando", "7007 Sea World Dr, Orlando, FL 32821"),
|
||||||
"6000 Universal Blvd, Orlando, FL 32819",
|
("Busch Gardens Tampa", "10165 McKinley Dr, Tampa, FL 33612"),
|
||||||
),
|
]
|
||||||
("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:")
|
print("Planning trip for these Florida parks:")
|
||||||
park_coords = {}
|
park_coords = {}
|
||||||
|
|
||||||
for name, address in florida_parks:
|
# small helper to geocode and store
|
||||||
print(f"\n📍 Geocoding {name}...")
|
def _geocode_and_store(name, address):
|
||||||
coords = service.geocode_address(address)
|
print(f"\n📍 Geocoding {name}...")
|
||||||
if coords:
|
coords = service.geocode_address(address)
|
||||||
park_coords[name] = coords
|
if coords:
|
||||||
print(
|
latlon = _format_coords(coords)
|
||||||
f" ✅ Located at {
|
if latlon:
|
||||||
coords.latitude:.4f}, {
|
park_coords[name] = coords
|
||||||
coords.longitude:.4f}"
|
print(f" ✅ Located at {latlon[0]:.4f}, {latlon[1]:.4f}")
|
||||||
)
|
return True
|
||||||
else:
|
print(f" ❌ Could not geocode {address}")
|
||||||
print(f" ❌ Could not geocode {address}")
|
return False
|
||||||
|
|
||||||
if len(park_coords) < 2:
|
for name, address in florida_parks:
|
||||||
print("❌ Need at least 2 parks to plan a trip")
|
_geocode_and_store(name, address)
|
||||||
return
|
|
||||||
|
|
||||||
# Calculate distances between all parks
|
if len(park_coords) < 2:
|
||||||
print("\n🗺️ Distance Matrix:")
|
print("❌ Need at least 2 parks to plan a trip")
|
||||||
park_names = list(park_coords.keys())
|
return
|
||||||
|
|
||||||
for i, park1 in enumerate(park_names):
|
# Calculate distances between all parks
|
||||||
for j, park2 in enumerate(park_names):
|
print("\n🗺️ Distance Matrix:")
|
||||||
if i < j: # Only calculate each pair once
|
park_names = list(park_coords.keys())
|
||||||
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
|
for i, park1 in enumerate(park_names):
|
||||||
print("\n🎢 Parks within 100km of Magic Kingdom:")
|
for j, park2 in enumerate(park_names):
|
||||||
magic_kingdom_coords = park_coords.get("Magic Kingdom")
|
if i < j: # Only calculate each pair once
|
||||||
if magic_kingdom_coords:
|
route = service.calculate_route(park_coords[park1], park_coords[park2])
|
||||||
for name, coords in park_coords.items():
|
if route:
|
||||||
if name != "Magic Kingdom":
|
print(f" {park1} ↔ {park2}")
|
||||||
route = service.calculate_route(magic_kingdom_coords, coords)
|
_print_route_summary(route, indent=" ")
|
||||||
if route:
|
|
||||||
print(
|
# Find central park for radiating searches
|
||||||
f" {name}: {
|
print(f"\n🎢 Parks within 100km of {MAGIC_KINGDOM}:")
|
||||||
route.formatted_distance} ({
|
magic_kingdom_coords = park_coords.get(MAGIC_KINGDOM)
|
||||||
route.formatted_duration})"
|
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_route_summary(route, indent=f" {name}: ")
|
||||||
|
|
||||||
|
|
||||||
def demo_cross_country_road_trip():
|
def demo_cross_country_road_trip():
|
||||||
"""
|
"""
|
||||||
Demonstrate planning a cross-country theme park road trip.
|
Demonstrate planning a cross-country theme park road trip.
|
||||||
"""
|
"""
|
||||||
print("\n\n🇺🇸 Cross-Country Theme Park Road Trip")
|
print("\n\n🇺🇸 Cross-Country Theme Park Road Trip")
|
||||||
print("=" * 50)
|
print("=" * 50)
|
||||||
|
|
||||||
service = RoadTripService()
|
service = RoadTripService()
|
||||||
|
|
||||||
# Major theme parks across the US
|
# Major theme parks across the US
|
||||||
major_parks = [
|
major_parks = [
|
||||||
("Disneyland", "1313 Disneyland Dr, Anaheim, CA 92802"),
|
("Disneyland", "1313 Disneyland Dr, Anaheim, CA 92802"),
|
||||||
("Cedar Point", "1 Cedar Point Dr, Sandusky, OH 44870"),
|
("Cedar Point", "1 Cedar Point Dr, Sandusky, OH 44870"),
|
||||||
(
|
("Six Flags Magic Mountain", "26101 Magic Mountain Pkwy, Valencia, CA 91355"),
|
||||||
"Six Flags Magic Mountain",
|
("Walt Disney World", "Walt Disney World Resort, Orlando, FL 32830"),
|
||||||
"26101 Magic Mountain Pkwy, Valencia, CA 91355",
|
]
|
||||||
),
|
|
||||||
("Walt Disney World", "Walt Disney World Resort, Orlando, FL 32830"),
|
|
||||||
]
|
|
||||||
|
|
||||||
print("Geocoding major US theme parks:")
|
print("Geocoding major US theme parks:")
|
||||||
park_coords = {}
|
park_coords = {}
|
||||||
|
|
||||||
for name, address in major_parks:
|
for name, address in major_parks:
|
||||||
print(f"\n📍 {name}...")
|
print(f"\n📍 {name}...")
|
||||||
coords = service.geocode_address(address)
|
coords = service.geocode_address(address)
|
||||||
if coords:
|
if coords:
|
||||||
park_coords[name] = coords
|
park_coords[name] = coords
|
||||||
print(f" ✅ {coords.latitude:.4f}, {coords.longitude:.4f}")
|
latlon = _format_coords(coords)
|
||||||
|
if latlon:
|
||||||
|
print(f" ✅ {latlon[0]:.4f}, {latlon[1]:.4f}")
|
||||||
|
|
||||||
if len(park_coords) >= 3:
|
if len(park_coords) >= 3:
|
||||||
# Calculate an optimized route if we have DB parks
|
# Calculate an optimized route if we have DB parks
|
||||||
print("\n🛣️ Optimized Route Planning:")
|
print("\n🛣️ Optimized Route Planning:")
|
||||||
print("Note: This would work with actual Park objects from the database")
|
print("Note: This would work with actual Park objects from the database")
|
||||||
|
|
||||||
# Show distances for a potential route
|
# Show distances for a potential route
|
||||||
route_order = [
|
route_order = [
|
||||||
"Disneyland",
|
"Disneyland",
|
||||||
"Six Flags Magic Mountain",
|
"Six Flags Magic Mountain",
|
||||||
"Cedar Point",
|
"Cedar Point",
|
||||||
"Walt Disney World",
|
"Walt Disney World",
|
||||||
]
|
]
|
||||||
total_distance = 0
|
total_distance = 0
|
||||||
total_time = 0
|
total_time = 0
|
||||||
|
|
||||||
for i in range(len(route_order) - 1):
|
for i in range(len(route_order) - 1):
|
||||||
from_park = route_order[i]
|
from_park = route_order[i]
|
||||||
to_park = route_order[i + 1]
|
to_park = route_order[i + 1]
|
||||||
|
|
||||||
if from_park in park_coords and to_park in park_coords:
|
if from_park in park_coords and to_park in park_coords:
|
||||||
route = service.calculate_route(
|
route = service.calculate_route(park_coords[from_park], park_coords[to_park])
|
||||||
park_coords[from_park], park_coords[to_park]
|
if route:
|
||||||
)
|
total_distance += getattr(route, "distance_km", 0) or route.get("distance_km", 0) if isinstance(route, dict) else getattr(route, "distance_km", 0)
|
||||||
if route:
|
total_time += getattr(route, "duration_minutes", 0) or route.get("duration_minutes", 0) if isinstance(route, dict) else getattr(route, "duration_minutes", 0)
|
||||||
total_distance += route.distance_km
|
print(f" {i + 1}. {from_park} → {to_park}")
|
||||||
total_time += route.duration_minutes
|
_print_route_summary(route, indent=" ")
|
||||||
print(f" {i + 1}. {from_park} → {to_park}")
|
|
||||||
print(
|
|
||||||
f" {
|
|
||||||
route.formatted_distance}, {
|
|
||||||
route.formatted_duration}"
|
|
||||||
)
|
|
||||||
|
|
||||||
print("\n📊 Trip Summary:")
|
print("\n📊 Trip Summary:")
|
||||||
print(f" Total Distance: {total_distance:.1f}km")
|
print(f" Total Distance: {total_distance:.1f}km")
|
||||||
print(
|
hours = total_time // 60
|
||||||
f" Total Driving Time: {
|
mins = total_time % 60
|
||||||
total_time //
|
print(f" Total Driving Time: {hours}h {mins}min")
|
||||||
60}h {
|
# avoid division by zero
|
||||||
total_time %
|
legs = max(1, len(route_order) - 1)
|
||||||
60}min"
|
print(f" Average Distance per Leg: {total_distance / legs:.1f}km")
|
||||||
)
|
|
||||||
print(f" Average Distance per Leg: {total_distance / 3:.1f}km")
|
|
||||||
|
|
||||||
|
|
||||||
def demo_database_integration():
|
def demo_database_integration():
|
||||||
"""
|
"""
|
||||||
Demonstrate working with actual parks from the database.
|
Demonstrate working with actual parks from the database.
|
||||||
"""
|
"""
|
||||||
print("\n\n🗄️ Database Integration Demo")
|
print("\n\n🗄️ Database Integration Demo")
|
||||||
print("=" * 50)
|
print("=" * 50)
|
||||||
|
|
||||||
service = RoadTripService()
|
service = RoadTripService()
|
||||||
|
|
||||||
# Get parks that have location data
|
# Get parks that have location data
|
||||||
parks_with_location = Park.objects.filter(
|
parks_with_location = Park.objects.filter(location__point__isnull=False).select_related("location")[:5]
|
||||||
location__point__isnull=False
|
|
||||||
).select_related("location")[:5]
|
|
||||||
|
|
||||||
if not parks_with_location:
|
if not parks_with_location:
|
||||||
print("❌ No parks with location data found in database")
|
print("❌ No parks with location data found in database")
|
||||||
return
|
return
|
||||||
|
|
||||||
print(f"Found {len(parks_with_location)} parks with location data:")
|
print(f"Found {len(parks_with_location)} parks with location data:")
|
||||||
|
|
||||||
for park in parks_with_location:
|
for park in parks_with_location:
|
||||||
coords = park.coordinates
|
coords = getattr(park, "coordinates", None)
|
||||||
if coords:
|
latlon = _format_coords(coords)
|
||||||
print(f" 🎢 {park.name}: {coords[0]:.4f}, {coords[1]:.4f}")
|
if latlon:
|
||||||
|
print(f" 🎢 {park.name}: {latlon[0]:.4f}, {latlon[1]:.4f}")
|
||||||
|
|
||||||
# Demonstrate nearby park search
|
# Demonstrate nearby park search
|
||||||
if len(parks_with_location) >= 1:
|
if len(parks_with_location) >= 1:
|
||||||
center_park = parks_with_location[0]
|
center_park = parks_with_location[0]
|
||||||
print(f"\n🔍 Finding parks within 500km of {center_park.name}:")
|
print(f"\n🔍 Finding parks within 500km of {center_park.name}:")
|
||||||
|
|
||||||
nearby_parks = service.get_park_distances(center_park, radius_km=500)
|
nearby_parks = service.get_park_distances(center_park, radius_km=500)
|
||||||
|
|
||||||
if nearby_parks:
|
if nearby_parks:
|
||||||
print(f" Found {len(nearby_parks)} nearby parks:")
|
print(f" Found {len(nearby_parks)} nearby parks:")
|
||||||
for result in nearby_parks[:3]: # Show top 3
|
for result in nearby_parks[:3]: # Show top 3
|
||||||
park = result["park"]
|
park = result.get("park") if isinstance(result, dict) else getattr(result, "park", None)
|
||||||
print(
|
# use safe formatted strings
|
||||||
f" 📍 {
|
formatted_distance = result.get("formatted_distance", "N/A") if isinstance(result, dict) else getattr(result, "formatted_distance", "N/A")
|
||||||
park.name}: {
|
formatted_duration = result.get("formatted_duration", "N/A") if isinstance(result, dict) else getattr(result, "formatted_duration", "N/A")
|
||||||
result['formatted_distance']} ({
|
if park:
|
||||||
result['formatted_duration']})"
|
print(f" 📍 {park.name}: {formatted_distance} ({formatted_duration})")
|
||||||
)
|
else:
|
||||||
else:
|
print(" No nearby parks found (may need larger radius)")
|
||||||
print(" No nearby parks found (may need larger radius)")
|
|
||||||
|
|
||||||
# Demonstrate multi-park trip planning
|
# Demonstrate multi-park trip planning
|
||||||
if len(parks_with_location) >= 3:
|
if len(parks_with_location) >= 3:
|
||||||
selected_parks = list(parks_with_location)[:3]
|
selected_parks = list(parks_with_location)[:3]
|
||||||
print("\n🗺️ Planning optimized trip for 3 parks:")
|
print("\n🗺️ Planning optimized trip for 3 parks:")
|
||||||
|
|
||||||
for park in selected_parks:
|
for park in selected_parks:
|
||||||
print(f" - {park.name}")
|
print(f" - {park.name}")
|
||||||
|
|
||||||
trip = service.create_multi_park_trip(selected_parks)
|
trip = service.create_multi_park_trip(selected_parks)
|
||||||
|
|
||||||
if trip:
|
if trip:
|
||||||
print("\n✅ Optimized Route:")
|
print("\n✅ Optimized Route:")
|
||||||
print(f" Total Distance: {trip.formatted_total_distance}")
|
print(f" Total Distance: {getattr(trip, 'formatted_total_distance', 'N/A')}")
|
||||||
print(f" Total Duration: {trip.formatted_total_duration}")
|
print(f" Total Duration: {getattr(trip, 'formatted_total_duration', 'N/A')}")
|
||||||
print(" Route:")
|
print(" Route:")
|
||||||
|
|
||||||
for i, leg in enumerate(trip.legs, 1):
|
for i, leg in enumerate(getattr(trip, "legs", []) or [], 1):
|
||||||
print(f" {i}. {leg.from_park.name} → {leg.to_park.name}")
|
from_park = getattr(leg, "from_park", None)
|
||||||
print(
|
to_park = getattr(leg, "to_park", None)
|
||||||
f" {
|
route = getattr(leg, "route", None)
|
||||||
leg.route.formatted_distance}, {
|
if from_park and to_park:
|
||||||
leg.route.formatted_duration}"
|
print(f" {i}. {from_park.name} → {to_park.name}")
|
||||||
)
|
_print_route_summary(route, indent=" ")
|
||||||
else:
|
else:
|
||||||
print(" ❌ Could not optimize trip route")
|
print(" ❌ Could not optimize trip route")
|
||||||
|
|
||||||
|
|
||||||
def demo_geocoding_fallback():
|
def demo_geocoding_fallback():
|
||||||
"""
|
"""
|
||||||
Demonstrate geocoding parks that don't have coordinates.
|
Demonstrate geocoding parks that don't have coordinates.
|
||||||
"""
|
"""
|
||||||
print("\n\n🌍 Geocoding Demo")
|
print("\n\n🌍 Geocoding Demo")
|
||||||
print("=" * 50)
|
print("=" * 50)
|
||||||
|
|
||||||
service = RoadTripService()
|
service = RoadTripService()
|
||||||
|
|
||||||
# Get parks without location data
|
# Get parks without location data
|
||||||
parks_without_coords = Park.objects.filter(
|
parks_without_coords = Park.objects.filter(location__point__isnull=True).select_related("location")[:3]
|
||||||
location__point__isnull=True
|
|
||||||
).select_related("location")[:3]
|
|
||||||
|
|
||||||
if not parks_without_coords:
|
if not parks_without_coords:
|
||||||
print("✅ All parks already have coordinates")
|
print("✅ All parks already have coordinates")
|
||||||
return
|
return
|
||||||
|
|
||||||
print(f"Found {len(parks_without_coords)} parks without coordinates:")
|
print(f"Found {len(parks_without_coords)} parks without coordinates:")
|
||||||
|
|
||||||
for park in parks_without_coords:
|
for park in parks_without_coords:
|
||||||
print(f"\n🎢 {park.name}")
|
print(f"\n🎢 {park.name}")
|
||||||
|
|
||||||
if hasattr(park, "location") and park.location:
|
location = getattr(park, "location", None)
|
||||||
location = park.location
|
if location:
|
||||||
address_parts = [
|
# use getattr to avoid attribute errors
|
||||||
park.name,
|
address_parts = [
|
||||||
location.street_address,
|
getattr(park, "name", None),
|
||||||
location.city,
|
getattr(location, "street_address", None),
|
||||||
location.state,
|
getattr(location, "city", None),
|
||||||
location.country,
|
getattr(location, "state", None),
|
||||||
]
|
getattr(location, "country", None),
|
||||||
address = ", ".join(part for part in address_parts if part)
|
]
|
||||||
print(f" Address: {address}")
|
address = ", ".join(part for part in address_parts if part)
|
||||||
|
print(f" Address: {address}")
|
||||||
|
|
||||||
# Try to geocode
|
# Try to geocode
|
||||||
success = service.geocode_park_if_needed(park)
|
success = service.geocode_park_if_needed(park)
|
||||||
if success:
|
if success:
|
||||||
coords = park.coordinates
|
coords = getattr(park, "coordinates", None)
|
||||||
print(f" ✅ Geocoded to: {coords[0]:.4f}, {coords[1]:.4f}")
|
latlon = _format_coords(coords)
|
||||||
else:
|
if latlon:
|
||||||
print(" ❌ Geocoding failed")
|
print(f" ✅ Geocoded to: {latlon[0]:.4f}, {latlon[1]:.4f}")
|
||||||
else:
|
else:
|
||||||
print(" ❌ No location data available")
|
print(" ✅ Geocoded but coordinates unavailable")
|
||||||
|
else:
|
||||||
|
print(" ❌ Geocoding failed")
|
||||||
|
else:
|
||||||
|
print(" ❌ No location data available")
|
||||||
|
|
||||||
|
|
||||||
def demo_cache_performance():
|
def demo_cache_performance():
|
||||||
"""
|
"""
|
||||||
Demonstrate caching performance benefits.
|
Demonstrate caching performance benefits.
|
||||||
"""
|
"""
|
||||||
print("\n\n⚡ Cache Performance Demo")
|
print("\n\n⚡ Cache Performance Demo")
|
||||||
print("=" * 50)
|
print("=" * 50)
|
||||||
|
|
||||||
service = RoadTripService()
|
service = RoadTripService()
|
||||||
|
|
||||||
import time
|
import time
|
||||||
|
|
||||||
# Test address for geocoding
|
# Test address for geocoding
|
||||||
test_address = "Disneyland, Anaheim, CA"
|
test_address = "Disneyland, Anaheim, CA"
|
||||||
|
|
||||||
print(f"Testing cache performance with: {test_address}")
|
print(f"Testing cache performance with: {test_address}")
|
||||||
|
|
||||||
# First request (cache miss)
|
# First request (cache miss)
|
||||||
print("\n1️⃣ First request (cache miss):")
|
print("\n1️⃣ First request (cache miss):")
|
||||||
start_time = time.time()
|
start_time = time.time()
|
||||||
coords1 = service.geocode_address(test_address)
|
coords1 = service.geocode_address(test_address)
|
||||||
first_duration = time.time() - start_time
|
first_duration = time.time() - start_time
|
||||||
|
|
||||||
if coords1:
|
if coords1:
|
||||||
print(f" ✅ Result: {coords1.latitude:.4f}, {coords1.longitude:.4f}")
|
latlon = _format_coords(coords1)
|
||||||
print(f" ⏱️ Duration: {first_duration:.2f} seconds")
|
if latlon:
|
||||||
|
print(f" ✅ Result: {latlon[0]:.4f}, {latlon[1]:.4f}")
|
||||||
|
else:
|
||||||
|
print(" ✅ Result obtained")
|
||||||
|
print(f" ⏱️ Duration: {first_duration:.2f} seconds")
|
||||||
|
|
||||||
# Second request (cache hit)
|
# Second request (cache hit)
|
||||||
print("\n2️⃣ Second request (cache hit):")
|
print("\n2️⃣ Second request (cache hit):")
|
||||||
start_time = time.time()
|
start_time = time.time()
|
||||||
coords2 = service.geocode_address(test_address)
|
coords2 = service.geocode_address(test_address)
|
||||||
second_duration = time.time() - start_time
|
second_duration = time.time() - start_time
|
||||||
|
|
||||||
if coords2:
|
if coords2:
|
||||||
print(f" ✅ Result: {coords2.latitude:.4f}, {coords2.longitude:.4f}")
|
latlon2 = _format_coords(coords2)
|
||||||
print(f" ⏱️ Duration: {second_duration:.2f} seconds")
|
if latlon2:
|
||||||
|
print(f" ✅ Result: {latlon2[0]:.4f}, {latlon2[1]:.4f}")
|
||||||
|
else:
|
||||||
|
print(" ✅ Result obtained")
|
||||||
|
print(f" ⏱️ Duration: {second_duration:.2f} seconds")
|
||||||
|
|
||||||
if first_duration > second_duration:
|
if first_duration > second_duration and second_duration > 0:
|
||||||
speedup = first_duration / second_duration
|
speedup = first_duration / second_duration
|
||||||
print(f" 🚀 Cache speedup: {speedup:.1f}x faster")
|
print(f" 🚀 Cache speedup: {speedup:.1f}x faster")
|
||||||
|
|
||||||
if (
|
# Compare coordinates if both present
|
||||||
coords1.latitude == coords2.latitude
|
if coords1 and coords2:
|
||||||
and coords1.longitude == coords2.longitude
|
latlon1 = _format_coords(coords1)
|
||||||
):
|
latlon2 = _format_coords(coords2)
|
||||||
print(" ✅ Results identical (cache working)")
|
if latlon1 and latlon2 and latlon1 == latlon2:
|
||||||
|
print(" ✅ Results identical (cache working)")
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
"""
|
"""
|
||||||
Run all demonstration scenarios.
|
Run all demonstration scenarios.
|
||||||
"""
|
"""
|
||||||
print("🎢 ThrillWiki Road Trip Service Demo")
|
print("🎢 ThrillWiki Road Trip Service Demo")
|
||||||
print("This demo shows practical usage scenarios for the OSM Road Trip Service")
|
print("This demo shows practical usage scenarios for the OSM Road Trip Service")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
demo_florida_theme_park_trip()
|
demo_florida_theme_park_trip()
|
||||||
demo_cross_country_road_trip()
|
demo_cross_country_road_trip()
|
||||||
demo_database_integration()
|
demo_database_integration()
|
||||||
demo_geocoding_fallback()
|
demo_geocoding_fallback()
|
||||||
demo_cache_performance()
|
demo_cache_performance()
|
||||||
|
|
||||||
print("\n" + "=" * 50)
|
print("\n" + "=" * 50)
|
||||||
print("🎉 Demo completed successfully!")
|
print("🎉 Demo completed successfully!")
|
||||||
print("\nThe Road Trip Service is ready for integration into ThrillWiki!")
|
print("\nThe Road Trip Service is ready for integration into ThrillWiki!")
|
||||||
print("\nKey Features Demonstrated:")
|
print("\nKey Features Demonstrated:")
|
||||||
print("✅ Geocoding theme park addresses")
|
print("✅ Geocoding theme park addresses")
|
||||||
print("✅ Route calculation with distance/time")
|
print("✅ Route calculation with distance/time")
|
||||||
print("✅ Multi-park trip optimization")
|
print("✅ Multi-park trip optimization")
|
||||||
print("✅ Database integration with Park models")
|
print("✅ Database integration with Park models")
|
||||||
print("✅ Caching for performance")
|
print("✅ Caching for performance")
|
||||||
print("✅ Rate limiting for OSM compliance")
|
print("✅ Rate limiting for OSM compliance")
|
||||||
print("✅ Error handling and fallbacks")
|
print("✅ Error handling and fallbacks")
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"\n❌ Demo failed with error: {e}")
|
print(f"\n❌ Demo failed with error: {e}")
|
||||||
import traceback
|
import traceback
|
||||||
|
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
"""
|
"""
|
||||||
Basic test script to verify RideLocation and CompanyHeadquarters models work correctly.
|
Basic test script to verify RideLocation and CompanyHeadquarters models work correctly.
|
||||||
"""
|
"""
|
||||||
from rides.models import Ride, RideLocation
|
from apps.rides.models import Ride, RideLocation
|
||||||
from parks.models import Company, CompanyHeadquarters
|
from apps.parks.models import Company, CompanyHeadquarters
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import django
|
import django
|
||||||
@@ -23,11 +23,11 @@ def test_company_headquarters():
|
|||||||
print("⚠️ No existing companies found, skipping CompanyHeadquarters test")
|
print("⚠️ No existing companies found, skipping CompanyHeadquarters test")
|
||||||
return None, None
|
return None, None
|
||||||
|
|
||||||
# Check if headquarters already exist
|
# Check if headquarters already exist (use queryset lookup to avoid relying on a reverse attribute name)
|
||||||
try:
|
headquarters = CompanyHeadquarters.objects.filter(company=existing_company).first()
|
||||||
headquarters = existing_company.headquarters
|
if headquarters:
|
||||||
print(f"✓ Found existing headquarters: {headquarters}")
|
print(f"✓ Found existing headquarters: {headquarters}")
|
||||||
except CompanyHeadquarters.DoesNotExist:
|
else:
|
||||||
# Create headquarters for existing company
|
# Create headquarters for existing company
|
||||||
headquarters = CompanyHeadquarters.objects.create(
|
headquarters = CompanyHeadquarters.objects.create(
|
||||||
company=existing_company,
|
company=existing_company,
|
||||||
@@ -53,7 +53,13 @@ def test_ride_location():
|
|||||||
# First, we need a ride - let's check if any exist
|
# First, we need a ride - let's check if any exist
|
||||||
if Ride.objects.exists():
|
if Ride.objects.exists():
|
||||||
ride = Ride.objects.first()
|
ride = Ride.objects.first()
|
||||||
print(f"✓ Using existing ride: {ride.name}")
|
# Safely access the ride's name in case static analysis or runtime sees None/no attribute.
|
||||||
|
ride_name = getattr(ride, "name", None) if ride is not None else None
|
||||||
|
if ride_name:
|
||||||
|
print(f"✓ Using existing ride: {ride_name}")
|
||||||
|
else:
|
||||||
|
# Fall back to repr of the ride object to avoid AttributeError
|
||||||
|
print(f"✓ Using existing ride: {ride!r}")
|
||||||
else:
|
else:
|
||||||
print("! No rides found in database - skipping RideLocation test")
|
print("! No rides found in database - skipping RideLocation test")
|
||||||
return None, None
|
return None, None
|
||||||
@@ -93,9 +99,9 @@ def cleanup_test_data(company=None, headquarters=None, ride_location=None):
|
|||||||
headquarters.delete()
|
headquarters.delete()
|
||||||
print("✓ Deleted test headquarters")
|
print("✓ Deleted test headquarters")
|
||||||
|
|
||||||
if company:
|
# Do not delete an existing company record discovered in the database.
|
||||||
company.delete()
|
# Tests should avoid removing production/existing data. If a test created a Company
|
||||||
print("✓ Deleted test company")
|
# instance explicitly, add logic to delete it here (not implemented by default).
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ def test_trigger_endpoint(token):
|
|||||||
"Content-Type": "application/json"
|
"Content-Type": "application/json"
|
||||||
}
|
}
|
||||||
|
|
||||||
print(f"\n🚀 Testing manual trigger endpoint...")
|
print("\n🚀 Testing manual trigger endpoint...")
|
||||||
print(f"URL: {trigger_url}")
|
print(f"URL: {trigger_url}")
|
||||||
|
|
||||||
response = requests.post(trigger_url, headers=headers)
|
response = requests.post(trigger_url, headers=headers)
|
||||||
@@ -72,7 +72,7 @@ def test_trigger_endpoint(token):
|
|||||||
|
|
||||||
def test_trending_endpoints():
|
def test_trending_endpoints():
|
||||||
"""Test the trending content endpoints to see the results."""
|
"""Test the trending content endpoints to see the results."""
|
||||||
print(f"\n📊 Testing trending content endpoints...")
|
print("\n📊 Testing trending content endpoints...")
|
||||||
|
|
||||||
# Test trending content endpoint
|
# Test trending content endpoint
|
||||||
trending_url = f"{BASE_URL}/api/v1/trending/content/"
|
trending_url = f"{BASE_URL}/api/v1/trending/content/"
|
||||||
@@ -109,7 +109,7 @@ def test_trending_endpoints():
|
|||||||
|
|
||||||
# Show the newly_opened structure to verify our changes
|
# Show the newly_opened structure to verify our changes
|
||||||
if data.get('newly_opened'):
|
if data.get('newly_opened'):
|
||||||
print(f"\n🎢 First newly opened item structure:")
|
print("\n🎢 First newly opened item structure:")
|
||||||
first_item = data['newly_opened'][0]
|
first_item = data['newly_opened'][0]
|
||||||
print(f" Name: {first_item.get('name')}")
|
print(f" Name: {first_item.get('name')}")
|
||||||
# Should be park name, not location
|
# Should be park name, not location
|
||||||
@@ -124,12 +124,12 @@ def test_trending_endpoints():
|
|||||||
print(
|
print(
|
||||||
f" ❌ ERROR: 'location' field still present: {first_item['location']}")
|
f" ❌ ERROR: 'location' field still present: {first_item['location']}")
|
||||||
else:
|
else:
|
||||||
print(f" ✅ SUCCESS: 'location' field removed as requested")
|
print(" ✅ SUCCESS: 'location' field removed as requested")
|
||||||
|
|
||||||
|
|
||||||
def test_unauthorized_access():
|
def test_unauthorized_access():
|
||||||
"""Test that non-admin users cannot access the trigger endpoint."""
|
"""Test that non-admin users cannot access the trigger endpoint."""
|
||||||
print(f"\n🔒 Testing unauthorized access...")
|
print("\n🔒 Testing unauthorized access...")
|
||||||
|
|
||||||
trigger_url = f"{BASE_URL}/api/v1/trending/calculate/"
|
trigger_url = f"{BASE_URL}/api/v1/trending/calculate/"
|
||||||
|
|
||||||
@@ -169,7 +169,7 @@ def main():
|
|||||||
trigger_result = test_trigger_endpoint(token)
|
trigger_result = test_trigger_endpoint(token)
|
||||||
|
|
||||||
if trigger_result:
|
if trigger_result:
|
||||||
print(f"\n⏳ Waiting 10 seconds for tasks to process...")
|
print("\n⏳ Waiting 10 seconds for tasks to process...")
|
||||||
time.sleep(10)
|
time.sleep(10)
|
||||||
|
|
||||||
# Test the trending endpoints to see results
|
# Test the trending endpoints to see results
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
"""
|
"""
|
||||||
Test script for ParkLocation model functionality
|
Test script for ParkLocation model functionality
|
||||||
"""
|
"""
|
||||||
from parks.models import Park, ParkLocation, Company
|
from apps.parks.models import Park, ParkLocation, Company
|
||||||
import os
|
import os
|
||||||
import django
|
import django
|
||||||
|
|
||||||
|
|||||||
@@ -9,14 +9,21 @@ This script tests all functionality of the OSM Road Trip Service including:
|
|||||||
- Integration with existing Park models
|
- Integration with existing Park models
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
from typing import cast
|
||||||
|
from apps.parks.services import RoadTripService
|
||||||
|
from apps.parks.services.roadtrip import Coordinates
|
||||||
|
from apps.parks.models import Park
|
||||||
from django.core.cache import cache
|
from django.core.cache import cache
|
||||||
from parks.models import Park
|
|
||||||
from parks.services.roadtrip import Coordinates
|
|
||||||
from parks.services import RoadTripService
|
|
||||||
import os
|
import os
|
||||||
|
import sys
|
||||||
import django
|
import django
|
||||||
|
|
||||||
# Setup Django
|
# Ensure project root is on sys.path so imports like `parks.models` resolve.
|
||||||
|
PROJECT_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||||
|
if PROJECT_ROOT not in sys.path:
|
||||||
|
sys.path.insert(0, PROJECT_ROOT)
|
||||||
|
|
||||||
|
# Setup Django before importing project modules that depend on settings.
|
||||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "thrillwiki.settings")
|
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "thrillwiki.settings")
|
||||||
django.setup()
|
django.setup()
|
||||||
|
|
||||||
@@ -40,16 +47,13 @@ def test_geocoding():
|
|||||||
print(f"\nGeocoding: {address}")
|
print(f"\nGeocoding: {address}")
|
||||||
coords = service.geocode_address(address)
|
coords = service.geocode_address(address)
|
||||||
if coords:
|
if coords:
|
||||||
print(
|
# fixed: single-line f-string formatting
|
||||||
f" ✅ Success: {
|
print(f" ✅ Success: {coords.latitude:.6f}, {coords.longitude:.6f}")
|
||||||
coords.latitude:.6f}, {
|
|
||||||
coords.longitude:.6f}"
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
print(f" ❌ Failed")
|
print(" ❌ Failed")
|
||||||
|
|
||||||
# Test cache functionality
|
# Test cache functionality
|
||||||
print(f"\nTesting cache...")
|
print("\nTesting cache...")
|
||||||
coords1 = service.geocode_address("Cedar Point, Sandusky, Ohio")
|
coords1 = service.geocode_address("Cedar Point, Sandusky, Ohio")
|
||||||
coords2 = service.geocode_address("Cedar Point, Sandusky, Ohio")
|
coords2 = service.geocode_address("Cedar Point, Sandusky, Ohio")
|
||||||
if coords1 and coords2:
|
if coords1 and coords2:
|
||||||
@@ -66,30 +70,30 @@ def test_route_calculation():
|
|||||||
cedar_point = Coordinates(41.4793, -82.6833)
|
cedar_point = Coordinates(41.4793, -82.6833)
|
||||||
magic_kingdom = Coordinates(28.4177, -81.5812)
|
magic_kingdom = Coordinates(28.4177, -81.5812)
|
||||||
|
|
||||||
print(f"Calculating route from Cedar Point to Magic Kingdom...")
|
print("Calculating route from Cedar Point to Magic Kingdom...")
|
||||||
route = service.calculate_route(cedar_point, magic_kingdom)
|
route = service.calculate_route(cedar_point, magic_kingdom)
|
||||||
|
|
||||||
if route:
|
if route:
|
||||||
print(f" ✅ Success:")
|
print(" ✅ Success:")
|
||||||
print(f" Distance: {route.formatted_distance}")
|
print(f" Distance: {route.formatted_distance}")
|
||||||
print(f" Duration: {route.formatted_duration}")
|
print(f" Duration: {route.formatted_duration}")
|
||||||
print(f" Geometry: {'Yes' if route.geometry else 'No'}")
|
print(f" Geometry: {'Yes' if route.geometry else 'No'}")
|
||||||
else:
|
else:
|
||||||
print(f" ❌ Failed")
|
print(" ❌ Failed")
|
||||||
|
|
||||||
# Test short distance (should use OSRM)
|
# Test short distance (should use OSRM)
|
||||||
disneyland = Coordinates(33.8121, -117.9190)
|
disneyland = Coordinates(33.8121, -117.9190)
|
||||||
knotts = Coordinates(33.8442, -118.0000)
|
knotts = Coordinates(33.8442, -118.0000)
|
||||||
|
|
||||||
print(f"\nCalculating route from Disneyland to Knott's Berry Farm...")
|
print("\nCalculating route from Disneyland to Knott's Berry Farm...")
|
||||||
route = service.calculate_route(disneyland, knotts)
|
route = service.calculate_route(disneyland, knotts)
|
||||||
|
|
||||||
if route:
|
if route:
|
||||||
print(f" ✅ Success:")
|
print(" ✅ Success:")
|
||||||
print(f" Distance: {route.formatted_distance}")
|
print(f" Distance: {route.formatted_distance}")
|
||||||
print(f" Duration: {route.formatted_duration}")
|
print(f" Duration: {route.formatted_duration}")
|
||||||
else:
|
else:
|
||||||
print(f" ❌ Failed")
|
print(" ❌ Failed")
|
||||||
|
|
||||||
|
|
||||||
def test_park_integration():
|
def test_park_integration():
|
||||||
@@ -108,24 +112,25 @@ def test_park_integration():
|
|||||||
print(f"Found {len(parks)} parks to test with:")
|
print(f"Found {len(parks)} parks to test with:")
|
||||||
for park in parks:
|
for park in parks:
|
||||||
print(f" - {park.name}")
|
print(f" - {park.name}")
|
||||||
if hasattr(park, "location") and park.location:
|
# Use getattr to safely access the optional related attribute and avoid static type warnings.
|
||||||
coords = park.coordinates
|
location = getattr(park, "location", None)
|
||||||
|
if location:
|
||||||
|
coords = getattr(park, "coordinates", None)
|
||||||
if coords:
|
if coords:
|
||||||
print(f" 📍 {coords[0]:.4f}, {coords[1]:.4f}")
|
print(f" 📍 {coords[0]:.4f}, {coords[1]:.4f}")
|
||||||
else:
|
else:
|
||||||
print(f" 📍 No coordinates, will try to geocode...")
|
print(" 📍 No coordinates, will try to geocode...")
|
||||||
success = service.geocode_park_if_needed(park)
|
success = service.geocode_park_if_needed(park)
|
||||||
if success:
|
if success:
|
||||||
coords = park.coordinates
|
coords = getattr(park, "coordinates", None)
|
||||||
print(
|
if coords:
|
||||||
f" ✅ Geocoded to: {
|
print(f" ✅ Geocoded to: {coords[0]:.4f}, {coords[1]:.4f}")
|
||||||
coords[0]:.4f}, {
|
else:
|
||||||
coords[1]:.4f}"
|
print(" ❌ Geocoding succeeded but coordinates still missing")
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
print(f" ❌ Geocoding failed")
|
print(" ❌ Geocoding failed")
|
||||||
else:
|
else:
|
||||||
print(f" ❌ No location data")
|
print(" ❌ No location data")
|
||||||
|
|
||||||
|
|
||||||
def test_nearby_parks():
|
def test_nearby_parks():
|
||||||
@@ -153,13 +158,9 @@ def test_nearby_parks():
|
|||||||
for result in nearby_parks[:5]: # Show first 5
|
for result in nearby_parks[:5]: # Show first 5
|
||||||
park = result["park"]
|
park = result["park"]
|
||||||
print(
|
print(
|
||||||
f" {
|
f" {park.name}: {result['formatted_distance']}, {result['formatted_duration']}")
|
||||||
park.name}: {
|
|
||||||
result['formatted_distance']}, {
|
|
||||||
result['formatted_duration']}"
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
print(f" ❌ No nearby parks found")
|
print(" ❌ No nearby parks found")
|
||||||
|
|
||||||
|
|
||||||
def test_route_park_discovery():
|
def test_route_park_discovery():
|
||||||
@@ -180,11 +181,7 @@ def test_route_park_discovery():
|
|||||||
start_park = parks_with_location[0]
|
start_park = parks_with_location[0]
|
||||||
end_park = parks_with_location[1]
|
end_park = parks_with_location[1]
|
||||||
|
|
||||||
print(
|
print(f"Finding parks along route from {start_park.name} to {end_park.name}...")
|
||||||
f"Finding parks along route from {
|
|
||||||
start_park.name} to {
|
|
||||||
end_park.name}..."
|
|
||||||
)
|
|
||||||
|
|
||||||
parks_along_route = service.find_parks_along_route(
|
parks_along_route = service.find_parks_along_route(
|
||||||
start_park, end_park, max_detour_km=100
|
start_park, end_park, max_detour_km=100
|
||||||
@@ -195,7 +192,7 @@ def test_route_park_discovery():
|
|||||||
for park in parks_along_route[:3]: # Show first 3
|
for park in parks_along_route[:3]: # Show first 3
|
||||||
print(f" - {park.name}")
|
print(f" - {park.name}")
|
||||||
else:
|
else:
|
||||||
print(f" ❌ No parks found along route")
|
print(" ❌ No parks found along route")
|
||||||
|
|
||||||
|
|
||||||
def test_multi_park_trip():
|
def test_multi_park_trip():
|
||||||
@@ -221,19 +218,16 @@ def test_multi_park_trip():
|
|||||||
trip = service.create_multi_park_trip(parks_list)
|
trip = service.create_multi_park_trip(parks_list)
|
||||||
|
|
||||||
if trip:
|
if trip:
|
||||||
print(f" ✅ Trip planned successfully:")
|
print(" ✅ Trip planned successfully:")
|
||||||
print(f" Total Distance: {trip.formatted_total_distance}")
|
print(f" Total Distance: {trip.formatted_total_distance}")
|
||||||
print(f" Total Duration: {trip.formatted_total_duration}")
|
print(f" Total Duration: {trip.formatted_total_duration}")
|
||||||
print(f" Route:")
|
print(" Route:")
|
||||||
for i, leg in enumerate(trip.legs, 1):
|
for i, leg in enumerate(trip.legs, 1):
|
||||||
print(f" {i}. {leg.from_park.name} → {leg.to_park.name}")
|
print(f" {i}. {leg.from_park.name} → {leg.to_park.name}")
|
||||||
print(
|
print(
|
||||||
f" {
|
f" {leg.route.formatted_distance}, {leg.route.formatted_duration}")
|
||||||
leg.route.formatted_distance}, {
|
|
||||||
leg.route.formatted_duration}"
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
print(f" ❌ Trip planning failed")
|
print(" ❌ Trip planning failed")
|
||||||
|
|
||||||
|
|
||||||
def test_error_handling():
|
def test_error_handling():
|
||||||
@@ -249,28 +243,28 @@ def test_error_handling():
|
|||||||
|
|
||||||
route = service.calculate_route(invalid_coords, valid_coords)
|
route = service.calculate_route(invalid_coords, valid_coords)
|
||||||
if route:
|
if route:
|
||||||
print(
|
print(f" ⚠️ Got route with invalid coords: {route.formatted_distance}")
|
||||||
f" ⚠️ Got route with invalid coords: {
|
|
||||||
route.formatted_distance}"
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
print(f" ✅ Correctly handled invalid coordinates")
|
print(" ✅ Correctly handled invalid coordinates")
|
||||||
|
|
||||||
# Test with empty address
|
# Test with empty address
|
||||||
print("Testing empty address geocoding...")
|
print("Testing empty address geocoding...")
|
||||||
coords = service.geocode_address("")
|
coords = service.geocode_address("")
|
||||||
if coords:
|
if coords:
|
||||||
print(f" ⚠️ Got coordinates for empty address")
|
print(" ⚠️ Got coordinates for empty address")
|
||||||
else:
|
else:
|
||||||
print(f" ✅ Correctly handled empty address")
|
print(" ✅ Correctly handled empty address")
|
||||||
|
|
||||||
# Test with None values
|
# Test with None values
|
||||||
print("Testing None coordinates...")
|
print("Testing None coordinates...")
|
||||||
route = service.calculate_route(None, valid_coords)
|
# cast(None, Coordinates) is used only to satisfy static typing checks
|
||||||
|
# while keeping the runtime intent of passing None to the service.
|
||||||
|
route = service.calculate_route(cast(Coordinates, None), valid_coords)
|
||||||
|
|
||||||
if route:
|
if route:
|
||||||
print(f" ⚠️ Got route with None coordinates")
|
print(" ⚠️ Got route with None coordinates")
|
||||||
else:
|
else:
|
||||||
print(f" ✅ Correctly handled None coordinates")
|
print(" ✅ Correctly handled None coordinates")
|
||||||
|
|
||||||
|
|
||||||
def test_rate_limiting():
|
def test_rate_limiting():
|
||||||
@@ -294,19 +288,15 @@ def test_rate_limiting():
|
|||||||
for address in addresses:
|
for address in addresses:
|
||||||
coords = service.geocode_address(address)
|
coords = service.geocode_address(address)
|
||||||
if coords:
|
if coords:
|
||||||
print(
|
print(f" ✅ {address}: {coords.latitude:.4f}, {coords.longitude:.4f}")
|
||||||
f" ✅ {address}: {
|
|
||||||
coords.latitude:.4f}, {
|
|
||||||
coords.longitude:.4f}"
|
|
||||||
)
|
|
||||||
|
|
||||||
elapsed = time.time() - start_time
|
elapsed = time.time() - start_time
|
||||||
print(f" Total time for 3 requests: {elapsed:.2f} seconds")
|
print(f" Total time for 3 requests: {elapsed:.2f} seconds")
|
||||||
|
|
||||||
if elapsed >= 2.0: # Should take at least 2 seconds with 1 req/sec limit
|
if elapsed >= 2.0: # Should take at least 2 seconds with 1 req/sec limit
|
||||||
print(f" ✅ Rate limiting appears to be working")
|
print(" ✅ Rate limiting appears to be working")
|
||||||
else:
|
else:
|
||||||
print(f" ⚠️ Requests may have been cached or rate limiting not working")
|
print(" ⚠️ Requests may have been cached or rate limiting not working")
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
|||||||
@@ -4,16 +4,24 @@ Test script for the unified map service.
|
|||||||
This script tests the map service with real location data.
|
This script tests the map service with real location data.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from core.services.data_structures import GeoBounds, MapFilters, LocationType
|
|
||||||
from core.services.map_service import unified_map_service
|
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import django
|
import django
|
||||||
|
|
||||||
# Setup Django environment
|
# Ensure project root is on sys.path so imports like `core.services.*` resolve.
|
||||||
|
# This inserts the parent directory of the tests folder (project root).
|
||||||
|
PROJECT_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||||
|
if PROJECT_ROOT not in sys.path:
|
||||||
|
sys.path.insert(0, PROJECT_ROOT)
|
||||||
|
|
||||||
|
# Setup Django environment before importing app modules that depend on settings.
|
||||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "thrillwiki.settings")
|
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "thrillwiki.settings")
|
||||||
django.setup()
|
django.setup()
|
||||||
|
|
||||||
|
# Now import project modules
|
||||||
|
from apps.core.services.data_structures import GeoBounds, MapFilters, LocationType # noqa: E402
|
||||||
|
from apps.core.services.map_service import unified_map_service # noqa: E402
|
||||||
|
|
||||||
|
|
||||||
def test_basic_map_service():
|
def test_basic_map_service():
|
||||||
"""Test basic map service functionality."""
|
"""Test basic map service functionality."""
|
||||||
@@ -215,7 +223,7 @@ def test_performance():
|
|||||||
print(f" Max time: {max(times):.2f}ms")
|
print(f" Max time: {max(times):.2f}ms")
|
||||||
|
|
||||||
# Test cache performance
|
# Test cache performance
|
||||||
print(f"\n Testing cache performance:")
|
print("\n Testing cache performance:")
|
||||||
start = time.time()
|
start = time.time()
|
||||||
response1 = unified_map_service.get_map_data(zoom_level=10, use_cache=True)
|
response1 = unified_map_service.get_map_data(zoom_level=10, use_cache=True)
|
||||||
time1 = time.time() - start
|
time1 = time.time() - start
|
||||||
|
|||||||
Reference in New Issue
Block a user