Skip to content

Commit

Permalink
Merge pull request #301 from HSLdevcom/DT-2950
Browse files Browse the repository at this point in the history
Dt 2950
  • Loading branch information
vesameskanen authored Apr 15, 2019
2 parents 6ec2963 + 10362af commit 0cee2bb
Show file tree
Hide file tree
Showing 5 changed files with 225 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,8 @@ protected void configurePolling (Graph graph, JsonNode config) throws Exception
source = new SmooveBikeRentalDataSource(networkName);
} else if (sourceType.equals("bicimad")) {
source = new BicimadBikeRentalDataSource();
} else if (sourceType.equals("samocat")) {
source = new SamocatScooterRentalDataSource(networkName);
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package org.opentripplanner.updater.bike_rental;

import org.opentripplanner.routing.bike_rental.BikeRentalStation;
import org.opentripplanner.util.NonLocalizedString;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashSet;

import com.fasterxml.jackson.databind.JsonNode;

/**
* Implementation of a BikeRentalDataSource for the Samocat scooter rental service used in Helsinki.
* Since scooters rental works similarly as bike rental, there is no point to create own data structures
* for them.
* @see BikeRentalDataSource
*/
public class SamocatScooterRentalDataSource extends GenericJsonBikeRentalDataSource {

private static final Logger log = LoggerFactory.getLogger(SamocatScooterRentalDataSource.class);

private String networkName;

public SamocatScooterRentalDataSource(String networkName) {
super("results");
this.networkName = defaultIfEmpty(networkName, "samocat");
}

private String defaultIfEmpty(String value, String defaultValue) {
if (value == null || value.isEmpty())
return defaultValue;

return value;
}

/**
* <pre>
* {
* "count": 10,
* "next": null,
* "previous": null,
* "results": [
* {
* "type": "Feature",
* "geometry": {
* "type": "Point",
* "coordinates": [
* 60.167913,
* 24.952269
* ]
* },
* "properties": {
* "station_id": "0309",
* "city": "Helsinki",
* "country": "Finland",
* "address": "some address",
* "rack_sum": 12,
* "free_racks": 2,
* "available_devices": 1
* }
* }
* ]
* }
* </pre>
*/
public BikeRentalStation makeStation(JsonNode node) {
BikeRentalStation station = new BikeRentalStation();
JsonNode properties = node.path("properties");
JsonNode coordinates = node.path("geometry").path("coordinates");
station.id = properties.path("station_id").asText();
station.name = new NonLocalizedString(properties.path("address").asText());
station.state = "Station on";
station.networks = new HashSet<String>();
station.networks.add(this.networkName);
try {
if (coordinates.get(0).isNull() || coordinates.isNull()) {
return null;
}
station.x = coordinates.get(0).asDouble();
station.y = coordinates.get(1).asDouble();
station.bikesAvailable = properties.path("available_devices").asInt();
station.spacesAvailable = properties.path("free_racks").asInt();
return station;
} catch (NumberFormatException e) {
// E.g. coordinates is empty
log.info("Error parsing bike rental station " + station.id, e);
return null;
}
}
}
1 change: 1 addition & 0 deletions src/main/resources/logback.xml
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
<logger name="com.conveyal" level="info"/>
<!-- for now disable realtime logging, leave only statistics -->
<logger name="org.opentripplanner.updater.bike_rental.SmooveBikeRentalDataSource" level="warn" />
<logger name="org.opentripplanner.updater.bike_rental.SamocatScooterRentalDataSource" level="warn" />
<logger name="org.opentripplanner.updater.bike_rental.BikeRentalUpdater" level="warn" />
<logger name="org.opentripplanner.updater.stoptime.TimetableSnapshotSource" level="error" />
<logger name="org.opentripplanner.updater.stoptime.TimetableSnapshotSource$GtfsRealtimeStatistics" level="info" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,4 +75,53 @@ public void testSmoove() {
BikeRentalStation hamnWithCustomNetwork = rentalStationsWithCustomNetwork.get(0);
assertEquals("[Helsinki]", hamnWithCustomNetwork.networks.toString());
}

public void testSamocat() {
SamocatScooterRentalDataSource source = new SamocatScooterRentalDataSource(null);
source.setUrl("file:src/test/resources/bike/samocat.json");
assertTrue(source.update());
List<BikeRentalStation> rentalStations = source.getStations();

// Invalid station without coordinates should be ignored, so only 3
assertEquals(3, rentalStations.size());
for (BikeRentalStation rentalStation : rentalStations) {
System.out.println(rentalStation);
}

BikeRentalStation testikuja = rentalStations.get(0);
assertEquals("Testikuja 3", testikuja.name.toString());
assertEquals("0451", testikuja.id);
// Ignore whitespace in coordinates string
assertEquals(24.9355143, testikuja.x);
assertEquals(60.1637284, testikuja.y);
assertEquals(0, testikuja.spacesAvailable);
assertEquals(0, testikuja.bikesAvailable);
assertEquals("Station on", testikuja.state);
assertEquals("[samocat]", testikuja.networks.toString());

BikeRentalStation footie = rentalStations.get(1);
assertEquals("Footie 3", footie.name.toString());
assertEquals("0450", footie.id);
assertEquals(3, footie.spacesAvailable);
assertEquals(4, footie.bikesAvailable);
assertEquals(24.958877, footie.x);
assertEquals(60.194449, footie.y);

BikeRentalStation bartie = rentalStations.get(2);
assertEquals("Bartie 10", bartie.name.toString());
assertEquals("3451", bartie.id);
assertEquals(24.9537278, bartie.x);
assertEquals(60.2177349, bartie.y);
assertEquals(5, bartie.spacesAvailable);
assertEquals(1, bartie.bikesAvailable);
// Ignores mismatch with total_slots

// Test giving network name to data source
SamocatScooterRentalDataSource sourceWithCustomNetwork = new SamocatScooterRentalDataSource("vuosaari");
sourceWithCustomNetwork.setUrl("file:src/test/resources/bike/samocat.json");
assertTrue(sourceWithCustomNetwork.update());
List<BikeRentalStation> rentalStationsWithCustomNetwork = sourceWithCustomNetwork.getStations();
BikeRentalStation testitieWithCustomNetwork = rentalStationsWithCustomNetwork.get(0);
assertEquals("[vuosaari]", testitieWithCustomNetwork.networks.toString());
}
}
83 changes: 83 additions & 0 deletions src/test/resources/bike/samocat.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
{
"count": 3,
"next": null,
"previous": null,
"results": [
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [
24.9355143,
60.1637284
]
},
"properties": {
"station_id": "0451",
"city": "Helsinki",
"country": "FI",
"address": "Testikuja 3",
"rack_sum": 12,
"free_racks": 0,
"available_devices": 0
}
},
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [
24.958877,
60.194449
]
},
"properties": {
"station_id": "0450",
"city": "Helsinki",
"country": "FI",
"address": "Footie 3",
"rack_sum": 12,
"free_racks": 3,
"available_devices": 4
}
},
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [
24.9537278,
60.2177349
]
},
"properties": {
"station_id": "3451",
"city": "Helsinki",
"country": "FI",
"address": "Bartie 10",
"rack_sum": 12,
"free_racks": 5,
"available_devices": 1
}
},
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [
null,
null
]
},
"properties": {
"station_id": "3451",
"city": "Helsinki",
"country": "FI",
"address": "Nulltie 1",
"rack_sum": 12,
"free_racks": 5,
"available_devices": 1
}
}
]
}

0 comments on commit 0cee2bb

Please sign in to comment.