KPublicTransport

vehicle.cpp
1/*
2 SPDX-FileCopyrightText: 2019 Volker Krause <vkrause@kde.org>
3
4 SPDX-License-Identifier: LGPL-2.0-or-later
5*/
6
7#include "vehicle.h"
8#include "json_p.h"
9#include "datatypes_p.h"
10#include "featureutil_p.h"
11#include "mergeutil_p.h"
12
13#include <QDebug>
14#include <QMetaEnum>
15#include <QVariant>
16
17#include <limits>
18
19using namespace Qt::Literals::StringLiterals;
20using namespace KPublicTransport;
21
22namespace KPublicTransport {
23
24class VehicleSectionPrivate : public QSharedData
25{
26public:
27 QString name;
28 float platformPositionBegin = -1.0;
29 float platformPositionEnd = -1.0;
30 VehicleSection::Type type = VehicleSection::UnknownType;
31 VehicleSection::Classes classes = VehicleSection::UnknownClass;
32 int deckCount = 1;
33 VehicleSection::Sides connectedSides = VehicleSection::Front | VehicleSection::Back;
34 QString platformSectionName;
35 std::vector<Feature> sectionFeatures;
36 Disruption::Effect disruptionEffect = Disruption::NormalService;
38};
39
40class VehiclePrivate : public QSharedData
41{
42public:
43 QString name;
44 std::vector<VehicleSection> sections;
45 Vehicle::Direction direction = Vehicle::UnknownDirection;
46 std::vector<Feature> features;
47};
48
49}
50
51KPUBLICTRANSPORT_MAKE_GADGET(VehicleSection)
52KPUBLICTRANSPORT_MAKE_PROPERTY(VehicleSection, QString, name, setName)
53KPUBLICTRANSPORT_MAKE_PROPERTY(VehicleSection, float, platformPositionBegin, setPlatformPositionBegin)
54KPUBLICTRANSPORT_MAKE_PROPERTY(VehicleSection, float, platformPositionEnd, setPlatformPositionEnd)
55KPUBLICTRANSPORT_MAKE_PROPERTY(VehicleSection, VehicleSection::Type, type, setType)
56KPUBLICTRANSPORT_MAKE_PROPERTY(VehicleSection, VehicleSection::Classes, classes, setClasses)
57KPUBLICTRANSPORT_MAKE_PROPERTY(VehicleSection, int, deckCount, setDeckCount)
58KPUBLICTRANSPORT_MAKE_PROPERTY(VehicleSection, VehicleSection::Sides, connectedSides, setConnectedSides)
59KPUBLICTRANSPORT_MAKE_PROPERTY(VehicleSection, QString, platformSectionName, setPlatformSectionName)
60KPUBLICTRANSPORT_MAKE_PROPERTY(VehicleSection, KPublicTransport::Disruption::Effect, disruptionEffect, setDisruptionEffect)
61KPUBLICTRANSPORT_MAKE_PROPERTY(VehicleSection, KPublicTransport::Load::Category, load, setLoad)
62
63const std::vector<KPublicTransport::Feature>& VehicleSection::sectionFeatures() const
64{
65 return d->sectionFeatures;
66}
67
68std::vector<KPublicTransport::Feature>&& VehicleSection::takeSectionFeatures()
69{
70 return std::move(d->sectionFeatures);
71}
72
73void VehicleSection::setSectionFeatures(std::vector<KPublicTransport::Feature> &&features)
74{
75 d.detach();
76 FeatureUtil::set(d->sectionFeatures, std::move(features));
77}
78
79KPublicTransport::Feature VehicleSection::feature(KPublicTransport::Feature::Type type) const
80{
81 return FeatureUtil::findByType(d->sectionFeatures, type);
82}
83
84QString VehicleSection::vehicleTypeIconName(VehicleSection::Type type)
85{
86 switch (type) {
87 case VehicleSection::UnknownType:
88 case VehicleSection::Engine:
89 case VehicleSection::PowerCar:
90 break;
91 case VehicleSection::PassengerCar:
92 case VehicleSection::ControlCar:
93 return u"qrc:///org.kde.kpublictransport/assets/images/train-coach-passenger.svg"_s;
94 case VehicleSection::SleepingCar:
95 return u"qrc:///org.kde.kpublictransport/assets/images/train-coach-sleeping.svg"_s;
96 case VehicleSection::CouchetteCar:
97 return u"qrc:///org.kde.kpublictransport/assets/images/train-coach-couchette.svg"_s;
98 case VehicleSection::RestaurantCar:
99 return u"qrc:///org.kde.kpublictransport/assets/images/train-coach-restaurant.svg"_s;
100 case VehicleSection::CarTransportCar:
101 return u"qrc:///org.kde.kpublictransport/assets/images/train-coach-cartransport.svg"_s;
102 }
103 return {};
104}
105
107{
108 return vehicleTypeIconName(type());
109}
110
111VehicleSection VehicleSection::merge(const VehicleSection &lhs, const VehicleSection &rhs)
112{
113 if (lhs.name() != rhs.name()) { // safety check, as we don't properly check for equalness before merging yet
114 return lhs;
115 }
116
117 auto res = lhs;
118 res.setPlatformPositionBegin(lhs.platformPositionBegin() < 0.0 ? rhs.platformPositionBegin() : lhs.platformPositionBegin());
119 res.setPlatformPositionEnd(lhs.platformPositionEnd() < 0.0 ? rhs.platformPositionEnd() : lhs.platformPositionEnd());
120 res.setType(std::max(lhs.type(), rhs.type()));
121 if (res.type() == VehicleSection::PassengerCar && lhs.type() != VehicleSection::UnknownType && rhs.type() != VehicleSection::UnknownType) {
122 res.setType(std::min(lhs.type(), rhs.type()));
123 }
124 res.setClasses(lhs.classes() | rhs.classes());
125 res.setDeckCount(std::max(lhs.deckCount(), rhs.deckCount()));
126 res.setConnectedSides(lhs.connectedSides() & rhs.connectedSides());
127 res.setPlatformSectionName(MergeUtil::mergeString(lhs.platformSectionName(), rhs.platformSectionName()));
128 res.setSectionFeatures(FeatureUtil::merge(lhs.sectionFeatures(), rhs.sectionFeatures()));
129 return res;
130}
131
132QJsonObject VehicleSection::toJson(const VehicleSection &section)
133{
134 auto obj = Json::toJson(section);
135 if (!section.d->sectionFeatures.empty()) {
136 obj.insert("features"_L1, KPublicTransport::Feature::toJson(section.d->sectionFeatures));
137 }
138 if (section.disruptionEffect() == Disruption::NormalService) {
139 obj.remove("disruptionEffect"_L1);
140 }
141 if (section.load() == Load::Unknown) {
142 obj.remove("load"_L1);
143 }
144 return obj;
145}
146
147QJsonArray VehicleSection::toJson(const std::vector<VehicleSection> &sections)
148{
149 return Json::toJson(sections);
150}
151
152VehicleSection VehicleSection::fromJson(const QJsonObject &obj)
153{
154 auto v = Json::fromJson<VehicleSection>(obj);
155 const auto fVal = obj.value("features"_L1);
156 if (fVal.isArray()) {
157 v.setSectionFeatures(KPublicTransport::Feature::fromJson(fVal.toArray()));
158 }
159 return v;
160}
161
162std::vector<VehicleSection> VehicleSection::fromJson(const QJsonArray &array)
163{
164 return Json::fromJson<VehicleSection>(array);
165}
166
167bool VehicleSection::hasPlatformPosition() const
168{
169 return d->platformPositionBegin >= 0.0 && d->platformPositionEnd >= 0.0;
170}
171
172KPUBLICTRANSPORT_MAKE_GADGET(Vehicle)
173KPUBLICTRANSPORT_MAKE_PROPERTY(Vehicle, QString, name, setName)
174KPUBLICTRANSPORT_MAKE_PROPERTY(Vehicle, Vehicle::Direction, direction, setDirection)
175
176bool Vehicle::isEmpty() const
177{
178 return d->name.isEmpty() && d->sections.empty() && d->direction == Vehicle::UnknownDirection && d->features.empty();
179}
180
181const std::vector<VehicleSection>& Vehicle::sections() const
182{
183 return d->sections;
184}
185
186std::vector<VehicleSection>&& Vehicle::takeSections()
187{
188 d.detach();
189 return std::move(d->sections);
190}
191
192void Vehicle::setSections(std::vector<VehicleSection> &&sections)
193{
194 d.detach();
195 d->sections = std::move(sections);
196}
197
198void Vehicle::setSections(const std::vector<VehicleSection> &sections)
199{
200 d.detach();
201 d->sections = sections;
202}
203
204QVariantList Vehicle::sectionsVariant() const
205{
206 QVariantList l;
207 l.reserve(d->sections.size());
208 std::transform(d->sections.begin(), d->sections.end(), std::back_inserter(l), [](const auto &sec) { return QVariant::fromValue(sec); });
209 return l;
210}
211
213{
214 float p = std::numeric_limits<float>::max();
215 for (const auto &section : sections()) {
216 p = std::min(p, section.platformPositionBegin());
217 }
218 return p;
219}
220
222{
223 float p = -1.0f;
224 for (const auto &section : sections()) {
225 p = std::max(p, section.platformPositionEnd());
226 }
227 return p;
228}
229
230float Vehicle::platformPositionForSection(const QString &sectionName) const
231{
232 for (const auto &section : sections()) {
233 if (section.name() == sectionName) {
234 return (section.platformPositionBegin() + section.platformPositionEnd()) / 2.0f;
235 }
236 }
237 return -1.0f;
238}
239
240Vehicle Vehicle::merge(const Vehicle &lhs, const Vehicle &rhs)
241{
242 Vehicle res;
243 res.setDirection(lhs.direction() == Vehicle::UnknownDirection ? rhs.direction() : lhs.direction());
244 res.setName(MergeUtil::mergeString(lhs.name(), rhs.name()));
245
246 if (lhs.sections().size() == rhs.sections().size()) {
247 std::vector<VehicleSection> secs;
248 secs.reserve(lhs.sections().size());
249 for (std::size_t i = 0; i < lhs.sections().size(); ++i) {
250 const auto &lhsSec = lhs.sections()[i];
251 const auto &rhsSec = rhs.sections()[i];
252 secs.push_back(VehicleSection::merge(lhsSec, rhsSec));
253 }
254 res.setSections(std::move(secs));
255 } else {
256 res.setSections(lhs.sections().size() < rhs.sections().size() ? rhs.sections() : lhs.sections());
257 }
258
259 res.setFeatures(FeatureUtil::merge(lhs.features(), rhs.features()));
260
261 return res;
262}
263
265{
266 auto obj = Json::toJson(vehicle);
267 if (!vehicle.sections().empty()) {
268 obj.insert("sections"_L1, VehicleSection::toJson(vehicle.sections()));
269 }
270 if (!vehicle.features().empty()) {
271 obj.insert("features"_L1, Feature::toJson(vehicle.features()));
272 }
273 return obj;
274}
275
276QJsonArray Vehicle::toJson(const std::vector<Vehicle> &vehicles)
277{
278 return Json::toJson(vehicles);
279}
280
282{
283 auto v = Json::fromJson<Vehicle>(obj);
284 v.setSections(VehicleSection::fromJson(obj.value("sections"_L1).toArray()));
285 v.setFeatures(Feature::fromJson(obj.value("features"_L1).toArray()));
286 return v;
287}
288
289std::vector<Vehicle> Vehicle::fromJson(const QJsonArray &array)
290{
291 return Json::fromJson<Vehicle>(array);
292}
293
295{
296 return std::all_of(d->sections.begin(), d->sections.end(), [](const auto &p) { return p.hasPlatformPosition(); });
297}
298
300{
301 return std::none_of(d->sections.begin(), d->sections.end(), [](const auto &p) { return p.platformSectionName().isEmpty(); });
302}
303
304const std::vector<KPublicTransport::Feature>& Vehicle::features() const
305{
306 return d->features;
307}
308
309[[nodiscard]] std::vector<KPublicTransport::Feature>&& Vehicle::takeFeatures()
310{
311 return std::move(d->features);
312}
313
314void Vehicle::setFeatures(std::vector<KPublicTransport::Feature> &&features)
315{
316 d.detach();
317 d->features = std::move(features);
318}
319
320std::vector<KPublicTransport::Feature> Vehicle::combinedFeatures() const
321{
322 std::vector<KPublicTransport::Feature> features(d->features);
323 for (const auto &section : d->sections) {
324 for (const auto &feature : section.sectionFeatures()) {
325 FeatureUtil::aggregate(features, feature);
326 }
327 }
328 return features;
329}
330
331#include "moc_vehicle.cpp"
An amenity, facility or other relevant property of a vehicle (train, bus, etc), vehicle part (e....
Definition feature.h:20
static Feature fromJson(const QJsonObject &obj)
Deserialize an object from JSON.
Definition feature.cpp:143
static QJsonObject toJson(const Feature &feature)
Serializes one object to JSON.
Definition feature.cpp:129
Information about a part of a vehicle.
Definition vehicle.h:25
QString name
Human readable identifier of this section, typically the coach number.
Definition vehicle.h:31
KPublicTransport::Load::Category load
Occupancy level for this coach.
Definition vehicle.h:110
Type type
Type of this vehicle section.
Definition vehicle.h:56
std::vector< KPublicTransport::Feature > sectionFeatures
Features of this section, for consumption by QML.
Definition vehicle.h:73
QString iconName
A suitable icon representing the coach.
Definition vehicle.h:130
QString platformSectionName
Name of the platform section(s) this coach is position in.
Definition vehicle.h:115
KPublicTransport::Disruption::Effect disruptionEffect
Distruption affecting this coach.
Definition vehicle.h:107
float platformPositionBegin
Relative position [0-1] of the begin of this vehicle section on the platform.
Definition vehicle.h:36
Classes classes
Classes available in this vehicle section.
Definition vehicle.h:70
Sides connectedSides
Sides on which this vehicle section is connected to neighboring sections in a way that passengers can...
Definition vehicle.h:102
int deckCount
Number of decks in this vehicle section.
Definition vehicle.h:85
float platformPositionEnd
Relative position [0-1] of the end of this vehicle section on the platform.
Definition vehicle.h:40
Information about the vehicle used on a journey.
Definition vehicle.h:159
static QJsonObject toJson(const Vehicle &vehicle)
Serializes one vehicle object to JSON.
Definition vehicle.cpp:264
QVariantList sections
Journey sections for consumption by QML.
Definition vehicle.h:175
void setSections(std::vector< VehicleSection > &&sections)
Sets the vehicle sections.
Definition vehicle.cpp:192
float platformPositionBegin
Relative position [0-1] of the begin of this vehicle on the platform.
Definition vehicle.h:180
bool hasPlatformPositions() const
Checks whether all vehicle sections have platform positions set.
Definition vehicle.cpp:294
static Vehicle fromJson(const QJsonObject &obj)
Deserialize an object from JSON.
Definition vehicle.cpp:281
Direction direction
Direction of travel of this vehicle.
Definition vehicle.h:172
float platformPositionEnd
Relative position [0-1] of the end of this vehicle on the platform.
Definition vehicle.h:184
bool hasPlatformSectionNames() const
Check whether all vehicle sections have platform section names set.
Definition vehicle.cpp:299
std::vector< KPublicTransport::Feature > combinedFeatures
Features of the entire vehicle including a union of all features of the individual sections.
Definition vehicle.h:190
std::vector< KPublicTransport::Feature > features
Features of this vehicle as a whole, not including the features of individual sections.
Definition vehicle.h:187
std::vector< VehicleSection > && takeSections()
Moves the vehicle sections out of this object.
Definition vehicle.cpp:186
Q_INVOKABLE float platformPositionForSection(const QString &sectionName) const
Returns the center position of the vehicle section named sectionName in relative platform coordinates...
Definition vehicle.cpp:230
static Vehicle merge(const Vehicle &lhs, const Vehicle &rhs)
Merge two Vehicle instances.
Definition vehicle.cpp:240
QString name
Human readable identifier of this vehicle, typically a train number.
Definition vehicle.h:162
Effect
Disruption effects, numerical sorted so that higher values imply more severe disruptions.
Definition disruption.h:25
Category
Vehicle load categories.
Definition load.h:20
@ Unknown
no load information are available
Definition load.h:21
Query operations and data types for accessing realtime public transport information from online servi...
iterator insert(QLatin1StringView key, const QJsonValue &value)
QJsonValue value(QLatin1StringView key) const const
QJsonArray toArray() const const
bool isEmpty() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Mon Nov 18 2024 12:07:52 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.