| 
									
										
										
										
											2021-12-12 17:35:08 +01:00
										 |  |  | import BaseUIElement from "./BaseUIElement" | 
					
						
							|  |  |  | import Combine from "./Base/Combine" | 
					
						
							|  |  |  | import Svg from "../Svg" | 
					
						
							|  |  |  | import Title from "./Base/Title" | 
					
						
							|  |  |  | import Toggle from "./Input/Toggle" | 
					
						
							|  |  |  | import { SubtleButton } from "./Base/SubtleButton" | 
					
						
							|  |  |  | import LayoutConfig from "../Models/ThemeConfig/LayoutConfig" | 
					
						
							|  |  |  | import ValidatedTextField from "./Input/ValidatedTextField" | 
					
						
							|  |  |  | import { Utils } from "../Utils" | 
					
						
							|  |  |  | import { UIEventSource } from "../Logic/UIEventSource" | 
					
						
							|  |  |  | import { VariableUiElement } from "./Base/VariableUIElement" | 
					
						
							|  |  |  | import { FixedUiElement } from "./Base/FixedUiElement" | 
					
						
							|  |  |  | import { Tiles } from "../Models/TileRange" | 
					
						
							|  |  |  | import { LocalStorageSource } from "../Logic/Web/LocalStorageSource" | 
					
						
							|  |  |  | import { DropDown } from "./Input/DropDown" | 
					
						
							|  |  |  | import { AllKnownLayouts } from "../Customizations/AllKnownLayouts" | 
					
						
							|  |  |  | import MinimapImplementation from "./Base/MinimapImplementation" | 
					
						
							|  |  |  | import { OsmConnection } from "../Logic/Osm/OsmConnection" | 
					
						
							| 
									
										
										
										
											2021-12-13 02:05:34 +01:00
										 |  |  | import { BBox } from "../Logic/BBox" | 
					
						
							|  |  |  | import MapState from "../Logic/State/MapState" | 
					
						
							|  |  |  | import FeaturePipeline from "../Logic/FeatureSource/FeaturePipeline" | 
					
						
							|  |  |  | import LayerConfig from "../Models/ThemeConfig/LayerConfig" | 
					
						
							|  |  |  | import TagRenderingConfig from "../Models/ThemeConfig/TagRenderingConfig" | 
					
						
							|  |  |  | import FeatureSource from "../Logic/FeatureSource/FeatureSource" | 
					
						
							|  |  |  | import List from "./Base/List" | 
					
						
							|  |  |  | import { QueryParameters } from "../Logic/Web/QueryParameters" | 
					
						
							|  |  |  | import { SubstitutedTranslation } from "./SubstitutedTranslation" | 
					
						
							|  |  |  | import { AutoAction } from "./Popup/AutoApplyButton" | 
					
						
							| 
									
										
										
										
											2021-12-13 13:22:23 +01:00
										 |  |  | import DynamicGeoJsonTileSource from "../Logic/FeatureSource/TiledFeatureSource/DynamicGeoJsonTileSource" | 
					
						
							| 
									
										
										
										
											2023-02-08 01:14:21 +01:00
										 |  |  | import themeOverview from "../assets/generated/theme_overview.json" | 
					
						
							| 
									
										
										
										
											2021-12-12 17:35:08 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-26 21:40:38 +01:00
										 |  |  | class AutomationPanel extends Combine { | 
					
						
							| 
									
										
										
										
											2021-12-17 19:28:05 +01:00
										 |  |  |     private static readonly openChangeset = new UIEventSource<number>(undefined) | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-13 13:22:23 +01:00
										 |  |  |     constructor( | 
					
						
							|  |  |  |         layoutToUse: LayoutConfig, | 
					
						
							|  |  |  |         indices: number[], | 
					
						
							|  |  |  |         extraCommentText: UIEventSource<string>, | 
					
						
							|  |  |  |         tagRenderingToAutomate: { layer: LayerConfig; tagRendering: TagRenderingConfig } | 
					
						
							|  |  |  |     ) { | 
					
						
							|  |  |  |         const layerId = tagRenderingToAutomate.layer.id | 
					
						
							|  |  |  |         const trId = tagRenderingToAutomate.tagRendering.id | 
					
						
							|  |  |  |         const tileState = LocalStorageSource.GetParsed( | 
					
						
							|  |  |  |             "automation-tile_state-" + layerId + "-" + trId, | 
					
						
							|  |  |  |             {} | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |         const logMessages = new UIEventSource<string[]>([]) | 
					
						
							|  |  |  |         if (indices === undefined) { | 
					
						
							| 
									
										
										
										
											2022-01-26 21:40:38 +01:00
										 |  |  |             throw "No tiles loaded - can not automate" | 
					
						
							| 
									
										
										
										
											2021-12-13 13:22:23 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-12-17 19:28:05 +01:00
										 |  |  |         const openChangeset = AutomationPanel.openChangeset | 
					
						
							| 
									
										
										
										
											2022-01-26 21:40:38 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-17 19:28:05 +01:00
										 |  |  |         openChangeset.addCallbackAndRun((cs) => | 
					
						
							|  |  |  |             console.trace("Sync current open changeset to:", cs) | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         ) | 
					
						
							| 
									
										
										
										
											2021-12-12 17:35:08 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-13 13:22:23 +01:00
										 |  |  |         const nextTileToHandle = tileState.map((handledTiles) => { | 
					
						
							|  |  |  |             for (const index of indices) { | 
					
						
							|  |  |  |                 if (handledTiles[index] !== undefined) { | 
					
						
							|  |  |  |                     // Already handled
 | 
					
						
							|  |  |  |                     continue | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 return index | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             return undefined | 
					
						
							|  |  |  |         }) | 
					
						
							|  |  |  |         nextTileToHandle.addCallback((t) => console.warn("Next tile to handle is", t)) | 
					
						
							| 
									
										
										
										
											2021-12-12 17:35:08 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-13 13:22:23 +01:00
										 |  |  |         const neededTimes = new UIEventSource<number[]>([]) | 
					
						
							|  |  |  |         const automaton = new VariableUiElement( | 
					
						
							|  |  |  |             nextTileToHandle.map((tileIndex) => { | 
					
						
							|  |  |  |                 if (tileIndex === undefined) { | 
					
						
							|  |  |  |                     return new FixedUiElement("All done!").SetClass("thanks") | 
					
						
							|  |  |  |                 } | 
					
						
							| 
									
										
										
										
											2022-01-26 21:40:38 +01:00
										 |  |  |                 console.warn("Triggered map on nextTileToHandle", tileIndex) | 
					
						
							| 
									
										
										
										
											2021-12-13 13:22:23 +01:00
										 |  |  |                 const start = new Date() | 
					
						
							| 
									
										
										
										
											2021-12-13 20:51:44 +01:00
										 |  |  |                 return AutomationPanel.TileHandler( | 
					
						
							|  |  |  |                     layoutToUse, | 
					
						
							|  |  |  |                     tileIndex, | 
					
						
							|  |  |  |                     layerId, | 
					
						
							|  |  |  |                     tagRenderingToAutomate.tagRendering, | 
					
						
							|  |  |  |                     extraCommentText, | 
					
						
							|  |  |  |                     (result, logMessage) => { | 
					
						
							| 
									
										
										
										
											2022-01-26 21:40:38 +01:00
										 |  |  |                         const end = new Date() | 
					
						
							|  |  |  |                         const timeNeeded = (end.getTime() - start.getTime()) / 1000 | 
					
						
							|  |  |  |                         neededTimes.data.push(timeNeeded) | 
					
						
							|  |  |  |                         neededTimes.ping() | 
					
						
							|  |  |  |                         tileState.data[tileIndex] = result | 
					
						
							|  |  |  |                         tileState.ping() | 
					
						
							|  |  |  |                         if (logMessage !== undefined) { | 
					
						
							|  |  |  |                             logMessages.data.push(logMessage) | 
					
						
							|  |  |  |                             logMessages.ping() | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                         } | 
					
						
							| 
									
										
										
										
											2022-01-26 21:40:38 +01:00
										 |  |  |                     } | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                 ) | 
					
						
							| 
									
										
										
										
											2021-12-13 13:22:23 +01:00
										 |  |  |             }) | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         ) | 
					
						
							| 
									
										
										
										
											2021-12-12 17:35:08 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-13 13:22:23 +01:00
										 |  |  |         const statistics = new VariableUiElement( | 
					
						
							|  |  |  |             tileState.map((states) => { | 
					
						
							|  |  |  |                 let total = 0 | 
					
						
							|  |  |  |                 const perResult = new Map<string, number>() | 
					
						
							|  |  |  |                 for (const key in states) { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                     total++ | 
					
						
							| 
									
										
										
										
											2021-12-13 13:22:23 +01:00
										 |  |  |                     const result = states[key] | 
					
						
							|  |  |  |                     perResult.set(result, (perResult.get(result) ?? 0) + 1) | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                 } | 
					
						
							| 
									
										
										
										
											2021-12-12 17:35:08 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-13 13:22:23 +01:00
										 |  |  |                 let sum = 0 | 
					
						
							|  |  |  |                 neededTimes.data.forEach((v) => { | 
					
						
							|  |  |  |                     sum = sum + v | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                 }) | 
					
						
							| 
									
										
										
										
											2021-12-13 13:22:23 +01:00
										 |  |  |                 let timePerTile = sum / neededTimes.data.length | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 return new Combine([ | 
					
						
							|  |  |  |                     "Handled " + total + "/" + indices.length + " tiles: ", | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                     new List( | 
					
						
							| 
									
										
										
										
											2021-12-13 13:22:23 +01:00
										 |  |  |                         Array.from(perResult.keys()).map((key) => key + ": " + perResult.get(key)) | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                     ), | 
					
						
							| 
									
										
										
										
											2021-12-13 13:22:23 +01:00
										 |  |  |                     "Handling one tile needs " + | 
					
						
							|  |  |  |                         Math.floor(timePerTile * 100) / 100 + | 
					
						
							|  |  |  |                         "s on average. Estimated time left: " + | 
					
						
							|  |  |  |                         Utils.toHumanTime((indices.length - total) * timePerTile), | 
					
						
							|  |  |  |                 ]).SetClass("flex flex-col") | 
					
						
							|  |  |  |             }) | 
					
						
							| 
									
										
										
										
											2021-12-13 20:51:44 +01:00
										 |  |  |         ) | 
					
						
							| 
									
										
										
										
											2021-12-13 13:22:23 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-26 21:40:38 +01:00
										 |  |  |         super([ | 
					
						
							|  |  |  |             statistics, | 
					
						
							|  |  |  |             automaton, | 
					
						
							|  |  |  |             new SubtleButton(undefined, "Clear fixed").onClick(() => { | 
					
						
							| 
									
										
										
										
											2021-12-13 20:51:44 +01:00
										 |  |  |                 const st = tileState.data | 
					
						
							| 
									
										
										
										
											2022-01-26 21:40:38 +01:00
										 |  |  |                 for (const tileIndex in st) { | 
					
						
							|  |  |  |                     if (st[tileIndex] === "fixed") { | 
					
						
							|  |  |  |                         delete st[tileIndex] | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 tileState.ping() | 
					
						
							|  |  |  |             }), | 
					
						
							|  |  |  |             new VariableUiElement(logMessages.map((logMessages) => new List(logMessages))), | 
					
						
							|  |  |  |         ]) | 
					
						
							|  |  |  |         this.SetClass("flex flex-col") | 
					
						
							| 
									
										
										
										
											2021-12-13 13:22:23 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-26 21:40:38 +01:00
										 |  |  |     private static TileHandler( | 
					
						
							|  |  |  |         layoutToUse: LayoutConfig, | 
					
						
							|  |  |  |         tileIndex: number, | 
					
						
							|  |  |  |         targetLayer: string, | 
					
						
							|  |  |  |         targetAction: TagRenderingConfig, | 
					
						
							|  |  |  |         extraCommentText: UIEventSource<string>, | 
					
						
							| 
									
										
										
										
											2021-12-13 20:51:44 +01:00
										 |  |  |         whenDone: (result: string, logMessage?: string) => void | 
					
						
							|  |  |  |     ): BaseUIElement { | 
					
						
							| 
									
										
										
										
											2021-12-13 02:05:34 +01:00
										 |  |  |         const state = new MapState(layoutToUse, { attemptLogin: false }) | 
					
						
							| 
									
										
										
										
											2022-01-26 21:40:38 +01:00
										 |  |  |         extraCommentText.syncWith(state.changes.extraComment) | 
					
						
							| 
									
										
										
										
											2021-12-13 02:05:34 +01:00
										 |  |  |         const [z, x, y] = Tiles.tile_from_index(tileIndex) | 
					
						
							|  |  |  |         state.locationControl.setData({ | 
					
						
							|  |  |  |             zoom: z, | 
					
						
							|  |  |  |             lon: x, | 
					
						
							|  |  |  |             lat: y, | 
					
						
							|  |  |  |         }) | 
					
						
							|  |  |  |         state.currentBounds.setData(BBox.fromTileIndex(tileIndex)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         let targetTiles: UIEventSource<FeatureSource[]> = new UIEventSource<FeatureSource[]>([]) | 
					
						
							|  |  |  |         const pipeline = new FeaturePipeline((tile) => { | 
					
						
							|  |  |  |             const layerId = tile.layer.layerDef.id | 
					
						
							|  |  |  |             if (layerId === targetLayer) { | 
					
						
							|  |  |  |                 targetTiles.data.push(tile) | 
					
						
							|  |  |  |                 targetTiles.ping() | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         }, state) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         state.locationControl.ping() | 
					
						
							|  |  |  |         state.currentBounds.ping() | 
					
						
							|  |  |  |         const stateToShow = new UIEventSource("") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         pipeline.runningQuery.map( | 
					
						
							|  |  |  |             async (isRunning) => { | 
					
						
							|  |  |  |                 if (targetTiles.data.length === 0) { | 
					
						
							|  |  |  |                     stateToShow.setData("No data loaded yet...") | 
					
						
							|  |  |  |                     return | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 if (isRunning) { | 
					
						
							|  |  |  |                     stateToShow.setData( | 
					
						
							|  |  |  |                         "Waiting for all layers to be loaded... Has " + | 
					
						
							|  |  |  |                             targetTiles.data.length + | 
					
						
							|  |  |  |                             " tiles already" | 
					
						
							|  |  |  |                     ) | 
					
						
							|  |  |  |                     return | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 if (targetTiles.data.length === 0) { | 
					
						
							|  |  |  |                     stateToShow.setData("No features found to apply the action") | 
					
						
							|  |  |  |                     whenDone("empty") | 
					
						
							|  |  |  |                     return true | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 stateToShow.setData("Gathering applicable elements") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 let handled = 0 | 
					
						
							|  |  |  |                 let inspected = 0 | 
					
						
							| 
									
										
										
										
											2021-12-13 13:22:23 +01:00
										 |  |  |                 let log = [] | 
					
						
							| 
									
										
										
										
											2021-12-13 02:05:34 +01:00
										 |  |  |                 for (const targetTile of targetTiles.data) { | 
					
						
							|  |  |  |                     for (const ffs of targetTile.features.data) { | 
					
						
							|  |  |  |                         inspected++ | 
					
						
							|  |  |  |                         if (inspected % 10 === 0) { | 
					
						
							|  |  |  |                             stateToShow.setData( | 
					
						
							|  |  |  |                                 "Inspected " + | 
					
						
							|  |  |  |                                     inspected + | 
					
						
							|  |  |  |                                     " features, updated " + | 
					
						
							|  |  |  |                                     handled + | 
					
						
							|  |  |  |                                     " features" | 
					
						
							|  |  |  |                             ) | 
					
						
							|  |  |  |                         } | 
					
						
							|  |  |  |                         const feature = ffs.feature | 
					
						
							| 
									
										
										
										
											2021-12-13 13:22:23 +01:00
										 |  |  |                         const renderingTr = targetAction.GetRenderValue(feature.properties) | 
					
						
							|  |  |  |                         const rendering = renderingTr.txt | 
					
						
							| 
									
										
										
										
											2022-06-28 03:21:18 +02:00
										 |  |  |                         log.push( | 
					
						
							|  |  |  |                             "<a href='https://openstreetmap.org/" + | 
					
						
							|  |  |  |                                 feature.properties.id + | 
					
						
							|  |  |  |                                 "' target='_blank'>" + | 
					
						
							|  |  |  |                                 feature.properties.id + | 
					
						
							|  |  |  |                                 "</a>: " + | 
					
						
							|  |  |  |                                 new SubstitutedTranslation( | 
					
						
							|  |  |  |                                     renderingTr, | 
					
						
							|  |  |  |                                     new UIEventSource<any>(feature.properties), | 
					
						
							|  |  |  |                                     undefined | 
					
						
							|  |  |  |                                 ).ConstructElement().textContent | 
					
						
							| 
									
										
										
										
											2021-12-13 02:05:34 +01:00
										 |  |  |                         ) | 
					
						
							|  |  |  |                         const actions = Utils.NoNull( | 
					
						
							|  |  |  |                             SubstitutedTranslation.ExtractSpecialComponents(rendering).map( | 
					
						
							|  |  |  |                                 (obj) => obj.special | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                             ) | 
					
						
							|  |  |  |                         ) | 
					
						
							| 
									
										
										
										
											2021-12-13 02:05:34 +01:00
										 |  |  |                         for (const action of actions) { | 
					
						
							|  |  |  |                             const auto = <AutoAction>action.func | 
					
						
							|  |  |  |                             if (auto.supportsAutoAction !== true) { | 
					
						
							|  |  |  |                                 continue | 
					
						
							|  |  |  |                             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                             await auto.applyActionOn( | 
					
						
							|  |  |  |                                 { | 
					
						
							|  |  |  |                                     layoutToUse: state.layoutToUse, | 
					
						
							|  |  |  |                                     changes: state.changes, | 
					
						
							|  |  |  |                                 }, | 
					
						
							|  |  |  |                                 state.allElements.getEventSourceById(feature.properties.id), | 
					
						
							|  |  |  |                                 action.args | 
					
						
							|  |  |  |                             ) | 
					
						
							|  |  |  |                             handled++ | 
					
						
							|  |  |  |                         } | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 stateToShow.setData( | 
					
						
							|  |  |  |                     "Done! Inspected " + inspected + " features, updated " + handled + " features" | 
					
						
							|  |  |  |                 ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 if (inspected === 0) { | 
					
						
							|  |  |  |                     whenDone("empty") | 
					
						
							| 
									
										
										
										
											2021-12-13 13:22:23 +01:00
										 |  |  |                     return true | 
					
						
							| 
									
										
										
										
											2021-12-13 02:05:34 +01:00
										 |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 if (handled === 0) { | 
					
						
							| 
									
										
										
										
											2022-01-26 21:40:38 +01:00
										 |  |  |                     whenDone("no-action", "Inspected " + inspected + " elements: " + log.join("; ")) | 
					
						
							|  |  |  |                 } else { | 
					
						
							| 
									
										
										
										
											2021-12-13 20:51:44 +01:00
										 |  |  |                     state.osmConnection.AttemptLogin() | 
					
						
							| 
									
										
										
										
											2022-06-05 02:24:14 +02:00
										 |  |  |                     state.changes.flushChanges("handled tile automatically, time to flush!") | 
					
						
							| 
									
										
										
										
											2022-01-26 21:40:38 +01:00
										 |  |  |                     whenDone( | 
					
						
							|  |  |  |                         "fixed", | 
					
						
							|  |  |  |                         "Updated " + | 
					
						
							|  |  |  |                             handled + | 
					
						
							|  |  |  |                             " elements, inspected " + | 
					
						
							|  |  |  |                             inspected + | 
					
						
							|  |  |  |                             ": " + | 
					
						
							|  |  |  |                             log.join("; ") | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                     ) | 
					
						
							| 
									
										
										
										
											2021-12-13 02:05:34 +01:00
										 |  |  |                 } | 
					
						
							| 
									
										
										
										
											2021-12-13 13:22:23 +01:00
										 |  |  |                 return true | 
					
						
							| 
									
										
										
										
											2021-12-13 02:05:34 +01:00
										 |  |  |             }, | 
					
						
							|  |  |  |             [targetTiles] | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return new Combine([ | 
					
						
							|  |  |  |             new Title("Performing action for tile " + tileIndex, 1), | 
					
						
							|  |  |  |             new VariableUiElement(stateToShow), | 
					
						
							|  |  |  |         ]).SetClass("flex flex-col") | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-12-13 13:22:23 +01:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2021-12-13 02:05:34 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-13 13:22:23 +01:00
										 |  |  | class AutomatonGui { | 
					
						
							|  |  |  |     constructor() { | 
					
						
							|  |  |  |         const osmConnection = new OsmConnection({ | 
					
						
							|  |  |  |             singlePage: false, | 
					
						
							|  |  |  |             oauth_token: QueryParameters.GetQueryParameter("oauth_token", "OAuth token"), | 
					
						
							|  |  |  |         }) | 
					
						
							| 
									
										
										
										
											2021-12-13 02:05:34 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-13 13:22:23 +01:00
										 |  |  |         new Combine([ | 
					
						
							|  |  |  |             new Combine([ | 
					
						
							|  |  |  |                 Svg.robot_svg().SetClass("w-24 h-24 p-4 rounded-full subtle-background"), | 
					
						
							|  |  |  |                 new Combine([ | 
					
						
							|  |  |  |                     new Title("MapComplete Automaton", 1), | 
					
						
							|  |  |  |                     "This page helps to automate certain tasks for a theme. Expert use only.", | 
					
						
							|  |  |  |                 ]).SetClass("flex flex-col m-4"), | 
					
						
							|  |  |  |             ]).SetClass("flex"), | 
					
						
							|  |  |  |             new Toggle( | 
					
						
							|  |  |  |                 AutomatonGui.GenerateMainPanel(), | 
					
						
							|  |  |  |                 new SubtleButton(Svg.osm_logo_svg(), "Login to get started").onClick(() => | 
					
						
							|  |  |  |                     osmConnection.AttemptLogin() | 
					
						
							|  |  |  |                 ), | 
					
						
							|  |  |  |                 osmConnection.isLoggedIn | 
					
						
							| 
									
										
										
										
											2022-01-26 21:40:38 +01:00
										 |  |  |             ), | 
					
						
							|  |  |  |         ]) | 
					
						
							|  |  |  |             .SetClass("block p-4") | 
					
						
							| 
									
										
										
										
											2021-12-13 13:22:23 +01:00
										 |  |  |             .AttachTo("main") | 
					
						
							| 
									
										
										
										
											2021-12-12 17:35:08 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     private static GenerateMainPanel(): BaseUIElement { | 
					
						
							|  |  |  |         const themeSelect = new DropDown<string>( | 
					
						
							|  |  |  |             "Select a theme", | 
					
						
							| 
									
										
										
										
											2022-01-26 21:40:38 +01:00
										 |  |  |             Array.from(themeOverview).map((l) => ({ value: l.id, shown: l.id })) | 
					
						
							| 
									
										
										
										
											2021-12-12 17:35:08 +01:00
										 |  |  |         ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-13 20:51:44 +01:00
										 |  |  |         LocalStorageSource.Get("automation-theme-id", "missing_streets").syncWith( | 
					
						
							|  |  |  |             themeSelect.GetValue() | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         ) | 
					
						
							| 
									
										
										
										
											2021-12-12 17:35:08 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-12 02:53:41 +01:00
										 |  |  |         const tilepath = ValidatedTextField.ForType("url").ConstructInputElement({ | 
					
						
							| 
									
										
										
										
											2021-12-12 17:35:08 +01:00
										 |  |  |             placeholder: "Specifiy the path of the overview", | 
					
						
							| 
									
										
										
										
											2022-02-11 01:20:01 +01:00
										 |  |  |             inputStyle: "width: 100%", | 
					
						
							| 
									
										
										
										
											2021-12-12 17:35:08 +01:00
										 |  |  |         }) | 
					
						
							|  |  |  |         tilepath.SetClass("w-full") | 
					
						
							|  |  |  |         LocalStorageSource.Get("automation-tile_path").syncWith(tilepath.GetValue(), true) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-13 02:05:34 +01:00
										 |  |  |         let tilesToRunOver = tilepath.GetValue().bind((path) => { | 
					
						
							| 
									
										
										
										
											2021-12-12 17:35:08 +01:00
										 |  |  |             if (path === undefined) { | 
					
						
							|  |  |  |                 return undefined | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2022-01-26 21:40:38 +01:00
										 |  |  |             return UIEventSource.FromPromiseWithErr(Utils.downloadJsonCached(path, 1000 * 60 * 60)) | 
					
						
							| 
									
										
										
										
											2021-12-12 17:35:08 +01:00
										 |  |  |         }) | 
					
						
							| 
									
										
										
										
											2022-01-26 21:40:38 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-13 02:05:34 +01:00
										 |  |  |         const targetZoom = 14 | 
					
						
							| 
									
										
										
										
											2021-12-12 17:35:08 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         const tilesPerIndex = tilesToRunOver.map((tiles) => { | 
					
						
							|  |  |  |             if (tiles === undefined || tiles["error"] !== undefined) { | 
					
						
							|  |  |  |                 return undefined | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2022-01-26 21:40:38 +01:00
										 |  |  |             let indexes: number[] = [] | 
					
						
							| 
									
										
										
										
											2021-12-12 17:35:08 +01:00
										 |  |  |             const tilesS = tiles["success"] | 
					
						
							| 
									
										
										
										
											2022-01-26 21:40:38 +01:00
										 |  |  |             DynamicGeoJsonTileSource.RegisterWhitelist(tilepath.GetValue().data, tilesS) | 
					
						
							| 
									
										
										
										
											2021-12-12 17:35:08 +01:00
										 |  |  |             const z = Number(tilesS["zoom"]) | 
					
						
							|  |  |  |             for (const key in tilesS) { | 
					
						
							|  |  |  |                 if (key === "zoom") { | 
					
						
							|  |  |  |                     continue | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 const x = Number(key) | 
					
						
							|  |  |  |                 const ys = tilesS[key] | 
					
						
							|  |  |  |                 indexes.push(...ys.map((y) => Tiles.tile_index(z, x, y))) | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2021-12-13 02:05:34 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |             console.log("Got ", indexes.length, "indexes") | 
					
						
							|  |  |  |             let rezoomed = new Set<number>() | 
					
						
							|  |  |  |             for (const index of indexes) { | 
					
						
							|  |  |  |                 let [z, x, y] = Tiles.tile_from_index(index) | 
					
						
							|  |  |  |                 while (z > targetZoom) { | 
					
						
							|  |  |  |                     z-- | 
					
						
							|  |  |  |                     x = Math.floor(x / 2) | 
					
						
							|  |  |  |                     y = Math.floor(y / 2) | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 rezoomed.add(Tiles.tile_index(z, x, y)) | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             return Array.from(rezoomed) | 
					
						
							| 
									
										
										
										
											2021-12-12 17:35:08 +01:00
										 |  |  |         }) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-12 02:53:41 +01:00
										 |  |  |         const extraComment = ValidatedTextField.ForType("text").ConstructInputElement() | 
					
						
							| 
									
										
										
										
											2021-12-13 02:05:34 +01:00
										 |  |  |         LocalStorageSource.Get("automaton-extra-comment").syncWith(extraComment.GetValue()) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-12 17:35:08 +01:00
										 |  |  |         return new Combine([ | 
					
						
							|  |  |  |             themeSelect, | 
					
						
							|  |  |  |             "Specify the path to a tile overview. This is a hosted .json of the format {x : [y0, y1, y2], x1: [y0, ...]} where x is a string and y are numbers", | 
					
						
							|  |  |  |             tilepath, | 
					
						
							| 
									
										
										
										
											2021-12-13 13:22:23 +01:00
										 |  |  |             "Add an extra comment:", | 
					
						
							| 
									
										
										
										
											2021-12-13 02:05:34 +01:00
										 |  |  |             extraComment, | 
					
						
							| 
									
										
										
										
											2022-01-26 21:40:38 +01:00
										 |  |  |             new VariableUiElement( | 
					
						
							|  |  |  |                 extraComment | 
					
						
							|  |  |  |                     .GetValue() | 
					
						
							|  |  |  |                     .map((c) => "Your comment is " + (c?.length ?? 0) + "/200 characters long") | 
					
						
							|  |  |  |             ).SetClass("subtle"), | 
					
						
							| 
									
										
										
										
											2021-12-12 17:35:08 +01:00
										 |  |  |             new VariableUiElement( | 
					
						
							|  |  |  |                 tilesToRunOver.map((t) => { | 
					
						
							|  |  |  |                     if (t === undefined) { | 
					
						
							|  |  |  |                         return "No path given or still loading..." | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                     if (t["error"] !== undefined) { | 
					
						
							|  |  |  |                         return new FixedUiElement("Invalid URL or data: " + t["error"]).SetClass( | 
					
						
							| 
									
										
										
										
											2021-12-13 02:05:34 +01:00
										 |  |  |                             "alert" | 
					
						
							|  |  |  |                         ) | 
					
						
							|  |  |  |                     } | 
					
						
							| 
									
										
										
										
											2021-12-12 17:35:08 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-13 02:05:34 +01:00
										 |  |  |                     return new FixedUiElement( | 
					
						
							| 
									
										
										
										
											2021-12-12 17:35:08 +01:00
										 |  |  |                         "Loaded " + tilesPerIndex.data.length + " tiles to automated over" | 
					
						
							|  |  |  |                     ).SetClass("thanks") | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                 }) | 
					
						
							|  |  |  |             ), | 
					
						
							| 
									
										
										
										
											2021-12-13 13:22:23 +01:00
										 |  |  |             new VariableUiElement( | 
					
						
							| 
									
										
										
										
											2021-12-12 17:35:08 +01:00
										 |  |  |                 themeSelect | 
					
						
							| 
									
										
										
										
											2021-12-13 13:22:23 +01:00
										 |  |  |                     .GetValue() | 
					
						
							| 
									
										
										
										
											2021-12-12 17:35:08 +01:00
										 |  |  |                     .map((id) => AllKnownLayouts.allKnownLayouts.get(id)) | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                     .map( | 
					
						
							| 
									
										
										
										
											2021-12-12 17:35:08 +01:00
										 |  |  |                         (layoutToUse) => { | 
					
						
							| 
									
										
										
										
											2021-12-13 13:22:23 +01:00
										 |  |  |                             if (layoutToUse === undefined) { | 
					
						
							| 
									
										
										
										
											2021-12-13 02:05:34 +01:00
										 |  |  |                                 return new FixedUiElement("Select a valid layout") | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                             } | 
					
						
							|  |  |  |                             if ( | 
					
						
							| 
									
										
										
										
											2021-12-13 02:05:34 +01:00
										 |  |  |                                 tilesPerIndex.data === undefined || | 
					
						
							|  |  |  |                                 tilesPerIndex.data.length === 0 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                             ) { | 
					
						
							| 
									
										
										
										
											2021-12-13 02:05:34 +01:00
										 |  |  |                                 return "No tiles given" | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                             } | 
					
						
							| 
									
										
										
										
											2021-12-12 17:35:08 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-13 02:05:34 +01:00
										 |  |  |                             const automatableTagRenderings: { | 
					
						
							|  |  |  |                                 layer: LayerConfig | 
					
						
							|  |  |  |                                 tagRendering: TagRenderingConfig | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                             }[] = [] | 
					
						
							| 
									
										
										
										
											2021-12-13 02:05:34 +01:00
										 |  |  |                             for (const layer of layoutToUse.layers) { | 
					
						
							|  |  |  |                                 for (const tagRendering of layer.tagRenderings) { | 
					
						
							|  |  |  |                                     if (tagRendering.group === "auto") { | 
					
						
							|  |  |  |                                         automatableTagRenderings.push({ | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                                             layer, | 
					
						
							| 
									
										
										
										
											2021-12-13 02:05:34 +01:00
										 |  |  |                                             tagRendering: tagRendering, | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                                         }) | 
					
						
							|  |  |  |                                     } | 
					
						
							|  |  |  |                                 } | 
					
						
							|  |  |  |                             } | 
					
						
							| 
									
										
										
										
											2021-12-13 02:05:34 +01:00
										 |  |  |                             console.log("Automatable tag renderings:", automatableTagRenderings) | 
					
						
							|  |  |  |                             if (automatableTagRenderings.length === 0) { | 
					
						
							|  |  |  |                                 return new FixedUiElement( | 
					
						
							|  |  |  |                                     'This theme does not have any tagRendering with "group": "auto" set' | 
					
						
							|  |  |  |                                 ).SetClass("alert") | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                             } | 
					
						
							| 
									
										
										
										
											2021-12-13 02:05:34 +01:00
										 |  |  |                             const pickAuto = new DropDown("Pick the action to automate", [ | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                                 { | 
					
						
							| 
									
										
										
										
											2021-12-13 02:05:34 +01:00
										 |  |  |                                     value: undefined, | 
					
						
							|  |  |  |                                     shown: "Pick an option", | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                                 }, | 
					
						
							| 
									
										
										
										
											2021-12-13 02:05:34 +01:00
										 |  |  |                                 ...automatableTagRenderings.map((config) => ({ | 
					
						
							|  |  |  |                                     shown: config.layer.id + " - " + config.tagRendering.id, | 
					
						
							|  |  |  |                                     value: config, | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                                 })), | 
					
						
							|  |  |  |                             ]) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-13 02:05:34 +01:00
										 |  |  |                             return new Combine([ | 
					
						
							|  |  |  |                                 pickAuto, | 
					
						
							| 
									
										
										
										
											2021-12-13 13:22:23 +01:00
										 |  |  |                                 new VariableUiElement( | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                                     pickAuto | 
					
						
							| 
									
										
										
										
											2021-12-13 13:22:23 +01:00
										 |  |  |                                         .GetValue() | 
					
						
							|  |  |  |                                         .map((auto) => | 
					
						
							|  |  |  |                                             auto === undefined | 
					
						
							|  |  |  |                                                 ? undefined | 
					
						
							|  |  |  |                                                 : new AutomationPanel( | 
					
						
							|  |  |  |                                                       layoutToUse, | 
					
						
							|  |  |  |                                                       tilesPerIndex.data, | 
					
						
							|  |  |  |                                                       extraComment.GetValue(), | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                                                       auto | 
					
						
							|  |  |  |                                                   ) | 
					
						
							|  |  |  |                                         ) | 
					
						
							|  |  |  |                                 ), | 
					
						
							|  |  |  |                             ]) | 
					
						
							|  |  |  |                         }, | 
					
						
							| 
									
										
										
										
											2021-12-13 02:05:34 +01:00
										 |  |  |                         [tilesPerIndex] | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                     ) | 
					
						
							| 
									
										
										
										
											2021-12-13 02:05:34 +01:00
										 |  |  |             ).SetClass("flex flex-col"), | 
					
						
							| 
									
										
										
										
											2021-12-12 17:35:08 +01:00
										 |  |  |         ]).SetClass("flex flex-col") | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | MinimapImplementation.initialize() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | new AutomatonGui() |