journeyreply.cpp 4.11 KB
Newer Older
Volker Krause's avatar
Volker Krause committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
/*
    Copyright (C) 2018 Volker Krause <vkrause@kde.org>

    This program is free software; you can redistribute it and/or modify it
    under the terms of the GNU Library General Public License as published by
    the Free Software Foundation; either version 2 of the License, or (at your
    option) any later version.

    This program is distributed in the hope that it will be useful, but WITHOUT
    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
    License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <https://www.gnu.org/licenses/>.
*/

#include "journeyreply.h"
19
#include "reply_p.h"
Volker Krause's avatar
Volker Krause committed
20
#include "journeyrequest.h"
Volker Krause's avatar
Volker Krause committed
21
#include "logging.h"
Volker Krause's avatar
Volker Krause committed
22 23 24 25 26

#include <KPublicTransport/Journey>
#include <KPublicTransport/Location>

#include <QDateTime>
27
#include <QTimeZone>
Volker Krause's avatar
Volker Krause committed
28 29 30 31

using namespace KPublicTransport;

namespace KPublicTransport {
32
class JourneyReplyPrivate : public ReplyPrivate {
Volker Krause's avatar
Volker Krause committed
33
public:
34
    void finalizeResult() override;
35 36
    void postProcessJourneys();

37
    JourneyRequest request;
Volker Krause's avatar
Volker Krause committed
38 39 40 41
    std::vector<Journey> journeys;
};
}

42 43 44 45 46 47 48 49
void JourneyReplyPrivate::finalizeResult()
{
    if (journeys.empty()) {
        return;
    }

    error = Reply::NoError;
    errorMsg.clear();
50 51 52

    postProcessJourneys();
    std::sort(journeys.begin(), journeys.end(), [](const auto &lhs, const auto &rhs) {
Volker Krause's avatar
Volker Krause committed
53
        return lhs.scheduledDepartureTime() < rhs.scheduledDepartureTime();
54
    });
55 56
}

57 58 59 60 61 62 63 64 65 66 67
void JourneyReplyPrivate::postProcessJourneys()
{
    // try to fill gaps in timezone data
    for (auto &journey : journeys) {
        auto sections = journey.takeSections();
        for (auto &section : sections) {
            if (section.mode() == JourneySection::Walking) {
                if (!section.from().timeZone().isValid() && section.to().timeZone().isValid()) {
                    auto from = section.from();
                    from.setTimeZone(section.to().timeZone());
                    section.setFrom(from);
Volker Krause's avatar
Volker Krause committed
68
                    auto dt = section.scheduledDepartureTime();
69
                    dt.setTimeZone(from.timeZone());
Volker Krause's avatar
Volker Krause committed
70
                    section.setScheduledDepartureTime(dt);
71 72 73 74 75
                }
                if (section.from().timeZone().isValid() && !section.to().timeZone().isValid()) {
                    auto to = section.to();
                    to.setTimeZone(section.from().timeZone());
                    section.setTo(to);
Volker Krause's avatar
Volker Krause committed
76
                    auto dt = section.scheduledArrivalTime();
77
                    dt.setTimeZone(to.timeZone());
Volker Krause's avatar
Volker Krause committed
78
                    section.setScheduledArrivalTime(dt);
79 80 81 82 83
                }
            }
        }
        journey.setSections(std::move(sections));
    }
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102

    // sort and merge results
    std::sort(journeys.begin(), journeys.end(), [](const auto &lhs, const auto &rhs) {
        return lhs.scheduledDepartureTime() < rhs.scheduledDepartureTime();
    });
    for (auto it = journeys.begin(); it != journeys.end(); ++it) {
        for (auto mergeIt = it + 1; mergeIt != journeys.end();) {
            if ((*it).scheduledDepartureTime() != (*mergeIt).scheduledDepartureTime()) {
                break;
            }

            if (Journey::isSame(*it, *mergeIt)) {
                *it = Journey::merge(*it, *mergeIt);
                mergeIt = journeys.erase(mergeIt);
            } else {
                ++mergeIt;
            }
        }
    }
103 104
}

105
JourneyReply::JourneyReply(const JourneyRequest &req)
106
    : Reply(new JourneyReplyPrivate)
Volker Krause's avatar
Volker Krause committed
107
{
108 109
    Q_D(JourneyReply);
    d->request = req;
Volker Krause's avatar
Volker Krause committed
110 111 112 113
}

JourneyReply::~JourneyReply() = default;

114 115 116 117 118 119
JourneyRequest JourneyReply::request() const
{
    Q_D(const JourneyReply);
    return d->request;
}

Volker Krause's avatar
Volker Krause committed
120 121
std::vector<Journey> JourneyReply::journeys() const
{
122
    Q_D(const JourneyReply);
Volker Krause's avatar
Volker Krause committed
123 124 125
    // TODO avoid the copy here
    return d->journeys;
}
126 127 128 129 130 131 132 133 134 135 136 137 138

void JourneyReply::addResult(std::vector<Journey> &&res)
{
    Q_D(JourneyReply);
    if (d->journeys.empty()) {
        d->journeys = std::move(res);
    } else {
        d->journeys.insert(d->journeys.end(), res.begin(), res.end());
    }

    d->pendingOps--;
    d->emitFinishedIfDone(this);
}