diff --git a/base/stl_helpers.hpp b/base/stl_helpers.hpp index 7f39e39a59..2130dd03d7 100644 --- a/base/stl_helpers.hpp +++ b/base/stl_helpers.hpp @@ -131,4 +131,10 @@ impl::Equals EqualsBy(T (C::*p)() const) { return impl::Equals(p); } + +template +typename std::underlying_type::type Key(T value) +{ + return static_cast::type>(value); +} } // namespace my diff --git a/drape_frontend/apply_feature_functors.cpp b/drape_frontend/apply_feature_functors.cpp index 9228ed0a41..4abac4082c 100644 --- a/drape_frontend/apply_feature_functors.cpp +++ b/drape_frontend/apply_feature_functors.cpp @@ -14,6 +14,7 @@ #include "indexer/drules_include.hpp" #include "indexer/map_style_reader.hpp" #include "indexer/osm_editor.hpp" +#include "indexer/road_shields_parser.hpp" #include "geometry/clipping.hpp" @@ -22,6 +23,7 @@ #include "drape/utils/projection.hpp" #include "base/logging.hpp" +#include "base/stl_helpers.hpp" #include #include @@ -256,11 +258,10 @@ bool IsColoredRoadShield(ftypes::RoadShield const & shield) { return shield.m_type == ftypes::RoadShieldType::Default || shield.m_type == ftypes::RoadShieldType::UK_Highway || - shield.m_type == ftypes::RoadShieldType::UK_Motorway || - shield.m_type == ftypes::RoadShieldType::Russia_Highway || - shield.m_type == ftypes::RoadShieldType::Euro_Motorway || - shield.m_type == ftypes::RoadShieldType::France_Motorway || - shield.m_type == ftypes::RoadShieldType::France_Departmental; + shield.m_type == ftypes::RoadShieldType::Generic_Blue || + shield.m_type == ftypes::RoadShieldType::Generic_Green || + shield.m_type == ftypes::RoadShieldType::Generic_Red || + shield.m_type == ftypes::RoadShieldType::Generic_Orange; } dp::FontDecl GetRoadShieldTextFont(MapStyle const & style, dp::FontDecl const & baseFont, @@ -272,17 +273,15 @@ dp::FontDecl GetRoadShieldTextFont(MapStyle const & style, dp::FontDecl const & using ftypes::RoadShieldType; static std::unordered_map kColors = { - {static_cast(RoadShieldType::Euro_Motorway), df::RoadShieldWhiteText}, - {static_cast(RoadShieldType::UK_Motorway), df::RoadShieldWhiteText}, - {static_cast(RoadShieldType::UK_Highway), df::RoadShieldUKYellowText}, - {static_cast(RoadShieldType::US_Interstate), df::RoadShieldWhiteText}, - {static_cast(RoadShieldType::US_Highway), df::RoadShieldBlackText}, - {static_cast(RoadShieldType::Russia_Highway), df::RoadShieldWhiteText}, - {static_cast(RoadShieldType::France_Motorway), df::RoadShieldWhiteText}, - {static_cast(RoadShieldType::France_Departmental), df::RoadShieldBlackText} - }; + {my::Key(RoadShieldType::Generic_Green), df::RoadShieldWhiteText}, + {my::Key(RoadShieldType::Generic_Blue), df::RoadShieldWhiteText}, + {my::Key(RoadShieldType::UK_Highway), df::RoadShieldUKYellowText}, + {my::Key(RoadShieldType::US_Interstate), df::RoadShieldWhiteText}, + {my::Key(RoadShieldType::US_Highway), df::RoadShieldBlackText}, + {my::Key(RoadShieldType::Generic_Red), df::RoadShieldWhiteText}, + {my::Key(RoadShieldType::Generic_Orange), df::RoadShieldBlackText}}; - auto it = kColors.find(static_cast(shield.m_type)); + auto it = kColors.find(my::Key(shield.m_type)); if (it != kColors.end()) f.m_color = df::GetColorConstant(style, it->second); @@ -295,15 +294,13 @@ dp::Color GetRoadShieldColor(MapStyle const & style, dp::Color const & baseColor using ftypes::RoadShieldType; static std::unordered_map kColors = { - {static_cast(RoadShieldType::Euro_Motorway), df::RoadShieldGreenBackground}, - {static_cast(RoadShieldType::UK_Motorway), df::RoadShieldBlueBackground}, - {static_cast(RoadShieldType::UK_Highway), df::RoadShieldGreenBackground}, - {static_cast(RoadShieldType::Russia_Highway), df::RoadShieldBlueBackground}, - {static_cast(RoadShieldType::France_Motorway), df::RoadShieldRedBackground}, - {static_cast(RoadShieldType::France_Departmental), df::RoadShieldOrangeBackground} - }; + {my::Key(RoadShieldType::Generic_Green), df::RoadShieldGreenBackground}, + {my::Key(RoadShieldType::Generic_Blue), df::RoadShieldBlueBackground}, + {my::Key(RoadShieldType::UK_Highway), df::RoadShieldGreenBackground}, + {my::Key(RoadShieldType::Generic_Red), df::RoadShieldRedBackground}, + {my::Key(RoadShieldType::Generic_Orange), df::RoadShieldOrangeBackground}}; - auto it = kColors.find(static_cast(shield.m_type)); + auto it = kColors.find(my::Key(shield.m_type)); if (it != kColors.end()) return df::GetColorConstant(style, it->second); @@ -313,10 +310,9 @@ dp::Color GetRoadShieldColor(MapStyle const & style, dp::Color const & baseColor float GetRoadShieldOutlineWidth(float baseWidth, ftypes::RoadShield const & shield) { if (shield.m_type == ftypes::RoadShieldType::UK_Highway || - shield.m_type == ftypes::RoadShieldType::UK_Motorway || - shield.m_type == ftypes::RoadShieldType::Russia_Highway || - shield.m_type == ftypes::RoadShieldType::Euro_Motorway || - shield.m_type == ftypes::RoadShieldType::France_Motorway) + shield.m_type == ftypes::RoadShieldType::Generic_Blue || + shield.m_type == ftypes::RoadShieldType::Generic_Green || + shield.m_type == ftypes::RoadShieldType::Generic_Red) return 0.0f; return baseWidth; diff --git a/drape_frontend/apply_feature_functors.hpp b/drape_frontend/apply_feature_functors.hpp index a03edfe314..827ecacd26 100644 --- a/drape_frontend/apply_feature_functors.hpp +++ b/drape_frontend/apply_feature_functors.hpp @@ -21,6 +21,11 @@ class SymbolRuleProto; //#define CALC_FILTERED_POINTS +namespace ftypes +{ +class RoadShield; +} + namespace df { diff --git a/drape_frontend/rule_drawer.cpp b/drape_frontend/rule_drawer.cpp index 65b66549bf..e4c880da57 100644 --- a/drape_frontend/rule_drawer.cpp +++ b/drape_frontend/rule_drawer.cpp @@ -11,8 +11,9 @@ #include "indexer/feature.hpp" #include "indexer/feature_algo.hpp" #include "indexer/feature_visibility.hpp" -#include "indexer/scales.hpp" #include "indexer/ftypes_matcher.hpp" +#include "indexer/road_shields_parser.hpp" +#include "indexer/scales.hpp" #include "base/assert.hpp" #include "base/logging.hpp" diff --git a/indexer/CMakeLists.txt b/indexer/CMakeLists.txt index 716fdf40bd..8596e0a2b2 100644 --- a/indexer/CMakeLists.txt +++ b/indexer/CMakeLists.txt @@ -108,6 +108,8 @@ set( postcodes_matcher.hpp # it's in indexer due to editor which is in indexer and depends on postcodes_marcher rank_table.cpp rank_table.hpp + road_shields_parser.cpp + road_shields_parser.hpp scale_index_builder.hpp scale_index.hpp scales.cpp diff --git a/indexer/ftypes_matcher.cpp b/indexer/ftypes_matcher.cpp index 67f316872f..d3eefbbc7b 100644 --- a/indexer/ftypes_matcher.cpp +++ b/indexer/ftypes_matcher.cpp @@ -557,200 +557,4 @@ bool IsTypeConformed(uint32_t type, StringIL const & path) } return true; } - -class RoadShieldParser -{ -public: - RoadShieldParser(std::string const & baseRoadNumber) - : m_baseRoadNumber(baseRoadNumber) - {} - virtual ~RoadShieldParser(){} - virtual RoadShield ParseRoadShield(std::string const & rawText) = 0; - - std::vector GetRoadShields() - { - std::vector result; - std::vector shieldsRawTests = strings::Tokenize(m_baseRoadNumber, ";"); - for (std::string const & rawText : shieldsRawTests) - { - RoadShield shield = ParseRoadShield(rawText); - if (!shield.m_name.empty()) - result.push_back(std::move(shield)); - } - return result; - } - -protected: - std::string const m_baseRoadNumber; -}; - -uint32_t constexpr kMaxRoadShieldTextSize = 8; - -class USRoadShieldParser : public RoadShieldParser -{ -public: - USRoadShieldParser(std::string const & baseRoadNumber) - : RoadShieldParser(baseRoadNumber) - {} - - RoadShield ParseRoadShield(std::string const & rawText) override - { - static std::vector kStatesCode = { - "US", "SR", "FSR", "AL", "AK", "AZ", "AR", "CA", "CO", "CT", "DE", "DC", "FL", "GA", - "HI", "ID", "IL", "IN", "IA", "KS", "KY", "LA", "ME", "MD", "MA", "MI", "MN", "MS", - "MO", "MT", "NE", "NV", "NH", "NJ", "NM", "NY", "NC", "ND", "OH", "OK", "OR", "PA", - "RI", "SC", "SD", "TN", "TX", "UT", "VT", "VA", "WA", "WV", "WI", "WY", "AS", "GU", - "MP", "PR", "VI", "UM", "FM", "MH", "PW", - }; - - static std::vector kModifiers = { - "alt", "alternate", "bus", "business", "bypass", "historic", "connector", "loop", - "scenic", "spur", "temporary", "toll", "truck" - }; - - std::string shieldText = rawText; - - std::replace(shieldText.begin(), shieldText.end(), '-', ' '); - auto const shieldParts = strings::Tokenize(shieldText, " "); - - // Process long road shield titles to skip invalid data. - if (shieldText.size() > kMaxRoadShieldTextSize) - { - std::string lowerShieldText = shieldText; - strings::AsciiToLower(lowerShieldText); - - bool modifierFound = false; - for (auto const & modifier : kModifiers) - { - if (lowerShieldText.find(modifier) != std::string::npos) - { - modifierFound = true; - break; - } - } - if (!modifierFound) - return RoadShield(); - } - - if (shieldParts.size() <= 1) - { - return RoadShield(RoadShieldType::Default, rawText); - } - else - { - std::string const & roadType = shieldParts[0]; // 'I' for interstates and kStatesCode for highways. - std::string roadNumber = shieldParts[1]; - std::string additionalInfo; - if (shieldParts.size() >= 3) - { - additionalInfo = shieldParts[2]; - // Process cases like "US Loop 16". - if (!strings::is_number(shieldParts[1]) && strings::is_number(shieldParts[2])) - { - roadNumber = shieldParts[2]; - additionalInfo = shieldParts[1]; - } - } - if (roadType == "I") - return RoadShield(RoadShieldType::US_Interstate, roadNumber, additionalInfo); - else if (std::find(kStatesCode.begin(), kStatesCode.end(), shieldParts[0]) !=kStatesCode.end()) - return RoadShield(RoadShieldType::US_Highway, roadNumber, additionalInfo); - - return RoadShield(RoadShieldType::Default, rawText); - } - } -}; - -class SimpleRoadShieldParser : public RoadShieldParser -{ -public: - using ShieldTypes = std::unordered_map; - - SimpleRoadShieldParser(std::string const & baseRoadNumber, ShieldTypes const & types) - : RoadShieldParser(baseRoadNumber) - , m_types(types) - {} - - RoadShield ParseRoadShield(std::string const & rawText) override - { - if (rawText.size() > kMaxRoadShieldTextSize) - return RoadShield(); - - for (auto const & p : m_types) - { - if (rawText.find(p.first) != std::string::npos) - return RoadShield(p.second, rawText); - } - - return RoadShield(RoadShieldType::Default, rawText); - } - -private: - ShieldTypes const m_types; -}; - -class UKRoadShieldParser : public SimpleRoadShieldParser -{ -public: - UKRoadShieldParser(std::string const & baseRoadNumber) - : SimpleRoadShieldParser(baseRoadNumber, {{'M', RoadShieldType::UK_Motorway}, - {'A', RoadShieldType::UK_Highway}}) - {} -}; - -class RussiaRoadShieldParser : public RoadShieldParser -{ -public: - RussiaRoadShieldParser(std::string const & baseRoadNumber) - : RoadShieldParser(baseRoadNumber) - {} - - RoadShield ParseRoadShield(std::string const & rawText) override - { - if (rawText.size() > kMaxRoadShieldTextSize) - return RoadShield(); - - strings::UniString s = strings::MakeUniString(rawText); - if (s[0] == 'E' || s[0] == strings::UniChar(1045)) // Latin and cyrillic. - return RoadShield(RoadShieldType::Euro_Motorway, rawText); - - return RoadShield(RoadShieldType::Russia_Highway, rawText); - } -}; - -class FranceRoadShieldParser : public SimpleRoadShieldParser -{ -public: - FranceRoadShieldParser(std::string const & baseRoadNumber) - : SimpleRoadShieldParser(baseRoadNumber, {{'A', RoadShieldType::France_Motorway}, - {'N', RoadShieldType::France_Motorway}, - {'E', RoadShieldType::Euro_Motorway}, - {'D', RoadShieldType::France_Departmental}}) - {} -}; - -std::vector GetRoadShields(FeatureType const & f) -{ - std::string const roadNumber = f.GetRoadNumber(); - if (roadNumber.empty()) - return std::vector(); - - // Find out country name. - std::string mwmName = f.GetID().GetMwmName(); - ASSERT_NOT_EQUAL(mwmName, FeatureID::kInvalidFileName, ()); - auto const underlinePos = mwmName.find('_'); - if (underlinePos != std::string::npos) - mwmName = mwmName.substr(0, underlinePos); - - if (mwmName == "US") - return USRoadShieldParser(roadNumber).GetRoadShields(); - if (mwmName == "UK") - return UKRoadShieldParser(roadNumber).GetRoadShields(); - if (mwmName == "Russia") - return RussiaRoadShieldParser(roadNumber).GetRoadShields(); - if (mwmName == "France") - return FranceRoadShieldParser(roadNumber).GetRoadShields(); - - return std::vector{RoadShield(RoadShieldType::Default, roadNumber)}; -} } // namespace ftypes diff --git a/indexer/ftypes_matcher.hpp b/indexer/ftypes_matcher.hpp index c599aaa35d..760d391120 100644 --- a/indexer/ftypes_matcher.hpp +++ b/indexer/ftypes_matcher.hpp @@ -249,35 +249,4 @@ enum class HighwayClass string DebugPrint(HighwayClass const cls); HighwayClass GetHighwayClass(feature::TypesHolder const & types); - -enum class RoadShieldType -{ - Default = 0, - US_Interstate, - US_Highway, - Euro_Motorway, - UK_Motorway, - UK_Highway, - Russia_Highway, - France_Motorway, - France_Departmental, - Count -}; - -struct RoadShield -{ - RoadShieldType m_type; - std::string m_name; - std::string m_additionalText; - - RoadShield() = default; - RoadShield(RoadShieldType const & type, std::string const & name) - : m_type(type), m_name(name) - {} - RoadShield(RoadShieldType const & type, std::string const & name, std::string const & additionalText) - : m_type(type), m_name(name), m_additionalText(additionalText) - {} -}; - -std::vector GetRoadShields(FeatureType const & f); } // namespace ftypes diff --git a/indexer/indexer.pro b/indexer/indexer.pro index cfb77f0945..54d9194d6d 100644 --- a/indexer/indexer.pro +++ b/indexer/indexer.pro @@ -56,6 +56,7 @@ SOURCES += \ point_to_int64.cpp \ postcodes_matcher.cpp \ # it's in indexer due to editor wich is in indexer and depends on postcodes_marcher rank_table.cpp \ + road_shields_parser.cpp \ scales.cpp \ search_delimiters.cpp \ # it's in indexer because of CategoriesHolder dependency. search_string_utils.cpp \ # it's in indexer because of CategoriesHolder dependency. @@ -118,6 +119,7 @@ HEADERS += \ point_to_int64.hpp \ postcodes_matcher.hpp \ # it's in indexer due to editor wich is in indexer and depends on postcodes_marcher rank_table.hpp \ + road_shields_parser.hpp \ scale_index.hpp \ scale_index_builder.hpp \ scales.hpp \ diff --git a/indexer/road_shields_parser.cpp b/indexer/road_shields_parser.cpp new file mode 100644 index 0000000000..f071c7f141 --- /dev/null +++ b/indexer/road_shields_parser.cpp @@ -0,0 +1,317 @@ +#include "indexer/road_shields_parser.hpp" + +#include "indexer/feature.hpp" + +#include "base/string_utils.hpp" + +#include +#include +#include +#include + +namespace +{ +using ftypes::RoadShield; +using ftypes::RoadShieldType; + +uint32_t constexpr kMaxRoadShieldBytesSize = 8; + +std::array const kStatesCode { + "US", "SR", "FSR", "AL", "AK", "AZ", "AR", "CA", "CO", "CT", "DE", "DC", "FL", "GA", + "HI", "ID", "IL", "IN", "IA", "KS", "KY", "LA", "ME", "MD", "MA", "MI", "MN", "MS", + "MO", "MT", "NE", "NV", "NH", "NJ", "NM", "NY", "NC", "ND", "OH", "OK", "OR", "PA", + "RI", "SC", "SD", "TN", "TX", "UT", "VT", "VA", "WA", "WV", "WI", "WY", "AS", "GU", + "MP", "PR", "VI", "UM", "FM", "MH", "PW", +}; + +std::array const kModifiers { + "alt", "alternate", "bus", "business", "bypass", "historic", "connector", "loop", + "scenic", "spur", "temporary", "toll", "truck" +}; + +class RoadShieldParser +{ +public: + RoadShieldParser(std::string const & baseRoadNumber) + : m_baseRoadNumber(baseRoadNumber) + {} + virtual ~RoadShieldParser(){} + virtual RoadShield ParseRoadShield(std::string const & rawText) = 0; + + std::vector GetRoadShields() + { + std::vector result; + std::vector shieldsRawTests = strings::Tokenize(m_baseRoadNumber, ";"); + for (std::string const & rawText : shieldsRawTests) + { + RoadShield shield = ParseRoadShield(rawText); + if (!shield.m_name.empty()) + result.push_back(std::move(shield)); + } + return result; + } + +protected: + std::string const m_baseRoadNumber; +}; + +class USRoadShieldParser : public RoadShieldParser +{ +public: + USRoadShieldParser(std::string const & baseRoadNumber) + : RoadShieldParser(baseRoadNumber) + {} + + RoadShield ParseRoadShield(std::string const & rawText) override + { + std::string shieldText = rawText; + + std::replace(shieldText.begin(), shieldText.end(), '-', ' '); + auto const shieldParts = strings::Tokenize(shieldText, " "); + + // Process long road shield titles to skip invalid data. + if (shieldText.size() > kMaxRoadShieldBytesSize) + { + std::string lowerShieldText = shieldText; + strings::AsciiToLower(lowerShieldText); + + bool modifierFound = false; + for (auto const & modifier : kModifiers) + { + if (lowerShieldText.find(modifier) != std::string::npos) + { + modifierFound = true; + break; + } + } + if (!modifierFound) + return RoadShield(); + } + + if (shieldParts.size() <= 1) + return RoadShield(RoadShieldType::Default, rawText); + + std::string const & roadType = shieldParts[0]; // 'I' for interstates and kStatesCode for highways. + std::string roadNumber = shieldParts[1]; + std::string additionalInfo; + if (shieldParts.size() >= 3) + { + additionalInfo = shieldParts[2]; + // Process cases like "US Loop 16". + if (!strings::is_number(shieldParts[1]) && strings::is_number(shieldParts[2])) + { + roadNumber = shieldParts[2]; + additionalInfo = shieldParts[1]; + } + } + + if (roadType == "I") + return RoadShield(RoadShieldType::US_Interstate, roadNumber, additionalInfo); + + if (std::find(kStatesCode.begin(), kStatesCode.end(), shieldParts[0]) != kStatesCode.end()) + return RoadShield(RoadShieldType::US_Highway, roadNumber, additionalInfo); + + return RoadShield(RoadShieldType::Default, rawText); + } +}; + +class SimpleRoadShieldParser : public RoadShieldParser +{ +public: + using ShieldTypes = std::unordered_map; + + SimpleRoadShieldParser(std::string const & baseRoadNumber, ShieldTypes const & types) + : RoadShieldParser(baseRoadNumber) + , m_types(types) + {} + + RoadShield ParseRoadShield(std::string const & rawText) override + { + if (rawText.size() > kMaxRoadShieldBytesSize) + return RoadShield(); + + for (auto const & p : m_types) + { + if (rawText.find(p.first) != std::string::npos) + return RoadShield(p.second, rawText); + } + + return RoadShield(RoadShieldType::Default, rawText); + } + +private: + ShieldTypes const m_types; +}; + +class UKRoadShieldParser : public SimpleRoadShieldParser +{ +public: + UKRoadShieldParser(std::string const & baseRoadNumber) + : SimpleRoadShieldParser(baseRoadNumber, {{'M', RoadShieldType::Generic_Blue}, {'A', RoadShieldType::UK_Highway}}) + {} +}; + +class RussiaRoadShieldParser : public RoadShieldParser +{ +public: + RussiaRoadShieldParser(std::string const & baseRoadNumber) + : RoadShieldParser(baseRoadNumber) + {} + + RoadShield ParseRoadShield(std::string const & rawText) override + { + if (rawText.size() > kMaxRoadShieldBytesSize) + return RoadShield(); + + strings::UniString s = strings::MakeUniString(rawText); + if (s[0] == 'E' || s[0] == strings::UniChar(1045)) // Latin and cyrillic. + return RoadShield(RoadShieldType::Generic_Green, rawText); + + return RoadShield(RoadShieldType::Generic_Blue, rawText); + } +}; + +class SimpleUnicodeRoadShieldParser : public RoadShieldParser +{ +public: + struct Name + { + Name(std::string const & simpleName, string const & unicodeName) + : m_simpleName(simpleName), m_unicodeName(strings::MakeUniString(unicodeName)) + { + } + + std::string m_simpleName; + strings::UniString m_unicodeName; + }; + + using ShieldTypes = std::vector>; + + SimpleUnicodeRoadShieldParser(std::string const & baseRoadNumber, ShieldTypes const & types) + : RoadShieldParser(baseRoadNumber), m_types(types) + { + } + + RoadShield ParseRoadShield(std::string const & rawText) override + { + uint32_t constexpr kMaxRoadShieldSymbolsSize = 4 * kMaxRoadShieldBytesSize; + + if (rawText.size() > kMaxRoadShieldSymbolsSize) + return RoadShield(); + + for (auto const & p : m_types) + { + Name const & name = p.first; + RoadShieldType const type = p.second; + + if (rawText.find(name.m_simpleName) != std::string::npos) + return RoadShield(type, rawText); + + auto const rawUnicode = strings::MakeUniString(rawText); + auto const & unicodeName = name.m_unicodeName; + auto const it = std::search(rawUnicode.begin(), rawUnicode.end(), unicodeName.begin(), unicodeName.end()); + if (it != rawUnicode.end()) + return RoadShield(type, rawText); + } + + return RoadShield(RoadShieldType::Default, rawText); + } + +private: + ShieldTypes const m_types; +}; + +class FranceRoadShieldParser : public SimpleRoadShieldParser +{ +public: + FranceRoadShieldParser(std::string const & baseRoadNumber) + : SimpleRoadShieldParser(baseRoadNumber, {{'A', RoadShieldType::Generic_Red}, + {'N', RoadShieldType::Generic_Red}, + {'E', RoadShieldType::Generic_Green}, + {'D', RoadShieldType::Generic_Orange}}) + { + } +}; + +class UkraineRoadShieldParser : public SimpleUnicodeRoadShieldParser +{ +public: + // The second parameter in the constructor is a cyrillic symbol. + UkraineRoadShieldParser(std::string const & baseRoadNumber) + : SimpleUnicodeRoadShieldParser(baseRoadNumber, {{Name("M", "М"), RoadShieldType::Generic_Blue}, + {Name("H", "Н"), RoadShieldType::Generic_Blue}, + {Name("P", "Р"), RoadShieldType::Generic_Blue}, + {Name("E", "Е"), RoadShieldType::Generic_Green}}) + { + } +}; + +class BelarusRoadShieldParser : public SimpleUnicodeRoadShieldParser +{ +public: + // The second parameter in the constructor is a cyrillic symbol. + BelarusRoadShieldParser(std::string const & baseRoadNumber) + : SimpleUnicodeRoadShieldParser(baseRoadNumber, {{Name("M", "М"), RoadShieldType::Generic_Red}, + {Name("P", "Р"), RoadShieldType::Generic_Red}, + {Name("E", "Е"), RoadShieldType::Generic_Green}}) + { + } +}; + +class LatviaRoadShieldParser : public SimpleRoadShieldParser +{ +public: + LatviaRoadShieldParser(std::string const & baseRoadNumber) + : SimpleRoadShieldParser(baseRoadNumber, {{'A', RoadShieldType::Generic_Red}, + {'E', RoadShieldType::Generic_Green}, + {'P', RoadShieldType::Generic_Blue}}) + { + } +}; + +class NetherlandsRoadShieldParser : public SimpleRoadShieldParser +{ +public: + NetherlandsRoadShieldParser(std::string const & baseRoadNumber) + : SimpleRoadShieldParser(baseRoadNumber, {{'A', RoadShieldType::Generic_Red}, + {'E', RoadShieldType::Generic_Green}, + {'N', RoadShieldType::Generic_Orange}}) + {} +}; +} // namespace + +namespace ftypes +{ +std::vector GetRoadShields(FeatureType const & f) +{ + std::string const roadNumber = f.GetRoadNumber(); + if (roadNumber.empty()) + return std::vector(); + + // Find out country name. + std::string mwmName = f.GetID().GetMwmName(); + ASSERT_NOT_EQUAL(mwmName, FeatureID::kInvalidFileName, ()); + auto const underlinePos = mwmName.find('_'); + if (underlinePos != std::string::npos) + mwmName = mwmName.substr(0, underlinePos); + + if (mwmName == "US") + return USRoadShieldParser(roadNumber).GetRoadShields(); + if (mwmName == "UK") + return UKRoadShieldParser(roadNumber).GetRoadShields(); + if (mwmName == "Russia") + return RussiaRoadShieldParser(roadNumber).GetRoadShields(); + if (mwmName == "France") + return FranceRoadShieldParser(roadNumber).GetRoadShields(); + if (mwmName == "Ukraine") + return UkraineRoadShieldParser(roadNumber).GetRoadShields(); + if (mwmName == "Belarus") + return BelarusRoadShieldParser(roadNumber).GetRoadShields(); + if (mwmName == "Latvia") + return LatviaRoadShieldParser(roadNumber).GetRoadShields(); + if (mwmName == "Netherlands") + return NetherlandsRoadShieldParser(roadNumber).GetRoadShields(); + + return std::vector{RoadShield(RoadShieldType::Default, roadNumber)}; +} +} // namespece ftypes diff --git a/indexer/road_shields_parser.hpp b/indexer/road_shields_parser.hpp new file mode 100644 index 0000000000..a0b8a5405e --- /dev/null +++ b/indexer/road_shields_parser.hpp @@ -0,0 +1,39 @@ +#pragma once + +#include "indexer/feature.hpp" + +#include +#include + +namespace ftypes +{ +enum class RoadShieldType +{ + Default = 0, + Generic_Green, + Generic_Blue, + Generic_Red, + Generic_Orange, + US_Interstate, + US_Highway, + UK_Highway, + Count +}; + +struct RoadShield +{ + RoadShieldType m_type; + std::string m_name; + std::string m_additionalText; + + RoadShield() = default; + RoadShield(RoadShieldType const & type, std::string const & name) + : m_type(type), m_name(name) + {} + RoadShield(RoadShieldType const & type, std::string const & name, std::string const & additionalText) + : m_type(type), m_name(name), m_additionalText(additionalText) + {} +}; + +std::vector GetRoadShields(FeatureType const & f); +} // namespace ftypes diff --git a/xcode/indexer/indexer.xcodeproj/project.pbxproj b/xcode/indexer/indexer.xcodeproj/project.pbxproj index 454193181d..93865c3c2b 100644 --- a/xcode/indexer/indexer.xcodeproj/project.pbxproj +++ b/xcode/indexer/indexer.xcodeproj/project.pbxproj @@ -205,6 +205,8 @@ 67F183731BD4FCF500AB1840 /* map_style.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 67F183721BD4FCF500AB1840 /* map_style.cpp */; }; E906DE3B1CF44934004C4F5E /* postcodes_matcher.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E906DE391CF44934004C4F5E /* postcodes_matcher.cpp */; }; E906DE3C1CF44934004C4F5E /* postcodes_matcher.hpp in Headers */ = {isa = PBXBuildFile; fileRef = E906DE3A1CF44934004C4F5E /* postcodes_matcher.hpp */; }; + F61F83061E4B187500B37B7A /* road_shields_parser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F61F83041E4B187500B37B7A /* road_shields_parser.cpp */; }; + F61F83071E4B187500B37B7A /* road_shields_parser.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F61F83051E4B187500B37B7A /* road_shields_parser.hpp */; }; F6381BF91CD26C9C004CA943 /* new_feature_categories.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F6381BF71CD26C9C004CA943 /* new_feature_categories.cpp */; }; F6381BFA1CD26C9C004CA943 /* new_feature_categories.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F6381BF81CD26C9C004CA943 /* new_feature_categories.hpp */; }; F6DF5F2D1CD0FC9D00A87154 /* categories_index.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F6DF5F2C1CD0FC9D00A87154 /* categories_index.cpp */; }; @@ -427,6 +429,8 @@ E906DE371CF44917004C4F5E /* postcodes_matcher_tests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = postcodes_matcher_tests.cpp; sourceTree = ""; }; E906DE391CF44934004C4F5E /* postcodes_matcher.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = postcodes_matcher.cpp; sourceTree = ""; }; E906DE3A1CF44934004C4F5E /* postcodes_matcher.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = postcodes_matcher.hpp; sourceTree = ""; }; + F61F83041E4B187500B37B7A /* road_shields_parser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = road_shields_parser.cpp; sourceTree = ""; }; + F61F83051E4B187500B37B7A /* road_shields_parser.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = road_shields_parser.hpp; sourceTree = ""; }; F6381BF71CD26C9C004CA943 /* new_feature_categories.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = new_feature_categories.cpp; sourceTree = ""; }; F6381BF81CD26C9C004CA943 /* new_feature_categories.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = new_feature_categories.hpp; sourceTree = ""; }; F6DF5F2C1CD0FC9D00A87154 /* categories_index.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = categories_index.cpp; sourceTree = ""; }; @@ -750,6 +754,8 @@ 675340FB1A3F540F00A0A8C3 /* types_mapping.cpp */, 675340FC1A3F540F00A0A8C3 /* types_mapping.hpp */, 670EE56B1B60033A001E8064 /* unique_index.hpp */, + F61F83041E4B187500B37B7A /* road_shields_parser.cpp */, + F61F83051E4B187500B37B7A /* road_shields_parser.hpp */, ); name = indexer; path = ../../indexer; @@ -830,6 +836,7 @@ 347F337C1C454242009758CC /* rank_table.hpp in Headers */, 0C5FEC731DDE1A140017688C /* routing_section.hpp in Headers */, 6753414B1A3F540F00A0A8C3 /* tesselator_decl.hpp in Headers */, + F61F83071E4B187500B37B7A /* road_shields_parser.hpp in Headers */, 347F33801C454242009758CC /* trie_reader.hpp in Headers */, 675341191A3F540F00A0A8C3 /* feature_decl.hpp in Headers */, 674125141B4C02F100A3E828 /* map_style_reader.hpp in Headers */, @@ -1056,6 +1063,7 @@ 675341251A3F540F00A0A8C3 /* feature.cpp in Sources */, 675341091A3F540F00A0A8C3 /* data_header.cpp in Sources */, 6753412C1A3F540F00A0A8C3 /* geometry_serialization.cpp in Sources */, + F61F83061E4B187500B37B7A /* road_shields_parser.cpp in Sources */, 670EE56C1B60033A001E8064 /* features_vector.cpp in Sources */, 34664CF31D49FEC1003D7096 /* altitude_loader.cpp in Sources */, 6726C1D11A49DAAC005EEA39 /* feature_meta.cpp in Sources */,