From 228ec191f6da72db08ee63195d716887bc55c40c Mon Sep 17 00:00:00 2001 From: Dan Paulat Date: Fri, 2 May 2025 22:56:41 -0500 Subject: [PATCH] Add year to Text Event Key --- .../scwx/qt/manager/text_event_manager.cpp | 24 ++++++++++++++++- .../source/scwx/qt/types/text_event_key.cpp | 14 ++++++---- .../source/scwx/qt/types/text_event_key.hpp | 26 +++++++++++++++++-- 3 files changed, 56 insertions(+), 8 deletions(-) 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 4c17e819..6337e97e 100644 --- a/scwx-qt/source/scwx/qt/manager/text_event_manager.cpp +++ b/scwx-qt/source/scwx/qt/manager/text_event_manager.cpp @@ -275,6 +275,8 @@ void TextEventManager::SelectTime( void TextEventManager::Impl::HandleMessage( const std::shared_ptr& message) { + using namespace std::chrono_literals; + auto segments = message->segments(); // If there are no segments, skip this message @@ -295,15 +297,35 @@ void TextEventManager::Impl::HandleMessage( } } + // Determine year + std::chrono::year_month_day wmoDate = std::chrono::floor( + message->wmo_header()->GetDateTime()); + std::chrono::year wmoYear = wmoDate.year(); + std::unique_lock lock(textEventMutex_); // Find a matching event in the event map auto& vtecString = segments[0]->header_->vtecString_; - types::TextEventKey key {vtecString[0].pVtec_}; + types::TextEventKey key {vtecString[0].pVtec_, wmoYear}; size_t messageIndex = 0; auto it = textEventMap_.find(key); bool updated = false; + if ( + // If there was no matching event + it == textEventMap_.cend() && + // The event is not new + vtecString[0].pVtec_.action() != awips::PVtec::Action::New && + // The message was on January 1 + wmoDate.month() == std::chrono::January && wmoDate.day() == 1d && + // This is at least the 10th ETN of the year + vtecString[0].pVtec_.event_tracking_number() > 10) + { + // Attempt to find a matching event from last year + key = {vtecString[0].pVtec_, wmoYear - std::chrono::years {1}}; + it = textEventMap_.find(key); + } + if (it == textEventMap_.cend()) { // If there was no matching event, add the message to a new event diff --git a/scwx-qt/source/scwx/qt/types/text_event_key.cpp b/scwx-qt/source/scwx/qt/types/text_event_key.cpp index bebf6f63..be5d0443 100644 --- a/scwx-qt/source/scwx/qt/types/text_event_key.cpp +++ b/scwx-qt/source/scwx/qt/types/text_event_key.cpp @@ -14,26 +14,29 @@ static const std::string logPrefix_ = "scwx::qt::types::text_event_key"; std::string TextEventKey::ToFullString() const { - return fmt::format("{} {} {} {:04}", + return fmt::format("{} {} {} {:04} ({:04})", officeId_, awips::GetPhenomenonText(phenomenon_), awips::GetSignificanceText(significance_), - etn_); + etn_, + static_cast(year_)); } std::string TextEventKey::ToString() const { - return fmt::format("{}.{}.{}.{:04}", + return fmt::format("{}.{}.{}.{:04}.{:04}", officeId_, awips::GetPhenomenonCode(phenomenon_), awips::GetSignificanceCode(significance_), - etn_); + etn_, + static_cast(year_)); } bool TextEventKey::operator==(const TextEventKey& o) const { return (officeId_ == o.officeId_ && phenomenon_ == o.phenomenon_ && - significance_ == o.significance_ && etn_ == o.etn_); + significance_ == o.significance_ && etn_ == o.etn_ && + year_ == o.year_); } size_t TextEventHash::operator()(const TextEventKey& x) const @@ -43,6 +46,7 @@ size_t TextEventHash::operator()(const TextEventKey& x) const boost::hash_combine(seed, x.phenomenon_); boost::hash_combine(seed, x.significance_); boost::hash_combine(seed, x.etn_); + boost::hash_combine(seed, static_cast(x.year_)); return seed; } diff --git a/scwx-qt/source/scwx/qt/types/text_event_key.hpp b/scwx-qt/source/scwx/qt/types/text_event_key.hpp index f962bcdf..4cc57dca 100644 --- a/scwx-qt/source/scwx/qt/types/text_event_key.hpp +++ b/scwx-qt/source/scwx/qt/types/text_event_key.hpp @@ -1,6 +1,7 @@ #pragma once #include +#include namespace scwx { @@ -12,12 +13,32 @@ namespace types struct TextEventKey { TextEventKey() : TextEventKey(awips::PVtec {}) {} - TextEventKey(const awips::PVtec& pvtec) : + TextEventKey(const awips::PVtec& pvtec, std::chrono::year yearHint = {}) : officeId_ {pvtec.office_id()}, phenomenon_ {pvtec.phenomenon()}, significance_ {pvtec.significance()}, etn_ {pvtec.event_tracking_number()} { + using namespace std::chrono_literals; + + std::chrono::year_month_day ymd = + std::chrono::floor(pvtec.event_begin()); + if (ymd.year() > 1970y) + { + // Prefer the year from the event begin + year_ = ymd.year(); + } + else if (yearHint > 1970y) + { + // Otherwise, use the year hint + year_ = yearHint; + } + else + { + // If there was no year hint, use the event end + ymd = std::chrono::floor(pvtec.event_end()); + year_ = ymd.year(); + } } std::string ToFullString() const; @@ -27,7 +48,8 @@ struct TextEventKey std::string officeId_; awips::Phenomenon phenomenon_; awips::Significance significance_; - int16_t etn_; + std::int16_t etn_; + std::chrono::year year_; }; template