diff options
author | Daria Volvenkova <d.volvenkova@corp.mail.ru> | 2017-02-01 16:02:19 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-02-01 16:02:19 +0300 |
commit | 450e210f9f5b8300f4b6064ec0ee1ca431c6991d (patch) | |
tree | 35cecd65ed2270b752bc4f6f35879a33e5b1bef9 /indexer/ftypes_matcher.cpp | |
parent | 01353f902a9e378960db520c3a3183f559ffeace (diff) | |
parent | eefb5272b2a1381168e05c00c7c79799e739cf25 (diff) |
Merge pull request #5288 from rokuz/shields-rendering
Added shields rendering
Diffstat (limited to 'indexer/ftypes_matcher.cpp')
-rw-r--r-- | indexer/ftypes_matcher.cpp | 191 |
1 files changed, 188 insertions, 3 deletions
diff --git a/indexer/ftypes_matcher.cpp b/indexer/ftypes_matcher.cpp index ee5c1584e2..a893befac4 100644 --- a/indexer/ftypes_matcher.cpp +++ b/indexer/ftypes_matcher.cpp @@ -4,9 +4,11 @@ #include "indexer/feature_data.hpp" #include "indexer/classificator.hpp" -#include "std/map.hpp" -#include "std/sstream.hpp" -#include "std/utility.hpp" +#include <algorithm> +#include <map> +#include <sstream> +#include <unordered_map> +#include <utility> namespace { @@ -555,4 +557,187 @@ 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<RoadShield> GetRoadShields() + { + std::vector<RoadShield> result; + std::vector<std::string> 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<std::string> 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<std::string> 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<char, RoadShieldType>; + + 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::Russia_Motorway, rawText); + + return RoadShield(RoadShieldType::Russia_Highway, rawText); + } +}; + +std::vector<RoadShield> GetRoadShields(FeatureType const & f) +{ + std::string const roadNumber = f.GetRoadNumber(); + if (roadNumber.empty()) + return std::vector<RoadShield>(); + + // 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(); + + return std::vector<RoadShield>{RoadShield(RoadShieldType::Default, roadNumber)}; +} } // namespace ftypes |