From c338622c4550cf839fa4dd127085ea8024192d7e Mon Sep 17 00:00:00 2001 From: Vladimir Byko-Ianko Date: Thu, 14 Nov 2019 16:56:13 +0300 Subject: [PATCH] Adding structures and methods for calculating track analyzing stats. --- track_analyzing/track_analyzer/utils.cpp | 131 ++++++++++++++++++++++- track_analyzing/track_analyzer/utils.hpp | 21 ++++ 2 files changed, 150 insertions(+), 2 deletions(-) diff --git a/track_analyzing/track_analyzer/utils.cpp b/track_analyzing/track_analyzer/utils.cpp index 899c4d5c12..ce17fd1eed 100644 --- a/track_analyzing/track_analyzer/utils.cpp +++ b/track_analyzing/track_analyzer/utils.cpp @@ -11,11 +11,113 @@ #include "base/logging.hpp" -namespace track_analyzing -{ +#include +#include +#include + using namespace routing; using namespace std; using namespace storage; +using namespace track_analyzing; + +namespace +{ +set GetKeys(Stat::NameToCountMapping const & mapping) +{ + set keys; + transform(mapping.begin(), mapping.end(), inserter(keys, keys.end()), + [](auto const & kv) { return kv.first; }); + return keys; +} + +inline void Add(Stat::NameToCountMapping const & addition, Stat::NameToCountMapping & base) +{ + set userKeys = GetKeys(addition); + set const userKeys2 = GetKeys(base); + userKeys.insert(userKeys2.cbegin(), userKeys2.cend()); + + for (auto const & c : userKeys) + { + if (addition.count(c) == 0) + continue; + + if (base.count(c) == 0) + { + base[c] = addition.at(c); + continue; + } + + base[c] += addition.at(c); + } +} + +void AddStat(uint32_t dataPointNum, routing::NumMwmId numMwmId, + NumMwmIds const & numMwmIds, Storage const & storage, Stat & stat) +{ + auto const mwmName = numMwmIds.GetFile(numMwmId).GetName(); + auto const countryName = storage.GetTopmostParentFor(mwmName); + + // Note. In case of disputed mwms |countryName| will be empty. + stat.m_mwmToTotalDataPoints[mwmName] += dataPointNum; + stat.m_countryToTotalDataPoints[countryName] += dataPointNum; +} + +void PrintMap(string const & keyType, string const & descr, + map const & mapping, ostringstream & ss) +{ + struct KeyValue + { + string m_key; + uint32_t m_value = 0; + }; + + ss << descr << '\n'; + if (mapping.empty()) + { + ss << "Map is empty." << endl; + return; + } + + // Sorting from bigger to smaller values. + vector keyValues; + keyValues.reserve(mapping.size()); + for (auto const & kv : mapping) + keyValues.push_back({kv.first, kv.second}); + + sort(keyValues.begin(), keyValues.end(), + [](KeyValue const & a, KeyValue const & b) { return a.m_value > b.m_value; }); + + uint32_t allValues = 0; + for (auto const & kv : keyValues) + allValues += kv.m_value; + + ss << keyType << ",number,percent"; + for (auto const & kv : keyValues) + { + if (kv.m_value == 0) + continue; + + ss << kv.m_key << "," << kv.m_value << "," + << 100.0 * static_cast(kv.m_value) / allValues << "\n"; + } + ss << "\n" << endl; +} +} // namespace + +namespace track_analyzing +{ +// Stat ============================================================================================ +void Stat::Add(Stat const & stat) +{ + ::Add(stat.m_mwmToTotalDataPoints, m_mwmToTotalDataPoints); + ::Add(stat.m_countryToTotalDataPoints, m_countryToTotalDataPoints); +} + +bool Stat::operator==(Stat const & stat) const +{ + return m_mwmToTotalDataPoints == stat.m_mwmToTotalDataPoints && + m_countryToTotalDataPoints == stat.m_countryToTotalDataPoints; +} void ParseTracks(string const & logFile, shared_ptr const & numMwmIds, MwmToTracks & mwmToTracks) @@ -30,4 +132,29 @@ void ParseTracks(string const & logFile, shared_ptr const & numMwmIds LogParser parser(numMwmIds, move(mwmTree), dataDir); parser.Parse(logFile, mwmToTracks); } + +void AddStat(MwmToTracks const & mwmToTracks, NumMwmIds const & numMwmIds, Storage const & storage, + Stat & stat) +{ + for (auto const & kv : mwmToTracks) + { + auto const & userToTrack = kv.second; + uint32_t dataPointNum = 0; + for (auto const & userTrack : userToTrack) + dataPointNum += userTrack.second.size(); + + ::AddStat(dataPointNum, kv.first, numMwmIds, storage, stat); + } +} + +string DebugPrint(Stat const & s) +{ + ostringstream ss; + ss << "Stat [\n"; + PrintMap("mwm", "Mwm to total data points number:", s.m_mwmToTotalDataPoints, ss); + PrintMap("country", "Country name to data points number:", s.m_countryToTotalDataPoints, ss); + ss << "]\n" << endl; + + return ss.str(); +} } // namespace track_analyzing diff --git a/track_analyzing/track_analyzer/utils.hpp b/track_analyzing/track_analyzer/utils.hpp index 6edbb0e7d9..c0354842cc 100644 --- a/track_analyzing/track_analyzer/utils.hpp +++ b/track_analyzing/track_analyzer/utils.hpp @@ -6,13 +6,34 @@ #include "track_analyzing/track.hpp" +#include +#include #include #include #include namespace track_analyzing { +struct Stat +{ + using NameToCountMapping = std::map; + + void Add(Stat const & stat); + bool operator==(Stat const & stat) const; + + /// \note These fields may present mapping from territory name to either DataPoints + /// or MatchedTrackPoint count. + NameToCountMapping m_mwmToTotalDataPoints; + NameToCountMapping m_countryToTotalDataPoints; +}; + /// \brief Parses tracks from |logFile| and fills |numMwmIds|, |storage| and |mwmToTracks|. void ParseTracks(std::string const & logFile, std::shared_ptr const & numMwmIds, MwmToTracks & mwmToTracks); + +/// \brief Fills |stat| according to |mwmToTracks|. +void AddStat(MwmToTracks const & mwmToTracks, routing::NumMwmIds const & numMwmIds, + storage::Storage const & storage, Stat & stat); + +std::string DebugPrint(Stat const & s); } // namespace track_analyzing