Commit e96b5266 authored by Volker Krause's avatar Volker Krause

Support real-time journey data

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