From 69406da7c8abbb7207a1e083ffd5a71fd1dee747 Mon Sep 17 00:00:00 2001 From: Marcus Lundblad Date: Tue, 4 Feb 2020 22:48:46 +0100 Subject: [PATCH 1/4] openTripPlanner: Refactor-out methods to create plan URLs Create methods to provide the URL for creating the plan call to enable specialized plugins to override them if needed. --- src/transitplugins/openTripPlanner.js | 28 +++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/src/transitplugins/openTripPlanner.js b/src/transitplugins/openTripPlanner.js index 21954c24..62edd2ac 100644 --- a/src/transitplugins/openTripPlanner.js +++ b/src/transitplugins/openTripPlanner.js @@ -489,10 +489,8 @@ var OpenTripPlanner = class OpenTripPlanner { return params; } - _fetchPlan(params, callback) { - let query = new HTTP.Query(params); - let uri = new Soup.URI(this._getRouterUrl() + '/plan?' + - query.toString()); + _fetchPlan(url, callback) { + let uri = new Soup.URI(url); let request = new Soup.Message({ method: 'GET', uri: uri }); request.request_headers.append('Accept', 'application/json'); @@ -514,6 +512,20 @@ var OpenTripPlanner = class OpenTripPlanner { }); } + _getPlanUrlFromParams(params) { + let query = new HTTP.Query(params); + + return this._getRouterUrl() + '/plan?' + query.toString(); + } + + _getPlanUrlWithStops(stops) { + return this._getPlanUrlFromParams(this._createParamsWithStops(stops)); + } + + _getPlanUrlWithLocations() { + return this._getPlanUrlFromParams(this._createParamsWithLocations()); + } + _fetchRoutes(callback) { if (this._onlyTransitData) { this._fetchTransitStops((stops) => { @@ -535,14 +547,10 @@ var OpenTripPlanner = class OpenTripPlanner { return; } - let params = this._createParamsWithStops(stops); - - this._fetchPlan(params, callback); + this._fetchPlan(this._getPlanUrlWithStops(stops), callback); }); } else { - let params = this._createParamsWithLocations(); - - this._fetchPlan(params, callback); + this._fetchPlan(this._getPlanUrlWithLocations(), callback); } } -- GitLab From a9fa5a88175658d2f54945bf146238ad8efa67f4 Mon Sep 17 00:00:00 2001 From: Marcus Lundblad Date: Wed, 5 Feb 2020 22:57:09 +0100 Subject: [PATCH 2/4] openTripPlanner: Add tweaks for the GoMetro API The "itineraries" element appears directly in the root rather than in a "plan" element. Transit legs lack intermediate stops. --- src/transitplugins/openTripPlanner.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/transitplugins/openTripPlanner.js b/src/transitplugins/openTripPlanner.js index 62edd2ac..eeb5aa56 100644 --- a/src/transitplugins/openTripPlanner.js +++ b/src/transitplugins/openTripPlanner.js @@ -591,6 +591,10 @@ var OpenTripPlanner = class OpenTripPlanner { itineraries = itineraries.concat( this._createItineraries(plan.itineraries)); + } else if (route.itineraries) { + itineraries = + itineraries.concat( + this._createItineraries(route.itineraries)); } if (itineraries.length === 0) { @@ -1062,7 +1066,7 @@ var OpenTripPlanner = class OpenTripPlanner { textColor: textColor, tripShortName: leg.tripShortName }); - if (leg.transitLeg) + if (leg.transitLeg && leg.intermediateStops) result.intermediateStops = this._createIntermediateStops(leg); else if (!this._onlyTransitData) result.walkingInstructions = this._createTurnpoints(leg, polyline); -- GitLab From f6d247622e4c9af172642936626928fd42365642 Mon Sep 17 00:00:00 2001 From: Marcus Lundblad Date: Wed, 5 Feb 2020 22:59:18 +0100 Subject: [PATCH 3/4] transitLegRow: Handle legs with no intermediate stops Handle the case where the list of intermediate stops for a leg is not set, for plugins that do not support showing them. --- src/transitLegRow.js | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/transitLegRow.js b/src/transitLegRow.js index 1d7444e3..142cf7c9 100644 --- a/src/transitLegRow.js +++ b/src/transitLegRow.js @@ -178,14 +178,16 @@ var TransitLegRow = GObject.registerClass({ _populateInstructions() { if (this._leg.transit) { - let stops = this._leg.intermediateStops; - for (let index = 0; index < stops.length; index++) { - let stop = stops[index]; - let row = - new TransitStopRow.TransitStopRow({ visible: true, - stop: stop, - final: index === stops.length - 1 }); - this._instructionList.add(row); + if (this._leg.intermediateStops) { + let stops = this._leg.intermediateStops; + for (let index = 0; index < stops.length; index++) { + let stop = stops[index]; + let row = + new TransitStopRow.TransitStopRow({ visible: true, + stop: stop, + final: index === stops.length - 1 }); + this._instructionList.add(row); + } } } else { /* don't output the starting and ending instructions from the walk -- GitLab From a75c6cba856834888cfe6363cb131279273a5dd1 Mon Sep 17 00:00:00 2001 From: Marcus Lundblad Date: Wed, 5 Feb 2020 23:00:05 +0100 Subject: [PATCH 4/4] Add transit plugin for the GoMetro API Adds a plugin for the South African GoMetro transit journey planning API. --- src/org.gnome.Maps.src.gresource.xml | 1 + src/transitplugins/goMetro.js | 131 +++++++++++++++++++++++++++ 2 files changed, 132 insertions(+) create mode 100644 src/transitplugins/goMetro.js diff --git a/src/org.gnome.Maps.src.gresource.xml b/src/org.gnome.Maps.src.gresource.xml index 8ecc6e9c..ab2e12f0 100644 --- a/src/org.gnome.Maps.src.gresource.xml +++ b/src/org.gnome.Maps.src.gresource.xml @@ -114,6 +114,7 @@ tile.js transform.js wrap.js + transitplugins/goMetro.js transitplugins/opendataCH.js transitplugins/openTripPlanner.js transitplugins/resrobot.js diff --git a/src/transitplugins/goMetro.js b/src/transitplugins/goMetro.js new file mode 100644 index 00000000..e68cd1c2 --- /dev/null +++ b/src/transitplugins/goMetro.js @@ -0,0 +1,131 @@ +/* -*- Mode: JS2; indent-tabs-mode: nil; js2-basic-offset: 4 -*- */ +/* vim: set et ts=4 sw=4: */ +/* + * Copyright (c) 2020 Marcus Lundblad + * + * GNOME Maps is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * GNOME Maps 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 General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with GNOME Maps; if not, see . + * + * Author: Marcus Lundblad + */ + +/** + * This module implements a transit routing plugin for the South African + * GoMetro API. + * https://proserver.gometro.co.za/api/v1/docs/#multimodal-routing + */ + +const BASE_URL = 'https://proserver.gometro.co.za/api'; +const API_VERSION = 'v1'; + +const NATIVE_TIMEZONE = 'Africa/Cape_Town'; + +const _ = imports.gettext.gettext; + +const GLib = imports.gi.GLib; + +const Application = imports.application; +const HVT = imports.hvt; +const TransitPlan = imports.transitPlan; +const Utils = imports.utils; + +const OpenTripPlanner = imports.transitplugins.openTripPlanner; + +var GoMetro = class GoMetro extends OpenTripPlanner.OpenTripPlanner { + constructor() { + super({ baseUrl: BASE_URL }); + + this._tz = GLib.TimeZone.new(NATIVE_TIMEZONE); + } + + // the GoMetro API only supports start and destination points + fetchFirstResults() { + if (this._query.filledPoints.length > 2) { + Utils.debug('This plugin does not support via locations'); + this._plan.reset(); + this._plan.requestFailed(); + this._query.reset(); + } else if (this._query.arriveBy) { + this._reset(); + this._plan.error(_("This plugin doesn't support latest arrival")); + } else { + super.fetchFirstResults(); + } + } + + _getPlanUrlWithLocations() { + let fromLocation = this._query.filledPoints[0].place.location; + let toLocation = this._query.filledPoints.last().place.location; + + return '%s/%s/trips/%s,%s/%s,%s/%s/%s'.format(BASE_URL, + API_VERSION, + fromLocation.latitude, + fromLocation.longitude, + toLocation.latitude, + toLocation.longitude, + this._getDateAndTimeParams(), + this._getModesParam()); + } + + _getDateAndTimeParams() { + if (this._query.time || this._extendPrevious) { + let params = {}; + + this._addCommonParams(params); + let time = params.time; + let date = params.date; + + return '%s/%s%s'.format(date, this._query.arriveBy ? '-' : '', time); + } else { + let dateTime = GLib.DateTime.new_now(this._tz); + + return '%04d-%02d-%02d/%02d:%02d'.format(dateTime.get_year(), + dateTime.get_month(), + dateTime.get_day_of_month(), + dateTime.get_hour(), + dateTime.get_minute()); + } + } + + // GoMetro seems to (ab)use routeType ferry for communal taxi + _createLeg(leg, index, legs) { + let result = super._createLeg(leg, index, legs); + + if (result.routeType === TransitPlan.RouteType.FERRY) + result.routeType = HVT.TAXI_SERVICE; + + return result; + } + + _getModesParam() { + let params = ''; + let transitOptions = this._query.transitOptions; + + if (transitOptions.showAllTransitTypes || + transitOptions.transitTypes.includes(TransitPlan.RouteType.TRAIN)) + params += 'RAIL,'; + if (transitOptions.showAllTransitTypes || + transitOptions.transitTypes.includes(TransitPlan.RouteType.BUS)) + params += 'BUS,'; + if (transitOptions.showAllTransitTypes || + transitOptions.transitTypes.includes(TransitPlan.RouteType.FERRY)) + params += 'FERRY,'; + if (transitOptions.showAllTransitTypes || + transitOptions.transitTypes.includes(TransitPlan.RouteType.TRAM)) + params += 'TRAM,'; + if (transitOptions.showAllTransitTypes) + params += 'GONDOLA,'; + + return params + 'WALK'; + } +} -- GitLab