forked from MapComplete/MapComplete
		
	
		
			
	
	
		
			233 lines
		
	
	
	
		
			9.1 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
		
		
			
		
	
	
			233 lines
		
	
	
	
		
			9.1 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
| 
								 | 
							
								import Script from "../Script"
							 | 
						|||
| 
								 | 
							
								import { writeFileSync } from "fs"
							 | 
						|||
| 
								 | 
							
								import { Feature, Geometry } from "geojson"
							 | 
						|||
| 
								 | 
							
								import { OsmObject } from "../../src/Logic/Osm/OsmObject"
							 | 
						|||
| 
								 | 
							
								import OsmObjectDownloader from "../../src/Logic/Osm/OsmObjectDownloader"
							 | 
						|||
| 
								 | 
							
								import { Changes } from "../../src/Logic/Osm/Changes"
							 | 
						|||
| 
								 | 
							
								import { ImmutableStore } from "../../src/Logic/UIEventSource"
							 | 
						|||
| 
								 | 
							
								import { OsmConnection } from "../../src/Logic/Osm/OsmConnection"
							 | 
						|||
| 
								 | 
							
								import ChangeTagAction from "../../src/Logic/Osm/Actions/ChangeTagAction"
							 | 
						|||
| 
								 | 
							
								import { Tag } from "../../src/Logic/Tags/Tag"
							 | 
						|||
| 
								 | 
							
								import { ChangeDescription } from "../../src/Logic/Osm/Actions/ChangeDescription"
							 | 
						|||
| 
								 | 
							
								import { GeoOperations } from "../../src/Logic/GeoOperations"
							 | 
						|||
| 
								 | 
							
								import { Overpass } from "../../src/Logic/Osm/Overpass"
							 | 
						|||
| 
								 | 
							
								import { TagUtils } from "../../src/Logic/Tags/TagUtils"
							 | 
						|||
