Created
June 10, 2024 06:48
-
-
Save musantro/7d30caba26d53d9235bb59cb28845d32 to your computer and use it in GitHub Desktop.
Get distance from two cities
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import asyncio | |
import math | |
from typing import Any, Final | |
import aiohttp | |
earth_radius: Final[str] = 6_371 # km | |
host: str = "https://nominatim.openstreetmap.org/" | |
endpoint: str = "/search" | |
global_parameters: dict[str, Any] = { | |
"addressdetails": 1, | |
"format": "jsonv2", | |
"limit": 1, | |
} | |
async def get_coords_city( | |
session: aiohttp.ClientSession, | |
city: str, | |
queue: asyncio.Queue, | |
) -> str: | |
query_parameters = global_parameters | {"city": city} | |
async with session.get(endpoint, params=query_parameters) as response: | |
print(f"Making request for {city}") | |
await queue.put(await response.json()) | |
def haversine( | |
coords_1: tuple[float, float], | |
coords_2: tuple[float, float], | |
) -> float: | |
lat1, lon1 = coords_1 | |
lat2, lon2 = coords_2 | |
lat1_rad = math.radians(lat1) | |
lon1_rad = math.radians(lon1) | |
lat2_rad = math.radians(lat2) | |
lon2_rad = math.radians(lon2) | |
dlat = lat2_rad - lat1_rad | |
dlon = lon2_rad - lon1_rad | |
a = ( | |
math.sin(dlat / 2) ** 2 | |
+ math.cos(lat1_rad) * math.cos(lat2_rad) * math.sin(dlon / 2) ** 2 | |
) | |
c = 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a)) | |
distance = earth_radius * c | |
return distance | |
async def main() -> None: | |
city_a = input("Enter first city: ") | |
city_b = input("Enter second city: ") | |
queue = asyncio.Queue() | |
async with aiohttp.ClientSession(host) as session, asyncio.TaskGroup() as group: | |
for city in [city_a, city_b]: | |
group.create_task(get_coords_city(session, city, queue)) | |
coords = [] | |
while not queue.empty(): | |
city = await queue.get() | |
first_city, *_ = city | |
city_coords = (float(first_city["lat"]), float(first_city["lon"])) | |
coords.append(city_coords) | |
print(f"{first_city['address']['city']} is in {city_coords}") | |
distance = haversine(*coords) | |
print(f"Distance between {city_a} and {city_b} is {distance:.2f} km") | |
if __name__ == "__main__": | |
asyncio.run(main()) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment