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:
authorDaria Volvenkova <d.volvenkova@corp.mail.ru>2017-08-28 15:07:27 +0300
committerRoman Kuznetsov <r.kuznetsow@gmail.com>2017-08-28 18:14:45 +0300
commit753499146c8f8365abe4f3018171d8f0c3188819 (patch)
treef7ae9ebf5960b5336a9b3a6cc08c9b762cbf5f24
parenta8428f9ffeb0c4ae2ebe449953ab9d321e41aad1 (diff)
Locals API. First iteration.
-rw-r--r--map/framework.cpp24
-rw-r--r--map/framework.hpp5
-rw-r--r--map/place_page_info.hpp16
-rw-r--r--partners_api/CMakeLists.txt2
-rw-r--r--partners_api/locals_api.cpp174
-rw-r--r--partners_api/locals_api.hpp64
-rw-r--r--partners_api/partners_api.pro2
-rw-r--r--xcode/partners_api/partners_api.xcodeproj/project.pbxproj8
8 files changed, 295 insertions, 0 deletions
diff --git a/map/framework.cpp b/map/framework.cpp
index 602ce0094b..87adbe3efa 100644
--- a/map/framework.cpp
+++ b/map/framework.cpp
@@ -552,6 +552,15 @@ cian::Api * Framework::GetCianApi(platform::NetworkPolicy const & policy)
return nullptr;
}
+locals::Api * Framework::GetLocalsApi(platform::NetworkPolicy const & policy)
+{
+ ASSERT(m_localsApi, ());
+ if (policy.CanUse())
+ return m_localsApi.get();
+
+ return nullptr;
+}
+
void Framework::ShowNode(storage::TCountryId const & countryId)
{
StopLocationFollow();
@@ -891,6 +900,8 @@ void Framework::FillInfoFromFeatureType(FeatureType const & ft, place_page::Info
info.SetPreviewIsExtended();
}
+ FillLocalExperts(ft, info);
+
auto const mwmInfo = ft.GetID().m_mwmId.GetInfo();
bool const isMapVersionEditable = mwmInfo && mwmInfo->m_version.IsEditableMap();
bool const canEditOrAdd = featureStatus != osm::Editor::FeatureStatus::Obsolete && CanEditMap() &&
@@ -3423,3 +3434,16 @@ void Framework::InjectViator(place_page::Info & info)
},
rect, scales::GetUpperScale(), mwmId);
}
+
+void Framework::FillLocalExperts(FeatureType const & ft, place_page::Info & info) const
+{
+ if (GetDrawScale() > scales::GetUpperWorldScale() ||
+ !ftypes::IsCityChecker::Instance()(ft))
+ {
+ info.SetLocalsStatus(place_page::LocalsStatus::NotAvailable);
+ return;
+ }
+
+ info.SetLocalsStatus(place_page::LocalsStatus::Available);
+ info.SetLocalsPageUrl(locals::Api::GetLocalsPageUrl());
+}
diff --git a/map/framework.hpp b/map/framework.hpp
index e2f33fe291..1be36f1ac4 100644
--- a/map/framework.hpp
+++ b/map/framework.hpp
@@ -46,6 +46,7 @@
#include "partners_api/booking_api.hpp"
#include "partners_api/cian_api.hpp"
+#include "partners_api/locals_api.hpp"
#include "partners_api/taxi_engine.hpp"
#include "partners_api/viator_api.hpp"
@@ -177,6 +178,7 @@ protected:
unique_ptr<booking::Api> m_bookingApi = make_unique<booking::Api>();
unique_ptr<viator::Api> m_viatorApi = make_unique<viator::Api>();
unique_ptr<cian::Api> m_cianApi = make_unique<cian::Api>();
+ unique_ptr<locals::Api> m_localsApi = make_unique<locals::Api>();
df::DrapeApi m_drapeApi;
@@ -218,6 +220,7 @@ public:
viator::Api * GetViatorApi(platform::NetworkPolicy const & policy);
taxi::Engine * GetTaxiEngine(platform::NetworkPolicy const & policy);
cian::Api * GetCianApi(platform::NetworkPolicy const & policy);
+ locals::Api * GetLocalsApi(platform::NetworkPolicy const & policy);
df::DrapeApi & GetDrapeApi() { return m_drapeApi; }
@@ -831,4 +834,6 @@ private:
/// Find feature with viator near point, provided in |info|, and inject viator data into |info|.
void InjectViator(place_page::Info & info);
+
+ void FillLocalExperts(FeatureType const & ft, place_page::Info & info) const;
};
diff --git a/map/place_page_info.hpp b/map/place_page_info.hpp
index 74b94018a8..f454e3a00c 100644
--- a/map/place_page_info.hpp
+++ b/map/place_page_info.hpp
@@ -46,6 +46,12 @@ enum class LocalAdsStatus
Customer
};
+enum class LocalsStatus
+{
+ NotAvailable,
+ Available
+};
+
class Info : public osm::MapObject
{
public:
@@ -149,6 +155,12 @@ public:
return m_reachableByProviders;
}
+ /// Local experts
+ void SetLocalsStatus(LocalsStatus status) { m_localsStatus = status; }
+ LocalsStatus GetLocalsStatus() const { return m_localsStatus; }
+ void SetLocalsPageUrl(std::string const & url) { m_localsUrl = url; }
+ std::string const & GetLocalsPageUrl() const { return m_localsUrl; }
+
/// Local ads
void SetLocalAdsStatus(LocalAdsStatus status) { m_localAdsStatus = status; }
LocalAdsStatus GetLocalAdsStatus() const { return m_localAdsStatus; }
@@ -251,5 +263,9 @@ private:
/// Booking
std::string m_bookingSearchUrl;
+
+ /// Local experts
+ std::string m_localsUrl;
+ LocalsStatus m_localsStatus = LocalsStatus::NotAvailable;
};
} // namespace place_page
diff --git a/partners_api/CMakeLists.txt b/partners_api/CMakeLists.txt
index cb4d3e3355..8af42c3e9a 100644
--- a/partners_api/CMakeLists.txt
+++ b/partners_api/CMakeLists.txt
@@ -17,6 +17,8 @@ set(
facebook_ads.hpp
google_ads.cpp
google_ads.hpp
+ locals_api.cpp
+ locals_api.hpp
mopub_ads.cpp
mopub_ads.hpp
opentable_api.cpp
diff --git a/partners_api/locals_api.cpp b/partners_api/locals_api.cpp
new file mode 100644
index 0000000000..2ee0f995be
--- /dev/null
+++ b/partners_api/locals_api.cpp
@@ -0,0 +1,174 @@
+#include "partners_api/locals_api.hpp"
+
+#include "platform/http_client.hpp"
+#include "platform/platform.hpp"
+#include "platform/preferred_languages.hpp"
+
+#include "coding/multilang_utf8_string.hpp"
+#include "coding/url_encode.hpp"
+
+#include "base/logging.hpp"
+#include "base/string_utils.hpp"
+
+#include "3party/jansson/myjansson.hpp"
+
+#include "private.h"
+
+namespace
+{
+using namespace locals;
+
+bool CheckJsonArray(json_t const * data)
+{
+ if (data == nullptr)
+ return false;
+ return json_is_array(data) && json_array_size(data) > 0;
+}
+
+void ParseError(std::string const & src, ErrorCode & errorCode, std::string & message)
+{
+ message.clear();
+ my::Json root(src.c_str());
+ int code = 0;
+ FromJSONObject(root.get(), "code", code);
+ FromJSONObject(root.get(), "message", message);
+ // TODO(darina): Process real error codes.
+ errorCode = code > 0 ? ErrorCode::NoLocals : ErrorCode::RemoteError;
+}
+
+void ParseLocals(std::string const & src, std::vector<LocalExpert> & locals,
+ bool & hasPrevious, bool & hasNext)
+{
+ locals.clear();
+ my::Json root(src.c_str());
+ auto previousField = my::GetJSONOptionalField(root.get(), "previous");
+ auto nextField = my::GetJSONOptionalField(root.get(), "next");
+ hasPrevious = json_is_number(previousField);
+ hasNext = json_is_number(nextField);
+ auto const results = json_object_get(root.get(), "results");
+ if (!CheckJsonArray(results))
+ return;
+ auto const dataSize = json_array_size(results);
+ for (size_t i = 0; i < dataSize; ++i)
+ {
+ LocalExpert local;
+ auto const item = json_array_get(results, i);
+ FromJSONObject(item, "id", local.m_id);
+ FromJSONObject(item, "motto", local.m_motto);
+ FromJSONObject(item, "link", local.m_pageUrl);
+ FromJSONObject(item, "photo", local.m_photoUrl);
+ FromJSONObject(item, "name", local.m_name);
+ FromJSONObject(item, "country", local.m_country);
+ FromJSONObject(item, "city", local.m_city);
+ FromJSONObject(item, "rating", local.m_rating);
+ FromJSONObject(item, "reviews", local.m_reviewCount);
+ FromJSONObject(item, "price_per_hour", local.m_pricePerHour);
+ FromJSONObject(item, "currency", local.m_currency);
+ FromJSONObject(item, "about_me", local.m_aboutExpert);
+ FromJSONObject(item, "i_will_show_you", local.m_offerDescription);
+ locals.push_back(move(local));
+ }
+}
+} // namespace
+
+namespace locals
+{
+bool RawApi::Get(double lat, double lon, std::string const & lang, size_t resultsOnPage, size_t pageNumber,
+ std::string & result)
+{
+ result.clear();
+ std::ostringstream ostream;
+ ostream << LOCALS_API_URL << "/search?api_key=" << LOCALS_API_KEY
+ << "&lat=" << lat << "&lon=" << lon
+ << "&limit=" << resultsOnPage << "&page=" << pageNumber;
+ if (!lang.empty())
+ ostream << "&lang=" << lang;
+
+ platform::HttpClient request(ostream.str());
+ request.SetHttpMethod("GET");
+ if (request.RunHttpRequest() && request.ErrorCode() == 200)
+ {
+ result = request.ServerResponse();
+ return true;
+ }
+ return false;
+}
+
+std::string Api::GetLocalsPageUrl()
+{
+ return LOCALS_PAGE_URL;
+}
+
+uint64_t Api::GetLocals(double lat, double lon, std::string const & lang,
+ size_t resultsOnPage, size_t pageNumber,
+ LocalsSuccessCallback const & successFn,
+ LocalsErrorCallback const & errorFn)
+{
+ uint64_t id = ++m_requestId;
+ GetPlatform().RunOnNetworkThread([id, lat, lon, lang,
+ resultsOnPage, pageNumber, successFn, errorFn]()
+ {
+ std::string result;
+ if (!RawApi::Get(lat, lon, lang, resultsOnPage, pageNumber, result))
+ {
+ try
+ {
+ ErrorCode errorCode;
+ std::string errorMessage;
+ ParseError(result, errorCode, errorMessage);
+ LOG(LWARNING, ("Locals request failed:", errorCode, errorMessage));
+ return errorFn(id, errorCode, errorMessage);
+ }
+ catch (my::Json::Exception const & e)
+ {
+ LOG(LWARNING, ("Unknown error:", e.Msg()));
+ return errorFn(id, ErrorCode::UnknownError, "Unknown error: " + e.Msg());
+ }
+ }
+
+ std::vector<LocalExpert> locals;
+ bool hasPreviousPage = false;
+ bool hasNextPage = false;
+ try
+ {
+ ParseLocals(result, locals, hasPreviousPage, hasNextPage);
+ }
+ catch (my::Json::Exception const & e)
+ {
+ LOG(LWARNING, ("Locals response parsing failed:", e.Msg()));
+ errorFn(id, ErrorCode::UnknownError, "Response parsing failed: " + e.Msg());
+ }
+
+ successFn(id, locals, pageNumber, resultsOnPage, hasPreviousPage, hasNextPage);
+ });
+ return id;
+}
+
+std::string DebugPrint(ErrorCode code)
+{
+ switch (code)
+ {
+ case ErrorCode::NoLocals: return "NoLocals";
+ case ErrorCode::RemoteError: return "RemoteError";
+ case ErrorCode::UnknownError: return "UnknownError";
+ }
+ return "Unknown error code";
+}
+
+std::string DebugPrint(LocalExpert const & localExpert)
+{
+ std::ostringstream out;
+ out << "id: " << localExpert.m_id << std::endl
+ << "name: " << localExpert.m_name << std::endl
+ << "about: " << localExpert.m_aboutExpert << std::endl
+ << "city: " << localExpert.m_city << std::endl
+ << "country: " << localExpert.m_country << std::endl
+ << "currency: " << localExpert.m_currency << std::endl
+ << "pageUrl: " << localExpert.m_pageUrl << std::endl
+ << "photoUrl: " << localExpert.m_photoUrl << std::endl
+ << "description: " << localExpert.m_offerDescription << std::endl
+ << "motto: " << localExpert.m_motto << std::endl;
+ return out.str();
+}
+
+} // namespace locals
diff --git a/partners_api/locals_api.hpp b/partners_api/locals_api.hpp
new file mode 100644
index 0000000000..fc0e1d1b58
--- /dev/null
+++ b/partners_api/locals_api.hpp
@@ -0,0 +1,64 @@
+#pragma once
+
+#include "platform/platform.hpp"
+#include "platform/safe_callback.hpp"
+
+#include <string>
+
+#define STAGE_LOCALS_SERVER
+
+namespace locals
+{
+class RawApi
+{
+public:
+ static bool Get(double lat, double lon, std::string const & lang,
+ size_t resultsOnPage, size_t pageNumber, std::string & result);
+};
+
+enum class ErrorCode
+{
+ NoLocals,
+ RemoteError,
+ UnknownError
+};
+
+struct LocalExpert
+{
+ size_t m_id;
+ std::string m_name;
+ std::string m_country;
+ std::string m_city;
+ double m_rating;
+ size_t m_reviewCount;
+ double m_pricePerHour;
+ std::string m_currency;
+ std::string m_motto;
+ std::string m_aboutExpert;
+ std::string m_offerDescription;
+ std::string m_pageUrl;
+ std::string m_photoUrl;
+};
+
+using LocalsSuccessCallback = platform::SafeCallback<void(uint64_t id, std::vector<LocalExpert> const & locals,
+ size_t pageNumber, size_t countPerPage,
+ bool hasPreviousPage, bool hasNextPage)>;
+using LocalsErrorCallback = platform::SafeCallback<void(uint64_t id, ErrorCode errorCode,
+ std::string const & errorMessage)>;
+
+class Api
+{
+public:
+ static std::string GetLocalsPageUrl();
+ uint64_t GetLocals(double lat, double lon, std::string const & lang,
+ size_t resultsOnPage, size_t pageNumber,
+ LocalsSuccessCallback const & successFn,
+ LocalsErrorCallback const & errorFn);
+private:
+ // Id for currently processed request.
+ uint64_t m_requestId = 0;
+};
+
+std::string DebugPrint(ErrorCode code);
+std::string DebugPrint(LocalExpert const & localExpert);
+} // namespace locals
diff --git a/partners_api/partners_api.pro b/partners_api/partners_api.pro
index 2810ed4fed..b3e4a05238 100644
--- a/partners_api/partners_api.pro
+++ b/partners_api/partners_api.pro
@@ -15,6 +15,7 @@ SOURCES += \
cian_api.cpp \
facebook_ads.cpp \
google_ads.cpp \
+ locals_api.cpp \
mopub_ads.cpp \
opentable_api.cpp \
rb_ads.cpp \
@@ -33,6 +34,7 @@ HEADERS += \
cian_api.hpp \
facebook_ads.hpp \
google_ads.hpp \
+ locals_api.hpp \
mopub_ads.hpp \
opentable_api.hpp \
rb_ads.hpp \
diff --git a/xcode/partners_api/partners_api.xcodeproj/project.pbxproj b/xcode/partners_api/partners_api.xcodeproj/project.pbxproj
index 825980e064..fe1e1916ca 100644
--- a/xcode/partners_api/partners_api.xcodeproj/project.pbxproj
+++ b/xcode/partners_api/partners_api.xcodeproj/project.pbxproj
@@ -46,6 +46,8 @@
3DFEBF9F1EFBFC1500317D5C /* yandex_api.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 3DFEBF991EFBFC1500317D5C /* yandex_api.hpp */; };
3DFEBFA31EFBFC2300317D5C /* taxi_engine_tests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3DFEBFA01EFBFC2300317D5C /* taxi_engine_tests.cpp */; };
3DFEBFA41EFBFC2300317D5C /* yandex_tests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3DFEBFA11EFBFC2300317D5C /* yandex_tests.cpp */; };
+ BB1956E61F543D7C003ECE6C /* locals_api.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BB1956E41F543D7B003ECE6C /* locals_api.cpp */; };
+ BB1956E71F543D7C003ECE6C /* locals_api.hpp in Headers */ = {isa = PBXBuildFile; fileRef = BB1956E51F543D7C003ECE6C /* locals_api.hpp */; };
F67E75251DB8F06F00D6741F /* opentable_api.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F67E75231DB8F06F00D6741F /* opentable_api.cpp */; };
F67E75261DB8F06F00D6741F /* opentable_api.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F67E75241DB8F06F00D6741F /* opentable_api.hpp */; };
F6B536401DA520E40067EEA5 /* booking_api.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F6B5363C1DA520E40067EEA5 /* booking_api.cpp */; };
@@ -107,6 +109,8 @@
3DFEBF991EFBFC1500317D5C /* yandex_api.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = yandex_api.hpp; sourceTree = "<group>"; };
3DFEBFA01EFBFC2300317D5C /* taxi_engine_tests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = taxi_engine_tests.cpp; sourceTree = "<group>"; };
3DFEBFA11EFBFC2300317D5C /* yandex_tests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = yandex_tests.cpp; sourceTree = "<group>"; };
+ BB1956E41F543D7B003ECE6C /* locals_api.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = locals_api.cpp; sourceTree = "<group>"; };
+ BB1956E51F543D7C003ECE6C /* locals_api.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = locals_api.hpp; sourceTree = "<group>"; };
F67E75231DB8F06F00D6741F /* opentable_api.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = opentable_api.cpp; sourceTree = "<group>"; };
F67E75241DB8F06F00D6741F /* opentable_api.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = opentable_api.hpp; sourceTree = "<group>"; };
F6B536341DA5209F0067EEA5 /* libpartners_api.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libpartners_api.a; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -178,6 +182,8 @@
F6B5363B1DA520B20067EEA5 /* partners_api */ = {
isa = PBXGroup;
children = (
+ BB1956E41F543D7B003ECE6C /* locals_api.cpp */,
+ BB1956E51F543D7C003ECE6C /* locals_api.hpp */,
3D47B2B01F14FA14000828D2 /* utils.hpp */,
3D47B2AA1F14BE89000828D2 /* cian_api.cpp */,
3D47B2AB1F14BE89000828D2 /* cian_api.hpp */,
@@ -288,6 +294,7 @@
3DFEBF9C1EFBFC1500317D5C /* taxi_engine.hpp in Headers */,
F6B536431DA520E40067EEA5 /* uber_api.hpp in Headers */,
3DBC1C551E4B14920016897F /* facebook_ads.hpp in Headers */,
+ BB1956E71F543D7C003ECE6C /* locals_api.hpp in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -398,6 +405,7 @@
346E88981E9D087400D4CE9B /* ads_engine.cpp in Sources */,
3D47B29B1F054C89000828D2 /* taxi_countries.cpp in Sources */,
F67E75251DB8F06F00D6741F /* opentable_api.cpp in Sources */,
+ BB1956E61F543D7C003ECE6C /* locals_api.cpp in Sources */,
3DFEBFA31EFBFC2300317D5C /* taxi_engine_tests.cpp in Sources */,
F6B536401DA520E40067EEA5 /* booking_api.cpp in Sources */,
3D47B29A1F054C89000828D2 /* taxi_base.cpp in Sources */,