| 
									
										
										
										
											2022-11-08 14:37:48 +01:00
										 |  |  | import { OsmNode, OsmObject, OsmRelation, OsmWay } from "./OsmObject" | 
					
						
							|  |  |  | import { UIEventSource } from "../UIEventSource" | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  | import Constants from "../../Models/Constants" | 
					
						
							|  |  |  | import OsmChangeAction from "./Actions/OsmChangeAction" | 
					
						
							| 
									
										
										
										
											2022-11-08 14:37:48 +01:00
										 |  |  | import { ChangeDescription, ChangeDescriptionTools } from "./Actions/ChangeDescription" | 
					
						
							|  |  |  | import { Utils } from "../../Utils" | 
					
						
							|  |  |  | import { LocalStorageSource } from "../Web/LocalStorageSource" | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  | import SimpleMetaTagger from "../SimpleMetaTagger" | 
					
						
							|  |  |  | import FeatureSource from "../FeatureSource/FeatureSource" | 
					
						
							| 
									
										
										
										
											2022-11-08 14:37:48 +01:00
										 |  |  | import { ElementStorage } from "../ElementStorage" | 
					
						
							| 
									
										
										
										
											2022-12-22 04:13:52 +01:00
										 |  |  | import { GeoLocationPointProperties } from "../State/GeoLocationState" | 
					
						
							| 
									
										
										
										
											2022-11-08 14:37:48 +01:00
										 |  |  | import { GeoOperations } from "../GeoOperations" | 
					
						
							|  |  |  | import { ChangesetHandler, ChangesetTag } from "./ChangesetHandler" | 
					
						
							|  |  |  | import { OsmConnection } from "./OsmConnection" | 
					
						
							| 
									
										
										
										
											2020-06-24 00:35:19 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-03 03:09:52 +01:00
										 |  |  | /** | 
					
						
							|  |  |  |  * Handles all changes made to OSM. | 
					
						
							|  |  |  |  * Needs an authenticator via OsmConnection | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2021-07-15 20:47:28 +02:00
										 |  |  | export class Changes { | 
					
						
							| 
									
										
										
										
											2021-04-23 12:56:56 +02:00
										 |  |  |     public readonly name = "Newly added features" | 
					
						
							| 
									
										
										
										
											2021-02-20 22:18:42 +01:00
										 |  |  |     /** | 
					
						
							| 
									
										
										
										
											2021-07-15 20:47:28 +02:00
										 |  |  |      * All the newly created features as featureSource + all the modified features | 
					
						
							| 
									
										
										
										
											2021-02-20 22:18:42 +01:00
										 |  |  |      */ | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |     public features = new UIEventSource<{ feature: any; freshness: Date }[]>([]) | 
					
						
							|  |  |  |     public readonly pendingChanges: UIEventSource<ChangeDescription[]> = | 
					
						
							|  |  |  |         LocalStorageSource.GetParsed<ChangeDescription[]>("pending-changes", []) | 
					
						
							| 
									
										
										
										
											2021-09-22 05:02:09 +02:00
										 |  |  |     public readonly allChanges = new UIEventSource<ChangeDescription[]>(undefined) | 
					
						
							| 
									
										
										
										
											2022-02-16 01:46:55 +01:00
										 |  |  |     public readonly state: { allElements: ElementStorage; osmConnection: OsmConnection } | 
					
						
							| 
									
										
										
										
											2022-01-26 21:40:38 +01:00
										 |  |  |     public readonly extraComment: UIEventSource<string> = new UIEventSource(undefined) | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-16 01:46:55 +01:00
										 |  |  |     private historicalUserLocations: FeatureSource | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |     private _nextId: number = -1 // Newly assigned ID's are negative
 | 
					
						
							|  |  |  |     private readonly isUploading = new UIEventSource(false) | 
					
						
							| 
									
										
										
										
											2021-09-09 00:05:51 +02:00
										 |  |  |     private readonly previouslyCreated: OsmObject[] = [] | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |     private readonly _leftRightSensitive: boolean | 
					
						
							|  |  |  |     private _changesetHandler: ChangesetHandler | 
					
						
							| 
									
										
										
										
											2021-12-05 05:19:59 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-13 02:05:34 +01:00
										 |  |  |     constructor( | 
					
						
							|  |  |  |         state?: { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             allElements: ElementStorage | 
					
						
							| 
									
										
										
										
											2021-12-13 02:05:34 +01:00
										 |  |  |             osmConnection: OsmConnection | 
					
						
							|  |  |  |         }, | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         leftRightSensitive: boolean = false | 
					
						
							|  |  |  |     ) { | 
					
						
							|  |  |  |         this._leftRightSensitive = leftRightSensitive | 
					
						
							| 
									
										
										
										
											2021-09-22 05:02:09 +02:00
										 |  |  |         // We keep track of all changes just as well
 | 
					
						
							|  |  |  |         this.allChanges.setData([...this.pendingChanges.data]) | 
					
						
							| 
									
										
										
										
											2021-09-22 16:07:56 +02:00
										 |  |  |         // If a pending change contains a negative ID, we save that
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         this._nextId = Math.min(-1, ...(this.pendingChanges.data?.map((pch) => pch.id) ?? [])) | 
					
						
							|  |  |  |         this.state = state | 
					
						
							|  |  |  |         this._changesetHandler = state?.osmConnection?.CreateChangesetHandler( | 
					
						
							|  |  |  |             state.allElements, | 
					
						
							|  |  |  |             this | 
					
						
							|  |  |  |         ) | 
					
						
							| 
									
										
										
										
											2021-09-26 23:35:26 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         // Note: a changeset might be reused which was opened just before and might have already used some ids
 | 
					
						
							|  |  |  |         // This doesn't matter however, as the '-1' is per piecewise upload, not global per changeset
 | 
					
						
							| 
									
										
										
										
											2021-07-15 20:47:28 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |     static createChangesetFor( | 
					
						
							|  |  |  |         csId: string, | 
					
						
							|  |  |  |         allChanges: { | 
					
						
							|  |  |  |             modifiedObjects: OsmObject[] | 
					
						
							|  |  |  |             newObjects: OsmObject[] | 
					
						
							|  |  |  |             deletedObjects: OsmObject[] | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     ): string { | 
					
						
							| 
									
										
										
										
											2021-07-15 20:47:28 +02:00
										 |  |  |         const changedElements = allChanges.modifiedObjects ?? [] | 
					
						
							| 
									
										
										
										
											2021-07-18 14:52:09 +02:00
										 |  |  |         const newElements = allChanges.newObjects ?? [] | 
					
						
							|  |  |  |         const deletedElements = allChanges.deletedObjects ?? [] | 
					
						
							| 
									
										
										
										
											2021-07-15 20:47:28 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         let changes = `<osmChange version='0.6' generator='Mapcomplete ${Constants.vNumber}'>` | 
					
						
							| 
									
										
										
										
											2021-07-15 20:47:28 +02:00
										 |  |  |         if (newElements.length > 0) { | 
					
						
							|  |  |  |             changes += | 
					
						
							|  |  |  |                 "\n<create>\n" + | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                 newElements.map((e) => e.ChangesetXML(csId)).join("\n") + | 
					
						
							|  |  |  |                 "</create>" | 
					
						
							| 
									
										
										
										
											2020-06-24 00:35:19 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-07-15 20:47:28 +02:00
										 |  |  |         if (changedElements.length > 0) { | 
					
						
							|  |  |  |             changes += | 
					
						
							|  |  |  |                 "\n<modify>\n" + | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                 changedElements.map((e) => e.ChangesetXML(csId)).join("\n") + | 
					
						
							|  |  |  |                 "\n</modify>" | 
					
						
							| 
									
										
										
										
											2020-06-24 00:35:19 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2020-08-27 18:44:16 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-15 20:47:28 +02:00
										 |  |  |         if (deletedElements.length > 0) { | 
					
						
							|  |  |  |             changes += | 
					
						
							| 
									
										
										
										
											2021-10-04 03:12:42 +02:00
										 |  |  |                 "\n<delete>\n" + | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                 deletedElements.map((e) => e.ChangesetXML(csId)).join("\n") + | 
					
						
							| 
									
										
										
										
											2021-10-04 03:12:42 +02:00
										 |  |  |                 "\n</delete>" | 
					
						
							| 
									
										
										
										
											2020-08-06 19:42:10 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2020-08-27 11:11:20 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         changes += "</osmChange>" | 
					
						
							|  |  |  |         return changes | 
					
						
							| 
									
										
										
										
											2020-06-24 00:35:19 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-15 20:47:28 +02:00
										 |  |  |     private static GetNeededIds(changes: ChangeDescription[]) { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         return Utils.Dedup(changes.filter((c) => c.id >= 0).map((c) => c.type + "/" + c.id)) | 
					
						
							| 
									
										
										
										
											2021-07-15 20:47:28 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-07-10 13:47:53 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-09 00:05:51 +02:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Returns a new ID and updates the value for the next ID | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public getNewID() { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         return this._nextId-- | 
					
						
							| 
									
										
										
										
											2021-09-09 00:05:51 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Uploads all the pending changes in one go. | 
					
						
							|  |  |  |      * Triggered by the 'PendingChangeUploader'-actor in Actors | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2022-02-14 02:50:21 +01:00
										 |  |  |     public async flushChanges(flushreason: string = undefined): Promise<void> { | 
					
						
							| 
									
										
										
										
											2021-09-09 00:05:51 +02:00
										 |  |  |         if (this.pendingChanges.data.length === 0) { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             return | 
					
						
							| 
									
										
										
										
											2021-09-09 00:05:51 +02:00
										 |  |  |         } | 
					
						
							|  |  |  |         if (this.isUploading.data) { | 
					
						
							|  |  |  |             console.log("Is already uploading... Abort") | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             return | 
					
						
							| 
									
										
										
										
											2021-09-09 00:05:51 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-12-17 19:28:05 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-20 00:09:40 +02:00
										 |  |  |         console.log("Uploading changes due to: ", flushreason) | 
					
						
							| 
									
										
										
										
											2021-09-09 00:05:51 +02:00
										 |  |  |         this.isUploading.setData(true) | 
					
						
							| 
									
										
										
										
											2021-12-12 02:59:24 +01:00
										 |  |  |         try { | 
					
						
							| 
									
										
										
										
											2022-02-14 02:50:21 +01:00
										 |  |  |             const csNumber = await this.flushChangesAsync() | 
					
						
							| 
									
										
										
										
											2021-12-12 02:59:24 +01:00
										 |  |  |             this.isUploading.setData(false) | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             console.log("Changes flushed. Your changeset is " + csNumber) | 
					
						
							| 
									
										
										
										
											2021-12-12 02:59:24 +01:00
										 |  |  |         } catch (e) { | 
					
						
							|  |  |  |             this.isUploading.setData(false) | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             console.error("Flushing changes failed due to", e) | 
					
						
							| 
									
										
										
										
											2021-12-12 02:59:24 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-09-26 23:35:26 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-26 21:40:38 +01:00
										 |  |  |     public async applyAction(action: OsmChangeAction): Promise<void> { | 
					
						
							|  |  |  |         const changeDescriptions = await action.Perform(this) | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         changeDescriptions[0].meta.distanceToObject = this.calculateDistanceToChanges( | 
					
						
							|  |  |  |             action, | 
					
						
							|  |  |  |             changeDescriptions | 
					
						
							|  |  |  |         ) | 
					
						
							| 
									
										
										
										
											2022-01-26 21:40:38 +01:00
										 |  |  |         this.applyChanges(changeDescriptions) | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     public applyChanges(changes: ChangeDescription[]) { | 
					
						
							|  |  |  |         console.log("Received changes:", changes) | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         this.pendingChanges.data.push(...changes) | 
					
						
							|  |  |  |         this.pendingChanges.ping() | 
					
						
							| 
									
										
										
										
											2022-01-26 21:40:38 +01:00
										 |  |  |         this.allChanges.data.push(...changes) | 
					
						
							|  |  |  |         this.allChanges.ping() | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-11-09 01:49:07 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |     private calculateDistanceToChanges( | 
					
						
							|  |  |  |         change: OsmChangeAction, | 
					
						
							|  |  |  |         changeDescriptions: ChangeDescription[] | 
					
						
							|  |  |  |     ) { | 
					
						
							| 
									
										
										
										
											2022-02-16 01:46:55 +01:00
										 |  |  |         const locations = this.historicalUserLocations?.features?.data | 
					
						
							| 
									
										
										
										
											2022-01-25 00:48:05 +01:00
										 |  |  |         if (locations === undefined) { | 
					
						
							|  |  |  |             // No state loaded or no locations -> we can't calculate...
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             return | 
					
						
							| 
									
										
										
										
											2021-11-09 01:49:07 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-12-05 05:19:59 +01:00
										 |  |  |         if (!change.trackStatistics) { | 
					
						
							| 
									
										
										
										
											2021-11-09 01:49:07 +01:00
										 |  |  |             // Probably irrelevant, such as a new helper node
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             return | 
					
						
							| 
									
										
										
										
											2021-11-09 01:49:07 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2022-01-26 21:40:38 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-09 01:49:07 +01:00
										 |  |  |         const now = new Date() | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         const recentLocationPoints = locations | 
					
						
							|  |  |  |             .map((ff) => ff.feature) | 
					
						
							|  |  |  |             .filter((feat) => feat.geometry.type === "Point") | 
					
						
							|  |  |  |             .filter((feat) => { | 
					
						
							|  |  |  |                 const visitTime = new Date( | 
					
						
							|  |  |  |                     (<GeoLocationPointProperties>(<any>feat.properties)).date | 
					
						
							|  |  |  |                 ) | 
					
						
							| 
									
										
										
										
											2021-11-09 01:49:07 +01:00
										 |  |  |                 // In seconds
 | 
					
						
							|  |  |  |                 const diff = (now.getTime() - visitTime.getTime()) / 1000 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                 return diff < Constants.nearbyVisitTime | 
					
						
							| 
									
										
										
										
											2021-11-09 01:49:07 +01:00
										 |  |  |             }) | 
					
						
							| 
									
										
										
										
											2021-12-05 05:19:59 +01:00
										 |  |  |         if (recentLocationPoints.length === 0) { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             // Probably no GPS enabled/no fix
 | 
					
						
							|  |  |  |             return | 
					
						
							| 
									
										
										
										
											2021-11-09 01:49:07 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-12-05 05:19:59 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-09 01:49:07 +01:00
										 |  |  |         // The applicable points, contain information in their properties about location, time and GPS accuracy
 | 
					
						
							|  |  |  |         // They are all GeoLocationPointProperties
 | 
					
						
							|  |  |  |         // We walk every change and determine the closest distance possible
 | 
					
						
							|  |  |  |         // Only if the change itself does _not_ contain any coordinates, we fall back and search the original feature in the state
 | 
					
						
							| 
									
										
										
										
											2021-12-05 05:19:59 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         const changedObjectCoordinates: [number, number][] = [] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-13 02:05:34 +01:00
										 |  |  |         const feature = this.state.allElements.ContainingFeatures.get(change.mainObjectId) | 
					
						
							| 
									
										
										
										
											2021-12-05 05:19:59 +01:00
										 |  |  |         if (feature !== undefined) { | 
					
						
							|  |  |  |             changedObjectCoordinates.push(GeoOperations.centerpointCoordinates(feature)) | 
					
						
							| 
									
										
										
										
											2021-11-09 01:49:07 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-11-03 00:44:53 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-09 01:49:07 +01:00
										 |  |  |         for (const changeDescription of changeDescriptions) { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             const chng: | 
					
						
							|  |  |  |                 | { lat: number; lon: number } | 
					
						
							|  |  |  |                 | { coordinates: [number, number][] } | 
					
						
							|  |  |  |                 | { members } = changeDescription.changes | 
					
						
							| 
									
										
										
										
											2021-12-05 05:19:59 +01:00
										 |  |  |             if (chng === undefined) { | 
					
						
							| 
									
										
										
										
											2021-11-09 01:49:07 +01:00
										 |  |  |                 continue | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2021-12-05 05:19:59 +01:00
										 |  |  |             if (chng["lat"] !== undefined) { | 
					
						
							|  |  |  |                 changedObjectCoordinates.push([chng["lat"], chng["lon"]]) | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             if (chng["coordinates"] !== undefined) { | 
					
						
							|  |  |  |                 changedObjectCoordinates.push(...chng["coordinates"]) | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2021-11-03 00:44:53 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-11-09 02:03:32 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         return Math.min( | 
					
						
							|  |  |  |             ...changedObjectCoordinates.map((coor) => | 
					
						
							|  |  |  |                 Math.min( | 
					
						
							|  |  |  |                     ...recentLocationPoints.map((gpsPoint) => { | 
					
						
							|  |  |  |                         const otherCoor = GeoOperations.centerpointCoordinates(gpsPoint) | 
					
						
							|  |  |  |                         return GeoOperations.distanceBetween(coor, otherCoor) | 
					
						
							|  |  |  |                     }) | 
					
						
							|  |  |  |                 ) | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  |         ) | 
					
						
							| 
									
										
										
										
											2021-11-09 01:49:07 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-12-05 05:19:59 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-04 03:12:42 +02:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * UPload the selected changes to OSM. | 
					
						
							|  |  |  |      * Returns 'true' if successfull and if they can be removed | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |     private async flushSelectChanges( | 
					
						
							|  |  |  |         pending: ChangeDescription[], | 
					
						
							|  |  |  |         openChangeset: UIEventSource<number> | 
					
						
							|  |  |  |     ): Promise<boolean> { | 
					
						
							|  |  |  |         const self = this | 
					
						
							| 
									
										
										
										
											2021-10-04 03:12:42 +02:00
										 |  |  |         const neededIds = Changes.GetNeededIds(pending) | 
					
						
							| 
									
										
										
										
											2021-12-05 05:19:59 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         const osmObjects = Utils.NoNull( | 
					
						
							|  |  |  |             await Promise.all( | 
					
						
							|  |  |  |                 neededIds.map(async (id) => | 
					
						
							|  |  |  |                     OsmObject.DownloadObjectAsync(id).catch((e) => { | 
					
						
							|  |  |  |                         console.error( | 
					
						
							|  |  |  |                             "Could not download OSM-object", | 
					
						
							|  |  |  |                             id, | 
					
						
							|  |  |  |                             " dropping it from the changes (" + e + ")" | 
					
						
							|  |  |  |                         ) | 
					
						
							|  |  |  |                         pending = pending.filter((ch) => ch.type + "/" + ch.id !== id) | 
					
						
							|  |  |  |                         return undefined | 
					
						
							|  |  |  |                     }) | 
					
						
							|  |  |  |                 ) | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  |         ) | 
					
						
							| 
									
										
										
										
											2021-10-29 16:38:33 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if (this._leftRightSensitive) { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             osmObjects.forEach((obj) => SimpleMetaTagger.removeBothTagging(obj.tags)) | 
					
						
							| 
									
										
										
										
											2021-10-22 14:01:40 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-10-29 16:38:33 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-04 03:12:42 +02:00
										 |  |  |         console.log("Got the fresh objects!", osmObjects, "pending: ", pending) | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         if (pending.length == 0) { | 
					
						
							| 
									
										
										
										
											2022-06-08 01:27:21 +02:00
										 |  |  |             console.log("No pending changes...") | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             return true | 
					
						
							| 
									
										
										
										
											2022-06-08 01:27:21 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-29 16:38:33 +02:00
										 |  |  |         const perType = Array.from( | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             Utils.Hist( | 
					
						
							|  |  |  |                 pending | 
					
						
							|  |  |  |                     .filter( | 
					
						
							|  |  |  |                         (descr) => | 
					
						
							|  |  |  |                             descr.meta.changeType !== undefined && descr.meta.changeType !== null | 
					
						
							|  |  |  |                     ) | 
					
						
							|  |  |  |                     .map((descr) => descr.meta.changeType) | 
					
						
							|  |  |  |             ), | 
					
						
							|  |  |  |             ([key, count]) => ({ | 
					
						
							|  |  |  |                 key: key, | 
					
						
							|  |  |  |                 value: count, | 
					
						
							|  |  |  |                 aggregate: true, | 
					
						
							|  |  |  |             }) | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |         const motivations = pending | 
					
						
							|  |  |  |             .filter((descr) => descr.meta.specialMotivation !== undefined) | 
					
						
							|  |  |  |             .map((descr) => ({ | 
					
						
							| 
									
										
										
										
											2021-10-29 16:38:33 +02:00
										 |  |  |                 key: descr.meta.changeType + ":" + descr.type + "/" + descr.id, | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                 value: descr.meta.specialMotivation, | 
					
						
							| 
									
										
										
										
											2021-10-04 03:12:42 +02:00
										 |  |  |             })) | 
					
						
							| 
									
										
										
										
											2021-12-05 05:19:59 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         const distances = Utils.NoNull(pending.map((descr) => descr.meta.distanceToObject)) | 
					
						
							| 
									
										
										
										
											2021-11-09 01:49:07 +01:00
										 |  |  |         distances.sort((a, b) => a - b) | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         const perBinCount = Constants.distanceToChangeObjectBins.map((_) => 0) | 
					
						
							| 
									
										
										
										
											2021-11-09 01:49:07 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         let j = 0 | 
					
						
							| 
									
										
										
										
											2021-11-09 01:49:07 +01:00
										 |  |  |         const maxDistances = Constants.distanceToChangeObjectBins | 
					
						
							| 
									
										
										
										
											2021-12-05 05:19:59 +01:00
										 |  |  |         for (let i = 0; i < maxDistances.length; i++) { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             const maxDistance = maxDistances[i] | 
					
						
							| 
									
										
										
										
											2021-11-09 01:49:07 +01:00
										 |  |  |             // distances is sorted in ascending order, so as soon as one is to big, all the resting elements will be bigger too
 | 
					
						
							| 
									
										
										
										
											2021-12-05 05:19:59 +01:00
										 |  |  |             while (j < distances.length && distances[j] < maxDistance) { | 
					
						
							|  |  |  |                 perBinCount[i]++ | 
					
						
							| 
									
										
										
										
											2021-11-09 01:49:07 +01:00
										 |  |  |                 j++ | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         const perBinMessage = Utils.NoNull( | 
					
						
							|  |  |  |             perBinCount.map((count, i) => { | 
					
						
							|  |  |  |                 if (count === 0) { | 
					
						
							|  |  |  |                     return undefined | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 const maxD = maxDistances[i] | 
					
						
							|  |  |  |                 let key = `change_within_${maxD}m` | 
					
						
							|  |  |  |                 if (maxD === Number.MAX_VALUE) { | 
					
						
							|  |  |  |                     key = `change_over_${maxDistances[i - 1]}m` | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 return { | 
					
						
							|  |  |  |                     key, | 
					
						
							|  |  |  |                     value: count, | 
					
						
							|  |  |  |                     aggregate: true, | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             }) | 
					
						
							|  |  |  |         ) | 
					
						
							| 
									
										
										
										
											2021-12-05 05:19:59 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-09 01:49:07 +01:00
										 |  |  |         // This method is only called with changedescriptions for this theme
 | 
					
						
							|  |  |  |         const theme = pending[0].meta.theme | 
					
						
							| 
									
										
										
										
											2021-12-13 02:05:34 +01:00
										 |  |  |         let comment = "Adding data with #MapComplete for theme #" + theme | 
					
						
							| 
									
										
										
										
											2022-01-26 21:40:38 +01:00
										 |  |  |         if (this.extraComment.data !== undefined) { | 
					
						
							|  |  |  |             comment += "\n\n" + this.extraComment.data | 
					
						
							| 
									
										
										
										
											2021-12-13 02:05:34 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2022-01-26 21:40:38 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         const metatags: ChangesetTag[] = [ | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 key: "comment", | 
					
						
							|  |  |  |                 value: comment, | 
					
						
							|  |  |  |             }, | 
					
						
							| 
									
										
										
										
											2021-10-04 03:12:42 +02:00
										 |  |  |             { | 
					
						
							| 
									
										
										
										
											2021-10-29 16:38:33 +02:00
										 |  |  |                 key: "theme", | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                 value: theme, | 
					
						
							| 
									
										
										
										
											2021-10-04 03:12:42 +02:00
										 |  |  |             }, | 
					
						
							|  |  |  |             ...perType, | 
					
						
							| 
									
										
										
										
											2021-11-09 01:49:07 +01:00
										 |  |  |             ...motivations, | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             ...perBinMessage, | 
					
						
							| 
									
										
										
										
											2021-10-04 03:12:42 +02:00
										 |  |  |         ] | 
					
						
							| 
									
										
										
										
											2021-10-29 16:38:33 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-15 23:44:16 +01:00
										 |  |  |         await this._changesetHandler.UploadChangeset( | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             (csId, remappings) => { | 
					
						
							|  |  |  |                 if (remappings.size > 0) { | 
					
						
							| 
									
										
										
										
											2022-04-08 04:18:53 +02:00
										 |  |  |                     console.log("Rewriting pending changes from", pending, "with", remappings) | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                     pending = pending.map((ch) => ChangeDescriptionTools.rewriteIds(ch, remappings)) | 
					
						
							| 
									
										
										
										
											2022-04-08 04:18:53 +02:00
										 |  |  |                     console.log("Result is", pending) | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 const changes: { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                     newObjects: OsmObject[] | 
					
						
							| 
									
										
										
										
											2022-04-08 04:18:53 +02:00
										 |  |  |                     modifiedObjects: OsmObject[] | 
					
						
							|  |  |  |                     deletedObjects: OsmObject[] | 
					
						
							|  |  |  |                 } = self.CreateChangesetObjects(pending, osmObjects) | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                 return Changes.createChangesetFor("" + csId, changes) | 
					
						
							| 
									
										
										
										
											2022-04-08 04:18:53 +02:00
										 |  |  |             }, | 
					
						
							| 
									
										
										
										
											2021-12-17 19:28:05 +01:00
										 |  |  |             metatags, | 
					
						
							|  |  |  |             openChangeset | 
					
						
							| 
									
										
										
										
											2021-10-04 03:12:42 +02:00
										 |  |  |         ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         console.log("Upload successfull!") | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         return true | 
					
						
							| 
									
										
										
										
											2021-10-04 03:12:42 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-14 02:50:21 +01:00
										 |  |  |     private async flushChangesAsync(): Promise<void> { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         const self = this | 
					
						
							| 
									
										
										
										
											2021-09-26 23:35:26 +02:00
										 |  |  |         try { | 
					
						
							| 
									
										
										
										
											2021-10-03 21:53:31 +02:00
										 |  |  |             // At last, we build the changeset and upload
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             const pending = self.pendingChanges.data | 
					
						
							| 
									
										
										
										
											2021-10-29 16:38:33 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-04 03:12:42 +02:00
										 |  |  |             const pendingPerTheme = new Map<string, ChangeDescription[]>() | 
					
						
							|  |  |  |             for (const changeDescription of pending) { | 
					
						
							|  |  |  |                 const theme = changeDescription.meta.theme | 
					
						
							| 
									
										
										
										
											2021-10-29 16:38:33 +02:00
										 |  |  |                 if (!pendingPerTheme.has(theme)) { | 
					
						
							| 
									
										
										
										
											2021-10-04 03:12:42 +02:00
										 |  |  |                     pendingPerTheme.set(theme, []) | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 pendingPerTheme.get(theme).push(changeDescription) | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2021-10-29 16:38:33 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             const successes = await Promise.all( | 
					
						
							|  |  |  |                 Array.from(pendingPerTheme, async ([theme, pendingChanges]) => { | 
					
						
							| 
									
										
										
										
											2021-10-29 16:38:33 +02:00
										 |  |  |                     try { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                         const openChangeset = this.state.osmConnection | 
					
						
							|  |  |  |                             .GetPreference("current-open-changeset-" + theme) | 
					
						
							|  |  |  |                             .sync( | 
					
						
							|  |  |  |                                 (str) => { | 
					
						
							|  |  |  |                                     const n = Number(str) | 
					
						
							|  |  |  |                                     if (isNaN(n)) { | 
					
						
							|  |  |  |                                         return undefined | 
					
						
							|  |  |  |                                     } | 
					
						
							|  |  |  |                                     return n | 
					
						
							|  |  |  |                                 }, | 
					
						
							|  |  |  |                                 [], | 
					
						
							|  |  |  |                                 (n) => "" + n | 
					
						
							|  |  |  |                             ) | 
					
						
							|  |  |  |                         console.log( | 
					
						
							|  |  |  |                             "Using current-open-changeset-" + | 
					
						
							|  |  |  |                                 theme + | 
					
						
							|  |  |  |                                 " from the preferences, got " + | 
					
						
							|  |  |  |                                 openChangeset.data | 
					
						
							|  |  |  |                         ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                         return await self.flushSelectChanges(pendingChanges, openChangeset) | 
					
						
							| 
									
										
										
										
											2021-10-29 16:38:33 +02:00
										 |  |  |                     } catch (e) { | 
					
						
							|  |  |  |                         console.error("Could not upload some changes:", e) | 
					
						
							| 
									
										
										
										
											2021-10-04 03:12:42 +02:00
										 |  |  |                         return false | 
					
						
							|  |  |  |                     } | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                 }) | 
					
						
							|  |  |  |             ) | 
					
						
							| 
									
										
										
										
											2021-10-29 16:38:33 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             if (!successes.some((s) => s == false)) { | 
					
						
							| 
									
										
										
										
											2021-10-04 03:12:42 +02:00
										 |  |  |                 // All changes successfull, we clear the data!
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                 this.pendingChanges.setData([]) | 
					
						
							| 
									
										
										
										
											2021-09-09 00:05:51 +02:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2021-09-26 23:35:26 +02:00
										 |  |  |         } catch (e) { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             console.error( | 
					
						
							|  |  |  |                 "Could not handle changes - probably an old, pending changeset in localstorage with an invalid format; erasing those", | 
					
						
							|  |  |  |                 e | 
					
						
							|  |  |  |             ) | 
					
						
							| 
									
										
										
										
											2021-09-26 23:35:26 +02:00
										 |  |  |             self.pendingChanges.setData([]) | 
					
						
							| 
									
										
										
										
											2021-10-29 16:38:33 +02:00
										 |  |  |         } finally { | 
					
						
							| 
									
										
										
										
											2021-09-26 23:35:26 +02:00
										 |  |  |             self.isUploading.setData(false) | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-09-09 00:05:51 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |     public CreateChangesetObjects( | 
					
						
							|  |  |  |         changes: ChangeDescription[], | 
					
						
							|  |  |  |         downloadedOsmObjects: OsmObject[] | 
					
						
							|  |  |  |     ): { | 
					
						
							|  |  |  |         newObjects: OsmObject[] | 
					
						
							| 
									
										
										
										
											2021-07-15 20:47:28 +02:00
										 |  |  |         modifiedObjects: OsmObject[] | 
					
						
							|  |  |  |         deletedObjects: OsmObject[] | 
					
						
							|  |  |  |     } { | 
					
						
							|  |  |  |         const objects: Map<string, OsmObject> = new Map<string, OsmObject>() | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         const states: Map<string, "unchanged" | "created" | "modified" | "deleted"> = new Map() | 
					
						
							| 
									
										
										
										
											2021-07-15 20:47:28 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         for (const o of downloadedOsmObjects) { | 
					
						
							|  |  |  |             objects.set(o.type + "/" + o.id, o) | 
					
						
							|  |  |  |             states.set(o.type + "/" + o.id, "unchanged") | 
					
						
							| 
									
										
										
										
											2021-01-03 03:09:52 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-07-10 13:47:53 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-18 14:52:09 +02:00
										 |  |  |         for (const o of this.previouslyCreated) { | 
					
						
							| 
									
										
										
										
											2021-09-09 00:05:51 +02:00
										 |  |  |             objects.set(o.type + "/" + o.id, o) | 
					
						
							| 
									
										
										
										
											2021-07-18 14:52:09 +02:00
										 |  |  |             states.set(o.type + "/" + o.id, "unchanged") | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-03 03:09:52 +01:00
										 |  |  |         for (const change of changes) { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             let changed = false | 
					
						
							| 
									
										
										
										
											2021-07-15 20:47:28 +02:00
										 |  |  |             const id = change.type + "/" + change.id | 
					
						
							|  |  |  |             if (!objects.has(id)) { | 
					
						
							| 
									
										
										
										
											2021-12-13 20:51:44 +01:00
										 |  |  |                 // The object hasn't been seen before, so it doesn't exist yet and is newly created by its very definition
 | 
					
						
							| 
									
										
										
										
											2021-09-09 00:05:51 +02:00
										 |  |  |                 if (change.id >= 0) { | 
					
						
							| 
									
										
										
										
											2021-12-13 20:51:44 +01:00
										 |  |  |                     // Might be a failed fetch for simply this object
 | 
					
						
							| 
									
										
										
										
											2021-09-09 00:05:51 +02:00
										 |  |  |                     throw "Did not get an object that should be known: " + id | 
					
						
							| 
									
										
										
										
											2021-07-18 14:52:09 +02:00
										 |  |  |                 } | 
					
						
							| 
									
										
										
										
											2022-01-26 21:40:38 +01:00
										 |  |  |                 if (change.changes === undefined) { | 
					
						
							| 
									
										
										
										
											2021-12-13 20:51:44 +01:00
										 |  |  |                     // This object is a change to a newly created object. However, we have not seen the creation changedescription yet!
 | 
					
						
							|  |  |  |                     throw "Not a creation of the object" | 
					
						
							|  |  |  |                 } | 
					
						
							| 
									
										
										
										
											2021-07-15 20:47:28 +02:00
										 |  |  |                 // This is a new object that should be created
 | 
					
						
							|  |  |  |                 states.set(id, "created") | 
					
						
							| 
									
										
										
										
											2021-07-18 14:52:09 +02:00
										 |  |  |                 console.log("Creating object for changeDescription", change) | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                 let osmObj: OsmObject = undefined | 
					
						
							| 
									
										
										
										
											2021-07-15 20:47:28 +02:00
										 |  |  |                 switch (change.type) { | 
					
						
							|  |  |  |                     case "node": | 
					
						
							|  |  |  |                         const n = new OsmNode(change.id) | 
					
						
							|  |  |  |                         n.lat = change.changes["lat"] | 
					
						
							|  |  |  |                         n.lon = change.changes["lon"] | 
					
						
							|  |  |  |                         osmObj = n | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                         break | 
					
						
							| 
									
										
										
										
											2021-07-15 20:47:28 +02:00
										 |  |  |                     case "way": | 
					
						
							|  |  |  |                         const w = new OsmWay(change.id) | 
					
						
							|  |  |  |                         w.nodes = change.changes["nodes"] | 
					
						
							|  |  |  |                         osmObj = w | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                         break | 
					
						
							| 
									
										
										
										
											2021-07-15 20:47:28 +02:00
										 |  |  |                     case "relation": | 
					
						
							|  |  |  |                         const r = new OsmRelation(change.id) | 
					
						
							|  |  |  |                         r.members = change.changes["members"] | 
					
						
							|  |  |  |                         osmObj = r | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                         break | 
					
						
							| 
									
										
										
										
											2021-07-15 20:47:28 +02:00
										 |  |  |                 } | 
					
						
							|  |  |  |                 if (osmObj === undefined) { | 
					
						
							|  |  |  |                     throw "Hmm? This is a bug" | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 objects.set(id, osmObj) | 
					
						
							| 
									
										
										
										
											2021-07-18 14:52:09 +02:00
										 |  |  |                 this.previouslyCreated.push(osmObj) | 
					
						
							| 
									
										
										
										
											2021-01-03 03:09:52 +01:00
										 |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-15 20:47:28 +02:00
										 |  |  |             const state = states.get(id) | 
					
						
							|  |  |  |             if (change.doDelete) { | 
					
						
							|  |  |  |                 if (state === "created") { | 
					
						
							|  |  |  |                     states.set(id, "unchanged") | 
					
						
							|  |  |  |                 } else { | 
					
						
							|  |  |  |                     states.set(id, "deleted") | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2021-07-14 15:28:02 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-15 20:47:28 +02:00
										 |  |  |             const obj = objects.get(id) | 
					
						
							|  |  |  |             // Apply tag changes
 | 
					
						
							|  |  |  |             for (const kv of change.tags ?? []) { | 
					
						
							|  |  |  |                 const k = kv.k | 
					
						
							|  |  |  |                 let v = kv.v | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 if (v === "") { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                     v = undefined | 
					
						
							| 
									
										
										
										
											2021-07-15 20:47:28 +02:00
										 |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-20 00:09:40 +02:00
										 |  |  |                 const oldV = obj.tags[k] | 
					
						
							| 
									
										
										
										
											2021-07-15 20:47:28 +02:00
										 |  |  |                 if (oldV === v) { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                     continue | 
					
						
							| 
									
										
										
										
											2021-07-15 20:47:28 +02:00
										 |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                 obj.tags[k] = v | 
					
						
							|  |  |  |                 changed = true | 
					
						
							| 
									
										
										
										
											2021-07-14 15:28:02 +02:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2021-07-10 13:47:53 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-15 20:47:28 +02:00
										 |  |  |             if (change.changes !== undefined) { | 
					
						
							|  |  |  |                 switch (change.type) { | 
					
						
							|  |  |  |                     case "node": | 
					
						
							|  |  |  |                         // @ts-ignore
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                         const nlat = change.changes.lat | 
					
						
							| 
									
										
										
										
											2021-07-15 20:47:28 +02:00
										 |  |  |                         // @ts-ignore
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                         const nlon = change.changes.lon | 
					
						
							| 
									
										
										
										
											2021-07-15 20:47:28 +02:00
										 |  |  |                         const n = <OsmNode>obj | 
					
						
							|  |  |  |                         if (n.lat !== nlat || n.lon !== nlon) { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                             n.lat = nlat | 
					
						
							|  |  |  |                             n.lon = nlon | 
					
						
							|  |  |  |                             changed = true | 
					
						
							| 
									
										
										
										
											2021-07-15 20:47:28 +02:00
										 |  |  |                         } | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                         break | 
					
						
							| 
									
										
										
										
											2021-07-15 20:47:28 +02:00
										 |  |  |                     case "way": | 
					
						
							|  |  |  |                         const nnodes = change.changes["nodes"] | 
					
						
							|  |  |  |                         const w = <OsmWay>obj | 
					
						
							|  |  |  |                         if (!Utils.Identical(nnodes, w.nodes)) { | 
					
						
							|  |  |  |                             w.nodes = nnodes | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                             changed = true | 
					
						
							| 
									
										
										
										
											2021-07-15 20:47:28 +02:00
										 |  |  |                         } | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                         break | 
					
						
							| 
									
										
										
										
											2021-07-15 20:47:28 +02:00
										 |  |  |                     case "relation": | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                         const nmembers: { | 
					
						
							|  |  |  |                             type: "node" | "way" | "relation" | 
					
						
							|  |  |  |                             ref: number | 
					
						
							|  |  |  |                             role: string | 
					
						
							|  |  |  |                         }[] = change.changes["members"] | 
					
						
							| 
									
										
										
										
											2021-07-15 20:47:28 +02:00
										 |  |  |                         const r = <OsmRelation>obj | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                         if ( | 
					
						
							|  |  |  |                             !Utils.Identical(nmembers, r.members, (a, b) => { | 
					
						
							|  |  |  |                                 return a.role === b.role && a.type === b.type && a.ref === b.ref | 
					
						
							|  |  |  |                             }) | 
					
						
							|  |  |  |                         ) { | 
					
						
							|  |  |  |                             r.members = nmembers | 
					
						
							|  |  |  |                             changed = true | 
					
						
							| 
									
										
										
										
											2021-07-15 20:47:28 +02:00
										 |  |  |                         } | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                         break | 
					
						
							| 
									
										
										
										
											2021-07-15 20:47:28 +02:00
										 |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2021-01-04 22:14:56 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-23 03:36:03 +01:00
										 |  |  |             if (changed && states.get(id) === "unchanged") { | 
					
						
							| 
									
										
										
										
											2021-07-15 20:47:28 +02:00
										 |  |  |                 states.set(id, "modified") | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2021-07-10 13:47:53 +02:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-15 20:47:28 +02:00
										 |  |  |         const result = { | 
					
						
							|  |  |  |             newObjects: [], | 
					
						
							|  |  |  |             modifiedObjects: [], | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             deletedObjects: [], | 
					
						
							| 
									
										
										
										
											2021-07-15 20:47:28 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-09-09 00:05:51 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-15 20:47:28 +02:00
										 |  |  |         objects.forEach((v, id) => { | 
					
						
							|  |  |  |             const state = states.get(id) | 
					
						
							|  |  |  |             if (state === "created") { | 
					
						
							|  |  |  |                 result.newObjects.push(v) | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             if (state === "modified") { | 
					
						
							|  |  |  |                 result.modifiedObjects.push(v) | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             if (state === "deleted") { | 
					
						
							|  |  |  |                 result.deletedObjects.push(v) | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2021-07-10 15:52:52 +02:00
										 |  |  |         }) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         console.debug( | 
					
						
							|  |  |  |             "Calculated the pending changes: ", | 
					
						
							|  |  |  |             result.newObjects.length, | 
					
						
							|  |  |  |             "new; ", | 
					
						
							|  |  |  |             result.modifiedObjects.length, | 
					
						
							|  |  |  |             "modified;", | 
					
						
							|  |  |  |             result.deletedObjects, | 
					
						
							|  |  |  |             "deleted" | 
					
						
							|  |  |  |         ) | 
					
						
							| 
									
										
										
										
											2021-07-15 20:47:28 +02:00
										 |  |  |         return result | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     public setHistoricalUserLocations(locations: FeatureSource) { | 
					
						
							| 
									
										
										
										
											2022-02-16 01:46:55 +01:00
										 |  |  |         this.historicalUserLocations = locations | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  | } |