mirror of
				https://github.com/ciphervance/supercell-wx.git
				synced 2025-10-31 01:40:04 +00:00 
			
		
		
		
	Robust coded location error handling
This commit is contained in:
		
							parent
							
								
									7d503ec506
								
							
						
					
					
						commit
						8f3baaa7c3
					
				
					 4 changed files with 131 additions and 13 deletions
				
			
		|  | @ -228,5 +228,29 @@ TEST(CodedLocation, MalformedData) | ||||||
|    EXPECT_EQ(dataValid, false); |    EXPECT_EQ(dataValid, false); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | TEST(CodedLocation, InvalidWFOToken) | ||||||
|  | { | ||||||
|  |    std::vector<std::string> data = { | ||||||
|  |       "LAT...LON abcd 14509 1371 18195 1348 14463 1325 14492"}; | ||||||
|  | 
 | ||||||
|  |    CodedLocation location; | ||||||
|  |    bool          dataValid = location.Parse(data); | ||||||
|  | 
 | ||||||
|  |    EXPECT_EQ(dataValid, false); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | TEST(CodedLocation, InvalidNCToken) | ||||||
|  | { | ||||||
|  |    std::vector<std::string> data = { | ||||||
|  |       "LAT...LON 4731abcd 47216795 46466767 45436766 44756779", | ||||||
|  |       "      44216834 43816943 43706970 43837006 44497009", | ||||||
|  |       "      45306974 46356946 46976921"}; | ||||||
|  | 
 | ||||||
|  |    CodedLocation location; | ||||||
|  |    bool          dataValid = location.Parse(data); | ||||||
|  | 
 | ||||||
|  |    EXPECT_EQ(dataValid, false); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| } // namespace awips
 | } // namespace awips
 | ||||||
| } // namespace scwx
 | } // namespace scwx
 | ||||||
|  |  | ||||||
|  | @ -106,5 +106,38 @@ TEST(CodedTimeMotionLocation, MalformedData) | ||||||
|    EXPECT_EQ(dataValid, false); |    EXPECT_EQ(dataValid, false); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | TEST(CodedTimeMotionLocation, InvalidDirection) | ||||||
|  | { | ||||||
|  |    std::vector<std::string> data = { | ||||||
|  |       "TIME...MOT...LOC 1959Z ZZZDEG 0KT 3253 11464"}; | ||||||
|  | 
 | ||||||
|  |    CodedTimeMotionLocation tml; | ||||||
|  |    bool                    dataValid = tml.Parse(data); | ||||||
|  | 
 | ||||||
|  |    EXPECT_EQ(dataValid, false); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | TEST(CodedTimeMotionLocation, InvalidSpeed) | ||||||
|  | { | ||||||
|  |    std::vector<std::string> data = { | ||||||
|  |       "TIME...MOT...LOC 1959Z 254DEG ZKT 3253 11464"}; | ||||||
|  | 
 | ||||||
|  |    CodedTimeMotionLocation tml; | ||||||
|  |    bool                    dataValid = tml.Parse(data); | ||||||
|  | 
 | ||||||
|  |    EXPECT_EQ(dataValid, false); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | TEST(CodedTimeMotionLocation, InvalidLocation) | ||||||
|  | { | ||||||
|  |    std::vector<std::string> data = { | ||||||
|  |       "TIME...MOT...LOC 1959Z 254DEG 0KT ZZZZ 11464"}; | ||||||
|  | 
 | ||||||
|  |    CodedTimeMotionLocation tml; | ||||||
|  |    bool                    dataValid = tml.Parse(data); | ||||||
|  | 
 | ||||||
|  |    EXPECT_EQ(dataValid, false); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| } // namespace awips
 | } // namespace awips
 | ||||||
| } // namespace scwx
 | } // namespace scwx
 | ||||||
