mirror of
				https://github.com/ciphervance/supercell-wx.git
				synced 2025-10-31 10:10:05 +00:00 
			
		
		
		
	Update IemApiProvider to use template functions
This commit is contained in:
		
							parent
							
								
									1a1c668d62
								
							
						
					
					
						commit
						65e3a66750
					
				
					 5 changed files with 159 additions and 115 deletions
				
			
		|  | @ -10,7 +10,6 @@ | |||
| #include <algorithm> | ||||
| #include <list> | ||||
| #include <map> | ||||
| #include <ranges> | ||||
| #include <shared_mutex> | ||||
| #include <unordered_map> | ||||
| 
 | ||||
|  | @ -20,8 +19,9 @@ | |||
| #include <boost/container/stable_vector.hpp> | ||||
| #include <boost/range/irange.hpp> | ||||
| #include <range/v3/range/conversion.hpp> | ||||
| #include <range/v3/view/any_view.hpp> | ||||
| #include <range/v3/view/filter.hpp> | ||||
| #include <range/v3/view/single.hpp> | ||||
| #include <range/v3/view/transform.hpp> | ||||
| 
 | ||||
| #if (__cpp_lib_chrono < 201907L) | ||||
| #   include <date/date.h> | ||||
|  | @ -117,11 +117,17 @@ public: | |||
| 
 | ||||
|    void | ||||
|    HandleMessage(const std::shared_ptr<awips::TextProductMessage>& message); | ||||
|    void ListArchives(ranges::any_view<std::chrono::sys_days> dates); | ||||
|    template<ranges::forward_range DateRange> | ||||
|       requires std::same_as<ranges::range_value_t<DateRange>, | ||||
|                             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<std::chrono::sys_days> dates); | ||||
|    template<ranges::forward_range DateRange> | ||||
|       requires std::same_as<ranges::range_value_t<DateRange>, | ||||
|                             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<provider::IemApiProvider> iemApiProvider_ { | ||||
|       std::make_unique<provider::IemApiProvider>()}; | ||||
|    std::shared_ptr<provider::WarningsProvider> 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<std::chrono::sys_days> 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<std::chrono::sys_days> dates) | ||||
| template<ranges::forward_range DateRange> | ||||
|    requires std::same_as<ranges::range_value_t<DateRange>, | ||||
|                          std::chrono::sys_days> | ||||
| void TextEventManager::Impl::ListArchives(DateRange dates) | ||||
| { | ||||
|    // Don't reload data that has already been loaded
 | ||||
|    ranges::any_view<std::chrono::sys_days> 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<std::chrono::sys_days> dates) | ||||
| template<ranges::forward_range DateRange> | ||||
|    requires std::same_as<ranges::range_value_t<DateRange>, | ||||
|                          std::chrono::sys_days> | ||||
| void TextEventManager::Impl::UpdateArchiveDates(DateRange dates) | ||||
| { | ||||
|    for (const auto& date : dates) | ||||
|    { | ||||
|  |  | |||
|  | @ -1,24 +1,21 @@ | |||
| #pragma once | ||||
| 
 | ||||
| #include <scwx/awips/text_product_file.hpp> | ||||
| #include <scwx/network/cpr.hpp> | ||||
| #include <scwx/types/iem_types.hpp> | ||||
| 
 | ||||
| #include <memory> | ||||
| #include <ranges> | ||||
| #include <string> | ||||
| #include <vector> | ||||
| 
 | ||||
| #include <boost/outcome/result.hpp> | ||||
| #include <cpr/cpr.h> | ||||
| #include <cpr/session.h> | ||||
| #include <range/v3/range/concepts.hpp> | ||||
| 
 | ||||
| #if defined(_MSC_VER) | ||||
| #   pragma warning(push) | ||||
| #   pragma warning(disable : 4702) | ||||
| #endif | ||||
| 
 | ||||
| #include <range/v3/view/any_view.hpp> | ||||
| 
 | ||||
| #if defined(_MSC_VER) | ||||
| #   pragma warning(pop) | ||||
| #endif | ||||
|  | @ -42,50 +39,41 @@ public: | |||
|    IemApiProvider& operator=(IemApiProvider&&) noexcept; | ||||
| 
 | ||||
|    static boost::outcome_v2::result<std::vector<types::iem::AfosEntry>> | ||||
|    ListTextProducts(std::chrono::sys_time<std::chrono::days> date, | ||||
|                     std::optional<std::string_view>          cccc = {}, | ||||
|                     std::optional<std::string_view>          pil  = {}); | ||||
|    ListTextProducts(std::chrono::sys_days           date, | ||||
|                     std::optional<std::string_view> cccc = {}, | ||||
|                     std::optional<std::string_view> pil  = {}); | ||||
| 
 | ||||
|    template<ranges::forward_range DateRange, | ||||
|             ranges::forward_range CcccRange, | ||||
|             ranges::forward_range PilRange> | ||||
|       requires std::same_as<ranges::range_value_t<DateRange>, | ||||
|                             std::chrono::sys_days> && | ||||
|                std::same_as<ranges::range_value_t<CcccRange>, | ||||
|                             std::string_view> && | ||||
|                std::same_as<ranges::range_value_t<PilRange>, std::string_view> | ||||
|    static boost::outcome_v2::result<std::vector<types::iem::AfosEntry>> | ||||
|    ListTextProducts( | ||||
|       ranges::any_view<std::chrono::sys_time<std::chrono::days>> dates, | ||||
|       ranges::any_view<std::string_view>                         ccccs = {}, | ||||
|       ranges::any_view<std::string_view>                         pils  = {}); | ||||
|    ListTextProducts(DateRange dates, CcccRange ccccs, PilRange pils); | ||||
| 
 | ||||
|    template<std::ranges::forward_range Range> | ||||
|       requires std::same_as<std::ranges::range_value_t<Range>, std::string> | ||||
|    template<ranges::forward_range Range> | ||||
|       requires std::same_as<ranges::range_value_t<Range>, std::string> | ||||
|    static std::vector<std::shared_ptr<awips::TextProductFile>> | ||||
|    LoadTextProducts(const Range& textProducts) | ||||
|    { | ||||
|       auto parameters = cpr::Parameters {{"nolimit", "true"}}; | ||||
| 
 | ||||
|       std::vector<std::pair<std::string, cpr::AsyncResponse>> 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<Impl> p; | ||||
| 
 | ||||
|    static boost::outcome_v2::result<std::vector<types::iem::AfosEntry>> | ||||
|    ProcessTextProductLists(std::vector<cpr::AsyncResponse>& asyncResponses); | ||||
|    static std::vector<std::shared_ptr<awips::TextProductFile>> | ||||
|    ProcessTextProductFiles( | ||||
|       std::vector<std::pair<std::string, cpr::AsyncResponse>>& asyncResponses); | ||||
| 
 | ||||
|    static const std::string kBaseUrl_; | ||||
|    static const std::string kListNwsTextProductsEndpoint_; | ||||
|    static const std::string kNwsTextProductEndpoint_; | ||||
| 
 | ||||
|    static std::vector<std::shared_ptr<awips::TextProductFile>> | ||||
|    ProcessTextProductResponses( | ||||
|       std::vector<std::pair<std::string, cpr::AsyncResponse>>& asyncResponses); | ||||
| }; | ||||
| 
 | ||||
| } // namespace scwx::provider
 | ||||
| 
 | ||||
| #include <scwx/provider/iem_api_provider.ipp> | ||||
|  |  | |||
							
								
								
									
										95
									
								
								wxdata/include/scwx/provider/iem_api_provider.ipp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										95
									
								
								wxdata/include/scwx/provider/iem_api_provider.ipp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,95 @@ | |||
| #pragma once | ||||
| 
 | ||||
| #include <scwx/provider/iem_api_provider.hpp> | ||||
| #include <scwx/network/cpr.hpp> | ||||
| 
 | ||||
| #include <cpr/cpr.h> | ||||
| #include <range/v3/view/cartesian_product.hpp> | ||||
| #include <range/v3/view/single.hpp> | ||||
| 
 | ||||
| #if (__cpp_lib_chrono < 201907L) | ||||
| #   include <date/date.h> | ||||
| #endif | ||||
| 
 | ||||
| namespace scwx::provider | ||||
| { | ||||
| 
 | ||||
| template<ranges::forward_range DateRange, | ||||
|          ranges::forward_range CcccRange, | ||||
|          ranges::forward_range PilRange> | ||||
|    requires std::same_as<ranges::range_value_t<DateRange>, | ||||
|                          std::chrono::sys_days> && | ||||
|             std::same_as<ranges::range_value_t<CcccRange>, std::string_view> && | ||||
|             std::same_as<ranges::range_value_t<PilRange>, std::string_view> | ||||
| boost::outcome_v2::result<std::vector<types::iem::AfosEntry>> | ||||
| 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<cpr::AsyncResponse> 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<ranges::forward_range Range> | ||||
|    requires std::same_as<ranges::range_value_t<Range>, std::string> | ||||
| std::vector<std::shared_ptr<awips::TextProductFile>> | ||||
| IemApiProvider::LoadTextProducts(const Range& textProducts) | ||||
| { | ||||
|    auto parameters = cpr::Parameters {{"nolimit", "true"}}; | ||||
| 
 | ||||
|    std::vector<std::pair<std::string, cpr::AsyncResponse>> 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 | ||||
|  | @ -44,7 +44,7 @@ IemApiProvider::IemApiProvider(IemApiProvider&&) noexcept            = default; | |||
| IemApiProvider& IemApiProvider::operator=(IemApiProvider&&) noexcept = default; | ||||
| 
 | ||||
| boost::outcome_v2::result<std::vector<types::iem::AfosEntry>> | ||||
| IemApiProvider::ListTextProducts(std::chrono::sys_time<std::chrono::days> date, | ||||
| IemApiProvider::ListTextProducts(std::chrono::sys_days           date, | ||||
|                                  std::optional<std::string_view> optionalCccc, | ||||
|                                  std::optional<std::string_view> optionalPil) | ||||
| { | ||||
|  | @ -61,67 +61,12 @@ IemApiProvider::ListTextProducts(std::chrono::sys_time<std::chrono::days> date, | |||
| } | ||||
| 
 | ||||
| boost::outcome_v2::result<std::vector<types::iem::AfosEntry>> | ||||
| IemApiProvider::ListTextProducts( | ||||
|    ranges::any_view<std::chrono::sys_time<std::chrono::days>> dates, | ||||
|    ranges::any_view<std::string_view>                         ccccs, | ||||
|    ranges::any_view<std::string_view>                         pils) | ||||
| IemApiProvider::ProcessTextProductLists( | ||||
|    std::vector<cpr::AsyncResponse>& 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<std::vector>(dates); | ||||
|    const auto cv = ranges::to<std::vector>(ccccs); | ||||
|    const auto pv = ranges::to<std::vector>(pils); | ||||
| 
 | ||||
|    std::vector<cpr::AsyncResponse> 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<types::iem::AfosEntry> textProducts {}; | ||||
| 
 | ||||
|    for (auto& asyncResponse : responses) | ||||
|    for (auto& asyncResponse : asyncResponses) | ||||
|    { | ||||
|       auto response = asyncResponse.get(); | ||||
| 
 | ||||
|  | @ -201,7 +146,7 @@ IemApiProvider::ListTextProducts( | |||
| } | ||||
| 
 | ||||
| std::vector<std::shared_ptr<awips::TextProductFile>> | ||||
| IemApiProvider::ProcessTextProductResponses( | ||||
| IemApiProvider::ProcessTextProductFiles( | ||||
|    std::vector<std::pair<std::string, cpr::AsyncResponse>>& asyncResponses) | ||||
| { | ||||
|    std::vector<std::shared_ptr<awips::TextProductFile>> textProductFiles; | ||||
|  |  | |||
|  | @ -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) | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Dan Paulat
						Dan Paulat