diff --git a/scwx-qt/source/scwx/qt/manager/radar_product_manager.cpp b/scwx-qt/source/scwx/qt/manager/radar_product_manager.cpp index 5ca206d1..272a23cb 100644 --- a/scwx-qt/source/scwx/qt/manager/radar_product_manager.cpp +++ b/scwx-qt/source/scwx/qt/manager/radar_product_manager.cpp @@ -216,6 +216,7 @@ public: bool level3ProductsInitialized_; std::shared_ptr radarSite_; + std::size_t cacheLimit_ {6u}; std::vector coordinates0_5Degree_; std::vector coordinates1Degree_; @@ -1135,7 +1136,7 @@ void RadarProductManagerImpl::UpdateRecentRecords( RadarProductRecordList& recentList, std::shared_ptr record) { - static constexpr std::size_t kRecentListMaxSize_ {2u}; + const std::size_t recentListMaxSize {cacheLimit_}; auto it = std::find(recentList.cbegin(), recentList.cend(), record); if (it != recentList.cbegin() && it != recentList.cend()) @@ -1150,7 +1151,7 @@ void RadarProductManagerImpl::UpdateRecentRecords( recentList.push_front(record); } - while (recentList.size() > kRecentListMaxSize_) + while (recentList.size() > recentListMaxSize) { // Remove from the end of the list while it's too big recentList.pop_back(); @@ -1215,6 +1216,11 @@ std::vector RadarProductManager::GetLevel3Products() return level3ProviderManager->provider_->GetAvailableProducts(); } +void RadarProductManager::SetCacheLimit(size_t cacheLimit) +{ + p->cacheLimit_ = cacheLimit; +} + void RadarProductManager::UpdateAvailableProducts() { std::lock_guard guard(p->level3ProductsInitializeMutex_); diff --git a/scwx-qt/source/scwx/qt/manager/radar_product_manager.hpp b/scwx-qt/source/scwx/qt/manager/radar_product_manager.hpp index 34c2c6fb..ed8ba97b 100644 --- a/scwx-qt/source/scwx/qt/manager/radar_product_manager.hpp +++ b/scwx-qt/source/scwx/qt/manager/radar_product_manager.hpp @@ -126,7 +126,15 @@ public: common::Level3ProductCategoryMap GetAvailableLevel3Categories(); std::vector GetLevel3Products(); - void UpdateAvailableProducts(); + + /** + * @brief Set the maximum number of products of each type that may be cached. + * + * @param [in] cacheLimit The maximum number of products of each type + */ + void SetCacheLimit(std::size_t cacheLimit); + + void UpdateAvailableProducts(); signals: void DataReloaded(std::shared_ptr record); diff --git a/scwx-qt/source/scwx/qt/manager/timeline_manager.cpp b/scwx-qt/source/scwx/qt/manager/timeline_manager.cpp index 531dfe15..80d836fc 100644 --- a/scwx-qt/source/scwx/qt/manager/timeline_manager.cpp +++ b/scwx-qt/source/scwx/qt/manager/timeline_manager.cpp @@ -42,6 +42,13 @@ public: TimelineManager* self_; + std::pair + GetLoopStartAndEndTimes(); + void UpdateCacheLimit( + std::shared_ptr radarProductManager, + const std::set& volumeTimes); + void Pause(); void Play(); void SelectTime(std::chrono::system_clock::time_point selectedTime = {}); @@ -223,6 +230,45 @@ void TimelineManager::Impl::Pause() } } +std::pair +TimelineManager::Impl::GetLoopStartAndEndTimes() +{ + // Determine loop end time + std::chrono::system_clock::time_point endTime; + + if (viewType_ == types::MapTime::Live || + pinnedTime_ == std::chrono::system_clock::time_point {}) + { + endTime = std::chrono::floor( + std::chrono::system_clock::now()); + } + else + { + endTime = pinnedTime_; + } + + // Determine loop start time and current position in the loop + std::chrono::system_clock::time_point startTime = endTime - loopTime_; + + return {startTime, endTime}; +} + +void TimelineManager::Impl::UpdateCacheLimit( + std::shared_ptr radarProductManager, + const std::set& volumeTimes) +{ + // Calculate the number of volume scans in the loop + auto [startTime, endTime] = GetLoopStartAndEndTimes(); + auto startIter = util::GetBoundedElementIterator(volumeTimes, startTime); + auto endIter = util::GetBoundedElementIterator(volumeTimes, endTime); + std::size_t numVolumeScans = std::distance(startIter, endIter) + 1; + + // Dynamically update maximum cached volume scans to 1.5x the loop length + radarProductManager->SetCacheLimit( + static_cast(numVolumeScans * 1.5)); +} + void TimelineManager::Impl::Play() { using namespace std::chrono_literals; @@ -244,22 +290,7 @@ void TimelineManager::Impl::Play() // Take a lock for time selection std::unique_lock lock {selectTimeMutex_}; - // Determine loop end time - std::chrono::system_clock::time_point endTime; - - if (viewType_ == types::MapTime::Live || - pinnedTime_ == std::chrono::system_clock::time_point {}) - { - endTime = std::chrono::floor( - std::chrono::system_clock::now()); - } - else - { - endTime = pinnedTime_; - } - - // Determine loop start time and current position in the loop - std::chrono::system_clock::time_point startTime = endTime - loopTime_; + auto [startTime, endTime] = GetLoopStartAndEndTimes(); std::chrono::system_clock::time_point currentTime = selectedTime_; std::chrono::system_clock::time_point newTime; @@ -353,6 +384,9 @@ void TimelineManager::Impl::SelectTime( auto volumeTimes = radarProductManager->GetActiveVolumeTimes(selectedTime); + // Dynamically update maximum cached volume scans + UpdateCacheLimit(radarProductManager, volumeTimes); + // Find the best match bounded time auto elementPtr = util::GetBoundedElementPointer(volumeTimes, selectedTime); @@ -418,6 +452,9 @@ void TimelineManager::Impl::Step(Direction direction) return; } + // Dynamically update maximum cached volume scans + UpdateCacheLimit(radarProductManager, volumeTimes); + std::set::const_iterator it; if (adjustedTime_ == std::chrono::system_clock::time_point {})