|  |  | ||||||
|  | @ -82,9 +82,23 @@ bool CodedLocation::Parse(const StringRange& lines, const std::string& wfo) | ||||||
|          for (auto token = tokenList.cbegin() + 1; token != tokenList.cend(); |          for (auto token = tokenList.cbegin() + 1; token != tokenList.cend(); | ||||||
|               ++token) |               ++token) | ||||||
|          { |          { | ||||||
|             double latitude = std::stod(*token) * 0.01; |             double latitude  = 0.0; | ||||||
|             ++token; |             double longitude = 0.0; | ||||||
|             double longitude = std::stod(*token) * 0.01; | 
 | ||||||
|  |             try | ||||||
|  |             { | ||||||
|  |                latitude = std::stod(*token) * 0.01; | ||||||
|  |                ++token; | ||||||
|  |                longitude = std::stod(*token) * 0.01; | ||||||
|  |             } | ||||||
|  |             catch (const std::exception& ex) | ||||||
|  |             { | ||||||
|  |                BOOST_LOG_TRIVIAL(warning) | ||||||
|  |                   << logPrefix_ << "Invalid WFO location token: \"" << *token | ||||||
|  |                   << "\" (" << ex.what() << ")"; | ||||||
|  |                dataValid = false; | ||||||
|  |                break; | ||||||
|  |             } | ||||||
| 
 | 
 | ||||||
|             // If a given product straddles 180 degrees longitude, those points
 |             // If a given product straddles 180 degrees longitude, those points
 | ||||||
|             // west of 180 degrees will be given as if they were west longitude
 |             // west of 180 degrees will be given as if they were west longitude
 | ||||||
|  | @ -99,7 +113,7 @@ bool CodedLocation::Parse(const StringRange& lines, const std::string& wfo) | ||||||
|             p->coordinates_.push_back({latitude, longitude}); |             p->coordinates_.push_back({latitude, longitude}); | ||||||
|          } |          } | ||||||
| 
 | 
 | ||||||
|          if (!wfoIsWest && straddlesDateLine) |          if (dataValid && !wfoIsWest && straddlesDateLine) | ||||||
|          { |          { | ||||||
|             for (auto& coordinate : p->coordinates_) |             for (auto& coordinate : p->coordinates_) | ||||||
|             { |             { | ||||||
|  | @ -123,8 +137,22 @@ bool CodedLocation::Parse(const StringRange& lines, const std::string& wfo) | ||||||
|                break; |                break; | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             double latitude  = std::stod(token->substr(0, 4)) * 0.01; |             double latitude  = 0.0; | ||||||
|             double longitude = std::stod(token->substr(4, 4)) * -0.01; |             double longitude = 0.0; | ||||||
|  | 
 | ||||||
|  |             try | ||||||
|  |             { | ||||||
|  |                latitude  = std::stod(token->substr(0, 4)) * 0.01; | ||||||
|  |                longitude = std::stod(token->substr(4, 4)) * -0.01; | ||||||
|  |             } | ||||||
|  |             catch (const std::exception& ex) | ||||||
|  |             { | ||||||
|  |                BOOST_LOG_TRIVIAL(warning) | ||||||
|  |                   << logPrefix_ << "Invalid National Center location token: \"" | ||||||
|  |                   << *token << "\" (" << ex.what() << ")"; | ||||||
|  |                dataValid = false; | ||||||
|  |                break; | ||||||
|  |             } | ||||||
| 
 | 
 | ||||||
|             // Longitudes of greater than 100 degrees will drop the leading 1;
 |             // Longitudes of greater than 100 degrees will drop the leading 1;
 | ||||||
|             // i.e., 105.22 W would be coded as 0522.  This is ambiguous
 |             // i.e., 105.22 W would be coded as 0522.  This is ambiguous
 | ||||||
|  |  | ||||||
|  | @ -122,8 +122,18 @@ bool CodedTimeMotionLocation::Parse(const StringRange& lines, | ||||||
|       std::string direction = tokenList.at(2); |       std::string direction = tokenList.at(2); | ||||||
|       if (direction.size() == 6 && direction.ends_with("DEG")) |       if (direction.size() == 6 && direction.ends_with("DEG")) | ||||||
|       { |       { | ||||||
|          p->direction_ = |          try | ||||||
|             static_cast<uint16_t>(std::stoul(direction.substr(0, 3))); |          { | ||||||
|  |             p->direction_ = | ||||||
|  |                static_cast<uint16_t>(std::stoul(direction.substr(0, 3))); | ||||||
|  |          } | ||||||
|  |          catch (const std::exception& ex) | ||||||
|  |          { | ||||||
|  |             BOOST_LOG_TRIVIAL(warning) | ||||||
|  |                << logPrefix_ << "Invalid direction: \"" << direction << "\" (" | ||||||
|  |                << ex.what() << ")"; | ||||||
|  |             dataValid = false; | ||||||
|  |          } | ||||||
|       } |       } | ||||||
|       else |       else | ||||||
|       { |       { | ||||||
|  | @ -136,8 +146,17 @@ bool CodedTimeMotionLocation::Parse(const StringRange& lines, | ||||||
|       std::string speed = tokenList.at(3); |       std::string speed = tokenList.at(3); | ||||||
|       if (speed.size() >= 3 && speed.size() <= 4 && speed.ends_with("KT")) |       if (speed.size() >= 3 && speed.size() <= 4 && speed.ends_with("KT")) | ||||||
|       { |       { | ||||||
|          p->speed_ = |          try | ||||||
|             static_cast<uint8_t>(std::stoul(speed.substr(0, speed.size() - 2))); |          { | ||||||
|  |             p->speed_ = static_cast<uint8_t>( | ||||||
|  |                std::stoul(speed.substr(0, speed.size() - 2))); | ||||||
|  |          } | ||||||
|  |          catch (const std::exception& ex) | ||||||
|  |          { | ||||||
|  |             BOOST_LOG_TRIVIAL(warning) << logPrefix_ << "Invalid speed: \"" | ||||||
|  |                                        << speed << "\" (" << ex.what() << ")"; | ||||||
|  |             dataValid = false; | ||||||
|  |          } | ||||||
|       } |       } | ||||||
|       else |       else | ||||||
|       { |       { | ||||||
|  | @ -150,9 +169,23 @@ bool CodedTimeMotionLocation::Parse(const StringRange& lines, | ||||||
|       for (auto token = tokenList.cbegin() + 4; token != tokenList.cend(); |       for (auto token = tokenList.cbegin() + 4; token != tokenList.cend(); | ||||||
|            ++token) |            ++token) | ||||||
|       { |       { | ||||||
|          double latitude = std::stod(*token) * 0.01; |          double latitude  = 0.0; | ||||||
|          ++token; |          double longitude = 0.0; | ||||||
|          double longitude = std::stod(*token) * 0.01; | 
 | ||||||
|  |          try | ||||||
|  |          { | ||||||
|  |             latitude = std::stod(*token) * 0.01; | ||||||
|  |             ++token; | ||||||
|  |             longitude = std::stod(*token) * 0.01; | ||||||
|  |          } | ||||||
|  |          catch (const std::exception& ex) | ||||||
|  |          { | ||||||
|  |             BOOST_LOG_TRIVIAL(warning) | ||||||
|  |                << logPrefix_ << "Invalid location token: \"" << *token << "\" (" | ||||||
|  |                << ex.what() << ")"; | ||||||
|  |             dataValid = false; | ||||||
|  |             break; | ||||||
|  |          } | ||||||
| 
 | 
 | ||||||
|          // If a given product straddles 180 degrees longitude, those points
 |          // If a given product straddles 180 degrees longitude, those points
 | ||||||
|          // west of 180 degrees will be given as if they were west longitude
 |          // west of 180 degrees will be given as if they were west longitude
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Dan Paulat
						Dan Paulat