diff options
author | r.kuznetsov <r.kuznetsov@corp.mail.ru> | 2016-07-05 18:10:18 +0300 |
---|---|---|
committer | r.kuznetsov <r.kuznetsov@corp.mail.ru> | 2016-08-23 14:59:15 +0300 |
commit | fafbc2469db5a3c5e4e00dd0c3d2d349d43f3074 (patch) | |
tree | af5f1740135a75c28f06deae40d8876c7216db64 | |
parent | 135a12cd030a8bf0c62caaae621bc625a8ff1be1 (diff) |
Added bookmark generation for bookingsbooking-selection
-rw-r--r-- | android/jni/com/mapswithme/maps/Framework.cpp | 6 | ||||
-rw-r--r-- | android/src/com/mapswithme/maps/Framework.java | 2 | ||||
-rw-r--r-- | android/src/com/mapswithme/maps/widget/placepage/PlacePageView.java | 2 | ||||
-rw-r--r-- | base/string_utils.cpp | 7 | ||||
-rw-r--r-- | base/string_utils.hpp | 13 | ||||
-rw-r--r-- | iphone/Maps/Classes/MWMPlacePageViewManager.mm | 2 | ||||
-rw-r--r-- | map/booking_api.cpp | 128 | ||||
-rw-r--r-- | map/booking_api.hpp | 39 | ||||
-rw-r--r-- | map/booking_collector.cpp | 106 | ||||
-rw-r--r-- | map/booking_collector.hpp | 29 | ||||
-rw-r--r-- | map/framework.cpp | 121 | ||||
-rw-r--r-- | map/framework.hpp | 14 | ||||
-rw-r--r-- | map/map.pro | 2 | ||||
-rw-r--r-- | xcode/map/map.xcodeproj/project.pbxproj | 8 |
14 files changed, 457 insertions, 22 deletions
diff --git a/android/jni/com/mapswithme/maps/Framework.cpp b/android/jni/com/mapswithme/maps/Framework.cpp index cf12d836f9..4dd4c86157 100644 --- a/android/jni/com/mapswithme/maps/Framework.cpp +++ b/android/jni/com/mapswithme/maps/Framework.cpp @@ -1103,4 +1103,10 @@ Java_com_mapswithme_maps_Framework_nativeGetActiveObjectFormattedCuisine(JNIEnv return jni::ToJavaString(env, g_framework->GetPlacePageInfo().FormatCuisines()); } +JNIEXPORT void JNICALL +Java_com_mapswithme_maps_Framework_nativeTryToBookHotel(JNIEnv * env, jclass, jstring jHotelId) +{ + frm()->GetBookingCollector().TryToBookHotel(jni::ToNativeString(env, jHotelId)); +} + } // extern "C" diff --git a/android/src/com/mapswithme/maps/Framework.java b/android/src/com/mapswithme/maps/Framework.java index 35eb79b54c..db12e4db94 100644 --- a/android/src/com/mapswithme/maps/Framework.java +++ b/android/src/com/mapswithme/maps/Framework.java @@ -223,4 +223,6 @@ public class Framework public static native boolean nativeIsInChoosePositionMode(); public static native boolean nativeIsDownloadedMapAtScreenCenter(); public static native String nativeGetActiveObjectFormattedCuisine(); + + public static native void nativeTryToBookHotel(String hotelId); } diff --git a/android/src/com/mapswithme/maps/widget/placepage/PlacePageView.java b/android/src/com/mapswithme/maps/widget/placepage/PlacePageView.java index 0e94928639..14ce7d97b9 100644 --- a/android/src/com/mapswithme/maps/widget/placepage/PlacePageView.java +++ b/android/src/com/mapswithme/maps/widget/placepage/PlacePageView.java @@ -450,6 +450,8 @@ public class PlacePageView extends RelativeLayout final Location location = LocationHelper.INSTANCE.getLastKnownLocation(); Statistics.INSTANCE.trackEvent(event, location, params); + Framework.nativeTryToBookHotel(info.getId()); + try { followUrl(book ? info.urlBook : info.urlDescription); diff --git a/base/string_utils.cpp b/base/string_utils.cpp index 6d017e2405..804b2e14ee 100644 --- a/base/string_utils.cpp +++ b/base/string_utils.cpp @@ -344,4 +344,11 @@ void ParseCSVRow(string const & s, char const delimiter, vector<string> & target target.clear(); } +system_clock::time_point ToTimePoint(string const & str, string const & format) +{ + tm outTm = {}; + strptime(str.c_str(), format.c_str(), &outTm); + return system_clock::from_time_t(mktime(&outTm)); +} + } // namespace strings diff --git a/base/string_utils.hpp b/base/string_utils.hpp index 179a5d560b..461c992b84 100644 --- a/base/string_utils.hpp +++ b/base/string_utils.hpp @@ -1,10 +1,12 @@ #pragma once #include "base/buffer_vector.hpp" +#include "base/gmtime.hpp" #include "base/stl_add.hpp" #include "std/algorithm.hpp" #include "std/cstdint.hpp" +#include "std/chrono.hpp" #include "std/iterator.hpp" #include "std/limits.hpp" #include "std/regex.hpp" @@ -518,4 +520,15 @@ size_t EditDistance(TIter const & b1, TIter const & e1, TIter const & b2, TIter } return prev[m]; } + +template<size_t BufferSize> +string FromTimePoint(system_clock::time_point const & timePoint, string const & format) +{ + char buffer[BufferSize]{}; + tm t = my::GmTime(system_clock::to_time_t(timePoint)); + strftime(buffer, sizeof(buffer), format.c_str(), &t); + return buffer; +} + +system_clock::time_point ToTimePoint(string const & str, string const & format); } // namespace strings diff --git a/iphone/Maps/Classes/MWMPlacePageViewManager.mm b/iphone/Maps/Classes/MWMPlacePageViewManager.mm index 288f410ca8..9e2712002c 100644 --- a/iphone/Maps/Classes/MWMPlacePageViewManager.mm +++ b/iphone/Maps/Classes/MWMPlacePageViewManager.mm @@ -226,6 +226,8 @@ extern NSString * const kBookmarksChangedNotification; withParameters:stat atLocation:[MWMLocationManager lastLocation]]; + GetFramework().GetBookingCollector().TryToBookHotel(string(en.hotelId.UTF8String)); + UIViewController * vc = static_cast<UIViewController *>([MapViewController controller]); NSURL * url = isDescription ? self.entity.bookingDescriptionUrl : self.entity.bookingUrl; NSAssert(url, @"Booking url can't be nil!"); diff --git a/map/booking_api.cpp b/map/booking_api.cpp index d852fc860c..ef0476cd2f 100644 --- a/map/booking_api.cpp +++ b/map/booking_api.cpp @@ -1,9 +1,10 @@ #include "map/booking_api.hpp" -#include "base/gmtime.hpp" +#include "geometry/mercator.hpp" + #include "base/logging.hpp" +#include "base/string_utils.hpp" -#include "std/chrono.hpp" #include "std/iostream.hpp" #include "std/sstream.hpp" @@ -13,6 +14,12 @@ char const BookingApi::kDefaultCurrency[1]; +string const kRequestTimestampFormat = "%Y-%m-%d+%H:%M:%S"; +string const kResponseTimestampFormat = "%Y-%m-%d %H:%M:%S"; +string const kResponseDateFormat = "%Y-%m-%d"; + +string const kServerUrl = "http://tile.osmz.ru/bt/"; + BookingApi::BookingApi() : m_affiliateId(BOOKING_AFFILIATE_ID) { stringstream ss; @@ -32,22 +39,19 @@ string BookingApi::GetDescriptionUrl(string const & baseUrl, string const & /* l void BookingApi::GetMinPrice(string const & hotelId, string const & currency, function<void(string const &, string const &)> const & fn) { - char dateArrival[12]{}; - char dateDeparture[12]{}; - system_clock::time_point p = system_clock::from_time_t(time(nullptr)); - tm arrival = my::GmTime(system_clock::to_time_t(p)); - tm departure = my::GmTime(system_clock::to_time_t(p + hours(24))); - strftime(dateArrival, sizeof(dateArrival), "%Y-%m-%d", &arrival); - strftime(dateDeparture, sizeof(dateDeparture), "%Y-%m-%d", &departure); - - string url = MakeApiUrl("getHotelAvailability", {{"hotel_ids", hotelId}, - {"currency_code", currency}, - {"arrival_date", dateArrival}, - {"departure_date", dateDeparture}}); + + int constexpr kBufferSize = 12; + string const kFormat = "%Y-%m-%d"; + string const dateArrival = strings::FromTimePoint<kBufferSize>(p, kFormat); + string const dateDeparture = strings::FromTimePoint<kBufferSize>(p + hours(24), kFormat); + + string url = MakeApiUrl(m_apiUrl, "getHotelAvailability", {{"hotel_ids", hotelId}, + {"currency_code", currency}, + {"arrival_date", dateArrival}, + {"departure_date", dateDeparture}}); auto const callback = [this, fn, currency](downloader::HttpRequest & answer) { - string minPrice; string priceCurrency; try @@ -94,20 +98,104 @@ void BookingApi::GetMinPrice(string const & hotelId, string const & currency, priceCurrency.clear(); } fn(minPrice, priceCurrency); - m_request.reset(); + m_minPriceRequest.reset(); + }; + + m_minPriceRequest.reset(downloader::HttpRequest::Get(url, callback)); +} + +void BookingApi::GetBookingDetails(system_clock::time_point const & timestampBegin, + system_clock::time_point const & timestampEnd, + vector<string> const & hotelIds, + function<void(vector<Details> const & details, bool success)> const & fn) +{ + if (fn == nullptr) + return; + + if (hotelIds.empty()) + { + fn({}, false /* success */); + return; + } + + int constexpr kBufferSize = 32; + string const dateBegin = strings::FromTimePoint<kBufferSize>(timestampBegin, kRequestTimestampFormat); + string const dateEnd = strings::FromTimePoint<kBufferSize>(timestampEnd, kRequestTimestampFormat); + string const hotelIdsStr = strings::JoinStrings(hotelIds, ","); + string url = MakeApiUrl(kServerUrl, "q", {{"after", dateBegin}, + {"before", dateEnd}, + {"hotel_ids", hotelIdsStr}}); + auto const callback = [this, fn](downloader::HttpRequest & answer) + { + vector<Details> details; + bool success = true; + try + { + my::Json root(answer.Data().c_str()); + if (!json_is_array(root.get())) + MYTHROW(my::Json::Exception, ("The answer must contain a json array.")); + size_t const sz = json_array_size(root.get()); + json_int_t intVal; + string strVal; + double lat, lon; + details.reserve(sz); + for (size_t i = 0; i < sz; i++) + { + Details bookingDetails; + auto obj = json_array_get(root.get(), i); + + my::FromJSONObject(obj, "hotel_id", intVal); + bookingDetails.m_hotelId = strings::to_string(intVal); + + my::FromJSONObjectOptionalField(obj, "booking_id", intVal); + if (intVal != 0) + bookingDetails.m_bookingId = strings::to_string(intVal); + + my::FromJSONObjectOptionalField(obj, "arrival_date", strVal); + if (!strVal.empty()) + { + bookingDetails.m_arrivalDate = strings::ToTimePoint(strVal, kResponseDateFormat); + bookingDetails.hasArrivalDate = true; + } + + my::FromJSONObjectOptionalField(obj, "departure_date", strVal); + if (!strVal.empty()) + { + bookingDetails.m_departureDate = strings::ToTimePoint(strVal, kResponseDateFormat); + bookingDetails.hasDepartureDate = true; + } + + my::FromJSONObject(obj, "booking_datetime", strVal); + bookingDetails.m_bookingTimestamp = strings::ToTimePoint(strVal, kResponseTimestampFormat); + + my::FromJSONObject(obj, "lat", lat); + my::FromJSONObject(obj, "lon", lon); + bookingDetails.m_point = MercatorBounds::FromLatLon(lat, lon); + + details.push_back(move(bookingDetails)); + } + } + catch (my::Json::Exception const & e) + { + LOG(LWARNING, (e.Msg())); + success = false; + } + + fn(details, success); + m_bookingDetailsRequest.reset(); }; - m_request.reset(downloader::HttpRequest::Get(url, callback)); + m_bookingDetailsRequest.reset(downloader::HttpRequest::Get(url, callback)); } -string BookingApi::MakeApiUrl(string const & func, +string BookingApi::MakeApiUrl(string const & url, string const & func, initializer_list<pair<string, string>> const & params) { stringstream ss; - ss << m_apiUrl << func << "?"; + ss << url << func << "?"; bool firstRun = true; for (auto const & param : params) ss << (firstRun ? firstRun = false, "" : "&") << param.first << "=" << param.second; return ss.str(); -}
\ No newline at end of file +} diff --git a/map/booking_api.hpp b/map/booking_api.hpp index 76fef16c7c..3ecd6058a1 100644 --- a/map/booking_api.hpp +++ b/map/booking_api.hpp @@ -1,7 +1,10 @@ #pragma once +#include "geometry/point2d.hpp" + #include "platform/http_request.hpp" +#include "std/chrono.hpp" #include "std/function.hpp" #include "std/initializer_list.hpp" #include "std/string.hpp" @@ -16,13 +19,45 @@ class BookingApi public: static constexpr const char kDefaultCurrency[1] = {0}; + struct Details + { + string m_bookingId; + string m_hotelId; + m2::PointD m_point; + system_clock::time_point m_arrivalDate; + system_clock::time_point m_departureDate; + system_clock::time_point m_bookingTimestamp; + bool hasArrivalDate = false; + bool hasDepartureDate = false; + + Details() = default; + Details(string const & bookingId, string const & hotelId, m2::PointD const & point, + system_clock::time_point const & arrivalDate, + system_clock::time_point const & departureDate, + system_clock::time_point const & bookingTimestamp) + : m_bookingId(bookingId) + , m_hotelId(hotelId) + , m_point(point) + , m_arrivalDate(arrivalDate) + , m_departureDate(departureDate) + , m_bookingTimestamp(bookingTimestamp) + {} + }; + BookingApi(); string GetBookingUrl(string const & baseUrl, string const & lang = string()) const; string GetDescriptionUrl(string const & baseUrl, string const & lang = string()) const; void GetMinPrice(string const & hotelId, string const & currency, function<void(string const &, string const &)> const & fn); + void GetBookingDetails(system_clock::time_point const & timestampBegin, + system_clock::time_point const & timestampEnd, + vector<string> const & hotelIds, + function<void(vector<Details> const & details, bool success)> const & fn); protected: - unique_ptr<downloader::HttpRequest> m_request; - string MakeApiUrl(string const & func, initializer_list<pair<string, string>> const & params); + unique_ptr<downloader::HttpRequest> m_minPriceRequest; + unique_ptr<downloader::HttpRequest> m_bookingDetailsRequest; + + static string MakeApiUrl(string const & url, string const & func, + initializer_list<pair<string, string>> const & params); }; diff --git a/map/booking_collector.cpp b/map/booking_collector.cpp new file mode 100644 index 0000000000..856820f32f --- /dev/null +++ b/map/booking_collector.cpp @@ -0,0 +1,106 @@ +#include "map/booking_collector.hpp" + +#include "platform/settings.hpp" + +#include "base/gmtime.hpp" +#include "base/stl_helpers.hpp" +#include "base/string_utils.hpp" + +#include "std/algorithm.hpp" +#include "std/sstream.hpp" + +namespace +{ +string const kTimestampFormat = "%Y-%m-%d %H:%M:%S"; + +string SerializeTimestamp(system_clock::time_point const & timestamp) +{ + int constexpr kBufferSize = 32; + return strings::FromTimePoint<kBufferSize>(timestamp, kTimestampFormat); +} + +system_clock::time_point DeserializeTimestamp(string const & str) +{ + return strings::ToTimePoint(str, kTimestampFormat); +} + +string SerializeHotels(vector<string> const & hotels) +{ + return strings::JoinStrings(hotels, ","); +} + +vector<string> DeserializeHotels(string const & str) +{ + vector<string> result; + strings::Tokenize(str, ",", [&result](string const & token) + { + result.push_back(token); + }); + return result; +} +} // namespace + +void BookingCollector::Serialize() +{ + settings::Set("BookingTimestampBegin", SerializeTimestamp(m_data.m_timestampBegin)); + settings::Set("BookingTimestampEnd", SerializeTimestamp(m_data.m_timestampEnd)); + settings::Set("BookingHotels", SerializeHotels(m_data.m_hotelIds)); +} + +void BookingCollector::Deserialize() +{ + string outVal; + if (settings::Get("BookingTimestampBegin", outVal)) + m_data.m_timestampBegin = DeserializeTimestamp(outVal); + + if (settings::Get("BookingTimestampEnd", outVal)) + m_data.m_timestampEnd = DeserializeTimestamp(outVal); + + if (settings::Get("BookingHotels", outVal)) + m_data.m_hotelIds = DeserializeHotels(outVal); +} + +void BookingCollector::TryToBookHotel(string const & hotelId) +{ + if (m_data.m_hotelIds.empty()) + { + m_data.m_timestampBegin = system_clock::from_time_t(time(nullptr)); + m_data.m_timestampEnd = m_data.m_timestampBegin + minutes(30); + } + else + { + system_clock::time_point t = system_clock::from_time_t(time(nullptr)); + if (t > m_data.m_timestampEnd) + m_data.m_timestampEnd = t + minutes(30); + } + + if (find(m_data.m_hotelIds.begin(), m_data.m_hotelIds.end(), hotelId) == m_data.m_hotelIds.end()) + m_data.m_hotelIds.push_back(hotelId); +} + +void BookingCollector::RestoreData(Data const & data) +{ + if (m_data.m_hotelIds.empty()) + { + m_data.m_timestampBegin = data.m_timestampBegin; + m_data.m_timestampEnd = data.m_timestampEnd; + m_data.m_hotelIds = data.m_hotelIds; + } + else + { + m_data.m_timestampBegin = min(m_data.m_timestampBegin, data.m_timestampBegin); + m_data.m_timestampEnd = max(m_data.m_timestampEnd, data.m_timestampEnd); + + // Paste hotels and remove duplicates. + auto & v = m_data.m_hotelIds; + v.insert(v.end(), data.m_hotelIds.begin(), data.m_hotelIds.end()); + my::SortUnique(v); + } +} + +BookingCollector::Data BookingCollector::CollectData() +{ + BookingCollector::Data data; + swap(m_data, data); + return data; +} diff --git a/map/booking_collector.hpp b/map/booking_collector.hpp new file mode 100644 index 0000000000..e1dc9a2773 --- /dev/null +++ b/map/booking_collector.hpp @@ -0,0 +1,29 @@ +#pragma once + +#include "std/chrono.hpp" +#include "std/string.hpp" +#include "std/vector.hpp" + +class BookingCollector +{ +public: + struct Data + { + system_clock::time_point m_timestampBegin; + system_clock::time_point m_timestampEnd; + vector<string> m_hotelIds; + }; + + BookingCollector() = default; + + void Serialize(); + void Deserialize(); + + void TryToBookHotel(string const & hotelId); + + Data CollectData(); + void RestoreData(Data const & data); + +private: + Data m_data; +}; diff --git a/map/framework.cpp b/map/framework.cpp index aa9732b0ff..1a0343dbff 100644 --- a/map/framework.cpp +++ b/map/framework.cpp @@ -69,6 +69,7 @@ #include "geometry/rect2d.hpp" #include "geometry/triangle2d.hpp" +#include "base/gmtime.hpp" #include "base/logging.hpp" #include "base/math.hpp" #include "base/scope_guard.hpp" @@ -346,6 +347,9 @@ Framework::Framework() m_stringsBundle.SetDefaultString("routing_failed_route_not_found", "There is no route found between the selected origin and destination.Please select a different start or end point."); m_stringsBundle.SetDefaultString("routing_failed_internal_error", "Internal error occurred. Please try to delete and download the map again. If problem persist please contact us at support@maps.me."); + m_stringsBundle.SetDefaultString("booking_category", "Booked hotels"); + //m_stringsBundle.SetDefaultString("booking_desc", "Arrival: %s\nDeparture: %s"); + m_model.InitClassificator(); m_model.SetOnMapDeregisteredCallback(bind(&Framework::OnMapDeregistered, this, _1)); LOG(LDEBUG, ("Classificator initialized")); @@ -821,6 +825,118 @@ void Framework::ClearBookmarks() m_bmManager.ClearItems(); } +void Framework::UpdateBookings() +{ + BookingCollector::Data data = m_bookingCollector.CollectData(); + if (data.m_hotelIds.empty()) + return; + + m_bookingApi.GetBookingDetails(data.m_timestampBegin, data.m_timestampEnd, data.m_hotelIds, + [this, data](vector<BookingApi::Details> const & details, bool success) + { + UpdateBookingsOnUiThread(details, data, success); + }); +} + +void Framework::UpdateBookingsOnUiThread(vector<BookingApi::Details> const & details, + BookingCollector::Data const & data, bool success) +{ + GetPlatform().RunOnGuiThread([this, details, data, success]() + { + if (success) + UpdateBookingBookmarks(details); + else + m_bookingCollector.RestoreData(data); + }); +} + +void Framework::UpdateBookingBookmarks(vector<BookingApi::Details> const & details) +{ + if (details.empty()) + return; + + // Find or create category. + string categoryName = m_stringsBundle.GetString("booking_category"); + int categoryIndex = -1; + ASSERT_LESS_OR_EQUAL(GetBmCategoriesCount(), numeric_limits<int>::max(), ()); + for (size_t i = 0; i < GetBmCategoriesCount(); ++i) + { + if (GetBmCategory(i)->GetName() == categoryName) + { + categoryIndex = static_cast<int>(i); + break; + } + } + if (categoryIndex == -1) + categoryIndex = AddCategory(categoryName); + + // Find new bookings. + vector<BookingApi::Details> newBookings; + newBookings.reserve(details.size()); + { + BookmarkCategory * cat = GetBmCategory(categoryIndex); + BookmarkCategory::Guard guard(*cat); + double const kEps = 1e-5; + for (BookingApi::Details const & bookingDetails : details) + { + bool isNewBooking = true; + for (size_t i = 0; i < guard.m_controller.GetUserMarkCount(); ++i) + { + UserMark const * bookmark = guard.m_controller.GetUserMark(i); + if (bookmark->GetPivot().EqualDxDy(bookingDetails.m_point, kEps)) + { + isNewBooking = false; + break; + } + } + if (isNewBooking) + newBookings.push_back(bookingDetails); + } + } + + // Create bookmarks. + for (BookingApi::Details const & bookingDetails : newBookings) + { + // TODO: Now we do not show additional information, because we aren't able to + // determine user's booking precisely. + string desc; + //int constexpr kDateBufferSize = 12; + //string const kFormat = "%Y-%m-%d"; + //string const dateArrival = strings::FromTimePoint<kDateBufferSize>(bookingDetails.m_arrivalDate, kFormat); + //string const dateDeparture = strings::FromTimePoint<kDateBufferSize>(bookingDetails.m_departureDate, kFormat); + + //int constexpr kBufferSize = 1024; + //char buffer[kBufferSize]; + //snprintf(buffer, kBufferSize, m_stringsBundle.GetString("booking_desc").c_str(), + // dateArrival.c_str(), dateDeparture.c_str()); + //desc = buffer; + + string bookmarkTitle = GetBookingBookmarkTitle(bookingDetails.m_point); + if (bookmarkTitle.empty()) + continue; + string const kBookmarkType = "placemark-hotel"; + BookmarkData bm(bookmarkTitle, kBookmarkType, desc); + AddBookmark(categoryIndex, bookingDetails.m_point, bm); + } +} + +string Framework::GetBookingBookmarkTitle(m2::PointD const & pt) +{ + string result; + constexpr int kScale = scales::GetUpperScale(); + constexpr double kSelectRectWidthInMeters = 1.0; + m2::RectD const rect = MercatorBounds::RectByCenterXYAndSizeInMeters(pt, kSelectRectWidthInMeters); + int8_t langCode = StringUtf8Multilang::GetLangIndex(languages::GetCurrentNorm()); + if (langCode == StringUtf8Multilang::kUnsupportedLanguageCode) + langCode = StringUtf8Multilang::kDefaultCode; + m_model.ForEachFeature(rect, [&](FeatureType & ft) + { + if (result.empty() && ftypes::IsBookingChecker::Instance()(ft)) + ft.GetName(langCode, result); + }, kScale); + return result; +} + namespace { @@ -1247,6 +1363,8 @@ void Framework::EnterBackground() SaveViewport(); + m_bookingCollector.Serialize(); + ms::LatLon const ll = MercatorBounds::ToLatLon(GetViewportCenter()); alohalytics::Stats::Instance().LogEvent("Framework::EnterBackground", {{"zoom", strings::to_string(GetDrawScale())}, {"foregroundSeconds", strings::to_string( @@ -1262,6 +1380,9 @@ void Framework::EnterBackground() void Framework::EnterForeground() { + m_bookingCollector.Deserialize(); + UpdateBookings(); + m_startForegroundTime = my::Timer::LocalTime(); double const time = m_startForegroundTime - m_startBackgroundTime; CallDrapeFunction(bind(&df::DrapeEngine::SetTimeInBackground, _1, time)); diff --git a/map/framework.hpp b/map/framework.hpp index ff78f9b079..739119a3ed 100644 --- a/map/framework.hpp +++ b/map/framework.hpp @@ -2,6 +2,7 @@ #include "map/api_mark_point.hpp" #include "map/booking_api.hpp" +#include "map/booking_collector.hpp" #include "map/bookmark.hpp" #include "map/bookmark_manager.hpp" #include "map/displacement_mode_manager.hpp" @@ -148,6 +149,7 @@ protected: BookmarkManager m_bmManager; BookingApi m_bookingApi; + BookingCollector m_bookingCollector; bool m_isRenderingEnabled; @@ -178,6 +180,9 @@ public: BookingApi & GetBookingApi() { return m_bookingApi; } BookingApi const & GetBookingApi() const { return m_bookingApi; } + BookingCollector & GetBookingCollector() { return m_bookingCollector; } + BookingCollector const & GetBookingCollector() const { return m_bookingCollector; } + /// Migrate to new version of very different data. bool IsEnoughSpaceForMigrate() const; storage::TCountryId PreMigrate(ms::LatLon const & position, storage::Storage::TChangeCountryFunction const & change, @@ -276,6 +281,9 @@ public: BookmarkAndCategory FindBookmark(UserMark const * mark) const; BookmarkManager & GetBookmarkManager() { return m_bmManager; } + /// Create/update bookmarks for booked hotels. + void UpdateBookings(); + m2::PointD GetSearchMarkSize(SearchMarkType searchMarkType); protected: @@ -304,6 +312,12 @@ private: df::SelectionShape::ESelectedObject selectionType, place_page::Info const & info); void InvalidateUserMarks(); + + void UpdateBookingsOnUiThread(vector<BookingApi::Details> const & details, + BookingCollector::Data const & data, bool success); + void UpdateBookingBookmarks(vector<BookingApi::Details> const & details); + string GetBookingBookmarkTitle(m2::PointD const & pt); + public: void DeactivateMapSelection(bool notifyUI); /// Used to "refresh" UI in some cases (e.g. feature editing). diff --git a/map/map.pro b/map/map.pro index 582f3744d1..feb578c589 100644 --- a/map/map.pro +++ b/map/map.pro @@ -13,6 +13,7 @@ include($$ROOT_DIR/common.pri) HEADERS += \ api_mark_point.hpp \ booking_api.hpp \ + booking_collector.hpp \ bookmark.hpp \ bookmark_manager.hpp \ displacement_mode_manager.hpp \ @@ -36,6 +37,7 @@ SOURCES += \ address_finder.cpp \ api_mark_point.cpp \ booking_api.cpp \ + booking_collector.cpp \ bookmark.cpp \ bookmark_manager.cpp \ displacement_mode_manager.cpp \ diff --git a/xcode/map/map.xcodeproj/project.pbxproj b/xcode/map/map.xcodeproj/project.pbxproj index 94ecc3ac72..e27c845fb7 100644 --- a/xcode/map/map.xcodeproj/project.pbxproj +++ b/xcode/map/map.xcodeproj/project.pbxproj @@ -13,6 +13,8 @@ 34583BD01C88556800F94664 /* place_page_info.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 34583BCE1C88556800F94664 /* place_page_info.hpp */; }; 34921F661BFA0A6900737D6E /* api_mark_point.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 34921F611BFA0A6900737D6E /* api_mark_point.hpp */; }; 45201E931CE4AC90008A4842 /* api_mark_point.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 45201E921CE4AC90008A4842 /* api_mark_point.cpp */; }; + 45D2C84E1D33A623001E9B73 /* booking_collector.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 45D2C84C1D33A623001E9B73 /* booking_collector.cpp */; }; + 45D2C84F1D33A623001E9B73 /* booking_collector.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 45D2C84D1D33A623001E9B73 /* booking_collector.hpp */; }; 670E39401C46C5C700E9C0A6 /* gps_tracker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 670E393E1C46C5C700E9C0A6 /* gps_tracker.cpp */; }; 670E39411C46C5C700E9C0A6 /* gps_tracker.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 670E393F1C46C5C700E9C0A6 /* gps_tracker.hpp */; }; 674A29F01B26FD6F001A525C /* testingmain.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 674A29EE1B26FD5F001A525C /* testingmain.cpp */; }; @@ -129,6 +131,8 @@ 34583BCE1C88556800F94664 /* place_page_info.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = place_page_info.hpp; sourceTree = "<group>"; }; 34921F611BFA0A6900737D6E /* api_mark_point.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = api_mark_point.hpp; sourceTree = "<group>"; }; 45201E921CE4AC90008A4842 /* api_mark_point.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = api_mark_point.cpp; sourceTree = "<group>"; }; + 45D2C84C1D33A623001E9B73 /* booking_collector.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = booking_collector.cpp; sourceTree = "<group>"; }; + 45D2C84D1D33A623001E9B73 /* booking_collector.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = booking_collector.hpp; sourceTree = "<group>"; }; 670D05A41B0DF4250013A7AC /* defaults.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = defaults.xcconfig; path = ../defaults.xcconfig; sourceTree = "<group>"; }; 670E393E1C46C5C700E9C0A6 /* gps_tracker.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = gps_tracker.cpp; sourceTree = "<group>"; }; 670E393F1C46C5C700E9C0A6 /* gps_tracker.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = gps_tracker.hpp; sourceTree = "<group>"; }; @@ -429,6 +433,8 @@ 674A2A371B2715FB001A525C /* osm_opening_hours.hpp */, 6788507C1D059068004201E1 /* booking_api.cpp */, 6788507D1D059068004201E1 /* booking_api.hpp */, + 45D2C84C1D33A623001E9B73 /* booking_collector.cpp */, + 45D2C84D1D33A623001E9B73 /* booking_collector.hpp */, ); name = map; path = ../../map; @@ -455,6 +461,7 @@ 675346491A4054E800A0A8C3 /* bookmark_manager.hpp in Headers */, F6B2830A1C1B03320081957A /* gps_track.hpp in Headers */, 675346631A4054E800A0A8C3 /* feature_vec_model.hpp in Headers */, + 45D2C84F1D33A623001E9B73 /* booking_collector.hpp in Headers */, 6753469C1A4054E800A0A8C3 /* track.hpp in Headers */, 675346651A4054E800A0A8C3 /* framework.hpp in Headers */, 674A2A381B2715FB001A525C /* osm_opening_hours.hpp in Headers */, @@ -571,6 +578,7 @@ F6B283031C1B03320081957A /* gps_track_collection.cpp in Sources */, 6753469B1A4054E800A0A8C3 /* track.cpp in Sources */, 675346621A4054E800A0A8C3 /* feature_vec_model.cpp in Sources */, + 45D2C84E1D33A623001E9B73 /* booking_collector.cpp in Sources */, 6753469D1A4054E800A0A8C3 /* user_mark_container.cpp in Sources */, 674C38621BFF3095000D603B /* user_mark.cpp in Sources */, 675346641A4054E800A0A8C3 /* framework.cpp in Sources */, |