Skip to content

Instantly share code, notes, and snippets.

@musantro
Created June 10, 2024 06:48
Show Gist options
  • Save musantro/7d30caba26d53d9235bb59cb28845d32 to your computer and use it in GitHub Desktop.
Save musantro/7d30caba26d53d9235bb59cb28845d32 to your computer and use it in GitHub Desktop.
Get distance from two cities
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