import configparser
import re
import sys
+import time
from copy import deepcopy
from datetime import timedelta
from typing import List, NamedTuple, Optional
co2_kg: float
-def vao_car_distance(vao: Vao, parking_lon: float, parking_lat: float, city: Feature) -> Optional[DistInfo]:
+class VaoError(RuntimeError):
+ pass
+
+
+def try_vao_car_distance(vao: Vao, parking_lon: float, parking_lat: float, city: Feature) -> DistInfo:
+ """may throw VaoError with JSON decoded response as argument"""
geometry = city.GetGeometryRef()
point = geometry.GetPoint(0)
city_lon, city_lat, _ = point
dist_m = leg['dist']
co2_kg = trip[0]['Eco']['co2']
return DistInfo(city['name'], city['geonames_id'], duration_minutes, dist_m, co2_kg)
- if response.get('errorCode') is not None:
- print(response)
- sys.exit(1)
- print('Unexpected result from VAO')
+ raise VaoError(response)
+
+
+def vao_car_distance(vao: Vao, parking_lon: float, parking_lat: float, city: Feature, retry_count: int = 2) -> DistInfo:
+ for c in range(retry_count):
+ try:
+ return try_vao_car_distance(vao, parking_lon, parking_lat, city)
+ except VaoError as vao_error:
+ response = vao_error.args[0]
+ if response.get('errorCode') is not None:
+ print(response['errorCode'], response.get('errorText'), f'(attempt {c+1}/{retry_count})')
+ if response['errorCode'] == 'SVC_NO_RESULT':
+ time.sleep(2.)
+ continue
+ else:
+ print('Unexpected result from VAO')
+ sys.exit(1)
+
+
+def distance_meter(a: Geometry, b: Geometry) -> float:
+ spatial_reference_ll = SpatialReference()
+ spatial_reference_ll.ImportFromEPSG(4326)
+ spatial_reference_ll.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER)
+
+ spatial_reference_m = SpatialReference()
+ spatial_reference_m.ImportFromProj4(f'+proj=merc +lat_ts={(a.GetY() + b.GetY()) / 2}')
+
+ ll_to_m = CoordinateTransformation(spatial_reference_ll, spatial_reference_m)
+
+ a_m = a.Clone()
+ a_m.Transform(ll_to_m)
+
+ b_m = b.Clone()
+ b_m.Transform(ll_to_m)
+
+ return a_m.Distance(b_m)
def dist_info_to_dict(dist_info: DistInfo) -> dict:
spatial_reference_m = SpatialReference()
spatial_reference_m.ImportFromProj4(f'+proj=merc +lat_ts={parking_lat}')
- # spatial_reference_m.ImportFromProj4(f'+proj=merc')
ll_to_m = CoordinateTransformation(spatial_reference_ll, spatial_reference_m)
m_to_ll = CoordinateTransformation(spatial_reference_m, spatial_reference_ll)
- loc_ll = Geometry(wkbPoint)
- loc_ll.AddPoint(parking_lon, parking_lat)
+ parking_ll = Geometry(wkbPoint)
+ parking_ll.AddPoint(parking_lon, parking_lat)
- loc_m = loc_ll.Clone()
- loc_m.Transform(ll_to_m)
+ parking_m = parking_ll.Clone()
+ parking_m.Transform(ll_to_m)
max_dist_m = 60000
- bound_m = loc_m.Buffer(max_dist_m)
+ bound_m = parking_m.Buffer(max_dist_m)
bound_ll = bound_m.Clone()
bound_ll.Transform(m_to_ll)
db_cities.SetSpatialFilter(bound_ll)
db_cities.SetAttributeFilter('level<=2')
+ close_cities = [city for city in db_cities]
+ close_cities = sorted(close_cities, key=lambda city: distance_meter(city.GetGeometryRef(), parking_ll))
+ max_number_distances = 3
car_distances_to_append: List[dict] = []
- for city in db_cities:
+ for city in close_cities:
+ if len(car_distances_to_append) >= max_number_distances:
+ if car_distances_to_append[2]['km'] * 1000 < distance_meter(city.GetGeometryRef(), parking_ll):
+ break
print(city['name'])
car_distance = next((cd for cd in car_distance_list if cd.get('geonames_id') == city['geonames_id']), None)
if car_distance is None:
car_distance = dist_info_to_dict(car_distance)
if car_distance is not None:
car_distances_to_append.append(car_distance)
- car_distances_to_append = sorted(car_distances_to_append, key=lambda di: di['km'])[:3]
+ car_distances_to_append = sorted(car_distances_to_append, key=lambda di: di['km'])
+
+ car_distances_to_append = sorted(car_distances_to_append, key=lambda di: di['km'])[:max_number_distances]
for car_distance in car_distances_to_append:
if len([cd for cd in car_distance_list if cd.get('geonames_id') == car_distance['geonames_id']]) == 0:
for result in site.query(list='categorymembers', cmtitle='Kategorie:Rodelbahn', cmlimit='max'):
for page in result['categorymembers']:
print(page['title'])
+ if page['title'] in ['Anzère', 'Hochhäderich (Falkenhütte)', 'Hochlitten-Moosalpe', 'Saas-Fee']:
+ continue
update_sledrun(vao, db_cities, site, page['title'])