Some checks failed
Build and deploy the backend to staging / Build and push image (pull_request) Successful in 1m45s
Run linting on the backend code / Build (pull_request) Successful in 27s
Run testing on the backend code / Build (pull_request) Failing after 45s
Build and deploy the backend to staging / Deploy to staging (pull_request) Successful in 25s
123 lines
4.1 KiB
Python
123 lines
4.1 KiB
Python
"""Module for finding public toilets around given coordinates."""
|
|
import logging
|
|
|
|
from ..overpass.overpass import Overpass, get_base_info
|
|
from ..structs.toilets import Toilets
|
|
from ..utils.bbox import create_bbox
|
|
|
|
|
|
# silence the overpass logger
|
|
logging.getLogger('Overpass').setLevel(level=logging.CRITICAL)
|
|
|
|
class ToiletsManager:
|
|
"""
|
|
Manages the process of fetching and caching toilet information from
|
|
OpenStreetMap (OSM) based on a specified location and radius.
|
|
|
|
This class is responsible for:
|
|
- Fetching toilet data from OSM using Overpass API around a given set of
|
|
coordinates (latitude, longitude).
|
|
- Using a caching strategy to optimize requests by saving and retrieving
|
|
data from a local cache.
|
|
- Logging important events and errors related to data fetching.
|
|
|
|
Attributes:
|
|
logger (logging.Logger): Logger for the class to capture events.
|
|
location (tuple[float, float]): Latitude and longitude representing the
|
|
location to search around.
|
|
radius (int): The search radius in meters for finding nearby toilets.
|
|
overpass (Overpass): The Overpass API instance used to query OSM.
|
|
"""
|
|
logger = logging.getLogger(__name__)
|
|
|
|
location: tuple[float, float]
|
|
radius: int # radius in meters
|
|
|
|
|
|
def __init__(self, location: tuple[float, float], radius : int) -> None:
|
|
|
|
self.radius = radius
|
|
self.location = location
|
|
|
|
# Setup the caching in the Overpass class.
|
|
self.overpass = Overpass()
|
|
|
|
|
|
def generate_toilet_list(self) -> list[Toilets] :
|
|
"""
|
|
Generates a list of toilet locations by fetching data from OpenStreetMap (OSM)
|
|
around the given coordinates stored in `self.location`.
|
|
|
|
Returns:
|
|
list[Toilets]: A list of `Toilets` objects containing detailed information
|
|
about the toilets found around the given coordinates.
|
|
"""
|
|
bbox = create_bbox(self.location, self.radius)
|
|
osm_types = ['node', 'way', 'relation']
|
|
toilets_list = []
|
|
|
|
query = Overpass.build_query(
|
|
bbox = bbox,
|
|
osm_types = osm_types,
|
|
selector = '"amenity"="toilets"',
|
|
out = 'ids center tags'
|
|
)
|
|
try:
|
|
result = self.overpass.fetch_data_from_api(query_str=query)
|
|
except Exception as e:
|
|
self.logger.error(f"Error fetching landmarks: {e}")
|
|
return None
|
|
|
|
toilets_list = self.to_toilets(result)
|
|
|
|
return toilets_list
|
|
|
|
|
|
def to_toilets(self, elements: list) -> list[Toilets]:
|
|
"""
|
|
Parse the Overpass API result and extract landmarks.
|
|
|
|
This method processes the JSON elements returned by the Overpass API and
|
|
extracts landmarks of types 'node', 'way', and 'relation'. It retrieves
|
|
relevant information such as name, coordinates, and tags, and converts them
|
|
into Landmark objects.
|
|
|
|
Args:
|
|
list (osm elements): The root element of the JSON response from Overpass API.
|
|
elem_type (str): The type of landmark (e.g., node, way, relation).
|
|
|
|
Returns:
|
|
list[Landmark]: A list of Landmark objects extracted from the JSON data.
|
|
"""
|
|
if elements is None :
|
|
return []
|
|
|
|
toilets_list = []
|
|
for elem in elements:
|
|
osm_type = elem.get('type')
|
|
# Get coordinates and append them to the points list
|
|
_, coords = get_base_info(elem, osm_type)
|
|
if coords is None :
|
|
continue
|
|
|
|
toilets = Toilets(location=coords)
|
|
|
|
# Extract tags as a dictionary
|
|
tags = elem.get('tags')
|
|
|
|
if 'wheelchair' in tags.keys() and tags['wheelchair'] == 'yes':
|
|
toilets.wheelchair = True
|
|
|
|
if 'changing_table' in tags.keys() and tags['changing_table'] == 'yes':
|
|
toilets.changing_table = True
|
|
|
|
if 'fee' in tags.keys() and tags['fee'] == 'yes':
|
|
toilets.fee = True
|
|
|
|
if 'opening_hours' in tags.keys() :
|
|
toilets.opening_hours = tags['opening_hours']
|
|
|
|
toilets_list.append(toilets)
|
|
|
|
return toilets_list
|