128 lines
3.9 KiB
Python
128 lines
3.9 KiB
Python
import math
|
|
from accounts.models import IAmPrincipal
|
|
from manage_events.models import Event, Venue
|
|
from django.utils.timezone import now
|
|
import googlemaps
|
|
from django.conf import settings
|
|
|
|
|
|
def haversine(lon1, lat1, lon2, lat2):
|
|
"""
|
|
Calculate the great circle distance in kilometers between two points
|
|
on the earth (specified in decimal degrees)
|
|
"""
|
|
# convert decimal degrees to radians
|
|
lon1, lat1, lon2, lat2 = map(math.radians, [lon1, lat1, lon2, lat2])
|
|
|
|
# haversine formula
|
|
dlon = lon2 - lon1
|
|
dlat = lat2 - lat1
|
|
a = (
|
|
math.sin(dlat / 2) ** 2
|
|
+ math.cos(lat1) * math.cos(lat2) * math.sin(dlon / 2) ** 2
|
|
)
|
|
c = 2 * math.asin(math.sqrt(a))
|
|
r = 6371 # Radius of earth in kilometers. Use 3956 for miles
|
|
return c * r
|
|
|
|
|
|
def filter_events_by_location(user_lat, user_lon, radius_km=10):
|
|
venues_within_radius = []
|
|
|
|
# Check each venue to see if it's within the radius
|
|
for venue in Venue.objects.filter(deleted=False, active=True):
|
|
print("venue: ", venue)
|
|
distance = haversine(user_lon, user_lat, venue.longitude, venue.latitude)
|
|
print("distance: ", distance)
|
|
if distance <= radius_km:
|
|
venues_within_radius.append(venue.id)
|
|
print("venues_within_radius: ", venues_within_radius)
|
|
# Filter events based on the venues within the radius
|
|
events = Event.objects.filter(venue__id__in=venues_within_radius)
|
|
return events
|
|
|
|
|
|
from math import sin, cos, radians, sqrt, atan2
|
|
|
|
|
|
def haversine_one(lon1, lat1, lon2, lat2):
|
|
"""
|
|
Calculates the distance between two points on a sphere using the Haversine formula.
|
|
|
|
Args:
|
|
lon1 (float): Longitude of the first point.
|
|
lat1 (float): Latitude of the first point.
|
|
lon2 (float): Longitude of the second point.
|
|
lat2 (float): Latitude of the second point.
|
|
|
|
Returns:
|
|
float: Distance in kilometers between the two points.
|
|
"""
|
|
R = 6371 # Earth's radius in kilometers
|
|
|
|
dlon = radians(lon2 - lon1)
|
|
dlat = radians(lat2 - lat1)
|
|
|
|
a = sin(dlat / 2) * sin(dlat / 2) + cos(radians(lat1)) * cos(radians(lat2)) * sin(
|
|
dlon / 2
|
|
) * sin(dlon / 2)
|
|
c = 2 * atan2(sqrt(a), sqrt(1 - a))
|
|
|
|
return R * c
|
|
|
|
|
|
API_KEY = settings.GOOGLE_MAPS_API_KEY
|
|
gmaps = googlemaps.Client(key=API_KEY)
|
|
|
|
|
|
def get_location_info(latitude, longitude):
|
|
reverse_geocode_result = gmaps.reverse_geocode((latitude, longitude))
|
|
|
|
if reverse_geocode_result:
|
|
location = reverse_geocode_result[0]
|
|
city = None
|
|
state = None
|
|
country = None
|
|
|
|
for component in location.get("address_components", []):
|
|
types = component.get("types", [])
|
|
# print("types: ", types)
|
|
if "locality" in types:
|
|
city = component.get("long_name")
|
|
elif "administrative_area_level_1" in types:
|
|
state = component.get("long_name")
|
|
elif "country" in types:
|
|
country = component.get("long_name")
|
|
country_code = component.get("short_name")
|
|
|
|
if city is None and state is not None:
|
|
city = state
|
|
return {
|
|
"city": city,
|
|
"state": state,
|
|
"country": country,
|
|
"country_code": country_code,
|
|
}
|
|
else:
|
|
return {}
|
|
|
|
|
|
def update_principal_location(principal, latitude, longitude):
|
|
location_data = get_location_info(latitude=latitude, longitude=longitude)
|
|
|
|
city = location_data.get("city")
|
|
state = location_data.get("state")
|
|
country = location_data.get("country")
|
|
country_code = location_data.get("country_code")
|
|
|
|
if hasattr(principal, "city"):
|
|
principal.city = city or state
|
|
if hasattr(principal, "state"):
|
|
principal.state = state
|
|
if hasattr(principal, "country"):
|
|
principal.country = country
|
|
if hasattr(principal, "address_line1"):
|
|
principal.address_line1 = country_code
|
|
|
|
principal.save()
|