diff --git a/autotests/data/otp/fi-digitransit-journey.out.json b/autotests/data/otp/fi-digitransit-journey.out.json index 5d758cb..03e625f 100644 --- a/autotests/data/otp/fi-digitransit-journey.out.json +++ b/autotests/data/otp/fi-digitransit-journey.out.json @@ -1,215 +1,223 @@ [ { "sections": [ { "disruptionEffect": "NormalService", "distance": 70, "from": { "latitude": 60.219459533691406, "longitude": 24.81308937072754, "name": "Origin" }, "mode": "Walking", "scheduledArrivalTime": "2020-01-09T17:14:14", "scheduledDepartureTime": "2020-01-09T17:13:19", "to": { "latitude": 60.21926498413086, "longitude": 24.814298629760742, "name": "LEPPÄVAARA" } }, { "disruptionEffect": "NormalService", "distance": 6973, + "expectedArrivalTime": "2020-01-09T17:18:46", + "expectedDepartureTime": "2020-01-09T17:14:28", "from": { "latitude": 60.21926498413086, "longitude": 24.814298629760742, "name": "LEPPÄVAARA" }, "mode": "PublicTransport", "route": { "direction": "HELSINKI", "line": { "mode": "LongDistanceTrain", "name": "986" } }, "scheduledArrivalTime": "2020-01-09T17:19:23", "scheduledDepartureTime": "2020-01-09T17:14:14", "to": { "latitude": 60.198551177978516, "longitude": 24.93345069885254, "name": "PASILA" } }, { "disruptionEffect": "NormalService", "distance": 12058, + "expectedArrivalTime": "2020-01-09T17:46:02", + "expectedDepartureTime": "2020-01-09T17:36:58", "from": { "latitude": 60.198551177978516, "longitude": 24.93345069885254, "name": "PASILA" }, "mode": "PublicTransport", "route": { "direction": "KAJAANI", "line": { "mode": "LongDistanceTrain", "name": "73" } }, "scheduledArrivalTime": "2020-01-09T17:40:01", "scheduledDepartureTime": "2020-01-09T17:30:59", "to": { "latitude": 60.29220199584961, "longitude": 25.043617248535156, "name": "TIKKURILA" } }, { "disruptionEffect": "NormalService", "distance": 152092, + "expectedArrivalTime": "2020-01-09T19:38:00", + "expectedDepartureTime": "2020-01-09T17:46:22", "from": { "latitude": 60.29220199584961, "longitude": 25.043617248535156, "name": "TIKKURILA" }, "mode": "PublicTransport", "route": { "direction": "KEMIJÄRVI", "line": { "mode": "LongDistanceTrain", "name": "265" } }, "scheduledArrivalTime": "2020-01-09T19:38:00", "scheduledDepartureTime": "2020-01-09T17:44:41", "to": { "latitude": 61.498775482177734, "longitude": 23.773019790649414, "name": "TAMPERE" } }, { "disruptionEffect": "NormalService", "distance": 570, "from": { "latitude": 61.498775482177734, "longitude": 23.773019790649414, "name": "TAMPERE" }, "mode": "Walking", "scheduledArrivalTime": "2020-01-09T19:45:56", "scheduledDepartureTime": "2020-01-09T19:38:00", "to": { "latitude": 61.49858856201172, "longitude": 23.7739200592041, "name": "Destination" } } ] }, { "sections": [ { "disruptionEffect": "NormalService", "distance": 127, "from": { "latitude": 60.219459533691406, "longitude": 24.81308937072754, "name": "Origin" }, "mode": "Walking", "scheduledArrivalTime": "2020-01-09T18:06:00", "scheduledDepartureTime": "2020-01-09T18:03:55", "to": { "latitude": 60.219478607177734, "longitude": 24.81322479248047, "name": "Leppävaara" } }, { "disruptionEffect": "NormalService", "distance": 7839, + "expectedArrivalTime": "2020-01-09T18:14:08", + "expectedDepartureTime": "2020-01-09T18:06:00", "from": { "latitude": 60.219478607177734, "longitude": 24.81322479248047, "name": "Leppävaara" }, "mode": "PublicTransport", "route": { "direction": "Helsinki", "line": { "mode": "RapidTransit", "name": "U" } }, "scheduledArrivalTime": "2020-01-09T18:13:34", "scheduledDepartureTime": "2020-01-09T18:06:00", "to": { "latitude": 60.1994743347168, "longitude": 24.93265151977539, "name": "Pasila" } }, { "disruptionEffect": "NormalService", "distance": 201, "from": { "latitude": 60.1994743347168, "longitude": 24.93265151977539, "name": "Pasila" }, "mode": "Walking", "scheduledArrivalTime": "2020-01-09T18:16:10", "scheduledDepartureTime": "2020-01-09T18:13:34", "to": { "latitude": 60.198551177978516, "longitude": 24.93345069885254, "name": "PASILA" } }, { "disruptionEffect": "NormalService", "distance": 162792, "from": { "latitude": 60.198551177978516, "longitude": 24.93345069885254, "name": "PASILA" }, "mode": "PublicTransport", "route": { "direction": "VAASA", "line": { "mode": "Train", "name": "53" } }, "scheduledArrivalTime": "2020-01-09T19:58:00", "scheduledDepartureTime": "2020-01-09T18:30:00", "to": { "latitude": 61.498775482177734, "longitude": 23.773019790649414, "name": "TAMPERE" } }, { "disruptionEffect": "NormalService", "distance": 570, "from": { "latitude": 61.498775482177734, "longitude": 23.773019790649414, "name": "TAMPERE" }, "mode": "Walking", "scheduledArrivalTime": "2020-01-09T20:05:56", "scheduledDepartureTime": "2020-01-09T19:58:00", "to": { "latitude": 61.49858856201172, "longitude": 23.7739200592041, "name": "Destination" } } ] } ] diff --git a/src/lib/backends/opentripplannerparser.cpp b/src/lib/backends/opentripplannerparser.cpp index 35b53b6..11f5727 100644 --- a/src/lib/backends/opentripplannerparser.cpp +++ b/src/lib/backends/opentripplannerparser.cpp @@ -1,141 +1,142 @@ /* Copyright (C) 2020 Volker Krause 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 . */ #include "opentripplannerparser.h" #include "gtfs/hvt.h" #include #include #include using namespace KPublicTransport; static Location parseLocation(const QJsonObject &obj) { Location loc; loc.setName(obj.value(QLatin1String("name")).toString()); loc.setLatitude(obj.value(QLatin1String("lat")).toDouble()); loc.setLongitude(obj.value(QLatin1String("lon")).toDouble()); // TODO time zone // TODO recursion into parent station // TODO gtfs id return loc; } static Line parseLine(const QJsonObject &obj) { Line line; // TODO alerts need to be propagated to journey section / departure line.setName(obj.value(QLatin1String("shortName")).toString()); line.setMode(Gtfs::Hvt::typeToMode(obj.value(QLatin1String("type")).toInt())); // TODO parse color return line; } static Route parseRoute(const QJsonObject &obj) { Route route; route.setLine(parseLine(obj.value(QLatin1String("route")).toObject())); route.setDirection(obj.value(QLatin1String("tripHeadsign")).toString()); return route; } static Departure parseDeparture(const QJsonObject &obj) { Departure dep; const auto baseTime = obj.value(QLatin1String("serviceDay")).toDouble(); // ### 64bit dep.setScheduledArrivalTime(QDateTime::fromSecsSinceEpoch(baseTime + obj.value(QLatin1String("scheduledArrival")).toDouble())); dep.setScheduledDepartureTime(QDateTime::fromSecsSinceEpoch(baseTime + obj.value(QLatin1String("scheduledDeparture")).toDouble())); if (obj.value(QLatin1String("realtime")).toBool()) { dep.setExpectedArrivalTime(QDateTime::fromSecsSinceEpoch(baseTime + obj.value(QLatin1String("realtimeArrival")).toDouble())); dep.setExpectedDepartureTime(QDateTime::fromSecsSinceEpoch(baseTime + obj.value(QLatin1String("realtimeDeparture")).toDouble())); } dep.setScheduledPlatform(obj.value(QLatin1String("stop")).toObject().value(QLatin1String("platformCode")).toString()); dep.setRoute(parseRoute(obj.value(QLatin1String("trip")).toObject())); return dep; } static void parseDeparturesForStop(const QJsonObject &obj, std::vector &deps) { const auto loc = parseLocation(obj.value(QLatin1String("stop")).toObject()); const auto stopTimes = obj.value(QLatin1String("stoptimes")).toArray(); for (const auto &stopTime : stopTimes) { auto dep = parseDeparture(stopTime.toObject()); dep.setStopPoint(loc); deps.push_back(dep); } } std::vector OpenTripPlannerParser::parseDepartures(const QJsonObject &obj) { std::vector deps; const auto depsArray = obj.value(QLatin1String("nearest")).toObject().value(QLatin1String("edges")).toArray(); for (const auto &depsV : depsArray) { parseDeparturesForStop(depsV.toObject().value(QLatin1String("node")).toObject().value(QLatin1String("place")).toObject(), deps); } return deps; } static JourneySection parseJourneySection(const QJsonObject &obj) { JourneySection section; section.setScheduledDepartureTime(QDateTime::fromMSecsSinceEpoch(obj.value(QLatin1String("startTime")).toDouble())); // ### sic! double to get 64 bit precision... section.setScheduledArrivalTime(QDateTime::fromMSecsSinceEpoch(obj.value(QLatin1String("endTime")).toDouble())); if (obj.value(QLatin1String("realTime")).toBool()) { - // TODO + section.setExpectedDepartureTime(section.scheduledDepartureTime().addSecs(obj.value(QLatin1String("departureDelay")).toInt())); + section.setExpectedArrivalTime(section.scheduledArrivalTime().addSecs(obj.value(QLatin1String("arrivalDelay")).toInt())); } section.setFrom(parseLocation(obj.value(QLatin1String("from")).toObject())); // TODO handle the nested structure correctly, TODO parse platforms section.setTo(parseLocation(obj.value(QLatin1String("to")).toObject())); section.setDistance(obj.value(QLatin1String("distance")).toDouble()); if (obj.value(QLatin1String("transitLeg")).toBool()) { section.setMode(JourneySection::PublicTransport); section.setRoute(parseRoute(obj.value(QLatin1String("trip")).toObject())); } else { section.setMode(JourneySection::Walking); } return section; } static Journey parseJourney(const QJsonObject &obj) { std::vector sections; const auto sectionsArray = obj.value(QLatin1String("legs")).toArray(); for (const auto §ionObj : sectionsArray) { sections.push_back(parseJourneySection(sectionObj.toObject())); } Journey journey; journey.setSections(std::move(sections)); return journey; } std::vector OpenTripPlannerParser::parseJourneys(const QJsonObject& obj) { std::vector journeys; const auto journeysArray = obj.value(QLatin1String("plan")).toObject().value(QLatin1String("itineraries")).toArray(); journeys.reserve(journeysArray.size()); for (const auto &journeyObj : journeysArray) { journeys.push_back(parseJourney(journeyObj.toObject())); } return journeys; }