Skip to content

Commit

Permalink
Merge pull request #5425 from cedarbaum/vehicle_rental_station_vehicl…
Browse files Browse the repository at this point in the history
…e_types

Add available types and spaces to `VehicleRentalStation`
  • Loading branch information
optionsome authored Oct 26, 2023
2 parents f55d693 + 8575360 commit eaf1ea2
Show file tree
Hide file tree
Showing 13 changed files with 264 additions and 30 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
import graphql.schema.DataFetcher;
import graphql.schema.DataFetchingEnvironment;
import org.opentripplanner.apis.gtfs.generated.GraphQLDataFetchers;
import org.opentripplanner.service.vehiclerental.model.VehicleRentalPlace;
import org.opentripplanner.service.vehiclerental.model.RentalVehicleEntityCounts;
import org.opentripplanner.service.vehiclerental.model.VehicleRentalStation;
import org.opentripplanner.service.vehiclerental.model.VehicleRentalStationUris;

public class VehicleRentalStationImpl implements GraphQLDataFetchers.GraphQLVehicleRentalStation {
Expand Down Expand Up @@ -96,7 +97,17 @@ public DataFetcher<Integer> vehiclesAvailable() {
return environment -> getSource(environment).getVehiclesAvailable();
}

private VehicleRentalPlace getSource(DataFetchingEnvironment environment) {
@Override
public DataFetcher<RentalVehicleEntityCounts> availableVehicles() {
return environment -> getSource(environment).getVehicleTypeCounts();
}

@Override
public DataFetcher<RentalVehicleEntityCounts> availableSpaces() {
return environment -> getSource(environment).getVehicleSpaceCounts();
}

private VehicleRentalStation getSource(DataFetchingEnvironment environment) {
return environment.getSource();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,9 @@
import org.opentripplanner.routing.vehicle_parking.VehicleParkingState;
import org.opentripplanner.service.realtimevehicles.model.RealtimeVehicle;
import org.opentripplanner.service.realtimevehicles.model.RealtimeVehicle.StopRelationship;
import org.opentripplanner.service.vehiclerental.model.RentalVehicleEntityCounts;
import org.opentripplanner.service.vehiclerental.model.RentalVehicleType;
import org.opentripplanner.service.vehiclerental.model.RentalVehicleTypeCount;
import org.opentripplanner.service.vehiclerental.model.VehicleRentalPlace;
import org.opentripplanner.service.vehiclerental.model.VehicleRentalStation;
import org.opentripplanner.service.vehiclerental.model.VehicleRentalStationUris;
Expand Down Expand Up @@ -1181,6 +1183,10 @@ public interface GraphQLVehicleRentalStation {
public DataFetcher<String> stationId();

public DataFetcher<Integer> vehiclesAvailable();

public DataFetcher<RentalVehicleEntityCounts> availableVehicles();

public DataFetcher<RentalVehicleEntityCounts> availableSpaces();
}

public interface GraphQLVehicleRentalUris {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ config:
BikeRentalStation: org.opentripplanner.service.vehiclerental.model.VehicleRentalPlace#VehicleRentalPlace
BikeRentalStationUris: org.opentripplanner.service.vehiclerental.model.VehicleRentalStationUris#VehicleRentalStationUris
VehicleRentalStation: org.opentripplanner.service.vehiclerental.model.VehicleRentalStation#VehicleRentalStation
RentalVehicleEntityCounts: org.opentripplanner.service.vehiclerental.model.RentalVehicleEntityCounts#RentalVehicleEntityCounts
RentalVehicleTypeCount: org.opentripplanner.service.vehiclerental.model.RentalVehicleTypeCount#RentalVehicleTypeCount
RentalVehicle: org.opentripplanner.service.vehiclerental.model.VehicleRentalVehicle#VehicleRentalVehicle
VehicleRentalUris: org.opentripplanner.service.vehiclerental.model.VehicleRentalStationUris#VehicleRentalStationUris
BikesAllowed: org.opentripplanner.apis.gtfs.generated.GraphQLTypes.GraphQLBikesAllowed#GraphQLBikesAllowed
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package org.opentripplanner.service.vehiclerental.model;

import java.util.List;

public record RentalVehicleEntityCounts(int total, List<RentalVehicleTypeCount> byType) {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package org.opentripplanner.service.vehiclerental.model;

public record RentalVehicleTypeCount(RentalVehicleType vehicleType, int count) {}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import static java.util.Locale.ROOT;

import java.time.Instant;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
Expand Down Expand Up @@ -188,4 +189,35 @@ public Set<RentalFormFactor> formFactors() {
getAvailablePickupFormFactors(false)
);
}

/**
* @return Counts of available vehicles by type as well as the total number of available vehicles.
*/
public RentalVehicleEntityCounts getVehicleTypeCounts() {
return new RentalVehicleEntityCounts(
vehiclesAvailable,
vehicleRentalTypeMapToList(vehicleTypesAvailable)
);
}

/**
* @return Counts of available vehicle spaces by type as well as the total number of available
* vehicle spaces.
*/
public RentalVehicleEntityCounts getVehicleSpaceCounts() {
return new RentalVehicleEntityCounts(
spacesAvailable,
vehicleRentalTypeMapToList(vehicleSpacesAvailable)
);
}

private List<RentalVehicleTypeCount> vehicleRentalTypeMapToList(
Map<RentalVehicleType, Integer> vehicleTypeMap
) {
return vehicleTypeMap
.entrySet()
.stream()
.map(vtc -> new RentalVehicleTypeCount(vtc.getKey(), vtc.getValue()))
.toList();
}
}
30 changes: 28 additions & 2 deletions src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls
Original file line number Diff line number Diff line change
Expand Up @@ -558,7 +558,7 @@ type VehicleRentalStation implements Node & PlaceInterface {
Number of vehicles currently available on the rental station.
See field `allowPickupNow` to know if is currently possible to pick up a vehicle.
"""
vehiclesAvailable: Int
vehiclesAvailable: Int @deprecated(reason: "Use `availableVehicles` instead, which also contains vehicle types")

"""
Number of free spaces currently available on the rental station.
Expand All @@ -567,7 +567,17 @@ type VehicleRentalStation implements Node & PlaceInterface {
the rental station, even if the vehicle racks don't have any spaces available.
See field `allowDropoffNow` to know if is currently possible to return a vehicle.
"""
spacesAvailable: Int
spacesAvailable: Int @deprecated(reason: "Use `availableSpaces` instead, which also contains the space vehicle types")

"""
Number of vehicles currently available on the rental station, grouped by vehicle type.
"""
availableVehicles: RentalVehicleEntityCounts

"""
Number of free spaces currently available on the rental station, grouped by vehicle type.
"""
availableSpaces: RentalVehicleEntityCounts

"""
If true, values of `vehiclesAvailable` and `spacesAvailable` are updated from a
Expand Down Expand Up @@ -617,6 +627,22 @@ type VehicleRentalStation implements Node & PlaceInterface {
operative: Boolean
}

type RentalVehicleEntityCounts {
"""The total number of entities (e.g. vehicles, spaces)."""
total: Int!

"""The number of entities by type"""
byType: [RentalVehicleTypeCount!]!
}

type RentalVehicleTypeCount {
"""The type of the rental vehicle (scooter, bicycle, car...)"""
vehicleType: RentalVehicleType!

"""The number of vehicles of this type"""
count: Int!
}

"""
Rental vehicle represents a vehicle that belongs to a rental network.
"""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@
import org.opentripplanner.service.realtimevehicles.internal.DefaultRealtimeVehicleService;
import org.opentripplanner.service.realtimevehicles.model.RealtimeVehicle;
import org.opentripplanner.service.vehiclerental.internal.DefaultVehicleRentalService;
import org.opentripplanner.service.vehiclerental.model.TestVehicleRentalStationBuilder;
import org.opentripplanner.service.vehiclerental.model.VehicleRentalStation;
import org.opentripplanner.standalone.config.framework.json.JsonSupport;
import org.opentripplanner.test.support.FilePatternSource;
import org.opentripplanner.transit.model._data.TransitModelForTest;
Expand Down Expand Up @@ -241,13 +243,22 @@ public TransitAlertService getTransitAlertService() {
.build();
realtimeVehicleService.setRealtimeVehicles(pattern, List.of(occypancyVehicle, positionVehicle));

DefaultVehicleRentalService defaultVehicleRentalService = new DefaultVehicleRentalService();
VehicleRentalStation vehicleRentalStation = new TestVehicleRentalStationBuilder()
.withVehicles(10)
.withSpaces(10)
.withVehicleTypeBicycle(5, 7)
.withVehicleTypeElectricBicycle(5, 3)
.build();
defaultVehicleRentalService.addVehicleRentalStation(vehicleRentalStation);

context =
new GraphQLRequestContext(
new TestRoutingService(List.of(i1)),
transitService,
new DefaultFareService(),
graph.getVehicleParkingService(),
new DefaultVehicleRentalService(),
defaultVehicleRentalService,
realtimeVehicleService,
GraphFinder.getInstance(graph, transitService::findRegularStop),
new RouteRequest()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,7 @@ void getVehicleRentalStationForEnvelopeShouldExcludeVehicleRentalVehicle() {
DefaultVehicleRentalService defaultVehicleRentalService = new DefaultVehicleRentalService();

VehicleRentalStation vehicleRentalStation = new TestVehicleRentalStationBuilder()
.withLatitude(1)
.withLongitude(1)
.withCoordinates(1, 1)
.build();
defaultVehicleRentalService.addVehicleRentalStation(vehicleRentalStation);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.opentripplanner.service.vehiclerental.model;

import java.util.HashMap;
import java.util.Map;
import javax.annotation.Nonnull;
import org.opentripplanner.framework.i18n.NonLocalizedString;
Expand All @@ -18,18 +19,15 @@ public class TestVehicleRentalStationBuilder {
private int spaces = 10;
private boolean overloadingAllowed = false;
private boolean stationOn = false;
private RentalVehicleType vehicleType = RentalVehicleType.getDefaultType(NETWORK_1);
private final Map<RentalVehicleType, Integer> vehicleTypesAvailable = new HashMap<>();
private final Map<RentalVehicleType, Integer> vehicleSpacesAvailable = new HashMap<>();

public static TestVehicleRentalStationBuilder of() {
return new TestVehicleRentalStationBuilder();
}

public TestVehicleRentalStationBuilder withLatitude(double latitude) {
public TestVehicleRentalStationBuilder withCoordinates(double latitude, double longitude) {
this.latitude = latitude;
return this;
}

public TestVehicleRentalStationBuilder withLongitude(double longitude) {
this.longitude = longitude;
return this;
}
Expand All @@ -54,24 +52,55 @@ public TestVehicleRentalStationBuilder withStationOn(boolean stationOn) {
return this;
}

public TestVehicleRentalStationBuilder withVehicleTypeBicycle() {
return buildVehicleType(RentalFormFactor.BICYCLE);
public TestVehicleRentalStationBuilder withVehicleTypeBicycle(int numAvailable, int numSpaces) {
return buildVehicleType(
RentalFormFactor.BICYCLE,
RentalVehicleType.PropulsionType.HUMAN,
numAvailable,
numSpaces
);
}

public TestVehicleRentalStationBuilder withVehicleTypeCar() {
return buildVehicleType(RentalFormFactor.CAR);
public TestVehicleRentalStationBuilder withVehicleTypeElectricBicycle(
int numAvailable,
int numSpaces
) {
return buildVehicleType(
RentalFormFactor.BICYCLE,
RentalVehicleType.PropulsionType.ELECTRIC,
numAvailable,
numSpaces
);
}

public TestVehicleRentalStationBuilder withVehicleTypeCar(int numAvailable, int numSpaces) {
return buildVehicleType(
RentalFormFactor.CAR,
RentalVehicleType.PropulsionType.ELECTRIC,
numAvailable,
numSpaces
);
}

@Nonnull
private TestVehicleRentalStationBuilder buildVehicleType(RentalFormFactor rentalFormFactor) {
this.vehicleType =
new RentalVehicleType(
new FeedScopedId(TestVehicleRentalStationBuilder.NETWORK_1, rentalFormFactor.name()),
rentalFormFactor.name(),
rentalFormFactor,
RentalVehicleType.PropulsionType.ELECTRIC,
100000d
);
private TestVehicleRentalStationBuilder buildVehicleType(
RentalFormFactor rentalFormFactor,
RentalVehicleType.PropulsionType propulsionType,
int numAvailable,
int numSpaces
) {
RentalVehicleType vehicleType = new RentalVehicleType(
new FeedScopedId(
TestVehicleRentalStationBuilder.NETWORK_1,
String.format("%s-%s", rentalFormFactor.name(), propulsionType.name())
),
rentalFormFactor.name(),
rentalFormFactor,
propulsionType,
100000d
);
this.vehicleTypesAvailable.put(vehicleType, numAvailable);
this.vehicleSpacesAvailable.put(vehicleType, numSpaces);
return this;
}

Expand All @@ -84,8 +113,16 @@ public VehicleRentalStation build() {
station.longitude = longitude;
station.vehiclesAvailable = vehicles;
station.spacesAvailable = spaces;
station.vehicleTypesAvailable = Map.of(vehicleType, vehicles);
station.vehicleSpacesAvailable = Map.of(vehicleType, spaces);

// If no vehicle types are specified, use the default type
if (vehicleTypesAvailable.isEmpty() || vehicleSpacesAvailable.isEmpty()) {
station.vehicleTypesAvailable = Map.of(RentalVehicleType.getDefaultType(NETWORK_1), vehicles);
station.vehicleSpacesAvailable = Map.of(RentalVehicleType.getDefaultType(NETWORK_1), spaces);
} else {
station.vehicleTypesAvailable = vehicleTypesAvailable;
station.vehicleSpacesAvailable = vehicleSpacesAvailable;
}

station.overloadingAllowed = overloadingAllowed;
station.isRenting = stationOn;
station.isReturning = stationOn;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ public TestStateBuilder streetEdge() {
public TestStateBuilder pickUpCarFromStation() {
return pickUpRentalVehicle(
RentalFormFactor.CAR,
TestVehicleRentalStationBuilder.of().withVehicleTypeCar().build()
TestVehicleRentalStationBuilder.of().withVehicleTypeCar(10, 10).build()
);
}

Expand All @@ -138,7 +138,7 @@ public TestStateBuilder pickUpFreeFloatingScooter() {
public TestStateBuilder pickUpBikeFromStation() {
return pickUpRentalVehicle(
RentalFormFactor.BICYCLE,
TestVehicleRentalStationBuilder.of().withVehicleTypeBicycle().build()
TestVehicleRentalStationBuilder.of().withVehicleTypeElectricBicycle(10, 10).build()
);
}

Expand Down
Loading

0 comments on commit eaf1ea2

Please sign in to comment.