File indexing completed on 2024-04-28 04:42:42

0001 /*
0002  * SPDX-FileCopyrightText: 2020-2021 Han Young <hanyoung@protonmail.com>
0003  * SPDX-FileCopyrightText: 2020 Devin Lin <espidev@gmail.com>
0004  *
0005  * SPDX-License-Identifier: LGPL-2.0-or-later
0006  */
0007 #include "hourlyweatherforecast.h"
0008 
0009 #include <cmath>
0010 
0011 namespace KWeatherCore
0012 {
0013 class HourlyWeatherForecast::HourlyWeatherForecastPrivate
0014 {
0015 public:
0016     QDateTime date = QDateTime::currentDateTime();
0017     QString weatherDescription = QStringLiteral("Unknown");
0018     QString weatherIcon = QStringLiteral("weather-none-available");
0019     // weather icon without time of day
0020     QString neutralWeatherIcon = QStringLiteral("weather-none-available");
0021     QString symbolCode;
0022     double temperature = 0; // celsius
0023     double pressure = 0; // hPa
0024     double windDirection = NAN;
0025     double windSpeed = 0; // m/s
0026     double humidity = 0; // %
0027     double fog = 0; // %
0028     double uvIndex = 0; // 0-1
0029     double precipitationAmount = 0; // mm
0030 };
0031 HourlyWeatherForecast::HourlyWeatherForecast(const QDateTime &date)
0032     : d(std::make_unique<HourlyWeatherForecastPrivate>())
0033 {
0034     d->date = date;
0035 }
0036 HourlyWeatherForecast::HourlyWeatherForecast(HourlyWeatherForecast &&other) = default;
0037 HourlyWeatherForecast::~HourlyWeatherForecast() = default;
0038 
0039 HourlyWeatherForecast::HourlyWeatherForecast()
0040     : d(std::make_unique<HourlyWeatherForecastPrivate>())
0041 {
0042 }
0043 
0044 HourlyWeatherForecast::HourlyWeatherForecast(const HourlyWeatherForecast &other)
0045     : d(std::make_unique<HourlyWeatherForecastPrivate>())
0046 {
0047     *d = *other.d;
0048 }
0049 HourlyWeatherForecast &HourlyWeatherForecast::operator=(HourlyWeatherForecast &&other) = default;
0050 QJsonObject HourlyWeatherForecast::toJson() const
0051 {
0052     QJsonObject obj;
0053     obj[QLatin1String("date")] = date().toString(Qt::ISODate);
0054     obj[QLatin1String("weatherDescription")] = weatherDescription();
0055     obj[QLatin1String("weatherIcon")] = weatherIcon();
0056     obj[QLatin1String("neutralWeatherIcon")] = neutralWeatherIcon();
0057     obj[QLatin1String("temperature")] = temperature();
0058     obj[QLatin1String("pressure")] = pressure();
0059     obj[QLatin1String("windDirectionDegree")] = windDirectionDegree();
0060     obj[QLatin1String("windSpeed")] = windSpeed();
0061     obj[QLatin1String("humidity")] = humidity();
0062     obj[QLatin1String("fog")] = fog();
0063     obj[QLatin1String("uvIndex")] = uvIndex();
0064     obj[QLatin1String("precipitationAmount")] = precipitationAmount();
0065     return obj;
0066 }
0067 HourlyWeatherForecast HourlyWeatherForecast::fromJson(const QJsonObject &obj)
0068 {
0069     HourlyWeatherForecast ret(QDateTime::fromString(obj[QLatin1String("date")].toString(), Qt::ISODate));
0070     ret.setWeatherDescription(obj[QLatin1String("weatherDescription")].toString());
0071     ret.setWeatherIcon(obj[QLatin1String("weatherIcon")].toString());
0072     ret.setNeutralWeatherIcon(obj[QLatin1String("neutralWeatherIcon")].toString());
0073     ret.setTemperature(obj[QLatin1String("temperature")].toDouble());
0074     ret.setPressure(obj[QLatin1String("pressure")].toDouble());
0075     ret.setWindDirectionDegree(obj[QLatin1String("windDirectionDegree")].toDouble(NAN));
0076     ret.setWindSpeed(obj[QLatin1String("windSpeed")].toDouble());
0077     ret.setHumidity(obj[QLatin1String("humidity")].toDouble());
0078     ret.setFog(obj[QLatin1String("fog")].toDouble());
0079     ret.setUvIndex(obj[QLatin1String("uvIndex")].toDouble());
0080     ret.setPrecipitationAmount(obj[QLatin1String("precipitationAmount")].toDouble());
0081     return ret;
0082 }
0083 const QDateTime &HourlyWeatherForecast::date() const
0084 {
0085     return d->date;
0086 }
0087 void HourlyWeatherForecast::setDate(const QDateTime &date)
0088 {
0089     d->date = std::move(date);
0090 }
0091 const QString &HourlyWeatherForecast::weatherDescription() const
0092 {
0093     return d->weatherDescription;
0094 }
0095 void HourlyWeatherForecast::setWeatherDescription(const QString &weatherDescription)
0096 {
0097     d->weatherDescription = weatherDescription;
0098 }
0099 const QString &HourlyWeatherForecast::weatherIcon() const
0100 {
0101     return d->weatherIcon;
0102 }
0103 void HourlyWeatherForecast::setWeatherIcon(const QString &weatherIcon)
0104 {
0105     d->weatherIcon = weatherIcon;
0106 }
0107 const QString &HourlyWeatherForecast::neutralWeatherIcon() const
0108 {
0109     return d->neutralWeatherIcon;
0110 }
0111 void HourlyWeatherForecast::setNeutralWeatherIcon(const QString &neutralWeatherIcon)
0112 {
0113     d->neutralWeatherIcon = neutralWeatherIcon;
0114 }
0115 const QString &HourlyWeatherForecast::symbolCode() const
0116 {
0117     return d->symbolCode;
0118 }
0119 void HourlyWeatherForecast::setSymbolCode(const QString &symbolCode)
0120 {
0121     d->symbolCode = symbolCode;
0122 }
0123 double HourlyWeatherForecast::temperature() const
0124 {
0125     return d->temperature;
0126 }
0127 void HourlyWeatherForecast::setTemperature(double temperature)
0128 {
0129     d->temperature = temperature;
0130 }
0131 double HourlyWeatherForecast::pressure() const
0132 {
0133     return d->pressure;
0134 }
0135 void HourlyWeatherForecast::setPressure(double pressure)
0136 {
0137     d->pressure = pressure;
0138 }
0139 
0140 double HourlyWeatherForecast::windDirectionDegree() const
0141 {
0142     return d->windDirection;
0143 }
0144 
0145 void HourlyWeatherForecast::setWindDirectionDegree(double windDirection)
0146 {
0147     d->windDirection = windDirection;
0148 }
0149 
0150 // sorted by degree for use with std::lower_bound
0151 struct {
0152     float degree;
0153     WindDirection direction;
0154 } static constexpr const cardinal_direction_map[] = {{22.5, WindDirection::N},
0155                                                      {67.5, WindDirection::NE},
0156                                                      {112.5, WindDirection::E},
0157                                                      {157.5, WindDirection::SE},
0158                                                      {202.5, WindDirection::S},
0159                                                      {247.5, WindDirection::SW},
0160                                                      {292.5, WindDirection::W},
0161                                                      {337.5, WindDirection::NW},
0162                                                      {360.0, WindDirection::N}};
0163 
0164 WindDirection HourlyWeatherForecast::windDirectionCardinal() const
0165 {
0166     const auto it = std::lower_bound(std::begin(cardinal_direction_map), std::end(cardinal_direction_map), d->windDirection, [](const auto &entry, double deg) {
0167         return entry.degree <= deg;
0168     });
0169     if (it != std::end(cardinal_direction_map)) {
0170         return (*it).direction;
0171     }
0172     return {};
0173 }
0174 
0175 double HourlyWeatherForecast::windSpeed() const
0176 {
0177     return d->windSpeed;
0178 }
0179 void HourlyWeatherForecast::setWindSpeed(double windSpeed)
0180 {
0181     d->windSpeed = windSpeed;
0182 }
0183 double HourlyWeatherForecast::humidity() const
0184 {
0185     return d->humidity;
0186 }
0187 void HourlyWeatherForecast::setHumidity(double humidity)
0188 {
0189     d->humidity = humidity;
0190 }
0191 double HourlyWeatherForecast::fog() const
0192 {
0193     return d->fog;
0194 }
0195 void HourlyWeatherForecast::setFog(double fog)
0196 {
0197     d->fog = fog;
0198 }
0199 double HourlyWeatherForecast::uvIndex() const
0200 {
0201     return d->uvIndex;
0202 }
0203 void HourlyWeatherForecast::setUvIndex(double uvIndex)
0204 {
0205     d->uvIndex = uvIndex;
0206 }
0207 double HourlyWeatherForecast::precipitationAmount() const
0208 {
0209     return d->precipitationAmount;
0210 }
0211 void HourlyWeatherForecast::setPrecipitationAmount(double precipitationAmount)
0212 {
0213     d->precipitationAmount = precipitationAmount;
0214 }
0215 bool HourlyWeatherForecast::operator==(const KWeatherCore::HourlyWeatherForecast &rhs) const
0216 {
0217     return (weatherDescription() == rhs.weatherDescription() && weatherIcon() == rhs.weatherIcon() && date() == rhs.date());
0218 }
0219 
0220 HourlyWeatherForecast &HourlyWeatherForecast::operator=(const HourlyWeatherForecast &other)
0221 {
0222     *d = *other.d;
0223     return *this;
0224 }
0225 }
0226 
0227 #include "moc_hourlyweatherforecast.cpp"