diff --git a/js/main.ts b/js/main.ts index f1eae6c..a0a2e3b 100644 --- a/js/main.ts +++ b/js/main.ts @@ -132,8 +132,6 @@ function updateInfo(info, coords) { maxZoom: 16, duration: 500, }); - const [lon, lat] = coords; - history.replaceState(null, "", "?g=" + encodeURIComponent(`${lat},${lon}`)); } function infoError(txt: string) { @@ -150,6 +148,7 @@ async function getInfo(coords: GeoJSONPosition) { if (response.ok) { const info = await response.json(); updateInfo(info, coords); + history.replaceState(null, "", "?g=" + encodeURIComponent(`${lat},${lon}`)); } else if (response.status == 404) { infoError(`L'endroit choisi ne se situe pas à Sainte-Adèle. Veuillez réessayer.`); @@ -161,6 +160,24 @@ endroit à proximité.`); } } +async function getZone(zone: string) { + const url = `${ZONALDA_API_URL}/z/${zone}`; + const response = await fetch(url); + if (response.ok) { + const info = await response.json(); + updateInfo(info, info.point); + history.replaceState(null, "", "?z=" + encodeURIComponent(zone)) + return info.point; + } + else if (response.status == 404) { + infoError(`La zone ${zone} n'existe pas. Veuillez réessayer.`); + } + else { + infoError(`Les informations n’ont pu être trouvées pour l'endroit choisi à cause +d'un problème avec la base géomatique.`); + } +} + autocomplete.on('select', async (location: GeoJSONFeature) => { const pos = location.geometry as GeoJSONPoint; source.clear(true); @@ -212,13 +229,22 @@ window.addEventListener("load", async () => { zonage = metadata.zonage; } const urlParams = new URLSearchParams(window.location.search); - const centroid = urlParams.get("g"); + let centroid = null; + const gps = urlParams.get("g"); + const zone = urlParams.get("z"); + if (gps !== null) { + const [lat, lon] = gps.split(",").map(parseFloat); + centroid = [lon, lat]; + getInfo(centroid); + } + else if (zone !== null) { + centroid = await getZone(zone); + console.log(centroid); + } if (centroid !== null) { - const [lat, lon] = centroid.split(",").map(parseFloat); - const coords = [lon, lat]; - const projPos = fromLonLat(coords); + const projPos = fromLonLat(centroid); + source.clear(true); source.addFeature(new Feature(new Point(projPos))); view.animate({center: projPos}); - getInfo(coords); } }); diff --git a/zonalda/__init__.py b/zonalda/__init__.py index 63ebdb5..47bfd42 100644 --- a/zonalda/__init__.py +++ b/zonalda/__init__.py @@ -12,7 +12,7 @@ from pandas import Series from shapely import Point # type: ignore -VERSION = "0.0.1" +VERSION = "0.0.2" THISDIR = Path(__file__).parent LOGGER = logging.getLogger("zonalda") @@ -27,12 +27,23 @@ class Zonalda: def __init__(self): self.ville = geopandas.read_file(THISDIR / "sainte-adele.geojson").iloc[0] self.districts = geopandas.read_file(THISDIR / "districts.geojson") - self.zonage = geopandas.read_file(THISDIR / "zonage.geojson") + zonage = geopandas.read_file(THISDIR / "zonage.geojson") + self.zonage = zonage.assign(ZONE=zonage["ZONE"].str.replace(" ", "")) self.collectes = geopandas.read_file(THISDIR / "collectes.geojson") - def __call__( - self, latitude: float, longitude: float - ) -> tuple[Series | None, Series | None, Series | None,]: + def __getitem__(self, name: str) -> tuple[float, float]: + """Trouver le centroïde d'une zone par son nom.""" + zones = self.zonage.loc[self.zonage["ZONE"] == name] + if zones.empty: + raise KeyError("Zone not found: %s" % name) + c = zones.iloc[0].geometry.centroid + return c.y, c.x + + def __call__(self, latitude: float, longitude: float) -> tuple[ + Series | None, + Series | None, + Series | None, + ]: """Chercher les informations citoyennes pour un emplacement.""" p = Point(longitude, latitude) if not self.ville.geometry.contains(p): diff --git a/zonalda/api.py b/zonalda/api.py index eb42383..f6785ee 100644 --- a/zonalda/api.py +++ b/zonalda/api.py @@ -48,9 +48,13 @@ class Emplacement(BaseModel): district: District | None collecte: Collecte | None zone: Zone | None + point: tuple[float, float] @classmethod def from_wgs84(self, latitude: float, longitude: float) -> "Emplacement": + """ + Chercher les informations géomatiques pour un emplacement GPS. + """ district, zone, collecte = zonalda(latitude, longitude) return self( district=District(numero=district["id"], conseiller=district["Conseiller"]) @@ -68,8 +72,17 @@ def from_wgs84(self, latitude: float, longitude: float) -> "Emplacement": ) if zone is not None else None, + point=(longitude, latitude), ) + @classmethod + def from_zone(self, zone: str) -> "Emplacement": + """ + Localiser le centroïde d'une zone et retourner les autres informations. + """ + latitude, longitude = zonalda[zone] + return self.from_wgs84(latitude, longitude) + @api.exception_handler(MunicipalityError) async def municipality_error_handler(request, exc): @@ -81,6 +94,14 @@ async def ll(latitude: float, longitude: float): return Emplacement.from_wgs84(latitude, longitude) +@api.get("/z/{zone}") +async def zz(zone: str): + try: + return Emplacement.from_zone(zone) + except KeyError: + return None + + GEOAPIFY_URL = "https://api.geoapify.com/v1/geocode/autocomplete" client = httpx.AsyncClient()