KPublicTransport

vehicle.cpp
1 /*
2  SPDX-FileCopyrightText: 2019 Volker Krause <[email protected]>
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 "mergeutil_p.h"
11 
12 #include <QDebug>
13 #include <QMetaEnum>
14 #include <QVariant>
15 
16 #include <limits>
17 
18 using namespace KPublicTransport;
19 
20 namespace KPublicTransport {
21 
22 class VehicleSectionPrivate : public QSharedData
23 {
24 public:
25  QString name;
26  float platformPositionBegin = -1.0;
27  float platformPositionEnd = -1.0;
28  VehicleSection::Type type = VehicleSection::UnknownType;
29  VehicleSection::Classes classes = VehicleSection::UnknownClass;
30  VehicleSection::Features features = VehicleSection::NoFeatures;
31  int deckCount = 1;
32  VehicleSection::Sides connectedSides = VehicleSection::Front | VehicleSection::Back;
33  QString platformSectionName;
34 };
35 
36 class VehiclePrivate : public QSharedData
37 {
38 public:
39  QString name;
40  std::vector<VehicleSection> sections;
41  Vehicle::Direction direction = Vehicle::UnknownDirection;
42 };
43 
44 }
45 
46 KPUBLICTRANSPORT_MAKE_GADGET(VehicleSection)
47 KPUBLICTRANSPORT_MAKE_PROPERTY(VehicleSection, QString, name, setName)
48 KPUBLICTRANSPORT_MAKE_PROPERTY(VehicleSection, float, platformPositionBegin, setPlatformPositionBegin)
49 KPUBLICTRANSPORT_MAKE_PROPERTY(VehicleSection, float, platformPositionEnd, setPlatformPositionEnd)
50 KPUBLICTRANSPORT_MAKE_PROPERTY(VehicleSection, VehicleSection::Type, type, setType)
51 KPUBLICTRANSPORT_MAKE_PROPERTY(VehicleSection, VehicleSection::Classes, classes, setClasses)
52 KPUBLICTRANSPORT_MAKE_PROPERTY(VehicleSection, VehicleSection::Features, features, setFeatures)
53 KPUBLICTRANSPORT_MAKE_PROPERTY(VehicleSection, int, deckCount, setDeckCount)
54 KPUBLICTRANSPORT_MAKE_PROPERTY(VehicleSection, VehicleSection::Sides, connectedSides, setConnectedSides)
55 KPUBLICTRANSPORT_MAKE_PROPERTY(VehicleSection, QString, platformSectionName, setPlatformSectionName)
56 
57 VehicleSection VehicleSection::merge(const VehicleSection &lhs, const VehicleSection &rhs)
58 {
59  if (lhs.name() != rhs.name()) { // safety check, as we don't properly check for equalness before merging yet
60  return lhs;
61  }
62 
63  auto res = lhs;
64  res.setPlatformPositionBegin(lhs.platformPositionBegin() < 0.0 ? rhs.platformPositionBegin() : lhs.platformPositionBegin());
65  res.setPlatformPositionEnd(lhs.platformPositionEnd() < 0.0 ? rhs.platformPositionEnd() : lhs.platformPositionEnd());
66  res.setType(std::max(lhs.type(), rhs.type()));
67  if (res.type() == VehicleSection::PassengerCar && lhs.type() != VehicleSection::UnknownType && rhs.type() != VehicleSection::UnknownType) {
68  res.setType(std::min(lhs.type(), rhs.type()));
69  }
70  res.setClasses(lhs.classes() | rhs.classes());
71  res.setFeatures(lhs.features() | rhs.features());
72  res.setDeckCount(std::max(lhs.deckCount(), rhs.deckCount()));
73  res.setConnectedSides(lhs.connectedSides() & rhs.connectedSides());
74  res.setPlatformSectionName(MergeUtil::mergeString(lhs.platformSectionName(), rhs.platformSectionName()));
75  return res;
76 }
77 
78 QJsonObject VehicleSection::toJson(const VehicleSection &section)
79 {
80  return Json::toJson(section);
81 }
82 
83 QJsonArray VehicleSection::toJson(const std::vector<VehicleSection> &sections)
84 {
85  return Json::toJson(sections);
86 }
87 
88 VehicleSection VehicleSection::fromJson(const QJsonObject &obj)
89 {
90  return Json::fromJson<VehicleSection>(obj);
91 }
92 
93 std::vector<VehicleSection> VehicleSection::fromJson(const QJsonArray &array)
94 {
95  return Json::fromJson<VehicleSection>(array);
96 }
97 
98 QVariantList VehicleSection::featureList() const
99 {
100  QVariantList l;
101  const auto me = QMetaEnum::fromType<VehicleSection::Features>();
102  for (int i = 0; i < me.keyCount(); ++i) {
103  if (features() & static_cast<VehicleSection::Feature>(1 << i))
104  l.push_back(static_cast<VehicleSection::Feature>(1 << i));
105  }
106  return l;
107 }
108 
109 bool VehicleSection::hasPlatformPosition() const
110 {
111  return d->platformPositionBegin >= 0.0 && d->platformPositionEnd >= 0.0;
112 }
113 
114 KPUBLICTRANSPORT_MAKE_GADGET(Vehicle)
115 KPUBLICTRANSPORT_MAKE_PROPERTY(Vehicle, QString, name, setName)
116 KPUBLICTRANSPORT_MAKE_PROPERTY(Vehicle, Vehicle::Direction, direction, setDirection)
117 
118 bool Vehicle::isEmpty() const
119 {
120  return d->name.isEmpty() && d->sections.empty() && d->direction == Vehicle::UnknownDirection;
121 }
122 
123 const std::vector<VehicleSection>& Vehicle::sections() const
124 {
125  return d->sections;
126 }
127 
128 std::vector<VehicleSection>&& Vehicle::takeSections()
129 {
130  d.detach();
131  return std::move(d->sections);
132 }
133 
134 void Vehicle::setSections(std::vector<VehicleSection> &&sections)
135 {
136  d.detach();
137  d->sections = std::move(sections);
138 }
139 
140 void Vehicle::setSections(const std::vector<VehicleSection> &sections)
141 {
142  d.detach();
143  d->sections = sections;
144 }
145 
146 QVariantList Vehicle::sectionsVariant() const
147 {
148  QVariantList l;
149  l.reserve(d->sections.size());
150  std::transform(d->sections.begin(), d->sections.end(), std::back_inserter(l), [](const auto &sec) { return QVariant::fromValue(sec); });
151  return l;
152 }
153 
154 float Vehicle::platformPositionBegin() const
155 {
156  float p = std::numeric_limits<float>::max();
157  for (const auto &section : sections()) {
158  p = std::min(p, section.platformPositionBegin());
159  }
160  return p;
161 }
162 
163 float Vehicle::platformPositionEnd() const
164 {
165  float p = -1.0f;
166  for (const auto &section : sections()) {
167  p = std::max(p, section.platformPositionEnd());
168  }
169  return p;
170 }
171 
172 float Vehicle::platformPositionForSection(const QString &sectionName) const
173 {
174  for (const auto &section : sections()) {
175  if (section.name() == sectionName) {
176  return (section.platformPositionBegin() + section.platformPositionEnd()) / 2.0f;
177  }
178  }
179  return -1.0f;
180 }
181 
182 Vehicle Vehicle::merge(const Vehicle &lhs, const Vehicle &rhs)
183 {
184  Vehicle res;
185  res.setDirection(lhs.direction() == Vehicle::UnknownDirection ? rhs.direction() : lhs.direction());
186  res.setName(MergeUtil::mergeString(lhs.name(), rhs.name()));
187 
188  if (lhs.sections().size() == rhs.sections().size()) {
189  std::vector<VehicleSection> secs;
190  secs.reserve(lhs.sections().size());
191  for (std::size_t i = 0; i < lhs.sections().size(); ++i) {
192  const auto &lhsSec = lhs.sections()[i];
193  const auto &rhsSec = rhs.sections()[i];
194  secs.push_back(VehicleSection::merge(lhsSec, rhsSec));
195  }
196  res.setSections(std::move(secs));
197  } else {
198  res.setSections(lhs.sections().size() < rhs.sections().size() ? rhs.sections() : lhs.sections());
199  }
200 
201  return res;
202 }
203 
205 {
206  auto obj = Json::toJson(vehicle);
207  if (!vehicle.sections().empty()) {
208  obj.insert(QStringLiteral("sections"), VehicleSection::toJson(vehicle.sections()));
209  }
210  return obj;
211 }
212 
213 QJsonArray Vehicle::toJson(const std::vector<Vehicle> &vehicles)
214 {
215  return Json::toJson(vehicles);
216 }
217 
219 {
220  auto v = Json::fromJson<Vehicle>(obj);
221  v.setSections(VehicleSection::fromJson(obj.value(QLatin1String("sections")).toArray()));
222  return v;
223 }
224 
225 std::vector<Vehicle> Vehicle::fromJson(const QJsonArray &array)
226 {
227  return Json::fromJson<Vehicle>(array);
228 }
229 
231 {
232  return std::all_of(d->sections.begin(), d->sections.end(), [](const auto &p) { return p.hasPlatformPosition(); });
233 }
234 
236 {
237  return std::none_of(d->sections.begin(), d->sections.end(), [](const auto &p) { return p.platformSectionName().isEmpty(); });
238 }
239 
240 #include "moc_vehicle.cpp"
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:172
Direction direction
Direction of travel of this vehicle.
Definition: vehicle.h:154
Query operations and data types for accessing realtime public transport information from online servi...
Definition: attribution.cpp:16
static Vehicle fromJson(const QJsonObject &obj)
Deserialize an object from JSON.
Definition: vehicle.cpp:218
const std::vector< VehicleSection > & sections() const
The vehicle sections.
Information about a part of a vehicle.
Definition: vehicle.h:22
QString name
Human readable identifier of this vehicle, typically a train number.
Definition: vehicle.h:144
std::vector< VehicleSection > && takeSections()
Moves the vehicle sections out of this object.
Definition: vehicle.cpp:128
bool hasPlatformPositions() const
Checks whether all vehicle sections have platform positions set.
Definition: vehicle.cpp:230
QVariantList sections
Journey sections for consumption by QML.
Definition: vehicle.h:157
QJsonArray toArray() const const
Information about the vehicle used on a journey.
Definition: vehicle.h:140
Direction
static Vehicle merge(const Vehicle &lhs, const Vehicle &rhs)
Merge two Vehicle instances.
Definition: vehicle.cpp:182
QVariant fromValue(const T &value)
static QJsonObject toJson(const Vehicle &vehicle)
Serializes one vehicle object to JSON.
Definition: vehicle.cpp:204
bool hasPlatformSectionNames() const
Check whether all vehicle sections have platform section names set.
Definition: vehicle.cpp:235
void setSections(std::vector< VehicleSection > &&sections)
Sets the vehicle sections.
Definition: vehicle.cpp:134
QJsonValue value(const QString &key) const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2021 The KDE developers.
Generated on Sat Oct 23 2021 23:05:21 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.