Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mapsme/omim.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArsentiy Milchakov <milcars@mapswithme.com>2018-01-19 13:42:39 +0300
committerYuri Gorshenin <mipt.vi002@gmail.com>2018-01-22 19:53:52 +0300
commit742732c65f15ec2d15d33105587f7bd17e4f1010 (patch)
tree24a34a8163087436ae8cde35f4e997286c839864
parentad6272577d0d571751ba7e7039638bf969bf7b42 (diff)
[search][ugc] UGC ratings in search
-rw-r--r--android/jni/com/mapswithme/maps/SearchEngine.cpp30
-rw-r--r--android/jni/com/mapswithme/maps/SearchEngine.hpp3
-rw-r--r--android/jni/com/mapswithme/maps/discovery/DiscoveryManager.cpp6
-rw-r--r--iphone/Maps/Core/Search/MWMSearch.h1
-rw-r--r--iphone/Maps/Core/Search/MWMSearch.mm10
-rw-r--r--iphone/Maps/UI/Search/TableView/MWMSearchCommonCell.h3
-rw-r--r--iphone/Maps/UI/Search/TableView/MWMSearchCommonCell.mm10
-rw-r--r--iphone/Maps/UI/Search/TableView/MWMSearchTableViewController.mm3
-rw-r--r--map/everywhere_search_params.hpp3
-rw-r--r--map/framework.cpp12
-rw-r--r--map/framework.hpp1
-rw-r--r--map/search_api.cpp12
-rw-r--r--map/search_api.hpp7
-rw-r--r--qt/search_panel.cpp3
-rw-r--r--search/everywhere_search_callback.cpp7
-rw-r--r--search/everywhere_search_callback.hpp5
-rw-r--r--search/intermediate_result.cpp6
-rw-r--r--ugc/api.cpp5
-rw-r--r--ugc/api.hpp2
-rw-r--r--ugc/loader.cpp14
-rw-r--r--ugc/loader.hpp8
21 files changed, 109 insertions, 42 deletions
diff --git a/android/jni/com/mapswithme/maps/SearchEngine.cpp b/android/jni/com/mapswithme/maps/SearchEngine.cpp
index 921d599b07..ad5c8e87de 100644
--- a/android/jni/com/mapswithme/maps/SearchEngine.cpp
+++ b/android/jni/com/mapswithme/maps/SearchEngine.cpp
@@ -4,6 +4,7 @@
#include "com/mapswithme/platform/Platform.hpp"
#include "map/everywhere_search_params.hpp"
+#include "map/place_page_info.hpp"
#include "map/viewport_search_params.hpp"
#include "search/hotels_filter.hpp"
@@ -331,8 +332,8 @@ jmethodID g_mapResultCtor;
booking::AvailabilityParams g_lastBookingFilterParams;
-jobject ToJavaResult(Result & result, bool isLocalAdsCustomer, bool hasPosition, double lat,
- double lon)
+jobject ToJavaResult(Result & result, bool isLocalAdsCustomer, float ugcRating, bool hasPosition,
+ double lat, double lon)
{
JNIEnv * env = jni::GetEnv();
::Framework * fr = g_framework->NativeFramework();
@@ -373,8 +374,13 @@ jobject ToJavaResult(Result & result, bool isLocalAdsCustomer, bool hasPosition,
jni::TScopedLocalRef address(env, jni::ToJavaString(env, result.GetAddress()));
jni::TScopedLocalRef dist(env, jni::ToJavaString(env, distance));
jni::TScopedLocalRef cuisine(env, jni::ToJavaString(env, result.GetCuisine()));
- jni::TScopedLocalRef rating(env, jni::ToJavaString(env, result.GetHotelRating()));
jni::TScopedLocalRef pricing(env, jni::ToJavaString(env, result.GetHotelApproximatePricing()));
+
+ string ratingTmp = result.GetHotelRating();
+ if (ratingTmp.empty() && ugcRating > 0.f)
+ ratingTmp = place_page::rating::GetRatingFormatted(ugcRating);
+ jni::TScopedLocalRef rating(env, jni::ToJavaString(env, ratingTmp));
+
jni::TScopedLocalRef desc(env, env->NewObject(g_descriptionClass, g_descriptionConstructor,
featureId.get(), featureType.get(), address.get(),
dist.get(), cuisine.get(),
@@ -391,7 +397,8 @@ jobject ToJavaResult(Result & result, bool isLocalAdsCustomer, bool hasPosition,
}
void OnResults(Results const & results, vector<bool> const & isLocalAdsCustomer,
- long long timestamp, bool isMapAndTable, bool hasPosition, double lat, double lon)
+ vector<float> const & ugcRatings, long long timestamp, bool isMapAndTable,
+ bool hasPosition, double lat, double lon)
{
// Ignore results from obsolete searches.
if (g_queryTimestamp > timestamp)
@@ -402,7 +409,7 @@ void OnResults(Results const & results, vector<bool> const & isLocalAdsCustomer,
if (!results.IsEndMarker() || results.IsEndedNormal())
{
jni::TScopedLocalObjectArrayRef jResults(
- env, BuildSearchResults(results, isLocalAdsCustomer, hasPosition, lat, lon));
+ env, BuildSearchResults(results, isLocalAdsCustomer, ugcRatings, hasPosition, lat, lon));
env->CallVoidMethod(g_javaListener, g_updateResultsId, jResults.get(),
static_cast<jlong>(timestamp),
search::HotelsClassifier::IsHotelResults(results));
@@ -460,7 +467,8 @@ void OnBookingFilterResults(booking::AvailabilityParams const & params,
} // namespace
jobjectArray BuildSearchResults(Results const & results, vector<bool> const & isLocalAdsCustomer,
- bool hasPosition, double lat, double lon)
+ vector<float> const & ugcRatings, bool hasPosition, double lat,
+ double lon)
{
JNIEnv * env = jni::GetEnv();
@@ -470,10 +478,12 @@ jobjectArray BuildSearchResults(Results const & results, vector<bool> const & is
jobjectArray const jResults = env->NewObjectArray(count, g_resultClass, nullptr);
ASSERT_EQUAL(results.GetCount(), isLocalAdsCustomer.size(), ());
+ ASSERT_EQUAL(results.GetCount(), ugcRatings.size(), ());
+
for (int i = 0; i < count; i++)
{
- jni::TScopedLocalRef jRes(
- env, ToJavaResult(g_results[i], isLocalAdsCustomer[i], hasPosition, lat, lon));
+ jni::TScopedLocalRef jRes(env, ToJavaResult(g_results[i], isLocalAdsCustomer[i], ugcRatings[i],
+ hasPosition, lat, lon));
env->SetObjectArrayElement(jResults, i, jRes.get());
}
return jResults;
@@ -519,7 +529,7 @@ extern "C"
search::EverywhereSearchParams params;
params.m_query = jni::ToNativeString(env, bytes);
params.m_inputLocale = jni::ToNativeString(env, lang);
- params.m_onResults = bind(&OnResults, _1, _2, timestamp, false, hasPosition, lat, lon);
+ params.m_onResults = bind(&OnResults, _1, _2, _3, timestamp, false, hasPosition, lat, lon);
params.m_hotelsFilter = g_hotelsFilterBuilder.Build(env, hotelsFilter);
g_lastBookingFilterParams = g_bookingAvailabilityParamsBuilder.Build(env, bookingFilterParams);
params.m_bookingFilterParams.m_params = g_lastBookingFilterParams;
@@ -553,7 +563,7 @@ extern "C"
search::EverywhereSearchParams eparams;
eparams.m_query = vparams.m_query;
eparams.m_inputLocale = vparams.m_inputLocale;
- eparams.m_onResults = bind(&OnResults, _1, _2, timestamp, isMapAndTable,
+ eparams.m_onResults = bind(&OnResults, _1, _2, _3, timestamp, isMapAndTable,
false /* hasPosition */, 0.0 /* lat */, 0.0 /* lon */);
eparams.m_hotelsFilter = vparams.m_hotelsFilter;
if (g_framework->NativeFramework()->SearchEverywhere(eparams))
diff --git a/android/jni/com/mapswithme/maps/SearchEngine.hpp b/android/jni/com/mapswithme/maps/SearchEngine.hpp
index 949c289a32..7942b95342 100644
--- a/android/jni/com/mapswithme/maps/SearchEngine.hpp
+++ b/android/jni/com/mapswithme/maps/SearchEngine.hpp
@@ -8,4 +8,5 @@
jobjectArray BuildSearchResults(search::Results const & results,
std::vector<bool> const & isLocalAdsCustomer,
- bool hasPosition, double lat, double lon);
+ std::vector<float> const & ugcRatings, bool hasPosition, double lat,
+ double lon);
diff --git a/android/jni/com/mapswithme/maps/discovery/DiscoveryManager.cpp b/android/jni/com/mapswithme/maps/discovery/DiscoveryManager.cpp
index 2118b82a3c..963218e1e3 100644
--- a/android/jni/com/mapswithme/maps/discovery/DiscoveryManager.cpp
+++ b/android/jni/com/mapswithme/maps/discovery/DiscoveryManager.cpp
@@ -69,9 +69,9 @@ struct DiscoveryCallback
auto const lat = MercatorBounds::YToLat(viewportCenter.y);
auto const lon = MercatorBounds::XToLon(viewportCenter.x);
std::vector<bool> customers(results.GetCount(), false);
- jni::TScopedLocalObjectArrayRef jResults(env, BuildSearchResults(results, customers,
- true /* hasPosition */,
- lat, lon));
+ std::vector<float> ugcRatings(results.GetCount(), -1.f);
+ jni::TScopedLocalObjectArrayRef jResults(
+ env, BuildSearchResults(results, customers, ugcRatings, true /* hasPosition */, lat, lon));
jobject discoveryManagerInstance = env->GetStaticObjectField(g_discoveryManagerClass,
g_discoveryManagerInstanceField);
env->CallVoidMethod(discoveryManagerInstance, g_onResultReceivedMethod,
diff --git a/iphone/Maps/Core/Search/MWMSearch.h b/iphone/Maps/Core/Search/MWMSearch.h
index b73e917b63..36f96d6799 100644
--- a/iphone/Maps/Core/Search/MWMSearch.h
+++ b/iphone/Maps/Core/Search/MWMSearch.h
@@ -22,6 +22,7 @@ class Result;
+ (NSUInteger)containerIndexWithRow:(NSUInteger)row;
+ (search::Result const &)resultWithContainerIndex:(NSUInteger)index;
+ (BOOL)isLocalAdsWithContainerIndex:(NSUInteger)index;
++ (CGFloat)ugcRatingWithContainerIndex:(NSUInteger)index;
+ (id<MWMBanner>)adWithContainerIndex:(NSUInteger)index;
+ (BOOL)isBookingAvailableWithContainerIndex:(NSUInteger)index;
diff --git a/iphone/Maps/Core/Search/MWMSearch.mm b/iphone/Maps/Core/Search/MWMSearch.mm
index a4407dc490..2b57ea788c 100644
--- a/iphone/Maps/Core/Search/MWMSearch.mm
+++ b/iphone/Maps/Core/Search/MWMSearch.mm
@@ -51,6 +51,7 @@ using Observers = NSHashTable<Observer>;
search::Results m_viewportResults;
std::vector<bool> m_isLocalAdsCustomer;
std::vector<FeatureID> m_bookingAvailableFeatureIDs;
+ std::vector<float> m_ugcRatings;
}
#pragma mark - Instance
@@ -81,12 +82,14 @@ using Observers = NSHashTable<Observer>;
self.lastSearchTimestamp += 1;
NSUInteger const timestamp = self.lastSearchTimestamp;
m_everywhereParams.m_onResults = [self, timestamp](search::Results const & results,
- vector<bool> const & isLocalAdsCustomer) {
+ vector<bool> const & isLocalAdsCustomer,
+ vector<float> const & ugcRatings) {
if (timestamp == self.lastSearchTimestamp)
{
self->m_everywhereResults = results;
self->m_isLocalAdsCustomer = isLocalAdsCustomer;
+ self->m_ugcRatings = ugcRatings;
self.suggestionsCount = results.GetSuggestsCount();
[self onSearchResultsUpdated];
@@ -218,6 +221,11 @@ using Observers = NSHashTable<Observer>;
return [MWMSearch manager]->m_isLocalAdsCustomer[index];
}
++ (CGFloat)ugcRatingWithContainerIndex:(NSUInteger)index
+{
+ return [MWMSearch manager]->m_ugcRatings[index];
+}
+
+ (id<MWMBanner>)adWithContainerIndex:(NSUInteger)index
{
return [[MWMSearch manager].banners bannerAtIndex:index];
diff --git a/iphone/Maps/UI/Search/TableView/MWMSearchCommonCell.h b/iphone/Maps/UI/Search/TableView/MWMSearchCommonCell.h
index 1807591968..decf8114f9 100644
--- a/iphone/Maps/UI/Search/TableView/MWMSearchCommonCell.h
+++ b/iphone/Maps/UI/Search/TableView/MWMSearchCommonCell.h
@@ -6,6 +6,7 @@
- (void)config:(search::Result const &)result
isLocalAds:(BOOL)isLocalAds
- isAvailable:(BOOL)isAvailable;
+ isAvailable:(BOOL)isAvailable
+ ugcRating:(CGFloat)ugcRating;
@end
diff --git a/iphone/Maps/UI/Search/TableView/MWMSearchCommonCell.mm b/iphone/Maps/UI/Search/TableView/MWMSearchCommonCell.mm
index c443107b4d..41a50817d3 100644
--- a/iphone/Maps/UI/Search/TableView/MWMSearchCommonCell.mm
+++ b/iphone/Maps/UI/Search/TableView/MWMSearchCommonCell.mm
@@ -3,8 +3,11 @@
#import "MWMLocationManager.h"
#include "geometry/mercator.hpp"
+
#include "platform/measurement_utils.hpp"
+#include "map/place_page_info.hpp"
+
@interface MWMSearchCommonCell ()
@property(nonatomic) IBOutletCollection(UIImageView) NSArray * infoRatingStars;
@@ -27,11 +30,14 @@
- (void)config:(search::Result const &)result
isLocalAds:(BOOL)isLocalAds
- isAvailable:(BOOL)isAvailable
+ isAvailable:(BOOL)isAvailable
+ ugcRating:(CGFloat)ugcRating
{
[super config:result];
self.typeLabel.text = @(result.GetFeatureTypeName().c_str()).capitalizedString;
- auto const & ratingStr = result.GetHotelRating();
+ auto ratingStr = result.GetHotelRating();
+ if (ratingStr.empty() && ugcRating > 0.f)
+ ratingStr = place_page::rating::GetRatingFormatted(ugcRating);
self.ratingLabel.text =
ratingStr.empty() ? @"" : [NSString stringWithFormat:L(@"place_page_booking_rating"),
ratingStr.c_str()];
diff --git a/iphone/Maps/UI/Search/TableView/MWMSearchTableViewController.mm b/iphone/Maps/UI/Search/TableView/MWMSearchTableViewController.mm
index 6366b747ea..dd80ad164b 100644
--- a/iphone/Maps/UI/Search/TableView/MWMSearchTableViewController.mm
+++ b/iphone/Maps/UI/Search/TableView/MWMSearchTableViewController.mm
@@ -89,7 +89,8 @@
auto const & result = [MWMSearch resultWithContainerIndex:containerIndex];
auto const isLocalAds = [MWMSearch isLocalAdsWithContainerIndex:containerIndex];
auto const isBookingAvailable = [MWMSearch isBookingAvailableWithContainerIndex:containerIndex];
- [cell config:result isLocalAds:isLocalAds isAvailable:isBookingAvailable];
+ auto const ugcRating = [MWMSearch ugcRatingWithContainerIndex:containerIndex];
+ [cell config:result isLocalAds:isLocalAds isAvailable:isBookingAvailable ugcRating:ugcRating];
return cell;
}
case MWMSearchItemTypeMopub:
diff --git a/map/everywhere_search_params.hpp b/map/everywhere_search_params.hpp
index 49f8c6ce00..ec1226e4ee 100644
--- a/map/everywhere_search_params.hpp
+++ b/map/everywhere_search_params.hpp
@@ -15,7 +15,8 @@ namespace search
struct EverywhereSearchParams
{
using OnResults =
- std::function<void(Results const & results, std::vector<bool> const & isLocalAdsCustomer)>;
+ std::function<void(Results const & results, std::vector<bool> const & isLocalAdsCustomer,
+ std::vector<float> const & ugcRatings)>;
std::string m_query;
std::string m_inputLocale;
diff --git a/map/framework.cpp b/map/framework.cpp
index c912a36fb1..607471b84c 100644
--- a/map/framework.cpp
+++ b/map/framework.cpp
@@ -3256,6 +3256,18 @@ bool Framework::IsLocalAdsCustomer(search::Result const & result) const
return m_localAdsManager.Contains(result.GetFeatureID());
}
+float Framework::GetUgcRating(search::Result const & result) const
+{
+ ASSERT(m_ugcApi, ());
+
+ if (result.GetResultType() != search::Result::Type::Feature)
+ return -1.f;
+
+ auto const ugc = m_ugcApi->GetLoader().GetUGC(result.GetFeatureID());
+
+ return ugc.m_totalRating;
+}
+
double Framework::GetMinDistanceBetweenResults() const
{
return m_searchMarks.GetMaxDimension(m_currentModelView);
diff --git a/map/framework.hpp b/map/framework.hpp
index 5c1a4db61e..13c7f84d63 100644
--- a/map/framework.hpp
+++ b/map/framework.hpp
@@ -359,6 +359,7 @@ public:
boost::optional<m2::PointD> GetCurrentPosition() const override;
bool ParseSearchQueryCommand(search::SearchParams const & params) override;
bool IsLocalAdsCustomer(search::Result const & result) const override;
+ float GetUgcRating(search::Result const & result) const override;
double GetMinDistanceBetweenResults() const override;
private:
diff --git a/map/search_api.cpp b/map/search_api.cpp
index de3bd15661..7136831a64 100644
--- a/map/search_api.cpp
+++ b/map/search_api.cpp
@@ -176,10 +176,11 @@ bool SearchAPI::SearchEverywhere(EverywhereSearchParams const & params)
p.m_onResults = EverywhereSearchCallback(
static_cast<EverywhereSearchCallback::Delegate &>(*this),
- [this, params](Results const & results, vector<bool> const & isLocalAdsCustomer) {
+ [this, params](Results const & results, vector<bool> const & isLocalAdsCustomer,
+ vector<float> const & ugcRatings) {
if (params.m_onResults)
- RunUITask([params, results, isLocalAdsCustomer] {
- params.m_onResults(results, isLocalAdsCustomer);
+ RunUITask([params, results, isLocalAdsCustomer, ugcRatings] {
+ params.m_onResults(results, isLocalAdsCustomer, ugcRatings);
});
if (results.IsEndedNormal() && !params.m_bookingFilterParams.IsEmpty())
{
@@ -339,6 +340,11 @@ bool SearchAPI::IsLocalAdsCustomer(Result const & result) const
return m_delegate.IsLocalAdsCustomer(result);
}
+float SearchAPI::GetUgcRating(search::Result const & result) const
+{
+ return m_delegate.GetUgcRating(result);
+}
+
void SearchAPI::OnBookmarksCreated(vector<pair<df::MarkID, BookmarkData>> const & marks)
{
vector<BookmarkIdDoc> data;
diff --git a/map/search_api.hpp b/map/search_api.hpp
index 20a3d4ec65..e81783e8b9 100644
--- a/map/search_api.hpp
+++ b/map/search_api.hpp
@@ -94,9 +94,9 @@ public:
{
}
- virtual void OnBookingFilterParamsUpdate(booking::AvailabilityParams const & params)
- {
- }
+ virtual void OnBookingFilterParamsUpdate(booking::AvailabilityParams const & params) {}
+
+ virtual float GetUgcRating(search::Result const & /* result */) const { return -1.f; }
};
SearchAPI(Index & index, storage::Storage const & storage,
@@ -141,6 +141,7 @@ public:
void ShowViewportSearchResults(bool clear, search::Results::ConstIter begin,
search::Results::ConstIter end) override;
bool IsLocalAdsCustomer(search::Result const & result) const override;
+ float GetUgcRating(search::Result const & result) const override;
void OnBookmarksCreated(std::vector<std::pair<df::MarkID, BookmarkData>> const & marks);
void OnBookmarksUpdated(std::vector<std::pair<df::MarkID, BookmarkData>> const & marks);
diff --git a/qt/search_panel.cpp b/qt/search_panel.cpp
index bb30680135..c39e619205 100644
--- a/qt/search_panel.cpp
+++ b/qt/search_panel.cpp
@@ -261,7 +261,8 @@ void SearchPanel::OnSearchTextChanged(QString const & str)
m_params.m_query = normalized.toUtf8().constData();
auto const timestamp = ++m_timestamp;
m_params.m_onResults = [this, timestamp](search::Results const & results,
- vector<bool> const & /* isLocalAdsCustomer */) {
+ vector<bool> const & /* isLocalAdsCustomer */,
+ vector<float> const & /* ugcRatings */) {
GetPlatform().RunTask(Platform::Thread::Gui, bind(&SearchPanel::OnSearchResults, this,
timestamp, results));
};
diff --git a/search/everywhere_search_callback.cpp b/search/everywhere_search_callback.cpp
index 9b80cda188..52b9db7d9b 100644
--- a/search/everywhere_search_callback.cpp
+++ b/search/everywhere_search_callback.cpp
@@ -12,13 +12,18 @@ EverywhereSearchCallback::EverywhereSearchCallback(Delegate & delegate, OnResult
void EverywhereSearchCallback::operator()(Results const & results)
{
+ ASSERT_EQUAL(m_isLocalAdsCustomer.size(), m_ugcRatings.size(), ());
+
auto const prevSize = m_isLocalAdsCustomer.size();
ASSERT_LESS_OR_EQUAL(prevSize, results.GetCount(), ());
for (size_t i = prevSize; i < results.GetCount(); ++i)
+ {
m_isLocalAdsCustomer.push_back(m_delegate.IsLocalAdsCustomer(results[i]));
+ m_ugcRatings.push_back(m_delegate.GetUgcRating(results[i]));
+ }
ASSERT_EQUAL(m_isLocalAdsCustomer.size(), results.GetCount(), ());
- m_onResults(results, m_isLocalAdsCustomer);
+ m_onResults(results, m_isLocalAdsCustomer, m_ugcRatings);
}
} // namespace search
diff --git a/search/everywhere_search_callback.hpp b/search/everywhere_search_callback.hpp
index a31e5abd02..3d9e39b31b 100644
--- a/search/everywhere_search_callback.hpp
+++ b/search/everywhere_search_callback.hpp
@@ -20,12 +20,14 @@ public:
virtual ~Delegate() = default;
virtual bool IsLocalAdsCustomer(Result const & result) const = 0;
+ virtual float GetUgcRating(Result const & result) const = 0;
};
// The signature of the callback should be the same as EverywhereSaerchParams::OnResults, but
// EverywhereSaerchParams is located in map project and we do not need dependency.
using OnResults =
- std::function<void(Results const & results, std::vector<bool> const & isLocalAdsCustomer)>;
+ std::function<void(Results const & results, std::vector<bool> const & isLocalAdsCustomer,
+ std::vector<float> const & ugcRatings)>;
EverywhereSearchCallback(Delegate & delegate, OnResults onResults);
@@ -35,5 +37,6 @@ private:
Delegate & m_delegate;
OnResults m_onResults;
std::vector<bool> m_isLocalAdsCustomer;
+ std::vector<float> m_ugcRatings;
};
} // namespace search
diff --git a/search/intermediate_result.cpp b/search/intermediate_result.cpp
index 10c5267fa8..374f42243f 100644
--- a/search/intermediate_result.cpp
+++ b/search/intermediate_result.cpp
@@ -1,6 +1,6 @@
-#include "intermediate_result.hpp"
-#include "geometry_utils.hpp"
-#include "reverse_geocoder.hpp"
+#include "search/intermediate_result.hpp"
+#include "search/geometry_utils.hpp"
+#include "search/reverse_geocoder.hpp"
#include "storage/country_info_getter.hpp"
diff --git a/ugc/api.cpp b/ugc/api.cpp
index 65f77af714..f9b45acde3 100644
--- a/ugc/api.cpp
+++ b/ugc/api.cpp
@@ -44,6 +44,11 @@ void Api::SaveUGCOnDisk()
m_thread.Push([this] { SaveUGCOnDiskImpl(); });
}
+Loader & Api::GetLoader()
+{
+ return m_loader;
+}
+
void Api::GetUGCImpl(FeatureID const & id, UGCCallbackUnsafe const & callback)
{
CHECK(callback, ());
diff --git a/ugc/api.hpp b/ugc/api.hpp
index 9af3ef365a..6b08de71b6 100644
--- a/ugc/api.hpp
+++ b/ugc/api.hpp
@@ -32,6 +32,8 @@ public:
void SendingCompleted();
void SaveUGCOnDisk();
+ Loader & GetLoader();
+
private:
void GetUGCImpl(FeatureID const & id, UGCCallbackUnsafe const & callback);
Storage::SettingResult SetUGCUpdateImpl(FeatureID const & id, UGCUpdate const & ugc);
diff --git a/ugc/loader.cpp b/ugc/loader.cpp
index 6fa54deffb..ce57c4c5bc 100644
--- a/ugc/loader.cpp
+++ b/ugc/loader.cpp
@@ -21,17 +21,15 @@ UGC Loader::GetUGC(FeatureID const & featureId)
if (!value.m_cont.IsExist(UGC_FILE_TAG))
return {};
- if (m_currentMwmId != featureId.m_mwmId)
+ UGC ugc;
{
- m_currentMwmId = featureId.m_mwmId;
- m_d = binary::UGCDeserializer();
- }
+ std::lock_guard<std::mutex> lock(m_mutex);
- auto readerPtr = value.m_cont.GetReader(UGC_FILE_TAG);
+ auto deserializer = m_deserializers[featureId.m_mwmId];
+ auto readerPtr = value.m_cont.GetReader(UGC_FILE_TAG);
- UGC ugc;
- if (!m_d.Deserialize(*readerPtr.GetPtr(), featureId.m_index, ugc))
- return {};
+ deserializer.Deserialize(*readerPtr.GetPtr(), featureId.m_index, ugc);
+ }
return ugc;
}
diff --git a/ugc/loader.hpp b/ugc/loader.hpp
index 0491fe8027..f141e841c7 100644
--- a/ugc/loader.hpp
+++ b/ugc/loader.hpp
@@ -5,11 +5,15 @@
#include "indexer/mwm_set.hpp"
+#include <map>
+#include <mutex>
+
class Index;
struct FeatureID;
namespace ugc
{
+// *NOTE* This class IS thread-safe.
class Loader
{
public:
@@ -18,7 +22,7 @@ public:
private:
Index const & m_index;
- MwmSet::MwmId m_currentMwmId;
- binary::UGCDeserializer m_d;
+ std::map<MwmSet::MwmId, binary::UGCDeserializer> m_deserializers;
+ std::mutex m_mutex;
};
} // namespace ugc