| 
								 | 
							
								import { BBox } from "../../src/Logic/BBox"
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								export default class CleanRepair extends Script {
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								    constructor() {
							 | 
						|||
| 
								 | 
							
								        super("Cleans 'repair'-tags for mass retagging")
							 | 
						|||
| 
								 | 
							
								    }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								    async main(args: string[]) {
							 | 
						|||
| 
								 | 
							
								        const path = args[0]
							 | 
						|||
| 
								 | 
							
								        console.log("Loading", path)
							 | 
						|||
| 
								 | 
							
								        const criteria = TagUtils.Tag({
							 | 
						|||
| 
								 | 
							
								            and: [
							 | 
						|||
| 
								 | 
							
								                "repair~*",
							 | 
						|||
| 
								 | 
							
								                "repair!=no",
							 | 
						|||
| 
								 | 
							
								                "repair!=yes",
							 | 
						|||
| 
								 | 
							
								                "repair!=brand",
							 | 
						|||
| 
								 | 
							
								                "repair!=only",
							 | 
						|||
| 
								 | 
							
								                "repair!=only_sold",
							 | 
						|||
| 
								 | 
							
								                "repair!=assisted_self_service"
							 | 
						|||
| 
								 | 
							
								            ]
							 | 
						|||
| 
								 | 
							
								        })
							 | 
						|||
| 
								 | 
							
								        const overpass = new Overpass(criteria, [],
							 | 
						|||
| 
								 | 
							
								            "https://overpass-api.de/api/interpreter"
							 | 
						|||
| 
								 | 
							
								        )
							 | 
						|||
| 
								 | 
							
								        const data: Feature<Geometry, Record<string, string>> [] = (await overpass.queryGeoJson(BBox.global))[0].features
							 | 
						|||
| 
								 | 
							
								        console.log("Got", data.length, "features; sample", data[0])
							 | 
						|||
| 
								 | 
							
								        const changes = new Changes({
							 | 
						|||
| 
								 | 
							
								            dryRun: new ImmutableStore(true),
							 | 
						|||
| 
								 | 
							
								            osmConnection: new OsmConnection({
							 | 
						|||
| 
								 | 
							
								                dryRun: new ImmutableStore(true)
							 | 
						|||
| 
								 | 
							
								            })
							 | 
						|||
| 
								 | 
							
								        })
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        const metakeys = ["id", "version", "changeset", "user", "uid", "timestamp"]
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        const replace = {
							 | 
						|||
| 
								 | 
							
								            "phone": "mobile_phone",
							 | 
						|||
| 
								 | 
							
								            "phones": "mobile_phone",
							 | 
						|||
| 
								 | 
							
								            "mobile": "mobile_phone",
							 | 
						|||
| 
								 | 
							
								            "cellphone": "mobile_phone",
							 | 
						|||
| 
								 | 
							
								            "pc": "computers",
							 | 
						|||
| 
								 | 
							
								            "mobile_phones": "mobile_phone",
							 | 
						|||
| 
								 | 
							
								            "mobilephones": "mobile_phone",
							 | 
						|||
| 
								 | 
							
								            "mobilephone": "mobile_phone",
							 | 
						|||
| 
								 | 
							
								            "clocks": "clock",
							 | 
						|||
| 
								 | 
							
								            "elektronik": "electronics",
							 | 
						|||
| 
								 | 
							
								            "tires": "tyres",
							 | 
						|||
| 
								 | 
							
								            "welcome": "yes",
							 | 
						|||
| 
								 | 
							
								            "tyre": "tyres",
							 | 
						|||
| 
								 | 
							
								            "electronic_products": "electronics",
							 | 
						|||
| 
								 | 
							
								            "shoe": "shoes",
							 | 
						|||
| 
								 | 
							
								            "pc_repairs": "computer",
							 | 
						|||
| 
								 | 
							
								            "computers": "computer",
							 | 
						|||
| 
								 | 
							
								            "body_construction": "body_work",
							 | 
						|||
| 
								 | 
							
								            "body": "body_work",
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            "body_repairer": "body_work",
							 | 
						|||
| 
								 | 
							
								            "instruments": "musical_instrument",
							 | 
						|||
| 
								 | 
							
								            "service": "yes",
							 | 
						|||
| 
								 | 
							
								            "punture": "tyres",
							 | 
						|||
| 
								 | 
							
								            "electricity": "electronics",
							 | 
						|||
| 
								 | 
							
								            "self_service": "assisted_self_repair",
							 | 
						|||
| 
								 | 
							
								            "paint": "bodywork",
							 | 
						|||
| 
								 | 
							
								            "paint shop": "bodywork",
							 | 
						|||
| 
								 | 
							
								            "paint_shop": "bodywork",
							 | 
						|||
| 
								 | 
							
								            "lawnmower": "lawn_mower",
							 | 
						|||
| 
								 | 
							
								            "aircon": "air_conditioning",
							 | 
						|||
| 
								 | 
							
								            "*": "yes",
							 | 
						|||
| 
								 | 
							
								            "ammeublement": "furniture",
							 | 
						|||
| 
								 | 
							
								            "all": "yes",
							 | 
						|||
| 
								 | 
							
								            "appliances": "appliance",
							 | 
						|||
| 
								 | 
							
								            "electronic": "electronics", "escooter": "electric_scooter",
							 | 
						|||
| 
								 | 
							
								            "aviation maintenance, repair, and_overhaul": "airplane",
							 | 
						|||
| 
								 | 
							
								            "aviation_maintenance": "airplanes",
							 | 
						|||
| 
								 | 
							
								            "bags": "bag",
							 | 
						|||
| 
								 | 
							
								            "boats": "boat",
							 | 
						|||
| 
								 | 
							
								            "boilers": "boiler",
							 | 
						|||
| 
								 | 
							
								            "breaks": "brakes",
							 | 
						|||
| 
								 | 
							
								            "car": "cars",
							 | 
						|||
| 
								 | 
							
								            "tv": "television",
							 | 
						|||
| 
								 | 
							
								            "clothing": "clothes",
							 | 
						|||
| 
								 | 
							
								            "coat_of_lacquer": "body_work",
							 | 
						|||
| 
								 | 
							
								            "cycle": "bicycle",
							 | 
						|||
| 
								 | 
							
								            "cars": "car",
							 | 
						|||
| 
								 | 
							
								            "blacharstwo": "tin", "lakiernictwo": "body_work",
							 | 
						|||
| 
								 | 
							
								            "tire": "tyres", "powder_coating": "body_work",
							 | 
						|||
| 
								 | 
							
								            "leather_products": "leather",
							 | 
						|||
| 
								 | 
							
								            "motocycle": "motorcycle",
							 | 
						|||
| 
								 | 
							
								            "motor": "motorcycle", "motoo": "motorcycle",
							 | 
						|||
| 
								 | 
							
								            "motorbike": "motorcycle", "motorcycle_repair": "motorcycle", "motorsports": "motorcycle",
							 | 
						|||
| 
								 | 
							
								            "printers": "printer",
							 | 
						|||
| 
								 | 
							
								            "tyres24": "tyres",
							 | 
						|||
| 
								 | 
							
								            "paintings": "painting",
							 | 
						|||
| 
								 | 
							
								            "paintwork": "body_work",
							 | 
						|||
| 
								 | 
							
								            "pumps": "pump",
							 | 
						|||
| 
								 | 
							
								            "shoes:yes": "shoes",
							 | 
						|||
| 
								 | 
							
								            "wheel": "tyres",
							 | 
						|||
| 
								 | 
							
								            "wheels": "tyres",
							 | 
						|||
| 
								 | 
							
								            "vacuum": "vacuum_cleaner",
							 | 
						|||
| 
								 | 
							
								            "glass": "car_glassj"
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        const brands = ["garage", "audi", "renault", "apple", "honda", "ducati", "ford", "mazda","garage_renault_aie"]
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        const valid = ["train", "tv", "jewelry", "scooter", ...Object.values(replace), "watch", "oldtimer", "car", "bicycle", "boat", "windbreaker",
							 | 
						|||
| 
								 | 
							
								            "agricultural", "alternator", "antiques", "atv", "auto",
							 | 
						|||
| 
								 | 
							
								            "aviation maintenance", "bag", "bags",
							 | 
						|||
| 
								 | 
							
								            "battery", "bicyle", "borehole", "building",
							 | 
						|||
| 
								 | 
							
								            "camera", "car_glass", "caravan",
							 | 
						|||
| 
								 | 
							
								            "carpenter", "coffee_machine", "construction machinery", "cycle",
							 | 
						|||
| 
								 | 
							
								            "dentures", "ducati", "electric motor",
							 | 
						|||
| 
								 | 
							
								            "electric_bike", "electric_scooter", "espresso_machines", "exhaust",
							 | 
						|||
| 
								 | 
							
								            "fire_extinguishers", "fountain_pen", "fridge",
							 | 
						|||
| 
								 | 
							
								            "garden_machinery", "gas appliances", "generator",
							 | 
						|||
| 
								 | 
							
								            "glasses", "golfcart", "guitar",
							 | 
						|||
| 
								 | 
							
								            "hammock", "hardware", "heating pumps",
							 | 
						|||
| 
								 | 
							
								            "hifi", "hvac", "installation", "jewellery", "keys", "kick_scooter",
							 | 
						|||
| 
								 | 
							
								            "kitesurfing", "tools", "toys", "tractor",
							 | 
						|||
| 
								 | 
							
								            "trailer", "transformer", "truck",
							 | 
						|||
| 
								 | 
							
								            "typewriter", "sail", "sewing_machine", "ship", "picture", "pillow", "plastic",
							 | 
						|||
| 
								 | 
							
								            "cash_register", "cnc", "laptop",
							 | 
						|||
| 
								 | 
							
								            "laundry_machines",
							 | 
						|||
| 
								 | 
							
								            "photo_camera", "photocopier", "piano",
							 | 
						|||
| 
								 | 
							
								            "power_tools", "pressure_gauges", "printer",
							 | 
						|||
| 
								 | 
							
								            , "snowboard", "snowmobile", "starter", "machines", "mainframe",
							 | 
						|||
| 
								 | 
							
								            "outboard_motor",
							 | 
						|||
| 
								 | 
							
								            "video", "washing_machine", "ski", "radiator",
							 | 
						|||
| 
								 | 
							
								            "radio", "refrigerator",
							 | 
						|||
| 
								 | 
							
								            "rv", "ski", "window", "zipper", "weighing_scale",
							 | 
						|||
| 
								 | 
							
								            "small_electric_vehicle"
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        ].map(s => s.replace(/ /g, "_"))
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        const skip = ["yes", "no", "only", "brand", "assisted_self_repair", "only_sold"]
							 | 
						|||
| 
								 | 
							
								        const dloader = new OsmObjectDownloader()
							 | 
						|||
| 
								 | 
							
								        const rm = ["50243147100015", "81342677200048", "and overhaul", "repair", "unset", "сервисный_центр", "taller_de_michu", "quitandinha_g_&_a", "mechanika"].map(v => v.replace(/ /g, "_"))
							 | 
						|||
| 
								 | 
							
								        const objects: OsmObject[] = []
							 | 
						|||
| 
								 | 
							
								        const changesToMake: ChangeDescription [] = []
							 | 
						|||
| 
								 | 
							
								        const first = GeoOperations.centerpointCoordinates(data[0])
							 | 
						|||
| 
								 | 
							
								        for (const f of data) {
							 | 
						|||
| 
								 | 
							
								            if (GeoOperations.distanceBetween(first, GeoOperations.centerpointCoordinates(f)) > 2500000) {
							 | 
						|||
| 
								 | 
							
								                continue
							 | 
						|||
| 
								 | 
							
								            }
							 | 
						|||
| 
								 | 
							
								            let keyRaw = f.properties.repair
							 | 
						|||
| 
								 | 
							
								            keyRaw = replace[keyRaw] ?? keyRaw
							 | 
						|||
| 
								 | 
							
								            if (brands.some(br => keyRaw.toLowerCase().indexOf(br.trim()) >= 0)) {
							 | 
						|||
| 
								 | 
							
								                f.properties.repair = "brand"
							 | 
						|||
| 
								 | 
							
								            } if(skip.indexOf(keyRaw) >= 0){
							 | 
						|||
| 
								 | 
							
								                f.properties.repair = keyRaw
							 | 
						|||
| 
								 | 
							
								            } else {
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								                const r = keyRaw.replace(/\/|,/g, ";").split(";").map(k => k.trim().replace(/ /g, "_").toLowerCase())
							 | 
						|||
| 
								 | 
							
								                for (let key of r) {
							 | 
						|||
| 
								 | 
							
								                    key = replace[key] ?? key
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								                    if (rm.indexOf(key) >= 0) {
							 | 
						|||
| 
								 | 
							
								                        delete f.properties.repair
							 | 
						|||
| 
								 | 
							
								                        continue
							 | 
						|||
| 
								 | 
							
								                    }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								                    f.properties[key + ":repair"] = "yes"
							 | 
						|||
| 
								 | 
							
								                    delete f.properties.repair
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								                }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            }
							 | 
						|||
| 
								 | 
							
								            if (f.properties.service === "repair") {
							 | 
						|||
| 
								 | 
							
								                delete f.properties.service
							 | 
						|||
| 
								 | 
							
								                f.properties.repair = "yes"
							 | 
						|||
| 
								 | 
							
								            }
							 | 
						|||
| 
								 | 
							
								            const id = f.properties["id"]
							 | 
						|||
| 
								 | 
							
								            const osm = await dloader.DownloadObjectAsync(id)
							 | 
						|||
| 
								 | 
							
								            if (osm === "deleted") {
							 | 
						|||
| 
								 | 
							
								                continue
							 | 
						|||
| 
								 | 
							
								            }
							 | 
						|||
| 
								 | 
							
								            objects.push(osm)
							 | 
						|||
| 
								 | 
							
								            for (const key in f.properties) {
							 | 
						|||
| 
								 | 
							
								                if (metakeys.indexOf(key) >= 0) {
							 | 
						|||
| 
								 | 
							
								                    continue
							 | 
						|||
| 
								 | 
							
								                }
							 | 
						|||
| 
								 | 
							
								                const value = f.properties[key]
							 | 
						|||
| 
								 | 
							
								                const ct = await new ChangeTagAction(id, new Tag(key, value), f.properties, {
							 | 
						|||
| 
								 | 
							
								                    changeType: "fix",
							 | 
						|||
| 
								 | 
							
								                    theme: "script"
							 | 
						|||
| 
								 | 
							
								                }).CreateChangeDescriptions()
							 | 
						|||
| 
								 | 
							
								                changesToMake.push(...ct)
							 | 
						|||
| 
								 | 
							
								                console.log(ct.map(cd => cd.tags))
							 | 
						|||
| 
								 | 
							
								                if (f.properties.repair === undefined) {
							 | 
						|||
| 
								 | 
							
								                    const ct = await new ChangeTagAction(id, new Tag("repair", ""), f.properties, {
							 | 
						|||
| 
								 | 
							
								                        changeType: "fix",
							 | 
						|||
| 
								 | 
							
								                        theme: "script"
							 | 
						|||
| 
								 | 
							
								                    }).CreateChangeDescriptions()
							 | 
						|||
| 
								 | 
							
								                    changesToMake.push(...ct)
							 | 
						|||
| 
								 | 
							
								                }
							 | 
						|||
| 
								 | 
							
								            }
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        const
							 | 
						|||
| 
								 | 
							
								            changedObjects = changes.CreateChangesetObjects(changesToMake, objects)
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        const
							 | 
						|||
| 
								 | 
							
								            osc = Changes.createChangesetFor("", changedObjects)
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        writeFileSync(
							 | 
						|||
| 
								 | 
							
								            "Cleanup.osc"
							 | 
						|||
| 
								 | 
							
								            ,
							 | 
						|||
| 
								 | 
							
								            osc
							 | 
						|||
| 
								 | 
							
								            ,
							 | 
						|||
| 
								 | 
							
								            "utf8"
							 | 
						|||
| 
								 | 
							
								        )
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								    }
							 | 
						|||
| 
								 | 
							
								}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								new CleanRepair().run()
							 |