swift
testweather.cpp
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: Copyright (C) 2013 swift Project Community / Contributors
2 // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-swift-pilot-client-1
3 
7 
8 #include <QTest>
9 
10 #include "test.h"
11 
13 #include "misc/aviation/altitude.h"
15 #include "misc/pq/angle.h"
16 #include "misc/pq/length.h"
18 #include "misc/pq/pressure.h"
19 #include "misc/pq/speed.h"
20 #include "misc/pq/temperature.h"
21 #include "misc/pq/time.h"
22 #include "misc/pq/units.h"
25 #include "misc/weather/metar.h"
29 #include "misc/weather/windlayer.h"
31 
32 using namespace swift::misc::weather;
33 using namespace swift::misc::aviation;
34 using namespace swift::misc::physical_quantities;
35 
36 namespace MiscTest
37 {
39  class CTestWeather : public QObject
40  {
41  Q_OBJECT
42 
43  private slots:
45  void cloudLayer();
46 
48  void windLayer();
49 
51  void metarDecoder();
52  };
53 
54  void CTestWeather::cloudLayer()
55  {
56  const CAltitude base1 { 0, CAltitude::AboveGround, CLengthUnit::ft() };
57  const CAltitude top1 { 5000, CAltitude::AboveGround, CLengthUnit::ft() };
58 
59  CCloudLayer cl1(base1, top1, CCloudLayer::Scattered);
60  QVERIFY(cl1.getBase() == base1);
61  QVERIFY(cl1.getTop() == top1);
62  QCOMPARE(cl1.getPrecipitationRate(), 0.0);
63  QVERIFY(cl1.getPrecipitation() == CCloudLayer::NoPrecipitation);
64  QVERIFY(cl1.getClouds() == CCloudLayer::NoClouds);
65  QVERIFY(cl1.getCoverage() == CCloudLayer::Scattered);
66 
67  const CAltitude base2 { 15000, CAltitude::AboveGround, CLengthUnit::ft() };
68  const CAltitude top2 { 35000, CAltitude::AboveGround, CLengthUnit::ft() };
69 
70  CCloudLayer cl2 { base2, top2, 5, CCloudLayer::Rain, CCloudLayer::Cirrus, CCloudLayer::Scattered };
71  QVERIFY(cl2.getBase() == base2);
72  QVERIFY(cl2.getTop() == top2);
73  QCOMPARE(cl2.getPrecipitationRate(), 5.0);
74  QVERIFY(cl2.getPrecipitation() == CCloudLayer::Rain);
75  QVERIFY(cl2.getClouds() == CCloudLayer::Cirrus);
76  QVERIFY(cl2.getCoverage() == CCloudLayer::Scattered);
77 
78  const CAltitude base3 { 25000, CAltitude::AboveGround, CLengthUnit::ft() };
79  CCloudLayerList cll { cl1, cl2 };
80  QVERIFY(cll.containsBase(base1));
81  QVERIFY(cll.containsBase(base2));
82  QVERIFY(!cll.containsBase(base3));
83  QVERIFY(cll.findByBase(base1) != CCloudLayer());
84  QVERIFY(cll.findByBase(base2) != CCloudLayer());
85  QVERIFY(cll.findByBase(base3) == CCloudLayer());
86  }
87 
88  void CTestWeather::windLayer()
89  {
90  const CAltitude level1 { 0, CAltitude::AboveGround, CLengthUnit::ft() };
91  const CAngle direction1 { 25, CAngleUnit::deg() };
92  const CSpeed speed1 { 10, CSpeedUnit::kts() };
93  const CSpeed gustSpeed1 { 20, CSpeedUnit::kts() };
94 
95  CWindLayer wl1(level1, direction1, speed1, gustSpeed1);
96  QVERIFY(wl1.getLevel() == level1);
97  QVERIFY(wl1.getDirection() == direction1);
98  QVERIFY(wl1.getSpeed() == speed1);
99  QVERIFY(wl1.getGustSpeed() == gustSpeed1);
100 
101  CAltitude level2 { 25000, CAltitude::AboveGround, CLengthUnit::ft() };
102  CWindLayerList wll { wl1 };
103  QVERIFY(wll.containsLevel(level1));
104  QVERIFY(!wll.containsLevel(level2));
105  QVERIFY(wll.findByLevel(level1) != CWindLayer());
106  QVERIFY(wll.findByLevel(level2) == CWindLayer());
107  }
108 
109  void CTestWeather::metarDecoder()
110  {
111  CMetarDecoder metarDecoder;
112  CMetar metar = metarDecoder.decode("KLBB 241753Z 20009KT 10SM -SHRA FEW045 SCT220 SCT300 28/17 A3022");
113  QVERIFY2(metar.getAirportIcaoCode() == CAirportIcaoCode("KLBB"), "Failed to parse airport code");
114  QVERIFY2(metar.getDay() == 24, "Failed to parse day of report");
115  QVERIFY2(metar.getTime() == CTime(17, 53, 0), "Failed to parse time of report");
116  QVERIFY2(metar.getWindLayer().getDirection() == CAngle(200, CAngleUnit::deg()),
117  "Failed to parse wind direction");
118  QVERIFY2(metar.getWindLayer().getSpeed() == CSpeed(9, CSpeedUnit::kts()), "Failed to parse wind speed");
119  QVERIFY2(metar.getWindLayer().getGustSpeed() == CSpeed(0, CSpeedUnit::kts()), "Wind gust speed should be null");
120  QVERIFY2(metar.getVisibility() == CLength(10, CLengthUnit::SM()), "Failed to parse visibility");
121  QVERIFY2(metar.getTemperature() == CTemperature(28, CTemperatureUnit::C()), "Failed to parse temperature");
122  QVERIFY2(metar.getDewPoint() == CTemperature(17, CTemperatureUnit::C()), "Failed to parse dew point");
123  QVERIFY2(metar.getAltimeter() == CPressure(30.22, CPressureUnit::inHg()), "Failed to parse altimeter");
124 
125  auto presentWeatherList = metar.getPresentWeather();
126  QVERIFY2(presentWeatherList.size() == 1, "Present weather has an incorrect size");
127  auto presentWeather = presentWeatherList.frontOrDefault();
128  QVERIFY2(presentWeather.getIntensity() == CPresentWeather::Light, "Itensity should be light");
129  QVERIFY2(presentWeather.getDescriptor() == CPresentWeather::Showers, "Descriptor should be showers");
130  QVERIFY2(presentWeather.getWeatherPhenomena() & CPresentWeather::Rain,
131  "Weather phenomina 'rain' should be set");
132  QVERIFY2((presentWeather.getWeatherPhenomena() & CPresentWeather::Snow) == 0,
133  "Weather phenomina 'Snow' should NOT be set");
134 
135  auto cloudLayers = metar.getCloudLayers();
136  QVERIFY2(cloudLayers.containsBase(CAltitude(4500, CAltitude::AboveGround, CLengthUnit::ft())),
137  "Cloud layer 4500 ft missing");
138  QVERIFY2(cloudLayers.containsBase(CAltitude(22000, CAltitude::AboveGround, CLengthUnit::ft())),
139  "Cloud layer 22000 ft missing");
140  QVERIFY2(cloudLayers.containsBase(CAltitude(30000, CAltitude::AboveGround, CLengthUnit::ft())),
141  "Cloud layer 30000 ft missing");
142  QVERIFY2(cloudLayers.findByBase(CAltitude(4500, CAltitude::AboveGround, CLengthUnit::ft())).getCoverage() ==
143  CCloudLayer::Few,
144  "Failed to parse cloud layer in 4500 ft");
145  QVERIFY2(cloudLayers.findByBase(CAltitude(22000, CAltitude::AboveGround, CLengthUnit::ft())).getCoverage() ==
146  CCloudLayer::Scattered,
147  "Failed to parse cloud layer in 22000 ft");
148  QVERIFY2(cloudLayers.findByBase(CAltitude(30000, CAltitude::AboveGround, CLengthUnit::ft())).getCoverage() ==
149  CCloudLayer::Scattered,
150  "Failed to parse cloud layer in 30000 ft");
151 
152  CMetar metar2 = metarDecoder.decode("EDDM 241753Z 20009G11KT 9000NDV FEW045 SCT220 SCT300 ///// Q1013");
153  QVERIFY2(metar2.getAirportIcaoCode() == CAirportIcaoCode("EDDM"), "Failed to parse airport code");
154  QVERIFY2(metar2.getDay() == 24, "Failed to parse day of report");
155  QVERIFY2(metar2.getTime() == CTime(17, 53, 0), "Failed to parse time of report");
156  QVERIFY2(metar2.getWindLayer().getDirection() == CAngle(200, CAngleUnit::deg()),
157  "Failed to parse wind direction");
158  QVERIFY2(metar2.getWindLayer().getSpeed() == CSpeed(9, CSpeedUnit::kts()), "Failed to parse wind speed");
159  QVERIFY2(metar2.getWindLayer().getGustSpeed() == CSpeed(11, CSpeedUnit::kts()),
160  "Wind gust speed should be null");
161  QVERIFY2(metar2.getVisibility() == CLength(9000, CLengthUnit::m()), "Failed to parse visibility");
162  QVERIFY2(metar2.getTemperature() == CTemperature(0, CTemperatureUnit::C()), "Failed to parse temperature");
163  QVERIFY2(metar2.getDewPoint() == CTemperature(0, CTemperatureUnit::C()), "Failed to parse dew point");
164  QVERIFY2(metar2.getAltimeter() == CPressure(1013, CPressureUnit::hPa()), "Failed to parse altimeter");
165 
166  auto presentWeatherList2 = metar2.getPresentWeather();
167  QVERIFY2(presentWeatherList2.size() == 0, "Present weather has an incorrect size");
168 
169  auto cloudLayers2 = metar2.getCloudLayers();
170  QVERIFY2(cloudLayers2.containsBase(CAltitude(4500, CAltitude::AboveGround, CLengthUnit::ft())),
171  "Cloud layer 4500 ft missing");
172  QVERIFY2(cloudLayers2.containsBase(CAltitude(22000, CAltitude::AboveGround, CLengthUnit::ft())),
173  "Cloud layer 22000 ft missing");
174  QVERIFY2(cloudLayers2.containsBase(CAltitude(30000, CAltitude::AboveGround, CLengthUnit::ft())),
175  "Cloud layer 30000 ft missing");
176  QVERIFY2(cloudLayers2.findByBase(CAltitude(4500, CAltitude::AboveGround, CLengthUnit::ft())).getCoverage() ==
177  CCloudLayer::Few,
178  "Failed to parse cloud layer in 4500 ft");
179  QVERIFY2(cloudLayers2.findByBase(CAltitude(22000, CAltitude::AboveGround, CLengthUnit::ft())).getCoverage() ==
180  CCloudLayer::Scattered,
181  "Failed to parse cloud layer in 22000 ft");
182  QVERIFY2(cloudLayers2.findByBase(CAltitude(30000, CAltitude::AboveGround, CLengthUnit::ft())).getCoverage() ==
183  CCloudLayer::Scattered,
184  "Failed to parse cloud layer in 30000 ft");
185  }
186 
187 } // namespace MiscTest
188 
191 
192 #include "testweather.moc"
193 
Weather unit tests.
Definition: testweather.cpp:40
Value object encapsulating information of airport ICAO data.
Altitude as used in aviation, can be AGL or MSL altitude.
Definition: altitude.h:52
Physical unit angle (radians, degrees)
Definition: angle.h:23
Physical unit length (length)
Definition: length.h:18
Value object for a cloud layer.
Definition: cloudlayer.h:27
Value object encapsulating a set of cloud layers.
CMetar decode(const QString &metarString) const
Decode metar.
Value object encapsulating information about METAR FIXME: runway visibilities FIXME: runway wind shea...
Definition: metar.h:38
const CPresentWeatherList & getPresentWeather() const
Get present weather list.
Definition: metar.h:105
CWindLayer getWindLayer() const
Get wind layer.
Definition: metar.h:93
const physical_quantities::CTime & getTime() const
Get report time.
Definition: metar.h:78
const physical_quantities::CPressure & getAltimeter() const
Get altimeter.
Definition: metar.h:132
physical_quantities::CLength getVisibility() const
Get visibility.
Definition: metar.cpp:48
const physical_quantities::CTemperature & getDewPoint() const
Get dew point.
Definition: metar.h:126
int getDay() const
Get report day.
Definition: metar.h:75
physical_quantities::CTemperature getTemperature() const
Get temperature.
Definition: metar.cpp:59
const CCloudLayerList & getCloudLayers() const
Get all cloud layers.
Definition: metar.h:111
const aviation::CAirportIcaoCode & getAirportIcaoCode() const
Get airport icao code.
Definition: metar.h:69
Value object for a wind layer.
Definition: windlayer.h:28
physical_quantities::CSpeed getGustSpeed() const
Get weather phenomenas.
Definition: windlayer.h:98
physical_quantities::CSpeed getSpeed() const
Get descriptor.
Definition: windlayer.h:92
physical_quantities::CAngle getDirection() const
Get direction.
Definition: windlayer.h:74
Value object encapsulating a set of wind layers.
Definition: windlayerlist.h:35
SWIFTTEST_APPLESS_MAIN(MiscTest::CTestWeather)
main