File indexing completed on 2024-05-12 04:42:46
0001 /* 0002 SPDX-FileCopyrightText: 2019 Volker Krause <vkrause@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "vehicle.h" 0008 #include "json_p.h" 0009 #include "datatypes_p.h" 0010 #include "mergeutil_p.h" 0011 0012 #include <QDebug> 0013 #include <QMetaEnum> 0014 #include <QVariant> 0015 0016 #include <limits> 0017 0018 using namespace KPublicTransport; 0019 0020 namespace KPublicTransport { 0021 0022 class VehicleSectionPrivate : public QSharedData 0023 { 0024 public: 0025 QString name; 0026 float platformPositionBegin = -1.0; 0027 float platformPositionEnd = -1.0; 0028 VehicleSection::Type type = VehicleSection::UnknownType; 0029 VehicleSection::Classes classes = VehicleSection::UnknownClass; 0030 VehicleSection::Features features = VehicleSection::NoFeatures; 0031 int deckCount = 1; 0032 VehicleSection::Sides connectedSides = VehicleSection::Front | VehicleSection::Back; 0033 QString platformSectionName; 0034 }; 0035 0036 class VehiclePrivate : public QSharedData 0037 { 0038 public: 0039 QString name; 0040 std::vector<VehicleSection> sections; 0041 Vehicle::Direction direction = Vehicle::UnknownDirection; 0042 }; 0043 0044 } 0045 0046 KPUBLICTRANSPORT_MAKE_GADGET(VehicleSection) 0047 KPUBLICTRANSPORT_MAKE_PROPERTY(VehicleSection, QString, name, setName) 0048 KPUBLICTRANSPORT_MAKE_PROPERTY(VehicleSection, float, platformPositionBegin, setPlatformPositionBegin) 0049 KPUBLICTRANSPORT_MAKE_PROPERTY(VehicleSection, float, platformPositionEnd, setPlatformPositionEnd) 0050 KPUBLICTRANSPORT_MAKE_PROPERTY(VehicleSection, VehicleSection::Type, type, setType) 0051 KPUBLICTRANSPORT_MAKE_PROPERTY(VehicleSection, VehicleSection::Classes, classes, setClasses) 0052 KPUBLICTRANSPORT_MAKE_PROPERTY(VehicleSection, VehicleSection::Features, features, setFeatures) 0053 KPUBLICTRANSPORT_MAKE_PROPERTY(VehicleSection, int, deckCount, setDeckCount) 0054 KPUBLICTRANSPORT_MAKE_PROPERTY(VehicleSection, VehicleSection::Sides, connectedSides, setConnectedSides) 0055 KPUBLICTRANSPORT_MAKE_PROPERTY(VehicleSection, QString, platformSectionName, setPlatformSectionName) 0056 0057 VehicleSection VehicleSection::merge(const VehicleSection &lhs, const VehicleSection &rhs) 0058 { 0059 if (lhs.name() != rhs.name()) { // safety check, as we don't properly check for equalness before merging yet 0060 return lhs; 0061 } 0062 0063 auto res = lhs; 0064 res.setPlatformPositionBegin(lhs.platformPositionBegin() < 0.0 ? rhs.platformPositionBegin() : lhs.platformPositionBegin()); 0065 res.setPlatformPositionEnd(lhs.platformPositionEnd() < 0.0 ? rhs.platformPositionEnd() : lhs.platformPositionEnd()); 0066 res.setType(std::max(lhs.type(), rhs.type())); 0067 if (res.type() == VehicleSection::PassengerCar && lhs.type() != VehicleSection::UnknownType && rhs.type() != VehicleSection::UnknownType) { 0068 res.setType(std::min(lhs.type(), rhs.type())); 0069 } 0070 res.setClasses(lhs.classes() | rhs.classes()); 0071 res.setFeatures(lhs.features() | rhs.features()); 0072 res.setDeckCount(std::max(lhs.deckCount(), rhs.deckCount())); 0073 res.setConnectedSides(lhs.connectedSides() & rhs.connectedSides()); 0074 res.setPlatformSectionName(MergeUtil::mergeString(lhs.platformSectionName(), rhs.platformSectionName())); 0075 return res; 0076 } 0077 0078 QJsonObject VehicleSection::toJson(const VehicleSection §ion) 0079 { 0080 return Json::toJson(section); 0081 } 0082 0083 QJsonArray VehicleSection::toJson(const std::vector<VehicleSection> §ions) 0084 { 0085 return Json::toJson(sections); 0086 } 0087 0088 VehicleSection VehicleSection::fromJson(const QJsonObject &obj) 0089 { 0090 return Json::fromJson<VehicleSection>(obj); 0091 } 0092 0093 std::vector<VehicleSection> VehicleSection::fromJson(const QJsonArray &array) 0094 { 0095 return Json::fromJson<VehicleSection>(array); 0096 } 0097 0098 QVariantList VehicleSection::featureList() const 0099 { 0100 QVariantList l; 0101 const auto me = QMetaEnum::fromType<VehicleSection::Features>(); 0102 for (int i = 0; i < me.keyCount(); ++i) { 0103 if (features() & static_cast<VehicleSection::Feature>(1 << i)) 0104 l.push_back(static_cast<VehicleSection::Feature>(1 << i)); 0105 } 0106 return l; 0107 } 0108 0109 bool VehicleSection::hasPlatformPosition() const 0110 { 0111 return d->platformPositionBegin >= 0.0 && d->platformPositionEnd >= 0.0; 0112 } 0113 0114 KPUBLICTRANSPORT_MAKE_GADGET(Vehicle) 0115 KPUBLICTRANSPORT_MAKE_PROPERTY(Vehicle, QString, name, setName) 0116 KPUBLICTRANSPORT_MAKE_PROPERTY(Vehicle, Vehicle::Direction, direction, setDirection) 0117 0118 bool Vehicle::isEmpty() const 0119 { 0120 return d->name.isEmpty() && d->sections.empty() && d->direction == Vehicle::UnknownDirection; 0121 } 0122 0123 const std::vector<VehicleSection>& Vehicle::sections() const 0124 { 0125 return d->sections; 0126 } 0127 0128 std::vector<VehicleSection>&& Vehicle::takeSections() 0129 { 0130 d.detach(); 0131 return std::move(d->sections); 0132 } 0133 0134 void Vehicle::setSections(std::vector<VehicleSection> &§ions) 0135 { 0136 d.detach(); 0137 d->sections = std::move(sections); 0138 } 0139 0140 void Vehicle::setSections(const std::vector<VehicleSection> §ions) 0141 { 0142 d.detach(); 0143 d->sections = sections; 0144 } 0145 0146 QVariantList Vehicle::sectionsVariant() const 0147 { 0148 QVariantList l; 0149 l.reserve(d->sections.size()); 0150 std::transform(d->sections.begin(), d->sections.end(), std::back_inserter(l), [](const auto &sec) { return QVariant::fromValue(sec); }); 0151 return l; 0152 } 0153 0154 float Vehicle::platformPositionBegin() const 0155 { 0156 float p = std::numeric_limits<float>::max(); 0157 for (const auto §ion : sections()) { 0158 p = std::min(p, section.platformPositionBegin()); 0159 } 0160 return p; 0161 } 0162 0163 float Vehicle::platformPositionEnd() const 0164 { 0165 float p = -1.0f; 0166 for (const auto §ion : sections()) { 0167 p = std::max(p, section.platformPositionEnd()); 0168 } 0169 return p; 0170 } 0171 0172 float Vehicle::platformPositionForSection(const QString §ionName) const 0173 { 0174 for (const auto §ion : sections()) { 0175 if (section.name() == sectionName) { 0176 return (section.platformPositionBegin() + section.platformPositionEnd()) / 2.0f; 0177 } 0178 } 0179 return -1.0f; 0180 } 0181 0182 Vehicle Vehicle::merge(const Vehicle &lhs, const Vehicle &rhs) 0183 { 0184 Vehicle res; 0185 res.setDirection(lhs.direction() == Vehicle::UnknownDirection ? rhs.direction() : lhs.direction()); 0186 res.setName(MergeUtil::mergeString(lhs.name(), rhs.name())); 0187 0188 if (lhs.sections().size() == rhs.sections().size()) { 0189 std::vector<VehicleSection> secs; 0190 secs.reserve(lhs.sections().size()); 0191 for (std::size_t i = 0; i < lhs.sections().size(); ++i) { 0192 const auto &lhsSec = lhs.sections()[i]; 0193 const auto &rhsSec = rhs.sections()[i]; 0194 secs.push_back(VehicleSection::merge(lhsSec, rhsSec)); 0195 } 0196 res.setSections(std::move(secs)); 0197 } else { 0198 res.setSections(lhs.sections().size() < rhs.sections().size() ? rhs.sections() : lhs.sections()); 0199 } 0200 0201 return res; 0202 } 0203 0204 QJsonObject Vehicle::toJson(const Vehicle &vehicle) 0205 { 0206 auto obj = Json::toJson(vehicle); 0207 if (!vehicle.sections().empty()) { 0208 obj.insert(QLatin1String("sections"), VehicleSection::toJson(vehicle.sections())); 0209 } 0210 return obj; 0211 } 0212 0213 QJsonArray Vehicle::toJson(const std::vector<Vehicle> &vehicles) 0214 { 0215 return Json::toJson(vehicles); 0216 } 0217 0218 Vehicle Vehicle::fromJson(const QJsonObject &obj) 0219 { 0220 auto v = Json::fromJson<Vehicle>(obj); 0221 v.setSections(VehicleSection::fromJson(obj.value(QLatin1String("sections")).toArray())); 0222 return v; 0223 } 0224 0225 std::vector<Vehicle> Vehicle::fromJson(const QJsonArray &array) 0226 { 0227 return Json::fromJson<Vehicle>(array); 0228 } 0229 0230 bool Vehicle::hasPlatformPositions() const 0231 { 0232 return std::all_of(d->sections.begin(), d->sections.end(), [](const auto &p) { return p.hasPlatformPosition(); }); 0233 } 0234 0235 bool Vehicle::hasPlatformSectionNames() const 0236 { 0237 return std::none_of(d->sections.begin(), d->sections.end(), [](const auto &p) { return p.platformSectionName().isEmpty(); }); 0238 } 0239 0240 #include "moc_vehicle.cpp"