mirror of
				https://github.com/ciphervance/supercell-wx.git
				synced 2025-10-31 05:10:04 +00:00 
			
		
		
		
	Finish parsing storm tracking tabular block
This commit is contained in:
		
							parent
							
								
									6eb9caf819
								
							
						
					
					
						commit
						c03947d604
					
				
					 3 changed files with 184 additions and 44 deletions
				
			
		|  | @ -35,6 +35,24 @@ public: | |||
|    std::optional<std::chrono::sys_time<std::chrono::seconds>> dateTime_ {}; | ||||
|    std::optional<std::uint16_t>                               numStormCells_ {}; | ||||
| 
 | ||||
|    // STORM CELL TRACKING/FORECAST ADAPTATION DATA
 | ||||
|    std::optional<units::angle::degrees<std::uint16_t>> defaultDirection_ {}; | ||||
|    std::optional<units::velocity::meters_per_second<float>> minimumSpeed_ {}; | ||||
|    std::optional<units::velocity::knots<float>>             defaultSpeed_ {}; | ||||
|    std::optional<units::length::kilometers<std::uint16_t>>  allowableError_ {}; | ||||
|    std::optional<std::chrono::minutes>                      maximumTime_ {}; | ||||
|    std::optional<std::chrono::minutes> forecastInterval_ {}; | ||||
|    std::optional<std::uint16_t>        numberOfPastVolumes_ {}; | ||||
|    std::optional<std::uint16_t>        numberOfIntervals_ {}; | ||||
|    std::optional<units::velocity::meters_per_second<float>> | ||||
|                                        correlationSpeed_ {}; | ||||
|    std::optional<std::chrono::minutes> errorInterval_ {}; | ||||
| 
 | ||||
|    // SCIT REFLECTIVITY MEDIAN FILTER
 | ||||
|    std::optional<units::length::kilometers<float>> filterKernelSize_ {}; | ||||
|    std::optional<float>                            filterFraction_ {}; | ||||
|    std::optional<bool>                             reflectivityFiltered_ {}; | ||||
| 
 | ||||
|    std::unordered_map<std::string, StiRecord> stiRecords_ {}; | ||||
| }; | ||||
| 
 | ||||
