mirror of
https://github.com/ciphervance/supercell-wx.git
synced 2025-10-30 13:30:06 +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