From 703971ad1110e97b992289c8ada6c851acf6c35e Mon Sep 17 00:00:00 2001 From: Arsentiy Milchakov Date: Tue, 13 Nov 2018 15:58:52 +0300 Subject: [PATCH] [ugc] HasUGCForPlace method is added --- metrics/eye_info.hpp | 2 -- ugc/api.cpp | 18 ++++++++++++++ ugc/api.hpp | 12 ++++++++++ ugc/storage.cpp | 42 ++++++++++++++++++++++++--------- ugc/storage.hpp | 10 ++++++++ ugc/ugc_tests/storage_tests.cpp | 17 +++++++++++++ 6 files changed, 88 insertions(+), 13 deletions(-) diff --git a/metrics/eye_info.hpp b/metrics/eye_info.hpp index 827550dec7..89613ba0aa 100644 --- a/metrics/eye_info.hpp +++ b/metrics/eye_info.hpp @@ -1,7 +1,5 @@ #pragma once -#include "storage/index.hpp" - #include "geometry/mercator.hpp" #include "geometry/point2d.hpp" #include "geometry/tree4d.hpp" diff --git a/ugc/api.cpp b/ugc/api.cpp index af4bb051e6..8e09d24f39 100644 --- a/ugc/api.cpp +++ b/ugc/api.cpp @@ -1,5 +1,7 @@ #include "ugc/api.hpp" +#include "indexer/feature_data.hpp" + #include "base/assert.hpp" #include @@ -38,6 +40,16 @@ void Api::GetUGCToSend(UGCJsonToSendCallback const & callback) m_thread.Push([callback, this] { GetUGCToSendImpl(callback); }); } +void Api::HasUGCForPlace(feature::TypesHolder const & types, m2::PointD const & point, + HasUGCForPlaceCallback const & callback) +{ + m_thread.Push([this, editableTypes = types, point, callback]() mutable + { + editableTypes.SortBySpec(); + HasUGCForPlaceImpl(editableTypes.GetBestType(), point, callback); + }); +} + void Api::SendingCompleted() { m_thread.Push([this] { SendingCompletedImpl(); }); @@ -80,6 +92,12 @@ void Api::GetUGCToSendImpl(UGCJsonToSendCallback const & callback) callback(move(json), m_storage.GetNumberOfUnsynchronized()); } +void Api::HasUGCForPlaceImpl(uint32_t bestType, m2::PointD const & point, + HasUGCForPlaceCallback const & callback) const +{ + callback(m_storage.HasUGCForPlace(bestType, point)); +} + void Api::SendingCompletedImpl() { m_storage.MarkAllAsSynchronized(); diff --git a/ugc/api.hpp b/ugc/api.hpp index b531be5943..e77bfc6e1c 100644 --- a/ugc/api.hpp +++ b/ugc/api.hpp @@ -6,6 +6,8 @@ #include "platform/safe_callback.hpp" +#include "geometry/point2d.hpp" + #include "base/worker_thread.hpp" #include @@ -13,6 +15,11 @@ class DataSource; struct FeatureID; +namespace feature +{ +class TypesHolder; +} + namespace ugc { class Api @@ -23,6 +30,7 @@ public: using UGCJsonToSendCallback = std::function; using OnResultCallback = platform::SafeCallback; using NumberOfUnsynchronizedCallback = std::function; + using HasUGCForPlaceCallback = std::function; Api(DataSource const & dataSource, NumberOfUnsynchronizedCallback const & callback); @@ -30,6 +38,8 @@ public: void SetUGCUpdate(FeatureID const & id, UGCUpdate const & ugc, OnResultCallback const & callback = nullptr); void GetUGCToSend(UGCJsonToSendCallback const & callback); + void HasUGCForPlace(feature::TypesHolder const & types, m2::PointD const & point, + HasUGCForPlaceCallback const & callback); void SendingCompleted(); void SaveUGCOnDisk(); @@ -39,6 +49,8 @@ private: void GetUGCImpl(FeatureID const & id, UGCCallbackUnsafe const & callback); Storage::SettingResult SetUGCUpdateImpl(FeatureID const & id, UGCUpdate const & ugc); void GetUGCToSendImpl(UGCJsonToSendCallback const & callback); + void HasUGCForPlaceImpl(uint32_t bestType, m2::PointD const & point, + HasUGCForPlaceCallback const & callback) const; void SendingCompletedImpl(); void SaveUGCOnDiskImpl(); diff --git a/ugc/storage.cpp b/ugc/storage.cpp index 41f3a477a0..5dfe6a1791 100644 --- a/ugc/storage.cpp +++ b/ugc/storage.cpp @@ -7,6 +7,7 @@ #include "indexer/classificator.hpp" #include "indexer/feature_algo.hpp" +#include "indexer/feature_data.hpp" #include "indexer/feature_decl.hpp" #include "indexer/ftraits.hpp" @@ -155,17 +156,7 @@ UGCUpdate Storage::GetUGCUpdate(FeatureID const & id) const if (m_indexes.empty()) return {}; - auto const feature = GetFeature(id); - auto const mercator = feature::GetCenter(*feature); - feature::TypesHolder th(*feature); - th.SortBySpec(); - auto const & c = classif(); - auto const type = c.GetIndexForType(th.GetBestType()); - - auto const index = find_if( - m_indexes.begin(), m_indexes.end(), [type, &mercator](UpdateIndex const & index) -> bool { - return type == index.m_type && mercator == index.m_mercator && !index.m_deleted; - }); + auto const index = FindIndex(id); if (index == m_indexes.end()) return {}; @@ -291,6 +282,30 @@ void Storage::Migrate(string const & indexFilePath) } } +UpdateIndexes::const_iterator Storage::FindIndex(FeatureID const & id) const +{ + auto const feature = GetFeature(id); + auto const mercator = feature::GetCenter(*feature); + feature::TypesHolder th(*feature); + th.SortBySpec(); + + return FindIndex(th.GetBestType(), mercator); +} + +UpdateIndexes::const_iterator Storage::FindIndex(uint32_t bestType, + m2::PointD const & point) const +{ + auto const & c = classif(); + auto const typeIndex = c.GetIndexForType(bestType); + + return find_if( + m_indexes.begin(), m_indexes.end(), [typeIndex, &point](UpdateIndex const & index) -> bool { + // We are use 1e-5 eps because of points in mwm have this accuracy. + return typeIndex == index.m_type && point.EqualDxDy(index.m_mercator, 1e-5 /* eps */) && + !index.m_deleted; + }); +} + bool Storage::SaveIndex(std::string const & pathToTargetFile /* = "" */) const { if (m_indexes.empty()) @@ -442,6 +457,11 @@ size_t Storage::GetNumberOfUnsynchronized() const return numberOfUnsynchronized; } +bool Storage::HasUGCForPlace(uint32_t bestType, m2::PointD const & point) const +{ + return FindIndex(bestType, point) != m_indexes.end(); +} + void Storage::MarkAllAsSynchronized() { if (m_indexes.empty()) diff --git a/ugc/storage.hpp b/ugc/storage.hpp index b9282614e2..bda776f2fc 100644 --- a/ugc/storage.hpp +++ b/ugc/storage.hpp @@ -2,6 +2,8 @@ #include "ugc/types.hpp" +#include "geometry/point2d.hpp" + #include "base/thread_checker.hpp" #include @@ -11,6 +13,11 @@ class DataSource; class FeatureType; struct FeatureID; +namespace feature +{ +class TypesHolder; +} + namespace ugc { class Storage @@ -34,6 +41,7 @@ public: void Defragmentation(); void Load(); size_t GetNumberOfUnsynchronized() const; + bool HasUGCForPlace(uint32_t bestType, m2::PointD const & point) const; /// Testing UpdateIndexes & GetIndexesForTesting() { return m_indexes; } @@ -46,6 +54,8 @@ private: uint64_t UGCSizeAtIndex(size_t const indexPosition) const; std::unique_ptr GetFeature(FeatureID const & id) const; void Migrate(std::string const & indexFilePath); + UpdateIndexes::const_iterator FindIndex(FeatureID const & id) const; + UpdateIndexes::const_iterator FindIndex(uint32_t bestType, m2::PointD const & point) const; DataSource const & m_dataSource; UpdateIndexes m_indexes; diff --git a/ugc/ugc_tests/storage_tests.cpp b/ugc/ugc_tests/storage_tests.cpp index e7e0e6ec56..909700a472 100644 --- a/ugc/ugc_tests/storage_tests.cpp +++ b/ugc/ugc_tests/storage_tests.cpp @@ -604,3 +604,20 @@ UNIT_TEST(UGC_TooOldDataVersionsForMigration) TEST(DeleteUGCFile(IndexVersion::V0), ()); } +UNIT_CLASS_TEST(StorageTest, UGC_HasUGCForPlace) +{ + auto & builder = MwmBuilder::Builder(); + m2::PointD const point(1.0, 1.0); + builder.Build({TestCafe(point)}); + auto const id = builder.FeatureIdForCafeAtPoint(point); + auto const original = MakeTestUGCUpdate(Time(chrono::hours(24 * 300))); + Storage storage(builder.GetDataSource()); + storage.Load(); + TEST_EQUAL(storage.SetUGCUpdate(id, original), Storage::SettingResult::Success, ()); + auto const actual = storage.GetUGCUpdate(id); + TEST_EQUAL(original, actual, ()); + + auto const & c = classif(); + auto const cafeType = c.GetTypeByReadableObjectName("amenity-cafe"); + TEST(storage.HasUGCForPlace(cafeType, point), ()); +}