wiki:Rules/KeepRight
meta
{
  title: "KeepRight Checks";
  version: "1_2019-03-22";
  description: "Checks for errors based on KeepRight checks";
  author: "Dave Manzer";
  watch-modified: true;
  link: "https://www.keepright.at/";
  min-josm-version: 14481;  
}

/* Keep Right Checks for JOSM */

/* KeepRight dead ended oneways 040 */
way[highway] node:connection {
        set kr_node;
}

way[highway] node:in-downloaded-area {
        set kr_downloaded;
}

way[highway] node:new {
        set kr_new_node;
}

way[building] node:connection,
way[amenity=parking] node:connection,
way[amenity=parking_entrance] node:connection {
        set exception;
}

/* 040 Message: The first node (id $1) of this one-way is not connected to any other way */
way[oneway][oneway!=no][highway][highway!~/path|track|footway|construction/]!:closed!.kr_node.kr_downloaded >[index=1] node[noexit!=yes][amenity!=parking_entrance][amenity!=parking],
way[oneway][oneway!=no][highway][highway!~/path|track|footway|construction/]!:closed!.kr_node.kr_new_node >[index=1] node[noexit!=yes][amenity!=parking_entrance][amenity!=parking] {
        throwWarning: tr("040: dead ended oneway at first node");
        group: tr("KeepRight");
}

/* 041 Message: The last node (id $1) of this one-way is not connected to any other way */
way[oneway][oneway!=no][highway][highway!~/path|track|footway|construction/]!:closed!.kr_node.kr_downloaded >[index=-1] node[noexit!=yes][amenity!=parking_entrance][amenity!=parking],
way[oneway][oneway!=no][highway][highway!~/path|track|footway|construction/]!:closed!.kr_node.kr_new_node >[index=-1] node[noexit!=yes][amenity!=parking_entrance][amenity!=parking] {
        throwWarning: tr("041: dead ended oneway at last node");
        group: tr("KeepRight");
}

/* 042 Message: This node cannot be reached, because one-ways only lead away from here */
way[highway][oneway=yes] >[index!=1] node:connection {
        set con_042;
}

way[highway][oneway!=yes] node:connection {
        set hwycon_042;
}

way[highway][oneway=yes] node[noexit!=yes][amenity!=parking_entrance][amenity!=parking]:connection!.con_042!.hwycon_042.kr_downloaded!.exception {
        throwWarning: tr("042: This node cannot be reached. One-ways only lead away from here");
        group: tr("KeepRight");
}

/* oneway=-1 */
way[highway][oneway=yes] >[index=1] node:connection {
        set negative_oneway;
}

way[highway][!oneway] node:connection {
        set ow;
}

way[highway][oneway=-1] >[index=-1] node[noexit!=yes][amenity!=parking_entrance][amenity!=parking]:connection!.ow.negative_oneway!.con_042.kr_downloaded!.exception {
        throwWarning: tr("042: This node cannot be reached. One-ways only lead away from here");
        group: tr("KeepRight");
}

/* 043 Message: This node cannot be reached, because one-ways only lead to here */

way[highway][oneway=yes] >[index!=-1] node:connection {
        set con_043;
}

way[highway][oneway!=yes] node:connection {
        set hwycon_043;
}

way[highway][oneway=yes] node[noexit!=yes][amenity!=parking_entrance][amenity!=parking]:connection!.con_043!.hwycon_043.kr_downloaded!.exception {
        throwWarning: tr("043: You cannot escape from this node. One-ways only lead to here");
        group: tr("KeepRight");
}

/* oneway=-1 */ 

way[highway][oneway=yes] >[index=-1] node:connection {
        set negative_oneway2;
}


way[highway][oneway=-1] >[index=1] node[noexit!=yes][amenity!=parking_entrance][amenity!=parking]:connection!.ow.negative_oneway2!.con_043.kr_downloaded!.exception {
        throwWarning: tr("043: You cannot escape from this node. One-ways only lead to here");
        group: tr("KeepRight");
}

