meta { title: "OpenRailwayMap – extra ruleset for Germany"; version: "2017-01-09"; description: "Additional validation of railway data according to the OpenRailwayMap tagging scheme."; author: "rurseekatze"; link: "https://wiki.openstreetmap.org/wiki/OpenRailwayMap/Tagging"; watch-modified: true; } /* track names containing "KBS" */ way[railway][name=~/^KBS [0-9]*.*/], way[railway][name=~/^Kursbuchstrecke [0-9]*.*/] { throwError: "Tracks should not be named by their timetable number (KBS xy). Use a route relation with route=railway, instead."; assertMatch: "way railway=rail name=\"KBS 258\""; assertMatch: "way railway=light_rail name=\"Kursbuchstrecke 710.1\""; assertNoMatch: "way railway=rail name=Frankenbahn"; assertNoMatch: "way railway=light_rail ref=\"Kursbuchstrecke 710.1\""; } /* track refs containing "KBS" */ way[railway][ref=~/^KBS [0-9]*.*/], way[railway][ref=~/^Kursbuchstrecke [0-9]*.*/] { throwError: "ref=* should be a VzG number (without \"VzG\"). Use a route relation with route=railway for KBS numbers, instead."; assertMatch: "way railway=rail ref=\"KBS 258\""; assertMatch: "way railway=light_rail ref=\"Kursbuchstrecke 710.1\""; assertNoMatch: "way railway=rail ref=7400"; } /* track refs containing "VzG" */ way[railway][ref=~/^VzG [0-9]*.*/] { throwError: "ref=* should be a VzG number without \"VzG\""; assertMatch: "way railway=rail ref=\"VzG 7400\""; assertNoMatch: "way railway=rail ref=7400"; } /* track names containing "VzG" */ way[railway][name=~/^VzG [0-9]*.*/] { throwError: "VzG numbers should be tagged as ref=* without \"VzG\""; assertMatch: "way railway=rail name=\"VzG 7400\""; assertNoMatch: "way railway=rail name=7400"; } /* track refs containing VzG number and track number */ way[railway][ref=~/^[0-9]{4}-[0-9]+/] { throwError: "ref=* should only be a VzG number, it should not contain the track number"; assertMatch: "way railway=rail ref=7400-1"; assertNoMatch: "way railway=rail ref=7400"; } /* track names containing only numbers (VzG) */ /* Strangely, JOSM also asserts a match, although it shouldn't, e.g. name=740 or name=740.5 */ way[railway][name=~/^[0-9]{4}$/] { throwError: "Track names should be real names. VzG numbers should be tagged ref=*. KBS numbers should be mapped as a relation with route=railway."; fixChangeKey: "name=>ref"; suggestAlternative: "ref"; assertMatch: "way railway=rail name=\"7400\""; assertNoMatch: "way railway=rail name=\"750\""; assertNoMatch: "way railway=rail ref=7400"; assertNoMatch: "way railway=rail name=Hohenlohebahn"; } /* track names containing only numbers (KBS) */ way[railway][name=~/^[0-9]{3}\.[0-9]+$/], way[railway][name=~/^[0-9]{3}\.[0-9]{1,2}[-.][0-9]{1,2}$/] { throwError: "Track names should be real names. KBS numbers should be mapped as a relation with route=railway."; assertMatch: "way railway=rail name=\"740.4\""; assertMatch: "way railway=rail name=\"790.4-5\""; assertMatch: "way railway=rail name=\"790.4.5\""; assertNoMatch: "way railway=rail name=\"780\""; assertNoMatch: "way railway=rail name=\"790.4a5\""; assertNoMatch: "way railway=rail name=Hohenlohebahn"; assertNoMatch: "way railway=rail name=\"790.4--5\""; assertNoMatch: "way railway=rail name=\"790.4..5\""; assertNoMatch: "way railway=rail name=7400"; assertNoMatch: "way railway=rail name=7400a"; } /* track names containing only three digits (KBS or track number) */ way[railway][name=~/^[0-9]{3}$/] { throwError: "Track names should be real names. KBS numbers should be mapped as a relation with route=railway, track numbers as railway:track_ref=*."; assertMatch: "way railway=rail name=\"780\""; assertNoMatch: "way railway=rail name=\"740.4\""; assertNoMatch: "way railway=rail name=\"790.4-5\""; assertNoMatch: "way railway=rail name=\"790.4.5\""; assertNoMatch: "way railway=rail name=\"790.4a5\""; assertNoMatch: "way railway=rail name=Hohenlohebahn"; assertNoMatch: "way railway=rail name=\"790.4--5\""; assertNoMatch: "way railway=rail name=\"790.4..5\""; assertNoMatch: "way railway=rail name=7400"; assertNoMatch: "way railway=rail name=7400a"; } /* track refs containing only numbers that look like KBS numbers */ way[railway][ref=~/^[0-9]{3}\.[0-9]+$/], way[railway][ref=~/^[0-9]{3}\.[0-9]{1,2}[-.][0-9]{1,2}$/] { throwError: "Track refs should be VzG numbers in Germany. KBS numbers should be mapped as a relation with route=railway."; assertMatch: "way railway=rail ref=\"740.4\""; assertMatch: "way railway=rail ref=\"790.4-5\""; assertMatch: "way railway=rail ref=\"790.4.5\""; assertNoMatch: "way railway=rail ref=\"780\""; assertNoMatch: "way railway=rail ref=\"790.4--5\""; assertNoMatch: "way railway=rail ref=\"790.4..5\""; assertNoMatch: "way railway=rail ref=\"790.4a5\""; assertNoMatch: "way railway=rail ref=7400"; assertNoMatch: "way railway=rail ref=7400a"; } /* track refs containing only three digits (KBS or track number) */ way[railway][ref=~/^[0-9]{3}$/] { throwError: "Track refs should be VzG numbers in Germany. KBS numbers should be mapped as a relation with route=railway, track numbers as railway:track_ref=*."; assertMatch: "way railway=rail ref=\"780\""; assertNoMatch: "way railway=rail ref=\"740.4\""; assertNoMatch: "way railway=rail ref=\"790.4-5\""; assertNoMatch: "way railway=rail ref=\"790.4.5\""; assertNoMatch: "way railway=rail ref=\"790.4--5\""; assertNoMatch: "way railway=rail ref=\"790.4..5\""; assertNoMatch: "way railway=rail ref=\"790.4a5\""; assertNoMatch: "way railway=rail ref=7400"; assertNoMatch: "way railway=rail ref=7400a"; } /* workrules=EBO is deprecated, should be changed to workrules=DE:EBO */ /* workrules=ESBO is deprecated, should be changed to workrules=DE:ESBO */ /* workrules=BOStrab is deprecated, should be changed to workrules=DE:BOStrab */ way[railway][workrules=EBO], way[railway][workrules=ESBO], way[railway][workrules=BOStrab] { throwError: "workrules={1.value} is deprecated, change to workrules=DE:{1.value}"; fixAdd: "workrules=DE:{1.value}"; assertMatch: "way railway=rail workrules=EBO"; assertMatch: "way railway=rail workrules=ESBO"; assertMatch: "way railway=rail workrules=BOStrab"; assertNoMatch: "node railway=rail"; assertNoMatch: "way railway=rail"; assertNoMatch: "area railway=rail"; assertNoMatch: "way railway=rail workrules=DE:EBO"; assertNoMatch: "way railway=rail workrules=DE:ESBO"; assertNoMatch: "way railway=rail workrules=DE:BOStrab"; } way[railway][workrules=BOA] { throwError: "workrules=BOA is deprecated, replace by an adequate value"; assertMatch: "way railway=rail workrules=BOA"; assertNoMatch: "node railway=rail"; assertNoMatch: "way railway=rail"; assertNoMatch: "area railway=rail"; assertNoMatch: "way railway=rail workrules=DE:BOStrab"; } way[railway][workrules="DE-BOStrab"] { throwError: "workrules: separate country and ruleset by : , not by -"; fixAdd: "workrules=DE:BOStrab"; suggestAlternative: "workrules=DE:BOStrab"; assertMatch: "way railway=rail workrules=DE-BOStrab"; assertNoMatch: "way railway=rail workrules=DE:BOStrab"; } way[railway][workrules="DE-EBO"] { throwError: "workrules: separate country and ruleset by : , not by -"; fixAdd: "workrules=DE:EBO"; suggestAlternative: "workrules=DE:EBO"; assertMatch: "way railway=rail workrules=DE-EBO"; assertNoMatch: "way railway=rail workrules=DE:EBO"; } /* ks and hl signals only exist as light signals */ node[railway=signal][railway:signal:main="DE-ESO:ks"][railway:signal:main:form!=light], node[railway=signal][railway:signal:distant="DE-ESO:ks"][railway:signal:distant:form!=light], node[railway=signal][railway:signal:combined="DE-ESO:ks"][railway:signal:combined:form!=light], node[railway=signal][railway:signal:main="DE-ESO:hl"][railway:signal:main:form!=light], node[railway=signal][railway:signal:distant="DE-ESO:hl"][railway:signal:distant:form!=light], node[railway=signal][railway:signal:combined="DE-ESO:hl"][railway:signal:combined:form!=light] { throwError: "{1.value} signals only exist as light signals"; fixAdd: "{2.key}=light"; assertMatch: "node railway=signal railway:signal:main=DE-ESO:ks"; assertMatch: "node railway=signal railway:signal:main=DE-ESO:ks railway:signal:main:form=semaphore"; assertMatch: "node railway=signal railway:signal:main=DE-ESO:hl"; assertMatch: "node railway=signal railway:signal:main=DE-ESO:hl railway:signal:main:form=semaphore"; assertNoMatch: "node railway=signal railway:signal:main=DE-ESO:hl railway:signal:main:form=light"; assertNoMatch: "node railway=signal railway:signal:main=DE-ESO:ks railway:signal:main:form=light"; } /* hp signals only exist as semaphore or light signals */ node[railway=signal][railway:signal:main="DE-ESO:hp"][railway:signal:main:form!=light][railway:signal:main:form!=semaphore], node[railway=signal][railway:signal:distant="DE-ESO:vr"][railway:signal:distant:form!=light][railway:signal:distant:form!=semaphore] { throwError: "hp signals only exist as semaphore or light signals"; assertMatch: "node railway=signal railway:signal:main=DE-ESO:hp"; assertMatch: "node railway=signal railway:signal:main=DE-ESO:hp railway:signal:main:form=typo"; assertNoMatch: "node railway=signal railway:signal:main=DE-ESO:hp railway:signal:main:form=semaphore"; assertNoMatch: "node railway=signal railway:signal:main=DE-ESO:hp railway:signal:main:form=light"; } /* KVB combined hp signals only exist as light signals */ node[railway=signal][railway:signal:combined="DE-KVB:hp"][railway:signal:combined:form!=light] { throwError: "KVB hp signals only exist as light signals"; assertMatch: "node railway=signal railway:signal:combined=DE-KVB:hp"; assertMatch: "node railway=signal railway:signal:combined=DE-KVB:hp railway:signal:combined:form=typo"; assertMatch: "node railway=signal railway:signal:combined=DE-KVB:hp railway:signal:combined:form=semaphore"; assertNoMatch: "node railway=signal railway:signal:combined=DE-KVB:hp railway:signal:combined:form=light"; assertNoMatch: "node railway=signal railway:signal:combined=DE-KVB:hp railway:signal:combined:form=light"; } /* Vr repeated signals only exist as light signals */ node[railway=signal]["railway:signal:distant"="DE-ESO:vr"]["railway:signal:distant:repeated"="yes"]["railway:signal:distant:form"!="light"] { throwError: "Vr repeated signals only exist as light signals"; assertMatch: "node railway=signal railway:signal:distant=DE-ESO:vr railway:signal:distant:repeated=yes railway:signal:distant:form=semaphore"; assertMatch: "node railway=signal railway:signal:distant=DE-ESO:vr railway:signal:distant:repeated=yes"; assertNoMatch: "node railway=signal railway:signal:distant=DE-ESO:vr railway:signal:distant:repeated=yes railway:signal:distant:form=light"; } /* German signal Gsp 2 was renamed to Wn 7 in 2008 */ node["railway:signal:minor:states"="DE-ESO:sh0;DE-ESO:gsp2"], node["railway:signal:minor:states"="sh0;gsp2"] { throwError: "Signal Gsp 2 was renamed to Wn 7 in 2008"; fixAdd: "railway:signal:minor:states=DE-ESO:sh0;DE-ESO:wn7"; suggestAlternative: "railway:signal:minor:states=DE-ESO:sh0;DE-ESO:wn7"; assertMatch: "node railway=derail railway:signal:minor:states=DE-ESO:sh0;DE-ESO:gsp2"; assertMatch: "node railway=signal railway:signal:minor:states=sh0;gsp2"; assertNoMatch: "node railway=derail railway:signal:minor:states=DE-ESO:sh0;DE-ESO:wn7"; assertNoMatch: "node railway=derail railway:signal:minor:states=DE-ESO:sh0;DE-ESO:sh1"; } /* German Ne 14 signs without railway:signal:train_protection:type=block_marker */ node["railway:signal:train_protection"="DE-ESO:ne14"]["railway:signal:train_protection:type"!=block_marker] { throwError: "Ne 14 sign requires additional tag railway:signal:train_protection:type=block_marker"; fixAdd: "railway:signal:train_protection:type=block_marker"; suggestAlternative: "railway:signal:train_protection:type=block_marker"; assertMatch: "node railway=signal railway:signal:train_protection=DE-ESO:ne14"; assertNoMatch: "node railway=signal railway:signal:train_protection=DE-ESO:ne14 railway:signal:train_protection:type=block_marker"; assertNoMatch: "node railway=signal railway:signal:main=DE-ESO:hp"; } /* a German distant signal can't be a repeated one if at the same pole as a main signal, as the prior distant * signal would refer to this main signal */ node["railway:signal:distant:repeated"="yes"]["railway:signal:main"="DE-ESO:hp"]["railway:signal:main:states"!~/^(.*;)?DE-ESO:kennlicht(;.*)?$/], node["railway:signal:distant:repeated"="yes"]["railway:signal:main"="DE-ESO:hp"]["railway:signal:main:states"~="DE-ESO:kennlicht"]["railway:signal:distant:shortened"="no"], node["railway:signal:distant:repeated"="yes"]["railway:signal:main"="DE-ESO:hp"]["railway:signal:main:states"~="DE-ESO:kennlicht"][!"railway:signal:distant:shortened"], node["railway:signal:distant:repeated"="yes"]["railway:signal:main"=~/^DE-ESO:/]["railway:signal:main"!="DE-ESO:hp"] { throwError: "main and repeated distant signal usually are not at the same place"; fixAdd: "railway:signal:distant:shortened=yes"; fixRemove: "railway:signal:distant:repeated"; suggestAlternative: "railway:signal:distant:shortened=yes"; assertMatch: "node railway=signal railway:signal:main=DE-ESO:hp railway:signal:distant=DE-ESO:vr railway:signal:distant:repeated=yes"; assertMatch: "node railway=signal railway:signal:main=DE-ESO:hp railway:signal:distant=DE-ESO:vr railway:signal:distant:repeated=yes railway:signal:main:states=DE-ESO:hp0;DE-ESO:hp1"; assertNoMatch: "node railway=signal railway:signal:main=DE-ESO:hp railway:signal:distant=DE-ESO:vr railway:signal:distant:repeated=yes railway:signal:main:states=DE-ESO:hp0;DE-ESO:kennlicht railway:signal:distant:shortened=yes"; assertNoMatch: "node railway=signal railway:signal:main=DE-ESO:hp railway:signal:distant=DE-ESO:vr railway:signal:distant:repeated=no"; assertNoMatch: "node railway=signal railway:signal:main=DE-ESO:hp railway:signal:distant=DE-ESO:vr"; assertNoMatch: "node railway=signal railway:signal:distant=DE-ESO:vr railway:signal:distant:repeated=yes"; } /* a German distant signal can't be both a repeated and a distant one. The only exception is H/V signals * for Halbregelabstand areas, determined by main signal at the same pole being able to show Kennlicht */ node["railway:signal:distant:repeated"="yes"]["railway:signal:distant:shortened"="yes"]["railway:signal:distant"=~/^DE-ESO:/]["railway:signal:distant"!="DE-ESO:vr"], node["railway:signal:distant:repeated"="yes"]["railway:signal:distant:shortened"="yes"]["railway:signal:distant"="DE-ESO:vr"][!"railway:signal:main"], node["railway:signal:distant:repeated"="yes"]["railway:signal:distant:shortened"="yes"]["railway:signal:main"]["railway:signal:main"!="DE-ESO:hp"], node["railway:signal:distant:repeated"="yes"]["railway:signal:distant:shortened"="yes"]["railway:signal:distant"="DE-ESO:vr"]["railway:signal:main"="DE-ESO:hp"]["railway:signal:main:states"!~/^(.*;)?DE-ESO:kennlicht(;.*)?$/] { throwError: "German distant signals can't be repeated and shortened at the same time"; assertMatch: "node railway=signal railway:signal:distant:repeated=yes railway:signal:distant:shortened=yes railway:signal:distant=DE-ESO:ks"; assertMatch: "node railway=signal railway:signal:distant:repeated=yes railway:signal:distant:shortened=yes railway:signal:distant=DE-ESO:vr"; assertMatch: "node railway=signal railway:signal:distant:repeated=yes railway:signal:distant:shortened=yes railway:signal:main=DE-ESO:hl"; assertMatch: "node railway=signal railway:signal:distant:repeated=yes railway:signal:distant:shortened=yes railway:signal:distant=DE-ESO:vr railway:signal:main=DE-ESO:hp"; assertMatch: "node railway=signal railway:signal:distant:repeated=yes railway:signal:distant:shortened=yes railway:signal:distant=DE-ESO:vr railway:signal:main=DE-ESO:hp railway:signal:main:states=DE-ESO:hp0;DE-ESO:hp1"; assertNoMatch: "node railway=signal railway:signal:distant=DE-ESO:ks railway:signal:distant:repeated=yes"; assertNoMatch: "node railway=signal railway:signal:distant=DE-ESO:ks railway:signal:distant:shortened=yes"; assertNoMatch: "node railway=signal railway:signal:distant=DE-ESO:vr railway:signal:distant:repeated=yes railway:signal:distant:shortened=yes railway:signal:main=DE-ESO:hp railway:signal:main:states=DE-ESO:kennlicht;DE-ESO:hp1"; assertNoMatch: "node railway=signal railway:signal:distant=DE-ESO:vr railway:signal:distant:repeated=yes"; assertNoMatch: "node railway=signal railway:signal:distant=DE-ESO:vr railway:signal:distant:shortened=yes"; } /* German Ks signals can't be distant and main at the same place */ node["railway:signal:main"="DE-ESO:ks"]["railway:signal:distant"], node["railway:signal:main"]["railway:signal:distant"="DE-ESO:ks"] { throwError: "German Ks signals can't have main and distant signal at the same place, try a combined signal instead"; assertMatch: "node railway=signal railway:signal:main=DE-ESO:ks railway:signal:distant=DE-ESO:vr"; assertMatch: "node railway=signal railway:signal:main=DE-ESO:hp railway:signal:distant=DE-ESO:ks"; assertNoMatch: "node railway=signal railway:signal:distant=DE-ESO:vr railway:signal:main=DE-ESO:hp"; assertNoMatch: "node railway=signal railway:signal:combined=DE-ESO:ks railway:signal:minor=DE-ESO:sh1"; } node[railway=signal]["railway:signal:minor"="DE-ESO:sh"]["railway:signal:minor:form"=semaphore]["railway:signal:minor:states"~="DE-ESO:hp0"] { throwError: "Sh semaphore signals cannot display Hp 0, but only Sh 0"; assertMatch: "node railway=signal railway:signal:minor=DE-ESO:sh railway:signal:minor:form=semaphore railway:signal:minor:states=DE-ESO:hp0"; assertMatch: "node railway=signal railway:signal:minor=DE-ESO:sh railway:signal:minor:form=semaphore railway:signal:minor:states=DE-ESO:hp0;DE-ESO:sh1"; assertNoMatch: "node railway=signal railway:signal:minor=DE-ESO:sh railway:signal:minor:form=light railway:signal:minor:states=DE-ESO:hp0"; assertNoMatch: "node railway=signal railway:signal:minor=DE-ESO:sh railway:signal:minor:form=light railway:signal:minor:states=DE-ESO:hp0;DE-ESO:sh1"; assertNoMatch: "node railway=signal railway:signal:minor=DE-ESO:sh railway:signal:minor:form=semaphore railway:signal:minor:states=DE-ESO:sh0"; assertNoMatch: "node railway=signal railway:signal:minor=DE-ESO:sh railway:signal:minor:form=semaphore railway:signal:minor:states=DE-ESO:sh0;DE-ESO:sh1"; } node[railway=signal]["railway:signal:minor"="DE-ESO:sh"]["railway:signal:minor:form"=light]["railway:signal:minor:states"~="DE-ESO:sh0"] { throwError: "Sh light signals cannot display Sh 0, but only Hp 0"; assertMatch: "node railway=signal railway:signal:minor=DE-ESO:sh railway:signal:minor:form=light railway:signal:minor:states=DE-ESO:sh0"; assertMatch: "node railway=signal railway:signal:minor=DE-ESO:sh railway:signal:minor:form=light railway:signal:minor:states=DE-ESO:sh0;DE-ESO:sh1"; assertNoMatch: "node railway=signal railway:signal:minor=DE-ESO:sh railway:signal:minor:form=light railway:signal:minor:states=DE-ESO:hp0"; assertNoMatch: "node railway=signal railway:signal:minor=DE-ESO:sh railway:signal:minor:form=light railway:signal:minor:states=DE-ESO:hp0;DE-ESO:sh1"; assertNoMatch: "node railway=signal railway:signal:minor=DE-ESO:sh railway:signal:minor:form=semaphore railway:signal:minor:states=DE-ESO:sh0"; assertNoMatch: "node railway=signal railway:signal:minor=DE-ESO:sh railway:signal:minor:form=semaphore railway:signal:minor:states=DE-ESO:sh0;DE-ESO:sh1"; } /* Check correct tagging of Zs3/Zs3v signs */ node[railway=signal]["railway:signal:speed_limit_distant"="DE-ESO:zs3v"]["railway:signal:speed_limit_distant:form"=sign]["railway:signal:speed_limit_distant:speed"]["railway:signal:speed_limit_distant:speed"!~/^[1-9][0-9]?[05]$/]["railway:signal:speed_limit_distant:speed"!=5]["railway:signal:speed_limit_distant:speed"!="?"], node[railway=signal]["railway:signal:speed_limit_distant"="DE-ESO:zs3v"]["railway:signal:speed_limit_distant:form"=sign]["railway:signal:speed_limit_distant:speed" > 160] { throwError: "Zs3v sign signals can only have a single speed, are a multiple of 5 and cannot be greater than 160"; assertMatch: "node railway=signal railway:signal:speed_limit_distant=\"DE-ESO:zs3v\" railway:signal:speed_limit_distant:form=sign railway:signal:speed_limit_distant:speed=foo"; assertMatch: "node railway=signal railway:signal:speed_limit_distant=\"DE-ESO:zs3v\" railway:signal:speed_limit_distant:form=sign railway:signal:speed_limit_distant:speed=05"; assertMatch: "node railway=signal railway:signal:speed_limit_distant=\"DE-ESO:zs3v\" railway:signal:speed_limit_distant:form=sign railway:signal:speed_limit_distant:speed=87"; assertMatch: "node railway=signal railway:signal:speed_limit_distant=\"DE-ESO:zs3v\" railway:signal:speed_limit_distant:form=sign railway:signal:speed_limit_distant:speed=200"; assertMatch: "node railway=signal railway:signal:speed_limit_distant=\"DE-ESO:zs3v\" railway:signal:speed_limit_distant:form=sign railway:signal:speed_limit_distant:speed=\"80;90\""; assertNoMatch: "node railway=signal railway:signal:speed_limit_distant=\"DE-ESO:zs3v\" railway:signal:speed_limit_distant:form=light railway:signal:speed_limit_distant:speed=foo"; assertNoMatch: "node railway=signal railway:signal:speed_limit_distant=\"DE-ESO:zs3v\" railway:signal:speed_limit_distant:form=light railway:signal:speed_limit_distant:speed=\"87\""; assertNoMatch: "node railway=signal railway:signal:speed_limit_distant=\"DE-ESO:zs3v\" railway:signal:speed_limit_distant:form=light railway:signal:speed_limit_distant:speed=\"80;90\""; assertNoMatch: "node railway=signal railway:signal:speed_limit_distant=\"DE-ESO:zs3v\" railway:signal:speed_limit_distant:form=sign railway:signal:speed_limit_distant:speed=5"; assertNoMatch: "node railway=signal railway:signal:speed_limit_distant=\"DE-ESO:zs3v\" railway:signal:speed_limit_distant:form=sign railway:signal:speed_limit_distant:speed=80"; assertNoMatch: "node railway=signal railway:signal:speed_limit_distant=\"DE-ESO:zs3v\" railway:signal:speed_limit_distant:form=sign railway:signal:speed_limit_distant:speed=85"; assertNoMatch: "node railway=signal railway:signal:speed_limit_distant=\"DE-ESO:zs3v\" railway:signal:speed_limit_distant:form=sign railway:signal:speed_limit_distant:speed=?"; } node[railway=signal]["railway:signal:speed_limit"="DE-ESO:zs3"]["railway:signal:speed_limit:form"=sign]["railway:signal:speed_limit:speed"]["railway:signal:speed_limit:speed"!~/^[1-9][0-9]?[05]$/]["railway:signal:speed_limit:speed"!=5]["railway:signal:speed_limit:speed"!="?"], node[railway=signal]["railway:signal:speed_limit"="DE-ESO:zs3"]["railway:signal:speed_limit:form"=sign]["railway:signal:speed_limit:speed" > 160] { throwError: "Zs3 sign signals can only have a single speed, are a multiple of 5 and cannot be greater than 160"; assertMatch: "node railway=signal railway:signal:speed_limit=\"DE-ESO:zs3\" railway:signal:speed_limit:form=sign railway:signal:speed_limit:speed=foo"; assertMatch: "node railway=signal railway:signal:speed_limit=\"DE-ESO:zs3\" railway:signal:speed_limit:form=sign railway:signal:speed_limit:speed=05"; assertMatch: "node railway=signal railway:signal:speed_limit=\"DE-ESO:zs3\" railway:signal:speed_limit:form=sign railway:signal:speed_limit:speed=87"; assertMatch: "node railway=signal railway:signal:speed_limit=\"DE-ESO:zs3\" railway:signal:speed_limit:form=sign railway:signal:speed_limit:speed=200"; assertMatch: "node railway=signal railway:signal:speed_limit=\"DE-ESO:zs3\" railway:signal:speed_limit:form=sign railway:signal:speed_limit:speed=\"80;90\""; assertNoMatch: "node railway=signal railway:signal:speed_limit=\"DE-ESO:zs3\" railway:signal:speed_limit:form=light railway:signal:speed_limit:speed=foo"; assertNoMatch: "node railway=signal railway:signal:speed_limit=\"DE-ESO:zs3\" railway:signal:speed_limit:form=light railway:signal:speed_limit:speed=87"; assertNoMatch: "node railway=signal railway:signal:speed_limit=\"DE-ESO:zs3\" railway:signal:speed_limit:form=light railway:signal:speed_limit:speed=\"80;90\""; assertNoMatch: "node railway=signal railway:signal:speed_limit=\"DE-ESO:zs3\" railway:signal:speed_limit:form=sign railway:signal:speed_limit:speed=5"; assertNoMatch: "node railway=signal railway:signal:speed_limit=\"DE-ESO:zs3\" railway:signal:speed_limit:form=sign railway:signal:speed_limit:speed=80"; assertNoMatch: "node railway=signal railway:signal:speed_limit=\"DE-ESO:zs3\" railway:signal:speed_limit:form=sign railway:signal:speed_limit:speed=85"; assertNoMatch: "node railway=signal railway:signal:speed_limit=\"DE-ESO:zs3\" railway:signal:speed_limit:form=sign railway:signal:speed_limit:speed=?"; } /* Check correct tagging of Zs3/Zs3v light signals */ node[railway=signal]["railway:signal:speed_limit_distant"="DE-ESO:zs3v"]["railway:signal:speed_limit:form"=light]["railway:signal:speed_limit_distant:speed"]["railway:signal:speed_limit_distant:speed"!~/^([1-9]0|1[0-6]0|off|\?)(;([1-9]0|1[0-6]0|off|\?))*$/] { throwError: "Zs3v light signal states should have the form 'speed[;speed …][;off][;?], speeds can only be multiples of 10"; assertMatch: "node railway=signal railway:signal:speed_limit_distant=\"DE-ESO:zs3v\" railway:signal:speed_limit:form=light railway:signal:speed_limit_distant:speed=foo"; assertMatch: "node railway=signal railway:signal:speed_limit_distant=\"DE-ESO:zs3v\" railway:signal:speed_limit:form=light railway:signal:speed_limit_distant:speed=85"; assertMatch: "node railway=signal railway:signal:speed_limit_distant=\"DE-ESO:zs3v\" railway:signal:speed_limit:form=light railway:signal:speed_limit_distant:speed=200"; assertMatch: "node railway=signal railway:signal:speed_limit_distant=\"DE-ESO:zs3v\" railway:signal:speed_limit:form=light railway:signal:speed_limit_distant:speed=\"80;foo\""; assertNoMatch: "node railway=signal railway:signal:speed_limit_distant=\"DE-ESO:zs3v\" railway:signal:speed_limit:form=light railway:signal:speed_limit_distant:speed=\"80\""; assertNoMatch: "node railway=signal railway:signal:speed_limit_distant=\"DE-ESO:zs3v\" railway:signal:speed_limit:form=light railway:signal:speed_limit_distant:speed=\"80;120\""; assertNoMatch: "node railway=signal railway:signal:speed_limit_distant=\"DE-ESO:zs3v\" railway:signal:speed_limit:form=light railway:signal:speed_limit_distant:speed=\"80;off\""; assertNoMatch: "node railway=signal railway:signal:speed_limit_distant=\"DE-ESO:zs3v\" railway:signal:speed_limit:form=light railway:signal:speed_limit_distant:speed=\"80;120;off;?\""; assertNoMatch: "node railway=signal railway:signal:speed_limit_distant=\"DE-ESO:zs3v\" railway:signal:speed_limit:form=light railway:signal:speed_limit_distant:speed=\"?;80;off;120\""; assertNoMatch: "node railway=signal railway:signal:speed_limit_distant=\"DE-ESO:zs3v\" railway:signal:speed_limit:form=light railway:signal:speed_limit_distant:speed=\"80;?\""; assertNoMatch: "node railway=signal railway:signal:speed_limit_distant=\"DE-ESO:zs3v\" railway:signal:speed_limit:form=light railway:signal:speed_limit_distant:speed=\"off;?\""; } node[railway=signal]["railway:signal:speed_limit"="DE-ESO:zs3"]["railway:signal:speed_limit:form"=light]["railway:signal:speed_limit:speed"]["railway:signal:speed_limit:speed"!~/^([1-9]0|1[0-6]0|off|\?)(;([1-9]0|1[0-6]0|off|\?))*$/] { throwError: "Zs3 light signal states should have the form 'speed[;speed …][;off][;?], speeds can only be multiples of 10"; assertMatch: "node railway=signal railway:signal:speed_limit=\"DE-ESO:zs3\" railway:signal:speed_limit:form=light railway:signal:speed_limit:speed=foo"; assertMatch: "node railway=signal railway:signal:speed_limit=\"DE-ESO:zs3\" railway:signal:speed_limit:form=light railway:signal:speed_limit:speed=85"; assertMatch: "node railway=signal railway:signal:speed_limit=\"DE-ESO:zs3\" railway:signal:speed_limit:form=light railway:signal:speed_limit:speed=200"; assertMatch: "node railway=signal railway:signal:speed_limit=\"DE-ESO:zs3\" railway:signal:speed_limit:form=light railway:signal:speed_limit:speed=\"80;foo\""; assertNoMatch: "node railway=signal railway:signal:speed_limit=\"DE-ESO:zs3\" railway:signal:speed_limit:form=light railway:signal:speed_limit:speed=\"80\""; assertNoMatch: "node railway=signal railway:signal:speed_limit=\"DE-ESO:zs3\" railway:signal:speed_limit:form=light railway:signal:speed_limit:speed=\"80;120\""; assertNoMatch: "node railway=signal railway:signal:speed_limit=\"DE-ESO:zs3\" railway:signal:speed_limit:form=light railway:signal:speed_limit:speed=\"80;off\""; assertNoMatch: "node railway=signal railway:signal:speed_limit=\"DE-ESO:zs3\" railway:signal:speed_limit:form=light railway:signal:speed_limit:speed=\"80;120;off;?\""; assertNoMatch: "node railway=signal railway:signal:speed_limit=\"DE-ESO:zs3\" railway:signal:speed_limit:form=light railway:signal:speed_limit:speed=\"?;80;off;120\""; assertNoMatch: "node railway=signal railway:signal:speed_limit=\"DE-ESO:zs3\" railway:signal:speed_limit:form=light railway:signal:speed_limit:speed=\"80;?\""; assertNoMatch: "node railway=signal railway:signal:speed_limit=\"DE-ESO:zs3\" railway:signal:speed_limit:form=light railway:signal:speed_limit:speed=\"off;?\""; } /* There are people that say Zs10 light signals have never existed in reality. */ node|z16-[railway=signal]["railway:signal:speed_limit"="DE-ESO:db:zs10"]["railway:signal:speed_limit:form"=light] { throwWarning: "It is unclear if Zs10 light signals have ever been placed, please double check."; assertMatch: "node railway=signal railway:signal:speed_limit=\"DE-ESO:db:zs10\" railway:signal:speed_limit:form=light"; assertNoMatch: "node railway=signal railway:signal:speed_limit=\"DE-ESO:db:zs1\" railway:signal:speed_limit:form=light"; assertNoMatch: "node railway=signal railway:signal:speed_limit=\"DE-ESO:db:zs10\" railway:signal:speed_limit:form=sign"; }