Commit e96b5266 authored by Volker Krause's avatar Volker Krause

Support real-time journey data

parent b6df8957
......@@ -49,12 +49,12 @@ private Q_SLOTS:
{
const auto journey = res[0];
QCOMPARE(journey.sections().size(), 6);
QCOMPARE(journey.departureTime(), QDateTime({2018, 12, 2}, {22, 4, 51}));
QCOMPARE(journey.scheduledDepartureTime(), QDateTime({2018, 12, 2}, {22, 4, 51}));
QEXPECT_FAIL("", "tz propagation not implemented yet", Continue);
QCOMPARE(journey.departureTime().timeZone().id(), "Europe/Paris");
QCOMPARE(journey.arrivalTime(), QDateTime({2018, 12, 2}, {23, 0, 15}));
QCOMPARE(journey.scheduledDepartureTime().timeZone().id(), "Europe/Paris");
QCOMPARE(journey.scheduledArrivalTime(), QDateTime({2018, 12, 2}, {23, 0, 15}));
QEXPECT_FAIL("", "tz propagation not implemented yet", Continue);
QCOMPARE(journey.arrivalTime().timeZone().id(), "Europe/Paris");
QCOMPARE(journey.scheduledArrivalTime().timeZone().id(), "Europe/Paris");
QCOMPARE(journey.duration(), 3324);
auto sec = journey.sections()[0];
......@@ -64,10 +64,12 @@ private Q_SLOTS:
sec = journey.sections()[1];
QCOMPARE(sec.mode(), KPublicTransport::JourneySection::PublicTransport);
QCOMPARE(sec.departureTime(), QDateTime({2018, 12, 2}, {22, 6}, QTimeZone("Europe/Paris")));
QCOMPARE(sec.departureTime().timeZone().id(), "Europe/Paris");
QCOMPARE(sec.arrivalTime(), QDateTime({2018, 12, 2}, {22, 41}, QTimeZone("Europe/Paris")));
QCOMPARE(sec.arrivalTime().timeZone().id(), "Europe/Paris");
QCOMPARE(sec.scheduledDepartureTime(), QDateTime({2018, 12, 2}, {22, 6}, QTimeZone("Europe/Paris")));
QCOMPARE(sec.scheduledDepartureTime().timeZone().id(), "Europe/Paris");
QCOMPARE(sec.hasExpectedDepartureTime(), false);
QCOMPARE(sec.scheduledArrivalTime(), QDateTime({2018, 12, 2}, {22, 41}, QTimeZone("Europe/Paris")));
QCOMPARE(sec.scheduledArrivalTime().timeZone().id(), "Europe/Paris");
QCOMPARE(sec.hasExpectedArrivalTime(), false);
QCOMPARE(sec.duration(), 2100);
QCOMPARE(sec.from().name(), QStringLiteral("Aéroport CDG 2 TGV (Le Mesnil-Amelot)"));
QCOMPARE(sec.from().latitude(), 49.0047f);
......@@ -88,8 +90,8 @@ private Q_SLOTS:
QCOMPARE(sec.mode(), KPublicTransport::JourneySection::Waiting);
sec = journey.sections()[4];
QCOMPARE(sec.departureTime(), QDateTime({2018, 12, 2}, {22, 49}, QTimeZone("Europe/Paris")));
QCOMPARE(sec.arrivalTime(), QDateTime({2018, 12, 2}, {22, 51}, QTimeZone("Europe/Paris")));
QCOMPARE(sec.scheduledDepartureTime(), QDateTime({2018, 12, 2}, {22, 49}, QTimeZone("Europe/Paris")));
QCOMPARE(sec.scheduledArrivalTime(), QDateTime({2018, 12, 2}, {22, 51}, QTimeZone("Europe/Paris")));
QCOMPARE(sec.duration(), 120);
QCOMPARE(sec.route().line().name(), QStringLiteral("A"));
QCOMPARE(sec.route().line().color(), QColor(QStringLiteral("#D1302F")));
......
......@@ -270,16 +270,23 @@ std::vector<Journey> HafasMgateParser::parseTripSearch(const QJsonObject &obj) c
const auto secObj = secV.toObject();
JourneySection section;
// TODO add real-time data
const auto dep = secObj.value(QLatin1String("dep")).toObject();
section.setDepartureTime(QDateTime::fromString(dateStr + dep.value(QLatin1String("dTimeS")).toString(), QLatin1String("yyyyMMddhhmmss")));
section.setScheduledDepartureTime(QDateTime::fromString(dateStr + dep.value(QLatin1String("dTimeS")).toString(), QLatin1String("yyyyMMddhhmmss")));
const auto dTimeR = dep.value(QLatin1String("dTimeR")).toString();
if (!dTimeR.isEmpty()) {
section.setExpectedDepartureTime(QDateTime::fromString(dateStr + dTimeR, QLatin1String("yyyyMMddhhmmss")));
}
auto locIdx = dep.value(QLatin1String("locX")).toInt();
if ((unsigned int)locIdx < locs.size()) {
section.setFrom(locs[locIdx]);
}
const auto arr = secObj.value(QLatin1String("arr")).toObject();
section.setArrivalTime(QDateTime::fromString(dateStr + arr.value(QLatin1String("aTimeS")).toString(), QLatin1String("yyyyMMddhhmmss")));
section.setScheduledArrivalTime(QDateTime::fromString(dateStr + arr.value(QLatin1String("aTimeS")).toString(), QLatin1String("yyyyMMddhhmmss")));
const auto aTimeR = dep.value(QLatin1String("aTimeR")).toString();
if (!aTimeR.isEmpty()) {
section.setExpectedArrivalTime(QDateTime::fromString(dateStr + aTimeR, QLatin1String("yyyyMMddhhmmss")));
}
locIdx = arr.value(QLatin1String("locX")).toInt();
if ((unsigned int)locIdx < locs.size()) {
section.setTo(locs[locIdx]);
......
......@@ -130,8 +130,9 @@ static JourneySection parseJourneySection(const QJsonObject &obj)
section.setFrom(parseWrappedLocation(obj.value(QLatin1String("from")).toObject()));
section.setTo(parseWrappedLocation(obj.value(QLatin1String("to")).toObject()));
section.setRoute(route);
section.setDepartureTime(parseDateTime(obj.value(QLatin1String("departure_date_time")), section.from().timeZone()));
section.setArrivalTime(parseDateTime(obj.value(QLatin1String("arrival_date_time")), section.to().timeZone()));
// TODO realtime data
section.setScheduledArrivalTime(parseDateTime(obj.value(QLatin1String("departure_date_time")), section.from().timeZone()));
section.setScheduledDepartureTime(parseDateTime(obj.value(QLatin1String("arrival_date_time")), section.to().timeZone()));
const auto typeStr = obj.value(QLatin1String("type")).toString();
if (typeStr == QLatin1String("public_transport")) {
......
......@@ -28,8 +28,10 @@ class JourneySectionPrivate : public QSharedData
{
public:
JourneySection::Mode mode = JourneySection::Invalid;
QDateTime departureTime;
QDateTime arrivalTime;
QDateTime scheduledDepartureTime;
QDateTime expectedDepartureTime;
QDateTime scheduledArrivalTime;
QDateTime expectedArrivalTime;
Location from;
Location to;
Route route;
......@@ -56,31 +58,79 @@ void JourneySection::setMode(JourneySection::Mode mode)
d->mode = mode;
}
QDateTime JourneySection::departureTime() const
QDateTime JourneySection::scheduledDepartureTime() const
{
return d->departureTime;
return d->scheduledDepartureTime;
}
void JourneySection::setDepartureTime(const QDateTime &dt)
void JourneySection::setScheduledDepartureTime(const QDateTime &dt)
{
d.detach();
d->departureTime = dt;
d->scheduledDepartureTime = dt;
}
QDateTime JourneySection::arrivalTime() const
QDateTime JourneySection::expectedDepartureTime() const
{
return d->arrivalTime;
return d->expectedDepartureTime;
}
void JourneySection::setArrivalTime(const QDateTime &dt)
void JourneySection::setExpectedDepartureTime(const QDateTime &dt)
{
d.detach();
d->arrivalTime = dt;
d->expectedDepartureTime = dt;
}
bool JourneySection::hasExpectedDepartureTime() const
{
return d->expectedDepartureTime.isValid();
}
int JourneySection::departureDelay() const
{
if (hasExpectedDepartureTime()) {
return d->scheduledDepartureTime.secsTo(d->expectedDepartureTime) / 60;
}
return 0;
}
QDateTime JourneySection::scheduledArrivalTime() const
{
return d->scheduledArrivalTime;
}
void JourneySection::setScheduledArrivalTime(const QDateTime &dt)
{
d.detach();
d->scheduledArrivalTime = dt;
}
QDateTime JourneySection::expectedArrivalTime() const
{
return d->expectedArrivalTime;
}
void JourneySection::setExpectedArrivalTime(const QDateTime &dt)
{
d.detach();
d->expectedArrivalTime = dt;
}
bool JourneySection::hasExpectedArrivalTime() const
{
return d->expectedArrivalTime.isValid();
}
int JourneySection::arrivalDelay() const
{
if (hasExpectedArrivalTime()) {
return d->scheduledArrivalTime.secsTo(d->expectedArrivalTime) / 60;
}
return 0;
}
int JourneySection::duration() const
{
return d->departureTime.secsTo(d->arrivalTime);
return d->scheduledDepartureTime.secsTo(d->scheduledArrivalTime);
}
Location JourneySection::from() const
......@@ -143,25 +193,25 @@ QVariantList Journey::sectionsVariant() const
return l;
}
QDateTime KPublicTransport::Journey::departureTime() const
QDateTime Journey::scheduledDepartureTime() const
{
if (!d->sections.empty()) {
return d->sections.front().departureTime();
return d->sections.front().scheduledDepartureTime();
}
return {};
}
QDateTime Journey::arrivalTime() const
QDateTime Journey::scheduledArrivalTime() const
{
if (!d->sections.empty()) {
return d->sections.back().arrivalTime();
return d->sections.back().scheduledArrivalTime();
}
return {};
}
int Journey::duration() const
{
return departureTime().secsTo(arrivalTime());
return scheduledDepartureTime().secsTo(scheduledArrivalTime());
}
#include "moc_journey.cpp"
......@@ -36,12 +36,32 @@ class JourneySection
KPUBLICTRANSPORT_GADGET(JourneySection)
/** Mode of transport for this section. */
Q_PROPERTY(Mode mode READ mode WRITE setMode)
/** Departue time for this segment. */
Q_PROPERTY(QDateTime departureTime READ departureTime WRITE setDepartureTime)
/** Arrival time for this segment. */
Q_PROPERTY(QDateTime arrivalTime READ arrivalTime WRITE setArrivalTime)
/** Planned departure time. */
Q_PROPERTY(QDateTime scheduledDepartureTime READ scheduledDepartureTime WRITE setScheduledDepartureTime)
/** Actual departure time, if available.
* Set to invalid to indicate real-time data is not available.
*/
Q_PROPERTY(QDateTime expectedDepartureTime READ expectedDepartureTime WRITE setExpectedDepartureTime)
/** @c true if this has real-time data. */
Q_PROPERTY(bool hasExpectedDepartureTime READ hasExpectedDepartureTime STORED false)
/** Difference to schedule in minutes. */
Q_PROPERTY(int departureDelay READ departureDelay STORED false)
/** Planned arrival time. */
Q_PROPERTY(QDateTime scheduledArrivalTime READ scheduledArrivalTime WRITE setScheduledArrivalTime)
/** Actual arrival time, if available.
* Set to invalid to indicate real-time data is not available.
*/
Q_PROPERTY(QDateTime expectedArrivalTime READ expectedArrivalTime WRITE setExpectedArrivalTime)
/** @c true if this has real-time data. */
Q_PROPERTY(bool hasExpectedArrivalTime READ hasExpectedArrivalTime STORED false)
/** Difference to schedule in minutes. */
Q_PROPERTY(int arrivalDelay READ arrivalDelay STORED false)
/** Duration of the section in seconds. */
Q_PROPERTY(int duration READ duration STORED false)
/** Departure location of this segment. */
Q_PROPERTY(KPublicTransport::Location from READ from WRITE setFrom)
/** Arrival location of this segment. */
......@@ -49,7 +69,7 @@ class JourneySection
/** Route to take on this segment. */
Q_PROPERTY(KPublicTransport::Route route READ route WRITE setRoute)
// TODO: planned vs. expected times?
// TODO: platforms
public:
/** Mode of transport. */
......@@ -63,11 +83,23 @@ public:
Q_ENUM(Mode)
Mode mode() const;
void setMode(Mode mode);
QDateTime departureTime() const;
void setDepartureTime(const QDateTime &dt);
QDateTime arrivalTime() const;
void setArrivalTime(const QDateTime &dt);
QDateTime scheduledDepartureTime() const;
void setScheduledDepartureTime(const QDateTime &dt);
QDateTime expectedDepartureTime() const;
void setExpectedDepartureTime(const QDateTime &dt);
bool hasExpectedDepartureTime() const;
int departureDelay() const;
QDateTime scheduledArrivalTime() const;
void setScheduledArrivalTime(const QDateTime &dt);
QDateTime expectedArrivalTime() const;
void setExpectedArrivalTime(const QDateTime &dt);
bool hasExpectedArrivalTime() const;
int arrivalDelay() const;
int duration() const;
Location from() const;
void setFrom(const Location &from);
Location to() const;
......@@ -84,10 +116,10 @@ class Journey
KPUBLICTRANSPORT_GADGET(Journey)
/** Journey sections for consumption by QML. */
Q_PROPERTY(QVariantList sections READ sectionsVariant)
/** Departure time of the journey. */
Q_PROPERTY(QDateTime departureTime READ departureTime STORED false)
/** Arrival time of the journey. */
Q_PROPERTY(QDateTime arrivalTime READ arrivalTime STORED false)
/** Departure time of the journey, according to schedule. */
Q_PROPERTY(QDateTime scheduledDepartureTime READ scheduledDepartureTime STORED false)
/** Arrival time of the journey, according to schedule. */
Q_PROPERTY(QDateTime scheduledArrivalTime READ scheduledArrivalTime STORED false)
/** Duration of the entire journey in seconds. */
Q_PROPERTY(int duration READ duration STORED false)
public:
......@@ -98,8 +130,8 @@ public:
/** Sets the journey sections. */
void setSections(std::vector<JourneySection> &&sections);
QDateTime departureTime() const;
QDateTime arrivalTime() const;
QDateTime scheduledDepartureTime() const;
QDateTime scheduledArrivalTime() const;
int duration() const;
private:
QVariantList sectionsVariant() const;
......
......@@ -50,7 +50,7 @@ void JourneyReplyPrivate::finalizeResult()
postProcessJourneys();
std::sort(journeys.begin(), journeys.end(), [](const auto &lhs, const auto &rhs) {
return lhs.departureTime() < rhs.departureTime();
return lhs.scheduledDepartureTime() < rhs.scheduledDepartureTime();
});
}
......@@ -65,17 +65,17 @@ void JourneyReplyPrivate::postProcessJourneys()
auto from = section.from();
from.setTimeZone(section.to().timeZone());
section.setFrom(from);
auto dt = section.departureTime();
auto dt = section.scheduledDepartureTime();
dt.setTimeZone(from.timeZone());
section.setDepartureTime(dt);
section.setScheduledDepartureTime(dt);
}
if (section.from().timeZone().isValid() && !section.to().timeZone().isValid()) {
auto to = section.to();
to.setTimeZone(section.from().timeZone());
section.setTo(to);
auto dt = section.arrivalTime();
auto dt = section.scheduledArrivalTime();
dt.setTimeZone(to.timeZone());
section.setArrivalTime(dt);
section.setScheduledArrivalTime(dt);
}
}
}
......
......@@ -73,9 +73,9 @@ public:
for (const auto &journey : res) {
qDebug() << journey.sections().size();
for (const auto &section : journey.sections()) {
qDebug() << " From" << section.from().name() << section.departureTime();
qDebug() << " From" << section.from().name() << section.scheduledDepartureTime();
qDebug() << " Mode" << section.mode() << section.route().line().name() << section.route().direction() << section.route().line().modeString();
qDebug() << " To" << section.to().name() << section.arrivalTime();
qDebug() << " To" << section.to().name() << section.scheduledArrivalTime();
}
}
} else {
......
......@@ -170,10 +170,16 @@ Kirigami.ApplicationWindow {
text: "From: " + modelData.from.name
}
// TODO platform
QQC2.Label {
text: "Departure: " + modelData.departureTime.toTimeString()
RowLayout {
QQC2.Label {
text: "Departure: " + modelData.scheduledDepartureTime.toTimeString()
}
QQC2.Label {
text: (modelData.departureDelay >= 0 ? "+" : "") + modelData.departureDelay
color: modelData.departureDelay > 1 ? Kirigami.Theme.negativeTextColor : Kirigami.Theme.positiveTextColor
visible: modelData.hasExpectedDepartureTime
}
}
// TODO departure delay
QQC2.Label {
text: {
switch (modelData.mode) {
......@@ -193,10 +199,16 @@ Kirigami.ApplicationWindow {
text: "To: " + modelData.to.name
}
// TODO platform
QQC2.Label {
text: "Arrival: " + modelData.arrivalTime.toTimeString()
RowLayout {
QQC2.Label {
text: "Arrival: " + modelData.scheduledArrivalTime.toTimeString()
}
QQC2.Label {
text: (modelData.arrivalDelay >= 0 ? "+" : "") + modelData.arrivalDelay
color: modelData.arrivalDelay > 1 ? Kirigami.Theme.negativeTextColor : Kirigami.Theme.positiveTextColor
visible: modelData.hasExpectedArrivalTime
}
}
// TODO arrival delay
}
}
}
......
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