meta { title: "Dutch specific rules"; version: "2024.11.08"; description: "Rules for The Netherlands only (European part)."; author: "Famlam"; min-josm-version: "15317"; /* due to tag_regex() usage */ link: "https://github.com/Famlam/OsmMapcssValidationNL"; icon: "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' id='flag-icons-nl' viewBox='0 0 640 480'%3E%3Cpath fill='%2321468b' d='M0 0h640v480H0z'/%3E%3Cpath fill='%23fff' d='M0 0h640v320H0z'/%3E%3Cpath fill='%23ae1c28' d='M0 0h640v160H0z'/%3E%3C/svg%3E%0A"; } /* github: https://github.com/Famlam/OsmMapcssValidationNL forum: https://community.openstreetmap.org/t/mapcss-regels-voor-nederland-josm-validator/95079 */ /* --------------------------- */ /* ------ Traffic signs ------ */ /* --------------------------- */ /* Traffic signs - moped/mofa access cycleways */ /* (Permitting yes rather than designated to prevent overflooding with errors) */ way[highway=cycleway][traffic_sign~="NL:G11"][moped][moped=~/^(yes|designated)$/], way[highway=cycleway][traffic_sign~="NL:G12a"][moped][moped=~/^(no|use_sidepath)$/], way[highway=cycleway][traffic_sign~="NL:G12a"][mofa][mofa=~/^(no|use_sidepath)$/], way[highway=cycleway][traffic_sign~="NL:G13"][moped][moped=~/^(yes|designated)$/], way[highway=cycleway][traffic_sign~="NL:G13"][mofa][mofa=~/^(yes|designated)$/], way[highway][traffic_sign~="NL:D103"][moped][moped=~/^(no|use_sidepath)$/][highway!=construction], way[highway][traffic_sign~="NL:D104"][moped][moped=~/^(no|use_sidepath)$/][highway!=construction] { group: tr("NL traffic signs"); throwWarning: tr("{0} together with {1}", "{1.tag}", "{2.tag}"); } way[highway][traffic_sign~="NL:D103"][!moped], way[highway][traffic_sign~="NL:D104"][!moped], way[highway=cycleway][traffic_sign~="NL:G12a"][!moped] { group: tr("NL traffic signs"); throwWarning: tr("{0} without {1}", "{1.tag}", "moped=designated"); } /* note: mind the Amsterdam-case: snorfietsers op de weg */ way[highway=cycleway][traffic_sign~="NL:G11"][!mofa] { group: tr("NL traffic signs"); throwOther: tr("{0} without {1}", "{1.tag}", "{2.key}"); } way[highway=cycleway][traffic_sign~="NL:G12a"][!mofa] { group: tr("NL traffic signs"); throwWarning: tr("{0} without {1}", "{1.tag}", "{2.key}"); } way[highway=cycleway][traffic_sign~="NL:G13"][!mofa][!motor_vehicle][!access] { group: tr("NL traffic signs"); throwWarning: tr("{0} without {1}", "{1.tag}", "mofa=no"); } /* Traffic signs - bus/hgv access */ way[highway][traffic_sign~="NL:F13"][!bus][!psv][highway!=busway][highway!=bus_guideway], way[highway][traffic_sign~="NL:F17"][!bus][!psv][highway!=busway][highway!=bus_guideway], way[highway][traffic_sign~="NL:F19"][!bus][!psv][highway!=busway][highway!=bus_guideway], way[highway][traffic_sign~="NL:F19"][!hgv], way[highway][traffic_sign~="NL:F21"][!hgv] { group: tr("NL traffic signs"); throwWarning: tr("{0} without {1}", "{1.tag}", "{2.key}=designated"); fixAdd: "{2.key}=designated"; } way[highway][traffic_sign~="NL:F13"][bus=no][highway!=construction], way[highway][traffic_sign~="NL:F17"][bus=no][highway!=construction], way[highway][traffic_sign~="NL:F19"][bus=no][highway!=construction], way[highway][traffic_sign~="NL:F13"][psv=no][!bus][highway!=construction], way[highway][traffic_sign~="NL:F17"][psv=no][!bus][highway!=construction], way[highway][traffic_sign~="NL:F19"][psv=no][!bus][highway!=construction], way[highway][traffic_sign~="NL:F19"][hgv=no][highway!=construction], way[highway][traffic_sign~="NL:F21"][hgv=no][highway!=construction] { group: tr("NL traffic signs"); throwWarning: tr("{0} together with {1}", "{1.tag}", "{2.tag}"); } /* Traffic sign - road types */ way[highway=steps][traffic_sign=~/(^|; ?)NL:L301\b/] { set .markedSteps; } way[highway=steps][ramp=yes], way[highway=steps][ramp:bicycle=yes] { set .stepsWithBicycleRamp; } way[highway][traffic_sign*="NL:G"][count(split(";NL:G", concat(";", replace(tag("traffic_sign"), " ", "")))) > 2] { /* 0 matches: count(split(...))=1; 1 match: count(split(...))=2; etc */ set multipleGsigns; } way[living_street=yes][highway][highway!~/^(residential|unclassified|tertiary|secondary|primary|trunk|motorway|busway)(_link)?$/] { set .altLivingStreet; } way[highway][traffic_sign~="NL:F13"][highway!=busway][highway!=service][highway!=bus_guideway][highway!=construction], way[highway][traffic_sign~="NL:G5"][highway!=living_street][highway!=construction][highway!=path][highway!=cycleway][highway!=pedestrian][highway!=bridleway][highway!=steps]!.altLivingStreet, way[highway][traffic_sign~="NL:G05"][highway!=living_street][highway!=construction][highway!=path][highway!=cycleway][highway!=pedestrian][highway!=bridleway][highway!=steps]!.altLivingStreet, way[highway][traffic_sign~="NL:G7"][highway!=footway][highway!=steps][highway!=pedestrian][highway!=construction]!.multipleGsigns, way[highway][traffic_sign~="NL:G07"][highway!=footway][highway!=steps][highway!=pedestrian][highway!=construction]!.multipleGsigns, way[highway][traffic_sign~="NL:G7-ZB"][highway!=footway][highway!=steps][highway!=pedestrian][highway!=construction]!.multipleGsigns, way[highway][traffic_sign~="NL:G07-ZB"][highway!=footway][highway!=steps][highway!=pedestrian][highway!=construction]!.multipleGsigns, way[highway][traffic_sign~="NL:G9"][highway!=bridleway][highway!=construction]!.multipleGsigns!.markedSteps, way[highway][traffic_sign~="NL:G09"][highway!=bridleway][highway!=construction]!.multipleGsigns!.markedSteps, way[highway][traffic_sign~="NL:G11"][highway!=cycleway][highway!=construction]!.multipleGsigns!.markedSteps!.stepsWithBicycleRamp, way[highway][traffic_sign~="NL:G12a"][highway!=cycleway][highway!=construction]!.multipleGsigns!.markedSteps, way[highway][traffic_sign~="NL:G13"][highway!=cycleway][highway!=construction]!.multipleGsigns!.markedSteps!.stepsWithBicycleRamp, way[highway][traffic_sign*="NL:L301"][highway!=steps][highway!=construction][traffic_sign=~/(^|; ?)NL:L301\b/] { group: tr("NL traffic signs"); throwWarning: tr("{0} together with {1}", "{1.tag}", "{0.tag}"); assertMatch: "way highway=cycleway traffic_sign=NL:G7"; assertMatch: "way highway=cycleway traffic_sign=NL:G7;OB109"; assertMatch: "way highway=cycleway traffic_sign=NL:J1;NL:G7;OB109"; assertMatch: "way highway=cycleway traffic_sign=NL:J1;NL:G7"; assertMatch: "way highway=cycleway traffic_sign=NL:L301"; assertMatch: "way highway=cycleway traffic_sign=NL:G13;NL:L301-A"; assertMatch: "way highway=cycleway traffic_sign=\"NL:G13; NL:L301-A\""; assertMatch: "way highway=residential traffic_sign=NL:G5 living_street=yes"; assertMatch: "way highway=service traffic_sign=NL:G5"; assertNoMatch: "way highway=cycleway traffic_sign=NL:G13"; assertNoMatch: "way highway=cycleway traffic_sign=NL:G11;NL:G07"; assertNoMatch: "way highway=cycleway traffic_sign=NL:G11;OB109;NL:G07"; assertNoMatch: "way highway=cycleway traffic_sign=NL:G11;NL:G07;OB109"; assertNoMatch: "way highway=cycleway traffic_sign=NL:J1;NL:G11;OB109;NL:G07"; assertNoMatch: "way highway=cycleway traffic_sign=\"NL:J1; NL:G11; NL:G07; OB109\""; assertNoMatch: "way highway=residential traffic_sign=NL:G12;NL:G10"; assertNoMatch: "way highway=steps traffic_sign=NL:G13;NL:L301-B"; assertNoMatch: "way highway=steps traffic_sign=\"NL:G13; NL:L301-B\""; assertNoMatch: "way highway=steps traffic_sign=NL:G13 ramp:bicycle=yes"; assertNoMatch: "way highway=service traffic_sign=NL:G5 living_street=yes"; } /* Smaller highways with G5 signs without living_street tagging */ /* Restricted to moped-accessible paths, to avoid warning on all paths where you'll only find vehicles/horses without speed indicator */ way[highway][traffic_sign~="NL:G5"][highway=~/^(path|cycleway|pedestrian|bridleway|steps)$/][moped][moped!~/^(no|use_sidepath)$/]!.altLivingStreet, way[highway][traffic_sign~="NL:G05"][highway=~/^(path|cycleway|pedestrian|bridleway|steps)$/][moped][moped!~/^(no|use_sidepath)$/]!.altLivingStreet { group: tr("NL traffic signs"); throwWarning: tr("{0} together with {1} but without {2}", "{1.tag}", "{0.tag}", "living_street=yes"); assertNoMatch: "way highway=living_street traffic_sign=NL:G05 moped=yes"; assertNoMatch: "way highway=cycleway traffic_sign=NL:G05 living_street=yes moped=designated"; assertNoMatch: "way highway=cycleway traffic_sign=NL:G05 moped=use_sidepath"; } way[highway][traffic_sign~="NL:L51"][!cyclestreet][highway!=construction] { group: tr("NL traffic signs"); throwWarning: tr("{0} without {1}", "{1.tag}", "cyclestreet=yes"); } /* Traffic signs - access prohibited */ way[highway][traffic_sign~="NL:C1"][!vehicle][!/^(access|vehicle|motor_vehicle)(:forward|:backward|:both_ways)?(:conditional)?$/][highway!=construction], way[highway][traffic_sign:forward~="NL:C1"][!vehicle:forward][!/^(access|vehicle|motor_vehicle)(:forward|:both_ways)?(:conditional)?$/][highway!=construction], way[highway][traffic_sign:backward~="NL:C1"][!vehicle:backward][!/^(access|vehicle|motor_vehicle)(:backward|:both_ways)?(:conditional)?$/][highway!=construction][oneway!=yes], way[highway][traffic_sign~="NL:C01"][!vehicle][!/^(access|vehicle|motor_vehicle)(:forward|:backward|:both_ways)?(:conditional)?$/][highway!=construction], way[highway][traffic_sign:forward~="NL:C01"][!vehicle:forward][!/^(access|vehicle|motor_vehicle)(:forward|:both_ways)?(:conditional)?$/][highway!=construction], way[highway][traffic_sign:backward~="NL:C01"][!vehicle:backward][!/^(access|vehicle|motor_vehicle)(:backward|:both_ways)?(:conditional)?$/][highway!=construction][oneway!=yes], way[highway][traffic_sign~="NL:C6"][!motor_vehicle][!/^(access|vehicle|motor_vehicle)(:forward|:backward|:both_ways)?(:conditional)?$/][highway!=construction], way[highway][traffic_sign:forward~="NL:C6"][!motor_vehicle:forward][!/^(access|vehicle|motor_vehicle)(:forward|:both_ways)?(:conditional)?$/][highway!=construction], way[highway][traffic_sign:backward~="NL:C6"][!motor_vehicle:backward][!/^(access|vehicle|motor_vehicle)(:backward|:both_ways)?(:conditional)?$/][highway!=construction][oneway!=yes][oneway:motor_vehicle!=yes], way[highway][traffic_sign~="NL:C06"][!motor_vehicle][!/^(access|vehicle|motor_vehicle)(:forward|:backward|:both_ways)?(:conditional)?$/][highway!=construction], way[highway][traffic_sign:forward~="NL:C06"][!motor_vehicle:forward][!/^(access|vehicle|motor_vehicle)(:forward|:both_ways)?(:conditional)?$/][highway!=construction], way[highway][traffic_sign:backward~="NL:C06"][!motor_vehicle:backward][!/^(access|vehicle|motor_vehicle)(:backward|:both_ways)?(:conditional)?$/][highway!=construction][oneway!=yes][oneway:motor_vehicle!=yes], way[highway][traffic_sign~="NL:C7"][!hgv][!/^hgv(:forward|:backward|:both_ways)?(:conditional)?$/][highway!=construction], way[highway][traffic_sign:forward~="NL:C7"][!hgv:forward][!/^hgv(:forward|:both_ways)?(:conditional)?$/][highway!=construction], way[highway][traffic_sign:backward~="NL:C7"][!hgv:backward][!/^hgv(:backward|:both_ways)?(:conditional)?$/][highway!=construction][oneway:hgv!=yes], way[highway][traffic_sign~="NL:C07"][!hgv][!/^hgv(:forward|:backward|:both_ways)?(:conditional)?$/][highway!=construction], way[highway][traffic_sign:forward~="NL:C07"][!hgv:forward][!/^hgv(:forward|:both_ways)?(:conditional)?$/][highway!=construction], way[highway][traffic_sign:backward~="NL:C07"][!hgv:backward][!/^hgv(:backward|:both_ways)?(:conditional)?$/][highway!=construction][oneway:hgv!=yes], way[highway][traffic_sign~="NL:C9"][!bicycle][!/^bicycle(:forward|:backward|:both_ways)?(:conditional)?$/][highway!=construction], way[highway][traffic_sign:forward~="NL:C9"][!bicycle:forward][!/^bicycle(:forward|:both_ways)?(:conditional)?$/][highway!=construction], way[highway][traffic_sign:backward~="NL:C9"][!bicycle:backward][!/^bicycle(:backward|:both_ways)?(:conditional)?$/][highway!=construction][oneway:bicycle!=yes], way[highway][traffic_sign~="NL:C9"][!moped][!/^moped(:forward|:backward|:both_ways)?(:conditional)?$/][highway!=construction], way[highway][traffic_sign:forward~="NL:C9"][!moped:forward][!/^moped(:forward|:both_ways)?(:conditional)?$/][highway!=construction], way[highway][traffic_sign:backward~="NL:C9"][!moped:backward][!/^moped(:backward|:both_ways)?(:conditional)?$/][highway!=construction][oneway:moped!=yes], way[highway][traffic_sign~="NL:C09"][!bicycle][!/^bicycle(:forward|:backward|:both_ways)?(:conditional)?$/][highway!=construction], way[highway][traffic_sign:forward~="NL:C09"][!bicycle:forward][!/^bicycle(:forward|:both_ways)?(:conditional)?$/][highway!=construction], way[highway][traffic_sign:backward~="NL:C09"][!bicycle:backward][!/^bicycle(:backward|:both_ways)?(:conditional)?$/][highway!=construction][oneway:bicycle!=yes], way[highway][traffic_sign~="NL:C09"][!moped][!/^moped(:forward|:backward|:both_ways)?(:conditional)?$/][highway!=construction], way[highway][traffic_sign:forward~="NL:C09"][!moped:forward][!/^moped(:forward|:both_ways)?(:conditional)?$/][highway!=construction], way[highway][traffic_sign:backward~="NL:C09"][!moped:backward][!/^moped(:backward|:both_ways)?(:conditional)?$/][highway!=construction][oneway:moped!=yes], way[highway][traffic_sign~="NL:C10"][!trailer][!/^trailer(:forward|:backward|:both_ways)?(:conditional)?$/][highway!=construction], way[highway][traffic_sign:forward~="NL:C10"][!trailer:forward][!/^trailer(:forward|:both_ways)?(:conditional)?$/][highway!=construction], way[highway][traffic_sign:backward~="NL:C10"][!trailer:backward][!/^trailer(:backward|:both_ways)?(:conditional)?$/][highway!=construction][oneway:trailer!=yes], way[highway][traffic_sign~="NL:C11"][!motorcycle][!/^motorcycle(:forward|:backward|:both_ways)?(:conditional)?$/][highway!=construction], way[highway][traffic_sign:forward~="NL:C11"][!motorcycle:forward][!/^motorcycle(:forward|:both_ways)?(:conditional)?$/][highway!=construction], way[highway][traffic_sign:backward~="NL:C11"][!motorcycle:backward][!/^motorcycle(:backward|:both_ways)?(:conditional)?$/][highway!=construction][oneway:motorcycle!=yes], way[highway][traffic_sign~="NL:C12"][!motor_vehicle][!/^(access|vehicle|motor_vehicle)(:forward|:backward|:both_ways)?(:conditional)?$/][highway!=construction], way[highway][traffic_sign:forward~="NL:C12"][!motor_vehicle:forward][!/^(access|vehicle|motor_vehicle)(:forward|:both_ways)?(:conditional)?$/][highway!=construction], way[highway][traffic_sign:backward~="NL:C12"][!motor_vehicle:backward][!/^(access|vehicle|motor_vehicle)(:backward|:both_ways)?(:conditional)?$/][highway!=construction][oneway!=yes][oneway:motor_vehicle!=yes], way[highway][traffic_sign~="NL:C13"][!moped][!/^moped(:forward|:backward|:both_ways)?(:conditional)?$/][highway!=construction][highway!=footway], way[highway][traffic_sign:forward~="NL:C13"][!moped:forward][!/^moped(:forward|:both_ways)?(:conditional)?$/][highway!=construction][highway!=footway], way[highway][traffic_sign:backward~="NL:C13"][!moped:backward][!/^moped(:backward|:both_ways)?(:conditional)?$/][highway!=construction][oneway:moped!=yes][highway!=footway], way[highway][traffic_sign~="NL:C14"][!bicycle][!/^bicycle(:forward|:backward|:both_ways)?(:conditional)?$/][highway!=construction][highway!=footway], way[highway][traffic_sign:forward~="NL:C14"][!bicycle:forward][!/^bicycle(:forward|:both_ways)?(:conditional)?$/][highway!=construction][highway!=footway], way[highway][traffic_sign:backward~="NL:C14"][!bicycle:backward][!/^bicycle(:backward|:both_ways)?(:conditional)?$/][highway!=construction][oneway:bicycle!=yes][highway!=footway], way[highway][traffic_sign~="NL:C15"][!bicycle][!/^bicycle(:forward|:backward|:both_ways)?(:conditional)?$/][highway!=construction][highway!=footway], way[highway][traffic_sign:forward~="NL:C15"][!bicycle:forward][!/^bicycle(:forward|:both_ways)?(:conditional)?$/][highway!=construction][highway!=footway], way[highway][traffic_sign:backward~="NL:C15"][!bicycle:backward][!/^bicycle(:backward|:both_ways)?(:conditional)?$/][highway!=construction][oneway:bicycle!=yes][highway!=footway], way[highway][traffic_sign~="NL:C15"][!moped][!/^moped(:forward|:backward|:both_ways)?(:conditional)?$/][highway!=construction][highway!=footway], way[highway][traffic_sign:forward~="NL:C15"][!moped:forward][!/^moped(:forward|:both_ways)?(:conditional)?$/][highway!=construction][highway!=footway], way[highway][traffic_sign:backward~="NL:C15"][!moped:backward][!/^moped(:backward|:both_ways)?(:conditional)?$/][highway!=construction][oneway:moped!=yes][highway!=footway], way[highway][traffic_sign~="NL:C16"][!foot][!/^foot(:forward|:backward|:both_ways)?(:conditional)?$/][!/^access(:forward|:backward|:both_ways)?(:conditional)?$/][highway!=construction], way[highway][traffic_sign:forward~="NL:C16"][!foot:forward][!/^foot(:forward|:both_ways)?(:conditional)?$/][!/^access(:forward|:both_ways)?(:conditional)?$/][highway!=construction], way[highway][traffic_sign:backward~="NL:C16"][!foot:backward][!/^foot(:backward|:both_ways)?(:conditional)?$/][!/^access(:backward|:both_ways)?(:conditional)?$/][highway!=construction][oneway:foot!=yes] { group: tr("NL traffic signs"); throwWarning: tr("{0} without {1}", "{1.tag}", "{2.key}=no/private/destination/..."); assertMatch: "way highway=service traffic_sign=\"NL:C01\""; assertMatch: "way highway=service traffic_sign:forward=\"NL:C9;NL:OB58\""; assertMatch: "way highway=service traffic_sign:forward=\"NL:C9;NL:OB58\" traffic_sign:backward=\"NL:C1\" access:backward=no"; assertMatch: "way highway=service traffic_sign:backward=\"NL:C14\" oneway=yes oneway:bicycle=no"; assertNoMatch: "way highway=service traffic_sign:backward=\"NL:C14\" oneway=yes oneway:bicycle=no bicycle:backward=destination"; assertNoMatch: "way highway=service traffic_sign:backward=\"NL:C14\" oneway:bicycle=yes"; assertNoMatch: "way highway=service traffic_sign=\"NL:C01;NL:C16\" access=no"; assertNoMatch: "way highway=service traffic_sign=\"NL:C01;NL:OB51;NL:OB54\" motor_vehicle=no"; assertNoMatch: "way highway=service traffic_sign:backward=\"NL:C07;NL:C16\" hgv=no foot=no"; assertNoMatch: "way highway=service traffic_sign:backward=\"NL:C07;NL:C16\" hgv:backward=no foot=no"; assertNoMatch: "way highway=track traffic_sign=\"NL:C12\" motor_vehicle=no"; assertNoMatch: "way highway=track traffic_sign:backward=\"NL:C12\" oneway=yes oneway:bicycle=no"; } way[traffic_sign][traffic_sign=~/(^|; ?)NL:C22(\[[A-E]\])?(;|$)/][!/^hazmat(:[A-E])?(:forward|:backward|:both_ways)?(:conditional)?$/][!/^(access|vehicle|motor_vehicle)(:forward|:backward|:both_ways)?(:conditional)?$/][highway!=construction][highway], way[traffic_sign:forward][traffic_sign:forward=~/(^|; ?)NL:C22(\[[A-E]\])?(;|$)/][!/^hazmat(:[A-E])?(:forward|:both_ways)?(:conditional)?$/][!/^(access|vehicle|motor_vehicle)(:forward|:both_ways)?(:conditional)?$/][highway!=construction][highway], way[traffic_sign:backward][traffic_sign:backward=~/(^|; ?)NL:C22(\[[A-E]\])?(;|$)/][!/^hazmat(:[A-E])?(:backward|:both_ways)?(:conditional)?$/][!/^(access|vehicle|motor_vehicle)(:backward|:both_ways)?(:conditional)?$/][highway!=construction][highway][/^oneway:hazmat/!~/^yes$/] { group: tr("NL traffic signs"); throwWarning: tr("{0} without {1} or {2}", "{0.tag}", "hazmat=no/private/destination/...", "hazmat:A-E=no/private/destination/..."); assertMatch: "way highway=service traffic_sign=\"NL:C22\""; assertMatch: "way highway=service traffic_sign:forward=\"NL:C16; NL:C22[A]; NL:OB58\""; assertMatch: "way highway=service traffic_sign:forward=\"NL:C22[A];NL:OB58\""; assertMatch: "way highway=service traffic_sign:backward=\"NL:C22[A]\" oneway=yes oneway:hazmat=no"; assertNoMatch: "way highway=service traffic_sign=\"NL:C22\" access=no"; assertNoMatch: "way highway=service traffic_sign=\"NL:C22a\""; assertNoMatch: "way highway=service traffic_sign=\"NL:C22\" hazmat=no"; assertNoMatch: "way highway=service traffic_sign:backward=\"NL:C22[A]\" hazmat:A:backward=no"; assertNoMatch: "way highway=service traffic_sign:backward=\"NL:C22[A]\" oneway:hazmat=yes"; assertNoMatch: "way highway=service traffic_sign:backward=\"NL:C22[C]\" oneway:hazmat:C=yes"; } /* Voertuiglimieten */ way[traffic_sign][traffic_sign=~/(^|; ?)NL:C17\b/][!maxlength][!/^maxlength(:forward|:backward|:both_ways)?(:conditional)?$/][highway], way[traffic_sign:forward][traffic_sign:forward=~/(^|; ?)NL:C17\b/][!maxlength:forward][!/^maxlength(:forward|:both_ways)?(:conditional)?$/][highway], way[traffic_sign:backward][traffic_sign:backward=~/(^|; ?)NL:C17\b/][!maxlength:backward][!/^maxlength(:backward|:both_ways)?(:conditional)?$/][highway], way[traffic_sign][traffic_sign=~/(^|; ?)NL:C18\b/][!maxwidth][!/^maxwidth(:forward|:backward|:both_ways)?(:conditional)?$/][highway], way[traffic_sign:forward][traffic_sign:forward=~/(^|; ?)NL:C18\b/][!maxwidth:forward][!/^maxwidth(:forward|:both_ways)?(:conditional)?$/][highway], way[traffic_sign:backward][traffic_sign:backward=~/(^|; ?)NL:C18\b/][!maxwidth:backward][!/^maxwidth(:backward|:both_ways)?(:conditional)?$/][highway], way[traffic_sign][traffic_sign=~/(^|; ?)NL:(C19|L0?1)\b/][!maxheight][!/^maxheight(:forward|:backward|:both_ways)?(:conditional)?$/][highway], way[traffic_sign:forward][traffic_sign:forward=~/(^|; ?)NL:(C19|L0?1)\b/][!maxheight:forward][!/^maxheight(:forward|:both_ways)?(:conditional)?$/][highway], way[traffic_sign:backward][traffic_sign:backward=~/(^|; ?)NL:(C19|L0?1)\b/][!maxheight:backward][!/^maxheight(:backward|:both_ways)?(:conditional)?$/][highway], way[traffic_sign][traffic_sign=~/(^|; ?)NL:C20\b/][!maxaxleload][!/^maxaxleload(:forward|:backward|:both_ways)?(:conditional)?$/][highway], way[traffic_sign:forward][traffic_sign:forward=~/(^|; ?)NL:C20\b/][!maxaxleload:forward][!/^maxaxleload(:forward|:both_ways)?(:conditional)?$/][highway], way[traffic_sign:backward][traffic_sign:backward=~/(^|; ?)NL:C20\b/][!maxaxleload:backward][!/^maxaxleload(:backward|:both_ways)?(:conditional)?$/][highway], way[traffic_sign][traffic_sign=~/(^|; ?)NL:C21\b/][!maxweight][!/^maxweight(:forward|:backward|:both_ways)?(:conditional)?$/][highway], way[traffic_sign:forward][traffic_sign:forward=~/(^|; ?)NL:C21\b/][!maxweight:forward][!/^maxweight(:forward|:both_ways)?(:conditional)?$/][highway], way[traffic_sign:backward][traffic_sign:backward=~/(^|; ?)NL:C21\b/][!maxweight:backward][!/^maxweight(:backward|:both_ways)?(:conditional)?$/][highway] { group: tr("NL traffic signs"); throwWarning: tr("{0} without {1}", "{0.tag}", "{2.key}"); assertMatch: "way highway=residential traffic_sign:forward=\"NL:C19[2.1]\""; assertMatch: "way highway=residential traffic_sign:forward=\"NL:J19;NL:L01[4.1];NL:OB108\""; assertMatch: "way highway=residential traffic_sign:forward=\"NL:J19; NL:L01[4.1]; NL:OB108\""; assertMatch: "way highway=residential traffic_sign=\"NL:C21[2.1]\""; assertMatch: "way highway=residential traffic_sign:forward=\"NL:C21[2.1]\""; assertNoMatch: "way highway=residential traffic_sign=\"NL:J19;NL:C21[2.1];NL:OB108\" maxweight:conditional=xxx"; assertNoMatch: "way highway=residential traffic_sign=\"NL:C19[2.1]\" maxheight=2.1"; assertNoMatch: "way highway=residential traffic_sign:backward=\"NL:C21[2.1]\" maxweight:backward=2.1"; } /* Eenrichtingsverkeer */ way[highway][traffic_sign~="NL:C2"][oneway!=yes][regexp_test("^(no|0)*$", join_list("", tag_regex("^oneway:")))][oneway!=-1][highway!=construction], way[highway][traffic_sign~="NL:C02"][oneway!=yes][regexp_test("^(no|0)*$", join_list("", tag_regex("^oneway:")))][oneway!=-1][highway!=construction], way[highway][traffic_sign~="NL:C3"][oneway!=yes][regexp_test("^(no|0)*$", join_list("", tag_regex("^oneway:")))][oneway!=-1][highway!=construction], way[highway][traffic_sign~="NL:C03"][oneway!=yes][regexp_test("^(no|0)*$", join_list("", tag_regex("^oneway:")))][oneway!=-1][highway!=construction], way[highway][traffic_sign:forward~="NL:C3"][oneway!=yes][regexp_test("^(no|-1|0)*$", join_list("", tag_regex("^oneway:")))][highway!=construction][traffic_sign:backward!~/\bNL:C0?2\b/], way[highway][traffic_sign:forward~="NL:C03"][oneway!=yes][regexp_test("^(no|-1|0)*$", join_list("", tag_regex("^oneway:")))][highway!=construction][traffic_sign:backward!~/\bNL:C0?2\b/], way[highway][traffic_sign:backward~="NL:C2"][oneway!=yes][regexp_test("^(no|-1|0)*$", join_list("", tag_regex("^oneway:")))][highway!=construction], way[highway][traffic_sign:backward~="NL:C02"][oneway!=yes][regexp_test("^(no|-1|0)*$", join_list("", tag_regex("^oneway:")))][highway!=construction] { group: tr("NL traffic signs"); throwWarning: tr("{0} without {1}", "{1.tag}", "{2.tag}"); assertMatch: "way highway=residential traffic_sign=\"NL:C02\""; assertMatch: "way highway=residential traffic_sign=\"NL:C02\" oneway:bicycle=no oneway=no"; assertMatch: "way highway=residential traffic_sign:forward=\"NL:C3\""; assertMatch: "way highway=residential traffic_sign:forward=\"NL:C3\" oneway=-1"; assertMatch: "way highway=residential traffic_sign=\"NL:C3;NL:OB58\""; assertMatch: "way highway=residential traffic_sign:backward=\"NL:C02;NL:OB58\""; assertMatch: "way highway=residential traffic_sign:forward=\"NL:C3\" oneway:motor_vehicle=-1"; assertNoMatch: "way highway=residential traffic_sign=\"NL:C02;NL:OB58\" oneway=yes"; assertNoMatch: "way highway=residential traffic_sign=\"NL:C02;NL:OB58\" oneway=-1"; assertNoMatch: "way highway=residential traffic_sign=\"NL:C3\" oneway:motor_vehicle=yes"; assertNoMatch: "way highway=residential traffic_sign:forward=\"NL:C3\" oneway:motor_vehicle=yes"; assertNoMatch: "way highway=residential traffic_sign:forward=\"NL:C3\" oneway=yes"; assertNoMatch: "way highway=residential traffic_sign=\"NL:C3\" oneway:motor_vehicle=-1"; assertNoMatch: "way highway=residential traffic_sign:backward=\"NL:C2\" oneway=yes oneway:bicycle=no"; assertNoMatch: "way highway=residential traffic_sign:backward=\"NL:C2\" oneway:motor_vehicle=yes"; assertNoMatch: "way highway=residential traffic_sign=\"NL:C3\" oneway:agricultural=no oneway:motor_vehicle=yes oneway:motorcycle=no oneway=no"; } way[highway][traffic_sign~="NL:C5"][oneway?][highway!=construction], way[highway][traffic_sign~="NL:C05"][oneway?][highway!=construction] { group: tr("NL traffic signs"); throwWarning: tr("{0} together with {1}", "{1.tag}", "{2.tag}"); suggestAlternative: "oneway=no"; assertMatch: "way highway=residential traffic_sign=\"NL:C05\" oneway=yes"; assertNoMatch: "way highway=residential traffic_sign=\"NL:C5;NL:OB58\" oneway=no"; assertNoMatch: "way highway=residential traffic_sign=\"NL:C05\""; } /* Rotondes en verkeerspleinen met verplichte rijrichting */ way[highway][traffic_sign~="NL:D1"][junction!=roundabout][junction!=circular], way[highway][traffic_sign~="NL:D01"][junction!=roundabout][junction!=circular] { group: tr("NL traffic signs"); throwWarning: tr("{0} without {1} or {2}", "{1.tag}", "{2.tag}", "{3.tag}"); assertMatch: "way highway=residential traffic_sign=NL:D1 oneway=yes"; assertNoMatch: "way highway=residential traffic_sign=NL:D1 junction=circular"; assertNoMatch: "way highway=residential traffic_sign=NL:D1 junction=roundabout"; } way[highway][traffic_sign~="NL:D1"][junction=circular][oneway!~/^(yes|-?1)$/], way[highway][traffic_sign~="NL:D01"][junction=circular][oneway!~/^(yes|-?1)$/] { group: tr("NL traffic signs"); throwWarning: tr("{0} together with {1} but without {2}", "{2.tag}", "{1.tag}", "oneway=yes"); assertMatch: "way highway=residential traffic_sign=NL:D1 oneway=no junction=circular"; assertMatch: "way highway=residential traffic_sign=NL:D1 junction=circular"; assertNoMatch: "way highway=residential traffic_sign=NL:D1 junction=circular oneway=yes"; assertNoMatch: "way highway=residential traffic_sign=NL:D1 junction=circular oneway=-1"; } /* Voorrangsborden bij kruising */ way[highway] > node[traffic_sign~="NL:B7"][highway!=stop], way[highway] > node[traffic_sign~="NL:B07"][highway!=stop], way[highway] > node[traffic_sign~="NL:B6"][highway!=give_way], way[highway] > node[traffic_sign~="NL:B06"][highway!=give_way] { group: tr("NL traffic signs"); throwWarning: tr("{0} without {1}", "{0.tag}", "{1.tag}"); fixAdd: "{1.tag}"; } /* Voorrangsweg */ way[traffic_sign="NL:B1"][!priority_road][!priority_road:forward][!priority_road:backward][!priority_road:both_ways][highway], way[traffic_sign="NL:B01"][!priority_road][!priority_road:forward][!priority_road:backward][!priority_road:both_ways][highway], way[traffic_sign:forward="NL:B1"][!priority_road][!priority_road:forward][!priority_road:both_ways][highway], way[traffic_sign:forward="NL:B01"][!priority_road][!priority_road:forward][!priority_road:both_ways][highway], way[traffic_sign:backward="NL:B1"][!priority_road][!priority_road:backward][!priority_road:both_ways][highway], way[traffic_sign:backward="NL:B01"][!priority_road][!priority_road:backward][!priority_road:both_ways][highway] { group: tr("NL traffic signs"); throwWarning: tr("{0} without {1}", "{0.tag}", "{1.key}"); suggestAlternative: "{0.key}=designated"; } /* Voetgangersoversteekplaats / zebra */ way[highway] > node[traffic_sign~="NL:L2"][highway!=crossing], way[highway] > node[traffic_sign~="NL:L02"][highway!=crossing] { group: tr("NL traffic signs"); throwWarning: tr("{0} without {1}", "{0.tag}", "{1.tag}"); suggestAlternative: "{1.tag} + crossing=zebra"; suggestAlternative: "{1.tag} + crossing=marked + crossing_ref=zebra"; suggestAlternative: "{1.tag} + crossing=uncontrolled + crossing_ref=zebra"; } /* Be very forgiving with the crossing/crossing_ref keys; there are a billion ways to tag it */ node[traffic_sign~="NL:L2"][crossing!=zebra][crossing!=uncontrolled][crossing!=marked][highway=crossing][crossing!=traffic_signals][crossing_ref!=zebra], node[traffic_sign~="NL:L02"][crossing!=zebra][crossing!=uncontrolled][crossing!=marked][highway=crossing][crossing!=traffic_signals][crossing_ref!=zebra] { group: tr("NL traffic signs"); throwWarning: tr("{0} without {1}, {2} or {3}", "{0.tag}", "{1.tag}", "{2.tag} + crossing_ref=zebra", "{3.tag} + crossing_ref=zebra"); assertMatch: "node traffic_sign=NL:L2 highway=crossing"; assertMatch: "node traffic_sign=NL:L02;NL:J23 highway=crossing"; assertNoMatch: "node traffic_sign=NL:L2 direction=300"; assertNoMatch: "node traffic_sign=NL:L2 highway=crossing crossing=uncontrolled crossing_ref=zebra"; assertNoMatch: "node traffic_sign=NL:L02 highway=crossing crossing=traffic_signals note=traffic_signals_combined_with_zebra"; } /* Stop- of parkeerverboden */ /* Let op: kan gecombineerd zijn met parkeervakken waarbij in het vak wel geparkeerd mag worden */ way[parking:both:restriction!=no_parking][traffic_sign~="NL:E01"][highway][parking:both=no][parking:right:restriction!=no_parking][parking:left:restriction!=no_parking], way[parking:both:restriction!=no_parking][traffic_sign~="NL:E01"][highway][parking:left=no][parking:lane:right=no][parking:right:restriction!=no_parking][parking:left:restriction!=no_parking], way[parking:both:restriction!=no_parking][traffic_sign~="NL:E1"][highway][parking:both=no][parking:right:restriction!=no_parking][parking:left:restriction!=no_parking], way[parking:both:restriction!=no_parking][traffic_sign~="NL:E1"][highway][parking:left=no][parking:lane:right=no][parking:right:restriction!=no_parking][parking:left:restriction!=no_parking], way[parking:right:restriction!=no_parking][traffic_sign:right~="NL:E01"][highway][parking:both=no][parking:both:restriction!=no_parking], way[parking:right:restriction!=no_parking][traffic_sign:right~="NL:E01"][highway][parking:right=no][parking:both:restriction!=no_parking], way[parking:right:restriction!=no_parking][traffic_sign:right~="NL:E1"][highway][parking:both=no][parking:both:restriction!=no_parking], way[parking:right:restriction!=no_parking][traffic_sign:right~="NL:E1"][highway][parking:right=no][parking:both:restriction!=no_parking], way[parking:left:restriction!=no_parking][traffic_sign:left~="NL:E01"][highway][parking:both=no][parking:both:restriction!=no_parking], way[parking:left:restriction!=no_parking][traffic_sign:left~="NL:E01"][highway][parking:left=no][parking:both:restriction!=no_parking], way[parking:left:restriction!=no_parking][traffic_sign:left~="NL:E1"][highway][parking:both=no][parking:both:restriction!=no_parking], way[parking:left:restriction!=no_parking][traffic_sign:left~="NL:E1"][highway][parking:left=no][parking:both:restriction!=no_parking], way[parking:both:restriction!=no_stopping][traffic_sign~="NL:E02"][highway][parking:both=no][parking:right:restriction!=no_stopping][parking:left:restriction!=no_stopping], way[parking:both:restriction!=no_stopping][traffic_sign~="NL:E02"][highway][parking:left=no][parking:right=no][parking:right:restriction!=no_stopping][parking:left:restriction!=no_stopping], way[parking:both:restriction!=no_stopping][traffic_sign~="NL:E2"][highway][parking:both=no][parking:right:restriction!=no_stopping][parking:left:restriction!=no_stopping], way[parking:both:restriction!=no_stopping][traffic_sign~="NL:E2"][highway][parking:left=no][parking:right=no][parking:right:restriction!=no_stopping][parking:left:restriction!=no_stopping], way[parking:right:restriction!=no_stopping][traffic_sign:right~="NL:E02"][highway][parking:both=no][parking:both:restriction!=no_stopping], way[parking:right:restriction!=no_stopping][traffic_sign:right~="NL:E02"][highway][parking:right=no][parking:both:restriction!=no_stopping], way[parking:right:restriction!=no_stopping][traffic_sign:right~="NL:E2"][highway][parking:both=no][parking:both:restriction!=no_stopping], way[parking:right:restriction!=no_stopping][traffic_sign:right~="NL:E2"][highway][parking:right=no][parking:both:restriction!=no_stopping], way[parking:left:restriction!=no_stopping][traffic_sign:left~="NL:E02"][highway][parking:both=no][parking:both:restriction!=no_stopping], way[parking:left:restriction!=no_stopping][traffic_sign:left~="NL:E02"][highway][parking:left=no][parking:both:restriction!=no_stopping], way[parking:left:restriction!=no_stopping][traffic_sign:left~="NL:E2"][highway][parking:both=no][parking:both:restriction!=no_stopping], way[parking:left:restriction!=no_stopping][traffic_sign:left~="NL:E2"][highway][parking:left=no][parking:both:restriction!=no_stopping] { group: tr("NL traffic signs"); throwWarning: tr("{0} without {1}", "{1.tag}", "{0.tag}"); fixAdd: "{0.tag}"; assertMatch: "way highway=residential traffic_sign:left=NL:E02 parking:left=no"; assertMatch: "way highway=residential traffic_sign:left=NL:E02 parking:both=no"; assertNoMatch: "way highway=residential traffic_sign:left=NL:E02 parking:left=parallel"; assertNoMatch: "way highway=residential traffic_sign:left=NL:E02 traffic_sign:right=NL:E02 parking:both=no parking:both:restriction=no_stopping"; assertNoMatch: "way highway=residential traffic_sign=NL:E01 parking:both=no parking:left:restriction=no_parking parking:right:restriction=no_parking"; } /* Voorrang bij een versmalling */ way[highway][traffic_sign~="NL:F5"][!priority][!/^priority:./][highway!=construction], way[highway][traffic_sign~="NL:F05"][!priority][!/^priority:./][highway!=construction], way[highway][traffic_sign~="NL:F6"][!priority][!/^priority:./][highway!=construction], way[highway][traffic_sign~="NL:F06"][!priority][!/^priority:./][highway!=construction] { group: tr("NL traffic signs"); throwWarning: tr("{0} without {1} or {2}", "{1.tag}", "{2.key}=forward", "{2.key}=backward"); assertMatch: "way highway=residential traffic_sign=\"NL:F6;OB05\""; assertNoMatch: "way highway=residential traffic_sign=\"NL:F6;OB05\" priority:agricultural=forward"; assertNoMatch: "way highway=residential traffic_sign=\"NL:F6;NL:F5\" priority=forward"; } way[highway][traffic_sign:forward~="NL:F5"][priority!=backward][/^priority:./!~/backward/][highway!=construction], way[highway][traffic_sign:forward~="NL:F05"][priority!=backward][/^priority:./!~/backward/][highway!=construction], way[highway][traffic_sign:backward~="NL:F6"][priority!=backward][/^priority:./!~/backward/][highway!=construction], way[highway][traffic_sign:backward~="NL:F06"][priority!=backward][/^priority:./!~/backward/][highway!=construction], way[highway][traffic_sign:backward~="NL:F5"][priority!=forward][/^priority:./!~/forward/][highway!=construction], way[highway][traffic_sign:backward~="NL:F05"][priority!=forward][/^priority:./!~/forward/][highway!=construction], way[highway][traffic_sign:forward~="NL:F6"][priority!=forward][/^priority:./!~/forward/][highway!=construction], way[highway][traffic_sign:forward~="NL:F06"][priority!=forward][/^priority:./!~/forward/][highway!=construction] { group: tr("NL traffic signs"); throwWarning: tr("{0} without {1}", "{1.tag}", "{2.tag}"); assertMatch: "way highway=residential traffic_sign:forward=\"NL:F6\""; assertMatch: "way highway=residential traffic_sign:forward=\"NL:F6\" priority=backward"; assertMatch: "way highway=residential traffic_sign:forward=\"NL:F5\" priority=forward"; assertMatch: "way highway=residential traffic_sign:backward=\"NL:F05\" priority=backward"; assertMatch: "way highway=residential traffic_sign:forward=\"NL:F6;OB05\" priority:agricultural=backward"; assertNoMatch: "way highway=residential traffic_sign:forward=\"NL:F6\" priority=forward"; assertNoMatch: "way highway=residential traffic_sign:backward=\"NL:F6\" priority=backward"; assertNoMatch: "way highway=residential traffic_sign:forward=\"NL:F5\" priority=backward"; assertNoMatch: "way highway=residential traffic_sign:forward=\"NL:F6\" priority:conditional=\"forward @ (10:00-12:00)\""; assertNoMatch: "way highway=residential traffic_sign:forward=\"NL:F6;OB05\" priority:agricultural=forward"; } /* Unofficial sign: no dogs allowed */ way[traffic_sign~="NL:L1030"][!dog][highway] { group: tr("NL traffic signs"); throwOther: tr("{0} without {1}", "{0.tag}", "{1.key}=*"); } /* Traffic signs not following the default syntax with uppercase NL and first letters of sign */ *[traffic_sign][traffic_sign=~/(?i)\bNL:\w+\d+/][traffic_sign!~/\bNL:[A-Z]+\d+/], *[traffic_sign:forward][traffic_sign:forward=~/(?i)\bNL:\w+\d+/][traffic_sign:forward!~/\bNL:[A-Z]+\d+/], *[traffic_sign:backward][traffic_sign:backward=~/(?i)\bNL:\w+\d+/][traffic_sign:backward!~/\bNL:[A-Z]+\d+/] { throwOther: tr("{0} zonder hoofdletters waar gangbaar", "{0.tag}"); group: tr("NL traffic signs"); assertMatch: "way traffic_sign=\"nl:C1\""; assertMatch: "way traffic_sign=\"NL:g12a\""; assertNoMatch: "way traffic_sign=\"NL:C1\""; assertNoMatch: "way traffic_sign=\"NL:G12a\""; assertNoMatch: "way traffic_sign=city_limit"; } /* ---------------------------- */ /* -- Addresses and contacts -- */ /* ---------------------------- */ /* Phone numbers - preceding zeros */ *[contact:phone=~/^(00|\+)31 ?0( ?[0-9]){7,}/], *[contact:mobile=~/^(00|\+)31 ?0( ?[0-9]){7,}/], *[contact:whatsapp=~/^(00|\+)31 ?0( ?[0-9]){7,}/], *[phone=~/^(00|\+)31 ?0( ?[0-9]){7,}/] { throwWarning: tr("Invalid tag {0}: country code should not be followed by a 0", "{0.key}"); group: tr("NL addresses and contacts"); assertMatch: "node phone=\"+31 0612345678\""; assertMatch: "node phone=\"+31 06 1234 5678\""; assertMatch: "node phone=\"00310612345678\""; assertNoMatch: "node phone=\"0031612345678\""; assertNoMatch: "node phone=\"+31 612345678\""; assertNoMatch: "node phone=\"+31 6 1234 5678\""; assertNoMatch: "node phone=\"0612345678\""; assertNoMatch: "node phone=\"06 12 34 56 78\""; assertMatch: "node phone=\"+31 08008844\""; set .badPhoneNumber; } /* Phone numbers - internationalized national/local numbers */ *[contact:phone=~/^(\+|00)31 ?0?( ?[0-9]){3,6}$/], *[contact:mobile=~/^(\+|00)31 ?0?( ?[0-9]){3,6}$/], *[phone=~/^(\+|00)31 ?0?( ?[0-9]){3,6}$/] { throwWarning: tr("Invalid tag {0}: short phone numbers cannot be used with international prefix (or: wrong phone number length)", "{0.key}"); group: tr("NL addresses and contacts"); assertMatch: "node phone=\"+3114024\""; assertMatch: "node phone=\"+31 14 0245\""; assertMatch: "node phone=\"+31 140245\""; assertMatch: "node phone=\"0031140245\""; assertNoMatch: "node phone=\"+318008844\""; assertNoMatch: "node phone=\"+31 800 8844\""; assertNoMatch: "node phone=\"00318008844\""; assertNoMatch: "node phone=\"0031612345678\""; assertNoMatch: "node phone=\"0612345678\""; assertNoMatch: "node phone=\"08008844\""; assertNoMatch: "node phone=\"0800 8844\""; assertNoMatch: "node phone=\"14024\""; assertNoMatch: "node phone=\"140245\""; set .badPhoneNumber; } /* Phone numbers - too many digits */ *[contact:phone=~/^(0031|\+31|0) ?[1-9]( ?[0-9]){11}/][inside("NL")]!.badPhoneNumber, *[contact:mobile=~/^(0031|\+31|0) ?[1-9]( ?[0-9]){11}/][inside("NL")]!.badPhoneNumber, *[contact:whatsapp=~/^(0031|\+31|0) ?[1-9]( ?[0-9]){11}/][inside("NL")]!.badPhoneNumber, *[phone=~/^(0031|\+31|0) ?[1-9]( ?[0-9]){11}/][inside("NL")]!.badPhoneNumber { throwWarning: tr("Invalid tag {0}: too many digits (or foreign number, if so: ignore)", "{0.key}"); group: tr("NL addresses and contacts"); assertNoMatch: "node phone=\"0031612345678\""; assertNoMatch: "node phone=\"+31 6 12345678\""; assertNoMatch: "node phone=\"+31 6 1234 5678\""; assertNoMatch: "node phone=\"06 12345678\""; assertNoMatch: "node phone=\"0800 1234567\""; /* Lang infonr, 11 cijfers */ assertNoMatch: "node contact:mobile=\"097 123456789\""; /* 097 nummer, 12 cijfers */ assertNoMatch: "node contact:whatsapp=\"+3197 123456789\""; /* 097 nummer, 12 cijfers */ assertNoMatch: "node contact:whatsapp=\"+31 97 1234 567 89\""; /* 097 nummer, 12 cijfers */ } /* Address tags on building */ area[building][/^addr:(street|housenumber|postcode|city)$/][amenity!=place_of_worship][shop!=mall][building!~/^(container|houseboat|static_caravan)$/][inside("NL")]:closed { throwWarning: tr("In Nederland is het gebouw niet gekoppeld aan het adres. Het adres is wel gekoppeld aan het gebruiksdoel."); group: tr("NL addresses and contacts"); assertNoMatch: "relation type=multipolygon building=yes addr:housename=huis"; /* housename has its own warning */ assertNoMatch: "relation type=multipolygon building=houseboat addr:housenumber=2"; assertNoMatch: "relation type=multipolygon building=house"; set .addrOnBuilding; } /* Addresses should consist of (at least) a street and a housenumber */ /* Postcode isn't always present; city can be derived from boundaries */ /* JOSM already complains about missing streets with housenumbers */ /* Rules for node and area separate to avoid Osmose issue 1766 */ node[/^addr:(city|postcode)$/][!/(^|.+:)addr:housenumber($|:.+)/][!/(^|.+:)addr:street($|:.+)/][inside("NL")], area[/^addr:(city|postcode)$/][!/(^|.+:)addr:housenumber($|:.+)/][!/(^|.+:)addr:street($|:.+)/][inside("NL")]!.addrOnBuilding, node[addr:street][!/(^|.+:)addr:housenumber($|:.+)/][!addr:interpolation][!addr:flats][inside("NL")], area[addr:street][!/(^|.+:)addr:housenumber($|:.+)/][!addr:interpolation][!addr:flats][inside("NL")]!.addrOnBuilding { throwWarning: tr("Incomplete address: {0} {1} {2} {3}", any(tag("addr:street"), "[street?]"), any(tag("addr:housenumber"), "[housenumber?]"), any(tag("addr:postcode"), ""), any(tag("addr:city"), "")); group: tr("NL addresses and contacts"); assertNoMatch: "node addr:street=XXX addr:housenumber=123 addr:postcode=1234AB addr:city=XXX"; assertNoMatch: "node addr:street=XXX addr:flats=1-3 addr:postcode=1234AB addr:city=XXX"; assertNoMatch: "node addr:street=XXX proposed:addr:housenumber=123 addr:postcode=1234AB addr:city=XXX"; assertNoMatch: "node addr:street=XXX addr:housenumber:construction=123 addr:postcode=1234AB addr:city=XXX"; assertNoMatch: "node addr:street=\"Pastoor Simonisplein\" addr:housenumber=2a addr:city=Milheeze amenity=atm"; /* No postcode */ assertNoMatch: "node addr:street=Ozingaloane addr:housenumber=1W-5 addr:city=Marrum power=generator"; /* No postcode */ } /* Postcodes using invalid format */ node["addr:postcode"]["addr:postcode"!~/[0-9]{4} ?[A-Z]{2}/][inside("NL")] { throwWarning: tr("Invalid tag {0}: expected 4 digits followed by 2 letters", "{0.tag}"); group: tr("NL addresses and contacts"); } /* --------------------------- */ /* -- Foreign style tagging -- */ /* --------------------------- */ /* Unwanted German style cycleway and footway tagging */ /* https://community.openstreetmap.org/t/duitse-stijl-surface-tagging-op-fietspaden-door-streetcomplete/92572 */ way[cycleway:surface][surface][highway=cycleway][surface=*"cycleway:surface"][inside("NL")], way[footway:surface][surface][highway=footway][surface=*"footway:surface"][inside("NL")] { throwWarning: tr("{0} together with {1} and {2}. Remove {0}.", "{0.key}", "{1.key}", "{2.tag}"); group: tr("NL German style tagging"); fixRemove: "{0.key}"; } way[cycleway:surface][surface][highway=cycleway][surface!=*"cycleway:surface"][inside("NL")], way[footway:surface][surface][highway=footway][surface!=*"footway:surface"][inside("NL")] { throwWarning: tr("{0} and {1} together with {2} and conflicting values", "{0.key}", "{1.key}", "{2.tag}"); group: tr("NL German style tagging"); } way[cycleway:surface][highway=cycleway][!surface][inside("NL")], way[footway:surface][highway=footway][!surface][inside("NL")] { throwWarning: tr("{0} together with {1}", "{0.key}", "{1.tag}"); group: tr("NL German style tagging"); suggestAlternative: "surface=*"; fixChangeKey: "{0.key}=>surface"; } way[footway:surface][cycleway:surface][segregated=no][highway][footway:surface!=*"cycleway:surface"][inside("NL")] { throwWarning: tr("{0} and {1} together with {2} and conflicting values", "{0.key}", "{1.key}", "{2.tag}"); group: tr("NL German style tagging"); } way[/^footway(:left|:right|:both)?:/][/^sidewalk:(left|right|both)$/][/^sidewalk:(left|right|both)$/=~/^yes$/][inside("NL")], way[/^footway(:left|:right|:both)?:/][sidewalk][sidewalk=~/^(left|right|both|yes)$/][inside("NL")] { throwWarning: tr("{0} together with {1}", "{0.key}", "{1.key}"); group: tr("NL German style tagging"); suggestAlternative: "sidewalk:*"; } /* Non-G7 footway with segregated or cycleway cannot be correct */ way[highway=footway][cycleway][cycleway!=no][cycleway!=lane][traffic_sign!~/\bNL:G0?7\b/][inside("NL")], /* JOSM already warns about cycleway=lane */ way[highway=footway][segregated=yes][traffic_sign!~/\bNL:G0?7\b/][inside("NL")] { throwWarning: tr("{0} together with {1}", "{0.tag}", "{1.tag}"); group: tr("NL German style tagging"); assertNoMatch: "way highway=footway segregated=yes traffic_sign=NL:G7"; assertNoMatch: "way highway=footway segregated=yes traffic_sign=NL:G07-ZB"; assertNoMatch: "way highway=footway cycleway=lane traffic_sign=NL:G07-ZB"; assertNoMatch: "way highway=footway cycleway=no"; suggestAlternative: "highway=path"; suggestAlternative: "highway=cycleway"; } /* -------------------------------- */ /* -- Tags considered deprecated -- */ /* -------------------------------- */ /* sidewalk=none */ /* https://community.openstreetmap.org/t/overbodig-foot-yes-en-sidewalk-none-door-potlatch/79696 */ way[sidewalk=none][inside("NL")] { throwWarning: tr("{0} is deprecated", "{0.tag}"); group: tr("NL deprecated features"); suggestAlternative: "sidewalk=no"; fixAdd: "{0.key}=no"; } /* associatedStreet */ /* https://community.openstreetmap.org/t/problemen-met-associatedstreet-in-josm/91103 */ relation[type=associatedStreet][inside("NL")] { throwWarning: tr("{0} is deprecated", "{0.tag}"); group: tr("NL deprecated features"); suggestAlternative: "type=street"; suggestAlternative: "geen relatie"; } /* postal_code */ /* https://community.openstreetmap.org/t/alle-is-in-en-postal-code-tags-verwijderen/93998 */ way[postal_code][inside("NL")] { throwWarning: tr("{0} is deprecated", "{0.key}"); group: tr("NL deprecated features"); suggestAlternative: "addr:postcode via BAG imports on addresses"; fixRemove: "{0.key}"; } /* building=terrace instead of multiple building=house (or leisure=outdoor_seating) */ /* https://community.openstreetmap.org/t/streetcomplete-en-building-terrace/95242 */ area[building=terrace][inside("NL")] { throwWarning: tr("Een rij met rijtjeshuizen ({0}) wordt in Nederland per huis geïmporteerd uit de BAG", "{0.tag}"); group: tr("NL deprecated features"); suggestAlternative: "building=house via een BAG importverzoek voor huizen"; suggestAlternative: "building=house + house=terraced voor een individueel rijtjeshuis"; suggestAlternative: "leisure=outdoor_seating voor 'terrasjes'"; } /* addr:interpolation instead of multiple separate addresses */ *[addr:interpolation][inside("NL")] { throwWarning: tr("Adressen ({0}) worden in Nederland individueel geïmporteerd uit de BAG", "{0.key}"); group: tr("NL deprecated features"); suggestAlternative: "meerdere addr:housenumber via een BAG importverzoek"; } /* almost all building geometries in NL can be imported from BAG, so no need for 'node-buildings' */ area[building][building!=no] ⊇ node[building] { set buildingNodeInBuilding; /* JOSM already warns for this */ } node[building][building!~/^(bridge|bunker|carport|chapel|construction|container|entrance|grandstand|houseboat|hut|no|proposed|roof|ruins|shed|shelter|shrine|static_caravan|storage_tank|tent|wayside_shrine)$/][!seasonal][!ruins][amenity!=shelter][wall!=no][inside("NL")]:unconnected!.buildingNodeInBuilding { throwWarning: tr("{0} on a node", "{0.tag}"); group: tr("NL deprecated features"); suggestAlternative: "een BAG importverzoek om de geometrie te verkrijgen"; } /* is_in */ /* https://community.openstreetmap.org/t/alle-is-in-en-postal-code-tags-verwijderen/93998 */ *[is_in=NL], *[is_in:country][inside("NL")], *[is_in:city][inside("NL")], *[is_in:province][inside("NL")], *[is_in:continent][inside("NL")], *[is_in:country_code=NL] { throwWarning: tr("{0} is deprecated", "{0.key}"); group: tr("NL deprecated features"); fixRemove: "{0.key}"; } /* ov-chipkaart spelling */ /* https://community.openstreetmap.org/t/tolpoortjes-ns-hoe-te-taggen/71223 */ node[/payment:O[vV][-_]?[cC]hipkaart/] { throwWarning: tr("{0} is deprecated", "{0.key}"); group: tr("NL deprecated features"); suggestAlternative: "payment:ov-chipkaart"; fixChangeKey: "{0.key}=>payment:ov-chipkaart"; } /* Niet los ingetekende sporen */ /* https://community.openstreetmap.org/t/aantal-tracks-passenger-lines-op-een-railway/76910 */ /* https://wiki.openstreetmap.org/wiki/OpenRailwayMap/Tagging_in_Netherlands */ way[railway][tracks][tracks!=1][inside("NL")] { throwWarning: tr("Railway lines should be drawn as separate ways per track, rather than one way with {0}", "{1.tag}"); group: tr("NL deprecated features"); suggestAlternative: "passenger_lines=* if the tracks are already drawn separately"; } /* Gebouwnaam op los ingetekende gebouwen (of building:part) is gewoon de naam */ /* https://community.openstreetmap.org/t/huizen-met-een-naam-wat-moeten-we-ermee/92162 */ area[addr:housename][/^building(:part)?$/][inside("NL")][!name], area[building:name][/^building(:part)?$/][inside("NL")][!name] { throwWarning: tr("{0} is deprecated", "{0.key}"); group: tr("NL deprecated features"); suggestAlternative: "name=*"; fixChangeKey: "{0.key}=>name"; set .housenameWithFix; } area[addr:housename][/^building(:part)?$/][inside("NL")][name=*"addr:housename"]!.housenameWithFix, area[building:name][/^building(:part)?$/][inside("NL")][name=*"building:name"]!.housenameWithFix { throwWarning: tr("{0} is deprecated", "{0.key}"); group: tr("NL deprecated features"); suggestAlternative: "name=*"; fixRemove: "{0.key}"; set .housenameWithFix; } area[addr:housename][/^building(:part)?$/][inside("NL")][name]!.housenameWithFix, area[building:name][/^building(:part)?$/][inside("NL")][name]!.housenameWithFix { throwWarning: tr("{0} is deprecated", "{0.key}"); group: tr("NL deprecated features"); suggestAlternative: "name=*"; } /* landuse=education op het grondgebruik rondom scholen e.d. */ /* Voorbereiding voor deprecated amenity=* verwijderen */ /* https://community.openstreetmap.org/t/taggen-van-scholen-in-nl-naar-aanleiding-van-nieuwe-tag/93211 */ area[amenity=college][landuse!=education][!building][inside("NL")]:closed, area[amenity=university][landuse!=education][!building][inside("NL")]:closed, area[amenity=kindergarten][landuse!=education][!building][inside("NL")]:closed, area[amenity=school][landuse!=education][!building][inside("NL")]:closed { throwOther: tr("{0} without {1}", "{0.tag}", "{1.tag}"); group: tr("NL deprecated features"); fixAdd: "landuse=education"; } /* Currently no active covid restrictions */ *[/.:covid19$/][inside("NL")] { throwWarning: tr("There are no active covid-19 restrictions at the moment. Remove {0}.", "{0.key}"); group: tr("NL deprecated features"); fixRemove: "{0.key}"; } /* bicycle_road doesn't exist in NL */ way[bicycle_road?][inside("NL")] { throwWarning: tr("Het concept {0} bestaat niet in Nederland", "{0.key}"); group: tr("NL deprecated features"); suggestAlternative: "highway=* + cyclestreet=yes (fietsstraat)"; suggestAlternative: "highway=cycleway (fietspad)"; suggestAlternative: "highway=* + cycleway=* (fietsstrook)"; } /* Seems an issue with (mostly) iD users to add translated values */ way[surface][surface=~/stenen$|^hout$|\bbestraa?t(ing)?$|grond$|^puin$|^grind$|zand$/], *[material][material=~/\bhout|\bmetaal\b|^beton$|^brons$|steen\b|ijzer\b|staal\b/] { throwWarning: tr("unusual value of {0}", "{0.key}"); group: tr("NL deprecated features"); assertMatch: "way highway=service surface=\"niet bestraat\""; assertMatch: "way highway=service surface=straatstenen"; assertMatch: "node tourism=artwork material=brons"; assertMatch: "node tourism=artwork material=hout,metaal"; assertNoMatch: "way highway=service surface=paving_stones"; assertNoMatch: "way tourism=artwork material=bronze"; } /* Based on a majority vote, paving_stones:30 should no longer be used */ /* https://community.openstreetmap.org/t/paving-stones-30-en-gebruik/104143 */ *[surface][surface=~/^paving_stones:([1-9])0$/][inside("NL")] { /* Difference with JOSM rule in deprecated.mapcss is the agreed upon tagging conversion */ throwWarning: tr("{0} is deprecated", "{0.tag}"); group: tr("NL deprecated features"); suggestAlternative: "surface=paving_stones + paving_stones:shape=square + paving_stones:length=[length in meter, e.g. 0.3]"; /* No specific suggestAlternative, see JOSM#23206 */ fixAdd: "surface=paving_stones"; fixAdd: "paving_stones:shape=square"; fixAdd: concat("paving_stones:length=0.", get(regexp_match("^paving_stones:([1-9])0$", tag("surface")), 1)); assertNoMatch: "way highway=footway surface=paving_stones"; } *[/^(.+):surface$/][/^(.+):surface$/=~/^paving_stones:([1-9])0$/][count(tag_regex("^(.+):surface$")) == 1][inside("NL")] { throwWarning: tr("{0} is deprecated", "{0.tag}"); group: tr("NL deprecated features"); suggestAlternative: "*:surface=paving_stones + *:paving_stones:shape=square + *:paving_stones:length=[length in meter, e.g. 0.3]"; /* No specific suggestAlternative, see JOSM#23206 */ assertNoMatch: "way highway=residential sidewalk:surface=paving_stones cycleway:surface=paving_stones:20"; /* We can't be sure we get the same element in {0.*} as in {1.*} as in tag_regex(...) */ assertNoMatch: "way highway=residential sidewalk:surface=paving_stones:30 cycleway:surface=paving_stones:20"; /* We can't be sure we get the same element in {0.*} as in {1.*} as in tag_regex(...) */ set .completedSurfacePavingStonesNumber; /* Enable fixes Dec 5, 2024, 1 year after the fix for josm.openstreetmap.de/ticket/23238 was released. Remember to update min-josm-version to 18875 */ /* fixAdd: concat(get(regexp_match("^(.+):surface$", "{0.key}"), 1), ":paving_stones:shape=square"); */ /* fixAdd: concat(get(regexp_match("^(.+):surface$", "{0.key}"), 1), ":paving_stones:length=0.", get(regexp_match("^paving_stones:([1-9])0$", get(tag_regex("^(.+):surface$"), 0)), 1)); */ /* fixAdd: "{0.key}=paving_stones"; */ } *[/^(.+):surface$/=~/^paving_stones:([1-9])0$/][inside("NL")]!.completedSurfacePavingStonesNumber { throwWarning: tr("{0} is deprecated", "*:surface=paving_stones:NN"); group: tr("NL deprecated features"); suggestAlternative: "*:surface=paving_stones + *:paving_stones:shape=square + *:paving_stones:length=[length in meter, e.g. 0.3]"; } /* https://community.openstreetmap.org/t/winkelnummer-tag-onlogisch/118170 */ *[winkelnummer] { throwWarning: tr("{0} is deprecated", "{0.key}"); group: tr("NL deprecated features"); suggestAlternative: "ref=*"; } /* -------------------------------- */ /* --- Tags with unusual values --- */ /* -------------------------------- */ /* Geldmaat en andere banken zijn 's nachts gesloten sinds 2019-2020; overige bedrijven vaak niet per se of onbekend */ /* https://community.openstreetmap.org/t/geld-auto-maat-24-7-geopend/98273 */ node[opening_hours="24/7"][amenity=atm][/^(brand|name|operator)$/=~/(?i)^(Geldmaat|ABN.?AMRO|ING|Rabobank|SNS)\b/][inside("NL")] { throwWarning: tr("{0} op {1} is onwaarschijnlijk, Geldmaten zijn niet de hele nacht geopend", "{0.tag}", "{1.tag}"); group: tr("NL unusual values"); } node[opening_hours="24/7"][amenity=atm][!/^(brand|name|operator)$/][inside("NL")] { throwOther: tr("{0} op {1} is onwaarschijnlijk, Geldmaten zijn niet de hele nacht geopend", "{0.tag}", "{1.tag}"); group: tr("NL unusual values"); } /* There is no traffic sign for (motor_)vehicle=designated, most cases seem to be *=yes or a typo for *=destination */ node[vehicle=designated][!amenity][!vehicle:conditional][inside("NL")], node[motor_vehicle=designated][!amenity][!motor_vehicle:conditional][inside("NL")] { throwWarning: tr("{0} on a node, such a traffic sign does not exist. Possibly a typo for destination?", "{0.tag}"); group: tr("NL unusual values"); suggestAlternative: "{0.key}=yes"; suggestAlternative: "{0.key}=destination"; assertNoMatch: "node motor_vehicle=designated amenity=parking_entrance"; assertNoMatch: "node motor_vehicle=designated amenity=charging_station"; } /* Vehicle=no on a cycleway prevents bicycle access, usually this is a mistake */ /* https://community.openstreetmap.org/t/verwijderen-vehicle-no-op-fietspaden/97576 */ way[highway=cycleway][vehicle=no][!bicycle][traffic_sign!~/\bNL:(C0?1|C0?9|C14|C15|D103|D104)\b/][!vehicle:conditional][!bicycle:conditional][inside("NL")] { throwWarning: tr("Suspicious combination: {0} together with {1} equals {2}", "{0.tag}", "{1.tag}", "{2.key}={1.value}"); group: tr("NL unusual values"); assertNoMatch: "way highway=cycleway vehicle=no traffic_sign=NL:C01"; assertNoMatch: "way highway=cycleway vehicle=no traffic_sign=NL:D104 moped=designated"; assertNoMatch: "way highway=cycleway vehicle=no bicycle:conditional=\"yes @ (sunrise-sunset)\""; } /* Trees larger than the largest in NL */ /* https://www.monumentaltrees.com/nl/records/nld/ */ /* Permission to use for this purpose per email May 6, 2024 19:04 */ node[natural=tree][circumference][siunit_length(tag("circumference")) > 10.32][siunit_length(tag("circumference")) <= 45][inside("NL")], /* 120% of 8.6m, largest known tree circumference in NL, default in meters. JOSM warns > 45m */ node[natural=tree][height][siunit_length(tag("height")) > 61.32][inside("NL")]{ /* 120% of 51.1m, tallest known tree in NL, default in meters */ throwWarning: tr("Unusually large value of {0} ({1} m), did you mean `{1} cm` or `{1} mm`?", "{1.key}", siunit_length("{1.value}")); group: tr("NL unusual values"); assertNoMatch: "node natural=tree circumference=8.6"; assertNoMatch: "node natural=tree height=51"; assertNoMatch: "node natural=tree height=\"288 cm\"" } /* ref:bag should be 16 numbers, but occasionally the first (max 3) zeros are omitted. Anything else is invalid */ /* https://community.openstreetmap.org/t/voorloop-nul-len-bag-referentie-nummers/119754 */ *[ref:bag][ref:bag!~/(; ?|^)([0-9]{0,3}[1-9]|[0-9]{0,2}[1-9][0-9]|[0-9]?[1-9][0-9]{2})[0-9]{12}($|;)/][inside("NL")] { throwWarning: tr("Invalid value of {0}", "{0.key}"); group: tr("NL unusual values"); /*assertMatch: "relation type=multipolygon ref:bag=abcdefghijklmnop"; assertMatch: "relation type=multipolygon ref:bag=12"; assertMatch: "relation type=multipolygon ref:bag=0000567890123456"; assertMatch: "relation type=multipolygon ref:bag=567890123456"; assertMatch: "relation type=multipolygon ref:bag=12345678901234567"; assertMatch: "relation type=multipolygon ref:bag=02345678901234567"; assertMatch: "relation type=multipolygon ref:bag=00501234567890123"; assertMatch: "relation type=multipolygon ref:bag=02001234567890123";*/ assertNoMatch: "relation type=multipolygon ref:bag=1234567890123456"; assertNoMatch: "relation type=multipolygon ref:bag=0234567890123456"; assertNoMatch: "relation type=multipolygon ref:bag=0004567890123456"; assertNoMatch: "relation type=multipolygon ref:bag=\"0004567890123456; 1234567890123456\""; assertNoMatch: "relation type=multipolygon ref:bag=4567890123456"; assertNoMatch: "relation type=multipolygon ref:bag=0050123456789012"; /* Zeewolde: 0050 */ assertNoMatch: "relation type=multipolygon ref:bag=050123456789012"; assertNoMatch: "relation type=multipolygon ref:bag=50123456789012"; assertNoMatch: "relation type=multipolygon ref:bag=0200123456789012"; /* Apeldoorn: 0200 */ assertNoMatch: "relation type=multipolygon ref:bag=200123456789012"; assertNoMatch: "relation type=multipolygon ref:bag=0310123456789012"; /* De Bilt: 0310 */ assertNoMatch: "relation type=multipolygon ref:bag=310123456789012"; } /* The Dutch gravel is not the same as English gravel (= grind). Commonly used for tennis fields */ /* https://community.openstreetmap.org/t/surface-tag-op-tennisbanen-in-nederland/120701 */ *[leisure][surface=gravel][sport~="tennis"][inside("NL")] { throwWarning: tr("unusual value of {0} for {1} (`gravel` in English means `grind` in Dutch)", "{1.key}", "{2.tag}"); group: tr("NL unusual values"); assertNoMatch: "way leisure=pitch sport=boules surface=gravel"; /* Gravel can be right for some sports */ suggestAlternative: "surface=clay"; } /* --------------------------- */ /* ---------- Names ---------- */ /* --------------------------- */ /* Descriptive (Dutch) names */ way[name][highway=service][name=~/(?i)(parkeren$|parkeerplaats$|^toegang(sweg)?\s|^richting\s|drive.thro?u(gh)?)/], way[name][highway][name=~/(?i)(^|\sen\s)((on)?verplicht\s)?(\(?brom\)?)?fietspad$/], way[name][highway][name=~/(?i)^roltrap(pen)?$/], way[name][highway][name=~/(?i)(rolstoel|invaliden)/], way[name][highway][name=~/(?i)(uit?laa[dt]|honden.*wandel|los.?loop)/], way[name][highway][name=~/(?i)bus\s?(baan|strook)/][highway!=busway][highway!=service][highway!=construction], way[name][highway][name=~/\bbouwweg/], area[name][name=~/(?i)^wadi$/][tag("natural")||tag("landuse")], area[name][natural=water][name=visvijver], node[name][highway][name=~/(?i)^(lift)$/], node[name][amenity=drinking_water][name=~/(?i)(drinkwater|\swater|kraan)/], node[name][amenity=charging_station][name=~/(?i)(oplaad|laadpunt|laadpaal)/], *[name][name="ijsbaan"], *[name][name=~/\b(([Aa]f)?gesloten|[Gg]eopend)\b/], *[name][amenity^=parking][name=~/(?i)(parkeren|parkeerplaats|parkeergarage|^garage)$/], *[name][name=~/(?i)^gratis\s|gratis\)/], *[name][name=~/(?i)(klanten|bezoek(ers)?|medewerkers)\b/][!route], *[name][leisure=playground][name=~/(?i)^speeltuin(tje)?$/], *[name][leisure^=dog][name=~/(?i)^(honden\s?)?(toilet|uitlaa[dt]|los.?loop)/], *[name][leisure=pitch][name=~/(?i)ball?(veld(je)?)?$/][!sport] { throwWarning: tr("descriptive name"); group: tr("NL nomenclature"); assertMatch: "node amenity=drinking_water name=kraanwater"; assertMatch: "node leisure=pitch name=\"voetbalveld\""; assertMatch: "node amenity=parking_entrance name=\"parkeerplaats voor bezoekers\""; assertMatch: "way highway=service name=\"McDonalds drive through\""; assertMatch: "way highway=service name=\"parkeerplaats voor bezoekers\""; assertMatch: "way highway=service name=rolstoelpad"; assertMatch: "way highway=service name=\"onverplicht fietspad\""; assertMatch: "node leisure=playground name=\"Abc (gesloten)\""; assertMatch: "way highway=service name=\"fiets- en bromfietspad\""; assertNoMatch: "way highway=unclassified name=Landbouwweg"; assertNoMatch: "way highway=unclassified name=\"Gesloten Stad\""; } *[name][name=~/(?i)(voormalige?)/][!historic][tourism!=information][!landuse][!highway][!boundary][!waterway] { throwWarning: tr("descriptive name"); group: tr("NL nomenclature"); suggestAlternative: "old_name=*"; suggestAlternative: "description=*"; suggestAlternative: "disused=yes"; } /* Street-, area or railway names with abbreviations */ way[name][highway][name=~/\b(Adm|Br|Burg|Cmdt|Dr|Drs|Ds|Gebr|Gen|Ing|Ir|Jhr|Kard|Kon|Luit|Mej|Mevr|Mgr|Min|Mr|Past|Pr|Pres|Prof|St|Vr|Weth|Zr)\.? [A-Za-z]/][inside("NL")]!.abbrname, way[name][highway][name=~/^[A-Z][a-z]{1,4}\. /][name!~/^(Adr|Anth?|Chr?|Corn|Fred|Hub|Jacq?|Joh|Jos|Mac|Nic|Ph|Th)\./][inside("NL")]!.abbrname { throwWarning: tr("Straatnaam met afkorting"); group: tr("NL nomenclature"); assertNoMatch: "way highway=residential name=\"De Visserstraat\""; assertNoMatch: "way highway=residential name=\"J.T. de Visserstraat\""; assertNoMatch: "node highway=residential name=\"Pieter Cornelisz. Hooftstraat\""; assertNoMatch: "way highway=residential name=\"Wim Kan Dreef\""; /* Afkorting Kan. niet toevoegen */ assertNoMatch: "way highway=residential name=\"Th. Weeversweg\""; assertNoMatch: "way highway=residential name=\"Jac. P. Thijsseplein\""; set .abbrname; } *[name][place][name=~/\b(Adm|Br|Burg|Cmdt|Dr|Drs|Ds|Gebr|Gen|Ing|Ir|Jhr|Kard|Kon|Luit|Mej|Mevr|Mgr|Min|Mr|Past|Pr|Pres|Prof|St|Vr|Weth|Zr)\.? [A-Za-z]/][inside("NL")]!.abbrname, *[name][place][name=~/^[A-Z][a-z]{1,4}\. /][name!~/^(Adr|Anth?|Chr?|Corn|Fred|Hub|Jacq?|Joh|Jos|Mac|Nic|Ph|Th)\./][inside("NL")]!.abbrname { throwWarning: tr("Gebiedsnaam met afkorting"); group: tr("NL nomenclature"); set .abbrname; } *[railway][name][name=~/(?i)(aansl|empl|goed|ind|inhaalsp|opstel|overloopw|racc|rang|terr)\./][inside("NL")]!.abbrname, *[railway][name][name=~/(?i)\b(aansl|empl|goed|ind|inhaalsp|opstel|overloopw|racc|rang|terr)\b/][inside("NL")]!.abbrname { throwWarning: tr("Spoorgebied met afgekorte naam"); group: tr("NL nomenclature"); suggestAlternative: "aansluiting, emplacement, goederen, industrieterrein, inhaalspoor, opstelterrein, overloopwissel, raccordement of rangeerterrein"; assertNoMatch: "node railway=tram_stop name=Landgoed"; set .abbrname; } /* Nederlandse naam zonder name */ *[name:nl][!name][inside("NL")][type!=route][name:fy]["name:fy"=*"name:nl"], *[name:nl][!name][inside("NL")][type!=route][!name:fy] { throwWarning: tr("{0} without {1}", "{0.key}", "{1.key}"); group: tr("NL nomenclature"); suggestAlternative: "name"; fixChangeKey: "{0.key}=>{1.key}"; assertNoMatch: "node name=x name:nl=x name:en=y"; assertNoMatch: "node name:nl=x name:fy=y"; } /* Regelmatig foutgespelde namen met minimaal 2500 objecten verspreid over heel NL */ node[operator][operator!=PostNL][operator=~/(?i)post\W?nl$/][amenity=post_box] { throwWarning: tr("Suspected typo in {0}", "{0.tag}"); group: tr("NL nomenclature"); assertNoMatch: "node amenity=post_box operator=PostNL"; assertMatch: "node amenity=post_box operator=postnl"; assertMatch: "node amenity=post_box operator=\"post nl\""; suggestAlternative: "operator=PostNL"; fixAdd: "operator=PostNL"; } /* Over het algemeen hebben namen in het Nederlands een hoofdletter */ *[name][tag("name") == lower(tag("name"))][name=~/^\p{Ll}/][inside("NL")] { /* \p{Ll}=lowercase letters not limited to a-z */ throwOther: tr("Eigennaam zonder hoofdletters"); group: tr("NL nomenclature"); assertNoMatch: "node name=1945"; assertNoMatch: "way name=Happy"; assertNoMatch: "node name=4heren"; assertNoMatch: "node name=\"'t hoekje\""; assertNoMatch: "node name=Çecic"; } /* --------------------------- */ /* --------- Erfgoed --------- */ /* --------------------------- */ *[heritage=2][heritage:operator!=rce][heritage:operator!~/(^|; ?)rce(;|$)/][inside("NL")] { throwWarning: tr("{0} without {1}", "{0.tag}", "{1.tag}"); group: tr("NL heritage"); fixAdd: "heritage:operator=rce"; assertNoMatch: "node heritage=2 heritage:operator=\"rce; Stichting ABCDE\""; } *[ref:rce][!heritage][!heritage:operator][inside("NL")], *[ref:rce][!heritage:operator][heritage][heritage!=2][inside("NL")] { /* Could be heritage=1, or heritage=2;8, or ... */ throwOther: tr("{0} without {1}", "{0.tag}", "{1.key}=*"); group: tr("NL heritage"); } *[heritage:operator=rce][!heritage][inside("NL")] { throwWarning: tr("{0} without {1}", "{0.tag}", "{1.key}=*"); group: tr("NL heritage"); fixAdd: "heritage=2"; } /* Address node with heritage tags, rather than the actual heritage object */ /* Didn't include containing historic=archaeological_site, leisure=park, ... etc as they usually don't have addresses assigned. (Is it even needed to check whether it's inside a building?) */ /* https://community.openstreetmap.org/t/mogen-monumenten-rijks-provincie-gemeente-gebouwen-keys-op-adresnode/111885 */ node[addr:street][addr:housenumber][heritage][!barrier][inside("NL")] ⊆ area[building][inside("NL")] { throwWarning: tr("Heritage tag and related tags on address node, should be on the heritage object instead (building, building:part, park, site, ...)"); group: tr("NL heritage"); } /* ----------------------------- */ /* ------ Route relations ------ */ /* ----------------------------- */ /* Public transport routes should be in a route_master relation; busses also in a consession network relation */ relation[route_master] > relation[route] { set .hasRouteMaster; } relation[network] > relation[route_master] { set .hasNetworkRelation; } relation[route][route=~/^((trolley)?bus|light_rail|subway|train|tram)$/][inside("NL")]!.hasRouteMaster:new { throwWarning: tr("{0} not in route_master relation", "{0.tag}"); group: tr("NL routes"); } relation[route_master][route_master=~/^(trolley)?bus$/][inside("NL")]!.hasNetworkRelation:new { throwWarning: tr("{0} not in network relation", "{0.tag}"); group: tr("NL routes"); } /* Exit-only stops not reflected in role */ relation[type=route][route=~/^((trolley)?bus|light_rail|subway|train|tram)$/]:new >[role!=platform_exit_only] *[public_transport=platform][/^(note|ref|description)$/=~/(?i)uitstaphalte/], relation[type=route][route=~/^((trolley)?bus|light_rail|subway|train|tram)$/][roundtrip?]:modified >[role!=platform_exit_only] *[public_transport=platform][/^(note|ref|description)$/=~/(?i)uitstaphalte/] { throwWarning: tr("{0} uitstaphalte met route-relatie zonder ''platform_exit_only'' role", "{0.tag}"); group: tr("NL routes"); set hasExitStopWarning; } relation[type=route][route=~/^((trolley)?bus|light_rail|subway|train|tram)$/]:new >[role!=stop_exit_only] node[public_transport=stop_position][/^(note|ref|description)$/=~/(?i)uitstaphalte/], relation[type=route][route=~/^((trolley)?bus|light_rail|subway|train|tram)$/][roundtrip?]:modified >[role!=stop_exit_only] node[public_transport=stop_position][/^(note|ref|description)$/=~/(?i)uitstaphalte/] { throwWarning: tr("{0} uitstaphalte met route-relatie zonder ''stop_exit_only'' role", "{0.tag}"); group: tr("NL routes"); set hasExitStopWarning; } relation[type=route][route=~/^((trolley)?bus|light_rail|subway|train|tram)$/] >[role!=platform_exit_only] *[public_transport=platform][/^(note|ref|description)$/=~/(?i)uitstaphalte/]!.hasExitStopWarning { throwOther: tr("{0} uitstaphalte met route-relatie zonder ''platform_exit_only'' role", "{0.tag}"); group: tr("NL routes"); } relation[type=route][route=~/^((trolley)?bus|light_rail|subway|train|tram)$/] >[role!=stop_exit_only] node[public_transport=stop_position][/^(note|ref|description)$/=~/(?i)uitstaphalte/]!.hasExitStopWarning { throwOther: tr("{0} uitstaphalte met route-relatie zonder ''stop_exit_only'' role", "{0.tag}"); group: tr("NL routes"); } /* --------------------------- */ /* ----- Maximumsnelheid ----- */ /* --------------------------- */ /* Maximum speeds per road defaults and signage */ way[highway=living_street][maxspeed!=15][!/^maxspeed(:forward|:backward|:both_ways)?$/][inside("NL")], way[living_street=yes][maxspeed!=15][!/^maxspeed(:forward|:backward|:both_ways)?$/][highway!=living_street][highway!=footway][inside("NL")], way[maxspeed:type="NL:zone30"][maxspeed!=30][!maxspeed][maxspeed:both_ways!=30][highway], way[maxspeed:type="NL:zone60"][maxspeed!=60][!maxspeed][maxspeed:both_ways!=60][highway], way[maxspeed:type="NL:urban"][maxspeed!=50][!maxspeed][maxspeed:both_ways!=50][highway][highway!=cycleway], way[maxspeed:type="NL:rural"][maxspeed!=80][!maxspeed][maxspeed:both_ways!=80][highway][highway!=cycleway] { throwWarning: tr("{0} without {1}", "{0.tag}", "{1.tag}"); group: tr("NL speed limits"); assertMatch: "way highway=residential maxspeed:type=NL:rural"; assertNoMatch: "way highway=residential source:maxspeed=NL:rural"; /* Handled by JOSM */ assertNoMatch: "way highway=cycleway maxspeed:type=NL:rural"; assertNoMatch: "way highway=living_street maxspeed=10 traffic_sign=\"NL:A01-10\""; assertNoMatch: "way highway=living_street maxspeed=18"; /* Handled by different rule */ assertNoMatch: "way highway=footway living_street=yes"; } way[maxspeed:type="NL:zone30"][maxspeed][maxspeed!=30][highway], way[maxspeed:type="NL:zone60"][maxspeed][maxspeed!=60][highway], way[maxspeed:type="NL:urban"][maxspeed][maxspeed!=50][highway][highway!=cycleway], way[maxspeed:type="NL:rural"][maxspeed][maxspeed!=80][highway][highway!=cycleway], way[source:maxspeed="NL:zone30"][maxspeed][maxspeed!=30][highway], way[source:maxspeed="NL:zone60"][maxspeed][maxspeed!=60][highway], way[source:maxspeed="NL:urban"][maxspeed][maxspeed!=50][highway][highway!=cycleway], way[source:maxspeed="NL:rural"][maxspeed][maxspeed!=80][highway][highway!=cycleway] { throwWarning: tr("{0} together with {1}", "{0.tag}", "{1.tag}"); group: tr("NL speed limits"); assertMatch: "way highway=primary maxspeed:type=NL:rural maxspeed=50"; assertMatch: "way highway=primary source:maxspeed=NL:zone60 maxspeed=50"; assertNoMatch: "way highway=primary maxspeed:type=NL:zone30"; /* Handled by different rule */ } way[maxspeed:type][!maxspeed][maxspeed:type^="NL:zone"][!maxspeed:both_ways][maxspeed:type!~/^NL:zone[36]0$/][highway], way[traffic_sign][!maxspeed][traffic_sign=~/(^|; ?)NL:A0?1-/][!/^maxspeed(:forward|:backward|:both_ways)?(:conditional)?$/][highway], way[traffic_sign:forward][!maxspeed:forward][traffic_sign:forward=~/(^|; ?)NL:A0?1-/][!/^maxspeed(:forward|:both_ways)?(:conditional)?$/][highway], way[traffic_sign:backward][!maxspeed:backward][traffic_sign:backward=~/(^|; ?)NL:A0?1-/][!/^maxspeed(:backward|:both_ways)?(:conditional)?$/][highway], way[traffic_sign][!maxspeed:advisory][traffic_sign=~/(^|; ?)NL:A0?4\b/][!/^maxspeed:advisory(:forward|:backward|:both_ways)?(:conditional)?$/][highway], way[traffic_sign:forward][!maxspeed:advisory:forward][traffic_sign:forward=~/(^|; ?)NL:A0?4\b/][!/^maxspeed:advisory(:forward|:both_ways)?(:conditional)?$/][highway], way[traffic_sign:backward][!maxspeed:advisory:backward][traffic_sign:backward=~/(^|; ?)NL:A0?4\b/][!/^maxspeed:advisory(:backward|:both_ways)?(:conditional)?$/][highway] { throwWarning: tr("{0} without {1}", "{0.tag}", "{1.key}"); group: tr("NL speed limits"); assertMatch: "way highway=residential traffic_sign=NL:A01-30"; assertMatch: "way highway=residential traffic_sign=\"NL:C16;NL:A01-30\""; assertMatch: "way highway=residential traffic_sign=\"NL:C16; NL:A01-30\""; assertMatch: "way highway=residential traffic_sign:forward=NL:A1-30-ZB"; assertMatch: "way highway=residential traffic_sign=NL:A04-30"; assertMatch: "way highway=residential traffic_sign=NL:A4"; assertMatch: "way highway=residential traffic_sign=\"NL:A4[60]\""; assertMatch: "way highway=residential maxspeed:type=\"NL:zone20\""; assertNoMatch: "way highway=residential traffic_sign:forward=NL:A1-30 maxspeed:forward=30"; assertNoMatch: "way highway=residential traffic_sign=NL:A01-30 maxspeed=30"; assertNoMatch: "way highway=residential traffic_sign=\"NL:A4[50]\" maxspeed:advisory:both_ways=50"; assertNoMatch: "way highway=residential maxspeed:type=\"NL:zone20\" maxspeed=20"; } /* The majority voted to use maxspeed=100 as the default, and maxspeed:conditional=* for the night-time speed on autosnelwegen */ /* https://community.openstreetmap.org/t/verlaging-maximumsnelheid-per-12-16-maart/89357 */ way[highway=motorway][maxspeed][maxspeed=~/^1[23]0$/][maxspeed:conditional=~/100.+19:00/][inside("NL")] { throwWarning: tr("Agreed upon was to use 100 as the maximum speed and {0} as the conditional maximum speed", "{1.value}"); group: tr("NL speed limits"); } /* Speed restrictions imposed by RVV art. 21 */ way[highway=motorway][maxspeed][maxspeed>130][inside("NL")], way[highway=motorway_link][maxspeed][maxspeed>130][inside("NL")], way[highway=trunk][maxspeed][maxspeed>100][inside("NL")], way[highway=trunk_link][maxspeed][maxspeed>100][inside("NL")], way[motorroad=yes][maxspeed][maxspeed>100][inside("NL")][highway!~/^(motorway(_link)?|construction|proposed)$/], way[highway][maxspeed][maxspeed>80][highway!~/^(motorway(_link)?|trunk(_link)?|cycleway|service|busway|construction|proposed|raceway)$/][motorroad!=yes][inside("NL")], way[highway=cycleway][maxspeed][maxspeed>40][!motor_vehicle][!vehicle][!access][inside("NL")] { throwWarning: tr("{0} together with {1}", "{0.tag}", "{1.tag}"); group: tr("NL speed limits"); assertNoMatch: "way highway=motorway maxspeed=120"; assertNoMatch: "way highway=motorway_link motorroad=yes maxspeed=130"; assertNoMatch: "way highway=trunk_link maxspeed=100"; assertNoMatch: "way highway=tertiary motorroad=yes maxspeed=100"; assertNoMatch: "way highway=trunk maxspeed=90"; assertNoMatch: "way highway=unclassified maxspeed=80"; } /* Speed restrictions imposed by RVV art. 22 */ way[maxspeed:mofa][maxspeed:mofa>25][inside("NL")], way[maxspeed:moped][maxspeed:moped>45][inside("NL")], way[maxspeed:bus][maxspeed:bus>100][inside("NL")], way[maxspeed:trailer][maxspeed:trailer>90][inside("NL")], way[maxspeed:hgv][maxspeed:hgv>80][inside("NL")] { throwWarning: tr("{0} overschrijdt de maximumsnelheid van RVV art. 22", "{0.tag}"); group: tr("NL speed limits"); assertNoMatch: "way highway=unclassified maxspeed:moped=45"; } /* Speed restrictions imposed by RVV art. 45 */ way[highway=living_street][maxspeed][maxspeed>15][inside("NL")][maxspeed<=20], /* JOSM warns for larger than 20 */ way[living_street=yes][maxspeed][maxspeed>15][highway!=living_street][inside("NL")] { throwWarning: tr("{0} together with {1}", "{0.tag}", "{1.tag}"); group: tr("NL speed limits"); assertNoMatch: "way highway=living_street maxspeed=10 traffic_sign=\"NL:A01-10\""; } /* Uncommon maxspeeds (except on private-owned roads) */ way[maxspeed][maxspeed=~/[1-9]$/][maxspeed!=5][maxspeed!=15][highway=~/^(residential|unclassified|tertiary|secondary|primary|trunk|motorway|busway)(_link)?$/][!access][!vehicle][!motor_vehicle][inside("NL")], way[maxspeed=20][highway=~/^(residential|unclassified|tertiary|secondary|primary|trunk|motorway|busway)(_link)?$/][!access][!vehicle][!motor_vehicle][source:maxspeed!="NL:zone20"][maxspeed:type!="NL:zone20"][inside("NL")], way[maxspeed=40][highway=~/^(residential|unclassified|tertiary|secondary|primary|trunk|motorway|busway)(_link)?$/][!access][!vehicle][!motor_vehicle][source:maxspeed!="NL:zone40"][maxspeed:type!="NL:zone40"][inside("NL")] { throwWarning: tr("{0} is a non-standard speed limit. Possibly this is an advisory speed limit instead?", "{0.tag}"); group: tr("NL speed limits"); assertNoMatch: "way highway=unclassified access=permissive note=eigen_weg maxspeed=25"; assertNoMatch: "way highway=cycleway maxspeed=40"; assertNoMatch: "way highway=residential maxspeed=30"; } /* ---------------------------- */ /* ------- Snorfietsers ------- */ /* ---------------------------- */ /* In practically all cases, oneway:bicycle=no (uitgezonderd fietsers) implies oneway:mofa=no too */ /* Disabled due to ongoing discussion: https://community.openstreetmap.org/t/onderbord-ob52-uitgezonderd-fietsers-bij-eenrichtingsweg/117479 */ /*way[oneway:bicycle][!oneway:mofa][oneway?][oneway:bicycle=~/^(no|-1|0)$/][mofa!~/^(no|use_sidepath)$/][motor_vehicle!~/^(no|use_sidepath)$/][mofa:backward!~/^(no|use_sidepath)$/][motor_vehicle:backward!~/^(no|use_sidepath)$/][inside("NL")] { throwWarning: tr("{0} without {1}", "{0.tag}", "{1.key}"); group: tr("NL mofa tagging"); fixAdd: "{1.key}={0.value}"; assertNoMatch: "way highway=residential oneway:bicycle=yes oneway=yes"; assertNoMatch: "way highway=residential oneway:bicycle=no oneway=no"; assertNoMatch: "way highway=residential oneway:bicycle=no oneway=yes oneway:mofa=yes"; assertNoMatch: "way highway=residential oneway:bicycle=no oneway=yes mofa=no"; assertNoMatch: "way highway=residential oneway:bicycle=no oneway=yes mofa:backward=no"; }*/ /* In practically all cases, something that applies to mopeds and bicycles, also applies to mofa's */ /* Restricted access: warn always (highways, ferry routes, ...) */ way[bicycle:conditional][moped:conditional][bicycle:conditional=*"moped:conditional"][!mofa:conditional][inside("NL")], way[bicycle:forward][moped:forward][bicycle:forward=*"moped:forward"][!mofa:forward][!mofa][!mofa:both_ways][bicycle:forward!=designated][bicycle:forward!=yes][inside("NL")], way[bicycle:backward][moped:backward][bicycle:backward=*"moped:backward"][!mofa:backward][!mofa][!mofa:both_ways][bicycle:backward!=designated][bicycle:backward!=yes][inside("NL")], way[bicycle:both_ways][moped:both_ways][bicycle:both_ways=*"moped:both_ways"][!mofa:both_ways][!mofa][bicycle:both_ways!=designated][bicycle:both_ways!=yes][inside("NL")], way[bicycle][moped][bicycle=*moped][!mofa][bicycle!=designated][bicycle!=yes][inside("NL")] { throwWarning: tr("{0} and {1} without {2}", "{0.tag}", "{1.tag}", "{3.key}={0.value}"); group: tr("NL mofa tagging"); fixAdd: "{3.key}={0.value}"; } /* Exclusions of turn restrictions: warn always */ relation[except][except~=bicycle][except~=moped][except!~/(^|; ?)mofa(;|$)/] { throwWarning: tr("{0} without {1}", "{0.tag}", "mofa"); group: tr("NL mofa tagging"); suggestAlternative: "{0.tag};mofa"; fixAdd: "{0.key}={0.value};mofa"; assertNoMatch: "relation type=restriction except=bicycle;mofa;moped"; assertNoMatch: "relation type=restriction except=bicycle"; } /* Positive access: warn only in case of an overruling access/vehicle/motor_vehicle tag... */ way[bicycle:forward][moped:forward][bicycle:forward=*"moped:forward"][!mofa:forward][/^(access|vehicle|motor_vehicle)(:forward|:both_ways)?(:conditional)?$/][!mofa][!mofa:both_ways][bicycle:forward=~/^(yes|designated)$/][join_list(";", uniq_list(tag_regex("^(access|vehicle|motor_vehicle)(:forward|:both_ways)?(:conditional)?$"))) != tag("bicycle:forward")][inside("NL")], way[bicycle:backward][moped:backward][bicycle:backward=*"moped:backward"][!mofa:backward][/^(access|vehicle|motor_vehicle)(:backward|:both_ways)?(:conditional)?$/][!mofa][!mofa:both_ways][bicycle:backward=~/^(yes|designated)$/][join_list(";", uniq_list(tag_regex("^(access|vehicle|motor_vehicle)(:backward|:both_ways)?(:conditional)?$"))) != tag("bicycle:backward")][inside("NL")], way[bicycle][moped][bicycle=*moped][!mofa][/^(access|vehicle|motor_vehicle)(:forward|:backward|:both_ways)?(:conditional)?$/][!mofa:both_ways][bicycle=~/^(yes|designated)$/][join_list(";", uniq_list(tag_regex("^(access|vehicle|motor_vehicle)(:forward|:backward|:both_ways)?(:conditional)?$"))) != tag("bicycle")][inside("NL")] { throwWarning: tr("{0}, {1} and {2} without {3}", "{0.tag}", "{1.tag}", "{4.tag}", "{3.key}={0.value}"); group: tr("NL mofa tagging"); fixAdd: "{3.key}={0.value}"; set .hasAddMofaPositive; assertNoMatch: "way bicycle=designated moped=designated highway=residential"; assertNoMatch: "way bicycle=designated moped=designated highway=residential access=designated"; assertNoMatch: "way bicycle=designated moped=designated mofa=designated highway=residential access=no"; } /* ... or if the default access condition doesn't imply access per the defaults in NL (not a highway or a highway of a frequently no-access type or - due to its wide definition - path) */ way[bicycle:forward][moped:forward][bicycle:forward=*"moped:forward"][!mofa:forward][!mofa][!mofa:both_ways][bicycle:forward=~/^(yes|designated)$/][highway=~/^(trunk|motorway|busway|path|busway|bridleway|footway|pedestrian)(_link)?$/][inside("NL")]!.hasAddMofaPositive, way[bicycle:backward][moped:backward][bicycle:backward=*"moped:backward"][!mofa:backward][!mofa][!mofa:both_ways][bicycle:backward=~/^(yes|designated)$/][highway=~/^(trunk|motorway|busway|path|busway|bridleway|footway|pedestrian)(_link)?$/][inside("NL")]!.hasAddMofaPositive, way[bicycle][moped][bicycle=*moped][!mofa][!mofa:both_ways][bicycle=~/^(yes|designated)$/][highway=~/^(trunk|motorway|busway|path|busway|bridleway|footway|pedestrian)(_link)?$/][inside("NL")]!.hasAddMofaPositive, way[bicycle:forward][moped:forward][bicycle:forward=*"moped:forward"][!mofa:forward][!mofa][!mofa:both_ways][bicycle:forward=~/^(yes|designated)$/][!highway][inside("NL")]!.hasAddMofaPositive, way[bicycle:backward][moped:backward][bicycle:backward=*"moped:backward"][!mofa:backward][!mofa][!mofa:both_ways][bicycle:backward=~/^(yes|designated)$/][!highway][inside("NL")]!.hasAddMofaPositive, way[bicycle][moped][bicycle=*moped][!mofa][!mofa:both_ways][bicycle=~/^(yes|designated)$/][!highway][inside("NL")]!.hasAddMofaPositive { throwWarning: tr("{0} and {1} without {2}", "{0.tag}", "{1.tag}", "{3.key}={0.value}"); group: tr("NL mofa tagging"); fixAdd: "{3.key}={0.value}"; set .hasAddMofaPositive; assertNoMatch: "way bicycle=designated moped=designated mofa=designated highway=busway"; assertNoMatch: "way bicycle=designated moped=destination highway=busway"; assertNoMatch: "way bicycle=designated moped=designated highway=residential"; }