From eb9aecfeeba269c5fe6f1c88177af785583794d4 Mon Sep 17 00:00:00 2001 From: Marco Schmid Date: Thu, 23 Apr 2026 17:06:00 +0200 Subject: [PATCH] Task_1: add fetch_bergbahn function --- .gitignore | 5 ++++ GIT_HINTS.md | 45 ++++++++++++++++++++++++++++++ README.md | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++++ TASK.md | 21 ++++++++++++++ main.py | 12 ++++++++ 5 files changed, 160 insertions(+) create mode 100644 .gitignore create mode 100644 GIT_HINTS.md create mode 100644 README.md create mode 100644 TASK.md create mode 100644 main.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8d78979 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +.idea +.venv +GIT_INSTRUCTOR.md +README_INSTRUCTOR.md + diff --git a/GIT_HINTS.md b/GIT_HINTS.md new file mode 100644 index 0000000..6a47bb7 --- /dev/null +++ b/GIT_HINTS.md @@ -0,0 +1,45 @@ +# Git-Hints + +Gesamtes Repo klonen: +``` +git clone https://gitea.fhgr.ch/schmidmarco/overpass.git +``` + +Neuen Arbeitsbranch 'work' machen beim Stand 'Task 1' (alle Files): +``` +git checkout -b work Task_1 +``` + +Nur nächsten Task holen: + - holt nur die Aufgabe + - eigener Code bleibt unangetastet +``` +git checkout Task_2 -- TASK.md +``` + +Den ganzen Code zu einem bestimmten Tag holen (Notfall): +``` +# Vorher eigene Arbeit sichern: +git add . +git commit -m "mein Stand vor Notfall-Checkout" + +# Dann eine einzelne Datei holen: +git checkout Task_3 -- main.py + +# Oder alles auf Tag zurücksetzen (unwiderruflich!): +git reset --hard Task_3 +``` + + +Vor dem reset, besser: +``` +git log work --oneline # nochmals anschauen was verloren geht +git commit -m "mein Stand, wird jetzt verworfen" # zumindest in History sichtbar +``` + + +Immer vor dem Holen des nächsten Tasks einen eigenen `commit` machen! + +``` +git commit -m "Task xy: ..." +``` \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..e78f1ae --- /dev/null +++ b/README.md @@ -0,0 +1,77 @@ +# README + +Ich habe euch den `GeoService` demonstriert. Das ist ein Docker-basierter Mikroservice, welcher Fragen wie +'Zeige mir basierend auf meinem Standort die 3 per Auto nächstgelegenen Restaurants' oder 'Wieviele Schwimmbäder +befinden sich im Umkreis von 3 Kilometer um meinen jetzigen Standort' etc. + +Um den Service zu betreiben braucht es (valide) Daten. Diese kann man kaufen oder sich selbst bauen. Wir gehen hier +den zweiten Weg :-). Das Ziel für die nächsten 3-4 Übungsstunden ist ein kleines Projekt, welches uns diese Basisdaten +mithilfe von OpenStreetMap (Overpass) für die ganze Schweiz baut. + +Es geht weniger darum, ein super End-Produkt zu bauen (also inhaltlich), als vielmehr darum viele in diesem Semester +gelernte Konzepte und Techniken zu integrieren und an einem praxisnahen Beispiel miteinander zu erarbeiten und zu +festigen. + +Dies sind u.U.: + +* Zugriff mit Python auf eine API (Overpass) +* Arbeiten mit git auf Gitea (commits, clone, checkout) +* Dataclasses +* sauberer Python-Code mit docstrings, typehints und logging +* Speichern der Resultate in eine postgres-Datenbank +* Parallelisierung (multithreading, multiprocessing) von Abfragen auf Overpass-API +* Dekorator-Pattern (für Zeitmessung) +* Schreiben von Pytests mit und ohne Mocks + +**Ziel:** + +Valide Daten für ausgewählte POI's (Points Of Interests) zu produzieren, z.B. + +```json +{ + "generated_at": "2026-03-09T23:03:40.107307+00:00", + "poi_type": "rail_station", + "count": 2511, + "pois": [ + { + "id": "node/2068758717", + "type": "rail_station", + "name": "St. Urban Ziegelei", + "lat": 47.2271478, + "lon": 7.8361018, + "tags": { + "name": "St. Urban Ziegelei" + } + }, + { + "id": "node/2068760081", + "type": "rail_station", + "name": "St. Urban", + "lat": 47.2317566, + "lon": 7.8359882, + "tags": { + "name": "St. Urban" + } + } + ] +} +``` + +Für die POIs machen wir unseren eigenen Datatyp 'POI' (`dataclass`) +Ein einzelner POI: + +``` { + "id": "node/2068758717", + "type": "rail_station", + "name": "St. Urban Ziegelei", + "lat": 47.2271478, + "lon": 7.8361018, + "tags": { + "name": "St. Urban Ziegelei" + } +``` + +Die Daten beziehen wir von `https://overpass-turbo.eu/`. Overpass bietet nebst diesem frontend-basierten Ansatz auch eine +API-Schnittstelle (POST- und GET-Requests) an, welche wir nutzen können (`OVERPASS_URL=https://overpass-api.de/api/interpreter`). + +Viel Spass im Projekt! \ No newline at end of file diff --git a/TASK.md b/TASK.md new file mode 100644 index 0000000..ac6fa14 --- /dev/null +++ b/TASK.md @@ -0,0 +1,21 @@ +# TASK: + +Overpass-Query: -> wir wollen diesen in eine Python-Funktion `fetch_bergbahnen() in `main.py` einbauen + +``` + [out:json][timeout:60]; + ( + node["aerialway"="station"]({{bbox}}); + way["aerialway"="station"]({{bbox}}); + node["railway"="funicular"]({{bbox}}); + way["railway"="funicular"]({{bbox}}); + node["railway"="station"]["funicular"="yes"]({{bbox}}); + ); + out center body; +``` + +* Kopiert diesen auf `https://overpass-turbo.eu/` und führt ihn mal aus. +* Spielt mit den Zoomstufen -> bbox +* Versucht mehr über bbox herauszufinden (z.B. https://wiki.openstreetmap.org/wiki/Overpass_API) +* Versucht eine einfache fetch_bergbahn() zu bauen, die API lautet "https://overpass-api.de/api/interpreter" + Nutzt dazu die request-Library in Python, wo ihr post- und get-Requests bauen könnt \ No newline at end of file diff --git a/main.py b/main.py new file mode 100644 index 0000000..722c831 --- /dev/null +++ b/main.py @@ -0,0 +1,12 @@ +from pprint import pprint + + +def fetch_bergbahnen(bbox) -> dict: + return {} + + +if __name__ == "__main__": + + bbox = (46.72, 9.70, 46.92, 10.00) + result = fetch_bergbahnen(bbox) + pprint(result) \ No newline at end of file