1 // metar interface class
2 //
3 // Written by Melchior FRANZ, started December 2003.
4 //
5 // Copyright (C) 2003  Melchior FRANZ - mfranz@aon.at
6 //
7 // This program is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU General Public License as
9 // published by the Free Software Foundation; either version 2 of the
10 // License, or (at your option) any later version.
11 //
12 // This program is distributed in the hope that it will be useful, but
13 // WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 // General Public License for more details.
16 //
17 // You should have received a copy of the GNU General Public License
18 // along with this program; if not, write to the Free Software
19 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
20 //
21 // $Id$
22 
23 #ifndef _METAR_HXX
24 #define _METAR_HXX
25 
26 #include <vector>
27 #include <map>
28 #include <string>
29 
30 #include <simgear/constants.h>
31 
32 struct Token {
33 	const char *id;
34 	const char *text;
35 };
36 
37 const double SGMetarNaN = -1E20;
38 
39 class SGMetar;
40 
41 class SGMetarVisibility {
42 	friend class SGMetar;
43 public:
SGMetarVisibility()44 	SGMetarVisibility() :
45 		_distance(SGMetarNaN),
46 		_direction(-1),
47 		_modifier(EQUALS),
48 		_tendency(NONE) {}
49 
50 	enum Modifier {
51 		NOGO,
52 		EQUALS,
53 		LESS_THAN,
54 		GREATER_THAN
55 	};
56 
57 	enum Tendency {
58 		NONE,
59 		STABLE,
60 		INCREASING,
61 		DECREASING
62 	};
63 
64 	void set(double dist, int dir = -1, int mod = -1, int tend = -1);
65 
getVisibility_m() const66 	inline double	getVisibility_m()	const { return _distance; }
getVisibility_ft() const67 	inline double	getVisibility_ft()	const { return _distance == SGMetarNaN ? SGMetarNaN : _distance * SG_METER_TO_FEET; }
getVisibility_sm() const68 	inline double	getVisibility_sm()	const { return _distance == SGMetarNaN ? SGMetarNaN : _distance * SG_METER_TO_SM; }
getDirection() const69 	inline int	getDirection()		const { return _direction; }
getModifier() const70 	inline int	getModifier()		const { return _modifier; }
getTendency() const71 	inline int	getTendency()		const { return _tendency; }
72 
73 protected:
74 	double	_distance;
75 	int	_direction;
76 	int	_modifier;
77 	int	_tendency;
78 };
79 
80 
81 // runway condition (surface and visibility)
82 class SGMetarRunway {
83 	friend class SGMetar;
84 public:
SGMetarRunway()85 	SGMetarRunway() :
86 		_deposit(-1),
87 		_deposit_string(0),
88 		_extent(-1),
89 		_extent_string(0),
90 		_depth(SGMetarNaN),
91 		_friction(SGMetarNaN),
92 		_friction_string(0),
93 		_comment(0),
94 		_wind_shear(false) {}
95 
getDeposit() const96 	inline int			getDeposit()		const { return _deposit; }
getDepositString() const97 	inline const char		*getDepositString()	const { return _deposit_string; }
getExtent() const98 	inline double			getExtent()		const { return _extent; }
getExtentString() const99 	inline const char		*getExtentString()	const { return _extent_string; }
getDepth() const100 	inline double			getDepth()		const { return _depth; }
getFriction() const101 	inline double			getFriction()		const { return _friction; }
getFrictionString() const102 	inline const char		*getFrictionString()	const { return _friction_string; }
getComment() const103 	inline const char		*getComment()		const { return _comment; }
getWindShear() const104 	inline       bool		getWindShear()		const { return _wind_shear; }
getMinVisibility() const105 	inline const SGMetarVisibility&	getMinVisibility()	const { return _min_visibility; }
getMaxVisibility() const106 	inline const SGMetarVisibility&	getMaxVisibility()	const { return _max_visibility; }
107 
108 protected:
109 	SGMetarVisibility _min_visibility;
110 	SGMetarVisibility _max_visibility;
111 	int		_deposit;
112 	const char	*_deposit_string;
113 	int		_extent;
114 	const char	*_extent_string;
115 	double		_depth;
116 	double		_friction;
117 	const char	*_friction_string;
118 	const char	*_comment;
119 	bool		_wind_shear;
120 };
121 
122 
123 // cloud layer
124 class SGMetarCloud {
125 	friend class SGMetar;
126 public:
127 	enum Coverage {
128 		COVERAGE_NIL = -1,
129 		COVERAGE_CLEAR = 0,
130 		COVERAGE_FEW = 1,
131 		COVERAGE_SCATTERED = 2,
132 		COVERAGE_BROKEN = 3,
133 		COVERAGE_OVERCAST = 4
134 	};
135 
136 	static const char * COVERAGE_NIL_STRING;
137 	static const char * COVERAGE_CLEAR_STRING;
138 	static const char * COVERAGE_FEW_STRING;
139 	static const char * COVERAGE_SCATTERED_STRING;
140 	static const char * COVERAGE_BROKEN_STRING;
141 	static const char * COVERAGE_OVERCAST_STRING;
142 
SGMetarCloud()143 	SGMetarCloud() : _coverage(COVERAGE_NIL), _altitude(SGMetarNaN), _type(0), _type_long(0) {}
144 
145 	void set(double alt, Coverage cov = COVERAGE_NIL );
146 
getCoverage() const147 	inline Coverage getCoverage() const { return _coverage; }
148 	static Coverage getCoverage( const std::string & coverage );
getAltitude_m() const149 	inline double getAltitude_m() const { return _altitude; }
getAltitude_ft() const150 	inline double getAltitude_ft() const { return _altitude == SGMetarNaN ? SGMetarNaN : _altitude * SG_METER_TO_FEET; }
getTypeString() const151 	inline const char *getTypeString() const { return _type; }
getTypeLongString() const152 	inline const char *getTypeLongString() const { return _type_long; }
153 
154 protected:
155 	Coverage _coverage;     // quarters: 0 -> clear ... 4 -> overcast
156 	double _altitude;       // 1000 m
157 	const char *_type;      // CU
158 	const char *_type_long; // cumulus
159 };
160 
161 
162 class SGMetar {
163 public:
164 	SGMetar(const std::string& m);
165 	~SGMetar();
166 
167 	enum ReportType {
168 		NONE,
169 		AUTO,
170 		COR,
171 		RTD
172 	};
173 
174 	enum Intensity {
175 		NIL = 0,
176 		LIGHT = 1,
177 		MODERATE = 2,
178 		HEAVY = 3
179 	};
180 
181 	struct Weather {
WeatherSGMetar::Weather182 		Weather() { intensity = NIL; vincinity = false; }
183 		Intensity intensity;
184 		bool      vincinity;
185 		std::vector<std::string> descriptions;
186 		std::vector<std::string> phenomena;
187 	};
188 
getData() const189 	inline const char *getData()		const { return _data; }
getUnusedData() const190 	inline const char *getUnusedData()	const { return _m; }
getProxy() const191 	inline       bool getProxy()		const { return _x_proxy; }
getId() const192 	inline const char *getId()		const { return _icao; }
getYear() const193 	inline int	getYear()		const { return _year; }
getMonth() const194 	inline int	getMonth()		const { return _month; }
getDay() const195 	inline int	getDay()		const { return _day; }
getHour() const196 	inline int	getHour()		const { return _hour; }
getMinute() const197 	inline int	getMinute()		const { return _minute; }
getReportType() const198 	inline int	getReportType()		const { return _report_type; }
199 
getWindDir() const200 	inline int	getWindDir()		const { return _wind_dir; }
getWindSpeed_mps() const201 	inline double	getWindSpeed_mps()	const { return _wind_speed; }
getWindSpeed_kmh() const202 	inline double	getWindSpeed_kmh()	const { return _wind_speed == SGMetarNaN ? SGMetarNaN : _wind_speed * SG_MPS_TO_KMH; }
getWindSpeed_kt() const203 	inline double	getWindSpeed_kt()	const { return _wind_speed == SGMetarNaN ? SGMetarNaN : _wind_speed * SG_MPS_TO_KT; }
getWindSpeed_mph() const204 	inline double	getWindSpeed_mph()	const { return _wind_speed == SGMetarNaN ? SGMetarNaN : _wind_speed * SG_MPS_TO_MPH; }
205 
getGustSpeed_mps() const206 	inline double	getGustSpeed_mps()	const { return _gust_speed; }
getGustSpeed_kmh() const207 	inline double	getGustSpeed_kmh()	const { return _gust_speed == SGMetarNaN ? SGMetarNaN : _gust_speed * SG_MPS_TO_KMH; }
getGustSpeed_kt() const208 	inline double	getGustSpeed_kt()	const { return _gust_speed == SGMetarNaN ? SGMetarNaN : _gust_speed * SG_MPS_TO_KT; }
getGustSpeed_mph() const209 	inline double	getGustSpeed_mph()	const { return _gust_speed == SGMetarNaN ? SGMetarNaN : _gust_speed * SG_MPS_TO_MPH; }
210 
getWindRangeFrom() const211 	inline int	getWindRangeFrom()	const { return _wind_range_from; }
getWindRangeTo() const212 	inline int	getWindRangeTo()	const { return _wind_range_to; }
213 
getMinVisibility() const214 	inline const SGMetarVisibility& getMinVisibility()	const { return _min_visibility; }
getMaxVisibility() const215 	inline const SGMetarVisibility& getMaxVisibility()	const { return _max_visibility; }
getVertVisibility() const216 	inline const SGMetarVisibility& getVertVisibility()	const { return _vert_visibility; }
getDirVisibility() const217 	inline const SGMetarVisibility *getDirVisibility()	const { return _dir_visibility; }
218 
getTemperature_C() const219 	inline double	getTemperature_C()	const { return _temp; }
getTemperature_F() const220 	inline double	getTemperature_F()	const { return _temp == SGMetarNaN ? SGMetarNaN : 1.8 * _temp + 32; }
getDewpoint_C() const221 	inline double	getDewpoint_C()		const { return _dewp; }
getDewpoint_F() const222 	inline double	getDewpoint_F()		const { return _dewp == SGMetarNaN ? SGMetarNaN : 1.8 * _dewp + 32; }
getPressure_hPa() const223 	inline double	getPressure_hPa()	const { return _pressure == SGMetarNaN ? SGMetarNaN : _pressure / 100; }
getPressure_inHg() const224 	inline double	getPressure_inHg()	const { return _pressure == SGMetarNaN ? SGMetarNaN : _pressure * SG_PA_TO_INHG; }
225 
getRain() const226 	inline int	getRain()		const { return _rain; }
getHail() const227 	inline int	getHail()		const { return _hail; }
getSnow() const228 	inline int	getSnow()		const { return _snow; }
getCAVOK() const229 	inline bool	getCAVOK()		const { return _cavok; }
230 
231 	double		getRelHumidity()	const;
232 
getClouds() const233 	inline const std::vector<SGMetarCloud>& getClouds()	const	{ return _clouds; }
getRunways() const234 	inline const std::map<std::string, SGMetarRunway>& getRunways()	const	{ return _runways; }
getWeather() const235 	inline const std::vector<std::string>& getWeather()		const	{ return _weather; }
getWeather2() const236 	inline const std::vector<struct Weather> getWeather2()	const   { return _weather2; }
237 
238         /* Returns human-readable description. If tabtops is 0, we use tab
239         characters. If +ve we use spaces to pad to multiple of <tabstops>. If
240         -1 all sequences of tabs are represented by a single space. */
241         std::string     getDescription(int tabstops)   const;
242 
243 protected:
244 	std::string	_url;
245 	int	_grpcount;
246 	bool	_x_proxy;
247 	char	*_data;
248 	char	*_m;
249 	char	_icao[5];
250 	int	_year;
251 	int	_month;
252 	int	_day;
253 	int	_hour;
254 	int	_minute;
255 	int	_report_type;
256 	int	_wind_dir;
257 	double	_wind_speed;
258 	double	_gust_speed;
259 	int	_wind_range_from;
260 	int	_wind_range_to;
261 	double	_temp;
262 	double	_dewp;
263 	double	_pressure;
264 	int	_rain;
265 	int	_hail;
266 	int	_snow;
267 	bool	_cavok;
268 	std::vector<struct Weather> _weather2;
269 
270 	SGMetarVisibility		_min_visibility;
271 	SGMetarVisibility		_max_visibility;
272 	SGMetarVisibility		_vert_visibility;
273 	SGMetarVisibility		_dir_visibility[8];
274 	std::vector<SGMetarCloud>		_clouds;
275 	std::map<std::string, SGMetarRunway>	_runways;
276 	std::vector<std::string>			_weather;
277 
278 	bool	scanPreambleDate();
279 	bool	scanPreambleTime();
280 	void	useCurrentDate();
281 
282 	bool	scanType();
283 	bool	scanId();
284 	bool	scanDate();
285 	bool	scanModifier();
286 	bool	scanWind();
287 	bool	scanVariability();
288 	bool	scanVisibility();
289 	bool	scanRwyVisRange();
290 	bool	scanSkyCondition();
291 	bool	scanWeather();
292 	bool	scanTemperature();
293 	bool	scanPressure();
294 	bool	scanRunwayReport();
295 	bool	scanWindShear();
296 	bool	scanTrendForecast();
297 	bool	scanColorState();
298 	bool	scanRemark();
299 	bool	scanRemainder();
300 
301 	int	scanNumber(char **str, int *num, int min, int max = 0);
302 	bool	scanBoundary(char **str);
303 	const struct Token *scanToken(char **str, const struct Token *list);
304 	void	normalizeData();
305 };
306 
307 #endif // _METAR_HXX
308