diff --git a/assets/layers/bench/bench.json b/assets/layers/bench/bench.json index e65f003f6..020c063f2 100644 --- a/assets/layers/bench/bench.json +++ b/assets/layers/bench/bench.json @@ -1045,6 +1045,49 @@ } ] }, + { + "id": "bench-view", + "render": { + "special": { + "type": "group", + "header": "bench-view-title", + "labels": "bench-view-content" + } + } + }, + { + "id": "bench-view-title", + "labels": [ + "hidden" + ], + "render": { + "en": "View from the bench", + "nl": "Zicht vanop de bank" + } + }, + { + "id": "bench-view-carousel", + "labels": [ + "hidden", + "bench-view-content" + ], + "render": { + "special": { + "type": "image_carousel", + "image_key": "image:view;panoramax:view;mapillary:view" + } + }, + "render": { + "special": { + "type": "image_upload", + "image_key": "panoramax:view", + "label": { + "en": "Add a picture of the view when sitting on the bench", + "nl": "Voeg een afbeelding van het zicht vanaf de bank toe" + } + } + } + }, { "id": "bench-artwork", "question": { diff --git a/assets/layers/maproulette/maproulette.json b/assets/layers/maproulette/maproulette.json index 886746c4b..8c4a1655d 100644 --- a/assets/layers/maproulette/maproulette.json +++ b/assets/layers/maproulette/maproulette.json @@ -278,6 +278,21 @@ "image": "./assets/svg/not_found.svg" } } + }, + { + "id": "mark_not_too_hard", + "labels": [ + "controls" + ], + "render": { + "special": { + "type": "maproulette_set_status", + "message": { + "en": "This challenge was marked as too hard. Try anyway?" + }, + "status": "0" + } + } } ], "filter": [ diff --git a/assets/themes/benches/benches.json b/assets/themes/benches/benches.json index 20ab941a3..0f5157498 100644 --- a/assets/themes/benches/benches.json +++ b/assets/themes/benches/benches.json @@ -98,8 +98,8 @@ "calculatedTags": [ "_id:=''+get(feat)('tags')['openbenches:id']", "image:=get(feat)('tags')['image']", - "_osm_poi_with_this_ref=closestn(feat)('bench',25, undefined, 50).filter(f => f.feat.properties['openbenches:id'] === feat.properties['_id']).map(f => f.feat.properties.id).join(';')", - "_nearby_osm_poi=closestn(feat)('bench', 5, undefined, 15)", + "_osm_poi_with_this_ref=closestn(feat)('bench',5, undefined, 500).filter(f => f.feat.properties['openbenches:id'] === feat.properties['_id']).map(f => f.feat.properties)", + "_nearby_osm_poi=closestn(feat)('bench', 5, undefined, 50)", "_nearby_osm_poi:count=get(feat)('_nearby_osm_poi')?.length", "_nearby_osm_poi:props=get(feat)('_nearby_osm_poi')?.map(f => ({_distance: Math.round(f.distance), _mr_id: feat.properties.id, ...f.feat.properties}))" ], @@ -115,6 +115,17 @@ "en": "OpenStreetMap knows about a bench which is {_closest_osm_poi_distance} meter away. " } }, + { + "id": "already_linked", + "condition": "_osm_poi_with_this_ref!=[]", + "render": { + "special": { + "type": "multi", + "key": "_osm_poi_with_this_ref", + "tagrendering": "The OSM-bench {id} is linked to this OpenBenches-datapoint" + } + } + }, { "id": "list_nearby_pois", "condition": { @@ -138,7 +149,17 @@ }, { "id": "import_point", - "condition": "mr_taskStatus=Created", + "condition": { + "or": [ + { + "or": [ + "mr_taskStatus=Created", + "mr_taskStatus=Open" + ] + }, + "mr_taskStatus=Open" + ] + }, "render": { "special": { "type": "import_button", @@ -153,8 +174,8 @@ } } }, - "maproulette.controls", + "{nearby_images()}", "all_tags" ] } diff --git a/scripts/importscripts/openbenches.ts b/scripts/importscripts/openbenches.ts index 2731f63da..197ca717f 100644 --- a/scripts/importscripts/openbenches.ts +++ b/scripts/importscripts/openbenches.ts @@ -1,11 +1,19 @@ import Script from "../Script" -import { promises as fs, writeFileSync } from "fs" -import { Feature, Point } from "geojson" +import { existsSync, promises as fs, readFileSync, writeFile, writeFileSync } from "fs" +import { Feature, FeatureCollection, Point } from "geojson" import { join } from "path" import sqlite3, { Database } from "sqlite3" import { open } from "sqlite" -import ScriptUtils from "../ScriptUtils" import { Lists } from "../../src/Utils/Lists" +import { Overpass } from "../../src/Logic/Osm/Overpass" +import { TagUtils } from "../../src/Logic/Tags/TagUtils" +import Constants from "../../src/Models/Constants" +import { BBox } from "../../src/Logic/BBox" +import LinkImageAction from "../../src/Logic/Osm/Actions/LinkImageAction" +import OsmChangeAction from "../../src/Logic/Osm/Actions/OsmChangeAction" +import ChangeTagAction from "../../src/Logic/Osm/Actions/ChangeTagAction" +import { Tag as OsmTag } from "../../src/Logic/Tags/Tag" +import { Changes } from "../../src/Logic/Osm/Changes" /** * Note: @@ -23,6 +31,7 @@ interface Bench { description: string, present: 0 | 1, published: 0 | 1, + /* time of creation (or possibly last edit?) */ added: string, userID: number } @@ -97,8 +106,6 @@ class Openbenches extends Script { filename: dbFile, driver: sqlite3.Database, }) - console.log(db) - console.dir(db) return db.db } @@ -114,11 +121,11 @@ class Openbenches extends Script { const mediaView = media.filter(m => m.media_type === "view") const properties = { - // added: benchWithUser.added, + lastModifiedTime: benchWithUser.added, "openbenches:id": id, inscription: benchWithUser.inscription.replaceAll("\\r\\n", "\n"), amenity: "bench", - // lastModifiedBy: benchWithUser.name, + lastModifiedBy: benchWithUser.name, } let mediaMerged = Lists.dedup(mediaBench.concat(mediaInscr).map(m => mediaUrl(m))) @@ -171,7 +178,7 @@ class Openbenches extends Script { return { type: "Feature", - properties: { tags: JSON.stringify(properties) }, + properties, geometry: { type: "Point", coordinates: [benchWithUser.longitude, benchWithUser.latitude], @@ -179,13 +186,93 @@ class Openbenches extends Script { } } + async getAlreadyImported(): Promise { + const alreadyImportedPath = "openbenches_linked_in_osm.geojson" + if (!existsSync(alreadyImportedPath)) { + const overpass = new Overpass(Constants.defaultOverpassUrls[0], TagUtils.Tag("openbenches:id~*")) + const dataAndDate = await overpass.queryGeoJson(BBox.global) + const data = dataAndDate[0] + writeFileSync(alreadyImportedPath, JSON.stringify(data), "utf-8") + return data + } + + return JSON.parse(readFileSync(alreadyImportedPath, "utf-8")) + } + + async conflate(osmData: FeatureCollection, openBenchesData: FeatureCollection) { + const dict: Map = new Map() + for (const bench of openBenchesData.features) { + const obid = bench.properties["openbenches:id"] + dict.set("" + obid, bench) + } + const changes: OsmChangeAction[] = [] + for (const bench of osmData.features) { + const obid = bench.properties["openbenches:id"] + const ob = dict.get(obid) + if (!ob) { + console.log("No match found for", obid, "https://osm.org/" + bench.properties.id) + continue + } + // console.log(`https://osm.org/${bench.properties.id} = https://openbenches.org/bench/${obid}`) + for (const key in ob.properties) { + if (key.startsWith("lastModified")) { + continue + } + if (key.startsWith("image")) { + const imgValue = ob.properties[key] + if (Object.values(bench.properties).some(v => v === imgValue || (v + ".jpg") === imgValue)) { + continue + } + let ikey = "image" + let i = -1 + while (bench.properties[ikey]) { + i++ + ikey = "image:" + i + } + const li = new ChangeTagAction(bench.properties.id, new OsmTag(ikey, imgValue), bench.properties, { + theme: "openbenches", + changeType: "link-image", + }) + changes.push(li) + bench.properties[ikey] = imgValue + console.log(` + ${ikey}=${imgValue}`) + } else if (!bench.properties[key]) { + const v = ob.properties[key] + if(v.length >= 255){ + console.log("Text too long:", v.replaceAll("\n"," ")) + continue + } + changes.push(new ChangeTagAction( + bench.properties.id, + new OsmTag(key, v), + bench.properties, + { + theme: "openbenches", + changeType: "answer", + }, + )) + console.log(` - ${key}=${ob.properties[key].replaceAll("\n", " ")}`) + } + } + } + const xml = await Changes.createChangesetXMLForJosm(changes) + writeFileSync("attributes_import.osc",xml, "utf-8") + } async main(args: string[]): Promise { const dbFile = "openbenches.sqlite" let createTest = false + const osmData = await this.getAlreadyImported() + const openBenches = JSON.parse(readFileSync("openbenches_export_josm_.geojson", "utf-8")) + await this.conflate(osmData, openBenches) // rmSync(dbFile) - // await this.buildDatabase("/home/pietervdvn/git/openbenches.org/database", dbFile) + /* + if(!existsSync(dbFile)){ + console.log("No database file found at "+dbFile+", recreating the database") + await this.buildDatabase("/home/pietervdvn/git/openbenches.org/database", dbFile) + } + this.db = await this.loadDb(dbFile) const tags = new Map() @@ -220,10 +307,19 @@ class Openbenches extends Script { } } - writeFileSync(`openbenches_export${createTest ? "_test" : ""}.geojson`, JSON.stringify({ + writeFileSync(`openbenches_export_josm_${createTest ? "_test" : ""}.geojson`, JSON.stringify({ type: "FeatureCollection", features, }, null, " "), "utf-8") - //console.log(r) + + const maproulette = features.map(f => { + f.properties = {tags: JSON.stringify(f.properties)} + }) + writeFileSync(`openbenches_export_maproulette_${createTest ? "_test" : ""}.geojson`, JSON.stringify({ + type: "FeatureCollection", features: maproulette, + }, null, " "), "utf-8") + + */ + } } diff --git a/src/Logic/Maproulette.ts b/src/Logic/Maproulette.ts index 20a490807..2eaea489b 100644 --- a/src/Logic/Maproulette.ts +++ b/src/Logic/Maproulette.ts @@ -8,7 +8,7 @@ export interface MaprouletteTask { instruction: string } export const maprouletteStatus = [ - "Open", + "Created", "Fixed", "False_positive", "Skipped", diff --git a/src/UI/MapRoulette/MaprouletteSetStatus.svelte b/src/UI/MapRoulette/MaprouletteSetStatus.svelte index 56619f6b7..1fa7b4dac 100644 --- a/src/UI/MapRoulette/MaprouletteSetStatus.svelte +++ b/src/UI/MapRoulette/MaprouletteSetStatus.svelte @@ -39,9 +39,11 @@ const maproulette_id = tags.data[maproulette_id_key] ?? tags.data.mr_taskId ?? tags.data.id try { const statusIndex = Maproulette.codeToIndex(statusToSet) ?? Number(statusToSet) - await Maproulette.singleton.closeTask(Number(maproulette_id), statusIndex, state, { - comment: feedback, - }) + if(statusIndex !== 0){ + await Maproulette.singleton.closeTask(Number(maproulette_id), statusIndex, state, { + comment: feedback, + }) + } tags.data["mr_taskStatus"] = maprouletteStatus[statusIndex] tags.data.status = statusToSet tags.ping() @@ -59,7 +61,7 @@ - {:else if $status === Maproulette.STATUS_OPEN} + {:else if $status === Maproulette.STATUS_OPEN || (statusToSet === ""+Maproulette.STATUS_OPEN && $status !== Maproulette.STATUS_OPEN)} {#if askFeedback !== "" && askFeedback !== undefined}

{askFeedback}