File indexing completed on 2024-05-12 04:42:45

0001 /*
0002     SPDX-FileCopyrightText: 2020 Volker Krause <vkrause@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "rentalvehicle.h"
0008 #include "datatypes_p.h"
0009 #include "json_p.h"
0010 
0011 #include <QMetaEnum>
0012 
0013 using namespace KPublicTransport;
0014 
0015 namespace KPublicTransport {
0016 class RentalVehicleNetworkPrivate : public QSharedData
0017 {
0018 public:
0019     QString name;
0020     RentalVehicle::VehicleTypes vehicleTypes = RentalVehicle::Unknown;
0021 };
0022 
0023 class RentalVehicleStationPrivate : public QSharedData
0024 {
0025 public:
0026     int availableVehicles = -1;
0027     int capacity = -1;
0028     RentalVehicleNetwork network;
0029     std::vector<int> capacities;
0030     std::vector<int> availabilities;
0031 };
0032 
0033 class RentalVehiclePrivate : public QSharedData
0034 {
0035 public:
0036     RentalVehicle::VehicleType type = RentalVehicle::Unknown;
0037     int remainingRange = -1;
0038     KPublicTransport::RentalVehicleNetwork network;
0039 };
0040 }
0041 
0042 KPUBLICTRANSPORT_MAKE_GADGET(RentalVehicleNetwork)
0043 KPUBLICTRANSPORT_MAKE_PROPERTY(RentalVehicleNetwork, QString, name, setName)
0044 KPUBLICTRANSPORT_MAKE_PROPERTY(RentalVehicleNetwork, RentalVehicle::VehicleTypes, vehicleTypes, setVehicleTypes)
0045 
0046 bool RentalVehicleNetwork::isValid() const
0047 {
0048     return !d->name.isEmpty();
0049 }
0050 
0051 /** Checks if two instances refer to the same network. */
0052 bool RentalVehicleNetwork::isSame(const RentalVehicleNetwork &lhs, const RentalVehicleNetwork &rhs)
0053 {
0054     return lhs.name() == rhs.name();
0055 }
0056 
0057 QJsonObject RentalVehicleNetwork::toJson(const RentalVehicleNetwork &network)
0058 {
0059     return Json::toJson(network);
0060 }
0061 
0062 RentalVehicleNetwork RentalVehicleNetwork::fromJson(const QJsonObject &obj)
0063 {
0064     return Json::fromJson<RentalVehicleNetwork>(obj);
0065 }
0066 
0067 KPUBLICTRANSPORT_MAKE_GADGET(RentalVehicleStation)
0068 KPUBLICTRANSPORT_MAKE_PROPERTY(RentalVehicleStation, int, availableVehicles, setAvailableVehicles)
0069 KPUBLICTRANSPORT_MAKE_PROPERTY(RentalVehicleStation, int, capacity, setCapacity)
0070 KPUBLICTRANSPORT_MAKE_PROPERTY(RentalVehicleStation, RentalVehicleNetwork, network, setNetwork)
0071 
0072 bool RentalVehicleStation::isValid() const
0073 {
0074     return d->network.isValid() || d->capacity >= 0 || d->availableVehicles >= 0;
0075 }
0076 
0077 RentalVehicle::VehicleTypes RentalVehicleStation::supportedVehicleTypes() const
0078 {
0079     RentalVehicle::VehicleTypes types = {};
0080     const auto me = QMetaEnum::fromType<RentalVehicle::VehicleType>();
0081     for (auto i = 0; i < me.keyCount() && i < (int)d->capacities.size(); ++i) {
0082         if (d->capacities[i] >= 0) {
0083             types |= (RentalVehicle::VehicleType)me.value(i);
0084         }
0085     }
0086     return types | availableVehicleTypes();
0087 }
0088 
0089 RentalVehicle::VehicleTypes KPublicTransport::RentalVehicleStation::availableVehicleTypes() const
0090 {
0091     RentalVehicle::VehicleTypes types = {};
0092     const auto me = QMetaEnum::fromType<RentalVehicle::VehicleType>();
0093     for (auto i = 0; i < me.keyCount() && i < (int)d->availabilities.size(); ++i) {
0094         if (d->availabilities[i] >= 0) {
0095             types |= (RentalVehicle::VehicleType)me.value(i);
0096         }
0097     }
0098     return types;
0099 }
0100 
0101 int RentalVehicleStation::capacity(RentalVehicle::VehicleType type) const
0102 {
0103     const auto me = QMetaEnum::fromType<RentalVehicle::VehicleType>();
0104     for (auto i = 0; i < me.keyCount() && i < (int)d->capacities.size(); ++i) {
0105         if (me.value(i) == type) {
0106             return d->capacities[i];
0107         }
0108     }
0109     return -1;
0110 }
0111 
0112 void RentalVehicleStation::setCapacity(RentalVehicle::VehicleType type, int capacity)
0113 {
0114     const auto me = QMetaEnum::fromType<RentalVehicle::VehicleType>();
0115     for (auto i = 0; i < me.keyCount(); ++i) {
0116         if (me.value(i) != type) {
0117             continue;
0118         }
0119         d->capacities.resize(std::max(d->capacities.size(), (std::size_t)(i + 1)), -1);
0120         d->capacities[i] = capacity;
0121         return;
0122     }
0123 }
0124 
0125 int RentalVehicleStation::availableVehicles(RentalVehicle::VehicleType type) const
0126 {
0127     const auto me = QMetaEnum::fromType<RentalVehicle::VehicleType>();
0128     for (auto i = 0; i < me.keyCount() && i < (int)d->availabilities.size(); ++i) {
0129         if (me.value(i) == type) {
0130             return d->availabilities[i];
0131         }
0132     }
0133     return -1;
0134 }
0135 
0136 void RentalVehicleStation::setAvailableVehicles(RentalVehicle::VehicleType type, int count)
0137 {
0138     const auto me = QMetaEnum::fromType<RentalVehicle::VehicleType>();
0139     for (auto i = 0; i < me.keyCount(); ++i) {
0140         if (me.value(i) != type) {
0141             continue;
0142         }
0143         d->availabilities.resize(std::max(d->availabilities.size(), (std::size_t)(i + 1)), -1);
0144         d->availabilities[i] = count;
0145         return;
0146     }
0147 }
0148 
0149 bool RentalVehicleStation::isSame(const RentalVehicleStation &lhs, const RentalVehicleStation &rhs)
0150 {
0151     return RentalVehicleNetwork::isSame(lhs.network(), rhs.network());
0152 }
0153 
0154 static QJsonValue typeVectorToJson(const std::vector<int> &v)
0155 {
0156     if (v.empty()) {
0157         return {};
0158     }
0159     QJsonObject obj;
0160     const auto me = QMetaEnum::fromType<RentalVehicle::VehicleType>();
0161     for (auto i = 0; i < me.keyCount() && i < (int)v.size(); ++i) {
0162         if (v[i] < 0) {
0163             continue;
0164         }
0165         obj.insert(QLatin1String(me.key(i)), v[i]);
0166     }
0167     return obj.isEmpty() ? QJsonValue() : obj;
0168 }
0169 
0170 QJsonObject RentalVehicleStation::toJson(const RentalVehicleStation &station)
0171 {
0172     auto obj = Json::toJson(station);
0173     if (station.network().isValid()) {
0174         obj.insert(QLatin1String("network"), RentalVehicleNetwork::toJson(station.network()));
0175     }
0176     auto v = typeVectorToJson(station.d->capacities);
0177     if (v.isObject()) {
0178         obj.insert(QLatin1String("capacitiesByType"), v);
0179     }
0180     v = typeVectorToJson(station.d->availabilities);
0181     if (v.isObject()) {
0182         obj.insert(QLatin1String("availabilitiesByType"), v);
0183     }
0184     return obj;
0185 }
0186 
0187 static std::vector<int> typeVectorFromJson(const QJsonValue &v)
0188 {
0189     std::vector<int> out;
0190     const auto obj = v.toObject();
0191     if (obj.isEmpty()) {
0192         return out;
0193     }
0194 
0195     const auto me = QMetaEnum::fromType<RentalVehicle::VehicleType>();
0196     for (auto i = 0; i < me.keyCount(); ++i) {
0197         const auto it = obj.find(QLatin1String(me.key(i)));
0198         if (it == obj.end()) {
0199             continue;
0200         }
0201         out.resize(i + 1, -1);
0202         out[i] = it.value().toInt();
0203     }
0204 
0205     return out;
0206 }
0207 
0208 RentalVehicleStation RentalVehicleStation::fromJson(const QJsonObject &obj)
0209 {
0210     auto station = Json::fromJson<RentalVehicleStation>(obj);
0211     station.setNetwork(RentalVehicleNetwork::fromJson(obj.value(QLatin1String("network")).toObject()));
0212     station.d->capacities = typeVectorFromJson(obj.value(QLatin1String("capacitiesByType")));
0213     station.d->availabilities = typeVectorFromJson(obj.value(QLatin1String("availabilitiesByType")));
0214     return station;
0215 }
0216 
0217 KPUBLICTRANSPORT_MAKE_GADGET(RentalVehicle)
0218 KPUBLICTRANSPORT_MAKE_PROPERTY(RentalVehicle, RentalVehicle::VehicleType, type, setType)
0219 KPUBLICTRANSPORT_MAKE_PROPERTY(RentalVehicle, int, remainingRange, setRemainingRange)
0220 KPUBLICTRANSPORT_MAKE_PROPERTY(RentalVehicle, RentalVehicleNetwork, network, setNetwork)
0221 
0222 QJsonObject RentalVehicle::toJson(const RentalVehicle &vehicle)
0223 {
0224     auto obj = Json::toJson(vehicle);
0225     if (vehicle.d->remainingRange < 0) {
0226         obj.remove(QLatin1String("remainingRange"));
0227     }
0228     if (vehicle.network().isValid()) {
0229         obj.insert(QLatin1String("network"), RentalVehicleNetwork::toJson(vehicle.network()));
0230     }
0231     return obj;
0232 }
0233 
0234 RentalVehicle RentalVehicle::fromJson(const QJsonObject &obj)
0235 {
0236     auto v = Json::fromJson<RentalVehicle>(obj);
0237     v.setNetwork(RentalVehicleNetwork::fromJson(obj.value(QLatin1String("network")).toObject()));
0238     return v;
0239 }
0240 
0241 #include "moc_rentalvehicle.cpp"