KPublicTransport

stopover.cpp
1 /*
2  SPDX-FileCopyrightText: 2018 Volker Krause <[email protected]>
3 
4  SPDX-License-Identifier: LGPL-2.0-or-later
5 */
6 
7 #include "stopover.h"
8 #include "datatypes_p.h"
9 #include "json_p.h"
10 #include "loadutil_p.h"
11 #include "mergeutil_p.h"
12 #include "notesutil_p.h"
13 #include "platformutils_p.h"
14 #include "stopoverutil_p.h"
15 
16 #include <QDateTime>
17 #include <QDebug>
18 
19 using namespace KPublicTransport;
20 
21 namespace KPublicTransport {
22 class StopoverPrivate : public QSharedData {
23 public:
24  Disruption::Effect disruptionEffect = Disruption::NormalService;
25  QDateTime scheduledArrivalTime;
26  QDateTime expectedArrivalTime;
27  QDateTime scheduledDepartureTime;
28  QDateTime expectedDepartureTime;
29  QString scheduledPlatform;
30  QString expectedPlatform;
31  Route route;
32  Location stopPoint;
33  QStringList notes;
34  std::vector<LoadInfo> loadInformation;
35  Vehicle vehicleLayout;
36  Platform platformLayout;
37 };
38 }
39 
40 KPUBLICTRANSPORT_MAKE_GADGET(Stopover)
41 KPUBLICTRANSPORT_MAKE_PROPERTY(Stopover, QDateTime, scheduledArrivalTime, setScheduledArrivalTime)
42 KPUBLICTRANSPORT_MAKE_PROPERTY(Stopover, QDateTime, expectedArrivalTime, setExpectedArrivalTime)
43 KPUBLICTRANSPORT_MAKE_PROPERTY(Stopover, QDateTime, scheduledDepartureTime, setScheduledDepartureTime)
44 KPUBLICTRANSPORT_MAKE_PROPERTY(Stopover, QDateTime, expectedDepartureTime, setExpectedDepartureTime)
45 KPUBLICTRANSPORT_MAKE_PROPERTY(Stopover, Route, route, setRoute)
46 KPUBLICTRANSPORT_MAKE_PROPERTY(Stopover, Location, stopPoint, setStopPoint)
47 KPUBLICTRANSPORT_MAKE_PROPERTY(Stopover, Disruption::Effect, disruptionEffect, setDisruptionEffect)
48 KPUBLICTRANSPORT_MAKE_PROPERTY(Stopover, QStringList, notes, setNotes)
49 KPUBLICTRANSPORT_MAKE_PROPERTY(Stopover, Vehicle, vehicleLayout, setVehicleLayout)
50 KPUBLICTRANSPORT_MAKE_PROPERTY(Stopover, Platform, platformLayout, setPlatformLayout)
51 
52 bool Stopover::hasExpectedArrivalTime() const
53 {
54  return d->expectedArrivalTime.isValid();
55 }
56 
57 int Stopover::arrivalDelay() const
58 {
59  if (hasExpectedArrivalTime()) {
60  return d->scheduledArrivalTime.secsTo(d->expectedArrivalTime) / 60;
61  }
62  return 0;
63 }
64 
65 bool Stopover::hasExpectedDepartureTime() const
66 {
67  return d->expectedDepartureTime.isValid();
68 }
69 
70 int Stopover::departureDelay() const
71 {
72  if (hasExpectedDepartureTime()) {
73  return d->scheduledDepartureTime.secsTo(d->expectedDepartureTime) / 60;
74  }
75  return 0;
76 }
77 
79 {
80  return d->scheduledPlatform;
81 }
82 
83 void Stopover::setScheduledPlatform(const QString &platform)
84 {
85  d.detach();
86  d->scheduledPlatform = PlatformUtils::normalizePlatform(platform);
87 }
88 
90 {
91  return d->expectedPlatform;
92 }
93 
94 void Stopover::setExpectedPlatform(const QString &platform)
95 {
96  d.detach();
97  d->expectedPlatform = PlatformUtils::normalizePlatform(platform);
98 }
99 
100 bool Stopover::hasExpectedPlatform() const
101 {
102  return !d->expectedPlatform.isEmpty();
103 }
104 
105 bool Stopover::platformChanged() const
106 {
107  return PlatformUtils::platformChanged(d->scheduledPlatform, d->expectedPlatform);
108 }
109 
110 void Stopover::addNote(const QString &note)
111 {
112  const auto n = NotesUtil::normalizeNote(note);
113  const auto idx = NotesUtil::needsAdding(d->notes, n);
114  if (idx >= 0) {
115  d.detach();
116  NotesUtil::performAdd(d->notes, n, idx);
117  }
118 }
119 
120 void Stopover::addNotes(const QStringList &notes)
121 {
122  for (const auto &n : notes) {
123  addNote(n);
124  }
125 }
126 
127 const std::vector<LoadInfo>& Stopover::loadInformation() const
128 {
129  return d->loadInformation;
130 }
131 
132 std::vector<LoadInfo>&& Stopover::takeLoadInformation()
133 {
134  d.detach();
135  return std::move(d->loadInformation);
136 }
137 
138 void Stopover::setLoadInformation(std::vector<LoadInfo> &&loadInfo)
139 {
140  d.detach();
141  d->loadInformation = std::move(loadInfo);
142 }
143 
144 QVariantList Stopover::loadInformationVariant() const
145 {
146  QVariantList l;
147  l.reserve(d->loadInformation.size());
148  std::transform(d->loadInformation.begin(), d->loadInformation.end(), std::back_inserter(l), [](const auto &load) { return QVariant::fromValue(load); });
149  return l;
150 }
151 
152 bool Stopover::isSame(const Stopover &lhs, const Stopover &rhs)
153 {
154  // same time is mandatory
155  const auto departureTimeMatch = lhs.scheduledDepartureTime().isValid()
157  && MergeUtil::distance(lhs.scheduledDepartureTime(), rhs.scheduledDepartureTime()) < 60;
158  const auto arrivalTimeMatch = lhs.scheduledArrivalTime().isValid()
159  && rhs.scheduledArrivalTime().isValid()
160  && MergeUtil::distance(lhs.scheduledArrivalTime(), rhs.scheduledArrivalTime()) < 60;
161  if (!departureTimeMatch && !arrivalTimeMatch) {
162  return false;
163  }
164 
165  // same route would be sufficient, if that's not the case, look for other hints
166  // this might be the same below
167  if (Route::isSame(lhs.route(), rhs.route())) {
168  return true;
169  }
170 
171  // different platform can't be the same train
172  if (!lhs.scheduledPlatform().isEmpty() && !rhs.scheduledPlatform().isEmpty() && lhs.scheduledPlatform() != rhs.scheduledPlatform()) {
173  return false;
174  }
175 
176  // same destination and departure time is likely the same route after all
177  // TODO we should check for conflicting line names or train types here maybe?
178  return (!lhs.route().destination().isEmpty() && !rhs.route().destination().isEmpty() && Location::isSame(lhs.route().destination(), rhs.route().destination()))
179  || Location::isSameName(lhs.route().direction(), rhs.route().direction());
180 }
181 
182 Stopover Stopover::merge(const Stopover &lhs, const Stopover &rhs)
183 {
184  auto stopover = lhs;
185 
186  using namespace MergeUtil;
187  stopover.setScheduledDepartureTime(mergeDateTimeEqual(lhs.scheduledDepartureTime(), rhs.scheduledDepartureTime()));
188  stopover.setExpectedDepartureTime(mergeDateTimeMax(lhs.expectedDepartureTime(), rhs.expectedDepartureTime()));
189  stopover.setScheduledArrivalTime(mergeDateTimeEqual(lhs.scheduledArrivalTime(), rhs.scheduledArrivalTime()));
190  stopover.setExpectedArrivalTime(mergeDateTimeMax(lhs.expectedArrivalTime(), rhs.expectedArrivalTime()));
191 
192  if (stopover.scheduledPlatform().isEmpty() && !rhs.scheduledPlatform().isEmpty()) {
193  stopover.setScheduledPlatform(rhs.scheduledPlatform());
194  }
195  if (!stopover.hasExpectedPlatform() && rhs.hasExpectedPlatform()) {
196  stopover.setExpectedPlatform(rhs.expectedPlatform());
197  }
198 
199  stopover.setRoute(Route::merge(lhs.route(), rhs.route()));
200  stopover.setStopPoint(Location::merge(lhs.stopPoint(), rhs.stopPoint()));
201  stopover.setDisruptionEffect(std::max(lhs.disruptionEffect(), rhs.disruptionEffect()));
202  stopover.setNotes(NotesUtil::mergeNotes(lhs.notes(), rhs.notes()));
203  stopover.d->loadInformation = LoadUtil::merge(lhs.d->loadInformation, rhs.d->loadInformation);
204  stopover.d->vehicleLayout = Vehicle::merge(lhs.d->vehicleLayout, rhs.d->vehicleLayout);
205  stopover.d->platformLayout = Platform::merge(lhs.d->platformLayout, rhs.d->platformLayout);
206  return stopover;
207 }
208 
209 QJsonObject Stopover::toJson(const Stopover &stopover)
210 {
211  auto obj = Json::toJson(stopover);
212  const auto routeObj = Route::toJson(stopover.route());
213  if (!routeObj.empty()) {
214  obj.insert(QLatin1String("route"), routeObj);
215  }
216  const auto locObj = Location::toJson(stopover.stopPoint());
217  if (!locObj.empty()) {
218  obj.insert(QLatin1String("stopPoint"), locObj);
219  }
220  if (!stopover.loadInformation().empty()) {
221  obj.insert(QLatin1String("load"), LoadInfo::toJson(stopover.loadInformation()));
222  }
223  if (!stopover.vehicleLayout().isEmpty()) {
224  obj.insert(QLatin1String("vehicleLayout"), Vehicle::toJson(stopover.vehicleLayout()));
225  }
226  if (!stopover.platformLayout().isEmpty()) {
227  obj.insert(QLatin1String("platformLayout"), Platform::toJson(stopover.platformLayout()));
228  }
229 
230  if (obj.size() == 1) { // only the disruption enum, ie. this is an empty object
231  return {};
232  }
233  return obj;
234 }
235 
236 QJsonArray Stopover::toJson(const std::vector<Stopover> &deps)
237 {
238  return Json::toJson(deps);
239 }
240 
241 Stopover Stopover::fromJson(const QJsonObject &obj)
242 {
243  auto stopover = Json::fromJson<Stopover>(obj);
244  stopover.setRoute(Route::fromJson(obj.value(QLatin1String("route")).toObject()));
245  stopover.setStopPoint(Location::fromJson(obj.value(QLatin1String("stopPoint")).toObject()));
247  stopover.setVehicleLayout(Vehicle::fromJson(obj.value(QLatin1String("vehicleLayout")).toObject()));
248  stopover.setPlatformLayout(Platform::fromJson(obj.value(QLatin1String("platformLayout")).toObject()));
249  StopoverUtil::applyMetaData(stopover, false);
250  return stopover;
251 }
252 
253 std::vector<Stopover> Stopover::fromJson(const QJsonArray &array)
254 {
255  return Json::fromJson<Stopover>(array);
256 }
257 
258 #include "moc_stopover.cpp"
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
KPublicTransport::Platform platformLayout
Platform layout information.
Definition: stopover.h:79
bool hasExpectedPlatform
true if real-time platform information are available.
Definition: stopover.h:56
std::vector< LoadInfo > && takeLoadInformation()
Moves the load information out of this object for modification.
Definition: stopover.cpp:132
QVariantList loadInformation
Vehicle load information for departure from this stopover Contains LoadInfo objects for consumption b...
Definition: stopover.h:74
static Stopover fromJson(const QJsonObject &obj)
Deserialize an object from JSON.
Definition: stopover.cpp:241
KPublicTransport::Location stopPoint
The stop point of this departure.
Definition: stopover.h:64
bool isEmpty() const
Returns true if this is an default-constructed location object not specifying any location...
Definition: location.cpp:76
Effect
Disruption effects, numerical sorted so that higher values imply more severe disruptions.
Definition: disruption.h:25
static bool isSame(const Route &lhs, const Route &rhs)
Checks if to instances refer to the same route (which does not necessarily mean they are exactly equa...
Definition: line.cpp:177
static QJsonObject toJson(const Route &r)
Serializes one object to JSON.
Definition: line.cpp:194
QString scheduledPlatform
Planned departure platform.
Definition: stopover.h:52
static bool isSame(const Location &lhs, const Location &rhs)
Checks if to instances refer to the same location (which does not necessarily mean they are exactly e...
Definition: location.cpp:262
static QJsonObject toJson(const Stopover &stopover)
Serializes one object to JSON.
Definition: stopover.cpp:209
A route of a public transport line.
Definition: line.h:120
bool isEmpty() const
Returns true if this object contains no information beyond the default values.
Definition: vehicle.cpp:118
static bool isSame(const Stopover &lhs, const Stopover &rhs)
Checks if to instances refer to the same departure (which does not necessarily mean they are exactly ...
Definition: stopover.cpp:152
static bool isSameName(const QString &lhs, const QString &rhs)
Checks if two location names refer to the same location.
Definition: location.cpp:321
KPublicTransport::Location destination
Destination of the route.
Definition: line.h:135
const std::vector< LoadInfo > & loadInformation() const
Expected vehicle load for departing from this stopover.
static Location fromJson(const QJsonObject &obj)
Deserialize a Location object from JSON.
Definition: location.cpp:485
QJsonObject toObject() const const
QJsonArray toArray() const const
KPublicTransport::Disruption::Effect disruptionEffect
Disruption effect on this arrival or departure, if any.
Definition: stopover.h:67
bool isEmpty() const const
KPublicTransport::Route route
The departing route.
Definition: stopover.h:61
Information about the vehicle used on a journey.
Definition: vehicle.h:140
static Location merge(const Location &lhs, const Location &rhs)
Merge two departure instances.
Definition: location.cpp:368
QDateTime scheduledArrivalTime
Planned arrival time.
Definition: stopover.h:30
static Route merge(const Route &lhs, const Route &rhs)
Merge two Route instances.
Definition: line.cpp:185
static LoadInfo fromJson(const QJsonObject &obj)
Deserialize an object from JSON.
Definition: load.cpp:36
static Platform fromJson(const QJsonObject &obj)
Deserialize an object from JSON.
Definition: platform.cpp:113
static QJsonObject toJson(const Platform &platform)
Serializes one platform object to JSON.
Definition: platform.cpp:99
static Vehicle merge(const Vehicle &lhs, const Vehicle &rhs)
Merge two Vehicle instances.
Definition: vehicle.cpp:182
QDateTime expectedDepartureTime
Actual departure time, if available.
Definition: stopover.h:45
KPublicTransport::Vehicle vehicleLayout
Vehicle coach layout information at this stopover.
Definition: stopover.h:77
static Route fromJson(const QJsonObject &obj)
Deserialize an object from JSON.
Definition: line.cpp:207
QVariant fromValue(const T &value)
bool isValid() const const
Information about an arrival and/or departure of a vehicle at a stop area.
Definition: stopover.h:25
static QJsonObject toJson(const Vehicle &vehicle)
Serializes one vehicle object to JSON.
Definition: vehicle.cpp:204
void addNote(const QString &note)
Adds a note.
Definition: stopover.cpp:110
QDateTime expectedArrivalTime
Actual arrival time, if available.
Definition: stopover.h:34
static QJsonObject toJson(const Location &loc)
Serializes one Location object to JSON.
Definition: location.cpp:444
Information about the layout of a station platform.
Definition: platform.h:44
QString expectedPlatform
Actual departure platform, in case real-time information are available.
Definition: stopover.h:54
QJsonValue value(const QString &key) const const
static Platform merge(const Platform &lhs, const Platform &rhs)
Merge two platform instances.
Definition: platform.cpp:93
static QJsonObject toJson(const LoadInfo &info)
Serializes one load information object to JSON.
Definition: load.cpp:26
QStringList notes
General human-readable notes on this service, e.g.
Definition: stopover.h:69
void setLoadInformation(std::vector< LoadInfo > &&loadInfo)
Set the expected vehicle load information for departing from this stopover.
Definition: stopover.cpp:138
static Stopover merge(const Stopover &lhs, const Stopover &rhs)
Merge two departure instances.
Definition: stopover.cpp:182
QJsonObject::iterator insert(const QString &key, const QJsonValue &value)
QDateTime scheduledDepartureTime
Planned departure time.
Definition: stopover.h:41
bool isEmpty() const
Returns true if this object contains no information beyond default values.
Definition: platform.cpp:66
QString direction
Direction of the route.
Definition: line.h:130
This file is part of the KDE documentation.
Documentation copyright © 1996-2021 The KDE developers.
Generated on Sun Oct 24 2021 23:05:21 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.