If an OSM-object does not exist anyore, ignore changes to this object. Fix #577
This commit is contained in:
parent
fc70909005
commit
76c84b3972
1 changed files with 41 additions and 35 deletions
|
@ -32,8 +32,8 @@ export class Changes {
|
||||||
|
|
||||||
private readonly previouslyCreated: OsmObject[] = []
|
private readonly previouslyCreated: OsmObject[] = []
|
||||||
private readonly _leftRightSensitive: boolean;
|
private readonly _leftRightSensitive: boolean;
|
||||||
|
|
||||||
private _state : { allElements: ElementStorage; historicalUserLocations: FeatureSource }
|
private _state: { allElements: ElementStorage; historicalUserLocations: FeatureSource }
|
||||||
|
|
||||||
constructor(leftRightSensitive: boolean = false) {
|
constructor(leftRightSensitive: boolean = false) {
|
||||||
this._leftRightSensitive = leftRightSensitive;
|
this._leftRightSensitive = leftRightSensitive;
|
||||||
|
@ -120,13 +120,13 @@ export class Changes {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private calculateDistanceToChanges(change: OsmChangeAction, changeDescriptions: ChangeDescription[]){
|
private calculateDistanceToChanges(change: OsmChangeAction, changeDescriptions: ChangeDescription[]) {
|
||||||
|
|
||||||
if (this._state === undefined) {
|
if (this._state === undefined) {
|
||||||
// No state loaded -> we can't calculate...
|
// No state loaded -> we can't calculate...
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(!change.trackStatistics){
|
if (!change.trackStatistics) {
|
||||||
// Probably irrelevant, such as a new helper node
|
// Probably irrelevant, such as a new helper node
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -139,34 +139,34 @@ export class Changes {
|
||||||
const diff = (now.getTime() - visitTime.getTime()) / 1000
|
const diff = (now.getTime() - visitTime.getTime()) / 1000
|
||||||
return diff < Constants.nearbyVisitTime;
|
return diff < Constants.nearbyVisitTime;
|
||||||
})
|
})
|
||||||
if(recentLocationPoints.length === 0){
|
if (recentLocationPoints.length === 0) {
|
||||||
// Probably no GPS enabled/no fix
|
// Probably no GPS enabled/no fix
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The applicable points, contain information in their properties about location, time and GPS accuracy
|
// The applicable points, contain information in their properties about location, time and GPS accuracy
|
||||||
// They are all GeoLocationPointProperties
|
// They are all GeoLocationPointProperties
|
||||||
// We walk every change and determine the closest distance possible
|
// 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
|
// Only if the change itself does _not_ contain any coordinates, we fall back and search the original feature in the state
|
||||||
|
|
||||||
const changedObjectCoordinates : [number, number][] = []
|
const changedObjectCoordinates: [number, number][] = []
|
||||||
|
|
||||||
const feature = this._state.allElements.ContainingFeatures.get(change.mainObjectId)
|
const feature = this._state.allElements.ContainingFeatures.get(change.mainObjectId)
|
||||||
if(feature !== undefined){
|
if (feature !== undefined) {
|
||||||
changedObjectCoordinates.push(GeoOperations.centerpointCoordinates(feature))
|
changedObjectCoordinates.push(GeoOperations.centerpointCoordinates(feature))
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const changeDescription of changeDescriptions) {
|
for (const changeDescription of changeDescriptions) {
|
||||||
const chng : {lat: number, lon: number} | {coordinates : [number,number][]} | {members} = changeDescription.changes
|
const chng: { lat: number, lon: number } | { coordinates: [number, number][] } | { members } = changeDescription.changes
|
||||||
if(chng === undefined){
|
if (chng === undefined) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if(chng["lat"] !== undefined){
|
if (chng["lat"] !== undefined) {
|
||||||
changedObjectCoordinates.push([chng["lat"],chng["lon"]])
|
changedObjectCoordinates.push([chng["lat"], chng["lon"]])
|
||||||
}
|
}
|
||||||
if(chng["coordinates"] !== undefined){
|
if (chng["coordinates"] !== undefined) {
|
||||||
changedObjectCoordinates.push(...chng["coordinates"])
|
changedObjectCoordinates.push(...chng["coordinates"])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Math.min(...changedObjectCoordinates.map(coor =>
|
return Math.min(...changedObjectCoordinates.map(coor =>
|
||||||
|
@ -176,7 +176,7 @@ export class Changes {
|
||||||
}))
|
}))
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
public async applyAction(action: OsmChangeAction): Promise<void> {
|
public async applyAction(action: OsmChangeAction): Promise<void> {
|
||||||
const changeDescriptions = await action.Perform(this)
|
const changeDescriptions = await action.Perform(this)
|
||||||
changeDescriptions[0].meta.distanceToObject = this.calculateDistanceToChanges(action, changeDescriptions)
|
changeDescriptions[0].meta.distanceToObject = this.calculateDistanceToChanges(action, changeDescriptions)
|
||||||
|
@ -190,12 +190,12 @@ export class Changes {
|
||||||
this.allChanges.data.push(...changes)
|
this.allChanges.data.push(...changes)
|
||||||
this.allChanges.ping()
|
this.allChanges.ping()
|
||||||
}
|
}
|
||||||
|
|
||||||
public useLocationHistory(state: {
|
public useLocationHistory(state: {
|
||||||
allElements: ElementStorage,
|
allElements: ElementStorage,
|
||||||
historicalUserLocations: FeatureSource
|
historicalUserLocations: FeatureSource
|
||||||
}){
|
}) {
|
||||||
this._state= state
|
this._state = state
|
||||||
}
|
}
|
||||||
|
|
||||||
public registerIdRewrites(mappings: Map<string, string>): void {
|
public registerIdRewrites(mappings: Map<string, string>): void {
|
||||||
|
@ -212,7 +212,13 @@ export class Changes {
|
||||||
private async flushSelectChanges(pending: ChangeDescription[]): Promise<boolean> {
|
private async flushSelectChanges(pending: ChangeDescription[]): Promise<boolean> {
|
||||||
const self = this;
|
const self = this;
|
||||||
const neededIds = Changes.GetNeededIds(pending)
|
const neededIds = Changes.GetNeededIds(pending)
|
||||||
const osmObjects = await Promise.all(neededIds.map(id => OsmObject.DownloadObjectAsync(id)));
|
|
||||||
|
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")
|
||||||
|
pending = pending.filter(ch => ch.type + "/" + ch.id !== id)
|
||||||
|
return undefined;
|
||||||
|
}))));
|
||||||
|
|
||||||
if (this._leftRightSensitive) {
|
if (this._leftRightSensitive) {
|
||||||
osmObjects.forEach(obj => SimpleMetaTagger.removeBothTagging(obj.tags))
|
osmObjects.forEach(obj => SimpleMetaTagger.removeBothTagging(obj.tags))
|
||||||
|
@ -243,41 +249,41 @@ export class Changes {
|
||||||
key: descr.meta.changeType + ":" + descr.type + "/" + descr.id,
|
key: descr.meta.changeType + ":" + descr.type + "/" + descr.id,
|
||||||
value: descr.meta.specialMotivation
|
value: descr.meta.specialMotivation
|
||||||
}))
|
}))
|
||||||
|
|
||||||
const distances = Utils.NoNull(pending.map(descr => descr.meta.distanceToObject));
|
const distances = Utils.NoNull(pending.map(descr => descr.meta.distanceToObject));
|
||||||
distances.sort((a, b) => a - b)
|
distances.sort((a, b) => a - b)
|
||||||
const perBinCount = Constants.distanceToChangeObjectBins.map(_ => 0)
|
const perBinCount = Constants.distanceToChangeObjectBins.map(_ => 0)
|
||||||
|
|
||||||
let j = 0;
|
let j = 0;
|
||||||
const maxDistances = Constants.distanceToChangeObjectBins
|
const maxDistances = Constants.distanceToChangeObjectBins
|
||||||
for (let i = 0; i < maxDistances.length; i++){
|
for (let i = 0; i < maxDistances.length; i++) {
|
||||||
const maxDistance = maxDistances[i];
|
const maxDistance = maxDistances[i];
|
||||||
// distances is sorted in ascending order, so as soon as one is to big, all the resting elements will be bigger too
|
// distances is sorted in ascending order, so as soon as one is to big, all the resting elements will be bigger too
|
||||||
while(j < distances.length && distances[j] < maxDistance){
|
while (j < distances.length && distances[j] < maxDistance) {
|
||||||
perBinCount[i] ++
|
perBinCount[i]++
|
||||||
j++
|
j++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const perBinMessage = Utils.NoNull(perBinCount.map((count, i) => {
|
const perBinMessage = Utils.NoNull(perBinCount.map((count, i) => {
|
||||||
if(count === 0){
|
if (count === 0) {
|
||||||
return undefined
|
return undefined
|
||||||
}
|
}
|
||||||
const maxD =maxDistances[i]
|
const maxD = maxDistances[i]
|
||||||
let key = `change_within_${maxD}m`
|
let key = `change_within_${maxD}m`
|
||||||
if(maxD === Number.MAX_VALUE){
|
if (maxD === Number.MAX_VALUE) {
|
||||||
key = `change_over_${maxDistances[i - 1]}m`
|
key = `change_over_${maxDistances[i - 1]}m`
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
key ,
|
key,
|
||||||
value: count,
|
value: count,
|
||||||
aggregate:true
|
aggregate: true
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
|
|
||||||
// This method is only called with changedescriptions for this theme
|
// This method is only called with changedescriptions for this theme
|
||||||
const theme = pending[0].meta.theme
|
const theme = pending[0].meta.theme
|
||||||
const metatags : ChangesetTag[] = [{
|
const metatags: ChangesetTag[] = [{
|
||||||
key: "comment",
|
key: "comment",
|
||||||
value: "Adding data with #MapComplete for theme #" + theme
|
value: "Adding data with #MapComplete for theme #" + theme
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in a new issue