| 
									
										
										
										
											2025-07-05 04:40:43 +02:00
										 |  |  | import Script from "./Script" | 
					
						
							|  |  |  | import ScriptUtils from "./ScriptUtils" | 
					
						
							|  |  |  | import { LayerConfigJson } from "../src/Models/ThemeConfig/Json/LayerConfigJson" | 
					
						
							|  |  |  | import { readFileSync, statSync } from "fs" | 
					
						
							|  |  |  | import LayerConfig from "../src/Models/ThemeConfig/LayerConfig" | 
					
						
							|  |  |  | import { PrepareLayer } from "../src/Models/ThemeConfig/Conversion/PrepareLayer" | 
					
						
							|  |  |  | import { TagUtils } from "../src/Logic/Tags/TagUtils" | 
					
						
							| 
									
										
										
										
											2025-07-05 05:04:19 +02:00
										 |  |  | import TagInfo from "../src/Logic/Web/TagInfo" | 
					
						
							| 
									
										
										
										
											2025-07-05 04:40:43 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | class CompareLayer { | 
					
						
							|  |  |  |     private _knownLayers: Map<string, LayerConfigJson> | 
					
						
							| 
									
										
										
										
											2025-07-05 05:04:19 +02:00
										 |  |  |     private static readonly tagInfo = new TagInfo() | 
					
						
							| 
									
										
										
										
											2025-07-05 04:40:43 +02:00
										 |  |  |     constructor(knownLayers: Map<string, LayerConfigJson>) { | 
					
						
							|  |  |  |         this._knownLayers = knownLayers | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-05 05:04:19 +02:00
										 |  |  |     public async compare(layer: LayerConfigJson, path: string) { | 
					
						
							| 
									
										
										
										
											2025-07-05 04:40:43 +02:00
										 |  |  |         const candidate = this._knownLayers.get(layer.id) | 
					
						
							|  |  |  |         if (!layer.source?.["osmTags"]) { | 
					
						
							|  |  |  |             return | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         layer.tagRenderings = layer.tagRenderings?.filter(tr => tr !== "images") ?? [] | 
					
						
							|  |  |  |         if(layer.tagRenderings.length === 0){ | 
					
						
							|  |  |  |             return | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (!candidate) { | 
					
						
							|  |  |  |             console.log("## " + layer.id + " (unique)") | 
					
						
							|  |  |  |             const info = statSync(path) | 
					
						
							|  |  |  |             console.log(`\n[${layer.id}](${path}) Last edited ${info.mtime.toISOString()}\n\n`) | 
					
						
							|  |  |  |             const source = TagUtils.Tag(layer.source?.["osmTags"]) | 
					
						
							| 
									
										
										
										
											2025-07-05 05:04:19 +02:00
										 |  |  |             let estimate = undefined | 
					
						
							|  |  |  |             try { | 
					
						
							|  |  |  |                 estimate = await CompareLayer.tagInfo.getCountEstimateFor(source) | 
					
						
							|  |  |  |             } catch (e) { | 
					
						
							|  |  |  |                 console.log("Error trying to get an estimate", e) | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             console.log(source.asHumanString(true, false) + " (estimated " + estimate + " items)") | 
					
						
							| 
									
										
										
										
											2025-07-05 04:40:43 +02:00
										 |  |  |             if (layer.tagRenderings.length === 0) { | 
					
						
							|  |  |  |                 console.log("MINIMAL") | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             console.log("> "+layer.description?.["en"]) | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class InspectStudioLayers extends Script { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     constructor() { | 
					
						
							|  |  |  |         super("Iterates over all the studio layers and tries to match it with an already existing layer and list differences") | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     async main(args: string[]): Promise<void> { | 
					
						
							|  |  |  |         const path = args[0] ?? "/home/pietervdvn/data/mapcomplete-custom-themes" | 
					
						
							| 
									
										
										
										
											2025-07-05 05:04:19 +02:00
										 |  |  |         ScriptUtils.erasableLog = () => {} | 
					
						
							| 
									
										
										
										
											2025-07-05 04:40:43 +02:00
										 |  |  |         const files = ScriptUtils.readDirRecSync(path) | 
					
						
							|  |  |  |             .filter(p => p.endsWith(".json")) | 
					
						
							|  |  |  |             .filter(p => p.indexOf("/themes/") < 0) | 
					
						
							|  |  |  |             .filter(p => !p.endsWith("license_info.json") && p.indexOf(".stversions") < 0) | 
					
						
							|  |  |  |         const officialFiles = new Map<string, LayerConfigJson>() | 
					
						
							|  |  |  |         const unofficial: { layer: LayerConfigJson, path: string }[] = [] | 
					
						
							|  |  |  |         for (const file of files) { | 
					
						
							|  |  |  |             const rest = file.substring(path.length + 1) | 
					
						
							|  |  |  |             console.log("Loading ", rest) | 
					
						
							|  |  |  |             try { | 
					
						
							|  |  |  |                 const config = <LayerConfigJson>JSON.parse(readFileSync(file, "utf-8")) | 
					
						
							|  |  |  |                 if (rest.indexOf("layers") < 3) { | 
					
						
							|  |  |  |                     officialFiles.set(config.id, config) | 
					
						
							|  |  |  |                 } else { | 
					
						
							|  |  |  |                     unofficial.push({ layer: config, path: file }) | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } catch (e) { | 
					
						
							|  |  |  |                 console.error("COULD NOT READ/PARSE", file, "ignoring it") | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         console.log("Loaded", unofficial.length, "custom layers and ", officialFiles.size, "official layers") | 
					
						
							|  |  |  |         const comp = new CompareLayer(officialFiles) | 
					
						
							|  |  |  |         for (const layerConfigJson of unofficial) { | 
					
						
							| 
									
										
										
										
											2025-07-05 05:04:19 +02:00
										 |  |  |             await comp.compare(layerConfigJson.layer, layerConfigJson.path) | 
					
						
							| 
									
										
										
										
											2025-07-05 04:40:43 +02:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | new InspectStudioLayers().run() |