File indexing completed on 2024-05-05 16:49:23

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 "weatherforecast.h"
0008 #include <QJsonArray>
0009 namespace KWeatherCore
0010 {
0011 class WeatherForecast::WeatherForecastPrivate
0012 {
0013 public:
0014     std::vector<DailyWeatherForecast> dailyWeatherForecast;
0015     QString timezone;
0016     double latitude, longitude;
0017     QDateTime createdTime = QDateTime::currentDateTime();
0018 };
0019 
0020 WeatherForecast::WeatherForecast()
0021     : d(std::make_unique<WeatherForecastPrivate>())
0022 {
0023 }
0024 WeatherForecast::WeatherForecast(const WeatherForecast &other)
0025     : QSharedData(QSharedData())
0026     , d(std::make_unique<WeatherForecastPrivate>())
0027 {
0028     *d = *other.d;
0029 }
0030 WeatherForecast::WeatherForecast(WeatherForecast &&other) = default;
0031 WeatherForecast::~WeatherForecast() = default;
0032 WeatherForecast &WeatherForecast::operator=(const WeatherForecast &other)
0033 {
0034     *d = *other.d;
0035     return *this;
0036 }
0037 QJsonObject WeatherForecast::toJson() const
0038 {
0039     QJsonObject obj;
0040     QJsonArray dayArray;
0041     for (auto d : dailyWeatherForecast()) {
0042         dayArray.append(d.toJson());
0043     }
0044     obj[QStringLiteral("day")] = dayArray;
0045     obj[QStringLiteral("lat")] = latitude();
0046     obj[QStringLiteral("lon")] = longitude();
0047     obj[QStringLiteral("timezone")] = timezone();
0048     return obj;
0049 }
0050 QExplicitlySharedDataPointer<WeatherForecast>
0051 WeatherForecast::fromJson(QJsonObject obj)
0052 {
0053     auto w = QExplicitlySharedDataPointer<WeatherForecast>(new WeatherForecast);
0054     std::vector<DailyWeatherForecast> dayVec;
0055     const auto &array = obj[QStringLiteral("day")].toArray();
0056     for (const auto &d : array) {
0057         dayVec.push_back(DailyWeatherForecast::fromJson(d.toObject()));
0058     }
0059     w->setDailyWeatherForecast(dayVec);
0060     w->setCoordinate(obj[QStringLiteral("lat")].toDouble(),
0061                      obj[QStringLiteral("lon")].toDouble());
0062     w->setTimezone(obj[QStringLiteral("timezone")].toString());
0063     return w;
0064 }
0065 const std::vector<DailyWeatherForecast> &
0066 WeatherForecast::dailyWeatherForecast() const
0067 {
0068     return d->dailyWeatherForecast;
0069 }
0070 double WeatherForecast::latitude() const
0071 {
0072     return d->latitude;
0073 }
0074 double WeatherForecast::longitude() const
0075 {
0076     return d->longitude;
0077 }
0078 const QDateTime &WeatherForecast::createdTime() const
0079 {
0080     return d->createdTime;
0081 }
0082 const QString &WeatherForecast::timezone() const
0083 {
0084     return d->timezone;
0085 }
0086 void WeatherForecast::setCoordinate(double latitude, double longitude)
0087 {
0088     d->latitude = latitude;
0089     d->longitude = longitude;
0090 }
0091 void WeatherForecast::setTimezone(QString timezone)
0092 {
0093     d->timezone = std::move(timezone);
0094 }
0095 void WeatherForecast::setDailyWeatherForecast(
0096     const std::vector<DailyWeatherForecast> &forecast)
0097 {
0098     d->dailyWeatherForecast = forecast;
0099 }
0100 void WeatherForecast::setDailyWeatherForecast(
0101     std::vector<DailyWeatherForecast> &&forecast)
0102 {
0103     d->dailyWeatherForecast = std::move(forecast);
0104 }
0105 void WeatherForecast::setSunriseForecast(const std::vector<Sunrise> &sunrise)
0106 {
0107     int i = 0, range = sunrise.size();
0108     for (auto &day : d->dailyWeatherForecast) {
0109         if (i >= range)
0110             break;
0111         day.setSunrise(sunrise.at(i));
0112         ++i;
0113     }
0114 }
0115 void WeatherForecast::setSunriseForecast(std::vector<Sunrise> &&sunrise)
0116 {
0117     int i = 0, range = sunrise.size();
0118     for (auto day : d->dailyWeatherForecast) {
0119         if (i >= range)
0120             break;
0121         // if on the same day, add sunrise to day
0122         if (day.date().daysTo(sunrise.at(i).sunRise().date()) == 0) {
0123             day.setSunrise(std::move(sunrise[i]));
0124             ++i;
0125         }
0126     }
0127 }
0128 WeatherForecast &
0129 WeatherForecast::operator+=(const DailyWeatherForecast &forecast)
0130 {
0131     for (int i = dailyWeatherForecast().size() - 1; i >= 0; --i) {
0132         if (dailyWeatherForecast().at(i) == forecast) {
0133             d->dailyWeatherForecast[i] += forecast;
0134             return *this;
0135         }
0136     }
0137 
0138     // if not find, append it at end
0139     d->dailyWeatherForecast.push_back(forecast);
0140     return *this;
0141 }
0142 WeatherForecast &WeatherForecast::operator+=(DailyWeatherForecast &&forecast)
0143 {
0144     for (int i = dailyWeatherForecast().size() - 1; i >= 0; --i) {
0145         if (dailyWeatherForecast().at(i) == forecast) {
0146             d->dailyWeatherForecast[i] += forecast;
0147             return *this;
0148         }
0149     }
0150 
0151     // if not find, append it at end
0152     d->dailyWeatherForecast.push_back(std::move(forecast));
0153     return *this;
0154 }
0155 WeatherForecast &
0156 WeatherForecast::operator+=(const HourlyWeatherForecast &forecast)
0157 {
0158     for (int i = dailyWeatherForecast().size() - 1; i >= 0; --i) {
0159         if (dailyWeatherForecast().at(i).date().isValid() &&
0160             dailyWeatherForecast().at(i).date().daysTo(
0161                 forecast.date().date()) == 0) {
0162             d->dailyWeatherForecast[i] += forecast;
0163             return *this;
0164         } else {
0165             break;
0166         }
0167     }
0168 
0169     // if not find, append it at end
0170     DailyWeatherForecast newDay;
0171     newDay += forecast;
0172     d->dailyWeatherForecast.push_back(std::move(newDay));
0173     return *this;
0174 }
0175 WeatherForecast &WeatherForecast::operator+=(HourlyWeatherForecast &&forecast)
0176 {
0177     for (int i = dailyWeatherForecast().size() - 1; i >= 0; --i) {
0178         if (dailyWeatherForecast().at(i).date().daysTo(
0179                 forecast.date().date()) == 0) {
0180             d->dailyWeatherForecast[i] += std::move(forecast);
0181             return *this;
0182         }
0183     }
0184 
0185     // if not find, append it at end
0186     auto newDay = DailyWeatherForecast();
0187     newDay += forecast;
0188     d->dailyWeatherForecast.push_back(std::move(newDay));
0189     return *this;
0190 }
0191 
0192 }