/* Keep Right/160 wrongly used railway crossing tag -- Partially Complete*/
/* Message: There are ways in different layers coming together in this railway crossing */

way[highway][layer][layer!=0] node:connection {
        set kr_160_1;
}

way[railway][!layer].kr_160_1 node[railway=level_crossing] {
        throwWarning: tr("160: wrongly used railway crossing tag - different layer tags on connecting ways");
        group: "KeepRight";
}

way[railway][layer] node:connection {
        set kr_160_1;
}

way[highway][!layer].kr_160_1 node[railway=level_crossing] {
        throwWarning: tr("160: wrongly used railway crossing tag - different layer tags on connecting ways");
        group: "KeepRight";
}
way[highway][layer=-5] node:connection,
way[railway][layer=-5] node:connection {
        set lyr_n5;
}

way[railway][layer][layer!=-5] node.lyr_n5[railway=level_crossing],
way[highway][layer][layer!=-5] node.lyr_n5[railway=level_crossing] {
        throwWarning: tr("160: wrongly used railway crossing tag - different layer tags on connecting ways");
        group: "KeepRight";
}

way[highway][layer=-4] node:connection,
way[railway][layer=-4] node:connection {
        set lyr_n4;
}

way[railway][layer][layer!=-4] node.lyr_n4[railway=level_crossing],
way[highway][layer][layer!=-4] node.lyr_n4[railway=level_crossing] {
        throwWarning: tr("160: wrongly used railway crossing tag - different layer tags on connecting ways");
        group: "KeepRight";
}

way[highway][layer=-3] node:connection,
way[railway][layer=-3] node:connection {
        set lyr_n3;
}

way[railway][layer][layer!=-3] node.lyr_n3[railway=level_crossing],
way[highway][layer][layer!=-3] node.lyr_n3[railway=level_crossing] {
        throwWarning: tr("160: wrongly used railway crossing tag - different layer tags on connecting ways");
        group: "KeepRight";
}

way[highway][layer=-2] node:connection,
way[railway][layer=-2] node:connection {
        set lyr_n2;
}

way[railway][layer][layer!=-2] node.lyr_n2[railway=level_crossing],
way[highway][layer][layer!=-2] node.lyr_n2[railway=level_crossing] {
        throwWarning: tr("160: wrongly used railway crossing tag - different layer tags on connecting ways");
        group: "KeepRight";
}

way[highway][layer=-1] node:connection,
way[railway][layer=-1] node:connection {
        set lyr_n1;
}

way[railway][layer][layer!=-1] node.lyr_n1[railway=level_crossing],
way[highway][layer][layer!=-1] node.lyr_n1[railway=level_crossing] {
        throwWarning: tr("160: wrongly used railway crossing tag - different layer tags on connecting ways");
        group: "KeepRight";
}

way[highway][layer=1] node:connection,
way[railway][layer=1] node:connection {
        set lyr_1;
}

way[railway][layer][layer!=1] node.lyr_1[railway=level_crossing],
way[highway][layer][layer!=1] node.lyr_1[railway=level_crossing] {
        throwWarning: tr("160: wrongly used railway crossing tag - different layer tags on connecting ways");
        group: "KeepRight";
} 

way[highway][layer=2] node:connection,
way[railway][layer=2] node:connection {
        set lyr_2;
}

way[railway][layer][layer!=2] node.lyr_2[railway=level_crossing],
way[highway][layer][layer!=2] node.lyr_2[railway=level_crossing] {
        throwWarning: tr("160: wrongly used railway crossing tag - different layer tags on connecting ways");
        group: "KeepRight";
}

way[highway][layer=3] node:connection,
way[railway][layer=3] node:connection {
        set lyr_3;
}

way[railway][layer][layer!=3] node.lyr_3[railway=level_crossing],
way[highway][layer][layer!=3] node.lyr_3[railway=level_crossing] {
        throwWarning: tr("160: wrongly used railway crossing tag - different layer tags on connecting ways");
        group: "KeepRight";
}

