KItinerary

sortutil.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 "sortutil.h"
8
9#include <KItinerary/BoatTrip>
10#include <KItinerary/BusTrip>
11#include <KItinerary/Event>
12#include <KItinerary/Flight>
13#include <KItinerary/MergeUtil>
14#include <KItinerary/Person>
15#include <KItinerary/Place>
16#include <KItinerary/RentalCar>
17#include <KItinerary/Reservation>
18#include <KItinerary/Ticket>
19#include <KItinerary/TrainTrip>
20#include <KItinerary/Visit>
21
22#include "knowledgedb/airportdb.h"
23
24#include <QDateTime>
25#include <QTimeZone>
26
27using namespace KItinerary;
28
30{
31 // reservation types
33 return elem.value<FoodEstablishmentReservation>().startTime();
34 }
36 const auto hotel = elem.value<LodgingReservation>();
37 // hotel checkin/checkout is always considered the first/last thing of the day
38 auto dt = QDateTime(hotel.checkinTime().date(), QTime(23, 59, 59));
39 if (hotel.checkinTime().timeSpec() == Qt::TimeZone) {
40 dt.setTimeZone(hotel.checkinTime().timeZone());
41 }
42 return dt;
43 }
45 return elem.value<RentalCarReservation>().pickupTime();
46 }
48 return elem.value<TaxiReservation>().pickupTime();
49 }
51 const auto res = JsonLd::convert<Reservation>(elem).reservationFor();
52 return startDateTime(res);
53 }
55 return elem.value<TouristAttractionVisit>().arrivalTime();
56 }
57
58 // "reservationFor" types
59 if (JsonLd::isA<Flight>(elem)) {
60 const auto flight = elem.value<Flight>();
61 if (flight.departureTime().isValid()) {
62 return flight.departureTime();
63 }
64 if (flight.boardingTime().isValid()) {
65 return flight.boardingTime();
66 }
67 QDateTime dt(flight.departureDay(), QTime(23, 59, 59));
68 if (const auto tz = KnowledgeDb::timezoneForAirport(KnowledgeDb::IataCode{flight.departureAirport().iataCode()}); tz.isValid()) {
69 dt.setTimeZone(tz);
70 }
71 return dt;
72 }
73 if (JsonLd::isA<TrainTrip>(elem)) {
74 const auto trip = elem.value<TrainTrip>();
75 if (trip.departureTime().isValid()) {
76 return trip.departureTime();
77 }
78 return QDateTime(trip.departureDay(), QTime(23, 59, 59));
79 }
80 if (JsonLd::isA<BusTrip>(elem)) {
81 return elem.value<BusTrip>().departureTime();
82 }
83 if (JsonLd::isA<BoatTrip>(elem)) {
84 return elem.value<BoatTrip>().departureTime();
85 }
86 if (JsonLd::isA<Event>(elem)) {
87 return elem.value<Event>().startDate();
88 }
89
90 // tickets/passes
91 if (JsonLd::isA<Ticket>(elem)) {
92 return elem.value<Ticket>().validFrom();
93 }
95 return elem.value<ProgramMembership>().validFrom();
96 }
97
98 return {};
99}
100
102{
103 // reservation types
105 auto endTime = elem.value<FoodEstablishmentReservation>().endTime();
106 if (!endTime.isValid()) {
107 endTime = QDateTime(elem.value<FoodEstablishmentReservation>().startTime().date(), QTime(23, 59, 59));
108 }
109 return endTime;
110 }
112 return elem.value<RentalCarReservation>().dropoffTime();
113 }
115 const auto hotel = elem.value<LodgingReservation>();
116 // hotel checkin/checkout is always considered the first/last thing of the day
117 auto dt = QDateTime(hotel.checkoutTime().date(), QTime(0, 0, 0));
118 if (hotel.checkoutTime().timeSpec() == Qt::TimeZone) {
119 dt.setTimeZone(hotel.checkoutTime().timeZone());
120 }
121 return dt;
122 }
124 const auto res = JsonLd::convert<Reservation>(elem).reservationFor();
125 return endDateTime(res);
126 }
128 return elem.value<TouristAttractionVisit>().departureTime();
129 }
130
131 // "reservationFor" types
132 if (JsonLd::isA<Event>(elem)) {
133 return elem.value<Event>().endDate();
134 }
135 if (JsonLd::isA<Flight>(elem)) {
136 const auto flight = elem.value<Flight>();
137 if (flight.arrivalTime().isValid()) {
138 return flight.arrivalTime();
139 }
140 QDateTime dt(flight.departureDay(), QTime(23, 59, 59));
141 dt.setTimeZone(KnowledgeDb::timezoneForAirport(KnowledgeDb::IataCode{flight.arrivalAirport().iataCode()}));
142 return dt;
143 }
144 if (JsonLd::isA<TrainTrip>(elem)) {
145 const auto trip = elem.value<TrainTrip>();
146 if (trip.arrivalTime().isValid()) {
147 return trip.arrivalTime();
148 }
149 return QDateTime(trip.departureDay(), QTime(23, 59, 59));
150 }
151 if (JsonLd::isA<BusTrip>(elem)) {
152 return elem.value<BusTrip>().arrivalTime();
153 }
154 if (JsonLd::isA<BoatTrip>(elem)) {
155 return elem.value<BoatTrip>().arrivalTime();
156 }
157
158 // tickets/passes
159 if (JsonLd::isA<Ticket>(elem)) {
160 return elem.value<Ticket>().validUntil();
161 }
163 return elem.value<ProgramMembership>().validUntil();
164 }
165
166 return {};
167}
168
169bool SortUtil::isBefore(const QVariant &lhs, const QVariant &rhs)
170{
171 if (startDateTime(lhs) == startDateTime(rhs) && lhs.userType() == rhs.userType() && JsonLd::canConvert<Reservation>(lhs)) {
172 // sort by end date if available next, e.g. for overlapping hotel bookings
173 const auto lhsEndDt = endDateTime(lhs);
174 const auto rhsEndDt = endDateTime(rhs);
175 if (JsonLd::isA<LodgingReservation>(lhs) && lhsEndDt.isValid() && rhsEndDt.isValid() && lhsEndDt != rhsEndDt) {
176 return lhsEndDt < rhsEndDt;
177 }
178
179 // for multi-traveler reservations, sort by traveler name to achieve a stable result
180 const auto lhsRes = JsonLd::convert<Reservation>(lhs);
181 const auto rhsRes = JsonLd::convert<Reservation>(rhs);
182 if (!lhsRes.underName().isNull() && !rhsRes.underName().isNull() && MergeUtil::isSame(lhsRes.reservationFor(), rhsRes.reservationFor())) {
183 const auto lhsUN = lhsRes.underName().value<Person>();
184 const auto rhsUN = rhsRes.underName().value<Person>();
185
186 // for multi-ticket reservations for the same person, sort by ticket name
187 if (lhsUN.name() == rhsUN.name()) {
188 const auto lhsTicket = lhsRes.reservedTicket().value<Ticket>();
189 const auto rhsTicket = rhsRes.reservedTicket().value<Ticket>();
190 return lhsTicket.name() < rhsTicket.name();
191 }
192 return lhsUN.name() < rhsUN.name();
193 }
194 }
195 return startDateTime(lhs) < startDateTime(rhs);
196}
197
199{
201 return elem.value<FoodEstablishmentReservation>().startTime().isValid();
202 }
204 return hasStartTime(JsonLd::convert<Reservation>(elem).reservationFor());
205 }
206 if (JsonLd::isA<TrainTrip>(elem)) {
207 return elem.value<TrainTrip>().departureTime().isValid();
208 }
209 if (JsonLd::isA<Flight>(elem)) {
210 return elem.value<Flight>().departureTime().isValid();
211 }
212
213 return SortUtil::startDateTime(elem).isValid();
214}
215
217{
219 return elem.value<FoodEstablishmentReservation>().endTime().isValid();
220 }
222 return hasEndTime(JsonLd::convert<Reservation>(elem).reservationFor());
223 }
224 if (JsonLd::isA<TrainTrip>(elem)) {
225 return elem.value<TrainTrip>().arrivalTime().isValid();
226 }
227 if (JsonLd::isA<Flight>(elem)) {
228 return elem.value<Flight>().arrivalTime().isValid();
229 }
230
231 return SortUtil::endDateTime(elem).isValid();
232}
A boat or ferry trip.
Definition boattrip.h:23
A bus trip.
Definition bustrip.h:22
An event.
Definition event.h:21
A flight.
Definition flight.h:25
A hotel reservation.
Definition reservation.h:77
static bool isSame(const QVariant &lhs, const QVariant &rhs)
Checks if two Reservation or Trip values refer to the same booking element.
A person.
Definition person.h:20
A frequent traveler, bonus points or discount scheme program membership.
A Rental Car reservation.
A Taxi reservation.
A booked ticket.
Definition ticket.h:41
A train trip.
Definition traintrip.h:24
bool isA(const QVariant &value)
Returns true if value is of type T.
Definition datatypes.h:24
bool canConvert(const QVariant &value)
Checks if the given value can be up-cast to T.
Definition datatypes.h:31
T convert(const QVariant &value)
Up-cast value to T.
Definition datatypes.h:47
QTimeZone timezoneForAirport(IataCode iataCode)
Returns the timezone the airport with IATA code iataCode is in.
Definition airportdb.cpp:40
QDateTime startDateTime(const QVariant &elem)
Returns the (start) time associated with the given element.
Definition sortutil.cpp:29
bool isBefore(const QVariant &lhs, const QVariant &rhs)
Sorting function for top-level reservation/visit/event elements.
Definition sortutil.cpp:169
bool hasStartTime(const QVariant &elem)
Returns whether the given element has a start time.
Definition sortutil.cpp:198
bool hasEndTime(const QVariant &elem)
Returns whether the given element has an end time.
Definition sortutil.cpp:216
QDateTime endDateTime(const QVariant &res)
Returns the (end) time associated with the given element.
Definition sortutil.cpp:101
Classes for reservation/travel data models, data extraction and data augmentation.
Definition berelement.h:17
QDate date() const const
bool isValid() const const
void setTimeZone(const QTimeZone &toZone)
TimeZone
bool isValid() const const
int userType() const const
T value() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri Jul 26 2024 11:50:18 by doxygen 1.11.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.