#!/usr/bin/python3 import argparse import json import sys from typing import List, Optional, Tuple from xml.etree.ElementTree import ElementTree, Element from geojson import Feature from shapely.geometry import shape from termcolor import cprint from wrpylib.cli_tools import unified_diff, input_yes_no_quit, Choice from wrpylib.json_tools import format_json from wrpylib.mwapi import WikiSite from wrpylib.wrgeojson import join_wrgeojson_ways from wrpylib.wrosm import find_sledrun_relations, convert_osm_to_geojson, DeRefError, tags def filter_way(feature: dict, way_type: str) -> bool: return feature['geometry']['type'] == 'LineString' and feature.get('properties', {}).get('type') == way_type def feature_distance(a: Feature, b: Feature) -> float: return shape(a['geometry']).hausdorff_distance(shape(b['geometry'])) def geojson_way_sort_key(feature: Feature, reference_feature: Feature) -> Tuple[str, float]: return feature.get('properties', {}).get('type', ''), feature_distance(feature, reference_feature) def _update_wrgeojson_from_osm_file(wrgeojson_title: str, osm_tree: ElementTree, osm_sledrun_relation: Element, site: WikiSite): try: wr_wrgeojson = convert_osm_to_geojson(osm_tree, osm_sledrun_relation) except DeRefError: cprint('Error: Incomplete XML - please load larger region.', 'red') return join_wrgeojson_ways(wr_wrgeojson) wrgeojson_page = site.query_page(wrgeojson_title) wrgeojson_page_content = wrgeojson_page['revisions'][0]['slots']['main']['content'] wr_wrgeojson_old = json.loads(wrgeojson_page_content) if wr_wrgeojson_old == wr_wrgeojson: cprint('No changes detected', 'red') return wr_wrgeojson['wr_properties']['simplified'] = False wr_wrgeojson_old_str = format_json(wr_wrgeojson_old) wr_wrgeojson_str = format_json(wr_wrgeojson) cprint(wrgeojson_title, 'green') unified_diff(wr_wrgeojson_old_str, wr_wrgeojson_str) choice = input_yes_no_quit('Do you accept the changes [yes, no, quit]? ', None) if choice == Choice.no: return elif choice == Choice.quit: sys.exit(0) site( 'edit', pageid=wrgeojson_page['pageid'], text=wr_wrgeojson_str, summary='Landkarte ersetzt.', minor=1, bot=1, baserevid=wrgeojson_page['revisions'][0]['revid'], nocreate=1, token=site.token(), ) def update_wrgeojson_from_osm_file(wrgeojson_title: str, osm_file: str, osm_index: Optional[int], ini_files: List[str]): osm_tree = ElementTree() osm_tree.parse(osm_file) site = WikiSite(ini_files) # Search all sledrun relations osm_sledrun_list = list(find_sledrun_relations(osm_tree)) # Select one sledrun to work with if len(osm_sledrun_list) == 0: cprint('No sledruns in OSM file.', 'red') return elif len(osm_sledrun_list) > 1 and osm_index is None: cprint(f'{len(osm_sledrun_list)} sledruns in the OSM. Please specify --osm_index:') for i, osm_sledrun in enumerate(osm_sledrun_list): t = tags(osm_sledrun) print(f'{i}: {t.get("name", t)}') return osm_sledrun = osm_sledrun_list[0 if osm_index is None else osm_index] _update_wrgeojson_from_osm_file(wrgeojson_title, osm_tree, osm_sledrun, site) def main(): parser = argparse.ArgumentParser( description='Updates sledrun wrgeojson maps with higher resolution ways from OSM files.') parser.add_argument('wrgeojson_title', help='Title of an existing wrgeojson page.') parser.add_argument('osm_file', help='OSM file containing high resolution ways.') parser.add_argument('--osm_index', type=int, help='Index of the sledrun relation within the OSM file.') parser.add_argument('ini_file', nargs='+', help='inifile.ini, see: https://www.winterrodeln.org/trac/wiki/ConfigIni') args = parser.parse_args() update_wrgeojson_from_osm_file(args.wrgeojson_title, args.osm_file, args.osm_index, args.ini_file) if __name__ == '__main__': main()