forked from MapComplete/MapComplete
Themes(benches): more work on integrating openbenches, polish a bit more
This commit is contained in:
parent
87823caabc
commit
11ab4965c6
6 changed files with 212 additions and 221 deletions
|
@ -12,7 +12,35 @@ A perfect example of this is to setup such a challenge to e.g. import new points
|
||||||
|
|
||||||
## Preparing the data
|
## Preparing the data
|
||||||
|
|
||||||
Convert your source data into a geojson. Use *`tags`* as field where all the OSM-properties should go. Make sure to include all tags there.
|
Convert your source data into a geojson. Use *`tags`* as field where all the OSM-properties should go. Make sure to include all tags that should be imported there and stringify it.
|
||||||
|
|
||||||
|
You have quite some freedom for the other tags. Make sure to add an *id* tag. Other tags (e.g. images, metadata) may go into the properties as well.
|
||||||
|
However, do _not_ add the generic tags for the layer to import into, to avoid that the maproulette challenges are loaded by the target layer.
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
{
|
||||||
|
"type": "FeatureCollection",
|
||||||
|
"features": [
|
||||||
|
{
|
||||||
|
"type": "Feature",
|
||||||
|
"geometry": {"type": "Point", "coordinates": [1.234, 5.678]},
|
||||||
|
"properties": {
|
||||||
|
"id": ..., # Especially important when you want to rebuild the data
|
||||||
|
"image": ...,
|
||||||
|
"lastModifiedBy": ..., # from the source data, just to help
|
||||||
|
"tags": "foo=bar;name=xyz;image=...", # To be imported
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
Then, create a challenge on https://maproulette.org/admin/projects (or, if you want to test first, on https://staging.maproulette.org/)
|
||||||
|
|
||||||
|
|
||||||
Hint: MapRoulette has a button 'rebuild task', where you can first 'remove all incomplete tasks'. This is perfect to start over in case of small data errors.
|
Hint: MapRoulette has a button 'rebuild task', where you can first 'remove all incomplete tasks'. This is perfect to start over in case of small data errors.
|
||||||
|
|
||||||
|
@ -127,35 +155,3 @@ The following example uses the calculated tags `_has_closeby_feature` and `_clos
|
||||||
The easiest way is to reuse a tagrendering from the [Maproulette-layer](./Docs/Layers/maproulette.md) (_not_ the `maproulette-challenge`-layer!), such as [`maproulette.mark_fixed`](./Docs/Layers/maproulette.md#markfixed),[`maproulette.mark_duplicate`](./Docs/Layers/maproulette.md#markduplicate),[`maproulette.mark_too_hard`](./Docs/Layers/maproulette.md#marktoohard).
|
The easiest way is to reuse a tagrendering from the [Maproulette-layer](./Docs/Layers/maproulette.md) (_not_ the `maproulette-challenge`-layer!), such as [`maproulette.mark_fixed`](./Docs/Layers/maproulette.md#markfixed),[`maproulette.mark_duplicate`](./Docs/Layers/maproulette.md#markduplicate),[`maproulette.mark_too_hard`](./Docs/Layers/maproulette.md#marktoohard).
|
||||||
|
|
||||||
In the background, these use the special visualisation [`maproulette_set_status`](./Docs/SpecialRenderings.md#maproulettesetstatus) - which allows to apply different status codes or different messages/icons.
|
In the background, these use the special visualisation [`maproulette_set_status`](./Docs/SpecialRenderings.md#maproulettesetstatus) - which allows to apply different status codes or different messages/icons.
|
||||||
|
|
||||||
## Creating a maproulette challenge
|
|
||||||
|
|
||||||
A challenge can be created on https://maproulette.org/admin/projects
|
|
||||||
|
|
||||||
This can be done with a geojson-file (or by other means).
|
|
||||||
|
|
||||||
MapRoulette works as a geojson-store with status fields added. As such, you have a bit of freedom in creating the data, but an **id** field is mandatory. A **name** tag is recommended
|
|
||||||
|
|
||||||
To setup a guided import, add a `tags`-field with tags formatted in such a way that they are compatible with the [import-button](./Docs/SpecialRenderings.md#specifying-which-tags-to-copy-or-add)
|
|
||||||
|
|
||||||
|
|
||||||
(The following example is not tested and might be wrong.)
|
|
||||||
|
|
||||||
```
|
|
||||||
{
|
|
||||||
"type": "FeatureCollection",
|
|
||||||
"features": [
|
|
||||||
{
|
|
||||||
"type": "Feature",
|
|
||||||
"geometry": {"type": "Point", "coordinates": [1.234, 5.678]},
|
|
||||||
"properties": {
|
|
||||||
"id": ...
|
|
||||||
"tags": "foo=bar;name=xyz",
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
|
@ -107,16 +107,15 @@
|
||||||
"=tagRenderings": [
|
"=tagRenderings": [
|
||||||
{
|
{
|
||||||
"id": "explanation",
|
"id": "explanation",
|
||||||
|
"classes":"border-2 border-interactive low-interaction p-2 m-2",
|
||||||
"render": {
|
"render": {
|
||||||
"en": "This is a bench that is known in Openbenches.org but might not exist in OpenStreetMap. If this bench still exists in the real world, you can add or link this information to OpenStreetMap with the tools below"
|
"en": "This is a bench that is known in Openbenches.org but might not exist in OpenStreetMap. If this bench still exists in the real world, you can add or link this information to OpenStreetMap with the tools below"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"id": "images",
|
|
||||||
"render": "<img src='{image}'/>"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"id": "see_on_openbenches",
|
"id": "see_on_openbenches",
|
||||||
|
"classes": "text-lg button",
|
||||||
|
"icon": "./assets/themes/benches/openbencheslogo.svg",
|
||||||
"render": {
|
"render": {
|
||||||
"special": {
|
"special": {
|
||||||
"type": "link",
|
"type": "link",
|
||||||
|
@ -127,6 +126,10 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"id": "images",
|
||||||
|
"render": "{image_carousel()}"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "closeness-indicator",
|
"id": "closeness-indicator",
|
||||||
"condition": "_has_closeby_feature=yes",
|
"condition": "_has_closeby_feature=yes",
|
||||||
|
|
|
@ -20,5 +20,15 @@
|
||||||
"https://github.com/streetcomplete/StreetComplete/blob/v25.0-beta1/res/graphics/authors.txt",
|
"https://github.com/streetcomplete/StreetComplete/blob/v25.0-beta1/res/graphics/authors.txt",
|
||||||
"https://github.com/streetcomplete/StreetComplete/tree/v25.0-beta1/res/graphics/quest%20icons"
|
"https://github.com/streetcomplete/StreetComplete/tree/v25.0-beta1/res/graphics/quest%20icons"
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "openbencheslogo.svg",
|
||||||
|
"license": "LOGO",
|
||||||
|
"authors": [
|
||||||
|
"Terence Eden"
|
||||||
|
],
|
||||||
|
"sources": [
|
||||||
|
"https://openbenches.org/images/openbencheslogo.svg"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
10
assets/themes/benches/openbencheslogo.svg
Normal file
10
assets/themes/benches/openbencheslogo.svg
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 800">
|
||||||
|
<circle cx="400" cy="400" r="400" fill="#11b0a3"/>
|
||||||
|
<circle cx="573" cy="275" r="106" fill="#070"/>
|
||||||
|
<path d="M153 345h256v77H153z" fill="#fff"/>
|
||||||
|
<path d="M191 376h177v20H191z" fill="#ffba00"/>
|
||||||
|
<path d="M28.7 507.6h735.7C706.5 748.5 539.5 771.1 409.2 792c-181.7-27.8-324-103.8-380.5-284.4z" fill="#8c5015"/>
|
||||||
|
<path d="M607 490c9-29 66 4 161-112 29-7 15 79 8 111z" fill="#070"/>
|
||||||
|
<path d="M259 197l19-7c-1 0-10-36 17-50l-10-18a55 55 0 0 0-29 45 95 95 0 0 0-49-10l2 20s39-3 50 20zM326 256l18 9c1-2 19-33 48-24l5-19c-21-7-39 0-52 11-6-24-26-41-27-42l-13 15c0 1 29 26 21 50z" fill="#000"/>
|
||||||
|
<path d="M768.6 244.3a398.7 398.7 0 0 0-85.8-127.1A398.7 398.7 0 0 0 400 0a397.5 397.5 0 0 0-282.8 117.2A398.7 398.7 0 0 0 0 400a397.5 397.5 0 0 0 117.2 282.8A398.7 398.7 0 0 0 400 800a397.5 397.5 0 0 0 282.8-117.2A398.7 398.7 0 0 0 800 400c0-54-10.6-106.4-31.4-155.7zM30.3 487.6A380.4 380.4 0 0 1 400 20c197.2 0 359.7 151 378.2 343.4a69.2 69.2 0 0 0-56.6 57.7 71 71 0 0 0-53.8 37.2 48.7 48.7 0 0 0-66.1 29.1h-20.5V381.8a110.5 110.5 0 0 0-12-220.2 110.5 110.5 0 0 0-8.1 220.5v105.5H396.5v-47h72.3v-20h-40.5v-94.4H133.5v94.4h-32.1v20h64.2v47zm644 0h-50.6a28.5 28.5 0 0 1 42.4-6.9zM561.1 324.4V362a90.5 90.5 0 0 1 8-180.3 90.4 90.4 0 0 1 12 179.9v-29.2l56.4-56.3-14.2-14.2-42.1 42.1v-38H561v30l-37-37.1-14.3 14.2zm-407.5 96.2v-74.3h254.6v74.3zm222.8 20v47H185.7v-47zM400 780c-41.2 0-81-6.6-118.1-18.8l403.8-111A379.1 379.1 0 0 1 400 780zm307-156.4L250 749c-11.4-5-22.6-10.4-33.4-16.4L484 655l-5.5-19.3-285.3 82.8c-13.3-8.7-26-18.2-38.1-28.4l131.8-24.9-3.7-19.7-146.8 27.7a383.3 383.3 0 0 1-36-39.8l637.6-60c-9 17.5-19.4 34.2-31 50zm41-71.2L86.6 614.6a378.6 378.6 0 0 1-51-107h728.8c-4.5 15.4-10 30.3-16.4 44.7zm-69.7-64.7L682 476a51 51 0 0 1 48.6-35.4h10l.2-9.8a49.3 49.3 0 0 1 38.8-47.3 385.6 385.6 0 0 1-9.9 104z" fill="#000"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.8 KiB |
2
assets/themes/benches/openbencheslogo.svg.license
Normal file
2
assets/themes/benches/openbencheslogo.svg.license
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
SPDX-FileCopyrightText: Terence Eden
|
||||||
|
SPDX-License-Identifier: LicenseRef-LOGO
|
|
@ -25,156 +25,93 @@ import { GeoOperations } from "../../src/Logic/GeoOperations"
|
||||||
* "sqlite3": "^5.1.7",
|
* "sqlite3": "^5.1.7",
|
||||||
*/
|
*/
|
||||||
interface Bench {
|
interface Bench {
|
||||||
benchID: number,
|
benchID: number
|
||||||
latitude: number,
|
latitude: number
|
||||||
longitude: number,
|
longitude: number
|
||||||
address: string,
|
address: string
|
||||||
inscription: string,
|
inscription: string
|
||||||
description: string,
|
description: string
|
||||||
present: 0 | 1,
|
present: 0 | 1
|
||||||
published: 0 | 1,
|
published: 0 | 1
|
||||||
/* time of creation (or possibly last edit?) */
|
/* time of creation (or possibly last edit?) */
|
||||||
added: string,
|
added: string
|
||||||
userID: number
|
userID: number
|
||||||
}
|
}
|
||||||
|
|
||||||
interface User {
|
interface User {
|
||||||
name: string,
|
name: string
|
||||||
providerID: string,
|
providerID: string
|
||||||
provider: string,
|
provider: string
|
||||||
userID: number
|
userID: number
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Tag {
|
interface Tag {
|
||||||
tagID: number,
|
tagID: number
|
||||||
tagText: string
|
tagText: string
|
||||||
}
|
}
|
||||||
|
|
||||||
function mediaUrl(sha: string | { "sha1": string }): string {
|
function mediaUrl(sha: string | { sha1: string }): string {
|
||||||
if (sha["sha1"]) {
|
if (sha["sha1"]) {
|
||||||
sha = sha["sha1"]
|
sha = sha["sha1"]
|
||||||
}
|
}
|
||||||
return `https://openbenches.org/image/${sha}.jpg`
|
return `https://openbenches.org/image/${sha}.jpg`
|
||||||
}
|
}
|
||||||
|
|
||||||
const uk: Feature<Polygon> = {
|
const uk: Feature<Polygon> = {
|
||||||
"type": "Feature",
|
type: "Feature",
|
||||||
"properties": {},
|
properties: {},
|
||||||
"geometry": {
|
geometry: {
|
||||||
"coordinates": [
|
coordinates: [
|
||||||
[
|
[
|
||||||
[
|
[3.139397666817615, 53.112746745001914],
|
||||||
3.139397666817615,
|
[0.12546232547020963, 61.34289409315957],
|
||||||
53.112746745001914
|
[-5.193638926198332, 60.3858935023425],
|
||||||
],
|
[-12.316831332595541, 56.76308878364702],
|
||||||
[
|
[-12.586640816376246, 51.076733390490034],
|
||||||
0.12546232547020963,
|
[-3.6443836396576046, 49.4256703574342],
|
||||||
61.34289409315957
|
[1.0194660085441853, 50.442813369706585],
|
||||||
],
|
[3.139397666817615, 53.112746745001914],
|
||||||
[
|
],
|
||||||
-5.193638926198332,
|
|
||||||
60.3858935023425
|
|
||||||
],
|
|
||||||
[
|
|
||||||
-12.316831332595541,
|
|
||||||
56.76308878364702
|
|
||||||
],
|
|
||||||
[
|
|
||||||
-12.586640816376246,
|
|
||||||
51.076733390490034
|
|
||||||
],
|
|
||||||
[
|
|
||||||
-3.6443836396576046,
|
|
||||||
49.4256703574342
|
|
||||||
],
|
|
||||||
[
|
|
||||||
1.0194660085441853,
|
|
||||||
50.442813369706585
|
|
||||||
],
|
|
||||||
[
|
|
||||||
3.139397666817615,
|
|
||||||
53.112746745001914
|
|
||||||
]
|
|
||||||
]
|
|
||||||
],
|
],
|
||||||
"type": "Polygon"
|
type: "Polygon",
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
const us : Feature<Polygon> = {
|
const us: Feature<Polygon> = {
|
||||||
"type": "Feature",
|
type: "Feature",
|
||||||
"properties": {},
|
properties: {},
|
||||||
"geometry": {
|
geometry: {
|
||||||
"coordinates": [
|
coordinates: [
|
||||||
[
|
[
|
||||||
[
|
[-171.55472370762342, 71.44263911390138],
|
||||||
-171.55472370762342,
|
[-171.31347027402668, 33.24735774004321],
|
||||||
71.44263911390138
|
[-105.9804086342826, -3.5292610992716362],
|
||||||
],
|
[-57.00596161415962, 15.805666337324794],
|
||||||
[
|
[-32.880618254493015, 49.584578264365916],
|
||||||
-171.31347027402668,
|
[-47.35582427029317, 72.85409976292118],
|
||||||
33.24735774004321
|
[-101.60890406091582, 79.0557752859543],
|
||||||
],
|
[-171.55472370762342, 71.44263911390138],
|
||||||
[
|
],
|
||||||
-105.9804086342826,
|
|
||||||
-3.5292610992716362
|
|
||||||
],
|
|
||||||
[
|
|
||||||
-57.00596161415962,
|
|
||||||
15.805666337324794
|
|
||||||
],
|
|
||||||
[
|
|
||||||
-32.880618254493015,
|
|
||||||
49.584578264365916
|
|
||||||
],
|
|
||||||
[
|
|
||||||
-47.35582427029317,
|
|
||||||
72.85409976292118
|
|
||||||
],
|
|
||||||
[
|
|
||||||
-101.60890406091582,
|
|
||||||
79.0557752859543
|
|
||||||
],
|
|
||||||
[
|
|
||||||
-171.55472370762342,
|
|
||||||
71.44263911390138
|
|
||||||
]
|
|
||||||
]
|
|
||||||
],
|
],
|
||||||
"type": "Polygon"
|
type: "Polygon",
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
const australia: Feature<Polygon> = {
|
const australia: Feature<Polygon> = {
|
||||||
"type": "Feature",
|
type: "Feature",
|
||||||
"properties": {},
|
properties: {},
|
||||||
"geometry": {
|
geometry: {
|
||||||
"coordinates": [
|
coordinates: [
|
||||||
[
|
[
|
||||||
[
|
[177.6309142850211, -48.72845301037672],
|
||||||
177.6309142850211,
|
[177.6309142850211, -8.050870320392335],
|
||||||
-48.72845301037672
|
[107.59695622498174, -8.050870320392335],
|
||||||
],
|
[107.59695622498174, -48.72845301037672],
|
||||||
[
|
[177.6309142850211, -48.72845301037672],
|
||||||
177.6309142850211,
|
],
|
||||||
-8.050870320392335
|
|
||||||
],
|
|
||||||
[
|
|
||||||
107.59695622498174,
|
|
||||||
-8.050870320392335
|
|
||||||
],
|
|
||||||
[
|
|
||||||
107.59695622498174,
|
|
||||||
-48.72845301037672
|
|
||||||
],
|
|
||||||
[
|
|
||||||
177.6309142850211,
|
|
||||||
-48.72845301037672
|
|
||||||
]
|
|
||||||
]
|
|
||||||
],
|
],
|
||||||
"type": "Polygon"
|
type: "Polygon",
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
const areas = {uk, us, australia}
|
const areas = { uk, us, australia }
|
||||||
|
|
||||||
class Openbenches extends Script {
|
class Openbenches extends Script {
|
||||||
private db: Database
|
private db: Database
|
||||||
|
@ -190,18 +127,18 @@ class Openbenches extends Script {
|
||||||
})
|
})
|
||||||
|
|
||||||
const files = await fs.readdir(sqlDir)
|
const files = await fs.readdir(sqlDir)
|
||||||
const sqlFiles = files.filter(f => f.endsWith(".sql"))
|
const sqlFiles = files.filter((f) => f.endsWith(".sql"))
|
||||||
|
|
||||||
const skip = ["database.sql"]
|
const skip = ["database.sql"]
|
||||||
|
|
||||||
|
|
||||||
const order = ["tags", "users", "tag_map", "media_types", "benches", "media"]
|
const order = ["tags", "users", "tag_map", "media_types", "benches", "media"]
|
||||||
|
|
||||||
for (let file of order) {
|
for (let file of order) {
|
||||||
console.log("Exec file", file)
|
console.log("Exec file", file)
|
||||||
file = "openbenc_benches_table_" + file + ".sql"
|
file = "openbenc_benches_table_" + file + ".sql"
|
||||||
let content = await fs.readFile(join(sqlDir, file), "utf-8")
|
let content = await fs.readFile(join(sqlDir, file), "utf-8")
|
||||||
content = content.replaceAll("ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci", "")
|
content = content
|
||||||
|
.replaceAll("ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci", "")
|
||||||
.replaceAll("\\'", "''")
|
.replaceAll("\\'", "''")
|
||||||
await db.exec(content)
|
await db.exec(content)
|
||||||
}
|
}
|
||||||
|
@ -228,39 +165,37 @@ class Openbenches extends Script {
|
||||||
driver: sqlite3.Database,
|
driver: sqlite3.Database,
|
||||||
})
|
})
|
||||||
return <any>db.db
|
return <any>db.db
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async createBenchInfo(benchWithUser: Bench & User, tags: string[]): Promise<Feature<Point>> {
|
async createBenchInfo(benchWithUser: Bench & User, tags: string[]): Promise<Feature<Point>> {
|
||||||
const id = benchWithUser.benchID
|
const id = benchWithUser.benchID
|
||||||
const media = await this.all<{
|
const media = await this.all<{
|
||||||
sha1: string,
|
sha1: string
|
||||||
media_type: string
|
media_type: string
|
||||||
}>("SELECT * FROM media WHERE media.benchID = " + id)
|
}>("SELECT * FROM media WHERE media.benchID = " + id)
|
||||||
const mediaBench = media.filter(m => m.media_type === "bench")
|
const mediaBench = media.filter((m) => m.media_type === "bench")
|
||||||
const mediaInscr = media.filter(m => m.media_type === "inscription")
|
const mediaInscr = media.filter((m) => m.media_type === "inscription")
|
||||||
const mediaView = media.filter(m => m.media_type === "view")
|
const mediaView = media.filter((m) => m.media_type === "view")
|
||||||
|
|
||||||
const inscription = benchWithUser.inscription.replaceAll("\\r\\n", "\n")
|
const inscription = benchWithUser.inscription.replaceAll("\\r\\n", "\n")
|
||||||
const properties = {
|
const properties = {
|
||||||
lastModifiedTime: benchWithUser.added,
|
lastModifiedTime: benchWithUser.added,
|
||||||
"openbenches:id": id,
|
"openbenches:id": id,
|
||||||
inscription: inscription.slice(0,255),
|
inscription: inscription.slice(0, 255),
|
||||||
amenity: "bench",
|
amenity: "bench",
|
||||||
lastModifiedBy: benchWithUser.name,
|
lastModifiedBy: benchWithUser.name,
|
||||||
}
|
}
|
||||||
if(inscription.length >= 255){
|
if (inscription.length >= 255) {
|
||||||
properties["inscription:0"] = inscription.slice(255)
|
properties["inscription:0"] = inscription.slice(255)
|
||||||
}
|
}
|
||||||
|
|
||||||
let mediaMerged = Lists.dedup(mediaBench.concat(mediaInscr).map(m => mediaUrl(m)))
|
let mediaMerged = Lists.dedup(mediaBench.concat(mediaInscr).map((m) => mediaUrl(m)))
|
||||||
for (let i = 0; i < mediaMerged.length; i++) {
|
for (let i = 0; i < mediaMerged.length; i++) {
|
||||||
const m = mediaMerged[i]
|
const m = mediaMerged[i]
|
||||||
if (i === 0) {
|
if (i === 0) {
|
||||||
properties["image"] = m
|
properties["image"] = m
|
||||||
} else {
|
} else {
|
||||||
properties["image:" + (i - 1)] = m
|
properties["image:" + (i - 1)] = m
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -270,18 +205,17 @@ class Openbenches extends Script {
|
||||||
properties["image:view"] = mediaUrl(m)
|
properties["image:view"] = mediaUrl(m)
|
||||||
} else {
|
} else {
|
||||||
properties["image:view:" + (i - 1)] = mediaUrl(m)
|
properties["image:view:" + (i - 1)] = mediaUrl(m)
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const tagsToProperties = {
|
const tagsToProperties = {
|
||||||
"wooden": "material=wood",
|
wooden: "material=wood",
|
||||||
"metal": "material=metal",
|
metal: "material=metal",
|
||||||
"indoors": "indoor=yes",
|
indoors: "indoor=yes",
|
||||||
"stone": "material=stone",
|
stone: "material=stone",
|
||||||
"poem": "artwork=poem",
|
poem: "artwork=poem",
|
||||||
"statue": "artwork=statue",
|
statue: "artwork=statue",
|
||||||
"composite": "material=plastic",
|
composite: "material=plastic",
|
||||||
/*"cat":"subject=cat",
|
/*"cat":"subject=cat",
|
||||||
"dog":"subject=dog" Not always a pet, sometimes also a 'dogwalker', someone mentioning their cat, ... */
|
"dog":"subject=dog" Not always a pet, sometimes also a 'dogwalker', someone mentioning their cat, ... */
|
||||||
// EMOJI: very broad category, basically that a little image is part of the 'inscription'. Should be handled by adding the emoji directly
|
// EMOJI: very broad category, basically that a little image is part of the 'inscription'. Should be handled by adding the emoji directly
|
||||||
|
@ -291,7 +225,7 @@ class Openbenches extends Script {
|
||||||
// FUnny: talk about subjective...
|
// FUnny: talk about subjective...
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const tag of (tags ?? [])) {
|
for (const tag of tags ?? []) {
|
||||||
const match = tagsToProperties[tag]
|
const match = tagsToProperties[tag]
|
||||||
if (!match) {
|
if (!match) {
|
||||||
continue
|
continue
|
||||||
|
@ -314,7 +248,10 @@ class Openbenches extends Script {
|
||||||
async getAlreadyImported(): Promise<FeatureCollection> {
|
async getAlreadyImported(): Promise<FeatureCollection> {
|
||||||
const alreadyImportedPath = "openbenches_linked_in_osm.geojson"
|
const alreadyImportedPath = "openbenches_linked_in_osm.geojson"
|
||||||
if (!existsSync(alreadyImportedPath)) {
|
if (!existsSync(alreadyImportedPath)) {
|
||||||
const overpass = new Overpass(Constants.defaultOverpassUrls[0], TagUtils.Tag("openbenches:id~*"))
|
const overpass = new Overpass(
|
||||||
|
Constants.defaultOverpassUrls[0],
|
||||||
|
TagUtils.Tag("openbenches:id~*")
|
||||||
|
)
|
||||||
const dataAndDate = await overpass.queryGeoJson(BBox.global)
|
const dataAndDate = await overpass.queryGeoJson(BBox.global)
|
||||||
const data = dataAndDate[0]
|
const data = dataAndDate[0]
|
||||||
writeFileSync(alreadyImportedPath, JSON.stringify(data), "utf-8")
|
writeFileSync(alreadyImportedPath, JSON.stringify(data), "utf-8")
|
||||||
|
@ -345,7 +282,11 @@ class Openbenches extends Script {
|
||||||
}
|
}
|
||||||
if (key.startsWith("image")) {
|
if (key.startsWith("image")) {
|
||||||
const imgValue = ob.properties[key]
|
const imgValue = ob.properties[key]
|
||||||
if (Object.values(bench.properties).some(v => v === imgValue || (v + ".jpg") === imgValue)) {
|
if (
|
||||||
|
Object.values(bench.properties).some(
|
||||||
|
(v) => v === imgValue || v + ".jpg" === imgValue
|
||||||
|
)
|
||||||
|
) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
let ikey = "image"
|
let ikey = "image"
|
||||||
|
@ -354,37 +295,44 @@ class Openbenches extends Script {
|
||||||
i++
|
i++
|
||||||
ikey = "image:" + i
|
ikey = "image:" + i
|
||||||
}
|
}
|
||||||
const li = new ChangeTagAction(bench.properties.id, new OsmTag(ikey, imgValue), bench.properties, {
|
const li = new ChangeTagAction(
|
||||||
theme: "openbenches",
|
bench.properties.id,
|
||||||
changeType: "link-image",
|
new OsmTag(ikey, imgValue),
|
||||||
})
|
bench.properties,
|
||||||
|
{
|
||||||
|
theme: "openbenches",
|
||||||
|
changeType: "link-image",
|
||||||
|
}
|
||||||
|
)
|
||||||
changes.push(li)
|
changes.push(li)
|
||||||
bench.properties[ikey] = imgValue
|
bench.properties[ikey] = imgValue
|
||||||
console.log(` + ${ikey}=${imgValue}`)
|
console.log(` + ${ikey}=${imgValue}`)
|
||||||
} else if (!bench.properties[key]) {
|
} else if (!bench.properties[key]) {
|
||||||
const v = ob.properties[key]
|
const v = ob.properties[key]
|
||||||
if(v.length >= 255){
|
if (v.length >= 255) {
|
||||||
console.log("Text too long:", v.replaceAll("\n"," "))
|
console.log("Text too long:", v.replaceAll("\n", " "))
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
changes.push(new ChangeTagAction(
|
changes.push(
|
||||||
bench.properties.id,
|
new ChangeTagAction(
|
||||||
new OsmTag(key, v),
|
bench.properties.id,
|
||||||
bench.properties,
|
new OsmTag(key, v),
|
||||||
{
|
bench.properties,
|
||||||
theme: "openbenches",
|
{
|
||||||
changeType: "answer",
|
theme: "openbenches",
|
||||||
},
|
changeType: "answer",
|
||||||
))
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
console.log(` - ${key}=${ob.properties[key].replaceAll("\n", " ")}`)
|
console.log(` - ${key}=${ob.properties[key].replaceAll("\n", " ")}`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(changes.length === 0){
|
if (changes.length === 0) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const xml = await Changes.createChangesetXMLForJosm(changes)
|
const xml = await Changes.createChangesetXMLForJosm(changes)
|
||||||
writeFileSync(`attributes_import${area}.osc`,xml, "utf-8")
|
writeFileSync(`attributes_import${area}.osc`, xml, "utf-8")
|
||||||
}
|
}
|
||||||
|
|
||||||
async main(args: string[]): Promise<void> {
|
async main(args: string[]): Promise<void> {
|
||||||
|
@ -394,12 +342,13 @@ class Openbenches extends Script {
|
||||||
const osmData = await this.getAlreadyImported()
|
const osmData = await this.getAlreadyImported()
|
||||||
|
|
||||||
// rmSync(dbFile)
|
// rmSync(dbFile)
|
||||||
if(!existsSync(dbFile)){
|
if (!existsSync(dbFile)) {
|
||||||
console.log("No database file found at "+dbFile+", recreating the database")
|
console.log("No database file found at " + dbFile + ", recreating the database")
|
||||||
await this.buildDatabase("/home/pietervdvn/git/openbenches.org/database", dbFile)
|
await this.buildDatabase("/home/pietervdvn/git/openbenches.org/database", dbFile)
|
||||||
}
|
}
|
||||||
const alreadyLinked: Set<number> = new Set(osmData.features.map(f => Number(f.properties["openbenches:id"])))
|
const alreadyLinked: Set<number> = new Set(
|
||||||
|
osmData.features.map((f) => Number(f.properties["openbenches:id"]))
|
||||||
|
)
|
||||||
|
|
||||||
this.db = await this.loadDb(dbFile)
|
this.db = await this.loadDb(dbFile)
|
||||||
|
|
||||||
|
@ -409,7 +358,9 @@ class Openbenches extends Script {
|
||||||
tags.set(tag.tagID, tag.tagText)
|
tags.set(tag.tagID, tag.tagText)
|
||||||
}
|
}
|
||||||
const tagsOnBenches = new Map<number, string[]>()
|
const tagsOnBenches = new Map<number, string[]>()
|
||||||
const tagOnBench = await this.all<{ benchID: number, tagID: number }>("SELECT * from tag_map")
|
const tagOnBench = await this.all<{ benchID: number; tagID: number }>(
|
||||||
|
"SELECT * from tag_map"
|
||||||
|
)
|
||||||
for (const tg of tagOnBench) {
|
for (const tg of tagOnBench) {
|
||||||
const bench = tg.benchID
|
const bench = tg.benchID
|
||||||
if (!tagsOnBenches.has(bench)) {
|
if (!tagsOnBenches.has(bench)) {
|
||||||
|
@ -418,11 +369,13 @@ class Openbenches extends Script {
|
||||||
tagsOnBenches.get(bench).push(tags.get(tg.tagID))
|
tagsOnBenches.get(bench).push(tags.get(tg.tagID))
|
||||||
}
|
}
|
||||||
|
|
||||||
const openbenches = await this.all<Bench & User>("SELECT * FROM benches INNER JOIN users ON benches.userID = users.userID")
|
const openbenches = await this.all<Bench & User>(
|
||||||
|
"SELECT * FROM benches INNER JOIN users ON benches.userID = users.userID"
|
||||||
|
)
|
||||||
const features: Feature<Point>[] = []
|
const features: Feature<Point>[] = []
|
||||||
let skipped = 0
|
let skipped = 0
|
||||||
for (let i = 0; i < openbenches.length; i++) {
|
for (let i = 0; i < openbenches.length; i++) {
|
||||||
if(alreadyLinked.has(i)){
|
if (alreadyLinked.has(i)) {
|
||||||
skipped++
|
skipped++
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -432,33 +385,50 @@ class Openbenches extends Script {
|
||||||
}
|
}
|
||||||
const tags = tagsOnBenches.get(benchWithUser.benchID)
|
const tags = tagsOnBenches.get(benchWithUser.benchID)
|
||||||
if (i % 100 === 0) {
|
if (i % 100 === 0) {
|
||||||
ScriptUtils.erasableLog(`Processing bench ${i}/${openbenches.length} (${Math.round(100 * i / openbenches.length)}%) `)
|
ScriptUtils.erasableLog(
|
||||||
|
`Processing bench ${i}/${openbenches.length} (${Math.round(
|
||||||
|
(100 * i) / openbenches.length
|
||||||
|
)}%) `
|
||||||
|
)
|
||||||
}
|
}
|
||||||
features.push(await this.createBenchInfo(benchWithUser, tags))
|
features.push(await this.createBenchInfo(benchWithUser, tags))
|
||||||
if (createTest && features.length > 1000) {
|
if (createTest && features.length > 1000) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
writeFileSync(`openbenches_export_josm_${createTest ? "_test" : ""}.geojson`, JSON.stringify({
|
writeFileSync(`openbenches_export_josm_${createTest ? "_test" : ""}.geojson`, JSON.stringify({
|
||||||
type: "FeatureCollection", features,
|
type: "FeatureCollection", features,
|
||||||
}, null, " "), "utf-8")*/
|
}, null, " "), "utf-8")*/
|
||||||
|
|
||||||
const maproulette = features
|
const maproulette = features.map((f) => {
|
||||||
.map(f => {
|
const fProps = {
|
||||||
const properties = {tags: JSON.stringify(f.properties)}
|
...f.properties
|
||||||
properties["id"] = "openbenches/"+f.properties["openbenches:id"]
|
}
|
||||||
return {...f, properties}
|
|
||||||
|
delete fProps["lastModifiedBy"]
|
||||||
|
delete fProps["lastModifiedTime"]
|
||||||
|
const properties = { ...f.properties, tags: JSON.stringify(fProps) }
|
||||||
|
delete properties["amenity"] // Makes sure mapcomplete doesn't think this is a bench...
|
||||||
|
properties["id"] = "openbenches/" + f.properties["openbenches:id"]
|
||||||
|
|
||||||
|
return { ...f, properties }
|
||||||
})
|
})
|
||||||
console.log("Skipped",skipped,"benches as already linked/imported")
|
console.log("Skipped", skipped, "benches as already linked/imported")
|
||||||
writeFileSync(`openbenches_export_maproulette${createTest ? "_test" : ""}.geojson`, JSON.stringify({
|
writeFileSync(
|
||||||
type: "FeatureCollection", features: maproulette,
|
`openbenches_export_maproulette${createTest ? "_test" : ""}.geojson`,
|
||||||
}, null, " "), "utf-8")
|
JSON.stringify(
|
||||||
|
{
|
||||||
|
type: "FeatureCollection",
|
||||||
|
features: maproulette,
|
||||||
|
},
|
||||||
|
null,
|
||||||
|
" "
|
||||||
|
),
|
||||||
|
"utf-8"
|
||||||
|
)
|
||||||
|
|
||||||
await this.conflate(osmData.features, { type: "FeatureCollection", features }, "_all")
|
await this.conflate(osmData.features, { type: "FeatureCollection", features }, "_all")
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue