Commit 2705de55 authored by Volker Krause's avatar Volker Krause

Fix spurious nested trip groups for symmetric multi-leg groups

When incrementally adding the legs, the intermediate state of the first
inner loop appearing triggered the trailing appendix pruning, which
resulted in any following outer loop adding a new superset group.

We now clean up nested groups when adding new ones, fixing that problem.
parent 5e9a9cc8
[
{
"@context": "http://schema.org",
"@type": "FlightReservation",
"reservationFor": {
"@type": "Flight",
"airline": {
"@type": "Airline",
"iataCode": "SN"
},
"arrivalAirport": {
"@type": "Airport",
"iataCode": "BRU"
},
"arrivalTime": {
"@type": "QDateTime",
"@value": "2019-04-05T08:15:00+02:00",
"timezone": "Europe/Brussels"
},
"departureAirport": {
"@type": "Airport",
"iataCode": "TXL"
},
"departureDay": "2019-04-05",
"departureTime": {
"@type": "QDateTime",
"@value": "2019-04-05T06:55:00+02:00",
"timezone": "Europe/Berlin"
},
"flightNumber": "2592"
},
"reservationNumber": "XXX007"
},
{
"@context": "http://schema.org",
"@type": "FlightReservation",
"reservationFor": {
"@type": "Flight",
"airline": {
"@type": "Airline",
"iataCode": "SN"
},
"arrivalAirport": {
"@type": "Airport",
"iataCode": "TLS"
},
"arrivalTime": {
"@type": "QDateTime",
"@value": "2019-04-05T11:15:00+02:00",
"timezone": "Europe/Paris"
},
"departureAirport": {
"@type": "Airport",
"iataCode": "BRU"
},
"departureDay": "2019-04-05",
"departureTime": {
"@type": "QDateTime",
"@value": "2019-04-05T09:35:00+02:00",
"timezone": "Europe/Brussels"
},
"flightNumber": "3667"
},
"reservationNumber": "XXX007"
},
{
"@context": "http://schema.org",
"@type": "FlightReservation",
"reservationFor": {
"@type": "Flight",
"airline": {
"@type": "Airline",
"iataCode": "SN"
},
"arrivalAirport": {
"@type": "Airport",
"iataCode": "BRU"
},
"arrivalTime": {
"@type": "QDateTime",
"@value": "2019-04-07T20:05:00+02:00",
"timezone": "Europe/Brussels"
},
"departureAirport": {
"@type": "Airport",
"iataCode": "TLS"
},
"departureDay": "2019-04-07",
"departureTime": {
"@type": "QDateTime",
"@value": "2019-04-07T18:20:00+02:00",
"timezone": "Europe/Paris"
},
"flightNumber": "3670"
},
"reservationNumber": "XXX007"
},
{
"@context": "http://schema.org",
"@type": "FlightReservation",
"reservationFor": {
"@type": "Flight",
"airline": {
"@type": "Airline",
"iataCode": "SN"
},
"arrivalAirport": {
"@type": "Airport",
"iataCode": "TXL"
},
"arrivalTime": {
"@type": "QDateTime",
"@value": "2019-04-07T22:10:00+02:00",
"timezone": "Europe/Berlin"
},
"departureAirport": {
"@type": "Airport",
"iataCode": "BRU"
},
"departureDay": "2019-04-07",
"departureTime": {
"@type": "QDateTime",
"@value": "2019-04-07T20:50:00+02:00",
"timezone": "Europe/Brussels"
},
"flightNumber": "2591"
},
"reservationNumber": "XXX007"
}
]
......@@ -111,6 +111,22 @@ private Q_SLOTS:
}
}
void testDynamicGrouping()
{
ReservationManager resMgr;
clearReservations(&resMgr);
TripGroupManager::clear();
TripGroupManager mgr;
mgr.setReservationManager(&resMgr);
// after adding the third element this will find a loop between the two inner legs and remove the first leg as a leading appendix
// the fourth leg however should be fixing that and result in a single 4 leg group
resMgr.importReservation(readFile(QLatin1String(SOURCE_DIR "/data/tripgroup/symmetric-two-leg-return-flight.json")));
QCOMPARE(mgr.tripGroups().size(), 1);
auto g = mgr.tripGroup(mgr.tripGroups().at(0));
QCOMPARE(g.elements().size(), resMgr.batches().size());
}
void testChanges()
{
ReservationManager resMgr;
......
......@@ -33,6 +33,8 @@
#include <QStandardPaths>
#include <QUuid>
#include <set>
using namespace KItinerary;
enum {
......@@ -126,7 +128,11 @@ void TripGroupManager::removeTripGroup(const QString &groupId)
}
for (const auto &elem : groupIt.value().elements()) {
m_reservationToGroupMap.remove(elem);
const auto it = m_reservationToGroupMap.find(elem);
// check if this still points to the removed group (might not be the case if an overlapping group was added meanwhile)
if (it != m_reservationToGroupMap.end() && it.value() == groupId) {
m_reservationToGroupMap.erase(it);
}
}
m_tripGroups.erase(groupIt);
if (!QFile::remove(basePath() + groupId + QLatin1String(".json"))) {
......@@ -370,11 +376,17 @@ void TripGroupManager::scanOne(std::vector<QString>::const_iterator beginIt)
return;
}
std::set<QString> pendingGroupRemovals;
if (groupIt == m_tripGroups.end()) {
const auto tgId = QUuid::createUuid().toString();
TripGroup g(this);
g.setElements(elems);
for (auto it2 = beginIt; it2 != it; ++it2) {
// remove overlapping/nested groups, delay this until the end though, as that will invalidate our iterators
const auto previousGroupId = m_reservationToGroupMap.value(*it2);
if (!previousGroupId.isEmpty() && previousGroupId != tgId) {
pendingGroupRemovals.insert(previousGroupId);
}
m_reservationToGroupMap.insert(*it2, tgId);
}
g.setName(guessName(g));
......@@ -396,6 +408,10 @@ void TripGroupManager::scanOne(std::vector<QString>::const_iterator beginIt)
g.store(basePath() + groupIt.key() + QLatin1String(".json"));
emit tripGroupChanged(groupIt.key());
}
for (const auto &tgId : pendingGroupRemovals) {
removeTripGroup(tgId);
}
}
void TripGroupManager::checkConsistency()
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment