From 65e3a667500e7073aeb4bf09bef33015a545173d Mon Sep 17 00:00:00 2001 From: Dan Paulat Date: Fri, 25 Apr 2025 00:15:05 -0500 Subject: [PATCH] Update IemApiProvider to use template functions --- .../scwx/qt/manager/text_event_manager.cpp | 49 ++++++---- .../scwx/provider/iem_api_provider.hpp | 64 +++++-------- .../scwx/provider/iem_api_provider.ipp | 95 +++++++++++++++++++ .../source/scwx/provider/iem_api_provider.cpp | 65 +------------ wxdata/wxdata.cmake | 1 + 5 files changed, 159 insertions(+), 115 deletions(-) create mode 100644 wxdata/include/scwx/provider/iem_api_provider.ipp diff --git a/scwx-qt/source/scwx/qt/manager/text_event_manager.cpp b/scwx-qt/source/scwx/qt/manager/text_event_manager.cpp index 153696ff..95d86354 100644 --- a/scwx-qt/source/scwx/qt/manager/text_event_manager.cpp +++ b/scwx-qt/source/scwx/qt/manager/text_event_manager.cpp @@ -10,7 +10,6 @@ #include #include #include -#include #include #include @@ -20,8 +19,9 @@ #include #include #include -#include #include +#include +#include #if (__cpp_lib_chrono < 201907L) # include @@ -117,11 +117,17 @@ public: void HandleMessage(const std::shared_ptr& message); - void ListArchives(ranges::any_view dates); + template + requires std::same_as, + std::chrono::sys_days> + void ListArchives(DateRange dates); void LoadArchives(std::chrono::system_clock::time_point dateTime); void RefreshAsync(); void Refresh(); - void UpdateArchiveDates(ranges::any_view dates); + template + requires std::same_as, + std::chrono::sys_days> + void UpdateArchiveDates(DateRange dates); // Thread pool sized for: // - Live Refresh (1x) @@ -139,8 +145,6 @@ public: textEventMap_; std::shared_mutex textEventMutex_; - std::unique_ptr iemApiProvider_ { - std::make_unique()}; std::shared_ptr warningsProvider_ {nullptr}; std::chrono::hours loadHistoryDuration_ {kInitialLoadHistoryDuration_}; @@ -240,7 +244,7 @@ void TextEventManager::SelectTime( const auto tomorrow = today + std::chrono::days {1}; const auto dateArray = std::array {today, yesterday, tomorrow}; - const ranges::any_view dates = + const auto dates = dateArray | ranges::views::filter( [this](const auto& date) { @@ -334,11 +338,13 @@ void TextEventManager::Impl::HandleMessage( } } -void TextEventManager::Impl::ListArchives( - ranges::any_view dates) +template + requires std::same_as, + std::chrono::sys_days> +void TextEventManager::Impl::ListArchives(DateRange dates) { // Don't reload data that has already been loaded - ranges::any_view filteredDates = + auto filteredDates = dates | ranges::views::filter([this](const auto& date) { return !unloadedProductMap_.contains(date); }); @@ -351,10 +357,17 @@ void TextEventManager::Impl::ListArchives( dv.end(), [this](const auto& date) { + static const auto kEmptyRange_ = + ranges::views::single(std::string_view {}); + static const auto kPilsView_ = + kPils_ | + ranges::views::transform([](const std::string& pil) + { return std::string_view {pil}; }); + const auto dateArray = std::array {date}; - auto productEntries = - iemApiProvider_->ListTextProducts(dateArray, {}, kPils_); + auto productEntries = provider::IemApiProvider::ListTextProducts( + dateArray | ranges::views::all, kEmptyRange_, kPilsView_); std::unique_lock lock {unloadedProductMapMutex_}; @@ -450,10 +463,10 @@ void TextEventManager::Impl::LoadArchives( } // Load the load list - auto loadView = loadListEntries | - std::ranges::views::transform([](const auto& entry) + auto loadView = + loadListEntries | ranges::views::transform([](const auto& entry) { return entry.productId_; }); - auto products = iemApiProvider_->LoadTextProducts(loadView); + auto products = provider::IemApiProvider::LoadTextProducts(loadView); // Process loaded products for (auto& product : products) @@ -550,8 +563,10 @@ void TextEventManager::Impl::Refresh() }); } -void TextEventManager::Impl::UpdateArchiveDates( - ranges::any_view dates) +template + requires std::same_as, + std::chrono::sys_days> +void TextEventManager::Impl::UpdateArchiveDates(DateRange dates) { for (const auto& date : dates) { diff --git a/wxdata/include/scwx/provider/iem_api_provider.hpp b/wxdata/include/scwx/provider/iem_api_provider.hpp index 7d697919..3af9f545 100644 --- a/wxdata/include/scwx/provider/iem_api_provider.hpp +++ b/wxdata/include/scwx/provider/iem_api_provider.hpp @@ -1,24 +1,21 @@ #pragma once #include -#include #include #include -#include #include #include #include -#include +#include +#include #if defined(_MSC_VER) # pragma warning(push) # pragma warning(disable : 4702) #endif -#include - #if defined(_MSC_VER) # pragma warning(pop) #endif @@ -42,50 +39,41 @@ public: IemApiProvider& operator=(IemApiProvider&&) noexcept; static boost::outcome_v2::result> - ListTextProducts(std::chrono::sys_time date, - std::optional cccc = {}, - std::optional pil = {}); + ListTextProducts(std::chrono::sys_days date, + std::optional cccc = {}, + std::optional pil = {}); + + template + requires std::same_as, + std::chrono::sys_days> && + std::same_as, + std::string_view> && + std::same_as, std::string_view> static boost::outcome_v2::result> - ListTextProducts( - ranges::any_view> dates, - ranges::any_view ccccs = {}, - ranges::any_view pils = {}); + ListTextProducts(DateRange dates, CcccRange ccccs, PilRange pils); - template - requires std::same_as, std::string> + template + requires std::same_as, std::string> static std::vector> - LoadTextProducts(const Range& textProducts) - { - auto parameters = cpr::Parameters {{"nolimit", "true"}}; - - std::vector> asyncResponses {}; - asyncResponses.reserve(textProducts.size()); - - const std::string endpointUrl = kBaseUrl_ + kNwsTextProductEndpoint_; - - for (const auto& productId : textProducts) - { - asyncResponses.emplace_back( - productId, - cpr::GetAsync(cpr::Url {endpointUrl + productId}, - network::cpr::GetHeader(), - parameters)); - } - - return ProcessTextProductResponses(asyncResponses); - } + LoadTextProducts(const Range& textProducts); private: class Impl; std::unique_ptr p; + static boost::outcome_v2::result> + ProcessTextProductLists(std::vector& asyncResponses); + static std::vector> + ProcessTextProductFiles( + std::vector>& asyncResponses); + static const std::string kBaseUrl_; static const std::string kListNwsTextProductsEndpoint_; static const std::string kNwsTextProductEndpoint_; - - static std::vector> - ProcessTextProductResponses( - std::vector>& asyncResponses); }; } // namespace scwx::provider + +#include diff --git a/wxdata/include/scwx/provider/iem_api_provider.ipp b/wxdata/include/scwx/provider/iem_api_provider.ipp new file mode 100644 index 00000000..3fc94dad --- /dev/null +++ b/wxdata/include/scwx/provider/iem_api_provider.ipp @@ -0,0 +1,95 @@ +#pragma once + +#include +#include + +#include +#include +#include + +#if (__cpp_lib_chrono < 201907L) +# include +#endif + +namespace scwx::provider +{ + +template + requires std::same_as, + std::chrono::sys_days> && + std::same_as, std::string_view> && + std::same_as, std::string_view> +boost::outcome_v2::result> +IemApiProvider::ListTextProducts(DateRange dates, + CcccRange ccccs, + PilRange pils) +{ + using namespace std::chrono; + +#if (__cpp_lib_chrono >= 201907L) + namespace df = std; + + static constexpr std::string_view kDateFormat {"{:%Y-%m-%d}"}; +#else + using namespace date; + namespace df = date; + +# define kDateFormat "%Y-%m-%d" +#endif + + std::vector asyncResponses {}; + + for (const auto& [date, cccc, pil] : + ranges::views::cartesian_product(dates, ccccs, pils)) + { + auto parameters = + cpr::Parameters {{"date", df::format(kDateFormat, date)}}; + + // WMO Source Code + if (!cccc.empty()) + { + parameters.Add({"cccc", std::string {cccc}}); + } + + // AFOS / AWIPS ID / 3-6 length identifier + if (!pil.empty()) + { + parameters.Add({"pil", std::string {pil}}); + } + + asyncResponses.emplace_back( + cpr::GetAsync(cpr::Url {kBaseUrl_ + kListNwsTextProductsEndpoint_}, + network::cpr::GetHeader(), + parameters)); + } + + return ProcessTextProductLists(asyncResponses); +} + +template + requires std::same_as, std::string> +std::vector> +IemApiProvider::LoadTextProducts(const Range& textProducts) +{ + auto parameters = cpr::Parameters {{"nolimit", "true"}}; + + std::vector> asyncResponses {}; + asyncResponses.reserve(textProducts.size()); + + const std::string endpointUrl = kBaseUrl_ + kNwsTextProductEndpoint_; + + for (const auto& productId : textProducts) + { + asyncResponses.emplace_back( + productId, + cpr::GetAsync(cpr::Url {endpointUrl + productId}, + network::cpr::GetHeader(), + parameters)); + } + + return ProcessTextProductFiles(asyncResponses); +} + +} // namespace scwx::provider diff --git a/wxdata/source/scwx/provider/iem_api_provider.cpp b/wxdata/source/scwx/provider/iem_api_provider.cpp index 7e3ff2c4..c4fb1ccd 100644 --- a/wxdata/source/scwx/provider/iem_api_provider.cpp +++ b/wxdata/source/scwx/provider/iem_api_provider.cpp @@ -44,7 +44,7 @@ IemApiProvider::IemApiProvider(IemApiProvider&&) noexcept = default; IemApiProvider& IemApiProvider::operator=(IemApiProvider&&) noexcept = default; boost::outcome_v2::result> -IemApiProvider::ListTextProducts(std::chrono::sys_time date, +IemApiProvider::ListTextProducts(std::chrono::sys_days date, std::optional optionalCccc, std::optional optionalPil) { @@ -61,67 +61,12 @@ IemApiProvider::ListTextProducts(std::chrono::sys_time date, } boost::outcome_v2::result> -IemApiProvider::ListTextProducts( - ranges::any_view> dates, - ranges::any_view ccccs, - ranges::any_view pils) +IemApiProvider::ProcessTextProductLists( + std::vector& asyncResponses) { - using namespace std::chrono; - -#if (__cpp_lib_chrono >= 201907L) - namespace df = std; - - static constexpr std::string_view kDateFormat {"{:%Y-%m-%d}"}; -#else - using namespace date; - namespace df = date; - -# define kDateFormat "%Y-%m-%d" -#endif - - if (ccccs.begin() == ccccs.end()) - { - ccccs = ranges::views::single(std::string_view {}); - } - - if (pils.begin() == pils.end()) - { - pils = ranges::views::single(std::string_view {}); - } - - const auto dv = ranges::to(dates); - const auto cv = ranges::to(ccccs); - const auto pv = ranges::to(pils); - - std::vector responses {}; - - for (const auto& [date, cccc, pil] : - ranges::views::cartesian_product(dv, cv, pv)) - { - auto parameters = - cpr::Parameters {{"date", df::format(kDateFormat, date)}}; - - // WMO Source Code - if (!cccc.empty()) - { - parameters.Add({"cccc", std::string {cccc}}); - } - - // AFOS / AWIPS ID / 3-6 length identifier - if (!pil.empty()) - { - parameters.Add({"pil", std::string {pil}}); - } - - responses.emplace_back( - cpr::GetAsync(cpr::Url {kBaseUrl_ + kListNwsTextProductsEndpoint_}, - network::cpr::GetHeader(), - parameters)); - } - std::vector textProducts {}; - for (auto& asyncResponse : responses) + for (auto& asyncResponse : asyncResponses) { auto response = asyncResponse.get(); @@ -201,7 +146,7 @@ IemApiProvider::ListTextProducts( } std::vector> -IemApiProvider::ProcessTextProductResponses( +IemApiProvider::ProcessTextProductFiles( std::vector>& asyncResponses) { std::vector> textProductFiles; diff --git a/wxdata/wxdata.cmake b/wxdata/wxdata.cmake index 32db05ab..8d2e15b4 100644 --- a/wxdata/wxdata.cmake +++ b/wxdata/wxdata.cmake @@ -63,6 +63,7 @@ set(HDR_PROVIDER include/scwx/provider/aws_level2_data_provider.hpp include/scwx/provider/aws_level3_data_provider.hpp include/scwx/provider/aws_nexrad_data_provider.hpp include/scwx/provider/iem_api_provider.hpp + include/scwx/provider/iem_api_provider.ipp include/scwx/provider/nexrad_data_provider.hpp include/scwx/provider/nexrad_data_provider_factory.hpp include/scwx/provider/warnings_provider.hpp)