forked from MapComplete/MapComplete
More improvements to the charging station theme
This commit is contained in:
parent
bd37cc812f
commit
3492b5d403
4 changed files with 1611 additions and 98 deletions
File diff suppressed because it is too large
Load diff
|
@ -129,10 +129,12 @@
|
||||||
{
|
{
|
||||||
"#": "capacity",
|
"#": "capacity",
|
||||||
"render": {
|
"render": {
|
||||||
"en": "{capacity} vehicles can be charged here at the same time"
|
"en": "{capacity} vehicles can be charged here at the same time",
|
||||||
|
"nl": "{capacity} voertuigen kunnen hier op hetzelfde moment opgeladen worden"
|
||||||
},
|
},
|
||||||
"question": {
|
"question": {
|
||||||
"en": "How much vehicles can be charged here at the same time?"
|
"en": "How much vehicles can be charged here at the same time?",
|
||||||
|
"nl": "Hoeveel voertuigen kunnen hier opgeladen worden?"
|
||||||
},
|
},
|
||||||
"freeform": {
|
"freeform": {
|
||||||
"key": "capacity",
|
"key": "capacity",
|
||||||
|
@ -277,6 +279,58 @@
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"#": "fee/charge",
|
||||||
|
"question": {
|
||||||
|
"en": "How much does one have to pay to use this charging station?",
|
||||||
|
"nl": "Hoeveel kost het gebruik van dit oplaadpunt?"
|
||||||
|
},
|
||||||
|
"freeform": {
|
||||||
|
"key": "charge",
|
||||||
|
"addExtraTags": [
|
||||||
|
"fee=yes"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"render": {
|
||||||
|
"en": "Using this charging station costs <b>{charge}</b>",
|
||||||
|
"nl": "Dit oplaadpunt gebruiken kost <b>{charge}</b>"
|
||||||
|
},
|
||||||
|
"mappings": [
|
||||||
|
{
|
||||||
|
"if": {
|
||||||
|
"and": [
|
||||||
|
"fee=no",
|
||||||
|
"charge="
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"then": {
|
||||||
|
"nl": "Gratis te gebruiken",
|
||||||
|
"en": "Free to use"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"builtin": "payment-options",
|
||||||
|
"override": {
|
||||||
|
"condition": {
|
||||||
|
"or": [
|
||||||
|
"fee=yes",
|
||||||
|
"charge~*"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"mappings+": [
|
||||||
|
{
|
||||||
|
"if": "payment:app=yes",
|
||||||
|
"ifnot": "payment:app=no",
|
||||||
|
"then": {
|
||||||
|
"en": "Payment is done using a dedicated app",
|
||||||
|
"nl": "Betalen via een app van het netwerk"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"#": "Network",
|
"#": "Network",
|
||||||
"render": {
|
"render": {
|
||||||
|
@ -518,6 +572,9 @@
|
||||||
],
|
],
|
||||||
"title": {
|
"title": {
|
||||||
"en": "Charging station"
|
"en": "Charging station"
|
||||||
|
},
|
||||||
|
"preciseInput": {
|
||||||
|
"preferredBackground": "map"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
|
@ -1,34 +1,80 @@
|
||||||
import {readFileSync, writeFileSync} from "fs";
|
import {readFileSync, writeFileSync} from "fs";
|
||||||
import {Utils} from "../../../Utils";
|
import {Utils} from "../../../Utils";
|
||||||
|
import {TagRenderingConfigJson} from "../../../Models/ThemeConfig/Json/TagRenderingConfigJson";
|
||||||
|
import ScriptUtils from "../../../scripts/ScriptUtils";
|
||||||
|
|
||||||
|
|
||||||
|
function colonSplit(value: string): string[] {
|
||||||
|
return value.split(";").map(v => v.replace(/"/g, '').trim().toLowerCase()).filter(s => s !== "");
|
||||||
|
}
|
||||||
|
|
||||||
|
function loadCsv(file): {
|
||||||
|
key: string,
|
||||||
|
image: string,
|
||||||
|
description: Map<string, string>,
|
||||||
|
countryWhiteList?: string[],
|
||||||
|
commonVoltages?: number[],
|
||||||
|
commonCurrents?: number[],
|
||||||
|
commonOutputs?: string[]
|
||||||
|
}[] {
|
||||||
|
const entries: string[] = Utils.NoNull(readFileSync(file, "utf8").split("\n").map(str => str.trim()))
|
||||||
|
const header = entries.shift().split(",")
|
||||||
|
|
||||||
|
return Utils.NoNull(entries.map(entry => {
|
||||||
|
const values = entry.split(",").map(str => str.trim())
|
||||||
|
if (values[0] === undefined || values[0] === "") {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
const v = {}
|
||||||
|
const colonSeperated = ["commonVoltages", "commonOutputs", "commonCurrents", "countryWhiteList"]
|
||||||
|
const descriptionTranslations = new Map<string, string>()
|
||||||
|
for (let j = 0; j < header.length; j++) {
|
||||||
|
const key = header[j];
|
||||||
|
if (key.startsWith("description")) {
|
||||||
|
const language = key.substring("description:".length)
|
||||||
|
descriptionTranslations.set(language, values[j])
|
||||||
|
}
|
||||||
|
|
||||||
|
if (colonSeperated.indexOf(key) >= 0) {
|
||||||
|
v[key] = colonSplit(values[j])
|
||||||
|
} else {
|
||||||
|
v[key] = values[j]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
v["description"] = descriptionTranslations
|
||||||
|
return <any>v;
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
// SMall script to output the properties of the types.csv as json to add in the tagRenderingGroup. Should be copied manually
|
// SMall script to output the properties of the types.csv as json to add in the tagRenderingGroup. Should be copied manually
|
||||||
function run(file, protojson) {
|
function run(file, protojson) {
|
||||||
const entries: string[] = Utils.NoNull(readFileSync(file, "utf8").split("\n").map(str => str.trim()))
|
|
||||||
entries.shift()
|
|
||||||
|
|
||||||
const overview_question_answers = []
|
const overview_question_answers = []
|
||||||
const questions = []
|
const questions: TagRenderingConfigJson[] = []
|
||||||
const filterOptions: { question: string, osmTags?: string } [] = [
|
const filterOptions: { question: any, osmTags?: string } [] = [
|
||||||
{
|
{
|
||||||
question: "All connectors"
|
question: {
|
||||||
|
en: "All connectors",
|
||||||
|
nl: "Alle types"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
for (const entry of entries) {
|
const entries = loadCsv(file)
|
||||||
const [key, image, description, whitelist] = entry.split(",").map(str => str.trim())
|
for (const e of entries) {
|
||||||
if (key === "") {
|
const txt = {
|
||||||
continue;
|
en: `<img style='width:3rem; margin-left: 1rem; margin-right: 1rem' src='./assets/layers/charging_station/${e.image}'/> ${e.description.get("en")}`,
|
||||||
|
nl: `<img style='width:3rem; margin-left: 1rem; margin-right: 1rem' src='./assets/layers/charging_station/${e.image}'/> ${e.description.get("nl")}`
|
||||||
}
|
}
|
||||||
|
|
||||||
const txt = `<img style='width:3rem; margin-left: 1rem; margin-right: 1rem' src='./assets/layers/charging_station/${image}'/> ${description}`
|
|
||||||
const json = {
|
const json = {
|
||||||
if: `${key}=1`,
|
if: `${e.key}=1`,
|
||||||
ifnot: `${key}=`,
|
ifnot: `${e.key}=`,
|
||||||
then: txt,
|
then: txt,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (whitelist) {
|
if (e.countryWhiteList !== undefined && e.countryWhiteList.length > 0) {
|
||||||
const countries = whitelist.replace(/"/g, '').split(",").map(country => "_country!=" + country) //HideInAnswer if it is in the wrong country
|
const countries = e.countryWhiteList.map(country => "_country!=" + country) //HideInAnswer if it is in the wrong country
|
||||||
json["hideInAnswer"] = {or: countries}
|
json["hideInAnswer"] = {or: countries}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,32 +83,123 @@ function run(file, protojson) {
|
||||||
// We add a second time for any amount to trigger a visualisation; but this is not an answer option
|
// We add a second time for any amount to trigger a visualisation; but this is not an answer option
|
||||||
const no_ask_json = {
|
const no_ask_json = {
|
||||||
if: {
|
if: {
|
||||||
and: [`${key}~*`, `${key}!=1`]
|
and: [`${e.key}~*`, `${e.key}!=1`]
|
||||||
},
|
},
|
||||||
then: txt,
|
then: txt,
|
||||||
hideInAnswer: true
|
hideInAnswer: true
|
||||||
}
|
}
|
||||||
overview_question_answers.push(no_ask_json)
|
overview_question_answers.push(no_ask_json)
|
||||||
|
|
||||||
const indivQ = {
|
const descrWithImage_en = `<b>${e.description.get("en")}</b> <img style='width:1rem;' src='./assets/layers/charging_station/${e.image}'/>`
|
||||||
|
const descrWithImage_nl = `<b>${e.description.get("nl")}</b> <img style='width:1rem;' src='./assets/layers/charging_station/${e.image}'/>`
|
||||||
|
|
||||||
|
questions.push({
|
||||||
question: {
|
question: {
|
||||||
en: `How much plugs of type ${description} <img style='width:1rem; margin-left: 1rem; margin-right: 1rem' src='./assets/layers/charging_station/${image}'/> are available here?`
|
en: `How much plugs of type ${descrWithImage_en} are available here?`,
|
||||||
|
nl: `Hoeveel stekkers van type ${descrWithImage_nl} heeft dit oplaadpunt?`,
|
||||||
|
},
|
||||||
|
render: {
|
||||||
|
en: `There are ${descrWithImage_en} plugs of type ${e.description.get("en")} available here`,
|
||||||
|
nl: `Hier zijn ${descrWithImage_nl} stekkers van het type ${e.description.get("nl")}`
|
||||||
},
|
},
|
||||||
render: `There are <b>{${key}}</b> <img style='width:1rem' src='./assets/layers/charging_station/${image}'/> plugs of type ${description} available here`,
|
|
||||||
freeform: {
|
freeform: {
|
||||||
key: key,
|
key: e.key,
|
||||||
type: "pnat"
|
type: "pnat"
|
||||||
},
|
},
|
||||||
condition: `${key}~*`
|
condition: {
|
||||||
|
and: [`${e.key}~*`, `${e.key}!=0`]
|
||||||
}
|
}
|
||||||
|
})
|
||||||
|
|
||||||
questions.push(indivQ)
|
questions.push({
|
||||||
|
question: {
|
||||||
|
en: `What voltage do the plugs with ${descrWithImage_en} offer?`,
|
||||||
|
nl: `Welke spanning levert de stekker van type ${descrWithImage_nl}`
|
||||||
|
},
|
||||||
|
render: {
|
||||||
|
en: `${descrWithImage_en} outputs {${e.key}:voltage} volt`,
|
||||||
|
nl: `${descrWithImage_nl} heeft een spanning van {${e.key}:voltage} volt`
|
||||||
|
},
|
||||||
|
freeform: {
|
||||||
|
key: `${e.key}:voltage`,
|
||||||
|
type: "pfloat"
|
||||||
|
},
|
||||||
|
mappings: e.commonVoltages.map(voltage => {
|
||||||
|
return {
|
||||||
|
if: `socket:${e.key}:voltage=${voltage} V`,
|
||||||
|
then: {
|
||||||
|
en: `${descrWithImage_en} outputs ${voltage} volt`,
|
||||||
|
nl: `${descrWithImage_nl} heeft een spanning van ${voltage} volt`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
condition: {
|
||||||
|
and: [`${e.key}~*`, `${e.key}!=0`]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
questions.push({
|
||||||
|
question: {
|
||||||
|
en: `What current do the plugs with ${descrWithImage_en} offer?`,
|
||||||
|
nl: `Welke stroom levert de stekker van type ${descrWithImage_nl}?`,
|
||||||
|
},
|
||||||
|
render: {
|
||||||
|
en: `${descrWithImage_en} outputs at most {${e.key}:current}A`,
|
||||||
|
nl: `${descrWithImage_nl} levert een stroom van maximaal {${e.key}:current}A`
|
||||||
|
},
|
||||||
|
freeform: {
|
||||||
|
key: `${e.key}:current`,
|
||||||
|
type: "pfloat"
|
||||||
|
},
|
||||||
|
mappings: e.commonCurrents.map(current => {
|
||||||
|
return {
|
||||||
|
if: `socket:${e.key}:current=${current} A`,
|
||||||
|
then: {
|
||||||
|
en: `${descrWithImage_en} outputs at most ${current} A`,
|
||||||
|
nl: `${descrWithImage_nl} levert een stroom van maximaal ${current} A`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
condition: {
|
||||||
|
and: [`${e.key}~*`, `${e.key}!=0`]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
questions.push({
|
||||||
|
question: {
|
||||||
|
en: `What power output does a single plug of type ${descrWithImage_en} offer?`,
|
||||||
|
nl: `Welk vermogen levert een enkele stekker van type ${descrWithImage_nl}?`,
|
||||||
|
},
|
||||||
|
render: {
|
||||||
|
en: `${descrWithImage_en} outputs at most {${e.key}:output}`,
|
||||||
|
nl: `${descrWithImage_nl} levert een vermogen van maximaal {${e.key}:output}`
|
||||||
|
},
|
||||||
|
freeform: {
|
||||||
|
key: `${e.key}:output`,
|
||||||
|
type: "pfloat"
|
||||||
|
},
|
||||||
|
mappings: e.commonOutputs.map(output => {
|
||||||
|
return {
|
||||||
|
if: `socket:${e.key}:output=${output}`,
|
||||||
|
then: {
|
||||||
|
en: `${descrWithImage_en} outputs at most ${output}`,
|
||||||
|
nl: `${descrWithImage_nl} levert een vermogen van maximaal ${output}`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
condition: {
|
||||||
|
and: [`${e.key}~*`, `${e.key}!=0`]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
filterOptions.push({
|
filterOptions.push({
|
||||||
question: `Has a ${description} <img style='width:1rem' src='./assets/layers/charging_station/${image}'/> connector`,
|
question: {
|
||||||
osmTags: `${key}~*`
|
en: `Has a ${descrWithImage_en} connector`,
|
||||||
|
nl: `Heeft een ${descrWithImage_nl}`
|
||||||
|
},
|
||||||
|
osmTags: `${e.key}~*`
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,11 +219,99 @@ function run(file, protojson) {
|
||||||
proto["filter"].push({
|
proto["filter"].push({
|
||||||
options: filterOptions
|
options: filterOptions
|
||||||
})
|
})
|
||||||
|
|
||||||
|
proto["units"] = [
|
||||||
|
{
|
||||||
|
appliesToKey: entries.map(e => e.key + ":voltage"),
|
||||||
|
applicableUnits: [{
|
||||||
|
canonicalDenomination: 'V',
|
||||||
|
alternativeDenomination: ["v", "volt", "voltage",'V','Volt'],
|
||||||
|
human: {
|
||||||
|
en: "Volts",
|
||||||
|
nl: "volt"
|
||||||
|
}
|
||||||
|
}],
|
||||||
|
eraseInvalidValues: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
appliesToKey: entries.map(e => e.key + ":current"),
|
||||||
|
applicableUnits: [{
|
||||||
|
canonicalDenomination: 'A',
|
||||||
|
alternativeDenomination: ["a", "amp", "amperage",'A'],
|
||||||
|
human: {
|
||||||
|
en: "A",
|
||||||
|
nl: "A"
|
||||||
|
}
|
||||||
|
}],
|
||||||
|
eraseInvalidValues: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
appliesToKey: entries.map(e => e.key + ":output"),
|
||||||
|
applicableUnits: [{
|
||||||
|
canonicalDenomination: 'kW',
|
||||||
|
alternativeDenomination: ["kilowatt"],
|
||||||
|
human: {
|
||||||
|
en: "kilowatt",
|
||||||
|
nl: "kilowatt"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
canonicalDenomination: 'mW',
|
||||||
|
alternativeDenomination: ["megawatt"],
|
||||||
|
human: {
|
||||||
|
en: "megawatt",
|
||||||
|
nl: "megawatt"
|
||||||
|
}
|
||||||
|
}],
|
||||||
|
eraseInvalidValues: true
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
writeFileSync("charging_station.json", JSON.stringify(proto, undefined, " "))
|
writeFileSync("charging_station.json", JSON.stringify(proto, undefined, " "))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async function queryTagInfo(file, type, clean: ((s: string) => string)) {
|
||||||
|
for (const e of loadCsv(file)) {
|
||||||
|
const value = await ScriptUtils.TagInfoHistogram(e.key + ":" + type)
|
||||||
|
const result = value.data
|
||||||
|
const counts = new Map<string, number>()
|
||||||
|
// console.log(result)
|
||||||
|
for (const r of result) {
|
||||||
|
let key = r.value;
|
||||||
|
key = clean(key)
|
||||||
|
key.trim();
|
||||||
|
if (key.indexOf('-') >= 0) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if (r.fraction < 0.05) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if (counts.has(key)) {
|
||||||
|
counts.set(key, counts.get(key) + r.count)
|
||||||
|
} else {
|
||||||
|
counts.set(key, r.count)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const countsArray = Array.from(counts.keys())
|
||||||
|
countsArray.sort()
|
||||||
|
// console.log(`${e.key}:${type} = ${countsArray.join(";")}`)
|
||||||
|
console.log(`${countsArray.join(";")}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
run("types.csv", "charging_station.protojson")
|
run("types.csv", "charging_station.protojson")
|
||||||
|
// queryTagInfo("types.csv","voltage", true)
|
||||||
|
// queryTagInfo("types.csv", "current", true)
|
||||||
|
/* queryTagInfo("types.csv", "output", s => {
|
||||||
|
if(s.endsWith("kW")){
|
||||||
|
s = s.substring(0, s.length - 2)
|
||||||
|
}
|
||||||
|
s = s.trim()
|
||||||
|
return s + " kW"
|
||||||
|
})*/
|
||||||
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e)
|
console.error(e)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
Key in OSM,image,Description,Country-whitelist,,,,,,,
|
key,image,description:en,countryWhitelist,commonVoltages,commonCurrents,commonOutputs,description:nl
|
||||||
socket:schuko,CEE7_4F.svg,<b>Schuko wall plug</b> without ground pin (CEE7/4 type F),"be,fr,ma,tn,pl,cs,sk,mo"
|
socket:schuko,CEE7_4F.svg,<b>Schuko wall plug</b> without ground pin (CEE7/4 type F),be;fr;ma;tn;pl;cs;sk;mo,230,16,3.6 kW,<b>Schuko stekker</b> zonder aardingspin (CEE7/4 type F)
|
||||||
socket:typee,TypeE.svg,<b>European wall plug</b> with ground pin (CEE7/4 type E),,,,,,,,
|
socket:typee,TypeE.svg,<b>European wall plug</b> with ground pin (CEE7/4 type E),,230,16,3 kW;22 kW;,<b>Europese stekker</b> met aardingspin (CEE7/4 type E)
|
||||||
socket:chademo,Chademo_type4.svg,<b>Chademo</b>,,,,,,,,
|
socket:chademo,Chademo_type4.svg,<b>Chademo</b>,,500,120,50 kW,
|
||||||
socket:type1_cable,Type1_J1772.svg,<b>Type 1 with cable</b> (J1772),,,,,,,,
|
socket:type1_cable,Type1_J1772.svg,<b>Type 1 with cable</b> (J1772),,200;240,32,3.7 kW;7 kW,<b>Type 1 met kabel</b> (J1772)
|
||||||
socket:type1,Type1_J1772.svg,<b>Type 1 <i>without</i> cable</b> (J1772),,,,,,,,
|
socket:type1,Type1_J1772.svg,<b>Type 1 <i>without</i> cable</b> (J1772),,200;240,32,3.7 kW;6.6 kW;7 kW;7.2 kW,<b>Type 1 <i>zonder</i> kabel</b> (J1772)
|
||||||
socket:type1_combo,Type1-ccs.svg,<b>Type 1 CCS</b> (aka Type 1 Combo),,,,,,,,
|
socket:type1_combo,Type1-ccs.svg,<b>Type 1 CCS</b> (aka Type 1 Combo),,400;1000,50;125,50 kW;62.5 kW;150 kW;350 kW;,
|
||||||
socket:tesla_supercharger,Tesla-hpwc-model-s.svg,<b>Tesla Supercharger</b>,,,,,,,,
|
socket:tesla_supercharger,Tesla-hpwc-model-s.svg,<b>Tesla Supercharger</b>,,480,125;350,120 kW;150 kW;250 kW,
|
||||||
socket:type2,Type2_socket.svg,<b>Type 2</b> (mennekes),,,,,,,,
|
socket:type2,Type2_socket.svg,<b>Type 2</b> (mennekes),,230;400,16;32,11 kW;22 kW,
|
||||||
socket:type2_combo,Type2_CCS.svg,<b>Type 2 CCS</b> (mennekes),,,,,,,,
|
socket:type2_combo,Type2_CCS.svg,<b>Type 2 CCS</b> (mennekes),,500;920,125;350,50 kW,
|
||||||
|
|
Can't render this file because it has a wrong number of fields in line 2.
|
Loading…
Add table
Add a link
Reference in a new issue