diff --git a/profiles/car.lua b/profiles/car.lua index f67b29927..883633a6f 100644 --- a/profiles/car.lua +++ b/profiles/car.lua @@ -8,6 +8,7 @@ Handlers = require("lib/way_handlers") Relations = require("lib/relations") find_access_tag = require("lib/access").find_access_tag limit = require("lib/maxspeed").limit +Utils = require("lib/utils") function setup() return { @@ -398,22 +399,55 @@ function process_way(profile, way, result, relations) WayHandlers.run(profile, way, result, data, handlers, relations) -- now process relations data - local data = Relations.Merge(relations) - local direction = data["route_direction"] - if direction then - if result.ref then - if result.ref:len() > 0 then - result.ref = result.ref .. ' ' .. direction + local matched_refs = nil; + if result.ref then + matched_refs = Relations.MatchToRef(relations, result.ref) + + local ref = '' + for k ,v in pairs(matched_refs) do + if ref ~= '' then + ref = ref .. '; ' + end + + if v then + ref = ref .. k .. ' $' .. v else - result.ref = direction + print(ref) + ref = ref .. k end end + + result.ref = ref + -- count = 0 + -- for k, v in pairs(matched_refs) do + -- count = count + 1 + -- end + -- if count > 1 then + -- print('---', way:id()) + -- for k, v in pairs(matched_refs) do + -- print(k, v) + -- end + -- end end + + end function process_relation(profile, relation, result) local t = relation:get_value_by_key("type") + function add_extra_data(m) + local name = relation:get_value_by_key("name") + if name then + result[m]["route_name"] = name + end + + local ref = relation:get_value_by_key("ref") + if ref then + result[m]["route_ref"] = ref + end + end + if t == "route" then local route = relation:get_value_by_key("route") if route == "road" then @@ -422,6 +456,7 @@ function process_relation(profile, relation, result) local role = string.lower(m:role()) if role == "north" or role == "south" or role == "west" or role == "east" then result[m]["route_direction"] = role + add_extra_data(m) end end end @@ -433,6 +468,7 @@ function process_relation(profile, relation, result) for _, m in ipairs(relation:members()) do if m:role() == "forward" then result[m]["route_direction"] = direction + add_extra_data(m) end end end diff --git a/profiles/lib/relations.lua b/profiles/lib/relations.lua index f789a6dcb..30f27a27b 100644 --- a/profiles/lib/relations.lua +++ b/profiles/lib/relations.lua @@ -3,6 +3,8 @@ -- You can run a selection you find useful in your profile, -- or do you own processing if/when required. +Utils = require('lib/utils') + Relations = {} function Relations.Merge(relations) @@ -17,4 +19,82 @@ function Relations.Merge(relations) return result end +-- match ref values to relations data +function Relations.MatchToRef(relations, ref) + + function calculate_scores(refs, tag_value) + local tag_tokens = Set(Utils.tokenize_common(tag_value)) + local result = {} + for i, r in ipairs(refs) do + local ref_tokens = Utils.tokenize_common(r) + local score = 0 + + for _, t in ipairs(ref_tokens) do + if tag_tokens[t] then + if Utils.is_number(t) then + score = score + 2 + else + score = score + 1 + end + end + end + + result[r] = score + end + + return result + end + + local references = Utils.string_list_tokens(ref) + local result_match = {} + + for _, r in ipairs(references) do + result_match[r] = nil + end + + for _, rel in ipairs(relations) do + local name_scores = nil + local name_tokens = {} + local route_name = rel["route_name"] + if route_name then + name_scores = calculate_scores(references, route_name) + end + + local ref_scores = nil + local ref_tokens = {} + local route_ref = rel["route_ref"] + if route_ref then + ref_scores = calculate_scores(references, route_ref) + end + + -- merge scores + local direction = rel["route_direction"] + if direction then + local best_score = -1 + local best_ref = nil + + function find_best(scores) + if scores then + for k ,v in pairs(scores) do + if v > best_score then + best_ref = k + best_score = v + end + end + end + end + + find_best(name_scores) + find_best(ref_scores) + + if best_ref then + result_match[best_ref] = direction + end + end + + end + + return result_match +end + return Relations \ No newline at end of file diff --git a/profiles/lib/utils.lua b/profiles/lib/utils.lua new file mode 100644 index 000000000..5cc8157be --- /dev/null +++ b/profiles/lib/utils.lua @@ -0,0 +1,43 @@ +-- Profile functions to implement common algorithms of data processing +-- +-- You can run a selection you find useful in your profile, +-- or do you own processing if/when required. + +Utils = {} + +-- split string 'a; b; c' to table with values ['a', 'b', 'c'] +-- so it use just one separator ';' +function Utils.string_list_tokens(str) + result = {} + local idx = 0 + for s in str.gmatch(str, "([^;]*)") do + if s ~= nil and s ~= '' then + idx = idx + 1 + table.insert(result, idx, (s:gsub("^%s*(.-)%s*$", "%1"))) + end + end + + return result +end + +-- same as Utils.StringListTokens, but with many possible separators: +-- ',' | ';' | ' '| '(' | ')' +function Utils.tokenize_common(str) + result = {} + local idx = 0 + for s in str.gmatch(str, "%S+") do + if s ~= nil and s ~= '' then + idx = idx + 1 + table.insert(result, idx, (s:gsub("^%s*(.-)%s*$", "%1"))) + end + end + + return result +end + +-- returns true, if string contains a number +function Utils.is_number(str) + return (tonumber(str) ~= nil) +end + +return Utils \ No newline at end of file