diff --git a/src/main/java/org/opentripplanner/updater/bike_rental/BikeRentalUpdater.java b/src/main/java/org/opentripplanner/updater/bike_rental/BikeRentalUpdater.java index 46cc4b2afd4..0f643fd6f1c 100644 --- a/src/main/java/org/opentripplanner/updater/bike_rental/BikeRentalUpdater.java +++ b/src/main/java/org/opentripplanner/updater/bike_rental/BikeRentalUpdater.java @@ -101,6 +101,8 @@ protected void configurePolling (Graph graph, JsonNode config) throws Exception source = new SamocatScooterRentalDataSource(networkName); } else if (sourceType.equals("sharingos")) { source = new SharingOSBikeRentalDataSource(networkName); + } else if (sourceType.equals("vilkku")) { + source = new VilkkuBikeRentalDataSource(networkName); } } diff --git a/src/main/java/org/opentripplanner/updater/bike_rental/VilkkuBikeRentalDataSource.java b/src/main/java/org/opentripplanner/updater/bike_rental/VilkkuBikeRentalDataSource.java new file mode 100644 index 00000000000..5916927016f --- /dev/null +++ b/src/main/java/org/opentripplanner/updater/bike_rental/VilkkuBikeRentalDataSource.java @@ -0,0 +1,64 @@ +package org.opentripplanner.updater.bike_rental; + +import java.util.Collections; +import java.util.HashSet; +import java.util.Map; + +import com.google.common.base.Strings; +import org.opentripplanner.routing.bike_rental.BikeRentalStation; +import org.opentripplanner.util.NonLocalizedString; + +/** + * Vilkku (Kuopio, Finland) bike rental data source. + * url: https://kaupunkipyorat.kuopio.fi/tkhs-export-map.html?format=xml + */ +public class VilkkuBikeRentalDataSource extends GenericXmlBikeRentalDataSource { + + private String networkName; + + public VilkkuBikeRentalDataSource(String networkName) { + super("//station"); + this.networkName = Strings.isNullOrEmpty(networkName) ? "vilkku" : networkName; + } + + public BikeRentalStation makeStation(Map attributes) { + + // some place entries appear to actually be checked-out bikes, not stations + if (attributes.get("bike") != null) { + return null; + } + + BikeRentalStation station = new BikeRentalStation(); + station.networks = new HashSet<>(Collections.singleton(this.networkName)); + station.id = attributes.get("name"); + station.x = getCoordinate(attributes.get("longitude")); + station.y = getCoordinate(attributes.get("latitude")); + station.name = new NonLocalizedString(attributes.get("name")); + station.bikesAvailable = getAvailableBikes(attributes); + station.spacesAvailable = getAvailableSpaces(attributes); + station.state = "Station on"; + return station; + } + + private double getCoordinate(String coordinate) { + // for some reason the API returns coordinates with ',' as decimal separator + if (coordinate.contains(",")) { + return Double.parseDouble(coordinate.replace(",", ".")); + } + return Double.parseDouble(coordinate); + } + + private int getAvailableBikes(Map attributes) { + int bikes = Integer.parseInt(attributes.get("freeBikes")); + int eBikes = Integer.parseInt(attributes.get("freeEBikes")); + + return bikes + eBikes; + } + + private int getAvailableSpaces(Map attributes) { + int locks = Integer.parseInt(attributes.get("freeLocks")); + int eLocks = Integer.parseInt(attributes.get("freeELocks")); + + return locks + eLocks; + } +} diff --git a/src/main/resources/logback.xml b/src/main/resources/logback.xml index 977369d3580..e4aacb9ede3 100644 --- a/src/main/resources/logback.xml +++ b/src/main/resources/logback.xml @@ -56,6 +56,7 @@ + diff --git a/src/test/java/org/opentripplanner/updater/bike_rental/TestBikeRentalStationSource.java b/src/test/java/org/opentripplanner/updater/bike_rental/TestBikeRentalStationSource.java index 9c463bea5ec..6d11d84f385 100644 --- a/src/test/java/org/opentripplanner/updater/bike_rental/TestBikeRentalStationSource.java +++ b/src/test/java/org/opentripplanner/updater/bike_rental/TestBikeRentalStationSource.java @@ -11,6 +11,7 @@ public class TestBikeRentalStationSource extends TestCase { private static final String NEXT_BIKE_TEST_DATA_URL = "file:src/test/resources/bike/next.xml"; + private static final String VILKKU_BIKE_TEST_DATA_URL = "file:src/test/resources/bike/vilkku.xml"; public void testKeolisRennes() { @@ -231,5 +232,36 @@ private NextBikeRentalDataSource createAndUpdateNextBikeRentalDataSource(String assertTrue(source.update()); return source; } - + + public void testVilkku() { + VilkkuBikeRentalDataSource source = createAndUpdateVilkkuBikeRentalDataSource(VILKKU_BIKE_TEST_DATA_URL, null); + List rentalStations = source.getStations(); + assertEquals(1, rentalStations.size()); + + Map stationByName = rentalStations.stream() + .peek(System.out::println) + .collect(Collectors.toMap(BikeRentalStation::getName, station -> station)); + + BikeRentalStation testStation = stationByName.get("test station"); + assertEquals("test station", testStation.id); + assertEquals(27.687, testStation.x); + assertEquals(62.887, testStation.y); + assertEquals(2, testStation.bikesAvailable); + assertEquals(3, testStation.spacesAvailable); + assertEquals("Station on", testStation.state); + assertEquals("[vilkku]", testStation.networks.toString()); + + // Test giving network name to data source + VilkkuBikeRentalDataSource sourceWithCustomNetwork = createAndUpdateVilkkuBikeRentalDataSource(VILKKU_BIKE_TEST_DATA_URL, "kuopio"); + List rentalStationsWithCustomNetwork = sourceWithCustomNetwork.getStations(); + BikeRentalStation tempClosedStationWithCustomNetwork = rentalStationsWithCustomNetwork.get(0); + assertEquals("[kuopio]", tempClosedStationWithCustomNetwork.networks.toString()); + } + + private VilkkuBikeRentalDataSource createAndUpdateVilkkuBikeRentalDataSource(String url, String networkName) { + VilkkuBikeRentalDataSource source = new VilkkuBikeRentalDataSource(networkName); + source.setUrl(url); + assertTrue(source.update()); + return source; + } } diff --git a/src/test/resources/bike/vilkku.xml b/src/test/resources/bike/vilkku.xml new file mode 100644 index 00000000000..4e222b971c1 --- /dev/null +++ b/src/test/resources/bike/vilkku.xml @@ -0,0 +1,11 @@ + + + test station + 1 + 1 + 1 + 2 + 62,887 + 27,687 + + \ No newline at end of file