mirror of
https://github.com/ciphervance/supercell-wx.git
synced 2025-10-30 17:50:04 +00:00
Merge pull request #240 from dpaulat/feature/enhanced-alerts
Show severity in Alert Dock
This commit is contained in:
commit
86bd48a12f
7 changed files with 219 additions and 19 deletions
|
|
@ -34,6 +34,10 @@ public:
|
|||
explicit AlertModelImpl();
|
||||
~AlertModelImpl() = default;
|
||||
|
||||
bool GetObserved(const types::TextEventKey& key);
|
||||
awips::ThreatCategory GetThreatCategory(const types::TextEventKey& key);
|
||||
bool GetTornadoPossible(const types::TextEventKey& key);
|
||||
|
||||
static std::string GetCounties(const types::TextEventKey& key);
|
||||
static std::string GetState(const types::TextEventKey& key);
|
||||
static std::chrono::system_clock::time_point
|
||||
|
|
@ -49,6 +53,18 @@ public:
|
|||
|
||||
const GeographicLib::Geodesic& geodesic_;
|
||||
|
||||
std::unordered_map<types::TextEventKey,
|
||||
bool,
|
||||
types::TextEventHash<types::TextEventKey>>
|
||||
observedMap_;
|
||||
std::unordered_map<types::TextEventKey,
|
||||
awips::ThreatCategory,
|
||||
types::TextEventHash<types::TextEventKey>>
|
||||
threatCategoryMap_;
|
||||
std::unordered_map<types::TextEventKey,
|
||||
bool,
|
||||
types::TextEventHash<types::TextEventKey>>
|
||||
tornadoPossibleMap_;
|
||||
std::unordered_map<types::TextEventKey,
|
||||
common::Coordinate,
|
||||
types::TextEventHash<types::TextEventKey>>
|
||||
|
|
@ -125,6 +141,29 @@ QVariant AlertModel::data(const QModelIndex& index, int role) const
|
|||
return QString::fromStdString(
|
||||
awips::GetSignificanceText(textEventKey.significance_));
|
||||
|
||||
case static_cast<int>(Column::Tornado):
|
||||
if (textEventKey.phenomenon_ == awips::Phenomenon::Tornado &&
|
||||
p->GetObserved(textEventKey))
|
||||
{
|
||||
return tr("Observed");
|
||||
}
|
||||
if (p->GetTornadoPossible(textEventKey))
|
||||
{
|
||||
return tr("Possible");
|
||||
}
|
||||
break;
|
||||
|
||||
case static_cast<int>(Column::ThreatCategory):
|
||||
if (role == Qt::DisplayRole)
|
||||
{
|
||||
return QString::fromStdString(awips::GetThreatCategoryName(
|
||||
p->GetThreatCategory(textEventKey)));
|
||||
}
|
||||
else
|
||||
{
|
||||
return static_cast<int>(p->GetThreatCategory(textEventKey));
|
||||
}
|
||||
|
||||
case static_cast<int>(Column::State):
|
||||
return QString::fromStdString(AlertModelImpl::GetState(textEventKey));
|
||||
|
||||
|
|
@ -204,6 +243,12 @@ AlertModel::headerData(int section, Qt::Orientation orientation, int role) const
|
|||
case static_cast<int>(Column::Significance):
|
||||
return tr("Significance");
|
||||
|
||||
case static_cast<int>(Column::ThreatCategory):
|
||||
return tr("Category");
|
||||
|
||||
case static_cast<int>(Column::Tornado):
|
||||
return tr("Tornado");
|
||||
|
||||
case static_cast<int>(Column::State):
|
||||
return tr("State");
|
||||
|
||||
|
|
@ -240,6 +285,14 @@ AlertModel::headerData(int section, Qt::Orientation orientation, int role) const
|
|||
contentsSize = fontMetrics.size(0, QString(10, 'W'));
|
||||
break;
|
||||
|
||||
case static_cast<int>(Column::ThreatCategory):
|
||||
contentsSize = fontMetrics.size(0, QString(6, 'W'));
|
||||
break;
|
||||
|
||||
case static_cast<int>(Column::Tornado):
|
||||
contentsSize = fontMetrics.size(0, QString(5, 'W'));
|
||||
break;
|
||||
|
||||
case static_cast<int>(Column::State):
|
||||
contentsSize = fontMetrics.size(0, "WW, WW");
|
||||
break;
|
||||
|
|
@ -285,6 +338,12 @@ void AlertModel::HandleAlert(const types::TextEventKey& alertKey,
|
|||
std::shared_ptr<const awips::Segment> alertSegment =
|
||||
alertMessages[messageIndex]->segments().back();
|
||||
|
||||
p->observedMap_.insert_or_assign(alertKey, alertSegment->observed_);
|
||||
p->threatCategoryMap_.insert_or_assign(alertKey,
|
||||
alertSegment->threatCategory_);
|
||||
p->tornadoPossibleMap_.insert_or_assign(alertKey,
|
||||
alertSegment->tornadoPossible_);
|
||||
|
||||
if (alertSegment->codedLocation_.has_value())
|
||||
{
|
||||
// Update centroid and distance
|
||||
|
|
@ -365,6 +424,46 @@ AlertModelImpl::AlertModelImpl() :
|
|||
{
|
||||
}
|
||||
|
||||
bool AlertModelImpl::GetObserved(const types::TextEventKey& key)
|
||||
{
|
||||
bool observed = false;
|
||||
|
||||
auto it = observedMap_.find(key);
|
||||
if (it != observedMap_.cend())
|
||||
{
|
||||
observed = it->second;
|
||||
}
|
||||
|
||||
return observed;
|
||||
}
|
||||
|
||||
awips::ThreatCategory
|
||||
AlertModelImpl::GetThreatCategory(const types::TextEventKey& key)
|
||||
{
|
||||
awips::ThreatCategory threatCategory = awips::ThreatCategory::Base;
|
||||
|
||||
auto it = threatCategoryMap_.find(key);
|
||||
if (it != threatCategoryMap_.cend())
|
||||
{
|
||||
threatCategory = it->second;
|
||||
}
|
||||
|
||||
return threatCategory;
|
||||
}
|
||||
|
||||
bool AlertModelImpl::GetTornadoPossible(const types::TextEventKey& key)
|
||||
{
|
||||
bool tornadoPossible = false;
|
||||
|
||||
auto it = tornadoPossibleMap_.find(key);
|
||||
if (it != tornadoPossibleMap_.cend())
|
||||
{
|
||||
tornadoPossible = it->second;
|
||||
}
|
||||
|
||||
return tornadoPossible;
|
||||
}
|
||||
|
||||
std::string AlertModelImpl::GetCounties(const types::TextEventKey& key)
|
||||
{
|
||||
auto messageList = manager::TextEventManager::Instance()->message_list(key);
|
||||
|
|
|
|||
|
|
@ -21,15 +21,17 @@ class AlertModel : public QAbstractTableModel
|
|||
public:
|
||||
enum class Column : int
|
||||
{
|
||||
Etn = 0,
|
||||
OfficeId = 1,
|
||||
Phenomenon = 2,
|
||||
Significance = 3,
|
||||
State = 4,
|
||||
Counties = 5,
|
||||
StartTime = 6,
|
||||
EndTime = 7,
|
||||
Distance = 8
|
||||
Etn = 0,
|
||||
OfficeId = 1,
|
||||
Phenomenon = 2,
|
||||
Significance = 3,
|
||||
ThreatCategory = 4,
|
||||
Tornado = 5,
|
||||
State = 6,
|
||||
Counties = 7,
|
||||
StartTime = 8,
|
||||
EndTime = 9,
|
||||
Distance = 10
|
||||
};
|
||||
|
||||
explicit AlertModel(QObject* parent = nullptr);
|
||||
|
|
|
|||
24
wxdata/include/scwx/awips/impact_based_warnings.hpp
Normal file
24
wxdata/include/scwx/awips/impact_based_warnings.hpp
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace scwx
|
||||
{
|
||||
namespace awips
|
||||
{
|
||||
|
||||
enum class ThreatCategory : int
|
||||
{
|
||||
Base = 0,
|
||||
Significant = 1,
|
||||
Considerable = 2,
|
||||
Destructive = 3,
|
||||
Catastrophic = 4,
|
||||
Unknown
|
||||
};
|
||||
|
||||
ThreatCategory GetThreatCategory(const std::string& name);
|
||||
const std::string& GetThreatCategoryName(ThreatCategory threatCategory);
|
||||
|
||||
} // namespace awips
|
||||
} // namespace scwx
|
||||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
#include <scwx/awips/coded_location.hpp>
|
||||
#include <scwx/awips/coded_time_motion_location.hpp>
|
||||
#include <scwx/awips/impact_based_warnings.hpp>
|
||||
#include <scwx/awips/message.hpp>
|
||||
#include <scwx/awips/pvtec.hpp>
|
||||
#include <scwx/awips/ugc.hpp>
|
||||
|
|
@ -56,15 +57,16 @@ struct SegmentHeader
|
|||
|
||||
struct Segment
|
||||
{
|
||||
std::optional<SegmentHeader> header_;
|
||||
std::vector<std::string> productContent_;
|
||||
std::optional<CodedLocation> codedLocation_;
|
||||
std::optional<CodedTimeMotionLocation> codedMotion_;
|
||||
std::optional<SegmentHeader> header_ {};
|
||||
std::vector<std::string> productContent_ {};
|
||||
std::optional<CodedLocation> codedLocation_ {};
|
||||
std::optional<CodedTimeMotionLocation> codedMotion_ {};
|
||||
|
||||
Segment() :
|
||||
header_ {}, productContent_ {}, codedLocation_ {}, codedMotion_ {}
|
||||
{
|
||||
}
|
||||
bool observed_ {false};
|
||||
ThreatCategory threatCategory_ {ThreatCategory::Base};
|
||||
bool tornadoPossible_ {false};
|
||||
|
||||
Segment() = default;
|
||||
|
||||
Segment(const Segment&) = delete;
|
||||
Segment& operator=(const Segment&) = delete;
|
||||
|
|
|
|||
31
wxdata/source/scwx/awips/impact_based_warnings.cpp
Normal file
31
wxdata/source/scwx/awips/impact_based_warnings.cpp
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
#include <scwx/awips/impact_based_warnings.hpp>
|
||||
#include <scwx/util/enum.hpp>
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
|
||||
namespace scwx
|
||||
{
|
||||
namespace awips
|
||||
{
|
||||
|
||||
static const std::string logPrefix_ = "scwx::awips::impact_based_warnings";
|
||||
|
||||
static const std::unordered_map<ThreatCategory, std::string>
|
||||
threatCategoryName_ {{ThreatCategory::Base, "Base"},
|
||||
{ThreatCategory::Significant, "Significant"},
|
||||
{ThreatCategory::Considerable, "Considerable"},
|
||||
{ThreatCategory::Destructive, "Destructive"},
|
||||
{ThreatCategory::Catastrophic, "Catastrophic"},
|
||||
{ThreatCategory::Unknown, "?"}};
|
||||
|
||||
SCWX_GET_ENUM(ThreatCategory, GetThreatCategory, threatCategoryName_)
|
||||
|
||||
const std::string& GetThreatCategoryName(ThreatCategory threatCategory)
|
||||
{
|
||||
return threatCategoryName_.at(threatCategory);
|
||||
}
|
||||
|
||||
} // namespace awips
|
||||
} // namespace scwx
|
||||
|
|
@ -3,6 +3,7 @@
|
|||
#include <scwx/util/logger.hpp>
|
||||
#include <scwx/util/streams.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <istream>
|
||||
#include <string>
|
||||
|
||||
|
|
@ -304,6 +305,14 @@ void ParseCodedInformation(std::shared_ptr<Segment> segment,
|
|||
{
|
||||
typedef std::vector<std::string>::const_iterator StringIterator;
|
||||
|
||||
static constexpr std::size_t kThreatCategoryTagCount = 4;
|
||||
static const std::array<std::string, kThreatCategoryTagCount>
|
||||
kThreatCategoryTags {"FLASH FLOOD DAMAGE THREAT...",
|
||||
"SNOW SQUALL IMPACT...",
|
||||
"THUNDERSTORM DAMAGE THREAT...",
|
||||
"TORNADO DAMAGE THREAT..."};
|
||||
std::array<std::string, kThreatCategoryTagCount>::const_iterator threatTagIt;
|
||||
|
||||
std::vector<std::string>& productContent = segment->productContent_;
|
||||
|
||||
StringIterator codedLocationBegin = productContent.cend();
|
||||
|
|
@ -325,8 +334,8 @@ void ParseCodedInformation(std::shared_ptr<Segment> segment,
|
|||
codedLocationEnd = it;
|
||||
}
|
||||
|
||||
if (codedMotionBegin == productContent.cend() &&
|
||||
it->starts_with("TIME...MOT...LOC"))
|
||||
else if (codedMotionBegin == productContent.cend() &&
|
||||
it->starts_with("TIME...MOT...LOC"))
|
||||
{
|
||||
codedMotionBegin = it;
|
||||
}
|
||||
|
|
@ -338,6 +347,37 @@ void ParseCodedInformation(std::shared_ptr<Segment> segment,
|
|||
{
|
||||
codedMotionEnd = it;
|
||||
}
|
||||
|
||||
else if (!segment->observed_ &&
|
||||
it->find("...OBSERVED") != std::string::npos)
|
||||
{
|
||||
segment->observed_ = true;
|
||||
}
|
||||
|
||||
else if (!segment->tornadoPossible_ && *it == "TORNADO...POSSIBLE")
|
||||
{
|
||||
segment->tornadoPossible_ = true;
|
||||
}
|
||||
|
||||
else if (segment->threatCategory_ == ThreatCategory::Base &&
|
||||
(threatTagIt = std::find_if(kThreatCategoryTags.cbegin(),
|
||||
kThreatCategoryTags.cend(),
|
||||
[&it](const std::string& tag) {
|
||||
return it->starts_with(tag);
|
||||
})) != kThreatCategoryTags.cend() &&
|
||||
it->length() > threatTagIt->length())
|
||||
{
|
||||
const std::string threatCategoryName =
|
||||
it->substr(threatTagIt->length());
|
||||
|
||||
ThreatCategory threatCategory = GetThreatCategory(threatCategoryName);
|
||||
if (threatCategory == ThreatCategory::Unknown)
|
||||
{
|
||||
threatCategory = ThreatCategory::Base;
|
||||
}
|
||||
|
||||
segment->threatCategory_ = threatCategory;
|
||||
}
|
||||
}
|
||||
|
||||
if (codedLocationBegin != productContent.cend())
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ endif()
|
|||
|
||||
set(HDR_AWIPS include/scwx/awips/coded_location.hpp
|
||||
include/scwx/awips/coded_time_motion_location.hpp
|
||||
include/scwx/awips/impact_based_warnings.hpp
|
||||
include/scwx/awips/message.hpp
|
||||
include/scwx/awips/phenomenon.hpp
|
||||
include/scwx/awips/pvtec.hpp
|
||||
|
|
@ -24,6 +25,7 @@ set(HDR_AWIPS include/scwx/awips/coded_location.hpp
|
|||
include/scwx/awips/wmo_header.hpp)
|
||||
set(SRC_AWIPS source/scwx/awips/coded_location.cpp
|
||||
source/scwx/awips/coded_time_motion_location.cpp
|
||||
source/scwx/awips/impact_based_warnings.cpp
|
||||
source/scwx/awips/message.cpp
|
||||
source/scwx/awips/phenomenon.cpp
|
||||
source/scwx/awips/pvtec.cpp
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue