#!/usr/bin/env python import overpy import numpy as np import pandas as pd import geopy.distance as distance from tqdm import tqdm # brandname : overpass query filters BRANDS: dict[str, str] = { "greggs": "[\"brand:wikidata\"=\"Q3403981\"]", } EncodedLocation = list[tuple[float, list[float]]] def fetch_data(brand: str) -> list[tuple[float | None, float | None]]: """Fetch a list of locations from OSM.""" api = overpy.Overpass() filters = BRANDS[brand] query = api.query(f"nwr{filters}; out center;") result = [] for way in query.ways: result.append((way.center_lat, way.center_lon)) for node in query.nodes: result.append((node.lat, node.lon)) for (lat, lon) in result: if (lat is None) or (lon is None): raise ValueError("Item missing coords!") return result def encode(location: tuple[float, float]) -> EncodedLocation: """Encode a location.""" print("fetching") greggs = fetch_data("greggs") print("fetched") #greggs = [(55.85,-4.02),(52.443,-1.833),(51.28,-1.0)] #relative distance matrix dist_matrix = np.zeros((len(greggs),len(greggs))) for i in tqdm(range(len(greggs))): first=greggs[i] for j in range(len(greggs)): second=greggs[j] #calculate the distance between i and j coordinates #dist_matrix[i,j] = np.sqrt((first[0]-second[0])**2 + (first[1]-second[1])**2 ) dist_matrix[i,j] = distance.distance(distance.lonlat(*first), distance.lonlat(*second)).km*1000 print(dist_matrix) #find closest greggs distances = pd.Series(np.zeros(len(greggs))) for i in range(len(greggs)): current = greggs[i] #distances[i] = np.sqrt((current[0]-location[0])**2 + (current[1]-location[1])**2 distances[i] = distance.distance(distance.lonlat(*current), distance.lonlat(*location)).km*1000 print(distances) distances = distances.sort_values() top3 = distances.head(3) print(top3) # Stub return [ (5., [1., 2., 3.]), (6., [4., 5., 6.]), ] def decode(location: EncodedLocation) -> tuple[float, float]: """Decode into a location.""" # Stub return (0.091659, 52.210796) def format_location(location: EncodedLocation) -> str: """Format an encoded location as a string.""" return ";".join([f"{a}:{','.join(map(str, b))}" for (a, b) in location]) def parse_location(location: str) -> EncodedLocation: """Parse a location string into an EncodedLocation.""" # Stub return [ (5., [1., 2., 3.]), (6., [4., 5., 6.]), ] def main(): """Testing.""" print("Running query...") #greggs = fetch_data("greggs") #print(f"Query done - got {len(greggs)} Greggs!") print(format_location(encode((0.091659, 52.210796)))) if __name__ == "__main__": main()