Subject: [PATCH] #21286: Add validate rule min_height < height
---
Index: resources/data/validator/combinations.mapcss
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/resources/data/validator/combinations.mapcss b/resources/data/validator/combinations.mapcss
--- a/resources/data/validator/combinations.mapcss	(revision 18726)
+++ b/resources/data/validator/combinations.mapcss	(date 1683826537969)
@@ -47,6 +47,8 @@
 way[length_unit                ][!waterway],
 way[canal                      ][!waterway],
 way[have_riverbank             ][!waterway],
+area[min_height                ][!height][/^(building|building:part)$/], /* #21286 */
+area[building:min_level        ][!building:levels][/^(building|building:part)$/], /* #21286 */
 *[border_type                  ][!boundary],
 *[piste:difficulty             ][!piste:type],
 *[place                        ][!name][place!=islet][place!=plot][noname!=yes],
@@ -1075,4 +1077,13 @@
 *[voltage:primary][voltage:secondary][transformer=generator][tag("voltage:secondary")<tag("voltage:primary")] {
   throwWarning: tr("{0} is lower than {1} on {2}.", "{1.key}", "{0.key}", "{2.tag}");
   group: tr("suspicious tag combination");
-}
\ No newline at end of file
+}
+
+/* #21286 */
+area[/^(building|building:part)$/][height =~ /^[0-9]+(\.[0-9]+)?( m)?$/][min_height =~ /^[0-9]+(\.[0-9]+)?( m)?$/][get(split(" ", tag(height)), 0) <= get(split(" ", tag(min_height)), 0)],
+area[/^(building|building:part)$/][height =~ /^[0-9]+(\.[0-9]+)?\'?$/][min_height =~ /^[0-9]+(\.[0-9]+)?\'$/][replace(tag(height), "'", "") <= replace(tag(min_height), "'", "")],
+area[/^(building|building:part)$/][building:levels][building:min_level][tag("building:levels") <= tag("building:min_level")] {
+  throwWarning: tr("{0} is lower or equal to {1} on {2}", "{1.key}", "{2.key}", "{0.key}");
+  group: tr("suspicious tag combination");
+}
+
Index: resources/data/validator/numeric.mapcss
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/resources/data/validator/numeric.mapcss b/resources/data/validator/numeric.mapcss
--- a/resources/data/validator/numeric.mapcss	(revision 18726)
+++ b/resources/data/validator/numeric.mapcss	(date 1683827161122)
@@ -67,27 +67,27 @@
   assertNoMatch: "node building:levels=0"; /* valid because there can be building:levels:underground > 0 or roof:levels > 0 */
 }
 
-*[height][height =~ /^[0-9]+(\.[0-9]+)?(( )*(metre|metres|meter|meters|Metre|Metres|Meter|Meters)|m)$/] {
+*[height][height =~ /^[0-9]+(\.[0-9]+)?( *(metre|metres|meter|meters|Metre|Metres|Meter|Meters)|m)$/] {
   throwWarning: tr("unusual value of {0}: use abbreviation for unit and space between value and unit", "{0.key}");
   set height_meter_autofix;
-  fixAdd: concat("height=", get(regexp_match("([0-9.]+)( )*(.+)",tag("height")),1)," m");
+  fixAdd: concat("height=", get(regexp_match("([0-9.]+) *.+",tag("height")),1)," m");
   assertMatch: "node height=6.78 meters";
   assertMatch: "node height=5  metre";
   assertMatch: "node height=2m";
   assertNoMatch: "node height=2 m";
   assertNoMatch: "node height=5";
 }
-*[height][height =~ /^[0-9]+(\.[0-9]+)?(( )*(foot|Foot|feet|Feet)|ft)$/] {
+*[height][height =~ /^[0-9]+(\.[0-9]+)?( *(foot|Foot|feet|Feet|ft)| +')$/] {
   throwWarning: tr("unusual value of {0}: use abbreviation for unit and space between value and unit", "{0.key}");
   set height_foot_autofix;
-  fixAdd: concat("height=", get(regexp_match("([0-9.]+)( )*(.+)",tag("height")),1)," ft");
+  fixAdd: concat("height=", get(regexp_match("([0-9.]+) *.+",tag("height")),1),"'");
   assertMatch: "node height=6.78 foot";
   assertMatch: "node height=5  Feet";
   assertMatch: "node height=2ft";
-  assertNoMatch: "node height=2 ft";
+  assertNoMatch: "node height=2'";
   assertNoMatch: "node height=5";
 }
-*[height][height =~ /^[0-9]+,[0-9][0-9]?( (m|ft))?$/] {
+*[height][height =~ /^[0-9]+,[0-9][0-9]?( (m|ft)|')?$/] {
   throwWarning: tr("unusual value of {0}: use . instead of , as decimal separator", "{0.key}");
   fixAdd: concat("height=", replace(tag("height"), ",", "."));
   set height_separator_autofix;
@@ -100,70 +100,72 @@
   assertNoMatch: "node height=4";
 }
 
-*[maxheight][maxheight =~ /^[1-9][0-9]*(\.[0-9]+)?(( )*(metre|metres|meter|meters|Metre|Metres|Meter|Meters)|m)$/] {
+*[maxheight][maxheight =~ /^[1-9][0-9]*(\.[0-9]+)?( *(metre|metres|meter|meters|Metre|Metres|Meter|Meters)|m)$/] {
   throwWarning: tr("unusual value of {0}: use abbreviation for unit and space between value and unit", "{0.key}");
   set maxheight_meter_autofix;
-  fixAdd: concat("maxheight=", get(regexp_match("([0-9.]+)( )*(.+)",tag("maxheight")),1)," m");
+  fixAdd: concat("maxheight=", get(regexp_match("([0-9.]+) *.+",tag("maxheight")),1)," m");
   assertMatch: "node maxheight=6.78 meters";
   assertMatch: "node maxheight=5  metre";
   assertMatch: "node maxheight=2m";
   assertNoMatch: "node maxheight=2 m";
   assertNoMatch: "node maxheight=5";
 }
-*[maxheight][maxheight =~ /^[0-9]+(\.[0-9]+)?(( )*(foot|Foot|feet|Feet)|ft)$/] {
+*[maxheight][maxheight =~ /^[0-9]+(\.[0-9]+)?( *(foot|Foot|feet|Feet|ft)| +')$/] {
   throwWarning: tr("unusual value of {0}: use abbreviation for unit and space between value and unit", "{0.key}");
   set maxheight_foot_autofix;
-  fixAdd: concat("maxheight=", get(regexp_match("([0-9.]+)( )*(.+)",tag("maxheight")),1)," ft");
+  fixAdd: concat("maxheight=", get(regexp_match("([0-9.]+) *.+",tag("maxheight")),1),"'");
   assertMatch: "node maxheight=6.78 foot";
   assertMatch: "node maxheight=5  Feet";
   assertMatch: "node maxheight=2ft";
-  assertNoMatch: "node maxheight=2 ft";
+  assertNoMatch: "node maxheight=2'";
   assertNoMatch: "node maxheight=5";
 }
-*[maxheight][maxheight =~ /^[0-9]+,[0-9][0-9]?( (m|ft))?$/] {
+*[maxheight][maxheight =~ /^[0-9]+,[0-9][0-9]?( (m|ft)|')?$/] {
   throwWarning: tr("unusual value of {0}: use . instead of , as decimal separator", "{0.key}");
   fixAdd: concat("maxheight=", replace(tag("maxheight"), ",", "."));
   set maxheight_separator_autofix;
   assertMatch: "node maxheight=5,5";
   assertMatch: "node maxheight=12,00";
-  assertMatch: "node maxheight=12,5 ft";
+  assertMatch: "node maxheight=12,5'";
   assertNoMatch: "node maxheight=12,000";
   assertNoMatch: "node maxheight=3,50,5";
   assertNoMatch: "node maxheight=3.5";
   assertNoMatch: "node maxheight=4";
 }
 
-*[roof:height][roof:height =~ /^0*(\.0*)?( (m|ft))?$/][roof:shape=flat] {
+*[roof:height][roof:height =~ /^0*(\.0*)?( (m|ft)|')?$/][roof:shape=flat] {
   throwWarning: tr("{0} is unnecessary for {1}", "{0.tag}", "{2.tag}");
   group: tr("unnecessary tag");
   fixRemove: "{0.key}";
   set zero_roof_height_flat;
   assertMatch: "node roof:height=0 roof:shape=flat";
   assertMatch: "node roof:shape=flat roof:height=\"00.00000 ft\" roof:shape=flat";
+  assertMatch: "node roof:shape=flat roof:height=\"00.00000'\" roof:shape=flat";
   assertNoMatch: "node roof:shape=flat roof:height=2 m roof:shape=flat";
   assertNoMatch: "node roof:height=0 roof:shape=gabled";
 }
-*[roof:height][roof:height =~ /^[0-9]+(\.[0-9]+)?(( )*(metre|metres|meter|meters|Metre|Metres|Meter|Meters)|m)$/]!.zero_roof_height_flat {
+*[roof:height][roof:height =~ /^[0-9]+(\.[0-9]+)?( *(metre|metres|meter|meters|Metre|Metres|Meter|Meters)|m)$/]!.zero_roof_height_flat {
   throwWarning: tr("unusual value of {0}: use abbreviation for unit and space between value and unit", "{0.key}");
   set roof_height_meter_autofix;
-  fixAdd: concat("roof:height=", get(regexp_match("([0-9.]+)( )*(.+)",tag("roof:height")),1)," m");
+  fixAdd: concat("roof:height=", get(regexp_match("([0-9.]+) *.+",tag("roof:height")),1)," m");
   assertMatch: "node roof:height=6.78 meters";
   assertMatch: "node roof:height=5  metre";
   assertMatch: "node roof:height=2m";
   assertNoMatch: "node roof:height=2 m";
   assertNoMatch: "node roof:height=5";
 }
-*[roof:height][roof:height =~ /^[0-9]+(\.[0-9]+)?(( )*(foot|Foot|feet|Feet)|ft)$/]!.zero_roof_height_flat {
+*[roof:height][roof:height =~ /^[0-9]+(\.[0-9]+)?( *(foot|Foot|feet|Feet|ft)| +')$/]!.zero_roof_height_flat {
   throwWarning: tr("unusual value of {0}: use abbreviation for unit and space between value and unit", "{0.key}");
   set roof_height_foot_autofix;
-  fixAdd: concat("roof:height=", get(regexp_match("([0-9.]+)( )*(.+)",tag("roof:height")),1)," ft");
+  fixAdd: concat("roof:height=", get(regexp_match("([0-9.]+) *.+",tag("roof:height")),1),"'");
   assertMatch: "node roof:height=6.78 foot";
   assertMatch: "node roof:height=5  Feet";
   assertMatch: "node roof:height=2ft";
-  assertNoMatch: "node roof:height=2 ft";
+  assertMatch: "node roof:height=2 ft";
+  assertNoMatch: "node roof:height=2'";
   assertNoMatch: "node roof:height=5";
 }
-*[roof:height][roof:height =~ /^[0-9]+,[0-9][0-9]?( (m|ft))?$/] {
+*[roof:height][roof:height =~ /^[0-9]+,[0-9][0-9]?( (m|ft)|')?$/] {
   throwWarning: tr("unusual value of {0}: use . instead of , as decimal separator", "{0.key}");
   fixAdd: concat("roof:height=", replace(tag("roof:height"), ",", "."));
   set roof_height_separator_autofix;
@@ -176,27 +178,27 @@
   assertNoMatch: "node roof:height=4";
 }
 
-*[maxlength][maxlength =~ /^[1-9][0-9]*(\.[0-9]+)?(( )*(metre|metres|meter|meters|Metre|Metres|Meter|Meters)|m)$/] {
+*[maxlength][maxlength =~ /^[1-9][0-9]*(\.[0-9]+)?( *(metre|metres|meter|meters|Metre|Metres|Meter|Meters)|m)$/] {
   throwWarning: tr("unusual value of {0}: use abbreviation for unit and space between value and unit", "{0.key}");
   set maxlength_meter_autofix;
-  fixAdd: concat("maxlength=", get(regexp_match("([0-9.]+)( )*(.+)",tag("maxlength")),1)," m");
+  fixAdd: concat("maxlength=", get(regexp_match("([0-9.]+) *.+",tag("maxlength")),1)," m");
   assertMatch: "node maxlength=6.78 meters";
   assertMatch: "node maxlength=5  metre";
   assertMatch: "node maxlength=2m";
   assertNoMatch: "node maxlength=2 m";
   assertNoMatch: "node maxlength=5";
 }
-*[maxlength][maxlength =~ /^[0-9]+(\.[0-9]+)?(( )*(foot|Foot|feet|Feet)|ft)$/] {
+*[maxlength][maxlength =~ /^[0-9]+(\.[0-9]+)?( *(foot|Foot|feet|Feet|ft)| +')$/] {
   throwWarning: tr("unusual value of {0}: use abbreviation for unit and space between value and unit", "{0.key}");
   set maxlength_foot_autofix;
-  fixAdd: concat("maxlength=", get(regexp_match("([0-9.]+)( )*(.+)",tag("maxlength")),1)," ft");
+  fixAdd: concat("maxlength=", get(regexp_match("([0-9.]+) *.+",tag("maxlength")),1),"'");
   assertMatch: "node maxlength=6.78 foot";
   assertMatch: "node maxlength=5  Feet";
   assertMatch: "node maxlength=2ft";
-  assertNoMatch: "node maxlength=2 ft";
+  assertNoMatch: "node maxlength=2'";
   assertNoMatch: "node maxlength=5";
 }
-*[maxlength][maxlength =~ /^[0-9]+,[0-9][0-9]?( (m|ft))?$/] {
+*[maxlength][maxlength =~ /^[0-9]+,[0-9][0-9]?( (m|ft)|')?$/] {
   throwWarning: tr("unusual value of {0}: use . instead of , as decimal separator", "{0.key}");
   fixAdd: concat("maxlength=", replace(tag("maxlength"), ",", "."));
   set maxlength_separator_autofix;
@@ -219,17 +221,19 @@
   assertNoMatch: "node width=2 m";
   assertNoMatch: "node width=5";
 }
-*[width][width =~ /^[0-9]+(\.[0-9]+)?(( )*(foot|Foot|feet|Feet)|ft)$/] {
+*[width][width =~ /^[0-9]+(\.[0-9]+)?( *(foot|Foot|feet|Feet|ft)| +')$/] {
   throwWarning: tr("unusual value of {0}: use abbreviation for unit and space between value and unit", "{0.key}");
   set width_foot_autofix;
-  fixAdd: concat("width=", get(regexp_match("([0-9.]+)( )*(.+)",tag("width")),1)," ft");
+  fixAdd: concat("width=", get(regexp_match("([0-9.]+) *.+",tag("width")),1),"'");
   assertMatch: "node width=6.78 foot";
   assertMatch: "node width=5  Feet";
   assertMatch: "node width=2ft";
-  assertNoMatch: "node width=2 ft";
+  assertMatch: "node width=2 ft";
+  assertMatch: "node width=2 '";
+  assertNoMatch: "node width=2'";
   assertNoMatch: "node width=5";
 }
-*[width][width =~ /^[0-9]+,[0-9][0-9]?( (m|ft))?$/] {
+*[width][width =~ /^[0-9]+,[0-9][0-9]?( (m|ft)|')?$/] {
   throwWarning: tr("unusual value of {0}: use . instead of , as decimal separator", "{0.key}");
   fixAdd: concat("width=", replace(tag("width"), ",", "."));
   set width_separator_autofix;
@@ -241,27 +245,29 @@
   assertNoMatch: "node width=4";
 }
 
-*[maxwidth][maxwidth=~ /^[0-9]+(\.[0-9]+)?(( )*(metre|metres|meter|meters|Metre|Metres|Meter|Meters)|m)$/] {
+*[maxwidth][maxwidth=~ /^[0-9]+(\.[0-9]+)?( *(metre|metres|meter|meters|Metre|Metres|Meter|Meters)|m)$/] {
   throwWarning: tr("unusual value of {0}: use abbreviation for unit and space between value and unit", "{0.key}");
   set maxwidth_meter_autofix;
-  fixAdd: concat("maxwidth=", get(regexp_match("([0-9.]+)( )*(.+)",tag("maxwidth")),1)," m");
+  fixAdd: concat("maxwidth=", get(regexp_match("([0-9.]+) *.+",tag("maxwidth")),1)," m");
   assertMatch: "node maxwidth=6.78 meters";
   assertMatch: "node maxwidth=5  metre";
   assertMatch: "node maxwidth=2m";
   assertNoMatch: "node maxwidth=2 m";
   assertNoMatch: "node maxwidth=5";
 }
-*[maxwidth][maxwidth =~ /^[0-9]+(\.[0-9]+)?(( )*(foot|Foot|feet|Feet)|ft)$/] {
+*[maxwidth][maxwidth =~ /^[0-9]+(\.[0-9]+)?( *(foot|Foot|feet|Feet|ft)| +')$/] {
   throwWarning: tr("unusual value of {0}: use abbreviation for unit and space between value and unit", "{0.key}");
   set maxwidth_foot_autofix;
-  fixAdd: concat("maxwidth=", get(regexp_match("([0-9.]+)( )*(.+)",tag("maxwidth")),1)," ft");
+  fixAdd: concat("maxwidth=", get(regexp_match("([0-9.]+)( )*(.+)",tag("maxwidth")),1),"'");
   assertMatch: "node maxwidth=6.78 foot";
   assertMatch: "node maxwidth=5  Feet";
   assertMatch: "node maxwidth=2ft";
-  assertNoMatch: "node maxwidth=2 ft";
+  assertMatch: "node maxwidth=2 ft";
+  assertMatch: "node maxwidth=2 '";
+  assertNoMatch: "node maxwidth=2'";
   assertNoMatch: "node maxwidth=5";
 }
-*[maxwidth][maxwidth =~ /^[0-9]+,[0-9][0-9]?( (m|ft))?$/] {
+*[maxwidth][maxwidth =~ /^[0-9]+,[0-9][0-9]?( (m|ft)|')?$/] {
   throwWarning: tr("unusual value of {0}: use . instead of , as decimal separator", "{0.key}");
   fixAdd: concat("maxwidth=", replace(tag("maxwidth"), ",", "."));
   set maxwidth_separator_autofix;
@@ -299,6 +305,47 @@
   assertNoMatch: "node width=10'";
 }
 
+*[min_height][min_height =~ /^-?[0-9]+(\.[0-9]+)?( *(metre|metres|meter|meters|Metre|Metres|Meter|Meters)|m)$/] {
+  throwWarning: tr("unusual value of {0}: use abbreviation for unit and space between value and unit", "{0.key}");
+  fixAdd: concat("min_height=", get(regexp_match("(-?[0-9.]+) *.+",tag("min_height")),1)," m");
+  set min_height_meter_autofix;
+  assertMatch: "node min_height=6.78 meters";
+  assertMatch: "node min_height=5  metre";
+  assertMatch: "node min_height=2m";
+  assertNoMatch: "node min_height=2 m";
+  assertNoMatch: "node min_height=5";
+}
+*[min_height][min_height =~ /^-?[0-9]+(\.[0-9]+)?( *(foot|Foot|feet|Feet|ft)| +')$/] {
+  throwWarning: tr("unusual value of {0}: use abbreviation for unit and space between value and unit", "{0.key}");
+  fixAdd: concat("min_height=", get(regexp_match("(-?[0-9.]+)( )*(.+)",tag("min_height")),1),"'");
+  set min_height_foot_autofix;
+  assertMatch: "node min_height=6.78 foot";
+  assertMatch: "node min_height=5  Feet";
+  assertMatch: "node min_height=2ft";
+  assertMatch: "node min_height=2 ft";
+  assertMatch: "node min_height=2 '";
+  assertNoMatch: "node min_height=2'";
+  assertNoMatch: "node min_height=5";
+}
+*[min_height][min_height =~ /^-?[0-9]+,[0-9][0-9]?( (m|ft)|')?$/] {
+  throwWarning: tr("unusual value of {0}: use . instead of , as decimal separator", "{0.key}");
+  fixAdd: concat("min_height=", replace(tag("min_height"), ",", "."));
+  set min_height_separator_autofix;
+  assertMatch: "node min_height=5,5";
+  assertMatch: "node min_height=12,00";
+  assertMatch: "node min_height=12,5 ft";
+  assertMatch: "node min_height=12,5'";
+  assertNoMatch: "node min_height=12,000";
+  assertNoMatch: "node min_height=3,50,5";
+  assertNoMatch: "node min_height=3.5";
+  assertNoMatch: "node min_height=4";
+}
+*[min_height ][min_height  !~ /^(-?([0-9]+(\.[0-9]+)?( (m|ft))?)|(-?[1-9][0-9]*\'((10|11|[0-9])((\.[0-9]+)?)\")?))$/]!.min_height_separator_autofix!.min_height_meter_autofix!.min_height_foot_autofix {
+  throwWarning: tr("unusual value of {0}: {1} is default; point is decimal separator; if units, put space then unit", "{0.key}", tr("meters"));
+  assertMatch: "node min_height=\"12. m\"";
+  assertNoMatch: "node min_height=-5";
+}
+
 *[maxaxleload][maxaxleload =~ /^[0-9]+,[0-9][0-9]?( (t|kg|st|lbs))?$/] {
   throwWarning: tr("unusual value of {0}: use . instead of , as decimal separator", "{0.key}");
   fixAdd: concat("maxaxleload=", replace(tag("maxaxleload"), ",", "."));
