KPublicTransport

journey.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 "journey.h"
8#include "journeyutil_p.h"
9#include "json_p.h"
10#include "datatypes_p.h"
11#include "loadutil_p.h"
12#include "mergeutil_p.h"
13#include "notesutil_p.h"
14#include "platformutils_p.h"
15#include "rentalvehicle.h"
16#include "rentalvehicleutil_p.h"
17#include "stopover.h"
18
19#include <QDebug>
20#include <QVariant>
21
22using namespace Qt::Literals::StringLiterals;
23using namespace KPublicTransport;
24
25namespace KPublicTransport {
26
27class JourneySectionPrivate : public QSharedData
28{
29public:
30 JourneySection::Mode mode = JourneySection::Invalid;
31 QDateTime scheduledDepartureTime;
32 QDateTime expectedDepartureTime;
33 QDateTime scheduledArrivalTime;
34 QDateTime expectedArrivalTime;
35 Location from;
36 Location to;
37 Route route;
38 QString scheduledDeparturePlatform;
39 QString expectedDeparturePlatform;
40 QString scheduledArrivalPlatform;
41 QString expectedArrivalPlatform;
42 int distance = 0;
43 Disruption::Effect disruptionEffect = Disruption::NormalService;
44 QStringList notes;
45 std::vector<Stopover> intermediateStops;
46 int co2Emission = -1;
47 std::vector<LoadInfo> loadInformation;
48 RentalVehicle rentalVehicle;
49 Path path;
50 Vehicle departureVehicleLayout;
51 Platform departurePlatformLayout;
52 Vehicle arrivalVehicleLayout;
53 Platform arrivalPlatformLayout;
54 IndividualTransport individualTransport;
55};
56
57class JourneyPrivate : public QSharedData
58{
59public:
60 std::vector<JourneySection> sections;
61};
62
63}
64
65KPUBLICTRANSPORT_MAKE_GADGET(JourneySection)
66KPUBLICTRANSPORT_MAKE_PROPERTY(JourneySection, JourneySection::Mode, mode, setMode)
67KPUBLICTRANSPORT_MAKE_PROPERTY(JourneySection, QDateTime, scheduledDepartureTime, setScheduledDepartureTime)
68KPUBLICTRANSPORT_MAKE_PROPERTY(JourneySection, QDateTime, expectedDepartureTime, setExpectedDepartureTime)
69KPUBLICTRANSPORT_MAKE_PROPERTY(JourneySection, QDateTime, scheduledArrivalTime, setScheduledArrivalTime)
70KPUBLICTRANSPORT_MAKE_PROPERTY(JourneySection, QDateTime, expectedArrivalTime, setExpectedArrivalTime)
71KPUBLICTRANSPORT_MAKE_PROPERTY(JourneySection, Location, from, setFrom)
72KPUBLICTRANSPORT_MAKE_PROPERTY(JourneySection, Location, to, setTo)
73KPUBLICTRANSPORT_MAKE_PROPERTY(JourneySection, Route, route, setRoute)
74KPUBLICTRANSPORT_MAKE_PROPERTY(JourneySection, Disruption::Effect, disruptionEffect, setDisruptionEffect)
75KPUBLICTRANSPORT_MAKE_PROPERTY(JourneySection, QStringList, notes, setNotes)
76KPUBLICTRANSPORT_MAKE_PROPERTY(JourneySection, RentalVehicle, rentalVehicle, setRentalVehicle)
77KPUBLICTRANSPORT_MAKE_PROPERTY(JourneySection, Path, path, setPath)
78KPUBLICTRANSPORT_MAKE_PROPERTY(JourneySection, Vehicle, departureVehicleLayout, setDepartureVehicleLayout)
79KPUBLICTRANSPORT_MAKE_PROPERTY(JourneySection, Platform, departurePlatformLayout, setDeparturePlatformLayout)
80KPUBLICTRANSPORT_MAKE_PROPERTY(JourneySection, Vehicle, arrivalVehicleLayout, setArrivalVehicleLayout)
81KPUBLICTRANSPORT_MAKE_PROPERTY(JourneySection, Platform, arrivalPlatformLayout, setArrivalPlatformLayout)
82KPUBLICTRANSPORT_MAKE_PROPERTY(JourneySection, KPublicTransport::IndividualTransport, individualTransport, setIndividualTransport)
83
85{
86 return d->expectedDepartureTime.isValid();
87}
88
90{
92 return d->scheduledDepartureTime.secsTo(d->expectedDepartureTime) / 60;
93 }
94 return 0;
95}
96
98{
99 return d->expectedArrivalTime.isValid();
100}
101
103{
105 return d->scheduledArrivalTime.secsTo(d->expectedArrivalTime) / 60;
106 }
107 return 0;
108}
109
110int JourneySection::duration() const
111{
112 return d->scheduledDepartureTime.secsTo(d->scheduledArrivalTime);
113}
114
115int JourneySection::distance() const
116{
117 if (d->mode == JourneySection::Waiting) {
118 return 0;
119 }
120
121 int dist = 0;
122 if (d->from.hasCoordinate() && d->to.hasCoordinate()) {
123 float startLat = d->from.latitude();
124 float startLon = d->from.longitude();
125
126 for (const auto &stop : d->intermediateStops) {
127 if (!stop.stopPoint().hasCoordinate()) {
128 continue;
129 }
130 dist += Location::distance(startLat, startLon, stop.stopPoint().latitude(), stop.stopPoint().longitude());
131 startLat = stop.stopPoint().latitude();
132 startLon = stop.stopPoint().longitude();
133 }
134
135 dist += Location::distance(startLat, startLon, d->to.latitude(), d->to.longitude());
136 }
137 dist = std::max(dist, d->path.distance());
138 return std::max(dist, d->distance);
139}
140
141void JourneySection::setDistance(int value)
142{
143 d.detach();
144 d->distance = value;
145}
146
148{
149 return d->scheduledDeparturePlatform;
150}
151
152void JourneySection::setScheduledDeparturePlatform(const QString &platform)
153{
154 d.detach();
155 d->scheduledDeparturePlatform = PlatformUtils::normalizePlatform(platform);
156}
157
159{
160 return d->expectedDeparturePlatform;
161}
162
163void JourneySection::setExpectedDeparturePlatform(const QString &platform)
164{
165 d.detach();
166 d->expectedDeparturePlatform = PlatformUtils::normalizePlatform(platform);
167}
168
170{
171 return !d->expectedDeparturePlatform.isEmpty();
172}
173
175{
176 return PlatformUtils::platformChanged(d->scheduledDeparturePlatform, d->expectedDeparturePlatform);
177}
178
180{
181 return d->scheduledArrivalPlatform;
182}
183
184void JourneySection::setScheduledArrivalPlatform(const QString &platform)
185{
186 d.detach();
187 d->scheduledArrivalPlatform = PlatformUtils::normalizePlatform(platform);
188}
189
191{
192 return d->expectedArrivalPlatform;
193}
194
195void JourneySection::setExpectedArrivalPlatform(const QString &platform)
196{
197 d.detach();
198 d->expectedArrivalPlatform = PlatformUtils::normalizePlatform(platform);
199}
200
202{
203 return !d->expectedArrivalPlatform.isEmpty();
204}
205
207{
208 return PlatformUtils::platformChanged(d->scheduledArrivalPlatform, d->expectedArrivalPlatform);
209}
210
212{
213 const auto n = NotesUtil::normalizeNote(note);
214 const auto idx = NotesUtil::needsAdding(d->notes, n);
215 if (idx >= 0) {
216 d.detach();
217 NotesUtil::performAdd(d->notes, n, idx);
218 }
219}
220
221void JourneySection::addNotes(const QStringList &notes)
222{
223 for (const auto &n : notes) {
224 addNote(n);
225 }
226}
227
228const std::vector<Stopover>& JourneySection::intermediateStops() const
229{
230 return d->intermediateStops;
231}
232
234{
235 d.detach();
236 return std::move(d->intermediateStops);
237}
238
239void JourneySection::setIntermediateStops(std::vector<Stopover> &&stops)
240{
241 d.detach();
242 d->intermediateStops = std::move(stops);
243}
244
245QVariantList JourneySection::intermediateStopsVariant() const
246{
247 QVariantList l;
248 l.reserve(d->intermediateStops.size());
249 std::transform(d->intermediateStops.begin(), d->intermediateStops.end(), std::back_inserter(l), [](const auto &stop) { return QVariant::fromValue(stop); });
250 return l;
251}
252
254{
255 Stopover dep;
256 dep.setStopPoint(from());
257 dep.setRoute(route());
258 dep.setScheduledDepartureTime(scheduledDepartureTime());
259 dep.setExpectedDepartureTime(expectedDepartureTime());
260 dep.setScheduledPlatform(scheduledDeparturePlatform());
261 dep.setExpectedPlatform(expectedDeparturePlatform());
262 dep.addNotes(notes());
263 dep.setDisruptionEffect(disruptionEffect());
264 dep.setVehicleLayout(departureVehicleLayout());
265 dep.setPlatformLayout(departurePlatformLayout());
266 return dep;
267}
268
270{
271 setFrom(departure.stopPoint());
272 setScheduledDepartureTime(departure.scheduledDepartureTime());
273 setExpectedDepartureTime(departure.expectedDepartureTime());
274 setScheduledDeparturePlatform(departure.scheduledPlatform());
275 setExpectedDeparturePlatform(departure.expectedPlatform());
276 setDeparturePlatformLayout(departure.platformLayout());
277 setDepartureVehicleLayout(departure.vehicleLayout());
278}
279
281{
282 Stopover arr;
283 arr.setStopPoint(to());
284 arr.setRoute(route());
285 arr.setScheduledArrivalTime(scheduledArrivalTime());
286 arr.setExpectedArrivalTime(expectedArrivalTime());
287 arr.setScheduledPlatform(scheduledArrivalPlatform());
288 arr.setExpectedPlatform(expectedArrivalPlatform());
289 arr.setDisruptionEffect(disruptionEffect());
290 arr.setVehicleLayout(arrivalVehicleLayout());
291 arr.setPlatformLayout(arrivalPlatformLayout());
292 return arr;
293}
294
296{
297 setTo(arrival.stopPoint());
298 setScheduledArrivalTime(arrival.scheduledArrivalTime());
299 setExpectedArrivalTime(arrival.expectedArrivalTime());
300 setScheduledArrivalPlatform(arrival.scheduledPlatform());
301 setExpectedArrivalPlatform(arrival.expectedPlatform());
302 setArrivalPlatformLayout(arrival.platformLayout());
303 setArrivalVehicleLayout(arrival.vehicleLayout());
304}
305
307{
308 // TODO handle rental vehicles and ride sharing in here!
309 if (d->co2Emission >= 0) {
310 return d->co2Emission;
311 }
312
313 struct {
315 int gramPerKm;
316 } static const emissionForModeMap[] = {
317 { Line::Air, 285 },
318 { Line::Boat, 245 },
319 { Line::Bus, 68 },
320 { Line::BusRapidTransit, 68 },
321 { Line::Coach, 68 },
322 { Line::Ferry, 245 },
323 { Line::LocalTrain, 14 },
324 { Line::LongDistanceTrain, 14 },
325 { Line::Metro, 11 },
326 { Line::RapidTransit, 11 },
327 { Line::Taxi, 158 },
328 { Line::Train, 14 },
329 { Line::Tramway, 11 },
330 };
331
332 const auto mode = route().line().mode();
333 for (const auto &map : emissionForModeMap) {
334 if (map.mode == mode) {
335 return (map.gramPerKm * distance()) / 1000;
336 }
337 }
338 return -1;
339}
340
341void JourneySection::setCo2Emission(int value)
342{
343 d.detach();
344 d->co2Emission = value;
345}
346
347const std::vector<LoadInfo>& JourneySection::loadInformation() const
348{
349 return d->loadInformation;
350}
351
352std::vector<LoadInfo>&& JourneySection::takeLoadInformation()
353{
354 d.detach();
355 return std::move(d->loadInformation);
356}
357
358void JourneySection::setLoadInformation(std::vector<LoadInfo> &&loadInfo)
359{
360 d.detach();
361 d->loadInformation = std::move(loadInfo);
362}
363
364QVariantList JourneySection::loadInformationVariant() const
365{
366 QVariantList l;
367 l.reserve(d->loadInformation.size());
368 std::transform(d->loadInformation.begin(), d->loadInformation.end(), std::back_inserter(l), [](const auto &load) { return QVariant::fromValue(load); });
369 return l;
370}
371
372const std::vector<KPublicTransport::Feature>& JourneySection::features() const
373{
374 return d->departureVehicleLayout.features();
375}
376
377[[nodiscard]] std::vector<KPublicTransport::Feature>&& JourneySection::takeFeatures()
378{
379 return d->departureVehicleLayout.takeFeatures();
380}
381
382void JourneySection::setFeatures(std::vector<KPublicTransport::Feature> &&features)
383{
384 d.detach();
385 d->departureVehicleLayout.setFeatures(std::move(features));
386}
387
389{
390 switch (d->mode) {
391 case JourneySection::Invalid:
392 return {};
393 case JourneySection::PublicTransport:
394 return d->route.line().iconName();
395 case JourneySection::Transfer:
396 return u"qrc:///org.kde.kpublictransport/assets/images/transfer.svg"_s;
397 case JourneySection::Walking:
398 return IndividualTransport::modeIconName(IndividualTransport::Walk);
399 case JourneySection::Waiting:
400 return u"qrc:///org.kde.kpublictransport/assets/images/wait.svg"_s;
402 return d->rentalVehicle.vehicleTypeIconName();
404 return d->individualTransport.modeIconName();
405 }
406
407 return u"question"_s;
408}
409
411{
412 if (!from().hasCoordinate() || mode() != JourneySection::PublicTransport) {
413 return;
414 }
415 auto line = d->route.line();
416 line.applyMetaData(from(), download);
417 d->route.setLine(line);
418
419 // propagate to intermediate stops
420 for (auto &stop : d->intermediateStops) {
421 stop.setRoute(d->route);
422 }
423}
424
426{
427 if (lhs.d->mode != rhs.d->mode) {
428 return false;
429 }
430
432 return false;
433 }
434
435 // we have N criteria to compare here, with 3 possible results:
436 // - equal
437 // - similar-ish, unknwon, or at least not conflicting
438 // - conflicting
439 // A single conflict results in a negative result, at least N - 1 equal comparisons lead to
440 // in a positive result.
441 enum { Equal = 1, Compatible = 0, Conflict = -1000 };
442 int result = 0;
443
444 const auto depTimeDist = MergeUtil::distance(lhs.d->scheduledDepartureTime, rhs.d->scheduledDepartureTime);
445 result += depTimeDist < 60 ? Equal : depTimeDist <= 60 ? Compatible : Conflict;
446 const auto arrTimeDist = MergeUtil::distance(lhs.d->scheduledArrivalTime, rhs.d->scheduledArrivalTime);
447 result += arrTimeDist < 60 ? Equal : depTimeDist <= 60 ? Compatible : Conflict;
448
449 const auto sameFrom = Location::isSame(lhs.d->from, rhs.d->from);
450 const auto fromDist = Location::distance(lhs.from(), rhs.from());
451 result += sameFrom ? Equal : fromDist < 200 ? Compatible : Conflict;
452
453 const auto sameTo = Location::isSame(lhs.d->to, rhs.d->to);
454 const auto toDist = Location::distance(lhs.to(), rhs.to());
455 result += sameTo ? Equal : toDist < 200 ? Compatible : Conflict;
456
457 const auto sameRoute = Route::isSame(lhs.d->route, rhs.d->route);
458 const auto sameDir = Location::isSameName(lhs.d->route.direction(), rhs.d->route.direction());
459 const auto sameLine = Line::isSame(lhs.d->route.line(), rhs.d->route.line());
460 result += sameRoute ? Equal : (sameDir || sameLine) ? Compatible : Conflict;
461
463 result += lhs.scheduledDeparturePlatform() == rhs.scheduledDeparturePlatform() ? Equal : Conflict;
464 }
465
466 return result >= 4;
467}
468
470{
471 using namespace MergeUtil;
472 auto res = lhs;
473 res.setScheduledDepartureTime(mergeDateTimeEqual(lhs.scheduledDepartureTime(), rhs.scheduledDepartureTime()));
474 res.setExpectedDepartureTime(mergeDateTimeMax(lhs.expectedDepartureTime(), rhs.expectedDepartureTime()));
475 res.setScheduledArrivalTime(mergeDateTimeMax(lhs.scheduledArrivalTime(), rhs.scheduledArrivalTime()));
476 res.setExpectedArrivalTime(mergeDateTimeMax(lhs.expectedArrivalTime(), rhs.expectedArrivalTime()));
477
478 if (res.expectedDeparturePlatform().isEmpty()) {
479 res.setExpectedDeparturePlatform(rhs.expectedDeparturePlatform());
480 }
481 if (res.expectedArrivalPlatform().isEmpty()) {
482 res.setExpectedArrivalPlatform(rhs.expectedArrivalPlatform());
483 }
484 res.setFrom(Location::merge(lhs.from(), rhs.from()));
485 res.setTo(Location::merge(lhs.to(), rhs.to()));
486 res.setRoute(Route::merge(lhs.route(), rhs.route()));
487
488 res.setScheduledDeparturePlatform(mergeString(lhs.scheduledDeparturePlatform(), rhs.scheduledDeparturePlatform()));
489 res.setScheduledArrivalPlatform(mergeString(lhs.scheduledArrivalPlatform(), rhs.scheduledArrivalPlatform()));
490
491 res.setDisruptionEffect(std::max(lhs.disruptionEffect(), rhs.disruptionEffect()));
492 res.setNotes(NotesUtil::mergeNotes(lhs.notes(), rhs.notes()));
493 res.setDistance(std::max(lhs.distance(), rhs.distance()));
494
495 if (lhs.intermediateStops().size() == rhs.intermediateStops().size()) {
496 auto stops = res.takeIntermediateStops();
497 for (uint i = 0; i < stops.size(); ++i) {
498 stops[i] = Stopover::merge(stops[i], rhs.intermediateStops()[i]);
499 stops[i].setRoute(res.route());
500 }
501 res.setIntermediateStops(std::move(stops));
502 }
503
504 res.d->co2Emission = std::max(lhs.d->co2Emission, rhs.d->co2Emission);
505 res.d->loadInformation = LoadUtil::merge(lhs.d->loadInformation, rhs.d->loadInformation);
506 res.d->rentalVehicle = RentalVehicleUtil::merge(lhs.d->rentalVehicle, rhs.d->rentalVehicle);
507
508 res.d->path = lhs.d->path.sections().size() < rhs.d->path.sections().size() ? rhs.d->path : lhs.d->path;
509
510 res.d->departureVehicleLayout = Vehicle::merge(lhs.d->departureVehicleLayout, rhs.d->departureVehicleLayout);
511 res.d->departurePlatformLayout = Platform::merge(lhs.d->departurePlatformLayout, rhs.d->departurePlatformLayout);
512 res.d->arrivalVehicleLayout = Vehicle::merge(lhs.d->arrivalVehicleLayout, rhs.d->arrivalVehicleLayout);
513 res.d->arrivalPlatformLayout = Platform::merge(lhs.d->arrivalPlatformLayout, rhs.d->arrivalPlatformLayout);
514
515 return res;
516}
517
519{
520 auto obj = Json::toJson(section);
521 if (section.mode() != Waiting) {
522 const auto fromObj = Location::toJson(section.from());
523 if (!fromObj.empty()) {
524 obj.insert(QLatin1String("from"), fromObj);
525 }
526 const auto toObj = Location::toJson(section.to());
527 if (!toObj.empty()) {
528 obj.insert(QLatin1String("to"), toObj);
529 }
530 }
531 if (section.mode() == PublicTransport) {
532 const auto routeObj = Route::toJson(section.route());
533 if (!routeObj.empty()) {
534 obj.insert(QLatin1String("route"), routeObj);
535 }
536 if (!section.intermediateStops().empty()) {
537 obj.insert(QLatin1String("intermediateStops"), Stopover::toJson(section.intermediateStops()));
538 }
539 if (!section.loadInformation().empty()) {
540 obj.insert(QLatin1String("load"), LoadInfo::toJson(section.loadInformation()));
541 }
542 }
543 if (section.d->co2Emission < 0) {
544 obj.remove(QLatin1String("co2Emission"));
545 }
546 if (section.rentalVehicle().type() != RentalVehicle::Unknown) {
547 obj.insert(QLatin1String("rentalVehicle"), RentalVehicle::toJson(section.rentalVehicle()));
548 }
549
550 if (!section.path().isEmpty()) {
551 obj.insert(QLatin1String("path"), Path::toJson(section.path()));
552 }
553
554 if (!section.departureVehicleLayout().isEmpty()) {
555 obj.insert(QLatin1String("departureVehicleLayout"), Vehicle::toJson(section.departureVehicleLayout()));
556 }
557 if (!section.departurePlatformLayout().isEmpty()) {
558 obj.insert(QLatin1String("departurePlatformLayout"), Platform::toJson(section.departurePlatformLayout()));
559 }
560 if (!section.arrivalVehicleLayout().isEmpty()) {
561 obj.insert(QLatin1String("arrivalVehicleLayout"), Vehicle::toJson(section.arrivalVehicleLayout()));
562 }
563 if (!section.arrivalPlatformLayout().isEmpty()) {
564 obj.insert(QLatin1String("arrivalPlatformLayout"), Platform::toJson(section.arrivalPlatformLayout()));
565 }
566
567 if (section.mode() == JourneySection::IndividualTransport) {
568 obj.insert(QLatin1String("individualTransport"), IndividualTransport::toJson(section.individualTransport()));
569 }
570
571 if (obj.size() <= 3) { // only the disruption and mode enums and distance, ie. this is an empty object
572 return {};
573 }
574 return obj;
575}
576
577QJsonArray JourneySection::toJson(const std::vector<JourneySection> &sections)
578{
579 return Json::toJson(sections);
580}
581
583{
584 auto section = Json::fromJson<JourneySection>(obj);
585 section.setFrom(Location::fromJson(obj.value(QLatin1String("from")).toObject()));
586 section.setTo(Location::fromJson(obj.value(QLatin1String("to")).toObject()));
587 section.setRoute(Route::fromJson(obj.value(QLatin1String("route")).toObject()));
588 section.setIntermediateStops(Stopover::fromJson(obj.value(QLatin1String("intermediateStops")).toArray()));
589 section.setLoadInformation(LoadInfo::fromJson(obj.value(QLatin1String("load")).toArray()));
590 section.setRentalVehicle(RentalVehicle::fromJson(obj.value(QLatin1String("rentalVehicle")).toObject()));
591 section.setPath(Path::fromJson(obj.value(QLatin1String("path")).toObject()));
592 section.setDepartureVehicleLayout(Vehicle::fromJson(obj.value(QLatin1String("departureVehicleLayout")).toObject()));
593 section.setDeparturePlatformLayout(Platform::fromJson(obj.value(QLatin1String("departurePlatformLayout")).toObject()));
594 section.setArrivalVehicleLayout(Vehicle::fromJson(obj.value(QLatin1String("arrivalVehicleLayout")).toObject()));
595 section.setArrivalPlatformLayout(Platform::fromJson(obj.value(QLatin1String("arrivalPlatformLayout")).toObject()));
596 section.setIndividualTransport(IndividualTransport::fromJson(obj.value(QLatin1String("individualTransport")).toObject()));
597 section.applyMetaData(false);
598 return section;
599}
600
601std::vector<JourneySection> JourneySection::fromJson(const QJsonArray &array)
602{
603 return Json::fromJson<JourneySection>(array);
604}
605
606
607KPUBLICTRANSPORT_MAKE_GADGET(Journey)
608
609const std::vector<JourneySection>& Journey::sections() const
610{
611 return d->sections;
612}
613
614std::vector<JourneySection>&& Journey::takeSections()
615{
616 d.detach();
617 return std::move(d->sections);
618}
619
620void Journey::setSections(std::vector<JourneySection> &&sections)
621{
622 d.detach();
623 d->sections = std::move(sections);
624}
625
626QVariantList Journey::sectionsVariant() const
627{
628 QVariantList l;
629 l.reserve(d->sections.size());
630 std::transform(d->sections.begin(), d->sections.end(), std::back_inserter(l), [](const auto &sec) { return QVariant::fromValue(sec); });
631 return l;
632}
633
635{
636 if (!d->sections.empty()) {
637 return d->sections.front().scheduledDepartureTime();
638 }
639 return {};
640}
641
643{
644 return d->sections.empty() ? false : d->sections.front().hasExpectedDepartureTime();
645}
646
648{
649 return d->sections.empty() ? QDateTime() : d->sections.front().expectedDepartureTime();
650}
651
652int Journey::departureDelay() const
653{
654 return d->sections.empty() ? 0 : d->sections.front().departureDelay();
655}
656
658{
659 if (!d->sections.empty()) {
660 return d->sections.back().scheduledArrivalTime();
661 }
662 return {};
663}
664
666{
667 return d->sections.empty() ? false : d->sections.back().hasExpectedArrivalTime();
668}
669
671{
672 return d->sections.empty() ? QDateTime() : d->sections.back().expectedArrivalTime();
673}
674
675int Journey::arrivalDelay() const
676{
677 return d->sections.empty() ? 0 : d->sections.back().arrivalDelay();
678}
679
680int Journey::duration() const
681{
683}
684
685int Journey::numberOfChanges() const
686{
687 return std::max(0, static_cast<int>(std::count_if(d->sections.begin(), d->sections.end(), [](const auto &section) { return section.mode() == JourneySection::PublicTransport; }) - 1));
688}
689
691{
692 Disruption::Effect effect = Disruption::NormalService;
693 for (const auto &sec : d->sections) {
694 effect = std::max(effect, sec.disruptionEffect());
695 }
696 return effect;
697}
698
699void Journey::applyMetaData(bool download)
700{
701 for (auto &sec : d->sections) {
702 sec.applyMetaData(download);
703 }
704}
705
706static bool isTransportSection(JourneySection::Mode mode)
707{
708 return mode == JourneySection::PublicTransport
711}
712
713bool Journey::isSame(const Journey &lhs, const Journey &rhs)
714{
715 auto lIt = lhs.sections().begin();
716 auto rIt = rhs.sections().begin();
717
718 while (lIt != lhs.sections().end() || rIt != rhs.sections().end()) {
719 // ignore non-transport sections
720 if (lIt != lhs.sections().end() && !isTransportSection((*lIt).mode())) {
721 ++lIt;
722 continue;
723 }
724 if (rIt != rhs.sections().end() && !isTransportSection((*rIt).mode())) {
725 ++rIt;
726 continue;
727 }
728
729 if (lIt == lhs.sections().end() || rIt == rhs.sections().end()) {
730 return false;
731 }
732
733 if (!JourneySection::isSame(*lIt, *rIt)) {
734 return false;
735 }
736
737 ++lIt;
738 ++rIt;
739 }
740
741 Q_ASSERT(lIt == lhs.sections().end() && rIt == rhs.sections().end());
742 return true;
743}
744
745Journey Journey::merge(const Journey &lhs, const Journey &rhs)
746{
747 std::vector<JourneySection> sections;
748 sections.reserve(lhs.sections().size() + rhs.sections().size());
749 std::copy(lhs.sections().begin(), lhs.sections().end(), std::back_inserter(sections));
750 std::copy(rhs.sections().begin(), rhs.sections().end(), std::back_inserter(sections));
751 std::sort(sections.begin(), sections.end(), [](const auto &lSec, const auto &rSec) {
752 if (MergeUtil::distance(lSec.scheduledDepartureTime(), rSec.scheduledDepartureTime()) == 0) {
753 return lSec.mode() < rSec.mode();
754 }
755 return MergeUtil::isBefore(lSec.scheduledDepartureTime(), rSec.scheduledDepartureTime());
756 });
757
758 for (auto it = sections.begin(); it != sections.end(); ++it) {
759 const auto nextIt = it + 1;
760 if (nextIt == sections.end()) {
761 break;
762 }
763
764 if (JourneySection::isSame(*it, *nextIt) || ((*it).mode() == (*nextIt).mode() && (*it).mode() != JourneySection::PublicTransport)) {
765 *it = JourneySection::merge(*it, *nextIt);
766 sections.erase(nextIt);
767 }
768 }
769
770 Journey res;
771 res.setSections(std::move(sections));
772 return res;
773}
774
776{
777 QJsonObject obj;
778 obj.insert(QLatin1String("sections"), JourneySection::toJson(journey.sections()));
779 return obj;
780}
781
782QJsonArray Journey::toJson(const std::vector<Journey> &journeys)
783{
784 return Json::toJson(journeys);
785}
786
788{
789 Journey j;
790 j.setSections(JourneySection::fromJson(obj.value(QLatin1String("sections")).toArray()));
791 return j;
792}
793
794std::vector<Journey> Journey::fromJson(const QJsonArray &array)
795{
796 return Json::fromJson<Journey>(array);
797}
798
799#include "moc_journey.cpp"
Individual transport mode details for a journey section, and for specifying journey requests.
static QJsonObject toJson(const IndividualTransport &it)
Serializes one object to JSON.
static IndividualTransport fromJson(const QJsonObject &obj)
Deserialize an object from JSON.
QString modeIconName
Name of an icon to represent this transport mode.
A segment of a journey plan.
Definition journey.h:32
KPublicTransport::Path path
Movement path for this journey section.
Definition journey.h:141
void applyMetaData(bool download)
Augment line meta data.
Definition journey.cpp:410
bool arrivalPlatformChanged
true if we have real-time platform information and the platform changed.
Definition journey.h:105
QString scheduledDeparturePlatform
Planned departure platform.
Definition journey.h:90
static JourneySection merge(const JourneySection &lhs, const JourneySection &rhs)
Merge two instances.
Definition journey.cpp:469
void setDeparture(const Stopover &departure)
Sets all departure properties from a given Stopover.
Definition journey.cpp:269
static bool isSame(const JourneySection &lhs, const JourneySection &rhs)
Checks if two instances refer to the same journey section (which does not necessarily mean they are e...
Definition journey.cpp:425
void setLoadInformation(std::vector< LoadInfo > &&loadInfo)
Set the vehicle load information for this journey section.
Definition journey.cpp:358
KPublicTransport::Location from
Departure location of this segment.
Definition journey.h:83
QDateTime expectedArrivalTime
Actual arrival time, if available.
Definition journey.h:71
QString expectedArrivalPlatform
Actual arrival platform, in case real-time information are available.
Definition journey.h:101
QString iconName
The best available icon to represent this journey section.
Definition journey.h:167
int departureDelay
Difference to schedule in minutes.
Definition journey.h:64
void setIntermediateStops(std::vector< Stopover > &&stops)
Set the intermediate stops.
Definition journey.cpp:239
KPublicTransport::Platform arrivalPlatformLayout
Platform layout information at arrival.
Definition journey.h:153
int co2Emission
CO₂ emission during this journey section, in gram.
Definition journey.h:127
KPublicTransport::RentalVehicle rentalVehicle
Information about a rental vehicle, for sections using one.
Definition journey.h:135
QStringList notes
General human-readable notes on this service, e.g.
Definition journey.h:110
void setArrival(const Stopover &arrival)
Sets all arrival properties from a given Stopover.
Definition journey.cpp:295
static QJsonObject toJson(const JourneySection &section)
Serializes one journey section to JSON.
Definition journey.cpp:518
QDateTime scheduledDepartureTime
Planned departure time.
Definition journey.h:56
bool hasExpectedArrivalPlatform
true if real-time platform information are available.
Definition journey.h:103
@ RentedVehicle
free floating or dock-based rental bike service, electric scooters, car sharing services,...
Definition journey.h:45
@ IndividualTransport
using your own vehicle (bike, car, etc).
Definition journey.h:46
KPublicTransport::Route route
Route to take on this segment.
Definition journey.h:87
KPublicTransport::Disruption::Effect disruptionEffect
Disruption effect on this section, if any.
Definition journey.h:108
KPublicTransport::Stopover departure
All departure information represented as Stopover object.
Definition journey.h:116
QVariantList loadInformation
Vehicle load information for this journey section.
Definition journey.h:132
KPublicTransport::Vehicle arrivalVehicleLayout
Vehicle coach layout information at arrival.
Definition journey.h:151
QVariantList intermediateStops
Intermediate stops for consumption by QML.
Definition journey.h:113
KPublicTransport::Platform departurePlatformLayout
Platform layout information at departure.
Definition journey.h:146
int arrivalDelay
Difference to schedule in minutes.
Definition journey.h:75
KPublicTransport::Location to
Arrival location of this segment.
Definition journey.h:85
std::vector< Stopover > && takeIntermediateStops()
Moves the intermediate stops out of this object.
Definition journey.cpp:233
bool hasExpectedDeparturePlatform
true if real-time platform information are available.
Definition journey.h:94
QString scheduledArrivalPlatform
Planned arrival platform.
Definition journey.h:99
bool hasExpectedDepartureTime
true if this has real-time data.
Definition journey.h:62
bool hasExpectedArrivalTime
true if this has real-time data.
Definition journey.h:73
QString expectedDeparturePlatform
Actual departure platform, in case real-time information are available.
Definition journey.h:92
static JourneySection fromJson(const QJsonObject &obj)
Deserialize an object from JSON.
Definition journey.cpp:582
std::vector< LoadInfo > && takeLoadInformation()
Moves the load information out of this object for modification.
Definition journey.cpp:352
KPublicTransport::Vehicle departureVehicleLayout
Vehicle coach layout information at departure.
Definition journey.h:144
std::vector< KPublicTransport::Feature > features
Features of the vehicle used on this section.
Definition journey.h:162
void addNote(const QString &note)
Adds a note.
Definition journey.cpp:211
int duration
Duration of the section in seconds.
Definition journey.h:78
Mode mode
Mode of transport for this section.
Definition journey.h:53
QDateTime scheduledArrivalTime
Planned arrival time.
Definition journey.h:67
KPublicTransport::IndividualTransport individualTransport
Individual transport details for sections using your own vehicle.
Definition journey.h:156
bool departurePlatformChanged
true if we have real-time platform information and the platform changed.
Definition journey.h:96
QDateTime expectedDepartureTime
Actual departure time, if available.
Definition journey.h:60
KPublicTransport::Stopover arrival
All arrival information represented as Stopover object.
Definition journey.h:118
int distance
Distance of the section in meter.
Definition journey.h:80
A journey plan.
Definition journey.h:267
void applyMetaData(bool download)
Augment line meta data.
Definition journey.cpp:699
KPublicTransport::Disruption::Effect disruptionEffect
Worst disruption effect of any of the journey sections.
Definition journey.h:298
static Journey fromJson(const QJsonObject &obj)
Deserialize an object from JSON.
Definition journey.cpp:787
QDateTime expectedDepartureTime
Actual departure time, if available.
Definition journey.h:278
QDateTime scheduledDepartureTime
Departure time of the journey, according to schedule.
Definition journey.h:272
static bool isSame(const Journey &lhs, const Journey &rhs)
Checks if two instances refer to the same journey (which does not necessarily mean they are exactly e...
Definition journey.cpp:713
QVariantList sections
Journey sections for consumption by QML.
Definition journey.h:270
QDateTime expectedArrivalTime
Actual arrival time, if available.
Definition journey.h:289
int departureDelay
Difference to schedule in minutes.
Definition journey.h:280
int numberOfChanges
Number of changes on this journey.
Definition journey.h:296
void setSections(std::vector< JourneySection > &&sections)
Sets the journey sections.
Definition journey.cpp:620
static QJsonObject toJson(const Journey &journey)
Serializes one journey object to JSON.
Definition journey.cpp:775
bool hasExpectedDepartureTime
true if this has real-time data.
Definition journey.h:274
int duration
Duration of the entire journey in seconds.
Definition journey.h:294
QDateTime scheduledArrivalTime
Arrival time of the journey, according to schedule.
Definition journey.h:283
int arrivalDelay
Difference to schedule in minutes.
Definition journey.h:291
std::vector< JourneySection > && takeSections()
Moves the journey sections out of this object.
Definition journey.cpp:614
static Journey merge(const Journey &lhs, const Journey &rhs)
Merge two instances.
Definition journey.cpp:745
bool hasExpectedArrivalTime
true if this has real-time data.
Definition journey.h:285
KPublicTransport::Line::Mode mode
Type of transport.
Definition line.h:61
Mode
Mode of transportation.
Definition line.h:27
static bool isSame(const Line &lhs, const Line &rhs)
Checks if to instances refer to the same line (which does not necessarily mean they are exactly equal...
Definition line.cpp:152
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:497
static bool isSameName(const QString &lhs, const QString &rhs)
Checks if two location names refer to the same location.
Definition location.cpp:333
static QJsonObject toJson(const Location &loc)
Serializes one Location object to JSON.
Definition location.cpp:456
static float distance(float lat1, float lon1, float lat2, float lon2)
Compute the distance between two geo coordinates, in meters.
Definition location.cpp:436
static Location merge(const Location &lhs, const Location &rhs)
Merge two departure instances.
Definition location.cpp:380
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:274
A path followed by any kind of location change.
Definition path.h:101
bool isEmpty() const
Returns true if this is an empty/not-set path.
Definition path.cpp:131
static Path fromJson(const QJsonObject &obj)
Deserialize an object from JSON.
Definition path.cpp:175
static QJsonObject toJson(const Path &path)
Serializes one path object to JSON.
Definition path.cpp:168
std::vector< KPublicTransport::PathSection > sections
Access to path sections for QML.
Definition path.h:105
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
An individual rental vehicle used on a JourneySection, ie.
static RentalVehicle fromJson(const QJsonObject &obj)
Deserialize an object from JSON.
static QJsonObject toJson(const RentalVehicle &vehicle)
Serializes one object to JSON.
VehicleType type
Vehicle type.
A route of a public transport line.
Definition line.h:146
QString direction
Direction of the route.
Definition line.h:155
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:251
static QJsonObject toJson(const Route &r)
Serializes one object to JSON.
Definition line.cpp:271
static Route merge(const Route &lhs, const Route &rhs)
Merge two Route instances.
Definition line.cpp:261
KPublicTransport::Line line
Line this route belongs to.
Definition line.h:149
static Route fromJson(const QJsonObject &obj)
Deserialize an object from JSON.
Definition line.cpp:284
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:205
QDateTime expectedDepartureTime
Actual departure time, if available.
Definition stopover.h:45
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:232
KPublicTransport::Location stopPoint
The stop point of this departure.
Definition stopover.h:64
QDateTime expectedArrivalTime
Actual arrival time, if available.
Definition stopover.h:34
QDateTime scheduledArrivalTime
Planned arrival time.
Definition stopover.h:30
static Stopover fromJson(const QJsonObject &obj)
Deserialize an object from JSON.
Definition stopover.cpp:264
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:186
static QJsonObject toJson(const Vehicle &vehicle)
Serializes one vehicle object to JSON.
Definition vehicle.cpp:340
static Vehicle fromJson(const QJsonObject &obj)
Deserialize an object from JSON.
Definition vehicle.cpp:357
bool isEmpty() const
Returns true if this object contains no information beyond the default values.
Definition vehicle.cpp:252
static Vehicle merge(const Vehicle &lhs, const Vehicle &rhs)
Merge two Vehicle instances.
Definition vehicle.cpp:316
void stop(Ekos::AlignState mode)
Effect
Disruption effects, numerical sorted so that higher values imply more severe disruptions.
Definition disruption.h:25
Query operations and data types for accessing realtime public transport information from online servi...
QAction * back(const QObject *recvr, const char *slot, QObject *parent)
qint64 secsTo(const QDateTime &other) const const
iterator insert(QLatin1StringView key, const QJsonValue &value)
QJsonValue value(QLatin1StringView key) const const
bool isEmpty() const const
QFuture< void > map(Iterator begin, Iterator end, MapFunctor &&function)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri Jul 19 2024 11:50:59 by doxygen 1.11.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.