@@ -25,8 +25,8 @@ themepark:add_table({
2525 { column = ' operator_wikidata' , type = ' text' },
2626 { column = ' related_law' , type = ' text' },
2727 { column = ' related_law_url' , type = ' text' },
28- { column = ' iucn' , type = ' text' }, -- tag "ref:IUCN"
2928 { column = ' iucn_level' , type = ' text' }, -- tag "iucn_level"
29+ { column = ' iucn' , type = ' text' }, -- IUCN category from iucn_level or protect_class
3030 { column = ' wdpa' , type = ' int' }, -- WDPA
3131 { column = ' capad_pa_id' , type = ' text' }, -- Collaborative Australian Protected Areas Database (CAPAD)
3232 { column = ' dtp_id' , type = ' text' }, -- DIGITIZE THE PLANET
@@ -37,58 +37,129 @@ themepark:add_table({
3737 name = ' protected_areas_errors' ,
3838 ids_type = ' area' ,
3939 geom = ' multipolygon' ,
40- columns = {
41- { column = ' errormsg' , type = ' text' , not_null = true },
40+ columns = themepark :columns ({
41+ { column = ' ecode' , type = ' text' , not_null = true },
42+ { column = ' emsg' , type = ' text' , not_null = true },
4243 { column = ' value' , type = ' text' },
43- }
44+ })
4445})
4546
47+ -- ---------------------------------------------------------------------------
48+
4649local get_qcode = function (wd )
4750 if wd and wd :match (' ^Q%d+$' ) then
4851 return wd
4952 end
5053 return nil
5154end
5255
56+ -- See https://en.wikipedia.org/wiki/IUCN_protected_area_categories
57+ local iucn_mapping = {
58+ -- these are the official levels
59+ [' IA' ] = ' IA' , -- strict nature reserve
60+ [' IB' ] = ' IB' , -- wilderness area
61+ [' II' ] = ' II' , -- national park
62+ [' III' ] = ' III' , -- natural monument or feature
63+ [' IV' ] = ' IV' , -- habitat or species management area
64+ [' V' ] = ' V' , -- protected landscape or seascape
65+ [' VI' ] = ' VI' , -- protected area with sustainable use of natural resources
66+
67+ -- these are different forms of the official levels
68+ [' Ia' ] = ' IA' ,
69+ [' Ib' ] = ' IB' ,
70+ [' 1a' ] = ' IA' ,
71+ [' 1b' ] = ' IB' ,
72+ [' 2' ] = ' II' ,
73+ [' 3' ] = ' III' ,
74+ [' 4' ] = ' IV' ,
75+ [' 5' ] = ' V' ,
76+ [' 6' ] = ' VI' ,
77+ }
78+
79+ local function valid_protect_class (pc )
80+ if pc == ' 1a' or pc == ' 1b' then
81+ return true
82+ end
83+ return pc :match (' ^%d%d?$' )
84+ end
85+
86+ -- ---------------------------------------------------------------------------
87+
88+ local error_messages = {
89+ dtp_id = ' invalid dtp_id (not a UUID)' ,
90+ iucn_level = ' invalid iucn_level' ,
91+ iucn_level_protect_class_mismatch = ' iucn_level tag does not match protect_class tag' ,
92+ operator_wikidata = ' invalid Q-item code for operator_wikidata tag' ,
93+ protect_class = ' invalid protect_class (allowed: 1a, 1b, 1-99)' ,
94+ ref_wdpa = ' invalid ref:WDPA tag (not an integer)' ,
95+ wikidata = ' invalid Q-item code for wikidata tag' ,
96+ }
97+
98+ local function add_error (ecode , value , geom , tags )
99+ themepark :insert (' protected_areas_errors' , {
100+ ecode = ecode ,
101+ emsg = error_messages [ecode ],
102+ value = value ,
103+ geom = geom ,
104+ }, tags )
105+ end
106+
107+ -- ---------------------------------------------------------------------------
108+
53109themepark :add_proc (' area' , function (object , data )
54110 local t = object .tags
55111 if t .boundary == ' protected_area'
56112 or t .boundary == ' national_park' or t .boundary == ' water_protection_area'
57113 or t .leisure == ' nature_reserve' or t .protected_area then
58114
115+ local geom = object :as_area ()
116+
59117 -- Check that wikidata tags contain syntactically valid Q codes
60118 -- https://www.wikidata.org/wiki/{wikidata_code}
61119 local wikidata_code = get_qcode (t .wikidata )
62120 local operator_wikidata_code = get_qcode (t .operator_wikidata )
63121
64122 if t .wikidata ~= wikidata_code then
65- themepark :insert (' protected_areas_errors' , {
66- errormsg = ' invalid Q-item code for wikidata tag' ,
67- value = t .wikidata
68- }, t )
123+ add_error (' wikidata' , t .wikidata , geom , t )
69124 end
70125 if t .operator_wikidata ~= operator_wikidata_code then
71- themepark :insert (' protected_areas_errors' , {
72- errormsg = ' invalid Q-item code for operator_wikidata tag' ,
73- value = t .operator_wikidata
74- }, t )
126+ add_error (' operator_wikidata' , t .operator_wikidata , geom , t )
127+ end
128+
129+ local iucn = iucn_mapping [t .iucn_level ]
130+ if t .iucn_level and iucn == nil then
131+ add_error (' iucn_level' , t .iucn_level , geom , t )
132+ end
133+
134+ if t .protect_class and not valid_protect_class (t .protect_class ) then
135+ add_error (' protect_class' , t .protect_class , geom , t )
136+ end
137+
138+ if iucn then
139+ if iucn_mapping [t .protect_class ] and iucn ~= iucn_mapping [t .protect_class ] then
140+ add_error (' iucn_level_protect_class_mismatch' , t .iucn_level .. ' <> ' .. t .protect_class , geom , t )
141+ end
142+ else
143+ iucn = iucn_mapping [t .protect_class ]
75144 end
76145
77146 -- WDPA is always an integer
78147 -- https://www.protectedplanet.net/{wdpa}
79148 local wdpa = t [' ref:WDPA' ]
80- if wdpa and wdpa :match (' ^%d+$' ) then
81- wdpa = tonumber (wdpa )
82- else
83- themepark :insert (' protected_areas_errors' , { errormsg = ' not a number in ref:WDPA tag' , value = wdpa }, t )
84- wdpa = nil
149+ if wdpa then
150+ if wdpa :match (' ^%d+$' ) then
151+ wdpa = tonumber (wdpa )
152+ else
153+ add_error (' ref_wdpa' , wdpa , geom , t )
154+ wdpa = nil
155+ end
85156 end
86157
87158 -- Digitize The Planet uses UUIDs
88159 -- https://content.digitizetheplanet.org/de/rules/show_protectedarea/{dtp_id}
89160 local dtp_id = t .dtp_id
90161 if dtp_id and not dtp_id :match (' ^[0-9a-f-]+$' ) then
91- themepark : insert ( ' protected_areas_errors ' , { errormsg = ' not a UUID in dtp_id tag ' , value = dtp_id } , t )
162+ add_error ( ' dtp_id ' , dtp_id , geom , t )
92163 end
93164
94165 local a = {
@@ -106,12 +177,12 @@ themepark:add_proc('area', function(object, data)
106177 operator_wikidata = operator_wikidata_code ,
107178 related_law = t .related_law ,
108179 related_law_url = t [' related_law:url' ],
109- iucn = t [' ref:IUCN' ],
110180 iucn_level = t .iucn_level ,
181+ iucn = iucn ,
111182 wdpa = wdpa ,
112183 capad_pa_id = t [' ref:capad:pa_id' ],
113184 dtp_id = dtp_id ,
114- geom = object : as_area () ,
185+ geom = geom ,
115186 }
116187
117188 themepark .themes .core .add_name (a , object )
0 commit comments