KPublicTransport

stopover.cpp
1/*
2 SPDX-FileCopyrightText: 2018 Volker Krause <vkrause@kde.org>
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
19using namespace KPublicTransport;
20
21namespace KPublicTransport {
22class StopoverPrivate : public QSharedData {
23public:
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
40KPUBLICTRANSPORT_MAKE_GADGET(Stopover)
41KPUBLICTRANSPORT_MAKE_PROPERTY(Stopover, QDateTime, scheduledArrivalTime, setScheduledArrivalTime)
42KPUBLICTRANSPORT_MAKE_PROPERTY(Stopover, QDateTime, expectedArrivalTime, setExpectedArrivalTime)
43KPUBLICTRANSPORT_MAKE_PROPERTY(Stopover, QDateTime, scheduledDepartureTime, setScheduledDepartureTime)
44KPUBLICTRANSPORT_MAKE_PROPERTY(Stopover, QDateTime, expectedDepartureTime, setExpectedDepartureTime)
45KPUBLICTRANSPORT_MAKE_PROPERTY(Stopover, Route, route, setRoute)
46KPUBLICTRANSPORT_MAKE_PROPERTY(Stopover, Location, stopPoint, setStopPoint)
47KPUBLICTRANSPORT_MAKE_PROPERTY(Stopover, Disruption::Effect, disruptionEffect, setDisruptionEffect)
48KPUBLICTRANSPORT_MAKE_PROPERTY(Stopover, QStringList, notes, setNotes)
49KPUBLICTRANSPORT_MAKE_PROPERTY(Stopover, Vehicle, vehicleLayout, setVehicleLayout)
50KPUBLICTRANSPORT_MAKE_PROPERTY(Stopover, Platform, platformLayout, setPlatformLayout)
51
53{
54 return d->expectedArrivalTime.isValid();
55}
56
57int Stopover::arrivalDelay() const
58{
60 return d->scheduledArrivalTime.secsTo(d->expectedArrivalTime) / 60;
61 }
62 return 0;
63}
64
66{
67 return d->expectedDepartureTime.isValid();
68}
69
71{
73 return d->scheduledDepartureTime.secsTo(d->expectedDepartureTime) / 60;
74 }
75 return 0;
76}
77
78QString Stopover::scheduledPlatform() const
79{
80 return d->scheduledPlatform;
81}
82
83void Stopover::setScheduledPlatform(const QString &platform)
84{
85 d.detach();
86 d->scheduledPlatform = PlatformUtils::normalizePlatform(platform);
87}
88
89QString Stopover::expectedPlatform() const
90{
91 return d->expectedPlatform;
92}
93
94void Stopover::setExpectedPlatform(const QString &platform)
95{
96 d.detach();
97 d->expectedPlatform = PlatformUtils::normalizePlatform(platform);
98}
99
101{
102 return !d->expectedPlatform.isEmpty();
103}
104
105bool Stopover::platformChanged() const
106{
107 return PlatformUtils::platformChanged(d->scheduledPlatform, d->expectedPlatform);
108}
109
110void 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
120void Stopover::addNotes(const QStringList &notes)
121{
122 for (const auto &n : notes) {
123 addNote(n);
124 }
125}
126
127const std::vector<LoadInfo>& Stopover::loadInformation() const
128{
129 return d->loadInformation;
130}
131
132std::vector<LoadInfo>&& Stopover::takeLoadInformation()
133{
134 d.detach();
135 return std::move(d->loadInformation);
136}
137
138void Stopover::setLoadInformation(std::vector<LoadInfo> &&loadInfo)
139{
140 d.detach();
141 d->loadInformation = std::move(loadInfo);
142}
143
144QList<LoadInfo> Stopover::loadInformationList() const
145{
147 l.reserve((qsizetype)d->loadInformation.size());
148 std::copy(d->loadInformation.begin(), d->loadInformation.end(), std::back_inserter(l));
149 return l;
150}
151
152const std::vector<KPublicTransport::Feature>& Stopover::features() const
153{
154 return d->vehicleLayout.features();
155}
156
157[[nodiscard]] std::vector<KPublicTransport::Feature>&& Stopover::takeFeatures()
158{
159 return d->vehicleLayout.takeFeatures();
160}
161
162void Stopover::setFeatures(std::vector<KPublicTransport::Feature> &&features)
163{
164 d.detach();
165 d->vehicleLayout.setFeatures(std::move(features));
166}
167
169{
170 return std::accumulate(d->loadInformation.begin(), d->loadInformation.end(), Load::Unknown, [](auto l, const auto &info) {
171 return std::max(l, info.load());
172 });
173}
174
175void Stopover::applyMetaData(bool download)
176{
177 auto line = d->route.line();
178 line.applyMetaData(stopPoint(), download);
179 d->route.setLine(line);
180}
181
182bool Stopover::isSame(const Stopover &lhs, const Stopover &rhs)
183{
184 // same time is mandatory
185 const auto departureTimeMatch = lhs.scheduledDepartureTime().isValid()
187 && MergeUtil::distance(lhs.scheduledDepartureTime(), rhs.scheduledDepartureTime()) < 60;
188 const auto arrivalTimeMatch = lhs.scheduledArrivalTime().isValid()
190 && MergeUtil::distance(lhs.scheduledArrivalTime(), rhs.scheduledArrivalTime()) < 60;
191 if (!departureTimeMatch && !arrivalTimeMatch) {
192 return false;
193 }
194
195 // same route would be sufficient, if that's not the case, look for other hints
196 // this might be the same below
197 if (Route::isSame(lhs.route(), rhs.route())) {
198 return true;
199 }
200
201 // different platform can't be the same train
202 if (!lhs.scheduledPlatform().isEmpty() && !rhs.scheduledPlatform().isEmpty() && lhs.scheduledPlatform() != rhs.scheduledPlatform()) {
203 return false;
204 }
205
206 // same destination and departure time is likely the same route after all
207 // TODO we should check for conflicting line names or train types here maybe?
208 return (!lhs.route().destination().isEmpty() && !rhs.route().destination().isEmpty() && Location::isSame(lhs.route().destination(), rhs.route().destination()))
210}
211
213{
214 auto stopover = lhs;
215
216 using namespace MergeUtil;
217 stopover.setScheduledDepartureTime(mergeDateTimeEqual(lhs.scheduledDepartureTime(), rhs.scheduledDepartureTime()));
218 stopover.setExpectedDepartureTime(mergeDateTimeMax(lhs.expectedDepartureTime(), rhs.expectedDepartureTime()));
219 stopover.setScheduledArrivalTime(mergeDateTimeEqual(lhs.scheduledArrivalTime(), rhs.scheduledArrivalTime()));
220 stopover.setExpectedArrivalTime(mergeDateTimeMax(lhs.expectedArrivalTime(), rhs.expectedArrivalTime()));
221
222 if (stopover.scheduledPlatform().isEmpty() && !rhs.scheduledPlatform().isEmpty()) {
223 stopover.setScheduledPlatform(rhs.scheduledPlatform());
224 }
225 if (!stopover.hasExpectedPlatform() && rhs.hasExpectedPlatform()) {
226 stopover.setExpectedPlatform(rhs.expectedPlatform());
227 }
228
229 stopover.setRoute(Route::merge(lhs.route(), rhs.route()));
230 stopover.setStopPoint(Location::merge(lhs.stopPoint(), rhs.stopPoint()));
231 stopover.setDisruptionEffect(std::max(lhs.disruptionEffect(), rhs.disruptionEffect()));
232 stopover.setNotes(NotesUtil::mergeNotes(lhs.notes(), rhs.notes()));
233 stopover.d->loadInformation = LoadUtil::merge(lhs.d->loadInformation, rhs.d->loadInformation);
234 stopover.d->vehicleLayout = Vehicle::merge(lhs.d->vehicleLayout, rhs.d->vehicleLayout);
235 stopover.d->platformLayout = Platform::merge(lhs.d->platformLayout, rhs.d->platformLayout);
236 return stopover;
237}
238
240{
241 auto obj = Json::toJson(stopover);
242 const auto routeObj = Route::toJson(stopover.route());
243 if (!routeObj.empty()) {
244 obj.insert(QLatin1String("route"), routeObj);
245 }
246 const auto locObj = Location::toJson(stopover.stopPoint());
247 if (!locObj.empty()) {
248 obj.insert(QLatin1String("stopPoint"), locObj);
249 }
250 if (!stopover.loadInformation().empty()) {
251 obj.insert(QLatin1String("load"), LoadInfo::toJson(stopover.loadInformation()));
252 }
253 if (!stopover.vehicleLayout().isEmpty()) {
254 obj.insert(QLatin1String("vehicleLayout"), Vehicle::toJson(stopover.vehicleLayout()));
255 }
256 if (!stopover.platformLayout().isEmpty()) {
257 obj.insert(QLatin1String("platformLayout"), Platform::toJson(stopover.platformLayout()));
258 }
259
260 if (obj.size() == 1) { // only the disruption enum, ie. this is an empty object
261 return {};
262 }
263 return obj;
264}
265
266QJsonArray Stopover::toJson(const std::vector<Stopover> &deps)
267{
268 return Json::toJson(deps);
269}
270
272{
273 auto stopover = Json::fromJson<Stopover>(obj);
274 stopover.setRoute(Route::fromJson(obj.value(QLatin1String("route")).toObject()));
275 stopover.setStopPoint(Location::fromJson(obj.value(QLatin1String("stopPoint")).toObject()));
276 stopover.setLoadInformation(LoadInfo::fromJson(obj.value(QLatin1String("load")).toArray()));
277 stopover.setVehicleLayout(Vehicle::fromJson(obj.value(QLatin1String("vehicleLayout")).toObject()));
278 stopover.setPlatformLayout(Platform::fromJson(obj.value(QLatin1String("platformLayout")).toObject()));
279 stopover.applyMetaData(false);
280 return stopover;
281}
282
283std::vector<Stopover> Stopover::fromJson(const QJsonArray &array)
284{
285 return Json::fromJson<Stopover>(array);
286}
287
288#include "moc_stopover.cpp"
static QJsonObject toJson(const LoadInfo &info)
Serializes one load information object to JSON.
Definition load.cpp:26
static LoadInfo fromJson(const QJsonObject &obj)
Deserialize an object from JSON.
Definition load.cpp:36
static Location fromJson(const QJsonObject &obj)
Deserialize a Location object from JSON.
Definition location.cpp:539
static bool isSameName(const QString &lhs, const QString &rhs)
Checks if two location names refer to the same location.
Definition location.cpp:360
static QJsonObject toJson(const Location &loc)
Serializes one Location object to JSON.
Definition location.cpp:478
static Location merge(const Location &lhs, const Location &rhs)
Merge two departure instances.
Definition location.cpp:407
bool isEmpty() const
Returns true if this is an default-constructed location object not specifying any location.
Definition location.cpp:121
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:312
Information about the layout of a station platform.
Definition platform.h:45
static Platform fromJson(const QJsonObject &obj)
Deserialize an object from JSON.
Definition platform.cpp:113
bool isEmpty() const
Returns true if this object contains no information beyond default values.
Definition platform.cpp:66
static Platform merge(const Platform &lhs, const Platform &rhs)
Merge two platform instances.
Definition platform.cpp:93
static QJsonObject toJson(const Platform &platform)
Serializes one platform object to JSON.
Definition platform.cpp:99
A route of a public transport line.
Definition line.h:148
KPublicTransport::Location destination
Destination of the route.
Definition line.h:162
QString direction
Direction of the route.
Definition line.h:157
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:266
static QJsonObject toJson(const Route &r)
Serializes one object to JSON.
Definition line.cpp:286
static Route merge(const Route &lhs, const Route &rhs)
Merge two Route instances.
Definition line.cpp:276
static Route fromJson(const QJsonObject &obj)
Deserialize an object from JSON.
Definition line.cpp:299
Information about an arrival and/or departure of a vehicle at a stop area.
Definition stopover.h:26
static Stopover merge(const Stopover &lhs, const Stopover &rhs)
Merge two departure instances.
Definition stopover.cpp:212
KPublicTransport::Route route
The departing route.
Definition stopover.h:61
bool platformChanged
true if we have real-time platform information and the platform changed.
Definition stopover.h:58
void applyMetaData(bool download)
Augment line meta data.
Definition stopover.cpp:175
bool hasExpectedDepartureTime
true if this has real-time data.
Definition stopover.h:47
KPublicTransport::Load::Category maximumOccupancy
Maximum occpancy leaving this stop, over all classes.
Definition stopover.h:88
int arrivalDelay
Difference to schedule in minutes.
Definition stopover.h:38
QDateTime expectedDepartureTime
Actual departure time, if available.
Definition stopover.h:45
QStringList notes
General human-readable notes on this service, e.g.
Definition stopover.h:69
QString expectedPlatform
Actual departure platform, in case real-time information are available.
Definition stopover.h:54
static QJsonObject toJson(const Stopover &stopover)
Serializes one object to JSON.
Definition stopover.cpp:239
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:182
KPublicTransport::Location stopPoint
The stop point of this departure.
Definition stopover.h:64
void setLoadInformation(std::vector< LoadInfo > &&loadInfo)
Set the expected vehicle load information for departing from this stopover.
Definition stopover.cpp:138
QDateTime expectedArrivalTime
Actual arrival time, if available.
Definition stopover.h:34
std::vector< LoadInfo > && takeLoadInformation()
Moves the load information out of this object for modification.
Definition stopover.cpp:132
QDateTime scheduledArrivalTime
Planned arrival time.
Definition stopover.h:30
QList< KPublicTransport::LoadInfo > loadInformation
Vehicle load information for departure from this stopover Contains LoadInfo objects for consumption b...
Definition stopover.h:74
bool hasExpectedArrivalTime
true if this has real-time data.
Definition stopover.h:36
bool hasExpectedPlatform
true if real-time platform information are available.
Definition stopover.h:56
static Stopover fromJson(const QJsonObject &obj)
Deserialize an object from JSON.
Definition stopover.cpp:271
KPublicTransport::Disruption::Effect disruptionEffect
Disruption effect on this arrival or departure, if any.
Definition stopover.h:67
void addNote(const QString &note)
Adds a note.
Definition stopover.cpp:110
std::vector< KPublicTransport::Feature > features
Features of the vehicle used on this section.
Definition stopover.h:85
int departureDelay
Difference to schedule in minutes.
Definition stopover.h:49
KPublicTransport::Vehicle vehicleLayout
Vehicle coach layout information at this stopover.
Definition stopover.h:77
QDateTime scheduledDepartureTime
Planned departure time.
Definition stopover.h:41
KPublicTransport::Platform platformLayout
Platform layout information.
Definition stopover.h:79
QString scheduledPlatform
Planned departure platform.
Definition stopover.h:52
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
static Vehicle fromJson(const QJsonObject &obj)
Deserialize an object from JSON.
Definition vehicle.cpp:281
bool isEmpty() const
Returns true if this object contains no information beyond the default values.
Definition vehicle.cpp:176
static Vehicle merge(const Vehicle &lhs, const Vehicle &rhs)
Merge two Vehicle instances.
Definition vehicle.cpp:240
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...
bool isValid() const const
QJsonValue value(QLatin1StringView key) const const
void reserve(qsizetype size)
bool isEmpty() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2025 The KDE developers.
Generated on Fri Jan 24 2025 11:50:52 by doxygen 1.13.2 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.