File size: 6,178 Bytes
187a965
0f04201
e3db752
187a965
0f04201
e3db752
 
187a965
 
 
 
bd669ec
187a965
 
 
 
 
 
 
 
 
 
 
0f04201
e3db752
187a965
bd669ec
 
 
 
187a965
 
 
 
 
0f04201
187a965
 
0f04201
 
 
 
 
 
 
 
 
 
 
 
 
e3db752
0f04201
 
 
187a965
 
 
0f04201
 
187a965
 
 
 
 
 
 
 
60a0b19
187a965
 
 
 
247bc50
187a965
 
 
 
 
 
e0e3529
 
187a965
 
 
 
 
 
 
 
 
 
 
0f04201
 
 
 
 
 
 
 
187a965
 
 
 
 
 
 
 
 
 
 
 
3ae3815
187a965
 
 
 
 
 
 
 
247bc50
187a965
 
 
 
 
0f04201
 
 
 
 
187a965
bd669ec
187a965
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bd669ec
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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
import json
import urllib.parse

import requests
from langchain.tools import tool
from loguru import logger

from .common import config, vehicle


# Select coordinates at equal distance, including the last one
def _select_equally_spaced_coordinates(coords, number_of_points=10):
    n = len(coords)
    selected_coords = []
    interval = max((n - 1) / (number_of_points - 1), 1)
    for i in range(number_of_points):
        # Calculate the index, ensuring it doesn't exceed the bounds of the list
        index = int(round(i * interval))
        if index < n:
            selected_coords.append(coords[index])
    return selected_coords


@tool
def search_points_of_interest(search_query: str = "french restaurant"):
    """
    Get some of the closest points of interest matching the query.

    Args:
        search_query (string): Required. Describing the type of point of interest depending on what the user wants to do. Make sure to include the type of POI you are looking for. For example italian restaurant, grocery shop, etc.
    """

    # Extract the latitude and longitude of the vehicle
    vehicle_coordinates = getattr(vehicle, "location_coordinates")
    lat, lon = vehicle_coordinates
    logger.info(f"POI search vehicle's lat: {lat}, lon: {lon}")

    # https://developer.tomtom.com/search-api/documentation/search-service/search
    # Encode the parameters
    # Even with encoding tomtom doesn't return the correct results
    search_query = search_query.replace("'", "")
    encoded_search_query = urllib.parse.quote(search_query)

    # Construct the URL
    url = f"https://api.tomtom.com/search/2/search/{encoded_search_query}.json"
    params = {
        "key": config.TOMTOM_API_KEY,
        "lat": lat,
        "lon": lon,
        "radius": 5000,
        "idxSet": "POI",
        "limit": 50,
    }

    r = requests.get(url, params=params, timeout=5)

    # Parse JSON from the response
    data = r.json()

    logger.debug(f"POI search response: {data}\n url:{url} params: {params}")
    # Extract results
    results = data["results"]

    # TODO: Handle the no results case.
    if not results:
        return "No results found in the vicinity."

    # Sort the results based on distance
    results = sorted(results, key=lambda x: x["dist"])
    # print(sorted_results)

    # Format and limit to top 5 results
    formatted_results = [
        f"{result['poi']['name']}, {int(result['dist'])} meters away"
        for result in results[:3]
    ]

    output = (
        f"There are {len(results)} options in the vicinity. The most relevant are: "
    )
    extra_info = [x["poi"] for x in results[:3]]
    return output + ".\n ".join(formatted_results)


def find_points_of_interest(lat="0", lon="0", type_of_poi="restaurant"):
    """
    Return some of the closest points of interest for a specific location and type of point of interest. The more parameters there are, the more precise.
    :param lat (string):  latitude
    :param lon (string):  longitude
    :param city (string): Required. city
    :param type_of_poi (string): Required. type of point of interest depending on what the user wants to do.
    """
    # https://developer.tomtom.com/search-api/documentation/search-service/points-of-interest-search
    # Encode the parameters
    encoded_type_of_poi = urllib.parse.quote(type_of_poi)

    # Construct the URL
    url = f"https://api.tomtom.com/search/2/search/{encoded_type_of_poi}.json?key={config.TOMTOM_API_KEY}&lat={lat}&lon={lon}&radius=10000&vehicleTypeSet=Car&idxSet=POI&limit=100"

    r = requests.get(url, timeout=5)

    # Parse JSON from the response
    data = r.json()
    # print(data)
    # Extract results
    results = data["results"]

    # Sort the results based on distance
    sorted_results = sorted(results, key=lambda x: x["dist"])
    # print(sorted_results)

    # Format and limit to top 5 results
    formatted_results = [
        f"The {type_of_poi} {result['poi']['name']}, {int(result['dist'])} meters away"
        for result in sorted_results[:5]
    ]

    return ". ".join(formatted_results)


def search_along_route_w_coordinates(points: list[tuple[float, float]], query: str):
    """
    Return some of the closest points of interest along the route/way from the depart point, specified by its coordinates.
    :param points (list[tuple(float, float)]): Required. List of tuples of latitude and longitude of the points along the route.
    :param query (string): Required. type of point of interest depending on what the user wants to do.
    """

    # The API endpoint for searching along a route

    # urlencode the query
    query = urllib.parse.quote(query)

    url = f"https://api.tomtom.com/search/2/searchAlongRoute/{query}.json?key={config.TOMTOM_API_KEY}&maxDetourTime=600&limit=20&sortBy=detourTime"

    points = _select_equally_spaced_coordinates(points, number_of_points=20)

    # The data payload
    payload = {
        "route": {
            "points": [{"lat": pt["latitude"], "lon": pt["longitude"]} for pt in points]
        }
    }

    # Make the POST request
    response = requests.post(url, json=payload, timeout=5)

    # Check if the request was successful
    if response.status_code == 200:
        # Parse the JSON response
        data = response.json()
        # print(json.dumps(data, indent=4))
    else:
        print("Failed to retrieve data:", response.status_code)
        return "Failed to retrieve data. Please try again."
    answer = ""
    if not data["results"]:
        return "No results found along the way."

    if len(data["results"]) == 20:
        answer = "There more than 20 results along the way. Here are the top 3 results:"
    elif len(data["results"]) > 3:
        answer = f"There are {len(data['results'])} results along the way. Here are the top 3 results:"
    for result in data["results"][:3]:
        name = result["poi"]["name"]
        address = result["address"]["freeformAddress"]
        detour_time = result["detourTime"]
        answer = (
            answer
            + f" \n{name} at {address} would require a detour of {int(detour_time/60)} minutes."
        )

    return answer, data["results"][:5]