way[highway][layer=4] node:connection,
way[railway][layer=4] node:connection {
        set lyr_4;
}

way[railway][layer][layer!=4] node.lyr_4[railway=level_crossing],
way[highway][layer][layer!=4] node.lyr_4[railway=level_crossing] {
        throwWarning: tr("160: wrongly used railway crossing tag - different layer tags on connecting ways");
        group: "KeepRight";
}

way[highway][layer=5] node:connection,
way[railway][layer=5] node:connection {
        set lyr_5;
}

way[railway][layer][layer!=5] node.lyr_5[railway=level_crossing],
way[highway][layer][layer!=5] node.lyr_5[railway=level_crossing] {
        throwWarning: tr("160: wrongly used railway crossing tag - different layer tags on connecting ways");
        group: "KeepRight";
}

/* Message: There are ways tagged as tunnel or bridge coming together in this railway crossing */ 
way[highway][bridge] node:connection,
way[highway][tunnel] node:connection {
        set kr_160_2;
}

way[railway].kr_160_2 node[railway=level_crossing] {
        throwWarning: tr("160: wrongly used railway crossing tag - connection on bridge or tunnel");
        group: "KeepRight";
}

way[railway][bridge] node:connection,
way[railway][tunnel] node:connection {
        set kr_160_3;
}

way[highway].kr_160_3 node[railway=level_crossing] {
        throwWarning: tr("160: wrongly used railway crossing tag - connection on bridge or tunnel");
        group: "KeepRight";
}


/* Keep Right fixme tagged items - 170 */

*[fixme] {
        throwWarning: tr("170: fixme tagged items");
        group: "KeepRight";
}

*[name=~/(?i).*tbd/] {
        throwWarning: tr("170: fixme tagged items; change {0} value", "{0.key}");
        group: "KeepRight";
}

*[ref=~/(?i).*tbd/] {
        throwWarning: tr("170: fixme tagged items; change {0} value", "{0.key}");
        group: "KeepRight";
}


/* Keep Right layer conflicts 230 -- Partially Complete */

/* 231 mixed layers intersections */

way[highway][layer][layer!=0] node:connection {
        set kr_230_connection;
}

way[highway][layer] >[index=-1] node,
way[highway][layer] >[index=1] node {
        set fl_node230;
}

way[highway][!layer] node!.fl_node230.kr_230_connection {
        throwWarning: tr("231: layer conflicts; mixed layer intersection");
        group: "KeepRight";
}

way[highway][layer=-5] node:connection {
        set lyrn5;
}

way[highway][layer][layer!=-5] node!.fl_node230.lyrn5 {
        throwWarning: tr("231: layer conflicts; mixed layer intersection");
        group: "KeepRight";
}

way[highway][layer=-4] node:connection {
        set lyrn4;
}

way[highway][layer][layer!=-4] node!.fl_node230.lyrn4 {
        throwWarning: tr("231: layer conflicts; mixed layer intersection");
        group: "KeepRight";
}


way[highway][layer=-3] node:connection {
        set lyrn3;
}

way[highway][layer][layer!=-3] node!.fl_node230.lyrn3 {
        throwWarning: tr("231: layer conflicts; mixed layer intersection");
        group: "KeepRight";
}

way[highway][layer=-2] node:connection {
        set lyrn2;
}

way[highway][layer][layer!=-2] node!.fl_node230.lyrn2 {
        throwWarning: tr("231: layer conflicts; mixed layer intersection");
        group: "KeepRight";
}

way[highway][layer=-1] node:connection {
        set lyrn1;
}

way[highway][layer][layer!=-1] node!.fl_node230.lyrn1 {
        throwWarning: tr("231: layer conflicts; mixed layer intersection");
        group: "KeepRight";
}

way[highway][layer=1] node:connection {
        set lyr1;
}

way[highway][layer][layer!=1] node!.fl_node230.lyr1 {
        throwWarning: tr("231: layer conflicts; mixed layer intersection");
        group: "KeepRight";
}

