Skip to content

Commit f8f50df

Browse files
committed
Handle conditional access tags for time ranges
1 parent 4930d2e commit f8f50df

File tree

2 files changed

+87
-0
lines changed

2 files changed

+87
-0
lines changed

profiles/lib/access_conditional.lua

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
-- Handle conditional access tags as described in the OSM wiki:
2+
-- https://wiki.openstreetmap.org/wiki/Conditional_restrictions
3+
4+
-- Note that we only handle conditional tags for a date range,
5+
-- meant to be used for temporary restrictions, typically due to
6+
-- construction. We also require the date range to be at least a
7+
-- week long
8+
9+
10+
11+
ConditionalAccess = {}
12+
13+
14+
local function parse_conditional_access(way, key)
15+
local conditional = way:get_value_by_key(key .. ':conditional')
16+
if not conditional then
17+
return nil
18+
end
19+
20+
-- Examples of conditional tags: "no @ (2018 May 22-2018 Oct 7)
21+
-- or "no @ 2018 Jun 01-2018 Jul 23"
22+
local condition, time_range = conditional:match("([^@]+)@(.+)")
23+
if not condition or not time_range then
24+
return nil
25+
end
26+
27+
local start_date_str, end_date_str = time_range:match("([^-]+)-(.+)")
28+
if not start_date_str or not end_date_str then
29+
return nil
30+
end
31+
32+
local function parse_date(date_str)
33+
local year, month, day = date_str:match("(%d+)%s+(%a+)%s+(%d+)")
34+
35+
local month_names = {
36+
Jan = 1, Feb = 2, Mar = 3, Apr = 4, May = 5, Jun = 6,
37+
Jul = 7, Aug = 8, Sep = 9, Oct = 10, Nov = 11, Dec = 12
38+
}
39+
month = month_names[month]
40+
if not year or not month or not day then
41+
return nil
42+
end
43+
44+
local numericYear = tonumber(year)
45+
local numericDay = tonumber(day)
46+
if numericYear and numericDay then
47+
return os.time({ year = numericYear, month = month, day = numericDay })
48+
else
49+
return nil
50+
end
51+
end
52+
53+
local start_date = parse_date(start_date_str)
54+
local end_date = parse_date(end_date_str)
55+
local current_date = os.time()
56+
57+
-- Require start and end date to be more than a week apart
58+
if not start_date or not end_date or end_date - start_date < 60 * 60 * 24 * 7 then
59+
return nil
60+
end
61+
62+
if current_date >= start_date and current_date <= end_date then
63+
return condition:match("%S+")
64+
else
65+
return nil
66+
end
67+
end
68+
69+
function ConditionalAccess.parse_by_set(way, keys)
70+
for i, key in ipairs(keys) do
71+
local conditional = parse_conditional_access(way, key)
72+
if conditional then
73+
return conditional
74+
end
75+
end
76+
return nil
77+
end
78+
79+
return ConditionalAccess

profiles/lib/way_handlers.lua

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ local set_classification = require("lib/guidance").set_classification
99
local get_destination = require("lib/destination").get_destination
1010
local Tags = require('lib/tags')
1111
local Measure = require("lib/measure")
12+
local ConditionalAccess = require("lib/access_conditional")
1213

1314
WayHandlers = {}
1415

@@ -243,6 +244,13 @@ function WayHandlers.access(profile,way,result,data)
243244
data.forward_access, data.backward_access =
244245
Tags.get_forward_backward_by_set(way,data,profile.access_tags_hierarchy)
245246

247+
-- check for conditional access (roads that are temporarily closed, etc.)
248+
local conditional = ConditionalAccess.parse_by_set(way,profile.access_tags_hierarchy)
249+
if conditional then
250+
data.forward_access = conditional
251+
data.backward_access = conditional
252+
end
253+
246254
-- only allow a subset of roads to be treated as restricted
247255
if profile.restricted_highway_whitelist[data.highway] then
248256
if profile.restricted_access_tag_list[data.forward_access] then

0 commit comments

Comments
 (0)