Commit af2ec896 authored by Volker Krause's avatar Volker Krause

Parse arrival responses, and add arrival data to Departure

Yes, Departure still needs a better name...
parent 18b7700d
......@@ -139,8 +139,10 @@ private slots:
{
const auto departure = res[0];
QCOMPARE(departure.scheduledTime(), QDateTime({2018, 12, 10}, {17, 17}, QTimeZone("Europe/Paris")));
QCOMPARE(departure.hasExpectedTime(), false);
QCOMPARE(departure.scheduledDepartureTime(), QDateTime({2018, 12, 10}, {17, 17}, QTimeZone("Europe/Paris")));
QCOMPARE(departure.hasExpectedDepartureTime(), false);
QCOMPARE(departure.scheduledArrivalTime(), QDateTime({2018, 12, 10}, {17, 17}, QTimeZone("Europe/Paris")));
QCOMPARE(departure.hasExpectedArrivalTime(), false);
QCOMPARE(departure.stopPoint().name(), QStringLiteral("Gare de Lyon - Diderot (Paris)"));
QCOMPARE(departure.route().direction(), QStringLiteral("Porte de la Chapelle (Paris)"));
QCOMPARE(departure.route().line().mode(), KPublicTransport::Line::Bus);
......@@ -150,9 +152,9 @@ private slots:
{
const auto departure = res[3];
QCOMPARE(departure.scheduledTime(), QDateTime({2018, 12, 10}, {17, 19}, QTimeZone("Europe/Paris")));
QCOMPARE(departure.hasExpectedTime(), true);
QCOMPARE(departure.expectedTime(), QDateTime({2018, 12, 10}, {17, 21}, QTimeZone("Europe/Paris")));
QCOMPARE(departure.scheduledDepartureTime(), QDateTime({2018, 12, 10}, {17, 19}, QTimeZone("Europe/Paris")));
QCOMPARE(departure.hasExpectedDepartureTime(), true);
QCOMPARE(departure.expectedDepartureTime(), QDateTime({2018, 12, 10}, {17, 21}, QTimeZone("Europe/Paris")));
QCOMPARE(departure.stopPoint().name(), QStringLiteral("Gare de Lyon RER D (Paris)"));
QCOMPARE(departure.route().direction(), QStringLiteral("Gare de Villiers le Bel Gonesse Arnouville (Arnouville)"));
QCOMPARE(departure.route().line().mode(), KPublicTransport::Line::RapidTransit);
......
......@@ -40,9 +40,9 @@ App.TimelineDelegate {
font.pointSize: Kirigami.Theme.defaultFont.pointSize * root.headerFontScale
}
QQC2.Label {
text: (departure.delay >= 0 ? "+" : "") + departure.delay
color: (departure.delay > 1) ? Kirigami.Theme.negativeTextColor : Kirigami.Theme.positiveTextColor
visible: departure.hasExpectedTime
text: (departure.departureDelay >= 0 ? "+" : "") + departure.departureDelay
color: (departure.departureDelay > 1) ? Kirigami.Theme.negativeTextColor : Kirigami.Theme.positiveTextColor
visible: departure.hasExpectedDepartureTime
}
}
......
......@@ -148,11 +148,11 @@ void LiveDataManager::checkTrainTrip(const TrainTrip& trip, const QString& resId
}
for (const auto &dep : reply->departures()) {
qCDebug(Log) << "Got departure information:" << dep.route().line().name() << dep.scheduledTime() << "for" << trip.trainNumber();
if (dep.scheduledTime() != trip.departureTime() || !isSameLine(dep.route().line().name(), trip.trainName(), trip.trainNumber())) {
qCDebug(Log) << "Got departure information:" << dep.route().line().name() << dep.scheduledDepartureTime() << "for" << trip.trainNumber();
if (dep.scheduledDepartureTime() != trip.departureTime() || !isSameLine(dep.route().line().name(), trip.trainName(), trip.trainNumber())) {
continue;
}
qCDebug(Log) << "Found departure information:" << dep.route().line().name() << dep.expectedPlatform() << dep.expectedTime();
qCDebug(Log) << "Found departure information:" << dep.route().line().name() << dep.expectedPlatform() << dep.expectedDepartureTime();
m_departures.insert(resId, dep);
emit departureUpdated(resId);
break;
......
......@@ -134,14 +134,25 @@ std::vector<Departure> HafasMgateParser::parseStationBoardResponse(const QJsonOb
dep.setRoute(route);
const auto dateStr = jnyObj.value(QLatin1String("date")).toString();
dep.setScheduledTime(QDateTime::fromString(dateStr + stbStop.value(QLatin1String("dTimeS")).toString(), QLatin1String("yyyyMMddhhmmss")));
dep.setScheduledDepartureTime(QDateTime::fromString(dateStr + stbStop.value(QLatin1String("dTimeS")).toString(), QLatin1String("yyyyMMddhhmmss")));
const auto dTimeR = stbStop.value(QLatin1String("dTimeR")).toString();
if (!dTimeR.isEmpty()) {
dep.setExpectedTime(QDateTime::fromString(dateStr + dTimeR, QLatin1String("yyyyMMddhhmmss")));
dep.setExpectedDepartureTime(QDateTime::fromString(dateStr + dTimeR, QLatin1String("yyyyMMddhhmmss")));
}
dep.setScheduledArrivalTime(QDateTime::fromString(dateStr + stbStop.value(QLatin1String("aTimeS")).toString(), QLatin1String("yyyyMMddhhmmss")));
const auto aTimeR = stbStop.value(QLatin1String("aTimeR")).toString();
if (!aTimeR.isEmpty()) {
dep.setExpectedArrivalTime(QDateTime::fromString(dateStr + aTimeR, QLatin1String("yyyyMMddhhmmss")));
}
dep.setScheduledPlatform(stbStop.value(QLatin1String("dPlatfS")).toString());
dep.setExpectedPlatform(stbStop.value(QLatin1String("dPlatfR")).toString());
if (dep.scheduledPlatform().isEmpty()) {
dep.setScheduledPlatform(stbStop.value(QLatin1String("aPlatfS")).toString());
}
if (dep.expectedPlatform().isEmpty()) {
dep.setExpectedPlatform(stbStop.value(QLatin1String("aPlatfR")).toString());
}
const auto locIdx = stbStop.value(QLatin1String("locX")).toInt();
if ((unsigned int)locIdx < locs.size()) {
......
......@@ -205,9 +205,11 @@ static Departure parseDeparture(const QJsonObject &obj)
const auto dtObj = obj.value(QLatin1String("stop_date_time")).toObject();
departure.setStopPoint(parseLocation(obj.value(QLatin1String("stop_point")).toObject()));
departure.setScheduledTime(parseDateTime(dtObj.value(QLatin1String("base_departure_date_time")), departure.stopPoint().timeZone()));
departure.setScheduledDepartureTime(parseDateTime(dtObj.value(QLatin1String("base_departure_date_time")), departure.stopPoint().timeZone()));
departure.setScheduledArrivalTime(parseDateTime(dtObj.value(QLatin1String("base_arrival_date_time")), departure.stopPoint().timeZone()));
if (dtObj.value(QLatin1String("data_freshness")).toString() != QLatin1String("base_schedule")) {
departure.setExpectedTime(parseDateTime(dtObj.value(QLatin1String("departure_date_time")), departure.stopPoint().timeZone()));
departure.setExpectedDepartureTime(parseDateTime(dtObj.value(QLatin1String("departure_date_time")), departure.stopPoint().timeZone()));
departure.setExpectedArrivalTime(parseDateTime(dtObj.value(QLatin1String("arrival_date_time")), departure.stopPoint().timeZone()));
}
return departure;
......
......@@ -25,8 +25,10 @@ using namespace KPublicTransport;
namespace KPublicTransport {
class DeparturePrivate : public QSharedData {
public:
QDateTime scheduledTime;
QDateTime expectedTime;
QDateTime scheduledArrivalTime;
QDateTime expectedArrivalTime;
QDateTime scheduledDepartureTime;
QDateTime expectedDepartureTime;
QString scheduledPlatform;
QString expectedPlatform;
Route route;
......@@ -36,37 +38,72 @@ public:
KPUBLICTRANSPORT_MAKE_GADGET(Departure)
QDateTime Departure::scheduledTime() const
QDateTime Departure::scheduledArrivalTime() const
{
return d->scheduledTime;
return d->scheduledArrivalTime;
}
void Departure::setScheduledTime(const QDateTime &scheduledTime)
void Departure::setScheduledArrivalTime(const QDateTime &scheduledTime)
{
d.detach();
d->scheduledTime = scheduledTime;
d->scheduledArrivalTime = scheduledTime;
}
QDateTime Departure::expectedTime() const
QDateTime Departure::expectedArrivalTime() const
{
return d->expectedTime;
return d->expectedArrivalTime;
}
void Departure::setExpectedTime(const QDateTime &expectedTime)
void Departure::setExpectedArrivalTime(const QDateTime &expectedTime)
{
d.detach();
d->expectedTime = expectedTime;
d->expectedArrivalTime = expectedTime;
}
bool Departure::hasExpectedTime() const
bool Departure::hasExpectedArrivalTime() const
{
return d->expectedTime.isValid();
return d->expectedArrivalTime.isValid();
}
int Departure::delay() const
int Departure::arrivalDelay() const
{
if (hasExpectedTime()) {
return d->scheduledTime.secsTo(d->expectedTime) / 60;
if (hasExpectedArrivalTime()) {
return d->scheduledArrivalTime.secsTo(d->expectedArrivalTime) / 60;
}
return 0;
}
QDateTime Departure::scheduledDepartureTime() const
{
return d->scheduledDepartureTime;
}
void Departure::setScheduledDepartureTime(const QDateTime &scheduledTime)
{
d.detach();
d->scheduledDepartureTime = scheduledTime;
}
QDateTime Departure::expectedDepartureTime() const
{
return d->expectedDepartureTime;
}
void Departure::setExpectedDepartureTime(const QDateTime &expectedTime)
{
d.detach();
d->expectedDepartureTime = expectedTime;
}
bool Departure::hasExpectedDepartureTime() const
{
return d->expectedDepartureTime.isValid();
}
int Departure::departureDelay() const
{
if (hasExpectedDepartureTime()) {
return d->scheduledDepartureTime.secsTo(d->expectedDepartureTime) / 60;
}
return 0;
}
......@@ -122,7 +159,8 @@ void Departure::setStopPoint(const Location &stopPoint)
bool Departure::isSame(const Departure &lhs, const Departure &rhs)
{
if (lhs.scheduledTime() != rhs.scheduledTime()) {
if ((lhs.scheduledDepartureTime().isValid() && lhs.scheduledDepartureTime() != rhs.scheduledDepartureTime()) ||
(lhs.scheduledArrivalTime().isValid() && lhs.scheduledArrivalTime() != rhs.scheduledArrivalTime())) {
return false;
}
......@@ -132,8 +170,17 @@ bool Departure::isSame(const Departure &lhs, const Departure &rhs)
Departure Departure::merge(const Departure &lhs, const Departure &rhs)
{
auto dep = lhs;
if (!dep.hasExpectedTime() && rhs.hasExpectedTime()) {
dep.setExpectedTime(rhs.expectedTime());
if (!dep.scheduledDepartureTime().isValid() && rhs.scheduledDepartureTime().isValid()) {
dep.setScheduledDepartureTime(rhs.scheduledDepartureTime());
}
if (!dep.hasExpectedDepartureTime() && rhs.hasExpectedDepartureTime()) {
dep.setExpectedDepartureTime(rhs.expectedDepartureTime());
}
if (!dep.scheduledArrivalTime().isValid() && rhs.scheduledArrivalTime().isValid()) {
dep.setScheduledArrivalTime(rhs.scheduledArrivalTime());
}
if (!dep.hasExpectedArrivalTime() && rhs.hasExpectedArrivalTime()) {
dep.setExpectedArrivalTime(rhs.expectedArrivalTime());
}
if (dep.scheduledPlatform().isEmpty() && !rhs.scheduledPlatform().isEmpty()) {
dep.setScheduledPlatform(rhs.scheduledPlatform());
......
......@@ -28,19 +28,32 @@ namespace KPublicTransport {
class DeparturePrivate;
/** Information about a departure of a vehicle at a stop area. */
/** Information about an arrival and/or departure of a vehicle at a stop area. */
class Departure
{
KPUBLICTRANSPORT_GADGET(Departure)
/** 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)
/** Planned departure time. */
Q_PROPERTY(QDateTime scheduledTime READ scheduledTime WRITE setScheduledTime)
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 expectedTime READ expectedTime WRITE setExpectedTime)
Q_PROPERTY(QDateTime expectedDepartureTime READ expectedDepartureTime WRITE setExpectedDepartureTime)
/** @c true if this has real-time data. */
Q_PROPERTY(bool hasExpectedTime READ hasExpectedTime STORED false)
Q_PROPERTY(bool hasExpectedDepartureTime READ hasExpectedDepartureTime STORED false)
/** Difference to schedule in minutes. */
Q_PROPERTY(int departureDelay READ departureDelay)
/** Planned departure platform. */
Q_PROPERTY(QString scheduledPlatform READ scheduledPlatform WRITE setScheduledPlatform)
......@@ -55,16 +68,20 @@ class Departure
/** The stop point of this departure. */
Q_PROPERTY(KPublicTransport::Location stopPoint READ stopPoint WRITE setStopPoint)
/** Difference to schedule in minutes. */
Q_PROPERTY(int delay READ delay)
public:
QDateTime scheduledTime() const;
void setScheduledTime(const QDateTime &scheduledTime);
QDateTime expectedTime() const;
void setExpectedTime(const QDateTime &expectedTime);
bool hasExpectedTime() const;
int delay() const;
QDateTime scheduledArrivalTime() const;
void setScheduledArrivalTime(const QDateTime &scheduledTime);
QDateTime expectedArrivalTime() const;
void setExpectedArrivalTime(const QDateTime &expectedTime);
bool hasExpectedArrivalTime() const;
int arrivalDelay() const;
QDateTime scheduledDepartureTime() const;
void setScheduledDepartureTime(const QDateTime &scheduledTime);
QDateTime expectedDepartureTime() const;
void setExpectedDepartureTime(const QDateTime &expectedTime);
bool hasExpectedDepartureTime() const;
int departureDelay() const;
QString scheduledPlatform() const;
void setScheduledPlatform(const QString &platform);
......
......@@ -44,14 +44,26 @@ void DepartureReplyPrivate::finalizeResult()
error = Reply::NoError;
errorMsg.clear();
std::sort(departures.begin(), departures.end(), [](const auto &lhs, const auto &rhs) {
return lhs.scheduledTime() < rhs.scheduledTime();
});
if (request.mode() == DepartureRequest::QueryDeparture) {
std::sort(departures.begin(), departures.end(), [](const auto &lhs, const auto &rhs) {
return lhs.scheduledDepartureTime() < rhs.scheduledDepartureTime();
});
} else {
std::sort(departures.begin(), departures.end(), [](const auto &lhs, const auto &rhs) {
return lhs.scheduledArrivalTime() < rhs.scheduledArrivalTime();
});
}
for (auto it = departures.begin(); it != departures.end(); ++it) {
for (auto mergeIt = it + 1; mergeIt != departures.end();) {
if ((*it).scheduledTime() != (*mergeIt).scheduledTime()) {
break;
if (request.mode() == DepartureRequest::QueryDeparture) {
if ((*it).scheduledDepartureTime() != (*mergeIt).scheduledDepartureTime()) {
break;
}
} else {
if ((*it).scheduledArrivalTime() != (*mergeIt).scheduledArrivalTime()) {
break;
}
}
if (Departure::isSame(*it, *mergeIt)) {
......
......@@ -71,7 +71,7 @@ public:
engine->rootContext()->setContextProperty(QStringLiteral("_departures"), l);
for (const auto &departure : res) {
qDebug() << departure.stopPoint().name() << departure.route().line().name() << departure.route().direction() << departure.scheduledTime();
qDebug() << departure.stopPoint().name() << departure.route().line().name() << departure.route().direction() << departure.scheduledDepartureTime();
}
} else {
m_errorMsg = reply->errorString();
......
......@@ -101,12 +101,20 @@ Kirigami.ApplicationWindow {
}
RowLayout {
QQC2.Label {
text: "Departure: " + modelData.scheduledTime.toTimeString()
text: "Arrival: " + modelData.scheduledArrivalTime.toTimeString()
}
QQC2.Label {
text: (modelData.delay >= 0 ? "+" : "") + modelData.delay
color: modelData.delay > 1 ? Kirigami.Theme.negativeTextColor : Kirigami.Theme.positiveTextColor
visible: modelData.hasExpectedTime
text: (modelData.arrivalDelay >= 0 ? "+" : "") + modelData.arrivalDelay
color: modelData.arrivalDelay > 1 ? Kirigami.Theme.negativeTextColor : Kirigami.Theme.positiveTextColor
visible: modelData.hasExpectedArrivalTime
}
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
}
}
RowLayout {
......
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