mirror of
				https://github.com/ciphervance/supercell-wx.git
				synced 2025-10-30 18:00:06 +00:00 
			
		
		
		
	P-VTEC parsing
This commit is contained in:
		
							parent
							
								
									e5c40b9eb5
								
							
						
					
					
						commit
						be1d7323bd
					
				
					 10 changed files with 835 additions and 5 deletions
				
			
		
							
								
								
									
										168
									
								
								wxdata/source/scwx/awips/phenomenon.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										168
									
								
								wxdata/source/scwx/awips/phenomenon.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,168 @@ | |||
| #include <scwx/awips/phenomenon.hpp> | ||||
| 
 | ||||
| #include <boost/assign.hpp> | ||||
| #include <boost/bimap.hpp> | ||||
| #include <boost/bimap/unordered_set_of.hpp> | ||||
| #include <boost/log/trivial.hpp> | ||||
| 
 | ||||
| namespace scwx | ||||
| { | ||||
| namespace awips | ||||
| { | ||||
| 
 | ||||
| static const std::string logPrefix_ = "[scwx::awips::phenomenon] "; | ||||
| 
 | ||||
| typedef boost::bimap<boost::bimaps::unordered_set_of<Phenomenon>, | ||||
|                      boost::bimaps::unordered_set_of<std::string>> | ||||
|    PhenomenonCodesBimap; | ||||
| 
 | ||||
| static const PhenomenonCodesBimap phenomenonCodes_ = | ||||
|    boost::assign::list_of<PhenomenonCodesBimap::relation> //
 | ||||
|    (Phenomenon::AshfallLand, "AF")                        //
 | ||||
|    (Phenomenon::AirStagnation, "AS")                      //
 | ||||
|    (Phenomenon::BeachHazard, "BH")                        //
 | ||||
|    (Phenomenon::BriskWind, "BW")                          //
 | ||||
|    (Phenomenon::Blizzard, "BZ")                           //
 | ||||
|    (Phenomenon::CoastalFlood, "CF")                       //
 | ||||
|    (Phenomenon::DebrisFlow, "DF")                         //
 | ||||
|    (Phenomenon::DustStorm, "DS")                          //
 | ||||
|    (Phenomenon::BlowingDust, "DU")                        //
 | ||||
|    (Phenomenon::ExtremeCold, "EC")                        //
 | ||||
|    (Phenomenon::ExcessiveHeat, "EH")                      //
 | ||||
|    (Phenomenon::ExtremeWind, "EW")                        //
 | ||||
|    (Phenomenon::Flood, "FA")                              //
 | ||||
|    (Phenomenon::FlashFlood, "FF")                         //
 | ||||
|    (Phenomenon::DenseFogLand, "FG")                       //
 | ||||
|    (Phenomenon::FloodForecastPoints, "FL")                //
 | ||||
|    (Phenomenon::Frost, "FR")                              //
 | ||||
|    (Phenomenon::FireWeather, "FW")                        //
 | ||||
|    (Phenomenon::Freeze, "FZ")                             //
 | ||||
|    (Phenomenon::Gale, "GL")                               //
 | ||||
|    (Phenomenon::HurricaneForceWind, "HF")                 //
 | ||||
|    (Phenomenon::Heat, "HT")                               //
 | ||||
|    (Phenomenon::Hurricane, "HU")                          //
 | ||||
|    (Phenomenon::HighWind, "HW")                           //
 | ||||
|    (Phenomenon::Hydrologic, "HY")                         //
 | ||||
|    (Phenomenon::HardFreeze, "HZ")                         //
 | ||||
|    (Phenomenon::IceStorm, "IS")                           //
 | ||||
|    (Phenomenon::LakeEffectSnow, "LE")                     //
 | ||||
|    (Phenomenon::LowWater, "LO")                           //
 | ||||
|    (Phenomenon::LakeshoreFlood, "LS")                     //
 | ||||
|    (Phenomenon::LakeWind, "LW")                           //
 | ||||
|    (Phenomenon::Marine, "MA")                             //
 | ||||
|    (Phenomenon::DenseFogMarine, "MF")                     //
 | ||||
|    (Phenomenon::AshfallMarine, "MH")                      //
 | ||||
|    (Phenomenon::DenseSmokeMarine, "MS")                   //
 | ||||
|    (Phenomenon::RipCurrentRisk, "RP")                     //
 | ||||
|    (Phenomenon::SmallCraft, "SC")                         //
 | ||||
|    (Phenomenon::HazardousSeas, "SE")                      //
 | ||||
|    (Phenomenon::DenseSmokeLand, "SM")                     //
 | ||||
|    (Phenomenon::Storm, "SR")                              //
 | ||||
|    (Phenomenon::StormSurge, "SS")                         //
 | ||||
|    (Phenomenon::SnowSquall, "SQ")                         //
 | ||||
|    (Phenomenon::HighSurf, "SU")                           //
 | ||||
|    (Phenomenon::SevereThunderstorm, "SV")                 //
 | ||||
|    (Phenomenon::Tornado, "TO")                            //
 | ||||
|    (Phenomenon::TropicalStorm, "TR")                      //
 | ||||
|    (Phenomenon::Tsunami, "TS")                            //
 | ||||
|    (Phenomenon::Typhoon, "TY")                            //
 | ||||
|    (Phenomenon::HeavyFreezingSpray, "UP")                 //
 | ||||
|    (Phenomenon::WindChill, "WC")                          //
 | ||||
|    (Phenomenon::Wind, "WI")                               //
 | ||||
|    (Phenomenon::WinterStorm, "WS")                        //
 | ||||
|    (Phenomenon::WinterWeather, "WW")                      //
 | ||||
|    (Phenomenon::FreezingFog, "ZF")                        //
 | ||||
|    (Phenomenon::FreezingRain, "ZR")                       //
 | ||||
|    (Phenomenon::FreezingSpray, "ZY")                      //
 | ||||
|    (Phenomenon::Unknown, "??"); | ||||
| 
 | ||||
| static const std::unordered_map<Phenomenon, std::string> phenomenonText_ { | ||||
|    {Phenomenon::AshfallLand, "Ashfall (land)"},              //
 | ||||
|    {Phenomenon::AirStagnation, "Air Stagnation"},            //
 | ||||
|    {Phenomenon::BeachHazard, "Beach Hazard"},                //
 | ||||
|    {Phenomenon::BriskWind, "Brisk Wind"},                    //
 | ||||
|    {Phenomenon::Blizzard, "Blizzard"},                       //
 | ||||
|    {Phenomenon::CoastalFlood, "Coastal Flood"},              //
 | ||||
|    {Phenomenon::DebrisFlow, "Debris Flow"},                  //
 | ||||
|    {Phenomenon::DustStorm, "Dust Storm"},                    //
 | ||||
|    {Phenomenon::BlowingDust, "Blowing Dust"},                //
 | ||||
|    {Phenomenon::ExtremeCold, "Extreme Cold"},                //
 | ||||
|    {Phenomenon::ExcessiveHeat, "Excessive Heat"},            //
 | ||||
|    {Phenomenon::ExtremeWind, "Extreme Wind"},                //
 | ||||
|    {Phenomenon::Flood, "Flood"},                             //
 | ||||
|    {Phenomenon::FlashFlood, "Flash Flood"},                  //
 | ||||
|    {Phenomenon::DenseFogLand, "Dense Fog (land)"},           //
 | ||||
|    {Phenomenon::Flood, "Flood (Forecast Points)"},           //
 | ||||
|    {Phenomenon::Frost, "Frost"},                             //
 | ||||
|    {Phenomenon::FireWeather, "Fire Weather"},                //
 | ||||
|    {Phenomenon::Freeze, "Freeze"},                           //
 | ||||
|    {Phenomenon::Gale, "Gale"},                               //
 | ||||
|    {Phenomenon::HurricaneForceWind, "Hurricane Force Wind"}, //
 | ||||
|    {Phenomenon::Heat, "Heat"},                               //
 | ||||
|    {Phenomenon::Hurricane, "Hurricane"},                     //
 | ||||
|    {Phenomenon::HighWind, "High Wind"},                      //
 | ||||
|    {Phenomenon::Hydrologic, "Hydrologic"},                   //
 | ||||
|    {Phenomenon::HardFreeze, "Hard Freeze"},                  //
 | ||||
|    {Phenomenon::IceStorm, "Ice Storm"},                      //
 | ||||
|    {Phenomenon::LakeEffectSnow, "Lake Effect Snow"},         //
 | ||||
|    {Phenomenon::LowWater, "Low Water"},                      //
 | ||||
|    {Phenomenon::LakeshoreFlood, "Lakeshore Flood"},          //
 | ||||
|    {Phenomenon::LakeWind, "Lake Wind"},                      //
 | ||||
|    {Phenomenon::Marine, "Marine"},                           //
 | ||||
|    {Phenomenon::DenseFogMarine, "Dense Fog (marine)"},       //
 | ||||
|    {Phenomenon::AshfallMarine, "Ashfall (marine)"},          //
 | ||||
|    {Phenomenon::DenseSmokeMarine, "Dense Smoke (marine)"},   //
 | ||||
|    {Phenomenon::RipCurrentRisk, "Rip Current Risk"},         //
 | ||||
|    {Phenomenon::SmallCraft, "Small Craft"},                  //
 | ||||
|    {Phenomenon::HazardousSeas, "Hazardous Seas"},            //
 | ||||
|    {Phenomenon::DenseSmokeLand, "Dense Smoke (land)"},       //
 | ||||
|    {Phenomenon::Storm, "Storm"},                             //
 | ||||
|    {Phenomenon::StormSurge, "Storm Surge"},                  //
 | ||||
|    {Phenomenon::SnowSquall, "Snow Squall"},                  //
 | ||||
|    {Phenomenon::HighSurf, "High Surf"},                      //
 | ||||
|    {Phenomenon::SevereThunderstorm, "Severe Thunderstorm"},  //
 | ||||
|    {Phenomenon::Tornado, "Tornado"},                         //
 | ||||
|    {Phenomenon::TropicalStorm, "Tropical Storm"},            //
 | ||||
|    {Phenomenon::Tsunami, "Tsunami"},                         //
 | ||||
|    {Phenomenon::Typhoon, "Typhoon"},                         //
 | ||||
|    {Phenomenon::HeavyFreezingSpray, "Heavy Freezing Spray"}, //
 | ||||
|    {Phenomenon::WindChill, "Wind Chill"},                    //
 | ||||
|    {Phenomenon::Wind, "Wind"},                               //
 | ||||
|    {Phenomenon::WinterStorm, "Winter Storm"},                //
 | ||||
|    {Phenomenon::WinterWeather, "Winter Weather"},            //
 | ||||
|    {Phenomenon::FreezingFog, "Freezing Fog"},                //
 | ||||
|    {Phenomenon::FreezingRain, "Freezing Rain"},              //
 | ||||
|    {Phenomenon::FreezingSpray, "Freezing Spray"},            //
 | ||||
|    {Phenomenon::Unknown, "Unknown"}}; | ||||
| 
 | ||||
| Phenomenon GetPhenomenon(const std::string& code) | ||||
| { | ||||
|    Phenomenon phenomenon; | ||||
| 
 | ||||
|    if (phenomenonCodes_.right.find(code) != phenomenonCodes_.right.end()) | ||||
|    { | ||||
|       phenomenon = phenomenonCodes_.right.at(code); | ||||
|    } | ||||
|    else | ||||
|    { | ||||
|       phenomenon = Phenomenon::Unknown; | ||||
| 
 | ||||
|       BOOST_LOG_TRIVIAL(debug) | ||||
|          << logPrefix_ << "Unrecognized code: \"" << code << "\""; | ||||
|    } | ||||
| 
 | ||||
|    return phenomenon; | ||||
| } | ||||
| 
 | ||||
| std::string GetPhenomenonCode(Phenomenon phenomenon) | ||||
| { | ||||
|    return phenomenonCodes_.left.at(phenomenon); | ||||
| } | ||||
| 
 | ||||
| std::string GetPhenomenonText(Phenomenon phenomenon) | ||||
| { | ||||
|    return phenomenonText_.at(phenomenon); | ||||
| } | ||||
| 
 | ||||
| } // namespace awips
 | ||||
| } // namespace scwx
 | ||||
							
								
								
									
										275
									
								
								wxdata/source/scwx/awips/pvtec.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										275
									
								
								wxdata/source/scwx/awips/pvtec.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,275 @@ | |||