|  | @ -122,8 +140,8 @@ void StormTrackingInformationMessage::Impl::ParseStormPositionForecastPage( | |||
|       { | ||||
|          if (radarId_ == std::nullopt) | ||||
|          { | ||||
|             radarId_ = | ||||
|                util::TryParseUnsignedLong<std::uint16_t>(line.substr(14, 3)); | ||||
|             // Radar ID (I3)
 | ||||
|             radarId_ = util::TryParseNumeric<std::uint16_t>(line.substr(14, 3)); | ||||
|          } | ||||
|          if (dateTime_ == std::nullopt) | ||||
|          { | ||||
|  | @ -134,8 +152,9 @@ void StormTrackingInformationMessage::Impl::ParseStormPositionForecastPage( | |||
|          } | ||||
|          if (numStormCells_ == std::nullopt) | ||||
|          { | ||||
|             // Number of Storm Cells (I3)
 | ||||
|             numStormCells_ = | ||||
|                util::TryParseUnsignedLong<std::uint16_t>(line.substr(71, 3)); | ||||
|                util::TryParseNumeric<std::uint16_t>(line.substr(71, 3)); | ||||
|          } | ||||
|       } | ||||
|       // clang-format off
 | ||||
|  | @ -151,9 +170,9 @@ void StormTrackingInformationMessage::Impl::ParseStormPositionForecastPage( | |||
| 
 | ||||
|             if (record.currentPosition_.azimuth_ == std::nullopt) | ||||
|             { | ||||
|                // Current Position: Azimuth (Degrees)
 | ||||
|                // Current Position: Azimuth (Degrees) (I3)
 | ||||
|                auto azimuth = | ||||
|                   util::TryParseUnsignedLong<std::uint16_t>(line.substr(9, 3)); | ||||
|                   util::TryParseNumeric<std::uint16_t>(line.substr(9, 3)); | ||||
|                if (azimuth.has_value()) | ||||
|                { | ||||
|                   record.currentPosition_.azimuth_ = | ||||
|  | @ -162,9 +181,9 @@ void StormTrackingInformationMessage::Impl::ParseStormPositionForecastPage( | |||
|             } | ||||
|             if (record.currentPosition_.range_ == std::nullopt) | ||||
|             { | ||||
|                // Current Position: Range (Nautical Miles)
 | ||||
|                // Current Position: Range (Nautical Miles) (I3)
 | ||||
|                auto range = | ||||
|                   util::TryParseUnsignedLong<std::uint16_t>(line.substr(13, 3)); | ||||
|                   util::TryParseNumeric<std::uint16_t>(line.substr(13, 3)); | ||||
|                if (range.has_value()) | ||||
|                { | ||||
|                   record.currentPosition_.range_ = | ||||
|  | @ -174,9 +193,9 @@ void StormTrackingInformationMessage::Impl::ParseStormPositionForecastPage( | |||
|             } | ||||
|             if (record.direction_ == std::nullopt) | ||||
|             { | ||||
|                // Movement: Direction (Degrees)
 | ||||
|                // Movement: Direction (Degrees) (I3)
 | ||||
|                auto direction = | ||||
|                   util::TryParseUnsignedLong<std::uint16_t>(line.substr(19, 3)); | ||||
|                   util::TryParseNumeric<std::uint16_t>(line.substr(19, 3)); | ||||
|                if (direction.has_value()) | ||||
|                { | ||||
|                   record.direction_ = | ||||
|  | @ -185,9 +204,9 @@ void StormTrackingInformationMessage::Impl::ParseStormPositionForecastPage( | |||
|             } | ||||
|             if (record.speed_ == std::nullopt) | ||||
|             { | ||||
|                // Movement: Speed (Knots)
 | ||||
|                // Movement: Speed (Knots) (I3)
 | ||||
|                auto speed = | ||||
|                   util::TryParseUnsignedLong<std::uint16_t>(line.substr(23, 3)); | ||||
|                   util::TryParseNumeric<std::uint16_t>(line.substr(23, 3)); | ||||
|                if (speed.has_value()) | ||||
|                { | ||||
|                   record.speed_ = | ||||
|  | @ -200,10 +219,10 @@ void StormTrackingInformationMessage::Impl::ParseStormPositionForecastPage( | |||
| 
 | ||||
|                if (record.forecastPosition_[j].azimuth_ == std::nullopt) | ||||
|                { | ||||
|                   // Forecast Position: Azimuth (Degrees)
 | ||||
|                   // Forecast Position: Azimuth (Degrees) (I3)
 | ||||
|                   std::size_t offset = 31 + positionOffset; | ||||
| 
 | ||||
|                   auto azimuth = util::TryParseUnsignedLong<std::uint16_t>( | ||||
|                   auto azimuth = util::TryParseNumeric<std::uint16_t>( | ||||
|                      line.substr(offset, 3)); | ||||
|                   if (azimuth.has_value()) | ||||
|                   { | ||||
|  | @ -213,10 +232,10 @@ void StormTrackingInformationMessage::Impl::ParseStormPositionForecastPage( | |||
|                } | ||||
|                if (record.forecastPosition_[j].range_ == std::nullopt) | ||||
|                { | ||||
|                   // Forecast Position: Range (Nautical Miles)
 | ||||
|                   // Forecast Position: Range (Nautical Miles) (I3)
 | ||||
|                   std::size_t offset = 35 + positionOffset; | ||||
| 
 | ||||
|                   auto range = util::TryParseUnsignedLong<std::uint16_t>( | ||||
|                   auto range = util::TryParseNumeric<std::uint16_t>( | ||||
|                      line.substr(offset, 3)); | ||||
|                   if (range.has_value()) | ||||
|                   { | ||||
|  | @ -228,8 +247,9 @@ void StormTrackingInformationMessage::Impl::ParseStormPositionForecastPage( | |||
|             } | ||||
|             if (record.forecastError_ == std::nullopt) | ||||
|             { | ||||
|                // Forecast Error (Nautical Miles)
 | ||||
|                auto forecastError = util::TryParseFloat(line.substr(71, 4)); | ||||
|                // Forecast Error (Nautical Miles) (F4.1)
 | ||||
|                auto forecastError = | ||||
|                   util::TryParseNumeric<float>(line.substr(71, 4)); | ||||
|                if (forecastError.has_value()) | ||||
|                { | ||||
|                   record.forecastError_ = units::length::nautical_miles<float> { | ||||
|  | @ -238,8 +258,9 @@ void StormTrackingInformationMessage::Impl::ParseStormPositionForecastPage( | |||
|             } | ||||
|             if (record.meanError_ == std::nullopt) | ||||
|             { | ||||
|                // Mean Error (Nautical Miles)
 | ||||
|                auto meanError = util::TryParseFloat(line.substr(76, 4)); | ||||
|                // Mean Error (Nautical Miles) (F4.1)
 | ||||
|                auto meanError = | ||||
|                   util::TryParseNumeric<float>(line.substr(76, 4)); | ||||
|                if (meanError.has_value()) | ||||
|                { | ||||
|                   record.meanError_ = | ||||
|  | @ -254,8 +275,137 @@ void StormTrackingInformationMessage::Impl::ParseStormPositionForecastPage( | |||
| void StormTrackingInformationMessage::Impl::ParseStormCellTrackingDataPage( | ||||
|    const std::vector<std::string>& page) | ||||
| { | ||||
|    // TODO
 | ||||
|    (void) (page); | ||||
|    for (std::size_t i = 1; i < page.size(); ++i) | ||||
|    { | ||||
|       const std::string& line = page[i]; | ||||
| 
 | ||||
|       // clang-format off
 | ||||
|       // "    260   (DEG) DEFAULT (DIRECTION)      2.5   (M/S) THRESH (MINIMUM SPEED)"
 | ||||
|       // clang-format on
 | ||||
|       if (i == 2 && line.size() >= 75) | ||||
|       { | ||||
|          // Default Direction (Degrees) (I3)
 | ||||
|          auto direction = | ||||
|             util::TryParseNumeric<std::uint16_t>(line.substr(4, 3)); | ||||
|          if (direction.has_value()) | ||||
|          { | ||||
|             defaultDirection_ = | ||||
|                units::angle::degrees<std::uint16_t> {direction.value()}; | ||||
|          } | ||||
| 
 | ||||
|          // Minimum Speed (Threshold) (m/s) (F4.1)
 | ||||
|          auto threshold = util::TryParseNumeric<float>(line.substr(40, 4)); | ||||
|          if (threshold.has_value()) | ||||
|          { | ||||
|             minimumSpeed_ = | ||||
|                units::velocity::meters_per_second<float> {threshold.value()}; | ||||
|          } | ||||
|       } | ||||
|       // clang-format off
 | ||||
|       // "   36.0   (KTS) DEFAULT (SPEED)           20    (KM) ALLOWABLE ERROR"
 | ||||
|       // clang-format on
 | ||||
|       if (i == 3 && line.size() >= 68) | ||||
|       { | ||||
|          // Default Speed (Knots) (F4.1)
 | ||||
|          auto speed = util::TryParseNumeric<float>(line.substr(3, 4)); | ||||
|          if (speed.has_value()) | ||||
|          { | ||||
|             defaultSpeed_ = units::velocity::knots<float> {speed.value()}; | ||||
|          } | ||||
| 
 | ||||
|          // Allowable Error (Kilometers) (I2)
 | ||||
|          auto error = util::TryParseNumeric<std::uint16_t>(line.substr(42, 2)); | ||||
|          if (error.has_value()) | ||||
|          { | ||||
|             allowableError_ = | ||||
|                units::length::kilometers<std::uint16_t> {error.value()}; | ||||
|          } | ||||
|       } | ||||
|       // clang-format off
 | ||||
|       // "     20   (MIN) TIME (MAXIMUM)            15   (MIN) FORECAST INTERVAL"
 | ||||
|       // clang-format on
 | ||||
|       if (i == 4 && line.size() >= 70) | ||||
|       { | ||||
|          // Maximum Time (Minutes) (I5)
 | ||||
|          auto time = util::TryParseNumeric<std::uint32_t>(line.substr(2, 5)); | ||||
|          if (time.has_value()) | ||||
|          { | ||||
|             maximumTime_ = std::chrono::minutes {time.value()}; | ||||
|          } | ||||
| 
 | ||||
|          // Forecast Interval (Minutes) (I2)
 | ||||
|          auto interval = | ||||
|             util::TryParseNumeric<std::uint16_t>(line.substr(42, 2)); | ||||
|          if (interval.has_value()) | ||||
|          { | ||||
|             forecastInterval_ = std::chrono::minutes {interval.value()}; | ||||
|          } | ||||
|       } | ||||
|       // clang-format off
 | ||||
|       // "     10         NUMBER OF PAST VOLUMES     4         NUMBER OF INTERVALS"
 | ||||
|       // clang-format on
 | ||||
|       if (i == 5 && line.size() >= 72) | ||||
|       { | ||||
|          // Number of Past Volumes (I2)
 | ||||
|          numberOfPastVolumes_ = | ||||
|             util::TryParseNumeric<std::uint16_t>(line.substr(5, 2)); | ||||
| 
 | ||||
|          // Number of Intervals (I2)
 | ||||
|          numberOfIntervals_ = | ||||
|             util::TryParseNumeric<std::uint16_t>(line.substr(42, 2)); | ||||
|       } | ||||
|       // clang-format off
 | ||||
|       // "   30.0   (M/S) CORRELATION SPEED         15   (MIN) ERROR INTERVAL"
 | ||||
|       // clang-format on
 | ||||
|       if (i == 6 && line.size() >= 67) | ||||
|       { | ||||
|          // Correlation Speed (m/s) (F4.1)
 | ||||
|          auto speed = util::TryParseNumeric<float>(line.substr(3, 4)); | ||||
|          if (speed.has_value()) | ||||
|          { | ||||
|             correlationSpeed_ = | ||||
|                units::velocity::meters_per_second<float> {speed.value()}; | ||||
|          } | ||||
| 
 | ||||
|          // Error Interval (Minutes) (I2)
 | ||||
|          auto interval = | ||||
|             util::TryParseNumeric<std::uint16_t>(line.substr(42, 2)); | ||||
|          if (interval.has_value()) | ||||
|          { | ||||
|             errorInterval_ = std::chrono::minutes {interval.value()}; | ||||
|          } | ||||
|       } | ||||
|       // clang-format off
 | ||||
|       // "    7.0   (KM)  FILTER KERNEL SIZE       0.5         THRESH (FILTER FRACTION)"
 | ||||
|       // clang-format on
 | ||||
|       if (i == 11 && line.size() >= 77) | ||||
|       { | ||||
|          // Filter Kernel Size (Kilometers) (F4.1)
 | ||||
|          auto kernelSize = util::TryParseNumeric<float>(line.substr(3, 4)); | ||||
|          if (kernelSize.has_value()) | ||||
|          { | ||||
|             filterKernelSize_ = | ||||
|                units::length::kilometers<float> {kernelSize.value()}; | ||||
|          } | ||||
| 
 | ||||
|          // Minimum Speed (Threshold) (m/s) (F4.1)
 | ||||
|          filterFraction_ = util::TryParseNumeric<float>(line.substr(40, 4)); | ||||
|       } | ||||
|       // clang-format off
 | ||||
|       // "    Yes         REFLECTIVITY FILTERED"
 | ||||
|       // clang-format on
 | ||||
|       if (i == 12 && line.size() >= 37) | ||||
|       { | ||||
|          if (line.substr(4, 3) == "Yes") | ||||
|          { | ||||
|             reflectivityFiltered_ = true; | ||||
|          } | ||||
|          else if (line.substr(5, 2) == "No") | ||||
|          { | ||||
|             reflectivityFiltered_ = false; | ||||
|          } | ||||
|       } | ||||
|    } | ||||
| } | ||||
| 
 | ||||
| std::shared_ptr<StormTrackingInformationMessage> | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Dan Paulat
						Dan Paulat