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

KDE's Doxygen guidelines are available online.