File size: 4,599 Bytes
b731d10
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
import os
import pandas as pd
from dotenv import load_dotenv
import requests
from geopy.distance import geodesic

load_dotenv()

def find_place(input_text, api_key):
    # Define the base URL and parameters for the request
    base_url = "https://maps.googleapis.com/maps/api/place/findplacefromtext/json"
    params = {
        "fields": "formatted_address,name,rating,opening_hours,geometry",
        "input": input_text,
        "inputtype": "textquery",
        "key": api_key  # Replace with your actual API key
    }

    # Make the GET request
    response = requests.get(base_url, params=params)

    # Check if the request was successful
    if response.status_code == 200:
        # Return the response content (JSON)
        return response.json()
    else:
        # Return an error message if the request failed
        return f"Request failed with status code: {response.status_code}"
    
    

def get_zip_code(address):
    base_url = "https://maps.googleapis.com/maps/api/geocode/json"
    params = {
        "address": address,
        "key": "AIzaSyDXCm-fwucr6R93CHa9Bb4j5qArup5D4kY"
    }
    response = requests.get(base_url, params=params)
    if response.status_code == 200:
        data = response.json()
        if data['status'] == 'OK':
            # Extract the postal code from the address components
            for component in data['results'][0]['address_components']:
                if 'postal_code' in component['types']:
                    return component['long_name']
            return None
        else:
            return f"API request returned status: {data['status']}"
    else:
        return f"Request failed with status code: {response.status_code}"


def get_distances_for_multiple_destinations(origin, destinations, api_key):
    destinations_param = '|'.join(destinations)

    base_url = "https://maps.googleapis.com/maps/api/distancematrix/json"
    params = {
        "origins": origin,
        "destinations": destinations_param,
        "key": api_key
    }

    response = requests.get(base_url, params=params)
    if response.status_code == 200:
        data = response.json()
        if data['status'] == 'OK':
            results = []
            for element in data['rows'][0]['elements']:
                if element['status'] == 'OK':
                    distance = element['distance']['text']
                    results.append(distance)
                else:
                    results.append("Distance calculation failed")
            return results
        else:
            return ["API request returned error: " + data['status']]
    else:
        return [f"Request failed with status code: {response.status_code}"]

class LocationDataHandler:
    def __init__(self, data_frame):
        # self.data_file = data_file
        self.api_key = os.getenv('GOOGLE_MAPS_API_KEY')
        self.data_frame = data_frame

    def get_latlong_from_address(self, address):
        try:
            result = find_place(address, self.api_key)
            lat = result['candidates'][0]['geometry']['location']['lat']
            lng = result['candidates'][0]['geometry']['location']['lng']
            return lat, lng
        except Exception as e:
            print(f"Error retrieving location for {address}: {e}")
            return None

    def calculate_distance(self, ref_point, latitude, longitude):
        try:
            location = (latitude, longitude)
            return geodesic(ref_point, location).kilometers
        except Exception as e:
            print(f"Error calculating distance: {e}")
            return None

    def filter_by_address(self, address, max_distance_km=30):
        ref_point = self.get_latlong_from_address(address)
        if not ref_point:
            return None
        
        def distance_calculation(row):
            return self.calculate_distance(ref_point, row['Latitude'], row['Longitude'])

        # Calculate distance for each row
        self.data_frame['Distance'] = self.data_frame.apply(distance_calculation, axis=1)

        # Select top 10 within the maximum distance
        df = self.data_frame[self.data_frame['Distance'] <= max_distance_km].sort_values(by='Distance').head(10).reset_index(drop=True)

        # Calculate Actual Distance Using GMaps API
        destinations = df.apply(lambda row: f"{row['Latitude']},{row['Longitude']}", axis=1).tolist()
        distances = get_distances_for_multiple_destinations(f"{ref_point[0]},{ref_point[1]}", destinations, self.api_key)

        # Add the distances back to the DataFrame
        df['Distance'] = distances

        return df