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() |