diff --git a/android/jni/Android.mk b/android/jni/Android.mk index aed7643bfd..68d14664b8 100644 --- a/android/jni/Android.mk +++ b/android/jni/Android.mk @@ -25,7 +25,7 @@ define add_prebuild_static_lib include $(PREBUILT_STATIC_LIBRARY) endef -prebuild_static_libs := map drape_frontend routing search storage indexer drape platform editor geometry coding base opening_hours +prebuild_static_libs := map drape_frontend routing search storage indexer drape platform editor partners_api geometry coding base opening_hours prebuild_static_libs += pugixml oauthcpp expat freetype fribidi minizip jansson tomcrypt protobuf osrm stats_client succinct $(foreach item,$(prebuild_static_libs),$(eval $(call add_prebuild_static_lib,$(item)))) diff --git a/android/jni/com/mapswithme/maps/SponsoredHotel.cpp b/android/jni/com/mapswithme/maps/SponsoredHotel.cpp index cabe3fe119..c420bc4320 100644 --- a/android/jni/com/mapswithme/maps/SponsoredHotel.cpp +++ b/android/jni/com/mapswithme/maps/SponsoredHotel.cpp @@ -2,9 +2,11 @@ #include "../core/jni_helper.hpp" #include "../platform/Platform.hpp" -#include "map/booking_api.hpp" + #include "map/place_page_info.hpp" +#include "partners_api/booking_api.hpp" + #include "std/bind.hpp" #include "std/chrono.hpp" diff --git a/android/jni/com/mapswithme/util/HttpClient.cpp b/android/jni/com/mapswithme/util/HttpClient.cpp index ccb2c74977..eaf7a65814 100644 --- a/android/jni/com/mapswithme/util/HttpClient.cpp +++ b/android/jni/com/mapswithme/util/HttpClient.cpp @@ -97,6 +97,7 @@ public: {"contentEncoding", GetHttpParamsFieldId(env, "contentEncoding")}, {"userAgent", GetHttpParamsFieldId(env, "userAgent")}, {"inputFilePath", GetHttpParamsFieldId(env, "inputFilePath")}, + {"outputFilePath", GetHttpParamsFieldId(env, "outputFilePath")}, {"basicAuthUser", GetHttpParamsFieldId(env, "basicAuthUser")}, {"basicAuthPassword", GetHttpParamsFieldId(env, "basicAuthPassword")}, {"cookies", GetHttpParamsFieldId(env, "cookies")}, diff --git a/configure.sh b/configure.sh index 6bc1d12062..9679318bbd 100755 --- a/configure.sh +++ b/configure.sh @@ -50,6 +50,8 @@ else #define BOOKING_AFFILIATE_ID "" #define BOOKING_KEY "" #define BOOKING_SECRET "" +#define UBER_SERVER_TOKEN "" +#define UBER_CLIENT_ID "" ' > "$PRIVATE_HEADER" echo 'ext { spropStoreFile = "../tools/android/debug.keystore" diff --git a/iphone/Maps/Maps.xcodeproj/project.pbxproj b/iphone/Maps/Maps.xcodeproj/project.pbxproj index 52f4e04a85..e510c1e487 100644 --- a/iphone/Maps/Maps.xcodeproj/project.pbxproj +++ b/iphone/Maps/Maps.xcodeproj/project.pbxproj @@ -774,6 +774,7 @@ F6AD57BD1C870A3C00CED368 /* MWMEditorCategoryCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = F6AD57BC1C870A3C00CED368 /* MWMEditorCategoryCell.xib */; }; F6AD57BE1C870A3C00CED368 /* MWMEditorCategoryCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = F6AD57BC1C870A3C00CED368 /* MWMEditorCategoryCell.xib */; }; F6B2E61F1C3D5F31005562DF /* MWMNightModeController.mm in Sources */ = {isa = PBXBuildFile; fileRef = F6B2E61E1C3D5F31005562DF /* MWMNightModeController.mm */; }; + F6B5364B1DA5222F0067EEA5 /* libpartners_api.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F6B5364A1DA5222F0067EEA5 /* libpartners_api.a */; }; F6B97B261CD0CA990009B612 /* MWMBookmarkNameCell.mm in Sources */ = {isa = PBXBuildFile; fileRef = F6B97B251CD0CA990009B612 /* MWMBookmarkNameCell.mm */; }; F6B97B271CD0CA990009B612 /* MWMBookmarkNameCell.mm in Sources */ = {isa = PBXBuildFile; fileRef = F6B97B251CD0CA990009B612 /* MWMBookmarkNameCell.mm */; }; F6B97B291CD0CB170009B612 /* MWMBookmarkNameCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = F6B97B281CD0CB170009B612 /* MWMBookmarkNameCell.xib */; }; @@ -1273,6 +1274,7 @@ 34FED54F1D21121000183B1B /* CLLocation+Mercator.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "CLLocation+Mercator.mm"; sourceTree = ""; }; 34FED5521D2123CE00183B1B /* MWMLocationHelpers.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MWMLocationHelpers.h; sourceTree = ""; }; 3D443C9C19E421EE0025C2FC /* sv */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sv; path = sv.lproj/Localizable.strings; sourceTree = ""; }; + 3DDB4BC31DAB98F000F4D021 /* libpartners_api.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libpartners_api.a; path = "../../../omim-xcode-build/Debug-iphonesimulator/libpartners_api.a"; sourceTree = ""; }; 451950391B7A3E070085DA05 /* patterns.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = patterns.txt; path = ../../data/patterns.txt; sourceTree = ""; }; 452FCA3A1B6A3DF7007019AB /* colors.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = colors.txt; path = ../../data/colors.txt; sourceTree = ""; }; 454040681AD2D8D2007A9B12 /* CoreVideo.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreVideo.framework; path = System/Library/Frameworks/CoreVideo.framework; sourceTree = SDKROOT; }; @@ -1513,6 +1515,7 @@ F6AD57BC1C870A3C00CED368 /* MWMEditorCategoryCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = MWMEditorCategoryCell.xib; sourceTree = ""; }; F6B2E61D1C3D5F31005562DF /* MWMNightModeController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MWMNightModeController.h; sourceTree = ""; }; F6B2E61E1C3D5F31005562DF /* MWMNightModeController.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MWMNightModeController.mm; sourceTree = ""; }; + F6B5364A1DA5222F0067EEA5 /* libpartners_api.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libpartners_api.a; path = "/Users/v.mikhaylenko/mapsme/omim/xcode/partners_api/../../../omim-xcode-build/Debug/libpartners_api.a"; sourceTree = ""; }; F6B97B241CD0CA990009B612 /* MWMBookmarkNameCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MWMBookmarkNameCell.h; sourceTree = ""; }; F6B97B251CD0CA990009B612 /* MWMBookmarkNameCell.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MWMBookmarkNameCell.mm; sourceTree = ""; }; F6B97B281CD0CB170009B612 /* MWMBookmarkNameCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = MWMBookmarkNameCell.xib; sourceTree = ""; }; @@ -1688,6 +1691,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + F6B5364B1DA5222F0067EEA5 /* libpartners_api.a in Frameworks */, 34170B7E1D93C3C80074117B /* MyTargetSDK.framework in Frameworks */, 34BF68631D7459E6001752F6 /* CoreSpotlight.framework in Frameworks */, F659FC6A1CF35C24000A06B1 /* SafariServices.framework in Frameworks */, @@ -1866,6 +1870,8 @@ 29B97323FDCFA39411CA2CEA /* Frameworks */ = { isa = PBXGroup; children = ( + 3DDB4BC31DAB98F000F4D021 /* libpartners_api.a */, + F6B5364A1DA5222F0067EEA5 /* libpartners_api.a */, 34170B7D1D93C3C80074117B /* MyTargetSDK.framework */, 34BF68621D7459E6001752F6 /* CoreSpotlight.framework */, 343E8B361D08004C0046AEEE /* libstdc++.tbd */, @@ -4483,6 +4489,7 @@ "-lrouting", "-lindexer", "-lplatform", + "-lpartners_api", "-lgeometry", "-lcoding", "-lbase", @@ -4605,6 +4612,7 @@ "-lrouting", "-lindexer", "-lplatform", + "-lpartners_api", "-lgeometry", "-lcoding", "-lbase", @@ -4729,6 +4737,7 @@ "-lrouting", "-lindexer", "-lplatform", + "-lpartners_api", "-lgeometry", "-lcoding", "-lbase", @@ -4854,6 +4863,7 @@ "-lrouting", "-lindexer", "-lplatform", + "-lpartners_api", "-lgeometry", "-lcoding", "-lbase", @@ -4978,6 +4988,7 @@ "-lrouting", "-lindexer", "-lplatform", + "-lpartners_api", "-lgeometry", "-lcoding", "-lbase", @@ -5100,6 +5111,7 @@ "-lrouting", "-lindexer", "-lplatform", + "-lpartners_api", "-lgeometry", "-lcoding", "-lbase", diff --git a/map/framework.cpp b/map/framework.cpp index c7f20a23b7..1284ad4f79 100644 --- a/map/framework.cpp +++ b/map/framework.cpp @@ -2379,8 +2379,11 @@ void Framework::InsertRoute(Route const & route) } vector turns; - if (m_currentRouterType == RouterType::Vehicle || m_currentRouterType == RouterType::Bicycle) + if (m_currentRouterType == RouterType::Vehicle || m_currentRouterType == RouterType::Bicycle || + m_currentRouterType == RouterType::Taxi) + { route.GetTurnsDistances(turns); + } df::ColorConstant routeColor = df::Route; df::RoutePattern pattern; @@ -2480,6 +2483,8 @@ RouterType Framework::GetBestRouter(m2::PointD const & startPoint, m2::PointD co case RouterType::Pedestrian: case RouterType::Bicycle: return lastUsedRouter; + case RouterType::Taxi: + ASSERT(false, ("GetLastUsedRouter sould not to return RouterType::Taxi")); case RouterType::Vehicle: ; // fall through } @@ -2557,8 +2562,10 @@ bool Framework::LoadAutoZoom() void Framework::AllowAutoZoom(bool allowAutoZoom) { bool const isPedestrianRoute = m_currentRouterType == RouterType::Pedestrian; + bool const isTaxiRoute = m_currentRouterType == RouterType::Taxi; - CallDrapeFunction(bind(&df::DrapeEngine::AllowAutoZoom, _1, allowAutoZoom && !isPedestrianRoute)); + CallDrapeFunction(bind(&df::DrapeEngine::AllowAutoZoom, _1, + allowAutoZoom && !isPedestrianRoute && !isTaxiRoute)); } void Framework::SaveAutoZoom(bool allowAutoZoom) diff --git a/map/framework.hpp b/map/framework.hpp index 7c5e46a9c6..961794dd16 100644 --- a/map/framework.hpp +++ b/map/framework.hpp @@ -1,7 +1,6 @@ #pragma once #include "map/api_mark_point.hpp" -#include "map/booking_api.hpp" #include "map/bookmark.hpp" #include "map/bookmark_manager.hpp" #include "map/displacement_mode_manager.hpp" @@ -34,6 +33,9 @@ #include "storage/downloading_policy.hpp" #include "storage/storage.hpp" +#include "partners_api/booking_api.hpp" +#include "partners_api/uber_api.hpp" + #include "platform/country_defines.hpp" #include "platform/location.hpp" #include "platform/platform.hpp" @@ -156,6 +158,8 @@ protected: BookingApi m_bookingApi; + uber::Api m_uberApi; + bool m_isRenderingEnabled; /// This function will be called by m_storage when latest local files @@ -185,6 +189,8 @@ public: BookingApi & GetBookingApi() { return m_bookingApi; } BookingApi const & GetBookingApi() const { return m_bookingApi; } + uber::Api & GetUberApi() { return m_uberApi;} + /// Migrate to new version of very different data. bool IsEnoughSpaceForMigrate() const; storage::TCountryId PreMigrate(ms::LatLon const & position, storage::Storage::TChangeCountryFunction const & change, @@ -731,6 +737,9 @@ public: /// GenerateTurnNotifications shall be called by the client when a new position is available. inline void GenerateTurnNotifications(vector & turnNotifications) { + if (m_currentRouterType == routing::RouterType::Taxi) + return; + return m_routingSession.GenerateTurnNotifications(turnNotifications); } diff --git a/map/map.pro b/map/map.pro index 4aabaf916c..264f744590 100644 --- a/map/map.pro +++ b/map/map.pro @@ -12,7 +12,6 @@ include($$ROOT_DIR/common.pri) HEADERS += \ api_mark_point.hpp \ - booking_api.hpp \ bookmark.hpp \ bookmark_manager.hpp \ chart_generator.hpp \ @@ -36,7 +35,6 @@ SOURCES += \ ../api/src/c/api-client.c \ address_finder.cpp \ api_mark_point.cpp \ - booking_api.cpp \ bookmark.cpp \ bookmark_manager.cpp \ chart_generator.cpp \ diff --git a/map/map_tests/map_tests.pro b/map/map_tests/map_tests.pro index 3a46cddf32..e44ce96790 100644 --- a/map/map_tests/map_tests.pro +++ b/map/map_tests/map_tests.pro @@ -6,7 +6,7 @@ CONFIG -= app_bundle TEMPLATE = app ROOT_DIR = ../.. -DEPENDENCIES = map drape_frontend routing search storage drape indexer platform editor geometry coding base \ +DEPENDENCIES = map drape_frontend routing search storage drape indexer partners_api platform editor geometry coding base \ freetype fribidi expat protobuf tomcrypt jansson osrm stats_client minizip succinct pugixml stats_client DEPENDENCIES *= opening_hours @@ -36,7 +36,6 @@ macx-*: LIBS *= "-framework IOKit" "-framework SystemConfiguration" SOURCES += \ ../../testing/testingmain.cpp \ address_tests.cpp \ - booking_tests.cpp \ bookmarks_test.cpp \ chart_generator_tests.cpp \ feature_getters_tests.cpp \ diff --git a/mapshot/mapshot.pro b/mapshot/mapshot.pro index d92c5a3d0b..c1f37891d9 100644 --- a/mapshot/mapshot.pro +++ b/mapshot/mapshot.pro @@ -1,7 +1,7 @@ # mapshot binary ROOT_DIR = .. -DEPENDENCIES = map drape_frontend routing search storage indexer drape platform editor geometry coding base \ +DEPENDENCIES = map drape_frontend routing search storage indexer drape partners_api platform editor geometry coding base \ freetype expat fribidi tomcrypt gflags jansson protobuf osrm stats_client minizip succinct \ pugixml opening_hours diff --git a/omim.pro b/omim.pro index ec42dcc0c5..9fc68bdcc5 100644 --- a/omim.pro +++ b/omim.pro @@ -64,7 +64,7 @@ SUBDIRS = 3party base coding geometry editor indexer routing search } !CONFIG(gtool):!CONFIG(osrm) { - SUBDIRS *= drape drape_frontend map + SUBDIRS *= drape drape_frontend partners_api map CONFIG(map_designer):CONFIG(desktop) { SUBDIRS *= skin_generator @@ -244,5 +244,9 @@ SUBDIRS = 3party base coding geometry editor indexer routing search drape_frontend_tests.subdir = drape_frontend/drape_frontend_tests drape_frontend_tests.depends = 3party base coding platform drape drape_frontend SUBDIRS *= drape_frontend_tests + + partners_api_tests.subdir = partners_api/partners_api_tests + partners_api_tests.depends = base platform partners_api + SUBDIRS *= partners_api_tests } # !no-tests } # !gtool diff --git a/map/booking_api.cpp b/partners_api/booking_api.cpp similarity index 99% rename from map/booking_api.cpp rename to partners_api/booking_api.cpp index 1e3aef6e73..b634411716 100644 --- a/map/booking_api.cpp +++ b/partners_api/booking_api.cpp @@ -1,4 +1,4 @@ -#include "map/booking_api.hpp" +#include "partners_api/booking_api.hpp" #include "base/gmtime.hpp" #include "base/logging.hpp" diff --git a/map/booking_api.hpp b/partners_api/booking_api.hpp similarity index 100% rename from map/booking_api.hpp rename to partners_api/booking_api.hpp diff --git a/partners_api/partners_api.pro b/partners_api/partners_api.pro new file mode 100644 index 0000000000..e49f090dae --- /dev/null +++ b/partners_api/partners_api.pro @@ -0,0 +1,17 @@ +TARGET = partners_api +TEMPLATE = lib +CONFIG += staticlib warn_on + +ROOT_DIR = .. + +INCLUDEPATH *= $$ROOT_DIR/3party/jansson/src + +include($$ROOT_DIR/common.pri) + +SOURCES += \ + booking_api.cpp \ + uber_api.cpp \ + +HEADERS += \ + booking_api.hpp \ + uber_api.hpp \ diff --git a/map/map_tests/booking_tests.cpp b/partners_api/partners_api_tests/booking_tests.cpp similarity index 98% rename from map/map_tests/booking_tests.cpp rename to partners_api/partners_api_tests/booking_tests.cpp index b92279a6bb..1af991dcee 100644 --- a/map/map_tests/booking_tests.cpp +++ b/partners_api/partners_api_tests/booking_tests.cpp @@ -1,6 +1,6 @@ #include "testing/testing.hpp" -#include "map/booking_api.hpp" +#include "partners_api/booking_api.hpp" UNIT_TEST(Booking_SmokeTest) { diff --git a/partners_api/partners_api_tests/partners_api_tests.pro b/partners_api/partners_api_tests/partners_api_tests.pro new file mode 100644 index 0000000000..4904006a86 --- /dev/null +++ b/partners_api/partners_api_tests/partners_api_tests.pro @@ -0,0 +1,30 @@ +TARGET = partners_api_tests +CONFIG += console warn_on +CONFIG -= app_bundle +TEMPLATE = app + +ROOT_DIR = ../.. + +INCLUDEPATH *= $$ROOT_DIR/3party/jansson/src + +DEPENDENCIES = partners_api platform coding base tomcrypt jansson stats_client + +include($$ROOT_DIR/common.pri) + +DEFINES *= OMIM_UNIT_TEST_WITH_QT_EVENT_LOOP + +QT *= core + +macx-* { + QT *= widgets # needed for QApplication with event loop, to test async events + LIBS *= "-framework IOKit" "-framework SystemConfiguration" +} + +win*|linux* { + QT *= network +} + +SOURCES += \ + $$ROOT_DIR/testing/testingmain.cpp \ + booking_tests.cpp \ + uber_tests.cpp \ diff --git a/partners_api/partners_api_tests/uber_tests.cpp b/partners_api/partners_api_tests/uber_tests.cpp new file mode 100644 index 0000000000..5da08c22f7 --- /dev/null +++ b/partners_api/partners_api_tests/uber_tests.cpp @@ -0,0 +1,221 @@ +#include "testing/testing.hpp" + +#include "partners_api/uber_api.hpp" + +#include "geometry/latlon.hpp" + +#include "std/algorithm.hpp" +#include "std/atomic.hpp" +#include "std/mutex.hpp" + +#include "3party/jansson/myjansson.hpp" + +namespace +{ +bool IsComplete(uber::Product const & product) +{ + return !product.m_productId.empty() && !product.m_name.empty() && !product.m_time.empty() && + !product.m_price.empty(); +} +} // namespace + +UNIT_TEST(Uber_GetProducts) +{ + ms::LatLon const pos(38.897724, -77.036531); + + TEST(!uber::RawApi::GetProducts(pos).empty(), ()); +} + +UNIT_TEST(Uber_GetTimes) +{ + ms::LatLon const pos(38.897724, -77.036531); + + my::Json timeRoot(uber::RawApi::GetEstimatedTime(pos).c_str()); + auto const timesArray = json_object_get(timeRoot.get(), "times"); + + TEST(json_is_array(timesArray), ()); + TEST_GREATER(json_array_size(timesArray), 0, ()); + + auto const timeSize = json_array_size(timesArray); + for (size_t i = 0; i < timeSize; ++i) + { + string name; + json_int_t estimatedTime = 0; + auto const item = json_array_get(timesArray, i); + + try + { + my::FromJSONObject(item, "display_name", name); + my::FromJSONObject(item, "estimate", estimatedTime); + } + catch (my::Json::Exception const & e) + { + TEST(false, (e.Msg())); + } + + string const estimated = strings::to_string(estimatedTime); + + TEST(!name.empty(), ()); + TEST(!estimated.empty(), ()); + } +} + +UNIT_TEST(Uber_GetPrices) +{ + ms::LatLon const from(38.897724, -77.036531); + ms::LatLon const to(38.862416, -76.883316); + + my::Json priceRoot(uber::RawApi::GetEstimatedPrice(from, to).c_str()); + auto const pricesArray = json_object_get(priceRoot.get(), "prices"); + + TEST(json_is_array(pricesArray), ()); + TEST_GREATER(json_array_size(pricesArray), 0, ()); + + auto const pricesSize = json_array_size(pricesArray); + for (size_t i = 0; i < pricesSize; ++i) + { + string productId; + string price; + string currency; + + auto const item = json_array_get(pricesArray, i); + + try + { + my::FromJSONObject(item, "product_id", productId); + my::FromJSONObject(item, "estimate", price); + + auto const val = json_object_get(item, "currency_code"); + if (val != nullptr) + { + if (!json_is_null(val)) + currency = json_string_value(val); + else + currency = "null"; + } + } + catch (my::Json::Exception const & e) + { + TEST(false, (e.Msg())); + } + + TEST(!productId.empty(), ()); + TEST(!price.empty(), ()); + TEST(!currency.empty(), ()); + } +} + +UNIT_TEST(Uber_ProductMaker) +{ + size_t reqId = 1; + ms::LatLon const from(38.897724, -77.036531); + ms::LatLon const to(38.862416, -76.883316); + + size_t returnedId = 0; + vector returnedProducts; + + uber::ProductMaker maker; + + maker.Reset(reqId); + maker.SetTimes(reqId, uber::RawApi::GetEstimatedTime(from)); + maker.SetPrices(reqId, uber::RawApi::GetEstimatedPrice(from, to)); + maker.MakeProducts(reqId, [&returnedId, &returnedProducts] + (vector const & products, size_t const requestId) + { + returnedId = requestId; + returnedProducts = products; + }); + + TEST(!returnedProducts.empty(), ()); + TEST_EQUAL(returnedId, reqId, ()); + + for (auto const & product : returnedProducts) + TEST(IsComplete(product),()); + + ++reqId; + + maker.Reset(reqId); + maker.SetTimes(reqId, uber::RawApi::GetEstimatedTime(from)); + maker.SetPrices(reqId, uber::RawApi::GetEstimatedPrice(from, to)); + + maker.MakeProducts(reqId + 1, [](vector const & products, size_t const requestId) + { + TEST(false, ()); + }); +} + +UNIT_TEST(Uber_Smoke) +{ + // Used to synchronize access into GetAvailableProducts callback method. + mutex resultsMutex; + size_t reqId = 1; + vector productsContainer; + ms::LatLon const from(38.897724, -77.036531); + ms::LatLon const to(38.862416, -76.883316); + + auto const standardCallback = + [&reqId, &productsContainer, &resultsMutex](vector const & products, size_t const requestId) + { + lock_guard lock(resultsMutex); + + if (reqId == requestId) + productsContainer = products; + }; + + auto const lastCallback = + [&standardCallback](vector const & products, size_t const requestId) + { + standardCallback(products, requestId); + testing::StopEventLoop(); + }; + + uber::ProductMaker maker; + + maker.Reset(reqId); + maker.SetTimes(reqId, uber::RawApi::GetEstimatedTime(from)); + maker.SetPrices(reqId, uber::RawApi::GetEstimatedPrice(from, to)); + maker.MakeProducts(reqId, standardCallback); + + reqId = 0; + + auto const synchronousProducts = productsContainer; + productsContainer.clear(); + + uber::Api uberApi; + + { + lock_guard lock(resultsMutex); + reqId = uberApi.GetAvailableProducts(ms::LatLon(55.753960, 37.624513), + ms::LatLon(55.765866, 37.661270), standardCallback); + } + { + lock_guard lock(resultsMutex); + reqId = uberApi.GetAvailableProducts(ms::LatLon(59.922445, 30.367201), + ms::LatLon(59.943675, 30.361123), standardCallback); + } + { + lock_guard lock(resultsMutex); + reqId = uberApi.GetAvailableProducts(ms::LatLon(52.509621, 13.450067), + ms::LatLon(52.510811, 13.409490), standardCallback); + } + { + lock_guard lock(resultsMutex); + reqId = uberApi.GetAvailableProducts(from, to, lastCallback); + } + + testing::RunEventLoop(); + + TEST_EQUAL(synchronousProducts.size(), productsContainer.size(), ()); + + for (auto const & product : synchronousProducts) + { + auto const it = find_if( + productsContainer.begin(), productsContainer.end(), [&product](uber::Product const & item) + { + return product.m_productId == item.m_productId && product.m_name == item.m_name && + product.m_price == item.m_price; + }); + + TEST(it != productsContainer.end(), ()); + } +} diff --git a/partners_api/uber_api.cpp b/partners_api/uber_api.cpp new file mode 100644 index 0000000000..668a910742 --- /dev/null +++ b/partners_api/uber_api.cpp @@ -0,0 +1,225 @@ +#include "partners_api/uber_api.hpp" + +#include "platform/http_client.hpp" + +#include "geometry/latlon.hpp" + +#include "base/logging.hpp" +#include "base/thread.hpp" + +#include "3party/jansson/myjansson.hpp" + +#include "private.h" + +using namespace platform; + +namespace +{ +string RunSimpleHttpRequest(string const & url) +{ + HttpClient request(url); + if (request.RunHttpRequest() && !request.WasRedirected() && request.ErrorCode() == 200) + { + return request.ServerResponse(); + } + return {}; +} + +bool CheckUberAnswer(json_t const * answer) +{ + if (answer == nullptr) + return false; + + // Uber products are not available at this point. + if (!json_is_array(answer)) + return false; + + if (json_array_size(answer) <= 0) + return false; + + return true; +} + +bool IsIncomplete(uber::Product const & p) +{ + return p.m_name.empty() || p.m_productId.empty() || p.m_time.empty() || p.m_price.empty(); +} + +void FillProducts(json_t const * time, json_t const * price, vector & products) +{ + // Fill data from time. + auto const timeSize = json_array_size(time); + for (size_t i = 0; i < timeSize; ++i) + { + uber::Product product; + json_int_t estimatedTime = 0; + auto const item = json_array_get(time, i); + my::FromJSONObject(item, "display_name", product.m_name); + my::FromJSONObject(item, "estimate", estimatedTime); + product.m_time = strings::to_string(estimatedTime); + products.push_back(move(product)); + } + + // Fill data from price. + auto const priceSize = json_array_size(price); + for (size_t i = 0; i < priceSize; ++i) + { + string name; + auto const item = json_array_get(price, i); + + my::FromJSONObject(item, "display_name", name); + auto const it = find_if(products.begin(), products.end(), [&name](uber::Product const & product) + { + return product.m_name == name; + }); + + if (it == products.end()) + continue; + + my::FromJSONObject(item, "product_id", it->m_productId); + my::FromJSONObject(item, "estimate", it->m_price); + + // The field currency_code can contain null in case when price equal to Metered. + auto const currency = json_object_get(item, "currency_code"); + if (currency != nullptr && !json_is_null(currency)) + it->m_currency = json_string_value(currency); + } + + products.erase(remove_if(products.begin(), products.end(), IsIncomplete), products.end()); +} + +void MakeFromJson(char const * times, char const * prices, vector & products) +{ + products.clear(); + try + { + my::Json timesRoot(times); + my::Json pricesRoot(prices); + auto const timesArray = json_object_get(timesRoot.get(), "times"); + auto const pricesArray = json_object_get(pricesRoot.get(), "prices"); + if (CheckUberAnswer(timesArray) && CheckUberAnswer(pricesArray)) + { + FillProducts(timesArray, pricesArray, products); + } + } + catch (my::Json::Exception const & e) + { + LOG(LERROR, (e.Msg())); + products.clear(); + } +} +} // namespace + +namespace uber +{ +// static +string RawApi::GetProducts(ms::LatLon const & pos) +{ + stringstream url; + url << "https://api.uber.com/v1/products?server_token=" << UBER_SERVER_TOKEN + << "&latitude=" << pos.lat << "&longitude=" << pos.lon; + + return RunSimpleHttpRequest(url.str()); +} + +// static +string RawApi::GetEstimatedTime(ms::LatLon const & pos) +{ + stringstream url; + url << "https://api.uber.com/v1/estimates/time?server_token=" << UBER_SERVER_TOKEN + << "&start_latitude=" << pos.lat << "&start_longitude=" << pos.lon; + + return RunSimpleHttpRequest(url.str()); +} + +// static +string RawApi::GetEstimatedPrice(ms::LatLon const & from, ms::LatLon const & to) +{ + stringstream url; + url << "https://api.uber.com/v1/estimates/price?server_token=" << UBER_SERVER_TOKEN + << "&start_latitude=" << from.lat << "&start_longitude=" << from.lon + << "&end_latitude=" << to.lat << "&end_longitude=" << to.lon; + + return RunSimpleHttpRequest(url.str()); +} + +void ProductMaker::Reset(size_t const requestId) +{ + lock_guard lock(m_mutex); + + m_requestId = requestId; + m_times.reset(); + m_prices.reset(); +} + +void ProductMaker::SetTimes(size_t const requestId, string const & times) +{ + lock_guard lock(m_mutex); + + if (requestId != m_requestId) + return; + + m_times = make_unique(times); +} + +void ProductMaker::SetPrices(size_t const requestId, string const & prices) +{ + lock_guard lock(m_mutex); + + if (requestId != m_requestId) + return; + + m_prices = make_unique(prices); +} + +void ProductMaker::MakeProducts(size_t const requestId, ProductsCallback const & fn) +{ + vector products; + { + lock_guard lock(m_mutex); + + if (requestId != m_requestId || !m_times || !m_prices) + return; + + if (!m_times->empty() && !m_prices->empty()) + MakeFromJson(m_times->c_str(), m_prices->c_str(), products); + else + LOG(LWARNING, ("Time or price is empty, time:", *m_times, "; price:", *m_prices)); + } + fn(products, requestId); +} + +size_t Api::GetAvailableProducts(ms::LatLon const & from, ms::LatLon const & to, + ProductsCallback const & fn) +{ + size_t const reqId = ++m_requestId; + + m_maker->Reset(reqId); + + threads::SimpleThread([this, from, reqId, fn]() + { + m_maker->SetTimes(reqId, uber::RawApi::GetEstimatedTime(from)); + m_maker->MakeProducts(reqId, fn); + }).detach(); + + threads::SimpleThread([this, from, to, reqId, fn]() + { + m_maker->SetPrices(reqId, uber::RawApi::GetEstimatedPrice(from, to)); + m_maker->MakeProducts(reqId, fn); + }).detach(); + + return reqId; +} + +// static +RideRequestLinks Api::GetRideRequestLinks(string const & productId, ms::LatLon const & from, + ms::LatLon const & to) +{ + stringstream url; + url << "?client_id=" << UBER_CLIENT_ID << "&action=setPickup&product_id=" << productId + << "&pickup[latitude]=" << from.lat << "&pickup[longitude]=" << from.lon + << "&dropoff[latitude]=" << to.lat << "&dropoff[longitude]=" << to.lon; + + return {"uber://" + url.str(), "https://m.uber.com/ul" + url.str()}; +} +} // namespace uber diff --git a/partners_api/uber_api.hpp b/partners_api/uber_api.hpp new file mode 100644 index 0000000000..9aed7dacff --- /dev/null +++ b/partners_api/uber_api.hpp @@ -0,0 +1,92 @@ +#pragma once + +#include "std/function.hpp" +#include "std/mutex.hpp" +#include "std/shared_ptr.hpp" +#include "std/string.hpp" +#include "std/unique_ptr.hpp" +#include "std/vector.hpp" + +namespace ms +{ +class LatLon; +} + +namespace downloader +{ +class HttpRequest; +} + +namespace uber +{ +// Uber api wrapper based on synchronous http requests. +class RawApi +{ +public: + /// Returns information about the Uber products offered at a given location. + /// The response includes the display name and other details about each product, and lists the + /// products in the proper display order. This endpoint does not reflect real-time availability + /// of the products. + static string GetProducts(ms::LatLon const & pos); + /// Returns ETAs for all products currently available at a given location, with the ETA for each + /// product expressed as integers in seconds. If a product returned from GetProducts is not + /// returned from this endpoint for a given latitude/longitude pair then there are currently none + /// of that product available to request. Call this endpoint every minute to provide the most + /// accurate, up-to-date ETAs. + static string GetEstimatedTime(ms::LatLon const & pos); + /// Returns an estimated price range for each product offered at a given location. The price + /// estimate is provided as a formatted string with the full price range and the localized + /// currency symbol. + static string GetEstimatedPrice(ms::LatLon const & from, ms::LatLon const & to); +}; + +struct Product +{ + string m_productId; + string m_name; + string m_time; + string m_price; // for some currencies this field contains symbol of currency but not always + string m_currency; // currency can be empty, for ex. when m_price equal to Metered +}; +/// @products - vector of available products for requested route. +/// @requestId - identificator which was provided to GetAvailableProducts to identify request. +using ProductsCallback = function const & products, size_t const requestId)>; + +/// Class which used for making products from http requests results. +class ProductMaker +{ +public: + void Reset(size_t const requestId); + void SetTimes(size_t const requestId, string const & times); + void SetPrices(size_t const requestId, string const & prices); + void MakeProducts(size_t const requestId, ProductsCallback const & fn); + +private: + size_t m_requestId = 0; + unique_ptr m_times; + unique_ptr m_prices; + mutex m_mutex; +}; + +struct RideRequestLinks +{ + string m_deepLink; + string m_universalLink; +}; + +class Api +{ +public: + /// Requests list of available products from Uber. Returns request identificator immediately. + size_t GetAvailableProducts(ms::LatLon const & from, ms::LatLon const & to, + ProductsCallback const & fn); + + /// Returns link which allows you to launch the Uber app. + static RideRequestLinks GetRideRequestLinks(string const & productId, ms::LatLon const & from, + ms::LatLon const & to); + +private: + shared_ptr m_maker = make_shared(); + size_t m_requestId = 0; +}; +} // namespace uber diff --git a/qt/qt.pro b/qt/qt.pro index 2befa2c463..1667db7068 100644 --- a/qt/qt.pro +++ b/qt/qt.pro @@ -1,6 +1,6 @@ # Main application in qt. ROOT_DIR = .. -DEPENDENCIES = map drape_frontend routing search storage indexer drape platform editor geometry \ +DEPENDENCIES = map drape_frontend routing search storage indexer drape partners_api platform editor geometry \ coding base freetype expat fribidi tomcrypt jansson protobuf osrm stats_client \ minizip succinct pugixml oauthcpp diff --git a/routing/router.cpp b/routing/router.cpp index c8c29a6d7a..eb3dc93e79 100644 --- a/routing/router.cpp +++ b/routing/router.cpp @@ -10,6 +10,7 @@ string ToString(RouterType type) case RouterType::Vehicle: return "Vehicle"; case RouterType::Pedestrian: return "Pedestrian"; case RouterType::Bicycle: return "Bicycle"; + case RouterType::Taxi: return "Taxi"; } ASSERT(false, ()); return "Error"; @@ -23,6 +24,8 @@ RouterType FromString(string const & str) return RouterType::Pedestrian; if (str == "bicycle") return RouterType::Bicycle; + if (str == "taxi") + return RouterType::Taxi; ASSERT(false, ("Incorrect routing string:", str)); return RouterType::Vehicle; diff --git a/routing/router.hpp b/routing/router.hpp index ac91916414..bd96dd6dad 100644 --- a/routing/router.hpp +++ b/routing/router.hpp @@ -22,6 +22,7 @@ enum class RouterType Vehicle = 0, /// For OSRM vehicle routing Pedestrian, /// For A star pedestrian routing Bicycle, /// For A star bicycle routing + Taxi, /// For taxi route calculation Vehicle routing is used. }; string ToString(RouterType type); diff --git a/std/future.hpp b/std/future.hpp index 1ef27855a6..8a72e54dd8 100644 --- a/std/future.hpp +++ b/std/future.hpp @@ -7,6 +7,7 @@ #include using std::async; +using std::future; using std::future_status; using std::launch; diff --git a/storage/storage_integration_tests/storage_integration_tests.pro b/storage/storage_integration_tests/storage_integration_tests.pro index d038ad45e4..7d6a357505 100644 --- a/storage/storage_integration_tests/storage_integration_tests.pro +++ b/storage/storage_integration_tests/storage_integration_tests.pro @@ -6,7 +6,7 @@ CONFIG -= app_bundle TEMPLATE = app ROOT_DIR = ../.. -DEPENDENCIES = map drape_frontend routing search storage indexer drape platform_tests_support platform editor opening_hours geometry \ +DEPENDENCIES = map drape_frontend routing search storage indexer drape partners_api platform_tests_support platform editor opening_hours geometry \ coding base freetype expat fribidi tomcrypt jansson protobuf osrm stats_client \ minizip succinct pugixml oauthcpp diff --git a/xcode/map/map.xcodeproj/project.pbxproj b/xcode/map/map.xcodeproj/project.pbxproj index f81da40a08..5242f0f23e 100644 --- a/xcode/map/map.xcodeproj/project.pbxproj +++ b/xcode/map/map.xcodeproj/project.pbxproj @@ -66,8 +66,6 @@ 6753469D1A4054E800A0A8C3 /* user_mark_container.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6753462E1A4054E800A0A8C3 /* user_mark_container.cpp */; }; 6753469E1A4054E800A0A8C3 /* user_mark_container.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 6753462F1A4054E800A0A8C3 /* user_mark_container.hpp */; }; 675346A21A4054E800A0A8C3 /* user_mark.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 675346331A4054E800A0A8C3 /* user_mark.hpp */; }; - 6788507E1D059068004201E1 /* booking_api.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6788507C1D059068004201E1 /* booking_api.cpp */; }; - 6788507F1D059068004201E1 /* booking_api.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 6788507D1D059068004201E1 /* booking_api.hpp */; }; 678850811D06F588004201E1 /* booking_tests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 678850801D06F588004201E1 /* booking_tests.cpp */; }; 678850821D071E33004201E1 /* libdrape.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 674A29F61B26FE62001A525C /* libdrape.a */; }; 6788508A1D071E34004201E1 /* libdrape_frontend.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 678850831D071E34004201E1 /* libdrape_frontend.a */; }; @@ -187,8 +185,6 @@ 6753462E1A4054E800A0A8C3 /* user_mark_container.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = user_mark_container.cpp; sourceTree = ""; }; 6753462F1A4054E800A0A8C3 /* user_mark_container.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = user_mark_container.hpp; sourceTree = ""; }; 675346331A4054E800A0A8C3 /* user_mark.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = user_mark.hpp; sourceTree = ""; }; - 6788507C1D059068004201E1 /* booking_api.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = booking_api.cpp; sourceTree = ""; }; - 6788507D1D059068004201E1 /* booking_api.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = booking_api.hpp; sourceTree = ""; }; 678850801D06F588004201E1 /* booking_tests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = booking_tests.cpp; sourceTree = ""; }; 678850831D071E34004201E1 /* libdrape_frontend.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libdrape_frontend.a; path = "../../../omim-xcode-build/Debug/libdrape_frontend.a"; sourceTree = ""; }; 678850841D071E34004201E1 /* libeditor.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libeditor.a; path = "../../../omim-xcode-build/Debug/libeditor.a"; sourceTree = ""; }; @@ -309,6 +305,13 @@ 674A2A341B2700B2001A525C /* libs */ = { isa = PBXGroup; children = ( + F6DA2A981CCE252600F087B5 /* libeditor.a */, + F6DA2A991CCE252600F087B5 /* liboauthcpp.a */, + F6DA2A9A1CCE252600F087B5 /* libplatform_tests_support.a */, + F6DA2A9B1CCE252600F087B5 /* libpugixml.a */, + F6DA2A9C1CCE252600F087B5 /* libsdf_image.a */, + F6DA2A9D1CCE252600F087B5 /* libstb_image.a */, + F6DA2A961CCE24DB00F087B5 /* libdrape_frontend.a */, 678850831D071E34004201E1 /* libdrape_frontend.a */, 678850841D071E34004201E1 /* libeditor.a */, 678850851D071E34004201E1 /* liboauthcpp.a */, @@ -358,13 +361,6 @@ 675345B21A4054AD00A0A8C3 = { isa = PBXGroup; children = ( - F6DA2A981CCE252600F087B5 /* libeditor.a */, - F6DA2A991CCE252600F087B5 /* liboauthcpp.a */, - F6DA2A9A1CCE252600F087B5 /* libplatform_tests_support.a */, - F6DA2A9B1CCE252600F087B5 /* libpugixml.a */, - F6DA2A9C1CCE252600F087B5 /* libsdf_image.a */, - F6DA2A9D1CCE252600F087B5 /* libstb_image.a */, - F6DA2A961CCE24DB00F087B5 /* libdrape_frontend.a */, 670D05A41B0DF4250013A7AC /* defaults.xcconfig */, 674A2A341B2700B2001A525C /* libs */, 675345BD1A4054AD00A0A8C3 /* map */, @@ -425,8 +421,6 @@ 6753462F1A4054E800A0A8C3 /* user_mark_container.hpp */, 675346331A4054E800A0A8C3 /* user_mark.hpp */, 674A2A371B2715FB001A525C /* osm_opening_hours.hpp */, - 6788507C1D059068004201E1 /* booking_api.cpp */, - 6788507D1D059068004201E1 /* booking_api.hpp */, ); name = map; path = ../../map; @@ -444,7 +438,6 @@ 675346671A4054E800A0A8C3 /* ge0_parser.hpp in Headers */, 675346A21A4054E800A0A8C3 /* user_mark.hpp in Headers */, F6B283061C1B03320081957A /* gps_track_filter.hpp in Headers */, - 6788507F1D059068004201E1 /* booking_api.hpp in Headers */, 34583BD01C88556800F94664 /* place_page_info.hpp in Headers */, 34921F661BFA0A6900737D6E /* api_mark_point.hpp in Headers */, 675346751A4054E800A0A8C3 /* mwm_url.hpp in Headers */, @@ -564,7 +557,6 @@ F6B283051C1B03320081957A /* gps_track_filter.cpp in Sources */, 675346481A4054E800A0A8C3 /* bookmark_manager.cpp in Sources */, 675346741A4054E800A0A8C3 /* mwm_url.cpp in Sources */, - 6788507E1D059068004201E1 /* booking_api.cpp in Sources */, F6B283091C1B03320081957A /* gps_track.cpp in Sources */, 34583BCF1C88556800F94664 /* place_page_info.cpp in Sources */, F6B283031C1B03320081957A /* gps_track_collection.cpp in Sources */, diff --git a/xcode/omim.xcworkspace/contents.xcworkspacedata b/xcode/omim.xcworkspace/contents.xcworkspacedata index 9b16c04836..4af9eaf9b0 100644 --- a/xcode/omim.xcworkspace/contents.xcworkspacedata +++ b/xcode/omim.xcworkspace/contents.xcworkspacedata @@ -120,6 +120,9 @@ + + diff --git a/xcode/partners_api/partners_api.xcodeproj/project.pbxproj b/xcode/partners_api/partners_api.xcodeproj/project.pbxproj new file mode 100644 index 0000000000..62eb3f0bc3 --- /dev/null +++ b/xcode/partners_api/partners_api.xcodeproj/project.pbxproj @@ -0,0 +1,455 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + F6B536401DA520E40067EEA5 /* booking_api.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F6B5363C1DA520E40067EEA5 /* booking_api.cpp */; }; + F6B536411DA520E40067EEA5 /* booking_api.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F6B5363D1DA520E40067EEA5 /* booking_api.hpp */; }; + F6B536421DA520E40067EEA5 /* uber_api.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F6B5363E1DA520E40067EEA5 /* uber_api.cpp */; }; + F6B536431DA520E40067EEA5 /* uber_api.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F6B5363F1DA520E40067EEA5 /* uber_api.hpp */; }; + F6B536471DA5213D0067EEA5 /* booking_tests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F6B536451DA5213D0067EEA5 /* booking_tests.cpp */; }; + F6B536481DA5213D0067EEA5 /* uber_tests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F6B536461DA5213D0067EEA5 /* uber_tests.cpp */; }; + F6B536671DA522D90067EEA5 /* booking_tests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F6B536451DA5213D0067EEA5 /* booking_tests.cpp */; }; + F6B536681DA522D90067EEA5 /* uber_tests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F6B536461DA5213D0067EEA5 /* uber_tests.cpp */; }; + F6B5366A1DA523060067EEA5 /* testingmain.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F6B536691DA523060067EEA5 /* testingmain.cpp */; }; + F6B5366B1DA5230C0067EEA5 /* testingmain.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F6B536691DA523060067EEA5 /* testingmain.cpp */; }; + F6B5366C1DA523430067EEA5 /* libpartners_api.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F6B536341DA5209F0067EEA5 /* libpartners_api.a */; }; + F6B5366F1DA523A70067EEA5 /* MAPSME.plist in Resources */ = {isa = PBXBuildFile; fileRef = F6B5366D1DA523A70067EEA5 /* MAPSME.plist */; }; + F6B536741DA523D60067EEA5 /* libbase.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F6B536711DA523D60067EEA5 /* libbase.a */; }; + F6B536751DA523D60067EEA5 /* libjansson.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F6B536721DA523D60067EEA5 /* libjansson.a */; }; + F6B536761DA523D60067EEA5 /* libplatform.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F6B536731DA523D60067EEA5 /* libplatform.a */; }; + F6B536781DA523EF0067EEA5 /* libindexer.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F6B536771DA523EF0067EEA5 /* libindexer.a */; }; + F6B5367B1DA524030067EEA5 /* libalohalitics.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F6B536791DA524030067EEA5 /* libalohalitics.a */; }; + F6B5367C1DA524030067EEA5 /* libtomcrypt.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F6B5367A1DA524030067EEA5 /* libtomcrypt.a */; }; + F6B5367E1DA5242A0067EEA5 /* libcoding.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F6B5367D1DA5242A0067EEA5 /* libcoding.a */; }; + F6B536801DA5243B0067EEA5 /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = F6B5367F1DA5243B0067EEA5 /* libz.tbd */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + F6B536341DA5209F0067EEA5 /* libpartners_api.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libpartners_api.a; sourceTree = BUILT_PRODUCTS_DIR; }; + F6B5363C1DA520E40067EEA5 /* booking_api.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = booking_api.cpp; sourceTree = ""; }; + F6B5363D1DA520E40067EEA5 /* booking_api.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = booking_api.hpp; sourceTree = ""; }; + F6B5363E1DA520E40067EEA5 /* uber_api.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = uber_api.cpp; sourceTree = ""; }; + F6B5363F1DA520E40067EEA5 /* uber_api.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = uber_api.hpp; sourceTree = ""; }; + F6B536451DA5213D0067EEA5 /* booking_tests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = booking_tests.cpp; sourceTree = ""; }; + F6B536461DA5213D0067EEA5 /* uber_tests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = uber_tests.cpp; sourceTree = ""; }; + F6B536491DA521530067EEA5 /* defaults.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = defaults.xcconfig; path = ../defaults.xcconfig; sourceTree = ""; }; + F6B536501DA522BB0067EEA5 /* partnes_api_test.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = partnes_api_test.app; sourceTree = BUILT_PRODUCTS_DIR; }; + F6B536691DA523060067EEA5 /* testingmain.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = testingmain.cpp; path = ../../testing/testingmain.cpp; sourceTree = ""; }; + F6B5366D1DA523A70067EEA5 /* MAPSME.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = MAPSME.plist; path = ../../iphone/Maps/MAPSME.plist; sourceTree = ""; }; + F6B536711DA523D60067EEA5 /* libbase.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libbase.a; path = "../../../omim-xcode-build/Debug/libbase.a"; sourceTree = ""; }; + F6B536721DA523D60067EEA5 /* libjansson.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libjansson.a; path = "../../../omim-xcode-build/Debug/libjansson.a"; sourceTree = ""; }; + F6B536731DA523D60067EEA5 /* libplatform.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libplatform.a; path = "../../../omim-xcode-build/Debug/libplatform.a"; sourceTree = ""; }; + F6B536771DA523EF0067EEA5 /* libindexer.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libindexer.a; path = "../../../omim-xcode-build/Debug/libindexer.a"; sourceTree = ""; }; + F6B536791DA524030067EEA5 /* libalohalitics.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libalohalitics.a; path = "../../../omim-xcode-build/Debug/libalohalitics.a"; sourceTree = ""; }; + F6B5367A1DA524030067EEA5 /* libtomcrypt.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libtomcrypt.a; path = "../../../omim-xcode-build/Debug/libtomcrypt.a"; sourceTree = ""; }; + F6B5367D1DA5242A0067EEA5 /* libcoding.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libcoding.a; path = "../../../omim-xcode-build/Debug/libcoding.a"; sourceTree = ""; }; + F6B5367F1DA5243B0067EEA5 /* libz.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS10.0.sdk/usr/lib/libz.tbd; sourceTree = DEVELOPER_DIR; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + F6B536311DA5209F0067EEA5 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + F6B5364D1DA522BB0067EEA5 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + F6B536801DA5243B0067EEA5 /* libz.tbd in Frameworks */, + F6B5367E1DA5242A0067EEA5 /* libcoding.a in Frameworks */, + F6B5367B1DA524030067EEA5 /* libalohalitics.a in Frameworks */, + F6B5367C1DA524030067EEA5 /* libtomcrypt.a in Frameworks */, + F6B536781DA523EF0067EEA5 /* libindexer.a in Frameworks */, + F6B536741DA523D60067EEA5 /* libbase.a in Frameworks */, + F6B536751DA523D60067EEA5 /* libjansson.a in Frameworks */, + F6B536761DA523D60067EEA5 /* libplatform.a in Frameworks */, + F6B5366C1DA523430067EEA5 /* libpartners_api.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + F6B5362B1DA5209F0067EEA5 = { + isa = PBXGroup; + children = ( + F6B536491DA521530067EEA5 /* defaults.xcconfig */, + F6B536441DA521060067EEA5 /* partners_api_tests */, + F6B5363B1DA520B20067EEA5 /* partners_api */, + F6B536351DA5209F0067EEA5 /* Products */, + F6B5366E1DA523A70067EEA5 /* Support files */, + F6B536701DA523D60067EEA5 /* Frameworks */, + ); + sourceTree = ""; + }; + F6B536351DA5209F0067EEA5 /* Products */ = { + isa = PBXGroup; + children = ( + F6B536341DA5209F0067EEA5 /* libpartners_api.a */, + F6B536501DA522BB0067EEA5 /* partnes_api_test.app */, + ); + name = Products; + sourceTree = ""; + }; + F6B5363B1DA520B20067EEA5 /* partners_api */ = { + isa = PBXGroup; + children = ( + F6B5363C1DA520E40067EEA5 /* booking_api.cpp */, + F6B5363D1DA520E40067EEA5 /* booking_api.hpp */, + F6B5363E1DA520E40067EEA5 /* uber_api.cpp */, + F6B5363F1DA520E40067EEA5 /* uber_api.hpp */, + ); + name = partners_api; + path = ../../partners_api; + sourceTree = SOURCE_ROOT; + }; + F6B536441DA521060067EEA5 /* partners_api_tests */ = { + isa = PBXGroup; + children = ( + F6B536691DA523060067EEA5 /* testingmain.cpp */, + F6B536451DA5213D0067EEA5 /* booking_tests.cpp */, + F6B536461DA5213D0067EEA5 /* uber_tests.cpp */, + ); + name = partners_api_tests; + path = ../../partners_api/partners_api_tests; + sourceTree = SOURCE_ROOT; + }; + F6B5366E1DA523A70067EEA5 /* Support files */ = { + isa = PBXGroup; + children = ( + F6B5366D1DA523A70067EEA5 /* MAPSME.plist */, + ); + name = "Support files"; + path = ../routing; + sourceTree = ""; + }; + F6B536701DA523D60067EEA5 /* Frameworks */ = { + isa = PBXGroup; + children = ( + F6B5367F1DA5243B0067EEA5 /* libz.tbd */, + F6B5367D1DA5242A0067EEA5 /* libcoding.a */, + F6B536791DA524030067EEA5 /* libalohalitics.a */, + F6B5367A1DA524030067EEA5 /* libtomcrypt.a */, + F6B536771DA523EF0067EEA5 /* libindexer.a */, + F6B536711DA523D60067EEA5 /* libbase.a */, + F6B536721DA523D60067EEA5 /* libjansson.a */, + F6B536731DA523D60067EEA5 /* libplatform.a */, + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + F6B536321DA5209F0067EEA5 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + F6B536411DA520E40067EEA5 /* booking_api.hpp in Headers */, + F6B536431DA520E40067EEA5 /* uber_api.hpp in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + F6B536331DA5209F0067EEA5 /* partners_api */ = { + isa = PBXNativeTarget; + buildConfigurationList = F6B536381DA5209F0067EEA5 /* Build configuration list for PBXNativeTarget "partners_api" */; + buildPhases = ( + F6B536301DA5209F0067EEA5 /* Sources */, + F6B536311DA5209F0067EEA5 /* Frameworks */, + F6B536321DA5209F0067EEA5 /* Headers */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = partners_api; + productName = partners_api; + productReference = F6B536341DA5209F0067EEA5 /* libpartners_api.a */; + productType = "com.apple.product-type.library.static"; + }; + F6B5364F1DA522BB0067EEA5 /* partnes_api_test */ = { + isa = PBXNativeTarget; + buildConfigurationList = F6B536641DA522BB0067EEA5 /* Build configuration list for PBXNativeTarget "partnes_api_test" */; + buildPhases = ( + F6B5364C1DA522BB0067EEA5 /* Sources */, + F6B5364D1DA522BB0067EEA5 /* Frameworks */, + F6B5364E1DA522BB0067EEA5 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = partnes_api_test; + productName = partnes_api_test; + productReference = F6B536501DA522BB0067EEA5 /* partnes_api_test.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + F6B5362C1DA5209F0067EEA5 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0800; + TargetAttributes = { + F6B536331DA5209F0067EEA5 = { + CreatedOnToolsVersion = 8.0; + ProvisioningStyle = Automatic; + }; + F6B5364F1DA522BB0067EEA5 = { + CreatedOnToolsVersion = 8.0; + ProvisioningStyle = Automatic; + }; + }; + }; + buildConfigurationList = F6B5362F1DA5209F0067EEA5 /* Build configuration list for PBXProject "partners_api" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = F6B5362B1DA5209F0067EEA5; + productRefGroup = F6B536351DA5209F0067EEA5 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + F6B536331DA5209F0067EEA5 /* partners_api */, + F6B5364F1DA522BB0067EEA5 /* partnes_api_test */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + F6B5364E1DA522BB0067EEA5 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + F6B5366F1DA523A70067EEA5 /* MAPSME.plist in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + F6B536301DA5209F0067EEA5 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + F6B536421DA520E40067EEA5 /* uber_api.cpp in Sources */, + F6B536471DA5213D0067EEA5 /* booking_tests.cpp in Sources */, + F6B5366A1DA523060067EEA5 /* testingmain.cpp in Sources */, + F6B536401DA520E40067EEA5 /* booking_api.cpp in Sources */, + F6B536481DA5213D0067EEA5 /* uber_tests.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + F6B5364C1DA522BB0067EEA5 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + F6B5366B1DA5230C0067EEA5 /* testingmain.cpp in Sources */, + F6B536671DA522D90067EEA5 /* booking_tests.cpp in Sources */, + F6B536681DA522D90067EEA5 /* uber_tests.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + F6B536361DA5209F0067EEA5 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = F6B536491DA521530067EEA5 /* defaults.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVES = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = "DEBUG=1"; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = ( + "$(OMIM_ROOT)", + "$(BOOST_ROOT)", + "$(OMIM_ROOT)/3party/jansson/src", + ); + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SUPPORTED_PLATFORMS = "iphonesimulator iphoneos macosx"; + }; + name = Debug; + }; + F6B536371DA5209F0067EEA5 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = F6B536491DA521530067EEA5 /* defaults.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVES = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = ( + "$(OMIM_ROOT)", + "$(BOOST_ROOT)", + "$(OMIM_ROOT)/3party/jansson/src", + ); + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + SUPPORTED_PLATFORMS = "iphonesimulator iphoneos macosx"; + }; + name = Release; + }; + F6B536391DA5209F0067EEA5 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + EXECUTABLE_PREFIX = lib; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + F6B5363A1DA5209F0067EEA5 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + EXECUTABLE_PREFIX = lib; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; + F6B536651DA522BB0067EEA5 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "OMIM_UNIT_TEST_WITH_QT_EVENT_LOOP=1", + ); + INFOPLIST_FILE = "$(SRCROOT)/../../iphone/Maps/MAPSME.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "V.partnes-api-test"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + F6B536661DA522BB0067EEA5 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + GCC_PREPROCESSOR_DEFINITIONS = "OMIM_UNIT_TEST_WITH_QT_EVENT_LOOP=1"; + INFOPLIST_FILE = "$(SRCROOT)/../../iphone/Maps/MAPSME.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "V.partnes-api-test"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + F6B5362F1DA5209F0067EEA5 /* Build configuration list for PBXProject "partners_api" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + F6B536361DA5209F0067EEA5 /* Debug */, + F6B536371DA5209F0067EEA5 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + F6B536381DA5209F0067EEA5 /* Build configuration list for PBXNativeTarget "partners_api" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + F6B536391DA5209F0067EEA5 /* Debug */, + F6B5363A1DA5209F0067EEA5 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + F6B536641DA522BB0067EEA5 /* Build configuration list for PBXNativeTarget "partnes_api_test" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + F6B536651DA522BB0067EEA5 /* Debug */, + F6B536661DA522BB0067EEA5 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = F6B5362C1DA5209F0067EEA5 /* Project object */; +}