| // Enable chrono formatters
 | ||||
| #ifndef __cpp_lib_format | ||||
| #   define __cpp_lib_format 202110L | ||||
| #endif | ||||
| 
 | ||||
| #include <scwx/awips/pvtec.hpp> | ||||
| 
 | ||||
| #include <chrono> | ||||
| 
 | ||||
| #include <boost/assign.hpp> | ||||
| #include <boost/bimap.hpp> | ||||
| #include <boost/bimap/unordered_set_of.hpp> | ||||
| #include <boost/log/trivial.hpp> | ||||
| 
 | ||||
| namespace scwx | ||||
| { | ||||
| namespace awips | ||||
| { | ||||
| 
 | ||||
| static const std::string logPrefix_ = "[scwx::awips::pvtec] "; | ||||
| 
 | ||||
| typedef boost::bimap<boost::bimaps::unordered_set_of<PVtec::ProductType>, | ||||
|                      boost::bimaps::unordered_set_of<std::string>> | ||||
|    ProductTypeCodesBimap; | ||||
| 
 | ||||
| static const ProductTypeCodesBimap productTypeCodes_ = | ||||
|    boost::assign::list_of<ProductTypeCodesBimap::relation>    //
 | ||||
|    (PVtec::ProductType::Operational, "O")                     //
 | ||||
|    (PVtec::ProductType::Test, "T")                            //
 | ||||
|    (PVtec::ProductType::Experimental, "E")                    //
 | ||||
|    (PVtec::ProductType::OperationalWithExperimentalVtec, "X") //
 | ||||
|    (PVtec::ProductType::Unknown, "??"); | ||||
| 
 | ||||
| typedef boost::bimap<boost::bimaps::unordered_set_of<PVtec::Action>, | ||||
|                      boost::bimaps::unordered_set_of<std::string>> | ||||
|    ActionCodesBimap; | ||||
| 
 | ||||
| static const ActionCodesBimap actionCodes_ = | ||||
|    boost::assign::list_of<ActionCodesBimap::relation> //
 | ||||
|    (PVtec::Action::New, "NEW")                        //
 | ||||
|    (PVtec::Action::Continued, "CON")                  //
 | ||||
|    (PVtec::Action::ExtendedInArea, "EXA")             //
 | ||||
|    (PVtec::Action::ExtendedInTime, "EXT")             //
 | ||||
|    (PVtec::Action::ExtendedInAreaAndTime, "EXB")      //
 | ||||
|    (PVtec::Action::Upgraded, "UPG")                   //
 | ||||
|    (PVtec::Action::Canceled, "CAN")                   //
 | ||||
|    (PVtec::Action::Expired, "EXP")                    //
 | ||||
|    (PVtec::Action::Routine, "ROU")                    //
 | ||||
|    (PVtec::Action::Correction, "COR")                 //
 | ||||
|    (PVtec::Action::Unknown, "???"); | ||||
| 
 | ||||
| class PVtecImpl | ||||
| { | ||||
| public: | ||||
|    explicit PVtecImpl() : | ||||
|        pVtecString_ {}, | ||||
|        fixedIdentifier_ {PVtec::ProductType::Unknown}, | ||||
|        action_ {PVtec::Action::Unknown}, | ||||
|        officeId_ {"????"}, | ||||
|        phenomenon_ {Phenomenon::Unknown}, | ||||
|        significance_ {Significance::Unknown}, | ||||
|        eventTrackingNumber_ {-1}, | ||||
|        eventBegin_ {}, | ||||
|        eventEnd_ {}, | ||||
|        valid_ {false} | ||||
|    { | ||||
|    } | ||||
| 
 | ||||
|    ~PVtecImpl() {} | ||||
| 
 | ||||
|    std::string pVtecString_; | ||||
| 
 | ||||
|    PVtec::ProductType fixedIdentifier_; | ||||
|    PVtec::Action      action_; | ||||
|    std::string        officeId_; | ||||
|    Phenomenon         phenomenon_; | ||||
|    Significance       significance_; | ||||
|    int16_t            eventTrackingNumber_; | ||||
| 
 | ||||
|    std::chrono::system_clock::time_point eventBegin_; | ||||
|    std::chrono::system_clock::time_point eventEnd_; | ||||
| 
 | ||||
|    bool valid_; | ||||
| }; | ||||
| 
 | ||||
| PVtec::PVtec() : p(std::make_unique<PVtecImpl>()) {} | ||||
| PVtec::~PVtec() = default; | ||||
| 
 | ||||
| PVtec::PVtec(PVtec&&) noexcept = default; | ||||
| PVtec& PVtec::operator=(PVtec&&) noexcept = default; | ||||
| 
 | ||||
| PVtec::ProductType PVtec::fixed_identifier() const | ||||
| { | ||||
|    return p->fixedIdentifier_; | ||||
| } | ||||
| 
 | ||||
| PVtec::Action PVtec::action() const | ||||
| { | ||||
|    return p->action_; | ||||
| } | ||||
| 
 | ||||
| std::string PVtec::office_id() const | ||||
| { | ||||
|    return p->officeId_; | ||||
| } | ||||
| 
 | ||||
| Phenomenon PVtec::phenomenon() const | ||||
| { | ||||
|    return p->phenomenon_; | ||||
| } | ||||
| 
 | ||||
| Significance PVtec::significance() const | ||||
| { | ||||
|    return p->significance_; | ||||
| } | ||||
| 
 | ||||
| int16_t PVtec::event_tracking_number() const | ||||
| { | ||||
|    return p->eventTrackingNumber_; | ||||
| } | ||||
| 
 | ||||
| std::chrono::system_clock::time_point PVtec::event_begin() const | ||||
| { | ||||
|    return p->eventBegin_; | ||||
| } | ||||
| 
 | ||||
| std::chrono::system_clock::time_point PVtec::event_end() const | ||||
| { | ||||
|    return p->eventEnd_; | ||||
| } | ||||
| 
 | ||||
| bool PVtec::Parse(const std::string& s) | ||||
| { | ||||
|    using namespace std::chrono; | ||||
| 
 | ||||
|    // P-VTEC takes the form:
 | ||||
|    // /k.aaa.cccc.pp.s.####.yymmddThhnnZ-yymmddThhnnZ/
 | ||||
|    // 012345678901234567890123456789012345678901234567
 | ||||
|    static constexpr size_t pVtecLength_             = 48u; | ||||
|    static constexpr size_t pVtecOffsetStart_        = 0u; | ||||
|    static constexpr size_t pVtecOffsetIdentifier_   = 1u; | ||||
|    static constexpr size_t pVtecOffsetAction_       = 3u; | ||||
|    static constexpr size_t pVtecOffsetOfficeId_     = 7u; | ||||
|    static constexpr size_t pVtecOffsetPhenomenon_   = 12u; | ||||
|    static constexpr size_t pVtecOffsetSignificance_ = 15u; | ||||
|    static constexpr size_t pVtecOffsetEventNumber_  = 17u; | ||||
|    static constexpr size_t pVtecOffsetEventBegin_   = 22u; | ||||
|    static constexpr size_t pVtecOffsetEventEnd_     = 35u; | ||||
|    static constexpr size_t pVtecOffsetEnd_          = 47u; | ||||
| 
 | ||||
|    bool dataValid = (s.length() >= pVtecLength_ &&     //
 | ||||
|                      s.at(pVtecOffsetStart_) == '/' && //
 | ||||
|                      s.at(pVtecOffsetEnd_) == '/'); | ||||
| 
 | ||||
|    if (dataValid) | ||||
|    { | ||||
|       p->pVtecString_ = s.substr(0, pVtecLength_); | ||||
| 
 | ||||
|       p->fixedIdentifier_ = GetProductType(s.substr(pVtecOffsetIdentifier_, 1)); | ||||
|       p->action_          = GetAction(s.substr(pVtecOffsetAction_, 3)); | ||||
|       p->officeId_        = s.substr(pVtecOffsetOfficeId_, 4); | ||||
|       p->phenomenon_      = GetPhenomenon(s.substr(pVtecOffsetPhenomenon_, 2)); | ||||
|       p->significance_ = GetSignificance(s.substr(pVtecOffsetSignificance_, 1)); | ||||
| 
 | ||||
|       std::string eventNumberString = s.substr(pVtecOffsetEventNumber_, 4); | ||||
| 
 | ||||
|       try | ||||
|       { | ||||
|          p->eventTrackingNumber_ = | ||||
|             static_cast<int16_t>(std::stoi(eventNumberString)); | ||||
|       } | ||||
|       catch (const std::exception& ex) | ||||
|       { | ||||
|          BOOST_LOG_TRIVIAL(warning) | ||||
|             << logPrefix_ << "Error parsing event tracking number: \"" | ||||
|             << eventNumberString << "\" (" << ex.what() << ")"; | ||||
| 
 | ||||
|          p->eventTrackingNumber_ = -1; | ||||
|       } | ||||
| 
 | ||||
|       static const std::string dateTimeFormat {"%y%m%dT%H%MZ"}; | ||||
| 
 | ||||
|       std::string sEventBegin = s.substr(pVtecOffsetEventBegin_, 12); | ||||
|       std::string sEventEnd   = s.substr(pVtecOffsetEventEnd_, 12); | ||||
| 
 | ||||
|       std::istringstream ssEventBegin {sEventBegin}; | ||||
|       std::istringstream ssEventEnd {sEventEnd}; | ||||
| 
 | ||||
|       sys_time<minutes> eventBegin; | ||||
|       sys_time<minutes> eventEnd; | ||||
| 
 | ||||
|       ssEventBegin >> parse(dateTimeFormat, eventBegin); | ||||
|       ssEventEnd >> parse(dateTimeFormat, eventEnd); | ||||
| 
 | ||||
|       if (!ssEventBegin.fail()) | ||||
|       { | ||||
|          p->eventBegin_ = eventBegin; | ||||
|       } | ||||
|       else | ||||
|       { | ||||
|          // Time parsing expected to fail if time is "000000T0000Z"
 | ||||
|          p->eventBegin_ = {}; | ||||
|       } | ||||
| 
 | ||||
|       if (!ssEventEnd.fail()) | ||||
|       { | ||||
|          p->eventEnd_ = eventEnd; | ||||
|       } | ||||
|       else | ||||
|       { | ||||
|          // Time parsing expected to fail if time is "000000T0000Z"
 | ||||
|          p->eventEnd_ = {}; | ||||
|       } | ||||
|    } | ||||
|    else | ||||
|    { | ||||
|       BOOST_LOG_TRIVIAL(warning) | ||||
|          << logPrefix_ << "Invalid P-VTEC: \"" << s << "\""; | ||||
|    } | ||||
| 
 | ||||
|    p->valid_ = dataValid; | ||||
| 
 | ||||
|    return dataValid; | ||||
| } | ||||
| 
 | ||||
| PVtec::ProductType PVtec::GetProductType(const std::string& code) | ||||
| { | ||||
|    ProductType productType; | ||||
| 
 | ||||
|    if (productTypeCodes_.right.find(code) != productTypeCodes_.right.end()) | ||||
|    { | ||||
|       productType = productTypeCodes_.right.at(code); | ||||
|    } | ||||
|    else | ||||
|    { | ||||
|       productType = ProductType::Unknown; | ||||
| 
 | ||||
|       BOOST_LOG_TRIVIAL(debug) | ||||
|          << logPrefix_ << "Unrecognized product code: \"" << code << "\""; | ||||
|    } | ||||
| 
 | ||||
|    return productType; | ||||
| } | ||||
| 
 | ||||
| std::string PVtec::GetProductTypeCode(PVtec::ProductType productType) | ||||
| { | ||||
|    return productTypeCodes_.left.at(productType); | ||||
| } | ||||
| 
 | ||||
| PVtec::Action PVtec::GetAction(const std::string& code) | ||||
| { | ||||
|    Action action; | ||||
| 
 | ||||
|    if (actionCodes_.right.find(code) != actionCodes_.right.end()) | ||||
|    { | ||||
|       action = actionCodes_.right.at(code); | ||||
|    } | ||||
|    else | ||||
|    { | ||||
|       action = Action::Unknown; | ||||
| 
 | ||||
|       BOOST_LOG_TRIVIAL(debug) | ||||
|          << logPrefix_ << "Unrecognized action code: \"" << code << "\""; | ||||
|    } | ||||
| 
 | ||||
|    return action; | ||||
| } | ||||
| 
 | ||||
| std::string PVtec::GetActionCode(PVtec::Action action) | ||||
| { | ||||
|    return actionCodes_.left.at(action); | ||||
| } | ||||
| 
 | ||||
| } // namespace awips
 | ||||
| } // namespace scwx
 | ||||
							
								
								
									
										70
									
								
								wxdata/source/scwx/awips/significance.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								wxdata/source/scwx/awips/significance.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,70 @@ | |||
| #include <scwx/awips/significance.hpp> | ||||
| 
 | ||||
| #include <boost/assign.hpp> | ||||
| #include <boost/bimap.hpp> | ||||
| #include <boost/bimap/unordered_set_of.hpp> | ||||
| #include <boost/log/trivial.hpp> | ||||
| 
 | ||||
| namespace scwx | ||||
| { | ||||
| namespace awips | ||||
| { | ||||
| 
 | ||||
| static const std::string logPrefix_ = "[scwx::awips::significance] "; | ||||
| 
 | ||||
| typedef boost::bimap<boost::bimaps::unordered_set_of<Significance>, | ||||
|                      boost::bimaps::unordered_set_of<std::string>> | ||||
|    SignificanceCodesBimap; | ||||
| 
 | ||||
| static const SignificanceCodesBimap significanceCodes_ = | ||||
|    boost::assign::list_of<SignificanceCodesBimap::relation> //
 | ||||
|    (Significance::Warning, "W")                             //
 | ||||
|    (Significance::Watch, "A")                               //
 | ||||
|    (Significance::Advisory, "Y")                            //
 | ||||
|    (Significance::Statement, "S")                           //
 | ||||
|    (Significance::Forecast, "F")                            //
 | ||||
|    (Significance::Outlook, "O")                             //
 | ||||
|    (Significance::Synopsis, "N")                            //
 | ||||
|    (Significance::Unknown, "?"); | ||||
| 
 | ||||
| static const std::unordered_map<Significance, std::string> significanceText_ { | ||||
|    {Significance::Warning, "Warning"},     //
 | ||||
|    {Significance::Watch, "Watch"},         //
 | ||||
|    {Significance::Advisory, "Advisory"},   //
 | ||||
|    {Significance::Statement, "Statement"}, //
 | ||||
|    {Significance::Forecast, "Forecast"},   //
 | ||||
|    {Significance::Outlook, "Outlook"},     //
 | ||||
|    {Significance::Synopsis, "Synopsis"},   //
 | ||||
|    {Significance::Unknown, "Unknown"}}; | ||||
| 
 | ||||
| Significance GetSignificance(const std::string& code) | ||||
| { | ||||
|    Significance significance; | ||||
| 
 | ||||
|    if (significanceCodes_.right.find(code) != significanceCodes_.right.end()) | ||||
|    { | ||||
|       significance = significanceCodes_.right.at(code); | ||||
|    } | ||||
|    else | ||||
|    { | ||||
|       significance = Significance::Unknown; | ||||
| 
 | ||||
|       BOOST_LOG_TRIVIAL(debug) | ||||
|          << logPrefix_ << "Unrecognized code: \"" << code << "\""; | ||||
|    } | ||||
| 
 | ||||
|    return significance; | ||||
| } | ||||
| 
 | ||||
| std::string GetSignificanceCode(Significance significance) | ||||
| { | ||||
|    return significanceCodes_.left.at(significance); | ||||
| } | ||||
| 
 | ||||
| std::string GetSignificanceText(Significance significance) | ||||
| { | ||||
|    return significanceText_.at(significance); | ||||
| } | ||||
| 
 | ||||
| } // namespace awips
 | ||||
| } // namespace scwx
 | ||||