way[highway][layer=2] node:connection {
        set lyr2;
}

way[highway][layer][layer!=2] node!.fl_node230.lyr2 {
        throwWarning: tr("231: layer conflicts; mixed layer intersection");
        group: "KeepRight";
}

way[highway][layer=3] node:connection {
        set lyr3;
}

way[highway][layer][layer!=3] node!.fl_node230.lyr3 {
        throwWarning: tr("231: layer conflicts; mixed layer intersection");
        group: "KeepRight";
}

way[highway][layer=4] node:connection {
        set lyr4;
}

way[highway][layer][layer!=4] node!.fl_node230.lyr4 {
        throwWarning: tr("231: layer conflicts; mixed layer intersection");
        group: "KeepRight";
}

way[highway][layer=5] node:connection {
        set lyr5;
}

way[highway][layer][layer!=5] node!.fl_node230.lyr5 {
        throwWarning: tr("231: layer conflicts; mixed layer intersection");
        group: "KeepRight";
}

/* 232 strange layer */

way[bridge][layer ^= "-"] {
        throwWarning: tr("232: strange layer; {0} with negative layer", "{0.key}");
        group: "KeepRight";
}

way[tunnel][layer][layer!~/-/] {
        throwWarning: tr("232: strange layer; {0} with positive layer", "{0.key}");
        group: "KeepRight";
}

/* Keep Right motorways connected directly 270 */
/* Message: This node is a junction of a motorway and a highway other than motorway, motorway_link, trunk, rest_area or construction. 
Service or unclassified is only valid if it has access=no/private or if it is a service=parking_aisle. */

way[highway=motorway] >[index=1] node:connection,
way[highway=motorway] >[index=-1] node:connection {
        set kr_270_end_motorway;
}

way[highway][highway!=motorway] node:connection {
        set hwycon270;
}

/* allowed junctions */
way[highway=service][access=no] node:connection,
way[highway=service][access=private] node:connection,
way[highway=service][service=parking_aisle] node:connection,
way[highway=unclassified][access=no] node:connection,
way[highway=unclassified][access=private] node:connection,
way[highway=unclassified][service=parking_aisle] node:connection,
way[highway=motorway_link] node:connection,
way[highway=motorway_junction] node:connection,
way[highway=construction] node:connection,
way[highway=proposed] node:connection {
        set kr_270_allowed;
}

way[highway=motorway] node:connection.hwycon270!.kr_270_allowed!.kr_270_end_motorway {
        throwWarning: tr("270: motorways connected directly");
        group: "KeepRight";
}

/* KeepRight missing maxspeed 300 */
/* Message: missing maxspeed tag */
way[highway=~/^(motorway|trunk|primary|secondary)$/][junction!=roundabout][!bridge][!tunnel][!maxspeed] {
        throwOther: tr("300: missing maxspeed on major road");
        group: "KeepRight";
}

/* Building Crossing Highway Atlas Check */

way[highway][highway=~/^(motorway|trunk|primary|secondary|tertiary|unclassified|residential|service|motorway_link|trunk_link|primary_link|secondary_link|tertiary_link|living_street|track|road)$/] node:connection {
        set atlas_highway;
}

way[highway][tunnel=yes] node:connection,
way[highway][tunnel=building_passage] node:connection,
way[highway][covered=yes] node:connection,
way[highway][indoor=yes] node:connection,
way[highway][service=driveway] node:connection {
        set atlas_allowed;
}

*[building][building!=roof][amenity!=fuel].atlas_highway!.atlas_allowed node[amenity!=parking_entrance][amenity!=parking][!barrier][entrance!=yes] {
        throwWarning: tr("Building Road Intersection Check: building connected to road");
        group: tr("Atlas");
}

Rules_KeepRight.validator.mapcss, Rules_KeepRight.zip

Last modified 2 months ago Last modified on 2019-03-22T16:35:14+01:00