diff options
Diffstat (limited to 'ugc')
-rw-r--r-- | ugc/api.cpp | 21 | ||||
-rw-r--r-- | ugc/api.hpp | 3 | ||||
-rw-r--r-- | ugc/binary/serdes.cpp | 2 | ||||
-rw-r--r-- | ugc/loader.cpp | 34 | ||||
-rw-r--r-- | ugc/loader.hpp | 22 | ||||
-rw-r--r-- | ugc/serdes_json.hpp | 28 | ||||
-rw-r--r-- | ugc/storage.cpp | 9 | ||||
-rw-r--r-- | ugc/storage.hpp | 2 | ||||
-rw-r--r-- | ugc/types.hpp | 144 | ||||
-rw-r--r-- | ugc/ugc.pro | 3 | ||||
-rw-r--r-- | ugc/ugc_tests/serdes_tests.cpp | 2 | ||||
-rw-r--r-- | ugc/ugc_tests/utils.cpp | 10 | ||||
-rw-r--r-- | ugc/ugc_tests/utils.hpp | 1 |
13 files changed, 193 insertions, 88 deletions
diff --git a/ugc/api.cpp b/ugc/api.cpp index 076df47507..523f47fc4d 100644 --- a/ugc/api.cpp +++ b/ugc/api.cpp @@ -1,5 +1,7 @@ #include "ugc/api.hpp" +#include "indexer/feature.hpp" + #include "platform/platform.hpp" #include <chrono> @@ -9,7 +11,11 @@ using namespace ugc; namespace ugc { -Api::Api(Index const & index, std::string const & filename) : m_index(index), m_storage(filename) {} +Api::Api(Index const & index, std::string const & filename) + : m_storage(filename) +, m_loader(index) +{ +} void Api::GetUGC(FeatureID const & id, UGCCallback callback) { @@ -23,17 +29,18 @@ void Api::SetUGCUpdate(FeatureID const & id, UGCUpdate const & ugc) void Api::GetUGCImpl(FeatureID const & id, UGCCallback callback) { - // TODO (@y, @mgsergio): retrieve static UGC - UGC ugc; - UGCUpdate update; - if (!id.IsValid()) { - GetPlatform().RunOnGuiThread([ugc, update, callback] { callback(ugc, update); }); + GetPlatform().RunOnGuiThread([callback] { callback({}, {}); }); return; } - // ugc = MakeTestUGC1(); + UGC ugc; + UGCUpdate update; + + m_storage.GetUGCUpdate(id, update); + m_loader.GetUGC(id, ugc); + GetPlatform().RunOnGuiThread([ugc, update, callback] { callback(ugc, update); }); } diff --git a/ugc/api.hpp b/ugc/api.hpp index 4f578ce53e..a9b50777b2 100644 --- a/ugc/api.hpp +++ b/ugc/api.hpp @@ -2,6 +2,7 @@ #include "base/worker_thread.hpp" +#include "ugc/loader.hpp" #include "ugc/storage.hpp" #include "ugc/types.hpp" @@ -28,8 +29,8 @@ private: void SetUGCUpdateImpl(FeatureID const & id, UGCUpdate const & ugc); - Index const & m_index; base::WorkerThread m_thread; Storage m_storage; + Loader m_loader; }; } // namespace ugc diff --git a/ugc/binary/serdes.cpp b/ugc/binary/serdes.cpp index fdecacaff8..b239b0edce 100644 --- a/ugc/binary/serdes.cpp +++ b/ugc/binary/serdes.cpp @@ -15,6 +15,8 @@ class BaseCollector public: virtual ~BaseCollector() = default; + void VisitVarUint(uint32_t, char const * /* name */ = nullptr) {} + void VisitVarUint(uint64_t, char const * /* name */ = nullptr) {} virtual void VisitRating(float const f, char const * /* name */ = nullptr) {} virtual void operator()(string const & /* s */, char const * /* name */ = nullptr) {} virtual void operator()(Sentiment const /* sentiment */, char const * /* name */ = nullptr) {} diff --git a/ugc/loader.cpp b/ugc/loader.cpp new file mode 100644 index 0000000000..b28d9e3461 --- /dev/null +++ b/ugc/loader.cpp @@ -0,0 +1,34 @@ +#include "ugc/loader.hpp" + +#include "ugc/types.hpp" + +#include "indexer/feature.hpp" +#include "indexer/index.hpp" + +#include "defines.hpp" + +namespace ugc +{ +Loader::Loader(Index const & index) : m_index(index) {} + +void Loader::GetUGC(FeatureID const & featureId, UGC & result) +{ + UGC ugc; + auto const & handle = m_index.GetMwmHandleById(featureId.m_mwmId); + + if (!handle.IsAlive()) + return; + + auto const & value = *handle.GetValue<MwmValue>(); + + if (!value.m_cont.IsExist(UGC_FILE_TAG)) + return; + + auto readerPtr = value.m_cont.GetReader(UGC_FILE_TAG); + + if (!m_d.Deserialize(*readerPtr.GetPtr(), featureId.m_index, ugc)) + return; + + result = std::move(ugc); +} +} // namespace ugc diff --git a/ugc/loader.hpp b/ugc/loader.hpp new file mode 100644 index 0000000000..45e332bd0c --- /dev/null +++ b/ugc/loader.hpp @@ -0,0 +1,22 @@ +#pragma once + +#include "ugc/binary/serdes.hpp" + +class Index; +struct FeatureID; + +namespace ugc +{ +struct UGC; + +class Loader +{ +public: + Loader(Index const & index); + void GetUGC(FeatureID const & featureId, UGC & ugc); + +private: + Index const & m_index; + binary::UGCDeserializer m_d; +}; +} // namespace ugc diff --git a/ugc/serdes_json.hpp b/ugc/serdes_json.hpp index 7fc8f36e01..c850db6cbe 100644 --- a/ugc/serdes_json.hpp +++ b/ugc/serdes_json.hpp @@ -73,6 +73,12 @@ public: ToJSONObject(*m_json, name, d); } + template <typename T> + void VisitVarUint(T const & t, char const * name = nullptr) + { + ToJSONObject(*m_json, name, t); + } + private: template <typename Fn> void NewScopeWith(my::JSONPtr json_object, char const * name, Fn && fn) @@ -95,20 +101,28 @@ private: Sink & m_sink; }; -template <typename Source> class DeserializerJsonV0 { public: DECLARE_EXCEPTION(Exception, RootException); - DeserializerJsonV0(Source & source) : m_source(source) + template <typename Source, + typename std::enable_if< + !std::is_convertible<Source, std::string>::value, Source>::type * = nullptr> + DeserializerJsonV0(Source & source) { std::string src(source.Size(), '\0'); source.Read(static_cast<void *>(&src[0]), source.Size()); - m_jsonObject.ParseFrom(src.c_str()); + m_jsonObject.ParseFrom(src); m_json = m_jsonObject.get(); } + DeserializerJsonV0(std::string const & source) + : m_jsonObject(source) + , m_json(m_jsonObject.get()) + { + } + void operator()(bool & d, char const * name = nullptr) { FromJSONObject(m_json, name, d); } void operator()(uint8_t & d, char const * name = nullptr) { FromJSONObject(m_json, name, d); } void operator()(uint32_t & d, char const * name = nullptr) { FromJSONObject(m_json, name, d); } @@ -118,6 +132,7 @@ public: { (*this)(key.m_key, name); } + void operator()(Time & t, char const * name = nullptr) { uint32_t d = 0; @@ -167,6 +182,12 @@ public: f = static_cast<float>(d); } + template <typename T> + void VisitVarUint(T & t, char const * name = nullptr) + { + FromJSONObject(m_json, name, t); + } + private: json_t * SaveContext(char const * name = nullptr) { @@ -184,6 +205,5 @@ private: my::Json m_jsonObject; json_t * m_json = nullptr; - Source & m_source; }; } // namespace ugc diff --git a/ugc/storage.cpp b/ugc/storage.cpp index 15fd9babb6..fe966264a7 100644 --- a/ugc/storage.cpp +++ b/ugc/storage.cpp @@ -10,12 +10,13 @@ Storage::Storage(std::string const & filename) Load(); } -UGCUpdate const * Storage::GetUGCUpdate(FeatureID const & id) const +void Storage::GetUGCUpdate(FeatureID const & id, UGCUpdate & ugc) const { auto const it = m_ugc.find(id); - if (it != end(m_ugc)) - return &it->second; - return nullptr; + if (it == end(m_ugc)) + return; + + ugc = it->second; } void Storage::SetUGCUpdate(FeatureID const & id, UGCUpdate const & ugc) diff --git a/ugc/storage.hpp b/ugc/storage.hpp index 2086dbad15..c6df8c5f67 100644 --- a/ugc/storage.hpp +++ b/ugc/storage.hpp @@ -14,7 +14,7 @@ class Storage public: explicit Storage(std::string const & filename); - UGCUpdate const * GetUGCUpdate(FeatureID const & id) const; + void GetUGCUpdate(FeatureID const & id, UGCUpdate & ugc) const; void SetUGCUpdate(FeatureID const & id, UGCUpdate const & ugc); void Save(); diff --git a/ugc/types.hpp b/ugc/types.hpp index 2e6f278756..fd60258bba 100644 --- a/ugc/types.hpp +++ b/ugc/types.hpp @@ -4,6 +4,7 @@ #include "coding/hex.hpp" +#include "base/math.hpp" #include "base/visitor.hpp" #include <chrono> @@ -30,14 +31,14 @@ struct TranslationKey bool operator==(TranslationKey const & rhs) const { return m_key == rhs.m_key; } bool operator<(TranslationKey const & rhs) const { return m_key < rhs.m_key; } - friend std::string DebugPrint(TranslationKey const & key) - { - return "TranslationKey [ " + key.m_key + " ]"; - } - std::string m_key; }; +std::string DebugPrint(TranslationKey const & key) +{ + return "TranslationKey [ " + key.m_key + " ]"; +} + enum class Sentiment { Positive, @@ -86,18 +87,18 @@ struct RatingRecord return m_key == rhs.m_key && m_value == rhs.m_value; } - friend std::string DebugPrint(RatingRecord const & ratingRecord) - { - std::ostringstream os; - os << "RatingRecord [ " << DebugPrint(ratingRecord.m_key) << " " << ratingRecord.m_value - << " ]"; - return os.str(); - } - TranslationKey m_key{}; float m_value{}; }; +std::string DebugPrint(RatingRecord const & ratingRecord) +{ + std::ostringstream os; + os << "RatingRecord [ " << DebugPrint(ratingRecord.m_key) << " " << ratingRecord.m_value + << " ]"; + return os.str(); +} + using Ratings = std::vector<RatingRecord>; struct UID @@ -110,17 +111,18 @@ struct UID DECLARE_VISITOR(visitor(m_hi, "hi"), visitor(m_lo, "lo")); bool operator==(UID const & rhs) const { return m_hi == rhs.m_hi && m_lo == rhs.m_lo; } - friend std::string DebugPrint(UID const & uid) - { - std::ostringstream os; - os << "UID [ " << uid.ToString() << " ]"; - return os.str(); - } uint64_t m_hi{}; uint64_t m_lo{}; }; +std::string DebugPrint(UID const & uid) +{ + std::ostringstream os; + os << "UID [ " << uid.ToString() << " ]"; + return os.str(); +} + using Author = std::string; struct Text @@ -132,18 +134,18 @@ struct Text bool operator==(Text const & rhs) const { return m_lang == rhs.m_lang && m_text == rhs.m_text; } - friend std::string DebugPrint(Text const & text) - { - std::ostringstream os; - os << "Text [ " << StringUtf8Multilang::GetLangByCode(text.m_lang) << ": " << text.m_text - << " ]"; - return os.str(); - } - std::string m_text; uint8_t m_lang = StringUtf8Multilang::kDefaultCode; }; +std::string DebugPrint(Text const & text) +{ + std::ostringstream os; + os << "Text [ " << StringUtf8Multilang::GetLangByCode(text.m_lang) << ": " << text.m_text + << " ]"; + return os.str(); +} + struct Review { using ReviewId = uint64_t; @@ -164,18 +166,6 @@ struct Review m_rating == rhs.m_rating && m_time == rhs.m_time; } - friend std::string DebugPrint(Review const & review) - { - std::ostringstream os; - os << "Review [ "; - os << "id:" << review.m_id << ", "; - os << "text:" << DebugPrint(review.m_text) << ", "; - os << "author:" << review.m_author << ", "; - os << "rating:" << review.m_rating << ", "; - os << "days since epoch:" << ToDaysSinceEpoch(review.m_time) << " ]"; - return os.str(); - } - ReviewId m_id{}; Text m_text{}; Author m_author{}; @@ -183,6 +173,18 @@ struct Review Time m_time{}; }; +std::string DebugPrint(Review const & review) +{ + std::ostringstream os; + os << "Review [ "; + os << "id:" << review.m_id << ", "; + os << "text:" << DebugPrint(review.m_text) << ", "; + os << "author:" << review.m_author << ", "; + os << "rating:" << review.m_rating << ", "; + os << "days since epoch:" << ToDaysSinceEpoch(review.m_time) << " ]"; + return os.str(); +} + using Reviews = std::vector<Review>; struct Attribute @@ -199,49 +201,56 @@ struct Attribute return m_key == rhs.m_key && m_value == rhs.m_value; } - friend std::string DebugPrint(Attribute const & attribute) - { - std::ostringstream os; - os << "Attribute [ key:" << DebugPrint(attribute.m_key) - << ", value:" << DebugPrint(attribute.m_value) << " ]"; - return os.str(); - } - TranslationKey m_key{}; TranslationKey m_value{}; }; +std::string DebugPrint(Attribute const & attribute) +{ + std::ostringstream os; + os << "Attribute [ key:" << DebugPrint(attribute.m_key) + << ", value:" << DebugPrint(attribute.m_value) << " ]"; + return os.str(); +} + struct UGC { UGC() = default; - UGC(Ratings const & records, Reviews const & reviews, float const totalRating, uint32_t votes) - : m_ratings(records), m_reviews(reviews), m_totalRating(totalRating), m_votes(votes) + UGC(Ratings const & records, Reviews const & reviews, float const totalRating, uint32_t basedOn) + : m_ratings(records), m_reviews(reviews), m_totalRating(totalRating), m_basedOn(basedOn) { } DECLARE_VISITOR(visitor(m_ratings, "ratings"), visitor(m_reviews, "reviews"), - visitor.VisitRating(m_totalRating, "totalRating")) + visitor.VisitRating(m_totalRating, "total_rating"), + visitor.VisitVarUint(m_basedOn, "based_on")) bool operator==(UGC const & rhs) const { - return m_ratings == rhs.m_ratings && m_reviews == rhs.m_reviews; + return m_ratings == rhs.m_ratings && m_reviews == rhs.m_reviews && + my::AlmostEqualAbs(m_totalRating, rhs.m_totalRating, 1e-6f) && m_basedOn == rhs.m_basedOn; } - friend std::string DebugPrint(UGC const & ugc) + bool IsValid() const { - std::ostringstream os; - os << "UGC [ "; - os << "records:" << ::DebugPrint(ugc.m_ratings) << ", "; - os << "reviews:" << ::DebugPrint(ugc.m_reviews) << " ]"; - return os.str(); + return (!m_ratings.empty() || !m_reviews.empty()) && m_totalRating > 1e-6 && m_basedOn > 0; } Ratings m_ratings; Reviews m_reviews; float m_totalRating{}; - uint32_t m_votes{}; + uint32_t m_basedOn{}; }; +std::string DebugPrint(UGC const & ugc) +{ + std::ostringstream os; + os << "UGC [ "; + os << "records:" << ::DebugPrint(ugc.m_ratings) << ", "; + os << "reviews:" << ::DebugPrint(ugc.m_reviews) << " ]"; + return os.str(); +} + struct UGCUpdate { UGCUpdate() = default; @@ -257,14 +266,9 @@ struct UGCUpdate return m_ratings == rhs.m_ratings && m_text == rhs.m_text && m_time == rhs.m_time; } - friend std::string DebugPrint(UGCUpdate const & ugcUpdate) + bool IsValid() const { - std::ostringstream os; - os << "UGCUpdate [ "; - os << "records:" << ::DebugPrint(ugcUpdate.m_ratings) << ", "; - os << "text:" << DebugPrint(ugcUpdate.m_text) << ", "; - os << "days since epoch:" << ToDaysSinceEpoch(ugcUpdate.m_time) << " ]"; - return os.str(); + return (!m_ratings.empty() || !m_text.m_text.empty()) && m_time != Time(); } Ratings m_ratings; @@ -272,6 +276,16 @@ struct UGCUpdate Time m_time{}; }; +std::string DebugPrint(UGCUpdate const & ugcUpdate) +{ + std::ostringstream os; + os << "UGCUpdate [ "; + os << "records:" << ::DebugPrint(ugcUpdate.m_ratings) << ", "; + os << "text:" << DebugPrint(ugcUpdate.m_text) << ", "; + os << "days since epoch:" << ToDaysSinceEpoch(ugcUpdate.m_time) << " ]"; + return os.str(); +} + struct ReviewFeedback { ReviewFeedback() = default; diff --git a/ugc/ugc.pro b/ugc/ugc.pro index 3142108058..a08da10f90 100644 --- a/ugc/ugc.pro +++ b/ugc/ugc.pro @@ -15,11 +15,14 @@ HEADERS += \ binary/serdes.hpp \ binary/ugc_holder.hpp \ binary/visitors.hpp \ + loader.hpp \ serdes.hpp \ + serdes_json.hpp \ storage.hpp \ types.hpp \ SOURCES += \ api.cpp \ binary/serdes.cpp \ + loader.cpp \ storage.cpp \ diff --git a/ugc/ugc_tests/serdes_tests.cpp b/ugc/ugc_tests/serdes_tests.cpp index 6cdc967a7d..b3f5c0154f 100644 --- a/ugc/ugc_tests/serdes_tests.cpp +++ b/ugc/ugc_tests/serdes_tests.cpp @@ -22,7 +22,7 @@ using Buffer = vector<uint8_t>; using ToBin = Serializer<MemWriter<Buffer>>; using FromBin = DeserializerV0<ReaderSource<MemReader>>; using ToJson = SerializerJson<MemWriter<Buffer>>; -using FromJson = DeserializerJsonV0<ReaderSource<MemReader>>; +using FromJson = DeserializerJsonV0; Ratings GetTestRating() { diff --git a/ugc/ugc_tests/utils.cpp b/ugc/ugc_tests/utils.cpp index 0693173410..11b178df42 100644 --- a/ugc/ugc_tests/utils.cpp +++ b/ugc/ugc_tests/utils.cpp @@ -19,13 +19,13 @@ UGC MakeTestUGC1(Time now) Reviews reviews; reviews.emplace_back(20 /* id */, Text("Damn good coffee", StringUtf8Multilang::kEnglishCode), - Author(UID(987654321 /* hi */, 123456789 /* lo */), "Cole"), + Author("Cole"), 5.0 /* rating */, FromDaysAgo(now, 10)); reviews.emplace_back( 67812 /* id */, Text("Clean place, reasonably priced", StringUtf8Multilang::kDefaultCode), - Author(UID(0 /* hi */, 315 /* lo */), "Cooper"), 5.0 /* rating */, FromDaysAgo(now, 1)); + Author("Cooper"), 5.0 /* rating */, FromDaysAgo(now, 1)); - return UGC(records, reviews, 4.5 /* rating */); + return UGC(records, reviews, 4.5 /* rating */, 4000000000 /* votes */); } UGC MakeTestUGC2(Time now) @@ -38,9 +38,9 @@ UGC MakeTestUGC2(Time now) vector<Review> reviews; reviews.emplace_back( 119 /* id */, Text("This pie's so good it is a crime", StringUtf8Multilang::kDefaultCode), - Author(UID(0 /* hi */, 315 /* lo */), "Cooper"), 5.0 /* rating */, FromDaysAgo(now, 1)); + Author("Cooper"), 5.0 /* rating */, FromDaysAgo(now, 1)); - return UGC(records, reviews, 5.0 /* rating */); + return UGC(records, reviews, 5.0 /* rating */, 1 /* votes */); } UGCUpdate MakeTestUGCUpdate(Time now) diff --git a/ugc/ugc_tests/utils.hpp b/ugc/ugc_tests/utils.hpp index 82cb5b8588..cc4507bb8c 100644 --- a/ugc/ugc_tests/utils.hpp +++ b/ugc/ugc_tests/utils.hpp @@ -6,5 +6,6 @@ namespace ugc { UGC MakeTestUGC1(Time now = Clock::now()); UGC MakeTestUGC2(Time now = Clock::now()); + UGCUpdate MakeTestUGCUpdate(Time now = Clock::now()); } // namespace ugc |