|  | @ -1,4 +1,5 @@ | |||
| #include <scwx/awips/text_product_message.hpp> | ||||
| #include <scwx/awips/pvtec.hpp> | ||||
| #include <scwx/awips/wmo_header.hpp> | ||||
| #include <scwx/common/characters.hpp> | ||||
| #include <scwx/util/streams.hpp> | ||||
|  | @ -26,7 +27,7 @@ static const std::regex reDateTimeString {"^[0-9]{3,4} ([AP]M|UTC)"}; | |||
| 
 | ||||
| struct Vtec | ||||
| { | ||||
|    std::string pVtec_; | ||||
|    PVtec       pVtec_; | ||||
|    std::string hVtec_; | ||||
| 
 | ||||
|    Vtec() : pVtec_ {}, hVtec_ {} {} | ||||
|  | @ -330,7 +331,7 @@ std::optional<Vtec> TryParseVtecString(std::istream& is) | |||
|    if (std::regex_search(line, rePVtecString)) | ||||
|    { | ||||
|       vtec = Vtec(); | ||||
|       vtec->pVtec_.swap(line); | ||||
|       vtec->pVtec_.Parse(line); | ||||
| 
 | ||||
|       isBegin = is.tellg(); | ||||
| 
 | ||||
|  | @ -342,8 +343,8 @@ std::optional<Vtec> TryParseVtecString(std::istream& is) | |||
|       } | ||||
|       else | ||||
|       { | ||||
|          // H-VTEC was not found, so reset the istream to the beginning of the
 | ||||
|          // line
 | ||||
|          // H-VTEC was not found, so reset the istream to the beginning of
 | ||||
|          // the line
 | ||||
|          is.seekg(isBegin, std::ios_base::beg); | ||||
|       } | ||||
|    } | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Dan Paulat
						Dan Paulat