From 01e1beb3a03ab4c8eb5f7fb8f151cc7f387ad589 Mon Sep 17 00:00:00 2001 From: Moritz Kobitzsch Date: Thu, 17 Aug 2017 15:31:13 +0200 Subject: [PATCH 1/3] fix detection of suffix/prefix changes for name-changes --- CHANGELOG.md | 2 + features/guidance/continue.feature | 34 +++++ features/guidance/new-name.feature | 8 +- include/util/guidance/name_announcements.hpp | 138 ++++++++++++------- profiles/car.lua | 4 +- 5 files changed, 130 insertions(+), 56 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bd4c11ba1aa..6c424df24b4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,8 @@ - Guidance - Fixed some cases of sliproads pre-processing (https://github.com/Project-OSRM/osrm-backend/issues/4348) - don't suppress name announcements via sliproad handler + - Bugfixes + - Fixed a bug that would result in unnecessary instructions, due to problems in suffix/prefix detection # 5.12.0 - Changes from 5.11: diff --git a/features/guidance/continue.feature b/features/guidance/continue.feature index 249a34aad67..86ac2c3fe1d 100644 --- a/features/guidance/continue.feature +++ b/features/guidance/continue.feature @@ -22,6 +22,40 @@ Feature: Continue Instructions | a,c | abc,abc,abc | depart,continue left,arrive | | a,d | abc,bd,bd | depart,turn straight,arrive | + Scenario: Road turning left, Suffix changes + Given the node map + """ + c + a - b-d + """ + + And the ways + | nodes | highway | name | + | ab | primary | North Capitol Northeast | + | bc | primary | North Capitol Northwest | + | bd | primary | some random street | + + When I route I should get + | waypoints | route | turns | + | a,c | North Capitol Northeast,North Capitol Northwest,North Capitol Northwest | depart,continue left,arrive | + + Scenario: Road turning left, Suffix changes, no-spaces + Given the node map + """ + c + a - b-d + """ + + And the ways + | nodes | highway | name | + | ab | primary | North CapitolNortheast | + | bc | primary | North CapitolNorthwest | + | bd | primary | some random street | + + When I route I should get + | waypoints | route | turns | + | a,c | North CapitolNortheast,North CapitolNorthwest,North CapitolNorthwest | depart,continue left,arrive | + Scenario: Road turning left and straight Given the node map """ diff --git a/features/guidance/new-name.feature b/features/guidance/new-name.feature index 65aa386906e..9ab342eef39 100644 --- a/features/guidance/new-name.feature +++ b/features/guidance/new-name.feature @@ -274,8 +274,8 @@ Feature: New-Name Instructions | bc | Central Expressway | US 75 | motorway | When I route I should get - | waypoints | route | turns | - | a,c | North Central Expressway,Central Expressway,Central Expressway | depart,new name straight,arrive | + | waypoints | route | turns | + | a,c | North Central Expressway,Central Expressway | depart,arrive | Scenario: Prefix Change Given the node map @@ -289,8 +289,8 @@ Feature: New-Name Instructions | cb | Central Expressway | US 75 | motorway | When I route I should get - | waypoints | route | turns | - | c,a | Central Expressway,North Central Expressway,North Central Expressway | depart,new name straight,arrive | + | waypoints | route | turns | + | c,a | Central Expressway,North Central Expressway | depart,arrive | Scenario: No Name, Same Reference Given the node map diff --git a/include/util/guidance/name_announcements.hpp b/include/util/guidance/name_announcements.hpp index 15c738e2a82..2c3c3338aba 100644 --- a/include/util/guidance/name_announcements.hpp +++ b/include/util/guidance/name_announcements.hpp @@ -10,6 +10,7 @@ #include #include +#include #include #include @@ -25,17 +26,81 @@ namespace guidance // Name Change Logic // Used both during Extraction as well as during Post-Processing -inline std::pair getPrefixAndSuffix(const std::string &data) +inline std::string longest_common_substring(const std::string &lhs, const std::string &rhs) { - const auto suffix_pos = data.find_last_of(' '); - if (suffix_pos == std::string::npos) - return {}; - - const auto prefix_pos = data.find_first_of(' '); - auto result = std::make_pair(data.substr(0, prefix_pos), data.substr(suffix_pos + 1)); - boost::to_lower(result.first); - boost::to_lower(result.second); - return result; + if (lhs.empty() || rhs.empty()) + return ""; + + // array for dynamic programming + std::vector> dp(lhs.size(), + std::vector(rhs.size(), 0)); + + // to remember the best location + std::uint32_t best = 0; + std::uint32_t best_pos = 0; + + for (std::uint32_t i = 0; i < lhs.size(); ++i) + { + for (std::uint32_t j = 0; j < rhs.size(); ++j) + { + if (lhs[i] == rhs[j]) + { + dp[i][j] = (i == 0 || j == 0) ? 1 : (dp[i - 1][j - 1] + 1); + if (dp[i][j] > best) + { + best = dp[i][j]; + best_pos = i + 1; + } + } + } + } + // the best position marks the end of the string + return lhs.substr(best_pos - best, best); +} + +inline auto decompose(const std::string &lhs, const std::string &rhs) +{ + auto const lcs = longest_common_substring(lhs, rhs); + + // trim spaces, transform to lower + const auto trim = [](auto str) { + boost::to_lower(str); + auto front = str.find_first_not_of(" "); + + if (front == std::string::npos) + return str; + + auto back = str.find_last_not_of(" "); + return str.substr(front, back - front + 1); + }; + + if (lcs.empty()) + { + std::string empty = ""; + return std::make_tuple(trim(lhs), trim(rhs), empty, empty); + } + + // find the common substring in both + auto lhs_pos = lhs.find(lcs); + auto rhs_pos = rhs.find(lcs); + + BOOST_ASSERT(lhs_pos + lcs.size() <= lhs.size()); + BOOST_ASSERT(rhs_pos + lcs.size() <= rhs.size()); + + // prefixes + std::string lhs_prefix = (lhs_pos > 0) ? lhs.substr(0, lhs_pos) : ""; + std::string rhs_prefix = (rhs_pos > 0) ? rhs.substr(0, rhs_pos) : ""; + + // suffices + std::string lhs_suffix = lhs.substr(lhs_pos + lcs.size()); + std::string rhs_suffix = rhs.substr(rhs_pos + lcs.size()); + + lhs_prefix = trim(std::move(lhs_prefix)); + lhs_suffix = trim(std::move(lhs_suffix)); + rhs_prefix = trim(std::move(rhs_prefix)); + rhs_suffix = trim(std::move(rhs_suffix)); + + return std::make_tuple(lhs_prefix, lhs_suffix, rhs_prefix, rhs_suffix); } // Note: there is an overload without suffix checking below. @@ -64,51 +129,24 @@ inline bool requiresNameAnnounced(const std::string &from_name, const auto name_is_contained = boost::starts_with(from_name, to_name) || boost::starts_with(to_name, from_name); - const auto checkForPrefixOrSuffixChange = []( - const std::string &first, const std::string &second, const SuffixTable &suffix_table) { + const auto checkForPrefixOrSuffixChange = + [](const std::string &first, const std::string &second, const SuffixTable &suffix_table) { + std::string first_prefix, first_suffix, second_prefix, second_suffix; + std::tie(first_prefix, first_suffix, second_prefix, second_suffix) = + decompose(first, second); - const auto first_prefix_and_suffixes = getPrefixAndSuffix(first); - const auto second_prefix_and_suffixes = getPrefixAndSuffix(second); + const auto checkTable = [&](const std::string &str) { + // workaround for cucumber tests: + if (str.length() == 1 && (first.length() == 2 || second.length() == 2)) + return false; - // reverse strings, get suffices and reverse them to get prefixes - const auto checkTable = [&](const std::string &str) { - return str.empty() || suffix_table.isSuffix(str); - }; + return str.empty() || suffix_table.isSuffix(str); + }; - const auto getOffset = [](const std::string &str) -> std::size_t { - if (str.empty()) - return 0; - else - return str.length() + 1; + return checkTable(first_prefix) && checkTable(first_suffix) && + checkTable(second_prefix) && checkTable(second_suffix); }; - const bool is_prefix_change = [&]() -> bool { - if (!checkTable(first_prefix_and_suffixes.first)) - return false; - if (!checkTable(second_prefix_and_suffixes.first)) - return false; - return !first.compare(getOffset(first_prefix_and_suffixes.first), - std::string::npos, - second, - getOffset(second_prefix_and_suffixes.first), - std::string::npos); - }(); - - const bool is_suffix_change = [&]() -> bool { - if (!checkTable(first_prefix_and_suffixes.second)) - return false; - if (!checkTable(second_prefix_and_suffixes.second)) - return false; - return !first.compare(0, - first.length() - getOffset(first_prefix_and_suffixes.second), - second, - 0, - second.length() - getOffset(second_prefix_and_suffixes.second)); - }(); - - return is_prefix_change || is_suffix_change; - }; - const auto is_suffix_change = checkForPrefixOrSuffixChange(from_name, to_name, suffix_table); const auto names_are_equal = from_name == to_name || name_is_contained || is_suffix_change; const auto name_is_removed = !from_name.empty() && to_name.empty(); diff --git a/profiles/car.lua b/profiles/car.lua index d10afae0d18..d9ba3edfeff 100644 --- a/profiles/car.lua +++ b/profiles/car.lua @@ -34,9 +34,9 @@ function setup() speed_reduction = 0.8, turn_bias = 1.075, - -- a list of suffixes to suppress in name change instructions + -- a list of suffixes to suppress in name change instructions. The suffixes also include common substrings of each other suffix_list = { - 'N', 'NE', 'E', 'SE', 'S', 'SW', 'W', 'NW', 'North', 'South', 'West', 'East' + 'N', 'NE', 'E', 'SE', 'S', 'SW', 'W', 'NW', 'North', 'South', 'West', 'East', 'Nor', 'Sou', 'We', 'Ea' }, barrier_whitelist = Set { From bea57786d25fc9b75396319ca98790a8577308a6 Mon Sep 17 00:00:00 2001 From: Moritz Kobitzsch Date: Fri, 18 Aug 2017 15:38:56 +0200 Subject: [PATCH 2/3] fix pedantic warning about additional `;` --- src/extractor/way_restriction_map.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/extractor/way_restriction_map.cpp b/src/extractor/way_restriction_map.cpp index e4cfb178b8a..d4c121b584b 100644 --- a/src/extractor/way_restriction_map.cpp +++ b/src/extractor/way_restriction_map.cpp @@ -34,7 +34,7 @@ template auto asDuplicatedNode(const restriction_typ auto &way = restriction.AsWayRestriction(); // group restrictions by the via-way. On same via-ways group by from return std::tie(way.in_restriction.via, way.out_restriction.via, way.in_restriction.from); -}; +} template struct CompareByDuplicatedNode { From 93281d5a8e8f3f3f9af150be901682cf3716d5a3 Mon Sep 17 00:00:00 2001 From: Moritz Kobitzsch Date: Wed, 11 Oct 2017 11:07:43 +0200 Subject: [PATCH 3/3] remove workaround, reduce memory consumption in lcs computation --- features/car/conditional_restrictions.feature | 352 +++++++++--------- features/car/restrictions.feature | 262 ++++++------- include/util/guidance/name_announcements.hpp | 20 +- 3 files changed, 320 insertions(+), 314 deletions(-) diff --git a/features/car/conditional_restrictions.feature b/features/car/conditional_restrictions.feature index d2adb67e356..48db15b6117 100644 --- a/features/car/conditional_restrictions.feature +++ b/features/car/conditional_restrictions.feature @@ -17,27 +17,27 @@ Feature: Car - Turn restrictions Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493719200" Given the node map """ - n - p j e - s + a + d j b + c """ And the ways | nodes | oneway | - | nj | no | - | js | no | - | ej | yes | - | jp | yes | + | aj | no | + | jc | no | + | bj | yes | + | jd | yes | And the relations | type | way:from | way:to | node:via | restriction:conditional | - | restriction | ej | nj | j | only_right_turn @ (has_pygmies > 10 p) | + | restriction | bj | aj | j | only_right_turn @ (has_pygmies > 10 p) | When I route I should get | from | to | route | - | e | s | ej,js,js | - | e | n | ej,nj,nj | - | e | p | ej,jp,jp | + | b | c | bj,jc,jc | + | b | a | bj,aj,aj | + | b | d | bj,jd,jd | @no_turning @conditionals Scenario: Car - Restriction would be on, but the restriction was badly tagged @@ -48,29 +48,29 @@ Feature: Car - Turn restrictions Given the node map """ - n + a p | \ | j | \ - s m + c m """ And the ways | nodes | - | nj | - | js | + | aj | + | jc | | pjm | And the relations | type | way:from | way:to | node:via | restriction:conditional | - | restriction | nj | pjm | j | no_left_turn @ (Mo-Fr 07:00-10:30) | - | restriction | js | pjm | j | no_right_turn @ (Mo-Fr 07:00-10:30) | + | restriction | aj | pjm | j | no_left_turn @ (Mo-Fr 07:00-10:30) | + | restriction | jc | pjm | j | no_right_turn @ (Mo-Fr 07:00-10:30) | When I route I should get | from | to | route | - | n | m | nj,pjm,pjm | - | s | m | js,pjm,pjm | + | a | m | aj,pjm,pjm | + | c | m | jc,pjm,pjm | @no_turning @conditionals Scenario: Car - Restriction With Compressed Geometry @@ -149,29 +149,29 @@ Feature: Car - Turn restrictions Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493719200" Given the node map """ - n - p j e - s + a + d j b + c """ And the ways | nodes | oneway | - | nj | no | - | js | no | - | ej | no | - | jp | no | + | aj | no | + | jc | no | + | bj | no | + | jd | no | And the relations | type | way:from | way:to | node:via | restriction:conditional | except | - | restriction | ej | nj | j | only_right_turn @ (Mo-Su 08:00-12:00) | motorcar | - | restriction | jp | nj | j | only_left_turn @ (Mo-Su 08:00-12:00) | bus | + | restriction | bj | aj | j | only_right_turn @ (Mo-Su 08:00-12:00) | motorcar | + | restriction | jd | aj | j | only_left_turn @ (Mo-Su 08:00-12:00) | bus | When I route I should get | from | to | route | # | - | e | s | ej,js,js | | - | e | n | ej,nj,nj | restriction does not apply to cars | - | e | p | ej,jp,jp | | - | p | s | jp,nj,nj,js,js | restriction excepting busses still applies to cars | + | b | c | bj,jc,jc | | + | b | a | bj,aj,aj | restriction does not apply to cars | + | b | d | bj,jd,jd | | + | d | c | jd,aj,aj,jc,jc | restriction excepting busses still applies to cars | @no_turning @conditionals Scenario: Car - only_right_turn @@ -181,27 +181,27 @@ Feature: Car - Turn restrictions Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493719200" Given the node map """ - n - p j e - s + a + d j b + c """ And the ways | nodes | oneway | - | nj | no | - | js | no | - | ej | yes | - | jp | yes | + | aj | no | + | jc | no | + | bj | yes | + | jd | yes | And the relations | type | way:from | way:to | node:via | restriction:conditional | - | restriction | ej | nj | j | only_right_turn @ (Mo-Su 07:00-14:00) | + | restriction | bj | aj | j | only_right_turn @ (Mo-Su 07:00-14:00) | When I route I should get | from | to | route | - | e | s | ej,nj,nj,js,js | - | e | n | ej,nj,nj | - | e | p | ej,nj,nj,jp,jp | + | b | c | bj,aj,aj,jc,jc | + | b | a | bj,aj,aj | + | b | d | bj,aj,aj,jd,jd | @no_turning @conditionals Scenario: Car - No right turn @@ -211,27 +211,27 @@ Feature: Car - Turn restrictions Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493719200" Given the node map """ - n - p j e - s + a + d j b + c """ And the ways | nodes | oneway | - | nj | no | - | js | no | - | ej | yes | - | jp | yes | + | aj | no | + | jc | no | + | bj | yes | + | jd | yes | And the relations | type | way:from | way:to | node:via | restriction:conditional | - | restriction | ej | nj | j | no_right_turn @ (Mo-Fr 07:00-13:00) | + | restriction | bj | aj | j | no_right_turn @ (Mo-Fr 07:00-13:00) | When I route I should get | from | to | route | # | - | e | s | ej,js,js | normal turn | - | e | n | ej,js,js,nj,nj | avoids right turn | - | e | p | ej,jp,jp | normal maneuver | + | b | c | bj,jc,jc | normal turn | + | b | a | bj,jc,jc,aj,aj | avoids right turn | + | b | d | bj,jd,jd | normal maneuver | @only_turning @conditionals Scenario: Car - only_left_turn @@ -241,27 +241,27 @@ Feature: Car - Turn restrictions Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493719200" Given the node map """ - n - p j e - s + a + d j b + c """ And the ways | nodes | oneway | - | nj | no | - | js | no | - | ej | yes | - | jp | yes | + | aj | no | + | jc | no | + | bj | yes | + | jd | yes | And the relations | type | way:from | way:to | node:via | restriction:conditional | - | restriction | ej | js | j | only_left_turn @ (Mo-Fr 07:00-16:00) | + | restriction | bj | jc | j | only_left_turn @ (Mo-Fr 07:00-16:00) | When I route I should get | from | to | route | - | e | s | ej,js,js | - | e | n | ej,js,js,nj,nj | - | e | p | ej,js,js,jp,jp | + | b | c | bj,jc,jc | + | b | a | bj,jc,jc,aj,aj | + | b | d | bj,jc,jc,jd,jd | @no_turning @conditionals Scenario: Car - No left turn @@ -271,27 +271,27 @@ Feature: Car - Turn restrictions Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493719200" Given the node map """ - n - p j e - s + a + d j b + c """ And the ways | nodes | oneway | - | nj | no | - | js | no | - | ej | yes | - | jp | yes | + | aj | no | + | jc | no | + | bj | yes | + | jd | yes | And the relations | type | way:from | way:to | node:via | restriction:conditional | - | restriction | ej | js | j | no_left_turn @ (Mo-Su 00:00-23:59) | + | restriction | bj | jc | j | no_left_turn @ (Mo-Su 00:00-23:59) | When I route I should get | from | to | route | - | e | s | ej,nj,nj,js,js | - | e | n | ej,nj,nj | - | e | p | ej,jp,jp | + | b | c | bj,aj,aj,jc,jc | + | b | a | bj,aj,aj | + | b | d | bj,jd,jd | @no_turning @conditionals Scenario: Car - Conditional restriction is off @@ -301,27 +301,27 @@ Feature: Car - Turn restrictions Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493719200" Given the node map """ - n - p j e - s + a + d j b + c """ And the ways | nodes | oneway | - | nj | no | - | js | no | - | ej | yes | - | jp | yes | + | aj | no | + | jc | no | + | bj | yes | + | jd | yes | And the relations | type | way:from | way:to | node:via | restriction:conditional | - | restriction | ej | nj | j | no_right_turn @ (Mo-Su 16:00-20:00) | + | restriction | bj | aj | j | no_right_turn @ (Mo-Su 16:00-20:00) | When I route I should get | from | to | route | - | e | s | ej,js,js | - | e | n | ej,nj,nj | - | e | p | ej,jp,jp | + | b | c | bj,jc,jc | + | b | a | bj,aj,aj | + | b | d | bj,jd,jd | @no_turning @conditionals Scenario: Car - Conditional restriction is on @@ -331,27 +331,27 @@ Feature: Car - Turn restrictions Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493805600" Given the node map """ - n - p j e - s + a + d j b + c """ And the ways | nodes | oneway | - | nj | no | - | js | no | - | ej | yes | - | jp | yes | + | aj | no | + | jc | no | + | bj | yes | + | jd | yes | And the relations | type | way:from | way:to | node:via | restriction:conditional | - | restriction | ej | nj | j | no_right_turn @ (Mo-Fr 07:00-14:00) | + | restriction | bj | aj | j | no_right_turn @ (Mo-Fr 07:00-14:00) | When I route I should get | from | to | route | - | e | s | ej,js,js | - | e | n | ej,js,js,nj,nj | - | e | p | ej,jp,jp | + | b | c | bj,jc,jc | + | b | a | bj,jc,jc,aj,aj | + | b | d | bj,jd,jd | @no_turning @conditionals Scenario: Car - Conditional restriction with multiple time windows @@ -362,28 +362,28 @@ Feature: Car - Turn restrictions Given the node map """ - n + a p | \ | j | \ - s m + c m """ And the ways | nodes | oneway | - | nj | no | - | js | no | + | aj | no | + | jc | no | | jp | yes | | mj | yes | And the relations | type | way:from | way:to | node:via | restriction:conditional | - | restriction | nj | jp | j | no_right_turn @ (Mo-Fr 07:00-11:00,16:00-18:30) | + | restriction | aj | jp | j | no_right_turn @ (Mo-Fr 07:00-11:00,16:00-18:30) | When I route I should get | from | to | route | - | n | p | nj,js,js,jp,jp | + | a | p | aj,jc,jc,jp,jp | | m | p | mj,jp,jp | @no_turning @conditionals @@ -394,27 +394,27 @@ Feature: Car - Turn restrictions Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493719200" Given the node map """ - n - p j e - s + a + d j b + c """ And the ways | nodes | oneway | - | nj | no | - | js | no | - | ej | yes | - | jp | yes | + | aj | no | + | jc | no | + | bj | yes | + | jd | yes | And the relations | type | way:from | way:to | node:via | restriction:conditional | - | restriction | ej | nj | j | only_right_turn @ (Mo-Su 07:00-14:00) | + | restriction | bj | aj | j | only_right_turn @ (Mo-Su 07:00-14:00) | When I route I should get | from | to | route | - | e | s | ej,nj,nj,js,js | - | e | n | ej,nj,nj | - | e | p | ej,nj,nj,jp,jp | + | b | c | bj,aj,aj,jc,jc | + | b | a | bj,aj,aj | + | b | d | bj,aj,aj,jd,jd | @no_turning @conditionals Scenario: Car - No right turn @@ -424,27 +424,27 @@ Feature: Car - Turn restrictions Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493719200" Given the node map """ - n - p j e - s + a + d j b + c """ And the ways | nodes | oneway | - | nj | no | - | js | no | - | ej | yes | - | jp | yes | + | aj | no | + | jc | no | + | bj | yes | + | jd | yes | And the relations | type | way:from | way:to | node:via | restriction:conditional | - | restriction | ej | nj | j | no_right_turn @ (Mo-Fr 07:00-13:00) | + | restriction | bj | aj | j | no_right_turn @ (Mo-Fr 07:00-13:00) | When I route I should get | from | to | route | # | - | e | s | ej,js,js | normal turn | - | e | n | ej,js,js,nj,nj | avoids right turn | - | e | p | ej,jp,jp | normal maneuver | + | b | c | bj,jc,jc | normal turn | + | b | a | bj,jc,jc,aj,aj | avoids right turn | + | b | d | bj,jd,jd | normal maneuver | @only_turning @conditionals Scenario: Car - only_left_turn @@ -454,27 +454,27 @@ Feature: Car - Turn restrictions Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493719200" Given the node map """ - n - p j e - s + a + d j b + c """ And the ways | nodes | oneway | - | nj | no | - | js | no | - | ej | yes | - | jp | yes | + | aj | no | + | jc | no | + | bj | yes | + | jd | yes | And the relations | type | way:from | way:to | node:via | restriction:conditional | - | restriction | ej | js | j | only_left_turn @ (Mo-Fr 07:00-16:00) | + | restriction | bj | jc | j | only_left_turn @ (Mo-Fr 07:00-16:00) | When I route I should get | from | to | route | - | e | s | ej,js,js | - | e | n | ej,js,js,nj,nj | - | e | p | ej,js,js,jp,jp | + | b | c | bj,jc,jc | + | b | a | bj,jc,jc,aj,aj | + | b | d | bj,jc,jc,jd,jd | @no_turning @conditionals Scenario: Car - No left turn @@ -484,27 +484,27 @@ Feature: Car - Turn restrictions Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493719200" Given the node map """ - n - p j e - s + a + d j b + c """ And the ways | nodes | oneway | - | nj | no | - | js | no | - | ej | yes | - | jp | yes | + | aj | no | + | jc | no | + | bj | yes | + | jd | yes | And the relations | type | way:from | way:to | node:via | restriction:conditional | - | restriction | ej | js | j | no_left_turn @ (Mo-Su 00:00-23:59) | + | restriction | bj | jc | j | no_left_turn @ (Mo-Su 00:00-23:59) | When I route I should get | from | to | route | - | e | s | ej,nj,nj,js,js | - | e | n | ej,nj,nj | - | e | p | ej,jp,jp | + | b | c | bj,aj,aj,jc,jc | + | b | a | bj,aj,aj | + | b | d | bj,jd,jd | @no_turning @conditionals Scenario: Car - Conditional restriction is off @@ -514,27 +514,27 @@ Feature: Car - Turn restrictions Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493719200" Given the node map """ - n - p j e - s + a + d j b + c """ And the ways | nodes | oneway | - | nj | no | - | js | no | - | ej | yes | - | jp | yes | + | aj | no | + | jc | no | + | bj | yes | + | jd | yes | And the relations | type | way:from | way:to | node:via | restriction:conditional | - | restriction | ej | nj | j | no_right_turn @ (Mo-Su 16:00-20:00) | + | restriction | bj | aj | j | no_right_turn @ (Mo-Su 16:00-20:00) | When I route I should get | from | to | route | - | e | s | ej,js,js | - | e | n | ej,nj,nj | - | e | p | ej,jp,jp | + | b | c | bj,jc,jc | + | b | a | bj,aj,aj | + | b | d | bj,jd,jd | @no_turning @conditionals Scenario: Car - Conditional restriction is on @@ -544,27 +544,27 @@ Feature: Car - Turn restrictions Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493805600" Given the node map """ - n - p j e - s + a + d j b + c """ And the ways | nodes | oneway | - | nj | no | - | js | no | - | ej | yes | - | jp | yes | + | aj | no | + | jc | no | + | bj | yes | + | jd | yes | And the relations | type | way:from | way:to | node:via | restriction:conditional | - | restriction | ej | nj | j | no_right_turn @ (Mo-Fr 07:00-14:00) | + | restriction | jb | aj | j | no_right_turn @ (Mo-Fr 07:00-14:00) | When I route I should get | from | to | route | - | e | s | ej,js,js | - | e | n | ej,js,js,nj,nj | - | e | p | ej,jp,jp | + | b | c | bj,jc,jc | + | b | a | bj,jc,jc,aj,aj | + | b | d | bj,jd,jd | @no_turning @conditionals Scenario: Car - Conditional restriction with multiple time windows @@ -575,28 +575,28 @@ Feature: Car - Turn restrictions Given the node map """ - n + a p | \ | j | \ - s m + c m """ And the ways | nodes | oneway | - | nj | no | - | js | no | + | aj | no | + | jc | no | | jp | yes | | mj | yes | And the relations | type | way:from | way:to | node:via | restriction:conditional | - | restriction | nj | jp | j | no_right_turn @ (Mo-Fr 07:00-11:00,16:00-18:30) | + | restriction | aj | jp | j | no_right_turn @ (Mo-Fr 07:00-11:00,16:00-18:30) | When I route I should get | from | to | route | - | n | p | nj,js,js,jp,jp | + | a | p | aj,jc,jc,jp,jp | | m | p | mj,jp,jp | @restriction-way diff --git a/features/car/restrictions.feature b/features/car/restrictions.feature index ee325da23c1..ff6a4365027 100644 --- a/features/car/restrictions.feature +++ b/features/car/restrictions.feature @@ -11,27 +11,27 @@ Feature: Car - Turn restrictions Scenario: Car - No left turn Given the node map """ - n - w j e - s + a + d j b + c """ And the ways | nodes | oneway | - | sj | yes | - | nj | -1 | - | wj | -1 | - | ej | -1 | + | cj | yes | + | aj | -1 | + | dj | -1 | + | bj | -1 | And the relations | type | way:from | way:to | node:via | restriction | - | restriction | sj | wj | j | no_left_turn | + | restriction | cj | dj | j | no_left_turn | When I route I should get | from | to | route | - | s | w | | - | s | n | sj,nj,nj | - | s | e | sj,ej,ej | + | c | d | | + | c | a | cj,aj,aj | + | c | b | cj,bj,bj | @no_turning Scenario: Car - No straight on @@ -67,253 +67,259 @@ Feature: Car - Turn restrictions Scenario: Car - No right turn Given the node map """ - n - w j e - s + a + d j b + c """ And the ways | nodes | oneway | - | sj | yes | - | nj | -1 | - | wj | -1 | - | ej | -1 | + | cj | yes | + | aj | -1 | + | dj | -1 | + | bj | -1 | And the relations | type | way:from | way:to | node:via | restriction | - | restriction | sj | ej | j | no_right_turn | + | restriction | cj | bj | j | no_right_turn | When I route I should get | from | to | route | - | s | w | sj,wj,wj | - | s | n | sj,nj,nj | - | s | e | | + | c | d | cj,dj,dj | + | c | a | cj,aj,aj | + | c | b | | @no_turning Scenario: Car - No u-turn Given the node map """ - n - w j e - s + a + d j b + c """ And the ways | nodes | oneway | - | sj | yes | - | nj | -1 | - | wj | -1 | - | ej | -1 | + | cj | yes | + | aj | -1 | + | dj | -1 | + | bj | -1 | And the relations | type | way:from | way:to | node:via | restriction | - | restriction | sj | wj | j | no_u_turn | + | restriction | cj | dj | j | no_u_turn | When I route I should get | from | to | route | - | s | w | | - | s | n | sj,nj,nj | - | s | e | sj,ej,ej | + | c | d | | + | c | a | cj,aj,aj | + | c | b | cj,bj,bj | @no_turning Scenario: Car - Handle any no_* relation Given the node map """ - n - w j e - s + a + d j b + c """ And the ways | nodes | oneway | - | sj | yes | - | nj | -1 | - | wj | -1 | - | ej | -1 | + | cj | yes | + | aj | -1 | + | dj | -1 | + | bj | -1 | And the relations | type | way:from | way:to | node:via | restriction | - | restriction | sj | wj | j | no_weird_zigzags | + | restriction | cj | dj | j | no_weird_zigzags | When I route I should get | from | to | route | - | s | w | | - | s | n | sj,nj,nj | - | s | e | sj,ej,ej | + | c | d | | + | c | a | cj,aj,aj | + | c | b | cj,bj,bj | @only_turning Scenario: Car - Only left turn Given the node map """ - n - w j e - s + a + d j b + c """ And the ways | nodes | oneway | - | sj | yes | - | nj | -1 | - | wj | -1 | - | ej | -1 | + | cj | yes | + | aj | -1 | + | dj | -1 | + | bj | -1 | And the relations | type | way:from | way:to | node:via | restriction | - | restriction | sj | wj | j | only_left_turn | + | restriction | cj | dj | j | only_left_turn | + + When I route I should get + | from | to | route | + | c | a | | + | c | b | | + | c | d | cj,dj,dj | Scenario: Car - Only right turn, invalid Given the node map """ - n - w j e r - s + a + d j b r + c """ And the ways | nodes | oneway | - | sj | yes | - | nj | -1 | - | wj | -1 | - | ej | -1 | - | re | -1 | + | cj | yes | + | aj | -1 | + | dj | -1 | + | bj | -1 | + | rb | -1 | And the relations | type | way:from | way:to | node:via | restriction | - | restriction | sj | er | j | only_right_on | + | restriction | cj | br | j | only_right_on | When I route I should get | from | to | route | - | s | r | sj,ej,re,re | + | c | r | cj,bj,rb,rb | @only_turning Scenario: Car - Only right turn Given the node map """ - n - w j e - s + a + d j b + c """ And the ways | nodes | oneway | - | sj | yes | - | nj | -1 | - | wj | -1 | - | ej | -1 | + | cj | yes | + | aj | -1 | + | dj | -1 | + | bj | -1 | And the relations | type | way:from | way:to | node:via | restriction | - | restriction | sj | ej | j | only_right_turn | + | restriction | cj | bj | j | only_right_turn | When I route I should get | from | to | route | - | s | w | | - | s | n | | - | s | e | sj,ej,ej | + | c | d | | + | c | a | | + | c | b | cj,bj,bj | @only_turning Scenario: Car - Only straight on Given the node map """ - n - w j e - s + a + d j b + c """ And the ways | nodes | oneway | - | sj | yes | - | nj | -1 | - | wj | -1 | - | ej | -1 | + | cj | yes | + | aj | -1 | + | dj | -1 | + | bj | -1 | And the relations | type | way:from | way:to | node:via | restriction | - | restriction | sj | nj | j | only_straight_on | + | restriction | cj | aj | j | only_straight_on | When I route I should get | from | to | route | - | s | w | | - | s | n | sj,nj,nj | - | s | e | | + | c | d | | + | c | a | cj,aj,aj | + | c | b | | @no_turning Scenario: Car - Handle any only_* restriction Given the node map """ - n - w j e - s + a + d j b + c """ And the ways | nodes | oneway | - | sj | yes | - | nj | -1 | - | wj | -1 | - | ej | -1 | + | cj | yes | + | aj | -1 | + | dj | -1 | + | bj | -1 | And the relations | type | way:from | way:to | node:via | restriction | - | restriction | sj | nj | j | only_weird_zigzags | + | restriction | cj | aj | j | only_weird_zigzags | When I route I should get | from | to | route | - | s | w | | - | s | n | sj,nj,nj | - | s | e | | + | c | d | | + | c | a | cj,aj,aj | + | c | b | | @specific Scenario: Car - :hgv-qualified on a standard turn restriction Given the node map """ - n - w j e - s + a + d j b + c """ And the ways | nodes | oneway | - | sj | yes | - | nj | -1 | - | wj | -1 | - | ej | -1 | + | cj | yes | + | aj | -1 | + | dj | -1 | + | bj | -1 | And the relations | type | way:from | way:to | node:via | restriction:hgv | - | restriction | sj | nj | j | no_straight_on | + | restriction | cj | aj | j | no_straight_on | When I route I should get | from | to | route | - | s | w | sj,wj,wj | - | s | n | sj,nj,nj | - | s | e | sj,ej,ej | + | c | d | cj,dj,dj | + | c | a | cj,aj,aj | + | c | b | cj,bj,bj | @specific Scenario: Car - :motorcar-qualified on a standard turn restriction Given the node map """ - n - w j e - s + a + d j b + c """ And the ways | nodes | oneway | - | sj | yes | - | nj | -1 | - | wj | -1 | - | ej | -1 | + | cj | yes | + | aj | -1 | + | dj | -1 | + | bj | -1 | And the relations | type | way:from | way:to | node:via | restriction:motorcar | - | restriction | sj | nj | j | no_straight_on | + | restriction | cj | aj | j | no_straight_on | When I route I should get | from | to | route | - | s | w | sj,wj,wj | - | s | n | | - | s | e | sj,ej,ej | + | c | d | cj,dj,dj | + | c | a | | + | c | b | cj,bj,bj | @except Scenario: Car - Except tag and on no_ restrictions @@ -484,27 +490,27 @@ Feature: Car - Turn restrictions Scenario: Car - Ignore unrecognized restriction Given the node map """ - n - w j e - s + a + d j b + c """ And the ways | nodes | oneway | - | sj | yes | - | nj | -1 | - | wj | -1 | - | ej | -1 | + | cj | yes | + | aj | -1 | + | dj | -1 | + | bj | -1 | And the relations | type | way:from | way:to | node:via | restriction | - | restriction | sj | wj | j | yield | + | restriction | cj | dj | j | yield | When I route I should get | from | to | route | - | s | w | sj,wj,wj | - | s | n | sj,nj,nj | - | s | e | sj,ej,ej | + | c | d | cj,dj,dj | + | c | a | cj,aj,aj | + | c | b | cj,bj,bj | @restriction @compression Scenario: Restriction On Compressed Geometry diff --git a/include/util/guidance/name_announcements.hpp b/include/util/guidance/name_announcements.hpp index 2c3c3338aba..43b3cf64a1f 100644 --- a/include/util/guidance/name_announcements.hpp +++ b/include/util/guidance/name_announcements.hpp @@ -32,38 +32,42 @@ inline std::string longest_common_substring(const std::string &lhs, const std::s return ""; // array for dynamic programming - std::vector> dp(lhs.size(), - std::vector(rhs.size(), 0)); + std::vector dp_previous(rhs.size(), 0), dp_current(rhs.size(), 0); // to remember the best location std::uint32_t best = 0; std::uint32_t best_pos = 0; - + using std::swap; for (std::uint32_t i = 0; i < lhs.size(); ++i) { for (std::uint32_t j = 0; j < rhs.size(); ++j) { if (lhs[i] == rhs[j]) { - dp[i][j] = (i == 0 || j == 0) ? 1 : (dp[i - 1][j - 1] + 1); - if (dp[i][j] > best) + dp_current[j] = (j == 0) ? 1 : (dp_previous[j - 1] + 1); + if (dp_current[j] > best) { - best = dp[i][j]; + best = dp_current[j]; best_pos = i + 1; } } } + swap(dp_previous, dp_current); } // the best position marks the end of the string return lhs.substr(best_pos - best, best); } +// TODO US-ASCII support only, no UTF-8 support +// While UTF-8 might work in some cases, we do not guarantee full functionality inline auto decompose(const std::string &lhs, const std::string &rhs) { auto const lcs = longest_common_substring(lhs, rhs); // trim spaces, transform to lower const auto trim = [](auto str) { + // we compare suffixes based on this value, it might break UTF chars, but as long as we are + // consistent in handling, we do not create bad results boost::to_lower(str); auto front = str.find_first_not_of(" "); @@ -136,10 +140,6 @@ inline bool requiresNameAnnounced(const std::string &from_name, decompose(first, second); const auto checkTable = [&](const std::string &str) { - // workaround for cucumber tests: - if (str.length() == 1 && (first.length() == 2 || second.length() == 2)) - return false; - return str.empty() || suffix_table.isSuffix(str); };